summaryrefslogtreecommitdiff
path: root/target/linux/generic/patches-2.6.36/403-ledtrig-usbdev.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/patches-2.6.36/403-ledtrig-usbdev.patch')
0 files changed, 0 insertions, 0 deletions
lass='mode'>-rw-r--r--README24
-rw-r--r--docs/config.txt72
-rw-r--r--docs/network-scripts.txt52
-rw-r--r--docs/network.txt79
-rw-r--r--include/host-build.mk123
-rw-r--r--include/host.mk31
-rw-r--r--include/image.mk96
-rw-r--r--include/kernel-build.mk145
-rw-r--r--include/kernel.mk106
-rw-r--r--include/modules-2.4.mk196
-rw-r--r--include/modules-2.6.mk233
-rw-r--r--include/netfilter.mk122
-rw-r--r--include/package.mk372
-rw-r--r--include/prereq-build.mk105
-rw-r--r--include/prereq.mk54
-rw-r--r--include/shell.sh15
-rw-r--r--include/target.mk31
-rw-r--r--include/verbose.mk43
-rw-r--r--package/Makefile69
-rw-r--r--package/alsa/Makefile81
-rw-r--r--package/alsa/files/alsa.modules10
-rw-r--r--package/alsa/patches/100-compile_fix.patch18
-rw-r--r--package/arptables/Makefile42
-rw-r--r--package/base-files/Makefile191
-rwxr-xr-xpackage/base-files/ar7-2.4/bin/firstboot89
-rw-r--r--package/base-files/ar7-2.4/etc/config/network14
-rwxr-xr-xpackage/base-files/ar7-2.4/etc/init.d/S00adam212
-rwxr-xr-xpackage/base-files/ar7-2.4/etc/preinit11
-rwxr-xr-xpackage/base-files/ar7-2.4/sbin/mount_root28
-rw-r--r--package/base-files/aruba-2.6/etc/config/network11
-rw-r--r--package/base-files/au1000-2.6/etc/config/network14
-rwxr-xr-xpackage/base-files/au1000-2.6/sbin/mount_root26
-rwxr-xr-xpackage/base-files/brcm-2.4/bin/firstboot90
-rw-r--r--package/base-files/brcm-2.4/etc/config/wireless14
-rwxr-xr-xpackage/base-files/brcm-2.4/etc/init.d/S05netconfig87
-rwxr-xr-xpackage/base-files/brcm-2.4/etc/preinit13
-rwxr-xr-xpackage/base-files/brcm-2.4/sbin/mount_root34
-rwxr-xr-xpackage/base-files/brcm-2.6/bin/firstboot90
-rwxr-xr-xpackage/base-files/brcm-2.6/etc/init.d/S05netconfig87
-rwxr-xr-xpackage/base-files/brcm-2.6/etc/preinit13
-rwxr-xr-xpackage/base-files/brcm-2.6/sbin/mount_root35
-rwxr-xr-xpackage/base-files/default/bin/ipcalc32
-rwxr-xr-xpackage/base-files/default/bin/login18
-rwxr-xr-xpackage/base-files/default/bin/uci159
-rw-r--r--package/base-files/default/etc/banner10
-rw-r--r--package/base-files/default/etc/config/network13
-rwxr-xr-xpackage/base-files/default/etc/functions.sh119
-rw-r--r--package/base-files/default/etc/group2
-rw-r--r--package/base-files/default/etc/hosts1
-rwxr-xr-xpackage/base-files/default/etc/hotplug.d/block/01-mount26
-rw-r--r--package/base-files/default/etc/hotplug.d/net/10-net28
-rwxr-xr-xpackage/base-files/default/etc/hotplug.d/usb/01-ln33
-rwxr-xr-xpackage/base-files/default/etc/init.d/S10boot25
-rwxr-xr-xpackage/base-files/default/etc/init.d/S40network11
-rwxr-xr-xpackage/base-files/default/etc/init.d/S50httpd10
-rwxr-xr-xpackage/base-files/default/etc/init.d/S50telnet10
-rwxr-xr-xpackage/base-files/default/etc/init.d/S60cron12
-rwxr-xr-xpackage/base-files/default/etc/init.d/rcS26
-rw-r--r--package/base-files/default/etc/inittab3
-rw-r--r--package/base-files/default/etc/ipkg.conf3
-rw-r--r--package/base-files/default/etc/nvram.sh19
-rw-r--r--package/base-files/default/etc/passwd2
-rw-r--r--package/base-files/default/etc/profile12
-rw-r--r--package/base-files/default/etc/protocols56
-rwxr-xr-xpackage/base-files/default/etc/rc.common73
-rw-r--r--package/base-files/default/etc/resolv.conf2
-rw-r--r--package/base-files/default/etc/shells1
-rw-r--r--package/base-files/default/etc/sysctl.conf12
-rw-r--r--package/base-files/default/lib/config/uci-update.awk160
-rwxr-xr-xpackage/base-files/default/lib/config/uci.sh138
-rwxr-xr-xpackage/base-files/default/lib/network/config.sh143
-rw-r--r--package/base-files/default/rom/note3
-rwxr-xr-xpackage/base-files/default/sbin/hotplug26
-rwxr-xr-xpackage/base-files/default/sbin/ifdown34
-rwxr-xr-xpackage/base-files/default/sbin/ifup14
-rwxr-xr-xpackage/base-files/default/sbin/mount_root10
-rwxr-xr-xpackage/base-files/default/sbin/wifi44
-rw-r--r--package/base-files/default/usr/lib/common.awk68
-rw-r--r--package/base-files/default/usr/lib/parse-config.awk42
-rwxr-xr-xpackage/base-files/default/usr/share/udhcpc/default.script57
-rw-r--r--package/base-files/rb532-2.6/etc/config/network12
-rw-r--r--package/base-files/sibyte-2.6/etc/config/network14
-rw-r--r--package/base-files/sibyte-2.6/etc/inittab5
-rw-r--r--package/base-files/src/adam2patcher.c59
-rw-r--r--package/base-files/src/jffs2root.c133
-rw-r--r--package/base-files/x86-2.4/etc/config/network19
-rw-r--r--package/base-files/x86-2.6/etc/config/network19
-rw-r--r--package/base-files/xscale-2.6/etc/config/network11
-rw-r--r--package/bridge/Makefile46
-rw-r--r--package/bridge/patches/patch-libbridge_Makefile_in11
-rw-r--r--package/broadcom-wl/Makefile148
-rw-r--r--package/broadcom-wl/files/lib/wifi/broadcom.sh177
-rw-r--r--package/broadcom-wl/src/kmod/Makefile31
-rw-r--r--package/broadcom-wl/src/kmod/bcmip.h101
-rw-r--r--package/broadcom-wl/src/kmod/bcmutils.c857
-rw-r--r--package/broadcom-wl/src/kmod/hnddma.c1157
-rw-r--r--package/broadcom-wl/src/kmod/hnddma.h156
-rw-r--r--package/broadcom-wl/src/kmod/linux_osl.c269
-rw-r--r--package/broadcom-wl/src/kmod/linux_osl.h171
-rw-r--r--package/broadcom-wl/src/kmod/patchtable.pl61
-rw-r--r--package/broadcom-wl/src/kmod/pktq.h97
-rw-r--r--package/broadcom-wl/src/kmod/sbhnddma.h284
-rw-r--r--package/broadcom-wl/src/wlc/Makefile9
-rw-r--r--package/broadcom-wl/src/wlc/include/bcmdefs.h106
-rw-r--r--package/broadcom-wl/src/wlc/include/bcmutils.h258
-rw-r--r--package/broadcom-wl/src/wlc/include/proto/802.11.h1258
-rw-r--r--package/broadcom-wl/src/wlc/include/proto/bcmeth.h101
-rw-r--r--package/broadcom-wl/src/wlc/include/proto/bcmevent.h152
-rw-r--r--package/broadcom-wl/src/wlc/include/proto/ethernet.h165
-rw-r--r--package/broadcom-wl/src/wlc/include/proto/wpa.h148
-rw-r--r--package/broadcom-wl/src/wlc/include/typedefs.h230
-rw-r--r--package/broadcom-wl/src/wlc/include/wlioctl.h1384
-rw-r--r--package/broadcom-wl/src/wlc/include/wlutils.h102
-rw-r--r--package/broadcom-wl/src/wlc/ioctl.c298
-rw-r--r--package/broadcom-wl/src/wlc/wlc.c1140
-rw-r--r--package/busybox/Makefile73
-rw-r--r--package/busybox/config/Config.in474
-rw-r--r--package/busybox/config/archival/Config.in308
-rw-r--r--package/busybox/config/console-tools/Config.in88
-rw-r--r--package/busybox/config/coreutils/Config.in775
-rw-r--r--package/busybox/config/debianutils/Config.in88
-rw-r--r--package/busybox/config/e2fsprogs/Config.in67
-rw-r--r--package/busybox/config/editors/Config.in131
-rw-r--r--package/busybox/config/findutils/Config.in159
-rw-r--r--package/busybox/config/init/Config.in83
-rw-r--r--package/busybox/config/libbb/Config.in22
-rw-r--r--package/busybox/config/loginutils/Config.in163
-rw-r--r--package/busybox/config/miscutils/Config.in346
-rw-r--r--package/busybox/config/modutils/Config.in147
-rw-r--r--package/busybox/config/networking/Config.in710
-rw-r--r--package/busybox/config/networking/udhcp/Config.in62
-rw-r--r--package/busybox/config/procps/Config.in121
-rw-r--r--package/busybox/config/shell/Config.in294
-rw-r--r--package/busybox/config/sysklogd/Config.in109
-rw-r--r--package/busybox/config/util-linux/Config.in480
-rw-r--r--package/busybox/patches/001-wget_long_options.patch22
-rw-r--r--package/busybox/patches/100-killall5.patch85
-rw-r--r--package/busybox/patches/110-telnetd.patch51
-rw-r--r--package/busybox/patches/140-unlink-passwd.patch32
-rw-r--r--package/busybox/patches/150-udhcp-release.patch90
-rw-r--r--package/busybox/patches/170-udhcp-options.patch15
-rw-r--r--package/busybox/patches/180-telnetd_ipv6.patch12
-rw-r--r--package/busybox/patches/190-ash_performance.patch80
-rw-r--r--package/busybox/patches/200-etc_crontabs.patch24
-rw-r--r--package/busybox/patches/210-passwd_limit.patch15
-rw-r--r--package/busybox/patches/220-awk_bitops.patch64
-rw-r--r--package/busybox/patches/230-grep_C.patch12
-rw-r--r--package/busybox/patches/300-netmsg.patch110
-rw-r--r--package/busybox/patches/310-passwd_access.patch44
-rw-r--r--package/busybox/patches/320-httpd_address_binding.patch95
-rw-r--r--package/busybox/patches/330-httpd_user_agent.patch30
-rw-r--r--package/busybox/patches/340-lock_util.patch180
-rw-r--r--package/busybox/patches/911-ipkg.patch13896
-rw-r--r--package/busybox/patches/912-ipkg-no_warnings.patch448
-rw-r--r--package/busybox/patches/913-libbb_hash.patch228
-rw-r--r--package/busybox/patches/914-ipkg-fixes.patch19
-rw-r--r--package/diag/Makefile48
-rw-r--r--package/diag/src/Makefile19
-rw-r--r--package/diag/src/diag.c284
-rw-r--r--package/dnsmasq/Makefile55
-rw-r--r--package/dnsmasq/files/dnsmasq.conf28
-rw-r--r--package/dnsmasq/files/dnsmasq.init57
-rw-r--r--package/dnsmasq/patches/101-ipv6.patch13
-rw-r--r--package/dropbear/Makefile120
-rwxr-xr-xpackage/dropbear/files/dropbear.init23
-rw-r--r--package/dropbear/patches/100-pubkey_path.patch45
-rw-r--r--package/dropbear/patches/110-change_user.patch19
-rw-r--r--package/dropbear/patches/120-hostkey_prompt.patch12
-rw-r--r--package/dropbear/patches/130-ssh_ignore_o_and_x_args.patch22
-rw-r--r--package/dropbear/patches/140-use_dev_urandom.patch12
-rw-r--r--package/dropbear/patches/150-dbconvert_standalone.patch14
-rw-r--r--package/ebtables/Makefile43
-rw-r--r--package/fuse/Makefile153
-rw-r--r--package/fuse/patches/101-kmod_build.patch46
-rw-r--r--package/fuse/patches/102-no_depmod.patch15
-rw-r--r--package/fuse/patches/111-uclibc_changes.patch16
-rw-r--r--package/fuse/patches/112-no_break_on_mknod.patch12
-rw-r--r--package/gdbserver/Makefile69
-rw-r--r--package/gmp/Makefile65
-rw-r--r--package/haserl/Makefile36
-rw-r--r--package/hostap-utils/Makefile48
-rw-r--r--package/hostap/Makefile139
-rw-r--r--package/hostapd/Makefile132
-rw-r--r--package/hostapd/files/default.config69
-rw-r--r--package/hostapd/files/mini.config69
-rw-r--r--package/hostapd/patches/001-cross_compile_fix.patch35
-rw-r--r--package/hostapd/patches/100-madwifi_fixes.patch52
-rw-r--r--package/iproute2/Makefile68
-rw-r--r--package/iproute2/patches/000-debian_patches_3.patch1425
-rw-r--r--package/iproute2/patches/001-iproute2-2.6.11_Config.patch8
-rw-r--r--package/iproute2/patches/002-iproute2-ipxfrm_no_sctp.patch19
-rw-r--r--package/iproute2/patches/003-iproute2-htb_overhead.patch96
-rw-r--r--package/ipsec-tools/Makefile99
-rw-r--r--package/ipsec-tools/patches/01-no_libfl.patch24
-rw-r--r--package/ipsec-tools/patches/02-configure_cppflags_typo.patch24
-rw-r--r--package/ipset/Makefile45
-rw-r--r--package/ipset/patches/kernel26.patch66
-rw-r--r--package/iptables/Makefile249
-rw-r--r--package/iptables/files/firewall.awk64
-rw-r--r--package/iptables/files/firewall.config48
-rwxr-xr-xpackage/iptables/files/firewall.init115
-rw-r--r--package/iptables/files/firewall.user28
-rw-r--r--package/iptables/files/l7/aim.pat27
-rw-r--r--package/iptables/files/l7/bittorrent.pat14
-rw-r--r--package/iptables/files/l7/edonkey-dl.pat8
-rw-r--r--package/iptables/files/l7/edonkey.pat29
-rw-r--r--package/iptables/files/l7/fasttrack.pat25
-rw-r--r--package/iptables/files/l7/ftp.pat34
-rw-r--r--package/iptables/files/l7/gnutella.pat36
-rw-r--r--package/iptables/files/l7/http.pat28
-rw-r--r--package/iptables/files/l7/ident.pat14
-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.pat15
-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.pat39
-rw-r--r--package/iptables/files/l7/ssl.pat15
-rw-r--r--package/iptables/files/l7/vnc.pat23
-rw-r--r--package/iptables/patches/01-ipp2p-0.8.1rc1.patch454
-rw-r--r--package/iptables/patches/02-layer7-1.5nbd.patch416
-rw-r--r--package/iptables/patches/04-multiport_v1.patch221
-rw-r--r--package/iptables/patches/05-imq1.patch224
-rw-r--r--package/isakmpd/Makefile51
-rw-r--r--package/isakmpd/patches/010-debian_3.patch1706
-rw-r--r--package/isakmpd/patches/020-standardize.patch59
-rw-r--r--package/isakmpd/patches/030-openssl_hashes.patch154
-rw-r--r--package/isakmpd/patches/040-security_fix.patch22
-rw-r--r--package/kernel/Makefile90
-rw-r--r--package/kernel/modules.mk506
-rw-r--r--package/keynote/Makefile68
-rw-r--r--package/keynote/patches/01-build.patch327
-rw-r--r--package/keynote/patches/02-cross_compile.patch586
-rw-r--r--package/libpcap/Makefile97
-rw-r--r--package/libpcap/patches/100-shared-lib.patch120
-rw-r--r--package/libpcap/patches/101-cross-compile-fix.patch12
-rw-r--r--package/libpcap/patches/102-alt-ether.patch40
-rw-r--r--package/libpcap/patches/103-flex_workaround.patch14
-rw-r--r--package/linux-atm/Makefile88
-rw-r--r--package/linux-atm/files/br2684.hotplug19
-rw-r--r--package/linux-atm/patches/000-debian_16.patch35073
-rw-r--r--package/linux-atm/patches/100-br2684.patch488
-rw-r--r--package/linux-atm/patches/200-no_libfl.patch193
-rw-r--r--package/linux-atm/patches/300-no_autotools.patch12014
-rw-r--r--package/linux-atm/patches/400-stdint_local_instead_of_host.patch12
-rw-r--r--package/madwifi/Makefile133
-rw-r--r--package/madwifi/files/madwifi.init4
-rw-r--r--package/madwifi/files/madwifi.modules10
-rw-r--r--package/madwifi/patches/100-kernel_cflags.patch42
-rw-r--r--package/madwifi/patches/101-no_werror.patch11
-rw-r--r--package/madwifi/patches/102-multicall_binary.patch369
-rw-r--r--package/madwifi/patches/103-disable_rfkill.patch12
-rw-r--r--package/madwifi/patches/104-apmode_by_default.patch12
-rw-r--r--package/mini_fo/Makefile50
-rw-r--r--package/mini_fo/patches/101-kmod_build.patch52
-rw-r--r--package/mini_fo/patches/102-mutex_change.patch602
-rw-r--r--package/mini_fo/patches/103-remove_dead_code.patch47
-rw-r--r--package/mtd/Makefile38
-rw-r--r--package/mtd/src/Makefile12
-rw-r--r--package/mtd/src/mtd.c475
-rw-r--r--package/nvram/Makefile49
-rw-r--r--package/nvram/src/Makefile21
-rw-r--r--package/nvram/src/bcmtimer.h42
-rw-r--r--package/nvram/src/defaults.c179
-rw-r--r--package/nvram/src/include/bcmnvram.h148
-rw-r--r--package/nvram/src/include/bcmutils.h157
-rw-r--r--package/nvram/src/include/cy_conf.h69
-rw-r--r--package/nvram/src/include/epivers.h69
-rw-r--r--package/nvram/src/include/proto/802.11.h852
-rw-r--r--package/nvram/src/include/proto/ethernet.h179
-rw-r--r--package/nvram/src/include/shutils.h200
-rw-r--r--package/nvram/src/include/typedefs.h293
-rw-r--r--package/nvram/src/include/utils.h131
-rw-r--r--package/nvram/src/include/wlcompat.h36
-rw-r--r--package/nvram/src/include/wlioctl.h1097
-rw-r--r--package/nvram/src/include/wlutils.h59
-rw-r--r--package/nvram/src/linux_timer.c738
-rw-r--r--package/nvram/src/main.c88
-rw-r--r--package/nvram/src/nvram_convert.c77
-rw-r--r--package/nvram/src/nvram_convert.h7
-rw-r--r--package/nvram/src/nvram_linux.c320
-rw-r--r--package/nvram/src/shutils.c329
-rw-r--r--package/nvram/src/wl.c299
-rw-r--r--package/nvram/src/wl_linux.c77
-rw-r--r--package/openssl/Makefile134
-rw-r--r--package/openssl/patches/110-optimize-for-size.patch12
-rw-r--r--package/openssl/patches/120-makedepend.patch28
-rw-r--r--package/openssl/patches/130-perl-path.patch72
-rw-r--r--package/openssl/patches/140-makefile-dirs.patch11
-rw-r--r--package/openssl/patches/150-no_engines.patch83
-rw-r--r--package/openssl/patches/160-disable_doc_tests.patch60
-rw-r--r--package/openswan/Makefile94
-rw-r--r--package/openswan/patches/100-pluto_includes.patch12
-rw-r--r--package/openswan/patches/110-scripts.patch243
-rw-r--r--package/openswan/patches/120-use_dev_urandom.patch36
-rw-r--r--package/pcmcia-cs/Makefile68
-rw-r--r--package/pcmcia-cs/patches/001-config-novatel_merlin_u630.patch14
-rw-r--r--package/ppp/Makefile182
-rw-r--r--package/ppp/files/etc/ppp/chap-secrets1
-rw-r--r--package/ppp/files/etc/ppp/filter23
-rwxr-xr-xpackage/ppp/files/etc/ppp/ip-down9
-rwxr-xr-xpackage/ppp/files/etc/ppp/ip-up9
-rw-r--r--package/ppp/files/etc/ppp/options6
-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.microsoft81
-rw-r--r--package/ppp/files/etc/ppp/radius/servers2
-rw-r--r--package/ppp/files/ppp.sh29
-rw-r--r--package/ppp/files/pppoa.sh20
-rw-r--r--package/ppp/files/pppoe.sh21
-rw-r--r--package/ppp/patches/010-use_target_for_configure.patch20
-rw-r--r--package/ppp/patches/100-debian_close_dev_ppp.patch34
-rw-r--r--package/ppp/patches/101-debian_ip-up_option.patch88
-rw-r--r--package/ppp/patches/102-debian_pppoe_multicast_pado.patch14
-rw-r--r--package/ppp/patches/103-debian_pppoe_cleanup.patch1079
-rw-r--r--package/ppp/patches/104-debian_fix_linkpidfile.patch43
-rw-r--r--package/ppp/patches/105-debian_pppoatm_cleanup.patch95
-rw-r--r--package/ppp/patches/106-debian_pppoatm_fix_mtu.patch31
-rw-r--r--package/ppp/patches/107-debian_stripMSdomain.patch35
-rw-r--r--package/ppp/patches/108-debian_defaultroute.patch253
-rw-r--r--package/ppp/patches/109-debian_demand.patch172
-rw-r--r--package/ppp/patches/200-makefile.patch53
-rw-r--r--package/ppp/patches/201-mppe_mppc_1.1.patch1585
-rw-r--r--package/ppp/patches/202-atm_fix.patch11
-rw-r--r--package/ppp/patches/203-no_strip.patch86
-rw-r--r--package/ppp/patches/204-opt_flags.patch26
-rw-r--r--package/ppp/patches/205-pppoe_iface_name.patch12
-rw-r--r--package/ppp/patches/206-radius_config.patch74
-rw-r--r--package/ppp/patches/207-ppp_reconnect.patch129
-rw-r--r--package/ppp/patches/208-no_exponential_timeout.patch28
-rw-r--r--package/ppp/patches/209-compensate_time_change.patch82
-rw-r--r--package/ppp/patches/210-lcp_mtu_max.patch17
-rw-r--r--package/ppp/patches/300-filter-pcap-includes-lib.patch14
-rw-r--r--package/ppp/patches/310-precompiled_filter.patch231
-rw-r--r--package/ppp/utils/pfc.c51
-rw-r--r--package/pptp/Makefile42
-rw-r--r--package/pptp/files/options.pptp7
-rw-r--r--package/pptp/files/pptp.sh23
-rw-r--r--package/qos-scripts/Makefile44
-rw-r--r--package/qos-scripts/files/etc/config/qos94
-rwxr-xr-xpackage/qos-scripts/files/etc/hotplug.d/iface/10-qos2
-rwxr-xr-xpackage/qos-scripts/files/etc/init.d/S50qos18
-rwxr-xr-xpackage/qos-scripts/files/usr/bin/qos-start4
-rwxr-xr-xpackage/qos-scripts/files/usr/bin/qos-stat16
-rwxr-xr-xpackage/qos-scripts/files/usr/bin/qos-stop6
-rwxr-xr-xpackage/qos-scripts/files/usr/lib/qos.sh495
-rw-r--r--package/robocfg/Makefile38
-rw-r--r--package/robocfg/src/Makefile12
-rw-r--r--package/robocfg/src/etc53xx.h620
-rw-r--r--package/robocfg/src/robocfg.c533
-rw-r--r--package/shfs/Makefile93
-rw-r--r--package/shfs/patches/101-kmod_build.patch98
-rw-r--r--package/shfs/patches/102-gcc4_fix.patch23
-rw-r--r--package/shfs/patches/103-dentry.patch21
-rw-r--r--package/spca5xx/Makefile52
-rw-r--r--package/spca5xx/patches/01-kmod-build.patch177
-rw-r--r--package/spca5xx/patches/02-seq_bug.patch14
-rw-r--r--package/switch/Makefile54
-rw-r--r--package/switch/files/switch.sh33
-rw-r--r--package/switch/src/Makefile19
-rw-r--r--package/switch/src/etc53xx.h620
-rw-r--r--package/switch/src/gpio.h52
-rw-r--r--package/switch/src/switch-adm.c579
-rw-r--r--package/switch/src/switch-core.c466
-rw-r--r--package/switch/src/switch-core.h59
-rw-r--r--package/switch/src/switch-robo.c484
-rw-r--r--package/udev/Makefile69
-rw-r--r--package/udev/patches/01-no_debug.patch21
-rw-r--r--package/ueagle-atm/Makefile55
-rw-r--r--package/ueagle-atm/files/ueagle-atm.modules2
-rw-r--r--package/ueagle-atm/patches/100-compile_fix.patch11
-rw-r--r--package/util-linux/Makefile93
-rw-r--r--package/util-linux/patches/501-mconfig.patch68
-rw-r--r--package/util-linux/patches/601-util-linux-2.12r-umount-no-special.patch11
-rw-r--r--package/wireless-tools/Makefile70
-rw-r--r--package/wireless-tools/patches/debian-2.patch35
-rw-r--r--package/wlcompat/Makefile77
-rw-r--r--package/wlcompat/src/Makefile19
-rw-r--r--package/wlcompat/src/include/bcmnvram.h148
-rw-r--r--package/wlcompat/src/include/bcmutils.h157
-rw-r--r--package/wlcompat/src/include/cy_conf.h69
-rw-r--r--package/wlcompat/src/include/epivers.h69
-rw-r--r--package/wlcompat/src/include/proto/802.11.h852
-rw-r--r--package/wlcompat/src/include/proto/ethernet.h179
-rw-r--r--package/wlcompat/src/include/shutils.h200
-rw-r--r--package/wlcompat/src/include/typedefs.h293
-rw-r--r--package/wlcompat/src/include/utils.h131
-rw-r--r--package/wlcompat/src/include/wlcompat.h36
-rw-r--r--package/wlcompat/src/include/wlioctl.h1094
-rw-r--r--package/wlcompat/src/include/wlutils.h59
-rw-r--r--package/wlcompat/src/wlcompat.c1056
-rw-r--r--package/yamonenv/Makefile40
-rw-r--r--package/zd1211/Makefile63
-rw-r--r--package/zlib/Makefile73
-rw-r--r--package/zlib/patches/zlib.patch206
-rw-r--r--rules.mk117
-rwxr-xr-xscripts/adam2flash.pl174
-rwxr-xr-xscripts/config.guess1465
-rw-r--r--scripts/config/Makefile55
-rw-r--r--scripts/config/README2
-rw-r--r--scripts/config/conf.c626
-rw-r--r--scripts/config/confdata.c553
-rw-r--r--scripts/config/expr.c1099
-rw-r--r--scripts/config/expr.h194
-rw-r--r--scripts/config/kconfig_load.c35
-rw-r--r--scripts/config/lex.backup1
-rw-r--r--scripts/config/lex.zconf.c_shipped2338
-rw-r--r--scripts/config/lkc.h147
-rw-r--r--scripts/config/lkc_proto.h42
-rw-r--r--scripts/config/lxdialog/BIG.FAT.WARNING4
-rw-r--r--scripts/config/lxdialog/Makefile20
-rw-r--r--scripts/config/lxdialog/check-lxdialog.sh90
-rw-r--r--scripts/config/lxdialog/checklist.c334
-rw-r--r--scripts/config/lxdialog/colors.h154
-rw-r--r--scripts/config/lxdialog/dialog.h177
-rw-r--r--scripts/config/lxdialog/inputbox.c224
-rw-r--r--scripts/config/lxdialog/lxdialog.c204
-rw-r--r--scripts/config/lxdialog/menubox.c425
-rw-r--r--scripts/config/lxdialog/msgbox.c71
-rw-r--r--scripts/config/lxdialog/textbox.c533
-rw-r--r--scripts/config/lxdialog/util.c362
-rw-r--r--scripts/config/lxdialog/yesno.c102
-rw-r--r--scripts/config/mconf.c1102
-rw-r--r--scripts/config/menu.c400
-rw-r--r--scripts/config/symbol.c891
-rw-r--r--scripts/config/util.c109
-rw-r--r--scripts/config/zconf.gperf43
-rw-r--r--scripts/config/zconf.hash.c_shipped231
-rw-r--r--scripts/config/zconf.l371
-rw-r--r--scripts/config/zconf.tab.c_shipped2146
-rw-r--r--scripts/config/zconf.y681
-rwxr-xr-xscripts/configtest.pl35
-rwxr-xr-xscripts/download.pl112
-rw-r--r--scripts/flash.sh66
-rwxr-xr-xscripts/gen_busybox_config.pl29
-rw-r--r--scripts/gen_busybox_menuconfig.pl76
-rwxr-xr-xscripts/gen_deps.pl91
-rwxr-xr-xscripts/gen_menuconfig.pl133
-rwxr-xr-xscripts/ipkg1187
-rwxr-xr-xscripts/ipkg-make-index.sh24
-rwxr-xr-xscripts/make-ipkg-dir.sh21
-rwxr-xr-xscripts/patch-kernel.sh54
-rwxr-xr-xscripts/rstrip.sh35
-rwxr-xr-xscripts/timestamp.pl64
-rw-r--r--target/Config.in272
-rw-r--r--target/Makefile49
-rw-r--r--target/image/ar7/Makefile102
-rw-r--r--target/image/ar7/sercomm/adam2.binbin0 -> 131072 bytes-rw-r--r--target/image/ar7/sercomm/dg834bin0 -> 80 bytes-rw-r--r--target/image/ar7/sercomm/jdr454wbbin0 -> 80 bytes-rw-r--r--target/image/ar7/src/LzmaDecode.c663
-rw-r--r--target/image/ar7/src/LzmaDecode.h100
-rw-r--r--target/image/ar7/src/gzip.h51
-rw-r--r--target/image/ar7/src/ld.script.in34
-rw-r--r--target/image/ar7/src/loader.c140
-rw-r--r--target/image/ar7/src/srec2bin.c523
-rw-r--r--target/image/ar7/src/zimage.script.in11
-rw-r--r--target/image/aruba/Makefile43
-rwxr-xr-xtarget/image/aruba/addVersionbin0 -> 34464 bytes-rw-r--r--target/image/aruba/version1
-rw-r--r--target/image/au1000/Makefile22
-rw-r--r--target/image/brcm/Makefile69
-rw-r--r--target/image/brcm/lzma-loader/Makefile34
-rw-r--r--target/image/brcm/lzma-loader/src/LzmaDecode.c663
-rw-r--r--target/image/brcm/lzma-loader/src/LzmaDecode.h100
-rw-r--r--target/image/brcm/lzma-loader/src/Makefile77
-rw-r--r--target/image/brcm/lzma-loader/src/README55
-rw-r--r--target/image/brcm/lzma-loader/src/decompress.c175
-rw-r--r--target/image/brcm/lzma-loader/src/decompress.lds.in20
-rw-r--r--target/image/brcm/lzma-loader/src/head.S155
-rw-r--r--target/image/brcm/lzma-loader/src/loader.lds.in17
-rw-r--r--target/image/brcm63xx/Makefile33
-rw-r--r--target/image/generic/Makefile12
-rw-r--r--target/image/generic/lzma-loader/Makefile43
-rw-r--r--target/image/generic/lzma-loader/src/LzmaDecode.c590
-rw-r--r--target/image/generic/lzma-loader/src/LzmaDecode.h131
-rw-r--r--target/image/generic/lzma-loader/src/Makefile63
-rw-r--r--target/image/generic/lzma-loader/src/decompress.c154
-rw-r--r--target/image/generic/lzma-loader/src/lzma-copy.lds.in20
-rw-r--r--target/image/generic/lzma-loader/src/lzma.lds.in24
-rw-r--r--target/image/generic/lzma-loader/src/print.c324
-rw-r--r--target/image/generic/lzma-loader/src/print.h36
-rw-r--r--target/image/generic/lzma-loader/src/printf.c35
-rw-r--r--target/image/generic/lzma-loader/src/printf.h18
-rw-r--r--target/image/generic/lzma-loader/src/start.S160
-rw-r--r--target/image/generic/lzma-loader/src/uart16550.c86
-rw-r--r--target/image/generic/lzma-loader/src/uart16550.h47
-rw-r--r--target/image/magicbox/Makefile38
-rw-r--r--target/image/rb532/Makefile57
-rwxr-xr-xtarget/image/uml/Makefile15
-rw-r--r--target/image/x86/Config.in20
-rw-r--r--target/image/x86/Makefile54
-rwxr-xr-xtarget/image/x86/gen_image.sh60
-rw-r--r--target/image/x86/grub/Makefile58
-rw-r--r--target/image/x86/grub/menu.lst11
-rw-r--r--target/image/xscale/Makefile32
-rw-r--r--target/linux/Config.in492
-rw-r--r--target/linux/Makefile24
-rw-r--r--target/linux/ar531x-2.4/Makefile22
-rw-r--r--target/linux/ar531x-2.4/config1164
-rw-r--r--target/linux/ar531x-2.4/patches/000-atheros-support.patch11411
-rw-r--r--target/linux/ar7-2.4/Config.in29
-rw-r--r--target/linux/ar7-2.4/Makefile72
-rw-r--r--target/linux/ar7-2.4/config1080
-rw-r--r--target/linux/ar7-2.4/patches/000-ar7_support.patch9549
-rw-r--r--target/linux/ar7-2.4/patches/001-flash_map.patch307
-rw-r--r--target/linux/ar7-2.4/patches/002-led_driver.patch1915
-rw-r--r--target/linux/ar7-2.4/patches/003-net_driver_cpmac.patch13341
-rw-r--r--target/linux/ar7-2.4/patches/004-atm_driver.patch27232
-rw-r--r--target/linux/ar7-2.4/patches/005-wdt_driver.patch392
-rw-r--r--target/linux/ar7-2.4/patches/006-sched_use_tsc.patch84
-rw-r--r--target/linux/aruba-2.6/Makefile22
-rw-r--r--target/linux/aruba-2.6/config1539
-rw-r--r--target/linux/aruba-2.6/patches/000-aruba.patch10521
-rw-r--r--target/linux/aruba-2.6/patches/001-flash.patch159
-rw-r--r--target/linux/aruba-2.6/patches/002-irq.patch286
-rw-r--r--target/linux/aruba-2.6/patches/003-pci.patch618
-rw-r--r--target/linux/aruba-2.6/patches/004-wdt.patch126
-rw-r--r--target/linux/aruba-2.6/patches/010-ar2313_enet.patch2175
-rw-r--r--target/linux/aruba-2.6/patches/011-ap6x_serial_fix.patch31
-rw-r--r--target/linux/aruba-2.6/patches/012-ehci_softirq.patch70
-rw-r--r--target/linux/au1000-2.6/Makefile27
-rw-r--r--target/linux/au1000-2.6/config1595
-rw-r--r--target/linux/au1000-2.6/patches/001-redefinitions_fixes.patch26
-rw-r--r--target/linux/au1000-2.6/patches/002-mtx1_flash_map.patch16
-rw-r--r--target/linux/au1000-2.6/patches/003-zImage.patch1364
-rw-r--r--target/linux/au1000-2.6/patches/004-mtx1_watchdog.patch279
-rw-r--r--target/linux/au1000-2.6/patches/005-au1000_eth_link_beat.patch24
-rw-r--r--target/linux/au1000-2.6/patches/006-mtx1_system_button.patch241
-rw-r--r--target/linux/au1000-2.6/patches/007-mtx1_sio2.patch13
-rw-r--r--target/linux/au1000-2.6/patches/008-isdel_cardbus.patch63
-rw-r--r--target/linux/brcm-2.4/Makefile22
-rw-r--r--target/linux/brcm-2.4/config1385
-rw-r--r--target/linux/brcm-2.4/patches/001-bcm47xx.patch16794
-rw-r--r--target/linux/brcm-2.4/patches/002-wl_fix.patch348
-rw-r--r--target/linux/brcm-2.4/patches/003-bcm47xx_cache_fixes.patch498
-rw-r--r--target/linux/brcm-2.4/patches/004-flash.patch916
-rw-r--r--target/linux/brcm-2.4/patches/005-bluetooth_sco_buffer_align.patch12
-rw-r--r--target/linux/brcm-2.4/patches/006-ide_workaround.patch18
-rw-r--r--target/linux/brcm-2.4/patches/007-sched_use_tsc.patch84
-rw-r--r--target/linux/brcm-2.4/patches/008-b44_bcm47xx_support.patch585
-rw-r--r--target/linux/brcm-2.4/patches/009-wrt54g3g_pcmcia.patch119
-rw-r--r--target/linux/brcm-2.4/patches/010-bcm47xx-cam_absent.patch42
-rw-r--r--target/linux/brcm-2.6/Makefile23
-rw-r--r--target/linux/brcm-2.6/config1740
-rw-r--r--target/linux/brcm-2.6/patches/001-bcm947xx.patch11862
-rw-r--r--target/linux/brcm-2.6/patches/002-flash-map.patch483
-rw-r--r--target/linux/brcm-2.6/patches/003-bcm4710_cache_fixes.patch354
-rw-r--r--target/linux/brcm-2.6/patches/004-b44_bcm47xx_support.patch699
-rw-r--r--target/linux/brcm-2.6/patches/010-bcm47xx-cam_absent.patch42
-rw-r--r--target/linux/brcm63xx-2.6/Makefile23
-rw-r--r--target/linux/brcm63xx-2.6/config1629
-rw-r--r--target/linux/brcm63xx-2.6/patches/001-bcm963xx.patch9656
-rw-r--r--target/linux/brcm63xx-2.6/patches/040-bcm963xx_flashmap.patch213
-rw-r--r--target/linux/brcm63xx-2.6/patches/100-binary_hacks.patch267
-rw-r--r--target/linux/control/kernel.control4
-rw-r--r--target/linux/control/kmod-atm.control4
-rw-r--r--target/linux/control/kmod-ax25.control4
-rw-r--r--target/linux/control/kmod-bluetooth.control4
-rw-r--r--target/linux/control/kmod-brcm-et.control4
-rw-r--r--target/linux/control/kmod-brcm-wl.control4
-rw-r--r--target/linux/control/kmod-brcm-wl2.control5
-rw-r--r--target/linux/control/kmod-cpmac.control4
-rw-r--r--target/linux/control/kmod-fs-cifs.control4
-rw-r--r--target/linux/control/kmod-fs-ext2.control4
-rw-r--r--target/linux/control/kmod-fs-ext3.control4
-rw-r--r--target/linux/control/kmod-fs-hfsplus.control4
-rw-r--r--target/linux/control/kmod-fs-minix.control4
-rw-r--r--target/linux/control/kmod-fs-nfs.control4
-rw-r--r--target/linux/control/kmod-fs-vfat.control4
-rw-r--r--target/linux/control/kmod-fs-xfs.control4
-rw-r--r--target/linux/control/kmod-imq.control4
-rw-r--r--target/linux/control/kmod-iptables-extra.control4
-rw-r--r--target/linux/control/kmod-iptables.control4
-rw-r--r--target/linux/control/kmod-loop.control4
-rw-r--r--target/linux/control/kmod-lp.control4
-rw-r--r--target/linux/control/kmod-nbd.control4
-rw-r--r--target/linux/control/kmod-net-airo.control4
-rw-r--r--target/linux/control/kmod-net-hermes-pci.control4
-rw-r--r--target/linux/control/kmod-net-hermes-plx.control4
-rw-r--r--target/linux/control/kmod-net-hermes.control4
-rw-r--r--target/linux/control/kmod-net-prism54.control4
-rw-r--r--target/linux/control/kmod-nls-base.control4
-rw-r--r--target/linux/control/kmod-nls-cp437.control4
-rw-r--r--target/linux/control/kmod-nls-cp850.control4
-rw-r--r--target/linux/control/kmod-nls-iso8859-1.control4
-rw-r--r--target/linux/control/kmod-nls-iso8859-15.control4
-rw-r--r--target/linux/control/kmod-nls-utf8.control4
-rw-r--r--target/linux/control/kmod-pcmcia-core.control4
-rw-r--r--target/linux/control/kmod-pcmcia-serial.control4
-rw-r--r--target/linux/control/kmod-pwc.control4
-rw-r--r--target/linux/control/kmod-sangam-atm-annex-a.control4
-rw-r--r--target/linux/control/kmod-sangam-atm-annex-b.control4
-rw-r--r--target/linux/control/kmod-softdog.control4
-rw-r--r--target/linux/control/kmod-soundcore.control4
-rw-r--r--target/linux/control/kmod-usb-acm.control4
-rw-r--r--target/linux/control/kmod-usb-atm-speedtouch.control4
-rw-r--r--target/linux/control/kmod-usb-atm.control5
-rw-r--r--target/linux/control/kmod-usb-audio.control5
-rw-r--r--target/linux/control/kmod-usb-core.control4
-rw-r--r--target/linux/control/kmod-usb-ohci.control4
-rw-r--r--target/linux/control/kmod-usb-printer.control4
-rw-r--r--target/linux/control/kmod-usb-serial-belkin.control4
-rw-r--r--target/linux/control/kmod-usb-serial-ftdi.control4
-rw-r--r--target/linux/control/kmod-usb-serial-mct-u232.control4
-rw-r--r--target/linux/control/kmod-usb-serial-pl2303.control4
-rw-r--r--target/linux/control/kmod-usb-serial-visor.control4
-rw-r--r--target/linux/control/kmod-usb-serial.control4
-rw-r--r--target/linux/control/kmod-usb-storage.control4
-rw-r--r--target/linux/control/kmod-usb-uhci.control4
-rw-r--r--target/linux/control/kmod-usb2.control4
-rw-r--r--target/linux/control/kmod-videodev.control4
-rw-r--r--target/linux/control/kmod-wd1100.control4
-rw-r--r--target/linux/generic-2.4/README98
-rw-r--r--target/linux/generic-2.4/patches/000-linux_mips.patch27959
-rw-r--r--target/linux/generic-2.4/patches/001-squashfs.patch4070
-rw-r--r--target/linux/generic-2.4/patches/002-squashfs_lzma.patch883
-rw-r--r--target/linux/generic-2.4/patches/003-jffs2_compression.patch9119
-rw-r--r--target/linux/generic-2.4/patches/004-exec_pagesize.patch11
-rw-r--r--target/linux/generic-2.4/patches/005-mtd_flashtypes.patch925
-rw-r--r--target/linux/generic-2.4/patches/006-gcc4_fixes.patch522
-rw-r--r--target/linux/generic-2.4/patches/007-more_gcc4_fixes.patch1339
-rw-r--r--target/linux/generic-2.4/patches/008-intel_flashchip_fix.patch101
-rw-r--r--target/linux/generic-2.4/patches/009-calibrate_section.patch11
-rw-r--r--target/linux/generic-2.4/patches/010-disable_old_squashfs_compatibility.patch25
-rw-r--r--target/linux/generic-2.4/patches/050-build_flags.patch83
-rw-r--r--target/linux/generic-2.4/patches/051-remove_pcmcia_modinst_compat.patch21
-rw-r--r--target/linux/generic-2.4/patches/100-wireless-extension.patch1121
-rw-r--r--target/linux/generic-2.4/patches/106-mppe_mppc.patch1649
-rw-r--r--target/linux/generic-2.4/patches/107-cifs.patch22022
-rw-r--r--target/linux/generic-2.4/patches/108-optional_aout_support.patch688
-rw-r--r--target/linux/generic-2.4/patches/109-ipsec_nat_traversal.patch140
-rw-r--r--target/linux/generic-2.4/patches/110-netdev_random_core.patch296
-rw-r--r--target/linux/generic-2.4/patches/112-bridging_performance.patch22
-rw-r--r--target/linux/generic-2.4/patches/113-even_more_gcc4_stuff.patch367
-rw-r--r--target/linux/generic-2.4/patches/200-i4l.patch20247
-rw-r--r--target/linux/generic-2.4/patches/201-hfc_usb_backport.patch2663
-rw-r--r--target/linux/generic-2.4/patches/202-pl2303_backport.patch40
-rw-r--r--target/linux/generic-2.4/patches/203-hfsplus_fix.patch23
-rw-r--r--target/linux/generic-2.4/patches/206-gcc_3.4_fixes.patch225
-rw-r--r--target/linux/generic-2.4/patches/208-usb2_fix.patch15
-rw-r--r--target/linux/generic-2.4/patches/209-build_fixes.patch48
-rw-r--r--target/linux/generic-2.4/patches/210-fix-irq-serial.patch21
-rw-r--r--target/linux/generic-2.4/patches/212-htb_time_fix.patch75
-rw-r--r--target/linux/generic-2.4/patches/213-htb_disable_hysteresis.patch11
-rw-r--r--target/linux/generic-2.4/patches/222-sound.patch27
-rw-r--r--target/linux/generic-2.4/patches/224-atm_hotplug.patch98
-rw-r--r--target/linux/generic-2.4/patches/225-string_lib_useful_exports.patch170
-rw-r--r--target/linux/generic-2.4/patches/226-atm_br2684.patch578
-rw-r--r--target/linux/generic-2.4/patches/227-jffs2_eofdetect.patch97
-rw-r--r--target/linux/generic-2.4/patches/228-more_usb_fixes.patch861
-rw-r--r--target/linux/generic-2.4/patches/229-pppoe_mtu_fix.patch12
-rw-r--r--target/linux/generic-2.4/patches/601-netfilter_ipp2p_0.8.1rc1.patch929
-rw-r--r--target/linux/generic-2.4/patches/602-netfilter_layer7_2.1nbd.patch2083
-rw-r--r--target/linux/generic-2.4/patches/603-netfilter_nat_pptp.patch2412
-rw-r--r--target/linux/generic-2.4/patches/604-netfilter_maxconn.patch20
-rw-r--r--target/linux/generic-2.4/patches/605-netfilter_TTL.patch180
-rw-r--r--target/linux/generic-2.4/patches/606-netfilter_NETMAP.patch159
-rw-r--r--target/linux/generic-2.4/patches/607-netfilter_connmark.patch351
-rw-r--r--target/linux/generic-2.4/patches/608-netfilter_ipset.patch5725
-rw-r--r--target/linux/generic-2.4/patches/609-netfilter_string.patch348
-rw-r--r--target/linux/generic-2.4/patches/610-netfilter_connbytes.patch439
-rw-r--r--target/linux/generic-2.4/patches/611-netfilter_condition.patch625
-rw-r--r--target/linux/generic-2.4/patches/612-netfilter_quota.patch147
-rw-r--r--target/linux/generic-2.4/patches/613-netfilter_nat_h323.patch821
-rw-r--r--target/linux/generic-2.4/patches/614-netfilter_nat_rtsp.patch1523
-rw-r--r--target/linux/generic-2.4/patches/615-netfilter_nat_mms.patch739
-rw-r--r--target/linux/generic-2.4/patches/616-netfilter_imq.patch748
-rw-r--r--target/linux/generic-2.4/patches/617-netfilter_time.patch238
-rw-r--r--target/linux/generic-2.4/patches/618-netfilter_multiport_backport.patch231
-rw-r--r--target/linux/generic-2.4/patches/700-multiple_default_gateways.patch1299
-rwxr-xr-xtarget/linux/generic-2.6/files/init82
-rw-r--r--target/linux/generic-2.6/patches/000-reenable_devfs.patch718
-rw-r--r--target/linux/generic-2.6/patches/001-squashfs.patch4173
-rw-r--r--target/linux/generic-2.6/patches/002-squashfs_lzma.patch886
-rw-r--r--target/linux/generic-2.6/patches/004-extra_optimization.patch12
-rw-r--r--target/linux/generic-2.6/patches/005-gcc4_fix.patch221
-rw-r--r--target/linux/generic-2.6/patches/006-gcc4_inline_fix.patch11
-rw-r--r--target/linux/generic-2.6/patches/010-disable_old_squashfs_compatibility.patch22
-rw-r--r--target/linux/generic-2.6/patches/011-mips_boot.patch15
-rw-r--r--target/linux/generic-2.6/patches/100-netfilter_layer7_2.1nbd.patch2071
-rw-r--r--target/linux/generic-2.6/patches/101-ipp2p_0.8.1rc1.patch935
-rw-r--r--target/linux/generic-2.6/patches/102-openswan-2.4.0.kernel-2.6-natt.patch171
-rw-r--r--target/linux/generic-2.6/patches/103-netfilter-ipset.patch5739
-rw-r--r--target/linux/generic-2.6/patches/105-netfilter_time.patch241
-rw-r--r--target/linux/generic-2.6/patches/106-netfilter_imq.patch885
-rw-r--r--target/linux/generic-2.6/patches/107-netfilter_nat_sip.patch830
-rw-r--r--target/linux/generic-2.6/patches/108-netfilter_route.patch914
-rw-r--r--target/linux/generic-2.6/patches/200-sched_esfq.patch730
-rw-r--r--target/linux/generic-2.6/patches/201-multiple_default_gateways.patch1238
-rw-r--r--target/linux/generic-2.6/patches/202-mips-freestanding.patch12
-rw-r--r--target/linux/generic-2.6/patches/203-fix_initrd_duplication.patch13
-rw-r--r--target/linux/generic-2.6/patches/204-jffs2_eofdetect.patch58
-rw-r--r--target/linux/generic-2.6/patches/205-block2mtd_fix.patch235
-rw-r--r--target/linux/generic-2.6/patches/206-pppoe_mtu_fix.patch12
-rw-r--r--target/linux/magicbox-2.6/Makefile22
-rw-r--r--target/linux/magicbox-2.6/config1161
-rw-r--r--target/linux/magicbox-2.6/patches/001-magicbox_support.patch372
-rw-r--r--target/linux/magicbox-2.6/patches/002-flash_map.patch147
-rw-r--r--target/linux/package/Config.in1
-rw-r--r--target/linux/package/Makefile54
-rw-r--r--target/linux/rb532-2.6/Makefile22
-rw-r--r--target/linux/rb532-2.6/config1335
-rw-r--r--target/linux/rb532-2.6/patches/100-rb5xx_support.patch5606
-rw-r--r--target/linux/rb532-2.6/patches/110-korina_ethernet.patch1375
-rw-r--r--target/linux/rb532-2.6/patches/120-cf.patch990
-rw-r--r--target/linux/rb532-2.6/patches/130-custom_partitions.patch311
-rw-r--r--target/linux/rb532-2.6/patches/200-bridge_resource_hack.patch13
-rw-r--r--target/linux/rb532-2.6/patches/210-pci_fixes.patch46
-rw-r--r--target/linux/rb532-2.6/patches/220-serial_fix.patch18
-rw-r--r--target/linux/rb532-2.6/patches/230-dma_limit.patch13
-rw-r--r--target/linux/rb532-2.6/patches/240-via_rhine_performance.patch461
-rw-r--r--target/linux/sibyte-2.6/Makefile22
-rw-r--r--target/linux/sibyte-2.6/config1313
-rw-r--r--target/linux/sibyte-2.6/patches/000-DUART.patch957
-rw-r--r--target/linux/sibyte-2.6/patches/001-bcm112x_ax.patch17
-rw-r--r--target/linux/uml-2.6/Makefile21
-rw-r--r--target/linux/uml-2.6/README45
-rw-r--r--target/linux/uml-2.6/config904
-rw-r--r--target/linux/x86-2.6/Makefile21
-rw-r--r--target/linux/x86-2.6/config2077
-rw-r--r--target/linux/x86-2.6/patches/100-scx200_hr_timer.patch320
-rw-r--r--target/linux/xscale-2.6/Makefile21
-rw-r--r--target/linux/xscale-2.6/config1384
-rw-r--r--target/linux/xscale-2.6/patches/001-gateway_7001.patch163
-rw-r--r--target/sdk/Config.in9
-rw-r--r--target/sdk/Makefile47
-rw-r--r--target/sdk/files/Makefile69
-rw-r--r--target/sdk/files/README.SDK7
-rw-r--r--target/sdk/files/package/depend.mk6
-rw-r--r--target/sdk/files/package/rules.mk89
-rw-r--r--target/utils/Makefile32
-rw-r--r--target/utils/src/addpattern.c235
-rw-r--r--target/utils/src/dgfirmware.c376
-rw-r--r--target/utils/src/motorola-bin.c146
-rw-r--r--target/utils/src/trx.c366
-rw-r--r--toolchain/Config.in54
-rw-r--r--toolchain/Makefile72
-rw-r--r--toolchain/binutils/Config.in24
-rw-r--r--toolchain/binutils/Makefile54
-rw-r--r--toolchain/binutils/patches/2.16.1/100-uclibc-conf.patch586
-rw-r--r--toolchain/binutils/patches/2.16.1/110-uclibc-libtool-conf.patch218
-rw-r--r--toolchain/binutils/patches/2.16.1/300-001_ld_makefile_patch.patch52
-rw-r--r--toolchain/binutils/patches/2.16.1/300-006_better_file_error.patch43
-rw-r--r--toolchain/binutils/patches/2.16.1/300-012_check_ldrunpath_length.patch47
-rw-r--r--toolchain/binutils/patches/2.16.1/702-binutils-skip-comments.patch93
-rw-r--r--toolchain/binutils/patches/2.17/100-uclibc-conf.patch139
-rw-r--r--toolchain/binutils/patches/2.17/110-arm-eabi-conf.patch24
-rw-r--r--toolchain/binutils/patches/2.17/300-001_ld_makefile_patch.patch50
-rw-r--r--toolchain/binutils/patches/2.17/300-006_better_file_error.patch43
-rw-r--r--toolchain/binutils/patches/2.17/300-012_check_ldrunpath_length.patch47
-rw-r--r--toolchain/binutils/patches/2.17/702-binutils-skip-comments.patch93
-rw-r--r--toolchain/binutils/patches/400-mips-ELF_MAXPAGESIZE-4k.patch12
-rw-r--r--toolchain/gcc/Config.in51
-rw-r--r--toolchain/gcc/Config.version20
-rw-r--r--toolchain/gcc/Makefile143
-rw-r--r--toolchain/gcc/patches/3.4.4/100-uclibc-conf.patch442
-rw-r--r--toolchain/gcc/patches/3.4.4/200-uclibc-locale.patch3246
-rw-r--r--toolchain/gcc/patches/3.4.4/300-libstdc++-pic.patch47
-rw-r--r--toolchain/gcc/patches/3.4.4/601-gcc34-arm-ldm.patch119
-rw-r--r--toolchain/gcc/patches/3.4.4/602-sdk-libstdc++-includes.patch22
-rw-r--r--toolchain/gcc/patches/3.4.4/700-pr15068-fix.patch44
-rw-r--r--toolchain/gcc/patches/3.4.4/800-arm-bigendian.patch70
-rw-r--r--toolchain/gcc/patches/3.4.4/810-arm-bigendian-uclibc.patch27
-rw-r--r--toolchain/gcc/patches/3.4.4/830-gcc-bug-num-22167.patch16
-rw-r--r--toolchain/gcc/patches/3.4.4/arm-softfloat.patch.conditional270
-rw-r--r--toolchain/gcc/patches/3.4.5/100-uclibc-conf.patch462
-rw-r--r--toolchain/gcc/patches/3.4.5/200-uclibc-locale.patch3255
-rw-r--r--toolchain/gcc/patches/3.4.5/300-libstdc++-pic.patch47
-rw-r--r--toolchain/gcc/patches/3.4.5/600-gcc34-arm-ldm-peephole.patch65
-rw-r--r--toolchain/gcc/patches/3.4.5/601-gcc34-arm-ldm-peephole2.patch42
-rw-r--r--toolchain/gcc/patches/3.4.5/601-gcc34-arm-ldm.patch119
-rw-r--r--toolchain/gcc/patches/3.4.5/602-sdk-libstdc++-includes.patch22
-rw-r--r--toolchain/gcc/patches/3.4.5/700-pr15068-fix.patch44
-rw-r--r--toolchain/gcc/patches/3.4.5/71_all_sh-pr16665-fix.patch43
-rw-r--r--toolchain/gcc/patches/3.4.5/72_all_sh-no-reorder-blocks.patch13
-rw-r--r--toolchain/gcc/patches/3.4.5/73_all_sh-pr20617.patch28
-rw-r--r--toolchain/gcc/patches/3.4.5/800-arm-bigendian.patch70
-rw-r--r--toolchain/gcc/patches/3.4.5/800-powerpc-libc_stack_end-uclibc.patch15
-rw-r--r--toolchain/gcc/patches/3.4.6-nonmips/001-non_mips.patch85
-rw-r--r--toolchain/gcc/patches/3.4.6-nonmips/100-uclibc-conf.patch442
-rw-r--r--toolchain/gcc/patches/3.4.6-nonmips/200-uclibc-locale.patch3246
-rw-r--r--toolchain/gcc/patches/3.4.6-nonmips/300-libstdc++-pic.patch47
-rw-r--r--toolchain/gcc/patches/3.4.6-nonmips/601-gcc34-arm-ldm.patch119
-rw-r--r--toolchain/gcc/patches/3.4.6-nonmips/602-sdk-libstdc++-includes.patch22
-rw-r--r--toolchain/gcc/patches/3.4.6-nonmips/700-pr15068-fix.patch44
-rw-r--r--toolchain/gcc/patches/3.4.6-nonmips/800-arm-bigendian.patch70
-rw-r--r--toolchain/gcc/patches/3.4.6-nonmips/810-arm-bigendian-uclibc.patch27
-rw-r--r--toolchain/gcc/patches/3.4.6-nonmips/arm-softfloat.patch.conditional270
-rw-r--r--toolchain/gcc/patches/3.4.6/100-uclibc-conf.patch442
-rw-r--r--toolchain/gcc/patches/3.4.6/200-uclibc-locale.patch3246
-rw-r--r--toolchain/gcc/patches/3.4.6/300-libstdc++-pic.patch47
-rw-r--r--toolchain/gcc/patches/3.4.6/601-gcc34-arm-ldm.patch119
-rw-r--r--toolchain/gcc/patches/3.4.6/602-sdk-libstdc++-includes.patch22
-rw-r--r--toolchain/gcc/patches/3.4.6/700-pr15068-fix.patch44
-rw-r--r--toolchain/gcc/patches/3.4.6/800-arm-bigendian.patch70
-rw-r--r--toolchain/gcc/patches/3.4.6/810-arm-bigendian-uclibc.patch27
-rw-r--r--toolchain/gcc/patches/3.4.6/arm-softfloat.patch.conditional270
-rw-r--r--toolchain/gcc/patches/4.0.2/100-uclibc-conf.patch410
-rw-r--r--toolchain/gcc/patches/4.0.2/200-uclibc-locale.patch3191
-rw-r--r--toolchain/gcc/patches/4.0.3/100-uclibc-conf.patch553
-rw-r--r--toolchain/gcc/patches/4.0.3/200-uclibc-locale.patch3237
-rw-r--r--toolchain/gcc/patches/4.0.3/300-libstdc++-pic.patch47
-rw-r--r--toolchain/gcc/patches/4.0.3/301-missing-execinfo_h.patch11
-rw-r--r--toolchain/gcc/patches/4.0.3/302-c99-snprintf.patch11
-rw-r--r--toolchain/gcc/patches/4.0.3/303-c99-complex-ugly-hack.patch12
-rw-r--r--toolchain/gcc/patches/4.0.3/602-sdk-libstdc++-includes.patch22
-rw-r--r--toolchain/gcc/patches/4.0.3/800-arm-bigendian.patch67
-rw-r--r--toolchain/gcc/patches/4.1.0/100-uclibc-conf.patch544
-rw-r--r--toolchain/gcc/patches/4.1.0/110-arm-eabi.patch27
-rw-r--r--toolchain/gcc/patches/4.1.0/200-uclibc-locale.patch3246
-rw-r--r--toolchain/gcc/patches/4.1.0/300-libstdc++-pic.patch46
-rw-r--r--toolchain/gcc/patches/4.1.0/301-missing-execinfo_h.patch11
-rw-r--r--toolchain/gcc/patches/4.1.0/302-c99-snprintf.patch11
-rw-r--r--toolchain/gcc/patches/4.1.0/303-c99-complex-ugly-hack.patch12
-rw-r--r--toolchain/gcc/patches/4.1.0/602-sdk-libstdc++-includes.patch20
-rw-r--r--toolchain/gcc/patches/4.1.0/740-sh-pr24836.patch25
-rw-r--r--toolchain/gcc/patches/4.1.0/800-arm-bigendian.patch67
-rw-r--r--toolchain/gcc/patches/4.1.1/100-uclibc-conf.patch544
-rw-r--r--toolchain/gcc/patches/4.1.1/110-arm-eabi.patch27
-rw-r--r--toolchain/gcc/patches/4.1.1/200-uclibc-locale.patch3239
-rw-r--r--toolchain/gcc/patches/4.1.1/300-libstdc++-pic.patch50
-rw-r--r--toolchain/gcc/patches/4.1.1/301-missing-execinfo_h.patch11
-rw-r--r--toolchain/gcc/patches/4.1.1/302-c99-snprintf.patch11
-rw-r--r--toolchain/gcc/patches/4.1.1/303-c99-complex-ugly-hack.patch12
-rw-r--r--toolchain/gcc/patches/4.1.1/304-index_macro.patch24
-rw-r--r--toolchain/gcc/patches/4.1.1/740-sh-pr24836.patch25
-rw-r--r--toolchain/gcc/patches/4.1.1/800-arm-bigendian.patch67
-rw-r--r--toolchain/gcc/patches/4.1.1/900-c++_fixes.patch37
-rw-r--r--toolchain/gdb/Config.in8
-rw-r--r--toolchain/gdb/Makefile55
-rw-r--r--toolchain/gdb/patches/100-uclibc-conf.patch280
-rw-r--r--toolchain/gdb/patches/200-uclibc-readline-conf.patch15
-rw-r--r--toolchain/gdb/patches/400-mips-coredump.patch28
-rw-r--r--toolchain/gdb/patches/500-thread-timeout.patch34
-rw-r--r--toolchain/gdb/patches/600-debian_10.selected-frame.patch552
-rw-r--r--toolchain/gdb/patches/620-debian_static-thread-db.patch156
-rw-r--r--toolchain/gdb/patches/630-debian_24.tracepoint-segv.patch15
-rw-r--r--toolchain/gdb/patches/640-debian_dwarf2-frame-signal-unwinder.patch120
-rw-r--r--toolchain/gdb/patches/650-debian_vsyscall-gdb-support.patch245
-rw-r--r--toolchain/gdb/patches/660-debian_dwarf-cfa-restore.patch23
-rw-r--r--toolchain/gdb/patches/680-debian_sim-destdir.patch53
-rw-r--r--toolchain/gdb/patches/690-debian_member-field-symtab.patch35
-rw-r--r--toolchain/gdb/patches/700-debian_cp-pass-by-reference.patch464
-rw-r--r--toolchain/gdb/patches/710-debian_thread-db-multiple-libraries.patch593
-rw-r--r--toolchain/gdb/patches/720-debian_static-threads-test.patch36
-rw-r--r--toolchain/gdb/patches/730-debian_gdb-fix-tracefork-check.patch225
-rw-r--r--toolchain/gdb/patches/740-debian_make-cv-type-crash.patch132
-rw-r--r--toolchain/gdb/patches/750-debian_sparc-singlestep.patch37
-rw-r--r--toolchain/gdb/patches/760-debian_vsyscall-bfd-close-result.patch20
-rw-r--r--toolchain/gdb/patches/770-debian_vfork-done-spelling.patch31
-rw-r--r--toolchain/gdb/patches/780-debian_gdbserver-rdynamic.patch675
-rw-r--r--toolchain/gdb/patches/790-debian_dwarf2-cfi-warning.patch39
-rw-r--r--toolchain/gdb/patches/800-debian_linux-use-underscore-exit.patch22
-rw-r--r--toolchain/gdb/patches/810-debian_bfd-no-kylix-crash.patch47
-rw-r--r--toolchain/gdb/patches/820-debian_disable-linux-fork-messages.patch46
-rw-r--r--toolchain/kernel-headers/Makefile63
-rw-r--r--toolchain/kernel-headers/files/config.arm778
-rw-r--r--toolchain/kernel-headers/files/config.i386950
-rw-r--r--toolchain/kernel-headers/files/config.mips1045
-rw-r--r--toolchain/kernel-headers/files/config.ppc341
-rw-r--r--toolchain/kernel-headers/patches/include.patch17954
-rw-r--r--toolchain/libnotimpl/Makefile39
-rw-r--r--toolchain/libnotimpl/src/math.c68
-rw-r--r--toolchain/uClibc/Makefile98
-rw-r--r--toolchain/uClibc/config/armeb168
-rw-r--r--toolchain/uClibc/config/i386185
-rw-r--r--toolchain/uClibc/config/mips170
-rw-r--r--toolchain/uClibc/config/mipsel170
-rw-r--r--toolchain/uClibc/config/powerpc168
-rw-r--r--toolchain/uClibc/patches/100-signal_handler_crash_workaround.patch13
-rw-r--r--toolchain/uClibc/patches/110-mips_pipe.patch27
-rw-r--r--toolchain/uClibc/patches/120-more_standard_math.patch12
-rw-r--r--toolchain/uClibc/patches/130-ppc_gcc4_fix.patch223
-rw-r--r--toolchain/uClibc/patches/140-ipv6_missing_sockopts.patch12
-rw-r--r--toolchain/uClibc/patches/150-portability.patch38
-rw-r--r--tools/Makefile60
-rw-r--r--tools/ext2fs/Makefile59
-rw-r--r--tools/include/byteswap.h3
-rw-r--r--tools/include/endian.h34
-rw-r--r--tools/include/getline.h62
-rw-r--r--tools/ipkg-utils/Makefile37
-rw-r--r--tools/ipkg-utils/patches/100-build_clean.patch36
-rw-r--r--tools/ipkg-utils/patches/110-buildpackage.patch24
-rw-r--r--tools/ipkg-utils/patches/120-build_tar.patch16
-rw-r--r--tools/ipkg-utils/patches/130-tar_wildcards.patch23
-rw-r--r--tools/ipkg-utils/patches/140-portability.patch50
-rw-r--r--tools/lzma/Makefile44
-rw-r--r--tools/lzma/patches/100-lzma_zlib.patch408
-rw-r--r--tools/mkimage/Makefile27
-rw-r--r--tools/mkimage/src/crc32.c197
-rw-r--r--tools/mkimage/src/image.h157
-rw-r--r--tools/mkimage/src/mkimage.c745
-rw-r--r--tools/mtd-utils/Makefile39
-rw-r--r--tools/mtd-utils/patches/100-gcc4_fix.patch24
-rw-r--r--tools/mtd-utils/patches/110-portability_fix.patch63
-rw-r--r--tools/sed/Makefile48
-rw-r--r--tools/squashfs/Makefile34
-rw-r--r--tools/squashfs/patches/100-lzma.patch25
-rw-r--r--tools/sstrip/Makefile30
-rw-r--r--tools/sstrip/include/elf.h2445
-rw-r--r--tools/sstrip/src/sstrip.c492
907 files changed, 495477 insertions, 0 deletions
diff --git a/BSDmakefile b/BSDmakefile
new file mode 100644
index 0000000000..f6f0cadf46
--- /dev/null
+++ b/BSDmakefile
@@ -0,0 +1,2 @@
+world ${.TARGETS}:
+ @gmake $@
diff --git a/Config.in b/Config.in
new file mode 100644
index 0000000000..74b3696242
--- /dev/null
+++ b/Config.in
@@ -0,0 +1,101 @@
+#
+
+mainmenu "OpenWrt Configuration"
+
+config HAVE_DOT_CONFIG
+ bool
+ default y
+
+source "target/Config.in"
+
+config ALL
+ bool "Select all packages by default"
+ default n
+
+menuconfig DEVEL
+ bool "Advanced configuration options (for developers)"
+ default n
+ select BUILDOPTS
+ select TOOLCHAINOPTS if !NATIVE_TOOLCHAIN
+
+config BROKEN
+ bool "Show broken platforms / packages" if DEVEL
+ default n
+
+menuconfig BUILDOPTS
+ bool "Build Options" if DEVEL
+
+config AUTOREBUILD
+ bool
+ prompt "Automatic rebuild of packages" if BUILDOPTS
+ default y
+ help
+ Automatically rebuild packages when their files change
+
+config TAR_VERBOSITY
+ bool
+ prompt "Tar verbose" if BUILDOPTS
+ default n
+
+config JLEVEL
+ int
+ prompt "Number of jobs to run simultaneously" if BUILDOPTS
+ default "1"
+ help
+ Number of jobs to run simultanesouly
+
+config CCACHE
+ bool
+ prompt "Use ccache" if BUILDOPTS
+ default n
+ help
+ Compiler cache; see http://ccache.samba.org/
+
+source "toolchain/Config.in"
+source "target/sdk/Config.in"
+
+menu "Target Images"
+ config TARGET_ROOTFS_INITRAMFS
+ bool "ramdisk"
+ default n
+ depends LINUX_2_6
+ help
+ Embed the rootfs into the kernel (initramfs)
+
+ config TARGET_ROOTFS_JFFS2
+ bool "jffs2"
+ default y if USES_JFFS2
+ depends !TARGET_ROOTFS_INITRAMFS
+ help
+ Build a jffs2 root filesystem
+
+ config TARGET_ROOTFS_SQUASHFS
+ bool "squashfs"
+ default y if USES_SQUASHFS
+ depends !TARGET_ROOTFS_INITRAMFS
+ help
+ Build a squashfs-lzma root filesystem
+
+ config TARGET_ROOTFS_TGZ
+ bool "tgz"
+ default y if !USES_SQUASHFS && !USES_JFFS2
+ depends !TARGET_ROOTFS_INITRAMFS
+ help
+ Build a compressed tar archive of the the root filesystem
+
+ config TARGET_ROOTFS_EXT2FS
+ bool "ext2"
+ default y if !USES_SQUASHFS && !USES_JFFS2
+ depends !TARGET_ROOTFS_INITRAMFS
+ help
+ Ext2 file system with some free space for uml images
+
+comment "Image Options"
+
+source "target/image/*/Config.in"
+
+endmenu
+
+source "target/linux/Config.in"
+source ".config.in"
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000000..d60c31a97a
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library General
+Public License instead of this License.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000..39ffb17fb5
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,141 @@
+# Makefile for OpenWrt
+#
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2006 by Felix Fietkau <openwrt@nbd.name>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+RELEASE:=Kamikaze
+#VERSION:=2.0 # uncomment for final release
+
+#--------------------------------------------------------------
+# Just run 'make menuconfig', configure stuff, then run 'make'.
+# You shouldn't need to mess with anything beyond this point...
+#--------------------------------------------------------------
+
+all: world
+
+SHELL:=/usr/bin/env bash
+export TOPDIR=${shell pwd}
+include $(TOPDIR)/include/verbose.mk
+
+OPENWRTVERSION:=$(RELEASE)
+ifneq ($(VERSION),)
+ OPENWRTVERSION:=$(VERSION) ($(OPENWRTVERSION))
+else
+ REV:=$(shell LANG=C svn info | awk '/^Revision:/ { print$$2 }' )
+ ifneq ($(REV),)
+ OPENWRTVERSION:=$(OPENWRTVERSION)/r$(REV)
+ endif
+endif
+export OPENWRTVERSION
+
+ifneq ($(shell ./scripts/timestamp.pl -p .pkginfo package Makefile),.pkginfo)
+ .pkginfo .config: FORCE
+endif
+
+ifeq ($(FORCE),)
+ .config scripts/config/conf scripts/config/mconf: .prereq-build
+ world: .prereq-packages
+endif
+
+.pkginfo:
+ @echo Collecting package info...
+ @-for dir in package/*/; do \
+ echo Source-Makefile: $${dir}Makefile; \
+ $(NO_TRACE_MAKE) --no-print-dir DUMP=1 -C $$dir || echo "ERROR: please fix $${dir}Makefile" >&2; \
+ done > $@
+
+pkginfo-clean: FORCE
+ -rm -f .pkginfo .config.in
+
+.config.in: .pkginfo
+ @./scripts/gen_menuconfig.pl < $< > $@ || rm -f $@
+
+.config: ./scripts/config/conf .config.in
+ @[ -f .config ] || $(NO_TRACE_MAKE) menuconfig
+ @$< -D .config Config.in &> /dev/null
+
+scripts/config/mconf:
+ @$(MAKE) -C scripts/config all
+
+scripts/config/conf:
+ @$(MAKE) -C scripts/config conf
+
+config: scripts/config/conf .config.in FORCE
+ $< Config.in
+
+config-clean: FORCE
+ $(NO_TRACE_MAKE) -C scripts/config clean
+
+defconfig: scripts/config/conf .config.in FORCE
+ touch .config
+ $< -D .config Config.in
+
+oldconfig: scripts/config/conf .config.in FORCE
+ $< -o Config.in
+
+menuconfig: scripts/config/mconf .config.in FORCE
+ $< Config.in
+
+package/%: .pkginfo FORCE
+ $(MAKE) -C package $(patsubst package/%,%,$@)
+
+target/%: .pkginfo FORCE
+ $(MAKE) -C target $(patsubst target/%,%,$@)
+
+tools/%: FORCE
+ $(MAKE) -C tools $(patsubst tools/%,%,$@)
+
+toolchain/%: FORCE
+ $(MAKE) -C toolchain $(patsubst toolchain/%,%,$@)
+
+.prereq-build: include/prereq-build.mk
+ @$(NO_TRACE_MAKE) -s -f $(TOPDIR)/include/prereq-build.mk prereq 2>/dev/null || { \
+ echo "Prerequisite check failed. Use FORCE=1 to override."; \
+ rm -rf $(TOPDIR)/tmp; \
+ false; \
+ }
+ @rm -rf $(TOPDIR)/tmp
+ @touch $@
+
+.prereq-packages: include/prereq.mk .pkginfo .config
+ @$(NO_TRACE_MAKE) -s -C package prereq 2>/dev/null || { \
+ echo "Prerequisite check failed. Use FORCE=1 to override."; \
+ false; \
+ }
+ @rm -rf "$(TOPDIR)/tmp"
+ @touch $@
+
+prereq: .prereq-build .prereq-packages FORCE
+
+download: .config FORCE
+ $(MAKE) tools/download
+ $(MAKE) toolchain/download
+ $(MAKE) package/download
+ $(MAKE) target/download
+
+world: .config FORCE
+ $(MAKE) tools/install
+ $(MAKE) toolchain/install
+ $(MAKE) target/compile
+ $(MAKE) package/compile
+ $(MAKE) package/install
+ $(MAKE) target/install
+ $(MAKE) package/index
+
+clean: FORCE
+ rm -rf build_* bin
+
+dirclean: clean
+ rm -rf staging_dir_* toolchain_build_* tool_build
+
+distclean: dirclean config-clean
+ rm -rf dl .*config* .pkg* .prereq
+
+.SILENT: clean dirclean distclean config-clean download world
+FORCE: ;
+.PHONY: FORCE
+%: ;
diff --git a/README b/README
new file mode 100644
index 0000000000..2bba6fa6f6
--- /dev/null
+++ b/README
@@ -0,0 +1,24 @@
+This is the buildsystem for the OpenWrt Linux distribution
+
+Please use "make menuconfig" to configure your appreciated
+configuration for the toolchain and firmware.
+
+You need to have installed gcc, binutils, patch, bzip2, flex, bison,
+make, gettext, pkg-config, unzip, libz-dev and libc headers.
+
+Simply running 'make' will build your firmware.
+It will download all sources, build the cross-compile toolchain,
+the kernel and all choosen applications.
+
+You can use scripts/flash.sh for remotely updating your embedded system
+via tftp.
+
+The buildroot system is documented in docs/buildroot-documentation.html.
+
+Building your own firmware you need to have access to a Linux system.
+
+Sunshine!
+ Your OpenWrt Project
+ http://openwrt.org
+
+
diff --git a/docs/config.txt b/docs/config.txt
new file mode 100644
index 0000000000..59881580b4
--- /dev/null
+++ b/docs/config.txt
@@ -0,0 +1,72 @@
+ == Structure of the configuration files ==
+
+The config files are divided into sections and options/values.
+
+Every section has a type, but does not necessarily have a name.
+Every option has a name and a value and is assigned to the section
+it was written under.
+
+Syntax:
+
+config <type> [<name>] # Section
+ option <name> <value> # Option
+
+
+Every parameter needs to be a single string and is formatted exactly
+like a parameter for a shell function. The same rules for Quoting and
+special characters also apply, as it is parsed by the shell.
+
+
+
+ == Parsing configuration files in custom scripts ==
+
+To be able to load configuration files, you need to include the common
+functions with:
+
+. /etc/functions.sh
+
+Then you can use config_load <name> to load config files. The function
+first checks for <name> as absolute filename and falls back to loading
+it from /etc/config (which is the most common way of using it).
+
+If you want to use special callbacks for sections and/or options, you
+need to define the following shell functions before running config_load
+(after including /etc/functions.sh):
+
+config_cb() {
+ local type="$1"
+ local name="$2"
+ # commands to be run for every section
+}
+
+option_cb() {
+ # commands to be run for every option
+}
+
+You can also alter option_cb from config_cb based on the section type.
+This allows you to process every single config section based on its type
+individually.
+
+config_cb is run every time a new section starts (before options are being
+processed). You can access the last section through the CONFIG_SECTION
+variable. Also an extra call to config_cb (without a new section) is generated
+after config_load is done.
+That allows you to process sections both before and after all options were
+processed.
+
+You can access already processed options with the config_get command
+Syntax:
+
+config_get <section> <option> # prints the value of the option
+config_get <variable> <section> <option> # stores the value inside the variable
+
+In busybox ash the three-option config_get is faster, because it does not
+result in an extra fork, so it is the preferred way.
+
+Additionally you can also modify or add options to sections by using the
+config_set command.
+
+Syntax:
+
+config_set <section> <option> <value>
+
diff --git a/docs/network-scripts.txt b/docs/network-scripts.txt
new file mode 100644
index 0000000000..024161bdeb
--- /dev/null
+++ b/docs/network-scripts.txt
@@ -0,0 +1,52 @@
+ Structure of the network scripts in buildroot-ng
+
+
+1) Usage
+
+To be able to access the network functions, you need to include
+the necessary shell scripts by running:
+
+. /etc/functions.sh # common functions
+include /lib/network # include /lib/network/*.sh
+scan_interfaces # read and parse the network config
+
+Some protocols, such as PPP might change the configured interface names
+at run time (e.g. eth0 => ppp0 for PPPoE). That's why you have to run
+scan_interfaces instead of reading the values from the config directly.
+After running scan_interfaces, the 'ifname' option will always contain
+the effective interface name (which is used for IP traffic) and if the
+physical device name differs from it, it will be stored in the 'device'
+option.
+That means that running 'config_get lan ifname' after scan_interfaces
+might not return the same result as running it before.
+
+After running scan_interfaces, the following functions are available:
+
+- find_config <interface> looks for a network configuration that includes
+ the specified network interface.
+
+- setup_interface <interface> [<config>] [<protocol>] will set up the
+ specified interface, optionally overriding the network configuration
+ name or the protocol that it uses.
+
+
+
+2) Writing protocol handlers
+
+You can add custom protocol handlers by adding shell scripts to
+/lib/network. They provide the following two shell functions:
+
+scan_<protocolname>() {
+ local config="$1"
+ # change the interface names if necessary
+}
+
+setup_interface_<protocolname>() {
+ local interface="$1"
+ local config="$2"
+ # set up the interface
+}
+
+scan_<protocolname> is optional and only necessary if your protocol
+uses a custom device, e.g. a tunnel or a PPP device.
+
diff --git a/docs/network.txt b/docs/network.txt
new file mode 100644
index 0000000000..69dbaa60ba
--- /dev/null
+++ b/docs/network.txt
@@ -0,0 +1,79 @@
+ Network configuration in buildroot-ng
+
+
+The network configuration in buildroot-ng is stored in /etc/config/network
+and is divided into interface configurations.
+Each interface configuration either refers directly to an ethernet/wifi
+interface (eth0, wl0, ..) or to a bridge containing multiple interfaces.
+It looks like this:
+
+ config interface "lan"
+ option ifname "eth0"
+ option proto "static"
+ option ipaddr "192.168.1.1"
+ option netmask "255.255.255.0"
+ option gateway "192.168.1.254"
+ option dns "192.168.1.254"
+
+"ifname" specifies the Linux interface name.
+If you want to use bridging on one or more interfaces, set "ifname" to a list
+of interfaces and add:
+ option type "bridge"
+
+It is possible to use VLAN tagging on an interface simply by adding the VLAN IDs
+to it, e.g. "eth0.1". These can be nested as well.
+
+This sets up a simple static configuration for eth0. "proto" specifies the
+'protocol' used for the interface. The default image usually provides 'none'
+'static', 'dhcp' and 'pppoe'. Others can be added by installing additional
+packages.
+
+When using the 'static' method like in the example, the options "ipaddr" and
+"netmask" are mandatory, while "gateway" and "dns" are optional.
+DHCP currently only accepts "ipaddr" (IP address to request from the server)
+and "hostname" (client hostname identify as) - both are optional.
+
+PPP based protocols (pppoe, pptp, ...) accept these options:
+ username:
+ The PPP username (usually with PAP authentication)
+ password:
+ The PPP password
+ keepalive:
+ Ping the PPP server (using LCP). The value of this option
+ specifies the maximum number of failed pings before reconnecting.
+ The ping interval defaults to 5, but can be changed by appending
+ ",<interval>" to the keepalive value
+ demand:
+ Use Dial on Demand (value specifies the maximum idle time)
+
+ (pptp)
+ server: The remote pptp server IP
+
+For all protocol types, you can also specify the MTU by using the "mtu" option.
+
+
+
+
+ Setting up the switch (currently broadcom only)
+
+
+The switch configuration is set by adding a 'switch' config section.
+Example:
+
+ config switch eth0
+ option vlan0 "1 2 3 4 5*"
+ option vlan1 "0 5"
+
+On Broadcom hardware the section name needs to be eth0, as the switch driver
+does not detect the switch on any other physical device.
+Every vlan option needs to have the name vlan<n> where <n> is the VLAN number
+as used in the switch driver.
+As value it takes a list of ports with these optional suffixes:
+
+ '*': Set the default VLAN (PVID) of the Port to the current VLAN
+ 'u': Force the port to be untagged
+ 't': Force the port to be tagged
+
+The CPU port defaults to tagged, all other ports to untagged.
+On Broadcom hardware the CPU port is always 5. The other ports may vary with
+different hardware.
diff --git a/include/host-build.mk b/include/host-build.mk
new file mode 100644
index 0000000000..a1287da475
--- /dev/null
+++ b/include/host-build.mk
@@ -0,0 +1,123 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(INCLUDE_DIR)/host.mk
+
+ifneq ($(strip $(PKG_CAT)),)
+ ifeq ($(PKG_CAT),unzip)
+ UNPACK=unzip -d $(PKG_BUILD_DIR) $(DL_DIR)/$(PKG_SOURCE)
+ else
+ UNPACK=$(PKG_CAT) $(DL_DIR)/$(PKG_SOURCE) | tar -C $(PKG_BUILD_DIR)/.. $(TAR_OPTIONS) -
+ endif
+ define Build/Prepare/Default
+ $(UNPACK)
+ @if [ -d ./patches ]; then \
+ $(PATCH) $(PKG_BUILD_DIR) ./patches; \
+ fi
+ endef
+endif
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+endef
+
+define Build/Configure/Default
+ @(cd $(PKG_BUILD_DIR)/$(3); \
+ [ -x configure ] && \
+ $(2) \
+ CPPFLAGS="-I$(STAGING_DIR)/host/include" \
+ LDFLAGS="-L$(STAGING_DIR)/host/lib" \
+ ./configure \
+ --target=$(GNU_TARGET_NAME) \
+ --host=$(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 \
+ --datadir=/usr/share \
+ --localstatedir=/var \
+ --mandir=/usr/man \
+ --infodir=/usr/info \
+ $(DISABLE_NLS) \
+ $(1); \
+ true; \
+ )
+endef
+
+define Build/Configure
+ $(call Build/Configure/Default)
+endef
+
+define Build/Compile/Default
+ $(MAKE) -C $(PKG_BUILD_DIR) $(1)
+endef
+
+define Build/Compile
+ $(call Build/Compile/Default)
+endef
+
+
+ifneq ($(strip $(PKG_SOURCE)),)
+ download: $(DL_DIR)/$(PKG_SOURCE)
+
+ $(DL_DIR)/$(PKG_SOURCE):
+ mkdir -p $(DL_DIR)
+ $(SCRIPT_DIR)/download.pl "$(DL_DIR)" "$(PKG_SOURCE)" "$(PKG_MD5SUM)" $(PKG_SOURCE_URL)
+
+ $(PKG_BUILD_DIR)/.prepared: $(DL_DIR)/$(PKG_SOURCE)
+endif
+
+define HostBuild
+ $(PKG_BUILD_DIR)/.prepared:
+ @-rm -rf $(PKG_BUILD_DIR)
+ @mkdir -p $(PKG_BUILD_DIR)
+ $(call Build/Prepare)
+ touch $$@
+
+ $(PKG_BUILD_DIR)/.configured: $(PKG_BUILD_DIR)/.prepared
+ $(call Build/Configure)
+ touch $$@
+
+ $(PKG_BUILD_DIR)/.built: $(PKG_BUILD_DIR)/.configured
+ $(call Build/Compile)
+ touch $$@
+
+ $(STAGING_DIR)/stampfiles/.host_$(PKG_NAME)-installed: $(PKG_BUILD_DIR)/.built
+ $(call Build/Install)
+ touch $$@
+
+ ifdef Build/Install
+ install-targets: $(STAGING_DIR)/stampfiles/.host_$(PKG_NAME)-installed
+ endif
+
+ package-clean: FORCE
+ $(call Build/Clean)
+ $(call Build/Uninstall)
+ rm -f $(STAGING_DIR)/stampfiles/.host_$(PKG_NAME)-installed
+
+ download:
+ prepare: $(PKG_BUILD_DIR)/.prepared
+ configure: $(PKG_BUILD_DIR)/.configured
+
+ compile-targets: $(PKG_BUILD_DIR)/.built
+ compile: compile-targets
+
+ install-targets:
+ install: install-targets
+
+ clean-targets:
+ clean: FORCE
+ @$(MAKE) clean-targets
+ $(call Build/Clean)
+ rm -rf $(PKG_BUILD_DIR)
+
+endef
diff --git a/include/host.mk b/include/host.mk
new file mode 100644
index 0000000000..3a5fd9683e
--- /dev/null
+++ b/include/host.mk
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/.host.mk
+
+export TAR
+
+$(TOPDIR)/.host.mk: $(INCLUDE_DIR)/host.mk
+ @( \
+ HOST_OS=`uname`; \
+ case "$$HOST_OS" in \
+ Linux) HOST_ARCH=`uname -m`;; \
+ *) HOST_ARCH=`uname -p`;; \
+ esac; \
+ GNU_HOST_NAME=`gcc -dumpmachine`; \
+ [ -n "$$GNU_HOST_NAME" ] || \
+ GNU_HOST_NAME=`$(SCRIPT_DIR)/config.guess`; \
+ echo "HOST_OS:=$$HOST_OS" > $@; \
+ echo "HOST_ARCH:=$$HOST_ARCH" >> $@; \
+ echo "GNU_HOST_NAME:=$$GNU_HOST_NAME" >> $@; \
+ if tar --version 2>&1 | grep 'GNU' >/dev/null; then \
+ echo "TAR_WILDCARDS:=--wildcards" >> $@; \
+ fi; \
+ TAR=`which gtar tar | head -n 1`; \
+ echo "TAR:=$$TAR" >> $@; \
+ )
+
diff --git a/include/image.mk b/include/image.mk
new file mode 100644
index 0000000000..0651679180
--- /dev/null
+++ b/include/image.mk
@@ -0,0 +1,96 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+KDIR:=$(BUILD_DIR)/linux-$(KERNEL)-$(BOARD)
+
+ifneq ($(CONFIG_BIG_ENDIAN),y)
+JFFS2OPTS := --pad --little-endian --squash
+SQUASHFS_OPTS := -le
+else
+JFFS2OPTS := --pad --big-endian --squash
+SQUASHFS_OPTS := -be
+endif
+
+ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),y)
+ ifeq ($(CONFIG_TARGET_ROOTFS_JFFS2),y)
+ define Image/mkfs/jffs2
+ rm -rf $(BUILD_DIR)/root/jffs
+
+ $(STAGING_DIR)/bin/mkfs.jffs2 $(JFFS2OPTS) -e 0x10000 -o $(KDIR)/root.jffs2-64k -d $(BUILD_DIR)/root
+ $(STAGING_DIR)/bin/mkfs.jffs2 $(JFFS2OPTS) -e 0x20000 -o $(KDIR)/root.jffs2-128k -d $(BUILD_DIR)/root
+
+ # add End-of-Filesystem markers
+ echo -ne '\xde\xad\xc0\xde' >> $(KDIR)/root.jffs2-64k
+ echo -ne '\xde\xad\xc0\xde' >> $(KDIR)/root.jffs2-128k
+
+ $(call Image/Build,jffs2-64k)
+ $(call Image/Build,jffs2-128k)
+ endef
+ endif
+
+ ifeq ($(CONFIG_TARGET_ROOTFS_SQUASHFS),y)
+ define Image/mkfs/squashfs
+ @mkdir -p $(BUILD_DIR)/root/jffs
+ $(STAGING_DIR)/bin/mksquashfs-lzma $(BUILD_DIR)/root $(KDIR)/root.squashfs -nopad -noappend -root-owned $(SQUASHFS_OPTS)
+ $(call Image/Build,squashfs)
+ endef
+ endif
+
+ ifeq ($(CONFIG_TARGET_ROOTFS_TGZ),y)
+ define Image/mkfs/tgz
+ tar -zcf $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-rootfs.tgz --owner=root --group=root -C $(BUILD_DIR)/root/ .
+ endef
+ endif
+
+
+endif
+
+ifeq ($(CONFIG_TARGET_ROOTFS_EXT2FS),y)
+ define Image/mkfs/ext2
+ $(STAGING_DIR)/bin/genext2fs -q -b 8192 -I 1500 -d $(BUILD_DIR)/root/ $(KDIR)/root.ext2
+ $(call Image/Build,ext2)
+ endef
+endif
+
+
+define Image/mkfs/prepare/default
+ find $(BUILD_DIR)/root -type f -not -perm +0100 | xargs chmod 0644
+ find $(BUILD_DIR)/root -type f -perm +0100 | xargs chmod 0755
+ find $(BUILD_DIR)/root -type d | xargs chmod 0755
+ mkdir -p $(BUILD_DIR)/root/tmp
+ chmod 0777 $(BUILD_DIR)/root/tmp
+endef
+
+define Image/mkfs/prepare
+ $(call Image/mkfs/prepare/default)
+endef
+
+define BuildImage
+compile:
+ $(call Build/Compile)
+
+install:
+ $(call Image/Prepare)
+ $(call Image/mkfs/prepare)
+ $(call Image/BuildKernel)
+ $(call Image/mkfs/jffs2)
+ $(call Image/mkfs/squashfs)
+ $(call Image/mkfs/tgz)
+ $(call Image/mkfs/ext2)
+
+clean:
+ $(call Build/Clean)
+endef
+
+compile-targets:
+install-targets:
+clean-targets:
+
+download:
+prepare:
+compile: compile-targets
+install: compile install-targets
+clean: clean-targets
diff --git a/include/kernel-build.mk b/include/kernel-build.mk
new file mode 100644
index 0000000000..5544a82e37
--- /dev/null
+++ b/include/kernel-build.mk
@@ -0,0 +1,145 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(INCLUDE_DIR)/host.mk
+-include $(INCLUDE_DIR)/modules-$(KERNEL).mk
+
+LINUX_SOURCE:=linux-$(LINUX_VERSION).tar.bz2
+LINUX_SITE=http://www.us.kernel.org/pub/linux/kernel/v$(KERNEL) \
+ http://www.us.kernel.org/pub/linux/kernel/v$(KERNEL) \
+ http://www.kernel.org/pub/linux/kernel/v$(KERNEL) \
+ http://www.de.kernel.org/pub/linux/kernel/v$(KERNEL)
+
+KERNEL_IDIR:=$(KERNEL_BUILD_DIR)/kernel-ipkg
+KERNEL_IPKG:=$(KERNEL_BUILD_DIR)/kernel_$(LINUX_VERSION)-$(BOARD)-$(LINUX_RELEASE)_$(ARCH).ipk
+TARGETS += $(KERNEL_IPKG)
+INSTALL_TARGETS += $(KERNEL_IPKG)
+
+LINUX_KARCH:=$(shell echo $(ARCH) | sed -e 's/i[3-9]86/i386/' \
+ -e 's/mipsel/mips/' \
+ -e 's/mipseb/mips/' \
+ -e 's/powerpc/ppc/' \
+ -e 's/sh[234]/sh/' \
+ -e 's/armeb/arm/' \
+)
+
+
+$(TARGETS): $(PACKAGE_DIR)
+
+$(PACKAGE_DIR):
+ mkdir -p $@
+
+$(DL_DIR)/$(LINUX_SOURCE):
+ -mkdir -p $(DL_DIR)
+ $(SCRIPT_DIR)/download.pl $(DL_DIR) $(LINUX_SOURCE) $(LINUX_KERNEL_MD5SUM) $(LINUX_SITE)
+
+$(LINUX_DIR)/.unpacked: $(DL_DIR)/$(LINUX_SOURCE)
+ -mkdir -p $(KERNEL_BUILD_DIR)
+ bzcat $(DL_DIR)/$(LINUX_SOURCE) | tar -C $(KERNEL_BUILD_DIR) $(TAR_OPTIONS) -
+ touch $@
+
+ifeq ($(KERNEL),2.4)
+$(LINUX_DIR)/.configured: $(LINUX_DIR)/.patched
+ $(SED) "s,\-mcpu=,\-mtune=,g;" $(LINUX_DIR)/arch/mips/Makefile
+ $(MAKE) -C $(LINUX_DIR) CROSS_COMPILE="$(KERNEL_CROSS)" CC="$(KERNEL_CC)" ARCH=$(LINUX_KARCH) oldconfig include/linux/compile.h include/linux/version.h
+ touch $@
+
+$(LINUX_DIR)/.depend_done: $(LINUX_DIR)/.configured
+ $(MAKE) -C $(LINUX_DIR) CROSS_COMPILE="$(KERNEL_CROSS)" ARCH=$(LINUX_KARCH) dep
+ touch $@
+
+$(LINUX_DIR)/vmlinux: $(LINUX_DIR)/.depend_done
+else
+$(LINUX_DIR)/.configured: $(LINUX_DIR)/.patched
+ $(MAKE) -C $(LINUX_DIR) CROSS_COMPILE="$(KERNEL_CROSS)" CC="$(KERNEL_CC)" ARCH=$(LINUX_KARCH) oldconfig prepare scripts
+ touch $@
+endif
+
+ramdisk-config: $(LINUX_DIR)/.configured FORCE
+ mv $(LINUX_DIR)/.config $(LINUX_DIR)/.config.old
+ grep -v INITRAMFS $(LINUX_DIR)/.config.old > $(LINUX_DIR)/.config
+ifeq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),y)
+ echo 'CONFIG_INITRAMFS_SOURCE="../../root"' >> $(LINUX_DIR)/.config
+ echo 'CONFIG_INITRAMFS_ROOT_UID=0' >> $(LINUX_DIR)/.config
+ echo 'CONFIG_INITRAMFS_ROOT_GID=0' >> $(LINUX_DIR)/.config
+ mkdir -p $(BUILD_DIR)/root/etc/init.d
+ $(CP) ../generic-2.6/files/init $(BUILD_DIR)/root/
+else
+ rm -f $(BUILD_DIR)/root/init $(BUILD_DIR)/root/etc/init.d/S00initramfs
+ echo 'CONFIG_INITRAMFS_SOURCE=""' >> $(LINUX_DIR)/.config
+endif
+
+$(LINUX_DIR)/vmlinux: $(LINUX_DIR)/.linux-compile pkg-install ramdisk-config
+ $(MAKE) -C $(LINUX_DIR) CROSS_COMPILE="$(KERNEL_CROSS)" CC="$(KERNEL_CC)" ARCH=$(LINUX_KARCH) $(KERNELNAME)
+
+$(LINUX_KERNEL): $(LINUX_DIR)/vmlinux
+ $(KERNEL_CROSS)objcopy -O binary -R .reginfo -R .note -R .comment -R .mdebug -S $< $@
+ touch -c $(LINUX_KERNEL)
+
+$(LINUX_DIR)/.modules_done:
+ rm -rf $(KERNEL_BUILD_DIR)/modules
+ $(MAKE) -C "$(LINUX_DIR)" CROSS_COMPILE="$(KERNEL_CROSS)" CC="$(KERNEL_CC)" ARCH=$(LINUX_KARCH) modules
+ $(MAKE) -C "$(LINUX_DIR)" CROSS_COMPILE="$(KERNEL_CROSS)" CC="$(KERNEL_CC)" ARCH=$(LINUX_KARCH) DEPMOD=true INSTALL_MOD_PATH=$(KERNEL_BUILD_DIR)/modules modules_install
+ touch $(LINUX_DIR)/.modules_done
+
+modules: $(LINUX_DIR)/.modules_done
+packages: $(TARGETS)
+
+$(LINUX_DIR)/.linux-compile:
+ @rm -f $(BUILD_DIR)/linux
+ ln -sf $(KERNEL_BUILD_DIR)/linux-$(LINUX_VERSION) $(BUILD_DIR)/linux
+ @$(MAKE) modules
+ touch $@
+
+$(KERNEL_IPKG):
+ rm -rf $(KERNEL_IDIR)
+ mkdir -p $(KERNEL_IDIR)/etc
+ $(SCRIPT_DIR)/make-ipkg-dir.sh $(KERNEL_IDIR) ../control/kernel.control $(LINUX_VERSION)-$(BOARD)-$(LINUX_RELEASE) $(ARCH)
+ if [ -f ./config/$(BOARD).modules ]; then \
+ cp ./config/$(BOARD).modules $(KERNEL_IDIR)/etc/modules; \
+ fi
+ $(IPKG_BUILD) $(KERNEL_IDIR) $(KERNEL_BUILD_DIR)
+
+$(TOPDIR)/.kernel.mk: $(TOPDIR)/target/linux/$(BOARD)-$(KERNEL)/Makefile
+ echo "CONFIG_BOARD:=$(BOARD)" > $@
+ echo "CONFIG_KERNEL:=$(KERNEL)" >> $@
+ echo "CONFIG_LINUX_VERSION:=$(LINUX_VERSION)" >> $@
+ echo "CONFIG_LINUX_RELEASE:=$(LINUX_RELEASE)" >> $@
+ echo "CONFIG_LINUX_KARCH:=$(LINUX_KARCH)" >> $@
+
+pkg-install: FORCE
+ @for pkg in $(INSTALL_TARGETS); do \
+ $(IPKG) install $$pkg || echo; \
+ done
+
+download: $(DL_DIR)/$(LINUX_SOURCE)
+prepare: $(LINUX_DIR)/.configured
+ @mkdir -p $(LINUX_DIR) $(PACKAGE_DIR)
+
+compile: prepare $(LINUX_DIR)/.linux-compile
+ @$(MAKE) packages
+
+install: compile $(LINUX_KERNEL)
+
+mostlyclean: FORCE
+ rm -f $(LINUX_DIR)/.linux-compile
+ rm -f $(KERNEL_BUILD_DIR)/linux-$(LINUX_VERSION)/.modules_done
+ rm -f $(KERNEL_BUILD_DIR)/linux-$(LINUX_VERSION)/.drivers-unpacked
+ $(MAKE) -C $(KERNEL_BUILD_DIR)/linux-$(LINUX_VERSION) clean
+ rm -f $(LINUX_KERNEL)
+
+rebuild: FORCE
+ -$(MAKE) mostlyclean
+ if [ -f $(LINUX_KERNEL) ]; then \
+ $(MAKE) clean; \
+ fi
+ $(MAKE) compile $(MAKE_TRACE)
+
+clean: FORCE
+ rm -f $(STAMP_DIR)/.linux-compile
+ rm -rf $(KERNEL_BUILD_DIR)
+ rm -f $(TARGETS)
+
diff --git a/include/kernel.mk b/include/kernel.mk
new file mode 100644
index 0000000000..580e3951d1
--- /dev/null
+++ b/include/kernel.mk
@@ -0,0 +1,106 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+ifeq ($(DUMP),1)
+ KERNEL:=<KERNEL>
+ BOARD:=<BOARD>
+ LINUX_VERSION:=<LINUX_VERSION>
+else
+
+ include $(TOPDIR)/.kernel.mk
+ include $(INCLUDE_DIR)/target.mk
+
+ # check to see if .kernel.mk matches target.mk
+ ifeq ($(CONFIG_BOARD)-$(CONFIG_KERNEL),$(BOARD)-$(KERNEL))
+ LINUX_VERSION:=$(CONFIG_LINUX_VERSION)
+ LINUX_RELEASE:=$(CONFIG_LINUX_RELEASE)
+ LINUX_KARCH:=$(CONFIG_LINUX_KARCH)
+ else
+ # oops, old .kernel.config; rebuild it (hiding the misleading errors this produces)
+ $(warning rebuilding .kernel.mk)
+ $(TOPDIR)/.kernel.mk: FORCE
+ @$(MAKE) -C $(TOPDIR)/target/linux/$(BOARD)-$(KERNEL) $@ &>/dev/null
+ endif
+
+ ifeq ($(KERNEL),2.6)
+ LINUX_KMOD_SUFFIX=ko
+ else
+ LINUX_KMOD_SUFFIX=o
+ endif
+
+ KERNELNAME=
+ ifneq (,$(findstring x86,$(BOARD)))
+ KERNELNAME="bzImage"
+ endif
+ ifneq (,$(findstring ppc,$(BOARD)))
+ KERNELNAME="uImage"
+ endif
+
+ ifneq (,$(findstring uml,$(BOARD)))
+ LINUX_KARCH:=um
+ KERNEL_CC:=$(HOSTCC)
+ KERNEL_CROSS:=
+ else
+ KERNEL_CC:=$(TARGET_CC)
+ KERNEL_CROSS:=$(TARGET_CROSS)
+ endif
+
+ KERNEL_BUILD_DIR:=$(BUILD_DIR)/linux-$(KERNEL)-$(BOARD)
+ LINUX_DIR := $(KERNEL_BUILD_DIR)/linux-$(LINUX_VERSION)
+
+ MODULES_SUBDIR:=lib/modules/$(LINUX_VERSION)
+ MODULES_DIR := $(KERNEL_BUILD_DIR)/modules/$(MODULES_SUBDIR)
+ TARGET_MODULES_DIR := $(LINUX_TARGET_DIR)/$(MODULES_SUBDIR)
+ KMOD_BUILD_DIR := $(KERNEL_BUILD_DIR)/linux-modules
+
+ LINUX_KERNEL:=$(KERNEL_BUILD_DIR)/vmlinux
+endif
+
+# FIXME: remove this crap
+define KMOD_template
+ifeq ($$(strip $(4)),)
+KDEPEND_$(1):=m
+else
+KDEPEND_$(1):=$($(4))
+endif
+
+IDEPEND_$(1):=kernel ($(LINUX_VERSION)-$(BOARD)-$(LINUX_RELEASE)) $(foreach pkg,$(5),", $(pkg)")
+
+PKG_$(1) := $(PACKAGE_DIR)/kmod-$(2)_$(LINUX_VERSION)-$(BOARD)-$(LINUX_RELEASE)_$(ARCH).ipk
+I_$(1) := $(KMOD_BUILD_DIR)/ipkg/$(2)
+
+ifeq ($$(KDEPEND_$(1)),m)
+ifneq ($$(CONFIG_PACKAGE_KMOD_$(1)),)
+TARGETS += $$(PKG_$(1))
+endif
+ifeq ($$(CONFIG_PACKAGE_KMOD_$(1)),y)
+INSTALL_TARGETS += $$(PKG_$(1))
+endif
+endif
+
+$$(PKG_$(1)): $(LINUX_DIR)/.modules_done
+ rm -rf $$(I_$(1))
+ $(SCRIPT_DIR)/make-ipkg-dir.sh $$(I_$(1)) ../control/kmod-$(2).control $(LINUX_VERSION)-$(BOARD)-$(LINUX_RELEASE) $(ARCH)
+ echo "Depends: $$(IDEPEND_$(1))" >> $$(I_$(1))/CONTROL/control
+ifneq ($(strip $(3)),)
+ mkdir -p $$(I_$(1))/lib/modules/$(LINUX_VERSION)
+ $(CP) $(3) $$(I_$(1))/lib/modules/$(LINUX_VERSION)
+endif
+ifneq ($(6),)
+ mkdir -p $$(I_$(1))/etc/modules.d
+ for module in $(7); do \
+ echo $$$$module >> $$(I_$(1))/etc/modules.d/$(6)-$(2); \
+ done
+ echo "#!/bin/sh" >> $$(I_$(1))/CONTROL/postinst
+ echo "[ -z \"\$$$$IPKG_INSTROOT\" ] || exit" >> $$(I_$(1))/CONTROL/postinst
+ echo ". /etc/functions.sh" >> $$(I_$(1))/CONTROL/postinst
+ echo "load_modules /etc/modules.d/$(6)-$(2)" >> $$(I_$(1))/CONTROL/postinst
+ chmod 0755 $$(I_$(1))/CONTROL/postinst
+endif
+ $(8)
+ $(IPKG_BUILD) $$(I_$(1)) $(PACKAGE_DIR)
+endef
+
diff --git a/include/modules-2.4.mk b/include/modules-2.4.mk
new file mode 100644
index 0000000000..e8c67ac105
--- /dev/null
+++ b/include/modules-2.4.mk
@@ -0,0 +1,196 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(INCLUDE_DIR)/netfilter.mk
+
+# Networking
+
+$(eval $(call KMOD_template,ATM,atm,\
+ $(MODULES_DIR)/kernel/net/atm/atm.o \
+ $(MODULES_DIR)/kernel/net/atm/br2684.o \
+,CONFIG_ATM,,50,atm))
+
+# Block devices
+
+$(eval $(call KMOD_template,LOOP,loop,\
+ $(MODULES_DIR)/kernel/drivers/block/loop.o \
+,CONFIG_BLK_DEV_LOOP,,20,loop))
+
+$(eval $(call KMOD_template,NBD,nbd,\
+ $(MODULES_DIR)/kernel/drivers/block/nbd.o \
+,CONFIG_BLK_DEV_NBD,,20,nbd))
+
+
+# Filesystems
+
+$(eval $(call KMOD_template,FS_CIFS,fs-cifs,\
+ $(MODULES_DIR)/kernel/fs/cifs/cifs.o \
+,CONFIG_CIFS,,30,cifs))
+
+$(eval $(call KMOD_template,FS_MINIX,fs-minix,\
+ $(MODULES_DIR)/kernel/fs/minix/*.o \
+,CONFIG_MINIX_FS,,30,minix))
+
+$(eval $(call KMOD_template,FS_EXT2,fs-ext2,\
+ $(MODULES_DIR)/kernel/fs/ext2/*.o \
+,CONFIG_EXT2_FS,,30,ext2))
+
+$(eval $(call KMOD_template,FS_EXT3,fs-ext3,\
+ $(MODULES_DIR)/kernel/fs/ext3/*.o \
+ $(MODULES_DIR)/kernel/fs/jbd/*.o \
+,CONFIG_EXT3_FS,,30,jbd ext3))
+
+$(eval $(call KMOD_template,FS_HFSPLUS,fs-hfsplus,\
+ $(MODULES_DIR)/kernel/fs/hfsplus/*.o \
+,CONFIG_HFSPLUS_FS,,30,hfsplus))
+
+$(eval $(call KMOD_template,FS_NFS,fs-nfs,\
+ $(MODULES_DIR)/kernel/fs/lockd/*.o \
+ $(MODULES_DIR)/kernel/fs/nfs/*.o \
+ $(MODULES_DIR)/kernel/net/sunrpc/*.o \
+,CONFIG_NFS_FS,,30,sunrpc lockd nfs))
+
+$(eval $(call KMOD_template,FS_VFAT,fs-vfat,\
+ $(MODULES_DIR)/kernel/fs/vfat/vfat.o \
+ $(MODULES_DIR)/kernel/fs/fat/fat.o \
+,CONFIG_VFAT_FS,,30,fat vfat))
+
+$(eval $(call KMOD_template,FS_XFS,fs-xfs,\
+ $(MODULES_DIR)/kernel/fs/xfs/*.o \
+,CONFIG_XFS_FS,,30,xfs))
+
+
+# Multimedia
+
+$(eval $(call KMOD_template,PWC,pwc,\
+ $(MODULES_DIR)/kernel/drivers/usb/pwc.o \
+,CONFIG_USB_PWC,kmod-videodev,63,pwc))
+
+$(eval $(call KMOD_template,SOUNDCORE,soundcore,\
+ $(MODULES_DIR)/kernel/drivers/sound/soundcore.o \
+,CONFIG_SOUND,,30,soundcore))
+
+$(eval $(call KMOD_template,VIDEODEV,videodev,\
+ $(MODULES_DIR)/kernel/drivers/media/video/videodev.o \
+,CONFIG_VIDEO_DEV,,62,videodev))
+
+
+# Network devices
+
+$(eval $(call KMOD_template,NET_AIRO,net-airo,\
+ $(MODULES_DIR)/kernel/drivers/net/wireless/airo.o \
+,CONFIG_AIRO,,10,airo))
+
+$(eval $(call KMOD_template,NET_HERMES,net-hermes,\
+ $(MODULES_DIR)/kernel/drivers/net/wireless/hermes.o \
+ $(MODULES_DIR)/kernel/drivers/net/wireless/orinoco.o \
+,CONFIG_HERMES,,10,hermes orinoco))
+
+$(eval $(call KMOD_template,NET_HERMES_PCI,net-hermes-pci,\
+ $(MODULES_DIR)/kernel/drivers/net/wireless/orinoco_pci.o \
+,CONFIG_PCI_HERMES,kmod-net-hermes,11,orinoco_pci))
+
+$(eval $(call KMOD_template,NET_HERMES_PCI,net-hermes-plx,\
+ $(MODULES_DIR)/kernel/drivers/net/wireless/orinoco_plx.o \
+,CONFIG_PLX_HERMES,kmod-net-hermes,11,orinoco_plx))
+
+$(eval $(call KMOD_template,NET_PRISM54,net-prism54,\
+ $(MODULES_DIR)/kernel/drivers/net/wireless/prism54/prism54.o \
+,CONFIG_PRISM54,,10,prism54))
+
+
+# PCMCIA/CardBus
+
+$(eval $(call KMOD_template,PCMCIA_CORE,pcmcia-core,\
+ $(MODULES_DIR)/kernel/drivers/pcmcia/pcmcia_core.o \
+ $(MODULES_DIR)/kernel/drivers/pcmcia/yenta_socket.o \
+ $(MODULES_DIR)/kernel/drivers/pcmcia/ds.o \
+,CONFIG_PCMCIA,,50,pcmcia_core yenta_socket ds))
+
+$(eval $(call KMOD_template,PCMCIA_SERIAL,pcmcia-serial,\
+ $(MODULES_DIR)/kernel/drivers/char/pcmcia/serial_cs.o \
+,CONFIG_PCMCIA_SERIAL_CS,kmod-pcmcia-core,51,serial_cs))
+
+
+# USB
+
+$(eval $(call KMOD_template,USB,usb-core,\
+ $(MODULES_DIR)/kernel/drivers/usb/usbcore.o \
+,CONFIG_USB,,50,usbcore))
+
+$(eval $(call KMOD_template,USB_OHCI,usb-ohci,\
+ $(MODULES_DIR)/kernel/drivers/usb/host/usb-ohci.o \
+,CONFIG_USB_OHCI,kmod-usb-core,60,usb-ohci))
+
+$(eval $(call KMOD_template,USB_UHCI,usb-uhci,\
+ $(MODULES_DIR)/kernel/drivers/usb/host/uhci.o \
+,CONFIG_USB_UHCI_ALT,kmod-usb-core,60,uhci))
+
+$(eval $(call KMOD_template,USB2,usb2,\
+ $(MODULES_DIR)/kernel/drivers/usb/host/ehci-hcd.o \
+,CONFIG_USB_EHCI_HCD,kmod-usb-core,60,ehci-hcd))
+
+$(eval $(call KMOD_template,USB_ACM,usb-acm,\
+ $(MODULES_DIR)/kernel/drivers/usb/acm.o \
+,CONFIG_USB_ACM))
+
+$(eval $(call KMOD_template,USB_AUDIO,usb-audio,\
+ $(MODULES_DIR)/kernel/drivers/usb/audio.o \
+,CONFIG_USB_AUDIO,kmod-soundcore kmod-usb-core,61,audio))
+
+$(eval $(call KMOD_template,USB_PRINTER,usb-printer,\
+ $(MODULES_DIR)/kernel/drivers/usb/printer.o \
+,CONFIG_USB_PRINTER,kmod-usb-core,60,printer))
+
+$(eval $(call KMOD_template,USB_SERIAL,usb-serial,\
+ $(MODULES_DIR)/kernel/drivers/usb/serial/usbserial.o \
+,CONFIG_USB_SERIAL,kmod-usb-core,60,usbserial))
+
+$(eval $(call KMOD_template,USB_SERIAL_BELKIN,usb-serial-belkin,\
+ $(MODULES_DIR)/kernel/drivers/usb/serial/belkin_sa.o \
+,CONFIG_USB_SERIAL_BELKIN,kmod-usb-serial,61,belkin_sa))
+
+$(eval $(call KMOD_template,USB_SERIAL_FTDI,usb-serial-ftdi,\
+ $(MODULES_DIR)/kernel/drivers/usb/serial/ftdi_sio.o \
+,CONFIG_USB_SERIAL_FTDI_SIO,kmod-usb-serial,61,ftdi_sio))
+
+$(eval $(call KMOD_template,USB_SERIAL_MCT_U232,usb-serial-mct-u232,\
+ $(MODULES_DIR)/kernel/drivers/usb/serial/mct_u232.o \
+,CONFIG_USB_SERIAL_MCT_U232,kmod-usb-serial,61,mct_u232))
+
+$(eval $(call KMOD_template,USB_SERIAL_PL2303,usb-serial-pl2303,\
+ $(MODULES_DIR)/kernel/drivers/usb/serial/pl2303.o \
+,CONFIG_USB_SERIAL_PL2303,kmod-usb-serial,61,pl2303))
+
+$(eval $(call KMOD_template,USB_SERIAL_VISOR,usb-serial-visor,\
+ $(MODULES_DIR)/kernel/drivers/usb/serial/visor.o \
+,CONFIG_USB_SERIAL_VISOR,kmod-usb-serial,61,visor))
+
+$(eval $(call KMOD_template,USB_STORAGE,usb-storage,\
+ $(MODULES_DIR)/kernel/drivers/scsi/*.o \
+ $(MODULES_DIR)/kernel/drivers/usb/storage/*.o \
+,CONFIG_USB_STORAGE,kmod-usb-core,60,scsi_mod sd_mod usb-storage))
+
+
+# Misc. devices
+
+$(eval $(call KMOD_template,AX25,ax25,\
+ $(MODULES_DIR)/kernel/net/ax25/ax25.o \
+ $(MODULES_DIR)/kernel/drivers/net/hamradio/mkiss.o \
+,CONFIG_AX25,,90,ax25 mkiss))
+
+$(eval $(call KMOD_template,BLUETOOTH,bluetooth,\
+ $(MODULES_DIR)/kernel/net/bluetooth/*.o \
+ $(MODULES_DIR)/kernel/net/bluetooth/rfcomm/*.o \
+ $(MODULES_DIR)/kernel/drivers/bluetooth/*.o \
+,CONFIG_BLUEZ))
+
+$(eval $(call KMOD_template,SOFTDOG,softdog,\
+ $(MODULES_DIR)/kernel/drivers/char/softdog.o \
+,CONFIG_SOFT_WATCHDOG,,95,softdog))
+
+
+
diff --git a/include/modules-2.6.mk b/include/modules-2.6.mk
new file mode 100644
index 0000000000..9bb08261ea
--- /dev/null
+++ b/include/modules-2.6.mk
@@ -0,0 +1,233 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+NF_2_6:=1
+include $(INCLUDE_DIR)/netfilter.mk
+
+# Networking
+
+$(eval $(call KMOD_template,ATM,atm,\
+ $(MODULES_DIR)/kernel/net/atm/atm.ko \
+ $(MODULES_DIR)/kernel/net/atm/br2684.ko \
+ $(MODULES_DIR)/kernel/drivers/atm/atmtcp.ko \
+,CONFIG_ATM,,50,atm))
+
+# Block devices
+
+$(eval $(call KMOD_template,LOOP,loop,\
+ $(MODULES_DIR)/kernel/drivers/block/loop.ko \
+,CONFIG_BLK_DEV_LOOP,,20,loop))
+
+$(eval $(call KMOD_template,NBD,nbd,\
+ $(MODULES_DIR)/kernel/drivers/block/nbd.ko \
+,CONFIG_BLK_DEV_NBD,,20,nbd))
+
+# Filesystems
+
+$(eval $(call KMOD_template,FS_CIFS,fs-cifs,\
+ $(MODULES_DIR)/kernel/fs/cifs/cifs.ko \
+,CONFIG_CIFS,kmod-nls-base,30,cifs))
+
+$(eval $(call KMOD_template,FS_MINIX,fs-minix,\
+ $(MODULES_DIR)/kernel/fs/minix/minix.ko \
+,CONFIG_MINIX_FS,,30,minix))
+
+$(eval $(call KMOD_template,FS_EXT2,fs-ext2,\
+ $(MODULES_DIR)/kernel/fs/ext2/ext2.ko \
+,CONFIG_EXT2_FS,,30,ext2))
+
+$(eval $(call KMOD_template,FS_EXT3,fs-ext3,\
+ $(MODULES_DIR)/kernel/fs/ext3/ext3.ko \
+ $(MODULES_DIR)/kernel/fs/jbd/jbd.ko \
+,CONFIG_EXT3_FS,,30,jbd ext3))
+
+$(eval $(call KMOD_template,FS_HFSPLUS,fs-hfsplus,\
+ $(MODULES_DIR)/kernel/fs/hfsplus/hfsplus.ko \
+,CONFIG_HFSPLUS_FS,kmod-nls-base,30,hfsplus))
+
+$(eval $(call KMOD_template,FS_NFS,fs-nfs,\
+ $(MODULES_DIR)/kernel/fs/lockd/lockd.ko \
+ $(MODULES_DIR)/kernel/fs/nfs/nfs.ko \
+ $(MODULES_DIR)/kernel/net/sunrpc/sunrpc.ko \
+,CONFIG_NFS_FS,,30,sunrpc lockd nfs))
+
+$(eval $(call KMOD_template,FS_VFAT,fs-vfat,\
+ $(MODULES_DIR)/kernel/fs/fat/fat.ko \
+ $(MODULES_DIR)/kernel/fs/vfat/vfat.ko \
+,CONFIG_VFAT_FS,kmod-nls-base,30,fat vfat))
+
+$(eval $(call KMOD_template,FS_XFS,fs-xfs,\
+ $(MODULES_DIR)/kernel/fs/xfs/xfs.ko \
+,CONFIG_XFS_FS,,30,xfs))
+
+
+# Multimedia
+
+$(eval $(call KMOD_template,PWC,pwc,\
+ $(MODULES_DIR)/kernel/drivers/usb/media/pwc/pwc.ko \
+,CONFIG_USB_PWC,kmod-videodev,63,pwc))
+
+$(eval $(call KMOD_template,SOUNDCORE,soundcore,\
+ $(MODULES_DIR)/kernel/sound/soundcore.ko \
+,CONFIG_SOUND,,30,soundcore))
+
+$(eval $(call KMOD_template,VIDEODEV,videodev,\
+ $(MODULES_DIR)/kernel/drivers/media/video/v4l1-compat.ko \
+ $(MODULES_DIR)/kernel/drivers/media/video/v4l2-common.ko \
+ $(MODULES_DIR)/kernel/drivers/media/video/videodev.ko \
+,CONFIG_VIDEO_DEV,,62,videodev))
+
+
+# NLS
+
+$(eval $(call KMOD_template,NLS_BASE,nls-base,\
+ $(MODULES_DIR)/kernel/fs/nls/nls_base.ko \
+,CONFIG_NLS,,20,nls_base))
+
+$(eval $(call KMOD_template,NLS_CP437,nls-cp437,\
+ $(MODULES_DIR)/kernel/fs/nls/nls_cp437.ko \
+,CONFIG_NLS_CODEPAGE_437,,20,nls_cp437))
+
+$(eval $(call KMOD_template,NLS_CP850,nls-cp850,\
+ $(MODULES_DIR)/kernel/fs/nls/nls_cp850.ko \
+,CONFIG_NLS_CODEPAGE_850,,20,nls_cp850))
+
+$(eval $(call KMOD_template,NLS_ISO8859_1,nls-iso8859-1,\
+ $(MODULES_DIR)/kernel/fs/nls/nls_iso8859-1.ko \
+,CONFIG_NLS_ISO8859_1,,20,nls_iso8859-1))
+
+$(eval $(call KMOD_template,NLS_ISO8859_15,nls-iso8859-15,\
+ $(MODULES_DIR)/kernel/fs/nls/nls_iso8859-15.ko \
+,CONFIG_NLS_ISO8859_15,,20,nls_iso8859-15))
+
+$(eval $(call KMOD_template,NLS_UTF8,nls-utf8,\
+ $(MODULES_DIR)/kernel/fs/nls/nls_utf8.ko \
+,CONFIG_NLS_UTF8,,20,nls_utf8))
+
+
+# Network devices
+
+$(eval $(call KMOD_template,NET_AIRO,net-airo,\
+ $(MODULES_DIR)/kernel/drivers/net/wireless/airo.ko \
+,CONFIG_AIRO,,10,airo))
+
+$(eval $(call KMOD_template,NET_HERMES,net-hermes,\
+ $(MODULES_DIR)/kernel/drivers/net/wireless/hermes.ko \
+ $(MODULES_DIR)/kernel/drivers/net/wireless/orinoco.ko \
+,CONFIG_HERMES,,10,hermes orinoco))
+
+$(eval $(call KMOD_template,NET_HERMES_PCI,net-hermes-pci,\
+ $(MODULES_DIR)/kernel/drivers/net/wireless/orinoco_pci.ko \
+,CONFIG_PCI_HERMES,kmod-net-hermes,11,orinoco_pci))
+
+$(eval $(call KMOD_template,NET_HERMES_PCI,net-hermes-plx,\
+ $(MODULES_DIR)/kernel/drivers/net/wireless/orinoco_plx.ko \
+,CONFIG_PLX_HERMES,kmod-net-hermes,11,orinoco_plx))
+
+$(eval $(call KMOD_template,NET_PRISM54,net-prism54,\
+ $(MODULES_DIR)/kernel/drivers/net/wireless/prism54/prism54.ko \
+,CONFIG_PRISM54,,10,prism54))
+
+
+# PCMCIA/CardBus
+
+$(eval $(call KMOD_template,PCMCIA_CORE,pcmcia-core,\
+ $(MODULES_DIR)/kernel/drivers/pcmcia/pcmcia.ko \
+ $(MODULES_DIR)/kernel/drivers/pcmcia/pcmcia_core.ko \
+ $(MODULES_DIR)/kernel/drivers/pcmcia/yenta_socket.ko \
+ $(MODULES_DIR)/kernel/drivers/pcmcia/rsrc_nonstatic.ko \
+,CONFIG_PCMCIA,,50,pcmcia_core pcmcia yenta_socket rsrc_nonstatic))
+
+$(eval $(call KMOD_template,PCMCIA_SERIAL,pcmcia-serial,\
+ $(MODULES_DIR)/kernel/drivers/serial/serial_cs.ko \
+,CONFIG_SERIAL_8250_CS))
+
+
+# USB
+
+$(eval $(call KMOD_template,USB,usb-core,\
+ $(MODULES_DIR)/kernel/drivers/usb/core/usbcore.ko \
+,CONFIG_USB,,50,usbcore))
+
+$(eval $(call KMOD_template,USB_OHCI,usb-ohci,\
+ $(MODULES_DIR)/kernel/drivers/usb/host/ohci-hcd.ko \
+,CONFIG_USB_OHCI_HCD,kmod-usb-core,60,ohci-hcd))
+
+$(eval $(call KMOD_template,USB_UHCI,usb-uhci,\
+ $(MODULES_DIR)/kernel/drivers/usb/host/uhci-hcd.ko \
+,CONFIG_USB_UHCI_HCD,kmod-usb-core,60,uhci-hcd))
+
+$(eval $(call KMOD_template,USB2,usb2,\
+ $(MODULES_DIR)/kernel/drivers/usb/host/ehci-hcd.ko \
+,CONFIG_USB_EHCI_HCD,kmod-usb-core,60,ehci-hcd))
+
+$(eval $(call KMOD_template,USB_ACM,usb-acm,\
+ $(MODULES_DIR)/kernel/drivers/usb/class/cdc-acm.ko \
+,CONFIG_USB_ACM))
+
+$(eval $(call KMOD_template,USB_AUDIO,usb-audio,\
+ $(MODULES_DIR)/kernel/drivers/usb/class/audio.ko \
+,CONFIG_USB_AUDIO,kmod-soundcore kmod-usb-core,61,audio))
+
+$(eval $(call KMOD_template,USB_PRINTER,usb-printer,\
+ $(MODULES_DIR)/kernel/drivers/usb/class/usblp.ko \
+,CONFIG_USB_PRINTER,kmod-usb-core,60,usblp))
+
+$(eval $(call KMOD_template,USB_SERIAL,usb-serial,\
+ $(MODULES_DIR)/kernel/drivers/usb/serial/usbserial.ko \
+,CONFIG_USB_SERIAL,kmod-usb-core,60,usbserial))
+
+$(eval $(call KMOD_template,USB_SERIAL_BELKIN,usb-serial-belkin,\
+ $(MODULES_DIR)/kernel/drivers/usb/serial/belkin_sa.ko \
+,CONFIG_USB_SERIAL_BELKIN,kmod-usb-serial,61,belkin_sa))
+
+$(eval $(call KMOD_template,USB_SERIAL_FTDI,usb-serial-ftdi,\
+ $(MODULES_DIR)/kernel/drivers/usb/serial/ftdi_sio.ko \
+,CONFIG_USB_SERIAL_FTDI_SIO,kmod-usb-serial,61,ftdi_sio))
+
+$(eval $(call KMOD_template,USB_SERIAL_MCT_U232,usb-serial-mct-u232,\
+ $(MODULES_DIR)/kernel/drivers/usb/serial/mct_u232.ko \
+,CONFIG_USB_SERIAL_MCT_U232,kmod-usb-serial,61,mct_u232))
+
+$(eval $(call KMOD_template,USB_SERIAL_PL2303,usb-serial-pl2303,\
+ $(MODULES_DIR)/kernel/drivers/usb/serial/pl2303.ko \
+,CONFIG_USB_SERIAL_PL2303,kmod-usb-serial,61,pl2303))
+
+$(eval $(call KMOD_template,USB_SERIAL_VISOR,usb-serial-visor,\
+ $(MODULES_DIR)/kernel/drivers/usb/serial/visor.ko \
+,CONFIG_USB_SERIAL_VISOR,kmod-usb-serial,61,visor))
+
+$(eval $(call KMOD_template,USB_STORAGE,usb-storage,\
+ $(MODULES_DIR)/kernel/drivers/scsi/scsi_mod.ko \
+ $(MODULES_DIR)/kernel/drivers/scsi/sd_mod.ko \
+ $(MODULES_DIR)/kernel/drivers/usb/storage/usb-storage.ko \
+,CONFIG_USB_STORAGE,kmod-usb-core,60,scsi_mod sd_mod usb-storage))
+
+$(eval $(call KMOD_template,USB_ATM,usb-atm,\
+ $(MODULES_DIR)/kernel/drivers/usb/atm/usbatm.ko \
+ ,CONFIG_USB_ATM,kmod-usb-atm,50,usbatm))
+
+$(eval $(call KMOD_template,USB_ATM_SPEEDTOUCH,usb-atm-speedtouch,\
+ $(MODULES_DIR)/kernel/drivers/usb/atm/speedtch.ko \
+ ,CONFIG_USB_SPEEDTOUCH,kmod-usb-atm-speedtouch,50,speedtch))
+
+# Misc. devices
+
+$(eval $(call KMOD_template,AX25,ax25,\
+ $(MODULES_DIR)/kernel/net/ax25/ax25.ko \
+ $(MODULES_DIR)/kernel/drivers/net/hamradio/mkiss.ko \
+,CONFIG_AX25,,90,ax25 mkiss))
+
+$(eval $(call KMOD_template,BLUETOOTH,bluetooth,\
+ $(MODULES_DIR)/kernel/net/bluetooth/bluetooth.ko \
+ $(MODULES_DIR)/kernel/net/bluetooth/l2cap.ko \
+ $(MODULES_DIR)/kernel/net/bluetooth/sco.ko \
+ $(MODULES_DIR)/kernel/net/bluetooth/rfcomm/rfcomm.ko \
+ $(MODULES_DIR)/kernel/drivers/bluetooth/hci_uart.ko \
+ $(MODULES_DIR)/kernel/drivers/bluetooth/hci_usb.ko \
+,CONFIG_BT))
+
+
diff --git a/include/netfilter.mk b/include/netfilter.mk
new file mode 100644
index 0000000000..ba1512e14a
--- /dev/null
+++ b/include/netfilter.mk
@@ -0,0 +1,122 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: netfilter.mk 2411 2005-11-11 03:41:43Z nico $
+
+ifeq ($(NF_KMOD),1)
+P_V4:=ipv4/netfilter/
+P_XT:=netfilter/
+endif
+
+IPT_CONNTRACK-m :=
+IPT_CONNTRACK-$(CONFIG_IP_NF_MATCH_CONNMARK) += $(P_V4)ipt_connmark
+IPT_CONNTRACK-$(CONFIG_IP_NF_TARGET_CONNMARK) += $(P_V4)ipt_CONNMARK
+IPT_CONNTRACK-$(CONFIG_IP_NF_MATCH_CONNTRACK) += $(P_V4)ipt_conntrack
+IPT_CONNTRACK-$(CONFIG_IP_NF_MATCH_HELPER) += $(P_V4)ipt_helper
+IPT_CONNTRACK-$(CONFIG_IP_NF_MATCH_STATE) += $(P_V4)ipt_state
+IPT_CONNTRACK-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += $(P_XT)xt_conntrack
+IPT_CONNTRACK-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += $(P_XT)xt_helper
+IPT_CONNTRACK-$(CONFIG_NETFILTER_XT_MATCH_STATE) += $(P_XT)xt_state
+
+
+IPT_EXTRA-m :=
+IPT_EXTRA-$(CONFIG_IP_NF_MATCH_CONDITION) += $(P_V4)ipt_condition
+IPT_EXTRA-$(CONFIG_IP_NF_MATCH_CONNBYTES) += $(P_V4)ipt_connbytes
+IPT_EXTRA-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += $(P_XT)xt_connbytes
+IPT_EXTRA-$(CONFIG_IP_NF_MATCH_LIMIT) += $(P_V4)ipt_limit
+IPT_EXTRA-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += $(P_XT)xt_limit
+IPT_EXTRA-$(CONFIG_IP_NF_TARGET_LOG) += $(P_V4)ipt_LOG
+IPT_EXTRA-$(CONFIG_IP_NF_MATCH_MULTIPORT) += $(P_XT)xt_multiport
+IPT_EXTRA-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += $(P_XT)xt_multiport
+IPT_EXTRA-$(CONFIG_IP_NF_MATCH_OWNER) += $(P_V4)ipt_owner
+IPT_EXTRA-$(CONFIG_IP_NF_MATCH_PHYSDEV) += $(P_V4)ipt_physdev
+IPT_EXTRA-$(CONFIG_IP_NF_MATCH_PKTTYPE) += $(P_V4)ipt_pkttype
+IPT_EXTRA-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += $(P_XT)xt_pkttype
+IPT_EXTRA-$(CONFIG_IP_NF_MATCH_QUOTA) += $(P_V4)ipt_quota
+IPT_EXTRA-$(CONFIG_IP_NF_MATCH_RECENT) += $(P_V4)ipt_recent
+IPT_EXTRA-$(CONFIG_IP_NF_TARGET_REJECT) += $(P_V4)ipt_REJECT
+IPT_EXTRA-$(CONFIG_IP_NF_MATCH_STRING) += $(P_V4)ipt_string
+IPT_EXTRA-$(CONFIG_NETFILTER_XT_MATCH_STRING) += $(P_XT)xt_string
+
+IPT_FILTER-m :=
+IPT_FILTER-$(CONFIG_IP_NF_MATCH_IPP2P) += $(P_V4)ipt_ipp2p
+IPT_FILTER-$(CONFIG_IP_NF_MATCH_LAYER7) += $(P_V4)ipt_layer7
+
+IPT_IMQ-m :=
+IPT_IMQ-$(CONFIG_IP_NF_TARGET_IMQ) += $(P_V4)ipt_IMQ
+
+IPT_IPOPT-m :=
+IPT_IPOPT-$(CONFIG_IP_NF_MATCH_DSCP) += $(P_V4)ipt_dscp
+IPT_IPOPT-$(CONFIG_IP_NF_TARGET_DSCP) += $(P_V4)ipt_DSCP
+IPT_IPOPT-$(CONFIG_IP_NF_MATCH_ECN) += $(P_V4)ipt_ecn
+IPT_IPOPT-$(CONFIG_IP_NF_TARGET_ECN) += $(P_V4)ipt_ECN
+IPT_IPOPT-$(CONFIG_IP_NF_MATCH_LENGTH) += $(P_V4)ipt_length
+IPT_IPOPT-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += $(P_XT)xt_length
+IPT_IPOPT-$(CONFIG_IP_NF_MATCH_MAC) += $(P_V4)ipt_mac
+IPT_IPOPT-$(CONFIG_NETFILTER_XT_MATCH_MAC) += $(P_XT)xt_mac
+IPT_IPOPT-$(CONFIG_IP_NF_MATCH_MARK) += $(P_V4)ipt_mark
+IPT_IPOPT-$(CONFIG_NETFILTER_XT_MATCH_MARK) += $(P_XT)xt_mark
+IPT_IPOPT-$(CONFIG_IP_NF_TARGET_MARK) += $(P_V4)ipt_MARK
+IPT_IPOPT-$(CONFIG_NETFILTER_XT_TARGET_MARK) += $(P_XT)xt_MARK
+IPT_IPOPT-$(CONFIG_IP_NF_MATCH_TCPMSS) += $(P_V4)ipt_tcpmss
+IPT_IPOPT-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += $(P_XT)xt_tcpmss
+IPT_IPOPT-$(CONFIG_IP_NF_TARGET_TCPMSS) += $(P_V4)ipt_TCPMSS
+IPT_IPOPT-$(CONFIG_IP_NF_MATCH_TOS) += $(P_V4)ipt_tos
+IPT_IPOPT-$(CONFIG_IP_NF_MATCH_TIME) += $(P_V4)ipt_time
+IPT_IPOPT-$(CONFIG_IP_NF_TARGET_TOS) += $(P_V4)ipt_TOS
+IPT_IPOPT-$(CONFIG_IP_NF_MATCH_TTL) += $(P_V4)ipt_ttl
+IPT_IPOPT-$(CONFIG_IP_NF_TARGET_TTL) += $(P_V4)ipt_TTL
+IPT_IPOPT-$(CONFIG_IP_NF_MATCH_UNCLEAN) += $(P_V4)ipt_unclean
+
+IPT_IPSEC-m :=
+IPT_IPSEC-$(CONFIG_IP_NF_MATCH_AH_ESP) += $(P_V4)ipt_ah $(P_V4)ipt_esp
+IPT_IPSEC-$(CONFIG_IP_NF_MATCH_AH) += $(P_V4)ipt_ah
+IPT_IPSEC-$(CONFIG_NETFILTER_XT_MATCH_ESP) += $(P_XT)xt_esp
+
+IPT_NAT-m :=
+ifneq ($(NF_KMOD),1)
+ IPT_NAT-$(CONFIG_IP_NF_NAT) += $(P_V4)ipt_SNAT $(P_V4)ipt_DNAT
+endif
+IPT_NAT-$(CONFIG_IP_NF_TARGET_MASQUERADE) += $(P_V4)ipt_MASQUERADE
+IPT_NAT-$(CONFIG_IP_NF_TARGET_MIRROR) += $(P_V4)ipt_MIRROR
+IPT_NAT-$(CONFIG_IP_NF_TARGET_REDIRECT) += $(P_V4)ipt_REDIRECT
+IPT_NAT-$(CONFIG_IP_NF_TARGET_NETMAP) += $(P_V4)ipt_NETMAP
+
+IPT_NAT_EXTRA-m :=
+IPT_NAT_EXTRA-$(CONFIG_IP_NF_AMANDA) += $(P_V4)ip_conntrack_amanda
+IPT_NAT_EXTRA-$(CONFIG_IP_NF_CT_PROTO_GRE) += $(P_V4)ip_conntrack_proto_gre
+IPT_NAT_EXTRA-$(CONFIG_IP_NF_NAT_PROTO_GRE) += $(P_V4)ip_nat_proto_gre
+IPT_NAT_EXTRA-$(CONFIG_IP_NF_H323) += $(P_V4)ip_conntrack_h323
+IPT_NAT_EXTRA-$(CONFIG_IP_NF_NAT_H323) += $(P_V4)ip_nat_h323
+IPT_NAT_EXTRA-$(CONFIG_IP_NF_MMS) += $(P_V4)ip_conntrack_mms
+IPT_NAT_EXTRA-$(CONFIG_IP_NF_NAT_MMS) += $(P_V4)ip_nat_mms
+IPT_NAT_EXTRA-$(CONFIG_IP_NF_RTSP) += $(P_V4)ip_conntrack_rtsp
+IPT_NAT_EXTRA-$(CONFIG_IP_NF_NAT_RTSP) += $(P_V4)ip_nat_rtsp
+IPT_NAT_EXTRA-$(CONFIG_IP_NF_PPTP) += $(P_V4)ip_conntrack_pptp
+IPT_NAT_EXTRA-$(CONFIG_IP_NF_SIP) += $(P_V4)ip_conntrack_sip
+IPT_NAT_EXTRA-$(CONFIG_IP_NF_NAT_PPTP) += $(P_V4)ip_nat_pptp
+IPT_NAT_EXTRA-$(CONFIG_IP_NF_NAT_SIP) += $(P_V4)ip_nat_sip
+IPT_NAT_EXTRA-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += $(P_V4)ip_nat_snmp_basic
+IPT_NAT_EXTRA-$(CONFIG_IP_NF_SIP) += $(P_V4)ip_conntrack_sip
+IPT_NAT_EXTRA-$(CONFIG_IP_NF_NAT_SIP) += $(P_V4)ip_nat_sip
+IPT_NAT_EXTRA-$(CONFIG_IP_NF_TFTP) += $(P_V4)ip_conntrack_tftp
+
+IPT_QUEUE-m :=
+IPT_QUEUE-$(CONFIG_IP_NF_QUEUE) += $(P_V4)ip_queue
+
+IPT_ULOG-m :=
+IPT_ULOG-$(CONFIG_IP_NF_TARGET_ULOG) += $(P_V4)ipt_ULOG
+
+IPT_BUILTIN := $(P_V4)ipt_standard
+IPT_BUILTIN += $(P_V4)ipt_icmp $(P_V4)ipt_tcp $(P_V4)ipt_udp
+IPT_BUILTIN += $(IPT_CONNTRACK-y)
+IPT_BUILTIN += $(IPT_EXTRA-y)
+IPT_BUILTIN += $(IPT_FILTER-y)
+IPT_BUILTIN += $(IPT_IMQ-y)
+IPT_BUILTIN += $(IPT_IPOPT-y)
+IPT_BUILTIN += $(IPT_IPSEC-y)
+IPT_BUILTIN += $(IPT_NAT-y)
+IPT_BUILTIN += $(IPT_ULOG-y)
diff --git a/include/package.mk b/include/package.mk
new file mode 100644
index 0000000000..5a9ba861af
--- /dev/null
+++ b/include/package.mk
@@ -0,0 +1,372 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+ifneq ($(DUMP),)
+ all: dumpinfo
+else
+ all: compile
+endif
+
+include $(INCLUDE_DIR)/prereq.mk
+include $(INCLUDE_DIR)/host.mk
+
+define shvar
+V_$(subst .,_,$(subst -,_,$(subst /,_,$(1))))
+endef
+
+define shexport
+$(call shvar,$(1))=$$(call $(1))
+export $(call shvar,$(1))
+endef
+
+define Build/DefaultTargets
+ ifeq ($(DUMP),)
+ ifeq ($(CONFIG_AUTOREBUILD),y)
+ _INFO:=
+ ifneq ($$(shell $(SCRIPT_DIR)/timestamp.pl -p $(PKG_BUILD_DIR) .),$(PKG_BUILD_DIR))
+ _INFO+=$(subst $(TOPDIR)/,,$(PKG_BUILD_DIR))
+ $(PKG_BUILD_DIR)/.prepared: package-clean
+ endif
+ endif
+ endif
+
+ $(PKG_BUILD_DIR)/.prepared:
+ @-rm -rf $(PKG_BUILD_DIR)
+ @mkdir -p $(PKG_BUILD_DIR)
+ $(call Build/Prepare)
+ touch $$@
+
+ $(PKG_BUILD_DIR)/.configured: $(PKG_BUILD_DIR)/.prepared
+ $(call Build/Configure)
+ touch $$@
+
+ $(PKG_BUILD_DIR)/.built: $(PKG_BUILD_DIR)/.configured
+ $(call Build/Compile)
+ touch $$@
+
+ ifdef Build/InstallDev
+ ifneq ($$(shell $(SCRIPT_DIR)/timestamp.pl -p -x ipkg -x ipkg-install $(STAGING_DIR)/stampfiles/.$(PKG_NAME)-installed $(PKG_BUILD_DIR)),$(STAGING_DIR)/stampfiles/.$(PKG_NAME)-installed)
+ $(PKG_BUILD_DIR)/.built: package-rebuild
+ endif
+
+ $(STAGING_DIR)/stampfiles/.$(PKG_NAME)-installed: $(PKG_BUILD_DIR)/.built
+ mkdir -p $(STAGING_DIR)/stampfiles
+ $(call Build/InstallDev)
+ touch $$@
+
+ compile-targets: $(STAGING_DIR)/stampfiles/.$(PKG_NAME)-installed
+ endif
+
+ package-clean: FORCE
+ $(call Build/Clean)
+ $(call Build/UninstallDev)
+ -rm -f $(STAGING_DIR)/stampfiles/.$(PKG_NAME)-installed
+
+ package-rebuild: FORCE
+ @-rm -f $(PKG_BUILD_DIR)/.built
+
+ define Build/DefaultTargets
+ endef
+endef
+
+define Package/Default
+ CONFIGFILE:=
+ SECTION:=opt
+ CATEGORY:=Extra packages
+ DEPENDS:=
+ EXTRA_DEPENDS:=
+ MAINTAINER:=OpenWrt Developers Team <openwrt-devel@openwrt.org>
+ SOURCE:=$(patsubst $(TOPDIR)/%,%,${shell pwd})
+ ifneq ($(PKG_VERSION),)
+ ifneq ($(PKG_RELEASE),)
+ VERSION:=$(PKG_VERSION)-$(PKG_RELEASE)
+ else
+ VERSION:=$(PKG_VERSION)
+ endif
+ else
+ VERSION:=$(PKG_RELEASE)
+ endif
+ PKGARCH:=$(ARCH)
+ PRIORITY:=optional
+ DEFAULT:=
+ MENU:=
+ SUBMENU:=
+ SUBMENUDEP:=
+ TITLE:=
+ DESCRIPTION:=
+endef
+
+define BuildDescription
+ ifneq ($(DESCRIPTION),)
+ DESCRIPTION:=$(TITLE)\\ $(DESCRIPTION)
+ else
+ DESCRIPTION:=$(TITLE)
+ endif
+endef
+
+define BuildIPKGVariable
+ $(call shexport,Package/$(1)/$(2))
+ $(1)_COMMANDS += var2file "$(call shvar,Package/$(1)/$(2))" $(2);
+endef
+
+define BuildPackage
+ $(eval $(call Package/Default))
+ $(eval $(call Package/$(1)))
+ $(eval $(call BuildDescription))
+
+ $(foreach FIELD, TITLE CATEGORY PRIORITY SECTION VERSION,
+ ifeq ($($(FIELD)),)
+ $$(error Package/$(1) is missing the $(FIELD) field)
+ endif
+ )
+
+ IPKG_$(1):=$(PACKAGE_DIR)/$(1)_$(VERSION)_$(PKGARCH).ipk
+ IDIR_$(1):=$(PKG_BUILD_DIR)/ipkg/$(1)
+ INFO_$(1):=$(IPKG_STATE_DIR)/info/$(1).list
+
+ ifdef Package/$(1)/install
+ ifeq ($(CONFIG_PACKAGE_$(1)),y)
+ install-targets: $$(INFO_$(1))
+ endif
+
+ ifneq ($(CONFIG_PACKAGE_$(1)),)
+ compile-targets: $$(IPKG_$(1))
+ else
+ compile-targets: $(1)-disabled
+ $(1)-disabled:
+ @echo "WARNING: skipping $(1) -- package not selected"
+ endif
+ endif
+
+ ifeq ($(FORCEREBUILD),y)
+ $$(IPKG_$(1)): FORCE
+ endif
+
+ IDEPEND_$(1):=$$(strip $$(DEPENDS))
+
+ ifneq ($(DUMP),)
+ DUMPINFO += \
+ echo "Package: $(1)";
+
+ ifneq ($(MENU),)
+ DUMPINFO += \
+ echo "Menu: $(MENU)";
+ endif
+
+ ifneq ($(SUBMENU),)
+ DUMPINFO += \
+ echo "Submenu: $(SUBMENU)";
+ ifneq ($(SUBMENUDEP),)
+ DUMPINFO += \
+ echo "Submenu-Depends: $(SUBMENUDEP)";
+ endif
+ endif
+
+ ifneq ($(DEFAULT),)
+ DUMPINFO += \
+ echo "Default: $(DEFAULT)";
+ endif
+
+ $(call shexport,Package/$(1)/description)
+
+ DUMPINFO += \
+ if [ "$$$$PREREQ_CHECK" = 1 ]; then echo "Prereq-Check: 1"; fi; \
+ echo "Version: $(VERSION)"; \
+ echo "Depends: $$(IDEPEND_$(1))"; \
+ echo "Build-Depends: $(PKG_BUILDDEP)"; \
+ echo "Category: $(CATEGORY)"; \
+ echo "Title: $(TITLE)"; \
+ if isset $(call shvar,Package/$(1)/description); then \
+ echo -n "Description: "; \
+ getvar $(call shvar,Package/$(1)/description); \
+ else \
+ echo "Description: $(DESCRIPTION)" | sed -e 's,\\,\n,g'; \
+ fi;
+
+ ifneq ($(URL),)
+ DUMPINFO += \
+ echo; \
+ echo "$(URL)";
+ endif
+
+ DUMPINFO += \
+ echo "@@";
+
+ $(call shexport,Package/$(1)/config)
+ DUMPINFO += \
+ if isset $(call shvar,Package/$(1)/config); then echo "Config: "; getvar $(call shvar,Package/$(1)/config); fi; \
+ echo "@@";
+
+ endif
+
+ $(eval $(call BuildIPKGVariable,$(1),conffiles))
+ $(eval $(call BuildIPKGVariable,$(1),preinst))
+ $(eval $(call BuildIPKGVariable,$(1),postinst))
+ $(eval $(call BuildIPKGVariable,$(1),prerm))
+ $(eval $(call BuildIPKGVariable,$(1),postrm))
+ $$(IDIR_$(1))/CONTROL/control: $(PKG_BUILD_DIR)/.version-$(1)_$(VERSION)_$(PKGARCH)
+ mkdir -p $$(IDIR_$(1))/CONTROL
+ echo "Package: $(1)" > $$(IDIR_$(1))/CONTROL/control
+ echo "Version: $(VERSION)" >> $$(IDIR_$(1))/CONTROL/control
+ ( \
+ DEPENDS=; \
+ for depend in $$(filter-out @%,$$(IDEPEND_$(1))); do \
+ DEPENDS=$$$${DEPENDS:+$$$$DEPENDS, }$$$${depend##+}; \
+ done; \
+ echo "Depends: $(EXTRA_DEPENDS) $$$$DEPENDS" >> $$(IDIR_$(1))/CONTROL/control; \
+ )
+ echo "Source: $(SOURCE)" >> $$(IDIR_$(1))/CONTROL/control
+ echo "Section: $(SECTION)" >> $$(IDIR_$(1))/CONTROL/control
+ echo "Priority: $(PRIORITY)" >> $$(IDIR_$(1))/CONTROL/control
+ echo "Maintainer: $(MAINTAINER)" >> $$(IDIR_$(1))/CONTROL/control
+ echo "Architecture: $(PKGARCH)" >> $$(IDIR_$(1))/CONTROL/control
+ echo "Description: $(DESCRIPTION)" | sed -e 's,\\,\n,g' | sed -e 's,^[[:space:]]*$$$$, .,g' >> $$(IDIR_$(1))/CONTROL/control
+ chmod 644 $$(IDIR_$(1))/CONTROL/control
+ (cd $$(IDIR_$(1))/CONTROL; \
+ $($(1)_COMMANDS) \
+ )
+
+ $$(IPKG_$(1)): $(PKG_BUILD_DIR)/.built $$(IDIR_$(1))/CONTROL/control
+ $(call Package/$(1)/install,$$(IDIR_$(1)))
+ mkdir -p $(PACKAGE_DIR)
+ -find $$(IDIR_$(1)) -name CVS | xargs rm -rf
+ -find $$(IDIR_$(1)) -name .svn | xargs rm -rf
+ -find $$(IDIR_$(1)) -name '.#*' | xargs rm -f
+ $(RSTRIP) $$(IDIR_$(1))
+ $(IPKG_BUILD) $$(IDIR_$(1)) $(PACKAGE_DIR)
+ @[ -f $$(IPKG_$(1)) ] || false
+
+ $$(INFO_$(1)): $$(IPKG_$(1))
+ $(IPKG) install $$(IPKG_$(1))
+
+ $(1)-clean:
+ rm -f $(PACKAGE_DIR)/$(1)_*
+
+ clean: $(1)-clean
+
+ $(PKG_BUILD_DIR)/.version-$(1)_$(VERSION)_$(PKGARCH): $(PKG_BUILD_DIR)/.prepared
+ -@rm $(PKG_BUILD_DIR)/.version-$(1)_* 2>/dev/null
+ @touch $$@
+
+ $$(eval $$(call Build/DefaultTargets,$(1)))
+
+ ifneq ($$(CONFIG_PACKAGE_$(1)),)
+ ifneq ($(MAKECMDGOALS),prereq)
+ ifneq ($(DUMP),1)
+ ifneq ($$(shell $(SCRIPT_DIR)/timestamp.pl -p -x ipkg -x ipkg-install '$$(IPKG_$(1))' '$(PKG_BUILD_DIR)'),$$(IPKG_$(1)))
+ _INFO+=$(subst $(TOPDIR)/,,$$(IPKG_$(1)))
+ $(PKG_BUILD_DIR)/.built: package-rebuild
+ endif
+
+ ifneq ($$(_INFO),)
+ $$(info Rebuilding $$(_INFO))
+ endif
+ endif
+ endif
+ endif
+endef
+
+ifneq ($(strip $(PKG_CAT)),)
+ ifeq ($(PKG_CAT),unzip)
+ UNPACK=unzip -d $(PKG_BUILD_DIR) $(DL_DIR)/$(PKG_SOURCE)
+ else
+ UNPACK=$(PKG_CAT) $(DL_DIR)/$(PKG_SOURCE) | tar -C $(PKG_BUILD_DIR)/.. $(TAR_OPTIONS) -
+ endif
+ define Build/Prepare/Default
+ $(UNPACK)
+ @if [ -d ./patches ]; then \
+ $(PATCH) $(PKG_BUILD_DIR) ./patches; \
+ fi
+ endef
+endif
+
+define Build/Prepare
+ $(call Build/Prepare/Default,)
+endef
+
+define Build/Configure/Default
+ (cd $(PKG_BUILD_DIR)/$(3); \
+ if [ -x configure ]; then \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ CXXFLAGS="$(TARGET_CFLAGS)" \
+ CPPFLAGS="-I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/include" \
+ LDFLAGS="-L$(STAGING_DIR)/usr/lib -L$(STAGING_DIR)/lib" \
+ PKG_CONFIG_PATH="$(STAGING_DIR)/usr/lib/pkgconfig" \
+ $(2) \
+ ./configure \
+ --target=$(GNU_TARGET_NAME) \
+ --host=$(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 \
+ --datadir=/usr/share \
+ --localstatedir=/var \
+ --mandir=/usr/man \
+ --infodir=/usr/info \
+ $(DISABLE_NLS) \
+ $(1); \
+ fi; \
+ )
+endef
+
+define Build/Configure
+ $(call Build/Configure/Default,)
+endef
+
+define Build/Compile/Default
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ CROSS="$(TARGET_CROSS)" \
+ EXTRA_CFLAGS="$(TARGET_CFLAGS) -I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/include " \
+ EXTRA_LDFLAGS="-L$(STAGING_DIR)/usr/lib -L$(STAGING_DIR)/lib " \
+ ARCH="$(ARCH)" \
+ $(1);
+endef
+
+define Build/Compile
+ $(call Build/Compile/Default,)
+endef
+
+ifneq ($(DUMP),)
+ dumpinfo: FORCE
+ @$(DUMPINFO)
+else
+ $(PACKAGE_DIR):
+ mkdir -p $@
+
+ ifneq ($(strip $(PKG_SOURCE)),)
+ download: $(DL_DIR)/$(PKG_SOURCE)
+
+ $(DL_DIR)/$(PKG_SOURCE):
+ mkdir -p $(DL_DIR)
+ $(SCRIPT_DIR)/download.pl "$(DL_DIR)" "$(PKG_SOURCE)" "$(PKG_MD5SUM)" $(PKG_SOURCE_URL)
+
+ $(PKG_BUILD_DIR)/.prepared: $(DL_DIR)/$(PKG_SOURCE)
+ endif
+
+ download:
+ prepare: $(PKG_BUILD_DIR)/.prepared
+ configure: $(PKG_BUILD_DIR)/.configured
+
+ compile-targets:
+ compile: compile-targets
+
+ install-targets:
+ install: install-targets
+
+ clean-targets:
+ clean: FORCE
+ @$(MAKE) clean-targets
+ $(call Build/Clean)
+ rm -rf $(PKG_BUILD_DIR)
+endif
diff --git a/include/prereq-build.mk b/include/prereq-build.mk
new file mode 100644
index 0000000000..d6396af8e2
--- /dev/null
+++ b/include/prereq-build.mk
@@ -0,0 +1,105 @@
+#
+# 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
+TMP_DIR:=$(TOPDIR)/tmp
+include $(INCLUDE_DIR)/prereq.mk
+include $(INCLUDE_DIR)/host.mk
+
+define Require/non-root
+ [ "$$(shell whoami)" != "root" ]
+endef
+$(eval $(call Require,non-root, \
+ Please do not compile as root. \
+))
+
+# Required for the toolchain
+define Require/working-make
+ echo 'all: test' > $(TMP_DIR)/check.mk
+ echo 'e0 = $$$$(foreach s,foobar,$$$$(eval $$$$s:))' >> $(TMP_DIR)/check.mk
+ echo 'e1 = $$$$(foreach s,foobar, $$$$(eval $$$$s:))' >> $(TMP_DIR)/check.mk
+ echo 'test: $$$$(strip $$$$(e0)) $$$$(strip $$$$(e1))' >> $(TMP_DIR)/check.mk
+ $(NO_TRACE_MAKE) -f $(TMP_DIR)/check.mk
+endef
+
+$(eval $(call Require,working-make, \
+ Please install GNU make v3.81 or later. (This version has bugs) \
+))
+
+define Require/working-gcc
+ echo 'int main(int argc, char **argv) { return 0; }' | \
+ gcc -x c -o $(TMP_DIR)/a.out -
+endef
+
+$(eval $(call Require,working-gcc, \
+ Please install the GNU C Compiler (gcc). \
+))
+
+define Require/working-g++
+ echo 'int main(int argc, char **argv) { return 0; }' | \
+ g++ -x c++ -o $(TMP_DIR)/a.out -lstdc++ -
+endef
+
+$(eval $(call Require,working-g++, \
+ Please install the GNU C++ Compiler (g++). \
+))
+
+define Require/ncurses
+ echo 'int main(int argc, char **argv) { initscr(); return 0; }' | \
+ gcc -include ncurses.h -x c -o $(TMP_DIR)/a.out -lncurses -
+endef
+
+$(eval $(call Require,ncurses, \
+ Please install ncurses. (Missing libncurses.so or ncurses.h) \
+))
+
+
+define Require/zlib
+ echo 'int main(int argc, char **argv) { gzdopen(0, "rb"); return 0; }' | \
+ gcc -include zlib.h -x c -o $(TMP_DIR)/a.out -lz -
+endef
+
+$(eval $(call Require,zlib, \
+ Please install zlib. (Missing libz.so or zlib.h) \
+))
+
+
+$(eval $(call RequireCommand,bison, \
+ Please install GNU bison. \
+))
+
+$(eval $(call RequireCommand,flex, \
+ Please install flex. \
+))
+
+$(eval $(call RequireCommand,python, \
+ Please install python. \
+))
+
+$(eval $(call RequireCommand,unzip, \
+ Please install unzip. \
+))
+
+$(eval $(call RequireCommand,bzip2, \
+ Please install bzip2. \
+))
+
+$(eval $(call RequireCommand,patch, \
+ Please install patch. \
+))
+
+$(eval $(call RequireCommand,perl, \
+ Please install perl. \
+))
+
+define Require/gnutar
+ $(TAR) --version 2>&1 | grep GNU > /dev/null
+endef
+
+$(eval $(call Require,gnutar, \
+ Please install GNU tar. \
+))
diff --git a/include/prereq.mk b/include/prereq.mk
new file mode 100644
index 0000000000..eda7ca35a6
--- /dev/null
+++ b/include/prereq.mk
@@ -0,0 +1,54 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+$(TMP_DIR):
+ mkdir -p $@
+
+prereq:
+ if [ -f $(TMP_DIR)/.prereq-error ]; then \
+ echo; \
+ cat $(TMP_DIR)/.prereq-error; \
+ echo; \
+ rm -rf $(TMP_DIR); \
+ false; \
+ fi
+ rm -rf $(TMP_DIR)
+ mkdir -p $(TMP_DIR)
+
+.SILENT: $(TMP_DIR) prereq
+
+define Require
+ export PREREQ_CHECK=1
+ ifeq ($$(CHECK_$(1)),)
+ prereq: prereq-$(1)
+
+ prereq-$(1): $(TMP_DIR) FORCE
+ echo -n "Checking '$(1)'... "
+ if $(NO_TRACE_MAKE) -f $(firstword $(MAKEFILE_LIST)) check-$(1) >/dev/null 2>/dev/null; then \
+ echo 'ok.'; \
+ else \
+ echo 'failed.'; \
+ echo -e "$(strip $(2))" >> $(TMP_DIR)/.prereq-error; \
+ fi
+
+ check-$(1): FORCE
+ $(call Require/$(1))
+ CHECK_$(1):=1
+
+ .SILENT: prereq-$(1) check-$(1)
+ endif
+endef
+
+
+define RequireCommand
+ define Require/$(1)
+ which $(1)
+ endef
+
+ $$(eval $$(call Require,$(1),$(2)))
+endef
+
diff --git a/include/shell.sh b/include/shell.sh
new file mode 100644
index 0000000000..6ee0cf6030
--- /dev/null
+++ b/include/shell.sh
@@ -0,0 +1,15 @@
+getvar() {
+ eval "echo \"\${$1}\""
+}
+
+var2file() {
+ local var
+ eval "var=\"\${$1}\""
+ if [ -n "$var" ]; then echo "$var" > "$2"; fi
+}
+
+isset() {
+ local var
+ eval "var=\"\${$1}\""
+ [ -n "$var" ]
+}
diff --git a/include/target.mk b/include/target.mk
new file mode 100644
index 0000000000..6c21f517bf
--- /dev/null
+++ b/include/target.mk
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+define kernel_template
+ifeq ($(CONFIG_LINUX_$(3)),y)
+KERNEL:=$(1)
+BOARD:=$(2)
+endif
+endef
+
+$(eval $(call kernel_template,2.4,brcm,2_4_BRCM))
+$(eval $(call kernel_template,2.4,ar7,2_4_AR7))
+$(eval $(call kernel_template,2.6,brcm,2_6_BRCM))
+$(eval $(call kernel_template,2.6,brcm63xx,2_6_BRCM63XX))
+$(eval $(call kernel_template,2.6,rb532,2_6_RB532))
+$(eval $(call kernel_template,2.6,x86,2_6_X86))
+$(eval $(call kernel_template,2.6,uml,2_6_UML))
+$(eval $(call kernel_template,2.4,ar531x,2_4_AR531X))
+$(eval $(call kernel_template,2.6,aruba,2_6_ARUBA))
+$(eval $(call kernel_template,2.6,au1000,2_6_AU1000))
+$(eval $(call kernel_template,2.6,xscale,2_6_XSCALE))
+$(eval $(call kernel_template,2.6,magicbox,2_6_MAGICBOX))
+$(eval $(call kernel_template,2.6,sibyte,2_6_SIBYTE))
+
+export BOARD
+export KERNEL
+
+
diff --git a/include/verbose.mk b/include/verbose.mk
new file mode 100644
index 0000000000..34568a31f8
--- /dev/null
+++ b/include/verbose.mk
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id:$
+
+ifeq ($(NO_TRACE_MAKE),)
+NO_TRACE_MAKE := $(MAKE) V=99
+export NO_TRACE_MAKE
+endif
+
+ifndef KBUILD_VERBOSE
+ KBUILD_VERBOSE:=0
+endif
+ifeq ("$(origin V)", "command line")
+ KBUILD_VERBOSE:=$(V)
+endif
+
+ifneq ($(shell tty -s <&3 || echo x),x)
+ _Y:="\\33[33m"# yellow
+ _N:="\\33[m"# normal
+endif
+
+ifneq ($(KBUILD_VERBOSE),99)
+ ifeq ($(QUIET),1)
+ $(MAKECMDGOALS): trace
+ trace: FORCE
+ @[ -f "$(MAKECMDGOALS)" ] || { \
+ [ -z "$${PWD##$$TOPDIR}" ] || DIR=" -C $${PWD##$$TOPDIR/}"; \
+ echo -e "$(_Y)make[$$(($(MAKELEVEL)+1))]$$DIR $(MAKECMDGOALS)$(_N)" >&3; \
+ }
+ else
+ export QUIET:=1
+ ifeq ($(KBUILD_VERBOSE),0)
+ MAKE:=&>/dev/null $(MAKE)
+ endif
+ MAKE:=cmd() { $(MAKE) $$* || { echo "Build failed. Please re-run make with V=99 to see what's going on"; false; } } 3>&1 4>&2; cmd
+ endif
+
+ .SILENT: $(MAKECMDGOALS)
+endif
diff --git a/package/Makefile b/package/Makefile
new file mode 100644
index 0000000000..e94c181ba0
--- /dev/null
+++ b/package/Makefile
@@ -0,0 +1,69 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+include $(TOPDIR)/.config
+include $(TOPDIR)/.pkgdeps
+include $(TOPDIR)/host.mk
+
+PREREQ_PACKAGES:=$(patsubst %,%-prereq,$(prereq-y) $(prereq-m))
+DOWNLOAD_PACKAGES:=$(patsubst %,%-download,$(package-y) $(package-m))
+COMPILE_PACKAGES:=$(patsubst %,%-compile,$(package-y) $(package-m))
+INSTALL_PACKAGES:=$(patsubst %,%-install,$(package-y))
+
+$(STAMP_DIR) $(TARGET_DIR):
+ mkdir -p $@
+
+%-prereq: $(STAMP_DIR) $(TARGET_DIR)
+ $(MAKE) -C $(patsubst %-prereq,%,$@) prereq
+
+%-download: $(STAMP_DIR) $(TARGET_DIR)
+ $(MAKE) -C $(patsubst %-download,%,$@) download
+
+%-prepare: $(STAMP_DIR) $(TARGET_DIR)
+ $(MAKE) -C $(patsubst %-prepare,%,$@) prepare
+
+%-compile: $(STAMP_DIR) $(TARGET_DIR)
+ $(MAKE) -C $(patsubst %-compile,%,$@) compile
+
+%-install: $(STAMP_DIR) $(TARGET_DIR)
+ $(MAKE) -C $(patsubst %-install,%,$@) install
+
+%-clean: $(STAMP_DIR) $(TARGET_DIR)
+ $(MAKE) -C $(patsubst %-clean,%,$@) clean
+
+ifeq ($(SDK),1)
+GENDEP_OPTS := -s
+endif
+
+$(TOPDIR)/.pkgdeps: $(TOPDIR)/.pkginfo
+ @$(TOPDIR)/scripts/gen_deps.pl $(GENDEP_OPTS) < $< > $@ || rm -f $@
+
+all: compile
+clean: $(patsubst %,%-clean,$(package-) $(package-y) $(package-m))
+prereq: $(PREREQ_PACKAGES)
+download: $(DOWNLOAD_PACKAGES)
+compile-targets: $(COMPILE_PACKAGES)
+compile:
+ $(MAKE) compile-targets
+install-targets: base-files-install $(INSTALL_PACKAGES)
+install:
+ rm -rf $(BUILD_DIR)/root
+ $(MAKE) install-targets
+
+index: $(PACKAGE_DIR)/Packages
+
+$(PACKAGE_DIR)/Packages: $(PACKAGE_DIR)/*.ipk
+ (cd $(PACKAGE_DIR); $(SCRIPT_DIR)/ipkg-make-index.sh . > Packages)
+
+
+ifeq ($(MAKECMDGOALS),compile-targets)
+MAKEFLAGS:=$(MAKEFLAGS) -j$(CONFIG_JLEVEL)
+else
+.NOTPARALLEL:
+endif
diff --git a/package/alsa/Makefile b/package/alsa/Makefile
new file mode 100644
index 0000000000..47ad4456bf
--- /dev/null
+++ b/package/alsa/Makefile
@@ -0,0 +1,81 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=alsa-driver
+PKG_VERSION:=1.0.11
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=ftp://ftp.alsa-project.org/pub/driver/
+PKG_MD5SUM:=57534e4297cd683371402220e3753885
+PKG_CAT:=bzcat
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/kmod-alsa
+ SECTION:=kernel
+ CATEGORY:=Kernel drivers
+ DEPENDS:=@USB_SUPPORT
+ TITLE:=Advanced Linux Sound Architecture
+ URL:=http://alsa-project.org/
+ VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE)
+endef
+
+ifeq ($(KERNEL),2.4)
+ ifeq ($(LINUX_KARCH),i386)
+ KERNEL_C_OPTS:= -Os -mpreferred-stack-boundary=2 -march=i486 -fno-unit-at-a-time
+ endif
+ ifeq ($(LINUX_KARCH),mips)
+ KERNEL_C_OPTS:= -Os -G 0 -mno-abicalls -fno-pic -finline-limit=100000 -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap
+ endif
+endif
+ifeq ($(LINUX_KARCH),i386)
+ KERNEL_C_INCS:= -I$(LINUX_DIR)/include/asm-i386/mach-generic -I$(LINUX_DIR)/include/asm-i386/mach-default
+endif
+ifeq ($(LINUX_KARCH),mips)
+ KERNEL_C_INCS:= -I$(LINUX_DIR)/include/asm-mips/mach-generic
+endif
+
+define Build/Configure
+ (cd $(PKG_BUILD_DIR); \
+ CFLAGS="$(KERNEL_C_INCS)" \
+ ./configure \
+ --with-build="$(LINUX_DIR)" \
+ --with-kernel="$(LINUX_DIR)" \
+ --with-cross="$(KERNEL_CROSS)" \
+ --with-redhat=no \
+ --with-suse=no \
+ --with-oss=yes \
+ --with-isapnp=no \
+ --with-sequencer=no \
+ --with-cards=usb-audio \
+ );
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ c_opts="$(KERNEL_C_OPTS)" \
+ all
+endef
+
+define Package/kmod-alsa/install
+ install -d -m0755 $(1)/lib/modules/$(LINUX_VERSION)
+ install -m0644 $(PKG_BUILD_DIR)/modules/*.$(LINUX_KMOD_SUFFIX) \
+ $(1)/lib/modules/$(LINUX_VERSION)/
+ install -d -m0755 $(1)/etc/modules.d
+ install -m0644 ./files/alsa.modules $(1)/etc/modules.d/70-alsa
+endef
+
+$(eval $(call BuildPackage,kmod-alsa))
diff --git a/package/alsa/files/alsa.modules b/package/alsa/files/alsa.modules
new file mode 100644
index 0000000000..6b16c8c586
--- /dev/null
+++ b/package/alsa/files/alsa.modules
@@ -0,0 +1,10 @@
+snd-page-alloc
+snd
+snd-timer
+snd-pcm
+snd-rawmidi
+snd-usb-lib
+snd-hwdep
+snd-usb-audio
+snd-mixer-oss
+snd-pcm-oss
diff --git a/package/alsa/patches/100-compile_fix.patch b/package/alsa/patches/100-compile_fix.patch
new file mode 100644
index 0000000000..2e2a3df79a
--- /dev/null
+++ b/package/alsa/patches/100-compile_fix.patch
@@ -0,0 +1,18 @@
+diff -urN alsa.old/include/adriver.h alsa.dev/include/adriver.h
+--- alsa.old/include/adriver.h 2006-04-19 08:24:30.000000000 +0200
++++ alsa.dev/include/adriver.h 2006-05-31 17:24:49.000000000 +0200
+@@ -451,7 +451,7 @@
+ #endif /* < 2.6.0 */
+
+ /* workarounds for USB API */
+-#if defined(SND_NEED_USB_WRAPPER) && (defined(CONFIG_USB) || defined(CONFIG_USB_MODULE))
++#if 1
+
+ #include <linux/usb.h>
+
+@@ -1174,4 +1174,5 @@
+ */
+ #define OPL3_HW_OPL3_PC98 0x0305 /* PC9800 */
+
++#undef info /* used in several structs */
+ #endif /* __SOUND_LOCAL_DRIVER_H */
diff --git a/package/arptables/Makefile b/package/arptables/Makefile
new file mode 100644
index 0000000000..0518e8ea36
--- /dev/null
+++ b/package/arptables/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.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=arptables
+PKG_VERSION:=0.0.3
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-v$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/ebtables
+PKG_MD5SUM:=1672244603c8979577aa4738be35a759
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-v$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/arptables
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=ARP firewalling software
+ 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 -m0755 -d $(1)/usr/sbin
+ $(CP) $(PKG_BUILD_DIR)/$(PKG_NAME) $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,arptables))
diff --git a/package/base-files/Makefile b/package/base-files/Makefile
new file mode 100644
index 0000000000..9f6da3bc7c
--- /dev/null
+++ b/package/base-files/Makefile
@@ -0,0 +1,191 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=base-files
+PKG_RELEASE:=8
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)
+
+REV:=$(shell LANG=C svn info | awk '/^Revision:/ { print$$2 }' )
+ifeq ($(REV),)
+ REV:=0
+endif
+
+include $(INCLUDE_DIR)/package.mk
+
+ifneq ($(DUMP),1)
+ TARGET:=-$(BOARD)-$(KERNEL)
+ UCLIBC_VERSION:=${shell cat $(STAGING_DIR)/uclibc_version 2>/dev/null}
+ LIBGCC_VERSION:=${shell cat $(STAGING_DIR)/gcc_version 2>/dev/null}
+else
+ UCLIBC_VERSION:=<UCLIBC_VERSION>
+ LIBGCC_VERSION:=<LIBGCC_VERSION>
+endif
+
+CONFIG_PACKAGE_base-files$(TARGET):=$(CONFIG_PACKAGE_base-files)
+
+define Package/base-files$(TARGET)
+ SECTION:=base
+ CATEGORY:=Base system
+ DEFAULT:=y
+ TITLE:=Base filesystem for OpenWrt
+ DESCRIPTION:=\
+ This package contains a base filesystem and system scripts for OpenWrt.
+ URL:=http://openwrt.org/
+ VERSION:=$(PKG_RELEASE)-$(REV)
+endef
+
+define -ar7-2.4/conffiles
+/etc/config/network
+endef
+
+define -aruba-2.6/conffiles
+/etc/config/network
+endef
+
+define -au1000-2.6/conffiles
+/etc/config/network
+endef
+
+define -rb532-2.6/conffiles
+/etc/config/network
+endef
+
+define -sibyte-2.6/conffiles
+/etc/config/network
+endef
+
+define -x86-2.6/conffiles
+/etc/config/network
+endef
+
+define -xscale-2.6/conffiles
+/etc/config/network
+endef
+
+define Package/base-files$(TARGET)/conffiles
+/etc/banner
+/etc/hosts
+/etc/inittab
+/etc/group
+/etc/passwd
+/etc/profile
+/etc/shells
+/etc/ipkg.conf
+/etc/sysctl.conf
+$(call $(TARGET)/conffiles)
+endef
+
+define Package/libgcc
+ SECTION:=libs
+ CATEGORY:=Base system
+ DEFAULT:=y
+ DEPENDS:=@!NATIVE_TOOLCHAIN
+ TITLE:=GCC support library
+ URL:=http://gcc.gnu.org/
+ VERSION:=$(LIBGCC_VERSION)-$(PKG_RELEASE)
+endef
+
+define Package/libpthread
+ SECTION:=libs
+ CATEGORY:=Libraries
+ DEPENDS:=@!NATIVE_TOOLCHAIN
+ TITLE:=POSIX thread library
+ URL:=http://uclibc.org/
+ VERSION:=$(UCLIBC_VERSION)-$(PKG_RELEASE)
+endef
+
+define Package/uclibc
+ SECTION:=libs
+ CATEGORY:=Base system
+ DEFAULT:=y
+ DEPENDS:=@!NATIVE_TOOLCHAIN
+ TITLE:=C library embedded systems
+ URL:=http://uclibc.org/
+ VERSION:=$(UCLIBC_VERSION)-$(PKG_RELEASE)
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+endef
+
+define Build/Compile/ar7
+ $(TARGET_CC) -o $(PKG_BUILD_DIR)/adam2patcher src/adam2patcher.c
+endef
+
+define Build/Compile/brcm
+ $(TARGET_CC) -o $(PKG_BUILD_DIR)/jffs2root src/jffs2root.c
+endef
+
+define Build/Compile
+ $(call Build/Compile/$(BOARD))
+endef
+
+
+define Package/base-files$(TARGET)/install-ar7
+ mkdir -p $(1)/sbin
+ $(CP) $(PKG_BUILD_DIR)/adam2patcher $(1)/sbin
+endef
+
+define Package/base-files$(TARGET)/install-brcm
+ rm -f $(1)/etc/config/network
+ mkdir -p $(1)/sbin
+ $(CP) $(PKG_BUILD_DIR)/jffs2root $(1)/sbin
+endef
+
+define Package/base-files$(TARGET)/install
+ $(CP) ./default/* $(1)/
+ if [ -d $(BOARD)-$(KERNEL) ]; then \
+ $(CP) $(BOARD)-$(KERNEL)/* $(1)/; \
+ fi
+ $(SED) 's,$$$$R,r$(REV),g' $(1)/etc/banner
+ $(SED) 's,$$$$S,$(BOARD)-$(KERNEL),g' $(1)/etc/ipkg.conf
+ mkdir -p $(1)/dev
+ mkdir -p $(1)/etc/crontabs
+ mkdir -p $(1)/jffs
+ mkdir -p $(1)/lib
+ mkdir -p $(1)/mnt
+ mkdir -p $(1)/proc
+ mkdir -p $(1)/tmp
+ mkdir -p $(1)/usr/lib
+ mkdir -p $(1)/usr/bin
+ mkdir -p $(1)/sys
+ mkdir -p $(1)/www
+ ln -sf /proc/mounts $(1)/etc/mtab
+ rm -f $(1)/var
+ ln -sf /tmp $(1)/var
+ mkdir -p $(1)/etc
+$(call Package/base-files$(TARGET)/install-$(BOARD),$(1))
+endef
+
+define Package/libgcc/install
+ install -m0755 -d $(1)/lib
+ $(CP) $(STAGING_DIR)/lib/libgcc_s.so.* $(1)/lib/
+endef
+
+define Package/libpthread/install
+ install -m0755 -d $(1)/lib
+ $(CP) $(STAGING_DIR)/lib/libpthread.so.* $(1)/lib/
+ $(CP) $(STAGING_DIR)/lib/libpthread-$(UCLIBC_VERSION).so $(1)/lib/
+endef
+
+define Package/uclibc/install
+ install -m0755 -d $(1)/lib
+ for file in ld-uClibc libc libcrypt libdl libm libnsl libresolv librt libuClibc libutil; do \
+ $(CP) $(STAGING_DIR)/lib/$$$$file.so.* $(1)/lib/; \
+ $(CP) $(STAGING_DIR)/lib/$$$$file-$(UCLIBC_VERSION).so $(1)/lib/; \
+ done
+endef
+
+$(eval $(call BuildPackage,base-files$(TARGET)))
+$(eval $(call BuildPackage,libgcc))
+$(eval $(call BuildPackage,libpthread))
+$(eval $(call BuildPackage,uclibc))
diff --git a/package/base-files/ar7-2.4/bin/firstboot b/package/base-files/ar7-2.4/bin/firstboot
new file mode 100755
index 0000000000..774bbc754b
--- /dev/null
+++ b/package/base-files/ar7-2.4/bin/firstboot
@@ -0,0 +1,89 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+rom=$(awk '/squashfs/ {print $2}' /proc/mounts)
+jffs=$(awk '/jffs2/ {print $2}' /proc/mounts)
+
+dupe() { # <new_root> <old_root>
+ cd $1
+ echo -n "creating directories... "
+ {
+ cd $2
+ find . -xdev -type d
+ echo "./dev ./jffs ./mnt ./proc ./tmp ./sys"
+ # 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*|\
+ ./etc/resolv.conf|\
+ ./usr/lib/ipkg/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
+ return 0
+ }
+}
+
+mountdp() { # <device> <mount_point> <ignored> <fs>
+ dev=$1; mnt=$2; shift 2; opt=$*
+ mount $dev $mnt $opt
+ dupe $mnt $rom
+ pivot $mnt /rom
+}
+
+ramoverlay() {
+ mkdir -p /tmp/root
+ mountdp /tmp/root /mnt -o bind
+}
+
+[ "${0##*/}" = "firstboot" ] && {
+ [ -z "$rom" ] && {
+ echo "You do not have a squashfs partition; aborting"
+ echo "(firstboot cannot be run on jffs2 based firmwares)"
+ exit 1
+ }
+
+ [ "$1" = "switch2jffs" ] && {
+ mtd erase OpenWrt
+ mount -o remount,ro none / # try to avoid fs changing while copying
+ mount -o bind / /mnt
+ mount /dev/mtdblock/4 /rom/jffs -t jffs2
+ echo -n "copying files ... "
+ cp -a /mnt/* /rom/jffs
+ umount /mnt
+ echo "done"
+ pivot /rom /mnt
+ mount -o move /mnt /tmp/root
+ pivot /jffs /rom
+ exit 0
+ }
+
+ # script run manually
+ [ \! -z "$jffs" ] && {
+ echo "firstboot has already been run"
+ echo "jffs2 partition is mounted, only resetting files"
+ dupe $jffs $rom
+ exit 0
+ }
+
+ mtd erase OpenWrt
+ mountdp /dev/mtdblock/4 /jffs -t jffs2
+}
diff --git a/package/base-files/ar7-2.4/etc/config/network b/package/base-files/ar7-2.4/etc/config/network
new file mode 100644
index 0000000000..911134bb0d
--- /dev/null
+++ b/package/base-files/ar7-2.4/etc/config/network
@@ -0,0 +1,14 @@
+# Network configuration file
+
+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 proto static
+ option ipaddr 192.168.1.1
+ option netmask 255.255.255.0
+
diff --git a/package/base-files/ar7-2.4/etc/init.d/S00adam2 b/package/base-files/ar7-2.4/etc/init.d/S00adam2
new file mode 100755
index 0000000000..5f5b3504c2
--- /dev/null
+++ b/package/base-files/ar7-2.4/etc/init.d/S00adam2
@@ -0,0 +1,12 @@
+#!/bin/sh /etc/rc.common
+# ADAM2 patcher for Netgear DG834 and compatible
+# Copyright (C) 2006 OpenWrt.org
+
+start() {
+ MD5="$(md5sum /dev/mtdblock/0 | awk '{print $1}')"
+ [ "$MD5" = "0530bfdf00ec155f4182afd70da028c1" ] && {
+ mtd unlock adam2
+ /sbin/adam2patcher /dev/mtdblock/0
+ }
+ rm -f /etc/init.d/S00adam2 /sbin/adam2patcher >&- 2>&-
+}
diff --git a/package/base-files/ar7-2.4/etc/preinit b/package/base-files/ar7-2.4/etc/preinit
new file mode 100755
index 0000000000..5b676ca3ac
--- /dev/null
+++ b/package/base-files/ar7-2.4/etc/preinit
@@ -0,0 +1,11 @@
+#!/bin/sh
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin
+mount none /proc -t proc
+
+[ -f /etc/preinit.arch ] && . /etc/preinit.arch
+[ -z "$FAILSAFE" ] || {
+ echo /bin/true > /proc/sys/kernel/hotplug
+ telnetd -l /bin/login <> /dev/null 2>&1
+}
+mount_root ${FAILSAFE:+failsafe}
+exec /sbin/init
diff --git a/package/base-files/ar7-2.4/sbin/mount_root b/package/base-files/ar7-2.4/sbin/mount_root
new file mode 100755
index 0000000000..6b90bdc9cc
--- /dev/null
+++ b/package/base-files/ar7-2.4/sbin/mount_root
@@ -0,0 +1,28 @@
+#!/bin/sh
+size=$(awk '/Mem:/ {l=5242880;print((s=$2/2)<l)?$2-l:s}' /proc/meminfo)
+mount none /tmp -t tmpfs -o size=$size
+
+if [ "$1" != "failsafe" ]; then
+ mtd unlock linux
+ mount | grep jffs2 >&-
+ if [ $? = 0 ] ; then
+ if [ $(cat /proc/mtd | wc -l) = 6 ]; then
+ mtd erase OpenWrt
+ else
+ mount -o remount,rw /dev/root /
+ fi
+ else
+ . /bin/firstboot
+ echo "switching to jffs2"
+ mount /dev/mtdblock/4 /jffs -t jffs2
+ pivot /jffs /rom || {
+ echo "jffs2 unusable; using ramdisk"
+ ramoverlay
+ }
+ fi
+fi
+
+mount none /tmp -t tmpfs -o remount,nosuid,nodev,mode=1777
+mkdir -p /dev/pts
+mount none /dev/pts -t devpts
+mount -t sysfs none /sys 2>&-
diff --git a/package/base-files/aruba-2.6/etc/config/network b/package/base-files/aruba-2.6/etc/config/network
new file mode 100644
index 0000000000..1d9b55b2d3
--- /dev/null
+++ b/package/base-files/aruba-2.6/etc/config/network
@@ -0,0 +1,11 @@
+# Network configuration file
+
+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 proto dhcp
diff --git a/package/base-files/au1000-2.6/etc/config/network b/package/base-files/au1000-2.6/etc/config/network
new file mode 100644
index 0000000000..9b65652f06
--- /dev/null
+++ b/package/base-files/au1000-2.6/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 type bridge
+ option ifname "eth0 ath0"
+ option proto static
+ option ipaddr 192.168.1.1
+ option netmask 255.255.255.0
diff --git a/package/base-files/au1000-2.6/sbin/mount_root b/package/base-files/au1000-2.6/sbin/mount_root
new file mode 100755
index 0000000000..718394ca4c
--- /dev/null
+++ b/package/base-files/au1000-2.6/sbin/mount_root
@@ -0,0 +1,26 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+mount none /proc -t proc
+size=$(awk '/Mem:/ {l=5242880;print((s=$2/2)<l)?$2-l:s}' /proc/meminfo)
+mount none /tmp -t tmpfs -o size=$size
+
+if [ "$1" != "failsafe" ]; then
+ mtd unlock filesystem
+ mount | grep jffs2 >&-
+ if [ $? = 0 ] ; then
+ if [ $(cat /proc/mtd | wc -l) = 6 ]; then
+ mtd erase filesystem
+ jffs2root --move
+ else
+ mount -o remount,rw /dev/root /
+ fi
+ else
+ . /bin/firstboot
+ fi
+fi
+
+mount none /tmp -t tmpfs -o remount,nosuid,nodev,mode=1777
+mkdir -p /dev/pts
+mount none /dev/pts -t devpts
+mount -t sysfs none /sys 2>&-
diff --git a/package/base-files/brcm-2.4/bin/firstboot b/package/base-files/brcm-2.4/bin/firstboot
new file mode 100755
index 0000000000..b65d3ee98b
--- /dev/null
+++ b/package/base-files/brcm-2.4/bin/firstboot
@@ -0,0 +1,90 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+rom=$(awk '/squashfs/ {print $2}' /proc/mounts)
+jffs=$(awk '/jffs2/ {print $2}' /proc/mounts)
+
+dupe() { # <new_root> <old_root>
+ cd $1
+ echo -n "creating directories... "
+ {
+ cd $2
+ find . -xdev -type d
+ echo "./dev ./jffs ./mnt ./proc ./tmp ./sys"
+ # 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*|\
+ ./etc/resolv.conf|\
+ ./usr/lib/ipkg/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
+ return 0
+ }
+}
+
+mountdp() { # <device> <mount_point> <ignored> <fs>
+ dev=$1; mnt=$2; shift 2; opt=$*
+ mount $dev $mnt $opt
+ dupe $mnt $rom
+ pivot $mnt /rom
+}
+
+ramoverlay() {
+ mkdir -p /tmp/root
+ mountdp /tmp/root /mnt -o bind
+}
+
+[ "${0##*/}" = "firstboot" ] && {
+ [ -z "$rom" ] && {
+ echo "You do not have a squashfs partition; aborting"
+ echo "(firstboot cannot be run on jffs2 based firmwares)"
+ exit 1
+ }
+
+ [ "$1" = "switch2jffs" ] && {
+ mtd erase OpenWrt
+ mount -o remount,ro none / # try to avoid fs changing while copying
+ mount -o bind / /mnt
+ mount /dev/mtdblock/4 /rom/jffs -t jffs2
+ echo -n "copying files ... "
+ cp -a /mnt/* /rom/jffs
+ umount /mnt
+ echo "done"
+ pivot /rom /mnt
+ mount -o move /mnt /tmp/root
+ pivot /jffs /rom
+ jffs2root --clean
+ exit 0
+ }
+
+ # script run manually
+ [ \! -z "$jffs" ] && {
+ echo "firstboot has already been run"
+ echo "jffs2 partition is mounted, only resetting files"
+ dupe $jffs $rom
+ exit 0
+ }
+
+ mtd erase OpenWrt
+ mountdp /dev/mtdblock/4 /jffs -t jffs2
+}
diff --git a/package/base-files/brcm-2.4/etc/config/wireless b/package/base-files/brcm-2.4/etc/config/wireless
new file mode 100644
index 0000000000..9dc4945e07
--- /dev/null
+++ b/package/base-files/brcm-2.4/etc/config/wireless
@@ -0,0 +1,14 @@
+# Copyright (C) 2006 OpenWrt.org
+
+config wifi-device wl0
+ option type broadcom
+ option channel 5
+
+config wifi-iface
+ option device wl0
+ option mode ap
+ option ssid OpenWrt
+ option hidden 0
+ option encryption none
+
+
diff --git a/package/base-files/brcm-2.4/etc/init.d/S05netconfig b/package/base-files/brcm-2.4/etc/init.d/S05netconfig
new file mode 100755
index 0000000000..71092da559
--- /dev/null
+++ b/package/base-files/brcm-2.4/etc/init.d/S05netconfig
@@ -0,0 +1,87 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+start() {
+ [ -e /etc/config/network ] && exit 0
+
+ mkdir -p /etc/config
+
+ (
+ if grep -E 'mtd0: 000(6|a)0000' /proc/mtd 2>&- >&-; then
+ # WGT634u
+ echo boardtype=wgt634u
+ else
+ strings /dev/mtdblock/3
+ fi
+ ) | awk '
+ function p(cfgname, name) {
+ if (c[name] != "") print " option " cfgname " \"" c[name] "\""
+ }
+
+ BEGIN {
+ FS="="
+ c["lan_ifname"]="eth0.0 wl0"
+ c["wan_ifname"]="eth0.1"
+ c["vlan0ports"]="1 2 3 4 5*"
+ c["vlan1ports"]="0 5"
+ }
+
+ ($1 == "boardnum") || ($1 == "boardtype") || ($1 == "boardflags") {
+ nvram[$1] = $2
+ }
+
+ END {
+ # v1 hardware
+ if (nvram["boardtype"] == "bcm94710dev") {
+ # Asus WL-500g
+ if (nvram["boardnum"] == "asusX") {
+ c["lan_ifname"]="eth0 eth1 wl0" # FIXME
+ c["wan_ifname"]=""
+ }
+ }
+ if (nvram["boardtype"] == "wgt634u") {
+ c["vlan0ports"] = "0 1 2 3 5*"
+ c["vlan1ports"] = "4 5"
+ c["lan_ifname"] = "eth0.0 ath0"
+ }
+ if ((nvram["boardtype"] == "0x0467") || (nvram["boardtype"] == "0x042f")) {
+ c["vlan0ports"] = "0 1 2 3 5*"
+ c["vlan1ports"] = "4 5"
+ }
+
+ # WAP54G
+ if ((nvram["boardnum"] == "2") || \
+ (nvram["boardnum"] == "1024")) {
+ c["lan_ifname"]="eth0 wl0"
+ c["wan_ifname"]=""
+ }
+
+ print "#### VLAN configuration "
+ print "config switch eth0"
+ p("vlan0", "vlan0ports")
+ p("vlan1", "vlan1ports")
+ 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")
+ 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")
+ print " option proto dhcp"
+ }' > /etc/config/network
+}
diff --git a/package/base-files/brcm-2.4/etc/preinit b/package/base-files/brcm-2.4/etc/preinit
new file mode 100755
index 0000000000..fb13e107e5
--- /dev/null
+++ b/package/base-files/brcm-2.4/etc/preinit
@@ -0,0 +1,13 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin
+mount none /proc -t proc
+
+[ -f /etc/preinit.arch ] && . /etc/preinit.arch
+[ -z "$FAILSAFE" ] || {
+ echo /bin/true > /proc/sys/kernel/hotplug
+ telnetd -l /bin/login <> /dev/null 2>&1
+}
+mount_root ${FAILSAFE:+failsafe}
+exec /sbin/init
diff --git a/package/base-files/brcm-2.4/sbin/mount_root b/package/base-files/brcm-2.4/sbin/mount_root
new file mode 100755
index 0000000000..ec82cd40fb
--- /dev/null
+++ b/package/base-files/brcm-2.4/sbin/mount_root
@@ -0,0 +1,34 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+is_dirty() {
+ grep Broadcom /proc/cpuinfo >&- || return 1
+ OFFSET="$(($(hexdump -v /dev/mtdblock/1 -s 20 -n 2 -e '"%d"')-1))"
+ return $(hexdump -v /dev/mtdblock/1 -s $OFFSET -n 1 -e '"%d"')
+}
+
+size=$(awk '/Mem:/ {l=5242880;print((s=$2/2)<l)?$2-l:s}' /proc/meminfo)
+mount none /tmp -t tmpfs -o size=$size
+
+if [ "$1" != "failsafe" ]; then
+ mtd unlock linux
+ mount | grep jffs2 >&-
+ if [ $? = 0 ] ; then
+ mount -o remount,rw /dev/root /
+ else
+ . /bin/firstboot
+ is_dirty
+ [ $? != 0 ] && {
+ echo "switching to jffs2"
+ mount /dev/mtdblock/4 /jffs -t jffs2
+ pivot /jffs /rom
+ } || {
+ echo "jffs2 unusable; using ramdisk"
+ ramoverlay
+ }
+ fi
+fi
+
+mount none /tmp -t tmpfs -o remount,nosuid,nodev,mode=1777
+mkdir -p /dev/pts
+mount none /dev/pts -t devpts
diff --git a/package/base-files/brcm-2.6/bin/firstboot b/package/base-files/brcm-2.6/bin/firstboot
new file mode 100755
index 0000000000..d37ce4f90b
--- /dev/null
+++ b/package/base-files/brcm-2.6/bin/firstboot
@@ -0,0 +1,90 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+rom=$(awk '/squashfs/ {print $2}' /proc/mounts)
+jffs=$(awk '/jffs2/ {print $2}' /proc/mounts)
+
+dupe() { # <new_root> <old_root>
+ cd $1
+ echo -n "creating directories... "
+ {
+ cd $2
+ find . -xdev -type d
+ echo "./dev ./jffs ./mnt ./proc ./tmp ./sys"
+ # 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*|\
+ ./etc/resolv.conf|\
+ ./usr/lib/ipkg/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
+ return 0
+ }
+}
+
+mountdp() { # <device> <mount_point> <ignored> <fs>
+ dev=$1; mnt=$2; shift 2; opt=$*
+ mount $dev $mnt $opt
+ dupe $mnt $rom
+ pivot $mnt /rom
+}
+
+ramoverlay() {
+ mkdir -p /tmp/root
+ mountdp /tmp/root /mnt -o bind
+}
+
+[ "${0##*/}" = "firstboot" ] && {
+ [ -z "$rom" ] && {
+ echo "You do not have a squashfs partition; aborting"
+ echo "(firstboot cannot be run on jffs2 based firmwares)"
+ exit 1
+ }
+
+ [ "$1" = "switch2jffs" ] && {
+ mtd erase OpenWrt
+ mount -o remount,ro none / # try to avoid fs changing while copying
+ mount -o bind / /mnt
+ mount /dev/mtdblock/4 /rom/jffs -t jffs2
+ echo -n "copying files ... "
+ cp -a /mnt/* /rom/jffs
+ umount /mnt
+ echo "done"
+ pivot /rom /mnt
+ mount -o move /mnt /tmp/root
+ pivot /jffs /rom
+ jffs2root --clean
+ exit 0
+ }
+
+ # script run manually
+ [ \! -z "$jffs" ] && {
+ echo "firstboot has already been run"
+ echo "jffs2 partition is mounted, only resetting files"
+ dupe $jffs $rom
+ exit 0
+ }
+
+ mtd erase OpenWrt
+ mountdp /dev/mtdblock/4 /jffs -t jffs2
+}
diff --git a/package/base-files/brcm-2.6/etc/init.d/S05netconfig b/package/base-files/brcm-2.6/etc/init.d/S05netconfig
new file mode 100755
index 0000000000..e37633e18f
--- /dev/null
+++ b/package/base-files/brcm-2.6/etc/init.d/S05netconfig
@@ -0,0 +1,87 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+start() {
+ [ -e /etc/config/network ] && exit 0
+
+ mkdir -p /etc/config
+
+ (
+ if grep -E 'mtd0: 000(6|a)0000' /proc/mtd 2>&- >&-; then
+ # WGT634u
+ echo boardtype=wgt634u
+ else
+ strings /dev/mtdblock/3
+ fi
+ ) | awk '
+ function p(cfgname, name) {
+ if (c[name] != "") print " option " cfgname " \"" c[name] "\""
+ }
+
+ BEGIN {
+ FS="="
+ c["lan_ifname"]="eth0.0 wl0"
+ c["wan_ifname"]="eth0.1"
+ c["vlan0ports"]="1 2 3 4 5*"
+ c["vlan1ports"]="0 5"
+ }
+
+ ($1 == "boardnum") || ($1 == "boardtype") || ($1 == "boardflags") {
+ nvram[$1] = $2
+ }
+
+ END {
+ # v1 hardware
+ if (nvram["boardtype"] == "bcm94710dev") {
+ # Asus WL-500g
+ if (nvram["boardnum"] == "asusX") {
+ c["lan_ifname"]="eth0 eth1 wl0" # FIXME
+ c["wan_ifname"]=""
+ }
+ }
+ if (nvram["boardtype"] == "wgt634u") {
+ c["vlan0ports"] = "0 1 2 3 5*"
+ c["vlan1ports"] = "4 5"
+ c["lan_ifname"] = "eth0.0 ath0"
+ }
+ if ((nvram["boardtype"] == "0x0467") || (nvram["boardtype"] == "0x042f")) {
+ c["vlan0ports"] = "0 1 2 3 5*"
+ c["vlan1ports"] = "4 5"
+ }
+
+ # WAP54G
+ if ((nvram["boardnum"] == "2") || \
+ (nvram["boardnum"] == "1024")) {
+ c["lan_ifname"]="eth0 wl0"
+ c["wan_ifname"]=""
+ }
+
+ print "#### VLAN configuration "
+ print "config switch eth0"
+ p("vlan0", "vlan0ports")
+ p("vlan1", "vlan1ports")
+ 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")
+ 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")
+ print " option proto dhcp"
+ }' > /etc/config/network
+}
diff --git a/package/base-files/brcm-2.6/etc/preinit b/package/base-files/brcm-2.6/etc/preinit
new file mode 100755
index 0000000000..fb13e107e5
--- /dev/null
+++ b/package/base-files/brcm-2.6/etc/preinit
@@ -0,0 +1,13 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin
+mount none /proc -t proc
+
+[ -f /etc/preinit.arch ] && . /etc/preinit.arch
+[ -z "$FAILSAFE" ] || {
+ echo /bin/true > /proc/sys/kernel/hotplug
+ telnetd -l /bin/login <> /dev/null 2>&1
+}
+mount_root ${FAILSAFE:+failsafe}
+exec /sbin/init
diff --git a/package/base-files/brcm-2.6/sbin/mount_root b/package/base-files/brcm-2.6/sbin/mount_root
new file mode 100755
index 0000000000..e3bdd3655c
--- /dev/null
+++ b/package/base-files/brcm-2.6/sbin/mount_root
@@ -0,0 +1,35 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+is_dirty() {
+ grep Broadcom /proc/cpuinfo >&- || return 1
+ OFFSET="$(($(hexdump -v /dev/mtdblock/1 -s 20 -n 2 -e '"%d"')-1))"
+ return $(hexdump -v /dev/mtdblock/1 -s $OFFSET -n 1 -e '"%d"')
+}
+
+size=$(awk '/Mem:/ {l=5242880;print((s=$2/2)<l)?$2-l:s}' /proc/meminfo)
+mount none /tmp -t tmpfs -o size=$size
+
+if [ "$1" != "failsafe" ]; then
+ mtd unlock linux
+ mount | grep jffs2 >&-
+ if [ $? = 0 ] ; then
+ mount -o remount,rw /dev/root /
+ else
+ . /bin/firstboot
+ is_dirty
+ [ $? != 0 ] && {
+ echo "switching to jffs2"
+ mount /dev/mtdblock/4 /jffs -t jffs2
+ pivot /jffs /rom
+ } || {
+ echo "jffs2 unusable; using ramdisk"
+ ramoverlay
+ }
+ fi
+fi
+
+mount none /tmp -t tmpfs -o remount,nosuid,nodev,mode=1777
+mkdir -p /dev/pts
+mount none /dev/pts -t devpts
+mount -t sysfs none /sys 2>&-
diff --git a/package/base-files/default/bin/ipcalc b/package/base-files/default/bin/ipcalc
new file mode 100755
index 0000000000..e8efa6b96c
--- /dev/null
+++ b/package/base-files/default/bin/ipcalc
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+awk -f /usr/lib/common.awk -f - $* <<EOF
+BEGIN {
+ ipaddr=ip2int(ARGV[1])
+ netmask=ip2int(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-1)
+ }
+}
+EOF
diff --git a/package/base-files/default/bin/login b/package/base-files/default/bin/login
new file mode 100755
index 0000000000..ff5d3660e4
--- /dev/null
+++ b/package/base-files/default/bin/login
@@ -0,0 +1,18 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+grep '^root:[^!]' /etc/passwd >&- 2>&-
+[ "$?" = "0" -a -z "$FAILSAFE" ] &&
+{
+ echo "Login failed."
+ exit 0
+} || {
+cat << EOF
+ === IMPORTANT ============================
+ Use 'passwd' to set your login password
+ this will disable telnet and enable SSH
+ ------------------------------------------
+EOF
+}
+
+exec /bin/ash --login
diff --git a/package/base-files/default/bin/uci b/package/base-files/default/bin/uci
new file mode 100755
index 0000000000..7f43549471
--- /dev/null
+++ b/package/base-files/default/bin/uci
@@ -0,0 +1,159 @@
+#!/bin/sh
+# Shell script for interacting with config files
+#
+# Copyright (C) 2006 by Fokus Fraunhofer <carsten.tittel@fokus.fraumhofer.de>
+# Copyright (C) 2006 by 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
+
+. /etc/functions.sh
+include /lib/config
+
+do_get() {
+ [ $# -ne 3 ] && {
+ uci_usage get
+ exit 1
+ }
+ local PACKAGE="$1"
+ local CONFIG="$2"
+ local OPTION="$3"
+
+ uci_load "$PACAKGE"
+ config_get "$CONFIG" "$OPTION"
+}
+
+do_set() {
+ [ $# -ne 4 ] && {
+ uci_usage set
+ exit 1
+ }
+ uci_set "$@"
+}
+
+do_add() {
+ [ $# -ne 3 ] && {
+ uci_usage add
+ exit 1
+ }
+ uci_add "$@"
+}
+
+do_rename() {
+ [ $# -ne 3 ] && {
+ uci_usage rename
+ exit 1
+ }
+ uci_rename "$@"
+}
+
+do_remove() {
+ [ $# -ne 3 -a $# -ne 2 ] && {
+ uci_usage rename
+ exit 1
+ }
+ uci_remove "$@"
+}
+
+do_commit() {
+ [ $# -ne 1 ] && {
+ uci_usage commit
+ exit 1
+ }
+ uci_commit "$1"
+}
+
+do_show() {
+ [ $# -gt 2 -o $# -lt 1 ] && {
+ uci_usage show
+ exit 1
+ }
+
+ PACKAGE="$1"
+ CONFIG="$2"
+ SECTION=""
+
+ config_cb() {
+ if [ -z "$CONFIG" -o "$CONFIG" = "$2" ]; then
+ append SECTION "$2"
+ option_cb() {
+ append "${CONFIG_SECTION}_VARS" "$1"
+ }
+ else
+ option_cb() {
+ return 0
+ }
+ fi
+ }
+
+ uci_load "$PACKAGE"
+
+ for section in $SECTION; do
+ config_get type "$section" TYPE
+ [ -z "$type" ] && continue
+ echo "@$section=$type"
+ eval "VARS=\"\${${section}_VARS}\""
+ for var in $VARS; do
+ config_get val "$section" "$var"
+ [ -n "$val" ] && {
+ echo "${section}.${var}=${val}"
+ config_set "$section" "$var" ""
+ }
+ done
+ config_set "$section" TYPE ""
+ done
+}
+
+uci_usage() {
+ case "$1" in
+ show) echo "$0 show <package> [<config>]";;
+ get) echo "$0 get <package> <config> <option>";;
+ set) echo "$0 set <package> <config> <option> <value>";;
+ add) echo "$0 add <package> <type> <config>";;
+ del) echo "$0 del <package> <config> [<option>]";;
+ rename) echo "$0 rename <package> <config> <name>";;
+ commit) echo "$0 commit <package>";;
+ *)
+ echo "Syntax: $0 <command> <arguments...>"
+ echo
+ uci_usage show
+ uci_usage get
+ uci_usage set
+ uci_usage add
+ uci_usage del
+ uci_usage rename
+ uci_usage commit
+ echo
+ exit 1
+ ;;
+ esac
+}
+
+if [ $# -eq 0 ] ; then
+ uci_usage
+ exit 0
+fi
+CMD="$1"
+shift
+case "$CMD" in
+ set) do_set "$@";;
+ add) do_add "$@";;
+ del) do_remove "$@";;
+ rename) do_rename "$@";;
+ get) do_get "$@";;
+ show) do_show "$@";;
+ commit) do_commit "$@";;
+ *) uci_usage;;
+esac
+exit 0
diff --git a/package/base-files/default/etc/banner b/package/base-files/default/etc/banner
new file mode 100644
index 0000000000..c2fbc12680
--- /dev/null
+++ b/package/base-files/default/etc/banner
@@ -0,0 +1,10 @@
+ _______ ________ __
+ | |.-----.-----.-----.| | | |.----.| |_
+ | - || _ | -__| || | | || _|| _|
+ |_______|| __|_____|__|__||________||__| |____|
+ |__| W I R E L E S S F R E E D O M
+ KAMIKAZE (bleeding edge, $R) -------------------
+ * 10 oz Vodka Shake well with ice and strain
+ * 10 oz Triple sec mixture into 10 shot glasses.
+ * 10 oz lime juice Salute!
+ ---------------------------------------------------
diff --git a/package/base-files/default/etc/config/network b/package/base-files/default/etc/config/network
new file mode 100644
index 0000000000..1d5ded3728
--- /dev/null
+++ b/package/base-files/default/etc/config/network
@@ -0,0 +1,13 @@
+# 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 proto static
+ option ipaddr 192.168.1.1
+ option netmask 255.255.255.0
diff --git a/package/base-files/default/etc/functions.sh b/package/base-files/default/etc/functions.sh
new file mode 100755
index 0000000000..9c3057ed00
--- /dev/null
+++ b/package/base-files/default/etc/functions.sh
@@ -0,0 +1,119 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2006 Fokus Fraunhofer <carsten.tittel@fokus.fraunhofer.de>
+
+alias debug=${DEBUG:-:}
+
+# newline
+N="
+"
+
+_C=0
+
+# valid interface?
+if_valid () (
+ ifconfig "$1" >&- 2>&- ||
+ [ "${1%%[0-9]}" = "br" ] ||
+ { debug "# missing interface '$1' ignored"; false; }
+)
+
+hotplug_dev() {
+ env -i ACTION=$1 INTERFACE=$2 /sbin/hotplug net
+}
+
+append() {
+ local var="$1"
+ local value="$2"
+ local sep="${3:- }"
+ eval "export ${var}=\"\${${var}:+\${${var}}${value:+$sep}}\$value\""
+}
+
+reset_cb() {
+ config_cb() {
+ return 0
+ }
+ option_cb() {
+ return 0
+ }
+}
+reset_cb
+
+config () {
+ local cfgtype="$1"
+ local name="$2"
+ _C=$(($_C + 1))
+ name="${name:-cfg${_C}}"
+ config_cb "$cfgtype" "$name"
+ export CONFIG_SECTION="$name"
+ export CONFIG_${CONFIG_SECTION}_TYPE="$cfgtype"
+}
+
+option () {
+ local varname="$1"; shift
+ export CONFIG_${CONFIG_SECTION}_${varname}="$*"
+ option_cb "$varname" "$*"
+}
+
+config_rename() {
+ local OLD="$1"
+ local NEW="$2"
+ local oldsetting
+ local newvar
+
+ [ -z "$OLD" -o -z "$NEW" ] && return
+ for oldsetting in `set | grep ^CONFIG_${OLD}_ | \
+ sed -e 's/\(.*\)=.*$/\1/'` ; do
+ newvar="CONFIG_${NEW}_${oldsetting##CONFIG_${OLD}_}"
+ eval "${newvar}=\${$oldsetting}"
+ unset "$oldsetting"
+ done
+ [ "$CONFIG_SECTION" = "$OLD" ] && CONFIG_SECTION="$NEW"
+}
+
+config_unset() {
+ config_set "$1" "$2" ""
+}
+
+config_clear() {
+ [ -z "$CONFIG_SECTION" ] && return
+ for oldsetting in `set | grep ^CONFIG_${CONFIG_SECTION}_ | \
+ sed -e 's/\(.*\)=.*$/\1/'` ; do
+ unset $oldsetting
+ done
+ unset CONFIG_SECTION
+}
+
+config_load() {
+ local DIR="./"
+ _C=0
+ [ \! -e "$1" -a -e "/etc/config/$1" ] && {
+ DIR="/etc/config/"
+ }
+ [ -e "$DIR$1" ] && {
+ CONFIG_FILENAME="$DIR$1"
+ . ${CONFIG_FILENAME}
+ } || return 1
+ ${CD:+cd -} >/dev/null
+ ${CONFIG_SECTION:+config_cb}
+}
+
+config_get() {
+ case "$3" in
+ "") eval "echo \"\${CONFIG_${1}_${2}}\"";;
+ *) eval "$1=\"\${CONFIG_${2}_${3}}\"";;
+ esac
+}
+
+config_set() {
+ export CONFIG_${1}_${2}="${3}"
+}
+
+load_modules() {
+ sed 's/^[^#]/insmod &/' $* | ash 2>&- || :
+}
+
+include() {
+ for file in $(ls $1/*.sh 2>/dev/null); do
+ . $file
+ done
+}
diff --git a/package/base-files/default/etc/group b/package/base-files/default/etc/group
new file mode 100644
index 0000000000..c4e77f316a
--- /dev/null
+++ b/package/base-files/default/etc/group
@@ -0,0 +1,2 @@
+root:x:0:
+nogroup:x:65534:
diff --git a/package/base-files/default/etc/hosts b/package/base-files/default/etc/hosts
new file mode 100644
index 0000000000..ce138ec1e6
--- /dev/null
+++ b/package/base-files/default/etc/hosts
@@ -0,0 +1 @@
+127.0.0.1 localhost OpenWrt
diff --git a/package/base-files/default/etc/hotplug.d/block/01-mount b/package/base-files/default/etc/hotplug.d/block/01-mount
new file mode 100755
index 0000000000..b6275e5a28
--- /dev/null
+++ b/package/base-files/default/etc/hotplug.d/block/01-mount
@@ -0,0 +1,26 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+DEV=${DEVPATH##*/}
+{
+echo "ACTION=$ACTION DEVPATH=$DEVPATH $0 $*"
+case "$ACTION" in
+add)
+ echo -ne "waiting for $DEV"
+ while [ ! -b /dev/$DEV ]; do {
+ echo -ne "."
+ sleep 1
+ time=$((time+1)); [ $time -gt 10 ] && break
+ }; done
+
+ [ ${DEV%%[0-9]} != ${DEV} ] && {
+ mkdir -p /tmp/$DEV
+ mount /dev/$DEV /tmp/$DEV -t auto -o sync
+ }
+ ;;
+remove)
+ umount /tmp/$DEV
+ rm -rf /dev/$DEV /tmp/$DEV
+ ;;
+esac
+} 2>&1 | logger
diff --git a/package/base-files/default/etc/hotplug.d/net/10-net b/package/base-files/default/etc/hotplug.d/net/10-net
new file mode 100644
index 0000000000..4e5c3041b5
--- /dev/null
+++ b/package/base-files/default/etc/hotplug.d/net/10-net
@@ -0,0 +1,28 @@
+# Copyright (C) 2006 OpenWrt.org
+
+include /lib/network
+
+addif() {
+ scan_interfaces
+ setup_interface "$INTERFACE"
+
+ # find all vlan configurations for this interface and set them up as well
+ for ifc in $interfaces; do
+ config_get iftype "$ifc" type
+ config_get ifs "$ifc" device
+ for dev in $ifs; do
+ [ "${dev%%\.*}" = "$INTERFACE" -a "$dev" != "$INTERFACE" ] && {
+ add_vlan "$dev"
+ }
+ done
+ done
+}
+
+case "$ACTION" in
+ add|register)
+ case "$PHYSDEVDRIVER" in
+ natsemi) sleep 1;;
+ esac
+ addif
+ ;;
+esac
diff --git a/package/base-files/default/etc/hotplug.d/usb/01-ln b/package/base-files/default/etc/hotplug.d/usb/01-ln
new file mode 100755
index 0000000000..f9eda02988
--- /dev/null
+++ b/package/base-files/default/etc/hotplug.d/usb/01-ln
@@ -0,0 +1,33 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+case "$ACTION" in
+add)
+ [ -f /sys/${DEVPATH}/idVendor -a "$(cat /sys/${DEVPATH}/idVendor)" -ne "0000" ] && {
+ cd /sys/${DEVPATH}
+
+ NUM=${DEVPATH##*/}
+ HOST=$(find ${NUM}:*/host* -type d)
+ HOST=${HOST##*/host}
+
+ echo -ne "waiting for disk"
+
+ while [ ! -d "/dev/scsi/host${HOST}/bus0/target0/lun0" ]; do {
+ echo -ne "."
+ sleep 1;
+ time=$((time+1)); [ $time -gt 10 ] && break
+ }; done
+ echo
+
+ cd /sys/bus/scsi/devices/${HOST}\:0\:0\:0
+ for BLOCK in block:* ; do {
+ cd ${BLOCK}
+ BLOCK=${BLOCK##block\:}
+ ln -sf /dev/scsi/host${HOST}/bus0/target0/lun0/disc /dev/${BLOCK}
+ for DEV in ${BLOCK}*; do {
+ ln -sf /dev/scsi/host${HOST}/bus0/target0/lun0/part${DEV##$BLOCK} /dev/$DEV
+ }; done
+ }; done
+ } 2>&1 | logger
+ ;;
+esac
diff --git a/package/base-files/default/etc/init.d/S10boot b/package/base-files/default/etc/init.d/S10boot
new file mode 100755
index 0000000000..77b5ca72d5
--- /dev/null
+++ b/package/base-files/default/etc/init.d/S10boot
@@ -0,0 +1,25 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+start() {
+ [ -f /proc/mounts ] || /sbin/mount_root
+ [ -f /proc/jffs2_bbc ] && echo "S" > /proc/jffs2_bbc
+ vconfig set_name_type DEV_PLUS_VID_NO_PAD
+
+ HOSTNAME=${wan_hostname%%.*}
+ echo ${HOSTNAME:=OpenWrt}>/proc/sys/kernel/hostname
+
+ mkdir -p /var/run
+ mkdir -p /var/log
+ mkdir -p /var/lock
+ touch /var/log/wtmp
+ touch /var/log/lastlog
+ [ "$FAILSAFE" = "true" ] && touch /tmp/.failsafe
+
+ # manually trigger hotplug before loading modules
+ for iface in $(awk -F: '/:/ {print $1}' /proc/net/dev); do
+ /usr/bin/env -i ACTION=add INTERFACE="$iface" /sbin/hotplug net
+ done
+
+ load_modules /etc/modules /etc/modules.d/*
+}
diff --git a/package/base-files/default/etc/init.d/S40network b/package/base-files/default/etc/init.d/S40network
new file mode 100755
index 0000000000..be045045e7
--- /dev/null
+++ b/package/base-files/default/etc/init.d/S40network
@@ -0,0 +1,11 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+start() {
+ setup_switch() { return 0; }
+
+ include /lib/network
+ setup_switch
+ /sbin/wifi
+}
+
diff --git a/package/base-files/default/etc/init.d/S50httpd b/package/base-files/default/etc/init.d/S50httpd
new file mode 100755
index 0000000000..a05b10c094
--- /dev/null
+++ b/package/base-files/default/etc/init.d/S50httpd
@@ -0,0 +1,10 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+start() {
+ [ -d /www ] && httpd -p 80 -h /www -r OpenWrt
+}
+
+stop() {
+ killall httpd
+}
diff --git a/package/base-files/default/etc/init.d/S50telnet b/package/base-files/default/etc/init.d/S50telnet
new file mode 100755
index 0000000000..228eac2b62
--- /dev/null
+++ b/package/base-files/default/etc/init.d/S50telnet
@@ -0,0 +1,10 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+start() {
+ if awk -F: '/^root:/ && $2 !~ /\!/ {exit 1}' /etc/passwd 2>/dev/null; then telnetd -l /bin/login; fi
+}
+
+stop() {
+ killall telnetd
+}
diff --git a/package/base-files/default/etc/init.d/S60cron b/package/base-files/default/etc/init.d/S60cron
new file mode 100755
index 0000000000..a450c36dd2
--- /dev/null
+++ b/package/base-files/default/etc/init.d/S60cron
@@ -0,0 +1,12 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+start () {
+ mkdir -p /var/spool/cron
+ ln -s /etc/crontabs /var/spool/cron/crontabs
+ crond -c /etc/crontabs
+}
+
+stop() {
+ killall crond
+}
diff --git a/package/base-files/default/etc/init.d/rcS b/package/base-files/default/etc/init.d/rcS
new file mode 100755
index 0000000000..7fae7f5b05
--- /dev/null
+++ b/package/base-files/default/etc/init.d/rcS
@@ -0,0 +1,26 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+${FAILSAFE:+exit}
+
+# FIXME: add logging configuration
+#[ -f /etc/config/network ] && . /etc/config/network
+#eval $(ipcalc "$log_ipaddr")
+#[ "$log_ipaddr" = "$IP" ] || log_ipaddr=""
+syslogd -C 16 #${log_ipaddr:+-L -R $log_ipaddr}
+klogd
+
+(
+ for i in /etc/init.d/S*; do
+ $i start 2>&1
+ done
+
+ sysctl -p >&-
+
+ # automagically run firstboot
+ { mount|grep "on / type tmpfs" 1>&-; } && {
+ lock /tmp/.switch2jffs
+ firstboot switch2jffs
+ lock -u /tmp/.switch2jffs
+ }
+) | logger -s -p 6 -t '' &
diff --git a/package/base-files/default/etc/inittab b/package/base-files/default/etc/inittab
new file mode 100644
index 0000000000..39e134cb16
--- /dev/null
+++ b/package/base-files/default/etc/inittab
@@ -0,0 +1,3 @@
+::sysinit:/etc/init.d/rcS
+tts/0::askfirst:/bin/ash --login
+#tts/1::askfirst:/bin/ash --login
diff --git a/package/base-files/default/etc/ipkg.conf b/package/base-files/default/etc/ipkg.conf
new file mode 100644
index 0000000000..2931d2cf80
--- /dev/null
+++ b/package/base-files/default/etc/ipkg.conf
@@ -0,0 +1,3 @@
+src snapshots http://openwrt.org/downloads/snapshots/$S/packages
+dest root /
+dest ram /tmp
diff --git a/package/base-files/default/etc/nvram.sh b/package/base-files/default/etc/nvram.sh
new file mode 100644
index 0000000000..ddbd88b52f
--- /dev/null
+++ b/package/base-files/default/etc/nvram.sh
@@ -0,0 +1,19 @@
+#!/bin/ash
+# Copyright (C) 2006 OpenWrt.org
+
+
+# allow env to override nvram
+nvram () {
+ if [ -x /usr/sbin/nvram ]; then
+ case $1 in
+ get) eval "echo \${$2:-\$(/usr/sbin/nvram get $2)}";;
+ *) /usr/sbin/nvram $*;;
+ esac
+ else
+ case $1 in
+ get) eval "echo \${$2:-\${DEFAULT_$2}}";;
+ *);;
+ esac
+ fi
+}
+
diff --git a/package/base-files/default/etc/passwd b/package/base-files/default/etc/passwd
new file mode 100644
index 0000000000..3b660a0d4e
--- /dev/null
+++ b/package/base-files/default/etc/passwd
@@ -0,0 +1,2 @@
+root:!:0:0:root:/tmp:/bin/ash
+nobody:*:65534:65534:nobody:/var:/bin/false
diff --git a/package/base-files/default/etc/profile b/package/base-files/default/etc/profile
new file mode 100644
index 0000000000..ae514b0924
--- /dev/null
+++ b/package/base-files/default/etc/profile
@@ -0,0 +1,12 @@
+#!/bin/sh
+[ -f /etc/banner ] && cat /etc/banner
+
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin
+export PS1='\u@\h:\w\$ '
+
+alias more=less
+[ -x /usr/bin/vim ] || alias vim=vi
+
+arp() { cat /proc/net/arp; }
+ldd() { LD_TRACE_LOADED_OBJECTS=1 $*; }
+reboot() { ifdown wan 2>&1 >/dev/null ; /sbin/reboot; }
diff --git a/package/base-files/default/etc/protocols b/package/base-files/default/etc/protocols
new file mode 100644
index 0000000000..53fecb6d3c
--- /dev/null
+++ b/package/base-files/default/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/default/etc/rc.common b/package/base-files/default/etc/rc.common
new file mode 100755
index 0000000000..20d1efa402
--- /dev/null
+++ b/package/base-files/default/etc/rc.common
@@ -0,0 +1,73 @@
+#!/bin/sh
+. /etc/functions.sh
+
+start() {
+ return 0
+}
+
+stop() {
+ return 0
+}
+
+reload() {
+ return 1
+}
+
+restart() {
+ stop
+ start
+}
+
+boot() {
+ start
+}
+
+shutdown() {
+ return 0
+}
+
+disable() {
+ rm -f /etc/rc.d/${initscript##*/}
+}
+
+enable() {
+ disable
+ ln -s /etc/init.d/${initscript##*/} /etc/rc.d/${initscript##*/}
+}
+
+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)
+$EXTRA_HELP
+EOF
+}
+
+initscript="$1"
+action="$2"
+
+. "$initscript"
+
+cmds=
+for cmd in $EXTRA_COMMANDS; do
+ cmds="$cmd) $cmd;;"
+done
+eval "case \"\$action\" in
+ start) start;;
+ stop) stop;;
+ reload) reload || restart;;
+ restart) restart;;
+ boot) boot;;
+ shutdown) shutdown;;
+ $cmds
+ *) help;;
+esac"
diff --git a/package/base-files/default/etc/resolv.conf b/package/base-files/default/etc/resolv.conf
new file mode 100644
index 0000000000..9617eacda7
--- /dev/null
+++ b/package/base-files/default/etc/resolv.conf
@@ -0,0 +1,2 @@
+nameserver 127.0.0.1
+search lan
diff --git a/package/base-files/default/etc/shells b/package/base-files/default/etc/shells
new file mode 100644
index 0000000000..006aa38ced
--- /dev/null
+++ b/package/base-files/default/etc/shells
@@ -0,0 +1 @@
+/bin/ash
diff --git a/package/base-files/default/etc/sysctl.conf b/package/base-files/default/etc/sysctl.conf
new file mode 100644
index 0000000000..e60038cf35
--- /dev/null
+++ b/package/base-files/default/etc/sysctl.conf
@@ -0,0 +1,12 @@
+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_fin_timeout=30
+net.ipv4.tcp_keepalive_time=120
+net.ipv4.tcp_syncookies=1
+net.ipv4.tcp_timestamps=0
+net.ipv4.ip_conntrack_tcp_timeouts="300 43200 120 60 120 120 10 60 30 120"
+net.ipv4.ip_conntrack_udp_timeouts="60 180"
diff --git a/package/base-files/default/lib/config/uci-update.awk b/package/base-files/default/lib/config/uci-update.awk
new file mode 100644
index 0000000000..efa8758507
--- /dev/null
+++ b/package/base-files/default/lib/config/uci-update.awk
@@ -0,0 +1,160 @@
+# Configuration update functions
+#
+# Copyright (C) 2006 by Fokus Fraunhofer <carsten.tittel@fokus.fraunhofer.de>
+# Copyright (C) 2006 by 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
+
+
+function read_file(filename, result) {
+ while ((getline <filename) == 1) {
+ result = result $0 "\n"
+ }
+ gsub(/\n*$/, "", result)
+ return result
+}
+
+function cmd2option(str, tmp) {
+ if (match(str,"=")!=0) {
+ res = "\toption " substr(str,1,RSTART-1) "\t'" substr(str,RSTART+1) "'"
+ } else {
+ res= ""
+ }
+ return res
+}
+
+function cmd2config(atype, aname) {
+ return "config \"" atype "\" \"" aname "\""
+}
+
+function update_config(cfg, update, \
+ lines, line, l, n, i, i2, section, scnt, remove, tmp, aidx, rest) {
+ scnt = 1
+ linecnt=split(cfg "\n", lines, "\n")
+
+ cfg = ""
+ for (n = 1; n < linecnt; n++) {
+ # stupid parser for quoted arguments (e.g. for the type string).
+ # not to be used to gather variable values (backslash escaping doesn't work)
+ line = lines[n]
+ gsub(/^[ \t]*/, "", line)
+ gsub(/#.*$/, "", line)
+ i2 = 1
+ delete l
+ rest = line
+ while (length(rest)) {
+ if (match(rest, /[ \t\"]+/)) {
+ if (RSTART>1) {
+ l[i2] = substr(rest,1,RSTART-1)
+ i2++
+ }
+ aidx=index(rest,"\"")
+ if (aidx>=RSTART && aidx<=RSTART+RLENGTH) {
+ rest=substr(rest,aidx+1)
+ # find the end of the string
+ match(rest,/\"/)
+ l[i2]=substr(rest,1,RSTART-1)
+ i2++
+ }
+ rest=substr(rest,RSTART+RLENGTH)
+ } else {
+ l[i2] = rest
+ i2++
+ rest = ""
+ }
+ }
+ line = lines[n]
+
+ # when a command wants to set a config value for the current
+ # section and a blank line is encountered before an option with
+ # the same name, insert it here to maintain some coherency between
+ # manually and automatically created option lines
+ # if an option with the same name appears after this point, simply
+ # ignore it, because it is already set.
+ if ((section != "") && (l[1] != "option")) {
+ if (line ~ /^[ \t]*$/) {
+ if (update ~ "^" section "\\.") {
+ gsub("^" section ".", "", update)
+ cfg = cfg cmd2option(update) "\n"
+ gsub(/=.*$/, "", update)
+ update = "-" section "." update
+ }
+ }
+ }
+
+ if (l[1] == "config") {
+ # look for all unset values
+ if (section != "") {
+ flag=0
+ if (update ~ "^" section "\\.") {
+ flag=1
+ gsub("^" section ".", "", update)
+ cfg = cfg cmd2option(update) "\n"
+
+ update = "-" section "." update
+ }
+ if (flag!=0) cfg = cfg "\n"
+ }
+
+ remove = ""
+ section = l[3]
+ if (!length(section)) {
+ section = "cfg" scnt
+ }
+ scnt++
+ if (update == "-" section) {
+ remove = "section"
+ update = ""
+ } else if (update ~ "^@" section "=") {
+ update = ""
+ } else if (update ~ "^&" section "=") {
+ gsub("^&" section "=", "", update)
+ line = cmd2config(l[2],update)
+ update = ""
+ }
+ }
+ if (remove == "option") remove = ""
+ if (l[1] == "option") {
+ if (update ~ "^-" section "\\." l[2] "$") remove = "option"
+ # if a supplied config value already exists, replace the whole line
+ if (match(update, "^" section "." l[2] "=")) {
+ gsub("^" section ".", "", update)
+ line = cmd2option(update)
+ update = ""
+ }
+ }
+ if (remove == "") cfg = cfg line "\n"
+ }
+
+ # any new options for the last section??
+ if (section != "") {
+ if (update ~ "^" section "\\.") {
+ gsub("^" section ".", "", update)
+ cfg = cfg cmd2option(update) "\n"
+
+ update = "-" section "." update
+ }
+ }
+
+ if (update ~ "^@") {
+ # new section
+ section = stype = substr(update,2)
+ gsub(/=.*$/,"",section)
+ gsub(/^.*=/,"",stype)
+ cfg = cfg "\nconfig \"" stype "\" \"" section "\"\n"
+ }
+
+ return cfg
+}
diff --git a/package/base-files/default/lib/config/uci.sh b/package/base-files/default/lib/config/uci.sh
new file mode 100755
index 0000000000..ccd6ee57ba
--- /dev/null
+++ b/package/base-files/default/lib/config/uci.sh
@@ -0,0 +1,138 @@
+#!/bin/sh
+# Shell script defining macros for manipulating config files
+#
+# Copyright (C) 2006 by Fokus Fraunhofer <carsten.tittel@fokus.fraumhofer.de>
+# Copyright (C) 2006 by 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
+
+uci_load() {
+ config_load "$PACKAGE"
+ local PACKAGE_BASE="$(basename "$PACKAGE")"
+ [ -f "/tmp/.uci/${PACKAGE_BASE}" ] && {
+ . "/tmp/.uci/${PACKAGE_BASE}"
+ config_cb
+ }
+}
+
+uci_do_update() {
+ local FILENAME="$1"
+ local UPDATE="$2"
+ awk -f /lib/config/uci-update.awk -f - <<EOF
+BEGIN {
+ config = read_file("$FILENAME")
+ $UPDATE
+ print config
+}
+EOF
+}
+
+uci_add_update() {
+ local PACKAGE="$1"
+ local UPDATE="$2"
+ local PACKAGE_BASE="$(basename "$PACKAGE")"
+
+ # FIXME: add locking?
+ mkdir -p "/tmp/.uci"
+ echo "$UPDATE" >> "/tmp/.uci/${PACKAGE_BASE}"
+}
+
+uci_set() {
+ local PACKAGE="$1"
+ local CONFIG="$2"
+ local OPTION="$3"
+ local VALUE="$4"
+
+ ( # spawn a subshell so you don't mess up the current environment
+ uci_load "$PACKAGE"
+ config_get type "$CONFIG" TYPE
+ [ -z "$type" ]
+ ) || uci_add_update "$PACKAGE" "CONFIG_SECTION='$CONFIG'${N}option '$OPTION' '$VALUE'"
+}
+
+uci_add() {
+ local PACKAGE="$1"
+ local TYPE="$2"
+ local CONFIG="$3"
+
+ uci_add_update "$PACKAGE" "config '$TYPE' '$CONFIG'"
+}
+
+uci_rename() {
+ local PACKAGE="$1"
+ local CONFIG="$2"
+ local VALUE="$3"
+
+ uci_add_update "$PACKAGE" "config_rename '$CONFIG' '$VALUE'"
+}
+
+uci_remove() {
+ local PACKAGE="$1"
+ local CONFIG="$2"
+ local OPTION="$3"
+
+ if [ -z "$OPTION" ]; then
+ uci_add_update "$PACKAGE" "config_clear '$CONFIG'"
+ else
+ uci_add_update "$PACKAGE" "config_unset '$CONFIG' '$OPTION'"
+ fi
+}
+
+uci_commit() {
+ local PACKAGE="$1"
+ local PACKAGE_BASE="$(basename "$PACKAGE")"
+
+ mkdir -p /tmp/.uci
+ lock "/tmp/.uci/$PACKAGE_BASE.lock"
+ [ -f "/tmp/.uci/$PACKAGE_BASE" ] && (
+ updatestr=""
+
+ # replace handlers
+ config() {
+ append updatestr "config = update_config(config, \"@$2=$1\")" "$N"
+ }
+ option() {
+ append updatestr "config = update_config(config, \"$CONFIG_SECTION.$1=$2\")" "$N"
+ }
+ config_rename() {
+ append updatestr "config = update_config(config, \"&$1=$2\")" "$N"
+ }
+ config_unset() {
+ append updatestr "config = update_config(config, \"-$1.$2\")" "$N"
+ }
+ config_clear() {
+ append updatestr "config = update_config(config, \"-$1\")" "$N"
+ }
+
+ . "/tmp/.uci/$PACKAGE_BASE"
+
+ # completely disable handlers so that they don't get in the way
+ config() {
+ return 0
+ }
+ option() {
+ return 0
+ }
+
+ config_load "$PACKAGE" || CONFIG_FILENAME="$ROOT/etc/config/$PACKAGE_BASE"
+ uci_do_update "$CONFIG_FILENAME" "$updatestr" > "/tmp/.uci/$PACKAGE_BASE.new" && {
+ mv -f "/tmp/.uci/$PACKAGE_BASE.new" "$CONFIG_FILENAME" && \
+ rm -f "/tmp/.uci/$PACKAGE_BASE"
+ }
+ )
+ lock -u "/tmp/.uci/$PACKAGE_BASE.lock"
+}
+
+
diff --git a/package/base-files/default/lib/network/config.sh b/package/base-files/default/lib/network/config.sh
new file mode 100755
index 0000000000..18f794a31b
--- /dev/null
+++ b/package/base-files/default/lib/network/config.sh
@@ -0,0 +1,143 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+# DEBUG="echo"
+
+find_config() {
+ local iftype device iface ifaces ifn
+ for ifn in $interfaces; do
+ config_get iftype "$ifn" type
+ config_get iface "$ifn" ifname
+ case "$iftype" in
+ bridge) config_get ifaces "$ifn" ifnames;;
+ esac
+ config_get device "$ifn" device
+ for ifc in $device $iface $ifaces; do
+ [ "$ifc" = "$1" ] && {
+ echo "$ifn"
+ return 0
+ }
+ done
+ done
+
+ return 1;
+}
+
+scan_interfaces() {
+ local mode iftype iface ifname device
+ interfaces=
+ config_cb() {
+ config_get iftype "$CONFIG_SECTION" TYPE
+ case "$iftype" in
+ interface)
+ config_get proto "$CONFIG_SECTION" proto
+ append interfaces "$CONFIG_SECTION"
+ config_get iftype "$CONFIG_SECTION" type
+ config_get ifname "$CONFIG_SECTION" ifname
+ config_set "$CONFIG_SECTION" device "$ifname"
+ case "$iftype" in
+ bridge)
+ config_set "$CONFIG_SECTION" ifnames "$ifname"
+ config_set "$CONFIG_SECTION" ifname br-"$CONFIG_SECTION"
+ ;;
+ esac
+ ( type "scan_$proto" ) >/dev/null 2>/dev/null && eval "scan_$proto '$CONFIG_SECTION'"
+ ;;
+ esac
+ }
+ config_load network
+}
+
+add_vlan() {
+ local vif="${1%\.*}"
+
+ [ "$1" = "$vif" ] || ifconfig "$1" >/dev/null 2>/dev/null || {
+ ifconfig "$vif" up 2>/dev/null >/dev/null || add_vlan "$vif"
+ $DEBUG vconfig add "$vif" "${1##*\.}"
+ }
+}
+
+setup_interface() {
+ local iface="$1"
+ local config="$2"
+ local proto
+
+ [ -n "$config" ] || {
+ config=$(find_config "$iface")
+ [ "$?" = 0 ] || return 1
+ }
+
+ proto="${3:-$(config_get "$config" proto)}"
+ config_get iftype "$config" type
+
+ # Setup VLAN interfaces
+ add_vlan "$iface"
+
+ # Setup bridging
+ case "$iftype" in
+ bridge)
+ ifconfig "$iface" up 2>/dev/null >/dev/null
+ ifconfig "br-$config" 2>/dev/null >/dev/null && {
+ $DEBUG brctl addif "br-$config" "$iface"
+ return 0
+ } || {
+ $DEBUG brctl addbr "br-$config"
+ $DEBUG brctl setfd "br-$config" 0
+ $DEBUG brctl addif "br-$config" "$iface"
+ iface="br-$config"
+ }
+ ;;
+ esac
+
+ # Interface settings
+ config_get mtu "$config" mtu
+ $DEBUG ifconfig "$iface" ${mtu:+mtu $mtu} up
+
+ pidfile="/var/run/$iface.pid"
+ case "$proto" in
+ static)
+ config_get ipaddr "$config" ipaddr
+ config_get netmask "$config" netmask
+ [ -z "$ipaddr" -o -z "$netmask" ] && return 1
+
+ config_get ip6addr "$config" ip6addr
+ config_get gateway "$config" gateway
+ config_get dns "$config" dns
+
+ $DEBUG ifconfig "$iface" "$ipaddr" netmask "$netmask"
+ [ -z "$gateway" ] || route add default gw "$gateway"
+ [ -z "$dns" -o -f /tmp/resolv.conf ] || {
+ for ns in $dns; do
+ echo "nameserver $ns" >> /tmp/resolv.conf
+ done
+ }
+
+ env -i ACTION="ifup" INTERFACE="config" DEVICE="$iface" PROTO=static /sbin/hotplug "iface" &
+ ;;
+ dhcp)
+ pid="$(cat "$pidfile" 2>/dev/null)"
+ [ -n "$pid" -a -d "/proc/$pid" ] && kill -9 "$pid"
+
+ config_get ipaddr "$config" ipaddr
+ config_get netmask "$config" netmask
+ config_get hostname "$config" hostname
+ config_get proto1 "$config" proto
+
+ [ -z "$ipaddr" ] || \
+ $DEBUG ifconfig "$iface" "$ipaddr" ${netmask:+netmask "$netmask"}
+
+ # don't stay running in background if dhcp is not the main proto on the interface (e.g. when using pptp)
+ [ "$proto1" != "$proto" ] && dhcpopts="-n -q"
+ $DEBUG udhcpc -i "$iface" ${ipaddr:+-r $ipaddr} ${hostname:+-H $hostname} -b -p "$pidfile" ${dhcpopts:- -R &}
+ ;;
+ *)
+ if ( eval "type setup_interface_$proto" ) >/dev/null 2>/dev/null; then
+ eval "setup_interface_$proto '$iface' '$config' '$proto'"
+ else
+ echo "Interface type $proto not supported."
+ return 1
+ fi
+ ;;
+ esac
+}
+
diff --git a/package/base-files/default/rom/note b/package/base-files/default/rom/note
new file mode 100644
index 0000000000..1746eb0509
--- /dev/null
+++ b/package/base-files/default/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/default/sbin/hotplug b/package/base-files/default/sbin/hotplug
new file mode 100755
index 0000000000..b1b6f97b23
--- /dev/null
+++ b/package/base-files/default/sbin/hotplug
@@ -0,0 +1,26 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+# bypass the normal hotplug path for firmware loading
+# would otherwise cause problems with drivers like bcm43xx
+[ "$1" = "firmware" -a "$ACTION" = "add" ] && {
+ [ -f "/lib/firmware/$FIRMWARE" ] && {
+ echo 1 > "/sys$DEVPATH/loading"
+ cp "/lib/firmware/$FIRMWARE" "/sys$DEVPATH/data"
+ echo 0 > "/sys$DEVPATH/loading"
+ }
+ exit 0
+}
+
+. /etc/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/default/sbin/ifdown b/package/base-files/default/sbin/ifdown
new file mode 100755
index 0000000000..073e80d2da
--- /dev/null
+++ b/package/base-files/default/sbin/ifdown
@@ -0,0 +1,34 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+[ $# = 0 ] && { echo " $0 <group>"; exit; }
+. /etc/functions.sh
+include /lib/network
+scan_interfaces
+
+cfg=$1
+debug "### ifdown $cfg ###"
+
+config_get proto "$cfg" proto
+[ -z "$proto" ] && { echo "interface not found."; exit; }
+
+# kill active ppp daemon
+pid="$(cat /var/run/ppp-${cfg}.pid 2>/dev/null)"
+[ -n "$pid" -a -d "/proc/$pid" ] && {
+ kill $pid
+ sleep 1
+ [ -d "/proc/$pid" ] && kill -9 $pid
+}
+
+# kill any other process associated with the interface
+config_get ifname "$cfg" ifname
+pid="$(cat /var/run/${ifname}.pid 2>/dev/null)"
+[ -n "$pid" -a -d "/proc/$pid" ] && kill -9 $pid
+
+config_get ifname "$cfg" ifname
+ifconfig "$ifname" >/dev/null 2>/dev/null && {
+ ifconfig "$ifname" 0.0.0.0 down
+
+ config_get iftype "$cfg" type
+ [ "$iftype" = "bridge" ] && brctl delbr "$ifname"
+}
diff --git a/package/base-files/default/sbin/ifup b/package/base-files/default/sbin/ifup
new file mode 100755
index 0000000000..c7055d4807
--- /dev/null
+++ b/package/base-files/default/sbin/ifup
@@ -0,0 +1,14 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+. /sbin/ifdown "$@"
+
+config_get iftype "$1" type
+case "$iftype" in
+ bridge) config_get ifname "$1" ifnames;;
+ *) config_get ifname "$1" ifname;;
+esac
+
+for dev in $ifname; do
+ setup_interface "$dev" "$1"
+done
diff --git a/package/base-files/default/sbin/mount_root b/package/base-files/default/sbin/mount_root
new file mode 100755
index 0000000000..81660f0067
--- /dev/null
+++ b/package/base-files/default/sbin/mount_root
@@ -0,0 +1,10 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+mount none /proc -t proc
+size=$(awk '/Mem:/ {l=5242880;print((s=$2/2)<l)?$2-l:s}' /proc/meminfo)
+mount none /tmp -t tmpfs -o size=$size,nosuid,nodev,mode=1777
+mkdir -p /dev/pts
+mount none /dev/pts -t devpts
+mount -t sysfs none /sys 2>&-
+mount -o remount,rw /dev/root /
diff --git a/package/base-files/default/sbin/wifi b/package/base-files/default/sbin/wifi
new file mode 100755
index 0000000000..4a3ec8cfef
--- /dev/null
+++ b/package/base-files/default/sbin/wifi
@@ -0,0 +1,44 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+. /etc/functions.sh
+
+config_get_bool() {
+ local _tmp
+ config_get "$1" "$2" "$3"
+ eval "_tmp=\$$1"
+ case "$_tmp" in
+ 1|on|enabled) eval "$1=1";;
+ 0|off|disabled) eval "$1=0";;
+ *) eval "$1=${4:-0}";;
+ esac
+}
+
+config_cb() {
+ config_get TYPE "$CONFIG_SECTION" TYPE
+ case "$TYPE" in
+ wifi-device)
+ append DEVICES "$CONFIG_SECTION"
+ ;;
+ 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 wireless
+include /lib/wifi
+
+for device in $DEVICES; do (
+ config_get iftype "$device" type
+ eval "type setup_$iftype" 2>/dev/null >/dev/null && {
+ eval "scan_$iftype '$device'"
+ eval "setup_$iftype '$device'" && {
+ # TODO: set up network settings
+ /bin/true
+ } || echo "$device($iftype): Setup failed" || true
+ } || echo "$device($iftype): Interface type not supported"
+); done
diff --git a/package/base-files/default/usr/lib/common.awk b/package/base-files/default/usr/lib/common.awk
new file mode 100644
index 0000000000..c5ce680fa6
--- /dev/null
+++ b/package/base-files/default/usr/lib/common.awk
@@ -0,0 +1,68 @@
+# Copyright (C) 2006 OpenWrt.org
+
+function portstr(type, str) {
+ gsub(/-/, ":", str)
+ if (insmod_mport != 1) {
+ print "insmod ipt_multiport >&- 2>&-"
+ insmod_mport = 1
+ }
+ if (type == "src") return " -m multiport --sports " str
+ else return " -m multiport --dports " str
+}
+
+function str2ipt(str) {
+ str2data(str)
+ _cmd = ""
+ if (_l["src"] != "") _cmd = _cmd " -s " _l["src"]
+ if (_l["dest"] != "") _cmd = _cmd " -d " _l["dest"]
+ if (_l["proto"] != "") {
+ _cmd = _cmd " -p " _l["proto"]
+ }
+ # scripts need to check for proto="" and emit two rules in that case
+ if ((_l["proto"] == "") || (_l["proto"] == "tcp") || (_l["proto"] == "udp")) {
+ if (_l["sport"] != "") _cmd = _cmd portstr("src", _l["sport"])
+ if (_l["dport"] != "") _cmd = _cmd portstr("dest", _l["dport"])
+ }
+ if (_l["layer7"] != "") {
+ if (insmod_l7 != 1) {
+ print "insmod ipt_layer7 >&- 2>&-"
+ insmod_l7 = 1
+ }
+ _cmd = _cmd " -m layer7 --l7proto " _l["layer7"]
+ }
+ return _cmd
+}
+
+function str2data(str) {
+ delete _l
+ _n = split(str, _o, "[\t ]")
+ for (_i = 1; _i <= _n; _i++) {
+ _n2 = split(_o[_i], _c, "=")
+ if (_n2 == 2) _l[_c[1]] = _c[2]
+ }
+}
+
+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 validate_netmask(nm) {
+ return and(-nm,compl(nm))
+}
+
+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
+}
diff --git a/package/base-files/default/usr/lib/parse-config.awk b/package/base-files/default/usr/lib/parse-config.awk
new file mode 100644
index 0000000000..9ce32b74ff
--- /dev/null
+++ b/package/base-files/default/usr/lib/parse-config.awk
@@ -0,0 +1,42 @@
+# Copyright (C) 2006 OpenWrt.org
+
+{
+ line=$0
+ gsub(/^[ \t]*/, "")
+ gsub(/[ \t]*$/, "")
+}
+
+$1 == "@define" {
+ v[$2] = $3
+}
+
+$1 == "@ifdef" {
+ if_open = 1
+ if (v[$2] != "") noprint = 0
+ else noprint = 1
+}
+
+$1 == "@ifndef" {
+ if_open = 1
+ if (v[$2] != "") noprint = 1
+ else noprint = 0
+}
+
+$1 == "@else" {
+ if (noprint == 1) noprint = 0
+ else noprint = 1
+}
+
+($1 !~ /^@[a-zA-Z]/) && (noprint != 1) {
+ n=split(line "@@", a, /@@/)
+ for (i=1; i<=n; i++) {
+ if ((i % 2) == 1) printf a[i]
+ else printf v[a[i]]
+ }
+ print ""
+}
+
+$1 == "@endif" {
+ if_open = 0
+ noprint = 0
+}
diff --git a/package/base-files/default/usr/share/udhcpc/default.script b/package/base-files/default/usr/share/udhcpc/default.script
new file mode 100755
index 0000000000..74e703715b
--- /dev/null
+++ b/package/base-files/default/usr/share/udhcpc/default.script
@@ -0,0 +1,57 @@
+#!/bin/sh
+[ -z "$1" ] && echo "Error: should be run by udhcpc" && exit 1
+. /etc/functions.sh
+include /lib/network
+
+RESOLV_CONF="/tmp/resolv.conf"
+
+hotplug_event() {
+ scan_interfaces
+ for ifc in $interfaces; do
+ config_get ifname $ifc ifname
+ [ "$ifname" = "$interface" ] || continue
+
+ config_get proto $ifc proto
+ [ "$proto" = "dhcp" ] || continue
+
+ env -i ACTION="$1" INTERFACE="$ifname" PROTO=dhcp /sbin/hotplug iface
+ done
+}
+
+case "$1" in
+ deconfig)
+ ifconfig $interface 0.0.0.0
+ hotplug_event ifdown
+ ;;
+ renew|bound)
+ ifconfig $interface $ip \
+ netmask ${subnet:-255.255.255.0} \
+ broadcast ${broadcast:-+}
+
+ if [ -n "$router" ] ; then
+ echo "deleting routers"
+ while route del default gw 0.0.0.0 dev $interface >&- 2>&- ; do :; done
+
+ for i in $router ; do
+ echo "adding router $i"
+ route add default gw $i dev $interface
+ done
+ fi
+
+ [ -n "$dns" ] && {
+ echo -n > $RESOLV_CONF
+ ${domain:+echo search $domain} >> $RESOLV_CONF
+ for i in $dns ; do
+ echo "adding dns $i"
+ echo "nameserver $i" >> $RESOLV_CONF
+ done
+ }
+
+ hotplug_event ifup
+
+ # user rules
+ [ -f /etc/udhcpc.user ] && . /etc/udhcpc.user
+ ;;
+esac
+
+exit 0
diff --git a/package/base-files/rb532-2.6/etc/config/network b/package/base-files/rb532-2.6/etc/config/network
new file mode 100644
index 0000000000..8279690574
--- /dev/null
+++ b/package/base-files/rb532-2.6/etc/config/network
@@ -0,0 +1,12 @@
+# 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 proto dhcp
+
diff --git a/package/base-files/sibyte-2.6/etc/config/network b/package/base-files/sibyte-2.6/etc/config/network
new file mode 100644
index 0000000000..9b65652f06
--- /dev/null
+++ b/package/base-files/sibyte-2.6/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 type bridge
+ option ifname "eth0 ath0"
+ option proto static
+ option ipaddr 192.168.1.1
+ option netmask 255.255.255.0
diff --git a/package/base-files/sibyte-2.6/etc/inittab b/package/base-files/sibyte-2.6/etc/inittab
new file mode 100644
index 0000000000..a6f4e17f01
--- /dev/null
+++ b/package/base-files/sibyte-2.6/etc/inittab
@@ -0,0 +1,5 @@
+# Copyright (C) 2006 OpenWrt.org
+
+::sysinit:/etc/init.d/rcS
+duart/0::askfirst:/bin/ash --login
+#tts/1::askfirst:/bin/ash --login
diff --git a/package/base-files/src/adam2patcher.c b/package/base-files/src/adam2patcher.c
new file mode 100644
index 0000000000..25a78074a6
--- /dev/null
+++ b/package/base-files/src/adam2patcher.c
@@ -0,0 +1,59 @@
+/*
+ * patcher.c - ADAM2 patcher for Netgear DG834 (and compatible)
+ *
+ * Copyright (C) 2006 Felix Fietkau
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <string.h>
+
+#include <sys/ioctl.h>
+
+int main(int argc, char **argv)
+{
+ int fd;
+ char *ptr;
+ uint32_t *i;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
+ exit(1);
+ }
+
+ if (((fd = open(argv[1], O_RDWR)) < 0)
+ || ((ptr = mmap(0, 128 * 1024, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == (void *) (-1))) {
+ fprintf(stderr, "Can't open file\n");
+ exit(1);
+ }
+
+ i = (uint32_t *) &ptr[0x3944];
+ if (*i == 0x0c000944) {
+ fprintf(stderr, "Unpatched ADAM2 detected. Patching... ");
+ *i = 0x00000000;
+ msync(i, sizeof(*i), MS_SYNC|MS_INVALIDATE);
+ fprintf(stderr, "done!\n");
+ } else if (*i == 0x00000000) {
+ fprintf(stderr, "Patched ADAM2 detected.\n");
+ } else {
+ fprintf(stderr, "Unknown ADAM2 detected. Can't patch!\n");
+ }
+
+ close(fd);
+}
diff --git a/package/base-files/src/jffs2root.c b/package/base-files/src/jffs2root.c
new file mode 100644
index 0000000000..14662fc945
--- /dev/null
+++ b/package/base-files/src/jffs2root.c
@@ -0,0 +1,133 @@
+/*
+ * jffs2root.c
+ *
+ * Copyright (C) 2005 Mike Baker
+ *
+ * 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.
+ *
+ * $Id$
+ *
+ */
+
+#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 <sys/ioctl.h>
+#include <linux/mtd/mtd.h>
+
+#define FILENAME "/dev/mtdblock/1"
+
+struct trx_header {
+ unsigned magic; /* "HDR0" */
+ unsigned len; /* Length of file including header */
+ unsigned crc32; /* 32-bit CRC from flag_version to end of file */
+ unsigned flag_version; /* 0:15 flags, 16:31 version */
+ unsigned offsets[3]; /* Offsets of partitions from start of header */
+};
+
+unsigned long *crc32;
+
+void init_crc32()
+{
+ unsigned long crc;
+ unsigned long poly = 0xEDB88320L;
+ int n, bit;
+ if ((crc32 = (unsigned long *) malloc(256 * sizeof(unsigned long))) == (void *)-1) {
+ perror("malloc");
+ exit(1);
+ }
+ for (n = 0; n < 256; n++) {
+ crc = (unsigned long) n;
+ for (bit = 0; bit < 8; bit++)
+ crc = (crc & 1) ? (poly ^ (crc >> 1)) : (crc >> 1);
+ crc32[n] = crc;
+ }
+}
+
+unsigned int crc32buf(char *buf, size_t len)
+{
+ unsigned int crc = 0xFFFFFFFF;
+ for (; len; len--, buf++)
+ crc = crc32[(crc ^ *buf) & 0xff] ^ (crc >> 8);
+ return crc;
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ struct mtd_info_user mtdInfo;
+ unsigned long len;
+ struct trx_header *ptr;
+ char *buf;
+
+ if (((fd = open(FILENAME, O_RDWR)) < 0)
+ || ((len = lseek(fd, 0, SEEK_END)) < 0)
+ || ((ptr = (struct trx_header *) mmap(0, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == (void *) (-1))
+ || (ptr->magic != 0x30524448)) {
+ printf("Error reading trx info\n");
+ exit(-1);
+ }
+ close (fd);
+
+ if (((fd = open("/dev/mtd/1", O_RDWR)) < 0)
+ || (ioctl(fd, MEMGETINFO, &mtdInfo))) {
+ fprintf(stderr, "Could not get MTD device info from %s\n", FILENAME);
+ close(fd);
+ exit(1);
+ }
+ close(fd);
+
+ if (argc > 1 && !strcmp(argv[1],"--move")) {
+ if (ptr->offsets[2] >= ptr->len) {
+ printf("Partition already moved outside trx\n");
+ } else {
+ init_crc32();
+ ptr->offsets[2] += (mtdInfo.erasesize - 1);
+ ptr->offsets[2] &= ~(mtdInfo.erasesize - 1);
+ ptr->len = ptr->offsets[2];
+ ptr->crc32 = crc32buf((void *) &(ptr->flag_version), ptr->len - offsetof(struct trx_header, flag_version));
+ msync(ptr,sizeof(struct trx_header),MS_SYNC|MS_INVALIDATE);
+ printf("Partition moved; please reboot\n");
+ }
+ } else if (argc > 1 && !strcmp(argv[1], "--clean")) {
+ buf = (char *) ptr;
+ if (buf[ptr->offsets[1] - 1] == 0) {
+ init_crc32();
+ buf[ptr->offsets[1] - 1] = 1;
+ ptr->crc32 = crc32buf((void *) &(ptr->flag_version), ptr->len - offsetof(struct trx_header, flag_version));
+ msync(ptr,sizeof(struct trx_header),MS_SYNC|MS_INVALIDATE);
+ printf("Partition marked as clean\n");
+ }
+ } else {
+ int x;
+ printf(" erase: 0x%08x\n",mtdInfo.erasesize);
+ printf("=== trx ===\n");
+ printf("mapped: 0x%08x\n", (unsigned)ptr);
+ printf(" magic: 0x%08x\n", ptr->magic);
+ printf(" len: 0x%08x\n", ptr->len);
+ printf(" crc: 0x%08x\n", ptr->crc32);
+ for (x = 0; x < 3; x++)
+ printf(" offset[%d]: 0x%08x\n", x, ptr->offsets[x]);
+ }
+
+ munmap((void *) ptr, len);
+ return 0;
+}
diff --git a/package/base-files/x86-2.4/etc/config/network b/package/base-files/x86-2.4/etc/config/network
new file mode 100644
index 0000000000..68d8e4240e
--- /dev/null
+++ b/package/base-files/x86-2.4/etc/config/network
@@ -0,0 +1,19 @@
+# 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 type bridge
+ option ifname "eth1 eth2"
+ option proto static
+ option ipaddr 192.168.1.1
+ option netmask 255.255.255.0
+
+config interface wan
+ option ifname eth0
+ option proto dhcp
+
diff --git a/package/base-files/x86-2.6/etc/config/network b/package/base-files/x86-2.6/etc/config/network
new file mode 100644
index 0000000000..68d8e4240e
--- /dev/null
+++ b/package/base-files/x86-2.6/etc/config/network
@@ -0,0 +1,19 @@
+# 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 type bridge
+ option ifname "eth1 eth2"
+ option proto static
+ option ipaddr 192.168.1.1
+ option netmask 255.255.255.0
+
+config interface wan
+ option ifname eth0
+ option proto dhcp
+
diff --git a/package/base-files/xscale-2.6/etc/config/network b/package/base-files/xscale-2.6/etc/config/network
new file mode 100644
index 0000000000..1d9b55b2d3
--- /dev/null
+++ b/package/base-files/xscale-2.6/etc/config/network
@@ -0,0 +1,11 @@
+# Network configuration file
+
+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 proto dhcp
diff --git a/package/bridge/Makefile b/package/bridge/Makefile
new file mode 100644
index 0000000000..c186c8e701
--- /dev/null
+++ b/package/bridge/Makefile
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bridge
+PKG_VERSION:=1.0.6
+PKG_RELEASE:=1
+
+PKG_SOURCE:=bridge-utils-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/bridge
+PKG_MD5SUM:=9b7dc52656f5cbec846a7ba3299f73bd
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/bridge-utils-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/bridge
+ SECTION:=net
+ CATEGORY:=Base system
+ DEFAULT:=y
+ TITLE:=Ethernet bridging configuration utility
+ DESCRIPTION:=\
+ Manage ethernet bridging: a way to connect networks together to \\\
+ form a larger network.
+ URL:=http://bridge.sourceforge.net/
+endef
+
+define Build/Configure
+ $(call Build/Configure/Default, \
+ --with-linux-headers="$(LINUX_DIR)" \
+ )
+endef
+
+define Package/bridge/install
+ install -m0755 -d $(1)/usr/sbin
+ install -m0755 $(PKG_BUILD_DIR)/brctl/brctl $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,bridge))
diff --git a/package/bridge/patches/patch-libbridge_Makefile_in b/package/bridge/patches/patch-libbridge_Makefile_in
new file mode 100644
index 0000000000..f44737750b
--- /dev/null
+++ b/package/bridge/patches/patch-libbridge_Makefile_in
@@ -0,0 +1,11 @@
+--- bridge-utils-0.9.6/libbridge/Makefile.in.dist 2004-03-01 20:55:52.000000000 -0600
++++ bridge-utils-0.9.6/libbridge/Makefile.in 2004-03-01 20:56:23.000000000 -0600
+@@ -5,7 +5,7 @@
+ 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-wl/Makefile b/package/broadcom-wl/Makefile
new file mode 100644
index 0000000000..3ef4bcf081
--- /dev/null
+++ b/package/broadcom-wl/Makefile
@@ -0,0 +1,148 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 2480 2005-11-14 02:07:33Z nbd $
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=broadcom-wl
+PKG_VERSION:=4.80.17.0
+PKG_RELEASE:=1
+WLC_VERSION:=0.1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://downloads.openwrt.org/sources
+PKG_MD5SUM:=3183ddb60e3e882b41df1776c89b614c
+PKG_CAT:=bzcat
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/broadcom-wl/Default
+ SECTION:=net
+ CATEGORY:=Kernel drivers
+ DEPENDS:=@PACKAGE_kmod-brcm-wl||PACKAGE_kmod-brcm-wl-mimo
+ SUBMENU:=Proprietary BCM43xx WiFi driver
+ SUBMENUDEP:=@LINUX_2_4_BRCM
+endef
+
+define Package/kmod-brcm-wl/Default
+ $(call Package/broadcom-wl/Default)
+ SECTION:=kernel
+ DEPENDS:=@LINUX_2_4_BRCM
+ TITLE:=Kernel driver for BCM43xx chipsets
+ DESCRIPTION:=\
+ This package contains the proprietary wireless driver for the Broadcom \\\
+ BCM43xx chipset
+ VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(PKG_RELEASE)
+endef
+
+define Package/kmod-brcm-wl
+ $(call Package/kmod-brcm-wl/Default)
+ DEFAULT:=y
+ TITLE+= (normal version)
+ DESCRIPTION+= (normal version).
+endef
+
+define Package/kmod-brcm-wl-mimo
+ $(call Package/kmod-brcm-wl/Default)
+ TITLE+= (MIMO version)
+ DESCRIPTION+= (MIMO version).
+endef
+
+define Package/wlc
+ $(call Package/broadcom-wl/Default)
+ DEFAULT:=y
+ TITLE:=Proprietary Broadcom wl driver setup utility
+ 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
+ DESCRIPTION:=\
+ This package contains the proprietary utility (wl) for configuring the \\\
+ proprietary Broadcom wl driver.
+endef
+
+define Package/nas
+ $(call Package/broadcom-wl/Default)
+ DEPENDS+= +nvram
+ TITLE:=Proprietary Broadcom WPA/WPA2 authenticator
+ DESCRIPTION:=\
+ This package contains the proprietary WPA/WPA2 authenticator (nas) for the \\\
+ proprietary Broadcom wl driver.
+endef
+
+MAKEFLAGS_KMOD:= -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) src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ # Compile the kernel part
+ $(MAKE) $(MAKEFLAGS_KMOD) \
+ modules
+ $(MAKE) $(MAKEFLAGS_KMOD) MOD_NAME="_mimo" \
+ modules
+
+ # Compile wlc
+ $(MAKE) -C $(PKG_BUILD_DIR)/wlc \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="-I$(PKG_BUILD_DIR)/wlc/include $(TARGET_CFLAGS)" \
+ all
+endef
+
+define wl_template
+ install -d -m0755 $(1)/etc/modules.d
+ echo "wl$(2)" > $(1)/etc/modules.d/20-wl$(2)
+ install -d -m0755 $(1)/lib/modules/$(LINUX_VERSION)
+ install -m0644 $(PKG_BUILD_DIR)/kmod/wl$(2).o $(PKG_BUILD_DIR)/kmod/wl$(2).o.patch $(1)/lib/modules/$(LINUX_VERSION)/
+endef
+
+define Package/kmod-brcm-wl/install
+ $(call wl_template,$(1))
+endef
+
+define Package/kmod-brcm-wl-mimo/install
+ $(call wl_template,$(1),_mimo)
+endef
+
+define Package/wlc/install
+ $(CP) ./files/* $(1)/
+ install -d -m0755 $(1)/sbin
+ install -m0755 $(PKG_BUILD_DIR)/wlc/wlc $(1)/sbin/
+endef
+
+define Package/wl/install
+ install -d -m0755 $(1)/usr/sbin
+ install -m0755 $(PKG_BUILD_DIR)/wl $(1)/usr/sbin/
+endef
+
+define Package/nas/install
+ install -d -m0755 $(1)/usr/lib
+ install -m0755 $(PKG_BUILD_DIR)/libbcmcrypto.so $(1)/usr/lib/
+ install -d -m0755 $(1)/usr/sbin
+ install -m0755 $(PKG_BUILD_DIR)/nas $(1)/usr/sbin/
+ ln -sf nas $(1)/usr/sbin/nas4not
+ ln -sf nas $(1)/usr/sbin/nas4wds
+endef
+
+$(eval $(call BuildPackage,kmod-brcm-wl))
+$(eval $(call BuildPackage,kmod-brcm-wl-mimo))
+$(eval $(call BuildPackage,wlc))
+$(eval $(call BuildPackage,wl))
+$(eval $(call BuildPackage,nas))
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 0000000000..435c440e2e
--- /dev/null
+++ b/package/broadcom-wl/files/lib/wifi/broadcom.sh
@@ -0,0 +1,177 @@
+bridge_interface() {
+ (
+ . /etc/functions.sh
+ include network
+ scan_interfaces
+ cfg="$(find_config "$1")"
+ [ -z "$cfg" ] && return 0
+ config_get iftype "$cfg" type
+ [ "$iftype" = bridge ] && config_get "$iftype" bridge
+ )
+}
+
+scan_broadcom() {
+ local device="$1"
+
+ config_get vifs "$device" vifs
+ for vif in $vifs; do
+ config_get mode "$vif" mode
+ case "$mode" in
+ adhoc)
+ adhoc=1
+ adhoc_if="$vif"
+ ;;
+ sta)
+ sta=1
+ sta_if="$vif"
+ ;;
+ ap)
+ ap=1
+ ap_if="${ap_if:+$ap_if }$vif"
+ ;;
+ *) echo "$device($vif): Invalid mode";;
+ esac
+ done
+
+ local _c=
+ for vif in ${adhoc_if:-$sta_if $ap_if}; do
+ config_set "$vif" ifname "wl0${_c:+.$_c}"
+ _c=$((${_c:-0} + 1))
+ done
+
+ 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
+ mssid=1
+ apsta=0
+ radio=1
+ case "$adhoc:$sta:$ap" in
+ 1*)
+ ap=0
+ mssid=0
+ infra=0
+ ;;
+ :1:1)
+ apsta=1
+ wet=1
+ ;;
+ :1:)
+ wet=1
+ ap=0
+ mssid=0
+ ;;
+ ::)
+ radio=0
+ ;;
+ esac
+}
+
+
+setup_broadcom() {
+ local _c
+ config_get channel "$device" channel
+ config_get country "$device" country
+ config_get maxassoc "$device" maxassoc
+
+ _c=0
+ nas="$(which nas)"
+ nas_cmd=
+ if_up=
+ for vif in ${adhoc_if:-$sta_if $ap_if}; do
+ append vif_pre_up "vif $_c" "$N"
+ append vif_post_up "vif $_c" "$N"
+
+ [ "$vif" = "$sta_if" ] || {
+ config_get_bool hidden "$vif" hidden 1
+ append vif_pre_up "closed $hidden" "$N"
+ config_get_bool isolate "$vif" isolate
+ append vif_pre_up "ap_isolate $hidden" "$N"
+ }
+
+ wsec_r=0
+ eap_r=0
+ wsec=0
+ auth=0
+ nasopts=
+ config_get enc "$vif" encryption
+ case "$enc" in
+ WEP|wep)
+ wsec_r=1
+ ;;
+ *psk*|*PSK*)
+ wsec_r=1
+ config_get key "$vif" key
+ case "$enc" in
+ wpa2*|WPA2*|PSK2*|psk2*) auth=128; wsec=4;;
+ *) auth=4; crypto=2;;
+ esac
+ eval "${vif}_key=\"\$key\""
+ nasopts="-k \"\$${vif}_key\""
+ ;;
+ *wpa*|*WPA*)
+ wsec_r=1
+ eap_r=1
+ config_get key "$vif" key
+ config_get server "$vif" server
+ config_get port "$vif" port
+ case "$enc" in
+ wpa2*|WPA2*) auth=64; wsec=4;;
+ *) auth=2; crypto=2;;
+ esac
+ eval "${vif}_key=\"\$key\""
+ nasopts="-r \"\$${vif}_key\" -h $server -p $port"
+ ;;
+ esac
+ append vif_post_up "wsec $wsec" "$N"
+ append vif_post_up "wpa_auth $auth" "$N"
+ append vif_post_up "wsec_restrict $wsec_r" "$N"
+ append vif_post_up "eap_restrict $eap_r" "$N"
+
+ config_get ssid "$vif" ssid
+ append vif_post_up "vlan_mode 0"
+ append vif_post_up "ssid $ssid" "$N"
+ append vif_post_up "enabled 1" "$N"
+
+ config_get ifname "$vif" ifname
+ append if_up "ifconfig $ifname up" ";$N"
+ [ -z "$nasopts" ] || {
+ bridge="$(bridge_interface "$ifname")"
+ eval "${vif}_ssid=\"\$ssid\""
+ mode="-A"
+ [ "$vif" = "$sta_if" ] && mode="-S"
+ [ -z "$nas" ] || nas_cmd="${nas_cmd:+$nas_cmd$N}$nas -P /var/run/nas.$ifname.pid -H 34954 ${bridge:+ -l $bridge} -i $ifname $mode -m $auth -w $crypto -s \"\$${vif}_ssid\" -g 3600 $nasopts &"
+ }
+ _c=$(($_c + 1))
+ done
+ killall -KILL nas >&- 2>&-
+ wlc stdin <<EOF
+$ifdown
+
+mssid $mssid
+ap $ap
+apsta $apsta
+infra $infra
+${wet:+wet 1}
+
+radio ${radio:-1}
+macfilter 0
+maclist none
+wds none
+channel ${channel:-0}
+country ${country:-IL0}
+maxassoc ${maxassoc:-128}
+
+$vif_pre_up
+up
+$vif_post_up
+EOF
+ eval "$nas_cmd"
+ eval "$if_up"
+}
+
+
diff --git a/package/broadcom-wl/src/kmod/Makefile b/package/broadcom-wl/src/kmod/Makefile
new file mode 100644
index 0000000000..450700f5ce
--- /dev/null
+++ b/package/broadcom-wl/src/kmod/Makefile
@@ -0,0 +1,31 @@
+#
+# Makefile for the Broadcom wl driver
+#
+# 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.
+#
+# $Id: Makefile,v 1.2 2005/03/29 03:32:18 mbm Exp $
+
+EXTRA_CFLAGS += -I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER
+
+O_TARGET := wl$(MOD_NAME).o
+
+obj-y := wl_mod$(MOD_NAME).o
+obj-y += bcmutils.o hnddma.o linux_osl.o
+
+obj-m := $(O_TARGET)
+
+wl_mod$(MOD_NAME).o: wl_apsta$(MOD_NAME).o
+ perl -ne 's,eth%d,wl%d\x00,g,print' < $< > $@
+
+wl$(MOD_NAME).o.patch: wl$(MOD_NAME).o
+ $(OBJDUMP) -d $< | perl patchtable.pl > $@
+
+modules: wl$(MOD_NAME).o.patch
+
+include $(TOPDIR)/Rules.make
diff --git a/package/broadcom-wl/src/kmod/bcmip.h b/package/broadcom-wl/src/kmod/bcmip.h
new file mode 100644
index 0000000000..423a0e5c5c
--- /dev/null
+++ b/package/broadcom-wl/src/kmod/bcmip.h
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ *
+ * Fundamental constants relating to IP Protocol
+ *
+ * $Id: bcmip.h,v 1.1.1.3 2006/02/27 03:43:16 honor Exp $
+ */
+
+#ifndef _bcmip_h_
+#define _bcmip_h_
+
+/* IPV4 and IPV6 common */
+#define IP_VER_OFFSET 0x0 /* offset to version field */
+#define IP_VER_MASK 0xf0 /* version mask */
+#define IP_VER_SHIFT 4 /* version shift */
+#define IP_VER_4 4 /* version number for IPV4 */
+#define IP_VER_6 6 /* version number for IPV6 */
+
+#define IP_VER(ip_body) \
+ ((((uint8 *)(ip_body))[IP_VER_OFFSET] & IP_VER_MASK) >> IP_VER_SHIFT)
+
+#define IP_PROT_ICMP 0x1 /* ICMP protocol */
+#define IP_PROT_TCP 0x6 /* TCP protocol */
+#define IP_PROT_UDP 0x11 /* UDP protocol type */
+
+/* IPV4 field offsets */
+#define IPV4_VER_HL_OFFSET 0 /* version and ihl byte offset */
+#define IPV4_TOS_OFFSET 1 /* type of service offset */
+#define IPV4_PROT_OFFSET 9 /* protocol type offset */
+#define IPV4_CHKSUM_OFFSET 10 /* IP header checksum offset */
+#define IPV4_SRC_IP_OFFSET 12 /* src IP addr offset */
+#define IPV4_DEST_IP_OFFSET 16 /* dest IP addr offset */
+
+/* IPV4 field decodes */
+#define IPV4_VER_MASK 0xf0 /* IPV4 version mask */
+#define IPV4_VER_SHIFT 4 /* IPV4 version shift */
+
+#define IPV4_HLEN_MASK 0x0f /* IPV4 header length mask */
+#define IPV4_HLEN(ipv4_body) (4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK))
+
+#define IPV4_ADDR_LEN 4 /* IPV4 address length */
+
+#define IPV4_ADDR_NULL(a) ((((uint8 *)(a))[0] | ((uint8 *)(a))[1] | \
+ ((uint8 *)(a))[2] | ((uint8 *)(a))[3]) == 0)
+
+#define IPV4_TOS_DSCP_MASK 0xfc /* DiffServ codepoint mask */
+#define IPV4_TOS_DSCP_SHIFT 2 /* DiffServ codepoint shift */
+
+#define IPV4_TOS(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_TOS_OFFSET])
+
+#define IPV4_TOS_PREC_MASK 0xe0 /* Historical precedence mask */
+#define IPV4_TOS_PREC_SHIFT 5 /* Historical precedence shift */
+
+#define IPV4_TOS_LOWDELAY 0x10 /* Lowest delay requested */
+#define IPV4_TOS_THROUGHPUT 0x8 /* Best throughput requested */
+#define IPV4_TOS_RELIABILITY 0x4 /* Most reliable delivery requested */
+
+#define IPV4_PROT(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_PROT_OFFSET])
+
+#define IPV4_ADDR_STR_LEN 16 /* Max IP address length in string format */
+
+/* IPV6 field offsets */
+#define IPV6_PAYLOAD_LEN_OFFSET 4 /* payload length offset */
+#define IPV6_NEXT_HDR_OFFSET 6 /* next header/protocol offset */
+#define IPV6_HOP_LIMIT_OFFSET 7 /* hop limit offset */
+#define IPV6_SRC_IP_OFFSET 8 /* src IP addr offset */
+#define IPV6_DEST_IP_OFFSET 24 /* dst IP addr offset */
+
+/* IPV6 field decodes */
+#define IPV6_TRAFFIC_CLASS(ipv6_body) \
+ (((((uint8 *)(ipv6_body))[0] & 0x0f) << 4) | \
+ ((((uint8 *)(ipv6_body))[1] & 0xf0) >> 4))
+
+#define IPV6_FLOW_LABEL(ipv6_body) \
+ (((((uint8 *)(ipv6_body))[1] & 0x0f) << 16) | \
+ (((uint8 *)(ipv6_body))[2] << 8) | \
+ (((uint8 *)(ipv6_body))[3]))
+
+#define IPV6_PAYLOAD_LEN(ipv6_body) \
+ ((((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 0] << 8) | \
+ ((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 1])
+
+#define IPV6_NEXT_HDR(ipv6_body) \
+ (((uint8 *)(ipv6_body))[IPV6_NEXT_HDR_OFFSET])
+
+#define IPV6_PROT(ipv6_body) IPV6_NEXT_HDR(ipv6_body)
+
+#define IPV6_ADDR_LEN 16 /* IPV6 address length */
+
+/* IPV4 TOS or IPV6 Traffic Classifier or 0 */
+#define IP_TOS(ip_body) \
+ (IP_VER(ip_body) == IP_VER_4 ? IPV4_TOS(ip_body) : \
+ IP_VER(ip_body) == IP_VER_6 ? IPV6_TRAFFIC_CLASS(ip_body) : 0)
+
+#endif /* _bcmip_h_ */
diff --git a/package/broadcom-wl/src/kmod/bcmutils.c b/package/broadcom-wl/src/kmod/bcmutils.c
new file mode 100644
index 0000000000..c264ea500b
--- /dev/null
+++ b/package/broadcom-wl/src/kmod/bcmutils.c
@@ -0,0 +1,857 @@
+/*
+ * Misc useful OS-independent routines.
+ *
+ * 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.
+ * $Id: bcmutils.c,v 1.1.1.12 2006/02/27 03:43:16 honor Exp $
+ */
+
+#include <typedefs.h>
+#include <bcmdefs.h>
+#include <stdarg.h>
+#include <osl.h>
+#include "linux_osl.h"
+#include "pktq.h"
+#include <bcmutils.h>
+#include <sbutils.h>
+#include <bcmnvram.h>
+#include <bcmendian.h>
+#include <bcmdevs.h>
+#include "bcmip.h"
+
+#define ETHER_TYPE_8021Q 0x8100
+#define ETHER_TYPE_IP 0x0800
+#define VLAN_PRI_SHIFT 13
+#define VLAN_PRI_MASK 7
+
+
+struct ether_header {
+ uint8 ether_dhost[6];
+ uint8 ether_shost[6];
+ uint16 ether_type;
+} __attribute__((packed));
+
+
+struct ethervlan_header {
+ uint8 ether_dhost[6];
+ uint8 ether_shost[6];
+ uint16 vlan_type; /* 0x8100 */
+ uint16 vlan_tag; /* priority, cfi and vid */
+ uint16 ether_type;
+};
+
+/* copy a pkt buffer chain into a buffer */
+uint
+pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf)
+{
+ uint n, ret = 0;
+
+ if (len < 0)
+ len = 4096; /* "infinite" */
+
+ /* skip 'offset' bytes */
+ for (; p && offset; p = PKTNEXT(osh, p)) {
+ if (offset < (uint)PKTLEN(osh, p))
+ break;
+ offset -= PKTLEN(osh, p);
+ }
+
+ if (!p)
+ return 0;
+
+ /* copy the data */
+ for (; p && len; p = PKTNEXT(osh, p)) {
+ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len);
+ bcopy(PKTDATA(osh, p) + offset, buf, n);
+ buf += n;
+ len -= n;
+ ret += n;
+ offset = 0;
+ }
+
+ return ret;
+}
+
+/* return total length of buffer chain */
+uint
+pkttotlen(osl_t *osh, void *p)
+{
+ uint total;
+
+ total = 0;
+ for (; p; p = PKTNEXT(osh, p))
+ total += PKTLEN(osh, p);
+ return (total);
+}
+
+/* return the last buffer of chained pkt */
+void *
+pktlast(osl_t *osh, void *p)
+{
+ for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p))
+ ;
+
+ return (p);
+}
+
+
+/*
+ * osl multiple-precedence packet queue
+ * hi_prec is always >= the number of the highest non-empty queue
+ */
+void *
+pktq_penq(struct pktq *pq, int prec, void *p)
+{
+ struct pktq_prec *q;
+
+ ASSERT(prec >= 0 && prec < pq->num_prec);
+ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */
+
+ ASSERT(!pktq_full(pq));
+ ASSERT(!pktq_pfull(pq, prec));
+
+ q = &pq->q[prec];
+
+ if (q->head)
+ PKTSETLINK(q->tail, p);
+ else
+ q->head = p;
+
+ q->tail = p;
+ q->len++;
+
+ pq->len++;
+
+ if (pq->hi_prec < prec)
+ pq->hi_prec = (uint8)prec;
+
+ return p;
+}
+
+void *
+pktq_penq_head(struct pktq *pq, int prec, void *p)
+{
+ struct pktq_prec *q;
+
+ ASSERT(prec >= 0 && prec < pq->num_prec);
+ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */
+
+ ASSERT(!pktq_full(pq));
+ ASSERT(!pktq_pfull(pq, prec));
+
+ q = &pq->q[prec];
+
+ if (q->head == NULL)
+ q->tail = p;
+
+ PKTSETLINK(p, q->head);
+ q->head = p;
+ q->len++;
+
+ pq->len++;
+
+ if (pq->hi_prec < prec)
+ pq->hi_prec = (uint8)prec;
+
+ return p;
+}
+
+void *
+pktq_pdeq(struct pktq *pq, int prec)
+{
+ struct pktq_prec *q;
+ void *p;
+
+ ASSERT(prec >= 0 && prec < pq->num_prec);
+
+ q = &pq->q[prec];
+
+ if ((p = q->head) == NULL)
+ return NULL;
+
+ if ((q->head = PKTLINK(p)) == NULL)
+ q->tail = NULL;
+
+ q->len--;
+
+ pq->len--;
+
+ PKTSETLINK(p, NULL);
+
+ return p;
+}
+
+void *
+pktq_pdeq_tail(struct pktq *pq, int prec)
+{
+ struct pktq_prec *q;
+ void *p, *prev;
+
+ ASSERT(prec >= 0 && prec < pq->num_prec);
+
+ q = &pq->q[prec];
+
+ if ((p = q->head) == NULL)
+ return NULL;
+
+ for (prev = NULL; p != q->tail; p = PKTLINK(p))
+ prev = p;
+
+ if (prev)
+ PKTSETLINK(prev, NULL);
+ else
+ q->head = NULL;
+
+ q->tail = prev;
+ q->len--;
+
+ pq->len--;
+
+ return p;
+}
+
+void
+pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir)
+{
+ struct pktq_prec *q;
+ void *p;
+
+ q = &pq->q[prec];
+ p = q->head;
+ while (p) {
+ q->head = PKTLINK(p);
+ PKTSETLINK(p, NULL);
+ PKTFREE(osh, p, dir);
+ q->len--;
+ pq->len--;
+ p = q->head;
+ }
+ ASSERT(q->len == 0);
+ q->tail = NULL;
+}
+
+bool
+pktq_pdel(struct pktq *pq, void *pktbuf, int prec)
+{
+ struct pktq_prec *q;
+ void *p;
+
+ ASSERT(prec >= 0 && prec < pq->num_prec);
+
+ if (!pktbuf)
+ return FALSE;
+
+ q = &pq->q[prec];
+
+ if (q->head == pktbuf) {
+ if ((q->head = PKTLINK(pktbuf)) == NULL)
+ q->tail = NULL;
+ } else {
+ for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p))
+ ;
+ if (p == NULL)
+ return FALSE;
+
+ PKTSETLINK(p, PKTLINK(pktbuf));
+ if (q->tail == pktbuf)
+ q->tail = p;
+ }
+
+ q->len--;
+ pq->len--;
+ PKTSETLINK(pktbuf, NULL);
+ return TRUE;
+}
+
+void
+pktq_init(struct pktq *pq, int num_prec, int max_len)
+{
+ int prec;
+
+ ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC);
+
+ bzero(pq, sizeof(*pq));
+
+ pq->num_prec = (uint16)num_prec;
+
+ pq->max = (uint16)max_len;
+
+ for (prec = 0; prec < num_prec; prec++)
+ pq->q[prec].max = pq->max;
+}
+
+void *
+pktq_deq(struct pktq *pq, int *prec_out)
+{
+ struct pktq_prec *q;
+ void *p;
+ int prec;
+
+ if (pq->len == 0)
+ return NULL;
+
+ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
+ pq->hi_prec--;
+
+ q = &pq->q[prec];
+
+ if ((p = q->head) == NULL)
+ return NULL;
+
+ if ((q->head = PKTLINK(p)) == NULL)
+ q->tail = NULL;
+
+ q->len--;
+
+ pq->len--;
+
+ if (prec_out)
+ *prec_out = prec;
+
+ PKTSETLINK(p, NULL);
+
+ return p;
+}
+
+void *
+pktq_deq_tail(struct pktq *pq, int *prec_out)
+{
+ struct pktq_prec *q;
+ void *p, *prev;
+ int prec;
+
+ if (pq->len == 0)
+ return NULL;
+
+ for (prec = 0; prec < pq->hi_prec; prec++)
+ if (pq->q[prec].head)
+ break;
+
+ q = &pq->q[prec];
+
+ if ((p = q->head) == NULL)
+ return NULL;
+
+ for (prev = NULL; p != q->tail; p = PKTLINK(p))
+ prev = p;
+
+ if (prev)
+ PKTSETLINK(prev, NULL);
+ else
+ q->head = NULL;
+
+ q->tail = prev;
+ q->len--;
+
+ pq->len--;
+
+ if (prec_out)
+ *prec_out = prec;
+
+ PKTSETLINK(p, NULL);
+
+ return p;
+}
+
+void *
+pktq_peek(struct pktq *pq, int *prec_out)
+{
+ int prec;
+
+ if (pq->len == 0)
+ return NULL;
+
+ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
+ pq->hi_prec--;
+
+ if (prec_out)
+ *prec_out = prec;
+
+ return (pq->q[prec].head);
+}
+
+void *
+pktq_peek_tail(struct pktq *pq, int *prec_out)
+{
+ int prec;
+
+ if (pq->len == 0)
+ return NULL;
+
+ for (prec = 0; prec < pq->hi_prec; prec++)
+ if (pq->q[prec].head)
+ break;
+
+ if (prec_out)
+ *prec_out = prec;
+
+ return (pq->q[prec].tail);
+}
+
+void
+pktq_flush(osl_t *osh, struct pktq *pq, bool dir)
+{
+ int prec;
+ for (prec = 0; prec < pq->num_prec; prec++)
+ pktq_pflush(osh, pq, prec, dir);
+ ASSERT(pq->len == 0);
+}
+
+/* Return sum of lengths of a specific set of precedences */
+int
+pktq_mlen(struct pktq *pq, uint prec_bmp)
+{
+ int prec, len;
+
+ len = 0;
+
+ for (prec = 0; prec <= pq->hi_prec; prec++)
+ if (prec_bmp & (1 << prec))
+ len += pq->q[prec].len;
+
+ return len;
+}
+
+/* Priority dequeue from a specific set of precedences */
+void *
+pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out)
+{
+ struct pktq_prec *q;
+ void *p;
+ int prec;
+
+ if (pq->len == 0)
+ return NULL;
+
+ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
+ pq->hi_prec--;
+
+ while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL)
+ if (prec-- == 0)
+ return NULL;
+
+ q = &pq->q[prec];
+
+ if ((p = q->head) == NULL)
+ return NULL;
+
+ if ((q->head = PKTLINK(p)) == NULL)
+ q->tail = NULL;
+
+ q->len--;
+
+ if (prec_out)
+ *prec_out = prec;
+
+ pq->len--;
+
+ PKTSETLINK(p, NULL);
+
+ return p;
+}
+
+char*
+bcmstrcat(char *dest, const char *src)
+{
+ strcpy(&dest[strlen(dest)], src);
+ return (dest);
+}
+
+char*
+bcm_ether_ntoa(struct ether_addr *ea, char *buf)
+{
+ sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
+ ea->octet[0]&0xff, ea->octet[1]&0xff, ea->octet[2]&0xff,
+ ea->octet[3]&0xff, ea->octet[4]&0xff, ea->octet[5]&0xff);
+ return (buf);
+}
+
+/* parse a xx:xx:xx:xx:xx:xx format ethernet address */
+int
+bcm_ether_atoe(char *p, struct ether_addr *ea)
+{
+ int i = 0;
+
+ for (;;) {
+ ea->octet[i++] = (char) bcm_strtoul(p, &p, 16);
+ if (!*p++ || i == 6)
+ break;
+ }
+
+ return (i == 6);
+}
+
+/* Takes an Ethernet frame and sets out-of-bound PKTPRIO
+ * Also updates the inplace vlan tag if requested
+ */
+void
+pktsetprio(void *pkt, bool update_vtag)
+{
+ struct ether_header *eh;
+ struct ethervlan_header *evh;
+ uint8 *pktdata;
+ int priority = 0;
+
+ pktdata = (uint8 *) PKTDATA(NULL, pkt);
+ ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16)));
+
+ eh = (struct ether_header *) pktdata;
+
+ if (ntoh16(eh->ether_type) == ETHER_TYPE_8021Q) {
+ uint16 vlan_tag;
+ int vlan_prio, dscp_prio = 0;
+
+ evh = (struct ethervlan_header *)eh;
+
+ vlan_tag = ntoh16(evh->vlan_tag);
+ vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
+
+ if (ntoh16(evh->ether_type) == ETHER_TYPE_IP) {
+ uint8 *ip_body = pktdata + sizeof(struct ethervlan_header);
+ uint8 tos_tc = IP_TOS(ip_body);
+ dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
+ }
+
+ /* DSCP priority gets precedence over 802.1P (vlan tag) */
+ priority = (dscp_prio != 0) ? dscp_prio : vlan_prio;
+
+ /*
+ * If the DSCP priority is not the same as the VLAN priority,
+ * then overwrite the priority field in the vlan tag, with the
+ * DSCP priority value. This is required for Linux APs because
+ * the VLAN driver on Linux, overwrites the skb->priority field
+ * with the priority value in the vlan tag
+ */
+ if (update_vtag && (priority != vlan_prio)) {
+ vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT);
+ vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT;
+ evh->vlan_tag = hton16(vlan_tag);
+ }
+ } else if (ntoh16(eh->ether_type) == ETHER_TYPE_IP) {
+ uint8 *ip_body = pktdata + sizeof(struct ether_header);
+ uint8 tos_tc = IP_TOS(ip_body);
+ priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
+ }
+
+ ASSERT(priority >= 0 && priority <= MAXPRIO);
+ PKTSETPRIO(pkt, priority);
+}
+
+static char bcm_undeferrstr[BCME_STRLEN];
+
+static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE;
+
+/* Convert the Error codes into related Error strings */
+const char *
+bcmerrorstr(int bcmerror)
+{
+ int abs_bcmerror;
+
+ abs_bcmerror = ABS(bcmerror);
+
+ /* check if someone added a bcmerror code but forgot to add errorstring */
+ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1));
+ if ((bcmerror > 0) || (abs_bcmerror > ABS(BCME_LAST))) {
+ sprintf(bcm_undeferrstr, "undefined Error %d", bcmerror);
+ return bcm_undeferrstr;
+ }
+
+ ASSERT((strlen((char*)bcmerrorstrtable[abs_bcmerror])) < BCME_STRLEN);
+
+ return bcmerrorstrtable[abs_bcmerror];
+}
+
+
+int
+bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set)
+{
+ int bcmerror = 0;
+
+ /* length check on io buf */
+ switch (vi->type) {
+ case IOVT_BOOL:
+ case IOVT_INT8:
+ case IOVT_INT16:
+ case IOVT_INT32:
+ case IOVT_UINT8:
+ case IOVT_UINT16:
+ case IOVT_UINT32:
+ /* all integers are int32 sized args at the ioctl interface */
+ if (len < (int)sizeof(int)) {
+ bcmerror = BCME_BUFTOOSHORT;
+ }
+ break;
+
+ case IOVT_BUFFER:
+ /* buffer must meet minimum length requirement */
+ if (len < vi->minlen) {
+ bcmerror = BCME_BUFTOOSHORT;
+ }
+ break;
+
+ case IOVT_VOID:
+ if (!set) {
+ /* Cannot return nil... */
+ bcmerror = BCME_UNSUPPORTED;
+ } else if (len) {
+ /* Set is an action w/o parameters */
+ bcmerror = BCME_BUFTOOLONG;
+ }
+ break;
+
+ default:
+ /* unknown type for length check in iovar info */
+ ASSERT(0);
+ bcmerror = BCME_UNSUPPORTED;
+ }
+
+ return bcmerror;
+}
+
+#define CRC_INNER_LOOP(n, c, x) \
+ (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff]
+
+static uint32 crc32_table[256] = {
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
+ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
+ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
+ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
+ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
+ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
+ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
+ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
+ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
+ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
+ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
+ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
+ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
+ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
+ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+};
+
+uint32
+hndcrc32(
+ uint8 *pdata, /* pointer to array of data to process */
+ uint nbytes, /* number of input data bytes to process */
+ uint32 crc /* either CRC32_INIT_VALUE or previous return value */
+)
+{
+ uint8 *pend;
+#ifdef __mips__
+ uint8 tmp[4];
+ ulong *tptr = (ulong *)tmp;
+
+ /* in case the beginning of the buffer isn't aligned */
+ pend = (uint8 *)((uint)(pdata + 3) & 0xfffffffc);
+ nbytes -= (pend - pdata);
+ while (pdata < pend)
+ CRC_INNER_LOOP(32, crc, *pdata++);
+
+ /* handle bulk of data as 32-bit words */
+ pend = pdata + (nbytes & 0xfffffffc);
+ while (pdata < pend) {
+ *tptr = *(ulong *)pdata;
+ pdata += sizeof(ulong *);
+ CRC_INNER_LOOP(32, crc, tmp[0]);
+ CRC_INNER_LOOP(32, crc, tmp[1]);
+ CRC_INNER_LOOP(32, crc, tmp[2]);
+ CRC_INNER_LOOP(32, crc, tmp[3]);
+ }
+
+ /* 1-3 bytes at end of buffer */
+ pend = pdata + (nbytes & 0x03);
+ while (pdata < pend)
+ CRC_INNER_LOOP(32, crc, *pdata++);
+#else
+ pend = pdata + nbytes;
+ while (pdata < pend)
+ CRC_INNER_LOOP(32, crc, *pdata++);
+#endif /* __mips__ */
+
+ return crc;
+}
+
+
+/*
+ * Advance from the current 1-byte tag/1-byte length/variable-length value
+ * triple, to the next, returning a pointer to the next.
+ * If the current or next TLV is invalid (does not fit in given buffer length),
+ * NULL is returned.
+ * *buflen is not modified if the TLV elt parameter is invalid, or is decremented
+ * by the TLV paramter's length if it is valid.
+ */
+bcm_tlv_t *
+bcm_next_tlv(bcm_tlv_t *elt, int *buflen)
+{
+ int len;
+
+ /* validate current elt */
+ if (!bcm_valid_tlv(elt, *buflen))
+ return NULL;
+
+ /* advance to next elt */
+ len = elt->len;
+ elt = (bcm_tlv_t*)(elt->data + len);
+ *buflen -= (2 + len);
+
+ /* validate next elt */
+ if (!bcm_valid_tlv(elt, *buflen))
+ return NULL;
+
+ return elt;
+}
+
+/*
+ * Traverse a string of 1-byte tag/1-byte length/variable-length value
+ * triples, returning a pointer to the substring whose first element
+ * matches tag
+ */
+bcm_tlv_t *
+bcm_parse_tlvs(void *buf, int buflen, uint key)
+{
+ bcm_tlv_t *elt;
+ int totlen;
+
+ elt = (bcm_tlv_t*)buf;
+ totlen = buflen;
+
+ /* find tagged parameter */
+ while (totlen >= 2) {
+ int len = elt->len;
+
+ /* validate remaining totlen */
+ if ((elt->id == key) && (totlen >= (len + 2)))
+ return (elt);
+
+ elt = (bcm_tlv_t*)((uint8*)elt + (len + 2));
+ totlen -= (len + 2);
+ }
+
+ return NULL;
+}
+
+/*
+ * Traverse a string of 1-byte tag/1-byte length/variable-length value
+ * triples, returning a pointer to the substring whose first element
+ * matches tag. Stop parsing when we see an element whose ID is greater
+ * than the target key.
+ */
+bcm_tlv_t *
+bcm_parse_ordered_tlvs(void *buf, int buflen, uint key)
+{
+ bcm_tlv_t *elt;
+ int totlen;
+
+ elt = (bcm_tlv_t*)buf;
+ totlen = buflen;
+
+ /* find tagged parameter */
+ while (totlen >= 2) {
+ uint id = elt->id;
+ int len = elt->len;
+
+ /* Punt if we start seeing IDs > than target key */
+ if (id > key)
+ return (NULL);
+
+ /* validate remaining totlen */
+ if ((id == key) && (totlen >= (len + 2)))
+ return (elt);
+
+ elt = (bcm_tlv_t*)((uint8*)elt + (len + 2));
+ totlen -= (len + 2);
+ }
+ return NULL;
+}
+
+
+/* Initialization of bcmstrbuf structure */
+void
+bcm_binit(struct bcmstrbuf *b, char *buf, uint size)
+{
+ b->origsize = b->size = size;
+ b->origbuf = b->buf = buf;
+}
+
+/* Buffer sprintf wrapper to guard against buffer overflow */
+int
+bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...)
+{
+ va_list ap;
+ int r;
+
+ va_start(ap, fmt);
+ r = vsnprintf(b->buf, b->size, fmt, ap);
+
+ /* Non Ansi C99 compliant returns -1,
+ * Ansi compliant return r >= b->size,
+ * bcmstdlib returns 0, handle all
+ */
+ if ((r == -1) || (r >= (int)b->size) || (r == 0))
+ {
+ b->size = 0;
+ }
+ else
+ {
+ b->size -= r;
+ b->buf += r;
+ }
+
+ va_end(ap);
+
+ return r;
+}
diff --git a/package/broadcom-wl/src/kmod/hnddma.c b/package/broadcom-wl/src/kmod/hnddma.c
new file mode 100644
index 0000000000..4336560888
--- /dev/null
+++ b/package/broadcom-wl/src/kmod/hnddma.c
@@ -0,0 +1,1157 @@
+/*
+ * Generic Broadcom Home Networking Division (HND) DMA module.
+ * This supports the following chips: BCM42xx, 44xx, 47xx .
+ *
+ * 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.
+ *
+ * $Id: hnddma.c,v 1.11 2006/04/08 07:12:42 honor Exp $
+ */
+
+#include <typedefs.h>
+#include <bcmdefs.h>
+#include <osl.h>
+#include "linux_osl.h"
+#include <bcmendian.h>
+#include <sbconfig.h>
+#include <bcmutils.h>
+#include <bcmdevs.h>
+#include <sbutils.h>
+
+#include "sbhnddma.h"
+#include "hnddma.h"
+
+/* debug/trace */
+#define DMA_ERROR(args)
+#define DMA_TRACE(args)
+
+/* default dma message level (if input msg_level pointer is null in dma_attach()) */
+static uint dma_msg_level =
+ 0;
+
+#define MAXNAMEL 8 /* 8 char names */
+
+#define DI_INFO(dmah) (dma_info_t *)dmah
+
+/* dma engine software state */
+typedef struct dma_info {
+ struct hnddma_pub hnddma; /* exported structure, don't use hnddma_t,
+ * which could be const
+ */
+ uint *msg_level; /* message level pointer */
+ char name[MAXNAMEL]; /* callers name for diag msgs */
+
+ void *osh; /* os handle */
+ sb_t *sbh; /* sb handle */
+
+ bool dma64; /* dma64 enabled */
+ bool addrext; /* this dma engine supports DmaExtendedAddrChanges */
+
+ dma32regs_t *d32txregs; /* 32 bits dma tx engine registers */
+ dma32regs_t *d32rxregs; /* 32 bits dma rx engine registers */
+ dma64regs_t *d64txregs; /* 64 bits dma tx engine registers */
+ dma64regs_t *d64rxregs; /* 64 bits dma rx engine registers */
+
+ uint32 dma64align; /* either 8k or 4k depends on number of dd */
+ dma32dd_t *txd32; /* pointer to dma32 tx descriptor ring */
+ dma64dd_t *txd64; /* pointer to dma64 tx descriptor ring */
+ uint ntxd; /* # tx descriptors tunable */
+ uint txin; /* index of next descriptor to reclaim */
+ uint txout; /* index of next descriptor to post */
+ void **txp; /* pointer to parallel array of pointers to packets */
+ osldma_t *tx_dmah; /* DMA TX descriptor ring handle */
+ osldma_t **txp_dmah; /* DMA TX packet data handle */
+ ulong txdpa; /* physical address of descriptor ring */
+ uint txdalign; /* #bytes added to alloc'd mem to align txd */
+ uint txdalloc; /* #bytes allocated for the ring */
+
+ dma32dd_t *rxd32; /* pointer to dma32 rx descriptor ring */
+ dma64dd_t *rxd64; /* pointer to dma64 rx descriptor ring */
+ uint nrxd; /* # rx descriptors tunable */
+ uint rxin; /* index of next descriptor to reclaim */
+ uint rxout; /* index of next descriptor to post */
+ void **rxp; /* pointer to parallel array of pointers to packets */
+ osldma_t *rx_dmah; /* DMA RX descriptor ring handle */
+ osldma_t **rxp_dmah; /* DMA RX packet data handle */
+ ulong rxdpa; /* physical address of descriptor ring */
+ uint rxdalign; /* #bytes added to alloc'd mem to align rxd */
+ uint rxdalloc; /* #bytes allocated for the ring */
+
+ /* tunables */
+ uint rxbufsize; /* rx buffer size in bytes,
+ not including the extra headroom
+ */
+ uint nrxpost; /* # rx buffers to keep posted */
+ uint rxoffset; /* rxcontrol offset */
+ uint ddoffsetlow; /* add to get dma address of descriptor ring, low 32 bits */
+ uint ddoffsethigh; /* high 32 bits */
+ uint dataoffsetlow; /* add to get dma address of data buffer, low 32 bits */
+ uint dataoffsethigh; /* high 32 bits */
+} dma_info_t;
+
+/* descriptor bumping macros */
+#define XXD(x, n) ((x) & ((n) - 1)) /* faster than %, but n must be power of 2 */
+#define TXD(x) XXD((x), di->ntxd)
+#define RXD(x) XXD((x), di->nrxd)
+#define NEXTTXD(i) TXD(i + 1)
+#define PREVTXD(i) TXD(i - 1)
+#define NEXTRXD(i) RXD(i + 1)
+#define NTXDACTIVE(h, t) TXD(t - h)
+#define NRXDACTIVE(h, t) RXD(t - h)
+
+/* macros to convert between byte offsets and indexes */
+#define B2I(bytes, type) ((bytes) / sizeof(type))
+#define I2B(index, type) ((index) * sizeof(type))
+
+#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */
+#define PCI32ADDR_HIGH_SHIFT 30 /* address[31:30] */
+
+
+/* common prototypes */
+static bool _dma_isaddrext(dma_info_t *di);
+static bool dma32_alloc(dma_info_t *di, uint direction);
+static void _dma_detach(dma_info_t *di);
+static void _dma_ddtable_init(dma_info_t *di, uint direction, ulong pa);
+static void _dma_rxinit(dma_info_t *di);
+static void *_dma_rx(dma_info_t *di);
+static void _dma_rxfill(dma_info_t *di);
+static void _dma_rxreclaim(dma_info_t *di);
+static void _dma_rxenable(dma_info_t *di);
+static void * _dma_getnextrxp(dma_info_t *di, bool forceall);
+
+static void _dma_txblock(dma_info_t *di);
+static void _dma_txunblock(dma_info_t *di);
+static uint _dma_txactive(dma_info_t *di);
+
+static void* _dma_peeknexttxp(dma_info_t *di);
+static uintptr _dma_getvar(dma_info_t *di, char *name);
+static void _dma_counterreset(dma_info_t *di);
+static void _dma_fifoloopbackenable(dma_info_t *di);
+
+/* ** 32 bit DMA prototypes */
+static bool dma32_alloc(dma_info_t *di, uint direction);
+static bool dma32_txreset(dma_info_t *di);
+static bool dma32_rxreset(dma_info_t *di);
+static bool dma32_txsuspendedidle(dma_info_t *di);
+static int dma32_txfast(dma_info_t *di, void *p0, bool commit);
+static void *dma32_getnexttxp(dma_info_t *di, bool forceall);
+static void *dma32_getnextrxp(dma_info_t *di, bool forceall);
+static void dma32_txrotate(dma_info_t *di);
+static bool dma32_rxidle(dma_info_t *di);
+static void dma32_txinit(dma_info_t *di);
+static bool dma32_txenabled(dma_info_t *di);
+static void dma32_txsuspend(dma_info_t *di);
+static void dma32_txresume(dma_info_t *di);
+static bool dma32_txsuspended(dma_info_t *di);
+static void dma32_txreclaim(dma_info_t *di, bool forceall);
+static bool dma32_txstopped(dma_info_t *di);
+static bool dma32_rxstopped(dma_info_t *di);
+static bool dma32_rxenabled(dma_info_t *di);
+static bool _dma32_addrext(osl_t *osh, dma32regs_t *dma32regs);
+
+
+static di_fcn_t dma32proc = {
+ (di_detach_t)_dma_detach,
+ (di_txinit_t)dma32_txinit,
+ (di_txreset_t)dma32_txreset,
+ (di_txenabled_t)dma32_txenabled,
+ (di_txsuspend_t)dma32_txsuspend,
+ (di_txresume_t)dma32_txresume,
+ (di_txsuspended_t)dma32_txsuspended,
+ (di_txsuspendedidle_t)dma32_txsuspendedidle,
+ (di_txfast_t)dma32_txfast,
+ (di_txstopped_t)dma32_txstopped,
+ (di_txreclaim_t)dma32_txreclaim,
+ (di_getnexttxp_t)dma32_getnexttxp,
+ (di_peeknexttxp_t)_dma_peeknexttxp,
+ (di_txblock_t)_dma_txblock,
+ (di_txunblock_t)_dma_txunblock,
+ (di_txactive_t)_dma_txactive,
+ (di_txrotate_t)dma32_txrotate,
+
+ (di_rxinit_t)_dma_rxinit,
+ (di_rxreset_t)dma32_rxreset,
+ (di_rxidle_t)dma32_rxidle,
+ (di_rxstopped_t)dma32_rxstopped,
+ (di_rxenable_t)_dma_rxenable,
+ (di_rxenabled_t)dma32_rxenabled,
+ (di_rx_t)_dma_rx,
+ (di_rxfill_t)_dma_rxfill,
+ (di_rxreclaim_t)_dma_rxreclaim,
+ (di_getnextrxp_t)_dma_getnextrxp,
+
+ (di_fifoloopbackenable_t)_dma_fifoloopbackenable,
+ (di_getvar_t)_dma_getvar,
+ (di_counterreset_t)_dma_counterreset,
+
+ NULL,
+ NULL,
+ NULL,
+ 34
+};
+
+hnddma_t *
+dma_attach(osl_t *osh, char *name, sb_t *sbh, void *dmaregstx, void *dmaregsrx,
+ uint ntxd, uint nrxd, uint rxbufsize, uint nrxpost, uint rxoffset, uint *msg_level)
+{
+ dma_info_t *di;
+ uint size;
+
+ /* allocate private info structure */
+ if ((di = MALLOC(osh, sizeof (dma_info_t))) == NULL) {
+ return (NULL);
+ }
+ bzero((char *)di, sizeof(dma_info_t));
+
+ di->msg_level = msg_level ? msg_level : &dma_msg_level;
+
+ /* old chips w/o sb is no longer supported */
+ ASSERT(sbh != NULL);
+
+ /* check arguments */
+ ASSERT(ISPOWEROF2(ntxd));
+ ASSERT(ISPOWEROF2(nrxd));
+ if (nrxd == 0)
+ ASSERT(dmaregsrx == NULL);
+ if (ntxd == 0)
+ ASSERT(dmaregstx == NULL);
+
+
+ /* init dma reg pointer */
+ ASSERT(ntxd <= D32MAXDD);
+ ASSERT(nrxd <= D32MAXDD);
+ di->d32txregs = (dma32regs_t *)dmaregstx;
+ di->d32rxregs = (dma32regs_t *)dmaregsrx;
+
+ DMA_TRACE(("%s: dma_attach: %s osh %p ntxd %d nrxd %d rxbufsize %d nrxpost %d "
+ "rxoffset %d dmaregstx %p dmaregsrx %p\n",
+ name, "DMA32", osh, ntxd, nrxd, rxbufsize,
+ nrxpost, rxoffset, dmaregstx, dmaregsrx));
+
+ /* make a private copy of our callers name */
+ strncpy(di->name, name, MAXNAMEL);
+ di->name[MAXNAMEL-1] = '\0';
+
+ di->osh = osh;
+ di->sbh = sbh;
+
+ /* save tunables */
+ di->ntxd = ntxd;
+ di->nrxd = nrxd;
+
+ /* the actual dma size doesn't include the extra headroom */
+ if (rxbufsize > BCMEXTRAHDROOM)
+ di->rxbufsize = rxbufsize - BCMEXTRAHDROOM;
+ else
+ di->rxbufsize = rxbufsize;
+
+ di->nrxpost = nrxpost;
+ di->rxoffset = rxoffset;
+
+ /*
+ * figure out the DMA physical address offset for dd and data
+ * for old chips w/o sb, use zero
+ * for new chips w sb,
+ * PCI/PCIE: they map silicon backplace address to zero based memory, need offset
+ * Other bus: use zero
+ * SB_BUS BIGENDIAN kludge: use sdram swapped region for data buffer, not descriptor
+ */
+ di->ddoffsetlow = 0;
+ di->dataoffsetlow = 0;
+ /* for pci bus, add offset */
+ if (sbh->bustype == PCI_BUS) {
+ di->ddoffsetlow = SB_PCI_DMA;
+ di->ddoffsethigh = 0;
+ di->dataoffsetlow = di->ddoffsetlow;
+ di->dataoffsethigh = di->ddoffsethigh;
+ }
+
+#if defined(__mips__) && defined(IL_BIGENDIAN)
+ di->dataoffsetlow = di->dataoffsetlow + SB_SDRAM_SWAPPED;
+#endif
+
+ di->addrext = _dma_isaddrext(di);
+
+ /* allocate tx packet pointer vector */
+ if (ntxd) {
+ size = ntxd * sizeof(void *);
+ if ((di->txp = MALLOC(osh, size)) == NULL) {
+ DMA_ERROR(("%s: dma_attach: out of tx memory, malloced %d bytes\n",
+ di->name, MALLOCED(osh)));
+ goto fail;
+ }
+ bzero((char *)di->txp, size);
+ }
+
+ /* allocate rx packet pointer vector */
+ if (nrxd) {
+ size = nrxd * sizeof(void *);
+ if ((di->rxp = MALLOC(osh, size)) == NULL) {
+ DMA_ERROR(("%s: dma_attach: out of rx memory, malloced %d bytes\n",
+ di->name, MALLOCED(osh)));
+ goto fail;
+ }
+ bzero((char *)di->rxp, size);
+ }
+
+ /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */
+ if (ntxd) {
+ if (!dma32_alloc(di, DMA_TX))
+ goto fail;
+ }
+
+ /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */
+ if (nrxd) {
+ if (!dma32_alloc(di, DMA_RX))
+ goto fail;
+ }
+
+ if ((di->ddoffsetlow == SB_PCI_DMA) && (di->txdpa > SB_PCI_DMA_SZ) && !di->addrext) {
+ DMA_ERROR(("%s: dma_attach: txdpa 0x%lx: addrext not supported\n",
+ di->name, di->txdpa));
+ goto fail;
+ }
+ if ((di->ddoffsetlow == SB_PCI_DMA) && (di->rxdpa > SB_PCI_DMA_SZ) && !di->addrext) {
+ DMA_ERROR(("%s: dma_attach: rxdpa 0x%lx: addrext not supported\n",
+ di->name, di->rxdpa));
+ goto fail;
+ }
+
+ DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh "
+ "0x%x addrext %d\n", di->ddoffsetlow, di->ddoffsethigh, di->dataoffsetlow,
+ di->dataoffsethigh, di->addrext));
+
+ /* allocate tx packet pointer vector and DMA mapping vectors */
+ if (ntxd) {
+
+ size = ntxd * sizeof(osldma_t **);
+ if ((di->txp_dmah = (osldma_t **)MALLOC(osh, size)) == NULL)
+ goto fail;
+ bzero((char*)di->txp_dmah, size);
+ }else
+ di->txp_dmah = NULL;
+
+ /* allocate rx packet pointer vector and DMA mapping vectors */
+ if (nrxd) {
+
+ size = nrxd * sizeof(osldma_t **);
+ if ((di->rxp_dmah = (osldma_t **)MALLOC(osh, size)) == NULL)
+ goto fail;
+ bzero((char*)di->rxp_dmah, size);
+
+ } else
+ di->rxp_dmah = NULL;
+
+ /* initialize opsvec of function pointers */
+ di->hnddma.di_fn = dma32proc;
+
+ return ((hnddma_t *)di);
+
+fail:
+ _dma_detach(di);
+ return (NULL);
+}
+
+/* init the tx or rx descriptor */
+static INLINE void
+dma32_dd_upd(dma_info_t *di, dma32dd_t *ddring, ulong pa, uint outidx, uint32 *flags,
+ uint32 bufcount)
+{
+ /* dma32 uses 32 bits control to fit both flags and bufcounter */
+ *flags = *flags | (bufcount & CTRL_BC_MASK);
+
+ if ((di->dataoffsetlow != SB_PCI_DMA) || !(pa & PCI32ADDR_HIGH)) {
+ W_SM(&ddring[outidx].addr, BUS_SWAP32(pa + di->dataoffsetlow));
+ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*flags));
+ } else {
+ /* address extension */
+ uint32 ae;
+ ASSERT(di->addrext);
+ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT;
+ pa &= ~PCI32ADDR_HIGH;
+
+ *flags |= (ae << CTRL_AE_SHIFT);
+ W_SM(&ddring[outidx].addr, BUS_SWAP32(pa + di->dataoffsetlow));
+ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*flags));
+ }
+}
+
+static bool
+_dma32_addrext(osl_t *osh, dma32regs_t *dma32regs)
+{
+ uint32 w;
+
+ OR_REG(osh, &dma32regs->control, XC_AE);
+ w = R_REG(osh, &dma32regs->control);
+ AND_REG(osh, &dma32regs->control, ~XC_AE);
+ return ((w & XC_AE) == XC_AE);
+}
+
+/* !! may be called with core in reset */
+static void
+_dma_detach(dma_info_t *di)
+{
+ if (di == NULL)
+ return;
+
+ DMA_TRACE(("%s: dma_detach\n", di->name));
+
+ /* shouldn't be here if descriptors are unreclaimed */
+ ASSERT(di->txin == di->txout);
+ ASSERT(di->rxin == di->rxout);
+
+ /* free dma descriptor rings */
+ if (di->txd32)
+ DMA_FREE_CONSISTENT(di->osh, ((int8*)di->txd32 - di->txdalign),
+ di->txdalloc, (di->txdpa - di->txdalign), &di->tx_dmah);
+ if (di->rxd32)
+ DMA_FREE_CONSISTENT(di->osh, ((int8*)di->rxd32 - di->rxdalign),
+ di->rxdalloc, (di->rxdpa - di->rxdalign), &di->rx_dmah);
+
+ /* free packet pointer vectors */
+ if (di->txp)
+ MFREE(di->osh, (void *)di->txp, (di->ntxd * sizeof(void *)));
+ if (di->rxp)
+ MFREE(di->osh, (void *)di->rxp, (di->nrxd * sizeof(void *)));
+
+ /* free tx packet DMA handles */
+ if (di->txp_dmah)
+ MFREE(di->osh, (void *)di->txp_dmah, di->ntxd * sizeof(osldma_t **));
+
+ /* free rx packet DMA handles */
+ if (di->rxp_dmah)
+ MFREE(di->osh, (void *)di->rxp_dmah, di->nrxd * sizeof(osldma_t **));
+
+ /* free our private info structure */
+ MFREE(di->osh, (void *)di, sizeof(dma_info_t));
+
+}
+
+/* return TRUE if this dma engine supports DmaExtendedAddrChanges, otherwise FALSE */
+static bool
+_dma_isaddrext(dma_info_t *di)
+{
+ if (di->d32txregs)
+ return (_dma32_addrext(di->osh, di->d32txregs));
+ else if (di->d32rxregs)
+ return (_dma32_addrext(di->osh, di->d32rxregs));
+ return FALSE;
+}
+
+/* initialize descriptor table base address */
+static void
+_dma_ddtable_init(dma_info_t *di, uint direction, ulong pa)
+{
+ if ((di->ddoffsetlow != SB_PCI_DMA) || !(pa & PCI32ADDR_HIGH)) {
+ if (direction == DMA_TX)
+ W_REG(di->osh, &di->d32txregs->addr, (pa + di->ddoffsetlow));
+ else
+ W_REG(di->osh, &di->d32rxregs->addr, (pa + di->ddoffsetlow));
+ } else {
+ /* dma32 address extension */
+ uint32 ae;
+ ASSERT(di->addrext);
+
+ /* shift the high bit(s) from pa to ae */
+ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT;
+ pa &= ~PCI32ADDR_HIGH;
+
+ if (direction == DMA_TX) {
+ W_REG(di->osh, &di->d32txregs->addr, (pa + di->ddoffsetlow));
+ SET_REG(di->osh, &di->d32txregs->control, XC_AE, ae <<XC_AE_SHIFT);
+ } else {
+ W_REG(di->osh, &di->d32rxregs->addr, (pa + di->ddoffsetlow));
+ SET_REG(di->osh, &di->d32rxregs->control, RC_AE, ae <<RC_AE_SHIFT);
+ }
+ }
+}
+
+static void
+_dma_fifoloopbackenable(dma_info_t *di)
+{
+ DMA_TRACE(("%s: dma_fifoloopbackenable\n", di->name));
+ OR_REG(di->osh, &di->d32txregs->control, XC_LE);
+}
+
+static void
+_dma_rxinit(dma_info_t *di)
+{
+ DMA_TRACE(("%s: dma_rxinit\n", di->name));
+
+ if (di->nrxd == 0)
+ return;
+
+ di->rxin = di->rxout = 0;
+
+ /* clear rx descriptor ring */
+ BZERO_SM((void *)di->rxd32, (di->nrxd * sizeof(dma32dd_t)));
+ _dma_rxenable(di);
+ _dma_ddtable_init(di, DMA_RX, di->rxdpa);
+}
+
+static void
+_dma_rxenable(dma_info_t *di)
+{
+ DMA_TRACE(("%s: dma_rxenable\n", di->name));
+
+ W_REG(di->osh, &di->d32rxregs->control, ((di->rxoffset << RC_RO_SHIFT) | RC_RE));
+}
+
+/* !! rx entry routine, returns a pointer to the next frame received,
+ * or NULL if there are no more
+ */
+static void *
+_dma_rx(dma_info_t *di)
+{
+ void *p;
+ uint len;
+ int skiplen = 0;
+
+ while ((p = _dma_getnextrxp(di, FALSE))) {
+ /* skip giant packets which span multiple rx descriptors */
+ if (skiplen > 0) {
+ skiplen -= di->rxbufsize;
+ if (skiplen < 0)
+ skiplen = 0;
+ PKTFREE(di->osh, p, FALSE);
+ continue;
+ }
+
+ len = ltoh16(*(uint16*)(PKTDATA(di->osh, p)));
+ DMA_TRACE(("%s: dma_rx len %d\n", di->name, len));
+
+ /* bad frame length check */
+ if (len > (di->rxbufsize - di->rxoffset)) {
+ DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n", di->name, len));
+ if (len > 0)
+ skiplen = len - (di->rxbufsize - di->rxoffset);
+ PKTFREE(di->osh, p, FALSE);
+ di->hnddma.rxgiants++;
+ continue;
+ }
+
+ /* set actual length */
+ PKTSETLEN(di->osh, p, (di->rxoffset + len));
+
+ break;
+ }
+
+ return (p);
+}
+
+/* post receive buffers */
+static void
+_dma_rxfill(dma_info_t *di)
+{
+ void *p;
+ uint rxin, rxout;
+ uint32 flags = 0;
+ uint n;
+ uint i;
+ uint32 pa;
+ uint extra_offset = 0;
+
+ /*
+ * Determine how many receive buffers we're lacking
+ * from the full complement, allocate, initialize,
+ * and post them, then update the chip rx lastdscr.
+ */
+
+ rxin = di->rxin;
+ rxout = di->rxout;
+
+ n = di->nrxpost - NRXDACTIVE(rxin, rxout);
+
+ DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n));
+
+ if (di->rxbufsize > BCMEXTRAHDROOM)
+ extra_offset = BCMEXTRAHDROOM;
+
+ for (i = 0; i < n; i++) {
+ /* the di->rxbufsize doesn't include the extra headroom, we need to add it to the
+ size to be allocated
+ */
+ if ((p = PKTGET(di->osh, di->rxbufsize + extra_offset,
+ FALSE)) == NULL) {
+ DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n", di->name));
+ di->hnddma.rxnobuf++;
+ break;
+ }
+ /* reserve an extra headroom, if applicable */
+ if (extra_offset)
+ PKTPULL(di->osh, p, extra_offset);
+
+ /* Do a cached write instead of uncached write since DMA_MAP
+ * will flush the cache.
+ */
+ *(uint32*)(PKTDATA(di->osh, p)) = 0;
+
+ pa = (uint32) DMA_MAP(di->osh, PKTDATA(di->osh, p),
+ di->rxbufsize, DMA_RX, p);
+
+ ASSERT(ISALIGNED(pa, 4));
+
+ /* save the free packet pointer */
+ ASSERT(di->rxp[rxout] == NULL);
+ di->rxp[rxout] = p;
+
+ /* reset flags for each descriptor */
+ flags = 0;
+ if (rxout == (di->nrxd - 1))
+ flags = CTRL_EOT;
+ dma32_dd_upd(di, di->rxd32, pa, rxout, &flags, di->rxbufsize);
+ rxout = NEXTRXD(rxout);
+ }
+
+ di->rxout = rxout;
+
+ /* update the chip lastdscr pointer */
+ W_REG(di->osh, &di->d32rxregs->ptr, I2B(rxout, dma32dd_t));
+}
+
+/* like getnexttxp but no reclaim */
+static void *
+_dma_peeknexttxp(dma_info_t *di)
+{
+ uint end, i;
+
+ if (di->ntxd == 0)
+ return (NULL);
+
+ end = B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t);
+
+ for (i = di->txin; i != end; i = NEXTTXD(i))
+ if (di->txp[i])
+ return (di->txp[i]);
+
+ return (NULL);
+}
+
+static void
+_dma_rxreclaim(dma_info_t *di)
+{
+ void *p;
+
+ /* "unused local" warning suppression for OSLs that
+ * define PKTFREE() without using the di->osh arg
+ */
+ di = di;
+
+ DMA_TRACE(("%s: dma_rxreclaim\n", di->name));
+
+ while ((p = _dma_getnextrxp(di, TRUE)))
+ PKTFREE(di->osh, p, FALSE);
+}
+
+static void *
+_dma_getnextrxp(dma_info_t *di, bool forceall)
+{
+ if (di->nrxd == 0)
+ return (NULL);
+
+ return dma32_getnextrxp(di, forceall);
+}
+
+static void
+_dma_txblock(dma_info_t *di)
+{
+ di->hnddma.txavail = 0;
+}
+
+static void
+_dma_txunblock(dma_info_t *di)
+{
+ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
+}
+
+static uint
+_dma_txactive(dma_info_t *di)
+{
+ return (NTXDACTIVE(di->txin, di->txout));
+}
+
+static void
+_dma_counterreset(dma_info_t *di)
+{
+ /* reset all software counter */
+ di->hnddma.rxgiants = 0;
+ di->hnddma.rxnobuf = 0;
+ di->hnddma.txnobuf = 0;
+}
+
+/* get the address of the var in order to change later */
+static uintptr
+_dma_getvar(dma_info_t *di, char *name)
+{
+ if (!strcmp(name, "&txavail"))
+ return ((uintptr) &(di->hnddma.txavail));
+ else {
+ ASSERT(0);
+ }
+ return (0);
+}
+
+void
+dma_txpioloopback(osl_t *osh, dma32regs_t *regs)
+{
+ OR_REG(osh, &regs->control, XC_LE);
+}
+
+
+
+/* 32 bits DMA functions */
+static void
+dma32_txinit(dma_info_t *di)
+{
+ DMA_TRACE(("%s: dma_txinit\n", di->name));
+
+ if (di->ntxd == 0)
+ return;
+
+ di->txin = di->txout = 0;
+ di->hnddma.txavail = di->ntxd - 1;
+
+ /* clear tx descriptor ring */
+ BZERO_SM((void *)di->txd32, (di->ntxd * sizeof(dma32dd_t)));
+ W_REG(di->osh, &di->d32txregs->control, XC_XE);
+ _dma_ddtable_init(di, DMA_TX, di->txdpa);
+}
+
+static bool
+dma32_txenabled(dma_info_t *di)
+{
+ uint32 xc;
+
+ /* If the chip is dead, it is not enabled :-) */
+ xc = R_REG(di->osh, &di->d32txregs->control);
+ return ((xc != 0xffffffff) && (xc & XC_XE));
+}
+
+static void
+dma32_txsuspend(dma_info_t *di)
+{
+ DMA_TRACE(("%s: dma_txsuspend\n", di->name));
+
+ if (di->ntxd == 0)
+ return;
+
+ OR_REG(di->osh, &di->d32txregs->control, XC_SE);
+}
+
+static void
+dma32_txresume(dma_info_t *di)
+{
+ DMA_TRACE(("%s: dma_txresume\n", di->name));
+
+ if (di->ntxd == 0)
+ return;
+
+ AND_REG(di->osh, &di->d32txregs->control, ~XC_SE);
+}
+
+static bool
+dma32_txsuspended(dma_info_t *di)
+{
+ return (di->ntxd == 0) || ((R_REG(di->osh, &di->d32txregs->control) & XC_SE) == XC_SE);
+}
+
+static void
+dma32_txreclaim(dma_info_t *di, bool forceall)
+{
+ void *p;
+
+ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, forceall ? "all" : ""));
+
+ while ((p = dma32_getnexttxp(di, forceall)))
+ PKTFREE(di->osh, p, TRUE);
+}
+
+static bool
+dma32_txstopped(dma_info_t *di)
+{
+ return ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) == XS_XS_STOPPED);
+}
+
+static bool
+dma32_rxstopped(dma_info_t *di)
+{
+ return ((R_REG(di->osh, &di->d32rxregs->status) & RS_RS_MASK) == RS_RS_STOPPED);
+}
+
+static bool
+dma32_alloc(dma_info_t *di, uint direction)
+{
+ uint size;
+ uint ddlen;
+ void *va;
+
+ ddlen = sizeof(dma32dd_t);
+
+ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen);
+
+ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, D32RINGALIGN))
+ size += D32RINGALIGN;
+
+
+ if (direction == DMA_TX) {
+ if ((va = DMA_ALLOC_CONSISTENT(di->osh, size, &di->txdpa, &di->tx_dmah)) == NULL) {
+ DMA_ERROR(("%s: dma_attach: DMA_ALLOC_CONSISTENT(ntxd) failed\n",
+ di->name));
+ return FALSE;
+ }
+
+ di->txd32 = (dma32dd_t *) ROUNDUP((uintptr)va, D32RINGALIGN);
+ di->txdalign = (uint)((int8*)di->txd32 - (int8*)va);
+ di->txdpa += di->txdalign;
+ di->txdalloc = size;
+ ASSERT(ISALIGNED((uintptr)di->txd32, D32RINGALIGN));
+ } else {
+ if ((va = DMA_ALLOC_CONSISTENT(di->osh, size, &di->rxdpa, &di->rx_dmah)) == NULL) {
+ DMA_ERROR(("%s: dma_attach: DMA_ALLOC_CONSISTENT(nrxd) failed\n",
+ di->name));
+ return FALSE;
+ }
+ di->rxd32 = (dma32dd_t *) ROUNDUP((uintptr)va, D32RINGALIGN);
+ di->rxdalign = (uint)((int8*)di->rxd32 - (int8*)va);
+ di->rxdpa += di->rxdalign;
+ di->rxdalloc = size;
+ ASSERT(ISALIGNED((uintptr)di->rxd32, D32RINGALIGN));
+ }
+
+ return TRUE;
+}
+
+static bool
+dma32_txreset(dma_info_t *di)
+{
+ uint32 status;
+
+ if (di->ntxd == 0)
+ return TRUE;
+
+ /* suspend tx DMA first */
+ W_REG(di->osh, &di->d32txregs->control, XC_SE);
+ SPINWAIT(((status = (R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK))
+ != XS_XS_DISABLED) &&
+ (status != XS_XS_IDLE) &&
+ (status != XS_XS_STOPPED),
+ (10000));
+
+ W_REG(di->osh, &di->d32txregs->control, 0);
+ SPINWAIT(((status = (R_REG(di->osh,
+ &di->d32txregs->status) & XS_XS_MASK)) != XS_XS_DISABLED),
+ 10000);
+
+ /* wait for the last transaction to complete */
+ OSL_DELAY(300);
+
+ return (status == XS_XS_DISABLED);
+}
+
+static bool
+dma32_rxidle(dma_info_t *di)
+{
+ DMA_TRACE(("%s: dma_rxidle\n", di->name));
+
+ if (di->nrxd == 0)
+ return TRUE;
+
+ return ((R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK) ==
+ R_REG(di->osh, &di->d32rxregs->ptr));
+}
+
+static bool
+dma32_rxreset(dma_info_t *di)
+{
+ uint32 status;
+
+ if (di->nrxd == 0)
+ return TRUE;
+
+ W_REG(di->osh, &di->d32rxregs->control, 0);
+ SPINWAIT(((status = (R_REG(di->osh,
+ &di->d32rxregs->status) & RS_RS_MASK)) != RS_RS_DISABLED),
+ 10000);
+
+ return (status == RS_RS_DISABLED);
+}
+
+static bool
+dma32_rxenabled(dma_info_t *di)
+{
+ uint32 rc;
+
+ rc = R_REG(di->osh, &di->d32rxregs->control);
+ return ((rc != 0xffffffff) && (rc & RC_RE));
+}
+
+static bool
+dma32_txsuspendedidle(dma_info_t *di)
+{
+ if (di->ntxd == 0)
+ return TRUE;
+
+ if (!(R_REG(di->osh, &di->d32txregs->control) & XC_SE))
+ return 0;
+
+ if ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) != XS_XS_IDLE)
+ return 0;
+
+ OSL_DELAY(2);
+ return ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) == XS_XS_IDLE);
+}
+
+/* !! tx entry routine
+ * supports full 32bit dma engine buffer addressing so
+ * dma buffers can cross 4 Kbyte page boundaries.
+ */
+static int
+dma32_txfast(dma_info_t *di, void *p0, bool commit)
+{
+ void *p, *next;
+ uchar *data;
+ uint len;
+ uint txout;
+ uint32 flags = 0;
+ uint32 pa;
+
+ DMA_TRACE(("%s: dma_txfast\n", di->name));
+
+ txout = di->txout;
+
+ /*
+ * Walk the chain of packet buffers
+ * allocating and initializing transmit descriptor entries.
+ */
+ for (p = p0; p; p = next) {
+ data = PKTDATA(di->osh, p);
+ len = PKTLEN(di->osh, p);
+ next = PKTNEXT(di->osh, p);
+
+ /* return nonzero if out of tx descriptors */
+ if (NEXTTXD(txout) == di->txin)
+ goto outoftxd;
+
+ if (len == 0)
+ continue;
+
+ /* get physical address of buffer start */
+ pa = (uint32) DMA_MAP(di->osh, data, len, DMA_TX, p);
+
+ flags = 0;
+ if (p == p0)
+ flags |= CTRL_SOF;
+ if (next == NULL)
+ flags |= (CTRL_IOC | CTRL_EOF);
+ if (txout == (di->ntxd - 1))
+ flags |= CTRL_EOT;
+
+ dma32_dd_upd(di, di->txd32, pa, txout, &flags, len);
+ ASSERT(di->txp[txout] == NULL);
+
+ txout = NEXTTXD(txout);
+ }
+
+ /* if last txd eof not set, fix it */
+ if (!(flags & CTRL_EOF))
+ W_SM(&di->txd32[PREVTXD(txout)].ctrl, BUS_SWAP32(flags | CTRL_IOC | CTRL_EOF));
+
+ /* save the packet */
+ di->txp[PREVTXD(txout)] = p0;
+
+ /* bump the tx descriptor index */
+ di->txout = txout;
+
+ /* kick the chip */
+ if (commit)
+ W_REG(di->osh, &di->d32txregs->ptr, I2B(txout, dma32dd_t));
+
+ /* tx flow control */
+ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
+
+ return (0);
+
+outoftxd:
+ DMA_ERROR(("%s: dma_txfast: out of txds\n", di->name));
+ PKTFREE(di->osh, p0, TRUE);
+ di->hnddma.txavail = 0;
+ di->hnddma.txnobuf++;
+ return (-1);
+}
+
+/*
+ * Reclaim next completed txd (txds if using chained buffers) and
+ * return associated packet.
+ * If 'force' is true, reclaim txd(s) and return associated packet
+ * regardless of the value of the hardware "curr" pointer.
+ */
+static void *
+dma32_getnexttxp(dma_info_t *di, bool forceall)
+{
+ uint start, end, i;
+ void *txp;
+
+ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, forceall ? "all" : ""));
+
+ if (di->ntxd == 0)
+ return (NULL);
+
+ txp = NULL;
+
+ start = di->txin;
+ if (forceall)
+ end = di->txout;
+ else
+ end = B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t);
+
+ if ((start == 0) && (end > di->txout))
+ goto bogus;
+
+ for (i = start; i != end && !txp; i = NEXTTXD(i)) {
+ DMA_UNMAP(di->osh, (BUS_SWAP32(R_SM(&di->txd32[i].addr)) - di->dataoffsetlow),
+ (BUS_SWAP32(R_SM(&di->txd32[i].ctrl)) & CTRL_BC_MASK),
+ DMA_TX, di->txp[i]);
+
+ W_SM(&di->txd32[i].addr, 0xdeadbeef);
+ txp = di->txp[i];
+ di->txp[i] = NULL;
+ }
+
+ di->txin = i;
+
+ /* tx flow control */
+ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
+
+ return (txp);
+
+bogus:
+/*
+ DMA_ERROR(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n",
+ start, end, di->txout, forceall));
+*/
+ return (NULL);
+}
+
+static void *
+dma32_getnextrxp(dma_info_t *di, bool forceall)
+{
+ uint i;
+ void *rxp;
+
+ /* if forcing, dma engine must be disabled */
+ ASSERT(!forceall || !dma32_rxenabled(di));
+
+ i = di->rxin;
+
+ /* return if no packets posted */
+ if (i == di->rxout)
+ return (NULL);
+
+ /* ignore curr if forceall */
+ if (!forceall && (i == B2I(R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK, dma32dd_t)))
+ return (NULL);
+
+ /* get the packet pointer that corresponds to the rx descriptor */
+ rxp = di->rxp[i];
+ ASSERT(rxp);
+ di->rxp[i] = NULL;
+
+ /* clear this packet from the descriptor ring */
+ DMA_UNMAP(di->osh, (BUS_SWAP32(R_SM(&di->rxd32[i].addr)) - di->dataoffsetlow),
+ di->rxbufsize, DMA_RX, rxp);
+
+ W_SM(&di->rxd32[i].addr, 0xdeadbeef);
+
+ di->rxin = NEXTRXD(i);
+
+ return (rxp);
+}
+
+/*
+ * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin).
+ */
+static void
+dma32_txrotate(dma_info_t *di)
+{
+ uint ad;
+ uint nactive;
+ uint rot;
+ uint old, new;
+ uint32 w;
+ uint first, last;
+
+ ASSERT(dma32_txsuspendedidle(di));
+
+ nactive = _dma_txactive(di);
+ ad = B2I(((R_REG(di->osh, &di->d32txregs->status) & XS_AD_MASK) >> XS_AD_SHIFT), dma32dd_t);
+ rot = TXD(ad - di->txin);
+
+ ASSERT(rot < di->ntxd);
+
+ /* full-ring case is a lot harder - don't worry about this */
+ if (rot >= (di->ntxd - nactive)) {
+ DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name));
+ return;
+ }
+
+ first = di->txin;
+ last = PREVTXD(di->txout);
+
+ /* move entries starting at last and moving backwards to first */
+ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) {
+ new = TXD(old + rot);
+
+ /*
+ * Move the tx dma descriptor.
+ * EOT is set only in the last entry in the ring.
+ */
+ w = BUS_SWAP32(R_SM(&di->txd32[old].ctrl)) & ~CTRL_EOT;
+ if (new == (di->ntxd - 1))
+ w |= CTRL_EOT;
+ W_SM(&di->txd32[new].ctrl, BUS_SWAP32(w));
+ W_SM(&di->txd32[new].addr, R_SM(&di->txd32[old].addr));
+
+ /* zap the old tx dma descriptor address field */
+ W_SM(&di->txd32[old].addr, BUS_SWAP32(0xdeadbeef));
+
+ /* move the corresponding txp[] entry */
+ ASSERT(di->txp[new] == NULL);
+ di->txp[new] = di->txp[old];
+ di->txp[old] = NULL;
+ }
+
+ /* update txin and txout */
+ di->txin = ad;
+ di->txout = TXD(di->txout + rot);
+ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
+
+ /* kick the chip */
+ W_REG(di->osh, &di->d32txregs->ptr, I2B(di->txout, dma32dd_t));
+}
+
+
+uint
+dma_addrwidth(sb_t *sbh, void *dmaregs)
+{
+ dma32regs_t *dma32regs;
+ osl_t *osh;
+
+ osh = sb_osh(sbh);
+
+ /* Start checking for 32-bit / 30-bit addressing */
+ dma32regs = (dma32regs_t *)dmaregs;
+
+ /* For System Backplane, PCIE bus or addrext feature, 32-bits ok */
+ if ((BUSTYPE(sbh->bustype) == SB_BUS) ||
+ ((BUSTYPE(sbh->bustype) == PCI_BUS) && sbh->buscoretype == SB_PCIE) ||
+ (_dma32_addrext(osh, dma32regs)))
+ return (DMADDRWIDTH_32);
+
+ /* Fallthru */
+ return (DMADDRWIDTH_30);
+}
diff --git a/package/broadcom-wl/src/kmod/hnddma.h b/package/broadcom-wl/src/kmod/hnddma.h
new file mode 100644
index 0000000000..de74c067b2
--- /dev/null
+++ b/package/broadcom-wl/src/kmod/hnddma.h
@@ -0,0 +1,156 @@
+/*
+ * Generic Broadcom Home Networking Division (HND) DMA engine SW interface
+ * This supports the following chips: BCM42xx, 44xx, 47xx .
+ *
+ * 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.
+ * $Id: hnddma.h,v 1.1.1.13 2006/04/08 06:13:39 honor Exp $
+ */
+
+#ifndef _hnddma_h_
+#define _hnddma_h_
+
+typedef const struct hnddma_pub hnddma_t;
+
+/* dma function type */
+typedef void (*di_detach_t)(hnddma_t *dmah);
+typedef bool (*di_txreset_t)(hnddma_t *dmah);
+typedef bool (*di_rxreset_t)(hnddma_t *dmah);
+typedef bool (*di_rxidle_t)(hnddma_t *dmah);
+typedef void (*di_txinit_t)(hnddma_t *dmah);
+typedef bool (*di_txenabled_t)(hnddma_t *dmah);
+typedef void (*di_rxinit_t)(hnddma_t *dmah);
+typedef void (*di_txsuspend_t)(hnddma_t *dmah);
+typedef void (*di_txresume_t)(hnddma_t *dmah);
+typedef bool (*di_txsuspended_t)(hnddma_t *dmah);
+typedef bool (*di_txsuspendedidle_t)(hnddma_t *dmah);
+typedef int (*di_txfast_t)(hnddma_t *dmah, void *p, bool commit);
+typedef void (*di_fifoloopbackenable_t)(hnddma_t *dmah);
+typedef bool (*di_txstopped_t)(hnddma_t *dmah);
+typedef bool (*di_rxstopped_t)(hnddma_t *dmah);
+typedef bool (*di_rxenable_t)(hnddma_t *dmah);
+typedef bool (*di_rxenabled_t)(hnddma_t *dmah);
+typedef void* (*di_rx_t)(hnddma_t *dmah);
+typedef void (*di_rxfill_t)(hnddma_t *dmah);
+typedef void (*di_txreclaim_t)(hnddma_t *dmah, bool forceall);
+typedef void (*di_rxreclaim_t)(hnddma_t *dmah);
+typedef uintptr (*di_getvar_t)(hnddma_t *dmah, char *name);
+typedef void* (*di_getnexttxp_t)(hnddma_t *dmah, bool forceall);
+typedef void* (*di_getnextrxp_t)(hnddma_t *dmah, bool forceall);
+typedef void* (*di_peeknexttxp_t)(hnddma_t *dmah);
+typedef void (*di_txblock_t)(hnddma_t *dmah);
+typedef void (*di_txunblock_t)(hnddma_t *dmah);
+typedef uint (*di_txactive_t)(hnddma_t *dmah);
+typedef void (*di_txrotate_t)(hnddma_t *dmah);
+typedef void (*di_counterreset_t)(hnddma_t *dmah);
+typedef char* (*di_dump_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring);
+typedef char* (*di_dumptx_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring);
+typedef char* (*di_dumprx_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring);
+
+/* dma opsvec */
+typedef struct di_fcn_s {
+ di_detach_t detach;
+ di_txinit_t txinit;
+ di_txreset_t txreset;
+ di_txenabled_t txenabled;
+ di_txsuspend_t txsuspend;
+ di_txresume_t txresume;
+ di_txsuspended_t txsuspended;
+ di_txsuspendedidle_t txsuspendedidle;
+ di_txfast_t txfast;
+ di_txstopped_t txstopped;
+ di_txreclaim_t txreclaim;
+ di_getnexttxp_t getnexttxp;
+ di_peeknexttxp_t peeknexttxp;
+ di_txblock_t txblock;
+ di_txunblock_t txunblock;
+ di_txactive_t txactive;
+ di_txrotate_t txrotate;
+
+ di_rxinit_t rxinit;
+ di_rxreset_t rxreset;
+ di_rxidle_t rxidle;
+ di_rxstopped_t rxstopped;
+ di_rxenable_t rxenable;
+ di_rxenabled_t rxenabled;
+ di_rx_t rx;
+ di_rxfill_t rxfill;
+ di_rxreclaim_t rxreclaim;
+ di_getnextrxp_t getnextrxp;
+
+ di_fifoloopbackenable_t fifoloopbackenable;
+ di_getvar_t d_getvar;
+ di_counterreset_t counterreset;
+ di_dump_t dump;
+ di_dumptx_t dumptx;
+ di_dumprx_t dumprx;
+ uint endnum;
+} di_fcn_t;
+
+/*
+ * Exported data structure (read-only)
+ */
+/* export structure */
+struct hnddma_pub {
+ di_fcn_t di_fn; /* DMA function pointers */
+ uint txavail; /* # free tx descriptors */
+
+ /* rx error counters */
+ uint rxgiants; /* rx giant frames */
+ uint rxnobuf; /* rx out of dma descriptors */
+ /* tx error counters */
+ uint txnobuf; /* tx out of dma descriptors */
+};
+
+
+extern hnddma_t * dma_attach(osl_t *osh, char *name, sb_t *sbh, void *dmaregstx, void *dmaregsrx,
+ uint ntxd, uint nrxd, uint rxbufsize, uint nrxpost, uint rxoffset,
+ uint *msg_level);
+#define dma_detach(di) ((di)->di_fn.detach(di))
+#define dma_txreset(di) ((di)->di_fn.txreset(di))
+#define dma_rxreset(di) ((di)->di_fn.rxreset(di))
+#define dma_rxidle(di) ((di)->di_fn.rxidle(di))
+#define dma_txinit(di) ((di)->di_fn.txinit(di))
+#define dma_txenabled(di) ((di)->di_fn.txenabled(di))
+#define dma_rxinit(di) ((di)->di_fn.rxinit(di))
+#define dma_txsuspend(di) ((di)->di_fn.txsuspend(di))
+#define dma_txresume(di) ((di)->di_fn.txresume(di))
+#define dma_txsuspended(di) ((di)->di_fn.txsuspended(di))
+#define dma_txsuspendedidle(di) ((di)->di_fn.txsuspendedidle(di))
+#define dma_txfast(di, p, commit) ((di)->di_fn.txfast(di, p, commit))
+#define dma_fifoloopbackenable(di) ((di)->di_fn.fifoloopbackenable(di))
+#define dma_txstopped(di) ((di)->di_fn.txstopped(di))
+#define dma_rxstopped(di) ((di)->di_fn.rxstopped(di))
+#define dma_rxenable(di) ((di)->di_fn.rxenable(di))
+#define dma_rxenabled(di) ((di)->di_fn.rxenabled(di))
+#define dma_rx(di) ((di)->di_fn.rx(di))
+#define dma_rxfill(di) ((di)->di_fn.rxfill(di))
+#define dma_txreclaim(di, forceall) ((di)->di_fn.txreclaim(di, forceall))
+#define dma_rxreclaim(di) ((di)->di_fn.rxreclaim(di))
+#define dma_getvar(di, name) ((di)->di_fn.d_getvar(di, name))
+#define dma_getnexttxp(di, forceall) ((di)->di_fn.getnexttxp(di, forceall))
+#define dma_getnextrxp(di, forceall) ((di)->di_fn.getnextrxp(di, forceall))
+#define dma_peeknexttxp(di) ((di)->di_fn.peeknexttxp(di))
+#define dma_txblock(di) ((di)->di_fn.txblock(di))
+#define dma_txunblock(di) ((di)->di_fn.txunblock(di))
+#define dma_txactive(di) ((di)->di_fn.txactive(di))
+#define dma_txrotate(di) ((di)->di_fn.txrotate(di))
+#define dma_counterreset(di) ((di)->di_fn.counterreset(di))
+
+#define DMA_DUMP_SIZE 2048
+/* return addresswidth allowed
+ * This needs to be done after SB attach but before dma attach.
+ * SB attach provides ability to probe backplane and dma core capabilities
+ * This info is needed by DMA_ALLOC_CONSISTENT in dma attach
+ */
+extern uint dma_addrwidth(sb_t *sbh, void *dmaregs);
+
+/* pio helpers */
+void dma_txpioloopback(osl_t *osh, dma32regs_t *);
+
+#endif /* _hnddma_h_ */
diff --git a/package/broadcom-wl/src/kmod/linux_osl.c b/package/broadcom-wl/src/kmod/linux_osl.c
new file mode 100644
index 0000000000..d702961032
--- /dev/null
+++ b/package/broadcom-wl/src/kmod/linux_osl.c
@@ -0,0 +1,269 @@
+/*
+ * Linux OS Independent Layer
+ *
+ * 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.
+ *
+ * $Id: linux_osl.c,v 1.1.1.14 2006/04/08 06:13:39 honor Exp $
+ */
+
+#define LINUX_OSL
+
+#include <typedefs.h>
+#include <bcmendian.h>
+#include <linux/module.h>
+#include <linuxver.h>
+#include <bcmdefs.h>
+#include <osl.h>
+#include "linux_osl.h"
+#include <bcmutils.h>
+#include <linux/delay.h>
+#ifdef mips
+#include <asm/paccess.h>
+#endif /* mips */
+#include <pcicfg.h>
+
+#define PCI_CFG_RETRY 10
+
+#define OS_HANDLE_MAGIC 0x1234abcd /* Magic # to recognise osh */
+#define BCM_MEM_FILENAME_LEN 24 /* Mem. filename length */
+
+typedef struct bcm_mem_link {
+ struct bcm_mem_link *prev;
+ struct bcm_mem_link *next;
+ uint size;
+ int line;
+ char file[BCM_MEM_FILENAME_LEN];
+} bcm_mem_link_t;
+
+static int16 linuxbcmerrormap[] = \
+{ 0, /* 0 */
+ -EINVAL, /* BCME_ERROR */
+ -EINVAL, /* BCME_BADARG */
+ -EINVAL, /* BCME_BADOPTION */
+ -EINVAL, /* BCME_NOTUP */
+ -EINVAL, /* BCME_NOTDOWN */
+ -EINVAL, /* BCME_NOTAP */
+ -EINVAL, /* BCME_NOTSTA */
+ -EINVAL, /* BCME_BADKEYIDX */
+ -EINVAL, /* BCME_RADIOOFF */
+ -EINVAL, /* BCME_NOTBANDLOCKED */
+ -EINVAL, /* BCME_NOCLK */
+ -EINVAL, /* BCME_BADRATESET */
+ -EINVAL, /* BCME_BADBAND */
+ -E2BIG, /* BCME_BUFTOOSHORT */
+ -E2BIG, /* BCME_BUFTOOLONG */
+ -EBUSY, /* BCME_BUSY */
+ -EINVAL, /* BCME_NOTASSOCIATED */
+ -EINVAL, /* BCME_BADSSIDLEN */
+ -EINVAL, /* BCME_OUTOFRANGECHAN */
+ -EINVAL, /* BCME_BADCHAN */
+ -EFAULT, /* BCME_BADADDR */
+ -ENOMEM, /* BCME_NORESOURCE */
+ -EOPNOTSUPP, /* BCME_UNSUPPORTED */
+ -EMSGSIZE, /* BCME_BADLENGTH */
+ -EINVAL, /* BCME_NOTREADY */
+ -EPERM, /* BCME_NOTPERMITTED */
+ -ENOMEM, /* BCME_NOMEM */
+ -EINVAL, /* BCME_ASSOCIATED */
+ -ERANGE, /* BCME_RANGE */
+ -EINVAL, /* BCME_NOTFOUND */
+ -EINVAL, /* BCME_WME_NOT_ENABLED */
+ -EINVAL, /* BCME_TSPEC_NOTFOUND */
+ -EINVAL, /* BCME_ACM_NOTSUPPORTED */
+ -EINVAL, /* BCME_NOT_WME_ASSOCIATION */
+ -EIO, /* BCME_SDIO_ERROR */
+ -ENODEV /* BCME_DONGLE_DOWN */
+};
+
+/* translate bcmerrors into linux errors */
+int
+osl_error(int bcmerror)
+{
+ int abs_bcmerror;
+ int array_size = ARRAYSIZE(linuxbcmerrormap);
+
+ abs_bcmerror = ABS(bcmerror);
+
+ if (bcmerror > 0)
+ abs_bcmerror = 0;
+
+ else if (abs_bcmerror >= array_size)
+ abs_bcmerror = BCME_ERROR;
+
+ return linuxbcmerrormap[abs_bcmerror];
+}
+
+osl_t *
+osl_attach(void *pdev, bool pkttag)
+{
+ osl_t *osh;
+
+ osh = kmalloc(sizeof(osl_t), GFP_ATOMIC);
+ ASSERT(osh);
+
+ bzero(osh, sizeof(osl_t));
+
+ /*
+ * check the cases where
+ * 1.Error code Added to bcmerror table, but forgot to add it to the OS
+ * dependent error code
+ * 2. Error code is added to the bcmerror table, but forgot to add the
+ * corresponding errorstring(dummy call to bcmerrorstr)
+ */
+ bcmerrorstr(0);
+ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1));
+
+ osh->magic = OS_HANDLE_MAGIC;
+ osh->malloced = 0;
+ osh->failed = 0;
+ osh->dbgmem_list = NULL;
+ osh->pdev = pdev;
+ osh->pub.pkttag = pkttag;
+
+ return osh;
+}
+
+void
+osl_detach(osl_t *osh)
+{
+ if (osh == NULL)
+ return;
+
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+ kfree(osh);
+}
+
+/* Return a new packet. zero out pkttag */
+void*
+osl_pktget(osl_t *osh, uint len, bool send)
+{
+ struct sk_buff *skb;
+
+ if ((skb = dev_alloc_skb(len))) {
+ skb_put(skb, len);
+ skb->priority = 0;
+
+#ifdef BCMDBG_PKT
+ pktlist_add(&(osh->pktlist), (void *) skb);
+#endif /* BCMDBG_PKT */
+
+ osh->pub.pktalloced++;
+ }
+
+ return ((void*) skb);
+}
+
+/* Free the driver packet. Free the tag if present */
+void
+osl_pktfree(osl_t *osh, void *p)
+{
+ struct sk_buff *skb, *nskb;
+
+ skb = (struct sk_buff*) p;
+
+ /* perversion: we use skb->next to chain multi-skb packets */
+ while (skb) {
+ nskb = skb->next;
+ skb->next = NULL;
+
+#ifdef BCMDBG_PKT
+ pktlist_remove(&(osh->pktlist), (void *) skb);
+#endif /* BCMDBG_PKT */
+
+ if (skb->destructor) {
+ /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if destructor exists
+ */
+ dev_kfree_skb_any(skb);
+ } else {
+ /* can free immediately (even in_irq()) if destructor does not exist */
+ dev_kfree_skb(skb);
+ }
+
+ osh->pub.pktalloced--;
+
+ skb = nskb;
+ }
+}
+
+void*
+osl_malloc(osl_t *osh, uint size)
+{
+ void *addr;
+
+ /* only ASSERT if osh is defined */
+ if (osh)
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+
+ if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) {
+ if (osh)
+ osh->failed++;
+ return (NULL);
+ }
+ if (osh)
+ osh->malloced += size;
+
+ return (addr);
+}
+
+void
+osl_mfree(osl_t *osh, void *addr, uint size)
+{
+ if (osh) {
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+ osh->malloced -= size;
+ }
+ kfree(addr);
+}
+
+uint
+osl_malloced(osl_t *osh)
+{
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+ return (osh->malloced);
+}
+
+uint osl_malloc_failed(osl_t *osh)
+{
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+ return (osh->failed);
+}
+
+#undef osl_delay
+void
+osl_delay(uint usec)
+{
+ OSL_DELAY(usec);
+}
+
+/* Clone a packet.
+ * The pkttag contents are NOT cloned.
+ */
+void *
+osl_pktdup(osl_t *osh, void *skb)
+{
+ void * p;
+
+ if ((p = skb_clone((struct sk_buff*)skb, GFP_ATOMIC)) == NULL)
+ return NULL;
+
+ /* skb_clone copies skb->cb.. we don't want that */
+ if (osh->pub.pkttag)
+ bzero((void*)((struct sk_buff *)p)->cb, OSL_PKTTAG_SZ);
+
+ /* Increment the packet counter */
+ osh->pub.pktalloced++;
+ return (p);
+}
+
+uint
+osl_pktalloced(osl_t *osh)
+{
+ return (osh->pub.pktalloced);
+}
+
diff --git a/package/broadcom-wl/src/kmod/linux_osl.h b/package/broadcom-wl/src/kmod/linux_osl.h
new file mode 100644
index 0000000000..f6af6124c6
--- /dev/null
+++ b/package/broadcom-wl/src/kmod/linux_osl.h
@@ -0,0 +1,171 @@
+/*
+ * Linux OS Independent Layer
+ *
+ * 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.
+ *
+ * $Id: linux_osl.h,v 1.1.1.13 2006/04/08 06:13:39 honor Exp $
+ */
+
+#ifndef _linux_osl_h_
+#define _linux_osl_h_
+
+#include <typedefs.h>
+#include <linuxver.h>
+#include <osl.h>
+
+#define OSL_PKTTAG_SZ 32 /* Size of PktTag */
+
+/* osl handle type forward declaration */
+typedef struct osl_dmainfo osldma_t;
+
+/* OSL initialization */
+extern osl_t *osl_attach(void *pdev, bool pkttag);
+extern void osl_detach(osl_t *osh);
+
+/* host/bus architecture-specific byte swap */
+#define BUS_SWAP32(v) (v)
+#define MALLOC_FAILED(osh) osl_malloc_failed((osh))
+
+extern void *osl_malloc(osl_t *osh, uint size);
+extern void osl_mfree(osl_t *osh, void *addr, uint size);
+extern uint osl_malloced(osl_t *osh);
+extern uint osl_malloc_failed(osl_t *osh);
+
+/* API for DMA addressing capability */
+#define DMA_MAP(osh, va, size, direction, p) \
+ osl_dma_map((osh), (va), (size), (direction))
+#define DMA_UNMAP(osh, pa, size, direction, p) \
+ osl_dma_unmap((osh), (pa), (size), (direction))
+static inline uint
+osl_dma_map(void *osh, void *va, uint size, int direction)
+{
+ int dir;
+ struct pci_dev *dev;
+
+ dev = (osh == NULL ? NULL : ((osl_t *)osh)->pdev);
+ dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
+ return (pci_map_single(dev, va, size, dir));
+}
+
+static inline void
+osl_dma_unmap(void *osh, uint pa, uint size, int direction)
+{
+ int dir;
+ struct pci_dev *dev;
+
+ dev = (osh == NULL ? NULL : ((osl_t *)osh)->pdev);
+ dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
+ pci_unmap_single(dev, (uint32)pa, size, dir);
+}
+
+#define OSL_DMADDRWIDTH(osh, addrwidth) do {} while (0)
+#define DMA_CONSISTENT_ALIGN PAGE_SIZE
+#define DMA_ALLOC_CONSISTENT(osh, size, pap, dmah) \
+ osl_dma_alloc_consistent((osh), (size), (pap))
+#define DMA_FREE_CONSISTENT(osh, va, size, pa, dmah) \
+ osl_dma_free_consistent((osh), (void*)(va), (size), (pa))
+static inline void*
+osl_dma_alloc_consistent(osl_t *osh, uint size, ulong *pap)
+{
+ return (pci_alloc_consistent(osh->pdev, size, (dma_addr_t*)pap));
+}
+
+static inline void
+osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa)
+{
+ pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa);
+}
+
+
+/* register access macros */
+#if defined(BCMJTAG)
+#include <bcmjtag.h>
+#define R_REG(osh, r) bcmjtag_read(NULL, (uint32)(r), sizeof(*(r)))
+#define W_REG(osh, r, v) bcmjtag_write(NULL, (uint32)(r), (uint32)(v), sizeof(*(r)))
+#endif /* defined(BCMSDIO) */
+
+/* packet primitives */
+#define PKTGET(osh, len, send) osl_pktget((osh), (len), (send))
+#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb))
+#define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data)
+#define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len)
+#define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head))
+#define PKTTAILROOM(osh, skb) ((((struct sk_buff*)(skb))->end)-(((struct sk_buff*)(skb))->tail))
+#define PKTNEXT(osh, skb) (((struct sk_buff*)(skb))->next)
+#define PKTSETNEXT(osh, skb, x) (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x))
+#define PKTSETLEN(osh, skb, len) __skb_trim((struct sk_buff*)(skb), (len))
+#define PKTPUSH(osh, skb, bytes) skb_push((struct sk_buff*)(skb), (bytes))
+#define PKTPULL(osh, skb, bytes) skb_pull((struct sk_buff*)(skb), (bytes))
+#define PKTDUP(osh, skb) osl_pktdup((osh), (skb))
+#define PKTTAG(skb) ((void*)(((struct sk_buff*)(skb))->cb))
+#define PKTALLOCED(osh) osl_pktalloced((osh))
+#define PKTLIST_DUMP(osh, buf)
+
+/* Convert a native(OS) packet to driver packet.
+ * In the process, native packet is destroyed, there is no copying
+ * Also, a packettag is zeroed out
+ */
+static INLINE void *
+osl_pkt_frmnative(struct osl_pubinfo *osh, struct sk_buff *skb)
+{
+ struct sk_buff *nskb;
+
+ if (osh->pkttag)
+ bzero((void*)skb->cb, OSL_PKTTAG_SZ);
+
+ /* Increment the packet counter */
+ for (nskb = skb; nskb; nskb = nskb->next) {
+ osh->pktalloced++;
+ }
+
+ return (void *)skb;
+}
+#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((struct osl_pubinfo *)osh), \
+ (struct sk_buff*)(skb))
+
+/* Convert a driver packet to native(OS) packet
+ * In the process, packettag is zeroed out before sending up
+ * IP code depends on skb->cb to be setup correctly with various options
+ * In our case, that means it should be 0
+ */
+static INLINE struct sk_buff *
+osl_pkt_tonative(struct osl_pubinfo *osh, void *pkt)
+{
+ struct sk_buff *nskb;
+
+ if (osh->pkttag)
+ bzero(((struct sk_buff*)pkt)->cb, OSL_PKTTAG_SZ);
+
+ /* Decrement the packet counter */
+ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) {
+ osh->pktalloced--;
+ }
+
+ return (struct sk_buff *)pkt;
+}
+#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((struct osl_pubinfo *)(osh), (pkt))
+
+#define PKTLINK(skb) (((struct sk_buff*)(skb))->prev)
+#define PKTSETLINK(skb, x) (((struct sk_buff*)(skb))->prev = (struct sk_buff*)(x))
+#define PKTPRIO(skb) (((struct sk_buff*)(skb))->priority)
+#define PKTSETPRIO(skb, x) (((struct sk_buff*)(skb))->priority = (x))
+#define PKTSHARED(skb) (((struct sk_buff*)(skb))->cloned)
+
+extern void *osl_pktget(osl_t *osh, uint len, bool send);
+extern void osl_pktfree(osl_t *osh, void *skb);
+extern void *osl_pktdup(osl_t *osh, void *skb);
+extern uint osl_pktalloced(osl_t *osh);
+
+#define OSL_ERROR(bcmerror) osl_error(bcmerror)
+extern int osl_error(int bcmerror);
+
+/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */
+#define PKTBUFSZ 2048 /* largest reasonable packet buffer, driver uses for ethernet MTU */
+
+#endif /* _linux_osl_h_ */
diff --git a/package/broadcom-wl/src/kmod/patchtable.pl b/package/broadcom-wl/src/kmod/patchtable.pl
new file mode 100644
index 0000000000..6999735125
--- /dev/null
+++ b/package/broadcom-wl/src/kmod/patchtable.pl
@@ -0,0 +1,61 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2006 Felix Fietkau
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+use strict;
+
+my $TABLE = pack("V", 0xbadc0ded);
+my $TABLE_SIZE = 512;
+my $SLT1 = "\x01\x00\x00\x00";
+my $SLT2 = "\x02\x00\x00\x00";
+my $ACKW = "\x03\x00\x00\x00";
+my $PTABLE_END = "\xff\xff\xff\xff";
+
+my $addr = "";
+my $opcode = "";
+my $function = "";
+
+sub add_entry {
+ my $key = shift;
+ my $value = shift;
+ my $default = shift;
+
+ $TABLE .= $key;
+ $TABLE .= pack("V", $value);
+ $TABLE .= pack("V", $default);
+}
+
+while (<>) {
+ $addr = $opcode = "";
+ /^\w{8}\s*<(.*)>:$/ and $function = $1;
+ /^\s*(\w+):\s*(\w{8})\s*/ and do {
+ $addr = $1;
+ $opcode = $2;
+ };
+
+ ($function eq 'wlc_update_slot_timing') and do {
+ # li a2,9 -- short slot time
+ ($opcode eq '24060009') and add_entry($SLT1, hex($addr), hex($opcode));
+ # li v0,519 -- 510 + short slot time
+ ($opcode eq '24020207') and add_entry($SLT2, hex($addr), hex($opcode));
+
+ # li a2,20 -- long slot time
+ ($opcode eq '24060014') and add_entry($SLT1, hex($addr), hex($opcode));
+ # li v0,530 -- 510 + long slot time
+ ($opcode eq '24020212') and add_entry($SLT2, hex($addr), hex($opcode));
+ };
+ ($function eq 'wlc_d11hdrs') and do {
+ # ori s6,s6,0x1 -- ack flag (new)
+ ($opcode eq '36d60001') and add_entry($ACKW, hex($addr), hex($opcode));
+ # ori s3,s3,0x1 -- ack flag (old)
+ ($opcode eq '36730001') and add_entry($ACKW, hex($addr), hex($opcode));
+ }
+}
+
+$TABLE .= $PTABLE_END;
+$TABLE .= ("\x00" x ($TABLE_SIZE - length($TABLE)));
+print $TABLE;
diff --git a/package/broadcom-wl/src/kmod/pktq.h b/package/broadcom-wl/src/kmod/pktq.h
new file mode 100644
index 0000000000..7fe21815e8
--- /dev/null
+++ b/package/broadcom-wl/src/kmod/pktq.h
@@ -0,0 +1,97 @@
+/*
+ * Misc useful os-independent macros and functions.
+ *
+ * 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.
+ * $Id: bcmutils.h,v 1.1.1.16 2006/04/08 06:13:39 honor Exp $
+ */
+
+#ifndef _pktq_h_
+#define _pktq_h_
+#include <osl.h>
+
+/* osl multi-precedence packet queue */
+
+#define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */
+#define PKTQ_MAX_PREC 16 /* Maximum precedence levels */
+
+struct pktq {
+ struct pktq_prec {
+ void *head; /* first packet to dequeue */
+ void *tail; /* last packet to dequeue */
+ uint16 len; /* number of queued packets */
+ uint16 max; /* maximum number of queued packets */
+ } q[PKTQ_MAX_PREC];
+ uint16 num_prec; /* number of precedences in use */
+ uint16 hi_prec; /* rapid dequeue hint (>= highest non-empty prec) */
+ uint16 max; /* total max packets */
+ uint16 len; /* total number of packets */
+};
+
+#define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--)
+
+/* forward definition of ether_addr structure used by some function prototypes */
+
+struct ether_addr;
+
+/* operations on a specific precedence in packet queue */
+
+#define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max))
+#define pktq_plen(pq, prec) ((pq)->q[prec].len)
+#define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len)
+#define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max)
+#define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0)
+
+#define pktq_ppeek(pq, prec) ((pq)->q[prec].head)
+#define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail)
+
+extern void *pktq_penq(struct pktq *pq, int prec, void *p);
+extern void *pktq_penq_head(struct pktq *pq, int prec, void *p);
+extern void *pktq_pdeq(struct pktq *pq, int prec);
+extern void *pktq_pdeq_tail(struct pktq *pq, int prec);
+/* Empty the queue at particular precedence level */
+extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir);
+/* Remove a specified packet from its queue */
+extern bool pktq_pdel(struct pktq *pq, void *p, int prec);
+
+/* operations on a set of precedences in packet queue */
+
+extern int pktq_mlen(struct pktq *pq, uint prec_bmp);
+extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out);
+
+/* operations on packet queue as a whole */
+
+#define pktq_len(pq) ((int)(pq)->len)
+#define pktq_max(pq) ((int)(pq)->max)
+#define pktq_avail(pq) ((int)((pq)->max - (pq)->len))
+#define pktq_full(pq) ((pq)->len >= (pq)->max)
+#define pktq_empty(pq) ((pq)->len == 0)
+
+/* operations for single precedence queues */
+#define pktenq(pq, p) pktq_penq((pq), 0, (p))
+#define pktenq_head(pq, p) pktq_penq_head((pq), 0, (p))
+#define pktdeq(pq) pktq_pdeq((pq), 0)
+#define pktdeq_tail(pq) pktq_pdeq_tail((pq), 0)
+
+extern void pktq_init(struct pktq *pq, int num_prec, int max_len);
+/* prec_out may be NULL if caller is not interested in return value */
+extern void *pktq_deq(struct pktq *pq, int *prec_out);
+extern void *pktq_deq_tail(struct pktq *pq, int *prec_out);
+extern void *pktq_peek(struct pktq *pq, int *prec_out);
+extern void *pktq_peek_tail(struct pktq *pq, int *prec_out);
+extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir); /* Empty the entire queue */
+
+/* externs */
+/* packet */
+extern uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf);
+extern uint pkttotlen(osl_t *osh, void *p);
+extern void *pktlast(osl_t *osh, void *p);
+
+extern void pktsetprio(void *pkt, bool update_vtag);
+
+#endif /* _pktq_h_ */
diff --git a/package/broadcom-wl/src/kmod/sbhnddma.h b/package/broadcom-wl/src/kmod/sbhnddma.h
new file mode 100644
index 0000000000..a26db7395e
--- /dev/null
+++ b/package/broadcom-wl/src/kmod/sbhnddma.h
@@ -0,0 +1,284 @@
+/*
+ * Generic Broadcom Home Networking Division (HND) DMA engine HW interface
+ * This supports the following chips: BCM42xx, 44xx, 47xx .
+ *
+ * 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.
+ *
+ * $Id: sbhnddma.h,v 1.1.1.2 2006/02/27 03:43:16 honor Exp $
+ */
+
+#ifndef _sbhnddma_h_
+#define _sbhnddma_h_
+
+/* DMA structure:
+ * support two DMA engines: 32 bits address or 64 bit addressing
+ * basic DMA register set is per channel(transmit or receive)
+ * a pair of channels is defined for convenience
+ */
+
+
+/* 32 bits addressing */
+
+/* dma registers per channel(xmt or rcv) */
+typedef volatile struct {
+ uint32 control; /* enable, et al */
+ uint32 addr; /* descriptor ring base address (4K aligned) */
+ uint32 ptr; /* last descriptor posted to chip */
+ uint32 status; /* current active descriptor, et al */
+} dma32regs_t;
+
+typedef volatile struct {
+ dma32regs_t xmt; /* dma tx channel */
+ dma32regs_t rcv; /* dma rx channel */
+} dma32regp_t;
+
+typedef volatile struct { /* diag access */
+ uint32 fifoaddr; /* diag address */
+ uint32 fifodatalow; /* low 32bits of data */
+ uint32 fifodatahigh; /* high 32bits of data */
+ uint32 pad; /* reserved */
+} dma32diag_t;
+
+/*
+ * DMA Descriptor
+ * Descriptors are only read by the hardware, never written back.
+ */
+typedef volatile struct {
+ uint32 ctrl; /* misc control bits & bufcount */
+ uint32 addr; /* data buffer address */
+} dma32dd_t;
+
+/*
+ * Each descriptor ring must be 4096byte aligned, and fit within a single 4096byte page.
+ */
+#define D32MAXRINGSZ 4096
+#define D32RINGALIGN 4096
+#define D32MAXDD (D32MAXRINGSZ / sizeof (dma32dd_t))
+
+/* transmit channel control */
+#define XC_XE ((uint32)1 << 0) /* transmit enable */
+#define XC_SE ((uint32)1 << 1) /* transmit suspend request */
+#define XC_LE ((uint32)1 << 2) /* loopback enable */
+#define XC_FL ((uint32)1 << 4) /* flush request */
+#define XC_AE ((uint32)3 << 16) /* address extension bits */
+#define XC_AE_SHIFT 16
+
+/* transmit descriptor table pointer */
+#define XP_LD_MASK 0xfff /* last valid descriptor */
+
+/* transmit channel status */
+#define XS_CD_MASK 0x0fff /* current descriptor pointer */
+#define XS_XS_MASK 0xf000 /* transmit state */
+#define XS_XS_SHIFT 12
+#define XS_XS_DISABLED 0x0000 /* disabled */
+#define XS_XS_ACTIVE 0x1000 /* active */
+#define XS_XS_IDLE 0x2000 /* idle wait */
+#define XS_XS_STOPPED 0x3000 /* stopped */
+#define XS_XS_SUSP 0x4000 /* suspend pending */
+#define XS_XE_MASK 0xf0000 /* transmit errors */
+#define XS_XE_SHIFT 16
+#define XS_XE_NOERR 0x00000 /* no error */
+#define XS_XE_DPE 0x10000 /* descriptor protocol error */
+#define XS_XE_DFU 0x20000 /* data fifo underrun */
+#define XS_XE_BEBR 0x30000 /* bus error on buffer read */
+#define XS_XE_BEDA 0x40000 /* bus error on descriptor access */
+#define XS_AD_MASK 0xfff00000 /* active descriptor */
+#define XS_AD_SHIFT 20
+
+/* receive channel control */
+#define RC_RE ((uint32)1 << 0) /* receive enable */
+#define RC_RO_MASK 0xfe /* receive frame offset */
+#define RC_RO_SHIFT 1
+#define RC_FM ((uint32)1 << 8) /* direct fifo receive (pio) mode */
+#define RC_AE ((uint32)3 << 16) /* address extension bits */
+#define RC_AE_SHIFT 16
+
+/* receive descriptor table pointer */
+#define RP_LD_MASK 0xfff /* last valid descriptor */
+
+/* receive channel status */
+#define RS_CD_MASK 0x0fff /* current descriptor pointer */
+#define RS_RS_MASK 0xf000 /* receive state */
+#define RS_RS_SHIFT 12
+#define RS_RS_DISABLED 0x0000 /* disabled */
+#define RS_RS_ACTIVE 0x1000 /* active */
+#define RS_RS_IDLE 0x2000 /* idle wait */
+#define RS_RS_STOPPED 0x3000 /* reserved */
+#define RS_RE_MASK 0xf0000 /* receive errors */
+#define RS_RE_SHIFT 16
+#define RS_RE_NOERR 0x00000 /* no error */
+#define RS_RE_DPE 0x10000 /* descriptor protocol error */
+#define RS_RE_DFO 0x20000 /* data fifo overflow */
+#define RS_RE_BEBW 0x30000 /* bus error on buffer write */
+#define RS_RE_BEDA 0x40000 /* bus error on descriptor access */
+#define RS_AD_MASK 0xfff00000 /* active descriptor */
+#define RS_AD_SHIFT 20
+
+/* fifoaddr */
+#define FA_OFF_MASK 0xffff /* offset */
+#define FA_SEL_MASK 0xf0000 /* select */
+#define FA_SEL_SHIFT 16
+#define FA_SEL_XDD 0x00000 /* transmit dma data */
+#define FA_SEL_XDP 0x10000 /* transmit dma pointers */
+#define FA_SEL_RDD 0x40000 /* receive dma data */
+#define FA_SEL_RDP 0x50000 /* receive dma pointers */
+#define FA_SEL_XFD 0x80000 /* transmit fifo data */
+#define FA_SEL_XFP 0x90000 /* transmit fifo pointers */
+#define FA_SEL_RFD 0xc0000 /* receive fifo data */
+#define FA_SEL_RFP 0xd0000 /* receive fifo pointers */
+#define FA_SEL_RSD 0xe0000 /* receive frame status data */
+#define FA_SEL_RSP 0xf0000 /* receive frame status pointers */
+
+/* descriptor control flags */
+#define CTRL_BC_MASK 0x1fff /* buffer byte count */
+#define CTRL_AE ((uint32)3 << 16) /* address extension bits */
+#define CTRL_AE_SHIFT 16
+#define CTRL_EOT ((uint32)1 << 28) /* end of descriptor table */
+#define CTRL_IOC ((uint32)1 << 29) /* interrupt on completion */
+#define CTRL_EOF ((uint32)1 << 30) /* end of frame */
+#define CTRL_SOF ((uint32)1 << 31) /* start of frame */
+
+/* control flags in the range [27:20] are core-specific and not defined here */
+#define CTRL_CORE_MASK 0x0ff00000
+
+/* 64 bits addressing */
+
+/* dma registers per channel(xmt or rcv) */
+typedef volatile struct {
+ uint32 control; /* enable, et al */
+ uint32 ptr; /* last descriptor posted to chip */
+ uint32 addrlow; /* descriptor ring base address low 32-bits (8K aligned) */
+ uint32 addrhigh; /* descriptor ring base address bits 63:32 (8K aligned) */
+ uint32 status0; /* current descriptor, xmt state */
+ uint32 status1; /* active descriptor, xmt error */
+} dma64regs_t;
+
+typedef volatile struct {
+ dma64regs_t tx; /* dma64 tx channel */
+ dma64regs_t rx; /* dma64 rx channel */
+} dma64regp_t;
+
+typedef volatile struct { /* diag access */
+ uint32 fifoaddr; /* diag address */
+ uint32 fifodatalow; /* low 32bits of data */
+ uint32 fifodatahigh; /* high 32bits of data */
+ uint32 pad; /* reserved */
+} dma64diag_t;
+
+/*
+ * DMA Descriptor
+ * Descriptors are only read by the hardware, never written back.
+ */
+typedef volatile struct {
+ uint32 ctrl1; /* misc control bits & bufcount */
+ uint32 ctrl2; /* buffer count and address extension */
+ uint32 addrlow; /* memory address of the date buffer, bits 31:0 */
+ uint32 addrhigh; /* memory address of the date buffer, bits 63:32 */
+} dma64dd_t;
+
+/*
+ * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical addresss.
+ */
+#define D64MAXRINGSZ 8192
+#define D64RINGALIGN 8192
+#define D64MAXDD (D64MAXRINGSZ / sizeof (dma64dd_t))
+
+/* transmit channel control */
+#define D64_XC_XE 0x00000001 /* transmit enable */
+#define D64_XC_SE 0x00000002 /* transmit suspend request */
+#define D64_XC_LE 0x00000004 /* loopback enable */
+#define D64_XC_FL 0x00000010 /* flush request */
+#define D64_XC_AE 0x00030000 /* address extension bits */
+#define D64_XC_AE_SHIFT 16
+
+/* transmit descriptor table pointer */
+#define D64_XP_LD_MASK 0x00000fff /* last valid descriptor */
+
+/* transmit channel status */
+#define D64_XS0_CD_MASK 0x00001fff /* current descriptor pointer */
+#define D64_XS0_XS_MASK 0xf0000000 /* transmit state */
+#define D64_XS0_XS_SHIFT 28
+#define D64_XS0_XS_DISABLED 0x00000000 /* disabled */
+#define D64_XS0_XS_ACTIVE 0x10000000 /* active */
+#define D64_XS0_XS_IDLE 0x20000000 /* idle wait */
+#define D64_XS0_XS_STOPPED 0x30000000 /* stopped */
+#define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */
+
+#define D64_XS1_AD_MASK 0x0001ffff /* active descriptor */
+#define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */
+#define D64_XS1_XE_SHIFT 28
+#define D64_XS1_XE_NOERR 0x00000000 /* no error */
+#define D64_XS1_XE_DPE 0x10000000 /* descriptor protocol error */
+#define D64_XS1_XE_DFU 0x20000000 /* data fifo underrun */
+#define D64_XS1_XE_DTE 0x30000000 /* data transfer error */
+#define D64_XS1_XE_DESRE 0x40000000 /* descriptor read error */
+#define D64_XS1_XE_COREE 0x50000000 /* core error */
+
+/* receive channel control */
+#define D64_RC_RE 0x00000001 /* receive enable */
+#define D64_RC_RO_MASK 0x000000fe /* receive frame offset */
+#define D64_RC_RO_SHIFT 1
+#define D64_RC_FM 0x00000100 /* direct fifo receive (pio) mode */
+#define D64_RC_AE 0x00030000 /* address extension bits */
+#define D64_RC_AE_SHIFT 16
+
+/* receive descriptor table pointer */
+#define D64_RP_LD_MASK 0x00000fff /* last valid descriptor */
+
+/* receive channel status */
+#define D64_RS0_CD_MASK 0x00001fff /* current descriptor pointer */
+#define D64_RS0_RS_MASK 0xf0000000 /* receive state */
+#define D64_RS0_RS_SHIFT 28
+#define D64_RS0_RS_DISABLED 0x00000000 /* disabled */
+#define D64_RS0_RS_ACTIVE 0x10000000 /* active */
+#define D64_RS0_RS_IDLE 0x20000000 /* idle wait */
+#define D64_RS0_RS_STOPPED 0x30000000 /* stopped */
+#define D64_RS0_RS_SUSP 0x40000000 /* suspend pending */
+
+#define D64_RS1_AD_MASK 0x0001ffff /* active descriptor */
+#define D64_RS1_RE_MASK 0xf0000000 /* receive errors */
+#define D64_RS1_RE_SHIFT 28
+#define D64_RS1_RE_NOERR 0x00000000 /* no error */
+#define D64_RS1_RE_DPO 0x10000000 /* descriptor protocol error */
+#define D64_RS1_RE_DFU 0x20000000 /* data fifo overflow */
+#define D64_RS1_RE_DTE 0x30000000 /* data transfer error */
+#define D64_RS1_RE_DESRE 0x40000000 /* descriptor read error */
+#define D64_RS1_RE_COREE 0x50000000 /* core error */
+
+/* fifoaddr */
+#define D64_FA_OFF_MASK 0xffff /* offset */
+#define D64_FA_SEL_MASK 0xf0000 /* select */
+#define D64_FA_SEL_SHIFT 16
+#define D64_FA_SEL_XDD 0x00000 /* transmit dma data */
+#define D64_FA_SEL_XDP 0x10000 /* transmit dma pointers */
+#define D64_FA_SEL_RDD 0x40000 /* receive dma data */
+#define D64_FA_SEL_RDP 0x50000 /* receive dma pointers */
+#define D64_FA_SEL_XFD 0x80000 /* transmit fifo data */
+#define D64_FA_SEL_XFP 0x90000 /* transmit fifo pointers */
+#define D64_FA_SEL_RFD 0xc0000 /* receive fifo data */
+#define D64_FA_SEL_RFP 0xd0000 /* receive fifo pointers */
+#define D64_FA_SEL_RSD 0xe0000 /* receive frame status data */
+#define D64_FA_SEL_RSP 0xf0000 /* receive frame status pointers */
+
+/* descriptor control flags 1 */
+#define D64_CTRL1_EOT ((uint32)1 << 28) /* end of descriptor table */
+#define D64_CTRL1_IOC ((uint32)1 << 29) /* interrupt on completion */
+#define D64_CTRL1_EOF ((uint32)1 << 30) /* end of frame */
+#define D64_CTRL1_SOF ((uint32)1 << 31) /* start of frame */
+
+/* descriptor control flags 2 */
+#define D64_CTRL2_BC_MASK 0x00007fff /* buffer byte count mask */
+#define D64_CTRL2_AE 0x00030000 /* address extension bits */
+#define D64_CTRL2_AE_SHIFT 16
+
+/* control flags in the range [27:20] are core-specific and not defined here */
+#define D64_CTRL_CORE_MASK 0x0ff00000
+
+
+#endif /* _sbhnddma_h_ */
diff --git a/package/broadcom-wl/src/wlc/Makefile b/package/broadcom-wl/src/wlc/Makefile
new file mode 100644
index 0000000000..ffe1649515
--- /dev/null
+++ b/package/broadcom-wl/src/wlc/Makefile
@@ -0,0 +1,9 @@
+all: wlc
+clean:
+ rm -f *.o wlc
+
+wlc: wlc.o ioctl.o
+%.o: %.c
+ $(CC) $(CFLAGS) -Wall -c -o $@ $<
+
+.PHONY: all clean
diff --git a/package/broadcom-wl/src/wlc/include/bcmdefs.h b/package/broadcom-wl/src/wlc/include/bcmdefs.h
new file mode 100644
index 0000000000..8b5abe5d26
--- /dev/null
+++ b/package/broadcom-wl/src/wlc/include/bcmdefs.h
@@ -0,0 +1,106 @@
+/*
+ * Misc system wide definitions
+ *
+ * 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.
+ * $Id: bcmdefs.h,v 1.1.1.3 2006/04/08 06:13:39 honor Exp $
+ */
+
+#ifndef _bcmdefs_h_
+#define _bcmdefs_h_
+
+/*
+ * One doesn't need to include this file explicitly, gets included automatically if
+ * typedefs.h is included.
+ */
+
+/* Reclaiming text and data :
+ * The following macros specify special linker sections that can be reclaimed
+ * after a system is considered 'up'.
+ */
+#if defined(__GNUC__) && defined(BCMRECLAIM)
+extern bool bcmreclaimed;
+#define BCMINITDATA(_data) __attribute__ ((__section__ (".dataini." #_data))) _data
+#define BCMINITFN(_fn) __attribute__ ((__section__ (".textini." #_fn))) _fn
+#else /* #if defined(__GNUC__) && defined(BCMRECLAIM) */
+#define BCMINITDATA(_data) _data
+#define BCMINITFN(_fn) _fn
+#define bcmreclaimed 0
+#endif /* #if defined(__GNUC__) && defined(BCMRECLAIM) */
+
+/* Reclaim uninit functions if BCMNODOWN is defined */
+/* and if they are not already removed by -gc-sections */
+#ifdef BCMNODOWN
+#define BCMUNINITFN(_fn) BCMINITFN(_fn)
+#else
+#define BCMUNINITFN(_fn) _fn
+#endif
+
+#ifdef BCMRECLAIM
+#define CONST
+#else
+#define CONST const
+#endif /* BCMRECLAIM */
+
+/* Compatibility with old-style BCMRECLAIM */
+#define BCMINIT(_id) _id
+
+
+/* Put some library data/code into ROM to reduce RAM requirements */
+#if defined(__GNUC__) && defined(BCMROMOFFLOAD)
+#define BCMROMDATA(_data) __attribute__ ((__section__ (".datarom." #_data))) _data
+#define BCMROMFN(_fn) __attribute__ ((__section__ (".textrom." #_fn))) _fn
+#else
+#define BCMROMDATA(_data) _data
+#define BCMROMFN(_fn) _fn
+#endif
+
+/* Bus types */
+#define SB_BUS 0 /* Silicon Backplane */
+#define PCI_BUS 1 /* PCI target */
+#define PCMCIA_BUS 2 /* PCMCIA target */
+#define SDIO_BUS 3 /* SDIO target */
+#define JTAG_BUS 4 /* JTAG */
+#define NO_BUS 0xFF /* Bus that does not support R/W REG */
+
+/* Allows optimization for single-bus support */
+#ifdef BCMBUSTYPE
+#define BUSTYPE(bus) (BCMBUSTYPE)
+#else
+#define BUSTYPE(bus) (bus)
+#endif
+
+/* Defines for DMA Address Width - Shared between OSL and HNDDMA */
+#define DMADDR_MASK_32 0x0 /* Address mask for 32-bits */
+#define DMADDR_MASK_30 0xc0000000 /* Address mask for 30-bits */
+#define DMADDR_MASK_0 0xffffffff /* Address mask for 0-bits (hi-part) */
+
+#define DMADDRWIDTH_30 30 /* 30-bit addressing capability */
+#define DMADDRWIDTH_32 32 /* 32-bit addressing capability */
+#define DMADDRWIDTH_63 63 /* 64-bit addressing capability */
+#define DMADDRWIDTH_64 64 /* 64-bit addressing capability */
+
+/* packet headroom necessary to accomodate the largest header in the system, (i.e TXOFF).
+ * By doing, we avoid the need to allocate an extra buffer for the header when bridging to WL.
+ * There is a compile time check in wlc.c which ensure that this value is at least as big
+ * as TXOFF. This value is used in dma_rxfill (hnddma.c).
+ */
+#define BCMEXTRAHDROOM 160
+
+/* Headroom required for dongle-to-host communication. Packets allocated
+ * locally in the dongle (e.g. for CDC ioctls or RNDIS messages) should
+ * leave this much room in front for low-level message headers which may
+ * be needed to get across the dongle bus to the host. (These messages
+ * don't go over the network, so room for the full WL header above would
+ * be a waste.)
+ */
+#define BCMDONGLEHDRSZ 8
+
+
+
+#endif /* _bcmdefs_h_ */
diff --git a/package/broadcom-wl/src/wlc/include/bcmutils.h b/package/broadcom-wl/src/wlc/include/bcmutils.h
new file mode 100644
index 0000000000..b6e7b0542b
--- /dev/null
+++ b/package/broadcom-wl/src/wlc/include/bcmutils.h
@@ -0,0 +1,258 @@
+/*
+ * Misc useful os-independent macros and functions.
+ *
+ * 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.
+ * $Id: bcmutils.h,v 1.1.1.16 2006/04/08 06:13:39 honor Exp $
+ */
+
+#ifndef _bcmutils_h_
+#define _bcmutils_h_
+
+/* ** driver/apps-shared section ** */
+
+#define BCME_STRLEN 64 /* Max string length for BCM errors */
+#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST))
+
+
+/*
+ * error codes could be added but the defined ones shouldn't be changed/deleted
+ * these error codes are exposed to the user code
+ * when ever a new error code is added to this list
+ * please update errorstring table with the related error string and
+ * update osl files with os specific errorcode map
+*/
+
+#define BCME_OK 0 /* Success */
+#define BCME_ERROR -1 /* Error generic */
+#define BCME_BADARG -2 /* Bad Argument */
+#define BCME_BADOPTION -3 /* Bad option */
+#define BCME_NOTUP -4 /* Not up */
+#define BCME_NOTDOWN -5 /* Not down */
+#define BCME_NOTAP -6 /* Not AP */
+#define BCME_NOTSTA -7 /* Not STA */
+#define BCME_BADKEYIDX -8 /* BAD Key Index */
+#define BCME_RADIOOFF -9 /* Radio Off */
+#define BCME_NOTBANDLOCKED -10 /* Not band locked */
+#define BCME_NOCLK -11 /* No Clock */
+#define BCME_BADRATESET -12 /* BAD Rate valueset */
+#define BCME_BADBAND -13 /* BAD Band */
+#define BCME_BUFTOOSHORT -14 /* Buffer too short */
+#define BCME_BUFTOOLONG -15 /* Buffer too long */
+#define BCME_BUSY -16 /* Busy */
+#define BCME_NOTASSOCIATED -17 /* Not Associated */
+#define BCME_BADSSIDLEN -18 /* Bad SSID len */
+#define BCME_OUTOFRANGECHAN -19 /* Out of Range Channel */
+#define BCME_BADCHAN -20 /* Bad Channel */
+#define BCME_BADADDR -21 /* Bad Address */
+#define BCME_NORESOURCE -22 /* Not Enough Resources */
+#define BCME_UNSUPPORTED -23 /* Unsupported */
+#define BCME_BADLEN -24 /* Bad length */
+#define BCME_NOTREADY -25 /* Not Ready */
+#define BCME_EPERM -26 /* Not Permitted */
+#define BCME_NOMEM -27 /* No Memory */
+#define BCME_ASSOCIATED -28 /* Associated */
+#define BCME_RANGE -29 /* Not In Range */
+#define BCME_NOTFOUND -30 /* Not Found */
+#define BCME_WME_NOT_ENABLED -31 /* WME Not Enabled */
+#define BCME_TSPEC_NOTFOUND -32 /* TSPEC Not Found */
+#define BCME_ACM_NOTSUPPORTED -33 /* ACM Not Supported */
+#define BCME_NOT_WME_ASSOCIATION -34 /* Not WME Association */
+#define BCME_SDIO_ERROR -35 /* SDIO Bus Error */
+#define BCME_DONGLE_DOWN -36 /* Dongle Not Accessible */
+#define BCME_LAST BCME_DONGLE_DOWN
+
+/* These are collection of BCME Error strings */
+#define BCMERRSTRINGTABLE { \
+ "OK", \
+ "Undefined error", \
+ "Bad Argument", \
+ "Bad Option", \
+ "Not up", \
+ "Not down", \
+ "Not AP", \
+ "Not STA", \
+ "Bad Key Index", \
+ "Radio Off", \
+ "Not band locked", \
+ "No clock", \
+ "Bad Rate valueset", \
+ "Bad Band", \
+ "Buffer too short", \
+ "Buffer too long", \
+ "Busy", \
+ "Not Associated", \
+ "Bad SSID len", \
+ "Out of Range Channel", \
+ "Bad Channel", \
+ "Bad Address", \
+ "Not Enough Resources", \
+ "Unsupported", \
+ "Bad length", \
+ "Not Ready", \
+ "Not Permitted", \
+ "No Memory", \
+ "Associated", \
+ "Not In Range", \
+ "Not Found", \
+ "WME Not Enabled", \
+ "TSPEC Not Found", \
+ "ACM Not Supported", \
+ "Not WME Association", \
+ "SDIO Bus Error", \
+ "Dongle Not Accessible" \
+}
+
+#ifndef ABS
+#define ABS(a) (((a) < 0)?-(a):(a))
+#endif /* ABS */
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b))?(a):(b))
+#endif /* MIN */
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b))?(a):(b))
+#endif /* MAX */
+
+#define CEIL(x, y) (((x) + ((y)-1)) / (y))
+#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
+#define ISALIGNED(a, x) (((a) & ((x)-1)) == 0)
+#define ISPOWEROF2(x) ((((x)-1)&(x)) == 0)
+#define VALID_MASK(mask) !((mask) & ((mask) + 1))
+#define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member)
+#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
+
+/* bit map related macros */
+#ifndef setbit
+#ifndef NBBY /* the BSD family defines NBBY */
+#define NBBY 8 /* 8 bits per byte */
+#endif /* #ifndef NBBY */
+#define setbit(a, i) (((uint8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY))
+#define clrbit(a, i) (((uint8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
+#define isset(a, i) (((uint8 *)a)[(i)/NBBY] & (1<<((i)%NBBY)))
+#define isclr(a, i) ((((uint8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
+#endif /* setbit */
+
+#define NBITS(type) (sizeof(type) * 8)
+#define NBITVAL(nbits) (1 << (nbits))
+#define MAXBITVAL(nbits) ((1 << (nbits)) - 1)
+#define NBITMASK(nbits) MAXBITVAL(nbits)
+#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8)
+
+/* basic mux operation - can be optimized on several architectures */
+#define MUX(pred, true, false) ((pred) ? (true) : (false))
+
+/* modulo inc/dec - assumes x E [0, bound - 1] */
+#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1)
+#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1)
+
+/* modulo inc/dec, bound = 2^k */
+#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1))
+#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1))
+
+/* modulo add/sub - assumes x, y E [0, bound - 1] */
+#define MODADD(x, y, bound) \
+ MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y))
+#define MODSUB(x, y, bound) \
+ MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y))
+
+/* module add/sub, bound = 2^k */
+#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1))
+#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1))
+
+/* crc defines */
+#define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */
+#define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */
+#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */
+#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */
+#define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */
+#define CRC32_GOOD_VALUE 0xdebb20e3 /* Good final CRC32 checksum value */
+
+/* bcm_format_flags() bit description structure */
+typedef struct bcm_bit_desc {
+ uint32 bit;
+ char* name;
+} bcm_bit_desc_t;
+
+/* tag_ID/length/value_buffer tuple */
+typedef struct bcm_tlv {
+ uint8 id;
+ uint8 len;
+ uint8 data[1];
+} bcm_tlv_t;
+
+/* Check that bcm_tlv_t fits into the given buflen */
+#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (int)(buflen) >= (int)(2 + (elt)->len))
+
+/* buffer length for ethernet address from bcm_ether_ntoa() */
+#define ETHER_ADDR_STR_LEN 18 /* 18-bytes of Ethernet address buffer length */
+
+/* unaligned load and store macros */
+#ifdef IL_BIGENDIAN
+static INLINE uint32
+load32_ua(uint8 *a)
+{
+ return ((a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]);
+}
+
+static INLINE void
+store32_ua(uint8 *a, uint32 v)
+{
+ a[0] = (v >> 24) & 0xff;
+ a[1] = (v >> 16) & 0xff;
+ a[2] = (v >> 8) & 0xff;
+ a[3] = v & 0xff;
+}
+
+static INLINE uint16
+load16_ua(uint8 *a)
+{
+ return ((a[0] << 8) | a[1]);
+}
+
+static INLINE void
+store16_ua(uint8 *a, uint16 v)
+{
+ a[0] = (v >> 8) & 0xff;
+ a[1] = v & 0xff;
+}
+
+#else
+
+static INLINE uint32
+load32_ua(uint8 *a)
+{
+ return ((a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0]);
+}
+
+static INLINE void
+store32_ua(uint8 *a, uint32 v)
+{
+ a[3] = (v >> 24) & 0xff;
+ a[2] = (v >> 16) & 0xff;
+ a[1] = (v >> 8) & 0xff;
+ a[0] = v & 0xff;
+}
+
+static INLINE uint16
+load16_ua(uint8 *a)
+{
+ return ((a[1] << 8) | a[0]);
+}
+
+static INLINE void
+store16_ua(uint8 *a, uint16 v)
+{
+ a[1] = (v >> 8) & 0xff;
+ a[0] = v & 0xff;
+}
+
+#endif /* IL_BIGENDIAN */
+
+#endif /* _bcmutils_h_ */
diff --git a/package/broadcom-wl/src/wlc/include/proto/802.11.h b/package/broadcom-wl/src/wlc/include/proto/802.11.h
new file mode 100644
index 0000000000..2b1c4ee111
--- /dev/null
+++ b/package/broadcom-wl/src/wlc/include/proto/802.11.h
@@ -0,0 +1,1258 @@
+/*
+ * 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.
+ *
+ * Fundamental types and constants relating to 802.11
+ *
+ * $Id: 802.11.h,v 1.1.1.17 2006/04/15 01:29:08 michael Exp $
+ */
+
+#ifndef _802_11_H_
+#define _802_11_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+#ifndef _NET_ETHERNET_H_
+#include <proto/ethernet.h>
+#endif
+
+#include <proto/wpa.h>
+
+/* enable structure packing */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#pragma pack(1)
+#define PACKED
+#endif
+
+#define DOT11_TU_TO_US 1024 /* 802.11 Time Unit is 1024 microseconds */
+
+/* Generic 802.11 frame constants */
+#define DOT11_A3_HDR_LEN 24 /* d11 header length with A3 */
+#define DOT11_A4_HDR_LEN 30 /* d11 header length with A4 */
+#define DOT11_MAC_HDR_LEN DOT11_A3_HDR_LEN /* MAC header length */
+#define DOT11_FCS_LEN 4 /* d11 FCS length */
+#define DOT11_ICV_LEN 4 /* d11 ICV length */
+#define DOT11_ICV_AES_LEN 8 /* d11 ICV/AES length */
+#define DOT11_QOS_LEN 2 /* d11 QoS length */
+#define DOT11_HTC_LEN 4 /* d11 HT Control field length */
+
+#define DOT11_KEY_INDEX_SHIFT 6 /* d11 key index shift */
+#define DOT11_IV_LEN 4 /* d11 IV length */
+#define DOT11_IV_TKIP_LEN 8 /* d11 IV TKIP length */
+#define DOT11_IV_AES_OCB_LEN 4 /* d11 IV/AES/OCB length */
+#define DOT11_IV_AES_CCM_LEN 8 /* d11 IV/AES/CCM length */
+#define DOT11_IV_MAX_LEN 8 /* maximum iv len for any encryption */
+
+/* Includes MIC */
+#define DOT11_MAX_MPDU_BODY_LEN 2304 /* max MPDU body length */
+/* A4 header + QoS + CCMP + PDU + ICV + FCS = 2352 */
+#define DOT11_MAX_MPDU_LEN (DOT11_A4_HDR_LEN + \
+ DOT11_QOS_LEN + \
+ DOT11_IV_AES_CCM_LEN + \
+ DOT11_MAX_MPDU_BODY_LEN + \
+ DOT11_ICV_LEN + \
+ DOT11_FCS_LEN) /* d11 max MPDU length */
+
+#define DOT11_MAX_SSID_LEN 32 /* d11 max ssid length */
+
+/* dot11RTSThreshold */
+#define DOT11_DEFAULT_RTS_LEN 2347 /* d11 default RTS length */
+#define DOT11_MAX_RTS_LEN 2347 /* d11 max RTS length */
+
+/* dot11FragmentationThreshold */
+#define DOT11_MIN_FRAG_LEN 256 /* d11 min fragmentation length */
+#define DOT11_MAX_FRAG_LEN 2346 /* Max frag is also limited by aMPDUMaxLength
+ * of the attached PHY
+ */
+#define DOT11_DEFAULT_FRAG_LEN 2346 /* d11 default fragmentation length */
+
+/* dot11BeaconPeriod */
+#define DOT11_MIN_BEACON_PERIOD 1 /* d11 min beacon period */
+#define DOT11_MAX_BEACON_PERIOD 0xFFFF /* d11 max beacon period */
+
+/* dot11DTIMPeriod */
+#define DOT11_MIN_DTIM_PERIOD 1 /* d11 min DTIM period */
+#define DOT11_MAX_DTIM_PERIOD 0xFF /* d11 max DTIM period */
+
+/* 802.2 LLC/SNAP header used by 802.11 per 802.1H */
+#define DOT11_LLC_SNAP_HDR_LEN 8 /* d11 LLC/SNAP header length */
+#define DOT11_OUI_LEN 3 /* d11 OUI length */
+struct dot11_llc_snap_header {
+ uint8 dsap; /* always 0xAA */
+ uint8 ssap; /* always 0xAA */
+ uint8 ctl; /* always 0x03 */
+ uint8 oui[DOT11_OUI_LEN]; /* RFC1042: 0x00 0x00 0x00
+ * Bridge-Tunnel: 0x00 0x00 0xF8
+ */
+ uint16 type; /* ethertype */
+} PACKED;
+
+/* RFC1042 header used by 802.11 per 802.1H */
+#define RFC1042_HDR_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN) /* RCF1042 header length */
+
+/* Generic 802.11 MAC header */
+/*
+ * N.B.: This struct reflects the full 4 address 802.11 MAC header.
+ * The fields are defined such that the shorter 1, 2, and 3
+ * address headers just use the first k fields.
+ */
+struct dot11_header {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr a1; /* address 1 */
+ struct ether_addr a2; /* address 2 */
+ struct ether_addr a3; /* address 3 */
+ uint16 seq; /* sequence control */
+ struct ether_addr a4; /* address 4 */
+} PACKED;
+
+/* Control frames */
+
+struct dot11_rts_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+ struct ether_addr ta; /* transmitter address */
+} PACKED;
+#define DOT11_RTS_LEN 16 /* d11 RTS frame length */
+
+struct dot11_cts_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+} PACKED;
+#define DOT11_CTS_LEN 10 /* d11 CTS frame length */
+
+struct dot11_ack_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+} PACKED;
+#define DOT11_ACK_LEN 10 /* d11 ACK frame length */
+
+struct dot11_ps_poll_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* AID */
+ struct ether_addr bssid; /* receiver address, STA in AP */
+ struct ether_addr ta; /* transmitter address */
+} PACKED;
+#define DOT11_PS_POLL_LEN 16 /* d11 PS poll frame length */
+
+struct dot11_cf_end_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+ struct ether_addr bssid; /* transmitter address, STA in AP */
+} PACKED;
+#define DOT11_CS_END_LEN 16 /* d11 CF-END frame length */
+
+/* BA/BAR Control parameters */
+#define DOT11_BA_CTL_POLICY_NORMAL 0x0000 /* normal ack */
+#define DOT11_BA_CTL_POLICY_NOACK 0x0001 /* no ack */
+#define DOT11_BA_CTL_POLICY_MASK 0x0001 /* ack policy mask */
+
+#define DOT11_BA_CTL_MTID 0x0002 /* multi tid BA */
+#define DOT11_BA_CTL_COMPRESSED 0x0004 /* compressed bitmap */
+
+#define DOT11_BA_CTL_NUMMSDU_MASK 0x0FC0 /* num msdu in bitmap mask */
+#define DOT11_BA_CTL_NUMMSDU_SHIFT 6 /* num msdu in bitmap shift */
+
+#define DOT11_BA_CTL_TID_MASK 0xF000 /* tid mask */
+#define DOT11_BA_CTL_TID_SHIFT 12 /* tid shift */
+
+struct dot11_ba_req_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+ struct ether_addr ta; /* transmitter address */
+ uint16 bar_control; /* BAR Control */
+ uint16 seqnum; /* Starting Sequence control */
+} PACKED;
+#define DOT11_BA_REQ_LEN 20 /* BAR frame length */
+
+#define DOT11_BA_BITMAP_LEN 128 /* bitmap length */
+#define DOT11_BA_CMP_BITMAP_LEN 8 /* compressed bitmap length */
+struct dot11_ba_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+ struct ether_addr ta; /* transmitter address */
+ uint16 ba_control; /* BA Control */
+ uint16 seqnum; /* Starting Sequence control */
+ uint8 bitmap[DOT11_BA_BITMAP_LEN]; /* Block Ack Bitmap */
+} PACKED;
+#define DOT11_BA_LEN 20 /* BA frame length (without bitmap) */
+
+/* Management frame header */
+struct dot11_management_header {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr da; /* receiver address */
+ struct ether_addr sa; /* transmitter address */
+ struct ether_addr bssid; /* BSS ID */
+ uint16 seq; /* sequence control */
+} PACKED;
+#define DOT11_MGMT_HDR_LEN 24 /* d11 management header length */
+
+/* Management frame payloads */
+
+struct dot11_bcn_prb {
+ uint32 timestamp[2];
+ uint16 beacon_interval;
+ uint16 capability;
+} PACKED;
+#define DOT11_BCN_PRB_LEN 12 /* d11 beacon probe frame length */
+
+struct dot11_auth {
+ uint16 alg; /* algorithm */
+ uint16 seq; /* sequence control */
+ uint16 status; /* status code */
+} PACKED;
+#define DOT11_AUTH_FIXED_LEN 6 /* length of auth frame without challenge info
+ * elt
+ */
+
+struct dot11_assoc_req {
+ uint16 capability; /* capability information */
+ uint16 listen; /* listen interval */
+} PACKED;
+#define DOT11_ASSOC_REQ_FIXED_LEN 4 /* length of assoc frame without info elts */
+
+struct dot11_reassoc_req {
+ uint16 capability; /* capability information */
+ uint16 listen; /* listen interval */
+ struct ether_addr ap; /* Current AP address */
+} PACKED;
+#define DOT11_REASSOC_REQ_FIXED_LEN 10 /* length of assoc frame without info elts */
+
+struct dot11_assoc_resp {
+ uint16 capability; /* capability information */
+ uint16 status; /* status code */
+ uint16 aid; /* association ID */
+} PACKED;
+
+struct dot11_action_measure {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} PACKED;
+#define DOT11_ACTION_MEASURE_LEN 3 /* d11 action measurement header length */
+
+struct dot11_action_switch_channel {
+ uint8 category;
+ uint8 action;
+ uint8 data[5]; /* for switch IE */
+} PACKED;
+
+struct dot11_action_ht_ch_width {
+ uint8 category;
+ uint8 action;
+ uint8 ch_width;
+} PACKED;
+
+struct dot11_action_ht_mimops {
+ uint8 category;
+ uint8 action;
+ uint8 enable;
+ uint8 psmode;
+} PACKED;
+
+/* ************* 802.11h related definitions. ************* */
+typedef struct {
+ uint8 id;
+ uint8 len;
+ uint8 power;
+} dot11_power_cnst_t;
+
+typedef struct {
+ uint8 min;
+ uint8 max;
+} dot11_power_cap_t;
+
+typedef struct {
+ uint8 id;
+ uint8 len;
+ uint8 tx_pwr;
+ uint8 margin;
+} dot11_tpc_rep_t;
+#define DOT11_MNG_IE_TPC_REPORT_LEN 2 /* length of IE data, not including 2 byte header */
+
+typedef struct {
+ uint8 id;
+ uint8 len;
+ uint8 first_channel;
+ uint8 num_channels;
+} dot11_supp_channels_t;
+
+/* channel switch announcement (CSA) mode type - 802.11h-2003 $7.3.2.20 */
+#define DOT11_CSA_MODE_ADVISORY 0 /* no DOT11_CSA_MODE_NO_TX restriction imposed */
+#define DOT11_CSA_MODE_NO_TX 1 /* no transmission upon receiving CSA frame. */
+
+/* CSA IE data structure */
+struct dot11_channel_switch {
+ uint8 id;
+ uint8 len;
+ uint8 mode;
+ uint8 channel;
+ uint8 count;
+} PACKED;
+typedef struct dot11_channel_switch dot11_channel_switch_t;
+
+#define DOT11_SWITCH_IE_LEN 3 /* length of IE data, not including 2 byte header */
+
+/* 802.11h Measurement Request/Report IEs */
+/* Measurement Type field */
+#define DOT11_MEASURE_TYPE_BASIC 0 /* d11 measurement basic type */
+#define DOT11_MEASURE_TYPE_CCA 1 /* d11 measurement CCA type */
+#define DOT11_MEASURE_TYPE_RPI 2 /* d11 measurement PRI type */
+
+/* Measurement Mode field */
+
+/* Measurement Request Modes */
+#define DOT11_MEASURE_MODE_ENABLE (1<<1) /* d11 measurement enable */
+#define DOT11_MEASURE_MODE_REQUEST (1<<2) /* d11 measurement request */
+#define DOT11_MEASURE_MODE_REPORT (1<<3) /* d11 measurement report */
+/* Measurement Report Modes */
+#define DOT11_MEASURE_MODE_LATE (1<<0) /* d11 measurement late */
+#define DOT11_MEASURE_MODE_INCAPABLE (1<<1) /* d11 measurement incapable */
+#define DOT11_MEASURE_MODE_REFUSED (1<<2) /* d11 measurement refuse */
+/* Basic Measurement Map bits */
+#define DOT11_MEASURE_BASIC_MAP_BSS ((uint8)(1<<0)) /* d11 measurement basic map BSS */
+#define DOT11_MEASURE_BASIC_MAP_OFDM ((uint8)(1<<1)) /* d11 measurement map OFDM */
+#define DOT11_MEASURE_BASIC_MAP_UKNOWN ((uint8)(1<<2)) /* d11 measurement map unknown */
+#define DOT11_MEASURE_BASIC_MAP_RADAR ((uint8)(1<<3)) /* d11 measurement map radar */
+#define DOT11_MEASURE_BASIC_MAP_UNMEAS ((uint8)(1<<4)) /* d11 measurement map unmeasuremnt */
+
+typedef struct {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+} dot11_meas_req_t;
+#define DOT11_MNG_IE_MREQ_LEN 14 /* d11 measurement request IE length */
+/* length of Measure Request IE data not including variable len */
+#define DOT11_MNG_IE_MREQ_FIXED_LEN 3 /* d11 measurement request IE fixed length */
+
+struct dot11_meas_rep {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ union
+ {
+ struct {
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+ uint8 map;
+ } PACKED basic;
+ uint8 data[1];
+ } PACKED rep;
+} PACKED;
+typedef struct dot11_meas_rep dot11_meas_rep_t;
+
+/* length of Measure Report IE data not including variable len */
+#define DOT11_MNG_IE_MREP_FIXED_LEN 3 /* d11 measurement response IE fixed length */
+
+struct dot11_meas_rep_basic {
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+ uint8 map;
+} PACKED;
+typedef struct dot11_meas_rep_basic dot11_meas_rep_basic_t;
+#define DOT11_MEASURE_BASIC_REP_LEN 12 /* d11 measurement basic report length */
+
+struct dot11_quiet {
+ uint8 id;
+ uint8 len;
+ uint8 count; /* TBTTs until beacon interval in quiet starts */
+ uint8 period; /* Beacon intervals between periodic quiet periods ? */
+ uint16 duration; /* Length of quiet period, in TU's */
+ uint16 offset; /* TU's offset from TBTT in Count field */
+} PACKED;
+typedef struct dot11_quiet dot11_quiet_t;
+
+typedef struct {
+ uint8 channel;
+ uint8 map;
+} chan_map_tuple_t;
+
+typedef struct {
+ uint8 id;
+ uint8 len;
+ uint8 eaddr[ETHER_ADDR_LEN];
+ uint8 interval;
+ chan_map_tuple_t map[1];
+} dot11_ibss_dfs_t;
+
+/* WME Elements */
+#define WME_OUI "\x00\x50\xf2" /* WME OUI */
+#define WME_VER 1 /* WME version */
+#define WME_TYPE 2 /* WME type */
+#define WME_SUBTYPE_IE 0 /* Information Element */
+#define WME_SUBTYPE_PARAM_IE 1 /* Parameter Element */
+#define WME_SUBTYPE_TSPEC 2 /* Traffic Specification */
+
+/* WME Access Category Indices (ACIs) */
+#define AC_BE 0 /* Best Effort */
+#define AC_BK 1 /* Background */
+#define AC_VI 2 /* Video */
+#define AC_VO 3 /* Voice */
+#define AC_COUNT 4 /* number of ACs */
+
+typedef uint8 ac_bitmap_t; /* AC bitmap of (1 << AC_xx) */
+
+#define AC_BITMAP_NONE 0x0 /* No ACs */
+#define AC_BITMAP_ALL 0xf /* All ACs */
+#define AC_BITMAP_TST(ab, ac) (((ab) & (1 << (ac))) != 0)
+
+/* WME Information Element (IE) */
+struct wme_ie {
+ uint8 oui[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 version;
+ uint8 qosinfo;
+} PACKED;
+typedef struct wme_ie wme_ie_t;
+#define WME_IE_LEN 7 /* WME IE length */
+
+struct edcf_acparam {
+ uint8 ACI;
+ uint8 ECW;
+ uint16 TXOP; /* stored in network order (ls octet first) */
+} PACKED;
+typedef struct edcf_acparam edcf_acparam_t;
+
+/* WME Parameter Element (PE) */
+struct wme_param_ie {
+ uint8 oui[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 version;
+ uint8 qosinfo;
+ uint8 rsvd;
+ edcf_acparam_t acparam[AC_COUNT];
+} PACKED;
+typedef struct wme_param_ie wme_param_ie_t;
+#define WME_PARAM_IE_LEN 24 /* WME Parameter IE length */
+
+/* QoS Info field for IE as sent from AP */
+#define WME_QI_AP_APSD_MASK 0x80 /* U-APSD Supported mask */
+#define WME_QI_AP_APSD_SHIFT 7 /* U-APSD Supported shift */
+#define WME_QI_AP_COUNT_MASK 0x0f /* Parameter set count mask */
+#define WME_QI_AP_COUNT_SHIFT 0 /* Parameter set count shift */
+
+/* QoS Info field for IE as sent from STA */
+#define WME_QI_STA_MAXSPLEN_MASK 0x60 /* Max Service Period Length mask */
+#define WME_QI_STA_MAXSPLEN_SHIFT 5 /* Max Service Period Length shift */
+#define WME_QI_STA_APSD_ALL_MASK 0xf /* APSD all AC bits mask */
+#define WME_QI_STA_APSD_ALL_SHIFT 0 /* APSD all AC bits shift */
+#define WME_QI_STA_APSD_BE_MASK 0x8 /* APSD AC_BE mask */
+#define WME_QI_STA_APSD_BE_SHIFT 3 /* APSD AC_BE shift */
+#define WME_QI_STA_APSD_BK_MASK 0x4 /* APSD AC_BK mask */
+#define WME_QI_STA_APSD_BK_SHIFT 2 /* APSD AC_BK shift */
+#define WME_QI_STA_APSD_VI_MASK 0x2 /* APSD AC_VI mask */
+#define WME_QI_STA_APSD_VI_SHIFT 1 /* APSD AC_VI shift */
+#define WME_QI_STA_APSD_VO_MASK 0x1 /* APSD AC_VO mask */
+#define WME_QI_STA_APSD_VO_SHIFT 0 /* APSD AC_VO shift */
+
+/* ACI */
+#define EDCF_AIFSN_MIN 1 /* AIFSN minimum value */
+#define EDCF_AIFSN_MAX 15 /* AIFSN maximum value */
+#define EDCF_AIFSN_MASK 0x0f /* AIFSN mask */
+#define EDCF_ACM_MASK 0x10 /* ACM mask */
+#define EDCF_ACI_MASK 0x60 /* ACI mask */
+#define EDCF_ACI_SHIFT 5 /* ACI shift */
+
+/* ECW */
+#define EDCF_ECW_MIN 0 /* cwmin/cwmax exponent minimum value */
+#define EDCF_ECW_MAX 15 /* cwmin/cwmax exponent maximum value */
+#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1)
+#define EDCF_ECWMIN_MASK 0x0f /* cwmin exponent form mask */
+#define EDCF_ECWMAX_MASK 0xf0 /* cwmax exponent form mask */
+#define EDCF_ECWMAX_SHIFT 4 /* cwmax exponent form shift */
+
+/* TXOP */
+#define EDCF_TXOP_MIN 0 /* TXOP minimum value */
+#define EDCF_TXOP_MAX 65535 /* TXOP maximum value */
+#define EDCF_TXOP2USEC(txop) ((txop) << 5)
+
+/* Default EDCF parameters that AP advertises for STA to use; WMM draft Table 12 */
+#define EDCF_AC_BE_ACI_STA 0x03 /* STA ACI value for best effort AC */
+#define EDCF_AC_BE_ECW_STA 0xA4 /* STA ECW value for best effort AC */
+#define EDCF_AC_BE_TXOP_STA 0x0000 /* STA TXOP value for best effort AC */
+#define EDCF_AC_BK_ACI_STA 0x27 /* STA ACI value for background AC */
+#define EDCF_AC_BK_ECW_STA 0xA4 /* STA ECW value for background AC */
+#define EDCF_AC_BK_TXOP_STA 0x0000 /* STA TXOP value for background AC */
+#define EDCF_AC_VI_ACI_STA 0x42 /* STA ACI value for video AC */
+#define EDCF_AC_VI_ECW_STA 0x43 /* STA ECW value for video AC */
+#define EDCF_AC_VI_TXOP_STA 0x005e /* STA TXOP value for video AC */
+#define EDCF_AC_VO_ACI_STA 0x62 /* STA ACI value for audio AC */
+#define EDCF_AC_VO_ECW_STA 0x32 /* STA ECW value for audio AC */
+#define EDCF_AC_VO_TXOP_STA 0x002f /* STA TXOP value for audio AC */
+
+/* Default EDCF parameters that AP uses; WMM draft Table 14 */
+#define EDCF_AC_BE_ACI_AP 0x03 /* AP ACI value for best effort AC */
+#define EDCF_AC_BE_ECW_AP 0x64 /* AP ECW value for best effort AC */
+#define EDCF_AC_BE_TXOP_AP 0x0000 /* AP TXOP value for best effort AC */
+#define EDCF_AC_BK_ACI_AP 0x27 /* AP ACI value for background AC */
+#define EDCF_AC_BK_ECW_AP 0xA4 /* AP ECW value for background AC */
+#define EDCF_AC_BK_TXOP_AP 0x0000 /* AP TXOP value for background AC */
+#define EDCF_AC_VI_ACI_AP 0x41 /* AP ACI value for video AC */
+#define EDCF_AC_VI_ECW_AP 0x43 /* AP ECW value for video AC */
+#define EDCF_AC_VI_TXOP_AP 0x005e /* AP TXOP value for video AC */
+#define EDCF_AC_VO_ACI_AP 0x61 /* AP ACI value for audio AC */
+#define EDCF_AC_VO_ECW_AP 0x32 /* AP ECW value for audio AC */
+#define EDCF_AC_VO_TXOP_AP 0x002f /* AP TXOP value for audio AC */
+
+struct dot11_qbss_load_ie {
+ uint8 id; /* 11, DOT11_MNG_QBSS_LOAD_ID */
+ uint8 length;
+ uint16 station_count; /* total number of STAs associated */
+ uint8 channel_utilization; /* % of time, normalized to 255, QAP sensed medium busy */
+ uint16 aac; /* available admission capacity */
+} PACKED;
+typedef struct dot11_qbss_load_ie dot11_qbss_load_ie_t;
+
+/* nom_msdu_size */
+#define FIXED_MSDU_SIZE 0x8000 /* MSDU size is fixed */
+#define MSDU_SIZE_MASK 0x7fff /* (Nominal or fixed) MSDU size */
+
+/* surplus_bandwidth */
+/* Represented as 3 bits of integer, binary point, 13 bits fraction */
+#define INTEGER_SHIFT 13 /* integer shift */
+#define FRACTION_MASK 0x1FFF /* fraction mask */
+
+/* Management Notification Frame */
+struct dot11_management_notification {
+ uint8 category; /* DOT11_ACTION_NOTIFICATION */
+ uint8 action;
+ uint8 token;
+ uint8 status;
+ uint8 data[1]; /* Elements */
+} PACKED;
+#define DOT11_MGMT_NOTIFICATION_LEN 4 /* Fixed length */
+
+/* WME Action Codes */
+#define WME_ADDTS_REQUEST 0 /* WME ADDTS request */
+#define WME_ADDTS_RESPONSE 1 /* WME ADDTS response */
+#define WME_DELTS_REQUEST 2 /* WME DELTS request */
+
+/* WME Setup Response Status Codes */
+#define WME_ADMISSION_ACCEPTED 0 /* WME admission accepted */
+#define WME_INVALID_PARAMETERS 1 /* WME invalide parameters */
+#define WME_ADMISSION_REFUSED 3 /* WME admission refused */
+
+/* Macro to take a pointer to a beacon or probe response
+ * header and return the char* pointer to the SSID info element
+ */
+#define BCN_PRB_SSID(hdr) ((char*)(hdr) + DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_LEN)
+
+/* Authentication frame payload constants */
+#define DOT11_OPEN_SYSTEM 0 /* d11 open authentication */
+#define DOT11_SHARED_KEY 1 /* d11 shared authentication */
+#define DOT11_CHALLENGE_LEN 128 /* d11 chanllenge text length */
+
+/* Frame control macros */
+#define FC_PVER_MASK 0x3 /* PVER mask */
+#define FC_PVER_SHIFT 0 /* PVER shift */
+#define FC_TYPE_MASK 0xC /* type mask */
+#define FC_TYPE_SHIFT 2 /* type shift */
+#define FC_SUBTYPE_MASK 0xF0 /* subtype mask */
+#define FC_SUBTYPE_SHIFT 4 /* subtype shift */
+#define FC_TODS 0x100 /* to DS */
+#define FC_TODS_SHIFT 8 /* to DS shift */
+#define FC_FROMDS 0x200 /* from DS */
+#define FC_FROMDS_SHIFT 9 /* from DS shift */
+#define FC_MOREFRAG 0x400 /* more frag. */
+#define FC_MOREFRAG_SHIFT 10 /* more frag. shift */
+#define FC_RETRY 0x800 /* retry */
+#define FC_RETRY_SHIFT 11 /* retry shift */
+#define FC_PM 0x1000 /* PM */
+#define FC_PM_SHIFT 12 /* PM shift */
+#define FC_MOREDATA 0x2000 /* more data */
+#define FC_MOREDATA_SHIFT 13 /* more data shift */
+#define FC_WEP 0x4000 /* WEP */
+#define FC_WEP_SHIFT 14 /* WEP shift */
+#define FC_ORDER 0x8000 /* order */
+#define FC_ORDER_SHIFT 15 /* order shift */
+
+/* sequence control macros */
+#define SEQNUM_SHIFT 4 /* seq. number shift */
+#define SEQNUM_MAX 0x1000 /* max seqnum + 1 */
+#define FRAGNUM_MASK 0xF /* frag. number mask */
+
+/* Frame Control type/subtype defs */
+
+/* FC Types */
+#define FC_TYPE_MNG 0 /* management type */
+#define FC_TYPE_CTL 1 /* control type */
+#define FC_TYPE_DATA 2 /* data type */
+
+/* Management Subtypes */
+#define FC_SUBTYPE_ASSOC_REQ 0 /* assoc. request */
+#define FC_SUBTYPE_ASSOC_RESP 1 /* assoc. response */
+#define FC_SUBTYPE_REASSOC_REQ 2 /* reassoc. request */
+#define FC_SUBTYPE_REASSOC_RESP 3 /* reassoc. response */
+#define FC_SUBTYPE_PROBE_REQ 4 /* probe request */
+#define FC_SUBTYPE_PROBE_RESP 5 /* probe response */
+#define FC_SUBTYPE_BEACON 8 /* beacon */
+#define FC_SUBTYPE_ATIM 9 /* ATIM */
+#define FC_SUBTYPE_DISASSOC 10 /* disassoc. */
+#define FC_SUBTYPE_AUTH 11 /* authentication */
+#define FC_SUBTYPE_DEAUTH 12 /* de-authentication */
+#define FC_SUBTYPE_ACTION 13 /* action */
+
+/* Control Subtypes */
+#define FC_SUBTYPE_BLOCKACK_REQ 8 /* Block Ack Req */
+#define FC_SUBTYPE_BLOCKACK 9 /* Block Ack */
+#define FC_SUBTYPE_PS_POLL 10 /* PS poll */
+#define FC_SUBTYPE_RTS 11 /* RTS */
+#define FC_SUBTYPE_CTS 12 /* CTS */
+#define FC_SUBTYPE_ACK 13 /* ACK */
+#define FC_SUBTYPE_CF_END 14 /* CF-END */
+#define FC_SUBTYPE_CF_END_ACK 15 /* CF-END ACK */
+
+/* Data Subtypes */
+#define FC_SUBTYPE_DATA 0 /* Data */
+#define FC_SUBTYPE_DATA_CF_ACK 1 /* Data + CF-ACK */
+#define FC_SUBTYPE_DATA_CF_POLL 2 /* Data + CF-Poll */
+#define FC_SUBTYPE_DATA_CF_ACK_POLL 3 /* Data + CF-Ack + CF-Poll */
+#define FC_SUBTYPE_NULL 4 /* Null */
+#define FC_SUBTYPE_CF_ACK 5 /* CF-Ack */
+#define FC_SUBTYPE_CF_POLL 6 /* CF-Poll */
+#define FC_SUBTYPE_CF_ACK_POLL 7 /* CF-Ack + CF-Poll */
+#define FC_SUBTYPE_QOS_DATA 8 /* QoS Data */
+#define FC_SUBTYPE_QOS_DATA_CF_ACK 9 /* QoS Data + CF-Ack */
+#define FC_SUBTYPE_QOS_DATA_CF_POLL 10 /* QoS Data + CF-Poll */
+#define FC_SUBTYPE_QOS_DATA_CF_ACK_POLL 11 /* QoS Data + CF-Ack + CF-Poll */
+#define FC_SUBTYPE_QOS_NULL 12 /* QoS Null */
+#define FC_SUBTYPE_QOS_CF_POLL 14 /* QoS CF-Poll */
+#define FC_SUBTYPE_QOS_CF_ACK_POLL 15 /* QoS CF-Ack + CF-Poll */
+
+/* Data Subtype Groups */
+#define FC_SUBTYPE_ANY_QOS(s) (((s) & 8) != 0)
+#define FC_SUBTYPE_ANY_NULL(s) (((s) & 4) != 0)
+#define FC_SUBTYPE_ANY_CF_POLL(s) (((s) & 2) != 0)
+#define FC_SUBTYPE_ANY_CF_ACK(s) (((s) & 1) != 0)
+
+/* Type/Subtype Combos */
+#define FC_KIND_MASK (FC_TYPE_MASK | FC_SUBTYPE_MASK) /* FC kind mask */
+
+#define FC_KIND(t, s) (((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT)) /* FC kind */
+
+#define FC_SUBTYPE(fc) (((fc) & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT) /* Subtype from FC */
+#define FC_TYPE(fc) (((fc) & FC_TYPE_MASK) >> FC_TYPE_SHIFT) /* Type from FC */
+
+#define FC_ASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_REQ) /* assoc. request */
+#define FC_ASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP) /* assoc. response */
+#define FC_REASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ) /* reassoc. request */
+#define FC_REASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP) /* reassoc. response */
+#define FC_PROBE_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ) /* probe request */
+#define FC_PROBE_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP) /* probe response */
+#define FC_BEACON FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON) /* beacon */
+#define FC_DISASSOC FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC) /* disassoc */
+#define FC_AUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH) /* authentication */
+#define FC_DEAUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH) /* deauthentication */
+#define FC_ACTION FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION) /* action */
+
+#define FC_BLOCKACK_REQ FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK_REQ) /* Block Ack Req */
+#define FC_BLOCKACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK) /* Block Ack */
+#define FC_PS_POLL FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL) /* PS poll */
+#define FC_RTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS) /* RTS */
+#define FC_CTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS) /* CTS */
+#define FC_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_ACK) /* ACK */
+#define FC_CF_END FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END) /* CF-END */
+#define FC_CF_END_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END_ACK) /* CF-END ACK */
+
+#define FC_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA) /* data */
+#define FC_NULL_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_NULL) /* null data */
+#define FC_DATA_CF_ACK FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA_CF_ACK) /* data CF ACK */
+#define FC_QOS_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_DATA) /* QoS data */
+#define FC_QOS_NULL FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_NULL) /* QoS null */
+
+/* QoS Control Field */
+
+/* 802.1D Priority */
+#define QOS_PRIO_SHIFT 0 /* QoS priority shift */
+#define QOS_PRIO_MASK 0x0007 /* QoS priority mask */
+#define QOS_PRIO(qos) (((qos) & QOS_PRIO_MASK) >> QOS_PRIO_SHIFT) /* QoS priority */
+
+/* Traffic Identifier */
+#define QOS_TID_SHIFT 0 /* QoS TID shift */
+#define QOS_TID_MASK 0x000f /* QoS TID mask */
+#define QOS_TID(qos) (((qos) & QOS_TID_MASK) >> QOS_TID_SHIFT) /* QoS TID */
+
+/* End of Service Period (U-APSD) */
+#define QOS_EOSP_SHIFT 4 /* QoS End of Service Period shift */
+#define QOS_EOSP_MASK 0x0010 /* QoS End of Service Period mask */
+#define QOS_EOSP(qos) (((qos) & QOS_EOSP_MASK) >> QOS_EOSP_SHIFT) /* Qos EOSP */
+
+/* Ack Policy */
+#define QOS_ACK_NORMAL_ACK 0 /* Normal Ack */
+#define QOS_ACK_NO_ACK 1 /* No Ack (eg mcast) */
+#define QOS_ACK_NO_EXP_ACK 2 /* No Explicit Ack */
+#define QOS_ACK_BLOCK_ACK 3 /* Block Ack */
+#define QOS_ACK_SHIFT 5 /* QoS ACK shift */
+#define QOS_ACK_MASK 0x0060 /* QoS ACK mask */
+#define QOS_ACK(qos) (((qos) & QOS_ACK_MASK) >> QOS_ACK_SHIFT) /* QoS ACK */
+
+/* A-MSDU flag */
+#define QOS_AMSDU_SHIFT 7 /* AMSDU shift */
+#define QOS_AMSDU_MASK 0x0080 /* AMSDU mask */
+
+/* Management Frames */
+
+/* Management Frame Constants */
+
+/* Fixed fields */
+#define DOT11_MNG_AUTH_ALGO_LEN 2 /* d11 management auth. algo. length */
+#define DOT11_MNG_AUTH_SEQ_LEN 2 /* d11 management auth. seq. length */
+#define DOT11_MNG_BEACON_INT_LEN 2 /* d11 management beacon interval length */
+#define DOT11_MNG_CAP_LEN 2 /* d11 management cap. length */
+#define DOT11_MNG_AP_ADDR_LEN 6 /* d11 management AP address length */
+#define DOT11_MNG_LISTEN_INT_LEN 2 /* d11 management listen interval length */
+#define DOT11_MNG_REASON_LEN 2 /* d11 management reason length */
+#define DOT11_MNG_AID_LEN 2 /* d11 management AID length */
+#define DOT11_MNG_STATUS_LEN 2 /* d11 management status length */
+#define DOT11_MNG_TIMESTAMP_LEN 8 /* d11 management timestamp length */
+
+/* DUR/ID field in assoc resp is 0xc000 | AID */
+#define DOT11_AID_MASK 0x3fff /* d11 AID mask */
+
+/* Reason Codes */
+#define DOT11_RC_RESERVED 0 /* d11 RC reserved */
+#define DOT11_RC_UNSPECIFIED 1 /* Unspecified reason */
+#define DOT11_RC_AUTH_INVAL 2 /* Previous authentication no longer
+ * valid
+ */
+#define DOT11_RC_DEAUTH_LEAVING 3 /* Deauthenticated because sending station
+ * is leaving (or has left) IBSS or ESS
+ */
+#define DOT11_RC_INACTIVITY 4 /* Disassociated due to inactivity */
+#define DOT11_RC_BUSY 5 /* Disassociated because AP is unable
+ * to handle all currently associated
+ * stations
+ */
+#define DOT11_RC_INVAL_CLASS_2 6 /* Class 2 frame received from
+ * nonauthenticated station
+ */
+#define DOT11_RC_INVAL_CLASS_3 7 /* Class 3 frame received from
+ * nonassociated station
+ */
+#define DOT11_RC_DISASSOC_LEAVING 8 /* Disassociated because sending station is
+ * leaving (or has left) BSS
+ */
+#define DOT11_RC_NOT_AUTH 9 /* Station requesting (re)association is
+ * not authenticated with responding
+ * station
+ */
+#define DOT11_RC_MAX 23 /* Reason codes > 23 are reserved */
+
+/* Status Codes */
+#define DOT11_STATUS_SUCCESS 0 /* Successful */
+#define DOT11_STATUS_FAILURE 1 /* Unspecified failure */
+#define DOT11_STATUS_CAP_MISMATCH 10 /* Cannot support all requested
+ * capabilities in the Capability
+ * Information field
+ */
+#define DOT11_STATUS_REASSOC_FAIL 11 /* Reassociation denied due to inability
+ * to confirm that association exists
+ */
+#define DOT11_STATUS_ASSOC_FAIL 12 /* Association denied due to reason
+ * outside the scope of this standard
+ */
+#define DOT11_STATUS_AUTH_MISMATCH 13 /* Responding station does not support
+ * the specified authentication
+ * algorithm
+ */
+#define DOT11_STATUS_AUTH_SEQ 14 /* Received an Authentication frame
+ * with authentication transaction
+ * sequence number out of expected
+ * sequence
+ */
+#define DOT11_STATUS_AUTH_CHALLENGE_FAIL 15 /* Authentication rejected because of
+ * challenge failure
+ */
+#define DOT11_STATUS_AUTH_TIMEOUT 16 /* Authentication rejected due to timeout
+ * waiting for next frame in sequence
+ */
+#define DOT11_STATUS_ASSOC_BUSY_FAIL 17 /* Association denied because AP is
+ * unable to handle additional
+ * associated stations
+ */
+#define DOT11_STATUS_ASSOC_RATE_MISMATCH 18 /* Association denied due to requesting
+ * station not supporting all of the
+ * data rates in the BSSBasicRateSet
+ * parameter
+ */
+#define DOT11_STATUS_ASSOC_SHORT_REQUIRED 19 /* Association denied due to requesting
+ * station not supporting the Short
+ * Preamble option
+ */
+#define DOT11_STATUS_ASSOC_PBCC_REQUIRED 20 /* Association denied due to requesting
+ * station not supporting the PBCC
+ * Modulation option
+ */
+#define DOT11_STATUS_ASSOC_AGILITY_REQUIRED 21 /* Association denied due to requesting
+ * station not supporting the Channel
+ * Agility option
+ */
+#define DOT11_STATUS_ASSOC_SPECTRUM_REQUIRED 22 /* Association denied because Spectrum
+ * Management capability is required.
+ */
+#define DOT11_STATUS_ASSOC_BAD_POWER_CAP 23 /* Association denied because the info
+ * in the Power Cap element is
+ * unacceptable.
+ */
+#define DOT11_STATUS_ASSOC_BAD_SUP_CHANNELS 24 /* Association denied because the info
+ * in the Supported Channel element is
+ * unacceptable
+ */
+#define DOT11_STATUS_ASSOC_SHORTSLOT_REQUIRED 25 /* Association denied due to requesting
+ * station not supporting the Short Slot
+ * Time option
+ */
+#define DOT11_STATUS_ASSOC_ERPBCC_REQUIRED 26 /* Association denied due to requesting
+ * station not supporting the ER-PBCC
+ * Modulation option
+ */
+#define DOT11_STATUS_ASSOC_DSSOFDM_REQUIRED 27 /* Association denied due to requesting
+ * station not supporting the DSS-OFDM
+ * option
+ */
+
+/* Info Elts, length of INFORMATION portion of Info Elts */
+#define DOT11_MNG_DS_PARAM_LEN 1 /* d11 management DS parameter length */
+#define DOT11_MNG_IBSS_PARAM_LEN 2 /* d11 management IBSS parameter length */
+
+/* TIM Info element has 3 bytes fixed info in INFORMATION field,
+ * followed by 1 to 251 bytes of Partial Virtual Bitmap
+ */
+#define DOT11_MNG_TIM_FIXED_LEN 3 /* d11 management TIM fixed length */
+#define DOT11_MNG_TIM_DTIM_COUNT 0 /* d11 management DTIM count */
+#define DOT11_MNG_TIM_DTIM_PERIOD 1 /* d11 management DTIM period */
+#define DOT11_MNG_TIM_BITMAP_CTL 2 /* d11 management TIM BITMAP control */
+#define DOT11_MNG_TIM_PVB 3 /* d11 management TIM PVB */
+
+/* TLV defines */
+#define TLV_TAG_OFF 0 /* tag offset */
+#define TLV_LEN_OFF 1 /* length offset */
+#define TLV_HDR_LEN 2 /* header length */
+#define TLV_BODY_OFF 2 /* body offset */
+
+/* Management Frame Information Element IDs */
+#define DOT11_MNG_SSID_ID 0 /* d11 management SSID id */
+#define DOT11_MNG_RATES_ID 1 /* d11 management rates id */
+#define DOT11_MNG_FH_PARMS_ID 2 /* d11 management FH parameter id */
+#define DOT11_MNG_DS_PARMS_ID 3 /* d11 management DS parameter id */
+#define DOT11_MNG_CF_PARMS_ID 4 /* d11 management CF parameter id */
+#define DOT11_MNG_TIM_ID 5 /* d11 management TIM id */
+#define DOT11_MNG_IBSS_PARMS_ID 6 /* d11 management IBSS parameter id */
+#define DOT11_MNG_COUNTRY_ID 7 /* d11 management country id */
+#define DOT11_MNG_HOPPING_PARMS_ID 8 /* d11 management hopping parameter id */
+#define DOT11_MNG_HOPPING_TABLE_ID 9 /* d11 management hopping table id */
+#define DOT11_MNG_REQUEST_ID 10 /* d11 management request id */
+#define DOT11_MNG_QBSS_LOAD_ID 11 /* d11 management QBSS Load id */
+#define DOT11_MNG_CHALLENGE_ID 16 /* d11 management chanllenge id */
+#define DOT11_MNG_PWR_CONSTRAINT_ID 32 /* 11H PowerConstraint */
+#define DOT11_MNG_PWR_CAP_ID 33 /* 11H PowerCapability */
+#define DOT11_MNG_TPC_REQUEST_ID 34 /* 11H TPC Request */
+#define DOT11_MNG_TPC_REPORT_ID 35 /* 11H TPC Report */
+#define DOT11_MNG_SUPP_CHANNELS_ID 36 /* 11H Supported Channels */
+#define DOT11_MNG_CHANNEL_SWITCH_ID 37 /* 11H ChannelSwitch Announcement */
+#define DOT11_MNG_MEASURE_REQUEST_ID 38 /* 11H MeasurementRequest */
+#define DOT11_MNG_MEASURE_REPORT_ID 39 /* 11H MeasurementReport */
+#define DOT11_MNG_QUIET_ID 40 /* 11H Quiet */
+#define DOT11_MNG_IBSS_DFS_ID 41 /* 11H IBSS_DFS */
+#define DOT11_MNG_ERP_ID 42 /* d11 management ERP id */
+#define DOT11_MNG_TS_DELAY_ID 43 /* d11 management TS Delay id */
+#define DOT11_MNG_NONERP_ID 47 /* d11 management NON-ERP id */
+#define DOT11_MNG_RSN_ID 48 /* d11 management RSN id */
+#define DOT11_MNG_EXT_RATES_ID 50 /* d11 management ext. rates id */
+#define DOT11_MNG_WPA_ID 221 /* d11 management WPA id */
+#define DOT11_MNG_PROPR_ID 221 /* d11 management proprietary id */
+
+/* Rate element Basic flag and rate mask */
+#define DOT11_RATE_BASIC 0x80 /* flag for a Basic Rate */
+#define DOT11_RATE_MASK 0x7F /* mask for numeric part of rate */
+
+/* ERP info element bit values */
+#define DOT11_MNG_ERP_LEN 1 /* ERP is currently 1 byte long */
+#define DOT11_MNG_NONERP_PRESENT 0x01 /* NonERP (802.11b) STAs are present
+ *in the BSS
+ */
+#define DOT11_MNG_USE_PROTECTION 0x02 /* Use protection mechanisms for
+ *ERP-OFDM frames
+ */
+#define DOT11_MNG_BARKER_PREAMBLE 0x04 /* Short Preambles: 0 == allowed,
+ * 1 == not allowed
+ */
+/* TS Delay element offset & size */
+#define DOT11_MGN_TS_DELAY_LEN 4 /* length of TS DELAY IE */
+#define TS_DELAY_FIELD_SIZE 4 /* TS DELAY field size */
+
+/* Capability Information Field */
+#define DOT11_CAP_ESS 0x0001 /* d11 cap. ESS */
+#define DOT11_CAP_IBSS 0x0002 /* d11 cap. IBSS */
+#define DOT11_CAP_POLLABLE 0x0004 /* d11 cap. pollable */
+#define DOT11_CAP_POLL_RQ 0x0008 /* d11 cap. poll request */
+#define DOT11_CAP_PRIVACY 0x0010 /* d11 cap. privacy */
+#define DOT11_CAP_SHORT 0x0020 /* d11 cap. short */
+#define DOT11_CAP_PBCC 0x0040 /* d11 cap. PBCC */
+#define DOT11_CAP_AGILITY 0x0080 /* d11 cap. agility */
+#define DOT11_CAP_SPECTRUM 0x0100 /* d11 cap. spectrum */
+#define DOT11_CAP_SHORTSLOT 0x0400 /* d11 cap. shortslot */
+#define DOT11_CAP_CCK_OFDM 0x2000 /* d11 cap. CCK/OFDM */
+
+/* Action Frame Constants */
+#define DOT11_ACTION_CAT_ERR_MASK 0x80 /* d11 action category error mask */
+#define DOT11_ACTION_CAT_MASK 0x7F /* d11 action category mask */
+#define DOT11_ACTION_CAT_SPECT_MNG 0x00 /* d11 action category spectrum management */
+#define DOT11_ACTION_CAT_BLOCKACK 0x03 /* d11 action category block ack */
+#define DOT11_ACTION_NOTIFICATION 0x11 /* 17 */
+
+#define DOT11_ACTION_ID_M_REQ 0 /* d11 action measurement request */
+#define DOT11_ACTION_ID_M_REP 1 /* d11 action measurement response */
+#define DOT11_ACTION_ID_TPC_REQ 2 /* d11 action TPC request */
+#define DOT11_ACTION_ID_TPC_REP 3 /* d11 action TPC response */
+#define DOT11_ACTION_ID_CHANNEL_SWITCH 4 /* d11 action channel switch */
+
+/* HT (EWC) action ids */
+#define DOT11_ACTION_ID_HT_CH_WIDTH 0 /* mimo ps action frame id */
+#define DOT11_ACTION_ID_HT_MIMO_PS 1 /* mimo ps action frame id */
+
+/* Block Ack action types */
+#define DOT11_BA_ACTION_ADDBA_REQ 0 /* ADDBA Req action frame type */
+#define DOT11_BA_ACTION_ADDBA_RESP 1 /* ADDBA Resp action frame type */
+#define DOT11_BA_ACTION_DELBA 2 /* DELBA action frame type */
+
+/* ADDBA action parameters */
+#define DOT11_ADDBA_PARAM_POLICY_MASK 0x0002 /* policy mask(ack vs delayed) */
+#define DOT11_ADDBA_PARAM_POLICY_SHIFT 1 /* policy shift */
+#define DOT11_ADDBA_PARAM_TID_MASK 0x003c /* tid mask */
+#define DOT11_ADDBA_PARAM_TID_SHIFT 2 /* tid shift */
+#define DOT11_ADDBA_PARAM_BSIZE_MASK 0xffc0 /* buffer size mask */
+#define DOT11_ADDBA_PARAM_BSIZE_SHIFT 6 /* buffer size shift */
+
+#define DOT11_ADDBA_POLICY_DELAYED 0 /* delayed BA policy */
+#define DOT11_ADDBA_POLICY_IMMEDIATE 1 /* immediate BA policy */
+
+struct dot11_addba_req {
+ uint8 category; /* category of action frame (3) */
+ uint8 action; /* action: addba req */
+ uint8 token; /* identifier */
+ uint16 addba_param_set; /* parameter set */
+ uint16 timeout; /* timeout in seconds */
+ uint16 start_seqnum; /* starting sequence number */
+}PACKED;
+typedef struct dot11_addba_req dot11_addba_req_t;
+#define DOT11_ADDBA_REQ_LEN 9 /* length of addba req frame */
+
+struct dot11_addba_resp {
+ uint8 category; /* category of action frame (3) */
+ uint8 action; /* action: addba resp */
+ uint8 token; /* identifier */
+ uint16 status; /* status of add request */
+ uint16 addba_param_set; /* negotiated parameter set */
+ uint16 timeout; /* negotiated timeout in seconds */
+}PACKED;
+typedef struct dot11_addba_resp dot11_addba_resp_t;
+#define DOT11_ADDBA_RESP_LEN 9 /* length of addba resp frame */
+
+/* DELBA action parameters */
+#define DOT11_DELBA_PARAM_INIT_MASK 0x0800 /* initiator mask */
+#define DOT11_DELBA_PARAM_INIT_SHIFT 11 /* initiator shift */
+#define DOT11_DELBA_PARAM_TID_MASK 0xf000 /* tid mask */
+#define DOT11_DELBA_PARAM_TID_SHIFT 12 /* tid shift */
+
+struct dot11_delba {
+ uint8 category; /* category of action frame (3) */
+ uint8 action; /* action: addba req */
+ uint16 delba_param_set; /* paarmeter set */
+ uint16 reason; /* reason for dellba */
+}PACKED;
+typedef struct dot11_delba dot11_delba_t;
+#define DOT11_DELBA_LEN 6 /* length of delba frame */
+
+/* MLME Enumerations */
+#define DOT11_BSSTYPE_INFRASTRUCTURE 0 /* d11 infrastructure */
+#define DOT11_BSSTYPE_INDEPENDENT 1 /* d11 independent */
+#define DOT11_BSSTYPE_ANY 2 /* d11 any BSS type */
+#define DOT11_SCANTYPE_ACTIVE 0 /* d11 scan active */
+#define DOT11_SCANTYPE_PASSIVE 1 /* d11 scan passive */
+
+/* 802.11 BRCM "Compromise" Pre N constants */
+#define PREN_PREAMBLE 24 /* green field preamble time */
+#define PREN_MM_EXT 16 /* extra mixed mode preamble time */
+#define PREN_PREAMBLE_EXT 4 /* extra preamble (multiply by unique_streams-1) */
+
+/* 802.11 A PHY constants */
+#define APHY_SLOT_TIME 9 /* APHY slot time */
+#define APHY_SIFS_TIME 16 /* APHY SIFS time */
+#define APHY_DIFS_TIME (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME)) /* APHY DIFS time */
+#define APHY_PREAMBLE_TIME 16 /* APHY preamble time */
+#define APHY_SIGNAL_TIME 4 /* APHY signal time */
+#define APHY_SYMBOL_TIME 4 /* APHY symbol time */
+#define APHY_SERVICE_NBITS 16 /* APHY service nbits */
+#define APHY_TAIL_NBITS 6 /* APHY tail nbits */
+#define APHY_CWMIN 15 /* APHY cwmin */
+
+/* 802.11 B PHY constants */
+#define BPHY_SLOT_TIME 20 /* BPHY slot time */
+#define BPHY_SIFS_TIME 10 /* BPHY SIFS time */
+#define BPHY_DIFS_TIME 50 /* BPHY DIFS time */
+#define BPHY_PLCP_TIME 192 /* BPHY PLCP time */
+#define BPHY_PLCP_SHORT_TIME 96 /* BPHY PLCP short time */
+#define BPHY_CWMIN 31 /* BPHY cwmin */
+
+/* 802.11 G constants */
+#define DOT11_OFDM_SIGNAL_EXTENSION 6 /* d11 OFDM signal extension */
+
+#define PHY_CWMAX 1023 /* PHY cwmax */
+
+#define DOT11_MAXNUMFRAGS 16 /* max # fragments per MSDU */
+
+/* dot11Counters Table - 802.11 spec., Annex D */
+typedef struct d11cnt {
+ uint32 txfrag; /* dot11TransmittedFragmentCount */
+ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */
+ uint32 txfail; /* dot11FailedCount */
+ uint32 txretry; /* dot11RetryCount */
+ uint32 txretrie; /* dot11MultipleRetryCount */
+ uint32 rxdup; /* dot11FrameduplicateCount */
+ uint32 txrts; /* dot11RTSSuccessCount */
+ uint32 txnocts; /* dot11RTSFailureCount */
+ uint32 txnoack; /* dot11ACKFailureCount */
+ uint32 rxfrag; /* dot11ReceivedFragmentCount */
+ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */
+ uint32 rxcrc; /* dot11FCSErrorCount */
+ uint32 txfrmsnt; /* dot11TransmittedFrameCount */
+ uint32 rxundec; /* dot11WEPUndecryptableCount */
+} d11cnt_t;
+
+/* BRCM OUI */
+#define BRCM_OUI "\x00\x10\x18" /* Broadcom OUI */
+
+/* OUI for BRCM proprietary IE */
+#define BRCM_PROP_OUI "\x00\x90\x4C" /* Broadcom proprietary OUI */
+
+/* BRCM info element */
+struct brcm_ie {
+ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */
+ uint8 len; /* IE length */
+ uint8 oui[3]; /* Proprietary OUI, BRCM_OUI */
+ uint8 ver; /* type/ver of this IE */
+ uint8 assoc; /* # of assoc STAs */
+ uint8 flags; /* misc flags */
+ uint8 flags1; /* misc flags */
+ uint16 amsdu_mtu_pref; /* preferred A-MSDU MTU */
+} PACKED;
+typedef struct brcm_ie brcm_ie_t;
+#define BRCM_IE_LEN 11 /* BRCM IE length */
+#define BRCM_IE_VER 2 /* BRCM IE version */
+#define BRCM_IE_LEGACY_AES_VER 1 /* BRCM IE legacy AES version */
+
+/* brcm_ie flags */
+#define BRF_ABCAP 0x1 /* afterburner capable */
+#define BRF_ABRQRD 0x2 /* afterburner requested */
+#define BRF_LZWDS 0x4 /* lazy wds enabled */
+#define BRF_BLOCKACK 0x8 /* BlockACK capable */
+#define BRF_ABCOUNTER_MASK 0xf0 /* afterburner wds "state" counter */
+#define BRF_ABCOUNTER_SHIFT 4 /* offset of afterburner wds "state" counter */
+
+/* brcm_ie flags1 */
+#define BRF1_AMSDU 0x1 /* A-MSDU capable */
+
+#define AB_WDS_TIMEOUT_MAX 15 /* afterburner wds Max count indicating not
+ * locally capable
+ */
+#define AB_WDS_TIMEOUT_MIN 1 /* afterburner wds, use zero count as indicating
+ * "downrev"
+ */
+
+/* EWC definitions */
+#define MCSSET_LEN 16 /* 16-bits per 8-bit set to give 128-bits bitmap of MCS Index */
+
+struct ewc_cap {
+ uint16 cap;
+ uint8 params;
+ uint8 supp_mcs[MCSSET_LEN];
+ uint16 ext_htcap;
+ uint32 txbf_cap;
+ uint8 as_cap;
+} PACKED;
+typedef struct ewc_cap ewc_cap_t;
+
+/* CAP IE: EWC 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */
+/* the capability IE is primarily used to convey this nodes abilities */
+struct ewc_cap_ie {
+ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */
+ uint8 len; /* IE length */
+ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */
+ uint8 type; /* type inidicates what follows */
+ ewc_cap_t cap;
+} PACKED;
+typedef struct ewc_cap_ie ewc_cap_ie_t;
+
+#define EWC_CAP_IE_LEN (26+4)
+#define EWC_CAP_IE_TYPE 51
+
+#define EWC_CAP_ADC_CODING 0x0001 /* Advance coding support */
+#define EWC_CAP_40MHZ 0x0002 /* FALSE:20Mhz, TRUE: 20 and 40MHZ supported */
+#define EWC_CAP_MIMO_PS_MASK 0x000C /* Mimo PS mask */
+#define EWC_CAP_MIMO_PS_SHIFT 0x0002 /* Mimo PS shift */
+#define EWC_CAP_MIMO_PS_OFF 0x0003 /* Mimo PS, no restriction */
+#define EWC_CAP_MIMO_PS_RTS 0x0001 /* Mimo PS, send RTS/CTS around MIMO frames */
+#define EWC_CAP_MIMO_PS_ON 0x0000 /* Mimo PS, MIMO disallowed */
+#define EWC_CAP_GF 0x0010 /* Greenfield preamble support */
+#define EWC_CAP_SHORT_GI_20 0x0020 /* 20MHZ short guard interval support */
+#define EWC_CAP_SHORT_GI_40 0x0040 /* 40Mhz short guard interval support */
+#define EWC_CAP_TX_STBC 0x0080 /* Tx STBC support */
+#define EWC_CAP_RX_STBC_MASK 0x0300 /* Rx STBC mask */
+#define EWC_CAP_RX_STBC_SHIFT 8 /* Rx STBC shift */
+#define EWC_CAP_DELAYED_BA 0x0400 /* delayed BA support */
+#define EWC_CAP_MAX_AMSDU 0x0800 /* Max AMSDU size in bytes , 0=3839, 1=7935 */
+#define EWC_CAP_DSSS_CCK 0x1000 /* DSSS/CCK supported by the BSS */
+#define EWC_CAP_PSMP 0x2000 /* Power Save Multi Poll support */
+#define EWC_CAP_STBC_CTL 0x4000 /* STBC control frame support */
+#define EWC_CAP_LSIG_TXOP 0x8000 /* L-SIG TXOP protection support */
+
+#define EWC_MAX_AMSDU 7935 /* max amsdu size (bytes) per the EWC spec */
+#define EWC_MIN_AMSDU 3835 /* min amsdu size (bytes) per the EWC spec */
+
+#define EWC_PARAMS_RX_FACTOR_MASK 0x03 /* ampdu rcv factor mask */
+#define EWC_PARAMS_DENSITY_MASK 0x1C /* ampdu density mask */
+#define EWC_PARAMS_DENSITY_SHIFT 2 /* ampdu density shift */
+
+/* EWC/AMPDU specific define */
+#define AMPDU_MAX_MPDU_DENSITY 7 /* max mpdu density; in 1/8 usec units */
+#define AMPDU_MAX_RX_FACTOR 3 /* max rcv ampdu len (64kb) */
+#define AMPDU_RX_FACTOR_BASE 8*1024 /* ampdu factor base for rx len */
+#define AMPDU_DELIMITER_LEN 4 /* length of ampdu delimiter */
+
+struct ewc_add {
+ uint8 ctl_ch; /* control channel number */
+ uint8 byte1; /* ext ch,rec. ch. width, RIFS support */
+ uint16 opmode; /* operation mode */
+ uint16 misc_bits; /* misc bits */
+ uint8 basic_mcs[MCSSET_LEN]; /* required MCS set */
+} PACKED;
+typedef struct ewc_add ewc_add_t;
+
+/* ADD IE: EWC 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */
+/* the additional IE is primarily used to convey the current BSS configuration */
+struct ewc_add_ie {
+ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */
+ uint8 len; /* IE length */
+ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */
+ uint8 type; /* indicates what follows */
+ ewc_add_t add;
+} PACKED;
+typedef struct ewc_add_ie ewc_add_ie_t;
+
+#define EWC_ADD_IE_LEN (22+4)
+#define EWC_ADD_IE_TYPE 52
+
+/* byte1 defn's */
+#define EWC_EXT_CH_MASK 0x03 /* extension channel mask */
+#define EWC_EXT_CH_UPPER 0x01 /* ext. ch. on upper sb */
+#define EWC_EXT_CH_LOWER 0x03 /* ext. ch. on lower sb */
+#define EWC_EXT_CH_NONE 0x00 /* extension channel mask */
+#define EWC_BW_ANY 0x04 /* set, STA can use 20 or 40MHz */
+#define EWC_RIFS_PERMITTED 0x08 /* RIFS allowed */
+
+/* opmode defn's */
+#define EWC_OPMODE_MASK 0x0003 /* protection mode mask */
+#define EWC_OPMODE_PURE 0x0000 /* protection mode PURE */
+#define EWC_OPMODE_HT20IN40 0x0002 /* protection mode 20MHz HT in 40MHz BSS */
+#define EWC_OPMODE_MIXED 0x0003 /* protection mode Mixed Mode */
+#define EWC_NONGF_PRESENT 0x0004 /* protection mode non-GF */
+
+/* misc_bites defn's */
+#define EWC_BASIC_STBC_MCS 0x007f /* basic STBC MCS */
+#define EWC_DUAL_STBC_PROT 0x0080 /* Dual STBC Protection */
+#define EWC_SECOND_BCN 0x0100 /* Secondary beacon support */
+#define EWC_LSIG_TXOP 0x0200 /* L-SIG TXOP Protection full support */
+#define EWC_PCO_ACTIVE 0x0400 /* PCO active */
+#define EWC_PCO_PHASE 0x0800 /* PCO phase */
+
+/* Macros for opmode */
+#define EWC_MIXEDMODE_PRESENT(add) ((ltoh16_ua(&add.opmode) & EWC_OPMODE_MASK) \
+ == EWC_OPMODE_MIXED) /* mixed mode present */
+#define EWC_HT20_PRESENT(add) ((ltoh16_ua(&add.opmode) & EWC_OPMODE_MASK) \
+ == EWC_OPMODE_HT20IN40) /* 20MHz HT present */
+#define EWC_USE_PROTECTION(add) (EWC_HT20_PRESENT((add)) || \
+ EWC_MIXEDMODE_PRESENT((add))) /* use protection */
+
+/* Vendor IE structure */
+struct vndr_ie {
+ uchar id;
+ uchar len;
+ uchar oui [3];
+ uchar data [1]; /* Variable size data */
+}PACKED;
+typedef struct vndr_ie vndr_ie_t;
+
+#define VNDR_IE_HDR_LEN 2 /* id + len field */
+#define VNDR_IE_MIN_LEN 3 /* size of the oui field */
+#define VNDR_IE_MAX_LEN 256 /* verdor IE max length */
+
+/* WPA definitions */
+#define WPA_VERSION 1 /* WPA version */
+#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */
+
+#define WPA2_VERSION 1 /* WPA2 version */
+#define WPA2_VERSION_LEN 2 /* WAP2 version length */
+#define WPA2_OUI "\x00\x0F\xAC" /* WPA2 OUI */
+
+#define WPA_OUI_LEN 3 /* WPA OUI length */
+
+/* RSN authenticated key managment suite */
+#define RSN_AKM_NONE 0 /* None (IBSS) */
+#define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */
+#define RSN_AKM_PSK 2 /* Pre-shared Key */
+
+/* Key related defines */
+#define DOT11_MAX_DEFAULT_KEYS 4 /* number of default keys */
+#define DOT11_MAX_KEY_SIZE 32 /* max size of any key */
+#define DOT11_MAX_IV_SIZE 16 /* max size of any IV */
+#define DOT11_EXT_IV_FLAG (1<<5) /* flag to indicate IV is > 4 bytes */
+
+#define WEP1_KEY_SIZE 5 /* max size of any WEP key */
+#define WEP1_KEY_HEX_SIZE 10 /* size of WEP key in hex. */
+#define WEP128_KEY_SIZE 13 /* max size of any WEP key */
+#define WEP128_KEY_HEX_SIZE 26 /* size of WEP key in hex. */
+#define TKIP_MIC_SIZE 8 /* size of TKIP MIC */
+#define TKIP_EOM_SIZE 7 /* max size of TKIP EOM */
+#define TKIP_EOM_FLAG 0x5a /* TKIP EOM flag byte */
+#define TKIP_KEY_SIZE 32 /* size of any TKIP key */
+#define TKIP_MIC_AUTH_TX 16 /* offset to Authenticator MIC TX key */
+#define TKIP_MIC_AUTH_RX 24 /* offset to Authenticator MIC RX key */
+#define TKIP_MIC_SUP_RX TKIP_MIC_AUTH_TX /* offset to Supplicant MIC RX key */
+#define TKIP_MIC_SUP_TX TKIP_MIC_AUTH_RX /* offset to Supplicant MIC TX key */
+#define AES_KEY_SIZE 16 /* size of AES key */
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#endif /* _802_11_H_ */
diff --git a/package/broadcom-wl/src/wlc/include/proto/bcmeth.h b/package/broadcom-wl/src/wlc/include/proto/bcmeth.h
new file mode 100644
index 0000000000..7b3295389a
--- /dev/null
+++ b/package/broadcom-wl/src/wlc/include/proto/bcmeth.h
@@ -0,0 +1,101 @@
+/*
+ * Broadcom Ethernettype protocol definitions
+ *
+ * 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.
+ *
+ * $Id: bcmeth.h,v 1.1.1.4 2006/02/27 03:43:16 honor Exp $
+ */
+
+/*
+ * Broadcom Ethernet protocol defines
+ */
+
+#ifndef _BCMETH_H_
+#define _BCMETH_H_
+
+/* enable structure packing */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#pragma pack(1)
+#define PACKED
+#endif
+
+/* ETHER_TYPE_BRCM is defined in ethernet.h */
+
+/*
+ * Following the 2byte BRCM ether_type is a 16bit BRCM subtype field
+ * in one of two formats: (only subtypes 32768-65535 are in use now)
+ *
+ * subtypes 0-32767:
+ * 8 bit subtype (0-127)
+ * 8 bit length in bytes (0-255)
+ *
+ * subtypes 32768-65535:
+ * 16 bit big-endian subtype
+ * 16 bit big-endian length in bytes (0-65535)
+ *
+ * length is the number of additional bytes beyond the 4 or 6 byte header
+ *
+ * Reserved values:
+ * 0 reserved
+ * 5-15 reserved for iLine protocol assignments
+ * 17-126 reserved, assignable
+ * 127 reserved
+ * 32768 reserved
+ * 32769-65534 reserved, assignable
+ * 65535 reserved
+ */
+
+/*
+ * While adding the subtypes and their specific processing code make sure
+ * bcmeth_bcm_hdr_t is the first data structure in the user specific data structure definition
+ */
+
+#define BCMILCP_SUBTYPE_RATE 1
+#define BCMILCP_SUBTYPE_LINK 2
+#define BCMILCP_SUBTYPE_CSA 3
+#define BCMILCP_SUBTYPE_LARQ 4
+#define BCMILCP_SUBTYPE_VENDOR 5
+#define BCMILCP_SUBTYPE_FLH 17
+
+#define BCMILCP_SUBTYPE_VENDOR_LONG 32769
+#define BCMILCP_SUBTYPE_CERT 32770
+#define BCMILCP_SUBTYPE_SES 32771
+
+
+#define BCMILCP_BCM_SUBTYPE_RESERVED 0
+#define BCMILCP_BCM_SUBTYPE_EVENT 1
+#define BCMILCP_BCM_SUBTYPE_SES 2
+/*
+ * The EAPOL type is not used anymore. Instead EAPOL messages are now embedded
+ * within BCMILCP_BCM_SUBTYPE_EVENT type messages
+ */
+/* #define BCMILCP_BCM_SUBTYPE_EAPOL 3 */
+
+#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH 8
+#define BCMILCP_BCM_SUBTYPEHDR_VERSION 0
+
+/* These fields are stored in network order */
+typedef struct bcmeth_hdr
+{
+ uint16 subtype; /* Vendor specific..32769 */
+ uint16 length;
+ uint8 version; /* Version is 0 */
+ uint8 oui[3]; /* Broadcom OUI */
+ /* user specific Data */
+ uint16 usr_subtype;
+} PACKED bcmeth_hdr_t;
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#endif /* _BCMETH_H_ */
diff --git a/package/broadcom-wl/src/wlc/include/proto/bcmevent.h b/package/broadcom-wl/src/wlc/include/proto/bcmevent.h
new file mode 100644
index 0000000000..d922a5d215
--- /dev/null
+++ b/package/broadcom-wl/src/wlc/include/proto/bcmevent.h
@@ -0,0 +1,152 @@
+/*
+ * Broadcom Event protocol definitions
+ *
+ * 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.
+ *
+ *
+ * Dependencies: proto/bcmeth.h
+ *
+ * $Id: bcmevent.h,v 1.1.1.3 2006/02/27 03:43:16 honor Exp $
+ *
+ */
+
+/*
+ * Broadcom Ethernet Events protocol defines
+ *
+ */
+
+#ifndef _BCMEVENT_H_
+#define _BCMEVENT_H_
+
+/* enable structure packing */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#pragma pack(1)
+#define PACKED
+#endif /* defined(__GNUC__) */
+
+#define BCM_EVENT_MSG_VERSION 1 /* wl_event_msg_t struct version */
+#define BCM_MSG_IFNAME_MAX 16 /* max length of interface name */
+
+/* flags */
+#define WLC_EVENT_MSG_LINK 0x01 /* link is up */
+#define WLC_EVENT_MSG_FLUSHTXQ 0x02 /* flush tx queue on MIC error */
+#define WLC_EVENT_MSG_GROUP 0x04 /* group MIC error */
+
+/* theses fields are stored in network order */
+typedef struct
+{
+ uint16 version;
+ uint16 flags; /* see flags below */
+ uint32 event_type; /* Message (see below) */
+ uint32 status; /* Status code (see below) */
+ uint32 reason; /* Reason code (if applicable) */
+ uint32 auth_type; /* WLC_E_AUTH */
+ uint32 datalen; /* data buf */
+ struct ether_addr addr; /* Station address (if applicable) */
+ char ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */
+} PACKED wl_event_msg_t;
+
+/* used by driver msgs */
+typedef struct bcm_event {
+ struct ether_header eth;
+ bcmeth_hdr_t bcm_hdr;
+ wl_event_msg_t event;
+ /* data portion follows */
+} PACKED bcm_event_t;
+
+#define BCM_MSG_LEN (sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - sizeof(struct ether_header))
+
+/* Event messages */
+#define WLC_E_SET_SSID 0 /* indicates status of set SSID */
+#define WLC_E_JOIN 1 /* differentiates join IBSS from found (WLC_E_START) IBSS */
+#define WLC_E_START 2 /* STA founded an IBSS or AP started a BSS */
+#define WLC_E_AUTH 3 /* 802.11 AUTH request */
+#define WLC_E_AUTH_IND 4 /* 802.11 AUTH indication */
+#define WLC_E_DEAUTH 5 /* 802.11 DEAUTH request */
+#define WLC_E_DEAUTH_IND 6 /* 802.11 DEAUTH indication */
+#define WLC_E_ASSOC 7 /* 802.11 ASSOC request */
+#define WLC_E_ASSOC_IND 8 /* 802.11 ASSOC indication */
+#define WLC_E_REASSOC 9 /* 802.11 REASSOC request */
+#define WLC_E_REASSOC_IND 10 /* 802.11 REASSOC indication */
+#define WLC_E_DISASSOC 11 /* 802.11 DISASSOC request */
+#define WLC_E_DISASSOC_IND 12 /* 802.11 DISASSOC indication */
+#define WLC_E_QUIET_START 13 /* 802.11h Quiet period started */
+#define WLC_E_QUIET_END 14 /* 802.11h Quiet period ended */
+#define WLC_E_BEACON_RX 15 /* BEACONS received/lost indication */
+#define WLC_E_LINK 16 /* generic link indication */
+#define WLC_E_MIC_ERROR 17 /* TKIP MIC error occurred */
+#define WLC_E_NDIS_LINK 18 /* NDIS style link indication */
+#define WLC_E_ROAM 19 /* roam attempt occurred: indicate status & reason */
+#define WLC_E_TXFAIL 20 /* change in dot11FailedCount (txfail) */
+#define WLC_E_PMKID_CACHE 21 /* WPA2 pmkid cache indication */
+#define WLC_E_RETROGRADE_TSF 22 /* current AP's TSF value went backward */
+#define WLC_E_PRUNE 23 /* AP was pruned from join list for reason */
+#define WLC_E_AUTOAUTH 24 /* report AutoAuth table entry match for join attempt */
+#define WLC_E_EAPOL_MSG 25 /* Event encapsulating an EAPOL message */
+#define WLC_E_SCAN_COMPLETE 26 /* Scan results are ready or scan was aborted */
+#define WLC_E_ADDTS_IND 27 /* indicate to host addts fail/success */
+#define WLC_E_DELTS_IND 28 /* indicate to host delts fail/success */
+#define WLC_E_BCNSENT_IND 29 /* indicate to host of beacon transmit */
+#define WLC_E_BCNRX_MSG 30 /* Send the received beacon up to the host */
+#define WLC_E_LAST 31 /* highest val + 1 for range checking */
+
+/* Event status codes */
+#define WLC_E_STATUS_SUCCESS 0 /* operation was successful */
+#define WLC_E_STATUS_FAIL 1 /* operation failed */
+#define WLC_E_STATUS_TIMEOUT 2 /* operation timed out */
+#define WLC_E_STATUS_NO_NETWORKS 3 /* failed due to no matching network found */
+#define WLC_E_STATUS_ABORT 4 /* operation was aborted */
+#define WLC_E_STATUS_NO_ACK 5 /* protocol failure: packet not ack'd */
+#define WLC_E_STATUS_UNSOLICITED 6 /* AUTH or ASSOC packet was unsolicited */
+#define WLC_E_STATUS_ATTEMPT 7 /* attempt to assoc to an auto auth configuration */
+
+/* roam reason codes */
+#define WLC_E_REASON_INITIAL_ASSOC 0 /* initial assoc */
+#define WLC_E_REASON_LOW_RSSI 1 /* roamed due to low RSSI */
+#define WLC_E_REASON_DEAUTH 2 /* roamed due to DEAUTH indication */
+#define WLC_E_REASON_DISASSOC 3 /* roamed due to DISASSOC indication */
+#define WLC_E_REASON_BCNS_LOST 4 /* roamed due to lost beacons */
+#define WLC_E_REASON_FAST_ROAM_FAILED 5 /* roamed due to fast roam failure */
+#define WLC_E_REASON_DIRECTED_ROAM 6 /* roamed due to request by AP */
+#define WLC_E_REASON_TSPEC_REJECTED 7 /* roamed due to TSPEC rejection */
+#define WLC_E_REASON_BETTER_AP 8 /* roamed due to finding better AP */
+
+/* prune reason codes */
+#define WLC_E_PRUNE_ENCR_MISMATCH 1 /* ecryption mismatch */
+#define WLC_E_PRUNE_BCAST_BSSID 2 /* AP uses a broadcast BSSID */
+#define WLC_E_PRUNE_MAC_DENY 3 /* STA's MAC addr is in AP's MAC deny list */
+#define WLC_E_PRUNE_MAC_NA 4 /* STA's MAC addr is not in AP's MAC allow list */
+#define WLC_E_PRUNE_REG_PASSV 5 /* AP not allowed due to regulatory restriction */
+#define WLC_E_PRUNE_SPCT_MGMT 6 /* AP does not support STA locale spectrum mgmt */
+#define WLC_E_PRUNE_RADAR 7 /* AP is on a radar channel of STA locale */
+#define WLC_E_RSN_MISMATCH 8 /* STA does not support AP's RSN */
+#define WLC_E_PRUNE_NO_COMMON_RATES 9 /* No rates in common with AP */
+#define WLC_E_PRUNE_BASIC_RATES 10 /* STA does not support all basic rates of BSS */
+#define WLC_E_PRUNE_CCXFAST_PREVAP 11 /* CCX FAST ROAM: prune previous AP */
+#define WLC_E_PRUNE_CIPHER_NA 12 /* BSS's cipher not supported */
+#define WLC_E_PRUNE_KNOWN_STA 13 /* AP is already known to us as a STA */
+#define WLC_E_PRUNE_CCXFAST_DROAM 14 /* CCX FAST ROAM: prune unqulified AP */
+#define WLC_E_PRUNE_WDS_PEER 15 /* AP is already known to us as a WDS peer */
+#define WLC_E_PRUNE_QBSS_LOAD 16 /* QBSS LOAD - AAC is too low */
+#define WLC_E_PRUNE_HOME_AP 17 /* prune home AP */
+
+/* WLC_SET_CALLBACK data type */
+typedef struct wlc_event_cb {
+ void (*fn)(void *, bcm_event_t *); /* Callback function */
+ void *context; /* Passed to callback function */
+} wlc_event_cb_t;
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif /* PACKED */
+
+#endif /* _BCMEVENT_H_ */
diff --git a/package/broadcom-wl/src/wlc/include/proto/ethernet.h b/package/broadcom-wl/src/wlc/include/proto/ethernet.h
new file mode 100644
index 0000000000..03fd4f654c
--- /dev/null
+++ b/package/broadcom-wl/src/wlc/include/proto/ethernet.h
@@ -0,0 +1,165 @@
+/*
+ * From FreeBSD 2.2.7: Fundamental constants relating to ethernet.
+ *
+ * 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.
+ *
+ * $Id: ethernet.h,v 1.1.1.14 2006/02/27 03:43:16 honor Exp $
+ */
+
+#ifndef _NET_ETHERNET_H_ /* use native BSD ethernet.h when available */
+#define _NET_ETHERNET_H_
+
+#ifndef _TYPEDEFS_H_
+#include "typedefs.h"
+#endif
+
+/* enable structure packing */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#pragma pack(1)
+#define PACKED
+#endif
+
+/*
+ * The number of bytes in an ethernet (MAC) address.
+ */
+#define ETHER_ADDR_LEN 6
+
+/*
+ * The number of bytes in the type field.
+ */
+#define ETHER_TYPE_LEN 2
+
+/*
+ * The number of bytes in the trailing CRC field.
+ */
+#define ETHER_CRC_LEN 4
+
+/*
+ * The length of the combined header.
+ */
+#define ETHER_HDR_LEN (ETHER_ADDR_LEN*2+ETHER_TYPE_LEN)
+
+/*
+ * The minimum packet length.
+ */
+#define ETHER_MIN_LEN 64
+
+/*
+ * The minimum packet user data length.
+ */
+#define ETHER_MIN_DATA 46
+
+/*
+ * The maximum packet length.
+ */
+#define ETHER_MAX_LEN 1518
+
+/*
+ * The maximum packet user data length.
+ */
+#define ETHER_MAX_DATA 1500
+
+/* ether types */
+#define ETHER_TYPE_IP 0x0800 /* IP */
+#define ETHER_TYPE_ARP 0x0806 /* ARP */
+#define ETHER_TYPE_8021Q 0x8100 /* 802.1Q */
+#define ETHER_TYPE_BRCM 0x886c /* Broadcom Corp. */
+#define ETHER_TYPE_802_1X 0x888e /* 802.1x */
+#ifdef BCMWPA2
+#define ETHER_TYPE_802_1X_PREAUTH 0x88c7 /* 802.1x preauthentication */
+#endif
+
+/* Broadcom subtype follows ethertype; First 2 bytes are reserved; Next 2 are subtype; */
+#define ETHER_BRCM_SUBTYPE_LEN 4 /* Broadcom 4 byte subtype */
+#define ETHER_BRCM_CRAM 0x1 /* Broadcom subtype cram protocol */
+
+/* ether header */
+#define ETHER_DEST_OFFSET 0 /* dest address offset */
+#define ETHER_SRC_OFFSET 6 /* src address offset */
+#define ETHER_TYPE_OFFSET 12 /* ether type offset */
+
+/*
+ * A macro to validate a length with
+ */
+#define ETHER_IS_VALID_LEN(foo) \
+ ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN)
+
+
+#ifndef __INCif_etherh /* Quick and ugly hack for VxWorks */
+/*
+ * Structure of a 10Mb/s Ethernet header.
+ */
+struct ether_header {
+ uint8 ether_dhost[ETHER_ADDR_LEN];
+ uint8 ether_shost[ETHER_ADDR_LEN];
+ uint16 ether_type;
+} PACKED;
+
+/*
+ * Structure of a 48-bit Ethernet address.
+ */
+struct ether_addr {
+ uint8 octet[ETHER_ADDR_LEN];
+} PACKED;
+#endif /* !__INCif_etherh Quick and ugly hack for VxWorks */
+
+/*
+ * Takes a pointer, sets locally admininistered
+ * address bit in the 48-bit Ethernet address.
+ */
+#define ETHER_SET_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] | 2))
+
+/*
+ * Takes a pointer, returns true if a 48-bit multicast address
+ * (including broadcast, since it is all ones)
+ */
+#define ETHER_ISMULTI(ea) (((uint8 *)(ea))[0] & 1)
+
+
+/* compare two ethernet addresses - assumes the pointers can be referenced as shorts */
+#define ether_cmp(a, b) (!(((short*)a)[0] == ((short*)b)[0]) | \
+ !(((short*)a)[1] == ((short*)b)[1]) | \
+ !(((short*)a)[2] == ((short*)b)[2]))
+
+/* copy an ethernet address - assumes the pointers can be referenced as shorts */
+#define ether_copy(s, d) { \
+ ((short*)d)[0] = ((short*)s)[0]; \
+ ((short*)d)[1] = ((short*)s)[1]; \
+ ((short*)d)[2] = ((short*)s)[2]; }
+
+/*
+ * Takes a pointer, returns true if a 48-bit broadcast (all ones)
+ */
+#define ETHER_ISBCAST(ea) ((((uint8 *)(ea))[0] & \
+ ((uint8 *)(ea))[1] & \
+ ((uint8 *)(ea))[2] & \
+ ((uint8 *)(ea))[3] & \
+ ((uint8 *)(ea))[4] & \
+ ((uint8 *)(ea))[5]) == 0xff)
+
+static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}};
+
+/*
+ * Takes a pointer, returns true if a 48-bit null address (all zeros)
+ */
+#define ETHER_ISNULLADDR(ea) ((((uint8 *)(ea))[0] | \
+ ((uint8 *)(ea))[1] | \
+ ((uint8 *)(ea))[2] | \
+ ((uint8 *)(ea))[3] | \
+ ((uint8 *)(ea))[4] | \
+ ((uint8 *)(ea))[5]) == 0)
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#endif /* _NET_ETHERNET_H_ */
diff --git a/package/broadcom-wl/src/wlc/include/proto/wpa.h b/package/broadcom-wl/src/wlc/include/proto/wpa.h
new file mode 100644
index 0000000000..dd35dbef02
--- /dev/null
+++ b/package/broadcom-wl/src/wlc/include/proto/wpa.h
@@ -0,0 +1,148 @@
+/*
+ * Fundamental types and constants relating to WPA
+ *
+ * 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.
+ *
+ * $Id: wpa.h,v 1.1.1.4 2006/02/27 03:43:16 honor Exp $
+ */
+
+#ifndef _proto_wpa_h_
+#define _proto_wpa_h_
+
+#include <typedefs.h>
+#include <proto/ethernet.h>
+
+/* enable structure packing */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#pragma pack(1)
+#define PACKED
+#endif
+
+/* Reason Codes */
+
+/* 10 and 11 are from TGh. */
+#define DOT11_RC_BAD_PC 10 /* Unacceptable power capability element */
+#define DOT11_RC_BAD_CHANNELS 11 /* Unacceptable supported channels element */
+/* 12 is unused */
+/* 13 through 23 taken from P802.11i/D3.0, November 2002 */
+#define DOT11_RC_INVALID_WPA_IE 13 /* Invalid info. element */
+#define DOT11_RC_MIC_FAILURE 14 /* Michael failure */
+#define DOT11_RC_4WH_TIMEOUT 15 /* 4-way handshake timeout */
+#define DOT11_RC_GTK_UPDATE_TIMEOUT 16 /* Group key update timeout */
+#define DOT11_RC_WPA_IE_MISMATCH 17 /* WPA IE in 4-way handshake differs from
+ * (re-)assoc. request/probe response
+ */
+#define DOT11_RC_INVALID_MC_CIPHER 18 /* Invalid multicast cipher */
+#define DOT11_RC_INVALID_UC_CIPHER 19 /* Invalid unicast cipher */
+#define DOT11_RC_INVALID_AKMP 20 /* Invalid authenticated key management protocol */
+#define DOT11_RC_BAD_WPA_VERSION 21 /* Unsupported WPA version */
+#define DOT11_RC_INVALID_WPA_CAP 22 /* Invalid WPA IE capabilities */
+#define DOT11_RC_8021X_AUTH_FAIL 23 /* 802.1X authentication failure */
+
+#define WPA2_PMKID_LEN 16
+
+/* WPA IE fixed portion */
+typedef struct
+{
+ uint8 tag; /* TAG */
+ uint8 length; /* TAG length */
+ uint8 oui[3]; /* IE OUI */
+ uint8 oui_type; /* OUI type */
+ struct {
+ uint8 low;
+ uint8 high;
+ } PACKED version; /* IE version */
+} PACKED wpa_ie_fixed_t;
+#define WPA_IE_OUITYPE_LEN 4
+#define WPA_IE_FIXED_LEN 8
+#define WPA_IE_TAG_FIXED_LEN 6
+
+#ifdef BCMWPA2
+typedef struct {
+ uint8 tag; /* TAG */
+ uint8 length; /* TAG length */
+ struct {
+ uint8 low;
+ uint8 high;
+ } PACKED version; /* IE version */
+} PACKED wpa_rsn_ie_fixed_t;
+#define WPA_RSN_IE_FIXED_LEN 4
+#define WPA_RSN_IE_TAG_FIXED_LEN 2
+typedef uint8 wpa_pmkid_t[WPA2_PMKID_LEN];
+#endif
+
+/* WPA suite/multicast suite */
+typedef struct
+{
+ uint8 oui[3];
+ uint8 type;
+} PACKED wpa_suite_t, wpa_suite_mcast_t;
+#define WPA_SUITE_LEN 4
+
+/* WPA unicast suite list/key management suite list */
+typedef struct
+{
+ struct {
+ uint8 low;
+ uint8 high;
+ } PACKED count;
+ wpa_suite_t list[1];
+} PACKED wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t;
+#define WPA_IE_SUITE_COUNT_LEN 2
+#ifdef BCMWPA2
+typedef struct
+{
+ struct {
+ uint8 low;
+ uint8 high;
+ } PACKED count;
+ wpa_pmkid_t list[1];
+} PACKED wpa_pmkid_list_t;
+#endif
+
+/* WPA cipher suites */
+#define WPA_CIPHER_NONE 0 /* None */
+#define WPA_CIPHER_WEP_40 1 /* WEP (40-bit) */
+#define WPA_CIPHER_TKIP 2 /* TKIP: default for WPA */
+#define WPA_CIPHER_AES_OCB 3 /* AES (OCB) */
+#define WPA_CIPHER_AES_CCM 4 /* AES (CCM) */
+#define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */
+
+#define IS_WPA_CIPHER(cipher) ((cipher) == WPA_CIPHER_NONE || \
+ (cipher) == WPA_CIPHER_WEP_40 || \
+ (cipher) == WPA_CIPHER_WEP_104 || \
+ (cipher) == WPA_CIPHER_TKIP || \
+ (cipher) == WPA_CIPHER_AES_OCB || \
+ (cipher) == WPA_CIPHER_AES_CCM)
+
+/* WPA TKIP countermeasures parameters */
+#define WPA_TKIP_CM_DETECT 60 /* multiple MIC failure window (seconds) */
+#define WPA_TKIP_CM_BLOCK 60 /* countermeasures active window (seconds) */
+
+/* WPA capabilities defined in 802.11i */
+#define WPA_CAP_4_REPLAY_CNTRS 2
+#define WPA_CAP_16_REPLAY_CNTRS 3
+#define WPA_CAP_REPLAY_CNTR_SHIFT 2
+#define WPA_CAP_REPLAY_CNTR_MASK 0x000c
+
+/* WPA Specific defines */
+#define WPA_CAP_LEN 2 /* Length of RSN capabilities in RSN IE (2 octets) */
+
+#ifdef BCMWPA2
+#define WPA_CAP_WPA2_PREAUTH 1
+#endif /* BCMWPA2 */
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#endif /* _proto_wpa_h_ */
diff --git a/package/broadcom-wl/src/wlc/include/typedefs.h b/package/broadcom-wl/src/wlc/include/typedefs.h
new file mode 100644
index 0000000000..6c498bbcb2
--- /dev/null
+++ b/package/broadcom-wl/src/wlc/include/typedefs.h
@@ -0,0 +1,230 @@
+/*
+ * 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.
+ * $Id: typedefs.h,v 1.1.1.12 2006/04/08 06:13:40 honor Exp $
+ */
+
+#ifndef _TYPEDEFS_H_
+#define _TYPEDEFS_H_
+
+/*
+ * Inferred Typedefs
+ *
+ */
+
+/* Infer the compile environment based on preprocessor symbols and pramas.
+ * Override type definitions as needed, and include configuration dependent
+ * header files to define types.
+ */
+
+#ifdef __cplusplus
+
+#define TYPEDEF_BOOL
+#ifndef FALSE
+#define FALSE false
+#endif
+#ifndef TRUE
+#define TRUE true
+#endif
+
+#endif /* __cplusplus */
+
+#if defined(_NEED_SIZE_T_)
+typedef long unsigned int size_t;
+#endif
+
+#define TYPEDEF_UINT
+#define TYPEDEF_USHORT
+#define TYPEDEF_ULONG
+
+
+/* Do not support the (u)int64 types with strict ansi for GNU C */
+#if defined(__GNUC__) && defined(__STRICT_ANSI__)
+#define TYPEDEF_INT64
+#define TYPEDEF_UINT64
+#endif
+
+/* pick up ushort & uint from standard types.h */
+#if defined(linux) && defined(__KERNEL__)
+#include <linux/types.h> /* sys/types.h and linux/types.h are oil and water */
+#else
+#include <sys/types.h>
+#endif
+
+/* use the default typedefs in the next section of this file */
+#define USE_TYPEDEF_DEFAULTS
+
+/*
+ * Default Typedefs
+ *
+ */
+
+#ifdef USE_TYPEDEF_DEFAULTS
+#undef USE_TYPEDEF_DEFAULTS
+
+#ifndef TYPEDEF_BOOL
+typedef /* @abstract@ */ unsigned char bool;
+#endif
+
+/* define uchar, ushort, uint, ulong */
+
+#ifndef TYPEDEF_UCHAR
+typedef unsigned char uchar;
+#endif
+
+#ifndef TYPEDEF_USHORT
+typedef unsigned short ushort;
+#endif
+
+#ifndef TYPEDEF_UINT
+typedef unsigned int uint;
+#endif
+
+#ifndef TYPEDEF_ULONG
+typedef unsigned long ulong;
+#endif
+
+/* define [u]int8/16/32/64, uintptr */
+
+#ifndef TYPEDEF_UINT8
+typedef unsigned char uint8;
+#endif
+
+#ifndef TYPEDEF_UINT16
+typedef unsigned short uint16;
+#endif
+
+#ifndef TYPEDEF_UINT32
+typedef unsigned int uint32;
+#endif
+
+#ifndef TYPEDEF_UINT64
+typedef unsigned long long uint64;
+#endif
+
+#ifndef TYPEDEF_UINTPTR
+typedef unsigned int uintptr;
+#endif
+
+#ifndef TYPEDEF_INT8
+typedef signed char int8;
+#endif
+
+#ifndef TYPEDEF_INT16
+typedef signed short int16;
+#endif
+
+#ifndef TYPEDEF_INT32
+typedef signed int int32;
+#endif
+
+#ifndef TYPEDEF_INT64
+typedef signed long long int64;
+#endif
+
+/* define float32/64, float_t */
+
+#ifndef TYPEDEF_FLOAT32
+typedef float float32;
+#endif
+
+#ifndef TYPEDEF_FLOAT64
+typedef double float64;
+#endif
+
+/*
+ * abstracted floating point type allows for compile time selection of
+ * single or double precision arithmetic. Compiling with -DFLOAT32
+ * selects single precision; the default is double precision.
+ */
+
+#ifndef TYPEDEF_FLOAT_T
+
+#if defined(FLOAT32)
+typedef float32 float_t;
+#else /* default to double precision floating point */
+typedef float64 float_t;
+#endif
+
+#endif /* TYPEDEF_FLOAT_T */
+
+/* define macro values */
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1 /* TRUE */
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef OFF
+#define OFF 0
+#endif
+
+#ifndef ON
+#define ON 1 /* ON = 1 */
+#endif
+
+#define AUTO (-1) /* Auto = -1 */
+
+/* define PTRSZ, INLINE */
+
+#ifndef PTRSZ
+#define PTRSZ sizeof(char*)
+#endif
+
+#ifndef INLINE
+
+#ifdef _MSC_VER
+
+#define INLINE __inline
+
+#elif __GNUC__
+
+#define INLINE __inline__
+
+#else
+
+#define INLINE
+
+#endif /* _MSC_VER */
+
+#endif /* INLINE */
+
+#undef TYPEDEF_BOOL
+#undef TYPEDEF_UCHAR
+#undef TYPEDEF_USHORT
+#undef TYPEDEF_UINT
+#undef TYPEDEF_ULONG
+#undef TYPEDEF_UINT8
+#undef TYPEDEF_UINT16
+#undef TYPEDEF_UINT32
+#undef TYPEDEF_UINT64
+#undef TYPEDEF_UINTPTR
+#undef TYPEDEF_INT8
+#undef TYPEDEF_INT16
+#undef TYPEDEF_INT32
+#undef TYPEDEF_INT64
+#undef TYPEDEF_FLOAT32
+#undef TYPEDEF_FLOAT64
+#undef TYPEDEF_FLOAT_T
+
+#endif /* USE_TYPEDEF_DEFAULTS */
+
+/*
+ * Including the bcmdefs.h here, to make sure everyone including typedefs.h
+ * gets this automatically
+*/
+#include <bcmdefs.h>
+
+#endif /* _TYPEDEFS_H_ */
diff --git a/package/broadcom-wl/src/wlc/include/wlioctl.h b/package/broadcom-wl/src/wlc/include/wlioctl.h
new file mode 100644
index 0000000000..0558415d33
--- /dev/null
+++ b/package/broadcom-wl/src/wlc/include/wlioctl.h
@@ -0,0 +1,1384 @@
+/*
+ * 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.
+ *
+ * $Id: wlioctl.h,v 1.1.1.22 2006/04/15 01:29:08 michael Exp $
+ */
+
+#ifndef _wlioctl_h_
+#define _wlioctl_h_
+
+#include <typedefs.h>
+#include <proto/ethernet.h>
+#include <proto/bcmeth.h>
+#include <proto/bcmevent.h>
+#include <proto/802.11.h>
+
+#ifdef __NetBSD__
+/* NetBSD 2.0 does not have SIOCDEVPRIVATE. This is NetBSD 2.0 specific */
+#define SIOCDEVPRIVATE _IOWR('i', 139, struct ifreq)
+#endif
+
+/* require default structure packing */
+#if !defined(__GNUC__)
+#pragma pack(push, 8)
+#endif
+
+/* A chanspec holds the channel number, band, bandwidth and control sideband */
+typedef uint16 chanspec_t;
+#define WL_CHANSPEC_CHAN_MASK 0x00ff
+
+#define WL_CHANSPEC_CTL_SB_MASK 0x0300
+#define WL_CHANSPEC_CTL_SB_SHIFT 8
+#define WL_CHANSPEC_CTL_SB_LOWER 0x0100
+#define WL_CHANSPEC_CTL_SB_UPPER 0x0200
+#define WL_CHANSPEC_CTL_SB_NONE 0x0300
+
+#define WL_CHANSPEC_BW_MASK 0x0C00
+#define WL_CHANSPEC_BW_SHIFT 10
+#define WL_CHANSPEC_BW_10 0x0400
+#define WL_CHANSPEC_BW_20 0x0800
+#define WL_CHANSPEC_BW_40 0x0C00
+
+#define WL_CHANSPEC_BAND_MASK 0xf000
+#define WL_CHANSPEC_BAND_SHIFT 12
+#define WL_CHANSPEC_BAND_5G 0x1000
+#define WL_CHANSPEC_BAND_2G 0x2000
+#define INVCHANSPEC 255
+
+/* Legacy structure to help keep backward compatible wl tool and tray app */
+
+#define LEGACY_WL_BSS_INFO_VERSION 107 /* older version of wl_bss_info struct */
+
+typedef struct wl_bss_info_107 {
+ uint32 version; /* version field */
+ uint32 length; /* byte length of data in this record,
+ * starting at version and including IEs
+ */
+ struct ether_addr BSSID;
+ uint16 beacon_period; /* units are Kusec */
+ uint16 capability; /* Capability information */
+ uint8 SSID_len;
+ uint8 SSID[32];
+ struct {
+ uint count; /* # rates in this set */
+ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */
+ } rateset; /* supported rates */
+ uint8 channel; /* Channel no. */
+ uint16 atim_window; /* units are Kusec */
+ uint8 dtim_period; /* DTIM period */
+ int16 RSSI; /* receive signal strength (in dBm) */
+ int8 phy_noise; /* noise (in dBm) */
+ uint32 ie_length; /* byte length of Information Elements */
+ /* variable length Information Elements */
+} wl_bss_info_107_t;
+
+/*
+ * Per-bss information structure.
+ */
+
+#define WL_BSS_INFO_VERSION 108 /* current version of wl_bss_info struct */
+
+/* BSS info structure
+ * Applications MUST CHECK ie_offset field and length field to access IEs and
+ * next bss_info structure in a vector (in wl_scan_results_t)
+ */
+typedef struct wl_bss_info {
+ uint32 version; /* version field */
+ uint32 length; /* byte length of data in this record,
+ * starting at version and including IEs
+ */
+ struct ether_addr BSSID;
+ uint16 beacon_period; /* units are Kusec */
+ uint16 capability; /* Capability information */
+ uint8 SSID_len;
+ uint8 SSID[32];
+ struct {
+ uint count; /* # rates in this set */
+ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */
+ } rateset; /* supported rates */
+ chanspec_t chanspec; /* chanspec for bss */
+ uint16 atim_window; /* units are Kusec */
+ uint8 dtim_period; /* DTIM period */
+ int16 RSSI; /* receive signal strength (in dBm) */
+ int8 phy_noise; /* noise (in dBm) */
+
+ bool n_cap; /* BSS is 802.11N Capable */
+ uint32 nbss_cap; /* 802.11N BSS Capabilities (based on EWC_CAP_*) */
+ uint8 ctl_ch; /* 802.11N BSS control channel number */
+ uint32 reserved[2]; /* Reserved for expansion of BSS properties */
+ uint8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */
+
+ uint16 ie_offset; /* offset at which IEs start, from beginning */
+ uint32 ie_length; /* byte length of Information Elements */
+ /* Add new fields here */
+ /* variable length Information Elements */
+} wl_bss_info_t;
+
+typedef struct wlc_ssid {
+ uint32 SSID_len;
+ uchar SSID[32];
+} wlc_ssid_t;
+
+typedef struct wl_scan_params {
+ wlc_ssid_t ssid; /* default: {0, ""} */
+ struct ether_addr bssid; /* default: bcast */
+ int8 bss_type; /* default: any,
+ * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
+ */
+ int8 scan_type; /* -1 use default, DOT11_SCANTYPE_ACTIVE/PASSIVE */
+ int32 nprobes; /* -1 use default, number of probes per channel */
+ int32 active_time; /* -1 use default, dwell time per channel for
+ * active scanning
+ */
+ int32 passive_time; /* -1 use default, dwell time per channel
+ * for passive scanning
+ */
+ int32 home_time; /* -1 use default, dwell time for the home channel
+ * between channel scans
+ */
+ int32 channel_num; /* 0 use default (all available channels), count of
+ * channels in channel_list
+ */
+ uint16 channel_list[1]; /* list of chanspecs */
+} wl_scan_params_t;
+/* size of wl_scan_params not including variable length array */
+#define WL_SCAN_PARAMS_FIXED_SIZE 64
+
+typedef struct wl_scan_results {
+ uint32 buflen;
+ uint32 version;
+ uint32 count;
+ wl_bss_info_t bss_info[1];
+} wl_scan_results_t;
+/* size of wl_scan_results not including variable length array */
+#define WL_SCAN_RESULTS_FIXED_SIZE 12
+
+
+#define WL_NUMRATES 255 /* max # of rates in a rateset */
+typedef struct wl_rateset {
+ uint32 count; /* # rates in this set */
+ uint8 rates[WL_NUMRATES]; /* rates in 500kbps units w/hi bit set if basic */
+} wl_rateset_t;
+
+/* uint32 list */
+typedef struct wl_uint32_list {
+ /* in - # of elements, out - # of entries */
+ uint32 count;
+ /* variable length uint32 list */
+ uint32 element[1];
+} wl_uint32_list_t;
+
+#define WLC_CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NULL */
+
+/* defines used by the nrate iovar */
+#define NRATE_MCS_INUSE 0x00000080 /* MSC in use,indicates b0-6 holds an mcs */
+#define NRATE_RATE_MASK 0x0000007f /* rate/mcs value */
+#define NRATE_STF_MASK 0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */
+#define NRATE_STF_SHIFT 8 /* stf mode shift */
+
+#define ANTENNA_NUM_1 1 /* total number of antennas to be used */
+#define ANTENNA_NUM_2 2
+#define ANTENNA_NUM_3 3
+#define ANTENNA_NUM_4 4
+
+typedef struct wl_channels_in_country {
+ uint32 buflen;
+ uint32 band;
+ char country_abbrev[WLC_CNTRY_BUF_SZ];
+ uint32 count;
+ uint32 channel[1];
+} wl_channels_in_country_t;
+
+typedef struct wl_country_list {
+ uint32 buflen;
+ uint32 band_set;
+ uint32 band;
+ uint32 count;
+ char country_abbrev[1];
+} wl_country_list_t;
+
+#define WL_RM_TYPE_BASIC 1
+#define WL_RM_TYPE_CCA 2
+#define WL_RM_TYPE_RPI 3
+
+#define WL_RM_FLAG_PARALLEL (1<<0)
+
+#define WL_RM_FLAG_LATE (1<<1)
+#define WL_RM_FLAG_INCAPABLE (1<<2)
+#define WL_RM_FLAG_REFUSED (1<<3)
+
+typedef struct wl_rm_req_elt {
+ int8 type;
+ int8 flags;
+ chanspec_t chanspec;
+ uint32 token; /* token for this measurement */
+ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */
+ uint32 tsf_l; /* TSF low 32-bits */
+ uint32 dur; /* TUs */
+} wl_rm_req_elt_t;
+
+typedef struct wl_rm_req {
+ uint32 token; /* overall measurement set token */
+ uint32 count; /* number of measurement requests */
+ wl_rm_req_elt_t req[1]; /* variable length block of requests */
+} wl_rm_req_t;
+#define WL_RM_REQ_FIXED_LEN 8
+
+typedef struct wl_rm_rep_elt {
+ int8 type;
+ int8 flags;
+ chanspec_t chanspec;
+ uint32 token; /* token for this measurement */
+ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */
+ uint32 tsf_l; /* TSF low 32-bits */
+ uint32 dur; /* TUs */
+ uint32 len; /* byte length of data block */
+ uint8 data[1]; /* variable length data block */
+} wl_rm_rep_elt_t;
+#define WL_RM_REP_ELT_FIXED_LEN 24 /* length excluding data block */
+
+#define WL_RPI_REP_BIN_NUM 8
+typedef struct wl_rm_rpi_rep {
+ uint8 rpi[WL_RPI_REP_BIN_NUM];
+ int8 rpi_max[WL_RPI_REP_BIN_NUM];
+} wl_rm_rpi_rep_t;
+
+typedef struct wl_rm_rep {
+ uint32 token; /* overall measurement set token */
+ uint32 len; /* length of measurement report block */
+ wl_rm_rep_elt_t rep[1]; /* variable length block of reports */
+} wl_rm_rep_t;
+#define WL_RM_REP_FIXED_LEN 8
+
+
+#if defined(BCMSUP_PSK)
+typedef enum sup_auth_status {
+ WLC_SUP_DISCONNECTED = 0,
+ WLC_SUP_CONNECTING,
+ WLC_SUP_IDREQUIRED,
+ WLC_SUP_AUTHENTICATING,
+ WLC_SUP_AUTHENTICATED,
+ WLC_SUP_KEYXCHANGE,
+ WLC_SUP_KEYED,
+ WLC_SUP_TIMEOUT
+} sup_auth_status_t;
+#endif /* BCMCCX | BCMSUP_PSK */
+
+/* Enumerate crypto algorithms */
+#define CRYPTO_ALGO_OFF 0
+#define CRYPTO_ALGO_WEP1 1
+#define CRYPTO_ALGO_TKIP 2
+#define CRYPTO_ALGO_WEP128 3
+#define CRYPTO_ALGO_AES_CCM 4
+#define CRYPTO_ALGO_AES_OCB_MSDU 5
+#define CRYPTO_ALGO_AES_OCB_MPDU 6
+#define CRYPTO_ALGO_NALG 7
+
+#define WSEC_GEN_MIC_ERROR 0x0001
+#define WSEC_GEN_REPLAY 0x0002
+
+#define WL_SOFT_KEY (1 << 0) /* Indicates this key is using soft encrypt */
+#define WL_PRIMARY_KEY (1 << 1) /* Indicates this key is the primary (ie tx) key */
+#define WL_KF_RES_4 (1 << 4) /* Reserved for backward compat */
+#define WL_KF_RES_5 (1 << 5) /* Reserved for backward compat */
+
+typedef struct wl_wsec_key {
+ uint32 index; /* key index */
+ uint32 len; /* key length */
+ uint8 data[DOT11_MAX_KEY_SIZE]; /* key data */
+ uint32 pad_1[18];
+ uint32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+ uint32 flags; /* misc flags */
+ uint32 pad_2[2];
+ int pad_3;
+ int iv_initialized; /* has IV been initialized already? */
+ int pad_4;
+ /* Rx IV */
+ struct {
+ uint32 hi; /* upper 32 bits of IV */
+ uint16 lo; /* lower 16 bits of IV */
+ } rxiv;
+ uint32 pad_5[2];
+ struct ether_addr ea; /* per station */
+} wl_wsec_key_t;
+
+#define WSEC_MIN_PSK_LEN 8
+#define WSEC_MAX_PSK_LEN 64
+
+/* Flag for key material needing passhash'ing */
+#define WSEC_PASSPHRASE (1<<0)
+
+/* receptacle for WLC_SET_WSEC_PMK parameter */
+typedef struct {
+ ushort key_len; /* octets in key material */
+ ushort flags; /* key handling qualification */
+ uint8 key[WSEC_MAX_PSK_LEN]; /* PMK material */
+} wsec_pmk_t;
+
+/* wireless security bitvec */
+#define WEP_ENABLED 0x0001
+#define TKIP_ENABLED 0x0002
+#define AES_ENABLED 0x0004
+#define WSEC_SWFLAG 0x0008
+#define SES_OW_ENABLED 0x0040 /* to go into transition mode without setting wep */
+#define FIPS_ENABLED 0x0080
+
+/* WPA authentication mode bitvec */
+#define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */
+#define WPA_AUTH_NONE 0x0001 /* none (IBSS) */
+#define WPA_AUTH_UNSPECIFIED 0x0002 /* over 802.1x */
+#define WPA_AUTH_PSK 0x0004 /* Pre-shared key */
+/* #define WPA_AUTH_8021X 0x0020 */ /* 802.1x, reserved */
+#ifdef BCMWPA2
+#define WPA2_AUTH_UNSPECIFIED 0x0040 /* over 802.1x */
+#define WPA2_AUTH_PSK 0x0080 /* Pre-shared key */
+#endif /* BCMWPA2 */
+
+#ifdef BCMWPA2
+/* pmkid */
+#define MAXPMKID 16
+
+typedef struct _pmkid
+{
+ struct ether_addr BSSID;
+ uint8 PMKID[WPA2_PMKID_LEN];
+} pmkid_t;
+
+typedef struct _pmkid_list
+{
+ uint32 npmkid;
+ pmkid_t pmkid[1];
+} pmkid_list_t;
+
+typedef struct _pmkid_cand {
+ struct ether_addr BSSID;
+ uint8 preauth;
+} pmkid_cand_t;
+
+typedef struct _pmkid_cand_list {
+ uint32 npmkid_cand;
+ pmkid_cand_t pmkid_cand[1];
+} pmkid_cand_list_t;
+#endif /* BCMWPA2 */
+
+typedef struct wl_led_info {
+ uint32 index; /* led index */
+ uint32 behavior;
+ bool activehi;
+} wl_led_info_t;
+
+typedef struct wlc_assoc_info {
+ uint32 req_len;
+ uint32 resp_len;
+ uint32 flags;
+ struct dot11_assoc_req req;
+ struct ether_addr reassoc_bssid; /* used in reassoc's */
+ struct dot11_assoc_resp resp;
+} wl_assoc_info_t;
+/* flags */
+#define WLC_ASSOC_REQ_IS_REASSOC 0x01 /* assoc req was actually a reassoc */
+/* srom read/write struct passed through ioctl */
+typedef struct {
+ uint byteoff; /* byte offset */
+ uint nbytes; /* number of bytes */
+ uint16 buf[1];
+} srom_rw_t;
+
+/* R_REG and W_REG struct passed through ioctl */
+typedef struct {
+ uint32 byteoff; /* byte offset of the field in d11regs_t */
+ uint32 val; /* read/write value of the field */
+ uint32 size; /* sizeof the field */
+ uint band; /* band (optional) */
+} rw_reg_t;
+
+/* Structure used by GET/SET_ATTEN ioctls - it controls power in b/g-band */
+/* PCL - Power Control Loop */
+/* current gain setting is replaced by user input */
+#define WL_ATTEN_APP_INPUT_PCL_OFF 0 /* turn off PCL, apply supplied input */
+#define WL_ATTEN_PCL_ON 1 /* turn on PCL */
+/* current gain setting is maintained */
+#define WL_ATTEN_PCL_OFF 2 /* turn off PCL. */
+typedef struct {
+ uint16 auto_ctrl; /* WL_ATTEN_XX */
+ uint16 bb; /* Baseband attenuation */
+ uint16 radio; /* Radio attenuation */
+ uint16 txctl1; /* Radio TX_CTL1 value */
+} atten_t;
+
+/* defines used by poweridx iovar - it controls power in a-band */
+/* current gain setting is maintained */
+#define WL_PWRIDX_PCL_OFF -2 /* turn off PCL. */
+#define WL_PWRIDX_PCL_ON -1 /* turn on PCL */
+#define WL_PWRIDX_LOWER_LIMIT -2 /* lower limit */
+#define WL_PWRIDX_UPPER_LIMIT 63 /* upper limit */
+/* value >= 0 causes
+ * - input to be set to that value
+ * - PCL to be off
+ */
+
+/* Used to get specific STA parameters */
+typedef struct {
+ uint32 val;
+ struct ether_addr ea;
+} scb_val_t;
+
+
+/* Event data type */
+typedef struct wlc_event {
+ wl_event_msg_t event; /* encapsulated event */
+ struct ether_addr *addr; /* used to keep a trace of the potential present of
+ * an address in wlc_event_msg_t
+ */
+ void *data; /* used to hang additional data on an event */
+ struct wlc_event *next; /* enables ordered list of pending events */
+} wlc_event_t;
+
+#define BCM_MAC_STATUS_INDICATION (0x40010200L)
+
+/* Please update the following when modifying this structure:
+ * StaInfo Twiki page flags section - description of the sta_info_t struct
+ * src/wl/exe/wlu.c - print of sta_info_t
+ * Pay attention to version if structure changes.
+ */
+typedef struct {
+ uint16 ver; /* version of this struct */
+ uint16 len; /* length in bytes of this structure */
+ uint16 cap; /* sta's advertised capabilities */
+ uint32 flags; /* flags defined below */
+ uint32 idle; /* time since data pkt rx'd from sta */
+ struct ether_addr ea; /* Station address */
+ wl_rateset_t rateset; /* rateset in use */
+ uint32 in; /* seconds elapsed since associated */
+ uint32 listen_interval_inms; /* Min Listen interval in ms for this STA */
+} sta_info_t;
+
+#define WL_STA_VER 2
+
+/* Flags for sta_info_t indicating properties of STA */
+#define WL_STA_BRCM 0x1 /* Running a Broadcom driver */
+#define WL_STA_WME 0x2 /* WMM association */
+#define WL_STA_ABCAP 0x4 /* Afterburner-capable */
+#define WL_STA_AUTHE 0x8 /* Authenticated */
+#define WL_STA_ASSOC 0x10 /* Associated */
+#define WL_STA_AUTHO 0x20 /* Authorized */
+#define WL_STA_WDS 0x40 /* Wireless Distribution System */
+#define WL_STA_WDS_LINKUP 0x80 /* WDS traffic/probes flowing properly */
+#define WL_STA_PS 0x100 /* STA is in power save mode from AP's viewpoint */
+#define WL_STA_APSD_BE 0x200 /* APSD delv/trigger for AC_BE is default enabled */
+#define WL_STA_APSD_BK 0x400 /* APSD delv/trigger for AC_BK is default enabled */
+#define WL_STA_APSD_VI 0x800 /* APSD delv/trigger for AC_VI is default enabled */
+#define WL_STA_APSD_VO 0x1000 /* APSD delv/trigger for AC_VO is default enabled */
+#define WL_STA_N_CAP 0x2000 /* STA 802.11n capable */
+
+#define WL_WDS_LINKUP WL_STA_WDS_LINKUP /* deprecated */
+
+/*
+ * Country locale determines which channels are available to us.
+ */
+typedef enum _wlc_locale {
+ WLC_WW = 0, /* Worldwide */
+ WLC_THA, /* Thailand */
+ WLC_ISR, /* Israel */
+ WLC_JDN, /* Jordan */
+ WLC_PRC, /* China */
+ WLC_JPN, /* Japan */
+ WLC_FCC, /* USA */
+ WLC_EUR, /* Europe */
+ WLC_USL, /* US Low Band only */
+ WLC_JPH, /* Japan High Band only */
+ WLC_ALL, /* All the channels in this band */
+ WLC_11D, /* Represents locale received by 11d beacons */
+ WLC_LAST_LOCALE,
+ WLC_UNDEFINED_LOCALE = 0xf
+} wlc_locale_t;
+
+/* channel encoding */
+typedef struct channel_info {
+ int hw_channel;
+ int target_channel;
+ int scan_channel;
+} channel_info_t;
+
+/* For ioctls that take a list of MAC addresses */
+struct maclist {
+ uint count; /* number of MAC addresses */
+ struct ether_addr ea[1]; /* variable length array of MAC addresses */
+};
+
+/* get pkt count struct passed through ioctl */
+typedef struct get_pktcnt {
+ uint rx_good_pkt;
+ uint rx_bad_pkt;
+ uint tx_good_pkt;
+ uint tx_bad_pkt;
+} get_pktcnt_t;
+
+/* Linux network driver ioctl encoding */
+typedef struct wl_ioctl {
+ uint cmd; /* common ioctl definition */
+ void *buf; /* pointer to user buffer */
+ uint len; /* length of user buffer */
+ bool set; /* get or set request (optional) */
+ uint used; /* bytes read or written (optional) */
+ uint needed; /* bytes needed (optional) */
+} wl_ioctl_t;
+
+/*
+ * Structure for passing hardware and software
+ * revision info up from the driver.
+ */
+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;
+
+#define WL_BRAND_MAX 10
+typedef struct wl_instance_info {
+ uint instance;
+ char brand[WL_BRAND_MAX];
+} wl_instance_info_t;
+
+/* check this magic number */
+#define WLC_IOCTL_MAGIC 0x14e46c77
+
+/* bump this number if you change the ioctl interface */
+#define WLC_IOCTL_VERSION 1
+
+#define WLC_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */
+#define WLC_IOCTL_SMLEN 256 /* "small" length ioctl buffer required */
+
+/* common ioctl definitions */
+#define WLC_GET_MAGIC 0
+#define WLC_GET_VERSION 1
+#define WLC_UP 2
+#define WLC_DOWN 3
+#define WLC_DUMP 6
+#define WLC_GET_MSGLEVEL 7
+#define WLC_SET_MSGLEVEL 8
+#define WLC_GET_PROMISC 9
+#define WLC_SET_PROMISC 10
+#define WLC_GET_RATE 12
+/* #define WLC_SET_RATE 13 */ /* no longer supported */
+#define WLC_GET_INSTANCE 14
+/* #define WLC_GET_FRAG 15 */ /* no longer supported */
+/* #define WLC_SET_FRAG 16 */ /* no longer supported */
+/* #define WLC_GET_RTS 17 */ /* no longer supported */
+/* #define WLC_SET_RTS 18 */ /* no longer supported */
+#define WLC_GET_INFRA 19
+#define WLC_SET_INFRA 20
+#define WLC_GET_AUTH 21
+#define WLC_SET_AUTH 22
+#define WLC_GET_BSSID 23
+#define WLC_SET_BSSID 24
+#define WLC_GET_SSID 25
+#define WLC_SET_SSID 26
+#define WLC_RESTART 27
+#define WLC_GET_CHANNEL 29
+#define WLC_SET_CHANNEL 30
+#define WLC_GET_SRL 31
+#define WLC_SET_SRL 32
+#define WLC_GET_LRL 33
+#define WLC_SET_LRL 34
+#define WLC_GET_PLCPHDR 35
+#define WLC_SET_PLCPHDR 36
+#define WLC_GET_RADIO 37
+#define WLC_SET_RADIO 38
+#define WLC_GET_PHYTYPE 39
+/* #define WLC_GET_WEP 42 */ /* no longer supported */
+/* #define WLC_SET_WEP 43 */ /* no longer supported */
+#define WLC_GET_KEY 44
+#define WLC_SET_KEY 45
+#define WLC_GET_REGULATORY 46
+#define WLC_SET_REGULATORY 47
+#define WLC_GET_PASSIVE 48
+#define WLC_SET_PASSIVE 49
+#define WLC_SCAN 50
+#define WLC_SCAN_RESULTS 51
+#define WLC_DISASSOC 52
+#define WLC_REASSOC 53
+#define WLC_GET_ROAM_TRIGGER 54
+#define WLC_SET_ROAM_TRIGGER 55
+#define WLC_GET_TXANT 61
+#define WLC_SET_TXANT 62
+#define WLC_GET_ANTDIV 63
+#define WLC_SET_ANTDIV 64
+/* #define WLC_GET_TXPWR 65 */ /* no longer supported */
+/* #define WLC_SET_TXPWR 66 */ /* no longer supported */
+#define WLC_GET_CLOSED 67
+#define WLC_SET_CLOSED 68
+#define WLC_GET_MACLIST 69
+#define WLC_SET_MACLIST 70
+#define WLC_GET_RATESET 71
+#define WLC_SET_RATESET 72
+#define WLC_GET_LOCALE 73
+#define WLC_LONGTRAIN 74
+#define WLC_GET_BCNPRD 75
+#define WLC_SET_BCNPRD 76
+#define WLC_GET_DTIMPRD 77
+#define WLC_SET_DTIMPRD 78
+#define WLC_GET_SROM 79
+#define WLC_SET_SROM 80
+#define WLC_GET_WEP_RESTRICT 81
+#define WLC_SET_WEP_RESTRICT 82
+#define WLC_GET_COUNTRY 83
+#define WLC_SET_COUNTRY 84
+#define WLC_GET_PM 85
+#define WLC_SET_PM 86
+#define WLC_GET_WAKE 87
+#define WLC_SET_WAKE 88
+#define WLC_GET_D11CNTS 89
+#define WLC_GET_FORCELINK 90 /* ndis only */
+#define WLC_SET_FORCELINK 91 /* ndis only */
+#define WLC_FREQ_ACCURACY 92
+#define WLC_CARRIER_SUPPRESS 93
+#define WLC_GET_PHYREG 94
+#define WLC_SET_PHYREG 95
+#define WLC_GET_RADIOREG 96
+#define WLC_SET_RADIOREG 97
+#define WLC_GET_REVINFO 98
+#define WLC_GET_UCANTDIV 99
+#define WLC_SET_UCANTDIV 100
+#define WLC_R_REG 101
+#define WLC_W_REG 102
+#define WLC_DIAG_LOOPBACK 103
+#define WLC_RESET_D11CNTS 104
+#define WLC_GET_MACMODE 105
+#define WLC_SET_MACMODE 106
+#define WLC_GET_MONITOR 107
+#define WLC_SET_MONITOR 108
+#define WLC_GET_GMODE 109
+#define WLC_SET_GMODE 110
+#define WLC_GET_LEGACY_ERP 111
+#define WLC_SET_LEGACY_ERP 112
+#define WLC_GET_RX_ANT 113
+#define WLC_GET_CURR_RATESET 114 /* current rateset */
+#define WLC_GET_SCANSUPPRESS 115
+#define WLC_SET_SCANSUPPRESS 116
+#define WLC_GET_AP 117
+#define WLC_SET_AP 118
+#define WLC_GET_EAP_RESTRICT 119
+#define WLC_SET_EAP_RESTRICT 120
+#define WLC_SCB_AUTHORIZE 121
+#define WLC_SCB_DEAUTHORIZE 122
+#define WLC_GET_WDSLIST 123
+#define WLC_SET_WDSLIST 124
+#define WLC_GET_ATIM 125
+#define WLC_SET_ATIM 126
+#define WLC_GET_RSSI 127
+#define WLC_GET_PHYANTDIV 128
+#define WLC_SET_PHYANTDIV 129
+#define WLC_AP_RX_ONLY 130
+#define WLC_GET_TX_PATH_PWR 131
+#define WLC_SET_TX_PATH_PWR 132
+#define WLC_GET_WSEC 133
+#define WLC_SET_WSEC 134
+#define WLC_GET_PHY_NOISE 135
+#define WLC_GET_BSS_INFO 136
+#define WLC_GET_PKTCNTS 137
+#define WLC_GET_LAZYWDS 138
+#define WLC_SET_LAZYWDS 139
+#define WLC_GET_BANDLIST 140
+#define WLC_GET_BAND 141
+#define WLC_SET_BAND 142
+#define WLC_SCB_DEAUTHENTICATE 143
+#define WLC_GET_SHORTSLOT 144
+#define WLC_GET_SHORTSLOT_OVERRIDE 145
+#define WLC_SET_SHORTSLOT_OVERRIDE 146
+#define WLC_GET_SHORTSLOT_RESTRICT 147
+#define WLC_SET_SHORTSLOT_RESTRICT 148
+#define WLC_GET_GMODE_PROTECTION 149
+#define WLC_GET_GMODE_PROTECTION_OVERRIDE 150
+#define WLC_SET_GMODE_PROTECTION_OVERRIDE 151
+#define WLC_UPGRADE 152
+/* #define WLC_GET_MRATE 153 */ /* no longer supported */
+/* #define WLC_SET_MRATE 154 */ /* no longer supported */
+#define WLC_GET_ASSOCLIST 159
+#define WLC_GET_CLK 160
+#define WLC_SET_CLK 161
+#define WLC_GET_UP 162
+#define WLC_OUT 163
+#define WLC_GET_WPA_AUTH 164
+#define WLC_SET_WPA_AUTH 165
+#define WLC_GET_PROTECTION_CONTROL 178
+#define WLC_SET_PROTECTION_CONTROL 179
+#define WLC_GET_PHYLIST 180
+#define WLC_GET_KEY_SEQ 183
+/* #define WLC_GET_GMODE_PROTECTION_CTS 198 */ /* no longer supported */
+/* #define WLC_SET_GMODE_PROTECTION_CTS 199 */ /* no longer supported */
+#define WLC_GET_PIOMODE 203
+#define WLC_SET_PIOMODE 204
+#define WLC_SET_LED 209
+#define WLC_GET_LED 210
+#define WLC_GET_CHANNEL_SEL 215
+#define WLC_START_CHANNEL_SEL 216
+#define WLC_GET_VALID_CHANNELS 217
+#define WLC_GET_FAKEFRAG 218
+#define WLC_SET_FAKEFRAG 219
+#define WLC_GET_WET 230
+#define WLC_SET_WET 231
+#define WLC_GET_KEY_PRIMARY 235
+#define WLC_SET_KEY_PRIMARY 236
+#define WLC_GET_RADAR 242
+#define WLC_SET_RADAR 243
+#define WLC_SET_SPECT_MANAGMENT 244
+#define WLC_GET_SPECT_MANAGMENT 245
+#define WLC_WDS_GET_REMOTE_HWADDR 246 /* handled in wl_linux.c/wl_vx.c */
+#define WLC_SET_CS_SCAN_TIMER 248
+#define WLC_GET_CS_SCAN_TIMER 249
+#define WLC_SEND_PWR_CONSTRAINT 254
+#define WLC_CURRENT_PWR 256
+#define WLC_GET_CHANNELS_IN_COUNTRY 260
+#define WLC_GET_COUNTRY_LIST 261
+#define WLC_GET_VAR 262 /* get value of named variable */
+#define WLC_SET_VAR 263 /* set named variable to value */
+#define WLC_NVRAM_GET 264 /* deprecated */
+#define WLC_NVRAM_SET 265
+#define WLC_SET_WSEC_PMK 268
+#define WLC_GET_AUTH_MODE 269
+#define WLC_SET_AUTH_MODE 270
+#define WLC_NDCONFIG_ITEM 273 /* currently handled in wl_oid.c */
+#define WLC_NVOTPW 274
+#define WLC_OTPW 275
+#define WLC_SET_LOCALE 278
+#define WLC_LAST 279 /* do not change - use get_var/set_var */
+
+/*
+ * Minor kludge alert:
+ * Duplicate a few definitions that irelay requires from epiioctl.h here
+ * so caller doesn't have to include this file and epiioctl.h .
+ * If this grows any more, it would be time to move these irelay-specific
+ * definitions out of the epiioctl.h and into a separate driver common file.
+ */
+#ifndef EPICTRL_COOKIE
+#define EPICTRL_COOKIE 0xABADCEDE
+#endif
+
+/* vx wlc ioctl's offset */
+#define CMN_IOCTL_OFF 0x180
+
+/*
+ * custom OID support
+ *
+ * 0xFF - implementation specific OID
+ * 0xE4 - first byte of Broadcom PCI vendor ID
+ * 0x14 - second byte of Broadcom PCI vendor ID
+ * 0xXX - the custom OID number
+ */
+
+/* begin 0x1f values beyond the start of the ET driver range. */
+#define WL_OID_BASE 0xFFE41420
+
+/* NDIS overrides */
+#define OID_WL_GETINSTANCE (WL_OID_BASE + WLC_GET_INSTANCE)
+#define OID_WL_NDCONFIG_ITEM (WL_OID_BASE + WLC_NDCONFIG_ITEM)
+
+#define WL_DECRYPT_STATUS_SUCCESS 1
+#define WL_DECRYPT_STATUS_FAILURE 2
+#define WL_DECRYPT_STATUS_UNKNOWN 3
+
+/* allows user-mode app to poll the status of USB image upgrade */
+#define WLC_UPGRADE_SUCCESS 0
+#define WLC_UPGRADE_PENDING 1
+
+#ifdef CONFIG_USBRNDIS_RETAIL
+/* struct passed in for WLC_NDCONFIG_ITEM */
+typedef struct {
+ char *name;
+ void *param;
+} ndconfig_item_t;
+#endif
+
+/* Bit masks for radio disabled status - returned by WL_GET_RADIO */
+#define WL_RADIO_SW_DISABLE (1<<0)
+#define WL_RADIO_HW_DISABLE (1<<1)
+#define WL_RADIO_MPC_DISABLE (1<<2)
+#define WL_RADIO_COUNTRY_DISABLE (1<<3) /* some countries don't support any channel */
+
+/* Override bit for WLC_SET_TXPWR. if set, ignore other level limits */
+#define WL_TXPWR_OVERRIDE (1<<31)
+
+/* "diag" iovar argument and error code */
+#define WL_DIAG_INTERRUPT 1 /* d11 loopback interrupt test */
+#define WL_DIAG_MEMORY 3 /* d11 memory test */
+#define WL_DIAG_LED 4 /* LED test */
+#define WL_DIAG_REG 5 /* d11/phy register test */
+#define WL_DIAG_SROM 6 /* srom read/crc test */
+#define WL_DIAG_DMA 7 /* DMA test */
+
+#define WL_DIAGERR_SUCCESS 0
+#define WL_DIAGERR_FAIL_TO_RUN 1 /* unable to run requested diag */
+#define WL_DIAGERR_NOT_SUPPORTED 2 /* diag requested is not supported */
+#define WL_DIAGERR_INTERRUPT_FAIL 3 /* loopback interrupt test failed */
+#define WL_DIAGERR_LOOPBACK_FAIL 4 /* loopback data test failed */
+#define WL_DIAGERR_SROM_FAIL 5 /* srom read failed */
+#define WL_DIAGERR_SROM_BADCRC 6 /* srom crc failed */
+#define WL_DIAGERR_REG_FAIL 7 /* d11/phy register test failed */
+#define WL_DIAGERR_MEMORY_FAIL 8 /* d11 memory test failed */
+#define WL_DIAGERR_NOMEM 9 /* diag test failed due to no memory */
+#define WL_DIAGERR_DMA_FAIL 10 /* DMA test failed */
+
+/* band types */
+#define WLC_BAND_AUTO 0 /* auto-select */
+#define WLC_BAND_5G 1 /* 5 Ghz */
+#define WLC_BAND_2G 2 /* 2.4 Ghz */
+#define WLC_BAND_ALL 3 /* all bands */
+
+/* phy types (returned by WLC_GET_PHYTPE) */
+#define WLC_PHY_TYPE_A 0
+#define WLC_PHY_TYPE_B 1
+#define WLC_PHY_TYPE_G 2
+#define WLC_PHY_TYPE_N 4
+#define WLC_PHY_TYPE_NULL 0xf
+
+/* MAC list modes */
+#define WLC_MACMODE_DISABLED 0 /* MAC list disabled */
+#define WLC_MACMODE_DENY 1 /* Deny specified (i.e. allow unspecified) */
+#define WLC_MACMODE_ALLOW 2 /* Allow specified (i.e. deny unspecified) */
+
+/*
+ *
+ */
+#define GMODE_LEGACY_B 0
+#define GMODE_AUTO 1
+#define GMODE_ONLY 2
+#define GMODE_B_DEFERRED 3
+#define GMODE_PERFORMANCE 4
+#define GMODE_LRS 5
+#define GMODE_MAX 6
+
+/* values for PLCPHdr_override */
+#define WLC_PLCP_AUTO -1
+#define WLC_PLCP_SHORT 0
+#define WLC_PLCP_LONG 1
+
+/* values for g_protection_override and n_protection_override */
+#define WLC_PROTECTION_AUTO -1
+#define WLC_PROTECTION_OFF 0
+#define WLC_PROTECTION_ON 1
+
+/* values for g_protection_control and n_protection_control */
+#define WLC_PROTECTION_CTL_OFF 0
+#define WLC_PROTECTION_CTL_LOCAL 1
+#define WLC_PROTECTION_CTL_OVERLAP 2
+
+/* deprecated const names for g_protection_override */
+#define WLC_G_PROTECTION_AUTO WLC_PROTECTION_AUTO
+#define WLC_G_PROTECTION_OFF WLC_PROTECTION_OFF
+#define WLC_G_PROTECTION_ON WLC_PROTECTION_ON
+
+/* deprecated const names for g_protection_control */
+#define WLC_G_PROTECTION_CTL_OFF WLC_PROTECTION_CTL_OFF
+#define WLC_G_PROTECTION_CTL_LOCAL WLC_PROTECTION_CTL_LOCAL
+#define WLC_G_PROTECTION_CTL_OVERLAP WLC_PROTECTION_CTL_OVERLAP
+
+/* deprecated const names for get/set g_protection_control */
+#define WLC_GET_GMODE_PROTECTION_CONTROL WLC_GET_PROTECTION_CONTROL
+#define WLC_SET_GMODE_PROTECTION_CONTROL WLC_SET_PROTECTION_CONTROL
+
+/* values for n_protection */
+#define WLC_N_PROTECTION_OFF 0
+#define WLC_N_PROTECTION_MIXEDMODE 1
+#define WLC_N_PROTECTION_CTS 2
+
+/* values for n_preamble_type */
+#define WLC_N_PREAMBLE_MIXEDMODE 0
+#define WLC_N_PREAMBLE_GF 1
+
+/* Values for PM */
+#define PM_OFF 0
+#define PM_MAX 1
+#define PM_FAST 2
+
+
+
+typedef struct {
+ int npulses; /* required number of pulses at n * t_int */
+ int ncontig; /* required number of pulses at t_int */
+ int min_pw; /* minimum pulse width (20 MHz clocks) */
+ int max_pw; /* maximum pulse width (20 MHz clocks) */
+ uint16 thresh0; /* Radar detection, thresh 0 */
+ uint16 thresh1; /* Radar detection, thresh 1 */
+ int npulses_lp; /* Radar detection, minimum long pulses */
+ int min_pw_lp; /* Minimum pulsewidth for long pulses */
+ int max_pw_lp; /* Maximum pulsewidth for long pulses */
+ int min_fm_lp; /* Minimum fm for long pulses */
+ int max_deltat_lp; /* Maximum deltat for long pulses */
+ int min_deltat; /* Minimum spacing between pulses */
+} wl_radar_args_t;
+
+/* radar iovar SET defines */
+#define WL_RADAR_DETECTOR_OFF 0 /* radar detector off */
+#define WL_RADAR_DETECTOR_ON 1 /* radar detector on */
+#define WL_RADAR_SIMULATED 2 /* force radar detector to declare
+ * detection once
+ */
+
+/* dfs_status iovar-related defines */
+
+/* cac - channel availability check,
+ * ism - in-service monitoring
+ * csa - channel switching announcement
+ */
+
+/* cac state values */
+#define WL_DFS_CACSTATE_IDLE 0 /* state for operating in non-radar channel */
+#define WL_DFS_CACSTATE_PREISM_CAC 1 /* CAC in progress */
+#define WL_DFS_CACSTATE_ISM 2 /* ISM in progress */
+#define WL_DFS_CACSTATE_CSA 3 /* csa */
+#define WL_DFS_CACSTATE_POSTISM_CAC 4 /* ISM CAC */
+#define WL_DFS_CACSTATE_PREISM_OOC 5 /* PREISM OOC */
+#define WL_DFS_CACSTATE_POSTISM_OOC 6 /* POSTISM OOC */
+#define WL_DFS_CACSTATES 7 /* this many states exist */
+
+/* data structure used in 'dfs_status' wl interface, which is used to query dfs status */
+typedef struct {
+ uint state; /* noted by WL_DFS_CACSTATE_XX. */
+ uint duration; /* time spent in ms in state. */
+ /* as dfs enters ISM state, it removes the operational channel from quiet channel
+ * list and notes the channel in channel_cleared. set to 0 if no channel is cleared
+ */
+ chanspec_t chanspec_cleared;
+ /* chanspec cleared used to be a uint, add another to uint16 to maintain size */
+ uint16 pad;
+} wl_dfs_status_t;
+
+#define NUM_PWRCTRL_RATES 12
+
+typedef struct tx_inst_power {
+} tx_inst_power_t;
+
+
+/* regulatory enforcement levels */
+#define SPECT_MNGMT_OFF 0 /* both 11h and 11d disabled */
+#define SPECT_MNGMT_LOOSE_11H 1 /* allow non-11h APs in scan lists */
+#define SPECT_MNGMT_STRICT_11H 2 /* prune out non-11h APs from scan list */
+#define SPECT_MNGMT_STRICT_11D 3 /* switch to 802.11D mode */
+/* SPECT_MNGMT_LOOSE_11H_D - same as SPECT_MNGMT_LOOSE with the exception that Country IE
+ * adoption is done irregardless of capability-spectrum_management
+ */
+#define SPECT_MNGMT_LOOSE_11H_D 4 /* operation defined above */
+
+#define WL_CHAN_VALID_HW (1 << 0) /* valid with current HW */
+#define WL_CHAN_VALID_SW (1 << 1) /* valid with current country setting */
+#define WL_CHAN_BAND_5G (1 << 2) /* 5GHz-band channel */
+#define WL_CHAN_RADAR (1 << 3) /* radar sensitive channel */
+#define WL_CHAN_INACTIVE (1 << 4) /* temporarily inactive due to radar */
+#define WL_CHAN_PASSIVE (1 << 5) /* channel is in passive mode */
+#define WL_CHAN_RESTRICTED (1 << 6) /* restricted use channel */
+
+/* BTC mode used by "btc_mode" iovar */
+#define WL_BTC_DISABLE 0 /* disable BT coexistance */
+#define WL_BTC_ENABLE 1 /* enable BT coexistance */
+#define WL_BTC_PREMPT 2 /* enable BT coexistance and BT pre-emption */
+
+#define WL_MPC_VAL 0x00400000
+#define WL_APSTA_VAL 0x00800000
+#define WL_DFS_VAL 0x01000000
+#define WL_BA_VAL 0x02000000
+#define WL_NITRO_VAL 0x04000000
+#define WL_CAC_VAL 0x08000000
+#define WL_AMSDU_VAL 0x10000000
+#define WL_AMPDU_VAL 0x20000000
+
+/* max # of leds supported by GPIO (gpio pin# == led index#) */
+#define WL_LED_NUMGPIO 16 /* gpio 0-15 */
+
+/* led per-pin behaviors */
+#define WL_LED_OFF 0 /* always off */
+#define WL_LED_ON 1 /* always on */
+#define WL_LED_ACTIVITY 2 /* activity */
+#define WL_LED_RADIO 3 /* radio enabled */
+#define WL_LED_ARADIO 4 /* 5 Ghz radio enabled */
+#define WL_LED_BRADIO 5 /* 2.4Ghz radio enabled */
+#define WL_LED_BGMODE 6 /* on if gmode, off if bmode */
+#define WL_LED_WI1 7
+#define WL_LED_WI2 8
+#define WL_LED_WI3 9
+#define WL_LED_ASSOC 10 /* associated state indicator */
+#define WL_LED_INACTIVE 11 /* null behavior (clears default behavior) */
+#define WL_LED_NUMBEHAVIOR 12
+
+/* led behavior numeric value format */
+#define WL_LED_BEH_MASK 0x7f /* behavior mask */
+#define WL_LED_AL_MASK 0x80 /* activelow (polarity) bit */
+
+/* max # of channels returnd by the get valid channels iovar */
+#define WL_NUMCHANSPECS 100
+
+/* WDS link local endpoint WPA role */
+#define WL_WDS_WPA_ROLE_AUTH 0 /* authenticator */
+#define WL_WDS_WPA_ROLE_SUP 1 /* supplicant */
+#define WL_WDS_WPA_ROLE_AUTO 255 /* auto, based on mac addr value */
+
+/* number of bytes needed to define a 128-bit mask for MAC event reporting */
+#define WL_EVENTING_MASK_LEN 16
+
+/* Structures and constants used for "vndr_ie" IOVar interface */
+#define VNDR_IE_CMD_LEN 4 /* length of the set command string:
+ * "add", "del" (+ NULL)
+ */
+
+/* 802.11 Mgmt Packet flags */
+#define VNDR_IE_BEACON_FLAG 0x1
+#define VNDR_IE_PRBRSP_FLAG 0x2
+#define VNDR_IE_ASSOCRSP_FLAG 0x4
+#define VNDR_IE_AUTHRSP_FLAG 0x8
+
+#define VNDR_IE_INFO_HDR_LEN (sizeof(uint32))
+
+typedef struct {
+ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */
+ vndr_ie_t vndr_ie_data; /* vendor IE data */
+} vndr_ie_info_t;
+
+typedef struct {
+ int iecount; /* number of entries in the vndr_ie_list[] array */
+ vndr_ie_info_t vndr_ie_list[1]; /* variable size list of vndr_ie_info_t structs */
+} vndr_ie_buf_t;
+
+typedef struct {
+ char cmd[VNDR_IE_CMD_LEN]; /* vndr_ie IOVar set command : "add", "del" + NULL */
+ vndr_ie_buf_t vndr_ie_buffer; /* buffer containing Vendor IE list information */
+} vndr_ie_setbuf_t;
+
+/* join target preference types */
+#define WL_JOIN_PREF_RSSI 1 /* by RSSI, mandatory */
+#define WL_JOIN_PREF_WPA 2 /* by akm and ciphers, optional, RSN and WPA as values */
+#define WL_JOIN_PREF_BAND 3 /* by 802.11 band, optional, WLC_BAND_XXXX as values */
+
+/* band preference */
+#define WLJP_BAND_ASSOC_PREF 255 /* use assoc preference settings */
+ /* others use WLC_BAND_XXXX as values */
+
+/* any multicast cipher suite */
+#define WL_WPA_ACP_MCS_ANY "\x00\x00\x00\x00"
+
+struct tsinfo_arg {
+ uint8 octets[3];
+};
+
+#if !defined(__GNUC__)
+#pragma pack(pop)
+#endif
+
+#define NFIFO 6 /* # tx/rx fifopairs */
+
+#define WL_CNT_T_VERSION 1 /* current version of wl_cnt_t struct */
+
+typedef struct {
+ uint16 version; /* see definition of WL_CNT_T_VERSION */
+ uint16 length; /* length of entire structure */
+
+ /* transmit stat counters */
+ uint32 txframe; /* tx data frames */
+ uint32 txbyte; /* tx data bytes */
+ uint32 txretrans; /* tx mac retransmits */
+ uint32 txerror; /* tx data errors (derived: sum of others) */
+ uint32 txctl; /* tx management frames */
+ uint32 txprshort; /* tx short preamble frames */
+ uint32 txserr; /* tx status errors */
+ uint32 txnobuf; /* tx out of buffers errors */
+ uint32 txnoassoc; /* tx discard because we're not associated */
+ uint32 txrunt; /* tx runt frames */
+ uint32 txchit; /* tx header cache hit (fastpath) */
+ uint32 txcmiss; /* tx header cache miss (slowpath) */
+
+ /* transmit chip error counters */
+ uint32 txuflo; /* tx fifo underflows */
+ uint32 txphyerr; /* tx phy errors (indicated in tx status) */
+ uint32 txphycrs;
+
+ /* receive stat counters */
+ uint32 rxframe; /* rx data frames */
+ uint32 rxbyte; /* rx data bytes */
+ uint32 rxerror; /* rx data errors (derived: sum of others) */
+ uint32 rxctl; /* rx management frames */
+ uint32 rxnobuf; /* rx out of buffers errors */
+ uint32 rxnondata; /* rx non data frames in the data channel errors */
+ uint32 rxbadds; /* rx bad DS errors */
+ uint32 rxbadcm; /* rx bad control or management frames */
+ uint32 rxfragerr; /* rx fragmentation errors */
+ uint32 rxrunt; /* rx runt frames */
+ uint32 rxgiant; /* rx giant frames */
+ uint32 rxnoscb; /* rx no scb error */
+ uint32 rxbadproto; /* rx invalid frames */
+ uint32 rxbadsrcmac; /* rx frames with Invalid Src Mac */
+ uint32 rxbadda; /* rx frames tossed for invalid da */
+ uint32 rxfilter; /* rx frames filtered out */
+
+ /* receive chip error counters */
+ uint32 rxoflo; /* rx fifo overflow errors */
+ uint32 rxuflo[NFIFO]; /* rx dma descriptor underflow errors */
+
+ uint32 d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */
+ uint32 d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */
+ uint32 d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */
+
+ /* misc counters */
+ uint32 dmade; /* tx/rx dma descriptor errors */
+ uint32 dmada; /* tx/rx dma data errors */
+ uint32 dmape; /* tx/rx dma descriptor protocol errors */
+ uint32 reset; /* reset count */
+ uint32 tbtt; /* cnts the TBTT int's */
+ uint32 txdmawar;
+ uint32 pkt_callback_reg_fail; /* callbacks register failure */
+
+ /* MAC counters: 32-bit version of d11.h's macstat_t */
+ uint32 txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS,
+ * Control Management (includes retransmissions)
+ */
+ uint32 txrtsfrm; /* number of RTS sent out by the MAC */
+ uint32 txctsfrm; /* number of CTS sent out by the MAC */
+ uint32 txackfrm; /* number of ACK frames sent out */
+ uint32 txdnlfrm; /* Not used */
+ uint32 txbcnfrm; /* beacons transmitted */
+ uint32 txfunfl[8]; /* per-fifo tx underflows */
+ uint32 txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS
+ * or BCN)
+ */
+ uint32 txphyerror; /* Transmit phy error, type of error is reported in tx-status for
+ * driver enqueued frames
+ */
+ uint32 rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */
+ uint32 rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */
+ uint32 rxinvmachdr; /* Either the protocol version != 0 or frame type not
+ * data/control/management
+ */
+ uint32 rxbadfcs; /* number of frames for which the CRC check failed in the MAC */
+ uint32 rxbadplcp; /* parity check of the PLCP header failed */
+ uint32 rxcrsglitch; /* PHY was able to correlate the preamble but not the header */
+ uint32 rxstrt; /* Number of received frames with a good PLCP
+ * (i.e. passing parity check)
+ */
+ uint32 rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */
+ uint32 rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */
+ uint32 rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */
+ uint32 rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */
+ uint32 rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */
+ uint32 rxackucast; /* number of ucast ACKS received (good FCS) */
+ uint32 rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */
+ uint32 rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */
+ uint32 rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */
+ uint32 rxrtsocast; /* number of received RTS not addressed to the MAC */
+ uint32 rxctsocast; /* number of received CTS not addressed to the MAC */
+ uint32 rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */
+ uint32 rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */
+ uint32 rxcfrmmcast; /* number of RX Control multicast frames received by the MAC
+ * (unlikely to see these)
+ */
+ uint32 rxbeaconmbss; /* beacons received from member of BSS */
+ uint32 rxdfrmucastobss; /* number of unicast frames addressed to the MAC from
+ * other BSS (WDS FRAME)
+ */
+ uint32 rxbeaconobss; /* beacons received from other BSS */
+ uint32 rxrsptmout; /* Number of response timeouts for transmitted frames
+ * expecting a response
+ */
+ uint32 bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */
+ uint32 rxf0ovfl; /* Number of receive fifo 0 overflows */
+ uint32 rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */
+ uint32 rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */
+ uint32 txsfovfl; /* Number of transmit status fifo overflows (obsolete) */
+ uint32 pmqovfl; /* Number of PMQ overflows */
+ uint32 rxcgprqfrm; /* Number of received Probe requests that made it into
+ * the PRQ fifo
+ */
+ uint32 rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */
+ uint32 txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did
+ * not get ACK
+ */
+ uint32 txcgprssuc; /* Tx Probe Response Success (ACK was received) */
+ uint32 prs_timeout; /* Number of probe requests that were dropped from the PRQ
+ * fifo because a probe response could not be sent out within
+ * the time limit defined in M_PRS_MAXTIME
+ */
+ uint32 rxnack; /* Number of NACKS received (Afterburner) */
+ uint32 frmscons; /* Number of frames completed without transmission because of an
+ * Afterburner re-queue
+ */
+ uint32 txnack; /* Number of NACKs transmitted (Afterburner) */
+ uint32 txglitch_nack; /* obsolete */
+ uint32 txburst; /* obsolete */
+
+ /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */
+ uint32 txfrag; /* dot11TransmittedFragmentCount */
+ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */
+ uint32 txfail; /* dot11FailedCount */
+ uint32 txretry; /* dot11RetryCount */
+ uint32 txretrie; /* dot11MultipleRetryCount */
+ uint32 rxdup; /* dot11FrameduplicateCount */
+ uint32 txrts; /* dot11RTSSuccessCount */
+ uint32 txnocts; /* dot11RTSFailureCount */
+ uint32 txnoack; /* dot11ACKFailureCount */
+ uint32 rxfrag; /* dot11ReceivedFragmentCount */
+ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */
+ uint32 rxcrc; /* dot11FCSErrorCount */
+ uint32 txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */
+ uint32 rxundec; /* dot11WEPUndecryptableCount */
+
+ /* WPA2 counters (see rxundec for DecryptFailureCount) */
+ uint32 tkipmicfaill; /* TKIPLocalMICFailures */
+ uint32 tkipcntrmsr; /* TKIPCounterMeasuresInvoked */
+ uint32 tkipreplay; /* TKIPReplays */
+ uint32 ccmpfmterr; /* CCMPFormatErrors */
+ uint32 ccmpreplay; /* CCMPReplays */
+ uint32 ccmpundec; /* CCMPDecryptErrors */
+ uint32 fourwayfail; /* FourWayHandshakeFailures */
+ uint32 wepundec; /* dot11WEPUndecryptableCount */
+ uint32 wepicverr; /* dot11WEPICVErrorCount */
+ uint32 decsuccess; /* DecryptSuccessCount */
+ uint32 tkipicverr; /* TKIPICVErrorCount */
+ uint32 wepexcluded; /* dot11WEPExcludedCount */
+
+ uint32 txchanrej; /* Tx frames suppressed due to channel rejection */
+ uint32 psmwds; /* Count PSM watchdogs */
+ uint32 phywatchdog; /* Count Phy lockups */
+} wl_cnt_t;
+
+#define WL_WME_CNT_VERSION 1 /* current version of wl_wme_cnt_t */
+
+typedef struct {
+ uint32 packets;
+ uint32 bytes;
+} wl_traffic_stats_t;
+
+typedef struct {
+ uint16 version; /* see definition of WL_CNT_T_VERSION */
+ uint16 length; /* length of entire structure */
+
+ wl_traffic_stats_t tx[AC_COUNT]; /* Packets transmitted */
+ wl_traffic_stats_t tx_failed[AC_COUNT]; /* Packets dropped or failed to transmit */
+ wl_traffic_stats_t rx[AC_COUNT]; /* Packets received */
+ wl_traffic_stats_t rx_failed[AC_COUNT]; /* Packets failed to receive */
+
+ wl_traffic_stats_t forward[AC_COUNT]; /* Packets forwarded by AP */
+
+ wl_traffic_stats_t tx_expired[AC_COUNT]; /* packets dropped due to lifetime expiry */
+
+} wl_wme_cnt_t;
+
+#ifdef WLBA
+
+#define WLC_BA_CNT_VERSION 1 /* current version of wlc_ba_cnt_t */
+
+/* block ack related stats */
+typedef struct wlc_ba_cnt {
+ uint16 version; /* WLC_BA_CNT_VERSION */
+ uint16 length; /* length of entire structure */
+
+ /* transmit stat counters */
+ uint32 txpdu; /* pdus sent */
+ uint32 txsdu; /* sdus sent */
+ uint32 txfc; /* tx side flow controlled packets */
+ uint32 txfci; /* tx side flow control initiated */
+ uint32 txretrans; /* retransmitted pdus */
+ uint32 txbatimer; /* ba resend due to timer */
+ uint32 txdrop; /* dropped packets */
+ uint32 txaddbareq; /* addba req sent */
+ uint32 txaddbaresp; /* addba resp sent */
+ uint32 txdelba; /* delba sent */
+ uint32 txba; /* ba sent */
+ uint32 txbar; /* bar sent */
+ uint32 txpad[4]; /* future */
+
+ /* receive side counters */
+ uint32 rxpdu; /* pdus recd */
+ uint32 rxqed; /* pdus buffered before sending up */
+ uint32 rxdup; /* duplicate pdus */
+ uint32 rxnobuf; /* pdus discarded due to no buf */
+ uint32 rxaddbareq; /* addba req recd */
+ uint32 rxaddbaresp; /* addba resp recd */
+ uint32 rxdelba; /* delba recd */
+ uint32 rxba; /* ba recd */
+ uint32 rxbar; /* bar recd */
+ uint32 rxinvba; /* invalid ba recd */
+ uint32 rxbaholes; /* ba recd with holes */
+ uint32 rxunexp; /* unexpected packets */
+ uint32 rxpad[4]; /* future */
+} wlc_ba_cnt_t;
+#endif /* WLBA */
+
+/* structure for per-tid ampdu control */
+struct ampdu_tid_control {
+ uint8 tid; /* tid */
+ uint8 enable; /* enable/disable */
+};
+
+/* structure for addts arguments */
+/* For ioctls that take a list of TSPEC */
+struct tslist {
+ int count; /* number of tspecs */
+ struct tsinfo_arg tsinfo[1]; /* variable length array of tsinfo */
+};
+
+/* structure for addts/delts arguments */
+typedef struct tspec_arg {
+ uint16 version; /* see definition of TSPEC_ARG_VERSION */
+ uint16 length; /* length of entire structure */
+ uint flag; /* bit field */
+ /* TSPEC Arguments */
+ struct tsinfo_arg tsinfo; /* TS Info bit field */
+ uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */
+ uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */
+ uint min_srv_interval; /* Minimum Service Interval (us) */
+ uint max_srv_interval; /* Maximum Service Interval (us) */
+ uint inactivity_interval; /* Inactivity Interval (us) */
+ uint suspension_interval; /* Suspension Interval (us) */
+ uint srv_start_time; /* Service Start Time (us) */
+ uint min_data_rate; /* Minimum Data Rate (bps) */
+ uint mean_data_rate; /* Mean Data Rate (bps) */
+ uint peak_data_rate; /* Peak Data Rate (bps) */
+ uint max_burst_size; /* Maximum Burst Size (bytes) */
+ uint delay_bound; /* Delay Bound (us) */
+ uint min_phy_rate; /* Minimum PHY Rate (bps) */
+ uint16 surplus_bw; /* Surplus Bandwidth Allowance Factor */
+ uint16 medium_time; /* Medium Time (32 us/s periods) */
+} tspec_arg_t;
+
+/* current version of wl_tspec_arg_t struct */
+#define TSPEC_ARG_VERSION 1 /* current version of wl_tspec_arg_t struct */
+#define TSPEC_ARG_LENGTH 55 /* argment length from tsinfo to medium_time */
+
+/* define for flag */
+#define TSPEC_PENDING 0 /* TSPEC pending */
+#define TSPEC_ACCEPTED 1 /* TSPEC accepted */
+#define TSPEC_REJECTED 2 /* TSPEC rejected */
+#define TSPEC_UNKNOWN 3 /* TSPEC unknown */
+#define TSPEC_STATUS_MASK 7 /* TSPEC status mask */
+
+
+/* Software feature flag defines used by wlfeatureflag */
+#define WL_SWFL_ABBFL 0x0001 /* Allow Afterburner on systems w/o hardware BFL */
+#define WL_SWFL_ABENCORE 0x0002 /* Allow AB on non-4318E chips */
+
+#define WL_LIFETIME_MAX 0xFFFF /* Max value in ms */
+
+/* Packet lifetime configuration per ac */
+typedef struct wl_lifetime {
+ uint32 ac; /* access class */
+ uint32 lifetime; /* Packet lifetime value in ms */
+} wl_lifetime_t;
+
+#endif /* _wlioctl_h_ */
diff --git a/package/broadcom-wl/src/wlc/include/wlutils.h b/package/broadcom-wl/src/wlc/include/wlutils.h
new file mode 100644
index 0000000000..a5aa1fd663
--- /dev/null
+++ b/package/broadcom-wl/src/wlc/include/wlutils.h
@@ -0,0 +1,102 @@
+/*
+ * Broadcom wireless network adapter utility functions
+ *
+ * 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.
+ *
+ * $Id: wlutils.h,v 1.1.1.12 2006/02/27 03:43:20 honor Exp $
+ */
+
+#ifndef _wlutils_h_
+#define _wlutils_h_
+
+#include <typedefs.h>
+#include <wlioctl.h>
+
+/*
+ * Pass a wlioctl request to the specified interface.
+ * @param name interface name
+ * @param cmd WLC_GET_MAGIC <= cmd < WLC_LAST
+ * @param buf buffer for passing in and/or receiving data
+ * @param len length of buf
+ * @return >= 0 if successful or < 0 otherwise
+ */
+extern int wl_ioctl(char *name, int cmd, void *buf, int len);
+
+/*
+ * Probe the specified interface.
+ * @param name interface name
+ * @return >= 0 if a Broadcom wireless device or < 0 otherwise
+ */
+extern int wl_probe(char *name);
+
+extern int wl_iovar_set(char *ifname, char *iovar, void *param, int paramlen);
+extern int wl_iovar_get(char *ifname, char *iovar, void *bufptr, int buflen);
+/*
+ * Set/Get named variable.
+ * @param ifname interface name
+ * @param iovar variable name
+ * @param param input param value/buffer
+ * @param paramlen input param value/buffer length
+ * @param bufptr io buffer
+ * @param buflen io buffer length
+ * @param val val or val pointer for int routines
+ * @return success == 0, failure != 0
+ */
+/*
+ * set named driver variable to int value
+ * calling example: wl_iovar_setint(ifname, "arate", rate)
+*/
+static inline int
+wl_iovar_setint(char *ifname, char *iovar, int val)
+{
+ return wl_iovar_set(ifname, iovar, &val, sizeof(val));
+}
+
+/*
+ * get named driver variable to int value and return error indication
+ * calling example: wl_iovar_getint(ifname, "arate", &rate)
+ */
+static inline int
+wl_iovar_getint(char *ifname, char *iovar, int *val)
+{
+ return wl_iovar_get(ifname, iovar, val, sizeof(int));
+}
+
+/*
+ * Set/Get named variable indexed by BSS Configuration
+ * @param ifname interface name
+ * @param iovar variable name
+ * @param bssidx bsscfg index
+ * @param param input param value/buffer
+ * @param paramlen input param value/buffer length
+ * @param bufptr io buffer
+ * @param buflen io buffer length
+ * @param val val or val pointer for int routines
+ * @return success == 0, failure != 0
+ */
+extern int wl_bssiovar_get(char *ifname, char *iovar, int bssidx, void *outbuf, int len);
+extern int wl_bssiovar_set(char *ifname, char *iovar, int bssidx, void *param, int paramlen);
+/*
+ * set named & bss indexed driver variable to int value
+ */
+static inline int
+wl_bssiovar_setint(char *ifname, char *iovar, int bssidx, int val)
+{
+ return wl_bssiovar_set(ifname, iovar, bssidx, &val, sizeof(int));
+}
+
+static inline int
+wl_bssiovar_getint(char *ifname, char *iovar, int bssidx, int *val)
+{
+ return wl_bssiovar_get(ifname, iovar, bssidx, val, sizeof(int));
+}
+
+extern int wl_bssiovar_setint(char *ifname, char *iovar, int bssidx, int val);
+
+#endif /* _wlutils_h_ */
diff --git a/package/broadcom-wl/src/wlc/ioctl.c b/package/broadcom-wl/src/wlc/ioctl.c
new file mode 100644
index 0000000000..6c676c7c9b
--- /dev/null
+++ b/package/broadcom-wl/src/wlc/ioctl.c
@@ -0,0 +1,298 @@
+/*
+ * Wireless network adapter utilities
+ *
+ * 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.
+ *
+ * $Id: wl.c,v 1.1.1.11 2006/02/27 03:43:20 honor Exp $
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <linux/types.h>
+
+typedef u_int64_t u64;
+typedef u_int32_t u32;
+typedef u_int16_t u16;
+typedef u_int8_t u8;
+#include <linux/sockios.h>
+#include <linux/ethtool.h>
+
+#include <typedefs.h>
+#include <wlioctl.h>
+#include <bcmutils.h>
+#include <wlutils.h>
+
+int
+wl_ioctl(char *name, int cmd, void *buf, int len)
+{
+ struct ifreq ifr;
+ wl_ioctl_t ioc;
+ int ret = 0;
+ int s;
+
+ /* open socket to kernel */
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("socket");
+ return errno;
+ }
+
+ /* do it */
+ ioc.cmd = cmd;
+ ioc.buf = buf;
+ ioc.len = len;
+ strncpy(ifr.ifr_name, name, IFNAMSIZ);
+ ifr.ifr_data = (caddr_t) &ioc;
+ if ((ret = ioctl(s, SIOCDEVPRIVATE, &ifr)) < 0)
+
+ /* cleanup */
+ close(s);
+ return ret;
+}
+
+static inline int
+wl_get_dev_type(char *name, void *buf, int len)
+{
+ int s;
+ int ret;
+ struct ifreq ifr;
+ struct ethtool_drvinfo info;
+
+ /* open socket to kernel */
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("socket");
+ return -1;
+ }
+
+ /* get device type */
+ memset(&info, 0, sizeof(info));
+ info.cmd = ETHTOOL_GDRVINFO;
+ ifr.ifr_data = (caddr_t)&info;
+ strncpy(ifr.ifr_name, name, IFNAMSIZ);
+ if ((ret = ioctl(s, SIOCETHTOOL, &ifr)) < 0) {
+ *(char *)buf = '\0';
+ } else
+ strncpy(buf, info.driver, len);
+
+ close(s);
+ return ret;
+}
+
+int
+wl_probe(char *name)
+{
+ int ret, val;
+ char buf[3];
+ if ((ret = wl_get_dev_type(name, buf, 3)) < 0)
+ return ret;
+ /* Check interface */
+ if (strncmp(buf, "wl", 2))
+ return -1;
+ if ((ret = wl_ioctl(name, WLC_GET_VERSION, &val, sizeof(val))))
+ return ret;
+ if (val > WLC_IOCTL_VERSION)
+ return -1;
+
+ return ret;
+}
+
+static int
+wl_iovar_getbuf(char *ifname, char *iovar, void *param, int paramlen, void *bufptr, int buflen)
+{
+ int err;
+ uint namelen;
+ uint iolen;
+
+ namelen = strlen(iovar) + 1; /* length of iovar name plus null */
+ iolen = namelen + paramlen;
+
+ /* check for overflow */
+ if (iolen > buflen)
+ return (BCME_BUFTOOSHORT);
+
+ memcpy(bufptr, iovar, namelen); /* copy iovar name including null */
+ memcpy((int8*)bufptr + namelen, param, paramlen);
+
+ err = wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen);
+
+ return (err);
+}
+
+static int
+wl_iovar_setbuf(char *ifname, char *iovar, void *param, int paramlen, void *bufptr, int buflen)
+{
+ uint namelen;
+ uint iolen;
+
+ namelen = strlen(iovar) + 1; /* length of iovar name plus null */
+ iolen = namelen + paramlen;
+
+ /* check for overflow */
+ if (iolen > buflen)
+ return (BCME_BUFTOOSHORT);
+
+ memcpy(bufptr, iovar, namelen); /* copy iovar name including null */
+ memcpy((int8*)bufptr + namelen, param, paramlen);
+
+ return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen);
+}
+
+int
+wl_iovar_set(char *ifname, char *iovar, void *param, int paramlen)
+{
+ char smbuf[WLC_IOCTL_SMLEN];
+
+ return wl_iovar_setbuf(ifname, iovar, param, paramlen, smbuf, sizeof(smbuf));
+}
+
+int
+wl_iovar_get(char *ifname, char *iovar, void *bufptr, int buflen)
+{
+ char smbuf[WLC_IOCTL_SMLEN];
+ int ret;
+
+ /* use the return buffer if it is bigger than what we have on the stack */
+ if (buflen > sizeof(smbuf)) {
+ ret = wl_iovar_getbuf(ifname, iovar, NULL, 0, bufptr, buflen);
+ } else {
+ ret = wl_iovar_getbuf(ifname, iovar, NULL, 0, smbuf, sizeof(smbuf));
+ if (ret == 0)
+ memcpy(bufptr, smbuf, buflen);
+ }
+
+ return ret;
+}
+
+
+/*
+ * format a bsscfg indexed iovar buffer
+ */
+static int
+wl_bssiovar_mkbuf(char *iovar, int bssidx, void *param, int paramlen, void *bufptr, int buflen,
+ int *plen)
+{
+ char *prefix = "bsscfg:";
+ int8* p;
+ uint prefixlen;
+ uint namelen;
+ uint iolen;
+
+ prefixlen = strlen(prefix); /* length of bsscfg prefix */
+ namelen = strlen(iovar) + 1; /* length of iovar name + null */
+ iolen = prefixlen + namelen + sizeof(int) + paramlen;
+
+ /* check for overflow */
+ if (buflen < 0 || iolen > (uint)buflen) {
+ *plen = 0;
+ return BCME_BUFTOOSHORT;
+ }
+
+ p = (int8*)bufptr;
+
+ /* copy prefix, no null */
+ memcpy(p, prefix, prefixlen);
+ p += prefixlen;
+
+ /* copy iovar name including null */
+ memcpy(p, iovar, namelen);
+ p += namelen;
+
+ /* bss config index as first param */
+ memcpy(p, &bssidx, sizeof(int32));
+ p += sizeof(int32);
+
+ /* parameter buffer follows */
+ if (paramlen)
+ memcpy(p, param, paramlen);
+
+ *plen = iolen;
+ return 0;
+}
+
+/*
+ * set named & bss indexed driver variable to buffer value
+ */
+static int
+wl_bssiovar_setbuf(char *ifname, char *iovar, int bssidx, void *param, int paramlen, void *bufptr,
+ int buflen)
+{
+ int err;
+ int iolen;
+
+ err = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &iolen);
+ if (err)
+ return err;
+
+ return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen);
+}
+
+/*
+ * get named & bss indexed driver variable buffer value
+ */
+static int
+wl_bssiovar_getbuf(char *ifname, char *iovar, int bssidx, void *param, int paramlen, void *bufptr,
+ int buflen)
+{
+ int err;
+ int iolen;
+
+ err = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &iolen);
+ if (err)
+ return err;
+
+ return wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen);
+}
+
+/*
+ * set named & bss indexed driver variable to buffer value
+ */
+int
+wl_bssiovar_set(char *ifname, char *iovar, int bssidx, void *param, int paramlen)
+{
+ char smbuf[WLC_IOCTL_SMLEN];
+
+ return wl_bssiovar_setbuf(ifname, iovar, bssidx, param, paramlen, smbuf, sizeof(smbuf));
+}
+
+/*
+ * get named & bss indexed driver variable buffer value
+ */
+int
+wl_bssiovar_get(char *ifname, char *iovar, int bssidx, void *outbuf, int len)
+{
+ char smbuf[WLC_IOCTL_SMLEN];
+ int err;
+
+ /* use the return buffer if it is bigger than what we have on the stack */
+ if (len > (int)sizeof(smbuf)) {
+ err = wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, outbuf, len);
+ } else {
+ memset(smbuf, 0, sizeof(smbuf));
+ err = wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, smbuf, sizeof(smbuf));
+ if (err == 0)
+ memcpy(outbuf, smbuf, len);
+ }
+
+ return err;
+}
+
+void
+wl_printlasterror(char *name)
+{
+ char err_buf[WLC_IOCTL_SMLEN];
+ strcpy(err_buf, "bcmerrstr");
+
+ fprintf(stderr, "Error: ");
+ if ( wl_ioctl(name, WLC_GET_VAR, err_buf, sizeof (err_buf)) != 0)
+ fprintf(stderr, "Error getting the Errorstring from driver\n");
+ else
+ fprintf(stderr, err_buf);
+}
diff --git a/package/broadcom-wl/src/wlc/wlc.c b/package/broadcom-wl/src/wlc/wlc.c
new file mode 100644
index 0000000000..09cbb84538
--- /dev/null
+++ b/package/broadcom-wl/src/wlc/wlc.c
@@ -0,0 +1,1140 @@
+/*
+ * 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 ptable[128];
+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,
+
+ /* 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);
+extern char *ether_ntoa(const struct ether_addr *addr);
+
+/*
+ * find the starting point of wl.o in memory
+ * by reading /proc/ksyms
+ */
+static inline void wlc_get_mem_offset(void)
+{
+ FILE *f;
+ char s[64];
+
+ /* yes, i'm lazy ;) */
+ f = popen("grep '\\[wl]' /proc/ksyms | sort", "r");
+ if (fgets(s, 64, f) == 0)
+ return;
+
+ pclose(f);
+
+ s[8] = 0;
+ kmem_offset = strtoul(s, NULL, 16);
+
+ /* sanity check */
+ if (kmem_offset < 0xc0000000)
+ kmem_offset = 0;
+}
+
+
+static int ptable_init(void)
+{
+ glob_t globbuf;
+ struct stat statbuf;
+ int fd;
+
+ if (ptable[0] == PTABLE_MAGIC)
+ return 0;
+
+ glob("/lib/modules/2.4.*/wl.o.patch", 0, NULL, &globbuf);
+
+ if (globbuf.gl_pathv[0] == NULL)
+ return -1;
+
+ if ((fd = open(globbuf.gl_pathv[0], O_RDONLY)) < 0)
+ return -1;
+
+ if (fstat(fd, &statbuf) < 0)
+ goto failed;
+
+ if (statbuf.st_size < 512)
+ goto failed;
+
+ if (read(fd, ptable, 512) < 512)
+ goto failed;
+
+ if (ptable[0] != PTABLE_MAGIC)
+ goto failed;
+
+ close(fd);
+
+ wlc_get_mem_offset();
+ if (kmem_offset == 0)
+ return -1;
+
+ return 0;
+
+failed:
+ close(fd);
+
+ return -1;
+}
+
+static inline unsigned long wlc_kmem_read(unsigned long offset)
+{
+ int fd;
+ unsigned long ret;
+
+ if ((fd = open("/dev/kmem", O_RDONLY )) < 0)
+ return -1;
+
+ lseek(fd, 0x70000000, SEEK_SET);
+ lseek(fd, (kmem_offset - 0x70000000) + offset, SEEK_CUR);
+ read(fd, &ret, 4);
+ close(fd);
+
+ return ret;
+}
+
+static inline void wlc_kmem_write(unsigned long offset, unsigned long value)
+{
+ int fd;
+
+ if ((fd = open("/dev/kmem", O_WRONLY )) < 0)
+ return;
+
+ lseek(fd, 0x70000000, SEEK_SET);
+ lseek(fd, (kmem_offset - 0x70000000) + offset, SEEK_CUR);
+ write(fd, &value, 4);
+ close(fd);
+}
+
+static int wlc_patcher_getval(unsigned long key, unsigned long *val)
+{
+ unsigned long *pt = &ptable[1];
+ unsigned long tmp;
+
+ if (ptable_init() < 0) {
+ fprintf(stderr, "Could not load the ptable\n");
+ return -1;
+ }
+
+ while (*pt != PTABLE_END) {
+ if (*pt == key) {
+ tmp = wlc_kmem_read(pt[1]);
+
+ if (tmp == pt[2])
+ *val = 0xffffffff;
+ else
+ *val = tmp;
+
+ return 0;
+ }
+ pt += 3;
+ }
+
+ return -1;
+}
+
+static int wlc_patcher_setval(unsigned long key, unsigned long val)
+{
+ unsigned long *pt = &ptable[1];
+
+ if (ptable_init() < 0) {
+ fprintf(stderr, "Could not load the ptable\n");
+ return -1;
+ }
+
+ if (val != 0xffffffff)
+ val = (pt[2] & ~(0xffff)) | (val & 0xffff);
+
+ while (*pt != PTABLE_END) {
+ if (*pt == key) {
+ if (val == 0xffffffff) /* default */
+ val = pt[2];
+
+ wlc_kmem_write(pt[1], val);
+ }
+ pt += 3;
+ }
+
+ return 0;
+}
+
+static int wlc_slottime(wlc_param param, void *data, void *value)
+{
+ int *val = (int *) value;
+ int ret = 0;
+
+ if ((param & PARAM_MODE) == SET) {
+ wlc_patcher_setval(PTABLE_SLT1, *val);
+ wlc_patcher_setval(PTABLE_SLT2, ((*val == -1) ? *val : *val + 510));
+ } else if ((param & PARAM_MODE) == GET) {
+ ret = wlc_patcher_getval(PTABLE_SLT1, (unsigned long *) val);
+ if (*val != 0xffffffff)
+ *val &= 0xffff;
+ }
+
+ return ret;
+}
+
+static int wlc_noack(wlc_param param, void *data, void *value)
+{
+ int *val = (int *) value;
+ int ret = 0;
+
+ if ((param & PARAM_MODE) == SET) {
+ wlc_patcher_setval(PTABLE_ACKW, ((*val) ? 1 : 0));
+ } else if ((param & PARAM_MODE) == GET) {
+ ret = wlc_patcher_getval(PTABLE_ACKW, (unsigned long *) val);
+ *val &= 0xffff;
+ *val = (*val ? 1 : 0);
+ }
+
+ return ret;
+}
+
+static int wlc_ibss_merge(wlc_param param, void *data, void *value)
+{
+ int *val = (int *) value;
+ int ret = 0;
+
+ if ((param & PARAM_MODE) == SET) {
+ /* overwrite the instruction with 'lui v0,0x0' - fake a return
+ * status of 0 for wlc_bcn_tsf_later */
+ wlc_patcher_setval(PTABLE_ACKW, ((*val) ? -1 : 0x3c020000));
+ } else if ((param & PARAM_MODE) == GET) {
+ ret = wlc_patcher_getval(PTABLE_ACKW, (unsigned long *) val);
+ *val = ((*val == -1) ? 1 : 0);
+ }
+
+ return ret;
+}
+
+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 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);
+ }
+ }
+ if (param & GET) {
+ switch(param & PARAM_TYPE) {
+ case INT:
+ ret = wl_iovar_getint(interface, iov, val);
+ }
+ }
+
+ 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_getint(interface, iov, vif, val);
+ }
+ }
+
+ 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_getint(interface, "afterburner", val);
+ } 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%s", ((((char *) value) == str) ? "" : " "), ether_ntoa(&list->ea[list->count-- - 1]));
+
+ 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 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 = "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 = "mssid",
+ .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 = "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 = "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 = "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 = "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",
+ .param = INT,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_PASSIVE << 16) | WLC_SET_PASSIVE),
+ .desc = "Passive 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 = "afterburner",
+ .param = INT,
+ .handler = wlc_afterburner,
+ .desc = "Broadcom Afterburner"
+ },
+ {
+ .name = "slottime",
+ .param = INT,
+ .handler = wlc_slottime,
+ .desc = "Slot time (-1 = auto)"
+ },
+ {
+ .name = "txack",
+ .param = INT,
+ .handler = wlc_noack,
+ .desc = "Tx ACK enabled flag"
+ },
+ {
+ .name = "ibss_merge",
+ .param = INT,
+ .handler = wlc_ibss_merge,
+ .desc = "Allow IBSS merge in Ad-Hoc 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;
+
+ 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);
+ }
+ }
+ } 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;
+ }
+
+ ret = cmd->handler(cmd->param | SET, (void *) &cmd->data, (void *) buf);
+ }
+
+ 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/Makefile b/package/busybox/Makefile
new file mode 100644
index 0000000000..05174a32bd
--- /dev/null
+++ b/package/busybox/Makefile
@@ -0,0 +1,73 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=busybox
+PKG_VERSION:=1.2.1
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://www.busybox.net/downloads
+PKG_MD5SUM:=362b3dc0f2023ddfda901dc1f1a74391
+PKG_CAT:=bzcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/busybox
+ SECTION:=base
+ CATEGORY:=Base system
+ DEFAULT:=y
+ TITLE:=Core utilities for embedded Linux
+ URL:=http://busybox.net/
+ 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
+ menu "Configuration"
+ depends on PACKAGE_busybox
+ source "$(SOURCE)/config/Config.in"
+ endmenu
+endef
+
+define Build/Configure
+ $(SCRIPT_DIR)/gen_busybox_config.pl $(TOPDIR)/.config > $(PKG_BUILD_DIR)/.config
+ yes '' | $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" \
+ CROSS="$(TARGET_CROSS)" \
+ oldconfig
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" \
+ CROSS="$(TARGET_CROSS)" \
+ EXTRA_CFLAGS="$(TARGET_CFLAGS)" \
+ IPKG_ARCH="$(ARCH)" \
+ all
+endef
+
+define Package/busybox/install
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" \
+ CROSS="$(TARGET_CROSS)" \
+ EXTRA_CFLAGS="$(TARGET_CFLAGS)" \
+ IPKG_ARCH="$(ARCH)" \
+ PREFIX="$(1)" \
+ install
+ -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 0000000000..6a5d6a74d1
--- /dev/null
+++ b/package/busybox/config/Config.in
@@ -0,0 +1,474 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+
+config BUSYBOX_HAVE_DOT_CONFIG
+ bool
+ default y
+
+menu "Busybox Settings"
+
+menu "General Configuration"
+
+config BUSYBOX_CONFIG_NITPICK
+ bool "See lots more (probably unnecessary) configuration options."
+ default n
+ help
+ Some BusyBox applets have more configuration options than anyone
+ will ever care about. To avoid drowining people in complexity, most
+ of the applet features that can be set to a sane default value are
+ hidden, unless you hit the above switch.
+
+ This is better than to telling people to edit the busybox source
+ code, but not by much.
+
+ See http://en.wikipedia.org/wiki/Fibber_McGee_and_Molly#The_Closet
+
+ You have been warned.
+
+choice
+ prompt "Buffer allocation policy"
+ default BUSYBOX_CONFIG_FEATURE_BUFFERS_GO_ON_STACK
+ depends on BUSYBOX_CONFIG_NITPICK
+ 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
+ select 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 n
+ depends on BUSYBOX_CONFIG_SHOW_USAGE && BUSYBOX_CONFIG_NITPICK
+ 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. This feature requires the
+ /proc filesystem.
+
+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_GETOPT_LONG
+ bool
+ default y
+# bool "Enable support for --long-options"
+# default n
+# 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
+ depends on BUSYBOX_CONFIG_NITPICK
+ 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_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, and it'll and it'll automatically drop
+ priviledges for applets that don't need root access.
+
+ If you're 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 currently marked to need the suid bit
+ are login, passwd, su, ping, traceroute, crontab, dnsd, ipcrm, ipcs,
+ and vlock.
+
+config BUSYBOX_CONFIG_FEATURE_SUID_CONFIG
+ bool "Runtime SUID/SGID configuration via /etc/busybox.conf"
+ default n if BUSYBOX_CONFIG_FEATURE_SUID
+ 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-] (<username>|<uid>).(<groupname>|<gid>)
+
+ 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
+ # and runs with euid=0
+
+ 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
+ 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_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.
+
+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_BUILD_LIBBUSYBOX
+ bool "Build shared libbusybox"
+ default n
+ help
+ Build a shared library libbusybox.so which contains all
+ libraries used inside busybox.
+
+ This is an experimental feature intended to support the upcoming
+ "make standalone" mode. Enabling it against the one big busybox
+ binary serves no purpose (and increases the size). You should
+ almost certainly say "no" to this right now.
+
+config BUSYBOX_CONFIG_FEATURE_FULL_LIBBUSYBOX
+ bool "Feature-complete libbusybox"
+ default n if !CONFIG_FEATURE_SHARED_BUSYBOX
+ depends on BUSYBOX_CONFIG_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_SHARED_BUSYBOX
+ bool "Use shared libbusybox for busybox"
+ default n if BUSYBOX_CONFIG_BUILD_LIBBUSYBOX
+ depends on !CONFIG_STATIC && BUSYBOX_CONFIG_BUILD_LIBBUSYBOX
+ help
+ Use libbusybox.so also for busybox itself.
+ You need to have a working dynamic linker to use this variant.
+
+config BUSYBOX_CONFIG_LFS
+ bool
+ default y
+ select BUSYBOX_FDISK_SUPPORT_LARGE_DISKS
+ 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_USING_CROSS_COMPILER
+ bool
+ default y
+ help
+ Do you want to build BusyBox with a Cross Compiler? If so,
+ then enable this option. Otherwise leave it set to 'N'.
+
+config BUSYBOX_CROSS_COMPILER_PREFIX
+ string
+ default "mipsel-uclibc-"
+ depends on BUSYBOX_USING_CROSS_COMPILER
+ 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,
+ if my cross-compiler is /usr/i386-linux-uclibc/bin/i386-uclibc-gcc
+ then I would enter '/usr/i386-linux-uclibc/bin/i386-uclibc-' here,
+ which will ensure the correct compiler is used.
+
+config BUSYBOX_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.
+
+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.
+
+choice
+ prompt "Additional debugging library"
+ default BUSYBOX_CONFIG_NO_DEBUG_LIB
+ depends on BUSYBOX_CONFIG_DEBUG
+ 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
+
+config BUSYBOX_CONFIG_DEBUG_YANK_SUSv2
+ bool "Disable obsolete features removed before SUSv3?"
+ default y
+ help
+ This option will disable backwards compatibility with SuSv2,
+ specifically, old-style numeric options ('command -1 <file>')
+ will not be supported in head, tail, and fold. (Note: should
+ yank from renice too.)
+
+endmenu
+
+menu 'Installation Options'
+
+config BUSYBOX_CONFIG_INSTALL_NO_USR
+ bool "Don't use /usr"
+ default n
+ help
+ Disable use of /usr. Don't activate this option if you don't know
+ that you really want this behaviour.
+
+choice
+ prompt "Applets links"
+ default BUSYBOX_CONFIG_INSTALL_APPLET_SYMLINKS
+ help
+ Choose how you install applets links.
+
+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_DONT
+ bool
+ prompt "not installed"
+ depends on BUSYBOX_CONFIG_FEATURE_INSTALLER || BUSYBOX_CONFIG_FEATURE_SH_STANDALONE_SHELL
+ help
+ Do not install applets links. Usefull when using the -install feature
+ or a standalone shell for rescue pruposes.
+
+endchoice
+
+config BUSYBOX_PREFIX
+ string
+ 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/procps/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 0000000000..ac71d753a2
--- /dev/null
+++ b/package/busybox/config/archival/Config.in
@@ -0,0 +1,308 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Archival Utilities"
+
+config BUSYBOX_CONFIG_AR
+ bool "ar"
+ default n
+ 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 "Enable support for long filenames (not need 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_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.
+
+ The BusyBox bunzip2 applet is limited to de-compression only.
+ On an x86 system, this applet adds about 11K.
+
+ Unless you have a specific application which requires bunzip2, 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_DPKG
+ bool "dpkg"
+ default n
+ 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
+ help
+ dpkg-deb packs, 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, you should
+ probably 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_FEATURE_GUNZIP_UNCOMPRESS
+ bool "Uncompress support"
+ default y
+ depends on BUSYBOX_CONFIG_GUNZIP
+ help
+ Enable if you want gunzip to have the ability to decompress
+ archives created by the program compress (not much
+ used anymore).
+
+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_IPKG
+ bool "ipkg"
+ default y
+ select BUSYBOX_CONFIG_MD5SUM
+ select BUSYBOX_CONFIG_WGET
+ help
+ ipkg is the itsy package management system.
+
+config BUSYBOX_CONFIG_RPM2CPIO
+ bool "rpm2cpio"
+ default n
+ help
+ Converts an RPM file into a CPIO archive.
+
+config BUSYBOX_CONFIG_RPM
+ bool "rpm"
+ default n
+ help
+ Mini RPM applet - queries and extracts
+
+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_BZIP2
+ bool "Enable -j option to handle .tar.bz2 files"
+ default y
+ depends on BUSYBOX_CONFIG_TAR
+ help
+ If you enable this option you'll be able to extract
+ archives compressed with bzip2.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_LZMA
+ bool "Enable -a option to handle .tar.lzma files"
+ default n
+ depends on BUSYBOX_CONFIG_TAR
+ help
+ If you enable this option you'll be able to extract
+ archives compressed with lzma.
+
+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_GZIP
+ bool "Enable -z option"
+ default y
+ depends on BUSYBOX_CONFIG_TAR
+ help
+ If you enable this option tar will be able to call gzip,
+ when creating or extracting tar gziped archives.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_COMPRESS
+ bool "Enable -Z option"
+ default n
+ depends on BUSYBOX_CONFIG_TAR
+ help
+ If you enable this option tar will be able to call uncompress,
+ when extracting .tar.Z archives.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY
+ bool "Enable support for old tar header format"
+ default n
+ depends on BUSYBOX_CONFIG_TAR
+ 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_GNU_EXTENSIONS
+ bool "Enable support for some GNU tar extensions"
+ default y
+ depends on BUSYBOX_CONFIG_TAR
+ 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_GETOPT_LONG
+ help
+ Enable use of long options, increases size by about 400 Bytes
+
+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 "Optimze unlzma for speed"
+ default n
+ depends on BUSYBOX_CONFIG_UNLZMA
+ help
+ This option reduces decompression time by about 33% at the cost of
+ a 2K bigger binary.
+
+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.
+
+comment "Common options for cpio and tar"
+ depends on BUSYBOX_CONFIG_CPIO || BUSYBOX_CONFIG_TAR
+
+config BUSYBOX_CONFIG_FEATURE_UNARCHIVE_TAPE
+ bool "Enable tape drive support"
+ default n
+ depends on BUSYBOX_CONFIG_CPIO || BUSYBOX_CONFIG_TAR
+ help
+ I don't think this is needed anymore.
+
+comment "Common options for dpkg and dpkg_deb"
+ depends on BUSYBOX_CONFIG_DPKG || BUSYBOX_CONFIG_DPKG_DEB
+
+config BUSYBOX_CONFIG_FEATURE_DEB_TAR_GZ
+ bool "gzip debian packages (normal)"
+ default n if BUSYBOX_CONFIG_DPKG || BUSYBOX_CONFIG_DPKG_DEB
+ depends on BUSYBOX_CONFIG_DPKG || BUSYBOX_CONFIG_DPKG_DEB
+ help
+ This is the default compression method inside the debian ar file.
+
+ If you want compatibility with standard .deb's you should say yes here.
+
+config BUSYBOX_CONFIG_FEATURE_DEB_TAR_BZ2
+ bool "bzip2 debian packages"
+ default n
+ depends on BUSYBOX_CONFIG_DPKG || BUSYBOX_CONFIG_DPKG_DEB
+ help
+ This allows dpkg and dpkg-deb to extract deb's that are compressed internally
+ with bzip2 instead of gzip.
+
+ You only want this if you are creating your own custom debian packages that
+ use an internal control.tar.bz2 or data.tar.bz2.
+
+config BUSYBOX_CONFIG_FEATURE_DEB_TAR_LZMA
+ bool "lzma debian packages"
+ default n
+ depends on BUSYBOX_CONFIG_DPKG || BUSYBOX_CONFIG_DPKG_DEB
+ help
+ This allows dpkg and dpkg-deb to extract deb's that are compressed
+ internally with lzma instead of gzip.
+
+ You only want this if you are creating your own custom debian
+ packages that use an internal control.tar.lzma or data.tar.lzma.
+
+endmenu
diff --git a/package/busybox/config/console-tools/Config.in b/package/busybox/config/console-tools/Config.in
new file mode 100644
index 0000000000..1efe300982
--- /dev/null
+++ b/package/busybox/config/console-tools/Config.in
@@ -0,0 +1,88 @@
+#
+# 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
+ help
+ This program is used to change to another terminal.
+ Example: chvt 4 (change to terminal /dev/tty4)
+
+config BUSYBOX_CONFIG_CLEAR
+ bool "clear"
+ default y
+ help
+ This program clears the terminal screen.
+
+config BUSYBOX_CONFIG_DEALLOCVT
+ bool "deallocvt"
+ default n
+ help
+ This program deallocates unused virtual consoles.
+
+config BUSYBOX_CONFIG_DUMPKMAP
+ bool "dumpkmap"
+ default n
+ 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_LOADFONT
+ bool "loadfont"
+ default n
+ help
+ This program loads a console font from standard input.
+
+config BUSYBOX_CONFIG_LOADKMAP
+ bool "loadkmap"
+ default n
+ help
+ This program loads a keyboard translation table from
+ standard input.
+
+config BUSYBOX_CONFIG_OPENVT
+ bool "openvt"
+ default n
+ 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_SETCONSOLE
+ bool "setconsole"
+ default n
+ 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_SET_CONSOLE && BUSYBOX_CONFIG_GETOPT_LONG
+ help
+ Support long options for the setconsole applet.
+
+config BUSYBOX_CONFIG_SETKEYCODES
+ bool "setkeycodes"
+ default n
+ 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
+ help
+ This program redirects the output console of kernel messages.
+
+endmenu
diff --git a/package/busybox/config/coreutils/Config.in b/package/busybox/config/coreutils/Config.in
new file mode 100644
index 0000000000..3487fc742c
--- /dev/null
+++ b/package/busybox/config/coreutils/Config.in
@@ -0,0 +1,775 @@
+#
+# 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_CAL
+ bool "cal"
+ default n
+ help
+ cal is used to display a monthly calender.
+
+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_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_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_CMP
+ bool "cmp"
+ default n
+ help
+ cmp is used to compare two files and returns the result
+ to standard output.
+
+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_CUT
+ bool "cut"
+ default y
+ help
+ cut is used to print selected parts of lines from
+ each file to stdout.
+
+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.
+
+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_IBS_OBS
+ bool "Enable ibs, obs and conv options"
+ default n
+ 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_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_BINARY
+ bool "Enable checks for binary files"
+ default n
+ depends on BUSYBOX_CONFIG_DIFF
+ help
+ This option enables support for checking for binary files
+ before a comparison is carried out.
+
+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_FEATURE_DIFF_MINIMAL
+ bool "Enable -d option to find smaller sets of changes"
+ default n
+ depends on BUSYBOX_CONFIG_DIFF
+ help
+ Enabling this option allows the use of -d to make diff
+ try hard to find the smallest possible set of changes.
+
+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
+ 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_GETOPT_LONG
+ help
+ Support long options for the env 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 n
+ 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_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_ID
+ bool "id"
+ default y
+ help
+ id displays the current user and group ID names.
+
+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_GETOPT_LONG
+ help
+ Support long options for the install applet.
+
+config BUSYBOX_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_GETOPT_LONG
+ 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_GETOPT_LONG
+ 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_GETOPT_LONG
+ help
+ Support long options for the mv applet.
+
+config BUSYBOX_CONFIG_NICE
+ bool "nice"
+ default n
+ 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_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_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_SLEEP
+ bool "sleep (single integer arg with no suffix)"
+ default y
+ help
+ sleep is used to pause for a specified number of seconds,
+
+config BUSYBOX_CONFIG_FEATURE_FANCY_SLEEP
+ bool "Enable multiple integer args and optional time suffixes"
+ default y
+ depends on BUSYBOX_CONFIG_SLEEP
+ help
+ Allow sleep to pause for specified minutes, hours, and days.
+
+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_STAT
+ bool "stat"
+ default n
+ 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_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, and -v)"
+ 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.
+
+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_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 n
+ depends on BUSYBOX_CONFIG_TEST
+ 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_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_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_WATCH
+ bool "watch"
+ default n
+ select BUSYBOX_CONFIG_DATE
+ help
+ watch is used to execute a program periodically, showing
+ output to the screen.
+
+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_WHO
+ bool "who"
+ default n
+ select BUSYBOX_CONFIG_FEATURE_UTMP
+ help
+ who is used to show who is logged on.
+
+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"
+ depends on BUSYBOX_CONFIG_MD5SUM || BUSYBOX_CONFIG_SHA1SUM
+
+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
+ 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 0000000000..bc98103c72
--- /dev/null
+++ b/package/busybox/config/debianutils/Config.in
@@ -0,0 +1,88 @@
+#
+# 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_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_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_GETOPT_LONG
+ help
+ Support long options for the run-parts applet.
+
+config BUSYBOX_CONFIG_START_STOP_DAEMON
+ bool "start-stop-daemon"
+ default n
+ 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
+
+config BUSYBOX_CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_START_STOP_DAEMON && BUSYBOX_CONFIG_GETOPT_LONG
+ 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 0000000000..e9ef3dc041
--- /dev/null
+++ b/package/busybox/config/e2fsprogs/Config.in
@@ -0,0 +1,67 @@
+#
+# 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 0000000000..3c1a320bc3
--- /dev/null
+++ b/package/busybox/config/editors/Config.in
@@ -0,0 +1,131 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Editors"
+
+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_MATH
+ 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_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_PATCH
+ bool "patch"
+ default n
+ help
+ Apply a unified diff formatted patch.
+
+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_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_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_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_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.
+
+endmenu
+
diff --git a/package/busybox/config/findutils/Config.in b/package/busybox/config/findutils/Config.in
new file mode 100644
index 0000000000..e708259888
--- /dev/null
+++ b/package/busybox/config/findutils/Config.in
@@ -0,0 +1,159 @@
+#
+# 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 option"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Causes output names to be separated by a null 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 modified time matching (-mtime) option"
+ 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 modified time matching (-min) option"
+ 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 permissions matching (-perm) option"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Enable searching based on file permissions.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_TYPE
+ bool "Enable filetype matching (-type) option"
+ 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 stay in filesystem (-xdev) option"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ This option will allow find to restrict searches to a single
+ filesystem.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_NEWER
+ bool "Enable -newer option for comparing file mtimes"
+ default n
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Support the 'find -newer' option for finding any files which have
+ a modified time that is more recent than the specified FILE.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_INUM
+ bool "Enable inode number matching (-inum) option"
+ 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) option allowing execution of 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_GREP
+ bool "grep"
+ default y
+ help
+ grep is used to search files for a specified pattern.
+
+config BUSYBOX_CONFIG_FEATURE_GREP_EGREP_ALIAS
+ bool "Support 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 is always builtin, 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 on
+ every item from standard input.
+
+config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION
+ bool "Enable prompt and confirmation option -p"
+ default y
+ depends on BUSYBOX_CONFIG_XARGS
+ help
+ Support prompt the user about whether to run each command
+ line and read a line from the terminal.
+
+config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_QUOTES
+ bool "Enable support single and double quotes and backslash"
+ default y
+ depends on BUSYBOX_CONFIG_XARGS
+ help
+ Default xargs unsupport single and double quotes
+ and backslash for can use aruments with spaces.
+
+config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT
+ bool "Enable support options -x"
+ default y
+ depends on BUSYBOX_CONFIG_XARGS
+ help
+ Enable support exit if the size (see the -s or -n option)
+ is exceeded.
+
+config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM
+ bool "Enable options -0"
+ default y
+ depends on BUSYBOX_CONFIG_XARGS
+ help
+ Enable input filenames are terminated by a null character
+ instead of by 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 0000000000..3696f7017f
--- /dev/null
+++ b/package/busybox/config/init/Config.in
@@ -0,0 +1,83 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Init Utilities"
+
+config BUSYBOX_CONFIG_INIT
+ bool "init"
+ default y
+ help
+ init is the first program run when the system boots.
+
+config BUSYBOX_CONFIG_DEBUG_INIT
+ bool "debugging aid"
+ default n
+ depends on BUSYBOX_CONFIG_INIT
+ help
+ Turn this on to disable all the dangerous
+ rebooting stuff when debugging.
+
+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_INIT_SCTTY
+ bool "Support running commands with a controlling-tty"
+ default n
+ depends on BUSYBOX_CONFIG_INIT
+ help
+ If this option is enabled a command starting with hyphen (-)
+ is run in its own session (setsid(2)) and possibly with a
+ controlling tty (TIOCSCTTY). 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.
+
+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_HALT
+ bool "poweroff, halt, and reboot"
+ default y
+ help
+ Stop all processes and either halt, reboot, or power off the system.
+
+config BUSYBOX_CONFIG_MESG
+ bool "mesg"
+ default y
+ help
+ Mesg controls access to your terminal by others. It is typically
+ used to allow or disallow other users to write to your terminal
+
+endmenu
diff --git a/package/busybox/config/libbb/Config.in b/package/busybox/config/libbb/Config.in
new file mode 100644
index 0000000000..7d84a75962
--- /dev/null
+++ b/package/busybox/config/libbb/Config.in
@@ -0,0 +1,22 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Busybox Library Tuning"
+
+config BUSYBOX_CONFIG_MD5_SIZE_VS_SPEED
+ int " MD5: Trade Bytes for Speed"
+ 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
+
+endmenu
diff --git a/package/busybox/config/loginutils/Config.in b/package/busybox/config/loginutils/Config.in
new file mode 100644
index 0000000000..33a764e35c
--- /dev/null
+++ b/package/busybox/config/loginutils/Config.in
@@ -0,0 +1,163 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Login/Password Management Utilities"
+
+config BUSYBOX_CONFIG_FEATURE_SHADOWPASSWDS
+ bool "Support for shadow passwords"
+ default n
+ 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_SHADOW
+ bool #" Use busybox 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_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 enable this option, it will add about 1.5k to busybox.
+
+config BUSYBOX_CONFIG_ADDGROUP
+ bool "addgroup"
+ default n
+ help
+ Utility for creating a new group account.
+
+config BUSYBOX_CONFIG_DELGROUP
+ bool "delgroup"
+ default n
+ help
+ Utility for deleting a group account.
+
+config BUSYBOX_CONFIG_ADDUSER
+ bool "adduser"
+ default n
+ help
+ Utility for creating a new user account.
+
+config BUSYBOX_CONFIG_DELUSER
+ bool "deluser"
+ default n
+ help
+ Utility for deleting a user account.
+
+config BUSYBOX_CONFIG_GETTY
+ bool "getty"
+ default n
+ help
+ getty lets you log in on a tty, it is normally invoked by init.
+
+config BUSYBOX_CONFIG_FEATURE_UTMP
+ bool "Support utmp file"
+ depends on BUSYBOX_CONFIG_GETTY || BUSYBOX_CONFIG_LOGIN || BUSYBOX_CONFIG_SU || BUSYBOX_CONFIG_WHO
+ default n
+ help
+ The file /var/run/utmp is used to track who is currently logged in.
+
+config BUSYBOX_CONFIG_FEATURE_WTMP
+ bool "Support wtmp file"
+ depends on BUSYBOX_CONFIG_GETTY || BUSYBOX_CONFIG_LOGIN || BUSYBOX_CONFIG_SU || BUSYBOX_CONFIG_LAST
+ default n
+ select BUSYBOX_CONFIG_FEATURE_UTMP
+ help
+ The file /var/run/wtmp is used to track when user's have logged into
+ and logged out of the system.
+
+config BUSYBOX_CONFIG_LOGIN
+ bool "login"
+ default n
+ select BUSYBOX_CONFIG_FEATURE_SUID
+ 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_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_SUID
+ 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_SU
+ bool "su"
+ default n
+ select BUSYBOX_CONFIG_FEATURE_SUID
+ 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_SULOGIN
+ bool "sulogin"
+ default n
+ 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
+ select BUSYBOX_CONFIG_FEATURE_SUID
+ 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/miscutils/Config.in b/package/busybox/config/miscutils/Config.in
new file mode 100644
index 0000000000..407503dc40
--- /dev/null
+++ b/package/busybox/config/miscutils/Config.in
@@ -0,0 +1,346 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Miscellaneous Utilities"
+
+config BUSYBOX_CONFIG_ADJTIMEX
+ bool "adjtimex"
+ default n
+ 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_CROND
+ bool "crond"
+ default y
+ select BUSYBOX_CONFIG_FEATURE_SUID
+ 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
+ Note that Busybox binary must be setuid root for this applet to
+ work properly.
+
+config BUSYBOX_CONFIG_DEBUG_CROND_OPTION
+ bool "Support debug option -d"
+ depends on BUSYBOX_CONFIG_CROND
+ default n
+ help
+ Support option -d to enter debug mode.
+
+config BUSYBOX_CONFIG_FEATURE_CROND_CALL_SENDMAIL
+ bool "Using /usr/sbin/sendmail?"
+ default n
+ depends on BUSYBOX_CONFIG_CROND
+ help
+ Support calling /usr/sbin/sendmail for send cmd outputs.
+
+config BUSYBOX_CONFIG_CRONTAB
+ bool "crontab"
+ default y
+ select BUSYBOX_CONFIG_FEATURE_SUID
+ help
+ Crontab manipulates the crontab for a particular user. Only
+ the superuser may specify a different user and/or crontab directory.
+
+config BUSYBOX_CONFIG_DC
+ bool "dc"
+ default n
+ help
+ Dc is a reverse-polish desk calculator which supports unlimited
+ precision arithmetic.
+
+config BUSYBOX_CONFIG_DEVFSD
+ bool "devfsd (obsolete)"
+ default n
+ help
+ This is deprecated, and will be going away in a future release.
+
+ 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 y
+ help
+ 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.
+
+ This is obsolete and will be going away someday. Consider it
+ deprecated.
+
+config BUSYBOX_CONFIG_EJECT
+ bool "eject"
+ default n
+ help
+ Used to eject cdroms. (defaults to /dev/cdrom)
+
+config BUSYBOX_CONFIG_LAST
+ bool "last"
+ default n
+ select BUSYBOX_CONFIG_FEATURE_WTMP
+ help
+ 'last' displays a list of the last users that logged into the system.
+
+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_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_FLAGCS
+ bool "Enable flag changes"
+ default n
+ depends on BUSYBOX_CONFIG_LESS
+ help
+ This enables the ability to change command-line flags within
+ less itself.
+
+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_HDPARM
+ bool "hdparm"
+ default n
+ help
+ Get/Set hard drive parameters. Primarily intended for ATA
+ drives. Adds about 13k (or around 30k if you enable the
+ BUSYBOX_CONFIG_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 (DANGEROUS)"
+ default n
+ depends on BUSYBOX_CONFIG_HDPARM
+ help
+ Enables the 'hdparm -d' option to get/set using_dma flag.
+ This is dangerous stuff, so you should probably say N.
+
+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 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_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_RUNLEVEL
+ bool "runlevel"
+ default n
+ 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
+ help
+ Receive files using the Xmodem protocol.
+
+config BUSYBOX_CONFIG_STRINGS
+ bool "strings"
+ default y
+ help
+ strings prints the printable character sequences for each file
+ specified.
+
+config BUSYBOX_CONFIG_SETSID
+ bool "setsid"
+ default n
+ help
+ setsid runs a program in a new session
+
+config BUSYBOX_CONFIG_TASKSET
+ bool "taskset"
+ default n
+ help
+ Retrieve or set a processes's CPU affinity
+
+config BUSYBOX_CONFIG_TASKSET
+ bool "taskset"
+ default n
+ help
+ Retrieve or set a processes's CPU affinity (on linux)
+
+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_WATCHDOG
+ bool "watchdog"
+ default y
+ 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 0000000000..4441632e85
--- /dev/null
+++ b/package/busybox/config/modutils/Config.in
@@ -0,0 +1,147 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Linux Module Utilities"
+
+config BUSYBOX_CONFIG_INSMOD
+ bool "insmod"
+ default y
+ help
+ insmod is used to load specified modules in the running kernel.
+
+config BUSYBOX_CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+ bool "Module version checking"
+ default n
+ depends on BUSYBOX_CONFIG_INSMOD && BUSYBOX_CONFIG_FEATURE_2_4_MODULES
+ 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_INSMOD && BUSYBOX_CONFIG_FEATURE_2_4_MODULES
+ 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 properly 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_INSMOD && BUSYBOX_CONFIG_FEATURE_2_4_MODULES
+ 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 load map (-m) option"
+ default n
+ depends on BUSYBOX_CONFIG_INSMOD && BUSYBOX_CONFIG_FEATURE_2_4_MODULES
+ 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
+ help
+ Without this option, -m will only output section
+ load map. With this option, -m will also output
+ symbols load map.
+
+config BUSYBOX_CONFIG_RMMOD
+ bool "rmmod"
+ default y
+ help
+ rmmod is used to unload specified modules from the kernel.
+
+config BUSYBOX_CONFIG_LSMOD
+ bool "lsmod"
+ default y
+ help
+ lsmod is used to display a list of loaded modules.
+
+config BUSYBOX_CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT
+ bool "lsmod pretty output for 2.6.x Linux kernels "
+ default n
+ depends on BUSYBOX_CONFIG_LSMOD
+ help
+ This option makes output format of lsmod adjusted to
+ the format of module-init-tools for Linux kernel 2.6.
+
+config BUSYBOX_CONFIG_MODPROBE
+ bool "modprobe"
+ default n
+ help
+ Handle the loading of modules, and their dependencies on a high
+ level.
+
+ Note that in the state, modprobe does not understand multiple
+ module options from the configuration file. See option below.
+
+config BUSYBOX_CONFIG_FEATURE_MODPROBE_MULTIPLE_OPTIONS
+ bool "Multiple options parsing"
+ default n
+ depends on BUSYBOX_CONFIG_MODPROBE
+ help
+ Allow modprobe to understand more than one option to pass to
+ modules.
+
+ This is a WIP, while waiting for a common argument parsing
+ common amongst all BB applets (shell, modprobe, etc...) and
+ adds around 600 bytes on x86, 700 bytes on ARM. The code is
+ biggish and uggly, but just works.
+
+ Saying Y here is not a bad idea if you're not that short
+ on storage capacity.
+
+comment "Options common to multiple modutils"
+ depends on BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_RMMOD || BUSYBOX_CONFIG_MODPROBE || BUSYBOX_CONFIG_LSMOD
+
+config BUSYBOX_CONFIG_FEATURE_CHECK_TAINTED_MODULE
+ # Simulate indentation
+ bool "Support tainted module checking with new kernels"
+ default y
+ depends on BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_LSMOD
+ 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_2_4_MODULES
+ # Simulate indentation
+ bool "Support version 2.2.x to 2.4.x Linux kernels"
+ default y
+ depends on BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_RMMOD
+ help
+ Support module loading for 2.2.x and 2.4.x Linux kernels.
+
+config BUSYBOX_CONFIG_FEATURE_2_6_MODULES
+ # Simulate indentation
+ bool "Support version 2.6.x Linux kernels"
+ default y
+ depends on BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_RMMOD || BUSYBOX_CONFIG_MODPROBE
+ help
+ Support module loading for newer 2.6.x Linux kernels.
+
+
+config BUSYBOX_CONFIG_FEATURE_QUERY_MODULE_INTERFACE
+ bool
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_2_4_MODULES && !CONFIG_FEATURE_2_6_MODULES
+
+
+endmenu
+
diff --git a/package/busybox/config/networking/Config.in b/package/busybox/config/networking/Config.in
new file mode 100644
index 0000000000..3e0cbc95d4
--- /dev/null
+++ b/package/busybox/config/networking/Config.in
@@ -0,0 +1,710 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Networking Utilities"
+
+config BUSYBOX_CONFIG_FEATURE_IPV6
+ bool "Enable IPv6 support"
+ default y
+ help
+ Enable IPv6 support in busybox.
+ This adds IPv6 support in the networking applets.
+
+config BUSYBOX_CONFIG_ARPING
+ bool "arping"
+ default y
+ help
+ Ping hosts by ARP packets
+
+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
+ help
+ Send a magic packet to wake up sleeping machines.
+
+config BUSYBOX_CONFIG_FAKEIDENTD
+ bool "fakeidentd"
+ default n
+ help
+ fakeidentd listens on the ident port and returns a predefined
+ fake value on any query.
+
+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_GETOPT_LONG && (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 y
+ help
+ Serve web pages via an HTTP server.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+ bool "Support using httpd as a daemon (not from inetd)"
+ default y
+ depends on BUSYBOX_CONFIG_HTTPD
+ help
+ This option enables uid and port options for the httpd applet,
+ and eliminates the need to be called from the inetd server daemon.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
+ bool "Support reloading the global config file using hup signal"
+ default n
+ depends on BUSYBOX_CONFIG_HTTPD && BUSYBOX_CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+ help
+ This option enables processing of SIGHUP to reload cached
+ configuration settings.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_SETUID
+ bool "Enable support -u <user> option"
+ default n
+ depends on BUSYBOX_CONFIG_HTTPD && BUSYBOX_CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+ 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 y
+ 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 y
+ 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_CONFIG_WITH_MIME_TYPES
+ bool "Support loading additional MIME types at run-time"
+ default y
+ depends on BUSYBOX_CONFIG_HTTPD
+ help
+ This option enables support for additional MIME types at
+ run-time to be specified in the configuration file.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_CGI
+ bool "Support Common Gateway Interface (CGI)"
+ default y
+ 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 "Enable 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 addition line in your httpd
+ config file:
+ *.php:/path/to/your/php
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
+ bool "Support the REMOTE_PORT environment variable for CGI"
+ default y
+ 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 the -e option for shell script CGI simplification."
+ default y
+ depends on BUSYBOX_CONFIG_HTTPD
+ help
+ This option allows html encoding arbitrary
+ strings for display of the browser. Output goes to stdout.
+ For example, httpd -e "<Hello World>" as
+ "&#60Hello&#32World&#62".
+
+config BUSYBOX_CONFIG_IFCONFIG
+ bool "ifconfig"
+ default y
+ 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_IFUPDOWN
+ bool "ifupdown"
+ default n
+ select BUSYBOX_CONFIG_RUN_PARTS
+ 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 BUSYBOX_CONFIG_IFCONFIG and BUSYBOX_CONFIG_ROUTE, or enable
+ BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IP and the various BUSYBOX_CONFIG_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" and "route" or the "ip" command, either via busybox or via
+ standalone utilities.
+
+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_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 leave this disabled, you must install the full-blown iproute2
+ utility or the "ifup" and "ifdown" applets will not work.
+
+config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN
+ bool "Use busybox ifconfig and route applets"
+ default n
+ depends on BUSYBOX_CONFIG_IFUPDOWN && !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 leave this 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 "Enable support for IPv4"
+ default n
+ depends on BUSYBOX_CONFIG_IFUPDOWN
+ help
+ If you want busybox to talk IPv4, leave this on.
+
+config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IPV6
+ bool "Enable 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.
+
+config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IPX
+ bool "Enable support for IPX"
+ default n
+ depends on BUSYBOX_CONFIG_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_INETD
+ bool "inetd"
+ default n
+ 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
+ help
+ Suuport Sun-RPC based services
+
+
+config BUSYBOX_CONFIG_IP
+ bool "ip"
+ default n
+ 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_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
+
+ Say N unless you desparately need the short form of the ip
+ object commands.
+
+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_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_GETOPT_LONG
+ help
+ Support long options for the ipcalc applet.
+
+config BUSYBOX_CONFIG_NAMEIF
+ bool "nameif"
+ default n
+ 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: IF_NAMESIZE = 16
+ File fields are separated by space or tab.
+ File format:
+ # Comment
+ new_interface_name XX:XX:XX:XX:XX:XX
+
+config BUSYBOX_CONFIG_NC
+ bool "nc"
+ default y
+ help
+ A simple Unix utility which reads and writes data across network
+ connections.
+
+config BUSYBOX_CONFIG_NETMSG
+ bool "netmsg"
+ default y
+ help
+ simple program for sending udp broadcast messages
+
+config BUSYBOX_CONFIG_NC_GAPING_SECURITY_HOLE
+ bool "gaping security hole"
+ default n
+ depends on BUSYBOX_CONFIG_NC
+ help
+ Add support for executing a program after making or receiving a
+ successful connection (-e option).
+
+config BUSYBOX_CONFIG_NETSTAT
+ bool "netstat"
+ default y
+ help
+ netstat prints information about the Linux networking subsystem.
+
+config BUSYBOX_CONFIG_NSLOOKUP
+ bool "nslookup"
+ default y
+ help
+ nslookup is a tool to query Internet name servers.
+
+config BUSYBOX_CONFIG_PING
+ bool "ping"
+ default y
+ 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_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_PING6
+ bool "ping6"
+ default y
+ depends on BUSYBOX_CONFIG_FEATURE_IPV6
+ help
+ This will give you a ping that can talk IPv6.
+
+config BUSYBOX_CONFIG_FEATURE_FANCY_PING6
+ bool "Enable fancy ping6 output"
+ default y
+ depends on BUSYBOX_CONFIG_PING6
+ help
+ Make the output from the ping6 applet include statistics, and at the
+ same time provide full support for ICMP packets.
+
+config BUSYBOX_CONFIG_ROUTE
+ bool "route"
+ default y
+ help
+ Route displays or manipulates the kernel's IP routing tables.
+
+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
+ 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:
+ BUSYBOX_CONFIG_UNIX98_PTYS=y
+ BUSYBOX_CONFIG_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 BUSYBOX_CONFIG_LOGIN and
+ BUSYBOX_CONFIG_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_INETD
+ bool "Support call from inetd only"
+ default n
+ depends on BUSYBOX_CONFIG_TELNETD
+ help
+ Selecting this will make telnetd only callable from inetd,
+ removing the standalone support.
+
+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_FEATURE_TFTP_GET
+ bool "Enable \"get\" command"
+ default n
+ depends on BUSYBOX_CONFIG_TFTP
+ help
+ Add support for the GET command within the TFTP client. This allows
+ a client to retrieve a file from a TFTP server.
+
+config BUSYBOX_CONFIG_FEATURE_TFTP_PUT
+ bool "Enable \"put\" command"
+ default n
+ depends on BUSYBOX_CONFIG_TFTP
+ help
+ Add support for the PUT command within the TFTP client. This allows
+ a client to transfer a file to a TFTP server.
+
+config BUSYBOX_CONFIG_FEATURE_TFTP_BLOCKSIZE
+ bool "Enable \"blocksize\" command"
+ default n
+ depends on BUSYBOX_CONFIG_TFTP
+ help
+ Allow the client to specify the desired block size for transfers.
+
+config BUSYBOX_CONFIG_DEBUG_TFTP
+ bool "Enable debug"
+ default n
+ depends on BUSYBOX_CONFIG_TFTP
+ help
+ Enable debug settings for tftp. This is useful if you're running
+ into problems with tftp as the protocol doesn't help you much when
+ you run into problems.
+
+config BUSYBOX_CONFIG_TRACEROUTE
+ bool "traceroute"
+ default y
+ help
+ Utility to trace the route of IP 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 amongst 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 feature to allow for ICMP ECHO instead of UDP datagrams.
+
+source package/busybox/config/networking/udhcp/Config.in
+
+config BUSYBOX_CONFIG_VCONFIG
+ bool "vconfig"
+ default y
+ 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_IP6_LITERAL
+ bool "Enable IPv6 literal addresses"
+ default y
+ depends on BUSYBOX_CONFIG_WGET && BUSYBOX_CONFIG_FEATURE_IPV6
+ help
+ Support IPv6 address literal notation in URLs.
+
+config BUSYBOX_CONFIG_FEATURE_WGET_LONG_OPTIONS
+ bool "Enable long options"
+ default y
+ depends on BUSYBOX_CONFIG_WGET && BUSYBOX_CONFIG_GETOPT_LONG
+ help
+ Support long options for the wget applet.
+
+config BUSYBOX_CONFIG_ZCIP
+ bool "zcip"
+ default n
+ 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 0000000000..741afa3279
--- /dev/null
+++ b/package/busybox/config/networking/udhcp/Config.in
@@ -0,0 +1,62 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "udhcp Server/Client"
+
+config BUSYBOX_CONFIG_APP_UDHCPD
+ bool "udhcp Server (udhcpd)"
+ default n
+ help
+ uDHCPd is a DHCP server geared primarily toward embedded systems,
+ while striving to be fully functional and RFC compliant.
+
+ See http://udhcp.busybox.net for further details.
+
+config BUSYBOX_CONFIG_APP_UDHCPC
+ bool "udhcp Client (udhcpc)"
+ default y
+ 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
+ notifies a set of scripts when a lease is obtained or lost.
+
+ See http://udhcp.busybox.net for further details.
+
+config BUSYBOX_CONFIG_APP_DUMPLEASES
+ bool "Lease display utility (dumpleases)"
+ default n
+ depends on BUSYBOX_CONFIG_APP_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.
+
+ See http://udhcp.busybox.net for further details.
+
+config BUSYBOX_CONFIG_FEATURE_UDHCP_SYSLOG
+ bool " Log udhcp messages to syslog (instead of stdout)"
+ default n
+ depends on BUSYBOX_CONFIG_APP_UDHCPD || BUSYBOX_CONFIG_APP_UDHCPC
+ help
+ If selected, udhcpd will log all its messages to syslog, otherwise,
+ it will attempt to log them to stdout.
+
+ See http://udhcp.busybox.net for further details.
+
+config BUSYBOX_CONFIG_FEATURE_UDHCP_DEBUG
+ bool " Compile udhcp with noisy debugging messages"
+ default n
+ depends on BUSYBOX_CONFIG_APP_UDHCPD || BUSYBOX_CONFIG_APP_UDHCPC
+ help
+ If selected, udhcpd will output extra debugging output. If using
+ this option, compile uDHCP with "-g", and do not fork the daemon to
+ the background.
+
+ See http://udhcp.busybox.net for further details.
+
+endmenu
+
diff --git a/package/busybox/config/procps/Config.in b/package/busybox/config/procps/Config.in
new file mode 100644
index 0000000000..34d1ace087
--- /dev/null
+++ b/package/busybox/config/procps/Config.in
@@ -0,0 +1,121 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Process Utilities"
+
+config BUSYBOX_CONFIG_FREE
+ bool "free"
+ default y
+ 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 y
+ depends on BUSYBOX_CONFIG_KILL
+
+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_PS
+ bool "ps"
+ default y
+ help
+ ps gives a snapshot of the current processes.
+
+config BUSYBOX_CONFIG_FEATURE_PS_WIDE
+ bool "Enable argument for wide output (-w)"
+ default n
+ depends on BUSYBOX_CONFIG_PS
+ help
+ Support argument 'w' for wide output.
+ If given once, 132 chars are printed and given more than
+ one, the length is unlimited.
+
+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 "Support showing CPU usage percentage (add 2k bytes)"
+ default y
+ depends on BUSYBOX_CONFIG_TOP
+ help
+ Make top display CPU usage.
+
+config BUSYBOX_CONFIG_UPTIME
+ bool "uptime"
+ default y
+ 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.
+
+
+endmenu
+
diff --git a/package/busybox/config/shell/Config.in b/package/busybox/config/shell/Config.in
new file mode 100644
index 0000000000..373c7461a4
--- /dev/null
+++ b/package/busybox/config/shell/Config.in
@@ -0,0 +1,294 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Shells"
+
+choice
+ prompt "Choose your default shell"
+ default BUSYBOX_CONFIG_FEATURE_SH_IS_ASH
+ help
+ Choose a shell. The ash shell is the most bash compatible
+ and full featured one.
+
+config BUSYBOX_CONFIG_FEATURE_SH_IS_ASH
+ select BUSYBOX_CONFIG_ASH
+ bool "ash"
+
+config BUSYBOX_CONFIG_FEATURE_SH_IS_HUSH
+ select BUSYBOX_CONFIG_HUSH
+ bool "hush"
+
+config BUSYBOX_CONFIG_FEATURE_SH_IS_LASH
+ select BUSYBOX_CONFIG_LASH
+ bool "lash"
+
+config BUSYBOX_CONFIG_FEATURE_SH_IS_MSH
+ select BUSYBOX_CONFIG_MSH
+ bool "msh"
+
+config BUSYBOX_CONFIG_FEATURE_SH_IS_NONE
+ bool "none"
+
+endchoice
+
+config BUSYBOX_CONFIG_ASH
+ bool "ash"
+ default y
+ select BUSYBOX_CONFIG_TEST
+ 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.
+
+comment "Ash Shell Options"
+ depends on BUSYBOX_CONFIG_ASH
+
+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_READ_NCHARS
+ bool "'read -n N' and 'read -s' support"
+ default n
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ 'read -n N' will return a value after N characters have been read.
+ 'read -s' will read without echoing the user's input.
+
+config BUSYBOX_CONFIG_ASH_READ_TIMEOUT
+ bool "'read -t S' support."
+ default y
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ 'read -t S' will return a value after S seconds have passed.
+ This implementation will allow fractional seconds, expressed
+ as a decimal fraction, e.g. 'read -t 2.5 foo'.
+
+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_MATH_SUPPORT
+ bool "Posix math support"
+ default y
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ Enable math support in the ash shell.
+
+config BUSYBOX_CONFIG_ASH_MATH_SUPPORT_64
+ bool "Extend Posix math support to 64 bit"
+ default n
+ depends on BUSYBOX_CONFIG_ASH_MATH_SUPPORT
+ help
+ Enable 64-bit math support in the ash shell. This will make
+ the shell slightly larger, but will allow computation with very
+ large numbers.
+
+config BUSYBOX_CONFIG_ASH_GETOPTS
+ bool "Builtin getopt to parse positional parameters"
+ default y
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ Enable getopts builtin in the ash shell.
+
+config BUSYBOX_CONFIG_ASH_BUILTIN_ECHO
+ bool "Builtin version of 'echo'"
+ default y
+ select BUSYBOX_CONFIG_ECHO
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ Enable support for echo, built in to ash.
+
+config BUSYBOX_CONFIG_ASH_BUILTIN_TEST
+ bool "Builtin version of 'test'"
+ default y
+ select BUSYBOX_CONFIG_TEST
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ Enable support for test, built in to 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" in the ash shell.
+
+config BUSYBOX_CONFIG_ASH_OPTIMIZE_FOR_SIZE
+ bool "Optimize for size instead of speed"
+ default y
+ 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 variable $RANDOM"
+ 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" then generator will switch off and this
+ variable will no longer have special treatment.
+
+config BUSYBOX_CONFIG_ASH_EXPAND_PRMT
+ bool "Expand prompt string"
+ default n
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ "PS#" may be 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_HUSH
+ bool "hush"
+ default n
+ select BUSYBOX_CONFIG_TRUE
+ select BUSYBOX_CONFIG_FALSE
+ select BUSYBOX_CONFIG_TEST
+ help
+ hush is a very small shell (just 18k) and it has fairly complete
+ Bourne shell grammar. It even handles all the normal flow control
+ options such as if/then/elif/else/fi, for/in/do/done, while loops,
+ etc.
+
+ It does not handle case/esac, select, function, here documents ( <<
+ word ), arithmetic expansion, aliases, brace expansion, tilde
+ expansion, &> and >& redirection of stdout+stderr, etc.
+
+
+config BUSYBOX_CONFIG_LASH
+ bool "lash"
+ default n
+ select BUSYBOX_CONFIG_TRUE
+ select BUSYBOX_CONFIG_FALSE
+ select BUSYBOX_CONFIG_TEST
+ help
+ lash is the very smallest shell (adds just 10k) and it is quite
+ usable as a command prompt, but it is not suitable for any but the
+ most trivial scripting (such as an initrd that calls insmod a few
+ times) since it does not understand any Bourne shell grammar. It
+ does handle pipes, redirects, and job control though. Adding in
+ command editing makes it a very nice lightweight command prompt.
+
+
+config BUSYBOX_CONFIG_MSH
+ bool "msh"
+ default n
+ select BUSYBOX_CONFIG_TRUE
+ select BUSYBOX_CONFIG_FALSE
+ select BUSYBOX_CONFIG_TEST
+ help
+ The minix shell (adds just 30k) is quite complete and handles things
+ like for/do/done, case/esac and all the things you expect a Bourne
+ shell to do. It is not always pedantically correct about Bourne
+ shell grammar (try running the shell testscript "tests/sh.testcases"
+ on it and compare vs bash) but for most things it works quite well.
+ It also uses only vfork, so it can be used on uClinux systems.
+
+comment "Bourne Shell Options"
+ depends on BUSYBOX_CONFIG_MSH || BUSYBOX_CONFIG_LASH || BUSYBOX_CONFIG_HUSH || BUSYBOX_CONFIG_ASH
+
+config BUSYBOX_CONFIG_FEATURE_SH_EXTRA_QUIET
+ bool "Hide message on interactive shell startup"
+ default n
+ depends on BUSYBOX_CONFIG_MSH || BUSYBOX_CONFIG_LASH || BUSYBOX_CONFIG_HUSH || BUSYBOX_CONFIG_ASH
+ help
+ Remove the busybox introduction when starting a shell.
+
+config BUSYBOX_CONFIG_FEATURE_SH_STANDALONE_SHELL
+ bool "Standalone shell"
+ default n
+ depends on BUSYBOX_CONFIG_MSH || BUSYBOX_CONFIG_LASH || BUSYBOX_CONFIG_HUSH || BUSYBOX_CONFIG_ASH
+ help
+ This option causes the selected busybox shell 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.
+
+ 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.
+
+ 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_COMMAND_EDITING
+ bool "Command line editing"
+ default y
+ depends on BUSYBOX_CONFIG_MSH || BUSYBOX_CONFIG_LASH || BUSYBOX_CONFIG_HUSH || BUSYBOX_CONFIG_ASH
+ help
+ Enable command editing in shell.
+
+config BUSYBOX_CONFIG_FEATURE_COMMAND_EDITING_VI
+ bool "vi-style line editing commands"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_COMMAND_EDITING
+ help
+ Enable vi-style line editing in the shell. This mode can be
+ turned on and off with "set -o vi" and "set +o vi".
+
+config BUSYBOX_CONFIG_FEATURE_COMMAND_HISTORY
+ int "History size"
+ default 15
+ depends on BUSYBOX_CONFIG_FEATURE_COMMAND_EDITING
+ help
+ Specify command history size in shell.
+
+config BUSYBOX_CONFIG_FEATURE_COMMAND_SAVEHISTORY
+ bool "History saving"
+ default n
+ depends on BUSYBOX_CONFIG_ASH && BUSYBOX_CONFIG_FEATURE_COMMAND_EDITING
+ help
+ Enable history saving in ash shell.
+
+config BUSYBOX_CONFIG_FEATURE_COMMAND_TAB_COMPLETION
+ bool "Tab completion"
+ default y
+ depends on BUSYBOX_CONFIG_FEATURE_COMMAND_EDITING
+ help
+ Enable tab completion in shell.
+
+config BUSYBOX_CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION
+ bool "Username completion"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_COMMAND_TAB_COMPLETION
+ help
+ Enable username completion in shell.
+
+config BUSYBOX_CONFIG_FEATURE_SH_FANCY_PROMPT
+ bool "Fancy shell prompts"
+ default y
+ depends on BUSYBOX_CONFIG_FEATURE_COMMAND_EDITING
+ help
+ Setting this option allows for prompts to use things like \w and
+ \$ and also using escape codes.
+
+endmenu
diff --git a/package/busybox/config/sysklogd/Config.in b/package/busybox/config/sysklogd/Config.in
new file mode 100644
index 0000000000..f120695664
--- /dev/null
+++ b/package/busybox/config/sysklogd/Config.in
@@ -0,0 +1,109 @@
+#
+# 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_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
+ 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 "logread 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
+ depends on BUSYBOX_CONFIG_SYSLOGD
+ 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_LOGGER
+ bool "logger"
+ default y
+ 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 0000000000..b7a8ae91f5
--- /dev/null
+++ b/package/busybox/config/util-linux/Config.in
@@ -0,0 +1,480 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Linux System Utilities"
+
+config BUSYBOX_CONFIG_DMESG
+ bool "dmesg"
+ default y
+ 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_FBSET
+ bool "fbset"
+ default n
+ 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
+ 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
+ help
+ fdformat is used to low-level format a floppy disk.
+
+config BUSYBOX_CONFIG_FDISK
+ bool "fdisk"
+ default n
+ 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_FDISK_SUPPORT_LARGE_DISKS
+ bool
+ default y
+ depends on BUSYBOX_CONFIG_FDISK
+ 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_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_FREERAMDISK
+ bool "freeramdisk"
+ default n
+ 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_MINIX
+ bool "mkfs_minix"
+ default n
+ 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.
+
+comment "Minix filesystem support"
+ depends on BUSYBOX_CONFIG_FSCK_MINIX || BUSYBOX_CONFIG_MKFS_MINIX
+
+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_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_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_HWCLOCK
+ bool "hwclock"
+ default n
+ 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_GETOPT_LONG
+ 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
+ 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.
+
+ http://www.pathname.com/fhs/pub/fhs-2.3.html#VARLIBHWCLOCKSTATEDIRECTORYFORHWCLO
+
+config BUSYBOX_CONFIG_IPCRM
+ bool "ipcrm"
+ default n
+ select BUSYBOX_CONFIG_FEATURE_SUID
+ 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_FEATURE_SUID
+ 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
+ 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_MDEV
+ bool "mdev"
+ default n
+ help
+ mdev is a mini-udev implementation: call it with -s to populate
+ /dev from /sys, then "echo /sbin/mdev > /proc/sys/kernel/hotplug" to
+ have it handle hotplug events afterwards. Device names are taken
+ from sysfs.
+
+config BUSYBOX_CONFIG_FEATURE_MDEV_CONF
+ bool "Support /etc/mdev.conf"
+ default n
+ depends on BUSYBOX_CONFIG_MDEV
+ help
+ The mdev config file contains lines that look like:
+
+ hd[a-z][0-9]* 0:3 660
+
+ That's device name (with regex match), uid:gid, and permissions.
+
+ Config file parsing stops on the first matching line. If no config
+ entry is matched, devices are created with default 0:0 660. (Make
+ the last line match .* to override this.)
+
+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, consisting
+ of a special character and a command line to run after creating the
+ corresponding device(s) and before removing, ala:
+
+ hdc root:cdrom 660 *ln -s $MDEV cdrom
+
+ The $MDEV environment variable is set to the name of the device.
+
+ The special characters and their meanings are:
+ @ Run after creating the device.
+ $ Run before removing the device.
+ * Run both after creating and before removing the device.
+
+ Commands are executed via system() so you need /bin/sh, meaning you
+ probably want to select a default shell in the Shells menu.
+
+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_V0
+ bool "version 0 support"
+ default n
+ depends on BUSYBOX_CONFIG_MKSWAP
+# depends on BUSYBOX_CONFIG_MKSWAP && BUSYBOX_CONFIG_DEPRECATED
+ help
+ Enable support for the old v0 style.
+ If your kernel is older than 2.1.117, then v0 support is the
+ only option.
+
+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_FEATURE_USE_TERMIOS
+ bool "Use termios to manipulate the screen"
+ default y
+ depends on BUSYBOX_CONFIG_MORE
+ 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_MOUNT
+ bool "mount"
+ default y
+ 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_NFS
+ bool "Support mounting NFS file systems"
+ default y
+ depends on BUSYBOX_CONFIG_MOUNT
+ help
+ Enable mounting of NFS file systems.
+
+config BUSYBOX_CONFIG_PIVOT_ROOT
+ bool "pivot_root"
+ default y
+ 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 y
+ 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_READPROFILE
+ bool "readprofile"
+ default n
+ help
+ This allows you to parse /proc/profile for basic profiling.
+
+config BUSYBOX_CONFIG_SETARCH
+ bool "setarch"
+ default n
+ 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
+ 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_SWITCH_ROOT
+ bool "switch_root"
+ default y
+ 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
+ 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 "umount -a option"
+ 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_MTAB_SUPPORT
+ bool "Support for the old /etc/mtab file"
+ default n
+ depends on BUSYBOX_CONFIG_MOUNT || BUSYBOX_CONFIG_UMOUNT
+ 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 writeable, 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.
+
+endmenu
+
diff --git a/package/busybox/patches/001-wget_long_options.patch b/package/busybox/patches/001-wget_long_options.patch
new file mode 100644
index 0000000000..9538427e3e
--- /dev/null
+++ b/package/busybox/patches/001-wget_long_options.patch
@@ -0,0 +1,22 @@
+Index: busybox-CURRENT/networking/wget.c
+===================================================================
+--- busybox-CURRENT/networking/wget.c (revision 15806)
++++ busybox-CURRENT/networking/wget.c (working copy)
+@@ -133,7 +133,7 @@
+ #define WGET_OPT_PREFIX 32
+ #define WGET_OPT_PROXY 64
+
+-#if ENABLE_WGET_LONG_OPTIONS
++#if CONFIG_FEATURE_WGET_LONG_OPTIONS
+ static const struct option wget_long_options[] = {
+ { "continue", 0, NULL, 'c' },
+ { "quiet", 0, NULL, 'q' },
+@@ -177,7 +177,7 @@
+ * Crack command line.
+ */
+ bb_opt_complementally = "-1:\203::";
+-#if ENABLE_WGET_LONG_OPTIONS
++#if CONFIG_FEATURE_WGET_LONG_OPTIONS
+ bb_applet_long_options = wget_long_options;
+ #endif
+ opt = bb_getopt_ulflags(argc, argv, "cq\213O:\203:P:Y:",
diff --git a/package/busybox/patches/100-killall5.patch b/package/busybox/patches/100-killall5.patch
new file mode 100644
index 0000000000..9828224800
--- /dev/null
+++ b/package/busybox/patches/100-killall5.patch
@@ -0,0 +1,85 @@
+diff -ruN busybox-1.2.0-old/include/applets.h busybox-1.2.0-new/include/applets.h
+--- busybox-1.2.0-old/include/applets.h 2006-07-01 00:42:10.000000000 +0200
++++ busybox-1.2.0-new/include/applets.h 2006-07-31 00:29:34.000000000 +0200
+@@ -157,6 +157,7 @@
+ USE_IPTUNNEL(APPLET(iptunnel, _BB_DIR_BIN, _BB_SUID_NEVER))
+ USE_KILL(APPLET(kill, _BB_DIR_BIN, _BB_SUID_NEVER))
+ USE_KILLALL(APPLET_ODDNAME(killall, kill, _BB_DIR_USR_BIN, _BB_SUID_NEVER, killall))
++USE_KILLALL5(APPLET_ODDNAME(killall5, kill, _BB_DIR_USR_BIN, _BB_SUID_NEVER, killall5))
+ USE_KLOGD(APPLET(klogd, _BB_DIR_SBIN, _BB_SUID_NEVER))
+ USE_LASH(APPLET(lash, _BB_DIR_BIN, _BB_SUID_NEVER))
+ USE_LAST(APPLET(last, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+diff -ruN busybox-1.2.0-old/include/usage.h busybox-1.2.0-new/include/usage.h
+--- busybox-1.2.0-old/include/usage.h 2006-07-01 00:42:10.000000000 +0200
++++ busybox-1.2.0-new/include/usage.h 2006-07-31 00:25:57.000000000 +0200
+@@ -1503,6 +1503,13 @@
+ #define killall_example_usage \
+ "$ killall apache\n"
+
++#define killall5_trivial_usage \
++ ""
++#define killall5_full_usage \
++ ""
++#define killall5_example_usage \
++ ""
++
+ #define klogd_trivial_usage \
+ "[-c n] [-n]"
+ #define klogd_full_usage \
+diff -ruN busybox-1.2.0-old/procps/Config.in busybox-1.2.0-new/procps/Config.in
+--- busybox-1.2.0-old/procps/Config.in 2006-07-01 00:42:12.000000000 +0200
++++ busybox-1.2.0-new/procps/Config.in 2006-07-31 00:25:57.000000000 +0200
+@@ -38,6 +38,11 @@
+ specified commands. If no signal name is specified, SIGTERM is
+ sent.
+
++config CONFIG_KILLALL5
++ bool "killall5"
++ default n
++ depends on CONFIG_KILL
++
+ config CONFIG_PIDOF
+ bool "pidof"
+ default n
+diff -ruN busybox-1.2.0-old/procps/kill.c busybox-1.2.0-new/procps/kill.c
+--- busybox-1.2.0-old/procps/kill.c 2006-07-01 00:42:12.000000000 +0200
++++ busybox-1.2.0-new/procps/kill.c 2006-07-31 00:25:57.000000000 +0200
+@@ -20,6 +20,7 @@
+
+ #define KILL 0
+ #define KILLALL 1
++#define KILLALL5 2
+
+ int kill_main(int argc, char **argv)
+ {
+@@ -34,6 +35,9 @@
+ #else
+ whichApp = KILL;
+ #endif
++#ifdef CONFIG_KILLALL5
++ whichApp = (strcmp(bb_applet_name, "killall5") == 0)? KILLALL5 : whichApp;
++#endif
+
+ /* Parse any options */
+ if (argc < 2)
+@@ -112,6 +116,20 @@
+ }
+
+ }
++#ifdef CONFIG_KILLALL5
++ else if (whichApp == KILLALL5) {
++ procps_status_t * p;
++ pid_t myPid=getpid();
++ while ((p = procps_scan(0)) != 0) {
++ if (p->pid != 1 && p->pid != myPid && p->pid != p->ppid) {
++ if (kill(p->pid, signo) != 0) {
++ bb_perror_msg( "Could not kill pid '%d'", p->pid);
++ errors++;
++ }
++ }
++ }
++ }
++#endif
+ #ifdef CONFIG_KILLALL
+ else {
+ pid_t myPid=getpid();
diff --git a/package/busybox/patches/110-telnetd.patch b/package/busybox/patches/110-telnetd.patch
new file mode 100644
index 0000000000..8ebb6de645
--- /dev/null
+++ b/package/busybox/patches/110-telnetd.patch
@@ -0,0 +1,51 @@
+diff -ruN busybox-1.2.0-old/networking/telnetd.c busybox-1.2.0-new/networking/telnetd.c
+--- busybox-1.2.0-old/networking/telnetd.c 2006-07-01 00:42:02.000000000 +0200
++++ busybox-1.2.0-new/networking/telnetd.c 2006-07-31 10:52:30.000000000 +0200
+@@ -44,6 +44,7 @@
+ #include <arpa/telnet.h>
+ #include <ctype.h>
+ #include <sys/syslog.h>
++#include <net/if.h>
+
+ #include "busybox.h"
+
+@@ -391,11 +392,13 @@
+ struct in_addr bind_addr = { .s_addr = 0x0 };
+ #endif /* CONFIG_FEATURE_TELNETD_INETD */
+ int c;
++ char *interface_name = NULL;
++ struct ifreq interface;
+ static const char options[] =
+ #ifdef CONFIG_FEATURE_TELNETD_INETD
+- "f:l:";
++ "i:f:l:";
+ #else /* CONFIG_EATURE_TELNETD_INETD */
+- "f:l:p:b:";
++ "i:f:l:p:b:";
+ #endif /* CONFIG_FEATURE_TELNETD_INETD */
+ int maxlen, w, r;
+
+@@ -410,6 +413,9 @@
+ case 'f':
+ issuefile = optarg;
+ break;
++ case 'i':
++ interface_name = strdup(optarg);
++ break;
+ case 'l':
+ loginpath = optarg;
+ break;
+@@ -459,6 +465,13 @@
+ sa.sin_addr = bind_addr;
+ #endif
+
++ /* Set it to listen on the specified interface */
++ if (interface_name) {
++ strncpy(interface.ifr_ifrn.ifrn_name, interface_name, IFNAMSIZ);
++ (void)setsockopt(master_fd, SOL_SOCKET,
++ SO_BINDTODEVICE, &interface, sizeof(interface));
++ }
++
+ bb_xbind(master_fd, (struct sockaddr *) &sa, sizeof(sa));
+ bb_xlisten(master_fd, 1);
+ bb_xdaemon(0, 0);
diff --git a/package/busybox/patches/140-unlink-passwd.patch b/package/busybox/patches/140-unlink-passwd.patch
new file mode 100644
index 0000000000..07b6767e6e
--- /dev/null
+++ b/package/busybox/patches/140-unlink-passwd.patch
@@ -0,0 +1,32 @@
+--- busybox-1.00.old/loginutils/passwd.c 2004-09-15 04:39:09.000000000 +0200
++++ busybox-1.00/loginutils/passwd.c 2005-03-23 15:31:07.000000000 +0100
+@@ -54,11 +54,12 @@
+ snprintf(filename, sizeof filename, "%s", bb_path_passwd_file);
+ }
+
+- if (((fp = fopen(filename, "r+")) == 0) || (fstat(fileno(fp), &sb))) {
++ if (((fp = fopen(filename, "r")) == 0) || (fstat(fileno(fp), &sb))) {
+ /* return 0; */
+ return 1;
+ }
+
++#if 0
+ /* Lock the password file before updating */
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+@@ -69,6 +70,7 @@
+ return 1;
+ }
+ lock.l_type = F_UNLCK;
++#endif
+
+ snprintf(buf, sizeof buf, "%s-", filename);
+ if (create_backup(buf, fp)) {
+@@ -119,6 +121,7 @@
+ fclose(fp);
+ return 1;
+ }
++ unlink(filename);
+ if (rename(buf, filename) < 0) {
+ fcntl(fileno(fp), F_SETLK, &lock);
+ fclose(fp);
diff --git a/package/busybox/patches/150-udhcp-release.patch b/package/busybox/patches/150-udhcp-release.patch
new file mode 100644
index 0000000000..1e1c00ef29
--- /dev/null
+++ b/package/busybox/patches/150-udhcp-release.patch
@@ -0,0 +1,90 @@
+diff -ruN busybox-1.2.0-old/include/usage.h busybox-1.2.0-new/include/usage.h
+--- busybox-1.2.0-old/include/usage.h 2006-07-31 10:47:56.000000000 +0200
++++ busybox-1.2.0-new/include/usage.h 2006-07-31 11:08:49.000000000 +0200
+@@ -3190,6 +3190,7 @@
+ "\t-n,\t--now\tExit with failure if lease cannot be immediately negotiated\n" \
+ "\t-p,\t--pidfile=file\tStore process ID of daemon in file\n" \
+ "\t-q,\t--quit\tQuit after obtaining lease\n" \
++ "\t-R,\t--release\tRelease IP on quit\n" \
+ "\t-r,\t--request=IP\tIP address to request (default: none)\n" \
+ "\t-s,\t--script=file\tRun file at dhcp events (default: /usr/share/udhcpc/default.script)\n" \
+ "\t-t,\t--retries=NUM\tSend up to NUM request packets\n"\
+diff -ruN busybox-1.2.0-old/networking/udhcp/dhcpc.c busybox-1.2.0-new/networking/udhcp/dhcpc.c
+--- busybox-1.2.0-old/networking/udhcp/dhcpc.c 2006-07-01 00:42:02.000000000 +0200
++++ busybox-1.2.0-new/networking/udhcp/dhcpc.c 2006-07-31 11:08:49.000000000 +0200
+@@ -47,6 +47,7 @@
+ .abort_if_no_lease = 0,
+ .foreground = 0,
+ .quit_after_lease = 0,
++ .release_on_quit = 0,
+ .background_if_no_lease = 0,
+ .interface = "eth0",
+ .pidfile = NULL,
+@@ -163,6 +164,7 @@
+ {"now", no_argument, 0, 'n'},
+ {"pidfile", required_argument, 0, 'p'},
+ {"quit", no_argument, 0, 'q'},
++ {"release", no_argument, 0, 'R'},
+ {"request", required_argument, 0, 'r'},
+ {"script", required_argument, 0, 's'},
+ {"timeout", required_argument, 0, 'T'},
+@@ -174,7 +176,7 @@
+ /* get options */
+ while (1) {
+ int option_index = 0;
+- c = getopt_long(argc, argv, "c:CV:fbH:h:F:i:np:qr:s:T:t:v", arg_options, &option_index);
++ c = getopt_long(argc, argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:v", arg_options, &option_index);
+ if (c == -1) break;
+
+ switch (c) {
+@@ -244,6 +246,9 @@
+ case 'q':
+ client_config.quit_after_lease = 1;
+ break;
++ case 'R':
++ client_config.release_on_quit = 1;
++ break;
+ case 'r':
+ requested_ip = inet_addr(optarg);
+ break;
+@@ -488,8 +493,11 @@
+
+ state = BOUND;
+ change_mode(LISTEN_NONE);
+- if (client_config.quit_after_lease)
++ if (client_config.quit_after_lease) {
++ if (client_config.release_on_quit)
++ perform_release();
+ return 0;
++ }
+ if (!client_config.foreground)
+ client_background();
+
+@@ -514,12 +522,13 @@
+ case SIGUSR1:
+ perform_renew();
+ break;
+- case SIGUSR2:
+- perform_release();
+- break;
+ case SIGTERM:
+ LOG(LOG_INFO, "Received SIGTERM");
++ if (!client_config.release_on_quit)
+ return 0;
++ case SIGUSR2:
++ perform_release();
++ break;
+ }
+ } else if (retval == -1 && errno == EINTR) {
+ /* a signal was caught */
+diff -ruN busybox-1.2.0-old/networking/udhcp/dhcpc.h busybox-1.2.0-new/networking/udhcp/dhcpc.h
+--- busybox-1.2.0-old/networking/udhcp/dhcpc.h 2006-07-01 00:42:02.000000000 +0200
++++ busybox-1.2.0-new/networking/udhcp/dhcpc.h 2006-07-31 11:08:49.000000000 +0200
+@@ -18,6 +18,7 @@
+ struct client_config_t {
+ char foreground; /* Do not fork */
+ char quit_after_lease; /* Quit after obtaining lease */
++ char release_on_quit; /* perform release on quit */
+ char abort_if_no_lease; /* Abort if no lease */
+ char background_if_no_lease; /* Fork to background if no lease */
+ char *interface; /* The name of the interface to use */
diff --git a/package/busybox/patches/170-udhcp-options.patch b/package/busybox/patches/170-udhcp-options.patch
new file mode 100644
index 0000000000..b03810adf5
--- /dev/null
+++ b/package/busybox/patches/170-udhcp-options.patch
@@ -0,0 +1,15 @@
+diff -Nur busybox-1.00.orig/networking/udhcp/options.c busybox-1.00/networking/udhcp/options.c
+--- busybox-1.00.orig/networking/udhcp/options.c 2004-03-15 09:29:01.000000000 +0100
++++ busybox-1.00/networking/udhcp/options.c 2005-09-14 13:27:23.792609800 +0200
+@@ -39,8 +39,11 @@
+ {"dhcptype", OPTION_U8, 0x35},
+ {"serverid", OPTION_IP, 0x36},
+ {"message", OPTION_STRING, 0x38},
++ {"vendorclass", OPTION_STRING, 0x3C},
++ {"clientid", OPTION_STRING, 0x3D},
+ {"tftp", OPTION_STRING, 0x42},
+ {"bootfile", OPTION_STRING, 0x43},
++ {"userclass", OPTION_STRING, 0x4D},
+ {"", 0x00, 0x00}
+ };
+
diff --git a/package/busybox/patches/180-telnetd_ipv6.patch b/package/busybox/patches/180-telnetd_ipv6.patch
new file mode 100644
index 0000000000..fb8df6fa92
--- /dev/null
+++ b/package/busybox/patches/180-telnetd_ipv6.patch
@@ -0,0 +1,12 @@
+diff -urN busybox.old/networking/telnetd.c busybox.dev/networking/telnetd.c
+--- busybox.old/networking/telnetd.c 2005-08-17 03:29:10.000000000 +0200
++++ busybox.dev/networking/telnetd.c 2005-10-22 19:37:49.976396000 +0200
+@@ -49,6 +49,8 @@
+
+ #define BUFSIZE 4000
+
++#undef CONFIG_FEATURE_IPV6
++
+ #ifdef CONFIG_FEATURE_IPV6
+ #define SOCKET_TYPE AF_INET6
+ typedef struct sockaddr_in6 sockaddr_type;
diff --git a/package/busybox/patches/190-ash_performance.patch b/package/busybox/patches/190-ash_performance.patch
new file mode 100644
index 0000000000..0931931419
--- /dev/null
+++ b/package/busybox/patches/190-ash_performance.patch
@@ -0,0 +1,80 @@
+
+ Copyright (C) 2006 OpenWrt.org
+
+diff -urN busybox.old/shell/ash.c busybox.dev/shell/ash.c
+--- busybox.old/shell/ash.c 2005-11-12 22:39:19.853826250 +0100
++++ busybox.dev/shell/ash.c 2005-11-12 22:39:42.771258500 +0100
+@@ -1414,6 +1414,13 @@
+
+ #define NUMBUILTINS (sizeof (builtincmd) / sizeof (struct builtincmd) )
+
++static const char *safe_applets[] = {
++ "[", "test", "echo", "cat",
++ "ln", "cp", "touch", "mkdir", "rm",
++ "cut", "hexdump", "awk", "sort",
++ "find", "xargs", "ls", "dd",
++ "chown", "chmod"
++};
+
+
+ struct cmdentry {
+@@ -2050,6 +2057,19 @@
+ static void exitshell(void) __attribute__((__noreturn__));
+ static int decode_signal(const char *, int);
+
++
++static int is_safe_applet(char *name)
++{
++ int n = sizeof(safe_applets) / sizeof(char *);
++ int i;
++ for (i = 0; i < n; i++)
++ if (strcmp(safe_applets[i], name) == 0)
++ return 1;
++
++ return 0;
++}
++
++
+ /*
+ * This routine is called when an error or an interrupt occurs in an
+ * interactive shell and control is returned to the main command loop.
+@@ -3680,6 +3700,7 @@
+ clearredir(1);
+ envp = environment();
+ if (strchr(argv[0], '/') != NULL
++ || is_safe_applet(argv[0])
+ #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
+ || find_applet_by_name(argv[0])
+ #endif
+@@ -3721,6 +3742,18 @@
+ tryexec(char *cmd, char **argv, char **envp)
+ {
+ int repeated = 0;
++ struct BB_applet *a;
++ int argc = 0;
++ char **c;
++
++ if(strchr(cmd, '/') == NULL && is_safe_applet(cmd) && (a = find_applet_by_name(cmd)) != NULL) {
++ c = argv;
++ while (*c != NULL) {
++ c++; argc++;
++ }
++ bb_applet_name = cmd;
++ exit(a->main(argc, argv));
++ }
+ #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
+ int flg_bb = 0;
+ char *name = cmd;
+@@ -3919,6 +3952,12 @@
+ }
+ #endif
+
++ if (is_safe_applet(name)) {
++ entry->cmdtype = CMDNORMAL;
++ entry->u.index = -1;
++ return;
++ }
++
+ updatetbl = (path == pathval());
+ if (!updatetbl) {
+ act |= DO_ALTPATH;
diff --git a/package/busybox/patches/200-etc_crontabs.patch b/package/busybox/patches/200-etc_crontabs.patch
new file mode 100644
index 0000000000..5ec01c1eb0
--- /dev/null
+++ b/package/busybox/patches/200-etc_crontabs.patch
@@ -0,0 +1,24 @@
+diff -urN busybox.old/miscutils/crond.c busybox.dev/miscutils/crond.c
+--- busybox.old/miscutils/crond.c 2004-04-14 19:51:21.000000000 +0200
++++ busybox.dev/miscutils/crond.c 2005-12-11 22:54:07.878256250 +0100
+@@ -36,7 +36,7 @@
+ #define arysize(ary) (sizeof(ary)/sizeof((ary)[0]))
+
+ #ifndef CRONTABS
+-#define CRONTABS "/var/spool/cron/crontabs"
++#define CRONTABS "/etc/crontabs"
+ #endif
+ #ifndef TMPDIR
+ #define TMPDIR "/var/spool/cron"
+diff -urN busybox.old/miscutils/crontab.c busybox.dev/miscutils/crontab.c
+--- busybox.old/miscutils/crontab.c 2004-04-14 19:51:21.000000000 +0200
++++ busybox.dev/miscutils/crontab.c 2005-12-11 22:54:28.647554250 +0100
+@@ -28,7 +28,7 @@
+ #include <sys/resource.h>
+
+ #ifndef CRONTABS
+-#define CRONTABS "/var/spool/cron/crontabs"
++#define CRONTABS "/etc/crontabs"
+ #endif
+ #ifndef TMPDIR
+ #define TMPDIR "/var/spool/cron"
diff --git a/package/busybox/patches/210-passwd_limit.patch b/package/busybox/patches/210-passwd_limit.patch
new file mode 100644
index 0000000000..6c10916b4a
--- /dev/null
+++ b/package/busybox/patches/210-passwd_limit.patch
@@ -0,0 +1,15 @@
+
+ Copyright (C) 2006 OpenWrt.org
+
+diff -urN busybox.old/loginutils/passwd.c busybox.dev/loginutils/passwd.c
+--- busybox.old/loginutils/passwd.c 2005-12-11 22:52:46.185150000 +0100
++++ busybox.dev/loginutils/passwd.c 2005-12-11 23:19:15.276596500 +0100
+@@ -353,7 +353,7 @@
+ } else {
+ orig[0] = '\0';
+ }
+- if (! (cp=bb_askpass(0, "Enter the new password (minimum of 5, maximum of 8 characters)\n"
++ if (! (cp=bb_askpass(0, "Enter the new password (minimum of 5 characters)\n"
+ "Please use a combination of upper and lower case letters and numbers.\n"
+ "Enter new password: ")))
+ {
diff --git a/package/busybox/patches/220-awk_bitops.patch b/package/busybox/patches/220-awk_bitops.patch
new file mode 100644
index 0000000000..1567583d2a
--- /dev/null
+++ b/package/busybox/patches/220-awk_bitops.patch
@@ -0,0 +1,64 @@
+
+ Copyright (C) 2006 OpenWrt.org
+
+--- busybox-1.00/editors/awk.c.orig 2004-09-24 05:24:27 -04:00
++++ busybox-1.00/editors/awk.c 2006-03-08 02:16:52 -05:00
+@@ -271,7 +271,8 @@
+ /* builtins */
+ enum {
+ B_a2=0, B_ix, B_ma, B_sp, B_ss, B_ti, B_lo, B_up,
+- B_ge, B_gs, B_su
++ B_ge, B_gs, B_su,
++ B_an, B_co, B_ls, B_or, B_rs, B_xo,
+ };
+
+ /* tokens and their corresponding info values */
+@@ -311,6 +312,8 @@
+ "\5while" NTC
+ "\4else" NTC
+
++ "\3and" "\5compl" "\6lshift" "\2or"
++ "\6rshift" "\3xor"
+ "\5close" "\6system" "\6fflush" "\5atan2" /* BUILTIN */
+ "\3cos" "\3exp" "\3int" "\3log"
+ "\4rand" "\3sin" "\4sqrt" "\5srand"
+@@ -364,6 +367,8 @@
+ ST_WHILE,
+ 0,
+
++ OC_B|B_an|P(0x83), OC_B|B_co|P(0x41), OC_B|B_ls|P(0x83), OC_B|B_or|P(0x83),
++ OC_B|B_rs|P(0x83), OC_B|B_xo|P(0x83),
+ OC_FBLTIN|Sx|F_cl, OC_FBLTIN|Sx|F_sy, OC_FBLTIN|Sx|F_ff, OC_B|B_a2|P(0x83),
+ OC_FBLTIN|Nx|F_co, OC_FBLTIN|Nx|F_ex, OC_FBLTIN|Nx|F_in, OC_FBLTIN|Nx|F_lg,
+ OC_FBLTIN|F_rn, OC_FBLTIN|Nx|F_si, OC_FBLTIN|Nx|F_sq, OC_FBLTIN|Nx|F_sr,
+@@ -1942,6 +1947,30 @@
+ strncpy(s, as[0]+i, n);
+ s[n] = '\0';
+ setvar_p(res, s);
++ break;
++
++ case B_an:
++ setvar_i(res, (long)getvar_i(av[0]) & (long)getvar_i(av[1]));
++ break;
++
++ case B_co:
++ setvar_i(res, ~(long)getvar_i(av[0]));
++ break;
++
++ case B_ls:
++ setvar_i(res, (long)getvar_i(av[0]) << (long)getvar_i(av[1]));
++ break;
++
++ case B_or:
++ setvar_i(res, (long)getvar_i(av[0]) | (long)getvar_i(av[1]));
++ break;
++
++ case B_rs:
++ setvar_i(res, (long)((unsigned long)getvar_i(av[0]) >> (unsigned long)getvar_i(av[1])));
++ break;
++
++ case B_xo:
++ setvar_i(res, (long)getvar_i(av[0]) ^ (long)getvar_i(av[1]));
+ break;
+
+ case B_lo:
diff --git a/package/busybox/patches/230-grep_C.patch b/package/busybox/patches/230-grep_C.patch
new file mode 100644
index 0000000000..08d76738b3
--- /dev/null
+++ b/package/busybox/patches/230-grep_C.patch
@@ -0,0 +1,12 @@
+diff -Nur busybox-1.2.1/findutils/grep.c busybox-1.2.1/findutils/grep.c
+--- busybox-1.2.1/findutils/grep.c 2006-09-25 14:47:51.000000000 -0700
++++ busybox-1.2.1/findutils/grep.c 2006-09-25 14:39:39.000000000 -0700
+@@ -51,7 +51,7 @@
+ #define GREP_OPT_L (1<<12)
+ #define PRINT_FILES_WITHOUT_MATCHES ((opt & GREP_OPT_L) != 0)
+ #if ENABLE_FEATURE_GREP_CONTEXT
+-#define GREP_OPT_CONTEXT "A:B:C"
++#define GREP_OPT_CONTEXT "A:B:C:"
+ #define GREP_OPT_A (1<<13)
+ #define GREP_OPT_B (1<<14)
+ #define GREP_OPT_C (1<<15)
diff --git a/package/busybox/patches/300-netmsg.patch b/package/busybox/patches/300-netmsg.patch
new file mode 100644
index 0000000000..428e321390
--- /dev/null
+++ b/package/busybox/patches/300-netmsg.patch
@@ -0,0 +1,110 @@
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+diff -ruN busybox-1.2.0-old/include/applets.h busybox-1.2.0-new/include/applets.h
+--- busybox-1.2.0-old/include/applets.h 2006-07-31 10:47:56.000000000 +0200
++++ busybox-1.2.0-new/include/applets.h 2006-07-31 11:21:00.000000000 +0200
+@@ -200,6 +200,7 @@
+ USE_MV(APPLET(mv, _BB_DIR_BIN, _BB_SUID_NEVER))
+ USE_NAMEIF(APPLET(nameif, _BB_DIR_SBIN, _BB_SUID_NEVER))
+ USE_NC(APPLET(nc, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
++USE_NETMSG(APPLET_NOUSAGE(netmsg, netmsg, _BB_DIR_BIN, _BB_SUID_ALWAYS))
+ USE_NETSTAT(APPLET(netstat, _BB_DIR_BIN, _BB_SUID_NEVER))
+ USE_NICE(APPLET(nice, _BB_DIR_BIN, _BB_SUID_NEVER))
+ USE_NOHUP(APPLET(nohup, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+diff -ruN busybox-1.2.0-old/networking/Config.in busybox-1.2.0-new/networking/Config.in
+--- busybox-1.2.0-old/networking/Config.in 2006-07-01 00:42:02.000000000 +0200
++++ busybox-1.2.0-new/networking/Config.in 2006-07-31 11:18:01.000000000 +0200
+@@ -445,6 +445,12 @@
+ help
+ A simple Unix utility which reads and writes data across network
+ connections.
++
++config CONFIG_NETMSG
++ bool "netmsg"
++ default n
++ help
++ simple program for sending udp broadcast messages
+
+ config CONFIG_NC_GAPING_SECURITY_HOLE
+ bool "gaping security hole"
+diff -ruN busybox-1.2.0-old/networking/Makefile.in busybox-1.2.0-new/networking/Makefile.in
+--- busybox-1.2.0-old/networking/Makefile.in 2006-07-01 00:42:02.000000000 +0200
++++ busybox-1.2.0-new/networking/Makefile.in 2006-07-31 11:18:01.000000000 +0200
+@@ -30,6 +30,7 @@
+ NETWORKING-$(CONFIG_IPTUNNEL) += iptunnel.o
+ NETWORKING-$(CONFIG_NAMEIF) += nameif.o
+ NETWORKING-$(CONFIG_NC) += nc.o
++NETWORKING-$(CONFIG_NETMSG) += netmsg.o
+ NETWORKING-$(CONFIG_NETSTAT) += netstat.o
+ NETWORKING-$(CONFIG_NSLOOKUP) += nslookup.o
+ NETWORKING-$(CONFIG_PING) += ping.o
+diff -ruN busybox-1.2.0-old/networking/netmsg.c busybox-1.2.0-new/networking/netmsg.c
+--- busybox-1.2.0-old/networking/netmsg.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0-new/networking/netmsg.c 2006-07-31 11:18:01.000000000 +0200
+@@ -0,0 +1,63 @@
++/*
++ * 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"
++
++
++#ifndef CONFIG_NETMSG
++int main(int argc, char **argv)
++#else
++int netmsg_main(int argc, char **argv)
++#endif
++{
++ int s, i;
++ 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 0000000000..868abfcd06
--- /dev/null
+++ b/package/busybox/patches/310-passwd_access.patch
@@ -0,0 +1,44 @@
+
+ Copyright (C) 2006 OpenWrt.org
+
+diff -urN busybox.old/networking/httpd.c busybox.dev/networking/httpd.c
+--- busybox.old/networking/httpd.c 2004-10-08 10:03:29.000000000 +0200
++++ busybox.dev/networking/httpd.c 2006-02-04 01:54:19.688016250 +0100
+@@ -1467,12 +1467,26 @@
+ {
+ char *cipher;
+ char *pp;
++ char *ppnew = NULL;
++ struct passwd *pwd = NULL;
+
+ if(strncmp(p, request, u-request) != 0) {
+ /* user uncompared */
+ continue;
+ }
+ pp = strchr(p, ':');
++ if(pp && pp[1] == '$' && pp[2] == 'p' &&
++ pp[3] == '$' && pp[4] &&
++ (pwd = getpwnam(&pp[4])) != NULL) {
++ if(pwd->pw_passwd && pwd->pw_passwd[0] == '!') {
++ prev = NULL;
++ continue;
++ }
++ ppnew = malloc(5 + strlen(pwd->pw_passwd));
++ ppnew[0] = ':';
++ strcpy(ppnew + 1, pwd->pw_passwd);
++ pp = ppnew;
++ }
+ if(pp && pp[1] == '$' && pp[2] == '1' &&
+ pp[3] == '$' && pp[4]) {
+ pp++;
+@@ -1482,6 +1492,10 @@
+ /* unauthorized */
+ continue;
+ }
++ if (ppnew) {
++ free(ppnew);
++ ppnew = NULL;
++ }
+ }
+ #endif
+ if (strcmp(p, request) == 0) {
diff --git a/package/busybox/patches/320-httpd_address_binding.patch b/package/busybox/patches/320-httpd_address_binding.patch
new file mode 100644
index 0000000000..68487b88c7
--- /dev/null
+++ b/package/busybox/patches/320-httpd_address_binding.patch
@@ -0,0 +1,95 @@
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+diff -ruN busybox-1.2.0-old/networking/httpd.c busybox-1.2.0-new/networking/httpd.c
+--- busybox-1.2.0-old/networking/httpd.c 2006-07-01 00:42:02.000000000 +0200
++++ busybox-1.2.0-new/networking/httpd.c 2006-08-01 10:06:58.000000000 +0200
+@@ -99,6 +99,7 @@
+ #include <sys/types.h>
+ #include <sys/socket.h> /* for connect and socket*/
+ #include <netinet/in.h> /* for sockaddr_in */
++#include <arpa/inet.h>
+ #include <sys/stat.h>
+ #include <sys/wait.h>
+ #include <fcntl.h> /* for open modes */
+@@ -165,6 +166,7 @@
+ #endif
+ unsigned port; /* server initial port and for
+ set env REMOTE_PORT */
++ char *address;
+ union HTTPD_FOUND {
+ const char *found_mime_type;
+ const char *found_moved_temporarily;
+@@ -868,7 +870,10 @@
+ /* inet_addr() returns a value that is already in network order */
+ memset(&lsocket, 0, sizeof(lsocket));
+ lsocket.sin_family = AF_INET;
+- lsocket.sin_addr.s_addr = INADDR_ANY;
++ if (inet_aton(config->address, &(lsocket.sin_addr)) == 1) {
++ if (config->address != NULL) lsocket.sin_addr.s_addr = ((struct in_addr *) ((gethostbyname(config->address))->h_addr))->s_addr;
++ else lsocket.sin_addr.s_addr = htons(INADDR_ANY);
++ }
+ lsocket.sin_port = htons(config->port);
+ fd = bb_xsocket(AF_INET, SOCK_STREAM, 0);
+ /* tell the OS it's OK to reuse a previous address even though */
+@@ -1899,6 +1904,7 @@
+ USE_FEATURE_HTTPD_AUTH_MD5(m_opt_md5,)
+ USE_FEATURE_HTTPD_SETUID(u_opt_setuid,)
+ USE_FEATURE_HTTPD_WITHOUT_INETD(p_opt_port,)
++ USE_FEATURE_HTTPD_WITHOUT_INETD(l_opt_addr,)
+ };
+
+ static const char httpd_opts[]="c:d:h:"
+@@ -1906,7 +1912,7 @@
+ USE_FEATURE_HTTPD_BASIC_AUTH("r:")
+ USE_FEATURE_HTTPD_AUTH_MD5("m:")
+ USE_FEATURE_HTTPD_SETUID("u:")
+- USE_FEATURE_HTTPD_WITHOUT_INETD("p:");
++ USE_FEATURE_HTTPD_WITHOUT_INETD("p:l:");
+
+ #define OPT_CONFIG_FILE (1<<c_opt_config_file)
+ #define OPT_DECODE_URL (1<<d_opt_decode_url)
+@@ -1927,6 +1933,8 @@
+ #define OPT_PORT USE_FEATURE_HTTPD_WITHOUT_INETD((1<<p_opt_port)) \
+ SKIP_FEATURE_HTTPD_WITHOUT_INETD(0)
+
++#define OPT_ADDRESS USE_FEATURE_HTTPD_WITHOUT_INETD((1<<l_opt_addr)) \
++ SKIP_FEATURE_HTTPD_WITHOUT_INETD(0)
+
+ int httpd_main(int argc, char *argv[])
+ {
+@@ -1935,6 +1943,7 @@
+ char *url_for_decode;
+ USE_FEATURE_HTTPD_ENCODE_URL_STR(const char *url_for_encode;)
+ USE_FEATURE_HTTPD_WITHOUT_INETD(const char *s_port;)
++ USE_FEATURE_HTTPD_WITHOUT_INETD(const char *s_addr;)
+ USE_FEATURE_HTTPD_WITHOUT_INETD(int server;)
+
+ USE_FEATURE_HTTPD_SETUID(const char *s_uid;)
+@@ -1949,6 +1958,7 @@
+
+ #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+ config->port = 80;
++ config->address = "";
+ #endif
+
+ config->ContentLength = -1;
+@@ -1960,6 +1970,7 @@
+ USE_FEATURE_HTTPD_AUTH_MD5(, &pass)
+ USE_FEATURE_HTTPD_SETUID(, &s_uid)
+ USE_FEATURE_HTTPD_WITHOUT_INETD(, &s_port)
++ USE_FEATURE_HTTPD_WITHOUT_INETD(, &s_addr)
+ );
+
+ if(opt & OPT_DECODE_URL) {
+@@ -1981,6 +1992,8 @@
+ #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+ if(opt & OPT_PORT)
+ config->port = bb_xgetlarg(s_port, 10, 1, 0xffff);
++ if (opt & OPT_ADDRESS)
++ if (s_addr) config->address = (char *) s_addr;
+ #ifdef CONFIG_FEATURE_HTTPD_SETUID
+ if(opt & OPT_SETUID) {
+ char *e;
diff --git a/package/busybox/patches/330-httpd_user_agent.patch b/package/busybox/patches/330-httpd_user_agent.patch
new file mode 100644
index 0000000000..bbe01f7826
--- /dev/null
+++ b/package/busybox/patches/330-httpd_user_agent.patch
@@ -0,0 +1,30 @@
+diff -Nur busybox-1.1.1/networking/httpd.c busybox-1.1.1-owrt/networking/httpd.c
+--- busybox-1.1.1/networking/httpd.c 2006-04-01 19:42:36.000000000 +0200
++++ busybox-1.1.1-owrt/networking/httpd.c 2006-04-01 19:43:59.000000000 +0200
+@@ -247,6 +247,7 @@
+ const char *query;
+
+ USE_FEATURE_HTTPD_CGI(char *referer;)
++ USE_FEATURE_HTTPD_CGI(char *user_agent;)
+
+ const char *configFile;
+
+@@ -1208,6 +1209,7 @@
+ addEnv("SERVER", "PROTOCOL", "HTTP/1.0");
+ addEnv("GATEWAY_INTERFACE", "", "CGI/1.1");
+ addEnv("REMOTE", "ADDR", config->rmt_ip_str);
++ addEnv("HTTP","USER_AGENT", config->user_agent);
+ #ifdef CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
+ addEnvPort("REMOTE");
+ #endif
+@@ -1771,6 +1773,10 @@
+ for(test = buf + 8; isspace(*test); test++)
+ ;
+ config->referer = strdup(test);
++ } else if ((strncasecmp(buf, "User-Agent:",11) ==0)) {
++ for(test = buf + 11; isspace(*test); test++)
++ ;
++ config->user_agent = strdup(test);
+ }
+ #endif
+
diff --git a/package/busybox/patches/340-lock_util.patch b/package/busybox/patches/340-lock_util.patch
new file mode 100644
index 0000000000..a86948d597
--- /dev/null
+++ b/package/busybox/patches/340-lock_util.patch
@@ -0,0 +1,180 @@
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+diff -ruN busybox-1.2.0-old/include/applets.h busybox-1.2.0-new/include/applets.h
+--- busybox-1.2.0-old/include/applets.h 2006-07-31 11:21:00.000000000 +0200
++++ busybox-1.2.0-new/include/applets.h 2006-08-01 10:21:15.000000000 +0200
+@@ -169,6 +169,7 @@
+ USE_LN(APPLET(ln, _BB_DIR_BIN, _BB_SUID_NEVER))
+ USE_LOADFONT(APPLET(loadfont, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+ USE_LOADKMAP(APPLET(loadkmap, _BB_DIR_SBIN, _BB_SUID_NEVER))
++USE_LOCK(APPLET_NOUSAGE(lock, lock, _BB_DIR_BIN, _BB_SUID_NEVER))
+ USE_LOGGER(APPLET(logger, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+ USE_LOGIN(APPLET(login, _BB_DIR_BIN, _BB_SUID_ALWAYS))
+ USE_LOGNAME(APPLET(logname, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+diff -ruN busybox-1.2.0-old/miscutils/Config.in busybox-1.2.0-new/miscutils/Config.in
+--- busybox-1.2.0-old/miscutils/Config.in 2006-07-01 00:42:09.000000000 +0200
++++ busybox-1.2.0-new/miscutils/Config.in 2006-08-01 10:21:15.000000000 +0200
+@@ -231,6 +231,12 @@
+ Enables the 'hdparm -d' option to get/set using_dma flag.
+ This is dangerous stuff, so you should probably say N.
+
++config CONFIG_LOCK
++ bool "lock"
++ default y
++ help
++ Small utility for using locks in scripts
++
+ config CONFIG_MAKEDEVS
+ bool "makedevs"
+ default n
+diff -ruN busybox-1.2.0-old/miscutils/lock.c busybox-1.2.0-new/miscutils/lock.c
+--- busybox-1.2.0-old/miscutils/lock.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0-new/miscutils/lock.c 2006-08-01 10:21:15.000000000 +0200
+@@ -0,0 +1,133 @@
++/*
++ * 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"
++
++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);
++ unlink(file);
++ 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, 0700)) < 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;
++ }
++}
++
++#ifndef CONFIG_LOCK
++int main(int argc, char **argv)
++#else
++int lock_main(int argc, char **argv)
++#endif
++{
++ 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 -ruN busybox-1.2.0-old/miscutils/Makefile.in busybox-1.2.0-new/miscutils/Makefile.in
+--- busybox-1.2.0-old/miscutils/Makefile.in 2006-07-01 00:42:09.000000000 +0200
++++ busybox-1.2.0-new/miscutils/Makefile.in 2006-08-01 10:21:15.000000000 +0200
+@@ -20,6 +20,7 @@
+ MISCUTILS-$(CONFIG_EJECT) += eject.o
+ MISCUTILS-$(CONFIG_HDPARM) += hdparm.o
+ MISCUTILS-$(CONFIG_LAST) += last.o
++MISCUTILS-$(CONFIG_LOCK) += lock.o
+ MISCUTILS-${CONFIG_LESS} += less.o
+ MISCUTILS-$(CONFIG_MAKEDEVS) += makedevs.o
+ MISCUTILS-$(CONFIG_MOUNTPOINT) += mountpoint.o
diff --git a/package/busybox/patches/911-ipkg.patch b/package/busybox/patches/911-ipkg.patch
new file mode 100644
index 0000000000..fdb790ad59
--- /dev/null
+++ b/package/busybox/patches/911-ipkg.patch
@@ -0,0 +1,13896 @@
+diff -ruN busybox-1.2.0-orig/archival/Config.in busybox-1.2.0+ipkg-0.99.162/archival/Config.in
+--- busybox-1.2.0-orig/archival/Config.in 2006-07-01 00:42:04.000000000 +0200
++++ busybox-1.2.0+ipkg-0.99.162/archival/Config.in 2006-07-22 16:31:25.000000000 +0200
+@@ -121,6 +121,14 @@
+ gzip is used to compress files.
+ It's probably the most widely used UNIX compression program.
+
++config CONFIG_IPKG
++ bool "ipkg"
++ default n
++ select CONFIG_MD5SUM
++ select CONFIG_WGET
++ help
++ ipkg is the itsy package management system.
++
+ config CONFIG_RPM2CPIO
+ bool "rpm2cpio"
+ default n
+diff -ruN busybox-1.2.0-orig/archival/dpkg.c busybox-1.2.0+ipkg-0.99.162/archival/dpkg.c
+--- busybox-1.2.0-orig/archival/dpkg.c 2006-07-01 00:42:04.000000000 +0200
++++ busybox-1.2.0+ipkg-0.99.162/archival/dpkg.c 2006-07-22 16:31:25.000000000 +0200
+@@ -1430,6 +1430,10 @@
+ return(ar_handle->sub_archive->buffer);
+ }
+
++/*
++
++// moved to data_extract_all.c
++
+ static void data_extract_all_prefix(archive_handle_t *archive_handle)
+ {
+ char *name_ptr = archive_handle->file_header->name;
+@@ -1442,6 +1446,8 @@
+ return;
+ }
+
++*/
++
+ static void unpack_package(deb_file_t *deb_file)
+ {
+ const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name];
+diff -ruN busybox-1.2.0-orig/archival/ipkg.c busybox-1.2.0+ipkg-0.99.162/archival/ipkg.c
+--- busybox-1.2.0-orig/archival/ipkg.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/ipkg.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,26 @@
++/* ipkg.c - the itsy package management system
++
++ Florina Boor
++
++ Copyright (C) 2003 kernel concepts
++
++ 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.
++
++ ipkg command line frontend using libipkg
++
++*/
++
++#include "libipkg/libipkg.h"
++
++int ipkg_main(int argc, char **argv)
++{
++ return ipkg_op(argc, argv);
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/args.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/args.c
+--- busybox-1.2.0-orig/archival/libipkg/args.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/args.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,242 @@
++/* args.c - parse command-line args
++
++ Carl D. Worth
++
++ Copyright 2001 University of Southern California
++
++ 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.
++ */
++
++#include <getopt.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++
++#include "ipkg.h"
++#include "ipkg_message.h"
++
++#include "args.h"
++#include "sprintf_alloc.h"
++
++#include "libbb.h"
++
++
++static void print_version(void);
++
++enum long_args_opt
++{
++ ARGS_OPT_FORCE_DEFAULTS = 129,
++ ARGS_OPT_FORCE_DEPENDS,
++ ARGS_OPT_FORCE_OVERWRITE,
++ ARGS_OPT_FORCE_DOWNGRADE,
++ ARGS_OPT_FORCE_REINSTALL,
++ ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES,
++ ARGS_OPT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES,
++ ARGS_OPT_FORCE_SPACE,
++ ARGS_OPT_NOACTION,
++ ARGS_OPT_NODEPS,
++ ARGS_OPT_VERBOSE_WGET,
++ ARGS_OPT_VERBOSITY,
++ ARGS_OPT_MULTIPLE_PROVIDERS
++};
++
++int args_init(args_t *args)
++{
++ char *conf_file_dir;
++
++ memset(args, 0, sizeof(args_t));
++
++ args->dest = ARGS_DEFAULT_DEST;
++
++ conf_file_dir = getenv("IPKG_CONF_DIR");
++ if (conf_file_dir == NULL || conf_file_dir[0] == '\0') {
++ conf_file_dir = ARGS_DEFAULT_CONF_FILE_DIR;
++ }
++ sprintf_alloc(&args->conf_file, "%s/%s", conf_file_dir,
++ ARGS_DEFAULT_CONF_FILE_NAME);
++
++ args->force_defaults = ARGS_DEFAULT_FORCE_DEFAULTS;
++ args->force_depends = ARGS_DEFAULT_FORCE_DEPENDS;
++ args->force_overwrite = ARGS_DEFAULT_FORCE_OVERWRITE;
++ args->force_downgrade = ARGS_DEFAULT_FORCE_DOWNGRADE;
++ args->force_reinstall = ARGS_DEFAULT_FORCE_REINSTALL;
++ args->force_removal_of_dependent_packages = ARGS_DEFAULT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES;
++ args->force_removal_of_essential_packages = ARGS_DEFAULT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES;
++ args->noaction = ARGS_DEFAULT_NOACTION;
++ args->nodeps = ARGS_DEFAULT_NODEPS;
++ args->verbose_wget = ARGS_DEFAULT_VERBOSE_WGET;
++ args->verbosity = ARGS_DEFAULT_VERBOSITY;
++ args->offline_root = ARGS_DEFAULT_OFFLINE_ROOT;
++ args->offline_root_pre_script_cmd = ARGS_DEFAULT_OFFLINE_ROOT_PRE_SCRIPT_CMD;
++ args->offline_root_post_script_cmd = ARGS_DEFAULT_OFFLINE_ROOT_POST_SCRIPT_CMD;
++ args->multiple_providers = 0;
++ args->nocheckfordirorfile = 0;
++ args->noreadfeedsfile = 0;
++
++ return 1;
++}
++
++void args_deinit(args_t *args)
++{
++ free(args->conf_file);
++ args->conf_file = NULL;
++}
++
++int args_parse(args_t *args, int argc, char *argv[])
++{
++ int c;
++ int option_index = 0;
++ int parse_err = 0;
++ static struct option long_options[] = {
++ {"query-all", 0, 0, 'A'},
++ {"conf-file", 1, 0, 'f'},
++ {"conf", 1, 0, 'f'},
++ {"dest", 1, 0, 'd'},
++ {"force-defaults", 0, 0, ARGS_OPT_FORCE_DEFAULTS},
++ {"force_defaults", 0, 0, ARGS_OPT_FORCE_DEFAULTS},
++ {"force-depends", 0, 0, ARGS_OPT_FORCE_DEPENDS},
++ {"force_depends", 0, 0, ARGS_OPT_FORCE_DEPENDS},
++ {"force-overwrite", 0, 0, ARGS_OPT_FORCE_OVERWRITE},
++ {"force_overwrite", 0, 0, ARGS_OPT_FORCE_OVERWRITE},
++ {"force_downgrade", 0, 0, ARGS_OPT_FORCE_DOWNGRADE},
++ {"force-downgrade", 0, 0, ARGS_OPT_FORCE_DOWNGRADE},
++ {"force-reinstall", 0, 0, ARGS_OPT_FORCE_REINSTALL},
++ {"force_reinstall", 0, 0, ARGS_OPT_FORCE_REINSTALL},
++ {"force-space", 0, 0, ARGS_OPT_FORCE_SPACE},
++ {"force_space", 0, 0, ARGS_OPT_FORCE_SPACE},
++ {"recursive", 0, 0,
++ ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES},
++ {"force-removal-of-dependent-packages", 0, 0,
++ ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES},
++ {"force_removal_of_dependent_packages", 0, 0,
++ ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES},
++ {"force-removal-of-essential-packages", 0, 0,
++ ARGS_OPT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES},
++ {"force_removal_of_essential_packages", 0, 0,
++ ARGS_OPT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES},
++ {"multiple-providers", 0, 0, ARGS_OPT_MULTIPLE_PROVIDERS},
++ {"multiple_providers", 0, 0, ARGS_OPT_MULTIPLE_PROVIDERS},
++ {"noaction", 0, 0, ARGS_OPT_NOACTION},
++ {"nodeps", 0, 0, ARGS_OPT_NODEPS},
++ {"offline", 1, 0, 'o'},
++ {"offline-root", 1, 0, 'o'},
++ {"test", 0, 0, ARGS_OPT_NOACTION},
++ {"tmp-dir", 1, 0, 't'},
++ {"verbose-wget", 0, 0, ARGS_OPT_VERBOSE_WGET},
++ {"verbose_wget", 0, 0, ARGS_OPT_VERBOSE_WGET},
++ {"verbosity", 2, 0, 'V'},
++ {"version", 0, 0, 'v'},
++ {0, 0, 0, 0}
++ };
++
++ while (1) {
++ c = getopt_long_only(argc, argv, "Ad:f:no:t:vV:", long_options, &option_index);
++ if (c == -1)
++ break;
++
++ switch (c) {
++ case 'A':
++ args->query_all = 1;
++ break;
++ case 'd':
++ args->dest = optarg;
++ break;
++ case 'f':
++ free(args->conf_file);
++ args->conf_file = strdup(optarg);
++ break;
++ case 'o':
++ args->offline_root = optarg;
++ break;
++ case 'n':
++ args->noaction = 1;
++ break;
++ case 't':
++ args->tmp_dir = strdup(optarg);
++ break;
++ case 'v':
++ print_version();
++ exit(0);
++ case 'V':
++ case ARGS_OPT_VERBOSITY:
++ if (optarg)
++ args->verbosity = atoi(optarg);
++ else
++ args->verbosity += 1;
++ break;
++ case ARGS_OPT_FORCE_DEFAULTS:
++ args->force_defaults = 1;
++ break;
++ case ARGS_OPT_FORCE_DEPENDS:
++ args->force_depends = 1;
++ break;
++ case ARGS_OPT_FORCE_OVERWRITE:
++ args->force_overwrite = 1;
++ break;
++ case ARGS_OPT_FORCE_DOWNGRADE:
++ args->force_downgrade = 1;
++ break;
++ case ARGS_OPT_FORCE_REINSTALL:
++ args->force_reinstall = 1;
++ break;
++ case ARGS_OPT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES:
++ args->force_removal_of_essential_packages = 1;
++ break;
++ case ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES:
++ args->force_removal_of_dependent_packages = 1;
++ break;
++ case ARGS_OPT_FORCE_SPACE:
++ args->force_space = 1;
++ break;
++ case ARGS_OPT_VERBOSE_WGET:
++ args->verbose_wget = 1;
++ break;
++ case ARGS_OPT_MULTIPLE_PROVIDERS:
++ args->multiple_providers = 1;
++ break;
++ case ARGS_OPT_NODEPS:
++ args->nodeps = 1;
++ break;
++ case ARGS_OPT_NOACTION:
++ args->noaction = 1;
++ break;
++ case ':':
++ parse_err++;
++ break;
++ case '?':
++ parse_err++;
++ break;
++ default:
++ bb_error_msg("Confusion: getopt_long returned %d\n", c);
++ }
++ }
++
++ if (parse_err) {
++ return -parse_err;
++ } else {
++ return optind;
++ }
++}
++
++void args_usage(char *complaint)
++{
++ if (complaint) {
++ bb_error_msg("%s\n", complaint);
++ }
++ print_version();
++ bb_show_usage();
++ exit(1);
++}
++
++static void print_version(void)
++{
++ bb_error_msg("version %s\n", IPKG_VERSION);
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/args.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/args.h
+--- busybox-1.2.0-orig/archival/libipkg/args.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/args.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,72 @@
++/* args.h - parse command-line args
++
++ Carl D. Worth
++
++ Copyright 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef ARGS_H
++#define ARGS_H
++
++struct args
++{
++ char *conf_file;
++ char *dest;
++ char *tmp_dir;
++ int force_defaults;
++ int force_depends;
++ int force_overwrite;
++ int force_downgrade;
++ int force_reinstall;
++ int force_removal_of_essential_packages;
++ int force_removal_of_dependent_packages;
++ int force_space;
++ int noaction;
++ int nodeps;
++ int multiple_providers;
++ int query_all;
++ int verbose_wget;
++ int verbosity;
++ int nocheckfordirorfile;
++ int noreadfeedsfile;
++ char *offline_root;
++ char *offline_root_pre_script_cmd;
++ char *offline_root_post_script_cmd;
++};
++typedef struct args args_t;
++
++#define ARGS_DEFAULT_CONF_FILE_DIR "/etc"
++#define ARGS_DEFAULT_CONF_FILE_NAME "ipkg.conf"
++#define ARGS_DEFAULT_DEST NULL
++#define ARGS_DEFAULT_FORCE_DEFAULTS 0
++#define ARGS_DEFAULT_FORCE_DEPENDS 0
++#define ARGS_DEFAULT_FORCE_OVERWRITE 0
++#define ARGS_DEFAULT_FORCE_DOWNGRADE 0
++#define ARGS_DEFAULT_FORCE_REINSTALL 0
++#define ARGS_DEFAULT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES 0
++#define ARGS_DEFAULT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES 0
++#define ARGS_DEFAULT_FORCE_SPACE 0
++#define ARGS_DEFAULT_OFFLINE_ROOT NULL
++#define ARGS_DEFAULT_OFFLINE_ROOT_PRE_SCRIPT_CMD NULL
++#define ARGS_DEFAULT_OFFLINE_ROOT_POST_SCRIPT_CMD NULL
++#define ARGS_DEFAULT_NOACTION 0
++#define ARGS_DEFAULT_NODEPS 0
++#define ARGS_DEFAULT_VERBOSE_WGET 0
++#define ARGS_DEFAULT_VERBOSITY 1
++
++int args_init(args_t *args);
++void args_deinit(args_t *args);
++int args_parse(args_t *args, int argc, char *argv[]);
++void args_usage(char *complaint);
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/conffile.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/conffile.c
+--- busybox-1.2.0-orig/archival/libipkg/conffile.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/conffile.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,64 @@
++/* conffile.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include <string.h>
++#include <stdlib.h>
++
++#include "ipkg.h"
++#include "ipkg_message.h"
++
++#include "conffile.h"
++#include "file_util.h"
++#include "sprintf_alloc.h"
++
++int conffile_init(conffile_t *conffile, const char *file_name, const char *md5sum)
++{
++ return nv_pair_init(conffile, file_name, md5sum);
++}
++
++void conffile_deinit(conffile_t *conffile)
++{
++ nv_pair_deinit(conffile);
++}
++
++int conffile_has_been_modified(ipkg_conf_t *conf, conffile_t *conffile)
++{
++ char *md5sum;
++ char *filename = conffile->name;
++ char *root_filename;
++ int ret;
++
++ if (conffile->value == NULL) {
++ ipkg_message(conf, IPKG_NOTICE, "%s: conffile %s has no md5sum\n", __FUNCTION__, conffile->name);
++ return 1;
++ }
++
++ root_filename = root_filename_alloc(conf, filename);
++
++ md5sum = file_md5sum_alloc(root_filename);
++
++ ret = strcmp(md5sum, conffile->value);
++ if (ret) {
++ ipkg_message(conf, IPKG_NOTICE, "%s: conffile %s: \t\nold md5=%s \t\nnew md5=%s\n", __FUNCTION__,
++ conffile->name, md5sum, conffile->value);
++ }
++
++ free(root_filename);
++ free(md5sum);
++
++ return ret;
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/conffile.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/conffile.h
+--- busybox-1.2.0-orig/archival/libipkg/conffile.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/conffile.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,30 @@
++/* conffile.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef CONFFILE_H
++#define CONFFILE_H
++
++#include "nv_pair.h"
++
++typedef struct nv_pair conffile_t;
++
++int conffile_init(conffile_t *conffile, const char *file_name, const char *md5sum);
++void conffile_deinit(conffile_t *conffile);
++int conffile_has_been_modified(struct ipkg_conf *conf, conffile_t *conffile);
++
++#endif
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/conffile_list.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/conffile_list.c
+--- busybox-1.2.0-orig/archival/libipkg/conffile_list.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/conffile_list.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,47 @@
++/* conffile_list.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++
++#include "conffile_list.h"
++
++int conffile_list_init(conffile_list_t *list)
++{
++ return nv_pair_list_init(list);
++}
++
++void conffile_list_deinit(conffile_list_t *list)
++{
++ nv_pair_list_deinit(list);
++}
++
++conffile_t *conffile_list_append(conffile_list_t *list, const char *file_name,
++ const char *md5sum)
++{
++ return nv_pair_list_append(list, file_name, md5sum);
++}
++
++int conffile_list_push(conffile_list_t *list, conffile_t *data)
++{
++ return nv_pair_list_push(list, data);
++}
++
++conffile_list_elt_t *conffile_list_pop(conffile_list_t *list)
++{
++ return nv_pair_list_pop(list);
++}
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/conffile_list.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/conffile_list.h
+--- busybox-1.2.0-orig/archival/libipkg/conffile_list.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/conffile_list.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,36 @@
++/* conffile_list.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef CONFFILE_LIST_H
++#define CONFFILE_LIST_H
++
++#include "conffile.h"
++#include "nv_pair_list.h"
++
++typedef struct nv_pair_list_elt conffile_list_elt_t;
++typedef struct nv_pair_list conffile_list_t;
++
++int conffile_list_init(conffile_list_t *list);
++void conffile_list_deinit(conffile_list_t *list);
++
++conffile_t *conffile_list_append(conffile_list_t *list, const char *name,
++ const char *root_dir);
++int conffile_list_push(conffile_list_t *list, conffile_t *data);
++conffile_list_elt_t *conffile_list_pop(conffile_list_t *list);
++
++#endif
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/file_util.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/file_util.c
+--- busybox-1.2.0-orig/archival/libipkg/file_util.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/file_util.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,177 @@
++/* file_util.c - convenience routines for common stat operations
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++#include <sys/types.h>
++#include <sys/stat.h>
++
++#include "sprintf_alloc.h"
++#include "file_util.h"
++#include "md5.h"
++#include "libbb.h"
++#undef strlen
++
++int file_exists(const char *file_name)
++{
++ int err;
++ struct stat stat_buf;
++
++ err = stat(file_name, &stat_buf);
++ if (err == 0) {
++ return 1;
++ } else {
++ return 0;
++ }
++}
++
++int file_is_dir(const char *file_name)
++{
++ int err;
++ struct stat stat_buf;
++
++ err = stat(file_name, &stat_buf);
++ if (err) {
++ return 0;
++ }
++
++ return S_ISDIR(stat_buf.st_mode);
++}
++
++/* read a single line from a file, stopping at a newline or EOF.
++ If a newline is read, it will appear in the resulting string.
++ Return value is a malloc'ed char * which should be freed at
++ some point by the caller.
++
++ Return value is NULL if the file is at EOF when called.
++*/
++#define FILE_READ_LINE_BUF_SIZE 1024
++char *file_read_line_alloc(FILE *file)
++{
++ char buf[FILE_READ_LINE_BUF_SIZE];
++ int buf_len;
++ char *line = NULL;
++ int line_size = 0;
++
++ memset(buf, 0, FILE_READ_LINE_BUF_SIZE);
++ while (fgets(buf, FILE_READ_LINE_BUF_SIZE, file)) {
++ buf_len = strlen(buf);
++ if (line) {
++ line_size += buf_len;
++ line = realloc(line, line_size);
++ if (line == NULL) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ break;
++ }
++ strcat(line, buf);
++ } else {
++ line_size = buf_len + 1;
++ line = strdup(buf);
++ }
++ if (buf[buf_len - 1] == '\n') {
++ break;
++ }
++ }
++
++ return line;
++}
++
++int file_move(const char *src, const char *dest)
++{
++ int err;
++
++ err = rename(src, dest);
++
++ if (err && errno == EXDEV) {
++ err = file_copy(src, dest);
++ unlink(src);
++ } else if (err) {
++ fprintf(stderr, "%s: ERROR: failed to rename %s to %s: %s\n",
++ __FUNCTION__, src, dest, strerror(errno));
++ }
++
++ return err;
++}
++
++/* I put these here to keep libbb dependencies from creeping all over
++ the ipkg code */
++int file_copy(const char *src, const char *dest)
++{
++ int err;
++
++ err = copy_file(src, dest, FILEUTILS_FORCE | FILEUTILS_PRESERVE_STATUS);
++ if (err) {
++ fprintf(stderr, "%s: ERROR: failed to copy %s to %s\n",
++ __FUNCTION__, src, dest);
++ }
++
++ return err;
++}
++
++int file_mkdir_hier(const char *path, long mode)
++{
++ return bb_make_directory(path, mode, FILEUTILS_RECUR);
++}
++
++char *file_md5sum_alloc(const char *file_name)
++{
++ static const int md5sum_bin_len = 16;
++ static const int md5sum_hex_len = 32;
++
++ static const unsigned char bin2hex[16] = {
++ '0', '1', '2', '3',
++ '4', '5', '6', '7',
++ '8', '9', 'a', 'b',
++ 'c', 'd', 'e', 'f'
++ };
++
++ int i, err;
++ FILE *file;
++ unsigned char *md5sum_hex;
++ unsigned char md5sum_bin[md5sum_bin_len];
++
++ md5sum_hex = malloc(md5sum_hex_len + 1);
++ if (md5sum_hex == NULL) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return strdup("");
++ }
++
++ file = fopen(file_name, "r");
++ if (file == NULL) {
++ fprintf(stderr, "%s: Failed to open file %s: %s\n",
++ __FUNCTION__, file_name, strerror(errno));
++ return strdup("");
++ }
++
++ err = md5_stream(file, md5sum_bin);
++ if (err) {
++ fprintf(stderr, "%s: ERROR computing md5sum for %s: %s\n",
++ __FUNCTION__, file_name, strerror(err));
++ return strdup("");
++ }
++
++ fclose(file);
++
++ for (i=0; i < md5sum_bin_len; i++) {
++ md5sum_hex[i*2] = bin2hex[md5sum_bin[i] >> 4];
++ md5sum_hex[i*2+1] = bin2hex[md5sum_bin[i] & 0xf];
++ }
++
++ md5sum_hex[md5sum_hex_len] = '\0';
++
++ return md5sum_hex;
++}
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/file_util.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/file_util.h
+--- busybox-1.2.0-orig/archival/libipkg/file_util.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/file_util.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,29 @@
++/* file_util.h - convenience routines for common file operations
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef FILE_UTIL_H
++#define FILE_UTIL_H
++
++int file_exists(const char *file_name);
++int file_is_dir(const char *file_name);
++char *file_read_line_alloc(FILE *file);
++int file_move(const char *src, const char *dest);
++int file_copy(const char *src, const char *dest);
++int file_mkdir_hier(const char *path, long mode);
++char *file_md5sum_alloc(const char *file_name);
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/hash_table.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/hash_table.c
+--- busybox-1.2.0-orig/archival/libipkg/hash_table.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/hash_table.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,155 @@
++/* hash.c - hash tables for ipkg
++
++ Steven M. Ayer, Jamey Hicks
++
++ Copyright (C) 2002 Compaq Computer Corporation
++
++ 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.
++*/
++
++#include <errno.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include "hash_table.h"
++#include "ipkg_message.h"
++
++
++static int hash_index(hash_table_t *hash, const char *pkg_name);
++static int rotating(const char *key, int len, int prime);
++
++static int hash_index(hash_table_t *hash, const char *pkg_name)
++{
++ return rotating(pkg_name, strlen(pkg_name), hash->n_entries);
++}
++
++static int rotating(const char *key, int len, int prime)
++{
++ unsigned int hash, i;
++ for (hash=len, i=0; i<len; ++i)
++ hash = (hash<<4)^(hash>>28)^key[i];
++ return (hash % prime);
++}
++
++
++/*
++ * this is an open table keyed by strings
++ */
++int hash_table_init(const char *name, hash_table_t *hash, int len)
++{
++ static int primes_table[] = {
++ 379, 761, 983, 1423, 2711, 3361, 3931, 4679, 5519, 6701, 9587,
++ 19471, 23143, 33961, 46499, 49727, 99529, 0
++ };
++ int *picker;
++
++ if (hash->entries != NULL) {
++ /* we have been here already */
++ return 0;
++ }
++
++ hash->name = name;
++ hash->entries = NULL;
++ hash->n_entries = 0;
++ hash->hash_entry_key = NULL;
++
++ picker = primes_table;
++ while(*picker && (*picker++ < len));
++ if(!*picker)
++ fprintf(stderr, "%s: primes table might not be big enough (! << %d)\n", __FUNCTION__, len);
++ --picker;
++
++ hash->n_entries = *picker;
++ hash->entries = (hash_entry_t *)calloc(hash->n_entries, sizeof(hash_entry_t));
++ if (hash->entries == NULL) {
++ fprintf(stderr, "%s: Out of memory.\n", __FUNCTION__);
++ return ENOMEM;
++ }
++ return 0;
++}
++
++void hash_table_deinit(hash_table_t *hash)
++{
++ free(hash->entries);
++ hash->entries = NULL;
++ hash->n_entries = 0;
++}
++
++void *hash_table_get(hash_table_t *hash, const char *key)
++{
++ int ndx= hash_index(hash, key);
++ hash_entry_t *hash_entry = hash->entries + ndx;
++ while (hash_entry)
++ {
++ if (hash_entry->key)
++ {
++ if (strcmp(key, hash_entry->key) == 0) {
++ // ipkg_message(NULL, IPKG_DEBUG, "Function: %s. Key found for '%s' \n", __FUNCTION__, key);
++ return hash_entry->data;
++ }
++ }
++ hash_entry = hash_entry->next;
++ }
++ return NULL;
++}
++
++int hash_table_insert(hash_table_t *hash, const char *key, void *value)
++{
++ int ndx= hash_index(hash, key);
++ hash_entry_t *hash_entry = hash->entries + ndx;
++ if (0) ipkg_message(NULL, IPKG_DEBUG2, "Function: %s. Inserting in hash for '%s' \n", __FUNCTION__, key);
++ if (hash_entry->key) {
++ if (strcmp(hash_entry->key, key) == 0) {
++ /* alread in table, update the value */
++ if (0) ipkg_message(NULL, IPKG_DEBUG2, "Function: %s. Value already in hash for '%s' \n", __FUNCTION__, key);
++ hash_entry->data = value;
++ return 0;
++ } else {
++ /*
++ * if this is a collision, we have to go to the end of the ll,
++ * then add a new entry
++ * before we can hook up the value
++ */
++ if (0) ipkg_message(NULL, IPKG_DEBUG2, "Function: %s. Value already in hash by collision for '%s' \n", __FUNCTION__, key);
++ while (hash_entry->next)
++ hash_entry = hash_entry->next;
++ hash_entry->next = (hash_entry_t *)malloc(sizeof(hash_entry_t));
++ if (!hash_entry->next) {
++ return -ENOMEM;
++ }
++ hash_entry = hash_entry->next;
++ hash_entry->next = NULL;
++ }
++ }
++ hash->n_elements++;
++ hash_entry->key = strdup(key);
++ hash_entry->data = value;
++
++ return 0;
++}
++
++
++void hash_table_foreach(hash_table_t *hash, void (*f)(const char *key, void *entry, void *data), void *data)
++{
++ int i;
++ if (!hash || !f)
++ return;
++
++ for (i = 0; i < hash->n_entries; i++) {
++ hash_entry_t *hash_entry = (hash->entries + i);
++ do {
++ if(hash_entry->key) {
++ f(hash_entry->key, hash_entry->data, data);
++ }
++ } while((hash_entry = hash_entry->next));
++ }
++}
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/hash_table.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/hash_table.h
+--- busybox-1.2.0-orig/archival/libipkg/hash_table.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/hash_table.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,44 @@
++/* hash.h - hash tables for ipkg
++
++ Steven M. Ayer, Jamey Hicks
++
++ Copyright (C) 2002 Compaq Computer Corporation
++
++ 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.
++*/
++
++#ifndef _HASH_TABLE_H_
++#define _HASH_TABLE_H_
++
++typedef struct hash_entry hash_entry_t;
++typedef struct hash_table hash_table_t;
++
++struct hash_entry {
++ const char * key;
++ void * data;
++ struct hash_entry * next;
++};
++
++struct hash_table {
++ const char *name;
++ hash_entry_t * entries;
++ int n_entries; /* number of buckets */
++ int n_elements;
++ const char * (*hash_entry_key)(void * data);
++};
++
++int hash_table_init(const char *name, hash_table_t *hash, int len);
++void hash_table_deinit(hash_table_t *hash);
++void *hash_table_get(hash_table_t *hash, const char *key);
++int hash_table_insert(hash_table_t *hash, const char *key, void *value);
++void hash_table_foreach(hash_table_t *hash, void (*f)(const char *key, void *entry, void *data), void *data);
++
++#endif /* _HASH_TABLE_H_ */
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_cmd.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_cmd.c
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_cmd.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_cmd.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,1431 @@
++/* ipkg_cmd.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include <string.h>
++
++#include "ipkg.h"
++#include <libgen.h>
++#include <glob.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <signal.h>
++#include <stdio.h>
++#include <dirent.h>
++
++#include "ipkg_conf.h"
++#include "ipkg_cmd.h"
++#include "ipkg_message.h"
++#include "pkg.h"
++#include "pkg_dest.h"
++#include "pkg_parse.h"
++#include "sprintf_alloc.h"
++#include "pkg.h"
++#include "file_util.h"
++#include "str_util.h"
++#include "libbb.h"
++#include "unarchive.h"
++
++#include <fnmatch.h>
++
++
++#include "ipkg_download.h"
++#include "ipkg_install.h"
++#include "ipkg_upgrade.h"
++#include "ipkg_remove.h"
++#include "ipkg_configure.h"
++#include "ipkg_message.h"
++
++#ifdef IPKG_LIB
++#include "libipkg.h"
++static void *p_userdata = NULL;
++#endif
++
++static int ipkg_update_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_upgrade_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_list_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_info_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_status_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_install_pending_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_install_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_list_installed_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_remove_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_purge_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_flag_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_files_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_search_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_download_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_depends_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_whatdepends_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_whatdepends_recursively_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_whatsuggests_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_whatrecommends_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_whatprovides_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_whatconflicts_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_whatreplaces_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_compare_versions_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_print_architecture_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_configure_cmd(ipkg_conf_t *conf, int argc, char **argv);
++
++/* XXX: CLEANUP: The usage strings should be incorporated into this
++ array for easier maintenance */
++static ipkg_cmd_t cmds[] = {
++ {"update", 0, (ipkg_cmd_fun_t)ipkg_update_cmd},
++ {"upgrade", 0, (ipkg_cmd_fun_t)ipkg_upgrade_cmd},
++ {"list", 0, (ipkg_cmd_fun_t)ipkg_list_cmd},
++ {"list_installed", 0, (ipkg_cmd_fun_t)ipkg_list_installed_cmd},
++ {"info", 0, (ipkg_cmd_fun_t)ipkg_info_cmd},
++ {"flag", 1, (ipkg_cmd_fun_t)ipkg_flag_cmd},
++ {"status", 0, (ipkg_cmd_fun_t)ipkg_status_cmd},
++ {"install_pending", 0, (ipkg_cmd_fun_t)ipkg_install_pending_cmd},
++ {"install", 1, (ipkg_cmd_fun_t)ipkg_install_cmd},
++ {"remove", 1, (ipkg_cmd_fun_t)ipkg_remove_cmd},
++ {"purge", 1, (ipkg_cmd_fun_t)ipkg_purge_cmd},
++ {"configure", 0, (ipkg_cmd_fun_t)ipkg_configure_cmd},
++ {"files", 1, (ipkg_cmd_fun_t)ipkg_files_cmd},
++ {"search", 1, (ipkg_cmd_fun_t)ipkg_search_cmd},
++ {"download", 1, (ipkg_cmd_fun_t)ipkg_download_cmd},
++ {"compare_versions", 1, (ipkg_cmd_fun_t)ipkg_compare_versions_cmd},
++ {"compare-versions", 1, (ipkg_cmd_fun_t)ipkg_compare_versions_cmd},
++ {"print-architecture", 0, (ipkg_cmd_fun_t)ipkg_print_architecture_cmd},
++ {"print_architecture", 0, (ipkg_cmd_fun_t)ipkg_print_architecture_cmd},
++ {"print-installation-architecture", 0, (ipkg_cmd_fun_t)ipkg_print_architecture_cmd},
++ {"print_installation_architecture", 0, (ipkg_cmd_fun_t)ipkg_print_architecture_cmd},
++ {"depends", 1, (ipkg_cmd_fun_t)ipkg_depends_cmd},
++ {"whatdepends", 1, (ipkg_cmd_fun_t)ipkg_whatdepends_cmd},
++ {"whatdependsrec", 1, (ipkg_cmd_fun_t)ipkg_whatdepends_recursively_cmd},
++ {"whatrecommends", 1, (ipkg_cmd_fun_t)ipkg_whatrecommends_cmd},
++ {"whatsuggests", 1, (ipkg_cmd_fun_t)ipkg_whatsuggests_cmd},
++ {"whatprovides", 1, (ipkg_cmd_fun_t)ipkg_whatprovides_cmd},
++ {"whatreplaces", 1, (ipkg_cmd_fun_t)ipkg_whatreplaces_cmd},
++ {"whatconflicts", 1, (ipkg_cmd_fun_t)ipkg_whatconflicts_cmd},
++};
++
++int ipkg_state_changed;
++static void write_status_files_if_changed(ipkg_conf_t *conf)
++{
++ if (ipkg_state_changed && !conf->noaction) {
++ ipkg_message(conf, IPKG_INFO,
++ " writing status file\n");
++ ipkg_conf_write_status_files(conf);
++ pkg_write_changed_filelists(conf);
++ } else {
++ ipkg_message(conf, IPKG_NOTICE, "Nothing to be done\n");
++ }
++}
++
++
++static int num_cmds = sizeof(cmds) / sizeof(ipkg_cmd_t);
++
++ipkg_cmd_t *ipkg_cmd_find(const char *name)
++{
++ int i;
++ ipkg_cmd_t *cmd;
++
++ for (i=0; i < num_cmds; i++) {
++ cmd = &cmds[i];
++ if (strcmp(name, cmd->name) == 0) {
++ return cmd;
++ }
++ }
++
++ return NULL;
++}
++
++#ifdef IPKG_LIB
++int ipkg_cmd_exec(ipkg_cmd_t *cmd, ipkg_conf_t *conf, int argc, const char **argv, void *userdata)
++{
++ int result;
++ p_userdata = userdata;
++
++
++ result = (cmd->fun)(conf, argc, argv);
++ if ( result == 0 ) {
++ ipkg_message(conf, IPKG_NOTICE, "Done.\n");
++ } else {
++ ipkg_message(conf, IPKG_NOTICE, "An error ocurred, return value: %d.\n", result);
++
++ }
++ if ( error_list ) {
++ reverse_error_list(&error_list);
++
++ ipkg_message(conf, IPKG_NOTICE, "Collected errors:\n");
++ /* Here we print the errors collected and free the list */
++ while (error_list != NULL) {
++ ipkg_message(conf, IPKG_NOTICE, "%s",error_list->errmsg);
++ error_list = error_list->next;
++
++ }
++ free_error_list(&error_list);
++
++ }
++
++ p_userdata = NULL;
++ return result;
++}
++#else
++int ipkg_cmd_exec(ipkg_cmd_t *cmd, ipkg_conf_t *conf, int argc, const char **argv)
++{
++ return (cmd->fun)(conf, argc, argv);
++}
++#endif
++
++static int ipkg_update_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ int err;
++ int failures;
++ char *lists_dir;
++ pkg_src_list_elt_t *iter;
++ pkg_src_t *src;
++
++
++ sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir);
++
++ if (! file_is_dir(lists_dir)) {
++ if (file_exists(lists_dir)) {
++ ipkg_message(conf, IPKG_ERROR,
++ "%s: ERROR: %s exists, but is not a directory\n",
++ __FUNCTION__, lists_dir);
++ free(lists_dir);
++ return EINVAL;
++ }
++ err = file_mkdir_hier(lists_dir, 0755);
++ if (err) {
++ ipkg_message(conf, IPKG_ERROR,
++ "%s: ERROR: failed to make directory %s: %s\n",
++ __FUNCTION__, lists_dir, strerror(errno));
++ free(lists_dir);
++ return EINVAL;
++ }
++ }
++
++ failures = 0;
++ for (iter = conf->pkg_src_list.head; iter; iter = iter->next) {
++ char *url, *list_file_name;
++
++ src = iter->data;
++
++ if (src->extra_data) /* debian style? */
++ sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
++ src->gzip ? "Packages.gz" : "Packages");
++ else
++ sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages");
++
++ sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
++ if (src->gzip) {
++ char *tmp;
++ char *tmp_file_name;
++ FILE *in, *out;
++
++ tmp = strdup ("/tmp/ipkg.XXXXXX");
++
++ if (mkdtemp (tmp) == NULL) {
++ perror ("mkdtemp");
++ failures++;
++ continue;
++ }
++
++ sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name);
++ err = ipkg_download(conf, url, tmp_file_name);
++ if (err == 0) {
++ ipkg_message (conf, IPKG_NOTICE, "Inflating %s\n", url);
++ in = fopen (tmp_file_name, "r");
++ out = fopen (list_file_name, "w");
++ if (in && out)
++ inflate_unzip (in, out);
++ else
++ err = 1;
++ if (in)
++ fclose (in);
++ if (out)
++ fclose (out);
++ unlink (tmp_file_name);
++ rmdir (tmp);
++ free (tmp);
++ }
++ } else
++ err = ipkg_download(conf, url, list_file_name);
++ if (err) {
++ failures++;
++ } else {
++ ipkg_message(conf, IPKG_NOTICE,
++ "Updated list of available packages in %s\n",
++ list_file_name);
++ }
++ free(url);
++ free(list_file_name);
++ }
++ free(lists_dir);
++
++#ifdef CONFIG_CLEAR_SW_INSTALL_FLAG
++#warning here
++ /* clear SW_INSTALL on any package where state is SS_NOT_INSTALLED.
++ * this is a hack to work around poor bookkeeping in old ipkg upgrade code
++ * -Jamey 3/1/03
++ */
++ {
++ int i;
++ int changed = 0;
++ pkg_vec_t *available = pkg_vec_alloc();
++ pkg_hash_fetch_available(&conf->pkg_hash, available);
++ ipkg_message(conf, IPKG_DEBUG, "Clearing SW_INSTALL for SS_NOT_INSTALLED packages.\n");
++ for (i = 0; i < available->len; i++) {
++ pkg_t *pkg = available->pkgs[i];
++ if (pkg->state_want == SW_INSTALL && pkg->state_status == SS_NOT_INSTALLED) {
++ ipkg_message(conf, IPKG_DEBUG, "Clearing SW_INSTALL on package %s.\n", pkg->name);
++ pkg->state_want = SW_UNKNOWN;
++ changed = 1;
++ }
++ }
++ pkg_vec_free(available);
++ if (changed) {
++ write_status_files_if_changed(conf);
++ }
++ }
++#endif
++
++ return failures;
++}
++
++
++/* scan the args passed and cache the local filenames of the packages */
++int ipkg_multiple_files_scan(ipkg_conf_t *conf, int argc, char **argv)
++{
++ int i;
++ int err;
++
++ /*
++ * First scan through package names/urls
++ * For any urls, download the packages and install in database.
++ * For any files, install package info in database.
++ */
++ for (i = 0; i < argc; i ++) {
++ char *filename = argv [i];
++ //char *tmp = basename (tmp);
++ //int tmplen = strlen (tmp);
++
++ //if (strcmp (tmp + (tmplen - strlen (IPKG_PKG_EXTENSION)), IPKG_PKG_EXTENSION) != 0)
++ // continue;
++ //if (strcmp (tmp + (tmplen - strlen (DPKG_PKG_EXTENSION)), DPKG_PKG_EXTENSION) != 0)
++ // continue;
++
++ ipkg_message(conf, IPKG_DEBUG2, "Debug mfs: %s \n",filename );
++
++ err = ipkg_prepare_url_for_install(conf, filename, &argv[i]);
++ if (err)
++ return err;
++ }
++ return 0;
++}
++
++struct ipkg_intercept
++{
++ char *oldpath;
++ char *statedir;
++};
++
++typedef struct ipkg_intercept *ipkg_intercept_t;
++
++ipkg_intercept_t ipkg_prep_intercepts(ipkg_conf_t *conf)
++{
++ ipkg_intercept_t ctx;
++ char *newpath;
++ int gen;
++
++ ctx = malloc (sizeof (*ctx));
++ ctx->oldpath = strdup (getenv ("PATH"));
++
++ sprintf_alloc (&newpath, "%s/ipkg/intercept:%s", IPKGLIBDIR, ctx->oldpath);
++ setenv ("PATH", newpath, 1);
++ free (newpath);
++
++ gen = 0;
++ retry:
++ sprintf_alloc (&ctx->statedir, "/tmp/ipkg-intercept-%d-%d", getpid (), gen);
++ if (mkdir (ctx->statedir, 0770) < 0) {
++ if (errno == EEXIST) {
++ free (ctx->statedir);
++ gen++;
++ goto retry;
++ }
++ perror (ctx->statedir);
++ return NULL;
++ }
++ setenv ("IPKG_INTERCEPT_DIR", ctx->statedir, 1);
++ return ctx;
++}
++
++int ipkg_finalize_intercepts(ipkg_intercept_t ctx)
++{
++ char *cmd;
++ DIR *dir;
++ int err = 0;
++
++ setenv ("PATH", ctx->oldpath, 1);
++ free (ctx->oldpath);
++
++ dir = opendir (ctx->statedir);
++ if (dir) {
++ struct dirent *de;
++ while (de = readdir (dir), de != NULL) {
++ char *path;
++
++ if (de->d_name[0] == '.')
++ continue;
++
++ sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
++ if (access (path, X_OK) == 0) {
++ if (system (path)) {
++ err = errno;
++ perror (de->d_name);
++ }
++ }
++ free (path);
++ }
++ } else
++ perror (ctx->statedir);
++
++ sprintf_alloc (&cmd, "rm -rf %s", ctx->statedir);
++ system (cmd);
++ free (cmd);
++
++ free (ctx->statedir);
++ free (ctx);
++
++ return err;
++}
++
++int ipkg_configure_packages(ipkg_conf_t *conf, char *pkg_name)
++{
++ pkg_vec_t *all;
++ int i;
++ pkg_t *pkg;
++ ipkg_intercept_t ic;
++ int r, err = 0;
++
++ ipkg_message(conf, IPKG_INFO,
++ "Configuring unpacked packages\n");
++ fflush( stdout );
++
++ all = pkg_vec_alloc();
++ pkg_hash_fetch_available(&conf->pkg_hash, all);
++
++ ic = ipkg_prep_intercepts (conf);
++
++ for(i = 0; i < all->len; i++) {
++ pkg = all->pkgs[i];
++
++ if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
++ continue;
++
++ if (pkg->state_status == SS_UNPACKED) {
++ ipkg_message(conf, IPKG_NOTICE,
++ "Configuring %s\n", pkg->name);
++ fflush( stdout );
++ r = ipkg_configure(conf, pkg);
++ if (r == 0) {
++ pkg->state_status = SS_INSTALLED;
++ pkg->parent->state_status = SS_INSTALLED;
++ pkg->state_flag &= ~SF_PREFER;
++ } else {
++ if (!err)
++ err = r;
++ }
++ }
++ }
++
++ r = ipkg_finalize_intercepts (ic);
++ if (r && !err)
++ err = r;
++
++ pkg_vec_free(all);
++ return err;
++}
++
++static void sigint_handler(int sig)
++{
++ signal(sig, SIG_DFL);
++ ipkg_message(NULL, IPKG_NOTICE,
++ "ipkg: interrupted. writing out status database\n");
++ write_status_files_if_changed(global_conf);
++ exit(128 + sig);
++}
++
++static int ipkg_install_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ int i;
++ char *arg;
++ int err=0;
++
++ global_conf = conf;
++ signal(SIGINT, sigint_handler);
++
++ /*
++ * Now scan through package names and install
++ */
++ for (i=0; i < argc; i++) {
++ arg = argv[i];
++
++ ipkg_message(conf, IPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
++ err = ipkg_prepare_url_for_install(conf, arg, &argv[i]);
++ if (err != EINVAL && err != 0)
++ return err;
++ }
++ pkg_info_preinstall_check(conf);
++
++ for (i=0; i < argc; i++) {
++ arg = argv[i];
++ if (conf->multiple_providers)
++ err = ipkg_install_multi_by_name(conf, arg);
++ else{
++ err = ipkg_install_by_name(conf, arg);
++ }
++ if (err == IPKG_PKG_HAS_NO_CANDIDATE) {
++ ipkg_message(conf, IPKG_ERROR,
++ "Cannot find package %s.\n"
++ "Check the spelling or perhaps run 'ipkg update'\n",
++ arg);
++ }
++ }
++
++ /* recheck to verify that all dependences are satisfied */
++ if (0) ipkg_satisfy_all_dependences(conf);
++
++ ipkg_configure_packages(conf, NULL);
++
++ write_status_files_if_changed(conf);
++
++ return err;
++}
++
++static int ipkg_upgrade_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ int i;
++ pkg_t *pkg;
++ int err;
++
++ global_conf = conf;
++ signal(SIGINT, sigint_handler);
++
++ if (argc) {
++ for (i=0; i < argc; i++) {
++ char *arg = argv[i];
++
++ err = ipkg_prepare_url_for_install(conf, arg, &arg);
++ if (err != EINVAL && err != 0)
++ return err;
++ }
++ pkg_info_preinstall_check(conf);
++
++ for (i=0; i < argc; i++) {
++ char *arg = argv[i];
++ if (conf->restrict_to_default_dest) {
++ pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
++ argv[i],
++ conf->default_dest);
++ if (pkg == NULL) {
++ ipkg_message(conf, IPKG_NOTICE,
++ "Package %s not installed in %s\n",
++ argv[i], conf->default_dest->name);
++ continue;
++ }
++ } else {
++ pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
++ argv[i]);
++ }
++ if (pkg)
++ ipkg_upgrade_pkg(conf, pkg);
++ else {
++ ipkg_install_by_name(conf, arg);
++ }
++ }
++ } else {
++ pkg_vec_t *installed = pkg_vec_alloc();
++
++ pkg_info_preinstall_check(conf);
++
++ pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
++ for (i = 0; i < installed->len; i++) {
++ pkg = installed->pkgs[i];
++ ipkg_upgrade_pkg(conf, pkg);
++ }
++ pkg_vec_free(installed);
++ }
++
++ /* recheck to verify that all dependences are satisfied */
++ if (0) ipkg_satisfy_all_dependences(conf);
++
++ ipkg_configure_packages(conf, NULL);
++
++ write_status_files_if_changed(conf);
++
++ return 0;
++}
++
++static int ipkg_download_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ int i, err;
++ char *arg;
++ pkg_t *pkg;
++
++ pkg_info_preinstall_check(conf);
++ for (i = 0; i < argc; i++) {
++ arg = argv[i];
++
++ pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg);
++ if (pkg == NULL) {
++ ipkg_message(conf, IPKG_ERROR,
++ "Cannot find package %s.\n"
++ "Check the spelling or perhaps run 'ipkg update'\n",
++ arg);
++ continue;
++ }
++
++ err = ipkg_download_pkg(conf, pkg, ".");
++
++ if (err) {
++ ipkg_message(conf, IPKG_ERROR,
++ "Failed to download %s\n", pkg->name);
++ } else {
++ ipkg_message(conf, IPKG_NOTICE,
++ "Downloaded %s as %s\n",
++ pkg->name, pkg->local_filename);
++ }
++ }
++
++ return 0;
++}
++
++
++static int ipkg_list_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ int i ;
++ pkg_vec_t *available;
++ pkg_t *pkg;
++ char desc_short[IPKG_LIST_DESCRIPTION_LENGTH];
++ char *newline;
++ char *pkg_name = NULL;
++ char *version_str;
++
++ if (argc > 0) {
++ pkg_name = argv[0];
++ }
++ available = pkg_vec_alloc();
++ pkg_hash_fetch_available(&conf->pkg_hash, available);
++ for (i=0; i < available->len; i++) {
++ pkg = available->pkgs[i];
++ /* if we have package name or pattern and pkg does not match, then skip it */
++ if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
++ continue;
++ if (pkg->description) {
++ strncpy(desc_short, pkg->description, IPKG_LIST_DESCRIPTION_LENGTH);
++ } else {
++ desc_short[0] = '\0';
++ }
++ desc_short[IPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
++ newline = strchr(desc_short, '\n');
++ if (newline) {
++ *newline = '\0';
++ }
++#ifndef IPKG_LIB
++ printf("%s - %s\n", pkg->name, desc_short);
++#else
++ if (ipkg_cb_list) {
++ version_str = pkg_version_str_alloc(pkg);
++ ipkg_cb_list(pkg->name,desc_short,
++ version_str,
++ pkg->state_status,
++ p_userdata);
++ free(version_str);
++ }
++#endif
++ }
++ pkg_vec_free(available);
++
++ return 0;
++}
++
++
++static int ipkg_list_installed_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ int i ;
++ pkg_vec_t *available;
++ pkg_t *pkg;
++ char desc_short[IPKG_LIST_DESCRIPTION_LENGTH];
++ char *newline;
++ char *pkg_name = NULL;
++ char *version_str;
++
++ if (argc > 0) {
++ pkg_name = argv[0];
++ }
++ available = pkg_vec_alloc();
++ pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
++ for (i=0; i < available->len; i++) {
++ pkg = available->pkgs[i];
++ /* if we have package name or pattern and pkg does not match, then skip it */
++ if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
++ continue;
++ if (pkg->description) {
++ strncpy(desc_short, pkg->description, IPKG_LIST_DESCRIPTION_LENGTH);
++ } else {
++ desc_short[0] = '\0';
++ }
++ desc_short[IPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
++ newline = strchr(desc_short, '\n');
++ if (newline) {
++ *newline = '\0';
++ }
++#ifndef IPKG_LIB
++ printf("%s - %s\n", pkg->name, desc_short);
++#else
++ if (ipkg_cb_list) {
++ version_str = pkg_version_str_alloc(pkg);
++ ipkg_cb_list(pkg->name,desc_short,
++ version_str,
++ pkg->state_status,
++ p_userdata);
++ free(version_str);
++ }
++#endif
++ }
++
++ return 0;
++}
++
++static int ipkg_info_status_cmd(ipkg_conf_t *conf, int argc, char **argv, int installed_only)
++{
++ int i;
++ pkg_vec_t *available;
++ pkg_t *pkg;
++ char *pkg_name = NULL;
++ char **pkg_fields = NULL;
++ int n_fields = 0;
++ char *buff ; // = (char *)malloc(1);
++
++ if (argc > 0) {
++ pkg_name = argv[0];
++ }
++ if (argc > 1) {
++ pkg_fields = &argv[1];
++ n_fields = argc - 1;
++ }
++
++ available = pkg_vec_alloc();
++ if (installed_only)
++ pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
++ else
++ pkg_hash_fetch_available(&conf->pkg_hash, available);
++ for (i=0; i < available->len; i++) {
++ pkg = available->pkgs[i];
++ if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
++ continue;
++ }
++#ifndef IPKG_LIB
++ if (n_fields) {
++ for (j = 0; j < n_fields; j++)
++ pkg_print_field(pkg, stdout, pkg_fields[j]);
++ } else {
++ pkg_print_info(pkg, stdout);
++ }
++#else
++
++ buff = pkg_formatted_info(pkg);
++ if ( buff ) {
++ if (ipkg_cb_status) ipkg_cb_status(pkg->name,
++ pkg->state_status,
++ buff,
++ p_userdata);
++/*
++ We should not forget that actually the pointer is allocated.
++ We need to free it :) ( Thanks florian for seeing the error )
++*/
++ free(buff);
++ }
++#endif
++ if (conf->verbosity > 1) {
++ conffile_list_elt_t *iter;
++ for (iter = pkg->conffiles.head; iter; iter = iter->next) {
++ conffile_t *cf = iter->data;
++ int modified = conffile_has_been_modified(conf, cf);
++ ipkg_message(conf, IPKG_NOTICE, "conffile=%s md5sum=%s modified=%d\n",
++ cf->name, cf->value, modified);
++ }
++ }
++ }
++#ifndef IPKG_LIB
++ if (buff)
++ free(buff);
++#endif
++ pkg_vec_free(available);
++
++ return 0;
++}
++
++static int ipkg_info_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ return ipkg_info_status_cmd(conf, argc, argv, 0);
++}
++
++static int ipkg_status_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ return ipkg_info_status_cmd(conf, argc, argv, 1);
++}
++
++static int ipkg_configure_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++
++ int err;
++ if (argc > 0) {
++ char *pkg_name = NULL;
++
++ pkg_name = argv[0];
++
++ err = ipkg_configure_packages (conf, pkg_name);
++
++ } else {
++ err = ipkg_configure_packages (conf, NULL);
++ }
++
++ write_status_files_if_changed(conf);
++
++ return err;
++}
++
++static int ipkg_install_pending_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ int i, err;
++ char *globpattern;
++ glob_t globbuf;
++
++ sprintf_alloc(&globpattern, "%s/*" IPKG_PKG_EXTENSION, conf->pending_dir);
++ err = glob(globpattern, 0, NULL, &globbuf);
++ free(globpattern);
++ if (err) {
++ return 0;
++ }
++
++ ipkg_message(conf, IPKG_NOTICE,
++ "The following packages in %s will now be installed.\n",
++ conf->pending_dir);
++ for (i = 0; i < globbuf.gl_pathc; i++) {
++ ipkg_message(conf, IPKG_NOTICE,
++ "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
++ }
++ ipkg_message(conf, IPKG_NOTICE, "\n");
++ for (i = 0; i < globbuf.gl_pathc; i++) {
++ err = ipkg_install_from_file(conf, globbuf.gl_pathv[i]);
++ if (err == 0) {
++ err = unlink(globbuf.gl_pathv[i]);
++ if (err) {
++ ipkg_message(conf, IPKG_ERROR,
++ "%s: ERROR: failed to unlink %s: %s\n",
++ __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
++ return err;
++ }
++ }
++ }
++ globfree(&globbuf);
++
++ return err;
++}
++
++static int ipkg_remove_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ int i,a,done;
++ pkg_t *pkg;
++ pkg_t *pkg_to_remove;
++ pkg_vec_t *available;
++ char *pkg_name = NULL;
++ global_conf = conf;
++ signal(SIGINT, sigint_handler);
++
++// ENH: Add the "no pkg removed" just in case.
++
++ done = 0;
++
++ available = pkg_vec_alloc();
++ pkg_info_preinstall_check(conf);
++ if ( argc > 0 ) {
++ pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
++ for (i=0; i < argc; i++) {
++ pkg_name = malloc(strlen(argv[i])+2);
++ strcpy(pkg_name,argv[i]);
++ for (a=0; a < available->len; a++) {
++ pkg = available->pkgs[a];
++ if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
++ continue;
++ }
++ if (conf->restrict_to_default_dest) {
++ pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
++ pkg->name,
++ conf->default_dest);
++ } else {
++ pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
++ }
++
++ if (pkg == NULL) {
++ ipkg_message(conf, IPKG_ERROR, "Package %s is not installed.\n", pkg->name);
++ continue;
++ }
++ if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
++ ipkg_message(conf, IPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
++ continue;
++ }
++ ipkg_remove_pkg(conf, pkg_to_remove,0);
++ done = 1;
++ }
++ free (pkg_name);
++ }
++ pkg_vec_free(available);
++ } else {
++ pkg_vec_t *installed_pkgs = pkg_vec_alloc();
++ int i;
++ int flagged_pkg_count = 0;
++ int removed;
++
++ pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
++
++ for (i = 0; i < installed_pkgs->len; i++) {
++ pkg_t *pkg = installed_pkgs->pkgs[i];
++ if (pkg->state_flag & SF_USER) {
++ flagged_pkg_count++;
++ } else {
++ if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
++ ipkg_message(conf, IPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
++ }
++ }
++ if (!flagged_pkg_count) {
++ ipkg_message(conf, IPKG_NOTICE, "No packages flagged as installed by user, \n"
++ "so refusing to uninstall unflagged non-leaf packages\n");
++ return 0;
++ }
++
++ /* find packages not flagged SF_USER (i.e., installed to
++ * satisfy a dependence) and not having any dependents, and
++ * remove them */
++ do {
++ removed = 0;
++ for (i = 0; i < installed_pkgs->len; i++) {
++ pkg_t *pkg = installed_pkgs->pkgs[i];
++ if (!(pkg->state_flag & SF_USER)
++ && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
++ removed++;
++ ipkg_message(conf, IPKG_NOTICE, "Removing non-user leaf package %s\n");
++ ipkg_remove_pkg(conf, pkg,0);
++ done = 1;
++ }
++ }
++ } while (removed);
++ pkg_vec_free(installed_pkgs);
++ }
++
++ if ( done == 0 )
++ ipkg_message(conf, IPKG_NOTICE, "No packages removed.\n");
++
++ write_status_files_if_changed(conf);
++ return 0;
++}
++
++static int ipkg_purge_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ int i;
++ pkg_t *pkg;
++
++ global_conf = conf;
++ signal(SIGINT, sigint_handler);
++
++ pkg_info_preinstall_check(conf);
++
++ for (i=0; i < argc; i++) {
++ if (conf->restrict_to_default_dest) {
++ pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
++ argv[i],
++ conf->default_dest);
++ } else {
++ pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
++ }
++
++ if (pkg == NULL) {
++ ipkg_message(conf, IPKG_ERROR,
++ "Package %s is not installed.\n", argv[i]);
++ continue;
++ }
++ ipkg_purge_pkg(conf, pkg);
++ }
++
++ write_status_files_if_changed(conf);
++ return 0;
++}
++
++static int ipkg_flag_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ int i;
++ pkg_t *pkg;
++ const char *flags = argv[0];
++
++ global_conf = conf;
++ signal(SIGINT, sigint_handler);
++
++ for (i=1; i < argc; i++) {
++ if (conf->restrict_to_default_dest) {
++ pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
++ argv[i],
++ conf->default_dest);
++ } else {
++ pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
++ }
++
++ if (pkg == NULL) {
++ ipkg_message(conf, IPKG_ERROR,
++ "Package %s is not installed.\n", argv[i]);
++ continue;
++ }
++ if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
++ ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
++ pkg->state_flag = pkg_state_flag_from_str(flags);
++ }
++/* pb_ asked this feature 03292004 */
++/* Actually I will use only this two, but this is an open for various status */
++ if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
++ pkg->state_status = pkg_state_status_from_str(flags);
++ }
++ ipkg_state_changed++;
++ ipkg_message(conf, IPKG_NOTICE,
++ "Setting flags for package %s to %s\n",
++ pkg->name, flags);
++ }
++
++ write_status_files_if_changed(conf);
++ return 0;
++}
++
++static int ipkg_files_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ pkg_t *pkg;
++ str_list_t *installed_files;
++ str_list_elt_t *iter;
++ char *pkg_version;
++ size_t buff_len = 8192;
++ size_t used_len;
++ char *buff ;
++
++ buff = (char *)malloc(buff_len);
++ if ( buff == NULL ) {
++ fprintf( stderr,"%s: Unable to allocate memory \n",__FUNCTION__);
++ return ENOMEM;
++ }
++
++ if (argc < 1) {
++ return EINVAL;
++ }
++
++ pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
++ argv[0]);
++ if (pkg == NULL) {
++ ipkg_message(conf, IPKG_ERROR,
++ "Package %s not installed.\n", argv[0]);
++ return 0;
++ }
++
++ installed_files = pkg_get_installed_files(pkg);
++ pkg_version = pkg_version_str_alloc(pkg);
++
++#ifndef IPKG_LIB
++ printf("Package %s (%s) is installed on %s and has the following files:\n",
++ pkg->name, pkg_version, pkg->dest->name);
++ for (iter = installed_files->head; iter; iter = iter->next) {
++ puts(iter->data);
++ }
++#else
++ if (buff) {
++ try_again:
++ used_len = snprintf(buff, buff_len, "Package %s (%s) is installed on %s and has the following files:\n",
++ pkg->name, pkg_version, pkg->dest->name) + 1;
++ if (used_len > buff_len) {
++ buff_len *= 2;
++ buff = realloc (buff, buff_len);
++ goto try_again;
++ }
++ for (iter = installed_files->head; iter; iter = iter->next) {
++ used_len += strlen (iter->data) + 1;
++ while (buff_len <= used_len) {
++ buff_len *= 2;
++ buff = realloc (buff, buff_len);
++ }
++ strncat(buff, iter->data, buff_len);
++ strncat(buff, "\n", buff_len);
++ }
++ if (ipkg_cb_list) ipkg_cb_list(pkg->name,
++ buff,
++ pkg_version_str_alloc(pkg),
++ pkg->state_status,
++ p_userdata);
++ free(buff);
++ }
++#endif
++
++ free(pkg_version);
++ pkg_free_installed_files(pkg);
++
++ return 0;
++}
++
++static int ipkg_depends_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++
++ if (argc > 0) {
++ pkg_vec_t *available_pkgs = pkg_vec_alloc();
++ const char *rel_str = "depends on";
++ int i;
++
++ pkg_info_preinstall_check(conf);
++
++ if (conf->query_all)
++ pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
++ else
++ pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
++ for (i = 0; i < argc; i++) {
++ const char *target = argv[i];
++ int j;
++
++ ipkg_message(conf, IPKG_ERROR, "target=%s\n", target);
++
++ for (j = 0; j < available_pkgs->len; j++) {
++ pkg_t *pkg = available_pkgs->pkgs[j];
++ if (fnmatch(target, pkg->name, 0) == 0) {
++ int k;
++ int count = pkg->depends_count + pkg->pre_depends_count;
++ ipkg_message(conf, IPKG_ERROR, "What %s (arch=%s) %s\n",
++ target, pkg->architecture, rel_str);
++ for (k = 0; k < count; k++) {
++ compound_depend_t *cdepend = &pkg->depends[k];
++ int l;
++ for (l = 0; l < cdepend->possibility_count; l++) {
++ depend_t *possibility = cdepend->possibilities[l];
++ ipkg_message(conf, IPKG_ERROR, " %s", possibility->pkg->name);
++ if (conf->verbosity > 0) {
++ // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
++ ipkg_message(conf, IPKG_NOTICE, " %s", possibility->version);
++ if (possibility->version) {
++ char *typestr = NULL;
++ switch (possibility->constraint) {
++ case NONE: typestr = "none"; break;
++ case EARLIER: typestr = "<"; break;
++ case EARLIER_EQUAL: typestr = "<="; break;
++ case EQUAL: typestr = "="; break;
++ case LATER_EQUAL: typestr = ">="; break;
++ case LATER: typestr = ">"; break;
++ }
++ ipkg_message(conf, IPKG_NOTICE, " (%s %s)", typestr, possibility->version);
++ }
++ // free(ver);
++ }
++ ipkg_message(conf, IPKG_ERROR, "\n");
++ }
++ }
++ }
++ }
++ }
++ pkg_vec_free(available_pkgs);
++ }
++ return 0;
++}
++
++enum what_field_type {
++ WHATDEPENDS,
++ WHATCONFLICTS,
++ WHATPROVIDES,
++ WHATREPLACES,
++ WHATRECOMMENDS,
++ WHATSUGGESTS
++};
++
++static int ipkg_what_depends_conflicts_cmd(ipkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
++{
++
++ if (argc > 0) {
++ pkg_vec_t *available_pkgs = pkg_vec_alloc();
++ const char *rel_str = NULL;
++ int i;
++ int changed;
++
++ switch (what_field_type) {
++ case WHATDEPENDS: rel_str = "depends on"; break;
++ case WHATCONFLICTS: rel_str = "conflicts with"; break;
++ case WHATSUGGESTS: rel_str = "suggests"; break;
++ case WHATRECOMMENDS: rel_str = "recommends"; break;
++ case WHATPROVIDES: rel_str = "provides"; break;
++ case WHATREPLACES: rel_str = "replaces"; break;
++ }
++
++ if (conf->query_all)
++ pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
++ else
++ pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
++
++ /* mark the root set */
++ pkg_vec_clear_marks(available_pkgs);
++ ipkg_message(conf, IPKG_NOTICE, "Root set:\n");
++ for (i = 0; i < argc; i++) {
++ const char *dependee_pattern = argv[i];
++ pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
++ }
++ for (i = 0; i < available_pkgs->len; i++) {
++ pkg_t *pkg = available_pkgs->pkgs[i];
++ if (pkg->state_flag & SF_MARKED) {
++ /* mark the parent (abstract) package */
++ pkg_mark_provides(pkg);
++ ipkg_message(conf, IPKG_NOTICE, " %s\n", pkg->name);
++ }
++ }
++
++ ipkg_message(conf, IPKG_NOTICE, "What %s root set\n", rel_str);
++ do {
++ int j;
++ changed = 0;
++
++ for (j = 0; j < available_pkgs->len; j++) {
++ pkg_t *pkg = available_pkgs->pkgs[j];
++ int k;
++ int count = ((what_field_type == WHATCONFLICTS)
++ ? pkg->conflicts_count
++ : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
++ /* skip this package if it is already marked */
++ if (pkg->parent->state_flag & SF_MARKED) {
++ continue;
++ }
++ for (k = 0; k < count; k++) {
++ compound_depend_t *cdepend =
++ (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
++ int l;
++ for (l = 0; l < cdepend->possibility_count; l++) {
++ depend_t *possibility = cdepend->possibilities[l];
++ if (possibility->pkg->state_flag & SF_MARKED) {
++ /* mark the depending package so we won't visit it again */
++ pkg->state_flag |= SF_MARKED;
++ pkg_mark_provides(pkg);
++ changed++;
++
++ ipkg_message(conf, IPKG_NOTICE, " %s", pkg->name);
++ if (conf->verbosity > 0) {
++ char *ver = pkg_version_str_alloc(pkg);
++ ipkg_message(conf, IPKG_NOTICE, " %s", ver);
++ ipkg_message(conf, IPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
++ if (possibility->version) {
++ char *typestr = NULL;
++ switch (possibility->constraint) {
++ case NONE: typestr = "none"; break;
++ case EARLIER: typestr = "<"; break;
++ case EARLIER_EQUAL: typestr = "<="; break;
++ case EQUAL: typestr = "="; break;
++ case LATER_EQUAL: typestr = ">="; break;
++ case LATER: typestr = ">"; break;
++ }
++ ipkg_message(conf, IPKG_NOTICE, " (%s %s)", typestr, possibility->version);
++ }
++ free(ver);
++ if (!pkg_dependence_satisfiable(conf, possibility))
++ ipkg_message(conf, IPKG_NOTICE, " unsatisfiable");
++ }
++ ipkg_message(conf, IPKG_NOTICE, "\n");
++ goto next_package;
++ }
++ }
++ }
++ next_package:
++ ;
++ }
++ } while (changed && recursive);
++ pkg_vec_free(available_pkgs);
++ }
++
++ return 0;
++}
++
++int pkg_mark_provides(pkg_t *pkg)
++{
++ int provides_count = pkg->provides_count;
++ abstract_pkg_t **provides = pkg->provides;
++ int i;
++ pkg->parent->state_flag |= SF_MARKED;
++ for (i = 0; i < provides_count; i++) {
++ provides[i]->state_flag |= SF_MARKED;
++ }
++ return 0;
++}
++
++static int ipkg_whatdepends_recursively_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ return ipkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
++}
++static int ipkg_whatdepends_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ return ipkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
++}
++
++static int ipkg_whatsuggests_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ return ipkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
++}
++
++static int ipkg_whatrecommends_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ return ipkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
++}
++
++static int ipkg_whatconflicts_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ return ipkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
++}
++
++static int ipkg_what_provides_replaces_cmd(ipkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
++{
++
++ if (argc > 0) {
++ pkg_vec_t *available_pkgs = pkg_vec_alloc();
++ const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
++ int i;
++
++ pkg_info_preinstall_check(conf);
++
++ if (conf->query_all)
++ pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
++ else
++ pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
++ for (i = 0; i < argc; i++) {
++ const char *target = argv[i];
++ int j;
++
++ ipkg_message(conf, IPKG_ERROR, "What %s %s\n",
++ rel_str, target);
++ for (j = 0; j < available_pkgs->len; j++) {
++ pkg_t *pkg = available_pkgs->pkgs[j];
++ int k;
++ int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
++ for (k = 0; k < count; k++) {
++ abstract_pkg_t *apkg =
++ ((what_field_type == WHATPROVIDES)
++ ? pkg->provides[k]
++ : pkg->replaces[k]);
++ if (fnmatch(target, apkg->name, 0) == 0) {
++ ipkg_message(conf, IPKG_ERROR, " %s", pkg->name);
++ if (strcmp(target, apkg->name) != 0)
++ ipkg_message(conf, IPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
++ ipkg_message(conf, IPKG_ERROR, "\n");
++ }
++ }
++ }
++ }
++ pkg_vec_free(available_pkgs);
++ }
++ return 0;
++}
++
++static int ipkg_whatprovides_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ return ipkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
++}
++
++static int ipkg_whatreplaces_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ return ipkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
++}
++
++static int ipkg_search_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ int i;
++
++ pkg_vec_t *installed;
++ pkg_t *pkg;
++ str_list_t *installed_files;
++ str_list_elt_t *iter;
++ char *installed_file;
++
++ if (argc < 1) {
++ return EINVAL;
++ }
++
++ installed = pkg_vec_alloc();
++ pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
++
++ for (i=0; i < installed->len; i++) {
++ pkg = installed->pkgs[i];
++
++ installed_files = pkg_get_installed_files(pkg);
++
++ for (iter = installed_files->head; iter; iter = iter->next) {
++ installed_file = iter->data;
++ if (fnmatch(argv[0], installed_file, 0)==0) {
++#ifndef IPKG_LIB
++ printf("%s: %s\n", pkg->name, installed_file);
++#else
++ if (ipkg_cb_list) ipkg_cb_list(pkg->name,
++ installed_file,
++ pkg_version_str_alloc(pkg),
++ pkg->state_status, p_userdata);
++#endif
++ }
++ }
++
++ pkg_free_installed_files(pkg);
++ }
++
++ /* XXX: CLEANUP: It's not obvious from the name of
++ pkg_hash_fetch_all_installed that we need to call
++ pkg_vec_free to avoid a memory leak. */
++ pkg_vec_free(installed);
++
++ return 0;
++}
++
++static int ipkg_compare_versions_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ if (argc == 3) {
++ /* this is a bit gross */
++ struct pkg p1, p2;
++ parseVersion(&p1, argv[0]);
++ parseVersion(&p2, argv[2]);
++ return pkg_version_satisfied(&p1, &p2, argv[1]);
++ } else {
++ ipkg_message(conf, IPKG_ERROR,
++ "ipkg compare_versions <v1> <op> <v2>\n"
++ "<op> is one of <= >= << >> =\n");
++ return -1;
++ }
++}
++
++#ifndef HOST_CPU_STR
++#define HOST_CPU_STR__(X) #X
++#define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
++#define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
++#endif
++
++static int ipkg_print_architecture_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++ nv_pair_list_elt_t *l;
++
++ l = conf->arch_list.head;
++ while (l) {
++ nv_pair_t *nv = l->data;
++ printf("arch %s %s\n", nv->name, nv->value);
++ l = l->next;
++ }
++ return 0;
++}
++
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_cmd.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_cmd.h
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_cmd.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_cmd.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,46 @@
++/* ipkg_cmd.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef IPKG_CMD_H
++#define IPKG_CMD_H
++
++typedef int (*ipkg_cmd_fun_t)(ipkg_conf_t *conf, int argc, const char **argv);
++
++struct ipkg_cmd
++{
++ char *name;
++ int requires_args;
++ ipkg_cmd_fun_t fun;
++};
++typedef struct ipkg_cmd ipkg_cmd_t;
++
++ipkg_cmd_t *ipkg_cmd_find(const char *name);
++#ifdef IPKG_LIB
++int ipkg_cmd_exec(ipkg_cmd_t *cmd, ipkg_conf_t *conf, int argc,
++ const char **argv, void *userdata);
++#else
++int ipkg_cmd_exec(ipkg_cmd_t *cmd, ipkg_conf_t *conf, int argc, const char **argv);
++#endif
++int ipkg_multiple_files_scan (ipkg_conf_t *conf, int argc, char *argv[]);
++/* install any packges with state_want == SW_INSTALL */
++int ipkg_install_wanted_packages(ipkg_conf_t *conf);
++/* ensure that all dependences are satisfied */
++int ipkg_configure_packages(ipkg_conf_t *conf, char *pkg_name);
++
++int pkg_mark_provides(pkg_t *pkg);
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_conf.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_conf.c
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_conf.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_conf.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,711 @@
++/* ipkg_conf.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include <glob.h>
++
++#include "ipkg.h"
++#include "ipkg_conf.h"
++
++#include "xregex.h"
++#include "sprintf_alloc.h"
++#include "ipkg_conf.h"
++#include "ipkg_message.h"
++#include "file_util.h"
++#include "str_util.h"
++#include "xsystem.h"
++
++
++ipkg_conf_t *global_conf;
++
++static int ipkg_conf_parse_file(ipkg_conf_t *conf, const char *filename,
++ pkg_src_list_t *pkg_src_list,
++ nv_pair_list_t *tmp_dest_nv_pair_list,
++ char **tmp_lists_dir);
++static int ipkg_init_options_array(const ipkg_conf_t *conf, ipkg_option_t **options);
++static int ipkg_conf_set_option(const ipkg_option_t *options,
++ const char *name, const char *value);
++static int ipkg_conf_set_default_dest(ipkg_conf_t *conf,
++ const char *default_dest_name);
++static int set_and_load_pkg_src_list(ipkg_conf_t *conf,
++ pkg_src_list_t *nv_pair_list);
++static int set_and_load_pkg_dest_list(ipkg_conf_t *conf,
++ nv_pair_list_t *nv_pair_list, char * lists_dir);
++
++int ipkg_init_options_array(const ipkg_conf_t *conf, ipkg_option_t **options)
++{
++ ipkg_option_t tmp[] = {
++ { "force_defaults", IPKG_OPT_TYPE_BOOL, &conf->force_defaults },
++ { "force_depends", IPKG_OPT_TYPE_BOOL, &conf->force_depends },
++ { "force_overwrite", IPKG_OPT_TYPE_BOOL, &conf->force_overwrite },
++ { "force_downgrade", IPKG_OPT_TYPE_BOOL, &conf->force_downgrade },
++ { "force_reinstall", IPKG_OPT_TYPE_BOOL, &conf->force_reinstall },
++ { "force_space", IPKG_OPT_TYPE_BOOL, &conf->force_space },
++ { "ftp_proxy", IPKG_OPT_TYPE_STRING, &conf->ftp_proxy },
++ { "http_proxy", IPKG_OPT_TYPE_STRING, &conf->http_proxy },
++ { "multiple_providers", IPKG_OPT_TYPE_BOOL, &conf->multiple_providers },
++ { "no_proxy", IPKG_OPT_TYPE_STRING, &conf->no_proxy },
++ { "test", IPKG_OPT_TYPE_INT, &conf->noaction },
++ { "noaction", IPKG_OPT_TYPE_INT, &conf->noaction },
++ { "nodeps", IPKG_OPT_TYPE_BOOL, &conf->nodeps },
++ { "offline_root", IPKG_OPT_TYPE_STRING, &conf->offline_root },
++ { "offline_root_post_script_cmd", IPKG_OPT_TYPE_STRING, &conf->offline_root_post_script_cmd },
++ { "offline_root_pre_script_cmd", IPKG_OPT_TYPE_STRING, &conf->offline_root_pre_script_cmd },
++ { "proxy_passwd", IPKG_OPT_TYPE_STRING, &conf->proxy_passwd },
++ { "proxy_user", IPKG_OPT_TYPE_STRING, &conf->proxy_user },
++ { "query-all", IPKG_OPT_TYPE_BOOL, &conf->query_all },
++ { "verbose-wget", IPKG_OPT_TYPE_BOOL, &conf->verbose_wget },
++ { "verbosity", IPKG_OPT_TYPE_BOOL, &conf->verbosity },
++ { NULL }
++ };
++
++ *options = (ipkg_option_t *)malloc(sizeof(tmp));
++ if ( options == NULL ){
++ fprintf(stderr,"%s: Unable to allocate memory\n",__FUNCTION__);
++ return -1;
++ }
++
++ memcpy(*options, tmp, sizeof(tmp));
++ return 0;
++};
++
++static void ipkg_conf_override_string(char **conf_str, char *arg_str)
++{
++ if (arg_str) {
++ if (*conf_str) {
++ free(*conf_str);
++ }
++ *conf_str = strdup(arg_str);
++ }
++}
++
++static void ipkg_conf_free_string(char **conf_str)
++{
++ if (*conf_str) {
++ free(*conf_str);
++ *conf_str = NULL;
++ }
++}
++
++int ipkg_conf_init(ipkg_conf_t *conf, const args_t *args)
++{
++ int err;
++ char *tmp_dir_base;
++ nv_pair_list_t tmp_dest_nv_pair_list;
++ char * lists_dir =NULL;
++ glob_t globbuf;
++ char *etc_ipkg_conf_pattern = "/etc/ipkg/*.conf";
++ char *pending_dir =NULL;
++
++ memset(conf, 0, sizeof(ipkg_conf_t));
++
++ pkg_src_list_init(&conf->pkg_src_list);
++
++ nv_pair_list_init(&tmp_dest_nv_pair_list);
++ pkg_dest_list_init(&conf->pkg_dest_list);
++
++ nv_pair_list_init(&conf->arch_list);
++
++ conf->restrict_to_default_dest = 0;
++ conf->default_dest = NULL;
++
++
++ if (args->tmp_dir)
++ tmp_dir_base = args->tmp_dir;
++ else
++ tmp_dir_base = getenv("TMPDIR");
++ sprintf_alloc(&conf->tmp_dir, "%s/%s",
++ tmp_dir_base ? tmp_dir_base : IPKG_CONF_DEFAULT_TMP_DIR_BASE,
++ IPKG_CONF_TMP_DIR_SUFFIX);
++ conf->tmp_dir = mkdtemp(conf->tmp_dir);
++ if (conf->tmp_dir == NULL) {
++ fprintf(stderr, "%s: Failed to create temporary directory `%s': %s\n",
++ __FUNCTION__, conf->tmp_dir, strerror(errno));
++ return errno;
++ }
++
++ conf->force_depends = 0;
++ conf->force_defaults = 0;
++ conf->force_overwrite = 0;
++ conf->force_downgrade = 0;
++ conf->force_reinstall = 0;
++ conf->force_space = 0;
++ conf->force_removal_of_essential_packages = 0;
++ conf->force_removal_of_dependent_packages = 0;
++ conf->nodeps = 0;
++ conf->verbose_wget = 0;
++ conf->offline_root = NULL;
++ conf->offline_root_pre_script_cmd = NULL;
++ conf->offline_root_post_script_cmd = NULL;
++ conf->multiple_providers = 0;
++ conf->verbosity = 1;
++ conf->noaction = 0;
++
++ conf->http_proxy = NULL;
++ conf->ftp_proxy = NULL;
++ conf->no_proxy = NULL;
++ conf->proxy_user = NULL;
++ conf->proxy_passwd = NULL;
++
++ pkg_hash_init("pkg-hash", &conf->pkg_hash, IPKG_CONF_DEFAULT_HASH_LEN);
++ hash_table_init("file-hash", &conf->file_hash, IPKG_CONF_DEFAULT_HASH_LEN);
++ hash_table_init("obs-file-hash", &conf->obs_file_hash, IPKG_CONF_DEFAULT_HASH_LEN);
++ lists_dir=(char *)malloc(1);
++ lists_dir[0]='\0';
++ if (args->conf_file) {
++ struct stat stat_buf;
++ err = stat(args->conf_file, &stat_buf);
++ if (err == 0)
++ if (ipkg_conf_parse_file(conf, args->conf_file,
++ &conf->pkg_src_list, &tmp_dest_nv_pair_list,&lists_dir)<0) {
++ /* Memory leakage from ipkg_conf_parse-file */
++ return -1;
++ }
++
++ }
++
++ /* if (!lists_dir ){*/
++ if (strlen(lists_dir)<=1 ){
++ lists_dir = realloc(lists_dir,strlen(IPKG_CONF_LISTS_DIR)+2);
++ sprintf (lists_dir,"%s",IPKG_CONF_LISTS_DIR);
++ }
++
++ if (args->offline_root) {
++ char *tmp = malloc(strlen(lists_dir) + strlen(args->offline_root) + 1);
++ sprintf_alloc(&tmp, "%s/%s",args->offline_root,lists_dir);
++ free(lists_dir);
++ lists_dir = tmp;
++ }
++
++ pending_dir = malloc(strlen(lists_dir)+strlen("/pending")+5);
++ snprintf(pending_dir,strlen(lists_dir)+strlen("/pending") ,"%s%s",lists_dir,"/pending");
++
++ conf->lists_dir = strdup(lists_dir);
++ conf->pending_dir = strdup(pending_dir);
++
++ if (args->offline_root)
++ sprintf_alloc(&etc_ipkg_conf_pattern, "%s/etc/ipkg/*.conf", args->offline_root);
++ memset(&globbuf, 0, sizeof(globbuf));
++ err = glob(etc_ipkg_conf_pattern, 0, NULL, &globbuf);
++ if (!err) {
++ int i;
++ for (i = 0; i < globbuf.gl_pathc; i++) {
++ if (globbuf.gl_pathv[i])
++ if ( ipkg_conf_parse_file(conf, globbuf.gl_pathv[i],
++ &conf->pkg_src_list, &tmp_dest_nv_pair_list,&lists_dir)<0) {
++ /* Memory leakage from ipkg_conf_parse-file */
++ return -1;
++ }
++ }
++ }
++ globfree(&globbuf);
++
++ /* if no architectures were defined, then default all, noarch, and host architecture */
++ if (nv_pair_list_empty(&conf->arch_list)) {
++ nv_pair_list_append(&conf->arch_list, "all", "1");
++ nv_pair_list_append(&conf->arch_list, "noarch", "1");
++ nv_pair_list_append(&conf->arch_list, HOST_CPU_STR, "10");
++ }
++
++ /* Even if there is no conf file, we'll need at least one dest. */
++ if (tmp_dest_nv_pair_list.head == NULL) {
++ nv_pair_list_append(&tmp_dest_nv_pair_list,
++ IPKG_CONF_DEFAULT_DEST_NAME,
++ IPKG_CONF_DEFAULT_DEST_ROOT_DIR);
++ }
++
++ /* After parsing the file, set options from command-line, (so that
++ command-line arguments take precedence) */
++ /* XXX: CLEANUP: The interaction between args.c and ipkg_conf.c
++ really needs to be cleaned up. There is so much duplication
++ right now it is ridiculous. Maybe ipkg_conf_t should just save
++ a pointer to args_t (which could then not be freed), rather
++ than duplicating every field here? */
++ if (args->force_depends) {
++ conf->force_depends = 1;
++ }
++ if (args->force_defaults) {
++ conf->force_defaults = 1;
++ }
++ if (args->force_overwrite) {
++ conf->force_overwrite = 1;
++ }
++ if (args->force_downgrade) {
++ conf->force_downgrade = 1;
++ }
++ if (args->force_reinstall) {
++ conf->force_reinstall = 1;
++ }
++ if (args->force_removal_of_dependent_packages) {
++ conf->force_removal_of_dependent_packages = 1;
++ }
++ if (args->force_removal_of_essential_packages) {
++ conf->force_removal_of_essential_packages = 1;
++ }
++ if (args->nodeps) {
++ conf->nodeps = 1;
++ }
++ if (args->noaction) {
++ conf->noaction = 1;
++ }
++ if (args->query_all) {
++ conf->query_all = 1;
++ }
++ if (args->verbose_wget) {
++ conf->verbose_wget = 1;
++ }
++ if (args->multiple_providers) {
++ conf->multiple_providers = 1;
++ }
++ if (args->verbosity != conf->verbosity) {
++ conf->verbosity = args->verbosity;
++ }
++
++ ipkg_conf_override_string(&conf->offline_root,
++ args->offline_root);
++ ipkg_conf_override_string(&conf->offline_root_pre_script_cmd,
++ args->offline_root_pre_script_cmd);
++ ipkg_conf_override_string(&conf->offline_root_post_script_cmd,
++ args->offline_root_post_script_cmd);
++
++/* Pigi: added a flag to disable the checking of structures if the command does not need to
++ read anything from there.
++*/
++ if ( !(args->nocheckfordirorfile)){
++ /* need to run load the source list before dest list -Jamey */
++ if ( !(args->noreadfeedsfile))
++ set_and_load_pkg_src_list(conf, &conf->pkg_src_list);
++
++ /* Now that we have resolved conf->offline_root, we can commit to
++ the directory names for the dests and load in all the package
++ lists. */
++ set_and_load_pkg_dest_list(conf, &tmp_dest_nv_pair_list,lists_dir);
++
++ if (args->dest) {
++ err = ipkg_conf_set_default_dest(conf, args->dest);
++ if (err) {
++ return err;
++ }
++ }
++ }
++ nv_pair_list_deinit(&tmp_dest_nv_pair_list);
++ free(lists_dir);
++ free(pending_dir);
++
++ return 0;
++}
++
++void ipkg_conf_deinit(ipkg_conf_t *conf)
++{
++#ifdef IPKG_DEBUG_NO_TMP_CLEANUP
++#error
++ fprintf(stderr, "%s: Not cleaning up %s since ipkg compiled "
++ "with IPKG_DEBUG_NO_TMP_CLEANUP\n",
++ __FUNCTION__, conf->tmp_dir);
++#else
++ int err;
++
++ err = rmdir(conf->tmp_dir);
++ if (err) {
++ if (errno == ENOTEMPTY) {
++ char *cmd;
++ sprintf_alloc(&cmd, "rm -fr %s\n", conf->tmp_dir);
++ err = xsystem(cmd);
++ free(cmd);
++ }
++ if (err)
++ fprintf(stderr, "WARNING: Unable to remove temporary directory: %s: %s\n", conf->tmp_dir, strerror(errno));
++ }
++#endif /* IPKG_DEBUG_NO_TMP_CLEANUP */
++
++ free(conf->tmp_dir); /*XXX*/
++
++ pkg_src_list_deinit(&conf->pkg_src_list);
++ pkg_dest_list_deinit(&conf->pkg_dest_list);
++ nv_pair_list_deinit(&conf->arch_list);
++ if (&conf->pkg_hash)
++ pkg_hash_deinit(&conf->pkg_hash);
++ if (&conf->file_hash)
++ hash_table_deinit(&conf->file_hash);
++ if (&conf->obs_file_hash)
++ hash_table_deinit(&conf->obs_file_hash);
++
++ ipkg_conf_free_string(&conf->offline_root);
++ ipkg_conf_free_string(&conf->offline_root_pre_script_cmd);
++ ipkg_conf_free_string(&conf->offline_root_post_script_cmd);
++
++ if (conf->verbosity > 1) {
++ int i;
++ hash_table_t *hashes[] = {
++ &conf->pkg_hash,
++ &conf->file_hash,
++ &conf->obs_file_hash };
++ for (i = 0; i < 3; i++) {
++ hash_table_t *hash = hashes[i];
++ int c = 0;
++ int n_conflicts = 0;
++ int j;
++ for (j = 0; j < hash->n_entries; j++) {
++ int len = 0;
++ hash_entry_t *e = &hash->entries[j];
++ if (e->next)
++ n_conflicts++;
++ while (e && e->key) {
++ len++;
++ e = e->next;
++ }
++ if (len > c)
++ c = len;
++ }
++ ipkg_message(conf, IPKG_DEBUG, "hash_table[%s] n_buckets=%d n_elements=%d max_conflicts=%d n_conflicts=%d\n",
++ hash->name, hash->n_entries, hash->n_elements, c, n_conflicts);
++ hash_table_deinit(hash);
++ }
++ }
++}
++
++static int ipkg_conf_set_default_dest(ipkg_conf_t *conf,
++ const char *default_dest_name)
++{
++ pkg_dest_list_elt_t *iter;
++ pkg_dest_t *dest;
++
++ for (iter = conf->pkg_dest_list.head; iter; iter = iter->next) {
++ dest = iter->data;
++ if (strcmp(dest->name, default_dest_name) == 0) {
++ conf->default_dest = dest;
++ conf->restrict_to_default_dest = 1;
++ return 0;
++ }
++ }
++
++ fprintf(stderr, "ERROR: Unknown dest name: `%s'\n", default_dest_name);
++
++ return 1;
++}
++
++static int set_and_load_pkg_src_list(ipkg_conf_t *conf, pkg_src_list_t *pkg_src_list)
++{
++ pkg_src_list_elt_t *iter;
++ pkg_src_t *src;
++ char *list_file;
++
++ for (iter = pkg_src_list->head; iter; iter = iter->next) {
++ src = iter->data;
++ if (src == NULL) {
++ continue;
++ }
++
++ sprintf_alloc(&list_file, "%s/%s",
++ conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir,
++ src->name);
++
++ if (file_exists(list_file)) {
++ pkg_hash_add_from_file(conf, list_file, src, NULL, 0);
++ }
++ free(list_file);
++ }
++
++ return 0;
++}
++
++static int set_and_load_pkg_dest_list(ipkg_conf_t *conf, nv_pair_list_t *nv_pair_list, char *lists_dir )
++{
++ nv_pair_list_elt_t *iter;
++ nv_pair_t *nv_pair;
++ pkg_dest_t *dest;
++ char *root_dir;
++
++ for (iter = nv_pair_list->head; iter; iter = iter->next) {
++ nv_pair = iter->data;
++
++ if (conf->offline_root) {
++ sprintf_alloc(&root_dir, "%s%s", conf->offline_root, nv_pair->value);
++ } else {
++ root_dir = strdup(nv_pair->value);
++ }
++ dest = pkg_dest_list_append(&conf->pkg_dest_list, nv_pair->name, root_dir, lists_dir);
++ free(root_dir);
++ if (dest == NULL) {
++ continue;
++ }
++ if (conf->default_dest == NULL) {
++ conf->default_dest = dest;
++ }
++ if (file_exists(dest->status_file_name)) {
++ pkg_hash_add_from_file(conf, dest->status_file_name,
++ NULL, dest, 1);
++ }
++ }
++
++ return 0;
++}
++
++static int ipkg_conf_parse_file(ipkg_conf_t *conf, const char *filename,
++ pkg_src_list_t *pkg_src_list,
++ nv_pair_list_t *tmp_dest_nv_pair_list,
++ char **lists_dir)
++{
++ ipkg_option_t * options;
++ FILE *file = fopen(filename, "r");
++ regex_t valid_line_re, comment_re;
++#define regmatch_size 12
++ regmatch_t regmatch[regmatch_size];
++
++ if (ipkg_init_options_array(conf, &options)<0)
++ return ENOMEM;
++
++ if (file == NULL) {
++ fprintf(stderr, "%s: failed to open %s: %s\n",
++ __FUNCTION__, filename, strerror(errno));
++ free(options);
++ return errno;
++ }
++ ipkg_message(conf, IPKG_NOTICE, "loading conf file %s\n", filename);
++
++ xregcomp(&comment_re,
++ "^[[:space:]]*(#.*|[[:space:]]*)$",
++ REG_EXTENDED);
++ xregcomp(&valid_line_re, "^[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))([[:space:]]+([^[:space:]]+))?[[:space:]]*$", REG_EXTENDED);
++
++ while(1) {
++ int line_num = 0;
++ char *line;
++ char *type, *name, *value, *extra;
++
++ line = file_read_line_alloc(file);
++ line_num++;
++ if (line == NULL) {
++ break;
++ }
++
++ str_chomp(line);
++
++ if (regexec(&comment_re, line, 0, 0, 0) == 0) {
++ goto NEXT_LINE;
++ }
++
++ if (regexec(&valid_line_re, line, regmatch_size, regmatch, 0) == REG_NOMATCH) {
++ str_chomp(line);
++ fprintf(stderr, "%s:%d: Ignoring invalid line: `%s'\n",
++ filename, line_num, line);
++ goto NEXT_LINE;
++ }
++
++ /* This has to be so ugly to deal with optional quotation marks */
++ if (regmatch[2].rm_so > 0) {
++ type = strndup(line + regmatch[2].rm_so,
++ regmatch[2].rm_eo - regmatch[2].rm_so);
++ } else {
++ type = strndup(line + regmatch[3].rm_so,
++ regmatch[3].rm_eo - regmatch[3].rm_so);
++ }
++ if (regmatch[5].rm_so > 0) {
++ name = strndup(line + regmatch[5].rm_so,
++ regmatch[5].rm_eo - regmatch[5].rm_so);
++ } else {
++ name = strndup(line + regmatch[6].rm_so,
++ regmatch[6].rm_eo - regmatch[6].rm_so);
++ }
++ if (regmatch[8].rm_so > 0) {
++ value = strndup(line + regmatch[8].rm_so,
++ regmatch[8].rm_eo - regmatch[8].rm_so);
++ } else {
++ value = strndup(line + regmatch[9].rm_so,
++ regmatch[9].rm_eo - regmatch[9].rm_so);
++ }
++ extra = NULL;
++ if (regmatch[11].rm_so > 0) {
++ extra = strndup (line + regmatch[11].rm_so,
++ regmatch[11].rm_eo - regmatch[11].rm_so);
++ }
++
++ /* We use the tmp_dest_nv_pair_list below instead of
++ conf->pkg_dest_list because we might encounter an
++ offline_root option later and that would invalidate the
++ directories we would have computed in
++ pkg_dest_list_init. (We do a similar thing with
++ tmp_src_nv_pair_list for sake of symmetry.) */
++ if (strcmp(type, "option") == 0) {
++ ipkg_conf_set_option(options, name, value);
++ } else if (strcmp(type, "src") == 0) {
++ if (!nv_pair_list_find(pkg_src_list, name)) {
++ pkg_src_list_append (pkg_src_list, name, value, extra, 0);
++ } else {
++ ipkg_message(conf, IPKG_ERROR, "ERROR: duplicate src declaration. Skipping:\n\t src %s %s\n",
++ name, value);
++ }
++ } else if (strcmp(type, "src/gz") == 0) {
++ if (!nv_pair_list_find(pkg_src_list, name)) {
++ pkg_src_list_append (pkg_src_list, name, value, extra, 1);
++ } else {
++ ipkg_message(conf, IPKG_ERROR, "ERROR: duplicate src declaration. Skipping:\n\t src %s %s\n",
++ name, value);
++ }
++ } else if (strcmp(type, "dest") == 0) {
++ nv_pair_list_append(tmp_dest_nv_pair_list, name, value);
++ } else if (strcmp(type, "lists_dir") == 0) {
++ *lists_dir = realloc(*lists_dir,strlen(value)+1);
++ if (*lists_dir == NULL) {
++ ipkg_message(conf, IPKG_ERROR, "ERROR: Not enough memory\n");
++ free(options);
++ return EINVAL;
++ }
++ sprintf (*lists_dir,"%s",value);
++ } else if (strcmp(type, "arch") == 0) {
++ ipkg_message(conf, IPKG_INFO, "supported arch %s priority (%s)\n", name, value);
++ if (!value) {
++ ipkg_message(conf, IPKG_NOTICE, "defaulting architecture %s priority to 10\n", name);
++ value = strdup("10");
++ }
++ nv_pair_list_append(&conf->arch_list, strdup(name), strdup(value));
++ } else {
++ fprintf(stderr, "WARNING: Ignoring unknown configuration "
++ "parameter: %s %s %s\n", type, name, value);
++ free(options);
++ return EINVAL;
++ }
++
++ free(type);
++ free(name);
++ free(value);
++ if (extra)
++ free (extra);
++
++ NEXT_LINE:
++ free(line);
++ }
++
++ free(options);
++ regfree(&comment_re);
++ regfree(&valid_line_re);
++ fclose(file);
++
++ return 0;
++}
++
++static int ipkg_conf_set_option(const ipkg_option_t *options,
++ const char *name, const char *value)
++{
++ int i = 0;
++ while (options[i].name) {
++ if (strcmp(options[i].name, name) == 0) {
++ switch (options[i].type) {
++ case IPKG_OPT_TYPE_BOOL:
++ *((int *)options[i].value) = 1;
++ return 0;
++ case IPKG_OPT_TYPE_INT:
++ if (value) {
++ *((int *)options[i].value) = atoi(value);
++ return 0;
++ } else {
++ printf("%s: Option %s need an argument\n",
++ __FUNCTION__, name);
++ return EINVAL;
++ }
++ case IPKG_OPT_TYPE_STRING:
++ if (value) {
++ *((char **)options[i].value) = strdup(value);
++ return 0;
++ } else {
++ printf("%s: Option %s need an argument\n",
++ __FUNCTION__, name);
++ return EINVAL;
++ }
++ }
++ }
++ i++;
++ }
++
++ fprintf(stderr, "%s: Unrecognized option: %s=%s\n",
++ __FUNCTION__, name, value);
++ return EINVAL;
++}
++
++int ipkg_conf_write_status_files(ipkg_conf_t *conf)
++{
++ pkg_dest_list_elt_t *iter;
++ pkg_dest_t *dest;
++ pkg_vec_t *all;
++ pkg_t *pkg;
++ register int i;
++ int err;
++
++ if (conf->noaction)
++ return 0;
++ for (iter = conf->pkg_dest_list.head; iter; iter = iter->next) {
++ dest = iter->data;
++ dest->status_file = fopen(dest->status_file_tmp_name, "w");
++ if (dest->status_file == NULL) {
++ fprintf(stderr, "%s: Can't open status file: %s for writing: %s\n",
++ __FUNCTION__, dest->status_file_name, strerror(errno));
++ }
++ }
++
++ all = pkg_vec_alloc();
++ pkg_hash_fetch_available(&conf->pkg_hash, all);
++
++ for(i = 0; i < all->len; i++) {
++ pkg = all->pkgs[i];
++ /* We don't need most uninstalled packages in the status file */
++ if (pkg->state_status == SS_NOT_INSTALLED
++ && (pkg->state_want == SW_UNKNOWN
++ || pkg->state_want == SW_DEINSTALL
++ || pkg->state_want == SW_PURGE)) {
++ continue;
++ }
++ if (!pkg) {
++ fprintf(stderr, "Null package\n");
++ }
++ if (pkg->dest == NULL) {
++ fprintf(stderr, "%s: ERROR: Can't write status for "
++ "package %s since it has a NULL dest\n",
++ __FUNCTION__, pkg->name);
++ continue;
++ }
++ if (pkg->dest->status_file) {
++ pkg_print_status(pkg, pkg->dest->status_file);
++ }
++ }
++
++ pkg_vec_free(all);
++
++ for (iter = conf->pkg_dest_list.head; iter; iter = iter->next) {
++ dest = iter->data;
++ if (dest->status_file) {
++ err = ferror(dest->status_file);
++ fclose(dest->status_file);
++ dest->status_file = NULL;
++ if (!err) {
++ file_move(dest->status_file_tmp_name, dest->status_file_name);
++ } else {
++ fprintf(stderr, "%s: ERROR: An error has occurred writing %s, "
++ "retaining old %s\n", __FUNCTION__,
++ dest->status_file_tmp_name, dest->status_file_name);
++ }
++ }
++ }
++
++ return 0;
++}
++
++
++char *root_filename_alloc(ipkg_conf_t *conf, char *filename)
++{
++ char *root_filename;
++ sprintf_alloc(&root_filename, "%s%s", (conf->offline_root ? conf->offline_root : ""), filename);
++ return root_filename;
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_conf.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_conf.h
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_conf.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_conf.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,107 @@
++/* ipkg_conf.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef IPKG_CONF_H
++#define IPKG_CONF_H
++
++typedef struct ipkg_conf ipkg_conf_t;
++
++#include "hash_table.h"
++#include "ipkg.h"
++#include "args.h"
++#include "pkg.h"
++#include "pkg_hash.h"
++#include "pkg_src_list.h"
++#include "pkg_dest_list.h"
++#include "nv_pair_list.h"
++
++#define IPKG_CONF_DEFAULT_TMP_DIR_BASE "/tmp"
++#define IPKG_CONF_TMP_DIR_SUFFIX "ipkg-XXXXXX"
++#define IPKG_CONF_LISTS_DIR IPKG_STATE_DIR_PREFIX "/lists"
++#define IPKG_CONF_PENDING_DIR IPKG_STATE_DIR_PREFIX "/pending"
++
++/* In case the config file defines no dest */
++#define IPKG_CONF_DEFAULT_DEST_NAME "root"
++#define IPKG_CONF_DEFAULT_DEST_ROOT_DIR "/"
++
++#define IPKG_CONF_DEFAULT_HASH_LEN 1024
++
++struct ipkg_conf
++{
++ pkg_src_list_t pkg_src_list;
++ pkg_dest_list_t pkg_dest_list;
++ nv_pair_list_t arch_list;
++
++ int restrict_to_default_dest;
++ pkg_dest_t *default_dest;
++
++ char *tmp_dir;
++ const char *lists_dir;
++ const char *pending_dir;
++
++ /* options */
++ int force_depends;
++ int force_defaults;
++ int force_overwrite;
++ int force_downgrade;
++ int force_reinstall;
++ int force_space;
++ int force_removal_of_dependent_packages;
++ int force_removal_of_essential_packages;
++ int nodeps; /* do not follow dependences */
++ int verbose_wget;
++ int multiple_providers;
++ char *offline_root;
++ char *offline_root_pre_script_cmd;
++ char *offline_root_post_script_cmd;
++ int query_all;
++ int verbosity;
++ int noaction;
++
++ /* proxy options */
++ char *http_proxy;
++ char *ftp_proxy;
++ char *no_proxy;
++ char *proxy_user;
++ char *proxy_passwd;
++
++ hash_table_t pkg_hash;
++ hash_table_t file_hash;
++ hash_table_t obs_file_hash;
++};
++
++enum ipkg_option_type {
++ IPKG_OPT_TYPE_BOOL,
++ IPKG_OPT_TYPE_INT,
++ IPKG_OPT_TYPE_STRING
++};
++typedef enum ipkg_option_type ipkg_option_type_t;
++
++typedef struct ipkg_option ipkg_option_t;
++struct ipkg_option {
++ const char *name;
++ const ipkg_option_type_t type;
++ const void *value;
++};
++
++int ipkg_conf_init(ipkg_conf_t *conf, const args_t *args);
++void ipkg_conf_deinit(ipkg_conf_t *conf);
++
++int ipkg_conf_write_status_files(ipkg_conf_t *conf);
++char *root_filename_alloc(ipkg_conf_t *conf, char *filename);
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_configure.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_configure.c
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_configure.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_configure.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,40 @@
++/* ipkg_configure.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++
++#include "ipkg_configure.h"
++
++int ipkg_configure(ipkg_conf_t *conf, pkg_t *pkg)
++{
++ int err;
++
++ /* DPKG_INCOMPATIBILITY:
++ dpkg actually does some conffile handling here, rather than at the
++ end of ipkg_install(). Do we care? */
++ /* DPKG_INCOMPATIBILITY:
++ dpkg actually includes a version number to this script call */
++ err = pkg_run_script(conf, pkg, "postinst", "configure");
++ if (err) {
++ printf("ERROR: %s.postinst returned %d\n", pkg->name, err);
++ return err;
++ }
++
++ ipkg_state_changed++;
++ return 0;
++}
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_configure.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_configure.h
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_configure.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_configure.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,25 @@
++/* ipkg_configure.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef IPKG_CONFIGURE_H
++#define IPKG_CONFIGURE_H
++
++#include "ipkg_conf.h"
++
++int ipkg_configure(ipkg_conf_t *ipkg_conf, pkg_t *pkg);
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_download.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_download.c
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_download.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_download.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,195 @@
++/* ipkg_download.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++#include "ipkg_download.h"
++#include "ipkg_message.h"
++
++#include "sprintf_alloc.h"
++#include "xsystem.h"
++#include "file_util.h"
++#include "str_util.h"
++
++int ipkg_download(ipkg_conf_t *conf, const char *src, const char *dest_file_name)
++{
++ int err = 0;
++
++ char *src_basec = strdup(src);
++ char *src_base = basename(src_basec);
++ char *tmp_file_location;
++ char *cmd;
++
++ ipkg_message(conf,IPKG_NOTICE,"Downloading %s\n", src);
++
++ fflush(stdout);
++
++ if (str_starts_with(src, "file:")) {
++ int ret;
++ const char *file_src = src + 5;
++ ipkg_message(conf,IPKG_INFO,"Copying %s to %s...", file_src, dest_file_name);
++ ret = file_copy(src + 5, dest_file_name);
++ ipkg_message(conf,IPKG_INFO,"Done.\n");
++ return ret;
++ }
++
++ sprintf_alloc(&tmp_file_location, "%s/%s", conf->tmp_dir, src_base);
++ err = unlink(tmp_file_location);
++ if (err && errno != ENOENT) {
++ ipkg_message(conf,IPKG_ERROR, "%s: ERROR: failed to unlink %s: %s\n",
++ __FUNCTION__, tmp_file_location, strerror(errno));
++ free(tmp_file_location);
++ return errno;
++ }
++
++ if (conf->http_proxy) {
++ ipkg_message(conf,IPKG_DEBUG,"Setting environment variable: http_proxy = %s\n", conf->http_proxy);
++ setenv("http_proxy", conf->http_proxy, 1);
++ }
++ if (conf->ftp_proxy) {
++ ipkg_message(conf,IPKG_DEBUG,"Setting environment variable: ftp_proxy = %s\n", conf->ftp_proxy);
++ setenv("ftp_proxy", conf->ftp_proxy, 1);
++ }
++ if (conf->no_proxy) {
++ ipkg_message(conf,IPKG_DEBUG,"Setting environment variable: no_proxy = %s\n", conf->no_proxy);
++ setenv("no_proxy", conf->no_proxy, 1);
++ }
++
++ /* XXX: BUG rewrite to use execvp or else busybox's internal wget -Jamey 7/23/2002 */
++ sprintf_alloc(&cmd, "wget --passive-ftp %s %s%s %s%s %s -P %s %s",
++ (conf->http_proxy || conf->ftp_proxy) ? "--proxy=on" : "",
++ conf->proxy_user ? "--proxy-user=" : "",
++ conf->proxy_user ? conf->proxy_user : "",
++ conf->proxy_passwd ? "--proxy-passwd=" : "",
++ conf->proxy_passwd ? conf->proxy_passwd : "",
++ conf->verbose_wget ? "" : "-q",
++ conf->tmp_dir,
++ src);
++ err = xsystem(cmd);
++ if (err) {
++ if (err != -1) {
++ ipkg_message(conf,IPKG_ERROR, "%s: ERROR: Command failed with return value %d: `%s'\n",
++ __FUNCTION__, err, cmd);
++ }
++ unlink(tmp_file_location);
++ free(tmp_file_location);
++ free(src_basec);
++ free(cmd);
++ return EINVAL;
++ }
++ free(cmd);
++
++ err = file_move(tmp_file_location, dest_file_name);
++
++ free(tmp_file_location);
++ free(src_basec);
++
++ if (err) {
++ return err;
++ }
++
++ return 0;
++}
++
++int ipkg_download_pkg(ipkg_conf_t *conf, pkg_t *pkg, const char *dir)
++{
++ int err;
++ char *url;
++
++ if (pkg->src == NULL) {
++ ipkg_message(conf,IPKG_ERROR, "ERROR: Package %s (parent %s) is not available from any configured src.\n",
++ pkg->name, pkg->parent->name);
++ return -1;
++ }
++
++ sprintf_alloc(&url, "%s/%s", pkg->src->value, pkg->filename);
++
++ /* XXX: BUG: The pkg->filename might be something like
++ "../../foo.ipk". While this is correct, and exactly what we
++ want to use to construct url above, here we actually need to
++ use just the filename part, without any directory. */
++ sprintf_alloc(&pkg->local_filename, "%s/%s", dir, pkg->filename);
++
++ err = ipkg_download(conf, url, pkg->local_filename);
++ free(url);
++
++ return err;
++}
++
++/*
++ * Downloads file from url, installs in package database, return package name.
++ */
++int ipkg_prepare_url_for_install(ipkg_conf_t *conf, const char *url, char **namep)
++{
++ int err = 0;
++ pkg_t *pkg;
++ pkg = pkg_new();
++ if (pkg == NULL)
++ return ENOMEM;
++
++ if (str_starts_with(url, "http://")
++ || str_starts_with(url, "ftp://")) {
++ char *tmp_file;
++ char *file_basec = strdup(url);
++ char *file_base = basename(file_basec);
++
++ sprintf_alloc(&tmp_file, "%s/%s", conf->tmp_dir, file_base);
++ err = ipkg_download(conf, url, tmp_file);
++ if (err)
++ return err;
++
++ err = pkg_init_from_file(pkg, tmp_file);
++ if (err)
++ return err;
++ pkg->local_filename = strdup(tmp_file);
++
++ free(tmp_file);
++ free(file_basec);
++
++ } else if (strcmp(&url[strlen(url) - 4], IPKG_PKG_EXTENSION) == 0
++ || strcmp(&url[strlen(url) - 4], DPKG_PKG_EXTENSION) == 0) {
++
++ err = pkg_init_from_file(pkg, url);
++ if (err)
++ return err;
++ pkg->local_filename = strdup(url);
++ ipkg_message(conf, IPKG_DEBUG2, "Package %s provided by hand \(%s\).\n", pkg->name,pkg->local_filename);
++ pkg->provided_by_hand = 1;
++
++ } else {
++ pkg_deinit(pkg);
++ free(pkg);
++ return 0;
++ }
++
++ if (!pkg->architecture) {
++ ipkg_message(conf, IPKG_ERROR, "Package %s has no Architecture defined.\n", pkg->name);
++ return -EINVAL;
++ }
++
++ pkg->dest = conf->default_dest;
++ pkg->state_want = SW_INSTALL;
++ pkg->state_flag |= SF_PREFER;
++ pkg = hash_insert_pkg(&conf->pkg_hash, pkg, 1,conf);
++ if ( pkg == NULL ){
++ fprintf(stderr, "%s : This should never happen. Report this Bug in bugzilla please \n ",__FUNCTION__);
++ return 0;
++ }
++ if (namep) {
++ *namep = strdup(pkg->name);
++ }
++ return 0;
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_download.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_download.h
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_download.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_download.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,30 @@
++/* ipkg_download.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef IPKG_DOWNLOAD_H
++#define IPKG_DOWNLOAD_H
++
++#include "ipkg_conf.h"
++
++int ipkg_download(ipkg_conf_t *conf, const char *src, const char *dest_file_name);
++int ipkg_download_pkg(ipkg_conf_t *conf, pkg_t *pkg, const char *dir);
++/*
++ * Downloads file from url, installs in package database, return package name.
++ */
++int ipkg_prepare_url_for_install(ipkg_conf_t *conf, const char *url, char **namep);
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg.h
+--- busybox-1.2.0-orig/archival/libipkg/ipkg.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,74 @@
++/* ipkg.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef IPKG_H
++#define IPKG_H
++
++/*
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++*/
++
++#if 0
++#define IPKG_DEBUG_NO_TMP_CLEANUP
++#endif
++
++#include "ipkg_includes.h"
++#include "ipkg_conf.h"
++#include "ipkg_message.h"
++
++#define IPKG_PKG_EXTENSION ".ipk"
++#define DPKG_PKG_EXTENSION ".deb"
++
++#define IPKG_LEGAL_PKG_NAME_CHARS "abcdefghijklmnopqrstuvwxyz0123456789.+-"
++#define IPKG_PKG_VERSION_SEP_CHAR '_'
++
++#define IPKG_STATE_DIR_PREFIX IPKGLIBDIR"/ipkg"
++#define IPKG_LISTS_DIR_SUFFIX "lists"
++#define IPKG_INFO_DIR_SUFFIX "info"
++#define IPKG_STATUS_FILE_SUFFIX "status"
++
++#define IPKG_BACKUP_SUFFIX "-ipkg.backup"
++
++#define IPKG_LIST_DESCRIPTION_LENGTH 128
++
++#define IPKG_VERSION "0.99.162"
++
++
++enum ipkg_error {
++ IPKG_SUCCESS = 0,
++ IPKG_PKG_DEPS_UNSATISFIED,
++ IPKG_PKG_IS_ESSENTIAL,
++ IPKG_PKG_HAS_DEPENDENTS,
++ IPKG_PKG_HAS_NO_CANDIDATE
++};
++typedef enum ipkg_error ipkg_error_t;
++
++extern int ipkg_state_changed;
++
++
++struct errlist {
++ char * errmsg;
++ struct errlist * next;
++} ;
++
++extern struct errlist* error_list;
++
++extern ipkg_conf_t *global_conf;
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_includes.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_includes.h
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_includes.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_includes.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,79 @@
++#ifndef IPKG_INCLUDES_H
++#define IPKG_INCLUDES_H
++
++/* Define to 1 if you have the <memory.h> header file. */
++#define HAVE_MEMORY_H 1
++
++/* Define to 1 if you have the <regex.h> header file. */
++#define HAVE_REGEX_H 1
++
++/* Define to 1 if you have the <stdlib.h> header file. */
++#define HAVE_STDLIB_H 1
++
++/* Define to 1 if you have the <strings.h> header file. */
++#define HAVE_STRINGS_H 1
++
++/* Define to 1 if you have the <string.h> header file. */
++#define HAVE_STRING_H 1
++
++/* Define to 1 if you have the <sys/stat.h> header file. */
++#define HAVE_SYS_STAT_H 1
++
++/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
++#define HAVE_SYS_WAIT_H 1
++
++/* Define to 1 if you have the <unistd.h> header file. */
++#define HAVE_UNISTD_H 1
++
++/* Define to 1 if you have the ANSI C header files. */
++#define STDC_HEADERS 1
++
++
++#include <stdio.h>
++
++#if STDC_HEADERS
++# include <stdlib.h>
++# include <stdarg.h>
++# include <stddef.h>
++# include <ctype.h>
++# include <errno.h>
++#else
++# if HAVE_STDLIB_H
++# include <stdlib.h>
++# endif
++#endif
++
++#if HAVE_REGEX_H
++# include <regex.h>
++#endif
++
++#if HAVE_STRING_H
++# if !STDC_HEADERS && HAVE_MEMORY_H
++# include <memory.h>
++# endif
++/* XXX: What's the right way to pick up GNU's strndup declaration? */
++# if __GNUC__
++# define __USE_GNU 1
++# endif
++# include <string.h>
++# undef __USE_GNU
++#endif
++
++#if HAVE_STRINGS_H
++# include <strings.h>
++#endif
++
++#if HAVE_SYS_STAT_H
++# include <sys/stat.h>
++#endif
++
++#if HAVE_SYS_WAIT_H
++# include <sys/wait.h>
++#endif
++
++#if HAVE_UNISTD_H
++# include <sys/types.h>
++# include <unistd.h>
++#endif
++
++#endif /* IPKG_INCLUDES_H */
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_install.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_install.c
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_install.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_install.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,1942 @@
++/* ipkg_install.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++#include <errno.h>
++#include <dirent.h>
++#include <glob.h>
++#include <time.h>
++#include <signal.h>
++typedef void (*sighandler_t)(int);
++
++#include "pkg.h"
++#include "pkg_hash.h"
++#include "pkg_extract.h"
++
++#include "ipkg_install.h"
++#include "ipkg_configure.h"
++#include "ipkg_download.h"
++#include "ipkg_remove.h"
++
++#include "ipkg_utils.h"
++#include "ipkg_message.h"
++
++#include "sprintf_alloc.h"
++#include "file_util.h"
++#include "str_util.h"
++#include "xsystem.h"
++#include "user.h"
++
++int satisfy_dependencies_for(ipkg_conf_t *conf, pkg_t *pkg);
++static int verify_pkg_installable(ipkg_conf_t *conf, pkg_t *pkg);
++static int unpack_pkg_control_files(ipkg_conf_t *conf, pkg_t *pkg);
++
++static int prerm_upgrade_old_pkg(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int prerm_upgrade_old_pkg_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int prerm_deconfigure_conflictors(ipkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *conflictors);
++static int prerm_deconfigure_conflictors_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *conflictors);
++static int preinst_configure(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int preinst_configure_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int check_data_file_clashes(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int check_data_file_clashes_change(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int check_data_file_clashes_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int backup_modified_conffiles(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int backup_modified_conffiles_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int postrm_upgrade_old_pkg(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int postrm_upgrade_old_pkg_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++
++static int remove_obsolesced_files(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int install_maintainer_scripts(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int remove_disappeared(ipkg_conf_t *conf, pkg_t *pkg);
++static int install_data_files(ipkg_conf_t *conf, pkg_t *pkg);
++static int resolve_conffiles(ipkg_conf_t *conf, pkg_t *pkg);
++
++static int cleanup_temporary_files(ipkg_conf_t *conf, pkg_t *pkg);
++
++static int user_prefers_old_conffile(const char *file, const char *backup);
++
++static char *backup_filename_alloc(const char *file_name);
++static int backup_make_backup(ipkg_conf_t *conf, const char *file_name);
++static int backup_exists_for(const char *file_name);
++static int backup_remove(const char *file_name);
++
++
++int ipkg_install_from_file(ipkg_conf_t *conf, const char *filename)
++{
++ int err, cmp;
++ pkg_t *pkg, *old;
++ char *old_version, *new_version;
++
++ pkg = pkg_new();
++ if (pkg == NULL) {
++ return ENOMEM;
++ }
++
++ err = pkg_init_from_file(pkg, filename);
++ if (err) {
++ return err;
++ }
++
++ if (!pkg->architecture) {
++ ipkg_message(conf, IPKG_ERROR, "Package %s has no Architecture defined.\n", pkg->name);
++ return -EINVAL;
++ }
++
++ /* XXX: CLEANUP: hash_insert_pkg has a nasty side effect of possibly
++ freeing the pkg that we pass in. It might be nice to clean this up
++ if possible. */
++ pkg = hash_insert_pkg(&conf->pkg_hash, pkg, 1,conf);
++ old = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name);
++
++ pkg->local_filename = strdup(filename);
++
++ if (old) {
++ old_version = pkg_version_str_alloc(old);
++ new_version = pkg_version_str_alloc(pkg);
++
++ cmp = pkg_compare_versions(old, pkg);
++ if ( (conf->force_downgrade==1) && (cmp > 0) ){ /* We've been asked to allow downgrade and version is precedent */
++ cmp = -1 ; /* then we force ipkg to downgrade */
++ /* We need to use a value < 0 because in the 0 case we are asking to */
++ /* reinstall, and some check could fail asking the "force-reinstall" option */
++ }
++ if (cmp > 0) {
++ ipkg_message(conf, IPKG_NOTICE,
++ "Not downgrading package %s on %s from %s to %s.\n",
++ old->name, old->dest->name, old_version, new_version);
++ pkg->state_want = SW_DEINSTALL;
++ pkg->state_flag |= SF_OBSOLETE;
++ free(old_version);
++ free(new_version);
++ return 0;
++ } else {
++ free(old_version);
++ free(new_version);
++ }
++ }
++
++ ipkg_message(conf, IPKG_DEBUG2,"Function: %s calling ipkg_install_pkg \n",__FUNCTION__);
++ return ipkg_install_pkg(conf, pkg,0);
++}
++
++ipkg_error_t ipkg_install_by_name(ipkg_conf_t *conf, const char *pkg_name)
++{
++ int cmp;
++ pkg_t *old, *new;
++ char *old_version, *new_version;
++
++ ipkg_message(conf, IPKG_DEBUG2, " Getting old from pkg_hash_fetch \n" );
++ old = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg_name);
++ if ( old )
++ ipkg_message(conf, IPKG_DEBUG2, " Old versions from pkg_hash_fetch %s \n", old->version );
++
++ ipkg_message(conf, IPKG_DEBUG2, " Getting new from pkg_hash_fetch \n" );
++ new = pkg_hash_fetch_best_installation_candidate_by_name(conf, pkg_name);
++ if ( new )
++ ipkg_message(conf, IPKG_DEBUG2, " New versions from pkg_hash_fetch %s \n", new->version );
++
++/* Pigi Basically here is broken the version stuff.
++ What's happening is that nothing provide the version to differents
++ functions, so the returned struct is always the latest.
++ That's why the install by name don't work.
++*/
++ ipkg_message(conf, IPKG_DEBUG2, " Versions from pkg_hash_fetch in %s ", __FUNCTION__ );
++
++ if ( old )
++ ipkg_message(conf, IPKG_DEBUG2, " old %s ", old->version );
++ if ( new )
++ ipkg_message(conf, IPKG_DEBUG2, " new %s ", new->version );
++ ipkg_message(conf, IPKG_DEBUG2, " \n");
++
++ if (new == NULL) {
++ return IPKG_PKG_HAS_NO_CANDIDATE;
++ }
++
++ new->state_flag |= SF_USER;
++ if (old) {
++ old_version = pkg_version_str_alloc(old);
++ new_version = pkg_version_str_alloc(new);
++
++ cmp = pkg_compare_versions(old, new);
++ if ( (conf->force_downgrade==1) && (cmp > 0) ){ /* We've been asked to allow downgrade and version is precedent */
++ ipkg_message(conf, IPKG_DEBUG, " Forcing downgrade \n");
++ cmp = -1 ; /* then we force ipkg to downgrade */
++ /* We need to use a value < 0 because in the 0 case we are asking to */
++ /* reinstall, and some check could fail asking the "force-reinstall" option */
++ }
++ ipkg_message(conf, IPKG_DEBUG,
++ "Comparing visible versions of pkg %s:"
++ "\n\t%s is installed "
++ "\n\t%s is available "
++ "\n\t%d was comparison result\n",
++ pkg_name, old_version, new_version, cmp);
++ if (cmp == 0 && !conf->force_reinstall) {
++ ipkg_message(conf, IPKG_NOTICE,
++ "Package %s (%s) installed in %s is up to date.\n",
++ old->name, old_version, old->dest->name);
++ free(old_version);
++ free(new_version);
++ return 0;
++ } else if (cmp > 0) {
++ ipkg_message(conf, IPKG_NOTICE,
++ "Not downgrading package %s on %s from %s to %s.\n",
++ old->name, old->dest->name, old_version, new_version);
++ free(old_version);
++ free(new_version);
++ return 0;
++ } else if (cmp < 0) {
++ new->dest = old->dest;
++ old->state_want = SW_DEINSTALL; /* Here probably the problem for bug 1277 */
++ }
++ }
++
++ /* XXX: CLEANUP: The error code of ipkg_install_by_name is really
++ supposed to be an ipkg_error_t, but ipkg_install_pkg could
++ return any kind of integer, (might be errno from a syscall,
++ etc.). This is a real mess and will need to be cleaned up if
++ anyone ever wants to make a nice libipkg. */
++
++ ipkg_message(conf, IPKG_DEBUG2,"Function: %s calling ipkg_install_pkg \n",__FUNCTION__);
++ return ipkg_install_pkg(conf, new,0);
++}
++
++ipkg_error_t ipkg_install_multi_by_name(ipkg_conf_t *conf, const char *pkg_name)
++{
++ abstract_pkg_vec_t *providers = pkg_hash_fetch_all_installation_candidates (&conf->pkg_hash, pkg_name);
++ int i;
++ ipkg_error_t err;
++ abstract_pkg_t *ppkg ;
++
++ if (providers == NULL)
++ return IPKG_PKG_HAS_NO_CANDIDATE;
++
++ for (i = 0; i < providers->len; i++) {
++ ppkg = abstract_pkg_vec_get(providers, i);
++ ipkg_message(conf, IPKG_DEBUG2,"Function: %s calling ipkg_install_by_name %d \n",__FUNCTION__, i);
++ err = ipkg_install_by_name(conf, ppkg->name);
++ if (err)
++ return err;
++/* XXX Maybe ppkg should be freed ? */
++ }
++ return 0;
++}
++
++/*
++ * Walk dependence graph starting with pkg, collect packages to be
++ * installed into pkgs_needed, in dependence order.
++ */
++int pkg_mark_dependencies_for_installation(ipkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *pkgs_needed)
++{
++ int i, err;
++ pkg_vec_t *depends = pkg_vec_alloc();
++ char **unresolved = NULL;
++ int ndepends;
++
++ ndepends = pkg_hash_fetch_unsatisfied_dependencies(conf,
++ pkg, depends,
++ &unresolved);
++
++ if (unresolved) {
++ ipkg_message(conf, IPKG_ERROR,
++ "%s: Cannot satisfy the following dependencies for %s:\n\t",
++ conf->force_depends ? "Warning" : "ERROR", pkg->name);
++ while (*unresolved) {
++ ipkg_message(conf, IPKG_ERROR, " %s", *unresolved);
++ unresolved++;
++ }
++ ipkg_message(conf, IPKG_ERROR, "\n");
++ if (! conf->force_depends) {
++ ipkg_message(conf, IPKG_INFO,
++ "This could mean that your package list is out of date or that the packages\n"
++ "mentioned above do not yet exist (try 'ipkg update'). To proceed in spite\n"
++ "of this problem try again with the '-force-depends' option.\n");
++ pkg_vec_free(depends);
++ return IPKG_PKG_DEPS_UNSATISFIED;
++ }
++ }
++
++ if (ndepends <= 0) {
++ pkg_vec_free(depends);
++ return 0;
++ }
++
++ for (i = 0; i < depends->len; i++) {
++ pkg_t *dep = depends->pkgs[i];
++ /* The package was uninstalled when we started, but another
++ dep earlier in this loop may have depended on it and pulled
++ it in, so check first. */
++ if ((dep->state_status != SS_INSTALLED)
++ && (dep->state_status != SS_UNPACKED)
++ && (dep->state_want != SW_INSTALL)) {
++
++ /* Mark packages as to-be-installed */
++ dep->state_want = SW_INSTALL;
++
++ /* Dependencies should be installed the same place as pkg */
++ if (dep->dest == NULL) {
++ dep->dest = pkg->dest;
++ }
++
++ err = pkg_mark_dependencies_for_installation(conf, dep, pkgs_needed);
++ if (err) {
++ pkg_vec_free(depends);
++ return err;
++ }
++ }
++ }
++ if (pkgs_needed)
++ pkg_vec_insert(pkgs_needed, pkg);
++
++ pkg_vec_free(depends);
++
++ return 0;
++}
++
++int name_mark_dependencies_for_installation(ipkg_conf_t *conf, const char *pkg_name, pkg_vec_t *pkgs_needed)
++{
++ int cmp;
++ pkg_t *old, *new;
++ char *old_version, *new_version;
++
++ old = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg_name);
++
++ new = pkg_hash_fetch_best_installation_candidate_by_name(conf, pkg_name);
++ if (new == NULL) {
++ return IPKG_PKG_HAS_NO_CANDIDATE;
++ }
++ if (old) {
++ old_version = pkg_version_str_alloc(old);
++ new_version = pkg_version_str_alloc(new);
++
++ cmp = pkg_compare_versions(old, new);
++ if ( (conf->force_downgrade==1) && (cmp > 0) ){ /* We've been asked to allow downgrade and version is precedent */
++ ipkg_message(conf, IPKG_DEBUG, " Forcing downgrade ");
++ cmp = -1 ; /* then we force ipkg to downgrade */
++ /* We need to use a value < 0 because in the 0 case we are asking to */
++ /* reinstall, and some check could fail asking the "force-reinstall" option */
++ }
++ ipkg_message(conf, IPKG_DEBUG,
++ "comparing visible versions of pkg %s:"
++ "\n\t%s is installed "
++ "\n\t%s is available "
++ "\n\t%d was comparison result\n",
++ pkg_name, old_version, new_version, cmp);
++ if (cmp == 0 && !conf->force_reinstall) {
++ ipkg_message(conf, IPKG_NOTICE,
++ "Package %s (%s) installed in %s is up to date.\n",
++ old->name, old_version, old->dest->name);
++ free(old_version);
++ free(new_version);
++ return 0;
++ } else if (cmp > 0) {
++ ipkg_message(conf, IPKG_NOTICE,
++ "Not downgrading package %s on %s from %s to %s.\n",
++ old->name, old->dest->name, old_version, new_version);
++ free(old_version);
++ free(new_version);
++ return 0;
++ } else if (cmp < 0) {
++ new->dest = old->dest;
++ old->state_want = SW_DEINSTALL;
++ old->state_flag |= SF_OBSOLETE;
++ }
++ }
++ return pkg_mark_dependencies_for_installation(conf, new, pkgs_needed);
++}
++
++
++
++int satisfy_dependencies_for(ipkg_conf_t *conf, pkg_t *pkg)
++{
++ int i, err;
++ pkg_vec_t *depends = pkg_vec_alloc();
++ pkg_t *dep;
++ char **unresolved = NULL;
++ int ndepends;
++
++ ndepends = pkg_hash_fetch_unsatisfied_dependencies(conf,
++ pkg, depends,
++ &unresolved);
++
++ if (unresolved) {
++ ipkg_message(conf, IPKG_ERROR,
++ "%s: Cannot satisfy the following dependencies for %s:\n\t",
++ conf->force_depends ? "Warning" : "ERROR", pkg->name);
++ while (*unresolved) {
++ ipkg_message(conf, IPKG_ERROR, " %s", *unresolved);
++ unresolved++;
++ }
++ ipkg_message(conf, IPKG_ERROR, "\n");
++ if (! conf->force_depends) {
++ ipkg_message(conf, IPKG_INFO,
++ "This could mean that your package list is out of date or that the packages\n"
++ "mentioned above do not yet exist (try 'ipkg update'). To proceed in spite\n"
++ "of this problem try again with the '-force-depends' option.\n");
++ pkg_vec_free(depends);
++ return IPKG_PKG_DEPS_UNSATISFIED;
++ }
++ }
++
++ if (ndepends <= 0) {
++ return 0;
++ }
++
++ /* Mark packages as to-be-installed */
++ for (i=0; i < depends->len; i++) {
++ /* Dependencies should be installed the same place as pkg */
++ if (depends->pkgs[i]->dest == NULL) {
++ depends->pkgs[i]->dest = pkg->dest;
++ }
++ depends->pkgs[i]->state_want = SW_INSTALL;
++ }
++
++ for (i = 0; i < depends->len; i++) {
++ dep = depends->pkgs[i];
++ /* The package was uninstalled when we started, but another
++ dep earlier in this loop may have depended on it and pulled
++ it in, so check first. */
++ if ((dep->state_status != SS_INSTALLED)
++ && (dep->state_status != SS_UNPACKED)) {
++ ipkg_message(conf, IPKG_DEBUG2,"Function: %s calling ipkg_install_pkg \n",__FUNCTION__);
++ err = ipkg_install_pkg(conf, dep,0);
++ if (err) {
++ pkg_vec_free(depends);
++ return err;
++ }
++ }
++ }
++
++ pkg_vec_free(depends);
++
++ return 0;
++}
++
++
++/* check all packages have their dependences satisfied, e.g., in case an upgraded package split */
++int ipkg_satisfy_all_dependences(ipkg_conf_t *conf)
++{
++ if (conf->nodeps == 0) {
++ int i;
++ pkg_vec_t *installed = pkg_vec_alloc();
++ pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
++ for (i = 0; i < installed->len; i++) {
++ pkg_t *pkg = installed->pkgs[i];
++ satisfy_dependencies_for(conf, pkg);
++ }
++ pkg_vec_free(installed);
++ }
++ return 0;
++}
++
++
++
++static int check_conflicts_for(ipkg_conf_t *conf, pkg_t *pkg)
++{
++ int i;
++ pkg_vec_t *conflicts = NULL;
++ int level;
++ const char *prefix;
++ if (conf->force_depends) {
++ level = IPKG_NOTICE;
++ prefix = "Warning";
++ } else {
++ level = IPKG_ERROR;
++ prefix = "ERROR";
++ }
++
++ if (!conf->force_depends)
++ conflicts = (pkg_vec_t *)pkg_hash_fetch_conflicts(&conf->pkg_hash, pkg);
++
++ if (conflicts) {
++ ipkg_message(conf, level,
++ "%s: The following packages conflict with %s:\n\t", prefix, pkg->name);
++ i = 0;
++ while (i < conflicts->len)
++ ipkg_message(conf, level, " %s", conflicts->pkgs[i++]->name);
++ ipkg_message(conf, level, "\n");
++ pkg_vec_free(conflicts);
++ return IPKG_PKG_DEPS_UNSATISFIED;
++ }
++ return 0;
++}
++
++static int update_file_ownership(ipkg_conf_t *conf, pkg_t *new_pkg, pkg_t *old_pkg)
++{
++ str_list_t *new_list = pkg_get_installed_files(new_pkg);
++ str_list_elt_t *iter;
++
++ for (iter = new_list->head; iter; iter = iter->next) {
++ char *new_file = iter->data;
++ pkg_t *owner = file_hash_get_file_owner(conf, new_file);
++ if (!new_file)
++ ipkg_message(conf, IPKG_ERROR, "Null new_file for new_pkg=%s\n", new_pkg->name);
++ if (!owner || (owner == old_pkg))
++ file_hash_set_file_owner(conf, new_file, new_pkg);
++ }
++ if (old_pkg) {
++ str_list_t *old_list = pkg_get_installed_files(old_pkg);
++ for (iter = old_list->head; iter; iter = iter->next) {
++ char *old_file = iter->data;
++ pkg_t *owner = file_hash_get_file_owner(conf, old_file);
++ if (owner == old_pkg) {
++ /* obsolete */
++ hash_table_insert(&conf->obs_file_hash, old_file, old_pkg);
++ }
++ }
++ }
++ return 0;
++}
++
++static int verify_pkg_installable(ipkg_conf_t *conf, pkg_t *pkg)
++{
++ /* XXX: FEATURE: Anything else needed here? Maybe a check on free space? */
++
++ /* sma 6.20.02: yup; here's the first bit */
++ /*
++ * XXX: BUG easy for cworth
++ * 1) please point the call below to the correct current root destination
++ * 2) we need to resolve how to check the required space for a pending pkg,
++ * my diddling with the .ipk file size below isn't going to cut it.
++ * 3) return a proper error code instead of 1
++ */
++ int comp_size, blocks_available;
++
++ if (!conf->force_space && pkg->installed_size != NULL) {
++ blocks_available = get_available_blocks(conf->default_dest->root_dir);
++
++ comp_size = strtoul(pkg->installed_size, NULL, 0);
++ /* round up a blocks count without doing fancy-but-slow casting jazz */
++ comp_size = (int)((comp_size + 1023) / 1024);
++
++ if (comp_size >= blocks_available) {
++ ipkg_message(conf, IPKG_ERROR,
++ "Only have %d available blocks on filesystem %s, pkg %s needs %d\n",
++ blocks_available, conf->default_dest->root_dir, pkg->name, comp_size);
++ return ENOSPC;
++ }
++ }
++ return 0;
++}
++
++static int unpack_pkg_control_files(ipkg_conf_t *conf, pkg_t *pkg)
++{
++ int err;
++ char *conffiles_file_name;
++ char *root_dir;
++ FILE *conffiles_file;
++
++ sprintf_alloc(&pkg->tmp_unpack_dir, "%s/%s-XXXXXX", conf->tmp_dir, pkg->name);
++
++ pkg->tmp_unpack_dir = mkdtemp(pkg->tmp_unpack_dir);
++ if (pkg->tmp_unpack_dir == NULL) {
++ ipkg_message(conf, IPKG_ERROR,
++ "%s: Failed to create temporary directory '%s': %s\n",
++ __FUNCTION__, pkg->tmp_unpack_dir, strerror(errno));
++ return errno;
++ }
++
++ err = pkg_extract_control_files_to_dir(pkg, pkg->tmp_unpack_dir);
++ if (err) {
++ return err;
++ }
++
++ /* XXX: CLEANUP: There might be a cleaner place to read in the
++ conffiles. Seems like I should be able to get everything to go
++ through pkg_init_from_file. If so, maybe it would make sense to
++ move all of unpack_pkg_control_files to that function. */
++
++ /* Don't need to re-read conffiles if we already have it */
++ if (pkg->conffiles.head) {
++ return 0;
++ }
++
++ sprintf_alloc(&conffiles_file_name, "%s/conffiles", pkg->tmp_unpack_dir);
++ if (! file_exists(conffiles_file_name)) {
++ free(conffiles_file_name);
++ return 0;
++ }
++
++ conffiles_file = fopen(conffiles_file_name, "r");
++ if (conffiles_file == NULL) {
++ fprintf(stderr, "%s: failed to open %s: %s\n",
++ __FUNCTION__, conffiles_file_name, strerror(errno));
++ free(conffiles_file_name);
++ return errno;
++ }
++ free(conffiles_file_name);
++
++ while (1) {
++ char *cf_name;
++ char *cf_name_in_dest;
++
++ cf_name = file_read_line_alloc(conffiles_file);
++ if (cf_name == NULL) {
++ break;
++ }
++ str_chomp(cf_name);
++ if (cf_name[0] == '\0') {
++ continue;
++ }
++
++ /* Prepend dest->root_dir to conffile name.
++ Take pains to avoid multiple slashes. */
++ root_dir = pkg->dest->root_dir;
++ if (conf->offline_root)
++ /* skip the offline_root prefix */
++ root_dir = pkg->dest->root_dir + strlen(conf->offline_root);
++ sprintf_alloc(&cf_name_in_dest, "%s%s", root_dir,
++ cf_name[0] == '/' ? (cf_name + 1) : cf_name);
++
++ /* Can't get an md5sum now, (file isn't extracted yet).
++ We'll wait until resolve_conffiles */
++ conffile_list_append(&pkg->conffiles, cf_name_in_dest, NULL);
++
++ free(cf_name);
++ free(cf_name_in_dest);
++ }
++
++ fclose(conffiles_file);
++
++ return 0;
++}
++
++/* returns number of installed replacees */
++int pkg_get_installed_replacees(ipkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *installed_replacees)
++{
++ abstract_pkg_t **replaces = pkg->replaces;
++ int replaces_count = pkg->replaces_count;
++ int i, j;
++ for (i = 0; i < replaces_count; i++) {
++ abstract_pkg_t *ab_pkg = replaces[i];
++ pkg_vec_t *pkg_vec = ab_pkg->pkgs;
++ if (pkg_vec) {
++ for (j = 0; j < pkg_vec->len; j++) {
++ pkg_t *replacee = pkg_vec->pkgs[j];
++ if (!pkg_conflicts(pkg, replacee))
++ continue;
++ if (replacee->state_status == SS_INSTALLED) {
++ pkg_vec_insert(installed_replacees, replacee);
++ }
++ }
++ }
++ }
++ return installed_replacees->len;
++}
++
++int pkg_remove_installed_replacees(ipkg_conf_t *conf, pkg_vec_t *replacees)
++{
++ int i;
++ int replaces_count = replacees->len;
++ for (i = 0; i < replaces_count; i++) {
++ pkg_t *replacee = replacees->pkgs[i];
++ int err;
++ replacee->state_flag |= SF_REPLACE; /* flag it so remove won't complain */
++ err = ipkg_remove_pkg(conf, replacee,0);
++ if (err)
++ return err;
++ }
++ return 0;
++}
++
++/* to unwind the removal: make sure they are installed */
++int pkg_remove_installed_replacees_unwind(ipkg_conf_t *conf, pkg_vec_t *replacees)
++{
++ int i, err;
++ int replaces_count = replacees->len;
++ for (i = 0; i < replaces_count; i++) {
++ pkg_t *replacee = replacees->pkgs[i];
++ if (replacee->state_status != SS_INSTALLED) {
++ ipkg_message(conf, IPKG_DEBUG2,"Function: %s calling ipkg_install_pkg \n",__FUNCTION__);
++ err = ipkg_install_pkg(conf, replacee,0);
++ if (err)
++ return err;
++ }
++ }
++ return 0;
++}
++
++int caught_sigint = 0;
++static void ipkg_install_pkg_sigint_handler(int sig)
++{
++ caught_sigint = sig;
++}
++
++/* compares versions of pkg and old_pkg, returns 0 if OK to proceed with installation of pkg, 1 otherwise */
++static int ipkg_install_check_downgrade(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg, int message)
++{
++ if (old_pkg) {
++ char message_out[15];
++ char *old_version = pkg_version_str_alloc(old_pkg);
++ char *new_version = pkg_version_str_alloc(pkg);
++ int cmp = pkg_compare_versions(old_pkg, pkg);
++ int rc = 0;
++
++ memset(message_out,'\x0',15);
++ strncpy (message_out,"Upgrading ",strlen("Upgrading "));
++ if ( (conf->force_downgrade==1) && (cmp > 0) ){ /* We've been asked to allow downgrade and version is precedent */
++ cmp = -1 ; /* then we force ipkg to downgrade */
++ strncpy (message_out,"Downgrading ",strlen("Downgrading ")); /* We need to use a value < 0 because in the 0 case we are asking to */
++ /* reinstall, and some check could fail asking the "force-reinstall" option */
++ }
++
++ if (cmp > 0) {
++ ipkg_message(conf, IPKG_NOTICE,
++ "Not downgrading package %s on %s from %s to %s.\n",
++ old_pkg->name, old_pkg->dest->name, old_version, new_version);
++ rc = 1;
++ } else if (cmp < 0) {
++ ipkg_message(conf, IPKG_NOTICE,
++ "%s%s on %s from %s to %s...\n",
++ message_out, pkg->name, old_pkg->dest->name, old_version, new_version);
++ pkg->dest = old_pkg->dest;
++ rc = 0;
++ } else /* cmp == 0 */ {
++ if (conf->force_reinstall) {
++ ipkg_message(conf, IPKG_NOTICE,
++ "Reinstalling %s (%s) on %s...\n",
++ pkg->name, new_version, old_pkg->dest->name);
++ pkg->dest = old_pkg->dest;
++ rc = 0;
++ } else {
++ ipkg_message(conf, IPKG_NOTICE,
++ "Not installing %s (%s) on %s -- already installed.\n",
++ pkg->name, new_version, old_pkg->dest->name);
++ rc = 1;
++ }
++ }
++ free(old_version);
++ free(new_version);
++ return rc;
++ } else {
++ char message_out[15] ;
++ memset(message_out,'\x0',15);
++ if ( message )
++ strncpy( message_out,"Upgrading ",strlen("Upgrading ") );
++ else
++ strncpy( message_out,"Installing ",strlen("Installing ") );
++ char *version = pkg_version_str_alloc(pkg);
++
++ ipkg_message(conf, IPKG_NOTICE,
++ "%s%s (%s) to %s...\n", message_out,
++ pkg->name, version, pkg->dest->name);
++ free(version);
++ return 0;
++ }
++}
++
++/* and now the meat... */
++int ipkg_install_pkg(ipkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
++{
++ int err = 0;
++ int message = 0;
++ pkg_t *old_pkg = NULL;
++ pkg_vec_t *replacees;
++ abstract_pkg_t *ab_pkg = NULL;
++ int old_state_flag;
++ char* file_md5;
++
++
++ if ( from_upgrade )
++ message = 1; /* Coming from an upgrade, and should change the output message */
++
++ if (!pkg) {
++ ipkg_message(conf, IPKG_ERROR,
++ "INTERNAL ERROR: null pkg passed to ipkg_install_pkg\n");
++ return -EINVAL;
++ }
++
++ ipkg_message(conf, IPKG_DEBUG2, "Function: %s calling pkg_arch_supported %s \n", __FUNCTION__, __FUNCTION__);
++
++ if (!pkg_arch_supported(conf, pkg)) {
++ ipkg_message(conf, IPKG_ERROR, "INTERNAL ERROR: architecture %s for pkg %s is unsupported.\n",
++ pkg->architecture, pkg->name);
++ return -EINVAL;
++ }
++ if (pkg->state_status == SS_INSTALLED && conf->force_reinstall == 0 && conf->nodeps == 0) {
++ err = satisfy_dependencies_for(conf, pkg);
++ if (err) { return err; }
++
++ ipkg_message(conf, IPKG_NOTICE,
++ "Package %s is already installed in %s.\n",
++ pkg->name, pkg->dest->name);
++ return 0;
++ }
++
++ if (pkg->dest == NULL) {
++ pkg->dest = conf->default_dest;
++ }
++
++ old_pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name);
++
++ err = ipkg_install_check_downgrade(conf, pkg, old_pkg, message);
++ if (err) { return err; }
++
++ pkg->state_want = SW_INSTALL;
++ if (old_pkg){
++ old_pkg->state_want = SW_DEINSTALL; /* needed for check_data_file_clashes of dependences */
++ }
++
++
++ /* Abhaya: conflicts check */
++ err = check_conflicts_for(conf, pkg);
++ if (err) { return err; }
++
++ /* this setup is to remove the upgrade scenario in the end when
++ installing pkg A, A deps B & B deps on A. So both B and A are
++ installed. Then A's installation is started resulting in an
++ uncecessary upgrade */
++ if (pkg->state_status == SS_INSTALLED
++ && conf->force_reinstall == 0) return 0;
++
++ err = verify_pkg_installable(conf, pkg);
++ if (err) { return err; }
++
++ if (pkg->local_filename == NULL) {
++ err = ipkg_download_pkg(conf, pkg, conf->tmp_dir);
++ if (err) {
++ ipkg_message(conf, IPKG_ERROR,
++ "Failed to download %s. Perhaps you need to run 'ipkg update'?\n",
++ pkg->name);
++ return err;
++ }
++ }
++
++/* Check for md5 values */
++ if (pkg->md5sum)
++ {
++ file_md5 = file_md5sum_alloc(pkg->local_filename);
++ if (strcmp(file_md5, pkg->md5sum))
++ {
++ ipkg_message(conf, IPKG_ERROR,
++ "Package %s md5sum mismatch. Either the ipkg or the package index are corrupt. Try 'ipkg update'.\n",
++ pkg->name);
++ free(file_md5);
++ return err;
++ }
++ free(file_md5);
++ }
++
++ if (pkg->tmp_unpack_dir == NULL) {
++ unpack_pkg_control_files(conf, pkg);
++ }
++
++ /* We should update the filelist here, so that upgrades of packages that split will not fail. -Jamey 27-MAR-03 */
++/* Pigi: check if it will pass from here when replacing. It seems to fail */
++/* That's rather strange that files don't change owner. Investigate !!!!!!*/
++ err = update_file_ownership(conf, pkg, old_pkg);
++ if (err) { return err; }
++
++ if (conf->nodeps == 0) {
++ err = satisfy_dependencies_for(conf, pkg);
++ if (err) { return err; }
++ }
++
++ replacees = pkg_vec_alloc();
++ pkg_get_installed_replacees(conf, pkg, replacees);
++
++ /* this next section we do with SIGINT blocked to prevent inconsistency between ipkg database and filesystem */
++ {
++ sigset_t newset, oldset;
++ sighandler_t old_handler = NULL;
++ int use_signal = 0;
++ caught_sigint = 0;
++ if (use_signal) {
++ old_handler = signal(SIGINT, ipkg_install_pkg_sigint_handler);
++ } else {
++ sigemptyset(&newset);
++ sigaddset(&newset, SIGINT);
++ sigprocmask(SIG_BLOCK, &newset, &oldset);
++ }
++
++ ipkg_state_changed++;
++ pkg->state_flag |= SF_FILELIST_CHANGED;
++
++ /* XXX: BUG: we really should treat replacement more like an upgrade
++ * Instead, we're going to remove the replacees
++ */
++ err = pkg_remove_installed_replacees(conf, replacees);
++ if (err) goto UNWIND_REMOVE_INSTALLED_REPLACEES;
++
++ err = prerm_upgrade_old_pkg(conf, pkg, old_pkg);
++ if (err) goto UNWIND_PRERM_UPGRADE_OLD_PKG;
++
++ err = prerm_deconfigure_conflictors(conf, pkg, replacees);
++ if (err) goto UNWIND_PRERM_DECONFIGURE_CONFLICTORS;
++
++ err = preinst_configure(conf, pkg, old_pkg);
++ if (err) goto UNWIND_PREINST_CONFIGURE;
++
++ err = backup_modified_conffiles(conf, pkg, old_pkg);
++ if (err) goto UNWIND_BACKUP_MODIFIED_CONFFILES;
++
++ err = check_data_file_clashes(conf, pkg, old_pkg);
++ if (err) goto UNWIND_CHECK_DATA_FILE_CLASHES;
++
++ err = postrm_upgrade_old_pkg(conf, pkg, old_pkg);
++ if (err) goto UNWIND_POSTRM_UPGRADE_OLD_PKG;
++
++ if (conf->noaction) return 0;
++
++ /* point of no return: no unwinding after this */
++ if (old_pkg && !conf->force_reinstall) {
++ old_pkg->state_want = SW_DEINSTALL;
++
++ if (old_pkg->state_flag & SF_NOPRUNE) {
++ ipkg_message(conf, IPKG_INFO,
++ " not removing obsolesced files because package marked noprune\n");
++ } else {
++ ipkg_message(conf, IPKG_INFO,
++ " removing obsolesced files\n");
++ remove_obsolesced_files(conf, pkg, old_pkg);
++ }
++ /* removing files from old package, to avoid ghost files */
++ remove_data_files_and_list(conf, old_pkg);
++/* Pigi : It should be better to remove also maintainer and postrem scripts here, just in case*/
++ remove_maintainer_scripts_except_postrm(conf, old_pkg);
++ remove_postrm(conf, old_pkg);
++/* Pigi */
++
++ }
++
++
++ ipkg_message(conf, IPKG_INFO,
++ " installing maintainer scripts\n");
++ install_maintainer_scripts(conf, pkg, old_pkg);
++
++ /* the following just returns 0 */
++ remove_disappeared(conf, pkg);
++
++ ipkg_message(conf, IPKG_INFO,
++ " installing data files\n");
++ install_data_files(conf, pkg);
++
++/* read comments from function for detail but I will execute this here as all other tests are ok.*/
++ err = check_data_file_clashes_change(conf, pkg, old_pkg);
++
++ ipkg_message(conf, IPKG_INFO,
++ " resolving conf files\n");
++ resolve_conffiles(conf, pkg);
++
++ pkg->state_status = SS_UNPACKED;
++ old_state_flag = pkg->state_flag;
++ pkg->state_flag &= ~SF_PREFER;
++ ipkg_message(conf, IPKG_DEBUG, " pkg=%s old_state_flag=%x state_flag=%x\n", pkg->name, old_state_flag, pkg->state_flag);
++
++ if (old_pkg && !conf->force_reinstall) {
++ old_pkg->state_status = SS_NOT_INSTALLED;
++ }
++
++ time(&pkg->installed_time);
++
++ ipkg_message(conf, IPKG_INFO,
++ " cleanup temp files\n");
++ cleanup_temporary_files(conf, pkg);
++
++ ab_pkg = pkg->parent;
++ if (ab_pkg)
++ ab_pkg->state_status = pkg->state_status;
++
++ ipkg_message(conf, IPKG_INFO, "Done.\n");
++
++ if (use_signal)
++ signal(SIGINT, old_handler);
++ else
++ sigprocmask(SIG_UNBLOCK, &newset, &oldset);
++
++ return 0;
++
++
++ UNWIND_POSTRM_UPGRADE_OLD_PKG:
++ postrm_upgrade_old_pkg_unwind(conf, pkg, old_pkg);
++ UNWIND_CHECK_DATA_FILE_CLASHES:
++ check_data_file_clashes_unwind(conf, pkg, old_pkg);
++ UNWIND_BACKUP_MODIFIED_CONFFILES:
++ backup_modified_conffiles_unwind(conf, pkg, old_pkg);
++ UNWIND_PREINST_CONFIGURE:
++ preinst_configure_unwind(conf, pkg, old_pkg);
++ UNWIND_PRERM_DECONFIGURE_CONFLICTORS:
++ prerm_deconfigure_conflictors_unwind(conf, pkg, replacees);
++ UNWIND_PRERM_UPGRADE_OLD_PKG:
++ prerm_upgrade_old_pkg_unwind(conf, pkg, old_pkg);
++ UNWIND_REMOVE_INSTALLED_REPLACEES:
++ pkg_remove_installed_replacees_unwind(conf, replacees);
++
++ ipkg_message(conf, IPKG_INFO,
++ " cleanup temp files\n");
++ cleanup_temporary_files(conf, pkg);
++
++ ipkg_message(conf, IPKG_INFO,
++ "Failed.\n");
++ if (use_signal)
++ signal(SIGINT, old_handler);
++ else
++ sigprocmask(SIG_UNBLOCK, &newset, &oldset);
++
++ return err;
++ }
++}
++
++static int prerm_upgrade_old_pkg(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
++{
++ /* DPKG_INCOMPATIBILITY:
++ dpkg does some things here that we don't do yet. Do we care?
++
++ 1. If a version of the package is already installed, call
++ old-prerm upgrade new-version
++ 2. If the script runs but exits with a non-zero exit status
++ new-prerm failed-upgrade old-version
++ Error unwind, for both the above cases:
++ old-postinst abort-upgrade new-version
++ */
++ return 0;
++}
++
++static int prerm_upgrade_old_pkg_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
++{
++ /* DPKG_INCOMPATIBILITY:
++ dpkg does some things here that we don't do yet. Do we care?
++ (See prerm_upgrade_old_package for details)
++ */
++ return 0;
++}
++
++static int prerm_deconfigure_conflictors(ipkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *conflictors)
++{
++ /* DPKG_INCOMPATIBILITY:
++ dpkg does some things here that we don't do yet. Do we care?
++ 2. If a 'conflicting' package is being removed at the same time:
++ 1. If any packages depended on that conflicting package and
++ --auto-deconfigure is specified, call, for each such package:
++ deconfigured's-prerm deconfigure \
++ in-favour package-being-installed version \
++ removing conflicting-package version
++ Error unwind:
++ deconfigured's-postinst abort-deconfigure \
++ in-favour package-being-installed-but-failed version \
++ removing conflicting-package version
++
++ The deconfigured packages are marked as requiring
++ configuration, so that if --install is used they will be
++ configured again if possible.
++ 2. To prepare for removal of the conflicting package, call:
++ conflictor's-prerm remove in-favour package new-version
++ Error unwind:
++ conflictor's-postinst abort-remove in-favour package new-version
++ */
++ return 0;
++}
++
++static int prerm_deconfigure_conflictors_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *conflictors)
++{
++ /* DPKG_INCOMPATIBILITY: dpkg does some things here that we don't
++ do yet. Do we care? (See prerm_deconfigure_conflictors for
++ details) */
++ return 0;
++}
++
++static int preinst_configure(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
++{
++ int err;
++ char *preinst_args;
++
++ if (old_pkg) {
++ char *old_version = pkg_version_str_alloc(old_pkg);
++ sprintf_alloc(&preinst_args, "upgrade %s", old_version);
++ free(old_version);
++ } else if (pkg->state_status == SS_CONFIG_FILES) {
++ char *pkg_version = pkg_version_str_alloc(pkg);
++ sprintf_alloc(&preinst_args, "install %s", pkg_version);
++ free(pkg_version);
++ } else {
++ preinst_args = strdup("install");
++ }
++
++ err = pkg_run_script(conf, pkg, "preinst", preinst_args);
++ if (err) {
++ ipkg_message(conf, IPKG_ERROR,
++ "Aborting installation of %s\n", pkg->name);
++ return 1;
++ }
++
++ free(preinst_args);
++
++ return 0;
++}
++
++static int preinst_configure_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
++{
++ /* DPKG_INCOMPATIBILITY:
++ dpkg does the following error unwind, should we?
++ pkg->postrm abort-upgrade old-version
++ OR pkg->postrm abort-install old-version
++ OR pkg->postrm abort-install
++ */
++ return 0;
++}
++
++static int backup_modified_conffiles(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
++{
++ int err;
++ conffile_list_elt_t *iter;
++ conffile_t *cf;
++
++ if (conf->noaction) return 0;
++
++ /* Backup all modified conffiles */
++ if (old_pkg) {
++ for (iter = old_pkg->conffiles.head; iter; iter = iter->next) {
++ char *cf_name;
++
++ cf = iter->data;
++ cf_name = root_filename_alloc(conf, cf->name);
++
++ /* Don't worry if the conffile is just plain gone */
++ if (file_exists(cf_name) && conffile_has_been_modified(conf, cf)) {
++ err = backup_make_backup(conf, cf_name);
++ if (err) {
++ return err;
++ }
++ }
++ free(cf_name);
++ }
++ }
++
++ /* Backup all conffiles that were not conffiles in old_pkg */
++ for (iter = pkg->conffiles.head; iter; iter = iter->next) {
++ char *cf_name;
++ cf = iter->data;
++ cf_name = root_filename_alloc(conf, cf->name);
++ /* Ignore if this was a conffile in old_pkg as well */
++ if (pkg_get_conffile(old_pkg, cf->name)) {
++ continue;
++ }
++
++ if (file_exists(cf_name) && (! backup_exists_for(cf_name))) {
++ err = backup_make_backup(conf, cf_name);
++ if (err) {
++ return err;
++ }
++ }
++ free(cf_name);
++ }
++
++ return 0;
++}
++
++static int backup_modified_conffiles_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
++{
++ conffile_list_elt_t *iter;
++
++ if (old_pkg) {
++ for (iter = old_pkg->conffiles.head; iter; iter = iter->next) {
++ backup_remove(iter->data->name);
++ }
++ }
++
++ for (iter = pkg->conffiles.head; iter; iter = iter->next) {
++ backup_remove(iter->data->name);
++ }
++
++ return 0;
++}
++
++
++static int check_data_file_clashes(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
++{
++ /* DPKG_INCOMPATIBILITY:
++ ipkg takes a slightly different approach than dpkg at this
++ point. dpkg installs each file in the new package while
++ creating a backup for any file that is replaced, (so that it
++ can unwind if necessary). To avoid complexity and redundant
++ storage, ipkg doesn't do any installation until later, (at the
++ point at which dpkg removes the backups.
++
++ But, we do have to check for data file clashes, since after
++ installing a package with a file clash, removing either of the
++ packages involved in the clash has the potential to break the
++ other package.
++ */
++ str_list_t *files_list;
++ str_list_elt_t *iter;
++
++ int clashes = 0;
++
++ files_list = pkg_get_installed_files(pkg);
++ for (iter = files_list->head; iter; iter = iter->next) {
++ char *root_filename;
++ char *filename = iter->data;
++ root_filename = root_filename_alloc(conf, filename);
++ if (file_exists(root_filename) && (! file_is_dir(root_filename))) {
++ pkg_t *owner;
++ pkg_t *obs;
++ /* Pre-existing conffiles are OK */
++ /* @@@@ should have way to check that it is a conffile -Jamey */
++ if (backup_exists_for(root_filename)) {
++ continue;
++ }
++
++ /* Pre-existing files are OK if force-overwrite was asserted. */
++ if (conf->force_overwrite) {
++ /* but we need to change who owns this file */
++ file_hash_set_file_owner(conf, filename, pkg);
++ continue;
++ }
++
++ owner = file_hash_get_file_owner(conf, filename);
++
++ /* Pre-existing files are OK if owned by the pkg being upgraded. */
++ if (owner && old_pkg) {
++ if (strcmp(owner->name, old_pkg->name) == 0) {
++ continue;
++ }
++ }
++
++ /* Pre-existing files are OK if owned by a package replaced by new pkg. */
++ if (owner) {
++ ipkg_message(conf, IPKG_DEBUG2, "Checking for replaces for %s in package %s\n", filename, owner->name);
++ if (pkg_replaces(pkg, owner)) {
++ continue;
++ }
++/* If the file that would be installed is owned by the same package, ( as per a reinstall or similar )
++ then it's ok to overwrite. */
++ if (strcmp(owner->name,pkg->name)==0){
++ ipkg_message(conf, IPKG_INFO, "Replacing pre-existing file %s owned by package %s\n", filename, owner->name);
++ continue;
++ }
++ }
++
++ /* Pre-existing files are OK if they are obsolete */
++ obs = hash_table_get(&conf->obs_file_hash, filename);
++ if (obs) {
++ ipkg_message(conf, IPKG_INFO, "Pre-exiting file %s is obsolete. obs_pkg=%s\n", filename, obs->name);
++ continue;
++ }
++
++ /* We have found a clash. */
++ ipkg_message(conf, IPKG_ERROR,
++ "Package %s wants to install file %s\n"
++ "\tBut that file is already provided by package ",
++ pkg->name, filename);
++ if (owner) {
++ ipkg_message(conf, IPKG_ERROR,
++ "%s\n", owner->name);
++ } else {
++ ipkg_message(conf, IPKG_ERROR,
++ "<no package>\nPlease move this file out of the way and try again.\n");
++ }
++ clashes++;
++ }
++ free(root_filename);
++ }
++ pkg_free_installed_files(pkg);
++
++ return clashes;
++}
++
++static int check_data_file_clashes_change(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
++{
++ /* Basically that's the worst hack I could do to be able to change ownership of
++ file list, but, being that we have no way to unwind the mods, due to structure
++ of hash table, probably is the quickest hack too, whishing it would not slow-up thing too much.
++ What we do here is change the ownership of file in hash if a replace ( or similar events
++ happens )
++ Only the action that are needed to change name should be considered.
++ @@@ To change after 1.0 release.
++ */
++ str_list_t *files_list;
++ str_list_elt_t *iter;
++
++ int clashes = 0;
++
++ files_list = pkg_get_installed_files(pkg);
++ for (iter = files_list->head; iter; iter = iter->next) {
++ char *root_filename;
++ char *filename = iter->data;
++ root_filename = root_filename_alloc(conf, filename);
++ if (file_exists(root_filename) && (! file_is_dir(root_filename))) {
++ pkg_t *owner;
++
++ if (conf->force_overwrite) {
++ /* but we need to change who owns this file */
++ file_hash_set_file_owner(conf, filename, pkg);
++ continue;
++ }
++
++ owner = file_hash_get_file_owner(conf, filename);
++
++ /* Pre-existing files are OK if owned by a package replaced by new pkg. */
++ if (owner) {
++ if (pkg_replaces(pkg, owner)) {
++/* It's now time to change the owner of that file.
++ It has been "replaced" from the new "Replaces", then I need to inform lists file about that. */
++ ipkg_message(conf, IPKG_INFO, "Replacing pre-existing file %s owned by package %s\n", filename, owner->name);
++ file_hash_set_file_owner(conf, filename, pkg);
++ continue;
++ }
++ }
++
++ }
++ free(root_filename);
++ }
++ pkg_free_installed_files(pkg);
++
++ return clashes;
++}
++
++static int check_data_file_clashes_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
++{
++ /* Nothing to do since check_data_file_clashes doesn't change state */
++ return 0;
++}
++
++static int postrm_upgrade_old_pkg(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
++{
++ /* DPKG_INCOMPATIBILITY: dpkg does the following here, should we?
++ 1. If the package is being upgraded, call
++ old-postrm upgrade new-version
++ 2. If this fails, attempt:
++ new-postrm failed-upgrade old-version
++ Error unwind, for both cases:
++ old-preinst abort-upgrade new-version */
++ return 0;
++}
++
++static int postrm_upgrade_old_pkg_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
++{
++ /* DPKG_INCOMPATIBILITY:
++ dpkg does some things here that we don't do yet. Do we care?
++ (See postrm_upgrade_old_pkg for details)
++ */
++ return 0;
++}
++
++static int remove_obsolesced_files(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
++{
++ int err;
++ str_list_t *old_files;
++ str_list_elt_t *of;
++ str_list_t *new_files;
++ str_list_elt_t *nf;
++
++ if (old_pkg == NULL) {
++ return 0;
++ }
++
++ old_files = pkg_get_installed_files(old_pkg);
++ new_files = pkg_get_installed_files(pkg);
++
++ for (of = old_files->head; of; of = of->next) {
++ pkg_t *owner;
++ char *old, *new;
++ old = of->data;
++ for (nf = new_files->head; nf; nf = nf->next) {
++ new = nf->data;
++ if (strcmp(old, new) == 0) {
++ goto NOT_OBSOLETE;
++ }
++ }
++ if (file_is_dir(old)) {
++ continue;
++ }
++ owner = file_hash_get_file_owner(conf, old);
++ if (owner != old_pkg) {
++ /* in case obsolete file no longer belongs to old_pkg */
++ continue;
++ }
++
++ /* old file is obsolete */
++ ipkg_message(conf, IPKG_INFO,
++ " removing obsolete file %s\n", old);
++ if (!conf->noaction) {
++ err = unlink(old);
++ if (err) {
++ ipkg_message(conf, IPKG_ERROR, " Warning: remove %s failed: %s\n", old,
++ strerror(errno));
++ }
++ }
++
++ NOT_OBSOLETE:
++ ;
++ }
++
++ pkg_free_installed_files(old_pkg);
++ pkg_free_installed_files(pkg);
++
++ return 0;
++}
++
++static int remove_obsolete_maintainer_scripts(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
++{
++ int i;
++ int err = 0;
++ char *globpattern;
++ glob_t globbuf;
++ if (0) {
++ if (!pkg->dest) {
++ ipkg_message(conf, IPKG_ERROR, "%s: no dest for package %s\n", __FUNCTION__, pkg->name);
++ return -1;
++ }
++ sprintf_alloc(&globpattern, "%s/%s.*", pkg->dest->info_dir, pkg->name);
++ err = glob(globpattern, 0, NULL, &globbuf);
++ free(globpattern);
++ if (err) {
++ return err;
++ }
++ /* XXXX this should perhaps only remove the ones that are not overwritten in new package. Jamey 11/11/2003 */
++ for (i = 0; i < globbuf.gl_pathc; i++) {
++ ipkg_message(conf, IPKG_DEBUG, "Removing control file %s from old_pkg %s\n",
++ globbuf.gl_pathv[i], old_pkg->name);
++ if (!conf->noaction)
++ unlink(globbuf.gl_pathv[i]);
++ }
++ globfree(&globbuf);
++ }
++ return err;
++}
++
++static int install_maintainer_scripts(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
++{
++ int ret;
++ char *prefix;
++
++ if (old_pkg)
++ remove_obsolete_maintainer_scripts(conf, pkg, old_pkg);
++ sprintf_alloc(&prefix, "%s.", pkg->name);
++ ret = pkg_extract_control_files_to_dir_with_prefix(pkg,
++ pkg->dest->info_dir,
++ prefix);
++ free(prefix);
++ return ret;
++}
++
++static int remove_disappeared(ipkg_conf_t *conf, pkg_t *pkg)
++{
++ /* DPKG_INCOMPATIBILITY:
++ This is a fairly sophisticated dpkg operation. Shall we
++ skip it? */
++
++ /* Any packages all of whose files have been overwritten during the
++ installation, and which aren't required for dependencies, are
++ considered to have been removed. For each such package
++ 1. disappearer's-postrm disappear overwriter overwriter-version
++ 2. The package's maintainer scripts are removed
++ 3. It is noted in the status database as being in a sane state,
++ namely not installed (any conffiles it may have are ignored,
++ rather than being removed by dpkg). Note that disappearing
++ packages do not have their prerm called, because dpkg doesn't
++ know in advance that the package is going to vanish.
++ */
++ return 0;
++}
++
++static int install_data_files(ipkg_conf_t *conf, pkg_t *pkg)
++{
++ int err;
++
++ /* ipkg takes a slightly different approach to data file backups
++ than dpkg. Rather than removing backups at this point, we
++ actually do the data file installation now. See comments in
++ check_data_file_clashes() for more details. */
++
++ ipkg_message(conf, IPKG_INFO,
++ " extracting data files to %s\n", pkg->dest->root_dir);
++ err = pkg_extract_data_files_to_dir(pkg, pkg->dest->root_dir);
++ if (err) {
++ return err;
++ }
++
++ /* XXX: BUG or FEATURE : We are actually loosing the Essential flag,
++ so we can't save ourself from removing important packages
++ At this point we (should) have extracted the .control file, so it
++ would be a good idea to reload the data in it, and set the Essential
++ state in *pkg. From now on the Essential is back in status file and
++ we can protect again.
++ We should operate this way:
++ fopen the file ( pkg->dest->root_dir/pkg->name.control )
++ check for "Essential" in it
++ set the value in pkg->essential.
++ This new routine could be useful also for every other flag
++ Pigi: 16/03/2004 */
++ set_flags_from_control(conf, pkg) ;
++
++ ipkg_message(conf, IPKG_DEBUG, " Calling pkg_write_filelist from %s\n", __FUNCTION__);
++ err = pkg_write_filelist(conf, pkg);
++ if (err)
++ return err;
++
++ /* XXX: FEATURE: ipkg should identify any files which existed
++ before installation and which were overwritten, (see
++ check_data_file_clashes()). What it must do is remove any such
++ files from the filelist of the old package which provided the
++ file. Otherwise, if the old package were removed at some point
++ it would break the new package. Removing the new package will
++ also break the old one, but this cannot be helped since the old
++ package's file has already been deleted. This is the importance
++ of check_data_file_clashes(), and only allowing ipkg to install
++ a clashing package with a user force. */
++
++ return 0;
++}
++
++static int resolve_conffiles(ipkg_conf_t *conf, pkg_t *pkg)
++{
++ conffile_list_elt_t *iter;
++ conffile_t *cf;
++ char *cf_backup;
++
++ char *md5sum;
++
++
++ if (conf->noaction) return 0;
++
++ for (iter = pkg->conffiles.head; iter; iter = iter->next) {
++ char *root_filename;
++ cf = iter->data;
++ root_filename = root_filename_alloc(conf, cf->name);
++
++ /* Might need to initialize the md5sum for each conffile */
++ if (cf->value == NULL) {
++ cf->value = file_md5sum_alloc(root_filename);
++ }
++
++ if (!file_exists(root_filename)) {
++ free(root_filename);
++ continue;
++ }
++
++ cf_backup = backup_filename_alloc(root_filename);
++
++
++ if (file_exists(cf_backup)) {
++ /* Let's compute md5 to test if files are changed */
++ md5sum = file_md5sum_alloc(cf_backup);
++ if (strcmp( cf->value,md5sum) != 0 ) {
++ if (conf->force_defaults
++ || user_prefers_old_conffile(cf->name, cf_backup) ) {
++ rename(cf_backup, root_filename);
++ }
++ }
++ unlink(cf_backup);
++ free(md5sum);
++ }
++
++ free(cf_backup);
++ free(root_filename);
++ }
++
++ return 0;
++}
++
++static int user_prefers_old_conffile(const char *file_name, const char *backup)
++{
++ char *response;
++ const char *short_file_name;
++
++ short_file_name = strrchr(file_name, '/');
++ if (short_file_name) {
++ short_file_name++;
++ } else {
++ short_file_name = file_name;
++ }
++
++ while (1) {
++ response = get_user_response(" Configuration file '%s'\n"
++ " ==> File on system created by you or by a script.\n"
++ " ==> File also in package provided by package maintainer.\n"
++ " What would you like to do about it ? Your options are:\n"
++ " Y or I : install the package maintainer's version\n"
++ " N or O : keep your currently-installed version\n"
++ " D : show the differences between the versions (if diff is installed)\n"
++ " The default action is to keep your current version.\n"
++ " *** %s (Y/I/N/O/D) [default=N] ? ", file_name, short_file_name);
++ if (strcmp(response, "y") == 0
++ || strcmp(response, "i") == 0
++ || strcmp(response, "yes") == 0) {
++ free(response);
++ return 0;
++ }
++
++ if (strcmp(response, "d") == 0) {
++ char *cmd;
++
++ free(response);
++ /* XXX: BUG rewrite to use exec or busybox's internal diff */
++ sprintf_alloc(&cmd, "diff -u %s %s", backup, file_name);
++ xsystem(cmd);
++ free(cmd);
++ printf(" [Press ENTER to continue]\n");
++ response = file_read_line_alloc(stdin);
++ free(response);
++ continue;
++ }
++
++ free(response);
++ return 1;
++ }
++}
++
++/* XXX: CLEANUP: I'd like to move all of the code for
++ creating/cleaning pkg->tmp_unpack_dir directly into pkg.c. (Then,
++ it would make sense to cleanup pkg->tmp_unpack_dir directly from
++ pkg_deinit for example). */
++static int cleanup_temporary_files(ipkg_conf_t *conf, pkg_t *pkg)
++{
++ DIR *tmp_dir;
++ struct dirent *dirent;
++ char *tmp_file;
++
++#ifdef IPKG_DEBUG_NO_TMP_CLEANUP
++#error
++ ipkg_message(conf, IPKG_DEBUG,
++ "%s: Not cleaning up %s since ipkg compiled with IPKG_DEBUG_NO_TMP_CLEANUP\n",
++ __FUNCTION__, pkg->tmp_unpack_dir);
++ return 0;
++#endif
++
++ if (pkg->tmp_unpack_dir && file_is_dir(pkg->tmp_unpack_dir)) {
++ tmp_dir = opendir(pkg->tmp_unpack_dir);
++ if (tmp_dir) {
++ while (1) {
++ dirent = readdir(tmp_dir);
++ if (dirent == NULL) {
++ break;
++ }
++ sprintf_alloc(&tmp_file, "%s/%s",
++ pkg->tmp_unpack_dir, dirent->d_name);
++ if (! file_is_dir(tmp_file)) {
++ unlink(tmp_file);
++ }
++ free(tmp_file);
++ }
++ closedir(tmp_dir);
++ rmdir(pkg->tmp_unpack_dir);
++ free(pkg->tmp_unpack_dir);
++ pkg->tmp_unpack_dir = NULL;
++ }
++ }
++
++ ipkg_message(conf, IPKG_INFO, "cleanup_temporary_files: pkg=%s local_filename=%s tmp_dir=%s\n",
++ pkg->name, pkg->local_filename, conf->tmp_dir);
++ if (pkg->local_filename && strncmp(pkg->local_filename, conf->tmp_dir, strlen(conf->tmp_dir)) == 0) {
++ unlink(pkg->local_filename);
++ free(pkg->local_filename);
++ pkg->local_filename = NULL;
++ }
++
++ return 0;
++}
++
++static char *backup_filename_alloc(const char *file_name)
++{
++ char *backup;
++
++ sprintf_alloc(&backup, "%s%s", file_name, IPKG_BACKUP_SUFFIX);
++
++ return backup;
++}
++
++int backup_make_backup(ipkg_conf_t *conf, const char *file_name)
++{
++ int err;
++ char *backup;
++
++ backup = backup_filename_alloc(file_name);
++ err = file_copy(file_name, backup);
++ if (err) {
++ ipkg_message(conf, IPKG_ERROR,
++ "%s: Failed to copy %s to %s\n",
++ __FUNCTION__, file_name, backup);
++ }
++
++ free(backup);
++
++ return err;
++}
++
++static int backup_exists_for(const char *file_name)
++{
++ int ret;
++ char *backup;
++
++ backup = backup_filename_alloc(file_name);
++
++ ret = file_exists(backup);
++
++ free(backup);
++
++ return ret;
++}
++
++static int backup_remove(const char *file_name)
++{
++ char *backup;
++
++ backup = backup_filename_alloc(file_name);
++ unlink(backup);
++ free(backup);
++
++ return 0;
++}
++
++
++
++#ifdef CONFIG_IPKG_PROCESS_ACTIONS
++
++int ipkg_remove_packages(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_remove)
++{
++ /* first, remove the packages that need removing */
++ for (i = 0 ; i < pkgs_to_remove->len; i++ ) {
++ pkg_t *pkg = pkgs_to_remove->pkgs[i];
++ err = ipkg_remove_pkg(conf, pkg,0);
++ if (err) return err;
++ }
++ return 0;
++}
++
++int ipkg_process_actions_sanity_check(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_remove, pkg_vec_t *pkgs_superseded, pkg_vec_t *pkgs_to_install)
++{
++ int i;
++ /* now one more pass checking on the ones that need to be installed */
++ for (i = 0 ; i < pkgs_to_install->len; i++ ) {
++ pkg_t *pkg = pkgs_to_install->pkgs[i];
++ if (pkg->dest == NULL)
++ pkg->dest = conf->default_dest;
++
++ pkg->state_want = SW_INSTALL;
++
++ /* Abhaya: conflicts check */
++ err = check_conflicts_for(conf, pkg);
++ if (err) { return err; }
++ }
++ return 0;
++}
++
++int ipkg_process_actions_unpack_packages(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_remove, pkg_vec_t *pkgs_to_install)
++{
++ int i;
++ /* now one more pass checking on the ones that need to be installed */
++ for (i = 0 ; i < pkgs_to_install->len; i++ ) {
++ pkg_t *pkg = pkgs_to_install->pkgs[i];
++
++ /* XXX: FEATURE: Need to really support Provides/Replaces: here at some point */
++ pkg_vec_t *replacees = pkg_vec_alloc();
++ pkg_get_installed_replacees(conf, pkg, replacees);
++
++ /* XXX: BUG: we really should treat replacement more like an upgrade
++ * Instead, we're going to remove the replacees
++ */
++ err = pkg_remove_installed_replacees(conf, replacees);
++ if (err) return err;
++ pkg->state_flag |= SF_REMOVED_REPLACEES;
++ }
++ return 0;
++}
++
++int ipkg_process_actions_unpack_packages(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_remove, pkg_vec_t *pkgs_to_install)
++{
++ int i;
++ /* now one more pass checking on the ones that need to be installed */
++ for (i = 0 ; i < pkgs_to_install->len; i++ ) {
++ pkg_t *pkg = pkgs_to_install->pkgs[i];
++ if (pkg->local_filename == NULL) {
++ err = ipkg_download_pkg(conf, pkg, conf->tmp_dir);
++ if (err) {
++ ipkg_message(conf, IPKG_ERROR,
++ "Failed to download %s. Perhaps you need to run 'ipkg update'?\n",
++ pkg->name);
++ return err;
++ }
++ }
++ if (pkg->tmp_unpack_dir == NULL) {
++ err = unpack_pkg_control_files(conf, pkg);
++ if (err) return err;
++ }
++ }
++ return 0;
++}
++
++int ipkg_process_actions_prerm(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_install)
++{
++ int i;
++ /* now one more pass checking on the ones that need to be installed */
++ for (i = 0 ; i < pkgs_to_install->len; i++ ) {
++ pkg_t *pkg = pkgs_to_install->pkgs[i];
++ pkg_t *old_pkg = pkg->old_pkg;
++
++ err = prerm_upgrade_old_pkg(conf, pkg, old_pkg);
++ if (err) return err;
++
++ err = prerm_deconfigure_conflictors(conf, pkg, replacees);
++ if (err) return err;
++
++ err = preinst_configure(conf, pkg, old_pkg);
++ if (err) return err;
++
++ err = backup_modified_conffiles(conf, pkg, old_pkg);
++ if (err) return err;
++
++ err = postrm_upgrade_old_pkg(conf, pkg, old_pkg);
++ if (err) return err;
++ }
++ return 0;
++}
++
++int ipkg_process_actions_install(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_install)
++{
++ int i;
++ /* now one more pass checking on the ones that need to be installed */
++ for (i = 0 ; i < pkgs_to_install->len; i++ ) {
++ pkg_t *pkg = pkgs_to_install->pkgs[i];
++ pkg_t *old_pkg = pkg->old_pkg;
++
++ if (old_pkg) {
++ old_pkg->state_want = SW_DEINSTALL;
++
++ if (old_pkg->state_flag & SF_NOPRUNE) {
++ ipkg_message(conf, IPKG_INFO,
++ " not removing obsolesced files because package marked noprune\n");
++ } else {
++ ipkg_message(conf, IPKG_INFO,
++ " removing obsolesced files\n");
++ remove_obsolesced_files(conf, pkg, old_pkg);
++ }
++ }
++
++ ipkg_message(conf, IPKG_INFO,
++ " installing maintainer scripts\n");
++ install_maintainer_scripts(conf, pkg, old_pkg);
++
++ /* the following just returns 0 */
++ remove_disappeared(conf, pkg);
++
++ ipkg_message(conf, IPKG_INFO,
++ " installing data files\n");
++ install_data_files(conf, pkg);
++
++ ipkg_message(conf, IPKG_INFO,
++ " resolving conf files\n");
++ resolve_conffiles(conf, pkg);
++
++ pkg->state_status = SS_UNPACKED;
++
++ if (old_pkg) {
++ old_pkg->state_status = SS_NOT_INSTALLED;
++ }
++
++ time(&pkg->installed_time);
++
++ ipkg_message(conf, IPKG_INFO,
++ " cleanup temp files\n");
++ cleanup_temporary_files(conf, pkg);
++
++ if (pkg->parent)
++ pkg->parent->state_status = pkg->state_status;
++ }
++ return 0;
++}
++
++int ipkg_process_actions_unwind_prerm(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_install)
++{
++ int i;
++ /* now one more pass checking on the ones that need to be installed */
++ for (i = 0 ; i < pkgs_to_install->len; i++ ) {
++ pkg_t *pkg = pkgs_to_install->pkgs[i];
++ pkg_t *old_pkg = pkg->old_pkg;
++
++ if (old_pkg) {
++ if (old_pkg->state_flags & SF_POSTRM_UPGRADE)
++ postrm_upgrade_old_pkg_unwind(conf, pkg, old_pkg);
++ if (old_pkg->state_flags & SF_CHECK_DATA_FILE_CLASHES)
++ check_data_file_clashes_unwind(conf, pkg, old_pkg);
++ if (old_pkg->state_flags & SF_BACKUP_MODIFIED_CONFFILES)
++ backup_modified_conffiles_unwind(conf, pkg, old_pkg);
++ if (old_pkg->state_flags & SF_PREINST_CONFIGURE)
++ preinst_configure_unwind(conf, pkg, old_pkg);
++ if (old_pkg->state_flags & SF_DECONFIGURE_CONFLICTORS)
++ prerm_deconfigure_conflictors_unwind(conf, pkg, replacees);
++ if (old_pkg->state_flags & SF_PRERM_UPGRADE)
++ prerm_upgrade_old_pkg_unwind(conf, pkg, old_pkg);
++
++ if (old_pkg->state_flags & SF_REMOVED_REPLACEES)
++ remove_installed_replacees_unwind(conf, pkg, old_pkg);
++
++ }
++ }
++ return 0;
++}
++
++/*
++ * Perform all the actions.
++ *
++ * pkgs_to_remove are packages marked for removal.
++ * pkgs_superseded are the old packages being replaced by upgrades.
++ *
++ * Assumes pkgs_to_install includes all dependences, recursively, sorted in installable order.
++ */
++int ipkg_process_actions(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_remove, pkg_vec_t *pkgs_superseded, pkg_vec_t *pkgs_to_install)
++{
++ int err;
++ int i;
++
++ err = ipkg_remove_packages(conf, pkgs_to_remove);
++ if (err) return err;
++
++ err = ipkg_process_actions_sanity_check(conf, pkgs_superseded, pkgs_to_install);
++ if (err) return err;
++
++ err = ipkg_process_actions_remove_replacees(conf, pkgs_to_install);
++ if (err) goto UNWIND;
++
++ /* @@@@ look at ipkg_install_pkg for handling replacements */
++ err = ipkg_process_actions_unpack_packages(conf, pkgs_to_install);
++ if (err) goto UNWIND;
++
++ /*
++ * Now that we have the packages unpacked, we can look for data
++ * file clashes. First, we mark the files from the superseded
++ * packages as obsolete. Then we scan the files in
++ * pkgs_to_install, and only complain about clashes with
++ * non-obsolete files.
++ */
++
++ err = ipkg_process_actions_check_data_file_clashes(conf, pkgs_superseded, pkgs_to_install);
++ if (err) goto UNWIND;
++
++ /* this was before checking data file clashes */
++ err = ipkg_process_actions_prerm(conf, pkgs_superseded, pkgs_to_install);
++ if (err) goto UNWIND;
++
++ /* point of no return: no unwinding after this */
++ err = ipkg_process_actions_install(conf, pkgs_to_install);
++ if (err) return err;
++
++ ipkg_message(conf, IPKG_INFO, "Done.\n");
++ return 0;
++
++ UNWIND:
++ ipkg_process_actions_unwind(conf, pkgs_to_install);
++
++ ipkg_message(conf, IPKG_INFO,
++ " cleanup temp files\n");
++ cleanup_temporary_files(conf, pkg);
++
++ ipkg_message(conf, IPKG_INFO,
++ "Failed.\n");
++ return err;
++}
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_install.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_install.h
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_install.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_install.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,35 @@
++/* ipkg_install.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef IPKG_INSTALL_H
++#define IPKG_INSTALL_H
++
++#include "pkg.h"
++#include "ipkg_conf.h"
++
++ipkg_error_t ipkg_install_by_name(ipkg_conf_t *conf, const char *pkg_name);
++ipkg_error_t ipkg_install_multi_by_name(ipkg_conf_t *conf, const char *pkg_name);
++int ipkg_install_from_file(ipkg_conf_t *conf, const char *filename);
++int ipkg_install_pkg(ipkg_conf_t *conf, pkg_t *pkg,int from_upgrading);
++int satisfy_dependencies_for(ipkg_conf_t *conf, pkg_t *pkg);
++
++int ipkg_satisfy_all_dependences(ipkg_conf_t *conf);
++
++int pkg_mark_dependencies_for_installation(ipkg_conf_t *conf, pkg_t *pkg_name, pkg_vec_t *pkgs_needed);
++int name_mark_dependencies_for_installation(ipkg_conf_t *conf, const char *pkg_name, pkg_vec_t *pkgs_needed);
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_message.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_message.c
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_message.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_message.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,61 @@
++/* ipkg_message.c - the itsy package management system
++
++ Copyright (C) 2003 Daniele Nicolodi <daniele@grinta.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, 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 "ipkg.h"
++#include "ipkg_conf.h"
++#include "ipkg_message.h"
++
++#ifndef IPKG_LIB
++
++void
++ipkg_message (ipkg_conf_t * conf, message_level_t level, char *fmt, ...)
++{
++ va_list ap;
++
++ if (conf && (conf->verbosity < level))
++ {
++ return;
++ }
++ else
++ {
++
++ va_start (ap, fmt);
++ vprintf (fmt, ap);
++ va_end (ap);
++ }
++}
++
++#else
++
++#include "libipkg.h"
++
++//#define ipkg_message(conf, level, fmt, arg...) ipkg_cb_message(conf, level, fmt, ## arg)
++
++void
++ipkg_message (ipkg_conf_t * conf, message_level_t level, char *fmt, ...)
++{
++ va_list ap;
++ char ts[256];
++
++ if (ipkg_cb_message)
++ {
++ va_start (ap, fmt);
++ vsnprintf (ts,256,fmt, ap);
++ va_end (ap);
++ ipkg_cb_message(conf,level,ts);
++ }
++}
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_message.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_message.h
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_message.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_message.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,32 @@
++/* ipkg_message.h - the itsy package management system
++
++ Copyright (C) 2003 Daniele Nicolodi <daniele@grinta.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, 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 _IPKG_MESSAGE_H_
++#define _IPKG_MESSAGE_H_
++
++#include "ipkg.h"
++#include "ipkg_conf.h"
++
++typedef enum {
++ IPKG_ERROR, /* error conditions */
++ IPKG_NOTICE, /* normal but significant condition */
++ IPKG_INFO, /* informational message */
++ IPKG_DEBUG, /* debug level message */
++ IPKG_DEBUG2, /* more debug level message */
++} message_level_t;
++
++extern void ipkg_message(ipkg_conf_t *conf, message_level_t level, char *fmt, ...);
++
++#endif /* _IPKG_MESSAGE_H_ */
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_remove.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_remove.c
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_remove.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_remove.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,383 @@
++/* ipkg_remove.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++#include "ipkg_message.h"
++
++#include <glob.h>
++
++#include "ipkg_remove.h"
++
++#include "file_util.h"
++#include "sprintf_alloc.h"
++#include "str_util.h"
++
++#include "ipkg_cmd.h"
++
++/*
++ * Returns number of the number of packages depending on the packages provided by this package.
++ * Every package implicitly provides itself.
++ */
++int pkg_has_installed_dependents(ipkg_conf_t *conf, abstract_pkg_t *parent_apkg, pkg_t *pkg, abstract_pkg_t *** pdependents)
++{
++ int nprovides = pkg->provides_count;
++ abstract_pkg_t **provides = pkg->provides;
++ int n_installed_dependents = 0;
++ int i;
++ for (i = 0; i <= nprovides; i++) {
++ abstract_pkg_t *providee = provides[i];
++ abstract_pkg_t **dependers = providee->depended_upon_by;
++ abstract_pkg_t *dep_ab_pkg;
++ if (dependers == NULL)
++ continue;
++ while ((dep_ab_pkg = *dependers++) != NULL) {
++ if (dep_ab_pkg->state_status == SS_INSTALLED){
++ n_installed_dependents++;
++ }
++ }
++
++ }
++ /* if caller requested the set of installed dependents */
++ if (pdependents) {
++ int p = 0;
++ abstract_pkg_t **dependents = (abstract_pkg_t **)malloc((n_installed_dependents+1)*sizeof(abstract_pkg_t *));
++
++ if ( dependents == NULL ){
++ fprintf(stderr,"%s Unable to allocate memory. REPORT THIS BUG IN BUGZILLA PLEASE\n", __FUNCTION__);
++ return -1;
++ }
++
++ *pdependents = dependents;
++ for (i = 0; i <= nprovides; i++) {
++ abstract_pkg_t *providee = provides[i];
++ abstract_pkg_t **dependers = providee->depended_upon_by;
++ abstract_pkg_t *dep_ab_pkg;
++ if (dependers == NULL)
++ continue;
++ while ((dep_ab_pkg = *dependers++) != NULL) {
++ if (dep_ab_pkg->state_status == SS_INSTALLED && !(dep_ab_pkg->state_flag & SF_MARKED)) {
++ dependents[p++] = dep_ab_pkg;
++ dep_ab_pkg->state_flag |= SF_MARKED;
++ }
++ }
++ }
++ dependents[p] = NULL;
++ /* now clear the marks */
++ for (i = 0; i < p; i++) {
++ abstract_pkg_t *dep_ab_pkg = dependents[i];
++ dep_ab_pkg->state_flag &= ~SF_MARKED;
++ }
++ }
++ return n_installed_dependents;
++}
++
++int ipkg_remove_dependent_pkgs (ipkg_conf_t *conf, pkg_t *pkg, abstract_pkg_t **dependents)
++{
++ int i;
++ int a;
++ int count;
++ pkg_vec_t *dependent_pkgs = pkg_vec_alloc();
++ abstract_pkg_t * ab_pkg;
++
++ if((ab_pkg = pkg->parent) == NULL){
++ fprintf(stderr, "%s: unable to get dependent pkgs. pkg %s isn't in hash table\n",
++ __FUNCTION__, pkg->name);
++ return 0;
++ }
++
++ if (dependents == NULL)
++ return 0;
++
++ // here i am using the dependencies_checked
++ if (ab_pkg->dependencies_checked == 2) // variable to make out whether this package
++ return 0; // has already been encountered in the process
++ // of marking packages for removal - Karthik
++ ab_pkg->dependencies_checked = 2;
++
++ i = 0;
++ count = 1;
++ while (dependents [i] != NULL) {
++ abstract_pkg_t *dep_ab_pkg = dependents[i];
++
++ if (dep_ab_pkg->dependencies_checked == 2){
++ i++;
++ continue;
++ }
++ if (dep_ab_pkg->state_status == SS_INSTALLED) {
++ for (a = 0; a < dep_ab_pkg->pkgs->len; a++) {
++ pkg_t *dep_pkg = dep_ab_pkg->pkgs->pkgs[a];
++ if (dep_pkg->state_status == SS_INSTALLED) {
++ pkg_vec_insert(dependent_pkgs, dep_pkg);
++ count++;
++ }
++ }
++ }
++ i++;
++ /* 1 - to keep track of visited ab_pkgs when checking for possiblility of a broken removal of pkgs.
++ * 2 - to keep track of pkgs whose deps have been checked alrdy - Karthik */
++ }
++
++ if (count == 1)
++ return 0;
++
++
++ for (i = 0; i < dependent_pkgs->len; i++) {
++ int err = ipkg_remove_pkg(conf, dependent_pkgs->pkgs[i],0);
++ if (err)
++ return err;
++ }
++ return 0;
++}
++
++static int user_prefers_removing_dependents(ipkg_conf_t *conf, abstract_pkg_t *abpkg, pkg_t *pkg, abstract_pkg_t **dependents)
++{
++ abstract_pkg_t *dep_ab_pkg;
++ ipkg_message(conf, IPKG_ERROR, "Package %s is depended upon by packages:\n", pkg->name);
++ while ((dep_ab_pkg = *dependents++) != NULL) {
++ if (dep_ab_pkg->state_status == SS_INSTALLED)
++ ipkg_message(conf, IPKG_ERROR, "\t%s\n", dep_ab_pkg->name);
++ }
++ ipkg_message(conf, IPKG_ERROR, "These might cease to work if package %s is removed.\n\n", pkg->name);
++ ipkg_message(conf, IPKG_ERROR, "");
++ ipkg_message(conf, IPKG_ERROR, "You can force removal of this package with -force-depends.\n");
++ ipkg_message(conf, IPKG_ERROR, "You can force removal of this package and its dependents\n");
++ ipkg_message(conf, IPKG_ERROR, "with -force-removal-of-dependent-packages or -recursive\n");
++ ipkg_message(conf, IPKG_ERROR, "or by setting option force_removal_of_dependent_packages\n");
++ ipkg_message(conf, IPKG_ERROR, "in ipkg.conf.\n");
++ return 0;
++}
++
++int ipkg_remove_pkg(ipkg_conf_t *conf, pkg_t *pkg,int message)
++{
++/* Actually, when "message == 1" I have been called from an upgrade, and not from a normal remove
++ thus I wan't check for essential, as I'm upgrading.
++ I hope it won't break anything :)
++*/
++ int err;
++ abstract_pkg_t *parent_pkg = NULL;
++
++ if (pkg->essential && !message) {
++ if (conf->force_removal_of_essential_packages) {
++ fprintf(stderr, "WARNING: Removing essential package %s under your coercion.\n"
++ "\tIf your system breaks, you get to keep both pieces\n",
++ pkg->name);
++ } else {
++ fprintf(stderr, "ERROR: Refusing to remove essential package %s.\n"
++ "\tRemoving an essential package may lead to an unusable system, but if\n"
++ "\tyou enjoy that kind of pain, you can force ipkg to proceed against\n"
++ "\tits will with the option: -force-removal-of-essential-packages\n",
++ pkg->name);
++ return IPKG_PKG_IS_ESSENTIAL;
++ }
++ }
++
++ if ((parent_pkg = pkg->parent) == NULL)
++ return 0;
++
++ /* only attempt to remove dependent installed packages if
++ * force_depends is not specified or the package is being
++ * replaced.
++ */
++ if (!conf->force_depends
++ && !(pkg->state_flag & SF_REPLACE)) {
++ abstract_pkg_t **dependents;
++ int has_installed_dependents =
++ pkg_has_installed_dependents(conf, parent_pkg, pkg, &dependents);
++
++ if (has_installed_dependents) {
++ /*
++ * if this package is depended up by others, then either we should
++ * not remove it or we should remove it and all of its dependents
++ */
++
++ if (!conf->force_removal_of_dependent_packages
++ && !user_prefers_removing_dependents(conf, parent_pkg, pkg, dependents)) {
++ return IPKG_PKG_HAS_DEPENDENTS;
++ }
++
++ /* remove packages depending on this package - Karthik */
++ err = ipkg_remove_dependent_pkgs (conf, pkg, dependents);
++ free(dependents);
++ if (err) return err;
++ }
++ }
++
++ if ( message==0 ){
++ printf("Removing package %s from %s...\n", pkg->name, pkg->dest->name);
++ fflush(stdout);
++ }
++ pkg->state_flag |= SF_FILELIST_CHANGED;
++
++ pkg->state_want = SW_DEINSTALL;
++ ipkg_state_changed++;
++
++ pkg_run_script(conf, pkg, "prerm", "remove");
++
++ /* DPKG_INCOMPATIBILITY: dpkg is slightly different here. It
++ maintains an empty filelist rather than deleting it. That seems
++ like a big pain, and I don't see that that should make a big
++ difference, but for anyone who wants tighter compatibility,
++ feel free to fix this. */
++ remove_data_files_and_list(conf, pkg);
++
++ pkg_run_script(conf, pkg, "postrm", "remove");
++
++ remove_maintainer_scripts_except_postrm(conf, pkg);
++
++ /* Aman Gupta - Since ipkg is made for handheld devices with limited
++ * space, it doesn't make sense to leave extra configurations, files,
++ * and maintainer scripts left around. So, we make remove like purge,
++ * and take out all the crap :) */
++
++ remove_postrm(conf, pkg);
++ pkg->state_status = SS_NOT_INSTALLED;
++
++ if (parent_pkg)
++ parent_pkg->state_status = SS_NOT_INSTALLED;
++
++ return 0;
++}
++
++int ipkg_purge_pkg(ipkg_conf_t *conf, pkg_t *pkg)
++{
++ ipkg_remove_pkg(conf, pkg,0);
++ return 0;
++}
++
++int remove_data_files_and_list(ipkg_conf_t *conf, pkg_t *pkg)
++{
++ str_list_t installed_dirs;
++ str_list_t *installed_files;
++ str_list_elt_t *iter;
++ char *file_name;
++ conffile_t *conffile;
++ int removed_a_dir;
++ pkg_t *owner;
++
++ str_list_init(&installed_dirs);
++ installed_files = pkg_get_installed_files(pkg);
++
++ for (iter = installed_files->head; iter; iter = iter->next) {
++ file_name = iter->data;
++
++ if (file_is_dir(file_name)) {
++ str_list_append(&installed_dirs, strdup(file_name));
++ continue;
++ }
++
++ conffile = pkg_get_conffile(pkg, file_name);
++ if (conffile) {
++ /* XXX: QUESTION: Is this right? I figure we only need to
++ save the conffile if it has been modified. Is that what
++ dpkg does? Or does dpkg preserve all conffiles? If so,
++ this seems like a better thing to do to conserve
++ space. */
++ if (conffile_has_been_modified(conf, conffile)) {
++ printf(" not deleting modified conffile %s\n", file_name);
++ fflush(stdout);
++ continue;
++ }
++ }
++
++ ipkg_message(conf, IPKG_INFO, " deleting %s (noaction=%d)\n", file_name, conf->noaction);
++ if (!conf->noaction)
++ unlink(file_name);
++ }
++
++ if (!conf->noaction) {
++ do {
++ removed_a_dir = 0;
++ for (iter = installed_dirs.head; iter; iter = iter->next) {
++ file_name = iter->data;
++
++ if (rmdir(file_name) == 0) {
++ ipkg_message(conf, IPKG_INFO, " deleting %s\n", file_name);
++ removed_a_dir = 1;
++ str_list_remove(&installed_dirs, &iter);
++ }
++ }
++ } while (removed_a_dir);
++ }
++
++ pkg_free_installed_files(pkg);
++ /* We have to remove the file list now, so that
++ find_pkg_owning_file does not always just report this package */
++ pkg_remove_installed_files_list(conf, pkg);
++
++ /* Don't print warning for dirs that are provided by other packages */
++ for (iter = installed_dirs.head; iter; iter = iter->next) {
++ file_name = iter->data;
++
++ owner = file_hash_get_file_owner(conf, file_name);
++ if (owner) {
++ free(iter->data);
++ iter->data = NULL;
++ str_list_remove(&installed_dirs, &iter);
++ }
++ }
++
++ /* cleanup */
++ for (iter = installed_dirs.head; iter; iter = iter->next) {
++ free(iter->data);
++ iter->data = NULL;
++ }
++ str_list_deinit(&installed_dirs);
++
++ return 0;
++}
++
++int remove_maintainer_scripts_except_postrm(ipkg_conf_t *conf, pkg_t *pkg)
++{
++ int i, err;
++ char *globpattern;
++ glob_t globbuf;
++
++ if (conf->noaction) return 0;
++
++ sprintf_alloc(&globpattern, "%s/%s.*",
++ pkg->dest->info_dir, pkg->name);
++ err = glob(globpattern, 0, NULL, &globbuf);
++ free(globpattern);
++ if (err) {
++ return 0;
++ }
++
++ for (i = 0; i < globbuf.gl_pathc; i++) {
++ if (str_ends_with(globbuf.gl_pathv[i], ".postrm")) {
++ continue;
++ }
++ ipkg_message(conf, IPKG_INFO, " deleting %s\n", globbuf.gl_pathv[i]);
++ unlink(globbuf.gl_pathv[i]);
++ }
++ globfree(&globbuf);
++
++ return 0;
++}
++
++int remove_postrm(ipkg_conf_t *conf, pkg_t *pkg)
++{
++ char *postrm_file_name;
++
++ if (conf->noaction) return 0;
++
++ sprintf_alloc(&postrm_file_name, "%s/%s.postrm",
++ pkg->dest->info_dir, pkg->name);
++ unlink(postrm_file_name);
++ free(postrm_file_name);
++
++ return 0;
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_remove.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_remove.h
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_remove.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_remove.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,33 @@
++/* ipkg_remove.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef IPKG_REMOVE_H
++#define IPKG_REMOVE_H
++
++#include "pkg.h"
++#include "ipkg_conf.h"
++
++int ipkg_remove_pkg(ipkg_conf_t *conf, pkg_t *pkg,int message);
++int ipkg_purge_pkg(ipkg_conf_t *conf, pkg_t *pkg);
++int possible_broken_removal_of_packages (ipkg_conf_t *conf, pkg_t *pkg);
++int pkg_has_installed_dependents(ipkg_conf_t *conf, abstract_pkg_t *parent_apkg, pkg_t *pkg, abstract_pkg_t *** pdependents);
++int remove_data_files_and_list(ipkg_conf_t *conf, pkg_t *pkg);
++int remove_maintainer_scripts_except_postrm (ipkg_conf_t *conf, pkg_t *pkg);
++int remove_postrm (ipkg_conf_t *conf, pkg_t *pkg);
++
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_upgrade.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_upgrade.c
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_upgrade.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_upgrade.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,77 @@
++/* ipkg_upgrade.c - the itsy package management system
++
++ Carl D. Worth
++ Copyright (C) 2001 University of Southern California
++
++ Copyright (C) 2003 Daniele Nicolodi <daniele@grinta.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, 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 "ipkg.h"
++#include "ipkg_install.h"
++#include "ipkg_message.h"
++
++int ipkg_upgrade_pkg(ipkg_conf_t *conf, pkg_t *old)
++{
++ pkg_t *new;
++ int cmp;
++ char *old_version, *new_version;
++
++ if (old->state_flag & SF_HOLD) {
++ ipkg_message(conf, IPKG_NOTICE,
++ "Not upgrading package %s which is marked "
++ "hold (flags=%#x)\n", old->name, old->state_flag);
++ return 0;
++ }
++
++ new = pkg_hash_fetch_best_installation_candidate_by_name(conf, old->name);
++ if (new == NULL) {
++ old_version = pkg_version_str_alloc(old);
++ ipkg_message(conf, IPKG_NOTICE,
++ "Assuming locally installed package %s (%s) "
++ "is up to date.\n", old->name, old_version);
++ free(old_version);
++ return 0;
++ }
++
++ old_version = pkg_version_str_alloc(old);
++ new_version = pkg_version_str_alloc(new);
++
++ cmp = pkg_compare_versions(old, new);
++ ipkg_message(conf, IPKG_DEBUG,
++ "comparing visible versions of pkg %s:"
++ "\n\t%s is installed "
++ "\n\t%s is available "
++ "\n\t%d was comparison result\n",
++ old->name, old_version, new_version, cmp);
++ if (cmp == 0) {
++ ipkg_message(conf, IPKG_INFO,
++ "Package %s (%s) installed in %s is up to date.\n",
++ old->name, old_version, old->dest->name);
++ free(old_version);
++ free(new_version);
++ return 0;
++ } else if (cmp > 0) {
++ ipkg_message(conf, IPKG_NOTICE,
++ "Not downgrading package %s on %s from %s to %s.\n",
++ old->name, old->dest->name, old_version, new_version);
++ free(old_version);
++ free(new_version);
++ return 0;
++ } else if (cmp < 0) {
++ new->dest = old->dest;
++ old->state_want = SW_DEINSTALL;
++ }
++
++ new->state_flag |= SF_USER;
++ return ipkg_install_pkg(conf, new,1);
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_upgrade.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_upgrade.h
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_upgrade.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_upgrade.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,18 @@
++/* ipkg_upgrade.c - the itsy package management system
++
++ Copyright (C) 2003 Daniele Nicolodi <daniele@grinta.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, 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 "ipkg.h"
++
++int ipkg_upgrade_pkg(ipkg_conf_t *conf, pkg_t *old);
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_utils.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_utils.c
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_utils.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_utils.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,181 @@
++/* ipkg_utils.c - the itsy package management system
++
++ Steven M. Ayer
++
++ Copyright (C) 2002 Compaq Computer Corporation
++
++ 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.
++*/
++
++#include "ipkg.h"
++#include <errno.h>
++#include <ctype.h>
++#include <sys/vfs.h>
++
++#include "ipkg_utils.h"
++#include "pkg.h"
++#include "pkg_hash.h"
++
++struct errlist* error_list;
++
++int get_available_blocks(char * filesystem)
++{
++ struct statfs sfs;
++
++ if(statfs(filesystem, &sfs)){
++ fprintf(stderr, "bad statfs\n");
++ return 0;
++ }
++ /* fprintf(stderr, "reported fs type %x\n", sfs.f_type); */
++ return ((sfs.f_bavail * sfs.f_bsize) / 1024);
++}
++
++char **read_raw_pkgs_from_file(const char *file_name)
++{
++ FILE *fp;
++ char **ret;
++
++ if(!(fp = fopen(file_name, "r"))){
++ fprintf(stderr, "can't get %s open for read\n", file_name);
++ return NULL;
++ }
++
++ ret = read_raw_pkgs_from_stream(fp);
++
++ fclose(fp);
++
++ return ret;
++}
++
++char **read_raw_pkgs_from_stream(FILE *fp)
++{
++ char **raw = NULL, *buf, *scout;
++ int count = 0;
++ size_t size = 512;
++
++ buf = malloc (size);
++
++ while (fgets(buf, size, fp)) {
++ while (strlen (buf) == (size - 1)
++ && buf[size-2] != '\n') {
++ size_t o = size - 1;
++ size *= 2;
++ buf = realloc (buf, size);
++ if (fgets (buf + o, size - o, fp) == NULL)
++ break;
++ }
++
++ if(!(count % 50))
++ raw = realloc(raw, (count + 50) * sizeof(char *));
++
++ if((scout = strchr(buf, '\n')))
++ *scout = '\0';
++
++ raw[count++] = strdup(buf);
++ }
++
++ raw = realloc(raw, (count + 1) * sizeof(char *));
++ raw[count] = NULL;
++
++ free (buf);
++
++ return raw;
++}
++
++/* something to remove whitespace, a hash pooper */
++char *trim_alloc(char *line)
++{
++ char *new;
++ char *dest, *src, *end;
++
++ new = malloc(strlen(line) + 1);
++ if ( new == NULL ){
++ fprintf(stderr,"%s: Unable to allocate memory\n",__FUNCTION__);
++ return NULL;
++ }
++ dest = new, src = line, end = line + (strlen(line) - 1);
++
++ /* remove it from the front */
++ while(src &&
++ isspace(*src) &&
++ *src)
++ src++;
++ /* and now from the back */
++ while((end > src) &&
++ isspace(*end))
++ end--;
++ end++;
++ *end = '\0';
++ strcpy(new, src);
++ /* this does from the first space
++ * blasting away any versions stuff in depends
++ while(src &&
++ !isspace(*src) &&
++ *src)
++ *dest++ = *src++;
++ *dest = '\0';
++ */
++
++ return new;
++}
++
++int line_is_blank(const char *line)
++{
++ const char *s;
++
++ for (s = line; *s; s++) {
++ if (!isspace(*s))
++ return 0;
++ }
++ return 1;
++}
++
++void push_error_list(struct errlist ** errors, char * msg){
++ struct errlist *err_lst_tmp;
++
++
++ err_lst_tmp = malloc ( sizeof (err_lst_tmp) );
++ err_lst_tmp->errmsg=strdup(msg) ;
++ err_lst_tmp->next = *errors;
++ *errors = err_lst_tmp;
++}
++
++
++void reverse_error_list(struct errlist **errors){
++ struct errlist *result=NULL;
++ struct errlist *current= *errors;
++ struct errlist *next;
++
++ while ( current != NULL ) {
++ next = current->next;
++ current->next=result;
++ result=current;
++ current=next;
++ }
++ *errors=result;
++
++}
++
++
++void free_error_list(struct errlist **errors){
++ struct errlist *current = *errors;
++
++ while (current != NULL) {
++ free(current->errmsg);
++ current = (*errors)->next;
++ free(*errors);
++ *errors = current;
++ }
++
++
++}
++
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/ipkg_utils.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_utils.h
+--- busybox-1.2.0-orig/archival/libipkg/ipkg_utils.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/ipkg_utils.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,29 @@
++/* ipkg_utils.h - the itsy package management system
++
++ Steven M. Ayer
++
++ Copyright (C) 2002 Compaq Computer Corporation
++
++ 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.
++*/
++
++#ifndef IPKG_UTILS_H
++#define IPKG_UTILS_H
++
++#include "pkg.h"
++
++int get_available_blocks(char * filesystem);
++char **read_raw_pkgs_from_file(const char *file_name);
++char **read_raw_pkgs_from_stream(FILE *fp);
++char *trim_alloc(char * line);
++int line_is_blank(const char *line);
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/libipkg.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/libipkg.c
+--- busybox-1.2.0-orig/archival/libipkg/libipkg.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/libipkg.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,527 @@
++/* ipkglib.c - the itsy package management system
++
++ Florina Boor
++
++ Copyright (C) 2003 kernel concepts
++
++ 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.
++*/
++
++#ifdef IPKG_LIB
++
++#include "ipkg.h"
++#include "ipkg_includes.h"
++#include "libipkg.h"
++
++#include "args.h"
++#include "ipkg_conf.h"
++#include "ipkg_cmd.h"
++#include "file_util.h"
++
++
++
++ipkg_message_callback ipkg_cb_message = NULL;
++ipkg_response_callback ipkg_cb_response = NULL;
++ipkg_status_callback ipkg_cb_status = NULL;
++ipkg_list_callback ipkg_cb_list = NULL;
++
++
++int
++ipkg_init (ipkg_message_callback mcall,
++ ipkg_response_callback rcall,
++ args_t * args)
++{
++ ipkg_cb_message = mcall;
++ ipkg_cb_response = rcall;
++
++ args_init (args);
++
++ return 0;
++}
++
++
++int
++ipkg_deinit (args_t * args)
++{
++ args_deinit (args);
++ ipkg_cb_message = NULL;
++ ipkg_cb_response = NULL;
++
++ /* place other cleanup stuff here */
++
++ return 0;
++}
++
++
++int
++ipkg_packages_list(args_t *args,
++ const char *packages,
++ ipkg_list_callback cblist,
++ void *userdata)
++{
++ ipkg_cmd_t *cmd;
++ ipkg_conf_t ipkg_conf;
++ int err;
++
++ err = ipkg_conf_init (&ipkg_conf, args);
++ if (err)
++ {
++ return err;
++ }
++
++ ipkg_cb_list = cblist;
++ /* we need to do this because of static declarations,
++ * maybe a good idea to change */
++ cmd = ipkg_cmd_find ("list");
++ if (packages)
++ err = ipkg_cmd_exec (cmd, &ipkg_conf, 1, &packages, userdata);
++ else
++ err = ipkg_cmd_exec (cmd, &ipkg_conf, 0, NULL, userdata);
++ ipkg_cb_list = NULL;
++ ipkg_conf_deinit (&ipkg_conf);
++ return (err);
++}
++
++
++int
++ipkg_packages_status(args_t *args,
++ const char *packages,
++ ipkg_status_callback cbstatus,
++ void *userdata)
++{
++ ipkg_cmd_t *cmd;
++ ipkg_conf_t ipkg_conf;
++ int err;
++
++ err = ipkg_conf_init (&ipkg_conf, args);
++ if (err)
++ {
++ return err;
++ }
++
++ ipkg_cb_status = cbstatus;
++
++ /* we need to do this because of static declarations,
++ * maybe a good idea to change */
++ cmd = ipkg_cmd_find ("status");
++ if (packages)
++ err = ipkg_cmd_exec (cmd, &ipkg_conf, 1, &packages, userdata);
++ else
++ err = ipkg_cmd_exec (cmd, &ipkg_conf, 0, NULL, userdata);
++
++ ipkg_cb_status = NULL;
++ ipkg_conf_deinit (&ipkg_conf);
++ return (err);
++}
++
++
++int
++ipkg_packages_info(args_t *args,
++ const char *packages,
++ ipkg_status_callback cbstatus,
++ void *userdata)
++{
++ ipkg_cmd_t *cmd;
++ ipkg_conf_t ipkg_conf;
++ int err;
++
++ err = ipkg_conf_init (&ipkg_conf, args);
++ if (err)
++ {
++ return err;
++ }
++
++ ipkg_cb_status = cbstatus;
++
++ /* we need to do this because of static declarations,
++ * maybe a good idea to change */
++ cmd = ipkg_cmd_find ("info");
++ if (packages)
++ err = ipkg_cmd_exec (cmd, &ipkg_conf, 1, &packages, userdata);
++ else
++ err = ipkg_cmd_exec (cmd, &ipkg_conf, 0, NULL, userdata);
++
++ ipkg_cb_status = NULL;
++ ipkg_conf_deinit (&ipkg_conf);
++ return (err);
++}
++
++
++int
++ipkg_packages_install (args_t * args, const char *name)
++{
++ ipkg_cmd_t *cmd;
++ ipkg_conf_t ipkg_conf;
++ int err;
++
++ /* this error should be handled in application */
++ if (!name || !strlen (name))
++ return (-1);
++
++ err = ipkg_conf_init (&ipkg_conf, args);
++ if (err)
++ {
++ return err;
++ }
++
++ /* we need to do this because of static declarations,
++ * maybe a good idea to change */
++ cmd = ipkg_cmd_find ("install");
++ err = ipkg_cmd_exec (cmd, &ipkg_conf, 1, &name, NULL);
++
++ ipkg_conf_deinit(&ipkg_conf);
++ return (err);
++}
++
++
++int
++ipkg_packages_remove(args_t *args, const char *name, int purge)
++{
++ ipkg_cmd_t *cmd;
++ ipkg_conf_t ipkg_conf;
++ int err;
++
++ /* this error should be handled in application */
++ if (!name || !strlen (name))
++ return (-1);
++
++ err = ipkg_conf_init (&ipkg_conf, args);
++ if (err)
++ {
++ return err;
++ }
++
++ /* we need to do this because of static declarations,
++ * maybe a good idea to change */
++ if (purge)
++ cmd = ipkg_cmd_find ("purge");
++ else
++ cmd = ipkg_cmd_find ("remove");
++
++ err = ipkg_cmd_exec (cmd, &ipkg_conf, 1, &name, NULL);
++
++ ipkg_conf_deinit(&ipkg_conf);
++ return (err);
++}
++
++
++int
++ipkg_lists_update(args_t *args)
++{
++ ipkg_cmd_t *cmd;
++ ipkg_conf_t ipkg_conf;
++ int err;
++
++ err = ipkg_conf_init (&ipkg_conf, args);
++ if (err)
++ {
++ return err;
++ }
++
++ /* we need to do this because of static declarations,
++ * maybe a good idea to change */
++ cmd = ipkg_cmd_find ("update");
++
++ err = ipkg_cmd_exec (cmd, &ipkg_conf, 0, NULL, NULL);
++
++ ipkg_conf_deinit(&ipkg_conf);
++ return (err);
++}
++
++
++int
++ipkg_packages_upgrade(args_t *args)
++{
++ ipkg_cmd_t *cmd;
++ ipkg_conf_t ipkg_conf;
++ int err;
++
++ err = ipkg_conf_init (&ipkg_conf, args);
++ if (err)
++ {
++ return err;
++ }
++
++ /* we need to do this because of static declarations,
++ * maybe a good idea to change */
++ cmd = ipkg_cmd_find ("upgrade");
++
++ err = ipkg_cmd_exec (cmd, &ipkg_conf, 0, NULL, NULL);
++
++ ipkg_conf_deinit(&ipkg_conf);
++ return (err);
++}
++
++
++int
++ipkg_packages_download (args_t * args, const char *name)
++{
++ ipkg_cmd_t *cmd;
++ ipkg_conf_t ipkg_conf;
++ int err;
++
++ /* this error should be handled in application */
++ if (!name || !strlen (name))
++ return (-1);
++
++ err = ipkg_conf_init (&ipkg_conf, args);
++ if (err)
++ {
++ return err;
++ }
++
++ /* we need to do this because of static declarations,
++ * maybe a good idea to change */
++ cmd = ipkg_cmd_find ("download");
++ err = ipkg_cmd_exec (cmd, &ipkg_conf, 1, &name, NULL);
++
++ ipkg_conf_deinit(&ipkg_conf);
++ return (err);
++}
++
++
++int
++ipkg_package_files(args_t *args,
++ const char *name,
++ ipkg_list_callback cblist,
++ void *userdata)
++{
++ ipkg_cmd_t *cmd;
++ ipkg_conf_t ipkg_conf;
++ int err;
++
++ /* this error should be handled in application */
++ if (!name || !strlen (name))
++ return (-1);
++
++ err = ipkg_conf_init (&ipkg_conf, args);
++ if (err)
++ {
++ return err;
++ }
++
++ ipkg_cb_list = cblist;
++
++ /* we need to do this because of static declarations,
++ * maybe a good idea to change */
++ cmd = ipkg_cmd_find ("files");
++
++ err = ipkg_cmd_exec (cmd, &ipkg_conf, 1, &name, userdata);
++
++ ipkg_cb_list = NULL;
++ ipkg_conf_deinit(&ipkg_conf);
++ return (err);
++}
++
++
++int
++ipkg_file_search(args_t *args,
++ const char *file,
++ ipkg_list_callback cblist,
++ void *userdata)
++{
++ ipkg_cmd_t *cmd;
++ ipkg_conf_t ipkg_conf;
++ int err;
++
++ /* this error should be handled in application */
++ if (!file || !strlen (file))
++ return (-1);
++
++ err = ipkg_conf_init (&ipkg_conf, args);
++ if (err)
++ {
++ return err;
++ }
++
++ ipkg_cb_list = cblist;
++
++ /* we need to do this because of static declarations,
++ * maybe a good idea to change */
++ cmd = ipkg_cmd_find ("search");
++ err = ipkg_cmd_exec (cmd, &ipkg_conf, 1, &file, userdata);
++
++ ipkg_cb_list = NULL;
++ ipkg_conf_deinit(&ipkg_conf);
++ return(err);
++}
++
++
++int
++ipkg_file_what(args_t *args, const char *file, const char* command)
++{
++ ipkg_cmd_t *cmd;
++ ipkg_conf_t ipkg_conf;
++ int err;
++
++ /* this error should be handled in application */
++ if (!file || !strlen (file))
++ return (-1);
++
++ err = ipkg_conf_init (&ipkg_conf, args);
++ if (err)
++ {
++ return err;
++ }
++
++ /* we need to do this because of static declarations,
++ * maybe a good idea to change */
++ cmd = ipkg_cmd_find (command);
++ err = ipkg_cmd_exec (cmd, &ipkg_conf, 1, &file, NULL);
++
++ ipkg_conf_deinit(&ipkg_conf);
++ return(err);
++}
++
++#define ipkg_package_whatdepends(args,file) ipkg_file_what(args,file,"whatdepends")
++#define ipkg_package_whatrecommends(args, file) ipkg_file_what(args,file,"whatrecommends")
++#define ipkg_package_whatprovides(args, file) ipkg_file_what(args,file,"whatprovides")
++#define ipkg_package_whatconflicts(args, file) ipkg_file_what(args,file,"whatconflicts")
++#define ipkg_package_whatreplaces(args, file) ipkg_file_what(args,file,"whatreplaces")
++
++
++int default_ipkg_message_callback(ipkg_conf_t *conf, message_level_t level,
++ char *msg)
++{
++ if (conf && (conf->verbosity < level)) {
++ return 0;
++ } else {
++#ifdef IPKG_LIB
++ if ( level == IPKG_ERROR ){
++ push_error_list(&error_list, msg);
++// printf(msg);
++ } else
++#endif
++ printf(msg);
++ }
++ return 0;
++}
++
++int default_ipkg_list_callback(char *name, char *desc, char *version,
++ pkg_state_status_t status, void *userdata)
++{
++ if (desc)
++ printf("%s - %s - %s\n", name, version, desc);
++ else
++ printf("%s - %s\n", name, version);
++ return 0;
++}
++
++int default_ipkg_files_callback(char *name, char *desc, char *version,
++ pkg_state_status_t status, void *userdata)
++{
++ if (desc)
++ printf("%s\n", desc);
++ return 0;
++}
++
++int default_ipkg_status_callback(char *name, int istatus, char *desc,
++ void *userdata)
++{
++ printf("%s\n", desc);
++ return 0;
++}
++
++char* default_ipkg_response_callback(char *question)
++{
++ char *response = NULL;
++ printf(question);
++ fflush(stdout);
++ do {
++ response = (char *)file_read_line_alloc(stdin);
++ } while (response == NULL);
++ return response;
++}
++
++/* This is used for backward compatibility */
++int
++ipkg_op (int argc, char *argv[])
++{
++ int err, optind;
++ args_t args;
++ char *cmd_name;
++ ipkg_cmd_t *cmd;
++ ipkg_conf_t ipkg_conf;
++
++ args_init (&args);
++
++ optind = args_parse (&args, argc, argv);
++ if (optind == argc || optind < 0)
++ {
++ args_usage ("ipkg must have one sub-command argument");
++ }
++
++ cmd_name = argv[optind++];
++/* Pigi: added a flag to disable the checking of structures if the command does not need to
++ read anything from there.
++*/
++ if ( !strcmp(cmd_name,"print-architecture") ||
++ !strcmp(cmd_name,"print_architecture") ||
++ !strcmp(cmd_name,"print-installation-architecture") ||
++ !strcmp(cmd_name,"print_installation_architecture") )
++ args.nocheckfordirorfile = 1;
++
++/* Pigi: added a flag to disable the reading of feed files if the command does not need to
++ read anything from there.
++*/
++ if ( !strcmp(cmd_name,"flag") ||
++ !strcmp(cmd_name,"configure") ||
++ !strcmp(cmd_name,"remove") ||
++ !strcmp(cmd_name,"files") ||
++ !strcmp(cmd_name,"search") ||
++ !strcmp(cmd_name,"compare_versions") ||
++ !strcmp(cmd_name,"compare-versions") ||
++ !strcmp(cmd_name,"list_installed") ||
++ !strcmp(cmd_name,"list-installed") ||
++ !strcmp(cmd_name,"status") )
++ args.noreadfeedsfile = 1;
++
++
++ err = ipkg_conf_init (&ipkg_conf, &args);
++ if (err)
++ {
++ return err;
++ }
++
++ args_deinit (&args);
++
++ ipkg_cb_message = default_ipkg_message_callback;
++ ipkg_cb_response = default_ipkg_response_callback;
++ ipkg_cb_status = default_ipkg_status_callback;
++ if ( strcmp(cmd_name, "files")==0)
++ ipkg_cb_list = default_ipkg_files_callback;
++ else
++ ipkg_cb_list = default_ipkg_list_callback;
++
++ cmd = ipkg_cmd_find (cmd_name);
++ if (cmd == NULL)
++ {
++ fprintf (stderr, "%s: unknown sub-command %s\n", argv[0],
++ cmd_name);
++ args_usage (NULL);
++ }
++
++ if (cmd->requires_args && optind == argc)
++ {
++ fprintf (stderr,
++ "%s: the ``%s'' command requires at least one argument\n",
++ __FUNCTION__, cmd_name);
++ args_usage (NULL);
++ }
++
++ err = ipkg_cmd_exec (cmd, &ipkg_conf, argc - optind, (const char **) (argv + optind), NULL);
++
++ ipkg_conf_deinit (&ipkg_conf);
++
++ return err;
++}
++
++#endif /* IPKG_LIB */
+diff -ruN busybox-1.2.0-orig/archival/libipkg/libipkg.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/libipkg.h
+--- busybox-1.2.0-orig/archival/libipkg/libipkg.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/libipkg.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,87 @@
++/* ipkglib.h - the itsy package management system
++
++ Florian Boor <florian.boor@kernelconcepts.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, 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 IPKGLIB_H
++#define IPKGLIB_H
++
++#ifdef IPKG_LIB
++
++#include "ipkg_conf.h"
++#include "ipkg_message.h"
++
++#include "args.h"
++#include "pkg.h"
++
++typedef int (*ipkg_message_callback)(ipkg_conf_t *conf, message_level_t level,
++ char *msg);
++typedef int (*ipkg_list_callback)(char *name, char *desc, char *version,
++ pkg_state_status_t status, void *userdata);
++typedef int (*ipkg_status_callback)(char *name, int istatus, char *desc,
++ void *userdata);
++typedef char* (*ipkg_response_callback)(char *question);
++
++extern int ipkg_op(int argc, char *argv[]); /* ipkglib.c */
++extern int ipkg_init (ipkg_message_callback mcall,
++ ipkg_response_callback rcall,
++ args_t * args);
++
++extern int ipkg_deinit (args_t *args);
++extern int ipkg_packages_list(args_t *args,
++ const char *packages,
++ ipkg_list_callback cblist,
++ void *userdata);
++extern int ipkg_packages_status(args_t *args,
++ const char *packages,
++ ipkg_status_callback cbstatus,
++ void *userdata);
++extern int ipkg_packages_info(args_t *args,
++ const char *packages,
++ ipkg_status_callback cbstatus,
++ void *userdata);
++extern int ipkg_packages_install(args_t *args, const char *name);
++extern int ipkg_packages_remove(args_t *args, const char *name, int purge);
++extern int ipkg_lists_update(args_t *args);
++extern int ipkg_packages_upgrade(args_t *args);
++extern int ipkg_packages_download(args_t *args, const char *name);
++extern int ipkg_package_files(args_t *args,
++ const char *name,
++ ipkg_list_callback cblist,
++ void *userdata);
++extern int ipkg_file_search(args_t *args,
++ const char *file,
++ ipkg_list_callback cblist,
++ void *userdata);
++extern int ipkg_package_whatdepends(args_t *args, const char *file);
++extern int ipkg_package_whatrecommends(args_t *args, const char *file);
++extern int ipkg_package_whatprovides(args_t *args, const char *file);
++extern int ipkg_package_whatconflicts(args_t *args, const char *file);
++extern int ipkg_package_whatreplaces(args_t *args, const char *file);
++
++extern ipkg_message_callback ipkg_cb_message; /* ipkglib.c */
++extern ipkg_response_callback ipkg_cb_response;
++extern ipkg_status_callback ipkg_cb_status;
++extern ipkg_list_callback ipkg_cb_list;
++extern void push_error_list(struct errlist **errors,char * msg);
++extern void reverse_error_list(struct errlist **errors);
++extern void free_error_list(struct errlist **errors);
++
++#else
++
++extern int ipkg_op(int argc, char *argv[]);
++
++#endif
++
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/Makefile busybox-1.2.0+ipkg-0.99.162/archival/libipkg/Makefile
+--- busybox-1.2.0-orig/archival/libipkg/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/Makefile 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,32 @@
++# Makefile for busybox
++#
++# Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.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
++#
++
++top_srcdir=../..
++top_builddir=../..
++srcdir=$(top_srcdir)/archival/libipkg
++LIBIPKG_DIR:=./
++include $(top_builddir)/Rules.mak
++include $(top_builddir)/.config
++include $(srcdir)/Makefile.in
++all: $(libraries-y)
++-include $(top_builddir)/.depend
++
++clean:
++ rm -f *.o *.a $(AR_TARGET)
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/Makefile.in busybox-1.2.0+ipkg-0.99.162/archival/libipkg/Makefile.in
+--- busybox-1.2.0-orig/archival/libipkg/Makefile.in 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/Makefile.in 2006-10-08 12:29:39.000000000 +0200
+@@ -0,0 +1,88 @@
++# Makefile for busybox
++#
++# Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.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
++#
++
++LIBIPKG_AR:=libipkg.a
++ifndef $(LIBIPKG_DIR)
++LIBIPKG_DIR:=$(top_builddir)/archival/libipkg/
++endif
++srcdir=$(top_srcdir)/archival/libipkg
++
++LIBIPKG_CORE_SOURCES:= \
++ args.c \
++ libipkg.c \
++ user.c \
++
++LIBIPKG_CMD_SOURCES:= \
++ ipkg_cmd.c \
++ ipkg_configure.c \
++ ipkg_download.c \
++ ipkg_install.c \
++ ipkg_remove.c \
++ ipkg_upgrade.c \
++
++LIBIPKG_DB_SOURCES:= \
++ hash_table.c \
++ ipkg_conf.c \
++ ipkg_utils.c \
++ pkg.c \
++ pkg_depends.c \
++ pkg_extract.c \
++ pkg_hash.c \
++ pkg_parse.c \
++ pkg_vec.c \
++
++LIBIPKG_LIST_SOURCES:= \
++ conffile.c \
++ conffile_list.c \
++ nv_pair.c \
++ nv_pair_list.c \
++ pkg_dest.c \
++ pkg_dest_list.c \
++ pkg_src.c \
++ pkg_src_list.c \
++ str_list.c \
++ void_list.c \
++
++LIBIPKG_UTIL_SOURCES:= \
++ file_util.c \
++ ipkg_message.c \
++ md5.c \
++ str_util.c \
++ xsystem.c \
++
++LIBIPKG-$(CONFIG_IPKG) += $(LIBIPKG_CORE_SOURCES)
++LIBIPKG-$(CONFIG_IPKG) += $(LIBIPKG_CMD_SOURCES)
++LIBIPKG-$(CONFIG_IPKG) += $(LIBIPKG_DB_SOURCES)
++LIBIPKG-$(CONFIG_IPKG) += $(LIBIPKG_LIST_SOURCES)
++LIBIPKG-$(CONFIG_IPKG) += $(LIBIPKG_UTIL_SOURCES)
++LIBIPKG_OBJS=$(patsubst %.c,$(LIBIPKG_DIR)%.o, $(LIBIPKG-y))
++
++ifeq ($(strip $(IPKG_ARCH)),)
++IPKG_ARCH:=$(TARGET_ARCH)
++endif
++CFLAGS += -DIPKG_LIB -DIPKGLIBDIR="\"/usr/lib\"" -DHOST_CPU_STR="\"$(IPKG_ARCH)\""
++
++libraries-$(CONFIG_IPKG) += $(LIBIPKG_DIR)$(LIBIPKG_AR)
++
++$(LIBIPKG_DIR)$(LIBIPKG_AR): $(LIBIPKG_OBJS)
++ $(do_ar)
++
++$(LIBIPKG_OBJS): $(LIBIPKG_DIR)%.o : $(srcdir)/%.c
++ $(compile.c)
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/md5.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/md5.c
+--- busybox-1.2.0-orig/archival/libipkg/md5.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/md5.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,48 @@
++/* md5.c - wrappers to busybox md5 functions
++ *
++ * Copyright (C) 1995-1999 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.
++ */
++
++#include <stdio.h>
++#include "libbb.h"
++
++#include "md5.h"
++
++int md5_stream(FILE *stream, void *resblock)
++{
++ int fd;
++ int sum;
++
++ if( (fd = fileno(stream)) == -1 ) {
++ bb_error_msg("bad file descriptor");
++ return 1;
++ }
++
++ hash_fd(fd, HASH_MD5, (uint8_t *)resblock);
++
++ return 0;
++}
++
++void *md5_buffer(const char *buffer, size_t len, void *resblock)
++{
++ md5_ctx_t md5_cx;
++
++ md5_begin(&md5_cx);
++ md5_hash(buffer, len, &md5_cx);
++ return md5_end(resblock, &md5_cx);
++}
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/md5.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/md5.h
+--- busybox-1.2.0-orig/archival/libipkg/md5.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/md5.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,35 @@
++/* md5.h - Compute MD5 checksum of files or strings according to the
++ * definition of MD5 in RFC 1321 from April 1992.
++ * Copyright (C) 1995-1999 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.
++ */
++
++#ifndef MD5_H
++#define MD5_H
++
++/* Compute MD5 message digest for bytes read from STREAM. The
++ resulting message digest number will be written into the 16 bytes
++ beginning at RESBLOCK. */
++int md5_stream(FILE *stream, void *resblock);
++
++/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
++ result is always in little endian byte order, so that a byte-wise
++ output yields to the wanted ASCII representation of the message
++ digest. */
++void *md5_buffer(const char *buffer, size_t len, void *resblock);
++
++#endif
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/nv_pair.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/nv_pair.c
+--- busybox-1.2.0-orig/archival/libipkg/nv_pair.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/nv_pair.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,40 @@
++/* nv_pair.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++
++#include "nv_pair.h"
++#include "str_util.h"
++
++int nv_pair_init(nv_pair_t *nv_pair, const char *name, const char *value)
++{
++ nv_pair->name = str_dup_safe(name);
++ nv_pair->value = str_dup_safe(value);
++
++ return 0;
++}
++
++void nv_pair_deinit(nv_pair_t *nv_pair)
++{
++ free(nv_pair->name);
++ nv_pair->name = NULL;
++
++ free(nv_pair->value);
++ nv_pair->value = NULL;
++}
++
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/nv_pair.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/nv_pair.h
+--- busybox-1.2.0-orig/archival/libipkg/nv_pair.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/nv_pair.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,32 @@
++/* nv_pair.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef NV_PAIR_H
++#define NV_PAIR_H
++
++typedef struct nv_pair nv_pair_t;
++struct nv_pair
++{
++ char *name;
++ char *value;
++};
++
++int nv_pair_init(nv_pair_t *nv_pair, const char *name, const char *value);
++void nv_pair_deinit(nv_pair_t *nv_pair);
++
++#endif
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/nv_pair_list.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/nv_pair_list.c
+--- busybox-1.2.0-orig/archival/libipkg/nv_pair_list.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/nv_pair_list.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,98 @@
++/* nv_pair_list.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++
++#include "nv_pair.h"
++#include "void_list.h"
++#include "nv_pair_list.h"
++
++int nv_pair_list_elt_init(nv_pair_list_elt_t *elt, nv_pair_t *data)
++{
++ return void_list_elt_init((void_list_elt_t *) elt, data);
++}
++
++void nv_pair_list_elt_deinit(nv_pair_list_elt_t *elt)
++{
++ void_list_elt_deinit((void_list_elt_t *) elt);
++}
++
++int nv_pair_list_init(nv_pair_list_t *list)
++{
++ return void_list_init((void_list_t *) list);
++}
++
++void nv_pair_list_deinit(nv_pair_list_t *list)
++{
++ nv_pair_list_elt_t *iter;
++ nv_pair_t *nv_pair;
++
++ for (iter = list->head; iter; iter = iter->next) {
++ nv_pair = iter->data;
++ nv_pair_deinit(nv_pair);
++
++ /* malloced in nv_pair_list_append */
++ free(nv_pair);
++ iter->data = NULL;
++ }
++ void_list_deinit((void_list_t *) list);
++}
++
++nv_pair_t *nv_pair_list_append(nv_pair_list_t *list, const char *name, const char *value)
++{
++ int err;
++
++ /* freed in nv_pair_list_deinit */
++ nv_pair_t *nv_pair = malloc(sizeof(nv_pair_t));
++
++ if (nv_pair == NULL) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ nv_pair_init(nv_pair, name, value);
++
++ err = void_list_append((void_list_t *) list, nv_pair);
++ if (err) {
++ return NULL;
++ }
++
++ return nv_pair;
++}
++
++int nv_pair_list_push(nv_pair_list_t *list, nv_pair_t *data)
++{
++ return void_list_push((void_list_t *) list, data);
++}
++
++nv_pair_list_elt_t *nv_pair_list_pop(nv_pair_list_t *list)
++{
++ return (nv_pair_list_elt_t *) void_list_pop((void_list_t *) list);
++}
++
++char *nv_pair_list_find(nv_pair_list_t *list, char *name)
++{
++ nv_pair_list_elt_t *iter;
++ nv_pair_t *nv_pair;
++
++ for (iter = list->head; iter; iter = iter->next) {
++ nv_pair = iter->data;
++ if (strcmp(nv_pair->name, name) == 0) {
++ return nv_pair->value;
++ }
++ }
++ return NULL;
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/nv_pair_list.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/nv_pair_list.h
+--- busybox-1.2.0-orig/archival/libipkg/nv_pair_list.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/nv_pair_list.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,60 @@
++/* nv_pair_list.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef NV_PAIR_LIST_H
++#define NV_PAIR_LIST_H
++
++#include "nv_pair.h"
++#include "void_list.h"
++
++typedef struct nv_pair_list_elt nv_pair_list_elt_t;
++struct nv_pair_list_elt
++{
++ nv_pair_list_elt_t *next;
++ nv_pair_t *data;
++};
++
++typedef struct nv_pair_list nv_pair_list_t;
++struct nv_pair_list
++{
++ nv_pair_list_elt_t pre_head;
++ nv_pair_list_elt_t *head;
++ nv_pair_list_elt_t *tail;
++};
++
++static inline int nv_pair_list_empty(nv_pair_list_t *list)
++{
++ if (list->head == NULL)
++ return 1;
++ else
++ return 0;
++}
++
++int nv_pair_list_elt_init(nv_pair_list_elt_t *elt, nv_pair_t *data);
++void nv_pair_list_elt_deinit(nv_pair_list_elt_t *elt);
++
++int nv_pair_list_init(nv_pair_list_t *list);
++void nv_pair_list_deinit(nv_pair_list_t *list);
++
++nv_pair_t *nv_pair_list_append(nv_pair_list_t *list,
++ const char *name, const char *value);
++int nv_pair_list_push(nv_pair_list_t *list, nv_pair_t *data);
++nv_pair_list_elt_t *nv_pair_list_pop(nv_pair_list_t *list);
++char *nv_pair_list_find(nv_pair_list_t *list, char *name);
++
++#endif
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg.c
+--- busybox-1.2.0-orig/archival/libipkg/pkg.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,1754 @@
++/* pkg.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++#include <ctype.h>
++#include <string.h>
++#include <errno.h>
++
++#include "pkg.h"
++
++#include "pkg_parse.h"
++#include "pkg_extract.h"
++#include "ipkg_message.h"
++#include "ipkg_utils.h"
++
++#include "sprintf_alloc.h"
++#include "file_util.h"
++#include "str_util.h"
++#include "xsystem.h"
++#include "ipkg_conf.h"
++
++typedef struct enum_map enum_map_t;
++struct enum_map
++{
++ int value;
++ char *str;
++};
++
++static const enum_map_t pkg_state_want_map[] = {
++ { SW_UNKNOWN, "unknown"},
++ { SW_INSTALL, "install"},
++ { SW_DEINSTALL, "deinstall"},
++ { SW_PURGE, "purge"}
++};
++
++static const enum_map_t pkg_state_flag_map[] = {
++ { SF_OK, "ok"},
++ { SF_REINSTREQ, "reinstreq"},
++ { SF_HOLD, "hold"},
++ { SF_REPLACE, "replace"},
++ { SF_NOPRUNE, "noprune"},
++ { SF_PREFER, "prefer"},
++ { SF_OBSOLETE, "obsolete"},
++ { SF_USER, "user"},
++};
++
++static const enum_map_t pkg_state_status_map[] = {
++ { SS_NOT_INSTALLED, "not-installed" },
++ { SS_UNPACKED, "unpacked" },
++ { SS_HALF_CONFIGURED, "half-configured" },
++ { SS_INSTALLED, "installed" },
++ { SS_HALF_INSTALLED, "half-installed" },
++ { SS_CONFIG_FILES, "config-files" },
++ { SS_POST_INST_FAILED, "post-inst-failed" },
++ { SS_REMOVAL_FAILED, "removal-failed" }
++};
++
++static int verrevcmp(const char *val, const char *ref);
++
++
++pkg_t *pkg_new(void)
++{
++ pkg_t *pkg;
++
++ pkg = malloc(sizeof(pkg_t));
++ if (pkg == NULL) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++
++ pkg_init(pkg);
++
++ return pkg;
++}
++
++int pkg_init(pkg_t *pkg)
++{
++ memset(pkg, 0, sizeof(pkg_t));
++ pkg->name = NULL;
++ pkg->epoch = 0;
++ pkg->version = NULL;
++ pkg->revision = NULL;
++ pkg->familiar_revision = NULL;
++ pkg->dest = NULL;
++ pkg->src = NULL;
++ pkg->architecture = NULL;
++ pkg->maintainer = NULL;
++ pkg->section = NULL;
++ pkg->description = NULL;
++ pkg->state_want = SW_UNKNOWN;
++ pkg->state_flag = SF_OK;
++ pkg->state_status = SS_NOT_INSTALLED;
++ pkg->depends_str = NULL;
++ pkg->provides_str = NULL;
++ pkg->depends_count = 0;
++ pkg->depends = NULL;
++ pkg->suggests_str = NULL;
++ pkg->recommends_str = NULL;
++ pkg->suggests_count = 0;
++ pkg->recommends_count = 0;
++
++ /* Abhaya: added init for conflicts fields */
++ pkg->conflicts = NULL;
++ pkg->conflicts_count = 0;
++
++ /* added for replaces. Jamey 7/23/2002 */
++ pkg->replaces = NULL;
++ pkg->replaces_count = 0;
++
++ pkg->pre_depends_count = 0;
++ pkg->pre_depends_str = NULL;
++ pkg->provides_count = 0;
++ pkg->provides = NULL;
++ pkg->filename = NULL;
++ pkg->local_filename = NULL;
++ pkg->tmp_unpack_dir = NULL;
++ pkg->md5sum = NULL;
++ pkg->size = NULL;
++ pkg->installed_size = NULL;
++ pkg->priority = NULL;
++ pkg->source = NULL;
++ conffile_list_init(&pkg->conffiles);
++ pkg->installed_files = NULL;
++ pkg->installed_files_ref_cnt = 0;
++ pkg->essential = 0;
++ pkg->provided_by_hand = 0;
++
++ return 0;
++}
++
++void pkg_deinit(pkg_t *pkg)
++{
++ free(pkg->name);
++ pkg->name = NULL;
++ pkg->epoch = 0;
++ free(pkg->version);
++ pkg->version = NULL;
++ /* revision and familiar_revision share storage with version, so
++ don't free */
++ pkg->revision = NULL;
++ pkg->familiar_revision = NULL;
++ /* owned by ipkg_conf_t */
++ pkg->dest = NULL;
++ /* owned by ipkg_conf_t */
++ pkg->src = NULL;
++ free(pkg->architecture);
++ pkg->architecture = NULL;
++ free(pkg->maintainer);
++ pkg->maintainer = NULL;
++ free(pkg->section);
++ pkg->section = NULL;
++ free(pkg->description);
++ pkg->description = NULL;
++ pkg->state_want = SW_UNKNOWN;
++ pkg->state_flag = SF_OK;
++ pkg->state_status = SS_NOT_INSTALLED;
++ free(pkg->depends_str);
++ pkg->depends_str = NULL;
++ free(pkg->provides_str);
++ pkg->provides_str = NULL;
++ pkg->depends_count = 0;
++ /* XXX: CLEANUP: MEMORY_LEAK: how to free up pkg->depends ? */
++ pkg->pre_depends_count = 0;
++ free(pkg->pre_depends_str);
++ pkg->pre_depends_str = NULL;
++ pkg->provides_count = 0;
++ /* XXX: CLEANUP: MEMORY_LEAK: how to free up pkg->provides ? */
++ /* XXX: CLEANUP: MEMORY_LEAK: how to free up pkg->suggests ? */
++ free(pkg->filename);
++ pkg->filename = NULL;
++ free(pkg->local_filename);
++ pkg->local_filename = NULL;
++ /* CLEANUP: It'd be nice to pullin the cleanup function from
++ ipkg_install.c here. See comment in
++ ipkg_install.c:cleanup_temporary_files */
++ free(pkg->tmp_unpack_dir);
++ pkg->tmp_unpack_dir = NULL;
++ free(pkg->md5sum);
++ pkg->md5sum = NULL;
++ free(pkg->size);
++ pkg->size = NULL;
++ free(pkg->installed_size);
++ pkg->installed_size = NULL;
++ free(pkg->priority);
++ pkg->priority = NULL;
++ free(pkg->source);
++ pkg->source = NULL;
++ conffile_list_deinit(&pkg->conffiles);
++ /* XXX: QUESTION: Is forcing this to 1 correct? I suppose so,
++ since if they are calling deinit, they should know. Maybe do an
++ assertion here instead? */
++ pkg->installed_files_ref_cnt = 1;
++ pkg_free_installed_files(pkg);
++ pkg->essential = 0;
++}
++
++int pkg_init_from_file(pkg_t *pkg, const char *filename)
++{
++ int err;
++ char **raw;
++ FILE *control_file;
++
++ err = pkg_init(pkg);
++ if (err) { return err; }
++
++ pkg->local_filename = strdup(filename);
++
++ control_file = tmpfile();
++ err = pkg_extract_control_file_to_stream(pkg, control_file);
++ if (err) { return err; }
++
++ rewind(control_file);
++ raw = read_raw_pkgs_from_stream(control_file);
++ pkg_parse_raw(pkg, &raw, NULL, NULL);
++
++ fclose(control_file);
++
++ return 0;
++}
++
++/* Merge any new information in newpkg into oldpkg */
++/* XXX: CLEANUP: This function shouldn't actually modify anything in
++ newpkg, but should leave it usable. This rework is so that
++ pkg_hash_insert doesn't clobber the pkg that you pass into it. */
++/*
++ * uh, i thought that i had originally written this so that it took
++ * two pkgs and returned a new one? we can do that again... -sma
++ */
++int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
++{
++ if (oldpkg == newpkg) {
++ return 0;
++ }
++
++ if (!oldpkg->src)
++ oldpkg->src = newpkg->src;
++ if (!oldpkg->dest)
++ oldpkg->dest = newpkg->dest;
++ if (!oldpkg->architecture)
++ oldpkg->architecture = str_dup_safe(newpkg->architecture);
++ if (!oldpkg->arch_priority)
++ oldpkg->arch_priority = newpkg->arch_priority;
++ if (!oldpkg->section)
++ oldpkg->section = str_dup_safe(newpkg->section);
++ if(!oldpkg->maintainer)
++ oldpkg->maintainer = str_dup_safe(newpkg->maintainer);
++ if(!oldpkg->description)
++ oldpkg->description = str_dup_safe(newpkg->description);
++ if (set_status) {
++ /* merge the state_flags from the new package */
++ oldpkg->state_want = newpkg->state_want;
++ oldpkg->state_status = newpkg->state_status;
++ oldpkg->state_flag = newpkg->state_flag;
++ } else {
++ if (oldpkg->state_want == SW_UNKNOWN)
++ oldpkg->state_want = newpkg->state_want;
++ if (oldpkg->state_status == SS_NOT_INSTALLED)
++ oldpkg->state_status = newpkg->state_status;
++ oldpkg->state_flag |= newpkg->state_flag;
++ }
++
++ if (!oldpkg->depends_str && !oldpkg->pre_depends_str && !oldpkg->recommends_str && !oldpkg->suggests_str) {
++ oldpkg->depends_str = newpkg->depends_str;
++ newpkg->depends_str = NULL;
++ oldpkg->depends_count = newpkg->depends_count;
++ newpkg->depends_count = 0;
++
++ oldpkg->depends = newpkg->depends;
++ newpkg->depends = NULL;
++
++ oldpkg->pre_depends_str = newpkg->pre_depends_str;
++ newpkg->pre_depends_str = NULL;
++ oldpkg->pre_depends_count = newpkg->pre_depends_count;
++ newpkg->pre_depends_count = 0;
++
++ oldpkg->recommends_str = newpkg->recommends_str;
++ newpkg->recommends_str = NULL;
++ oldpkg->recommends_count = newpkg->recommends_count;
++ newpkg->recommends_count = 0;
++
++ oldpkg->suggests_str = newpkg->suggests_str;
++ newpkg->suggests_str = NULL;
++ oldpkg->suggests_count = newpkg->suggests_count;
++ newpkg->suggests_count = 0;
++ }
++
++ if (!oldpkg->provides_str) {
++ oldpkg->provides_str = newpkg->provides_str;
++ newpkg->provides_str = NULL;
++ oldpkg->provides_count = newpkg->provides_count;
++ newpkg->provides_count = 0;
++
++ oldpkg->provides = newpkg->provides;
++ newpkg->provides = NULL;
++ }
++
++ if (!oldpkg->conflicts_str) {
++ oldpkg->conflicts_str = newpkg->conflicts_str;
++ newpkg->conflicts_str = NULL;
++ oldpkg->conflicts_count = newpkg->conflicts_count;
++ newpkg->conflicts_count = 0;
++
++ oldpkg->conflicts = newpkg->conflicts;
++ newpkg->conflicts = NULL;
++ }
++
++ if (!oldpkg->replaces_str) {
++ oldpkg->replaces_str = newpkg->replaces_str;
++ newpkg->replaces_str = NULL;
++ oldpkg->replaces_count = newpkg->replaces_count;
++ newpkg->replaces_count = 0;
++
++ oldpkg->replaces = newpkg->replaces;
++ newpkg->replaces = NULL;
++ }
++
++ if (!oldpkg->filename)
++ oldpkg->filename = str_dup_safe(newpkg->filename);
++ if (0)
++ fprintf(stdout, "pkg=%s old local_filename=%s new local_filename=%s\n",
++ oldpkg->name, oldpkg->local_filename, newpkg->local_filename);
++ if (!oldpkg->local_filename)
++ oldpkg->local_filename = str_dup_safe(newpkg->local_filename);
++ if (!oldpkg->tmp_unpack_dir)
++ oldpkg->tmp_unpack_dir = str_dup_safe(newpkg->tmp_unpack_dir);
++ if (!oldpkg->md5sum)
++ oldpkg->md5sum = str_dup_safe(newpkg->md5sum);
++ if (!oldpkg->size)
++ oldpkg->size = str_dup_safe(newpkg->size);
++ if (!oldpkg->installed_size)
++ oldpkg->installed_size = str_dup_safe(newpkg->installed_size);
++ if (!oldpkg->priority)
++ oldpkg->priority = str_dup_safe(newpkg->priority);
++ if (!oldpkg->source)
++ oldpkg->source = str_dup_safe(newpkg->source);
++ if (oldpkg->conffiles.head == NULL){
++ oldpkg->conffiles = newpkg->conffiles;
++ conffile_list_init(&newpkg->conffiles);
++ }
++ if (!oldpkg->installed_files){
++ oldpkg->installed_files = newpkg->installed_files;
++ oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
++ newpkg->installed_files = NULL;
++ }
++ if (!oldpkg->essential)
++ oldpkg->essential = newpkg->essential;
++
++ return 0;
++}
++
++abstract_pkg_t *abstract_pkg_new(void)
++{
++ abstract_pkg_t * ab_pkg;
++
++ ab_pkg = malloc(sizeof(abstract_pkg_t));
++
++ if (ab_pkg == NULL) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++
++ if ( abstract_pkg_init(ab_pkg) < 0 )
++ return NULL;
++
++ return ab_pkg;
++}
++
++int abstract_pkg_init(abstract_pkg_t *ab_pkg)
++{
++ memset(ab_pkg, 0, sizeof(abstract_pkg_t));
++
++ ab_pkg->provided_by = abstract_pkg_vec_alloc();
++ if (ab_pkg->provided_by==NULL){
++ return -1;
++ }
++ ab_pkg->dependencies_checked = 0;
++ ab_pkg->state_status = SS_NOT_INSTALLED;
++
++ return 0;
++}
++
++void set_flags_from_control(ipkg_conf_t *conf, pkg_t *pkg){
++ char * temp_str;
++ char **raw =NULL;
++ char **raw_start=NULL;
++
++ temp_str = (char *) malloc (strlen(pkg->dest->info_dir)+strlen(pkg->name)+12);
++ if (temp_str == NULL ){
++ ipkg_message(conf, IPKG_INFO, "Out of memory in %s\n", __FUNCTION__);
++ return;
++ }
++ sprintf( temp_str,"%s/%s.control",pkg->dest->info_dir,pkg->name);
++
++ raw = raw_start = read_raw_pkgs_from_file(temp_str);
++ if (raw == NULL ){
++ ipkg_message(conf, IPKG_ERROR, "Unable to open the control file in %s\n", __FUNCTION__);
++ return;
++ }
++
++ while(*raw){
++ if (!pkg_valorize_other_field(pkg, &raw ) == 0) {
++ ipkg_message(conf, IPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
++ }
++ }
++ raw = raw_start;
++ while (*raw) {
++ if (raw!=NULL)
++ free(*raw++);
++ }
++
++ free(raw_start);
++ free(temp_str);
++
++ return ;
++
++}
++
++char * pkg_formatted_info(pkg_t *pkg )
++{
++ char *line;
++ char * buff;
++
++ buff = malloc(8192);
++ if (buff == NULL) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++
++ buff[0] = '\0';
++
++ line = pkg_formatted_field(pkg, "Package");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Version");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Depends");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Recommends");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Suggests");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Provides");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Replaces");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Conflicts");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Status");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Section");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Essential"); /* @@@@ should be removed in future release. *//* I do not agree with this Pigi*/
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Architecture");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Maintainer");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "MD5sum");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Size");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Filename");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Conffiles");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Source");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Description");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ line = pkg_formatted_field(pkg, "Installed-Time");
++ strncat(buff ,line, strlen(line));
++ free(line);
++
++ return buff;
++}
++
++char * pkg_formatted_field(pkg_t *pkg, const char *field )
++{
++ static size_t LINE_LEN = 128;
++ char * temp = (char *)malloc(1);
++ int len = 0;
++ int flag_provide_false = 0;
++
++/*
++ Pigi: After some discussion with Florian we decided to modify the full procedure in
++ dynamic memory allocation. This should avoid any other segv in this area ( except for bugs )
++*/
++
++ if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
++ goto UNKNOWN_FMT_FIELD;
++ }
++
++ temp[0]='\0';
++
++ switch (field[0])
++ {
++ case 'a':
++ case 'A':
++ if (strcasecmp(field, "Architecture") == 0) {
++ /* Architecture */
++ if (pkg->architecture) {
++ temp = (char *)realloc(temp,strlen(pkg->architecture)+17);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ snprintf(temp, (strlen(pkg->architecture)+17), "Architecture: %s\n", pkg->architecture);
++ }
++ } else {
++ goto UNKNOWN_FMT_FIELD;
++ }
++ break;
++ case 'c':
++ case 'C':
++ if (strcasecmp(field, "Conffiles") == 0) {
++ /* Conffiles */
++ conffile_list_elt_t *iter;
++ char confstr[LINE_LEN];
++
++ if (pkg->conffiles.head == NULL) {
++ return temp;
++ }
++
++ len = 14 ;
++ for (iter = pkg->conffiles.head; iter; iter = iter->next) {
++ if (iter->data->name && iter->data->value) {
++ len = len + (strlen(iter->data->name)+strlen(iter->data->value)+5);
++ }
++ }
++ temp = (char *)realloc(temp,len);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ strncpy(temp, "Conffiles:\n", 12);
++ for (iter = pkg->conffiles.head; iter; iter = iter->next) {
++ if (iter->data->name && iter->data->value) {
++ snprintf(confstr, LINE_LEN, "%s %s\n", iter->data->name, iter->data->value);
++ strncat(temp, confstr, strlen(confstr));
++ }
++ }
++ } else if (strcasecmp(field, "Conflicts") == 0) {
++ int i;
++
++ if (pkg->conflicts_count) {
++ char conflictstr[LINE_LEN];
++ len = 14 ;
++ for(i = 0; i < pkg->conflicts_count; i++) {
++ len = len + (strlen(pkg->conflicts_str[i])+5);
++ }
++ temp = (char *)realloc(temp,len);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ strncpy(temp, "Conflicts:", 11);
++ for(i = 0; i < pkg->conflicts_count; i++) {
++ snprintf(conflictstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->conflicts_str[i]);
++ strncat(temp, conflictstr, strlen(conflictstr));
++ }
++ strncat(temp, "\n", strlen("\n"));
++ }
++ } else {
++ goto UNKNOWN_FMT_FIELD;
++ }
++ break;
++ case 'd':
++ case 'D':
++ if (strcasecmp(field, "Depends") == 0) {
++ /* Depends */
++ int i;
++
++ if (pkg->depends_count) {
++ char depstr[LINE_LEN];
++ len = 14 ;
++ for(i = 0; i < pkg->depends_count; i++) {
++ len = len + (strlen(pkg->depends_str[i])+4);
++ }
++ temp = (char *)realloc(temp,len);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ strncpy(temp, "Depends:", 10);
++ for(i = 0; i < pkg->depends_count; i++) {
++ snprintf(depstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->depends_str[i]);
++ strncat(temp, depstr, strlen(depstr));
++ }
++ strncat(temp, "\n", strlen("\n"));
++ }
++ } else if (strcasecmp(field, "Description") == 0) {
++ /* Description */
++ if (pkg->description) {
++ temp = (char *)realloc(temp,strlen(pkg->description)+16);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ snprintf(temp, (strlen(pkg->description)+16), "Description: %s\n", pkg->description);
++ }
++ } else {
++ goto UNKNOWN_FMT_FIELD;
++ }
++ break;
++ case 'e':
++ case 'E': {
++ /* Essential */
++ if (pkg->essential) {
++ temp = (char *)realloc(temp,16);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ snprintf(temp, (16), "Essential: yes\n");
++ }
++ }
++ break;
++ case 'f':
++ case 'F': {
++ /* Filename */
++ if (pkg->filename) {
++ temp = (char *)realloc(temp,strlen(pkg->filename)+12);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ snprintf(temp, (strlen(pkg->filename)+12), "Filename: %s\n", pkg->filename);
++ }
++ }
++ break;
++ case 'i':
++ case 'I': {
++ if (strcasecmp(field, "Installed-Size") == 0) {
++ /* Installed-Size */
++ temp = (char *)realloc(temp,strlen(pkg->installed_size)+17);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ snprintf(temp, (strlen(pkg->installed_size)+17), "Installed-Size: %s\n", pkg->installed_size);
++ } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
++ temp = (char *)realloc(temp,29);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ snprintf(temp, 29, "Installed-Time: %lu\n", pkg->installed_time);
++ }
++ }
++ break;
++ case 'm':
++ case 'M': {
++ /* Maintainer | MD5sum */
++ if (strcasecmp(field, "Maintainer") == 0) {
++ /* Maintainer */
++ if (pkg->maintainer) {
++ temp = (char *)realloc(temp,strlen(pkg->maintainer)+14);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ snprintf(temp, (strlen(pkg->maintainer)+14), "maintainer: %s\n", pkg->maintainer);
++ }
++ } else if (strcasecmp(field, "MD5sum") == 0) {
++ /* MD5sum */
++ if (pkg->md5sum) {
++ temp = (char *)realloc(temp,strlen(pkg->md5sum)+11);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ snprintf(temp, (strlen(pkg->md5sum)+11), "MD5Sum: %s\n", pkg->md5sum);
++ }
++ } else {
++ goto UNKNOWN_FMT_FIELD;
++ }
++ }
++ break;
++ case 'p':
++ case 'P': {
++ if (strcasecmp(field, "Package") == 0) {
++ /* Package */
++ temp = (char *)realloc(temp,strlen(pkg->name)+11);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ snprintf(temp, (strlen(pkg->name)+11), "Package: %s\n", pkg->name);
++ } else if (strcasecmp(field, "Priority") == 0) {
++ /* Priority */
++ temp = (char *)realloc(temp,strlen(pkg->priority)+12);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ snprintf(temp, (strlen(pkg->priority)+12), "Priority: %s\n", pkg->priority);
++ } else if (strcasecmp(field, "Provides") == 0) {
++ /* Provides */
++ int i;
++
++ if (pkg->provides_count) {
++ /* Here we check if the ipkg_internal_use_only is used, and we discard it.*/
++ for ( i=0; i < pkg->provides_count; i++ ){
++ if (strstr(pkg->provides_str[i],"ipkg_internal_use_only")!=NULL) {
++ memset (pkg->provides_str[i],'\x0',strlen(pkg->provides_str[i])); /* Pigi clear my trick flag, just in case */
++ flag_provide_false = 1;
++ }
++ }
++ if ( !flag_provide_false || /* Pigi there is not my trick flag */
++ ((flag_provide_false) && (pkg->provides_count > 1))){ /* Pigi There is, but we also have others Provides */
++ char provstr[LINE_LEN];
++ len = 15;
++ for(i = 0; i < pkg->provides_count; i++) {
++ len = len + (strlen(pkg->provides_str[i])+5);
++ }
++ temp = (char *)realloc(temp,len);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ strncpy(temp, "Provides:", 12);
++ for(i = 0; i < pkg->provides_count; i++) {
++ if (strlen(pkg->provides_str[i])>0){;
++ snprintf(provstr, LINE_LEN, "%s %s", i == 1 ? "" : ",", pkg->provides_str[i]);
++ strncat(temp, provstr, strlen(provstr));
++ }
++ }
++ strncat(temp, "\n", strlen("\n"));
++ }
++ }
++ } else {
++ goto UNKNOWN_FMT_FIELD;
++ }
++ }
++ break;
++ case 'r':
++ case 'R': {
++ int i;
++ /* Replaces | Recommends*/
++ if (strcasecmp (field, "Replaces") == 0) {
++ if (pkg->replaces_count) {
++ char replstr[LINE_LEN];
++ len = 14;
++ for (i = 0; i < pkg->replaces_count; i++) {
++ len = len + (strlen(pkg->replaces_str[i])+5);
++ }
++ temp = (char *)realloc(temp,len);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ strncpy(temp, "Replaces:", 12);
++ for (i = 0; i < pkg->replaces_count; i++) {
++ snprintf(replstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->replaces_str[i]);
++ strncat(temp, replstr, strlen(replstr));
++ }
++ strncat(temp, "\n", strlen("\n"));
++ }
++ } else if (strcasecmp (field, "Recommends") == 0) {
++ if (pkg->recommends_count) {
++ char recstr[LINE_LEN];
++ len = 15;
++ for(i = 0; i < pkg->recommends_count; i++) {
++ len = len + (strlen( pkg->recommends_str[i])+5);
++ }
++ temp = (char *)realloc(temp,len);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ strncpy(temp, "Recommends:", 13);
++ for(i = 0; i < pkg->recommends_count; i++) {
++ snprintf(recstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->recommends_str[i]);
++ strncat(temp, recstr, strlen(recstr));
++ }
++ strncat(temp, "\n", strlen("\n"));
++ }
++ } else {
++ goto UNKNOWN_FMT_FIELD;
++ }
++ }
++ break;
++ case 's':
++ case 'S': {
++ /* Section | Size | Source | Status | Suggests */
++ if (strcasecmp(field, "Section") == 0) {
++ /* Section */
++ if (pkg->section) {
++ temp = (char *)realloc(temp,strlen(pkg->section)+11);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ snprintf(temp, (strlen(pkg->section)+11), "Section: %s\n", pkg->section);
++ }
++ } else if (strcasecmp(field, "Size") == 0) {
++ /* Size */
++ if (pkg->size) {
++ temp = (char *)realloc(temp,strlen(pkg->size)+8);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ snprintf(temp, (strlen(pkg->size)+8), "Size: %s\n", pkg->size);
++ }
++ } else if (strcasecmp(field, "Source") == 0) {
++ /* Source */
++ if (pkg->source) {
++ temp = (char *)realloc(temp,strlen(pkg->source)+10);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ snprintf(temp, (strlen(pkg->source)+10), "Source: %s\n", pkg->source);
++ }
++ } else if (strcasecmp(field, "Status") == 0) {
++ /* Status */
++ /* Benjamin Pineau note: we should avoid direct usage of
++ * strlen(arg) without keeping "arg" for later free()
++ */
++ char *pflag=pkg_state_flag_to_str(pkg->state_flag);
++ char *pstat=pkg_state_status_to_str(pkg->state_status);
++ char *pwant=pkg_state_want_to_str(pkg->state_want);
++
++ size_t sum_of_sizes = (size_t) ( strlen(pwant)+ strlen(pflag)+ strlen(pstat) + 12 );
++ temp = (char *)realloc(temp,sum_of_sizes);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ snprintf(temp, sum_of_sizes , "Status: %s %s %s\n", pwant, pflag, pstat);
++ free(pflag);
++ free(pwant);
++ if(pstat) /* pfstat can be NULL if ENOMEM */
++ free(pstat);
++ } else if (strcasecmp(field, "Suggests") == 0) {
++ if (pkg->suggests_count) {
++ int i;
++ char sugstr[LINE_LEN];
++ len = 13;
++ for(i = 0; i < pkg->suggests_count; i++) {
++ len = len + (strlen(pkg->suggests_str[i])+5);
++ }
++ temp = (char *)realloc(temp,len);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ strncpy(temp, "Suggests:", 10);
++ for(i = 0; i < pkg->suggests_count; i++) {
++ snprintf(sugstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->suggests_str[i]);
++ strncat(temp, sugstr, strlen(sugstr));
++ }
++ strncat(temp, "\n", strlen("\n"));
++ }
++ } else {
++ goto UNKNOWN_FMT_FIELD;
++ }
++ }
++ break;
++ case 'v':
++ case 'V': {
++ /* Version */
++ char *version = pkg_version_str_alloc(pkg);
++ temp = (char *)realloc(temp,strlen(version)+14);
++ if ( temp == NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ temp[0]='\0';
++ snprintf(temp, (strlen(version)+12), "Version: %s\n", version);
++ free(version);
++ }
++ break;
++ default:
++ goto UNKNOWN_FMT_FIELD;
++ }
++
++ if ( strlen(temp)<2 ) {
++ temp[0]='\0';
++ }
++ return temp;
++
++ UNKNOWN_FMT_FIELD:
++ fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
++ if ( strlen(temp)<2 ) {
++ temp[0]='\0';
++ }
++
++ return temp;
++}
++
++void pkg_print_info(pkg_t *pkg, FILE *file)
++{
++ char * buff;
++ if (pkg == NULL) {
++ return;
++ }
++
++ buff = pkg_formatted_info(pkg);
++ if ( buff == NULL )
++ return;
++ if (strlen(buff)>2){
++ fwrite(buff, 1, strlen(buff), file);
++ }
++ free(buff);
++}
++
++void pkg_print_status(pkg_t * pkg, FILE * file)
++{
++ if (pkg == NULL) {
++ return;
++ }
++
++ /* XXX: QUESTION: Do we actually want more fields here? The
++ original idea was to save space by installing only what was
++ needed for actual computation, (package, version, status,
++ essential, conffiles). The assumption is that all other fields
++ can be found in th available file.
++
++ But, someone proposed the idea to make it possible to
++ reconstruct a .ipk from an installed package, (ie. for beaming
++ from one handheld to another). So, maybe we actually want a few
++ more fields here, (depends, suggests, etc.), so that that would
++ be guaranteed to work even in the absence of more information
++ from the available file.
++
++ 28-MAR-03: kergoth and I discussed this yesterday. We think
++ the essential info needs to be here for all installed packages
++ because they may not appear in the Packages files on various
++ feeds. Furthermore, one should be able to install from URL or
++ local storage without requiring a Packages file from any feed.
++ -Jamey
++ */
++ pkg_print_field(pkg, file, "Package");
++ pkg_print_field(pkg, file, "Version");
++ pkg_print_field(pkg, file, "Depends");
++ pkg_print_field(pkg, file, "Recommends");
++ pkg_print_field(pkg, file, "Suggests");
++ pkg_print_field(pkg, file, "Provides");
++ pkg_print_field(pkg, file, "Replaces");
++ pkg_print_field(pkg, file, "Conflicts");
++ pkg_print_field(pkg, file, "Status");
++ pkg_print_field(pkg, file, "Essential"); /* @@@@ should be removed in future release. */
++ pkg_print_field(pkg, file, "Architecture");
++ pkg_print_field(pkg, file, "Conffiles");
++ pkg_print_field(pkg, file, "Installed-Time");
++ fputs("\n", file);
++}
++
++void pkg_print_field(pkg_t *pkg, FILE *file, const char *field)
++{
++ char *buff;
++ if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
++ fprintf(stderr, "%s: ERROR: Unknown field name: %s\n",
++ __FUNCTION__, field);
++ }
++ buff = pkg_formatted_field(pkg, field);
++ if (strlen(buff)>2) {
++ fprintf(file, "%s", buff);
++ fflush(file);
++ }
++ free(buff);
++ return;
++}
++
++/*
++ * libdpkg - Debian packaging suite library routines
++ * vercmp.c - comparison of version numbers
++ *
++ * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
++ */
++int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
++{
++ int r;
++
++ if (pkg->epoch > ref_pkg->epoch) {
++ return 1;
++ }
++
++ if (pkg->epoch < ref_pkg->epoch) {
++ return -1;
++ }
++
++ r = verrevcmp(pkg->version, ref_pkg->version);
++ if (r) {
++ return r;
++ }
++
++#ifdef USE_DEBVERSION
++ r = verrevcmp(pkg->revision, ref_pkg->revision);
++ if (r) {
++ return r;
++ }
++
++ r = verrevcmp(pkg->familiar_revision, ref_pkg->familiar_revision);
++#endif
++
++ return r;
++}
++
++int verrevcmp(const char *val, const char *ref)
++{
++ int vc, rc;
++ long vl, rl;
++ const char *vp, *rp;
++ const char *vsep, *rsep;
++
++ if (!val) val= "";
++ if (!ref) ref= "";
++ for (;;) {
++ vp= val; while (*vp && !isdigit(*vp)) vp++;
++ rp= ref; while (*rp && !isdigit(*rp)) rp++;
++ for (;;) {
++ vc= (val == vp) ? 0 : *val++;
++ rc= (ref == rp) ? 0 : *ref++;
++ if (!rc && !vc) break;
++ if (vc && !isalpha(vc)) vc += 256; /* assumes ASCII character set */
++ if (rc && !isalpha(rc)) rc += 256;
++ if (vc != rc) return vc - rc;
++ }
++ val= vp;
++ ref= rp;
++ vl=0; if (isdigit(*vp)) vl= strtol(val,(char**)&val,10);
++ rl=0; if (isdigit(*rp)) rl= strtol(ref,(char**)&ref,10);
++ if (vl != rl) return vl - rl;
++
++ vc = *val;
++ rc = *ref;
++ vsep = strchr(".-", vc);
++ rsep = strchr(".-", rc);
++ if (vsep && !rsep) return -1;
++ if (!vsep && rsep) return +1;
++
++ if (!*val && !*ref) return 0;
++ if (!*val) return -1;
++ if (!*ref) return +1;
++ }
++}
++
++int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
++{
++ int r;
++
++ r = pkg_compare_versions(it, ref);
++
++ if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
++ return r <= 0;
++ }
++
++ if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
++ return r >= 0;
++ }
++
++ if (strcmp(op, "<<") == 0) {
++ return r < 0;
++ }
++
++ if (strcmp(op, ">>") == 0) {
++ return r > 0;
++ }
++
++ if (strcmp(op, "=") == 0) {
++ return r == 0;
++ }
++
++ fprintf(stderr, "unknown operator: %s", op);
++ return 0;
++}
++
++int pkg_name_version_and_architecture_compare(void *p1, void *p2)
++{
++ const pkg_t *a = *(const pkg_t **)p1;
++ const pkg_t *b = *(const pkg_t **)p2;
++ int namecmp;
++ int vercmp;
++ if (!a->name || !b->name) {
++ fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
++ a, a->name, b, b->name);
++ return 0;
++ }
++
++ namecmp = strcmp(a->name, b->name);
++ if (namecmp)
++ return namecmp;
++ vercmp = pkg_compare_versions(a, b);
++ if (vercmp)
++ return vercmp;
++ if (!a->arch_priority || !b->arch_priority) {
++ fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
++ a, a->arch_priority, b, b->arch_priority);
++ return 0;
++ }
++ if (a->arch_priority > b->arch_priority)
++ return 1;
++ if (a->arch_priority < b->arch_priority)
++ return -1;
++ return 0;
++}
++
++int abstract_pkg_name_compare(void *p1, void *p2)
++{
++ const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
++ const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
++ if (!a->name || !b->name) {
++ fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
++ a, a->name, b, b->name);
++ return 0;
++ }
++ return strcmp(a->name, b->name);
++}
++
++
++char *pkg_version_str_alloc(pkg_t *pkg)
++{
++ char *complete_version;
++ char *epoch_str;
++#ifdef USE_DEBVERSION
++ char *revision_str;
++ char *familiar_revision_str;
++#endif
++
++ if (pkg->epoch) {
++ sprintf_alloc(&epoch_str, "%d:", pkg->epoch);
++ } else {
++ epoch_str = strdup("");
++ }
++
++#ifdef USE_DEBVERSION
++ if (pkg->revision && strlen(pkg->revision)) {
++ sprintf_alloc(&revision_str, "-%s", pkg->revision);
++ } else {
++ revision_str = strdup("");
++ }
++
++ if (pkg->familiar_revision && strlen(pkg->familiar_revision)) {
++ sprintf_alloc(&familiar_revision_str, "-fam%s", pkg->familiar_revision);
++ } else {
++ familiar_revision_str = strdup("");
++ }
++#endif
++
++#ifdef USE_DEBVERSION
++ sprintf_alloc(&complete_version, "%s%s%s%s",
++ epoch_str, pkg->version, revision_str, familiar_revision_str);
++#else
++ sprintf_alloc(&complete_version, "%s%s",
++ epoch_str, pkg->version);
++#endif
++
++ free(epoch_str);
++#ifdef USE_DEBVERSION
++ free(revision_str);
++ free(familiar_revision_str);
++#endif
++
++ return complete_version;
++}
++
++str_list_t *pkg_get_installed_files(pkg_t *pkg)
++{
++ int err;
++ char *list_file_name = NULL;
++ FILE *list_file = NULL;
++ char *line;
++ char *installed_file_name;
++ int rootdirlen;
++
++ pkg->installed_files_ref_cnt++;
++
++ if (pkg->installed_files) {
++ return pkg->installed_files;
++ }
++
++ pkg->installed_files = str_list_alloc();
++ if (pkg->installed_files == NULL) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++
++ /* For uninstalled packages, get the file list firectly from the package.
++ For installed packages, look at the package.list file in the database.
++ */
++ if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
++ if (pkg->local_filename == NULL) {
++ return pkg->installed_files;
++ }
++ /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
++ file. In other words, change deb_extract so that it can
++ simply return the file list as a char *[] rather than
++ insisting on writing in to a FILE * as it does now. */
++ list_file = tmpfile();
++ err = pkg_extract_data_file_names_to_stream(pkg, list_file);
++ if (err) {
++ fclose(list_file);
++ fprintf(stderr, "%s: Error extracting file list from %s: %s\n",
++ __FUNCTION__, pkg->local_filename, strerror(err));
++ return pkg->installed_files;
++ }
++ rewind(list_file);
++ } else {
++ sprintf_alloc(&list_file_name, "%s/%s.list",
++ pkg->dest->info_dir, pkg->name);
++ if (! file_exists(list_file_name)) {
++ free(list_file_name);
++ return pkg->installed_files;
++ }
++
++ list_file = fopen(list_file_name, "r");
++ if (list_file == NULL) {
++ fprintf(stderr, "WARNING: Cannot open %s: %s\n",
++ list_file_name, strerror(errno));
++ free(list_file_name);
++ return pkg->installed_files;
++ }
++ free(list_file_name);
++ }
++
++ rootdirlen = strlen( pkg->dest->root_dir );
++ while (1) {
++ char *file_name;
++
++ line = file_read_line_alloc(list_file);
++ if (line == NULL) {
++ break;
++ }
++ str_chomp(line);
++ file_name = line;
++
++ /* Take pains to avoid uglies like "/./" in the middle of file_name. */
++ if( strncmp( pkg->dest->root_dir,
++ file_name,
++ rootdirlen ) ) {
++ if (*file_name == '.') {
++ file_name++;
++ }
++ if (*file_name == '/') {
++ file_name++;
++ }
++
++ /* Freed in pkg_free_installed_files */
++ sprintf_alloc(&installed_file_name, "%s%s", pkg->dest->root_dir, file_name);
++ } else {
++ // already contains root_dir as header -> ABSOLUTE
++ sprintf_alloc(&installed_file_name, "%s", file_name);
++ }
++ str_list_append(pkg->installed_files, installed_file_name);
++ free(line);
++ }
++
++ fclose(list_file);
++
++ return pkg->installed_files;
++}
++
++/* XXX: CLEANUP: This function and it's counterpart,
++ (pkg_get_installed_files), do not match our init/deinit naming
++ convention. Nor the alloc/free convention. But, then again, neither
++ of these conventions currrently fit the way these two functions
++ work. */
++int pkg_free_installed_files(pkg_t *pkg)
++{
++ str_list_elt_t *iter;
++
++ pkg->installed_files_ref_cnt--;
++ if (pkg->installed_files_ref_cnt > 0) {
++ return 0;
++ }
++
++ if (pkg->installed_files) {
++
++ for (iter = pkg->installed_files->head; iter; iter = iter->next) {
++ /* malloced in pkg_get_installed_files */
++ free (iter->data);
++ iter->data = NULL;
++ }
++
++ str_list_deinit(pkg->installed_files);
++ }
++
++ pkg->installed_files = NULL;
++
++ return 0;
++}
++
++int pkg_remove_installed_files_list(ipkg_conf_t *conf, pkg_t *pkg)
++{
++ int err;
++ char *list_file_name;
++
++ //I don't think pkg_free_installed_files should be called here. Jamey
++ //pkg_free_installed_files(pkg);
++
++ sprintf_alloc(&list_file_name, "%s/%s.list",
++ pkg->dest->info_dir, pkg->name);
++ if (!conf->noaction) {
++ err = unlink(list_file_name);
++ free(list_file_name);
++
++ if (err) {
++ return errno;
++ }
++ }
++ return 0;
++}
++
++conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
++{
++ conffile_list_elt_t *iter;
++ conffile_t *conffile;
++
++ if (pkg == NULL) {
++ return NULL;
++ }
++
++ for (iter = pkg->conffiles.head; iter; iter = iter->next) {
++ conffile = iter->data;
++
++ if (strcmp(conffile->name, file_name) == 0) {
++ return conffile;
++ }
++ }
++
++ return NULL;
++}
++
++int pkg_run_script(ipkg_conf_t *conf, pkg_t *pkg,
++ const char *script, const char *args)
++{
++ int err;
++ char *path;
++ char *cmd;
++
++ /* XXX: FEATURE: When conf->offline_root is set, we should run the
++ maintainer script within a chroot environment. */
++
++ /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
++ have scripts in pkg->tmp_unpack_dir. */
++ if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
++ if (pkg->dest == NULL) {
++ fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
++ __FUNCTION__, pkg->name);
++ return EINVAL;
++ }
++ sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
++ } else {
++ if (pkg->tmp_unpack_dir == NULL) {
++ fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
++ __FUNCTION__, pkg->name);
++ return EINVAL;
++ }
++ sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
++ }
++
++ ipkg_message(conf, IPKG_INFO, "Running script %s\n", path);
++ if (conf->noaction) return 0;
++
++ /* XXX: CLEANUP: There must be a better way to handle maintainer
++ scripts when running with offline_root mode and/or a dest other
++ than '/'. I've been playing around with some clever chroot
++ tricks and I might come up with something workable. */
++ if (conf->offline_root) {
++ setenv("IPKG_OFFLINE_ROOT", conf->offline_root, 1);
++ }
++
++ setenv("PKG_ROOT",
++ pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
++
++ if (! file_exists(path)) {
++ free(path);
++ return 0;
++ }
++
++ if (conf->offline_root) {
++ fprintf(stderr, "(offline root mode: not running %s.%s)\n", pkg->name, script);
++ free(path);
++ return 0;
++ }
++
++ sprintf_alloc(&cmd, "%s %s", path, args);
++ free(path);
++
++ err = xsystem(cmd);
++ free(cmd);
++
++ if (err) {
++ fprintf(stderr, "%s script returned status %d\n", script, err);
++ return err;
++ }
++
++ return 0;
++}
++
++char *pkg_state_want_to_str(pkg_state_want_t sw)
++{
++ int i;
++
++ for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
++ if (pkg_state_want_map[i].value == sw) {
++ return strdup(pkg_state_want_map[i].str);
++ }
++ }
++
++ fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
++ __FUNCTION__, sw);
++ return strdup("<STATE_WANT_UNKNOWN>");
++}
++
++pkg_state_want_t pkg_state_want_from_str(char *str)
++{
++ int i;
++
++ for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
++ if (strcmp(str, pkg_state_want_map[i].str) == 0) {
++ return pkg_state_want_map[i].value;
++ }
++ }
++
++ fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
++ __FUNCTION__, str);
++ return SW_UNKNOWN;
++}
++
++char *pkg_state_flag_to_str(pkg_state_flag_t sf)
++{
++ int i;
++ int len = 3; /* ok\000 is minimum */
++ char *str = NULL;
++
++ /* clear the temporary flags before converting to string */
++ sf &= SF_NONVOLATILE_FLAGS;
++
++ if (sf == 0) {
++ return strdup("ok");
++ } else {
++
++ for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
++ if (sf & pkg_state_flag_map[i].value) {
++ len += strlen(pkg_state_flag_map[i].str) + 1;
++ }
++ }
++ str = malloc(len);
++ if ( str == NULL ) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ str[0] = 0;
++ for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
++ if (sf & pkg_state_flag_map[i].value) {
++ strcat(str, pkg_state_flag_map[i].str);
++ strcat(str, ",");
++ }
++ }
++ len = strlen(str);
++ str[len-1] = 0; /* squash last comma */
++ return str;
++ }
++}
++
++pkg_state_flag_t pkg_state_flag_from_str(char *str)
++{
++ int i;
++ int sf = SF_OK;
++
++ if (strcmp(str, "ok") == 0) {
++ return SF_OK;
++ }
++ for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
++ const char *sfname = pkg_state_flag_map[i].str;
++ int sfname_len = strlen(sfname);
++ if (strncmp(str, sfname, sfname_len) == 0) {
++ sf |= pkg_state_flag_map[i].value;
++ str += sfname_len;
++ if (str[0] == ',') {
++ str++;
++ } else {
++ break;
++ }
++ }
++ }
++
++ return sf;
++}
++
++char *pkg_state_status_to_str(pkg_state_status_t ss)
++{
++ int i;
++
++ for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
++ if (pkg_state_status_map[i].value == ss) {
++ return strdup(pkg_state_status_map[i].str);
++ }
++ }
++
++ fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
++ __FUNCTION__, ss);
++ return strdup("<STATE_STATUS_UNKNOWN>");
++}
++
++pkg_state_status_t pkg_state_status_from_str(char *str)
++{
++ int i;
++
++ for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
++ if (strcmp(str, pkg_state_status_map[i].str) == 0) {
++ return pkg_state_status_map[i].value;
++ }
++ }
++
++ fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
++ __FUNCTION__, str);
++ return SS_NOT_INSTALLED;
++}
++
++int pkg_arch_supported(ipkg_conf_t *conf, pkg_t *pkg)
++{
++ nv_pair_list_elt_t *l;
++
++ if (!pkg->architecture)
++ return 1;
++
++ l = conf->arch_list.head;
++
++ while (l) {
++ nv_pair_t *nv = l->data;
++ if (strcmp(nv->name, pkg->architecture) == 0) {
++ ipkg_message(conf, IPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
++ return 1;
++ }
++ l = l->next;
++ }
++
++ ipkg_message(conf, IPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
++ return 0;
++}
++
++int pkg_get_arch_priority(ipkg_conf_t *conf, const char *archname)
++{
++ nv_pair_list_elt_t *l;
++
++ l = conf->arch_list.head;
++
++ while (l) {
++ nv_pair_t *nv = l->data;
++ if (strcmp(nv->name, archname) == 0) {
++ int priority = strtol(nv->value, NULL, 0);
++ return priority;
++ }
++ l = l->next;
++ }
++ return 0;
++}
++
++int pkg_info_preinstall_check(ipkg_conf_t *conf)
++{
++ int i;
++ hash_table_t *pkg_hash = &conf->pkg_hash;
++ pkg_vec_t *available_pkgs = pkg_vec_alloc();
++ pkg_vec_t *installed_pkgs = pkg_vec_alloc();
++
++ ipkg_message(conf, IPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
++ pkg_hash_fetch_available(pkg_hash, available_pkgs);
++ /* update arch_priority for each package */
++ for (i = 0; i < available_pkgs->len; i++) {
++ pkg_t *pkg = available_pkgs->pkgs[i];
++ int arch_priority = 1;
++ if (!pkg)
++ continue;
++ // ipkg_message(conf, IPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
++ if (pkg->architecture)
++ arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
++ else
++ ipkg_message(conf, IPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
++ // ipkg_message(conf, IPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
++ pkg->arch_priority = arch_priority;
++ }
++
++ for (i = 0; i < available_pkgs->len; i++) {
++ pkg_t *pkg = available_pkgs->pkgs[i];
++ if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
++ /* clear flags and want for any uninstallable package */
++ ipkg_message(conf, IPKG_NOTICE, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n",
++ pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
++ pkg->state_want = SW_UNKNOWN;
++ pkg->state_flag = 0;
++ }
++ }
++ pkg_vec_free(available_pkgs);
++
++ /* update the file owner data structure */
++ ipkg_message(conf, IPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
++ pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
++ for (i = 0; i < installed_pkgs->len; i++) {
++ pkg_t *pkg = installed_pkgs->pkgs[i];
++ str_list_t *installed_files = pkg_get_installed_files(pkg); /* this causes installed_files to be cached */
++ str_list_elt_t *iter;
++ if (installed_files == NULL) {
++ ipkg_message(conf, IPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
++ break;
++ }
++ for (iter = installed_files->head; iter; iter = iter->next) {
++ char *installed_file = iter->data;
++ // ipkg_message(conf, IPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
++ file_hash_set_file_owner(conf, installed_file, pkg);
++ }
++ }
++ pkg_vec_free(installed_pkgs);
++
++ return 0;
++}
++
++struct pkg_write_filelist_data {
++ ipkg_conf_t *conf;
++ pkg_t *pkg;
++ FILE *stream;
++};
++
++void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
++{
++ struct pkg_write_filelist_data *data = data_;
++ pkg_t *entry = entry_;
++ if (entry == data->pkg) {
++ fprintf(data->stream, "%s\n", key);
++ }
++}
++
++int pkg_write_filelist(ipkg_conf_t *conf, pkg_t *pkg)
++{
++ struct pkg_write_filelist_data data;
++ char *list_file_name = NULL;
++ int err = 0;
++
++ if (!pkg) {
++ ipkg_message(conf, IPKG_ERROR, "Null pkg\n");
++ return -EINVAL;
++ }
++ ipkg_message(conf, IPKG_INFO,
++ " creating %s.list file\n", pkg->name);
++ sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
++ if (!list_file_name) {
++ ipkg_message(conf, IPKG_ERROR, "Failed to alloc list_file_name\n");
++ return -ENOMEM;
++ }
++ ipkg_message(conf, IPKG_INFO,
++ " creating %s file for pkg %s\n", list_file_name, pkg->name);
++ data.stream = fopen(list_file_name, "w");
++ if (!data.stream) {
++ ipkg_message(conf, IPKG_ERROR, "Could not open %s for writing: %s\n",
++ list_file_name, strerror(errno));
++ return errno;
++ }
++ data.pkg = pkg;
++ data.conf = conf;
++ hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
++ fclose(data.stream);
++ free(list_file_name);
++
++ return err;
++}
++
++int pkg_write_changed_filelists(ipkg_conf_t *conf)
++{
++ pkg_vec_t *installed_pkgs = pkg_vec_alloc();
++ hash_table_t *pkg_hash = &conf->pkg_hash;
++ int i;
++ int err;
++ if (conf->noaction)
++ return 0;
++
++ ipkg_message(conf, IPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
++ pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
++ for (i = 0; i < installed_pkgs->len; i++) {
++ pkg_t *pkg = installed_pkgs->pkgs[i];
++ if (pkg->state_flag & SF_FILELIST_CHANGED) {
++ ipkg_message(conf, IPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
++ err = pkg_write_filelist(conf, pkg);
++ if (err)
++ ipkg_message(conf, IPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
++ }
++ }
++ return 0;
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_depends.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_depends.c
+--- busybox-1.2.0-orig/archival/libipkg/pkg_depends.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_depends.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,1033 @@
++/* pkg_depends.c - the itsy package management system
++
++ Steven M. Ayer
++
++ Copyright (C) 2002 Compaq Computer Corporation
++
++ 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.
++*/
++
++#include "ipkg.h"
++#include <errno.h>
++#include <ctype.h>
++
++#include "pkg.h"
++#include "ipkg_utils.h"
++#include "pkg_hash.h"
++#include "ipkg_message.h"
++#include "pkg_parse.h"
++#include "hash_table.h"
++
++static int parseDepends(compound_depend_t *compound_depend, hash_table_t * hash, char * depend_str);
++static depend_t * depend_init(void);
++static void depend_deinit(depend_t *d);
++static char ** add_unresolved_dep(pkg_t * pkg, char ** the_lost, int ref_ndx);
++static char ** merge_unresolved(char ** oldstuff, char ** newstuff);
++static int is_pkg_in_pkg_vec(pkg_vec_t * vec, pkg_t * pkg);
++
++static int pkg_installed_and_constraint_satisfied(pkg_t *pkg, void *cdata)
++{
++ depend_t *depend = (depend_t *)cdata;
++ if ((pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) && version_constraints_satisfied(depend, pkg))
++ return 1;
++ else
++ return 0;
++}
++
++static int pkg_constraint_satisfied(pkg_t *pkg, void *cdata)
++{
++ depend_t *depend = (depend_t *)cdata;
++#if 0
++ pkg_t * temp = pkg_new();
++ int comparison;
++ parseVersion(temp, depend->version);
++ comparison = pkg_compare_versions(pkg, temp);
++ free(temp);
++
++ fprintf(stderr, "%s: pkg=%s pkg->version=%s constraint=%p type=%d version=%s comparison=%d satisfied=%d\n",
++ __FUNCTION__, pkg->name, pkg->version,
++ depend, depend->constraint, depend->version,
++ comparison, version_constraints_satisfied(depend, pkg));
++#endif
++ if (version_constraints_satisfied(depend, pkg))
++ return 1;
++ else
++ return 0;
++}
++
++/* returns ndependences or negative error value */
++int pkg_hash_fetch_unsatisfied_dependencies(ipkg_conf_t *conf, pkg_t * pkg,
++ pkg_vec_t *unsatisfied, char *** unresolved)
++{
++ pkg_t * satisfier_entry_pkg;
++ register int i, j, k;
++ int count, found;
++ char ** the_lost;
++ abstract_pkg_t * ab_pkg;
++
++ /*
++ * this is a setup to check for redundant/cyclic dependency checks,
++ * which are marked at the abstract_pkg level
++ */
++ if (!(ab_pkg = pkg->parent)) {
++ fprintf(stderr, "%s:%d: something terribly wrong with pkg %s\n", __FUNCTION__, __LINE__, pkg->name);
++ *unresolved = NULL;
++ return 0;
++ }
++ if (ab_pkg->dependencies_checked) { /* avoid duplicate or cyclic checks */
++ *unresolved = NULL;
++ return 0;
++ } else {
++ ab_pkg->dependencies_checked = 1; /* mark it for subsequent visits */
++ }
++ /**/
++
++ count = pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count;
++ if (!count){
++ *unresolved = NULL;
++ return 0;
++ }
++
++ the_lost = NULL;
++
++ /* foreach dependency */
++ for (i = 0; i < count; i++) {
++ compound_depend_t * compound_depend = &pkg->depends[i];
++ depend_t ** possible_satisfiers = compound_depend->possibilities;;
++ found = 0;
++ satisfier_entry_pkg = NULL;
++
++ if (compound_depend->type == GREEDY_DEPEND) {
++ /* foreach possible satisfier */
++ for (j = 0; j < compound_depend->possibility_count; j++) {
++ /* foreach provided_by, which includes the abstract_pkg itself */
++ abstract_pkg_t *abpkg = possible_satisfiers[j]->pkg;
++ abstract_pkg_vec_t *ab_provider_vec = abpkg->provided_by;
++ int nposs = ab_provider_vec->len;
++ abstract_pkg_t **ab_providers = ab_provider_vec->pkgs;
++ int l;
++ for (l = 0; l < nposs; l++) {
++ pkg_vec_t *test_vec = ab_providers[l]->pkgs;
++ /* if no depends on this one, try the first package that Provides this one */
++ if (!test_vec){ /* no pkg_vec hooked up to the abstract_pkg! (need another feed?) */
++ continue;
++ }
++
++ /* cruise this possiblity's pkg_vec looking for an installed version */
++ for (k = 0; k < test_vec->len; k++) {
++ pkg_t *pkg_scout = test_vec->pkgs[k];
++ /* not installed, and not already known about? */
++ if ((pkg_scout->state_want != SW_INSTALL)
++ && !pkg_scout->parent->dependencies_checked
++ && !is_pkg_in_pkg_vec(unsatisfied, pkg_scout)) {
++ char ** newstuff = NULL;
++ int rc;
++ pkg_vec_t *tmp_vec = pkg_vec_alloc ();
++ /* check for not-already-installed dependencies */
++ rc = pkg_hash_fetch_unsatisfied_dependencies(conf,
++ pkg_scout,
++ tmp_vec,
++ &newstuff);
++ if (newstuff == NULL) {
++ int i;
++ int ok = 1;
++ for (i = 0; i < rc; i++) {
++ pkg_t *p = tmp_vec->pkgs[i];
++ if (p->state_want == SW_INSTALL)
++ continue;
++ ipkg_message(conf, IPKG_DEBUG, "not installing %s due to requirement for %s\n", pkg_scout->name, p->name);
++ ok = 0;
++ break;
++ }
++ pkg_vec_free (tmp_vec);
++ if (ok) {
++ /* mark this one for installation */
++ ipkg_message(conf, IPKG_NOTICE, "Adding satisfier for greedy dependence: %s\n", pkg_scout->name);
++ pkg_vec_insert(unsatisfied, pkg_scout);
++ }
++ } else {
++ ipkg_message(conf, IPKG_DEBUG, "not installing %s due to broken depends \n", pkg_scout->name);
++ free (newstuff);
++ }
++ }
++ }
++ }
++ }
++
++ continue;
++ }
++
++ /* foreach possible satisfier, look for installed package */
++ for (j = 0; j < compound_depend->possibility_count; j++) {
++ /* foreach provided_by, which includes the abstract_pkg itself */
++ depend_t *dependence_to_satisfy = possible_satisfiers[j];
++ abstract_pkg_t *satisfying_apkg = possible_satisfiers[j]->pkg;
++ pkg_t *satisfying_pkg =
++ pkg_hash_fetch_best_installation_candidate(conf, satisfying_apkg,
++ pkg_installed_and_constraint_satisfied,
++ dependence_to_satisfy, 1);
++ /* Being that I can't test constraing in pkg_hash, I will test it here */
++ if (satisfying_pkg != NULL) {
++ if (!pkg_installed_and_constraint_satisfied ( satisfying_pkg,dependence_to_satisfy)) {
++ satisfying_pkg = NULL;
++ }
++ }
++ ipkg_message(conf, IPKG_DEBUG, "%s:%d: satisfying_pkg=%p \n", __FILE__, __LINE__, satisfying_pkg);
++ if (satisfying_pkg != NULL) {
++ found = 1;
++ break;
++ }
++
++ }
++ /* if nothing installed matches, then look for uninstalled satisfier */
++ if (!found) {
++ /* foreach possible satisfier, look for installed package */
++ for (j = 0; j < compound_depend->possibility_count; j++) {
++ /* foreach provided_by, which includes the abstract_pkg itself */
++ depend_t *dependence_to_satisfy = possible_satisfiers[j];
++ abstract_pkg_t *satisfying_apkg = possible_satisfiers[j]->pkg;
++ pkg_t *satisfying_pkg =
++ pkg_hash_fetch_best_installation_candidate(conf, satisfying_apkg,
++ pkg_constraint_satisfied,
++ dependence_to_satisfy, 1);
++ /* Being that I can't test constraing in pkg_hash, I will test it here too */
++ if (satisfying_pkg != NULL) {
++ if (!pkg_constraint_satisfied ( satisfying_pkg,dependence_to_satisfy)) {
++ satisfying_pkg = NULL;
++ }
++ }
++
++ /* user request overrides package recommendation */
++ if (satisfying_pkg != NULL
++ && (compound_depend->type == RECOMMEND || compound_depend->type == SUGGEST)
++ && (satisfying_pkg->state_want == SW_DEINSTALL || satisfying_pkg->state_want == SW_PURGE)) {
++ ipkg_message (conf, IPKG_NOTICE, "%s: ignoring recommendation for %s at user request\n",
++ pkg->name, satisfying_pkg->name);
++ continue;
++ }
++
++ ipkg_message(conf, IPKG_DEBUG, "%s:%d: satisfying_pkg=%p\n", __FILE__, __LINE__, satisfying_pkg);
++ if (satisfying_pkg != NULL) {
++ satisfier_entry_pkg = satisfying_pkg;
++ break;
++ }
++ }
++ }
++
++ /* we didn't find one, add something to the unsatisfied vector */
++ if (!found) {
++ if (!satisfier_entry_pkg) {
++ /* failure to meet recommendations is not an error */
++ if (compound_depend->type != RECOMMEND && compound_depend->type != SUGGEST)
++ the_lost = add_unresolved_dep(pkg, the_lost, i);
++ else
++ ipkg_message (conf, IPKG_NOTICE, "%s: unsatisfied recommendation for %s\n",
++ pkg->name, compound_depend->possibilities[0]->pkg->name);
++ }
++ else {
++ if (compound_depend->type == SUGGEST) {
++ /* just mention it politely */
++ ipkg_message (conf, IPKG_NOTICE, "package %s suggests installing %s\n",
++ pkg->name, satisfier_entry_pkg->name);
++ } else {
++ char ** newstuff = NULL;
++
++ if (satisfier_entry_pkg != pkg &&
++ !is_pkg_in_pkg_vec(unsatisfied, satisfier_entry_pkg)) {
++ pkg_vec_insert(unsatisfied, satisfier_entry_pkg);
++ pkg_hash_fetch_unsatisfied_dependencies(conf,
++ satisfier_entry_pkg,
++ unsatisfied,
++ &newstuff);
++ the_lost = merge_unresolved(the_lost, newstuff);
++ }
++ }
++ }
++ }
++ }
++ *unresolved = the_lost;
++
++ return unsatisfied->len;
++}
++
++/*checking for conflicts !in replaces
++ If a packages conflicts with another but is also replacing it, I should not consider it a
++ really conflicts
++ returns 0 if conflicts <> replaces or 1 if conflicts == replaces
++*/
++int is_pkg_a_replaces(pkg_t *pkg_scout,pkg_t *pkg)
++{
++ int i ;
++ int replaces_count = pkg->replaces_count;
++ abstract_pkg_t **replaces;
++
++ if (pkg->replaces_count==0) // No replaces, it's surely a conflict
++ return 0;
++
++ replaces = pkg->replaces;
++
++ for (i = 0; i < replaces_count; i++) {
++ if (strcmp(pkg_scout->name,pkg->replaces[i]->name)==0) { // Found
++ ipkg_message(NULL, IPKG_DEBUG2, "Seems I've found a replace %s %s \n",pkg_scout->name,pkg->replaces[i]->name);
++ return 1;
++ }
++ }
++ return 0;
++
++}
++
++
++/* Abhaya: added support for conflicts */
++pkg_vec_t * pkg_hash_fetch_conflicts(hash_table_t * hash, pkg_t * pkg)
++{
++ pkg_vec_t * installed_conflicts, * test_vec;
++ compound_depend_t * conflicts;
++ depend_t ** possible_satisfiers;
++ depend_t * possible_satisfier;
++ register int i, j, k;
++ int count;
++ abstract_pkg_t * ab_pkg;
++ pkg_t **pkg_scouts;
++ pkg_t *pkg_scout;
++
++ /*
++ * this is a setup to check for redundant/cyclic dependency checks,
++ * which are marked at the abstract_pkg level
++ */
++ if(!(ab_pkg = pkg->parent)){
++ fprintf(stderr, "dependency check error. pkg %s isn't in hash table\n", pkg->name);
++ return (pkg_vec_t *)NULL;
++ }
++
++ conflicts = pkg->conflicts;
++ if(!conflicts){
++ return (pkg_vec_t *)NULL;
++ }
++ installed_conflicts = pkg_vec_alloc();
++
++ count = pkg->conflicts_count;
++
++
++
++ /* foreach conflict */
++ for(i = 0; i < pkg->conflicts_count; i++){
++
++ possible_satisfiers = conflicts->possibilities;
++
++ /* foreach possible satisfier */
++ for(j = 0; j < conflicts->possibility_count; j++){
++ possible_satisfier = possible_satisfiers[j];
++ if (!possible_satisfier)
++ fprintf(stderr, "%s:%d: possible_satisfier is null\n", __FUNCTION__, __LINE__);
++ if (!possible_satisfier->pkg)
++ fprintf(stderr, "%s:%d: possible_satisfier->pkg is null\n", __FUNCTION__, __LINE__);
++ test_vec = possible_satisfier->pkg->pkgs;
++ if (test_vec) {
++ /* pkg_vec found, it is an actual package conflict
++ * cruise this possiblity's pkg_vec looking for an installed version */
++ pkg_scouts = test_vec->pkgs;
++ for(k = 0; k < test_vec->len; k++){
++ pkg_scout = pkg_scouts[k];
++ if (!pkg_scout) {
++ fprintf(stderr, "%s: null pkg scout\n", __FUNCTION__);
++ continue;
++ }
++ if ((pkg_scout->state_status == SS_INSTALLED || pkg_scout->state_want == SW_INSTALL) &&
++ version_constraints_satisfied(possible_satisfier, pkg_scout) && !is_pkg_a_replaces(pkg_scout,pkg)){
++ if (!is_pkg_in_pkg_vec(installed_conflicts, pkg_scout)){
++ pkg_vec_insert(installed_conflicts, pkg_scout);
++ }
++ }
++ }
++ }
++ }
++ conflicts++;
++ }
++
++ if (installed_conflicts->len)
++ return installed_conflicts;
++ pkg_vec_free(installed_conflicts);
++ return (pkg_vec_t *)NULL;
++}
++
++int version_constraints_satisfied(depend_t * depends, pkg_t * pkg)
++{
++ pkg_t * temp;
++ int comparison;
++
++ if(depends->constraint == NONE)
++ return 1;
++
++ temp = pkg_new();
++
++ parseVersion(temp, depends->version);
++
++ comparison = pkg_compare_versions(pkg, temp);
++
++ free(temp);
++
++ if((depends->constraint == EARLIER) &&
++ (comparison < 0))
++ return 1;
++ else if((depends->constraint == LATER) &&
++ (comparison > 0))
++ return 1;
++ else if(comparison == 0)
++ return 1;
++ else if((depends->constraint == LATER_EQUAL) &&
++ (comparison >= 0))
++ return 1;
++ else if((depends->constraint == EARLIER_EQUAL) &&
++ (comparison <= 0))
++ return 1;
++
++ return 0;
++}
++
++int pkg_dependence_satisfiable(ipkg_conf_t *conf, depend_t *depend)
++{
++ abstract_pkg_t *apkg = depend->pkg;
++ abstract_pkg_vec_t *provider_apkgs = apkg->provided_by;
++ int n_providers = provider_apkgs->len;
++ abstract_pkg_t **apkgs = provider_apkgs->pkgs;
++ pkg_vec_t *pkg_vec;
++ int n_pkgs ;
++ int i;
++ int j;
++
++ for (i = 0; i < n_providers; i++) {
++ abstract_pkg_t *papkg = apkgs[i];
++ pkg_vec = papkg->pkgs;
++ if (pkg_vec) {
++ n_pkgs = pkg_vec->len;
++ for (j = 0; j < n_pkgs; j++) {
++ pkg_t *pkg = pkg_vec->pkgs[j];
++ if (version_constraints_satisfied(depend, pkg)) {
++ return 1;
++ }
++ }
++ }
++ }
++ return 0;
++}
++
++int pkg_dependence_satisfied(ipkg_conf_t *conf, depend_t *depend)
++{
++ abstract_pkg_t *apkg = depend->pkg;
++ abstract_pkg_vec_t *provider_apkgs = apkg->provided_by;
++ int n_providers = provider_apkgs->len;
++ abstract_pkg_t **apkgs = provider_apkgs->pkgs;
++ int i;
++ int n_pkgs;
++ int j;
++
++ for (i = 0; i < n_providers; i++) {
++ abstract_pkg_t *papkg = apkgs[i];
++ pkg_vec_t *pkg_vec = papkg->pkgs;
++ if (pkg_vec) {
++ n_pkgs = pkg_vec->len;
++ for (j = 0; j < n_pkgs; j++) {
++ pkg_t *pkg = pkg_vec->pkgs[j];
++ if (version_constraints_satisfied(depend, pkg)) {
++ if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED)
++ return 1;
++ }
++ }
++ }
++ }
++ return 0;
++}
++
++static int is_pkg_in_pkg_vec(pkg_vec_t * vec, pkg_t * pkg)
++{
++ register int i;
++ pkg_t ** pkgs = vec->pkgs;
++
++ for(i = 0; i < vec->len; i++)
++ if((strcmp(pkg->name, (*(pkgs + i))->name) == 0)
++ && (pkg_compare_versions(pkg, *(pkgs + i)) == 0)
++ && (strcmp(pkg->architecture, (*(pkgs + i))->architecture) == 0))
++ return 1;
++ return 0;
++}
++
++
++#ifdef DeadCode
++/**
++ * pkg_has_common_provides returns 1 if pkg and replacee both provide
++ * the same abstract package and 0 otherwise.
++ */
++int pkg_has_common_provides(pkg_t *pkg, pkg_t *replacee)
++{
++ abstract_pkg_t **provides = pkg->provides;
++ int provides_count = pkg->provides_count;
++ abstract_pkg_t **replacee_provides = replacee->provides;
++ int replacee_provides_count = replacee->provides_count;
++ int i, j;
++ for (i = 0; i < provides_count; i++) {
++ abstract_pkg_t *apkg = provides[i];
++ for (j = 0; j < replacee_provides_count; j++) {
++ abstract_pkg_t *replacee_apkg = replacee_provides[i];
++ if (apkg == replacee_apkg)
++ return 1;
++ }
++ }
++ return 0;
++}
++#endif
++
++/**
++ * pkg_provides_abstract returns 1 if pkg->provides contains providee
++ * and 0 otherwise.
++ */
++int pkg_provides_abstract(pkg_t *pkg, abstract_pkg_t *providee)
++{
++ abstract_pkg_t **provides = pkg->provides;
++ int provides_count = pkg->provides_count;
++ int i;
++ for (i = 0; i < provides_count; i++) {
++ if (provides[i] == providee)
++ return 1;
++ }
++ return 0;
++}
++
++/**
++ * pkg_replaces returns 1 if pkg->replaces contains one of replacee's provides and 0
++ * otherwise.
++ */
++int pkg_replaces(pkg_t *pkg, pkg_t *replacee)
++{
++ abstract_pkg_t **replaces = pkg->replaces;
++ int replaces_count = pkg->replaces_count;
++ /* abstract_pkg_t **replacee_provides = pkg->provides;
++ int replacee_provides_count = pkg->provides_count; */
++ int i, j;
++ for (i = 0; i < replaces_count; i++) {
++ abstract_pkg_t *abstract_replacee = replaces[i];
++ for (j = 0; j < replaces_count; j++) {
++ /* ipkg_message(NULL, IPKG_DEBUG2, "Searching pkg-name %s repprovname %s absrepname %s \n",
++ pkg->name,replacee->provides[j]->name, abstract_replacee->name); */
++ if (replacee->provides[j] == abstract_replacee)
++ return 1;
++ }
++ }
++ return 0;
++}
++
++
++/**
++ * pkg_conflicts_abstract returns 1 if pkg->conflicts contains conflictee and 0
++ * otherwise.
++ */
++int pkg_conflicts_abstract(pkg_t *pkg, abstract_pkg_t *conflictee)
++{
++ compound_depend_t *conflicts = pkg->conflicts;
++ int conflicts_count = pkg->conflicts_count;
++ int i, j;
++ for (i = 0; i < conflicts_count; i++) {
++ int possibility_count = conflicts[i].possibility_count;
++ struct depend **possibilities = conflicts[i].possibilities;
++ for (j = 0; j < possibility_count; j++) {
++ if (possibilities[j]->pkg == conflictee) {
++ return 1;
++ }
++ }
++ }
++ return 0;
++}
++
++/**
++ * pkg_conflicts returns 1 if pkg->conflicts contains one of
++ * conflictee's provides and 0 otherwise.
++ */
++int pkg_conflicts(pkg_t *pkg, pkg_t *conflictee)
++{
++ compound_depend_t *conflicts = pkg->conflicts;
++ int conflicts_count = pkg->conflicts_count;
++ abstract_pkg_t **conflictee_provides = conflictee->provides;
++ int conflictee_provides_count = conflictee->provides_count;
++ int i, j, k;
++ int possibility_count;
++ struct depend **possibilities;
++ abstract_pkg_t *possibility ;
++
++ for (i = 0; i < conflicts_count; i++) {
++ possibility_count = conflicts[i].possibility_count;
++ possibilities = conflicts[i].possibilities;
++ for (j = 0; j < possibility_count; j++) {
++ possibility = possibilities[j]->pkg;
++ for (k = 0; k < conflictee_provides_count; k++) {
++ if (possibility == conflictee_provides[k]) {
++ return 1;
++ }
++ }
++ }
++ }
++ return 0;
++}
++
++static char ** merge_unresolved(char ** oldstuff, char ** newstuff)
++{
++ int oldlen = 0, newlen = 0;
++ char ** result;
++ register int i, j;
++
++ if(!newstuff)
++ return oldstuff;
++
++ while(oldstuff && oldstuff[oldlen]) oldlen++;
++ while(newstuff && newstuff[newlen]) newlen++;
++
++ result = (char **)realloc(oldstuff, sizeof(char *) * (oldlen + newlen + 1));
++ if (result == NULL) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++
++ for(i = oldlen, j = 0; i < (oldlen + newlen); i++, j++)
++ *(result + i) = *(newstuff + j);
++
++ *(result + i) = NULL;
++
++ return result;
++}
++
++/*
++ * a kinda kludgy way to back out depends str from two different arrays (reg'l'r 'n pre)
++ * this is null terminated, no count is carried around
++ */
++char ** add_unresolved_dep(pkg_t * pkg, char ** the_lost, int ref_ndx)
++{
++ int count;
++ char ** resized;
++ char *depend_str = pkg_depend_str(pkg, ref_ndx);
++
++ count = 0;
++ while(the_lost && the_lost[count]) count++;
++
++ count++; /* need one to hold the null */
++ resized = (char **)realloc(the_lost, sizeof(char *) * (count + 1));
++ if (resized == NULL) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ resized[count - 1] = strdup(depend_str);
++ resized[count] = NULL;
++
++ return resized;
++}
++
++void printDepends(pkg_t * pkg)
++{
++ register int i, j;
++ compound_depend_t * depend;
++ int count;
++
++ count = pkg->pre_depends_count + pkg->depends_count;
++
++ depend = pkg->depends;
++ if(!depend){
++ fprintf(stderr, "Depends pointer is NULL\n");
++ return;
++ }
++ for(i = 0; i < count; i++){
++ fprintf(stderr, "%s has %d possibilities:\n",
++ (depend->type == GREEDY_DEPEND) ? "Greedy-Depend" : ((depend->type == DEPEND) ? "Depend" : "Pre-Depend"),
++ depend->possibility_count);
++ for(j = 0; j < depend->possibility_count; j++)
++ fprintf(stderr, "\t%s version %s (%d)\n",
++ depend->possibilities[j]->pkg->name,
++ depend->possibilities[j]->version,
++ depend->possibilities[j]->constraint);
++ depend++;
++ }
++}
++
++int buildProvides(hash_table_t * hash, abstract_pkg_t * ab_pkg, pkg_t * pkg)
++{
++ register int i, j;
++
++ /* every pkg provides itself */
++ abstract_pkg_vec_insert(ab_pkg->provided_by, ab_pkg);
++
++ if (!pkg->provides_count)
++ return 0;
++
++ pkg->provides = (abstract_pkg_t **)malloc(sizeof(abstract_pkg_t *) * (pkg->provides_count + 1));
++ if (pkg->provides == NULL) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return -1 ;
++ }
++ pkg->provides[0] = ab_pkg;
++
++ // if (strcmp(ab_pkg->name, pkg->name))
++ // fprintf(stderr, __FUNCTION__ ": ab_pkg=%s pkg=%s\n", ab_pkg->name, pkg->name);
++
++ for(i = 0; i < pkg->provides_count; i++){
++ abstract_pkg_t *provided_abpkg = ensure_abstract_pkg_by_name(hash, pkg->provides_str[i]);
++
++ pkg->provides[i+1] = provided_abpkg;
++
++ j = 0;
++ abstract_pkg_vec_insert(provided_abpkg->provided_by, ab_pkg);
++ }
++ return 0;
++}
++
++/* Abhaya: added conflicts support */
++int buildConflicts(hash_table_t * hash, abstract_pkg_t * ab_pkg, pkg_t * pkg)
++{
++ register int i;
++ compound_depend_t * conflicts;
++
++ if (!pkg->conflicts_count)
++ return 0;
++
++ conflicts = pkg->conflicts = malloc(sizeof(compound_depend_t) *
++ pkg->conflicts_count);
++ if (conflicts == NULL) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return -1;
++ }
++ for (i = 0; i < pkg->conflicts_count; i++) {
++ conflicts->type = CONFLICTS;
++ parseDepends(conflicts, hash,
++ pkg->conflicts_str[i]);
++#if 0
++ for (j = 0; j < conflicts->possibility_count; j++) {
++ depend_t *possibility = conflicts->possibilities[j];
++ abstract_pkg_t *conflicting_apkg = possibility->pkg;
++ pkg_add_conflict_pair(ab_pkg, conflicting_apkg);
++ }
++#endif
++ conflicts++;
++ }
++ return 0;
++}
++
++int buildReplaces(hash_table_t * hash, abstract_pkg_t * ab_pkg, pkg_t * pkg)
++{
++ register int i, j;
++
++ if (!pkg->replaces_count)
++ return 0;
++
++ pkg->replaces = (abstract_pkg_t **)malloc(sizeof(abstract_pkg_t *) * pkg->replaces_count);
++ if (pkg->replaces == NULL) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return -1;
++ }
++
++ // if (strcmp(ab_pkg->name, pkg->name))
++ // fprintf(stderr, __FUNCTION__ ": ab_pkg=%s pkg=%s\n", ab_pkg->name, pkg->name);
++
++ for(i = 0; i < pkg->replaces_count; i++){
++ abstract_pkg_t *old_abpkg = ensure_abstract_pkg_by_name(hash, pkg->replaces_str[i]);
++
++ pkg->replaces[i] = old_abpkg;
++
++ j = 0;
++ if (!old_abpkg->replaced_by)
++ old_abpkg->replaced_by = abstract_pkg_vec_alloc();
++ if ( old_abpkg->replaced_by == NULL ){
++ return -1;
++ }
++ /* if a package pkg both replaces and conflicts old_abpkg,
++ * then add it to the replaced_by vector so that old_abpkg
++ * will be upgraded to ab_pkg automatically */
++ if (pkg_conflicts_abstract(pkg, old_abpkg))
++ abstract_pkg_vec_insert(old_abpkg->replaced_by, ab_pkg);
++ }
++ return 0;
++}
++
++int buildDepends(hash_table_t * hash, pkg_t * pkg)
++{
++ int count;
++ register int i;
++ compound_depend_t * depends;
++
++ if(!(count = pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count))
++ return 0;
++
++ if (0 && pkg->pre_depends_count)
++ fprintf(stderr, "pkg=%s pre_depends_count=%d depends_count=%d\n",
++ pkg->name, pkg->pre_depends_count, pkg->depends_count);
++ depends = pkg->depends = malloc(sizeof(compound_depend_t) * count);
++ if (depends == NULL) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return -1;
++ }
++
++
++ for(i = 0; i < pkg->pre_depends_count; i++){
++ parseDepends(depends, hash, pkg->pre_depends_str[i]);
++ if (0 && pkg->pre_depends_count)
++ fprintf(stderr, " pre_depends_str=%s depends=%p possibility_count=%x\n",
++ pkg->pre_depends_str[i], depends, depends->possibility_count);
++ depends->type = PREDEPEND;
++ depends++;
++ }
++
++ for(i = 0; i < pkg->recommends_count; i++){
++ parseDepends(depends, hash, pkg->recommends_str[i]);
++ if (0 && pkg->recommends_count)
++ fprintf(stderr, " recommends_str=%s depends=%p possibility_count=%x\n",
++ pkg->recommends_str[i], depends, depends->possibility_count);
++ depends->type = RECOMMEND;
++ depends++;
++ }
++
++ for(i = 0; i < pkg->suggests_count; i++){
++ parseDepends(depends, hash, pkg->suggests_str[i]);
++ if (0 && pkg->suggests_count)
++ fprintf(stderr, " suggests_str=%s depends=%p possibility_count=%x\n",
++ pkg->suggests_str[i], depends, depends->possibility_count);
++ depends->type = SUGGEST;
++ depends++;
++ }
++
++ for(i = 0; i < pkg->depends_count; i++){
++ parseDepends(depends, hash, pkg->depends_str[i]);
++ if (0 && pkg->depends_count)
++ fprintf(stderr, " depends_str=%s depends=%p possibility_count=%x\n",
++ pkg->depends_str[i], depends, depends->possibility_count);
++ depends++;
++ }
++ return 0;
++}
++
++/*
++ * pkg_depend_string: returns the depends string specified by index.
++ * All 4 kinds of dependences: dependence, pre-dependence, recommend, and suggest are number starting from 0.
++ * [0,npredepends) -> returns pre_depends_str[index]
++ * [npredepends,npredepends+nrecommends) -> returns recommends_str[index]
++ * [npredepends+nrecommends,npredepends+nrecommends+nsuggests) -> returns recommends_str[index]
++ * [npredepends+nrecommends+nsuggests,npredepends+nrecommends+nsuggests+ndepends) -> returns depends_str[index]
++ */
++char *pkg_depend_str(pkg_t *pkg, int index)
++{
++ if (index < pkg->pre_depends_count) {
++ return pkg->pre_depends_str[index];
++ }
++ index -= pkg->pre_depends_count;
++
++ if (index < pkg->recommends_count) {
++ return pkg->recommends_str[index];
++ }
++ index -= pkg->recommends_count;
++
++ if (index < pkg->suggests_count) {
++ return pkg->suggests_str[index];
++ }
++ index -= pkg->suggests_count;
++
++ if (index < pkg->depends_count) {
++ return pkg->depends_str[index];
++ }
++ fprintf(stderr, "pkg_depend_str: index %d out of range for pkg=%s\n", index, pkg->name);
++ return NULL;
++}
++
++void freeDepends(pkg_t *pkg)
++{
++ int i;
++
++ if (pkg == NULL || pkg->depends == NULL) {
++ return;
++ }
++
++ fprintf(stderr, "Freeing depends=%p\n", pkg->depends);
++ for (i=0; i < pkg->depends->possibility_count; i++) {
++ depend_deinit(pkg->depends->possibilities[i]);
++ }
++ free(pkg->depends->possibilities);
++ free(pkg->depends);
++ pkg->depends = NULL;
++}
++
++void buildDependedUponBy(pkg_t * pkg, abstract_pkg_t * ab_pkg)
++{
++ compound_depend_t * depends;
++ int count, othercount;
++ register int i, j;
++ abstract_pkg_t * ab_depend;
++ abstract_pkg_t ** temp;
++
++ count = pkg->pre_depends_count + pkg->depends_count;
++ depends = pkg->depends;
++
++ if (0 && pkg->pre_depends_count)
++ fprintf(stderr, "pkg=%s pre_depends_count=%d depends_count=%d\n",
++ pkg->name, pkg->pre_depends_count, pkg->depends_count);
++ for (i = 0; i < count; i++) {
++ if (0 && pkg->pre_depends_count)
++ fprintf(stderr, " i=%d possibility_count=%x depends=%p\n", i, depends->possibility_count, depends);
++ for (j = 0; j < depends->possibility_count; j++){
++ ab_depend = depends->possibilities[j]->pkg;
++ if(!ab_depend->depended_upon_by)
++ ab_depend->depended_upon_by = (abstract_pkg_t **)calloc(1, sizeof(abstract_pkg_t *));
++
++ temp = ab_depend->depended_upon_by;
++ othercount = 1;
++ while(*temp){
++ temp++;
++ othercount++;
++ }
++ *temp = ab_pkg;
++
++ ab_depend->depended_upon_by = (abstract_pkg_t **)realloc(ab_depend->depended_upon_by,
++ (othercount + 1) * sizeof(abstract_pkg_t *));
++ /* the array may have moved */
++ temp = ab_depend->depended_upon_by + othercount;
++ *temp = NULL;
++ }
++ depends++;
++ }
++}
++
++static depend_t * depend_init(void)
++{
++ depend_t * d = (depend_t *)malloc(sizeof(depend_t));
++ if ( d==NULL ){
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ d->constraint = NONE;
++ d->version = NULL;
++ d->pkg = NULL;
++
++ return d;
++}
++
++static void depend_deinit(depend_t *d)
++{
++ free(d);
++}
++
++static int parseDepends(compound_depend_t *compound_depend,
++ hash_table_t * hash, char * depend_str)
++{
++ char * pkg_name, buffer[2048];
++ int num_of_ors = 0;
++ register int i;
++ register char * src, * dest;
++ depend_t ** possibilities;
++
++ /* first count the number of ored possibilities for satisfying dependency */
++ src = depend_str;
++ while(*src)
++ if(*src++ == '|')
++ num_of_ors++;
++
++ compound_depend->type = DEPEND;
++
++ compound_depend->possibility_count = num_of_ors + 1;
++ possibilities = (depend_t **)malloc(sizeof(depend_t *) * (num_of_ors + 1));
++ if (!possibilities)
++ return -ENOMEM;
++ compound_depend->possibilities = possibilities;
++
++ src = depend_str;
++ for(i = 0; i < num_of_ors + 1; i++){
++ possibilities[i] = depend_init();
++ if (!possibilities[i])
++ return -ENOMEM;
++ /* gobble up just the name first */
++ dest = buffer;
++ while(*src &&
++ !isspace(*src) &&
++ (*src != '(') &&
++ (*src != '*') &&
++ (*src != '|'))
++ *dest++ = *src++;
++ *dest = '\0';
++ pkg_name = trim_alloc(buffer);
++ if (pkg_name == NULL )
++ return -ENOMEM;
++
++ /* now look at possible version info */
++
++ /* skip to next chars */
++ if(isspace(*src))
++ while(*src && isspace(*src)) src++;
++
++ /* extract constraint and version */
++ if(*src == '('){
++ src++;
++ if(!strncmp(src, "<<", 2)){
++ possibilities[i]->constraint = EARLIER;
++ src += 2;
++ }
++ else if(!strncmp(src, "<=", 2)){
++ possibilities[i]->constraint = EARLIER_EQUAL;
++ src += 2;
++ }
++ else if(!strncmp(src, ">=", 2)){
++ possibilities[i]->constraint = LATER_EQUAL;
++ src += 2;
++ }
++ else if(!strncmp(src, ">>", 2)){
++ possibilities[i]->constraint = LATER;
++ src += 2;
++ }
++ else if(!strncmp(src, "=", 1)){
++ possibilities[i]->constraint = EQUAL;
++ src++;
++ }
++ /* should these be here to support deprecated designations; dpkg does */
++ else if(!strncmp(src, "<", 1)){
++ possibilities[i]->constraint = EARLIER_EQUAL;
++ src++;
++ }
++ else if(!strncmp(src, ">", 1)){
++ possibilities[i]->constraint = LATER_EQUAL;
++ src++;
++ }
++
++ /* now we have any constraint, pass space to version string */
++ while(isspace(*src)) src++;
++
++ /* this would be the version string */
++ dest = buffer;
++ while(*src && *src != ')')
++ *dest++ = *src++;
++ *dest = '\0';
++
++ possibilities[i]->version = trim_alloc(buffer);
++ /* fprintf(stderr, "let's print the depends version string:");
++ fprintf(stderr, "version %s\n", possibilities[i]->version);*/
++ if (possibilities[i]->version == NULL )
++ return -ENOMEM;
++
++
++ }
++ /* hook up the dependency to its abstract pkg */
++ possibilities[i]->pkg = ensure_abstract_pkg_by_name(hash, pkg_name);
++
++ free(pkg_name);
++
++ /* now get past the ) and any possible | chars */
++ while(*src &&
++ (isspace(*src) ||
++ (*src == ')') ||
++ (*src == '|')))
++ src++;
++ if (*src == '*')
++ {
++ compound_depend->type = GREEDY_DEPEND;
++ src++;
++ }
++ }
++
++ return 0;
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_depends.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_depends.h
+--- busybox-1.2.0-orig/archival/libipkg/pkg_depends.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_depends.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,105 @@
++/* pkg_depends.h - the itsy package management system
++
++ Steven M. Ayer
++
++ Copyright (C) 2002 Compaq Computer Corporation
++
++ 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.
++*/
++
++#ifndef PKG_DEPENDS_H
++#define PKG_DEPENDS_H
++
++#include "pkg.h"
++#include "pkg_hash.h"
++
++enum depend_type {
++ PREDEPEND,
++ DEPEND,
++ CONFLICTS,
++ GREEDY_DEPEND,
++ RECOMMEND,
++ SUGGEST
++};
++typedef enum depend_type depend_type_t;
++
++enum version_constraint {
++ NONE,
++ EARLIER,
++ EARLIER_EQUAL,
++ EQUAL,
++ LATER_EQUAL,
++ LATER
++};
++typedef enum version_constraint version_constraint_t;
++
++struct depend{
++ version_constraint_t constraint;
++ char * version;
++ abstract_pkg_t * pkg;
++};
++typedef struct depend depend_t;
++
++struct compound_depend{
++ depend_type_t type;
++ int possibility_count;
++ struct depend ** possibilities;
++};
++typedef struct compound_depend compound_depend_t;
++
++#include "hash_table.h"
++
++int buildProvides(hash_table_t * hash, abstract_pkg_t * ab_pkg, pkg_t * pkg);
++int buildConflicts(hash_table_t * hash, abstract_pkg_t * ab_pkg, pkg_t * pkg);
++int buildReplaces(hash_table_t * hash, abstract_pkg_t * ab_pkg, pkg_t * pkg);
++int buildDepends(hash_table_t * hash, pkg_t * pkg);
++
++/**
++ * pkg_has_common_provides returns 1 if pkg and replacee both provide
++ * the same abstract package and 0 otherwise.
++ */
++int pkg_has_common_provides(pkg_t *pkg, pkg_t *replacee);
++
++/**
++ * pkg_provides returns 1 if pkg->provides contains providee and 0
++ * otherwise.
++ */
++int pkg_provides_abstract(pkg_t *pkg, abstract_pkg_t *providee);
++
++/**
++ * pkg_replaces returns 1 if pkg->replaces contains one of replacee's provides and 0
++ * otherwise.
++ */
++int pkg_replaces(pkg_t *pkg, pkg_t *replacee);
++
++/**
++ * pkg_conflicts_abstract returns 1 if pkg->conflicts contains conflictee provides and 0
++ * otherwise.
++ */
++int pkg_conflicts_abstract(pkg_t *pkg, abstract_pkg_t *conflicts);
++
++/**
++ * pkg_conflicts returns 1 if pkg->conflicts contains one of conflictee's provides and 0
++ * otherwise.
++ */
++int pkg_conflicts(pkg_t *pkg, pkg_t *conflicts);
++
++char *pkg_depend_str(pkg_t *pkg, int index);
++void buildDependedUponBy(pkg_t * pkg, abstract_pkg_t * ab_pkg);
++void freeDepends(pkg_t *pkg);
++void printDepends(pkg_t * pkg);
++int version_constraints_satisfied(depend_t * depends, pkg_t * pkg);
++int pkg_hash_fetch_unsatisfied_dependencies(ipkg_conf_t *conf, pkg_t * pkg, pkg_vec_t *depends, char *** unresolved);
++pkg_vec_t * pkg_hash_fetch_conflicts(hash_table_t * hash, pkg_t * pkg);
++int pkg_dependence_satisfiable(ipkg_conf_t *conf, depend_t *depend);
++int pkg_dependence_satisfied(ipkg_conf_t *conf, depend_t *depend);
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_dest.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_dest.c
+--- busybox-1.2.0-orig/archival/libipkg/pkg_dest.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_dest.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,92 @@
++/* pkg_dest.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++
++#include "pkg_dest.h"
++#include "file_util.h"
++#include "str_util.h"
++#include "sprintf_alloc.h"
++
++int pkg_dest_init(pkg_dest_t *dest, const char *name, const char *root_dir,const char * lists_dir)
++{
++ dest->name = strdup(name);
++
++ /* Guarantee that dest->root_dir ends with a '/' */
++ if (str_ends_with(root_dir, "/")) {
++ dest->root_dir = strdup(root_dir);
++ } else {
++ sprintf_alloc(&dest->root_dir, "%s/", root_dir);
++ }
++ file_mkdir_hier(dest->root_dir, 0755);
++
++ sprintf_alloc(&dest->ipkg_dir, "%s%s",
++ dest->root_dir, IPKG_STATE_DIR_PREFIX);
++ file_mkdir_hier(dest->ipkg_dir, 0755);
++
++ if (str_starts_with (lists_dir, "/"))
++ sprintf_alloc(&dest->lists_dir, "%s", lists_dir);
++ else
++ sprintf_alloc(&dest->lists_dir, "/%s", lists_dir);
++
++ file_mkdir_hier(dest->lists_dir, 0755);
++
++ sprintf_alloc(&dest->info_dir, "%s/%s",
++ dest->ipkg_dir, IPKG_INFO_DIR_SUFFIX);
++ file_mkdir_hier(dest->info_dir, 0755);
++
++ sprintf_alloc(&dest->status_file_name, "%s/%s",
++ dest->ipkg_dir, IPKG_STATUS_FILE_SUFFIX);
++
++ sprintf_alloc(&dest->status_file_tmp_name, "%s/%s.tmp",
++ dest->ipkg_dir, IPKG_STATUS_FILE_SUFFIX);
++
++ dest->status_file = NULL;
++
++ return 0;
++}
++
++void pkg_dest_deinit(pkg_dest_t *dest)
++{
++ free(dest->name);
++ dest->name = NULL;
++
++ free(dest->root_dir);
++ dest->root_dir = NULL;
++
++ free(dest->ipkg_dir);
++ dest->ipkg_dir = NULL;
++
++ free(dest->lists_dir);
++ dest->lists_dir = NULL;
++
++ free(dest->info_dir);
++ dest->info_dir = NULL;
++
++ free(dest->status_file_name);
++ dest->status_file_name = NULL;
++
++ free(dest->status_file_tmp_name);
++ dest->status_file_tmp_name = NULL;
++
++ if (dest->status_file) {
++ fclose(dest->status_file);
++ }
++ dest->status_file = NULL;
++
++ dest->root_dir = NULL;
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_dest.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_dest.h
+--- busybox-1.2.0-orig/archival/libipkg/pkg_dest.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_dest.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,38 @@
++/* pkg_dest.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef PKG_DEST_H
++#define PKG_DEST_H
++
++typedef struct pkg_dest pkg_dest_t;
++struct pkg_dest
++{
++ char *name;
++ char *root_dir;
++ char *ipkg_dir;
++ char *lists_dir;
++ char *info_dir;
++ char *status_file_name;
++ char *status_file_tmp_name;
++ FILE *status_file;
++};
++
++int pkg_dest_init(pkg_dest_t *dest, const char *name, const char *root_dir,const char *lists_dir);
++void pkg_dest_deinit(pkg_dest_t *dest);
++
++#endif
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_dest_list.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_dest_list.c
+--- busybox-1.2.0-orig/archival/libipkg/pkg_dest_list.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_dest_list.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,85 @@
++/* pkg_dest_list.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++
++#include "pkg_dest.h"
++#include "void_list.h"
++#include "pkg_dest_list.h"
++
++int pkg_dest_list_elt_init(pkg_dest_list_elt_t *elt, pkg_dest_t *data)
++{
++ return void_list_elt_init((void_list_elt_t *) elt, data);
++}
++
++void pkg_dest_list_elt_deinit(pkg_dest_list_elt_t *elt)
++{
++ void_list_elt_deinit((void_list_elt_t *) elt);
++}
++
++int pkg_dest_list_init(pkg_dest_list_t *list)
++{
++ return void_list_init((void_list_t *) list);
++}
++
++void pkg_dest_list_deinit(pkg_dest_list_t *list)
++{
++ pkg_dest_list_elt_t *iter;
++ pkg_dest_t *pkg_dest;
++
++ for (iter = list->head; iter; iter = iter->next) {
++ pkg_dest = iter->data;
++ pkg_dest_deinit(pkg_dest);
++
++ /* malloced in pkg_dest_list_append */
++ free(pkg_dest);
++ iter->data = NULL;
++ }
++ void_list_deinit((void_list_t *) list);
++}
++
++pkg_dest_t *pkg_dest_list_append(pkg_dest_list_t *list, const char *name,
++ const char *root_dir,const char *lists_dir)
++{
++ int err;
++ pkg_dest_t *pkg_dest;
++
++ /* freed in plg_dest_list_deinit */
++ pkg_dest = malloc(sizeof(pkg_dest_t));
++ if (pkg_dest == NULL) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++
++ pkg_dest_init(pkg_dest, name, root_dir,lists_dir);
++ err = void_list_append((void_list_t *) list, pkg_dest);
++ if (err) {
++ return NULL;
++ }
++
++ return pkg_dest;
++}
++
++int pkg_dest_list_push(pkg_dest_list_t *list, pkg_dest_t *data)
++{
++ return void_list_push((void_list_t *) list, data);
++}
++
++pkg_dest_list_elt_t *pkg_dest_list_pop(pkg_dest_list_t *list)
++{
++ return (pkg_dest_list_elt_t *) void_list_pop((void_list_t *) list);
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_dest_list.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_dest_list.h
+--- busybox-1.2.0-orig/archival/libipkg/pkg_dest_list.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_dest_list.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,50 @@
++/* pkg_dest_list.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef PKG_DEST_LIST_H
++#define PKG_DEST_LIST_H
++
++#include "pkg_dest.h"
++
++typedef struct pkg_dest_list_elt pkg_dest_list_elt_t;
++struct pkg_dest_list_elt
++{
++ pkg_dest_list_elt_t *next;
++ pkg_dest_t *data;
++};
++
++typedef struct pkg_dest_list pkg_dest_list_t;
++struct pkg_dest_list
++{
++ pkg_dest_list_elt_t pre_head;
++ pkg_dest_list_elt_t *head;
++ pkg_dest_list_elt_t *tail;
++};
++
++int pkg_dest_list_elt_init(pkg_dest_list_elt_t *elt, pkg_dest_t *data);
++void pkg_dest_list_elt_deinit(pkg_dest_list_elt_t *elt);
++
++int pkg_dest_list_init(pkg_dest_list_t *list);
++void pkg_dest_list_deinit(pkg_dest_list_t *list);
++
++pkg_dest_t *pkg_dest_list_append(pkg_dest_list_t *list, const char *name,
++ const char *root_dir,const char* lists_dir);
++int pkg_dest_list_push(pkg_dest_list_t *list, pkg_dest_t *data);
++pkg_dest_list_elt_t *pkg_dest_list_pop(pkg_dest_list_t *list);
++
++#endif
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_extract.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_extract.c
+--- busybox-1.2.0-orig/archival/libipkg/pkg_extract.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_extract.c 2006-07-30 22:47:49.000000000 +0200
+@@ -0,0 +1,224 @@
++/* pkg_extract.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++#include <errno.h>
++#include <fcntl.h>
++#include <stdio.h>
++
++#include "pkg_extract.h"
++
++#include "libbb.h"
++#include "file_util.h"
++#include "sprintf_alloc.h"
++#include "unarchive.h"
++
++#define IPKG_CONTROL_ARCHIVE "control.tar.gz"
++#define IPKG_DATA_ARCHIVE "data.tar.gz"
++#define IPKG_CONTROL_FILE "control"
++
++static void extract_ipkg_file_to_dir(pkg_t *pkg, const char *dir, const char *filename)
++{
++ archive_handle_t *archive;
++ char *path;
++
++ sprintf_alloc(&path, "%s/", dir);
++ archive = init_handle();
++ archive->src_fd = bb_xopen(pkg->local_filename, O_RDONLY);
++ archive->filter = filter_accept_list;
++ llist_add_to(&(archive->accept), (char *)filename);
++ archive->buffer = path;
++ archive->action_data = data_extract_all_prefix;
++ archive->flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;
++ while( get_header_tar_gz(archive) == EXIT_SUCCESS );
++ close(archive->src_fd);
++ free(archive->accept);
++ free(archive);
++ free(path);
++}
++
++static void data_extract_file_name_to_buffer(archive_handle_t *archive)
++{
++ unsigned int size = strlen(archive->file_header->name) + 2;
++
++ if (archive->buffer == NULL) {
++ archive->buffer = xmalloc(size);
++ strcpy(archive->buffer, archive->file_header->name);
++ } else {
++ size += strlen(archive->buffer);
++ archive->buffer = xrealloc(archive->buffer, size);
++ strcat(archive->buffer, archive->file_header->name);
++ }
++ strcat(archive->buffer, "\n");
++ data_skip(archive);
++}
++
++int pkg_extract_control_file_to_stream(pkg_t *pkg, FILE *stream)
++{
++ archive_handle_t *archive;
++ char *name;
++
++ extract_ipkg_file_to_dir(pkg, global_conf->tmp_dir, "./" IPKG_CONTROL_ARCHIVE);
++ sprintf_alloc(&name, "%s/%s", global_conf->tmp_dir, IPKG_CONTROL_ARCHIVE);
++ archive = init_handle();
++ archive->src_fd = bb_xopen(name, O_RDONLY);
++ archive->filter = filter_accept_list;
++ llist_add_to(&(archive->accept), "./" IPKG_CONTROL_FILE);
++ archive->action_data = data_extract_to_buffer;
++ while( get_header_tar_gz(archive) == EXIT_SUCCESS );
++ close(archive->src_fd);
++ fputs(archive->buffer, stream);
++ free(archive->buffer);
++ free(archive->accept);
++ free(archive);
++ free(name);
++
++ return 0;
++}
++
++int pkg_extract_control_files_to_dir(pkg_t *pkg, const char *dir)
++{
++ return pkg_extract_control_files_to_dir_with_prefix(pkg, dir, "");
++}
++
++int pkg_extract_control_files_to_dir_with_prefix(pkg_t *pkg, const char *dir, const char *prefix)
++{
++ archive_handle_t *archive;
++ char *name;
++ char *path;
++
++ extract_ipkg_file_to_dir(pkg, global_conf->tmp_dir, "./" IPKG_CONTROL_ARCHIVE);
++ sprintf_alloc(&name, "%s/%s", global_conf->tmp_dir, IPKG_CONTROL_ARCHIVE);
++ sprintf_alloc(&path, "%s/%s", dir, prefix);
++ archive = init_handle();
++ archive->src_fd = bb_xopen(name, O_RDONLY);
++ archive->filter = filter_accept_all;
++ archive->buffer = path;
++ archive->action_data = data_extract_all_prefix;
++ archive->flags |= ARCHIVE_CREATE_LEADING_DIRS | ARCHIVE_PRESERVE_DATE | ARCHIVE_EXTRACT_UNCONDITIONAL;
++ while( get_header_tar_gz(archive) == EXIT_SUCCESS );
++ close(archive->src_fd);
++ free(archive);
++ free(path);
++ free(name);
++
++ return 0;
++}
++
++int pkg_extract_data_files_to_dir(pkg_t *pkg, const char *dir)
++{
++ archive_handle_t *archive;
++ char *name;
++ char *path;
++
++ extract_ipkg_file_to_dir(pkg, global_conf->tmp_dir, "./" IPKG_DATA_ARCHIVE);
++ sprintf_alloc(&name, "%s/%s", global_conf->tmp_dir, IPKG_DATA_ARCHIVE);
++ sprintf_alloc(&path, "%s/", dir);
++ archive = init_handle();
++ archive->src_fd = bb_xopen(name, O_RDONLY);
++ archive->filter = filter_accept_all;
++ archive->buffer = path;
++ archive->action_data = data_extract_all_prefix;
++ archive->flags |= ARCHIVE_CREATE_LEADING_DIRS | ARCHIVE_PRESERVE_DATE | ARCHIVE_EXTRACT_UNCONDITIONAL;
++ while( get_header_tar_gz(archive) == EXIT_SUCCESS );
++ close(archive->src_fd);
++ free(archive);
++ free(path);
++ free(name);
++
++ return 0;
++}
++
++int pkg_extract_data_file_names_to_file(pkg_t *pkg, const char *file_name)
++{
++ int err=0;
++ char *line, *data_file;
++ FILE *file;
++ FILE *tmp;
++
++ file = fopen(file_name, "w");
++ if (file == NULL) {
++ fprintf(stderr, "%s: ERROR: Failed to open %s for writing.\n",
++ __FUNCTION__, file_name);
++ return EINVAL;
++ }
++
++ tmp = tmpfile();
++ if (pkg->installed_files) {
++ str_list_elt_t *elt;
++ for (elt = pkg->installed_files->head; elt; elt = elt->next) {
++ fprintf(file, "%s\n", elt->data);
++ }
++ } else {
++ err = pkg_extract_data_file_names_to_stream(pkg, tmp);
++ if (err) {
++ fclose(file);
++ fclose(tmp);
++ return err;
++ }
++
++ /* Fixup data file names by removing the initial '.' */
++ rewind(tmp);
++ while (1) {
++ line = file_read_line_alloc(tmp);
++ if (line == NULL) {
++ break;
++ }
++
++ data_file = line;
++ if (*data_file == '.') {
++ data_file++;
++ }
++
++ if (*data_file != '/') {
++ fputs("/", file);
++ }
++
++ /* I have no idea why, but this is what dpkg does */
++ if (strcmp(data_file, "/\n") == 0) {
++ fputs("/.\n", file);
++ } else {
++ fputs(data_file, file);
++ }
++ }
++ }
++ fclose(tmp);
++ fclose(file);
++
++ return err;
++}
++
++int pkg_extract_data_file_names_to_stream(pkg_t *pkg, FILE *file)
++{
++ archive_handle_t *archive;
++ char *name;
++
++ extract_ipkg_file_to_dir(pkg, global_conf->tmp_dir, "./" IPKG_DATA_ARCHIVE);
++ sprintf_alloc(&name, "%s/%s", global_conf->tmp_dir, IPKG_DATA_ARCHIVE);
++ archive = init_handle();
++ archive->src_fd = bb_xopen(name, O_RDONLY);
++ archive->filter = filter_accept_all;
++ archive->action_data = data_extract_file_name_to_buffer;
++ while( get_header_tar_gz(archive) == EXIT_SUCCESS );
++ close(archive->src_fd);
++ fputs(archive->buffer, file);
++ free(archive->buffer);
++ free(archive);
++ free(name);
++
++ return 0;
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_extract.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_extract.h
+--- busybox-1.2.0-orig/archival/libipkg/pkg_extract.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_extract.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,32 @@
++/* pkg_extract.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef PKG_EXTRACT_H
++#define PKG_EXTRACT_H
++
++#include "pkg.h"
++
++int pkg_extract_control_file_to_stream(pkg_t *pkg, FILE *stream);
++int pkg_extract_control_files_to_dir(pkg_t *pkg, const char *dir);
++int pkg_extract_control_files_to_dir_with_prefix(pkg_t *pkg,
++ const char *dir,
++ const char *prefix);
++int pkg_extract_data_files_to_dir(pkg_t *pkg, const char *dir);
++int pkg_extract_data_file_names_to_file(pkg_t *pkg, const char *file_name);
++int pkg_extract_data_file_names_to_stream(pkg_t *pkg, FILE *file);
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg.h
+--- busybox-1.2.0-orig/archival/libipkg/pkg.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,232 @@
++/* pkg.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef PKG_H
++#define PKG_H
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <unistd.h>
++
++#include "pkg_vec.h"
++#include "str_list.h"
++#include "pkg_src.h"
++#include "pkg_dest.h"
++#include "ipkg_conf.h"
++#include "conffile_list.h"
++
++struct ipkg_conf;
++
++
++#define ARRAY_SIZE(array) sizeof(array) / sizeof((array)[0])
++
++/* I think "Size" is currently the shortest field name */
++#define PKG_MINIMUM_FIELD_NAME_LEN 4
++
++enum pkg_state_want
++{
++ SW_UNKNOWN = 1,
++ SW_INSTALL,
++ SW_DEINSTALL,
++ SW_PURGE,
++ SW_LAST_STATE_WANT
++};
++typedef enum pkg_state_want pkg_state_want_t;
++
++enum pkg_state_flag
++{
++ SF_OK = 0,
++ SF_REINSTREQ = 1,
++ SF_HOLD = 2, /* do not upgrade version */
++ SF_REPLACE = 4, /* replace this package */
++ SF_NOPRUNE = 8, /* do not remove obsolete files */
++ SF_PREFER = 16, /* prefer this version */
++ SF_OBSOLETE = 32, /* old package in upgrade pair */
++ SF_MARKED = 64, /* temporary mark */
++ SF_FILELIST_CHANGED = 128, /* needs filelist written */
++ SF_USER = 256,
++ SF_LAST_STATE_FLAG
++};
++typedef enum pkg_state_flag pkg_state_flag_t;
++#define SF_NONVOLATILE_FLAGS (SF_HOLD|SF_NOPRUNE|SF_PREFER|SF_OBSOLETE|SF_USER)
++
++enum pkg_state_status
++{
++ SS_NOT_INSTALLED = 1,
++ SS_UNPACKED,
++ SS_HALF_CONFIGURED,
++ SS_INSTALLED,
++ SS_HALF_INSTALLED,
++ SS_CONFIG_FILES,
++ SS_POST_INST_FAILED,
++ SS_REMOVAL_FAILED,
++ SS_LAST_STATE_STATUS
++};
++typedef enum pkg_state_status pkg_state_status_t;
++
++struct abstract_pkg{
++ char * name;
++ int dependencies_checked;
++ pkg_vec_t * pkgs;
++ pkg_state_status_t state_status;
++ pkg_state_flag_t state_flag;
++ struct abstract_pkg ** depended_upon_by; /* @@@@ this should be abstract_pkg_vec_t -Jamey */
++ abstract_pkg_vec_t * provided_by;
++ abstract_pkg_vec_t * replaced_by;
++};
++
++#include "pkg_depends.h"
++
++/* XXX: CLEANUP: I'd like to clean up pkg_t in several ways:
++
++ The 3 version fields should go into a single version struct. (This
++ is especially important since, currently, pkg->version can easily
++ be mistaken for pkg_verson_str_alloc(pkg) although they are very
++ distinct. This has been the source of multiple bugs.
++
++ The 3 state fields could possibly also go into their own struct.
++
++ All fields which deal with lists of packages, (Depends,
++ Pre-Depends, Provides, Suggests, Recommends, Enhances), should each
++ be handled by a single struct in pkg_t
++
++ All string fields for which there is a small set of possible
++ values, (section, maintainer, architecture, maybe version?), that
++ are reused among different packages -- for all such packages we
++ should move from "char *"s to some atom datatype to share data
++ storage and use less memory. We might even do reference counting,
++ but probably not since most often we only create new pkg_t structs,
++ we don't often free them. */
++struct pkg
++{
++ char *name;
++ unsigned long epoch;
++ char *version;
++ char *revision;
++ char *familiar_revision;
++ pkg_src_t *src;
++ pkg_dest_t *dest;
++ char *architecture;
++ char *section;
++ char *maintainer;
++ char *description;
++ pkg_state_want_t state_want;
++ pkg_state_flag_t state_flag;
++ pkg_state_status_t state_status;
++ char **depends_str;
++ int depends_count;
++ char **pre_depends_str;
++ int pre_depends_count;
++ char **recommends_str;
++ int recommends_count;
++ char **suggests_str;
++ int suggests_count;
++ compound_depend_t * depends;
++
++ /* Abhaya: new conflicts */
++ char **conflicts_str;
++ compound_depend_t * conflicts;
++ int conflicts_count;
++
++ char **replaces_str;
++ int replaces_count;
++ abstract_pkg_t ** replaces;
++
++ char **provides_str;
++ int provides_count;
++ abstract_pkg_t ** provides;
++
++ abstract_pkg_t *parent;
++
++ pkg_t *old_pkg; /* during upgrade, points from installee to previously installed */
++
++ char *filename;
++ char *local_filename;
++ char *url;
++ char *tmp_unpack_dir;
++ char *md5sum;
++ char *size;
++ char *installed_size;
++ char *priority;
++ char *source;
++ conffile_list_t conffiles;
++ time_t installed_time;
++ /* As pointer for lazy evaluation */
++ str_list_t *installed_files;
++ /* XXX: CLEANUP: I'd like to perhaps come up with a better
++ mechanism to avoid the problem here, (which is that the
++ installed_files list was being freed from an inner loop while
++ still being used within an outer loop. */
++ int installed_files_ref_cnt;
++ int essential;
++ int arch_priority;
++/* Adding this flag, to "force" ipkg to choose a "provided_by_hand" package, if there are multiple choice */
++ int provided_by_hand;
++};
++
++pkg_t *pkg_new(void);
++int pkg_init(pkg_t *pkg);
++void pkg_deinit(pkg_t *pkg);
++int pkg_init_from_file(pkg_t *pkg, const char *filename);
++abstract_pkg_t *abstract_pkg_new(void);
++int abstract_pkg_init(abstract_pkg_t *ab_pkg);
++
++/*
++ * merges fields from newpkg into oldpkg.
++ * Forcibly sets oldpkg state_status, state_want and state_flags if set_status is nonzero
++ */
++int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status);
++
++char *pkg_version_str_alloc(pkg_t *pkg);
++
++int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg);
++int pkg_name_version_and_architecture_compare(void *a, void *b);
++int abstract_pkg_name_compare(void *a, void *b);
++
++char * pkg_formatted_info(pkg_t *pkg );
++char * pkg_formatted_field(pkg_t *pkg, const char *field );
++
++void set_flags_from_control(ipkg_conf_t *conf, pkg_t *pkg);
++
++void pkg_print_info(pkg_t *pkg, FILE *file);
++void pkg_print_status(pkg_t * pkg, FILE * file);
++void pkg_print_field(pkg_t *pkg, FILE *file, const char *field);
++str_list_t *pkg_get_installed_files(pkg_t *pkg);
++int pkg_free_installed_files(pkg_t *pkg);
++int pkg_remove_installed_files_list(ipkg_conf_t *conf, pkg_t *pkg);
++conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name);
++int pkg_run_script(struct ipkg_conf *conf, pkg_t *pkg,
++ const char *script, const char *args);
++
++/* enum mappings */
++char *pkg_state_want_to_str(pkg_state_want_t sw);
++pkg_state_want_t pkg_state_want_from_str(char *str);
++char *pkg_state_flag_to_str(pkg_state_flag_t sf);
++pkg_state_flag_t pkg_state_flag_from_str(char *str);
++char *pkg_state_status_to_str(pkg_state_status_t ss);
++pkg_state_status_t pkg_state_status_from_str(char *str);
++
++int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op);
++
++int pkg_arch_supported(ipkg_conf_t *conf, pkg_t *pkg);
++int pkg_info_preinstall_check(ipkg_conf_t *conf);
++int pkg_free_installed_files(pkg_t *pkg);
++
++int pkg_write_filelist(ipkg_conf_t *conf, pkg_t *pkg);
++int pkg_write_changed_filelists(ipkg_conf_t *conf);
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_hash.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_hash.c
+--- busybox-1.2.0-orig/archival/libipkg/pkg_hash.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_hash.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,617 @@
++/* ipkg_hash.c - the itsy package management system
++
++ Steven M. Ayer
++
++ Copyright (C) 2002 Compaq Computer Corporation
++
++ 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.
++*/
++
++#include "ipkg.h"
++#include <errno.h>
++#include <ctype.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include "hash_table.h"
++#include "pkg.h"
++#include "ipkg_message.h"
++#include "pkg_vec.h"
++#include "pkg_hash.h"
++#include "pkg_parse.h"
++#include "ipkg_utils.h"
++
++static abstract_pkg_t * add_new_abstract_pkg_by_name(hash_table_t * hash, const char * pkg_name);
++
++/*
++ * this will talk to both feeds-lists files and installed status files
++ * example api:
++ *
++ * hash_table_t hash;
++ * pkg_hash_init(name, &hash, 1000);
++ * pkg_hash_add_from_file(<feed filename>);
++ *
++ * the query function is just there as a shell to prove to me that this
++ * sort of works, but isn't far from doing something useful
++ *
++ * -sma, 12/21/01
++ * modified: CDW 3 Jan. 2002
++ */
++
++
++
++int pkg_hash_init(const char *name, hash_table_t *hash, int len)
++{
++ return hash_table_init(name, hash, len);
++}
++
++void pkg_hash_deinit(hash_table_t *hash)
++{
++ hash_table_deinit(hash);
++}
++
++
++/* Find the default arch for a given package status file if none is given. */
++static char *pkg_get_default_arch(ipkg_conf_t *conf)
++{
++ nv_pair_list_elt_t *l;
++ char *def_arch = HOST_CPU_STR; /* Default arch */
++ int def_prio = 0; /* Other archs override this */
++
++ l = conf->arch_list.head;
++
++ while (l) {
++ nv_pair_t *nv = l->data;
++ int priority = strtol(nv->value, NULL, 0);
++
++ /* Check if this arch has higher priority, and is valid */
++ if ((priority > def_prio) &&
++ (strcmp(nv->name, "all")) && (strcmp(nv->name, "noarch"))) {
++ /* Our new default */
++ def_prio = priority;
++ def_arch = nv->name;
++ }
++ l = l->next;
++ }
++
++ return strdup(def_arch);
++}
++
++int pkg_hash_add_from_file(ipkg_conf_t *conf, const char *file_name,
++ pkg_src_t *src, pkg_dest_t *dest, int is_status_file)
++{
++ hash_table_t *hash = &conf->pkg_hash;
++ char **raw;
++ char **raw_start;
++ pkg_t *pkg;
++
++ raw = raw_start = read_raw_pkgs_from_file(file_name);
++ if (!raw)
++ return -ENOMEM;
++
++ while(*raw){ /* don't worry, we'll increment raw in the parsing function */
++ pkg = pkg_new();
++ if (!pkg)
++ return -ENOMEM;
++
++ if (pkg_parse_raw(pkg, &raw, src, dest) == 0) {
++ if (!pkg->architecture) {
++ char *version_str = pkg_version_str_alloc(pkg);
++ pkg->architecture = pkg_get_default_arch(conf);
++ ipkg_message(conf, IPKG_ERROR, "Package %s version %s has no architecture specified, defaulting to %s.\n",
++ pkg->name, version_str, pkg->architecture);
++ free(version_str);
++ }
++ hash_insert_pkg(hash, pkg, is_status_file,conf);
++ } else {
++ free(pkg);
++ }
++ }
++
++ /* XXX: CLEANUP: I'd like a cleaner interface for cleaning up
++ memory after read_raw_pkgs_from_file */
++ raw = raw_start;
++ while (*raw) {
++ free(*raw++);
++ }
++ free(raw_start);
++ return 0;
++}
++
++abstract_pkg_t * abstract_pkg_fetch_by_name(hash_table_t * hash, const char * pkg_name)
++{
++ return (abstract_pkg_t *)hash_table_get(hash, pkg_name);
++}
++
++abstract_pkg_vec_t *pkg_hash_fetch_all_installation_candidates(hash_table_t *hash, const char *name)
++{
++ abstract_pkg_t *apkg = abstract_pkg_fetch_by_name(hash, name);
++ if (apkg)
++ return NULL;
++ return apkg->provided_by;
++}
++
++
++pkg_t *pkg_hash_fetch_best_installation_candidate(ipkg_conf_t *conf, abstract_pkg_t *apkg,
++ int (*constraint_fcn)(pkg_t *pkg, void *cdata), void *cdata, int quiet)
++{
++ int i;
++ int nprovides = 0;
++ int nmatching = 0;
++ pkg_vec_t *matching_pkgs = pkg_vec_alloc();
++ abstract_pkg_vec_t *matching_apkgs = abstract_pkg_vec_alloc();
++ abstract_pkg_vec_t *provided_apkg_vec;
++ abstract_pkg_t **provided_apkgs;
++ abstract_pkg_vec_t *providers = abstract_pkg_vec_alloc();
++ pkg_t *latest_installed_parent = NULL;
++ pkg_t *latest_matching = NULL;
++ pkg_t *held_pkg = NULL;
++ pkg_t *good_pkg_by_name = NULL;
++
++ if (matching_apkgs == NULL || providers == NULL ||
++ apkg == NULL || apkg->provided_by == NULL || (apkg->provided_by->len == 0))
++ return NULL;
++
++ ipkg_message(conf, IPKG_DEBUG, "best installation candidate for %s\n", apkg->name);
++
++ provided_apkg_vec = apkg->provided_by;
++ nprovides = provided_apkg_vec->len;
++ provided_apkgs = provided_apkg_vec->pkgs;
++ if (nprovides > 1)
++ ipkg_message(conf, IPKG_DEBUG, " apkg=%s nprovides=%d\n", apkg->name, nprovides);
++
++ /* accumulate all the providers */
++ for (i = 0; i < nprovides; i++) {
++ abstract_pkg_t *provider_apkg = provided_apkgs[i];
++ ipkg_message(conf, IPKG_DEBUG, " adding %s to providers\n", provider_apkg->name);
++ abstract_pkg_vec_insert(providers, provider_apkg);
++ }
++ nprovides = providers->len;
++
++ for (i = 0; i < nprovides; i++) {
++ abstract_pkg_t *provider_apkg = abstract_pkg_vec_get(providers, i);
++ abstract_pkg_t *replacement_apkg = NULL;
++ pkg_vec_t *vec;
++
++ if (provider_apkg->replaced_by && provider_apkg->replaced_by->len) {
++ replacement_apkg = provider_apkg->replaced_by->pkgs[0];
++ if (provider_apkg->replaced_by->len > 1) {
++ ipkg_message(conf, IPKG_NOTICE, "Multiple replacers for %s, using first one (%s)\n",
++ provider_apkg->name, replacement_apkg->name);
++ }
++ }
++
++ if (replacement_apkg)
++ ipkg_message(conf, IPKG_DEBUG, " replacement_apkg=%s for provider_apkg=%s\n",
++ replacement_apkg->name, provider_apkg->name);
++
++ if (replacement_apkg && (replacement_apkg != provider_apkg)) {
++ if (abstract_pkg_vec_contains(providers, replacement_apkg))
++ continue;
++ else
++ provider_apkg = replacement_apkg;
++ }
++
++ if (!(vec = provider_apkg->pkgs)) {
++ ipkg_message(conf, IPKG_DEBUG, " no pkgs for provider_apkg %s\n", provider_apkg->name);
++ continue;
++ }
++
++
++ /* now check for supported architecture */
++ {
++ int max_count = 0;
++ int i;
++
++ /* count packages matching max arch priority and keep track of last one */
++ for (i = 0; i < vec->len; i++) {
++ pkg_t *maybe = vec->pkgs[i];
++ ipkg_message(conf, IPKG_DEBUG, " %s arch=%s arch_priority=%d version=%s \n",
++ maybe->name, maybe->architecture, maybe->arch_priority, maybe->version);
++ if (maybe->arch_priority > 0) {
++ max_count++;
++ abstract_pkg_vec_insert(matching_apkgs, maybe->parent);
++ pkg_vec_insert(matching_pkgs, maybe);
++ }
++ }
++ }
++ }
++
++ if (matching_pkgs->len > 1)
++ pkg_vec_sort(matching_pkgs, pkg_name_version_and_architecture_compare);
++ if (matching_apkgs->len > 1)
++ abstract_pkg_vec_sort(matching_pkgs, abstract_pkg_name_compare);
++
++/* Here it is usefull, if ( matching_apkgs->len > 1 ), to test if one of this matching packages has the same name of the
++ needed package. In this case, I would return it for install, otherwise I will continue with the procedure */
++/* The problem is what to do when there are more than a mathing package, with the same name and several version ?
++ Until now I always got the latest, but that breaks the downgrade option.
++ If I stop at the first one, I would probably miss the new ones
++ Maybe the way is to have some kind of flag somewhere, to see if the package been asked to install is from a file,
++ or from a Packages feed.
++ It it is from a file it always need to be checked whatever version I have in feeds or everywhere, according to force-down or whatever options*/
++/*Pigi*/
++
++ for (i = 0; i < matching_pkgs->len; i++) {
++ pkg_t *matching = matching_pkgs->pkgs[i];
++ if (constraint_fcn(matching, cdata)) { /* We found it */
++ ipkg_message(conf, IPKG_DEBUG, " Found a valid candidate for the install: %s %s \n", matching->name, matching->version) ;
++ good_pkg_by_name = matching;
++ if ( matching->provided_by_hand == 1 ) /* It has been provided by hand, so it is what user want */
++ break;
++ }
++ }
++
++
++ for (i = 0; i < matching_pkgs->len; i++) {
++ pkg_t *matching = matching_pkgs->pkgs[i];
++ latest_matching = matching;
++ if (matching->parent->state_status == SS_INSTALLED || matching->parent->state_status == SS_UNPACKED)
++ latest_installed_parent = matching;
++ if (matching->state_flag & (SF_HOLD|SF_PREFER)) {
++ if (held_pkg)
++ ipkg_message(conf, IPKG_ERROR, "Multiple packages (%s and %s) providing same name marked HOLD or PREFER. Using latest.\n",
++ held_pkg->name, matching->name);
++ held_pkg = matching;
++ }
++ }
++
++ if (!good_pkg_by_name && !held_pkg && !latest_installed_parent && matching_apkgs->len > 1 && !quiet) {
++ ipkg_message(conf, IPKG_ERROR, "Package=%s, %d matching providers\n",
++ apkg->name, matching_apkgs->len);
++ for (i = 0; i < matching_apkgs->len; i++) {
++ abstract_pkg_t *matching = matching_apkgs->pkgs[i];
++ ipkg_message(conf, IPKG_ERROR, " %s\n", matching->name);
++ }
++ ipkg_message(conf, IPKG_ERROR, "Please select one with ipkg install or ipkg flag prefer\n");
++ }
++
++ if (matching_apkgs->len > 1 && conf->verbosity > 1) {
++ ipkg_message(conf, IPKG_NOTICE, "%s: for apkg=%s, %d matching pkgs\n",
++ __FUNCTION__, apkg->name, matching_pkgs->len);
++ for (i = 0; i < matching_pkgs->len; i++) {
++ pkg_t *matching = matching_pkgs->pkgs[i];
++ ipkg_message(conf, IPKG_INFO, " %s %s %s\n",
++ matching->name, matching->version, matching->architecture);
++ }
++ }
++
++ nmatching = matching_apkgs->len;
++
++ pkg_vec_free(matching_pkgs);
++ abstract_pkg_vec_free(matching_apkgs);
++ abstract_pkg_vec_free(providers);
++
++ if (good_pkg_by_name) { /* We found a good candidate, we will install it */
++ return good_pkg_by_name;
++ }
++ if (held_pkg) {
++ ipkg_message(conf, IPKG_INFO, " using held package %s\n", held_pkg->name);
++ return held_pkg;
++ }
++ if (latest_installed_parent) {
++ ipkg_message(conf, IPKG_INFO, " using latest version of installed package %s\n", latest_installed_parent->name);
++ return latest_installed_parent;
++ }
++ if (nmatching > 1) {
++ ipkg_message(conf, IPKG_INFO, " no matching pkg out of matching_apkgs=%d\n", nmatching);
++ return NULL;
++ }
++ if (latest_matching) {
++ ipkg_message(conf, IPKG_INFO, " using latest matching %s %s %s\n",
++ latest_matching->name, latest_matching->version, latest_matching->architecture);
++ return latest_matching;
++ }
++ return NULL;
++}
++
++static int pkg_name_constraint_fcn(pkg_t *pkg, void *cdata)
++{
++ const char *name = (const char *)cdata;
++ if (strcmp(pkg->name, name) == 0)
++ return 1;
++ else
++ return 0;
++}
++
++pkg_t *pkg_hash_fetch_best_installation_candidate_by_name(ipkg_conf_t *conf, const char *name)
++{
++ hash_table_t *hash = &conf->pkg_hash;
++ abstract_pkg_t *apkg = NULL;
++
++ if (!(apkg = abstract_pkg_fetch_by_name(hash, name)))
++ return NULL;
++
++ return pkg_hash_fetch_best_installation_candidate(conf, apkg, pkg_name_constraint_fcn, apkg->name, 0);
++}
++
++
++pkg_t * pkg_hash_fetch_by_name_version(hash_table_t *hash,
++ const char *pkg_name,
++ const char * version)
++{
++ pkg_vec_t * vec;
++ register int i;
++ char *version_str = NULL;
++
++ if(!(vec = pkg_vec_fetch_by_name(hash, pkg_name)))
++ return NULL;
++
++ for(i = 0; i < vec->len; i++) {
++ version_str = pkg_version_str_alloc(vec->pkgs[i]);
++ if(!strcmp(version_str, version)) {
++ free(version_str);
++ break;
++ }
++ free(version_str);
++ }
++
++ if(i == vec->len)
++ return NULL;
++
++ return vec->pkgs[i];
++}
++
++pkg_t *pkg_hash_fetch_installed_by_name_dest(hash_table_t *hash,
++ const char *pkg_name,
++ pkg_dest_t *dest)
++{
++ pkg_vec_t * vec;
++ register int i;
++
++ if(!(vec = pkg_vec_fetch_by_name(hash, pkg_name))) {
++ return NULL;
++ }
++
++ for(i = 0; i < vec->len; i++)
++ if((vec->pkgs[i]->state_status == SS_INSTALLED || vec->pkgs[i]->state_status == SS_UNPACKED) && vec->pkgs[i]->dest == dest) {
++ return vec->pkgs[i];
++ }
++ return NULL;
++}
++
++pkg_t *pkg_hash_fetch_installed_by_name(hash_table_t *hash,
++ const char *pkg_name)
++{
++ pkg_vec_t * vec;
++ register int i;
++
++ if(!(vec = pkg_vec_fetch_by_name(hash, pkg_name))){
++ return NULL;
++ }
++
++ for(i = 0; i < vec->len; i++)
++ if (vec->pkgs[i]->state_status == SS_INSTALLED || vec->pkgs[i]->state_status == SS_UNPACKED){
++ return vec->pkgs[i];
++ }
++
++ return NULL;
++}
++
++pkg_vec_t *pkg_vec_fetch_by_name(hash_table_t *hash, const char *pkg_name)
++{
++ abstract_pkg_t * ab_pkg;
++
++ if(!(ab_pkg = abstract_pkg_fetch_by_name(hash, pkg_name))){
++ return NULL;
++ }
++
++ if (ab_pkg->pkgs) {
++ return ab_pkg->pkgs;
++ } else if (ab_pkg->provided_by) {
++ abstract_pkg_t *abpkg = abstract_pkg_vec_get(ab_pkg->provided_by, 0);
++ if (abpkg != NULL){
++ return abpkg->pkgs;
++ } else {
++ return ab_pkg->pkgs;
++ }
++ } else {
++ return NULL;
++ }
++}
++
++static int pkg_compare_names(const void *p1, const void *p2)
++{
++ const pkg_t *pkg1 = *(const pkg_t **)p1;
++ const pkg_t *pkg2 = *(const pkg_t **)p2;
++ if (pkg1->name == NULL)
++ return 1;
++ if (pkg2->name == NULL)
++ return -1;
++ return(strcmp(pkg1->name, pkg2->name));
++}
++
++
++static void pkg_hash_fetch_available_helper(const char *pkg_name, void *entry, void *data)
++{
++ int j;
++ abstract_pkg_t *ab_pkg = (abstract_pkg_t *)entry;
++ pkg_vec_t *all = (pkg_vec_t *)data;
++ pkg_vec_t *pkg_vec = ab_pkg->pkgs;
++ if (pkg_vec) {
++ for (j = 0; j < pkg_vec->len; j++) {
++ pkg_t *pkg = pkg_vec->pkgs[j];
++ pkg_vec_insert(all, pkg);
++ }
++ }
++}
++
++void pkg_hash_fetch_available(hash_table_t *hash, pkg_vec_t *all)
++{
++ hash_table_foreach(hash, pkg_hash_fetch_available_helper, all);
++ qsort(all->pkgs, all->len, sizeof(pkg_t *), pkg_compare_names);
++}
++
++static void pkg_hash_fetch_all_installed_helper(const char *pkg_name, void *entry, void *data)
++{
++ abstract_pkg_t *ab_pkg = (abstract_pkg_t *)entry;
++ pkg_vec_t *all = (pkg_vec_t *)data;
++ pkg_vec_t *pkg_vec = ab_pkg->pkgs;
++ int j;
++ if (pkg_vec) {
++ for (j = 0; j < pkg_vec->len; j++) {
++ pkg_t *pkg = pkg_vec->pkgs[j];
++ if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
++ pkg_vec_insert(all, pkg);
++ }
++ }
++ }
++}
++void pkg_hash_fetch_all_installed(hash_table_t *hash, pkg_vec_t *all)
++{
++ hash_table_foreach(hash, pkg_hash_fetch_all_installed_helper, all);
++ qsort(all->pkgs, all->len, sizeof(void*), pkg_compare_names);
++}
++
++static void pkg_hash_dump_helper(const char *pkg_name, void *entry, void *data)
++{
++ int i;
++ pkg_t *pkg;
++ abstract_pkg_t *ab_pkg = (abstract_pkg_t *)entry;
++ ipkg_conf_t *conf = (ipkg_conf_t *)data;
++ abstract_pkg_t ** dependents = ab_pkg->depended_upon_by;
++ fprintf(stdout, "%s\n", ab_pkg->name);
++ i = 0;
++ if (dependents != NULL)
++ while (dependents [i] != NULL)
++ printf ("\tdepended upon by - %s\n", dependents [i ++]->name);
++ dependents = ab_pkg->provided_by->pkgs;
++ i = 0;
++ if (dependents != NULL)
++ while (dependents [i] != NULL && i < ab_pkg->provided_by->len)
++ printf ("\tprovided by - %s\n", dependents [i ++]->name);
++ pkg = pkg_hash_fetch_best_installation_candidate_by_name (conf, ab_pkg->name);
++ if (pkg) {
++ i = 0;
++ while (i < pkg->depends_count)
++ printf ("\tdepends on - %s\n", pkg->depends_str [i ++]);
++ }
++}
++void pkg_hash_dump(hash_table_t *hash, void *data)
++{
++
++ printf ("\n\n+=+%s+=+\n\n", __FUNCTION__);
++ hash_table_foreach(hash, pkg_hash_dump_helper, data);
++ printf ("\n+=+%s+=+\n\n", __FUNCTION__);
++}
++
++abstract_pkg_t * ensure_abstract_pkg_by_name(hash_table_t * hash, const char * pkg_name)
++{
++ abstract_pkg_t * ab_pkg;
++
++ if(!(ab_pkg = abstract_pkg_fetch_by_name(hash, pkg_name)))
++ ab_pkg = add_new_abstract_pkg_by_name(hash, pkg_name);
++
++ return ab_pkg;
++}
++
++pkg_t *hash_insert_pkg(hash_table_t *hash, pkg_t *pkg, int set_status,ipkg_conf_t *conf)
++{
++ abstract_pkg_t * ab_pkg;
++ int arch_priority;
++
++ if(!pkg)
++ return pkg;
++
++ arch_priority = pkg->arch_priority;
++
++ if (buildDepends(hash, pkg)<0){
++ fprintf(stderr, "%s : This should never happen. Report this Bug in bugzilla please \n ",__FUNCTION__);
++ return NULL;
++ }
++ ab_pkg = ensure_abstract_pkg_by_name(hash, pkg->name);
++
++ if (set_status) {
++ if (pkg->state_status == SS_INSTALLED) {
++ ab_pkg->state_status = SS_INSTALLED;
++ } else if (pkg->state_status == SS_UNPACKED) {
++ ab_pkg->state_status = SS_UNPACKED;
++ }
++ }
++
++ if(!ab_pkg->pkgs)
++ ab_pkg->pkgs = pkg_vec_alloc();
++
++ /* pkg_vec_insert_merge might munge package, but it returns an unmunged pkg */
++ pkg = pkg_vec_insert_merge(ab_pkg->pkgs, pkg, set_status,conf );
++ pkg->parent = ab_pkg;
++
++ if (buildProvides(hash, ab_pkg, pkg)<0){
++ fprintf(stderr, "%s : This should never happen. Report this Bug in bugzilla please \n ",__FUNCTION__);
++ return NULL;
++ }
++ /* need to build the conflicts graph before replaces for correct calculation of replaced_by relation */
++ if (buildConflicts(hash, ab_pkg, pkg)<0){
++ fprintf(stderr, "%s : This should never happen. Report this Bug in bugzilla please \n ",__FUNCTION__);
++ return NULL;
++ }
++ if (buildReplaces(hash, ab_pkg, pkg)<0) {
++ fprintf(stderr, "%s : This should never happen. Report this Bug in bugzilla please \n ",__FUNCTION__);
++ return NULL;
++ }
++
++ buildDependedUponBy(pkg, ab_pkg);
++ return pkg;
++}
++
++/*
++ * this will assume that we've already determined that
++ * the abstract pkg doesn't exist, 'cause we should know these things...
++ */
++static abstract_pkg_t * add_new_abstract_pkg_by_name(hash_table_t * hash, const char * pkg_name)
++{
++ abstract_pkg_t * ab_pkg;
++
++ ab_pkg = abstract_pkg_new();
++ if (ab_pkg == NULL) { return NULL; }
++
++ ab_pkg->name = strdup(pkg_name);
++ hash_table_insert(hash, pkg_name, ab_pkg);
++
++ return ab_pkg;
++}
++
++
++pkg_t *file_hash_get_file_owner(ipkg_conf_t *conf, const char *file_name)
++{
++ hash_table_t *file_hash = &conf->file_hash;
++
++ return hash_table_get(file_hash, file_name);
++}
++
++int file_hash_set_file_owner(ipkg_conf_t *conf, const char *file_name, pkg_t *owning_pkg)
++{
++ hash_table_t *file_hash = &conf->file_hash;
++ pkg_t *old_owning_pkg = hash_table_get(file_hash, file_name);
++ int file_name_len = strlen(file_name);
++
++ if (file_name[file_name_len -1] == '/')
++ return 0;
++
++ if (conf->offline_root) {
++ int len = strlen(conf->offline_root);
++ if (strncmp(file_name, conf->offline_root, len) == 0) {
++ file_name += len;
++ }
++ }
++
++ // ipkg_message(conf, IPKG_DEBUG2, "owning_pkg=%s filename=%s\n", owning_pkg->name, file_name);
++ hash_table_insert(file_hash, file_name, owning_pkg);
++ if (old_owning_pkg) {
++ str_list_remove_elt(old_owning_pkg->installed_files, file_name);
++ /* mark this package to have its filelist written */
++ old_owning_pkg->state_flag |= SF_FILELIST_CHANGED;
++ owning_pkg->state_flag |= SF_FILELIST_CHANGED;
++ }
++ return 0;
++}
++
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_hash.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_hash.h
+--- busybox-1.2.0-orig/archival/libipkg/pkg_hash.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_hash.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,61 @@
++/* pkg_hash.h - the itsy package management system
++
++ Steven M. Ayer
++
++ Copyright (C) 2002 Compaq Computer Corporation
++
++ 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.
++*/
++
++#ifndef PKG_HASH_H
++#define PKG_HASH_H
++
++#include "pkg.h"
++#include "pkg_vec.h"
++#include "hash_table.h"
++
++
++int pkg_hash_init(const char *name, hash_table_t *hash, int len);
++void pkg_hash_deinit(hash_table_t *hash);
++void pkg_hash_map(hash_table_t *hash, void (*f)(void *data, void *entry), void *data);
++
++void pkg_hash_dump(hash_table_t *hash, void *data);
++void pkg_hash_fetch_available(hash_table_t *hash, pkg_vec_t *available);
++
++int pkg_hash_add_from_file(ipkg_conf_t *conf, const char *file_name,
++ pkg_src_t *src, pkg_dest_t *dest, int is_status_file);
++pkg_t *hash_insert_pkg(hash_table_t *hash, pkg_t *pkg, int set_status,ipkg_conf_t *conf);
++
++abstract_pkg_t * ensure_abstract_pkg_by_name(hash_table_t * hash, const char * pkg_name);
++abstract_pkg_t * abstract_pkg_fetch_by_name(hash_table_t * hash, const char * pkg_name);
++pkg_vec_t *pkg_hash_fetch_by_name(hash_table_t *hash, const char *pkg_name);
++void pkg_hash_fetch_all_installed(hash_table_t *hash, pkg_vec_t *installed);
++pkg_t * pkg_hash_fetch_by_name_version(hash_table_t *hash,
++ const char *pkg_name,
++ const char * version);
++abstract_pkg_vec_t *pkg_hash_fetch_all_installation_candidates(hash_table_t *hash, const char *name);
++pkg_t *pkg_hash_fetch_best_installation_candidate(ipkg_conf_t *conf, abstract_pkg_t *apkg,
++ int (*constraint_fcn)(pkg_t *pkg, void *data), void *cdata, int quiet);
++pkg_t *pkg_hash_fetch_best_installation_candidate_by_name(ipkg_conf_t *conf, const char *name);
++pkg_t *pkg_hash_fetch_installed_by_name(hash_table_t *hash,
++ const char *pkg_name);
++pkg_t *pkg_hash_fetch_installed_by_name_dest(hash_table_t *hash,
++ const char *pkg_name,
++ pkg_dest_t *dest);
++
++pkg_t *file_hash_get_file_owner(ipkg_conf_t *conf, const char *file_name);
++int file_hash_set_file_owner(ipkg_conf_t *conf, const char *file_name, pkg_t *pkg);
++
++/* XXX: shouldn't this go in pkg_vec.[ch]? */
++pkg_vec_t *pkg_vec_fetch_by_name(hash_table_t *hash, const char *pkg_name);
++
++#endif
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_parse.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_parse.c
+--- busybox-1.2.0-orig/archival/libipkg/pkg_parse.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_parse.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,366 @@
++/* pkg_parse.c - the itsy package management system
++
++ Steven M. Ayer
++
++ Copyright (C) 2002 Compaq Computer Corporation
++
++ 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.
++*/
++
++#include "ipkg.h"
++#include <errno.h>
++#include <ctype.h>
++
++#include "pkg.h"
++#include "ipkg_utils.h"
++#include "pkg_parse.h"
++
++int isGenericFieldType(char * type, char * line)
++{
++ if(!strncmp(line, type, strlen(type)))
++ return 1;
++ return 0;
++}
++
++char * parseGenericFieldType(char * type, char * raw)
++{
++ char * field_value = raw + (strlen(type) + 1);
++ return trim_alloc(field_value);
++}
++
++void parseStatus(pkg_t *pkg, char * raw)
++{
++ char sw_str[64], sf_str[64], ss_str[64];
++
++ sscanf(raw, "Status: %s %s %s", sw_str, sf_str, ss_str);
++ pkg->state_want = pkg_state_want_from_str(sw_str);
++ pkg->state_flag = pkg_state_flag_from_str(sf_str);
++ pkg->state_status = pkg_state_status_from_str(ss_str);
++}
++
++char ** parseDependsString(char * raw, int * depends_count)
++{
++ char ** depends = NULL;
++ int line_count = 0;
++ char buff[2048], * dest;
++
++ while(raw && *raw && !isspace(*raw)) {
++ raw++;
++ }
++
++ if(line_is_blank(raw)){
++ *depends_count = line_count;
++ return NULL;
++ }
++ while(raw && *raw){
++ depends = (char **)realloc(depends, sizeof(char *) * (line_count + 1));
++
++ while(isspace(*raw)) raw++;
++
++ dest = buff;
++ while((*raw != ',') && *raw)
++ *dest++ = *raw++;
++
++ *dest = '\0';
++ depends[line_count] = trim_alloc(buff);
++ if(depends[line_count] ==NULL)
++ return NULL;
++ line_count++;
++ if(*raw == ',')
++ raw++;
++ }
++ *depends_count = line_count;
++ return depends;
++}
++
++void parseConffiles(pkg_t * pkg, char * raw)
++{
++ char file_name[1048], md5sum[1048]; /* please tell me there aren't any longer that 1k */
++
++ if(!strncmp(raw, "Conffiles:", 10))
++ raw += strlen("Conffiles:");
++
++ while(*raw && (sscanf(raw, "%s%s", file_name, md5sum) == 2)){
++ conffile_list_append(&pkg->conffiles, file_name, md5sum);
++ /* fprintf(stderr, "%s %s ", file_name, md5sum);*/
++ while (*raw && isspace(*raw)) {
++ raw++;
++ }
++ raw += strlen(file_name);
++ while (*raw && isspace(*raw)) {
++ raw++;
++ }
++ raw += strlen(md5sum);
++ }
++}
++
++int parseVersion(pkg_t *pkg, char *raw)
++{
++ char *colon, *eepochcolon;
++#ifdef USE_DEBVERSION
++ char *hyphen;
++#endif
++ unsigned long epoch;
++
++ if (!*raw) {
++ fprintf(stderr, "%s: ERROR: version string is empty", __FUNCTION__);
++ return EINVAL;
++ }
++
++ if (strncmp(raw, "Version:", 8) == 0) {
++ raw += 8;
++ }
++ while (*raw && isspace(*raw)) {
++ raw++;
++ }
++
++ colon= strchr(raw,':');
++ if (colon) {
++ epoch= strtoul(raw,&eepochcolon,10);
++ if (colon != eepochcolon) {
++ fprintf(stderr, "%s: ERROR: epoch in version is not number", __FUNCTION__);
++ return EINVAL;
++ }
++ if (!*++colon) {
++ fprintf(stderr, "%s: ERROR: nothing after colon in version number", __FUNCTION__);
++ return EINVAL;
++ }
++ raw= colon;
++ pkg->epoch= epoch;
++ } else {
++ pkg->epoch= 0;
++ }
++
++ pkg->revision = "";
++ pkg->familiar_revision = "";
++
++ pkg->version= malloc(strlen(raw)+1);
++ if ( pkg->version == NULL ) {
++ fprintf(stderr, "%s: out of memory \n", __FUNCTION__);
++ return ENOMEM;
++ }
++ strcpy(pkg->version, raw);
++
++#ifdef USE_DEBVERSION
++ hyphen= strrchr(pkg->version,'-');
++
++ if (hyphen) {
++ *hyphen++= 0;
++ if (strncmp("fam", hyphen, 3) == 0) {
++ pkg->familiar_revision=hyphen+3;
++ hyphen= strrchr(pkg->version,'-');
++ if (hyphen) {
++ *hyphen++= 0;
++ pkg->revision = hyphen;
++ }
++ } else {
++ pkg->revision = hyphen;
++ }
++ }
++#endif
++
++/*
++ fprintf(stderr,"Parsed version: %lu, %s, %s, %s\n",
++ pkg->epoch,
++ pkg->version,
++ pkg->revision,
++ pkg->familiar_revision);
++*/
++
++ return 0;
++}
++
++
++/* This code is needed to insert in first position the keyword for the aligning bug */
++
++int alterProvidesLine(char *raw, char *temp)
++{
++
++
++ if (!*raw) {
++ fprintf(stderr, "%s: ERROR: Provides string is empty", __FUNCTION__);
++ return -EINVAL;
++ }
++
++ if ( temp == NULL ) {
++ fprintf(stderr, "%s: out of memory \n", __FUNCTION__);
++ return -ENOMEM;
++ }
++
++ if (strncmp(raw, "Provides:", 9) == 0) {
++ raw += 9;
++ }
++ while (*raw && isspace(*raw)) {
++ raw++;
++ }
++
++ snprintf ( temp, 35, "Provides: ipkg_internal_use_only, "); /* First part of the line */
++ while (*raw) {
++ strncat( temp, raw++, 1);
++ }
++ return 0;
++
++}
++
++/* Some random thoughts from Carl:
++
++ This function could be considerably simplified if we just kept
++ an array of all the generic string-valued field names, and looped
++ through those looking for a match. Also, these fields could perhaps
++ be stored in the package as an array as well, (or, probably better,
++ as an nv_pair_list_t).
++
++ Fields which require special parsing or storage, (such as Depends:
++ and Status:) could be handled as they are now.
++*/
++/* XXX: FEATURE: The Suggests: field needs to be changed from a string
++ to a dependency list. And, since we already have
++ Depends/Pre-Depends and need to add Conflicts, Recommends, and
++ Enhances, perhaps we could generalize all of these and save some
++ code duplication.
++*/
++int pkg_parse_raw(pkg_t *pkg, char ***raw, pkg_src_t *src, pkg_dest_t *dest)
++{
++ int reading_conffiles, reading_description;
++ int pkg_false_provides=1;
++ char ** lines;
++ char * provide=NULL;
++
++ pkg->src = src;
++ pkg->dest = dest;
++
++ reading_conffiles = reading_description = 0;
++
++ for (lines = *raw; *lines; lines++) {
++ /* fprintf(stderr, "PARSING %s\n", *lines);*/
++ if(isGenericFieldType("Package:", *lines))
++ pkg->name = parseGenericFieldType("Package", *lines);
++ else if(isGenericFieldType("Architecture:", *lines))
++ pkg->architecture = parseGenericFieldType("Architecture", *lines);
++ else if(isGenericFieldType("Filename:", *lines))
++ pkg->filename = parseGenericFieldType("Filename", *lines);
++ else if(isGenericFieldType("Section:", *lines))
++ pkg->section = parseGenericFieldType("Section", *lines);
++ else if(isGenericFieldType("MD5sum:", *lines))
++ pkg->md5sum = parseGenericFieldType("MD5sum", *lines);
++ /* The old ipkg wrote out status files with the wrong case for MD5sum,
++ let's parse it either way */
++ else if(isGenericFieldType("MD5Sum:", *lines))
++ pkg->md5sum = parseGenericFieldType("MD5Sum", *lines);
++ else if(isGenericFieldType("Size:", *lines))
++ pkg->size = parseGenericFieldType("Size", *lines);
++ else if(isGenericFieldType("Source:", *lines))
++ pkg->source = parseGenericFieldType("Source", *lines);
++ else if(isGenericFieldType("Installed-Size:", *lines))
++ pkg->installed_size = parseGenericFieldType("Installed-Size", *lines);
++ else if(isGenericFieldType("Installed-Time:", *lines)) {
++ char *time_str = parseGenericFieldType("Installed-Time", *lines);
++ pkg->installed_time = strtoul(time_str, NULL, 0);
++ } else if(isGenericFieldType("Priority:", *lines))
++ pkg->priority = parseGenericFieldType("Priority", *lines);
++ else if(isGenericFieldType("Essential:", *lines)) {
++ char *essential_value;
++ essential_value = parseGenericFieldType("Essential", *lines);
++ if (strcmp(essential_value, "yes") == 0) {
++ pkg->essential = 1;
++ }
++ free(essential_value);
++ }
++ else if(isGenericFieldType("Status", *lines))
++ parseStatus(pkg, *lines);
++ else if(isGenericFieldType("Version", *lines))
++ parseVersion(pkg, *lines);
++ else if(isGenericFieldType("Maintainer", *lines))
++ pkg->maintainer = parseGenericFieldType("Maintainer", *lines);
++ else if(isGenericFieldType("Conffiles", *lines)){
++ parseConffiles(pkg, *lines);
++ reading_conffiles = 1;
++ }
++ else if(isGenericFieldType("Description", *lines)) {
++ pkg->description = parseGenericFieldType("Description", *lines);
++ reading_conffiles = 0;
++ reading_description = 1;
++ }
++
++ else if(isGenericFieldType("Provides", *lines)){
++/* Here we add the internal_use to align the off by one problem between provides_str and provides */
++ provide = (char * ) malloc(strlen(*lines)+ 35 ); /* Preparing the space for the new ipkg_internal_use_only */
++ if ( alterProvidesLine(*lines,provide) ){
++ return EINVAL;
++ }
++ pkg->provides_str = parseDependsString( provide, &pkg->provides_count);
++/* Let's try to hack a bit here.
++ The idea is that if a package has no Provides, we would add one generic, to permit the check of dependencies
++ in alot of other places. We will remove it before writing down the status database */
++ pkg_false_provides=0;
++ free(provide);
++ }
++
++ else if(isGenericFieldType("Depends", *lines))
++ pkg->depends_str = parseDependsString(*lines, &pkg->depends_count);
++ else if(isGenericFieldType("Pre-Depends", *lines))
++ pkg->pre_depends_str = parseDependsString(*lines, &pkg->pre_depends_count);
++ else if(isGenericFieldType("Recommends", *lines))
++ pkg->recommends_str = parseDependsString(*lines, &pkg->recommends_count);
++ else if(isGenericFieldType("Suggests", *lines))
++ pkg->suggests_str = parseDependsString(*lines, &pkg->suggests_count);
++ /* Abhaya: support for conflicts */
++ else if(isGenericFieldType("Conflicts", *lines))
++ pkg->conflicts_str = parseDependsString(*lines, &pkg->conflicts_count);
++ else if(isGenericFieldType("Replaces", *lines))
++ pkg->replaces_str = parseDependsString(*lines, &pkg->replaces_count);
++ else if(line_is_blank(*lines)) {
++ lines++;
++ break;
++ }
++ else if(**lines == ' '){
++ if(reading_description) {
++ /* we already know it's not blank, so the rest of description */
++ pkg->description = realloc(pkg->description,
++ strlen(pkg->description)
++ + 1 + strlen(*lines) + 1);
++ strcat(pkg->description, "\n");
++ strcat(pkg->description, (*lines));
++ }
++ else if(reading_conffiles)
++ parseConffiles(pkg, *lines);
++ }
++ }
++ *raw = lines;
++/* If the ipk has not a Provides line, we insert our false line */
++ if ( pkg_false_provides==1)
++ pkg->provides_str = parseDependsString ((char *)"Provides: ipkg_internal_use_only ", &pkg->provides_count);
++
++ if (pkg->name) {
++ return 0;
++ } else {
++ return EINVAL;
++ }
++}
++
++int pkg_valorize_other_field(pkg_t *pkg, char ***raw)
++{
++ char ** lines;
++
++ for (lines = *raw; *lines; lines++) {
++ if(isGenericFieldType("Essential:", *lines)) {
++ char *essential_value;
++ essential_value = parseGenericFieldType("Essential", *lines);
++ if (strcmp(essential_value, "yes") == 0) {
++ pkg->essential = 1;
++ }
++ free(essential_value);
++ }
++ }
++ *raw = lines;
++
++ return 0;
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_parse.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_parse.h
+--- busybox-1.2.0-orig/archival/libipkg/pkg_parse.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_parse.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,31 @@
++/* pkg_parse.h - the itsy package management system
++
++ Steven M. Ayer
++
++ Copyright (C) 2002 Compaq Computer Corporation
++
++ 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.
++*/
++
++#ifndef PKG_PARSE_H
++#define PKG_PARSE_H
++
++int isGenericFieldType(char * type, char * line);
++char * parseGenericFieldType(char * type, char * raw);
++void parseStatus(pkg_t *pkg, char * raw);
++int parseVersion(pkg_t *pkg, char *raw);
++char ** parseDependsString(char * raw, int * depends_count);
++int parseVersion(pkg_t *pkg, char *raw);
++void parseConffiles(pkg_t * pkg, char * raw);
++int pkg_parse_raw(pkg_t *pkg, char ***raw, pkg_src_t *src, pkg_dest_t *dest);
++int pkg_valorize_other_field(pkg_t *pkg, char ***raw);
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_src.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_src.c
+--- busybox-1.2.0-orig/archival/libipkg/pkg_src.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_src.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,43 @@
++/* pkg_src.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++
++#include "pkg_src.h"
++#include "str_util.h"
++
++int pkg_src_init(pkg_src_t *src, const char *name, const char *base_url, const char *extra_data, int gzip)
++{
++ src->gzip = gzip;
++ src->name = str_dup_safe (name);
++ src->value = str_dup_safe (base_url);
++ if (extra_data)
++ src->extra_data = str_dup_safe (extra_data);
++ else
++ src->extra_data = NULL;
++ return 0;
++}
++
++void pkg_src_deinit(pkg_src_t *src)
++{
++ free (src->name);
++ free (src->value);
++ if (src->extra_data)
++ free (src->extra_data);
++}
++
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_src.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_src.h
+--- busybox-1.2.0-orig/archival/libipkg/pkg_src.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_src.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,34 @@
++/* pkg_src.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef PKG_SRC_H
++#define PKG_SRC_H
++
++#include "nv_pair.h"
++
++typedef struct
++{
++ char *name;
++ char *value;
++ char *extra_data;
++ int gzip;
++} pkg_src_t;
++
++int pkg_src_init(pkg_src_t *src, const char *name, const char *base_url, const char *extra_data, int gzip);
++void pkg_src_deinit(pkg_src_t *src);
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_src_list.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_src_list.c
+--- busybox-1.2.0-orig/archival/libipkg/pkg_src_list.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_src_list.c 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,75 @@
++/* pkg_src_list.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++
++#include "pkg_src_list.h"
++#include "void_list.h"
++
++int pkg_src_list_init(pkg_src_list_t *list)
++{
++ return void_list_init((void_list_t *) list);
++}
++
++void pkg_src_list_deinit(pkg_src_list_t *list)
++{
++ pkg_src_list_elt_t *iter;
++ pkg_src_t *pkg_src;
++
++ for (iter = list->head; iter; iter = iter->next) {
++ pkg_src = iter->data;
++ pkg_src_deinit(pkg_src);
++
++ /* malloced in pkg_src_list_append */
++ free(pkg_src);
++ iter->data = NULL;
++ }
++ void_list_deinit((void_list_t *) list);
++}
++
++pkg_src_t *pkg_src_list_append(pkg_src_list_t *list,
++ const char *name, const char *base_url, const char *extra_data,
++ int gzip)
++{
++ int err;
++
++ /* freed in pkg_src_list_deinit */
++ pkg_src_t *pkg_src = malloc(sizeof(pkg_src_t));
++
++ if (pkg_src == NULL) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ pkg_src_init(pkg_src, name, base_url, extra_data, gzip);
++
++ err = void_list_append((void_list_t *) list, pkg_src);
++ if (err) {
++ return NULL;
++ }
++
++ return pkg_src;
++}
++
++int pkg_src_list_push(pkg_src_list_t *list, pkg_src_t *data)
++{
++ return void_list_push((void_list_t *) list, data);
++}
++
++pkg_src_list_elt_t *pkg_src_list_pop(pkg_src_list_t *list)
++{
++ return (pkg_src_list_elt_t *) void_list_pop((void_list_t *) list);
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_src_list.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_src_list.h
+--- busybox-1.2.0-orig/archival/libipkg/pkg_src_list.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_src_list.h 2006-07-22 16:31:25.000000000 +0200
+@@ -0,0 +1,57 @@
++/* pkg_src_list.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef PKG_SRC_LIST_H
++#define PKG_SRC_LIST_H
++
++#include "pkg_src.h"
++
++typedef struct pkg_src_list_elt pkg_src_list_elt_t;
++struct pkg_src_list_elt
++{
++ pkg_src_list_elt_t *next;
++ pkg_src_t *data;
++};
++
++typedef struct pkg_src_list pkg_src_list_t;
++struct pkg_src_list
++{
++ pkg_src_list_elt_t pre_head;
++ pkg_src_list_elt_t *head;
++ pkg_src_list_elt_t *tail;
++};
++
++static inline int pkg_src_list_empty(pkg_src_list_t *list)
++{
++ if (list->head == NULL)
++ return 1;
++ else
++ return 0;
++}
++
++int pkg_src_list_elt_init(pkg_src_list_elt_t *elt, nv_pair_t *data);
++void pkg_src_list_elt_deinit(pkg_src_list_elt_t *elt);
++
++int pkg_src_list_init(pkg_src_list_t *list);
++void pkg_src_list_deinit(pkg_src_list_t *list);
++
++pkg_src_t *pkg_src_list_append(pkg_src_list_t *list, const char *name, const char *root_dir, const char *extra_data, int gzip);
++int pkg_src_list_push(pkg_src_list_t *list, pkg_src_t *data);
++pkg_src_list_elt_t *pkg_src_list_pop(pkg_src_list_t *list);
++
++#endif
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_vec.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_vec.c
+--- busybox-1.2.0-orig/archival/libipkg/pkg_vec.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_vec.c 2006-07-22 16:31:26.000000000 +0200
+@@ -0,0 +1,230 @@
++/* pkg_vec.c - the itsy package management system
++
++ Steven M. Ayer
++
++ Copyright (C) 2002 Compaq Computer Corporation
++
++ 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.
++*/
++
++#include <stdlib.h>
++#include <fnmatch.h>
++#include "xregex.h"
++#include "ipkg.h"
++#include "pkg.h"
++
++pkg_vec_t * pkg_vec_alloc(void)
++{
++ pkg_vec_t * vec = (pkg_vec_t *)malloc(sizeof(pkg_vec_t));
++ if (!vec) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ vec->pkgs = NULL;
++ vec->len = 0;
++
++ return vec;
++}
++
++void pkg_vec_free(pkg_vec_t *vec)
++{
++ free(vec->pkgs);
++ free(vec);
++}
++
++/*
++ * assumption: all names in a vector are identical
++ * assumption: all version strings are trimmed,
++ * so identical versions have identical version strings,
++ * implying identical packages; let's marry these
++ */
++pkg_t *pkg_vec_insert_merge(pkg_vec_t *vec, pkg_t *pkg, int set_status,ipkg_conf_t *conf)
++{
++ int i;
++ int found = 0;
++
++ /* look for a duplicate pkg by name, version, and architecture */
++ for (i = 0; i < vec->len; i++){
++ ipkg_message(conf, IPKG_DEBUG2, "Function: %s. Found pkg=%s version=%s arch=%s cmp=%s version=%s arch=%s \n",
++ __FUNCTION__, pkg->name, pkg->version, pkg->architecture,
++ vec->pkgs[i]->name, vec->pkgs[i]->version,vec->pkgs[i]->architecture );
++ if ((strcmp(pkg->name, vec->pkgs[i]->name) == 0)
++ && (pkg_compare_versions(pkg, vec->pkgs[i]) == 0)
++ && (strcmp(pkg->architecture, vec->pkgs[i]->architecture) == 0)) {
++ found = 1;
++ ipkg_message(conf, IPKG_DEBUG2, "Function: %s. Found duplicate for pkg=%s version=%s arch=%s\n",
++ __FUNCTION__, pkg->name, pkg->version, pkg->architecture);
++ break;
++ }
++ }
++
++ /* we didn't find one, add it */
++ if (!found){
++ ipkg_message(conf, IPKG_DEBUG2, "Function: %s. Adding new pkg=%s version=%s arch=%s\n",
++ __FUNCTION__, pkg->name, pkg->version, pkg->architecture);
++
++ vec->pkgs = (pkg_t **)realloc(vec->pkgs, (vec->len + 1) * sizeof(pkg_t *));
++ vec->pkgs[vec->len] = pkg;
++ vec->len++;
++ return pkg;
++ }
++ /* update the one that we have */
++ else {
++ ipkg_message(conf, IPKG_DEBUG2, "Function: %s. calling pkg_merge for pkg=%s version=%s arch=%s",
++ __FUNCTION__, pkg->name, pkg->version, pkg->architecture);
++ if (set_status) {
++ /* this is from the status file, so need to merge with existing database */
++ ipkg_message(conf, IPKG_DEBUG2, " with set_status\n");
++ pkg_merge(vec->pkgs[i], pkg, set_status);
++ /* XXX: CLEANUP: It's not so polite to free something here
++ that was passed in from above. */
++ pkg_deinit(pkg);
++ free(pkg);
++ } else {
++ ipkg_message(conf, IPKG_DEBUG2, " WITHOUT set_status\n");
++ /* just overwrite the old one */
++ pkg_deinit(vec->pkgs[i]);
++ free(vec->pkgs[i]);
++ vec->pkgs[i] = pkg;
++ }
++ return vec->pkgs[i];
++ }
++}
++
++void pkg_vec_insert(pkg_vec_t *vec, const pkg_t *pkg)
++{
++ int i;
++ int found = 0;
++
++ /* look for a duplicate pkg by name, version, and architecture */
++ for (i = 0; i < vec->len; i++)
++ if ((strcmp(pkg->name, vec->pkgs[i]->name) == 0)
++ && (pkg_compare_versions(pkg, vec->pkgs[i]) == 0)
++ && (strcmp(pkg->architecture, vec->pkgs[i]->name) == 0)) {
++ found = 1;
++ break;
++ }
++
++ /* we didn't find one, add it */
++ if(!found){
++ vec->pkgs = (pkg_t **)realloc(vec->pkgs, (vec->len + 1) * sizeof(pkg_t *));
++ *(const pkg_t **)&vec->pkgs[vec->len] = pkg;
++ vec->len++;
++ }
++}
++
++int pkg_vec_contains(pkg_vec_t *vec, pkg_t *apkg)
++{
++ int i;
++ for (i = 0; i < vec->len; i++)
++ if (vec->pkgs[i] == apkg)
++ return 1;
++ return 0;
++}
++
++typedef int (*compare_fcn_t)(const void *, const void *);
++void pkg_vec_sort(pkg_vec_t *vec, int (*compar)(pkg_t *, pkg_t *))
++{
++ qsort(vec->pkgs, vec->len, sizeof(pkg_t *), (compare_fcn_t)compar);
++}
++
++int pkg_vec_clear_marks(pkg_vec_t *vec)
++{
++ int npkgs = vec->len;
++ int i;
++ for (i = 0; i < npkgs; i++) {
++ pkg_t *pkg = vec->pkgs[i];
++ pkg->state_flag &= ~SF_MARKED;
++ }
++ return 0;
++}
++
++int pkg_vec_mark_if_matches(pkg_vec_t *vec, const char *pattern)
++{
++ int matching_count = 0;
++ pkg_t **pkgs = vec->pkgs;
++ int npkgs = vec->len;
++ int i;
++ for (i = 0; i < npkgs; i++) {
++ pkg_t *pkg = pkgs[i];
++ if (fnmatch(pattern, pkg->name, 0)==0) {
++ pkg->state_flag |= SF_MARKED;
++ matching_count++;
++ }
++ }
++ return matching_count;
++}
++
++
++abstract_pkg_vec_t * abstract_pkg_vec_alloc(void)
++{
++ abstract_pkg_vec_t * vec ;
++ vec = (abstract_pkg_vec_t *)malloc(sizeof(abstract_pkg_vec_t));
++ if (!vec) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ vec->pkgs = NULL;
++ vec->len = 0;
++
++ return vec;
++}
++
++void abstract_pkg_vec_free(abstract_pkg_vec_t *vec)
++{
++ free(vec->pkgs);
++ free(vec);
++}
++
++/*
++ * assumption: all names in a vector are unique
++ */
++void abstract_pkg_vec_insert(abstract_pkg_vec_t *vec, abstract_pkg_t *pkg)
++{
++ int i;
++
++ /* look for a duplicate pkg by name */
++ for(i = 0; i < vec->len; i++)
++ if (strcmp(pkg->name, vec->pkgs[i]->name) == 0)
++ break;
++
++ /* we didn't find one, add it */
++ if(i == vec->len){
++ vec->pkgs =
++ (abstract_pkg_t **)
++ realloc(vec->pkgs, (vec->len + 1) * sizeof(abstract_pkg_t *));
++ vec->pkgs[vec->len] = pkg;
++ vec->len++;
++ }
++}
++
++abstract_pkg_t * abstract_pkg_vec_get(abstract_pkg_vec_t *vec, int i)
++{
++ if (vec->len > i)
++ return vec->pkgs[i];
++ else
++ return NULL;
++}
++
++int abstract_pkg_vec_contains(abstract_pkg_vec_t *vec, abstract_pkg_t *apkg)
++{
++ int i;
++ for (i = 0; i < vec->len; i++)
++ if (vec->pkgs[i] == apkg)
++ return 1;
++ return 0;
++}
++
++void abstract_pkg_vec_sort(pkg_vec_t *vec, int (*compar)(abstract_pkg_t *, abstract_pkg_t *))
++{
++ qsort(vec->pkgs, vec->len, sizeof(pkg_t *), (compare_fcn_t)compar);
++}
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/pkg_vec.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_vec.h
+--- busybox-1.2.0-orig/archival/libipkg/pkg_vec.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/pkg_vec.h 2006-07-22 16:31:26.000000000 +0200
+@@ -0,0 +1,62 @@
++/* pkg_vec.h - the itsy package management system
++
++ Steven M. Ayer
++
++ Copyright (C) 2002 Compaq Computer Corporation
++
++ 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.
++*/
++
++#ifndef PKG_VEC_H
++#define PKG_VEC_H
++
++typedef struct pkg pkg_t;
++typedef struct abstract_pkg abstract_pkg_t;
++
++struct pkg_vec
++{
++ pkg_t **pkgs;
++ int len;
++};
++typedef struct pkg_vec pkg_vec_t;
++
++struct abstract_pkg_vec
++{
++ abstract_pkg_t **pkgs;
++ int len;
++};
++typedef struct abstract_pkg_vec abstract_pkg_vec_t;
++
++
++pkg_vec_t * pkg_vec_alloc(void);
++void pkg_vec_free(pkg_vec_t *vec);
++void marry_two_packages(pkg_t * newpkg, pkg_t * oldpkg);
++
++void pkg_vec_add(pkg_vec_t *vec, pkg_t *pkg);
++/* pkg_vec_insert_merge: might munge pkg.
++* returns the pkg that is in the pkg graph */
++pkg_t *pkg_vec_insert_merge(pkg_vec_t *vec, pkg_t *pkg, int set_status, ipkg_conf_t *conf);
++/* this one never munges pkg */
++void pkg_vec_insert(pkg_vec_t *vec, const pkg_t *pkg);
++int pkg_vec_contains(pkg_vec_t *vec, pkg_t *apkg);
++void pkg_vec_sort(pkg_vec_t *vec, int (*compar)(pkg_t *, pkg_t *));
++
++int pkg_vec_clear_marks(pkg_vec_t *vec);
++int pkg_vec_mark_if_matches(pkg_vec_t *vec, const char *pattern);
++
++abstract_pkg_vec_t * abstract_pkg_vec_alloc(void);
++void abstract_pkg_vec_free(abstract_pkg_vec_t *vec);
++void abstract_pkg_vec_insert(abstract_pkg_vec_t *vec, abstract_pkg_t *pkg);
++abstract_pkg_t * abstract_pkg_vec_get(abstract_pkg_vec_t *vec, int i);
++int abstract_pkg_vec_contains(abstract_pkg_vec_t *vec, abstract_pkg_t *apkg);
++void abstract_pkg_vec_sort(pkg_vec_t *vec, int (*compar)(abstract_pkg_t *, abstract_pkg_t *));
++#endif
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/sprintf_alloc.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/sprintf_alloc.h
+--- busybox-1.2.0-orig/archival/libipkg/sprintf_alloc.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/sprintf_alloc.h 2006-07-22 16:31:26.000000000 +0200
+@@ -0,0 +1,25 @@
++/* sprintf_alloca.c -- like sprintf with memory allocation
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef SPRINTF_ALLOC_H
++#define SPRINTF_ALLOC_H
++
++#include "libbb.h"
++
++#define sprintf_alloc(str, fmt, args...) *str = bb_xasprintf(fmt, ## args)
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/str_list.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/str_list.c
+--- busybox-1.2.0-orig/archival/libipkg/str_list.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/str_list.c 2006-07-22 16:31:26.000000000 +0200
+@@ -0,0 +1,76 @@
++/* str_list.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++
++#include "str_list.h"
++
++int str_list_elt_init(str_list_elt_t *elt, char *data)
++{
++ return void_list_elt_init((void_list_elt_t *) elt, data);
++}
++
++void str_list_elt_deinit(str_list_elt_t *elt)
++{
++ void_list_elt_deinit((void_list_elt_t *) elt);
++}
++
++str_list_t *str_list_alloc()
++{
++ str_list_t *list = (str_list_t *)malloc(sizeof(str_list_t));
++ if (list)
++ str_list_init(list);
++ return list;
++}
++
++int str_list_init(str_list_t *list)
++{
++ return void_list_init((void_list_t *) list);
++}
++
++void str_list_deinit(str_list_t *list)
++{
++ void_list_deinit((void_list_t *) list);
++}
++
++int str_list_append(str_list_t *list, char *data)
++{
++ return void_list_append((void_list_t *) list, data);
++}
++
++int str_list_push(str_list_t *list, char *data)
++{
++ return void_list_push((void_list_t *) list, data);
++}
++
++str_list_elt_t *str_list_pop(str_list_t *list)
++{
++ return (str_list_elt_t *) void_list_pop((void_list_t *) list);
++}
++
++str_list_elt_t *str_list_remove(str_list_t *list, str_list_elt_t **iter)
++{
++ return (str_list_elt_t *) void_list_remove((void_list_t *) list,
++ (void_list_elt_t **) iter);
++}
++
++char *str_list_remove_elt(str_list_t *list, const char *target_str)
++{
++ return (char *)void_list_remove_elt((void_list_t *) list,
++ (void *)target_str,
++ (void_list_cmp_t)strcmp);
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/str_list.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/str_list.h
+--- busybox-1.2.0-orig/archival/libipkg/str_list.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/str_list.h 2006-07-22 16:31:26.000000000 +0200
+@@ -0,0 +1,51 @@
++/* str_list.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef STR_LIST_H
++#define STR_LIST_H
++
++#include "void_list.h"
++
++typedef struct str_list_elt str_list_elt_t;
++struct str_list_elt
++{
++ str_list_elt_t *next;
++ char *data;
++};
++
++typedef struct xstr_list str_list_t;
++struct xstr_list
++{
++ str_list_elt_t pre_head;
++ str_list_elt_t *head;
++ str_list_elt_t *tail;
++};
++
++int str_list_elt_init(str_list_elt_t *elt, char *data);
++void str_list_elt_deinit(str_list_elt_t *elt);
++
++str_list_t *str_list_alloc(void);
++int str_list_init(str_list_t *list);
++void str_list_deinit(str_list_t *list);
++
++int str_list_append(str_list_t *list, char *data);
++int str_list_push(str_list_t *list, char *data);
++str_list_elt_t *str_list_pop(str_list_t *list);
++str_list_elt_t *str_list_remove(str_list_t *list, str_list_elt_t **iter);
++char *str_list_remove_elt(str_list_t *list, const char *target_str);
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/str_util.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/str_util.c
+--- busybox-1.2.0-orig/archival/libipkg/str_util.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/str_util.c 2006-07-22 16:31:26.000000000 +0200
+@@ -0,0 +1,73 @@
++/* str_utils.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++
++int str_starts_with(const char *str, const char *prefix)
++{
++ return (strncmp(str, prefix, strlen(prefix)) == 0);
++}
++
++int str_ends_with(const char *str, const char *suffix)
++{
++ int suffix_len;
++ int str_len;
++
++ str_len = strlen(str);
++ suffix_len = strlen(suffix);
++
++ if (str_len < suffix_len) {
++ return 0;
++ }
++
++ return (strcmp(str + str_len - suffix_len, suffix) == 0);
++}
++
++int str_chomp(char *str)
++{
++ if (str[strlen(str) - 1] == '\n') {
++ str[strlen(str) - 1] = '\0';
++ return 1;
++ }
++ return 0;
++}
++
++int str_tolower(char *str)
++{
++ while (*str) {
++ *str = tolower(*str);
++ str++;
++ }
++
++ return 0;
++}
++
++int str_toupper(char *str)
++{
++ while (*str) {
++ *str = toupper(*str);
++ str++;
++ }
++
++ return 0;
++}
++
++char *str_dup_safe(const char *str)
++{
++ return str ? strdup(str) : NULL;
++}
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/str_util.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/str_util.h
+--- busybox-1.2.0-orig/archival/libipkg/str_util.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/str_util.h 2006-07-22 16:31:26.000000000 +0200
+@@ -0,0 +1,28 @@
++/* str_utils.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef STR_UTILS_H
++#define STR_UTILS_H
++
++int str_starts_with(const char *str, const char *prefix);
++int str_ends_with(const char *str, const char *suffix);
++int str_chomp(char *str);
++int str_tolower(char *str);
++int str_toupper(char *str);
++char *str_dup_safe(const char *str);
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/user.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/user.c
+--- busybox-1.2.0-orig/archival/libipkg/user.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/user.c 2006-07-22 16:31:26.000000000 +0200
+@@ -0,0 +1,58 @@
++/* user.c - the itsy package management system
++
++ Jamey Hicks
++
++ Copyright (C) 2002 Hewlett Packard Company
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include <stdio.h>
++#include <stdarg.h>
++#include "file_util.h"
++#include "str_util.h"
++#ifdef IPKG_LIB
++#include "libipkg.h"
++#endif
++
++
++#ifdef IPKG_LIB
++static char *question = NULL;
++static int question_len = 255;
++#endif
++char *get_user_response(const char *format, ...)
++{
++ int len = question_len;
++ va_list ap;
++ char *response;
++ va_start(ap, format);
++
++#ifndef IPKG_LIB
++ vprintf(format, ap);
++ do {
++ response = file_read_line_alloc(stdin);
++ } while (response == NULL);
++#else
++ do {
++ if (question == NULL || len > question_len) {
++ question = realloc(question, len + 1);
++ question_len = len;
++ }
++ len = vsnprintf(question,question_len,format,ap);
++ } while (len > question_len);
++ response = strdup(ipkg_cb_response(question));
++#endif
++ str_chomp(response);
++ str_tolower(response);
++
++ return response;
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/user.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/user.h
+--- busybox-1.2.0-orig/archival/libipkg/user.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/user.h 2006-07-22 16:31:26.000000000 +0200
+@@ -0,0 +1,23 @@
++/* user.c - the itsy package management system
++
++ Jamey Hicks
++
++ Copyright (C) 2002 Hewlett Packard Company
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include <stdio.h>
++#include <stdarg.h>
++
++char *get_user_response(const char *format, ...);
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/void_list.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/void_list.c
+--- busybox-1.2.0-orig/archival/libipkg/void_list.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/void_list.c 2006-07-22 16:31:26.000000000 +0200
+@@ -0,0 +1,194 @@
++/* void_list.c - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++#include <errno.h>
++
++#include "void_list.h"
++
++int void_list_elt_init(void_list_elt_t *elt, void *data)
++{
++ elt->next = NULL;
++ elt->data = data;
++
++ return 0;
++}
++
++void void_list_elt_deinit(void_list_elt_t *elt)
++{
++ void_list_elt_init(elt, NULL);
++}
++
++int void_list_init(void_list_t *list)
++{
++ void_list_elt_init(&list->pre_head, NULL);
++ list->head = NULL;
++ list->pre_head.next = list->head;
++ list->tail = NULL;
++
++ return 0;
++}
++
++void void_list_deinit(void_list_t *list)
++{
++ void_list_elt_t *elt;
++
++ while (list->head) {
++ elt = void_list_pop(list);
++ void_list_elt_deinit(elt);
++ /* malloced in void_list_append */
++ free(elt);
++ }
++}
++
++int void_list_append(void_list_t *list, void *data)
++{
++ void_list_elt_t *elt;
++
++ /* freed in void_list_deinit */
++ elt = malloc(sizeof(void_list_elt_t));
++ if (elt == NULL) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return ENOMEM;
++ }
++
++ void_list_elt_init(elt, data);
++
++ if (list->tail) {
++ list->tail->next = elt;
++ list->tail = elt;
++ } else {
++ list->head = elt;
++ list->pre_head.next = list->head;
++ list->tail = elt;
++ }
++
++ return 0;
++}
++
++int void_list_push(void_list_t *list, void *data)
++{
++ void_list_elt_t *elt;
++
++ elt = malloc(sizeof(void_list_elt_t));
++ if (elt == NULL) {
++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++ return ENOMEM;
++ }
++
++ void_list_elt_init(elt, data);
++
++ elt->next = list->head;
++ list->head->next = elt;
++ if (list->tail == NULL) {
++ list->tail = list->head;
++ }
++
++ return 0;
++}
++
++void_list_elt_t *void_list_pop(void_list_t *list)
++{
++ void_list_elt_t *elt;
++
++ elt = list->head;
++
++ if (list->head) {
++ list->head = list->head->next;
++ list->pre_head.next = list->head;
++ if (list->head == NULL) {
++ list->tail = NULL;
++ }
++ }
++
++ return elt;
++}
++
++void *void_list_remove(void_list_t *list, void_list_elt_t **iter)
++{
++ void_list_elt_t *prior;
++ void_list_elt_t *old_elt;
++ void *old_data;
++
++ old_elt = *iter;
++ old_data = old_elt->data;
++
++ if (old_elt == list->head) {
++ prior = &list->pre_head;
++ void_list_pop(list);
++ } else {
++ for (prior = list->head; prior; prior = prior->next) {
++ if (prior->next == old_elt) {
++ break;
++ }
++ }
++ if (prior == NULL || prior->next != old_elt) {
++ fprintf(stderr, "%s: ERROR: element not found in list\n", __FUNCTION__);
++ return NULL;
++ }
++ prior->next = old_elt->next;
++
++ if (old_elt == list->tail) {
++ list->tail = prior;
++ }
++ }
++
++ void_list_elt_deinit(old_elt);
++ *iter = prior;
++
++ return old_data;
++}
++
++/* remove element containing elt data, using cmp(elt->data, target_data) == 0. */
++void *void_list_remove_elt(void_list_t *list, const void *target_data, void_list_cmp_t cmp)
++{
++ void_list_elt_t *prior;
++ void_list_elt_t *old_elt = NULL;
++ void *old_data = NULL;
++
++ /* first element */
++ if (list->head && list->head->data && (cmp(list->head->data, target_data) == 0)) {
++ old_elt = list->head;
++ old_data = list->head->data;
++ void_list_pop(list);
++ } else {
++ int found = 0;
++ for (prior = list->head; prior && prior->next; prior = prior->next) {
++ if (prior->next->data && (cmp(prior->next->data, target_data) == 0)) {
++ old_elt = prior->next;
++ old_data = old_elt->data;
++ found = 1;
++ break;
++ }
++ }
++ if (!found) {
++ return NULL;
++ }
++ prior->next = old_elt->next;
++
++ if (old_elt == list->tail) {
++ list->tail = prior;
++ }
++ }
++ if (old_elt)
++ void_list_elt_deinit(old_elt);
++
++ if (old_data)
++ return old_data;
++ else
++ return NULL;
++}
+diff -ruN busybox-1.2.0-orig/archival/libipkg/void_list.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/void_list.h
+--- busybox-1.2.0-orig/archival/libipkg/void_list.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/void_list.h 2006-07-22 16:31:26.000000000 +0200
+@@ -0,0 +1,59 @@
++/* void_list.h - the itsy package management system
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef VOID_LIST_H
++#define VOID_LIST_H
++
++typedef struct void_list_elt void_list_elt_t;
++struct void_list_elt
++{
++ void_list_elt_t *next;
++ void *data;
++};
++
++typedef struct void_list void_list_t;
++struct void_list
++{
++ void_list_elt_t pre_head;
++ void_list_elt_t *head;
++ void_list_elt_t *tail;
++};
++
++static inline int void_list_empty(void_list_t *list)
++{
++ if (list->head == NULL)
++ return 1;
++ else
++ return 0;
++}
++
++int void_list_elt_init(void_list_elt_t *elt, void *data);
++void void_list_elt_deinit(void_list_elt_t *elt);
++
++int void_list_init(void_list_t *list);
++void void_list_deinit(void_list_t *list);
++
++int void_list_append(void_list_t *list, void *data);
++int void_list_push(void_list_t *list, void *data);
++void_list_elt_t *void_list_pop(void_list_t *list);
++
++void *void_list_remove(void_list_t *list, void_list_elt_t **iter);
++/* remove element containing elt data, using cmp(elt->data, target_data) == 0. */
++typedef int (*void_list_cmp_t)(const void *, const void *);
++void *void_list_remove_elt(void_list_t *list, const void *target_data, void_list_cmp_t cmp);
++
++#endif
+diff -ruN busybox-1.2.0-orig/archival/libipkg/xsystem.c busybox-1.2.0+ipkg-0.99.162/archival/libipkg/xsystem.c
+--- busybox-1.2.0-orig/archival/libipkg/xsystem.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/xsystem.c 2006-07-22 16:31:26.000000000 +0200
+@@ -0,0 +1,64 @@
++/* xsystem.c - system(3) with error messages
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#include "ipkg.h"
++#include <sys/wait.h>
++
++#include "xsystem.h"
++
++/* XXX: FEATURE: I shouldn't actually use system(3) at all. I don't
++ really need the /bin/sh invocation which takes resources and
++ introduces security problems. I should switch all of this to a sort
++ of execl() or execv() interface/implementation.
++*/
++
++/* Like system(3), but with error messages printed if the fork fails
++ or if the child process dies due to an uncaught signal. Also, the
++ return value is a bit simpler:
++
++ -1 if there was any problem
++ Otherwise, the 8-bit return value of the program ala WEXITSTATUS
++ as defined in <sys/wait.h>.
++*/
++int xsystem(const char *cmd)
++{
++ int err;
++
++ err = system(cmd);
++
++ if (err == -1) {
++ fprintf(stderr, "%s: ERROR: fork failed before execution: `%s'\n",
++ __FUNCTION__, cmd);
++ return -1;
++ }
++
++ if (WIFSIGNALED(err)) {
++ fprintf(stderr, "%s: ERROR: Child process died due to signal %d: `%s'\n",
++ __FUNCTION__, WTERMSIG(err), cmd);
++ return -1;
++ }
++
++ if (WIFEXITED(err)) {
++ /* Normal child exit */
++ return WEXITSTATUS(err);
++ }
++
++ fprintf(stderr, "%s: ERROR: Received unintelligible return value from system: %d",
++ __FUNCTION__, err);
++ return -1;
++}
++
+diff -ruN busybox-1.2.0-orig/archival/libipkg/xsystem.h busybox-1.2.0+ipkg-0.99.162/archival/libipkg/xsystem.h
+--- busybox-1.2.0-orig/archival/libipkg/xsystem.h 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0+ipkg-0.99.162/archival/libipkg/xsystem.h 2006-07-22 16:31:26.000000000 +0200
+@@ -0,0 +1,34 @@
++/* xsystem.h - system(3) with error messages
++
++ Carl D. Worth
++
++ Copyright (C) 2001 University of Southern California
++
++ 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.
++*/
++
++#ifndef XSYSTEM_H
++#define XSYSTEM_H
++
++#include <stdlib.h>
++
++/* Like system(3), but with error messages printed if the fork fails
++ or if the child process dies due to an uncaught signal. Also, the
++ return value is a bit simpler:
++
++ -1 if there was any problem
++ Otherwise, the 8-bit return value of the program ala WEXITSTATUS
++ as defined in <sys/wait.h>.
++*/
++int xsystem(const char *cmd);
++
++#endif
++
+diff -ruN busybox-1.2.0-orig/archival/libunarchive/data_extract_all.c busybox-1.2.0+ipkg-0.99.162/archival/libunarchive/data_extract_all.c
+--- busybox-1.2.0-orig/archival/libunarchive/data_extract_all.c 2006-07-01 00:42:04.000000000 +0200
++++ busybox-1.2.0+ipkg-0.99.162/archival/libunarchive/data_extract_all.c 2006-07-22 16:31:26.000000000 +0200
+@@ -126,3 +126,17 @@
+ utime(file_header->name, &t);
+ }
+ }
++
++extern void data_extract_all_prefix(archive_handle_t *archive_handle)
++{
++ char *name_ptr = archive_handle->file_header->name;
++
++ name_ptr += strspn(name_ptr, "./");
++ if (name_ptr[0] != '\0') {
++ archive_handle->file_header->name = xmalloc(strlen(archive_handle->buffer) + 1 + strlen(name_ptr) + 1);
++ strcpy(archive_handle->file_header->name, archive_handle->buffer);
++ strcat(archive_handle->file_header->name, name_ptr);
++ data_extract_all(archive_handle);
++ }
++}
++
+diff -ruN busybox-1.2.0-orig/archival/libunarchive/Makefile.in busybox-1.2.0+ipkg-0.99.162/archival/libunarchive/Makefile.in
+--- busybox-1.2.0-orig/archival/libunarchive/Makefile.in 2006-07-01 00:42:03.000000000 +0200
++++ busybox-1.2.0+ipkg-0.99.162/archival/libunarchive/Makefile.in 2006-07-22 16:31:26.000000000 +0200
+@@ -58,6 +58,7 @@
+ LIBUNARCHIVE-$(CONFIG_FEATURE_DEB_TAR_LZMA) += decompress_unlzma.o get_header_tar_lzma.o
+ LIBUNARCHIVE-$(CONFIG_GUNZIP) += $(GUNZIP_FILES)
+ LIBUNARCHIVE-$(CONFIG_FEATURE_GUNZIP_UNCOMPRESS) += decompress_uncompress.o
++LIBUNARCHIVE-$(CONFIG_IPKG) += $(GUNZIP_FILES) get_header_tar.o get_header_tar_gz.o
+ LIBUNARCHIVE-$(CONFIG_RPM2CPIO) += $(GUNZIP_FILES) get_header_cpio.o
+ LIBUNARCHIVE-$(CONFIG_RPM) += $(GUNZIP_FILES) get_header_cpio.o
+ LIBUNARCHIVE-$(CONFIG_TAR) += get_header_tar.o
+diff -ruN busybox-1.2.0-orig/archival/Makefile.in busybox-1.2.0+ipkg-0.99.162/archival/Makefile.in
+--- busybox-1.2.0-orig/archival/Makefile.in 2006-07-01 00:42:04.000000000 +0200
++++ busybox-1.2.0+ipkg-0.99.162/archival/Makefile.in 2006-07-22 16:31:25.000000000 +0200
+@@ -20,6 +20,7 @@
+ ARCHIVAL-$(CONFIG_DPKG_DEB) += dpkg_deb.o
+ ARCHIVAL-$(CONFIG_GUNZIP) += gunzip.o
+ ARCHIVAL-$(CONFIG_GZIP) += gzip.o
++ARCHIVAL-$(CONFIG_IPKG) += ipkg.o
+ ARCHIVAL-$(CONFIG_RPM2CPIO) += rpm2cpio.o
+ ARCHIVAL-$(CONFIG_RPM) += rpm.o
+ ARCHIVAL-$(CONFIG_TAR) += tar.o
+diff -ruN busybox-1.2.0-orig/include/applets.h busybox-1.2.0+ipkg-0.99.162/include/applets.h
+--- busybox-1.2.0-orig/include/applets.h 2006-07-01 00:42:10.000000000 +0200
++++ busybox-1.2.0+ipkg-0.99.162/include/applets.h 2006-07-22 16:35:35.000000000 +0200
+@@ -152,6 +152,7 @@
+ USE_IPCALC(APPLET(ipcalc, _BB_DIR_BIN, _BB_SUID_NEVER))
+ USE_IPCRM(APPLET(ipcrm, _BB_DIR_USR_BIN, _BB_SUID_ALWAYS))
+ USE_IPCS(APPLET(ipcs, _BB_DIR_USR_BIN, _BB_SUID_ALWAYS))
++USE_IPKG(APPLET(ipkg, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+ USE_IPLINK(APPLET(iplink, _BB_DIR_BIN, _BB_SUID_NEVER))
+ USE_IPROUTE(APPLET(iproute, _BB_DIR_BIN, _BB_SUID_NEVER))
+ USE_IPTUNNEL(APPLET(iptunnel, _BB_DIR_BIN, _BB_SUID_NEVER))
+diff -ruN busybox-1.2.0-orig/include/unarchive.h busybox-1.2.0+ipkg-0.99.162/include/unarchive.h
+--- busybox-1.2.0-orig/include/unarchive.h 2006-07-01 00:42:10.000000000 +0200
++++ busybox-1.2.0+ipkg-0.99.162/include/unarchive.h 2006-07-22 16:31:26.000000000 +0200
+@@ -77,6 +77,7 @@
+
+ extern void data_skip(archive_handle_t *archive_handle);
+ extern void data_extract_all(archive_handle_t *archive_handle);
++extern void data_extract_all_prefix(archive_handle_t *archive_handle);
+ extern void data_extract_to_stdout(archive_handle_t *archive_handle);
+ extern void data_extract_to_buffer(archive_handle_t *archive_handle);
+
+diff -ruN busybox-1.2.0-orig/include/usage.h busybox-1.2.0+ipkg-0.99.162/include/usage.h
+--- busybox-1.2.0-orig/include/usage.h 2006-07-01 00:42:10.000000000 +0200
++++ busybox-1.2.0+ipkg-0.99.162/include/usage.h 2006-07-22 16:31:26.000000000 +0200
+@@ -982,6 +982,82 @@
+ "$ ls -la /tmp/busybox*\n" \
+ "-rw-rw-r-- 1 andersen andersen 554058 Apr 14 17:49 /tmp/busybox.tar.gz\n"
+
++#define ipkg_trivial_usage \
++ "[options]... sub-command [arguments]..."
++#define ipkg_full_usage \
++ "ipkg is an utility to install, remove and manage .ipk packages.\n" \
++ "\n" \
++ "Sub-commands:\n" \
++ "\nPackage Manipulation:\n" \
++ "\tupdate Update list of available packages\n" \
++ "\tupgrade Upgrade all installed packages to latest version\n" \
++ "\tinstall <pkg> Download and install <pkg> (and dependencies)\n" \
++ "\tinstall <file.ipk> Install package <file.ipk>\n" \
++ "\tconfigure [<pkg>] Configure unpacked packages\n" \
++ "\tremove <pkg|regexp> Remove package <pkg|packages following regexp>\n" \
++ "\tflag <flag> <pkg> ... Flag package(s) <pkg>\n" \
++ "\t <flag>=hold|noprune|user|ok|installed|unpacked (one per invocation) \n" \
++ "\n" \
++ "Informational Commands:\n" \
++ "\tlist List available packages and descriptions\n" \
++ "\tlist_installed List all and only the installed packages and description \n" \
++ "\tfiles <pkg> List all files belonging to <pkg>\n" \
++ "\tsearch <file|regexp> Search for a package providing <file>\n" \
++ "\tinfo [pkg|regexp [<field>]] Display all/some info fields for <pkg> or all\n" \
++ "\tstatus [pkg|regexp [<field>]] Display all/some status fields for <pkg> or all\n" \
++ "\tdownload <pkg> Download <pkg> to current directory.\n" \
++ "\tcompare_versions <v1> <op> <v2>\n" \
++ "\t compare versions using <= < > >= = << >>\n" \
++ "\tprint_architecture prints the architecture.\n" \
++ "\tprint_installation_architecture\n" \
++ "\twhatdepends [-A] [pkgname|pat]+\n" \
++ "\twhatdependsrec [-A] [pkgname|pat]+\n" \
++ "\twhatprovides [-A] [pkgname|pat]+\n" \
++ "\twhatconflicts [-A] [pkgname|pat]+\n" \
++ "\twhatreplaces [-A] [pkgname|pat]+\n" \
++ "\t prints the installation architecture.\n" \
++ "\n" \
++ "\nOptions:\n" \
++ "\t-A Query all packages with whatdepends, whatprovides, whatreplaces, whatconflicts\n" \
++ "\t-V <level> Set verbosity level to <level>. If no value is\n" \
++ "\t--verbosity <level> provided increase verbosity by one. Verbosity levels:\n" \
++ "\t 0 errors only\n" \
++ "\t 1 normal messages (default)\n" \
++ "\t 2 informative messages\n" \
++ "\t 3 debug output\n" \
++ "\t-f <conf_file> Use <conf_file> as the ipkg configuration file\n" \
++ "\t-conf <conf_file> Default configuration file location\n" \
++ " is /etc/ipkg.conf\n" \
++ "\t-d <dest_name> Use <dest_name> as the the root directory for\n" \
++ "\t-dest <dest_name> package installation, removal, upgrading.\n" \
++ " <dest_name> should be a defined dest name from\n" \
++ " the configuration file, (but can also be a\n" \
++ " directory name in a pinch).\n" \
++ "\t-o <offline_root> Use <offline_root> as the root directory for\n" \
++ "\t-offline <offline_root> offline installation of packages.\n" \
++ "\t-verbose_wget more wget messages\n" \
++ "\n" \
++ "Force Options (use when ipkg is too smart for its own good):\n" \
++ "\t-force-depends Make dependency checks warnings instead of errors\n" \
++ "\t Install/remove package in spite of failed dependences\n" \
++ "\t-force-defaults Use default options for questions asked by ipkg.\n" \
++ " (no prompts). Note that this will not prevent\n" \
++ " package installation scripts from prompting.\n" \
++ "\t-force-reinstall Allow ipkg to reinstall a package.\n" \
++ "\t-force-overwrite Allow ipkg to overwrite files from another package during an install.\n" \
++ "\t-force-downgrade Allow ipkg to downgrade packages.\n" \
++ "\t-force_space Install even if there does not seem to be enough space.\n" \
++ "\t-noaction No action -- test only\n" \
++ "\t-nodeps Do not follow dependences\n" \
++ "\t-force-removal-of-dependent-packages\n" \
++ "\t-recursive Allow ipkg to remove package and all that depend on it.\n" \
++ "\t-test No action -- test only\n" \
++ "\t-t Specify tmp-dir.\n" \
++ "\t--tmp-dir Specify tmp-dir.\n" \
++ "\n" \
++ "\tregexp could be something like 'pkgname*' '*file*' or similar\n" \
++ "\teg: ipkg info 'libstd*' or ipkg search '*libop*' or ipkg remove 'libncur*'\n"
++
+ #define halt_trivial_usage \
+ "[-d<delay>] [-n<nosync>] [-f<force>]"
+ #define halt_full_usage \
+diff -ruN busybox-1.2.0-orig/Makefile busybox-1.2.0+ipkg-0.99.162/Makefile
+--- busybox-1.2.0-orig/Makefile 2006-07-01 00:42:13.000000000 +0200
++++ busybox-1.2.0+ipkg-0.99.162/Makefile 2006-07-22 16:31:25.000000000 +0200
+@@ -31,7 +31,7 @@
+ export srctree=$(top_srcdir)
+ vpath %/Config.in $(srctree)
+
+-DIRS:=applets archival archival/libunarchive coreutils console-tools \
++DIRS:=applets archival archival/libipkg archival/libunarchive coreutils console-tools \
+ debianutils editors findutils init miscutils modutils networking \
+ networking/libiproute networking/udhcp procps loginutils shell \
+ sysklogd util-linux e2fsprogs libpwdgrp coreutils/libcoreutils libbb
diff --git a/package/busybox/patches/912-ipkg-no_warnings.patch b/package/busybox/patches/912-ipkg-no_warnings.patch
new file mode 100644
index 0000000000..b5ba7705fb
--- /dev/null
+++ b/package/busybox/patches/912-ipkg-no_warnings.patch
@@ -0,0 +1,448 @@
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# remove (numerous) compile warnings
+#
+diff -ruN busybox-1.1.2+ipkg-0.99.162/archival/libipkg/file_util.c busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/file_util.c
+--- busybox-1.1.2+ipkg-0.99.162/archival/libipkg/file_util.c 2006-05-09 02:06:48.000000000 +0200
++++ busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/file_util.c 2006-05-09 02:16:48.000000000 +0200
+@@ -123,7 +123,7 @@
+
+ int file_mkdir_hier(const char *path, long mode)
+ {
+- return bb_make_directory(path, mode, FILEUTILS_RECUR);
++ return bb_make_directory((char *)path, mode, FILEUTILS_RECUR);
+ }
+
+ char *file_md5sum_alloc(const char *file_name)
+diff -ruN busybox-1.1.2+ipkg-0.99.162/archival/libipkg/ipkg_cmd.c busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/ipkg_cmd.c
+--- busybox-1.1.2+ipkg-0.99.162/archival/libipkg/ipkg_cmd.c 2006-05-09 02:23:37.000000000 +0200
++++ busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/ipkg_cmd.c 2006-05-09 02:23:17.000000000 +0200
+@@ -246,7 +246,7 @@
+ in = fopen (tmp_file_name, "r");
+ out = fopen (list_file_name, "w");
+ if (in && out)
+- inflate_unzip (in, out);
++ inflate_unzip (fileno(in), fileno(out));
+ else
+ err = 1;
+ if (in)
+@@ -894,14 +894,13 @@
+ pkg_vec_free(available);
+ } else {
+ pkg_vec_t *installed_pkgs = pkg_vec_alloc();
+- int i;
+ int flagged_pkg_count = 0;
+ int removed;
+
+ pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
+
+ for (i = 0; i < installed_pkgs->len; i++) {
+- pkg_t *pkg = installed_pkgs->pkgs[i];
++ pkg = installed_pkgs->pkgs[i];
+ if (pkg->state_flag & SF_USER) {
+ flagged_pkg_count++;
+ } else {
+@@ -921,7 +920,7 @@
+ do {
+ removed = 0;
+ for (i = 0; i < installed_pkgs->len; i++) {
+- pkg_t *pkg = installed_pkgs->pkgs[i];
++ pkg = installed_pkgs->pkgs[i];
+ if (!(pkg->state_flag & SF_USER)
+ && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
+ removed++;
+@@ -976,7 +975,7 @@
+ {
+ int i;
+ pkg_t *pkg;
+- const char *flags = argv[0];
++ char *flags = argv[0];
+
+ global_conf = conf;
+ signal(SIGINT, sigint_handler);
+diff -ruN busybox-1.1.2+ipkg-0.99.162/archival/libipkg/ipkg_conf.c busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/ipkg_conf.c
+--- busybox-1.1.2+ipkg-0.99.162/archival/libipkg/ipkg_conf.c 2006-05-09 02:12:04.000000000 +0200
++++ busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/ipkg_conf.c 2006-05-09 02:16:48.000000000 +0200
+@@ -542,14 +542,14 @@
+ if (strcmp(type, "option") == 0) {
+ ipkg_conf_set_option(options, name, value);
+ } else if (strcmp(type, "src") == 0) {
+- if (!nv_pair_list_find(pkg_src_list, name)) {
++ if (!nv_pair_list_find((nv_pair_list_t *)pkg_src_list, name)) {
+ pkg_src_list_append (pkg_src_list, name, value, extra, 0);
+ } else {
+ ipkg_message(conf, IPKG_ERROR, "ERROR: duplicate src declaration. Skipping:\n\t src %s %s\n",
+ name, value);
+ }
+ } else if (strcmp(type, "src/gz") == 0) {
+- if (!nv_pair_list_find(pkg_src_list, name)) {
++ if (!nv_pair_list_find((nv_pair_list_t *)pkg_src_list, name)) {
+ pkg_src_list_append (pkg_src_list, name, value, extra, 1);
+ } else {
+ ipkg_message(conf, IPKG_ERROR, "ERROR: duplicate src declaration. Skipping:\n\t src %s %s\n",
+diff -ruN busybox-1.1.2+ipkg-0.99.162/archival/libipkg/ipkg_download.c busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/ipkg_download.c
+--- busybox-1.1.2+ipkg-0.99.162/archival/libipkg/ipkg_download.c 2006-05-09 02:12:04.000000000 +0200
++++ busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/ipkg_download.c 2006-05-09 02:22:51.000000000 +0200
+@@ -166,7 +166,7 @@
+ if (err)
+ return err;
+ pkg->local_filename = strdup(url);
+- ipkg_message(conf, IPKG_DEBUG2, "Package %s provided by hand \(%s\).\n", pkg->name,pkg->local_filename);
++ ipkg_message(conf, IPKG_DEBUG2, "Package %s provided by hand (%s).\n", pkg->name,pkg->local_filename);
+ pkg->provided_by_hand = 1;
+
+ } else {
+diff -ruN busybox-1.1.2+ipkg-0.99.162/archival/libipkg/libipkg.c busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/libipkg.c
+--- busybox-1.1.2+ipkg-0.99.162/archival/libipkg/libipkg.c 2006-05-09 02:12:05.000000000 +0200
++++ busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/libipkg.c 2006-05-09 02:16:48.000000000 +0200
+@@ -445,7 +445,7 @@
+ int
+ ipkg_op (int argc, char *argv[])
+ {
+- int err, optind;
++ int err, opt_index;
+ args_t args;
+ char *cmd_name;
+ ipkg_cmd_t *cmd;
+@@ -453,13 +453,13 @@
+
+ args_init (&args);
+
+- optind = args_parse (&args, argc, argv);
+- if (optind == argc || optind < 0)
++ opt_index = args_parse (&args, argc, argv);
++ if (opt_index == argc || opt_index < 0)
+ {
+ args_usage ("ipkg must have one sub-command argument");
+ }
+
+- cmd_name = argv[optind++];
++ cmd_name = argv[opt_index++];
+ /* Pigi: added a flag to disable the checking of structures if the command does not need to
+ read anything from there.
+ */
+@@ -509,7 +509,7 @@
+ args_usage (NULL);
+ }
+
+- if (cmd->requires_args && optind == argc)
++ if (cmd->requires_args && opt_index == argc)
+ {
+ fprintf (stderr,
+ "%s: the ``%s'' command requires at least one argument\n",
+@@ -517,7 +517,7 @@
+ args_usage (NULL);
+ }
+
+- err = ipkg_cmd_exec (cmd, &ipkg_conf, argc - optind, (const char **) (argv + optind), NULL);
++ err = ipkg_cmd_exec (cmd, &ipkg_conf, argc - opt_index, (const char **) (argv + opt_index), NULL);
+
+ ipkg_conf_deinit (&ipkg_conf);
+
+diff -ruN busybox-1.1.2+ipkg-0.99.162/archival/libipkg/md5.c busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/md5.c
+--- busybox-1.1.2+ipkg-0.99.162/archival/libipkg/md5.c 2006-05-09 02:06:48.000000000 +0200
++++ busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/md5.c 2006-05-09 02:16:48.000000000 +0200
+@@ -25,7 +25,6 @@
+ int md5_stream(FILE *stream, void *resblock)
+ {
+ int fd;
+- int sum;
+
+ if( (fd = fileno(stream)) == -1 ) {
+ bb_error_msg("bad file descriptor");
+diff -ruN busybox-1.1.2+ipkg-0.99.162/archival/libipkg/pkg.c busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/pkg.c
+--- busybox-1.1.2+ipkg-0.99.162/archival/libipkg/pkg.c 2006-05-09 02:12:05.000000000 +0200
++++ busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/pkg.c 2006-05-09 02:16:48.000000000 +0200
+@@ -528,6 +528,7 @@
+ char * pkg_formatted_field(pkg_t *pkg, const char *field )
+ {
+ static size_t LINE_LEN = 128;
++ char line_str[LINE_LEN];
+ char * temp = (char *)malloc(1);
+ int len = 0;
+ int flag_provide_false = 0;
+@@ -567,7 +568,6 @@
+ if (strcasecmp(field, "Conffiles") == 0) {
+ /* Conffiles */
+ conffile_list_elt_t *iter;
+- char confstr[LINE_LEN];
+
+ if (pkg->conffiles.head == NULL) {
+ return temp;
+@@ -588,15 +588,14 @@
+ strncpy(temp, "Conffiles:\n", 12);
+ for (iter = pkg->conffiles.head; iter; iter = iter->next) {
+ if (iter->data->name && iter->data->value) {
+- snprintf(confstr, LINE_LEN, "%s %s\n", iter->data->name, iter->data->value);
+- strncat(temp, confstr, strlen(confstr));
++ snprintf(line_str, LINE_LEN, "%s %s\n", iter->data->name, iter->data->value);
++ strncat(temp, line_str, strlen(line_str));
+ }
+ }
+ } else if (strcasecmp(field, "Conflicts") == 0) {
+ int i;
+
+ if (pkg->conflicts_count) {
+- char conflictstr[LINE_LEN];
+ len = 14 ;
+ for(i = 0; i < pkg->conflicts_count; i++) {
+ len = len + (strlen(pkg->conflicts_str[i])+5);
+@@ -609,8 +608,8 @@
+ temp[0]='\0';
+ strncpy(temp, "Conflicts:", 11);
+ for(i = 0; i < pkg->conflicts_count; i++) {
+- snprintf(conflictstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->conflicts_str[i]);
+- strncat(temp, conflictstr, strlen(conflictstr));
++ snprintf(line_str, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->conflicts_str[i]);
++ strncat(temp, line_str, strlen(line_str));
+ }
+ strncat(temp, "\n", strlen("\n"));
+ }
+@@ -625,7 +624,6 @@
+ int i;
+
+ if (pkg->depends_count) {
+- char depstr[LINE_LEN];
+ len = 14 ;
+ for(i = 0; i < pkg->depends_count; i++) {
+ len = len + (strlen(pkg->depends_str[i])+4);
+@@ -638,8 +636,8 @@
+ temp[0]='\0';
+ strncpy(temp, "Depends:", 10);
+ for(i = 0; i < pkg->depends_count; i++) {
+- snprintf(depstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->depends_str[i]);
+- strncat(temp, depstr, strlen(depstr));
++ snprintf(line_str, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->depends_str[i]);
++ strncat(temp, line_str, strlen(line_str));
+ }
+ strncat(temp, "\n", strlen("\n"));
+ }
+@@ -804,7 +802,6 @@
+ /* Replaces | Recommends*/
+ if (strcasecmp (field, "Replaces") == 0) {
+ if (pkg->replaces_count) {
+- char replstr[LINE_LEN];
+ len = 14;
+ for (i = 0; i < pkg->replaces_count; i++) {
+ len = len + (strlen(pkg->replaces_str[i])+5);
+@@ -817,14 +814,13 @@
+ temp[0]='\0';
+ strncpy(temp, "Replaces:", 12);
+ for (i = 0; i < pkg->replaces_count; i++) {
+- snprintf(replstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->replaces_str[i]);
+- strncat(temp, replstr, strlen(replstr));
++ snprintf(line_str, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->replaces_str[i]);
++ strncat(temp, line_str, strlen(line_str));
+ }
+ strncat(temp, "\n", strlen("\n"));
+ }
+ } else if (strcasecmp (field, "Recommends") == 0) {
+ if (pkg->recommends_count) {
+- char recstr[LINE_LEN];
+ len = 15;
+ for(i = 0; i < pkg->recommends_count; i++) {
+ len = len + (strlen( pkg->recommends_str[i])+5);
+@@ -837,8 +833,8 @@
+ temp[0]='\0';
+ strncpy(temp, "Recommends:", 13);
+ for(i = 0; i < pkg->recommends_count; i++) {
+- snprintf(recstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->recommends_str[i]);
+- strncat(temp, recstr, strlen(recstr));
++ snprintf(line_str, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->recommends_str[i]);
++ strncat(temp, line_str, strlen(line_str));
+ }
+ strncat(temp, "\n", strlen("\n"));
+ }
+@@ -907,7 +903,6 @@
+ } else if (strcasecmp(field, "Suggests") == 0) {
+ if (pkg->suggests_count) {
+ int i;
+- char sugstr[LINE_LEN];
+ len = 13;
+ for(i = 0; i < pkg->suggests_count; i++) {
+ len = len + (strlen(pkg->suggests_str[i])+5);
+@@ -920,8 +915,8 @@
+ temp[0]='\0';
+ strncpy(temp, "Suggests:", 10);
+ for(i = 0; i < pkg->suggests_count; i++) {
+- snprintf(sugstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->suggests_str[i]);
+- strncat(temp, sugstr, strlen(sugstr));
++ snprintf(line_str, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->suggests_str[i]);
++ strncat(temp, line_str, strlen(line_str));
+ }
+ strncat(temp, "\n", strlen("\n"));
+ }
+@@ -1140,10 +1135,8 @@
+ return 0;
+ }
+
+-int pkg_name_version_and_architecture_compare(void *p1, void *p2)
++int pkg_name_version_and_architecture_compare(pkg_t *a, pkg_t *b)
+ {
+- const pkg_t *a = *(const pkg_t **)p1;
+- const pkg_t *b = *(const pkg_t **)p2;
+ int namecmp;
+ int vercmp;
+ if (!a->name || !b->name) {
+@@ -1170,10 +1163,8 @@
+ return 0;
+ }
+
+-int abstract_pkg_name_compare(void *p1, void *p2)
++int abstract_pkg_name_compare(abstract_pkg_t *a, abstract_pkg_t *b)
+ {
+- const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
+- const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
+ if (!a->name || !b->name) {
+ fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
+ a, a->name, b, b->name);
+@@ -1193,7 +1184,7 @@
+ #endif
+
+ if (pkg->epoch) {
+- sprintf_alloc(&epoch_str, "%d:", pkg->epoch);
++ sprintf_alloc(&epoch_str, "%d:", (int)(pkg->epoch));
+ } else {
+ epoch_str = strdup("");
+ }
+diff -ruN busybox-1.1.2+ipkg-0.99.162/archival/libipkg/pkg.h busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/pkg.h
+--- busybox-1.1.2+ipkg-0.99.162/archival/libipkg/pkg.h 2006-05-09 02:12:05.000000000 +0200
++++ busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/pkg.h 2006-05-09 02:16:48.000000000 +0200
+@@ -194,8 +194,8 @@
+ char *pkg_version_str_alloc(pkg_t *pkg);
+
+ int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg);
+-int pkg_name_version_and_architecture_compare(void *a, void *b);
+-int abstract_pkg_name_compare(void *a, void *b);
++int pkg_name_version_and_architecture_compare(pkg_t *a, pkg_t *b);
++int abstract_pkg_name_compare(abstract_pkg_t *a, abstract_pkg_t *b);
+
+ char * pkg_formatted_info(pkg_t *pkg );
+ char * pkg_formatted_field(pkg_t *pkg, const char *field );
+diff -ruN busybox-1.1.2+ipkg-0.99.162/archival/libipkg/pkg_depends.c busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/pkg_depends.c
+--- busybox-1.1.2+ipkg-0.99.162/archival/libipkg/pkg_depends.c 2006-05-09 02:12:05.000000000 +0200
++++ busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/pkg_depends.c 2006-05-09 02:16:48.000000000 +0200
+@@ -68,7 +68,7 @@
+ pkg_vec_t *unsatisfied, char *** unresolved)
+ {
+ pkg_t * satisfier_entry_pkg;
+- register int i, j, k;
++ register int i, j, k, l;
+ int count, found;
+ char ** the_lost;
+ abstract_pkg_t * ab_pkg;
+@@ -113,7 +113,6 @@
+ abstract_pkg_vec_t *ab_provider_vec = abpkg->provided_by;
+ int nposs = ab_provider_vec->len;
+ abstract_pkg_t **ab_providers = ab_provider_vec->pkgs;
+- int l;
+ for (l = 0; l < nposs; l++) {
+ pkg_vec_t *test_vec = ab_providers[l]->pkgs;
+ /* if no depends on this one, try the first package that Provides this one */
+@@ -137,10 +136,9 @@
+ tmp_vec,
+ &newstuff);
+ if (newstuff == NULL) {
+- int i;
+ int ok = 1;
+- for (i = 0; i < rc; i++) {
+- pkg_t *p = tmp_vec->pkgs[i];
++ for (l = 0; l < rc; l++) {
++ pkg_t *p = tmp_vec->pkgs[l];
+ if (p->state_want == SW_INSTALL)
+ continue;
+ ipkg_message(conf, IPKG_DEBUG, "not installing %s due to requirement for %s\n", pkg_scout->name, p->name);
+@@ -814,27 +812,27 @@
+ * [npredepends+nrecommends,npredepends+nrecommends+nsuggests) -> returns recommends_str[index]
+ * [npredepends+nrecommends+nsuggests,npredepends+nrecommends+nsuggests+ndepends) -> returns depends_str[index]
+ */
+-char *pkg_depend_str(pkg_t *pkg, int index)
++char *pkg_depend_str(pkg_t *pkg, int pkg_index)
+ {
+- if (index < pkg->pre_depends_count) {
+- return pkg->pre_depends_str[index];
++ if (pkg_index < pkg->pre_depends_count) {
++ return pkg->pre_depends_str[pkg_index];
+ }
+- index -= pkg->pre_depends_count;
++ pkg_index -= pkg->pre_depends_count;
+
+- if (index < pkg->recommends_count) {
+- return pkg->recommends_str[index];
++ if (pkg_index < pkg->recommends_count) {
++ return pkg->recommends_str[pkg_index];
+ }
+- index -= pkg->recommends_count;
++ pkg_index -= pkg->recommends_count;
+
+- if (index < pkg->suggests_count) {
+- return pkg->suggests_str[index];
++ if (pkg_index < pkg->suggests_count) {
++ return pkg->suggests_str[pkg_index];
+ }
+- index -= pkg->suggests_count;
++ pkg_index -= pkg->suggests_count;
+
+- if (index < pkg->depends_count) {
+- return pkg->depends_str[index];
++ if (pkg_index < pkg->depends_count) {
++ return pkg->depends_str[pkg_index];
+ }
+- fprintf(stderr, "pkg_depend_str: index %d out of range for pkg=%s\n", index, pkg->name);
++ fprintf(stderr, "pkg_depend_str: index %d out of range for pkg=%s\n", pkg_index, pkg->name);
+ return NULL;
+ }
+
+diff -ruN busybox-1.1.2+ipkg-0.99.162/archival/libipkg/pkg_depends.h busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/pkg_depends.h
+--- busybox-1.1.2+ipkg-0.99.162/archival/libipkg/pkg_depends.h 2006-05-09 02:06:48.000000000 +0200
++++ busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/pkg_depends.h 2006-05-09 02:16:48.000000000 +0200
+@@ -92,7 +92,7 @@
+ */
+ int pkg_conflicts(pkg_t *pkg, pkg_t *conflicts);
+
+-char *pkg_depend_str(pkg_t *pkg, int index);
++char *pkg_depend_str(pkg_t *pkg, int pkg_index);
+ void buildDependedUponBy(pkg_t * pkg, abstract_pkg_t * ab_pkg);
+ void freeDepends(pkg_t *pkg);
+ void printDepends(pkg_t * pkg);
+diff -ruN busybox-1.1.2+ipkg-0.99.162/archival/libipkg/pkg_hash.c busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/pkg_hash.c
+--- busybox-1.1.2+ipkg-0.99.162/archival/libipkg/pkg_hash.c 2006-05-09 02:12:05.000000000 +0200
++++ busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/pkg_hash.c 2006-05-09 02:17:35.000000000 +0200
+@@ -143,7 +143,7 @@
+ pkg_t *pkg_hash_fetch_best_installation_candidate(ipkg_conf_t *conf, abstract_pkg_t *apkg,
+ int (*constraint_fcn)(pkg_t *pkg, void *cdata), void *cdata, int quiet)
+ {
+- int i;
++ int i, j;
+ int nprovides = 0;
+ int nmatching = 0;
+ pkg_vec_t *matching_pkgs = pkg_vec_alloc();
+@@ -209,11 +209,10 @@
+ /* now check for supported architecture */
+ {
+ int max_count = 0;
+- int i;
+
+ /* count packages matching max arch priority and keep track of last one */
+- for (i = 0; i < vec->len; i++) {
+- pkg_t *maybe = vec->pkgs[i];
++ for (j = 0; j < vec->len; j++) {
++ pkg_t *maybe = vec->pkgs[j];
+ ipkg_message(conf, IPKG_DEBUG, " %s arch=%s arch_priority=%d version=%s \n",
+ maybe->name, maybe->architecture, maybe->arch_priority, maybe->version);
+ if (maybe->arch_priority > 0) {
+diff -ruN busybox-1.1.2+ipkg-0.99.162/archival/libipkg/pkg_vec.h busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/pkg_vec.h
+--- busybox-1.1.2+ipkg-0.99.162/archival/libipkg/pkg_vec.h 2006-05-09 02:06:48.000000000 +0200
++++ busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/pkg_vec.h 2006-05-09 02:16:48.000000000 +0200
+@@ -35,6 +35,8 @@
+ };
+ typedef struct abstract_pkg_vec abstract_pkg_vec_t;
+
++typedef int (*pkg_compar_t)(pkg_t *, pkg_t *);
++typedef int (*abstract_pkg_compar_t)(abstract_pkg_t *, abstract_pkg_t *);
+
+ pkg_vec_t * pkg_vec_alloc(void);
+ void pkg_vec_free(pkg_vec_t *vec);
diff --git a/package/busybox/patches/913-libbb_hash.patch b/package/busybox/patches/913-libbb_hash.patch
new file mode 100644
index 0000000000..a7c2291caa
--- /dev/null
+++ b/package/busybox/patches/913-libbb_hash.patch
@@ -0,0 +1,228 @@
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# expose (again) an hash_fd function (used in 911-ipkg.patch)
+#
+diff -ruN busybox-1.2.0-orig/coreutils/md5_sha1_sum.c busybox-1.2.0-libbb_hash/coreutils/md5_sha1_sum.c
+--- busybox-1.2.0-orig/coreutils/md5_sha1_sum.c 2006-07-01 00:42:07.000000000 +0200
++++ busybox-1.2.0-libbb_hash/coreutils/md5_sha1_sum.c 2006-07-22 17:08:02.000000000 +0200
+@@ -16,79 +16,10 @@
+
+ #include "busybox.h"
+
+-typedef enum { HASH_SHA1, HASH_MD5 } hash_algo_t;
+-
+ #define FLAG_SILENT 1
+ #define FLAG_CHECK 2
+ #define FLAG_WARN 4
+
+-/* This might be useful elsewhere */
+-static unsigned char *hash_bin_to_hex(unsigned char *hash_value,
+- unsigned char hash_length)
+-{
+- int x, len, max;
+- unsigned char *hex_value;
+-
+- max = (hash_length * 2) + 2;
+- hex_value = xmalloc(max);
+- for (x = len = 0; x < hash_length; x++) {
+- len += snprintf((char*)(hex_value + len), max - len, "%02x", hash_value[x]);
+- }
+- return (hex_value);
+-}
+-
+-static uint8_t *hash_file(const char *filename, hash_algo_t hash_algo)
+-{
+- int src_fd, hash_len, count;
+- union _ctx_ {
+- sha1_ctx_t sha1;
+- md5_ctx_t md5;
+- } context;
+- uint8_t *hash_value = NULL;
+- RESERVE_CONFIG_UBUFFER(in_buf, 4096);
+- void (*update)(const void*, size_t, void*);
+- void (*final)(void*, void*);
+-
+- if (strcmp(filename, "-") == 0) {
+- src_fd = STDIN_FILENO;
+- } else if(0 > (src_fd = open(filename, O_RDONLY))) {
+- bb_perror_msg("%s", filename);
+- return NULL;
+- }
+-
+- /* figure specific hash algorithims */
+- if (ENABLE_MD5SUM && hash_algo==HASH_MD5) {
+- md5_begin(&context.md5);
+- update = (void (*)(const void*, size_t, void*))md5_hash;
+- final = (void (*)(void*, void*))md5_end;
+- hash_len = 16;
+- } else if (ENABLE_SHA1SUM && hash_algo==HASH_SHA1) {
+- sha1_begin(&context.sha1);
+- update = (void (*)(const void*, size_t, void*))sha1_hash;
+- final = (void (*)(void*, void*))sha1_end;
+- hash_len = 20;
+- } else {
+- bb_error_msg_and_die("algorithm not supported");
+- }
+-
+- while (0 < (count = read(src_fd, in_buf, 4096))) {
+- update(in_buf, count, &context);
+- }
+-
+- if (count == 0) {
+- final(in_buf, &context);
+- hash_value = hash_bin_to_hex(in_buf, hash_len);
+- }
+-
+- RELEASE_CONFIG_BUFFER(in_buf);
+-
+- if (src_fd != STDIN_FILENO) {
+- close(src_fd);
+- }
+-
+- return hash_value;
+-}
+-
+ /* This could become a common function for md5 as well, by using md5_stream */
+ static int hash_files(int argc, char **argv, hash_algo_t hash_algo)
+ {
+diff -ruN busybox-1.2.0-orig/include/libbb.h busybox-1.2.0-libbb_hash/include/libbb.h
+--- busybox-1.2.0-orig/include/libbb.h 2006-07-01 00:42:10.000000000 +0200
++++ busybox-1.2.0-libbb_hash/include/libbb.h 2006-07-22 17:01:06.000000000 +0200
+@@ -518,6 +518,8 @@
+ extern int get_terminal_width_height(int fd, int *width, int *height);
+ extern unsigned long get_ug_id(const char *s, long (*__bb_getxxnam)(const char *));
+
++typedef enum { HASH_SHA1, HASH_MD5 } hash_algo_t;
++
+ typedef struct _sha1_ctx_t_ {
+ uint32_t count[2];
+ uint32_t hash[5];
+@@ -542,6 +544,10 @@
+ void md5_hash(const void *data, size_t length, md5_ctx_t *ctx);
+ void *md5_end(void *resbuf, md5_ctx_t *ctx);
+
++unsigned char *hash_bin_to_hex(unsigned char *hash_value, unsigned char hash_length);
++int hash_fd(int fd, hash_algo_t hash_algo, uint8_t *hash_value);
++uint8_t *hash_file(const char *filename, hash_algo_t hash_algo);
++
+ extern uint32_t *bb_crc32_filltable (int endian);
+
+ #ifndef RB_POWER_OFF
+diff -ruN busybox-1.2.0-orig/libbb/hash.c busybox-1.2.0-libbb_hash/libbb/hash.c
+--- busybox-1.2.0-orig/libbb/hash.c 1970-01-01 01:00:00.000000000 +0100
++++ busybox-1.2.0-libbb_hash/libbb/hash.c 2006-07-22 17:07:34.000000000 +0200
+@@ -0,0 +1,100 @@
++/*
++ * Copyright (C) 2003 Glenn L. McGrath
++ * Copyright (C) 2003-2004 Erik Andersen
++ *
++ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
++ */
++
++#include <fcntl.h>
++#include <limits.h>
++#include <stdio.h>
++#include <stdint.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++
++#include "busybox.h"
++
++unsigned char *hash_bin_to_hex(unsigned char *hash_value, unsigned char hash_length)
++{
++ int x, len, max;
++ unsigned char *hex_value;
++
++ max = (hash_length * 2) + 2;
++ hex_value = xmalloc(max);
++ for (x = len = 0; x < hash_length; x++) {
++ len += snprintf((char*)(hex_value + len), max - len, "%02x", hash_value[x]);
++ }
++ return (hex_value);
++}
++
++int hash_fd(int fd, hash_algo_t hash_algo, uint8_t *hash_value)
++{
++ int count, result = 0;
++ union _ctx_ {
++ sha1_ctx_t sha1;
++ md5_ctx_t md5;
++ } context;
++ RESERVE_CONFIG_UBUFFER(in_buf, 4096);
++ void (*update)(const void*, size_t, void*) = NULL;
++ void (*final)(void*, void*) = NULL;
++
++ // figure specific hash algorithims
++ if (hash_algo==HASH_MD5) {
++ md5_begin(&context.md5);
++ update = (void (*)(const void*, size_t, void*))md5_hash;
++ final = (void (*)(void*, void*))md5_end;
++ } else if (hash_algo==HASH_SHA1) {
++ sha1_begin(&context.sha1);
++ update = (void (*)(const void*, size_t, void*))sha1_hash;
++ final = (void (*)(void*, void*))sha1_end;
++ }
++
++
++ while (0 < (count = read(fd, in_buf, sizeof in_buf))) {
++ update(in_buf, count, &context);
++ result += count;
++ }
++
++ if (count == 0) {
++ final(hash_value, &context);
++ }
++
++ RELEASE_CONFIG_BUFFER(in_buf);
++
++ return result;
++}
++
++uint8_t *hash_file(const char *filename, hash_algo_t hash_algo)
++{
++ int src_fd, hash_len;
++ RESERVE_CONFIG_UBUFFER(hash_buf, 20);
++ uint8_t *hash_value = NULL;
++
++ if (ENABLE_MD5SUM && hash_algo==HASH_MD5) {
++ hash_len = 16;
++ } else if (ENABLE_SHA1SUM && hash_algo==HASH_SHA1) {
++ hash_len = 20;
++ } else {
++ bb_error_msg_and_die("algotithm not supported");
++ }
++
++ if (strcmp(filename, "-") == 0) {
++ src_fd = STDIN_FILENO;
++ } else if (0 > (src_fd = open(filename, O_RDONLY))) {
++ bb_perror_msg("%s", filename);
++ return NULL;
++ }
++
++ if (hash_fd(src_fd, hash_algo, hash_buf) > 0) {
++ hash_value = hash_bin_to_hex(hash_buf, hash_len);
++ }
++
++ if (src_fd != STDIN_FILENO) {
++ close(src_fd);
++ }
++
++ RELEASE_CONFIG_BUFFER(hash_buf);
++
++ return hash_value;
++}
+diff -ruN busybox-1.2.0-orig/libbb/Makefile.in busybox-1.2.0-libbb_hash/libbb/Makefile.in
+--- busybox-1.2.0-orig/libbb/Makefile.in 2006-07-01 00:42:08.000000000 +0200
++++ busybox-1.2.0-libbb_hash/libbb/Makefile.in 2006-07-22 16:51:47.000000000 +0200
+@@ -11,6 +11,7 @@
+
+ LIBBB-n:=
+ LIBBB-y:= \
++ hash.c \
+ bb_asprintf.c ask_confirmation.c change_identity.c chomp.c \
+ compare_string_array.c concat_path_file.c copy_file.c copyfd.c \
+ crc32.c create_icmp_socket.c create_icmp6_socket.c \
diff --git a/package/busybox/patches/914-ipkg-fixes.patch b/package/busybox/patches/914-ipkg-fixes.patch
new file mode 100644
index 0000000000..72375bc5b7
--- /dev/null
+++ b/package/busybox/patches/914-ipkg-fixes.patch
@@ -0,0 +1,19 @@
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# fix ipkg bugs
+#
+diff -ruN busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/pkg.c busybox-1.1.2+ipkg-0.99.162-fixes/archival/libipkg/pkg.c
+--- busybox-1.1.2+ipkg-0.99.162-no_warnings/archival/libipkg/pkg.c 2006-05-09 02:16:48.000000000 +0200
++++ busybox-1.1.2+ipkg-0.99.162-fixes/archival/libipkg/pkg.c 2006-05-09 05:15:29.000000000 +0200
+@@ -359,6 +359,8 @@
+ if (!oldpkg->essential)
+ oldpkg->essential = newpkg->essential;
+
++ oldpkg->provided_by_hand |= newpkg->provided_by_hand;
++
+ return 0;
+ }
+
diff --git a/package/diag/Makefile b/package/diag/Makefile
new file mode 100644
index 0000000000..c182321cc1
--- /dev/null
+++ b/package/diag/Makefile
@@ -0,0 +1,48 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=kmod-diag
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/kmod-diag
+ SECTION:=kernel
+ CATEGORY:=Kernel drivers
+ DEFAULT:=y
+ DEPENDS:=@LINUX_2_4_BRCM
+ TITLE:=Driver for router LEDs and Buttons
+ VERSION:=$(LINUX_VERSION)-$(BOARD)-$(PKG_RELEASE)
+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="-DBCMDRIVER -I$(LINUX_DIR)/arch/mips/bcm947xx/include" \
+ modules
+endef
+
+define Package/kmod-diag/install
+ install -d -m0755 $(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) $(PKG_BUILD_DIR)/diag.$(LINUX_KMOD_SUFFIX) \
+ $(1)/lib/modules/$(LINUX_VERSION)/
+endef
+
+$(eval $(call BuildPackage,kmod-diag))
diff --git a/package/diag/src/Makefile b/package/diag/src/Makefile
new file mode 100644
index 0000000000..169f2e9725
--- /dev/null
+++ b/package/diag/src/Makefile
@@ -0,0 +1,19 @@
+# $Id$
+#
+# 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)
+export-objs := diag.o
+
+-include $(TOPDIR)/Rules.make
+endif
diff --git a/package/diag/src/diag.c b/package/diag/src/diag.c
new file mode 100644
index 0000000000..d25f749df5
--- /dev/null
+++ b/package/diag/src/diag.c
@@ -0,0 +1,284 @@
+/*
+ * diag_led.c - replacement diag module
+ *
+ * Copyright (C) 2004 Mike Baker,
+ * Imre Kaloz <kaloz@dune.hu>
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+/*
+ * ChangeLog:
+ * 2004/03/28 initial release
+ * 2004/08/26 asus & buffalo support added
+ * 2005/03/14 asus wl-500g deluxe and buffalo v2 support added
+ * 2005/04/13 added licensing informations
+ * 2005/04/18 base reset polarity off initial readings
+ * 2006/02/07 motorola wa840g/we800g support added
+ * 2006/08/18 asus power led support added
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sysctl.h>
+#include <asm/io.h>
+#include <typedefs.h>
+#include <osl.h>
+#include <bcmdevs.h>
+#include <sbutils.h>
+
+extern char * nvram_get(const char *name);
+static void *sbh;
+
+// v2.x - - - - -
+#define DIAG_GPIO (1<<1)
+#define DMZ_GPIO (1<<7)
+
+static void set_gpio(uint32 mask, uint32 value) {
+ sb_gpiocontrol(sbh,mask, 0, GPIO_DRV_PRIORITY);
+ sb_gpioouten(sbh,mask,mask,GPIO_DRV_PRIORITY);
+ sb_gpioout(sbh,mask,value,GPIO_DRV_PRIORITY);
+}
+
+static void v2_set_diag(u8 state) {
+ set_gpio(DIAG_GPIO,state);
+}
+static void v2_set_dmz(u8 state) {
+ set_gpio(DMZ_GPIO,state);
+}
+
+// asus wl-500g (+deluxe)
+#define ASUS_PWR_GPIO (1<<0)
+
+static void asus_set_pwr(u8 state) {
+ set_gpio(ASUS_PWR_GPIO,state);
+}
+
+// v1.x - - - - -
+#define LED_DIAG 0x13
+#define LED_DMZ 0x12
+
+static void v1_set_diag(u8 state) {
+ if (!state) {
+ *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG)=0xFF;
+ } else {
+ *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG);
+ }
+}
+static void v1_set_dmz(u8 state) {
+ if (!state) {
+ *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ)=0xFF;
+ } else {
+ *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ);
+ }
+}
+
+static void wap1_set_diag(u8 state) {
+ set_gpio(1<<3,state);
+}
+static void wap1_set_dmz(u8 state) {
+ set_gpio(1<<4,state);
+}
+
+// - - - - -
+static void ignore(u8 ignored) {};
+
+// - - - - -
+#define BIT_DMZ 0x01
+#define BIT_PWR 0x02
+#define BIT_DIAG 0x04
+
+void (*set_diag)(u8 state);
+void (*set_dmz)(u8 state);
+void (*set_pwr)(u8 state);
+
+static unsigned int diag = 0x02; // default: diag off, pwr on, dmz off
+
+static void diag_change(void)
+{
+ set_diag(0xFF); // off
+ set_dmz(0xFF); // off
+ set_pwr(0xFF); // off
+
+ if(diag & BIT_DIAG)
+ set_diag(0x00); // on
+ if(diag & BIT_DMZ)
+ set_dmz(0x00); // on
+ if (diag & BIT_PWR)
+ set_pwr(0x00); //on
+}
+
+static int proc_diag(ctl_table *table, int write, struct file *filp,
+ void *buffer, size_t *lenp)
+{
+ int r;
+ r = proc_dointvec(table, write, filp, buffer, lenp);
+ if (write && !r) {
+ diag_change();
+ }
+ return r;
+}
+
+// - - - - -
+static unsigned char reset_gpio = 0;
+static unsigned char reset_polarity = 0;
+static unsigned int reset = 0;
+
+static int proc_reset(ctl_table *table, int write, struct file *filp,
+ void *buffer, size_t *lenp)
+{
+
+ if (reset_gpio) {
+ sb_gpiocontrol(sbh,reset_gpio,reset_gpio,GPIO_DRV_PRIORITY);
+ sb_gpioouten(sbh,reset_gpio,0,GPIO_DRV_PRIORITY);
+ reset=!(sb_gpioin(sbh)&reset_gpio);
+
+ if (reset_polarity) reset=!reset;
+ } else {
+ reset=0;
+ }
+
+ return proc_dointvec(table, write, filp, buffer, lenp);
+}
+
+// - - - - -
+static struct ctl_table_header *diag_sysctl_header;
+
+static ctl_table sys_diag[] = {
+ {
+ ctl_name: 2000,
+ procname: "diag",
+ data: &diag,
+ maxlen: sizeof(diag),
+ mode: 0644,
+ proc_handler: proc_diag
+ },
+ {
+ ctl_name: 2001,
+ procname: "reset",
+ data: &reset,
+ maxlen: sizeof(reset),
+ mode: 0444,
+ proc_handler: proc_reset
+ },
+ { 0 }
+};
+
+static int __init diag_init(void)
+{
+ char *buf;
+ u32 board_type;
+ sbh = (void *)sb_kattach();
+ sb_gpiosetcore(sbh);
+
+ board_type = sb_boardtype(sbh);
+ printk(KERN_INFO "diag boardtype: %08x\n",board_type);
+
+ set_diag=ignore;
+ set_dmz=ignore;
+ set_pwr=ignore;
+
+ buf=nvram_get("pmon_ver") ?: "";
+ if (((board_type & 0xf00) == 0x400) && (strncmp(buf, "CFE", 3) != 0)) {
+ buf=nvram_get("boardtype")?:"";
+ if (!strncmp(buf,"bcm94710dev",11)) {
+ buf=nvram_get("boardnum")?:"";
+ if (!strcmp(buf,"42")) {
+ // wrt54g v1.x
+ set_diag=v1_set_diag;
+ set_dmz=v1_set_dmz;
+ reset_gpio=(1<<6);
+ }
+ if (simple_strtoul(buf, NULL, 0) == 2) {
+ // wap54g v1.0
+ // do not use strcmp as PMON v5.3.22 has some built-in nvram
+ // defaults with trailing \r
+ set_diag=wap1_set_diag;
+ // no dmz led on wap54g, used green led
+ // labeled "WLAN Link" instead
+ set_dmz=wap1_set_dmz;
+ reset_gpio=(1<<0);
+ }
+ if (!strcmp(buf,"asusX")) {
+ //asus wl-500g
+ set_pwr=asus_set_pwr;
+ reset_gpio=(1<<6);
+ }
+ if (!strcmp(buf,"2")) {
+ //wa840g v1 / we800g v1
+ reset_gpio=(1<<0);
+ }
+ }
+ if (!strcmp(buf,"bcm94710ap")) {
+ buf=nvram_get("boardnum")?:"";
+ if (!strcmp(buf,"42")) {
+ // buffalo
+ set_dmz=v2_set_dmz;
+ reset_gpio=(1<<4);
+ }
+ if (!strcmp(buf,"44")) {
+ //dell truemobile
+ set_dmz=v2_set_dmz;
+ reset_gpio=(1<<0);
+ }
+ }
+ } else {
+ buf=nvram_get("boardnum")?:"";
+ if (!strcmp(buf,"42")) {
+ //linksys
+ set_diag=v2_set_diag;
+ set_dmz=v2_set_dmz;
+ reset_gpio=(1<<6);
+ }
+ if (!strcmp(buf,"44")) {
+ //motorola
+ reset_gpio=(1<<5);
+ }
+ if (!strcmp(buf,"00")) {
+ //buffalo
+ reset_gpio=(1<<7);
+ }
+ if (!strcmp(buf,"45")) {
+ //wl-500g deluxe
+ set_pwr=asus_set_pwr;
+ reset_gpio=(1<<6);
+ }
+ }
+
+
+ sb_gpiocontrol(sbh,reset_gpio,reset_gpio,GPIO_DRV_PRIORITY);
+ sb_gpioouten(sbh,reset_gpio,0,GPIO_DRV_PRIORITY);
+ reset_polarity=!(sb_gpioin(sbh)&reset_gpio);
+
+ diag_sysctl_header = register_sysctl_table(sys_diag, 0);
+ diag_change();
+
+ return 0;
+}
+
+static void __exit diag_exit(void)
+{
+ unregister_sysctl_table(diag_sysctl_header);
+}
+
+EXPORT_NO_SYMBOLS;
+MODULE_AUTHOR("openwrt.org");
+MODULE_LICENSE("GPL");
+
+module_init(diag_init);
+module_exit(diag_exit);
diff --git a/package/dnsmasq/Makefile b/package/dnsmasq/Makefile
new file mode 100644
index 0000000000..6283fdc898
--- /dev/null
+++ b/package/dnsmasq/Makefile
@@ -0,0 +1,55 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=dnsmasq
+PKG_VERSION:=2.33
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq
+PKG_MD5SUM:=45696461b6e6bc929273b1191ca50447
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/dnsmasq
+ SECTION:=net
+ CATEGORY:=Base system
+ DEFAULT:=y
+ TITLE:=A lightweight DNS and DHCP server
+ DESCRIPTION:=\
+ It is intended to provide coupled DNS and DHCP service to a LAN.
+ URL:=http://www.thekelleys.org.uk/dnsmasq/
+endef
+
+define Package/dnsmasq/conffiles
+/etc/dnsmasq.conf
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS) -DHAVE_ISC_READER=1" \
+ BINDIR="/usr/sbin" MANDIR="/usr/man" \
+ all
+endef
+
+define Package/dnsmasq/install
+ install -m0755 -d $(1)/usr/sbin
+ install -m0755 $(PKG_BUILD_DIR)/src/dnsmasq $(1)/usr/sbin/
+ install -m0755 -d $(1)/etc
+ install -m0644 ./files/dnsmasq.conf $(1)/etc/dnsmasq.conf
+ install -m0755 -d $(1)/etc/init.d
+ install -m0755 ./files/dnsmasq.init $(1)/etc/init.d/S50dnsmasq
+endef
+
+$(eval $(call BuildPackage,dnsmasq))
diff --git a/package/dnsmasq/files/dnsmasq.conf b/package/dnsmasq/files/dnsmasq.conf
new file mode 100644
index 0000000000..8a51f8445d
--- /dev/null
+++ b/package/dnsmasq/files/dnsmasq.conf
@@ -0,0 +1,28 @@
+# filter what we send upstream
+domain-needed
+bogus-priv
+filterwin2k
+localise-queries
+
+# allow /etc/hosts and dhcp lookups via *.lan
+local=/lan/
+domain=lan
+expand-hosts
+resolv-file=/tmp/resolv.conf
+
+@ifdef dhcp_enable
+dhcp-range=@@start@@,@@end@@,@@netmask@@,@@lease@@
+dhcp-authoritative
+dhcp-leasefile=/tmp/dhcp.leases
+@endif
+@ifdef wan_ifname
+except-interface=@@wan_ifname@@
+@endif
+
+# use /etc/ethers for static hosts; same format as --dhcp-host
+# <hwaddr> <ipaddr>
+read-ethers
+
+# other useful options:
+# default route(s): dhcp-option=3,192.168.1.1,192.168.1.2
+# dns server(s): dhcp-option=6,192.168.1.1,192.168.1.2
diff --git a/package/dnsmasq/files/dnsmasq.init b/package/dnsmasq/files/dnsmasq.init
new file mode 100644
index 0000000000..8ac0ab638d
--- /dev/null
+++ b/package/dnsmasq/files/dnsmasq.init
@@ -0,0 +1,57 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+start() {
+ include /lib/network
+ scan_interfaces
+
+ # The following is to automatically configure the DHCP settings
+ # based on config settings. Feel free to replace all this crap
+ # with a simple "dnsmasq" and manage everything via the
+ # /etc/dnsmasq.conf config file
+
+ [ -f /etc/dnsmasq.conf ] || exit
+
+ args=""
+ iface=lan
+ config_get ifname "$iface" ifname
+ config_get proto "$iface" proto
+
+ [ "$proto" = static ] && dhcp_enable="${dhcp_enable:-1}"
+ dhcp_start="${dhcp_start:-100}"
+ dhcp_num="${dhcp_num:-50}"
+ dhcp_lease="${dhcp_lease:-12h}"
+
+ # if dhcp_enable is unset and there is a dhcp server on the network already, default to dhcp_enable=0
+ [ -z "$dhcp_enable" ] && udhcpc -n -q -R -s /bin/true -i $ifname >&- && dhcp_enable="${dhcp_enable:-0}"
+
+ # dhcp_enable=0 disables the dhcp server
+ (
+ [ -z "$dhcp_enable" -o "$dhcp_enable" -eq 1 ] && {
+ # no existing DHCP server?
+
+ # calculate settings
+ config_get ipaddr "$iface" ipaddr
+ config_get netmask "$iface" netmask
+ eval $(ipcalc $ipaddr $netmask ${dhcp_start:-100} ${dhcp_num:-150})
+
+ # and pass the args via config parser defines
+ echo "${dhcp_enable:+@define dhcp_enable 1}"
+ echo "@define netmask $NETMASK"
+ echo "@define start $START"
+ echo "@define end $END"
+ echo "@define lease ${dhcp_lease:-12h}"
+ }
+
+ # ignore requests from wan interface
+ config_get wan_proto wan proto
+ config_get wan_ifname wan ifname
+ [ -z "$wan_proto" -o "$wan_proto" = "none" ] || echo "@define wan_ifname $wan_ifname"
+
+ cat /etc/dnsmasq.conf
+ ) | awk -f /usr/lib/parse-config.awk | dnsmasq -C /proc/self/fd/0
+}
+
+stop() {
+ killall dnsmasq
+}
diff --git a/package/dnsmasq/patches/101-ipv6.patch b/package/dnsmasq/patches/101-ipv6.patch
new file mode 100644
index 0000000000..5cbf781744
--- /dev/null
+++ b/package/dnsmasq/patches/101-ipv6.patch
@@ -0,0 +1,13 @@
+--- dnsmasq-2.15.orig/src/config.h 2004-09-20 15:47:57.000000000 +0200
++++ dnsmasq-2.15/src/config.h 2004-09-20 23:21:10.000000000 +0200
+@@ -78,8 +78,9 @@
+ /* We assume that systems which don't have IPv6
+ headers don't have ntop and pton either */
+
+-#if defined(INET6_ADDRSTRLEN) && defined(IPV6_V6ONLY) && !defined(NO_IPV6)
++#if defined(INET6_ADDRSTRLEN) && !defined(NO_IPV6)
+ # define HAVE_IPV6
++# define IPV6_V6ONLY 26
+ # define ADDRSTRLEN INET6_ADDRSTRLEN
+ # if defined(SOL_IPV6)
+ # define IPV6_LEVEL SOL_IPV6
diff --git a/package/dropbear/Makefile b/package/dropbear/Makefile
new file mode 100644
index 0000000000..b28b44ef9e
--- /dev/null
+++ b/package/dropbear/Makefile
@@ -0,0 +1,120 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=dropbear
+PKG_VERSION:=0.48.1
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://matt.ucc.asn.au/dropbear/releases/
+PKG_MD5SUM:=ca8e53a766faec831882831364568421
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+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
+ DEFAULT:=y
+ TITLE:=Small SSH2 client/server
+ DESCRIPTION:=\
+ A small SSH2 server/client designed for small memory environments.
+endef
+
+define Package/dropbearconvert
+ $(call Package/dropbear/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Utility for converting SSH keys
+endef
+
+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
+ (cd $(PKG_BUILD_DIR); rm -rf config.cache; \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ ./configure \
+ --target=$(GNU_TARGET_NAME) \
+ --host=$(GNU_TARGET_NAME) \
+ --build=$(GNU_HOST_NAME) \
+ --program-prefix="" \
+ --program-suffix="" \
+ --prefix=/usr \
+ --exec-prefix=/usr \
+ --bindir=/usr/bin \
+ --datadir=/usr/share \
+ --includedir=/usr/include \
+ --infodir=/usr/share/info \
+ --libdir=/usr/lib \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --mandir=/usr/share/man \
+ --sbindir=/usr/sbin \
+ --sysconfdir=/etc \
+ $(DISABLE_LARGEFILE) \
+ $(DISABLE_NLS) \
+ --with-shared \
+ --disable-pam \
+ --enable-openpty \
+ --enable-syslog \
+ --disable-shadow \
+ --disable-lastlog \
+ --disable-utmp \
+ --disable-utmpx \
+ --disable-wtmp \
+ --disable-wtmpx \
+ --disable-loginfunc \
+ --disable-pututline \
+ --disable-pututxline \
+ --disable-zlib \
+ );
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ LD="$(TARGET_CC)" \
+ PROGRAMS="dropbear dbclient dropbearkey scp" \
+ MULTI=1 SCPPROGRESS=1
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ LD="$(TARGET_CC)" \
+ PROGRAMS="dropbearconvert"
+endef
+
+define Package/dropbear/install
+ install -d -m0755 $(1)/usr/sbin
+ install -m0755 $(PKG_BUILD_DIR)/dropbearmulti \
+ $(1)/usr/sbin/dropbear
+ install -d -m0755 $(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 -d -m0755 $(1)/etc/init.d
+ install -m0755 ./files/dropbear.init $(1)/etc/init.d/S50dropbear
+endef
+
+define Package/dropbearconvert/install
+ install -d -m0755 $(1)/usr/bin
+ install -m0755 $(PKG_BUILD_DIR)/dropbearconvert \
+ $(1)/usr/bin/dropbearconvert
+endef
+
+$(eval $(call BuildPackage,dropbear))
+$(eval $(call BuildPackage,dropbearconvert))
diff --git a/package/dropbear/files/dropbear.init b/package/dropbear/files/dropbear.init
new file mode 100755
index 0000000000..a5822e4f2b
--- /dev/null
+++ b/package/dropbear/files/dropbear.init
@@ -0,0 +1,23 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+start() {
+ for type in rsa dss; do {
+ # check for keys
+ key=/etc/dropbear/dropbear_${type}_host_key
+ [ ! -f $key ] && {
+ # generate missing keys
+ mkdir -p /etc/dropbear
+ [ -x /usr/bin/dropbearkey ] && {
+ /usr/bin/dropbearkey -t $type -f $key 2>&- >&- && exec $0 $*
+ } &
+ exit 0
+ }
+ }; done
+
+ /usr/sbin/dropbear
+}
+
+stop() {
+ killall dropbear
+}
diff --git a/package/dropbear/patches/100-pubkey_path.patch b/package/dropbear/patches/100-pubkey_path.patch
new file mode 100644
index 0000000000..cbe525bcc3
--- /dev/null
+++ b/package/dropbear/patches/100-pubkey_path.patch
@@ -0,0 +1,45 @@
+--- dropbear.old/svr-authpubkey.c.orig 2006-06-03 14:54:43.000000000 +0000
++++ dropbear.dev/svr-authpubkey.c 2006-06-03 15:03:19.000000000 +0000
+@@ -176,6 +176,8 @@
+ goto out;
+ }
+
++ if (ses.authstate.pw->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->pw_dir);
+@@ -187,6 +189,9 @@
+
+ /* open the file */
+ authfile = fopen(filename, "r");
++ } else {
++ authfile = fopen("/etc/dropbear/authorized_keys","r");
++ }
+ if (authfile == NULL) {
+ goto out;
+ }
+@@ -274,6 +279,8 @@
+ goto out;
+ }
+
++ if (ses.authstate.pw->pw_uid != 0) {
++
+ /* allocate max required pathname storage,
+ * = path + "/.ssh/authorized_keys" + '\0' = pathlen + 22 */
+ filename = m_malloc(len + 22);
+@@ -295,6 +302,14 @@
+ if (checkfileperm(filename) != DROPBEAR_SUCCESS) {
+ goto out;
+ }
++ } else {
++ if (checkfileperm("/etc/dropbear") != DROPBEAR_SUCCESS) {
++ goto out;
++ }
++ if (checkfileperm("/etc/dropbear/authorized_keys") != DROPBEAR_SUCCESS) {
++ goto out;
++ }
++ }
+
+ /* file looks ok, return success */
+ ret = DROPBEAR_SUCCESS;
diff --git a/package/dropbear/patches/110-change_user.patch b/package/dropbear/patches/110-change_user.patch
new file mode 100644
index 0000000000..ac617e2806
--- /dev/null
+++ b/package/dropbear/patches/110-change_user.patch
@@ -0,0 +1,19 @@
+diff -urN dropbear.old/svr-chansession.c dropbear.dev/svr-chansession.c
+--- dropbear.old/svr-chansession.c 2005-12-09 06:42:33.000000000 +0100
++++ dropbear.dev/svr-chansession.c 2005-12-12 01:42:38.982034750 +0100
+@@ -860,12 +860,12 @@
+ /* We can only change uid/gid as root ... */
+ if (getuid() == 0) {
+
+- if ((setgid(ses.authstate.pw->pw_gid) < 0) ||
++ if ((ses.authstate.pw->pw_gid != 0) && ((setgid(ses.authstate.pw->pw_gid) < 0) ||
+ (initgroups(ses.authstate.pw->pw_name,
+- ses.authstate.pw->pw_gid) < 0)) {
++ ses.authstate.pw->pw_gid) < 0))) {
+ dropbear_exit("error changing user group");
+ }
+- if (setuid(ses.authstate.pw->pw_uid) < 0) {
++ if ((ses.authstate.pw->pw_uid != 0) && (setuid(ses.authstate.pw->pw_uid) < 0)) {
+ dropbear_exit("error changing user");
+ }
+ } else {
diff --git a/package/dropbear/patches/120-hostkey_prompt.patch b/package/dropbear/patches/120-hostkey_prompt.patch
new file mode 100644
index 0000000000..59639e7b97
--- /dev/null
+++ b/package/dropbear/patches/120-hostkey_prompt.patch
@@ -0,0 +1,12 @@
+diff -urN dropbear-0.45.old/cli-kex.c dropbear-0.45/cli-kex.c
+--- dropbear-0.45.old/cli-kex.c 2005-03-07 05:27:01.000000000 +0100
++++ dropbear-0.45/cli-kex.c 2005-03-25 11:13:57.000000000 +0100
+@@ -119,7 +119,7 @@
+ char response = 'z';
+
+ fp = sign_key_fingerprint(keyblob, keybloblen);
+- fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(fingerprint %s)\nDo you want to continue connecting? (y/n)\n",
++ fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(fingerprint %s)\nDo you want to continue connecting? (y/n) ",
+ cli_opts.remotehost,
+ fp);
+
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 0000000000..9b79e4864e
--- /dev/null
+++ b/package/dropbear/patches/130-ssh_ignore_o_and_x_args.patch
@@ -0,0 +1,22 @@
+diff -ruN dropbear-0.48-old/cli-runopts.c dropbear-0.48-new/cli-runopts.c
+--- dropbear-0.48-old/cli-runopts.c 2006-03-09 16:06:03.000000000 +0100
++++ dropbear-0.48-new/cli-runopts.c 2006-03-11 12:28:54.000000000 +0100
+@@ -188,6 +188,10 @@
+ debug_trace = 1;
+ break;
+ #endif
++ case 'o':
++ next = &dummy;
++ case 'x':
++ break;
+ case 'F':
+ case 'e':
+ case 'c':
+@@ -199,7 +203,6 @@
+ #ifndef ENABLE_CLI_LOCALTCPFWD
+ case 'L':
+ #endif
+- case 'o':
+ case 'b':
+ next = &dummy;
+ default:
diff --git a/package/dropbear/patches/140-use_dev_urandom.patch b/package/dropbear/patches/140-use_dev_urandom.patch
new file mode 100644
index 0000000000..e1424f59a3
--- /dev/null
+++ b/package/dropbear/patches/140-use_dev_urandom.patch
@@ -0,0 +1,12 @@
+diff -urN dropbear-0.45.old/options.h dropbear-0.45/options.h
+--- dropbear-0.45.old/options.h 2005-03-14 17:12:22.000000000 +0100
++++ dropbear-0.45/options.h 2005-03-14 17:13:49.000000000 +0100
+@@ -143,7 +143,7 @@
+ * however significantly reduce the security of your ssh connections
+ * if the PRNG state becomes guessable - make sure you know what you are
+ * doing if you change this. */
+-#define DROPBEAR_RANDOM_DEV "/dev/random"
++#define DROPBEAR_RANDOM_DEV "/dev/urandom"
+
+ /* prngd must be manually set up to produce output */
+ /*#define DROPBEAR_PRNGD_SOCKET "/var/run/dropbear-rng"*/
diff --git a/package/dropbear/patches/150-dbconvert_standalone.patch b/package/dropbear/patches/150-dbconvert_standalone.patch
new file mode 100644
index 0000000000..50c035ae8c
--- /dev/null
+++ b/package/dropbear/patches/150-dbconvert_standalone.patch
@@ -0,0 +1,14 @@
+--- dropbear-0.47.old/options.h 2006-01-31 13:36:25.301562500 +0100
++++ dropbear-0.47.dev/options.h 2006-01-31 13:37:41.846346250 +0100
+@@ -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/ebtables/Makefile b/package/ebtables/Makefile
new file mode 100644
index 0000000000..a0e53a48d3
--- /dev/null
+++ b/package/ebtables/Makefile
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ebtables
+PKG_VERSION:=2.0.8-rc2
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-v$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/ebtables
+PKG_MD5SUM:=f07111fcc1966be669278433c35dcc28
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/ebtables-v$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ebtables
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=Ethernet bridge firewall administration utility
+ URL:=http://ebtables.sourceforge.net/
+endef
+
+define Package/ebtables/install
+ install -d -m0755 $(1)/etc
+ install -m0644 $(PKG_BUILD_DIR)/ethertypes $(1)/etc/
+ install -d -m0755 $(1)/usr/lib/ebtables
+ install -m0755 $(PKG_BUILD_DIR)/lib*.so $(1)/usr/lib/
+ install -m0755 $(PKG_BUILD_DIR)/extensions/*.so $(1)/usr/lib/ebtables/
+ install -d -m0755 $(1)/usr/sbin
+ install -m0755 $(PKG_BUILD_DIR)/ebtables $(1)/usr/sbin/
+ install -m0755 $(PKG_BUILD_DIR)/ebtables-save $(1)/usr/sbin/
+ install -m0755 $(PKG_BUILD_DIR)/ebtables-restore $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,ebtables))
diff --git a/package/fuse/Makefile b/package/fuse/Makefile
new file mode 100644
index 0000000000..8c6b2ce564
--- /dev/null
+++ b/package/fuse/Makefile
@@ -0,0 +1,153 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=fuse
+PKG_VERSION:=2.5.3
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/$(PKG_NAME)
+PKG_MD5SUM:=9c7e8b6606b9f158ae20b8521ba2867c
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/fuse/Default
+ TITLE:=FUSE
+ DESCRIPTION:=\
+ FUSE (Filesystem in UserSpacE)
+ URL:=http://fuse.sourceforge.net/
+endef
+
+define Package/fuse-utils
+ $(call Package/fuse/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE+= (utilities)
+ DESCRIPTION+=\\\
+ \\\
+ This package contains the FUSE utilities.
+endef
+
+define Package/kmod-fuse
+ $(call Package/fuse/Default)
+ SECTION:=kernel
+ CATEGORY:=Kernel drivers
+ TITLE+= (kernel module)
+ DESCRIPTION+=\\\
+ \\\
+ This package contains the FUSE kernel module.
+ VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE)
+endef
+
+define Package/libfuse
+ $(call Package/fuse/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE+= (library)
+ DESCRIPTION+=\\\
+ \\\
+ This package contains the FUSE shared library, needed by other programs.
+endef
+
+define Build/Configure
+ (cd $(PKG_BUILD_DIR); rm -f config.cache; \
+ touch configure.in ; \
+ touch aclocal.m4 ; \
+ touch Makefile.in ; \
+ touch include/config.h.in ; \
+ touch configure ; \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ ./configure \
+ --target=$(GNU_TARGET_NAME) \
+ --host=$(GNU_TARGET_NAME) \
+ --build=$(GNU_HOST_NAME) \
+ --program-prefix="" \
+ --program-suffix="" \
+ --prefix=/usr \
+ --exec-prefix=/usr \
+ --bindir=/usr/bin \
+ --datadir=/usr/share \
+ --includedir=/usr/include \
+ --infodir=/usr/share/info \
+ --libdir=/usr/lib \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --mandir=/usr/share/man \
+ --sbindir=/usr/sbin \
+ --sysconfdir=/etc \
+ $(DISABLE_LARGEFILE) \
+ $(DISABLE_NLS) \
+ --enable-shared \
+ --enable-static \
+ --disable-rpath \
+ --enable-kernel-module \
+ --enable-lib \
+ --enable-util \
+ --disable-example \
+ --disable-auto-modprobe \
+ --with-kernel="$(LINUX_DIR)" \
+ --disable-mtab \
+ );
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ all install
+endef
+
+define Build/InstallDev
+ mkdir -p $(STAGING_DIR)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/fuse{,.h} $(STAGING_DIR)/usr/include/
+ mkdir -p $(STAGING_DIR)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libfuse.{a,so*} $(STAGING_DIR)/usr/lib/
+ mkdir -p $(STAGING_DIR)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/fuse.pc $(STAGING_DIR)/usr/lib/pkgconfig/
+ $(SED) 's,-I$$$${includedir}/fuse,,g' $(STAGING_DIR)/usr/lib/pkgconfig/fuse.pc
+ $(SED) 's,-L$$$${libdir},,g' $(STAGING_DIR)/usr/lib/pkgconfig/fuse.pc
+endef
+
+define Build/UninstallDev
+ rm -rf $(STAGING_DIR)/usr/include/fuse{,.h} \
+ $(STAGING_DIR)/usr/lib/libfuse.{a,so*} \
+ $(STAGING_DIR)/usr/lib/pkgconfig/fuse.pc
+endef
+
+define Package/fuse-utils/install
+ install -d -m0755 $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/fusermount $(1)/usr/bin/
+endef
+
+define Package/kmod-fuse/install
+ install -d -m0755 $(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) $(PKG_INSTALL_DIR)/lib/modules/$(LINUX_VERSION)/kernel/fs/fuse/fuse.$(LINUX_KMOD_SUFFIX) \
+ $(1)/lib/modules/$(LINUX_VERSION)/
+ install -d -m0755 $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libfuse.so.* $(1)/usr/lib/
+ install -d -m0755 $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/fusermount $(1)/usr/bin/
+endef
+
+define Package/libfuse/install
+ install -d -m0755 $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libfuse.so.* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,fuse-utils))
+$(eval $(call BuildPackage,kmod-fuse))
+$(eval $(call BuildPackage,libfuse))
diff --git a/package/fuse/patches/101-kmod_build.patch b/package/fuse/patches/101-kmod_build.patch
new file mode 100644
index 0000000000..e541d47142
--- /dev/null
+++ b/package/fuse/patches/101-kmod_build.patch
@@ -0,0 +1,46 @@
+diff -Nur fuse-2.5.2/kernel/Makefile.in fuse-2.5.2.patched/kernel/Makefile.in
+--- fuse-2.5.2/kernel/Makefile.in 2006-02-02 18:04:52.000000000 +0100
++++ fuse-2.5.2.patched/kernel/Makefile.in 2006-03-28 20:17:13.000000000 +0200
+@@ -54,23 +54,8 @@
+
+ ifeq ($(majver), 2.4)
+
+-CC = gcc
+-LD = ld
+-CFLAGS = -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -pipe @KERNELCFLAGS@
+-CPPFLAGS = -I@kernelsrc@/include -I. -D__KERNEL__ -DMODULE -D_LOOSE_KERNEL_NAMES -DFUSE_VERSION=\"$(VERSION)\" @KERNELCPPFLAGS@
+-
+ fuse_objs = dev.o dir.o file.o inode.o compat/parser.o
+
+-SUFFIXES = .c .o .s
+-
+-all-spec: fuse.o
+-
+-.c.o:
+- $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
+-
+-fuse.o: $(fuse_objs)
+- $(LD) -r -o fuse.o $(fuse_objs)
+-
+ fuse_headers = fuse_i.h fuse_kernel.h
+
+ dev.o: $(fuse_headers)
+@@ -78,6 +63,18 @@
+ file.o: $(fuse_headers)
+ inode.o: $(fuse_headers)
+
++EXTRA_CFLAGS += -DFUSE_VERSION=\"$(VERSION)\"
++
++O_TARGET := fuse.o
++
++obj-y := $(fuse_objs)
++obj-m := $(O_TARGET)
++
++-include $(TOPDIR)/Rules.make
++
++all-spec:
++ $(MAKE) -C @kernelsrc@ TOPDIR=@kernelsrc@ SUBDIRS=$(PWD) modules
++
+ else
+
+ EXTRA_CFLAGS += -DFUSE_VERSION=\"$(VERSION)\"
diff --git a/package/fuse/patches/102-no_depmod.patch b/package/fuse/patches/102-no_depmod.patch
new file mode 100644
index 0000000000..ea9539a200
--- /dev/null
+++ b/package/fuse/patches/102-no_depmod.patch
@@ -0,0 +1,15 @@
+diff -ruN fuse-2.5.3-old/kernel/Makefile.in fuse-2.5.3-new/kernel/Makefile.in
+--- fuse-2.5.3-old/kernel/Makefile.in 2006-06-17 00:04:06.000000000 +0200
++++ fuse-2.5.3-new/kernel/Makefile.in 2006-06-17 00:08:44.000000000 +0200
+@@ -31,11 +31,9 @@
+ install-y: all
+ $(mkdir_p) $(DESTDIR)$(fusemoduledir)
+ $(INSTALL) -m 644 $(fusemodule) $(DESTDIR)$(fusemoduledir)/$(fusemodule)
+- -/sbin/depmod -a
+
+ uninstall-y:
+ rm -f $(DESTDIR)$(fusemoduledir)/$(fusemodule)
+- -/sbin/depmod -a
+
+ clean:
+ -rm -f $(fusemodule) *.o .*.cmd *.mod.c *.ko *.s */*.o
diff --git a/package/fuse/patches/111-uclibc_changes.patch b/package/fuse/patches/111-uclibc_changes.patch
new file mode 100644
index 0000000000..69730758e6
--- /dev/null
+++ b/package/fuse/patches/111-uclibc_changes.patch
@@ -0,0 +1,16 @@
+diff -ruw fuse-2.4.0/util/fusermount.c.org fuse-2.4.0/util/fusermount.c
+--- fuse-2.4.0/util/fusermount.c.org 2005-10-14 11:34:06.000000000 +0200
++++ fuse-2.4.0/util/fusermount.c 2005-10-14 11:56:26.000000000 +0200
+@@ -42,7 +42,12 @@
+ #define FUSE_COMMFD_ENV "_FUSE_COMMFD"
+
+ #define FUSE_DEV_OLD "/proc/fs/fuse/dev"
++#ifdef __UCLIBC__
++/* /dev is mounted as devfs in OpenWRT, and device is created here */
++#define FUSE_DEV_NEW "/dev/misc/fuse"
++#else
+ #define FUSE_DEV_NEW "/dev/fuse"
++#endif
+ #define FUSE_VERSION_FILE_OLD "/proc/fs/fuse/version"
+ #define FUSE_CONF "/etc/fuse.conf"
+
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 0000000000..96ed70f291
--- /dev/null
+++ b/package/fuse/patches/112-no_break_on_mknod.patch
@@ -0,0 +1,12 @@
+diff -ruN fuse-2.4.1-old/util/Makefile.in fuse-2.4.1-new/util/Makefile.in
+--- fuse-2.4.1-old/util/Makefile.in 2005-10-17 12:29:20.000000000 +0200
++++ fuse-2.4.1-new/util/Makefile.in 2005-10-19 17:11:13.000000000 +0200
+@@ -445,7 +445,7 @@
+ install-exec-hook:
+ -chown root $(DESTDIR)$(bindir)/fusermount
+ -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"; \
+ mknod $(DESTDIR)/dev/fuse -m 0666 c 10 229; \
diff --git a/package/gdbserver/Makefile b/package/gdbserver/Makefile
new file mode 100644
index 0000000000..c07eaf9927
--- /dev/null
+++ b/package/gdbserver/Makefile
@@ -0,0 +1,69 @@
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gdbserver
+PKG_VERSION:=6.3
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+GDB_DIR:=$(TOOLCHAIN_BUILD_DIR)/gdb-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/gdbserver
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=@GDB@
+ TITLE:=Remote Server for the GNU Debugger
+ 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
+
+define Build/Configure
+ (cd $(PKG_BUILD_DIR); rm -rf config.{cache,status}; \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ $(GDB_DIR)/gdb/gdbserver/configure \
+ --target=$(GNU_TARGET_NAME) \
+ --host=$(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 \
+ --datadir=/usr/share \
+ --localstatedir=/var \
+ --mandir=/usr/man \
+ --infodir=/usr/info \
+ $(DISABLE_NLS) \
+ $(DISABLE_LARGEFILE) \
+ );
+endef
+
+define Build/Compile
+ rm -rf $(PKG_INSTALL_DIR)
+ mkdir -p $(PKG_INSTALL_DIR)
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ install
+endef
+
+define Package/gdbserver/install
+ install -m0755 -d $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/gdbserver $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,gdbserver))
+
diff --git a/package/gmp/Makefile b/package/gmp/Makefile
new file mode 100644
index 0000000000..1470ead89a
--- /dev/null
+++ b/package/gmp/Makefile
@@ -0,0 +1,65 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gmp
+PKG_VERSION:=4.1.4
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=@GNU/gmp
+PKG_MD5SUM:=0aa7d3b3f5b5ec5951e7dddd6f65e891
+PKG_CAT:=bzcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libgmp
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=GNU multiprecision arithmetic library
+ URL:=http://www.swox.com/gmp/
+endef
+
+define Build/Configure
+ $(call Build/Configure/Default, \
+ --enable-shared \
+ --enable-static, \
+ CC="$(TARGET_CROSS)gcc" \
+ )
+endef
+
+define Build/Compile
+ $(call Build/Compile/Default, \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ CC="$(TARGET_CC)" \
+ all install \
+ )
+endef
+
+define Build/InstallDev
+ mkdir -p $(STAGING_DIR)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/gmp* $(STAGING_DIR)/usr/include/
+ mkdir -p $(STAGING_DIR)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libgmp.{a,so*} $(STAGING_DIR)/usr/lib/
+endef
+
+define Build/UninstallDev
+ rm -rf $(STAGING_DIR)/usr/include/gmp* \
+ $(STAGING_DIR)/usr/lib/libgmp.{a,so*}
+endef
+
+define Package/libgmp/install
+ install -m0755 -d $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libgmp.so.* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,libgmp))
diff --git a/package/haserl/Makefile b/package/haserl/Makefile
new file mode 100644
index 0000000000..83a7d848f8
--- /dev/null
+++ b/package/haserl/Makefile
@@ -0,0 +1,36 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=haserl
+PKG_VERSION:=0.8.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/haserl
+PKG_MD5SUM:=bd9195d086566f56634c0bcbbbcbebea
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/haserl
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=A CGI wrapper to embed shell scripts in HTML documents
+ URL:=http://haserl.sourceforge.net/
+endef
+
+define Package/haserl/install
+ install -m0755 -d $(1)/usr/bin
+ install -m0755 $(PKG_BUILD_DIR)/src/haserl $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,haserl))
diff --git a/package/hostap-utils/Makefile b/package/hostap-utils/Makefile
new file mode 100644
index 0000000000..ad142f33d2
--- /dev/null
+++ b/package/hostap-utils/Makefile
@@ -0,0 +1,48 @@
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+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
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/hostap-utils
+ SECTION:=utils
+ CATEGORY:=Kernel drivers
+ 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) -I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/include -Wall" \
+ all
+endef
+
+define Package/hostap-utils/install
+ install -m0755 -d $(1)/usr/sbin
+ install -m0755 $(PKG_BUILD_DIR)/hostap_crypt_conf $(1)/usr/sbin/
+ install -m0755 $(PKG_BUILD_DIR)/hostap_diag $(1)/usr/sbin/
+ install -m0755 $(PKG_BUILD_DIR)/hostap_io_debug $(1)/usr/sbin/
+ install -m0755 $(PKG_BUILD_DIR)/hostap_rid $(1)/usr/sbin/
+ install -m0755 $(PKG_BUILD_DIR)/prism2_srec $(1)/usr/sbin/
+ install -m0755 $(PKG_BUILD_DIR)/split_combined_hex $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,hostap-utils))
diff --git a/package/hostap/Makefile b/package/hostap/Makefile
new file mode 100644
index 0000000000..82e7475a0e
--- /dev/null
+++ b/package/hostap/Makefile
@@ -0,0 +1,139 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=hostap-driver
+PKG_VERSION:=0.4.9
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://hostap.epitest.fi/releases/
+PKG_MD5SUM:=c7534dc040ab90218257a78488ecd378
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/kmod-hostap/Default
+ SECTION:=kernel
+ CATEGORY:=Kernel drivers
+ 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.
+ URL:=http://hostap.epitest.fi/
+ ifeq ($(KERNEL),2.6)
+ VERSION:=$(LINUX_VERSION)-$(BOARD)-$(PKG_RELEASE)
+ else
+ VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE)
+ endif
+endef
+
+define Package/kmod-hostap
+ $(call Package/kmod-hostap/Default)
+ DEPENDS:=@PCI_SUPPORT||PCMCIA_SUPPORT
+ TITLE:=Host AP support for Prism2/2.5/3
+ 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 Package/kmod-hostap-pci
+ $(call Package/kmod-hostap/Default)
+ DEPENDS:=kmod-hostap
+ TITLE:=Host AP driver for PCI adaptors
+ DESCRIPTION+=\\\
+ \\\
+ This package contains the Host AP driver for Prism2.5 PCI adaptors.
+endef
+
+define Package/kmod-hostap-plx
+ $(call Package/kmod-hostap/Default)
+ DEPENDS:=kmod-hostap
+ TITLE:=Host AP driver for PLX9052 based PCI adaptors
+ DESCRIPTION+=\\\
+ \\\
+ This package contains the Host AP driver for Prism2/2.5/3 in PLX9052 \\\
+ based PCI adaptors.
+endef
+
+ifeq ($(KERNEL),2.4)
+ define Build/Compile
+ $(MAKE) -C $(LINUX_DIR)/ \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ SUBDIRS="$(PKG_BUILD_DIR)/driver/modules" \
+ modules
+ endef
+
+ define Package/kmod-hostap/install
+ install -m0755 -d $(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) \
+ $(PKG_BUILD_DIR)/driver/modules/hostap.$(LINUX_KMOD_SUFFIX) \
+ $(PKG_BUILD_DIR)/driver/modules/hostap_crypt_ccmp.$(LINUX_KMOD_SUFFIX) \
+ $(PKG_BUILD_DIR)/driver/modules/hostap_crypt_tkip.$(LINUX_KMOD_SUFFIX) \
+ $(PKG_BUILD_DIR)/driver/modules/hostap_crypt_wep.$(LINUX_KMOD_SUFFIX) \
+ $(1)/lib/modules/$(LINUX_VERSION)/
+ endef
+
+ define Package/kmod-hostap-pci/install
+ install -m0755 -d $(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) \
+ $(PKG_BUILD_DIR)/driver/modules/hostap_pci.$(LINUX_KMOD_SUFFIX) \
+ $(1)/lib/modules/$(LINUX_VERSION)/
+ endef
+
+ define Package/kmod-hostap-plx/install
+ install -m0755 -d $(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) \
+ $(PKG_BUILD_DIR)/driver/modules/hostap_plx.$(LINUX_KMOD_SUFFIX) \
+ $(1)/lib/modules/$(LINUX_VERSION)/
+ endef
+endif
+
+ifeq ($(KERNEL),2.6)
+ define Build/Compile
+ endef
+
+ifeq ($(CONFIG_HOSTAP),m)
+ define Package/kmod-hostap/install
+ install -m0755 -d $(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) \
+ $(MODULES_DIR)/kernel/drivers/net/wireless/hostap/hostap.$(LINUX_KMOD_SUFFIX) \
+ $(1)/lib/modules/$(LINUX_VERSION)/
+ endef
+endif
+
+ifeq ($(CONFIG_HOSTAP_PCI),m)
+ define Package/kmod-hostap-pci/install
+ install -m0755 -d $(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) \
+ $(MODULES_DIR)/kernel/drivers/net/wireless/hostap/hostap_pci.$(LINUX_KMOD_SUFFIX) \
+ $(1)/lib/modules/$(LINUX_VERSION)/
+ endef
+endif
+
+ifeq ($(CONFIG_HOSTAP_PLX),m)
+ define Package/kmod-hostap-plx/install
+ install -m0755 -d $(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) \
+ $(MODULES_DIR)/kernel/drivers/net/wireless/hostap/hostap_plx.$(LINUX_KMOD_SUFFIX) \
+ $(1)/lib/modules/$(LINUX_VERSION)/
+ endef
+endif
+endif
+
+$(eval $(call BuildPackage,kmod-hostap))
+$(eval $(call BuildPackage,kmod-hostap-pci))
+$(eval $(call BuildPackage,kmod-hostap-plx))
diff --git a/package/hostapd/Makefile b/package/hostapd/Makefile
new file mode 100644
index 0000000000..ba16193daf
--- /dev/null
+++ b/package/hostapd/Makefile
@@ -0,0 +1,132 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=hostapd
+PKG_VERSION:=0.5.3
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://hostap.epitest.fi/releases/
+PKG_MD5SUM:=4e3134e8b0d86e831230f8c620fd81bb
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+PKG_BUILDDEP:=madwifi
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/hostapd/Default
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=IEEE 802.1x Authenticator
+ URL:=http://hostap.epitest.fi/
+endef
+
+define Package/hostapd
+ $(call Package/hostapd/Default)
+ DEPENDS:=+libopenssl
+ TITLE+= (full)
+ DESCRIPTION:=\
+ This package contains a full featured IEEE 802.1x/WPA/EAP/RADIUS \\\
+ Authenticator.
+endef
+
+define Package/hostapd/conffiles
+/etc/hostapd.conf
+endef
+
+define Package/hostapd-mini
+ $(call Package/hostapd/Default)
+ TITLE+= (WPA-PSK only)
+ DESCRIPTION:=\
+ This package contains a minimal IEEE 802.1x/WPA/EAP/RADIUS Authenticator \\\
+ (WPA-PSK only).
+endef
+
+define Package/hostapd-mini/conffiles
+/etc/hostapd.conf
+endef
+
+define Package/hostapd-utils
+ $(call Package/hostapd/Default)
+ DEPENDS:=@PACKAGE_hostapd||PACKAGE_hostapd-mini
+ TITLE+= (utils)
+ DESCRIPTION:=\
+ This package contains a command line utility to control the \\\
+ IEEE 802.1x/WPA/EAP/RADIUS Authenticator.
+endef
+
+define Build/ConfigureTarget
+ $(CP) $(PKG_BUILD_DIR) $(PKG_BUILD_DIR)_$(1)
+ $(CP) ./files/$(1).config $(PKG_BUILD_DIR)_$(1)/.config
+endef
+
+define Build/CompileTarget
+ $(MAKE) -C $(PKG_BUILD_DIR)_$(1) \
+ $(TARGET_CONFIGURE_OPTS) \
+ OPTFLAGS="$(TARGET_CFLAGS)" \
+ CPPFLAGS="-I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/include -I$(STAGING_DIR)/usr/include/madwifi" \
+ LDFLAGS="-L$(STAGING_DIR)/usr/lib -L$(STAGING_DIR)/lib" \
+ hostapd hostapd_cli
+ $(CP) $(PKG_BUILD_DIR)_$(1)/hostapd_cli $(PKG_BUILD_DIR)/
+endef
+
+define Package/InstallTemplate
+ if [ \! -f "$(PKG_BUILD_DIR)_$(2)/hostapd" ]; then \
+ rm -f $(PKG_BUILD_DIR)/.built; \
+ $(MAKE) $(PKG_BUILD_DIR)/.built; \
+ fi
+ install -m0755 -d $$(1)/etc
+ install -m0600 $(PKG_BUILD_DIR)_$(2)/madwifi.conf $$(1)/etc/hostapd.conf
+ install -m0755 -d $$(1)/usr/sbin
+ install -m0755 $(PKG_BUILD_DIR)_$(2)/hostapd $$(1)/usr/sbin/
+endef
+
+define Package/Template
+ ifneq ($(CONFIG_PACKAGE_$(1)),)
+ define Build/Configure/$(2)
+ $(call Build/ConfigureTarget,$(2))
+ endef
+ define Build/Compile/$(2)
+ $(call Build/CompileTarget,$(2))
+ endef
+ define Package/$(1)/install
+ $(call Package/InstallTemplate,$(1),$(2))
+ endef
+ endif
+endef
+
+define Build/Configure
+ $(call Build/Configure/default)
+ $(call Build/Configure/mini)
+endef
+
+define Build/Compile
+ $(call Build/Compile/default)
+ $(call Build/Compile/mini)
+endef
+
+define Build/Clean
+ rm -rf $(PKG_BUILD_DIR)_default
+ rm -rf $(PKG_BUILD_DIR)_mini
+endef
+
+define Package/hostapd-utils/install
+ install -m0755 -d $(1)/usr/sbin
+ install -m0755 $(PKG_BUILD_DIR)/hostapd_cli $(1)/usr/sbin/
+endef
+
+$(eval $(call Package/Template,hostapd,default))
+$(eval $(call Package/Template,hostapd-mini,mini))
+
+$(eval $(call BuildPackage,hostapd))
+$(eval $(call BuildPackage,hostapd-mini))
+$(eval $(call BuildPackage,hostapd-utils))
diff --git a/package/hostapd/files/default.config b/package/hostapd/files/default.config
new file mode 100644
index 0000000000..e2237d6d8d
--- /dev/null
+++ b/package/hostapd/files/default.config
@@ -0,0 +1,69 @@
+# 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../head # change to reflect local setup; directory for madwifi src
+
+# Driver interface for Prism54 driver
+#CONFIG_DRIVER_PRISM54=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
+
+# IEEE 802.11F/IAPP
+CONFIG_IAPP=y
+
+# WPA2/IEEE 802.11i RSN pre-authentication
+CONFIG_RSN_PREAUTH=y
+
+# Integrated EAP authenticator
+CONFIG_EAP=y
+
+# EAP-MD5 for the integrated EAP authenticator
+CONFIG_EAP_MD5=y
+
+# EAP-TLS for the integrated EAP authenticator
+CONFIG_EAP_TLS=y
+
+# EAP-MSCHAPv2 for the integrated EAP authenticator
+CONFIG_EAP_MSCHAPV2=y
+
+# EAP-PEAP for the integrated EAP authenticator
+CONFIG_EAP_PEAP=y
+
+# EAP-PSK for the integrated EAP authenticator
+CONFIG_EAP_PSK=y
+
+# EAP-GTC for the integrated EAP authenticator
+CONFIG_EAP_GTC=y
+
+# EAP-TTLS for the integrated EAP authenticator
+CONFIG_EAP_TTLS=y
+
+# EAP-SIM for the integrated EAP authenticator
+#CONFIG_EAP_SIM=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
+# authenticator from external hosts using RADIUS.
+#CONFIG_RADIUS_SERVER=y
diff --git a/package/hostapd/files/mini.config b/package/hostapd/files/mini.config
new file mode 100644
index 0000000000..912bee8d7f
--- /dev/null
+++ b/package/hostapd/files/mini.config
@@ -0,0 +1,69 @@
+# 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../head # change to reflect local setup; directory for madwifi src
+
+# Driver interface for Prism54 driver
+#CONFIG_DRIVER_PRISM54=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
+
+# IEEE 802.11F/IAPP
+CONFIG_IAPP=y
+
+# WPA2/IEEE 802.11i RSN pre-authentication
+CONFIG_RSN_PREAUTH=y
+
+# Integrated EAP authenticator
+CONFIG_EAP=y
+
+# EAP-MD5 for the integrated EAP authenticator
+#CONFIG_EAP_MD5=y
+
+# EAP-TLS for the integrated EAP authenticator
+#CONFIG_EAP_TLS=y
+
+# EAP-MSCHAPv2 for the integrated EAP authenticator
+#CONFIG_EAP_MSCHAPV2=y
+
+# EAP-PEAP for the integrated EAP authenticator
+#CONFIG_EAP_PEAP=y
+
+# EAP-PSK for the integrated EAP authenticator
+CONFIG_EAP_PSK=y
+
+# EAP-GTC for the integrated EAP authenticator
+#CONFIG_EAP_GTC=y
+
+# EAP-TTLS for the integrated EAP authenticator
+#CONFIG_EAP_TTLS=y
+
+# EAP-SIM for the integrated EAP authenticator
+#CONFIG_EAP_SIM=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
+# authenticator from external hosts using RADIUS.
+#CONFIG_RADIUS_SERVER=y
diff --git a/package/hostapd/patches/001-cross_compile_fix.patch b/package/hostapd/patches/001-cross_compile_fix.patch
new file mode 100644
index 0000000000..8b5ca681d2
--- /dev/null
+++ b/package/hostapd/patches/001-cross_compile_fix.patch
@@ -0,0 +1,35 @@
+Common subdirectories: hostapd-0.5.2/logwatch and hostapd-0.5.2.new/logwatch
+diff -u hostapd-0.5.2/Makefile hostapd-0.5.2.new/Makefile
+--- hostapd-0.5.2/Makefile 2006-03-20 03:20:09.000000000 +0000
++++ hostapd-0.5.2.new/Makefile 2006-03-21 22:25:23.803473592 +0000
+@@ -3,7 +3,7 @@
+ DIR_HOSTAP=.
+
+ ifndef CFLAGS
+-CFLAGS = -MMD -O2 -Wall -g
++CFLAGS = -MMD $(OPTFLAGS) $(CPPFLAGS)
+ endif
+
+ # define HOSTAPD_DUMP_STATE to include SIGUSR1 handler for dumping state to
+@@ -266,7 +266,7 @@
+ for i in $(ALL); do cp $$i /usr/local/bin/$$i; done
+
+ hostapd: $(OBJS)
+- $(CC) -o hostapd $(OBJS) $(LIBS)
++ $(CC) -o hostapd $(OBJS) $(LDFLAGS) $(LIBS)
+
+ driver_conf.c: Makefile .config
+ rm -f driver_conf.c
+@@ -330,10 +330,10 @@
+ endif
+
+ nt_password_hash: $(NOBJS)
+- $(CC) -o nt_password_hash $(NOBJS) $(LIBS_n)
++ $(CC) -o nt_password_hash $(NOBJS) $(LDFLAGS) $(LIBS_n)
+
+ hlr_auc_gw: $(HOBJS)
+- $(CC) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
++ $(CC) -o hlr_auc_gw $(HOBJS) $(LDFLAGS) $(LIBS_h)
+
+ clean:
+ rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw
diff --git a/package/hostapd/patches/100-madwifi_fixes.patch b/package/hostapd/patches/100-madwifi_fixes.patch
new file mode 100644
index 0000000000..eb7299b41a
--- /dev/null
+++ b/package/hostapd/patches/100-madwifi_fixes.patch
@@ -0,0 +1,52 @@
+diff -ur hostapd.old/driver_madwifi.c hostapd.dev/driver_madwifi.c
+--- hostapd.old/driver_madwifi.c 2006-03-25 20:55:18.000000000 +0100
++++ hostapd.dev/driver_madwifi.c 2006-06-12 21:54:22.000000000 +0200
+@@ -20,11 +20,6 @@
+
+ #include <include/compat.h>
+ #include <net80211/ieee80211.h>
+-#ifdef WME_NUM_AC
+-/* Assume this is built against BSD branch of madwifi driver. */
+-#define MADWIFI_BSD
+-#include <net80211/_ieee80211.h>
+-#endif /* WME_NUM_AC */
+ #include <net80211/ieee80211_crypto.h>
+ #include <net80211/ieee80211_ioctl.h>
+
+@@ -168,7 +164,10 @@
+ }
+ return 0;
+ }
+-
++static int madwifi_get_inact_sec(void *priv, const u8 *addr)
++{
++return 0;
++}
+ static int
+ set80211param(struct madwifi_driver_data *drv, int op, int arg)
+ {
+@@ -1204,8 +1203,6 @@
+ goto bad;
+ }
+
+- madwifi_set_iface_flags(drv, 0); /* mark down during setup */
+-
+ hapd->driver = &drv->ops;
+ return 0;
+ bad:
+@@ -1226,7 +1223,6 @@
+
+ drv->hapd->driver = NULL;
+
+- (void) madwifi_set_iface_flags(drv, 0);
+ if (drv->ioctl_sock >= 0)
+ close(drv->ioctl_sock);
+ if (drv->sock_recv != NULL && drv->sock_recv != drv->sock_xmit)
+@@ -1306,6 +1452,7 @@
+ .get_ssid = madwifi_get_ssid,
+ .set_countermeasures = madwifi_set_countermeasures,
+ .sta_clear_stats = madwifi_sta_clear_stats,
++ .get_inact_sec = madwifi_get_inact_sec,
+ };
+
+ void madwifi_driver_register(void)
diff --git a/package/iproute2/Makefile b/package/iproute2/Makefile
new file mode 100644
index 0000000000..01097c88b9
--- /dev/null
+++ b/package/iproute2/Makefile
@@ -0,0 +1,68 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=iproute2
+PKG_VERSION:=2.6.15-060110
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://developer.osdl.org/dev/iproute2/download/
+PKG_MD5SUM:=04f57a6d366d36426d276178b600f5c5
+PKG_CAT:=zcat
+
+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)
+ TITLE:=Routing control utility
+endef
+
+define Package/tc
+ $(call Package/iproute2/Default)
+ TITLE:=Traffic control utility
+endef
+
+define Build/Configure
+ $(SED) "s:-O2:${TARGET_CFLAGS}:g" $(PKG_BUILD_DIR)/Makefile
+ $(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
+ # For now disable compiling of the misc directory because it seems to fail
+ rm -rf $(PKG_BUILD_DIR)/misc
+ $(SED) "s, misc,," $(PKG_BUILD_DIR)/Makefile
+endef
+
+define Build/Compile
+ $(MAKE) -j1 -C $(PKG_BUILD_DIR)/netem HOSTCC="$(HOSTCC)" CFLAGS="-D_GNU_SOURCE -O2 -Wstrict-prototypes -Wall -I ../include -DRESOLVE_HOSTNAMES"
+ $(MAKE) -j1 -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS) KERNEL_INCLUDE=$(LINUX_DIR)/include all tc/tc ip/ip
+endef
+
+define Package/ip/install
+ install -d -m0755 $(1)/usr/sbin
+ install -m0755 $(PKG_BUILD_DIR)/ip/ip $(1)/usr/sbin/
+endef
+
+define Package/tc/install
+ install -d -m0755 $(1)/usr/sbin
+ install -m0755 $(PKG_BUILD_DIR)/tc/tc $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,ip))
+$(eval $(call BuildPackage,tc))
diff --git a/package/iproute2/patches/000-debian_patches_3.patch b/package/iproute2/patches/000-debian_patches_3.patch
new file mode 100644
index 0000000000..c6b1bd6bb7
--- /dev/null
+++ b/package/iproute2/patches/000-debian_patches_3.patch
@@ -0,0 +1,1425 @@
+diff -Nur iproute2-2.6.15-060110/doc/ip-cref.tex iproute2-2.6.15-060110-owrt/doc/ip-cref.tex
+--- iproute2-2.6.15-060110/doc/ip-cref.tex 2004-04-15 22:56:59.000000000 +0200
++++ iproute2-2.6.15-060110-owrt/doc/ip-cref.tex 2006-03-22 12:49:35.000000000 +0100
+@@ -1322,6 +1322,19 @@
+ If it is not given, Linux uses the value selected with \verb|sysctl|
+ variable \verb|net/ipv4/tcp_reordering|.
+
++\item \verb|hoplimit NUMBER|
++
++--- [2.5.74+ only] Hop limit on the path to this destination. If it is not
++ given, Linux uses the value selected with \verb|sysctl| variable
++ \verb|net/ipv4/ip_default_ttl|.
++
++\item \verb|initcwnd NUMBER|
++
++--- [2.5.70+ only] Initial congestion window size when establishing
++ connections to this destination. This value is multiplied with the
++ MSS (``Maximal Segment Size'') for the connection to get the actual
++ window size. If it is not given (or set to zero), Linux uses the
++ values specified in~\cite{RFC2414}.
+
+
+ \item \verb|nexthop NEXTHOP|
+@@ -2651,6 +2664,9 @@
+ \bibitem{RFC-DHCP} R.~Droms.
+ ``Dynamic Host Configuration Protocol.'', RFC-2131
+
++\bibitem{RFC2414} M.~Allman, S.~Floyd, C.~Partridge.
++``Increasing TCP's Initial Window'', RFC-2414.
++
+ \end{thebibliography}
+
+
+diff -Nur iproute2-2.6.15-060110/doc/Makefile iproute2-2.6.15-060110-owrt/doc/Makefile
+--- iproute2-2.6.15-060110/doc/Makefile 2005-03-10 20:01:36.000000000 +0100
++++ iproute2-2.6.15-060110-owrt/doc/Makefile 2006-03-22 12:49:35.000000000 +0100
+@@ -14,6 +14,7 @@
+ PAGESPERPAGE=2
+
+ HTMLFILES=$(subst .sgml,.html,$(shell echo *.sgml))
++TXTFILES=$(subst .sgml,.txt,$(shell echo *.sgml))
+ DVIFILES=$(subst .ps,.dvi,$(PSFILES))
+
+
+@@ -23,6 +24,8 @@
+
+ html: $(HTMLFILES)
+
++txt: $(TXTFILES)
++
+ dvi: $(DVIFILES)
+
+ print: $(PSFILES)
+@@ -47,9 +50,12 @@
+ %.html: %.sgml
+ $(SGML2HTML) $<
+
++%.txt: %.html
++ lynx -nolist -dump $< > $@
++
+ install:
+ install -m 0644 $(shell echo *.tex) $(DESTDIR)$(DOCDIR)
+ install -m 0644 $(shell echo *.sgml) $(DESTDIR)$(DOCDIR)
+
+ clean:
+- rm -f *.aux *.log *.toc $(PSFILES) $(DVIFILES) *.html
++ rm -f *.aux *.log *.toc $(PSFILES) $(DVIFILES) *.html $(TXTFILES)
+diff -Nur iproute2-2.6.15-060110/include/linux/pkt_sched.h iproute2-2.6.15-060110-owrt/include/linux/pkt_sched.h
+--- iproute2-2.6.15-060110/include/linux/pkt_sched.h 2005-12-10 00:27:44.000000000 +0100
++++ iproute2-2.6.15-060110-owrt/include/linux/pkt_sched.h 2006-03-22 12:49:35.000000000 +0100
+@@ -1,3 +1,409 @@
++#if 0
++#ifndef __LINUX_PKT_SCHED_H
++#define __LINUX_PKT_SCHED_H
++
++/* Logical priority bands not depending on specific packet scheduler.
++ Every scheduler will map them to real traffic classes, if it has
++ no more precise mechanism to classify packets.
++
++ These numbers have no special meaning, though their coincidence
++ with obsolete IPv6 values is not occasional :-). New IPv6 drafts
++ preferred full anarchy inspired by diffserv group.
++
++ Note: TC_PRIO_BESTEFFORT does not mean that it is the most unhappy
++ class, actually, as rule it will be handled with more care than
++ filler or even bulk.
++ */
++
++#define TC_PRIO_BESTEFFORT 0
++#define TC_PRIO_FILLER 1
++#define TC_PRIO_BULK 2
++#define TC_PRIO_INTERACTIVE_BULK 4
++#define TC_PRIO_INTERACTIVE 6
++#define TC_PRIO_CONTROL 7
++
++#define TC_PRIO_MAX 15
++
++/* Generic queue statistics, available for all the elements.
++ Particular schedulers may have also their private records.
++ */
++
++struct tc_stats
++{
++ __u64 bytes; /* NUmber of enqueues bytes */
++ __u32 packets; /* Number of enqueued packets */
++ __u32 drops; /* Packets dropped because of lack of resources */
++ __u32 overlimits; /* Number of throttle events when this
++ * flow goes out of allocated bandwidth */
++ __u32 bps; /* Current flow byte rate */
++ __u32 pps; /* Current flow packet rate */
++ __u32 qlen;
++ __u32 backlog;
++#ifdef __KERNEL__
++ spinlock_t *lock;
++#endif
++};
++
++struct tc_estimator
++{
++ char interval;
++ unsigned char ewma_log;
++};
++
++/* "Handles"
++ ---------
++
++ All the traffic control objects have 32bit identifiers, or "handles".
++
++ They can be considered as opaque numbers from user API viewpoint,
++ but actually they always consist of two fields: major and
++ minor numbers, which are interpreted by kernel specially,
++ that may be used by applications, though not recommended.
++
++ F.e. qdisc handles always have minor number equal to zero,
++ classes (or flows) have major equal to parent qdisc major, and
++ minor uniquely identifying class inside qdisc.
++
++ Macros to manipulate handles:
++ */
++
++#define TC_H_MAJ_MASK (0xFFFF0000U)
++#define TC_H_MIN_MASK (0x0000FFFFU)
++#define TC_H_MAJ(h) ((h)&TC_H_MAJ_MASK)
++#define TC_H_MIN(h) ((h)&TC_H_MIN_MASK)
++#define TC_H_MAKE(maj,min) (((maj)&TC_H_MAJ_MASK)|((min)&TC_H_MIN_MASK))
++
++#define TC_H_UNSPEC (0U)
++#define TC_H_ROOT (0xFFFFFFFFU)
++#define TC_H_INGRESS (0xFFFFFFF1U)
++
++struct tc_ratespec
++{
++ unsigned char cell_log;
++ unsigned char __reserved;
++ unsigned short feature;
++ short addend;
++ unsigned short mpu;
++ __u32 rate;
++};
++
++/* FIFO section */
++
++struct tc_fifo_qopt
++{
++ __u32 limit; /* Queue length: bytes for bfifo, packets for pfifo */
++};
++
++/* PRIO section */
++
++#define TCQ_PRIO_BANDS 16
++
++struct tc_prio_qopt
++{
++ int bands; /* Number of bands */
++ __u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */
++};
++
++/* CSZ section */
++
++struct tc_csz_qopt
++{
++ int flows; /* Maximal number of guaranteed flows */
++ unsigned char R_log; /* Fixed point position for round number */
++ unsigned char delta_log; /* Log of maximal managed time interval */
++ __u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> CSZ band */
++};
++
++struct tc_csz_copt
++{
++ struct tc_ratespec slice;
++ struct tc_ratespec rate;
++ struct tc_ratespec peakrate;
++ __u32 limit;
++ __u32 buffer;
++ __u32 mtu;
++};
++
++enum
++{
++ TCA_CSZ_UNSPEC,
++ TCA_CSZ_PARMS,
++ TCA_CSZ_RTAB,
++ TCA_CSZ_PTAB,
++};
++
++/* TBF section */
++
++struct tc_tbf_qopt
++{
++ struct tc_ratespec rate;
++ struct tc_ratespec peakrate;
++ __u32 limit;
++ __u32 buffer;
++ __u32 mtu;
++};
++
++enum
++{
++ TCA_TBF_UNSPEC,
++ TCA_TBF_PARMS,
++ TCA_TBF_RTAB,
++ TCA_TBF_PTAB,
++};
++
++
++/* TEQL section */
++
++/* TEQL does not require any parameters */
++
++/* SFQ section */
++
++struct tc_sfq_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 */
++};
++
++/*
++ * NOTE: limit, divisor and flows are hardwired to code at the moment.
++ *
++ * limit=flows=128, divisor=1024;
++ *
++ * The only reason for this is efficiency, it is possible
++ * to change these parameters in compile time.
++ */
++
++/* RED section */
++
++enum
++{
++ TCA_RED_UNSPEC,
++ TCA_RED_PARMS,
++ TCA_RED_STAB,
++};
++
++struct tc_red_qopt
++{
++ __u32 limit; /* HARD maximal queue length (bytes) */
++ __u32 qth_min; /* Min average length threshold (bytes) */
++ __u32 qth_max; /* Max average length threshold (bytes) */
++ unsigned char Wlog; /* log(W) */
++ unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
++ unsigned char Scell_log; /* cell size for idle damping */
++ unsigned char flags;
++#define TC_RED_ECN 1
++};
++
++struct tc_red_xstats
++{
++ __u32 early; /* Early drops */
++ __u32 pdrop; /* Drops due to queue limits */
++ __u32 other; /* Drops due to drop() calls */
++ __u32 marked; /* Marked packets */
++};
++
++/* GRED section */
++
++#define MAX_DPs 16
++
++enum
++{
++ TCA_GRED_UNSPEC,
++ TCA_GRED_PARMS,
++ TCA_GRED_STAB,
++ TCA_GRED_DPS,
++};
++
++#define TCA_SET_OFF TCA_GRED_PARMS
++struct tc_gred_qopt
++{
++ __u32 limit; /* HARD maximal queue length (bytes)
++*/
++ __u32 qth_min; /* Min average length threshold (bytes)
++*/
++ __u32 qth_max; /* Max average length threshold (bytes)
++*/
++ __u32 DP; /* upto 2^32 DPs */
++ __u32 backlog;
++ __u32 qave;
++ __u32 forced;
++ __u32 early;
++ __u32 other;
++ __u32 pdrop;
++
++ unsigned char Wlog; /* log(W) */
++ unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
++ unsigned char Scell_log; /* cell size for idle damping */
++ __u8 prio; /* prio of this VQ */
++ __u32 packets;
++ __u32 bytesin;
++};
++/* gred setup */
++struct tc_gred_sopt
++{
++ __u32 DPs;
++ __u32 def_DP;
++ __u8 grio;
++};
++
++/* HTB section */
++#define TC_HTB_NUMPRIO 8
++#define TC_HTB_MAXDEPTH 8
++#define TC_HTB_PROTOVER 3 /* the same as HTB and TC's major */
++
++struct tc_htb_opt
++{
++ struct tc_ratespec rate;
++ struct tc_ratespec ceil;
++ __u32 buffer;
++ __u32 cbuffer;
++ __u32 quantum;
++ __u32 level; /* out only */
++ __u32 prio;
++};
++struct tc_htb_glob
++{
++ __u32 version; /* to match HTB/TC */
++ __u32 rate2quantum; /* bps->quantum divisor */
++ __u32 defcls; /* default class number */
++ __u32 debug; /* debug flags */
++
++ /* stats */
++ __u32 direct_pkts; /* count of non shapped packets */
++};
++enum
++{
++ TCA_HTB_UNSPEC,
++ TCA_HTB_PARMS,
++ TCA_HTB_INIT,
++ TCA_HTB_CTAB,
++ TCA_HTB_RTAB,
++};
++struct tc_htb_xstats
++{
++ __u32 lends;
++ __u32 borrows;
++ __u32 giants; /* too big packets (rate will not be accurate) */
++ __u32 tokens;
++ __u32 ctokens;
++};
++
++/* CBQ section */
++
++#define TC_CBQ_MAXPRIO 8
++#define TC_CBQ_MAXLEVEL 8
++#define TC_CBQ_DEF_EWMA 5
++
++struct tc_cbq_lssopt
++{
++ unsigned char change;
++ unsigned char flags;
++#define TCF_CBQ_LSS_BOUNDED 1
++#define TCF_CBQ_LSS_ISOLATED 2
++ unsigned char ewma_log;
++ unsigned char level;
++#define TCF_CBQ_LSS_FLAGS 1
++#define TCF_CBQ_LSS_EWMA 2
++#define TCF_CBQ_LSS_MAXIDLE 4
++#define TCF_CBQ_LSS_MINIDLE 8
++#define TCF_CBQ_LSS_OFFTIME 0x10
++#define TCF_CBQ_LSS_AVPKT 0x20
++ __u32 maxidle;
++ __u32 minidle;
++ __u32 offtime;
++ __u32 avpkt;
++};
++
++struct tc_cbq_wrropt
++{
++ unsigned char flags;
++ unsigned char priority;
++ unsigned char cpriority;
++ unsigned char __reserved;
++ __u32 allot;
++ __u32 weight;
++};
++
++struct tc_cbq_ovl
++{
++ unsigned char strategy;
++#define TC_CBQ_OVL_CLASSIC 0
++#define TC_CBQ_OVL_DELAY 1
++#define TC_CBQ_OVL_LOWPRIO 2
++#define TC_CBQ_OVL_DROP 3
++#define TC_CBQ_OVL_RCLASSIC 4
++ unsigned char priority2;
++ __u32 penalty;
++};
++
++struct tc_cbq_police
++{
++ unsigned char police;
++ unsigned char __res1;
++ unsigned short __res2;
++};
++
++struct tc_cbq_fopt
++{
++ __u32 split;
++ __u32 defmap;
++ __u32 defchange;
++};
++
++struct tc_cbq_xstats
++{
++ __u32 borrows;
++ __u32 overactions;
++ __s32 avgidle;
++ __s32 undertime;
++};
++
++enum
++{
++ TCA_CBQ_UNSPEC,
++ TCA_CBQ_LSSOPT,
++ TCA_CBQ_WRROPT,
++ TCA_CBQ_FOPT,
++ TCA_CBQ_OVL_STRATEGY,
++ TCA_CBQ_RATE,
++ TCA_CBQ_RTAB,
++ TCA_CBQ_POLICE,
++};
++
++#define TCA_CBQ_MAX TCA_CBQ_POLICE
++
++/* dsmark section */
++
++enum {
++ TCA_DSMARK_UNSPEC,
++ TCA_DSMARK_INDICES,
++ TCA_DSMARK_DEFAULT_INDEX,
++ TCA_DSMARK_SET_TC_INDEX,
++ TCA_DSMARK_MASK,
++ TCA_DSMARK_VALUE
++};
++
++#define TCA_DSMARK_MAX TCA_DSMARK_VALUE
++
++/* ATM section */
++
++enum {
++ TCA_ATM_UNSPEC,
++ TCA_ATM_FD, /* file/socket descriptor */
++ TCA_ATM_PTR, /* pointer to descriptor - later */
++ TCA_ATM_HDR, /* LL header */
++ TCA_ATM_EXCESS, /* excess traffic class (0 for CLP) */
++ TCA_ATM_ADDR, /* PVC address (for output only) */
++ TCA_ATM_STATE /* VC state (ATM_VS_*; for output only) */
++};
++
++#define TCA_ATM_MAX TCA_ATM_STATE
++
++#endif
++#endif
+ #ifndef __LINUX_PKT_SCHED_H
+ #define __LINUX_PKT_SCHED_H
+
+@@ -466,4 +872,116 @@
+
+ #define NETEM_DIST_SCALE 8192
+
++/* WRR section */
++
++/* Other includes */
++#include <linux/if_ether.h>
++
++// A sub weight and of a class
++// All numbers are represented as parts of (2^64-1).
++struct tc_wrr_class_weight {
++ __u64 val; // Current value (0 is not valid)
++ __u64 decr; // Value pr bytes (2^64-1 is not valid)
++ __u64 incr; // Value pr seconds (2^64-1 is not valid)
++ __u64 min; // Minimal value (0 is not valid)
++ __u64 max; // Minimal value (0 is not valid)
++
++// The time where the above information was correct:
++ time_t tim;
++};
++
++// Packet send when modifying a class:
++struct tc_wrr_class_modf {
++ // Not-valid values are ignored.
++ struct tc_wrr_class_weight weight1;
++ struct tc_wrr_class_weight weight2;
++};
++
++// Packet returned when quering a class:
++struct tc_wrr_class_stats {
++ char used; // If this is false the information below is invalid
++
++ struct tc_wrr_class_modf class_modf;
++
++ unsigned char addr[ETH_ALEN];
++ char usemac; // True if addr is a MAC address, else it is an IP address
++ // (this value is only for convience, it is always the same
++ // value as in the qdisc)
++ int heappos; // Current heap position or 0 if not in heap
++ __u64 penal_ls; // Penalty value in heap (ls)
++ __u64 penal_ms; // Penalty value in heap (ms)
++};
++
++// Qdisc-wide penalty information (boolean values - 2 not valid)
++struct tc_wrr_qdisc_weight {
++ char weight_mode; // 0=No automatic change to weight
++ // 1=Decrease normally
++ // 2=Also multiply with number of machines
++ // 3=Instead multiply with priority divided
++ // with priority of the other.
++ // -1=no change
++};
++
++// Packet send when modifing a qdisc:
++struct tc_wrr_qdisc_modf {
++ // Not-valid values are ignored:
++ struct tc_wrr_qdisc_weight weight1;
++ struct tc_wrr_qdisc_weight weight2;
++};
++
++// Packet send when creating a qdisc:
++struct tc_wrr_qdisc_crt {
++ struct tc_wrr_qdisc_modf qdisc_modf;
++
++ char srcaddr; // 1=lookup source, 0=lookup destination
++ char usemac; // 1=Classify on MAC addresses, 0=classify on IP
++ char usemasq; // 1=Classify based on masqgrading - only valid
++ // if usemac is zero
++ int bands_max; // Maximal number of bands (i.e.: classes)
++ int proxy_maxconn;// If differnt from 0 then we support proxy remapping
++ // of packets. And this is the number of maximal
++ // concurrent proxy connections.
++};
++
++// Packet returned when quering a qdisc:
++struct tc_wrr_qdisc_stats {
++ struct tc_wrr_qdisc_crt qdisc_crt;
++ int proxy_curconn;
++ int nodes_in_heap; // Current number of bands wanting to send something
++ int bands_cur; // Current number of bands used (i.e.: MAC/IP addresses seen)
++ int bands_reused; // Number of times this band has been reused.
++ int packets_requed; // Number of times packets have been requeued.
++ __u64 priosum; // Sum of priorities in heap where 1 is 2^32
++};
++
++struct tc_wrr_qdisc_modf_std {
++ // This indicates which of the tc_wrr_qdisc_modf structers this is:
++ char proxy; // 0=This struct
++
++ // Should we also change a class?
++ char change_class;
++
++ // Only valid if change_class is false
++ struct tc_wrr_qdisc_modf qdisc_modf;
++
++ // Only valid if change_class is true:
++ unsigned char addr[ETH_ALEN]; // Class to change (non-used bytes should be 0)
++ struct tc_wrr_class_modf class_modf; // The change
++};
++
++// Used for proxyrempping:
++struct tc_wrr_qdisc_modf_proxy {
++ // This indicates which of the tc_wrr_qdisc_modf structers this is:
++ char proxy; // 1=This struct
++
++ // This is 1 if the proxyremap information should be reset
++ char reset;
++
++ // changec is the number of elements in changes.
++ int changec;
++
++ // This is an array of type ProxyRemapBlock:
++ long changes[0];
++};
++
+ #endif
+diff -Nur iproute2-2.6.15-060110/ip/iproute.c iproute2-2.6.15-060110-owrt/ip/iproute.c
+--- iproute2-2.6.15-060110/ip/iproute.c 2005-10-13 00:49:50.000000000 +0200
++++ iproute2-2.6.15-060110-owrt/ip/iproute.c 2006-03-22 12:49:35.000000000 +0100
+@@ -60,7 +60,7 @@
+ fprintf(stderr, "OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ]\n");
+ fprintf(stderr, " [ rtt NUMBER ] [ rttvar NUMBER ]\n");
+ fprintf(stderr, " [ window NUMBER] [ cwnd NUMBER ] [ ssthresh NUMBER ]\n");
+- fprintf(stderr, " [ realms REALM ]\n");
++ fprintf(stderr, " [ realms REALM ] [ hoplimit NUMBER ] [ initcwnd NUMBER ]\n");
+ fprintf(stderr, "TYPE := [ unicast | local | broadcast | multicast | throw |\n");
+ fprintf(stderr, " unreachable | prohibit | blackhole | nat ]\n");
+ fprintf(stderr, "TABLE_ID := [ local | main | default | all | NUMBER ]\n");
+@@ -497,6 +497,8 @@
+ "cwnd",
+ "advmss",
+ "reordering",
++ "hoplimit",
++ "initcwnd",
+ };
+ static int hz;
+ if (mxrta[i] == NULL)
+@@ -764,6 +766,30 @@
+ invarg("\"reordering\" value is invalid\n", *argv);
+ rta_addattr32(mxrta, sizeof(mxbuf), RTAX_REORDERING, reord);
+ #endif
++#ifdef RTAX_HOPLIMIT
++ } else if (strcmp(*argv, "hoplimit") == 0) {
++ unsigned hoplim;
++ NEXT_ARG();
++ if (strcmp(*argv, "lock") == 0) {
++ mxlock |= (1<<RTAX_HOPLIMIT);
++ NEXT_ARG();
++ }
++ if (get_unsigned(&hoplim, *argv, 0))
++ invarg("\"hoplimit\" value is invalid\n", *argv);
++ rta_addattr32(mxrta, sizeof(mxbuf), RTAX_HOPLIMIT, hoplim);
++#endif
++#ifdef RTAX_INITCWND
++ } else if (strcmp(*argv, "initcwnd") == 0) {
++ unsigned initcwnd;
++ NEXT_ARG();
++ if (strcmp(*argv, "lock") == 0) {
++ mxlock |= (1<<RTAX_HOPLIMIT);
++ NEXT_ARG();
++ }
++ if (get_unsigned(&initcwnd, *argv, 0))
++ invarg("\"initcwnd\" value is invalid\n", *argv);
++ rta_addattr32(mxrta, sizeof(mxbuf), RTAX_INITCWND, initcwnd);
++#endif
+ } else if (strcmp(*argv, "rtt") == 0) {
+ unsigned rtt;
+ NEXT_ARG();
+diff -Nur iproute2-2.6.15-060110/ip/iptunnel.c iproute2-2.6.15-060110-owrt/ip/iptunnel.c
+--- iproute2-2.6.15-060110/ip/iptunnel.c 2005-02-10 19:31:18.000000000 +0100
++++ iproute2-2.6.15-060110-owrt/ip/iptunnel.c 2006-03-22 12:49:35.000000000 +0100
+@@ -225,7 +225,7 @@
+ NEXT_ARG();
+ p->i_flags |= GRE_KEY;
+ if (strchr(*argv, '.'))
+- p->o_key = get_addr32(*argv);
++ p->i_key = get_addr32(*argv);
+ else {
+ if (get_unsigned(&uval, *argv, 0)<0) {
+ fprintf(stderr, "invalid value of \"ikey\"\n");
+diff -Nur iproute2-2.6.15-060110/Makefile iproute2-2.6.15-060110-owrt/Makefile
+--- iproute2-2.6.15-060110/Makefile 2005-07-09 00:08:47.000000000 +0200
++++ iproute2-2.6.15-060110-owrt/Makefile 2006-03-22 12:51:29.000000000 +0100
+@@ -32,7 +32,7 @@
+ LIBNETLINK=../lib/libnetlink.a ../lib/libutil.a
+
+ all: Config
+- @for i in $(SUBDIRS); \
++ @set -e; for i in $(SUBDIRS); \
+ do $(MAKE) $(MFLAGS) -C $$i; done
+
+ Config:
+@@ -47,7 +47,7 @@
+ $(DESTDIR)$(DOCDIR)/examples
+ install -m 0644 $(shell find examples/diffserv -maxdepth 1 -type f) \
+ $(DESTDIR)$(DOCDIR)/examples/diffserv
+- @for i in $(SUBDIRS) doc; do $(MAKE) -C $$i install; done
++ @set -e; for i in $(SUBDIRS) doc; do $(MAKE) -C $$i install; done
+ install -m 0644 $(shell find etc/iproute2 -maxdepth 1 -type f) $(DESTDIR)$(CONFDIR)
+ install -m 0755 -d $(DESTDIR)$(MANDIR)/man8
+ install -m 0644 $(shell find man/man8 -maxdepth 1 -type f) $(DESTDIR)$(MANDIR)/man8
+@@ -58,7 +58,7 @@
+
+ clean:
+ rm -f cscope.*
+- @for i in $(SUBDIRS) doc; \
++ @set -e; for i in $(SUBDIRS) doc; \
+ do $(MAKE) $(MFLAGS) -C $$i clean; done
+
+ clobber: clean
+diff -Nur iproute2-2.6.15-060110/man/man8/ip.8 iproute2-2.6.15-060110-owrt/man/man8/ip.8
+--- iproute2-2.6.15-060110/man/man8/ip.8 2006-01-03 20:25:29.000000000 +0100
++++ iproute2-2.6.15-060110-owrt/man/man8/ip.8 2006-03-22 12:49:35.000000000 +0100
+@@ -1808,6 +1808,8 @@
+ .RB "IP Command reference " ip-cref.ps
+ .br
+ .RB "IP tunnels " ip-cref.ps
++.br
++.RB http://lartc.org/
+
+ .SH AUTHOR
+ Original Manpage by Michail Litvak <mci@owl.openwall.com>
+diff -Nur iproute2-2.6.15-060110/man/man8/tc.8 iproute2-2.6.15-060110-owrt/man/man8/tc.8
+--- iproute2-2.6.15-060110/man/man8/tc.8 2004-06-08 22:34:17.000000000 +0200
++++ iproute2-2.6.15-060110-owrt/man/man8/tc.8 2006-03-22 12:49:35.000000000 +0100
+@@ -341,7 +341,7 @@
+ .BR tc-pfifo (8),
+ .BR tc-bfifo (8),
+ .BR tc-pfifo_fast (8),
+-.BR tc-filters (8)
++.BR http://lartc.org/
+
+ .SH AUTHOR
+ Manpage maintained by bert hubert (ahu@ds9a.nl)
+diff -Nur iproute2-2.6.15-060110/misc/Makefile iproute2-2.6.15-060110-owrt/misc/Makefile
+--- iproute2-2.6.15-060110/misc/Makefile 2005-06-23 19:39:57.000000000 +0200
++++ iproute2-2.6.15-060110-owrt/misc/Makefile 2006-03-22 12:49:35.000000000 +0100
+@@ -1,7 +1,8 @@
+ SSOBJ=ss.o ssfilter.o
+ LNSTATOBJ=lnstat.o lnstat_util.o
+
+-TARGETS=ss nstat ifstat rtacct arpd lnstat
++#TARGETS=ss nstat ifstat rtacct arpd lnstat
++TARGETS=ss nstat rtacct lnstat
+
+ include ../Config
+
+diff -Nur iproute2-2.6.15-060110/misc/netbug iproute2-2.6.15-060110-owrt/misc/netbug
+--- iproute2-2.6.15-060110/misc/netbug 2004-04-15 22:56:59.000000000 +0200
++++ iproute2-2.6.15-060110-owrt/misc/netbug 2006-03-22 12:49:35.000000000 +0100
+@@ -1,23 +1,16 @@
+ #! /bin/bash
+
++set -e
++
+ echo -n "Send network configuration summary to [ENTER means kuznet@ms2.inr.ac.ru] "
+ IFS="" read mail || exit 1
+ [ -z "$mail" ] && mail=kuznet@ms2.inr.ac.ru
+
++netbug=`mktemp -d -t netbug.XXXXXX` || {echo "$0: Cannot create temporary directory" >&2; exit 1; }
++netbugtar=`tempfile -d $netbug --suffix=tar.gz` || {echo "$0: Cannot create temporary file" >&2; exit 1; }
++tmppath=$netbug
++trap "/bin/rm -rf $netbug $netbugtar" 0 1 2 3 13 15
+
+-netbug=""
+-while [ "$netbug" = "" ]; do
+- netbug=`echo netbug.$$.$RANDOM`
+- if [ -e /tmp/$netbug ]; then
+- netbug=""
+- fi
+-done
+-
+-tmppath=/tmp/$netbug
+-
+-trap "rm -rf $tmppath $tmppath.tar.gz" 0 SIGINT
+-
+-mkdir $tmppath
+ mkdir $tmppath/net
+
+ cat /proc/slabinfo > $tmppath/slabinfo
+@@ -44,9 +37,8 @@
+ fi
+
+ cd /tmp
+-tar c $netbug | gzip -9c > $netbug.tar.gz
+-
+-uuencode $netbug.tar.gz $netbug.tar.gz | mail -s $netbug "$mail"
++tar c $tmppath | gzip -9c > $netbugtar
++uuencode $netbugtar $netbugtar | mail -s $netbug "$mail"
+
+ echo "Sending to <$mail>; subject is $netbug"
+
+diff -Nur iproute2-2.6.15-060110/tc/Makefile iproute2-2.6.15-060110-owrt/tc/Makefile
+--- iproute2-2.6.15-060110/tc/Makefile 2005-07-06 00:11:37.000000000 +0200
++++ iproute2-2.6.15-060110-owrt/tc/Makefile 2006-03-22 12:49:35.000000000 +0100
+@@ -11,6 +11,7 @@
+ TCMODULES += q_prio.o
+ TCMODULES += q_tbf.o
+ TCMODULES += q_cbq.o
++TCMODULES += q_wrr.o
+ TCMODULES += f_rsvp.o
+ TCMODULES += f_u32.o
+ TCMODULES += f_route.o
+diff -Nur iproute2-2.6.15-060110/tc/q_htb.c iproute2-2.6.15-060110-owrt/tc/q_htb.c
+--- iproute2-2.6.15-060110/tc/q_htb.c 2005-01-18 23:11:58.000000000 +0100
++++ iproute2-2.6.15-060110-owrt/tc/q_htb.c 2006-03-22 12:49:35.000000000 +0100
+@@ -1,3 +1,311 @@
++#if 0
++/*
++ * q_htb.c HTB.
++ *
++ * 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: Martin Devera, devik@cdi.cz
++ *
++ */
++
++#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"
++
++#define HTB_TC_VER 0x30003
++#if HTB_TC_VER >> 16 != TC_HTB_PROTOVER
++#error "Different kernel and TC HTB versions"
++#endif
++
++static void explain(void)
++{
++ fprintf(stderr, "Usage: ... qdisc add ... htb [default N] [r2q N]\n"
++ " default minor id of class to which unclassified packets are sent {0}\n"
++ " r2q DRR quantums are computed as rate in Bps/r2q {10}\n"
++ " debug string of 16 numbers each 0-3 {0}\n\n"
++ "... class add ... htb rate R1 burst B1 [prio P] [slot S] [pslot PS]\n"
++ " [ceil R2] [cburst B2] [mtu MTU] [quantum Q]\n"
++ " rate rate allocated to this class (class can still borrow)\n"
++ " burst max bytes burst which can be accumulated during idle period {computed}\n"
++ " ceil definite upper class rate (no borrows) {rate}\n"
++ " cburst burst but for ceil {computed}\n"
++ " mtu max packet size we create rate map for {1600}\n"
++ " prio priority of leaf; lower are served first {0}\n"
++ " quantum how much bytes to serve from leaf at once {use r2q}\n"
++ "\nTC HTB version %d.%d\n",HTB_TC_VER>>16,HTB_TC_VER&0xffff
++ );
++}
++
++static void explain1(char *arg)
++{
++ fprintf(stderr, "Illegal \"%s\"\n", arg);
++ explain();
++}
++
++
++#define usage() return(-1)
++
++static int htb_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
++{
++ struct tc_htb_glob opt;
++ struct rtattr *tail;
++ unsigned i; char *p;
++ memset(&opt,0,sizeof(opt));
++ opt.rate2quantum = 10;
++ opt.version = 3;
++
++ while (argc > 0) {
++ if (matches(*argv, "r2q") == 0) {
++ NEXT_ARG();
++ if (get_u32(&opt.rate2quantum, *argv, 10)) {
++ explain1("r2q"); return -1;
++ }
++ } else if (matches(*argv, "default") == 0) {
++ NEXT_ARG();
++ if (get_u32(&opt.defcls, *argv, 16)) {
++ explain1("default"); return -1;
++ }
++ } else if (matches(*argv, "debug") == 0) {
++ NEXT_ARG(); p = *argv;
++ for (i=0; i<16; i++,p++) {
++ if (*p<'0' || *p>'3') break;
++ opt.debug |= (*p-'0')<<(2*i);
++ }
++ } else {
++ fprintf(stderr, "What is \"%s\"?\n", *argv);
++ explain();
++ return -1;
++ }
++ argc--; argv++;
++ }
++ tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len));
++ addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
++ addattr_l(n, 2024, TCA_HTB_INIT, &opt, NLMSG_ALIGN(sizeof(opt)));
++ tail->rta_len = (((void*)n)+NLMSG_ALIGN(n->nlmsg_len)) - (void*)tail;
++ return 0;
++}
++
++static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
++{
++ int ok=0;
++ struct tc_htb_opt opt;
++ __u32 rtab[256],ctab[256];
++ unsigned buffer=0,cbuffer=0;
++ int cell_log=-1,ccell_log = -1,mtu;
++ struct rtattr *tail;
++
++ memset(&opt, 0, sizeof(opt)); mtu = 1600; /* eth packet len */
++
++ while (argc > 0) {
++ if (matches(*argv, "prio") == 0) {
++ NEXT_ARG();
++ if (get_u32(&opt.prio, *argv, 10)) {
++ explain1("prio"); return -1;
++ }
++ ok++;
++ } else if (matches(*argv, "mtu") == 0) {
++ NEXT_ARG();
++ if (get_u32(&mtu, *argv, 10)) {
++ explain1("mtu"); return -1;
++ }
++ } else if (matches(*argv, "quantum") == 0) {
++ NEXT_ARG();
++ if (get_u32(&opt.quantum, *argv, 10)) {
++ explain1("quantum"); return -1;
++ }
++ } else if (matches(*argv, "burst") == 0 ||
++ strcmp(*argv, "buffer") == 0 ||
++ strcmp(*argv, "maxburst") == 0) {
++ NEXT_ARG();
++ if (get_size_and_cell(&buffer, &cell_log, *argv) < 0) {
++ explain1("buffer");
++ return -1;
++ }
++ ok++;
++ } else if (matches(*argv, "cburst") == 0 ||
++ strcmp(*argv, "cbuffer") == 0 ||
++ strcmp(*argv, "cmaxburst") == 0) {
++ NEXT_ARG();
++ if (get_size_and_cell(&cbuffer, &ccell_log, *argv) < 0) {
++ explain1("cbuffer");
++ return -1;
++ }
++ ok++;
++ } else if (strcmp(*argv, "ceil") == 0) {
++ NEXT_ARG();
++ if (opt.ceil.rate) {
++ fprintf(stderr, "Double \"ceil\" spec\n");
++ return -1;
++ }
++ if (get_rate(&opt.ceil.rate, *argv)) {
++ explain1("ceil");
++ return -1;
++ }
++ ok++;
++ } else if (strcmp(*argv, "rate") == 0) {
++ NEXT_ARG();
++ if (opt.rate.rate) {
++ fprintf(stderr, "Double \"rate\" spec\n");
++ return -1;
++ }
++ if (get_rate(&opt.rate.rate, *argv)) {
++ explain1("rate");
++ 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)
++ return 0;*/
++
++ if (opt.rate.rate == 0) {
++ fprintf(stderr, "\"rate\" is required.\n");
++ return -1;
++ }
++ /* if ceil params are missing, use the same as rate */
++ if (!opt.ceil.rate) opt.ceil = opt.rate;
++
++ /* compute minimal allowed burst from rate; mtu is added here to make
++ sute that buffer is larger than mtu and to have some safeguard space */
++ if (!buffer) buffer = opt.rate.rate / HZ + mtu;
++ if (!cbuffer) cbuffer = opt.ceil.rate / HZ + mtu;
++
++ if ((cell_log = tc_calc_rtable(opt.rate.rate, rtab, cell_log, mtu, 0)) < 0) {
++ fprintf(stderr, "htb: failed to calculate rate table.\n");
++ return -1;
++ }
++ opt.buffer = tc_calc_xmittime(opt.rate.rate, buffer);
++ opt.rate.cell_log = cell_log;
++
++ if ((ccell_log = tc_calc_rtable(opt.ceil.rate, ctab, cell_log, mtu, 0)) < 0) {
++ fprintf(stderr, "htb: failed to calculate ceil rate table.\n");
++ return -1;
++ }
++ opt.cbuffer = tc_calc_xmittime(opt.ceil.rate, cbuffer);
++ opt.ceil.cell_log = ccell_log;
++
++ tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len));
++ addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
++ addattr_l(n, 2024, TCA_HTB_PARMS, &opt, sizeof(opt));
++ addattr_l(n, 3024, TCA_HTB_RTAB, rtab, 1024);
++ addattr_l(n, 4024, TCA_HTB_CTAB, ctab, 1024);
++ tail->rta_len = (((void*)n)+NLMSG_ALIGN(n->nlmsg_len)) - (void*)tail;
++ return 0;
++}
++
++static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
++{
++ struct rtattr *tb[TCA_HTB_RTAB+1];
++ struct tc_htb_opt *hopt;
++ struct tc_htb_glob *gopt;
++ double buffer,cbuffer;
++ SPRINT_BUF(b1);
++ SPRINT_BUF(b2);
++
++ if (opt == NULL)
++ return 0;
++
++ memset(tb, 0, sizeof(tb));
++ parse_rtattr(tb, TCA_HTB_RTAB, RTA_DATA(opt), RTA_PAYLOAD(opt));
++
++ if (tb[TCA_HTB_PARMS]) {
++
++ hopt = RTA_DATA(tb[TCA_HTB_PARMS]);
++ if (RTA_PAYLOAD(tb[TCA_HTB_PARMS]) < sizeof(*hopt)) return -1;
++
++ if (!hopt->level) {
++ fprintf(f, "prio %d ", (int)hopt->prio);
++ if (show_details)
++ fprintf(f, "quantum %d ", (int)hopt->quantum);
++ }
++ fprintf(f, "rate %s ", sprint_rate(hopt->rate.rate, b1));
++ buffer = ((double)hopt->rate.rate*tc_core_tick2usec(hopt->buffer))/1000000;
++ fprintf(f, "ceil %s ", sprint_rate(hopt->ceil.rate, b1));
++ cbuffer = ((double)hopt->ceil.rate*tc_core_tick2usec(hopt->cbuffer))/1000000;
++ if (show_details) {
++ fprintf(f, "burst %s/%u mpu %s ", sprint_size(buffer, b1),
++ 1<<hopt->rate.cell_log, sprint_size(hopt->rate.mpu, b2));
++ fprintf(f, "cburst %s/%u mpu %s ", sprint_size(cbuffer, b1),
++ 1<<hopt->ceil.cell_log, sprint_size(hopt->ceil.mpu, b2));
++ fprintf(f, "level %d ", (int)hopt->level);
++ } else {
++ fprintf(f, "burst %s ", sprint_size(buffer, b1));
++ fprintf(f, "cburst %s ", sprint_size(cbuffer, b1));
++ }
++ if (show_raw)
++ fprintf(f, "buffer [%08x] cbuffer [%08x] ",
++ hopt->buffer,hopt->cbuffer);
++ }
++ if (tb[TCA_HTB_INIT]) {
++ gopt = RTA_DATA(tb[TCA_HTB_INIT]);
++ if (RTA_PAYLOAD(tb[TCA_HTB_INIT]) < sizeof(*gopt)) return -1;
++
++ fprintf(f, "r2q %d default %x direct_packets_stat %u",
++ gopt->rate2quantum,gopt->defcls,gopt->direct_pkts);
++ if (show_details)
++ fprintf(f," ver %d.%d",gopt->version >> 16,gopt->version & 0xffff);
++ }
++ return 0;
++}
++
++static int htb_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats)
++{
++ struct tc_htb_xstats *st;
++ if (xstats == NULL)
++ return 0;
++
++ if (RTA_PAYLOAD(xstats) < sizeof(*st))
++ return -1;
++
++ st = RTA_DATA(xstats);
++ fprintf(f, " lended: %u borrowed: %u giants: %u\n",
++ st->lends,st->borrows,st->giants);
++ fprintf(f, " tokens: %d ctokens: %d\n", st->tokens,st->ctokens);
++ return 0;
++}
++
++struct qdisc_util htb_util = {
++ NULL,
++ "htb",
++ htb_parse_opt,
++ htb_print_opt,
++ htb_print_xstats,
++ htb_parse_class_opt,
++ htb_print_opt,
++};
++
++/* for testing of old one */
++struct qdisc_util htb2_util = {
++ NULL,
++ "htb2",
++ htb_parse_opt,
++ htb_print_opt,
++ htb_print_xstats,
++ htb_parse_class_opt,
++ htb_print_opt,
++};
++#endif
+ /*
+ * q_htb.c HTB.
+ *
+diff -Nur iproute2-2.6.15-060110/tc/q_wrr.c iproute2-2.6.15-060110-owrt/tc/q_wrr.c
+--- iproute2-2.6.15-060110/tc/q_wrr.c 1970-01-01 01:00:00.000000000 +0100
++++ iproute2-2.6.15-060110-owrt/tc/q_wrr.c 2006-03-22 12:49:35.000000000 +0100
+@@ -0,0 +1,322 @@
++#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 <math.h>
++
++#include "utils.h"
++#include "tc_util.h"
++
++#define usage() return(-1)
++
++// Returns -1 on error
++static int wrr_parse_qdisc_weight(int argc, char** argv,
++ struct tc_wrr_qdisc_modf* opt) {
++ int i;
++
++ opt->weight1.weight_mode=-1;
++ opt->weight2.weight_mode=-1;
++
++ for(i=0; i<argc; i++) {
++ if(!memcmp(argv[i],"wmode1=",7)) {
++ opt->weight1.weight_mode=atoi(argv[i]+7);
++ } else if(!memcmp(argv[i],"wmode2=",7)) {
++ opt->weight2.weight_mode=atoi(argv[i]+7);
++ } else {
++ printf("Usage: ... [wmode1=0|1|2|3] [wmode2=0|1|2|3]\n");
++ return -1;
++ }
++ }
++ return 0;
++}
++
++static int wrr_parse_class_modf(int argc, char** argv,
++ struct tc_wrr_class_modf* modf) {
++ int i;
++
++ if(argc<1) {
++ fprintf(stderr, "Usage: ... [weight1=val] [decr1=val] [incr1=val] [min1=val] [max1=val] [val2=val] ...\n");
++ fprintf(stderr, " The values can be floating point like 0.42 or divisions like 42/100\n");
++ return -1;
++ }
++
++ // Set meaningless values:
++ modf->weight1.val=0;
++ modf->weight1.decr=(__u64)-1;
++ modf->weight1.incr=(__u64)-1;
++ modf->weight1.min=0;
++ modf->weight1.max=0;
++ modf->weight2.val=0;
++ modf->weight2.decr=(__u64)-1;
++ modf->weight2.incr=(__u64)-1;
++ modf->weight2.min=0;
++ modf->weight2.max=0;
++
++ // And read values:
++ for(i=0; i<argc; i++) {
++ char arg[80];
++ char* name,*value1=0,*value2=0;
++ long double f_val1,f_val2=1,value;
++ if(strlen(argv[i])>=sizeof(arg)) {
++ fprintf(stderr,"Argument too long: %s\n",argv[i]);
++ return -1;
++ }
++ strcpy(arg,argv[i]);
++
++ name=strtok(arg,"=");
++ if(name) value1=strtok(0,"/");
++ if(value1) value2=strtok(0,"");
++
++ if(!value1) {
++ fprintf(stderr,"No = found in argument: %s\n",argv[i]);
++ return -1;
++ }
++
++ f_val1=atof(value1);
++ if(value2) f_val2=atof(value2);
++
++ if(f_val2==0) {
++ fprintf(stderr,"Division by 0\n");
++ return -1;
++ }
++
++ value=f_val1/f_val2;
++ if(value>1) value=1;
++ if(value<0) value=0;
++ value*=((__u64)-1);
++
++ // And find the value set
++ if(!strcmp(name,"weight1")) modf->weight1.val=value;
++ else if(!strcmp(name,"decr1")) modf->weight1.decr=value;
++ else if(!strcmp(name,"incr1")) modf->weight1.incr=value;
++ else if(!strcmp(name,"min1")) modf->weight1.min=value;
++ else if(!strcmp(name,"max1")) modf->weight1.max=value;
++ else if(!strcmp(name,"weight2")) modf->weight2.val=value;
++ else if(!strcmp(name,"decr2")) modf->weight2.decr=value;
++ else if(!strcmp(name,"incr2")) modf->weight2.incr=value;
++ else if(!strcmp(name,"min2")) modf->weight2.min=value;
++ else if(!strcmp(name,"max2")) modf->weight2.max=value;
++ else {
++ fprintf(stderr,"illegal value: %s\n",name);
++ return -1;
++ }
++ }
++
++ return 0;
++}
++
++static int wrr_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
++{
++ if(n->nlmsg_flags & NLM_F_CREATE) {
++ // This is a create request:
++ struct tc_wrr_qdisc_crt opt;
++
++ int sour,dest,ip,mac,masq;
++
++ if(argc<4) {
++ fprintf(stderr, "Usage: ... wrr sour|dest ip|masq|mac maxclasses proxymaxcon [penalty-setup]\n");
++ return -1;
++ }
++
++ // Read sour/dest:
++ memset(&opt,0,sizeof(opt));
++ sour=!strcmp(argv[0],"sour");
++ dest=!strcmp(argv[0],"dest");
++
++ if(!sour && !dest) {
++ fprintf(stderr,"sour or dest must be specified\n");
++ return -1;
++ }
++
++ // Read ip/mac
++ ip=!strcmp(argv[1],"ip");
++ mac=!strcmp(argv[1],"mac");
++ masq=!strcmp(argv[1],"masq");
++
++ if(!ip && !mac && !masq) {
++ fprintf(stderr,"ip, masq or mac must be specified\n");
++ return -1;
++ }
++
++ opt.srcaddr=sour;
++ opt.usemac=mac;
++ opt.usemasq=masq;
++ opt.bands_max=atoi(argv[2]);
++
++ opt.proxy_maxconn=atoi(argv[3]);
++
++ // Read weights:
++ if(wrr_parse_qdisc_weight(argc-4,argv+4,&opt.qdisc_modf)<0) return -1;
++ if(opt.qdisc_modf.weight1.weight_mode==-1) opt.qdisc_modf.weight1.weight_mode=0;
++ if(opt.qdisc_modf.weight2.weight_mode==-1) opt.qdisc_modf.weight2.weight_mode=0;
++
++ addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt));
++ } else {
++ struct tc_wrr_qdisc_modf_std opt;
++ char qdisc,class;
++
++ // This is a modify request:
++ if(argc<1) {
++ fprintf(stderr,"... qdisc ... or ... class ...\n");
++ return -1;
++ }
++
++ qdisc=!strcmp(argv[0],"qdisc");
++ class=!strcmp(argv[0],"class");
++
++ if(!qdisc && !class) {
++ fprintf(stderr,"qdisc or class must be specified\n");
++ return -1;
++ }
++
++ argc--;
++ argv++;
++
++ opt.proxy=0;
++
++ if(qdisc) {
++ opt.change_class=0;
++ if(wrr_parse_qdisc_weight(argc, argv, &opt.qdisc_modf)<0) return -1;
++ } else {
++ int a0,a1,a2,a3,a4=0,a5=0;
++
++ opt.change_class=1;
++
++ if(argc<1) {
++ fprintf(stderr,"... <mac>|<ip>|<masq> ...\n");
++ return -1;
++ }
++ memset(opt.addr,0,sizeof(opt.addr));
++
++ if((sscanf(argv[0],"%i.%i.%i.%i",&a0,&a1,&a2,&a3)!=4) &&
++ (sscanf(argv[0],"%x:%x:%x:%x:%x:%x",&a0,&a1,&a2,&a3,&a4,&a5)!=6)) {
++ fprintf(stderr,"Wrong format of mac or ip address\n");
++ return -1;
++ }
++
++ opt.addr[0]=a0; opt.addr[1]=a1; opt.addr[2]=a2;
++ opt.addr[3]=a3; opt.addr[4]=a4; opt.addr[5]=a5;
++
++ if(wrr_parse_class_modf(argc-1, argv+1, &opt.class_modf)<0) return -1;
++ }
++
++ addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt));
++ }
++ return 0;
++}
++
++static int wrr_parse_copt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) {
++ struct tc_wrr_class_modf opt;
++
++ memset(&opt,0,sizeof(opt));
++ if(wrr_parse_class_modf(argc,argv,&opt)<0) return -1;
++
++ addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt));
++ return 0;
++}
++
++static int wrr_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
++{
++ struct tc_wrr_qdisc_stats *qopt;
++
++ if (opt == NULL)
++ return 0;
++
++ if (RTA_PAYLOAD(opt) < sizeof(*qopt))
++ return -1;
++ qopt = RTA_DATA(opt);
++
++ fprintf(f,"\n (%s/%s) (maxclasses %i) (usedclasses %i) (reused classes %i)\n",
++ qopt->qdisc_crt.srcaddr ? "sour" : "dest",
++ qopt->qdisc_crt.usemac ? "mac" : (qopt->qdisc_crt.usemasq ? "masq" : "ip"),
++ qopt->qdisc_crt.bands_max,
++ qopt->bands_cur,
++ qopt->bands_reused
++ );
++
++ if(qopt->qdisc_crt.proxy_maxconn) {
++ fprintf(f," (proxy maxcon %i) (proxy curcon %i)\n",
++ qopt->qdisc_crt.proxy_maxconn,qopt->proxy_curconn);
++ }
++
++ fprintf(f," (waiting classes %i) (packets requeued %i) (priosum: %Lg)\n",
++ qopt->nodes_in_heap,
++ qopt->packets_requed,
++ qopt->priosum/((long double)((__u32)-1))
++ );
++
++ fprintf(f," (wmode1 %i) (wmode2 %i) \n",
++ qopt->qdisc_crt.qdisc_modf.weight1.weight_mode,
++ qopt->qdisc_crt.qdisc_modf.weight2.weight_mode);
++
++ return 0;
++}
++
++static int wrr_print_copt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) {
++ struct tc_wrr_class_stats *copt;
++ long double d=(__u64)-1;
++
++ if (opt == NULL) return 0;
++
++ if (RTA_PAYLOAD(opt) < sizeof(*copt))
++ return -1;
++ copt = RTA_DATA(opt);
++
++ if(!copt->used) {
++ fprintf(f,"(unused)");
++ return 0;
++ }
++
++ if(copt->usemac) {
++ fprintf(f,"\n (address: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X)\n",
++ copt->addr[0],copt->addr[1],copt->addr[2],
++ copt->addr[3],copt->addr[4],copt->addr[5]);
++ } else {
++ fprintf(f,"\n (address: %i.%i.%i.%i)\n",copt->addr[0],copt->addr[1],copt->addr[2],copt->addr[3]);
++ }
++
++ fprintf(f," (total weight: %Lg) (current position: %i) (counters: %u %u : %u %u)\n",
++ (copt->class_modf.weight1.val/d)*(copt->class_modf.weight2.val/d),
++ copt->heappos,
++ (unsigned)(copt->penal_ms>>32),
++ (unsigned)(copt->penal_ms & 0xffffffffU),
++ (unsigned)(copt->penal_ls>>32),
++ (unsigned)(copt->penal_ls & 0xffffffffU)
++ );
++
++ fprintf(f," Pars 1: (weight %Lg) (decr: %Lg) (incr: %Lg) (min: %Lg) (max: %Lg)\n",
++ copt->class_modf.weight1.val/d,
++ copt->class_modf.weight1.decr/d,
++ copt->class_modf.weight1.incr/d,
++ copt->class_modf.weight1.min/d,
++ copt->class_modf.weight1.max/d);
++
++ fprintf(f," Pars 2: (weight %Lg) (decr: %Lg) (incr: %Lg) (min: %Lg) (max: %Lg)",
++ copt->class_modf.weight2.val/d,
++ copt->class_modf.weight2.decr/d,
++ copt->class_modf.weight2.incr/d,
++ copt->class_modf.weight2.min/d,
++ copt->class_modf.weight2.max/d);
++
++ return 0;
++}
++
++static int wrr_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats)
++{
++ return 0;
++}
++
++
++struct qdisc_util wrr_qdisc_util = {
++ .id = "wrr",
++ .parse_qopt = wrr_parse_opt,
++ .print_qopt = wrr_print_opt,
++ .print_xstats = wrr_print_xstats,
++ .parse_copt = wrr_parse_copt,
++ .print_copt = wrr_print_copt
++};
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 0000000000..c1491f455f
--- /dev/null
+++ b/package/iproute2/patches/001-iproute2-2.6.11_Config.patch
@@ -0,0 +1,8 @@
+diff -ruN iproute2-2.6.9-old/Config iproute2-2.6.9-new/Config
+--- iproute2-2.6.9-old/Config 1970-01-01 01:00:00.000000000 +0100
++++ iproute2-2.6.9-new/Config 2005-03-22 23:56:56.000000000 +0100
+@@ -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 0000000000..34eaeb0553
--- /dev/null
+++ b/package/iproute2/patches/002-iproute2-ipxfrm_no_sctp.patch
@@ -0,0 +1,19 @@
+diff -Nur iproute2-2.6.11-050330/ip/ipxfrm.c iproute2-2.6.11-050330.new/ip/ipxfrm.c
+--- iproute2-2.6.11-050330/ip/ipxfrm.c 2005-04-01 21:58:11.000000000 +0200
++++ iproute2-2.6.11-050330.new/ip/ipxfrm.c 2005-05-27 12:27:44.000000000 +0200
+@@ -444,7 +444,6 @@
+ switch (sel->proto) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+- case IPPROTO_SCTP:
+ default: /* XXX */
+ if (sel->sport_mask)
+ fprintf(fp, "sport %u ", ntohs(sel->sport));
+@@ -998,7 +997,6 @@
+ switch (sel->proto) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+- case IPPROTO_SCTP:
+ break;
+ default:
+ fprintf(stderr, "\"sport\" and \"dport\" are invalid with proto=%s\n", strxf_proto(sel->proto));
diff --git a/package/iproute2/patches/003-iproute2-htb_overhead.patch b/package/iproute2/patches/003-iproute2-htb_overhead.patch
new file mode 100644
index 0000000000..77ab983835
--- /dev/null
+++ b/package/iproute2/patches/003-iproute2-htb_overhead.patch
@@ -0,0 +1,96 @@
+--- iproute2-2.6.11-050330.new/tc/q_htb.c Sun May 12 22:18:27 2002
++++ iproute2-2.6.11-050330.new/tc/q_htb.c Sat Oct 18 00:05:18 2003
+@@ -34,10 +34,14 @@
+ " default minor id of class to which unclassified packets are sent {0}\n"
+ " r2q DRR quantums are computed as rate in Bps/r2q {10}\n"
+ " debug string of 16 numbers each 0-3 {0}\n\n"
+- "... class add ... htb rate R1 burst B1 [prio P] [slot S] [pslot PS]\n"
++ "... class add ... htb rate R1 [burst B1] [mpu B] [overhead O]\n"
++ " [prio P] [slot S] [pslot PS]\n"
+ " [ceil R2] [cburst B2] [mtu MTU] [quantum Q]\n"
+ " rate rate allocated to this class (class can still borrow)\n"
+ " burst max bytes burst which can be accumulated during idle period {computed}\n"
++ " mpu minimum packet size used in rate computations\n"
++ " overhead per-packet size overhead used in rate computations\n"
++
+ " ceil definite upper class rate (no borrows) {rate}\n"
+ " cburst burst but for ceil {computed}\n"
+ " mtu max packet size we create rate map for {1600}\n"
+@@ -102,7 +106,9 @@
+ struct tc_htb_opt opt;
+ __u32 rtab[256],ctab[256];
+ unsigned buffer=0,cbuffer=0;
+- int cell_log=-1,ccell_log = -1,mtu;
++ int cell_log=-1,ccell_log = -1;
++ unsigned mtu, mpu;
++ unsigned char mpu8 = 0, overhead = 0;
+ struct rtattr *tail;
+
+ memset(&opt, 0, sizeof(opt)); mtu = 1600; /* eth packet len */
+@@ -119,6 +125,16 @@
+ if (get_u32(&mtu, *argv, 10)) {
+ explain1("mtu"); return -1;
+ }
++ } else if (matches(*argv, "mpu") == 0) {
++ NEXT_ARG();
++ if (get_u8(&mpu8, *argv, 10)) {
++ explain1("mpu"); return -1;
++ }
++ } else if (matches(*argv, "overhead") == 0) {
++ NEXT_ARG();
++ if (get_u8(&overhead, *argv, 10)) {
++ explain1("overhead"); return -1;
++ }
+ } else if (matches(*argv, "quantum") == 0) {
+ NEXT_ARG();
+ if (get_u32(&opt.quantum, *argv, 10)) {
+@@ -190,14 +206,18 @@
+ if (!buffer) buffer = opt.rate.rate / HZ + mtu;
+ if (!cbuffer) cbuffer = opt.ceil.rate / HZ + mtu;
+
+- if ((cell_log = tc_calc_rtable(opt.rate.rate, rtab, cell_log, mtu, 0)) < 0) {
++/* encode overhead and mpu, 8 bits each, into lower 16 bits */
++ mpu = (unsigned)mpu8 | (unsigned)overhead << 8;
++ opt.ceil.mpu = mpu; opt.rate.mpu = mpu;
++
++ if ((cell_log = tc_calc_rtable(opt.rate.rate, rtab, cell_log, mtu, mpu)) < 0) {
+ fprintf(stderr, "htb: failed to calculate rate table.\n");
+ return -1;
+ }
+ opt.buffer = tc_calc_xmittime(opt.rate.rate, buffer);
+ opt.rate.cell_log = cell_log;
+
+- if ((ccell_log = tc_calc_rtable(opt.ceil.rate, ctab, cell_log, mtu, 0)) < 0) {
++ if ((ccell_log = tc_calc_rtable(opt.ceil.rate, ctab, cell_log, mtu, mpu)) < 0) {
+ fprintf(stderr, "htb: failed to calculate ceil rate table.\n");
+ return -1;
+ }
+@@ -221,6 +241,7 @@
+ double buffer,cbuffer;
+ SPRINT_BUF(b1);
+ SPRINT_BUF(b2);
++ SPRINT_BUF(b3);
+
+ if (opt == NULL)
+ return 0;
+@@ -243,10 +264,16 @@
+ fprintf(f, "ceil %s ", sprint_rate(hopt->ceil.rate, b1));
+ cbuffer = ((double)hopt->ceil.rate*tc_core_tick2usec(hopt->cbuffer))/1000000;
+ if (show_details) {
+- fprintf(f, "burst %s/%u mpu %s ", sprint_size(buffer, b1),
+- 1<<hopt->rate.cell_log, sprint_size(hopt->rate.mpu, b2));
+- fprintf(f, "cburst %s/%u mpu %s ", sprint_size(cbuffer, b1),
+- 1<<hopt->ceil.cell_log, sprint_size(hopt->ceil.mpu, b2));
++ fprintf(f, "burst %s/%u mpu %s overhead %s ",
++ sprint_size(buffer, b1),
++ 1<<hopt->rate.cell_log,
++ sprint_size(hopt->rate.mpu&0xFF, b2),
++ sprint_size((hopt->rate.mpu>>8)&0xFF, b3));
++ fprintf(f, "cburst %s/%u mpu %s overhead %s ",
++ sprint_size(cbuffer, b1),
++ 1<<hopt->ceil.cell_log,
++ sprint_size(hopt->ceil.mpu&0xFF, b2),
++ sprint_size((hopt->ceil.mpu>>8)&0xFF, b3));
+ fprintf(f, "level %d ", (int)hopt->level);
+ } else {
+ fprintf(f, "burst %s ", sprint_size(buffer, b1));
diff --git a/package/ipsec-tools/Makefile b/package/ipsec-tools/Makefile
new file mode 100644
index 0000000000..2ae6b27eb5
--- /dev/null
+++ b/package/ipsec-tools/Makefile
@@ -0,0 +1,99 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ipsec-tools
+PKG_VERSION:=0.6.4
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=@SF/ipsec-tools
+PKG_MD5SUM:=d0242a943c82c0cbf28005966ff35e21
+PKG_CAT:=bzcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+define Package/ipsec-tools
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=@LINUX_2_6 +libopenssl
+ TITLE:=IPsec management tools
+ URL:=http://ipsec-tools.sourceforge.net/
+endef
+
+define Build/Configure
+ (cd $(PKG_BUILD_DIR); rm -f config.cache; \
+ touch configure.ac; \
+ touch aclocal.m4; \
+ touch Makefile.in; \
+ touch config.h.in; \
+ touch configure; \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ CPPFLAGS="-I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/include" \
+ LDFLAGS="-L$(STAGING_DIR)/usr/lib -L$(STAGING_DIR)/lib" \
+ ./configure \
+ --target=$(GNU_TARGET_NAME) \
+ --host=$(GNU_TARGET_NAME) \
+ --build=$(GNU_HOST_NAME) \
+ --program-prefix="" \
+ --program-suffix="" \
+ --prefix=/usr \
+ --exec-prefix=/usr \
+ --bindir=/usr/bin \
+ --datadir=/usr/share \
+ --includedir=/usr/include \
+ --infodir=/usr/share/info \
+ --libdir=/usr/lib \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --mandir=/usr/share/man \
+ --sbindir=/usr/sbin \
+ --sysconfdir=/etc \
+ $(DISABLE_LARGEFILE) \
+ $(DISABLE_NLS) \
+ --enable-shared \
+ --enable-static \
+ --disable-rpath \
+ --with-gnu-ld \
+ --with-kernel-headers="$(LINUX_DIR)/include" \
+ --without-readline \
+ --with-openssl="$(STAGING_DIR)/usr" \
+ --without-libradius \
+ --without-libpam \
+ --enable-dpd \
+ --enable-natt \
+ );
+endef
+
+define Build/Compile
+ $(call Build/Compile/Default, \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ all install \
+ )
+endef
+
+define Package/ipsec-tools/install
+ install -d -m0755 $(1)/etc
+ install -m0600 $(PKG_BUILD_DIR)/src/racoon/samples/racoon.conf $(1)/etc/
+ install -d -m0755 $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libipsec.so.* $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libracoon.so.* $(1)/usr/lib/
+ install -d -m0755 $(1)/usr/sbin
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/plainrsa-gen $(1)/usr/sbin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/racoon $(1)/usr/sbin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/racoonctl $(1)/usr/sbin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/setkey $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,ipsec-tools))
diff --git a/package/ipsec-tools/patches/01-no_libfl.patch b/package/ipsec-tools/patches/01-no_libfl.patch
new file mode 100644
index 0000000000..c842e229ed
--- /dev/null
+++ b/package/ipsec-tools/patches/01-no_libfl.patch
@@ -0,0 +1,24 @@
+diff -ruN ipsec-tools-0.6.3-old/src/racoon/cftoken.l ipsec-tools-0.6.3-new/src/racoon/cftoken.l
+--- ipsec-tools-0.6.3-old/src/racoon/cftoken.l 2005-11-06 18:18:26.000000000 +0100
++++ ipsec-tools-0.6.3-new/src/racoon/cftoken.l 2005-12-09 01:27:27.000000000 +0100
+@@ -105,6 +105,8 @@
+ static int incstackp = 0;
+
+ static int yy_first_time = 1;
++
++int yywrap(void) { return 1; }
+ %}
+
+ /* common seciton */
+diff -ruN ipsec-tools-0.6.3-old/src/setkey/token.l ipsec-tools-0.6.3-new/src/setkey/token.l
+--- ipsec-tools-0.6.3-old/src/setkey/token.l 2005-06-29 15:01:30.000000000 +0200
++++ ipsec-tools-0.6.3-new/src/setkey/token.l 2005-12-09 01:27:31.000000000 +0100
+@@ -84,6 +84,8 @@
+ #ifndef SADB_X_EALG_AESCTR
+ #define SADB_X_EALG_AESCTR (-1)
+ #endif
++
++int yywrap(void) { return 1; }
+ %}
+
+ /* common section */
diff --git a/package/ipsec-tools/patches/02-configure_cppflags_typo.patch b/package/ipsec-tools/patches/02-configure_cppflags_typo.patch
new file mode 100644
index 0000000000..f725ebdeed
--- /dev/null
+++ b/package/ipsec-tools/patches/02-configure_cppflags_typo.patch
@@ -0,0 +1,24 @@
+diff -ruN ipsec-tools-0.6.3-old/configure.ac ipsec-tools-0.6.3-new/configure.ac
+--- ipsec-tools-0.6.3-old/configure.ac 2005-11-21 12:11:41.000000000 +0100
++++ ipsec-tools-0.6.3-new/configure.ac 2005-12-09 02:09:06.000000000 +0100
+@@ -180,7 +180,7 @@
+
+ if test "x$crypto_dir" != "x"; then
+ LIBS="$LIBS -L${crypto_dir}/lib"
+- CPPFLAGS="-I${crypto_dir}/include $CPPLAGS"
++ CPPFLAGS="-I${crypto_dir}/include $CPPFLAGS"
+ fi
+ AC_MSG_CHECKING(openssl version)
+
+diff -ruN ipsec-tools-0.6.3-old/configure ipsec-tools-0.6.3-new/configure
+--- ipsec-tools-0.6.3-old/configure 2005-11-21 12:15:12.000000000 +0100
++++ ipsec-tools-0.6.3-new/configure 2005-12-09 02:09:13.000000000 +0100
+@@ -23680,7 +23680,7 @@
+
+ if test "x$crypto_dir" != "x"; then
+ LIBS="$LIBS -L${crypto_dir}/lib"
+- CPPFLAGS="-I${crypto_dir}/include $CPPLAGS"
++ CPPFLAGS="-I${crypto_dir}/include $CPPFLAGS"
+ fi
+ echo "$as_me:$LINENO: checking openssl version" >&5
+ echo $ECHO_N "checking openssl version... $ECHO_C" >&6
diff --git a/package/ipset/Makefile b/package/ipset/Makefile
new file mode 100644
index 0000000000..f78ab77a05
--- /dev/null
+++ b/package/ipset/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ipset
+PKG_VERSION:=2.2.3
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-20050914.tar.bz2
+PKG_SOURCE_URL:=http://ipset.netfilter.org
+PKG_MD5SUM:=1709424cc2cdb925d4fb6fd5fcaefc26
+PKG_CAT:=bzcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ipset
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=Netfilter ip sets administration utility
+ URL:=http://ipset.netfilter.org/
+endef
+
+define Build/Compile
+ $(call Build/Compile/Default, \
+ KERNEL_DIR="$(LINUX_DIR)" \
+ )
+endef
+
+define Package/ipset/install
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ DESTDIR="$(1)" \
+ PREFIX="/usr" \
+ install
+ rm -rf $(1)/usr/man
+endef
+
+$(eval $(call BuildPackage,ipset))
diff --git a/package/ipset/patches/kernel26.patch b/package/ipset/patches/kernel26.patch
new file mode 100644
index 0000000000..46112ab25f
--- /dev/null
+++ b/package/ipset/patches/kernel26.patch
@@ -0,0 +1,66 @@
+diff -Nur ipset-2.2.3.orig/ipset.c ipset-2.2.3/ipset.c
+--- ipset-2.2.3.orig/ipset.c 2005-04-05 09:56:02.000000000 +0200
++++ ipset-2.2.3/ipset.c 2005-09-29 13:07:07.446923250 +0200
+@@ -21,7 +21,6 @@
+ #include <stdarg.h>
+ #include <netdb.h>
+ #include <dlfcn.h>
+-#include <asm/bitops.h>
+
+ #include "ipset.h"
+
+diff -Nur ipset-2.2.3.orig/ipset_iphash.c ipset-2.2.3/ipset_iphash.c
+--- ipset-2.2.3.orig/ipset_iphash.c 2005-01-19 14:38:57.000000000 +0100
++++ ipset-2.2.3/ipset_iphash.c 2005-09-29 13:07:26.308102000 +0200
+@@ -25,7 +25,6 @@
+ #include <sys/types.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+-#include <asm/bitops.h>
+ #include <asm/types.h>
+
+ #include <linux/netfilter_ipv4/ip_set_iphash.h>
+diff -Nur ipset-2.2.3.orig/ipset_ipmap.c ipset-2.2.3/ipset_ipmap.c
+--- ipset-2.2.3.orig/ipset_ipmap.c 2005-01-19 14:38:57.000000000 +0100
++++ ipset-2.2.3/ipset_ipmap.c 2005-09-29 13:07:07.446923250 +0200
+@@ -22,7 +22,6 @@
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+-#include <asm/bitops.h>
+
+ #include <linux/netfilter_ipv4/ip_set_ipmap.h>
+ #include "ipset.h"
+diff -Nur ipset-2.2.3.orig/ipset_macipmap.c ipset-2.2.3/ipset_macipmap.c
+--- ipset-2.2.3.orig/ipset_macipmap.c 2005-01-19 14:38:57.000000000 +0100
++++ ipset-2.2.3/ipset_macipmap.c 2005-09-29 13:07:07.446923250 +0200
+@@ -24,7 +24,6 @@
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+-#include <asm/bitops.h>
+ #include <linux/if_ether.h>
+
+ #include <linux/netfilter_ipv4/ip_set_macipmap.h>
+diff -Nur ipset-2.2.3.orig/ipset_nethash.c ipset-2.2.3/ipset_nethash.c
+--- ipset-2.2.3.orig/ipset_nethash.c 2005-05-09 07:44:25.000000000 +0200
++++ ipset-2.2.3/ipset_nethash.c 2005-09-29 13:07:07.446923250 +0200
+@@ -25,7 +25,6 @@
+ #include <sys/types.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+-#include <asm/bitops.h>
+ #include <asm/types.h>
+
+ #include <linux/netfilter_ipv4/ip_set_nethash.h>
+diff -Nur ipset-2.2.3.orig/ipset_portmap.c ipset-2.2.3/ipset_portmap.c
+--- ipset-2.2.3.orig/ipset_portmap.c 2005-01-19 14:38:57.000000000 +0100
++++ ipset-2.2.3/ipset_portmap.c 2005-09-29 13:07:07.446923250 +0200
+@@ -21,7 +21,6 @@
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+-#include <asm/bitops.h>
+
+ #include <linux/netfilter_ipv4/ip_set_portmap.h>
+ #include "ipset.h"
diff --git a/package/iptables/Makefile b/package/iptables/Makefile
new file mode 100644
index 0000000000..d198a9271a
--- /dev/null
+++ b/package/iptables/Makefile
@@ -0,0 +1,249 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=iptables
+PKG_VERSION:=1.3.5
+PKG_RELEASE:=1
+
+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_MD5SUM:=00fb916fa8040ca992a5ace56d905ea5
+PKG_CAT:=bzcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+ifeq ($(DUMP),)
+ -include $(LINUX_DIR)/.config
+ include $(INCLUDE_DIR)/netfilter.mk
+endif
+
+define Package/iptables/Default
+ SECTION:=net
+ CATEGORY:=Base system
+ URL:=http://netfilter.org/
+endef
+
+define Package/iptables
+ $(call Package/iptables/Default)
+ DEFAULT:=y
+ TITLE:=IPv4 firewall administration tool
+ MENU:=1
+endef
+
+define Package/iptables/conffiles
+/etc/config/firewall
+/etc/firewall.user
+endef
+
+define Package/iptables-mod-conntrack
+ $(call Package/iptables/Default)
+ DEPENDS:=iptables +kmod-ipt-conntrack
+ TITLE:=connection tracking modules
+ DESCRIPTION:=\
+ iptables extensions for connection tracking.\\\
+ \\\
+ Includes: \\\
+ - libipt_conntrack \\\
+ - libipt_helper \\\
+ - libipt_connmark/CONNMARK
+endef
+
+define Package/iptables-mod-filter
+ $(call Package/iptables/Default)
+ DEPENDS:=iptables +kmod-ipt-filter
+ TITLE:=filter modules
+ DESCRIPTION:=\
+ iptables extensions for packet content inspection.\\\
+ \\\
+ Includes: \\\
+ - libipt_ipp2p \\\
+ - libipt_layer7
+endef
+
+define Package/iptables-mod-imq
+ $(call Package/iptables/Default)
+ DEPENDS:=iptables
+ TITLE:=IMQ support
+ DESCRIPTION:=\
+ iptables extension for IMQ support.\\\
+ \\\
+ Includes: \\\
+ - libipt_IMQ
+endef
+
+define Package/iptables-mod-ipopt
+ $(call Package/iptables/Default)
+ DEPENDS:=iptables +kmod-ipt-ipopt
+ TITLE:=IP/Packet option modules
+ DESCRIPTION:=\
+ iptables extensions for matching/changing IP packet options.\\\
+ \\\
+ Includes: \\\
+ - libipt_dscp/DSCP \\\
+ - libipt_ecn/ECN \\\
+ - libipt_length \\\
+ - libipt_mac \\\
+ - libipt_tos/TOS \\\
+ - libipt_tcpmms \\\
+ - libipt_ttl/TTL \\\
+ - libipt_unclean
+endef
+
+define Package/iptables-mod-ipsec
+ $(call Package/iptables/Default)
+ DEPENDS:=iptables +kmod-ipt-ipsec
+ TITLE:=IPSec extensions
+ DESCRIPTION:=\
+ iptables extensions for matching ipsec traffic.\\\
+ \\\
+ Includes: \\\
+ - libipt_ah \\\
+ - libipt_esp
+endef
+
+define Package/iptables-mod-nat
+ $(call Package/iptables/Default)
+ DEPENDS:=iptables +kmod-ipt-nat
+ TITLE:=extra NAT targets
+ DESCRIPTION:=\
+ iptables extensions for different NAT targets.\\\
+ \\\
+ Includes: \\\
+ - libipt_REDIRECT
+endef
+
+define Package/iptables-mod-ulog
+ $(call Package/iptables/Default)
+ DEPENDS:=iptables +kmod-ipt-ulog
+ TITLE:=user-space packet logging
+ DESCRIPTION:=\
+ iptables extensions for user-space packet logging.\\\
+ \\\
+ Includes: \\\
+ - libipt_ULOG
+endef
+
+define Package/iptables-mod-extra
+ $(call Package/iptables/Default)
+ DEPENDS:=iptables +kmod-ipt-extra
+ TITLE:=other extra iptables extensions
+ DESCRIPTION:=\
+ other extra iptables extensions.\\\
+ \\\
+ Includes: \\\
+ - libipt_limit \\\
+ - libipt_owner \\\
+ - libipt_physdev \\\
+ - libipt_pkttype \\\
+ - libipt_recent
+endef
+
+define Package/iptables-utils
+ $(call Package/iptables/Default)
+ DEPENDS:=iptables
+ TITLE:=iptables save and restore utilities
+endef
+
+define Package/ip6tables
+ $(call Package/iptables/Default)
+ CATEGORY:=Network
+ TITLE:=IPv6 firewall administration tool
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+ chmod a+x $(PKG_BUILD_DIR)/extensions/.*-test*
+ mkdir -p $(PKG_INSTALL_DIR)
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ COPT_FLAGS="$(TARGET_CFLAGS)" \
+ KERNEL_DIR="$(LINUX_DIR)" PREFIX=/usr \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ all install install-devel
+endef
+
+define Build/InstallDev
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ COPT_FLAGS="$(TARGET_CFLAGS)" \
+ KERNEL_DIR="$(LINUX_DIR)" PREFIX=/usr \
+ DESTDIR="$(STAGING_DIR)" \
+ install install-devel
+endef
+
+define Build/UninstallDev
+ rm -rf $(STAGING_DIR)/usr/include/libipq.h
+ rm -rf $(STAGING_DIR)/usr/lib/libipq.a
+endef
+
+define Package/iptables/install
+ install -d -m0755 $(1)/etc/config
+ install -m0644 ./files/firewall.config $(1)/etc/config/firewall
+ install -d -m0755 $(1)/etc/init.d
+ install -m0755 ./files/firewall.init $(1)/etc/init.d/S45firewall
+ install -m0755 ./files/firewall.user $(1)/etc/
+ install -d -m0755 $(1)/usr/lib
+ install -m0644 ./files/firewall.awk $(1)/usr/lib
+ install -d -m0755 $(1)/usr/sbin
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/iptables $(1)/usr/sbin/
+ install -d -m0755 $(1)/usr/lib/iptables
+ (cd $(PKG_INSTALL_DIR)/usr/lib/iptables ; \
+ $(CP) $(patsubst %,lib%.so,$(IPT_BUILTIN:xt_%=ipt_%)) $(1)/usr/lib/iptables/ \
+ )
+endef
+
+define Package/iptables-utils/install
+ install -d -m0755 $(1)/usr/sbin
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/iptables-{save,restore} $(1)/usr/sbin/
+endef
+
+define Package/ip6tables/install
+ install -d -m0755 $(1)/usr/sbin
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/ip6tables $(1)/usr/sbin/
+ install -d -m0755 $(1)/usr/lib/iptables
+ (cd $(PKG_INSTALL_DIR)/usr/lib/iptables ; \
+ $(CP) libip6t_*.so $(1)/usr/lib/iptables/ \
+ )
+endef
+
+define BuildPlugin
+ define Package/$(1)/install
+ install -m0755 -d $$(1)/usr/lib/iptables
+ for m in $$(patsubst xt_%,ipt_%,$(2)); do \
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/iptables/lib$$$$$$$${m}.so $$(1)/usr/lib/iptables/ ; \
+ done
+ $(3)
+ endef
+
+ $$(eval $$(call BuildPackage,$(1)))
+endef
+
+L7_INSTALL:=mkdir -p $$(1)/etc/l7-protocols; \
+ $(CP) files/l7/*.pat $$(1)/etc/l7-protocols/
+
+$(eval $(call BuildPackage,iptables))
+$(eval $(call BuildPackage,iptables-utils))
+$(eval $(call BuildPlugin,iptables-mod-conntrack,$(IPT_CONNTRACK-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-imq,$(IPT_IMQ-m)))
+$(eval $(call BuildPlugin,iptables-mod-ipopt,$(IPT_IPOPT-m)))
+$(eval $(call BuildPlugin,iptables-mod-ipsec,$(IPT_IPSEC-m)))
+$(eval $(call BuildPlugin,iptables-mod-nat,$(IPT_NAT-m)))
+$(eval $(call BuildPlugin,iptables-mod-ulog,$(IPT_ULOG-m)))
+$(eval $(call BuildPackage,ip6tables))
diff --git a/package/iptables/files/firewall.awk b/package/iptables/files/firewall.awk
new file mode 100644
index 0000000000..902c7b1888
--- /dev/null
+++ b/package/iptables/files/firewall.awk
@@ -0,0 +1,64 @@
+# Copyright (C) 2006 OpenWrt.org
+
+BEGIN {
+ print "ifname=\"$WAN\""
+ print "[ -z \"$ifname\" ] && exit"
+ print ""
+ print "iptables -X input_$ifname 2>&- >&-"
+ print "iptables -N input_$ifname"
+ print "iptables -X forward_$ifname 2>&- >&-"
+ print "iptables -N forward_$ifname"
+ print "iptables -t nat -X prerouting_$ifname 2>&- >&-"
+ print "iptables -t nat -N prerouting_$ifname"
+ print ""
+ print "iptables -A input_rule -i \"$ifname\" -j input_$ifname"
+ print "iptables -A forwarding_rule -i \"$ifname\" -j forward_$ifname"
+ print "iptables -t nat -A prerouting_rule -i \"$ifname\" -j prerouting_$ifname"
+ print ""
+ FS=":"
+}
+
+($1 == "accept") || ($1 == "drop") || ($1 == "forward") {
+ delete _opt
+ str2data($2)
+ if ((_l["proto"] == "") && (_l["sport"] _l["dport"] != "")) {
+ _opt[0] = " -p tcp"
+ _opt[1] = " -p udp"
+ } else {
+ _opt[0] = ""
+ }
+}
+
+($1 == "accept") {
+ target = " -j ACCEPT"
+ for (o in _opt) {
+ print "iptables -t nat -A prerouting_$ifname" _opt[o] str2ipt($2) target
+ print "iptables -A input_$ifname " _opt[o] str2ipt($2) target
+ print ""
+ }
+}
+
+($1 == "drop") {
+ for (o in _opt) {
+ print "iptables -t nat -A prerouting_$ifname" _opt[o] str2ipt($2) " -j DROP"
+ print ""
+ }
+}
+
+($1 == "forward") {
+ target = " -j DNAT --to " $3
+ fwopts = ""
+ if ($4 != "") {
+ if ((_l["proto"] == "tcp") || (_l["proto"] == "udp") || (_l["proto"] == "")) {
+ if (_l["proto"] != "") fwopts = " -p " _l["proto"]
+ fwopts = fwopts " --dport " $4
+ target = target ":" $4
+ }
+ else fwopts = ""
+ }
+ for (o in _opt) {
+ print "iptables -t nat -A prerouting_$ifname" _opt[o] str2ipt($2) target
+ print "iptables -A forward_$ifname " _opt[o] " -d " $3 fwopts " -j ACCEPT"
+ print ""
+ }
+}
diff --git a/package/iptables/files/firewall.config b/package/iptables/files/firewall.config
new file mode 100644
index 0000000000..1b92954c93
--- /dev/null
+++ b/package/iptables/files/firewall.config
@@ -0,0 +1,48 @@
+# Copyright (C) 2006 OpenWrt.org
+
+# RULE SYNTAX:
+#
+# forward:<match>:<target>[:<port>]
+# - forwards all packets matched by <match> to <target>,
+# optionally changing the port to <port>
+#
+# accept:<match>
+# - accepts all traffic matched by <match>
+#
+# drop:<match>
+# - drops all traffic matched by <match>
+#
+#
+# MATCHING OPTIONS:
+#
+# src=<ip>
+# - match the source ip <ip>
+#
+# dest=<ip>
+# - match the destination ip <ip>
+#
+# proto=<proto>
+# - match the protocol by name or number
+#
+# sport=<port(s)>
+# - match the source port(s), see below for syntax
+#
+# dport=<port(s)>
+# - match the destination port(s), see below for syntax
+#
+#
+#
+# PORT SYNTAX:
+#
+# You can enter an arbitrary list of ports and port ranges in the following format:
+# - 22,53,993,1000-1024
+#
+# If you don't set the protocol to tcp or udp, it will apply to both
+#
+#
+#
+# EXAMPLES:
+#
+# drop:dport=22 src=1.3.3.7
+# accept:proto=tcp dport=22
+# forward:dport=60168:192.168.1.2:60169
diff --git a/package/iptables/files/firewall.init b/package/iptables/files/firewall.init
new file mode 100755
index 0000000000..731485bcdd
--- /dev/null
+++ b/package/iptables/files/firewall.init
@@ -0,0 +1,115 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+## Please make changes in /etc/firewall.user
+
+start() {
+ include /lib/network
+ scan_interfaces
+
+ config_get WAN wan ifname
+ config_get LAN lan ifname
+
+ ## CLEAR TABLES
+ for T in filter nat; do
+ iptables -t $T -F
+ iptables -t $T -X
+ done
+
+ iptables -N input_rule
+ iptables -N output_rule
+ iptables -N forwarding_rule
+
+ iptables -t nat -N prerouting_rule
+ iptables -t nat -N postrouting_rule
+
+ iptables -N LAN_ACCEPT
+ [ -z "$WAN" ] || iptables -A LAN_ACCEPT -i "$WAN" -j RETURN
+ iptables -A LAN_ACCEPT -j ACCEPT
+
+ ### INPUT
+ ### (connections with the router as destination)
+
+ # base case
+ iptables -P INPUT DROP
+ iptables -A INPUT -m state --state INVALID -j DROP
+ iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
+ iptables -A INPUT -p tcp --tcp-flags SYN SYN --tcp-option \! 2 -j DROP
+
+ #
+ # insert accept rule or to jump to new accept-check table here
+ #
+ iptables -A INPUT -j input_rule
+
+ # allow
+ iptables -A INPUT -j LAN_ACCEPT # allow from lan/wifi interfaces
+ iptables -A INPUT -p icmp -j ACCEPT # allow ICMP
+ iptables -A INPUT -p gre -j ACCEPT # allow GRE
+
+ # reject (what to do with anything not allowed earlier)
+ iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset
+ iptables -A INPUT -j REJECT --reject-with icmp-port-unreachable
+
+ ### OUTPUT
+ ### (connections with the router as source)
+
+ # base case
+ iptables -P OUTPUT DROP
+ iptables -A OUTPUT -m state --state INVALID -j DROP
+ iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
+
+ #
+ # insert accept rule or to jump to new accept-check table here
+ #
+ iptables -A OUTPUT -j output_rule
+
+ # allow
+ iptables -A OUTPUT -j ACCEPT #allow everything out
+
+ # reject (what to do with anything not allowed earlier)
+ iptables -A OUTPUT -p tcp -j REJECT --reject-with tcp-reset
+ iptables -A OUTPUT -j REJECT --reject-with icmp-port-unreachable
+
+ ### FORWARDING
+ ### (connections routed through the router)
+
+ # base case
+ iptables -P FORWARD DROP
+ iptables -A FORWARD -m state --state INVALID -j DROP
+ iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
+ iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
+
+ #
+ # insert accept rule or to jump to new accept-check table here
+ #
+ iptables -A FORWARD -j forwarding_rule
+
+ # allow
+ iptables -A FORWARD -i br0 -o br0 -j ACCEPT
+ [ -z "$WAN" ] || iptables -A FORWARD -i $LAN -o $WAN -j ACCEPT
+
+ # reject (what to do with anything not allowed earlier)
+ # uses the default -P DROP
+
+ ### MASQ
+ iptables -t nat -A PREROUTING -j prerouting_rule
+ iptables -t nat -A POSTROUTING -j postrouting_rule
+ [ -z "$WAN" ] || iptables -t nat -A POSTROUTING -o $WAN -j MASQUERADE
+
+ ## USER RULES
+ [ -f /etc/firewall.user ] && . /etc/firewall.user
+ [ -n "$WAN" -a -e /etc/config/firewall ] && {
+ awk -f /usr/lib/common.awk -f /usr/lib/firewall.awk /etc/config/firewall | ash
+ }
+}
+
+stop() {
+ iptables -P INPUT ACCEPT
+ iptables -P OUTPUT ACCEPT
+ iptables -P FORWARD ACCEPT
+ iptables -F
+ iptables -t nat -P PREROUTING ACCEPT
+ iptables -t nat -P POSTROUTING ACCEPT
+ iptables -t nat -P OUTPUT ACCEPT
+ iptables -t nat -F
+}
diff --git a/package/iptables/files/firewall.user b/package/iptables/files/firewall.user
new file mode 100644
index 0000000000..5f295babf2
--- /dev/null
+++ b/package/iptables/files/firewall.user
@@ -0,0 +1,28 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+iptables -F input_rule
+iptables -F output_rule
+iptables -F forwarding_rule
+iptables -t nat -F prerouting_rule
+iptables -t nat -F postrouting_rule
+
+### BIG FAT DISCLAIMER
+## The "-i $WAN" is used to match packets that come in via the $WAN interface.
+## it WILL NOT MATCH packets sent from the $WAN ip address -- you won't be able
+## to see the effects from within the LAN.
+
+### Open port to WAN
+## -- This allows port 22 to be answered by (dropbear on) the router
+# iptables -t nat -A prerouting_rule -i $WAN -p tcp --dport 22 -j ACCEPT
+# iptables -A input_rule -i $WAN -p tcp --dport 22 -j ACCEPT
+
+### Port forwarding
+## -- This forwards port 8080 on the WAN to port 80 on 192.168.1.2
+# iptables -t nat -A prerouting_rule -i $WAN -p tcp --dport 8080 -j DNAT --to 192.168.1.2:80
+# iptables -A forwarding_rule -i $WAN -p tcp --dport 80 -d 192.168.1.2 -j ACCEPT
+
+### DMZ
+## -- Connections to ports not handled above will be forwarded to 192.168.1.2
+# iptables -t nat -A prerouting_rule -i $WAN -j DNAT --to 192.168.1.2
+# iptables -A forwarding_rule -i $WAN -d 192.168.1.2 -j ACCEPT
diff --git a/package/iptables/files/l7/aim.pat b/package/iptables/files/l7/aim.pat
new file mode 100644
index 0000000000..9768dbbdc8
--- /dev/null
+++ b/package/iptables/files/l7/aim.pat
@@ -0,0 +1,27 @@
+# AIM - AOL instant messenger (OSCAR and TOC)
+# Pattern quality: good notsofast
+# Usually runs on port 5190
+#
+# This may also match ICQ traffic.
+#
+# This pattern has been tested and is believed to work well. If it does not
+# work for you, or you believe it could be improved, please post to
+# l7-filter-developers@lists.sf.net . This list may be subscribed to at
+# http://lists.sourceforge.net/lists/listinfo/l7-filter-developers
+
+aim
+# See http://gridley.acns.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 0000000000..c1804ee4ba
--- /dev/null
+++ b/package/iptables/files/l7/bittorrent.pat
@@ -0,0 +1,14 @@
+# Bittorrent - P2P filesharing / publishing tool - http://www.bittorrent.com
+# Pattern quality: great veryfast
+#
+# This pattern has been tested and is believed to work well. If it does not
+# work for you, or you believe it could be improved, please post to
+# l7-filter-developers@lists.sf.net . This list may be subscribed to at
+# http://lists.sourceforge.net/lists/listinfo/l7-filter-developers
+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, commented out until it's tested
+#^(\x13bittorrent protocol|d1:ad2:id20:|\x08'7P\)[RP])
+^\x13bittorrent protocol
diff --git a/package/iptables/files/l7/edonkey-dl.pat b/package/iptables/files/l7/edonkey-dl.pat
new file mode 100644
index 0000000000..d344d169d0
--- /dev/null
+++ b/package/iptables/files/l7/edonkey-dl.pat
@@ -0,0 +1,8 @@
+# eDonkey2000 - P2P filesharing (download part) - http://edonkey2000.com
+# Pattern quality: good veryfast overmatch usepacket
+
+edonkey-dl
+
+^[\xe3\xe4\xc5\xe5\xd4](....)?[\x01\x0a\x0e\x0f\x10\x18\x19\x1b\x1c\x47\x4a\x4f\x51\x53\x54\x58\x60\x81\x90\x96\x9a\x9c\xa2]
+
+
diff --git a/package/iptables/files/l7/edonkey.pat b/package/iptables/files/l7/edonkey.pat
new file mode 100644
index 0000000000..efbc3f361e
--- /dev/null
+++ b/package/iptables/files/l7/edonkey.pat
@@ -0,0 +1,29 @@
+# eDonkey2000 - P2P filesharing - http://edonkey2000.com
+# Pattern quality: good veryfast overmatch
+#
+# Please post to l7-filter-developers@lists.sf.net as to whether this pattern
+# works for you or not. If you believe it could be improved please post your
+# suggestions to that list as well. You may subscribe to this list at
+# http://lists.sourceforge.net/lists/listinfo/l7-filter-developers
+
+# 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
+#
+# God this is a mess. What an irritating protocol.
+# This will match about 1% of streams with random data in them!
+
+^[\xe3\xc5\xe5\xd4](....)?([\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\x5b\x5c\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 0000000000..46295c6bbe
--- /dev/null
+++ b/package/iptables/files/l7/fasttrack.pat
@@ -0,0 +1,25 @@
+# FastTrack - P2P filesharing (Kazaa, Morpheus, iMesh, Grokster, etc)
+# Pattern quality: good notsofast
+#
+# 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 :-( ).
+#
+# Please post to l7-filter-developers@lists.sf.net as to whether it works
+# for you or not. If you believe it could be improved please post your
+# suggestions to that list as well. You may subscribe to this list at
+# http://lists.sourceforge.net/lists/listinfo/l7-filter-developers
+
+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 0000000000..9593ffd1bd
--- /dev/null
+++ b/package/iptables/files/l7/ftp.pat
@@ -0,0 +1,34 @@
+# FTP - File Transfer Protocol - RFC 959
+# Pattern quality: great fast
+#
+# 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. If it does not
+# work for you, or you believe it could be improved, please post to
+# l7-filter-developers@lists.sf.net . This list may be subscribed to at
+# http://lists.sourceforge.net/lists/listinfo/l7-filter-developers
+#
+# Matches the first two things a server should say. 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. Just in case, the next
+# thing the server sends is a 331. All the above servers also send
+# something including "password" after this code.
+ftp
+# actually, let's just do the first for now, it's faster
+^220[\x09-\x0d -~]*ftp
+
+# This is ~10x faster if the stream starts with "220"
+#^220.*ftp
+
+# This will match more, but 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 0000000000..ebbd5c621d
--- /dev/null
+++ b/package/iptables/files/l7/gnutella.pat
@@ -0,0 +1,36 @@
+# Gnutella - P2P filesharing
+# Pattern quality: good fast
+#
+# This should match both Gnutella and "Gnutella2" ("Mike's protocol")
+#
+# Various clients use this protocol including Mactella, Shareaza,
+# GTK-gnutella, Gnucleus, Gnotella, LimeWire, BearShare, and iMesh.
+#
+# This is tested with gtk-gnutella and Shareaza.
+#
+# Please report on how this pattern works for you at
+# l7-filter-developers@lists.sf.net . If you can improve on this
+# pattern, please also post to that list. You may subscribe at
+# http://lists.sourceforge.net/lists/listinfo/l7-filter-developers
+
+# 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 0000000000..520e7fe212
--- /dev/null
+++ b/package/iptables/files/l7/http.pat
@@ -0,0 +1,28 @@
+# HTTP - HyperText Transfer Protocol - RFC 2616
+# Pattern quality: great notsofast
+# Usually runs on port 80
+#
+# This pattern has been tested and is believed to work well. If it does not
+# work for you, or you believe it could be improved, please post to
+# l7-filter-developers@lists.sf.net . This list may be subscribed to at
+# http://lists.sourceforge.net/lists/listinfo/l7-filter-developers
+#
+# 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 0000000000..672b0753ce
--- /dev/null
+++ b/package/iptables/files/l7/ident.pat
@@ -0,0 +1,14 @@
+# Ident - Identification Protocol - RFC 1413
+# Pattern quality: good veryfast
+# Usually runs on port 113
+#
+# This pattern is believed to work. If it does not
+# work for you, or you believe it could be improved, please post to
+# l7-filter-developers@lists.sf.net . This list may be subscribed to at
+# http://lists.sourceforge.net/lists/listinfo/l7-filter-developers
+
+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 0000000000..6643f6c2f7
--- /dev/null
+++ b/package/iptables/files/l7/irc.pat
@@ -0,0 +1,20 @@
+# IRC - Internet Relay Chat - RFC 1459
+# Pattern quality: good veryfast
+#
+# 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. If it does not
+# work for you, or you believe it could be improved, please post to
+# l7-filter-developers@lists.sf.net . This list may be subscribed to at
+# http://lists.sourceforge.net/lists/listinfo/l7-filter-developers
+
+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 0000000000..7a0c6840e1
--- /dev/null
+++ b/package/iptables/files/l7/jabber.pat
@@ -0,0 +1,24 @@
+# Jabber (XMPP) - an open instant messenger protocol - http://jabber.org
+# Pattern quality: good fast
+#
+# This pattern has been tested with Gaim and Gabber. It is only tested
+# with non-SSL mode Jabber with no proxies. If it does not
+# work for you, or you believe it could be improved, please post to
+# l7-filter-developers@lists.sf.net . This list may be subscribed to at
+# http://lists.sourceforge.net/lists/listinfo/l7-filter-developers
+
+# 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 0000000000..e07f71f311
--- /dev/null
+++ b/package/iptables/files/l7/msnmessenger.pat
@@ -0,0 +1,15 @@
+# MSN Messenger - Microsoft Network chat client
+# Pattern quality: good veryfast
+#
+# Usually uses port 1863
+# http://www.hypothetic.org/docs/msn/index.php
+#
+# This pattern has been tested and is believed to work well. If it does not
+# work for you, or you believe it could be improved, please post to
+# l7-filter-developers@lists.sf.net . This list may be subscribed to at
+# http://lists.sourceforge.net/lists/listinfo/l7-filter-developers
+
+msnmessenger
+# ver: allow versions up to 99.
+# usr (in case ver didn't work):
+^(ver [0-9]+ msnp[1-9][0-9]? [\x09-\x0d -~]* cvr|usr md5 i [ -~]*)
diff --git a/package/iptables/files/l7/ntp.pat b/package/iptables/files/l7/ntp.pat
new file mode 100644
index 0000000000..b7e443e21f
--- /dev/null
+++ b/package/iptables/files/l7/ntp.pat
@@ -0,0 +1,17 @@
+# (S)NTP - (Simple) Network Time Protocol - RFCs 1305 and 2030
+# Pattern quality: good veryfast overmatch
+#
+# This pattern is tested and is believed to work. If this does not work
+# for you, or you believe it could be improved, please post to
+# l7-filter-developers@lists.sf.net . Subscribe at
+# http://lists.sourceforge.net/lists/listinfo/l7-filter-developers
+
+# 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 0000000000..f6bb630614
--- /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 quality: good veryfast
+#
+# This pattern has been tested somewhat. If it does not
+# work for you, or you believe it could be improved, please post to
+# l7-filter-developers@lists.sf.net . This list may be subscribed to at
+# http://lists.sourceforge.net/lists/listinfo/l7-filter-developers
+
+# 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 0000000000..1bab7a1df4
--- /dev/null
+++ b/package/iptables/files/l7/smtp.pat
@@ -0,0 +1,39 @@
+# SMTP - Simple Mail Transfer Protocol - RFC 2821 (See also RFC 1869)
+# Pattern quality: great fast
+# usually runs on port 25
+#
+# This pattern has been tested and is believed to work well. If it does not
+# work for you, or you believe it could be improved, please post to
+# l7-filter-developers@lists.sf.net . This list may be subscribed to at
+# http://lists.sourceforge.net/lists/listinfo/l7-filter-developers
+
+smtp
+# 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.
+^220[\x09-\x0d -~]* (e?smtp|simple mail)
+
+# This is ~3x faster if the stream starts with "220"
+#^220.* (e?smtp|simple mail)
+
+# 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
diff --git a/package/iptables/files/l7/ssl.pat b/package/iptables/files/l7/ssl.pat
new file mode 100644
index 0000000000..ab5f62caa7
--- /dev/null
+++ b/package/iptables/files/l7/ssl.pat
@@ -0,0 +1,15 @@
+# SSL and TLS - Secure Socket Layer / Transport Layer Security - RFC 2246
+# Pattern quality: good fast
+# Usually runs on port 443
+#
+# This is a superset validcertssl. For it to match, it must be first.
+#
+# This pattern has been tested and is believed to work well. If it does not
+# work for you, or you believe it could be improved, please post to
+# l7-filter-developers@lists.sf.net . This list may be subscribed to at
+# http://lists.sourceforge.net/lists/listinfo/l7-filter-developers
+
+ssl
+# Client Hello | Server Hello with certificate
+# 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 0000000000..35bfbd4bad
--- /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 quality: good fast
+# http://www.realvnc.com/documentation.html
+#
+# This pattern has been verified with vnc v3.3.7 on WinXP and Linux
+# Please report on how this pattern works for you at
+# l7-filter-developers@lists.sf.net . If you can improve on this pattern,
+# please also post to that list. You may subscribe at
+# http://lists.sourceforge.net/lists/listinfo/l7-filter-developers
+#
+# 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/01-ipp2p-0.8.1rc1.patch b/package/iptables/patches/01-ipp2p-0.8.1rc1.patch
new file mode 100644
index 0000000000..f7129b4560
--- /dev/null
+++ b/package/iptables/patches/01-ipp2p-0.8.1rc1.patch
@@ -0,0 +1,454 @@
+diff -urN iptables.old/extensions/Makefile iptables.dev/extensions/Makefile
+--- iptables.old/extensions/Makefile 2005-07-20 04:22:56.000000000 +0200
++++ iptables.dev/extensions/Makefile 2006-03-23 14:42:28.000000000 +0100
+@@ -8,6 +8,10 @@
+ PF_EXT_SLIB:=ah addrtype comment connlimit connmark conntrack dscp ecn esp hashlimit helper icmp iprange length limit mac mark multiport owner physdev pkttype realm rpc sctp standard state tcp tcpmss tos ttl udp unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NFQUEUE NOTRACK REDIRECT REJECT SAME SNAT TARPIT TCPMSS TOS TRACE TTL ULOG
+ PF6_EXT_SLIB:=eui64 hl icmpv6 length limit mac mark multiport owner physdev standard tcp udp HL LOG NFQUEUE MARK TRACE
+
++
++# ipp2p
++PF_EXT_SLIB += ipp2p
++
+ # Optionals
+ PF_EXT_SLIB_OPTS:=$(foreach T,$(wildcard extensions/.*-test),$(shell KERNEL_DIR=$(KERNEL_DIR) $(T)))
+ PF6_EXT_SLIB_OPTS:=$(foreach T,$(wildcard extensions/.*-test6),$(shell KERNEL_DIR=$(KERNEL_DIR) $(T)))
+diff -urN iptables.old/extensions/libipt_ipp2p.c iptables.dev/extensions/libipt_ipp2p.c
+--- iptables.old/extensions/libipt_ipp2p.c 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/libipt_ipp2p.c 2006-03-23 14:43:26.000000000 +0100
+@@ -0,0 +1,401 @@
++
++#include <stdio.h>
++#include <netdb.h>
++#include <string.h>
++#include <stdlib.h>
++#include <getopt.h>
++#include <ctype.h>
++
++#include <iptables.h>
++
++#include <linux/netfilter_ipv4/ipt_ipp2p.h>
++
++static void
++help(void)
++{
++ printf(
++ "IPP2P v%s options:\n"
++ " --ipp2p Grab all known p2p packets\n"
++ " --edk [TCP&UDP] All known eDonkey/eMule/Overnet packets\n"
++ " --dc [TCP] All known Direct Connect packets\n"
++ " --kazaa [TCP&UDP] All known KaZaA packets\n"
++ " --gnu [TCP&UDP] All known Gnutella packets\n"
++ " --bit [TCP&UDP] All known BitTorrent packets\n"
++ " --apple [TCP] All known AppleJuice packets\n"
++ " --winmx [TCP] All known WinMX\n"
++ " --soul [TCP] All known SoulSeek\n"
++ " --ares [TCP] All known Ares\n\n"
++ " EXPERIMENTAL protocols (please send feedback to: ipp2p@ipp2p.org) :\n"
++ " --mute [TCP] All known Mute packets\n"
++ " --waste [TCP] All known Waste packets\n"
++ " --xdcc [TCP] All known XDCC packets (only xdcc login)\n\n"
++ " DEBUG SUPPPORT, use only if you know why\n"
++ " --debug Generate kernel debug output, THIS WILL SLOW DOWN THE FILTER\n"
++ "\nNote that the follwing options will have the same meaning:\n"
++ " '--ipp2p' is equal to '--edk --dc --kazaa --gnu --bit --apple --winmx --soul --ares'\n"
++ "\nIPP2P was intended for TCP only. Due to increasing usage of UDP we needed to change this.\n"
++ "You can now use -p udp to search UDP packets only or without -p switch to search UDP and TCP packets.\n"
++ "\nSee README included with this package for more details or visit http://www.ipp2p.org\n"
++ "\nExamples:\n"
++ " iptables -A FORWARD -m ipp2p --ipp2p -j MARK --set-mark 0x01\n"
++ " iptables -A FORWARD -p udp -m ipp2p --kazaa --bit -j DROP\n"
++ " iptables -A FORWARD -p tcp -m ipp2p --edk --soul -j DROP\n\n"
++ , IPP2P_VERSION);
++}
++
++static struct option opts[] = {
++ { "ipp2p", 0, 0, '1' },
++ { "edk", 0, 0, '2' },
++ { "dc", 0, 0, '7' },
++ { "gnu", 0, 0, '9' },
++ { "kazaa", 0, 0, 'a' },
++ { "bit", 0, 0, 'b' },
++ { "apple", 0, 0, 'c' },
++ { "soul", 0, 0, 'd' },
++ { "winmx", 0, 0, 'e' },
++ { "ares", 0, 0, 'f' },
++ { "mute", 0, 0, 'g' },
++ { "waste", 0, 0, 'h' },
++ { "xdcc", 0, 0, 'i' },
++ { "debug", 0, 0, 'j' },
++ {0}
++};
++
++
++
++static void
++init(struct ipt_entry_match *m, unsigned int *nfcache)
++{
++ struct ipt_p2p_info *info = (struct ipt_p2p_info *)m->data;
++
++ *nfcache |= NFC_UNKNOWN;
++
++ /*init the module with default values*/
++ info->cmd = 0;
++ info->debug = 0;
++
++}
++
++
++static int
++parse(int c, char **argv, int invert, unsigned int *flags,
++ const struct ipt_entry *entry,
++ unsigned int *nfcache,
++ struct ipt_entry_match **match)
++{
++ struct ipt_p2p_info *info = (struct ipt_p2p_info *)(*match)->data;
++
++ switch (c) {
++ case '1': /*cmd: ipp2p*/
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified once!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags) != 0)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += SHORT_HAND_IPP2P;
++ info->cmd = *flags;
++ break;
++
++ case '2': /*cmd: edk*/
++ if ((*flags & IPP2P_EDK) == IPP2P_EDK)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--edk' may only be "
++ "specified once");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags & IPP2P_DATA_EDK) == IPP2P_DATA_EDK)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: use `--edk' OR `--edk-data' but not both of them!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_EDK;
++ info->cmd = *flags;
++ break;
++
++
++ case '7': /*cmd: dc*/
++ if ((*flags & IPP2P_DC) == IPP2P_DC)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--dc' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags & IPP2P_DATA_DC) == IPP2P_DATA_DC)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: use `--dc' OR `--dc-data' but not both of them!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_DC;
++ info->cmd = *flags;
++ break;
++
++
++ case '9': /*cmd: gnu*/
++ if ((*flags & IPP2P_GNU) == IPP2P_GNU)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--gnu' may only be "
++ "specified once!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if ((*flags & IPP2P_DATA_GNU) == IPP2P_DATA_GNU)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: use `--gnu' OR `--gnu-data' but not both of them!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_GNU;
++ info->cmd = *flags;
++ break;
++
++ case 'a': /*cmd: kazaa*/
++ if ((*flags & IPP2P_KAZAA) == IPP2P_KAZAA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--kazaa' may only be "
++ "specified once!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if ((*flags & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: use `--kazaa' OR `--kazaa-data' but not both of them!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_KAZAA;
++ info->cmd = *flags;
++ break;
++
++ case 'b': /*cmd: bit*/
++ if ((*flags & IPP2P_BIT) == IPP2P_BIT)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--bit' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_BIT;
++ info->cmd = *flags;
++ break;
++
++ case 'c': /*cmd: apple*/
++ if ((*flags & IPP2P_APPLE) == IPP2P_APPLE)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--apple' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_APPLE;
++ info->cmd = *flags;
++ break;
++
++
++ case 'd': /*cmd: soul*/
++ if ((*flags & IPP2P_SOUL) == IPP2P_SOUL)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--soul' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_SOUL;
++ info->cmd = *flags;
++ break;
++
++
++ case 'e': /*cmd: winmx*/
++ if ((*flags & IPP2P_WINMX) == IPP2P_WINMX)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--winmx' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_WINMX;
++ info->cmd = *flags;
++ break;
++
++ case 'f': /*cmd: ares*/
++ if ((*flags & IPP2P_ARES) == IPP2P_ARES)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ares' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_ARES;
++ info->cmd = *flags;
++ break;
++
++ case 'g': /*cmd: mute*/
++ if ((*flags & IPP2P_MUTE) == IPP2P_MUTE)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--mute' may only be "
++ "specified once!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_MUTE;
++ info->cmd = *flags;
++ break;
++ case 'h': /*cmd: waste*/
++ if ((*flags & IPP2P_WASTE) == IPP2P_WASTE)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--waste' may only be "
++ "specified once!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_WASTE;
++ info->cmd = *flags;
++ break;
++ case 'i': /*cmd: xdcc*/
++ if ((*flags & IPP2P_XDCC) == IPP2P_XDCC)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ares' may only be "
++ "specified once!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_XDCC;
++ info->cmd = *flags;
++ break;
++
++ case 'j': /*cmd: debug*/
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ info->debug = 1;
++ break;
++
++ default:
++// exit_error(PARAMETER_PROBLEM,
++// "\nipp2p-parameter problem: for ipp2p usage type: iptables -m ipp2p --help\n");
++ return 0;
++ }
++ return 1;
++}
++
++
++static void
++final_check(unsigned int flags)
++{
++ if (!flags)
++ exit_error(PARAMETER_PROBLEM,
++ "\nipp2p-parameter problem: for ipp2p usage type: iptables -m ipp2p --help\n");
++}
++
++
++
++static void
++print(const struct ipt_ip *ip,
++ const struct ipt_entry_match *match,
++ int numeric)
++{
++ struct ipt_p2p_info *info = (struct ipt_p2p_info *)match->data;
++
++ printf("ipp2p v%s", IPP2P_VERSION);
++ if ((info->cmd & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P) printf(" --ipp2p");
++// if ((info->cmd & SHORT_HAND_DATA) == SHORT_HAND_DATA) printf(" --ipp2p-data");
++ if ((info->cmd & IPP2P_KAZAA) == IPP2P_KAZAA) printf(" --kazaa");
++// if ((info->cmd & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA) printf(" --kazaa-data");
++// if ((info->cmd & IPP2P_DATA_GNU) == IPP2P_DATA_GNU) printf(" --gnu-data");
++ if ((info->cmd & IPP2P_GNU) == IPP2P_GNU) printf(" --gnu");
++ if ((info->cmd & IPP2P_EDK) == IPP2P_EDK) printf(" --edk");
++// if ((info->cmd & IPP2P_DATA_EDK) == IPP2P_DATA_EDK) printf(" --edk-data");
++// if ((info->cmd & IPP2P_DATA_DC) == IPP2P_DATA_DC) printf(" --dc-data");
++ if ((info->cmd & IPP2P_DC) == IPP2P_DC) printf(" --dc");
++ if ((info->cmd & IPP2P_BIT) == IPP2P_BIT) printf(" --bit");
++ if ((info->cmd & IPP2P_APPLE) == IPP2P_APPLE) printf(" --apple");
++ if ((info->cmd & IPP2P_SOUL) == IPP2P_SOUL) printf(" --soul");
++ if ((info->cmd & IPP2P_WINMX) == IPP2P_WINMX) printf(" --winmx");
++ if ((info->cmd & IPP2P_ARES) == IPP2P_ARES) printf(" --ares");
++ if ((info->cmd & IPP2P_MUTE) == IPP2P_MUTE) printf(" --mute");
++ if ((info->cmd & IPP2P_WASTE) == IPP2P_WASTE) printf(" --waste");
++ if ((info->cmd & IPP2P_XDCC) == IPP2P_XDCC) printf(" --xdcc");
++ if (info->debug != 0) printf(" --debug");
++ printf(" ");
++}
++
++
++
++static void
++save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
++{
++ struct ipt_p2p_info *info = (struct ipt_p2p_info *)match->data;
++
++ if ((info->cmd & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P) printf("--ipp2p ");
++// if ((info->cmd & SHORT_HAND_DATA) == SHORT_HAND_DATA) printf("--ipp2p-data ");
++ if ((info->cmd & IPP2P_KAZAA) == IPP2P_KAZAA) printf("--kazaa ");
++// if ((info->cmd & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA) printf("--kazaa-data ");
++// if ((info->cmd & IPP2P_DATA_GNU) == IPP2P_DATA_GNU) printf("--gnu-data ");
++ if ((info->cmd & IPP2P_GNU) == IPP2P_GNU) printf("--gnu ");
++ if ((info->cmd & IPP2P_EDK) == IPP2P_EDK) printf("--edk ");
++// if ((info->cmd & IPP2P_DATA_EDK) == IPP2P_DATA_EDK) printf("--edk-data ");
++// if ((info->cmd & IPP2P_DATA_DC) == IPP2P_DATA_DC) printf("--dc-data ");
++ if ((info->cmd & IPP2P_DC) == IPP2P_DC) printf("--dc ");
++ if ((info->cmd & IPP2P_BIT) == IPP2P_BIT) printf("--bit ");
++ if ((info->cmd & IPP2P_APPLE) == IPP2P_APPLE) printf("--apple ");
++ if ((info->cmd & IPP2P_SOUL) == IPP2P_SOUL) printf("--soul ");
++ if ((info->cmd & IPP2P_WINMX) == IPP2P_WINMX) printf("--winmx ");
++ if ((info->cmd & IPP2P_ARES) == IPP2P_ARES) printf("--ares ");
++ if ((info->cmd & IPP2P_MUTE) == IPP2P_MUTE) printf(" --mute");
++ if ((info->cmd & IPP2P_WASTE) == IPP2P_WASTE) printf(" --waste");
++ if ((info->cmd & IPP2P_XDCC) == IPP2P_XDCC) printf(" --xdcc");
++ if (info->debug != 0) printf("--debug ");
++}
++
++
++
++
++static
++struct iptables_match ipp2p=
++{
++ .next = NULL,
++ .name = "ipp2p",
++ .version = IPTABLES_VERSION,
++ .size = IPT_ALIGN(sizeof(struct ipt_p2p_info)),
++ .userspacesize = IPT_ALIGN(sizeof(struct ipt_p2p_info)),
++ .help = &help,
++ .init = &init,
++ .parse = &parse,
++ .final_check = &final_check,
++ .print = &print,
++ .save = &save,
++ .extra_opts = opts
++};
++
++
++
++void _init(void)
++{
++ register_match(&ipp2p);
++}
++
+diff -urN iptables.old/include/linux/netfilter_ipv4/ipt_ipp2p.h iptables.dev/include/linux/netfilter_ipv4/ipt_ipp2p.h
+--- iptables.old/include/linux/netfilter_ipv4/ipt_ipp2p.h 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/include/linux/netfilter_ipv4/ipt_ipp2p.h 2006-03-23 14:44:26.000000000 +0100
+@@ -0,0 +1,31 @@
++#ifndef __IPT_IPP2P_H
++#define __IPT_IPP2P_H
++#define IPP2P_VERSION "0.8.1_rc1"
++
++struct ipt_p2p_info {
++ int cmd;
++ int debug;
++};
++
++#endif //__IPT_IPP2P_H
++
++#define SHORT_HAND_IPP2P 1 /* --ipp2p switch*/
++//#define SHORT_HAND_DATA 4 /* --ipp2p-data switch*/
++#define SHORT_HAND_NONE 5 /* no short hand*/
++
++#define IPP2P_EDK (1 << 1)
++#define IPP2P_DATA_KAZAA (1 << 2)
++#define IPP2P_DATA_EDK (1 << 3)
++#define IPP2P_DATA_DC (1 << 4)
++#define IPP2P_DC (1 << 5)
++#define IPP2P_DATA_GNU (1 << 6)
++#define IPP2P_GNU (1 << 7)
++#define IPP2P_KAZAA (1 << 8)
++#define IPP2P_BIT (1 << 9)
++#define IPP2P_APPLE (1 << 10)
++#define IPP2P_SOUL (1 << 11)
++#define IPP2P_WINMX (1 << 12)
++#define IPP2P_ARES (1 << 13)
++#define IPP2P_MUTE (1 << 14)
++#define IPP2P_WASTE (1 << 15)
++#define IPP2P_XDCC (1 << 16)
diff --git a/package/iptables/patches/02-layer7-1.5nbd.patch b/package/iptables/patches/02-layer7-1.5nbd.patch
new file mode 100644
index 0000000000..95c62a860a
--- /dev/null
+++ b/package/iptables/patches/02-layer7-1.5nbd.patch
@@ -0,0 +1,416 @@
+diff -urN iptables.old/extensions/.layer7-test iptables.dev/extensions/.layer7-test
+--- iptables.old/extensions/.layer7-test 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/.layer7-test 2005-11-10 16:57:51.819381000 +0100
+@@ -0,0 +1,2 @@
++#! /bin/sh
++[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_layer7.h ] && echo layer7
+diff -urN iptables.old/extensions/ipt_layer7.h iptables.dev/extensions/ipt_layer7.h
+--- iptables.old/extensions/ipt_layer7.h 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/ipt_layer7.h 2005-11-10 17:46:32.933599750 +0100
+@@ -0,0 +1,27 @@
++/*
++ By Matthew Strait <quadong@users.sf.net>, Dec 2003.
++ 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
++*/
++
++#ifndef _IPT_LAYER7_H
++#define _IPT_LAYER7_H
++
++#define MAX_PATTERN_LEN 8192
++#define MAX_PROTOCOL_LEN 256
++
++typedef char *(*proc_ipt_search) (char *, char, char *);
++
++struct ipt_layer7_info {
++ char protocol[MAX_PROTOCOL_LEN];
++ char invert:1;
++ char pattern[MAX_PATTERN_LEN];
++ char pkt;
++};
++
++#endif /* _IPT_LAYER7_H */
+diff -urN iptables.old/extensions/libipt_layer7.c iptables.dev/extensions/libipt_layer7.c
+--- iptables.old/extensions/libipt_layer7.c 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/libipt_layer7.c 2005-11-10 17:47:01.399378750 +0100
+@@ -0,0 +1,358 @@
++/*
++ Shared library add-on to iptables to add layer 7 matching support.
++
++ By Matthew Strait <quadong@users.sf.net>, Oct 2003.
++
++ 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
++
++ Based on libipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>
++*/
++
++#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 <iptables.h>
++#include "ipt_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 v%s 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 the protocol defined in /etc/l7-protocols/name.pat\n"
++ "--l7pkt : Skip connection tracking and match individual packets\n",
++ IPTABLES_VERSION);
++ fputc('\n', stdout);
++}
++
++static struct option opts[] = {
++ { .name = "l7proto", .has_arg = 1, .flag = 0, .val = '1' },
++ { .name = "l7dir", .has_arg = 1, .flag = 0, .val = '2' },
++ { .name = "l7pkt", .has_arg = 0, .flag = 0, .val = '3' },
++ { .name = 0 }
++};
++
++/* reads filename, puts protocol info into layer7_protocol_info, number of protocols to numprotos */
++int parse_protocol_file(char * filename, const unsigned char * protoname, struct ipt_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)
++ {
++ if(strcmp(line, protoname))
++ exit_error(OTHER_PROBLEM,
++ "Protocol name (%s) doesn't match file name (%s). Bailing out\n",
++ protoname, filename);
++
++ if(strlen(line) >= MAX_PROTOCOL_LEN)
++ exit_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)
++ exit_error(PARAMETER_PROBLEM, "Pattern in %s too long!", filename);
++ strncpy(info->pattern, line, MAX_PATTERN_LEN);
++
++ datatype = done;
++ break;
++ }
++ else
++ exit_error(OTHER_PROBLEM, "Internal error");
++ }
++
++ if(datatype != done)
++ exit_error(OTHER_PROBLEM, "Failed to get all needed data from %s", filename);
++
++ if(line) free(line);
++ fclose(f);
++
++ return 1;
++
++/*
++ fprintf(stderr, "protocol: %s\npattern: %s\n\n",
++ info->protocol,
++ info->pattern);
++*/
++}
++
++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:
++ exit_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, rindex = 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[rindex] = tolower( hex2dec(s[sindex + 2])*16 +
++ hex2dec(s[sindex + 3] ) );
++ sindex += 3; /* 4 total */
++ }
++ else
++ result[rindex] = tolower(s[sindex]);
++
++ sindex++;
++ rindex++;
++ }
++ result[rindex] = '\0';
++
++ return result;
++}
++
++#define MAX_SUBDIRS 128
++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");
++ exit_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 unsigned char *s, struct ipt_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);
++
++ //fprintf(stderr, "Trying to find pattern in %s ... ", filename);
++
++ if(c > MAX_FN_LEN)
++ {
++ exit_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))
++ {
++ //fprintf(stderr, "found\n");
++ done = 1;
++ break;
++ }
++
++ //fprintf(stderr, "not found\n");
++
++ n++;
++ }
++
++ if(!done)
++ exit_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 struct ipt_entry *entry, unsigned int *nfcache,
++ struct ipt_entry_match **match)
++{
++ struct ipt_layer7_info *layer7info =
++ (struct ipt_layer7_info *)(*match)->data;
++
++ switch (c) {
++ case '1':
++ check_inverse(optarg, &invert, &optind, 0);
++ parse_layer7_protocol(argv[optind-1], layer7info);
++ if (invert)
++ layer7info->invert = 1;
++ *flags = 1;
++ break;
++
++ case '2':
++ /* not going to use this, but maybe we need to strip a ! anyway (?) */
++ check_inverse(optarg, &invert, &optind, 0);
++
++ if(strlen(argv[optind-1]) >= MAX_FN_LEN)
++ exit_error(PARAMETER_PROBLEM, "directory name too long\n");
++
++ strncpy(l7dir, argv[optind-1], MAX_FN_LEN);
++
++ *flags = 1;
++ break;
++ case '3':
++ layer7info->pkt = 1;
++ break;
++
++ default:
++ return 0;
++ }
++
++ return 1;
++}
++
++/* Final check; must have specified --pattern. */
++static void final_check(unsigned int flags)
++{
++ if (!flags)
++ exit_error(PARAMETER_PROBLEM,
++ "LAYER7 match: You must specify `--pattern'");
++}
++
++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 struct ipt_ip *ip,
++ const struct ipt_entry_match *match,
++ int numeric)
++{
++ printf("LAYER7 ");
++
++ print_protocol(((struct ipt_layer7_info *)match->data)->protocol,
++ ((struct ipt_layer7_info *)match->data)->invert, numeric);
++
++ if (((struct ipt_layer7_info *)match->data)->pkt)
++ printf("l7pkt ");
++}
++/* Saves the union ipt_matchinfo in parsable form to stdout. */
++static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
++{
++ const struct ipt_layer7_info *info =
++ (const struct ipt_layer7_info*) match->data;
++
++ printf("--l7proto %s%s ", (info->invert) ? "! ": "", info->protocol);
++}
++
++static struct iptables_match layer7 = {
++ .name = "layer7",
++ .version = IPTABLES_VERSION,
++ .size = IPT_ALIGN(sizeof(struct ipt_layer7_info)),
++ .userspacesize = IPT_ALIGN(sizeof(struct ipt_layer7_info)),
++ .help = &help,
++ .parse = &parse,
++ .final_check = &final_check,
++ .print = &print,
++ .save = &save,
++ .extra_opts = opts
++};
++
++void _init(void)
++{
++ register_match(&layer7);
++}
+diff -urN iptables.old/extensions/libipt_layer7.man iptables.dev/extensions/libipt_layer7.man
+--- iptables.old/extensions/libipt_layer7.man 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/libipt_layer7.man 2005-11-10 16:57:51.823381250 +0100
+@@ -0,0 +1,13 @@
++This module matches packets based on the application layer data of
++their connections. It uses regular expression matching to compare
++the application layer data to regular expressions found it the layer7
++configuration files. This is an experimental module which can be found at
++http://l7-filter.sf.net. It takes two options.
++.TP
++.BI "--l7proto " "\fIprotocol\fP"
++Match the specified protocol. The protocol name must match a file
++name in /etc/l7-protocols/
++.TP
++.BI "--l7dir " "\fIdirectory\fP"
++Use \fIdirectory\fP instead of /etc/l7-protocols/
++
diff --git a/package/iptables/patches/04-multiport_v1.patch b/package/iptables/patches/04-multiport_v1.patch
new file mode 100644
index 0000000000..90b5144c75
--- /dev/null
+++ b/package/iptables/patches/04-multiport_v1.patch
@@ -0,0 +1,221 @@
+diff -urN iptables.old/extensions/libipt_multiport.c iptables.dev/extensions/libipt_multiport.c
+--- iptables.old/extensions/libipt_multiport.c 2005-02-19 20:19:17.000000000 +0100
++++ iptables.dev/extensions/libipt_multiport.c 2006-02-04 05:46:12.154127750 +0100
+@@ -8,24 +8,6 @@
+ /* To ensure that iptables compiles with an old kernel */
+ #include "../include/linux/netfilter_ipv4/ipt_multiport.h"
+
+-/* Function which prints out usage message. */
+-static void
+-help(void)
+-{
+- printf(
+-"multiport v%s 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",
+-IPTABLES_VERSION);
+-}
+-
+ static void
+ help_v1(void)
+ {
+@@ -75,26 +57,6 @@
+ "invalid port/service `%s' specified", port);
+ }
+
+-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) exit_error(OTHER_PROBLEM, "strdup failed");
+-
+- for (cp=buffer, i=0; cp && i<IPT_MULTI_PORTS; cp=next,i++)
+- {
+- next=strchr(cp, ',');
+- if (next) *next++='\0';
+- ports[i] = parse_port(cp, proto);
+- }
+- if (cp) exit_error(PARAMETER_PROBLEM, "too many ports specified");
+- free(buffer);
+- return i;
+-}
+-
+ static void
+ parse_multi_ports_v1(const char *portstring,
+ struct ipt_multiport_v1 *multiinfo,
+@@ -160,58 +122,6 @@
+ "multiport only works with TCP or UDP");
+ }
+
+-/* 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 struct ipt_entry *entry,
+- unsigned int *nfcache,
+- struct ipt_entry_match **match)
+-{
+- const char *proto;
+- struct ipt_multiport *multiinfo
+- = (struct ipt_multiport *)(*match)->data;
+-
+- switch (c) {
+- case '1':
+- check_inverse(argv[optind-1], &invert, &optind, 0);
+- proto = check_proto(entry);
+- multiinfo->count = parse_multi_ports(argv[optind-1],
+- multiinfo->ports, proto);
+- multiinfo->flags = IPT_MULTIPORT_SOURCE;
+- break;
+-
+- case '2':
+- check_inverse(argv[optind-1], &invert, &optind, 0);
+- proto = check_proto(entry);
+- multiinfo->count = parse_multi_ports(argv[optind-1],
+- multiinfo->ports, proto);
+- multiinfo->flags = IPT_MULTIPORT_DESTINATION;
+- break;
+-
+- case '3':
+- check_inverse(argv[optind-1], &invert, &optind, 0);
+- proto = check_proto(entry);
+- multiinfo->count = parse_multi_ports(argv[optind-1],
+- multiinfo->ports, proto);
+- multiinfo->flags = IPT_MULTIPORT_EITHER;
+- break;
+-
+- default:
+- return 0;
+- }
+-
+- if (invert)
+- exit_error(PARAMETER_PROBLEM,
+- "multiport does not support invert");
+-
+- if (*flags)
+- exit_error(PARAMETER_PROBLEM,
+- "multiport can only have one option");
+- *flags = 1;
+- return 1;
+-}
+-
+ static int
+ parse_v1(int c, char **argv, int invert, unsigned int *flags,
+ const struct ipt_entry *entry,
+@@ -289,43 +199,6 @@
+ printf("%s", service);
+ }
+
+-/* Prints out the matchinfo. */
+-static void
+-print(const struct ipt_ip *ip,
+- const struct ipt_entry_match *match,
+- int numeric)
+-{
+- const struct ipt_multiport *multiinfo
+- = (const struct ipt_multiport *)match->data;
+- unsigned int i;
+-
+- printf("multiport ");
+-
+- switch (multiinfo->flags) {
+- case IPT_MULTIPORT_SOURCE:
+- printf("sports ");
+- break;
+-
+- case IPT_MULTIPORT_DESTINATION:
+- printf("dports ");
+- break;
+-
+- case IPT_MULTIPORT_EITHER:
+- printf("ports ");
+- break;
+-
+- default:
+- printf("ERROR ");
+- break;
+- }
+-
+- for (i=0; i < multiinfo->count; i++) {
+- printf("%s", i ? "," : "");
+- print_port(multiinfo->ports[i], ip->proto, numeric);
+- }
+- printf(" ");
+-}
+-
+ static void
+ print_v1(const struct ipt_ip *ip,
+ const struct ipt_entry_match *match,
+@@ -369,34 +242,6 @@
+ printf(" ");
+ }
+
+-/* Saves the union ipt_matchinfo in parsable form to stdout. */
+-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
+-{
+- const struct ipt_multiport *multiinfo
+- = (const struct ipt_multiport *)match->data;
+- unsigned int i;
+-
+- switch (multiinfo->flags) {
+- case IPT_MULTIPORT_SOURCE:
+- printf("--sports ");
+- break;
+-
+- case IPT_MULTIPORT_DESTINATION:
+- printf("--dports ");
+- break;
+-
+- case IPT_MULTIPORT_EITHER:
+- printf("--ports ");
+- break;
+- }
+-
+- for (i=0; i < multiinfo->count; i++) {
+- printf("%s", i ? "," : "");
+- print_port(multiinfo->ports[i], ip->proto, 1);
+- }
+- printf(" ");
+-}
+-
+ static void save_v1(const struct ipt_ip *ip,
+ const struct ipt_entry_match *match)
+ {
+@@ -432,19 +277,20 @@
+ printf(" ");
+ }
+
++
+ static struct iptables_match multiport = {
+ .next = NULL,
+ .name = "multiport",
+- .revision = 0,
+ .version = IPTABLES_VERSION,
+- .size = IPT_ALIGN(sizeof(struct ipt_multiport)),
+- .userspacesize = IPT_ALIGN(sizeof(struct ipt_multiport)),
+- .help = &help,
++ .revision = 0,
++ .size = IPT_ALIGN(sizeof(struct ipt_multiport_v1)),
++ .userspacesize = IPT_ALIGN(sizeof(struct ipt_multiport_v1)),
++ .help = &help_v1,
+ .init = &init,
+- .parse = &parse,
++ .parse = &parse_v1,
+ .final_check = &final_check,
+- .print = &print,
+- .save = &save,
++ .print = &print_v1,
++ .save = &save_v1,
+ .extra_opts = opts
+ };
+
diff --git a/package/iptables/patches/05-imq1.patch b/package/iptables/patches/05-imq1.patch
new file mode 100644
index 0000000000..4591890304
--- /dev/null
+++ b/package/iptables/patches/05-imq1.patch
@@ -0,0 +1,224 @@
+diff -urN iptables.old/extensions/.IMQ-test iptables.dev/extensions/.IMQ-test
+--- iptables.old/extensions/.IMQ-test 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/.IMQ-test 2005-10-09 01:00:36.358959750 +0200
+@@ -0,0 +1,3 @@
++#!/bin/sh
++# True if IMQ target patch is applied.
++[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_IMQ.c ] && echo IMQ
+diff -urN iptables.old/extensions/.IMQ-test6 iptables.dev/extensions/.IMQ-test6
+--- iptables.old/extensions/.IMQ-test6 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/.IMQ-test6 2005-10-09 01:00:36.358959750 +0200
+@@ -0,0 +1,3 @@
++#!/bin/sh
++# True if IMQ target patch is applied.
++[ -f $KERNEL_DIR/net/ipv6/netfilter/ip6t_IMQ.c ] && echo IMQ
+diff -urN iptables.old/extensions/libip6t_IMQ.c iptables.dev/extensions/libip6t_IMQ.c
+--- iptables.old/extensions/libip6t_IMQ.c 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/libip6t_IMQ.c 2005-10-09 01:00:36.358959750 +0200
+@@ -0,0 +1,101 @@
++/* Shared library add-on to iptables to add IMQ target support. */
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <getopt.h>
++
++#include <ip6tables.h>
++#include <linux/netfilter_ipv6/ip6_tables.h>
++#include <linux/netfilter_ipv6/ip6t_IMQ.h>
++
++/* Function which prints out usage message. */
++static void
++help(void)
++{
++ printf(
++"IMQ target v%s options:\n"
++" --todev <N> enqueue to imq<N>, defaults to 0\n",
++IPTABLES_VERSION);
++}
++
++static struct option opts[] = {
++ { "todev", 1, 0, '1' },
++ { 0 }
++};
++
++/* Initialize the target. */
++static void
++init(struct ip6t_entry_target *t, unsigned int *nfcache)
++{
++ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)t->data;
++
++ mr->todev = 0;
++ *nfcache |= NFC_UNKNOWN;
++}
++
++/* 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 struct ip6t_entry *entry,
++ struct ip6t_entry_target **target)
++{
++ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)(*target)->data;
++
++ switch(c) {
++ case '1':
++ if (check_inverse(optarg, &invert, NULL, 0))
++ exit_error(PARAMETER_PROBLEM,
++ "Unexpected `!' after --todev");
++ mr->todev=atoi(optarg);
++ break;
++ default:
++ return 0;
++ }
++ return 1;
++}
++
++static void
++final_check(unsigned int flags)
++{
++}
++
++/* Prints out the targinfo. */
++static void
++print(const struct ip6t_ip6 *ip,
++ const struct ip6t_entry_target *target,
++ int numeric)
++{
++ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)target->data;
++
++ printf("IMQ: todev %u ", mr->todev);
++}
++
++/* Saves the union ipt_targinfo in parsable form to stdout. */
++static void
++save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
++{
++ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)target->data;
++
++ printf("--todev %u", mr->todev);
++}
++
++static struct ip6tables_target imq = {
++ .next = NULL,
++ .name = "IMQ",
++ .version = IPTABLES_VERSION,
++ .size = IP6T_ALIGN(sizeof(struct ip6t_imq_info)),
++ .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_imq_info)),
++ .help = &help,
++ .init = &init,
++ .parse = &parse,
++ .final_check = &final_check,
++ .print = &print,
++ .save = &save,
++ .extra_opts = opts
++};
++
++void _init(void)
++{
++ register_target6(&imq);
++}
+diff -urN iptables.old/extensions/libipt_IMQ.c iptables.dev/extensions/libipt_IMQ.c
+--- iptables.old/extensions/libipt_IMQ.c 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/libipt_IMQ.c 2005-10-09 01:00:36.358959750 +0200
+@@ -0,0 +1,101 @@
++/* Shared library add-on to iptables to add IMQ target support. */
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <getopt.h>
++
++#include <iptables.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_IMQ.h>
++
++/* Function which prints out usage message. */
++static void
++help(void)
++{
++ printf(
++"IMQ target v%s options:\n"
++" --todev <N> enqueue to imq<N>, defaults to 0\n",
++IPTABLES_VERSION);
++}
++
++static struct option opts[] = {
++ { "todev", 1, 0, '1' },
++ { 0 }
++};
++
++/* Initialize the target. */
++static void
++init(struct ipt_entry_target *t, unsigned int *nfcache)
++{
++ struct ipt_imq_info *mr = (struct ipt_imq_info*)t->data;
++
++ mr->todev = 0;
++ *nfcache |= NFC_UNKNOWN;
++}
++
++/* 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 struct ipt_entry *entry,
++ struct ipt_entry_target **target)
++{
++ struct ipt_imq_info *mr = (struct ipt_imq_info*)(*target)->data;
++
++ switch(c) {
++ case '1':
++ if (check_inverse(optarg, &invert, NULL, 0))
++ exit_error(PARAMETER_PROBLEM,
++ "Unexpected `!' after --todev");
++ mr->todev=atoi(optarg);
++ break;
++ default:
++ return 0;
++ }
++ return 1;
++}
++
++static void
++final_check(unsigned int flags)
++{
++}
++
++/* Prints out the targinfo. */
++static void
++print(const struct ipt_ip *ip,
++ const struct ipt_entry_target *target,
++ int numeric)
++{
++ struct ipt_imq_info *mr = (struct ipt_imq_info*)target->data;
++
++ printf("IMQ: todev %u ", mr->todev);
++}
++
++/* Saves the union ipt_targinfo in parsable form to stdout. */
++static void
++save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
++{
++ struct ipt_imq_info *mr = (struct ipt_imq_info*)target->data;
++
++ printf("--todev %u", mr->todev);
++}
++
++static struct iptables_target imq = {
++ .next = NULL,
++ .name = "IMQ",
++ .version = IPTABLES_VERSION,
++ .size = IPT_ALIGN(sizeof(struct ipt_imq_info)),
++ .userspacesize = IPT_ALIGN(sizeof(struct ipt_imq_info)),
++ .help = &help,
++ .init = &init,
++ .parse = &parse,
++ .final_check = &final_check,
++ .print = &print,
++ .save = &save,
++ .extra_opts = opts
++};
++
++void _init(void)
++{
++ register_target(&imq);
++}
diff --git a/package/isakmpd/Makefile b/package/isakmpd/Makefile
new file mode 100644
index 0000000000..a4e7ff7b03
--- /dev/null
+++ b/package/isakmpd/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 4619 2006-08-22 09:50:02Z florian $
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=isakmpd
+PKG_VERSION:=20041012
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).orig.tar.gz
+PKG_SOURCE_URL:=http://ftp.debian.org/debian/pool/main/i/isakmpd/
+PKG_MD5SUM:=e6d25a9e232fb186e1a48dc06453bd57
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION).orig
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+define Package/isakmpd
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=@BROKEN @LINUX_2_6 +libopenssl +keynote +libgmp
+ TITLE:=IPsec management tools
+ URL:=http://isakmpd.sourceforge.net/
+endef
+
+define Build/Compile
+ $(call Build/Compile/Default,LINUX_DIR="$(LINUX_DIR)" \
+ STAGING_DIR="$(STAGING_DIR)" \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ )
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ STAGING_DIR="$(STAGING_DIR)" \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ INSTALL="install -c" \
+ install-bin
+endef
+
+define Package/isakmpd/install
+ install -d -m0755 $(1)/usr/sbin
+ $(CP) $(PKG_INSTALL_DIR)/* $(1)/
+endef
+
+$(eval $(call BuildPackage,isakmpd))
diff --git a/package/isakmpd/patches/010-debian_3.patch b/package/isakmpd/patches/010-debian_3.patch
new file mode 100644
index 0000000000..551ae1ffcd
--- /dev/null
+++ b/package/isakmpd/patches/010-debian_3.patch
@@ -0,0 +1,1706 @@
+--- isakmpd-20041012.orig/dpd.c
++++ isakmpd-20041012/dpd.c
+@@ -26,6 +26,7 @@
+
+ #include <sys/types.h>
+ #include <stdlib.h>
++#include <memory.h>
+
+ #include "sysdep.h"
+
+@@ -174,6 +175,7 @@
+ }
+ break;
+ default:
++ ;
+ }
+
+ /* Mark handled. */
+@@ -223,6 +225,7 @@
+ dpd_check_event, sa, &tv);
+ break;
+ default:
++ ;
+ }
+ if (!sa->dpd_event)
+ log_print("dpd_timer_reset: timer_add_event failed");
+--- isakmpd-20041012.orig/ipsec.c
++++ isakmpd-20041012/ipsec.c
+@@ -1020,6 +1020,52 @@
+ }
+ }
+
++/*
++ * deal with a NOTIFY of INVALID_SPI
++ */
++static void
++ipsec_invalid_spi (struct message *msg, struct payload *p)
++{
++ struct sockaddr *dst;
++ int invspisz, off;
++ u_int32_t spi;
++ u_int16_t totsiz;
++ u_int8_t spisz;
++
++ /* Any notification that make us do something should be protected */
++ if(!TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_HASH]))
++ {
++ LOG_DBG ((LOG_SA, 40,
++ "ipsec_invalid_spi: missing HASH payload in INVALID_SPI"
++ " notification"));
++ return;
++ }
++
++ /*
++ * get the invalid spi out of the variable sized notification data
++ * field, which is after the variable sized SPI field [which specifies
++ * the receiving entity's phase-1 SPI, not the invalid spi]
++ */
++ totsiz = GET_ISAKMP_GEN_LENGTH (p->p);
++ spisz = GET_ISAKMP_NOTIFY_SPI_SZ (p->p);
++ off = ISAKMP_NOTIFY_SPI_OFF + spisz;
++ invspisz = totsiz - off;
++
++ if (invspisz != sizeof spi)
++ {
++ LOG_DBG ((LOG_SA, 40,
++ "ipsec_invalid_spi: SPI size %d in INVALID_SPI "
++ "payload unsupported", spisz));
++ return;
++ }
++ memcpy (&spi, p->p + off, sizeof spi);
++
++ msg->transport->vtbl->get_dst (msg->transport, &dst);
++
++ /* delete matching SPI's from this peer */
++ ipsec_delete_spi_list (dst, 0, (u_int8_t *)&spi, 1, "INVALID_SPI");
++}
++
+ static int
+ ipsec_responder(struct message *msg)
+ {
+@@ -1205,7 +1251,9 @@
+ return dv != IPSEC_ENCAP_TUNNEL
+ && dv != IPSEC_ENCAP_TRANSPORT
+ && dv != IPSEC_ENCAP_UDP_ENCAP_TUNNEL
+- && dv != IPSEC_ENCAP_UDP_ENCAP_TRANSPORT;
++ && dv != IPSEC_ENCAP_UDP_ENCAP_TRANSPORT
++ && dv != IPSEC_ENCAP_UDP_ENCAP_TUNNEL_DRAFT
++ && dv != IPSEC_ENCAP_UDP_ENCAP_TRANSPORT_DRAFT;
+ #else
+ return dv < IPSEC_ENCAP_TUNNEL
+ || dv > IPSEC_ENCAP_TRANSPORT;
+@@ -1837,7 +1885,7 @@
+ ipsec_get_id(char *section, int *id, struct sockaddr **addr,
+ struct sockaddr **mask, u_int8_t *tproto, u_int16_t *port)
+ {
+- char *type, *address, *netmask;
++ char *type, *address, *netmask;
+
+ type = conf_get_str(section, "ID-type");
+ if (!type) {
+--- isakmpd-20041012.orig/GNUmakefile
++++ isakmpd-20041012/GNUmakefile
+@@ -40,12 +40,12 @@
+ # integrated, freebsd/netbsd means FreeBSD/NetBSD with KAME IPsec.
+ # darwin means MacOS X 10.2 and later with KAME IPsec. linux means Linux-2.5
+ # and later with native IPSec support.
+-OS= openbsd
++#OS= openbsd
+ #OS= netbsd
+ #OS= freebsd
+ #OS= freeswan
+ #OS= darwin
+-#OS= linux
++OS= linux
+
+ .CURDIR:= $(shell pwd)
+ VPATH= ${.CURDIR}/sysdep/${OS}
+@@ -55,9 +55,10 @@
+ ifndef BINDIR
+ BINDIR= /sbin
+ endif
+-ifndef LDSTATIC
+-LDSTATIC= -static
+-endif
++
++#ifndef LDSTATIC
++#LDSTATIC= -static
++#endif
+
+ SRCS= app.c attribute.c cert.c connection.c \
+ constants.c conf.c cookie.c crypto.c dh.c doi.c exchange.c \
+@@ -131,11 +132,14 @@
+ ifneq ($(findstring install,$(MAKECMDGOALS)),install)
+ # Skip 'regress' until the regress/ structure has gmake makefiles for it.
+ #SUBDIR:= regress
+-SUBDIR:=
++#SUBDIR:= apps/certpatch
+ mksubdirs:
+ $(foreach DIR, ${SUBDIR}, \
+- cd ${DIR}; ${MAKE} ${MAKEFLAGS} CFLAGS="${CFLAGS}" \
+- MKDEP="${MKDEP}" ${MAKECMDGOALS})
++ cd ${.CURDIR}/${DIR}; ${MAKE} ${MAKECMDGOALS};)
++
++# $(foreach DIR, ${SUBDIR}, \
++# cd ${DIR}; ${MAKE} CFLAGS="${CFLAGS}" \
++# MKDEP="${MKDEP}" ${MAKECMDGOALS})
+ else
+ mksubdirs:
+ endif
+@@ -173,7 +177,7 @@
+ endif
+
+ SRCS+= ${IPSEC_SRCS} ${X509} ${POLICY} ${EC} ${AGGRESSIVE} ${DNSSEC} \
+- $(ISAKMP_CFG)
++ $(ISAKMP_CFG) ${DPD} ${NAT_TRAVERSAL}
+ CFLAGS+= ${IPSEC_CFLAGS}
+ LDADD+= ${DESLIB}
+ DPADD+= ${DESLIBDEP}
+--- isakmpd-20041012.orig/exchange.h
++++ isakmpd-20041012/exchange.h
+@@ -221,6 +221,8 @@
+ #define EXCHANGE_FLAG_NAT_T_ENABLE 0x10 /* We are doing NAT-T. */
+ #define EXCHANGE_FLAG_NAT_T_KEEPALIVE 0x20 /* We are the NAT:ed peer. */
+ #define EXCHANGE_FLAG_DPD_CAP_PEER 0x40 /* Peer is DPD capable. */
++#define EXCHANGE_FLAG_NAT_T_RFC 0x0080 /* Peer does RFC NAT-T. */
++#define EXCHANGE_FLAG_NAT_T_DRAFT 0x0100 /* Peer does draft NAT-T.*/
+
+ extern int exchange_add_certs(struct message *);
+ extern void exchange_finalize(struct message *);
+--- isakmpd-20041012.orig/log.c
++++ isakmpd-20041012/log.c
+@@ -79,7 +79,6 @@
+
+ struct packhdr {
+ struct pcap_pkthdr pcap;/* pcap file packet header */
+- u_int32_t sa_family; /* address family */
+ union {
+ struct ip ip4; /* IPv4 header (w/o options) */
+ struct ip6_hdr ip6; /* IPv6 header */
+@@ -97,7 +96,7 @@
+ static u_int8_t *packet_buf = NULL;
+
+ static int udp_cksum(struct packhdr *, const struct udphdr *,
+- u_int16_t *);
++ u_int16_t *, int);
+ static u_int16_t in_cksum(const u_int16_t *, int);
+ #endif /* USE_DEBUG */
+
+@@ -539,11 +538,9 @@
+ udp.uh_ulen = htons(datalen);
+
+ /* ip */
+- hdr.sa_family = htonl(src->sa_family);
+ switch (src->sa_family) {
+ default:
+ /* Assume IPv4. XXX Can 'default' ever happen here? */
+- hdr.sa_family = htonl(AF_INET);
+ hdr.ip.ip4.ip_src.s_addr = 0x02020202;
+ hdr.ip.ip4.ip_dst.s_addr = 0x01010101;
+ /* The rest of the setup is common to AF_INET. */
+@@ -584,9 +581,7 @@
+ }
+
+ /* Calculate UDP checksum. */
+- udp.uh_sum = udp_cksum(&hdr, &udp, (u_int16_t *) packet_buf);
+- hdrlen += sizeof hdr.sa_family;
+-
++ udp.uh_sum = udp_cksum(&hdr, &udp, (u_int16_t *) packet_buf, src->sa_family);
+ /* pcap file packet header */
+ gettimeofday(&tv, 0);
+ hdr.pcap.ts.tv_sec = tv.tv_sec;
+@@ -610,7 +605,7 @@
+
+ /* Copied from tcpdump/print-udp.c, mostly rewritten. */
+ static int
+-udp_cksum(struct packhdr *hdr, const struct udphdr *u, u_int16_t *d)
++udp_cksum(struct packhdr *hdr, const struct udphdr *u, u_int16_t *d, int af)
+ {
+ struct ip *ip4;
+ struct ip6_hdr *ip6;
+@@ -639,7 +634,7 @@
+
+ /* Setup pseudoheader. */
+ memset(phu.pa, 0, sizeof phu);
+- switch (ntohl(hdr->sa_family)) {
++ switch (af) {
+ case AF_INET:
+ ip4 = &hdr->ip.ip4;
+ memcpy(&phu.ip4p.src, &ip4->ip_src, sizeof(struct in_addr));
+@@ -664,7 +659,7 @@
+
+ /* IPv6 wants a 0xFFFF checksum "on error", not 0x0. */
+ if (tlen < 0)
+- return (ntohl(hdr->sa_family) == AF_INET ? 0 : 0xFFFF);
++ return (af == AF_INET ? 0 : 0xFFFF);
+
+ sum = 0;
+ for (i = 0; i < hdrlen; i += 2)
+--- isakmpd-20041012.orig/nat_traversal.c
++++ isakmpd-20041012/nat_traversal.c
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: nat_traversal.c,v 1.7 2004/08/08 19:11:06 deraadt Exp $ */
++/* $OpenBSD: nat_traversal.c,v 1.17 2006/06/14 14:03:33 hshoexer Exp $ */
+
+ /*
+ * Copyright (c) 2004 Håkan Olsson. All rights reserved.
+@@ -48,40 +48,40 @@
+ #include "util.h"
+ #include "virtual.h"
+
++int disable_nat_t = 0;
++
+ /*
+- * XXX According to draft-ietf-ipsec-nat-t-ike-07.txt, the NAT-T
+- * capability of the other peer is determined by a particular vendor ID
+- * sent as the first message. This vendor ID string is supposed to be a
+- * MD5 hash of "RFC XXXX", where XXXX is the future RFC number.
++ * NAT-T capability of the other peer is determined by a particular vendor
++ * ID sent in the first message. This vendor ID string is supposed to be a
++ * MD5 hash of "RFC 3947".
+ *
+ * These seem to be the "well" known variants of this string in use by
+ * products today.
+ */
+-static const char *isakmp_nat_t_cap_text[] = {
+- "draft-ietf-ipsec-nat-t-ike-00", /* V1 (XXX: may be obsolete) */
+- "draft-ietf-ipsec-nat-t-ike-02\n", /* V2 */
+- "draft-ietf-ipsec-nat-t-ike-03", /* V3 */
+-#ifdef notyet
+- "RFC XXXX",
+-#endif
++
++static struct nat_t_cap isakmp_nat_t_cap[] = {
++ { VID_DRAFT_V2_N, EXCHANGE_FLAG_NAT_T_DRAFT,
++ "draft-ietf-ipsec-nat-t-ike-02\n", NULL, 0 },
++ { VID_DRAFT_V3, EXCHANGE_FLAG_NAT_T_DRAFT,
++ "draft-ietf-ipsec-nat-t-ike-03", NULL, 0 },
++ { VID_RFC3947, EXCHANGE_FLAG_NAT_T_RFC,
++ "RFC 3947", NULL, 0 },
+ };
+
++#define NUMNATTCAP (sizeof isakmp_nat_t_cap / sizeof isakmp_nat_t_cap[0])
++
+ /* In seconds. Recommended in draft-ietf-ipsec-udp-encaps-09. */
+ #define NAT_T_KEEPALIVE_INTERVAL 20
+
+-/* The MD5 hashes of the above strings is put in this array. */
+-static char **nat_t_hashes;
+-static size_t nat_t_hashsize;
+-
+ static int nat_t_setup_hashes(void);
+-static int nat_t_add_vendor_payload(struct message *, char *);
++static int nat_t_add_vendor_payload(struct message *, struct nat_t_cap *);
+ static int nat_t_add_nat_d(struct message *, struct sockaddr *);
+ static int nat_t_match_nat_d_payload(struct message *, struct sockaddr *);
+
+ void
+ nat_t_init(void)
+ {
+- nat_t_hashes = (char **)NULL;
++ nat_t_setup_hashes();
+ }
+
+ /* Generate the NAT-T capability marker hashes. Executed only once. */
+@@ -89,7 +89,7 @@
+ nat_t_setup_hashes(void)
+ {
+ struct hash *hash;
+- int n = sizeof isakmp_nat_t_cap_text / sizeof isakmp_nat_t_cap_text[0];
++ int n = NUMNATTCAP;
+ int i;
+
+ /* The draft says to use MD5. */
+@@ -100,56 +100,49 @@
+ "could not find MD5 hash structure!");
+ return -1;
+ }
+- nat_t_hashsize = hash->hashsize;
+
+- /* Allocate one more than is necessary, i.e NULL terminated. */
+- nat_t_hashes = (char **)calloc((size_t)(n + 1), sizeof(char *));
+- if (!nat_t_hashes) {
+- log_error("nat_t_setup_hashes: calloc (%lu,%lu) failed",
+- (unsigned long)n, (unsigned long)sizeof(char *));
+- return -1;
+- }
+-
+- /* Populate with hashes. */
++ /* Populate isakmp_nat_t_cap with hashes. */
+ for (i = 0; i < n; i++) {
+- nat_t_hashes[i] = (char *)malloc(nat_t_hashsize);
+- if (!nat_t_hashes[i]) {
++ isakmp_nat_t_cap[i].hashsize = hash->hashsize;
++ isakmp_nat_t_cap[i].hash = (char *)malloc(hash->hashsize);
++ if (!isakmp_nat_t_cap[i].hash) {
+ log_error("nat_t_setup_hashes: malloc (%lu) failed",
+- (unsigned long)nat_t_hashsize);
++ (unsigned long)hash->hashsize);
+ goto errout;
+ }
+
+ hash->Init(hash->ctx);
+ hash->Update(hash->ctx,
+- (unsigned char *)isakmp_nat_t_cap_text[i],
+- strlen(isakmp_nat_t_cap_text[i]));
+- hash->Final(nat_t_hashes[i], hash->ctx);
++ (unsigned char *)isakmp_nat_t_cap[i].text,
++ strlen(isakmp_nat_t_cap[i].text));
++ hash->Final(isakmp_nat_t_cap[i].hash, hash->ctx);
+
+ LOG_DBG((LOG_EXCHANGE, 50, "nat_t_setup_hashes: "
+- "MD5(\"%s\") (%lu bytes)", isakmp_nat_t_cap_text[i],
+- (unsigned long)nat_t_hashsize));
++ "MD5(\"%s\") (%lu bytes)", isakmp_nat_t_cap[i].text,
++ (unsigned long)hash->hashsize));
+ LOG_DBG_BUF((LOG_EXCHANGE, 50, "nat_t_setup_hashes",
+- nat_t_hashes[i], nat_t_hashsize));
++ isakmp_nat_t_cap[i].hash, hash->hashsize));
+ }
+
+ return 0;
+
+- errout:
++errout:
+ for (i = 0; i < n; i++)
+- if (nat_t_hashes[i])
+- free(nat_t_hashes[i]);
+- free(nat_t_hashes);
+- nat_t_hashes = NULL;
++ if (isakmp_nat_t_cap[i].hash)
++ free(isakmp_nat_t_cap[i].hash);
+ return -1;
+ }
+
+ /* Add one NAT-T VENDOR payload. */
+ static int
+-nat_t_add_vendor_payload(struct message *msg, char *hash)
++nat_t_add_vendor_payload(struct message *msg, struct nat_t_cap *cap)
+ {
+- size_t buflen = nat_t_hashsize + ISAKMP_GEN_SZ;
++ size_t buflen = cap->hashsize + ISAKMP_GEN_SZ;
+ u_int8_t *buf;
+
++ if (disable_nat_t)
++ return 0;
++
+ buf = malloc(buflen);
+ if (!buf) {
+ log_error("nat_t_add_vendor_payload: malloc (%lu) failed",
+@@ -158,12 +151,11 @@
+ }
+
+ SET_ISAKMP_GEN_LENGTH(buf, buflen);
+- memcpy(buf + ISAKMP_VENDOR_ID_OFF, hash, nat_t_hashsize);
++ memcpy(buf + ISAKMP_VENDOR_ID_OFF, cap->hash, cap->hashsize);
+ if (message_add_payload(msg, ISAKMP_PAYLOAD_VENDOR, buf, buflen, 1)) {
+ free(buf);
+ return -1;
+ }
+-
+ return 0;
+ }
+
+@@ -171,16 +163,14 @@
+ int
+ nat_t_add_vendor_payloads(struct message *msg)
+ {
+- int i = 0;
++ int i;
+
+- if (!nat_t_hashes)
+- if (nat_t_setup_hashes())
+- return 0; /* XXX should this be an error? */
++ if (disable_nat_t)
++ return 0;
+
+- while (nat_t_hashes[i])
+- if (nat_t_add_vendor_payload(msg, nat_t_hashes[i++]))
++ for (i = 0; i < NUMNATTCAP; i++)
++ if (nat_t_add_vendor_payload(msg, &isakmp_nat_t_cap[i]))
+ return -1;
+-
+ return 0;
+ }
+
+@@ -192,36 +182,31 @@
+ {
+ u_int8_t *pbuf = p->p;
+ size_t vlen;
+- int i = 0;
++ int i;
+
+- /* Already checked? */
+- if (p->flags & PL_MARK ||
+- msg->exchange->flags & EXCHANGE_FLAG_NAT_T_CAP_PEER)
++ if (disable_nat_t)
+ return;
+
+- if (!nat_t_hashes)
+- if (nat_t_setup_hashes())
+- return;
+-
+ vlen = GET_ISAKMP_GEN_LENGTH(pbuf) - ISAKMP_GEN_SZ;
+- if (vlen != nat_t_hashsize) {
+- LOG_DBG((LOG_EXCHANGE, 50, "nat_t_check_vendor_payload: "
+- "bad size %lu != %lu", (unsigned long)vlen,
+- (unsigned long)nat_t_hashsize));
+- return;
+- }
+
+- while (nat_t_hashes[i])
+- if (memcmp(nat_t_hashes[i++], pbuf + ISAKMP_GEN_SZ,
++ for (i = 0; i < NUMNATTCAP; i++) {
++ if (vlen != isakmp_nat_t_cap[i].hashsize) {
++ LOG_DBG((LOG_EXCHANGE, 50, "nat_t_check_vendor_payload: "
++ "bad size %lu != %lu", (unsigned long)vlen,
++ (unsigned long)isakmp_nat_t_cap[i].hashsize));
++ continue;
++ }
++ if (memcmp(isakmp_nat_t_cap[i].hash, pbuf + ISAKMP_GEN_SZ,
+ vlen) == 0) {
+ /* This peer is NAT-T capable. */
+ msg->exchange->flags |= EXCHANGE_FLAG_NAT_T_CAP_PEER;
++ msg->exchange->flags |= isakmp_nat_t_cap[i].flags;
+ LOG_DBG((LOG_EXCHANGE, 10,
+ "nat_t_check_vendor_payload: "
+ "NAT-T capable peer detected"));
+ p->flags |= PL_MARK;
+- return;
+ }
++ }
+
+ return;
+ }
+@@ -233,10 +218,8 @@
+ {
+ struct ipsec_exch *ie = (struct ipsec_exch *)msg->exchange->data;
+ struct hash *hash;
+- struct prf *prf;
+ u_int8_t *res;
+ in_port_t port;
+- int prf_type = PRF_HMAC; /* XXX */
+
+ hash = hash_get(ie->hash->type);
+ if (hash == NULL) {
+@@ -244,31 +227,25 @@
+ return NULL;
+ }
+
+- prf = prf_alloc(prf_type, hash->type, msg->exchange->cookies,
+- ISAKMP_HDR_COOKIES_LEN);
+- if(!prf) {
+- log_print("nat_t_generate_nat_d_hash: prf_alloc failed");
+- return NULL;
+- }
++ *hashlen = hash->hashsize;
+
+- *hashlen = prf->blocksize;
+ res = (u_int8_t *)malloc((unsigned long)*hashlen);
+ if (!res) {
+ log_print("nat_t_generate_nat_d_hash: malloc (%lu) failed",
+ (unsigned long)*hashlen);
+- prf_free(prf);
+ *hashlen = 0;
+ return NULL;
+ }
+
+ port = sockaddr_port(sa);
+- memset(res, 0, *hashlen);
+-
+- prf->Update(prf->prfctx, sockaddr_addrdata(sa), sockaddr_addrlen(sa));
+- prf->Update(prf->prfctx, (unsigned char *)&port, sizeof port);
+- prf->Final(res, prf->prfctx);
+- prf_free (prf);
++ bzero(res, *hashlen);
+
++ hash->Init(hash->ctx);
++ hash->Update(hash->ctx, msg->exchange->cookies,
++ sizeof msg->exchange->cookies);
++ hash->Update(hash->ctx, sockaddr_addrdata(sa), sockaddr_addrlen(sa));
++ hash->Update(hash->ctx, (unsigned char *)&port, sizeof port);
++ hash->Final(res, hash->ctx);
+ return res;
+ }
+
+@@ -276,6 +253,7 @@
+ static int
+ nat_t_add_nat_d(struct message *msg, struct sockaddr *sa)
+ {
++ int ret;
+ u_int8_t *hbuf, *buf;
+ size_t hbuflen, buflen;
+
+@@ -298,11 +276,19 @@
+ memcpy(buf + ISAKMP_NAT_D_DATA_OFF, hbuf, hbuflen);
+ free(hbuf);
+
+- if (message_add_payload(msg, ISAKMP_PAYLOAD_NAT_D, buf, buflen, 1)) {
++ if (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_RFC)
++ ret = message_add_payload(msg, ISAKMP_PAYLOAD_NAT_D, buf,
++ buflen, 1);
++ else if (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_DRAFT)
++ ret = message_add_payload(msg, ISAKMP_PAYLOAD_NAT_D_DRAFT,
++ buf, buflen, 1);
++ else
++ ret = -1;
++
++ if (ret) {
+ free(buf);
+ return -1;
+ }
+-
+ return 0;
+ }
+
+@@ -312,14 +298,14 @@
+ {
+ struct sockaddr *sa;
+
+- msg->transport->vtbl->get_src(msg->transport, &sa);
++ /* Remote address first. */
++ msg->transport->vtbl->get_dst(msg->transport, &sa);
+ if (nat_t_add_nat_d(msg, sa))
+ return -1;
+
+- msg->transport->vtbl->get_dst(msg->transport, &sa);
++ msg->transport->vtbl->get_src(msg->transport, &sa);
+ if (nat_t_add_nat_d(msg, sa))
+ return -1;
+-
+ return 0;
+ }
+
+@@ -336,8 +322,8 @@
+ * If there are no NAT-D payloads in the message, return "found"
+ * as this will avoid NAT-T (see nat_t_exchange_check_nat_d()).
+ */
+- p = payload_first(msg, ISAKMP_PAYLOAD_NAT_D);
+- if (!p)
++ if ((p = payload_first(msg, ISAKMP_PAYLOAD_NAT_D_DRAFT)) == NULL &&
++ (p = payload_first(msg, ISAKMP_PAYLOAD_NAT_D)) == NULL)
+ return 1;
+
+ hbuf = nat_t_generate_nat_d_hash(msg, sa, &hbuflen);
+--- isakmpd-20041012.orig/udp_encap.c
++++ isakmpd-20041012/udp_encap.c
+@@ -61,6 +61,11 @@
+
+ #define UDP_SIZE 65536
+
++#if defined(USE_NAT_TRAVERSAL) && defined (LINUX_IPSEC)
++#include <linux/socket.h>
++#include <linux/udp.h>
++#endif
++
+ /* If a system doesn't have SO_REUSEPORT, SO_REUSEADDR will have to do. */
+ #ifndef SO_REUSEPORT
+ #define SO_REUSEPORT SO_REUSEADDR
+@@ -134,6 +139,18 @@
+ if (sysdep_cleartext(s, laddr->sa_family) == -1)
+ goto err;
+
++#if defined(USE_NAT_TRAVERSAL) && defined (LINUX_IPSEC)
++ {
++#ifndef SOL_UDP
++#define SOL_UDP 17
++#endif
++ int option = UDP_ENCAP_ESPINUDP;
++ if(setsockopt(s, SOL_UDP, UDP_ENCAP, &option,
++ sizeof (option)) < 0)
++ goto err;
++ }
++#endif
++
+ /* Wildcard address ? */
+ switch (laddr->sa_family) {
+ case AF_INET:
+--- isakmpd-20041012.orig/apps/Makefile
++++ isakmpd-20041012/apps/Makefile
+@@ -31,4 +31,4 @@
+
+ SUBDIR= certpatch
+
+-.include <bsd.subdir.mk>
++#.include <bsd.subdir.mk>
+--- isakmpd-20041012.orig/apps/certpatch/GNUmakefile
++++ isakmpd-20041012/apps/certpatch/GNUmakefile
+@@ -0,0 +1,55 @@
++# $OpenBSD: Makefile,v 1.7 2003/06/03 14:35:00 ho Exp $
++# $EOM: Makefile,v 1.6 2000/03/28 21:22:06 ho Exp $
++
++#
++# Copyright (c) 1999 Niels Provos. All rights reserved.
++# Copyright (c) 2001 Niklas Hallqvist. All rights reserved.
++#
++# Redistribution and use in source and binary forms, with or without
++# modification, are permitted provided that the following conditions
++# are met:
++# 1. Redistributions of source code must retain the above copyright
++# notice, this list of conditions and the following disclaimer.
++# 2. Redistributions in binary form must reproduce the above copyright
++# notice, this list of conditions and the following disclaimer in the
++# documentation and/or other materials provided with the distribution.
++#
++# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 code was written under funding by Ericsson Radio Systems.
++#
++
++PROG= certpatch
++SRCS= certpatch.c
++BINDIR?= /usr/sbin
++TOPSRC= ${.CURDIR}../..
++TOPOBJ!= cd ${TOPSRC}; printf "all:\n\t@pwd\n" |${MAKE} -f-
++OS= linux
++FEATURES!= awk '/^FEATURES=/ { print $$0 }' ${.CURDIR}/../../Makefile | sed 's/FEATURES=.//'
++.PATH: ${TOPSRC} ${TOPSRC}/sysdep/${OS} ${TOPOBJ}
++CFLAGS+= -I${TOPSRC} -I${TOPSRC}/sysdep/${OS} -I${TOPOBJ} -Wall
++LDFLAGS+= -lcrypto -lssl -lgmp
++MAN= certpatch.8
++
++CFLAGS+= -DMP_FLAVOUR=MP_FLAVOUR_GMP
++LDADD+= -lgmp
++DPADD+= ${LIBGMP}
++
++# Override LIBSYSDEPDIR definition from Makefile.sysdep
++LIBSYSDEPDIR= ${TOPSRC}/sysdep/common/libsysdep
++
++all: ${PROG}
++
++clean:
++ rm -f ${PROG}
+--- isakmpd-20041012.orig/pf_key_v2.c
++++ isakmpd-20041012/pf_key_v2.c
+@@ -1055,6 +1055,10 @@
+ #endif
+ #if defined (USE_NAT_TRAVERSAL) && defined (SADB_X_EXT_UDPENCAP)
+ struct sadb_x_udpencap udpencap;
++#elif defined (USE_NAT_TRAVERSAL) && defined (SADB_X_EXT_NAT_T_TYPE)
++ struct sadb_x_nat_t_type nat_t_type;
++ struct sadb_x_nat_t_port nat_t_sport;
++ struct sadb_x_nat_t_port nat_t_dport;
+ #endif
+ #ifdef USE_DEBUG
+ char *addr_str;
+@@ -1273,10 +1277,15 @@
+ log_print("pf_key_v2_set_spi: invalid proto %d", proto->proto);
+ goto cleanup;
+ }
+- if (incoming)
++ if (incoming) {
+ sa->transport->vtbl->get_src(sa->transport, &dst);
+- else
++ sa->transport->vtbl->get_dst(sa->transport, &src);
++ }
++ else {
+ sa->transport->vtbl->get_dst(sa->transport, &dst);
++ sa->transport->vtbl->get_src(sa->transport, &src);
++ }
++
+ #ifdef KAME
+ msg.sadb_msg_seq = (incoming ?
+ pf_key_v2_seq_by_sa(proto->spi[incoming], sizeof ssa.sadb_sa_spi,
+@@ -1319,12 +1328,13 @@
+ ssa.sadb_sa_flags = 0;
+ #ifdef SADB_X_SAFLAGS_TUNNEL
+ if (iproto->encap_mode == IPSEC_ENCAP_TUNNEL ||
+- iproto->encap_mode == IPSEC_ENCAP_UDP_ENCAP_TUNNEL)
++ iproto->encap_mode == IPSEC_ENCAP_UDP_ENCAP_TUNNEL ||
++ iproto->encap_mode == IPSEC_ENCAP_UDP_ENCAP_TUNNEL_DRAFT)
+ ssa.sadb_sa_flags = SADB_X_SAFLAGS_TUNNEL;
+ #endif
+
+-#if defined (USE_NAT_TRAVERSAL) && defined (SADB_X_EXT_UDPENCAP)
+ if (isakmp_sa->flags & SA_FLAG_NAT_T_ENABLE) {
++#if defined (USE_NAT_TRAVERSAL) && defined (SADB_X_EXT_UDPENCAP)
+ memset(&udpencap, 0, sizeof udpencap);
+ ssa.sadb_sa_flags |= SADB_X_SAFLAGS_UDPENCAP;
+ udpencap.sadb_x_udpencap_exttype = SADB_X_EXT_UDPENCAP;
+@@ -1334,8 +1344,40 @@
+ if (pf_key_v2_msg_add(update, (struct sadb_ext *)&udpencap, 0)
+ == -1)
+ goto cleanup;
+- }
++#elif defined (USE_NAT_TRAVERSAL) && defined (SADB_X_EXT_NAT_T_TYPE)
++#ifndef UDP_ENCAP_ESPINUDP
++#define UDP_ENCAP_ESPINUDP 2
++#endif
++ memset(&nat_t_type, 0, sizeof nat_t_type);
++ memset(&nat_t_sport, 0, sizeof nat_t_sport);
++ memset(&nat_t_dport, 0, sizeof nat_t_dport);
++
++ /* type = draft-udp-encap-06 */
++ nat_t_type.sadb_x_nat_t_type_len = sizeof nat_t_type / PF_KEY_V2_CHUNK;
++ nat_t_type.sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
++ nat_t_type.sadb_x_nat_t_type_type = UDP_ENCAP_ESPINUDP;
++ if(pf_key_v2_msg_add(update, (struct sadb_ext *)&nat_t_type, 0) == -1)
++ goto cleanup;
++
++ /* source port */
++ nat_t_sport.sadb_x_nat_t_port_len = sizeof nat_t_sport /
++ PF_KEY_V2_CHUNK;
++ nat_t_sport.sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_SPORT;
++ nat_t_sport.sadb_x_nat_t_port_port = sockaddr_port(src);
++ if(pf_key_v2_msg_add(update, (struct sadb_ext *)&nat_t_sport, 0) == -1)
++ goto cleanup;
++
++ /* destination port */
++ nat_t_dport.sadb_x_nat_t_port_len = sizeof nat_t_dport /
++ PF_KEY_V2_CHUNK;
++ nat_t_dport.sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_DPORT;
++ nat_t_dport.sadb_x_nat_t_port_port = sockaddr_port(dst);
++ if(pf_key_v2_msg_add(update, (struct sadb_ext *)&nat_t_dport, 0) == -1)
++ goto cleanup;
++
++ /* original address (transport mode checksum missing info) goes here */
+ #endif
++ }
+
+ if (pf_key_v2_msg_add(update, (struct sadb_ext *)&ssa, 0) == -1)
+ goto cleanup;
+@@ -1395,10 +1437,6 @@
+ /*
+ * Setup the ADDRESS extensions.
+ */
+- if (incoming)
+- sa->transport->vtbl->get_dst(sa->transport, &src);
+- else
+- sa->transport->vtbl->get_src(sa->transport, &src);
+ len = sizeof *addr + PF_KEY_V2_ROUND(sysdep_sa_len(src));
+ addr = calloc(1, len);
+ if (!addr)
+@@ -2167,7 +2205,7 @@
+ pf_key_v2_msg_free(ret);
+ return -1;
+
+-#elif defined (SADB_X_SPDADD) && defined (SADB_X_SPDDELETE)
++#elif defined (SADB_X_SPDUPDATE) && defined (SADB_X_SPDDELETE)
+ struct sadb_msg msg;
+ struct sadb_x_policy *policy = 0;
+ struct sadb_x_ipsecrequest *ipsecrequest;
+@@ -2181,7 +2219,7 @@
+ struct sockaddr_in *ip4_sa;
+ struct sockaddr_in6 *ip6_sa;
+
+- msg.sadb_msg_type = delete ? SADB_X_SPDDELETE : SADB_X_SPDADD;
++ msg.sadb_msg_type = delete ? SADB_X_SPDDELETE : SADB_X_SPDUPDATE;
+ msg.sadb_msg_satype = SADB_SATYPE_UNSPEC;
+ msg.sadb_msg_seq = 0;
+ flow = pf_key_v2_msg_new(&msg, 0);
+--- isakmpd-20041012.orig/isakmp_num.cst
++++ isakmpd-20041012/isakmp_num.cst
+@@ -57,15 +57,18 @@
+ KD 17 # RFC 3547, Key Download
+ SEQ 18 # RFC 3547, Sequence Number
+ POP 19 # RFC 3547, Proof of possession
+- RESERVED_MIN 20
++ NAT_D 20 # RFC 3947, NAT Discovery payload
++ NAT_OA 21 # RFC 3947, NAT Original Address payload
++ RESERVED_MIN 22
+ RESERVED_MAX 127
+ PRIVATE_MIN 128
+ # XXX values from draft-ietf-ipsec-nat-t-ike-01,02,03. Later drafts specify
+ # XXX NAT_D as payload 15 and NAT_OA as 16, but these are allocated by RFC
+ # XXX 3547 as seen above.
+- NAT_D 130 # NAT Discovery payload
+- NAT_OA 131 # NAT Original Address payload
++ NAT_D_DRAFT 130 # NAT Discovery payload
++ NAT_OA_DRAFT 131 # NAT Original Address payload
+ PRIVATE_MAX 255
++ MAX 255
+ .
+
+ # ISAKMP exchange types.
+--- isakmpd-20041012.orig/ipsec_num.cst
++++ isakmpd-20041012/ipsec_num.cst
+@@ -62,10 +62,10 @@
+ IPSEC_ENCAP
+ TUNNEL 1
+ TRANSPORT 2
+- FUTURE_UDP_ENCAP_TUNNEL 3 # XXX Not yet assigned
+- FUTURE_UDP_ENCAP_TRANSPORT 4 # XXX Not yet assigned
+- UDP_ENCAP_TUNNEL 61443 # draft-ietf-ipsec-nat-t-ike
+- UDP_ENCAP_TRANSPORT 61443 # draft-ietf-ipsec-nat-t-ike
++ UDP_ENCAP_TUNNEL 3
++ UDP_ENCAP_TRANSPORT 4
++ UDP_ENCAP_TUNNEL_DRAFT 61443 # draft-ietf-ipsec-nat-t-ike
++ UDP_ENCAP_TRANSPORT_DRAFT 61443 # draft-ietf-ipsec-nat-t-ike
+ .
+
+ # IPSEC authentication algorithm.
+--- isakmpd-20041012.orig/nat_traversal.h
++++ isakmpd-20041012/nat_traversal.h
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: nat_traversal.h,v 1.2 2004/06/21 23:27:10 ho Exp $ */
++/* $OpenBSD: nat_traversal.h,v 1.4 2005/07/25 15:03:47 hshoexer Exp $ */
+
+ /*
+ * Copyright (c) 2004 Håkan Olsson. All rights reserved.
+@@ -27,6 +27,24 @@
+ #ifndef _NAT_TRAVERSAL_H_
+ #define _NAT_TRAVERSAL_H_
+
++#define VID_DRAFT_V2 0
++#define VID_DRAFT_V2_N 1
++#define VID_DRAFT_V3 2
++#define VID_RFC3947 3
++
++struct nat_t_cap {
++ int id;
++ u_int32_t flags;
++ const char *text;
++ char *hash;
++ size_t hashsize;
++};
++
++/*
++ * Set if -T is given on the command line to disable NAT-T support.
++ */
++extern int disable_nat_t;
++
+ void nat_t_init(void);
+ int nat_t_add_vendor_payloads(struct message *);
+ void nat_t_check_vendor_payload(struct message *, struct payload *);
+--- isakmpd-20041012.orig/message.c
++++ isakmpd-20041012/message.c
+@@ -112,6 +112,7 @@
+ message_validate_hash, message_validate_sig, message_validate_nonce,
+ message_validate_notify, message_validate_delete,
+ message_validate_vendor, message_validate_attribute,
++ message_validate_nat_d, message_validate_nat_oa,
+ message_validate_nat_d, message_validate_nat_oa
+ };
+
+@@ -120,7 +121,7 @@
+ isakmp_id_fld, isakmp_cert_fld, isakmp_certreq_fld, isakmp_hash_fld,
+ isakmp_sig_fld, isakmp_nonce_fld, isakmp_notify_fld, isakmp_delete_fld,
+ isakmp_vendor_fld, isakmp_attribute_fld, isakmp_nat_d_fld,
+- isakmp_nat_oa_fld
++ isakmp_nat_oa_fld, isakmp_nat_d_fld, isakmp_nat_oa_fld
+ };
+
+ /*
+@@ -138,7 +139,8 @@
+ ISAKMP_PAYLOAD_SAK, ISAKMP_PAYLOAD_SAT, ISAKMP_PAYLOAD_KD,
+ ISAKMP_PAYLOAD_SEQ, ISAKMP_PAYLOAD_POP
+ #endif
+- ISAKMP_PAYLOAD_NAT_D, ISAKMP_PAYLOAD_NAT_OA
++ ISAKMP_PAYLOAD_NAT_D, ISAKMP_PAYLOAD_NAT_OA,
++ ISAKMP_PAYLOAD_NAT_D_DRAFT, ISAKMP_PAYLOAD_NAT_OA_DRAFT
+ };
+
+ static u_int8_t payload_map[256];
+@@ -347,8 +349,8 @@
+ }
+ /* Ignore most private payloads. */
+ if (next >= ISAKMP_PAYLOAD_PRIVATE_MIN &&
+- next != ISAKMP_PAYLOAD_NAT_D &&
+- next != ISAKMP_PAYLOAD_NAT_OA) {
++ next != ISAKMP_PAYLOAD_NAT_D_DRAFT &&
++ next != ISAKMP_PAYLOAD_NAT_OA_DRAFT) {
+ LOG_DBG((LOG_MESSAGE, 30, "message_parse_payloads: "
+ "private next payload type %s in payload of "
+ "type %d ignored",
+@@ -460,8 +462,10 @@
+ return ISAKMP_ATTRIBUTE_SZ;
+ #if defined (USE_NAT_TRAVERSAL)
+ case ISAKMP_PAYLOAD_NAT_D:
++ case ISAKMP_PAYLOAD_NAT_D_DRAFT:
+ return ISAKMP_NAT_D_SZ;
+ case ISAKMP_PAYLOAD_NAT_OA:
++ case ISAKMP_PAYLOAD_NAT_OA_DRAFT:
+ return ISAKMP_NAT_OA_SZ;
+ #endif
+ /* Not yet supported and any other unknown payloads. */
+--- isakmpd-20041012.orig/policy.c
++++ isakmpd-20041012/policy.c
+@@ -511,7 +511,10 @@
+ break;
+ }
+ #if defined (USE_NAT_TRAVERSAL)
+- else if (decode_16(value) == IPSEC_ENCAP_UDP_ENCAP_TUNNEL)
++ else if (decode_16(value) ==
++ IPSEC_ENCAP_UDP_ENCAP_TUNNEL ||
++ decode_16(value) ==
++ IPSEC_ENCAP_UDP_ENCAP_TUNNEL_DRAFT)
+ switch (proto->proto) {
+ case IPSEC_PROTO_IPSEC_AH:
+ ah_encapsulation = "udp-encap-tunnel";
+@@ -1932,7 +1935,7 @@
+ void
+ policy_init(void)
+ {
+- char *ptr, *policy_file;
++ char *ptr, *policy_file, *use_keynote;
+ char **asserts;
+ size_t sz, len;
+ int fd, i;
+@@ -1940,10 +1943,11 @@
+ LOG_DBG((LOG_POLICY, 30, "policy_init: initializing"));
+
+ /* Do we want to use the policy modules? */
+- if (ignore_policy ||
+- strncmp("yes", conf_get_str("General", "Use-Keynote"), 3))
+- return;
+-
++ use_keynote = conf_get_str("General", "Use-Keynote");
++ if (ignore_policy ||
++ (use_keynote && strncmp("yes", use_keynote, 3)))
++ return;
++
+ /* Get policy file from configuration. */
+ policy_file = conf_get_str("General", "Policy-file");
+ if (!policy_file)
+--- isakmpd-20041012.orig/ike_phase_1.c
++++ isakmpd-20041012/ike_phase_1.c
+@@ -1040,9 +1040,9 @@
+
+ /* Compare expected/desired and received remote ID */
+ if (bcmp(rid, payload->p + ISAKMP_ID_DATA_OFF, sz)) {
+- free(rid);
+ log_print("ike_phase_1_recv_ID: "
+- "received remote ID other than expected %s", p);
++ "received remote ID other than expected %s - %s", p, payload->p);
++ free(rid);
+ return -1;
+ }
+ free(rid);
+--- isakmpd-20041012.orig/x509.c
++++ isakmpd-20041012/x509.c
+@@ -910,7 +910,11 @@
+ X509_STORE_CTX_init(&csc, x509_cas, cert, NULL);
+ #if OPENSSL_VERSION_NUMBER >= 0x00907000L
+ /* XXX See comment in x509_read_crls_from_dir. */
++#if OPENSSL_VERSION_NUMBER >= 0x00908000L
++ if (x509_cas->param->flags & X509_V_FLAG_CRL_CHECK) {
++#else
+ if (x509_cas->flags & X509_V_FLAG_CRL_CHECK) {
++#endif
+ X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK);
+ X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK_ALL);
+ }
+--- isakmpd-20041012.orig/sysdep/linux/sysdep.c
++++ isakmpd-20041012/sysdep/linux/sysdep.c
+@@ -169,22 +169,22 @@
+ return 0;
+
+ if (!(af == AF_INET || af == AF_INET6))
+- {
++ {
+ log_print ("sysdep_cleartext: unsupported protocol family %d", af);
+ return -1;
+ }
+
+ if (setsockopt (fd, af == AF_INET ? IPPROTO_IP : IPPROTO_IPV6,
+- af == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY,
+- &pol_in, sizeof pol_in) < 0 ||
++ af == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY,
++ &pol_in, sizeof pol_in) < 0 ||
+ setsockopt (fd, af == AF_INET ? IPPROTO_IP : IPPROTO_IPV6,
+- af == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY,
+- &pol_out, sizeof pol_out) < 0)
+- {
++ af == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY,
++ &pol_out, sizeof pol_out) < 0)
++ {
+ log_error ("sysdep_cleartext: "
+- "setsockopt (%d, IPPROTO_IP%s, IP%s_IPSEC_POLICY, ...) "
+- "failed", fd, af == AF_INET ? "" : "V6",
+- af == AF_INET ? "" : "V6");
++ "setsockopt (%d, IPPROTO_IP%s, IP%s_IPSEC_POLICY, ...) "
++ "failed", fd, af == AF_INET ? "" : "V6",
++ af == AF_INET ? "" : "V6");
+ return -1;
+ }
+ return 0;
+--- isakmpd-20041012.orig/sysdep/linux/GNUmakefile.sysdep
++++ isakmpd-20041012/sysdep/linux/GNUmakefile.sysdep
+@@ -33,13 +33,13 @@
+ LDADD+= -lgmp ${LIBSYSDEP} ${LIBCRYPTO}
+ DPADD+= ${LIBGMP} ${LIBSYSDEP}
+
+-CFLAGS+= -DUSE_OLD_SOCKADDR -DHAVE_PCAP \
+- -DNEED_SYSDEP_APP -DMP_FLAVOUR=MP_FLAVOUR_GMP \
+- -I/usr/src/linux/include -I${.CURDIR}/sysdep/common \
++CFLAGS+= -DHAVE_GETNAMEINFO -DUSE_OLD_SOCKADDR -DHAVE_PCAP \
++ -DNEED_SYSDEP_APP -DMP_FLAVOUR=MP_FLAVOUR_GMP -DUSE_AES \
++ -I${.CURDIR}/sysdep/linux/include -I${.CURDIR}/sysdep/common \
+ -I/usr/include/openssl
+
+ FEATURES= debug tripledes blowfish cast ec aggressive x509 policy
+-FEATURES+= des aes
++FEATURES+= dpd nat_traversal isakmp_cfg des aes
+
+ IPSEC_SRCS= pf_key_v2.c
+ IPSEC_CFLAGS= -DUSE_PF_KEY_V2
+@@ -51,7 +51,7 @@
+ # hack libsysdep.a dependenc
+ ${LIBSYSDEPDIR}/.depend ${LIBSYSDEP}:
+ cd ${LIBSYSDEPDIR} && \
+- ${MAKE} --no-print-directory ${MAKEFLAGS} \
++ ${MAKE} --no-print-directory \
+ CFLAGS="${CFLAGS}" MKDEP="${MKDEP}" ${MAKECMDGOALS}
+
+ ifeq ($(findstring clean,$(MAKECMDGOALS)),clean)
+--- isakmpd-20041012.orig/sysdep/linux/include/bitstring.h
++++ isakmpd-20041012/sysdep/linux/include/bitstring.h
+@@ -0,0 +1,132 @@
++/* $OpenBSD: bitstring.h,v 1.4 2002/06/19 02:50:10 millert Exp $ */
++/* $NetBSD: bitstring.h,v 1.5 1997/05/14 15:49:55 pk Exp $ */
++
++/*
++ * Copyright (c) 1989, 1993
++ * The Regents of the University of California. All rights reserved.
++ *
++ * This code is derived from software contributed to Berkeley by
++ * Paul Vixie.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ * must display the following acknowledgement:
++ * This product includes software developed by the University of
++ * California, Berkeley and its contributors.
++ * 4. Neither the name of the University nor the names of its contributors
++ * may be used to endorse or promote products derived from this software
++ * without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ * @(#)bitstring.h 8.1 (Berkeley) 7/19/93
++ */
++
++#ifndef _BITSTRING_H_
++#define _BITSTRING_H_
++
++/* modified for SV/AT and bitstring bugfix by M.R.Murphy, 11oct91
++ * bitstr_size changed gratuitously, but shorter
++ * bit_alloc spelling error fixed
++ * the following were efficient, but didn't work, they've been made to
++ * work, but are no longer as efficient :-)
++ * bit_nclear, bit_nset, bit_ffc, bit_ffs
++ */
++typedef unsigned char bitstr_t;
++
++/* internal macros */
++ /* byte of the bitstring bit is in */
++#define _bit_byte(bit) \
++ ((bit) >> 3)
++
++ /* mask for the bit within its byte */
++#define _bit_mask(bit) \
++ (1 << ((bit)&0x7))
++
++/* external macros */
++ /* bytes in a bitstring of nbits bits */
++#define bitstr_size(nbits) \
++ (((nbits) + 7) >> 3)
++
++ /* allocate a bitstring */
++#define bit_alloc(nbits) \
++ (bitstr_t *)calloc((size_t)bitstr_size(nbits), sizeof(bitstr_t))
++
++ /* allocate a bitstring on the stack */
++#define bit_decl(name, nbits) \
++ ((name)[bitstr_size(nbits)])
++
++ /* is bit N of bitstring name set? */
++#define bit_test(name, bit) \
++ ((name)[_bit_byte(bit)] & _bit_mask(bit))
++
++ /* set bit N of bitstring name */
++#define bit_set(name, bit) \
++ ((name)[_bit_byte(bit)] |= _bit_mask(bit))
++
++ /* clear bit N of bitstring name */
++#define bit_clear(name, bit) \
++ ((name)[_bit_byte(bit)] &= ~_bit_mask(bit))
++
++ /* clear bits start ... stop in bitstring */
++#define bit_nclear(name, start, stop) do { \
++ register bitstr_t *_name = name; \
++ register int _start = start, _stop = stop; \
++ while (_start <= _stop) { \
++ bit_clear(_name, _start); \
++ _start++; \
++ } \
++} while(0)
++
++ /* set bits start ... stop in bitstring */
++#define bit_nset(name, start, stop) do { \
++ register bitstr_t *_name = name; \
++ register int _start = start, _stop = stop; \
++ while (_start <= _stop) { \
++ bit_set(_name, _start); \
++ _start++; \
++ } \
++} while(0)
++
++ /* find first bit clear in name */
++#define bit_ffc(name, nbits, value) do { \
++ register bitstr_t *_name = name; \
++ register int _bit, _nbits = nbits, _value = -1; \
++ for (_bit = 0; _bit < _nbits; ++_bit) \
++ if (!bit_test(_name, _bit)) { \
++ _value = _bit; \
++ break; \
++ } \
++ *(value) = _value; \
++} while(0)
++
++ /* find first bit set in name */
++#define bit_ffs(name, nbits, value) do { \
++ register bitstr_t *_name = name; \
++ register int _bit, _nbits = nbits, _value = -1; \
++ for (_bit = 0; _bit < _nbits; ++_bit) \
++ if (bit_test(_name, _bit)) { \
++ _value = _bit; \
++ break; \
++ } \
++ *(value) = _value; \
++} while(0)
++
++#endif /* !_BITSTRING_H_ */
+--- isakmpd-20041012.orig/sysdep/linux/include/sys/queue.h
++++ isakmpd-20041012/sysdep/linux/include/sys/queue.h
+@@ -0,0 +1,453 @@
++/*
++ * Copyright (c) 1991, 1993
++ * The Regents of the University of California. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ * must display the following acknowledgement:
++ * This product includes software developed by the University of
++ * California, Berkeley and its contributors.
++ * 4. Neither the name of the University nor the names of its contributors
++ * may be used to endorse or promote products derived from this software
++ * without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ * @(#)queue.h 8.5 (Berkeley) 8/20/94
++ * $FreeBSD: src/sys/sys/queue.h,v 1.45 2001/12/11 11:49:58 sheldonh Exp $
++ */
++
++#ifndef _SYS_QUEUE_H_
++#define _SYS_QUEUE_H_
++
++//#include <machine/ansi.h> /* for __offsetof */
++
++/*
++ * This file defines four types of data structures: singly-linked lists,
++ * singly-linked tail queues, lists and tail queues.
++ *
++ * A singly-linked list is headed by a single forward pointer. The elements
++ * are singly linked for minimum space and pointer manipulation overhead at
++ * the expense of O(n) removal for arbitrary elements. New elements can be
++ * added to the list after an existing element or at the head of the list.
++ * Elements being removed from the head of the list should use the explicit
++ * macro for this purpose for optimum efficiency. A singly-linked list may
++ * only be traversed in the forward direction. Singly-linked lists are ideal
++ * for applications with large datasets and few or no removals or for
++ * implementing a LIFO queue.
++ *
++ * A singly-linked tail queue is headed by a pair of pointers, one to the
++ * head of the list and the other to the tail of the list. The elements are
++ * singly linked for minimum space and pointer manipulation overhead at the
++ * expense of O(n) removal for arbitrary elements. New elements can be added
++ * to the list after an existing element, at the head of the list, or at the
++ * end of the list. Elements being removed from the head of the tail queue
++ * should use the explicit macro for this purpose for optimum efficiency.
++ * A singly-linked tail queue may only be traversed in the forward direction.
++ * Singly-linked tail queues are ideal for applications with large datasets
++ * and few or no removals or for implementing a FIFO queue.
++ *
++ * A list is headed by a single forward pointer (or an array of forward
++ * pointers for a hash table header). The elements are doubly linked
++ * so that an arbitrary element can be removed without a need to
++ * traverse the list. New elements can be added to the list before
++ * or after an existing element or at the head of the list. A list
++ * may only be traversed in the forward direction.
++ *
++ * A tail queue is headed by a pair of pointers, one to the head of the
++ * list and the other to the tail of the list. The elements are doubly
++ * linked so that an arbitrary element can be removed without a need to
++ * traverse the list. New elements can be added to the list before or
++ * after an existing element, at the head of the list, or at the end of
++ * the list. A tail queue may be traversed in either direction.
++ *
++ * For details on the use of these macros, see the queue(3) manual page.
++ *
++ *
++ * SLIST LIST STAILQ TAILQ
++ * _HEAD + + + +
++ * _HEAD_INITIALIZER + + + +
++ * _ENTRY + + + +
++ * _INIT + + + +
++ * _EMPTY + + + +
++ * _FIRST + + + +
++ * _NEXT + + + +
++ * _PREV - - - +
++ * _LAST - - + +
++ * _FOREACH + + + +
++ * _FOREACH_REVERSE - - - +
++ * _INSERT_HEAD + + + +
++ * _INSERT_BEFORE - + - +
++ * _INSERT_AFTER + + + +
++ * _INSERT_TAIL - - + +
++ * _REMOVE_HEAD + - + -
++ * _REMOVE + + + +
++ *
++ */
++
++/*
++ * Singly-linked List declarations.
++ */
++#define SLIST_HEAD(name, type) \
++struct name { \
++ struct type *slh_first; /* first element */ \
++}
++
++#define SLIST_HEAD_INITIALIZER(head) \
++ { NULL }
++
++#define SLIST_ENTRY(type) \
++struct { \
++ struct type *sle_next; /* next element */ \
++}
++
++/*
++ * Singly-linked List functions.
++ */
++#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
++
++#define SLIST_FIRST(head) ((head)->slh_first)
++
++#define SLIST_FOREACH(var, head, field) \
++ for ((var) = SLIST_FIRST((head)); \
++ (var); \
++ (var) = SLIST_NEXT((var), field))
++
++#define SLIST_INIT(head) do { \
++ SLIST_FIRST((head)) = NULL; \
++} while (0)
++
++#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
++ SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
++ SLIST_NEXT((slistelm), field) = (elm); \
++} while (0)
++
++#define SLIST_INSERT_HEAD(head, elm, field) do { \
++ SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
++ SLIST_FIRST((head)) = (elm); \
++} while (0)
++
++#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
++
++#define SLIST_REMOVE(head, elm, type, field) do { \
++ if (SLIST_FIRST((head)) == (elm)) { \
++ SLIST_REMOVE_HEAD((head), field); \
++ } \
++ else { \
++ struct type *curelm = SLIST_FIRST((head)); \
++ while (SLIST_NEXT(curelm, field) != (elm)) \
++ curelm = SLIST_NEXT(curelm, field); \
++ SLIST_NEXT(curelm, field) = \
++ SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
++ } \
++} while (0)
++
++#define SLIST_REMOVE_HEAD(head, field) do { \
++ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
++} while (0)
++
++/*
++ * Singly-linked Tail queue declarations.
++ */
++#define STAILQ_HEAD(name, type) \
++struct name { \
++ struct type *stqh_first;/* first element */ \
++ struct type **stqh_last;/* addr of last next element */ \
++}
++
++#define STAILQ_HEAD_INITIALIZER(head) \
++ { NULL, &(head).stqh_first }
++
++#define STAILQ_ENTRY(type) \
++struct { \
++ struct type *stqe_next; /* next element */ \
++}
++
++/*
++ * Singly-linked Tail queue functions.
++ */
++#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
++
++#define STAILQ_FIRST(head) ((head)->stqh_first)
++
++#define STAILQ_FOREACH(var, head, field) \
++ for((var) = STAILQ_FIRST((head)); \
++ (var); \
++ (var) = STAILQ_NEXT((var), field))
++
++#define STAILQ_INIT(head) do { \
++ STAILQ_FIRST((head)) = NULL; \
++ (head)->stqh_last = &STAILQ_FIRST((head)); \
++} while (0)
++
++#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
++ if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
++ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
++ STAILQ_NEXT((tqelm), field) = (elm); \
++} while (0)
++
++#define STAILQ_INSERT_HEAD(head, elm, field) do { \
++ if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
++ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
++ STAILQ_FIRST((head)) = (elm); \
++} while (0)
++
++#define STAILQ_INSERT_TAIL(head, elm, field) do { \
++ STAILQ_NEXT((elm), field) = NULL; \
++ *(head)->stqh_last = (elm); \
++ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
++} while (0)
++
++#define STAILQ_LAST(head, type, field) \
++ (STAILQ_EMPTY(head) ? \
++ NULL : \
++ ((struct type *) \
++ ((char *)((head)->stqh_last) - __offsetof(struct type, field))))
++
++#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
++
++#define STAILQ_REMOVE(head, elm, type, field) do { \
++ if (STAILQ_FIRST((head)) == (elm)) { \
++ STAILQ_REMOVE_HEAD(head, field); \
++ } \
++ else { \
++ struct type *curelm = STAILQ_FIRST((head)); \
++ while (STAILQ_NEXT(curelm, field) != (elm)) \
++ curelm = STAILQ_NEXT(curelm, field); \
++ if ((STAILQ_NEXT(curelm, field) = \
++ STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
++ (head)->stqh_last = &STAILQ_NEXT((curelm), field);\
++ } \
++} while (0)
++
++#define STAILQ_REMOVE_HEAD(head, field) do { \
++ if ((STAILQ_FIRST((head)) = \
++ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
++ (head)->stqh_last = &STAILQ_FIRST((head)); \
++} while (0)
++
++#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
++ if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
++ (head)->stqh_last = &STAILQ_FIRST((head)); \
++} while (0)
++
++/*
++ * List declarations.
++ */
++#define LIST_HEAD(name, type) \
++struct name { \
++ struct type *lh_first; /* first element */ \
++}
++
++#define LIST_HEAD_INITIALIZER(head) \
++ { NULL }
++
++#define LIST_ENTRY(type) \
++struct { \
++ struct type *le_next; /* next element */ \
++ struct type **le_prev; /* address of previous next element */ \
++}
++
++/*
++ * List functions.
++ */
++
++#define LIST_EMPTY(head) ((head)->lh_first == NULL)
++
++#define LIST_FIRST(head) ((head)->lh_first)
++
++#define LIST_FOREACH(var, head, field) \
++ for ((var) = LIST_FIRST((head)); \
++ (var); \
++ (var) = LIST_NEXT((var), field))
++
++#define LIST_INIT(head) do { \
++ LIST_FIRST((head)) = NULL; \
++} while (0)
++
++#define LIST_INSERT_AFTER(listelm, elm, field) do { \
++ if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
++ LIST_NEXT((listelm), field)->field.le_prev = \
++ &LIST_NEXT((elm), field); \
++ LIST_NEXT((listelm), field) = (elm); \
++ (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
++} while (0)
++
++#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
++ (elm)->field.le_prev = (listelm)->field.le_prev; \
++ LIST_NEXT((elm), field) = (listelm); \
++ *(listelm)->field.le_prev = (elm); \
++ (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
++} while (0)
++
++#define LIST_INSERT_HEAD(head, elm, field) do { \
++ if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
++ LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
++ LIST_FIRST((head)) = (elm); \
++ (elm)->field.le_prev = &LIST_FIRST((head)); \
++} while (0)
++
++#define LIST_NEXT(elm, field) ((elm)->field.le_next)
++
++#define LIST_REMOVE(elm, field) do { \
++ if (LIST_NEXT((elm), field) != NULL) \
++ LIST_NEXT((elm), field)->field.le_prev = \
++ (elm)->field.le_prev; \
++ *(elm)->field.le_prev = LIST_NEXT((elm), field); \
++} while (0)
++
++/*
++ * Tail queue declarations.
++ */
++#define TAILQ_HEAD(name, type) \
++struct name { \
++ struct type *tqh_first; /* first element */ \
++ struct type **tqh_last; /* addr of last next element */ \
++}
++
++#define TAILQ_HEAD_INITIALIZER(head) \
++ { NULL, &(head).tqh_first }
++
++#define TAILQ_ENTRY(type) \
++struct { \
++ struct type *tqe_next; /* next element */ \
++ struct type **tqe_prev; /* address of previous next element */ \
++}
++
++/*
++ * Tail queue functions.
++ */
++#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
++
++#define TAILQ_FIRST(head) ((head)->tqh_first)
++
++#define TAILQ_FOREACH(var, head, field) \
++ for ((var) = TAILQ_FIRST((head)); \
++ (var); \
++ (var) = TAILQ_NEXT((var), field))
++
++#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
++ for ((var) = TAILQ_LAST((head), headname); \
++ (var); \
++ (var) = TAILQ_PREV((var), headname, field))
++
++#define TAILQ_INIT(head) do { \
++ TAILQ_FIRST((head)) = NULL; \
++ (head)->tqh_last = &TAILQ_FIRST((head)); \
++} while (0)
++
++#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
++ if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
++ TAILQ_NEXT((elm), field)->field.tqe_prev = \
++ &TAILQ_NEXT((elm), field); \
++ else \
++ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
++ TAILQ_NEXT((listelm), field) = (elm); \
++ (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
++} while (0)
++
++#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
++ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
++ TAILQ_NEXT((elm), field) = (listelm); \
++ *(listelm)->field.tqe_prev = (elm); \
++ (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
++} while (0)
++
++#define TAILQ_INSERT_HEAD(head, elm, field) do { \
++ if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
++ TAILQ_FIRST((head))->field.tqe_prev = \
++ &TAILQ_NEXT((elm), field); \
++ else \
++ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
++ TAILQ_FIRST((head)) = (elm); \
++ (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
++} while (0)
++
++#define TAILQ_INSERT_TAIL(head, elm, field) do { \
++ TAILQ_NEXT((elm), field) = NULL; \
++ (elm)->field.tqe_prev = (head)->tqh_last; \
++ *(head)->tqh_last = (elm); \
++ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
++} while (0)
++
++#define TAILQ_LAST(head, headname) \
++ (*(((struct headname *)((head)->tqh_last))->tqh_last))
++
++#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
++
++#define TAILQ_PREV(elm, headname, field) \
++ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
++
++#define TAILQ_REMOVE(head, elm, field) do { \
++ if ((TAILQ_NEXT((elm), field)) != NULL) \
++ TAILQ_NEXT((elm), field)->field.tqe_prev = \
++ (elm)->field.tqe_prev; \
++ else \
++ (head)->tqh_last = (elm)->field.tqe_prev; \
++ *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
++} while (0)
++
++
++#ifdef _KERNEL
++
++/*
++ * XXX insque() and remque() are an old way of handling certain queues.
++ * They bogusly assumes that all queue heads look alike.
++ */
++
++struct quehead {
++ struct quehead *qh_link;
++ struct quehead *qh_rlink;
++};
++
++#ifdef __GNUC__
++
++static __inline void
++insque(void *a, void *b)
++{
++ struct quehead *element = (struct quehead *)a,
++ *head = (struct quehead *)b;
++
++ element->qh_link = head->qh_link;
++ element->qh_rlink = head;
++ head->qh_link = element;
++ element->qh_link->qh_rlink = element;
++}
++
++static __inline void
++remque(void *a)
++{
++ struct quehead *element = (struct quehead *)a;
++
++ element->qh_link->qh_rlink = element->qh_rlink;
++ element->qh_rlink->qh_link = element->qh_link;
++ element->qh_rlink = 0;
++}
++
++#else /* !__GNUC__ */
++
++void insque __P((void *a, void *b));
++void remque __P((void *a));
++
++#endif /* __GNUC__ */
++
++#endif /* _KERNEL */
++
++#endif /* !_SYS_QUEUE_H_ */
+--- isakmpd-20041012.orig/sysdep/common/pcap.h
++++ isakmpd-20041012/sysdep/common/pcap.h
+@@ -55,8 +55,13 @@
+ u_int32_t linktype; /* data link type (DLT_*) */
+ };
+
++struct pcap_timeval {
++ int32_t tv_sec; /* seconds */
++ int32_t tv_usec; /* microseconds */
++};
++
+ struct pcap_pkthdr {
+- struct timeval ts; /* time stamp */
++ struct pcap_timeval ts; /* time stamp */
+ u_int32_t caplen; /* length of portion present */
+ u_int32_t len; /* length this packet (off wire) */
+ };
+--- isakmpd-20041012.orig/sysdep/common/libsysdep/arc4random.c
++++ isakmpd-20041012/sysdep/common/libsysdep/arc4random.c
+@@ -78,7 +78,7 @@
+ static void
+ arc4_stir(struct arc4_stream *as)
+ {
+- int fd;
++ int fd, i;
+ struct {
+ struct timeval tv;
+ u_int8_t rnd[128 - sizeof(struct timeval)];
+--- isakmpd-20041012.orig/x509v3.cnf
++++ isakmpd-20041012/x509v3.cnf
+@@ -0,0 +1,26 @@
++# default settings
++CERTPATHLEN = 1
++CERTUSAGE = digitalSignature,keyCertSign
++CERTIP = 0.0.0.0
++CERTFQDN = nohost.nodomain
++
++# This section should be referenced when building an x509v3 CA
++# Certificate.
++# The default path length and the key usage can be overriden
++# modified by setting the CERTPATHLEN and CERTUSAGE environment
++# variables.
++[x509v3_CA]
++basicConstraints=critical,CA:true,pathlen:$ENV::CERTPATHLEN
++keyUsage=$ENV::CERTUSAGE
++
++# This section should be referenced to add an IP Address
++# as an alternate subject name, needed by isakmpd
++# The address must be provided in the CERTIP environment variable
++[x509v3_IPAddr]
++subjectAltName=IP:$ENV::CERTIP
++
++# This section should be referenced to add a FQDN hostname
++# as an alternate subject name, needed by isakmpd
++# The address must be provided in the CERTFQDN environment variable
++[x509v3_FQDN]
++subjectAltName=DNS:$ENV::CERTFQDN
+
diff --git a/package/isakmpd/patches/020-standardize.patch b/package/isakmpd/patches/020-standardize.patch
new file mode 100644
index 0000000000..d3dfabf349
--- /dev/null
+++ b/package/isakmpd/patches/020-standardize.patch
@@ -0,0 +1,59 @@
+diff -urN isakmpd/GNUmakefile isakmpd.new/GNUmakefile
+--- isakmpd/GNUmakefile 2004-01-16 13:36:32.000000000 +0100
++++ isakmpd.new/GNUmakefile 2006-09-03 17:33:03.000000000 +0200
+@@ -238,3 +238,16 @@
+
+ realcleandepend:
+ rm -f .depend tags
++
++# Install rules
++install: install-bin install-man
++
++install-bin: isakmpd
++ -mkdir -p $(DESTDIR)$(BINDIR)
++ $(INSTALL) $(INSTALL_OPTS) -m 755 isakmpd $(DESTDIR)$(BINDIR)
++
++install-man:
++ -mkdir -p $(DESTDIR)$(MANDIR)/man8
++ $(INSTALL) $(INSTALL_OPTS) -m 444 isakmpd.8 $(DESTDIR)$(MANDIR)/man8
++ -mkdir -p $(DESTDIR)$(MANDIR)/man5
++ $(INSTALL) $(INSTALL_OPTS) -m 444 isakmpd.conf.5 isakmpd.policy.5 $(DESTDIR)$(MANDIR)/man5
+diff -urN isakmpd/samples/Makefile isakmpd.new/samples/Makefile
+--- isakmpd/samples/Makefile 2003-06-03 16:39:50.000000000 +0200
++++ isakmpd.new/samples/Makefile 2006-09-03 17:07:24.000000000 +0200
+@@ -26,7 +26,7 @@
+ #
+
+ FILES= VPN-* policy singlehost-*
+-TARGETDIR= /usr/share/ipsec/isakmpd
++TARGETDIR= /usr/share/isakmpd/samples
+
+ # The mkdir below is for installation on OpenBSD pre 2.7
+ install:
+
+diff -urN isakmp.old/sysdep/linux/GNUmakefile.sysdep isakmp.dev/sysdep/linux/GNUmakefile.sysdep
+--- isakmp.old/sysdep/linux/GNUmakefile.sysdep 2006-09-07 13:49:20.000000000 +0200
++++ isakmp.dev/sysdep/linux/GNUmakefile.sysdep 2006-09-07 13:51:41.000000000 +0200
+@@ -25,18 +25,18 @@
+ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ #
+
+-LIBGMP:= /usr/lib/libgmp.a
+-LIBCRYPTO:= /usr/lib/libcrypto.a
++LIBGMP:=
++LIBCRYPTO:= -lcrypto
+ LIBSYSDEPDIR:= ${.CURDIR}/sysdep/common/libsysdep
+ LIBSYSDEP:= ${LIBSYSDEPDIR}/libsysdep.a
+
+-LDADD+= -lgmp ${LIBSYSDEP} ${LIBCRYPTO}
++LDADD+= -L$(STAGING_DIR)/usr/lib -lgmp ${LIBSYSDEP} ${LIBCRYPTO}
+ DPADD+= ${LIBGMP} ${LIBSYSDEP}
+
+ CFLAGS+= -DHAVE_GETNAMEINFO -DUSE_OLD_SOCKADDR -DHAVE_PCAP \
+ -DNEED_SYSDEP_APP -DMP_FLAVOUR=MP_FLAVOUR_GMP -DUSE_AES \
+ -I${.CURDIR}/sysdep/linux/include -I${.CURDIR}/sysdep/common \
+- -I/usr/include/openssl
++ -I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/usr/include/openssl -I$(LINUX_DIR)/include
+
+ FEATURES= debug tripledes blowfish cast ec aggressive x509 policy
+ FEATURES+= dpd nat_traversal isakmp_cfg des aes
diff --git a/package/isakmpd/patches/030-openssl_hashes.patch b/package/isakmpd/patches/030-openssl_hashes.patch
new file mode 100644
index 0000000000..680db86a31
--- /dev/null
+++ b/package/isakmpd/patches/030-openssl_hashes.patch
@@ -0,0 +1,154 @@
+diff -urN isakmpd/GNUmakefile isakmpd.new/GNUmakefile
+--- isakmpd/GNUmakefile 2006-09-01 19:29:05.000000000 +0200
++++ isakmpd.new/GNUmakefile 2006-09-01 19:29:28.000000000 +0200
+@@ -75,13 +75,14 @@
+ isakmp_fld.c isakmp_fld.h
+ MAN= isakmpd.8 isakmpd.conf.5 isakmpd.policy.5
+
+-CFLAGS+= -O2 ${DEBUG} -Wall -DNEED_SYSDEP_APP \
++CFLAGS+= ${DEBUG} -Wall -DNEED_SYSDEP_APP \
+ -I${.CURDIR} -I${.CURDIR}/sysdep/${OS} -I. \
+
+ # Different debugging & profiling suggestions
+
+ # Include symbolic debugging info
+ DEBUG= -g
++CFLAGS+= -g
+
+ # Do execution time profiles
+ #CFLAGS+= -pg
+@@ -172,6 +173,14 @@
+ CFLAGS+= -DUSE_RAWKEY
+ endif
+
++ifdef USE_OPENSSL_MD5
++CFLAGS+= -DUSE_OPENSSL_MD5
++endif
++
++ifdef USE_OPENSSL_SHA1
++CFLAGS+= -DUSE_OPENSSL_SHA1
++endif
++
+ SRCS+= ${IPSEC_SRCS} ${X509} ${POLICY} ${EC} ${AGGRESSIVE} ${DNSSEC} \
+ $(ISAKMP_CFG)
+ CFLAGS+= ${IPSEC_CFLAGS}
+diff -urN isakmpd/sysdep/common/libsysdep/GNUmakefile isakmpd.new/sysdep/common/libsysdep/GNUmakefile
+--- isakmpd/sysdep/common/libsysdep/GNUmakefile 2003-06-03 16:52:06.000000000 +0200
++++ isakmpd.new/sysdep/common/libsysdep/GNUmakefile 2006-09-01 19:29:28.000000000 +0200
+@@ -31,10 +31,18 @@
+ .CURDIR:= $(shell pwd)
+
+ LIB= sysdep
+-SRCS= arc4random.c blowfish.c cast.c md5.c sha1.c strlcat.c strlcpy.c
++SRCS= arc4random.c blowfish.c cast.c strlcat.c strlcpy.c
+ NOMAN=
+ CFLAGS+= -I${.CURDIR}/.. -I/usr/include/machine
+
++ifeq (,$(findstring USE_OPENSSL_MD5,$(CFLAGS)))
++SRCS+=md5.c
++endif
++
++ifeq (,$(findstring USE_OPENSSL_SHA1,$(CFLAGS)))
++SRCS+=sha1.c
++endif
++
+ lib${LIB}.a: ${SRCS:%.c=%.o}
+ ar cq $@ ${SRCS:%.c=%.o}
+
+diff -urN isakmpd/sysdep/common/libsysdep/md5.c isakmpd.new/sysdep/common/libsysdep/md5.c
+--- isakmpd/sysdep/common/libsysdep/md5.c 2002-06-14 23:34:58.000000000 +0200
++++ isakmpd.new/sysdep/common/libsysdep/md5.c 2006-09-01 19:29:28.000000000 +0200
+@@ -5,6 +5,8 @@
+ * changes to accommodate it in the kernel by ji.
+ */
+
++#ifndef USE_OPENSSL_MD5
++
+ /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ */
+
+@@ -390,3 +392,4 @@
+ #endif
+ #endif
+
++#endif /* USE_OPENSSL_MD5 */
+diff -urN isakmpd/sysdep/common/libsysdep/sha1.c isakmpd.new/sysdep/common/libsysdep/sha1.c
+--- isakmpd/sysdep/common/libsysdep/sha1.c 2001-01-28 23:38:48.000000000 +0100
++++ isakmpd.new/sysdep/common/libsysdep/sha1.c 2006-09-01 19:29:28.000000000 +0200
+@@ -1,5 +1,7 @@
+ /* $OpenBSD: sha1.c,v 1.2 2001/01/28 22:38:48 niklas Exp $ */
+
++#ifndef USE_OPENSSL_SHA1
++
+ /*
+ SHA-1 in C
+ By Steve Reid <steve@edmweb.com>
+@@ -171,3 +173,5 @@
+ SHA1Transform(context->state, context->buffer);
+ #endif
+ }
++
++#endif /* USE_OPENSSL_SHA1 */
+diff -urN isakmpd/sysdep/common/md5.h isakmpd.new/sysdep/common/md5.h
+--- isakmpd/sysdep/common/md5.h 2001-01-28 23:38:47.000000000 +0100
++++ isakmpd.new/sysdep/common/md5.h 2006-09-01 19:29:28.000000000 +0200
+@@ -1,5 +1,15 @@
+ /* $OpenBSD: md5.h,v 1.2 2001/01/28 22:38:47 niklas Exp $ */
+
++#ifdef USE_OPENSSL_MD5
++
++#include <openssl/md5.h>
++
++#define MD5Init MD5_Init
++#define MD5Update MD5_Update
++#define MD5Final MD5_Final
++
++#else /* USE_OPENSSL_MD5 */
++
+ /* GLOBAL.H - RSAREF types and constants
+ */
+
+@@ -71,3 +81,5 @@
+ void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
+
+ #define _MD5_H_
++
++#endif /* USE_OPENSSL_MD5 */
+diff -urN isakmpd/sysdep/common/sha1.h isakmpd.new/sysdep/common/sha1.h
+--- isakmpd/sysdep/common/sha1.h 2001-01-28 23:38:47.000000000 +0100
++++ isakmpd.new/sysdep/common/sha1.h 2006-09-01 19:29:28.000000000 +0200
+@@ -1,5 +1,16 @@
+ /* $OpenBSD: sha1.h,v 1.2 2001/01/28 22:38:47 niklas Exp $ */
+
++#ifdef USE_OPENSSL_SHA1
++
++#include <openssl/sha.h>
++
++typedef SHA_CTX SHA1_CTX;
++#define SHA1Init SHA1_Init
++#define SHA1Update SHA1_Update
++#define SHA1Final SHA1_Final
++
++#else /* USE_OPENSSL_SHA1 */
++
+ /*
+ SHA-1 in C
+ By Steve Reid <steve@edmweb.com>
+@@ -16,3 +27,5 @@
+ void SHA1Init(SHA1_CTX* context);
+ void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len);
+ void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
++
++#endif /* USE_OPENSSL_SHA1 */
+diff -urN isakmpd/sysdep/linux/GNUmakefile.sysdep isakmpd.new/sysdep/linux/GNUmakefile.sysdep
+--- isakmpd/sysdep/linux/GNUmakefile.sysdep 2006-09-01 19:29:05.000000000 +0200
++++ isakmpd.new/sysdep/linux/GNUmakefile.sysdep 2006-09-01 19:29:29.000000000 +0200
+@@ -48,6 +48,8 @@
+ USE_LIBCRYPO= defined
+ HAVE_DLOPEN= defined
+ USE_KEYNOTE= defined
++USE_OPENSSL_MD5= defined
++USE_OPENSSL_SHA1= defined
+
+ # hack libsysdep.a dependenc
+ ${LIBSYSDEPDIR}/.depend ${LIBSYSDEP}:
diff --git a/package/isakmpd/patches/040-security_fix.patch b/package/isakmpd/patches/040-security_fix.patch
new file mode 100644
index 0000000000..9128880107
--- /dev/null
+++ b/package/isakmpd/patches/040-security_fix.patch
@@ -0,0 +1,22 @@
+Index: sbin/isakmpd/ipsec.c
+===================================================================
+RCS file: /cvs/src/sbin/isakmpd/ipsec.c,v
+retrieving revision 1.122
+retrieving revision 1.122.2.1
+diff -u -p -r1.122 -r1.122.2.1
+--- isakmpd/ipsec.c 23 Sep 2005 14:44:03 -0000 1.122
++++ isakmpd/ipsec.c 19 Aug 2006 20:23:28 -0000 1.122.2.1
+@@ -2076,9 +2076,10 @@ ipsec_proto_init(struct proto *proto, ch
+ {
+ struct ipsec_proto *iproto = proto->data;
+
+- if (proto->sa->phase == 2 && section)
+- iproto->replay_window = conf_get_num(section, "ReplayWindow",
+- DEFAULT_REPLAY_WINDOW);
++ if (proto->sa->phase == 2)
++ iproto->replay_window = section ? conf_get_num(section,
++ "ReplayWindow", DEFAULT_REPLAY_WINDOW) :
++ DEFAULT_REPLAY_WINDOW;
+ }
+
+ /*
diff --git a/package/kernel/Makefile b/package/kernel/Makefile
new file mode 100644
index 0000000000..bb9fd4f70f
--- /dev/null
+++ b/package/kernel/Makefile
@@ -0,0 +1,90 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=kernel
+PKG_VERSION:=$(LINUX_VERSION)-$(BOARD)
+PKG_RELEASE:=$(LINUX_RELEASE)
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/packages
+
+include $(INCLUDE_DIR)/package.mk
+ifeq ($(DUMP),)
+ -include $(LINUX_DIR)/.config
+ NF_KMOD:=1
+ include $(INCLUDE_DIR)/netfilter.mk
+endif
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+endef
+
+define Build/Compile
+endef
+
+define KernelPackage/Defaults
+ FILES:=
+ KCONFIG:=m
+ AUTOLOAD:=
+endef
+
+define ModuleAutoLoad
+ export modules=; \
+ add_module() { \
+ mkdir -p $(2)/etc/modules.d; \
+ echo "$$$$$$$$2" > $(2)/etc/modules.d/$$$$$$$$1-$(1); \
+ modules="$$$$$$$${modules:+$$$$$$$$modules }$$$$$$$$1-$(1)"; \
+ }; \
+ $(3) \
+ if [ -n "$$$$$$$$modules" ]; then \
+ mkdir -p $(2)/etc/modules.d; \
+ echo "#!/bin/sh" > $(2)/CONTROL/postinst; \
+ echo "[ -z \"\$$$$$$$$IPKG_INSTROOT\" ] || exit 0" >> $(2)/CONTROL/postinst; \
+ echo ". /etc/functions.sh" >> $(2)/CONTROL/postinst; \
+ echo "load_modules $$$$$$$$modules" >> $(2)/CONTROL/postinst; \
+ chmod 0755 $(2)/CONTROL/postinst; \
+ fi
+endef
+
+
+define KernelPackage
+ NAME:=$(1)
+ $(eval $(call KernelPackage/Defaults))
+ $(eval $(call KernelPackage/$(1)))
+ $(eval $(call KernelPackage/$(1)/$(KERNEL)))
+
+ define Package/kmod-$(1)
+ TITLE:=$(TITLE)
+ SECTION:=kernel
+ CATEGORY:=Kernel modules
+ DEFAULT:=m
+ DESCRIPTION:=$(DESCRIPTION)
+ EXTRA_DEPENDS:='kernel (=$(PKG_VERSION)-$(PKG_RELEASE))'
+ $(call KernelPackage/$(1))
+ $(call KernelPackage/$(1)/$(KERNEL))
+ endef
+
+ ifeq ($(findstring m,$(KCONFIG)),m)
+ ifneq ($(strip $(FILES)),)
+ define Package/kmod-$(1)/install
+ mkdir -p $$(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) $$(FILES) $$(1)/lib/modules/$(LINUX_VERSION)/
+ $(call ModuleAutoLoad,$(1),$$(1),$(AUTOLOAD))
+ endef
+ endif
+ endif
+ $$(eval $$(call BuildPackage,kmod-$(1)))
+endef
+
+define AutoLoad
+ add_module $(1) "$(2)";
+endef
+
+include ./modules.mk
diff --git a/package/kernel/modules.mk b/package/kernel/modules.mk
new file mode 100644
index 0000000000..7449cb3e1b
--- /dev/null
+++ b/package/kernel/modules.mk
@@ -0,0 +1,506 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+
+define KernelPackage/crypto
+ TITLE:=CryptoAPI modules
+ KCONFIG:= \
+ $(CONFIG_CRYPTO_HMAC) \
+ $(CONFIG_CRYPTO_NULL) \
+ $(CONFIG_CRYPTO_MD4) \
+ $(CONFIG_CRYPTO_MD5) \
+ $(CONFIG_CRYPTO_SHA1) \
+ $(CONFIG_CRYPTO_SHA256) \
+ $(CONFIG_CRYPTO_SHA512) \
+ $(CONFIG_CRYPTO_WP512) \
+ $(CONFIG_CRYPTO_TGR192) \
+ $(CONFIG_CRYPTO_DES) \
+ $(CONFIG_CRYPTO_BLOWFISH) \
+ $(CONFIG_CRYPTO_TWOFISH) \
+ $(CONFIG_CRYPTO_SERPENT) \
+ $(CONFIG_CRYPTO_AES) \
+ $(CONFIG_CRYPTO_CAST5) \
+ $(CONFIG_CRYPTO_CAST6) \
+ $(CONFIG_CRYPTO_TEA) \
+ $(CONFIG_CRYPTO_ARC4) \
+ $(CONFIG_CRYPTO_KHAZAD) \
+ $(CONFIG_CRYPTO_ANUBIS) \
+ $(CONFIG_CRYPTO_DEFLATE) \
+ $(CONFIG_CRYPTO_MICHAEL_MIC) \
+ $(CONFIG_CRYPTO_CRC32C)
+ FILES:=$(MODULES_DIR)/kernel/crypto/*.$(LINUX_KMOD_SUFFIX)
+endef
+$(eval $(call KernelPackage,crypto))
+
+define KernelPackage/ide-core
+ TITLE:=Kernel support for IDE
+ DESCRIPTION:=\
+ Useful for usb mass storage devices (e.g. on WL-HDD)\\\
+ \\\
+ Includes: \\\
+ - ide-core \\\
+ - ide-detect \\\
+ - ide-disk
+ KCONFIG:=$(CONFIG_IDE)
+ FILES:=$(MODULES_DIR)/kernel/drivers/ide/*.$(LINUX_KMOD_SUFFIX)
+ AUTOLOAD:=$(call AutoLoad,20,ide-core) $(call AutoLoad,90,ide-detect ide-disk)
+endef
+$(eval $(call KernelPackage,ide-core))
+
+define KernelPackage/ide-pdc202xx
+ TITLE:=PDC202xx IDE driver
+ KCONFIG:=$(CONFIG_BLK_DEV_PDC202XX_OLD)
+ FILES:=$(MODULES_DIR)/kernel/drivers/ide/pci/pdc202xx_old.$(LINUX_KMOD_SUFFIX)
+ AUTOLOAD:=$(call AutoLoad,30,pdc202xx_old)
+endef
+$(eval $(call KernelPackage,ide-pdc202xx))
+
+
+define KernelPackage/lp
+ TITLE:=Parallel port and line printer support
+ KCONFIG:=$(CONFIG_PARPORT)
+ FILES:= \
+ $(MODULES_DIR)/kernel/drivers/parport/parport.o \
+ $(MODULES_DIR)/kernel/drivers/parport/parport_splink.o \
+ $(MODULES_DIR)/kernel/drivers/char/lp.o \
+ $(MODULES_DIR)/kernel/drivers/char/ppdev.o
+ AUTOLOAD:=$(call AutoLoad,50, \
+ parport \
+ parport_splink \
+ lp \
+ )
+endef
+$(eval $(call KernelPackage,lp))
+
+
+define KernelPackage/ieee80211softmac
+ TITLE:=802.11 Networking stack
+ DESCRIPTION:=\\\
+ \\\
+ Includes: \\\
+ - ieee80211_crypt \\\
+ - ieee80211 \\\
+ - ieee80211_crypt_wep \\\
+ - ieee80211_crypt_tkip \\\
+ - ieee80211_crytp_ccmp \\\
+ - ieee80211softmac
+ KCONFIG:=$(CONFIG_IEEE80211_SOFTMAC)
+ FILES:=$(MODULES_DIR)/kernel/net/ieee80211/*.$(LINUX_KMOD_SUFFIX) $(MODULES_DIR)/kernel/net/ieee80211/softmac/*.$(LINUX_KMOD_SUFFIX)
+ AUTOLOAD:=$(call AutoLoad,10, \
+ ieee80211_crypt \
+ ieee80211 \
+ ieee80211_crypt_wep \
+ ieee80211_crypt_tkip \
+ ieee80211_crypt_ccmp \
+ ieee80211softmac \
+ )
+endef
+$(eval $(call KernelPackage,ieee80211softmac))
+
+
+WIMENU:=Wireless drivers
+
+define KernelPackage/bcm43xx
+ TITLE:=Broadcom BCM43xx driver
+ DESCRIPTION:=\\\
+ \\\
+ Includes: \\\
+ - bcm43xx
+ KCONFIG:=$(CONFIG_BCM43XX)
+ FILES:=$(MODULES_DIR)/kernel/drivers/net/wireless/bcm43xx/bcm43xx.$(LINUX_KMOD_SUFFIX)
+ AUTOLOAD:=$(call Autoload,50,bcm43xx)
+ SUBMENU:=$(WIMENU)
+endef
+$(eval $(call KernelPackage,bcm43xx))
+
+define KernelPackage/ipw2100
+ TITLE:=Intel IPw2100 driver
+ DESCRIPTION:=\\\
+ \\\
+ Includes: \\\
+ - ipw2100
+ KCONFIG:=$(CONFIG_IPW2100)
+ FILES:=$(MODULES_DIR)/kernel/drivers/net/wireless/ipw2100.$(LINUX_KMOD_SUFFIX)
+ AUTOLOAD:=$(call Autoload,50,ipw2100)
+ SUBMENU:=$(WIMENU)
+endef
+$(eval $(call KernelPackage,ipw2100))
+
+define KernelPackage/ipw2200
+ TITLE:=Intel IPw2200 driver
+ DESCRIPTION:=\\\
+ \\\
+ Includes: \\\
+ - ipw2200
+ KCONFIG:=$(CONFIG_IPW2200)
+ FILES:=$(MODULES_DIR)/kernel/drivers/net/wireless/ipw2200.$(LINUX_KMOD_SUFFIX)
+ AUTOLOAD:=$(call Autoload,50,ipw2200)
+ SUBMENU:=$(WIMENU)
+endef
+$(eval $(call KernelPackage,ipw2200))
+
+
+NFMENU:=Netfilter Extensions
+
+define KernelPackage/ipt-conntrack
+ TITLE:=Modules for connection tracking
+ DESCRIPTION:=\
+ Netfilter (IPv4) kernel modules for connection tracking\\\
+ \\\
+ Includes: \\\
+ - ipt_conntrack \\\
+ - ipt_helper \\\
+ - ipt_connmark/CONNMARK
+ FILES:=$(foreach mod,$(IPT_CONNTRACK-m),$(MODULES_DIR)/kernel/net/$(mod).$(LINUX_KMOD_SUFFIX))
+ SUBMENU:=$(NFMENU)
+endef
+$(eval $(call KernelPackage,ipt-conntrack))
+
+define KernelPackage/ipt-filter
+ TITLE:=Modules for packet content inspection
+ DESCRIPTION:=\
+ Netfilter (IPv4) kernel modules for packet content inspection \\\
+ \\\
+ Includes: \\\
+ - ipt_ipp2p \\\
+ - ipt_layer7
+ FILES:=$(foreach mod,$(IPT_FILTER-m),$(MODULES_DIR)/kernel/net/$(mod).$(LINUX_KMOD_SUFFIX))
+ SUBMENU:=$(NFMENU)
+endef
+$(eval $(call KernelPackage,ipt-filter))
+
+define KernelPackage/ipt-ipopt
+ TITLE:=Modules for matching/changing IP packet options
+ DESCRIPTION:=\
+ Netfilter (IPv4) modules for matching/changing IP packet options \\\
+ \\\
+ Includes: \\\
+ - ipt_dscp/DSCP \\\
+ - ipt_ecn/ECN \\\
+ - ipt_length \\\
+ - ipt_mac \\\
+ - ipt_tos/TOS \\\
+ - ipt_tcpmms \\\
+ - ipt_ttl/TTL \\\
+ - ipt_unclean
+ FILES:=$(foreach mod,$(IPT_IPOPT-m),$(MODULES_DIR)/kernel/net/$(mod).$(LINUX_KMOD_SUFFIX))
+ SUBMENU:=$(NFMENU)
+endef
+$(eval $(call KernelPackage,ipt-ipopt))
+
+define KernelPackage/ipt-ipsec
+ TITLE:=Modules for matching IPSec packets
+ DESCRIPTION:=\
+ Netfilter (IPv4) modules for matching IPSec packets \\\
+ \\\
+ Includes: \\\
+ - ipt_ah \\\
+ - ipt_esp
+ FILES:=$(foreach mod,$(IPT_IPSEC-m),$(MODULES_DIR)/kernel/net/$(mod).$(LINUX_KMOD_SUFFIX))
+ SUBMENU:=$(NFMENU)
+endef
+$(eval $(call KernelPackage,ipt-ipsec))
+
+define KernelPackage/ipt-nat
+ TITLE:=Modules for extra NAT targets
+ DESCRIPTION:=\
+ Netfilter (IPv4) modules for extra NAT targets \\\
+ \\\
+ Includes: \\\
+ - ipt_REDIRECT \\\
+ - ipt_NETMAP
+ FILES:=$(foreach mod,$(IPT_NAT-m),$(MODULES_DIR)/kernel/net/$(mod).$(LINUX_KMOD_SUFFIX))
+ SUBMENU:=$(NFMENU)
+endef
+$(eval $(call KernelPackage,ipt-nat))
+
+define KernelPackage/ipt-nathelper
+ TITLE:=Extra Conntrack and NAT helpers
+ DESCRIPTION:=\
+ Extra Netfilter (IPv4) Conntrack and NAT helpers \\\
+ \\\
+ Includes: \\\
+ - ip_conntrack_amanda \\\
+ - ip_conntrack_proto_gre \\\
+ - ip_nat_proto_gre \\\
+ - ip_conntrack_pptp \\\
+ - ip_nat_pptp \\\
+ - ip_conntrack_sip \\\
+ - ip_nat_sip \\\
+ - ip_nat_snmp_basic \\\
+ - ip_conntrack_tftp
+ FILES:=$(foreach mod,$(IPT_NAT_EXTRA-m),$(MODULES_DIR)/kernel/net/$(mod).$(LINUX_KMOD_SUFFIX))
+ SUBMENU:=$(NFMENU)
+endef
+$(eval $(call KernelPackage,ipt-nathelper))
+
+define KernelPackage/ipt-imq
+ TITLE:=Intermediate Queueing support
+ DESCRIPTION:=\
+ Kernel support for Intermediate Queueing devices
+ KCONFIG:=$(CONFIG_IP_NF_TARGET_IMQ)
+ FILES:=$(MODULES_DIR)/kernel/net/ipv4/netfilter/*IMQ*.$(LINUX_KMOD_SUFFIX) $(MODULES_DIR)/kernel/drivers/net/imq.$(LINUX_KMOD_SUFFIX)
+ SUBMENU:=$(NFMENU)
+endef
+$(eval $(call KernelPackage,ipt-imq))
+
+
+define KernelPackage/ipt-queue
+ TITLE:=Module for user-space packet queueing
+ DESCRIPTION:=\
+ Netfilter (IPv4) module for user-space packet queueing \\\
+ \\\
+ Includes: \\\
+ - ipt_QUEUE
+ FILES:=$(foreach mod,$(IPT_QUEUE-m),$(MODULES_DIR)/kernel/net/$(mod).$(LINUX_KMOD_SUFFIX))
+ SUBMENU:=$(NFMENU)
+endef
+$(eval $(call KernelPackage,ipt-queue))
+
+define KernelPackage/ipt-ulog
+ TITLE:=Module for user-space packet logging
+ DESCRIPTION:=\
+ Netfilter (IPv4) module for user-space packet logging \\\
+ \\\
+ Includes: \\\
+ - ipt_ULOG
+ FILES:=$(foreach mod,$(IPT_ULOG-m),$(MODULES_DIR)/kernel/net/$(mod).$(LINUX_KMOD_SUFFIX))
+ SUBMENU:=$(NFMENU)
+endef
+$(eval $(call KernelPackage,ipt-ulog))
+
+define KernelPackage/ipt-extra
+ TITLE:=Extra modules
+ DESCRIPTION:=\
+ Other Netfilter (IPv4) kernel modules\\\
+ Includes: \\\
+ - ipt_limit \\\
+ - ipt_owner \\\
+ - ipt_physdev \\\
+ - ipt_pkttype \\\
+ - ipt_recent
+ FILES:=$(foreach mod,$(IPT_EXTRA-m),$(MODULES_DIR)/kernel/net/$(mod).$(LINUX_KMOD_SUFFIX))
+ SUBMENU:=$(NFMENU)
+endef
+$(eval $(call KernelPackage,ipt-extra))
+
+define KernelPackage/ip6tables
+ TITLE:=IPv6 modules
+ DESCRIPTION:=\
+ Netfilter IPv6 firewalling support
+ KCONFIG:=$(CONFIG_IP6_NF_IPTABLES)
+ FILES:=$(MODULES_DIR)/kernel/net/ipv6/netfilter/ip*.$(LINUX_KMOD_SUFFIX)
+ SUBMENU:=$(NFMENU)
+endef
+$(eval $(call KernelPackage,ip6tables))
+
+
+define KernelPackage/arptables
+ TITLE:=ARP firewalling modules
+ DESCRIPTION:=\
+ Kernel modules for ARP firewalling
+ FILES:=$(MODULES_DIR)/kernel/net/ipv4/netfilter/arp*.$(LINUX_KMOD_SUFFIX)
+ KCONFIG:=$(CONFIG_IP_NF_ARPTABLES)
+ SUBMENU:=$(NFMENU)
+endef
+$(eval $(call KernelPackage,arptables))
+
+
+define KernelPackage/ebtables
+ TITLE:=Bridge firewalling modules
+ DESCRIPTION:=\
+ Kernel modules for Ethernet Bridge firewalling
+ FILES:=$(MODULES_DIR)/kernel/net/bridge/netfilter/*.$(LINUX_KMOD_SUFFIX)
+ KCONFIG:=$(CONFIG_BRIDGE_NF_EBTABLES)
+ SUBMENU:=$(NFMENU)
+endef
+$(eval $(call KernelPackage,ebtables))
+
+define KernelPackage/ipip
+ TITLE:=IP in IP encapsulation support
+ DESCRIPTION:=\
+ Kernel modules for IP in IP encapsulation
+ FILES:=$(MODULES_DIR)/kernel/net/ipv4/ipip.$(LINUX_KMOD_SUFFIX)
+ KCONFIG:=$(CONFIG_NET_IPIP)
+endef
+$(eval $(call KernelPackage,ipip))
+
+
+define KernelPackage/ipv6
+ TITLE:=IPv6 support
+ DESCRIPTION:=\
+ Kernel modules for IPv6 support
+ KCONFIG:=$(CONFIG_IPV6)
+ FILES:=$(MODULES_DIR)/kernel/net/ipv6/ipv6.$(LINUX_KMOD_SUFFIX)
+endef
+$(eval $(call KernelPackage,ipv6))
+
+
+define KernelPackage/gre
+ TITLE:=GRE support
+ DESCRIPTION:=\
+ Generic Routing Encapsulation support
+ KCONFIG=$(CONFIG_NET_IPGRE)
+ FILES=$(MODULES_DIR)/kernel/net/ipv4/ip_gre.$(LINUX_KMOD_SUFFIX)
+endef
+$(eval $(call KernelPackage,gre))
+
+
+define KernelPackage/tun
+ TITLE:=Universal TUN/TAP driver
+ DESCRIPTION:=\
+ Kernel support for the TUN/TAP tunneling device
+ KCONFIG:=$(CONFIG_TUN)
+ FILES:=$(MODULES_DIR)/kernel/drivers/net/tun.$(LINUX_KMOD_SUFFIX)
+endef
+$(eval $(call KernelPackage,tun))
+
+
+define KernelPackage/ppp
+ TITLE:=PPP modules
+ DESCRIPTION:=\
+ Kernel modules for PPP support
+ KCONFIG:=$(CONFIG_PPP)
+endef
+
+define KernelPackage/ppp/2.6
+ FILES:=$(MODULES_DIR)/kernel/drivers/net/ppp_async.ko $(MODULES_DIR)/kernel/drivers/net/ppp_generic.ko $(MODULES_DIR)/kernel/drivers/net/slhc.ko $(MODULES_DIR)/kernel/lib/crc-ccitt.ko
+ AUTOLOAD:=$(call AutoLoad,30,crc-ccitt)
+endef
+
+define KernelPackage/ppp/2.4
+ FILES:=$(MODULES_DIR)/kernel/drivers/net/ppp_async.o $(MODULES_DIR)/kernel/drivers/net/ppp_generic.o $(MODULES_DIR)/kernel/drivers/net/slhc.o
+endef
+$(eval $(call KernelPackage,ppp))
+
+
+define KernelPackage/pppoe
+ TITLE:=PPPoE support
+ DESCRIPTION:=\
+ Kernel modules for PPPoE (PPP over Ethernet) support
+ DEPENDS:=kmod-ppp
+ KCONFIG:=$(CONFIG_PPPOE)
+ FILES:=$(MODULES_DIR)/kernel/drivers/net/pppoe.$(LINUX_KMOD_SUFFIX) $(MODULES_DIR)/kernel/drivers/net/pppox.$(LINUX_KMOD_SUFFIX)
+endef
+$(eval $(call KernelPackage,pppoe))
+
+
+define KernelPackage/pppoa
+ TITLE:=PPPoA support
+ DESCRIPTION:=\
+ Kernel modules for PPPoA (PPP over ATM) support
+ DEPENDS:=kmod-ppp
+ KCONFIG:=$(CONFIG_PPPOATM)
+ FILES:=$(MODULES_DIR)/kernel/net/atm/pppoatm.$(LINUX_KMOD_SUFFIX)
+endef
+$(eval $(call KernelPackage,pppoa))
+
+
+define KernelPackage/mppe
+ TITLE:=Microsoft PPP compression/encryption
+ DESCRIPTION:=Kernel modules for Microsoft PPP compression/encryption
+ DEPENDS:=kmod-ppp
+ KCONFIG:=$(CONFIG_PPP_MPPE)
+endef
+
+define KernelPackage/mppe/2.4
+ FILES:=$(MODULES_DIR)/kernel/drivers/net/ppp_mppe_mppc.$(LINUX_KMOD_SUFFIX)
+endef
+
+define KernelPackage/mppe/2.6
+ FILES:=$(MODULES_DIR)/kernel/drivers/net/ppp_mppe.$(LINUX_KMOD_SUFFIX)
+endef
+$(eval $(call KernelPackage,mppe))
+
+
+define KernelPackage/sched
+ TITLE:=Traffic schedulers
+ DESCRIPTION:=\
+ Kernel schedulers for IP traffic
+ FILES:=$(MODULES_DIR)/kernel/net/sched/*.$(LINUX_KMOD_SUFFIX)
+endef
+$(eval $(call KernelPackage,sched))
+
+
+
+NDMENU:=Network Devices
+
+define KernelPackage/natsemi
+ TITLE:=National Semiconductor DP8381x series
+ DESCRIPTION:=\
+ Kernel modules for National Semiconductor DP8381x series PCI Ethernet \\\
+ adapters.
+ FILES:=$(MODULES_DIR)/kernel/drivers/net/natsemi.$(LINUX_KMOD_SUFFIX)
+ KCONFIG:=$(CONFIG_NATSEMI)
+ DEPENDS:=@LINUX_2_6_X86
+ DEFAULT:=y
+ SUBMENU:=$(NDMENU)
+ AUTOLOAD:=$(call AutoLoad,20,natsemi)
+endef
+$(eval $(call KernelPackage,natsemi))
+
+define KernelPackage/sis900
+ TITLE:=SiS 900 Ethernet support
+ DESCRIPTION:=\
+ Kernel modules for Sis 900 Ethernet adapters.
+ FILES:=$(MODULES_DIR)/kernel/drivers/net/sis900.$(LINUX_KMOD_SUFFIX)
+ KCONFIG:=$(CONFIG_SIS900)
+ DEPENDS:=@LINUX_2_6_X86||LINUX_2_4_X86
+ SUBMENU:=$(NDMENU)
+endef
+$(eval $(call KernelPackage,sis900))
+
+define KernelPackage/via-rhine
+ TITLE:=Via Rhine ethernet support
+ DESCRIPTION:=\
+ Kernel modules for Via Rhine Ethernet chipsets.
+ FILES:=$(MODULES_DIR)/kernel/drivers/net/via-rhine.$(LINUX_KMOD_SUFFIX)
+ KCONFIG:=$(CONFIG_VIA_RHINE)
+ DEPENDS:=@LINUX_2_6_X86||LINUX_2_4_X86
+ SUBMENU:=$(NDMENU)
+endef
+$(eval $(call KernelPackage,via-rhine))
+
+define KernelPackage/8139too
+ TITLE:=RealTek RTL-8139 PCI Fast Ethernet Adapter kernel support
+ DESCRIPTION:=\
+ Kernel modules for RealTek RTL-8139 PCI Fast Ethernet adapters.
+ FILES:=$(MODULES_DIR)/kernel/drivers/net/8139too.$(LINUX_KMOD_SUFFIX)
+ KCONFIG:=$(CONFIG_8139TOO)
+ DEPENDS:=@LINUX_2_6_X86||LINUX_2_4_X86
+ SUBMENU:=$(NDMENU)
+endef
+$(eval $(call KernelPackage,8139too))
+
+define KernelPackage/e100
+ TITLE:=Intel(R) PRO/100+ cards kernel support
+ DESCRIPTION:=\
+ Kernel modules for Intel(R) PRO/100+ Ethernet adapters.
+ FILES:=$(MODULES_DIR)/kernel/drivers/net/e100.$(LINUX_KMOD_SUFFIX)
+ KCONFIG:=$(CONFIG_E100)
+ DEPENDS:=@LINUX_2_6_X86||LINUX_2_4_X86
+ SUBMENU:=$(NDMENU)
+endef
+$(eval $(call KernelPackage,e100))
+
+define KernelPackage/3c59x
+ TITLE:=3Com 3c590/3c900 series (592/595/597) Vortex/Boomerang
+ 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
+ FILES:=$(MODULES_DIR)/kernel/drivers/net/3c59x.$(LINUX_KMOD_SUFFIX)
+ KCONFIG:=$(CONFIG_3C59X)
+ DEPENDS:=@LINUX_2_6_X86||LINUX_2_4_X86
+ SUBMENU:=$(NDMENU)
+endef
+$(eval $(call KernelPackage,3c59x))
diff --git a/package/keynote/Makefile b/package/keynote/Makefile
new file mode 100644
index 0000000000..38f1f6901d
--- /dev/null
+++ b/package/keynote/Makefile
@@ -0,0 +1,68 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 4619 2006-08-22 09:50:02Z florian $
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=keynote
+PKG_VERSION:=2.3
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://downloads.openwrt.org/sources/
+PKG_MD5SUM:=b569066ac2ba1356c2112b118a7d74d0
+PKG_CAT:=bzcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+define Package/keynote
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=@LINUX_2_6 +libopenssl
+ TITLE:=Simple and flexible trust-management system
+ DESCRIPTION:=\
+ KeyNote is a simple and flexible trust-management system designed to work \\\
+ well for a variety of large- and small- scale Internet-based applications.\\\
+ It provides a single, unified language for both local policies and \\\
+ credentials.
+ URL:=http://www1.cs.columbia.edu/~angelos/keynote.html
+endef
+
+define Build/Configure
+ $(call Build/Configure/Default, \
+ --enable-static \
+ --enable-shared \
+ )
+endef
+
+define Build/Compile
+ $(call Build/Compile/Default, \
+ CFLAGS="\$$$$(EXTRA_CFLAGS) \$$$$(EXTRA_LDFLAGS)" \
+ )
+endef
+
+define Build/InstallDev
+ mkdir -p $(STAGING_DIR)/usr/include
+ $(CP) $(PKG_BUILD_DIR)/{assertion,header,keynote,signature}.h $(STAGING_DIR)/usr/include/
+ mkdir -p $(STAGING_DIR)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/libkeynote.a $(STAGING_DIR)/usr/lib/
+endef
+
+define Build/UninstallDev
+ rm -rf $(STAGING_DIR)/usr/include/keynote \
+ $(STAGING_DIR)/usr/lib/libkeynote.a
+endef
+
+define Package/keynote/install
+ install -d -m0755 $(1)/usr/sbin
+ $(CP) $(PKG_BUILD_DIR)/keynote $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,keynote))
diff --git a/package/keynote/patches/01-build.patch b/package/keynote/patches/01-build.patch
new file mode 100644
index 0000000000..05351f714c
--- /dev/null
+++ b/package/keynote/patches/01-build.patch
@@ -0,0 +1,327 @@
+diff -ru keynote-2.3/configure.in keynote-2.3.new/configure.in
+--- keynote-2.3/configure.in 2000-09-27 01:16:28.000000000 +0200
++++ keynote-2.3.new/configure.in 2004-01-16 11:34:03.991537404 +0100
+@@ -21,19 +21,13 @@
+ AC_PATH_PROG(ECHO, echo, /bin/echo)
+ AC_PATH_PROG(SED, sed, /usr/bin/sed)
+
+-dnl Checks for libraries.
+-LIBS="-L/usr/lib -L/usr/local/lib -L/usr/ssl/lib -L/usr/openssl/lib\
+- -L/usr/local/ssl/lib -L/usr/local/openssl/lib -L/usr/pkg/lib -L/pkg/lib"
+-
+ AC_CHECK_LIB(m, floor, LIBS="$LIBS -lm")
+ AC_CHECK_LIB(rsaref, RSAPrivateDecrypt, LIBS="$LIBS -lrsaref")
+ AC_CHECK_LIB(crypto, i2a_ASN1_STRING, LIBS="$LIBS -lcrypto")
+ AC_CHECK_LIB(RSAglue, RSA_ref_private_encrypt, LIBS="$LIBS -lRSAglue")
+
+ dnl Checks for header files.
+-CPPFLAGS="-I/usr/include -I/usr/local/include -I/usr/ssl/include\
+- -I/usr/local/ssl/include -I/usr/openssl/include -I/usr/pkg/include\
+- -I/usr/local/openssl/include -I/pkg/include"
++CPPFLAGS="-I/usr/include/openssl"
+
+ AC_HEADER_STDC
+ AC_HEADER_TIME
+diff -ru keynote-2.3/keynote-keygen.c keynote-2.3.new/keynote-keygen.c
+--- keynote-2.3/keynote-keygen.c 2000-09-27 02:09:13.000000000 +0200
++++ keynote-2.3.new/keynote-keygen.c 2004-01-16 11:32:06.652242269 +0100
+@@ -161,7 +161,7 @@
+ if (strlen(algname) + 2 > prlen)
+ {
+ fprintf(stderr, "Parameter ``print-length'' should be larger "
+- "than the length of AlgorithmName (%d)\n", strlen(algname));
++ "than the length of AlgorithmName (%lu)\n", strlen(algname));
+ exit(-1);
+ }
+
+diff -ru keynote-2.3/keynote.l keynote-2.3.new/keynote.l
+--- keynote-2.3/keynote.l 2000-08-11 22:49:13.000000000 +0200
++++ keynote-2.3.new/keynote.l 2004-01-16 11:17:29.910430978 +0100
+@@ -61,7 +61,8 @@ struct lex_list
+ static struct lex_list *keynote_lex_list = (struct lex_list *) NULL;
+ static int keynote_max_lex_list = 32;
+ static int keynote_lex_counter = 0;
+-static int first_tok = 0;
++extern int first_tok;
++int first_tok = 0;
+ %}
+ digit [0-9]
+ specnumber [1-9][0-9]*
+@@ -766,7 +767,7 @@
+ if (0)
+ {
+ yyunput(0, NULL);
+- yy_flex_realloc(0, NULL);
++ yy_flex_realloc(NULL, 0);
+ }
+
+ return en;
+diff -ru keynote-2.3/keynote-ver.l keynote-2.3.new/keynote-ver.l
+--- keynote-2.3/keynote-ver.l 2000-08-11 22:49:13.000000000 +0200
++++ keynote-2.3.new/keynote-ver.l 2004-01-16 11:31:14.667107044 +0100
+@@ -267,7 +267,7 @@
+ if (0)
+ {
+ yyunput(0, NULL);
+- yy_flex_realloc(0, NULL);
++ yy_flex_realloc(NULL, 0);
+ }
+ }
+
+diff -ru keynote-2.3/keynote-ver.y keynote-2.3.new/keynote-ver.y
+--- keynote-2.3/keynote-ver.y 1999-10-12 00:34:29.000000000 +0200
++++ keynote-2.3.new/keynote-ver.y 2004-01-16 11:07:19.709634736 +0100
+@@ -49,7 +49,7 @@
+ return keynote_errno;
+ free($1);
+ }
+-
++ ;
+ expr: VSTRING EQ STRING { int i = kn_add_action(sessid, $1, $3, 0);
+
+ if (i != 0)
+@@ -64,6 +64,7 @@
+ free($1);
+ free($3);
+ } expr
++ ;
+ %%
+ void
+ kverror(char *s)
+diff -ru keynote-2.3/keynote.y keynote-2.3.new/keynote.y
+--- keynote-2.3/keynote.y 2000-06-14 08:28:23.000000000 +0200
++++ keynote-2.3.new/keynote.y 2004-01-16 11:14:55.365898229 +0100
+@@ -73,8 +73,7 @@
+ %}
+ %%
+
+-grammarswitch: LOCINI { keynote_exceptionflag = keynote_donteval = 0; }
+- localinit
++grammarswitch: LOCINI { keynote_exceptionflag = keynote_donteval = 0; } localinit
+ | ACTSTR { keynote_exceptionflag = keynote_donteval = 0; } program
+ | KEYPRE { keynote_exceptionflag = keynote_donteval = 0; }
+ keypredicate
+@@ -91,17 +90,17 @@
+ STRING { keynote_lex_remove($3);
+ keynote_privkey = $3;
+ }
+-
++ ;
+ keypredicate: /* Nothing */ { keynote_returnvalue = 0;
+ return 0;
+ }
+ | notemptykeypredicate { keynote_returnvalue = $1;
+ return 0;
+ }
+-
++ ;
+ notemptykeypredicate: key { $$ = $1; }
+ | keyexp { $$ = $1; }
+-
++ ;
+ keyexp: notemptykeypredicate AND { if (($1 == 0) && !keynote_justrecord)
+ keynote_donteval = 1;
+ } notemptykeypredicate
+@@ -138,7 +137,7 @@
+ else
+ $$ = 0;
+ } /* K-th */
+-
++ ;
+ keylist: key
+ { /* Don't do anything if we're just recording */
+ if (!keynote_justrecord && !keynote_donteval)
+@@ -155,7 +154,7 @@
+
+ keylistcount++;
+ }
+-
++ ;
+ key: str {
+ if (keynote_donteval)
+ $$ = 0;
+@@ -193,10 +192,10 @@
+ }
+ }
+ }
+-
++ ;
+ localinit: /* Nothing */
+ | localconstants
+-
++ ;
+ localconstants: VARIABLE EQQ STRING
+ {
+ int i;
+@@ -265,12 +264,12 @@
+ if (i != RESULT_TRUE)
+ return -1;
+ } localconstants
+-
++ ;
+ program: prog {
+ keynote_returnvalue = $1;
+ return 0;
+ }
+-
++ ;
+ prog: /* Nada */ { $$ = 0; }
+ | notemptyprog {
+ /*
+@@ -285,7 +284,7 @@
+ else
+ $$ = $4;
+ }
+-
++ ;
+ notemptyprog: expr HINT afterhint
+ {
+ if (checkexception($1))
+@@ -300,7 +299,7 @@
+ else
+ $$ = 0;
+ }
+-
++ ;
+ afterhint: str { if (keynote_exceptionflag || keynote_donteval)
+ $$ = 0;
+ else
+@@ -315,7 +314,7 @@
+ }
+ }
+ | OPENBLOCK prog CLOSEBLOCK { $$ = $2; }
+-
++ ;
+
+ expr: OPENPAREN expr CLOSEPAREN { $$ = $2; }
+ | expr AND { if ($1 == 0)
+@@ -334,19 +333,19 @@
+ | stringexp { $$ = $1; }
+ | TRUE { $$ = 1; }
+ | FALSE { $$ = 0; }
+-
++ ;
+ numexp: numex LT numex { $$ = $1 < $3; }
+ | numex GT numex { $$ = $1 > $3; }
+ | numex EQ numex { $$ = $1 == $3; }
+ | numex LE numex { $$ = $1 <= $3; }
+ | numex GE numex { $$ = $1 >= $3; }
+ | numex NE numex { $$ = $1 != $3; }
+-
++ ;
+ floatexp: floatex LT floatex { $$ = $1 < $3; }
+ | floatex GT floatex { $$ = $1 > $3; }
+ | floatex LE floatex { $$ = $1 <= $3; }
+ | floatex GE floatex { $$ = $1 >= $3; }
+-
++ ;
+ numex: numex PLUS numex { $$ = $1 + $3; }
+ | numex MINUS numex { $$ = $1 - $3; }
+ | numex MULT numex { $$ = $1 * $3; }
+@@ -384,7 +383,7 @@
+ free($2);
+ }
+ }
+-
++ ;
+ floatex: floatex PLUS floatex { $$ = ($1 + $3); }
+ | floatex MINUS floatex { $$ = ($1 - $3); }
+ | floatex MULT floatex { $$ = ($1 * $3); }
+@@ -418,7 +417,7 @@
+ free($2);
+ }
+ }
+-
++ ;
+ stringexp: str EQ str {
+ if (keynote_exceptionflag || keynote_donteval)
+ $$ = 0;
+@@ -529,9 +528,9 @@
+ if (i == 0)
+ {
+ #if !defined(HAVE_SNPRINTF)
+- sprintf(grp, "%d", preg.re_nsub);
++ sprintf(grp, "%d", (int)preg.re_nsub);
+ #else /* !HAVE_SNPRINTF */
+- snprintf(grp, 3, "%d", preg.re_nsub);
++ snprintf(grp, 3, "%d", (int)preg.re_nsub);
+ #endif /* !HAVE_SNPRINTF */
+ if (keynote_env_add("_0", grp, &keynote_temp_list,
+ 1, 0) != RESULT_TRUE)
+@@ -579,7 +578,7 @@
+ }
+ }
+ }
+-
++ ;
+ str: str DOTT str { if (keynote_exceptionflag || keynote_donteval)
+ $$ = (char *) NULL;
+ else
+@@ -605,7 +604,7 @@
+ }
+ }
+ | strnotconcat { $$ = $1; }
+-
++ ;
+ strnotconcat: STRING { $$ = $1; }
+ | OPENPAREN str CLOSEPAREN { $$ = $2; }
+ | VARIABLE { if (keynote_exceptionflag || keynote_donteval)
+@@ -660,6 +659,7 @@
+ return -1;
+ }
+ }
++ ;
+ %%
+
+ /*
+diff -ru keynote-2.3/Makefile.in keynote-2.3.new/Makefile.in
+--- keynote-2.3/Makefile.in 2000-09-27 01:16:27.000000000 +0200
++++ keynote-2.3.new/Makefile.in 2004-01-16 11:35:38.841528129 +0100
+@@ -41,7 +41,7 @@
+ YACCFLAGS = -d -p kn -b k
+ LEXFLAGS2 = -Pkv -s -i
+ LEXFLAGS = -Cr -Pkn -s -i
+-CFLAGS = -O2 -Wall # -g
++CFLAGS = -O2 -Wall -fno-strict-aliasing # -g
+ RMFLAGS2 = -rf
+ RMFLAGS = -f
+ NROFFFLAGS = -mandoc
+diff -ru keynote-2.3/signature.c keynote-2.3.new/signature.c
+--- keynote-2.3/signature.c 1999-10-12 00:34:31.000000000 +0200
++++ keynote-2.3.new/signature.c 2004-01-16 11:30:48.062084986 +0100
+@@ -515,7 +515,7 @@
+ kk = dc->dec_key;
+ if (keytype == KEYNOTE_PRIVATE_KEY)
+ {
+- if (d2i_DSAPrivateKey((DSA **) &kk, &decoded, len) == (DSA *) NULL)
++ if (d2i_DSAPrivateKey((DSA **) &kk, (const unsigned char **) &decoded, len) == (DSA *) NULL)
+ {
+ if (ptr != (unsigned char *) NULL)
+ free(ptr);
+@@ -526,7 +526,7 @@
+ }
+ else
+ {
+- if (d2i_DSAPublicKey((DSA **) &kk, &decoded, len) == (DSA *) NULL)
++ if (d2i_DSAPublicKey((DSA **) &kk, (const unsigned char **) &decoded, len) == (DSA *) NULL)
+ {
+ if (ptr != (unsigned char *) NULL)
+ free(ptr);
+@@ -556,7 +556,7 @@
+ kk = dc->dec_key;
+ if (keytype == KEYNOTE_PRIVATE_KEY)
+ {
+- if (d2i_RSAPrivateKey((RSA **) &kk, &decoded, len) == (RSA *) NULL)
++ if (d2i_RSAPrivateKey((RSA **) &kk, (const unsigned char **) &decoded, len) == (RSA *) NULL)
+ {
+ if (ptr != (unsigned char *) NULL)
+ free(ptr);
+@@ -567,7 +567,7 @@
+ }
+ else
+ {
+- if (d2i_RSAPublicKey((RSA **) &kk, &decoded, len) == (RSA *) NULL)
++ if (d2i_RSAPublicKey((RSA **) &kk, (const unsigned char **) &decoded, len) == (RSA *) NULL)
+ {
+ if (ptr != (unsigned char *) NULL)
+ free(ptr);
diff --git a/package/keynote/patches/02-cross_compile.patch b/package/keynote/patches/02-cross_compile.patch
new file mode 100644
index 0000000000..c6d5365507
--- /dev/null
+++ b/package/keynote/patches/02-cross_compile.patch
@@ -0,0 +1,586 @@
+diff -urN keynote-2.3/configure keynote-2.3.new/configure
+--- keynote-2.3/configure 2000-09-27 01:16:28.000000000 +0200
++++ keynote-2.3.new/configure 2006-09-01 19:16:35.000000000 +0200
+@@ -889,52 +889,10 @@
+ done
+ test -n "$YACC" || YACC="yacc"
+
+-for ac_prog in openssl ssleay
+-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 $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:898: checking for $ac_word" >&5
+-if eval "test \"`echo '$''{'ac_cv_path_SSLEAY'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
+-else
+- case "$SSLEAY" in
+- /*)
+- ac_cv_path_SSLEAY="$SSLEAY" # Let the user override the test with a path.
+- ;;
+- ?:/*)
+- ac_cv_path_SSLEAY="$SSLEAY" # Let the user override the test with a dos path.
+- ;;
+- *)
+- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+- ac_dummy="\
+- $PATH:/usr/local/bin:/usr/local/ssl/sbin:/usr/local/ssl/bin:/usr/ssl/bin:/usr/ssl/sbin:/usr/sbin:/usr/openssl/bin:/usr/openssl/bin:/usr/local/openssl/bin:/usr/local/openssl/sbin"
+- for ac_dir in $ac_dummy; do
+- test -z "$ac_dir" && ac_dir=.
+- if test -f $ac_dir/$ac_word; then
+- ac_cv_path_SSLEAY="$ac_dir/$ac_word"
+- break
+- fi
+- done
+- IFS="$ac_save_ifs"
+- ;;
+-esac
+-fi
+-SSLEAY="$ac_cv_path_SSLEAY"
+-if test -n "$SSLEAY"; then
+- echo "$ac_t""$SSLEAY" 1>&6
+-else
+- echo "$ac_t""no" 1>&6
+-fi
+-
+-test -n "$SSLEAY" && break
+-done
+-test -n "$SSLEAY" || SSLEAY="/usr/local/bin/ssleay"
+-
+ # Extract the first word of "rm", so it can be a program name with args.
+ set dummy rm; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:938: checking for $ac_word" >&5
++echo "configure:896: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_RM'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -970,7 +928,7 @@
+ # Extract the first word of "ar", so it can be a program name with args.
+ set dummy ar; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:974: checking for $ac_word" >&5
++echo "configure:932: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_AR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -1006,7 +964,7 @@
+ # Extract the first word of "nroff", so it can be a program name with args.
+ set dummy nroff; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:1010: checking for $ac_word" >&5
++echo "configure:968: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_NROFF'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -1042,7 +1000,7 @@
+ # Extract the first word of "tar", so it can be a program name with args.
+ set dummy tar; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:1046: checking for $ac_word" >&5
++echo "configure:1004: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_TAR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -1078,7 +1036,7 @@
+ # Extract the first word of "true", so it can be a program name with args.
+ set dummy true; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:1082: checking for $ac_word" >&5
++echo "configure:1040: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_TRUE'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -1114,7 +1072,7 @@
+ # Extract the first word of "mkdir", so it can be a program name with args.
+ set dummy mkdir; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:1118: checking for $ac_word" >&5
++echo "configure:1076: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_MKDIR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -1150,7 +1108,7 @@
+ # Extract the first word of "tr", so it can be a program name with args.
+ set dummy tr; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:1154: checking for $ac_word" >&5
++echo "configure:1112: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_TR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -1186,7 +1144,7 @@
+ # Extract the first word of "echo", so it can be a program name with args.
+ set dummy echo; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:1190: checking for $ac_word" >&5
++echo "configure:1148: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_ECHO'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -1222,7 +1180,7 @@
+ # Extract the first word of "sed", so it can be a program name with args.
+ set dummy sed; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:1226: checking for $ac_word" >&5
++echo "configure:1184: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_SED'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -1256,11 +1214,8 @@
+ fi
+
+
+-LIBS="-L/usr/lib -L/usr/local/lib -L/usr/ssl/lib -L/usr/openssl/lib\
+- -L/usr/local/ssl/lib -L/usr/local/openssl/lib -L/usr/pkg/lib -L/pkg/lib"
+-
+ echo $ac_n "checking for floor in -lm""... $ac_c" 1>&6
+-echo "configure:1264: checking for floor in -lm" >&5
++echo "configure:1219: checking for floor in -lm" >&5
+ ac_lib_var=`echo m'_'floor | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+@@ -1268,7 +1223,7 @@
+ ac_save_LIBS="$LIBS"
+ LIBS="-lm $LIBS"
+ cat > conftest.$ac_ext <<EOF
+-#line 1272 "configure"
++#line 1227 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+@@ -1279,7 +1234,7 @@
+ floor()
+ ; return 0; }
+ EOF
+-if { (eval echo configure:1283: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
++if { (eval echo configure:1238: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+@@ -1300,7 +1255,7 @@
+ fi
+
+ echo $ac_n "checking for RSAPrivateDecrypt in -lrsaref""... $ac_c" 1>&6
+-echo "configure:1304: checking for RSAPrivateDecrypt in -lrsaref" >&5
++echo "configure:1259: checking for RSAPrivateDecrypt in -lrsaref" >&5
+ ac_lib_var=`echo rsaref'_'RSAPrivateDecrypt | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+@@ -1308,7 +1263,7 @@
+ ac_save_LIBS="$LIBS"
+ LIBS="-lrsaref $LIBS"
+ cat > conftest.$ac_ext <<EOF
+-#line 1312 "configure"
++#line 1267 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+@@ -1319,7 +1274,7 @@
+ RSAPrivateDecrypt()
+ ; return 0; }
+ EOF
+-if { (eval echo configure:1323: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
++if { (eval echo configure:1278: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+@@ -1340,7 +1295,7 @@
+ fi
+
+ echo $ac_n "checking for i2a_ASN1_STRING in -lcrypto""... $ac_c" 1>&6
+-echo "configure:1344: checking for i2a_ASN1_STRING in -lcrypto" >&5
++echo "configure:1299: checking for i2a_ASN1_STRING in -lcrypto" >&5
+ ac_lib_var=`echo crypto'_'i2a_ASN1_STRING | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+@@ -1348,7 +1303,7 @@
+ ac_save_LIBS="$LIBS"
+ LIBS="-lcrypto $LIBS"
+ cat > conftest.$ac_ext <<EOF
+-#line 1352 "configure"
++#line 1307 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+@@ -1359,7 +1314,7 @@
+ i2a_ASN1_STRING()
+ ; return 0; }
+ EOF
+-if { (eval echo configure:1363: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
++if { (eval echo configure:1318: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+@@ -1380,7 +1335,7 @@
+ fi
+
+ echo $ac_n "checking for RSA_ref_private_encrypt in -lRSAglue""... $ac_c" 1>&6
+-echo "configure:1384: checking for RSA_ref_private_encrypt in -lRSAglue" >&5
++echo "configure:1339: checking for RSA_ref_private_encrypt in -lRSAglue" >&5
+ ac_lib_var=`echo RSAglue'_'RSA_ref_private_encrypt | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+@@ -1388,7 +1343,7 @@
+ ac_save_LIBS="$LIBS"
+ LIBS="-lRSAglue $LIBS"
+ cat > conftest.$ac_ext <<EOF
+-#line 1392 "configure"
++#line 1347 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+@@ -1399,7 +1354,7 @@
+ RSA_ref_private_encrypt()
+ ; return 0; }
+ EOF
+-if { (eval echo configure:1403: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
++if { (eval echo configure:1358: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+@@ -1420,12 +1375,9 @@
+ fi
+
+
+-CPPFLAGS="-I/usr/include -I/usr/local/include -I/usr/ssl/include\
+- -I/usr/local/ssl/include -I/usr/openssl/include -I/usr/pkg/include\
+- -I/usr/local/openssl/include -I/pkg/include"
+
+ echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+-echo "configure:1429: checking how to run the C preprocessor" >&5
++echo "configure:1381: checking how to run the C preprocessor" >&5
+ # On Suns, sometimes $CPP names a directory.
+ if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+@@ -1440,13 +1392,13 @@
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+-#line 1444 "configure"
++#line 1396 "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:1450: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
++{ (eval echo configure:1402: \"$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
+ :
+@@ -1457,13 +1409,13 @@
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+-#line 1461 "configure"
++#line 1413 "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:1467: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
++{ (eval echo configure:1419: \"$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
+ :
+@@ -1474,13 +1426,13 @@
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+-#line 1478 "configure"
++#line 1430 "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:1484: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
++{ (eval echo configure:1436: \"$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
+ :
+@@ -1505,12 +1457,12 @@
+ echo "$ac_t""$CPP" 1>&6
+
+ echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+-echo "configure:1509: checking for ANSI C header files" >&5
++echo "configure:1461: 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 1514 "configure"
++#line 1466 "configure"
+ #include "confdefs.h"
+ #include <stdlib.h>
+ #include <stdarg.h>
+@@ -1518,7 +1470,7 @@
+ #include <float.h>
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+-{ (eval echo configure:1522: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
++{ (eval echo configure:1474: \"$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*
+@@ -1535,7 +1487,7 @@
+ 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 1539 "configure"
++#line 1491 "configure"
+ #include "confdefs.h"
+ #include <string.h>
+ EOF
+@@ -1553,7 +1505,7 @@
+ 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 1557 "configure"
++#line 1509 "configure"
+ #include "confdefs.h"
+ #include <stdlib.h>
+ EOF
+@@ -1574,7 +1526,7 @@
+ :
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 1578 "configure"
++#line 1530 "configure"
+ #include "confdefs.h"
+ #include <ctype.h>
+ #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+@@ -1585,7 +1537,7 @@
+ exit (0); }
+
+ EOF
+-if { (eval echo configure:1589: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
++if { (eval echo configure:1541: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ :
+ else
+@@ -1609,12 +1561,12 @@
+ fi
+
+ echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
+-echo "configure:1613: checking whether time.h and sys/time.h may both be included" >&5
++echo "configure:1565: 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 1618 "configure"
++#line 1570 "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #include <sys/time.h>
+@@ -1623,7 +1575,7 @@
+ struct tm *tp;
+ ; return 0; }
+ EOF
+-if { (eval echo configure:1627: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
++if { (eval echo configure:1579: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_time=yes
+ else
+@@ -1647,17 +1599,17 @@
+ do
+ ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+ echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+-echo "configure:1651: checking for $ac_hdr" >&5
++echo "configure:1603: 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 1656 "configure"
++#line 1608 "configure"
+ #include "confdefs.h"
+ #include <$ac_hdr>
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+-{ (eval echo configure:1661: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
++{ (eval echo configure:1613: \"$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*
+@@ -1687,17 +1639,17 @@
+ do
+ ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+ echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+-echo "configure:1691: checking for $ac_hdr" >&5
++echo "configure:1643: 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 1696 "configure"
++#line 1648 "configure"
+ #include "confdefs.h"
+ #include <$ac_hdr>
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+-{ (eval echo configure:1701: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
++{ (eval echo configure:1653: \"$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*
+@@ -1726,12 +1678,12 @@
+
+
+ echo $ac_n "checking for working const""... $ac_c" 1>&6
+-echo "configure:1730: checking for working const" >&5
++echo "configure:1682: 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 1735 "configure"
++#line 1687 "configure"
+ #include "confdefs.h"
+
+ int main() {
+@@ -1780,7 +1732,7 @@
+
+ ; return 0; }
+ EOF
+-if { (eval echo configure:1784: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
++if { (eval echo configure:1736: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+ else
+@@ -1801,12 +1753,12 @@
+ fi
+
+ echo $ac_n "checking for u_int""... $ac_c" 1>&6
+-echo "configure:1805: checking for u_int" >&5
++echo "configure:1757: checking for u_int" >&5
+ if eval "test \"`echo '$''{'ac_cv_type_u_int'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 1810 "configure"
++#line 1762 "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #if STDC_HEADERS
+@@ -1834,12 +1786,12 @@
+ fi
+
+ echo $ac_n "checking for u_char""... $ac_c" 1>&6
+-echo "configure:1838: checking for u_char" >&5
++echo "configure:1790: checking for u_char" >&5
+ if eval "test \"`echo '$''{'ac_cv_type_u_char'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 1843 "configure"
++#line 1795 "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #if STDC_HEADERS
+@@ -1870,12 +1822,12 @@
+ for ac_func in regcomp open close read _open _close _read strchr memcpy
+ do
+ echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+-echo "configure:1874: checking for $ac_func" >&5
++echo "configure:1826: 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 1879 "configure"
++#line 1831 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+@@ -1898,7 +1850,7 @@
+
+ ; return 0; }
+ EOF
+-if { (eval echo configure:1902: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
++if { (eval echo configure:1854: \"$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
+@@ -1925,12 +1877,12 @@
+ for ac_func in strcasecmp strncasecmp stricmp strnicmp snprintf __b64_ntop
+ do
+ echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+-echo "configure:1929: checking for $ac_func" >&5
++echo "configure:1881: 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 1934 "configure"
++#line 1886 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+@@ -1953,7 +1905,7 @@
+
+ ; return 0; }
+ EOF
+-if { (eval echo configure:1957: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
++if { (eval echo configure:1909: \"$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
+@@ -1980,12 +1932,12 @@
+ for ac_func in getopt
+ do
+ echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+-echo "configure:1984: checking for $ac_func" >&5
++echo "configure:1936: 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 1989 "configure"
++#line 1941 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+@@ -2008,7 +1960,7 @@
+
+ ; return 0; }
+ EOF
+-if { (eval echo configure:2012: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
++if { (eval echo configure:1964: \"$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
+@@ -2172,7 +2124,6 @@
+ s%@CC@%$CC%g
+ s%@RANLIB@%$RANLIB%g
+ s%@YACC@%$YACC%g
+-s%@SSLEAY@%$SSLEAY%g
+ s%@RM@%$RM%g
+ s%@AR@%$AR%g
+ s%@NROFF@%$NROFF%g
+diff -urN keynote-2.3/configure.in keynote-2.3.new/configure.in
+--- keynote-2.3/configure.in 2006-09-01 19:08:13.000000000 +0200
++++ keynote-2.3.new/configure.in 2006-09-01 19:16:05.000000000 +0200
+@@ -9,8 +9,8 @@
+ AC_PROG_CC
+ AC_PROG_RANLIB
+ AC_PROG_YACC
+-AC_PATH_PROGS(SSLEAY, openssl ssleay, /usr/local/bin/ssleay, \
+- $PATH:/usr/local/bin:/usr/local/ssl/sbin:/usr/local/ssl/bin:/usr/ssl/bin:/usr/ssl/sbin:/usr/sbin:/usr/openssl/bin:/usr/openssl/bin:/usr/local/openssl/bin:/usr/local/openssl/sbin)
++dnl AC_PATH_PROGS(SSLEAY, openssl ssleay, /usr/local/bin/ssleay, \
++dnl $PATH:/usr/local/bin:/usr/local/ssl/sbin:/usr/local/ssl/bin:/usr/ssl/bin:/usr/ssl/sbin:/usr/sbin:/usr/openssl/bin:/usr/openssl/bin:/usr/local/openssl/bin:/usr/local/openssl/sbin)
+ AC_PATH_PROG(RM, rm, /bin/rm)
+ AC_PATH_PROG(AR, ar, /usr/bin/ar)
+ AC_PATH_PROG(NROFF, nroff, /usr/bin/nroff)
+@@ -27,7 +27,7 @@
+ AC_CHECK_LIB(RSAglue, RSA_ref_private_encrypt, LIBS="$LIBS -lRSAglue")
+
+ dnl Checks for header files.
+-CPPFLAGS="-I/usr/include/openssl"
++dnl CPPFLAGS="-I/usr/include/openssl"
+
+ AC_HEADER_STDC
+ AC_HEADER_TIME
diff --git a/package/libpcap/Makefile b/package/libpcap/Makefile
new file mode 100644
index 0000000000..f8de02d559
--- /dev/null
+++ b/package/libpcap/Makefile
@@ -0,0 +1,97 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=libpcap
+PKG_VERSION:=0.9.4
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://www.tcpdump.org/release/
+PKG_MD5SUM:=79025766e8027df154cb1f32de8a7974
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libpcap
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=Low-level packet capture library
+ DESCRIPTION:=\
+ This package contains a system-independent library for user-level \\\
+ network packet capture.
+ URL:=http://www.tcpdump.org/
+endef
+
+define Build/Configure
+ (cd $(PKG_BUILD_DIR); rm -f config.cache; \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ CPPFLAGS="-I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/include" \
+ LDFLAGS="-L$(STAGING_DIR)/usr/lib -L$(STAGING_DIR)/lib" \
+ ac_cv_linux_vers= \
+ ./configure \
+ --target=$(GNU_TARGET_NAME) \
+ --host=$(GNU_TARGET_NAME) \
+ --build=$(GNU_HOST_NAME) \
+ --program-prefix="" \
+ --program-suffix="" \
+ --prefix=/usr \
+ --exec-prefix=/usr \
+ --bindir=/usr/bin \
+ --datadir=/usr/share \
+ --includedir=/usr/include \
+ --infodir=/usr/share/info \
+ --libdir=/usr/lib \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --mandir=/usr/share/man \
+ --sbindir=/usr/sbin \
+ --sysconfdir=/etc \
+ $(DISABLE_NLS) \
+ $(DISABLE_LARGEFILE) \
+ --enable-shared \
+ --enable-static \
+ --disable-yydebug \
+ --enable-ipv6 \
+ --with-build-cc="$(HOSTCC)" \
+ --with-pcap=linux \
+ );
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CCOPT="$(TARGET_CFLAGS) -I$(BUILD_DIR)/linux/include" \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ all install
+endef
+
+define Build/InstallDev
+ mkdir -p $(STAGING_DIR)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/pcap{,-bpf,-namedb}.h \
+ $(STAGING_DIR)/usr/include/
+ mkdir -p $(STAGING_DIR)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libpcap.{a,so*} \
+ $(STAGING_DIR)/usr/lib/
+endef
+
+define Build/UninstallDev
+ rm -rf $(STAGING_DIR)/usr/include/pcap{,-bpf,-named}.h \
+ $(STAGING_DIR)/usr/lib/libpcap.{a,so*}
+endef
+
+define Package/libpcap/install
+ install -m0755 -d $(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-shared-lib.patch b/package/libpcap/patches/100-shared-lib.patch
new file mode 100644
index 0000000000..54cc774a37
--- /dev/null
+++ b/package/libpcap/patches/100-shared-lib.patch
@@ -0,0 +1,120 @@
+diff -urN libpcap-0.9.4.orig/Makefile.in libpcap-0.9.4/Makefile.in
+--- libpcap-0.9.4.orig/Makefile.in 2003-12-15 02:35:03.000000000 +0100
++++ libpcap-0.9.4/Makefile.in 2006-02-05 16:56:18.000000000 +0100
+@@ -37,6 +37,15 @@
+ srcdir = @srcdir@
+ VPATH = @srcdir@
+
++# some defines for shared library compilation
++MAJ=0.9
++MIN=4
++VERSION=$(MAJ).$(MIN)
++LIBNAME=pcap
++LIBRARY=lib$(LIBNAME).a
++SOLIBRARY=lib$(LIBNAME).so
++SHAREDLIB=$(SOLIBRARY).$(VERSION)
++
+ #
+ # You shouldn't need to edit anything below.
+ #
+@@ -50,6 +59,7 @@
+
+ # Standard CFLAGS
+ CFLAGS = $(CCOPT) $(INCLS) $(DEFS)
++CFLAGS_SHARED = -shared -Wl,-soname,$(SOLIBRARY).$(MAJ)
+
+ INSTALL = @INSTALL@
+ INSTALL_PROGRAM = @INSTALL_PROGRAM@
+@@ -70,7 +80,12 @@
+ .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
+ FSRC = fad-@V_FINDALLDEVS@.c
+ SSRC = @SSRC@
+@@ -84,6 +99,7 @@
+ # 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)
+ HDR = pcap.h pcap-int.h pcap-namedb.h pcap-nit.h pcap-pf.h \
+ ethertype.h gencode.h gnuc.h
+ GENHDR = \
+@@ -95,15 +111,23 @@
+ TAGFILES = \
+ $(SRC) $(HDR) $(TAGHDR)
+
+-CLEANFILES = $(OBJ) libpcap.a $(GENSRC) $(GENHDR) lex.yy.c
++CLEANFILES = $(OBJ) $(OBJ_PIC) libpcap.a $(GENSRC) $(GENHDR) lex.yy.c libpcap.so*
+
+-all: libpcap.a
++all: libpcap.a $(SHAREDLIB)
+
+ libpcap.a: $(OBJ)
+ @rm -f $@
+ ar rc $@ $(OBJ) $(LIBS)
+ $(RANLIB) $@
+
++$(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)
++
++
+ shared: libpcap.$(DYEXT)
+
+ #
+@@ -129,6 +153,10 @@
+ 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
+@@ -142,9 +170,16 @@
+ @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
+
+@@ -170,10 +205,17 @@
+ 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 $@
++
++
+ install: libpcap.a
+ [ -d $(DESTDIR)$(libdir) ] || \
+ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+ $(INSTALL_DATA) libpcap.a $(DESTDIR)$(libdir)/libpcap.a
++ $(INSTALL_DATA) $(SHAREDLIB) $(DESTDIR)$(libdir)/
++ ln -sf $(SHAREDLIB) $(DESTDIR)$(libdir)/$(SOLIBRARY).$(MAJ)
++ ln -sf $(SOLIBRARY).$(MAJ) $(DESTDIR)$(libdir)/$(SOLIBRARY)
+ $(RANLIB) $(DESTDIR)$(libdir)/libpcap.a
+ [ -d $(DESTDIR)$(includedir) ] || \
+ (mkdir -p $(DESTDIR)$(includedir); chmod 755 $(DESTDIR)$(includedir))
diff --git a/package/libpcap/patches/101-cross-compile-fix.patch b/package/libpcap/patches/101-cross-compile-fix.patch
new file mode 100644
index 0000000000..5ba78adaef
--- /dev/null
+++ b/package/libpcap/patches/101-cross-compile-fix.patch
@@ -0,0 +1,12 @@
+diff -urN libpcap-0.9.4.orig/Makefile.in libpcap-0.9.4/Makefile.in
+--- libpcap-0.9.4.orig/Makefile.in 2006-02-05 16:57:16.000000000 +0100
++++ libpcap-0.9.4/Makefile.in 2006-02-05 16:57:03.000000000 +0100
+@@ -117,7 +117,7 @@
+
+ libpcap.a: $(OBJ)
+ @rm -f $@
+- ar rc $@ $(OBJ) $(LIBS)
++ $(AR) rc $@ $(OBJ) $(LIBS)
+ $(RANLIB) $@
+
+ $(SHAREDLIB): $(OBJ_PIC)
diff --git a/package/libpcap/patches/102-alt-ether.patch b/package/libpcap/patches/102-alt-ether.patch
new file mode 100644
index 0000000000..347265d6e9
--- /dev/null
+++ b/package/libpcap/patches/102-alt-ether.patch
@@ -0,0 +1,40 @@
+diff -urN libpcap-0.9.4.orig/nametoaddr.c libpcap-0.9.4/nametoaddr.c
+--- libpcap-0.9.4.orig/nametoaddr.c 2005-04-20 13:13:51.000000000 +0200
++++ libpcap-0.9.4/nametoaddr.c 2006-02-05 16:58:46.000000000 +0100
+@@ -410,7 +410,7 @@
+ e = ep = (u_char *)malloc(6);
+
+ while (*s) {
+- if (*s == ':')
++ if (*s == ':' || *s == '.')
+ s += 1;
+ d = xdtoi(*s++);
+ if (isxdigit((unsigned char)*s)) {
+diff -urN libpcap-0.9.4.orig/scanner.l libpcap-0.9.4/scanner.l
+--- libpcap-0.9.4.orig/scanner.l 2005-09-05 11:08:07.000000000 +0200
++++ libpcap-0.9.4/scanner.l 2006-02-05 17:00:13.000000000 +0100
+@@ -80,6 +80,7 @@
+ N ([0-9]+|(0X|0x)[0-9A-Fa-f]+)
+ B ([0-9A-Fa-f][0-9A-Fa-f]?)
+ W ([0-9A-Fa-f][0-9A-Fa-f]?[0-9A-Fa-f]?[0-9A-Fa-f]?)
++X [0-9A-Fa-f]
+
+ %a 16000
+ %o 19000
+@@ -306,7 +307,7 @@
+ {N} { yylval.i = stoi((char *)yytext); return NUM; }
+ ({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N}) {
+ yylval.s = sdup((char *)yytext); return HID; }
+-{B}:{B}:{B}:{B}:{B}:{B} { yylval.e = pcap_ether_aton((char *)yytext);
++({B}:{B}:{B}:{B}:{B}:{B})|({B}\.{B}\.{B}\.{B}\.{B}\.{B}) { yylval.e = pcap_ether_aton((char *)yytext);
+ return EID; }
+ {V6} {
+ #ifdef INET6
+@@ -324,6 +325,7 @@
+ #endif /*INET6*/
+ }
+ {B}:+({B}:+)+ { bpf_error("bogus ethernet address %s", yytext); }
++{X}{12} { yylval.e = pcap_ether_aton((char *)yytext); return EID;}
+ icmptype { yylval.i = 0; return NUM; }
+ icmpcode { yylval.i = 1; return NUM; }
+ icmp-echoreply { yylval.i = 0; return NUM; }
diff --git a/package/libpcap/patches/103-flex_workaround.patch b/package/libpcap/patches/103-flex_workaround.patch
new file mode 100644
index 0000000000..5b6d0db0cb
--- /dev/null
+++ b/package/libpcap/patches/103-flex_workaround.patch
@@ -0,0 +1,14 @@
+
+ Copyright (C) 2006 Markus Wigge
+
+diff -urN libpcap-0.9.4.orig/Makefile.in libpcap-0.9.4/Makefile.in
+--- libpcap-0.9.4.orig/Makefile.in 2006-07-19 09:27:47.000000000 +0200
++++ libpcap-0.9.4/Makefile.in 2006-07-19 09:34:48.000000000 +0200
+@@ -53,7 +53,7 @@
+ CC = @CC@
+ CCOPT = @V_CCOPT@
+ INCLS = -I. @V_INCLS@
+-DEFS = @DEFS@ @V_DEFS@
++DEFS = -D_BSD_SOURCE @DEFS@ @V_DEFS@
+ LIBS = @V_LIBS@
+ DYEXT = @DYEXT@
diff --git a/package/linux-atm/Makefile b/package/linux-atm/Makefile
new file mode 100644
index 0000000000..24a914a71c
--- /dev/null
+++ b/package/linux-atm/Makefile
@@ -0,0 +1,88 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=linux-atm
+PKG_VERSION:=2.4.1
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).orig.tar.gz
+PKG_SOURCE_URL:=http://ftp.debian.org/debian/pool/main/l/linux-atm/
+PKG_MD5SUM:=84fef49cc39ff2605204246666f65864
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/linux-atm/Default
+ URL:=http://linux-atm.sourceforge.net/
+endef
+
+define Package/linux-atm
+ $(call Package/linux-atm/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=Linux ATM Library
+ DESCRIPTION:=\
+ This package contains a library for accessing the Linux ATM subsystem.
+endef
+
+define Package/br2684ctl
+ $(call Package/linux-atm/Default)
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=+linux-atm
+ TITLE:=RFC2684 bridging utility
+ DESCRIPTION:=\
+ This package contains an ATM RFC2684 bridging utility.
+endef
+
+define Build/Configure
+ $(call Build/Configure/Default)
+ # prevent autoheader invocation
+ touch $(PKG_BUILD_DIR)/stamp-h.in
+endef
+
+define Build/Compile
+ $(call Build/Compile/Default, \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ all install \
+ )
+endef
+
+define Build/InstallDev
+ mkdir -p $(STAGING_DIR)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/atm{,d,sap}.h \
+ $(STAGING_DIR)/usr/include/
+ mkdir -p $(STAGING_DIR)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libatm.{a,so*} \
+ $(STAGING_DIR)/usr/lib/
+endef
+
+define Build/UninstallDev
+ rm -rf $(STAGING_DIR)/usr/include/atm{,d,sap}.h \
+ $(STAGING_DIR)/usr/lib/libatm.{a,so*}
+endef
+
+define Package/linux-atm/install
+ install -d -m0755 $(1)/usr/lib
+ cp -f $(PKG_INSTALL_DIR)/usr/lib/libatm.so.1 $(1)/usr/lib
+endef
+
+define Package/br2684ctl/install
+ install -d -m0755 $(1)/usr/sbin
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/br2684ctl $(1)/usr/sbin/
+ install -d -m0755 $(1)/etc/hotplug.d/net
+ install -m0644 ./files/br2684.hotplug $(1)/etc/hotplug.d/net/30-br2684
+endef
+
+$(eval $(call BuildPackage,linux-atm))
+$(eval $(call BuildPackage,br2684ctl))
diff --git a/package/linux-atm/files/br2684.hotplug b/package/linux-atm/files/br2684.hotplug
new file mode 100644
index 0000000000..242e7e5152
--- /dev/null
+++ b/package/linux-atm/files/br2684.hotplug
@@ -0,0 +1,19 @@
+[ "${INTERFACE%%[0-9]*}" = "atm" ] && {
+ case "$ACTION" in
+ register)
+ [ "$pppoe_atm" = 1 ] && {
+ case "$atm_encaps" in
+ 0|vc) ENCAPS=0 ;;
+ 1|llc) ENCAPS=1 ;;
+ *) ENCAPS=0 ;;
+ esac
+ insmod br2684 2>&- >&-
+ br2684ctl -c0 -e${ENCAPS} -a${atm_vpi:-8}.${atm_vci:-35} &
+ }
+ ;;
+ unregister)
+ killall br2684ctl 2>&- >&-
+ rmmod br2684
+ ;;
+ esac
+}
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 0000000000..41dc437ca4
--- /dev/null
+++ b/package/linux-atm/patches/000-debian_16.patch
@@ -0,0 +1,35073 @@
+--- linux-atm-2.4.1.orig/Makefile.in
++++ linux-atm-2.4.1/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -100,14 +100,14 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
+ all: all-redirect
+ .SUFFIXES:
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -225,7 +225,7 @@
+ 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)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -274,6 +274,11 @@
+ -rm -rf $(distdir)
+ mkdir $(distdir)
+ -chmod 777 $(distdir)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+--- linux-atm-2.4.1.orig/aclocal.m4
++++ linux-atm-2.4.1/aclocal.m4
+@@ -1,4 +1,4 @@
+-dnl aclocal.m4 generated automatically by aclocal 1.4-p5
++dnl aclocal.m4 generated automatically by aclocal 1.4-p6
+
+ dnl Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ dnl This file is free software; the Free Software Foundation
+@@ -43,7 +43,8 @@
+ dnl AM_INIT_AUTOMAKE(package,version, [no-define])
+
+ AC_DEFUN([AM_INIT_AUTOMAKE],
+-[AC_REQUIRE([AC_PROG_INSTALL])
++[AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
++AC_REQUIRE([AC_PROG_INSTALL])
+ PACKAGE=[$1]
+ AC_SUBST(PACKAGE)
+ VERSION=[$2]
+@@ -59,13 +60,42 @@
+ 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(ACLOCAL, aclocal-${am__api_version}, $missing_dir)
+ AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
+-AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
++AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}, $missing_dir)
+ AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
+ AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
+ AC_REQUIRE([AC_PROG_MAKE_SET])])
+
++# Copyright 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, 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
++
++# AM_AUTOMAKE_VERSION(VERSION)
++# ----------------------------
++# Automake X.Y traces this macro to ensure aclocal.m4 has been
++# generated from the m4 files accompanying Automake X.Y.
++AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.4"])
++
++# AM_SET_CURRENT_AUTOMAKE_VERSION
++# -------------------------------
++# 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.4-p6])])
++
+ #
+ # Check to make sure that the build environment is sane.
+ #
+@@ -130,13 +160,14 @@
+ dnl Look for flex, lex or missing, then run AC_PROG_LEX and AC_DECL_YYTEXT
+ AC_DEFUN([AM_PROG_LEX],
+ [missing_dir=ifelse([$1],,`cd $ac_aux_dir && pwd`,$1)
+-AC_CHECK_PROGS(LEX, flex lex, "$missing_dir/missing flex")
++AC_CHECK_PROGS(LEX, flex lex, $missing_dir/missing flex)
+ AC_PROG_LEX
+ AC_DECL_YYTEXT])
+
+ # libtool.m4 - Configure libtool for the host system. -*-Shell-script-*-
+
+ # serial 46 AC_PROG_LIBTOOL
++
+ AC_DEFUN([AC_PROG_LIBTOOL],
+ [AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+
+@@ -162,6 +193,8 @@
+ AC_REQUIRE([AC_PROG_LD])dnl
+ AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl
+ AC_REQUIRE([AC_PROG_NM])dnl
++AC_REQUIRE([LT_AC_PROG_SED])dnl
++
+ AC_REQUIRE([AC_PROG_LN_S])dnl
+ AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl
+ AC_REQUIRE([AC_OBJEXT])dnl
+@@ -262,9 +295,30 @@
+
+ ])
+
++# AC_LIBTOOL_HEADER_ASSERT
++# ------------------------
++AC_DEFUN([AC_LIBTOOL_HEADER_ASSERT],
++[AC_CACHE_CHECK([whether $CC supports assert without backlinking],
++ [lt_cv_func_assert_works],
++ [case $host in
++ *-*-solaris*)
++ if test "$GCC" = yes && test "$with_gnu_ld" != yes; then
++ case `$CC --version 2>/dev/null` in
++ [[12]].*) lt_cv_func_assert_works=no ;;
++ *) lt_cv_func_assert_works=yes ;;
++ esac
++ fi
++ ;;
++ esac])
++
++if test "x$lt_cv_func_assert_works" = xyes; then
++ AC_CHECK_HEADERS(assert.h)
++fi
++])# AC_LIBTOOL_HEADER_ASSERT
++
+ # _LT_AC_CHECK_DLFCN
+ # --------------------
+-AC_DEFUN(_LT_AC_CHECK_DLFCN,
++AC_DEFUN([_LT_AC_CHECK_DLFCN],
+ [AC_CHECK_HEADERS(dlfcn.h)
+ ])# _LT_AC_CHECK_DLFCN
+
+@@ -282,10 +336,10 @@
+ # [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+ # Character class describing NM global symbol codes.
+-[symcode='[BCDEGRST]']
++symcode='[[BCDEGRST]]'
+
+ # Regexp to match symbols that can be accessed directly from C.
+-[sympat='\([_A-Za-z][_A-Za-z0-9]*\)']
++sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+ # Transform the above into a raw symbol and a C symbol.
+ symxfrm='\1 \2\3 \3'
+@@ -293,25 +347,32 @@
+ # Transform an extracted symbol line into a proper C declaration
+ lt_cv_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
+
++# Transform an extracted symbol line into symbol name and symbol address
++lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
++
+ # Define system-specific variables.
+ case $host_os in
+ aix*)
+- [symcode='[BCDT]']
++ symcode='[[BCDT]]'
+ ;;
+ cygwin* | mingw* | pw32*)
+- [symcode='[ABCDGISTW]']
++ symcode='[[ABCDGISTW]]'
+ ;;
+ hpux*) # Its linker distinguishes data from code symbols
+ lt_cv_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
++ lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
++ ;;
++irix* | nonstopux*)
++ symcode='[[BCDEGRST]]'
+ ;;
+-irix*)
+- [symcode='[BCDEGRST]']
++osf*)
++ symcode='[[BCDEGQRST]]'
+ ;;
+ solaris* | sysv5*)
+- [symcode='[BDT]']
++ symcode='[[BDT]]'
+ ;;
+ sysv4)
+- [symcode='[DFNSTU]']
++ symcode='[[DFNSTU]]'
+ ;;
+ esac
+
+@@ -325,14 +386,14 @@
+
+ # If we're using GNU nm, then use its standard symbol codes.
+ if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+- [symcode='[ABCDGISTW]']
++ symcode='[[ABCDGISTW]]'
+ fi
+
+ # Try without a prefix undercore, then with it.
+ for ac_symprfx in "" "_"; do
+
+ # Write the raw and C identifiers.
+-[lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'"]
++lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+@@ -374,23 +435,23 @@
+
+ cat <<EOF >> conftest.$ac_ext
+ #if defined (__STDC__) && __STDC__
+-# define lt_ptr_t void *
++# define lt_ptr void *
+ #else
+-# define lt_ptr_t char *
++# define lt_ptr char *
+ # define const
+ #endif
+
+ /* The mapping between symbol names and symbols. */
+ const struct {
+ const char *name;
+- lt_ptr_t address;
++ lt_ptr address;
+ }
+-[lt_preloaded_symbols[] =]
++lt_preloaded_symbols[[]] =
+ {
+ EOF
+- sed "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" >> conftest.$ac_ext
++ sed "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr) \&\2},/" < "$nlist" >> conftest.$ac_ext
+ cat <<\EOF >> conftest.$ac_ext
+- {0, (lt_ptr_t) 0}
++ {0, (lt_ptr) 0}
+ };
+
+ #ifdef __cplusplus
+@@ -403,7 +464,7 @@
+ save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$no_builtin_flag"
+- if AC_TRY_EVAL(ac_link) && test -s conftest; then
++ if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then
+ pipe_works=yes
+ fi
+ LIBS="$save_LIBS"
+@@ -434,10 +495,13 @@
+ global_symbol_pipe="$lt_cv_sys_global_symbol_pipe"
+ if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ global_symbol_to_cdecl=
++ global_symbol_to_c_name_address=
+ else
+ global_symbol_to_cdecl="$lt_cv_global_symbol_to_cdecl"
++ global_symbol_to_c_name_address="$lt_cv_global_symbol_to_c_name_address"
+ fi
+-if test -z "$global_symbol_pipe$global_symbol_to_cdecl"; then
++if test -z "$global_symbol_pipe$global_symbol_to_cdec$global_symbol_to_c_name_address";
++then
+ AC_MSG_RESULT(failed)
+ else
+ AC_MSG_RESULT(ok)
+@@ -455,16 +519,17 @@
+ *-DOS) lt_cv_sys_path_separator=';' ;;
+ *) lt_cv_sys_path_separator=':' ;;
+ esac
++ PATH_SEPARATOR=$lt_cv_sys_path_separator
+ fi
+ ])# _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR
+
+ # _LT_AC_PROG_ECHO_BACKSLASH
+ # --------------------------
+ # Add some code to the start of the generated configure script which
+-# will find an echo command which doesn;t interpret backslashes.
++# will find an echo command which doesn't interpret backslashes.
+ AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH],
+ [ifdef([AC_DIVERSION_NOTICE], [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+- [AC_DIVERT_PUSH(NOTICE)])
++ [AC_DIVERT_PUSH(NOTICE)])
+ _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR
+
+ # Check that we are running under the correct shell.
+@@ -530,7 +595,7 @@
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
++ IFS="${IFS= }"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+@@ -619,7 +684,7 @@
+ # _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+ # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+ # ------------------------------------------------------------------
+-AC_DEFUN(_LT_AC_TRY_DLOPEN_SELF,
++AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF],
+ [if test "$cross_compiling" = yes; then :
+ [$4]
+ else
+@@ -706,7 +771,7 @@
+
+ # AC_LIBTOOL_DLOPEN_SELF
+ # -------------------
+-AC_DEFUN(AC_LIBTOOL_DLOPEN_SELF,
++AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF],
+ [if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+@@ -728,16 +793,22 @@
+ ;;
+
+ *)
+- AC_CHECK_LIB(dl, dlopen, [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+- [AC_CHECK_FUNC(dlopen, lt_cv_dlopen="dlopen",
+- [AC_CHECK_FUNC(shl_load, lt_cv_dlopen="shl_load",
+- [AC_CHECK_LIB(svld, dlopen,
+- [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+- [AC_CHECK_LIB(dld, shl_load,
+- [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"])
++ AC_CHECK_FUNC([shl_load],
++ [lt_cv_dlopen="shl_load"],
++ [AC_CHECK_LIB([dld], [shl_load],
++ [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"],
++ [AC_CHECK_FUNC([dlopen],
++ [lt_cv_dlopen="dlopen"],
++ [AC_CHECK_LIB([dl], [dlopen],
++ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
++ [AC_CHECK_LIB([svld], [dlopen],
++ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
++ [AC_CHECK_LIB([dld], [dld_link],
++ [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"])
++ ])
+ ])
+- ])
+- ])
++ ])
++ ])
+ ])
+ ;;
+ esac
+@@ -800,10 +871,10 @@
+ # Sed substitution that helps us do robust quoting. It backslashifies
+ # metacharacters that are still active within double-quoted strings.
+ Xsed='sed -e s/^X//'
+-[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g']
++sed_quote_subst='s/\([[\\"\\`$\\\\]]\)/\\\1/g'
+
+ # Same as above, but do not quote variable references.
+-[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g']
++double_quote_subst='s/\([[\\"\\`\\\\]]\)/\\\1/g'
+
+ # Sed substitution to delay expansion of an escaped shell variable in a
+ # double_quote_subst'ed string.
+@@ -872,8 +943,15 @@
+ old_postuninstall_cmds=
+
+ if test -n "$RANLIB"; then
++ case $host_os in
++ openbsd*)
++ old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds"
++ ;;
++ *)
++ old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
++ ;;
++ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+- old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
+ fi
+
+ # Allow CC to be a program name with arguments.
+@@ -893,7 +971,7 @@
+ AC_MSG_RESULT($objdir)
+
+
+-AC_ARG_WITH(pic,
++AC_ARG_WITH(pic,
+ [ --with-pic try to use only PIC/non-PIC objects [default=use both]],
+ pic_mode="$withval", pic_mode=default)
+ test -z "$pic_mode" && pic_mode=default
+@@ -921,7 +999,7 @@
+ # libC (AIX C++ library), which obviously doesn't included in libraries
+ # list by gcc. This cause undefined symbols with -static flags.
+ # This hack allows C programs to be linked with "-static -ldl", but
+- # we not sure about C++ programs.
++ # not sure about C++ programs.
+ lt_cv_prog_cc_static="$lt_cv_prog_cc_static ${lt_cv_prog_cc_wl}-lC"
+ ;;
+ amigaos*)
+@@ -930,7 +1008,7 @@
+ # like `-m68040'.
+ lt_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4'
+ ;;
+- beos* | irix5* | irix6* | osf3* | osf4* | osf5*)
++ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ darwin* | rhapsody*)
+@@ -956,13 +1034,13 @@
+ # PORTME Check for PIC flags for the system compiler.
+ case $host_os in
+ aix3* | aix4* | aix5*)
++ lt_cv_prog_cc_wl='-Wl,'
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+- # AIX 5 now supports IA64 processor
+- lt_cv_prog_cc_static='-Bstatic'
+- lt_cv_prog_cc_wl='-Wl,'
++ # AIX 5 now supports IA64 processor
++ lt_cv_prog_cc_static='-Bstatic'
+ else
+- lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp'
++ lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+
+@@ -973,7 +1051,7 @@
+ lt_cv_prog_cc_pic='+Z'
+ ;;
+
+- irix5* | irix6*)
++ irix5* | irix6* | nonstopux*)
+ lt_cv_prog_cc_wl='-Wl,'
+ lt_cv_prog_cc_static='-non_shared'
+ # PIC (with -KPIC) is the default.
+@@ -1017,11 +1095,7 @@
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ lt_cv_prog_cc_pic='-KPIC'
+ lt_cv_prog_cc_static='-Bstatic'
+- if test "x$host_vendor" = xsni; then
+- lt_cv_prog_cc_wl='-LD'
+- else
+- lt_cv_prog_cc_wl='-Wl,'
+- fi
++ lt_cv_prog_cc_wl='-Wl,'
+ ;;
+
+ uts4*)
+@@ -1087,7 +1161,7 @@
+ # Check for any special shared library compilation flags.
+ if test -n "$lt_cv_prog_cc_shlib"; then
+ AC_MSG_WARN([\`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries])
+- if echo "$old_CC $old_CFLAGS " | [egrep -e "[ ]$lt_cv_prog_cc_shlib[ ]"] >/dev/null; then :
++ if echo "$old_CC $old_CFLAGS " | egrep -e "[[ ]]$lt_cv_prog_cc_shlib[[ ]]" >/dev/null; then :
+ else
+ AC_MSG_WARN([add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure])
+ lt_cv_prog_cc_can_build_shared=no
+@@ -1163,6 +1237,8 @@
+ lt_cv_compiler_o_lo=no
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -c -o conftest.lo"
++ save_objext="$ac_objext"
++ ac_objext=lo
+ AC_TRY_COMPILE([], [int some_variable = 0;], [dnl
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+@@ -1172,6 +1248,7 @@
+ lt_cv_compiler_o_lo=yes
+ fi
+ ])
++ ac_objext="$save_objext"
+ CFLAGS="$save_CFLAGS"
+ ])
+ compiler_o_lo=$lt_cv_compiler_o_lo
+@@ -1268,7 +1345,7 @@
+ extract_expsyms_cmds=
+
+ case $host_os in
+-cygwin* | mingw* | pw32* )
++cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+@@ -1276,7 +1353,9 @@
+ with_gnu_ld=no
+ fi
+ ;;
+-
++openbsd*)
++ with_gnu_ld=no
++ ;;
+ esac
+
+ ld_shlibs=yes
+@@ -1363,7 +1442,7 @@
+ # can override, but on older systems we have to supply one (in ltdll.c)
+ if test "x$lt_cv_need_dllmain" = "xyes"; then
+ ltdll_obj='$output_objdir/$soname-ltdll.'"$ac_objext "
+- ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < [$]0 > $output_objdir/$soname-ltdll.c~
++ ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $''0 > $output_objdir/$soname-ltdll.c~
+ test -f $output_objdir/$soname-ltdll.$ac_objext || (cd $output_objdir && $CC -c $soname-ltdll.c)~'
+ else
+ ltdll_obj=
+@@ -1376,24 +1455,25 @@
+ # Be careful not to strip the DATA tag left be newer dlltools.
+ export_symbols_cmds="$ltdll_cmds"'
+ $DLLTOOL --export-all --exclude-symbols '$dll_exclude_symbols' --output-def $output_objdir/$soname-def '$ltdll_obj'$libobjs $convenience~
+- [sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//"] < $output_objdir/$soname-def > $export_symbols'
++ sed -e "1,/EXPORTS/d" -e "s/ @ [[0-9]]*//" -e "s/ *;.*$//" < $output_objdir/$soname-def > $export_symbols'
+
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is.
+ # If DATA tags from a recent dlltool are present, honour them!
+- archive_expsym_cmds='if test "x`head -1 $export_symbols`" = xEXPORTS; then
+- cp $export_symbols $output_objdir/$soname-def;
++ archive_expsym_cmds='if test "x`sed 1q $export_symbols`" = xEXPORTS; then
++ cp $export_symbols $output_objdir/$soname-def;
+ else
+- echo EXPORTS > $output_objdir/$soname-def;
+- _lt_hint=1;
+- cat $export_symbols | while read symbol; do
+- set dummy \$symbol;
+- case \[$]# in
+- 2) echo " \[$]2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;;
+- *) echo " \[$]2 @ \$_lt_hint \[$]3 ; " >> $output_objdir/$soname-def;;
+- esac;
+- _lt_hint=`expr 1 + \$_lt_hint`;
+- done;
++ echo EXPORTS > $output_objdir/$soname-def;
++ _lt_hint=1;
++ cat $export_symbols | while read symbol; do
++ set dummy \$symbol;
++ case \[$]# in
++ 2) echo " \[$]2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;;
++ 4) echo " \[$]2 \[$]3 \[$]4 ; " >> $output_objdir/$soname-def; _lt_hint=`expr \$_lt_hint - 1`;;
++ *) echo " \[$]2 @ \$_lt_hint \[$]3 ; " >> $output_objdir/$soname-def;;
++ esac;
++ _lt_hint=`expr 1 + \$_lt_hint`;
++ done;
+ fi~
+ '"$ltdll_cmds"'
+ $CC -Wl,--base-file,$output_objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~
+@@ -1488,80 +1568,98 @@
+ ;;
+
+ aix4* | aix5*)
++ if test "$host_cpu" = ia64; then
++ # On IA64, the linker does run time linking by default, so we don't
++ # have to do anything special.
++ aix_use_runtimelinking=no
++ exp_sym_flag='-Bexport'
++ no_entry_flag=""
++ else
++ aix_use_runtimelinking=no
++
++ # Test if we are trying to use run time linking or normal
++ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
++ # need to do runtime linking.
++ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
++ for ld_flag in $LDFLAGS; do
++ case $ld_flag in
++ *-brtl*)
++ aix_use_runtimelinking=yes
++ break
++ ;;
++ esac
++ done
++ esac
++
++ exp_sym_flag='-bexport'
++ no_entry_flag='-bnoentry'
++ fi
++
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
++ hardcode_direct=yes
+ archive_cmds=''
+ hardcode_libdir_separator=':'
+ if test "$GCC" = yes; then
+- collect2name=`${CC} -print-prog-name=collect2`
+- if test -f "$collect2name" && \
+- strings "$collect2name" | grep resolve_lib_name >/dev/null
+- then
+- # We have reworked collect2
+- hardcode_direct=yes
+- else
+- # We have old collect2
+- hardcode_direct=unsupported
+- # It fails to find uninstalled libraries when the uninstalled
+- # path is not listed in the libpath. Setting hardcode_minus_L
+- # to unsupported forces relinking
+- hardcode_minus_L=yes
+- hardcode_libdir_flag_spec='-L$libdir'
+- hardcode_libdir_separator=
+- fi
++ case $host_os in aix4.[[012]]|aix4.[[012]].*)
++ collect2name=`${CC} -print-prog-name=collect2`
++ if test -f "$collect2name" && \
++ strings "$collect2name" | grep resolve_lib_name >/dev/null
++ then
++ # We have reworked collect2
++ hardcode_direct=yes
++ else
++ # We have old collect2
++ hardcode_direct=unsupported
++ # It fails to find uninstalled libraries when the uninstalled
++ # path is not listed in the libpath. Setting hardcode_minus_L
++ # to unsupported forces relinking
++ hardcode_minus_L=yes
++ hardcode_libdir_flag_spec='-L$libdir'
++ hardcode_libdir_separator=
++ fi
++ esac
++
+ shared_flag='-shared'
+ else
++ # not using gcc
+ if test "$host_cpu" = ia64; then
+- shared_flag='-G'
++ shared_flag='${wl}-G'
+ else
+- shared_flag='${wl}-bM:SRE'
++ if test "$aix_use_runtimelinking" = yes; then
++ shared_flag='${wl}-G'
++ else
++ shared_flag='${wl}-bM:SRE'
++ fi
+ fi
+- hardcode_direct=yes
+ fi
+
+- if test "$host_cpu" = ia64; then
+- # On IA64, the linker does run time linking by default, so we don't
+- # have to do anything special.
+- aix_use_runtimelinking=no
+- exp_sym_flag='-Bexport'
+- no_entry_flag=""
+- else
+- # Test if we are trying to use run time linking, or normal AIX style linking.
+- # If -brtl is somewhere in LDFLAGS, we need to do run time linking.
+- aix_use_runtimelinking=no
+- for ld_flag in $LDFLAGS; do
+- if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl" ); then
+- aix_use_runtimelinking=yes
+- break
+- fi
+- done
+- exp_sym_flag='-bexport'
+- no_entry_flag='-bnoentry'
+- fi
+ # It seems that -bexpall can do strange things, so it is better to
+ # generate a list of symbols to export.
+ always_export_symbols=yes
+ if test "$aix_use_runtimelinking" = yes; then
++ # Warning - without using the other runtime loading flags (-brtl),
++ # -berok will link without error, but may produce a broken library.
++ allow_undefined_flag='-berok'
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib'
+- allow_undefined_flag=' -Wl,-G'
+- archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
++ archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+- hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+- allow_undefined_flag="-znodefs"
+- archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname ${wl}-h$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
++ hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
++ allow_undefined_flag="-z nodefs"
++ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname ${wl}-h$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
+ else
+- hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib'
+- # Warning - without using the other run time loading flags, -berok will
+- # link without error, but may produce a broken library.
+- allow_undefined_flag='${wl}-berok'
+- # This is a bit strange, but is similar to how AIX traditionally builds
+- # it's shared libraries.
+- archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"' ~$AR -crlo $objdir/$libname$release.a $objdir/$soname'
++ hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib'
++ # Warning - without using the other run time loading flags,
++ # -berok will link without error, but may produce a broken library.
++ allow_undefined_flag='${wl}-berok'
++ # This is a bit strange, but is similar to how AIX traditionally builds
++ # it's shared libraries.
++ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"' ~$AR -crlo $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+@@ -1593,11 +1691,19 @@
+ ;;
+
+ darwin* | rhapsody*)
+- allow_undefined_flag='-undefined suppress'
++ case "$host_os" in
++ rhapsody* | darwin1.[[012]])
++ allow_undefined_flag='-undefined suppress'
++ ;;
++ *) # Darwin 1.3 on
++ allow_undefined_flag='-flat_namespace -undefined suppress'
++ ;;
++ esac
+ # FIXME: Relying on posixy $() will cause problems for
+ # cross-compilation, but unfortunately the echo tests do not
+- # yet detect zsh echo's removal of \ escapes.
+- archive_cmds='$CC $(test .$module = .yes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs$linkopts -install_name $rpath/$soname $(test -n "$verstring" -a x$verstring != x0.0 && echo $verstring)'
++ # yet detect zsh echo's removal of \ escapes. Also zsh mangles
++ # `"' quotes if we put them in here... so don't!
++ archive_cmds='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs && $CC $(test .$module = .yes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib ${lib}-master.o $deplibs$linker_flags $(test .$module != .yes && echo -install_name $rpath/$soname $verstring)'
+ # We need to add '_' to the symbols in $export_symbols first
+ #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols'
+ hardcode_direct=yes
+@@ -1649,13 +1755,14 @@
+ export_dynamic_flag_spec='${wl}-E'
+ ;;
+
+- irix5* | irix6*)
++ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
++ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ else
+ archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
++ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ link_all_deplibs=yes
+ ;;
+@@ -1672,7 +1779,7 @@
+ ;;
+
+ newsos6)
+- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
++ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+@@ -1680,10 +1787,24 @@
+ ;;
+
+ openbsd*)
+- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+- hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
++ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
++ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
++ export_dynamic_flag_spec='${wl}-E'
++ else
++ case "$host_os" in
++ openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
++ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
++ hardcode_libdir_flag_spec='-R$libdir'
++ ;;
++ *)
++ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
++ ;;
++ esac
++ fi
+ ;;
+
+ os2*)
+@@ -1728,10 +1849,39 @@
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
++ export_dynamic_flag_spec='${wl}-Bexport'
+ ;;
+
+ solaris*)
++ # gcc --version < 3.0 without binutils cannot create self contained
++ # shared libraries reliably, requiring libgcc.a to resolve some of
++ # the object symbols generated in some cases. Libraries that use
++ # assert need libgcc.a to resolve __eprintf, for example. Linking
++ # a copy of libgcc.a into every shared library to guarantee resolving
++ # such symbols causes other problems: According to Tim Van Holder
++ # <tim.van.holder@pandora.be>, C++ libraries end up with a separate
++ # (to the application) exception stack for one thing.
+ no_undefined_flag=' -z defs'
++ if test "$GCC" = yes; then
++ case `$CC --version 2>/dev/null` in
++ [[12]].*)
++ cat <<EOF 1>&2
++
++*** Warning: Releases of GCC earlier than version 3.0 cannot reliably
++*** create self contained shared libraries on Solaris systems, without
++*** introducing a dependency on libgcc.a. Therefore, libtool is disabling
++*** -no-undefined support, which will at least allow you to build shared
++*** libraries. However, you may find that when you link such libraries
++*** into an application without using GCC, you have to manually add
++*** \`gcc --print-libgcc-file-name\` to the link command. We urge you to
++*** upgrade to a newer version of GCC. Another option is to rebuild your
++*** current GCC to use the GNU linker from GNU binutils 2.9.1 or newer.
++
++EOF
++ no_undefined_flag=
++ ;;
++ esac
++ fi
+ # $CC -shared without GNU ld will not create a library from C++
+ # object files and a static libstdc++, better avoid it by now
+ archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+@@ -1740,7 +1890,7 @@
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_shlibpath_var=no
+ case $host_os in
+- [solaris2.[0-5] | solaris2.[0-5].*]) ;;
++ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+ whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
+ esac
+@@ -1762,13 +1912,23 @@
+ ;;
+
+ sysv4)
+- if test "x$host_vendor" = xsno; then
+- archive_cmds='$LD -G -Bsymbolic -h $soname -o $lib $libobjs $deplibs $linkopts'
+- hardcode_direct=yes # is this really true???
+- else
+- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+- hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+- fi
++ case $host_vendor in
++ sni)
++ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ hardcode_direct=yes # is this really true???
++ ;;
++ siemens)
++ ## LD is ld it makes a PLAMLIB
++ ## CC just makes a GrossModule.
++ archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
++ reload_cmds='$CC -r -o $output$reload_objs'
++ hardcode_direct=no
++ ;;
++ motorola)
++ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
++ ;;
++ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ ;;
+@@ -1909,6 +2069,9 @@
+
+ aix4* | aix5*)
+ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}.so$major ${libname}${release}.so$versuffix $libname.so'
+@@ -1920,22 +2083,24 @@
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+- [ aix4 | aix4.[01] | aix4.[01].*)]
+- if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+- echo ' yes '
+- echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+- :
+- else
+- can_build_shared=no
+- fi
+- ;;
++ aix4 | aix4.[[01]] | aix4.[[01]].*)
++ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
++ echo ' yes '
++ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
++ :
++ else
++ can_build_shared=no
++ fi
++ ;;
+ esac
+- # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+- # soname into executable. Probably we can add versioning support to
+- # collect2, so additional links can be useful in future.
++ # AIX (on Power*) has no versioning support, so currently we can
++ # not hardcode correct soname into executable. Probably we can
++ # add versioning support to collect2, so additional links can
++ # be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+- # If using run time linking (on AIX 4.2 or later) use lib<name>.so instead of
+- # lib<name>.a to let people know that these are not typical AIX shared libraries.
++ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
++ # instead of lib<name>.a to let people know that these are not
++ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+@@ -1944,14 +2109,14 @@
+ soname_spec='${libname}${release}.so$major'
+ fi
+ shlibpath_var=LIBPATH
+- deplibs_check_method=pass_all
+ fi
++ hardcode_into_libs=yes
+ ;;
+
+ amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+- finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | [$Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\'']`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
++ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
+ ;;
+
+ beos*)
+@@ -1982,7 +2147,7 @@
+ case $GCC,$host_os in
+ yes,cygwin*)
+ library_names_spec='$libname.dll.a'
+- soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | [sed -e 's/[.]/-/g']`${versuffix}.dll'
++ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll'
+ postinstall_cmds='dlpath=`bash 2>&1 -c '\''. $dir/${file}i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+@@ -1992,14 +2157,14 @@
+ $rm \$dlpath'
+ ;;
+ yes,mingw*)
+- library_names_spec='${libname}`echo ${release} | [sed -e 's/[.]/-/g']`${versuffix}.dll'
+- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g"`
++ library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll'
++ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g" -e "s,=/,/,g"`
+ ;;
+ yes,pw32*)
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll'
+ ;;
+ *)
+- library_names_spec='${libname}`echo ${release} | [sed -e 's/[.]/-/g']`${versuffix}.dll $libname.lib'
++ library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+@@ -2025,6 +2190,18 @@
+ dynamic_linker=no
+ ;;
+
++freebsd*-gnu*)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
++ soname_spec='${libname}${release}.so$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ hardcode_into_libs=yes
++ dynamic_linker='GNU/FreeBSD ld.so'
++ ;;
++
+ freebsd*)
+ objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+ version_type=freebsd-$objformat
+@@ -2076,14 +2253,17 @@
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+-irix5* | irix6*)
+- version_type=irix
++irix5* | irix6* | nonstopux*)
++ case $host_os in
++ nonstopux*) version_type=nonstopux ;;
++ *) version_type=irix ;;
++ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}.so$major'
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so $libname.so'
+ case $host_os in
+- irix5*)
++ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+@@ -2157,9 +2337,19 @@
+
+ openbsd*)
+ version_type=sunos
+- if test "$with_gnu_ld" = yes; then
+- need_lib_prefix=no
+- need_version=no
++ need_lib_prefix=no
++ need_version=no
++ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
++ case "$host_os" in
++ openbsd2.[[89]] | openbsd2.[[89]].*)
++ shlibpath_overrides_runpath=no
++ ;;
++ *)
++ shlibpath_overrides_runpath=yes
++ ;;
++ esac
++ else
++ shlibpath_overrides_runpath=yes
+ fi
+ library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+@@ -2177,11 +2367,13 @@
+ osf3* | osf4* | osf5*)
+ version_type=osf
+ need_version=no
+- soname_spec='${libname}${release}.so'
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
++ need_lib_prefix=no
++ soname_spec='${libname}${release}.so$major'
++ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
++ hardcode_into_libs=yes
+ ;;
+
+ sco3.2v5*)
+@@ -2224,6 +2416,12 @@
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
++ need_lib_prefix=no
++ export_dynamic_flag_spec='${wl}-Blargedynsym'
++ runpath_var=LD_RUN_PATH
++ ;;
++ siemens)
++ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+@@ -2270,6 +2468,33 @@
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
++AC_MSG_CHECKING([whether to build shared libraries])
++test "$can_build_shared" = "no" && enable_shared=no
++
++# On AIX, shared libraries and static libraries use the same namespace, and
++# are all built from PIC.
++case "$host_os" in
++aix3*)
++ test "$enable_shared" = yes && enable_static=no
++ if test -n "$RANLIB"; then
++ archive_cmds="$archive_cmds~\$RANLIB \$lib"
++ postinstall_cmds='$RANLIB $lib'
++ fi
++ ;;
++
++aix4*)
++ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
++ test "$enable_shared" = yes && enable_static=no
++ fi
++ ;;
++esac
++AC_MSG_RESULT([$enable_shared])
++
++AC_MSG_CHECKING([whether to build static libraries])
++# Make sure either enable_shared or enable_static is yes.
++test "$enable_shared" = yes || enable_static=yes
++AC_MSG_RESULT([$enable_static])
++
+ if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+@@ -2351,7 +2576,7 @@
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+- for var in echo old_CC old_CFLAGS \
++ for var in echo old_CC old_CFLAGS SED \
+ AR AR_FLAGS CC LD LN_S NM SHELL \
+ reload_flag reload_cmds wl \
+ pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
+@@ -2363,6 +2588,7 @@
+ old_striplib striplib file_magic_cmd export_symbols_cmds \
+ deplibs_check_method allow_undefined_flag no_undefined_flag \
+ finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
++ global_symbol_to_c_name_address \
+ hardcode_libdir_flag_spec hardcode_libdir_separator \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
+@@ -2412,8 +2638,11 @@
+ # configuration script generated by Autoconf, you may include it under
+ # the same distribution terms that you use for the rest of that program.
+
++# A sed that does not truncate output.
++SED=$lt_SED
++
+ # Sed that helps us avoid accidentally triggering echo(1) options like -n.
+-Xsed="sed -e s/^X//"
++Xsed="${SED} -e s/^X//"
+
+ # The HP-UX ksh and POSIX shell print the target directory to stdout
+ # if CDPATH is set.
+@@ -2429,12 +2658,12 @@
+ # Whether or not to build shared libraries.
+ build_libtool_libs=$enable_shared
+
+-# Whether or not to add -lc for building shared libraries.
+-build_libtool_need_lc=$need_lc
+-
+ # Whether or not to build static libraries.
+ build_old_libs=$enable_static
+
++# Whether or not to add -lc for building shared libraries.
++build_libtool_need_lc=$need_lc
++
+ # Whether or not to optimize for fast installation.
+ fast_install=$enable_fast_install
+
+@@ -2600,6 +2829,9 @@
+ # Transform the output of nm in a proper C declaration
+ global_symbol_to_cdecl=$lt_global_symbol_to_cdecl
+
++# Transform the output of nm in a C name address pair
++global_symbol_to_c_name_address=$lt_global_symbol_to_c_name_address
++
+ # This is the shared library runtime path variable.
+ runpath_var=$runpath_var
+
+@@ -2722,9 +2954,9 @@
+ # return TRUE;
+ # }
+ # /* ltdll.c ends here */
+- # This is a source program that is used to create import libraries
+- # on Windows for dlls which lack them. Don't remove nor modify the
+- # starting and closing comments
++ # This is a source program that is used to create import libraries
++ # on Windows for dlls which lack them. Don't remove nor modify the
++ # starting and closing comments
+ # /* impgen.c starts here */
+ # /* Copyright (C) 1999-2000 Free Software Foundation, Inc.
+ #
+@@ -3079,6 +3311,7 @@
+ AC_REQUIRE([AC_PROG_CC])dnl
+ AC_REQUIRE([AC_CANONICAL_HOST])dnl
+ AC_REQUIRE([AC_CANONICAL_BUILD])dnl
++AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl
+ ac_prog=ld
+ if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+@@ -3092,8 +3325,8 @@
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+- [[\\/]* | [A-Za-z]:[\\/]*)]
+- [re_direlt='/[^/][^/]*/\.\./']
++ [[\\/]]* | [[A-Za-z]]:[[\\/]]*)
++ re_direlt='/[[^/]][[^/]]*/\.\./'
+ # Canonicalize the path of ld
+ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+@@ -3117,7 +3350,7 @@
+ fi
+ AC_CACHE_VAL(lt_cv_path_LD,
+ [if test -z "$LD"; then
+- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
++ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+@@ -3170,7 +3403,7 @@
+ # AC_DEPLIBS_CHECK_METHOD - how to check for library dependencies
+ # -- PORTME fill in with the dynamic library characteristics
+ AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
+-[AC_CACHE_CHECK([how to recognise dependant libraries],
++[AC_CACHE_CHECK([how to recognise dependent libraries],
+ lt_cv_deplibs_check_method,
+ [lt_cv_file_magic_cmd='$MAGIC_CMD'
+ lt_cv_file_magic_test_file=
+@@ -3181,7 +3414,7 @@
+ # `unknown' -- same as none, but documents that we really don't know.
+ # 'pass_all' -- all dependencies passed with no checks.
+ # 'test_compile' -- check by making test program.
+-# ['file_magic [regex]'] -- check by looking for files in library path
++# 'file_magic [[regex]]' -- check by looking for files in library path
+ # which responds to the $file_magic_cmd with a given egrep regex.
+ # If you have `file' or equivalent on your system and you're not sure
+ # whether `pass_all' will *always* work, you probably want this one.
+@@ -3196,7 +3429,7 @@
+ ;;
+
+ bsdi4*)
+- [lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)']
++ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+@@ -3210,7 +3443,7 @@
+ lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ case "$host_os" in
+- rhapsody* | darwin1.[012])
++ rhapsody* | darwin1.[[012]])
+ lt_cv_file_magic_test_file=`echo /System/Library/Frameworks/System.framework/Versions/*/System | head -1`
+ ;;
+ *) # Darwin 1.3 on
+@@ -3225,7 +3458,7 @@
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+- [lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[3-9]86 (compact )?demand paged shared library']
++ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+@@ -3240,14 +3473,14 @@
+ ;;
+
+ hpux10.20*|hpux11*)
+- [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library']
++ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+
+-irix5* | irix6*)
++irix5* | irix6* | nonstopux*)
+ case $host_os in
+- irix5*)
++ irix5* | nonstopux*)
+ # this will be overridden with pass_all, but let us keep it just in case
+ lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
+ ;;
+@@ -3259,7 +3492,7 @@
+ *) libmagic=never-match;;
+ esac
+ # this will be overridden with pass_all, but let us keep it just in case
+- [lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[1234] dynamic lib MIPS - version 1"]
++ lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[[1234]] dynamic lib MIPS - version 1"
+ ;;
+ esac
+ lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*`
+@@ -3269,29 +3502,39 @@
+ # This must be Linux ELF.
+ linux-gnu*)
+ case $host_cpu in
+- alpha* | hppa* | i*86 | powerpc* | sparc* | ia64* | s390* )
++ alpha* | hppa* | i*86 | mips | mipsel | powerpc* | sparc* | ia64* | arm* | m68k)
+ lt_cv_deplibs_check_method=pass_all ;;
+ *)
+ # glibc up to 2.1.1 does not perform some relocations on ARM
+- [lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;;]
++ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;;
+ esac
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+- [lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$']
++ lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so\.[[0-9]]+\.[[0-9]]+$'
+ else
+- [lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so$']
++ lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so$'
+ fi
+ ;;
+
+ newos6*)
+- [lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)']
++ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
++openbsd*)
++ lt_cv_file_magic_cmd=/usr/bin/file
++ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
++ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
++ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object'
++ else
++ lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library'
++ fi
++ ;;
++
+ osf3* | osf4* | osf5*)
+ # this will be overridden with pass_all, but let us keep it just in case
+ lt_cv_deplibs_check_method='file_magic COFF format alpha shared library'
+@@ -3308,14 +3551,14 @@
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+
+-[sysv5uw[78]* | sysv4*uw2*)]
++sysv5uw[[78]]* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ case $host_vendor in
+ motorola)
+- [lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]']
++ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+@@ -3323,13 +3566,16 @@
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+- [lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )']
++ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+- [lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"]
++ lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
++ siemens)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
+ esac
+ ;;
+ esac
+@@ -3341,13 +3587,14 @@
+
+ # AC_PROG_NM - find the path to a BSD-compatible name lister
+ AC_DEFUN([AC_PROG_NM],
+-[AC_MSG_CHECKING([for BSD-compatible nm])
++[AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl
++AC_MSG_CHECKING([for BSD-compatible nm])
+ AC_CACHE_VAL(lt_cv_path_NM,
+ [if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+ else
+- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
++ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm=$ac_dir/${ac_tool_prefix}nm
+@@ -3394,12 +3641,12 @@
+ ])
+
+ # AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for
+-# the libltdl convenience library and INCLTDL to the include flags for
++# the libltdl convenience library and LTDLINCL to the include flags for
+ # the libltdl header and adds --enable-ltdl-convenience to the
+-# configure arguments. Note that LIBLTDL and INCLTDL are not
++# configure arguments. Note that LIBLTDL and LTDLINCL are not
+ # AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If DIR is not
+ # provided, it is assumed to be `libltdl'. LIBLTDL will be prefixed
+-# with '${top_builddir}/' and INCLTDL will be prefixed with
++# with '${top_builddir}/' and LTDLINCL will be prefixed with
+ # '${top_srcdir}/' (note the single quotes!). If your package is not
+ # flat and you're not using automake, define top_builddir and
+ # top_srcdir appropriately in the Makefiles.
+@@ -3411,16 +3658,18 @@
+ ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+ esac
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
+- INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
++ LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
++ # For backwards non-gettext consistent compatibility...
++ INCLTDL="$LTDLINCL"
+ ])
+
+ # AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
+-# the libltdl installable library and INCLTDL to the include flags for
++# the libltdl installable library and LTDLINCL to the include flags for
+ # the libltdl header and adds --enable-ltdl-install to the configure
+-# arguments. Note that LIBLTDL and INCLTDL are not AC_SUBSTed, nor is
++# arguments. Note that LIBLTDL and LTDLINCL are not AC_SUBSTed, nor is
+ # AC_CONFIG_SUBDIRS called. If DIR is not provided and an installed
+ # libltdl is not found, it is assumed to be `libltdl'. LIBLTDL will
+-# be prefixed with '${top_builddir}/' and INCLTDL will be prefixed
++# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed
+ # with '${top_srcdir}/' (note the single quotes!). If your package is
+ # not flat and you're not using automake, define top_builddir and
+ # top_srcdir appropriately in the Makefiles.
+@@ -3438,12 +3687,14 @@
+ if test x"$enable_ltdl_install" = x"yes"; then
+ ac_configure_args="$ac_configure_args --enable-ltdl-install"
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
+- INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
++ LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+ else
+ ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+ LIBLTDL="-lltdl"
+- INCLTDL=
++ LTDLINCL=
+ fi
++ # For backwards non-gettext consistent compatibility...
++ INCLTDL="$LTDLINCL"
+ ])
+
+ # old names
+@@ -3458,3 +3709,92 @@
+ # This is just to silence aclocal about the macro not being used
+ ifelse([AC_DISABLE_FAST_INSTALL])
+
++# NOTE: This macro has been submitted for inclusion into #
++# GNU Autoconf as AC_PROG_SED. When it is available in #
++# a released version of Autoconf we should remove this #
++# macro and use it instead. #
++# LT_AC_PROG_SED
++# --------------
++# Check for a fully-functional sed program, that truncates
++# as few characters as possible. Prefer GNU sed if found.
++AC_DEFUN([LT_AC_PROG_SED],
++[AC_MSG_CHECKING([for a sed that does not truncate output])
++AC_CACHE_VAL(lt_cv_path_SED,
++[# Loop through the user's path and test for sed and gsed.
++# Then use that list of sed's as ones to test for truncation.
++as_executable_p="test -f"
++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_prog in sed gsed; do
++ for ac_exec_ext in '' $ac_executable_extensions; do
++ if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
++ _sed_list="$_sed_list $as_dir/$ac_prog$ac_exec_ext"
++ fi
++ done
++ done
++done
++
++ # Create a temporary directory, and hook for its removal unless debugging.
++$debug ||
++{
++ trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
++ trap '{ (exit 1); exit 1; }' 1 2 13 15
++}
++
++# Create a (secure) tmp directory for tmp files.
++: ${TMPDIR=/tmp}
++{
++ tmp=`(umask 077 && mktemp -d -q "$TMPDIR/sedXXXXXX") 2>/dev/null` &&
++ test -n "$tmp" && test -d "$tmp"
++} ||
++{
++ tmp=$TMPDIR/sed$$-$RANDOM
++ (umask 077 && mkdir $tmp)
++} ||
++{
++ echo "$me: cannot create a temporary directory in $TMPDIR" >&2
++ { (exit 1); exit 1; }
++}
++ _max=0
++ _count=0
++ # Add /usr/xpg4/bin/sed as it is typically found on Solaris
++ # along with /bin/sed that truncates output.
++ for _sed in $_sed_list /usr/xpg4/bin/sed; do
++ test ! -f ${_sed} && break
++ cat /dev/null > "$tmp/sed.in"
++ _count=0
++ echo ${ECHO_N-$ac_n} "0123456789${ECHO_C-$ac_c}" >"$tmp/sed.in"
++ # Check for GNU sed and select it if it is found.
++ if "${_sed}" --version 2>&1 < /dev/null | egrep '(GNU)' > /dev/null; then
++ lt_cv_path_SED=${_sed}
++ break
++ fi
++ while true; do
++ cat "$tmp/sed.in" "$tmp/sed.in" >"$tmp/sed.tmp"
++ mv "$tmp/sed.tmp" "$tmp/sed.in"
++ cp "$tmp/sed.in" "$tmp/sed.nl"
++ echo >>"$tmp/sed.nl"
++ ${_sed} -e 's/a$//' < "$tmp/sed.nl" >"$tmp/sed.out" || break
++ cmp -s "$tmp/sed.out" "$tmp/sed.nl" || break
++ # 40000 chars as input seems more than enough
++ test $_count -gt 10 && break
++ _count=`expr $_count + 1`
++ if test $_count -gt $_max; then
++ _max=$_count
++ lt_cv_path_SED=$_sed
++ fi
++ done
++ done
++ rm -rf "$tmp"
++])
++if test "X$SED" != "X"; then
++ lt_cv_path_SED=$SED
++else
++ SED=$lt_cv_path_SED
++fi
++AC_MSG_RESULT([$SED])
++])
++
+--- linux-atm-2.4.1.orig/config.guess
++++ linux-atm-2.4.1/config.guess
+@@ -1,9 +1,9 @@
+ #! /bin/sh
+ # Attempt to guess a canonical system name.
+-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+-# Free Software Foundation, Inc.
++# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
++# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+-timestamp='2001-04-20'
++timestamp='2003-05-19'
+
+ # This file is free software; you can redistribute it and/or modify it
+ # under the terms of the GNU General Public License as published by
+@@ -24,8 +24,9 @@
+ # configuration script generated by Autoconf, you may include it under
+ # the same distribution terms that you use for the rest of that program.
+
+-# Written by Per Bothner <bothner@cygnus.com>.
+-# Please send patches to <config-patches@gnu.org>.
++# Originally written by Per Bothner <per@bothner.com>.
++# Please send patches to <config-patches@gnu.org>. Submit a context
++# diff and a properly formatted ChangeLog entry.
+ #
+ # This script attempts to guess a canonical system name similar to
+ # config.sub. If it succeeds, it prints the system name on stdout, and
+@@ -52,7 +53,7 @@
+ GNU config.guess ($timestamp)
+
+ Originally written by Per Bothner.
+-Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 99, 2000
++Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ Free Software Foundation, Inc.
+
+ This is free software; see the source for copying conditions. There is NO
+@@ -87,33 +88,44 @@
+ exit 1
+ fi
+
++trap 'exit 1' 1 2 15
+
+-dummy=dummy-$$
+-trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15
++# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
++# compiler to aid in system detection is discouraged as it requires
++# temporary files to be created and, as you can see below, it is a
++# headache to deal with in a portable fashion.
+
+-# CC_FOR_BUILD -- compiler used by this script.
+ # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+ # use `HOST_CC' if defined, but it is deprecated.
+
++# Portable tmp directory creation inspired by the Autoconf team.
++
++set_cc_for_build='
++trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
++trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
++: ${TMPDIR=/tmp} ;
++ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
++ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
++ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
++dummy=$tmp/dummy ;
++tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+ case $CC_FOR_BUILD,$HOST_CC,$CC in
+- ,,) echo "int dummy(){}" > $dummy.c
+- for c in cc gcc c89 ; do
+- ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1
+- if test $? = 0 ; then
+- CC_FOR_BUILD="$c"; break
+- fi
+- done
+- rm -f $dummy.c $dummy.o $dummy.rel
++ ,,) echo "int x;" > $dummy.c ;
++ for c in cc gcc c89 c99 ; do
++ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
++ CC_FOR_BUILD="$c"; break ;
++ fi ;
++ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+- CC_FOR_BUILD=no_compiler_found
++ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+-esac
++esac ;'
+
+ # This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+-# (ghazi@noc.rutgers.edu 8/24/94.)
++# (ghazi@noc.rutgers.edu 1994-08-24)
+ if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+ fi
+@@ -127,29 +139,31 @@
+
+ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+- # Netbsd (nbsd) targets should (where applicable) match one or
++ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+- # Determine the machine/vendor (is the vendor relevant).
+- case "${UNAME_MACHINE}" in
+- amiga) machine=m68k-unknown ;;
+- arm32) machine=arm-unknown ;;
+- atari*) machine=m68k-atari ;;
+- sun3*) machine=m68k-sun ;;
+- mac68k) machine=m68k-apple ;;
+- macppc) machine=powerpc-apple ;;
+- hp3[0-9][05]) machine=m68k-hp ;;
+- ibmrt|romp-ibm) machine=romp-ibm ;;
+- *) machine=${UNAME_MACHINE}-unknown ;;
++ #
++ # Note: NetBSD doesn't particularly care about the vendor
++ # portion of the name. We always set it to "unknown".
++ sysctl="sysctl -n hw.machine_arch"
++ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
++ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
++ case "${UNAME_MACHINE_ARCH}" in
++ armeb) machine=armeb-unknown ;;
++ arm*) machine=arm-unknown ;;
++ sh3el) machine=shl-unknown ;;
++ sh3eb) machine=sh-unknown ;;
++ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+- case "${UNAME_MACHINE}" in
+- i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k)
++ case "${UNAME_MACHINE_ARCH}" in
++ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
++ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+@@ -165,69 +179,107 @@
+ ;;
+ esac
+ # The OS release
+- release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
++ # Debian GNU/NetBSD machines have a different userland, and
++ # thus, need a distinct triplet. However, they do not need
++ # kernel version information, so it can be replaced with a
++ # suitable tag, in the style of linux-gnu.
++ case "${UNAME_VERSION}" in
++ Debian*)
++ release='-gnu'
++ ;;
++ *)
++ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
++ ;;
++ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit 0 ;;
++ amiga:OpenBSD:*:*)
++ echo m68k-unknown-openbsd${UNAME_RELEASE}
++ exit 0 ;;
++ arc:OpenBSD:*:*)
++ echo mipsel-unknown-openbsd${UNAME_RELEASE}
++ exit 0 ;;
++ hp300:OpenBSD:*:*)
++ echo m68k-unknown-openbsd${UNAME_RELEASE}
++ exit 0 ;;
++ mac68k:OpenBSD:*:*)
++ echo m68k-unknown-openbsd${UNAME_RELEASE}
++ exit 0 ;;
++ macppc:OpenBSD:*:*)
++ echo powerpc-unknown-openbsd${UNAME_RELEASE}
++ exit 0 ;;
++ mvme68k:OpenBSD:*:*)
++ echo m68k-unknown-openbsd${UNAME_RELEASE}
++ exit 0 ;;
++ mvme88k:OpenBSD:*:*)
++ echo m88k-unknown-openbsd${UNAME_RELEASE}
++ exit 0 ;;
++ mvmeppc:OpenBSD:*:*)
++ echo powerpc-unknown-openbsd${UNAME_RELEASE}
++ exit 0 ;;
++ pmax:OpenBSD:*:*)
++ echo mipsel-unknown-openbsd${UNAME_RELEASE}
++ exit 0 ;;
++ sgi:OpenBSD:*:*)
++ echo mipseb-unknown-openbsd${UNAME_RELEASE}
++ exit 0 ;;
++ sun3:OpenBSD:*:*)
++ echo m68k-unknown-openbsd${UNAME_RELEASE}
++ exit 0 ;;
++ wgrisc:OpenBSD:*:*)
++ echo mipsel-unknown-openbsd${UNAME_RELEASE}
++ exit 0 ;;
++ *:OpenBSD:*:*)
++ echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
++ exit 0 ;;
+ alpha:OSF1:*:*)
+ if test $UNAME_RELEASE = "V4.0"; then
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ fi
++ # According to Compaq, /usr/sbin/psrinfo has been available on
++ # OSF/1 and Tru64 systems produced since 1995. I hope that
++ # covers most systems running today. This code pipes the CPU
++ # types through head -n 1, so we only detect the type of CPU 0.
++ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
++ case "$ALPHA_CPU_TYPE" in
++ "EV4 (21064)")
++ UNAME_MACHINE="alpha" ;;
++ "EV4.5 (21064)")
++ UNAME_MACHINE="alpha" ;;
++ "LCA4 (21066/21068)")
++ UNAME_MACHINE="alpha" ;;
++ "EV5 (21164)")
++ UNAME_MACHINE="alphaev5" ;;
++ "EV5.6 (21164A)")
++ UNAME_MACHINE="alphaev56" ;;
++ "EV5.6 (21164PC)")
++ UNAME_MACHINE="alphapca56" ;;
++ "EV5.7 (21164PC)")
++ UNAME_MACHINE="alphapca57" ;;
++ "EV6 (21264)")
++ UNAME_MACHINE="alphaev6" ;;
++ "EV6.7 (21264A)")
++ UNAME_MACHINE="alphaev67" ;;
++ "EV6.8CB (21264C)")
++ UNAME_MACHINE="alphaev68" ;;
++ "EV6.8AL (21264B)")
++ UNAME_MACHINE="alphaev68" ;;
++ "EV6.8CX (21264D)")
++ UNAME_MACHINE="alphaev68" ;;
++ "EV6.9A (21264/EV69A)")
++ UNAME_MACHINE="alphaev69" ;;
++ "EV7 (21364)")
++ UNAME_MACHINE="alphaev7" ;;
++ "EV7.9 (21364A)")
++ UNAME_MACHINE="alphaev79" ;;
++ esac
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+- cat <<EOF >$dummy.s
+- .data
+-\$Lformat:
+- .byte 37,100,45,37,120,10,0 # "%d-%x\n"
+-
+- .text
+- .globl main
+- .align 4
+- .ent main
+-main:
+- .frame \$30,16,\$26,0
+- ldgp \$29,0(\$27)
+- .prologue 1
+- .long 0x47e03d80 # implver \$0
+- lda \$2,-1
+- .long 0x47e20c21 # amask \$2,\$1
+- lda \$16,\$Lformat
+- mov \$0,\$17
+- not \$1,\$18
+- jsr \$26,printf
+- ldgp \$29,0(\$26)
+- mov 0,\$16
+- jsr \$26,exit
+- .end main
+-EOF
+- $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
+- if test "$?" = 0 ; then
+- case `./$dummy` in
+- 0-0)
+- UNAME_MACHINE="alpha"
+- ;;
+- 1-0)
+- UNAME_MACHINE="alphaev5"
+- ;;
+- 1-1)
+- UNAME_MACHINE="alphaev56"
+- ;;
+- 1-101)
+- UNAME_MACHINE="alphapca56"
+- ;;
+- 2-303)
+- UNAME_MACHINE="alphaev6"
+- ;;
+- 2-307)
+- UNAME_MACHINE="alphaev67"
+- ;;
+- esac
+- fi
+- rm -f $dummy.s $dummy
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha\ *:Windows_NT*:*)
+@@ -242,29 +294,11 @@
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit 0;;
+- amiga:OpenBSD:*:*)
+- echo m68k-unknown-openbsd${UNAME_RELEASE}
+- exit 0 ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+- arc64:OpenBSD:*:*)
+- echo mips64el-unknown-openbsd${UNAME_RELEASE}
+- exit 0 ;;
+- arc:OpenBSD:*:*)
+- echo mipsel-unknown-openbsd${UNAME_RELEASE}
+- exit 0 ;;
+- hkmips:OpenBSD:*:*)
+- echo mips-unknown-openbsd${UNAME_RELEASE}
+- exit 0 ;;
+- pmax:OpenBSD:*:*)
+- echo mipsel-unknown-openbsd${UNAME_RELEASE}
+- exit 0 ;;
+- sgi:OpenBSD:*:*)
+- echo mips-unknown-openbsd${UNAME_RELEASE}
+- exit 0 ;;
+- wgrisc:OpenBSD:*:*)
+- echo mipsel-unknown-openbsd${UNAME_RELEASE}
++ *:[Mm]orph[Oo][Ss]:*:*)
++ echo ${UNAME_MACHINE}-unknown-morphos
+ exit 0 ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+@@ -286,6 +320,10 @@
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
++ DRS?6000:UNIX_SV:4.2*:7*)
++ case `/usr/bin/uname -p` in
++ sparc) echo sparc-icl-nx7 && exit 0 ;;
++ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+@@ -314,7 +352,7 @@
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+- UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
++ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+@@ -328,9 +366,6 @@
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+- atari*:OpenBSD:*:*)
+- echo m68k-unknown-openbsd${UNAME_RELEASE}
+- exit 0 ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+@@ -357,18 +392,6 @@
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit 0 ;;
+- sun3*:OpenBSD:*:*)
+- echo m68k-unknown-openbsd${UNAME_RELEASE}
+- exit 0 ;;
+- mac68k:OpenBSD:*:*)
+- echo m68k-unknown-openbsd${UNAME_RELEASE}
+- exit 0 ;;
+- mvme68k:OpenBSD:*:*)
+- echo m68k-unknown-openbsd${UNAME_RELEASE}
+- exit 0 ;;
+- mvme88k:OpenBSD:*:*)
+- echo m88k-unknown-openbsd${UNAME_RELEASE}
+- exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+@@ -385,6 +408,7 @@
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
++ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #ifdef __cplusplus
+ #include <stdio.h> /* for printf() prototype */
+@@ -406,15 +430,20 @@
+ exit (-1);
+ }
+ EOF
+- $CC_FOR_BUILD $dummy.c -o $dummy \
+- && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+- && rm -f $dummy.c $dummy && exit 0
+- rm -f $dummy.c $dummy
++ $CC_FOR_BUILD -o $dummy $dummy.c \
++ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
++ && exit 0
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit 0 ;;
++ Motorola:*:4.3:PL8-*)
++ echo powerpc-harris-powermax
++ exit 0 ;;
++ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
++ echo powerpc-harris-powermax
++ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+@@ -475,6 +504,7 @@
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
++ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+@@ -486,8 +516,7 @@
+ exit(0);
+ }
+ EOF
+- $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+- rm -f $dummy.c $dummy
++ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+@@ -496,7 +525,7 @@
+ fi
+ exit 0 ;;
+ *:AIX:*:[45])
+- IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
++ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+@@ -536,10 +565,8 @@
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+- case "${HPUX_REV}" in
+- 11.[0-9][0-9])
+- if [ -x /usr/bin/getconf ]; then
+- sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
++ if [ -x /usr/bin/getconf ]; then
++ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+@@ -548,12 +575,13 @@
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
++ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+- fi ;;
+- esac
+- if [ "${HP_ARCH}" = "" ]; then
+- sed 's/^ //' << EOF >$dummy.c
++ fi
++ if [ "${HP_ARCH}" = "" ]; then
++ eval $set_cc_for_build
++ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+@@ -586,11 +614,21 @@
+ exit (0);
+ }
+ EOF
+- (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
+- if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
+- rm -f $dummy.c $dummy
+- fi ;;
++ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
++ test -z "$HP_ARCH" && HP_ARCH=hppa
++ fi ;;
+ esac
++ if [ ${HP_ARCH} = "hppa2.0w" ]
++ then
++ # avoid double evaluation of $set_cc_for_build
++ test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
++ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
++ then
++ HP_ARCH="hppa2.0w"
++ else
++ HP_ARCH="hppa64"
++ fi
++ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ ia64:HP-UX:*:*)
+@@ -598,6 +636,7 @@
+ echo ia64-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
++ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+@@ -623,8 +662,7 @@
+ exit (0);
+ }
+ EOF
+- $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+- rm -f $dummy.c $dummy
++ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+@@ -633,7 +671,7 @@
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+- *9??*:MPE/iX:*:*)
++ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+@@ -652,9 +690,6 @@
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+- hppa*:OpenBSD:*:*)
+- echo hppa-unknown-openbsd
+- exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+@@ -673,41 +708,33 @@
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+- CRAY*X-MP:*:*:*)
+- echo xmp-cray-unicos
+- exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+- echo ymp-cray-unicos${UNAME_RELEASE}
++ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+- -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
++ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
++ -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+- CRAY*T3D:*:*:*)
+- echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+- exit 0 ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+- CRAY-2:*:*:*)
+- echo cray2-cray-unicos
+- exit 0 ;;
++ *:UNICOS/mp:*:*)
++ echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
++ exit 0 ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+- hp300:OpenBSD:*:*)
+- echo m68k-unknown-openbsd${UNAME_RELEASE}
+- exit 0 ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+@@ -717,11 +744,19 @@
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+- *:FreeBSD:*:*)
+- echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+- exit 0 ;;
+- *:OpenBSD:*:*)
+- echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
++ *:FreeBSD:*:*|*:GNU/FreeBSD:*:*)
++ # Determine whether the default compiler uses glibc.
++ eval $set_cc_for_build
++ sed 's/^ //' << EOF >$dummy.c
++ #include <features.h>
++ #if __GLIBC__ >= 2
++ LIBC=gnu
++ #else
++ LIBC=
++ #endif
++EOF
++ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
++ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+@@ -732,11 +767,17 @@
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit 0 ;;
++ x86:Interix*:3*)
++ echo i586-pc-interix3
++ exit 0 ;;
++ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
++ echo i${UNAME_MACHINE}-pc-mks
++ exit 0 ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+- echo i386-pc-interix
++ echo i586-pc-interix
+ exit 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+@@ -756,104 +797,71 @@
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
++ cris:Linux:*:*)
++ echo cris-axis-linux-gnu
++ exit 0 ;;
+ ia64:Linux:*:*)
+- echo ${UNAME_MACHINE}-unknown-linux
++ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ mips:Linux:*:*)
+- cat >$dummy.c <<EOF
+-#ifdef __cplusplus
+-#include <stdio.h> /* for printf() prototype */
+-int main (int argc, char *argv[]) {
+-#else
+-int main (argc, argv) int argc; char *argv[]; {
+-#endif
+-#ifdef __MIPSEB__
+- printf ("%s-unknown-linux-gnu\n", argv[1]);
+-#endif
+-#ifdef __MIPSEL__
+- printf ("%sel-unknown-linux-gnu\n", argv[1]);
+-#endif
+- return 0;
+-}
++ eval $set_cc_for_build
++ sed 's/^ //' << EOF >$dummy.c
++ #undef CPU
++ #undef mips
++ #undef mipsel
++ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
++ CPU=mipsel
++ #else
++ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
++ CPU=mips
++ #else
++ CPU=
++ #endif
++ #endif
+ EOF
+- $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0
+- rm -f $dummy.c $dummy
++ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
++ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+- ppc:Linux:*:*)
+- # Determine Lib Version
+- cat >$dummy.c <<EOF
+-#include <features.h>
+-#if defined(__GLIBC__)
+-extern char __libc_version[];
+-extern char __libc_release[];
+-#endif
+-main(argc, argv)
+- int argc;
+- char *argv[];
+-{
+-#if defined(__GLIBC__)
+- printf("%s %s\n", __libc_version, __libc_release);
+-#else
+- printf("unknown\n");
+-#endif
+- return 0;
+-}
++ mips64:Linux:*:*)
++ eval $set_cc_for_build
++ sed 's/^ //' << EOF >$dummy.c
++ #undef CPU
++ #undef mips64
++ #undef mips64el
++ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
++ CPU=mips64el
++ #else
++ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
++ CPU=mips64
++ #else
++ CPU=
++ #endif
++ #endif
+ EOF
+- LIBC=""
+- $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null
+- if test "$?" = 0 ; then
+- ./$dummy | grep 1\.99 > /dev/null
+- if test "$?" = 0 ; then LIBC="libc1" ; fi
+- fi
+- rm -f $dummy.c $dummy
+- echo powerpc-unknown-linux-gnu${LIBC}
++ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
++ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
++ ;;
++ ppc:Linux:*:*)
++ echo powerpc-unknown-linux-gnu
++ exit 0 ;;
++ ppc64:Linux:*:*)
++ echo powerpc64-unknown-linux-gnu
+ exit 0 ;;
+ alpha:Linux:*:*)
+- cat <<EOF >$dummy.s
+- .data
+- \$Lformat:
+- .byte 37,100,45,37,120,10,0 # "%d-%x\n"
+- .text
+- .globl main
+- .align 4
+- .ent main
+- main:
+- .frame \$30,16,\$26,0
+- ldgp \$29,0(\$27)
+- .prologue 1
+- .long 0x47e03d80 # implver \$0
+- lda \$2,-1
+- .long 0x47e20c21 # amask \$2,\$1
+- lda \$16,\$Lformat
+- mov \$0,\$17
+- not \$1,\$18
+- jsr \$26,printf
+- ldgp \$29,0(\$26)
+- mov 0,\$16
+- jsr \$26,exit
+- .end main
+-EOF
+- LIBC=""
+- $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
+- if test "$?" = 0 ; then
+- case `./$dummy` in
+- 0-0) UNAME_MACHINE="alpha" ;;
+- 1-0) UNAME_MACHINE="alphaev5" ;;
+- 1-1) UNAME_MACHINE="alphaev56" ;;
+- 1-101) UNAME_MACHINE="alphapca56" ;;
+- 2-303) UNAME_MACHINE="alphaev6" ;;
+- 2-307) UNAME_MACHINE="alphaev67" ;;
+- esac
+- objdump --private-headers $dummy | \
+- grep ld.so.1 > /dev/null
+- if test "$?" = 0 ; then
+- LIBC="libc1"
+- fi
+- fi
+- rm -f $dummy.s $dummy
++ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
++ EV5) UNAME_MACHINE=alphaev5 ;;
++ EV56) UNAME_MACHINE=alphaev56 ;;
++ PCA56) UNAME_MACHINE=alphapca56 ;;
++ PCA57) UNAME_MACHINE=alphapca56 ;;
++ EV6) UNAME_MACHINE=alphaev6 ;;
++ EV67) UNAME_MACHINE=alphaev67 ;;
++ EV68*) UNAME_MACHINE=alphaev68 ;;
++ esac
++ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
++ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit 0 ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+@@ -883,71 +891,59 @@
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+- ld_supported_emulations=`cd /; ld --help 2>&1 \
+- | sed -ne '/supported emulations:/!d
++ # Set LC_ALL=C to ensure ld outputs messages in English.
++ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
++ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+- s/.*supported emulations: *//
++ s/.*supported targets: *//
+ s/ .*//
+ p'`
+- case "$ld_supported_emulations" in
+- i*86linux)
+- echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+- exit 0
+- ;;
+- elf_i*86)
++ case "$ld_supported_targets" in
++ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+- i*86coff)
++ a.out-i386-linux)
++ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
++ exit 0 ;;
++ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+- exit 0
+- ;;
+- esac
+- # Either a pre-BFD a.out linker (linux-gnuoldld)
+- # or one that does not give us useful --help.
+- # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout.
+- # If ld does not provide *any* "supported emulations:"
+- # that means it is gnuoldld.
+- test -z "$ld_supported_emulations" && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
+- case "${UNAME_MACHINE}" in
+- i*86)
+- VENDOR=pc;
+- ;;
+- *)
+- VENDOR=unknown;
+- ;;
++ exit 0 ;;
++ "")
++ # Either a pre-BFD a.out linker (linux-gnuoldld) or
++ # one that does not give us useful --help.
++ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
++ exit 0 ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+- cat >$dummy.c <<EOF
+-#include <features.h>
+-#ifdef __cplusplus
+-#include <stdio.h> /* for printf() prototype */
+- int main (int argc, char *argv[]) {
+-#else
+- int main (argc, argv) int argc; char *argv[]; {
+-#endif
+-#ifdef __ELF__
+-# ifdef __GLIBC__
+-# if __GLIBC__ >= 2
+- printf ("%s-${VENDOR}-linux-gnu\n", argv[1]);
+-# else
+- printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
+-# endif
+-# else
+- printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
+-# endif
+-#else
+- printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]);
+-#endif
+- return 0;
+-}
++ eval $set_cc_for_build
++ sed 's/^ //' << EOF >$dummy.c
++ #include <features.h>
++ #ifdef __ELF__
++ # ifdef __GLIBC__
++ # if __GLIBC__ >= 2
++ LIBC=gnu
++ # else
++ LIBC=gnulibc1
++ # endif
++ # else
++ LIBC=gnulibc1
++ # endif
++ #else
++ #ifdef __INTEL_COMPILER
++ LIBC=gnu
++ #else
++ LIBC=gnuaout
++ #endif
++ #endif
+ EOF
+- $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0
+- rm -f $dummy.c $dummy
++ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
++ test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+ test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+ ;;
+-# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
+-# are messed up and put the nodename in both sysname and nodename.
+ i*86:DYNIX/ptx:4*:*)
++ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
++ # earlier versions are messed up and put the nodename in both
++ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+@@ -958,6 +954,23 @@
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
++ i*86:OS/2:*:*)
++ # If we were able to find `uname', then EMX Unix compatibility
++ # is probably installed.
++ echo ${UNAME_MACHINE}-pc-os2-emx
++ exit 0 ;;
++ i*86:XTS-300:*:STOP)
++ echo ${UNAME_MACHINE}-unknown-stop
++ exit 0 ;;
++ i*86:atheos:*:*)
++ echo ${UNAME_MACHINE}-unknown-atheos
++ exit 0 ;;
++ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
++ echo i386-unknown-lynxos${UNAME_RELEASE}
++ exit 0 ;;
++ i*86:*DOS:*:*)
++ echo ${UNAME_MACHINE}-pc-msdosdjgpp
++ exit 0 ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+@@ -966,36 +979,32 @@
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit 0 ;;
+- i*86:*:5:7*)
+- # Fixed at (any) Pentium or better
+- UNAME_MACHINE=i586
+- if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then
+- echo ${UNAME_MACHINE}-sco-sysv${UNAME_RELEASE}uw${UNAME_VERSION}
+- else
+- echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
+- fi
++ i*86:*:5:[78]*)
++ case `/bin/uname -X | grep "^Machine"` in
++ *486*) UNAME_MACHINE=i486 ;;
++ *Pentium) UNAME_MACHINE=i586 ;;
++ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
++ esac
++ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit 0 ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+- UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+- (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+- (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
++ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
++ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
++ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+- (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
++ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+- (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
++ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+- i*86:*DOS:*:*)
+- echo ${UNAME_MACHINE}-pc-msdosdjgpp
+- exit 0 ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+@@ -1019,9 +1028,15 @@
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
++ mc68k:UNIX:SYSTEM5:3.51m)
++ echo m68k-convergent-sysv
++ exit 0 ;;
++ M680?0:D-NIX:5.3:*)
++ echo m68k-diab-dnix
++ exit 0 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+- 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
++ 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+@@ -1038,9 +1053,6 @@
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+- i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+- echo i386-unknown-lynxos${UNAME_RELEASE}
+- exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+@@ -1067,8 +1079,8 @@
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+- PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+- # says <Richard.M.Bartel@ccMail.Census.GOV>
++ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
++ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+@@ -1080,6 +1092,10 @@
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
++ *:VOS:*:*)
++ # From Paul.Green@stratus.com.
++ echo hppa1.1-stratus-vos
++ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+@@ -1108,6 +1124,9 @@
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
++ SX-6:SUPER-UX:*:*)
++ echo sx6-nec-superux${UNAME_RELEASE}
++ exit 0 ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+@@ -1115,18 +1134,24 @@
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Darwin:*:*)
+- echo `uname -p`-apple-darwin${UNAME_RELEASE}
++ case `uname -p` in
++ *86) UNAME_PROCESSOR=i686 ;;
++ powerpc) UNAME_PROCESSOR=powerpc ;;
++ esac
++ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit 0 ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+- if test "${UNAME_MACHINE}" = "x86pc"; then
++ UNAME_PROCESSOR=`uname -p`
++ if test "$UNAME_PROCESSOR" = "x86"; then
++ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+- echo `uname -p`-${UNAME_MACHINE}-nto-qnx
++ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit 0 ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit 0 ;;
+- NSR-[KW]:NONSTOP_KERNEL:*:*)
++ NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ *:NonStop-UX:*:*)
+@@ -1149,11 +1174,6 @@
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit 0 ;;
+- i*86:OS/2:*:*)
+- # If we were able to find `uname', then EMX Unix compatibility
+- # is probably installed.
+- echo ${UNAME_MACHINE}-pc-os2-emx
+- exit 0 ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit 0 ;;
+@@ -1177,6 +1197,7 @@
+ #echo '(No uname command or uname output not recognized.)' 1>&2
+ #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
++eval $set_cc_for_build
+ cat >$dummy.c <<EOF
+ #ifdef _SEQUENT_
+ # include <sys/types.h>
+@@ -1291,8 +1312,7 @@
+ }
+ EOF
+
+-$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0
+-rm -f $dummy.c $dummy
++$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+
+ # Apollos put the system type in the environment.
+
+--- linux-atm-2.4.1.orig/config.h.in
++++ linux-atm-2.4.1/config.h.in
+@@ -1,4 +1,4 @@
+-/* config.h.in. Generated automatically from configure.in by autoheader. */
++/* config.h.in. Generated automatically from configure.in by autoheader 2.13. */
+ #ifndef _ATM_CONFIG_H
+ #define _ATM_CONFIG_H
+
+--- linux-atm-2.4.1.orig/config.sub
++++ linux-atm-2.4.1/config.sub
+@@ -1,9 +1,9 @@
+ #! /bin/sh
+ # Configuration validation subroutine script.
+-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+-# Free Software Foundation, Inc.
++# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
++# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+-timestamp='2001-04-20'
++timestamp='2003-05-09'
+
+ # This file is (in principle) common to ALL GNU software.
+ # The presence of a machine in this file suggests that SOME GNU software
+@@ -29,7 +29,8 @@
+ # configuration script generated by Autoconf, you may include it under
+ # the same distribution terms that you use for the rest of that program.
+
+-# Please send patches to <config-patches@gnu.org>.
++# Please send patches to <config-patches@gnu.org>. Submit a context
++# diff and a properly formatted ChangeLog entry.
+ #
+ # Configuration subroutine to validate and canonicalize a configuration type.
+ # Supply the specified configuration type as an argument.
+@@ -117,7 +118,7 @@
+ # Here we must recognize all the valid KERNEL-OS combinations.
+ maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+ case $maybe_os in
+- nto-qnx* | linux-gnu* | storm-chaos* | os2-emx*)
++ nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+@@ -157,6 +158,14 @@
+ os=-vxworks
+ basic_machine=$1
+ ;;
++ -chorusos*)
++ os=-chorusos
++ basic_machine=$1
++ ;;
++ -chorusrdb)
++ os=-chorusrdb
++ basic_machine=$1
++ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+@@ -215,26 +224,48 @@
+ case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+- tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc \
+- | arm | arme[lb] | arm[bl]e | armv[2345] | armv[345][lb] | strongarm | xscale \
+- | pyramid | mn10200 | mn10300 | tron | a29k \
+- | 580 | i960 | h8300 \
+- | x86 | ppcbe | mipsbe | mipsle | shbe | shle \
+- | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
+- | hppa64 \
+- | alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \
+- | alphaev6[78] \
+- | we32k | ns16k | clipper | i370 | sh | sh[34] \
+- | powerpc | powerpcle \
+- | 1750a | dsp16xx | pdp10 | pdp11 \
+- | mips16 | mips64 | mipsel | mips64el \
+- | mips64orion | mips64orionel | mipstx39 | mipstx39el \
+- | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \
+- | mips64vr5000 | miprs64vr5000el | mcore | s390 | s390x \
+- | sparc | sparclet | sparclite | sparc64 | sparcv9 | sparcv9b \
+- | v850 | c4x \
+- | thumb | d10v | d30v | fr30 | avr | openrisc | tic80 \
+- | pj | pjl | h8500)
++ 1750a | 580 \
++ | 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 \
++ | clipper \
++ | d10v | d30v | dlx | dsp16xx \
++ | fr30 | frv \
++ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
++ | i370 | i860 | i960 | ia64 \
++ | ip2k \
++ | m32r | m68000 | m68k | m88k | mcore \
++ | mips | mipsbe | mipseb | mipsel | mipsle \
++ | mips16 \
++ | mips64 | mips64el \
++ | mips64vr | mips64vrel \
++ | mips64orion | mips64orionel \
++ | mips64vr4100 | mips64vr4100el \
++ | mips64vr4300 | mips64vr4300el \
++ | mips64vr5000 | mips64vr5000el \
++ | mipsisa32 | mipsisa32el \
++ | mipsisa32r2 | mipsisa32r2el \
++ | mipsisa64 | mipsisa64el \
++ | mipsisa64sb1 | mipsisa64sb1el \
++ | mipsisa64sr71k | mipsisa64sr71kel \
++ | mipstx39 | mipstx39el \
++ | mn10200 | mn10300 \
++ | msp430 \
++ | ns16k | ns32k \
++ | openrisc | or32 \
++ | pdp10 | pdp11 | pj | pjl \
++ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
++ | pyramid \
++ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
++ | sh64 | sh64le \
++ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
++ | strongarm \
++ | tahoe | thumb | tic80 | tron \
++ | v850 | v850e \
++ | we32k \
++ | x86 | xscale | xstormy16 | xtensa \
++ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+@@ -242,7 +273,7 @@
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+- m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | w65)
++ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+@@ -257,31 +288,60 @@
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+- # FIXME: clean up the formatting here.
+- vax-* | tahoe-* | i*86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \
+- | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* \
+- | arm-* | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \
+- | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
+- | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \
+- | xmp-* | ymp-* \
+- | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* \
+- | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \
+- | hppa2.0n-* | hppa64-* \
+- | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \
+- | alphaev6[78]-* \
+- | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \
+- | clipper-* | orion-* \
+- | sparclite-* | pdp10-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
+- | sparc64-* | sparcv9-* | sparcv9b-* | sparc86x-* \
+- | mips16-* | mips64-* | mipsel-* \
+- | mips64el-* | mips64orion-* | mips64orionel-* \
+- | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \
+- | mipstx39-* | mipstx39el-* | mcore-* \
+- | f30[01]-* | f700-* | s390-* | s390x-* | sv1-* | t3e-* \
+- | [cjt]90-* \
+- | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \
+- | thumb-* | v850-* | d30v-* | tic30-* | tic80-* | c30-* | fr30-* \
+- | bs2000-* | tic54x-* | c54x-* | x86_64-* | pj-* | pjl-*)
++ 580-* \
++ | a29k-* \
++ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
++ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
++ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
++ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
++ | avr-* \
++ | bs2000-* \
++ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
++ | clipper-* | cydra-* \
++ | d10v-* | d30v-* | dlx-* \
++ | elxsi-* \
++ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
++ | h8300-* | h8500-* \
++ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
++ | i*86-* | i860-* | i960-* | ia64-* \
++ | ip2k-* \
++ | m32r-* \
++ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
++ | m88110-* | m88k-* | mcore-* \
++ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
++ | mips16-* \
++ | mips64-* | mips64el-* \
++ | mips64vr-* | mips64vrel-* \
++ | mips64orion-* | mips64orionel-* \
++ | mips64vr4100-* | mips64vr4100el-* \
++ | mips64vr4300-* | mips64vr4300el-* \
++ | mips64vr5000-* | mips64vr5000el-* \
++ | mipsisa32-* | mipsisa32el-* \
++ | mipsisa32r2-* | mipsisa32r2el-* \
++ | mipsisa64-* | mipsisa64el-* \
++ | mipsisa64sb1-* | mipsisa64sb1el-* \
++ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
++ | mipstx39-* | mipstx39el-* \
++ | msp430-* \
++ | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
++ | orion-* \
++ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
++ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
++ | pyramid-* \
++ | romp-* | rs6000-* \
++ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
++ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
++ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
++ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
++ | tahoe-* | thumb-* \
++ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
++ | tron-* \
++ | v850-* | v850e-* | vax-* \
++ | we32k-* \
++ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
++ | xtensa-* \
++ | ymp-* \
++ | z8k-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+@@ -313,6 +373,9 @@
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
++ amd64)
++ basic_machine=x86_64-pc
++ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+@@ -344,6 +407,10 @@
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
++ c90)
++ basic_machine=c90-cray
++ os=-unicos
++ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+@@ -364,16 +431,8 @@
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+- cray | ymp)
+- basic_machine=ymp-cray
+- os=-unicos
+- ;;
+- cray2)
+- basic_machine=cray2-cray
+- os=-unicos
+- ;;
+- [cjt]90)
+- basic_machine=${basic_machine}-cray
++ cray | j90)
++ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ crds | unos)
+@@ -388,6 +447,14 @@
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
++ decsystem10* | dec10*)
++ basic_machine=pdp10-dec
++ os=-tops10
++ ;;
++ decsystem20* | dec20*)
++ basic_machine=pdp10-dec
++ os=-tops20
++ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+@@ -568,14 +635,6 @@
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+- mipsel*-linux*)
+- basic_machine=mipsel-unknown
+- os=-linux-gnu
+- ;;
+- mips*-linux*)
+- basic_machine=mips-unknown
+- os=-linux-gnu
+- ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+@@ -590,6 +649,10 @@
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
++ morphos)
++ basic_machine=powerpc-unknown
++ os=-morphos
++ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+@@ -662,6 +725,10 @@
+ np1)
+ basic_machine=np1-gould
+ ;;
++ nv1)
++ basic_machine=nv1-cray
++ os=-unicosmp
++ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+@@ -669,6 +736,10 @@
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
++ or32 | or32-*)
++ basic_machine=or32-unknown
++ os=-coff
++ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+@@ -691,19 +762,19 @@
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+- pc532 | pc532-*)
++ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+- pentium | p5 | k5 | k6 | nexgen)
++ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+- pentiumpro | p6 | 6x86 | athlon)
++ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2)
+ basic_machine=i686-pc
+ ;;
+- pentium-* | p5-* | k5-* | k6-* | nexgen-*)
++ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+@@ -718,15 +789,25 @@
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+- ;;
++ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+- ;;
++ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
++ ppc64) basic_machine=powerpc64-unknown
++ ;;
++ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
++ ;;
++ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
++ basic_machine=powerpc64le-unknown
++ ;;
++ ppc64le-* | powerpc64little-*)
++ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
++ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+@@ -744,10 +825,22 @@
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
++ s390 | s390-*)
++ basic_machine=s390-ibm
++ ;;
++ s390x | s390x-*)
++ basic_machine=s390x-ibm
++ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
++ sb1)
++ basic_machine=mipsisa64sb1-unknown
++ ;;
++ sb1el)
++ basic_machine=mipsisa64sb1el-unknown
++ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+@@ -755,7 +848,7 @@
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+- sparclite-wrs)
++ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+@@ -822,19 +915,39 @@
+ os=-dynix
+ ;;
+ t3e)
+- basic_machine=t3e-cray
++ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
++ t90)
++ basic_machine=t90-cray
++ os=-unicos
++ ;;
++ tic4x | c4x*)
++ basic_machine=tic4x-unknown
++ os=-coff
++ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
++ tic55x | c55x*)
++ basic_machine=tic55x-unknown
++ os=-coff
++ ;;
++ tic6x | c6x*)
++ basic_machine=tic6x-unknown
++ os=-coff
++ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
++ toad1)
++ basic_machine=pdp10-xkl
++ os=-tops20
++ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+@@ -859,8 +972,8 @@
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+- basic_machine=f301-fujitsu
+- ;;
++ basic_machine=f301-fujitsu
++ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+@@ -881,13 +994,13 @@
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+- xmp)
+- basic_machine=xmp-cray
+- os=-unicos
+- ;;
+- xps | xps100)
++ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
++ ymp)
++ basic_machine=ymp-cray
++ os=-unicos
++ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+@@ -908,13 +1021,6 @@
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+- mips)
+- if [ x$os = x-linux-gnu ]; then
+- basic_machine=mips-unknown
+- else
+- basic_machine=mips-mips
+- fi
+- ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+@@ -934,13 +1040,16 @@
+ we32k)
+ basic_machine=we32k-att
+ ;;
+- sh3 | sh4)
++ sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
++ sh64)
++ basic_machine=sh64-unknown
++ ;;
+ sparc | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+- cydra)
++ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+@@ -955,10 +1064,6 @@
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+- c4x*)
+- basic_machine=c4x-none
+- os=-coff
+- ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+@@ -1018,11 +1123,15 @@
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
++ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+- | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
++ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+- | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*)
++ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
++ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
++ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
++ | -powermax* | -dnix*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+@@ -1034,8 +1143,10 @@
+ ;;
+ esac
+ ;;
++ -nto-qnx*)
++ ;;
+ -nto*)
+- os=-nto-qnx
++ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+@@ -1074,14 +1185,20 @@
+ -acis*)
+ os=-aos
+ ;;
++ -atheos*)
++ os=-atheos
++ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
++ -nova*)
++ os=-rtmk-nova
++ ;;
+ -ns2 )
+- os=-nextstep2
++ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+@@ -1120,8 +1237,14 @@
+ -xenix)
+ os=-xenix
+ ;;
+- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+- os=-mint
++ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
++ os=-mint
++ ;;
++ -aros*)
++ os=-aros
++ ;;
++ -kaos*)
++ os=-kaos
+ ;;
+ -none)
+ ;;
+@@ -1154,10 +1277,11 @@
+ arm*-semi)
+ os=-aout
+ ;;
++ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+- pdp11-*)
++ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+@@ -1184,6 +1308,9 @@
+ mips*-*)
+ os=-elf
+ ;;
++ or32-*)
++ os=-coff
++ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+@@ -1247,19 +1374,19 @@
+ *-next)
+ os=-nextstep3
+ ;;
+- *-gould)
++ *-gould)
+ os=-sysv
+ ;;
+- *-highlevel)
++ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+- *-sgi)
++ *-sgi)
+ os=-irix
+ ;;
+- *-siemens)
++ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+@@ -1331,7 +1458,7 @@
+ -ptx*)
+ vendor=sequent
+ ;;
+- -vxsim* | -vxworks*)
++ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+@@ -1346,6 +1473,9 @@
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
++ -vos*)
++ vendor=stratus
++ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+--- linux-atm-2.4.1.orig/configure
++++ linux-atm-2.4.1/configure
+@@ -1,24 +1,244 @@
+ #! /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.
++# Generated by GNU Autoconf 2.57.
+ #
++# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
++# Free Software Foundation, Inc.
+ # This configure script is free software; the Free Software Foundation
+ # gives unlimited permission to copy, distribute and modify it.
++## --------------------- ##
++## M4sh Initialization. ##
++## --------------------- ##
++
++# Be Bourne compatible
++if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
++ emulate sh
++ NULLCMD=:
++ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
++ # is contrary to our usage. Disable this feature.
++ alias -g '${1+"$@"}'='"$@"'
++elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
++ set -o posix
++fi
++
++# Support unset when possible.
++if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
++ as_unset=unset
++else
++ as_unset=false
++fi
++
++
++# Work around bugs in pre-3.0 UWIN ksh.
++$as_unset ENV MAIL MAILPATH
++PS1='$ '
++PS2='> '
++PS4='+ '
++
++# NLS nuisances.
++for as_var in \
++ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
++ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
++ LC_TELEPHONE LC_TIME
++do
++ if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then
++ eval $as_var=C; export $as_var
++ else
++ $as_unset $as_var
++ fi
++done
++
++# Required to use basename.
++if expr a : '\(a\)' >/dev/null 2>&1; then
++ as_expr=expr
++else
++ as_expr=false
++fi
++
++if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
++ as_basename=basename
++else
++ as_basename=false
++fi
++
++
++# Name of the executable.
++as_me=`$as_basename "$0" ||
++$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
++ X"$0" : 'X\(//\)$' \| \
++ X"$0" : 'X\(/\)$' \| \
++ . : '\(.\)' 2>/dev/null ||
++echo X/"$0" |
++ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
++ /^X\/\(\/\/\)$/{ s//\1/; q; }
++ /^X\/\(\/\).*/{ s//\1/; q; }
++ s/.*/./; q'`
++
++
++# PATH needs CR, and LINENO needs CR and PATH.
++# Avoid depending upon Character Ranges.
++as_cr_letters='abcdefghijklmnopqrstuvwxyz'
++as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
++as_cr_Letters=$as_cr_letters$as_cr_LETTERS
++as_cr_digits='0123456789'
++as_cr_alnum=$as_cr_Letters$as_cr_digits
++
++# The user is always right.
++if test "${PATH_SEPARATOR+set}" != set; then
++ echo "#! /bin/sh" >conf$$.sh
++ echo "exit 0" >>conf$$.sh
++ chmod +x conf$$.sh
++ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
++ PATH_SEPARATOR=';'
++ else
++ PATH_SEPARATOR=:
++ fi
++ rm -f conf$$.sh
++fi
++
++
++ as_lineno_1=$LINENO
++ as_lineno_2=$LINENO
++ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
++ test "x$as_lineno_1" != "x$as_lineno_2" &&
++ test "x$as_lineno_3" = "x$as_lineno_2" || {
++ # Find who we are. Look in the path if we contain no path at all
++ # relative or not.
++ case $0 in
++ *[\\/]* ) as_myself=$0 ;;
++ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++ IFS=$as_save_IFS
++ test -z "$as_dir" && as_dir=.
++ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
++done
++
++ ;;
++ esac
++ # We did not find ourselves, most probably we were run as `sh COMMAND'
++ # in which case we are not to be found in the path.
++ if test "x$as_myself" = x; then
++ as_myself=$0
++ fi
++ if test ! -f "$as_myself"; then
++ { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
++ { (exit 1); exit 1; }; }
++ fi
++ case $CONFIG_SHELL in
++ '')
++ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
++do
++ IFS=$as_save_IFS
++ test -z "$as_dir" && as_dir=.
++ for as_base in sh bash ksh sh5; do
++ case $as_dir in
++ /*)
++ if ("$as_dir/$as_base" -c '
++ as_lineno_1=$LINENO
++ as_lineno_2=$LINENO
++ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
++ test "x$as_lineno_1" != "x$as_lineno_2" &&
++ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
++ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
++ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
++ CONFIG_SHELL=$as_dir/$as_base
++ export CONFIG_SHELL
++ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
++ fi;;
++ esac
++ done
++done
++;;
++ esac
++
++ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
++ # uniformly replaced by the line number. The first 'sed' inserts a
++ # line-number line before each line; the second 'sed' does the real
++ # work. The second script uses 'N' to pair each line-number line
++ # with the numbered line, and appends trailing '-' during
++ # substitution so that $LINENO is not a special case at line end.
++ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
++ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
++ sed '=' <$as_myself |
++ sed '
++ N
++ s,$,-,
++ : loop
++ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
++ t loop
++ s,-$,,
++ s,^['$as_cr_digits']*\n,,
++ ' >$as_me.lineno &&
++ chmod +x $as_me.lineno ||
++ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
++ { (exit 1); exit 1; }; }
++
++ # Don't try to exec as it changes $[0], causing all sort of problems
++ # (the dirname of $[0] is not the place where we might find the
++ # original and so on. Autoconf is especially sensible to this).
++ . ./$as_me.lineno
++ # Exit status is that of the last command.
++ exit
++}
++
++
++case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
++ *c*,-n*) ECHO_N= ECHO_C='
++' ECHO_T=' ' ;;
++ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
++ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
++esac
++
++if expr a : '\(a\)' >/dev/null 2>&1; then
++ as_expr=expr
++else
++ as_expr=false
++fi
++
++rm -f conf$$ conf$$.exe conf$$.file
++echo >conf$$.file
++if ln -s conf$$.file conf$$ 2>/dev/null; then
++ # We could just check for DJGPP; but this test a) works b) is more generic
++ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
++ if test -f conf$$.exe; then
++ # Don't use ln at all; we don't have any links
++ as_ln_s='cp -p'
++ else
++ as_ln_s='ln -s'
++ fi
++elif ln conf$$.file conf$$ 2>/dev/null; then
++ as_ln_s=ln
++else
++ as_ln_s='cp -p'
++fi
++rm -f conf$$ conf$$.exe conf$$.file
++
++if mkdir -p . 2>/dev/null; then
++ as_mkdir_p=:
++else
++ as_mkdir_p=false
++fi
++
++as_executable_p="test -f"
++
++# Sed expression to map a string onto a valid CPP name.
++as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
++
++# Sed expression to map a string onto a valid variable name.
++as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
++
++
++# IFS
++# We need space, tab and new line, in precisely that order.
++as_nl='
++'
++IFS=" $as_nl"
++
++# CDPATH.
++$as_unset CDPATH
+
+-# Defaults:
+-ac_help=
+-ac_default_prefix=/usr/local
+-# Any additions from configure.in:
+-ac_help="$ac_help
+- --enable-shared[=PKGS] build shared libraries [default=yes]"
+-ac_help="$ac_help
+- --enable-static[=PKGS] build static libraries [default=yes]"
+-ac_help="$ac_help
+- --enable-fast-install[=PKGS] optimize for fast installation [default=yes]"
+-ac_help="$ac_help
+- --with-gnu-ld assume the C compiler uses GNU ld [default=no]"
+
+ # Find the correct PATH separator. Usually this is `:', but
+ # DJGPP uses `;' like DOS.
+@@ -28,6 +248,7 @@
+ *-DOS) lt_cv_sys_path_separator=';' ;;
+ *) lt_cv_sys_path_separator=':' ;;
+ esac
++ PATH_SEPARATOR=$lt_cv_sys_path_separator
+ fi
+
+
+@@ -94,7 +315,7 @@
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
++ IFS="${IFS= }"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+@@ -177,34 +398,86 @@
+ fi
+
+
+-ac_help="$ac_help
+- --disable-libtool-lock avoid locking (might break parallel builds)"
+-ac_help="$ac_help
+- --with-pic try to use only PIC/non-PIC objects [default=use both]"
+-ac_help="$ac_help
+- --with-uni=VERSION UNI version to use (3.0,3.1,4.0) [default=dynamic]"
+-ac_help="$ac_help
+- --enable-allow_uni30 Allow UNI 3.0 backwards-compatible extensions (if using UNI 3.1)"
+-ac_help="$ac_help
+- --enable-q2963_1 Enable peak cell rate modification as specified in Q.2963.1 (if using UNI 4.0)"
+-ac_help="$ac_help
+- --enable-cisco Enable work around for point-to-multipoint signaling bug in Cisco LS100 or LS7010 switches"
+-ac_help="$ac_help
+- --enable-thomflex Some versions of the Thomson Thomflex 5000 won't do any signaling before they get a RESTART. Enable sending of a RESTART whenever SAAL comes up."
+-ac_help="$ac_help
+- --enable-mpoa_1_1 Enable proposed MPOA 1.1 features"
+-ac_help="$ac_help
+- --enable-mpr Enable memory debugging (if MPR is installed)"
++
++# Name of the host.
++# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
++# so uname gets run too.
++ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
++
++exec 6>&1
++
++#
++# Initializations.
++#
++ac_default_prefix=/usr/local
++ac_config_libobj_dir=.
++cross_compiling=no
++subdirs=
++MFLAGS=
++MAKEFLAGS=
++SHELL=${CONFIG_SHELL-/bin/sh}
++
++# Maximum number of lines to put in a shell here document.
++# This variable seems obsolete. It should probably be removed, and
++# only ac_max_sed_lines should be used.
++: ${ac_max_here_lines=38}
++
++# Identity of this package.
++PACKAGE_NAME=
++PACKAGE_TARNAME=
++PACKAGE_VERSION=
++PACKAGE_STRING=
++PACKAGE_BUGREPORT=
++
++ac_unique_file="src/include/atm.h"
++# Factoring default headers for most tests.
++ac_includes_default="\
++#include <stdio.h>
++#if HAVE_SYS_TYPES_H
++# include <sys/types.h>
++#endif
++#if HAVE_SYS_STAT_H
++# include <sys/stat.h>
++#endif
++#if STDC_HEADERS
++# include <stdlib.h>
++# include <stddef.h>
++#else
++# if HAVE_STDLIB_H
++# include <stdlib.h>
++# endif
++#endif
++#if HAVE_STRING_H
++# if !STDC_HEADERS && HAVE_MEMORY_H
++# include <memory.h>
++# endif
++# include <string.h>
++#endif
++#if HAVE_STRINGS_H
++# include <strings.h>
++#endif
++#if HAVE_INTTYPES_H
++# include <inttypes.h>
++#else
++# if HAVE_STDINT_H
++# include <stdint.h>
++# endif
++#endif
++#if HAVE_UNISTD_H
++# 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 build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO SET_MAKE LIBVER_CURRENT LIBVER_REVISION LIBVER_AGE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT LEX LEXLIB LEX_OUTPUT_ROOT YACC LN_S ECHO RANLIB ac_ct_RANLIB STRIP ac_ct_STRIP CPP EGREP LIBTOOL LIBTOOL_DEPS PERL LIBOBJS LTLIBOBJS'
++ac_subst_files=''
+
+ # Initialize some variables set by options.
++ac_init_help=
++ac_init_version=false
+ # The variables have the same names as the options, with
+ # dashes changed to underlines.
+-build=NONE
+-cache_file=./config.cache
++cache_file=/dev/null
+ exec_prefix=NONE
+-host=NONE
+ no_create=
+-nonopt=NONE
+ no_recursion=
+ prefix=NONE
+ program_prefix=NONE
+@@ -213,10 +486,15 @@
+ silent=
+ site=
+ srcdir=
+-target=NONE
+ verbose=
+ x_includes=NONE
+ x_libraries=NONE
++
++# Installation directory options.
++# These are left unexpanded so users can "make install exec_prefix=/foo"
++# and all the variables that are supposed to be based on exec_prefix
++# by default will actually change.
++# Use braces instead of parens because sh, perl, etc. also accept them.
+ bindir='${exec_prefix}/bin'
+ sbindir='${exec_prefix}/sbin'
+ libexecdir='${exec_prefix}/libexec'
+@@ -230,17 +508,9 @@
+ 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"
+@@ -248,59 +518,59 @@
+ continue
+ fi
+
+- case "$ac_option" in
+- -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+- *) ac_optarg= ;;
+- esac
++ ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+- case "$ac_option" in
++ case $ac_option in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+- bindir="$ac_optarg" ;;
++ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+- ac_prev=build ;;
++ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+- build="$ac_optarg" ;;
++ build_alias=$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" ;;
++ cache_file=$ac_optarg ;;
++
++ --config-cache | -C)
++ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+- datadir="$ac_optarg" ;;
++ datadir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+- ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
++ ac_feature=`expr "x$ac_option" : 'x-*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" ;;
++ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
++ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
++ { (exit 1); exit 1; }; }
++ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
++ eval "enable_$ac_feature=no" ;;
+
+ -enable-* | --enable-*)
+- ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
++ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # 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
+- *=*) ;;
++ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
++ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
++ { (exit 1); exit 1; }; }
++ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
++ case $ac_option in
++ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+- eval "enable_${ac_feature}='$ac_optarg'" ;;
++ eval "enable_$ac_feature='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+@@ -309,95 +579,47 @@
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+- exec_prefix="$ac_optarg" ;;
++ 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 ;;
++ -help | --help | --hel | --he | -h)
++ ac_init_help=long ;;
++ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
++ ac_init_help=recursive ;;
++ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
++ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+- ac_prev=host ;;
++ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+- host="$ac_optarg" ;;
++ host_alias=$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" ;;
++ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+- infodir="$ac_optarg" ;;
++ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+- libdir="$ac_optarg" ;;
++ 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" ;;
++ libexecdir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+@@ -406,19 +628,19 @@
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+- localstatedir="$ac_optarg" ;;
++ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+- mandir="$ac_optarg" ;;
++ 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-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+@@ -432,26 +654,26 @@
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+- oldincludedir="$ac_optarg" ;;
++ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+- prefix="$ac_optarg" ;;
++ 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_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_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+@@ -468,7 +690,7 @@
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+- program_transform_name="$ac_optarg" ;;
++ program_transform_name=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+@@ -478,7 +700,7 @@
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+- sbindir="$ac_optarg" ;;
++ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+@@ -489,58 +711,57 @@
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+- sharedstatedir="$ac_optarg" ;;
++ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+- site="$ac_optarg" ;;
++ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+- srcdir="$ac_optarg" ;;
++ 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" ;;
++ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+- ac_prev=target ;;
++ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+- target="$ac_optarg" ;;
++ target_alias=$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 ;;
++ -version | --version | --versio | --versi | --vers | -V)
++ ac_init_version=: ;;
+
+ -with-* | --with-*)
+- ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
++ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # 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
++ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
++ { echo "$as_me: error: invalid package name: $ac_package" >&2
++ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+- case "$ac_option" in
+- *=*) ;;
++ case $ac_option in
++ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+- eval "with_${ac_package}='$ac_optarg'" ;;
++ eval "with_$ac_package='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+- ac_package=`echo $ac_option|sed -e 's/-*without-//'`
++ ac_package=`expr "x$ac_option" : 'x-*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" ;;
++ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
++ { echo "$as_me: error: invalid package name: $ac_package" >&2
++ { (exit 1); exit 1; }; }
++ ac_package=`echo $ac_package | sed 's/-/_/g'`
++ eval "with_$ac_package=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+@@ -551,99 +772,110 @@
+ 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_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" ;;
++ x_libraries=$ac_optarg ;;
+
+- -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
++ -*) { echo "$as_me: error: unrecognized option: $ac_option
++Try \`$0 --help' for more information." >&2
++ { (exit 1); exit 1; }; }
+ ;;
+
++ *=*)
++ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
++ # Reject names that are not valid shell variable names.
++ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
++ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
++ { (exit 1); exit 1; }; }
++ ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
++ eval "$ac_envvar='$ac_optarg'"
++ export $ac_envvar ;;
++
+ *)
+- 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"
++ # FIXME: should be removed in autoconf 3.0.
++ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
++ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
++ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
++ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$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
++ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
++ { echo "$as_me: error: missing argument to $ac_option" >&2
++ { (exit 1); exit 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
++# Be sure to have absolute paths.
++for ac_var in exec_prefix prefix
++do
++ eval ac_val=$`echo $ac_var`
++ case $ac_val in
++ [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
++ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
++ { (exit 1); exit 1; }; };;
++ esac
++done
+
+-# 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
++# Be sure to have absolute paths.
++for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
++ localstatedir libdir includedir oldincludedir infodir mandir
+ 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" ;;
++ eval ac_val=$`echo $ac_var`
++ case $ac_val in
++ [\\/$]* | ?:[\\/]* ) ;;
++ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
++ { (exit 1); exit 1; }; };;
+ esac
+ done
+
+-# 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
++# There might be people who depend on the old broken behavior: `$host'
++# used to hold the argument of --host etc.
++# FIXME: To remove some day.
++build=$build_alias
++host=$host_alias
++target=$target_alias
++
++# FIXME: To remove some day.
++if test "x$host_alias" != x; then
++ if test "x$build_alias" = x; then
++ cross_compiling=maybe
++ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
++ If a cross compiler is detected then cross compile mode will be used." >&2
++ elif test "x$build_alias" != "x$host_alias"; then
++ cross_compiling=yes
++ fi
++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
++ac_tool_prefix=
++test -n "$host_alias" && ac_tool_prefix=$host_alias-
++
++test "$silent" = yes && exec 6>/dev/null
+
+-# 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=src/include/atm.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=.
++ ac_confdir=`(dirname "$0") 2>/dev/null ||
++$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
++ X"$0" : 'X\(//\)[^/]' \| \
++ X"$0" : 'X\(//\)$' \| \
++ X"$0" : 'X\(/\)' \| \
++ . : '\(.\)' 2>/dev/null ||
++echo X"$0" |
++ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
++ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
++ /^X\(\/\/\)$/{ s//\1/; q; }
++ /^X\(\/\).*/{ s//\1/; q; }
++ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+@@ -653,13 +885,453 @@
+ 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; }
++ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
++ { (exit 1); exit 1; }; }
+ else
+- { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
++ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
++ { (exit 1); exit 1; }; }
+ fi
+ fi
+-srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
++(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
++ { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
++ { (exit 1); exit 1; }; }
++srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
++ac_env_build_alias_set=${build_alias+set}
++ac_env_build_alias_value=$build_alias
++ac_cv_env_build_alias_set=${build_alias+set}
++ac_cv_env_build_alias_value=$build_alias
++ac_env_host_alias_set=${host_alias+set}
++ac_env_host_alias_value=$host_alias
++ac_cv_env_host_alias_set=${host_alias+set}
++ac_cv_env_host_alias_value=$host_alias
++ac_env_target_alias_set=${target_alias+set}
++ac_env_target_alias_value=$target_alias
++ac_cv_env_target_alias_set=${target_alias+set}
++ac_cv_env_target_alias_value=$target_alias
++ac_env_CC_set=${CC+set}
++ac_env_CC_value=$CC
++ac_cv_env_CC_set=${CC+set}
++ac_cv_env_CC_value=$CC
++ac_env_CFLAGS_set=${CFLAGS+set}
++ac_env_CFLAGS_value=$CFLAGS
++ac_cv_env_CFLAGS_set=${CFLAGS+set}
++ac_cv_env_CFLAGS_value=$CFLAGS
++ac_env_LDFLAGS_set=${LDFLAGS+set}
++ac_env_LDFLAGS_value=$LDFLAGS
++ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
++ac_cv_env_LDFLAGS_value=$LDFLAGS
++ac_env_CPPFLAGS_set=${CPPFLAGS+set}
++ac_env_CPPFLAGS_value=$CPPFLAGS
++ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
++ac_cv_env_CPPFLAGS_value=$CPPFLAGS
++ac_env_CPP_set=${CPP+set}
++ac_env_CPP_value=$CPP
++ac_cv_env_CPP_set=${CPP+set}
++ac_cv_env_CPP_value=$CPP
++
++#
++# Report the --help message.
++#
++if test "$ac_init_help" = "long"; then
++ # 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 <<_ACEOF
++\`configure' configures this package to adapt to many kinds of systems.
++
++Usage: $0 [OPTION]... [VAR=VALUE]...
++
++To assign environment variables (e.g., CC, CFLAGS...), specify them as
++VAR=VALUE. See below for descriptions of some of the useful variables.
++
++Defaults for the options are specified in brackets.
++
++Configuration:
++ -h, --help display this help and exit
++ --help=short display options specific to this package
++ --help=recursive display the short help of all the included packages
++ -V, --version display version information and exit
++ -q, --quiet, --silent do not print \`checking...' messages
++ --cache-file=FILE cache test results in FILE [disabled]
++ -C, --config-cache alias for \`--cache-file=config.cache'
++ -n, --no-create do not create output files
++ --srcdir=DIR find the sources in DIR [configure dir or \`..']
++
++_ACEOF
++
++ cat <<_ACEOF
++Installation directories:
++ --prefix=PREFIX install architecture-independent files in PREFIX
++ [$ac_default_prefix]
++ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
++ [PREFIX]
++
++By default, \`make install' will install all the files in
++\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
++an installation prefix other than \`$ac_default_prefix' using \`--prefix',
++for instance \`--prefix=\$HOME'.
++
++For better control, use the options below.
++
++Fine tuning of the installation directories:
++ --bindir=DIR user executables [EPREFIX/bin]
++ --sbindir=DIR system admin executables [EPREFIX/sbin]
++ --libexecdir=DIR program executables [EPREFIX/libexec]
++ --datadir=DIR read-only architecture-independent data [PREFIX/share]
++ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
++ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
++ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
++ --libdir=DIR object code libraries [EPREFIX/lib]
++ --includedir=DIR C header files [PREFIX/include]
++ --oldincludedir=DIR C header files for non-gcc [/usr/include]
++ --infodir=DIR info documentation [PREFIX/info]
++ --mandir=DIR man documentation [PREFIX/man]
++_ACEOF
++
++ cat <<\_ACEOF
++
++Program names:
++ --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
++
++System types:
++ --build=BUILD configure for building on BUILD [guessed]
++ --host=HOST cross-compile to build programs to run on HOST [BUILD]
++ --target=TARGET configure for building compilers for TARGET [HOST]
++_ACEOF
++fi
++
++if test -n "$ac_init_help"; then
++
++ cat <<\_ACEOF
++
++Optional Features:
++ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
++ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
++ --enable-shared=PKGS build shared libraries default=yes
++ --enable-static=PKGS build static libraries default=yes
++ --enable-fast-install=PKGS optimize for fast installation default=yes
++ --disable-libtool-lock avoid locking (might break parallel builds)
++ --enable-allow_uni30 Allow UNI 3.0 backwards-compatible extensions (if using UNI 3.1)
++ --enable-q2963_1 Enable peak cell rate modification as specified in Q.2963.1 (if using UNI 4.0)
++ --enable-cisco Enable work around for point-to-multipoint signaling bug in Cisco LS100 or LS7010 switches
++ --enable-thomflex Some versions of the Thomson Thomflex 5000 won't do any signaling before they get a RESTART. Enable sending of a RESTART whenever SAAL comes up.
++ --enable-mpoa_1_1 Enable proposed MPOA 1.1 features
++ --enable-mpr Enable memory debugging (if MPR is installed)
++
++Optional Packages:
++ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
++ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
++ --with-gnu-ld assume the C compiler uses GNU ld default=no
++ --with-pic try to use only PIC/non-PIC objects default=use both
++ --with-uni=VERSION UNI version to use (3.0,3.1,4.0) default=dynamic
++
++Some influential environment variables:
++ CC C compiler command
++ CFLAGS C compiler flags
++ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
++ nonstandard directory <lib dir>
++ CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
++ headers in a nonstandard directory <include dir>
++ CPP C preprocessor
++
++Use these variables to override the choices made by `configure' or to help
++it to find libraries and programs with nonstandard names/locations.
++
++_ACEOF
++fi
++
++if test "$ac_init_help" = "recursive"; then
++ # If there are subdirs, report their specific --help.
++ ac_popdir=`pwd`
++ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
++ test -d $ac_dir || continue
++ ac_builddir=.
++
++if test "$ac_dir" != .; then
++ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
++ # A "../" for each directory in $ac_dir_suffix.
++ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
++else
++ ac_dir_suffix= ac_top_builddir=
++fi
++
++case $srcdir in
++ .) # No --srcdir option. We are building in place.
++ ac_srcdir=.
++ if test -z "$ac_top_builddir"; then
++ ac_top_srcdir=.
++ else
++ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
++ fi ;;
++ [\\/]* | ?:[\\/]* ) # Absolute path.
++ ac_srcdir=$srcdir$ac_dir_suffix;
++ ac_top_srcdir=$srcdir ;;
++ *) # Relative path.
++ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
++ ac_top_srcdir=$ac_top_builddir$srcdir ;;
++esac
++# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
++# absolute.
++ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
++ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
++ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
++ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
++
++ cd $ac_dir
++ # Check for guested configure; otherwise get Cygnus style configure.
++ if test -f $ac_srcdir/configure.gnu; then
++ echo
++ $SHELL $ac_srcdir/configure.gnu --help=recursive
++ elif test -f $ac_srcdir/configure; then
++ echo
++ $SHELL $ac_srcdir/configure --help=recursive
++ elif test -f $ac_srcdir/configure.ac ||
++ test -f $ac_srcdir/configure.in; then
++ echo
++ $ac_configure --help
++ else
++ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
++ fi
++ cd $ac_popdir
++ done
++fi
++
++test -n "$ac_init_help" && exit 0
++if $ac_init_version; then
++ cat <<\_ACEOF
++
++Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
++Free Software Foundation, Inc.
++This configure script is free software; the Free Software Foundation
++gives unlimited permission to copy, distribute and modify it.
++_ACEOF
++ exit 0
++fi
++exec 5>config.log
++cat >&5 <<_ACEOF
++This file contains any messages produced by compilers while
++running configure, to aid debugging if configure makes a mistake.
++
++It was created by $as_me, which was
++generated by GNU Autoconf 2.57. Invocation command line was
++
++ $ $0 $@
++
++_ACEOF
++{
++cat <<_ASUNAME
++## --------- ##
++## Platform. ##
++## --------- ##
++
++hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
++uname -m = `(uname -m) 2>/dev/null || echo unknown`
++uname -r = `(uname -r) 2>/dev/null || echo unknown`
++uname -s = `(uname -s) 2>/dev/null || echo unknown`
++uname -v = `(uname -v) 2>/dev/null || echo unknown`
++
++/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
++/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
++
++/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
++/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
++/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
++hostinfo = `(hostinfo) 2>/dev/null || echo unknown`
++/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
++/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
++/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
++
++_ASUNAME
++
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++ IFS=$as_save_IFS
++ test -z "$as_dir" && as_dir=.
++ echo "PATH: $as_dir"
++done
++
++} >&5
++
++cat >&5 <<_ACEOF
++
++
++## ----------- ##
++## Core tests. ##
++## ----------- ##
++
++_ACEOF
++
++
++# Keep a trace of the command line.
++# Strip out --no-create and --no-recursion so they do not pile up.
++# Strip out --silent because we don't want to record it for future runs.
++# Also quote any args containing shell meta-characters.
++# Make two passes to allow for proper duplicate-argument suppression.
++ac_configure_args=
++ac_configure_args0=
++ac_configure_args1=
++ac_sep=
++ac_must_keep_next=false
++for ac_pass in 1 2
++do
++ for ac_arg
++ do
++ case $ac_arg in
++ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
++ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
++ | -silent | --silent | --silen | --sile | --sil)
++ continue ;;
++ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
++ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
++ esac
++ case $ac_pass in
++ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
++ 2)
++ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
++ if test $ac_must_keep_next = true; then
++ ac_must_keep_next=false # Got value, back to normal.
++ else
++ case $ac_arg in
++ *=* | --config-cache | -C | -disable-* | --disable-* \
++ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
++ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
++ | -with-* | --with-* | -without-* | --without-* | --x)
++ case "$ac_configure_args0 " in
++ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
++ esac
++ ;;
++ -* ) ac_must_keep_next=true ;;
++ esac
++ fi
++ ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
++ # Get rid of the leading space.
++ ac_sep=" "
++ ;;
++ esac
++ done
++done
++$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
++$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
++
++# When interrupted or exit'd, cleanup temporary files, and complete
++# config.log. We remove comments because anyway the quotes in there
++# would cause problems or look ugly.
++# WARNING: Be sure not to use single quotes in there, as some shells,
++# such as our DU 5.0 friend, will then `close' the trap.
++trap 'exit_status=$?
++ # Save into config.log some information that might help in debugging.
++ {
++ echo
++
++ cat <<\_ASBOX
++## ---------------- ##
++## Cache variables. ##
++## ---------------- ##
++_ASBOX
++ echo
++ # The following way of writing the cache mishandles newlines in values,
++{
++ (set) 2>&1 |
++ case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
++ *ac_space=\ *)
++ sed -n \
++ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
++ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
++ ;;
++ *)
++ sed -n \
++ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
++ ;;
++ esac;
++}
++ echo
++
++ cat <<\_ASBOX
++## ----------------- ##
++## Output variables. ##
++## ----------------- ##
++_ASBOX
++ echo
++ for ac_var in $ac_subst_vars
++ do
++ eval ac_val=$`echo $ac_var`
++ echo "$ac_var='"'"'$ac_val'"'"'"
++ done | sort
++ echo
++
++ if test -n "$ac_subst_files"; then
++ cat <<\_ASBOX
++## ------------- ##
++## Output files. ##
++## ------------- ##
++_ASBOX
++ echo
++ for ac_var in $ac_subst_files
++ do
++ eval ac_val=$`echo $ac_var`
++ echo "$ac_var='"'"'$ac_val'"'"'"
++ done | sort
++ echo
++ fi
++
++ if test -s confdefs.h; then
++ cat <<\_ASBOX
++## ----------- ##
++## confdefs.h. ##
++## ----------- ##
++_ASBOX
++ echo
++ sed "/^$/d" confdefs.h | sort
++ echo
++ fi
++ test "$ac_signal" != 0 &&
++ echo "$as_me: caught signal $ac_signal"
++ echo "$as_me: exit $exit_status"
++ } >&5
++ rm -f core *.core &&
++ rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
++ exit $exit_status
++ ' 0
++for ac_signal in 1 2 13 15; do
++ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
++done
++ac_signal=0
++
++# 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
++
++# Predefined preprocessor variables.
+
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE_NAME "$PACKAGE_NAME"
++_ACEOF
++
++
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
++_ACEOF
++
++
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE_VERSION "$PACKAGE_VERSION"
++_ACEOF
++
++
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE_STRING "$PACKAGE_STRING"
++_ACEOF
++
++
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
++_ACEOF
++
++
++# Let the site file select an alternate cache file if it wants to.
+ # Prefer explicitly selected file to automatically selected ones.
+ if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+@@ -670,45 +1342,111 @@
+ fi
+ for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+- echo "loading site script $ac_site_file"
++ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
++echo "$as_me: loading site script $ac_site_file" >&6;}
++ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+ done
+
+ if test -r "$cache_file"; then
+- echo "loading cache $cache_file"
+- . $cache_file
++ # Some versions of bash will fail to source /dev/null (special
++ # files actually), so we avoid doing that.
++ if test -f "$cache_file"; then
++ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
++echo "$as_me: loading cache $cache_file" >&6;}
++ case $cache_file in
++ [\\/]* | ?:[\\/]* ) . $cache_file;;
++ *) . ./$cache_file;;
++ esac
++ fi
+ else
+- echo "creating cache $cache_file"
+- > $cache_file
++ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
++echo "$as_me: creating cache $cache_file" >&6;}
++ >$cache_file
++fi
++
++# Check that the precious variables saved in the cache have kept the same
++# value.
++ac_cache_corrupted=false
++for ac_var in `(set) 2>&1 |
++ sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
++ eval ac_old_set=\$ac_cv_env_${ac_var}_set
++ eval ac_new_set=\$ac_env_${ac_var}_set
++ eval ac_old_val="\$ac_cv_env_${ac_var}_value"
++ eval ac_new_val="\$ac_env_${ac_var}_value"
++ case $ac_old_set,$ac_new_set in
++ set,)
++ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
++echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
++ ac_cache_corrupted=: ;;
++ ,set)
++ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
++echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
++ ac_cache_corrupted=: ;;
++ ,);;
++ *)
++ if test "x$ac_old_val" != "x$ac_new_val"; then
++ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
++echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
++ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
++echo "$as_me: former value: $ac_old_val" >&2;}
++ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
++echo "$as_me: current value: $ac_new_val" >&2;}
++ ac_cache_corrupted=:
++ fi;;
++ esac
++ # Pass precious variables to config.status.
++ if test "$ac_new_set" = set; then
++ case $ac_new_val in
++ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
++ ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
++ *) ac_arg=$ac_var=$ac_new_val ;;
++ esac
++ case " $ac_configure_args " in
++ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
++ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
++ esac
++ fi
++done
++if $ac_cache_corrupted; then
++ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
++echo "$as_me: error: changes in the environment can compromise the build" >&2;}
++ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
++echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
++ { (exit 1); exit 1; }; }
+ fi
+
+ ac_ext=c
+-# 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_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
++
++
++
++
++
++
++
++
++
++
+
+
+
+
+
+
++
++
++
++
++ ac_config_headers="$ac_config_headers config.h"
++
++ ac_config_commands="$ac_config_commands default-1"
++
++
+ ac_aux_dir=
+ for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+@@ -719,105 +1457,105 @@
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
++ elif test -f $ac_dir/shtool; then
++ ac_aux_dir=$ac_dir
++ ac_install_sh="$ac_aux_dir/shtool install -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.
+-
+-
+-# Do some error checking and defaulting for the host and target type.
+-# The inputs are:
+-# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+-#
+-# The rules are:
+-# 1. You are not allowed to specify --host, --target, and nonopt at the
+-# same time.
+-# 2. Host defaults to nonopt.
+-# 3. If nonopt is not specified, then host defaults to the current host,
+-# as determined by config.guess.
+-# 4. Target and build default to nonopt.
+-# 5. If nonopt is not specified, then target and build default to host.
+-
+-# The aliases save the names the user supplied, while $host etc.
+-# will get canonicalized.
+-case $host---$target---$nonopt in
+-NONE---*---* | *---NONE---* | *---*---NONE) ;;
+-*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+-esac
+-
++ { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
++echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
++ { (exit 1); exit 1; }; }
++fi
++ac_config_guess="$SHELL $ac_aux_dir/config.guess"
++ac_config_sub="$SHELL $ac_aux_dir/config.sub"
++ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+ # Make sure we can run config.sub.
+-if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+-else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+-fi
++$ac_config_sub sun4 >/dev/null 2>&1 ||
++ { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5
++echo "$as_me: error: cannot run $ac_config_sub" >&2;}
++ { (exit 1); exit 1; }; }
++
++echo "$as_me:$LINENO: checking build system type" >&5
++echo $ECHO_N "checking build system type... $ECHO_C" >&6
++if test "${ac_cv_build+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ ac_cv_build_alias=$build_alias
++test -z "$ac_cv_build_alias" &&
++ ac_cv_build_alias=`$ac_config_guess`
++test -z "$ac_cv_build_alias" &&
++ { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
++echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
++ { (exit 1); exit 1; }; }
++ac_cv_build=`$ac_config_sub $ac_cv_build_alias` ||
++ { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5
++echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;}
++ { (exit 1); exit 1; }; }
++
++fi
++echo "$as_me:$LINENO: result: $ac_cv_build" >&5
++echo "${ECHO_T}$ac_cv_build" >&6
++build=$ac_cv_build
++build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
++build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
++build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
++
++
++echo "$as_me:$LINENO: checking host system type" >&5
++echo $ECHO_N "checking host system type... $ECHO_C" >&6
++if test "${ac_cv_host+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ ac_cv_host_alias=$host_alias
++test -z "$ac_cv_host_alias" &&
++ ac_cv_host_alias=$ac_cv_build_alias
++ac_cv_host=`$ac_config_sub $ac_cv_host_alias` ||
++ { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5
++echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;}
++ { (exit 1); exit 1; }; }
++
++fi
++echo "$as_me:$LINENO: result: $ac_cv_host" >&5
++echo "${ECHO_T}$ac_cv_host" >&6
++host=$ac_cv_host
++host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
++host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
++host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
++
++
++echo "$as_me:$LINENO: checking target system type" >&5
++echo $ECHO_N "checking target system type... $ECHO_C" >&6
++if test "${ac_cv_target+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ ac_cv_target_alias=$target_alias
++test "x$ac_cv_target_alias" = "x" &&
++ ac_cv_target_alias=$ac_cv_host_alias
++ac_cv_target=`$ac_config_sub $ac_cv_target_alias` ||
++ { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_target_alias failed" >&5
++echo "$as_me: error: $ac_config_sub $ac_cv_target_alias failed" >&2;}
++ { (exit 1); exit 1; }; }
++
++fi
++echo "$as_me:$LINENO: result: $ac_cv_target" >&5
++echo "${ECHO_T}$ac_cv_target" >&6
++target=$ac_cv_target
++target_cpu=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
++target_vendor=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
++target_os=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+-echo $ac_n "checking host system type""... $ac_c" 1>&6
+-echo "configure:760: checking host system type" >&5
+
+-host_alias=$host
+-case "$host_alias" in
+-NONE)
+- case $nonopt in
+- NONE)
+- if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+- else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+- fi ;;
+- *) host_alias=$nonopt ;;
+- esac ;;
+-esac
+-
+-host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+-host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+-host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+-host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+-echo "$ac_t""$host" 1>&6
+-
+-echo $ac_n "checking target system type""... $ac_c" 1>&6
+-echo "configure:781: checking target system type" >&5
+-
+-target_alias=$target
+-case "$target_alias" in
+-NONE)
+- case $nonopt in
+- NONE) target_alias=$host_alias ;;
+- *) target_alias=$nonopt ;;
+- esac ;;
+-esac
+-
+-target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+-target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+-target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+-target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+-echo "$ac_t""$target" 1>&6
+-
+-echo $ac_n "checking build system type""... $ac_c" 1>&6
+-echo "configure:799: checking build system type" >&5
+-
+-build_alias=$build
+-case "$build_alias" in
+-NONE)
+- case $nonopt in
+- NONE) build_alias=$host_alias ;;
+- *) build_alias=$nonopt ;;
+- esac ;;
+-esac
+-
+-build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+-build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+-build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+-build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+-echo "$ac_t""$build" 1>&6
+-
+-test "$host_alias" != "$target_alias" &&
++# The aliases save the names the user supplied, while $host etc.
++# will get canonicalized.
++test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+-
++am__api_version="1.4"
+ # 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:
+@@ -825,65 +1563,78 @@
+ # SunOS /usr/etc/install
+ # IRIX /sbin/install
+ # AIX /bin/install
++# AmigaOS /C/install, which installs bootblocks on floppy discs
+ # 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:834: checking for a BSD compatible install" >&5
++echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
++echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+ if test -z "$INSTALL"; then
+-if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++if test "${ac_cv_path_install+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&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
++ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++ IFS=$as_save_IFS
++ test -z "$as_dir" && as_dir=.
++ # Account for people who put trailing slashes in PATH elements.
++case $as_dir/ in
++ ./ | .// | /cC/* | \
++ /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
++ for ac_exec_ext in '' $ac_executable_extensions; do
++ if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
++ if test $ac_prog = install &&
++ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
++ # AIX install. It has an incompatible calling convention.
++ :
++ elif test $ac_prog = install &&
++ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
++ # program-specific install script used by HP pwplus--don't use.
++ :
++ else
++ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
++ break 3
++ fi
++ fi
+ done
+- ;;
+- esac
+- done
+- IFS="$ac_save_IFS"
++ done
++ ;;
++esac
++done
++
+
+ fi
+ if test "${ac_cv_path_install+set}" = set; then
+- INSTALL="$ac_cv_path_install"
++ 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"
++ INSTALL=$ac_install_sh
+ fi
+ fi
+-echo "$ac_t""$INSTALL" 1>&6
++echo "$as_me:$LINENO: result: $INSTALL" >&5
++echo "${ECHO_T}$INSTALL" >&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_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+-echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
+-echo "configure:887: checking whether build environment is sane" >&5
++echo "$as_me:$LINENO: checking whether build environment is sane" >&5
++echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6
+ # Just in case
+ sleep 1
+ echo timestamp > conftestfile
+@@ -905,8 +1656,11 @@
+ # 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; }
++ { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken
++alias in your environment" >&5
++echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken
++alias in your environment" >&2;}
++ { (exit 1); exit 1; }; }
+ fi
+
+ test "$2" = conftestfile
+@@ -915,54 +1669,54 @@
+ # Ok.
+ :
+ else
+- { echo "configure: error: newly created file is older than distributed files!
+-Check your system clock" 1>&2; exit 1; }
++ { { echo "$as_me:$LINENO: error: newly created file is older than distributed files!
++Check your system clock" >&5
++echo "$as_me: error: newly created file is older than distributed files!
++Check your system clock" >&2;}
++ { (exit 1); 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
++echo "$as_me:$LINENO: result: yes" >&5
++echo "${ECHO_T}yes" >&6
+ test "$program_prefix" != NONE &&
+- program_transform_name="s,^,${program_prefix},; $program_transform_name"
++ 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:944: 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
++ program_transform_name="s,\$,$program_suffix,;$program_transform_name"
++# Double any \ or $. echo might interpret backslashes.
++# By default was `s,x,x', remove it if useless.
++cat <<\_ACEOF >conftest.sed
++s/[\\$]/&&/g;s/;s,x,x,$//
++_ACEOF
++program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
++rm conftest.sed
++
++echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
++echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
++set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'`
++if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+- cat > conftestmake <<\EOF
++ cat >conftest.make <<\_ACEOF
+ all:
+- @echo 'ac_maketemp="${MAKE}"'
+-EOF
++ @echo 'ac_maketemp="$(MAKE)"'
++_ACEOF
+ # GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+-eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
++eval `${MAKE-make} -f conftest.make 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
++rm -f conftest.make
+ fi
+ if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+- echo "$ac_t""yes" 1>&6
++ echo "$as_me:$LINENO: result: yes" >&5
++echo "${ECHO_T}yes" >&6
+ SET_MAKE=
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
+ SET_MAKE="MAKE=${MAKE-make}"
+ fi
+
+@@ -972,82 +1726,96 @@
+ VERSION=2.4.1
+
+ 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; }
++ { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
++echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
++ { (exit 1); exit 1; }; }
+ fi
+-cat >> confdefs.h <<EOF
++
++cat >>confdefs.h <<_ACEOF
+ #define PACKAGE "$PACKAGE"
+-EOF
++_ACEOF
+
+-cat >> confdefs.h <<EOF
++
++cat >>confdefs.h <<_ACEOF
+ #define VERSION "$VERSION"
+-EOF
++_ACEOF
+
+
+
+ missing_dir=`cd $ac_aux_dir && pwd`
+-echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
+-echo "configure:990: checking for working aclocal" >&5
++echo "$as_me:$LINENO: checking for working aclocal-${am__api_version}" >&5
++echo $ECHO_N "checking for working aclocal-${am__api_version}... $ECHO_C" >&6
+ # 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
++if (aclocal-${am__api_version} --version) < /dev/null > /dev/null 2>&1; then
++ ACLOCAL=aclocal-${am__api_version}
++ echo "$as_me:$LINENO: result: found" >&5
++echo "${ECHO_T}found" >&6
++else
++ ACLOCAL="$missing_dir/missing aclocal-${am__api_version}"
++ echo "$as_me:$LINENO: result: missing" >&5
++echo "${ECHO_T}missing" >&6
+ fi
+
+-echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
+-echo "configure:1003: checking for working autoconf" >&5
++echo "$as_me:$LINENO: checking for working autoconf" >&5
++echo $ECHO_N "checking for working autoconf... $ECHO_C" >&6
+ # 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
++ echo "$as_me:$LINENO: result: found" >&5
++echo "${ECHO_T}found" >&6
+ else
+ AUTOCONF="$missing_dir/missing autoconf"
+- echo "$ac_t""missing" 1>&6
++ echo "$as_me:$LINENO: result: missing" >&5
++echo "${ECHO_T}missing" >&6
+ fi
+
+-echo $ac_n "checking for working automake""... $ac_c" 1>&6
+-echo "configure:1016: checking for working automake" >&5
++echo "$as_me:$LINENO: checking for working automake-${am__api_version}" >&5
++echo $ECHO_N "checking for working automake-${am__api_version}... $ECHO_C" >&6
+ # 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
++if (automake-${am__api_version} --version) < /dev/null > /dev/null 2>&1; then
++ AUTOMAKE=automake-${am__api_version}
++ echo "$as_me:$LINENO: result: found" >&5
++echo "${ECHO_T}found" >&6
++else
++ AUTOMAKE="$missing_dir/missing automake-${am__api_version}"
++ echo "$as_me:$LINENO: result: missing" >&5
++echo "${ECHO_T}missing" >&6
+ fi
+
+-echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
+-echo "configure:1029: checking for working autoheader" >&5
++echo "$as_me:$LINENO: checking for working autoheader" >&5
++echo $ECHO_N "checking for working autoheader... $ECHO_C" >&6
+ # 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
++ echo "$as_me:$LINENO: result: found" >&5
++echo "${ECHO_T}found" >&6
+ else
+ AUTOHEADER="$missing_dir/missing autoheader"
+- echo "$ac_t""missing" 1>&6
++ echo "$as_me:$LINENO: result: missing" >&5
++echo "${ECHO_T}missing" >&6
+ fi
+
+-echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
+-echo "configure:1042: checking for working makeinfo" >&5
++echo "$as_me:$LINENO: checking for working makeinfo" >&5
++echo $ECHO_N "checking for working makeinfo... $ECHO_C" >&6
+ # 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
++ echo "$as_me:$LINENO: result: found" >&5
++echo "${ECHO_T}found" >&6
+ else
+ MAKEINFO="$missing_dir/missing makeinfo"
+- echo "$ac_t""missing" 1>&6
++ echo "$as_me:$LINENO: result: missing" >&5
++echo "${ECHO_T}missing" >&6
+ fi
+
+
+@@ -1059,214 +1827,643 @@
+
+
+
+-# Extract the first word of "gcc", so it can be a program name with args.
++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
++if test -n "$ac_tool_prefix"; then
++ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
++set dummy ${ac_tool_prefix}gcc; 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_CC+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ if test -n "$CC"; then
++ ac_cv_prog_CC="$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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ ac_cv_prog_CC="${ac_tool_prefix}gcc"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
++ fi
++done
++done
++
++fi
++fi
++CC=$ac_cv_prog_CC
++if test -n "$CC"; then
++ echo "$as_me:$LINENO: result: $CC" >&5
++echo "${ECHO_T}$CC" >&6
++else
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
++fi
++
++fi
++if test -z "$ac_cv_prog_CC"; then
++ ac_ct_CC=$CC
++ # 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:1066: checking for $ac_word" >&5
+-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++echo "$as_me:$LINENO: checking for $ac_word" >&5
++echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
++if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ if test -n "$ac_ct_CC"; then
++ ac_cv_prog_ac_ct_CC="$ac_ct_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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ ac_cv_prog_ac_ct_CC="gcc"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
++ fi
++done
++done
++
++fi
++fi
++ac_ct_CC=$ac_cv_prog_ac_ct_CC
++if test -n "$ac_ct_CC"; then
++ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
++echo "${ECHO_T}$ac_ct_CC" >&6
++else
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
++fi
++
++ CC=$ac_ct_CC
++else
++ CC="$ac_cv_prog_CC"
++fi
++
++if test -z "$CC"; then
++ if test -n "$ac_tool_prefix"; then
++ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
++set dummy ${ac_tool_prefix}cc; 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_CC+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&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"
++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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ ac_cv_prog_CC="${ac_tool_prefix}cc"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
++ fi
++done
++done
++
+ fi
+ fi
+-CC="$ac_cv_prog_CC"
++CC=$ac_cv_prog_CC
+ if test -n "$CC"; then
+- echo "$ac_t""$CC" 1>&6
++ echo "$as_me:$LINENO: result: $CC" >&5
++echo "${ECHO_T}$CC" >&6
++else
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
++fi
++
++fi
++if test -z "$ac_cv_prog_CC"; then
++ ac_ct_CC=$CC
++ # Extract the first word of "cc", so it can be a program name with args.
++set dummy cc; 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_ac_ct_CC+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ if test -n "$ac_ct_CC"; then
++ ac_cv_prog_ac_ct_CC="$ac_ct_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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ ac_cv_prog_ac_ct_CC="cc"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
++ fi
++done
++done
++
++fi
++fi
++ac_ct_CC=$ac_cv_prog_ac_ct_CC
++if test -n "$ac_ct_CC"; then
++ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
++echo "${ECHO_T}$ac_ct_CC" >&6
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
+ fi
+
++ CC=$ac_ct_CC
++else
++ CC="$ac_cv_prog_CC"
++fi
++
++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:1096: checking for $ac_word" >&5
+-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++echo "$as_me:$LINENO: checking for $ac_word" >&5
++echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
++if test "${ac_cv_prog_CC+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&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"
++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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
++ ac_prog_rejected=yes
++ continue
++ fi
++ ac_cv_prog_CC="cc"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
++ fi
++done
++done
++
+ 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
++ if test $# != 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="$@"
++ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+ fi
+ fi
+ fi
+-CC="$ac_cv_prog_CC"
++CC=$ac_cv_prog_CC
+ if test -n "$CC"; then
+- echo "$ac_t""$CC" 1>&6
++ echo "$as_me:$LINENO: result: $CC" >&5
++echo "${ECHO_T}$CC" >&6
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&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:1147: checking for $ac_word" >&5
+-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++fi
++if test -z "$CC"; then
++ if test -n "$ac_tool_prefix"; then
++ for ac_prog in cl
++ do
++ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
++set dummy $ac_tool_prefix$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_CC+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&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"
++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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
++ fi
++done
++done
++
+ fi
+ fi
+-CC="$ac_cv_prog_CC"
++CC=$ac_cv_prog_CC
+ if test -n "$CC"; then
+- echo "$ac_t""$CC" 1>&6
++ echo "$as_me:$LINENO: result: $CC" >&5
++echo "${ECHO_T}$CC" >&6
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
+ fi
+- ;;
+- esac
++
++ test -n "$CC" && break
++ done
++fi
++if test -z "$CC"; then
++ ac_ct_CC=$CC
++ for ac_prog in cl
++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_ac_ct_CC+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ if test -n "$ac_ct_CC"; then
++ ac_cv_prog_ac_ct_CC="$ac_ct_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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ ac_cv_prog_ac_ct_CC="$ac_prog"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
+ fi
+- test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
++done
++done
++
+ fi
++fi
++ac_ct_CC=$ac_cv_prog_ac_ct_CC
++if test -n "$ac_ct_CC"; then
++ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
++echo "${ECHO_T}$ac_ct_CC" >&6
++else
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
++fi
++
++ test -n "$ac_ct_CC" && break
++done
+
+-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+-echo "configure:1179: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
++ CC=$ac_ct_CC
++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
++fi
+
+-cat > conftest.$ac_ext << EOF
+
+-#line 1190 "configure"
+-#include "confdefs.h"
++test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
++See \`config.log' for more details." >&5
++echo "$as_me: error: no acceptable C compiler found in \$PATH
++See \`config.log' for more details." >&2;}
++ { (exit 1); exit 1; }; }
++
++# Provide some information about the compiler.
++echo "$as_me:$LINENO:" \
++ "checking for C compiler version" >&5
++ac_compiler=`set X $ac_compile; echo $2`
++{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
++ (eval $ac_compiler --version </dev/null >&5) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }
++{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
++ (eval $ac_compiler -v </dev/null >&5) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }
++{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
++ (eval $ac_compiler -V </dev/null >&5) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }
++
++cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
+
+-main(){return(0);}
+-EOF
+-if { (eval echo configure:1195: \"$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
++int
++main ()
++{
++
++ ;
++ return 0;
++}
++_ACEOF
++ac_clean_files_save=$ac_clean_files
++ac_clean_files="$ac_clean_files a.out a.exe b.out"
++# Try to create an executable without -o first, disregard a.out.
++# It will help us diagnose broken compilers, and finding out an intuition
++# of exeext.
++echo "$as_me:$LINENO: checking for C compiler default output" >&5
++echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6
++ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
++if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
++ (eval $ac_link_default) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; then
++ # Find the output, starting from the most likely. This scheme is
++# not robust to junk in `.', hence go to wildcards (a.*) only as a last
++# resort.
++
++# Be careful to initialize this variable, since it used to be cached.
++# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
++ac_cv_exeext=
++# b.out is created by i960 compilers.
++for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
++do
++ test -f "$ac_file" || continue
++ case $ac_file in
++ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
++ ;;
++ conftest.$ac_ext )
++ # This is the source file.
++ ;;
++ [ab].out )
++ # We found the default executable, but exeext='' is most
++ # certainly right.
++ break;;
++ *.* )
++ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
++ # FIXME: I believe we export ac_cv_exeext for Libtool,
++ # but it would be cool to find out if it's true. Does anybody
++ # maintain Libtool? --akim.
++ export ac_cv_exeext
++ break;;
++ * )
++ break;;
++ esac
++done
+ else
+- echo "configure: failed program was:" >&5
+- cat conftest.$ac_ext >&5
+- ac_cv_prog_cc_works=no
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
++See \`config.log' for more details." >&5
++echo "$as_me: error: C compiler cannot create executables
++See \`config.log' for more details." >&2;}
++ { (exit 77); exit 77; }; }
++fi
++
++ac_exeext=$ac_cv_exeext
++echo "$as_me:$LINENO: result: $ac_file" >&5
++echo "${ECHO_T}$ac_file" >&6
++
++# Check the compiler produces executables we can run. If not, either
++# the compiler is broken, or we cross compile.
++echo "$as_me:$LINENO: checking whether the C compiler works" >&5
++echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
++# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
++# If not cross compiling, check that we can run a simple program.
++if test "$cross_compiling" != yes; then
++ if { ac_try='./$ac_file'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ cross_compiling=no
++ else
++ if test "$cross_compiling" = maybe; then
++ cross_compiling=yes
++ else
++ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
++If you meant to cross compile, use \`--host'.
++See \`config.log' for more details." >&5
++echo "$as_me: error: cannot run C compiled programs.
++If you meant to cross compile, use \`--host'.
++See \`config.log' for more details." >&2;}
++ { (exit 1); exit 1; }; }
++ fi
++ fi
+ fi
+-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:1221: 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:1226: 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:1235: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+- ac_cv_prog_gcc=yes
++echo "$as_me:$LINENO: result: yes" >&5
++echo "${ECHO_T}yes" >&6
++
++rm -f a.out a.exe conftest$ac_cv_exeext b.out
++ac_clean_files=$ac_clean_files_save
++# Check the compiler produces executables we can run. If not, either
++# the compiler is broken, or we cross compile.
++echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
++echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
++echo "$as_me:$LINENO: result: $cross_compiling" >&5
++echo "${ECHO_T}$cross_compiling" >&6
++
++echo "$as_me:$LINENO: checking for suffix of executables" >&5
++echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; then
++ # If both `conftest.exe' and `conftest' are `present' (well, observable)
++# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
++# work properly (i.e., refer to `conftest.exe'), while it won't with
++# `rm'.
++for ac_file in conftest.exe conftest conftest.*; do
++ test -f "$ac_file" || continue
++ case $ac_file in
++ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
++ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
++ export ac_cv_exeext
++ break;;
++ * ) break;;
++ esac
++done
+ else
+- ac_cv_prog_gcc=no
+-fi
++ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
++See \`config.log' for more details." >&5
++echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
++See \`config.log' for more details." >&2;}
++ { (exit 1); exit 1; }; }
+ fi
+
+-echo "$ac_t""$ac_cv_prog_gcc" 1>&6
++rm -f conftest$ac_cv_exeext
++echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
++echo "${ECHO_T}$ac_cv_exeext" >&6
++
++rm -f conftest.$ac_ext
++EXEEXT=$ac_cv_exeext
++ac_exeext=$EXEEXT
++echo "$as_me:$LINENO: checking for suffix of object files" >&5
++echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
++if test "${ac_cv_objext+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++
++int
++main ()
++{
+
+-if test $ac_cv_prog_gcc = yes; then
+- GCC=yes
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.o conftest.obj
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; then
++ for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
++ case $ac_file in
++ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
++ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
++ break;;
++ esac
++done
+ else
+- GCC=
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
++See \`config.log' for more details." >&5
++echo "$as_me: error: cannot compute suffix of object files: cannot compile
++See \`config.log' for more details." >&2;}
++ { (exit 1); exit 1; }; }
+ fi
+
+-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:1254: 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
++rm -f conftest.$ac_cv_objext conftest.$ac_ext
++fi
++echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
++echo "${ECHO_T}$ac_cv_objext" >&6
++OBJEXT=$ac_cv_objext
++ac_objext=$OBJEXT
++echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
++echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
++if test "${ac_cv_c_compiler_gnu+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++
++int
++main ()
++{
++#ifndef __GNUC__
++ choke me
++#endif
++
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest.$ac_objext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ ac_compiler_gnu=yes
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_compiler_gnu=no
++fi
++rm -f conftest.$ac_objext conftest.$ac_ext
++ac_cv_c_compiler_gnu=$ac_compiler_gnu
++
++fi
++echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
++echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
++GCC=`test $ac_compiler_gnu = yes && echo yes`
++ac_test_CFLAGS=${CFLAGS+set}
++ac_save_CFLAGS=$CFLAGS
++CFLAGS="-g"
++echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
++echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
++if test "${ac_cv_prog_cc_g+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++
++int
++main ()
++{
++
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest.$ac_objext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_g=yes
+ else
+- ac_cv_prog_cc_g=no
+-fi
+-rm -f conftest*
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
+
++ac_cv_prog_cc_g=no
+ fi
+-
+-echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
++rm -f conftest.$ac_objext conftest.$ac_ext
++fi
++echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
++echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+ if test "$ac_test_CFLAGS" = set; then
+- CFLAGS="$ac_save_CFLAGS"
++ CFLAGS=$ac_save_CFLAGS
+ elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+@@ -1280,295 +2477,548 @@
+ CFLAGS=
+ fi
+ fi
++echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
++echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
++if test "${ac_cv_prog_cc_stdc+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ ac_cv_prog_cc_stdc=no
++ac_save_CC=$CC
++cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++#include <stdarg.h>
++#include <stdio.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
++struct buf { int x; };
++FILE * (*rcsopen) (struct buf *, struct stat *, int);
++static char *e (p, i)
++ char **p;
++ int i;
++{
++ return p[i];
++}
++static char *f (char * (*g) (char **, int), char **p, ...)
++{
++ char *s;
++ va_list v;
++ va_start (v,p);
++ s = g (p, va_arg (v,int));
++ va_end (v);
++ return s;
++}
++int test (int i, double x);
++struct s1 {int (*f) (int a);};
++struct s2 {int (*f) (double a);};
++int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
++int argc;
++char **argv;
++int
++main ()
++{
++return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
++ ;
++ return 0;
++}
++_ACEOF
++# Don't try gcc -ansi; that turns off useful extensions and
++# breaks some systems' header files.
++# AIX -qlanglvl=ansi
++# Ultrix and OSF/1 -std1
++# HP-UX 10.20 and later -Ae
++# HP-UX older versions -Aa -D_HPUX_SOURCE
++# SVR4 -Xc -D__EXTENSIONS__
++for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
++do
++ CC="$ac_save_CC $ac_arg"
++ rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest.$ac_objext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ ac_cv_prog_cc_stdc=$ac_arg
++break
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++fi
++rm -f conftest.$ac_objext
++done
++rm -f conftest.$ac_ext conftest.$ac_objext
++CC=$ac_save_CC
+
+-echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+-echo "configure:1286: 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 1301 "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:1307: \"$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 1318 "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:1324: \"$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 1335 "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: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
++
++case "x$ac_cv_prog_cc_stdc" in
++ x|xno)
++ echo "$as_me:$LINENO: result: none needed" >&5
++echo "${ECHO_T}none needed" >&6 ;;
++ *)
++ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
++echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
++ CC="$CC $ac_cv_prog_cc_stdc" ;;
++esac
++
++# Some people use a C++ compiler to compile C. Since we use `exit',
++# in C++ we need to declare it. In case someone uses the same compiler
++# for both compiling C and C++ we need to have the C++ compiler decide
++# the declaration of exit, since it's the most demanding environment.
++cat >conftest.$ac_ext <<_ACEOF
++#ifndef __cplusplus
++ choke me
++#endif
++_ACEOF
++rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest.$ac_objext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ for ac_declaration in \
++ '' \
++ 'extern "C" void std::exit (int) throw (); using std::exit;' \
++ 'extern "C" void std::exit (int); using std::exit;' \
++ 'extern "C" void exit (int) throw ();' \
++ 'extern "C" void exit (int);' \
++ 'void exit (int);'
++do
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++$ac_declaration
++#include <stdlib.h>
++int
++main ()
++{
++exit (42);
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest.$ac_objext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; 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*
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++continue
+ fi
+-rm -f conftest*
++rm -f conftest.$ac_objext conftest.$ac_ext
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++$ac_declaration
++int
++main ()
++{
++exit (42);
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest.$ac_objext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ break
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ fi
++rm -f conftest.$ac_objext conftest.$ac_ext
++done
+ rm -f conftest*
+- ac_cv_prog_CPP="$CPP"
++if test -n "$ac_declaration"; then
++ echo '#ifdef __cplusplus' >>confdefs.h
++ echo $ac_declaration >>confdefs.h
++ echo '#endif' >>confdefs.h
+ fi
+- CPP="$ac_cv_prog_CPP"
++
+ else
+- ac_cv_prog_CPP="$CPP"
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ fi
+-echo "$ac_t""$CPP" 1>&6
++rm -f conftest.$ac_objext conftest.$ac_ext
++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
++
+
+ missing_dir=`cd $ac_aux_dir && pwd`
+ for ac_prog in flex lex
+ do
+-# Extract the first word of "$ac_prog", so it can be a program name with args.
++ # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:1371: checking for $ac_word" >&5
+-if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++echo "$as_me:$LINENO: checking for $ac_word" >&5
++echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
++if test "${ac_cv_prog_LEX+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ if test -n "$LEX"; then
+ ac_cv_prog_LEX="$LEX" # 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_LEX="$ac_prog"
+- break
+- fi
+- done
+- IFS="$ac_save_ifs"
++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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ ac_cv_prog_LEX="$ac_prog"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
++ fi
++done
++done
++
+ fi
+ fi
+-LEX="$ac_cv_prog_LEX"
++LEX=$ac_cv_prog_LEX
+ if test -n "$LEX"; then
+- echo "$ac_t""$LEX" 1>&6
++ echo "$as_me:$LINENO: result: $LEX" >&5
++echo "${ECHO_T}$LEX" >&6
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
+ fi
+
+-test -n "$LEX" && break
++ test -n "$LEX" && break
+ done
+-test -n "$LEX" || LEX=""$missing_dir/missing flex""
++test -n "$LEX" || LEX="$missing_dir/missing flex"
+
+-# Extract the first word of "flex", so it can be a program name with args.
+-set dummy flex; ac_word=$2
+-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:1404: checking for $ac_word" >&5
+-if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++for ac_prog in flex lex
++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_LEX+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ if test -n "$LEX"; then
+ ac_cv_prog_LEX="$LEX" # 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_LEX="flex"
+- break
+- fi
+- done
+- IFS="$ac_save_ifs"
+- test -z "$ac_cv_prog_LEX" && ac_cv_prog_LEX="lex"
++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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ ac_cv_prog_LEX="$ac_prog"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
++ fi
++done
++done
++
+ fi
+ fi
+-LEX="$ac_cv_prog_LEX"
++LEX=$ac_cv_prog_LEX
+ if test -n "$LEX"; then
+- echo "$ac_t""$LEX" 1>&6
++ echo "$as_me:$LINENO: result: $LEX" >&5
++echo "${ECHO_T}$LEX" >&6
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
+ fi
+
++ test -n "$LEX" && break
++done
++test -n "$LEX" || LEX=":"
++
+ if test -z "$LEXLIB"
+ then
+- case "$LEX" in
+- flex*) ac_lib=fl ;;
+- *) ac_lib=l ;;
+- esac
+- echo $ac_n "checking for yywrap in -l$ac_lib""... $ac_c" 1>&6
+-echo "configure:1438: checking for yywrap in -l$ac_lib" >&5
+-ac_lib_var=`echo $ac_lib'_'yywrap | sed 'y%./+-%__p_%'`
+-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
+-else
+- ac_save_LIBS="$LIBS"
+-LIBS="-l$ac_lib $LIBS"
+-cat > conftest.$ac_ext <<EOF
+-#line 1446 "configure"
+-#include "confdefs.h"
++ echo "$as_me:$LINENO: checking for yywrap in -lfl" >&5
++echo $ECHO_N "checking for yywrap in -lfl... $ECHO_C" >&6
++if test "${ac_cv_lib_fl_yywrap+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ ac_check_lib_save_LIBS=$LIBS
++LIBS="-lfl $LIBS"
++cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++
+ /* Override any gcc2 internal prototype to avoid an error. */
++#ifdef __cplusplus
++extern "C"
++#endif
+ /* We use char because int might match the return type of a gcc2
+- builtin and then its argument prototype would still apply. */
+-char yywrap();
++ builtin and then its argument prototype would still apply. */
++char yywrap ();
++int
++main ()
++{
++yywrap ();
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext conftest$ac_exeext
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest$ac_exeext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ ac_cv_lib_fl_yywrap=yes
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_cv_lib_fl_yywrap=no
++fi
++rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++echo "$as_me:$LINENO: result: $ac_cv_lib_fl_yywrap" >&5
++echo "${ECHO_T}$ac_cv_lib_fl_yywrap" >&6
++if test $ac_cv_lib_fl_yywrap = yes; then
++ LEXLIB="-lfl"
++else
++ echo "$as_me:$LINENO: checking for yywrap in -ll" >&5
++echo $ECHO_N "checking for yywrap in -ll... $ECHO_C" >&6
++if test "${ac_cv_lib_l_yywrap+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ ac_check_lib_save_LIBS=$LIBS
++LIBS="-ll $LIBS"
++cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
+
+-int main() {
+-yywrap()
+-; return 0; }
+-EOF
+-if { (eval echo configure:1457: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+- rm -rf conftest*
+- eval "ac_cv_lib_$ac_lib_var=yes"
++/* Override any gcc2 internal prototype to avoid an error. */
++#ifdef __cplusplus
++extern "C"
++#endif
++/* We use char because int might match the return type of a gcc2
++ builtin and then its argument prototype would still apply. */
++char yywrap ();
++int
++main ()
++{
++yywrap ();
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext conftest$ac_exeext
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest$ac_exeext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ ac_cv_lib_l_yywrap=yes
+ else
+- echo "configure: failed program was:" >&5
+- cat conftest.$ac_ext >&5
+- rm -rf conftest*
+- eval "ac_cv_lib_$ac_lib_var=no"
+-fi
+-rm -f conftest*
+-LIBS="$ac_save_LIBS"
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
+
++ac_cv_lib_l_yywrap=no
+ fi
+-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+- echo "$ac_t""yes" 1>&6
+- LEXLIB="-l$ac_lib"
+-else
+- echo "$ac_t""no" 1>&6
++rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++echo "$as_me:$LINENO: result: $ac_cv_lib_l_yywrap" >&5
++echo "${ECHO_T}$ac_cv_lib_l_yywrap" >&6
++if test $ac_cv_lib_l_yywrap = yes; then
++ LEXLIB="-ll"
++fi
++
+ fi
+
+ fi
+
+-echo $ac_n "checking lex output file root""... $ac_c" 1>&6
+-echo "configure:1480: checking lex output file root" >&5
+-if eval "test \"`echo '$''{'ac_cv_prog_lex_root'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++if test "x$LEX" != "x:"; then
++ echo "$as_me:$LINENO: checking lex output file root" >&5
++echo $ECHO_N "checking lex output file root... $ECHO_C" >&6
++if test "${ac_cv_prog_lex_root+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ # The minimal lex program is just a single line: %%. But some broken lexes
+ # (Solaris, I think it was) want two %% lines, so accommodate them.
+-echo '%%
+-%%' | $LEX
++cat >conftest.l <<_ACEOF
++%%
++%%
++_ACEOF
++{ (eval echo "$as_me:$LINENO: \"$LEX conftest.l\"") >&5
++ (eval $LEX conftest.l) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }
+ if test -f lex.yy.c; then
+ ac_cv_prog_lex_root=lex.yy
+ elif test -f lexyy.c; then
+ ac_cv_prog_lex_root=lexyy
+ else
+- { echo "configure: error: cannot find output from $LEX; giving up" 1>&2; exit 1; }
++ { { echo "$as_me:$LINENO: error: cannot find output from $LEX; giving up" >&5
++echo "$as_me: error: cannot find output from $LEX; giving up" >&2;}
++ { (exit 1); exit 1; }; }
+ fi
+ fi
+-
+-echo "$ac_t""$ac_cv_prog_lex_root" 1>&6
++echo "$as_me:$LINENO: result: $ac_cv_prog_lex_root" >&5
++echo "${ECHO_T}$ac_cv_prog_lex_root" >&6
++rm -f conftest.l
+ LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root
+
+-echo $ac_n "checking whether yytext is a pointer""... $ac_c" 1>&6
+-echo "configure:1501: checking whether yytext is a pointer" >&5
+-if eval "test \"`echo '$''{'ac_cv_prog_lex_yytext_pointer'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++echo "$as_me:$LINENO: checking whether yytext is a pointer" >&5
++echo $ECHO_N "checking whether yytext is a pointer... $ECHO_C" >&6
++if test "${ac_cv_prog_lex_yytext_pointer+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ # POSIX says lex can declare yytext either as a pointer or an array; the
+ # default is implementation-dependent. Figure out which it is, since
+ # not all implementations provide the %pointer and %array declarations.
+ ac_cv_prog_lex_yytext_pointer=no
+ echo 'extern char *yytext;' >>$LEX_OUTPUT_ROOT.c
+-ac_save_LIBS="$LIBS"
++ac_save_LIBS=$LIBS
+ LIBS="$LIBS $LEXLIB"
+-cat > conftest.$ac_ext <<EOF
+-#line 1513 "configure"
+-#include "confdefs.h"
++cat >conftest.$ac_ext <<_ACEOF
+ `cat $LEX_OUTPUT_ROOT.c`
+-int main() {
+-
+-; return 0; }
+-EOF
+-if { (eval echo configure:1520: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+- rm -rf conftest*
++_ACEOF
++rm -f conftest.$ac_objext conftest$ac_exeext
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest$ac_exeext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
+ ac_cv_prog_lex_yytext_pointer=yes
+ else
+- echo "configure: failed program was:" >&5
+- cat conftest.$ac_ext >&5
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ fi
+-rm -f conftest*
+-LIBS="$ac_save_LIBS"
++rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_save_LIBS
+ rm -f "${LEX_OUTPUT_ROOT}.c"
+
+ fi
+-
+-echo "$ac_t""$ac_cv_prog_lex_yytext_pointer" 1>&6
++echo "$as_me:$LINENO: result: $ac_cv_prog_lex_yytext_pointer" >&5
++echo "${ECHO_T}$ac_cv_prog_lex_yytext_pointer" >&6
+ if test $ac_cv_prog_lex_yytext_pointer = yes; then
+- cat >> confdefs.h <<\EOF
++
++cat >>confdefs.h <<\_ACEOF
+ #define YYTEXT_POINTER 1
+-EOF
++_ACEOF
++
++fi
+
+ fi
+
+ for ac_prog in 'bison -y' byacc
+ do
+-# Extract the first word of "$ac_prog", so it can be a program name with args.
++ # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:1546: checking for $ac_word" >&5
+-if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++echo "$as_me:$LINENO: checking for $ac_word" >&5
++echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
++if test "${ac_cv_prog_YACC+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ if test -n "$YACC"; then
+ ac_cv_prog_YACC="$YACC" # 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_YACC="$ac_prog"
+- break
+- fi
+- done
+- IFS="$ac_save_ifs"
++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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ ac_cv_prog_YACC="$ac_prog"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
++ fi
++done
++done
++
+ fi
+ fi
+-YACC="$ac_cv_prog_YACC"
++YACC=$ac_cv_prog_YACC
+ if test -n "$YACC"; then
+- echo "$ac_t""$YACC" 1>&6
++ echo "$as_me:$LINENO: result: $YACC" >&5
++echo "${ECHO_T}$YACC" >&6
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
+ fi
+
+-test -n "$YACC" && break
++ test -n "$YACC" && break
+ done
+ test -n "$YACC" || YACC="yacc"
+
+@@ -1579,126 +3029,77 @@
+ # SunOS /usr/etc/install
+ # IRIX /sbin/install
+ # AIX /bin/install
++# AmigaOS /C/install, which installs bootblocks on floppy discs
+ # 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:1588: checking for a BSD compatible install" >&5
++echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
++echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+ if test -z "$INSTALL"; then
+-if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++if test "${ac_cv_path_install+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&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
++ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++ IFS=$as_save_IFS
++ test -z "$as_dir" && as_dir=.
++ # Account for people who put trailing slashes in PATH elements.
++case $as_dir/ in
++ ./ | .// | /cC/* | \
++ /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
++ for ac_exec_ext in '' $ac_executable_extensions; do
++ if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
++ if test $ac_prog = install &&
++ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
++ # AIX install. It has an incompatible calling convention.
++ :
++ elif test $ac_prog = install &&
++ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
++ # program-specific install script used by HP pwplus--don't use.
++ :
++ else
++ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
++ break 3
++ fi
++ fi
+ done
+- ;;
+- esac
+- done
+- IFS="$ac_save_IFS"
++ done
++ ;;
++esac
++done
++
+
+ fi
+ if test "${ac_cv_path_install+set}" = set; then
+- INSTALL="$ac_cv_path_install"
++ 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"
++ INSTALL=$ac_install_sh
+ fi
+ fi
+-echo "$ac_t""$INSTALL" 1>&6
++echo "$as_me:$LINENO: result: $INSTALL" >&5
++echo "${ECHO_T}$INSTALL" >&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_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+-echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
+-echo "configure:1642: checking for Cygwin environment" >&5
+-if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
+-else
+- cat > conftest.$ac_ext <<EOF
+-#line 1647 "configure"
+-#include "confdefs.h"
+-
+-int main() {
+-
+-#ifndef __CYGWIN__
+-#define __CYGWIN__ __CYGWIN32__
+-#endif
+-return __CYGWIN__;
+-; return 0; }
+-EOF
+-if { (eval echo configure:1658: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+- rm -rf conftest*
+- ac_cv_cygwin=yes
+-else
+- echo "configure: failed program was:" >&5
+- cat conftest.$ac_ext >&5
+- rm -rf conftest*
+- ac_cv_cygwin=no
+-fi
+-rm -f conftest*
+-rm -f conftest*
+-fi
+-
+-echo "$ac_t""$ac_cv_cygwin" 1>&6
+-CYGWIN=
+-test "$ac_cv_cygwin" = yes && CYGWIN=yes
+-echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
+-echo "configure:1675: checking for mingw32 environment" >&5
+-if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
+-else
+- cat > conftest.$ac_ext <<EOF
+-#line 1680 "configure"
+-#include "confdefs.h"
+-
+-int main() {
+-return __MINGW32__;
+-; return 0; }
+-EOF
+-if { (eval echo configure:1687: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+- rm -rf conftest*
+- ac_cv_mingw32=yes
+-else
+- echo "configure: failed program was:" >&5
+- cat conftest.$ac_ext >&5
+- rm -rf conftest*
+- ac_cv_mingw32=no
+-fi
+-rm -f conftest*
+-rm -f conftest*
+-fi
+-
+-echo "$ac_t""$ac_cv_mingw32" 1>&6
+-MINGW32=
+-test "$ac_cv_mingw32" = yes && MINGW32=yes
+ # Check whether --enable-shared or --disable-shared was given.
+ if test "${enable_shared+set}" = set; then
+ enableval="$enable_shared"
+@@ -1720,8 +3121,7 @@
+ esac
+ else
+ enable_shared=yes
+-fi
+-
++fi;
+ # Check whether --enable-static or --disable-static was given.
+ if test "${enable_static+set}" = set; then
+ enableval="$enable_static"
+@@ -1743,8 +3143,7 @@
+ esac
+ else
+ enable_static=yes
+-fi
+-
++fi;
+ # Check whether --enable-fast-install or --disable-fast-install was given.
+ if test "${enable_fast_install+set}" = set; then
+ enableval="$enable_fast_install"
+@@ -1766,21 +3165,31 @@
+ esac
+ else
+ enable_fast_install=yes
++fi;
++# Find the correct PATH separator. Usually this is `:', but
++# DJGPP uses `;' like DOS.
++if test "X${PATH_SEPARATOR+set}" != Xset; then
++ UNAME=${UNAME-`uname 2>/dev/null`}
++ case X$UNAME in
++ *-DOS) lt_cv_sys_path_separator=';' ;;
++ *) lt_cv_sys_path_separator=':' ;;
++ esac
++ PATH_SEPARATOR=$lt_cv_sys_path_separator
+ fi
+
++
+ # Check whether --with-gnu-ld or --without-gnu-ld was given.
+ if test "${with_gnu_ld+set}" = set; then
+ withval="$with_gnu_ld"
+ test "$withval" = no || with_gnu_ld=yes
+ else
+ with_gnu_ld=no
+-fi
+-
++fi;
+ ac_prog=ld
+ if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+- echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6
+-echo "configure:1784: checking for ld used by GCC" >&5
++ echo "$as_me:$LINENO: checking for ld used by GCC" >&5
++echo $ECHO_N "checking for ld used by GCC... $ECHO_C" >&6
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+@@ -1809,17 +3218,17 @@
+ ;;
+ esac
+ elif test "$with_gnu_ld" = yes; then
+- echo $ac_n "checking for GNU ld""... $ac_c" 1>&6
+-echo "configure:1814: checking for GNU ld" >&5
++ echo "$as_me:$LINENO: checking for GNU ld" >&5
++echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
+ else
+- echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
+-echo "configure:1817: checking for non-GNU ld" >&5
++ echo "$as_me:$LINENO: checking for non-GNU ld" >&5
++echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
+ fi
+-if eval "test \"`echo '$''{'lt_cv_path_LD'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++if test "${lt_cv_path_LD+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ if test -z "$LD"; then
+- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
++ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+@@ -1842,15 +3251,19 @@
+
+ LD="$lt_cv_path_LD"
+ if test -n "$LD"; then
+- echo "$ac_t""$LD" 1>&6
++ echo "$as_me:$LINENO: result: $LD" >&5
++echo "${ECHO_T}$LD" >&6
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
+ fi
+-test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; }
+-echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6
+-echo "configure:1852: checking if the linker ($LD) is GNU ld" >&5
+-if eval "test \"`echo '$''{'lt_cv_prog_gnu_ld'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
++echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
++ { (exit 1); exit 1; }; }
++echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
++echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
++if test "${lt_cv_prog_gnu_ld+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+ if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+@@ -1859,33 +3272,33 @@
+ lt_cv_prog_gnu_ld=no
+ fi
+ fi
+-
+-echo "$ac_t""$lt_cv_prog_gnu_ld" 1>&6
++echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
++echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6
+ with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+-echo $ac_n "checking for $LD option to reload object files""... $ac_c" 1>&6
+-echo "configure:1869: checking for $LD option to reload object files" >&5
+-if eval "test \"`echo '$''{'lt_cv_ld_reload_flag'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5
++echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6
++if test "${lt_cv_ld_reload_flag+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ lt_cv_ld_reload_flag='-r'
+ fi
+-
+-echo "$ac_t""$lt_cv_ld_reload_flag" 1>&6
++echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5
++echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6
+ reload_flag=$lt_cv_ld_reload_flag
+ test -n "$reload_flag" && reload_flag=" $reload_flag"
+
+-echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6
+-echo "configure:1881: checking for BSD-compatible nm" >&5
+-if eval "test \"`echo '$''{'lt_cv_path_NM'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5
++echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6
++if test "${lt_cv_path_NM+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+ else
+- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
++ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm=$ac_dir/${ac_tool_prefix}nm
+@@ -1912,33 +3325,109 @@
+ fi
+
+ NM="$lt_cv_path_NM"
+-echo "$ac_t""$NM" 1>&6
++echo "$as_me:$LINENO: result: $NM" >&5
++echo "${ECHO_T}$NM" >&6
++
++echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5
++echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6
++if test "${lt_cv_path_SED+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ # Loop through the user's path and test for sed and gsed.
++# Then use that list of sed's as ones to test for truncation.
++as_executable_p="test -f"
++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_prog in sed gsed; do
++ for ac_exec_ext in '' $ac_executable_extensions; do
++ if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
++ _sed_list="$_sed_list $as_dir/$ac_prog$ac_exec_ext"
++ fi
++ done
++ done
++done
++
++ # Create a temporary directory, and hook for its removal unless debugging.
++$debug ||
++{
++ trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
++ trap '{ (exit 1); exit 1; }' 1 2 13 15
++}
++
++# Create a (secure) tmp directory for tmp files.
++: ${TMPDIR=/tmp}
++{
++ tmp=`(umask 077 && mktemp -d -q "$TMPDIR/sedXXXXXX") 2>/dev/null` &&
++ test -n "$tmp" && test -d "$tmp"
++} ||
++{
++ tmp=$TMPDIR/sed$$-$RANDOM
++ (umask 077 && mkdir $tmp)
++} ||
++{
++ echo "$me: cannot create a temporary directory in $TMPDIR" >&2
++ { (exit 1); exit 1; }
++}
++ _max=0
++ _count=0
++ # Add /usr/xpg4/bin/sed as it is typically found on Solaris
++ # along with /bin/sed that truncates output.
++ for _sed in $_sed_list /usr/xpg4/bin/sed; do
++ test ! -f ${_sed} && break
++ cat /dev/null > "$tmp/sed.in"
++ _count=0
++ echo ${ECHO_N-$ac_n} "0123456789${ECHO_C-$ac_c}" >"$tmp/sed.in"
++ # Check for GNU sed and select it if it is found.
++ if "${_sed}" --version 2>&1 < /dev/null | egrep '(GNU)' > /dev/null; then
++ lt_cv_path_SED=${_sed}
++ break
++ fi
++ while true; do
++ cat "$tmp/sed.in" "$tmp/sed.in" >"$tmp/sed.tmp"
++ mv "$tmp/sed.tmp" "$tmp/sed.in"
++ cp "$tmp/sed.in" "$tmp/sed.nl"
++ echo >>"$tmp/sed.nl"
++ ${_sed} -e 's/a$//' < "$tmp/sed.nl" >"$tmp/sed.out" || break
++ cmp -s "$tmp/sed.out" "$tmp/sed.nl" || break
++ # 40000 chars as input seems more than enough
++ test $_count -gt 10 && break
++ _count=`expr $_count + 1`
++ if test $_count -gt $_max; then
++ _max=$_count
++ lt_cv_path_SED=$_sed
++ fi
++ done
++ done
++ rm -rf "$tmp"
+
+-echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+-echo "configure:1919: 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
++
++if test "X$SED" != "X"; then
++ lt_cv_path_SED=$SED
++else
++ SED=$lt_cv_path_SED
+ fi
+-LN_S="$ac_cv_prog_LN_S"
+-if test "$ac_cv_prog_LN_S" = "ln -s"; then
+- echo "$ac_t""yes" 1>&6
++echo "$as_me:$LINENO: result: $SED" >&5
++echo "${ECHO_T}$SED" >&6
++
++echo "$as_me:$LINENO: checking whether ln -s works" >&5
++echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6
++LN_S=$as_ln_s
++if test "$LN_S" = "ln -s"; then
++ echo "$as_me:$LINENO: result: yes" >&5
++echo "${ECHO_T}yes" >&6
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me:$LINENO: result: no, using $LN_S" >&5
++echo "${ECHO_T}no, using $LN_S" >&6
+ fi
+
+-echo $ac_n "checking how to recognise dependant libraries""... $ac_c" 1>&6
+-echo "configure:1940: checking how to recognise dependant libraries" >&5
+-if eval "test \"`echo '$''{'lt_cv_deplibs_check_method'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5
++echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6
++if test "${lt_cv_deplibs_check_method+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ lt_cv_file_magic_cmd='$MAGIC_CMD'
+ lt_cv_file_magic_test_file=
+@@ -1949,7 +3438,7 @@
+ # `unknown' -- same as none, but documents that we really don't know.
+ # 'pass_all' -- all dependencies passed with no checks.
+ # 'test_compile' -- check by making test program.
+-# ['file_magic [regex]'] -- check by looking for files in library path
++# 'file_magic [[regex]]' -- check by looking for files in library path
+ # which responds to the $file_magic_cmd with a given egrep regex.
+ # If you have `file' or equivalent on your system and you're not sure
+ # whether `pass_all' will *always* work, you probably want this one.
+@@ -1978,7 +3467,7 @@
+ lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ case "$host_os" in
+- rhapsody* | darwin1.012)
++ rhapsody* | darwin1.[012])
+ lt_cv_file_magic_test_file=`echo /System/Library/Frameworks/System.framework/Versions/*/System | head -1`
+ ;;
+ *) # Darwin 1.3 on
+@@ -2013,9 +3502,9 @@
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+
+-irix5* | irix6*)
++irix5* | irix6* | nonstopux*)
+ case $host_os in
+- irix5*)
++ irix5* | nonstopux*)
+ # this will be overridden with pass_all, but let us keep it just in case
+ lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
+ ;;
+@@ -2037,7 +3526,7 @@
+ # This must be Linux ELF.
+ linux-gnu*)
+ case $host_cpu in
+- alpha* | hppa* | i*86 | powerpc* | sparc* | ia64* | s390* )
++ alpha* | hppa* | i*86 | mips | mipsel | powerpc* | sparc* | ia64* | arm* | m68k)
+ lt_cv_deplibs_check_method=pass_all ;;
+ *)
+ # glibc up to 2.1.1 does not perform some relocations on ARM
+@@ -2060,6 +3549,16 @@
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
++openbsd*)
++ lt_cv_file_magic_cmd=/usr/bin/file
++ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
++ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
++ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object'
++ else
++ lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library'
++ fi
++ ;;
++
+ osf3* | osf4* | osf5*)
+ # this will be overridden with pass_all, but let us keep it just in case
+ lt_cv_deplibs_check_method='file_magic COFF format alpha shared library'
+@@ -2098,89 +3597,32 @@
+ lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
++ siemens)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
+ esac
+ ;;
+ esac
+
+ fi
+-
+-echo "$ac_t""$lt_cv_deplibs_check_method" 1>&6
++echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5
++echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6
+ file_magic_cmd=$lt_cv_file_magic_cmd
+ deplibs_check_method=$lt_cv_deplibs_check_method
+
+-echo $ac_n "checking for object suffix""... $ac_c" 1>&6
+-echo "configure:2113: checking for object suffix" >&5
+-if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
+-else
+- rm -f conftest*
+-echo 'int i = 1;' > conftest.$ac_ext
+-if { (eval echo configure:2119: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+- for ac_file in conftest.*; do
+- case $ac_file in
+- *.c) ;;
+- *) ac_cv_objext=`echo $ac_file | sed -e s/conftest.//` ;;
+- esac
+- done
+-else
+- { echo "configure: error: installation or configuration problem; compiler does not work" 1>&2; exit 1; }
+-fi
+-rm -f conftest*
+-fi
+-
+-echo "$ac_t""$ac_cv_objext" 1>&6
+-OBJEXT=$ac_cv_objext
+-ac_objext=$ac_cv_objext
+-
+-
+-
+-echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
+-echo "configure:2139: checking for executable suffix" >&5
+-if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
+-else
+- if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
+- ac_cv_exeext=.exe
+-else
+- rm -f conftest*
+- echo 'int main () { return 0; }' > conftest.$ac_ext
+- ac_cv_exeext=
+- if { (eval echo configure:2149: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+- for file in conftest.*; do
+- case $file in
+- *.c | *.o | *.obj) ;;
+- *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;;
+- esac
+- done
+- else
+- { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; }
+- fi
+- rm -f conftest*
+- test x"${ac_cv_exeext}" = x && ac_cv_exeext=no
+-fi
+-fi
+
+-EXEEXT=""
+-test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext}
+-echo "$ac_t""${ac_cv_exeext}" 1>&6
+-ac_exeext=$EXEEXT
+
+-if test $host != $build; then
+- ac_tool_prefix=${host_alias}-
+-else
+- ac_tool_prefix=
+-fi
+
+
+
+
+ # Check for command to grab the raw symbol name followed by C symbol from nm.
+-echo $ac_n "checking command to parse $NM output""... $ac_c" 1>&6
+-echo "configure:2180: checking command to parse $NM output" >&5
+-if eval "test \"`echo '$''{'lt_cv_sys_global_symbol_pipe'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++echo "$as_me:$LINENO: checking command to parse $NM output" >&5
++echo $ECHO_N "checking command to parse $NM output... $ECHO_C" >&6
++if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+-
++
+ # These are sane defaults that work on at least a few old systems.
+ # [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+@@ -2196,6 +3638,9 @@
+ # Transform an extracted symbol line into a proper C declaration
+ lt_cv_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
+
++# Transform an extracted symbol line into symbol name and symbol address
++lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
++
+ # Define system-specific variables.
+ case $host_os in
+ aix*)
+@@ -2206,10 +3651,14 @@
+ ;;
+ hpux*) # Its linker distinguishes data from code symbols
+ lt_cv_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
++ lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ ;;
+-irix*)
++irix* | nonstopux*)
+ symcode='[BCDEGRST]'
+ ;;
++osf*)
++ symcode='[BCDEGQRST]'
++ ;;
+ solaris* | sysv5*)
+ symcode='[BDT]'
+ ;;
+@@ -2252,10 +3701,18 @@
+ int main(){nm_test_var='a';nm_test_func();return(0);}
+ EOF
+
+- if { (eval echo configure:2256: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
++ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+- if { (eval echo configure:2259: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\") 1>&5; (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5; } && test -s "$nlist"; then
++ if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5
++ (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+@@ -2277,23 +3734,23 @@
+
+ cat <<EOF >> conftest.$ac_ext
+ #if defined (__STDC__) && __STDC__
+-# define lt_ptr_t void *
++# define lt_ptr void *
+ #else
+-# define lt_ptr_t char *
++# define lt_ptr char *
+ # define const
+ #endif
+
+ /* The mapping between symbol names and symbols. */
+ const struct {
+ const char *name;
+- lt_ptr_t address;
++ lt_ptr address;
+ }
+ lt_preloaded_symbols[] =
+ {
+ EOF
+- sed "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" >> conftest.$ac_ext
++ sed "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr) \&\2},/" < "$nlist" >> conftest.$ac_ext
+ cat <<\EOF >> conftest.$ac_ext
+- {0, (lt_ptr_t) 0}
++ {0, (lt_ptr) 0}
+ };
+
+ #ifdef __cplusplus
+@@ -2306,7 +3763,11 @@
+ save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$no_builtin_flag"
+- if { (eval echo configure:2310: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
++ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } && test -s conftest$ac_exeext; then
+ pipe_works=yes
+ fi
+ LIBS="$save_LIBS"
+@@ -2339,84 +3800,665 @@
+ global_symbol_pipe="$lt_cv_sys_global_symbol_pipe"
+ if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ global_symbol_to_cdecl=
++ global_symbol_to_c_name_address=
+ else
+ global_symbol_to_cdecl="$lt_cv_global_symbol_to_cdecl"
++ global_symbol_to_c_name_address="$lt_cv_global_symbol_to_c_name_address"
+ fi
+-if test -z "$global_symbol_pipe$global_symbol_to_cdecl"; then
+- echo "$ac_t""failed" 1>&6
++if test -z "$global_symbol_pipe$global_symbol_to_cdec$global_symbol_to_c_name_address";
++then
++ echo "$as_me:$LINENO: result: failed" >&5
++echo "${ECHO_T}failed" >&6
+ else
+- echo "$ac_t""ok" 1>&6
++ echo "$as_me:$LINENO: result: ok" >&5
++echo "${ECHO_T}ok" >&6
+ fi
+
+-for ac_hdr in dlfcn.h
++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
++echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
++echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
++# On Suns, sometimes $CPP names a directory.
++if test -n "$CPP" && test -d "$CPP"; then
++ CPP=
++fi
++if test -z "$CPP"; then
++ if test "${ac_cv_prog_CPP+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ # Double quotes because CPP needs to be expanded
++ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
++ do
++ ac_preproc_ok=false
++for ac_c_preproc_warn_flag in '' yes
+ do
+-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+-echo "configure:2356: 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
++ # Use a header file that comes with gcc, so configuring glibc
++ # with a fresh cross-compiler works.
++ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
++ # <limits.h> exists even on freestanding compilers.
++ # On the NeXT, cc -E runs the code through the compiler's parser,
++ # not just through cpp. "Syntax error" is here to catch this case.
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++#ifdef __STDC__
++# include <limits.h>
++#else
++# include <assert.h>
++#endif
++ Syntax error
++_ACEOF
++if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
++ (eval $ac_cpp conftest.$ac_ext) 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); } >/dev/null; then
++ if test -s conftest.err; then
++ ac_cpp_err=$ac_c_preproc_warn_flag
++ else
++ ac_cpp_err=
++ fi
+ else
+- cat > conftest.$ac_ext <<EOF
+-#line 2361 "configure"
+-#include "confdefs.h"
+-#include <$ac_hdr>
+-EOF
+-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+-{ (eval echo configure:2366: \"$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"
++ ac_cpp_err=yes
++fi
++if test -z "$ac_cpp_err"; then
++ :
+ 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"
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ # Broken: fails on valid input.
++continue
+ fi
+-rm -f conftest*
++rm -f conftest.err conftest.$ac_ext
++
++ # OK, works on sane cases. Now check whether non-existent headers
++ # can be detected and how.
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++#include <ac_nonexistent.h>
++_ACEOF
++if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
++ (eval $ac_cpp conftest.$ac_ext) 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); } >/dev/null; then
++ if test -s conftest.err; then
++ ac_cpp_err=$ac_c_preproc_warn_flag
++ else
++ ac_cpp_err=
++ fi
++else
++ ac_cpp_err=yes
+ 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
+-
++if test -z "$ac_cpp_err"; then
++ # Broken: success on invalid input.
++continue
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ # Passes both tests.
++ac_preproc_ok=:
++break
+ fi
++rm -f conftest.err conftest.$ac_ext
++
+ done
++# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
++rm -f conftest.err conftest.$ac_ext
++if $ac_preproc_ok; then
++ break
++fi
+
++ done
++ ac_cv_prog_CPP=$CPP
++
++fi
++ CPP=$ac_cv_prog_CPP
++else
++ ac_cv_prog_CPP=$CPP
++fi
++echo "$as_me:$LINENO: result: $CPP" >&5
++echo "${ECHO_T}$CPP" >&6
++ac_preproc_ok=false
++for ac_c_preproc_warn_flag in '' yes
++do
++ # Use a header file that comes with gcc, so configuring glibc
++ # with a fresh cross-compiler works.
++ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
++ # <limits.h> exists even on freestanding compilers.
++ # On the NeXT, cc -E runs the code through the compiler's parser,
++ # not just through cpp. "Syntax error" is here to catch this case.
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++#ifdef __STDC__
++# include <limits.h>
++#else
++# include <assert.h>
++#endif
++ Syntax error
++_ACEOF
++if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
++ (eval $ac_cpp conftest.$ac_ext) 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); } >/dev/null; then
++ if test -s conftest.err; then
++ ac_cpp_err=$ac_c_preproc_warn_flag
++ else
++ ac_cpp_err=
++ fi
++else
++ ac_cpp_err=yes
++fi
++if test -z "$ac_cpp_err"; then
++ :
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
+
++ # Broken: fails on valid input.
++continue
++fi
++rm -f conftest.err conftest.$ac_ext
+
++ # OK, works on sane cases. Now check whether non-existent headers
++ # can be detected and how.
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++#include <ac_nonexistent.h>
++_ACEOF
++if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
++ (eval $ac_cpp conftest.$ac_ext) 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); } >/dev/null; then
++ if test -s conftest.err; then
++ ac_cpp_err=$ac_c_preproc_warn_flag
++ else
++ ac_cpp_err=
++ fi
++else
++ ac_cpp_err=yes
++fi
++if test -z "$ac_cpp_err"; then
++ # Broken: success on invalid input.
++continue
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
+
++ # Passes both tests.
++ac_preproc_ok=:
++break
++fi
++rm -f conftest.err conftest.$ac_ext
+
+-# Only perform the check for file, if the check method requires it
+-case $deplibs_check_method in
+-file_magic*)
+- if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+- echo $ac_n "checking for ${ac_tool_prefix}file""... $ac_c" 1>&6
+-echo "configure:2401: checking for ${ac_tool_prefix}file" >&5
+-if eval "test \"`echo '$''{'lt_cv_path_MAGIC_CMD'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++done
++# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
++rm -f conftest.err conftest.$ac_ext
++if $ac_preproc_ok; then
++ :
+ else
+- case $MAGIC_CMD in
+- /*)
+- lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+- ;;
+- ?:/*)
+- lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path.
+- ;;
+- *)
+- ac_save_MAGIC_CMD="$MAGIC_CMD"
+- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+- ac_dummy="/usr/bin:$PATH"
+- for ac_dir in $ac_dummy; do
+- test -z "$ac_dir" && ac_dir=.
+- if test -f $ac_dir/${ac_tool_prefix}file; then
+- lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+- if test -n "$file_magic_test_file"; then
++ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
++See \`config.log' for more details." >&5
++echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
++See \`config.log' for more details." >&2;}
++ { (exit 1); exit 1; }; }
++fi
++
++ac_ext=c
++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
++
++
++echo "$as_me:$LINENO: checking for egrep" >&5
++echo $ECHO_N "checking for egrep... $ECHO_C" >&6
++if test "${ac_cv_prog_egrep+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ if echo a | (grep -E '(a|b)') >/dev/null 2>&1
++ then ac_cv_prog_egrep='grep -E'
++ else ac_cv_prog_egrep='egrep'
++ fi
++fi
++echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
++echo "${ECHO_T}$ac_cv_prog_egrep" >&6
++ EGREP=$ac_cv_prog_egrep
++
++
++echo "$as_me:$LINENO: checking for ANSI C header files" >&5
++echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
++if test "${ac_cv_header_stdc+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++#include <stdlib.h>
++#include <stdarg.h>
++#include <string.h>
++#include <float.h>
++
++int
++main ()
++{
++
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest.$ac_objext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ ac_cv_header_stdc=yes
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_cv_header_stdc=no
++fi
++rm -f conftest.$ac_objext conftest.$ac_ext
++
++if test $ac_cv_header_stdc = yes; then
++ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++#include <string.h>
++
++_ACEOF
++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
++ $EGREP "memchr" >/dev/null 2>&1; then
++ :
++else
++ 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 <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++#include <stdlib.h>
++
++_ACEOF
++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
++ $EGREP "free" >/dev/null 2>&1; then
++ :
++else
++ 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 <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++#include <ctype.h>
++#if ((' ' & 0x0FF) == 0x020)
++# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
++# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
++#else
++# define ISLOWER(c) \
++ (('a' <= (c) && (c) <= 'i') \
++ || ('j' <= (c) && (c) <= 'r') \
++ || ('s' <= (c) && (c) <= 'z'))
++# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
++#endif
++
++#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);
++}
++_ACEOF
++rm -f conftest$ac_exeext
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ :
++else
++ echo "$as_me: program exited with status $ac_status" >&5
++echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++( exit $ac_status )
++ac_cv_header_stdc=no
++fi
++rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
++fi
++fi
++fi
++echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
++echo "${ECHO_T}$ac_cv_header_stdc" >&6
++if test $ac_cv_header_stdc = yes; then
++
++cat >>confdefs.h <<\_ACEOF
++#define STDC_HEADERS 1
++_ACEOF
++
++fi
++
++# On IRIX 5.3, sys/types and inttypes.h are conflicting.
++
++
++
++
++
++
++
++
++
++for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
++ inttypes.h stdint.h unistd.h
++do
++as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
++echo "$as_me:$LINENO: checking for $ac_header" >&5
++echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
++if eval "test \"\${$as_ac_Header+set}\" = set"; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++$ac_includes_default
++
++#include <$ac_header>
++_ACEOF
++rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest.$ac_objext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ eval "$as_ac_Header=yes"
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++eval "$as_ac_Header=no"
++fi
++rm -f conftest.$ac_objext conftest.$ac_ext
++fi
++echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
++echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
++if test `eval echo '${'$as_ac_Header'}'` = yes; then
++ cat >>confdefs.h <<_ACEOF
++#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
++_ACEOF
++
++fi
++
++done
++
++
++
++for ac_header in dlfcn.h
++do
++as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
++if eval "test \"\${$as_ac_Header+set}\" = set"; then
++ echo "$as_me:$LINENO: checking for $ac_header" >&5
++echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
++if eval "test \"\${$as_ac_Header+set}\" = set"; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++fi
++echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
++echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
++else
++ # Is the header compilable?
++echo "$as_me:$LINENO: checking $ac_header usability" >&5
++echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
++cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++$ac_includes_default
++#include <$ac_header>
++_ACEOF
++rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest.$ac_objext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ ac_header_compiler=yes
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_header_compiler=no
++fi
++rm -f conftest.$ac_objext conftest.$ac_ext
++echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
++echo "${ECHO_T}$ac_header_compiler" >&6
++
++# Is the header present?
++echo "$as_me:$LINENO: checking $ac_header presence" >&5
++echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
++cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++#include <$ac_header>
++_ACEOF
++if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
++ (eval $ac_cpp conftest.$ac_ext) 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); } >/dev/null; then
++ if test -s conftest.err; then
++ ac_cpp_err=$ac_c_preproc_warn_flag
++ else
++ ac_cpp_err=
++ fi
++else
++ ac_cpp_err=yes
++fi
++if test -z "$ac_cpp_err"; then
++ ac_header_preproc=yes
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ ac_header_preproc=no
++fi
++rm -f conftest.err conftest.$ac_ext
++echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
++echo "${ECHO_T}$ac_header_preproc" >&6
++
++# So? What about this header?
++case $ac_header_compiler:$ac_header_preproc in
++ yes:no )
++ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
++echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
++ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
++echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
++ (
++ cat <<\_ASBOX
++## ------------------------------------ ##
++## Report this to bug-autoconf@gnu.org. ##
++## ------------------------------------ ##
++_ASBOX
++ ) |
++ sed "s/^/$as_me: WARNING: /" >&2
++ ;;
++ no:yes )
++ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
++echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
++ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
++echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
++ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
++echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
++ (
++ cat <<\_ASBOX
++## ------------------------------------ ##
++## Report this to bug-autoconf@gnu.org. ##
++## ------------------------------------ ##
++_ASBOX
++ ) |
++ sed "s/^/$as_me: WARNING: /" >&2
++ ;;
++esac
++echo "$as_me:$LINENO: checking for $ac_header" >&5
++echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
++if eval "test \"\${$as_ac_Header+set}\" = set"; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ eval "$as_ac_Header=$ac_header_preproc"
++fi
++echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
++echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
++
++fi
++if test `eval echo '${'$as_ac_Header'}'` = yes; then
++ cat >>confdefs.h <<_ACEOF
++#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
++_ACEOF
++
++fi
++
++done
++
++
++
++
++
++
++# Only perform the check for file, if the check method requires it
++case $deplibs_check_method in
++file_magic*)
++ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
++ echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5
++echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6
++if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ case $MAGIC_CMD in
++ /*)
++ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
++ ;;
++ ?:/*)
++ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path.
++ ;;
++ *)
++ ac_save_MAGIC_CMD="$MAGIC_CMD"
++ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
++ ac_dummy="/usr/bin:$PATH"
++ for ac_dir in $ac_dummy; do
++ test -z "$ac_dir" && ac_dir=.
++ if test -f $ac_dir/${ac_tool_prefix}file; then
++ lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
++ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+@@ -2451,17 +4493,19 @@
+
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if test -n "$MAGIC_CMD"; then
+- echo "$ac_t""$MAGIC_CMD" 1>&6
++ echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
++echo "${ECHO_T}$MAGIC_CMD" >&6
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
+ fi
+
+ if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+- echo $ac_n "checking for file""... $ac_c" 1>&6
+-echo "configure:2463: checking for file" >&5
+-if eval "test \"`echo '$''{'lt_cv_path_MAGIC_CMD'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++ echo "$as_me:$LINENO: checking for file" >&5
++echo $ECHO_N "checking for file... $ECHO_C" >&6
++if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ case $MAGIC_CMD in
+ /*)
+@@ -2513,9 +4557,11 @@
+
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if test -n "$MAGIC_CMD"; then
+- echo "$ac_t""$MAGIC_CMD" 1>&6
++ echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
++echo "${ECHO_T}$MAGIC_CMD" >&6
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
+ fi
+
+ else
+@@ -2527,138 +4573,164 @@
+ ;;
+ esac
+
+-# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
++if test -n "$ac_tool_prefix"; then
++ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:2534: checking for $ac_word" >&5
+-if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++echo "$as_me:$LINENO: checking for $ac_word" >&5
++echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
++if test "${ac_cv_prog_RANLIB+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&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="${ac_tool_prefix}ranlib"
+- break
+- fi
+- done
+- IFS="$ac_save_ifs"
++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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
++ fi
++done
++done
++
+ fi
+ fi
+-RANLIB="$ac_cv_prog_RANLIB"
++RANLIB=$ac_cv_prog_RANLIB
+ if test -n "$RANLIB"; then
+- echo "$ac_t""$RANLIB" 1>&6
++ echo "$as_me:$LINENO: result: $RANLIB" >&5
++echo "${ECHO_T}$RANLIB" >&6
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
+ fi
+
+-
++fi
+ if test -z "$ac_cv_prog_RANLIB"; then
+-if test -n "$ac_tool_prefix"; then
++ ac_ct_RANLIB=$RANLIB
+ # 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:2566: checking for $ac_word" >&5
+-if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++echo "$as_me:$LINENO: checking for $ac_word" >&5
++echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
++if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+- if test -n "$RANLIB"; then
+- ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
++ if test -n "$ac_ct_RANLIB"; then
++ ac_cv_prog_ac_ct_RANLIB="$ac_ct_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=":"
++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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ ac_cv_prog_ac_ct_RANLIB="ranlib"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
++ fi
++done
++done
++
++ test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+ fi
+ fi
+-RANLIB="$ac_cv_prog_RANLIB"
+-if test -n "$RANLIB"; then
+- echo "$ac_t""$RANLIB" 1>&6
++ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
++if test -n "$ac_ct_RANLIB"; then
++ echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
++echo "${ECHO_T}$ac_ct_RANLIB" >&6
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
+ fi
+
++ RANLIB=$ac_ct_RANLIB
+ else
+- RANLIB=":"
+-fi
++ RANLIB="$ac_cv_prog_RANLIB"
+ fi
+
+-# Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
++if test -n "$ac_tool_prefix"; then
++ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}strip; ac_word=$2
+-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:2601: checking for $ac_word" >&5
+-if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++echo "$as_me:$LINENO: checking for $ac_word" >&5
++echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
++if test "${ac_cv_prog_STRIP+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # 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_STRIP="${ac_tool_prefix}strip"
+- break
+- fi
+- done
+- IFS="$ac_save_ifs"
++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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
++ fi
++done
++done
++
+ fi
+ fi
+-STRIP="$ac_cv_prog_STRIP"
++STRIP=$ac_cv_prog_STRIP
+ if test -n "$STRIP"; then
+- echo "$ac_t""$STRIP" 1>&6
++ echo "$as_me:$LINENO: result: $STRIP" >&5
++echo "${ECHO_T}$STRIP" >&6
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
+ fi
+
+-
++fi
+ if test -z "$ac_cv_prog_STRIP"; then
+-if test -n "$ac_tool_prefix"; then
++ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+ set dummy strip; ac_word=$2
+-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:2633: checking for $ac_word" >&5
+-if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++echo "$as_me:$LINENO: checking for $ac_word" >&5
++echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
++if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+- if test -n "$STRIP"; then
+- ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
++ if test -n "$ac_ct_STRIP"; then
++ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # 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_STRIP="strip"
+- break
+- fi
+- done
+- IFS="$ac_save_ifs"
+- test -z "$ac_cv_prog_STRIP" && ac_cv_prog_STRIP=":"
++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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ ac_cv_prog_ac_ct_STRIP="strip"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
++ fi
++done
++done
++
++ test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":"
+ fi
+ fi
+-STRIP="$ac_cv_prog_STRIP"
+-if test -n "$STRIP"; then
+- echo "$ac_t""$STRIP" 1>&6
++ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
++if test -n "$ac_ct_STRIP"; then
++ echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
++echo "${ECHO_T}$ac_ct_STRIP" >&6
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
+ fi
+
++ STRIP=$ac_ct_STRIP
+ else
+- STRIP=":"
+-fi
++ STRIP="$ac_cv_prog_STRIP"
+ fi
+
+
+@@ -2668,9 +4740,8 @@
+ # Check whether --enable-libtool-lock or --disable-libtool-lock was given.
+ if test "${enable_libtool_lock+set}" = set; then
+ enableval="$enable_libtool_lock"
+- :
+-fi
+
++fi;
+ test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+ # Some flags need to be propagated to the compiler or linker for good
+@@ -2678,8 +4749,12 @@
+ case $host in
+ *-*-irix6*)
+ # Find out which ABI we are using.
+- echo '#line 2682 "configure"' > conftest.$ac_ext
+- if { (eval echo configure:2683: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
++ echo '#line 4752 "configure"' > conftest.$ac_ext
++ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+@@ -2699,47 +4774,64 @@
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+- echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6
+-echo "configure:2704: checking whether the C compiler needs -belf" >&5
+-if eval "test \"`echo '$''{'lt_cv_cc_needs_belf'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++ echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5
++echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6
++if test "${lt_cv_cc_needs_belf+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+-
++
++
+ 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_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
++
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
+
+- cat > conftest.$ac_ext <<EOF
+-#line 2717 "configure"
+-#include "confdefs.h"
+-
+-int main() {
++int
++main ()
++{
+
+-; return 0; }
+-EOF
+-if { (eval echo configure:2724: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+- rm -rf conftest*
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext conftest$ac_exeext
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest$ac_exeext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
+ lt_cv_cc_needs_belf=yes
+ else
+- echo "configure: failed program was:" >&5
+- cat conftest.$ac_ext >&5
+- rm -rf conftest*
+- lt_cv_cc_needs_belf=no
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++lt_cv_cc_needs_belf=no
+ fi
+-rm -f conftest*
++rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+ 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_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
+
+ fi
+-
+-echo "$ac_t""$lt_cv_cc_needs_belf" 1>&6
++echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5
++echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+@@ -2824,16 +4916,23 @@
+ old_postuninstall_cmds=
+
+ if test -n "$RANLIB"; then
++ case $host_os in
++ openbsd*)
++ old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds"
++ ;;
++ *)
++ old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
++ ;;
++ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+- old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
+ fi
+
+ # Allow CC to be a program name with arguments.
+ set dummy $CC
+ compiler="$2"
+
+-echo $ac_n "checking for objdir""... $ac_c" 1>&6
+-echo "configure:2837: checking for objdir" >&5
++echo "$as_me:$LINENO: checking for objdir" >&5
++echo $ECHO_N "checking for objdir... $ECHO_C" >&6
+ rm -f .libs 2>/dev/null
+ mkdir .libs 2>/dev/null
+ if test -d .libs; then
+@@ -2843,7 +4942,9 @@
+ objdir=_libs
+ fi
+ rmdir .libs 2>/dev/null
+-echo "$ac_t""$objdir" 1>&6
++echo "$as_me:$LINENO: result: $objdir" >&5
++echo "${ECHO_T}$objdir" >&6
++
+
+
+ # Check whether --with-pic or --without-pic was given.
+@@ -2852,17 +4953,16 @@
+ pic_mode="$withval"
+ else
+ pic_mode=default
+-fi
+-
++fi;
+ test -z "$pic_mode" && pic_mode=default
+
+ # We assume here that the value for lt_cv_prog_cc_pic will not be cached
+ # in isolation, and that seeing it set (from the cache) indicates that
+ # the associated values are set (in the cache) correctly too.
+-echo $ac_n "checking for $compiler option to produce PIC""... $ac_c" 1>&6
+-echo "configure:2864: checking for $compiler option to produce PIC" >&5
+-if eval "test \"`echo '$''{'lt_cv_prog_cc_pic'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
++echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
++if test "${lt_cv_prog_cc_pic+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ lt_cv_prog_cc_pic=
+ lt_cv_prog_cc_shlib=
+@@ -2882,7 +4982,7 @@
+ # libC (AIX C++ library), which obviously doesn't included in libraries
+ # list by gcc. This cause undefined symbols with -static flags.
+ # This hack allows C programs to be linked with "-static -ldl", but
+- # we not sure about C++ programs.
++ # not sure about C++ programs.
+ lt_cv_prog_cc_static="$lt_cv_prog_cc_static ${lt_cv_prog_cc_wl}-lC"
+ ;;
+ amigaos*)
+@@ -2891,7 +4991,7 @@
+ # like `-m68040'.
+ lt_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4'
+ ;;
+- beos* | irix5* | irix6* | osf3* | osf4* | osf5*)
++ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ darwin* | rhapsody*)
+@@ -2917,13 +5017,13 @@
+ # PORTME Check for PIC flags for the system compiler.
+ case $host_os in
+ aix3* | aix4* | aix5*)
++ lt_cv_prog_cc_wl='-Wl,'
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+- # AIX 5 now supports IA64 processor
+- lt_cv_prog_cc_static='-Bstatic'
+- lt_cv_prog_cc_wl='-Wl,'
++ # AIX 5 now supports IA64 processor
++ lt_cv_prog_cc_static='-Bstatic'
+ else
+- lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp'
++ lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+
+@@ -2934,7 +5034,7 @@
+ lt_cv_prog_cc_pic='+Z'
+ ;;
+
+- irix5* | irix6*)
++ irix5* | irix6* | nonstopux*)
+ lt_cv_prog_cc_wl='-Wl,'
+ lt_cv_prog_cc_static='-non_shared'
+ # PIC (with -KPIC) is the default.
+@@ -2978,11 +5078,7 @@
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ lt_cv_prog_cc_pic='-KPIC'
+ lt_cv_prog_cc_static='-Bstatic'
+- if test "x$host_vendor" = xsni; then
+- lt_cv_prog_cc_wl='-LD'
+- else
+- lt_cv_prog_cc_wl='-Wl,'
+- fi
++ lt_cv_prog_cc_wl='-Wl,'
+ ;;
+
+ uts4*)
+@@ -3006,28 +5102,48 @@
+ fi
+
+ if test -z "$lt_cv_prog_cc_pic"; then
+- echo "$ac_t""none" 1>&6
++ echo "$as_me:$LINENO: result: none" >&5
++echo "${ECHO_T}none" >&6
+ else
+- echo "$ac_t""$lt_cv_prog_cc_pic" 1>&6
++ echo "$as_me:$LINENO: result: $lt_cv_prog_cc_pic" >&5
++echo "${ECHO_T}$lt_cv_prog_cc_pic" >&6
+
+ # Check to make sure the pic_flag actually works.
+- echo $ac_n "checking if $compiler PIC flag $lt_cv_prog_cc_pic works""... $ac_c" 1>&6
+-echo "configure:3016: checking if $compiler PIC flag $lt_cv_prog_cc_pic works" >&5
+- if eval "test \"`echo '$''{'lt_cv_prog_cc_pic_works'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_cv_prog_cc_pic works" >&5
++echo $ECHO_N "checking if $compiler PIC flag $lt_cv_prog_cc_pic works... $ECHO_C" >&6
++ if test "${lt_cv_prog_cc_pic_works+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC"
+- cat > conftest.$ac_ext <<EOF
+-#line 3023 "configure"
+-#include "confdefs.h"
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
+
+-int main() {
++int
++main ()
++{
+
+-; return 0; }
+-EOF
+-if { (eval echo configure:3030: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+- rm -rf conftest*
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest.$ac_objext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
+ case $host_os in
+ hpux9* | hpux10* | hpux11*)
+ # On HP-UX, both CC and GCC only warn that PIC is supported... then
+@@ -3043,17 +5159,17 @@
+ lt_cv_prog_cc_pic_works=yes
+ ;;
+ esac
+-
++
+ else
+- echo "configure: failed program was:" >&5
+- cat conftest.$ac_ext >&5
+- rm -rf conftest*
+- lt_cv_prog_cc_pic_works=no
+-
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ lt_cv_prog_cc_pic_works=no
++
+ fi
+-rm -f conftest*
++rm -f conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+-
++
+ fi
+
+
+@@ -3064,43 +5180,65 @@
+ lt_cv_prog_cc_pic=" $lt_cv_prog_cc_pic"
+ fi
+
+- echo "$ac_t""$lt_cv_prog_cc_pic_works" 1>&6
++ echo "$as_me:$LINENO: result: $lt_cv_prog_cc_pic_works" >&5
++echo "${ECHO_T}$lt_cv_prog_cc_pic_works" >&6
+ fi
+
+ # Check for any special shared library compilation flags.
+ if test -n "$lt_cv_prog_cc_shlib"; then
+- echo "configure: warning: \`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries" 1>&2
++ { echo "$as_me:$LINENO: WARNING: \`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries" >&5
++echo "$as_me: WARNING: \`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries" >&2;}
+ if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$lt_cv_prog_cc_shlib[ ]" >/dev/null; then :
+ else
+- echo "configure: warning: add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" 1>&2
++ { echo "$as_me:$LINENO: WARNING: add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&5
++echo "$as_me: WARNING: add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&2;}
+ lt_cv_prog_cc_can_build_shared=no
+ fi
+ fi
+
+-echo $ac_n "checking if $compiler static flag $lt_cv_prog_cc_static works""... $ac_c" 1>&6
+-echo "configure:3082: checking if $compiler static flag $lt_cv_prog_cc_static works" >&5
+-if eval "test \"`echo '$''{'lt_cv_prog_cc_static_works'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++echo "$as_me:$LINENO: checking if $compiler static flag $lt_cv_prog_cc_static works" >&5
++echo $ECHO_N "checking if $compiler static flag $lt_cv_prog_cc_static works... $ECHO_C" >&6
++if test "${lt_cv_prog_cc_static_works+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ lt_cv_prog_cc_static_works=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static"
+- cat > conftest.$ac_ext <<EOF
+-#line 3090 "configure"
+-#include "confdefs.h"
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
+
+-int main() {
++int
++main ()
++{
+
+-; return 0; }
+-EOF
+-if { (eval echo configure:3097: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+- rm -rf conftest*
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext conftest$ac_exeext
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest$ac_exeext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
+ lt_cv_prog_cc_static_works=yes
+ else
+- echo "configure: failed program was:" >&5
+- cat conftest.$ac_ext >&5
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ fi
+-rm -f conftest*
++rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS="$save_LDFLAGS"
+
+ fi
+@@ -3108,7 +5246,8 @@
+
+ # Belt *and* braces to stop my trousers falling down:
+ test "X$lt_cv_prog_cc_static_works" = Xno && lt_cv_prog_cc_static=
+-echo "$ac_t""$lt_cv_prog_cc_static_works" 1>&6
++echo "$as_me:$LINENO: result: $lt_cv_prog_cc_static_works" >&5
++echo "${ECHO_T}$lt_cv_prog_cc_static_works" >&6
+
+ pic_flag="$lt_cv_prog_cc_pic"
+ special_shlib_compile_flags="$lt_cv_prog_cc_shlib"
+@@ -3119,12 +5258,12 @@
+
+
+ # Check to see if options -o and -c are simultaneously supported by compiler
+-echo $ac_n "checking if $compiler supports -c -o file.$ac_objext""... $ac_c" 1>&6
+-echo "configure:3124: checking if $compiler supports -c -o file.$ac_objext" >&5
+-if eval "test \"`echo '$''{'lt_cv_compiler_c_o'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
++echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
++if test "${lt_cv_compiler_c_o+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+-
++
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+@@ -3139,7 +5278,7 @@
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
+ compiler_c_o=no
+-if { (eval echo configure:3143: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
++if { (eval echo configure:5281: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s out/conftest.err; then
+@@ -3163,29 +5302,50 @@
+ fi
+
+ compiler_c_o=$lt_cv_compiler_c_o
+-echo "$ac_t""$compiler_c_o" 1>&6
++echo "$as_me:$LINENO: result: $compiler_c_o" >&5
++echo "${ECHO_T}$compiler_c_o" >&6
+
+ if test x"$compiler_c_o" = x"yes"; then
+ # Check to see if we can write to a .lo
+- echo $ac_n "checking if $compiler supports -c -o file.lo""... $ac_c" 1>&6
+-echo "configure:3172: checking if $compiler supports -c -o file.lo" >&5
+- if eval "test \"`echo '$''{'lt_cv_compiler_o_lo'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.lo" >&5
++echo $ECHO_N "checking if $compiler supports -c -o file.lo... $ECHO_C" >&6
++ if test "${lt_cv_compiler_o_lo+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+-
++
+ lt_cv_compiler_o_lo=no
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -c -o conftest.lo"
+- cat > conftest.$ac_ext <<EOF
+-#line 3181 "configure"
+-#include "confdefs.h"
++ save_objext="$ac_objext"
++ ac_objext=lo
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
+
+-int main() {
++int
++main ()
++{
+ int some_variable = 0;
+-; return 0; }
+-EOF
+-if { (eval echo configure:3188: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+- rm -rf conftest*
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest.$ac_objext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+@@ -3193,18 +5353,21 @@
+ else
+ lt_cv_compiler_o_lo=yes
+ fi
+-
++
+ else
+- echo "configure: failed program was:" >&5
+- cat conftest.$ac_ext >&5
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ fi
+-rm -f conftest*
++rm -f conftest.$ac_objext conftest.$ac_ext
++ ac_objext="$save_objext"
+ CFLAGS="$save_CFLAGS"
+-
++
+ fi
+
+ compiler_o_lo=$lt_cv_compiler_o_lo
+- echo "$ac_t""$compiler_o_lo" 1>&6
++ echo "$as_me:$LINENO: result: $compiler_o_lo" >&5
++echo "${ECHO_T}$compiler_o_lo" >&6
+ else
+ compiler_o_lo=no
+ fi
+@@ -3213,17 +5376,19 @@
+ hard_links="nottested"
+ if test "$compiler_c_o" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+- echo $ac_n "checking if we can lock with hard links""... $ac_c" 1>&6
+-echo "configure:3218: checking if we can lock with hard links" >&5
++ echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
++echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+- echo "$ac_t""$hard_links" 1>&6
++ echo "$as_me:$LINENO: result: $hard_links" >&5
++echo "${ECHO_T}$hard_links" >&6
+ if test "$hard_links" = no; then
+- echo "configure: warning: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" 1>&2
++ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
++echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+ else
+@@ -3232,22 +5397,40 @@
+
+ if test "$GCC" = yes; then
+ # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
+- echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions""... $ac_c" 1>&6
+-echo "configure:3237: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
++ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
++echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6
+ echo "int some_variable = 0;" > conftest.$ac_ext
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext"
+ compiler_rtti_exceptions=no
+- cat > conftest.$ac_ext <<EOF
+-#line 3243 "configure"
+-#include "confdefs.h"
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
+
+-int main() {
++int
++main ()
++{
+ int some_variable = 0;
+-; return 0; }
+-EOF
+-if { (eval echo configure:3250: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+- rm -rf conftest*
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest.$ac_objext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+@@ -3255,14 +5438,16 @@
+ else
+ compiler_rtti_exceptions=yes
+ fi
+-
++
+ else
+- echo "configure: failed program was:" >&5
+- cat conftest.$ac_ext >&5
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ fi
+-rm -f conftest*
++rm -f conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+- echo "$ac_t""$compiler_rtti_exceptions" 1>&6
++ echo "$as_me:$LINENO: result: $compiler_rtti_exceptions" >&5
++echo "${ECHO_T}$compiler_rtti_exceptions" >&6
+
+ if test "$compiler_rtti_exceptions" = "yes"; then
+ no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
+@@ -3272,8 +5457,8 @@
+ fi
+
+ # See if the linker supports building shared libraries.
+-echo $ac_n "checking whether the linker ($LD) supports shared libraries""... $ac_c" 1>&6
+-echo "configure:3277: checking whether the linker ($LD) supports shared libraries" >&5
++echo "$as_me:$LINENO: checking whether the linker ($LD) supports shared libraries" >&5
++echo $ECHO_N "checking whether the linker ($LD) supports shared libraries... $ECHO_C" >&6
+
+ allow_undefined_flag=
+ no_undefined_flag=
+@@ -3314,7 +5499,7 @@
+ extract_expsyms_cmds=
+
+ case $host_os in
+-cygwin* | mingw* | pw32* )
++cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+@@ -3322,7 +5507,9 @@
+ with_gnu_ld=no
+ fi
+ ;;
+-
++openbsd*)
++ with_gnu_ld=no
++ ;;
+ esac
+
+ ld_shlibs=yes
+@@ -3409,7 +5596,7 @@
+ # can override, but on older systems we have to supply one (in ltdll.c)
+ if test "x$lt_cv_need_dllmain" = "xyes"; then
+ ltdll_obj='$output_objdir/$soname-ltdll.'"$ac_objext "
+- ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < [$]0 > $output_objdir/$soname-ltdll.c~
++ ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $''0 > $output_objdir/$soname-ltdll.c~
+ test -f $output_objdir/$soname-ltdll.$ac_objext || (cd $output_objdir && $CC -c $soname-ltdll.c)~'
+ else
+ ltdll_obj=
+@@ -3427,19 +5614,20 @@
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is.
+ # If DATA tags from a recent dlltool are present, honour them!
+- archive_expsym_cmds='if test "x`head -1 $export_symbols`" = xEXPORTS; then
+- cp $export_symbols $output_objdir/$soname-def;
++ archive_expsym_cmds='if test "x`sed 1q $export_symbols`" = xEXPORTS; then
++ cp $export_symbols $output_objdir/$soname-def;
+ else
+- echo EXPORTS > $output_objdir/$soname-def;
+- _lt_hint=1;
+- cat $export_symbols | while read symbol; do
+- set dummy \$symbol;
+- case \$# in
+- 2) echo " \$2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;;
+- *) echo " \$2 @ \$_lt_hint \$3 ; " >> $output_objdir/$soname-def;;
+- esac;
+- _lt_hint=`expr 1 + \$_lt_hint`;
+- done;
++ echo EXPORTS > $output_objdir/$soname-def;
++ _lt_hint=1;
++ cat $export_symbols | while read symbol; do
++ set dummy \$symbol;
++ case \$# in
++ 2) echo " \$2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;;
++ 4) echo " \$2 \$3 \$4 ; " >> $output_objdir/$soname-def; _lt_hint=`expr \$_lt_hint - 1`;;
++ *) echo " \$2 @ \$_lt_hint \$3 ; " >> $output_objdir/$soname-def;;
++ esac;
++ _lt_hint=`expr 1 + \$_lt_hint`;
++ done;
+ fi~
+ '"$ltdll_cmds"'
+ $CC -Wl,--base-file,$output_objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~
+@@ -3534,80 +5722,98 @@
+ ;;
+
+ aix4* | aix5*)
++ if test "$host_cpu" = ia64; then
++ # On IA64, the linker does run time linking by default, so we don't
++ # have to do anything special.
++ aix_use_runtimelinking=no
++ exp_sym_flag='-Bexport'
++ no_entry_flag=""
++ else
++ aix_use_runtimelinking=no
++
++ # Test if we are trying to use run time linking or normal
++ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
++ # need to do runtime linking.
++ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
++ for ld_flag in $LDFLAGS; do
++ case $ld_flag in
++ *-brtl*)
++ aix_use_runtimelinking=yes
++ break
++ ;;
++ esac
++ done
++ esac
++
++ exp_sym_flag='-bexport'
++ no_entry_flag='-bnoentry'
++ fi
++
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
++ hardcode_direct=yes
+ archive_cmds=''
+ hardcode_libdir_separator=':'
+ if test "$GCC" = yes; then
+- collect2name=`${CC} -print-prog-name=collect2`
+- if test -f "$collect2name" && \
+- strings "$collect2name" | grep resolve_lib_name >/dev/null
+- then
+- # We have reworked collect2
+- hardcode_direct=yes
+- else
+- # We have old collect2
+- hardcode_direct=unsupported
+- # It fails to find uninstalled libraries when the uninstalled
+- # path is not listed in the libpath. Setting hardcode_minus_L
+- # to unsupported forces relinking
+- hardcode_minus_L=yes
+- hardcode_libdir_flag_spec='-L$libdir'
+- hardcode_libdir_separator=
+- fi
+- shared_flag='-shared'
+- else
++ case $host_os in aix4.[012]|aix4.[012].*)
++ collect2name=`${CC} -print-prog-name=collect2`
++ if test -f "$collect2name" && \
++ strings "$collect2name" | grep resolve_lib_name >/dev/null
++ then
++ # We have reworked collect2
++ hardcode_direct=yes
++ else
++ # We have old collect2
++ hardcode_direct=unsupported
++ # It fails to find uninstalled libraries when the uninstalled
++ # path is not listed in the libpath. Setting hardcode_minus_L
++ # to unsupported forces relinking
++ hardcode_minus_L=yes
++ hardcode_libdir_flag_spec='-L$libdir'
++ hardcode_libdir_separator=
++ fi
++ esac
++
++ shared_flag='-shared'
++ else
++ # not using gcc
+ if test "$host_cpu" = ia64; then
+- shared_flag='-G'
++ shared_flag='${wl}-G'
+ else
+- shared_flag='${wl}-bM:SRE'
++ if test "$aix_use_runtimelinking" = yes; then
++ shared_flag='${wl}-G'
++ else
++ shared_flag='${wl}-bM:SRE'
++ fi
+ fi
+- hardcode_direct=yes
+ fi
+
+- if test "$host_cpu" = ia64; then
+- # On IA64, the linker does run time linking by default, so we don't
+- # have to do anything special.
+- aix_use_runtimelinking=no
+- exp_sym_flag='-Bexport'
+- no_entry_flag=""
+- else
+- # Test if we are trying to use run time linking, or normal AIX style linking.
+- # If -brtl is somewhere in LDFLAGS, we need to do run time linking.
+- aix_use_runtimelinking=no
+- for ld_flag in $LDFLAGS; do
+- if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl" ); then
+- aix_use_runtimelinking=yes
+- break
+- fi
+- done
+- exp_sym_flag='-bexport'
+- no_entry_flag='-bnoentry'
+- fi
+ # It seems that -bexpall can do strange things, so it is better to
+ # generate a list of symbols to export.
+ always_export_symbols=yes
+ if test "$aix_use_runtimelinking" = yes; then
++ # Warning - without using the other runtime loading flags (-brtl),
++ # -berok will link without error, but may produce a broken library.
++ allow_undefined_flag='-berok'
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib'
+- allow_undefined_flag=' -Wl,-G'
+- archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
++ archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+- hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+- allow_undefined_flag="-znodefs"
+- archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname ${wl}-h$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
++ hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
++ allow_undefined_flag="-z nodefs"
++ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname ${wl}-h$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
+ else
+- hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib'
+- # Warning - without using the other run time loading flags, -berok will
+- # link without error, but may produce a broken library.
+- allow_undefined_flag='${wl}-berok'
+- # This is a bit strange, but is similar to how AIX traditionally builds
+- # it's shared libraries.
+- archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"' ~$AR -crlo $objdir/$libname$release.a $objdir/$soname'
++ hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib'
++ # Warning - without using the other run time loading flags,
++ # -berok will link without error, but may produce a broken library.
++ allow_undefined_flag='${wl}-berok'
++ # This is a bit strange, but is similar to how AIX traditionally builds
++ # it's shared libraries.
++ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"' ~$AR -crlo $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+@@ -3639,11 +5845,19 @@
+ ;;
+
+ darwin* | rhapsody*)
+- allow_undefined_flag='-undefined suppress'
++ case "$host_os" in
++ rhapsody* | darwin1.[012])
++ allow_undefined_flag='-undefined suppress'
++ ;;
++ *) # Darwin 1.3 on
++ allow_undefined_flag='-flat_namespace -undefined suppress'
++ ;;
++ esac
+ # FIXME: Relying on posixy $() will cause problems for
+ # cross-compilation, but unfortunately the echo tests do not
+- # yet detect zsh echo's removal of \ escapes.
+- archive_cmds='$CC $(test .$module = .yes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs$linkopts -install_name $rpath/$soname $(test -n "$verstring" -a x$verstring != x0.0 && echo $verstring)'
++ # yet detect zsh echo's removal of \ escapes. Also zsh mangles
++ # `"' quotes if we put them in here... so don't!
++ archive_cmds='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs && $CC $(test .$module = .yes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib ${lib}-master.o $deplibs$linker_flags $(test .$module != .yes && echo -install_name $rpath/$soname $verstring)'
+ # We need to add '_' to the symbols in $export_symbols first
+ #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols'
+ hardcode_direct=yes
+@@ -3695,13 +5909,14 @@
+ export_dynamic_flag_spec='${wl}-E'
+ ;;
+
+- irix5* | irix6*)
++ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
++ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ else
+ archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
++ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ link_all_deplibs=yes
+ ;;
+@@ -3718,7 +5933,7 @@
+ ;;
+
+ newsos6)
+- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
++ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+@@ -3726,10 +5941,24 @@
+ ;;
+
+ openbsd*)
+- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+- hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
++ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
++ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
++ export_dynamic_flag_spec='${wl}-E'
++ else
++ case "$host_os" in
++ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
++ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
++ hardcode_libdir_flag_spec='-R$libdir'
++ ;;
++ *)
++ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
++ ;;
++ esac
++ fi
+ ;;
+
+ os2*)
+@@ -3774,10 +6003,39 @@
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
++ export_dynamic_flag_spec='${wl}-Bexport'
+ ;;
+
+ solaris*)
++ # gcc --version < 3.0 without binutils cannot create self contained
++ # shared libraries reliably, requiring libgcc.a to resolve some of
++ # the object symbols generated in some cases. Libraries that use
++ # assert need libgcc.a to resolve __eprintf, for example. Linking
++ # a copy of libgcc.a into every shared library to guarantee resolving
++ # such symbols causes other problems: According to Tim Van Holder
++ # <tim.van.holder@pandora.be>, C++ libraries end up with a separate
++ # (to the application) exception stack for one thing.
+ no_undefined_flag=' -z defs'
++ if test "$GCC" = yes; then
++ case `$CC --version 2>/dev/null` in
++ [12].*)
++ cat <<EOF 1>&2
++
++*** Warning: Releases of GCC earlier than version 3.0 cannot reliably
++*** create self contained shared libraries on Solaris systems, without
++*** introducing a dependency on libgcc.a. Therefore, libtool is disabling
++*** -no-undefined support, which will at least allow you to build shared
++*** libraries. However, you may find that when you link such libraries
++*** into an application without using GCC, you have to manually add
++*** \`gcc --print-libgcc-file-name\` to the link command. We urge you to
++*** upgrade to a newer version of GCC. Another option is to rebuild your
++*** current GCC to use the GNU linker from GNU binutils 2.9.1 or newer.
++
++EOF
++ no_undefined_flag=
++ ;;
++ esac
++ fi
+ # $CC -shared without GNU ld will not create a library from C++
+ # object files and a static libstdc++, better avoid it by now
+ archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+@@ -3808,13 +6066,23 @@
+ ;;
+
+ sysv4)
+- if test "x$host_vendor" = xsno; then
+- archive_cmds='$LD -G -Bsymbolic -h $soname -o $lib $libobjs $deplibs $linkopts'
+- hardcode_direct=yes # is this really true???
+- else
+- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+- hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+- fi
++ case $host_vendor in
++ sni)
++ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ hardcode_direct=yes # is this really true???
++ ;;
++ siemens)
++ ## LD is ld it makes a PLAMLIB
++ ## CC just makes a GrossModule.
++ archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
++ reload_cmds='$CC -r -o $output$reload_objs'
++ hardcode_direct=no
++ ;;
++ motorola)
++ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
++ ;;
++ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ ;;
+@@ -3884,12 +6152,13 @@
+ ;;
+ esac
+ fi
+-echo "$ac_t""$ld_shlibs" 1>&6
++echo "$as_me:$LINENO: result: $ld_shlibs" >&5
++echo "${ECHO_T}$ld_shlibs" >&6
+ test "$ld_shlibs" = no && can_build_shared=no
+
+ # Check hardcoding attributes.
+-echo $ac_n "checking how to hardcode library paths into programs""... $ac_c" 1>&6
+-echo "configure:3893: checking how to hardcode library paths into programs" >&5
++echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
++echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
+ hardcode_action=
+ if test -n "$hardcode_libdir_flag_spec" || \
+ test -n "$runpath_var"; then
+@@ -3912,26 +6181,29 @@
+ # directories.
+ hardcode_action=unsupported
+ fi
+-echo "$ac_t""$hardcode_action" 1>&6
++echo "$as_me:$LINENO: result: $hardcode_action" >&5
++echo "${ECHO_T}$hardcode_action" >&6
+
+ striplib=
+ old_striplib=
+-echo $ac_n "checking whether stripping libraries is possible""... $ac_c" 1>&6
+-echo "configure:3921: checking whether stripping libraries is possible" >&5
++echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5
++echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6
+ if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+- echo "$ac_t""yes" 1>&6
++ echo "$as_me:$LINENO: result: yes" >&5
++echo "${ECHO_T}yes" >&6
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
+ fi
+
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+ # PORTME Fill in your ld.so characteristics
+-echo $ac_n "checking dynamic linker characteristics""... $ac_c" 1>&6
+-echo "configure:3935: checking dynamic linker characteristics" >&5
++echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
++echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
+ library_names_spec=
+ libname_spec='lib$name'
+ soname_spec=
+@@ -3958,6 +6230,9 @@
+
+ aix4* | aix5*)
+ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}.so$major ${libname}${release}.so$versuffix $libname.so'
+@@ -3969,22 +6244,24 @@
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+- aix4 | aix4.[01] | aix4.[01].*)
+- if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+- echo ' yes '
+- echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+- :
+- else
+- can_build_shared=no
+- fi
+- ;;
++ aix4 | aix4.[01] | aix4.[01].*)
++ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
++ echo ' yes '
++ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
++ :
++ else
++ can_build_shared=no
++ fi
++ ;;
+ esac
+- # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+- # soname into executable. Probably we can add versioning support to
+- # collect2, so additional links can be useful in future.
++ # AIX (on Power*) has no versioning support, so currently we can
++ # not hardcode correct soname into executable. Probably we can
++ # add versioning support to collect2, so additional links can
++ # be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+- # If using run time linking (on AIX 4.2 or later) use lib<name>.so instead of
+- # lib<name>.a to let people know that these are not typical AIX shared libraries.
++ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
++ # instead of lib<name>.a to let people know that these are not
++ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+@@ -3993,8 +6270,8 @@
+ soname_spec='${libname}${release}.so$major'
+ fi
+ shlibpath_var=LIBPATH
+- deplibs_check_method=pass_all
+ fi
++ hardcode_into_libs=yes
+ ;;
+
+ amigaos*)
+@@ -4042,7 +6319,7 @@
+ ;;
+ yes,mingw*)
+ library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll'
+- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g"`
++ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g" -e "s,=/,/,g"`
+ ;;
+ yes,pw32*)
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | sed -e 's/./-/g'`${versuffix}.dll'
+@@ -4074,6 +6351,18 @@
+ dynamic_linker=no
+ ;;
+
++freebsd*-gnu*)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
++ soname_spec='${libname}${release}.so$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ hardcode_into_libs=yes
++ dynamic_linker='GNU/FreeBSD ld.so'
++ ;;
++
+ freebsd*)
+ objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+ version_type=freebsd-$objformat
+@@ -4125,14 +6414,17 @@
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+-irix5* | irix6*)
+- version_type=irix
++irix5* | irix6* | nonstopux*)
++ case $host_os in
++ nonstopux*) version_type=nonstopux ;;
++ *) version_type=irix ;;
++ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}.so$major'
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so $libname.so'
+ case $host_os in
+- irix5*)
++ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+@@ -4206,9 +6498,19 @@
+
+ openbsd*)
+ version_type=sunos
+- if test "$with_gnu_ld" = yes; then
+- need_lib_prefix=no
+- need_version=no
++ need_lib_prefix=no
++ need_version=no
++ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
++ case "$host_os" in
++ openbsd2.[89] | openbsd2.[89].*)
++ shlibpath_overrides_runpath=no
++ ;;
++ *)
++ shlibpath_overrides_runpath=yes
++ ;;
++ esac
++ else
++ shlibpath_overrides_runpath=yes
+ fi
+ library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+@@ -4226,11 +6528,13 @@
+ osf3* | osf4* | osf5*)
+ version_type=osf
+ need_version=no
+- soname_spec='${libname}${release}.so'
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
++ need_lib_prefix=no
++ soname_spec='${libname}${release}.so$major'
++ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
++ hardcode_into_libs=yes
+ ;;
+
+ sco3.2v5*)
+@@ -4273,6 +6577,12 @@
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
++ need_lib_prefix=no
++ export_dynamic_flag_spec='${wl}-Blargedynsym'
++ runpath_var=LD_RUN_PATH
++ ;;
++ siemens)
++ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+@@ -4312,13 +6622,46 @@
+ dynamic_linker=no
+ ;;
+ esac
+-echo "$ac_t""$dynamic_linker" 1>&6
++echo "$as_me:$LINENO: result: $dynamic_linker" >&5
++echo "${ECHO_T}$dynamic_linker" >&6
+ test "$dynamic_linker" = no && can_build_shared=no
+
+ # Report the final consequences.
+-echo $ac_n "checking if libtool supports shared libraries""... $ac_c" 1>&6
+-echo "configure:4321: checking if libtool supports shared libraries" >&5
+-echo "$ac_t""$can_build_shared" 1>&6
++echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
++echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6
++echo "$as_me:$LINENO: result: $can_build_shared" >&5
++echo "${ECHO_T}$can_build_shared" >&6
++
++echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
++echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6
++test "$can_build_shared" = "no" && enable_shared=no
++
++# On AIX, shared libraries and static libraries use the same namespace, and
++# are all built from PIC.
++case "$host_os" in
++aix3*)
++ test "$enable_shared" = yes && enable_static=no
++ if test -n "$RANLIB"; then
++ archive_cmds="$archive_cmds~\$RANLIB \$lib"
++ postinstall_cmds='$RANLIB $lib'
++ fi
++ ;;
++
++aix4*)
++ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
++ test "$enable_shared" = yes && enable_static=no
++ fi
++ ;;
++esac
++echo "$as_me:$LINENO: result: $enable_shared" >&5
++echo "${ECHO_T}$enable_shared" >&6
++
++echo "$as_me:$LINENO: checking whether to build static libraries" >&5
++echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6
++# Make sure either enable_shared or enable_static is yes.
++test "$enable_shared" = yes || enable_static=yes
++echo "$as_me:$LINENO: result: $enable_static" >&5
++echo "${ECHO_T}$enable_static" >&6
+
+ if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+@@ -4355,224 +6698,398 @@
+ ;;
+
+ *)
+- echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
+-echo "configure:4360: checking for dlopen in -ldl" >&5
+-ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
+-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
+-else
+- ac_save_LIBS="$LIBS"
+-LIBS="-ldl $LIBS"
+-cat > conftest.$ac_ext <<EOF
+-#line 4368 "configure"
+-#include "confdefs.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 dlopen();
+-
+-int main() {
+-dlopen()
+-; return 0; }
+-EOF
+-if { (eval echo configure:4379: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+- rm -rf conftest*
+- eval "ac_cv_lib_$ac_lib_var=yes"
+-else
+- echo "configure: failed program was:" >&5
+- cat conftest.$ac_ext >&5
+- rm -rf conftest*
+- eval "ac_cv_lib_$ac_lib_var=no"
+-fi
+-rm -f conftest*
+-LIBS="$ac_save_LIBS"
+-
+-fi
+-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+- echo "$ac_t""yes" 1>&6
+- lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+-else
+- echo "$ac_t""no" 1>&6
+-echo $ac_n "checking for dlopen""... $ac_c" 1>&6
+-echo "configure:4398: checking for dlopen" >&5
+-if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
+-else
+- cat > conftest.$ac_ext <<EOF
+-#line 4403 "configure"
+-#include "confdefs.h"
++ echo "$as_me:$LINENO: checking for shl_load" >&5
++echo $ECHO_N "checking for shl_load... $ECHO_C" >&6
++if test "${ac_cv_func_shl_load+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
+ /* System header to define __stub macros and hopefully few prototypes,
+- which can conflict with char dlopen(); below. */
+-#include <assert.h>
++ which can conflict with char shl_load (); below.
++ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
++ <limits.h> exists even on freestanding compilers. */
++#ifdef __STDC__
++# include <limits.h>
++#else
++# include <assert.h>
++#endif
+ /* Override any gcc2 internal prototype to avoid an error. */
++#ifdef __cplusplus
++extern "C"
++{
++#endif
+ /* We use char because int might match the return type of a gcc2
+- builtin and then its argument prototype would still apply. */
+-char dlopen();
+-
+-int main() {
+-
++ builtin and then its argument prototype would still apply. */
++char shl_load ();
+ /* 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_dlopen) || defined (__stub___dlopen)
++#if defined (__stub_shl_load) || defined (__stub___shl_load)
+ choke me
+ #else
+-dlopen();
++char (*f) () = shl_load;
++#endif
++#ifdef __cplusplus
++}
+ #endif
+
+-; return 0; }
+-EOF
+-if { (eval echo configure:4426: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+- rm -rf conftest*
+- eval "ac_cv_func_dlopen=yes"
+-else
+- echo "configure: failed program was:" >&5
+- cat conftest.$ac_ext >&5
+- rm -rf conftest*
+- eval "ac_cv_func_dlopen=no"
+-fi
+-rm -f conftest*
+-fi
+-
+-if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then
+- echo "$ac_t""yes" 1>&6
+- lt_cv_dlopen="dlopen"
++int
++main ()
++{
++return f != shl_load;
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext conftest$ac_exeext
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest$ac_exeext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ ac_cv_func_shl_load=yes
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_cv_func_shl_load=no
++fi
++rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++fi
++echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
++echo "${ECHO_T}$ac_cv_func_shl_load" >&6
++if test $ac_cv_func_shl_load = yes; then
++ lt_cv_dlopen="shl_load"
+ else
+- echo "$ac_t""no" 1>&6
+-echo $ac_n "checking for shl_load""... $ac_c" 1>&6
+-echo "configure:4444: checking for shl_load" >&5
+-if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++ echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
++echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6
++if test "${ac_cv_lib_dld_shl_load+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+- cat > conftest.$ac_ext <<EOF
+-#line 4449 "configure"
+-#include "confdefs.h"
++ ac_check_lib_save_LIBS=$LIBS
++LIBS="-ldld $LIBS"
++cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++
++/* Override any gcc2 internal prototype to avoid an error. */
++#ifdef __cplusplus
++extern "C"
++#endif
++/* We use char because int might match the return type of a gcc2
++ builtin and then its argument prototype would still apply. */
++char shl_load ();
++int
++main ()
++{
++shl_load ();
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext conftest$ac_exeext
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest$ac_exeext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ ac_cv_lib_dld_shl_load=yes
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_cv_lib_dld_shl_load=no
++fi
++rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
++echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6
++if test $ac_cv_lib_dld_shl_load = yes; then
++ lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"
++else
++ echo "$as_me:$LINENO: checking for dlopen" >&5
++echo $ECHO_N "checking for dlopen... $ECHO_C" >&6
++if test "${ac_cv_func_dlopen+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
+ /* System header to define __stub macros and hopefully few prototypes,
+- which can conflict with char shl_load(); below. */
+-#include <assert.h>
++ which can conflict with char dlopen (); below.
++ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
++ <limits.h> exists even on freestanding compilers. */
++#ifdef __STDC__
++# include <limits.h>
++#else
++# include <assert.h>
++#endif
+ /* Override any gcc2 internal prototype to avoid an error. */
++#ifdef __cplusplus
++extern "C"
++{
++#endif
+ /* We use char because int might match the return type of a gcc2
+- builtin and then its argument prototype would still apply. */
+-char shl_load();
+-
+-int main() {
+-
++ builtin and then its argument prototype would still apply. */
++char dlopen ();
+ /* 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_shl_load) || defined (__stub___shl_load)
++#if defined (__stub_dlopen) || defined (__stub___dlopen)
+ choke me
+ #else
+-shl_load();
++char (*f) () = dlopen;
++#endif
++#ifdef __cplusplus
++}
+ #endif
+
+-; return 0; }
+-EOF
+-if { (eval echo configure:4472: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+- rm -rf conftest*
+- eval "ac_cv_func_shl_load=yes"
++int
++main ()
++{
++return f != dlopen;
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext conftest$ac_exeext
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest$ac_exeext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ ac_cv_func_dlopen=yes
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_cv_func_dlopen=no
++fi
++rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++fi
++echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5
++echo "${ECHO_T}$ac_cv_func_dlopen" >&6
++if test $ac_cv_func_dlopen = yes; then
++ lt_cv_dlopen="dlopen"
+ else
+- echo "configure: failed program was:" >&5
+- cat conftest.$ac_ext >&5
+- rm -rf conftest*
+- eval "ac_cv_func_shl_load=no"
+-fi
+-rm -f conftest*
+-fi
++ echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
++echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
++if test "${ac_cv_lib_dl_dlopen+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ ac_check_lib_save_LIBS=$LIBS
++LIBS="-ldl $LIBS"
++cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
+
+-if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then
+- echo "$ac_t""yes" 1>&6
+- lt_cv_dlopen="shl_load"
++/* Override any gcc2 internal prototype to avoid an error. */
++#ifdef __cplusplus
++extern "C"
++#endif
++/* We use char because int might match the return type of a gcc2
++ builtin and then its argument prototype would still apply. */
++char dlopen ();
++int
++main ()
++{
++dlopen ();
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext conftest$ac_exeext
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest$ac_exeext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ ac_cv_lib_dl_dlopen=yes
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_cv_lib_dl_dlopen=no
++fi
++rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
++echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
++if test $ac_cv_lib_dl_dlopen = yes; then
++ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+ else
+- echo "$ac_t""no" 1>&6
+-echo $ac_n "checking for dlopen in -lsvld""... $ac_c" 1>&6
+-echo "configure:4490: checking for dlopen in -lsvld" >&5
+-ac_lib_var=`echo svld'_'dlopen | sed 'y%./+-%__p_%'`
+-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++ echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5
++echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6
++if test "${ac_cv_lib_svld_dlopen+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+- ac_save_LIBS="$LIBS"
++ ac_check_lib_save_LIBS=$LIBS
+ LIBS="-lsvld $LIBS"
+-cat > conftest.$ac_ext <<EOF
+-#line 4498 "configure"
+-#include "confdefs.h"
++cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++
+ /* Override any gcc2 internal prototype to avoid an error. */
++#ifdef __cplusplus
++extern "C"
++#endif
+ /* We use char because int might match the return type of a gcc2
+- builtin and then its argument prototype would still apply. */
+-char dlopen();
+-
+-int main() {
+-dlopen()
+-; return 0; }
+-EOF
+-if { (eval echo configure:4509: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+- rm -rf conftest*
+- eval "ac_cv_lib_$ac_lib_var=yes"
+-else
+- echo "configure: failed program was:" >&5
+- cat conftest.$ac_ext >&5
+- rm -rf conftest*
+- eval "ac_cv_lib_$ac_lib_var=no"
+-fi
+-rm -f conftest*
+-LIBS="$ac_save_LIBS"
+-
+-fi
+-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+- echo "$ac_t""yes" 1>&6
++ builtin and then its argument prototype would still apply. */
++char dlopen ();
++int
++main ()
++{
++dlopen ();
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext conftest$ac_exeext
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest$ac_exeext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ ac_cv_lib_svld_dlopen=yes
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_cv_lib_svld_dlopen=no
++fi
++rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
++echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6
++if test $ac_cv_lib_svld_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+ else
+- echo "$ac_t""no" 1>&6
+-echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
+-echo "configure:4528: checking for shl_load in -ldld" >&5
+-ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
+-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++ echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5
++echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6
++if test "${ac_cv_lib_dld_dld_link+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+- ac_save_LIBS="$LIBS"
++ ac_check_lib_save_LIBS=$LIBS
+ LIBS="-ldld $LIBS"
+-cat > conftest.$ac_ext <<EOF
+-#line 4536 "configure"
+-#include "confdefs.h"
++cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++
+ /* Override any gcc2 internal prototype to avoid an error. */
++#ifdef __cplusplus
++extern "C"
++#endif
+ /* We use char because int might match the return type of a gcc2
+- builtin and then its argument prototype would still apply. */
+-char shl_load();
+-
+-int main() {
+-shl_load()
+-; return 0; }
+-EOF
+-if { (eval echo configure:4547: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+- rm -rf conftest*
+- eval "ac_cv_lib_$ac_lib_var=yes"
+-else
+- echo "configure: failed program was:" >&5
+- cat conftest.$ac_ext >&5
+- rm -rf conftest*
+- eval "ac_cv_lib_$ac_lib_var=no"
++ builtin and then its argument prototype would still apply. */
++char dld_link ();
++int
++main ()
++{
++dld_link ();
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext conftest$ac_exeext
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest$ac_exeext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ ac_cv_lib_dld_dld_link=yes
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_cv_lib_dld_dld_link=no
++fi
++rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
++echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6
++if test $ac_cv_lib_dld_dld_link = yes; then
++ lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"
+ fi
+-rm -f conftest*
+-LIBS="$ac_save_LIBS"
+
+-fi
+-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+- echo "$ac_t""yes" 1>&6
+- lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"
+-else
+- echo "$ac_t""no" 1>&6
++
+ fi
+
+-
++
+ fi
+
+-
++
+ fi
+
+-
++
+ fi
+
+-
++
+ fi
+
+ ;;
+@@ -4595,10 +7112,10 @@
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+- echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6
+-echo "configure:4600: checking whether a program can dlopen itself" >&5
+-if eval "test \"`echo '$''{'lt_cv_dlopen_self'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++ echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5
++echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6
++if test "${lt_cv_dlopen_self+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self=cross
+@@ -4606,7 +7123,7 @@
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+-#line 4610 "configure"
++#line 7126 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+@@ -4667,7 +7184,11 @@
+ exit (status);
+ }
+ EOF
+- if { (eval echo configure:4671: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} 2>/dev/null; then
++ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+@@ -4682,17 +7203,17 @@
+ fi
+ rm -fr conftest*
+
+-
+-fi
+
+-echo "$ac_t""$lt_cv_dlopen_self" 1>&6
++fi
++echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5
++echo "${ECHO_T}$lt_cv_dlopen_self" >&6
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ LDFLAGS="$LDFLAGS $link_static_flag"
+- echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6
+-echo "configure:4694: checking whether a statically linked program can dlopen itself" >&5
+-if eval "test \"`echo '$''{'lt_cv_dlopen_self_static'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++ echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5
++echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6
++if test "${lt_cv_dlopen_self_static+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self_static=cross
+@@ -4700,7 +7221,7 @@
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+-#line 4704 "configure"
++#line 7224 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+@@ -4761,7 +7282,11 @@
+ exit (status);
+ }
+ EOF
+- if { (eval echo configure:4765: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} 2>/dev/null; then
++ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+@@ -4776,10 +7301,10 @@
+ fi
+ rm -fr conftest*
+
+-
+-fi
+
+-echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6
++fi
++echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5
++echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+@@ -4809,15 +7334,19 @@
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+- echo $ac_n "checking whether -lc should be explicitly linked in""... $ac_c" 1>&6
+-echo "configure:4814: checking whether -lc should be explicitly linked in" >&5
+- if eval "test \"`echo '$''{'lt_cv_archive_cmds_need_lc'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++ echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
++echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
++ if test "${lt_cv_archive_cmds_need_lc+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ $rm conftest*
+ echo 'static int dummy;' > conftest.$ac_ext
+
+- if { (eval echo configure:4821: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
++ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+@@ -4830,7 +7359,11 @@
+ libname=conftest
+ save_allow_undefined_flag=$allow_undefined_flag
+ allow_undefined_flag=
+- if { (eval echo configure:4834: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\") 1>&5; (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5; }
++ if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
++ (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }
+ then
+ lt_cv_archive_cmds_need_lc=no
+ else
+@@ -4842,7 +7375,8 @@
+ fi
+ fi
+
+- echo "$ac_t""$lt_cv_archive_cmds_need_lc" 1>&6
++ echo "$as_me:$LINENO: result: $lt_cv_archive_cmds_need_lc" >&5
++echo "${ECHO_T}$lt_cv_archive_cmds_need_lc" >&6
+ ;;
+ esac
+ fi
+@@ -4870,7 +7404,7 @@
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+- for var in echo old_CC old_CFLAGS \
++ for var in echo old_CC old_CFLAGS SED \
+ AR AR_FLAGS CC LD LN_S NM SHELL \
+ reload_flag reload_cmds wl \
+ pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
+@@ -4882,6 +7416,7 @@
+ old_striplib striplib file_magic_cmd export_symbols_cmds \
+ deplibs_check_method allow_undefined_flag no_undefined_flag \
+ finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
++ global_symbol_to_c_name_address \
+ hardcode_libdir_flag_spec hardcode_libdir_separator \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
+@@ -4931,8 +7466,11 @@
+ # configuration script generated by Autoconf, you may include it under
+ # the same distribution terms that you use for the rest of that program.
+
++# A sed that does not truncate output.
++SED=$lt_SED
++
+ # Sed that helps us avoid accidentally triggering echo(1) options like -n.
+-Xsed="sed -e s/^X//"
++Xsed="${SED} -e s/^X//"
+
+ # The HP-UX ksh and POSIX shell print the target directory to stdout
+ # if CDPATH is set.
+@@ -4948,12 +7486,12 @@
+ # Whether or not to build shared libraries.
+ build_libtool_libs=$enable_shared
+
+-# Whether or not to add -lc for building shared libraries.
+-build_libtool_need_lc=$need_lc
+-
+ # Whether or not to build static libraries.
+ build_old_libs=$enable_static
+
++# Whether or not to add -lc for building shared libraries.
++build_libtool_need_lc=$need_lc
++
+ # Whether or not to optimize for fast installation.
+ fast_install=$enable_fast_install
+
+@@ -5119,6 +7657,9 @@
+ # Transform the output of nm in a proper C declaration
+ global_symbol_to_cdecl=$lt_global_symbol_to_cdecl
+
++# Transform the output of nm in a C name address pair
++global_symbol_to_c_name_address=$lt_global_symbol_to_c_name_address
++
+ # This is the shared library runtime path variable.
+ runpath_var=$runpath_var
+
+@@ -5241,9 +7782,9 @@
+ # return TRUE;
+ # }
+ # /* ltdll.c ends here */
+- # This is a source program that is used to create import libraries
+- # on Windows for dlls which lack them. Don't remove nor modify the
+- # starting and closing comments
++ # This is a source program that is used to create import libraries
++ # on Windows for dlls which lack them. Don't remove nor modify the
++ # starting and closing comments
+ # /* impgen.c starts here */
+ # /* Copyright (C) 1999-2000 Free Software Foundation, Inc.
+ #
+@@ -5411,156 +7952,386 @@
+
+ # Extract the first word of "perl", so it can be a program name with args.
+ set dummy perl; ac_word=$2
+-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:5416: checking for $ac_word" >&5
+-if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++echo "$as_me:$LINENO: checking for $ac_word" >&5
++echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
++if test "${ac_cv_path_PERL+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+- case "$PERL" in
+- /*)
++ case $PERL in
++ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
+ ;;
+- ?:/*)
+- ac_cv_path_PERL="$PERL" # Let the user override the test with a dos path.
+- ;;
+ *)
+- 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_path_PERL="$ac_dir/$ac_word"
+- break
+- fi
+- done
+- IFS="$ac_save_ifs"
++ 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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
++ fi
++done
++done
++
+ ;;
+ esac
+ fi
+-PERL="$ac_cv_path_PERL"
++PERL=$ac_cv_path_PERL
++
+ if test -n "$PERL"; then
+- echo "$ac_t""$PERL" 1>&6
++ echo "$as_me:$LINENO: result: $PERL" >&5
++echo "${ECHO_T}$PERL" >&6
+ else
+- echo "$ac_t""no" 1>&6
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
+ fi
+
+
+
+
+-ac_safe=`echo "asm/errno.h" | sed 'y%./+-%__p_%'`
+-echo $ac_n "checking for asm/errno.h""... $ac_c" 1>&6
+-echo "configure:5453: checking for asm/errno.h" >&5
+-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++if test "${ac_cv_header_asm_errno_h+set}" = set; then
++ echo "$as_me:$LINENO: checking for asm/errno.h" >&5
++echo $ECHO_N "checking for asm/errno.h... $ECHO_C" >&6
++if test "${ac_cv_header_asm_errno_h+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++fi
++echo "$as_me:$LINENO: result: $ac_cv_header_asm_errno_h" >&5
++echo "${ECHO_T}$ac_cv_header_asm_errno_h" >&6
+ else
+- cat > conftest.$ac_ext <<EOF
+-#line 5458 "configure"
+-#include "confdefs.h"
++ # Is the header compilable?
++echo "$as_me:$LINENO: checking asm/errno.h usability" >&5
++echo $ECHO_N "checking asm/errno.h usability... $ECHO_C" >&6
++cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++$ac_includes_default
+ #include <asm/errno.h>
+-EOF
+-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+-{ (eval echo configure:5463: \"$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"
++_ACEOF
++rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest.$ac_objext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ ac_header_compiler=yes
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_header_compiler=no
++fi
++rm -f conftest.$ac_objext conftest.$ac_ext
++echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
++echo "${ECHO_T}$ac_header_compiler" >&6
++
++# Is the header present?
++echo "$as_me:$LINENO: checking asm/errno.h presence" >&5
++echo $ECHO_N "checking asm/errno.h presence... $ECHO_C" >&6
++cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++#include <asm/errno.h>
++_ACEOF
++if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
++ (eval $ac_cpp conftest.$ac_ext) 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); } >/dev/null; then
++ if test -s conftest.err; then
++ ac_cpp_err=$ac_c_preproc_warn_flag
++ else
++ ac_cpp_err=
++ fi
+ 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"
++ ac_cpp_err=yes
+ fi
+-rm -f conftest*
++if test -z "$ac_cpp_err"; then
++ ac_header_preproc=yes
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ ac_header_preproc=no
++fi
++rm -f conftest.err conftest.$ac_ext
++echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
++echo "${ECHO_T}$ac_header_preproc" >&6
++
++# So? What about this header?
++case $ac_header_compiler:$ac_header_preproc in
++ yes:no )
++ { echo "$as_me:$LINENO: WARNING: asm/errno.h: accepted by the compiler, rejected by the preprocessor!" >&5
++echo "$as_me: WARNING: asm/errno.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
++ { echo "$as_me:$LINENO: WARNING: asm/errno.h: proceeding with the preprocessor's result" >&5
++echo "$as_me: WARNING: asm/errno.h: proceeding with the preprocessor's result" >&2;}
++ (
++ cat <<\_ASBOX
++## ------------------------------------ ##
++## Report this to bug-autoconf@gnu.org. ##
++## ------------------------------------ ##
++_ASBOX
++ ) |
++ sed "s/^/$as_me: WARNING: /" >&2
++ ;;
++ no:yes )
++ { echo "$as_me:$LINENO: WARNING: asm/errno.h: present but cannot be compiled" >&5
++echo "$as_me: WARNING: asm/errno.h: present but cannot be compiled" >&2;}
++ { echo "$as_me:$LINENO: WARNING: asm/errno.h: check for missing prerequisite headers?" >&5
++echo "$as_me: WARNING: asm/errno.h: check for missing prerequisite headers?" >&2;}
++ { echo "$as_me:$LINENO: WARNING: asm/errno.h: proceeding with the preprocessor's result" >&5
++echo "$as_me: WARNING: asm/errno.h: proceeding with the preprocessor's result" >&2;}
++ (
++ cat <<\_ASBOX
++## ------------------------------------ ##
++## Report this to bug-autoconf@gnu.org. ##
++## ------------------------------------ ##
++_ASBOX
++ ) |
++ sed "s/^/$as_me: WARNING: /" >&2
++ ;;
++esac
++echo "$as_me:$LINENO: checking for asm/errno.h" >&5
++echo $ECHO_N "checking for asm/errno.h... $ECHO_C" >&6
++if test "${ac_cv_header_asm_errno_h+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ ac_cv_header_asm_errno_h=$ac_header_preproc
++fi
++echo "$as_me:$LINENO: result: $ac_cv_header_asm_errno_h" >&5
++echo "${ECHO_T}$ac_cv_header_asm_errno_h" >&6
++
+ fi
+-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+- echo "$ac_t""yes" 1>&6
++if test $ac_cv_header_asm_errno_h = yes; then
+ :
+ else
+- echo "$ac_t""no" 1>&6
+-{ echo "configure: error: *** Unable to find asm/errno.h!!!" 1>&2; exit 1; }
++ { { echo "$as_me:$LINENO: error: *** Unable to find asm/errno.h!!!" >&5
++echo "$as_me: error: *** Unable to find asm/errno.h!!!" >&2;}
++ { (exit 1); exit 1; }; }
+
+ fi
+
+
+-ac_safe=`echo "linux/atmsap.h" | sed 'y%./+-%__p_%'`
+-echo $ac_n "checking for linux/atmsap.h""... $ac_c" 1>&6
+-echo "configure:5489: checking for linux/atmsap.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 5494 "configure"
+-#include "confdefs.h"
++
++if test "${ac_cv_header_linux_atmsap_h+set}" = set; then
++ echo "$as_me:$LINENO: checking for linux/atmsap.h" >&5
++echo $ECHO_N "checking for linux/atmsap.h... $ECHO_C" >&6
++if test "${ac_cv_header_linux_atmsap_h+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++fi
++echo "$as_me:$LINENO: result: $ac_cv_header_linux_atmsap_h" >&5
++echo "${ECHO_T}$ac_cv_header_linux_atmsap_h" >&6
++else
++ # Is the header compilable?
++echo "$as_me:$LINENO: checking linux/atmsap.h usability" >&5
++echo $ECHO_N "checking linux/atmsap.h usability... $ECHO_C" >&6
++cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++$ac_includes_default
+ #include <linux/atmsap.h>
+-EOF
+-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+-{ (eval echo configure:5499: \"$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"
++_ACEOF
++rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest.$ac_objext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ ac_header_compiler=yes
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_header_compiler=no
++fi
++rm -f conftest.$ac_objext conftest.$ac_ext
++echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
++echo "${ECHO_T}$ac_header_compiler" >&6
++
++# Is the header present?
++echo "$as_me:$LINENO: checking linux/atmsap.h presence" >&5
++echo $ECHO_N "checking linux/atmsap.h presence... $ECHO_C" >&6
++cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++#include <linux/atmsap.h>
++_ACEOF
++if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
++ (eval $ac_cpp conftest.$ac_ext) 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); } >/dev/null; then
++ if test -s conftest.err; then
++ ac_cpp_err=$ac_c_preproc_warn_flag
++ else
++ ac_cpp_err=
++ fi
+ 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"
++ ac_cpp_err=yes
+ fi
+-rm -f conftest*
++if test -z "$ac_cpp_err"; then
++ ac_header_preproc=yes
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ ac_header_preproc=no
++fi
++rm -f conftest.err conftest.$ac_ext
++echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
++echo "${ECHO_T}$ac_header_preproc" >&6
++
++# So? What about this header?
++case $ac_header_compiler:$ac_header_preproc in
++ yes:no )
++ { echo "$as_me:$LINENO: WARNING: linux/atmsap.h: accepted by the compiler, rejected by the preprocessor!" >&5
++echo "$as_me: WARNING: linux/atmsap.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
++ { echo "$as_me:$LINENO: WARNING: linux/atmsap.h: proceeding with the preprocessor's result" >&5
++echo "$as_me: WARNING: linux/atmsap.h: proceeding with the preprocessor's result" >&2;}
++ (
++ cat <<\_ASBOX
++## ------------------------------------ ##
++## Report this to bug-autoconf@gnu.org. ##
++## ------------------------------------ ##
++_ASBOX
++ ) |
++ sed "s/^/$as_me: WARNING: /" >&2
++ ;;
++ no:yes )
++ { echo "$as_me:$LINENO: WARNING: linux/atmsap.h: present but cannot be compiled" >&5
++echo "$as_me: WARNING: linux/atmsap.h: present but cannot be compiled" >&2;}
++ { echo "$as_me:$LINENO: WARNING: linux/atmsap.h: check for missing prerequisite headers?" >&5
++echo "$as_me: WARNING: linux/atmsap.h: check for missing prerequisite headers?" >&2;}
++ { echo "$as_me:$LINENO: WARNING: linux/atmsap.h: proceeding with the preprocessor's result" >&5
++echo "$as_me: WARNING: linux/atmsap.h: proceeding with the preprocessor's result" >&2;}
++ (
++ cat <<\_ASBOX
++## ------------------------------------ ##
++## Report this to bug-autoconf@gnu.org. ##
++## ------------------------------------ ##
++_ASBOX
++ ) |
++ sed "s/^/$as_me: WARNING: /" >&2
++ ;;
++esac
++echo "$as_me:$LINENO: checking for linux/atmsap.h" >&5
++echo $ECHO_N "checking for linux/atmsap.h... $ECHO_C" >&6
++if test "${ac_cv_header_linux_atmsap_h+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ ac_cv_header_linux_atmsap_h=$ac_header_preproc
+ fi
+-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+- echo "$ac_t""yes" 1>&6
++echo "$as_me:$LINENO: result: $ac_cv_header_linux_atmsap_h" >&5
++echo "${ECHO_T}$ac_cv_header_linux_atmsap_h" >&6
++
++fi
++if test $ac_cv_header_linux_atmsap_h = yes; then
+ :
+ else
+- echo "$ac_t""no" 1>&6
+-{ echo "configure: error: *** Unable to find linux/atmsap.h!!!" 1>&2; exit 1; }
++ { { echo "$as_me:$LINENO: error: *** Unable to find linux/atmsap.h!!!" >&5
++echo "$as_me: error: *** Unable to find linux/atmsap.h!!!" >&2;}
++ { (exit 1); exit 1; }; }
+
+ fi
+
+
+-echo $ac_n "checking for main in -lresolv""... $ac_c" 1>&6
+-echo "configure:5524: checking for main in -lresolv" >&5
+-ac_lib_var=`echo resolv'_'main | sed 'y%./+-%__p_%'`
+-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++
++
++echo "$as_me:$LINENO: checking for main in -lresolv" >&5
++echo $ECHO_N "checking for main in -lresolv... $ECHO_C" >&6
++if test "${ac_cv_lib_resolv_main+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+- ac_save_LIBS="$LIBS"
++ ac_check_lib_save_LIBS=$LIBS
+ LIBS="-lresolv $LIBS"
+-cat > conftest.$ac_ext <<EOF
+-#line 5532 "configure"
+-#include "confdefs.h"
++cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
+
+-int main() {
+-main()
+-; return 0; }
+-EOF
+-if { (eval echo configure:5539: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+- rm -rf conftest*
+- eval "ac_cv_lib_$ac_lib_var=yes"
+-else
+- echo "configure: failed program was:" >&5
+- cat conftest.$ac_ext >&5
+- rm -rf conftest*
+- eval "ac_cv_lib_$ac_lib_var=no"
+-fi
+-rm -f conftest*
+-LIBS="$ac_save_LIBS"
+
+-fi
+-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+- echo "$ac_t""yes" 1>&6
+- ac_tr_lib=HAVE_LIB`echo resolv | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+- cat >> confdefs.h <<EOF
+-#define $ac_tr_lib 1
+-EOF
++int
++main ()
++{
++main ();
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext conftest$ac_exeext
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest$ac_exeext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ ac_cv_lib_resolv_main=yes
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_cv_lib_resolv_main=no
++fi
++rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++echo "$as_me:$LINENO: result: $ac_cv_lib_resolv_main" >&5
++echo "${ECHO_T}$ac_cv_lib_resolv_main" >&6
++if test $ac_cv_lib_resolv_main = yes; then
++ cat >>confdefs.h <<_ACEOF
++#define HAVE_LIBRESOLV 1
++_ACEOF
+
+ LIBS="-lresolv $LIBS"
+
+ else
+- echo "$ac_t""no" 1>&6
+-{ echo "configure: error: *** Unable to find libresolv!!!" 1>&2; exit 1; }
++ { { echo "$as_me:$LINENO: error: *** Unable to find libresolv!!!" >&5
++echo "$as_me: error: *** Unable to find libresolv!!!" >&2;}
++ { (exit 1); exit 1; }; }
+
+ fi
+
+@@ -5571,639 +8342,1417 @@
+ CFLAGS="$INCLUDES $CFLAGS -Wall -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes"
+ YACC="$YACC -d"
+
+-cat >> confdefs.h <<\EOF
++cat >>confdefs.h <<\_ACEOF
+ #define YY_USE_CONST 1
+-EOF
++_ACEOF
+
+
+ atmsigd_conf_dir=` test "x$exec_prefix" = xNONE && exec_prefix=$ac_default_prefix
+ test "x$prefix" = xNONE && prefix=${exec_prefix}
+ eval echo "$sysconfdir"`
+-cat >> confdefs.h <<EOF
++cat >>confdefs.h <<_ACEOF
+ #define ATMSIGD_CONF "$atmsigd_conf_dir/atmsigd.conf"
+-EOF
++_ACEOF
++
+
+
+ # Check whether --with-uni or --without-uni was given.
+ if test "${with_uni+set}" = set; then
+ withval="$with_uni"
+-
++
+ case "$with_uni" in
+- "3.0" ) cat >> confdefs.h <<\EOF
++ "3.0" ) cat >>confdefs.h <<\_ACEOF
+ #define UNI30 1
+-EOF
++_ACEOF
+
+ ;;
+- "3.1" ) cat >> confdefs.h <<\EOF
++ "3.1" ) cat >>confdefs.h <<\_ACEOF
+ #define UNI31 1
+-EOF
++_ACEOF
+
+ ;;
+- "4.0" ) cat >> confdefs.h <<\EOF
++ "4.0" ) cat >>confdefs.h <<\_ACEOF
+ #define UNI40 1
+-EOF
++_ACEOF
+
+ ;;
+ *)
+- cat >> confdefs.h <<\EOF
++ cat >>confdefs.h <<\_ACEOF
+ #define DYNAMIC_UNI 1
+-EOF
++_ACEOF
+
+- echo "configure: warning: *** UNI version not specified correctly. Defaulting to dynamic UNI." 1>&2
++ { echo "$as_me:$LINENO: WARNING: *** UNI version not specified correctly. Defaulting to dynamic UNI." >&5
++echo "$as_me: WARNING: *** UNI version not specified correctly. Defaulting to dynamic UNI." >&2;}
+ esac
+-
++
+ else
+- cat >> confdefs.h <<\EOF
++ cat >>confdefs.h <<\_ACEOF
+ #define DYNAMIC_UNI 1
+-EOF
++_ACEOF
+
+
+-fi
+-
++fi;
+
+ # Check whether --enable-allow_uni30 or --disable-allow_uni30 was given.
+ if test "${enable_allow_uni30+set}" = set; then
+ enableval="$enable_allow_uni30"
+-
++
+ if test "$with_uni" = "3.1" ; then
+- cat >> confdefs.h <<\EOF
++ cat >>confdefs.h <<\_ACEOF
+ #define ALLOW_UNI30 1
+-EOF
++_ACEOF
+
+ else
+- echo "configure: warning: *** Allow UNI 3.0 was not enabled. It is only valid when UNI 3.1 is specified as the default via --with-uni." 1>&2
++ { echo "$as_me:$LINENO: WARNING: *** Allow UNI 3.0 was not enabled. It is only valid when UNI 3.1 is specified as the default via --with-uni." >&5
++echo "$as_me: WARNING: *** Allow UNI 3.0 was not enabled. It is only valid when UNI 3.1 is specified as the default via --with-uni." >&2;}
+ fi
+-
+
+-fi
+
++fi;
+
+ # Check whether --enable-q2963_1 or --disable-q2963_1 was given.
+ if test "${enable_q2963_1+set}" = set; then
+ enableval="$enable_q2963_1"
+-
++
+ if test "$with_uni" = "4.0" ; then
+- cat >> confdefs.h <<\EOF
++ cat >>confdefs.h <<\_ACEOF
+ #define Q2963_1 1
+-EOF
++_ACEOF
+
+ else
+- echo "configure: warning: *** Q.2963.1 was not enabled. It is only valid when UNI 4.0 is specified as the default via --with-uni." 1>&2
++ { echo "$as_me:$LINENO: WARNING: *** Q.2963.1 was not enabled. It is only valid when UNI 4.0 is specified as the default via --with-uni." >&5
++echo "$as_me: WARNING: *** Q.2963.1 was not enabled. It is only valid when UNI 4.0 is specified as the default via --with-uni." >&2;}
+ fi
+-
+
+-fi
+
++fi;
+
+ # Check whether --enable-cisco or --disable-cisco was given.
+ if test "${enable_cisco+set}" = set; then
+ enableval="$enable_cisco"
+- cat >> confdefs.h <<\EOF
++ cat >>confdefs.h <<\_ACEOF
+ #define CISCO 1
+-EOF
++_ACEOF
+
+
+-fi
+-
++fi;
+
+ # Check whether --enable-thomflex or --disable-thomflex was given.
+ if test "${enable_thomflex+set}" = set; then
+ enableval="$enable_thomflex"
+- cat >> confdefs.h <<\EOF
++ cat >>confdefs.h <<\_ACEOF
+ #define THOMFLEX 1
+-EOF
+-
++_ACEOF
+
+-fi
+
++fi;
+
+-cat >> confdefs.h <<\EOF
++cat >>confdefs.h <<\_ACEOF
+ #define BROKEN_POLL 1
+-EOF
++_ACEOF
+
+
+ # Check whether --enable-mpoa_1_1 or --disable-mpoa_1_1 was given.
+ if test "${enable_mpoa_1_1+set}" = set; then
+ enableval="$enable_mpoa_1_1"
+- cat >> confdefs.h <<\EOF
++ cat >>confdefs.h <<\_ACEOF
+ #define MPOA_1_1 1
+-EOF
+-
++_ACEOF
+
+-fi
+
++fi;
+
+ # Check whether --enable-mpr or --disable-mpr was given.
+ if test "${enable_mpr+set}" = set; then
+ enableval="$enable_mpr"
+-
++
+ case "$enable_mpr" in
+ "" | y | ye | yes | Y | YE | YES )
+- echo $ac_n "checking for main in -lmpr""... $ac_c" 1>&6
+-echo "configure:5704: checking for main in -lmpr" >&5
+-ac_lib_var=`echo mpr'_'main | sed 'y%./+-%__p_%'`
+-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+- echo $ac_n "(cached) $ac_c" 1>&6
++
++echo "$as_me:$LINENO: checking for main in -lmpr" >&5
++echo $ECHO_N "checking for main in -lmpr... $ECHO_C" >&6
++if test "${ac_cv_lib_mpr_main+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+- ac_save_LIBS="$LIBS"
++ ac_check_lib_save_LIBS=$LIBS
+ LIBS="-lmpr $LIBS"
+-cat > conftest.$ac_ext <<EOF
+-#line 5712 "configure"
+-#include "confdefs.h"
++cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
+
+-int main() {
+-main()
+-; return 0; }
+-EOF
+-if { (eval echo configure:5719: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+- rm -rf conftest*
+- eval "ac_cv_lib_$ac_lib_var=yes"
+-else
+- echo "configure: failed program was:" >&5
+- cat conftest.$ac_ext >&5
+- rm -rf conftest*
+- eval "ac_cv_lib_$ac_lib_var=no"
+-fi
+-rm -f conftest*
+-LIBS="$ac_save_LIBS"
+
+-fi
+-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+- echo "$ac_t""yes" 1>&6
+- ac_tr_lib=HAVE_LIB`echo mpr | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+- cat >> confdefs.h <<EOF
+-#define $ac_tr_lib 1
+-EOF
++int
++main ()
++{
++main ();
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext conftest$ac_exeext
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest$ac_exeext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ ac_cv_lib_mpr_main=yes
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_cv_lib_mpr_main=no
++fi
++rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++echo "$as_me:$LINENO: result: $ac_cv_lib_mpr_main" >&5
++echo "${ECHO_T}$ac_cv_lib_mpr_main" >&6
++if test $ac_cv_lib_mpr_main = yes; then
++ cat >>confdefs.h <<_ACEOF
++#define HAVE_LIBMPR 1
++_ACEOF
+
+ LIBS="-lmpr $LIBS"
+
+ else
+- echo "$ac_t""no" 1>&6
+
+- echo "configure: warning: *** Could not find libmpr! Is MPR installed?" 1>&2
+-
+-
++ { echo "$as_me:$LINENO: WARNING: *** Could not find libmpr! Is MPR installed?" >&5
++echo "$as_me: WARNING: *** Could not find libmpr! Is MPR installed?" >&2;}
++
++
+ fi
+
+ ;;
+ esac
+-
+
+-fi
+
++fi;
+
+
+-trap '' 1 2 15
+-cat > confcache <<\EOF
++ ac_config_files="$ac_config_files Makefile doc/Makefile m4/Makefile src/Makefile src/include/Makefile src/lib/Makefile src/test/Makefile src/debug/Makefile src/qgen/Makefile src/saal/Makefile src/sigd/Makefile src/maint/Makefile src/arpd/Makefile src/ilmid/Makefile src/ilmid/asn1/Makefile src/man/Makefile src/led/Makefile src/lane/Makefile src/mpoad/Makefile src/switch/Makefile src/switch/debug/Makefile src/switch/tcp/Makefile src/config/Makefile src/config/init-redhat/Makefile src/extra/Makefile src/extra/linux-atm.spec src/extra/ANS/Makefile"
++cat >confcache <<\_ACEOF
+ # 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.
++# scripts and configure runs, see configure's option --config-cache.
++# 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.
++# config.status only pays attention to the cache file if you give it
++# the --recheck option to rerun configure.
+ #
+-EOF
++# `ac_cv_env_foo' variables (set or unset) will be overridden when
++# loading this file, other *unset* `ac_cv_foo' will be assigned the
++# following values.
++
++_ACEOF
++
+ # 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
++{
++ (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 \
++ "s/'/'\\\\''/g;
++ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
++ ;;
++ *)
++ # `set' quotes correctly as required by POSIX, so do not add quotes.
++ sed -n \
++ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
++ ;;
++ esac;
++} |
++ sed '
++ t clear
++ : clear
++ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
++ t end
++ /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
++ : end' >>confcache
++if diff $cache_file confcache >/dev/null 2>&1; then :; else
+ if test -w $cache_file; then
+- echo "updating cache $cache_file"
+- cat confcache > $cache_file
++ test "x$cache_file" != "x/dev/null" && 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.
++# VPATH may cause trouble with some makes, so we remove $(srcdir),
++# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
++# trailing colons and then remove the whole line if VPATH becomes empty
++# (actually we leave an empty line to preserve line numbers).
+ if test "x$srcdir" = x.; then
+- ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
++ ac_vpsub='/^[ ]*VPATH[ ]*=/{
++s/:*\$(srcdir):*/:/;
++s/:*\${srcdir}:*/:/;
++s/:*@srcdir@:*/:/;
++s/^\([^=]*=[ ]*\):*/\1/;
++s/:*$//;
++s/^[^=]*=[ ]*$//;
++}'
+ 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}
++ac_libobjs=
++ac_ltlibobjs=
++for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
++ # 1. Remove the extension, and $U if already installed.
++ ac_i=`echo "$ac_i" |
++ sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
++ # 2. Add them.
++ ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
++ ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
++done
++LIBOBJS=$ac_libobjs
+
+-echo creating $CONFIG_STATUS
+-rm -f $CONFIG_STATUS
+-cat > $CONFIG_STATUS <<EOF
+-#! /bin/sh
+-# Generated automatically by configure.
++LTLIBOBJS=$ac_ltlibobjs
++
++
++
++: ${CONFIG_STATUS=./config.status}
++ac_clean_files_save=$ac_clean_files
++ac_clean_files="$ac_clean_files $CONFIG_STATUS"
++{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
++echo "$as_me: creating $CONFIG_STATUS" >&6;}
++cat >$CONFIG_STATUS <<_ACEOF
++#! $SHELL
++# Generated by $as_me.
+ # 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.
++# configure, is in config.log if it exists.
+
+-ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+-for ac_option
++debug=false
++ac_cs_recheck=false
++ac_cs_silent=false
++SHELL=\${CONFIG_SHELL-$SHELL}
++_ACEOF
++
++cat >>$CONFIG_STATUS <<\_ACEOF
++## --------------------- ##
++## M4sh Initialization. ##
++## --------------------- ##
++
++# Be Bourne compatible
++if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
++ emulate sh
++ NULLCMD=:
++ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
++ # is contrary to our usage. Disable this feature.
++ alias -g '${1+"$@"}'='"$@"'
++elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
++ set -o posix
++fi
++
++# Support unset when possible.
++if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
++ as_unset=unset
++else
++ as_unset=false
++fi
++
++
++# Work around bugs in pre-3.0 UWIN ksh.
++$as_unset ENV MAIL MAILPATH
++PS1='$ '
++PS2='> '
++PS4='+ '
++
++# NLS nuisances.
++for as_var in \
++ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
++ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
++ LC_TELEPHONE LC_TIME
+ 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 ;;
++ if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then
++ eval $as_var=C; export $as_var
++ else
++ $as_unset $as_var
++ fi
++done
++
++# Required to use basename.
++if expr a : '\(a\)' >/dev/null 2>&1; then
++ as_expr=expr
++else
++ as_expr=false
++fi
++
++if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
++ as_basename=basename
++else
++ as_basename=false
++fi
++
++
++# Name of the executable.
++as_me=`$as_basename "$0" ||
++$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
++ X"$0" : 'X\(//\)$' \| \
++ X"$0" : 'X\(/\)$' \| \
++ . : '\(.\)' 2>/dev/null ||
++echo X/"$0" |
++ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
++ /^X\/\(\/\/\)$/{ s//\1/; q; }
++ /^X\/\(\/\).*/{ s//\1/; q; }
++ s/.*/./; q'`
++
++
++# PATH needs CR, and LINENO needs CR and PATH.
++# Avoid depending upon Character Ranges.
++as_cr_letters='abcdefghijklmnopqrstuvwxyz'
++as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
++as_cr_Letters=$as_cr_letters$as_cr_LETTERS
++as_cr_digits='0123456789'
++as_cr_alnum=$as_cr_Letters$as_cr_digits
++
++# The user is always right.
++if test "${PATH_SEPARATOR+set}" != set; then
++ echo "#! /bin/sh" >conf$$.sh
++ echo "exit 0" >>conf$$.sh
++ chmod +x conf$$.sh
++ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
++ PATH_SEPARATOR=';'
++ else
++ PATH_SEPARATOR=:
++ fi
++ rm -f conf$$.sh
++fi
++
++
++ as_lineno_1=$LINENO
++ as_lineno_2=$LINENO
++ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
++ test "x$as_lineno_1" != "x$as_lineno_2" &&
++ test "x$as_lineno_3" = "x$as_lineno_2" || {
++ # Find who we are. Look in the path if we contain no path at all
++ # relative or not.
++ case $0 in
++ *[\\/]* ) as_myself=$0 ;;
++ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++ IFS=$as_save_IFS
++ test -z "$as_dir" && as_dir=.
++ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
++done
++
++ ;;
+ esac
++ # We did not find ourselves, most probably we were run as `sh COMMAND'
++ # in which case we are not to be found in the path.
++ if test "x$as_myself" = x; then
++ as_myself=$0
++ fi
++ if test ! -f "$as_myself"; then
++ { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
++echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
++ { (exit 1); exit 1; }; }
++ fi
++ case $CONFIG_SHELL in
++ '')
++ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
++do
++ IFS=$as_save_IFS
++ test -z "$as_dir" && as_dir=.
++ for as_base in sh bash ksh sh5; do
++ case $as_dir in
++ /*)
++ if ("$as_dir/$as_base" -c '
++ as_lineno_1=$LINENO
++ as_lineno_2=$LINENO
++ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
++ test "x$as_lineno_1" != "x$as_lineno_2" &&
++ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
++ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
++ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
++ CONFIG_SHELL=$as_dir/$as_base
++ export CONFIG_SHELL
++ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
++ fi;;
++ esac
++ done
+ done
++;;
++ esac
+
+-ac_given_srcdir=$srcdir
+-ac_given_INSTALL="$INSTALL"
+-
+-trap 'rm -fr `echo "Makefile \
+- doc/Makefile \
+- m4/Makefile \
+- src/Makefile \
+- src/include/Makefile \
+- src/lib/Makefile \
+- src/test/Makefile \
+- src/debug/Makefile \
+- src/qgen/Makefile \
+- src/saal/Makefile \
+- src/sigd/Makefile \
+- src/maint/Makefile \
+- src/arpd/Makefile \
+- src/ilmid/Makefile \
+- src/ilmid/asn1/Makefile \
+- src/man/Makefile \
+- src/led/Makefile \
+- src/lane/Makefile \
+- src/mpoad/Makefile \
+- src/switch/Makefile \
+- src/switch/debug/Makefile \
+- src/switch/tcp/Makefile \
+- src/config/Makefile \
+- src/config/init-redhat/Makefile \
+- src/extra/Makefile \
+- src/extra/linux-atm.spec \
+- src/extra/ANS/Makefile
+- config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+-EOF
+-cat >> $CONFIG_STATUS <<EOF
++ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
++ # uniformly replaced by the line number. The first 'sed' inserts a
++ # line-number line before each line; the second 'sed' does the real
++ # work. The second script uses 'N' to pair each line-number line
++ # with the numbered line, and appends trailing '-' during
++ # substitution so that $LINENO is not a special case at line end.
++ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
++ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
++ sed '=' <$as_myself |
++ sed '
++ N
++ s,$,-,
++ : loop
++ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
++ t loop
++ s,-$,,
++ s,^['$as_cr_digits']*\n,,
++ ' >$as_me.lineno &&
++ chmod +x $as_me.lineno ||
++ { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
++echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
++ { (exit 1); exit 1; }; }
++
++ # Don't try to exec as it changes $[0], causing all sort of problems
++ # (the dirname of $[0] is not the place where we might find the
++ # original and so on. Autoconf is especially sensible to this).
++ . ./$as_me.lineno
++ # Exit status is that of the last command.
++ exit
++}
+
+-# 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%@host@%$host%g
+-s%@host_alias@%$host_alias%g
+-s%@host_cpu@%$host_cpu%g
+-s%@host_vendor@%$host_vendor%g
+-s%@host_os@%$host_os%g
+-s%@target@%$target%g
+-s%@target_alias@%$target_alias%g
+-s%@target_cpu@%$target_cpu%g
+-s%@target_vendor@%$target_vendor%g
+-s%@target_os@%$target_os%g
+-s%@build@%$build%g
+-s%@build_alias@%$build_alias%g
+-s%@build_cpu@%$build_cpu%g
+-s%@build_vendor@%$build_vendor%g
+-s%@build_os@%$build_os%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%@LIBVER_CURRENT@%$LIBVER_CURRENT%g
+-s%@LIBVER_REVISION@%$LIBVER_REVISION%g
+-s%@LIBVER_AGE@%$LIBVER_AGE%g
+-s%@CC@%$CC%g
+-s%@LEX@%$LEX%g
+-s%@LEXLIB@%$LEXLIB%g
+-s%@CPP@%$CPP%g
+-s%@LEX_OUTPUT_ROOT@%$LEX_OUTPUT_ROOT%g
+-s%@YACC@%$YACC%g
+-s%@LN_S@%$LN_S%g
+-s%@OBJEXT@%$OBJEXT%g
+-s%@EXEEXT@%$EXEEXT%g
+-s%@ECHO@%$ECHO%g
+-s%@RANLIB@%$RANLIB%g
+-s%@STRIP@%$STRIP%g
+-s%@LIBTOOL@%$LIBTOOL%g
+-s%@LIBTOOL_DEPS@%$LIBTOOL_DEPS%g
+-s%@PERL@%$PERL%g
+
+-CEOF
+-EOF
++case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
++ *c*,-n*) ECHO_N= ECHO_C='
++' ECHO_T=' ' ;;
++ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
++ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
++esac
+
+-cat >> $CONFIG_STATUS <<\EOF
++if expr a : '\(a\)' >/dev/null 2>&1; then
++ as_expr=expr
++else
++ as_expr=false
++fi
+
+-# 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
++rm -f conf$$ conf$$.exe conf$$.file
++echo >conf$$.file
++if ln -s conf$$.file conf$$ 2>/dev/null; then
++ # We could just check for DJGPP; but this test a) works b) is more generic
++ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
++ if test -f conf$$.exe; then
++ # Don't use ln at all; we don't have any links
++ as_ln_s='cp -p'
+ 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`
++ as_ln_s='ln -s'
+ fi
++elif ln conf$$.file conf$$ 2>/dev/null; then
++ as_ln_s=ln
++else
++ as_ln_s='cp -p'
++fi
++rm -f conf$$ conf$$.exe conf$$.file
++
++if mkdir -p . 2>/dev/null; then
++ as_mkdir_p=:
++else
++ as_mkdir_p=false
++fi
++
++as_executable_p="test -f"
++
++# Sed expression to map a string onto a valid CPP name.
++as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
++
++# Sed expression to map a string onto a valid variable name.
++as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
++
++
++# IFS
++# We need space, tab and new line, in precisely that order.
++as_nl='
++'
++IFS=" $as_nl"
++
++# CDPATH.
++$as_unset CDPATH
++
++exec 6>&1
++
++# Open the log real soon, to keep \$[0] and so on meaningful, and to
++# report actual input values of CONFIG_FILES etc. instead of their
++# values after options handling. Logging --version etc. is OK.
++exec 5>>config.log
++{
++ echo
++ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
++## Running $as_me. ##
++_ASBOX
++} >&5
++cat >&5 <<_CSEOF
++
++This file was extended by $as_me, which was
++generated by GNU Autoconf 2.57. Invocation command line was
++
++ CONFIG_FILES = $CONFIG_FILES
++ CONFIG_HEADERS = $CONFIG_HEADERS
++ CONFIG_LINKS = $CONFIG_LINKS
++ CONFIG_COMMANDS = $CONFIG_COMMANDS
++ $ $0 $@
++
++_CSEOF
++echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
++echo >&5
++_ACEOF
++
++# Files that config.status was made for.
++if test -n "$ac_config_files"; then
++ echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
++fi
++
++if test -n "$ac_config_headers"; then
++ echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
++fi
++
++if test -n "$ac_config_links"; then
++ echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
++fi
++
++if test -n "$ac_config_commands"; then
++ echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
++fi
++
++cat >>$CONFIG_STATUS <<\_ACEOF
++
++ac_cs_usage="\
++\`$as_me' instantiates files from templates according to the
++current configuration.
++
++Usage: $0 [OPTIONS] [FILE]...
++
++ -h, --help print this help, then exit
++ -V, --version print version number, then exit
++ -q, --quiet do not print progress messages
++ -d, --debug don't remove temporary files
++ --recheck update $as_me by reconfiguring in the same conditions
++ --file=FILE[:TEMPLATE]
++ instantiate the configuration file FILE
++ --header=FILE[:TEMPLATE]
++ instantiate the configuration header FILE
++
++Configuration files:
++$config_files
++
++Configuration headers:
++$config_headers
++
++Configuration commands:
++$config_commands
++
++Report bugs to <bug-autoconf@gnu.org>."
++_ACEOF
++
++cat >>$CONFIG_STATUS <<_ACEOF
++ac_cs_version="\\
++config.status
++configured by $0, generated by GNU Autoconf 2.57,
++ with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
++
++Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
++Free Software Foundation, Inc.
++This config.status script is free software; the Free Software Foundation
++gives unlimited permission to copy, distribute and modify it."
++srcdir=$srcdir
++INSTALL="$INSTALL"
++_ACEOF
++
++cat >>$CONFIG_STATUS <<\_ACEOF
++# If no file are specified by the user, then we need to provide default
++# value. By we need to know if files were specified by the user.
++ac_need_defaults=:
++while test $# != 0
++do
++ case $1 in
++ --*=*)
++ ac_option=`expr "x$1" : 'x\([^=]*\)='`
++ ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
++ ac_shift=:
++ ;;
++ -*)
++ ac_option=$1
++ ac_optarg=$2
++ ac_shift=shift
++ ;;
++ *) # This is not an option, so the user has probably given explicit
++ # arguments.
++ ac_option=$1
++ ac_need_defaults=false;;
++ esac
++
++ case $ac_option in
++ # Handling of the options.
++_ACEOF
++cat >>$CONFIG_STATUS <<\_ACEOF
++ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
++ ac_cs_recheck=: ;;
++ --version | --vers* | -V )
++ echo "$ac_cs_version"; exit 0 ;;
++ --he | --h)
++ # Conflict between --help and --header
++ { { echo "$as_me:$LINENO: error: ambiguous option: $1
++Try \`$0 --help' for more information." >&5
++echo "$as_me: error: ambiguous option: $1
++Try \`$0 --help' for more information." >&2;}
++ { (exit 1); exit 1; }; };;
++ --help | --hel | -h )
++ echo "$ac_cs_usage"; exit 0 ;;
++ --debug | --d* | -d )
++ debug=: ;;
++ --file | --fil | --fi | --f )
++ $ac_shift
++ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
++ ac_need_defaults=false;;
++ --header | --heade | --head | --hea )
++ $ac_shift
++ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
++ ac_need_defaults=false;;
++ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
++ | -silent | --silent | --silen | --sile | --sil | --si | --s)
++ ac_cs_silent=: ;;
++
++ # This is an error.
++ -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
++Try \`$0 --help' for more information." >&5
++echo "$as_me: error: unrecognized option: $1
++Try \`$0 --help' for more information." >&2;}
++ { (exit 1); exit 1; }; } ;;
++
++ *) ac_config_targets="$ac_config_targets $1" ;;
++
++ esac
++ shift
++done
++
++ac_configure_extra_args=
++
++if $ac_cs_silent; then
++ exec 6>/dev/null
++ ac_configure_extra_args="$ac_configure_extra_args --silent"
++fi
++
++_ACEOF
++cat >>$CONFIG_STATUS <<_ACEOF
++if \$ac_cs_recheck; then
++ echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
++ exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
++fi
++
++_ACEOF
++
++cat >>$CONFIG_STATUS <<_ACEOF
++#
++# INIT-COMMANDS section.
++#
++
++
++
++_ACEOF
++
++
++
++cat >>$CONFIG_STATUS <<\_ACEOF
++for ac_config_target in $ac_config_targets
++do
++ case "$ac_config_target" in
++ # Handling of arguments.
++ "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
++ "doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
++ "m4/Makefile" ) CONFIG_FILES="$CONFIG_FILES m4/Makefile" ;;
++ "src/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
++ "src/include/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/include/Makefile" ;;
++ "src/lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/lib/Makefile" ;;
++ "src/test/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/test/Makefile" ;;
++ "src/debug/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/debug/Makefile" ;;
++ "src/qgen/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/qgen/Makefile" ;;
++ "src/saal/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/saal/Makefile" ;;
++ "src/sigd/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/sigd/Makefile" ;;
++ "src/maint/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/maint/Makefile" ;;
++ "src/arpd/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/arpd/Makefile" ;;
++ "src/ilmid/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/ilmid/Makefile" ;;
++ "src/ilmid/asn1/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/ilmid/asn1/Makefile" ;;
++ "src/man/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/man/Makefile" ;;
++ "src/led/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/led/Makefile" ;;
++ "src/lane/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/lane/Makefile" ;;
++ "src/mpoad/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/mpoad/Makefile" ;;
++ "src/switch/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/switch/Makefile" ;;
++ "src/switch/debug/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/switch/debug/Makefile" ;;
++ "src/switch/tcp/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/switch/tcp/Makefile" ;;
++ "src/config/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/config/Makefile" ;;
++ "src/config/init-redhat/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/config/init-redhat/Makefile" ;;
++ "src/extra/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/extra/Makefile" ;;
++ "src/extra/linux-atm.spec" ) CONFIG_FILES="$CONFIG_FILES src/extra/linux-atm.spec" ;;
++ "src/extra/ANS/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/extra/ANS/Makefile" ;;
++ "default-1" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
++ "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
++ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
++echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
++ { (exit 1); exit 1; }; };;
++ esac
+ done
+-if test -z "$ac_sed_cmds"; then
+- ac_sed_cmds=cat
++
++# If the user did not use the arguments to specify the items to instantiate,
++# then the envvar interface is used. Set only those that are not.
++# We use the long form for the default assignment because of an extremely
++# bizarre bug on SunOS 4.1.3.
++if $ac_need_defaults; then
++ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
++ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
++ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+ fi
+-EOF
+
+-cat >> $CONFIG_STATUS <<EOF
++# Have a temporary directory for convenience. Make it in the build tree
++# simply because there is no reason to put it here, and in addition,
++# creating and moving files from /tmp can sometimes cause problems.
++# Create a temporary directory, and hook for its removal unless debugging.
++$debug ||
++{
++ trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
++ trap '{ (exit 1); exit 1; }' 1 2 13 15
++}
+
+-CONFIG_FILES=\${CONFIG_FILES-"Makefile \
+- doc/Makefile \
+- m4/Makefile \
+- src/Makefile \
+- src/include/Makefile \
+- src/lib/Makefile \
+- src/test/Makefile \
+- src/debug/Makefile \
+- src/qgen/Makefile \
+- src/saal/Makefile \
+- src/sigd/Makefile \
+- src/maint/Makefile \
+- src/arpd/Makefile \
+- src/ilmid/Makefile \
+- src/ilmid/asn1/Makefile \
+- src/man/Makefile \
+- src/led/Makefile \
+- src/lane/Makefile \
+- src/mpoad/Makefile \
+- src/switch/Makefile \
+- src/switch/debug/Makefile \
+- src/switch/tcp/Makefile \
+- src/config/Makefile \
+- src/config/init-redhat/Makefile \
+- src/extra/Makefile \
+- src/extra/linux-atm.spec \
+- src/extra/ANS/Makefile
+- "}
+-EOF
+-cat >> $CONFIG_STATUS <<\EOF
+-for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
++# Create a (secure) tmp directory for tmp files.
++
++{
++ tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
++ test -n "$tmp" && test -d "$tmp"
++} ||
++{
++ tmp=./confstat$$-$RANDOM
++ (umask 077 && mkdir $tmp)
++} ||
++{
++ echo "$me: cannot create a temporary directory in ." >&2
++ { (exit 1); exit 1; }
++}
++
++_ACEOF
++
++cat >>$CONFIG_STATUS <<_ACEOF
++
++#
++# CONFIG_FILES section.
++#
++
++# No need to generate the scripts if there are no CONFIG_FILES.
++# This happens for instance when ./config.status config.h
++if test -n "\$CONFIG_FILES"; then
++ # Protect against being on the right side of a sed subst in config.status.
++ sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
++ s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
++s,@SHELL@,$SHELL,;t t
++s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
++s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
++s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
++s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
++s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
++s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
++s,@exec_prefix@,$exec_prefix,;t t
++s,@prefix@,$prefix,;t t
++s,@program_transform_name@,$program_transform_name,;t t
++s,@bindir@,$bindir,;t t
++s,@sbindir@,$sbindir,;t t
++s,@libexecdir@,$libexecdir,;t t
++s,@datadir@,$datadir,;t t
++s,@sysconfdir@,$sysconfdir,;t t
++s,@sharedstatedir@,$sharedstatedir,;t t
++s,@localstatedir@,$localstatedir,;t t
++s,@libdir@,$libdir,;t t
++s,@includedir@,$includedir,;t t
++s,@oldincludedir@,$oldincludedir,;t t
++s,@infodir@,$infodir,;t t
++s,@mandir@,$mandir,;t t
++s,@build_alias@,$build_alias,;t t
++s,@host_alias@,$host_alias,;t t
++s,@target_alias@,$target_alias,;t t
++s,@DEFS@,$DEFS,;t t
++s,@ECHO_C@,$ECHO_C,;t t
++s,@ECHO_N@,$ECHO_N,;t t
++s,@ECHO_T@,$ECHO_T,;t t
++s,@LIBS@,$LIBS,;t t
++s,@build@,$build,;t t
++s,@build_cpu@,$build_cpu,;t t
++s,@build_vendor@,$build_vendor,;t t
++s,@build_os@,$build_os,;t t
++s,@host@,$host,;t t
++s,@host_cpu@,$host_cpu,;t t
++s,@host_vendor@,$host_vendor,;t t
++s,@host_os@,$host_os,;t t
++s,@target@,$target,;t t
++s,@target_cpu@,$target_cpu,;t t
++s,@target_vendor@,$target_vendor,;t t
++s,@target_os@,$target_os,;t t
++s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
++s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
++s,@INSTALL_DATA@,$INSTALL_DATA,;t t
++s,@PACKAGE@,$PACKAGE,;t t
++s,@VERSION@,$VERSION,;t t
++s,@ACLOCAL@,$ACLOCAL,;t t
++s,@AUTOCONF@,$AUTOCONF,;t t
++s,@AUTOMAKE@,$AUTOMAKE,;t t
++s,@AUTOHEADER@,$AUTOHEADER,;t t
++s,@MAKEINFO@,$MAKEINFO,;t t
++s,@SET_MAKE@,$SET_MAKE,;t t
++s,@LIBVER_CURRENT@,$LIBVER_CURRENT,;t t
++s,@LIBVER_REVISION@,$LIBVER_REVISION,;t t
++s,@LIBVER_AGE@,$LIBVER_AGE,;t t
++s,@CC@,$CC,;t t
++s,@CFLAGS@,$CFLAGS,;t t
++s,@LDFLAGS@,$LDFLAGS,;t t
++s,@CPPFLAGS@,$CPPFLAGS,;t t
++s,@ac_ct_CC@,$ac_ct_CC,;t t
++s,@EXEEXT@,$EXEEXT,;t t
++s,@OBJEXT@,$OBJEXT,;t t
++s,@LEX@,$LEX,;t t
++s,@LEXLIB@,$LEXLIB,;t t
++s,@LEX_OUTPUT_ROOT@,$LEX_OUTPUT_ROOT,;t t
++s,@YACC@,$YACC,;t t
++s,@LN_S@,$LN_S,;t t
++s,@ECHO@,$ECHO,;t t
++s,@RANLIB@,$RANLIB,;t t
++s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
++s,@STRIP@,$STRIP,;t t
++s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t
++s,@CPP@,$CPP,;t t
++s,@EGREP@,$EGREP,;t t
++s,@LIBTOOL@,$LIBTOOL,;t t
++s,@LIBTOOL_DEPS@,$LIBTOOL_DEPS,;t t
++s,@PERL@,$PERL,;t t
++s,@LIBOBJS@,$LIBOBJS,;t t
++s,@LTLIBOBJS@,$LTLIBOBJS,;t t
++CEOF
++
++_ACEOF
++
++ cat >>$CONFIG_STATUS <<\_ACEOF
++ # 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_lines=48
++ ac_sed_frag=1 # Number of current file.
++ ac_beg=1 # First line for current file.
++ ac_end=$ac_max_sed_lines # 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" $tmp/subs.sed >$tmp/subs.frag
++ else
++ sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
++ fi
++ if test ! -s $tmp/subs.frag; then
++ ac_more_lines=false
++ else
++ # The purpose of the label and of the branching condition is to
++ # speed up the sed processing (if there are no `@' at all, there
++ # is no need to browse any of the substitutions).
++ # These are the two extra sed commands mentioned above.
++ (echo ':t
++ /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
++ if test -z "$ac_sed_cmds"; then
++ ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
++ else
++ ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
++ fi
++ ac_sed_frag=`expr $ac_sed_frag + 1`
++ ac_beg=$ac_end
++ ac_end=`expr $ac_end + $ac_max_sed_lines`
++ fi
++ done
++ if test -z "$ac_sed_cmds"; then
++ ac_sed_cmds=cat
++ fi
++fi # test -n "$CONFIG_FILES"
++
++_ACEOF
++cat >>$CONFIG_STATUS <<\_ACEOF
++for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+ # 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" ;;
++ case $ac_file in
++ - | *:- | *:-:* ) # input from stdin
++ cat >$tmp/stdin
++ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
++ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
++ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
++ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
++ * ) ac_file_in=$ac_file.in ;;
++ esac
++
++ # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
++ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
++$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
++ X"$ac_file" : 'X\(//\)[^/]' \| \
++ X"$ac_file" : 'X\(//\)$' \| \
++ X"$ac_file" : 'X\(/\)' \| \
++ . : '\(.\)' 2>/dev/null ||
++echo X"$ac_file" |
++ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
++ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
++ /^X\(\/\/\)$/{ s//\1/; q; }
++ /^X\(\/\).*/{ s//\1/; q; }
++ s/.*/./; q'`
++ { if $as_mkdir_p; then
++ mkdir -p "$ac_dir"
++ else
++ as_dir="$ac_dir"
++ as_dirs=
++ while test ! -d "$as_dir"; do
++ as_dirs="$as_dir $as_dirs"
++ as_dir=`(dirname "$as_dir") 2>/dev/null ||
++$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
++ X"$as_dir" : 'X\(//\)[^/]' \| \
++ X"$as_dir" : 'X\(//\)$' \| \
++ X"$as_dir" : 'X\(/\)' \| \
++ . : '\(.\)' 2>/dev/null ||
++echo X"$as_dir" |
++ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
++ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
++ /^X\(\/\/\)$/{ s//\1/; q; }
++ /^X\(\/\).*/{ s//\1/; q; }
++ s/.*/./; q'`
++ done
++ test ! -n "$as_dirs" || mkdir $as_dirs
++ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
++echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
++ { (exit 1); exit 1; }; }; }
++
++ ac_builddir=.
++
++if test "$ac_dir" != .; then
++ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
++ # A "../" for each directory in $ac_dir_suffix.
++ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
++else
++ ac_dir_suffix= ac_top_builddir=
++fi
++
++case $srcdir in
++ .) # No --srcdir option. We are building in place.
++ ac_srcdir=.
++ if test -z "$ac_top_builddir"; then
++ ac_top_srcdir=.
++ else
++ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
++ fi ;;
++ [\\/]* | ?:[\\/]* ) # Absolute path.
++ ac_srcdir=$srcdir$ac_dir_suffix;
++ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+- srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+- top_srcdir="$ac_dots$ac_given_srcdir" ;;
++ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
++ ac_top_srcdir=$ac_top_builddir$srcdir ;;
++esac
++# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
++# absolute.
++ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
++ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
++ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
++ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
++
++
++ case $INSTALL in
++ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
++ *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+ 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*
++ if test x"$ac_file" != x-; then
++ { echo "$as_me:$LINENO: creating $ac_file" >&5
++echo "$as_me: creating $ac_file" >&6;}
++ rm -f "$ac_file"
++ fi
++ # Let's still pretend it is `configure' which instantiates (i.e., don't
++ # use $as_me), people would be surprised to read:
++ # /* config.h. Generated by config.status. */
++ if test x"$ac_file" = x-; then
++ configure_input=
++ else
++ configure_input="$ac_file. "
++ fi
++ configure_input=$configure_input"Generated from `echo $ac_file_in |
++ sed 's,.*/,,'` by configure."
++
++ # First look for the input files in the build tree, otherwise in the
++ # src tree.
++ ac_file_inputs=`IFS=:
++ for f in $ac_file_in; do
++ case $f in
++ -) echo $tmp/stdin ;;
++ [\\/$]*)
++ # Absolute (can't be DOS-style, as IFS=:)
++ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
++echo "$as_me: error: cannot find input file: $f" >&2;}
++ { (exit 1); exit 1; }; }
++ echo $f;;
++ *) # Relative
++ if test -f "$f"; then
++ # Build tree
++ echo $f
++ elif test -f "$srcdir/$f"; then
++ # Source tree
++ echo $srcdir/$f
++ else
++ # /dev/null tree
++ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
++echo "$as_me: error: cannot find input file: $f" >&2;}
++ { (exit 1); exit 1; }; }
++ fi;;
++ esac
++ done` || { (exit 1); exit 1; }
++_ACEOF
++cat >>$CONFIG_STATUS <<_ACEOF
++ sed "$ac_vpsub
++$extrasub
++_ACEOF
++cat >>$CONFIG_STATUS <<\_ACEOF
++:t
++/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
++s,@configure_input@,$configure_input,;t t
++s,@srcdir@,$ac_srcdir,;t t
++s,@abs_srcdir@,$ac_abs_srcdir,;t t
++s,@top_srcdir@,$ac_top_srcdir,;t t
++s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
++s,@builddir@,$ac_builddir,;t t
++s,@abs_builddir@,$ac_abs_builddir,;t t
++s,@top_builddir@,$ac_top_builddir,;t t
++s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
++s,@INSTALL@,$ac_INSTALL,;t t
++" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
++ rm -f $tmp/stdin
++ if test x"$ac_file" != x-; then
++ mv $tmp/out $ac_file
++ else
++ cat $tmp/out
++ rm -f $tmp/out
++ fi
++
++done
++_ACEOF
++cat >>$CONFIG_STATUS <<\_ACEOF
++
++#
++# CONFIG_HEADER section.
++#
+
+ # 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_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)'
++ac_dB='[ ].*$,\1#\2'
++ac_dC=' '
++ac_dD=',;t'
++# ac_u turns "#undef NAME" without 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'
++ac_uD=',;t'
+
+-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
++for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+ # 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" ;;
++ case $ac_file in
++ - | *:- | *:-:* ) # input from stdin
++ cat >$tmp/stdin
++ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
++ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
++ *:* ) 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
++ test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
++echo "$as_me: creating $ac_file" >&6;}
+
+-# 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
++ # First look for the input files in the build tree, otherwise in the
++ # src tree.
++ ac_file_inputs=`IFS=:
++ for f in $ac_file_in; do
++ case $f in
++ -) echo $tmp/stdin ;;
++ [\\/$]*)
++ # Absolute (can't be DOS-style, as IFS=:)
++ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
++echo "$as_me: error: cannot find input file: $f" >&2;}
++ { (exit 1); exit 1; }; }
++ echo $f;;
++ *) # Relative
++ if test -f "$f"; then
++ # Build tree
++ echo $f
++ elif test -f "$srcdir/$f"; then
++ # Source tree
++ echo $srcdir/$f
++ else
++ # /dev/null tree
++ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
++echo "$as_me: error: cannot find input file: $f" >&2;}
++ { (exit 1); exit 1; }; }
++ fi;;
++ esac
++ done` || { (exit 1); exit 1; }
++ # Remove the trailing spaces.
++ sed 's/[ ]*$//' $ac_file_inputs >$tmp/in
++
++_ACEOF
++
++# Transform confdefs.h into two sed scripts, `conftest.defines' and
++# `conftest.undefs', that substitutes the proper values into
++# config.h.in to produce config.h. The first handles `#define'
++# templates, and the second `#undef' templates.
++# 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.defines conftest.undefs
++# Using a here document instead of a string reduces the quoting nightmare.
++# Putting comments in sed scripts is not portable.
++#
++# `end' is used to avoid that the second main sed command (meant for
++# 0-ary CPP macros) applies to n-ary macro definitions.
++# See the Autoconf documentation for `clear'.
++cat >confdef2sed.sed <<\_ACEOF
++s/[\\&,]/\\&/g
++s,[\\$`],\\&,g
++t clear
++: clear
++s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
++t end
++s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
++: end
++_ACEOF
++# If some macros were called several times there might be several times
++# the same #defines, which is useless. Nevertheless, we may not want to
++# sort them, since we want the *last* AC-DEFINE to be honored.
++uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
++sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
++rm -f confdef2sed.sed
+
+ # 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.
+-
++cat >>conftest.undefs <<\_ACEOF
++s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
++_ACEOF
++
++# Break up conftest.defines because some shells have a limit on the size
++# of here documents, and old seds have small limits too (100 cmds).
++echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
++echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
++echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
++echo ' :' >>$CONFIG_STATUS
++rm -f conftest.tail
++while grep . conftest.defines >/dev/null
++do
++ # Write a limited-size here document to $tmp/defines.sed.
++ echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
++ # Speed up: don't consider the non `#define' lines.
++ echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS
++ # Work around the forget-to-reset-the-flag bug.
++ echo 't clr' >>$CONFIG_STATUS
++ echo ': clr' >>$CONFIG_STATUS
++ sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
++ echo 'CEOF
++ sed -f $tmp/defines.sed $tmp/in >$tmp/out
++ rm -f $tmp/in
++ mv $tmp/out $tmp/in
++' >>$CONFIG_STATUS
++ sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
++ rm -f conftest.defines
++ mv conftest.tail conftest.defines
++done
++rm -f conftest.defines
++echo ' fi # grep' >>$CONFIG_STATUS
++echo >>$CONFIG_STATUS
++
++# Break up conftest.undefs because some shells have a limit on the size
++# of here documents, and old seds have small limits too (100 cmds).
++echo ' # Handle all the #undef templates' >>$CONFIG_STATUS
+ rm -f conftest.tail
+-while :
++while grep . conftest.undefs >/dev/null
+ 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
++ # Write a limited-size here document to $tmp/undefs.sed.
++ echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
++ # Speed up: don't consider the non `#undef'
++ echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS
++ # Work around the forget-to-reset-the-flag bug.
++ echo 't clr' >>$CONFIG_STATUS
++ echo ': clr' >>$CONFIG_STATUS
++ sed ${ac_max_here_lines}q conftest.undefs >>$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"
++ sed -f $tmp/undefs.sed $tmp/in >$tmp/out
++ rm -f $tmp/in
++ mv $tmp/out $tmp/in
++' >>$CONFIG_STATUS
++ sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
++ rm -f conftest.undefs
++ mv conftest.tail conftest.undefs
++done
++rm -f conftest.undefs
++
++cat >>$CONFIG_STATUS <<\_ACEOF
++ # Let's still pretend it is `configure' which instantiates (i.e., don't
++ # use $as_me), people would be surprised to read:
++ # /* config.h. Generated by config.status. */
++ if test x"$ac_file" = x-; then
++ echo "/* Generated by configure. */" >$tmp/config.h
++ else
++ echo "/* $ac_file. Generated by configure. */" >$tmp/config.h
++ fi
++ cat $tmp/in >>$tmp/config.h
++ rm -f $tmp/in
++ if test x"$ac_file" != x-; then
++ if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
++ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
++echo "$as_me: $ac_file is unchanged" >&6;}
++ else
++ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
++$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
++ X"$ac_file" : 'X\(//\)[^/]' \| \
++ X"$ac_file" : 'X\(//\)$' \| \
++ X"$ac_file" : 'X\(/\)' \| \
++ . : '\(.\)' 2>/dev/null ||
++echo X"$ac_file" |
++ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
++ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
++ /^X\(\/\/\)$/{ s//\1/; q; }
++ /^X\(\/\).*/{ s//\1/; q; }
++ s/.*/./; q'`
++ { if $as_mkdir_p; then
++ mkdir -p "$ac_dir"
++ else
++ as_dir="$ac_dir"
++ as_dirs=
++ while test ! -d "$as_dir"; do
++ as_dirs="$as_dir $as_dirs"
++ as_dir=`(dirname "$as_dir") 2>/dev/null ||
++$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
++ X"$as_dir" : 'X\(//\)[^/]' \| \
++ X"$as_dir" : 'X\(//\)$' \| \
++ X"$as_dir" : 'X\(/\)' \| \
++ . : '\(.\)' 2>/dev/null ||
++echo X"$as_dir" |
++ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
++ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
++ /^X\(\/\/\)$/{ s//\1/; q; }
++ /^X\(\/\).*/{ s//\1/; q; }
++ s/.*/./; q'`
++ done
++ test ! -n "$as_dirs" || mkdir $as_dirs
++ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
++echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
++ { (exit 1); exit 1; }; }; }
++
++ rm -f $ac_file
++ mv $tmp/config.h $ac_file
+ fi
+- rm -f $ac_file
+- mv conftest.h $ac_file
++ else
++ cat $tmp/config.h
++ rm -f $tmp/config.h
+ fi
+-fi; done
++done
++_ACEOF
++cat >>$CONFIG_STATUS <<\_ACEOF
+
+-EOF
+-cat >> $CONFIG_STATUS <<EOF
++#
++# CONFIG_COMMANDS section.
++#
++for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
++ ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
++ ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
++ ac_dir=`(dirname "$ac_dest") 2>/dev/null ||
++$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
++ X"$ac_dest" : 'X\(//\)[^/]' \| \
++ X"$ac_dest" : 'X\(//\)$' \| \
++ X"$ac_dest" : 'X\(/\)' \| \
++ . : '\(.\)' 2>/dev/null ||
++echo X"$ac_dest" |
++ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
++ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
++ /^X\(\/\/\)$/{ s//\1/; q; }
++ /^X\(\/\).*/{ s//\1/; q; }
++ s/.*/./; q'`
++ ac_builddir=.
++
++if test "$ac_dir" != .; then
++ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
++ # A "../" for each directory in $ac_dir_suffix.
++ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
++else
++ ac_dir_suffix= ac_top_builddir=
++fi
++
++case $srcdir in
++ .) # No --srcdir option. We are building in place.
++ ac_srcdir=.
++ if test -z "$ac_top_builddir"; then
++ ac_top_srcdir=.
++ else
++ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
++ fi ;;
++ [\\/]* | ?:[\\/]* ) # Absolute path.
++ ac_srcdir=$srcdir$ac_dir_suffix;
++ ac_top_srcdir=$srcdir ;;
++ *) # Relative path.
++ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
++ ac_top_srcdir=$ac_top_builddir$srcdir ;;
++esac
++# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
++# absolute.
++ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
++ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
++ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
++ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+
+
+-EOF
+-cat >> $CONFIG_STATUS <<\EOF
+-test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h
++ { echo "$as_me:$LINENO: executing $ac_dest commands" >&5
++echo "$as_me: executing $ac_dest commands" >&6;}
++ case $ac_dest in
++ default-1 ) test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h ;;
++ esac
++done
++_ACEOF
+
+-exit 0
+-EOF
++cat >>$CONFIG_STATUS <<\_ACEOF
++
++{ (exit 0); exit 0; }
++_ACEOF
+ chmod +x $CONFIG_STATUS
+-rm -fr confdefs* $ac_clean_files
+-test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
++ac_clean_files=$ac_clean_files_save
++
++
++# configure is writing to config.log, and then calls config.status.
++# config.status does its own redirection, appending to config.log.
++# Unfortunately, on DOS this fails, as config.log is still kept open
++# by configure, so config.status won't be able to write to it; its
++# output is simply discarded. So we exec the FD to /dev/null,
++# effectively closing config.log, so it can be properly (re)opened and
++# appended to by config.status. When coming back to configure, we
++# need to make the FD available again.
++if test "$no_create" != yes; then
++ ac_cs_success=:
++ ac_config_status_args=
++ test "$silent" = yes &&
++ ac_config_status_args="$ac_config_status_args --quiet"
++ exec 5>/dev/null
++ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
++ exec 5>>config.log
++ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
++ # would make configure fail if this is the last instruction.
++ $ac_cs_success || { (exit 1); exit 1; }
++fi
+
+
+--- linux-atm-2.4.1.orig/ltmain.sh
++++ linux-atm-2.4.1/ltmain.sh
+@@ -49,14 +49,14 @@
+ fi
+
+ # The name of this program.
+-progname=`$echo "$0" | sed 's%^.*/%%'`
++progname=`$echo "$0" | ${SED} 's%^.*/%%'`
+ modename="$progname"
+
+ # Constants.
+ PROGRAM=ltmain.sh
+ PACKAGE=libtool
+-VERSION=1.4
+-TIMESTAMP=" (1.920 2001/04/24 23:26:18)"
++VERSION=1.4.3
++TIMESTAMP=" (1.922.2.111 2002/10/23 02:54:36)"
+
+ default_mode=
+ help="Try \`$progname --help' for more information."
+@@ -67,10 +67,19 @@
+
+ # Sed substitution that helps us do robust quoting. It backslashifies
+ # metacharacters that are still active within double-quoted strings.
+-Xsed='sed -e 1s/^X//'
++Xsed="${SED}"' -e 1s/^X//'
+ sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+-SP2NL='tr \040 \012'
+-NL2SP='tr \015\012 \040\040'
++# test EBCDIC or ASCII
++case `echo A|od -x` in
++ *[Cc]1*) # EBCDIC based system
++ SP2NL="tr '\100' '\n'"
++ NL2SP="tr '\r\n' '\100\100'"
++ ;;
++ *) # Assume ASCII based system
++ SP2NL="tr '\040' '\012'"
++ NL2SP="tr '\015\012' '\040\040'"
++ ;;
++esac
+
+ # NLS nuisances.
+ # Only set LANG and LC_ALL to C if already set.
+@@ -84,6 +93,9 @@
+ save_LANG="$LANG"; LANG=C; export LANG
+ fi
+
++# Make sure IFS has a sensible default
++: ${IFS=" "}
++
+ if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+ echo "$modename: not configured to build any kind of library" 1>&2
+ echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+@@ -141,7 +153,7 @@
+ ;;
+
+ --config)
+- sed -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0
++ ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0
+ exit 0
+ ;;
+
+@@ -174,6 +186,8 @@
+ --mode) prevopt="--mode" prev=mode ;;
+ --mode=*) mode="$optarg" ;;
+
++ --preserve-dup-deps) duplicate_deps="yes" ;;
++
+ --quiet | --silent)
+ show=:
+ ;;
+@@ -202,12 +216,17 @@
+ exit 1
+ fi
+
++# If this variable is set in any of the actions, the command in it
++# will be execed at the end. This prevents here-documents from being
++# left over by shells.
++exec_cmd=
++
+ if test -z "$show_help"; then
+
+ # Infer the operation mode.
+ if test -z "$mode"; then
+ case $nonopt in
+- *cc | *++ | gcc* | *-gcc*)
++ *cc | *++ | gcc* | *-gcc* | g++* | xlc*)
+ mode=link
+ for arg
+ do
+@@ -329,7 +348,7 @@
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
+ lastarg=
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS=','
++ save_ifs="$IFS"; IFS=','
+ for arg in $args; do
+ IFS="$save_ifs"
+
+@@ -615,6 +634,10 @@
+ # Now arrange that obj and lo_libobj become the same file
+ $show "(cd $xdir && $LN_S $baseobj $libobj)"
+ if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then
++ # Unlock the critical section if it was locked
++ if test "$need_locks" != no; then
++ $run $rm "$lockfile"
++ fi
+ exit 0
+ else
+ error=$?
+@@ -745,6 +768,7 @@
+ linker_flags=
+ dllsearchpath=
+ lib_search_path=`pwd`
++ inst_prefix_dir=
+
+ avoid_version=no
+ dlfiles=
+@@ -875,6 +899,11 @@
+ prev=
+ continue
+ ;;
++ inst_prefix)
++ inst_prefix_dir="$arg"
++ prev=
++ continue
++ ;;
+ release)
+ release="-$arg"
+ prev=
+@@ -976,11 +1005,16 @@
+ continue
+ ;;
+
++ -inst-prefix-dir)
++ prev=inst_prefix
++ continue
++ ;;
++
+ # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+ # so, if we see these flags be careful not to treat them like -L
+ -L[A-Z][A-Z]*:*)
+ case $with_gcc/$host in
+- no/*-*-irix*)
++ no/*-*-irix* | no/*-*-nonstopux*)
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ ;;
+@@ -1031,6 +1065,17 @@
+ # These systems don't actually have a C library (as such)
+ test "X$arg" = "X-lc" && continue
+ ;;
++ *-*-openbsd* | *-*-freebsd*)
++ # Do not include libc due to us having libc/libc_r.
++ test "X$arg" = "X-lc" && continue
++ ;;
++ esac
++ elif test "X$arg" = "X-lc_r"; then
++ case $host in
++ *-*-openbsd* | *-*-freebsd*)
++ # Do not include libc_r directly, use -pthread flag.
++ continue
++ ;;
+ esac
+ fi
+ deplibs="$deplibs $arg"
+@@ -1122,7 +1167,7 @@
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
+ arg=
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS=','
++ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+@@ -1140,7 +1185,7 @@
+ -Wl,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'`
+ arg=
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS=','
++ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+@@ -1307,9 +1352,11 @@
+ # Find all interdependent deplibs by searching for libraries
+ # that are linked more than once (e.g. -la -lb -la)
+ for deplib in $deplibs; do
+- case "$libs " in
+- *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+- esac
++ if test "X$duplicate_deps" = "Xyes" ; then
++ case "$libs " in
++ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
++ esac
++ fi
+ libs="$libs $deplib"
+ done
+ deplibs=
+@@ -1343,7 +1390,7 @@
+ ;;
+ esac
+ for pass in $passes; do
+- if test "$linkmode" = prog; then
++ if test $linkmode = prog; then
+ # Determine which files to process
+ case $pass in
+ dlopen)
+@@ -1360,11 +1407,11 @@
+ found=no
+ case $deplib in
+ -l*)
+- if test "$linkmode" = oldlib && test "$linkmode" = obj; then
++ if test $linkmode = oldlib && test $linkmode = obj; then
+ $echo "$modename: warning: \`-l' is ignored for archives/objects: $deplib" 1>&2
+ continue
+ fi
+- if test "$pass" = conv; then
++ if test $pass = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+@@ -1384,7 +1431,7 @@
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+- test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
++ test $linkmode = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+@@ -1393,16 +1440,16 @@
+ case $linkmode in
+ lib)
+ deplibs="$deplib $deplibs"
+- test "$pass" = conv && continue
++ test $pass = conv && continue
+ newdependency_libs="$deplib $newdependency_libs"
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ ;;
+ prog)
+- if test "$pass" = conv; then
++ if test $pass = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+- if test "$pass" = scan; then
++ if test $pass = scan; then
+ deplibs="$deplib $deplibs"
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ else
+@@ -1417,7 +1464,7 @@
+ continue
+ ;; # -L
+ -R*)
+- if test "$pass" = link; then
++ if test $pass = link; then
+ dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+ # Make sure the xrpath contains only unique directories.
+ case "$xrpath " in
+@@ -1430,7 +1477,7 @@
+ ;;
+ *.la) lib="$deplib" ;;
+ *.$libext)
+- if test "$pass" = conv; then
++ if test $pass = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+@@ -1438,10 +1485,12 @@
+ lib)
+ if test "$deplibs_check_method" != pass_all; then
+ echo
+- echo "*** Warning: This library needs some functionality provided by $deplib."
++ echo "*** Warning: Trying to link with static lib archive $deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+- echo "*** shared version of the library, which you do not appear to have."
++ echo "*** shared version of the library, which you do not appear to have"
++ echo "*** because the file extensions .$libext of this argument makes me believe"
++ echo "*** that it is just a static archive that I should not used here."
+ else
+ echo
+ echo "*** Warning: Linking the shared library $output against the"
+@@ -1451,7 +1500,7 @@
+ continue
+ ;;
+ prog)
+- if test "$pass" != link; then
++ if test $pass != link; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+@@ -1462,7 +1511,7 @@
+ esac # linkmode
+ ;; # *.$libext
+ *.lo | *.$objext)
+- if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
++ if test $pass = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+ # If there is no dlopen support or we're linking statically,
+ # we need to preload.
+ newdlprefiles="$newdlprefiles $deplib"
+@@ -1485,7 +1534,7 @@
+ fi
+
+ # Check to see that this really is a libtool archive.
+- if (sed -e '2q' $lib | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
++ if (${SED} -e '2q' $lib | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit 1
+@@ -1512,13 +1561,13 @@
+
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan" ||
+- { test "$linkmode" = oldlib && test "$linkmode" = obj; }; then
++ { test $linkmode = oldlib && test $linkmode = obj; }; then
+ # Add dl[pre]opened files of deplib
+ test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+ test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+ fi
+
+- if test "$pass" = conv; then
++ if test $pass = conv; then
+ # Only check for convenience libraries
+ deplibs="$lib $deplibs"
+ if test -z "$libdir"; then
+@@ -1532,12 +1581,14 @@
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ deplibs="$deplib $deplibs"
+- case "$tmp_libs " in
+- *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+- esac
++ if test "X$duplicate_deps" = "Xyes" ; then
++ case "$tmp_libs " in
++ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
++ esac
++ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+- elif test "$linkmode" != prog && test "$linkmode" != lib; then
++ elif test $linkmode != prog && test $linkmode != lib; then
+ $echo "$modename: \`$lib' is not a convenience library" 1>&2
+ exit 1
+ fi
+@@ -1555,7 +1606,7 @@
+ fi
+
+ # This library was specified with -dlopen.
+- if test "$pass" = dlopen; then
++ if test $pass = dlopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
+ exit 1
+@@ -1604,7 +1655,7 @@
+ name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+
+ # This library was specified with -dlpreopen.
+- if test "$pass" = dlpreopen; then
++ if test $pass = dlpreopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
+ exit 1
+@@ -1623,7 +1674,7 @@
+
+ if test -z "$libdir"; then
+ # Link the convenience library
+- if test "$linkmode" = lib; then
++ if test $linkmode = lib; then
+ deplibs="$dir/$old_library $deplibs"
+ elif test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$dir/$old_library $compile_deplibs"
+@@ -1634,7 +1685,7 @@
+ continue
+ fi
+
+- if test "$linkmode" = prog && test "$pass" != link; then
++ if test $linkmode = prog && test $pass != link; then
+ newlib_search_path="$newlib_search_path $ladir"
+ deplibs="$lib $deplibs"
+
+@@ -1657,9 +1708,11 @@
+ # or/and link against static libraries
+ newdependency_libs="$deplib $newdependency_libs"
+ fi
+- case "$tmp_libs " in
+- *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+- esac
++ if test "X$duplicate_deps" = "Xyes" ; then
++ case "$tmp_libs " in
++ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
++ esac
++ fi
+ tmp_libs="$tmp_libs $deplib"
+ done # for deplib
+ continue
+@@ -1671,7 +1724,7 @@
+ # Link against this shared library
+
+ if test "$linkmode,$pass" = "prog,link" ||
+- { test "$linkmode" = lib && test "$hardcode_into_libs" = yes; }; then
++ { test $linkmode = lib && test $hardcode_into_libs = yes; }; then
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+@@ -1693,7 +1746,7 @@
+ esac
+ ;;
+ esac
+- if test "$linkmode" = prog; then
++ if test $linkmode = prog; then
+ # We need to hardcode the library path
+ if test -n "$shlibpath_var"; then
+ # Make sure the rpath contains only unique directories.
+@@ -1743,14 +1796,14 @@
+
+ # Make a new name for the extract_expsyms_cmds to use
+ soroot="$soname"
+- soname=`echo $soroot | sed -e 's/^.*\///'`
+- newlib="libimp-`echo $soname | sed 's/^lib//;s/\.dll$//'`.a"
++ soname=`echo $soroot | ${SED} -e 's/^.*\///'`
++ newlib="libimp-`echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
+
+ # If the library has no export list, then create one now
+ if test -f "$output_objdir/$soname-def"; then :
+ else
+ $show "extracting exported symbol list from \`$soname'"
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
++ save_ifs="$IFS"; IFS='~'
+ eval cmds=\"$extract_expsyms_cmds\"
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+@@ -1763,7 +1816,7 @@
+ # Create $newlib
+ if test -f "$output_objdir/$newlib"; then :; else
+ $show "generating import library for \`$soname'"
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
++ save_ifs="$IFS"; IFS='~'
+ eval cmds=\"$old_archive_from_expsyms_cmds\"
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+@@ -1777,7 +1830,7 @@
+ linklib=$newlib
+ fi # test -n $old_archive_from_expsyms_cmds
+
+- if test "$linkmode" = prog || test "$mode" != relink; then
++ if test $linkmode = prog || test "$mode" != relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+@@ -1804,6 +1857,14 @@
+ add="$dir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$dir"
++ # Try looking first in the location we're being installed to.
++ if test -n "$inst_prefix_dir"; then
++ case "$libdir" in
++ [\/]*)
++ add_dir="-L$inst_prefix_dir$libdir $add_dir"
++ ;;
++ esac
++ fi
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ add_shlibpath="$dir"
+@@ -1826,7 +1887,7 @@
+ *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+ esac
+ fi
+- if test "$linkmode" = prog; then
++ if test $linkmode = prog; then
+ test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+ test -n "$add" && compile_deplibs="$add $compile_deplibs"
+ else
+@@ -1843,7 +1904,7 @@
+ fi
+ fi
+
+- if test "$linkmode" = prog || test "$mode" = relink; then
++ if test $linkmode = prog || test "$mode" = relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+@@ -1862,10 +1923,18 @@
+ else
+ # We cannot seem to hardcode it, guess we'll fake it.
+ add_dir="-L$libdir"
++ # Try looking first in the location we're being installed to.
++ if test -n "$inst_prefix_dir"; then
++ case "$libdir" in
++ [\/]*)
++ add_dir="-L$inst_prefix_dir$libdir $add_dir"
++ ;;
++ esac
++ fi
+ add="-l$name"
+ fi
+
+- if test "$linkmode" = prog; then
++ if test $linkmode = prog; then
+ test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+ test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+ else
+@@ -1873,7 +1942,7 @@
+ test -n "$add" && deplibs="$add $deplibs"
+ fi
+ fi
+- elif test "$linkmode" = prog; then
++ elif test $linkmode = prog; then
+ if test "$alldeplibs" = yes &&
+ { test "$deplibs_check_method" = pass_all ||
+ { test "$build_libtool_libs" = yes &&
+@@ -1903,25 +1972,26 @@
+ # Just print a warning and add the library to dependency_libs so
+ # that the program can be linked against the static library.
+ echo
+- echo "*** Warning: This library needs some functionality provided by $lib."
++ echo "*** Warning: This system can not link to static lib archive $lib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ if test "$module" = yes; then
+- echo "*** Therefore, libtool will create a static module, that should work "
+- echo "*** as long as the dlopening application is linked with the -dlopen flag."
++ echo "*** But as you try to build a module library, libtool will still create "
++ echo "*** a static module, that should work as long as the dlopening application"
++ echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+ if test -z "$global_symbol_pipe"; then
+- echo
+- echo "*** However, this would only work if libtool was able to extract symbol"
+- echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+- echo "*** not find such a program. So, this module is probably useless."
+- echo "*** \`nm' from GNU binutils and a full rebuild may help."
++ echo
++ echo "*** However, this would only work if libtool was able to extract symbol"
++ echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
++ echo "*** not find such a program. So, this module is probably useless."
++ echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+- build_libtool_libs=module
+- build_old_libs=yes
++ build_libtool_libs=module
++ build_old_libs=yes
+ else
+- build_libtool_libs=no
++ build_libtool_libs=no
+ fi
+ fi
+ else
+@@ -1932,9 +2002,9 @@
+ fi
+ fi # link shared/static library?
+
+- if test "$linkmode" = lib; then
++ if test $linkmode = lib; then
+ if test -n "$dependency_libs" &&
+- { test "$hardcode_into_libs" != yes || test $build_old_libs = yes ||
++ { test $hardcode_into_libs != yes || test $build_old_libs = yes ||
+ test $link_static = yes; }; then
+ # Extract -R from dependency_libs
+ temp_deplibs=
+@@ -1958,13 +2028,15 @@
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ newdependency_libs="$deplib $newdependency_libs"
+- case "$tmp_libs " in
+- *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+- esac
++ if test "X$duplicate_deps" = "Xyes" ; then
++ case "$tmp_libs " in
++ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
++ esac
++ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+
+- if test "$link_all_deplibs" != no; then
++ if test $link_all_deplibs != no; then
+ # Add the search paths of all dependency libraries
+ for deplib in $dependency_libs; do
+ case $deplib in
+@@ -1986,7 +2058,7 @@
+ if grep "^installed=no" $deplib > /dev/null; then
+ path="-L$absdir/$objdir"
+ else
+- eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
++ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit 1
+@@ -2007,15 +2079,15 @@
+ fi # link_all_deplibs != no
+ fi # linkmode = lib
+ done # for deplib in $libs
+- if test "$pass" = dlpreopen; then
++ if test $pass = dlpreopen; then
+ # Link the dlpreopened libraries before other libraries
+ for deplib in $save_deplibs; do
+ deplibs="$deplib $deplibs"
+ done
+ fi
+- if test "$pass" != dlopen; then
+- test "$pass" != scan && dependency_libs="$newdependency_libs"
+- if test "$pass" != conv; then
++ if test $pass != dlopen; then
++ test $pass != scan && dependency_libs="$newdependency_libs"
++ if test $pass != conv; then
+ # Make sure lib_search_path contains only unique directories.
+ lib_search_path=
+ for dir in $newlib_search_path; do
+@@ -2073,7 +2145,7 @@
+ deplibs=
+ fi
+ done # for pass
+- if test "$linkmode" = prog; then
++ if test $linkmode = prog; then
+ dlfiles="$newdlfiles"
+ dlprefiles="$newdlprefiles"
+ fi
+@@ -2175,7 +2247,7 @@
+ else
+
+ # Parse the version information argument.
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS=':'
++ save_ifs="$IFS"; IFS=':'
+ set dummy $vinfo 0 0 0
+ IFS="$save_ifs"
+
+@@ -2250,16 +2322,21 @@
+ versuffix=".$current";
+ ;;
+
+- irix)
++ irix | nonstopux)
+ major=`expr $current - $age + 1`
+- verstring="sgi$major.$revision"
++
++ case $version_type in
++ nonstopux) verstring_prefix=nonstopux ;;
++ *) verstring_prefix=sgi ;;
++ esac
++ verstring="$verstring_prefix$major.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$revision
+ while test $loop != 0; do
+ iface=`expr $revision - $loop`
+ loop=`expr $loop - 1`
+- verstring="sgi$major.$iface:$verstring"
++ verstring="$verstring_prefix$major.$iface:$verstring"
+ done
+
+ # Before this point, $major must not contain `.'.
+@@ -2273,7 +2350,7 @@
+ ;;
+
+ osf)
+- major=`expr $current - $age`
++ major=.`expr $current - $age`
+ versuffix=".$current.$age.$revision"
+ verstring="$current.$age.$revision"
+
+@@ -2312,6 +2389,16 @@
+ if test -z "$vinfo" && test -n "$release"; then
+ major=
+ verstring="0.0"
++ case $version_type in
++ darwin)
++ # we can't check for "0.0" in archive_cmds due to quoting
++ # problems, so we reset it completely
++ verstring=""
++ ;;
++ *)
++ verstring="0.0"
++ ;;
++ esac
+ if test "$need_version" = no; then
+ versuffix=
+ else
+@@ -2355,9 +2442,9 @@
+
+ # Eliminate all temporary directories.
+ for path in $notinst_path; do
+- lib_search_path=`echo "$lib_search_path " | sed -e 's% $path % %g'`
+- deplibs=`echo "$deplibs " | sed -e 's% -L$path % %g'`
+- dependency_libs=`echo "$dependency_libs " | sed -e 's% -L$path % %g'`
++ lib_search_path=`echo "$lib_search_path " | ${SED} -e 's% $path % %g'`
++ deplibs=`echo "$deplibs " | ${SED} -e 's% -L$path % %g'`
++ dependency_libs=`echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'`
+ done
+
+ if test -n "$xrpath"; then
+@@ -2408,9 +2495,12 @@
+ *-*-netbsd*)
+ # Don't link with libc until the a.out ld.so is fixed.
+ ;;
++ *-*-openbsd* | *-*-freebsd*)
++ # Do not include libc due to us having libc/libc_r.
++ ;;
+ *)
+ # Add libc to deplibs on all other systems if necessary.
+- if test "$build_libtool_need_lc" = "yes"; then
++ if test $build_libtool_need_lc = "yes"; then
+ deplibs="$deplibs -lc"
+ fi
+ ;;
+@@ -2466,18 +2556,20 @@
+ else
+ droppeddeps=yes
+ echo
+- echo "*** Warning: This library needs some functionality provided by $i."
++ echo "*** Warning: dynamic linker does not accept needed library $i."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+- echo "*** shared version of the library, which you do not appear to have."
++ echo "*** shared version of the library, which I believe you do not have"
++ echo "*** because a test_compile did reveal that the linker did not use it for"
++ echo "*** its dynamic dependency list that programs get resolved with at runtime."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ else
+- # Error occured in the first compile. Let's try to salvage the situation:
+- # Compile a seperate program for each library.
++ # Error occured in the first compile. Let's try to salvage
++ # the situation: Compile a separate program for each library.
+ for i in $deplibs; do
+ name="`expr $i : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+@@ -2496,10 +2588,12 @@
+ else
+ droppeddeps=yes
+ echo
+- echo "*** Warning: This library needs some functionality provided by $i."
++ echo "*** Warning: dynamic linker does not accept needed library $i."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+- echo "*** shared version of the library, which you do not appear to have."
++ echo "*** shared version of the library, which you do not appear to have"
++ echo "*** because a test_compile did reveal that the linker did not use this one"
++ echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+ fi
+ else
+ droppeddeps=yes
+@@ -2538,14 +2632,14 @@
+ # but so what?
+ potlib="$potent_lib"
+ while test -h "$potlib" 2>/dev/null; do
+- potliblink=`ls -ld $potlib | sed 's/.* -> //'`
++ potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+ case $potliblink in
+ [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+ *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+ esac
+ done
+ if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+- | sed 10q \
++ | ${SED} 10q \
+ | egrep "$file_magic_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+@@ -2556,10 +2650,17 @@
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ echo
+- echo "*** Warning: This library needs some functionality provided by $a_deplib."
++ echo "*** Warning: linker path does not have real file for library $a_deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+- echo "*** shared version of the library, which you do not appear to have."
++ echo "*** shared version of the library, which you do not appear to have"
++ echo "*** because I did check the linker path looking for a file starting"
++ if test -z "$potlib" ; then
++ echo "*** with $libname but no candidates were found. (...for file magic test)"
++ else
++ echo "*** with $libname and none of the candidates passed a file format test"
++ echo "*** using a file magic. Last file checked: $potlib"
++ fi
+ fi
+ else
+ # Add a -L argument.
+@@ -2578,8 +2679,9 @@
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
++ potlib="$potent_lib" # see symlink-check below in file_magic test
+ if eval echo \"$potent_lib\" 2>/dev/null \
+- | sed 10q \
++ | ${SED} 10q \
+ | egrep "$match_pattern_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+@@ -2590,10 +2692,17 @@
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ echo
+- echo "*** Warning: This library needs some functionality provided by $a_deplib."
++ echo "*** Warning: linker path does not have real file for library $a_deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+- echo "*** shared version of the library, which you do not appear to have."
++ echo "*** shared version of the library, which you do not appear to have"
++ echo "*** because I did check the linker path looking for a file starting"
++ if test -z "$potlib" ; then
++ echo "*** with $libname but no candidates were found. (...for regex pattern test)"
++ else
++ echo "*** with $libname and none of the candidates passed a file format test"
++ echo "*** using a regex pattern. Last file checked: $potlib"
++ fi
+ fi
+ else
+ # Add a -L argument.
+@@ -2683,7 +2792,7 @@
+
+ # Test again, we may have decided not to build it any more
+ if test "$build_libtool_libs" = yes; then
+- if test "$hardcode_into_libs" = yes; then
++ if test $hardcode_into_libs = yes; then
+ # Hardcode the library paths
+ hardcode_libdirs=
+ dep_rpath=
+@@ -2784,7 +2893,7 @@
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ eval cmds=\"$export_symbols_cmds\"
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
++ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+@@ -2858,9 +2967,20 @@
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval cmds=\"$archive_expsym_cmds\"
+ else
++ save_deplibs="$deplibs"
++ for conv in $convenience; do
++ tmp_deplibs=
++ for test_deplib in $deplibs; do
++ if test "$test_deplib" != "$conv"; then
++ tmp_deplibs="$tmp_deplibs $test_deplib"
++ fi
++ done
++ deplibs="$tmp_deplibs"
++ done
+ eval cmds=\"$archive_cmds\"
++ deplibs="$save_deplibs"
+ fi
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
++ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+@@ -2988,7 +3108,7 @@
+
+ output="$obj"
+ eval cmds=\"$reload_cmds\"
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
++ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+@@ -3024,7 +3144,7 @@
+ reload_objs="$libobjs $reload_conv_objs"
+ output="$libobj"
+ eval cmds=\"$reload_cmds\"
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
++ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+@@ -3057,7 +3177,7 @@
+
+ prog)
+ case $host in
+- *cygwin*) output=`echo $output | sed -e 's,.exe$,,;s,$,.exe,'` ;;
++ *cygwin*) output=`echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
+ esac
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+@@ -3079,6 +3199,13 @@
+ # On Rhapsody replace the C library is the System framework
+ compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
++ case $host in
++ *darwin*)
++ # Don't allow lazy linking, it breaks C++ global constructors
++ compile_command="$compile_command ${wl}-bind_at_load"
++ finalize_command="$finalize_command ${wl}-bind_at_load"
++ ;;
++ esac
+ ;;
+ esac
+
+@@ -3245,9 +3372,9 @@
+ if test -z "$export_symbols"; then
+ export_symbols="$output_objdir/$output.exp"
+ $run $rm $export_symbols
+- $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
++ $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ else
+- $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
++ $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
+ $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
+ $run eval 'mv "$nlist"T "$nlist"'
+ fi
+@@ -3255,7 +3382,7 @@
+
+ for arg in $dlprefiles; do
+ $show "extracting global C symbols from \`$arg'"
+- name=`echo "$arg" | sed -e 's%^.*/%%'`
++ name=`echo "$arg" | ${SED} -e 's%^.*/%%'`
+ $run eval 'echo ": $name " >> "$nlist"'
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+@@ -3270,7 +3397,13 @@
+ fi
+
+ # Try sorting and uniquifying the output.
+- if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then
++ if grep -v "^: " < "$nlist" |
++ if sort -k 3 </dev/null >/dev/null 2>&1; then
++ sort -k 3
++ else
++ sort +2
++ fi |
++ uniq > "$nlist"S; then
+ :
+ else
+ grep -v "^: " < "$nlist" > "$nlist"S
+@@ -3287,27 +3420,25 @@
+ #undef lt_preloaded_symbols
+
+ #if defined (__STDC__) && __STDC__
+-# define lt_ptr_t void *
++# define lt_ptr void *
+ #else
+-# define lt_ptr_t char *
++# define lt_ptr char *
+ # define const
+ #endif
+
+ /* The mapping between symbol names and symbols. */
+ const struct {
+ const char *name;
+- lt_ptr_t address;
++ lt_ptr address;
+ }
+ lt_preloaded_symbols[] =
+ {\
+ "
+
+- sed -n -e 's/^: \([^ ]*\) $/ {\"\1\", (lt_ptr_t) 0},/p' \
+- -e 's/^. \([^ ]*\) \([^ ]*\)$/ {"\2", (lt_ptr_t) \&\2},/p' \
+- < "$nlist" >> "$output_objdir/$dlsyms"
++ eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
+
+ $echo >> "$output_objdir/$dlsyms" "\
+- {0, (lt_ptr_t) 0}
++ {0, (lt_ptr) 0}
+ };
+
+ /* This works around a problem in FreeBSD linker */
+@@ -3494,7 +3625,7 @@
+ relink_command="$var=\"$var_value\"; export $var; $relink_command"
+ fi
+ done
+- relink_command="cd `pwd`; $relink_command"
++ relink_command="(cd `pwd`; $relink_command)"
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+@@ -3514,7 +3645,7 @@
+ # win32 will think the script is a binary if it has
+ # a .exe suffix, so we strip it off here.
+ case $output in
+- *.exe) output=`echo $output|sed 's,.exe$,,'` ;;
++ *.exe) output=`echo $output|${SED} 's,.exe$,,'` ;;
+ esac
+ # test for cygwin because mv fails w/o .exe extensions
+ case $host in
+@@ -3538,7 +3669,7 @@
+
+ # Sed substitution that helps us do robust quoting. It backslashifies
+ # metacharacters that are still active within double-quoted strings.
+-Xsed='sed -e 1s/^X//'
++Xsed="${SED}"' -e 1s/^X//'
+ sed_quote_subst='$sed_quote_subst'
+
+ # The HP-UX ksh and POSIX shell print the target directory to stdout
+@@ -3576,7 +3707,7 @@
+ test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+- file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\`
++ file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
+ while test -n \"\$file\"; do
+ destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+@@ -3589,7 +3720,7 @@
+ fi
+
+ file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+- file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\`
++ file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+ done
+
+ # Try to get the absolute directory name.
+@@ -3603,7 +3734,7 @@
+ progdir=\"\$thisdir/$objdir\"
+
+ if test ! -f \"\$progdir/\$program\" || \\
+- { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\
++ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+ test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+ file=\"\$\$-\$program\"
+@@ -3618,8 +3749,9 @@
+
+ # relink executable if necessary
+ if test -n \"\$relink_command\"; then
+- if (eval \$relink_command); then :
++ if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+ else
++ $echo \"\$relink_command_output\" >&2
+ $rm \"\$progdir/\$file\"
+ exit 1
+ fi
+@@ -3648,7 +3780,7 @@
+ $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+- # The second colon is a workaround for a bug in BeOS R4 sed
++ # The second colon is a workaround for a bug in BeOS R4 ${SED}
+ $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+ export $shlibpath_var
+@@ -3790,7 +3922,7 @@
+
+ eval cmds=\"$old_archive_cmds\"
+ fi
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
++ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+@@ -3823,7 +3955,7 @@
+ fi
+ done
+ # Quote the link command for shipping.
+- relink_command="cd `pwd`; $SHELL $0 --mode=relink $libtool_args"
++ relink_command="(cd `pwd`; $SHELL $0 --mode=relink $libtool_args @inst_prefix_dir@)"
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+
+ # Only create the output if not a dry run.
+@@ -3840,7 +3972,7 @@
+ case $deplib in
+ *.la)
+ name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
+- eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
++ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit 1
+@@ -3854,7 +3986,7 @@
+ newdlfiles=
+ for lib in $dlfiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+- eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
++ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit 1
+@@ -3865,7 +3997,7 @@
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+- eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
++ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit 1
+@@ -4089,7 +4221,7 @@
+
+ *.la)
+ # Check to see that this really is a libtool archive.
+- if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
++ if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+@@ -4124,12 +4256,30 @@
+ dir="$dir$objdir"
+
+ if test -n "$relink_command"; then
++ # Determine the prefix the user has applied to our future dir.
++ inst_prefix_dir=`$echo "$destdir" | sed "s%$libdir\$%%"`
++
++ # Don't allow the user to place us outside of our expected
++ # location b/c this prevents finding dependent libraries that
++ # are installed to the same prefix.
++ if test "$inst_prefix_dir" = "$destdir"; then
++ $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
++ exit 1
++ fi
++
++ if test -n "$inst_prefix_dir"; then
++ # Stick the inst_prefix_dir data into the link command.
++ relink_command=`$echo "$relink_command" | sed "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
++ else
++ relink_command=`$echo "$relink_command" | sed "s%@inst_prefix_dir@%%"`
++ fi
++
+ $echo "$modename: warning: relinking \`$file'" 1>&2
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+- continue
++ exit 1
+ fi
+ fi
+
+@@ -4165,7 +4315,7 @@
+ # Do each command in the postinstall commands.
+ lib="$destdir/$realname"
+ eval cmds=\"$postinstall_cmds\"
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
++ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+@@ -4238,19 +4388,27 @@
+ fi
+
+ # Do a test to see if this is really a libtool program.
+- if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
++ case $host in
++ *cygwin*|*mingw*)
++ wrapper=`echo $file | ${SED} -e 's,.exe$,,'`
++ ;;
++ *)
++ wrapper=$file
++ ;;
++ esac
++ if (${SED} -e '4q' $wrapper | egrep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
+ notinst_deplibs=
+ relink_command=
+
+ # If there is no directory component, then add one.
+ case $file in
+- */* | *\\*) . $file ;;
+- *) . ./$file ;;
++ */* | *\\*) . $wrapper ;;
++ *) . ./$wrapper ;;
+ esac
+
+ # Check the variables that should have been set.
+ if test -z "$notinst_deplibs"; then
+- $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2
++ $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
+ exit 1
+ fi
+
+@@ -4275,8 +4433,8 @@
+ relink_command=
+ # If there is no directory component, then add one.
+ case $file in
+- */* | *\\*) . $file ;;
+- *) . ./$file ;;
++ */* | *\\*) . $wrapper ;;
++ *) . ./$wrapper ;;
+ esac
+
+ outputname=
+@@ -4324,7 +4482,7 @@
+ destfile=$destfile.exe
+ ;;
+ *:*.exe)
+- destfile=`echo $destfile | sed -e 's,.exe$,,'`
++ destfile=`echo $destfile | ${SED} -e 's,.exe$,,'`
+ ;;
+ esac
+ ;;
+@@ -4352,7 +4510,7 @@
+
+ # Do each command in the postinstall commands.
+ eval cmds=\"$old_postinstall_cmds\"
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
++ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+@@ -4368,11 +4526,10 @@
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ test -n "$run" && current_libdirs=" -n$current_libdirs"
+- exec $SHELL $0 --finish$current_libdirs
+- exit 1
++ exec_cmd='$SHELL $0 --finish$current_libdirs'
++ else
++ exit 0
+ fi
+-
+- exit 0
+ ;;
+
+ # libtool finish mode
+@@ -4391,7 +4548,7 @@
+ if test -n "$finish_cmds"; then
+ # Do each command in the finish commands.
+ eval cmds=\"$finish_cmds\"
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
++ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+@@ -4473,7 +4630,7 @@
+ case $file in
+ *.la)
+ # Check to see that this really is a libtool archive.
+- if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
++ if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+@@ -4544,7 +4701,7 @@
+ -*) ;;
+ *)
+ # Do a test to see if this is really a libtool program.
+- if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
++ if (${SED} -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+@@ -4575,11 +4732,8 @@
+ LANG="$save_LANG"; export LANG
+ fi
+
+- # Now actually exec the command.
+- eval "exec \$cmd$args"
+-
+- $echo "$modename: cannot exec \$cmd$args"
+- exit 1
++ # Now prepare to actually exec the command.
++ exec_cmd="\$cmd$args"
+ else
+ # Display what would be done.
+ if test -n "$shlibpath_var"; then
+@@ -4641,14 +4795,14 @@
+
+ # Don't error if the file doesn't exist and rm -f was used.
+ if (test -L "$file") >/dev/null 2>&1 \
+- || (test -h "$file") >/dev/null 2>&1 \
++ || (test -h "$file") >/dev/null 2>&1 \
+ || test -f "$file"; then
+- :
++ :
+ elif test -d "$file"; then
+- exit_status=1
++ exit_status=1
+ continue
+ elif test "$rmforce" = yes; then
+- continue
++ continue
+ fi
+
+ rmfiles="$file"
+@@ -4656,7 +4810,7 @@
+ case $name in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+- if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
++ if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ . $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+@@ -4670,7 +4824,7 @@
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ eval cmds=\"$postuninstall_cmds\"
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
++ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+@@ -4685,7 +4839,7 @@
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ eval cmds=\"$old_postuninstall_cmds\"
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
++ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+@@ -4711,7 +4865,7 @@
+ *)
+ # Do a test to see if this is a libtool program.
+ if test $mode = clean &&
+- (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
++ (${SED} -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ relink_command=
+ . $dir/$file
+
+@@ -4744,11 +4898,18 @@
+ ;;
+ esac
+
+- $echo "$modename: invalid operation mode \`$mode'" 1>&2
+- $echo "$generic_help" 1>&2
+- exit 1
++ if test -z "$exec_cmd"; then
++ $echo "$modename: invalid operation mode \`$mode'" 1>&2
++ $echo "$generic_help" 1>&2
++ exit 1
++ fi
+ fi # test -z "$show_help"
+
++if test -n "$exec_cmd"; then
++ eval exec $exec_cmd
++ exit 1
++fi
++
+ # We need to display help for each of the modes.
+ case $mode in
+ "") $echo \
+--- linux-atm-2.4.1.orig/m4/Makefile.in
++++ linux-atm-2.4.1/m4/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -92,14 +92,14 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
+ all: all-redirect
+ .SUFFIXES:
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps m4/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu m4/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -112,6 +112,11 @@
+ subdir = m4
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu m4/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+--- linux-atm-2.4.1.orig/src/Makefile.in
++++ linux-atm-2.4.1/src/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -85,8 +85,7 @@
+ VERSION = @VERSION@
+ YACC = @YACC@
+
+-SUBDIRS = include lib test debug qgen saal sigd maint arpd ilmid man led lane \
+- mpoad switch config extra
++SUBDIRS = include lib
+
+ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+ CONFIG_HEADER = ../config.h
+@@ -96,14 +95,14 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
+ all: all-redirect
+ .SUFFIXES:
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -186,7 +185,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -202,6 +201,11 @@
+ subdir = src
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+--- linux-atm-2.4.1.orig/src/include/Makefile.in
++++ linux-atm-2.4.1/src/include/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -97,14 +97,14 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
+ all: all-redirect
+ .SUFFIXES:
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/include/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/include/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -142,7 +142,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -158,6 +158,11 @@
+ subdir = src/include
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/include/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+--- linux-atm-2.4.1.orig/src/include/atmd.h
++++ linux-atm-2.4.1/src/include/atmd.h
+@@ -24,6 +24,10 @@
+ (i)->prev = (b)->prev; if ((b)->prev) (b)->prev->next = i; else r = i; \
+ (b)->prev = i; } else { (i)->next = r; (i)->prev = NULL; \
+ if (r) (r)->prev = i; r = i; } })
++#define Q_INSERT_BEFORE_TYPED(r,t,i,b) ({ if (b) { (i)->next = b; \
++ (i)->prev = (b)->prev; if ((b)->prev) (b)->prev->next = i; else r = i; \
++ (b)->prev = i; } else { (i)->next = t r; (i)->prev = NULL; \
++ if (t r) (t r)->prev = i; r = i; } })
+ #define Q_REMOVE(r,i) ({ if ((i)->next) (i)->next->prev = (i)->prev; \
+ if ((i)->prev) (i)->prev->next = (i)->next; else r = (i)->next; })
+
+--- linux-atm-2.4.1.orig/src/lib/Makefile.in
++++ linux-atm-2.4.1/src/lib/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -92,16 +92,10 @@
+ # ATMLIBS_VERSION comes from configure.in in the toplevel directory
+ LDFLAGS = -version-info @LIBVER_CURRENT@:@LIBVER_REVISION@:@LIBVER_AGE@
+
+-libatm_la_SOURCES = text2atm.c atm2text.c atmequal.c sdu2cell.c text2qos.c \
+- qos2text.c qosequal.c sap2text.c text2sap.c sapequal.c \
+- misc.c atmres.h ans.c \
+- common.c diag.c kptr.c text2ip.c timer.c unix.c
++libatm_la_SOURCES = text2atm.c atm2text.c atmequal.c sdu2cell.c text2qos.c qos2text.c qosequal.c sap2text.c text2sap.c sapequal.c misc.c atmres.h ans.c common.c diag.c kptr.c text2ip.c timer.c unix.c
+
+ libatm_la_LIBADD = -lresolv
+-libatm_la_DEPENDENCIES = $(top_builddir)/src/include/atm.h \
+- $(top_builddir)/src/include/atmsap.h \
+- $(top_builddir)/src/include/stdint.h \
+- $(top_builddir)/src/include/atmd.h
++libatm_la_DEPENDENCIES = $(top_builddir)/src/include/atm.h $(top_builddir)/src/include/atmsap.h $(top_builddir)/src/include/stdint.h $(top_builddir)/src/include/atmd.h
+
+ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+ CONFIG_HEADER = ../../config.h
+@@ -126,8 +120,13 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
++DEP_FILES = .deps/ans.P .deps/atm2text.P .deps/atmequal.P \
++.deps/common.P .deps/diag.P .deps/kptr.P .deps/misc.P .deps/qos2text.P \
++.deps/qosequal.P .deps/sap2text.P .deps/sapequal.P .deps/sdu2cell.P \
++.deps/text2atm.P .deps/text2ip.P .deps/text2qos.P .deps/text2sap.P \
++.deps/timer.P .deps/unix.P
+ SOURCES = $(libatm_la_SOURCES)
+ OBJECTS = $(libatm_la_OBJECTS)
+
+@@ -135,9 +134,9 @@
+ .SUFFIXES:
+ .SUFFIXES: .S .c .lo .o .obj .s
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/lib/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/lib/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -167,9 +166,6 @@
+ $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \
+ done
+
+-.c.o:
+- $(COMPILE) -c $<
+-
+ # FIXME: We should only use cygpath when building on Windows,
+ # and only if it is available.
+ .c.obj:
+@@ -192,9 +188,6 @@
+
+ maintainer-clean-compile:
+
+-.c.lo:
+- $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+-
+ .s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+@@ -232,7 +225,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -248,6 +241,11 @@
+ subdir = src/lib
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/lib/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+@@ -258,48 +256,38 @@
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+-ans.lo ans.o : ans.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atm.h atmres.h
+-atm2text.lo atm2text.o : atm2text.c ../../config.h \
+- ../../src/include/atm.h ../../src/include/stdint.h atmres.h
+-atmequal.lo atmequal.o : atmequal.c ../../config.h \
+- ../../src/include/atm.h ../../src/include/stdint.h
+-common.lo common.o : common.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atmd.h ../../src/include/atm.h
+-diag.lo diag.o : diag.c ../../config.h ../../src/include/atmd.h \
+- ../../src/include/stdint.h ../../src/include/atm.h
+-kptr.lo kptr.o : kptr.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h
+-misc.lo misc.o : misc.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atm.h ../../src/include/atmsap.h
+-qos2text.lo qos2text.o : qos2text.c ../../config.h \
+- ../../src/include/atm.h ../../src/include/stdint.h
+-qosequal.lo qosequal.o : qosequal.c ../../config.h \
+- ../../src/include/atm.h ../../src/include/stdint.h
+-sap2text.lo sap2text.o : sap2text.c ../../config.h \
+- ../../src/include/atmsap.h ../../src/include/stdint.h \
+- ../../src/include/atm.h
+-sapequal.lo sapequal.o : sapequal.c ../../config.h \
+- ../../src/include/atm.h ../../src/include/stdint.h \
+- ../../src/include/atmsap.h
+-sdu2cell.lo sdu2cell.o : sdu2cell.c ../../config.h \
+- ../../src/include/atm.h ../../src/include/stdint.h
+-text2atm.lo text2atm.o : text2atm.c ../../config.h \
+- ../../src/include/atm.h ../../src/include/stdint.h \
+- ../../src/include/atmsap.h atmres.h
+-text2ip.lo text2ip.o : text2ip.c ../../config.h \
+- ../../src/include/stdint.h ../../src/include/atm.h \
+- ../../src/include/atmd.h
+-text2qos.lo text2qos.o : text2qos.c ../../config.h \
+- ../../src/include/atm.h ../../src/include/stdint.h
+-text2sap.lo text2sap.o : text2sap.c ../../config.h \
+- ../../src/include/atmsap.h ../../src/include/stdint.h \
+- ../../src/include/atm.h
+-timer.lo timer.o : timer.c ../../config.h ../../src/include/atmd.h \
+- ../../src/include/stdint.h ../../src/include/atm.h
+-unix.lo unix.o : unix.c ../../config.h ../../src/include/atmd.h \
+- ../../src/include/stdint.h ../../src/include/atm.h
+
++DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
++
++-include $(DEP_FILES)
++
++mostlyclean-depend:
++
++clean-depend:
++
++distclean-depend:
++ -rm -rf .deps
++
++maintainer-clean-depend:
++
++%.o: %.c
++ @echo '$(COMPILE) -c $<'; \
++ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-cp .deps/$(*F).pp .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm .deps/$(*F).pp
++
++%.lo: %.c
++ @echo '$(LTCOMPILE) -c $<'; \
++ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
++ < .deps/$(*F).pp > .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm -f .deps/$(*F).pp
+ info-am:
+ info: info-am
+ dvi-am:
+@@ -337,27 +325,27 @@
+
+ maintainer-clean-generic:
+ mostlyclean-am: mostlyclean-libLTLIBRARIES mostlyclean-compile \
+- mostlyclean-libtool mostlyclean-tags \
++ mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+ mostlyclean-generic
+
+ mostlyclean: mostlyclean-am
+
+ clean-am: clean-libLTLIBRARIES clean-compile clean-libtool clean-tags \
+- clean-generic mostlyclean-am
++ clean-depend clean-generic mostlyclean-am
+
+ clean: clean-am
+
+ distclean-am: distclean-libLTLIBRARIES distclean-compile \
+- distclean-libtool distclean-tags distclean-generic \
+- clean-am
++ distclean-libtool distclean-tags distclean-depend \
++ distclean-generic clean-am
+ -rm -f libtool
+
+ distclean: distclean-am
+
+ maintainer-clean-am: maintainer-clean-libLTLIBRARIES \
+ maintainer-clean-compile maintainer-clean-libtool \
+- maintainer-clean-tags maintainer-clean-generic \
+- distclean-am
++ maintainer-clean-tags maintainer-clean-depend \
++ 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."
+
+@@ -369,12 +357,13 @@
+ distclean-compile clean-compile maintainer-clean-compile \
+ mostlyclean-libtool distclean-libtool clean-libtool \
+ maintainer-clean-libtool tags mostlyclean-tags distclean-tags \
+-clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+-check-am installcheck-am installcheck 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
++clean-tags maintainer-clean-tags distdir mostlyclean-depend \
++distclean-depend clean-depend maintainer-clean-depend info-am info \
++dvi-am dvi check check-am installcheck-am installcheck 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
+
+
+ #libatm_la_SOURCES = text2atm.c atm2text.c atmequal.c sdu2cell.c text2qos.c \
+--- linux-atm-2.4.1.orig/src/lib/sapequal.c
++++ linux-atm-2.4.1/src/lib/sapequal.c
+@@ -65,6 +65,7 @@
+ CHECK(l2.itu.window,a.l2.itu.window > b.l2.itu.window);
+ break;
+ default:
++ break;
+ }
+ switch (a.l3_proto) {
+ case ATM_L3_X25:
+@@ -83,6 +84,7 @@
+ if (a.l3.user != b.l3.user) return 0;
+ break;
+ default:
++ break;
+ }
+ return 1;
+ }
+--- linux-atm-2.4.1.orig/src/test/Makefile.in
++++ linux-atm-2.4.1/src/test/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -168,8 +168,11 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
++DEP_FILES = .deps/align.P .deps/aping.P .deps/aread.P .deps/awrite.P \
++.deps/br.P .deps/bw.P .deps/isp.P .deps/ispl_l.P .deps/ispl_y.P \
++.deps/ttcp.P .deps/window.P
+ SOURCES = $(aread_SOURCES) $(awrite_SOURCES) $(ttcp_atm_SOURCES) $(align_SOURCES) $(aping_SOURCES) $(br_SOURCES) $(bw_SOURCES) $(isp_SOURCES) $(window_SOURCES)
+ OBJECTS = $(aread_OBJECTS) $(awrite_OBJECTS) $(ttcp_atm_OBJECTS) $(align_OBJECTS) $(aping_OBJECTS) $(br_OBJECTS) $(bw_OBJECTS) $(isp_OBJECTS) $(window_OBJECTS)
+
+@@ -177,9 +180,9 @@
+ .SUFFIXES:
+ .SUFFIXES: .S .c .l .lo .o .obj .s .y
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/test/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/test/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -218,9 +221,6 @@
+
+ maintainer-clean-noinstPROGRAMS:
+
+-.c.o:
+- $(COMPILE) -c $<
+-
+ # FIXME: We should only use cygpath when building on Windows,
+ # and only if it is available.
+ .c.obj:
+@@ -243,9 +243,6 @@
+
+ maintainer-clean-compile:
+
+-.c.lo:
+- $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+-
+ .s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+@@ -325,7 +322,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -341,6 +338,11 @@
+ subdir = src/test
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/test/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+@@ -351,30 +353,38 @@
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+-align.o: align.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h
+-aping.o: aping.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h
+-aread.o: aread.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h
+-awrite.o: awrite.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h
+-br.o: br.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h
+-bw.o: bw.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h
+-isp.o: isp.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h isp.h \
+- errnos.inc
+-ispl_l.o: ispl_l.c ../../config.h ../../src/include/stdint.h isp.h \
+- ../../src/include/atm.h ispl_y.h
+-ispl_y.o: ispl_y.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h isp.h
+-ttcp.o: ttcp.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atm.h ../../src/include/atmsap.h
+-window.o: window.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h
+
++DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
++
++-include $(DEP_FILES)
++
++mostlyclean-depend:
++
++clean-depend:
++
++distclean-depend:
++ -rm -rf .deps
++
++maintainer-clean-depend:
++
++%.o: %.c
++ @echo '$(COMPILE) -c $<'; \
++ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-cp .deps/$(*F).pp .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm .deps/$(*F).pp
++
++%.lo: %.c
++ @echo '$(LTCOMPILE) -c $<'; \
++ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
++ < .deps/$(*F).pp > .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm -f .deps/$(*F).pp
+ info-am:
+ info: info-am
+ dvi-am:
+@@ -412,21 +422,22 @@
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+ maintainer-clean-generic:
+- -test -z "ispl_llispl_yhispl_yc" || rm -f ispl_ll ispl_yh ispl_yc
++ -test -z "ispl_lcispl_yhispl_yc" || rm -f ispl_lc ispl_yh ispl_yc
+ mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-noinstPROGRAMS \
+ mostlyclean-compile mostlyclean-libtool \
+- mostlyclean-tags mostlyclean-generic
++ mostlyclean-tags mostlyclean-depend mostlyclean-generic
+
+ mostlyclean: mostlyclean-am
+
+ clean-am: clean-binPROGRAMS clean-noinstPROGRAMS clean-compile \
+- clean-libtool clean-tags clean-generic mostlyclean-am
++ clean-libtool clean-tags clean-depend clean-generic \
++ mostlyclean-am
+
+ clean: clean-am
+
+ distclean-am: distclean-binPROGRAMS distclean-noinstPROGRAMS \
+ distclean-compile distclean-libtool distclean-tags \
+- distclean-generic clean-am
++ distclean-depend distclean-generic clean-am
+ -rm -f libtool
+
+ distclean: distclean-am
+@@ -434,8 +445,8 @@
+ maintainer-clean-am: maintainer-clean-binPROGRAMS \
+ maintainer-clean-noinstPROGRAMS \
+ maintainer-clean-compile maintainer-clean-libtool \
+- maintainer-clean-tags maintainer-clean-generic \
+- distclean-am
++ maintainer-clean-tags maintainer-clean-depend \
++ 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."
+
+@@ -448,19 +459,22 @@
+ mostlyclean-compile distclean-compile clean-compile \
+ maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+ clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+-distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+-dvi-am dvi check check-am installcheck-am installcheck 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
++distclean-tags clean-tags maintainer-clean-tags distdir \
++mostlyclean-depend distclean-depend clean-depend \
++maintainer-clean-depend info-am info dvi-am dvi check check-am \
++installcheck-am installcheck 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
+
+
+ isp.o: errnos.inc
+
+ errnos.inc: mkerrnos.pl
+- @PERL@ ./mkerrnos.pl </usr/include/asm/errno.h \
+- >errnos.inc || { rm -f errnos.inc; exit 1; }
++ cpp -I/usr/include/ -dM /usr/include/asm/errno.h | grep "^#define E" \
++ | @PERL@ ./mkerrnos.pl | grep -v EMAXERRNO >errnos.inc \
++ || { rm -f errnos.inc; exit 1; }
+
+ # 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.
+--- linux-atm-2.4.1.orig/src/test/Makefile.am
++++ linux-atm-2.4.1/src/test/Makefile.am
+@@ -26,6 +26,7 @@
+ isp.o: errnos.inc
+
+ errnos.inc: mkerrnos.pl
+- @PERL@ ./mkerrnos.pl </usr/include/asm/errno.h \
+- >errnos.inc || { rm -f errnos.inc; exit 1; }
+-
++ cpp -I/usr/include/ -dM /usr/include/asm/errno.h | grep "^#define E" \
++ | @PERL@ ./mkerrnos.pl | grep -v EMAXERRNO >errnos.inc \
++ || { rm -f errnos.inc; exit 1; }
++
+--- linux-atm-2.4.1.orig/src/test/ttcp.c
++++ linux-atm-2.4.1/src/test/ttcp.c
+@@ -55,6 +55,8 @@
+ /* #define SYSV */ /* required on SGI IRIX releases before 3.3 */
+
+ #include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
+ #include <signal.h>
+ #include <ctype.h>
+ #include <errno.h>
+@@ -67,6 +69,7 @@
+ #include <sys/time.h> /* struct timeval */
+ #include <atm.h>
+ #include <atmsap.h>
++#include <unistd.h>
+
+ #if defined(SYSV)
+ #include <sys/times.h>
+@@ -85,7 +88,8 @@
+ 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 */
+@@ -120,7 +124,6 @@
+ static struct rusage ru0; /* Resource utilization at the start */
+
+ struct hostent *addr;
+-extern int errno;
+ extern int optind;
+ extern char *optarg;
+
+@@ -158,23 +161,21 @@
+ unsigned long numCalls; /* # of I/O system calls */
+ double cput, realt; /* user, real time (seconds) */
+
+-void err();
+-void mes();
+-int pattern();
+-void prep_timer();
+-double read_timer();
+-int Nread();
+-int Nwrite();
+-void delay();
+-int mread();
+-char *outfmt();
+-static void prusage();
+-static void tvadd();
+-static void tvsub();
+-static void psecs();
++void err(const char *s);
++void mes(const char *s);
++void prep_timer(void);
++void pattern(char *cp, int cnt);
++int Nread(int nfd, char *Nbuf, int count);
++int Nwrite(int nfd, char *Nbuf, int count);
++void delay(int us);
++int mread(int mfd, char *bufp, unsigned n);
++char *outfmt(double b);
++static void prusage(struct rusage *r0, struct rusage *r1, struct timeval *e, struct timeval *b, char *outp);
++static void tvadd(struct timeval *tsum, struct timeval *t0, struct timeval *t1);
++static void tvsub(struct timeval *tdiff, struct timeval *t1, struct timeval *t0);
++static void psecs(long l, char *cp);
+
+-void
+-sigpipe()
++void sigpipe(int unused)
+ {
+ }
+
+@@ -183,16 +184,14 @@
+ * main -
+ *-------------------------------------------------------------------------
+ */
+-main(argc,argv)
+-int argc;
+-char **argv;
++int main(int argc,char **argv)
+ {
+ struct timeval td;
+ unsigned long addr_tmp;
+ const char *port_name = NULL,*tos = NULL;
+ int c;
+ double mbps;
+-int no_check = 0;
++ int no_check = 0;
+
+ if (argc < 2) goto usage;
+
+@@ -275,7 +274,7 @@
+ }
+ }
+
+- if (port_name)
++ if (port_name) {
+ if (atm) goto usage;
+ else {
+ struct servent *se;
+@@ -283,13 +282,13 @@
+ se = getservbyname(port_name,udp ? "udp" : "tcp");
+ if (se) port = ntohs(se->s_port);
+ else {
+- const char *end;
++ char *end;
+
+ port = strtoul(port_name,&end,0);
+ if (*end) goto usage;
+ }
+ }
+-
++ }
+ host = argv[optind];
+
+ if (atm) {
+@@ -435,9 +434,9 @@
+ #endif
+
+ if (!atm || satm.sas_family == AF_ATMPVC || !trans)
+- if (bind(fd, atm ? &satm : &sinme, atm ? satm.sas_family == AF_ATMPVC ?
+- sizeof(struct sockaddr_atmpvc) : sizeof(struct sockaddr_atmsvc) :
+- sizeof(sinme)) < 0)
++ if (bind(fd, atm ?
++ (struct sockaddr *)&satm : (struct sockaddr *)&sinme,
++ atm ? satm.sas_family == AF_ATMPVC ? sizeof(struct sockaddr_atmpvc) : sizeof(struct sockaddr_atmsvc) : sizeof(sinme)) < 0)
+ err("bind");
+
+ if (!udp || (atm && satm.sas_family == AF_ATMSVC)) {
+@@ -453,8 +452,8 @@
+ err("setsockopt");
+ }
+
+- if (connect(fd, atm ? &satm : &sinhim, atm ? sizeof(satm) :
+- sizeof(sinhim)) < 0)
++ if (connect(fd,
++ atm ? (struct sockaddr *)&satm : (struct sockaddr *)&sinhim, atm ? sizeof(satm) : sizeof(sinhim)) < 0)
+ err("connect");
+
+ mes("connect");
+@@ -482,13 +481,13 @@
+ fromlen = sizeof(frominet);
+ domain = AF_INET;
+
+- if ((fd=accept(fd, &frominet, &fromlen) ) < 0)
++ if ((fd=accept(fd, (struct sockaddr *)&frominet, &fromlen) ) < 0)
+ err("accept");
+
+ {
+ struct sockaddr_atmsvc peer;
+ int peerlen = sizeof(peer);
+- if (getpeername(fd, (struct sockaddr_in *) &peer,
++ if (getpeername(fd, (struct sockaddr *) &peer,
+ &peerlen) < 0) {
+ err("getpeername");
+ }
+@@ -638,13 +637,13 @@
+ nbytes, cput, outfmt((double)nbytes/cput));
+
+ fprintf(stdout,
+- "ttcp%s: %d I/O calls, msec/call = %.2f, calls/sec = %.2f\n",
++ "ttcp%s: %lu I/O calls, msec/call = %.2f, calls/sec = %.2f\n",
+ trans?"-t":"-r",
+ numCalls,
+ 1000.0 * realt/((double)numCalls),
+ ((double)numCalls)/realt);
+ fprintf(stdout,
+- "ttcp%s: buffer address %#x\n",
++ "ttcp%s: buffer address %p\n",
+ trans?"-t":"-r",
+ buf);
+ }
+@@ -656,8 +655,7 @@
+ }
+
+ void
+-err(s)
+-char *s;
++err(const char *s)
+ {
+ int en = errno;
+
+@@ -670,8 +668,7 @@
+ }
+
+ void
+-mes(s)
+-char *s;
++mes(const char *s)
+ {
+ fprintf(stderr,"ttcp%s: %s\n", trans?"-t":"-r", s);
+ }
+@@ -681,9 +678,7 @@
+ * pattern -
+ *-------------------------------------------------------------------------
+ */
+-pattern(cp, cnt)
+-register char *cp;
+-register int cnt;
++void pattern(char *cp, int cnt)
+ {
+ register char c;
+ c = 0;
+@@ -694,9 +689,7 @@
+ }
+
+
+-char *
+-outfmt(b)
+-double b;
++char *outfmt(double b)
+ {
+ static char obuf[50];
+ switch (fmt) {
+@@ -758,7 +751,7 @@
+ * P R E P _ T I M E R
+ */
+ void
+-prep_timer()
++prep_timer(void)
+ {
+ gettimeofday(&start_time, (struct timezone *)0);
+ getrusage(RUSAGE_SELF, &ru0);
+@@ -768,8 +761,7 @@
+ * read_timer -
+ *-------------------------------------------------------------------------
+ */
+-double read_timer(str,len)
+-char *str;
++double read_timer(char *str,int len)
+ {
+ struct rusage ru1;
+ struct timeval tend, tstart, td;
+@@ -788,15 +780,11 @@
+ return( cput );
+ }
+
+-static void
+-prusage(r0, r1, e, b, outp)
+- register struct rusage *r0, *r1;
+- struct timeval *e, *b;
+- char *outp;
++static void prusage(struct rusage *r0, struct rusage *r1, struct timeval *e, struct timeval *b, char *outp)
+ {
+ struct timeval tdiff;
+ register time_t t;
+- register char *cp;
++ register const char *cp;
+ register int i;
+ int ms;
+
+@@ -823,13 +811,13 @@
+
+ case 'U':
+ tvsub(&tdiff, &r1->ru_utime, &r0->ru_utime);
+- sprintf(outp,"%d.%01d", tdiff.tv_sec, tdiff.tv_usec/100000);
++ sprintf(outp,"%ld.%01ld", tdiff.tv_sec, tdiff.tv_usec/100000);
+ END(outp);
+ break;
+
+ case 'S':
+ tvsub(&tdiff, &r1->ru_stime, &r0->ru_stime);
+- sprintf(outp,"%d.%01d", tdiff.tv_sec, tdiff.tv_usec/100000);
++ sprintf(outp,"%ld.%01ld", tdiff.tv_sec, tdiff.tv_usec/100000);
+ END(outp);
+ break;
+
+@@ -851,49 +839,49 @@
+ break;
+
+ case 'X':
+- sprintf(outp,"%d", t == 0 ? 0 : (r1->ru_ixrss-r0->ru_ixrss)/t);
++ sprintf(outp,"%ld", t == 0 ? 0 : (r1->ru_ixrss-r0->ru_ixrss)/t);
+ END(outp);
+ break;
+
+ case 'D':
+- sprintf(outp,"%d", t == 0 ? 0 :
++ sprintf(outp,"%ld", t == 0 ? 0 :
+ (r1->ru_idrss+r1->ru_isrss-(r0->ru_idrss+r0->ru_isrss))/t);
+ END(outp);
+ break;
+
+ case 'K':
+- sprintf(outp,"%d", t == 0 ? 0 :
++ sprintf(outp,"%ld", t == 0 ? 0 :
+ ((r1->ru_ixrss+r1->ru_isrss+r1->ru_idrss) -
+ (r0->ru_ixrss+r0->ru_idrss+r0->ru_isrss))/t);
+ END(outp);
+ break;
+
+ case 'M':
+- sprintf(outp,"%d", r1->ru_maxrss/2);
++ sprintf(outp,"%ld", r1->ru_maxrss/2);
+ END(outp);
+ break;
+
+ case 'F':
+- sprintf(outp,"%d", r1->ru_majflt-r0->ru_majflt);
++ sprintf(outp,"%ld", r1->ru_majflt-r0->ru_majflt);
+ END(outp);
+ break;
+
+ case 'R':
+- sprintf(outp,"%d", r1->ru_minflt-r0->ru_minflt);
++ sprintf(outp,"%ld", r1->ru_minflt-r0->ru_minflt);
+ END(outp);
+ break;
+
+ case 'I':
+- sprintf(outp,"%d", r1->ru_inblock-r0->ru_inblock);
++ sprintf(outp,"%ld", r1->ru_inblock-r0->ru_inblock);
+ END(outp);
+ break;
+
+ case 'O':
+- sprintf(outp,"%d", r1->ru_oublock-r0->ru_oublock);
++ sprintf(outp,"%ld", r1->ru_oublock-r0->ru_oublock);
+ END(outp);
+ break;
+ case 'C':
+- sprintf(outp,"%d+%d", r1->ru_nvcsw-r0->ru_nvcsw,
++ sprintf(outp,"%ld+%ld", r1->ru_nvcsw-r0->ru_nvcsw,
+ r1->ru_nivcsw-r0->ru_nivcsw );
+ END(outp);
+ break;
+@@ -903,9 +891,7 @@
+ *outp = '\0';
+ }
+
+-static void
+-tvadd(tsum, t0, t1)
+- struct timeval *tsum, *t0, *t1;
++static void tvadd(struct timeval *tsum, struct timeval *t0, struct timeval *t1)
+ {
+
+ tsum->tv_sec = t0->tv_sec + t1->tv_sec;
+@@ -919,8 +905,7 @@
+ * tvsub - tdiff = t1 - t0
+ *-------------------------------------------------------------------------
+ */
+-static void tvsub(tdiff, t1, t0)
+- struct timeval *tdiff, *t1, *t0;
++static void tvsub(struct timeval *tdiff, struct timeval *t1, struct timeval *t0)
+ {
+
+ tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
+@@ -931,10 +916,7 @@
+ }
+ }
+
+-static void
+-psecs(l,cp)
+-long l;
+-register char *cp;
++static void psecs(long l, char *cp)
+ {
+ register int i;
+
+@@ -958,26 +940,23 @@
+ /*
+ * N R E A D
+ */
+-Nread( fd, buf, count )
+-int fd;
+-char *buf;
+-int count;
++int Nread( int nfd, char *Nbuf, int count )
+ {
+ struct sockaddr_in from;
+ int len = sizeof(from);
+ register int cnt;
+ if( udp ) {
+ #if 0
+- cnt = recvfrom( fd, buf, count, 0, &from, &len );
++ cnt = recvfrom( nfd, Nbuf, count, 0, &from, &len );
+ #else
+- cnt = recv( fd, buf, count, 0);
++ cnt = recv( nfd, Nbuf, count, 0);
+ #endif
+ numCalls++;
+ } else {
+ if( b_flag )
+- cnt = mread( fd, buf, count ); /* fill buf */
++ cnt = mread( nfd, Nbuf, count ); /* fill buf */
+ else {
+- cnt = read( fd, buf, count );
++ cnt = read( nfd, Nbuf, count );
+ numCalls++;
+ }
+ if (touchdata && cnt > 0) {
+@@ -994,17 +973,15 @@
+ * Nwrite -
+ *-------------------------------------------------------------------------
+ */
+-Nwrite(fd, buf, count)
+-int fd;
+-char *buf;
+-int count;
++int Nwrite(int nfd, char *Nbuf, int count)
+ {
+ register int cnt;
+
+ if (udp) {
+ again:
+- if (atm) cnt = write(fd, buf, count);
+- else cnt = sendto(fd, buf, count, 0, &sinhim, sizeof(sinhim));
++ if (atm) cnt = write(nfd, Nbuf, count);
++ else cnt = sendto(nfd, Nbuf, count, 0, (struct sockaddr *)&sinhim,
++ sizeof(sinhim));
+ numCalls++;
+ if ( cnt<0 && errno == ENOBUFS ) {
+ delay(18000);
+@@ -1012,7 +989,7 @@
+ goto again;
+ }
+ } else {
+- cnt = write(fd, buf, count);
++ cnt = write(nfd, Nbuf, count);
+ numCalls++;
+ }
+ if (cnt < 0) perror("WA:write");
+@@ -1020,13 +997,13 @@
+ }
+
+ void
+-delay(us)
++delay(int us)
+ {
+ struct timeval tv;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = us;
+- (void)select( 1, (char *)0, (char *)0, (char *)0, &tv );
++ (void)select( 1, NULL, NULL, NULL, &tv );
+ }
+
+ /*
+@@ -1038,17 +1015,13 @@
+ * network connections don't deliver data with the same
+ * grouping as it is written with. Written by Robert S. Miles, BRL.
+ */
+-int
+-mread(fd, bufp, n)
+-int fd;
+-register char *bufp;
+-unsigned n;
++int mread(int mfd, char *bufp, unsigned n)
+ {
+ register unsigned count = 0;
+ register int nread;
+
+ do {
+- nread = read(fd, bufp, n-count);
++ nread = read(mfd, bufp, n-count);
+ numCalls++;
+ if(nread < 0) {
+ perror("ttcp_mread");
+--- linux-atm-2.4.1.orig/src/debug/Makefile.in
++++ linux-atm-2.4.1/src/debug/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -129,8 +129,9 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
++DEP_FILES = .deps/delay.P .deps/svctor.P
+ SOURCES = $(delay_SOURCES) $(svctor_SOURCES)
+ OBJECTS = $(delay_OBJECTS) $(svctor_OBJECTS)
+
+@@ -138,9 +139,9 @@
+ .SUFFIXES:
+ .SUFFIXES: .S .c .lo .o .obj .s
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/debug/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/debug/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -154,9 +155,6 @@
+
+ maintainer-clean-noinstPROGRAMS:
+
+-.c.o:
+- $(COMPILE) -c $<
+-
+ # FIXME: We should only use cygpath when building on Windows,
+ # and only if it is available.
+ .c.obj:
+@@ -179,9 +177,6 @@
+
+ maintainer-clean-compile:
+
+-.c.lo:
+- $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+-
+ .s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+@@ -224,7 +219,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -240,6 +235,11 @@
+ subdir = src/debug
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/debug/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+@@ -250,11 +250,38 @@
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+-delay.o: delay.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h
+-svctor.o: svctor.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h
+
++DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
++
++-include $(DEP_FILES)
++
++mostlyclean-depend:
++
++clean-depend:
++
++distclean-depend:
++ -rm -rf .deps
++
++maintainer-clean-depend:
++
++%.o: %.c
++ @echo '$(COMPILE) -c $<'; \
++ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-cp .deps/$(*F).pp .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm .deps/$(*F).pp
++
++%.lo: %.c
++ @echo '$(LTCOMPILE) -c $<'; \
++ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
++ < .deps/$(*F).pp > .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm -f .deps/$(*F).pp
+ info-am:
+ info: info-am
+ dvi-am:
+@@ -291,27 +318,27 @@
+
+ maintainer-clean-generic:
+ mostlyclean-am: mostlyclean-noinstPROGRAMS mostlyclean-compile \
+- mostlyclean-libtool mostlyclean-tags \
++ mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+ mostlyclean-generic
+
+ mostlyclean: mostlyclean-am
+
+ clean-am: clean-noinstPROGRAMS clean-compile clean-libtool clean-tags \
+- clean-generic mostlyclean-am
++ clean-depend clean-generic mostlyclean-am
+
+ clean: clean-am
+
+ distclean-am: distclean-noinstPROGRAMS distclean-compile \
+- distclean-libtool distclean-tags distclean-generic \
+- clean-am
++ distclean-libtool distclean-tags distclean-depend \
++ distclean-generic clean-am
+ -rm -f libtool
+
+ distclean: distclean-am
+
+ maintainer-clean-am: maintainer-clean-noinstPROGRAMS \
+ maintainer-clean-compile maintainer-clean-libtool \
+- maintainer-clean-tags maintainer-clean-generic \
+- distclean-am
++ maintainer-clean-tags maintainer-clean-depend \
++ 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."
+
+@@ -322,12 +349,14 @@
+ mostlyclean-compile distclean-compile clean-compile \
+ maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+ clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+-distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+-dvi-am dvi check check-am installcheck-am installcheck 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
++distclean-tags clean-tags maintainer-clean-tags distdir \
++mostlyclean-depend distclean-depend clean-depend \
++maintainer-clean-depend info-am info dvi-am dvi check check-am \
++installcheck-am installcheck 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.
+--- linux-atm-2.4.1.orig/src/qgen/Makefile.in
++++ linux-atm-2.4.1/src/qgen/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -88,8 +88,7 @@
+ noinst_PROGRAMS = qgen q.dump # q40.out.o
+ check_PROGRAMS = q.test
+
+-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_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
+
+@@ -108,17 +107,10 @@
+
+ EXTRA_DIST = ql_y.h incl.pl mknl.pl msg.fmt TODO
+
+-CLEANFILES = q.out.h q.out.c q.test.c qd.out.h qd.out.c qd.dump.c qd.test.c \
+- default.nl # q40.out.h q40.out.c q40.test.c
++CLEANFILES = q.out.h q.out.c q.test.c qd.out.h qd.out.c qd.dump.c qd.test.c default.nl # q40.out.h q40.out.c q40.test.c
+
+
+-NLS = atm_ai_msg atm_ai_ie atm_loc atm_cv atm_pu atm_na atm_cond atm_ie \
+- atm_msg atm_np atm_ton atm_sat atm_prs atm_scrn atm_vpa atm_poe \
+- q2931_cs atm_td atm_bc atm_tc atm_stc atm_upcc q2931_proto atm_flag \
+- atm_aalp atm_fd atm_tag atm_l2 atm_l3 atm_tt atm_mc atm_hl atm_imd \
+- atm_tdl atm_tni atm_nip atm_shi atm_oci atm_unfm atm_ofi atm_irs \
+- atm_it atm_lit atm_lsi atm_tcs atm_css atm_eqo atm_eqp atm_aap \
+- atm_asp atm_tor
++NLS = atm_ai_msg atm_ai_ie atm_loc atm_cv atm_pu atm_na atm_cond atm_ie atm_msg atm_np atm_ton atm_sat atm_prs atm_scrn atm_vpa atm_poe q2931_cs atm_td atm_bc atm_tc atm_stc atm_upcc q2931_proto atm_flag atm_aalp atm_fd atm_tag atm_l2 atm_l3 atm_tt atm_mc atm_hl atm_imd atm_tdl atm_tni atm_nip atm_shi atm_oci atm_unfm atm_ofi atm_irs atm_it atm_lit atm_lsi atm_tcs atm_css atm_eqo atm_eqp atm_aap atm_asp atm_tor
+
+ SYMFILES = uni.h $(shell @PERL@ incl.pl $(CFLAGS) linux/atmsap.h)
+ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+@@ -155,8 +147,11 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
++DEP_FILES = .deps/common.P .deps/file.P .deps/first.P .deps/qgen.P \
++.deps/ql_l.P .deps/ql_y.P .deps/qlib.P .deps/qtest.P .deps/second.P \
++.deps/third.P
+ SOURCES = $(q_test_SOURCES) $(qgen_SOURCES) $(q_dump_SOURCES) $(EXTRA_q_dump_SOURCES)
+ OBJECTS = $(q_test_OBJECTS) $(qgen_OBJECTS) $(q_dump_OBJECTS)
+
+@@ -164,9 +159,9 @@
+ .SUFFIXES:
+ .SUFFIXES: .S .c .l .lo .o .obj .s .y
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/qgen/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/qgen/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -189,9 +184,6 @@
+
+ maintainer-clean-noinstPROGRAMS:
+
+-.c.o:
+- $(COMPILE) -c $<
+-
+ # FIXME: We should only use cygpath when building on Windows,
+ # and only if it is available.
+ .c.obj:
+@@ -214,9 +206,6 @@
+
+ maintainer-clean-compile:
+
+-.c.lo:
+- $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+-
+ .s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+@@ -272,7 +261,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -288,6 +277,11 @@
+ subdir = src/qgen
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/qgen/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+@@ -298,15 +292,38 @@
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+-common.o: common.c ../../config.h common.h
+-file.o: file.c ../../config.h common.h file.h
+-first.o: first.c ../../config.h common.h qgen.h file.h
+-qgen.o: qgen.c ../../config.h common.h file.h qgen.h
+-ql_l.o: ql_l.c ../../config.h common.h qgen.h ql_y.h
+-ql_y.o: ql_y.c ../../config.h common.h qgen.h file.h
+-second.o: second.c ../../config.h common.h qgen.h file.h
+-third.o: third.c ../../config.h common.h qgen.h file.h
+
++DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
++
++-include $(DEP_FILES)
++
++mostlyclean-depend:
++
++clean-depend:
++
++distclean-depend:
++ -rm -rf .deps
++
++maintainer-clean-depend:
++
++%.o: %.c
++ @echo '$(COMPILE) -c $<'; \
++ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-cp .deps/$(*F).pp .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm .deps/$(*F).pp
++
++%.lo: %.c
++ @echo '$(LTCOMPILE) -c $<'; \
++ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
++ < .deps/$(*F).pp > .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm -f .deps/$(*F).pp
+ info-am:
+ info: info-am
+ dvi-am:
+@@ -344,21 +361,22 @@
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+ maintainer-clean-generic:
+- -test -z "ql_llql_yhql_yc" || rm -f ql_ll ql_yh ql_yc
++ -test -z "ql_lcql_yhql_yc" || rm -f ql_lc ql_yh ql_yc
+ mostlyclean-am: mostlyclean-checkPROGRAMS mostlyclean-noinstPROGRAMS \
+ mostlyclean-compile mostlyclean-libtool \
+- mostlyclean-tags mostlyclean-generic
++ mostlyclean-tags mostlyclean-depend mostlyclean-generic
+
+ mostlyclean: mostlyclean-am
+
+ clean-am: clean-checkPROGRAMS clean-noinstPROGRAMS clean-compile \
+- clean-libtool clean-tags clean-generic mostlyclean-am
++ clean-libtool clean-tags clean-depend clean-generic \
++ mostlyclean-am
+
+ clean: clean-am
+
+ distclean-am: distclean-checkPROGRAMS distclean-noinstPROGRAMS \
+ distclean-compile distclean-libtool distclean-tags \
+- distclean-generic clean-am
++ distclean-depend distclean-generic clean-am
+ -rm -f libtool
+
+ distclean: distclean-am
+@@ -366,8 +384,8 @@
+ maintainer-clean-am: maintainer-clean-checkPROGRAMS \
+ maintainer-clean-noinstPROGRAMS \
+ maintainer-clean-compile maintainer-clean-libtool \
+- maintainer-clean-tags maintainer-clean-generic \
+- distclean-am
++ maintainer-clean-tags maintainer-clean-depend \
++ 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."
+
+@@ -380,12 +398,14 @@
+ mostlyclean-compile distclean-compile clean-compile \
+ maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+ clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+-distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+-dvi-am dvi check check-am installcheck-am installcheck 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
++distclean-tags clean-tags maintainer-clean-tags distdir \
++mostlyclean-depend distclean-depend clean-depend \
++maintainer-clean-depend info-am info dvi-am dvi check check-am \
++installcheck-am installcheck 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
+
+
+ default.nl: mknl.pl $(SYMFILES)
+--- linux-atm-2.4.1.orig/src/qgen/ql_l.c
++++ linux-atm-2.4.1/src/qgen/ql_l.c
+@@ -1,32 +1,85 @@
+-/* A lexical scanner generated by flex */
+
+-/* Scanner skeleton version:
+- * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
+- */
++#line 3 "lex.yy.c"
++
++#define YY_INT_ALIGNED short int
++
++/* A lexical scanner generated by flex */
+
+ #define FLEX_SCANNER
+ #define YY_FLEX_MAJOR_VERSION 2
+ #define YY_FLEX_MINOR_VERSION 5
++#define YY_FLEX_SUBMINOR_VERSION 31
++#if YY_FLEX_SUBMINOR_VERSION > 0
++#define FLEX_BETA
++#endif
+
++/* First, we deal with platform-specific or compiler-specific issues. */
++
++/* begin standard C headers. */
+ #include <stdio.h>
+-#include <unistd.h>
++#include <string.h>
++#include <errno.h>
++#include <stdlib.h>
+
++/* end standard C headers. */
+
+-/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+-#ifdef c_plusplus
+-#ifndef __cplusplus
+-#define __cplusplus
++/* flex integer type definitions */
++
++#ifndef FLEXINT_H
++#define FLEXINT_H
++
++/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
++
++#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
++#include <inttypes.h>
++typedef int8_t flex_int8_t;
++typedef uint8_t flex_uint8_t;
++typedef int16_t flex_int16_t;
++typedef uint16_t flex_uint16_t;
++typedef int32_t flex_int32_t;
++typedef uint32_t flex_uint32_t;
++#else
++typedef signed char flex_int8_t;
++typedef short int flex_int16_t;
++typedef int flex_int32_t;
++typedef unsigned char flex_uint8_t;
++typedef unsigned short int flex_uint16_t;
++typedef unsigned int flex_uint32_t;
++#endif /* ! C99 */
++
++/* Limits of integral types. */
++#ifndef INT8_MIN
++#define INT8_MIN (-128)
++#endif
++#ifndef INT16_MIN
++#define INT16_MIN (-32767-1)
++#endif
++#ifndef INT32_MIN
++#define INT32_MIN (-2147483647-1)
+ #endif
++#ifndef INT8_MAX
++#define INT8_MAX (127)
++#endif
++#ifndef INT16_MAX
++#define INT16_MAX (32767)
++#endif
++#ifndef INT32_MAX
++#define INT32_MAX (2147483647)
++#endif
++#ifndef UINT8_MAX
++#define UINT8_MAX (255U)
++#endif
++#ifndef UINT16_MAX
++#define UINT16_MAX (65535U)
++#endif
++#ifndef UINT32_MAX
++#define UINT32_MAX (4294967295U)
+ #endif
+
++#endif /* ! FLEXINT_H */
+
+ #ifdef __cplusplus
+
+-#include <stdlib.h>
+-
+-/* Use prototypes in function declarations. */
+-#define YY_USE_PROTOS
+-
+ /* The "const" storage-class-modifier is valid. */
+ #define YY_USE_CONST
+
+@@ -34,34 +87,17 @@
+
+ #if __STDC__
+
+-#define YY_USE_PROTOS
+ #define YY_USE_CONST
+
+ #endif /* __STDC__ */
+ #endif /* ! __cplusplus */
+
+-#ifdef __TURBOC__
+- #pragma warn -rch
+- #pragma warn -use
+-#include <io.h>
+-#include <stdlib.h>
+-#define YY_USE_CONST
+-#define YY_USE_PROTOS
+-#endif
+-
+ #ifdef YY_USE_CONST
+ #define yyconst const
+ #else
+ #define yyconst
+ #endif
+
+-
+-#ifdef YY_USE_PROTOS
+-#define YY_PROTO(proto) proto
+-#else
+-#define YY_PROTO(proto) ()
+-#endif
+-
+ /* Returned upon end-of-file. */
+ #define YY_NULL 0
+
+@@ -76,71 +112,71 @@
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+-#define BEGIN yy_start = 1 + 2 *
++#define BEGIN (yy_start) = 1 + 2 *
+
+ /* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+-#define YY_START ((yy_start - 1) / 2)
++#define YY_START (((yy_start) - 1) / 2)
+ #define YYSTATE YY_START
+
+ /* Action number for EOF rule of a given start state. */
+ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+ /* Special action meaning "start processing a new file". */
+-#define YY_NEW_FILE yyrestart( yyin )
++#define YY_NEW_FILE yyrestart(yyin )
+
+ #define YY_END_OF_BUFFER_CHAR 0
+
+ /* Size of default input buffer. */
++#ifndef YY_BUF_SIZE
+ #define YY_BUF_SIZE 16384
++#endif
+
++#ifndef YY_TYPEDEF_YY_BUFFER_STATE
++#define YY_TYPEDEF_YY_BUFFER_STATE
+ typedef struct yy_buffer_state *YY_BUFFER_STATE;
++#endif
+
+ extern int yyleng;
++
+ extern FILE *yyin, *yyout;
+
+ #define EOB_ACT_CONTINUE_SCAN 0
+ #define EOB_ACT_END_OF_FILE 1
+ #define EOB_ACT_LAST_MATCH 2
+
+-/* The funky do-while in the following #define is used to turn the definition
+- * int a single C statement (which needs a semi-colon terminator). This
+- * avoids problems with code like:
+- *
+- * if ( condition_holds )
+- * yyless( 5 );
+- * else
+- * do_something_else();
+- *
+- * Prior to using the do-while the compiler would get upset at the
+- * "else" because it interpreted the "if" statement as being all
+- * done when it reached the ';' after the yyless() call.
+- */
+-
+-/* Return all but the first 'n' matched characters back to the input stream. */
+-
++ #define YY_LESS_LINENO(n)
++
++/* Return all but the first "n" matched characters back to the input stream. */
+ #define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+- *yy_cp = yy_hold_char; \
++ int yyless_macro_arg = (n); \
++ YY_LESS_LINENO(yyless_macro_arg);\
++ *yy_cp = (yy_hold_char); \
+ YY_RESTORE_YY_MORE_OFFSET \
+- yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
++ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+-#define unput(c) yyunput( c, yytext_ptr )
++#define unput(c) yyunput( c, (yytext_ptr) )
+
+ /* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+-typedef unsigned int yy_size_t;
+
++#ifndef YY_TYPEDEF_YY_SIZE_T
++#define YY_TYPEDEF_YY_SIZE_T
++typedef unsigned int yy_size_t;
++#endif
+
++#ifndef YY_STRUCT_YY_BUFFER_STATE
++#define YY_STRUCT_YY_BUFFER_STATE
+ struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+@@ -177,12 +213,16 @@
+ */
+ int yy_at_bol;
+
++ int yy_bs_lineno; /**< The line count. */
++ int yy_bs_column; /**< The column count. */
++
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
++
+ #define YY_BUFFER_NEW 0
+ #define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+@@ -196,23 +236,33 @@
+ * just pointing yyin at a new input file.
+ */
+ #define YY_BUFFER_EOF_PENDING 2
++
+ };
++#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+-static YY_BUFFER_STATE yy_current_buffer = 0;
++/* Stack of input buffers. */
++static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
++static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
++static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+ /* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
++ *
++ * Returns the top of the stack, or NULL.
+ */
+-#define YY_CURRENT_BUFFER yy_current_buffer
++#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
++ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
++ : NULL)
+
++/* Same as previous macro, but useful when we know that the buffer stack is not
++ * NULL or when we need an lvalue. For internal use only.
++ */
++#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+ /* yy_hold_char holds the character lost when yytext is formed. */
+ static char yy_hold_char;
+-
+ static int yy_n_chars; /* number of characters read into yy_ch_buf */
+-
+-
+ int yyleng;
+
+ /* Points to current character in buffer. */
+@@ -225,66 +275,92 @@
+ */
+ static int yy_did_buffer_switch_on_eof;
+
+-void yyrestart YY_PROTO(( FILE *input_file ));
+-
+-void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+-void yy_load_buffer_state YY_PROTO(( void ));
+-YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+-void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+-void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+-void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+-#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+-
+-YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+-YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+-YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+-
+-static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+-static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+-static void yy_flex_free YY_PROTO(( void * ));
++void yyrestart (FILE *input_file );
++void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer );
++YY_BUFFER_STATE yy_create_buffer (FILE *file,int size );
++void yy_delete_buffer (YY_BUFFER_STATE b );
++void yy_flush_buffer (YY_BUFFER_STATE b );
++void yypush_buffer_state (YY_BUFFER_STATE new_buffer );
++void yypop_buffer_state (void );
++
++static void yyensure_buffer_stack (void );
++static void yy_load_buffer_state (void );
++static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file );
++
++#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
++
++YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size );
++YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str );
++YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len );
++
++void *yyalloc (yy_size_t );
++void *yyrealloc (void *,yy_size_t );
++void yyfree (void * );
+
+ #define yy_new_buffer yy_create_buffer
+
+ #define yy_set_interactive(is_interactive) \
+ { \
+- if ( ! yy_current_buffer ) \
+- yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+- yy_current_buffer->yy_is_interactive = is_interactive; \
++ if ( ! YY_CURRENT_BUFFER ){ \
++ yyensure_buffer_stack (); \
++ YY_CURRENT_BUFFER_LVALUE = \
++ yy_create_buffer(yyin,YY_BUF_SIZE ); \
++ } \
++ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+ #define yy_set_bol(at_bol) \
+ { \
+- if ( ! yy_current_buffer ) \
+- yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+- yy_current_buffer->yy_at_bol = at_bol; \
++ if ( ! YY_CURRENT_BUFFER ){\
++ yyensure_buffer_stack (); \
++ YY_CURRENT_BUFFER_LVALUE = \
++ yy_create_buffer(yyin,YY_BUF_SIZE ); \
++ } \
++ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+-#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
++#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
++
++/* Begin user sect3 */
+
+ typedef unsigned char YY_CHAR;
++
+ FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
++
+ typedef int yy_state_type;
++
++extern int yylineno;
++
++int yylineno = 1;
++
+ extern char *yytext;
+ #define yytext_ptr yytext
+
+-static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+-static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+-static int yy_get_next_buffer YY_PROTO(( void ));
+-static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
++static yy_state_type yy_get_previous_state (void );
++static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
++static int yy_get_next_buffer (void );
++static void yy_fatal_error (yyconst char msg[] );
+
+ /* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+ #define YY_DO_BEFORE_ACTION \
+- yytext_ptr = yy_bp; \
+- yyleng = (int) (yy_cp - yy_bp); \
+- yy_hold_char = *yy_cp; \
++ (yytext_ptr) = yy_bp; \
++ yyleng = (size_t) (yy_cp - yy_bp); \
++ (yy_hold_char) = *yy_cp; \
+ *yy_cp = '\0'; \
+- yy_c_buf_p = yy_cp;
++ (yy_c_buf_p) = yy_cp;
+
+ #define YY_NUM_RULES 16
+ #define YY_END_OF_BUFFER 17
+-static yyconst short int yy_accept[70] =
++/* This struct is not used in this scanner,
++ but its presence is necessary. */
++struct yy_trans_info
++ {
++ flex_int32_t yy_verify;
++ flex_int32_t yy_nxt;
++ };
++static yyconst flex_int16_t yy_accept[70] =
+ { 0,
+ 10, 10, 17, 15, 10, 10, 15, 15, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 10, 0, 0,
+@@ -295,7 +371,7 @@
+ 7, 0, 0, 0, 0, 0, 11, 12, 0
+ } ;
+
+-static yyconst int yy_ec[256] =
++static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+@@ -327,14 +403,14 @@
+ 1, 1, 1, 1, 1
+ } ;
+
+-static yyconst int yy_meta[29] =
++static yyconst flex_int32_t yy_meta[29] =
+ { 0,
+ 1, 2, 2, 1, 3, 1, 4, 5, 5, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4
+ } ;
+
+-static yyconst short int yy_base[75] =
++static yyconst flex_int16_t yy_base[75] =
+ { 0,
+ 0, 0, 99, 100, 27, 28, 0, 95, 0, 86,
+ 72, 85, 80, 71, 78, 64, 76, 31, 84, 85,
+@@ -346,7 +422,7 @@
+ 48, 34, 53, 58
+ } ;
+
+-static yyconst short int yy_def[75] =
++static yyconst flex_int16_t yy_def[75] =
+ { 0,
+ 69, 1, 69, 69, 69, 69, 70, 71, 72, 72,
+ 72, 72, 72, 72, 72, 72, 72, 69, 70, 71,
+@@ -358,7 +434,7 @@
+ 69, 69, 69, 69
+ } ;
+
+-static yyconst short int yy_nxt[129] =
++static yyconst flex_int16_t yy_nxt[129] =
+ { 0,
+ 4, 5, 6, 5, 7, 8, 9, 4, 4, 10,
+ 11, 12, 13, 9, 9, 9, 9, 14, 9, 15,
+@@ -376,7 +452,7 @@
+ 69, 69, 69, 69, 69, 69, 69, 69
+ } ;
+
+-static yyconst short int yy_chk[129] =
++static yyconst flex_int16_t yy_chk[129] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+@@ -397,6 +473,9 @@
+ static yy_state_type yy_last_accepting_state;
+ static char *yy_last_accepting_cpos;
+
++extern int yy_flex_debug;
++int yy_flex_debug = 0;
++
+ /* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+@@ -406,7 +485,6 @@
+ #define YY_RESTORE_YY_MORE_OFFSET
+ char *yytext;
+ #line 1 "ql_l.l"
+-#define INITIAL 0
+ #line 2 "ql_l.l"
+ /* ql.l - Q.2931 data structures description language */
+
+@@ -451,7 +529,21 @@
+ return (*walk)->str;
+ }
+
+-#line 455 "lex.yy.c"
++#line 533 "lex.yy.c"
++
++#define INITIAL 0
++
++#ifndef YY_NO_UNISTD_H
++/* Special case for "unistd.h", since it is non-ANSI. We include it way
++ * down here because we want the user's section 1 to have been scanned first.
++ * The user has a chance to override it with an option.
++ */
++#include <unistd.h>
++#endif
++
++#ifndef YY_EXTRA_TYPE
++#define YY_EXTRA_TYPE void *
++#endif
+
+ /* Macros after this point can all be overridden by user definitions in
+ * section 1.
+@@ -459,65 +551,30 @@
+
+ #ifndef YY_SKIP_YYWRAP
+ #ifdef __cplusplus
+-extern "C" int yywrap YY_PROTO(( void ));
++extern "C" int yywrap (void );
+ #else
+-extern int yywrap YY_PROTO(( void ));
++extern int yywrap (void );
+ #endif
+ #endif
+
+-#ifndef YY_NO_UNPUT
+-static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+-#endif
+-
++ static void yyunput (int c,char *buf_ptr );
++
+ #ifndef yytext_ptr
+-static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
++static void yy_flex_strncpy (char *,yyconst char *,int );
+ #endif
+
+ #ifdef YY_NEED_STRLEN
+-static int yy_flex_strlen YY_PROTO(( yyconst char * ));
++static int yy_flex_strlen (yyconst char * );
+ #endif
+
+ #ifndef YY_NO_INPUT
++
+ #ifdef __cplusplus
+-static int yyinput YY_PROTO(( void ));
++static int yyinput (void );
+ #else
+-static int input YY_PROTO(( void ));
+-#endif
+-#endif
+-
+-#if YY_STACK_USED
+-static int yy_start_stack_ptr = 0;
+-static int yy_start_stack_depth = 0;
+-static int *yy_start_stack = 0;
+-#ifndef YY_NO_PUSH_STATE
+-static void yy_push_state YY_PROTO(( int new_state ));
+-#endif
+-#ifndef YY_NO_POP_STATE
+-static void yy_pop_state YY_PROTO(( void ));
+-#endif
+-#ifndef YY_NO_TOP_STATE
+-static int yy_top_state YY_PROTO(( void ));
++static int input (void );
+ #endif
+
+-#else
+-#define YY_NO_PUSH_STATE 1
+-#define YY_NO_POP_STATE 1
+-#define YY_NO_TOP_STATE 1
+-#endif
+-
+-#ifdef YY_MALLOC_DECL
+-YY_MALLOC_DECL
+-#else
+-#if __STDC__
+-#ifndef __cplusplus
+-#include <stdlib.h>
+-#endif
+-#else
+-/* Just try to get by without declaring the routines. This will fail
+- * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+- * or sizeof(void*) != sizeof(int).
+- */
+-#endif
+ #endif
+
+ /* Amount of stuff to slurp up with each read. */
+@@ -526,7 +583,6 @@
+ #endif
+
+ /* Copy whatever the last rule matched to the standard output. */
+-
+ #ifndef ECHO
+ /* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+@@ -539,9 +595,10 @@
+ */
+ #ifndef YY_INPUT
+ #define YY_INPUT(buf,result,max_size) \
+- if ( yy_current_buffer->yy_is_interactive ) \
++ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+- int c = '*', n; \
++ int c = '*'; \
++ size_t n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+@@ -551,9 +608,22 @@
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+- else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
+- && ferror( yyin ) ) \
+- YY_FATAL_ERROR( "input in flex scanner failed" );
++ else \
++ { \
++ errno=0; \
++ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
++ { \
++ if( errno != EINTR) \
++ { \
++ YY_FATAL_ERROR( "input in flex scanner failed" ); \
++ break; \
++ } \
++ errno=0; \
++ clearerr(yyin); \
++ } \
++ }\
++\
++
+ #endif
+
+ /* No semi-colon after return; correct usage is to write "yyterminate();" -
+@@ -574,12 +644,18 @@
+ #define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+ #endif
+
++/* end tables serialization structures and prototypes */
++
+ /* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+ #ifndef YY_DECL
+-#define YY_DECL int yylex YY_PROTO(( void ))
+-#endif
++#define YY_DECL_IS_OURS 1
++
++extern int yylex (void);
++
++#define YY_DECL int yylex (void)
++#endif /* !YY_DECL */
+
+ /* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+@@ -596,27 +672,29 @@
+ #define YY_RULE_SETUP \
+ YY_USER_ACTION
+
++/** The main scanner function which does all the work.
++ */
+ YY_DECL
+- {
++{
+ register yy_state_type yy_current_state;
+- register char *yy_cp = NULL, *yy_bp = NULL;
++ register char *yy_cp, *yy_bp;
+ register int yy_act;
+-
++
+ #line 47 "ql_l.l"
+
+
+-#line 609 "lex.yy.c"
++#line 687 "lex.yy.c"
+
+- if ( yy_init )
++ if ( (yy_init) )
+ {
+- yy_init = 0;
++ (yy_init) = 0;
+
+ #ifdef YY_USER_INIT
+ YY_USER_INIT;
+ #endif
+
+- if ( ! yy_start )
+- yy_start = 1; /* first start state */
++ if ( ! (yy_start) )
++ (yy_start) = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+@@ -624,34 +702,36 @@
+ if ( ! yyout )
+ yyout = stdout;
+
+- if ( ! yy_current_buffer )
+- yy_current_buffer =
+- yy_create_buffer( yyin, YY_BUF_SIZE );
++ if ( ! YY_CURRENT_BUFFER ) {
++ yyensure_buffer_stack ();
++ YY_CURRENT_BUFFER_LVALUE =
++ yy_create_buffer(yyin,YY_BUF_SIZE );
++ }
+
+- yy_load_buffer_state();
++ yy_load_buffer_state( );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+- yy_cp = yy_c_buf_p;
++ yy_cp = (yy_c_buf_p);
+
+ /* Support of yytext. */
+- *yy_cp = yy_hold_char;
++ *yy_cp = (yy_hold_char);
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+- yy_current_state = yy_start;
++ yy_current_state = (yy_start);
+ yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+- yy_last_accepting_state = yy_current_state;
+- yy_last_accepting_cpos = yy_cp;
++ (yy_last_accepting_state) = yy_current_state;
++ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+@@ -668,24 +748,22 @@
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+- yy_cp = yy_last_accepting_cpos;
+- yy_current_state = yy_last_accepting_state;
++ yy_cp = (yy_last_accepting_cpos);
++ yy_current_state = (yy_last_accepting_state);
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+-
+ do_action: /* This label is used only to access EOF actions. */
+
+-
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+- *yy_cp = yy_hold_char;
+- yy_cp = yy_last_accepting_cpos;
+- yy_current_state = yy_last_accepting_state;
++ *yy_cp = (yy_hold_char);
++ yy_cp = (yy_last_accepting_cpos);
++ yy_current_state = (yy_last_accepting_state);
+ goto yy_find_action;
+
+ case 1:
+@@ -735,6 +813,7 @@
+ return TOK_ID; }
+ YY_BREAK
+ case 10:
++/* rule 10 can match eol */
+ YY_RULE_SETUP
+ #line 59 "ql_l.l"
+ lineno += *yytext == '\n';
+@@ -755,6 +834,7 @@
+ return TOK_STRING; }
+ YY_BREAK
+ case 14:
++/* rule 14 can match eol */
+ YY_RULE_SETUP
+ #line 66 "ql_l.l"
+ lineno++;
+@@ -769,33 +849,33 @@
+ #line 69 "ql_l.l"
+ ECHO;
+ YY_BREAK
+-#line 773 "lex.yy.c"
++#line 853 "lex.yy.c"
+ case YY_STATE_EOF(INITIAL):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+- int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
++ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+- *yy_cp = yy_hold_char;
++ *yy_cp = (yy_hold_char);
+ YY_RESTORE_YY_MORE_OFFSET
+
+- if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
++ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+- * consistency between yy_current_buffer and our
++ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+- yy_n_chars = yy_current_buffer->yy_n_chars;
+- yy_current_buffer->yy_input_file = yyin;
+- yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
++ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
++ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
++ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+@@ -805,13 +885,13 @@
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+- if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
++ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+- yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
++ (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+- yy_current_state = yy_get_previous_state();
++ yy_current_state = yy_get_previous_state( );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+@@ -824,30 +904,30 @@
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+- yy_bp = yytext_ptr + YY_MORE_ADJ;
++ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+- yy_cp = ++yy_c_buf_p;
++ yy_cp = ++(yy_c_buf_p);
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+- yy_cp = yy_c_buf_p;
++ yy_cp = (yy_c_buf_p);
+ goto yy_find_action;
+ }
+ }
+
+- else switch ( yy_get_next_buffer() )
++ else switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+- yy_did_buffer_switch_on_eof = 0;
++ (yy_did_buffer_switch_on_eof) = 0;
+
+- if ( yywrap() )
++ if ( yywrap( ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+@@ -858,7 +938,7 @@
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+- yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
++ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+@@ -866,30 +946,30 @@
+
+ else
+ {
+- if ( ! yy_did_buffer_switch_on_eof )
++ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+- yy_c_buf_p =
+- yytext_ptr + yy_amount_of_matched_text;
++ (yy_c_buf_p) =
++ (yytext_ptr) + yy_amount_of_matched_text;
+
+- yy_current_state = yy_get_previous_state();
++ yy_current_state = yy_get_previous_state( );
+
+- yy_cp = yy_c_buf_p;
+- yy_bp = yytext_ptr + YY_MORE_ADJ;
++ yy_cp = (yy_c_buf_p);
++ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+- yy_c_buf_p =
+- &yy_current_buffer->yy_ch_buf[yy_n_chars];
++ (yy_c_buf_p) =
++ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+- yy_current_state = yy_get_previous_state();
++ yy_current_state = yy_get_previous_state( );
+
+- yy_cp = yy_c_buf_p;
+- yy_bp = yytext_ptr + YY_MORE_ADJ;
++ yy_cp = (yy_c_buf_p);
++ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+@@ -900,8 +980,7 @@
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+- } /* end of yylex */
+-
++} /* end of yylex */
+
+ /* yy_get_next_buffer - try to read in a new buffer
+ *
+@@ -910,21 +989,20 @@
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+-
+-static int yy_get_next_buffer()
+- {
+- register char *dest = yy_current_buffer->yy_ch_buf;
+- register char *source = yytext_ptr;
++static int yy_get_next_buffer (void)
++{
++ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
++ register char *source = (yytext_ptr);
+ register int number_to_move, i;
+ int ret_val;
+
+- if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
++ if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+- if ( yy_current_buffer->yy_fill_buffer == 0 )
++ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+- if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
++ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+@@ -944,34 +1022,30 @@
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+- number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
++ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+- if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
++ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+- yy_current_buffer->yy_n_chars = yy_n_chars = 0;
++ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+ else
+ {
+- int num_to_read =
+- yy_current_buffer->yy_buf_size - number_to_move - 1;
++ size_t num_to_read =
++ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+-#ifdef YY_USES_REJECT
+- YY_FATAL_ERROR(
+-"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+-#else
+
+ /* just a shorter name for the current buffer */
+- YY_BUFFER_STATE b = yy_current_buffer;
++ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+ int yy_c_buf_p_offset =
+- (int) (yy_c_buf_p - b->yy_ch_buf);
++ (int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+@@ -984,8 +1058,7 @@
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+- yy_flex_realloc( (void *) b->yy_ch_buf,
+- b->yy_buf_size + 2 );
++ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+@@ -995,35 +1068,35 @@
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+- yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
++ (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+- num_to_read = yy_current_buffer->yy_buf_size -
++ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+-#endif
++
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+- YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+- yy_n_chars, num_to_read );
++ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
++ (yy_n_chars), num_to_read );
+
+- yy_current_buffer->yy_n_chars = yy_n_chars;
++ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+- if ( yy_n_chars == 0 )
++ if ( (yy_n_chars) == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+- yyrestart( yyin );
++ yyrestart(yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+- yy_current_buffer->yy_buffer_status =
++ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+@@ -1031,32 +1104,31 @@
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+- yy_n_chars += number_to_move;
+- yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+- yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
++ (yy_n_chars) += number_to_move;
++ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
++ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+- yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
++ (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+- }
+-
++}
+
+ /* yy_get_previous_state - get the state just before the EOB char was reached */
+
+-static yy_state_type yy_get_previous_state()
+- {
++ static yy_state_type yy_get_previous_state (void)
++{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
++
++ yy_current_state = (yy_start);
+
+- yy_current_state = yy_start;
+-
+- for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
++ for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+- yy_last_accepting_state = yy_current_state;
+- yy_last_accepting_cpos = yy_cp;
++ (yy_last_accepting_state) = yy_current_state;
++ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+@@ -1068,30 +1140,23 @@
+ }
+
+ return yy_current_state;
+- }
+-
++}
+
+ /* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+-
+-#ifdef YY_USE_PROTOS
+-static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+-#else
+-static yy_state_type yy_try_NUL_trans( yy_current_state )
+-yy_state_type yy_current_state;
+-#endif
+- {
++ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
++{
+ register int yy_is_jam;
+- register char *yy_cp = yy_c_buf_p;
++ register char *yy_cp = (yy_c_buf_p);
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+- yy_last_accepting_state = yy_current_state;
+- yy_last_accepting_cpos = yy_cp;
++ (yy_last_accepting_state) = yy_current_state;
++ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+@@ -1103,80 +1168,73 @@
+ yy_is_jam = (yy_current_state == 69);
+
+ return yy_is_jam ? 0 : yy_current_state;
+- }
+-
++}
+
+-#ifndef YY_NO_UNPUT
+-#ifdef YY_USE_PROTOS
+-static void yyunput( int c, register char *yy_bp )
+-#else
+-static void yyunput( c, yy_bp )
+-int c;
+-register char *yy_bp;
+-#endif
+- {
+- register char *yy_cp = yy_c_buf_p;
++ static void yyunput (int c, register char * yy_bp )
++{
++ register char *yy_cp;
++
++ yy_cp = (yy_c_buf_p);
+
+ /* undo effects of setting up yytext */
+- *yy_cp = yy_hold_char;
++ *yy_cp = (yy_hold_char);
+
+- if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
++ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+- register int number_to_move = yy_n_chars + 2;
+- register char *dest = &yy_current_buffer->yy_ch_buf[
+- yy_current_buffer->yy_buf_size + 2];
++ register int number_to_move = (yy_n_chars) + 2;
++ register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
++ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+ register char *source =
+- &yy_current_buffer->yy_ch_buf[number_to_move];
++ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+- while ( source > yy_current_buffer->yy_ch_buf )
++ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+- yy_current_buffer->yy_n_chars =
+- yy_n_chars = yy_current_buffer->yy_buf_size;
++ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
++ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+- if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
++ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
++ (yytext_ptr) = yy_bp;
++ (yy_hold_char) = *yy_cp;
++ (yy_c_buf_p) = yy_cp;
++}
+
+- yytext_ptr = yy_bp;
+- yy_hold_char = *yy_cp;
+- yy_c_buf_p = yy_cp;
+- }
+-#endif /* ifndef YY_NO_UNPUT */
+-
+-
++#ifndef YY_NO_INPUT
+ #ifdef __cplusplus
+-static int yyinput()
++ static int yyinput (void)
+ #else
+-static int input()
++ static int input (void)
+ #endif
+- {
+- int c;
+
+- *yy_c_buf_p = yy_hold_char;
++{
++ int c;
++
++ *(yy_c_buf_p) = (yy_hold_char);
+
+- if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
++ if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+- if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
++ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ /* This was really a NUL. */
+- *yy_c_buf_p = '\0';
++ *(yy_c_buf_p) = '\0';
+
+ else
+ { /* need more input */
+- int offset = yy_c_buf_p - yytext_ptr;
+- ++yy_c_buf_p;
++ int offset = (yy_c_buf_p) - (yytext_ptr);
++ ++(yy_c_buf_p);
+
+- switch ( yy_get_next_buffer() )
++ switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+@@ -1190,16 +1248,16 @@
+ */
+
+ /* Reset buffer status. */
+- yyrestart( yyin );
++ yyrestart(yyin );
+
+- /* fall through */
++ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+- if ( yywrap() )
++ if ( yywrap( ) )
+ return EOF;
+
+- if ( ! yy_did_buffer_switch_on_eof )
++ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+ #ifdef __cplusplus
+ return yyinput();
+@@ -1209,90 +1267,92 @@
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+- yy_c_buf_p = yytext_ptr + offset;
++ (yy_c_buf_p) = (yytext_ptr) + offset;
+ break;
+ }
+ }
+ }
+
+- c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */
+- *yy_c_buf_p = '\0'; /* preserve yytext */
+- yy_hold_char = *++yy_c_buf_p;
+-
++ c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
++ *(yy_c_buf_p) = '\0'; /* preserve yytext */
++ (yy_hold_char) = *++(yy_c_buf_p);
+
+ return c;
+- }
+-
+-
+-#ifdef YY_USE_PROTOS
+-void yyrestart( FILE *input_file )
+-#else
+-void yyrestart( input_file )
+-FILE *input_file;
+-#endif
+- {
+- if ( ! yy_current_buffer )
+- yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
++}
++#endif /* ifndef YY_NO_INPUT */
+
+- yy_init_buffer( yy_current_buffer, input_file );
+- yy_load_buffer_state();
++/** Immediately switch to a different input stream.
++ * @param input_file A readable stream.
++ *
++ * @note This function does not reset the start condition to @c INITIAL .
++ */
++ void yyrestart (FILE * input_file )
++{
++
++ if ( ! YY_CURRENT_BUFFER ){
++ yyensure_buffer_stack ();
++ YY_CURRENT_BUFFER_LVALUE =
++ yy_create_buffer(yyin,YY_BUF_SIZE );
+ }
+
++ yy_init_buffer(YY_CURRENT_BUFFER,input_file );
++ yy_load_buffer_state( );
++}
+
+-#ifdef YY_USE_PROTOS
+-void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+-#else
+-void yy_switch_to_buffer( new_buffer )
+-YY_BUFFER_STATE new_buffer;
+-#endif
+- {
+- if ( yy_current_buffer == new_buffer )
++/** Switch to a different input buffer.
++ * @param new_buffer The new input buffer.
++ *
++ */
++ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer )
++{
++
++ /* TODO. We should be able to replace this entire function body
++ * with
++ * yypop_buffer_state();
++ * yypush_buffer_state(new_buffer);
++ */
++ yyensure_buffer_stack ();
++ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+- if ( yy_current_buffer )
++ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+- *yy_c_buf_p = yy_hold_char;
+- yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+- yy_current_buffer->yy_n_chars = yy_n_chars;
++ *(yy_c_buf_p) = (yy_hold_char);
++ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
++ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+- yy_current_buffer = new_buffer;
+- yy_load_buffer_state();
++ YY_CURRENT_BUFFER_LVALUE = new_buffer;
++ yy_load_buffer_state( );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+- yy_did_buffer_switch_on_eof = 1;
+- }
+-
+-
+-#ifdef YY_USE_PROTOS
+-void yy_load_buffer_state( void )
+-#else
+-void yy_load_buffer_state()
+-#endif
+- {
+- yy_n_chars = yy_current_buffer->yy_n_chars;
+- yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+- yyin = yy_current_buffer->yy_input_file;
+- yy_hold_char = *yy_c_buf_p;
+- }
++ (yy_did_buffer_switch_on_eof) = 1;
++}
+
++static void yy_load_buffer_state (void)
++{
++ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
++ (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
++ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
++ (yy_hold_char) = *(yy_c_buf_p);
++}
+
+-#ifdef YY_USE_PROTOS
+-YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+-#else
+-YY_BUFFER_STATE yy_create_buffer( file, size )
+-FILE *file;
+-int size;
+-#endif
+- {
++/** Allocate and initialize an input buffer state.
++ * @param file A readable stream.
++ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
++ *
++ * @return the allocated buffer state.
++ */
++ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size )
++{
+ YY_BUFFER_STATE b;
+-
+- b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
++
++ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+@@ -1301,75 +1361,75 @@
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+- b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
++ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+- yy_init_buffer( b, file );
++ yy_init_buffer(b,file );
+
+ return b;
+- }
+-
++}
+
+-#ifdef YY_USE_PROTOS
+-void yy_delete_buffer( YY_BUFFER_STATE b )
+-#else
+-void yy_delete_buffer( b )
+-YY_BUFFER_STATE b;
+-#endif
+- {
++/** Destroy the buffer.
++ * @param b a buffer created with yy_create_buffer()
++ *
++ */
++ void yy_delete_buffer (YY_BUFFER_STATE b )
++{
++
+ if ( ! b )
+ return;
+
+- if ( b == yy_current_buffer )
+- yy_current_buffer = (YY_BUFFER_STATE) 0;
++ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
++ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+- yy_flex_free( (void *) b->yy_ch_buf );
++ yyfree((void *) b->yy_ch_buf );
+
+- yy_flex_free( (void *) b );
+- }
+-
+-
+-
+-#ifdef YY_USE_PROTOS
+-void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+-#else
+-void yy_init_buffer( b, file )
+-YY_BUFFER_STATE b;
+-FILE *file;
+-#endif
++ yyfree((void *) b );
++}
+
++#ifndef __cplusplus
++extern int isatty (int );
++#endif /* __cplusplus */
++
++/* Initializes or reinitializes a buffer.
++ * This function is sometimes called more than once on the same buffer,
++ * such as during a yyrestart() or at EOF.
++ */
++ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file )
+
+- {
+- yy_flush_buffer( b );
++{
++ int oerrno = errno;
++
++ yy_flush_buffer(b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+-#if YY_ALWAYS_INTERACTIVE
+- b->yy_is_interactive = 1;
+-#else
+-#if YY_NEVER_INTERACTIVE
+- b->yy_is_interactive = 0;
+-#else
+- b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+-#endif
+-#endif
+- }
+-
++ /* If b is the current buffer, then yy_init_buffer was _probably_
++ * called from yyrestart() or through yy_get_next_buffer.
++ * In that case, we don't want to reset the lineno or column.
++ */
++ if (b != YY_CURRENT_BUFFER){
++ b->yy_bs_lineno = 1;
++ b->yy_bs_column = 0;
++ }
+
+-#ifdef YY_USE_PROTOS
+-void yy_flush_buffer( YY_BUFFER_STATE b )
+-#else
+-void yy_flush_buffer( b )
+-YY_BUFFER_STATE b;
+-#endif
++ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
++
++ errno = oerrno;
++}
+
+- {
+- if ( ! b )
++/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
++ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
++ *
++ */
++ void yy_flush_buffer (YY_BUFFER_STATE b )
++{
++ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+@@ -1386,29 +1446,121 @@
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+- if ( b == yy_current_buffer )
+- yy_load_buffer_state();
++ if ( b == YY_CURRENT_BUFFER )
++ yy_load_buffer_state( );
++}
++
++/** Pushes the new state onto the stack. The new state becomes
++ * the current state. This function will allocate the stack
++ * if necessary.
++ * @param new_buffer The new state.
++ *
++ */
++void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
++{
++ if (new_buffer == NULL)
++ return;
++
++ yyensure_buffer_stack();
++
++ /* This block is copied from yy_switch_to_buffer. */
++ if ( YY_CURRENT_BUFFER )
++ {
++ /* Flush out information for old buffer. */
++ *(yy_c_buf_p) = (yy_hold_char);
++ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
++ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
++ }
++
++ /* Only push if top exists. Otherwise, replace top. */
++ if (YY_CURRENT_BUFFER)
++ (yy_buffer_stack_top)++;
++ YY_CURRENT_BUFFER_LVALUE = new_buffer;
++
++ /* copied from yy_switch_to_buffer. */
++ yy_load_buffer_state( );
++ (yy_did_buffer_switch_on_eof) = 1;
++}
++
++/** Removes and deletes the top of the stack, if present.
++ * The next element becomes the new top.
++ *
++ */
++void yypop_buffer_state (void)
++{
++ if (!YY_CURRENT_BUFFER)
++ return;
++
++ yy_delete_buffer(YY_CURRENT_BUFFER );
++ YY_CURRENT_BUFFER_LVALUE = NULL;
++ if ((yy_buffer_stack_top) > 0)
++ --(yy_buffer_stack_top);
++
++ if (YY_CURRENT_BUFFER) {
++ yy_load_buffer_state( );
++ (yy_did_buffer_switch_on_eof) = 1;
+ }
++}
+
++/* Allocates the stack if it does not exist.
++ * Guarantees space for at least one push.
++ */
++static void yyensure_buffer_stack (void)
++{
++ int num_to_alloc;
++
++ if (!(yy_buffer_stack)) {
++
++ /* First allocation is just for 2 elements, since we don't know if this
++ * scanner will even need a stack. We use 2 instead of 1 to avoid an
++ * immediate realloc on the next call.
++ */
++ num_to_alloc = 1;
++ (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
++ (num_to_alloc * sizeof(struct yy_buffer_state*)
++ );
++
++ memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
++
++ (yy_buffer_stack_max) = num_to_alloc;
++ (yy_buffer_stack_top) = 0;
++ return;
++ }
+
+-#ifndef YY_NO_SCAN_BUFFER
+-#ifdef YY_USE_PROTOS
+-YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+-#else
+-YY_BUFFER_STATE yy_scan_buffer( base, size )
+-char *base;
+-yy_size_t size;
+-#endif
+- {
+- YY_BUFFER_STATE b;
++ if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
++
++ /* Increase the buffer to prepare for a possible push. */
++ int grow_size = 8 /* arbitrary grow size */;
+
++ num_to_alloc = (yy_buffer_stack_max) + grow_size;
++ (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
++ ((yy_buffer_stack),
++ num_to_alloc * sizeof(struct yy_buffer_state*)
++ );
++
++ /* zero only the new slots.*/
++ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
++ (yy_buffer_stack_max) = num_to_alloc;
++ }
++}
++
++/** Setup the input buffer state to scan directly from a user-specified character buffer.
++ * @param base the character buffer
++ * @param size the size in bytes of the character buffer
++ *
++ * @return the newly allocated buffer state object.
++ */
++YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
++{
++ YY_BUFFER_STATE b;
++
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+- b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
++ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+@@ -1422,47 +1574,42 @@
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+- yy_switch_to_buffer( b );
++ yy_switch_to_buffer(b );
+
+ return b;
+- }
+-#endif
+-
+-
+-#ifndef YY_NO_SCAN_STRING
+-#ifdef YY_USE_PROTOS
+-YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+-#else
+-YY_BUFFER_STATE yy_scan_string( yy_str )
+-yyconst char *yy_str;
+-#endif
+- {
+- int len;
+- for ( len = 0; yy_str[len]; ++len )
+- ;
+-
+- return yy_scan_bytes( yy_str, len );
+- }
+-#endif
++}
+
++/** Setup the input buffer state to scan a string. The next call to yylex() will
++ * scan from a @e copy of @a str.
++ * @param str a NUL-terminated string to scan
++ *
++ * @return the newly allocated buffer state object.
++ * @note If you want to scan bytes that may contain NUL values, then use
++ * yy_scan_bytes() instead.
++ */
++YY_BUFFER_STATE yy_scan_string (yyconst char * yy_str )
++{
++
++ return yy_scan_bytes(yy_str,strlen(yy_str) );
++}
+
+-#ifndef YY_NO_SCAN_BYTES
+-#ifdef YY_USE_PROTOS
+-YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+-#else
+-YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+-yyconst char *bytes;
+-int len;
+-#endif
+- {
++/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
++ * scan from a @e copy of @a bytes.
++ * @param bytes the byte buffer to scan
++ * @param len the number of bytes in the buffer pointed to by @a bytes.
++ *
++ * @return the newly allocated buffer state object.
++ */
++YY_BUFFER_STATE yy_scan_bytes (yyconst char * bytes, int len )
++{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+-
++
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = len + 2;
+- buf = (char *) yy_flex_alloc( n );
++ buf = (char *) yyalloc(n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+@@ -1471,7 +1618,7 @@
+
+ buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+- b = yy_scan_buffer( buf, n );
++ b = yy_scan_buffer(buf,n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+@@ -1481,148 +1628,164 @@
+ b->yy_is_our_buffer = 1;
+
+ return b;
+- }
+-#endif
+-
++}
+
+-#ifndef YY_NO_PUSH_STATE
+-#ifdef YY_USE_PROTOS
+-static void yy_push_state( int new_state )
+-#else
+-static void yy_push_state( new_state )
+-int new_state;
++#ifndef YY_EXIT_FAILURE
++#define YY_EXIT_FAILURE 2
+ #endif
+- {
+- if ( yy_start_stack_ptr >= yy_start_stack_depth )
+- {
+- yy_size_t new_size;
+
+- yy_start_stack_depth += YY_START_STACK_INCR;
+- new_size = yy_start_stack_depth * sizeof( int );
++static void yy_fatal_error (yyconst char* msg )
++{
++ (void) fprintf( stderr, "%s\n", msg );
++ exit( YY_EXIT_FAILURE );
++}
+
+- if ( ! yy_start_stack )
+- yy_start_stack = (int *) yy_flex_alloc( new_size );
++/* Redefine yyless() so it works in section 3 code. */
+
+- else
+- yy_start_stack = (int *) yy_flex_realloc(
+- (void *) yy_start_stack, new_size );
++#undef yyless
++#define yyless(n) \
++ do \
++ { \
++ /* Undo effects of setting up yytext. */ \
++ int yyless_macro_arg = (n); \
++ YY_LESS_LINENO(yyless_macro_arg);\
++ yytext[yyleng] = (yy_hold_char); \
++ (yy_c_buf_p) = yytext + yyless_macro_arg; \
++ (yy_hold_char) = *(yy_c_buf_p); \
++ *(yy_c_buf_p) = '\0'; \
++ yyleng = yyless_macro_arg; \
++ } \
++ while ( 0 )
+
+- if ( ! yy_start_stack )
+- YY_FATAL_ERROR(
+- "out of memory expanding start-condition stack" );
+- }
++/* Accessor methods (get/set functions) to struct members. */
+
+- yy_start_stack[yy_start_stack_ptr++] = YY_START;
++/** Get the current line number.
++ *
++ */
++int yyget_lineno (void)
++{
++
++ return yylineno;
++}
+
+- BEGIN(new_state);
+- }
+-#endif
++/** Get the input stream.
++ *
++ */
++FILE *yyget_in (void)
++{
++ return yyin;
++}
+
++/** Get the output stream.
++ *
++ */
++FILE *yyget_out (void)
++{
++ return yyout;
++}
+
+-#ifndef YY_NO_POP_STATE
+-static void yy_pop_state()
+- {
+- if ( --yy_start_stack_ptr < 0 )
+- YY_FATAL_ERROR( "start-condition stack underflow" );
++/** Get the length of the current token.
++ *
++ */
++int yyget_leng (void)
++{
++ return yyleng;
++}
+
+- BEGIN(yy_start_stack[yy_start_stack_ptr]);
+- }
+-#endif
++/** Get the current token.
++ *
++ */
+
++char *yyget_text (void)
++{
++ return yytext;
++}
+
+-#ifndef YY_NO_TOP_STATE
+-static int yy_top_state()
+- {
+- return yy_start_stack[yy_start_stack_ptr - 1];
+- }
+-#endif
++/** Set the current line number.
++ * @param line_number
++ *
++ */
++void yyset_lineno (int line_number )
++{
++
++ yylineno = line_number;
++}
+
+-#ifndef YY_EXIT_FAILURE
+-#define YY_EXIT_FAILURE 2
+-#endif
++/** Set the input stream. This does not discard the current
++ * input buffer.
++ * @param in_str A readable stream.
++ *
++ * @see yy_switch_to_buffer
++ */
++void yyset_in (FILE * in_str )
++{
++ yyin = in_str ;
++}
+
+-#ifdef YY_USE_PROTOS
+-static void yy_fatal_error( yyconst char msg[] )
+-#else
+-static void yy_fatal_error( msg )
+-char msg[];
+-#endif
+- {
+- (void) fprintf( stderr, "%s\n", msg );
+- exit( YY_EXIT_FAILURE );
+- }
++void yyset_out (FILE * out_str )
++{
++ yyout = out_str ;
++}
+
++int yyget_debug (void)
++{
++ return yy_flex_debug;
++}
+
++void yyset_debug (int bdebug )
++{
++ yy_flex_debug = bdebug ;
++}
+
+-/* Redefine yyless() so it works in section 3 code. */
++/* yylex_destroy is for both reentrant and non-reentrant scanners. */
++int yylex_destroy (void)
++{
++
++ /* Pop the buffer stack, destroying each element. */
++ while(YY_CURRENT_BUFFER){
++ yy_delete_buffer(YY_CURRENT_BUFFER );
++ YY_CURRENT_BUFFER_LVALUE = NULL;
++ yypop_buffer_state();
++ }
+
+-#undef yyless
+-#define yyless(n) \
+- do \
+- { \
+- /* Undo effects of setting up yytext. */ \
+- yytext[yyleng] = yy_hold_char; \
+- yy_c_buf_p = yytext + n; \
+- yy_hold_char = *yy_c_buf_p; \
+- *yy_c_buf_p = '\0'; \
+- yyleng = n; \
+- } \
+- while ( 0 )
++ /* Destroy the stack itself. */
++ yyfree((yy_buffer_stack) );
++ (yy_buffer_stack) = NULL;
+
++ return 0;
++}
+
+-/* Internal utility routines. */
++/*
++ * Internal utility routines.
++ */
+
+ #ifndef yytext_ptr
+-#ifdef YY_USE_PROTOS
+-static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+-#else
+-static void yy_flex_strncpy( s1, s2, n )
+-char *s1;
+-yyconst char *s2;
+-int n;
+-#endif
+- {
++static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
++{
+ register int i;
+- for ( i = 0; i < n; ++i )
++ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+- }
++}
+ #endif
+
+ #ifdef YY_NEED_STRLEN
+-#ifdef YY_USE_PROTOS
+-static int yy_flex_strlen( yyconst char *s )
+-#else
+-static int yy_flex_strlen( s )
+-yyconst char *s;
+-#endif
+- {
++static int yy_flex_strlen (yyconst char * s )
++{
+ register int n;
+- for ( n = 0; s[n]; ++n )
++ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+- }
++}
+ #endif
+
+-
+-#ifdef YY_USE_PROTOS
+-static void *yy_flex_alloc( yy_size_t size )
+-#else
+-static void *yy_flex_alloc( size )
+-yy_size_t size;
+-#endif
+- {
++void *yyalloc (yy_size_t size )
++{
+ return (void *) malloc( size );
+- }
++}
+
+-#ifdef YY_USE_PROTOS
+-static void *yy_flex_realloc( void *ptr, yy_size_t size )
+-#else
+-static void *yy_flex_realloc( ptr, size )
+-void *ptr;
+-yy_size_t size;
+-#endif
+- {
++void *yyrealloc (void * ptr, yy_size_t size )
++{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+@@ -1631,30 +1794,34 @@
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+- }
++}
+
+-#ifdef YY_USE_PROTOS
+-static void yy_flex_free( void *ptr )
+-#else
+-static void yy_flex_free( ptr )
+-void *ptr;
+-#endif
+- {
+- free( ptr );
+- }
++void yyfree (void * ptr )
++{
++ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
++}
+
+-#if YY_MAIN
+-int main()
+- {
+- yylex();
+- return 0;
+- }
++#define YYTABLES_NAME "yytables"
++
++#undef YY_NEW_FILE
++#undef YY_FLUSH_BUFFER
++#undef yy_set_bol
++#undef yy_new_buffer
++#undef yy_set_interactive
++#undef yytext_ptr
++#undef YY_DO_BEFORE_ACTION
++
++#ifdef YY_DECL_IS_OURS
++#undef YY_DECL_IS_OURS
++#undef YY_DECL
+ #endif
+ #line 69 "ql_l.l"
+
+
+-void yyerror(char *s)
++
++void yyerror(const char *s)
+ {
+ fprintf(stderr,"line %d: %s near \"%s\"\n",lineno,s,yytext);
+ exit(1);
+ }
++
+--- linux-atm-2.4.1.orig/src/qgen/ql_y.c
++++ linux-atm-2.4.1/src/qgen/ql_y.c
+@@ -1,21 +1,87 @@
++/* A Bison parser, made by GNU Bison 1.875d. */
+
+-/* A Bison parser, made from ql_y.y
+- by GNU Bison version 1.28 */
++/* Skeleton parser for Yacc-like parsing with Bison,
++ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+-#define YYBISON 1 /* Identify Bison output. */
++ 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.
+
+-#define TOK_BREAK 257
+-#define TOK_CASE 258
+-#define TOK_DEF 259
+-#define TOK_DEFAULT 260
+-#define TOK_LENGTH 261
+-#define TOK_MULTI 262
+-#define TOK_RECOVER 263
+-#define TOK_ABORT 264
+-#define TOK_ID 265
+-#define TOK_INCLUDE 266
+-#define TOK_STRING 267
++ 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, when this file is copied by Bison into a
++ Bison output file, you may use that output file without restriction.
++ This special exception was added by the Free Software Foundation
++ in version 1.24 of Bison. */
++
++/* Written by Richard Stallman by simplifying the original so called
++ ``semantic'' parser. */
++
++/* All symbols defined below should begin with yy or YY, to avoid
++ infringing on user name space. This should be done even for local
++ variables, as they might otherwise be expanded by user macros.
++ There are some unavoidable exceptions within include files to
++ define necessary library symbols; they are noted "INFRINGES ON
++ USER NAME SPACE" below. */
++
++/* Identify Bison output. */
++#define YYBISON 1
++
++/* Skeleton name. */
++#define YYSKELETON_NAME "yacc.c"
++
++/* Pure parsers. */
++#define YYPURE 0
++
++/* Using locations. */
++#define YYLSP_NEEDED 0
++
++
++
++/* Tokens. */
++#ifndef YYTOKENTYPE
++# define YYTOKENTYPE
++ /* Put the tokens into the symbol table, so that GDB and other debuggers
++ know about them. */
++ enum yytokentype {
++ TOK_BREAK = 258,
++ TOK_CASE = 259,
++ TOK_DEF = 260,
++ TOK_DEFAULT = 261,
++ TOK_LENGTH = 262,
++ TOK_MULTI = 263,
++ TOK_RECOVER = 264,
++ TOK_ABORT = 265,
++ TOK_ID = 266,
++ TOK_INCLUDE = 267,
++ TOK_STRING = 268
++ };
++#endif
++#define TOK_BREAK 258
++#define TOK_CASE 259
++#define TOK_DEF 260
++#define TOK_DEFAULT 261
++#define TOK_LENGTH 262
++#define TOK_MULTI 263
++#define TOK_RECOVER 264
++#define TOK_ABORT 265
++#define TOK_ID 266
++#define TOK_INCLUDE 267
++#define TOK_STRING 268
++
++
++
++
++/* Copy the first part of user declarations. */
+ #line 1 "ql_y.y"
+
+ /* ql.y - Q.2931 data structures description language */
+@@ -36,6 +102,8 @@
+ #include "qgen.h"
+ #include "file.h"
+
++extern void yyerror(const char *s);
++
+
+ #define MAX_TOKEN 256
+ #define DEFAULT_NAMELIST_FILE "default.nl"
+@@ -77,9 +145,10 @@
+ for (walk = strchr(start,0)-1; walk > start && isspace(*walk); walk--)
+ *walk = 0;
+ if (*start == ':') {
+- if (!(searching = strcmp(start+1,name)))
++ if (!(searching = strcmp(start+1,name))) {
+ if (found) yyerror("multiple entries");
+ else found = 1;
++ }
+ continue;
+ }
+ if (searching) continue;
+@@ -154,8 +223,23 @@
+
+
+
+-#line 139 "ql_y.y"
+-typedef union {
++
++/* Enabling traces. */
++#ifndef YYDEBUG
++# define YYDEBUG 0
++#endif
++
++/* Enabling verbose error messages. */
++#ifdef YYERROR_VERBOSE
++# undef YYERROR_VERBOSE
++# define YYERROR_VERBOSE 1
++#else
++# define YYERROR_VERBOSE 0
++#endif
++
++#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
++#line 142 "ql_y.y"
++typedef union YYSTYPE {
+ const char *str;
+ int num;
+ FIELD *field;
+@@ -164,470 +248,762 @@
+ TAG *tag;
+ NAME_LIST *nlist;
+ } YYSTYPE;
+-#include <stdio.h>
++/* Line 191 of yacc.c. */
++#line 253 "y.tab.c"
++# define yystype YYSTYPE /* obsolescent; will be withdrawn */
++# define YYSTYPE_IS_DECLARED 1
++# define YYSTYPE_IS_TRIVIAL 1
++#endif
++
++
++
++/* Copy the second part of user declarations. */
++
++
++/* Line 214 of yacc.c. */
++#line 265 "y.tab.c"
++
++#if ! defined (yyoverflow) || YYERROR_VERBOSE
++
++# ifndef YYFREE
++# define YYFREE free
++# endif
++# ifndef YYMALLOC
++# define YYMALLOC malloc
++# endif
++
++/* The parser invokes alloca or malloc; define the necessary symbols. */
++
++# ifdef YYSTACK_USE_ALLOCA
++# if YYSTACK_USE_ALLOCA
++# define YYSTACK_ALLOC alloca
++# endif
++# else
++# if defined (alloca) || defined (_ALLOCA_H)
++# define YYSTACK_ALLOC alloca
++# else
++# ifdef __GNUC__
++# define YYSTACK_ALLOC __builtin_alloca
++# endif
++# endif
++# endif
++
++# ifdef YYSTACK_ALLOC
++ /* Pacify GCC's `empty if-body' warning. */
++# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
++# else
++# if defined (__STDC__) || defined (__cplusplus)
++# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
++# define YYSIZE_T size_t
++# endif
++# define YYSTACK_ALLOC YYMALLOC
++# define YYSTACK_FREE YYFREE
++# endif
++#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
++
++
++#if (! defined (yyoverflow) \
++ && (! defined (__cplusplus) \
++ || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
++
++/* A type that is properly aligned for any stack member. */
++union yyalloc
++{
++ short int yyss;
++ YYSTYPE yyvs;
++ };
++
++/* The size of the maximum gap between one aligned stack and the next. */
++# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
++
++/* The size of an array large to enough to hold all stacks, each with
++ N elements. */
++# define YYSTACK_BYTES(N) \
++ ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \
++ + YYSTACK_GAP_MAXIMUM)
++
++/* Copy COUNT objects from FROM to TO. The source and destination do
++ not overlap. */
++# ifndef YYCOPY
++# if defined (__GNUC__) && 1 < __GNUC__
++# define YYCOPY(To, From, Count) \
++ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
++# else
++# define YYCOPY(To, From, Count) \
++ do \
++ { \
++ register YYSIZE_T yyi; \
++ for (yyi = 0; yyi < (Count); yyi++) \
++ (To)[yyi] = (From)[yyi]; \
++ } \
++ while (0)
++# endif
++# endif
++
++/* Relocate STACK from its old location to the new one. The
++ local variables YYSIZE and YYSTACKSIZE give the old and new number of
++ elements in the stack, and YYPTR gives the new location of the
++ stack. Advance YYPTR to a properly aligned location for the next
++ stack. */
++# define YYSTACK_RELOCATE(Stack) \
++ do \
++ { \
++ YYSIZE_T yynewbytes; \
++ YYCOPY (&yyptr->Stack, Stack, yysize); \
++ Stack = &yyptr->Stack; \
++ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
++ yyptr += yynewbytes / sizeof (*yyptr); \
++ } \
++ while (0)
+
+-#ifndef __cplusplus
+-#ifndef __STDC__
+-#define const
+-#endif
+ #endif
+
++#if defined (__STDC__) || defined (__cplusplus)
++ typedef signed char yysigned_char;
++#else
++ typedef short int yysigned_char;
++#endif
+
+-
+-#define YYFINAL 86
+-#define YYFLAG -32768
+-#define YYNTBASE 23
+-
+-#define YYTRANSLATE(x) ((unsigned)(x) <= 267 ? yytranslate[x] : 47)
+-
+-static const char yytranslate[] = { 0,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 21, 18, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 22, 2, 17,
+- 14, 19, 2, 20, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 15, 2, 16, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
+- 7, 8, 9, 10, 11, 12, 13
++/* YYFINAL -- State number of the termination state. */
++#define YYFINAL 5
++/* YYLAST -- Last index in YYTABLE. */
++#define YYLAST 65
++
++/* YYNTOKENS -- Number of terminals. */
++#define YYNTOKENS 23
++/* YYNNTS -- Number of nonterminals. */
++#define YYNNTS 25
++/* YYNRULES -- Number of rules. */
++#define YYNRULES 46
++/* YYNRULES -- Number of states. */
++#define YYNSTATES 86
++
++/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
++#define YYUNDEFTOK 2
++#define YYMAXUTOK 268
++
++#define YYTRANSLATE(YYX) \
++ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
++
++/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
++static const unsigned char yytranslate[] =
++{
++ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 21, 18, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 22, 2,
++ 17, 14, 19, 2, 20, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 15, 2, 16, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
++ 5, 6, 7, 8, 9, 10, 11, 12, 13
+ };
+
+-#if YYDEBUG != 0
+-static const short yyprhs[] = { 0,
+- 0, 4, 5, 8, 9, 12, 17, 18, 21, 23,
+- 27, 30, 31, 34, 40, 41, 43, 47, 53, 54,
+- 57, 59, 60, 63, 64, 67, 69, 74, 79, 83,
+- 84, 87, 88, 90, 91, 97, 98, 105, 106, 112,
+- 113, 120, 121, 124, 125
++#if YYDEBUG
++/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
++ YYRHS. */
++static const unsigned char yyprhs[] =
++{
++ 0, 0, 3, 7, 8, 11, 12, 15, 20, 21,
++ 24, 26, 30, 33, 34, 37, 43, 44, 46, 50,
++ 56, 57, 60, 62, 63, 66, 67, 70, 72, 77,
++ 82, 86, 87, 90, 91, 93, 94, 100, 101, 108,
++ 109, 115, 116, 123, 124, 127, 128
+ };
+
+-static const short yyrhs[] = { 24,
+- 25, 29, 0, 0, 12, 24, 0, 0, 25, 26,
+- 0, 5, 11, 14, 29, 0, 0, 28, 29, 0,
+- 11, 0, 15, 30, 16, 0, 10, 11, 0, 0,
+- 31, 30, 0, 32, 11, 40, 17, 33, 0, 0,
+- 3, 0, 18, 35, 19, 0, 35, 34, 36, 19,
+- 37, 0, 0, 20, 35, 0, 11, 0, 0, 21,
+- 11, 0, 0, 14, 38, 0, 11, 0, 4, 15,
+- 41, 16, 0, 8, 15, 43, 16, 0, 39, 7,
+- 29, 0, 0, 9, 11, 0, 0, 13, 0, 0,
+- 6, 11, 45, 46, 29, 0, 0, 11, 45, 46,
+- 29, 42, 41, 0, 0, 6, 11, 45, 46, 27,
+- 0, 0, 11, 45, 46, 27, 44, 43, 0, 0,
+- 22, 11, 0, 0, 21, 11, 46, 0
++/* YYRHS -- A `-1'-separated list of the rules' RHS. */
++static const yysigned_char yyrhs[] =
++{
++ 24, 0, -1, 25, 26, 30, -1, -1, 12, 25,
++ -1, -1, 26, 27, -1, 5, 11, 14, 30, -1,
++ -1, 29, 30, -1, 11, -1, 15, 31, 16, -1,
++ 10, 11, -1, -1, 32, 31, -1, 33, 11, 41,
++ 17, 34, -1, -1, 3, -1, 18, 36, 19, -1,
++ 36, 35, 37, 19, 38, -1, -1, 20, 36, -1,
++ 11, -1, -1, 21, 11, -1, -1, 14, 39, -1,
++ 11, -1, 4, 15, 42, 16, -1, 8, 15, 44,
++ 16, -1, 40, 7, 30, -1, -1, 9, 11, -1,
++ -1, 13, -1, -1, 6, 11, 46, 47, 30, -1,
++ -1, 11, 46, 47, 30, 43, 42, -1, -1, 6,
++ 11, 46, 47, 28, -1, -1, 11, 46, 47, 28,
++ 45, 44, -1, -1, 22, 11, -1, -1, 21, 11,
++ 47, -1
+ };
+
+-#endif
+-
+-#if YYDEBUG != 0
+-static const short yyrline[] = { 0,
+- 163, 175, 176, 184, 185, 188, 202, 207, 212, 231,
+- 236, 243, 247, 254, 278, 282, 288, 301, 318, 322,
+- 329, 339, 343, 350, 354, 360, 367, 374, 380, 390,
+- 394, 400, 404, 410, 414, 431, 437, 454, 458, 474,
+- 480, 497, 501, 507, 511
++/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
++static const unsigned short int yyrline[] =
++{
++ 0, 167, 167, 178, 179, 187, 188, 192, 206, 206,
++ 216, 234, 239, 247, 250, 258, 282, 285, 292, 304,
++ 323, 326, 334, 344, 347, 355, 358, 365, 371, 378,
++ 384, 395, 398, 405, 408, 415, 418, 436, 435, 459,
++ 462, 479, 478, 502, 505, 512, 515
+ };
+ #endif
+
+-
+-#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
+-
+-static const char * const yytname[] = { "$","error","$undefined.","TOK_BREAK",
+-"TOK_CASE","TOK_DEF","TOK_DEFAULT","TOK_LENGTH","TOK_MULTI","TOK_RECOVER","TOK_ABORT",
+-"TOK_ID","TOK_INCLUDE","TOK_STRING","'='","'{'","'}'","'<'","'-'","'>'","'@'",
+-"','","':'","all","includes","structures","structure","rep_block","@1","block",
+-"fields","field","opt_break","field_cont","opt_pos","decimal","opt_more","opt_val",
+-"value","opt_recover","opt_name_list","tags","@2","rep_tags","@3","opt_id","list", NULL
++#if YYDEBUG || YYERROR_VERBOSE
++/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
++ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
++static const char *const yytname[] =
++{
++ "$end", "error", "$undefined", "TOK_BREAK", "TOK_CASE", "TOK_DEF",
++ "TOK_DEFAULT", "TOK_LENGTH", "TOK_MULTI", "TOK_RECOVER", "TOK_ABORT",
++ "TOK_ID", "TOK_INCLUDE", "TOK_STRING", "'='", "'{'", "'}'", "'<'", "'-'",
++ "'>'", "'@'", "','", "':'", "$accept", "all", "includes", "structures",
++ "structure", "rep_block", "@1", "block", "fields", "field", "opt_break",
++ "field_cont", "opt_pos", "decimal", "opt_more", "opt_val", "value",
++ "opt_recover", "opt_name_list", "tags", "@2", "rep_tags", "@3", "opt_id",
++ "list", 0
+ };
+ #endif
+
+-static const short yyr1[] = { 0,
+- 23, 24, 24, 25, 25, 26, 28, 27, 29, 29,
+- 29, 30, 30, 31, 32, 32, 33, 33, 34, 34,
+- 35, 36, 36, 37, 37, 38, 38, 38, 38, 39,
+- 39, 40, 40, 41, 41, 42, 41, 43, 43, 44,
+- 43, 45, 45, 46, 46
++# ifdef YYPRINT
++/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
++ token YYLEX-NUM. */
++static const unsigned short int yytoknum[] =
++{
++ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
++ 265, 266, 267, 268, 61, 123, 125, 60, 45, 62,
++ 64, 44, 58
+ };
++# endif
+
+-static const short yyr2[] = { 0,
+- 3, 0, 2, 0, 2, 4, 0, 2, 1, 3,
+- 2, 0, 2, 5, 0, 1, 3, 5, 0, 2,
+- 1, 0, 2, 0, 2, 1, 4, 4, 3, 0,
+- 2, 0, 1, 0, 5, 0, 6, 0, 5, 0,
+- 6, 0, 2, 0, 3
++/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
++static const unsigned char yyr1[] =
++{
++ 0, 23, 24, 25, 25, 26, 26, 27, 29, 28,
++ 30, 30, 30, 31, 31, 32, 33, 33, 34, 34,
++ 35, 35, 36, 37, 37, 38, 38, 39, 39, 39,
++ 39, 40, 40, 41, 41, 42, 42, 43, 42, 44,
++ 44, 45, 44, 46, 46, 47, 47
+ };
+
+-static const short yydefact[] = { 2,
+- 2, 4, 3, 0, 0, 0, 9, 12, 5, 1,
+- 0, 11, 16, 0, 12, 0, 0, 10, 13, 32,
+- 6, 33, 0, 0, 21, 0, 14, 19, 0, 0,
+- 22, 17, 20, 0, 0, 23, 24, 30, 18, 0,
+- 0, 0, 26, 25, 0, 34, 38, 31, 0, 0,
+- 42, 0, 0, 42, 0, 29, 42, 0, 44, 27,
+- 42, 44, 28, 44, 43, 0, 0, 44, 7, 0,
+- 44, 36, 7, 40, 0, 35, 45, 34, 39, 38,
+- 8, 37, 41, 0, 0, 0
++/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
++static const unsigned char yyr2[] =
++{
++ 0, 2, 3, 0, 2, 0, 2, 4, 0, 2,
++ 1, 3, 2, 0, 2, 5, 0, 1, 3, 5,
++ 0, 2, 1, 0, 2, 0, 2, 1, 4, 4,
++ 3, 0, 2, 0, 1, 0, 5, 0, 6, 0,
++ 5, 0, 6, 0, 2, 0, 3
+ };
+
+-static const short yydefgoto[] = { 84,
+- 2, 4, 9, 74, 75, 10, 14, 15, 16, 27,
+- 31, 28, 35, 39, 44, 45, 23, 52, 78, 55,
+- 80, 59, 67
++/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
++ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
++ means the default is an error. */
++static const unsigned char yydefact[] =
++{
++ 3, 3, 0, 5, 4, 1, 0, 0, 0, 10,
++ 13, 6, 2, 0, 12, 17, 0, 13, 0, 0,
++ 11, 14, 33, 7, 34, 0, 0, 22, 0, 15,
++ 20, 0, 0, 23, 18, 21, 0, 0, 24, 25,
++ 31, 19, 0, 0, 0, 27, 26, 0, 35, 39,
++ 32, 0, 0, 43, 0, 0, 43, 0, 30, 43,
++ 0, 45, 28, 43, 45, 29, 45, 44, 0, 0,
++ 45, 8, 0, 45, 37, 8, 41, 0, 36, 46,
++ 35, 40, 39, 9, 38, 42
+ };
+
+-static const short yypact[] = { -8,
+- -8,-32768,-32768, -4, 3, 17,-32768, -1,-32768,-32768,
+- 20,-32768,-32768, 21, -1, 22, 11,-32768,-32768, 23,
+--32768,-32768, 24, -3,-32768, 27,-32768, 15, 25, 27,
+- 26,-32768,-32768, 28, 29,-32768, 31, 9,-32768, 34,
+- 36, 32,-32768,-32768, 33, 18, 19,-32768, 11, 35,
+- 30, 38, 44, 30, 40,-32768, 30, 46, 39,-32768,
+- 30, 39,-32768, 39,-32768, 48, 11, 39,-32768, 11,
+- 39,-32768,-32768,-32768, 11,-32768,-32768, 18,-32768, 19,
+--32768,-32768,-32768, 42, 61,-32768
++/* YYDEFGOTO[NTERM-NUM]. */
++static const yysigned_char yydefgoto[] =
++{
++ -1, 2, 3, 6, 11, 76, 77, 12, 16, 17,
++ 18, 29, 33, 30, 37, 41, 46, 47, 25, 54,
++ 80, 57, 82, 61, 69
+ };
+
+-static const short yypgoto[] = {-32768,
+- 62,-32768,-32768, -11,-32768, -17, 49,-32768,-32768,-32768,
+--32768, 1,-32768,-32768,-32768,-32768,-32768, -13,-32768, -14,
+--32768, -38, -59
++/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
++ STATE-NUM. */
++#define YYPACT_NINF -62
++static const yysigned_char yypact[] =
++{
++ -8, -8, 14, -62, -62, -62, -4, 16, 17, -62,
++ -1, -62, -62, 20, -62, -62, 21, -1, 22, 11,
++ -62, -62, 23, -62, -62, 24, -3, -62, 27, -62,
++ 25, 28, 27, 30, -62, -62, 29, 33, -62, 32,
++ 9, -62, 34, 39, 31, -62, -62, 36, 18, 19,
++ -62, 11, 37, 35, 40, 44, 35, 43, -62, 35,
++ 49, 41, -62, 35, 41, -62, 41, -62, 50, 11,
++ 41, -62, 11, 41, -62, -62, -62, 11, -62, -62,
++ 18, -62, 19, -62, -62, -62
+ };
+
+-
+-#define YYLAST 66
+-
+-
+-static const short yytable[] = { 21,
+- 5, 13, 69, 1, 70, 6, 7, 25, 73, -15,
+- 8, 77, 40, 11, 26, 62, 41, 42, 64, 43,
+- 6, 7, 68, 50, 53, 8, 29, 12, 51, 54,
+- 33, 56, 20, 17, 30, 22, 18, 25, 36, 49,
+- 24, 85, 48, 32, 38, 57, 34, 37, 46, 72,
+- 47, 58, 76, 60, 61, 63, 65, 81, 71, 66,
+- 86, 79, 3, 19, 82, 83
++/* YYPGOTO[NTERM-NUM]. */
++static const yysigned_char yypgoto[] =
++{
++ -62, -62, 38, -62, -62, -31, -62, -19, 46, -62,
++ -62, -62, -62, 3, -62, -62, -62, -62, -62, -16,
++ -62, -17, -62, -40, -61
+ };
+
+-static const short yycheck[] = { 17,
+- 5, 3, 62, 12, 64, 10, 11, 11, 68, 11,
+- 15, 71, 4, 11, 18, 54, 8, 9, 57, 11,
+- 10, 11, 61, 6, 6, 15, 26, 11, 11, 11,
+- 30, 49, 11, 14, 20, 13, 16, 11, 11, 7,
+- 17, 0, 11, 19, 14, 11, 21, 19, 15, 67,
+- 15, 22, 70, 16, 11, 16, 11, 75, 11, 21,
+- 0, 73, 1, 15, 78, 80
++/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
++ positive, shift that token. If negative, reduce the rule which
++ number is the opposite. If zero, do what YYDEFACT says.
++ If YYTABLE_NINF, syntax error. */
++#define YYTABLE_NINF -17
++static const yysigned_char yytable[] =
++{
++ 23, 7, 15, 71, 1, 72, 8, 9, 27, 75,
++ -16, 10, 79, 42, 5, 28, 64, 43, 44, 66,
++ 45, 8, 9, 70, 52, 55, 10, 13, 14, 53,
++ 56, 31, 58, 22, 19, 35, 24, 20, 27, 4,
++ 38, 26, 50, 51, 81, 32, 40, 34, 59, 48,
++ 74, 36, 39, 78, 49, 63, 62, 60, 83, 65,
++ 67, 73, 68, 21, 84, 85
+ };
+-/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
+-#line 3 "/usr/lib/bison.simple"
+-/* This file comes from bison-1.28. */
+
+-/* Skeleton output parser for bison,
+- Copyright (C) 1984, 1989, 1990 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. */
+-
+-/* As a special exception, when this file is copied by Bison into a
+- Bison output file, you may use that output file without restriction.
+- This special exception was added by the Free Software Foundation
+- in version 1.24 of Bison. */
++static const unsigned char yycheck[] =
++{
++ 19, 5, 3, 64, 12, 66, 10, 11, 11, 70,
++ 11, 15, 73, 4, 0, 18, 56, 8, 9, 59,
++ 11, 10, 11, 63, 6, 6, 15, 11, 11, 11,
++ 11, 28, 51, 11, 14, 32, 13, 16, 11, 1,
++ 11, 17, 11, 7, 75, 20, 14, 19, 11, 15,
++ 69, 21, 19, 72, 15, 11, 16, 22, 77, 16,
++ 11, 11, 21, 17, 80, 82
++};
+
+-/* This is the parser code that is written into each bison parser
+- when the %semantic_parser declaration is not specified in the grammar.
+- It was written by Richard Stallman by simplifying the hairy parser
+- used when %semantic_parser is specified. */
+-
+-#ifndef YYSTACK_USE_ALLOCA
+-#ifdef alloca
+-#define YYSTACK_USE_ALLOCA
+-#else /* alloca not defined */
+-#ifdef __GNUC__
+-#define YYSTACK_USE_ALLOCA
+-#define alloca __builtin_alloca
+-#else /* not GNU C. */
+-#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
+-#define YYSTACK_USE_ALLOCA
+-#include <alloca.h>
+-#else /* not sparc */
+-/* We think this test detects Watcom and Microsoft C. */
+-/* This used to test MSDOS, but that is a bad idea
+- since that symbol is in the user namespace. */
+-#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
+-#if 0 /* No need for malloc.h, which pollutes the namespace;
+- instead, just don't use alloca. */
+-#include <malloc.h>
+-#endif
+-#else /* not MSDOS, or __TURBOC__ */
+-#if defined(_AIX)
+-/* I don't know what this was needed for, but it pollutes the namespace.
+- So I turned it off. rms, 2 May 1997. */
+-/* #include <malloc.h> */
+- #pragma alloca
+-#define YYSTACK_USE_ALLOCA
+-#else /* not MSDOS, or __TURBOC__, or _AIX */
+-#if 0
+-#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
+- and on HPUX 10. Eventually we can turn this on. */
+-#define YYSTACK_USE_ALLOCA
+-#define alloca __builtin_alloca
+-#endif /* __hpux */
+-#endif
+-#endif /* not _AIX */
+-#endif /* not MSDOS, or __TURBOC__ */
+-#endif /* not sparc */
+-#endif /* not GNU C */
+-#endif /* alloca not defined */
+-#endif /* YYSTACK_USE_ALLOCA not defined */
++/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
++ symbol of state STATE-NUM. */
++static const unsigned char yystos[] =
++{
++ 0, 12, 24, 25, 25, 0, 26, 5, 10, 11,
++ 15, 27, 30, 11, 11, 3, 31, 32, 33, 14,
++ 16, 31, 11, 30, 13, 41, 17, 11, 18, 34,
++ 36, 36, 20, 35, 19, 36, 21, 37, 11, 19,
++ 14, 38, 4, 8, 9, 11, 39, 40, 15, 15,
++ 11, 7, 6, 11, 42, 6, 11, 44, 30, 11,
++ 22, 46, 16, 11, 46, 16, 46, 11, 21, 47,
++ 46, 47, 47, 11, 30, 47, 28, 29, 30, 47,
++ 43, 28, 45, 30, 42, 44
++};
+
+-#ifdef YYSTACK_USE_ALLOCA
+-#define YYSTACK_ALLOC alloca
+-#else
+-#define YYSTACK_ALLOC malloc
++#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
++# define YYSIZE_T __SIZE_TYPE__
++#endif
++#if ! defined (YYSIZE_T) && defined (size_t)
++# define YYSIZE_T size_t
++#endif
++#if ! defined (YYSIZE_T)
++# if defined (__STDC__) || defined (__cplusplus)
++# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
++# define YYSIZE_T size_t
++# endif
++#endif
++#if ! defined (YYSIZE_T)
++# define YYSIZE_T unsigned int
+ #endif
+-
+-/* Note: there must be only one dollar sign in this file.
+- It is replaced by the list of actions, each action
+- as one case of the switch. */
+
+ #define yyerrok (yyerrstatus = 0)
+ #define yyclearin (yychar = YYEMPTY)
+-#define YYEMPTY -2
++#define YYEMPTY (-2)
+ #define YYEOF 0
++
+ #define YYACCEPT goto yyacceptlab
+-#define YYABORT goto yyabortlab
+-#define YYERROR goto yyerrlab1
+-/* Like YYERROR except do call yyerror.
+- This remains here temporarily to ease the
+- transition to the new meaning of YYERROR, for GCC.
++#define YYABORT goto yyabortlab
++#define YYERROR goto yyerrorlab
++
++
++/* Like YYERROR except do call yyerror. This remains here temporarily
++ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
++
+ #define YYFAIL goto yyerrlab
++
+ #define YYRECOVERING() (!!yyerrstatus)
+-#define YYBACKUP(token, value) \
++
++#define YYBACKUP(Token, Value) \
+ do \
+ if (yychar == YYEMPTY && yylen == 1) \
+- { yychar = (token), yylval = (value); \
+- yychar1 = YYTRANSLATE (yychar); \
++ { \
++ yychar = (Token); \
++ yylval = (Value); \
++ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+- { yyerror ("syntax error: cannot back up"); YYERROR; } \
++ { \
++ yyerror ("syntax error: cannot back up");\
++ YYERROR; \
++ } \
+ while (0)
+
+ #define YYTERROR 1
+ #define YYERRCODE 256
+
+-#ifndef YYPURE
+-#define YYLEX yylex()
+-#endif
++/* YYLLOC_DEFAULT -- Compute the default location (before the actions
++ are run). */
+
+-#ifdef YYPURE
+-#ifdef YYLSP_NEEDED
+-#ifdef YYLEX_PARAM
+-#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
+-#else
+-#define YYLEX yylex(&yylval, &yylloc)
++#ifndef YYLLOC_DEFAULT
++# define YYLLOC_DEFAULT(Current, Rhs, N) \
++ ((Current).first_line = (Rhs)[1].first_line, \
++ (Current).first_column = (Rhs)[1].first_column, \
++ (Current).last_line = (Rhs)[N].last_line, \
++ (Current).last_column = (Rhs)[N].last_column)
+ #endif
+-#else /* not YYLSP_NEEDED */
++
++/* YYLEX -- calling `yylex' with the right arguments. */
++
+ #ifdef YYLEX_PARAM
+-#define YYLEX yylex(&yylval, YYLEX_PARAM)
++# define YYLEX yylex (YYLEX_PARAM)
+ #else
+-#define YYLEX yylex(&yylval)
+-#endif
+-#endif /* not YYLSP_NEEDED */
++# define YYLEX yylex ()
+ #endif
+
+-/* If nonreentrant, generate the variables here */
++/* Enable debugging if requested. */
++#if YYDEBUG
+
+-#ifndef YYPURE
++# ifndef YYFPRINTF
++# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
++# define YYFPRINTF fprintf
++# endif
++
++# define YYDPRINTF(Args) \
++do { \
++ if (yydebug) \
++ YYFPRINTF Args; \
++} while (0)
++
++# define YYDSYMPRINT(Args) \
++do { \
++ if (yydebug) \
++ yysymprint Args; \
++} while (0)
++
++# define YYDSYMPRINTF(Title, Token, Value, Location) \
++do { \
++ if (yydebug) \
++ { \
++ YYFPRINTF (stderr, "%s ", Title); \
++ yysymprint (stderr, \
++ Token, Value); \
++ YYFPRINTF (stderr, "\n"); \
++ } \
++} while (0)
+
+-int yychar; /* the lookahead symbol */
+-YYSTYPE yylval; /* the semantic value of the */
+- /* lookahead symbol */
++/*------------------------------------------------------------------.
++| yy_stack_print -- Print the state stack from its BOTTOM up to its |
++| TOP (included). |
++`------------------------------------------------------------------*/
+
+-#ifdef YYLSP_NEEDED
+-YYLTYPE yylloc; /* location data for the lookahead */
+- /* symbol */
++#if defined (__STDC__) || defined (__cplusplus)
++static void
++yy_stack_print (short int *bottom, short int *top)
++#else
++static void
++yy_stack_print (bottom, top)
++ short int *bottom;
++ short int *top;
+ #endif
++{
++ YYFPRINTF (stderr, "Stack now");
++ for (/* Nothing. */; bottom <= top; ++bottom)
++ YYFPRINTF (stderr, " %d", *bottom);
++ YYFPRINTF (stderr, "\n");
++}
+
+-int yynerrs; /* number of parse errors so far */
+-#endif /* not YYPURE */
++# define YY_STACK_PRINT(Bottom, Top) \
++do { \
++ if (yydebug) \
++ yy_stack_print ((Bottom), (Top)); \
++} while (0)
+
+-#if YYDEBUG != 0
+-int yydebug; /* nonzero means print parse trace */
+-/* Since this is uninitialized, it does not stop multiple parsers
+- from coexisting. */
++
++/*------------------------------------------------.
++| Report that the YYRULE is going to be reduced. |
++`------------------------------------------------*/
++
++#if defined (__STDC__) || defined (__cplusplus)
++static void
++yy_reduce_print (int yyrule)
++#else
++static void
++yy_reduce_print (yyrule)
++ int yyrule;
+ #endif
++{
++ int yyi;
++ unsigned int yylno = yyrline[yyrule];
++ YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
++ yyrule - 1, yylno);
++ /* Print the symbols being reduced, and their result. */
++ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
++ YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
++ YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
++}
+
+-/* YYINITDEPTH indicates the initial size of the parser's stacks */
++# define YY_REDUCE_PRINT(Rule) \
++do { \
++ if (yydebug) \
++ yy_reduce_print (Rule); \
++} while (0)
++
++/* Nonzero means print parse trace. It is left uninitialized so that
++ multiple parsers can coexist. */
++int yydebug;
++#else /* !YYDEBUG */
++# define YYDPRINTF(Args)
++# define YYDSYMPRINT(Args)
++# define YYDSYMPRINTF(Title, Token, Value, Location)
++# define YY_STACK_PRINT(Bottom, Top)
++# define YY_REDUCE_PRINT(Rule)
++#endif /* !YYDEBUG */
+
++
++/* YYINITDEPTH -- initial size of the parser's stacks. */
+ #ifndef YYINITDEPTH
+-#define YYINITDEPTH 200
++# define YYINITDEPTH 200
+ #endif
+
+-/* YYMAXDEPTH is the maximum size the stacks can grow to
+- (effective only if the built-in stack extension method is used). */
++/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
++ if the built-in stack extension method is used).
++
++ Do not make this value too large; the results are undefined if
++ SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
++ evaluated with infinite-precision integer arithmetic. */
+
+-#if YYMAXDEPTH == 0
+-#undef YYMAXDEPTH
++#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
++# undef YYMAXDEPTH
+ #endif
+
+ #ifndef YYMAXDEPTH
+-#define YYMAXDEPTH 10000
++# define YYMAXDEPTH 10000
+ #endif
++
+
+-/* Define __yy_memcpy. Note that the size argument
+- should be passed with type unsigned int, because that is what the non-GCC
+- definitions require. With GCC, __builtin_memcpy takes an arg
+- of type size_t, but it can handle unsigned int. */
+-
+-#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
+-#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
+-#else /* not GNU C or C++ */
+-#ifndef __cplusplus
+
+-/* This is the most reliable way to avoid incompatibilities
+- in available built-in functions on various systems. */
+-static void
+-__yy_memcpy (to, from, count)
+- char *to;
+- char *from;
+- unsigned int count;
+-{
+- register char *f = from;
+- register char *t = to;
+- register int i = count;
++#if YYERROR_VERBOSE
++
++# ifndef yystrlen
++# if defined (__GLIBC__) && defined (_STRING_H)
++# define yystrlen strlen
++# else
++/* Return the length of YYSTR. */
++static YYSIZE_T
++# if defined (__STDC__) || defined (__cplusplus)
++yystrlen (const char *yystr)
++# else
++yystrlen (yystr)
++ const char *yystr;
++# endif
++{
++ register const char *yys = yystr;
++
++ while (*yys++ != '\0')
++ continue;
+
+- while (i-- > 0)
+- *t++ = *f++;
++ return yys - yystr - 1;
+ }
++# endif
++# endif
+
+-#else /* __cplusplus */
++# ifndef yystpcpy
++# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
++# define yystpcpy stpcpy
++# else
++/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
++ YYDEST. */
++static char *
++# if defined (__STDC__) || defined (__cplusplus)
++yystpcpy (char *yydest, const char *yysrc)
++# else
++yystpcpy (yydest, yysrc)
++ char *yydest;
++ const char *yysrc;
++# endif
++{
++ register char *yyd = yydest;
++ register const char *yys = yysrc;
++
++ while ((*yyd++ = *yys++) != '\0')
++ continue;
++
++ return yyd - 1;
++}
++# endif
++# endif
++
++#endif /* !YYERROR_VERBOSE */
++
++
++
++#if YYDEBUG
++/*--------------------------------.
++| Print this symbol on YYOUTPUT. |
++`--------------------------------*/
+
+-/* This is the most reliable way to avoid incompatibilities
+- in available built-in functions on various systems. */
++#if defined (__STDC__) || defined (__cplusplus)
+ static void
+-__yy_memcpy (char *to, char *from, unsigned int count)
++yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
++#else
++static void
++yysymprint (yyoutput, yytype, yyvaluep)
++ FILE *yyoutput;
++ int yytype;
++ YYSTYPE *yyvaluep;
++#endif
+ {
+- register char *t = to;
+- register char *f = from;
+- register int i = count;
++ /* Pacify ``unused variable'' warnings. */
++ (void) yyvaluep;
++
++ if (yytype < YYNTOKENS)
++ {
++ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
++# ifdef YYPRINT
++ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
++# endif
++ }
++ else
++ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+- while (i-- > 0)
+- *t++ = *f++;
++ switch (yytype)
++ {
++ default:
++ break;
++ }
++ YYFPRINTF (yyoutput, ")");
+ }
+
++#endif /* ! YYDEBUG */
++/*-----------------------------------------------.
++| Release the memory associated to this symbol. |
++`-----------------------------------------------*/
++
++#if defined (__STDC__) || defined (__cplusplus)
++static void
++yydestruct (int yytype, YYSTYPE *yyvaluep)
++#else
++static void
++yydestruct (yytype, yyvaluep)
++ int yytype;
++ YYSTYPE *yyvaluep;
+ #endif
+-#endif
++{
++ /* Pacify ``unused variable'' warnings. */
++ (void) yyvaluep;
++
++ switch (yytype)
++ {
++
++ default:
++ break;
++ }
++}
+
+-#line 217 "/usr/lib/bison.simple"
+
+-/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+- into yyparse. The argument should have type void *.
+- It should actually point to an object.
+- Grammar actions can access the variable by casting it
+- to the proper pointer type. */
++/* Prevent warnings from -Wmissing-prototypes. */
+
+ #ifdef YYPARSE_PARAM
+-#ifdef __cplusplus
+-#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+-#define YYPARSE_PARAM_DECL
+-#else /* not __cplusplus */
+-#define YYPARSE_PARAM_ARG YYPARSE_PARAM
+-#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+-#endif /* not __cplusplus */
+-#else /* not YYPARSE_PARAM */
+-#define YYPARSE_PARAM_ARG
+-#define YYPARSE_PARAM_DECL
+-#endif /* not YYPARSE_PARAM */
++# if defined (__STDC__) || defined (__cplusplus)
++int yyparse (void *YYPARSE_PARAM);
++# else
++int yyparse ();
++# endif
++#else /* ! YYPARSE_PARAM */
++#if defined (__STDC__) || defined (__cplusplus)
++int yyparse (void);
++#else
++int yyparse ();
++#endif
++#endif /* ! YYPARSE_PARAM */
++
++
++
++/* The lookahead symbol. */
++int yychar;
++
++/* The semantic value of the lookahead symbol. */
++YYSTYPE yylval;
++
++/* Number of syntax errors so far. */
++int yynerrs;
++
++
++
++/*----------.
++| yyparse. |
++`----------*/
+
+-/* Prevent warning if -Wstrict-prototypes. */
+-#ifdef __GNUC__
+ #ifdef YYPARSE_PARAM
+-int yyparse (void *);
++# if defined (__STDC__) || defined (__cplusplus)
++int yyparse (void *YYPARSE_PARAM)
++# else
++int yyparse (YYPARSE_PARAM)
++ void *YYPARSE_PARAM;
++# endif
++#else /* ! YYPARSE_PARAM */
++#if defined (__STDC__) || defined (__cplusplus)
++int
++yyparse (void)
+ #else
+-int yyparse (void);
++int
++yyparse ()
++
+ #endif
+ #endif
+-
+-int
+-yyparse(YYPARSE_PARAM_ARG)
+- YYPARSE_PARAM_DECL
+ {
++
+ register int yystate;
+ register int yyn;
+- register short *yyssp;
++ int yyresult;
++ /* Number of tokens to shift before error messages enabled. */
++ int yyerrstatus;
++ /* Lookahead token as an internal (translated) token number. */
++ int yytoken = 0;
++
++ /* Three stacks and their tools:
++ `yyss': related to states,
++ `yyvs': related to semantic values,
++ `yyls': related to locations.
++
++ Refer to the stacks thru separate pointers, to allow yyoverflow
++ to reallocate them elsewhere. */
++
++ /* The state stack. */
++ short int yyssa[YYINITDEPTH];
++ short int *yyss = yyssa;
++ register short int *yyssp;
++
++ /* The semantic value stack. */
++ YYSTYPE yyvsa[YYINITDEPTH];
++ YYSTYPE *yyvs = yyvsa;
+ register YYSTYPE *yyvsp;
+- int yyerrstatus; /* number of tokens to shift before error messages enabled */
+- int yychar1 = 0; /* lookahead token as an internal (translated) token number */
+
+- short yyssa[YYINITDEPTH]; /* the state stack */
+- YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
+
+- short *yyss = yyssa; /* refer to the stacks thru separate pointers */
+- YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
+
+-#ifdef YYLSP_NEEDED
+- YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
+- YYLTYPE *yyls = yylsa;
+- YYLTYPE *yylsp;
+-
+-#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
+-#else
+ #define YYPOPSTACK (yyvsp--, yyssp--)
+-#endif
+
+- int yystacksize = YYINITDEPTH;
+- int yyfree_stacks = 0;
++ YYSIZE_T yystacksize = YYINITDEPTH;
+
+-#ifdef YYPURE
+- int yychar;
+- YYSTYPE yylval;
+- int yynerrs;
+-#ifdef YYLSP_NEEDED
+- YYLTYPE yylloc;
+-#endif
+-#endif
++ /* The variables used to return semantic value and location from the
++ action routines. */
++ YYSTYPE yyval;
+
+- YYSTYPE yyval; /* the variable used to return */
+- /* semantic values from the action */
+- /* routines */
+
++ /* When reducing, the number of symbols on the RHS of the reduced
++ rule. */
+ int yylen;
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Starting parse\n");
+-#endif
++ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+@@ -639,110 +1015,97 @@
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+- yyssp = yyss - 1;
++ yyssp = yyss;
+ yyvsp = yyvs;
+-#ifdef YYLSP_NEEDED
+- yylsp = yyls;
+-#endif
+
+-/* Push a new state, which is found in yystate . */
+-/* In all cases, when you get here, the value and location stacks
+- have just been pushed. so pushing a state here evens the stacks. */
+-yynewstate:
+
+- *++yyssp = yystate;
++ goto yysetstate;
+
+- if (yyssp >= yyss + yystacksize - 1)
+- {
+- /* Give user a chance to reallocate the stack */
+- /* Use copies of these so that the &'s don't force the real ones into memory. */
+- YYSTYPE *yyvs1 = yyvs;
+- short *yyss1 = yyss;
+-#ifdef YYLSP_NEEDED
+- YYLTYPE *yyls1 = yyls;
+-#endif
++/*------------------------------------------------------------.
++| yynewstate -- Push a new state, which is found in yystate. |
++`------------------------------------------------------------*/
++ yynewstate:
++ /* In all cases, when you get here, the value and location stacks
++ have just been pushed. so pushing a state here evens the stacks.
++ */
++ yyssp++;
+
++ yysetstate:
++ *yyssp = yystate;
++
++ if (yyss + yystacksize - 1 <= yyssp)
++ {
+ /* Get the current used size of the three stacks, in elements. */
+- int size = yyssp - yyss + 1;
++ YYSIZE_T yysize = yyssp - yyss + 1;
+
+ #ifdef yyoverflow
+- /* Each stack pointer address is followed by the size of
+- the data in use in that stack, in bytes. */
+-#ifdef YYLSP_NEEDED
+- /* This used to be a conditional around just the two extra args,
+- but that might be undefined if yyoverflow is a macro. */
+- yyoverflow("parser stack overflow",
+- &yyss1, size * sizeof (*yyssp),
+- &yyvs1, size * sizeof (*yyvsp),
+- &yyls1, size * sizeof (*yylsp),
+- &yystacksize);
+-#else
+- yyoverflow("parser stack overflow",
+- &yyss1, size * sizeof (*yyssp),
+- &yyvs1, size * sizeof (*yyvsp),
+- &yystacksize);
+-#endif
+-
+- yyss = yyss1; yyvs = yyvs1;
+-#ifdef YYLSP_NEEDED
+- yyls = yyls1;
+-#endif
++ {
++ /* Give user a chance to reallocate the stack. Use copies of
++ these so that the &'s don't force the real ones into
++ memory. */
++ YYSTYPE *yyvs1 = yyvs;
++ short int *yyss1 = yyss;
++
++
++ /* Each stack pointer address is followed by the size of the
++ data in use in that stack, in bytes. This used to be a
++ conditional around just the two extra args, but that might
++ be undefined if yyoverflow is a macro. */
++ yyoverflow ("parser stack overflow",
++ &yyss1, yysize * sizeof (*yyssp),
++ &yyvs1, yysize * sizeof (*yyvsp),
++
++ &yystacksize);
++
++ yyss = yyss1;
++ yyvs = yyvs1;
++ }
+ #else /* no yyoverflow */
++# ifndef YYSTACK_RELOCATE
++ goto yyoverflowlab;
++# else
+ /* Extend the stack our own way. */
+- if (yystacksize >= YYMAXDEPTH)
+- {
+- yyerror("parser stack overflow");
+- if (yyfree_stacks)
+- {
+- free (yyss);
+- free (yyvs);
+-#ifdef YYLSP_NEEDED
+- free (yyls);
+-#endif
+- }
+- return 2;
+- }
++ if (YYMAXDEPTH <= yystacksize)
++ goto yyoverflowlab;
+ yystacksize *= 2;
+- if (yystacksize > YYMAXDEPTH)
++ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+-#ifndef YYSTACK_USE_ALLOCA
+- yyfree_stacks = 1;
+-#endif
+- yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
+- __yy_memcpy ((char *)yyss, (char *)yyss1,
+- size * (unsigned int) sizeof (*yyssp));
+- yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
+- __yy_memcpy ((char *)yyvs, (char *)yyvs1,
+- size * (unsigned int) sizeof (*yyvsp));
+-#ifdef YYLSP_NEEDED
+- yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
+- __yy_memcpy ((char *)yyls, (char *)yyls1,
+- size * (unsigned int) sizeof (*yylsp));
+-#endif
++
++ {
++ short int *yyss1 = yyss;
++ union yyalloc *yyptr =
++ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
++ if (! yyptr)
++ goto yyoverflowlab;
++ YYSTACK_RELOCATE (yyss);
++ YYSTACK_RELOCATE (yyvs);
++
++# undef YYSTACK_RELOCATE
++ if (yyss1 != yyssa)
++ YYSTACK_FREE (yyss1);
++ }
++# endif
+ #endif /* no yyoverflow */
+
+- yyssp = yyss + size - 1;
+- yyvsp = yyvs + size - 1;
+-#ifdef YYLSP_NEEDED
+- yylsp = yyls + size - 1;
+-#endif
++ yyssp = yyss + yysize - 1;
++ yyvsp = yyvs + yysize - 1;
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+-#endif
+
+- if (yyssp >= yyss + yystacksize - 1)
++ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
++ (unsigned long int) yystacksize));
++
++ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Entering state %d\n", yystate);
+-#endif
++ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+- yybackup:
++
++/*-----------.
++| yybackup. |
++`-----------*/
++yybackup:
+
+ /* Do appropriate processing given the current state. */
+ /* Read a lookahead token if we need one and don't already have one. */
+@@ -751,154 +1114,120 @@
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+- if (yyn == YYFLAG)
++ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+- /* yychar is either YYEMPTY or YYEOF
+- or a valid token in external form. */
+-
++ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Reading a token: ");
+-#endif
++ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+- /* Convert token to internal form (in yychar1) for indexing tables with */
+-
+- if (yychar <= 0) /* This means end of input. */
++ if (yychar <= YYEOF)
+ {
+- yychar1 = 0;
+- yychar = YYEOF; /* Don't call YYLEX any more */
+-
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Now at end of input.\n");
+-#endif
++ yychar = yytoken = YYEOF;
++ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+- yychar1 = YYTRANSLATE(yychar);
+-
+-#if YYDEBUG != 0
+- if (yydebug)
+- {
+- fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+- /* Give the individual parser a way to print the precise meaning
+- of a token, for further debugging info. */
+-#ifdef YYPRINT
+- YYPRINT (stderr, yychar, yylval);
+-#endif
+- fprintf (stderr, ")\n");
+- }
+-#endif
++ yytoken = YYTRANSLATE (yychar);
++ YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+- yyn += yychar1;
+- if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
++ /* If the proper action on seeing token YYTOKEN is to reduce or to
++ detect an error, take that action. */
++ yyn += yytoken;
++ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+-
+ yyn = yytable[yyn];
+-
+- /* yyn is what to do for this token type in this state.
+- Negative => reduce, -yyn is rule number.
+- Positive => shift, yyn is new state.
+- New state is final state => don't bother to shift,
+- just return success.
+- 0, or most negative number => error. */
+-
+- if (yyn < 0)
++ if (yyn <= 0)
+ {
+- if (yyn == YYFLAG)
++ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+- else if (yyn == 0)
+- goto yyerrlab;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+-
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+-#endif
++ YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+-#ifdef YYLSP_NEEDED
+- *++yylsp = yylloc;
+-#endif
+
+- /* count tokens shifted since error; after three, turn off error status. */
+- if (yyerrstatus) yyerrstatus--;
++
++ /* Count tokens shifted since error; after three, turn off error
++ status. */
++ if (yyerrstatus)
++ yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+-/* Do the default action for the current state. */
+-yydefault:
+
++/*-----------------------------------------------------------.
++| yydefault -- do the default action for the current state. |
++`-----------------------------------------------------------*/
++yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
++ goto yyreduce;
+
+-/* Do a reduction. yyn is the number of a rule to reduce with. */
++
++/*-----------------------------.
++| yyreduce -- Do a reduction. |
++`-----------------------------*/
+ yyreduce:
++ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+- if (yylen > 0)
+- yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- {
+- int i;
++ /* If YYLEN is nonzero, implement the default value of the action:
++ `$$ = $1'.
+
+- fprintf (stderr, "Reducing via rule %d (line %d), ",
+- yyn, yyrline[yyn]);
++ Otherwise, the following line sets YYVAL to garbage.
++ This behavior is undocumented and Bison
++ users should not rely upon it. Assigning to YYVAL
++ unconditionally makes the parser a bit smaller, and it avoids a
++ GCC warning that YYVAL may be used uninitialized. */
++ yyval = yyvsp[1-yylen];
+
+- /* Print the symbols being reduced, and their result. */
+- for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+- fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+- fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+- }
+-#endif
+
+-
+- switch (yyn) {
+-
+-case 1:
+-#line 165 "ql_y.y"
+-{
++ YY_REDUCE_PRINT (yyn);
++ switch (yyn)
++ {
++ case 2:
++#line 168 "ql_y.y"
++ {
+ STRUCTURE *walk;
+
+ def = yyvsp[0].field;
+ for (walk = structures; walk; walk = walk->next)
+ if (!walk->instances)
+ fprintf(stderr,"unused structure: %s\n",walk->id);
+- ;
+- break;}
+-case 3:
+-#line 177 "ql_y.y"
+-{
++ }
++ break;
++
++ case 4:
++#line 180 "ql_y.y"
++ {
+ to_c("#%s\n",yyvsp[-1].str);
+ to_test("#%s\n",yyvsp[-1].str);
+ if (dump) to_dump("#%s\n",yyvsp[-1].str);
+- ;
+- break;}
+-case 6:
+-#line 190 "ql_y.y"
+-{
++ }
++ break;
++
++ case 7:
++#line 193 "ql_y.y"
++ {
+ STRUCTURE *n;
+
+ n = alloc_t(STRUCTURE);
+@@ -907,23 +1236,26 @@
+ n->instances = 0;
+ n->next = structures;
+ structures = n;
+- ;
+- break;}
+-case 7:
+-#line 203 "ql_y.y"
+-{
++ }
++ break;
++
++ case 8:
++#line 206 "ql_y.y"
++ {
+ abort_id = NULL;
+- ;
+- break;}
+-case 8:
+-#line 207 "ql_y.y"
+-{
++ }
++ break;
++
++ case 9:
++#line 210 "ql_y.y"
++ {
+ yyval.field = yyvsp[0].field;
+- ;
+- break;}
+-case 9:
+-#line 214 "ql_y.y"
+-{
++ }
++ break;
++
++ case 10:
++#line 217 "ql_y.y"
++ {
+ STRUCTURE *walk;
+
+ for (walk = structures; walk; walk = walk->next)
+@@ -939,38 +1271,43 @@
+ yyval.field->my_block = copy_block(walk->block);
+ yyval.field->next = NULL;
+ abort_id = NULL;
+- ;
+- break;}
+-case 10:
+-#line 232 "ql_y.y"
+-{
++ }
++ break;
++
++ case 11:
++#line 235 "ql_y.y"
++ {
+ yyval.field = yyvsp[-1].field;
+ abort_id = NULL;
+- ;
+- break;}
+-case 11:
+-#line 237 "ql_y.y"
+-{
++ }
++ break;
++
++ case 12:
++#line 240 "ql_y.y"
++ {
+ yyval.field = NULL;
+ abort_id = yyvsp[0].str;
+- ;
+- break;}
+-case 12:
+-#line 244 "ql_y.y"
+-{
++ }
++ break;
++
++ case 13:
++#line 247 "ql_y.y"
++ {
+ yyval.field = NULL;
+- ;
+- break;}
+-case 13:
+-#line 248 "ql_y.y"
+-{
++ }
++ break;
++
++ case 14:
++#line 251 "ql_y.y"
++ {
+ yyval.field = yyvsp[-1].field;
+ yyvsp[-1].field->next = yyvsp[0].field;
+- ;
+- break;}
+-case 14:
+-#line 256 "ql_y.y"
+-{
++ }
++ break;
++
++ case 15:
++#line 259 "ql_y.y"
++ {
+ TAG *walk;
+
+ yyval.field = yyvsp[0].field;
+@@ -989,23 +1326,26 @@
+ "selections");
+ if (*yyval.field->id != '_' && yyval.field->value && yyval.field->value->type == vt_multi)
+ yyerror("multi selectors must be unnamed");
+- ;
+- break;}
+-case 15:
+-#line 279 "ql_y.y"
+-{
++ }
++ break;
++
++ case 16:
++#line 282 "ql_y.y"
++ {
+ yyval.num = 0;
+- ;
+- break;}
+-case 16:
+-#line 283 "ql_y.y"
+-{
++ }
++ break;
++
++ case 17:
++#line 286 "ql_y.y"
++ {
+ yyval.num = 1;
+- ;
+- break;}
+-case 17:
+-#line 290 "ql_y.y"
+-{
++ }
++ break;
++
++ case 18:
++#line 293 "ql_y.y"
++ {
+ yyval.field = alloc_t(FIELD);
+ yyval.field->size = yyvsp[-1].num;
+ yyval.field->var_len = -2; /* hack */
+@@ -1015,140 +1355,159 @@
+ yyval.field->value = NULL;
+ yyval.field->structure = NULL;
+ yyval.field->next = NULL;
+- ;
+- break;}
+-case 18:
+-#line 302 "ql_y.y"
+-{
++ }
++ break;
++
++ case 19:
++#line 305 "ql_y.y"
++ {
+ yyval.field = alloc_t(FIELD);
+ yyval.field->size = yyvsp[-4].num;
+ yyval.field->var_len = -1;
+ yyval.field->pos = yyvsp[-3].num;
+ yyval.field->flush = !yyvsp[-2].num;
+- if (yyval.field->pos == -1)
++ if (yyval.field->pos == -1) {
+ if (yyval.field->size & 7)
+ yyerror("position required for small fields");
+ else yyval.field->pos = 0;
++ }
+ yyval.field->value = yyvsp[0].value;
+ yyval.field->structure = NULL;
+ yyval.field->next = NULL;
+- ;
+- break;}
+-case 19:
+-#line 319 "ql_y.y"
+-{
+- yyval.num = -1;
+- ;
+- break;}
+-case 20:
++ }
++ break;
++
++ case 20:
+ #line 323 "ql_y.y"
+-{
++ {
++ yyval.num = -1;
++ }
++ break;
++
++ case 21:
++#line 327 "ql_y.y"
++ {
+ yyval.num = yyvsp[0].num-1;
+ if (yyval.num < 0 || yyval.num > 7) yyerror("invalid position");
+- ;
+- break;}
+-case 21:
+-#line 331 "ql_y.y"
+-{
++ }
++ break;
++
++ case 22:
++#line 335 "ql_y.y"
++ {
+ char *end;
+
+ yyval.num = strtoul(yyvsp[0].str,&end,10);
+ if (*end) yyerror("no a decimal number");
+- ;
+- break;}
+-case 22:
+-#line 340 "ql_y.y"
+-{
+- yyval.num = 0;
+- ;
+- break;}
+-case 23:
++ }
++ break;
++
++ case 23:
+ #line 344 "ql_y.y"
+-{
++ {
++ yyval.num = 0;
++ }
++ break;
++
++ case 24:
++#line 348 "ql_y.y"
++ {
+ if (strcmp(yyvsp[0].str,"more")) yyerror("\"more\" expected");
+ yyval.num = 1;
+- ;
+- break;}
+-case 24:
+-#line 351 "ql_y.y"
+-{
+- yyval.value = NULL;
+- ;
+- break;}
+-case 25:
++ }
++ break;
++
++ case 25:
+ #line 355 "ql_y.y"
+-{
++ {
++ yyval.value = NULL;
++ }
++ break;
++
++ case 26:
++#line 359 "ql_y.y"
++ {
+ yyval.value = yyvsp[0].value;
+- ;
+- break;}
+-case 26:
+-#line 362 "ql_y.y"
+-{
++ }
++ break;
++
++ case 27:
++#line 366 "ql_y.y"
++ {
+ yyval.value = alloc_t(VALUE);
+ yyval.value->type = vt_id;
+ yyval.value->id = yyvsp[0].str;
+- ;
+- break;}
+-case 27:
+-#line 368 "ql_y.y"
+-{
++ }
++ break;
++
++ case 28:
++#line 372 "ql_y.y"
++ {
+ yyval.value = alloc_t(VALUE);
+ yyval.value->type = vt_case;
+ yyval.value->id = NULL;
+ yyval.value->tags = yyvsp[-1].tag;
+- ;
+- break;}
+-case 28:
+-#line 375 "ql_y.y"
+-{
++ }
++ break;
++
++ case 29:
++#line 379 "ql_y.y"
++ {
+ yyval.value = alloc_t(VALUE);
+ yyval.value->type = vt_multi;
+ yyval.value->tags = yyvsp[-1].tag;
+- ;
+- break;}
+-case 29:
+-#line 381 "ql_y.y"
+-{
++ }
++ break;
++
++ case 30:
++#line 385 "ql_y.y"
++ {
+ yyval.value = alloc_t(VALUE);
+ yyval.value->type = vt_length;
+ yyval.value->recovery = yyvsp[-2].str;
+ yyval.value->block = yyvsp[0].field;
+ yyval.value->abort_id = abort_id;
+- ;
+- break;}
+-case 30:
+-#line 391 "ql_y.y"
+-{
+- yyval.str = NULL;
+- ;
+- break;}
+-case 31:
++ }
++ break;
++
++ case 31:
+ #line 395 "ql_y.y"
+-{
++ {
++ yyval.str = NULL;
++ }
++ break;
++
++ case 32:
++#line 399 "ql_y.y"
++ {
+ yyval.str = yyvsp[0].str;
+- ;
+- break;}
+-case 32:
+-#line 401 "ql_y.y"
+-{
+- yyval.nlist = NULL;
+- ;
+- break;}
+-case 33:
++ }
++ break;
++
++ case 33:
+ #line 405 "ql_y.y"
+-{
++ {
++ yyval.nlist = NULL;
++ }
++ break;
++
++ case 34:
++#line 409 "ql_y.y"
++ {
+ yyval.nlist = get_name_list(yyvsp[0].str);
+- ;
+- break;}
+-case 34:
+-#line 411 "ql_y.y"
+-{
+- yyval.tag = NULL;
+- ;
+- break;}
+-case 35:
++ }
++ break;
++
++ case 35:
+ #line 415 "ql_y.y"
+-{
++ {
++ yyval.tag = NULL;
++ }
++ break;
++
++ case 36:
++#line 419 "ql_y.y"
++ {
+ yyval.tag = alloc_t(TAG);
+ yyval.tag->deflt = 1;
+ if (yyvsp[-2].str) {
+@@ -1163,18 +1522,20 @@
+ yyval.tag->block = yyvsp[0].field;
+ yyval.tag->next = NULL;
+ yyval.tag->abort_id = abort_id;
+- ;
+- break;}
+-case 36:
+-#line 432 "ql_y.y"
+-{
++ }
++ break;
++
++ case 37:
++#line 436 "ql_y.y"
++ {
+ yyval.tag = alloc_t(TAG);
+ yyval.tag->abort_id = abort_id;
+- ;
+- break;}
+-case 37:
+-#line 437 "ql_y.y"
+-{
++ }
++ break;
++
++ case 38:
++#line 441 "ql_y.y"
++ {
+ yyval.tag = yyvsp[-1].tag;
+ yyval.tag->deflt = 0;
+ if (yyvsp[-4].str) {
+@@ -1188,17 +1549,19 @@
+ yyval.tag->more = yyvsp[-3].list;
+ yyval.tag->block = yyvsp[-2].field;
+ yyval.tag->next = yyvsp[0].tag;
+- ;
+- break;}
+-case 38:
+-#line 455 "ql_y.y"
+-{
+- yyval.tag = NULL;
+- ;
+- break;}
+-case 39:
++ }
++ break;
++
++ case 39:
+ #line 459 "ql_y.y"
+-{
++ {
++ yyval.tag = NULL;
++ }
++ break;
++
++ case 40:
++#line 463 "ql_y.y"
++ {
+ yyval.tag = alloc_t(TAG);
+ yyval.tag->deflt = 1;
+ if (yyvsp[-2].str) {
+@@ -1212,18 +1575,20 @@
+ yyval.tag->more = yyvsp[-1].list;
+ yyval.tag->block = yyvsp[0].field;
+ yyval.tag->next = NULL;
+- ;
+- break;}
+-case 40:
+-#line 475 "ql_y.y"
+-{
++ }
++ break;
++
++ case 41:
++#line 479 "ql_y.y"
++ {
+ yyval.tag = alloc_t(TAG);
+ yyval.tag->abort_id = abort_id;
+- ;
+- break;}
+-case 41:
+-#line 480 "ql_y.y"
+-{
++ }
++ break;
++
++ case 42:
++#line 484 "ql_y.y"
++ {
+ yyval.tag = yyvsp[-1].tag;
+ yyval.tag->deflt = 0;
+ if (yyvsp[-4].str) {
+@@ -1237,254 +1602,266 @@
+ yyval.tag->more = yyvsp[-3].list;
+ yyval.tag->block = yyvsp[-2].field;
+ yyval.tag->next = yyvsp[0].tag;
+- ;
+- break;}
+-case 42:
+-#line 498 "ql_y.y"
+-{
+- yyval.str = NULL;
+- ;
+- break;}
+-case 43:
++ }
++ break;
++
++ case 43:
+ #line 502 "ql_y.y"
+-{
++ {
++ yyval.str = NULL;
++ }
++ break;
++
++ case 44:
++#line 506 "ql_y.y"
++ {
+ yyval.str = yyvsp[0].str;
+- ;
+- break;}
+-case 44:
+-#line 508 "ql_y.y"
+-{
+- yyval.list = NULL;
+- ;
+- break;}
+-case 45:
++ }
++ break;
++
++ case 45:
+ #line 512 "ql_y.y"
+-{
++ {
++ yyval.list = NULL;
++ }
++ break;
++
++ case 46:
++#line 516 "ql_y.y"
++ {
+ yyval.list = alloc_t(VALUE_LIST);
+ yyval.list->value = yyvsp[-1].str;
+ yyval.list->next = yyvsp[0].list;
+- ;
+- break;}
+-}
+- /* the action file gets copied in in place of this dollarsign */
+-#line 543 "/usr/lib/bison.simple"
++ }
++ break;
++
++
++ }
++
++/* Line 1010 of yacc.c. */
++#line 1643 "y.tab.c"
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+-#ifdef YYLSP_NEEDED
+- yylsp -= yylen;
+-#endif
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- {
+- short *ssp1 = yyss - 1;
+- fprintf (stderr, "state stack now");
+- while (ssp1 != yyssp)
+- fprintf (stderr, " %d", *++ssp1);
+- fprintf (stderr, "\n");
+- }
+-#endif
++
++ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+-#ifdef YYLSP_NEEDED
+- yylsp++;
+- if (yylen == 0)
+- {
+- yylsp->first_line = yylloc.first_line;
+- yylsp->first_column = yylloc.first_column;
+- yylsp->last_line = (yylsp-1)->last_line;
+- yylsp->last_column = (yylsp-1)->last_column;
+- yylsp->text = 0;
+- }
+- else
+- {
+- yylsp->last_line = (yylsp+yylen-1)->last_line;
+- yylsp->last_column = (yylsp+yylen-1)->last_column;
+- }
+-#endif
+
+- /* Now "shift" the result of the reduction.
+- Determine what state that goes to,
+- based on the state we popped back to
+- and the rule number reduced by. */
++ /* Now `shift' the result of the reduction. Determine what state
++ that goes to, based on the state we popped back to and the rule
++ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+- yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+- if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
++ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
++ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+- yystate = yydefgoto[yyn - YYNTBASE];
++ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+-yyerrlab: /* here on detecting error */
+
+- if (! yyerrstatus)
+- /* If not already recovering from an error, report this error. */
++/*------------------------------------.
++| yyerrlab -- here on detecting error |
++`------------------------------------*/
++yyerrlab:
++ /* If not already recovering from an error, report this error. */
++ if (!yyerrstatus)
+ {
+ ++yynerrs;
+-
+-#ifdef YYERROR_VERBOSE
++#if YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+- if (yyn > YYFLAG && yyn < YYLAST)
++ if (YYPACT_NINF < yyn && yyn < YYLAST)
+ {
+- int size = 0;
+- char *msg;
+- int x, count;
+-
+- count = 0;
+- /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
+- for (x = (yyn < 0 ? -yyn : 0);
+- x < (sizeof(yytname) / sizeof(char *)); x++)
+- if (yycheck[x + yyn] == x)
+- size += strlen(yytname[x]) + 15, count++;
+- msg = (char *) malloc(size + 15);
+- if (msg != 0)
++ YYSIZE_T yysize = 0;
++ int yytype = YYTRANSLATE (yychar);
++ const char* yyprefix;
++ char *yymsg;
++ int yyx;
++
++ /* Start YYX at -YYN if negative to avoid negative indexes in
++ YYCHECK. */
++ int yyxbegin = yyn < 0 ? -yyn : 0;
++
++ /* Stay within bounds of both yycheck and yytname. */
++ int yychecklim = YYLAST - yyn;
++ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
++ int yycount = 0;
++
++ yyprefix = ", expecting ";
++ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
++ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
++ {
++ yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
++ yycount += 1;
++ if (yycount == 5)
++ {
++ yysize = 0;
++ break;
++ }
++ }
++ yysize += (sizeof ("syntax error, unexpected ")
++ + yystrlen (yytname[yytype]));
++ yymsg = (char *) YYSTACK_ALLOC (yysize);
++ if (yymsg != 0)
+ {
+- strcpy(msg, "parse error");
++ char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
++ yyp = yystpcpy (yyp, yytname[yytype]);
+
+- if (count < 5)
++ if (yycount < 5)
+ {
+- count = 0;
+- for (x = (yyn < 0 ? -yyn : 0);
+- x < (sizeof(yytname) / sizeof(char *)); x++)
+- if (yycheck[x + yyn] == x)
++ yyprefix = ", expecting ";
++ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
++ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+- strcat(msg, count == 0 ? ", expecting `" : " or `");
+- strcat(msg, yytname[x]);
+- strcat(msg, "'");
+- count++;
++ yyp = yystpcpy (yyp, yyprefix);
++ yyp = yystpcpy (yyp, yytname[yyx]);
++ yyprefix = " or ";
+ }
+ }
+- yyerror(msg);
+- free(msg);
++ yyerror (yymsg);
++ YYSTACK_FREE (yymsg);
+ }
+ else
+- yyerror ("parse error; also virtual memory exceeded");
++ yyerror ("syntax error; also virtual memory exhausted");
+ }
+ else
+ #endif /* YYERROR_VERBOSE */
+- yyerror("parse error");
++ yyerror ("syntax error");
+ }
+
+- goto yyerrlab1;
+-yyerrlab1: /* here on error raised explicitly by an action */
++
+
+ if (yyerrstatus == 3)
+ {
+- /* if just tried and failed to reuse lookahead token after an error, discard it. */
++ /* If just tried and failed to reuse lookahead token after an
++ error, discard it. */
+
+- /* return failure if at end of input */
+- if (yychar == YYEOF)
+- YYABORT;
+-
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+-#endif
++ if (yychar <= YYEOF)
++ {
++ /* If at end of input, pop the error token,
++ then the rest of the stack, then return failure. */
++ if (yychar == YYEOF)
++ for (;;)
++ {
++ YYPOPSTACK;
++ if (yyssp == yyss)
++ YYABORT;
++ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
++ yydestruct (yystos[*yyssp], yyvsp);
++ }
++ }
++ else
++ {
++ YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
++ yydestruct (yytoken, &yylval);
++ yychar = YYEMPTY;
+
+- yychar = YYEMPTY;
++ }
+ }
+
+- /* Else will try to reuse lookahead token
+- after shifting the error token. */
+-
+- yyerrstatus = 3; /* Each real token shifted decrements this */
++ /* Else will try to reuse lookahead token after shifting the error
++ token. */
++ goto yyerrlab1;
+
+- goto yyerrhandle;
+
+-yyerrdefault: /* current state does not do anything special for the error token. */
++/*---------------------------------------------------.
++| yyerrorlab -- error raised explicitly by YYERROR. |
++`---------------------------------------------------*/
++yyerrorlab:
+
+-#if 0
+- /* This is wrong; only states that explicitly want error tokens
+- should shift them. */
+- yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
+- if (yyn) goto yydefault;
++#ifdef __GNUC__
++ /* Pacify GCC when the user code never invokes YYERROR and the label
++ yyerrorlab therefore never appears in user code. */
++ if (0)
++ goto yyerrorlab;
+ #endif
+
+-yyerrpop: /* pop the current state because it cannot handle the error token */
+-
+- if (yyssp == yyss) YYABORT;
+- yyvsp--;
+- yystate = *--yyssp;
+-#ifdef YYLSP_NEEDED
+- yylsp--;
+-#endif
++ yyvsp -= yylen;
++ yyssp -= yylen;
++ yystate = *yyssp;
++ goto yyerrlab1;
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- {
+- short *ssp1 = yyss - 1;
+- fprintf (stderr, "Error: state stack now");
+- while (ssp1 != yyssp)
+- fprintf (stderr, " %d", *++ssp1);
+- fprintf (stderr, "\n");
+- }
+-#endif
+
+-yyerrhandle:
++/*-------------------------------------------------------------.
++| yyerrlab1 -- common code for both syntax error and YYERROR. |
++`-------------------------------------------------------------*/
++yyerrlab1:
++ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+- yyn = yypact[yystate];
+- if (yyn == YYFLAG)
+- goto yyerrdefault;
++ for (;;)
++ {
++ yyn = yypact[yystate];
++ if (yyn != YYPACT_NINF)
++ {
++ yyn += YYTERROR;
++ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
++ {
++ yyn = yytable[yyn];
++ if (0 < yyn)
++ break;
++ }
++ }
+
+- yyn += YYTERROR;
+- if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+- goto yyerrdefault;
++ /* Pop the current state because it cannot handle the error token. */
++ if (yyssp == yyss)
++ YYABORT;
+
+- yyn = yytable[yyn];
+- if (yyn < 0)
+- {
+- if (yyn == YYFLAG)
+- goto yyerrpop;
+- yyn = -yyn;
+- goto yyreduce;
++ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
++ yydestruct (yystos[yystate], yyvsp);
++ YYPOPSTACK;
++ yystate = *yyssp;
++ YY_STACK_PRINT (yyss, yyssp);
+ }
+- else if (yyn == 0)
+- goto yyerrpop;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Shifting error token, ");
+-#endif
++ YYDPRINTF ((stderr, "Shifting error token, "));
+
+ *++yyvsp = yylval;
+-#ifdef YYLSP_NEEDED
+- *++yylsp = yylloc;
+-#endif
++
+
+ yystate = yyn;
+ goto yynewstate;
+
+- yyacceptlab:
+- /* YYACCEPT comes here. */
+- if (yyfree_stacks)
+- {
+- free (yyss);
+- free (yyvs);
+-#ifdef YYLSP_NEEDED
+- free (yyls);
+-#endif
+- }
+- return 0;
+
+- yyabortlab:
+- /* YYABORT comes here. */
+- if (yyfree_stacks)
+- {
+- free (yyss);
+- free (yyvs);
+-#ifdef YYLSP_NEEDED
+- free (yyls);
++/*-------------------------------------.
++| yyacceptlab -- YYACCEPT comes here. |
++`-------------------------------------*/
++yyacceptlab:
++ yyresult = 0;
++ goto yyreturn;
++
++/*-----------------------------------.
++| yyabortlab -- YYABORT comes here. |
++`-----------------------------------*/
++yyabortlab:
++ yyresult = 1;
++ goto yyreturn;
++
++#ifndef yyoverflow
++/*----------------------------------------------.
++| yyoverflowlab -- parser overflow comes here. |
++`----------------------------------------------*/
++yyoverflowlab:
++ yyerror ("parser stack overflow");
++ yyresult = 2;
++ /* Fall through. */
++#endif
++
++yyreturn:
++#ifndef yyoverflow
++ if (yyss != yyssa)
++ YYSTACK_FREE (yyss);
+ #endif
+- }
+- return 1;
++ return yyresult;
+ }
+-#line 518 "ql_y.y"
++
++
++
+--- linux-atm-2.4.1.orig/src/qgen/ql_y.y
++++ linux-atm-2.4.1/src/qgen/ql_y.y
+@@ -17,6 +17,8 @@
+ #include "qgen.h"
+ #include "file.h"
+
++extern void yyerror(const char *s);
++
+
+ #define MAX_TOKEN 256
+ #define DEFAULT_NAMELIST_FILE "default.nl"
+@@ -58,9 +60,10 @@
+ for (walk = strchr(start,0)-1; walk > start && isspace(*walk); walk--)
+ *walk = 0;
+ if (*start == ':') {
+- if (!(searching = strcmp(start+1,name)))
++ if (!(searching = strcmp(start+1,name))) {
+ if (found) yyerror("multiple entries");
+ else found = 1;
++ }
+ continue;
+ }
+ if (searching) continue;
+@@ -305,10 +308,11 @@
+ $$->var_len = -1;
+ $$->pos = $2;
+ $$->flush = !$3;
+- if ($$->pos == -1)
++ if ($$->pos == -1) {
+ if ($$->size & 7)
+ yyerror("position required for small fields");
+ else $$->pos = 0;
++ }
+ $$->value = $5;
+ $$->structure = NULL;
+ $$->next = NULL;
+--- linux-atm-2.4.1.orig/src/qgen/ql_l.l
++++ linux-atm-2.4.1/src/qgen/ql_l.l
+@@ -68,7 +68,7 @@
+
+ %%
+
+-void yyerror(char *s)
++void yyerror(const char *s)
+ {
+ fprintf(stderr,"line %d: %s near \"%s\"\n",lineno,s,yytext);
+ exit(1);
+--- linux-atm-2.4.1.orig/src/qgen/qlib.c
++++ linux-atm-2.4.1/src/qgen/qlib.c
+@@ -26,14 +26,14 @@
+ #include "op.h"
+
+
+-static int debug = 0;
++static int q_debug = 0;
+
+
+ void PREFIX(report)(int severity,const char *msg,...)
+ {
+ va_list ap;
+
+- if (!debug && severity > Q_ERROR) return;
++ if (!q_debug && severity > Q_ERROR) return;
+ va_start(ap,msg);
+ vprintf(msg,ap);
+ printf("\n");
+@@ -836,7 +836,7 @@
+ Q_DSC dsc;
+ int len,c;
+
+- debug = argc != 1;
++ q_debug = argc != 1;
+ len = 0;
+ while (scanf("%x",&c) == 1) msg[len++] = c;
+ qd_start();
+--- linux-atm-2.4.1.orig/src/qgen/qlib.h
++++ linux-atm-2.4.1/src/qgen/qlib.h
+@@ -23,7 +23,9 @@
+ #define Q_FATAL -1
+
+
++#ifndef DUMP_MODE
+ extern int q_dump;
++#endif
+ extern void q_report(int severity,const char *msg,...);
+
+ #ifdef DUMP_MODE
+--- linux-atm-2.4.1.orig/src/qgen/ql_y.h
++++ linux-atm-2.4.1/src/qgen/ql_y.h
+@@ -1,4 +1,65 @@
+-typedef union {
++/* A Bison parser, made by GNU Bison 1.875d. */
++
++/* Skeleton parser for Yacc-like parsing with Bison,
++ Copyright (C) 1984, 1989, 1990, 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.
++
++ 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, when this file is copied by Bison into a
++ Bison output file, you may use that output file without restriction.
++ This special exception was added by the Free Software Foundation
++ in version 1.24 of Bison. */
++
++/* Tokens. */
++#ifndef YYTOKENTYPE
++# define YYTOKENTYPE
++ /* Put the tokens into the symbol table, so that GDB and other debuggers
++ know about them. */
++ enum yytokentype {
++ TOK_BREAK = 258,
++ TOK_CASE = 259,
++ TOK_DEF = 260,
++ TOK_DEFAULT = 261,
++ TOK_LENGTH = 262,
++ TOK_MULTI = 263,
++ TOK_RECOVER = 264,
++ TOK_ABORT = 265,
++ TOK_ID = 266,
++ TOK_INCLUDE = 267,
++ TOK_STRING = 268
++ };
++#endif
++#define TOK_BREAK 258
++#define TOK_CASE 259
++#define TOK_DEF 260
++#define TOK_DEFAULT 261
++#define TOK_LENGTH 262
++#define TOK_MULTI 263
++#define TOK_RECOVER 264
++#define TOK_ABORT 265
++#define TOK_ID 266
++#define TOK_INCLUDE 267
++#define TOK_STRING 268
++
++
++
++
++#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
++#line 142 "ql_y.y"
++typedef union YYSTYPE {
+ const char *str;
+ int num;
+ FIELD *field;
+@@ -7,17 +68,14 @@
+ TAG *tag;
+ NAME_LIST *nlist;
+ } YYSTYPE;
+-#define TOK_BREAK 257
+-#define TOK_CASE 258
+-#define TOK_DEF 259
+-#define TOK_DEFAULT 260
+-#define TOK_LENGTH 261
+-#define TOK_MULTI 262
+-#define TOK_RECOVER 263
+-#define TOK_ABORT 264
+-#define TOK_ID 265
+-#define TOK_INCLUDE 266
+-#define TOK_STRING 267
+-
++/* Line 1285 of yacc.c. */
++#line 73 "y.tab.h"
++# define yystype YYSTYPE /* obsolescent; will be withdrawn */
++# define YYSTYPE_IS_DECLARED 1
++# define YYSTYPE_IS_TRIVIAL 1
++#endif
+
+ extern YYSTYPE yylval;
++
++
++
+--- linux-atm-2.4.1.orig/src/qgen/incl.pl
++++ linux-atm-2.4.1/src/qgen/incl.pl
+@@ -24,7 +24,7 @@
+ }
+ die "no include file specified" unless defined $last;
+ for (@STD,@USR) {
+- next unless defined stat $_."/".$last;
++ next unless -e "$_/$last";
+ print $_."/".$last."\n" || die "print STDOUT: $!";
+ exit 0;
+ }
+--- linux-atm-2.4.1.orig/src/qgen/msg.fmt
++++ linux-atm-2.4.1/src/qgen/msg.fmt
+@@ -53,7 +53,7 @@
+ ATM_TD_FW_PCR_0 { p##fw_pcr_0 <24> } \
+ ATM_TD_BW_PCR_0 { p##bw_pcr_0 <24> } \
+ ATM_TD_FW_PCR_01 { p##fw_pcr_01 <24> } \
+- ATM_TD_BW_PCR_01 { p##bw_pcr_01 <24> } \
++ ATM_TD_BW_PCR_01 { p##bw_pcr_01 <24> }
+
+ #define TRAFFIC_DESCRIPTOR_VBR(p) \
+ ATM_TD_FW_SCR_0 { p##fw_scr_0 <24> } \
+@@ -63,15 +63,15 @@
+ ATM_TD_FW_MBS_0 { p##fw_mbs_0 <24> } \
+ ATM_TD_BW_MBS_0 { p##bw_mbs_0 <24> } \
+ ATM_TD_FW_MBS_01 { p##fw_mbs_01 <24> } \
+- ATM_TD_BW_MBS_01 { p##bw_mbs_01 <24> } \
++ ATM_TD_BW_MBS_01 { p##bw_mbs_01 <24> }
+
+ #define TRAFFIC_DESCRIPTOR_BE(p) \
+- ATM_TD_BEST_EFFORT { p##best_effort <0> } \
++ ATM_TD_BEST_EFFORT { p##best_effort <0> }
+
+ #if defined(UNI40) || defined(DYNAMIC_UNI)
+ #define TRAFFIC_DESCRIPTOR_ABR(p) \
+ ATM_TD_FW_MCR_01 { p##fw_mcr_01 <24> } \
+- ATM_TD_BW_MCR_01 { p##bw_mcr_01 <24> } \
++ ATM_TD_BW_MCR_01 { p##bw_mcr_01 <24> }
+
+ #else
+ #define TRAFFIC_DESCRIPTOR_ABR(p) /* not yet */
+--- linux-atm-2.4.1.orig/src/qgen/output
++++ linux-atm-2.4.1/src/qgen/output
+@@ -0,0 +1,704 @@
++# 1 "<stdin>"
++# 1 "<built-in>"
++# 1 "<command line>"
++# 1 "<stdin>"
++
++
++
++
++
++# 1 "../../config.h" 1
++# 7 "<stdin>" 2
++
++
++
++
++include "atmsap.h"
++include "uni.h"
++# 26 "<stdin>"
++def ie_aal = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ aal_type <8> = case {
++ 5 {
++ _id "atm_aalp" <8> = multi {
++ ATM_AALP_FW_MAX_SDU {
++ fw_max_sdu <16>
++ }
++ ATM_AALP_BW_MAX_SDU {
++ bw_max_sdu <16>
++ }
++
++ ATM_AALP_AAL_MODE {
++ aal_mode <8> # UNI 3.0 only
++ }
++
++ ATM_AALP_SSCS {
++ sscs_type <8>
++ }
++ }
++ }
++ }
++ }
++}
++# 90 "<stdin>"
++def ie_td = { # UNI 3.0 calls this "User Cell Rate"
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ _id "atm_td" <8> = multi {
++ ATM_TD_FW_PCR_0 { _dummy <0> = length {}fw_pcr_0 <24> } ATM_TD_BW_PCR_0 { _dummy <0> = length {}bw_pcr_0 <24> } ATM_TD_FW_PCR_01 { _dummy <0> = length {}fw_pcr_01 <24> } ATM_TD_BW_PCR_01 { _dummy <0> = length {}bw_pcr_01 <24> } ATM_TD_FW_SCR_0 { _dummy <0> = length {}fw_scr_0 <24> } ATM_TD_BW_SCR_0 { _dummy <0> = length {}bw_scr_0 <24> } ATM_TD_FW_SCR_01 { _dummy <0> = length {}fw_scr_01 <24> } ATM_TD_BW_SCR_01 { _dummy <0> = length {}bw_scr_01 <24> } ATM_TD_FW_MBS_0 { _dummy <0> = length {}fw_mbs_0 <24> } ATM_TD_BW_MBS_0 { _dummy <0> = length {}bw_mbs_0 <24> } ATM_TD_FW_MBS_01 { _dummy <0> = length {}fw_mbs_01 <24> } ATM_TD_BW_MBS_01 { _dummy <0> = length {}bw_mbs_01 <24> } ATM_TD_BEST_EFFORT { _dummy <0> = length {}best_effort <0> }
++# 104 "<stdin>"
++ ATM_TD_TM_OPT { # @@@ should this also go into the TD macro ?
++
++ fw_fdisc "atm_fd" <1@8,more> = ATM_FD_NO
++ bw_fdisc "atm_fd" <1@7,more> = ATM_FD_NO
++
++ bw_tag "atm_tag" <1@2,more> = ATM_TAG_NO
++ fw_tag "atm_tag" <1@1> = ATM_TAG_NO
++ }
++ }
++ }
++}
++
++
++def ie_bbcap = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ bearer_class "atm_bc" <5@1,more>
++ _ext <1@8> = case {
++ 0 {
++ _ext <1@8,more> = 1
++ trans_cap "atm_tc" <7@1>
++ }
++ default 1 {}
++ }
++ _ext <1@8,more> = 1
++ susc_clip "atm_stc" <2@6,more> = ATM_STC_NO
++ upcc "atm_upcc" <2@1> = ATM_UPCC_P2P
++ }
++}
++
++
++def ie_bhli = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ _ext <1@8,more> = 1
++ hli_type <7@1> = case {
++
++
++ 0 { # ISO
++ iso_hli <-64>
++ }
++ 1 { # User Specific
++ user_hli <-64>
++ }
++
++ 2 { # High layer profile - UNI 3.0 only
++ hlp <32>
++ }
++
++ 3 { # Vendor-Specific Application identifier
++ hli_oui <24>
++ app_id <32>
++ }
++
++ 4 { # Reference to ITU-T SG 1 B-ISDN Teleservice Recommendation
++ tobedefined <8>
++ }
++
++ }
++ }
++}
++
++
++def ie_blli = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ _lid <2@6,more> = multi {
++ 1 {
++ _ext <1@8,more> = 1
++ uil1_proto <5@1>
++ }
++ 2 {
++ uil2_proto "atm_l2" <5@1,more> = case {
++ ATM_L2_X25_LL,ATM_L2_X25_ML,ATM_L2_HDLC_ARM,
++ ATM_L2_HDLC_NRM,ATM_L2_HDLC_ABM,ATM_L2_Q922,
++ ATM_L2_ISO7776 { # CCITT encoding
++ _ext <1@8> = case {
++ 0 {
++ l2_mode "atm_imd" <2@6,more> = ATM_IMD_NORMAL
++ q933 <2@1,more> = 0
++ _ext <1@8> = case {
++ 0 {
++ window_size <7@1,more>
++ _ext <1@8> = 1
++ }
++ default 1 {}
++ }
++ }
++ default 1 {}
++ }
++ }
++ ATM_L2_USER { # User specified
++ _ext <1@8> = 0
++ user_l2 <7@1,more>
++ _ext <1@8> = 1
++ }
++ default ATM_L2_ISO1745,ATM_L2_Q291,ATM_L2_LAPB,
++ ATM_L2_ISO8802,ATM_L2_X75 { # No additional data
++ _ext <1@8> = 1
++ }
++ }
++ }
++ 3 {
++ uil3_proto "atm_l3" <5@1,more> = case {
++ ATM_L3_X25,ATM_L3_ISO8208,ATM_L3_X223 { # CCITT coding
++ _ext <1@8> = case {
++ 0 {
++ l3_mode "atm_imd" <2@6,more> = ATM_IMD_NORMAL
++ _ext <1@8> = case {
++ 0 {
++ def_pck_size <4@1,more>
++ _ext <1@8> = case {
++ 0 {
++ _ext <1@8> = 1
++ pck_win_size <7@1>
++ }
++ default 1 {}
++ }
++ }
++ default 1 {}
++ }
++ }
++ default 1 {}
++ }
++ }
++
++ ATM_L3_H310 { # ITU-T Rec. H.310
++ _ext <1@8> = case {
++ 0 {
++ term_type "atm_tt" <4@1,more> = ATM_TT_RXTX
++ _ext <1@8> = case {
++ 0 {
++ _ext <1@8,more> = 1
++ fw_mpx_cap "atm_mc" <3@4,more> =
++ ATM_MC_NONE
++ bw_mpx_cap "atm_mc" <3@1> = ATM_MC_NONE
++ }
++ default 1 {}
++ }
++ }
++ default 1 {}
++ }
++ }
++
++ ATM_L3_TR9577 { # ISO/IEC TR9577
++ _ext <1@8> = case {
++ 0 {
++ _ext <1@8,more> = 0
++ ipi_high <7@1> = case {
++ 0x40 { # SNAP hack
++ _ext <1@8,more> = 1
++ _ipi_low <1@7> = case { # ugly
++ 0 {
++ _ext <1@8,more> = 1
++ _snap_id <2@6> = 0
++ oui <24>
++ pid <16>
++ }
++ default 1 {}
++ }
++ }
++ default 0x0 { # ugly
++ _ext <1@8,more> = 1
++ ipi_low <1@7>
++ }
++ }
++ }
++ default 1 {}
++ }
++ }
++ ATM_L3_USER { # User specified
++ _ext <1@8> = 0
++ user_l3 <7@1,more>
++ _ext <1@8> = 1
++ }
++ }
++ }
++ }
++ }
++}
++
++
++def ie_call_state = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ call_state <6@1>
++ }
++}
++
++
++def ie_cdpn = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ _ext <1@8,more> = 1
++ _plan "atm_np" <4@1,more> = case {
++ ATM_NP_E164 {
++ _type "atm_ton" <3@5> = ATM_TON_INTRNTNL
++ cdpn_e164 <-96>
++ }
++ ATM_NP_AEA { # ATM Endsystem Address
++ _type "atm_ton" <3@5> = ATM_TON_UNKNOWN
++ cdpn_esa <-160>
++ }
++ }
++ }
++}
++
++
++def ie_cdps = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ _ext <1@8,more> = 1
++
++
++
++
++ cdps_type "atm_sat" <3@5,more> = ATM_SAT_AEA
++
++ _oddeven <1@4> = 0
++ cdps <-160>
++ }
++}
++
++
++def ie_cgpn = { # @@@ extend language to allow same trick as for cdpn
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ cgpn_plan "atm_np" <4@1,more>
++ cgpn_type "atm_ton" <3@5,more>
++ _ext <1@8> = case {
++ 0 {
++ _ext <1@8,more> = 1
++ pres_ind "atm_prs" <2@6,more> = ATM_PRS_ALLOW
++ scr_ind "atm_scrn" <2@1> = ATM_SCRN_UP_NS
++ }
++ default 1 {}
++ }
++ cgpn <-160>
++ }
++}
++
++
++def ie_cgps = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ _ext <1@8,more> = 1
++
++
++
++
++ cgps_type "atm_sat" <3@5,more> = ATM_SAT_AEA
++
++ _oddeven <1@4> = 0
++ cgps <-160>
++ }
++}
++
++
++def ie_cause = {
++ _ext <1@8,more> = 1 cause_cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ _ext <1@8,more> = 1
++ location "atm_loc" <4@1> = ATM_LOC_USER
++ _ext <1@8,more> = 1
++ cause "atm_cv" <7@1> = case {
++ ATM_CV_UNALLOC,ATM_CV_NO_ROUTE_DEST,ATM_CV_QOS_UNAVAIL { # Note 2
++ break
++ _ext <1@8,more> = 1
++ pu "atm_pu" <1@4,more> = ATM_PU_USER
++ na "atm_na" <1@3,more> = ATM_NA_NORMAL
++ cond2 "atm_cond" <2@1> = ATM_COND_UNKNOWN
++ }
++ ATM_CV_CALL_REJ { # Note 3
++ break
++ _ext <1@8,more> = 1
++ cond3 "atm_cond" <2@1,more> = ATM_COND_UNKNOWN
++ reason <5@3> = case {
++ ATM_RSN_USER {
++ user_diag <-216>
++ }
++ ATM_RSN_IE_MISS,ATM_RSN_IE_INSUFF {
++ ie_id3 "atm_ie" <8>
++ }
++ }
++ }
++ ATM_CV_NUM_CHANGED { # Note 4
++ break
++ new_dest <-224> # good luck ...
++ }
++ ATM_CV_REJ_CLIR { # Note 5
++ break
++ invalid <8> # not supported
++ }
++ ATM_CV_ACC_INF_DISC,ATM_CV_INCOMP_DEST,ATM_CV_MAND_IE_MISSING,
++ ATM_CV_UNKNOWN_IE,ATM_CV_INVALID_IE { # Note 6
++ break
++ ie_id6 <-224>
++ }
++
++ ATM_CV_UCR_UNAVAIL_OLD,ATM_CV_UCR_UNAVAIL_NEW { # Note 8
++
++
++
++
++
++
++
++ break
++ ucr_id <-224>
++ }
++ ATM_CV_NO_SUCH_CHAN { # Note 9
++ break
++ unav_vpci <16>
++ unav_vci <16>
++ }
++ ATM_CV_UNKNOWN_MSG_TYPE,ATM_CV_INCOMP_MSG { # Note 10
++ break
++ bad_msg_type "atm_msg" <8>
++ }
++ ATM_CV_TIMER_EXP { # Note 11
++ break
++ timer <24>
++ }
++ default 0 {}
++ }
++ }
++}
++
++
++def ie_conn_id = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ _ext <1@8,more> = 1
++ _vp_ass "atm_vpa" <2@4,more> = ATM_VPA_EXPL
++ _pref_exc "atm_poe" <3@1> = 0
++ vpi <16>
++ vci <16>
++ }
++}
++
++
++
++
++def ie_e2e_tdl = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ _id "atm_tdl" <8> = multi {
++ ATM_TDL_CUM {
++ cum_delay <16>
++ }
++ ATM_TDL_E2EMAX {
++ max_delay <16>
++ }
++ ATM_TDL_NGI {}
++ }
++
++ }
++}
++
++
++
++
++def ie_qos = {
++# 467 "<stdin>"
++ _ext <1@8,more> = 1 qos_cs "q2931_cs" <2@6,more> = Q2931_CS_NET _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++
++ qos_fw <8> = 0
++ qos_bw <8> = 0
++ }
++}
++
++
++def ie_bbrep = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ _ext <1@8,more> = 1
++ rep_ind <4@1> = 2
++ }
++}
++
++
++def ie_restart = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ _ext <1@8,more> = 1
++ rst_class <3@1>
++ }
++}
++
++
++def ie_bbs_comp = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ _ext <1@8,more> = 1
++ bbsc_ind <7@1> = 0x21
++ }
++}
++
++
++def ie_tns = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ _ext <1@8,more> = 1
++ _net_type "atm_tni" <3@5,more> = ATM_TNI_NNI
++ _carrier_id "atm_nip" <4@1> = ATM_NIP_CARRIER
++ net_id <-32>
++ }
++}
++
++
++
++
++def ie_notify = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ notification <-32> # @@@ how many actually ?
++ }
++}
++
++
++def ie_oam_td = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ _ext <1@8,more> = 1
++ shaping "atm_shi" <2@6,more> = ATM_SHI_NONE
++ compliance "atm_oci" <1@5,more> = ATM_OCI_OPT
++ fault "atm_unfm" <3@1> = ATM_UNFM_NONE
++ _ext <1@8,more> = 1
++ fwd_ofi "atm_ofi" <3@5,more> = ATM_OFI_0_0
++ bwd_ofi "atm_ofi" <3@1> = ATM_OFI_0_0
++ }
++}
++
++
++def ie_git = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_NET _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length { # @@@ UNI 4.0 does not specify the coding
++ _dummy <1@8> = 0 # bit is "spare", although not indicated in spec
++ id_std_app "atm_irs" <7@1> = case {
++ ATM_IRS_DSMCC,ATM_IRS_H245 {
++ _type "atm_it" <8> = ATM_IT_SESSION
++ _length <8> = length {
++ session_id <-160>
++ }
++ _type "atm_it" <8> = ATM_IT_RESOURCE
++ _length <8> = length {
++ resource_id <-32>
++ }
++ }
++ default 0 {
++ unrecognized_git_identifiers <-224> # 33-5 bytes
++ }
++ }
++ }
++}
++
++
++def ie_lij_id = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_NET _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length { # @@@ UNI 4.0 does not specify the coding
++ _ext <1@8,more> = 1
++ lij_id_type "atm_lit" <7@1> = ATM_LIT_ROOT
++ lij_id <32>
++ }
++}
++
++
++def ie_lij_prm = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_NET _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length { # @@@ UNI 4.0 does not specify the coding
++ _ext <1@8,more> = 1
++ lij_scr_ind "atm_lsi" <2@1>
++ }
++}
++
++
++def ie_leaf_sn = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_NET _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length { # @@@ UNI 4.0 does not specify the coding
++ leaf_sn <32>
++ }
++}
++
++
++def ie_scope_sel = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_NET _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length { # @@@ UNI 4.0 does not specify the coding
++ _ext <1@8,more> = 1
++ scope_type "atm_tcs" <4@1> = ATM_TCS_ORGANIZATIONAL
++ scope_sel "atm_css" <8>
++ }
++}
++
++
++def ie_alt_td = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ _id "atm_td" <8> = multi {
++ ATM_TD_FW_PCR_0 { altfw_pcr_0 <24> } ATM_TD_BW_PCR_0 { altbw_pcr_0 <24> } ATM_TD_FW_PCR_01 { altfw_pcr_01 <24> } ATM_TD_BW_PCR_01 { altbw_pcr_01 <24> } ATM_TD_FW_SCR_0 { altfw_scr_0 <24> } ATM_TD_BW_SCR_0 { altbw_scr_0 <24> } ATM_TD_FW_SCR_01 { altfw_scr_01 <24> } ATM_TD_BW_SCR_01 { altbw_scr_01 <24> } ATM_TD_FW_MBS_0 { altfw_mbs_0 <24> } ATM_TD_BW_MBS_0 { altbw_mbs_0 <24> } ATM_TD_FW_MBS_01 { altfw_mbs_01 <24> } ATM_TD_BW_MBS_01 { altbw_mbs_01 <24> } ATM_TD_BEST_EFFORT { altbest_effort <0> }
++ }
++ }
++}
++
++
++def ie_min_td = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_NET _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length { # @@@ UNI 4.0 does not specify the coding
++ _id "atm_td" <8> = multi {
++ ATM_TD_FW_PCR_0 { minfw_pcr_0 <24> } ATM_TD_BW_PCR_0 { minbw_pcr_0 <24> } ATM_TD_FW_PCR_01 { minfw_pcr_01 <24> } ATM_TD_BW_PCR_01 { minbw_pcr_01 <24> }
++ ATM_TD_FW_MCR_01 { minfw_mcr_01 <24> } ATM_TD_BW_MCR_01 { minbw_mcr_01 <24> }
++ }
++ }
++}
++
++
++def ie_eqos = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_NET _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ eqos_origin "atm_eqo" <8>
++ _id "atm_eqp" <8> = multi {
++ ATM_EQP_ACC_FW_CDV {
++ acc_fw_cdv <24>
++ }
++ ATM_EQP_ACC_BW_CDV {
++ acc_bw_cdv <24>
++ }
++ ATM_EQP_CUM_FW_CDV {
++ cum_fw_cdv <24>
++ }
++ ATM_EQP_CUM_BW_CDV {
++ cum_bw_cdv <24>
++ }
++ ATM_EQP_ACC_FW_CLR {
++ acc_fw_clr <8>
++ }
++ ATM_EQP_ACC_BW_CLR {
++ acc_bw_clr <8>
++ }
++ }
++ }
++}
++
++
++def ie_abr_add_prm = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_NET _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ _id "atm_aap" <8> = multi {
++ ATM_AAP_FW_REC {
++ abr_fw_add_rec <32>
++ }
++ ATM_AAP_BW_REC {
++ abr_bw_add_rec <32>
++ }
++ }
++ }
++}
++
++
++def ie_abr_set_prm = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_NET _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length { # @@@ UNI 4.0 does not specify the coding
++ _id "atm_asp" <8> = multi {
++ ATM_ASP_FW_ICR {
++ abr_fw_icr <24>
++ }
++ ATM_ASP_BW_ICR {
++ abr_bw_icr <24>
++ }
++ ATM_ASP_FW_TBE {
++ abr_fw_tbe <24>
++ }
++ ATM_ASP_BW_TBE {
++ abr_bw_tbe <24>
++ }
++ ATM_ASP_CRF_RTT {
++ atm_crf_rtt <24>
++ }
++ ATM_ASP_FW_RIF {
++ atm_fw_rif <8>
++ }
++ ATM_ASP_BW_RIF {
++ atm_bw_rif <8>
++ }
++ ATM_ASP_FW_RDF {
++ atm_fw_rdf <8>
++ }
++ ATM_ASP_BW_RDF {
++ atm_bw_rdf <8>
++ }
++ }
++ }
++}
++
++
++
++
++def ie_ep_ref = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ _ep_type <8> = 0
++ ep_ref <16>
++ }
++}
++
++
++def ie_ep_state = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ ep_state <6@1>
++ }
++}
++
++
++
++
++def ie_bbrt = {
++ _ext <1@8,more> = 1 _cs "q2931_cs" <2@6,more> = Q2931_CS_ITU _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length {
++ type_of_report "atm_tor" <8>
++ }
++}
++
++
++
++
++{
++ _pdsc "q2931_proto" <8> = Q2931_PROTO_DSC
++ _cr_len <8> = 3
++ call_ref <24>
++ msg_type "atm_msg" <8>
++ _ext <1@8,more> = 1
++ _flag "atm_flag" <1@5,more> = ATM_FLAG_NO
++ _action_ind "atm_ai_msg" <2@1> = 0
++ msg_len <16> = length {
++ _ie_id "atm_ie" <8> = multi {
++ aal: ATM_IE_AAL ie_aal
++ td: ATM_IE_TD ie_td
++ bbcap: ATM_IE_BBCAP ie_bbcap
++ bhli: ATM_IE_BHLI ie_bhli
++ blli1: ATM_IE_BLLI ie_blli
++ blli2: ATM_IE_BLLI ie_blli
++ blli3: ATM_IE_BLLI ie_blli
++ call_state: ATM_IE_CALL_STATE ie_call_state
++ cdpn: ATM_IE_CDPN ie_cdpn
++ cdps: ATM_IE_CDPS ie_cdps
++ cgpn: ATM_IE_CGPN ie_cgpn
++ cgps: ATM_IE_CGPS ie_cgps
++ cause: ATM_IE_CAUSE ie_cause
++ cause2: ATM_IE_CAUSE ie_cause
++ conn_id: ATM_IE_CONN_ID ie_conn_id
++
++ e2e_tdl: ATM_IE_E2E_TDL ie_e2e_tdl
++
++ qos: ATM_IE_QOS ie_qos
++ bbrep: ATM_IE_BBREP ie_bbrep
++ restart: ATM_IE_RESTART ie_restart
++ bbs_comp: ATM_IE_BBS_COMP ie_bbs_comp
++ tns: ATM_IE_TNS ie_tns
++
++ notify: ATM_IE_NOTIFY ie_notify
++ oam_td: ATM_IE_OAM_TD ie_oam_td
++ git: ATM_IE_GIT ie_git
++ git2: ATM_IE_GIT ie_git
++ git3: ATM_IE_GIT ie_git
++ lij_id: ATM_IE_LIJ_ID ie_lij_id
++ lij_prm: ATM_IE_LIJ_PRM ie_lij_prm
++ leaf_sn: ATM_IE_LEAF_SN ie_leaf_sn
++ scope_sel: ATM_IE_SCOPE_SEL ie_scope_sel
++ alt_td: ATM_IE_ALT_TD ie_alt_td
++ min_td: ATM_IE_MIN_TD ie_min_td
++ eqos: ATM_IE_EQOS ie_eqos
++ abr_add_prm:ATM_IE_ABR_ADD_PRM ie_abr_add_prm
++ abr_set_prm:ATM_IE_ABR_SET_PRM ie_abr_set_prm
++
++ ep_ref: ATM_IE_EPR ie_ep_ref
++ ep_state: ATM_IE_EP_STATE ie_ep_state
++
++ bbrt: ATM_IE_BBRT ie_bbrt
++
++ default 0 {
++ _ext <1@8,more> = 1 __cs "q2931_cs" <2@6,more> = 0 _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_ie" <3@1> = 0 _ie_len <16> = recover RECOV_IND_IE length
++ abort RECOV_ASE_UNKNOWN_IE
++ }
++ }
++ }
++}
+--- linux-atm-2.4.1.orig/src/saal/Makefile.in
++++ linux-atm-2.4.1/src/saal/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -87,8 +87,7 @@
+
+ noinst_LIBRARIES = libsaal.a
+
+-libsaal_a_SOURCES = pdu.h queue.h saal.h sscf.h sscop.h pdu.c queue.c saal.c \
+- sscf.c sscop.c
++libsaal_a_SOURCES = pdu.h queue.h saal.h sscf.h sscop.h pdu.c queue.c saal.c sscf.c sscop.c
+
+ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+ CONFIG_HEADER = ../../config.h
+@@ -114,8 +113,10 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
++DEP_FILES = .deps/pdu.P .deps/queue.P .deps/saal.P .deps/sscf.P \
++.deps/sscop.P
+ SOURCES = $(libsaal_a_SOURCES)
+ OBJECTS = $(libsaal_a_OBJECTS)
+
+@@ -123,9 +124,9 @@
+ .SUFFIXES:
+ .SUFFIXES: .S .c .lo .o .obj .s
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/saal/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/saal/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -139,9 +140,6 @@
+
+ maintainer-clean-noinstLIBRARIES:
+
+-.c.o:
+- $(COMPILE) -c $<
+-
+ # FIXME: We should only use cygpath when building on Windows,
+ # and only if it is available.
+ .c.obj:
+@@ -164,9 +162,6 @@
+
+ maintainer-clean-compile:
+
+-.c.lo:
+- $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+-
+ .s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+@@ -206,7 +201,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -222,6 +217,11 @@
+ subdir = src/saal
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/saal/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+@@ -232,20 +232,38 @@
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+-pdu.o: pdu.c ../../config.h ../../src/include/stdint.h pdu.h \
+- ../../src/include/atmd.h ../../src/include/atm.h
+-queue.o: queue.c ../../config.h ../../src/include/atmd.h \
+- ../../src/include/stdint.h ../../src/include/atm.h queue.h
+-saal.o: saal.c ../../config.h sscop.h ../../src/include/stdint.h \
+- ../../src/include/atmd.h ../../src/include/atm.h queue.h saal.h \
+- sscf.h
+-sscf.o: sscf.c ../../config.h ../../src/include/atmd.h \
+- ../../src/include/stdint.h ../../src/include/atm.h sscop.h \
+- queue.h sscf.h
+-sscop.o: sscop.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atmd.h ../../src/include/atm.h sscop.h \
+- queue.h pdu.h
+
++DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
++
++-include $(DEP_FILES)
++
++mostlyclean-depend:
++
++clean-depend:
++
++distclean-depend:
++ -rm -rf .deps
++
++maintainer-clean-depend:
++
++%.o: %.c
++ @echo '$(COMPILE) -c $<'; \
++ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-cp .deps/$(*F).pp .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm .deps/$(*F).pp
++
++%.lo: %.c
++ @echo '$(LTCOMPILE) -c $<'; \
++ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
++ < .deps/$(*F).pp > .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm -f .deps/$(*F).pp
+ info-am:
+ info: info-am
+ dvi-am:
+@@ -282,27 +300,27 @@
+
+ maintainer-clean-generic:
+ mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+- mostlyclean-libtool mostlyclean-tags \
++ mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+ mostlyclean-generic
+
+ mostlyclean: mostlyclean-am
+
+ clean-am: clean-noinstLIBRARIES clean-compile clean-libtool clean-tags \
+- clean-generic mostlyclean-am
++ clean-depend clean-generic mostlyclean-am
+
+ clean: clean-am
+
+ distclean-am: distclean-noinstLIBRARIES distclean-compile \
+- distclean-libtool distclean-tags distclean-generic \
+- clean-am
++ distclean-libtool distclean-tags distclean-depend \
++ distclean-generic clean-am
+ -rm -f libtool
+
+ distclean: distclean-am
+
+ maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
+ maintainer-clean-compile maintainer-clean-libtool \
+- maintainer-clean-tags maintainer-clean-generic \
+- distclean-am
++ maintainer-clean-tags maintainer-clean-depend \
++ 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."
+
+@@ -313,12 +331,14 @@
+ mostlyclean-compile distclean-compile clean-compile \
+ maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+ clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+-distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+-dvi-am dvi check check-am installcheck-am installcheck 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
++distclean-tags clean-tags maintainer-clean-tags distdir \
++mostlyclean-depend distclean-depend clean-depend \
++maintainer-clean-depend info-am info dvi-am dvi check check-am \
++installcheck-am installcheck 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.
+--- linux-atm-2.4.1.orig/src/sigd/Makefile.in
++++ linux-atm-2.4.1/src/sigd/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -88,14 +88,9 @@
+ INCLUDES = -I$(top_builddir)/src/qgen -I$(top_builddir)/src/saal -I.
+
+ sbin_PROGRAMS = atmsigd
+-atmsigd_SOURCES = atmsigd.c io.c io.h kernel.c proto.c proto.h uni.c \
+- sap.c sap.h timeout.c timeout.h trace.c trace.h \
+- policy.c policy.h cfg_y.y cfg_l.l
+-
+-atmsigd_XTRAS = mess.o $(top_builddir)/src/qgen/q.out.o \
+- $(top_builddir)/src/qgen/qd.dump.o \
+- $(top_builddir)/src/lib/libatm.la \
+- $(top_builddir)/src/saal/libsaal.a
++atmsigd_SOURCES = atmsigd.c io.c io.h kernel.c proto.c proto.h uni.c sap.c sap.h timeout.c timeout.h trace.c trace.h policy.c policy.h cfg_y.y cfg_l.l
++
++atmsigd_XTRAS = mess.o $(top_builddir)/src/qgen/q.out.o $(top_builddir)/src/qgen/qd.dump.o $(top_builddir)/src/lib/libatm.la $(top_builddir)/src/saal/libsaal.a
+
+ atmsigd_LDADD = $(atmsigd_XTRAS) -lfl
+ atmsigd_DEPENDENCIES = mess.c $(atmsigd_XTRAS)
+@@ -140,8 +135,11 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
++DEP_FILES = .deps/atmsigd.P .deps/cfg_l.P .deps/cfg_y.P .deps/io.P \
++.deps/kernel.P .deps/policy.P .deps/proto.P .deps/sap.P .deps/timeout.P \
++.deps/trace.P .deps/uni.P
+ SOURCES = $(atmsigd_SOURCES)
+ OBJECTS = $(atmsigd_OBJECTS)
+
+@@ -149,9 +147,9 @@
+ .SUFFIXES:
+ .SUFFIXES: .S .c .l .lo .o .obj .s .y
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/sigd/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/sigd/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -181,9 +179,6 @@
+ rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ done
+
+-.c.o:
+- $(COMPILE) -c $<
+-
+ # FIXME: We should only use cygpath when building on Windows,
+ # and only if it is available.
+ .c.obj:
+@@ -206,9 +201,6 @@
+
+ maintainer-clean-compile:
+
+-.c.lo:
+- $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+-
+ .s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+@@ -347,7 +339,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -363,6 +355,11 @@
+ subdir = src/sigd
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/sigd/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+@@ -373,69 +370,38 @@
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+-atmsigd.o: atmsigd.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h \
+- ../../src/qgen/qlib.h io.h proto.h ../../src/include/atmsap.h \
+- ../../src/saal/saal.h ../../src/saal/sscf.h \
+- ../../src/saal/sscop.h ../../src/saal/queue.h trace.h
+-cfg_l.o: cfg_l.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h cfg_y.h
+-cfg_y.o: cfg_y.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h proto.h \
+- ../../src/include/atmsap.h ../../src/saal/saal.h \
+- ../../src/saal/sscf.h ../../src/saal/sscop.h \
+- ../../src/saal/queue.h io.h trace.h policy.h
+-io.o: io.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h \
+- ../../src/qgen/uni.h ../../src/saal/pdu.h proto.h \
+- ../../src/include/atmsap.h ../../src/saal/saal.h \
+- ../../src/saal/sscf.h ../../src/saal/sscop.h \
+- ../../src/saal/queue.h io.h trace.h
+-kernel.o: kernel.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h \
+- ../../src/qgen/uni.h ../../src/qgen/qlib.h \
+- ../../src/qgen/q.out.h proto.h ../../src/include/atmsap.h \
+- ../../src/saal/saal.h ../../src/saal/sscf.h \
+- ../../src/saal/sscop.h ../../src/saal/queue.h sap.h io.h \
+- policy.h timeout.h
+-mess.o: mess.c ../../config.h
+-policy.o: policy.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h proto.h \
+- ../../src/include/atmsap.h ../../src/saal/saal.h \
+- ../../src/saal/sscf.h ../../src/saal/sscop.h \
+- ../../src/saal/queue.h policy.h
+-proto.o: proto.c ../../config.h ../../src/include/atmd.h \
+- ../../src/include/stdint.h ../../src/include/atm.h \
+- ../../src/qgen/uni.h ../../src/qgen/qlib.h \
+- ../../src/qgen/q.out.h io.h proto.h ../../src/include/atmsap.h \
+- ../../src/saal/saal.h ../../src/saal/sscf.h \
+- ../../src/saal/sscop.h ../../src/saal/queue.h sap.h
+-sap.o: sap.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h \
+- ../../src/qgen/uni.h ../../src/qgen/qlib.h \
+- ../../src/qgen/q.out.h ../../src/qgen/common.h proto.h \
+- ../../src/include/atmsap.h ../../src/saal/saal.h \
+- ../../src/saal/sscf.h ../../src/saal/sscop.h \
+- ../../src/saal/queue.h sap.h
+-timeout.o: timeout.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h \
+- ../../src/qgen/uni.h proto.h ../../src/include/atmsap.h \
+- ../../src/saal/saal.h ../../src/saal/sscf.h \
+- ../../src/saal/sscop.h ../../src/saal/queue.h timeout.h
+-trace.o: trace.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h \
+- ../../src/include/atmsap.h trace.h proto.h \
+- ../../src/saal/saal.h ../../src/saal/sscf.h \
+- ../../src/saal/sscop.h ../../src/saal/queue.h \
+- ../../src/qgen/qlib.h
+-uni.o: uni.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h \
+- ../../src/qgen/uni.h ../../src/qgen/qlib.h \
+- ../../src/qgen/q.out.h proto.h ../../src/include/atmsap.h \
+- ../../src/saal/saal.h ../../src/saal/sscf.h \
+- ../../src/saal/sscop.h ../../src/saal/queue.h sap.h io.h \
+- policy.h timeout.h trace.h
+
++DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
++
++-include $(DEP_FILES)
++
++mostlyclean-depend:
++
++clean-depend:
++
++distclean-depend:
++ -rm -rf .deps
++
++maintainer-clean-depend:
++
++%.o: %.c
++ @echo '$(COMPILE) -c $<'; \
++ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-cp .deps/$(*F).pp .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm .deps/$(*F).pp
++
++%.lo: %.c
++ @echo '$(LTCOMPILE) -c $<'; \
++ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
++ < .deps/$(*F).pp > .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm -f .deps/$(*F).pp
+ info-am:
+ info: info-am
+ dvi-am:
+@@ -474,29 +440,29 @@
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+ maintainer-clean-generic:
+- -test -z "cfg_llcfg_yhcfg_yc" || rm -f cfg_ll cfg_yh cfg_yc
++ -test -z "cfg_lccfg_yhcfg_yc" || rm -f cfg_lc cfg_yh cfg_yc
+ mostlyclean-am: mostlyclean-sbinPROGRAMS mostlyclean-compile \
+- mostlyclean-libtool mostlyclean-tags \
++ mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+ mostlyclean-generic
+
+ mostlyclean: mostlyclean-am
+
+ clean-am: clean-sbinPROGRAMS clean-compile clean-libtool clean-tags \
+- clean-generic mostlyclean-am
++ clean-depend clean-generic mostlyclean-am
+
+ clean: clean-am
+
+ distclean-am: distclean-sbinPROGRAMS distclean-compile \
+- distclean-libtool distclean-tags distclean-generic \
+- clean-am
++ distclean-libtool distclean-tags distclean-depend \
++ distclean-generic clean-am
+ -rm -f libtool
+
+ distclean: distclean-am
+
+ maintainer-clean-am: maintainer-clean-sbinPROGRAMS \
+ maintainer-clean-compile maintainer-clean-libtool \
+- maintainer-clean-tags maintainer-clean-generic \
+- distclean-am
++ maintainer-clean-tags maintainer-clean-depend \
++ 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."
+
+@@ -509,12 +475,14 @@
+ distclean-libtool clean-libtool maintainer-clean-libtool install-man4 \
+ uninstall-man4 install-man8 uninstall-man8 install-man uninstall-man \
+ uninstall-sysconfDATA install-sysconfDATA tags mostlyclean-tags \
+-distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+-dvi-am dvi check check-am installcheck-am installcheck 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
++distclean-tags clean-tags maintainer-clean-tags distdir \
++mostlyclean-depend distclean-depend clean-depend \
++maintainer-clean-depend info-am info dvi-am dvi check check-am \
++installcheck-am installcheck 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
+
+
+ mess.c: $(top_builddir)/src/qgen/uni.h mkmess.pl
+--- linux-atm-2.4.1.orig/src/sigd/cfg_y.c
++++ linux-atm-2.4.1/src/sigd/cfg_y.c
+@@ -1,46 +1,137 @@
++/* A Bison parser, made by GNU Bison 1.875d. */
+
+-/* A Bison parser, made from cfg_y.y
+- by GNU Bison version 1.28 */
++/* Skeleton parser for Yacc-like parsing with Bison,
++ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+-#define YYBISON 1 /* Identify Bison output. */
++ 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.
+
+-#define TOK_LEVEL 257
+-#define TOK_DEBUG 258
+-#define TOK_INFO 259
+-#define TOK_WARN 260
+-#define TOK_ERROR 261
+-#define TOK_FATAL 262
+-#define TOK_SIG 263
+-#define TOK_UNI30 264
+-#define TOK_UNI31 265
+-#define TOK_UNI40 266
+-#define TOK_Q2963_1 267
+-#define TOK_SAAL 268
+-#define TOK_VC 269
+-#define TOK_IO 270
+-#define TOK_MODE 271
+-#define TOK_USER 272
+-#define TOK_NET 273
+-#define TOK_SWITCH 274
+-#define TOK_VPCI 275
+-#define TOK_ITF 276
+-#define TOK_PCR 277
+-#define TOK_TRACE 278
+-#define TOK_POLICY 279
+-#define TOK_ALLOW 280
+-#define TOK_REJECT 281
+-#define TOK_ENTITY 282
+-#define TOK_DEFAULT 283
+-#define TOK_NUMBER 284
+-#define TOK_MAX_RATE 285
+-#define TOK_DUMP_DIR 286
+-#define TOK_LOGFILE 287
+-#define TOK_QOS 288
+-#define TOK_FROM 289
+-#define TOK_TO 290
+-#define TOK_ROUTE 291
+-#define TOK_PVC 292
++ 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, when this file is copied by Bison into a
++ Bison output file, you may use that output file without restriction.
++ This special exception was added by the Free Software Foundation
++ in version 1.24 of Bison. */
++
++/* Written by Richard Stallman by simplifying the original so called
++ ``semantic'' parser. */
++
++/* All symbols defined below should begin with yy or YY, to avoid
++ infringing on user name space. This should be done even for local
++ variables, as they might otherwise be expanded by user macros.
++ There are some unavoidable exceptions within include files to
++ define necessary library symbols; they are noted "INFRINGES ON
++ USER NAME SPACE" below. */
++
++/* Identify Bison output. */
++#define YYBISON 1
++
++/* Skeleton name. */
++#define YYSKELETON_NAME "yacc.c"
++
++/* Pure parsers. */
++#define YYPURE 0
++
++/* Using locations. */
++#define YYLSP_NEEDED 0
++
++
++
++/* Tokens. */
++#ifndef YYTOKENTYPE
++# define YYTOKENTYPE
++ /* Put the tokens into the symbol table, so that GDB and other debuggers
++ know about them. */
++ enum yytokentype {
++ TOK_LEVEL = 258,
++ TOK_DEBUG = 259,
++ TOK_INFO = 260,
++ TOK_WARN = 261,
++ TOK_ERROR = 262,
++ TOK_FATAL = 263,
++ TOK_SIG = 264,
++ TOK_UNI30 = 265,
++ TOK_UNI31 = 266,
++ TOK_UNI40 = 267,
++ TOK_Q2963_1 = 268,
++ TOK_SAAL = 269,
++ TOK_VC = 270,
++ TOK_IO = 271,
++ TOK_MODE = 272,
++ TOK_USER = 273,
++ TOK_NET = 274,
++ TOK_SWITCH = 275,
++ TOK_VPCI = 276,
++ TOK_ITF = 277,
++ TOK_PCR = 278,
++ TOK_TRACE = 279,
++ TOK_POLICY = 280,
++ TOK_ALLOW = 281,
++ TOK_REJECT = 282,
++ TOK_ENTITY = 283,
++ TOK_DEFAULT = 284,
++ TOK_NUMBER = 285,
++ TOK_MAX_RATE = 286,
++ TOK_DUMP_DIR = 287,
++ TOK_LOGFILE = 288,
++ TOK_QOS = 289,
++ TOK_FROM = 290,
++ TOK_TO = 291,
++ TOK_ROUTE = 292,
++ TOK_PVC = 293
++ };
++#endif
++#define TOK_LEVEL 258
++#define TOK_DEBUG 259
++#define TOK_INFO 260
++#define TOK_WARN 261
++#define TOK_ERROR 262
++#define TOK_FATAL 263
++#define TOK_SIG 264
++#define TOK_UNI30 265
++#define TOK_UNI31 266
++#define TOK_UNI40 267
++#define TOK_Q2963_1 268
++#define TOK_SAAL 269
++#define TOK_VC 270
++#define TOK_IO 271
++#define TOK_MODE 272
++#define TOK_USER 273
++#define TOK_NET 274
++#define TOK_SWITCH 275
++#define TOK_VPCI 276
++#define TOK_ITF 277
++#define TOK_PCR 278
++#define TOK_TRACE 279
++#define TOK_POLICY 280
++#define TOK_ALLOW 281
++#define TOK_REJECT 282
++#define TOK_ENTITY 283
++#define TOK_DEFAULT 284
++#define TOK_NUMBER 285
++#define TOK_MAX_RATE 286
++#define TOK_DUMP_DIR 287
++#define TOK_LOGFILE 288
++#define TOK_QOS 289
++#define TOK_FROM 290
++#define TOK_TO 291
++#define TOK_ROUTE 292
++#define TOK_PVC 293
++
++
++
++
++/* Copy the first part of user declarations. */
+ #line 1 "cfg_y.y"
+
+ /* cfg.y - configuration language */
+@@ -51,6 +142,7 @@
+ #include <config.h>
+ #endif
+
++#include <stdlib.h>
+ #include <string.h>
+ #include <ctype.h>
+ #include <limits.h>
+@@ -63,6 +155,8 @@
+ #include "trace.h"
+ #include "policy.h"
+
++extern void yywarn(const char *s);
++extern void yyerror(const char *s);
+
+ static RULE *rule;
+ static SIG_ENTITY *curr_sig = &_entity;
+@@ -93,516 +187,830 @@
+ }
+
+
+-#line 53 "cfg_y.y"
+-typedef union {
++
++/* Enabling traces. */
++#ifndef YYDEBUG
++# define YYDEBUG 0
++#endif
++
++/* Enabling verbose error messages. */
++#ifdef YYERROR_VERBOSE
++# undef YYERROR_VERBOSE
++# define YYERROR_VERBOSE 1
++#else
++# define YYERROR_VERBOSE 0
++#endif
++
++#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
++#line 56 "cfg_y.y"
++typedef union YYSTYPE {
+ int num;
+ char *str;
+ struct sockaddr_atmpvc pvc;
+ } YYSTYPE;
+-#include <stdio.h>
++/* Line 191 of yacc.c. */
++#line 213 "y.tab.c"
++# define yystype YYSTYPE /* obsolescent; will be withdrawn */
++# define YYSTYPE_IS_DECLARED 1
++# define YYSTYPE_IS_TRIVIAL 1
++#endif
++
++
++
++/* Copy the second part of user declarations. */
++
++
++/* Line 214 of yacc.c. */
++#line 225 "y.tab.c"
++
++#if ! defined (yyoverflow) || YYERROR_VERBOSE
++
++# ifndef YYFREE
++# define YYFREE free
++# endif
++# ifndef YYMALLOC
++# define YYMALLOC malloc
++# endif
++
++/* The parser invokes alloca or malloc; define the necessary symbols. */
++
++# ifdef YYSTACK_USE_ALLOCA
++# if YYSTACK_USE_ALLOCA
++# define YYSTACK_ALLOC alloca
++# endif
++# else
++# if defined (alloca) || defined (_ALLOCA_H)
++# define YYSTACK_ALLOC alloca
++# else
++# ifdef __GNUC__
++# define YYSTACK_ALLOC __builtin_alloca
++# endif
++# endif
++# endif
++
++# ifdef YYSTACK_ALLOC
++ /* Pacify GCC's `empty if-body' warning. */
++# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
++# else
++# if defined (__STDC__) || defined (__cplusplus)
++# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
++# define YYSIZE_T size_t
++# endif
++# define YYSTACK_ALLOC YYMALLOC
++# define YYSTACK_FREE YYFREE
++# endif
++#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
++
++
++#if (! defined (yyoverflow) \
++ && (! defined (__cplusplus) \
++ || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
++
++/* A type that is properly aligned for any stack member. */
++union yyalloc
++{
++ short int yyss;
++ YYSTYPE yyvs;
++ };
++
++/* The size of the maximum gap between one aligned stack and the next. */
++# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
++
++/* The size of an array large to enough to hold all stacks, each with
++ N elements. */
++# define YYSTACK_BYTES(N) \
++ ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \
++ + YYSTACK_GAP_MAXIMUM)
++
++/* Copy COUNT objects from FROM to TO. The source and destination do
++ not overlap. */
++# ifndef YYCOPY
++# if defined (__GNUC__) && 1 < __GNUC__
++# define YYCOPY(To, From, Count) \
++ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
++# else
++# define YYCOPY(To, From, Count) \
++ do \
++ { \
++ register YYSIZE_T yyi; \
++ for (yyi = 0; yyi < (Count); yyi++) \
++ (To)[yyi] = (From)[yyi]; \
++ } \
++ while (0)
++# endif
++# endif
++
++/* Relocate STACK from its old location to the new one. The
++ local variables YYSIZE and YYSTACKSIZE give the old and new number of
++ elements in the stack, and YYPTR gives the new location of the
++ stack. Advance YYPTR to a properly aligned location for the next
++ stack. */
++# define YYSTACK_RELOCATE(Stack) \
++ do \
++ { \
++ YYSIZE_T yynewbytes; \
++ YYCOPY (&yyptr->Stack, Stack, yysize); \
++ Stack = &yyptr->Stack; \
++ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
++ yyptr += yynewbytes / sizeof (*yyptr); \
++ } \
++ while (0)
+
+-#ifndef __cplusplus
+-#ifndef __STDC__
+-#define const
+-#endif
+ #endif
+
++#if defined (__STDC__) || defined (__cplusplus)
++ typedef signed char yysigned_char;
++#else
++ typedef short int yysigned_char;
++#endif
+
+-
+-#define YYFINAL 117
+-#define YYFLAG -32768
+-#define YYNTBASE 41
+-
+-#define YYTRANSLATE(x) ((unsigned)(x) <= 292 ? yytranslate[x] : 71)
+-
+-static const char yytranslate[] = { 0,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 39, 2, 40, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 1, 3, 4, 5, 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
++/* YYFINAL -- State number of the termination state. */
++#define YYFINAL 53
++/* YYLAST -- Last index in YYTABLE. */
++#define YYLAST 108
++
++/* YYNTOKENS -- Number of terminals. */
++#define YYNTOKENS 41
++/* YYNNTS -- Number of nonterminals. */
++#define YYNNTS 31
++/* YYNRULES -- Number of rules. */
++#define YYNRULES 79
++/* YYNRULES -- Number of states. */
++#define YYNSTATES 117
++
++/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
++#define YYUNDEFTOK 2
++#define YYMAXUTOK 293
++
++#define YYTRANSLATE(YYX) \
++ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
++
++/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
++static const unsigned char yytranslate[] =
++{
++ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 39, 2, 40, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 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, 26, 27, 28, 29, 30, 31, 32, 33, 34,
++ 35, 36, 37, 38
+ };
+
+-#if YYDEBUG != 0
+-static const short yyprhs[] = { 0,
+- 0, 3, 4, 7, 8, 11, 14, 17, 20, 23,
+- 26, 29, 30, 35, 36, 40, 41, 44, 49, 52,
+- 54, 56, 58, 60, 62, 66, 67, 70, 72, 76,
+- 77, 80, 82, 86, 87, 90, 92, 96, 97, 100,
+- 102, 106, 107, 110, 113, 118, 120, 122, 124, 126,
+- 128, 131, 134, 137, 140, 143, 145, 147, 150, 152,
+- 154, 157, 158, 160, 162, 164, 166, 168, 170, 172,
+- 174, 176, 179, 180, 184, 186, 188, 190
++#if YYDEBUG
++/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
++ YYRHS. */
++static const unsigned char yyprhs[] =
++{
++ 0, 0, 3, 6, 7, 10, 11, 14, 17, 20,
++ 23, 26, 29, 32, 33, 38, 39, 43, 44, 47,
++ 52, 55, 57, 59, 61, 63, 65, 69, 70, 73,
++ 75, 79, 80, 83, 85, 89, 90, 93, 95, 99,
++ 100, 103, 105, 109, 110, 113, 116, 121, 123, 125,
++ 127, 129, 131, 134, 137, 140, 143, 146, 148, 150,
++ 153, 155, 157, 160, 161, 163, 165, 167, 169, 171,
++ 173, 175, 177, 179, 182, 183, 187, 189, 191, 193
+ };
+
+-static const short yyrhs[] = { 42,
+- 43, 0, 0, 44, 42, 0, 0, 45, 43, 0,
+- 3, 65, 0, 9, 50, 0, 14, 52, 0, 16,
+- 54, 0, 4, 56, 0, 25, 58, 0, 0, 28,
+- 38, 46, 47, 0, 0, 39, 48, 40, 0, 0,
+- 49, 48, 0, 21, 30, 22, 30, 0, 17, 66,
+- 0, 34, 0, 31, 0, 37, 0, 29, 0, 60,
+- 0, 39, 51, 40, 0, 0, 60, 51, 0, 61,
+- 0, 39, 53, 40, 0, 0, 61, 53, 0, 62,
+- 0, 39, 55, 40, 0, 0, 62, 55, 0, 63,
+- 0, 39, 57, 40, 0, 0, 63, 57, 0, 67,
+- 0, 39, 59, 40, 0, 0, 67, 59, 0, 3,
+- 65, 0, 21, 30, 22, 30, 0, 10, 0, 11,
+- 0, 12, 0, 13, 0, 19, 0, 17, 66, 0,
+- 3, 65, 0, 3, 65, 0, 15, 38, 0, 23,
+- 30, 0, 34, 0, 31, 0, 3, 65, 0, 32,
+- 0, 33, 0, 24, 64, 0, 0, 30, 0, 4,
+- 0, 5, 0, 6, 0, 7, 0, 8, 0, 18,
+- 0, 19, 0, 20, 0, 3, 65, 0, 0, 69,
+- 68, 70, 0, 26, 0, 27, 0, 35, 0, 36,
+- 0
++/* YYRHS -- A `-1'-separated list of the rules' RHS. */
++static const yysigned_char yyrhs[] =
++{
++ 42, 0, -1, 43, 44, -1, -1, 45, 43, -1,
++ -1, 46, 44, -1, 3, 66, -1, 9, 51, -1,
++ 14, 53, -1, 16, 55, -1, 4, 57, -1, 25,
++ 59, -1, -1, 28, 38, 47, 48, -1, -1, 39,
++ 49, 40, -1, -1, 50, 49, -1, 21, 30, 22,
++ 30, -1, 17, 67, -1, 34, -1, 31, -1, 37,
++ -1, 29, -1, 61, -1, 39, 52, 40, -1, -1,
++ 61, 52, -1, 62, -1, 39, 54, 40, -1, -1,
++ 62, 54, -1, 63, -1, 39, 56, 40, -1, -1,
++ 63, 56, -1, 64, -1, 39, 58, 40, -1, -1,
++ 64, 58, -1, 68, -1, 39, 60, 40, -1, -1,
++ 68, 60, -1, 3, 66, -1, 21, 30, 22, 30,
++ -1, 10, -1, 11, -1, 12, -1, 13, -1, 19,
++ -1, 17, 67, -1, 3, 66, -1, 3, 66, -1,
++ 15, 38, -1, 23, 30, -1, 34, -1, 31, -1,
++ 3, 66, -1, 32, -1, 33, -1, 24, 65, -1,
++ -1, 30, -1, 4, -1, 5, -1, 6, -1, 7,
++ -1, 8, -1, 18, -1, 19, -1, 20, -1, 3,
++ 66, -1, -1, 70, 69, 71, -1, 26, -1, 27,
++ -1, 35, -1, 36, -1
+ };
+
+-#endif
+-
+-#if YYDEBUG != 0
+-static const short yyrline[] = { 0,
+- 73, 77, 78, 81, 82, 105, 110, 111, 112, 113,
+- 114, 117, 138, 140, 141, 144, 145, 148, 153, 154,
+- 158, 162, 176, 182, 184, 187, 188, 191, 193, 196,
+- 197, 200, 202, 205, 206, 209, 211, 214, 215, 218,
+- 220, 223, 224, 227, 234, 238, 247, 256, 265, 274,
+- 279, 282, 290, 295, 299, 304, 308, 314, 319, 324,
+- 328, 334, 338, 344, 349, 353, 357, 361, 367, 372,
+- 376, 382, 387, 393, 395, 400, 406, 412
++/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
++static const unsigned short int yyrline[] =
++{
++ 0, 77, 77, 80, 81, 84, 85, 109, 113, 114,
++ 115, 116, 117, 122, 121, 151, 152, 155, 156, 160,
++ 164, 165, 169, 173, 187, 194, 195, 198, 199, 203,
++ 204, 207, 208, 212, 213, 216, 217, 221, 222, 225,
++ 226, 230, 231, 234, 235, 239, 245, 249, 258, 267,
++ 276, 285, 290, 294, 302, 306, 310, 315, 319, 326,
++ 330, 335, 339, 346, 349, 356, 360, 364, 368, 372,
++ 379, 383, 387, 394, 399, 398, 407, 411, 418, 423
+ };
+ #endif
+
+-
+-#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
+-
+-static const char * const yytname[] = { "$","error","$undefined.","TOK_LEVEL",
+-"TOK_DEBUG","TOK_INFO","TOK_WARN","TOK_ERROR","TOK_FATAL","TOK_SIG","TOK_UNI30",
+-"TOK_UNI31","TOK_UNI40","TOK_Q2963_1","TOK_SAAL","TOK_VC","TOK_IO","TOK_MODE",
+-"TOK_USER","TOK_NET","TOK_SWITCH","TOK_VPCI","TOK_ITF","TOK_PCR","TOK_TRACE",
+-"TOK_POLICY","TOK_ALLOW","TOK_REJECT","TOK_ENTITY","TOK_DEFAULT","TOK_NUMBER",
+-"TOK_MAX_RATE","TOK_DUMP_DIR","TOK_LOGFILE","TOK_QOS","TOK_FROM","TOK_TO","TOK_ROUTE",
+-"TOK_PVC","'{'","'}'","all","global","local","item","entity","@1","opt_options",
+-"options","option","sig","sig_items","saal","saal_items","io","io_items","debug",
+-"debug_items","policy","policy_items","sig_item","saal_item","io_item","debug_item",
+-"opt_trace_size","level","mode","policy_item","@2","action","direction", NULL
++#if YYDEBUG || YYERROR_VERBOSE
++/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
++ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
++static const char *const yytname[] =
++{
++ "$end", "error", "$undefined", "TOK_LEVEL", "TOK_DEBUG", "TOK_INFO",
++ "TOK_WARN", "TOK_ERROR", "TOK_FATAL", "TOK_SIG", "TOK_UNI30",
++ "TOK_UNI31", "TOK_UNI40", "TOK_Q2963_1", "TOK_SAAL", "TOK_VC", "TOK_IO",
++ "TOK_MODE", "TOK_USER", "TOK_NET", "TOK_SWITCH", "TOK_VPCI", "TOK_ITF",
++ "TOK_PCR", "TOK_TRACE", "TOK_POLICY", "TOK_ALLOW", "TOK_REJECT",
++ "TOK_ENTITY", "TOK_DEFAULT", "TOK_NUMBER", "TOK_MAX_RATE",
++ "TOK_DUMP_DIR", "TOK_LOGFILE", "TOK_QOS", "TOK_FROM", "TOK_TO",
++ "TOK_ROUTE", "TOK_PVC", "'{'", "'}'", "$accept", "all", "global",
++ "local", "item", "entity", "@1", "opt_options", "options", "option",
++ "sig", "sig_items", "saal", "saal_items", "io", "io_items", "debug",
++ "debug_items", "policy", "policy_items", "sig_item", "saal_item",
++ "io_item", "debug_item", "opt_trace_size", "level", "mode",
++ "policy_item", "@2", "action", "direction", 0
+ };
+ #endif
+
+-static const short yyr1[] = { 0,
+- 41, 42, 42, 43, 43, 44, 44, 44, 44, 44,
+- 44, 46, 45, 47, 47, 48, 48, 49, 49, 49,
+- 49, 49, 49, 50, 50, 51, 51, 52, 52, 53,
+- 53, 54, 54, 55, 55, 56, 56, 57, 57, 58,
+- 58, 59, 59, 60, 60, 60, 60, 60, 60, 60,
+- 60, 61, 62, 62, 62, 62, 62, 63, 63, 63,
+- 63, 64, 64, 65, 65, 65, 65, 65, 66, 66,
+- 66, 67, 68, 67, 69, 69, 70, 70
++# ifdef YYPRINT
++/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
++ token YYLEX-NUM. */
++static const unsigned short int yytoknum[] =
++{
++ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
++ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
++ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
++ 285, 286, 287, 288, 289, 290, 291, 292, 293, 123,
++ 125
+ };
++# endif
+
+-static const short yyr2[] = { 0,
+- 2, 0, 2, 0, 2, 2, 2, 2, 2, 2,
+- 2, 0, 4, 0, 3, 0, 2, 4, 2, 1,
+- 1, 1, 1, 1, 3, 0, 2, 1, 3, 0,
+- 2, 1, 3, 0, 2, 1, 3, 0, 2, 1,
+- 3, 0, 2, 2, 4, 1, 1, 1, 1, 1,
+- 2, 2, 2, 2, 2, 1, 1, 2, 1, 1,
+- 2, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+- 1, 2, 0, 3, 1, 1, 1, 1
++/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
++static const unsigned char yyr1[] =
++{
++ 0, 41, 42, 43, 43, 44, 44, 45, 45, 45,
++ 45, 45, 45, 47, 46, 48, 48, 49, 49, 50,
++ 50, 50, 50, 50, 50, 51, 51, 52, 52, 53,
++ 53, 54, 54, 55, 55, 56, 56, 57, 57, 58,
++ 58, 59, 59, 60, 60, 61, 61, 61, 61, 61,
++ 61, 61, 61, 62, 63, 63, 63, 63, 63, 64,
++ 64, 64, 64, 65, 65, 66, 66, 66, 66, 66,
++ 67, 67, 67, 68, 69, 68, 70, 70, 71, 71
+ };
+
+-static const short yydefact[] = { 2,
+- 0, 0, 0, 0, 0, 0, 4, 2, 64, 65,
+- 66, 67, 68, 6, 0, 62, 59, 60, 38, 10,
+- 36, 0, 46, 47, 48, 49, 0, 50, 0, 26,
+- 7, 24, 0, 30, 8, 28, 0, 0, 0, 57,
+- 56, 34, 9, 32, 0, 75, 76, 42, 11, 40,
+- 73, 0, 1, 4, 3, 58, 63, 61, 0, 38,
+- 44, 69, 70, 71, 51, 0, 0, 26, 52, 0,
+- 30, 53, 54, 55, 0, 34, 72, 0, 42, 0,
+- 12, 5, 37, 39, 0, 25, 27, 29, 31, 33,
+- 35, 41, 43, 77, 78, 74, 14, 45, 16, 13,
+- 0, 0, 23, 21, 20, 22, 0, 16, 19, 0,
+- 15, 17, 0, 18, 0, 0, 0
++/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
++static const unsigned char yyr2[] =
++{
++ 0, 2, 2, 0, 2, 0, 2, 2, 2, 2,
++ 2, 2, 2, 0, 4, 0, 3, 0, 2, 4,
++ 2, 1, 1, 1, 1, 1, 3, 0, 2, 1,
++ 3, 0, 2, 1, 3, 0, 2, 1, 3, 0,
++ 2, 1, 3, 0, 2, 2, 4, 1, 1, 1,
++ 1, 1, 2, 2, 2, 2, 2, 1, 1, 2,
++ 1, 1, 2, 0, 1, 1, 1, 1, 1, 1,
++ 1, 1, 1, 2, 0, 3, 1, 1, 1, 1
+ };
+
+-static const short yydefgoto[] = { 115,
+- 7, 53, 8, 54, 97, 100, 107, 108, 31, 67,
+- 35, 70, 43, 75, 20, 59, 49, 78, 68, 71,
+- 76, 60, 58, 14, 65, 79, 80, 51, 96
++/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
++ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
++ means the default is an error. */
++static const unsigned char yydefact[] =
++{
++ 3, 0, 0, 0, 0, 0, 0, 0, 5, 3,
++ 65, 66, 67, 68, 69, 7, 0, 63, 60, 61,
++ 39, 11, 37, 0, 47, 48, 49, 50, 0, 51,
++ 0, 27, 8, 25, 0, 31, 9, 29, 0, 0,
++ 0, 58, 57, 35, 10, 33, 0, 76, 77, 43,
++ 12, 41, 74, 1, 0, 2, 5, 4, 59, 64,
++ 62, 0, 39, 45, 70, 71, 72, 52, 0, 0,
++ 27, 53, 0, 31, 54, 55, 56, 0, 35, 73,
++ 0, 43, 0, 13, 6, 38, 40, 0, 26, 28,
++ 30, 32, 34, 36, 42, 44, 78, 79, 75, 15,
++ 46, 17, 14, 0, 0, 24, 22, 21, 23, 0,
++ 17, 20, 0, 16, 18, 0, 19
+ };
+
+-static const short yypact[] = { 52,
+- 100, 1, -3, -1, -2, 0, -17, 52,-32768,-32768,
+--32768,-32768,-32768,-32768, 100, -18,-32768,-32768, 25,-32768,
+--32768, 100,-32768,-32768,-32768,-32768, 60,-32768, -15, 82,
+--32768,-32768, 100, 14,-32768,-32768, 100, -19, -10,-32768,
+--32768, 20,-32768,-32768, 100,-32768,-32768, 19,-32768,-32768,
+--32768, -14,-32768, -17,-32768,-32768,-32768,-32768, -9, 25,
+--32768,-32768,-32768,-32768,-32768, 8, 2, 82,-32768, 4,
+- 14,-32768,-32768,-32768, 7, 20,-32768, 10, 19, -30,
+--32768,-32768,-32768,-32768, 22,-32768,-32768,-32768,-32768,-32768,
+--32768,-32768,-32768,-32768,-32768,-32768, 21,-32768, 53,-32768,
+- 60, 23,-32768,-32768,-32768,-32768, 24, 53,-32768, 40,
+--32768,-32768, 35,-32768, 67, 69,-32768
++/* YYDEFGOTO[NTERM-NUM]. */
++static const yysigned_char yydefgoto[] =
++{
++ -1, 7, 8, 55, 9, 56, 99, 102, 109, 110,
++ 32, 69, 36, 72, 44, 77, 21, 61, 50, 80,
++ 70, 73, 78, 62, 60, 15, 67, 81, 82, 52,
++ 98
+ };
+
+-static const short yypgoto[] = {-32768,
+- 64, 27,-32768,-32768,-32768,-32768, -35,-32768,-32768, 15,
+--32768, 5,-32768, 12,-32768, 29,-32768, -4, 83, 87,
+- 91, 95,-32768, 26, 9, 92,-32768,-32768,-32768
++/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
++ STATE-NUM. */
++#define YYPACT_NINF -31
++static const yysigned_char yypact[] =
++{
++ 53, 69, 1, -3, -1, -2, 0, 11, -16, 53,
++ -31, -31, -31, -31, -31, -31, 69, -15, -31, -31,
++ 28, -31, -31, 69, -31, -31, -31, -31, 46, -31,
++ -13, 80, -31, -31, 69, 16, -31, -31, 69, -18,
++ -6, -31, -31, 20, -31, -31, 69, -31, -31, 19,
++ -31, -31, -31, -31, -10, -31, -16, -31, -31, -31,
++ -31, 2, 28, -31, -31, -31, -31, -31, 8, 4,
++ 80, -31, 7, 16, -31, -31, -31, 9, 20, -31,
++ 10, 19, -30, -31, -31, -31, -31, 23, -31, -31,
++ -31, -31, -31, -31, -31, -31, -31, -31, -31, 31,
++ -31, 51, -31, 46, 49, -31, -31, -31, -31, 15,
++ 51, -31, 36, -31, -31, 54, -31
+ };
+
+-
+-#define YYLAST 110
+-
+-
+-static const short yytable[] = { 22,
+- 37, 33, 45, 15, 94, 95, 23, 24, 25, 26,
+- 52, 57, 38, 27, 66, 28, 33, 29, 73, 74,
+- 39, 45, 37, 81, 16, 46, 47, 15, 40, 85,
+- 83, 41, 17, 18, 38, 30, 42, 34, 48, 19,
+- 56, 86, 39, 88, 46, 47, 90, 61, 16, 92,
+- 40, 98, 110, 41, 1, 2, 17, 18, 69, 99,
+- 3, 113, 72, 111, 114, 4, 116, 5, 117, 101,
+- 77, 55, 112, 102, 93, 89, 6, 62, 63, 64,
+- 82, 103, 87, 104, 22, 32, 105, 91, 84, 106,
+- 36, 23, 24, 25, 26, 44, 21, 50, 27, 0,
+- 28, 0, 29, 9, 10, 11, 12, 13, 0, 109
++/* YYPGOTO[NTERM-NUM]. */
++static const yysigned_char yypgoto[] =
++{
++ -31, -31, 72, 30, -31, -31, -31, -31, -23, -31,
++ -31, 24, -31, 22, -31, 18, -31, 27, -31, 17,
++ 97, 98, 99, 101, -31, 25, 3, 102, -31, -31,
++ -31
+ };
+
+-static const short yycheck[] = { 3,
+- 3, 3, 3, 3, 35, 36, 10, 11, 12, 13,
+- 28, 30, 15, 17, 30, 19, 3, 21, 38, 30,
+- 23, 3, 3, 38, 24, 26, 27, 3, 31, 22,
+- 40, 34, 32, 33, 15, 39, 39, 39, 39, 39,
+- 15, 40, 23, 40, 26, 27, 40, 22, 24, 40,
+- 31, 30, 30, 34, 3, 4, 32, 33, 33, 39,
+- 9, 22, 37, 40, 30, 14, 0, 16, 0, 17,
+- 45, 8, 108, 21, 79, 71, 25, 18, 19, 20,
+- 54, 29, 68, 31, 3, 3, 34, 76, 60, 37,
+- 4, 10, 11, 12, 13, 5, 2, 6, 17, -1,
+- 19, -1, 21, 4, 5, 6, 7, 8, -1, 101
++/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
++ positive, shift that token. If negative, reduce the rule which
++ number is the opposite. If zero, do what YYDEFACT says.
++ If YYTABLE_NINF, syntax error. */
++#define YYTABLE_NINF -1
++static const unsigned char yytable[] =
++{
++ 23, 38, 34, 46, 16, 96, 97, 24, 25, 26,
++ 27, 53, 54, 39, 28, 59, 29, 68, 30, 34,
++ 75, 40, 46, 38, 76, 17, 47, 48, 83, 41,
++ 87, 16, 42, 18, 19, 39, 31, 43, 35, 49,
++ 20, 58, 85, 40, 88, 47, 48, 90, 63, 92,
++ 94, 41, 17, 100, 42, 113, 1, 2, 115, 71,
++ 18, 19, 3, 74, 64, 65, 66, 4, 103, 5,
++ 101, 79, 104, 10, 11, 12, 13, 14, 6, 112,
++ 105, 57, 106, 23, 116, 107, 84, 114, 108, 86,
++ 24, 25, 26, 27, 89, 91, 93, 28, 95, 29,
++ 33, 30, 37, 22, 45, 0, 111, 0, 51
+ };
+-/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
+-#line 3 "/usr/lib/bison.simple"
+-/* This file comes from bison-1.28. */
+-
+-/* Skeleton output parser for bison,
+- Copyright (C) 1984, 1989, 1990 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. */
+-
+-/* As a special exception, when this file is copied by Bison into a
+- Bison output file, you may use that output file without restriction.
+- This special exception was added by the Free Software Foundation
+- in version 1.24 of Bison. */
++static const yysigned_char yycheck[] =
++{
++ 3, 3, 3, 3, 3, 35, 36, 10, 11, 12,
++ 13, 0, 28, 15, 17, 30, 19, 30, 21, 3,
++ 38, 23, 3, 3, 30, 24, 26, 27, 38, 31,
++ 22, 3, 34, 32, 33, 15, 39, 39, 39, 39,
++ 39, 16, 40, 23, 40, 26, 27, 40, 23, 40,
++ 40, 31, 24, 30, 34, 40, 3, 4, 22, 34,
++ 32, 33, 9, 38, 18, 19, 20, 14, 17, 16,
++ 39, 46, 21, 4, 5, 6, 7, 8, 25, 30,
++ 29, 9, 31, 3, 30, 34, 56, 110, 37, 62,
++ 10, 11, 12, 13, 70, 73, 78, 17, 81, 19,
++ 3, 21, 4, 2, 5, -1, 103, -1, 6
++};
+
+-/* This is the parser code that is written into each bison parser
+- when the %semantic_parser declaration is not specified in the grammar.
+- It was written by Richard Stallman by simplifying the hairy parser
+- used when %semantic_parser is specified. */
+-
+-#ifndef YYSTACK_USE_ALLOCA
+-#ifdef alloca
+-#define YYSTACK_USE_ALLOCA
+-#else /* alloca not defined */
+-#ifdef __GNUC__
+-#define YYSTACK_USE_ALLOCA
+-#define alloca __builtin_alloca
+-#else /* not GNU C. */
+-#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
+-#define YYSTACK_USE_ALLOCA
+-#include <alloca.h>
+-#else /* not sparc */
+-/* We think this test detects Watcom and Microsoft C. */
+-/* This used to test MSDOS, but that is a bad idea
+- since that symbol is in the user namespace. */
+-#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
+-#if 0 /* No need for malloc.h, which pollutes the namespace;
+- instead, just don't use alloca. */
+-#include <malloc.h>
+-#endif
+-#else /* not MSDOS, or __TURBOC__ */
+-#if defined(_AIX)
+-/* I don't know what this was needed for, but it pollutes the namespace.
+- So I turned it off. rms, 2 May 1997. */
+-/* #include <malloc.h> */
+- #pragma alloca
+-#define YYSTACK_USE_ALLOCA
+-#else /* not MSDOS, or __TURBOC__, or _AIX */
+-#if 0
+-#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
+- and on HPUX 10. Eventually we can turn this on. */
+-#define YYSTACK_USE_ALLOCA
+-#define alloca __builtin_alloca
+-#endif /* __hpux */
+-#endif
+-#endif /* not _AIX */
+-#endif /* not MSDOS, or __TURBOC__ */
+-#endif /* not sparc */
+-#endif /* not GNU C */
+-#endif /* alloca not defined */
+-#endif /* YYSTACK_USE_ALLOCA not defined */
++/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
++ symbol of state STATE-NUM. */
++static const unsigned char yystos[] =
++{
++ 0, 3, 4, 9, 14, 16, 25, 42, 43, 45,
++ 4, 5, 6, 7, 8, 66, 3, 24, 32, 33,
++ 39, 57, 64, 3, 10, 11, 12, 13, 17, 19,
++ 21, 39, 51, 61, 3, 39, 53, 62, 3, 15,
++ 23, 31, 34, 39, 55, 63, 3, 26, 27, 39,
++ 59, 68, 70, 0, 28, 44, 46, 43, 66, 30,
++ 65, 58, 64, 66, 18, 19, 20, 67, 30, 52,
++ 61, 66, 54, 62, 66, 38, 30, 56, 63, 66,
++ 60, 68, 69, 38, 44, 40, 58, 22, 40, 52,
++ 40, 54, 40, 56, 40, 60, 35, 36, 71, 47,
++ 30, 39, 48, 17, 21, 29, 31, 34, 37, 49,
++ 50, 67, 30, 40, 49, 22, 30
++};
+
+-#ifdef YYSTACK_USE_ALLOCA
+-#define YYSTACK_ALLOC alloca
+-#else
+-#define YYSTACK_ALLOC malloc
++#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
++# define YYSIZE_T __SIZE_TYPE__
++#endif
++#if ! defined (YYSIZE_T) && defined (size_t)
++# define YYSIZE_T size_t
++#endif
++#if ! defined (YYSIZE_T)
++# if defined (__STDC__) || defined (__cplusplus)
++# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
++# define YYSIZE_T size_t
++# endif
++#endif
++#if ! defined (YYSIZE_T)
++# define YYSIZE_T unsigned int
+ #endif
+-
+-/* Note: there must be only one dollar sign in this file.
+- It is replaced by the list of actions, each action
+- as one case of the switch. */
+
+ #define yyerrok (yyerrstatus = 0)
+ #define yyclearin (yychar = YYEMPTY)
+-#define YYEMPTY -2
++#define YYEMPTY (-2)
+ #define YYEOF 0
++
+ #define YYACCEPT goto yyacceptlab
+-#define YYABORT goto yyabortlab
+-#define YYERROR goto yyerrlab1
+-/* Like YYERROR except do call yyerror.
+- This remains here temporarily to ease the
+- transition to the new meaning of YYERROR, for GCC.
++#define YYABORT goto yyabortlab
++#define YYERROR goto yyerrorlab
++
++
++/* Like YYERROR except do call yyerror. This remains here temporarily
++ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
++
+ #define YYFAIL goto yyerrlab
++
+ #define YYRECOVERING() (!!yyerrstatus)
+-#define YYBACKUP(token, value) \
++
++#define YYBACKUP(Token, Value) \
+ do \
+ if (yychar == YYEMPTY && yylen == 1) \
+- { yychar = (token), yylval = (value); \
+- yychar1 = YYTRANSLATE (yychar); \
++ { \
++ yychar = (Token); \
++ yylval = (Value); \
++ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+- { yyerror ("syntax error: cannot back up"); YYERROR; } \
++ { \
++ yyerror ("syntax error: cannot back up");\
++ YYERROR; \
++ } \
+ while (0)
+
+ #define YYTERROR 1
+ #define YYERRCODE 256
+
+-#ifndef YYPURE
+-#define YYLEX yylex()
+-#endif
++/* YYLLOC_DEFAULT -- Compute the default location (before the actions
++ are run). */
+
+-#ifdef YYPURE
+-#ifdef YYLSP_NEEDED
+-#ifdef YYLEX_PARAM
+-#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
+-#else
+-#define YYLEX yylex(&yylval, &yylloc)
++#ifndef YYLLOC_DEFAULT
++# define YYLLOC_DEFAULT(Current, Rhs, N) \
++ ((Current).first_line = (Rhs)[1].first_line, \
++ (Current).first_column = (Rhs)[1].first_column, \
++ (Current).last_line = (Rhs)[N].last_line, \
++ (Current).last_column = (Rhs)[N].last_column)
+ #endif
+-#else /* not YYLSP_NEEDED */
++
++/* YYLEX -- calling `yylex' with the right arguments. */
++
+ #ifdef YYLEX_PARAM
+-#define YYLEX yylex(&yylval, YYLEX_PARAM)
++# define YYLEX yylex (YYLEX_PARAM)
+ #else
+-#define YYLEX yylex(&yylval)
+-#endif
+-#endif /* not YYLSP_NEEDED */
++# define YYLEX yylex ()
+ #endif
+
+-/* If nonreentrant, generate the variables here */
++/* Enable debugging if requested. */
++#if YYDEBUG
+
+-#ifndef YYPURE
++# ifndef YYFPRINTF
++# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
++# define YYFPRINTF fprintf
++# endif
++
++# define YYDPRINTF(Args) \
++do { \
++ if (yydebug) \
++ YYFPRINTF Args; \
++} while (0)
++
++# define YYDSYMPRINT(Args) \
++do { \
++ if (yydebug) \
++ yysymprint Args; \
++} while (0)
++
++# define YYDSYMPRINTF(Title, Token, Value, Location) \
++do { \
++ if (yydebug) \
++ { \
++ YYFPRINTF (stderr, "%s ", Title); \
++ yysymprint (stderr, \
++ Token, Value); \
++ YYFPRINTF (stderr, "\n"); \
++ } \
++} while (0)
+
+-int yychar; /* the lookahead symbol */
+-YYSTYPE yylval; /* the semantic value of the */
+- /* lookahead symbol */
++/*------------------------------------------------------------------.
++| yy_stack_print -- Print the state stack from its BOTTOM up to its |
++| TOP (included). |
++`------------------------------------------------------------------*/
+
+-#ifdef YYLSP_NEEDED
+-YYLTYPE yylloc; /* location data for the lookahead */
+- /* symbol */
++#if defined (__STDC__) || defined (__cplusplus)
++static void
++yy_stack_print (short int *bottom, short int *top)
++#else
++static void
++yy_stack_print (bottom, top)
++ short int *bottom;
++ short int *top;
+ #endif
++{
++ YYFPRINTF (stderr, "Stack now");
++ for (/* Nothing. */; bottom <= top; ++bottom)
++ YYFPRINTF (stderr, " %d", *bottom);
++ YYFPRINTF (stderr, "\n");
++}
++
++# define YY_STACK_PRINT(Bottom, Top) \
++do { \
++ if (yydebug) \
++ yy_stack_print ((Bottom), (Top)); \
++} while (0)
+
+-int yynerrs; /* number of parse errors so far */
+-#endif /* not YYPURE */
+
+-#if YYDEBUG != 0
+-int yydebug; /* nonzero means print parse trace */
+-/* Since this is uninitialized, it does not stop multiple parsers
+- from coexisting. */
++/*------------------------------------------------.
++| Report that the YYRULE is going to be reduced. |
++`------------------------------------------------*/
++
++#if defined (__STDC__) || defined (__cplusplus)
++static void
++yy_reduce_print (int yyrule)
++#else
++static void
++yy_reduce_print (yyrule)
++ int yyrule;
+ #endif
++{
++ int yyi;
++ unsigned int yylno = yyrline[yyrule];
++ YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
++ yyrule - 1, yylno);
++ /* Print the symbols being reduced, and their result. */
++ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
++ YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
++ YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
++}
++
++# define YY_REDUCE_PRINT(Rule) \
++do { \
++ if (yydebug) \
++ yy_reduce_print (Rule); \
++} while (0)
++
++/* Nonzero means print parse trace. It is left uninitialized so that
++ multiple parsers can coexist. */
++int yydebug;
++#else /* !YYDEBUG */
++# define YYDPRINTF(Args)
++# define YYDSYMPRINT(Args)
++# define YYDSYMPRINTF(Title, Token, Value, Location)
++# define YY_STACK_PRINT(Bottom, Top)
++# define YY_REDUCE_PRINT(Rule)
++#endif /* !YYDEBUG */
+
+-/* YYINITDEPTH indicates the initial size of the parser's stacks */
+
++/* YYINITDEPTH -- initial size of the parser's stacks. */
+ #ifndef YYINITDEPTH
+-#define YYINITDEPTH 200
++# define YYINITDEPTH 200
+ #endif
+
+-/* YYMAXDEPTH is the maximum size the stacks can grow to
+- (effective only if the built-in stack extension method is used). */
++/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
++ if the built-in stack extension method is used).
+
+-#if YYMAXDEPTH == 0
+-#undef YYMAXDEPTH
++ Do not make this value too large; the results are undefined if
++ SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
++ evaluated with infinite-precision integer arithmetic. */
++
++#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
++# undef YYMAXDEPTH
+ #endif
+
+ #ifndef YYMAXDEPTH
+-#define YYMAXDEPTH 10000
++# define YYMAXDEPTH 10000
+ #endif
++
+
+-/* Define __yy_memcpy. Note that the size argument
+- should be passed with type unsigned int, because that is what the non-GCC
+- definitions require. With GCC, __builtin_memcpy takes an arg
+- of type size_t, but it can handle unsigned int. */
+-
+-#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
+-#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
+-#else /* not GNU C or C++ */
+-#ifndef __cplusplus
+
+-/* This is the most reliable way to avoid incompatibilities
+- in available built-in functions on various systems. */
+-static void
+-__yy_memcpy (to, from, count)
+- char *to;
+- char *from;
+- unsigned int count;
+-{
+- register char *f = from;
+- register char *t = to;
+- register int i = count;
++#if YYERROR_VERBOSE
+
+- while (i-- > 0)
+- *t++ = *f++;
++# ifndef yystrlen
++# if defined (__GLIBC__) && defined (_STRING_H)
++# define yystrlen strlen
++# else
++/* Return the length of YYSTR. */
++static YYSIZE_T
++# if defined (__STDC__) || defined (__cplusplus)
++yystrlen (const char *yystr)
++# else
++yystrlen (yystr)
++ const char *yystr;
++# endif
++{
++ register const char *yys = yystr;
++
++ while (*yys++ != '\0')
++ continue;
++
++ return yys - yystr - 1;
+ }
++# endif
++# endif
+
+-#else /* __cplusplus */
++# ifndef yystpcpy
++# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
++# define yystpcpy stpcpy
++# else
++/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
++ YYDEST. */
++static char *
++# if defined (__STDC__) || defined (__cplusplus)
++yystpcpy (char *yydest, const char *yysrc)
++# else
++yystpcpy (yydest, yysrc)
++ char *yydest;
++ const char *yysrc;
++# endif
++{
++ register char *yyd = yydest;
++ register const char *yys = yysrc;
++
++ while ((*yyd++ = *yys++) != '\0')
++ continue;
++
++ return yyd - 1;
++}
++# endif
++# endif
+
+-/* This is the most reliable way to avoid incompatibilities
+- in available built-in functions on various systems. */
++#endif /* !YYERROR_VERBOSE */
++
++
++
++#if YYDEBUG
++/*--------------------------------.
++| Print this symbol on YYOUTPUT. |
++`--------------------------------*/
++
++#if defined (__STDC__) || defined (__cplusplus)
+ static void
+-__yy_memcpy (char *to, char *from, unsigned int count)
++yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
++#else
++static void
++yysymprint (yyoutput, yytype, yyvaluep)
++ FILE *yyoutput;
++ int yytype;
++ YYSTYPE *yyvaluep;
++#endif
+ {
+- register char *t = to;
+- register char *f = from;
+- register int i = count;
++ /* Pacify ``unused variable'' warnings. */
++ (void) yyvaluep;
+
+- while (i-- > 0)
+- *t++ = *f++;
++ if (yytype < YYNTOKENS)
++ {
++ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
++# ifdef YYPRINT
++ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
++# endif
++ }
++ else
++ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
++
++ switch (yytype)
++ {
++ default:
++ break;
++ }
++ YYFPRINTF (yyoutput, ")");
+ }
+
++#endif /* ! YYDEBUG */
++/*-----------------------------------------------.
++| Release the memory associated to this symbol. |
++`-----------------------------------------------*/
++
++#if defined (__STDC__) || defined (__cplusplus)
++static void
++yydestruct (int yytype, YYSTYPE *yyvaluep)
++#else
++static void
++yydestruct (yytype, yyvaluep)
++ int yytype;
++ YYSTYPE *yyvaluep;
+ #endif
+-#endif
++{
++ /* Pacify ``unused variable'' warnings. */
++ (void) yyvaluep;
++
++ switch (yytype)
++ {
++
++ default:
++ break;
++ }
++}
+
+-#line 217 "/usr/lib/bison.simple"
+
+-/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+- into yyparse. The argument should have type void *.
+- It should actually point to an object.
+- Grammar actions can access the variable by casting it
+- to the proper pointer type. */
++/* Prevent warnings from -Wmissing-prototypes. */
+
+ #ifdef YYPARSE_PARAM
+-#ifdef __cplusplus
+-#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+-#define YYPARSE_PARAM_DECL
+-#else /* not __cplusplus */
+-#define YYPARSE_PARAM_ARG YYPARSE_PARAM
+-#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+-#endif /* not __cplusplus */
+-#else /* not YYPARSE_PARAM */
+-#define YYPARSE_PARAM_ARG
+-#define YYPARSE_PARAM_DECL
+-#endif /* not YYPARSE_PARAM */
++# if defined (__STDC__) || defined (__cplusplus)
++int yyparse (void *YYPARSE_PARAM);
++# else
++int yyparse ();
++# endif
++#else /* ! YYPARSE_PARAM */
++#if defined (__STDC__) || defined (__cplusplus)
++int yyparse (void);
++#else
++int yyparse ();
++#endif
++#endif /* ! YYPARSE_PARAM */
++
++
++
++/* The lookahead symbol. */
++int yychar;
++
++/* The semantic value of the lookahead symbol. */
++YYSTYPE yylval;
++
++/* Number of syntax errors so far. */
++int yynerrs;
++
++
++
++/*----------.
++| yyparse. |
++`----------*/
+
+-/* Prevent warning if -Wstrict-prototypes. */
+-#ifdef __GNUC__
+ #ifdef YYPARSE_PARAM
+-int yyparse (void *);
++# if defined (__STDC__) || defined (__cplusplus)
++int yyparse (void *YYPARSE_PARAM)
++# else
++int yyparse (YYPARSE_PARAM)
++ void *YYPARSE_PARAM;
++# endif
++#else /* ! YYPARSE_PARAM */
++#if defined (__STDC__) || defined (__cplusplus)
++int
++yyparse (void)
+ #else
+-int yyparse (void);
++int
++yyparse ()
++
+ #endif
+ #endif
+-
+-int
+-yyparse(YYPARSE_PARAM_ARG)
+- YYPARSE_PARAM_DECL
+ {
++
+ register int yystate;
+ register int yyn;
+- register short *yyssp;
++ int yyresult;
++ /* Number of tokens to shift before error messages enabled. */
++ int yyerrstatus;
++ /* Lookahead token as an internal (translated) token number. */
++ int yytoken = 0;
++
++ /* Three stacks and their tools:
++ `yyss': related to states,
++ `yyvs': related to semantic values,
++ `yyls': related to locations.
++
++ Refer to the stacks thru separate pointers, to allow yyoverflow
++ to reallocate them elsewhere. */
++
++ /* The state stack. */
++ short int yyssa[YYINITDEPTH];
++ short int *yyss = yyssa;
++ register short int *yyssp;
++
++ /* The semantic value stack. */
++ YYSTYPE yyvsa[YYINITDEPTH];
++ YYSTYPE *yyvs = yyvsa;
+ register YYSTYPE *yyvsp;
+- int yyerrstatus; /* number of tokens to shift before error messages enabled */
+- int yychar1 = 0; /* lookahead token as an internal (translated) token number */
+
+- short yyssa[YYINITDEPTH]; /* the state stack */
+- YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
+
+- short *yyss = yyssa; /* refer to the stacks thru separate pointers */
+- YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
+
+-#ifdef YYLSP_NEEDED
+- YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
+- YYLTYPE *yyls = yylsa;
+- YYLTYPE *yylsp;
+-
+-#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
+-#else
+ #define YYPOPSTACK (yyvsp--, yyssp--)
+-#endif
+
+- int yystacksize = YYINITDEPTH;
+- int yyfree_stacks = 0;
++ YYSIZE_T yystacksize = YYINITDEPTH;
+
+-#ifdef YYPURE
+- int yychar;
+- YYSTYPE yylval;
+- int yynerrs;
+-#ifdef YYLSP_NEEDED
+- YYLTYPE yylloc;
+-#endif
+-#endif
++ /* The variables used to return semantic value and location from the
++ action routines. */
++ YYSTYPE yyval;
+
+- YYSTYPE yyval; /* the variable used to return */
+- /* semantic values from the action */
+- /* routines */
+
++ /* When reducing, the number of symbols on the RHS of the reduced
++ rule. */
+ int yylen;
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Starting parse\n");
+-#endif
++ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+@@ -614,110 +1022,97 @@
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+- yyssp = yyss - 1;
++ yyssp = yyss;
+ yyvsp = yyvs;
+-#ifdef YYLSP_NEEDED
+- yylsp = yyls;
+-#endif
+
+-/* Push a new state, which is found in yystate . */
+-/* In all cases, when you get here, the value and location stacks
+- have just been pushed. so pushing a state here evens the stacks. */
+-yynewstate:
+
+- *++yyssp = yystate;
++ goto yysetstate;
+
+- if (yyssp >= yyss + yystacksize - 1)
+- {
+- /* Give user a chance to reallocate the stack */
+- /* Use copies of these so that the &'s don't force the real ones into memory. */
+- YYSTYPE *yyvs1 = yyvs;
+- short *yyss1 = yyss;
+-#ifdef YYLSP_NEEDED
+- YYLTYPE *yyls1 = yyls;
+-#endif
++/*------------------------------------------------------------.
++| yynewstate -- Push a new state, which is found in yystate. |
++`------------------------------------------------------------*/
++ yynewstate:
++ /* In all cases, when you get here, the value and location stacks
++ have just been pushed. so pushing a state here evens the stacks.
++ */
++ yyssp++;
+
++ yysetstate:
++ *yyssp = yystate;
++
++ if (yyss + yystacksize - 1 <= yyssp)
++ {
+ /* Get the current used size of the three stacks, in elements. */
+- int size = yyssp - yyss + 1;
++ YYSIZE_T yysize = yyssp - yyss + 1;
+
+ #ifdef yyoverflow
+- /* Each stack pointer address is followed by the size of
+- the data in use in that stack, in bytes. */
+-#ifdef YYLSP_NEEDED
+- /* This used to be a conditional around just the two extra args,
+- but that might be undefined if yyoverflow is a macro. */
+- yyoverflow("parser stack overflow",
+- &yyss1, size * sizeof (*yyssp),
+- &yyvs1, size * sizeof (*yyvsp),
+- &yyls1, size * sizeof (*yylsp),
+- &yystacksize);
+-#else
+- yyoverflow("parser stack overflow",
+- &yyss1, size * sizeof (*yyssp),
+- &yyvs1, size * sizeof (*yyvsp),
+- &yystacksize);
+-#endif
+-
+- yyss = yyss1; yyvs = yyvs1;
+-#ifdef YYLSP_NEEDED
+- yyls = yyls1;
+-#endif
++ {
++ /* Give user a chance to reallocate the stack. Use copies of
++ these so that the &'s don't force the real ones into
++ memory. */
++ YYSTYPE *yyvs1 = yyvs;
++ short int *yyss1 = yyss;
++
++
++ /* Each stack pointer address is followed by the size of the
++ data in use in that stack, in bytes. This used to be a
++ conditional around just the two extra args, but that might
++ be undefined if yyoverflow is a macro. */
++ yyoverflow ("parser stack overflow",
++ &yyss1, yysize * sizeof (*yyssp),
++ &yyvs1, yysize * sizeof (*yyvsp),
++
++ &yystacksize);
++
++ yyss = yyss1;
++ yyvs = yyvs1;
++ }
+ #else /* no yyoverflow */
++# ifndef YYSTACK_RELOCATE
++ goto yyoverflowlab;
++# else
+ /* Extend the stack our own way. */
+- if (yystacksize >= YYMAXDEPTH)
+- {
+- yyerror("parser stack overflow");
+- if (yyfree_stacks)
+- {
+- free (yyss);
+- free (yyvs);
+-#ifdef YYLSP_NEEDED
+- free (yyls);
+-#endif
+- }
+- return 2;
+- }
++ if (YYMAXDEPTH <= yystacksize)
++ goto yyoverflowlab;
+ yystacksize *= 2;
+- if (yystacksize > YYMAXDEPTH)
++ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+-#ifndef YYSTACK_USE_ALLOCA
+- yyfree_stacks = 1;
+-#endif
+- yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
+- __yy_memcpy ((char *)yyss, (char *)yyss1,
+- size * (unsigned int) sizeof (*yyssp));
+- yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
+- __yy_memcpy ((char *)yyvs, (char *)yyvs1,
+- size * (unsigned int) sizeof (*yyvsp));
+-#ifdef YYLSP_NEEDED
+- yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
+- __yy_memcpy ((char *)yyls, (char *)yyls1,
+- size * (unsigned int) sizeof (*yylsp));
+-#endif
++
++ {
++ short int *yyss1 = yyss;
++ union yyalloc *yyptr =
++ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
++ if (! yyptr)
++ goto yyoverflowlab;
++ YYSTACK_RELOCATE (yyss);
++ YYSTACK_RELOCATE (yyvs);
++
++# undef YYSTACK_RELOCATE
++ if (yyss1 != yyssa)
++ YYSTACK_FREE (yyss1);
++ }
++# endif
+ #endif /* no yyoverflow */
+
+- yyssp = yyss + size - 1;
+- yyvsp = yyvs + size - 1;
+-#ifdef YYLSP_NEEDED
+- yylsp = yyls + size - 1;
+-#endif
++ yyssp = yyss + yysize - 1;
++ yyvsp = yyvs + yysize - 1;
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+-#endif
+
+- if (yyssp >= yyss + yystacksize - 1)
++ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
++ (unsigned long int) yystacksize));
++
++ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Entering state %d\n", yystate);
+-#endif
++ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+- yybackup:
++
++/*-----------.
++| yybackup. |
++`-----------*/
++yybackup:
+
+ /* Do appropriate processing given the current state. */
+ /* Read a lookahead token if we need one and don't already have one. */
+@@ -726,135 +1121,99 @@
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+- if (yyn == YYFLAG)
++ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+- /* yychar is either YYEMPTY or YYEOF
+- or a valid token in external form. */
+-
++ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Reading a token: ");
+-#endif
++ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+- /* Convert token to internal form (in yychar1) for indexing tables with */
+-
+- if (yychar <= 0) /* This means end of input. */
++ if (yychar <= YYEOF)
+ {
+- yychar1 = 0;
+- yychar = YYEOF; /* Don't call YYLEX any more */
+-
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Now at end of input.\n");
+-#endif
++ yychar = yytoken = YYEOF;
++ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+- yychar1 = YYTRANSLATE(yychar);
+-
+-#if YYDEBUG != 0
+- if (yydebug)
+- {
+- fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+- /* Give the individual parser a way to print the precise meaning
+- of a token, for further debugging info. */
+-#ifdef YYPRINT
+- YYPRINT (stderr, yychar, yylval);
+-#endif
+- fprintf (stderr, ")\n");
+- }
+-#endif
++ yytoken = YYTRANSLATE (yychar);
++ YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+- yyn += yychar1;
+- if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
++ /* If the proper action on seeing token YYTOKEN is to reduce or to
++ detect an error, take that action. */
++ yyn += yytoken;
++ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+-
+ yyn = yytable[yyn];
+-
+- /* yyn is what to do for this token type in this state.
+- Negative => reduce, -yyn is rule number.
+- Positive => shift, yyn is new state.
+- New state is final state => don't bother to shift,
+- just return success.
+- 0, or most negative number => error. */
+-
+- if (yyn < 0)
++ if (yyn <= 0)
+ {
+- if (yyn == YYFLAG)
++ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+- else if (yyn == 0)
+- goto yyerrlab;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+-
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+-#endif
++ YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+-#ifdef YYLSP_NEEDED
+- *++yylsp = yylloc;
+-#endif
+
+- /* count tokens shifted since error; after three, turn off error status. */
+- if (yyerrstatus) yyerrstatus--;
++
++ /* Count tokens shifted since error; after three, turn off error
++ status. */
++ if (yyerrstatus)
++ yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+-/* Do the default action for the current state. */
+-yydefault:
+
++/*-----------------------------------------------------------.
++| yydefault -- do the default action for the current state. |
++`-----------------------------------------------------------*/
++yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
++ goto yyreduce;
++
+
+-/* Do a reduction. yyn is the number of a rule to reduce with. */
++/*-----------------------------.
++| yyreduce -- Do a reduction. |
++`-----------------------------*/
+ yyreduce:
++ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+- if (yylen > 0)
+- yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- {
+- int i;
+-
+- fprintf (stderr, "Reducing via rule %d (line %d), ",
+- yyn, yyrline[yyn]);
++ /* If YYLEN is nonzero, implement the default value of the action:
++ `$$ = $1'.
+
+- /* Print the symbols being reduced, and their result. */
+- for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+- fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+- fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+- }
+-#endif
++ Otherwise, the following line sets YYVAL to garbage.
++ This behavior is undocumented and Bison
++ users should not rely upon it. Assigning to YYVAL
++ unconditionally makes the parser a bit smaller, and it avoids a
++ GCC warning that YYVAL may be used uninitialized. */
++ yyval = yyvsp[1-yylen];
+
+
+- switch (yyn) {
+-
+-case 5:
+-#line 83 "cfg_y.y"
+-{
++ YY_REDUCE_PRINT (yyn);
++ switch (yyn)
++ {
++ case 6:
++#line 86 "cfg_y.y"
++ {
+ if (!curr_sig->uni)
+ curr_sig->uni =
+ #if defined(UNI30) || defined(DYNAMIC_UNI)
+@@ -873,17 +1232,19 @@
+ #endif
+ #endif
+ ;
+- ;
+- break;}
+-case 6:
+-#line 107 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 7:
++#line 110 "cfg_y.y"
++ {
+ set_verbosity(NULL,yyvsp[0].num);
+- ;
+- break;}
+-case 12:
+-#line 119 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 13:
++#line 122 "cfg_y.y"
++ {
+ SIG_ENTITY *sig,**walk;
+
+ if (atmpvc_addr_in_use(_entity.signaling_pvc))
+@@ -892,37 +1253,49 @@
+ if (entities == &_entity) entities = NULL;
+ for (sig = entities; sig; sig = sig->next)
+ if (atm_equal((struct sockaddr *) &sig->signaling_pvc,
+- (struct sockaddr *) &yyvsp[0].pvc,0,0))
+- yyerror("duplicate PVC address %d.%d.%d",S_PVC(sig));
++ (struct sockaddr *) &yyvsp[0].pvc,0,0)) {
++ const char *err;
++ asprintf(&err,"duplicate PVC address %d.%d.%d",S_PVC(sig));
++ if(err) {
++ yyerror(err);
++ free(err);
++ }
++ else
++ yyerror("duplicate PVC address");
++ }
+ curr_sig = alloc_t(SIG_ENTITY);
+ *curr_sig = _entity;
+ curr_sig->signaling_pvc = yyvsp[0].pvc;
+ curr_sig->next = NULL;
+ for (walk = &entities; *walk; walk = &(*walk)->next);
+ *walk = curr_sig;
+- ;
+- break;}
+-case 18:
+-#line 150 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 19:
++#line 161 "cfg_y.y"
++ {
+ enter_vpci(curr_sig,yyvsp[-2].num,yyvsp[0].num);
+- ;
+- break;}
+-case 20:
+-#line 155 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 21:
++#line 166 "cfg_y.y"
++ {
+ curr_sig->sig_qos = yyvsp[0].str;
+- ;
+- break;}
+-case 21:
+-#line 159 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 22:
++#line 170 "cfg_y.y"
++ {
+ curr_sig->max_rate = yyvsp[0].num;
+- ;
+- break;}
+-case 22:
+-#line 163 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 23:
++#line 174 "cfg_y.y"
++ {
+ struct sockaddr_atmsvc addr;
+ char *mask;
+
+@@ -931,464 +1304,506 @@
+ if (text2atm(yyvsp[0].str,(struct sockaddr *) &addr,sizeof(addr),
+ T2A_SVC | T2A_WILDCARD | T2A_NAME | T2A_LOCAL) < 0) {
+ yyerror("invalid address");
+- return;
++ return 0;
+ }
+ add_route(curr_sig,&addr,mask ? strtol(mask,NULL,10) : INT_MAX);
+- ;
+- break;}
+-case 23:
+-#line 177 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 24:
++#line 188 "cfg_y.y"
++ {
+ add_route(curr_sig,NULL,0);
+- ;
+- break;}
+-case 44:
+-#line 229 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 45:
++#line 240 "cfg_y.y"
++ {
+ set_verbosity("UNI",yyvsp[0].num);
+ set_verbosity("KERNEL",yyvsp[0].num);
+ set_verbosity("SAP",yyvsp[0].num);
+- ;
+- break;}
+-case 45:
+-#line 235 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 46:
++#line 246 "cfg_y.y"
++ {
+ enter_vpci(curr_sig,yyvsp[-2].num,yyvsp[0].num);
+- ;
+- break;}
+-case 46:
+-#line 239 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 47:
++#line 250 "cfg_y.y"
++ {
+ #if defined(UNI30) || defined(ALLOW_UNI30) || defined(DYNAMIC_UNI)
+ if (curr_sig->uni & ~S_UNI31) yyerror("UNI mode is already set");
+ curr_sig->uni |= S_UNI30;
+ #else
+ yyerror("Sorry, not supported yet");
+ #endif
+- ;
+- break;}
+-case 47:
+-#line 248 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 48:
++#line 259 "cfg_y.y"
++ {
+ #if defined(UNI31) || defined(ALLOW_UNI30) || defined(DYNAMIC_UNI)
+ if (curr_sig->uni & ~S_UNI30) yyerror("UNI mode is already set");
+ curr_sig->uni |= S_UNI31;
+ #else
+ yyerror("Sorry, not supported yet");
+ #endif
+- ;
+- break;}
+-case 48:
+-#line 257 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 49:
++#line 268 "cfg_y.y"
++ {
+ #if defined(UNI40) || defined(DYNAMIC_UNI)
+ if (curr_sig->uni) yyerror("UNI mode is already set");
+ curr_sig->uni = S_UNI40;
+ #else
+ yyerror("Sorry, not supported yet");
+ #endif
+- ;
+- break;}
+-case 49:
+-#line 266 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 50:
++#line 277 "cfg_y.y"
++ {
+ #if defined(Q2963_1) || defined(DYNAMIC_UNI)
+ if (!(curr_sig->uni & S_UNI40)) yyerror("Incompatible UNI mode");
+ curr_sig->uni |= S_Q2963_1;
+ #else
+ yyerror("Sorry, not supported yet");
+ #endif
+- ;
+- break;}
+-case 50:
+-#line 275 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 51:
++#line 286 "cfg_y.y"
++ {
+ yywarn("sig net is obsolete, please use sig mode net instead");
+ curr_sig->mode = sm_net;
+- ;
+- break;}
+-case 52:
+-#line 284 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 53:
++#line 295 "cfg_y.y"
++ {
+ set_verbosity("SSCF",yyvsp[0].num);
+ set_verbosity("SSCOP",yyvsp[0].num);
+- ;
+- break;}
+-case 53:
+-#line 292 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 54:
++#line 303 "cfg_y.y"
++ {
+ set_verbosity("IO",yyvsp[0].num);
+- ;
+- break;}
+-case 54:
+-#line 296 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 55:
++#line 307 "cfg_y.y"
++ {
+ curr_sig->signaling_pvc = yyvsp[0].pvc;
+- ;
+- break;}
+-case 55:
+-#line 300 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 56:
++#line 311 "cfg_y.y"
++ {
+ yywarn("io pcr is obsolete, please use io qos instead");
+ curr_sig->sig_pcr = yyvsp[0].num;
+- ;
+- break;}
+-case 56:
+-#line 305 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 57:
++#line 316 "cfg_y.y"
++ {
+ curr_sig->sig_qos = yyvsp[0].str;
+- ;
+- break;}
+-case 57:
+-#line 309 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 58:
++#line 320 "cfg_y.y"
++ {
+ curr_sig->max_rate = yyvsp[0].num;
+- ;
+- break;}
+-case 58:
+-#line 316 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 59:
++#line 327 "cfg_y.y"
++ {
+ set_verbosity(NULL,yyvsp[0].num);
+- ;
+- break;}
+-case 59:
+-#line 320 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 60:
++#line 331 "cfg_y.y"
++ {
+ dump_dir = yyvsp[0].str;
+ if (!trace_size) trace_size = DEFAULT_TRACE_SIZE;
+- ;
+- break;}
+-case 60:
+-#line 325 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 61:
++#line 336 "cfg_y.y"
++ {
+ set_logfile(yyvsp[0].str);
+- ;
+- break;}
+-case 61:
+-#line 329 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 62:
++#line 340 "cfg_y.y"
++ {
+ trace_size = yyvsp[0].num;
+- ;
+- break;}
+-case 62:
+-#line 335 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 63:
++#line 346 "cfg_y.y"
++ {
+ yyval.num = DEFAULT_TRACE_SIZE;
+- ;
+- break;}
+-case 63:
+-#line 339 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 64:
++#line 350 "cfg_y.y"
++ {
+ yyval.num = yyvsp[0].num;
+- ;
+- break;}
+-case 64:
+-#line 346 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 65:
++#line 357 "cfg_y.y"
++ {
+ yyval.num = DIAG_DEBUG;
+- ;
+- break;}
+-case 65:
+-#line 350 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 66:
++#line 361 "cfg_y.y"
++ {
+ yyval.num = DIAG_INFO;
+- ;
+- break;}
+-case 66:
+-#line 354 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 67:
++#line 365 "cfg_y.y"
++ {
+ yyval.num = DIAG_WARN;
+- ;
+- break;}
+-case 67:
+-#line 358 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 68:
++#line 369 "cfg_y.y"
++ {
+ yyval.num = DIAG_ERROR;
+- ;
+- break;}
+-case 68:
+-#line 362 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 69:
++#line 373 "cfg_y.y"
++ {
+ yyval.num = DIAG_FATAL;
+- ;
+- break;}
+-case 69:
+-#line 369 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 70:
++#line 380 "cfg_y.y"
++ {
+ curr_sig->mode = sm_user;
+- ;
+- break;}
+-case 70:
+-#line 373 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 71:
++#line 384 "cfg_y.y"
++ {
+ curr_sig->mode = sm_net;
+- ;
+- break;}
+-case 71:
+-#line 377 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 72:
++#line 388 "cfg_y.y"
++ {
+ curr_sig->mode = sm_switch;
+- ;
+- break;}
+-case 72:
+-#line 384 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 73:
++#line 395 "cfg_y.y"
++ {
+ set_verbosity("POLICY",yyvsp[0].num);
+- ;
+- break;}
+-case 73:
+-#line 388 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 74:
++#line 399 "cfg_y.y"
++ {
+ rule = alloc_t(RULE);
+ rule->type = yyvsp[0].num;
+- ;
+- break;}
+-case 75:
+-#line 397 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 76:
++#line 408 "cfg_y.y"
++ {
+ yyval.num = ACL_ALLOW;
+- ;
+- break;}
+-case 76:
+-#line 401 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 77:
++#line 412 "cfg_y.y"
++ {
+ yyval.num = ACL_REJECT;
+- ;
+- break;}
+-case 77:
+-#line 408 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 78:
++#line 419 "cfg_y.y"
++ {
+ rule->type |= ACL_IN;
+ put_address(yyvsp[0].str);
+- ;
+- break;}
+-case 78:
+-#line 413 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 79:
++#line 424 "cfg_y.y"
++ {
+ rule->type |= ACL_OUT;
+ put_address(yyvsp[0].str);
+- ;
+- break;}
+-}
+- /* the action file gets copied in in place of this dollarsign */
+-#line 543 "/usr/lib/bison.simple"
++ }
++ break;
++
++
++ }
++
++/* Line 1010 of yacc.c. */
++#line 1585 "y.tab.c"
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+-#ifdef YYLSP_NEEDED
+- yylsp -= yylen;
+-#endif
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- {
+- short *ssp1 = yyss - 1;
+- fprintf (stderr, "state stack now");
+- while (ssp1 != yyssp)
+- fprintf (stderr, " %d", *++ssp1);
+- fprintf (stderr, "\n");
+- }
+-#endif
++
++ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+-#ifdef YYLSP_NEEDED
+- yylsp++;
+- if (yylen == 0)
+- {
+- yylsp->first_line = yylloc.first_line;
+- yylsp->first_column = yylloc.first_column;
+- yylsp->last_line = (yylsp-1)->last_line;
+- yylsp->last_column = (yylsp-1)->last_column;
+- yylsp->text = 0;
+- }
+- else
+- {
+- yylsp->last_line = (yylsp+yylen-1)->last_line;
+- yylsp->last_column = (yylsp+yylen-1)->last_column;
+- }
+-#endif
+
+- /* Now "shift" the result of the reduction.
+- Determine what state that goes to,
+- based on the state we popped back to
+- and the rule number reduced by. */
++ /* Now `shift' the result of the reduction. Determine what state
++ that goes to, based on the state we popped back to and the rule
++ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+- yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+- if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
++ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
++ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+- yystate = yydefgoto[yyn - YYNTBASE];
++ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+-yyerrlab: /* here on detecting error */
+
+- if (! yyerrstatus)
+- /* If not already recovering from an error, report this error. */
++/*------------------------------------.
++| yyerrlab -- here on detecting error |
++`------------------------------------*/
++yyerrlab:
++ /* If not already recovering from an error, report this error. */
++ if (!yyerrstatus)
+ {
+ ++yynerrs;
+-
+-#ifdef YYERROR_VERBOSE
++#if YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+- if (yyn > YYFLAG && yyn < YYLAST)
++ if (YYPACT_NINF < yyn && yyn < YYLAST)
+ {
+- int size = 0;
+- char *msg;
+- int x, count;
+-
+- count = 0;
+- /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
+- for (x = (yyn < 0 ? -yyn : 0);
+- x < (sizeof(yytname) / sizeof(char *)); x++)
+- if (yycheck[x + yyn] == x)
+- size += strlen(yytname[x]) + 15, count++;
+- msg = (char *) malloc(size + 15);
+- if (msg != 0)
++ YYSIZE_T yysize = 0;
++ int yytype = YYTRANSLATE (yychar);
++ const char* yyprefix;
++ char *yymsg;
++ int yyx;
++
++ /* Start YYX at -YYN if negative to avoid negative indexes in
++ YYCHECK. */
++ int yyxbegin = yyn < 0 ? -yyn : 0;
++
++ /* Stay within bounds of both yycheck and yytname. */
++ int yychecklim = YYLAST - yyn;
++ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
++ int yycount = 0;
++
++ yyprefix = ", expecting ";
++ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
++ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
++ {
++ yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
++ yycount += 1;
++ if (yycount == 5)
++ {
++ yysize = 0;
++ break;
++ }
++ }
++ yysize += (sizeof ("syntax error, unexpected ")
++ + yystrlen (yytname[yytype]));
++ yymsg = (char *) YYSTACK_ALLOC (yysize);
++ if (yymsg != 0)
+ {
+- strcpy(msg, "parse error");
++ char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
++ yyp = yystpcpy (yyp, yytname[yytype]);
+
+- if (count < 5)
++ if (yycount < 5)
+ {
+- count = 0;
+- for (x = (yyn < 0 ? -yyn : 0);
+- x < (sizeof(yytname) / sizeof(char *)); x++)
+- if (yycheck[x + yyn] == x)
++ yyprefix = ", expecting ";
++ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
++ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+- strcat(msg, count == 0 ? ", expecting `" : " or `");
+- strcat(msg, yytname[x]);
+- strcat(msg, "'");
+- count++;
++ yyp = yystpcpy (yyp, yyprefix);
++ yyp = yystpcpy (yyp, yytname[yyx]);
++ yyprefix = " or ";
+ }
+ }
+- yyerror(msg);
+- free(msg);
++ yyerror (yymsg);
++ YYSTACK_FREE (yymsg);
+ }
+ else
+- yyerror ("parse error; also virtual memory exceeded");
++ yyerror ("syntax error; also virtual memory exhausted");
+ }
+ else
+ #endif /* YYERROR_VERBOSE */
+- yyerror("parse error");
++ yyerror ("syntax error");
+ }
+
+- goto yyerrlab1;
+-yyerrlab1: /* here on error raised explicitly by an action */
++
+
+ if (yyerrstatus == 3)
+ {
+- /* if just tried and failed to reuse lookahead token after an error, discard it. */
++ /* If just tried and failed to reuse lookahead token after an
++ error, discard it. */
+
+- /* return failure if at end of input */
+- if (yychar == YYEOF)
+- YYABORT;
+-
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+-#endif
++ if (yychar <= YYEOF)
++ {
++ /* If at end of input, pop the error token,
++ then the rest of the stack, then return failure. */
++ if (yychar == YYEOF)
++ for (;;)
++ {
++ YYPOPSTACK;
++ if (yyssp == yyss)
++ YYABORT;
++ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
++ yydestruct (yystos[*yyssp], yyvsp);
++ }
++ }
++ else
++ {
++ YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
++ yydestruct (yytoken, &yylval);
++ yychar = YYEMPTY;
+
+- yychar = YYEMPTY;
++ }
+ }
+
+- /* Else will try to reuse lookahead token
+- after shifting the error token. */
+-
+- yyerrstatus = 3; /* Each real token shifted decrements this */
++ /* Else will try to reuse lookahead token after shifting the error
++ token. */
++ goto yyerrlab1;
+
+- goto yyerrhandle;
+
+-yyerrdefault: /* current state does not do anything special for the error token. */
++/*---------------------------------------------------.
++| yyerrorlab -- error raised explicitly by YYERROR. |
++`---------------------------------------------------*/
++yyerrorlab:
+
+-#if 0
+- /* This is wrong; only states that explicitly want error tokens
+- should shift them. */
+- yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
+- if (yyn) goto yydefault;
++#ifdef __GNUC__
++ /* Pacify GCC when the user code never invokes YYERROR and the label
++ yyerrorlab therefore never appears in user code. */
++ if (0)
++ goto yyerrorlab;
+ #endif
+
+-yyerrpop: /* pop the current state because it cannot handle the error token */
+-
+- if (yyssp == yyss) YYABORT;
+- yyvsp--;
+- yystate = *--yyssp;
+-#ifdef YYLSP_NEEDED
+- yylsp--;
+-#endif
++ yyvsp -= yylen;
++ yyssp -= yylen;
++ yystate = *yyssp;
++ goto yyerrlab1;
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- {
+- short *ssp1 = yyss - 1;
+- fprintf (stderr, "Error: state stack now");
+- while (ssp1 != yyssp)
+- fprintf (stderr, " %d", *++ssp1);
+- fprintf (stderr, "\n");
+- }
+-#endif
+
+-yyerrhandle:
++/*-------------------------------------------------------------.
++| yyerrlab1 -- common code for both syntax error and YYERROR. |
++`-------------------------------------------------------------*/
++yyerrlab1:
++ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+- yyn = yypact[yystate];
+- if (yyn == YYFLAG)
+- goto yyerrdefault;
++ for (;;)
++ {
++ yyn = yypact[yystate];
++ if (yyn != YYPACT_NINF)
++ {
++ yyn += YYTERROR;
++ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
++ {
++ yyn = yytable[yyn];
++ if (0 < yyn)
++ break;
++ }
++ }
+
+- yyn += YYTERROR;
+- if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+- goto yyerrdefault;
++ /* Pop the current state because it cannot handle the error token. */
++ if (yyssp == yyss)
++ YYABORT;
+
+- yyn = yytable[yyn];
+- if (yyn < 0)
+- {
+- if (yyn == YYFLAG)
+- goto yyerrpop;
+- yyn = -yyn;
+- goto yyreduce;
++ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
++ yydestruct (yystos[yystate], yyvsp);
++ YYPOPSTACK;
++ yystate = *yyssp;
++ YY_STACK_PRINT (yyss, yyssp);
+ }
+- else if (yyn == 0)
+- goto yyerrpop;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Shifting error token, ");
+-#endif
++ YYDPRINTF ((stderr, "Shifting error token, "));
+
+ *++yyvsp = yylval;
+-#ifdef YYLSP_NEEDED
+- *++yylsp = yylloc;
+-#endif
++
+
+ yystate = yyn;
+ goto yynewstate;
+
+- yyacceptlab:
+- /* YYACCEPT comes here. */
+- if (yyfree_stacks)
+- {
+- free (yyss);
+- free (yyvs);
+-#ifdef YYLSP_NEEDED
+- free (yyls);
+-#endif
+- }
+- return 0;
+
+- yyabortlab:
+- /* YYABORT comes here. */
+- if (yyfree_stacks)
+- {
+- free (yyss);
+- free (yyvs);
+-#ifdef YYLSP_NEEDED
+- free (yyls);
++/*-------------------------------------.
++| yyacceptlab -- YYACCEPT comes here. |
++`-------------------------------------*/
++yyacceptlab:
++ yyresult = 0;
++ goto yyreturn;
++
++/*-----------------------------------.
++| yyabortlab -- YYABORT comes here. |
++`-----------------------------------*/
++yyabortlab:
++ yyresult = 1;
++ goto yyreturn;
++
++#ifndef yyoverflow
++/*----------------------------------------------.
++| yyoverflowlab -- parser overflow comes here. |
++`----------------------------------------------*/
++yyoverflowlab:
++ yyerror ("parser stack overflow");
++ yyresult = 2;
++ /* Fall through. */
++#endif
++
++yyreturn:
++#ifndef yyoverflow
++ if (yyss != yyssa)
++ YYSTACK_FREE (yyss);
+ #endif
+- }
+- return 1;
++ return yyresult;
+ }
+-#line 418 "cfg_y.y"
++
++
++
+--- linux-atm-2.4.1.orig/src/sigd/proto.c
++++ linux-atm-2.4.1/src/sigd/proto.c
+@@ -259,6 +259,7 @@
+ break;
+ }
+ default:
++ break;
+ }
+ va_end(ap);
+ if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size);
+@@ -288,6 +289,7 @@
+ }
+ break;
+ default:
++ break;
+ }
+ va_end(ap);
+ }
+--- linux-atm-2.4.1.orig/src/sigd/cfg_y.y
++++ linux-atm-2.4.1/src/sigd/cfg_y.y
+@@ -7,6 +7,7 @@
+ #include <config.h>
+ #endif
+
++#include <stdlib.h>
+ #include <string.h>
+ #include <ctype.h>
+ #include <limits.h>
+@@ -19,6 +20,8 @@
+ #include "trace.h"
+ #include "policy.h"
+
++extern void yywarn(const char *s);
++extern void yyerror(const char *s);
+
+ static RULE *rule;
+ static SIG_ENTITY *curr_sig = &_entity;
+@@ -125,8 +128,16 @@
+ if (entities == &_entity) entities = NULL;
+ for (sig = entities; sig; sig = sig->next)
+ if (atm_equal((struct sockaddr *) &sig->signaling_pvc,
+- (struct sockaddr *) &$2,0,0))
+- yyerror("duplicate PVC address %d.%d.%d",S_PVC(sig));
++ (struct sockaddr *) &$2,0,0)) {
++ const char *err;
++ asprintf(&err,"duplicate PVC address %d.%d.%d",S_PVC(sig));
++ if(err) {
++ yyerror(err);
++ free(err);
++ }
++ else
++ yyerror("duplicate PVC address");
++ }
+ curr_sig = alloc_t(SIG_ENTITY);
+ *curr_sig = _entity;
+ curr_sig->signaling_pvc = $2;
+@@ -169,7 +180,7 @@
+ if (text2atm($1,(struct sockaddr *) &addr,sizeof(addr),
+ T2A_SVC | T2A_WILDCARD | T2A_NAME | T2A_LOCAL) < 0) {
+ yyerror("invalid address");
+- return;
++ return 0;
+ }
+ add_route(curr_sig,&addr,mask ? strtol(mask,NULL,10) : INT_MAX);
+ }
+--- linux-atm-2.4.1.orig/src/sigd/cfg_y.h
++++ linux-atm-2.4.1/src/sigd/cfg_y.h
+@@ -1,44 +1,127 @@
+-typedef union {
++/* A Bison parser, made by GNU Bison 1.875d. */
++
++/* Skeleton parser for Yacc-like parsing with Bison,
++ Copyright (C) 1984, 1989, 1990, 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.
++
++ 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, when this file is copied by Bison into a
++ Bison output file, you may use that output file without restriction.
++ This special exception was added by the Free Software Foundation
++ in version 1.24 of Bison. */
++
++/* Tokens. */
++#ifndef YYTOKENTYPE
++# define YYTOKENTYPE
++ /* Put the tokens into the symbol table, so that GDB and other debuggers
++ know about them. */
++ enum yytokentype {
++ TOK_LEVEL = 258,
++ TOK_DEBUG = 259,
++ TOK_INFO = 260,
++ TOK_WARN = 261,
++ TOK_ERROR = 262,
++ TOK_FATAL = 263,
++ TOK_SIG = 264,
++ TOK_UNI30 = 265,
++ TOK_UNI31 = 266,
++ TOK_UNI40 = 267,
++ TOK_Q2963_1 = 268,
++ TOK_SAAL = 269,
++ TOK_VC = 270,
++ TOK_IO = 271,
++ TOK_MODE = 272,
++ TOK_USER = 273,
++ TOK_NET = 274,
++ TOK_SWITCH = 275,
++ TOK_VPCI = 276,
++ TOK_ITF = 277,
++ TOK_PCR = 278,
++ TOK_TRACE = 279,
++ TOK_POLICY = 280,
++ TOK_ALLOW = 281,
++ TOK_REJECT = 282,
++ TOK_ENTITY = 283,
++ TOK_DEFAULT = 284,
++ TOK_NUMBER = 285,
++ TOK_MAX_RATE = 286,
++ TOK_DUMP_DIR = 287,
++ TOK_LOGFILE = 288,
++ TOK_QOS = 289,
++ TOK_FROM = 290,
++ TOK_TO = 291,
++ TOK_ROUTE = 292,
++ TOK_PVC = 293
++ };
++#endif
++#define TOK_LEVEL 258
++#define TOK_DEBUG 259
++#define TOK_INFO 260
++#define TOK_WARN 261
++#define TOK_ERROR 262
++#define TOK_FATAL 263
++#define TOK_SIG 264
++#define TOK_UNI30 265
++#define TOK_UNI31 266
++#define TOK_UNI40 267
++#define TOK_Q2963_1 268
++#define TOK_SAAL 269
++#define TOK_VC 270
++#define TOK_IO 271
++#define TOK_MODE 272
++#define TOK_USER 273
++#define TOK_NET 274
++#define TOK_SWITCH 275
++#define TOK_VPCI 276
++#define TOK_ITF 277
++#define TOK_PCR 278
++#define TOK_TRACE 279
++#define TOK_POLICY 280
++#define TOK_ALLOW 281
++#define TOK_REJECT 282
++#define TOK_ENTITY 283
++#define TOK_DEFAULT 284
++#define TOK_NUMBER 285
++#define TOK_MAX_RATE 286
++#define TOK_DUMP_DIR 287
++#define TOK_LOGFILE 288
++#define TOK_QOS 289
++#define TOK_FROM 290
++#define TOK_TO 291
++#define TOK_ROUTE 292
++#define TOK_PVC 293
++
++
++
++
++#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
++#line 56 "cfg_y.y"
++typedef union YYSTYPE {
+ int num;
+ char *str;
+ struct sockaddr_atmpvc pvc;
+ } YYSTYPE;
+-#define TOK_LEVEL 257
+-#define TOK_DEBUG 258
+-#define TOK_INFO 259
+-#define TOK_WARN 260
+-#define TOK_ERROR 261
+-#define TOK_FATAL 262
+-#define TOK_SIG 263
+-#define TOK_UNI30 264
+-#define TOK_UNI31 265
+-#define TOK_UNI40 266
+-#define TOK_Q2963_1 267
+-#define TOK_SAAL 268
+-#define TOK_VC 269
+-#define TOK_IO 270
+-#define TOK_MODE 271
+-#define TOK_USER 272
+-#define TOK_NET 273
+-#define TOK_SWITCH 274
+-#define TOK_VPCI 275
+-#define TOK_ITF 276
+-#define TOK_PCR 277
+-#define TOK_TRACE 278
+-#define TOK_POLICY 279
+-#define TOK_ALLOW 280
+-#define TOK_REJECT 281
+-#define TOK_ENTITY 282
+-#define TOK_DEFAULT 283
+-#define TOK_NUMBER 284
+-#define TOK_MAX_RATE 285
+-#define TOK_DUMP_DIR 286
+-#define TOK_LOGFILE 287
+-#define TOK_QOS 288
+-#define TOK_FROM 289
+-#define TOK_TO 290
+-#define TOK_ROUTE 291
+-#define TOK_PVC 292
+-
++/* Line 1285 of yacc.c. */
++#line 119 "y.tab.h"
++# define yystype YYSTYPE /* obsolescent; will be withdrawn */
++# define YYSTYPE_IS_DECLARED 1
++# define YYSTYPE_IS_TRIVIAL 1
++#endif
+
+ extern YYSTYPE yylval;
++
++
++
+--- linux-atm-2.4.1.orig/src/maint/Makefile.in
++++ linux-atm-2.4.1/src/maint/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -181,8 +181,11 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
++DEP_FILES = .deps/atmaddr.P .deps/atmdiag.P .deps/atmdump.P \
++.deps/atmloop.P .deps/atmtcp.P .deps/enitune.P .deps/esi.P \
++.deps/saaldump.P .deps/sonetdiag.P .deps/zntune.P
+ SOURCES = $(atmdiag_SOURCES) $(atmdump_SOURCES) $(sonetdiag_SOURCES) $(saaldump_SOURCES) $(atmaddr_SOURCES) $(esi_SOURCES) $(atmloop_SOURCES) $(atmtcp_SOURCES) $(enitune_SOURCES) $(zntune_SOURCES)
+ OBJECTS = $(atmdiag_OBJECTS) $(atmdump_OBJECTS) $(sonetdiag_OBJECTS) $(saaldump_OBJECTS) $(atmaddr_OBJECTS) $(esi_OBJECTS) $(atmloop_OBJECTS) $(atmtcp_OBJECTS) $(enitune_OBJECTS) $(zntune_OBJECTS)
+
+@@ -190,9 +193,9 @@
+ .SUFFIXES:
+ .SUFFIXES: .S .c .lo .o .obj .s
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/maint/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/maint/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -247,9 +250,6 @@
+ rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ done
+
+-.c.o:
+- $(COMPILE) -c $<
+-
+ # FIXME: We should only use cygpath when building on Windows,
+ # and only if it is available.
+ .c.obj:
+@@ -272,9 +272,6 @@
+
+ maintainer-clean-compile:
+
+-.c.lo:
+- $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+-
+ .s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+@@ -388,7 +385,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -404,6 +401,11 @@
+ subdir = src/maint
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/maint/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+@@ -414,28 +416,38 @@
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+-atmaddr.o: atmaddr.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h
+-atmdiag.o: atmdiag.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h
+-atmdump.o: atmdump.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atm.h
+-atmloop.o: atmloop.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h
+-atmtcp.o: atmtcp.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atm.h ../../src/include/atmd.h
+-enitune.o: enitune.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h
+-esi.o: esi.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h
+-saaldump.o: saaldump.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/saal/pdu.h \
+- ../../src/include/atmd.h ../../src/qgen/qlib.h
+-sonetdiag.o: sonetdiag.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h
+-zntune.o: zntune.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h
+
++DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
++
++-include $(DEP_FILES)
++
++mostlyclean-depend:
++
++clean-depend:
++
++distclean-depend:
++ -rm -rf .deps
++
++maintainer-clean-depend:
++
++%.o: %.c
++ @echo '$(COMPILE) -c $<'; \
++ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-cp .deps/$(*F).pp .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm .deps/$(*F).pp
++
++%.lo: %.c
++ @echo '$(LTCOMPILE) -c $<'; \
++ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
++ < .deps/$(*F).pp > .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm -f .deps/$(*F).pp
+ info-am:
+ info: info-am
+ dvi-am:
+@@ -475,18 +487,19 @@
+ maintainer-clean-generic:
+ mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-sbinPROGRAMS \
+ mostlyclean-compile mostlyclean-libtool \
+- mostlyclean-tags mostlyclean-generic
++ mostlyclean-tags mostlyclean-depend mostlyclean-generic
+
+ mostlyclean: mostlyclean-am
+
+ clean-am: clean-binPROGRAMS clean-sbinPROGRAMS clean-compile \
+- clean-libtool clean-tags clean-generic mostlyclean-am
++ clean-libtool clean-tags clean-depend clean-generic \
++ mostlyclean-am
+
+ clean: clean-am
+
+ distclean-am: distclean-binPROGRAMS distclean-sbinPROGRAMS \
+ distclean-compile distclean-libtool distclean-tags \
+- distclean-generic clean-am
++ distclean-depend distclean-generic clean-am
+ -rm -f libtool
+
+ distclean: distclean-am
+@@ -494,7 +507,8 @@
+ maintainer-clean-am: maintainer-clean-binPROGRAMS \
+ maintainer-clean-sbinPROGRAMS maintainer-clean-compile \
+ maintainer-clean-libtool maintainer-clean-tags \
+- maintainer-clean-generic distclean-am
++ maintainer-clean-depend 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."
+
+@@ -508,12 +522,14 @@
+ clean-compile maintainer-clean-compile mostlyclean-libtool \
+ distclean-libtool clean-libtool maintainer-clean-libtool install-man8 \
+ uninstall-man8 install-man uninstall-man tags mostlyclean-tags \
+-distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+-dvi-am dvi check check-am installcheck-am installcheck 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
++distclean-tags clean-tags maintainer-clean-tags distdir \
++mostlyclean-depend distclean-depend clean-depend \
++maintainer-clean-depend info-am info dvi-am dvi check check-am \
++installcheck-am installcheck 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.
+--- linux-atm-2.4.1.orig/src/maint/atmtcp.c
++++ linux-atm-2.4.1/src/maint/atmtcp.c
+@@ -60,7 +60,7 @@
+ static IN *inputs = NULL;
+ static fd_set in_set;
+ static int fds = 0;
+-static int debug = 0;
++static int atmtcp_debug = 0;
+ static int links = 0;
+
+
+@@ -86,7 +86,7 @@
+ {
+ OUT *out;
+
+- if (debug)
++ if (atmtcp_debug)
+ fprintf(stderr,"Emit: %d.%d, %d bytes\n",ntohs(hdr->vpi),
+ ntohs(hdr->vci),(int) ntohl(hdr->length));
+ for (out = outputs; out; out = out->next)
+@@ -99,7 +99,7 @@
+ OUT *out;
+ int changed = 0;
+
+- if (debug)
++ if (atmtcp_debug)
+ fprintf(stderr,"Control: (%d.%d) %s %d.%d, vcc %s\n",
+ ntohs(msg->hdr.vpi),ntohs(msg->hdr.vci),
+ msg->type == ATMTCP_CTRL_OPEN ? "OPEN" :
+@@ -295,19 +295,19 @@
+ }
+ if ((s = socket(PF_ATMPVC,SOCK_DGRAM,0)) < 0) {
+ msg->result = -errno;
+- if (debug) perror("socket");
++ if (atmtcp_debug) perror("socket");
+ return 1;
+ }
+ if (setsockopt(s,SOL_ATM,SO_ATMQOS,&msg->qos,sizeof(msg->qos)) < 0) {
+ msg->result = -errno;
+- if (debug) perror("setsockopt SO_ATMQOS");
++ if (atmtcp_debug) perror("setsockopt SO_ATMQOS");
+ return 1;
+ }
+ msg->addr.sap_addr.itf = data->itf;
+ if (connect(s,(struct sockaddr *) &msg->addr,
+ sizeof(struct sockaddr_atmpvc)) < 0) {
+ msg->result = -errno;
+- if (debug) perror("connect");
++ if (atmtcp_debug) perror("connect");
+ return 1;
+ }
+ (*vcc) = alloc_t(VCC);
+@@ -333,7 +333,7 @@
+ addr.sap_addr.vci = ntohs(hdr->vci);
+ vcc = real_lookup(data,&addr);
+ if (!*vcc) {
+- if (debug)
++ if (atmtcp_debug)
+ fprintf(stderr,"VCC %d.%d not found\n",addr.sap_addr.vpi,
+ addr.sap_addr.vci);
+ return;
+@@ -430,7 +430,7 @@
+ exit(1);
+ }
+ if (in->bytes < sizeof(*hdr)+ntohl(hdr->length)) return;
+- if (debug)
++ if (atmtcp_debug)
+ fprintf(stderr,"TCP %d.%d, %d bytes\n",ntohs(hdr->vpi),
+ ntohs(hdr->vci),(unsigned int) ntohl(hdr->length));
+ in->bytes = 0;
+@@ -447,7 +447,7 @@
+ fprintf(stderr,"unrecognized control message \"%s\"\n",msg);
+ return;
+ }
+- if (debug) fprintf(stderr,"received control \"%s\"\n",msg);
++ if (atmtcp_debug) fprintf(stderr,"received control \"%s\"\n",msg);
+ ctl.hdr.vpi = htons(vpi);
+ ctl.hdr.vci = htons(vci);
+ ctl.hdr.length = htonl(ATMTCP_HDR_MAGIC);
+@@ -508,7 +508,7 @@
+ }
+ hdr->vpi = hdr->vci = htons(0);
+ hdr->length = htonl(pos-start);
+- if (debug) fprintf(stderr,"sending control \"%s\"\n",start);
++ if (atmtcp_debug) fprintf(stderr,"sending control \"%s\"\n",start);
+ tcp_do_send(*(int *) out->user,buf,pos-buf);
+ return 0;
+ }
+@@ -555,7 +555,7 @@
+ exit(1);
+ }
+ if (in->bytes < sizeof(int)+sizeof(*hdr)+ntohl(hdr->length)) return;
+- if (debug)
++ if (atmtcp_debug)
+ fprintf(stderr,"File %d.%d, %d bytes\n",ntohs(hdr->vpi),
+ ntohs(hdr->vci),(unsigned int) ntohl(hdr->length));
+ }
+@@ -708,7 +708,7 @@
+ while ((c = getopt(argc,argv,"dvV")) != EOF)
+ switch (c) {
+ case 'd':
+- debug = 1;
++ atmtcp_debug = 1;
+ break;
+ case 'v':
+ verbose = 1;
+@@ -817,7 +817,8 @@
+ }
+ else if (!strcmp(ARG,"listen") ||
+ (do_background = !strcmp(ARG,"listen-bg"))) {
+- int fd,port,addr_len;
++ int fd,port;
++ size_t addr_len;
+ int *fd2 = alloc_t(int);
+
+ if ((fd = socket(PF_INET,SOCK_STREAM,0)) < 0) {
+--- linux-atm-2.4.1.orig/src/maint/enitune.c
++++ linux-atm-2.4.1/src/maint/enitune.c
+@@ -44,6 +44,7 @@
+ if (*end || mult.rx <= 100) usage(name);
+ break;
+ default:
++ break;
+ }
+ if (argc != optind+1) usage(name);
+ sioc.number = strtol(argv[optind],&end,0);
+--- linux-atm-2.4.1.orig/src/arpd/Makefile.in
++++ linux-atm-2.4.1/src/arpd/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -90,8 +90,7 @@
+ sbin_PROGRAMS = atmarp atmarpd
+
+ atmarp_SOURCES = atmarp.c atmarp.h atmarpd.h
+-atmarpd_SOURCES = atmarpd.c atmarpd.h arp.c arp.h io.c io.h itf.c itf.h \
+- table.c table.h atmarp.h
++atmarpd_SOURCES = atmarpd.c atmarpd.h arp.c arp.h io.c io.h itf.c itf.h table.c table.h atmarp.h
+
+
+ include_HEADERS = atmarp.h atmarpd.h
+@@ -135,8 +134,10 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
++DEP_FILES = .deps/arp.P .deps/atmarp.P .deps/atmarpd.P .deps/io.P \
++.deps/itf.P .deps/table.P
+ SOURCES = $(atmarp_SOURCES) $(atmarpd_SOURCES)
+ OBJECTS = $(atmarp_OBJECTS) $(atmarpd_OBJECTS)
+
+@@ -144,9 +145,9 @@
+ .SUFFIXES:
+ .SUFFIXES: .S .c .lo .o .obj .s
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/arpd/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/arpd/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -176,9 +177,6 @@
+ rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ done
+
+-.c.o:
+- $(COMPILE) -c $<
+-
+ # FIXME: We should only use cygpath when building on Windows,
+ # and only if it is available.
+ .c.obj:
+@@ -201,9 +199,6 @@
+
+ maintainer-clean-compile:
+
+-.c.lo:
+- $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+-
+ .s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+@@ -300,7 +295,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -316,6 +311,11 @@
+ subdir = src/arpd
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/arpd/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+@@ -326,24 +326,38 @@
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+-arp.o: arp.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atm.h ../../src/include/atmd.h atmarp.h \
+- atmarpd.h table.h itf.h io.h arp.h
+-atmarp.o: atmarp.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atm.h ../../src/include/atmd.h atmarpd.h
+-atmarpd.o: atmarpd.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h atmarpd.h \
+- io.h table.h
+-io.o: io.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atm.h ../../src/include/atmd.h atmarpd.h \
+- table.h arp.h atmarp.h itf.h io.h
+-itf.o: itf.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atmd.h ../../src/include/atm.h table.h io.h \
+- itf.h arp.h atmarp.h atmarpd.h
+-table.o: table.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atm.h ../../src/include/atmd.h atmarpd.h \
+- table.h
+
++DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
++
++-include $(DEP_FILES)
++
++mostlyclean-depend:
++
++clean-depend:
++
++distclean-depend:
++ -rm -rf .deps
++
++maintainer-clean-depend:
++
++%.o: %.c
++ @echo '$(COMPILE) -c $<'; \
++ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-cp .deps/$(*F).pp .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm .deps/$(*F).pp
++
++%.lo: %.c
++ @echo '$(LTCOMPILE) -c $<'; \
++ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
++ < .deps/$(*F).pp > .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm -f .deps/$(*F).pp
+ info-am:
+ info: info-am
+ dvi-am:
+@@ -383,27 +397,27 @@
+
+ maintainer-clean-generic:
+ mostlyclean-am: mostlyclean-sbinPROGRAMS mostlyclean-compile \
+- mostlyclean-libtool mostlyclean-tags \
++ mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+ mostlyclean-generic
+
+ mostlyclean: mostlyclean-am
+
+ clean-am: clean-sbinPROGRAMS clean-compile clean-libtool clean-tags \
+- clean-generic mostlyclean-am
++ clean-depend clean-generic mostlyclean-am
+
+ clean: clean-am
+
+ distclean-am: distclean-sbinPROGRAMS distclean-compile \
+- distclean-libtool distclean-tags distclean-generic \
+- clean-am
++ distclean-libtool distclean-tags distclean-depend \
++ distclean-generic clean-am
+ -rm -f libtool
+
+ distclean: distclean-am
+
+ maintainer-clean-am: maintainer-clean-sbinPROGRAMS \
+ maintainer-clean-compile maintainer-clean-libtool \
+- maintainer-clean-tags maintainer-clean-generic \
+- distclean-am
++ maintainer-clean-tags maintainer-clean-depend \
++ 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."
+
+@@ -416,8 +430,9 @@
+ distclean-libtool clean-libtool maintainer-clean-libtool install-man8 \
+ uninstall-man8 install-man uninstall-man 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 install-exec-am install-exec \
++maintainer-clean-tags distdir mostlyclean-depend distclean-depend \
++clean-depend maintainer-clean-depend info-am info dvi-am dvi check \
++check-am installcheck-am installcheck 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 \
+--- linux-atm-2.4.1.orig/src/arpd/atmarp.c
++++ linux-atm-2.4.1/src/arpd/atmarp.c
+@@ -92,7 +92,7 @@
+ perror("read " ATMARP_DUMP_DIR "/" ATMARP_DUMP_FILE);
+ return 1;
+ }
+- if (write(0,buffer,size) < 0) {
++ if (write(1,buffer,size) < 0) {
+ perror("write stdout");
+ return 1;
+ }
+--- linux-atm-2.4.1.orig/src/ilmid/Makefile.in
++++ linux-atm-2.4.1/src/ilmid/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -91,13 +91,9 @@
+
+ sbin_PROGRAMS = ilmid
+
+-ilmid_SOURCES = rfc1157_snmp.c rfc1157_snmp.h rfc1155_smi.c rfc1155_smi.h \
+- util.c util.h io.c io.h message.c message.h \
+- atmf_uni.c atmf_uni.h mib.c mib.h \
+- sysgroup.c sysgroup.h ilmid.c
++ilmid_SOURCES = rfc1157_snmp.c rfc1157_snmp.h rfc1155_smi.c rfc1155_smi.h util.c util.h io.c io.h message.c message.h atmf_uni.c atmf_uni.h mib.c mib.h sysgroup.c sysgroup.h ilmid.c
+
+-ilmid_LDADD = $(top_builddir)/src/lib/libatm.la \
+- $(top_builddir)/src/ilmid/asn1/libasn1.a
++ilmid_LDADD = $(top_builddir)/src/lib/libatm.la $(top_builddir)/src/ilmid/asn1/libasn1.a
+
+ ilmid_DEPENDENCIES = $(ilmid_LDADD)
+
+@@ -127,8 +123,11 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
++DEP_FILES = .deps/atmf_uni.P .deps/ilmid.P .deps/io.P .deps/message.P \
++.deps/mib.P .deps/rfc1155_smi.P .deps/rfc1157_snmp.P .deps/sysgroup.P \
++.deps/util.P
+ SOURCES = $(ilmid_SOURCES)
+ OBJECTS = $(ilmid_OBJECTS)
+
+@@ -136,9 +135,9 @@
+ .SUFFIXES:
+ .SUFFIXES: .S .c .lo .o .obj .s
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/ilmid/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/ilmid/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -168,9 +167,6 @@
+ rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ done
+
+-.c.o:
+- $(COMPILE) -c $<
+-
+ # FIXME: We should only use cygpath when building on Windows,
+ # and only if it is available.
+ .c.obj:
+@@ -193,9 +189,6 @@
+
+ maintainer-clean-compile:
+
+-.c.lo:
+- $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+-
+ .s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+@@ -294,7 +287,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -310,6 +303,11 @@
+ subdir = src/ilmid
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/ilmid/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+@@ -330,62 +328,38 @@
+ || exit 1; \
+ fi; \
+ done
+-atmf_uni.o: atmf_uni.c ../../config.h atmf_uni.h asn1/asn_incl.h \
+- asn1/asn_config.h asn1/nibble_alloc.h asn1/sbuf.h asn1/print.h \
+- asn1/asn_len.h asn1/asn_tag.h asn1/asn_int.h asn1/asn_octs.h \
+- asn1/asn_bits.h asn1/asn_oid.h asn1/asn_null.h asn1/asn_list.h \
+- rfc1155_smi.h rfc1157_snmp.h mib.h ../../src/include/atmd.h \
+- ../../src/include/stdint.h ../../src/include/atm.h util.h
+-ilmid.o: ilmid.c ../../config.h asn1/asn_incl.h asn1/asn_config.h \
+- asn1/nibble_alloc.h asn1/sbuf.h asn1/print.h asn1/asn_len.h \
+- asn1/asn_tag.h asn1/asn_int.h asn1/asn_octs.h asn1/asn_bits.h \
+- asn1/asn_oid.h asn1/asn_null.h asn1/asn_list.h rfc1155_smi.h \
+- rfc1157_snmp.h message.h util.h ../../src/include/atmd.h \
+- ../../src/include/stdint.h ../../src/include/atm.h io.h mib.h \
+- atmf_uni.h sysgroup.h
+-io.o: io.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atm.h io.h asn1/asn_incl.h asn1/asn_config.h \
+- asn1/nibble_alloc.h asn1/sbuf.h asn1/print.h asn1/asn_len.h \
+- asn1/asn_tag.h asn1/asn_int.h asn1/asn_octs.h asn1/asn_bits.h \
+- asn1/asn_oid.h asn1/asn_null.h asn1/asn_list.h rfc1155_smi.h \
+- rfc1157_snmp.h ../../src/include/atmd.h atmf_uni.h mib.h
+-message.o: message.c ../../config.h message.h asn1/asn_incl.h \
+- asn1/asn_config.h asn1/nibble_alloc.h asn1/sbuf.h asn1/print.h \
+- asn1/asn_len.h asn1/asn_tag.h asn1/asn_int.h asn1/asn_octs.h \
+- asn1/asn_bits.h asn1/asn_oid.h asn1/asn_null.h asn1/asn_list.h \
+- rfc1155_smi.h rfc1157_snmp.h atmf_uni.h mib.h \
+- ../../src/include/atmd.h ../../src/include/stdint.h \
+- ../../src/include/atm.h util.h
+-mib.o: mib.c ../../config.h mib.h ../../src/include/atmd.h \
+- ../../src/include/stdint.h ../../src/include/atm.h \
+- asn1/asn_incl.h asn1/asn_config.h asn1/nibble_alloc.h \
+- asn1/sbuf.h asn1/print.h asn1/asn_len.h asn1/asn_tag.h \
+- asn1/asn_int.h asn1/asn_octs.h asn1/asn_bits.h asn1/asn_oid.h \
+- asn1/asn_null.h asn1/asn_list.h rfc1155_smi.h rfc1157_snmp.h \
+- sysgroup.h atmf_uni.h util.h
+-rfc1155_smi.o: rfc1155_smi.c ../../config.h asn1/asn_incl.h \
+- asn1/asn_config.h asn1/nibble_alloc.h asn1/sbuf.h asn1/print.h \
+- asn1/asn_len.h asn1/asn_tag.h asn1/asn_int.h asn1/asn_octs.h \
+- asn1/asn_bits.h asn1/asn_oid.h asn1/asn_null.h asn1/asn_list.h \
+- rfc1155_smi.h rfc1157_snmp.h
+-rfc1157_snmp.o: rfc1157_snmp.c ../../config.h asn1/asn_incl.h \
+- asn1/asn_config.h asn1/nibble_alloc.h asn1/sbuf.h asn1/print.h \
+- asn1/asn_len.h asn1/asn_tag.h asn1/asn_int.h asn1/asn_octs.h \
+- asn1/asn_bits.h asn1/asn_oid.h asn1/asn_null.h asn1/asn_list.h \
+- rfc1155_smi.h rfc1157_snmp.h
+-sysgroup.o: sysgroup.c ../../config.h sysgroup.h asn1/asn_incl.h \
+- asn1/asn_config.h asn1/nibble_alloc.h asn1/sbuf.h asn1/print.h \
+- asn1/asn_len.h asn1/asn_tag.h asn1/asn_int.h asn1/asn_octs.h \
+- asn1/asn_bits.h asn1/asn_oid.h asn1/asn_null.h asn1/asn_list.h \
+- rfc1155_smi.h rfc1157_snmp.h mib.h ../../src/include/atmd.h \
+- ../../src/include/stdint.h ../../src/include/atm.h
+-util.o: util.c ../../config.h util.h asn1/asn_incl.h asn1/asn_config.h \
+- asn1/nibble_alloc.h asn1/sbuf.h asn1/print.h asn1/asn_len.h \
+- asn1/asn_tag.h asn1/asn_int.h asn1/asn_octs.h asn1/asn_bits.h \
+- asn1/asn_oid.h asn1/asn_null.h asn1/asn_list.h rfc1155_smi.h \
+- rfc1157_snmp.h ../../src/include/atmd.h \
+- ../../src/include/stdint.h ../../src/include/atm.h
+
++DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
++
++-include $(DEP_FILES)
++
++mostlyclean-depend:
++
++clean-depend:
++
++distclean-depend:
++ -rm -rf .deps
++
++maintainer-clean-depend:
++
++%.o: %.c
++ @echo '$(COMPILE) -c $<'; \
++ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-cp .deps/$(*F).pp .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm .deps/$(*F).pp
++
++%.lo: %.c
++ @echo '$(LTCOMPILE) -c $<'; \
++ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
++ < .deps/$(*F).pp > .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm -f .deps/$(*F).pp
+ info-am:
+ info: info-recursive
+ dvi-am:
+@@ -424,27 +398,27 @@
+
+ maintainer-clean-generic:
+ mostlyclean-am: mostlyclean-sbinPROGRAMS mostlyclean-compile \
+- mostlyclean-libtool mostlyclean-tags \
++ mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+ mostlyclean-generic
+
+ mostlyclean: mostlyclean-recursive
+
+ clean-am: clean-sbinPROGRAMS clean-compile clean-libtool clean-tags \
+- clean-generic mostlyclean-am
++ clean-depend clean-generic mostlyclean-am
+
+ clean: clean-recursive
+
+ distclean-am: distclean-sbinPROGRAMS distclean-compile \
+- distclean-libtool distclean-tags distclean-generic \
+- clean-am
++ distclean-libtool distclean-tags distclean-depend \
++ distclean-generic clean-am
+ -rm -f libtool
+
+ distclean: distclean-recursive
+
+ maintainer-clean-am: maintainer-clean-sbinPROGRAMS \
+ maintainer-clean-compile maintainer-clean-libtool \
+- maintainer-clean-tags maintainer-clean-generic \
+- distclean-am
++ maintainer-clean-tags maintainer-clean-depend \
++ 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."
+
+@@ -460,12 +434,14 @@
+ all-recursive check-recursive installcheck-recursive info-recursive \
+ dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
+ maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
+-distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+-dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
+-install-exec install-data-am install-data install-am install \
+-uninstall-am uninstall all-redirect all-am all installdirs-am \
+-installdirs mostlyclean-generic distclean-generic clean-generic \
+-maintainer-clean-generic clean mostlyclean distclean maintainer-clean
++distclean-tags clean-tags maintainer-clean-tags distdir \
++mostlyclean-depend distclean-depend clean-depend \
++maintainer-clean-depend info-am info dvi-am dvi check check-am \
++installcheck-am installcheck install-exec-am install-exec \
++install-data-am install-data install-am install uninstall-am uninstall \
++all-redirect all-am all installdirs-am 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.
+--- linux-atm-2.4.1.orig/src/ilmid/io.c
++++ linux-atm-2.4.1/src/ilmid/io.c
+@@ -32,6 +32,7 @@
+ #include <net/if.h>
+ #include <atm.h>
+ #include <linux/atmdev.h>
++#include <unistd.h>
+ #include "io.h"
+ #include "atmd.h"
+ #include "atmf_uni.h"
+@@ -299,4 +300,5 @@
+ diag(COMPONENT,DIAG_ERROR,"ioctl ATM_GETCIRANGE: %s",strerror(errno));
+ return error;
+ }
++ return 0;
+ }
+--- linux-atm-2.4.1.orig/src/ilmid/atmf_uni.c
++++ linux-atm-2.4.1/src/ilmid/atmf_uni.c
+@@ -187,7 +187,7 @@
+ newPrefix->name = alloc_t(AsnOid);
+ newPrefix->name->octs = alloc(varBindName->octetLen);
+ AsnOidCopy(newPrefix->name, varBindName);
+- Q_INSERT_BEFORE((NetPrefixNode *) var->value, newPrefix, prefix);
++ Q_INSERT_BEFORE_TYPED(var->value,(NetPrefixNode *), newPrefix, prefix);
+ if(atmNetPrefix.octs == NULL)
+ {
+ atmNetPrefix.octetLen = varBindName->octetLen - NETPREFIX_LEN - 2;
+@@ -197,7 +197,7 @@
+ }
+ else if (varbind->value->a.simple->a.number == INVALID && cmp == AsnOidEqual)
+ {
+- Q_REMOVE((NetPrefixNode *) var->value, prefix);
++ Q_REMOVE(var->value, prefix);
+ }
+
+ return NOERROR;
+--- linux-atm-2.4.1.orig/src/ilmid/mib.c
++++ linux-atm-2.4.1/src/ilmid/mib.c
+@@ -58,13 +58,13 @@
+ { NULL }
+ };
+
+-void MIBget(VarBindList *list, PDUInt *status, AsnInt *index)
++void MIBget(VarBindList *list, PDUInt *status, AsnInt *Mindex)
+ {
+ VarBind *varbind;
+ Variable *var;
+ AsnOidResult result;
+
+- *index = 1;
++ *Mindex = 1;
+ FOR_EACH_LIST_ELMT(varbind, list)
+ {
+ /* Find the first MIB object not lexigraphically less than the *
+@@ -91,20 +91,20 @@
+ if(*status != NOERROR)
+ return;
+
+- (*index)++;
++ (*Mindex)++;
+ }
+- *index = 0;
++ *Mindex = 0;
+ return;
+ }
+
+
+-void MIBgetnext(VarBindList *list, PDUInt *status, AsnInt *index)
++void MIBgetnext(VarBindList *list, PDUInt *status, AsnInt *Mindex)
+ {
+ VarBind *varbind;
+ Variable *var;
+ AsnOidResult result;
+
+- *index = 1;
++ *Mindex = 1;
+ FOR_EACH_LIST_ELMT(varbind, list)
+ {
+ /* Find the first complex MIB object not lexigraphically less than *
+@@ -139,19 +139,19 @@
+ if(*status != NOERROR)
+ return;
+
+- (*index)++;
++ (*Mindex)++;
+ }
+- *index = 0;
++ *Mindex = 0;
+ return;
+ }
+
+-void MIBset(VarBindList *list, PDUInt *status, AsnInt *index)
++void MIBset(VarBindList *list, PDUInt *status, AsnInt *Mindex)
+ {
+ VarBind *varbind;
+ Variable *var;
+ AsnOidResult result;
+
+- *index = 1;
++ *Mindex = 1;
+ FOR_EACH_LIST_ELMT(varbind, list)
+ {
+ /* Find the first MIB object not lexigraphically less than the *
+@@ -182,9 +182,9 @@
+ if(*status != NOERROR)
+ return;
+
+- (*index)++;
++ (*Mindex)++;
+ }
+- *index = 0;
++ *Mindex = 0;
+ return;
+ }
+
+--- linux-atm-2.4.1.orig/src/ilmid/mib.h
++++ linux-atm-2.4.1/src/ilmid/mib.h
+@@ -39,9 +39,9 @@
+ void *value;
+ } Variable;
+
+-void MIBget(VarBindList *list, PDUInt *status, AsnInt *index);
+-void MIBgetnext(VarBindList *list, PDUInt *status, AsnInt *index);
+-void MIBset(VarBindList *list, PDUInt *status, AsnInt *index);
++void MIBget(VarBindList *list, PDUInt *status, AsnInt *Mindex);
++void MIBgetnext(VarBindList *list, PDUInt *status, AsnInt *Mindex);
++void MIBset(VarBindList *list, PDUInt *status, AsnInt *Mindex);
+ void *MIBdelete(AsnOid *oid);
+
+ AsnInt getString(VarBind *varbind, Variable *var);
+--- linux-atm-2.4.1.orig/src/ilmid/ilmid.c
++++ linux-atm-2.4.1/src/ilmid/ilmid.c
+@@ -33,6 +33,7 @@
+ #include <config.h>
+ #endif
+
++#include <stdlib.h>
+ #include <unistd.h>
+ #include <sys/time.h>
+ #include <errno.h>
+--- linux-atm-2.4.1.orig/src/ilmid/asn1/Makefile.in
++++ linux-atm-2.4.1/src/ilmid/asn1/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -87,13 +87,7 @@
+
+ noinst_LIBRARIES = libasn1.a
+
+-libasn1_a_SOURCES = asn_len.c asn_len.h asn_tag.c asn_tag.h \
+- asn_int.c asn_int.h asn_octs.c asn_octs.h \
+- asn_bits.c asn_bits.h str_stk.c str_stk.h \
+- asn_oid.c asn_oid.h asn_null.c asn_null.h \
+- asn_list.c asn_list.h nibble_alloc.c nibble_alloc.h \
+- print.c print.h \
+- asn_config.h min_buf.h sbuf.h exp_buf.h
++libasn1_a_SOURCES = asn_len.c asn_len.h asn_tag.c asn_tag.h asn_int.c asn_int.h asn_octs.c asn_octs.h asn_bits.c asn_bits.h str_stk.c str_stk.h asn_oid.c asn_oid.h asn_null.c asn_null.h asn_list.c asn_list.h nibble_alloc.c nibble_alloc.h print.c print.h asn_config.h min_buf.h sbuf.h exp_buf.h
+
+
+ EXTRA_libasn1_a_SOURCES = asn_incl.h exp_buf.c
+@@ -125,8 +119,12 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
++DEP_FILES = .deps/asn_bits.P .deps/asn_int.P .deps/asn_len.P \
++.deps/asn_list.P .deps/asn_null.P .deps/asn_octs.P .deps/asn_oid.P \
++.deps/asn_tag.P .deps/exp_buf.P .deps/nibble_alloc.P .deps/print.P \
++.deps/str_stk.P
+ SOURCES = $(libasn1_a_SOURCES) $(EXTRA_libasn1_a_SOURCES)
+ OBJECTS = $(libasn1_a_OBJECTS)
+
+@@ -134,9 +132,9 @@
+ .SUFFIXES:
+ .SUFFIXES: .S .c .lo .o .obj .s
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/ilmid/asn1/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/ilmid/asn1/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -150,9 +148,6 @@
+
+ maintainer-clean-noinstLIBRARIES:
+
+-.c.o:
+- $(COMPILE) -c $<
+-
+ # FIXME: We should only use cygpath when building on Windows,
+ # and only if it is available.
+ .c.obj:
+@@ -175,9 +170,6 @@
+
+ maintainer-clean-compile:
+
+-.c.lo:
+- $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+-
+ .s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+@@ -217,7 +209,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -233,6 +225,11 @@
+ subdir = src/ilmid/asn1
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/ilmid/asn1/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+@@ -243,30 +240,38 @@
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+-asn_bits.o: asn_bits.c ../../../config.h asn_config.h nibble_alloc.h \
+- sbuf.h print.h asn_len.h asn_tag.h str_stk.h asn_bits.h
+-asn_int.o: asn_int.c ../../../config.h asn_config.h nibble_alloc.h \
+- sbuf.h print.h asn_len.h asn_tag.h asn_int.h
+-asn_len.o: asn_len.c ../../../config.h asn_config.h nibble_alloc.h \
+- sbuf.h print.h asn_len.h
+-asn_list.o: asn_list.c ../../../config.h asn_config.h nibble_alloc.h \
+- sbuf.h print.h asn_list.h
+-asn_null.o: asn_null.c ../../../config.h asn_config.h nibble_alloc.h \
+- sbuf.h print.h asn_len.h asn_tag.h asn_null.h
+-asn_octs.o: asn_octs.c ../../../config.h asn_config.h nibble_alloc.h \
+- sbuf.h print.h asn_len.h asn_tag.h str_stk.h asn_bits.h \
+- asn_octs.h
+-asn_oid.o: asn_oid.c ../../../config.h asn_config.h nibble_alloc.h \
+- sbuf.h print.h asn_len.h asn_tag.h asn_octs.h asn_oid.h
+-asn_tag.o: asn_tag.c ../../../config.h asn_config.h nibble_alloc.h \
+- sbuf.h print.h asn_len.h asn_tag.h
+-nibble_alloc.o: nibble_alloc.c ../../../config.h asn_config.h \
+- nibble_alloc.h sbuf.h print.h
+-print.o: print.c ../../../config.h asn_config.h nibble_alloc.h sbuf.h \
+- print.h
+-str_stk.o: str_stk.c ../../../config.h asn_config.h nibble_alloc.h \
+- sbuf.h print.h str_stk.h
+
++DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
++
++-include $(DEP_FILES)
++
++mostlyclean-depend:
++
++clean-depend:
++
++distclean-depend:
++ -rm -rf .deps
++
++maintainer-clean-depend:
++
++%.o: %.c
++ @echo '$(COMPILE) -c $<'; \
++ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-cp .deps/$(*F).pp .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm .deps/$(*F).pp
++
++%.lo: %.c
++ @echo '$(LTCOMPILE) -c $<'; \
++ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
++ < .deps/$(*F).pp > .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm -f .deps/$(*F).pp
+ info-am:
+ info: info-am
+ dvi-am:
+@@ -303,27 +308,27 @@
+
+ maintainer-clean-generic:
+ mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+- mostlyclean-libtool mostlyclean-tags \
++ mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+ mostlyclean-generic
+
+ mostlyclean: mostlyclean-am
+
+ clean-am: clean-noinstLIBRARIES clean-compile clean-libtool clean-tags \
+- clean-generic mostlyclean-am
++ clean-depend clean-generic mostlyclean-am
+
+ clean: clean-am
+
+ distclean-am: distclean-noinstLIBRARIES distclean-compile \
+- distclean-libtool distclean-tags distclean-generic \
+- clean-am
++ distclean-libtool distclean-tags distclean-depend \
++ distclean-generic clean-am
+ -rm -f libtool
+
+ distclean: distclean-am
+
+ maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
+ maintainer-clean-compile maintainer-clean-libtool \
+- maintainer-clean-tags maintainer-clean-generic \
+- distclean-am
++ maintainer-clean-tags maintainer-clean-depend \
++ 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."
+
+@@ -334,12 +339,14 @@
+ mostlyclean-compile distclean-compile clean-compile \
+ maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+ clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+-distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+-dvi-am dvi check check-am installcheck-am installcheck 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
++distclean-tags clean-tags maintainer-clean-tags distdir \
++mostlyclean-depend distclean-depend clean-depend \
++maintainer-clean-depend info-am info dvi-am dvi check check-am \
++installcheck-am installcheck 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.
+--- linux-atm-2.4.1.orig/src/ilmid/asn1/asn_int.c
++++ linux-atm-2.4.1/src/ilmid/asn1/asn_int.c
+@@ -185,7 +185,7 @@
+ AsnInt* v _AND_
+ unsigned short int indent)
+ {
+- fprintf(f,"%d", *v);
++ fprintf(f,"%ld", *v);
+ }
+
+
+@@ -252,7 +252,6 @@
+ UAsnInt* data)
+ {
+ int len;
+- int retLen;
+ int i;
+ unsigned long int mask;
+ unsigned long int dataCpy;
+@@ -370,5 +369,5 @@
+ UAsnInt* v _AND_
+ unsigned short int indent)
+ {
+- fprintf(f,"%u", *v);
++ fprintf(f,"%lu", *v);
+ }
+--- linux-atm-2.4.1.orig/src/ilmid/asn1/asn_octs.c
++++ linux-atm-2.4.1/src/ilmid/asn1/asn_octs.c
+@@ -21,6 +21,9 @@
+ #include <config.h>
+ #endif
+
++#include <stdlib.h>
++#include <string.h>
++
+ #include "asn_config.h"
+ #include "asn_len.h"
+ #include "asn_tag.h"
+--- linux-atm-2.4.1.orig/src/ilmid/asn1/asn_bits.c
++++ linux-atm-2.4.1/src/ilmid/asn1/asn_bits.c
+@@ -21,6 +21,9 @@
+ #include <config.h>
+ #endif
+
++#include <stdlib.h>
++#include <string.h>
++
+ #include "asn_config.h"
+ #include "asn_len.h"
+ #include "asn_tag.h"
+--- linux-atm-2.4.1.orig/src/ilmid/asn1/asn_oid.c
++++ linux-atm-2.4.1/src/ilmid/asn1/asn_oid.c
+@@ -21,6 +21,9 @@
+ #include <config.h>
+ #endif
+
++#include <stdlib.h>
++#include <string.h>
++
+ #include "asn_config.h"
+ #include "asn_len.h"
+ #include "asn_tag.h"
+@@ -125,7 +128,7 @@
+ 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 ; )
+ {
+@@ -134,7 +137,7 @@
+
+ arcNum = (arcNum << 7) + (v->octs[i] & 0x7f);
+ i++;
+- fprintf(f," %u", arcNum);
++ fprintf(f," %lu", arcNum);
+ }
+ fprintf(f,"}");
+
+--- linux-atm-2.4.1.orig/src/ilmid/asn1/asn_list.c
++++ linux-atm-2.4.1/src/ilmid/asn1/asn_list.c
+@@ -20,6 +20,8 @@
+ #include <config.h>
+ #endif
+
++#include <stdlib.h>
++
+ #include "asn_config.h"
+ #include "asn_list.h"
+
+--- linux-atm-2.4.1.orig/src/ilmid/asn1/nibble_alloc.c
++++ linux-atm-2.4.1/src/ilmid/asn1/nibble_alloc.c
+@@ -20,7 +20,9 @@
+ #include <config.h>
+ #endif
+
++#include <string.h>
+ #include <memory.h>
++#include <stdlib.h>
+ #include "asn_config.h"
+ #include "nibble_alloc.h"
+
+--- linux-atm-2.4.1.orig/src/ilmid/asn1/nibble_alloc.h
++++ linux-atm-2.4.1/src/ilmid/asn1/nibble_alloc.h
+@@ -39,13 +39,13 @@
+ void InitNibbleMem PROTO((unsigned long int initialSize,
+ unsigned long int incrementSize));
+
+-void ShutdownNibbleMem();
++void ShutdownNibbleMem(void);
+
+ void ServiceNibbleFault PROTO((unsigned long int size));
+
+ void* NibbleAlloc PROTO((unsigned long int size));
+
+-void ResetNibbleMem();
++void ResetNibbleMem(void);
+
+
+ #endif /* conditional include */
+--- linux-atm-2.4.1.orig/src/man/Makefile.in
++++ linux-atm-2.4.1/src/man/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -100,14 +100,14 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
+ all: all-redirect
+ .SUFFIXES:
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/man/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/man/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -159,6 +159,11 @@
+ subdir = src/man
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/man/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+--- linux-atm-2.4.1.orig/src/led/Makefile.in
++++ linux-atm-2.4.1/src/led/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -87,9 +87,7 @@
+
+ sbin_PROGRAMS = zeppelin
+
+-zeppelin_SOURCES = join.c join.h conn.c conn.h main.c address.c address.h \
+- frames.c frames.h display.c display.h \
+- kernel.c kernel.h frame_defs.h lec.h
++zeppelin_SOURCES = join.c join.h conn.c conn.h main.c address.c address.h frames.c frames.h display.c display.h kernel.c kernel.h frame_defs.h lec.h
+
+ zeppelin_LDADD = $(top_builddir)/src/lib/libatm.la
+ zeppelin_DEPENDENCIES = $(zeppelin_LDADD)
+@@ -125,8 +123,10 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
++DEP_FILES = .deps/address.P .deps/conn.P .deps/display.P .deps/frames.P \
++.deps/join.P .deps/kernel.P .deps/main.P
+ SOURCES = $(zeppelin_SOURCES)
+ OBJECTS = $(zeppelin_OBJECTS)
+
+@@ -134,9 +134,9 @@
+ .SUFFIXES:
+ .SUFFIXES: .S .c .lo .o .obj .s
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/led/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/led/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -166,9 +166,6 @@
+ rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ done
+
+-.c.o:
+- $(COMPILE) -c $<
+-
+ # FIXME: We should only use cygpath when building on Windows,
+ # and only if it is available.
+ .c.obj:
+@@ -191,9 +188,6 @@
+
+ maintainer-clean-compile:
+
+-.c.lo:
+- $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+-
+ .s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+@@ -271,7 +265,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -287,6 +281,11 @@
+ subdir = src/led
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/led/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+@@ -297,28 +296,38 @@
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+-address.o: address.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h address.h
+-conn.o: conn.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmsap.h \
+- ../../src/include/atmd.h conn.h display.h lec.h frames.h \
+- frame_defs.h kernel.h
+-display.o: display.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h display.h \
+- frame_defs.h
+-frames.o: frames.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h conn.h \
+- lec.h frames.h frame_defs.h display.h kernel.h
+-join.o: join.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h conn.h \
+- lec.h join.h frames.h frame_defs.h display.h
+-kernel.o: kernel.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h kernel.h \
+- lec.h conn.h frames.h frame_defs.h
+-main.o: main.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h join.h \
+- lec.h conn.h address.h display.h kernel.h
+
++DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
++
++-include $(DEP_FILES)
++
++mostlyclean-depend:
++
++clean-depend:
++
++distclean-depend:
++ -rm -rf .deps
++
++maintainer-clean-depend:
++
++%.o: %.c
++ @echo '$(COMPILE) -c $<'; \
++ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-cp .deps/$(*F).pp .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm .deps/$(*F).pp
++
++%.lo: %.c
++ @echo '$(LTCOMPILE) -c $<'; \
++ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
++ < .deps/$(*F).pp > .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm -f .deps/$(*F).pp
+ info-am:
+ info: info-am
+ dvi-am:
+@@ -356,27 +365,27 @@
+
+ maintainer-clean-generic:
+ mostlyclean-am: mostlyclean-sbinPROGRAMS mostlyclean-compile \
+- mostlyclean-libtool mostlyclean-tags \
++ mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+ mostlyclean-generic
+
+ mostlyclean: mostlyclean-am
+
+ clean-am: clean-sbinPROGRAMS clean-compile clean-libtool clean-tags \
+- clean-generic mostlyclean-am
++ clean-depend clean-generic mostlyclean-am
+
+ clean: clean-am
+
+ distclean-am: distclean-sbinPROGRAMS distclean-compile \
+- distclean-libtool distclean-tags distclean-generic \
+- clean-am
++ distclean-libtool distclean-tags distclean-depend \
++ distclean-generic clean-am
+ -rm -f libtool
+
+ distclean: distclean-am
+
+ maintainer-clean-am: maintainer-clean-sbinPROGRAMS \
+ maintainer-clean-compile maintainer-clean-libtool \
+- maintainer-clean-tags maintainer-clean-generic \
+- distclean-am
++ maintainer-clean-tags maintainer-clean-depend \
++ 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."
+
+@@ -388,12 +397,14 @@
+ clean-compile maintainer-clean-compile mostlyclean-libtool \
+ distclean-libtool clean-libtool maintainer-clean-libtool install-man8 \
+ uninstall-man8 install-man uninstall-man tags mostlyclean-tags \
+-distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+-dvi-am dvi check check-am installcheck-am installcheck 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
++distclean-tags clean-tags maintainer-clean-tags distdir \
++mostlyclean-depend distclean-depend clean-depend \
++maintainer-clean-depend info-am info dvi-am dvi check check-am \
++installcheck-am installcheck 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.
+--- linux-atm-2.4.1.orig/src/lane/Makefile.in
++++ linux-atm-2.4.1/src/lane/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -89,14 +89,11 @@
+
+ LDADD = $(top_builddir)/src/lib/libatm.la
+
+-LES_BUS_SRCS = mem.c mem.h load.c load.h units.c units.h load_lex.l load_lex.h \
+- timers.c timers.h dump.c dump.h lane_atm.c lane_atm.h \
+- events.c events.h lane.c lane.h
++LES_BUS_SRCS = mem.c mem.h load.c load.h units.c units.h load_lex.l load_lex.h timers.c timers.h dump.c dump.h lane_atm.c lane_atm.h events.c events.h lane.c lane.h
+
+ les_SOURCES = $(LES_BUS_SRCS) packet.c packet.h connect.c connect.h db.c db.h
+ bus_SOURCES = $(LES_BUS_SRCS) connect_bus.c
+-lecs_SOURCES = lecs_db.l lecs_db.h lecs_load.c lecs_load.h lecs.c lecs.h \
+- ldb.c ldb.h mem_lecs.c mem_lecs.h atm_lecs.c atm_lecs.h
++lecs_SOURCES = lecs_db.l lecs_db.h lecs_load.c lecs_load.h lecs.c lecs.h ldb.c ldb.h mem_lecs.c mem_lecs.h atm_lecs.c atm_lecs.h
+
+
+ man_MANS = les.8 lecs.8 bus.8
+@@ -148,8 +145,13 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
++DEP_FILES = .deps/atm_lecs.P .deps/connect.P .deps/connect_bus.P \
++.deps/db.P .deps/dump.P .deps/events.P .deps/lane.P .deps/lane_atm.P \
++.deps/ldb.P .deps/lecs.P .deps/lecs_db.P .deps/lecs_load.P .deps/load.P \
++.deps/load_lex.P .deps/mem.P .deps/mem_lecs.P .deps/packet.P \
++.deps/timers.P .deps/units.P
+ SOURCES = $(les_SOURCES) $(bus_SOURCES) $(lecs_SOURCES)
+ OBJECTS = $(les_OBJECTS) $(bus_OBJECTS) $(lecs_OBJECTS)
+
+@@ -157,9 +159,9 @@
+ .SUFFIXES:
+ .SUFFIXES: .S .c .l .lo .o .obj .s
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/lane/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/lane/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -189,9 +191,6 @@
+ rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ done
+
+-.c.o:
+- $(COMPILE) -c $<
+-
+ # FIXME: We should only use cygpath when building on Windows,
+ # and only if it is available.
+ .c.obj:
+@@ -214,9 +213,6 @@
+
+ maintainer-clean-compile:
+
+-.c.lo:
+- $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+-
+ .s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+@@ -304,7 +300,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -320,6 +316,11 @@
+ subdir = src/lane
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/lane/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+@@ -330,62 +331,38 @@
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+-atm_lecs.o: atm_lecs.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmsap.h \
+- atm_lecs.h
+-connect.o: connect.c ../../config.h ../../src/include/stdint.h mem.h \
+- units.h lane.h dump.h ../../src/include/atm.h \
+- ../../src/include/atmsap.h load.h connect.h timers.h events.h \
+- db.h packet.h lane_atm.h
+-connect_bus.o: connect_bus.c ../../config.h ../../src/include/stdint.h \
+- mem.h units.h lane.h dump.h ../../src/include/atm.h \
+- ../../src/include/atmsap.h load.h connect.h timers.h events.h \
+- lane_atm.h
+-db.o: db.c ../../config.h ../../src/include/stdint.h mem.h units.h \
+- lane.h dump.h ../../src/include/atm.h \
+- ../../src/include/atmsap.h load.h connect.h timers.h events.h \
+- db.h
+-dump.o: dump.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atm.h ../../src/include/atmsap.h dump.h \
+- units.h lane.h load.h
+-events.o: events.c ../../config.h events.h units.h load.h lane.h dump.h \
+- ../../src/include/atm.h ../../src/include/stdint.h \
+- ../../src/include/atmsap.h mem.h timers.h connect.h
+-lane.o: lane.c ../../config.h units.h load.h lane.h dump.h \
+- ../../src/include/atm.h ../../src/include/stdint.h \
+- ../../src/include/atmsap.h mem.h connect.h timers.h events.h
+-lane_atm.o: lane_atm.c ../../config.h lane_atm.h units.h lane.h \
+- connect.h timers.h load.h events.h ../../src/include/atmsap.h \
+- ../../src/include/stdint.h dump.h ../../src/include/atm.h mem.h
+-ldb.o: ldb.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h lecs.h ldb.h mem_lecs.h
+-lecs.o: lecs.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atm.h lecs_load.h ldb.h mem_lecs.h lecs.h \
+- atm_lecs.h
+-lecs_db.o: lecs_db.c ../../config.h lecs_load.h lecs_db.h
+-lecs_load.o: lecs_load.c ../../config.h lecs_load.h lecs_db.h ldb.h \
+- lecs.h
+-load.o: load.c ../../config.h load.h units.h lane.h dump.h \
+- ../../src/include/atm.h ../../src/include/stdint.h \
+- ../../src/include/atmsap.h mem.h load_lex.h
+-load_lex.o: load_lex.c ../../config.h ../../src/include/stdint.h \
+- load_lex.h lane.h units.h load.h mem.h
+-mem.o: mem.c ../../config.h mem.h units.h dump.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmsap.h lane.h \
+- load.h
+-mem_lecs.o: mem_lecs.c ../../config.h mem_lecs.h
+-packet.o: packet.c ../../config.h ../../src/include/stdint.h mem.h \
+- units.h lane.h dump.h ../../src/include/atm.h \
+- ../../src/include/atmsap.h load.h connect.h timers.h events.h \
+- db.h packet.h
+-timers.o: timers.c ../../config.h timers.h units.h load.h lane.h dump.h \
+- ../../src/include/atm.h ../../src/include/stdint.h \
+- ../../src/include/atmsap.h mem.h
+-units.o: units.c ../../config.h units.h mem.h lane.h load.h dump.h \
+- ../../src/include/atm.h ../../src/include/stdint.h \
+- ../../src/include/atmsap.h connect.h timers.h events.h \
+- lane_atm.h
+
++DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
++
++-include $(DEP_FILES)
++
++mostlyclean-depend:
++
++clean-depend:
++
++distclean-depend:
++ -rm -rf .deps
++
++maintainer-clean-depend:
++
++%.o: %.c
++ @echo '$(COMPILE) -c $<'; \
++ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-cp .deps/$(*F).pp .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm .deps/$(*F).pp
++
++%.lo: %.c
++ @echo '$(LTCOMPILE) -c $<'; \
++ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
++ < .deps/$(*F).pp > .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm -f .deps/$(*F).pp
+ info-am:
+ info: info-am
+ dvi-am:
+@@ -422,29 +399,29 @@
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+ maintainer-clean-generic:
+- -test -z "lecs_dblload_lexl" || rm -f lecs_dbl load_lexl
++ -test -z "lecs_dbcload_lexc" || rm -f lecs_dbc load_lexc
+ mostlyclean-am: mostlyclean-sbinPROGRAMS mostlyclean-compile \
+- mostlyclean-libtool mostlyclean-tags \
++ mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+ mostlyclean-generic
+
+ mostlyclean: mostlyclean-am
+
+ clean-am: clean-sbinPROGRAMS clean-compile clean-libtool clean-tags \
+- clean-generic mostlyclean-am
++ clean-depend clean-generic mostlyclean-am
+
+ clean: clean-am
+
+ distclean-am: distclean-sbinPROGRAMS distclean-compile \
+- distclean-libtool distclean-tags distclean-generic \
+- clean-am
++ distclean-libtool distclean-tags distclean-depend \
++ distclean-generic clean-am
+ -rm -f libtool
+
+ distclean: distclean-am
+
+ maintainer-clean-am: maintainer-clean-sbinPROGRAMS \
+ maintainer-clean-compile maintainer-clean-libtool \
+- maintainer-clean-tags maintainer-clean-generic \
+- distclean-am
++ maintainer-clean-tags maintainer-clean-depend \
++ 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."
+
+@@ -456,12 +433,14 @@
+ clean-compile maintainer-clean-compile mostlyclean-libtool \
+ distclean-libtool clean-libtool maintainer-clean-libtool install-man8 \
+ uninstall-man8 install-man uninstall-man tags mostlyclean-tags \
+-distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+-dvi-am dvi check check-am installcheck-am installcheck 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
++distclean-tags clean-tags maintainer-clean-tags distdir \
++mostlyclean-depend distclean-depend clean-depend \
++maintainer-clean-depend info-am info dvi-am dvi check check-am \
++installcheck-am installcheck 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.
+--- linux-atm-2.4.1.orig/src/mpoad/Makefile.in
++++ linux-atm-2.4.1/src/mpoad/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -89,9 +89,7 @@
+
+ LDADD = $(top_builddir)/src/lib/libatm.la
+
+-mpcd_SOURCES = get_vars.c get_vars.h io.c io.h k_interf.c k_interf.h main.c \
+- p_factory.c p_recogn.c id_list.c tag_list.c \
+- poll2select.c poll2select.h lecs.c lecs.h packets.h
++mpcd_SOURCES = get_vars.c get_vars.h io.c io.h k_interf.c k_interf.h main.c p_factory.c p_recogn.c id_list.c tag_list.c poll2select.c poll2select.h lecs.c lecs.h packets.h
+
+
+ man_MANS = mpcd.8
+@@ -128,8 +126,11 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
++DEP_FILES = .deps/get_vars.P .deps/id_list.P .deps/io.P \
++.deps/k_interf.P .deps/lecs.P .deps/main.P .deps/p_factory.P \
++.deps/p_recogn.P .deps/poll2select.P .deps/tag_list.P
+ SOURCES = $(mpcd_SOURCES)
+ OBJECTS = $(mpcd_OBJECTS)
+
+@@ -137,9 +138,9 @@
+ .SUFFIXES:
+ .SUFFIXES: .S .c .lo .o .obj .s
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/mpoad/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/mpoad/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -169,9 +170,6 @@
+ rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ done
+
+-.c.o:
+- $(COMPILE) -c $<
+-
+ # FIXME: We should only use cygpath when building on Windows,
+ # and only if it is available.
+ .c.obj:
+@@ -194,9 +192,6 @@
+
+ maintainer-clean-compile:
+
+-.c.lo:
+- $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+-
+ .s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+@@ -274,7 +269,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -290,6 +285,11 @@
+ subdir = src/mpoad
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/mpoad/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+@@ -300,29 +300,38 @@
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+-get_vars.o: get_vars.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atm.h packets.h get_vars.h io.h
+-id_list.o: id_list.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h packets.h
+-io.o: io.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h packets.h k_interf.h io.h get_vars.h \
+- poll2select.h
+-k_interf.o: k_interf.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atm.h k_interf.h packets.h io.h get_vars.h
+-lecs.o: lecs.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atm.h ../../src/include/atmsap.h lecs.h \
+- k_interf.h
+-main.o: main.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h packets.h io.h k_interf.h get_vars.h \
+- lecs.h
+-p_factory.o: p_factory.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atm.h packets.h get_vars.h io.h
+-p_recogn.o: p_recogn.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h io.h k_interf.h packets.h
+-poll2select.o: poll2select.c ../../config.h
+-tag_list.o: tag_list.c ../../config.h packets.h ../../src/include/atm.h \
+- ../../src/include/stdint.h
+
++DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
++
++-include $(DEP_FILES)
++
++mostlyclean-depend:
++
++clean-depend:
++
++distclean-depend:
++ -rm -rf .deps
++
++maintainer-clean-depend:
++
++%.o: %.c
++ @echo '$(COMPILE) -c $<'; \
++ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-cp .deps/$(*F).pp .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm .deps/$(*F).pp
++
++%.lo: %.c
++ @echo '$(LTCOMPILE) -c $<'; \
++ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
++ < .deps/$(*F).pp > .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm -f .deps/$(*F).pp
+ info-am:
+ info: info-am
+ dvi-am:
+@@ -360,27 +369,27 @@
+
+ maintainer-clean-generic:
+ mostlyclean-am: mostlyclean-sbinPROGRAMS mostlyclean-compile \
+- mostlyclean-libtool mostlyclean-tags \
++ mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+ mostlyclean-generic
+
+ mostlyclean: mostlyclean-am
+
+ clean-am: clean-sbinPROGRAMS clean-compile clean-libtool clean-tags \
+- clean-generic mostlyclean-am
++ clean-depend clean-generic mostlyclean-am
+
+ clean: clean-am
+
+ distclean-am: distclean-sbinPROGRAMS distclean-compile \
+- distclean-libtool distclean-tags distclean-generic \
+- clean-am
++ distclean-libtool distclean-tags distclean-depend \
++ distclean-generic clean-am
+ -rm -f libtool
+
+ distclean: distclean-am
+
+ maintainer-clean-am: maintainer-clean-sbinPROGRAMS \
+ maintainer-clean-compile maintainer-clean-libtool \
+- maintainer-clean-tags maintainer-clean-generic \
+- distclean-am
++ maintainer-clean-tags maintainer-clean-depend \
++ 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."
+
+@@ -392,12 +401,14 @@
+ clean-compile maintainer-clean-compile mostlyclean-libtool \
+ distclean-libtool clean-libtool maintainer-clean-libtool install-man8 \
+ uninstall-man8 install-man uninstall-man tags mostlyclean-tags \
+-distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+-dvi-am dvi check check-am installcheck-am installcheck 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
++distclean-tags clean-tags maintainer-clean-tags distdir \
++mostlyclean-depend distclean-depend clean-depend \
++maintainer-clean-depend info-am info dvi-am dvi check check-am \
++installcheck-am installcheck 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.
+--- linux-atm-2.4.1.orig/src/mpoad/p_factory.c
++++ linux-atm-2.4.1/src/mpoad/p_factory.c
+@@ -34,7 +34,7 @@
+
+ while( count > 1 ) {
+ /* This is the inner loop */
+- sum += * ((uint16_t *) addr)++;
++ sum += * ((uint16_t *) addr); addr += sizeof(uint16_t);
+ count -= 2;
+ }
+
+--- linux-atm-2.4.1.orig/src/switch/Makefile.in
++++ linux-atm-2.4.1/src/switch/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -92,11 +92,9 @@
+
+ swc_SOURCES = swc.c swc.h
+ swc_LDADD = $(top_builddir)/src/lib/libatm.la
+-swc_DEPENDENCIES = $(swc_LDADD) $(top_builddir)/src/include/atm.h \
+- $(top_builddir)/src/include/atmd.h
++swc_DEPENDENCIES = $(swc_LDADD) $(top_builddir)/src/include/atm.h $(top_builddir)/src/include/atmd.h
+
+-libsw_a_SOURCES = control.c dispatch.c dispatch.h proto.c proto.h relay.c \
+- route.c route.h sig.c sig.h cfg_y.y cfg_l.l fab.h
++libsw_a_SOURCES = control.c dispatch.c dispatch.h proto.c proto.h relay.c route.c route.h sig.c sig.h cfg_y.y cfg_l.l fab.h
+
+
+ EXTRA_DIST = cfg_y.h README
+@@ -132,8 +130,11 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
++DEP_FILES = .deps/cfg_l.P .deps/cfg_y.P .deps/control.P \
++.deps/dispatch.P .deps/proto.P .deps/relay.P .deps/route.P .deps/sig.P \
++.deps/swc.P
+ SOURCES = $(libsw_a_SOURCES) $(swc_SOURCES)
+ OBJECTS = $(libsw_a_OBJECTS) $(swc_OBJECTS)
+
+@@ -141,9 +142,9 @@
+ .SUFFIXES:
+ .SUFFIXES: .S .c .l .lo .o .obj .s .y
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/switch/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/switch/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -157,9 +158,6 @@
+
+ maintainer-clean-noinstLIBRARIES:
+
+-.c.o:
+- $(COMPILE) -c $<
+-
+ # FIXME: We should only use cygpath when building on Windows,
+ # and only if it is available.
+ .c.obj:
+@@ -182,9 +180,6 @@
+
+ maintainer-clean-compile:
+
+-.c.lo:
+- $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+-
+ .s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+@@ -306,7 +301,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -322,6 +317,11 @@
+ subdir = src/switch
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/switch/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+@@ -342,32 +342,38 @@
+ || exit 1; \
+ fi; \
+ done
+-cfg_l.o: cfg_l.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h cfg_y.h
+-cfg_y.o: cfg_y.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h fab.h proto.h \
+- ../../src/include/atmsap.h ../../src/include/atmd.h sig.h \
+- route.h swc.h
+-control.o: control.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h fab.h \
+- proto.h ../../src/include/atmsap.h sig.h dispatch.h swc.h
+-dispatch.o: dispatch.c ../../config.h ../../src/include/atmd.h \
+- ../../src/include/stdint.h ../../src/include/atm.h dispatch.h
+-proto.o: proto.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h sig.h fab.h \
+- proto.h ../../src/include/atmsap.h
+-relay.o: relay.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h fab.h \
+- proto.h ../../src/include/atmsap.h sig.h dispatch.h route.h
+-route.o: route.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h route.h \
+- sig.h
+-sig.o: sig.c ../../config.h ../../src/include/stdint.h \
+- ../../src/include/atmd.h ../../src/include/atm.h dispatch.h \
+- proto.h ../../src/include/atmsap.h sig.h route.h fab.h
+-swc.o: swc.c ../../config.h ../../src/include/atm.h \
+- ../../src/include/stdint.h ../../src/include/atmd.h swc.h
+
++DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
++
++-include $(DEP_FILES)
++
++mostlyclean-depend:
++
++clean-depend:
++
++distclean-depend:
++ -rm -rf .deps
++
++maintainer-clean-depend:
++
++%.o: %.c
++ @echo '$(COMPILE) -c $<'; \
++ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-cp .deps/$(*F).pp .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm .deps/$(*F).pp
++
++%.lo: %.c
++ @echo '$(LTCOMPILE) -c $<'; \
++ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
++ < .deps/$(*F).pp > .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm -f .deps/$(*F).pp
+ info-am:
+ info: info-recursive
+ dvi-am:
+@@ -404,22 +410,23 @@
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+ maintainer-clean-generic:
+- -test -z "cfg_llcfg_yhcfg_yc" || rm -f cfg_ll cfg_yh cfg_yc
++ -test -z "cfg_lccfg_yhcfg_yc" || rm -f cfg_lc cfg_yh cfg_yc
+ mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+ mostlyclean-libtool mostlyclean-noinstPROGRAMS \
+- mostlyclean-tags mostlyclean-generic
++ mostlyclean-tags mostlyclean-depend mostlyclean-generic
+
+ mostlyclean: mostlyclean-recursive
+
+ clean-am: clean-noinstLIBRARIES clean-compile clean-libtool \
+- clean-noinstPROGRAMS clean-tags clean-generic \
+- mostlyclean-am
++ clean-noinstPROGRAMS clean-tags clean-depend \
++ clean-generic mostlyclean-am
+
+ clean: clean-recursive
+
+ distclean-am: distclean-noinstLIBRARIES distclean-compile \
+ distclean-libtool distclean-noinstPROGRAMS \
+- distclean-tags distclean-generic clean-am
++ distclean-tags distclean-depend distclean-generic \
++ clean-am
+ -rm -f libtool
+
+ distclean: distclean-recursive
+@@ -427,7 +434,8 @@
+ maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
+ maintainer-clean-compile maintainer-clean-libtool \
+ maintainer-clean-noinstPROGRAMS maintainer-clean-tags \
+- maintainer-clean-generic distclean-am
++ maintainer-clean-depend 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."
+
+@@ -445,12 +453,14 @@
+ all-recursive check-recursive installcheck-recursive info-recursive \
+ dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
+ maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
+-distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+-dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
+-install-exec install-data-am install-data install-am install \
+-uninstall-am uninstall all-redirect all-am all installdirs-am \
+-installdirs mostlyclean-generic distclean-generic clean-generic \
+-maintainer-clean-generic clean mostlyclean distclean maintainer-clean
++distclean-tags clean-tags maintainer-clean-tags distdir \
++mostlyclean-depend distclean-depend clean-depend \
++maintainer-clean-depend info-am info dvi-am dvi check check-am \
++installcheck-am installcheck install-exec-am install-exec \
++install-data-am install-data install-am install uninstall-am uninstall \
++all-redirect all-am all installdirs-am 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.
+--- linux-atm-2.4.1.orig/src/switch/cfg_y.c
++++ linux-atm-2.4.1/src/switch/cfg_y.c
+@@ -1,21 +1,87 @@
++/* A Bison parser, made by GNU Bison 1.875d. */
+
+-/* A Bison parser, made from cfg_y.y
+- by GNU Bison version 1.28 */
++/* Skeleton parser for Yacc-like parsing with Bison,
++ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+-#define YYBISON 1 /* Identify Bison output. */
++ 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. */
++
++/* As a special exception, when this file is copied by Bison into a
++ Bison output file, you may use that output file without restriction.
++ This special exception was added by the Free Software Foundation
++ in version 1.24 of Bison. */
++
++/* Written by Richard Stallman by simplifying the original so called
++ ``semantic'' parser. */
++
++/* All symbols defined below should begin with yy or YY, to avoid
++ infringing on user name space. This should be done even for local
++ variables, as they might otherwise be expanded by user macros.
++ There are some unavoidable exceptions within include files to
++ define necessary library symbols; they are noted "INFRINGES ON
++ USER NAME SPACE" below. */
++
++/* Identify Bison output. */
++#define YYBISON 1
++
++/* Skeleton name. */
++#define YYSKELETON_NAME "yacc.c"
++
++/* Pure parsers. */
++#define YYPURE 0
++
++/* Using locations. */
++#define YYLSP_NEEDED 0
+
+-#define TOK_COMMAND 257
+-#define TOK_VPCI 258
+-#define TOK_ITF 259
+-#define TOK_DEFAULT 260
+-#define TOK_ROUTE 261
+-#define TOK_STR 262
+-#define TOK_SOCKET 263
+-#define TOK_OPTION 264
+-#define TOK_CONTROL 265
+-#define TOK_NUM 266
+-#define TOK_PVC 267
+
++
++/* Tokens. */
++#ifndef YYTOKENTYPE
++# define YYTOKENTYPE
++ /* Put the tokens into the symbol table, so that GDB and other debuggers
++ know about them. */
++ enum yytokentype {
++ TOK_COMMAND = 258,
++ TOK_VPCI = 259,
++ TOK_ITF = 260,
++ TOK_DEFAULT = 261,
++ TOK_ROUTE = 262,
++ TOK_STR = 263,
++ TOK_SOCKET = 264,
++ TOK_OPTION = 265,
++ TOK_CONTROL = 266,
++ TOK_NUM = 267,
++ TOK_PVC = 268
++ };
++#endif
++#define TOK_COMMAND 258
++#define TOK_VPCI 259
++#define TOK_ITF 260
++#define TOK_DEFAULT 261
++#define TOK_ROUTE 262
++#define TOK_STR 263
++#define TOK_SOCKET 264
++#define TOK_OPTION 265
++#define TOK_CONTROL 266
++#define TOK_NUM 267
++#define TOK_PVC 268
++
++
++
++
++/* Copy the first part of user declarations. */
+ #line 1 "cfg_y.y"
+
+ /* cfg.y - switch configuration language */
+@@ -29,6 +95,7 @@
+ #include <string.h>
+ #include <errno.h>
+ #include <limits.h>
++#include <stdlib.h>
+
+ #include "atm.h"
+
+@@ -38,436 +105,743 @@
+ #include "swc.h"
+
+
++extern void yyerror(const char *s);
++
+ static int itf;
+ static SIGNALING_ENTITY *sig;
+
+
+-#line 27 "cfg_y.y"
+-typedef union {
++
++/* Enabling traces. */
++#ifndef YYDEBUG
++# define YYDEBUG 0
++#endif
++
++/* Enabling verbose error messages. */
++#ifdef YYERROR_VERBOSE
++# undef YYERROR_VERBOSE
++# define YYERROR_VERBOSE 1
++#else
++# define YYERROR_VERBOSE 0
++#endif
++
++#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
++#line 30 "cfg_y.y"
++typedef union YYSTYPE {
+ int num;
+ char *str;
+ struct sockaddr_atmpvc pvc;
+ } YYSTYPE;
+-#include <stdio.h>
+-
+-#ifndef __cplusplus
+-#ifndef __STDC__
+-#define const
+-#endif
++/* Line 191 of yacc.c. */
++#line 137 "y.tab.c"
++# define yystype YYSTYPE /* obsolescent; will be withdrawn */
++# define YYSTYPE_IS_DECLARED 1
++# define YYSTYPE_IS_TRIVIAL 1
+ #endif
+
+
+
+-#define YYFINAL 31
+-#define YYFLAG -32768
+-#define YYNTBASE 16
+-
+-#define YYTRANSLATE(x) ((unsigned)(x) <= 267 ? yytranslate[x] : 27)
+-
+-static const char yytranslate[] = { 0,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 14, 2, 15, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
+- 7, 8, 9, 10, 11, 12, 13
+-};
+-
+-#if YYDEBUG != 0
+-static const short yyprhs[] = { 0,
+- 0, 1, 4, 7, 10, 13, 14, 15, 25, 26,
+- 29, 30, 33, 34, 36, 37, 40, 41, 45
+-};
++/* Copy the second part of user declarations. */
++
++
++/* Line 214 of yacc.c. */
++#line 149 "y.tab.c"
++
++#if ! defined (yyoverflow) || YYERROR_VERBOSE
++
++# ifndef YYFREE
++# define YYFREE free
++# endif
++# ifndef YYMALLOC
++# define YYMALLOC malloc
++# endif
++
++/* The parser invokes alloca or malloc; define the necessary symbols. */
++
++# ifdef YYSTACK_USE_ALLOCA
++# if YYSTACK_USE_ALLOCA
++# define YYSTACK_ALLOC alloca
++# endif
++# else
++# if defined (alloca) || defined (_ALLOCA_H)
++# define YYSTACK_ALLOC alloca
++# else
++# ifdef __GNUC__
++# define YYSTACK_ALLOC __builtin_alloca
++# endif
++# endif
++# endif
++
++# ifdef YYSTACK_ALLOC
++ /* Pacify GCC's `empty if-body' warning. */
++# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
++# else
++# if defined (__STDC__) || defined (__cplusplus)
++# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
++# define YYSIZE_T size_t
++# endif
++# define YYSTACK_ALLOC YYMALLOC
++# define YYSTACK_FREE YYFREE
++# endif
++#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
++
++
++#if (! defined (yyoverflow) \
++ && (! defined (__cplusplus) \
++ || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
+
+-static const short yyrhs[] = { -1,
+- 17, 16, 0, 18, 16, 0, 11, 16, 0, 10,
+- 8, 0, 0, 0, 21, 9, 14, 19, 22, 20,
+- 23, 24, 15, 0, 0, 3, 8, 0, 0, 5,
+- 12, 0, 0, 13, 0, 0, 26, 24, 0, 0,
+- 6, 25, 24, 0, 7, 0
+-};
++/* A type that is properly aligned for any stack member. */
++union yyalloc
++{
++ short int yyss;
++ YYSTYPE yyvs;
++ };
++
++/* The size of the maximum gap between one aligned stack and the next. */
++# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
++
++/* The size of an array large to enough to hold all stacks, each with
++ N elements. */
++# define YYSTACK_BYTES(N) \
++ ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \
++ + YYSTACK_GAP_MAXIMUM)
++
++/* Copy COUNT objects from FROM to TO. The source and destination do
++ not overlap. */
++# ifndef YYCOPY
++# if defined (__GNUC__) && 1 < __GNUC__
++# define YYCOPY(To, From, Count) \
++ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
++# else
++# define YYCOPY(To, From, Count) \
++ do \
++ { \
++ register YYSIZE_T yyi; \
++ for (yyi = 0; yyi < (Count); yyi++) \
++ (To)[yyi] = (From)[yyi]; \
++ } \
++ while (0)
++# endif
++# endif
++
++/* Relocate STACK from its old location to the new one. The
++ local variables YYSIZE and YYSTACKSIZE give the old and new number of
++ elements in the stack, and YYPTR gives the new location of the
++ stack. Advance YYPTR to a properly aligned location for the next
++ stack. */
++# define YYSTACK_RELOCATE(Stack) \
++ do \
++ { \
++ YYSIZE_T yynewbytes; \
++ YYCOPY (&yyptr->Stack, Stack, yysize); \
++ Stack = &yyptr->Stack; \
++ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
++ yyptr += yynewbytes / sizeof (*yyptr); \
++ } \
++ while (0)
+
+ #endif
+
+-#if YYDEBUG != 0
+-static const short yyrline[] = { 0,
+- 43, 44, 45, 46, 52, 59, 65, 73, 76, 80,
+- 87, 88, 94, 95, 101, 102, 103, 108, 110
+-};
++#if defined (__STDC__) || defined (__cplusplus)
++ typedef signed char yysigned_char;
++#else
++ typedef short int yysigned_char;
+ #endif
+
++/* YYFINAL -- State number of the termination state. */
++#define YYFINAL 11
++/* YYLAST -- Last index in YYTABLE. */
++#define YYLAST 22
++
++/* YYNTOKENS -- Number of terminals. */
++#define YYNTOKENS 16
++/* YYNNTS -- Number of nonterminals. */
++#define YYNNTS 12
++/* YYNRULES -- Number of rules. */
++#define YYNRULES 20
++/* YYNRULES -- Number of states. */
++#define YYNSTATES 31
++
++/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
++#define YYUNDEFTOK 2
++#define YYMAXUTOK 268
+
+-#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
++#define YYTRANSLATE(YYX) \
++ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+-static const char * const yytname[] = { "$","error","$undefined.","TOK_COMMAND",
+-"TOK_VPCI","TOK_ITF","TOK_DEFAULT","TOK_ROUTE","TOK_STR","TOK_SOCKET","TOK_OPTION",
+-"TOK_CONTROL","TOK_NUM","TOK_PVC","'{'","'}'","all","option","sig","@1","@2",
+-"opt_command","opt_itf","opt_via","routes","@3","route", NULL
++/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
++static const unsigned char yytranslate[] =
++{
++ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 14, 2, 15, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
++ 5, 6, 7, 8, 9, 10, 11, 12, 13
+ };
+-#endif
+
+-static const short yyr1[] = { 0,
+- 16, 16, 16, 16, 17, 19, 20, 18, 21, 21,
+- 22, 22, 23, 23, 24, 24, 25, 24, 26
++#if YYDEBUG
++/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
++ YYRHS. */
++static const unsigned char yyprhs[] =
++{
++ 0, 0, 3, 4, 7, 10, 13, 16, 17, 18,
++ 28, 29, 32, 33, 36, 37, 39, 40, 43, 44,
++ 48
+ };
+
+-static const short yyr2[] = { 0,
+- 0, 2, 2, 2, 2, 0, 0, 9, 0, 2,
+- 0, 2, 0, 1, 0, 2, 0, 3, 1
++/* YYRHS -- A `-1'-separated list of the rules' RHS. */
++static const yysigned_char yyrhs[] =
++{
++ 17, 0, -1, -1, 18, 17, -1, 19, 17, -1,
++ 11, 17, -1, 10, 8, -1, -1, -1, 22, 9,
++ 14, 20, 23, 21, 24, 25, 15, -1, -1, 3,
++ 8, -1, -1, 5, 12, -1, -1, 13, -1, -1,
++ 27, 25, -1, -1, 6, 26, 25, -1, 7, -1
+ };
+
+-static const short yydefact[] = { 1,
+- 0, 0, 1, 1, 1, 0, 10, 5, 4, 2,
+- 3, 0, 6, 11, 0, 7, 12, 13, 14, 15,
+- 17, 19, 0, 15, 15, 8, 16, 18, 0, 0,
+- 0
++/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
++static const unsigned char yyrline[] =
++{
++ 0, 46, 46, 47, 48, 49, 56, 64, 68, 63,
++ 80, 83, 90, 91, 97, 98, 104, 105, 107, 106,
++ 114
+ };
++#endif
+
+-static const short yydefgoto[] = { 9,
+- 4, 5, 14, 18, 6, 16, 20, 23, 25, 24
++#if YYDEBUG || YYERROR_VERBOSE
++/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
++ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
++static const char *const yytname[] =
++{
++ "$end", "error", "$undefined", "TOK_COMMAND", "TOK_VPCI", "TOK_ITF",
++ "TOK_DEFAULT", "TOK_ROUTE", "TOK_STR", "TOK_SOCKET", "TOK_OPTION",
++ "TOK_CONTROL", "TOK_NUM", "TOK_PVC", "'{'", "'}'", "$accept", "all",
++ "option", "sig", "@1", "@2", "opt_command", "opt_itf", "opt_via",
++ "routes", "@3", "route", 0
+ };
++#endif
+
+-static const short yypact[] = { -3,
+- 3, 4, -3, -3, -3, 6,-32768,-32768,-32768,-32768,
+--32768, -1,-32768, 9, 7,-32768,-32768, 8,-32768, -5,
+--32768,-32768, 1, -5, -5,-32768,-32768,-32768, 17, 18,
+--32768
++# ifdef YYPRINT
++/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
++ token YYLEX-NUM. */
++static const unsigned short int yytoknum[] =
++{
++ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
++ 265, 266, 267, 268, 123, 125
+ };
++# endif
+
+-static const short yypgoto[] = { 5,
+--32768,-32768,-32768,-32768,-32768,-32768,-32768, -21,-32768,-32768
++/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
++static const unsigned char yyr1[] =
++{
++ 0, 16, 17, 17, 17, 17, 18, 20, 21, 19,
++ 22, 22, 23, 23, 24, 24, 25, 25, 26, 25,
++ 27
+ };
+
+-
+-#define YYLAST 21
+-
+-
+-static const short yytable[] = { 1,
+- 21, 22, 27, 28, 29, -9, 2, 3, 10, 11,
+- 7, 8, 13, 15, 12, 26, 30, 31, 17, 0,
+- 19
++/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
++static const unsigned char yyr2[] =
++{
++ 0, 2, 0, 2, 2, 2, 2, 0, 0, 9,
++ 0, 2, 0, 2, 0, 1, 0, 2, 0, 3,
++ 1
+ };
+
+-static const short yycheck[] = { 3,
+- 6, 7, 24, 25, 0, 9, 10, 11, 4, 5,
+- 8, 8, 14, 5, 9, 15, 0, 0, 12, -1,
+- 13
++/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
++ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
++ means the default is an error. */
++static const unsigned char yydefact[] =
++{
++ 2, 0, 0, 2, 0, 2, 2, 0, 11, 6,
++ 5, 1, 3, 4, 0, 7, 12, 0, 8, 13,
++ 14, 15, 16, 18, 20, 0, 16, 16, 9, 17,
++ 19
+ };
+-/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
+-#line 3 "/usr/lib/bison.simple"
+-/* This file comes from bison-1.28. */
+
+-/* Skeleton output parser for bison,
+- Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
++/* YYDEFGOTO[NTERM-NUM]. */
++static const yysigned_char yydefgoto[] =
++{
++ -1, 4, 5, 6, 16, 20, 7, 18, 22, 25,
++ 27, 26
++};
+
+- 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.
++/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
++ STATE-NUM. */
++#define YYPACT_NINF -16
++static const yysigned_char yypact[] =
++{
++ -3, -6, 5, -3, 14, -3, -3, -4, -16, -16,
++ -16, -16, -16, -16, 1, -16, 11, 6, -16, -16,
++ 4, -16, 3, -16, -16, 7, 3, 3, -16, -16,
++ -16
++};
+
+- 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.
++/* YYPGOTO[NTERM-NUM]. */
++static const yysigned_char yypgoto[] =
++{
++ -16, -2, -16, -16, -16, -16, -16, -16, -16, -15,
++ -16, -16
++};
+
+- 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. */
++/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
++ positive, shift that token. If negative, reduce the rule which
++ number is the opposite. If zero, do what YYDEFACT says.
++ If YYTABLE_NINF, syntax error. */
++#define YYTABLE_NINF -11
++static const yysigned_char yytable[] =
++{
++ 1, 10, 8, 12, 13, 14, -10, 2, 3, 23,
++ 24, 29, 30, 9, 11, 15, 17, 21, 19, 0,
++ 0, 0, 28
++};
+
+-/* As a special exception, when this file is copied by Bison into a
+- Bison output file, you may use that output file without restriction.
+- This special exception was added by the Free Software Foundation
+- in version 1.24 of Bison. */
++static const yysigned_char yycheck[] =
++{
++ 3, 3, 8, 5, 6, 9, 9, 10, 11, 6,
++ 7, 26, 27, 8, 0, 14, 5, 13, 12, -1,
++ -1, -1, 15
++};
+
+-/* This is the parser code that is written into each bison parser
+- when the %semantic_parser declaration is not specified in the grammar.
+- It was written by Richard Stallman by simplifying the hairy parser
+- used when %semantic_parser is specified. */
+-
+-#ifndef YYSTACK_USE_ALLOCA
+-#ifdef alloca
+-#define YYSTACK_USE_ALLOCA
+-#else /* alloca not defined */
+-#ifdef __GNUC__
+-#define YYSTACK_USE_ALLOCA
+-#define alloca __builtin_alloca
+-#else /* not GNU C. */
+-#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
+-#define YYSTACK_USE_ALLOCA
+-#include <alloca.h>
+-#else /* not sparc */
+-/* We think this test detects Watcom and Microsoft C. */
+-/* This used to test MSDOS, but that is a bad idea
+- since that symbol is in the user namespace. */
+-#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
+-#if 0 /* No need for malloc.h, which pollutes the namespace;
+- instead, just don't use alloca. */
+-#include <malloc.h>
+-#endif
+-#else /* not MSDOS, or __TURBOC__ */
+-#if defined(_AIX)
+-/* I don't know what this was needed for, but it pollutes the namespace.
+- So I turned it off. rms, 2 May 1997. */
+-/* #include <malloc.h> */
+- #pragma alloca
+-#define YYSTACK_USE_ALLOCA
+-#else /* not MSDOS, or __TURBOC__, or _AIX */
+-#if 0
+-#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
+- and on HPUX 10. Eventually we can turn this on. */
+-#define YYSTACK_USE_ALLOCA
+-#define alloca __builtin_alloca
+-#endif /* __hpux */
+-#endif
+-#endif /* not _AIX */
+-#endif /* not MSDOS, or __TURBOC__ */
+-#endif /* not sparc */
+-#endif /* not GNU C */
+-#endif /* alloca not defined */
+-#endif /* YYSTACK_USE_ALLOCA not defined */
++/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
++ symbol of state STATE-NUM. */
++static const unsigned char yystos[] =
++{
++ 0, 3, 10, 11, 17, 18, 19, 22, 8, 8,
++ 17, 0, 17, 17, 9, 14, 20, 5, 23, 12,
++ 21, 13, 24, 6, 7, 25, 27, 26, 15, 25,
++ 25
++};
+
+-#ifdef YYSTACK_USE_ALLOCA
+-#define YYSTACK_ALLOC alloca
+-#else
+-#define YYSTACK_ALLOC malloc
++#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
++# define YYSIZE_T __SIZE_TYPE__
++#endif
++#if ! defined (YYSIZE_T) && defined (size_t)
++# define YYSIZE_T size_t
++#endif
++#if ! defined (YYSIZE_T)
++# if defined (__STDC__) || defined (__cplusplus)
++# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
++# define YYSIZE_T size_t
++# endif
++#endif
++#if ! defined (YYSIZE_T)
++# define YYSIZE_T unsigned int
+ #endif
+-
+-/* Note: there must be only one dollar sign in this file.
+- It is replaced by the list of actions, each action
+- as one case of the switch. */
+
+ #define yyerrok (yyerrstatus = 0)
+ #define yyclearin (yychar = YYEMPTY)
+-#define YYEMPTY -2
++#define YYEMPTY (-2)
+ #define YYEOF 0
++
+ #define YYACCEPT goto yyacceptlab
+-#define YYABORT goto yyabortlab
+-#define YYERROR goto yyerrlab1
+-/* Like YYERROR except do call yyerror.
+- This remains here temporarily to ease the
+- transition to the new meaning of YYERROR, for GCC.
++#define YYABORT goto yyabortlab
++#define YYERROR goto yyerrorlab
++
++
++/* Like YYERROR except do call yyerror. This remains here temporarily
++ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
++
+ #define YYFAIL goto yyerrlab
++
+ #define YYRECOVERING() (!!yyerrstatus)
+-#define YYBACKUP(token, value) \
++
++#define YYBACKUP(Token, Value) \
+ do \
+ if (yychar == YYEMPTY && yylen == 1) \
+- { yychar = (token), yylval = (value); \
+- yychar1 = YYTRANSLATE (yychar); \
++ { \
++ yychar = (Token); \
++ yylval = (Value); \
++ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+- { yyerror ("syntax error: cannot back up"); YYERROR; } \
++ { \
++ yyerror ("syntax error: cannot back up");\
++ YYERROR; \
++ } \
+ while (0)
+
+ #define YYTERROR 1
+ #define YYERRCODE 256
+
+-#ifndef YYPURE
+-#define YYLEX yylex()
+-#endif
++/* YYLLOC_DEFAULT -- Compute the default location (before the actions
++ are run). */
+
+-#ifdef YYPURE
+-#ifdef YYLSP_NEEDED
+-#ifdef YYLEX_PARAM
+-#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
+-#else
+-#define YYLEX yylex(&yylval, &yylloc)
++#ifndef YYLLOC_DEFAULT
++# define YYLLOC_DEFAULT(Current, Rhs, N) \
++ ((Current).first_line = (Rhs)[1].first_line, \
++ (Current).first_column = (Rhs)[1].first_column, \
++ (Current).last_line = (Rhs)[N].last_line, \
++ (Current).last_column = (Rhs)[N].last_column)
+ #endif
+-#else /* not YYLSP_NEEDED */
++
++/* YYLEX -- calling `yylex' with the right arguments. */
++
+ #ifdef YYLEX_PARAM
+-#define YYLEX yylex(&yylval, YYLEX_PARAM)
++# define YYLEX yylex (YYLEX_PARAM)
+ #else
+-#define YYLEX yylex(&yylval)
+-#endif
+-#endif /* not YYLSP_NEEDED */
++# define YYLEX yylex ()
+ #endif
+
+-/* If nonreentrant, generate the variables here */
++/* Enable debugging if requested. */
++#if YYDEBUG
+
+-#ifndef YYPURE
++# ifndef YYFPRINTF
++# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
++# define YYFPRINTF fprintf
++# endif
++
++# define YYDPRINTF(Args) \
++do { \
++ if (yydebug) \
++ YYFPRINTF Args; \
++} while (0)
++
++# define YYDSYMPRINT(Args) \
++do { \
++ if (yydebug) \
++ yysymprint Args; \
++} while (0)
++
++# define YYDSYMPRINTF(Title, Token, Value, Location) \
++do { \
++ if (yydebug) \
++ { \
++ YYFPRINTF (stderr, "%s ", Title); \
++ yysymprint (stderr, \
++ Token, Value); \
++ YYFPRINTF (stderr, "\n"); \
++ } \
++} while (0)
+
+-int yychar; /* the lookahead symbol */
+-YYSTYPE yylval; /* the semantic value of the */
+- /* lookahead symbol */
++/*------------------------------------------------------------------.
++| yy_stack_print -- Print the state stack from its BOTTOM up to its |
++| TOP (included). |
++`------------------------------------------------------------------*/
+
+-#ifdef YYLSP_NEEDED
+-YYLTYPE yylloc; /* location data for the lookahead */
+- /* symbol */
++#if defined (__STDC__) || defined (__cplusplus)
++static void
++yy_stack_print (short int *bottom, short int *top)
++#else
++static void
++yy_stack_print (bottom, top)
++ short int *bottom;
++ short int *top;
+ #endif
++{
++ YYFPRINTF (stderr, "Stack now");
++ for (/* Nothing. */; bottom <= top; ++bottom)
++ YYFPRINTF (stderr, " %d", *bottom);
++ YYFPRINTF (stderr, "\n");
++}
+
+-int yynerrs; /* number of parse errors so far */
+-#endif /* not YYPURE */
++# define YY_STACK_PRINT(Bottom, Top) \
++do { \
++ if (yydebug) \
++ yy_stack_print ((Bottom), (Top)); \
++} while (0)
+
+-#if YYDEBUG != 0
+-int yydebug; /* nonzero means print parse trace */
+-/* Since this is uninitialized, it does not stop multiple parsers
+- from coexisting. */
++
++/*------------------------------------------------.
++| Report that the YYRULE is going to be reduced. |
++`------------------------------------------------*/
++
++#if defined (__STDC__) || defined (__cplusplus)
++static void
++yy_reduce_print (int yyrule)
++#else
++static void
++yy_reduce_print (yyrule)
++ int yyrule;
+ #endif
++{
++ int yyi;
++ unsigned int yylno = yyrline[yyrule];
++ YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
++ yyrule - 1, yylno);
++ /* Print the symbols being reduced, and their result. */
++ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
++ YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
++ YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
++}
++
++# define YY_REDUCE_PRINT(Rule) \
++do { \
++ if (yydebug) \
++ yy_reduce_print (Rule); \
++} while (0)
++
++/* Nonzero means print parse trace. It is left uninitialized so that
++ multiple parsers can coexist. */
++int yydebug;
++#else /* !YYDEBUG */
++# define YYDPRINTF(Args)
++# define YYDSYMPRINT(Args)
++# define YYDSYMPRINTF(Title, Token, Value, Location)
++# define YY_STACK_PRINT(Bottom, Top)
++# define YY_REDUCE_PRINT(Rule)
++#endif /* !YYDEBUG */
+
+-/* YYINITDEPTH indicates the initial size of the parser's stacks */
+
++/* YYINITDEPTH -- initial size of the parser's stacks. */
+ #ifndef YYINITDEPTH
+-#define YYINITDEPTH 200
++# define YYINITDEPTH 200
+ #endif
+
+-/* YYMAXDEPTH is the maximum size the stacks can grow to
+- (effective only if the built-in stack extension method is used). */
++/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
++ if the built-in stack extension method is used).
+
+-#if YYMAXDEPTH == 0
+-#undef YYMAXDEPTH
++ Do not make this value too large; the results are undefined if
++ SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
++ evaluated with infinite-precision integer arithmetic. */
++
++#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
++# undef YYMAXDEPTH
+ #endif
+
+ #ifndef YYMAXDEPTH
+-#define YYMAXDEPTH 10000
++# define YYMAXDEPTH 10000
+ #endif
++
+
+-/* Define __yy_memcpy. Note that the size argument
+- should be passed with type unsigned int, because that is what the non-GCC
+- definitions require. With GCC, __builtin_memcpy takes an arg
+- of type size_t, but it can handle unsigned int. */
+-
+-#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
+-#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
+-#else /* not GNU C or C++ */
+-#ifndef __cplusplus
+
+-/* This is the most reliable way to avoid incompatibilities
+- in available built-in functions on various systems. */
+-static void
+-__yy_memcpy (to, from, count)
+- char *to;
+- char *from;
+- unsigned int count;
+-{
+- register char *f = from;
+- register char *t = to;
+- register int i = count;
++#if YYERROR_VERBOSE
++
++# ifndef yystrlen
++# if defined (__GLIBC__) && defined (_STRING_H)
++# define yystrlen strlen
++# else
++/* Return the length of YYSTR. */
++static YYSIZE_T
++# if defined (__STDC__) || defined (__cplusplus)
++yystrlen (const char *yystr)
++# else
++yystrlen (yystr)
++ const char *yystr;
++# endif
++{
++ register const char *yys = yystr;
++
++ while (*yys++ != '\0')
++ continue;
++
++ return yys - yystr - 1;
++}
++# endif
++# endif
++
++# ifndef yystpcpy
++# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
++# define yystpcpy stpcpy
++# else
++/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
++ YYDEST. */
++static char *
++# if defined (__STDC__) || defined (__cplusplus)
++yystpcpy (char *yydest, const char *yysrc)
++# else
++yystpcpy (yydest, yysrc)
++ char *yydest;
++ const char *yysrc;
++# endif
++{
++ register char *yyd = yydest;
++ register const char *yys = yysrc;
+
+- while (i-- > 0)
+- *t++ = *f++;
++ while ((*yyd++ = *yys++) != '\0')
++ continue;
++
++ return yyd - 1;
+ }
++# endif
++# endif
++
++#endif /* !YYERROR_VERBOSE */
+
+-#else /* __cplusplus */
++
++
++#if YYDEBUG
++/*--------------------------------.
++| Print this symbol on YYOUTPUT. |
++`--------------------------------*/
+
+-/* This is the most reliable way to avoid incompatibilities
+- in available built-in functions on various systems. */
++#if defined (__STDC__) || defined (__cplusplus)
+ static void
+-__yy_memcpy (char *to, char *from, unsigned int count)
++yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
++#else
++static void
++yysymprint (yyoutput, yytype, yyvaluep)
++ FILE *yyoutput;
++ int yytype;
++ YYSTYPE *yyvaluep;
++#endif
+ {
+- register char *t = to;
+- register char *f = from;
+- register int i = count;
++ /* Pacify ``unused variable'' warnings. */
++ (void) yyvaluep;
+
+- while (i-- > 0)
+- *t++ = *f++;
++ if (yytype < YYNTOKENS)
++ {
++ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
++# ifdef YYPRINT
++ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
++# endif
++ }
++ else
++ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
++
++ switch (yytype)
++ {
++ default:
++ break;
++ }
++ YYFPRINTF (yyoutput, ")");
+ }
+
++#endif /* ! YYDEBUG */
++/*-----------------------------------------------.
++| Release the memory associated to this symbol. |
++`-----------------------------------------------*/
++
++#if defined (__STDC__) || defined (__cplusplus)
++static void
++yydestruct (int yytype, YYSTYPE *yyvaluep)
++#else
++static void
++yydestruct (yytype, yyvaluep)
++ int yytype;
++ YYSTYPE *yyvaluep;
+ #endif
+-#endif
++{
++ /* Pacify ``unused variable'' warnings. */
++ (void) yyvaluep;
++
++ switch (yytype)
++ {
++
++ default:
++ break;
++ }
++}
+
+-#line 217 "/usr/lib/bison.simple"
+
+-/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+- into yyparse. The argument should have type void *.
+- It should actually point to an object.
+- Grammar actions can access the variable by casting it
+- to the proper pointer type. */
++/* Prevent warnings from -Wmissing-prototypes. */
+
+ #ifdef YYPARSE_PARAM
+-#ifdef __cplusplus
+-#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+-#define YYPARSE_PARAM_DECL
+-#else /* not __cplusplus */
+-#define YYPARSE_PARAM_ARG YYPARSE_PARAM
+-#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+-#endif /* not __cplusplus */
+-#else /* not YYPARSE_PARAM */
+-#define YYPARSE_PARAM_ARG
+-#define YYPARSE_PARAM_DECL
+-#endif /* not YYPARSE_PARAM */
++# if defined (__STDC__) || defined (__cplusplus)
++int yyparse (void *YYPARSE_PARAM);
++# else
++int yyparse ();
++# endif
++#else /* ! YYPARSE_PARAM */
++#if defined (__STDC__) || defined (__cplusplus)
++int yyparse (void);
++#else
++int yyparse ();
++#endif
++#endif /* ! YYPARSE_PARAM */
++
++
++
++/* The lookahead symbol. */
++int yychar;
++
++/* The semantic value of the lookahead symbol. */
++YYSTYPE yylval;
++
++/* Number of syntax errors so far. */
++int yynerrs;
++
++
++
++/*----------.
++| yyparse. |
++`----------*/
+
+-/* Prevent warning if -Wstrict-prototypes. */
+-#ifdef __GNUC__
+ #ifdef YYPARSE_PARAM
+-int yyparse (void *);
++# if defined (__STDC__) || defined (__cplusplus)
++int yyparse (void *YYPARSE_PARAM)
++# else
++int yyparse (YYPARSE_PARAM)
++ void *YYPARSE_PARAM;
++# endif
++#else /* ! YYPARSE_PARAM */
++#if defined (__STDC__) || defined (__cplusplus)
++int
++yyparse (void)
+ #else
+-int yyparse (void);
++int
++yyparse ()
++
+ #endif
+ #endif
+-
+-int
+-yyparse(YYPARSE_PARAM_ARG)
+- YYPARSE_PARAM_DECL
+ {
++
+ register int yystate;
+ register int yyn;
+- register short *yyssp;
++ int yyresult;
++ /* Number of tokens to shift before error messages enabled. */
++ int yyerrstatus;
++ /* Lookahead token as an internal (translated) token number. */
++ int yytoken = 0;
++
++ /* Three stacks and their tools:
++ `yyss': related to states,
++ `yyvs': related to semantic values,
++ `yyls': related to locations.
++
++ Refer to the stacks thru separate pointers, to allow yyoverflow
++ to reallocate them elsewhere. */
++
++ /* The state stack. */
++ short int yyssa[YYINITDEPTH];
++ short int *yyss = yyssa;
++ register short int *yyssp;
++
++ /* The semantic value stack. */
++ YYSTYPE yyvsa[YYINITDEPTH];
++ YYSTYPE *yyvs = yyvsa;
+ register YYSTYPE *yyvsp;
+- int yyerrstatus; /* number of tokens to shift before error messages enabled */
+- int yychar1 = 0; /* lookahead token as an internal (translated) token number */
+-
+- short yyssa[YYINITDEPTH]; /* the state stack */
+- YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
+
+- short *yyss = yyssa; /* refer to the stacks thru separate pointers */
+- YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
+
+-#ifdef YYLSP_NEEDED
+- YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
+- YYLTYPE *yyls = yylsa;
+- YYLTYPE *yylsp;
+
+-#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
+-#else
+ #define YYPOPSTACK (yyvsp--, yyssp--)
+-#endif
+
+- int yystacksize = YYINITDEPTH;
+- int yyfree_stacks = 0;
++ YYSIZE_T yystacksize = YYINITDEPTH;
+
+-#ifdef YYPURE
+- int yychar;
+- YYSTYPE yylval;
+- int yynerrs;
+-#ifdef YYLSP_NEEDED
+- YYLTYPE yylloc;
+-#endif
+-#endif
++ /* The variables used to return semantic value and location from the
++ action routines. */
++ YYSTYPE yyval;
+
+- YYSTYPE yyval; /* the variable used to return */
+- /* semantic values from the action */
+- /* routines */
+
++ /* When reducing, the number of symbols on the RHS of the reduced
++ rule. */
+ int yylen;
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Starting parse\n");
+-#endif
++ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+@@ -479,110 +853,97 @@
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+- yyssp = yyss - 1;
++ yyssp = yyss;
+ yyvsp = yyvs;
+-#ifdef YYLSP_NEEDED
+- yylsp = yyls;
+-#endif
+
+-/* Push a new state, which is found in yystate . */
+-/* In all cases, when you get here, the value and location stacks
+- have just been pushed. so pushing a state here evens the stacks. */
+-yynewstate:
+
+- *++yyssp = yystate;
++ goto yysetstate;
+
+- if (yyssp >= yyss + yystacksize - 1)
+- {
+- /* Give user a chance to reallocate the stack */
+- /* Use copies of these so that the &'s don't force the real ones into memory. */
+- YYSTYPE *yyvs1 = yyvs;
+- short *yyss1 = yyss;
+-#ifdef YYLSP_NEEDED
+- YYLTYPE *yyls1 = yyls;
+-#endif
++/*------------------------------------------------------------.
++| yynewstate -- Push a new state, which is found in yystate. |
++`------------------------------------------------------------*/
++ yynewstate:
++ /* In all cases, when you get here, the value and location stacks
++ have just been pushed. so pushing a state here evens the stacks.
++ */
++ yyssp++;
+
++ yysetstate:
++ *yyssp = yystate;
++
++ if (yyss + yystacksize - 1 <= yyssp)
++ {
+ /* Get the current used size of the three stacks, in elements. */
+- int size = yyssp - yyss + 1;
++ YYSIZE_T yysize = yyssp - yyss + 1;
+
+ #ifdef yyoverflow
+- /* Each stack pointer address is followed by the size of
+- the data in use in that stack, in bytes. */
+-#ifdef YYLSP_NEEDED
+- /* This used to be a conditional around just the two extra args,
+- but that might be undefined if yyoverflow is a macro. */
+- yyoverflow("parser stack overflow",
+- &yyss1, size * sizeof (*yyssp),
+- &yyvs1, size * sizeof (*yyvsp),
+- &yyls1, size * sizeof (*yylsp),
+- &yystacksize);
+-#else
+- yyoverflow("parser stack overflow",
+- &yyss1, size * sizeof (*yyssp),
+- &yyvs1, size * sizeof (*yyvsp),
+- &yystacksize);
+-#endif
+-
+- yyss = yyss1; yyvs = yyvs1;
+-#ifdef YYLSP_NEEDED
+- yyls = yyls1;
+-#endif
++ {
++ /* Give user a chance to reallocate the stack. Use copies of
++ these so that the &'s don't force the real ones into
++ memory. */
++ YYSTYPE *yyvs1 = yyvs;
++ short int *yyss1 = yyss;
++
++
++ /* Each stack pointer address is followed by the size of the
++ data in use in that stack, in bytes. This used to be a
++ conditional around just the two extra args, but that might
++ be undefined if yyoverflow is a macro. */
++ yyoverflow ("parser stack overflow",
++ &yyss1, yysize * sizeof (*yyssp),
++ &yyvs1, yysize * sizeof (*yyvsp),
++
++ &yystacksize);
++
++ yyss = yyss1;
++ yyvs = yyvs1;
++ }
+ #else /* no yyoverflow */
++# ifndef YYSTACK_RELOCATE
++ goto yyoverflowlab;
++# else
+ /* Extend the stack our own way. */
+- if (yystacksize >= YYMAXDEPTH)
+- {
+- yyerror("parser stack overflow");
+- if (yyfree_stacks)
+- {
+- free (yyss);
+- free (yyvs);
+-#ifdef YYLSP_NEEDED
+- free (yyls);
+-#endif
+- }
+- return 2;
+- }
++ if (YYMAXDEPTH <= yystacksize)
++ goto yyoverflowlab;
+ yystacksize *= 2;
+- if (yystacksize > YYMAXDEPTH)
++ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+-#ifndef YYSTACK_USE_ALLOCA
+- yyfree_stacks = 1;
+-#endif
+- yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
+- __yy_memcpy ((char *)yyss, (char *)yyss1,
+- size * (unsigned int) sizeof (*yyssp));
+- yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
+- __yy_memcpy ((char *)yyvs, (char *)yyvs1,
+- size * (unsigned int) sizeof (*yyvsp));
+-#ifdef YYLSP_NEEDED
+- yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
+- __yy_memcpy ((char *)yyls, (char *)yyls1,
+- size * (unsigned int) sizeof (*yylsp));
+-#endif
++
++ {
++ short int *yyss1 = yyss;
++ union yyalloc *yyptr =
++ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
++ if (! yyptr)
++ goto yyoverflowlab;
++ YYSTACK_RELOCATE (yyss);
++ YYSTACK_RELOCATE (yyvs);
++
++# undef YYSTACK_RELOCATE
++ if (yyss1 != yyssa)
++ YYSTACK_FREE (yyss1);
++ }
++# endif
+ #endif /* no yyoverflow */
+
+- yyssp = yyss + size - 1;
+- yyvsp = yyvs + size - 1;
+-#ifdef YYLSP_NEEDED
+- yylsp = yyls + size - 1;
+-#endif
++ yyssp = yyss + yysize - 1;
++ yyvsp = yyvs + yysize - 1;
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+-#endif
+
+- if (yyssp >= yyss + yystacksize - 1)
++ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
++ (unsigned long int) yystacksize));
++
++ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Entering state %d\n", yystate);
+-#endif
++ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+- yybackup:
++
++/*-----------.
++| yybackup. |
++`-----------*/
++yybackup:
+
+ /* Do appropriate processing given the current state. */
+ /* Read a lookahead token if we need one and don't already have one. */
+@@ -591,194 +952,167 @@
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+- if (yyn == YYFLAG)
++ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+- /* yychar is either YYEMPTY or YYEOF
+- or a valid token in external form. */
+-
++ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Reading a token: ");
+-#endif
++ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+- /* Convert token to internal form (in yychar1) for indexing tables with */
+-
+- if (yychar <= 0) /* This means end of input. */
++ if (yychar <= YYEOF)
+ {
+- yychar1 = 0;
+- yychar = YYEOF; /* Don't call YYLEX any more */
+-
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Now at end of input.\n");
+-#endif
++ yychar = yytoken = YYEOF;
++ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+- yychar1 = YYTRANSLATE(yychar);
+-
+-#if YYDEBUG != 0
+- if (yydebug)
+- {
+- fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+- /* Give the individual parser a way to print the precise meaning
+- of a token, for further debugging info. */
+-#ifdef YYPRINT
+- YYPRINT (stderr, yychar, yylval);
+-#endif
+- fprintf (stderr, ")\n");
+- }
+-#endif
++ yytoken = YYTRANSLATE (yychar);
++ YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+- yyn += yychar1;
+- if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
++ /* If the proper action on seeing token YYTOKEN is to reduce or to
++ detect an error, take that action. */
++ yyn += yytoken;
++ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+-
+ yyn = yytable[yyn];
+-
+- /* yyn is what to do for this token type in this state.
+- Negative => reduce, -yyn is rule number.
+- Positive => shift, yyn is new state.
+- New state is final state => don't bother to shift,
+- just return success.
+- 0, or most negative number => error. */
+-
+- if (yyn < 0)
++ if (yyn <= 0)
+ {
+- if (yyn == YYFLAG)
++ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+- else if (yyn == 0)
+- goto yyerrlab;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+-
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+-#endif
++ YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+-#ifdef YYLSP_NEEDED
+- *++yylsp = yylloc;
+-#endif
+
+- /* count tokens shifted since error; after three, turn off error status. */
+- if (yyerrstatus) yyerrstatus--;
++
++ /* Count tokens shifted since error; after three, turn off error
++ status. */
++ if (yyerrstatus)
++ yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+-/* Do the default action for the current state. */
+-yydefault:
+
++/*-----------------------------------------------------------.
++| yydefault -- do the default action for the current state. |
++`-----------------------------------------------------------*/
++yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
++ goto yyreduce;
++
+
+-/* Do a reduction. yyn is the number of a rule to reduce with. */
++/*-----------------------------.
++| yyreduce -- Do a reduction. |
++`-----------------------------*/
+ yyreduce:
++ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+- if (yylen > 0)
+- yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- {
+- int i;
++ /* If YYLEN is nonzero, implement the default value of the action:
++ `$$ = $1'.
+
+- fprintf (stderr, "Reducing via rule %d (line %d), ",
+- yyn, yyrline[yyn]);
++ Otherwise, the following line sets YYVAL to garbage.
++ This behavior is undocumented and Bison
++ users should not rely upon it. Assigning to YYVAL
++ unconditionally makes the parser a bit smaller, and it avoids a
++ GCC warning that YYVAL may be used uninitialized. */
++ yyval = yyvsp[1-yylen];
+
+- /* Print the symbols being reduced, and their result. */
+- for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+- fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+- fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+- }
+-#endif
+
+-
+- switch (yyn) {
+-
+-case 4:
+-#line 47 "cfg_y.y"
+-{
++ YY_REDUCE_PRINT (yyn);
++ switch (yyn)
++ {
++ case 5:
++#line 50 "cfg_y.y"
++ {
+ control_init(yyvsp[-1].str);
+- ;
+- break;}
+-case 5:
+-#line 54 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 6:
++#line 57 "cfg_y.y"
++ {
+ fab_option(yyvsp[-1].str,yyvsp[0].str);
+- ;
+- break;}
+-case 6:
+-#line 61 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 7:
++#line 64 "cfg_y.y"
++ {
+ itf = 0;
+- ;
+- break;}
+-case 7:
+-#line 65 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 8:
++#line 68 "cfg_y.y"
++ {
+ char *tmp;
+
+ tmp = strdup(yyvsp[-3].str);
+ if (!tmp) yyerror(strerror(errno));
+ sig = sig_vc(yyvsp[-4].str,tmp,itf);
+- ;
+- break;}
+-case 9:
+-#line 77 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 10:
++#line 80 "cfg_y.y"
++ {
+ yyval.str = NULL;
+- ;
+- break;}
+-case 10:
+-#line 81 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 11:
++#line 84 "cfg_y.y"
++ {
+ yyval.str = strdup(yyvsp[0].str);
+ if (!yyval.str) yyerror(strerror(errno));
+- ;
+- break;}
+-case 12:
+-#line 89 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 13:
++#line 92 "cfg_y.y"
++ {
+ itf = yyvsp[0].num;
+- ;
+- break;}
+-case 14:
+-#line 96 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 15:
++#line 99 "cfg_y.y"
++ {
+ sig->pvc = yyvsp[0].pvc;
+- ;
+- break;}
+-case 17:
+-#line 104 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 18:
++#line 107 "cfg_y.y"
++ {
+ put_route(NULL,0,sig);
+- ;
+- break;}
+-case 19:
+-#line 112 "cfg_y.y"
+-{
++ }
++ break;
++
++ case 20:
++#line 115 "cfg_y.y"
++ {
+ struct sockaddr_atmsvc addr;
+ char *mask;
+
+@@ -790,228 +1124,236 @@
+ return;
+ }
+ put_route(&addr,mask ? strtol(mask,NULL,10) : INT_MAX,sig);
+- ;
+- break;}
+-}
+- /* the action file gets copied in in place of this dollarsign */
+-#line 543 "/usr/lib/bison.simple"
++ }
++ break;
++
++
++ }
++
++/* Line 1010 of yacc.c. */
++#line 1135 "y.tab.c"
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+-#ifdef YYLSP_NEEDED
+- yylsp -= yylen;
+-#endif
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- {
+- short *ssp1 = yyss - 1;
+- fprintf (stderr, "state stack now");
+- while (ssp1 != yyssp)
+- fprintf (stderr, " %d", *++ssp1);
+- fprintf (stderr, "\n");
+- }
+-#endif
++
++ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+-#ifdef YYLSP_NEEDED
+- yylsp++;
+- if (yylen == 0)
+- {
+- yylsp->first_line = yylloc.first_line;
+- yylsp->first_column = yylloc.first_column;
+- yylsp->last_line = (yylsp-1)->last_line;
+- yylsp->last_column = (yylsp-1)->last_column;
+- yylsp->text = 0;
+- }
+- else
+- {
+- yylsp->last_line = (yylsp+yylen-1)->last_line;
+- yylsp->last_column = (yylsp+yylen-1)->last_column;
+- }
+-#endif
+
+- /* Now "shift" the result of the reduction.
+- Determine what state that goes to,
+- based on the state we popped back to
+- and the rule number reduced by. */
++ /* Now `shift' the result of the reduction. Determine what state
++ that goes to, based on the state we popped back to and the rule
++ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+- yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+- if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
++ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
++ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+- yystate = yydefgoto[yyn - YYNTBASE];
++ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+-yyerrlab: /* here on detecting error */
+
+- if (! yyerrstatus)
+- /* If not already recovering from an error, report this error. */
++/*------------------------------------.
++| yyerrlab -- here on detecting error |
++`------------------------------------*/
++yyerrlab:
++ /* If not already recovering from an error, report this error. */
++ if (!yyerrstatus)
+ {
+ ++yynerrs;
+-
+-#ifdef YYERROR_VERBOSE
++#if YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+- if (yyn > YYFLAG && yyn < YYLAST)
++ if (YYPACT_NINF < yyn && yyn < YYLAST)
+ {
+- int size = 0;
+- char *msg;
+- int x, count;
+-
+- count = 0;
+- /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
+- for (x = (yyn < 0 ? -yyn : 0);
+- x < (sizeof(yytname) / sizeof(char *)); x++)
+- if (yycheck[x + yyn] == x)
+- size += strlen(yytname[x]) + 15, count++;
+- msg = (char *) malloc(size + 15);
+- if (msg != 0)
++ YYSIZE_T yysize = 0;
++ int yytype = YYTRANSLATE (yychar);
++ const char* yyprefix;
++ char *yymsg;
++ int yyx;
++
++ /* Start YYX at -YYN if negative to avoid negative indexes in
++ YYCHECK. */
++ int yyxbegin = yyn < 0 ? -yyn : 0;
++
++ /* Stay within bounds of both yycheck and yytname. */
++ int yychecklim = YYLAST - yyn;
++ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
++ int yycount = 0;
++
++ yyprefix = ", expecting ";
++ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
++ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
++ {
++ yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
++ yycount += 1;
++ if (yycount == 5)
++ {
++ yysize = 0;
++ break;
++ }
++ }
++ yysize += (sizeof ("syntax error, unexpected ")
++ + yystrlen (yytname[yytype]));
++ yymsg = (char *) YYSTACK_ALLOC (yysize);
++ if (yymsg != 0)
+ {
+- strcpy(msg, "parse error");
++ char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
++ yyp = yystpcpy (yyp, yytname[yytype]);
+
+- if (count < 5)
++ if (yycount < 5)
+ {
+- count = 0;
+- for (x = (yyn < 0 ? -yyn : 0);
+- x < (sizeof(yytname) / sizeof(char *)); x++)
+- if (yycheck[x + yyn] == x)
++ yyprefix = ", expecting ";
++ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
++ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+- strcat(msg, count == 0 ? ", expecting `" : " or `");
+- strcat(msg, yytname[x]);
+- strcat(msg, "'");
+- count++;
++ yyp = yystpcpy (yyp, yyprefix);
++ yyp = yystpcpy (yyp, yytname[yyx]);
++ yyprefix = " or ";
+ }
+ }
+- yyerror(msg);
+- free(msg);
++ yyerror (yymsg);
++ YYSTACK_FREE (yymsg);
+ }
+ else
+- yyerror ("parse error; also virtual memory exceeded");
++ yyerror ("syntax error; also virtual memory exhausted");
+ }
+ else
+ #endif /* YYERROR_VERBOSE */
+- yyerror("parse error");
++ yyerror ("syntax error");
+ }
+
+- goto yyerrlab1;
+-yyerrlab1: /* here on error raised explicitly by an action */
++
+
+ if (yyerrstatus == 3)
+ {
+- /* if just tried and failed to reuse lookahead token after an error, discard it. */
++ /* If just tried and failed to reuse lookahead token after an
++ error, discard it. */
+
+- /* return failure if at end of input */
+- if (yychar == YYEOF)
+- YYABORT;
+-
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+-#endif
++ if (yychar <= YYEOF)
++ {
++ /* If at end of input, pop the error token,
++ then the rest of the stack, then return failure. */
++ if (yychar == YYEOF)
++ for (;;)
++ {
++ YYPOPSTACK;
++ if (yyssp == yyss)
++ YYABORT;
++ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
++ yydestruct (yystos[*yyssp], yyvsp);
++ }
++ }
++ else
++ {
++ YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
++ yydestruct (yytoken, &yylval);
++ yychar = YYEMPTY;
+
+- yychar = YYEMPTY;
++ }
+ }
+
+- /* Else will try to reuse lookahead token
+- after shifting the error token. */
+-
+- yyerrstatus = 3; /* Each real token shifted decrements this */
++ /* Else will try to reuse lookahead token after shifting the error
++ token. */
++ goto yyerrlab1;
+
+- goto yyerrhandle;
+
+-yyerrdefault: /* current state does not do anything special for the error token. */
++/*---------------------------------------------------.
++| yyerrorlab -- error raised explicitly by YYERROR. |
++`---------------------------------------------------*/
++yyerrorlab:
+
+-#if 0
+- /* This is wrong; only states that explicitly want error tokens
+- should shift them. */
+- yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
+- if (yyn) goto yydefault;
++#ifdef __GNUC__
++ /* Pacify GCC when the user code never invokes YYERROR and the label
++ yyerrorlab therefore never appears in user code. */
++ if (0)
++ goto yyerrorlab;
+ #endif
+
+-yyerrpop: /* pop the current state because it cannot handle the error token */
+-
+- if (yyssp == yyss) YYABORT;
+- yyvsp--;
+- yystate = *--yyssp;
+-#ifdef YYLSP_NEEDED
+- yylsp--;
+-#endif
++ yyvsp -= yylen;
++ yyssp -= yylen;
++ yystate = *yyssp;
++ goto yyerrlab1;
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- {
+- short *ssp1 = yyss - 1;
+- fprintf (stderr, "Error: state stack now");
+- while (ssp1 != yyssp)
+- fprintf (stderr, " %d", *++ssp1);
+- fprintf (stderr, "\n");
+- }
+-#endif
+
+-yyerrhandle:
++/*-------------------------------------------------------------.
++| yyerrlab1 -- common code for both syntax error and YYERROR. |
++`-------------------------------------------------------------*/
++yyerrlab1:
++ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+- yyn = yypact[yystate];
+- if (yyn == YYFLAG)
+- goto yyerrdefault;
++ for (;;)
++ {
++ yyn = yypact[yystate];
++ if (yyn != YYPACT_NINF)
++ {
++ yyn += YYTERROR;
++ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
++ {
++ yyn = yytable[yyn];
++ if (0 < yyn)
++ break;
++ }
++ }
+
+- yyn += YYTERROR;
+- if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+- goto yyerrdefault;
++ /* Pop the current state because it cannot handle the error token. */
++ if (yyssp == yyss)
++ YYABORT;
+
+- yyn = yytable[yyn];
+- if (yyn < 0)
+- {
+- if (yyn == YYFLAG)
+- goto yyerrpop;
+- yyn = -yyn;
+- goto yyreduce;
++ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
++ yydestruct (yystos[yystate], yyvsp);
++ YYPOPSTACK;
++ yystate = *yyssp;
++ YY_STACK_PRINT (yyss, yyssp);
+ }
+- else if (yyn == 0)
+- goto yyerrpop;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+-#if YYDEBUG != 0
+- if (yydebug)
+- fprintf(stderr, "Shifting error token, ");
+-#endif
++ YYDPRINTF ((stderr, "Shifting error token, "));
+
+ *++yyvsp = yylval;
+-#ifdef YYLSP_NEEDED
+- *++yylsp = yylloc;
+-#endif
++
+
+ yystate = yyn;
+ goto yynewstate;
+
+- yyacceptlab:
+- /* YYACCEPT comes here. */
+- if (yyfree_stacks)
+- {
+- free (yyss);
+- free (yyvs);
+-#ifdef YYLSP_NEEDED
+- free (yyls);
+-#endif
+- }
+- return 0;
+
+- yyabortlab:
+- /* YYABORT comes here. */
+- if (yyfree_stacks)
+- {
+- free (yyss);
+- free (yyvs);
+-#ifdef YYLSP_NEEDED
+- free (yyls);
++/*-------------------------------------.
++| yyacceptlab -- YYACCEPT comes here. |
++`-------------------------------------*/
++yyacceptlab:
++ yyresult = 0;
++ goto yyreturn;
++
++/*-----------------------------------.
++| yyabortlab -- YYABORT comes here. |
++`-----------------------------------*/
++yyabortlab:
++ yyresult = 1;
++ goto yyreturn;
++
++#ifndef yyoverflow
++/*----------------------------------------------.
++| yyoverflowlab -- parser overflow comes here. |
++`----------------------------------------------*/
++yyoverflowlab:
++ yyerror ("parser stack overflow");
++ yyresult = 2;
++ /* Fall through. */
++#endif
++
++yyreturn:
++#ifndef yyoverflow
++ if (yyss != yyssa)
++ YYSTACK_FREE (yyss);
+ #endif
+- }
+- return 1;
++ return yyresult;
+ }
+-#line 126 "cfg_y.y"
++
++
++
+--- linux-atm-2.4.1.orig/src/switch/cfg_y.y
++++ linux-atm-2.4.1/src/switch/cfg_y.y
+@@ -10,6 +10,7 @@
+ #include <string.h>
+ #include <errno.h>
+ #include <limits.h>
++#include <stdlib.h>
+
+ #include "atm.h"
+
+@@ -19,6 +20,8 @@
+ #include "swc.h"
+
+
++extern void yyerror(const char *s);
++
+ static int itf;
+ static SIGNALING_ENTITY *sig;
+
+--- linux-atm-2.4.1.orig/src/switch/cfg_y.h
++++ linux-atm-2.4.1/src/switch/cfg_y.h
+@@ -1,19 +1,77 @@
+-typedef union {
++/* A Bison parser, made by GNU Bison 1.875d. */
++
++/* Skeleton parser for Yacc-like parsing with Bison,
++ Copyright (C) 1984, 1989, 1990, 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.
++
++ 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, when this file is copied by Bison into a
++ Bison output file, you may use that output file without restriction.
++ This special exception was added by the Free Software Foundation
++ in version 1.24 of Bison. */
++
++/* Tokens. */
++#ifndef YYTOKENTYPE
++# define YYTOKENTYPE
++ /* Put the tokens into the symbol table, so that GDB and other debuggers
++ know about them. */
++ enum yytokentype {
++ TOK_COMMAND = 258,
++ TOK_VPCI = 259,
++ TOK_ITF = 260,
++ TOK_DEFAULT = 261,
++ TOK_ROUTE = 262,
++ TOK_STR = 263,
++ TOK_SOCKET = 264,
++ TOK_OPTION = 265,
++ TOK_CONTROL = 266,
++ TOK_NUM = 267,
++ TOK_PVC = 268
++ };
++#endif
++#define TOK_COMMAND 258
++#define TOK_VPCI 259
++#define TOK_ITF 260
++#define TOK_DEFAULT 261
++#define TOK_ROUTE 262
++#define TOK_STR 263
++#define TOK_SOCKET 264
++#define TOK_OPTION 265
++#define TOK_CONTROL 266
++#define TOK_NUM 267
++#define TOK_PVC 268
++
++
++
++
++#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
++#line 30 "cfg_y.y"
++typedef union YYSTYPE {
+ int num;
+ char *str;
+ struct sockaddr_atmpvc pvc;
+ } YYSTYPE;
+-#define TOK_COMMAND 257
+-#define TOK_VPCI 258
+-#define TOK_ITF 259
+-#define TOK_DEFAULT 260
+-#define TOK_ROUTE 261
+-#define TOK_STR 262
+-#define TOK_SOCKET 263
+-#define TOK_OPTION 264
+-#define TOK_CONTROL 265
+-#define TOK_NUM 266
+-#define TOK_PVC 267
+-
++/* Line 1285 of yacc.c. */
++#line 69 "y.tab.h"
++# define yystype YYSTYPE /* obsolescent; will be withdrawn */
++# define YYSTYPE_IS_DECLARED 1
++# define YYSTYPE_IS_TRIVIAL 1
++#endif
+
+ extern YYSTYPE yylval;
++
++
++
+--- linux-atm-2.4.1.orig/src/switch/debug/Makefile.in
++++ linux-atm-2.4.1/src/switch/debug/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -90,8 +90,7 @@
+ INCLUDES = -I$(top_builddir)/src/qgen
+
+ sw_debug_SOURCES = debug.c
+-sw_debug_XTRAS = $(top_builddir)/src/switch/libsw.a \
+- $(top_builddir)/src/lib/libatm.la
++sw_debug_XTRAS = $(top_builddir)/src/switch/libsw.a $(top_builddir)/src/lib/libatm.la
+
+ sw_debug_LDADD = $(sw_debug_XTRAS) -lfl
+
+@@ -121,8 +120,9 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
++DEP_FILES = .deps/debug.P
+ SOURCES = $(sw_debug_SOURCES)
+ OBJECTS = $(sw_debug_OBJECTS)
+
+@@ -130,9 +130,9 @@
+ .SUFFIXES:
+ .SUFFIXES: .S .c .lo .o .obj .s
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/switch/debug/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/switch/debug/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -146,9 +146,6 @@
+
+ maintainer-clean-noinstPROGRAMS:
+
+-.c.o:
+- $(COMPILE) -c $<
+-
+ # FIXME: We should only use cygpath when building on Windows,
+ # and only if it is available.
+ .c.obj:
+@@ -171,9 +168,6 @@
+
+ maintainer-clean-compile:
+
+-.c.lo:
+- $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+-
+ .s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+@@ -212,7 +206,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -228,6 +222,11 @@
+ subdir = src/switch/debug
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/switch/debug/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+@@ -238,11 +237,38 @@
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+-debug.o: debug.c ../../../config.h ../../../src/include/atm.h \
+- ../../../src/include/stdint.h ../../../src/include/atmd.h \
+- ../../../src/qgen/uni.h ../fab.h ../proto.h \
+- ../../../src/include/atmsap.h ../sig.h
+
++DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
++
++-include $(DEP_FILES)
++
++mostlyclean-depend:
++
++clean-depend:
++
++distclean-depend:
++ -rm -rf .deps
++
++maintainer-clean-depend:
++
++%.o: %.c
++ @echo '$(COMPILE) -c $<'; \
++ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-cp .deps/$(*F).pp .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm .deps/$(*F).pp
++
++%.lo: %.c
++ @echo '$(LTCOMPILE) -c $<'; \
++ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
++ < .deps/$(*F).pp > .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm -f .deps/$(*F).pp
+ info-am:
+ info: info-am
+ dvi-am:
+@@ -279,27 +305,27 @@
+
+ maintainer-clean-generic:
+ mostlyclean-am: mostlyclean-noinstPROGRAMS mostlyclean-compile \
+- mostlyclean-libtool mostlyclean-tags \
++ mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+ mostlyclean-generic
+
+ mostlyclean: mostlyclean-am
+
+ clean-am: clean-noinstPROGRAMS clean-compile clean-libtool clean-tags \
+- clean-generic mostlyclean-am
++ clean-depend clean-generic mostlyclean-am
+
+ clean: clean-am
+
+ distclean-am: distclean-noinstPROGRAMS distclean-compile \
+- distclean-libtool distclean-tags distclean-generic \
+- clean-am
++ distclean-libtool distclean-tags distclean-depend \
++ distclean-generic clean-am
+ -rm -f libtool
+
+ distclean: distclean-am
+
+ maintainer-clean-am: maintainer-clean-noinstPROGRAMS \
+ maintainer-clean-compile maintainer-clean-libtool \
+- maintainer-clean-tags maintainer-clean-generic \
+- distclean-am
++ maintainer-clean-tags maintainer-clean-depend \
++ 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."
+
+@@ -310,12 +336,14 @@
+ mostlyclean-compile distclean-compile clean-compile \
+ maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+ clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+-distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+-dvi-am dvi check check-am installcheck-am installcheck 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
++distclean-tags clean-tags maintainer-clean-tags distdir \
++mostlyclean-depend distclean-depend clean-depend \
++maintainer-clean-depend info-am info dvi-am dvi check check-am \
++installcheck-am installcheck 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.
+--- linux-atm-2.4.1.orig/src/switch/debug/debug.c
++++ linux-atm-2.4.1/src/switch/debug/debug.c
+@@ -43,7 +43,7 @@
+
+ void fab_init(CALL *call)
+ {
+- PRV(call) = alloc_t(FAB);
++ call->fab = alloc_t(FAB);
+ PRV(call)->next = calls;
+ calls = call;
+ }
+@@ -59,7 +59,7 @@
+ diag(COMPONENT,DIAG_FATAL,"fab_destroy: call %p not found",call);
+ *walk = PRV(call)->next;
+ free(PRV(call));
+- PRV(call) = NULL;
++ call->fab = NULL;
+ }
+
+
+--- linux-atm-2.4.1.orig/src/switch/tcp/Makefile.in
++++ linux-atm-2.4.1/src/switch/tcp/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -90,8 +90,7 @@
+ INCLUDES = -I$(top_builddir)/src/qgen
+
+ sw_tcp_SOURCES = tcpsw.c
+-sw_tcp_XTRAS = $(top_builddir)/src/switch/libsw.a \
+- $(top_builddir)/src/lib/libatm.la
++sw_tcp_XTRAS = $(top_builddir)/src/switch/libsw.a $(top_builddir)/src/lib/libatm.la
+
+ sw_tcp_LDADD = $(sw_tcp_XTRAS) -lfl
+ sw_tcp_DEPENDENCIES = $(sw_tcp_XTRAS)
+@@ -120,8 +119,9 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
++DEP_FILES = .deps/tcpsw.P
+ SOURCES = $(sw_tcp_SOURCES)
+ OBJECTS = $(sw_tcp_OBJECTS)
+
+@@ -129,9 +129,9 @@
+ .SUFFIXES:
+ .SUFFIXES: .S .c .lo .o .obj .s
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/switch/tcp/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/switch/tcp/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -145,9 +145,6 @@
+
+ maintainer-clean-noinstPROGRAMS:
+
+-.c.o:
+- $(COMPILE) -c $<
+-
+ # FIXME: We should only use cygpath when building on Windows,
+ # and only if it is available.
+ .c.obj:
+@@ -170,9 +167,6 @@
+
+ maintainer-clean-compile:
+
+-.c.lo:
+- $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+-
+ .s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+@@ -211,7 +205,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -227,6 +221,11 @@
+ subdir = src/switch/tcp
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/switch/tcp/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+@@ -237,11 +236,38 @@
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+-tcpsw.o: tcpsw.c ../../../config.h ../../../src/include/stdint.h \
+- ../../../src/include/atm.h ../../../src/include/atmd.h \
+- ../../../src/qgen/uni.h ../fab.h ../proto.h \
+- ../../../src/include/atmsap.h ../sig.h ../dispatch.h ../swc.h
+
++DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
++
++-include $(DEP_FILES)
++
++mostlyclean-depend:
++
++clean-depend:
++
++distclean-depend:
++ -rm -rf .deps
++
++maintainer-clean-depend:
++
++%.o: %.c
++ @echo '$(COMPILE) -c $<'; \
++ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-cp .deps/$(*F).pp .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm .deps/$(*F).pp
++
++%.lo: %.c
++ @echo '$(LTCOMPILE) -c $<'; \
++ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
++ < .deps/$(*F).pp > .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm -f .deps/$(*F).pp
+ info-am:
+ info: info-am
+ dvi-am:
+@@ -278,27 +304,27 @@
+
+ maintainer-clean-generic:
+ mostlyclean-am: mostlyclean-noinstPROGRAMS mostlyclean-compile \
+- mostlyclean-libtool mostlyclean-tags \
++ mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+ mostlyclean-generic
+
+ mostlyclean: mostlyclean-am
+
+ clean-am: clean-noinstPROGRAMS clean-compile clean-libtool clean-tags \
+- clean-generic mostlyclean-am
++ clean-depend clean-generic mostlyclean-am
+
+ clean: clean-am
+
+ distclean-am: distclean-noinstPROGRAMS distclean-compile \
+- distclean-libtool distclean-tags distclean-generic \
+- clean-am
++ distclean-libtool distclean-tags distclean-depend \
++ distclean-generic clean-am
+ -rm -f libtool
+
+ distclean: distclean-am
+
+ maintainer-clean-am: maintainer-clean-noinstPROGRAMS \
+ maintainer-clean-compile maintainer-clean-libtool \
+- maintainer-clean-tags maintainer-clean-generic \
+- distclean-am
++ maintainer-clean-tags maintainer-clean-depend \
++ 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."
+
+@@ -309,12 +335,14 @@
+ mostlyclean-compile distclean-compile clean-compile \
+ maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+ clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+-distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+-dvi-am dvi check check-am installcheck-am installcheck 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
++distclean-tags clean-tags maintainer-clean-tags distdir \
++mostlyclean-depend distclean-depend clean-depend \
++maintainer-clean-depend info-am info dvi-am dvi check check-am \
++installcheck-am installcheck 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.
+--- linux-atm-2.4.1.orig/src/switch/tcp/tcpsw.c
++++ linux-atm-2.4.1/src/switch/tcp/tcpsw.c
+@@ -345,7 +345,7 @@
+
+ void fab_init(CALL *call)
+ {
+- PRV(call) = alloc_t(FAB);
++ call->fab = alloc_t(FAB);
+ PRV(call)->active = 0;
+ PRV(call)->next = calls;
+ calls = call;
+@@ -362,7 +362,7 @@
+ diag(COMPONENT,DIAG_FATAL,"fab_destroy: call %p not found",call);
+ *walk = PRV(call)->next;
+ free(PRV(call));
+- PRV(call) = NULL;
++ call->fab = NULL;
+ }
+
+
+--- linux-atm-2.4.1.orig/src/config/Makefile.in
++++ linux-atm-2.4.1/src/config/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -96,14 +96,14 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
+ all: all-redirect
+ .SUFFIXES:
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/config/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/config/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -186,7 +186,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -202,6 +202,11 @@
+ subdir = src/config
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/config/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+--- linux-atm-2.4.1.orig/src/config/init-redhat/Makefile.in
++++ linux-atm-2.4.1/src/config/init-redhat/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -94,14 +94,14 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
+ all: all-redirect
+ .SUFFIXES:
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/config/init-redhat/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/config/init-redhat/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -114,6 +114,11 @@
+ subdir = src/config/init-redhat
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/config/init-redhat/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+--- linux-atm-2.4.1.orig/src/extra/Makefile.in
++++ linux-atm-2.4.1/src/extra/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -96,14 +96,14 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
+ all: all-redirect
+ .SUFFIXES:
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/extra/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/extra/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -188,7 +188,7 @@
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+
+ mostlyclean-tags:
+
+@@ -204,6 +204,11 @@
+ subdir = src/extra
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/extra/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+--- linux-atm-2.4.1.orig/src/extra/ANS/Makefile.in
++++ linux-atm-2.4.1/src/extra/ANS/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -94,14 +94,14 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
+ all: all-redirect
+ .SUFFIXES:
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/extra/ANS/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/extra/ANS/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -114,6 +114,11 @@
+ subdir = src/extra/ANS
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/extra/ANS/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+--- linux-atm-2.4.1.orig/src/br2684/Makefile.am
++++ linux-atm-2.4.1/src/br2684/Makefile.am
+@@ -0,0 +1,10 @@
++sbin_PROGRAMS = br2684ctl
++
++LDADD = $(top_builddir)/src/lib/libatm.la
++
++br2684ctl_SOURCES = br2684ctl.c
++
++man_MANS = br2684ctl.8
++
++EXTRA_DIST = $(man_MANS) USAGE.br2684
++
+--- linux-atm-2.4.1.orig/src/br2684/Makefile.in
++++ linux-atm-2.4.1/src/br2684/Makefile.in
+@@ -0,0 +1,418 @@
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
++
++# Copyright (C) 1994, 1995-8, 1999, 2001 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@ $(AM_INSTALL_PROGRAM_FLAGS)
++INSTALL_DATA = @INSTALL_DATA@
++INSTALL_SCRIPT = @INSTALL_SCRIPT@
++transform = @program_transform_name@
++
++NORMAL_INSTALL = :
++PRE_INSTALL = :
++POST_INSTALL = :
++NORMAL_UNINSTALL = :
++PRE_UNINSTALL = :
++POST_UNINSTALL = :
++host_alias = @host_alias@
++host_triplet = @host@
++AR = @AR@
++AS = @AS@
++CC = /usr/src/openwrt/staging_dir_mipsel/bin/mipsel-linux-gcc
++CXX = @CXX@
++CXXCPP = @CXXCPP@
++DLLTOOL = @DLLTOOL@
++ECHO = @ECHO@
++EGREP = @EGREP@
++EXEEXT = @EXEEXT@
++F77 = @F77@
++GCJ = @GCJ@
++GCJFLAGS = @GCJFLAGS@
++HAVE_LIB = @HAVE_LIB@
++LEX = @LEX@
++LIB = @LIB@
++LIBTOOL = @LIBTOOL@
++LIBTOOL_DEPS = @LIBTOOL_DEPS@
++LIBVER_AGE = @LIBVER_AGE@
++LIBVER_CURRENT = @LIBVER_CURRENT@
++LIBVER_REVISION = @LIBVER_REVISION@
++LN_S = @LN_S@
++LTLIB = @LTLIB@
++MAKEINFO = @MAKEINFO@
++OBJDUMP = @OBJDUMP@
++OBJEXT = @OBJEXT@
++PACKAGE = @PACKAGE@
++PERL = @PERL@
++RANLIB = @RANLIB@
++RC = @RC@
++STRIP = @STRIP@
++VERSION = @VERSION@
++YACC = @YACC@
++
++sbin_PROGRAMS = br2684ctl
++
++LDADD = $(top_builddir)/src/lib/libatm.la
++
++br2684ctl_SOURCES = br2684ctl.c
++
++man_MANS = br2684ctl.8
++
++EXTRA_DIST = $(man_MANS) USAGE.br2684
++mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
++CONFIG_HEADER = ../../config.h
++CONFIG_CLEAN_FILES =
++sbin_PROGRAMS = br2684ctl$(EXEEXT)
++PROGRAMS = $(sbin_PROGRAMS)
++
++
++DEFS = @DEFS@ -I. -I$(srcdir) -I../..
++CPPFLAGS = @CPPFLAGS@
++LDFLAGS = @LDFLAGS@
++LIBS = @LIBS@
++br2684ctl_OBJECTS = br2684ctl.$(OBJEXT)
++br2684ctl_LDADD = $(LDADD)
++br2684ctl_DEPENDENCIES = $(top_builddir)/src/lib/libatm.la
++br2684ctl_LDFLAGS =
++CFLAGS = @CFLAGS@
++COMPILE = $(TARGET_CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
++LTCOMPILE = $(LIBTOOL) --mode=compile $(TARGET_CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
++CCLD = $(TARGET_CC)
++LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
++man8dir = $(mandir)/man8
++MANS = $(man_MANS)
++
++NROFF = nroff
++DIST_COMMON = Makefile.am Makefile.in
++
++
++DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
++
++TAR = tar
++GZIP_ENV = --best
++DEP_FILES = .deps/br2684ctl.P
++SOURCES = $(br2684ctl_SOURCES)
++OBJECTS = $(br2684ctl_OBJECTS)
++
++all: all-redirect
++.SUFFIXES:
++.SUFFIXES: .S .c .lo .o .obj .s
++$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu src/br2684/Makefile
++
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
++ cd $(top_builddir) \
++ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
++
++
++mostlyclean-sbinPROGRAMS:
++
++clean-sbinPROGRAMS:
++ -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS)
++
++distclean-sbinPROGRAMS:
++
++maintainer-clean-sbinPROGRAMS:
++
++install-sbinPROGRAMS: $(sbin_PROGRAMS)
++ @$(NORMAL_INSTALL)
++ $(mkinstalldirs) $(DESTDIR)$(sbindir)
++ @list='$(sbin_PROGRAMS)'; for p in $$list; do \
++ if test -f $$p; then \
++ echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
++ $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
++ else :; fi; \
++ done
++
++uninstall-sbinPROGRAMS:
++ @$(NORMAL_UNINSTALL)
++ list='$(sbin_PROGRAMS)'; for p in $$list; do \
++ rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
++ done
++
++# FIXME: We should only use cygpath when building on Windows,
++# and only if it is available.
++.c.obj:
++ $(COMPILE) -c `cygpath -w $<`
++
++.s.o:
++ $(COMPILE) -c $<
++
++.S.o:
++ $(COMPILE) -c $<
++
++mostlyclean-compile:
++ -rm -f *.o core *.core
++ -rm -f *.$(OBJEXT)
++
++clean-compile:
++
++distclean-compile:
++ -rm -f *.tab.c
++
++maintainer-clean-compile:
++
++.s.lo:
++ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
++
++.S.lo:
++ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
++
++mostlyclean-libtool:
++ -rm -f *.lo
++
++clean-libtool:
++ -rm -rf .libs _libs
++
++distclean-libtool:
++
++maintainer-clean-libtool:
++
++br2684ctl$(EXEEXT): $(br2684ctl_OBJECTS) $(br2684ctl_DEPENDENCIES)
++ @rm -f br2684ctl$(EXEEXT)
++ $(LINK) $(br2684ctl_LDFLAGS) $(br2684ctl_OBJECTS) $(br2684ctl_LDADD) $(LIBS)
++
++install-man8:
++ $(mkinstalldirs) $(DESTDIR)$(man8dir)
++ @list='$(man8_MANS)'; \
++ l2='$(man_MANS)'; for i in $$l2; do \
++ case "$$i" in \
++ *.8*) list="$$list $$i" ;; \
++ esac; \
++ done; \
++ for i in $$list; do \
++ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
++ else file=$$i; fi; \
++ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
++ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
++ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
++ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \
++ $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \
++ done
++
++uninstall-man8:
++ @list='$(man8_MANS)'; \
++ l2='$(man_MANS)'; for i in $$l2; do \
++ case "$$i" in \
++ *.8*) list="$$list $$i" ;; \
++ esac; \
++ done; \
++ for i in $$list; do \
++ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
++ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
++ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
++ echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \
++ rm -f $(DESTDIR)$(man8dir)/$$inst; \
++ done
++install-man: $(MANS)
++ @$(NORMAL_INSTALL)
++ $(MAKE) $(AM_MAKEFLAGS) install-man8
++uninstall-man:
++ @$(NORMAL_UNINSTALL)
++ $(MAKE) $(AM_MAKEFLAGS) uninstall-man8
++
++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) $(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)$$unique$(LISP)$$tags" \
++ || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
++
++mostlyclean-tags:
++
++clean-tags:
++
++distclean-tags:
++ -rm -f TAGS ID
++
++maintainer-clean-tags:
++
++distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
++
++subdir = src/br2684
++
++distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/br2684/Makefile
++ @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
++
++DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
++
++-include $(DEP_FILES)
++
++mostlyclean-depend:
++
++clean-depend:
++
++distclean-depend:
++ -rm -rf .deps
++
++maintainer-clean-depend:
++
++%.o: %.c
++ @echo '$(COMPILE) -c $<'; \
++ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-cp .deps/$(*F).pp .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm .deps/$(*F).pp
++
++%.lo: %.c
++ @echo '$(LTCOMPILE) -c $<'; \
++ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
++ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
++ < .deps/$(*F).pp > .deps/$(*F).P; \
++ tr ' ' '\012' < .deps/$(*F).pp \
++ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
++ >> .deps/$(*F).P; \
++ rm -f .deps/$(*F).pp
++info-am:
++info: info-am
++dvi-am:
++dvi: dvi-am
++check-am: all-am
++check: check-am
++installcheck-am:
++installcheck: installcheck-am
++install-exec-am: install-sbinPROGRAMS
++install-exec: install-exec-am
++
++install-data-am: install-man
++install-data: install-data-am
++
++install-am: all-am
++ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
++install: install-am
++uninstall-am: uninstall-sbinPROGRAMS uninstall-man
++uninstall: uninstall-am
++all-am: Makefile $(PROGRAMS) $(MANS)
++all-redirect: all-am
++install-strip:
++ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
++installdirs:
++ $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(mandir)/man8
++
++
++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-sbinPROGRAMS mostlyclean-compile \
++ mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
++ mostlyclean-generic
++
++mostlyclean: mostlyclean-am
++
++clean-am: clean-sbinPROGRAMS clean-compile clean-libtool clean-tags \
++ clean-depend clean-generic mostlyclean-am
++
++clean: clean-am
++
++distclean-am: distclean-sbinPROGRAMS distclean-compile \
++ distclean-libtool distclean-tags distclean-depend \
++ distclean-generic clean-am
++ -rm -f libtool
++
++distclean: distclean-am
++
++maintainer-clean-am: maintainer-clean-sbinPROGRAMS \
++ maintainer-clean-compile maintainer-clean-libtool \
++ maintainer-clean-tags maintainer-clean-depend \
++ 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
++
++.PHONY: mostlyclean-sbinPROGRAMS distclean-sbinPROGRAMS \
++clean-sbinPROGRAMS maintainer-clean-sbinPROGRAMS uninstall-sbinPROGRAMS \
++install-sbinPROGRAMS mostlyclean-compile distclean-compile \
++clean-compile maintainer-clean-compile mostlyclean-libtool \
++distclean-libtool clean-libtool maintainer-clean-libtool install-man8 \
++uninstall-man8 install-man uninstall-man tags mostlyclean-tags \
++distclean-tags clean-tags maintainer-clean-tags distdir \
++mostlyclean-depend distclean-depend clean-depend \
++maintainer-clean-depend info-am info dvi-am dvi check check-am \
++installcheck-am installcheck 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:
+--- linux-atm-2.4.1.orig/src/br2684/br2684ctl.8
++++ linux-atm-2.4.1/src/br2684/br2684ctl.8
+@@ -0,0 +1,74 @@
++.\"
++.TH br2684ctl 1 "7 Jul 2003"
++.SH NAME
++br2684ctl \- RFC1483/2684 Bridge Daemon
++.SH SYNOPSIS
++.B br2684ctl
++[
++.BI \-b
++] [[
++.BI \-c\ n
++] [
++.BI \-e\ 0|1
++] [
++.BI \-s\ sndbuf
++] [
++.BI \-a\ [itf].vpi.vci
++]] ...
++.SH PARAMETERS
++.TP 15
++.BI \-a\ [itf].vpi.vci
++ATM PVC number, VPI and VCI. (Required)
++.BI \-b
++Puts the process in the background.
++.TP 15
++.BI \-c\ n
++br2684 interface number such as 0, 1, ... (Required)
++.TP 15
++.BI \-e\ 0|1
++Encapsulation method: 0=LLC, 1=VC mux (the default is 0 or LLC)
++.TP 15
++.TP 15
++.BI \-s\ sndbuf
++Send buffer size. Default is 8192.
++.SH DESCRIPTION
++br2684ctl handles RFC1483/2684 bridged PDUs.
++This is most often used in ADSL scenarios where
++.I usually
++the subscribers'
++ethernet traffic is encapsulated in ATM AAL5 (by bridging ADSL modems)
++according to RFC2684.
++The subscriber-side ADSL modem can be external with an ethernet connector
++or an internal ADSL card in a PC.
++RFC1483 has been obsoleted by RFC2684.
++
++For example it is possible to set up your Linux box to handle several
++ATM PVC's with bridged-1483 (sometimes referred as SNAP) encapsulation.
++The Linux network stack might provide DHCP, IP masquerading, IP firewall services or
++bridge the Ethernet frames just like it had several ethernet interfaces.
++In fact it can have several (logical) ethernet interfaces, where
++ATM is just used as a carrier.
++.SH USAGE
++br2684ctl creates a new network interface named nas[n]
++which is bound to an specific ATM PVC. It requires two mandatory
++arguments: -c, the interface number, and -a, the ATM PVC. It should be
++noted that the order of the command arguments matter; -c should be
++followed by -a. You can create as many interfaces as necessary
++in one go, just make a long command line ;)
++
++For example, following command will create a nas0 interface which uses
++the ATM PVC with VPI=0 and VCI=401. You need to configure the PVC connection
++0.401 on the ATM switch manually.
++
++% br2684ctl -c 0 -a 0.401
++
++The command will only create a new interface nas0.
++Next step is to assign an IP address and netmask to
++the interface nas0 using the ifconfig command. Using ifconfig, you can
++also assign a Ethernet MAC address to the interface nas0, if necessary.
++
++% ifconfig nas0 192.168.2.1 netmask 255.255.255.0
++.SH NOTES
++This man page is based on a tutorial by by Joonbum Byun <jbyun@megaxess.com>
++.SH SEE ALSO
++.BR qos (7)
+--- linux-atm-2.4.1.orig/doc/Makefile.in
++++ linux-atm-2.4.1/doc/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
++# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+@@ -96,14 +96,14 @@
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+-TAR = gtar
++TAR = tar
+ GZIP_ENV = --best
+ all: all-redirect
+ .SUFFIXES:
+ $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps doc/Makefile
++ cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile
+
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+@@ -116,6 +116,11 @@
+ subdir = doc
+
+ distdir: $(DISTFILES)
++ here=`cd $(top_builddir) && pwd`; \
++ top_distdir=`cd $(top_distdir) && pwd`; \
++ distdir=`cd $(distdir) && pwd`; \
++ cd $(top_srcdir) \
++ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu doc/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+--- linux-atm-2.4.1.orig/debian/patches/00list
++++ linux-atm-2.4.1/debian/patches/00list
+@@ -0,0 +1 @@
++10_atmbr2684.h
+--- linux-atm-2.4.1.orig/debian/patches/10_atmbr2684.h.dpatch
++++ linux-atm-2.4.1/debian/patches/10_atmbr2684.h.dpatch
+@@ -0,0 +1,598 @@
++#! /bin/sh -e
++## 01_kernel-header.dpatch by <bengen+debian@hilluzination.de>
++##
++## All lines beginning with ## DP:' are a description of the patch.
++## DP: add header file atmbr2684.h
++
++if [ -e /usr/include/linux/atmbr2684.h ]; then exit 0; fi
++
++if [ $# -ne 1 ]; then
++ echo "basename $0: script expects -patch|-unpatch as argument" >&2
++ exit 1
++fi
++case "$1" in
++ -patch) patch -f --no-backup-if-mismatch -p1 < $0;;
++ -unpatch) patch -f --no-backup-if-mismatch -E -R -p1 < $0;;
++ *)
++ echo "basename $0: script expects -patch|-unpatch as argument" >&2
++ exit 1;;
++esac
++
++exit 0
++@DPATCH@
++
++--- linux-atm.orig/src/include/linux/atmbr2684.h
+++++ linux-atm/src/include/linux/atmbr2684.h
++@@ -0,0 +1,101 @@
+++#ifndef _LINUX_ATMBR2684_H
+++#define _LINUX_ATMBR2684_H
+++
+++#include <linux/atm.h>
+++#include <linux/if.h> /* For IFNAMSIZ */
+++
+++/*
+++ * Type of media we're bridging (ethernet, token ring, etc) Currently only
+++ * ethernet is supported
+++ */
+++#define BR2684_MEDIA_ETHERNET (0) /* 802.3 */
+++#define BR2684_MEDIA_802_4 (1) /* 802.4 */
+++#define BR2684_MEDIA_TR (2) /* 802.5 - token ring */
+++#define BR2684_MEDIA_FDDI (3)
+++#define BR2684_MEDIA_802_6 (4) /* 802.6 */
+++
+++/*
+++ * Is there FCS inbound on this VC? This currently isn't supported.
+++ */
+++#define BR2684_FCSIN_NO (0)
+++#define BR2684_FCSIN_IGNORE (1)
+++#define BR2684_FCSIN_VERIFY (2)
+++
+++/*
+++ * Is there FCS outbound on this VC? This currently isn't supported.
+++ */
+++#define BR2684_FCSOUT_NO (0)
+++#define BR2684_FCSOUT_SENDZERO (1)
+++#define BR2684_FCSOUT_GENERATE (2)
+++
+++/*
+++ * Does this VC include LLC encapsulation?
+++ */
+++#define BR2684_ENCAPS_VC (0) /* VC-mux */
+++#define BR2684_ENCAPS_LLC (1)
+++#define BR2684_ENCAPS_AUTODETECT (2) /* Unsuported */
+++
+++/*
+++ * This is for the ATM_NEWBACKENDIF call - these are like socket families:
+++ * the first element of the structure is the backend number and the rest
+++ * is per-backend specific
+++ */
+++struct atm_newif_br2684 {
+++ atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */
+++ int media; /* BR2684_MEDIA_* */
+++ char ifname[IFNAMSIZ];
+++ int mtu;
+++};
+++
+++/*
+++ * This structure is used to specify a br2684 interface - either by a
+++ * positive integer (returned by ATM_NEWBACKENDIF) or the interfaces name
+++ */
+++#define BR2684_FIND_BYNOTHING (0)
+++#define BR2684_FIND_BYNUM (1)
+++#define BR2684_FIND_BYIFNAME (2)
+++struct br2684_if_spec {
+++ int method; /* BR2684_FIND_* */
+++ union {
+++ char ifname[IFNAMSIZ];
+++ int devnum;
+++ } spec;
+++};
+++
+++/*
+++ * This is for the ATM_SETBACKEND call - these are like socket families:
+++ * the first element of the structure is the backend number and the rest
+++ * is per-backend specific
+++ */
+++struct atm_backend_br2684 {
+++ atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */
+++ struct br2684_if_spec ifspec;
+++ int fcs_in; /* BR2684_FCSIN_* */
+++ int fcs_out; /* BR2684_FCSOUT_* */
+++ int fcs_auto; /* 1: fcs_{in,out} disabled if no FCS rx'ed */
+++ int encaps; /* BR2684_ENCAPS_* */
+++ int has_vpiid; /* 1: use vpn_id - Unsupported */
+++ __u8 vpn_id[7];
+++ int send_padding; /* unsupported */
+++ int min_size; /* we will pad smaller packets than this */
+++};
+++
+++/*
+++ * The BR2684_SETFILT ioctl is an experimental mechanism for folks
+++ * terminating a large number of IP-only vcc's. When netfilter allows
+++ * efficient per-if in/out filters, this support will be removed
+++ */
+++struct br2684_filter {
+++ __u32 prefix; /* network byte order */
+++ __u32 netmask; /* 0 = disable filter */
+++};
+++
+++struct br2684_filter_set {
+++ struct br2684_if_spec ifspec;
+++ struct br2684_filter filter;
+++};
+++
+++#define BR2684_SETFILT _IOW( 'a', ATMIOC_BACKEND + 0, \
+++ struct br2684_filter_set)
+++
+++#endif /* _LINUX_ATMBR2684_H */
++--- linux-atm.orig/src/include/linux/atmdev.h
+++++ linux-atm/src/include/linux/atmdev.h
++@@ -0,0 +1,468 @@
+++/* atmdev.h - ATM device driver declarations and various related items */
+++
+++/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
+++
+++
+++#ifndef LINUX_ATMDEV_H
+++#define LINUX_ATMDEV_H
+++
+++
+++#include <linux/config.h>
+++#include <linux/atmapi.h>
+++#include <linux/atm.h>
+++#include <linux/atmioc.h>
+++
+++
+++#define ESI_LEN 6
+++
+++#define ATM_OC3_PCR (155520000/270*260/8/53)
+++ /* OC3 link rate: 155520000 bps
+++ SONET overhead: /270*260 (9 section, 1 path)
+++ bits per cell: /8/53
+++ max cell rate: 353207.547 cells/sec */
+++#define ATM_25_PCR ((25600000/8-8000)/54)
+++ /* 25 Mbps ATM cell rate (59111) */
+++#define ATM_OC12_PCR (622080000/1080*1040/8/53)
+++ /* OC12 link rate: 622080000 bps
+++ SONET overhead: /1080*1040
+++ bits per cell: /8/53
+++ max cell rate: 1412830.188 cells/sec */
+++#define ATM_DS3_PCR (8000*12)
+++ /* DS3: 12 cells in a 125 usec time slot */
+++
+++#define ATM_SD(s) ((s)->sk->protinfo.af_atm)
+++
+++
+++#define __AAL_STAT_ITEMS \
+++ __HANDLE_ITEM(tx); /* TX okay */ \
+++ __HANDLE_ITEM(tx_err); /* TX errors */ \
+++ __HANDLE_ITEM(rx); /* RX okay */ \
+++ __HANDLE_ITEM(rx_err); /* RX errors */ \
+++ __HANDLE_ITEM(rx_drop); /* RX out of memory */
+++
+++struct atm_aal_stats {
+++#define __HANDLE_ITEM(i) int i
+++ __AAL_STAT_ITEMS
+++#undef __HANDLE_ITEM
+++};
+++
+++
+++struct atm_dev_stats {
+++ struct atm_aal_stats aal0;
+++ struct atm_aal_stats aal34;
+++ struct atm_aal_stats aal5;
+++} __ATM_API_ALIGN;
+++
+++
+++#define ATM_GETLINKRATE _IOW('a',ATMIOC_ITF+1,struct atmif_sioc)
+++ /* get link rate */
+++#define ATM_GETNAMES _IOW('a',ATMIOC_ITF+3,struct atm_iobuf)
+++ /* get interface names (numbers) */
+++#define ATM_GETTYPE _IOW('a',ATMIOC_ITF+4,struct atmif_sioc)
+++ /* get interface type name */
+++#define ATM_GETESI _IOW('a',ATMIOC_ITF+5,struct atmif_sioc)
+++ /* get interface ESI */
+++#define ATM_GETADDR _IOW('a',ATMIOC_ITF+6,struct atmif_sioc)
+++ /* get itf's local ATM addr. list */
+++#define ATM_RSTADDR _IOW('a',ATMIOC_ITF+7,struct atmif_sioc)
+++ /* reset itf's ATM address list */
+++#define ATM_ADDADDR _IOW('a',ATMIOC_ITF+8,struct atmif_sioc)
+++ /* add a local ATM address */
+++#define ATM_DELADDR _IOW('a',ATMIOC_ITF+9,struct atmif_sioc)
+++ /* remove a local ATM address */
+++#define ATM_GETCIRANGE _IOW('a',ATMIOC_ITF+10,struct atmif_sioc)
+++ /* get connection identifier range */
+++#define ATM_SETCIRANGE _IOW('a',ATMIOC_ITF+11,struct atmif_sioc)
+++ /* set connection identifier range */
+++#define ATM_SETESI _IOW('a',ATMIOC_ITF+12,struct atmif_sioc)
+++ /* set interface ESI */
+++#define ATM_SETESIF _IOW('a',ATMIOC_ITF+13,struct atmif_sioc)
+++ /* force interface ESI */
+++#define ATM_GETSTAT _IOW('a',ATMIOC_SARCOM+0,struct atmif_sioc)
+++ /* get AAL layer statistics */
+++#define ATM_GETSTATZ _IOW('a',ATMIOC_SARCOM+1,struct atmif_sioc)
+++ /* get AAL layer statistics and zero */
+++#define ATM_GETLOOP _IOW('a',ATMIOC_SARCOM+2,struct atmif_sioc)
+++ /* get loopback mode */
+++#define ATM_SETLOOP _IOW('a',ATMIOC_SARCOM+3,struct atmif_sioc)
+++ /* set loopback mode */
+++#define ATM_QUERYLOOP _IOW('a',ATMIOC_SARCOM+4,struct atmif_sioc)
+++ /* query supported loopback modes */
+++#define ATM_SETSC _IOW('a',ATMIOC_SPECIAL+1,int)
+++ /* enable or disable single-copy */
+++#define ATM_SETBACKEND _IOW('a',ATMIOC_SPECIAL+2,atm_backend_t)
+++ /* set backend handler */
+++#define ATM_NEWBACKENDIF _IOW('a',ATMIOC_SPECIAL+3,atm_backend_t)
+++ /* use backend to make new if */
+++
+++/*
+++ * These are backend handkers that can be set via the ATM_SETBACKEND call
+++ * above. In the future we may support dynamic loading of these - for now,
+++ * they're just being used to share the ATMIOC_BACKEND ioctls
+++ */
+++#define ATM_BACKEND_RAW 0
+++#define ATM_BACKEND_PPP 1 /* PPPoATM - RFC2364 */
+++#define ATM_BACKEND_BR2684 2 /* Bridged RFC1483/2684 */
+++
+++/* for ATM_GETTYPE */
+++#define ATM_ITFTYP_LEN 8 /* maximum length of interface type name */
+++
+++/*
+++ * Loopback modes for ATM_{PHY,SAR}_{GET,SET}LOOP
+++ */
+++
+++/* Point of loopback CPU-->SAR-->PHY-->line--> ... */
+++#define __ATM_LM_NONE 0 /* no loop back ^ ^ ^ ^ */
+++#define __ATM_LM_AAL 1 /* loop back PDUs --' | | | */
+++#define __ATM_LM_ATM 2 /* loop back ATM cells ---' | | */
+++/* RESERVED 4 loop back on PHY side ---' */
+++#define __ATM_LM_PHY 8 /* loop back bits (digital) ----' | */
+++#define __ATM_LM_ANALOG 16 /* loop back the analog signal --------' */
+++
+++/* Direction of loopback */
+++#define __ATM_LM_MKLOC(n) ((n)) /* Local (i.e. loop TX to RX) */
+++#define __ATM_LM_MKRMT(n) ((n) << 8) /* Remote (i.e. loop RX to TX) */
+++
+++#define __ATM_LM_XTLOC(n) ((n) & 0xff)
+++#define __ATM_LM_XTRMT(n) (((n) >> 8) & 0xff)
+++
+++#define ATM_LM_NONE 0 /* no loopback */
+++
+++#define ATM_LM_LOC_AAL __ATM_LM_MKLOC(__ATM_LM_AAL)
+++#define ATM_LM_LOC_ATM __ATM_LM_MKLOC(__ATM_LM_ATM)
+++#define ATM_LM_LOC_PHY __ATM_LM_MKLOC(__ATM_LM_PHY)
+++#define ATM_LM_LOC_ANALOG __ATM_LM_MKLOC(__ATM_LM_ANALOG)
+++
+++#define ATM_LM_RMT_AAL __ATM_LM_MKRMT(__ATM_LM_AAL)
+++#define ATM_LM_RMT_ATM __ATM_LM_MKRMT(__ATM_LM_ATM)
+++#define ATM_LM_RMT_PHY __ATM_LM_MKRMT(__ATM_LM_PHY)
+++#define ATM_LM_RMT_ANALOG __ATM_LM_MKRMT(__ATM_LM_ANALOG)
+++
+++/*
+++ * Note: ATM_LM_LOC_* and ATM_LM_RMT_* can be combined, provided that
+++ * __ATM_LM_XTLOC(x) <= __ATM_LM_XTRMT(x)
+++ */
+++
+++
+++struct atm_iobuf {
+++ int length;
+++ void *buffer;
+++};
+++
+++/* for ATM_GETCIRANGE / ATM_SETCIRANGE */
+++
+++#define ATM_CI_MAX -1 /* use maximum range of VPI/VCI */
+++
+++struct atm_cirange {
+++ char vpi_bits; /* 1..8, ATM_CI_MAX (-1) for maximum */
+++ char vci_bits; /* 1..16, ATM_CI_MAX (-1) for maximum */
+++};
+++
+++/* for ATM_SETSC; actually taken from the ATM_VF number space */
+++
+++#define ATM_SC_RX 1024 /* enable RX single-copy */
+++#define ATM_SC_TX 2048 /* enable TX single-copy */
+++
+++#define ATM_BACKLOG_DEFAULT 32 /* if we get more, we're likely to time out
+++ anyway */
+++
+++/* MF: change_qos (Modify) flags */
+++
+++#define ATM_MF_IMMED 1 /* Block until change is effective */
+++#define ATM_MF_INC_RSV 2 /* Change reservation on increase */
+++#define ATM_MF_INC_SHP 4 /* Change shaping on increase */
+++#define ATM_MF_DEC_RSV 8 /* Change reservation on decrease */
+++#define ATM_MF_DEC_SHP 16 /* Change shaping on decrease */
+++#define ATM_MF_BWD 32 /* Set the backward direction parameters */
+++
+++#define ATM_MF_SET (ATM_MF_INC_RSV | ATM_MF_INC_SHP | ATM_MF_DEC_RSV | \
+++ ATM_MF_DEC_SHP | ATM_MF_BWD)
+++
+++/*
+++ * ATM_VS_* are used to express VC state in a human-friendly way.
+++ */
+++
+++#define ATM_VS_IDLE 0 /* VC is not used */
+++#define ATM_VS_CONNECTED 1 /* VC is connected */
+++#define ATM_VS_CLOSING 2 /* VC is closing */
+++#define ATM_VS_LISTEN 3 /* VC is listening for incoming setups */
+++#define ATM_VS_INUSE 4 /* VC is in use (registered with atmsigd) */
+++#define ATM_VS_BOUND 5 /* VC is bound */
+++
+++#define ATM_VS2TXT_MAP \
+++ "IDLE", "CONNECTED", "CLOSING", "LISTEN", "INUSE", "BOUND"
+++
+++#define ATM_VF2TXT_MAP \
+++ "ADDR", "READY", "PARTIAL", "REGIS", \
+++ "RELEASED", "HASQOS", "LISTEN", "META", \
+++ "256", "512", "1024", "2048", \
+++ "SESSION", "HASSAP", "BOUND", "CLOSE"
+++
+++
+++#ifndef __KERNEL__
+++#undef __AAL_STAT_ITEMS
+++#else
+++
+++#include <linux/sched.h> /* wait_queue_head_t */
+++#include <linux/time.h> /* struct timeval */
+++#include <linux/net.h>
+++#include <linux/skbuff.h> /* struct sk_buff */
+++#include <linux/uio.h>
+++#include <net/sock.h>
+++#include <asm/atomic.h>
+++
+++#ifdef CONFIG_PROC_FS
+++#include <linux/proc_fs.h>
+++#endif
+++
+++
+++struct k_atm_aal_stats {
+++#define __HANDLE_ITEM(i) atomic_t i
+++ __AAL_STAT_ITEMS
+++#undef __HANDLE_ITEM
+++};
+++
+++
+++struct k_atm_dev_stats {
+++ struct k_atm_aal_stats aal0;
+++ struct k_atm_aal_stats aal34;
+++ struct k_atm_aal_stats aal5;
+++};
+++
+++
+++enum {
+++ ATM_VF_ADDR, /* Address is in use. Set by anybody, cleared
+++ by device driver. */
+++ ATM_VF_READY, /* VC is ready to transfer data. Set by device
+++ driver, cleared by anybody. */
+++ ATM_VF_PARTIAL, /* resources are bound to PVC (partial PVC
+++ setup), controlled by socket layer */
+++ ATM_VF_REGIS, /* registered with demon, controlled by SVC
+++ socket layer */
+++ ATM_VF_BOUND, /* local SAP is set, controlled by SVC socket
+++ layer */
+++ ATM_VF_RELEASED, /* demon has indicated/requested release,
+++ controlled by SVC socket layer */
+++ ATM_VF_HASQOS, /* QOS parameters have been set */
+++ ATM_VF_LISTEN, /* socket is used for listening */
+++ ATM_VF_META, /* SVC socket isn't used for normal data
+++ traffic and doesn't depend on signaling
+++ to be available */
+++ ATM_VF_SESSION, /* VCC is p2mp session control descriptor */
+++ ATM_VF_HASSAP, /* SAP has been set */
+++ ATM_VF_CLOSE, /* asynchronous close - treat like VF_RELEASED*/
+++};
+++
+++
+++#define ATM_VF2VS(flags) \
+++ (test_bit(ATM_VF_READY,&(flags)) ? ATM_VS_CONNECTED : \
+++ test_bit(ATM_VF_RELEASED,&(flags)) ? ATM_VS_CLOSING : \
+++ test_bit(ATM_VF_LISTEN,&(flags)) ? ATM_VS_LISTEN : \
+++ test_bit(ATM_VF_REGIS,&(flags)) ? ATM_VS_INUSE : \
+++ test_bit(ATM_VF_BOUND,&(flags)) ? ATM_VS_BOUND : ATM_VS_IDLE)
+++
+++
+++enum {
+++ ATM_DF_CLOSE, /* close device when last VCC is closed */
+++};
+++
+++
+++#define ATM_PHY_SIG_LOST 0 /* no carrier/light */
+++#define ATM_PHY_SIG_UNKNOWN 1 /* carrier/light status is unknown */
+++#define ATM_PHY_SIG_FOUND 2 /* carrier/light okay */
+++
+++#define ATM_ATMOPT_CLP 1 /* set CLP bit */
+++
+++
+++typedef struct { unsigned long bits; } atm_vcc_flags_t;
+++
+++
+++struct atm_vcc {
+++ atm_vcc_flags_t flags; /* VCC flags (ATM_VF_*) */
+++ short vpi; /* VPI and VCI (types must be equal */
+++ /* with sockaddr) */
+++ int vci;
+++ unsigned long aal_options; /* AAL layer options */
+++ unsigned long atm_options; /* ATM layer options */
+++ struct atm_dev *dev; /* device back pointer */
+++ struct atm_qos qos; /* QOS */
+++ struct atm_sap sap; /* SAP */
+++ void (*push)(struct atm_vcc *vcc,struct sk_buff *skb);
+++ void (*pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* optional */
+++ int (*push_oam)(struct atm_vcc *vcc,void *cell);
+++ int (*send)(struct atm_vcc *vcc,struct sk_buff *skb);
+++ void *dev_data; /* per-device data */
+++ void *proto_data; /* per-protocol data */
+++ struct k_atm_aal_stats *stats; /* pointer to AAL stats group */
+++ wait_queue_head_t sleep; /* if socket is busy */
+++ struct sock *sk; /* socket backpointer */
+++ struct atm_vcc *prev,*next;
+++ /* SVC part --- may move later ------------------------------------- */
+++ short itf; /* interface number */
+++ struct sockaddr_atmsvc local;
+++ struct sockaddr_atmsvc remote;
+++ void (*callback)(struct atm_vcc *vcc);
+++ struct sk_buff_head listenq;
+++ int backlog_quota; /* number of connection requests we */
+++ /* can still accept */
+++ int reply; /* also used by ATMTCP */
+++ /* Multipoint part ------------------------------------------------- */
+++ struct atm_vcc *session; /* session VCC descriptor */
+++ /* Other stuff ----------------------------------------------------- */
+++ void *user_back; /* user backlink - not touched by */
+++ /* native ATM stack. Currently used */
+++ /* by CLIP and sch_atm. */
+++};
+++
+++
+++struct atm_dev_addr {
+++ struct sockaddr_atmsvc addr; /* ATM address */
+++ struct atm_dev_addr *next; /* next address */
+++};
+++
+++
+++typedef struct { unsigned int bits; } atm_dev_flags_t;
+++
+++
+++struct atm_dev {
+++ const struct atmdev_ops *ops; /* device operations; NULL if unused */
+++ const struct atmphy_ops *phy; /* PHY operations, may be undefined */
+++ /* (NULL) */
+++ const char *type; /* device type name */
+++ int number; /* device index */
+++ struct atm_vcc *vccs; /* VCC table (or NULL) */
+++ struct atm_vcc *last; /* last VCC (or undefined) */
+++ void *dev_data; /* per-device data */
+++ void *phy_data; /* private PHY date */
+++ atm_dev_flags_t flags; /* device flags (ATM_DF_*) */
+++ struct atm_dev_addr *local; /* local ATM addresses */
+++ unsigned char esi[ESI_LEN]; /* ESI ("MAC" addr) */
+++ struct atm_cirange ci_range; /* VPI/VCI range */
+++ struct k_atm_dev_stats stats; /* statistics */
+++ char signal; /* signal status (ATM_PHY_SIG_*) */
+++ int link_rate; /* link rate (default: OC3) */
+++ atomic_t refcnt; /* reference count */
+++ spinlock_t lock; /* protect internal members */
+++#ifdef CONFIG_PROC_FS
+++ struct proc_dir_entry *proc_entry; /* proc entry */
+++ char *proc_name; /* proc entry name */
+++#endif
+++ struct list_head dev_list; /* linkage */
+++};
+++
+++
+++/*
+++ * ioctl, getsockopt, setsockopt, and sg_send are optional and can be set to
+++ * NULL. */
+++
+++/* OF: send_Oam Flags */
+++
+++#define ATM_OF_IMMED 1 /* Attempt immediate delivery */
+++#define ATM_OF_INRATE 2 /* Attempt in-rate delivery */
+++
+++struct atmdev_ops { /* only send is required */
+++ void (*dev_close)(struct atm_dev *dev);
+++ int (*open)(struct atm_vcc *vcc,short vpi,int vci);
+++ void (*close)(struct atm_vcc *vcc);
+++ int (*ioctl)(struct atm_dev *dev,unsigned int cmd,void *arg);
+++ int (*getsockopt)(struct atm_vcc *vcc,int level,int optname,
+++ void *optval,int optlen);
+++ int (*setsockopt)(struct atm_vcc *vcc,int level,int optname,
+++ void *optval,int optlen);
+++ int (*send)(struct atm_vcc *vcc,struct sk_buff *skb);
+++ int (*sg_send)(struct atm_vcc *vcc,unsigned long start,
+++ unsigned long size);
+++#if 0 /* keep the current hack for now */
+++ int (*send_iovec)(struct atm_vcc *vcc,struct iovec *iov,int size,
+++ void (*discard)(struct atm_vcc *vcc,void *user),void *user);
+++#endif
+++ int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags);
+++ void (*phy_put)(struct atm_dev *dev,unsigned char value,
+++ unsigned long addr);
+++ unsigned char (*phy_get)(struct atm_dev *dev,unsigned long addr);
+++ void (*feedback)(struct atm_vcc *vcc,struct sk_buff *skb,
+++ unsigned long start,unsigned long dest,int len);
+++ int (*change_qos)(struct atm_vcc *vcc,struct atm_qos *qos,int flags);
+++ int (*proc_read)(struct atm_dev *dev,loff_t *pos,char *page);
+++ struct module *owner;
+++};
+++
+++
+++struct atmphy_ops {
+++ int (*start)(struct atm_dev *dev);
+++ int (*ioctl)(struct atm_dev *dev,unsigned int cmd,void *arg);
+++ void (*interrupt)(struct atm_dev *dev);
+++ int (*stop)(struct atm_dev *dev);
+++};
+++
+++struct atm_skb_data {
+++ struct atm_vcc *vcc; /* ATM VCC */
+++ unsigned long atm_options; /* ATM layer options */
+++};
+++
+++#define ATM_SKB(skb) (((struct atm_skb_data *) (skb)->cb))
+++
+++struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops,
+++ int number,atm_dev_flags_t *flags); /* number == -1: pick first available */
+++struct atm_dev *atm_dev_lookup(int number);
+++void atm_dev_deregister(struct atm_dev *dev);
+++void shutdown_atm_dev(struct atm_dev *dev);
+++void bind_vcc(struct atm_vcc *vcc,struct atm_dev *dev);
+++
+++
+++/*
+++ * This is approximately the algorithm used by alloc_skb.
+++ *
+++ */
+++
+++static inline int atm_guess_pdu2truesize(int pdu_size)
+++{
+++ return ((pdu_size+15) & ~15) + sizeof(struct sk_buff);
+++}
+++
+++
+++static inline void atm_force_charge(struct atm_vcc *vcc,int truesize)
+++{
+++ atomic_add(truesize, &vcc->sk->rmem_alloc);
+++}
+++
+++
+++static inline void atm_return(struct atm_vcc *vcc,int truesize)
+++{
+++ atomic_sub(truesize, &vcc->sk->rmem_alloc);
+++}
+++
+++
+++static inline int atm_may_send(struct atm_vcc *vcc,unsigned int size)
+++{
+++ return (size + atomic_read(&vcc->sk->wmem_alloc)) < vcc->sk->sndbuf;
+++}
+++
+++
+++static inline void atm_dev_hold(struct atm_dev *dev)
+++{
+++ atomic_inc(&dev->refcnt);
+++}
+++
+++
+++static inline void atm_dev_release(struct atm_dev *dev)
+++{
+++ atomic_dec(&dev->refcnt);
+++
+++ if ((atomic_read(&dev->refcnt) == 1) &&
+++ test_bit(ATM_DF_CLOSE,&dev->flags))
+++ shutdown_atm_dev(dev);
+++}
+++
+++
+++int atm_charge(struct atm_vcc *vcc,int truesize);
+++struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size,
+++ int gfp_flags);
+++int atm_find_ci(struct atm_vcc *vcc,short *vpi,int *vci);
+++int atm_pcr_goal(struct atm_trafprm *tp);
+++
+++void atm_async_release_vcc(struct atm_vcc *vcc,int reply);
+++
+++#endif /* __KERNEL__ */
+++
+++#endif
+--- linux-atm-2.4.1.orig/debian/README.br2684
++++ linux-atm-2.4.1/debian/README.br2684
+@@ -0,0 +1,79 @@
++README.br2684
++~~~~~~~~~~~~~
++
++The linux-atm CVS includes a program called br2684 which can be used
++to configure br2684 ATM bridging. On request (#216663), the Debian
++maintainer included br2684 in the source package.
++
++This was done in a way that separates the - unreleased CVS snapshot -
++br2684 program into its own binary package so avoid shipping
++released and unreleased software in the same binary package.
++
++The modified source package (2.4.1-10) was rejected by Debian
++ftpmaster because he found the package too small to warrant its own
++.deb.
++
++Hence, atm-tools-br2684 is not built any more.
++
++You can, however, build your own atm-tools-br2684 package from the
++official Debian source package by following this "script".
++
++(0)
++Install all build dependencies plus autoconf, libtool, automake. If
++#219936 is still unfixed, copy /usr/bin/autoreconf to a local
++directory and apply the following patch after changing "+@@" to "@@"
++in the first line (this was inserted to be able to feed this readme to
++patch to apply the patch given in (1).
++
++--- /usr/bin/autoreconf
+++++ autoreconf
+++@@ -183,7 +183,7 @@
++ {
++ $autoconf .= ' --force';
++ $autoheader .= ' --force';
++- $automake .= ' --force-missing';
+++ $automake .= '';
++ $autopoint .= ' --force';
++ $libtoolize .= ' --force';
++ }
++
++(1) Apply the following patch
++--- configure.in.orig
+++++ configure.in
++@@ -152,6 +152,7 @@
++ m4/Makefile \
++ src/Makefile \
++ src/include/Makefile \
+++ src/br2684/Makefile \
++ src/lib/Makefile \
++ src/test/Makefile \
++ src/debug/Makefile \
++--- debian/rules.orig
+++++ debian/rules
++@@ -11,7 +11,7 @@
++ export PACKAGE=linux-atm
++
++ buildindeppackages=atm-dev
++-buildarchpackages=atm-tools libatm1 libatm1-dev
+++buildarchpackages=atm-tools atm-tools-br2684 libatm1 libatm1-dev
++
++ # generate -ppackage1 -ppackage2 ... commandline for debhelper
++ dhbuildarchpackages=$(addprefix -p,$(buildarchpackages))
++--- src/Makefile.am.orig
+++++ src/Makefile.am
++@@ -1,3 +1,3 @@
++ SUBDIRS = include lib test debug qgen saal sigd maint arpd ilmid man led lane \
++- mpoad switch config extra
+++ mpoad switch config extra br2684
++
++
++(2)
++Invoke autoreconf -f -i
++
++(3)
++create your own changelog entry and your own local version number
++
++(4)
++Build the package as usual
++
++Marc Haber, 2003-11-05
+--- linux-atm-2.4.1.orig/debian/control
++++ linux-atm-2.4.1/debian/control
+@@ -0,0 +1,57 @@
++Source: linux-atm
++Section: net
++Priority: optional
++Maintainer: Peter De Schrijver (p2) <p2@mind.be>
++Build-Depends: debhelper (>> 4.0.0), bison, flex, perl, dpatch, automake1.4
++Standards-Version: 3.6.1
++
++Package: atm-tools
++Architecture: any
++Depends: ${shlibs:Depends}
++Description: Base programs for ATM in Linux, the net-tools for ATM
++ This package provides all the basic programs needed for setting up,
++ monitoring and tuning ATM networks. Such as:
++ * atmsigd, an ATM signal daemon that implements the ATM UNI protocol.
++ * atmtcp, a tool to setup ATM over TCP connections.
++ * atmarpd, an implementation of the ATMARP protocol (RFC1577, RFC1755)
++ * zeppelin, an ATM LAN Emulation client daemon
++ * les and bus, ATM LAN Emulation service daemons
++ .
++ Notice that upstream still flags these tools as experimental software and
++ says that there is still a number of known bugs and issues. The
++ software is, however, in productive use at a number of sites and is
++ working reliably.
++ .
++ Homepage: http://linux-atm.sourceforge.net/
++
++Package: atm-dev
++Depends: libatm1-dev
++Architecture: all
++Section: oldlibs
++Description: Development files for compiling ATM programs (dummy package)
++ This dummy package provides a transition from the previous atm packages.
++ It is provided for backwards compatibility only and may be removedafter
++ the upgrade has completed or when when no other package depend on it.
++
++Package: libatm1
++Section: libs
++Architecture: any
++Depends: ${shlibs:Depends}
++Conflicts: atm-tools (<< 2.4.1-6)
++Description: shared library for ATM (Asynchronous Transfer Mode)
++ Shared libraries needed by ATM (Asynchronous Transfer Mode) related programs
++ .
++ Homepage: http://linux-atm.sourceforge.net/
++
++Package: libatm1-dev
++Section: libdevel
++Architecture: any
++Depends: libc6-dev, libatm1
++Replaces: atm-dev (<< 2.4.1-7)
++Conflicts: atm-dev (<< 2.4.1-7)
++Provides: libatm-dev
++Description: Development files for compiling ATM programs
++ Header files and development libraries for compiling ATM (Asynchronous
++ Transfer Mode) related programs.
++ .
++ Homepage: http://linux-atm.sourceforge.net/
+--- linux-atm-2.4.1.orig/debian/atm-tools-br2684.dirs
++++ linux-atm-2.4.1/debian/atm-tools-br2684.dirs
+@@ -0,0 +1,2 @@
++usr/sbin
++usr/share/man/man8
+--- linux-atm-2.4.1.orig/debian/rules
++++ linux-atm-2.4.1/debian/rules
+@@ -0,0 +1,136 @@
++#!/usr/bin/make -f
++# Sample debian/rules that uses debhelper.
++# GNU copyright 1997 to 1999 by Joey Hess.
++
++# Uncomment this to turn on verbose mode.
++#export DH_VERBOSE=1
++
++# This is the debhelper compatability version to use.
++export DH_COMPAT=4
++
++export PACKAGE=linux-atm
++
++buildindeppackages=atm-dev
++buildarchpackages=atm-tools libatm1 libatm1-dev
++
++# generate -ppackage1 -ppackage2 ... commandline for debhelper
++dhbuildarchpackages=$(addprefix -p,$(buildarchpackages))
++dhbuildindeppackages=$(addprefix -p,$(buildindeppackages))
++
++include /usr/share/dpatch/dpatch.make
++
++configure: configure-stamp
++configure-stamp:
++ dh_testdir
++ ./configure --prefix /usr --mandir /usr/share/man --sysconfdir /etc
++ touch configure-stamp
++
++build: configure-stamp build-stamp
++build-stamp: patch-stamp
++ dh_testdir
++
++ # Add here commands to compile the package.
++ $(MAKE) $(EXTRA_VARS)
++ cat debian/copyright.header COPYING > debian/copyright
++
++ touch build-stamp
++
++clean: clean1 unpatch
++clean1:
++ dh_testdir
++ dh_testroot
++ rm -f build-stamp configure-stamp
++
++ # Add here commands to clean up after the build process.
++ -$(MAKE) distclean
++
++ dh_clean
++ rm -rf debian/atm-tools.8 debian/copyright
++
++install: build
++ dh_testdir
++ dh_testroot
++ dh_clean -k
++ dh_installdirs
++
++ # Add here commands to install the package into debian/atm-tools
++ $(MAKE) DESTDIR=`pwd`/debian/tmp install
++
++ # manpages
++ /usr/bin/pod2man --section=8 --release="atm-tools $(PKG_VER)" --lax \
++ --center="Debian GNU/Linux" debian/atm-tools.pod > debian/atm-tools.8
++
++ ln -s atm-tools.8 debian/tmp/usr/share/man/man8/aread.8
++ ln -s atm-tools.8 debian/tmp/usr/share/man/man8/awrite.8
++ ln -s atm-tools.8 debian/tmp/usr/share/man/man8/enitune.8
++ ln -s atm-tools.8 debian/tmp/usr/share/man/man8/ilmid.8
++ ln -s atm-tools.8 debian/tmp/usr/share/man/man8/saaldump.8
++ ln -s atm-tools.8 debian/tmp/usr/share/man/man8/sonetdiag.8
++ ln -s atm-tools.8 debian/tmp/usr/share/man/man8/ttcp_atm.8
++ ln -s atm-tools.8 debian/tmp/usr/share/man/man8/zntune.8
++
++# Build architecture-independent files here.
++binary-indep: build install
++ dh_testdir $(dhbuildindeppackages)
++ dh_testroot $(dhbuildindeppackages)
++ dh_install $(dhbuildindeppackages)
++
++# dh_installdebconf $(dhbuildindeppackages)
++ dh_installdocs $(dhbuildindeppackages)
++ dh_installmenu $(dhbuildindeppackages)
++# dh_installlogrotate $(dhbuildindeppackages)
++# dh_installemacsen $(dhbuildindeppackages)
++# dh_installpam $(dhbuildindeppackages)
++# dh_installmime $(dhbuildindeppackages)
++ dh_installinit $(dhbuildindeppackages) --init-script=atm -- start 34 0 6 . start 39 S .
++ dh_installcron $(dhbuildindeppackages)
++ dh_installman $(dhbuildindeppackages)
++ dh_installinfo $(dhbuildindeppackages)
++# dh_undocumented $(dhbuildindeppackages)
++ dh_installchangelogs -i ChangeLog $(dhbuildpackages)
++ dh_link $(dhbuildindeppackages)
++ dh_strip $(dhbuildindeppackages)
++ dh_compress $(dhbuildindeppackages)
++ dh_fixperms $(dhbuildindeppackages)
++ dh_makeshlibs $(dhbuildindeppackages)
++ dh_installdeb $(dhbuildindeppackages)
++# dh_perl $(dhbuildindeppackages)
++ dh_shlibdeps $(dhbuildindeppackages)
++ dh_gencontrol $(dhbuildindeppackages)
++ dh_md5sums $(dhbuildindeppackages)
++ dh_builddeb $(dhbuildindeppackages)
++
++# Build architecture-dependent files here.
++binary-arch: build install
++ dh_testdir $(dhbuildarchpackages)
++ dh_testroot $(dhbuildarchpackages)
++ dh_install $(dhbuildarchpackages)
++
++# dh_installdebconf $(dhbuildarchpackages)
++ dh_installdocs $(dhbuildarchpackages)
++ dh_installmenu $(dhbuildarchpackages)
++# dh_installlogrotate $(dhbuildarchpackages)
++# dh_installemacsen $(dhbuildarchpackages)
++# dh_installpam $(dhbuildarchpackages)
++# dh_installmime $(dhbuildarchpackages)
++ dh_installinit $(dhbuildarchpackages) --init-script=atm -- start 34 0 6 . start 39 S .
++ dh_installcron $(dhbuildarchpackages)
++ dh_installman $(dhbuildarchpackages)
++ dh_installinfo $(dhbuildarchpackages)
++# dh_undocumented $(dhbuildarchpackages)
++ dh_installchangelogs -a ChangeLog $(dhbuildarchpackages)
++ dh_link $(dhbuildarchpackages)
++ dh_strip $(dhbuildarchpackages)
++ dh_compress $(dhbuildarchpackages)
++ dh_fixperms $(dhbuildarchpackages)
++ dh_makeshlibs $(dhbuildarchpackages)
++ dh_installdeb $(dhbuildarchpackages)
++# dh_perl $(dhbuildarchpackages)
++ dh_shlibdeps -a -L libatm1 -l debian/libatm1/lib $(dhbuildarchpackages)
++ dh_gencontrol $(dhbuildarchpackages)
++ dh_md5sums $(dhbuildarchpackages)
++ dh_builddeb $(dhbuildarchpackages)
++
++binary: binary-indep binary-arch
++.PHONY: build binary-indep binary-arch binary install configure
++ get-2684 patch unpatch clean1
+--- linux-atm-2.4.1.orig/debian/atm-tools-br2684.install
++++ linux-atm-2.4.1/debian/atm-tools-br2684.install
+@@ -0,0 +1 @@
++debian/tmp/usr/sbin/br2684ctl usr/sbin
+--- linux-atm-2.4.1.orig/debian/atm-tools-br2684/usr/share/doc/atm-tools-br2684/changelog.Debian
++++ linux-atm-2.4.1/debian/atm-tools-br2684/usr/share/doc/atm-tools-br2684/changelog.Debian
+@@ -0,0 +1,206 @@
++linux-atm (2.4.1-16) unstable; urgency=low
++
++ * Fix build problem with gcc 3.4 (Closes: #259422)
++
++ -- Peter De Schrijver (p2) <p2@mind.be> Thu, 15 Jul 2004 14:28:10 +0200
++
++linux-atm (2.4.1-15) unstable; urgency=low
++
++ * Updated descriptions (Closes: #239161)
++
++ -- Peter De Schrijver (p2) <p2@mind.be> Sun, 4 Apr 2004 21:10:20 +0200
++
++linux-atm (2.4.1-14) unstable; urgency=low
++
++ * Fix symlink for /usr/lib/libatm.so (Closes: #221011)
++
++ -- Peter De Schrijver (p2) <p2@mind.be> Sun, 7 Dec 2003 21:53:19 +0100
++
++linux-atm (2.4.1-13) unstable; urgency=low
++
++ * Previous version fixed #217259, but no changelog entry (Closes: #217259)
++ * Previous version fixed #216662, but no changelog entry (Closes: #216662)
++ * Added missing build dependency on automake1.4 (Closes: #221120, #221284)
++ * New Maintainer (Closes: #206982)
++
++ -- Peter De Schrijver (p2) <p2@mind.be> Mon, 17 Nov 2003 23:03:58 +0100
++
++linux-atm (2.4.1-12) unstable; urgency=low
++
++ * don't build atm-tools-br2684 by default. Thanks to ftpmaster for
++ not allowing the package to be in Debian.
++ * Since we don't build atm-tools-br2684 any more, revert back to
++ autotools output from 2.4.1-9
++ * Add README.br2684 documenting a way to build the package locally.
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Wed, 5 Nov 2003 21:31:42 +0000
++
++linux-atm (2.4.1-11) experimental; urgency=low
++
++ * Build-Depend on dpatch
++ * dpatch br2684 header files from later libc for old libc (woody)
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Wed, 29 Oct 2003 19:05:07 +0000
++
++linux-atm (2.4.1-10) experimental; urgency=low
++
++ * add br2684 to package (closes: #216663)
++ * autoreconf to actually build br2684
++ * have libatm1-dev provide libatm-dev (closes: #216662)
++ * move lib symlink to libatm1-dev as well (closes: #217259)
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Thu, 23 Oct 2003 17:55:43 +0000
++
++linux-atm (2.4.1-9) unstable; urgency=low
++
++ * put libatm1-dev in libdevel (closes: #213170)
++ * make sure that new descriptions actually make it into the package
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Thu, 9 Oct 2003 17:08:10 +0000
++
++linux-atm (2.4.1-8) unstable; urgency=low
++
++ * build arch-indep package as targets of binary-indep (closes: #212124)
++ * use dh_installdocs to install files to libatm1-dev/docs
++ * symlink shared lib to usr/bin (closes: #213146)
++ * Use better long descriptions. Thanks to Javier (closes: #209427)
++ Fernandez-Sanguino (closes: #209612)
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Sun, 28 Sep 2003 19:29:08 +0000
++
++linux-atm (2.4.1-7) unstable; urgency=low
++
++ * libatm1 now conflicts with atm-tools (<< 2.4.1-6) (closes: #208170)
++ * armarp now writes output to stdout.
++ * add atm-dev as empty transitional package to help upgrades
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Tue, 2 Sep 2003 09:20:33 +0000
++
++linux-atm (2.4.1-6) unstable; urgency=low
++
++ * split off shared libraries to libatm1
++ * rename atm-dev to libatm1-dev
++ * Standards-Version: 3.6.1
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Tue, 26 Aug 2003 15:46:27 +0000
++
++linux-atm (2.4.1-5) unstable; urgency=low
++
++ * move *.a and *.la to usr/lib (closes: #199506).
++ * let atm-dev depend on atm-tools to avoid dangling /lib/libatm.so
++ symlink.
++ * Standards-Version: 3.5.6
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Wed, 30 Jul 2003 11:46:19 +0000
++
++linux-atm (2.4.1-4) unstable; urgency=low
++
++ * add Build-Depends: on automake1.4
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Wed, 11 Jun 2003 16:58:21 +0000
++
++linux-atm (2.4.1-3) unstable; urgency=low
++
++ * rebuilding libtool broke src/test/Makefile.in. Applied fix to
++ Makefile.am and re-built again.
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Wed, 11 Jun 2003 11:05:26 +0000
++
++linux-atm (2.4.1-2) unstable; urgency=low
++
++ * rebuild configure script with new libtool (closes: #196909)
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Tue, 10 Jun 2003 21:01:50 +0000
++
++linux-atm (2.4.1-1) unstable; urgency=low
++
++ * new upstream source
++ * remove atmarp and atmarpd from /usr/sbin as they are already in
++ /sbin (closes: #196216)
++ * lintian fixes
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Mon, 9 Jun 2003 16:03:45 +0000
++
++linux-atm (2.4.0-5) unstable; urgency=low
++
++ * Fix for src/test/Makefile.in to allow building on hppa and ia64
++ which the fix introduced to 2.4.0-4 broke. Thanks to Goswin
++ Brederlow.
++ * Move init.d priority to that atmarpd is started before network
++ interfaces are started.
++ * Move atmarpd and libatm to /sbin and /lib to allow atmarpd to be
++ started before /usr is mounted.
++ * use dh_install instead of dh_movefiles.
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Sat, 24 Aug 2002 15:13:48 +0000
++
++linux-atm (2.4.0-4) unstable; urgency=low
++
++ * new maintainer
++ * Fix for src/test/Makefile.in to allow building on sparc.
++ Thanks to Patrick Mauritz. (closes: #144225).
++ * added pseudo-manpage for manpage-less binaries.
++ * removed rpath by changing configure and make install paramaters
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Fri, 16 Aug 2002 20:39:05 +0000
++
++linux-atm (2.4.0-3) unstable; urgency=HIGH
++
++ * Re-ran libtoolize.
++ Closes: #143522
++
++ * Previous version Closes: #135328
++
++ -- Russell Coker <russell@coker.com.au> Fri, 19 Apr 2002 01:55:00 +0200
++
++linux-atm (2.4.0-2) unstable; urgency=HIGH
++
++ * Put a "grep -v EMAXERRNO" into the build process to deal with mipsel and
++ the "#ifdef __KERNEL__" it has in it's /usr/include/asm/errno.h .
++
++ -- Russell Coker <russell@coker.com.au> Thu, 18 Apr 2002 19:56:00 +0200
++
++linux-atm (2.4.0-1) unstable; urgency=HIGH
++
++ * New upstream version which changes source package name.
++ Closes: #138911
++
++ -- Russell Coker <russell@coker.com.au> Mon, 18 Mar 2002 17:42:00 +0100
++
++atm (0.79-4) unstable; urgency=low
++
++ * Added build-depends on flex.
++ Closes: #111072
++
++ * Made the atm tools use a shared object to save space.
++
++ * Fixed the copyright file and put all copyright details in both packages.
++
++ * Added support for easy building with different kernel headers.
++ Closes: #110249
++
++ -- Russell Coker <russell@coker.com.au> Sun, 7 Oct 2001 14:11:33 +0200
++
++atm (0.79-3) unstable; urgency=low
++
++ * Created /etc/init.d/atm to start and stop atmarpd.
++ Closes: #110252
++
++ * Added build-depends on bison.
++ Closes: #110576
++
++ -- Russell Coker <russell@coker.com.au> Fri, 31 Aug 2001 15:21:44 +0200
++
++atm (0.79-2) unstable; urgency=low
++
++ * Changed the main package name to atm-tools to indicate that it doesn't
++ provide ATM (gotta have the kernel support), it just has the daemons and
++ utilities.
++
++ -- Russell Coker <russell@coker.com.au> Sat, 25 Aug 2001 17:55:00 +0200
++
++atm (0.79-1) unstable; urgency=low
++
++ * Initial Release.
++
++ -- Russell Coker <russell@coker.com.au> Fri, 24 Aug 2001 17:31:00 +0200
+--- linux-atm-2.4.1.orig/debian/atm-tools-br2684/usr/share/doc/atm-tools-br2684/changelog
++++ linux-atm-2.4.1/debian/atm-tools-br2684/usr/share/doc/atm-tools-br2684/changelog
+@@ -0,0 +1,3299 @@
++Version 2.4.0 to 2.4.1 (25-APR-2003)
++=====================
++
++Bug fixes
++---------
++
++ - vsprintf's changed to vsnprintf's to prevent possible stack overflows
++
++
++Version 0.79 to 2.4.0 (18-OCT-2001)
++=====================
++
++Bug fixes
++---------
++
++ - defined 'now' in src/lib/timer.c
++ - ia64 build fix for ASN (Chas Williams)
++
++Other changes
++-------------
++
++ - In general, the source tree was rearranged and the old cruft was removed
++ - Old ad hoc build system replaced in favor of a standardized autoconfiscation
++ - Build configuration options are now controlled by 'configure' script instead
++ of changes to the previous 'Rules.make' file
++ - libatm and libatmd merged into one lib: libatm
++ - Both static and shared libraries are built by default. Binaries now built
++ with shared library by default.
++ - Sample atmsigd.conf and hosts.atm are now installed when doing 'make install'
++ - RPM spec file is now available in src/extra/
++ - New RedHat init scripts available in src/config/init-redhat/ (John Strange)
++ (old RedHat 4.0 scripts removed)
++ - ATM on Linux HOWTO now included in doc/ (much derived from usage.tex). We
++ will publish this on the home page as well as linuxdoc.org
++ - tcpdump and libpcap ATM patches/build removed (they have been integrated into
++ their respective packages; see www.tcpdump.org)
++ - ATM Name Service (ANS) files coalesced into src/extra/ANS
++ - ANS bind patch upgraded to bind-4.9.8 (untested)
++ - rtf2e164_cc.pl removed in favor of src/extra/ANS/pdf2e164_cc.pl. The ITU no
++ longer provides E.164 country codes in RTF format. PDF used instead.
++
++
++Version 0.78 to 0.79 (15-AUG-2001)
++====================
++
++Bug fixes
++---------
++
++- uni.c fix for newer versions of gcc
++- mpoad/io.c quick fix for undefined OPEN_MAX
++
++
++Version 0.77 to 0.78 (7-JUL-2000)
++====================
++
++Bug fixes
++---------
++
++ - skb_migrate wasn't protected against functions accessing the list via
++ skb->list
++ - removal of MOD_xxx races in FORE 200E and atmtcp (by Jeff Garzik)
++ - CONFIG_ATM_NICSTAR_USE_IDT77105 set NEED_SUNI_MX instead of
++ NEED_IDT77105_MX (fix from mainstream)
++ - ambassador.c: changed string concatenation and offset calculation breaking
++ compilation with gcc 2.96 (by Jakub Jelinek)
++ - nicstar.c: various locking fixes for SMP (by Rui Prior)
++ - LANE vs. bridging build conflict solved (from mainstream)
++ - %%u instead of %u in mpc.c
++ - fixed formatting of /proc/net/atm/svc
++ - /proc/net/atm/clip always added + after public address, not only if followed
++ by private address
++ - atmsigd now returns EINVAL if attempting to change max_sdu
++ - atm_change_qos now calls adjust_to for additional parameter checking
++ - sendmsg now returns error if size > max_sdu (reported by Alan Kennington)
++ - removed explicit defaults in Config.in (by Christoph Hellwig)
++ - Fore200E: removed #ifdef MODULE
++ - ipcommon.c didn't export skb_migrate to modules (by Mitchell Blank)
++ - ENI: /proc/net/atm/eni:* claimed backlog was in bytes instead of packets
++ - br, bw, window: changed variables receiving possibly negative return values
++ from size_t to ssize_t (reported by Alan Kennington)
++ - LANE: fixed stray errors on lack of ATM address, ATM address change, or ESI
++ change (by Heikki Vatiainen)
++ - LANE: could loop forwever when trying to connect to LECS (by Heikki
++ Vatiainen)
++
++New features
++------------
++
++ - upgraded to the 2.4.0-test3-pre4 kernel
++
++Other changes
++-------------
++
++ - as_reject now returns the errno value in msg->reply
++ - removed save_qos hack in svc_change_qos
++ - atmsigd: sap_encode now always includes both max_sdu fields, even if one
++ contains the null value for some reason (by Mohsen Souissi)
++ - PCI updates for Ambassador, FORE 200E, Horizon, Iphase, nicstar, ENI, and
++ ZATM (by Jeff Garzik)
++ - removal of unnecessary #ifdef MODULE for nicstar, idt77105, and FORE 200E
++ (by Jeff Garzik)
++ - generalized skb_migrate to append to an arbitrary sk_buff list
++ - iphase.c: timer initialization cleanup (from mainstream)
++ - clip: dev->name initialization change (from mainstream)
++ - idt77105: cleaned up timer initialization
++ - clip.c: some general cleanup
++ - removed redundant return in clip.c (by Heikki Vatiainen)
++ - changed atm_change_qos to static
++ - fore200e.c: re-enabled anti-unloading code
++ - lec.c: now drops packets on overrun instead of growing infinite queue (by
++ Heikki Vatiainen)
++ - COPYING still mentioned the old led code with partial DEC copyright
++ (reported by Chris Pimlott)
++ - Horizon: removed const warning by casting to (hrz_flags *)
++ - Iphase: tried to print unsigned long with %x when errors are enabled
++ - ENI: eni_send tries to use do_tx instead of tasklet_schedule to reduce delay
++ - ENI: removed eni_dev->backlog_len (information is already in backlog->qlen)
++ - changed the kernel source tree references from .gz to .bz2 compression
++ - changed mkdiff to allow more flexible selection of additional patch
++
++
++Version 0.76 to 0.77 (29-APR-2000)
++====================
++
++Bug fixes
++---------
++
++ - atmaddr.8, atmarp.8, atmdump.8, atmloop.8, esi.8 didn't print all options
++ in bold
++ - atmsigd crashed if an interface had more than one local ATM address
++ - atmarpd continued to use VCs after closing if they were closed because
++ ATMARP_SETENTRY failed (reported by Joseph Gooch)
++
++New features
++------------
++
++ - upgraded to the 2.3.99-pre6 kernel
++
++Other changes
++-------------
++
++ - CLIP now uses NETDEV_GOING_DOWN instead of NETDEV_DOWN; also avoids
++ "clip_device_event: unknown event 9" warning
++ - added ubr:pcr example to qos(7)
++ - added -V option to atmaddr, atmarp, atmarpd, atmloop, atmsigd, atmtcp, esi,
++ ilmid
++ - sock->sk->sleep now points to vcc->sleep (by Alexander Viro)
++ - CLIP: ATMARP server now reponds to query for local IP address (suggested by
++ Joseph Gooch)
++ - updated t2a.pl
++
++
++Version 0.75 to 0.76 (13-APR-2000)
++====================
++
++Bug fixes
++---------
++
++ - ttcp_atm declared port as "short" instead of "unsigned short", yielding
++ confusing diagnostic output
++
++New features
++------------
++
++ - upgraded to the 2.3.99-pre5 kernel
++
++Other changes
++-------------
++
++ - eliminated eni_send-tasklet synchronization
++ - PCA200: merged unconditional #inclusion of linux/pci.h from pre5
++
++
++Version 0.74 to 0.75 (7-APR-2000)
++====================
++
++Bug fixes
++---------
++
++ - ENI: moved send operation into tasklet to correct synchronization (reported
++ by Heikki Vatiainen)
++ - MPOA: possible deadlock fix (by Heikki Vatiainen)
++ - atm_vcc_flags_t was too small on PPC, causing an overlap with vcc->family
++ (fixed by Chas Williams)
++ - CLIP: needs spin_lock_irqsave instead of only spin_lock (by Rui Prior)
++ - CLIP: clip_push may be called from an interrupt, so the kfree_skb has to
++ become dev_kfree_skb_any (by Heikki Vatiainen)
++
++Other changes
++-------------
++
++ - removed INCLUDES from atm/ilmid/asn1/Makefile (suggested by Jean Marc
++ Lacroix)
++ - atm/maint/Makefile no longer special-cases atmdiag.c (suggested by Jean Marc
++ Lacroix)
++
++
++Version 0.73 to 0.74 (2-APR-2000)
++====================
++
++Bug fixes
++---------
++
++ - atm_poll tried to sleep on two wait queues, which is no longer possible.
++ Removed vcc->wsleep to solve this. (Reported by Joseph Gooch)
++ - lec.c:lec_arp_clear_vccs changed the VCC flags of the wrong VCC, fortunately
++ only in commented-out code
++ - major revision of MPOA ingress and egress cache locking (Heikki Vatiainen)
++
++Other changes
++-------------
++
++ - removed last remnants of bogus bridging lock from lane_mpoa_init.c
++ (reported by Heikki Vatiainen)
++ - removed last traces of TNET1570A driver
++ - atmdev_init still knew about ENI, but ENI now uses new-style initialization
++ - improved Fore 200E configuration to catch useless settings already at
++ configuration time (by Christophe Lizzi)
++
++
++Version 0.72 to 0.73 (29-MAR-2000)
++====================
++
++Bug fixes
++---------
++
++ - ambassador.c and horizon.c had module loading races (fixed by Giuliano
++ Procida)
++ - fore200e: one set_bit was accidently converted to clear_bit, preventing VCs
++ from being opened (fixed by Christophe Lizzi)
++
++Other changes
++-------------
++
++ - fore200e: moved interrupt handler work to tasklet (by Christophe Lizzi)
++ - fore200e: fixed SBUS DMA direction flags (by Christophe Lizzi)
++ - fore200e: the compile no longer fails when the driver is compiled without
++ any hardware support (and displays a warning; by Christophe Lizzi)
++ - oops, atm/README was lagging behind a few versions
++
++
++Version 0.71 to 0.72 (25-MAR-2000)
++====================
++
++Bug fixes
++---------
++
++ - fore200e.h and lec.h didn't #include <linux/config.h> (fixed by David S.
++ Miller ?)
++ - atmloop.c always assumed -q to be present
++
++New features
++------------
++
++ - upgraded to the 2.3.99-pre3 kernel
++
++Other changes
++-------------
++
++ - kernel patch still included wd.c hack (reported by David S. Miller)
++ - removed bogus initialization of skb->rx_dev (spotted by Alexey Kuznetsov)
++ - removed bogus lane_bridge_hook_lock (by Heikki Vatiainen)
++ - added sparc64 support for ATM_QUERYLOOP (by Christophe Lizzi)
++ - minor Fore driver cleanup (by Christophe Lizzi)
++ - eni.c: moved interrupt handler work to tasklet
++
++
++Version 0.70 to 0.71 (21-MAR-2000)
++====================
++
++Bug fixes
++---------
++
++ - eni.c: fixed potential SMP deadlock on tx_wait
++ - clip.c and lec.c didn't initialize skb->rx_dev
++ - net/atm/svc.c:svc_connect left wait entry in queue on return in some cases
++ - idiot bug in skb_migrate caused weird crashes
++ - atmloop usage erroneously claimed -s was optional
++
++New features
++------------
++
++ - upgraded to the 2.3.99-pre2 kernel
++ - added atmloop.8 man page
++ - added enqueuing result NET_XMIT_BYPASS for qdiscs that send packets on a
++ path without dequeue (e.g. sch_atm)
++
++Other changes
++-------------
++
++ - ambassador.c: removed warnings when compiling with CONFIG_SMP (by Giuliano
++ Procida)
++ - changed drivers/atm target from atm.a to atm.o, to make initcalls work
++ - converted eni.c to use pci_register_driver and initcall
++ - cleaned up #ifdef hell in net/atm/signaling.c:sigd_put_skb
++
++
++Version 0.69 to 0.70 (20-MAR-2000)
++====================
++
++Bug fixes
++---------
++
++ - LEC compilation as a module still left it in the kernel
++
++Other changes
++-------------
++
++ - moved LANE-bridging interface code from lec.c to lane_mpoa_init.c (by
++ Heikki Vatiainen)
++ - made SONET and ATM statistics counters atomic to avoid cli() when reading
++ (not updated: similar mechanism in idt77105.c and private shadow statistics
++ of ambassador.c)
++ - changed access to VCC and device flags (ATM_VF_* and ATM_DF_*) to bit set
++ operations
++ - changed flag types to structs to fail compilation of old code
++ - changed last argument of atm_dev_register to a pointer to a bit set for
++ easier migration
++ - net/atm/*.c: eliminated all sleep_on and cli (except in lec.c)
++ - ditto for eni.c and suni.c
++ - corrected indentation of some "permanent" debugging code in zatm.c
++ - made skb_migrate partially atomic, obsoleting yet another cli() in clip.c
++
++
++Version 0.68 to 0.69 (19-MAR-2000)
++====================
++
++Bug fixes
++---------
++
++ - ambassador.c: corrected location of initial PLX window for use on Alpha (by
++ Giuliano Procida)
++ - zeppelin: fixed address initialization (found by Christophe Lizzi)
++ - atmsigd.conf man page erroneously described the option "q.2963.1" as
++ "q2963_1"
++ - LANE didn't compile when bridging was enabled (fixed by Heikki Vatiainen;
++ note that bridging also needs an update which is being merged via the
++ mainstream kernel)
++
++New features
++------------
++
++ - atmsigd: added command-line option -u to set the UNI mode
++ - added ioctl ATM_QUERYLOOP to determine supported loopback modes
++ - added atmloop(8) option -q
++
++Other changes
++-------------
++
++ - added CREDITS entry of Giuliano Procida
++ - various cosmetic changes to horizon.c (by Giuliano Procida)
++ - ambassador.c: various bits of cleanup (by Giuliano Procida)
++ - added -S <tos> option to ttcp_atm to set the IPv4 TOS byte (this is not
++ really related to ATM)
++ - changed loopback mode values to a bit set
++ - idt77105_ioctl: returned sizeof(int) instead of 0 on ATM_GETLOOP
++ - added phy_ops->stop to suni.c and uPD98402_stop, cleaned up suni.c in the
++ process
++ - removed (very obsolete) mmuio.o from net/atm/Makefile
++
++
++Version 0.67 to 0.68 (28-FEB-2000)
++====================
++
++Bug fixes
++---------
++
++ - removed potential dev_kfree_skb(NULL) from *_send of eni.c, zatm.c, iphase.c
++ - eni.c, zatm.c, iphase.c sometimes returned PCI error codes instead of errno
++ codes
++ - arpd/io.c could try to de-reference entry->addr with addr == NULL (fixed by
++ Thomas Dietz)
++ - LANE copied more than dev->addr_len address bytes (fixed by Heikki
++ Vatiainen)
++ - sch_atm didn't remove filters on destroy
++ - fixed typo in esi.c error message
++ - esi.8 claimed to be the man page of atmarp, and it wasn't installed
++ - added checking for VPI/VCI when sending AAL0 cells (by Mitchell Blank)
++ - atmtcp allowed sending on receive-only VCs
++ - various ioctl permission checks were missing (fixed by Mitchell Blank)
++ - fore200e.c and horizon.c didn't always free skbs on send error (fixed by
++ Mitchell Blank)
++ - included an ugly hack to fix the wd.c driver that was broken around 2.3.47
++ (not related to ATM at all...)
++
++New features
++------------
++
++ - upgraded to the 2.3.48 kernel
++ - added device-independent SAR/PHY loopback setting interface (with many good
++ ideas from Greg Banks and Mitchell Blank), and removed old loopback ioctls
++ - new utility atmloop to set loopback mode
++ - added "stop" to atmphy_ops (requested by Mitchell Blank)
++
++Other changes
++-------------
++
++ - mkdiff can now also use pre-release kernels
++ - changed *kfree_skb to dev_kfree_skb_{irq,any} in eni.c, zatm.c, and raw.c,
++ where necessary (with help from Heikki Vatiainen)
++ - changed {dev_,}kfree_skb to dev_kfree_skb_any in ambassador.c, horizon.c,
++ iphase.c, and nicstar.c (needs further cleanup)
++ - softnet updates for LANE (by Heikki Vatiainen)
++ - fixed firmeware license of Fore 200E driver and general 0.46/0.47 updates
++ (Christophe Lizzi)
++ - more CREDITS file additions
++ - softnet updates for sch_atm
++ - softnet updates for CLIP (also cleaned up flow control for > 1 VCC/itf;
++ reported by Alexey Kuznetsov)
++ - updated documentation for iproute2-2.2.4-now-ss000225 and streamlined the
++ build procedure
++ - PCI DMA updates for ENI driver
++ - changed the default install location of executables and man pages from
++ /usr/local to /usr
++ - make install no longer installs align, aping, br, bw, delay, isp, svctor,
++ sw_debug, sw_tcp, swc, and window
++ - eni.c: made highly controversial aal5 = ... line more readable
++ - moved /proc/atm to /proc/net/atm
++ - added vcc->send function to allow for AAL-specific processing (may be set
++ to dev->ops->send)
++ - atm_do_connect_dev now calls bind_vcc before AAL initialization to make
++ vcc->dev available
++ - change_qos no longer allows changing of AAL or traffic class (by Mitchell
++ Blank)
++ - changes for new loopback support to fore200e driver and sparc64 code (by
++ Christophe Lizzi)
++
++
++Version 0.66 to 0.67 (2-FEB-2000)
++====================
++
++New features
++------------
++
++ - upgraded to 2.3.42
++ - added sunimode utility to set SUNI loopback mode (by Christophe Lizzi)
++
++Other changes
++-------------
++
++ - removed unused variable warning in net/sched/sch_atm.c
++ - changed ENI_SETMULT from ATMIOC_SARPRV+1 to ATMIOC_SARPRV+7
++ - changed atmarpd's complaint about VCC-less non-ATMARP-server entries from
++ DIAG_ERROR to DIAG_INFO (the condition is okay for an ATMARP server)
++
++
++Version 0.65 to 0.66 (31-JAN-2000)
++====================
++
++Bug fixes
++---------
++
++ - atmsigd crashed on reception of as_accept, etc., because of inverted NULL
++ pointer test (reported by Kevin Vargo, Rui Prior, fixed by Julian Cable)
++ - fixed various SPARC build problems (by Christophe Lizzi)
++ - atmsigd insisted that calling party number is local in switch mode
++ - debug switch didn't initialize any ports
++ - net/atm/signaling.c:sigd_enq didn't properly zero the message, yielding
++ kernel pointers partially containing junk
++ - accept(2) didn't copy local ATM address to VCC descriptor (reported by
++ Pedro Brandao)
++ - ilmid/io.c didn't compile on SPARC (reported by Christophe Lizzi)
++ - usage.txt didn't define the %: macro, leaving garbage in usage.txt
++
++New features
++------------
++
++ - upgraded to 2.3.41
++ - Fore 200E driver now also works for SBA-200E (by Christophe Lizzi)
++
++Other changes
++-------------
++
++ - added various CREDITS entries
++ - changed TIOC{IN,OUT}Q to SIOC{IN,OUT}Q (no user space rebuild required;
++ the values are identical)
++ - added script atm/switch/tcp/mkfiles for automatic extraction of
++ configuration files
++ - atmsigd called ATM_GETLINKRATE "ATM_GETLINERATE" in complaints
++ - atmsigd tried to obtain link speed in switch mode, although it's not used
++ - Ambassador NIC: various files still had the wrong copyright/licensing text
++ (patch by Giuliano Procida)
++
++
++Version 0.64 to 0.65 (21-JAN-2000)
++====================
++
++Bug fixes
++---------
++
++ - fixed 32/64 bit %p formatting problem in /proc/atm/vc
++ - atmtcp: fixed RX/TX statistics (by Jens Axboe)
++ - sparc64-specific ioctl 32/64 bit marshalling fixes (by Christophe Lizzi,
++ with further improvements by Jens Axboe)
++ - zeppelin -l option handling (reported by Mike Prudence, fixed by Heikki
++ Vatiainen)
++ - mkpatch didn't include drivers/atm/eni.h
++ - updated eni.h (tx->backlog_len was missing)
++ - fixed various uint32_t build problems of user space tools by including
++ atm.h before anything other ATM headers (first reported by Rashmi Dravid)
++ - "natmtcp virtual" didn't parse the command line properly
++ - natmtcp's TCP link changed VPI/VCI to 0.0 on close
++ - CLIP: fixed crash after sending ARP (reported by Rui Prior)
++
++New features
++------------
++
++ - upgraded to 2.3.40 (with help from Jens Axboe)
++ - added sparc64 changes for ENI driver (by Heikki Vatiainen)
++ - added the Fore PCA-200E(/SBA-200E) driver (by Uwe Dannowski and Christophe
++ Lizzi)
++ - added the Interphase ATM PCI (i)Chip (x575, x525, x531, etc.) driver (by
++ Monalisa Agrawal and Peter Wang)
++ - added ABR fields to struct atm_trafprm (by Peter Wang)
++ - nicstar driver now supports setting of the CLP bit (by Rui Prior)
++ - added ENI_SETMULT ioctl and enitune utility to change ENI buffer size
++ multipliers at run time
++
++Other changes
++-------------
++
++ - atmsigd: changed default UNI version from 3.0 to dynamic (which defaults
++ to 3.0)
++ - atmtcp: removed ugly ../../net/atm/protocols.h include
++ - ioctls now internally return -ENOIOCTLCMD if ioctl command number is not
++ recognized
++ - removed ATM_CREATE_LEAF ioctl (wasn't used and suggested the wrong design
++ approach anyway)
++ - updated README.DRIVERS
++ - natmtcp now uses port 2812 (assigned by IANA)
++ - moved Documentation/atm.txt to Documentation/networking
++ - improved atm_kptr_int_t for non-Sparc architectures (by Christophe Lizzi)
++ - removed two compiler warnings from nicstar.c
++ - some minor nicstar cleanup (by Rui Prior)
++ - added "vbr" and "abr" to text2qos/qos2text ("vbr" not used for anything
++ right now)
++ - natmtcp: added commands "create", "remove", "switch", corresponding to
++ options -p, -r, and -s of atmtcp
++ - natmtcp: added link type "print" (write PDU content to stdout)
++ - natmtcp: now uses atm_kptr_int_t for VCC kernel pointer instead of unsigned
++ long
++ - added apologetic man page for natmtcp
++ - renamed natmtcp to atmtcp and removed the old atmtcp
++ - changed some user-space code to avoid patronizing "ambiguous `else'"
++ warnings from egcs, adding as few ugly redundant curly braces as possible
++ - fixed some other compiler warnings
++ - kernel part: trimmed operations structure initializers which consisted
++ mainly of NULL pointers
++ - kernel pointers sent as opaque references to user space are now of type
++ atm_kptr_t. Added support functions kptr_eq and kptr_print. (With help from
++ Richard Johnson and Mitchell Blank)
++ - removed various "overriding commands" warnings in user-space build process
++ - mkdist now creates arcvie in current directory if ~/l/arch doesn't exist
++ - make clean && make now works also if dependencies are present (make clean
++ used to remove sigd/q.out.h, which the dependencies required)
++ - atmtcp uses command bg instead of -b for backgrounding. Also, listen-bg
++ listens and backgrounds before calling accept.
++
++
++Version 0.63 to 0.64 (1-DEC-1999)
++====================
++
++Bug fixes
++---------
++
++ - atmapi.h logic was still wrong (fixed by Christophe Lizzi)
++ - LANE: fixed BUS filtering and net/atm/lec.c cleanup (by Heikki Vatiainen)
++ - arpd/io.c assumed that diag() preserves errno
++ - atmarpd didn't include QOS in output if getsockopt failed
++
++New features
++------------
++
++ - /proc/atm/eni:* now also shows transmit queue and backlog length
++ - added option "sndbuf" to atmarp
++ - added option "sndbuf" to tc ... atm ...
++ - /proc/atm/vc lists internal details for all VCs (flags, buffers, etc.);
++ added ATM_VF2TXT_MAP to atmdev.h to allow translation of flag values
++
++Other changes
++-------------
++
++ - ATM now uses sk->sndbuf/rvcbuf instead of atm_vcc->tx_quota/rx_quota
++ - removed rx_quota hack from zatm.c
++ - removed net/atm/tunable.h
++ - CLIP and sch_atm now only send packets if the VC's send queue allows them to
++ - implemented correct "requeue" function in sch_atm
++ - updated zeppelin(8) man page (Heikki Vatiainen)
++ - atmarp: atmarp -q qos_spec usage is obsolete; use atmarp -q qos qos_spec
++ instead
++ - /proc/atm/svc now prints "N/A@xxxxxxxx" instead of "Unassigned", with the
++ address of the descriptor in xxxxxxxx
++ - removed all traces of CONFIG_MMU_HACKS
++ - obsoleted ATM_SETSC (single-copy control)
++
++
++Version 0.62 to 0.63 (22-NOV-1999)
++====================
++
++Bug fixes
++---------
++
++ - horizon.c: cleared weird rate_lock/rates_lock patch conflict
++ - saaldump output formatting was completely wrecked; added option -q for
++ "quiet" output (no Q.2931 printing)
++ - fixed LANE Ethernet interface MTU mapping (patch by Rob Scott)
++ - atmsigd incorrectly rejected CONNECTION AVAILABLE (Q.2963.1)
++ - SVC address was wrong in /proc/atm/arp if using private and public part
++ - RESTART ACKNOWLEDGE was not sent with the correct global call reference
++ value (reported by Peter Ryan)
++ - zatm: usec timestamps need 64 division of x86, so this option must be
++ unavailable on other architectures (reported by Matti Aarnio)
++ - nicstar: added "fix3" and "fix4" (by Rui Prior)
++ - LANE: non-proxy didn't filter packets coming from BUS (fix by Marko Kiiskila
++ and Heikki Vatiainen)
++
++New features
++------------
++
++ - upgraded to kernel version 2.3.28
++ - atmtcp now reports VC open/close and generates timestamps (Note: the
++ protocol used between the kernel and the atmtcp utility has changed)
++ - new utility "natmtcp" which combines the ATMTCP protocol, ATMTCP ("virtual")
++ interfaces, "real" ATM interfaces, and log files (experimental)
++ - added ILMI 4.0 MIB variables atmfPortMyIdentifier and atmfMySystemIdentifier
++ (by Thomas Seidel)
++ - zeppelin: new command line option -I to select interface, allowing the use
++ of LANE with multiple physical interfaces (by Heikki Vatiainen)
++ - UltraSparc (sparc64) support (by Christophe Lizzi)
++ - nicstar: added IDT77105 PHY support (by Greg Banks)
++ - added utility loop25 to control ForeRunner LE loopback mode (by Greg Banks)
++ - added support for DNS lookup of NSAP addresses (by Rui Prior)
++ - added utility debug/dnstest (by Rui Prior)
++
++Other changes
++-------------
++
++ - net/atm/tunable.h cleanup
++ - removed SO_BCTXOPT, SO_BCRXOPT, and struct atm_buffconst
++ - removed obsolete field "next" from struct atm_blli
++ - changed potentially unaligned 32 bit accesses in SAAL to use read_netl
++ (spotted by Christophe Lizzi)
++ - added __attribute__ ((aligned(8))) to many structures containing structures
++ which are shared by kernel and user space to enfore uniform packing on
++ sparc64 (with help from Christophe Lizzi)
++ - changed unsigned long to unsigned int at API for compatibility with
++ architecture where sizeof(long) differs between user and kernel space
++ (e.g. sparc64; suggested by Christophe Lizzi)
++ - changed struct atmsvc_msg.{vcc,listen_vcc} from unsigned long to new type
++ atm_kptr_int_t; changed atmsigd accordingly (NB: debugging output may strip
++ upper bits)
++ - changed various casts pointer->int to pointer->long->int (where the pointer
++ does indeed only contain an int, e.g. in ioctl) for Alpha (reported by
++ Matti Aarnio)
++ - nicstar: changes card->membase from u32 to unsigned long
++ - added __attribute__ ((unused)) to mpc.c and mpoa_caches.c to remove
++ warnings about variables used only for debugging
++ - drivers/atm/Config.in: changed ! "$foo" = "x" to "$foo" != "x"
++
++
++Version 0.61 to 0.62 (27-AUG-1999)
++====================
++
++Bug fixes
++---------
++
++ - lib/diag.c:set_logfile didn't set log_to_initialized (reported by Lars
++ Burgstahler)
++ - sch_atm did not use classifiers attached to the x:0 class (reported by Lars
++ Burgstahler)
++ - net/atm/atm_misc.c EXPORT'ed atm_return, which is an inline function (fixed
++ by Mitchell Blank)
++ - work-around for SO_LEVEL range problems (by Mitchell Blank)
++ - nicstar oops fix (by Rui Prior and John Brosnan)
++ - nicstar should now work also as non-module (by Rui Prior)
++ - nicstar fix for chip bug showing up on 64-bit CPCI bus systems (by Jay
++ Talbott)
++ - cleared confusion about inclusion of suni.o when building both nicstar and
++ ENI
++ - suni.c now always exports suni_init
++ - various fixes and cleanups in the Madge drivers (by Giuliano Procida)
++ - fixed new set of atm_pdu2truesize problems by introducing atm_alloc_charge
++ which handles the allocation too (problem report and work-around by Alexey
++ Kuznetsov)
++ - getsockname on unbound PVC socket caused an oops
++ - LANE: Token Ring source route bridge support fix (by Heikki Vatiainen)
++
++New features
++------------
++
++ - upgraded to kernel version 2.3.15 (mainly by Alexey Kuznetsov and Mitchell
++ Blank)
++ - new socket option SO_ATMPVC to retrieve the "PVC" address (PVC & SVC) (based
++ on a patch by Jay Talbott)
++ - zeppelin -l now also accepts only the selector byte (by Robert Slaski)
++
++Other changes
++-------------
++
++ - removed obsolete drivers/atm/nicstar.c.old_skb
++ - removed all references to Arequipa (obsolete)
++ - SO_BCTXOPT/SO_BCRXOPT are now obsolete, given that the final verdict on page
++ flipping has been spoken in linux-kernel
++ - interface statistics are now counted in struct net_device_stats instead of
++ struct enet_statistics (by Mitchell Blank)
++ - added pointer to mailing list to Documentation/atm.txt
++ - Documentation/Configure.help now points to Documentation/atm.txt instead of
++ directly to the Web page.
++ - usage.tex: clarified the consequences of interrupting atmtcp
++ - changed the highly misleading "atmarpd:ITF: no such interface" message to
++ DIAG_DEBUG
++
++
++Version 0.60 to 0.61 (11-JUN-1999)
++====================
++
++Bug fixes
++---------
++
++ - nicstar: driver sometimes crashed when starting for 25 Mbps cards (Rui
++ Prior)
++ - Zeitnet driver: uPD98402.c wasn't compiled with -DEXPORT_SYMTAB when
++ building as a module
++ - net/atm/raw.c didn't export atm_init_aal5, so ATMTCP didn't load as a module
++ - atmtcp could still be accessed after loading and then unloading, yielding an
++ Oops
++
++Other changes
++-------------
++
++ - PPC configuration now also includes ATM (Jay Talbott)
++ - lots of cleanup in the Madge drivers (Giuliano Procida)
++ - tamed down a bit the tone in README
++
++
++Version 0.59 to 0.60 (3-JUN-1999)
++====================
++
++New features
++------------
++
++ - upgraded to kernel version 2.3.3 (main change is slightly different wait
++ queue handling; affects all drivers)
++
++Other changes
++-------------
++
++ - mkdiff script now takes .bz2 kernel if no .gz can be found
++ - made a few changes to the Madge drivers to reduce the number of warnings
++
++
++Version 0.58 to 0.59 (3-JUN-1999)
++====================
++
++New features
++------------
++
++ - upgrade to kernel version 2.2.9
++ - zeppelin now adjusts MTU when joining ELAN (Heikki Vatiainen)
++
++Other changes
++-------------
++
++ - adjusted tr interface name limit to 8 characters (down from a wasteful 9)
++
++
++Version 0.57 to 0.58 (3-JUN-1999)
++====================
++
++Bug fixes
++---------
++
++ - ENI drivers sometimes directly dereferenced pointers instead of using readl/
++ writel (fixed by Mitchell Blank)
++ - nicstar driver no longer uses floating point (fixed by Rui Prior)
++ - nicstar driver may have refused CBR VC in some cases even with enough
++ bandwidth available (fixed by Rui Prior)
++ - usage.tex failed to build (fixed by Bill Brooks)
++ - zeppelin got byte order in BLLI wrong (reported by Chas Williams; fixed by
++ Mitchell Blank and Heikki Vatiainen)
++ - zeppelin did not work when the host had multiple ATM addresses (reported by
++ Benoit Steiner; fixed by Heikki Vatiainen)
++ - zeppelin incorrectly parsed -i command line option (reported by Benoit
++ Steiner; fixed by Heikki Vatiainen)
++ - atm_connect_vcc and /proc/atm/pvc report AAL0 now properly (reported by Zhu
++ Qun Ying and Uwe Dannowski)
++
++New features
++------------
++
++ - nicstar driver now support SONET diagnostics (by Rui Prior)
++ - nicstar driver now works on PowerPC (by Jay Talbott)
++ - LANE now also supports Token Ring (Heikki Vatiainen, with testing by
++ Holger Smolinski)
++
++Other changes
++-------------
++
++ - major non-i386 architecture and other cleanup in ENI driver (by Mitchell
++ Blank)
++ - number of lec devices is 40+8 (lec0-lec39 are Ethernet and lec40-lec47 are
++ Token Ring; Heikki Vatiainen)
++ - lec.c and mpc.c now use atm_force_charge (Heikki Vatiainen)
++ - net/802/tr.c limited interface names to 4 characters (fixed by Heikki
++ Vatiainen)
++ - zeppelin man page updated (Heikki Vatiainen)
++ - "zeppelin.new" is now "zeppelin", the old "zeppelin" is gone
++ - set "atm_connect" printk to KERN_DEBUG
++ - removed ATM_SAAL from include/linux/atm.h (there never was any support for
++ SAAL in the kernel)
++
++
++Version 0.56 to 0.57 (18-MAY-1999)
++====================
++
++Bug fixes
++---------
++
++ - atmarpd complained "invalid control msg type" when changing interface
++ characteristics (reported by Soo-Khim Ho)
++ - sch_atm didn't compile without CLIP (reported by Zhu Qun Ying)
++ - LANE & MPOA: plugged a few memory leaks after failure to atm_charge (Heikki
++ Vatiainen)
++ - mpcd could not be killed if MPS's address was not known (fixed by Heikki
++ Vatiainen)
++ - nicstar: fixed the sleeping in interrupt issue (Rui Prior)
++
++New features
++------------
++
++ - drivers for the Madge "Ambassador" and "Horizon [Ultra]" NICs, also known
++ as Collage PCI 155 Server, 25, and 155 Client (by Giuliano Procida)
++
++Other changes
++-------------
++
++ - MPOA code cleanup and debugging printks are now conditional (Heikki
++ Vatiainen)
++ - removed both led/USAGE files
++ - removed the old atmsigd (was in atm/sig.old/)
++ - nicstar driver now works around TSQ bug on older chips (77201) (by Rui
++ Prior, with the detective work by Jay Talbott)
++
++
++Version 0.55 to 0.56 (22-APR-1999)
++====================
++
++Bug fixes
++---------
++
++ - atm/doc/Makefile assumed . to be included in PATH when invoking rlatex
++ (fix by Heikki Vatiainen)
++ - usage.txt leaked Arequipa configuration examples (fix by Heikki Vatiainen)
++ - plugged a small memory leak in led.new which occurred when using the LANE
++ client as a proxy (Heikki Vatiainen)
++ - atmarpd crashed when printing ATMARP table entries with flag 0x8000 set
++ (reported by Vinay Kulkarni)
++ - CLIP interfaces now follow netmask changes
++ - Nicstar: 25.6 Mbps cell rate corrected (by Rui Prior)
++ - atm_equal could loop forever when comparing NSAP-encoded E.164 addresses
++ (reported by Valley Zhizhkun)
++ - [AP]F_ATM[PS]VC definitions in lib/atm.h conflicted with glibc 2.1
++ (reported by Heikki Vatiainen and Jens Vagelpohl)
++ - changed a few non-int main to int main (reported by Heikki Vatiainen)
++ - changed lib/diag.c work with glibc 2.1, where stderr is no longer a constant
++ (based on a patch by Heikki Vatiainen, also reported by Giuliano Procida)
++ - make clean didn't remove qgen/q.test.c, qgen/qd.out.h, qgen/qd.test.c,
++ sigd/q.out.h and sigd.old/q.out.h (reported by Giuliano Procida)
++ - optional headers were installed even with system headers present if
++ INSTROOT was different from / (reported by Giuliano Procida)
++ - lib/stdint.h was used even on systems that had a "real" stdlib.h (based on a
++ patch by Heikki Vatiainen, also reported by Giuliano Procida)
++ - renamed net/atm/misc.c to atm_misc.c to avoid name clash with
++ drivers/char/misc.c on include/linux/modules/misc.* (reported by Borek
++ Lupomesky)
++
++New features
++------------
++
++ - new ioctl ATM_GETLINKRATE to query link rate of an interface (suggested by
++ Vitaly Lavrov)
++ - new atmsigd.conf option io max_rate to specify rate to signal if
++ application requests the "maximum"
++ - added decription of CONFIG_ATM_LANE and CONFIG_ATM_MPOA to the kernel
++ configuration help (Heikki Vatiainen)
++ - added description of LANE to usage.tex (Heikki Vatiainen)
++ - new function atm_force_charge to unconditionally add data to a receive
++ buffer
++
++Other changes
++-------------
++
++ - atmsigd now determines maximum link rate by querying interfaces (suggested
++ by Vitaly Lavrov)
++ - moved local address registry from a global table to VPCI structures
++ - changed unknown net device notification severity from KERN_ERR to
++ KERN_WARNING
++ - atmarpd now overwrites old atmarpd.table on startup (it used to keep it
++ until the first configuration change)
++ - shutdown(2) of native ATM VCs now returns 0 instead of -EOPNOTSUPP
++ (suggested by Mitchell Blank)
++ - Nicstar: IRQ sharing is now allowed (by Rui Prior)
++ - Nicstar: default maximum number of cards is now 4 (by Rui Prior)
++ - Nicstar: when compiled as a module, the driver may no longer be removed
++ while in use (by Rui Prior)
++ - Nicstar: loss of cells is no longer reported as a plain CRC error (by Rui
++ Prior)
++ - atmsigd now always clears the endpoint reference flag if in UNI 3.0 mode
++ (based on a patch by Heikki Vatiainen)
++
++
++Version 0.54 to 0.55 (1-MAR-1999)
++====================
++
++Bug fixes
++---------
++
++ - SELECT_TOP_PCR didn't take intro account the "pcr" field, causing SVC with
++ QoS pcr=xxx to be set up at link speed
++ - qos_equal didn't detect differences in the "pcr" fields
++ - sch_atm only accepted parent == root or absent (reported by John Loughney)
++ - sch_atm:atm_tc_put accessed flow structure after kfree'ing it
++ - sch_atm:atm_tc_change didn't put excess traffic class if class creation
++ failed
++ - sch_atm:atm_tc_dump_class didn't return class ID in tcm->tcm_handle
++ - sch_atm:atm_tc_delete refused to delete classes because it expected
++ ref == 1, but ref == 2 (reported by John Loughney)
++
++
++Version 0.53 to 0.54 (19-FEB-1999)
++====================
++
++Bug fixes
++---------
++
++ - led.new: fixed build problem and warning (Heikki Vatiainen)
++ - fixed LANE arp cache timeouts (Heikki Vatiainen)
++ - ilmid -i option fell through into -l, causing logging to go into a file
++ named after the local address
++ - flipping the highest bit of ep_ref made it negative which was erroneously
++ interpreted to mean "absent" (reported by Giuliano Procida and Chas
++ Williams)
++ - ilmid used the result of AsnOidCompare inconsistently, causing network
++ prefix registration to fail with some switches (based on a patch by Giuliano
++ Procida)
++
++New features
++------------
++
++ - tc:q_atm: new option "clip" to select Classical IP processing of inbound
++ traffic
++ - new sch_atm class attribute TCA_ATM_STATE to retrieve VC state
++
++Other changes
++-------------
++
++ - led.new: improved handling of LANE flush protocol (Heikki Vatiainen)
++ - copied USAGE from led/ to led.new/
++ - added description of ilmid options -i and -u to USAGE (Heikki Vatiainen)
++ - ilmid -u now also works without -DDYNAMIC_UNI (all values but the default
++ are refused)
++ - tcpdump patch updated to tcpdump version 3.4 (Heikki Vatiainen)
++ - updated "tc" patch to iproute2 version 2.1.99-now-ss990203
++
++
++Version 0.52 to 0.53 (9-FEB-1999)
++====================
++
++Bug fixes
++---------
++
++ - atmsigd: selecting the UNI version via compile-time options didn't yield
++ the desired result in some cases (reported by Vinay Kulkarni and others)
++ - ATM VCCs now use struct sock, as required by protocol-independent layer
++ starting with recent 2.1 kernels (by Mitchell Blank)
++ - led fixes: htons/htonl bugs in LANEv2 code, one duplicate close() removed
++ (by Heikki Vatiainen)
++
++New features
++------------
++
++ - upgraded to the 2.2.1 kernel (by Mitchell Blank)
++ - LANE: added bridging support (by Heikki Vatiainen)
++ - complete rewrite of led (in led.new), which is now leaner and no longer
++ contains code (c) Digital (by Heikki Vatiainen)
++ - added macros for local AESA format and group addresses, and support in
++ atm2text (by Heikki Vatiainen)
++
++Other changes
++-------------
++
++ - ENI: buffer sizes are now limited to MID_MAX_BUF_SIZE even if max_sdu >
++ MID_MAX_BUF_SIZE/3 (reported by Andrew Lunn)
++ - plenty of NICStAR changes (Rui Prior and Mitchell Blank)
++ - LANE interface to upper layer looks more like Ethernet, so adding bridge and
++ 802.1Q support is easier, and tcpdump does not need any extra patches (by
++ Heikki Vatiainen)
++
++
++Version 0.51 to 0.52 (5-DEC-1998)
++====================
++
++Bug fixes
++---------
++
++ - atmsigd crashed when receiving STATUS ENQUIRY for call in Null state
++ (reported by Heikki Vatiainen)
++ - outbound endpoint reference didin't have the 16th bit toggled (fixed by
++ Andrew Lunn)
++ - lec.c: fixed a bug in kernel which could cause kernel part to deadlock when
++ signalling was not started successfully (by Heikki Vatiainen)
++ - MPOA: bug fixes and other changes, see atm/mpoa/CHANGELOG (by Heikki
++ Vatiainen)
++
++New features
++------------
++
++ - LANE: both kernel & daemon: support for ELANs which have MTUs greater than
++ 1516 (by Eric H. Kinzie)
++ - MPOA: can now ask LECS for configuratino information (by Heikki Vatiainen)
++
++Other changes
++-------------
++
++ - zeppelin.8: updated (Heikki Vatiainen)
++
++
++Version 0.50 to 0.51 (6-NOV-1998)
++====================
++
++Bug fixes
++---------
++
++ - atmsigd: typo prevented kernel.c from compiling with UNI30 disabled (fix by
++ Andrew Lunn and Uwe Dannowski)
++ - option -u crashed ilmid (reported by Michael Wolf)
++
++Other changes
++-------------
++
++ - bearer capability is now set to "CBR" for CBR (suggested by Heikki
++ Vatiainen)
++
++
++Version 0.49 to 0.50 (3-NOV-1998)
++====================
++
++Bug fixes
++---------
++
++ - atmsigd didn't compile for -DUNI31 -DALLOW_UNI30 (fixed by Richard Gooch)
++ - atmsigd crashed on as_bind and also had problems with as_connect after
++ as_bind (reported by Heiko Krupp, Heikki Vatiainen, and many others)
++
++Other changes
++-------------
++
++ - atmsigd now enables tracing by default (use -t 0 to turn it off)
++ - added "terminate" message to test/isp
++ - mpoad defaults to UBR if service category is absent (by Heikki Vatiainen)
++ - LANE now avoids blocking intact connections when other connections have
++ problems by queuing packets independently per destination while waiting for
++ a connection (by Heikki Vatiainen)
++
++
++Version 0.48 to 0.49 (1-NOV-1998)
++====================
++
++Bug fixes
++---------
++
++ - q_atm.c passed TCA_ATM_EXCESS even if zero, while the kernel expected it
++ to be absent in this case (changed q_atm.c)
++ - q_atm: tc class show didn't separate fields properly with blanks
++ - removed double inclusion of atm/config from mkdist
++
++New features
++------------
++
++ - upgraded to the 2.1.126 kernel
++
++Other changes
++-------------
++
++ - "new" atmsigd is now the default (atm/sigd got renamed to atm/sigd.old,
++ atm/sigd.new to atm/sigd)
++ - updated extra/tc/README
++
++
++Version 0.47 to 0.48 (30-OCT-1998)
++====================
++
++Bug fixes
++---------
++
++ - ilmid didn't recognize the -u option
++ - ATM_GETCIRANGE copied wrong amount of data (fix by Heikki Vatiainen)
++ - sch_atm didn't compile without policing enabled (reported by Calin Poenaru)
++ - BHLI octets: qgen/msg.fmt allowed nine instead of eight bytes for ISO and
++ user specified, include/linux/atmsap.h:ATM_MAX_HLI was 7 instead of 8 (by
++ Damian Gilmurray and Paisit Thamsakorn)
++ - MPOA: bug fixes and other changes, see atm/mpoa/CHANGELOG (by Heikki
++ Vatiainen)
++
++New features
++------------
++
++ - ilmid: new option -i to set local IP address (suggested by Andrew May)
++ - ilmid now also supports the MIB variables atmfAtmLayerMaxVpiBits and
++ atmfAtmLayerMaxVciBits (based on a patch by Uwe Dannowski)
++
++Other changes
++-------------
++
++ - ilmid: search for local IP address didn't consider LANE interfaces (lec*)
++ - consolidated most of the various calls to gethostbyname and friends into
++ text2ip (libatmd)
++ - corrected some glitches in net/sched/sch_atm.c (untested)
++ - removed debug/encopy, debug/endump, and debug/zndump from the distribution.
++ They were almost useless and caused problems with make depend
++ - SYMFILES in qgen/Makefile now determines location of atmsap.h at run time to
++ avoid problems when kernel headers are not in /usr/include/linux (reported
++ by Uwe Dannowski)
++
++
++Version 0.46 to 0.47 (6-OCT-1998)
++====================
++
++Bug fixes
++---------
++
++ - qgen didn't build for all UNI versions (fixed by Richard Gooch)
++
++New features
++------------
++
++ - ilmid: new option -u to set UNI version (3.0, 3.1, or 4.0). Only available
++ if compiled with -DDYNAMIC_UNI.
++
++Other changes
++-------------
++
++ - ilmid: getIpAddr: improved robustness and added debugging output
++
++
++Version 0.45 to 0.46 (5-OCT-1998)
++====================
++
++Bug fixes
++---------
++
++ - ENI and ZATM driver used to read IRQ directly from PCI configuration,
++ bypassing any fixups (reported by Richard Gooch)
++ - atmsigd.new: removed "Known bug" memory leak (when tracing)
++ - led/lec_ctrl.c: signalling bug fixed, max_sdu now has correct value instead
++ of 1 (by Heikki Vatiainen, reported by Josh Baratz <jbaratz@lucentctc.com>
++ and Wolfgang Platzer <wplatzer@iaik.tu-graz.ac.at>)
++ - lots of MPOA bug fixes and other changes, see atm/mpoa/CHANGELOG (by Heikki
++ Vatiainen)
++ - atmsigd reported "Q.2931.1" when configured to support Q.2963.1
++
++New features
++------------
++
++ - atmsigd.new now supports run-time configuration of the signaling protocol
++ version (via atmsigd.conf)
++
++Other changes
++-------------
++
++ - added 16W bursts to ENI burst size configuration (NB: 16W may actually be
++ *slower* than 8W)
++ - lec_ctrl.c: zeppelin now uses LE_REGISTER protocol when TLVs are associated
++ with client's MAC address (by Heikki Vatiainen)
++
++
++Version 0.44 to 0.45 (1-OCT-1998)
++====================
++
++Bug fixes
++---------
++
++ - ENI driver didn't do four-word bursts on RX for sizes < 8 words
++ - arequipad, atmarpd, bus, lecs, les, mpcd, sw_*, and zeppelin silently
++ ignored extra command-line arguments instead of complaining
++
++New features
++------------
++
++ - ENI: added configuration options to fine-tune burst sizes (in reponse to
++ incompatibility found by Dave Airlie)
++
++Other changes
++-------------
++
++ - changed the way how ATM-specific data is stored in skbs. Tentatively updated
++ the the stack, including drivers. Use CONFIG_ATM_SKB to enable the new-style
++ skbs.
++ - Rules.make no longer discards the previous value of LDLIBS
++ - sw_tcp now only establishes bi-directional VCs if both directions are really
++ requested in the QoS structure
++ - moved manual switch control from sw_tcp to the generic switch code; "tcpswc"
++ is now called "swc", the corresponding switch.conf clause is now
++ 'control <path>' instead of 'option control "<path>"'
++
++
++Version 0.43 to 0.44 (24-SEP-1998)
++====================
++
++Bug fixes
++---------
++
++ - CONNECT messages no longer contain the AAL type IE if EP ref is present and
++ non-zero (reported by Heikki Vatiainen)
++ - SSCOP: added mode for partial compatibility with Q.SAAL1 (to get rid of
++ warnings reported by Heikki Vatiainen and of interoperability problems with
++ Virata switches reported by Damian Gilmurray)
++ - ilmid now returns a valid response for atmfMyIpNmAddress (by Uwe Dannowski)
++ - configuration on-line help for CLIP didn't work because tag was different
++ from configuration variable
++ - atmsigd crashed when adding multiple local addresses on an interface
++ (reported by Heiko Krupp)
++ - atmaddr.8 said "ATMARP" in the header (reported by Hans Einsiedler)
++ - net/atm/misc.c didn't include linux/config.h and linux/module.h, causing
++ symbols to be missing when rebuilding the kernel after enabling modules
++ (reported by Thomas Parvais)
++
++New features
++------------
++
++ - new maintenance utility tcpswc to control sw_tcp "switches" (description at
++ the end of switch/tcp/README)
++ - added support for setting the CLP bit (untested; see doc/README.CLP)
++ - added support for policing to the ATM qdisc (untested; see extra/tc/README)
++ - ilmid: added support for atmfAtmLayerUniVersion (by Uwe Dannowski)
++
++Other changes
++-------------
++
++ - updated the NICStAR driver to version 008b (by Rui Prior)
++ - new switch fabric function fab_option to pass configuration options
++ - atm2text now also supports unspecified and wildcard components in PVC
++ addresses
++ - added configuration option CONFIG_ATM_CLIP_NO_ICMP to discard packets for
++ which no ATMARP entry exists silently instead of sending an ICMP (this is an
++ ugly hack-around for the revalidation problem reported by Gerald Hanusch)
++ - various minor documentation updates
++ - atmarpd now sends InARP requests when active VC setup completes in order to
++ tell the peer our IP address(es)
++
++
++Version 0.42 to 0.43 (21-AUG-1998)
++====================
++
++Bug fixes
++---------
++
++ - trying to use atmtcp when compiled as a module with the module not loaded
++ crashed the kernel
++
++New features
++------------
++
++ - upgraded to the 2.1.117 kernel
++ - included NICStAR driver by Rui Prior at INESC (this driver also includes
++ parts of an earlier driver written by Matt Welsh, then enhanced by R. D.
++ Rechenmacher and Jawaid Bazyar)
++ - new atmsigd with support for multiple signaling entities (experimental)
++
++Other changes
++-------------
++
++ - removed register dumping code from suni.c (leaked out into the distribution)
++
++
++Version 0.41 to 0.42 (19-AUG-1998)
++====================
++
++Bug fixes
++---------
++
++ - atm.patch was out of sync again :-(
++
++
++Version 0.40 to 0.41 (19-AUG-1998)
++====================
++
++Bug fixes
++---------
++
++ - 0.40 contained an older atm.patch than the one that was supposed to go with
++ it (some changes to sch_atm and MPOA were missing)
++ - kernel didn't build with LANE enabled and MPOA disabled (fix by Mitchell
++ Blank Jr)
++
++New features
++------------
++
++ - MPOA now also supports CBR SVCs (by Heikki Vatiainen and Sampo Saaristo)
++
++Other changes
++-------------
++
++ - atmtcp may work as a module (untested)
++ - kernel code now uses capabilities instead of suser()
++ - removed obsolete recycle_buffer code
++ - distribution now also includes mkpatch, the script that's used to create
++ atm.patch
++
++
++Version 0.39 to 0.40 (13-AUG-1998)
++====================
++
++Bug fixes
++---------
++
++ - ilmid defined the value of "invalid" as 0 instead of 2 (fix by Timo
++ Parnanen)
++ - bash-2 doesn't like for n in $(SUBDIR); ... if SUBDIR is undefined (fix
++ by Heikki Vatiainen)
++ - LANE still cleared ATM_VF_RELEASED instead of calling atm_async_release_vcc,
++ which apparently led to stray kernel crashes in signaling (found with a lot
++ of help from John McPherson)
++ - ATM qdisc now properly re-allocates skb memory to grow headers, if necessary
++ - atm/switch/Makefile didn't build SUBDIRS
++ - atmarpd sent garbage ATM addresses in InARP responses over PVCs (reported by
++ Stefan Keller-Tuberg)
++
++New features
++------------
++
++ - MPOA (Multi-Protocol Over ATM) client support written by Heikki Vatiainen
++ and Sampo Saaristo
++ - LANE client (zeppelin) now also supports LANE2 (by Heikki Vatiainen)
++
++Other changes
++-------------
++
++ - accept() now also returns on ATM_VF_CLOSE
++ - ATM qdisc now uses the same data format on rtnetlink as other qdiscs; new
++ option for user-provided headers
++ - atm/switch can now use "external" routing (e.g. provided by the fab control)
++
++
++Version 0.38 to 0.39 (4-AUG-1998)
++====================
++
++Bug fixes
++---------
++
++ - added missing #include <atm.h> in tcpsw.c (fixed by Heikki Vatiainen)
++ - atmsigd allowed both sides to initiate PCR modification; Q.2963.1 only
++ allows the connection owner (i.e. the caller) to do this
++ - atmarpd no longer tries to use incoming SVCs with zero backward bandwidth
++ for ATMARP
++ - ENI and ZATM drivers didn't invoke vcc->pop on dev->ops->send failure
++ - make install didn't probe correctly for presence of /usr/include/stdint.h
++ (needed on GLIBC 1 systems)
++ - net/atm/resources.c didn't export bind_vcc to modules (fix by Oliver
++ Frommel)
++ - net/arpd/atmarp didn't build without make depend (reported by Stefano
++ Giacometti)
++ - clip_mkip zeroed vcc->rx_inuse and didn't take into account that clip_push
++ calls atm_return, which subtracts from vcc->rx_inuse too
++ - fixed typos in qgen/uni.h (and msg.fmt) for causes 38, 41, and 43
++ - atmsigd wrote exit trace to stderr when it had a dump directory and vice
++ versa
++ - documentation still claimed that atmtcp yields messages at boot time
++
++New features
++------------
++
++ - added flow to ATM VCC mapping queuing discipline (experimental)
++ - module for setting up ATM PVC/SVC mappings with "tc" in extra/tc (see
++ extra/tc/README)
++ - atmarpd: new request type art_query to request resolution without VC setup
++ - atmarp: new undocumented option -Q to test art_query
++ - added ATMTCP interfaces that survive disconnects (persistent; new atmtcp(8)
++ options -p and -r; new ioctls ATMTCP_CREATE and ATMTCP_REMOVE)
++
++Other changes
++-------------
++
++ - zeppelin didn't explicitly set the AAL type for outbound connections (by
++ Heikki Vatiainen)
++ - CLIP also allows SVCs to have no idle timeout at all (timeout = 0)
++ - moved SUNI private ioctls (SUNI_GETLOOP and SUNI_SETLOOP) from
++ drivers/atm/suni.h to include/linux/atm_suni.h
++ - atmarpd now shows QoS information for VCs where it differs from the default
++ or where no default is applicable
++ - removed the file atm/WARNING, which gave an overly pessimistic perspective
++ of the state of things
++ - switch: fab_op now returns the cause value plus (optionally) a pointer to
++ diagnostics in the callback instead of a simple okay/not okay indication
++ - updated and corrected the atmtcp man page
++ - further cleanup of the build procedure
++ - README now mainly refers to http://lrcwww.epfl.ch/linux-atm/info.html
++ - updated and trimmed BUGS
++ - added a note to CREDITS indicating its obsolescence
++
++
++Version 0.37 to 0.38 (25-JUN-1998)
++====================
++
++Bug fixes
++---------
++
++ - fixed the remaining few #include <linux/atm.h>
++ - invoking fcntl() or socketpair() on an ATM socket caused an "Oops" (reported
++ by Jonathan Chan)
++ - CLIP PVCs caused an "Oops" when cat'ing /proc/atm/pvc (reported by Marko
++ Kiiskila and Robert Olsson)
++ - atm/qgen/default.nl wasn't removed after build failure
++ - debugging switch (sw_debug) did not stop operations after the first error
++ - svc_accept returned apparent success instead of -EAGAIN, usually leading to
++ a later -ENOTCONN
++ - ttcp.c didn't initialize port_name, leading to erratic behaviour when making
++ slight changes to the build process
++ - atm_pdu2truesize diverged from alloc_skb, leading to sudden failure of VCs
++ or of ATMARP (reported by Robert Olsson)
++ - corrected use of '~' when applied to unsigned longs representing memory
++ addresses in aread, ENI, and ZATM (reported by Wai-Sun Chia)
++ - atmtcp and LANE didn't use bind_vcc when setting up control VCs
++ - atmtcp got ENOMEM/EBUSY wrong when failing to create an interface
++ - sig level <level> in atmsigd.conf didn't affect UNI diagnostics
++
++New features
++------------
++
++ - upgraded to the 2.1.105 kernel
++ - added ATMTCP "switch" in atm/switch/tcp
++ - atmtcp: new mode -s to connect to an ATMTCP "switch"
++ - atmtcp: new option -d for debugging output
++ - added -b option (the usual "background") to switch/relay.c
++
++Other changes
++-------------
++
++ - changed "PDU" to "SDU" in the atmtcp(8) man page
++ - atmarpd now includes the interface netmask in ATMARP table dumps
++ - added ATM devices also to the Alpha architecture, because at least ATMTCP
++ works (by Wai-Sun Chia)
++ - added the removal of -Wmissing-prototypes to the 0.37 changes
++ - removed -Wcast-align from Rules.make because of a conflict with
++ /usr/include/socketbits.h of glibc 2 on Alphas (reported by Wai-Sun Chia)
++ - atmsigd.conf.4: documented that debug log stderr works too
++ - sap_equal now also allows wildcard matches for BHLI (with SXE_COMPATIBLE)
++ - atmsigd now uses -m <mode> instead of -N and -A
++ - atmsigd.conf now uses sig mode <mode> instead of sig net
++
++
++Version 0.36 to 0.37 (6-JUN-1998)
++====================
++
++Bug fixes
++---------
++
++ - lib/atm.h defined AF_ATMPVC to 20, but the correct value is 8. Likewise,
++ AF_ATMSVC should be 20, not 21. (Reported by Luke Diamand)
++ - fixed bad ASN encoding in ilmid (by Vesa-Matti Puro)
++ - make install and make instdirs didn't stop on error
++
++New features
++------------
++
++ - upgraded to the 2.1.104 kernel
++ - included a script to demonstrate the debug switch (see switch/debug/README)
++
++Other changes
++-------------
++
++ - moved definitions not used by the kernel from linux/atmarp.h to atmarp.h
++ - removed linux/atm_stdint.h (linux/types.h has now caught up)
++ - changed ENI and ZATM driver to use new PCI interface
++ - net/atm/clip.c no longer uses ether_setup (suggested by Alexey Kuznetsov)
++ - more header file cleanup (main change: applications should now
++ #include <atm.h> instead of #include <linux/atm.h>)
++ - removed -Wmissing-prototypes from Rules.make because of a conflict with
++ include/linux/byteorder/swab.h
++
++
++Version 0.35 to 0.36 (23-APR-1998)
++====================
++
++Bug fixes
++---------
++
++ - changed the numeric values of PF/AF_ATMPVC/SVC and SOL_ATM/AAL to avoid
++ conflicts with other allocations. This breaks binary compatibility with
++ ATM programs compiled under older kernels
++ - RESTART ACK was sent with the wrong class when acknowledging the restart of
++ the indicated virtual channel (fix by Mohsen Souissi)
++ - RELEASE was retransmitted forever (to avoid having to perform a RESTART),
++ although it's sufficient to retransmit once and then drop the connection
++ - esi.c checked the kernel version code without including linux/version.h
++ - CLIP changes magically fixed hangs on SICGIFCONF (reported by Wayne Salamon)
++ - atmsigd usually didn't set pvc.sap_family in ISP messages
++
++New features
++------------
++
++ - added build-time option -DTHOMFLEX to send RESTART when SAAL comes up, which
++ works around a bug in some Thomson Thomflex 5000 switches (by Mohsen
++ Souissi)
++ - atmtcp: new option "-i itf" to request a specific interface number
++ - the "debug switch" (switch/debug/sw_debug) is now capable of successfully
++ signaling a UNI 3.x call (see switch/debug/README for details)
++
++Other changes
++-------------
++
++ - atm_equal can now also compare PVC addresses. The argument type has
++ therefore been changed from struct sockaddr_atmsvc * to struct sockaddr *
++ - moved driver-private data from skb->atm.* into skb->cb
++ - complete redesign of communication between atmarp(8) and atmarpd(8) (now
++ uses a UNIX domain socket; suggested by Alexey Kuznetsov)
++ - atmarp -a now also produces correct output if atmarpd is running with -d
++ - removed clip(8)
++ - moved atmarp(8) from atm/ip into atm/arpd, removed atm/ip
++ - /proc/atm/svc shows listening sockets again
++ - cleaned up a few cases where diag(...,DIAG_FATAL,...) was followed by an
++ "else" or a "return".
++ - atmsigd now uses Unix domain sockets (instead of named pipes) to communicate
++ with non-kernel ISP users (updated test/isp too)
++ - net/atm/resources.c:atm_dev_register can now be asked to assign a specific
++ interface number (-1 yields the old behaviour)
++
++
++Version 0.34 to 0.35 (27-MAR-1998)
++====================
++
++Bug fixes
++---------
++
++ - ilmid compared memcmp results with -1,1, which fails under optimization
++ (fixed by Damian Gilmurray)
++ - various fixes and cleanup in how CLIP interacts with the neighbour cache
++ (spotted by Alexey Kuznetsov)
++ - Rules.make complained about missing "optprocess" command on some occasions
++
++New features
++------------
++
++ - upgraded to the 2.1.90 kernel
++ - added some components for ATM switch control (not properly integrated yet,
++ so they don't do anything useful at the moment; written by Roman Pletka)
++
++Other changes
++-------------
++
++ - eliminated various compiler warnings when compiling with glibc2
++ - removed clip_hard_header (suggested by Alexey Kuznetsov)
++
++
++Version 0.33 to 0.34 (13-MAR-1998)
++====================
++
++Bug fixes
++---------
++
++ - eni.c didn't include config.h (fix by Pete Wyckoff)
++ - (yet another) VCC list handling bug (fixed by Heikki Vatiainen)
++ - kernel also applied idle timeout to CLIP PVCs
++ - make clean didn't remove test/errnos.inc
++ - atmsigd errored as_connect and as_accept with as_close instead of as_error
++ - eni: bandwidth was sometimes reserved for UBR VCs
++ - eni: checking of bandwidth changes was broken
++ - eni: error handling after failed bw change checks destroyed the free list
++ - test/errnos.inc sometimes wasn't generated because of mtime granularity (fix
++ by Brian Armstrong and Corinne Rosier)
++ - fixed use of return code of get/put_user and copy_from/to_user
++ - kernel: fixed a few minor race conditions
++ - ATM_GETADDR left address list locked on fault
++ - maximum length of high layer information was 7 bytes instead of 8 for ISO
++ and User Specific high layer information (reported by Damian Gilmurray)
++ - some tools didn't include errno.h although they use errno or Exxx
++ - atmsigd usually accessed deallocated memory when writing traces, which
++ sometimes led to crashes (reported by Heikki Vatiainen)
++ - indentation of the first two lines of UNI signaling messages in traces was
++ missing
++ - LANE: duplicate data direct connections to entities where we already
++ have a connection are now forbidden. LES and BUS can now co-reside.
++ (Reported by Jean-Francois Moine, fixed by Heikki Vatiainen)
++ - LANE: plugged a file descriptor leak (by Heikki Vatiainen)
++ - atmsigd.conf.4 incorrectly stated that diagnostics must have a higher
++ priority than the specified level to get printed (they're also printed if
++ their priority is equal to that level)
++ - zatm driver didn't virt_to_bus the back pointer of TX rings, leading to
++ crash after sending the 32nd PDU of a VCC (reported by Ajay Bakre)
++ - zatm_feedback sometimes returned with interrupts disabled
++ - ENI driver didn't treat requests for UBR at link speed as "unlimited" and
++ allocated one shaper for each such VCC
++ - atm_async_release_vcc now has its own flag ATM_VF_CLOSE. Overloading
++ ATM_VF_RELEASED caused hung SVCs under some conditions.
++ - atmsigd sometimes released listening sockets before kernel completed its
++ cleanup, yielding warnings and zombies
++ - atmsigd accessed already deallocated data structures when handling
++ unparseable signaling messages
++
++
++New features
++------------
++
++ - upgraded to the 2.1.79 kernel
++ - CLIP now handles NETDEV_CHANGE (proposed by Pete Wyckoff; untested)
++ - various minor signaling changes for operation as switch control
++ - new device operation proc_read: device drivers can now register in /proc
++ (e.g. /proc/atm/eni:0)
++ - added some more BHLI definitions to include/atmsap.h, including draft
++ mapping of well-known TCP/UDP port numbers
++ - added support for TIOCOUTQ/TIOCINQ on native ATM
++ - new library function sap_equal
++ - added convenience function atmpvc_addr_in_use to linux/atm.h
++ - major overhaul of "isp", which is now a good tool for signaling regression
++ tests. See atm/test/README.isp
++ - LANE can now be compiled as a kernel module (by Heikki Vatiainen)
++ - new tool debug/svctor.c to torture signaling by setting up and releasing
++ lots of SVCs (see the source for details)
++
++Other changes
++-------------
++
++ - cleaned up the copying terms: libraries are now covered by LGPL instead of
++ GPL and qgen doesn't "taint" the code it generates
++ - atmarpd: IP addresses are now __u32 instead of unsigned long
++ - atmarpd: changed printf("... %08x ...",(unsigned long) ptr) to %p ...",ptr
++ - /proc support now allocates inode numbers dynamically
++ - added comment to clarify motivation for useless buffer alignment in aread.c
++ (reported by Jeon Jong Hwan)
++ - suni.c and uPD98402.c: SONET_GETSTATZ no longer clears the statistics if the
++ copy faults
++ - ilmid should now work on any interface (patch by Heikki Vatiainen)
++ - changed all __uNN of tools to uintNN_t for glibc2-compatibility
++ - added stdint.h to lib for compatibility with future versions of glibc2
++ - various other evil hacks in tools to make things compile with glibc2
++ - the NIC debugging programs ed, encopy, endump, zndump, and znth are no
++ longer built and installed by default
++ - for compatibility with POSIX 1003.1g, accept now returns ECONNABORTED
++ instead of ECONNREFUSED if connection is already gone (proposed by Heikki
++ Vatiainen)
++ - listening sockets now return instantly if the signaling demon dies
++ - various minor LANE updates to track API changes (by Heikki Vatiainen)
++ - SUNI now also warns if signal is missing at initialization time
++ - zatm: added work-around for unfair buffer space accounting
++ - clarified some of atmarpd's diagnostics
++ - documentation updates
++
++
++Version 0.32 to 0.33 (19-NOV-1997)
++====================
++
++Bug fixes
++---------
++
++ - SSCOP did poll sequence number comparisons in the (data) sequence number
++ space, typically leading to periodic SSCOP restarts (reported by Heikki
++ Vatiainen)
++ - atmsigd now releases calls on receipt of STATUS with call state 0 (reported
++ by Heikki Vatiainen)
++ - qgen tried to print the names of unnamed groups (fix by Simon Leinen)
++ - make clean in qgen left all the .c and .h files produced by qgen
++ - minor fixes to signaling message format description (qgen/msg.fmt,
++ previously qgen/uni*)
++ - /usr/include/atm.h was calling itself "atmlib" (found by Leena Chandran)
++ - atmsigd: the address format of the calling party number was used to
++ determine the format of the called party number in a SETUP message
++ - added some semicolons to Rules.make for bash 2.0 compatibility (by Tan Chang
++ Hu and Rolf Kunisch)
++ - select/poll indicated an exception when a non-blocking connect terminated.
++ Now it indicates writability, and an error only if the connect failed.
++ - LES/BUS can now co-exist at the same address (by Heikki Vatiainen)
++ - fixed race condition between asynchronous release (e.g. on ATMARP idle timer
++ expiration) and signaling demon response
++ - fixed a typo "[itf]." instead of "[itf.]" in atmsigd.conf.8
++ - "ATM drivers" kernel configuration section is no longer a top-level menu
++ item but it's now under "Network devices"
++ - sigd_close forgot to purge VCs not connected to devices (e.g. closing ones),
++ so they hung
++ - the list of unconnected VCs was sometimes garbled
++ - atmsigd printed null string for as_itf_notify message name when debugging
++ - Arequipa: check_aq_vcc also accepted VCs that were already released by
++ signaling
++ - ATM_VF_PARTIAL and ATM_VF_BOUND had the same value
++ - atmaddr still used old calling convention of ATM_GETNAMES
++ - the atmarpd man page referred to atmarpd as "atmsigd"
++ - various atmtcp bug fixes
++ - atm_recvmsg sometimes returned with interrupts disabled (reported by Pete
++ Wyckoff)
++ - fixed ttcp_atm dependencies (.depend contains dependencies for "ttcp.o")
++ - UNI message format: "more" was missing for def_pck_size
++ - eni/suni didn't compile as modules (fixed by Pete Wyckoff and Ladislav
++ Lhotka)
++ - further net/atm/Makefile cleanup
++ - arequipa_close always left the socket with arequipa_expect enabled. Now it
++ returns it to the previous state.
++ - ENI driver was leaking buffer memory on failure of set_tx
++ - atmarpd didn't print symbolic names of "new" flags (ATF_ARPSRV, etc.)
++ - ATM ARP server didn't make client entries public (reported by Tom Mahieu)
++ - drivers/atm/Config.in had extra "endmenu" (fixed by Ladislav Lhotka)
++ - atmarpd got confused when receiving InARP reply without source ATM address
++ - atmsigd sometimes didn't stop timers if Q.2963.1 wasn't enabled
++ - when rejecting a call, the kernel freed the VCC twice
++
++New features
++------------
++
++ - merged source tree (except Arequipa, single-copy, and various NIC drivers)
++ with 2.1.65-Linus tree
++ - qgen can now handle repeated information elements
++ - added ATM_SETESI[F] ioctl and esi utility (boards without a real ESI in ROM
++ should now set the default ESI to 0x000000000000)
++ - new socket option SO_ATMSAP along with struct atm_sap (using a fixed-size
++ BLLI array instead of the linked list in struct sockaddr_atmsvc)
++ - added Q.2963.1 PCR modification in signaling and the ENI driver
++ - aread: new option -c to print received data as characters (similar to od -c)
++ - new tool test/align to test handling of mis-alignment in NIC drivers
++ - atmsigd now supports policy restrictions for incoming/outgoing calls (see
++ atmsigd.conf.4, "policy")
++ - atmsigd can now also use a pair of named pipes (or, actually, any named
++ object in the file system) for communicating with the user of signaling
++ (normally the kernel)
++ - new tool called "isp" (for "Internal Signaling Protocol") to talk ISP with
++ atmsigd over named pipes
++ - new functions sap2text and text2sap to converts SAPs to/from textual
++ representation, and a sap(7) man page
++ - new traffic parameter field "pcr" to indicate the desired PCR. min_pcr and
++ max_pcr can the be used to indicate the acceptable range.
++ - new function atm_pcr_goal to help drivers to interpret traffic parameters
++
++Other changes
++-------------
++
++ - removed some more obsolete CLIP-related ioctls
++ - qgen: simplified generation of engines with a prefix other than "q" or "qd"
++ - ENI and ZATM drivers now use shareable interrupts
++ - cleaned up some 32bit-isms in ENI driver
++ - cleaned up several 32bit-isms in SSCOP (reported by Tan Chang Hu)
++ - SSCOP: work-arounds for buggy ntohl prototype in some early versions of
++ glibc (reported by Tan Chang Hu, further explored by David S. Miller and
++ Richard Henderson)
++ - started updating the ZATM driver for 2.1 (still crashes under load)
++ - added missing 2.1 pieces in ENI's SUNI driver
++ - added __initfunc and __initdata where appropriate
++ - tools tree now compiles under 0.31 (2.0.25 kernel) and 0.33 (2.1.55 kernel)
++ - gratuitous improvement of identifier tree allocation in qgen
++ - the interface number is now optional for sonetdiag (like for atmdiag)
++ - started implementing the kernel side of point-to-multipoint signaling
++ support
++ - /proc/atm/arp now displays "resolving" or "expired" (with the number of
++ times the entry is referenced) instead of "incomplete".
++ - moved ATM_MAX_BLLI from linux/atm.h to linux/atmsap.h
++ - changed ttcp_atm to use SO_ATMSAP (if available) to set BHLI
++ Note: ttcp_atm previously didn't use a BHLI, so old and new versions of
++ ttcp_atm don't interoperate.
++ - updated all other programs using SAPs too, except for LANE
++ - ENI: failure to allocate a traffic shaper now yields EBUSY instead of EAGAIN
++ - instead of just complaining, the ENI driver now handles all kinds of
++ mis-alignment in the TX path properly
++ - re-implemented send and receive side of Arequipa
++ - merged qgen/uni3x and qgen/uni40 into msg.fmt
++ - added missing Q.2931/UNI 4.0 items to qgen/q2931.h and msg.fmt
++ - also added BLLI L3 H.310 codepoint with related encodings
++ - various file name and identifier changes to give a more appropriate name
++ (e.g. "uni" or "call") to something that's never been Q.2931
++ - added library dependencies
++ - atmsigd produces more readable and usually more comprehensive debugging
++ output
++ - atmsigd.conf.4 now mentions that -d is the debugging output addict's choice
++ - all programs accepting -l syslog now also accept -l stderr. (This is useful
++ for atmsigd if atmsigd.conf sets logging to something else.)
++ - atmsigd now issues ATM_GETADDR ioctls on the signaling socket, not on the
++ kernel socket
++ - WARNING: text2qos: "pcr" is no longer a synonym for "max_pcr" !
++ - text2qos now refuses min_pcr=max
++ - device driver interface: removed vcc->peek; device drivers now choose their
++ own allocation strategy (change motivated by bug report from Furquan Ansari)
++ - drive driver interface: new helper functions atm_charge/atm_return to handle
++ buffer space allocation
++ - device driver interface: vcc->push no longer allocates buffer space. This is
++ now done by the driver, via atm_charge
++ - updated eni, zatm, and atmtcp to use the new mechanism
++ - zero padding in eni driver failed due to mis-alignment on some systems
++ (fixed by Pete Wyckoff)
++ - various compiler warnings removed (by Pete Wyckoff)
++ - removed support for pre-AREQUIPA_WORK mechanism
++ - arequipa close mechanism cleanup
++ - further cleaned up QOS parameter checking
++ - new ISP message as_identify for parallel call processing (not supported yet)
++ - zatm: renamed struct zatm_thist to struct zatm_t_hist after wondering
++ myself what on earth "this t" could be ...
++ - doc/Makefile now invokes dvips with -o
++
++
++Version 0.31 to 0.32 (10-JUL-1997)
++====================
++
++Bug fixes
++---------
++
++ - manipulation of local ATM addresses didn't check for permission
++
++New features
++------------
++
++ - ilmid now supports the system group and a couple of ILMI MIB objects (by
++ Scott Shumate)
++ - device and VCC allocation is now dynamic
++ - E.164 addressing support and corrections to address coding in uni3x/uni40
++ (by S. A. Wright, T. C. Jepsen, and Z. Zhang)
++ - support for device de-allocation via per-device operation dev_close
++
++Other changes
++-------------
++
++ - upgrade to kernel version 2.1.37
++ - ENI driver cleanup (uses readl/writel, skb_put, etc.)
++ - socket option handling has changed: optval is now void * (to improve
++ compile-time type checking) and optlen is int (not int *) in getsockopt
++ - socket option "names" now encode the level and the size (based on an idea of
++ Elwyn Davies)
++ - cleaned up some of the #includes in net/atm/proc.c
++ - total rewrite of ATMTCP (now the data forwarding is done in user space,
++ which makes things slower but a lot more flexible)
++ - separated PDU parsing and printing from SSCOP state machine
++ - new per-device operation dev_close to shut down devices
++ - changed a few DIAG_WARNs to DIAG_INFO in ilmid
++
++Removed features
++----------------
++
++ - polled ATM devices are no longer supported
++ - CLIP is gone (use ATMARP instead)
++ - Arequipa and LANE don't work yet (will come back later)
++
++
++Version 0.30 to 0.31 (22-APR-1997)
++====================
++
++Bug fixes
++---------
++
++ - atmarpd even refused IP address changes by the ATMARP server, which
++ typically led to the creation of one extra SVC
++ - ATMARP timeouts were computed at the wrong place (found by Gerald Hanusch)
++ - aqtest's usage didn't mention the -v option
++ - some tools used 0x%p instead of %p (which is fine in the kernel, by the way)
++ - skb_migrate didn't update skb->list
++ - zeppelin: incurred spurious core dumps on unsuccessful attempts to connect
++ to LANE servers, ESI parsing from command line seg faulted, obtaining ESI
++ from NIC left an ATM socket hanging, man page didn't describe all options
++ (by Marko Kiiskila and Heikki Vatiainen)
++
++Other changes
++-------------
++
++ - arequipa_close now only returns after the Arequipa connection has been
++ successfully closed. This allows applications to reliably close and
++ re-create Arequipa SVCs, e.g. to change the traffic parameters.
++ - the arequipad operations 3rd party close and synchronization are now handled
++ inside the kernel and survive arequipad restarts
++
++
++Version 0.29 to 0.30 (10-APR-1997)
++====================
++
++Bug fixes
++---------
++
++ - atmtcp didn't use vcc->push and therefore got the buffer usage accounting
++ wrong (fix by Gerald Hanusch)
++ - when closing a VC, the ENI driver didn't wait until all TX data has really
++ left the board, which created a close/open race (found by Richard Jones)
++ - SSCOP sometimes omitted the last element in a STAT PDU (fix - even with
++ optimization vs. Q.2110 - by Ngo Bach Long)
++ - atmarpd allowed ARP information to change permanent entries (found by Gerald
++ Hanusch)
++ - atmsigd's get_pvc used the maximum SDU size, thereby wasting buffer space
++ very quickly, which led to signaling problems (reported by Richard Jones and
++ Rik Wade)
++ - oops, the BUGS file was always one version number ahead
++ - ATMARP had a race between packets sent by the remote station and the
++ ATMARP_MKIP ioctl. This caused the dreaded "unknown hw protocol 0xaaaa"
++ error. (Finally fixed thanks to a dump provided by Patrick Flynn)
++ - Arequipa had the same race for AREQUIPA_INCOMING. This probably caused the
++ occasional "loss" (they were actually kept in vcc->recvq until the
++ connection was closed) of the first packet(s).
++
++
++Version 0.28 to 0.29 (4-APR-1997)
++====================
++
++Bug fixes
++---------
++
++ - saal/sscop.c: NORMALIZE macro was weird and broken (fix by Ngo Bach Long)
++ - InARP queries didn't contain the target ATM address, even if it is known,
++ which stretches the allowances RFC1577 makes for violating RFC1293 (found
++ by Juha Heinanen)
++ - tcp_conn_request: Arequipa modification to MTU size calculation used wrong
++ socket (fix by Gerald Hanusch)
++ - kernel ATMARP table handling had some obscure races
++ - temporary work-around: added A2T_LOCAL when using A2T_NAME in atmsigd and
++ atmarpd. Before, systems using ANS where the name server is reached via (IP
++ over) ATM exhibited truly bizarre failure patterns when refreshing ATMARP
++ entries. (With a lot of help from Juha Heinanen)
++ - ditto for arequipad, although the effects were less dramatic
++ - atmarpd: if not using -m, incoming connections for which a valid entry
++ already existed (e.g. due to manual configuration) were not entered in the
++ kernel ATMARP table until after the entry timed out for the first time (by
++ Gerald Hanusch)
++ - skb data areas are now aligned using skb_reserve instead of directly
++ tampering with skb->data (and forgetting skb->tail in the process ...)
++ (found by Uwe Dannowski)
++
++New features
++------------
++
++ - atmarpd is now automatically notified of IP over ATM interfaces already
++ existing at startup. This greatly simplifies the atmarpd restart ritual.
++ (All ATMARP table entries and the default QoS are still lost, though.)
++
++Other changes
++-------------
++
++ - cleaned up some weird and partially dead code in arpd/arp.c (found by
++ Gerald Hanusch)
++ - removed superfluous continue in arp.c:atmarp_setentry
++ - device-driver specific declarations now reside in
++ /usr/include/linux/atm_<drv_name>.h, so that disgusting hacks like
++ #include "/usr/src/linux/..." can be avoided (based on proposal by Uwe
++ Dannowski)
++ - updated the list of supported NICs in README and the on-line help
++ - arpd/atmarpd.8: documented that atmarpd -m may violate RFC1577 in subtle
++ ways (pointed out by Gerald Hanusch)
++ - updated MPR usage description to version 1.5 and removed mpr.patch
++ - removed MEM_DEBUG from the build process (MPR 1.5 initializes itself
++ automatically)
++
++
++Version 0.27 to 0.28 (27-MAR-1997)
++====================
++
++Bug fixes
++---------
++
++ - atmarpd restarted timers on as_valid -> as_valid transitions, illegally
++ delayed necessary refreshes (reported by Juha Heinanen)
++ - SSCOP cleared POLL timer on IDLE timer expiry (fix by Ngo Bach Long)
++ - atmsigd didn't initialize "now" soon enough, causing an unnecessary
++ retransmission of the first BGN PDU (by Ngo Bach Long)
++ - atmsigd responded to RELEASE COMPLETE in ss_rel_ind with a STATUS instead of
++ entering ss_wait_close (by Steve Pope)
++
++New features
++------------
++
++ - new tool aqpvc to declare incoming Arequipa traffic on a PVC to the system
++ (caveat: removing such a PVC can turn out to be surprisingly difficult)
++
++Other changes
++-------------
++
++ - removed some useless code in atmarpd's handling of VC disconnects
++ - removed unused signaling state ss_hold (equivalent to ss_wait_rel)
++
++
++Version 0.26 to 0.27 (11-MAR-1997)
++====================
++
++Bug fixes
++---------
++
++ - oops, forgot to include atm/lib/rtf2e164_cc.pl in the distribution
++ - atmsigd's VCI allocation in -N mode was too simplistic and failed after some
++ signaling activity (reported by Richard Jones)
++ - atm_connect was rejecting ATM_{VPI,VCI}_ANY
++ - aq_prev in the list of Arequipa connections wasn't set properly, leading to
++ random crashes when using Arequipa (found and fixed by Richard Jones, after
++ weeks of tearing his hair out)
++ - arequipa_close didn't remove the Arequipa route, which kept the upper layer
++ protocol connection alive for a rather long time (reported by Richard Jones)
++
++New features
++------------
++
++ - ilmid enhancements: vastly improved retry mechanism, workaround for a bug in
++ the ATML Virata switch, -v option for very detailed debug output (Scott
++ Shumate)
++ - atmsigd now also accepts the signaling VC as a command line argument
++ - qos2text appended colon to traffic type even if nothing else followed
++ - new program debug/aqtest to test Arequipa (based on work by Mehdi Tazi)
++
++Other changes
++-------------
++
++ - added a few missing NULLs to struct atmdev_ops initialization in various
++ drivers (this change does not alter any semantics)
++ - changed printk ...%lx... (unsigned long) ptr to ...%p... ptr at many
++ places
++ - removed atm/lib/rtf2cc.pl and atm/lib/cc.inc (they were only used by an
++ interim version of cc_len)
++ - atmarp's usage no longer contains lines longer than 80 characters
++ - added get_logfile() and get_verbosity() to libatm (for ilmid, by Scott
++ Shumate)
++ - select() consumed CPU time unnecessarily if testing for one direction while
++ there's a lot of activity in the other direction (e.g. atmarpd wasted cycles
++ in select() for each outbound packet while waiting for ARP messages)
++ - the value of ATM_AAL0 has changed (from zero to 13), so all programs using
++ AAL0 need to be recompiled
++ - MAX_ATM_QOS_LEN has changed, so most programs using qos2text need to be
++ recompiled
++ - the AAL can now also be set along with the QoS parameters. This approach
++ should be used instead of specifying it in the socket() call.
++ - if no AAL is specified, the kernel now defaults to AAL5 (was AAL0)
++ - updated most demons, tools, and library functions to set the AAL along with
++ the QoS parameters
++
++
++Version 0.25 to 0.26 (29-JAN-1997)
++====================
++
++Bug fixes
++---------
++
++ - ATMARP VCCs could stay around forever even after timing out, because the
++ process was not woken up.
++ - the ATMARP "fix" in 0.25 introduced an infinite loop. Fixed that one too.
++ - bit 8 in octets 6 and 7 of BLLI ("ext") were set to 1 instead of 0 when
++ using ATM_L2_USER/ATM_L3_USER (reported by ukl2@rz.uni-karlsruhe.de)
++ - qlib added silly offset (which fortunately happened to be zero most of the
++ time) to dumps of large fields (fixed by Jean-Francois Moine)
++ - IP over ATM restricted MTU changes to valid Ethernet MTU sizes
++ - LANE: fixed two bugs that crashed zeppelin when the connection to the
++ servers failed (by Marko Kiiskila)
++
++New features
++------------
++
++ - lib/ans.c now properly computes the length of the country prefix of E.164
++ addresses for reverse lookups (needs file /etc/e164_cc, see USAGE)
++ - if the new -m option is set, atmarpd now merges incoming calls into the
++ ATMARP table if the ATM address is known (see atmarpd.8 for details)
++ - included an RPM spec file (this is still very experimental)
++ - NICStAR driver now also works with IP over ATM (by Stuart Daniel)
++ - usage.txt: added description of how to run ATM NICs back-to-back (by Richard
++ Jones)
++
++Other changes
++-------------
++
++ - signaling traces now also include SAAL up/down transitions
++ - qgen no longer (unnecessarily) depends on libatm.a
++ - started work on letting qgen handle items that appear at more than one
++ place, e.g. repeated IEs (after an idea by Jean-Francois Moine)
++ - did some cleanup and added comments to qlib.[ch]
++ - added -m option to atmarp in config/redhat-4.0/atm.init
++ - added new make target "filenames" to generate a list of all the files which
++ are installed
++ - config/redhat-4.0 now contains an example hosts.atm file and also a Makefile
++ for more convenient installation
++ - atmsigd now reads atmsigd.conf before parsing the command-line options,
++ thereby allowing values set in the file to be superseeded
++ - atmsigd now also logs the internal reference and the caller's address on
++ calls establishment
++ - ilmid: very dirty hack to give switches some time to process ILMI cold start
++ (by Joseph Evans)
++
++
++Version 0.24 to 0.25 (20-DEC-1996)
++====================
++
++Bug fixes
++---------
++
++ - net/atm/atmarp.c:idle_timer_check only expired every other entry (reported
++ by Marko Kiiskila)
++
++New features
++------------
++
++ - LANE now also supports IPX (SNAP and 802.3; by Marko Kiiskila)
++ - NICStAR driver now supports VPI != 0 and has configurable settings in
++ nicstar.h (by Stuart Daniel)
++
++Other changes
++-------------
++
++ - ENI: TX DMA scratch are is now stored per device. This should allow multiple
++ NICs to coexist.
++
++
++Version 0.23 to 0.24 (29-NOV-1996)
++====================
++
++Bug fixes
++---------
++
++ - atm/test/window.c was missing in 0.23
++ - atm/debug/delay didn't build unless atm/lib headers were already installed
++ in /usr/include
++ - atm/debug/znth had undefined return value
++ - SSCOP: fixed typo (that could probably kill the SSCOP connection in case of
++ a retransmission); fix by Olivier Bonaventure
++ - corrected unnecessarily large buffer allocation in zatm.c:pool_index (by
++ Jonathan Larmour)
++ - hosts2ans.pl generated reverse addresses for the domain "ATM.INT" instead of
++ "ATMA.INT"
++ - atmarpd "forgot" any pre-set QOS when receiving new ARP information for the
++ respective entry (reported by Gerald Hanusch)
++ - window scale didn't scale the window sent in the SYNACK packet (reported by
++ Juan-Antonio Ibanez)
++ - LANE: better connection failure handling in zeppelin (by Marko Kiiskila)
++ - LEC kernel timer wasn't restarted when restarting zeppelin (found by Gerald
++ Hanusch, fixed by Marko Kiiskila)
++ - LANE: le_flush_request was sent too early when establishing connection (by
++ Marko Kiiskila)
++ - zeppelin stopped operation (unwantedly) in random cases when LANE servers
++ were down (by Marko Kiiskila)
++ - LANE: non-blocking connections, VCC and LE ARP timeouts, and TLV fields in
++ LE_CONFIG_RESPONSE fixed (by Marko Kiiskila)
++
++New features
++------------
++
++ - atm2text now also uses ANS
++ - signaling traces now also contain error reports from qgen
++ - added new build-time configuration option "CISCO" (in atm/Rules.make) to
++ work around a bug in Cisco's point-to-multipoint signaling
++ - included example configuration files for RedHat 4.0 (see
++ atm/config/redhat-4.0/README)
++
++Other changes
++-------------
++
++ - local variable "link" in atm/debug/delay.c:loop was shadowing "link" system
++ call
++ - cleaned up various Makefiles
++ - qgen: bytes left in qet_space are now more meaningful
++ - named (ANS) now also starts even if atmsigd is not running and retries to
++ create the ATM socket in 15 minute intervals until is succeeds (by Marko
++ Kiiskila)
++ - LANE: (too) short le_flush_responses (Cisco 7010, sw ??.??) are now handled
++ (by Marko Kiiskila)
++
++
++Version 0.22 to 0.23 (16-NOV-1996)
++====================
++
++Bug fixes
++---------
++
++ - fixed stupid typos in atm/lib/atmres.h and an unnecessary dependency on
++ libresolv.a in atm/lib/Makefile (reported by Gerald Hanusch)
++ - fixed warning about implicit declaration of function bigphysarea_init in
++ init/main.c
++ - I think I fixed the SSCOP VR(MR) problems that were first reported by
++ Edouard Lamboray in '95, then by Heinz Schuerch, and that finally led to a
++ total SSCOP breakdown (in 0.22) reported by Gerald Hanusch
++
++New features
++------------
++
++ - integrated the IDT 77201 (NICStAR) driver by Matt Welsh and Stuart Daniel
++ <stuartd@eecs.umich.edu>. Note that this driver currently only supports
++ native ATM.
++ - new throughput and latency benchmark test/window (by Matt Welsh)
++
++Other changes
++-------------
++
++ - upgrade to kernel version 2.0.25
++ - changed drivers/atm/eni.c:do_tx:dma to static in order to reduce kernel
++ stack use (by 480 bytes). Note that this hack may crash systems with more
++ than one ENI adapter.
++ - qlib now also complains if changing a field without a fixed list of values
++ - made a few changes to the native ATM data delivery path to handle some
++ strangeness required by the IDT driver
++
++
++Version 0.21 to 0.22 (13-NOV-1996)
++====================
++
++Bug fixes
++---------
++
++ - (dummy) depend target was missing in atm/man (reported by Bernd Wolf)
++ - net/atm/arequipa.c:make_aq_vcc didn't set ATM_VF_AQINUSE, thereby allowing
++ race conditions to slip through
++ - fixed a few potential race conditions when activating Arequipa
++ - text2qos didn't complain if unit was omitted after multiplier, allowing
++ misleading settings like pcr=50M (that's 19.2 Gbps)
++ - SSCOP: took wrong branch if POLL_AFTER_RETRANSMISSION was enabled (fix by
++ Jonathan Larmour)
++ - SSCOP: rel_ind for ENDAK and BGREJ PDU in sscop_inconn was sent with "user"
++ = 1 (must be 0 for "Source := SSCOP")
++ - initialize_vr_mr now initializes vr_mr to a constant value (instead of
++ garbage plus constant value)
++ - atm_recvmsg now ignores msg->msg_name, as it should by POSIX 1003.1g (fix by
++ Mike Wooten)
++ - atm_sendmsg now fails with EISCONN instead of with EINVAL if msg->msg_name
++ is set, as it should by POSIX 1003.1g (reported by Mike Wooten)
++ - atm_recvmsg and atm_sendmsg now return ENOTCONN if not connected and
++ EOPNOTSUP if flags are passed, as they should by POSIX 1003.1g
++ - the QOS zeppelin uses for its connections can now be set with the option -q
++ - atmarpd didn't include the QOS in PVC entries, so atmarp -a complained about
++ them
++
++New features
++------------
++
++ - kernel changes to support tcpdump with LANE (by Marko Kiiskila)
++ - patch for tcpdump 3.0.4 (installed as tcpdump_atm) to support Classical IP
++ and LANE (by Marko Kiiskila)
++ - patch for BIND 4.9.5 to support ANS (ATM Name Service) functionality (by
++ Marko Kiiskila)
++ - added hierarchy extra/ for packages for which only patches are contained in
++ the ATM on Linux distribution
++ - enhanced text2atm to use ANS if local lookups fail (atm2text will be updated
++ later)
++ - wrote script extra/hosts2ans.pl to convert hosts.atm file to ANS zone files
++
++Other changes
++-------------
++
++ - changed ATM_VF_AQINUSE to ATM_VF_AQDANG and changed aq_list membership to
++ be for dangling VCs only
++ - added the new command-line options to ttcp_atm's online help (finally !)
++ - atm_sendmsg now returns error codes from the driver's send function
++ (suggested by Jonathan Larmour)
++ - text2qos now performs a syntax check if NULL is passed in the qos argument
++ - various minor LANE cleanup (Marko Kiiskila)
++ - upgraded to the latest version of t2a.pl
++ - {A2T,T2A}_REMOTE is obsolete; instead, {A2T,T2A}_LOCAL should be used if
++ ANS lookups are _not_ desired
++
++
++Version 0.20 to 0.21 (18-OCT-1996)
++====================
++
++Bug fixes
++---------
++
++ - net/atm/common.c:atm_connect didn't refuse traffic_class == ATM_NONE in both
++ directions
++ - include/linux/atmsvc.h:SELECT_TOP_PCR didn't default to ATM_MAX_PCR if
++ min_pcr == 0 && max_pcr == 0
++ - debug/delay swallowed one-byte packets
++ - oops, forgot man/Makefile, so qos.7 wasn't installed
++ - atmarpd left max_sdu at zero for automatically generated entries
++ - atmarpd now only uses the default QOS if the traffic type is set in neither
++ direction
++ - signaling: if the listen queue was full, new connections were rejected with
++ as_close instead of as_reject, thereby upsetting atmsigd
++ - svc_accept didn't adjust the listen queue quota when rejecting incoming
++ connection requests
++ - fixed a few bad font selections in atmsigd(8)
++
++New features
++------------
++
++ - included the window scale patch by Randy Scott <scottr@belle.bork.com> and
++ Robert Hill <rhill@tisl.ukans.edu>
++ - -q option for ilmid to set the QOS (like in atmsigd)
++ - new script mkbindist to install the utilities into a tar.gz file
++
++Other changes
++-------------
++
++ - debug/delay now prints the usage if invoked without arguments
++ - removed the pretentious usec resolution for delays in debug/delay
++ - removed the UBR semantics change warning
++ - qos.7: clarified that bps are the user data rate
++ - arequipa_attach_unchecked now also adjusts the upper layer MTU (which can
++ violate RFC1122, but I'll tackle that later)
++ - text2qos now also accepts fractional values, e.g. 9.6kbps
++
++
++Version 0.19 to 0.20 (14-OCT-1996)
++====================
++
++Bug fixes
++---------
++
++ - fixed a few typos and errors in the 0.18 to 0.19 change log
++ - signaling traces only included hl_type bytes instead of hl_length
++ bytes
++ - TNET1570 driver: various fixes (DMA allocation, seg ring overflow,
++ timeouts, etc.) (Christian Paetz)
++ - TNET1570 driver: removed most compiler warnings (Christian Paetz)
++ - listen() on an arequipa_preset() socket and arequipa_preset() on a listening
++ socket now both return EPROTO
++ - oops, forgot to enable the "rm" in make uninstall
++ - kernel didn't set interface number field in act_create messages to atmarpd
++
++New features
++------------
++
++ - added ioctl ATM_SETSC to enable or disable RX and TX single-copy per VC
++ - new device driver operation change_qos (not yet implemented)
++ - TNET1570 driver supports DEC Alphas and 64 bit PCI transfer (for CIA PCI
++ chipsets) (Christian Paetz)
++ - TNET1570 driver also supports the UniNET1570 board (Christian Paetz)
++ - new functions text2qos and qos2text to convert between textual and binary
++ QOS specifications (the format is described in man qos)
++ - atmarp -q ip_addr qos sets the default QOS to use for all VCs created for
++ that IP interface
++ - new utility debug/delay to use machine as AAL5-level delay line
++
++Other changes
++-------------
++
++ - NLPIDs and vendor-specific application identifiers are now collected in
++ the new file /usr/include/atmsap.h
++ - SO_ATMQOS now attempts to change the QOS settings when invoked on an active
++ connection
++ - included Matt Welsh's bigphysarea patch (this isn't related to ATM, but it
++ keeps my development source tree simpler)
++ - arequipa_preset now initializes max_sdu to RFC1626_MTU+RFC1483LLC_LEN if
++ zero
++ - atmarp: new option qos <spec> to set the QOS parameters (uses text2qos)
++ Use of pcr <pcr> is deprecated.
++ - ttcp_atm's -P option now also accepts a QOS specification string. (use of
++ -P <number> is deprecated.
++ - atmsigd: new option -q <qos> and configuration clause io qos <qos> to
++ set the QOS of the signaling VC. Use of -P <pcr> or io pcr <pcr> is
++ deprecated.
++ - removed the backward compatibility #define class traffic_class in
++ linux/atm.h
++ - removed obsolete keywords from atmsigd.conf language
++ - atmarp -a now also includes QOS parameters
++ - UBR now respects txtp.max_pcr if set
++ - new rules for the use of [rt]xtp.traffic_class: both fields must be either
++ equal or zero, e.g. ATM_CBR in TX and ATM_UBR in RX no longer works
++ - doc/usage.tex now points to the man pages instead of repeating their content
++
++
++Version 0.18 to 0.19 (27-SEP-1996)
++====================
++
++Bug fixes
++---------
++
++ - sscop.c:data_sd had a comparison inversed, so generation of USTAT PDUs was
++ wrong in some cases (by Juhana Rasanen)
++ - sigd_enq: accessed vcc->qos without checking for vcc == NULL, causing an
++ "Oops" in atmaddr
++ - svc_accept: generated a general protection fault when atmsigd was killed
++ while a process was waiting for new incoming connections
++ - atmaddr didn't zero the address structure before calling text2atm
++ - LANE: fixed usage of kernel timers and LE_ARP_REQUESTs should now get sent
++ until the entry expires or a response is received (by Marko Kiiskila)
++ - less compiler warnings from LANE servers (Marko Kiiskila)
++ - SSCOP: fixed SDU size in AA-RETRIEVE.indication (reported by Heinz Schuerch)
++ - NULL encapsulation for ATMARP works now (reported by Gerald Hanusch)
++ - fixed stray EINVAL from get{sock,peer}name on PVCs (reported by Gerald
++ Hanusch)
++ - clip now sets max_sdu to RFC1626_MTU+RFC1483LLC_LEN when using LLC/SNAP
++ encapsulation
++ - if parsing of a Q.2931 message fails, atmsigd now aborts the call instead of
++ (stupidly) trying to process the incomplete and probably inconsistent data
++ - SUNI driver didn't properly mask out unused highest bits of some statistics
++ counters, thereby yielding absurdly high values
++ - zatm: changed timing of RX channel closing, so the dreaded "can't close RX
++ channel" message should be history
++ - fixed race between Arequipa attachment due to packet reception and closing
++ of the Arequipa VC
++ - local address validity check (for ATM_???ADDR) was all wrong (reported by
++ David Simpson)
++ - message dumper ignored fatal errors if debugging was not enabled
++
++New features
++------------
++
++ - man pages for lecs, les, bus, and zeppelin (Marko Kiiskila)
++ - configuration file name for les and bus can be defined (Marko Kiiskila)
++ - zatm: new kernel configuration option CONFIG_ATM_ZATM_EXACT_TS now supports
++ reception timestamps with microsecond resolution (the accuracy is only in
++ the ms range, though)
++ - new utility znth (ZeitNet Timer History) to monitor timer synchronization
++ - LANE now supports up to 4 LEC network interfaces (Marko Kiiskila)
++ - the Q.2931 message parser now recovers nicely from IE errors, logs the
++ event, and continues parsing. The higher layers of the signaling stack
++ don't use this information yet, though.
++
++Other changes
++-------------
++
++ - Arequipa's BHLI now uses a "vendor-specific application identifier" under
++ the EPFL OUI
++ - moved buffer/queue handling from lib/libatmd to saal/, because it is rather
++ SSCOP-specific anyway
++ - atm_release_vcc now complains if rx_inuse != 0 when closing (if this ever
++ happens, it may point out dangerous races with upper layer protocols)
++ - SO_ATMQOS now issues a warning when using UBR with {min,max}_pcr != 0
++ - max_sdu is now set by atmarpd to MTU+RFC1483LLC_LEN (atmarp could still
++ override this, if necessary)
++ - atmdump: new option -i to display the arrival interval instead of the
++ absolute time. Also changed the time format to be more readable.
++ - updated the kernel configuration documentation to indicate that the SMC
++ ATM Power155 adapters are compatible with the Efficient ENI-155
++ - atmarpd now deletes the old table file (containing stale information) if
++ invoked with -d (debug)
++
++
++Version 0.17 to 0.18 (9-SEP-1996)
++====================
++
++Bug fixes
++---------
++
++ - atmsigd didn't respond to SETUP followed by RELEASE with a RELEASE COMPLETE
++ - atmsigd now implements incoming call rejection (as_indicate -> as_close)
++ - kernel now opens the VC before sending the as_accept. This a) allows to
++ check if the parameters are acceptable, and b) avoids a race condition
++ between the sender and the local VC open procedure, which frequently led to
++ loss of the beginning of the first PDU sent on a new connection.
++ - qdump: _q_parse used the wrong length when dumping variable-length fields,
++ yielding a fatal internal error
++ - clip didn't set rxtp.max_sdu
++ - svc_accept didn't set ATM_VF_HASQOS, so getsockopt SO_ATMQOS didn't work
++ (by Marko Kiiskila)
++ - ttcp_atm calculated Mbps as 2^20 bits/sec instead of 10^6, thereby making
++ all results come out approximately 5% too low (by Fraz Ahmad)
++ - added $(LDLIBS) to linking of lane/lecs (by Lawrence MacIntyre)
++ - interface number allocation in clip and atmarp did not check for collision
++ with the respective other name space
++ - atmarp's -c option didn't work when omitting the "atm" in the interface name
++
++New features
++------------
++
++ - new man page: arequipad.8
++
++Other changes
++-------------
++
++ - simplified the internal signaling protocol by adding the as_reject message
++ (sent by kernel in response to as_indicate; not acknowledged by demon)
++ - packets received from Arequipa are no longer forwarded to other hosts
++ - further ilmid improvements to use RSTADDR less frequently (by Gerald
++ Hanusch; with a slight modification)
++
++
++Version 0.16 to 0.17 (2-SEP-1996)
++====================
++
++Bug fixes
++---------
++
++ - lib/diag.c didn't fflush when logging to a file
++ - arequipad didn't accept the -l option
++ - qgen: possible weird crashes because second.c:find_required accessed
++ value->tag even if vt_id
++ - qgen: fixed wrong PC indication in one error message in _q_parse
++ - make spotless didn't know about new $(*PGMS) targets
++ - atmsigd: fixed memory leak when sending messages to the kernel
++ - atmarpd: fixed memory leak when sending messages to the network
++ - atmsigd: didn't send final as_close when kernel closed connection
++ immediately after requesting it (as_connect)
++ - several minor corrections
++
++New features
++------------
++
++ - added make target "uninstall" to remove all files installed by
++ make install
++ - atmsigd has two new options: -D dump_dir to set the dump directory and
++ -t trace_length to set the length of the trace buffer
++ - wrote a few man pages: atmarp.8, atmarpd.8, atmsigd.8, atmsigd.conf.4
++ - added automatic support for memory debugging if MPR is installed (and
++ included a patch to make MPR 1.1 work with ELF). atmarpd and atmsigd
++ currently use this feature.
++
++Other changes
++-------------
++
++ - changed "class" to "traffic_class" everywhere
++ - make install is now implemented in a more elegant way
++ - q.dump is now much better at finding symbolic names for numbers
++ - q.dump no longer prints zero-length fields
++ - qgen no longer includes constructor "microcode" in dumper
++ - atmarp now gives more informative error messages on ioctl failure
++ - removed obsolete ioctls SIOCGIFATMADDR and SIOCSIFATMADDR
++ - added hack to allow ilmid to be less hostile to locally configured addresses
++ (by Gerald Hanusch; with slight modifications)
++ - atmarpd now automatically sets ATF_PERM of PVC entries with NULL
++ encapsulation
++
++
++Version 0.15 to 0.16 (29-AUG-1996)
++====================
++
++Bug fixes
++---------
++
++ - fixed an "unterminated character constant" warning by CPP in qgen/uni3x
++ - atm/sigd/q2931.c always tried to read the Cause IE of RELEASE COMPLETE
++ messages even if it wasn't included
++ - LANE: fixed buffer allocation and VCC timeouts (Marko Kiiskila)
++ - LANE: when connecting directly to LES, name of the ELAN was not set
++ properly (discoverd by Gerald Hanusch; fixed by Marko Kiiskila)
++ - LANE, ATMARP, signaling: control sockets didn't account for messages sent
++ back from demons (fixed by Marko Kiiskila)
++ - permanent ATMARP entries for SVCs were ignored if no ATMARP server was
++ configured (reported by Gerald Hanusch)
++ - atmarp option "temp" mis-spelled as "term" (fixed by Gerald Hanusch)
++ - forgot to undo experimental rcvbuf/sndbuf change to unsigned long
++ - make modules didn't generate ATM modules
++ - atmtcp_attach_hook wasn't defined when compiling ATMTCP as a module
++ - ATM patch set dev->ip_atm to ether_arp in net/ppp.c and net/eql.c, so they
++ failed to work as modules
++
++New features
++------------
++
++ - added LANE servers (LECS, LES, and BUS) by Marko Kiiskila
++ - Rules.make: new variable INSTROOT for easier cross-installation
++ - atmsigd: added option -P to set the maximum PCR used on the signaling VC
++ - atmarp: added option "pcr <value>" (proposed by Gerald Hanusch)
++ - added the usual -l <logfile> option to arequipad
++
++Other changes
++-------------
++
++ - upgrade to kernel version 2.0.14
++ - SVCs can now be bound with any SEL value
++ - messages of size > quota can be sent if the send buffer is empty
++ - ilmid no longer empties the address list when refreshing the NSAP address
++ (by Gerald Hanusch)
++ - LANE client should now survive network reset (e.g. restart) gracefully
++ (Marko Kiiskila)
++ - LANE: major cleanup of zeppelin code (Marko Kiiskila)
++ - improved loadable module support for eni and zatm (i.e. loading works now)
++ - the message dumper can now be linked to programs that also use the
++ compilation/parsing functions
++
++
++Version 0.14 to 0.15 (31-JUL-1996)
++====================
++
++Bug fixes
++---------
++
++ - zatm: fixed traffic shaper settings for UBR (with a little help from Joern
++ Wohlrab)
++ - atmsigd compilation didn't use the same UNI version configuration as qgen
++ - field "class" in struct atm_traform broke compilation of ATM applications
++ written in C++, so it has been renamed to "traffic_class" (reported by
++ Furquan Ansari)
++ - AAL parameters IE wasn't included in CONNECT, which violated RFC1755
++ (discovered by Robert Olsson)
++ - zatm: removed broken sanity check for in-sequence skb delivery on RX
++ - clip didn't have clip_open function, so SIOCSIFFLAGS on the interface failed
++ with ENODEV
++ - single-copy compiles again
++ - zatm: driver doesn't pretend any longer to support single-copy (but
++ single-copy will come back later)
++ - QOS IE was sent with the wrong coding standard when using UNI 3.1 (with help
++ from Fraz Ahmad)
++ - zatm: forgot to remove some debugging code (around ZATM_TUNE)
++ - qlib.c didn't zero the length array, leading to (rare) "not enough space"
++ errors from QMSG (actually, the "break" mechanism seems to be flaky - will
++ have to check)
++ - fixed Arequipa race condition when the upper layer protocol and signaling
++ decided to close the SVC at the same time
++ - alloc_tx used to return NULL in out of memory conditions, thereby possibly
++ hanging atm_sendmsg
++
++New features
++------------
++
++ - ttcp_atm now also accepts names with -p
++ - (finally !) added send/receive buffer limits and cleaned up the use of
++ vcc->[rt]x_{inuse,quota}
++ - added mkdiff script for automatic generation of diffs
++ - Arequipa now works for PVCs too (but arequipad is now required for any
++ use of Arequipa, not only for incoming connections)
++
++Other changes
++-------------
++
++ - atm/atm-<version>.patch is now called atm/atm.patch (to make the diffs more
++ useful)
++ - the maximum SDU size is now checked in net/atm/common.c:adjust_tp
++ - text2atm/atm2text now accepts/generates E.164 addresses with a leading +
++ sign, as required by ANS (atm95-1532)
++ - internal signaling protocol: added message as_error to un-overload as_close
++ - internal signaling protocol: split as_establish into as_connect and
++ as_accept
++ - internal signaling prococol: as_close.reply no longer contains positive
++ numbers
++ - internal signaling prococol: as_bind now also carries the AAL type
++ - atmsigd: now also checks the AAL type in as_bind messages
++ - kernel signaling: a few minor changes
++ - STANDARDS (i.e. UNI version) configuration option has been moved from
++ atm/qgen/Makefile to atm/Rules.make
++ - atmsigd's startup message now gives more useful indication of which UNI
++ version(s) it supports
++ - signaling no longer uses sa[sp]_[rt]xtp, so ...
++ - sa[sp]_[rt]xtp is gone
++ - removed atm/sigd/svc.c from the distribution. We now have many other tools
++ for testing SVCs, so it's superfluous.
++ - atmarpd: revalidation is now less frequent (use -DFREQUENT_REVAL for
++ the faster timeout)
++ - ioctl CLIP_PVC now returns the number of the new interface and clip prints
++ its name to standard output (like atmarp -c)
++ - clip now issues the CLIP_PVC ioctl after binding, which avoids wasting
++ interface numbers on failed setup attempts
++ - atmsigd -d now sets the debug level for qgen and SSCOP to DIAG_INFO, and
++ doesn't set q_dump
++ - zatm: added protection against I > M
++ - atm_peek_aal5 now only aligns to page boundaries for pdu_size >= PAGE_SIZE
++ - eni driver now spits out CRC error messages at most every other second
++ - zatm driver now repeats RX error messages at most every other second
++ - ttcp_atm now sleeps for a second after setting up an SVC, because the
++ switch seems to lag behind (need to examine this further)
++ - moved SAAL from sigd/ to saal/ (for sharing with UNI 4.0 signaling)
++ - Arequipa sockets are now closed via arequipad instead of via atmsigd (new
++ ioctls AREQUIPA_CTRL and AREQUIPA_CLS3RD)
++ - various minor changes
++
++
++Version 0.13 to 0.14 (19-JUL-1996)
++====================
++
++Bug fixes
++---------
++
++ - LANE: reaction to LE_ARP_RESPONSE's wasn't always correct
++ - LANE: compiler warnings fixed
++ - LANE: comparing ATM addresses in checking whether connection is formed was
++ wrong
++ - zntune didn't divide by 1024 when displaying the "k"
++ - .depend wasn't deleted by make spotless
++ - ATM_GETSTAT and ATM_GETSTATZ used wrong argument type for coding ioctl
++ number. WARNING: programs using ATM_GETSTAT{,Z} need to be recompiled.
++ - requests to set up SVCs with ATM_NONE in both directions are now caught by
++ svc_connect (used to yield an invalid SETUP message)
++ - signaling: fixed connection identifier setting when acting as network side
++ (fix by Elwyn B Davies)
++ - ATMARP server ARP entries were undeletable
++ - atmarp showed wrong argument in error message when given an invalid ATM
++ address
++ - zatm: do_tx left interrupts turned off when returning with RING_BUSY
++ - LANE ARP hash table handling bugs fixed
++ - atmarp: act_create is now only sent on interface creation
++ - atmarp: act_down is now only sent once per transition
++ - demon control SVCs are no longer closed when atmsigd dies (new VCC flag
++ ATM_VF_META)
++ - netdevice notifier is now properly unregistered when atmarpd goes down
++ (not doing so caused endless loop in kernel on atmarpd restart)
++ - sigd_enq{_atomic} never calls schedule()
++ - atmsigd no longer "forgets" to bring up ARP server SVC before sending an
++ InARP
++ - atmarpd no longer dies with "timer in state 3" when the ARP server becomes
++ unreachable
++ - atm/atmarp.c: clip_create() now refuses creation of already existing
++ interface
++ - Documentation/Configure.help gave an obsolete URL for CONFIG_AREQUIPA
++ and doc/usage.tex also mentioned the old file name
++ - Arequipa didn't work in the outbound direction for TCP, because
++ net/ipv4/tcp.c was missing in the kernel patch
++ - drivers/atm/eni.c:foo raced with initialization of eni_boards if the
++ board lost the signal _immediately_ after being initialized
++ - atmarpd: fixed a few uninitialized entry->timer pointers (discovered by
++ Gerald Hanusch)
++ - atmarpd: arps entry should no longer get stuck in as_resolv
++
++New features
++------------
++
++ - compiles on SparcLinux too (but only atmtcp works)
++
++Other changes
++-------------
++
++ - upgrade to kernel version 2.0.0
++ - BHLI matching changed: SAPs without BHLI are now incompatible with calls
++ that specify a BHLI
++ - LANE: interface stays up when zeppelin dies -> possibility for
++ wrapper script around zeppelin
++ - LANE: LUNI interoperability test (ATM Forum/96-0805) is now followed
++ in setting ELAN name in LE_CONFIG_RESPONSE and LE_JOIN_RESPONSE,
++ there is also a delay of 1 second before sending LE_CONFIG_REQUEST and
++ LE_JOIN_REQUEST. This allows 'slow' LE servers to catch up.
++ - LANE: no longer uses sa[sp]_[rt]xtp
++ - LANE: now adjusts better to ATM address changes
++ - zeppelin: new option -m to select debugging output
++ - updated aping, aread, awrite, br, bw, atmdump, ilmid, atmarp, clip, atmarpd,
++ and zeppelin to use setsockopt SO_ATMQOS
++ - added option -x for ilmid to disable variable bindings (caused
++ interoperability problems with certain switches, e.g. the LS100)
++ - changed SO_CIRANGE into a pair of ioctls
++ - changed return value of fetch() (passed to atm_vcc->peek) from unsigned long
++ to __u32
++ - atmarp now accepts arpsrv option also for -d
++ - zatm driver can now also read ESIs of rev. 10 boards (with help from Nikos
++ Anerousis)
++ - awrite: fixed txtp.max_sdu calculation in awrite (was using uninitialized
++ variable "offset")
++ - atmarpd: IP interface removal now has the desired effect (used to do
++ nothing)
++ - atmarpd: now reports and ignores unexpected interface transitions
++ - added sigd_enq_atomic for atomic sigd_enq (so that non-Arequipa SVCs can
++ still use the "safe" but non-atomic version)
++ - made SIOCGIF* failures in atmarpd non-fatal (itf.c:itf_up was handling them
++ anyway)
++ - moved Arequipa-specific code from net/atm/clip.c to net/atm/arequipa.c, and
++ put code common to CLIP, Arequipa, and - to a lesser extent - ATMARP into
++ net/atm/ipcommon.[ch]
++ - Arequipa can now be complied without CLIP
++ - various minor documentation changes
++ - moved ATM device initialization from net/atm/pvc.c to drivers/block/genhd.c,
++ where most other devices are initialized too
++ - preparation for new binary locations: tools build process now knows about
++ four types of programs: for booting, for system use, for users, and for
++ internal use during build
++ - make install now hides the for loops
++ - non-user binaries are now installed in /usr/local/sbin
++ - struct atm_iobuf.buffer is now of type void * (was int*). Also,
++ ATM_GETNAMES now returns the length in bytes in that field.
++
++
++Version 0.12 to 0.13 (7-JUN-1996)
++====================
++
++Bug fixes
++---------
++
++ - BHLI type used the ATM_HL_* values (which are off by one) in qgen/uni3x
++ - atmarpd ended up in a tight select-accept loop if atmsigd went away
++ - removed sleep in ZATM's do_tx (so it works with IP over ATM again)
++
++New features
++------------
++
++ - added experimental support for Application requested IP over ATM (Arequipa),
++ prototyped by Jean-Michel Pittet
++ - new traffic class ATM_ANYCLASS to accept incoming SVCs without looking at
++ the traffic parameters
++ - added (untested) support for SO_BCTXOPT/SO_BCRXOPT
++
++Other changes
++-------------
++
++ - SVCs used to listen are now marked as "LISTEN" in /proc/atm/svc
++ - added option -Q <atm_addr> to ttcp_atm to support AREQUIPA
++ - cleaned up the FILE macro and removed atm_dir in net/atm/proc.c
++
++
++Version 0.11 to 0.12 (3-JUN-1996)
++====================
++
++Bug fixes
++---------
++
++ - atm/lib/Makefile: had to comment out PGMS=test
++ - distribution didn't include atm/doc/usage.txt
++ - patch didn't include arch/i386/config.in
++ - return 0; was missing at the end of net/atm/mmuio.c:mmu_step
++ - atm/ilmid didn't install into INSTBIN; also made some other Makefile
++ changes
++ - read() returned garbage instead of error when network drops connections
++ - POLL_AFTER_RETRANSMISSION in SSCOP didn't even compile
++ - SVCs: bind to wildcard addresses should now work even if no local address
++ is known yet
++ - make clean in atm/qgen left some dirt
++ - ATM drivers didn't free skbs when detecting an error in TX direction
++ - SIOCMKCLIP was in the wrong #ifdef, so CLIP had to be enabled to make
++ ATMARP usable
++ - signaling didn't respond properly to messages with non-existent call
++ reference
++
++New features
++------------
++
++ - merged in LAN Emulation client support written by Marko Kiiskila
++ - new socket option SO_ATMQOS at SOL_ATM to set/get QOS parameters
++
++Other changes
++-------------
++
++ - t2a.pl now also works with Perl 5.001
++ - changed the TX side of the ZATM driver to use a ring instead of a list in
++ order to improve stability and throughput (needs some more testing)
++
++
++Version 0.10 to 0.11 (21-MAY-1996)
++====================
++
++Bug fixes
++---------
++
++ - README.DRIVERS still referenced INSTALL (it's now in USAGE)
++ - sap_decode didn't clear BLLI part of address structure
++ - trying to connect to NULL address fails locally instead of yielding an
++ invalid SETUP message
++ - bind now properly sets the local address
++ - SVC getname now returns the traffic parameters
++ - oops, zatm open_tx didn't return PCR
++ - awrite printed errors for connect() as "bind: ..."
++ - atmsigd no longer generates dummy call references (0x7fffff)
++ - atmtcp: changed a few kfree_skb to dev_kfree_skb, which should make it
++ work better (does anybody care to try ?)
++ - some more dev_kfree_skb fixed for control messages from or to demons (led
++ to some minor memory leaks)
++ - various major fixes for CBR SVCs
++ - RELEASE was signaled for SVCs before all data was sent
++ - single copy tried to access mem_map with user space addresses, leading to
++ crashes or worse
++ - zatm: sleep_on was racing with TX completion in close_tx, leading to hangs
++ - zatm: now fails attempts to open AAL0 VCs (used to accept them and to
++ crash later)
++ - BHLI encoding/decoding was broken in several ways
++
++New features
++------------
++
++ - hacked in primitive leaf-only p2m support (based on an idea by Marko
++ Kiiskil{)
++ - the socket layer, and the zatm, eni, and atmtcp drivers now support
++ two-phase connect
++ - PVCs now respect max_pcr (SVCs can't for now)
++ - lib/diag.c can now also log to a file or to syslog, and atmarpd, atmsigd,
++ and ilmid now have a -l option to use that
++ - new option -c config_file for atmsigd
++ - zatm and atmtcp now also support timestamps (but zatm timestamps can be
++ improved a lot by using the timestamps the uPD98401 generates)
++ - Classical IP over ATM support is now configurable
++ - added on-line help texts for configuration
++ - added atm/test/aping, a round-trip tester for PVCs
++ - added "flags" field to struct atm_dev and to atm_dev_register, on request
++ by Bureau 13
++
++Other changes
++-------------
++
++ - past versions of the BUGS list aren't included in the distribution anymore
++ because I didn't update them anyway
++ - invalid connect() calls now return an error instead of panicing atmsigd
++ - text2atm no longer clobbers sas_addr.{blli,bhli}
++ - greatly simplified zatm traffic shaper settings calculation (and it's
++ better than before too)
++ - atmsigd: diagnostics class "sig" (in atmsigd.conf) now also includes "SAP"
++ - DPRINTK now uses GNU-specific #define foo(bar...)
++ - signaling: PCR is now also indicated (0) for directions in which ATM_NONE
++ is requested, which is probably "cleaner" (for CBR)
++ - added logging priorities to most printks
++ - the default location for atmsigd.conf changed from . to /etc
++ - ipv4/af_inet.c: atmtcp_attach_hook is now only included when using ATM over
++ TCP
++ - configuration options for extended driver debugging, (old) CLIP, and
++ ATM over TCP are turned off by default
++
++
++Version 0.9 to 0.10 (21-MAR-1996)
++===================
++
++Bug fixes
++---------
++
++ - zatm: deallocated UBR shaper when closing UBR VC, which the other UBR VCs
++ didn't really appreciate
++ - fixed nasty memory leak for native ATM (spotted by Rolf Fiedler)
++
++New features
++------------
++
++ - added Rolf Fiedler's driver for his adapter based on the TI TNETA1570
++ - single-copy is back again !
++
++Other changes
++-------------
++
++ - eni buffers are now slightly (50%) bigger, allowing for more effective
++ overlapped operations
++ - documented zntune
++
++
++Version 0.8 to 0.9 (14-MAR-1996)
++==================
++
++Bug fixes
++---------
++
++ - oops, accidently removed ZN1221 from drivers/pci/pci.c (so /proc/pci
++ reported it as "unknown")
++ - sigd didn't poll for the default interface on startup
++ - atmarpd didn't initialize timer field in newly allocated table entries,
++ which led to crashes
++ - removed a few stray debugging printks in net/atm/svc.c:svc_bind
++ - ATMARP tried to send queued packet before adding new table entry, so the
++ packet was always discarded
++ - sigd/sap.c: didn't allow to use different traffic classes for fwd and bwd
++ direction
++ - atm2text accepted SVC addresses of all zeroes
++ - atmsigd didn't refresh its local address list properly after ilmid restart
++ - net/atm/common.c: returned positive error codes (-vcc->reply) instead of
++ negative ones
++ - forgot to include maint/zntune.c in the distribution
++
++New features
++------------
++
++ - sigd/svc now accepts ATM addresses in all formats supported by text2atm
++
++Other changes
++-------------
++
++ - upgraded to kernel version 1.3.73
++ - the called party number must now match the local address (if bound)
++ - renamed ttcp.atm to ttcp_atm
++ - all executables are now explicitly linked (so make works even without
++ dependencies)
++
++
++Version 0.7 to 0.8 (12-MAR-1996)
++==================
++
++Bug fixes
++---------
++
++ - fixed stray segmentation violation in arpd/arp.c:learn
++ - fixed coding standard of the QoS IE if using UNI 3.0 (and made coding
++ standard variable)
++ - made coding standard variable for Cause IE
++ - SSCOP didn't properly set N(MR)
++ - list elements in STAT PDUs had host byte order
++ - SSCF didn't call sscop_estab_resp on restart (AA-EST.ind in 1/1)
++ - signaling didn't handle SAPs with >= 2 BLLI IEs properly
++ - uni3x: iso_hli and user_hli were confined to 7 bytes, but UNI allows up to 8
++ - q_read choked on non-variable-length fields
++ - qgen sometimes didn't read all IEs of a signaling message
++ - fixed usage line of test/bw
++ - qgen no longer complains about missing required fields after a break
++ - fixed compiler warning in zntune.c
++ - fixed ATMARP table additions (caused GPF when flushing ATMARP entry at
++ the end of the table and possibly other problems)
++ - qgen: q_put or'ed data instead of overwriting it, which caused problems
++ only on surprisingly few occasions
++
++New features
++------------
++
++ - atm2text and text2atm now also do name lookups via a /etc/hosts.atm file
++ - atmaddr, atmarpd, and atmsigd now pretty-print addresses using name
++ translation (unless invoked with -n)
++ - atmarpd now dumps its table into /var/run/atmarpd.table and atmarp -a
++ reads it from there
++ - started modularizing the ENI and ZATM drivers
++ - ilmid and atmsigd now support multiple interfaces (untested)
++
++Other changes
++-------------
++
++ - the documentation is now available in LaTeX and in ASCII
++ - rewrote most of the SAP handling code (now everything is in sigd/sap.c)
++ - proto.c:lookup_sap now picks wildcard SAP last
++ - signaling always includes SSCS type = 0 in SETUP messages (for LANE)
++ - changed the message format for the the kernel-demon signaling protocol
++ - qgen is now a bit more tolerant when being fed with bad data
++ - qgen now assumes that q_report(Q_FATAL,...) doesn't return
++ - marked sigd/test.c as obsolete
++ - svc_accept failing in atm_connect no longer returns success
++ - atmsigd -n is now atmsigd -N
++ - qgen now puts the PC in q.out.c and qd.out.c at the beginning of the code
++ line and not on a line by itself
++
++
++Version 0.6 to 0.7 (2-FEB-1996)
++==================
++
++Bug fixes
++---------
++
++ - removed TTL setting ioctl (1234) used for something entirely unrelated to
++ ATM, oops
++ - changed kfree_skb in atm_pop_raw to dev_kfree_skb (this fixes the socket
++ "leak")
++ - more unusual configurations (no PCI, no IP, no /proc) should compile now
++ - atm_equal didn't recognize wildcards in embedded E.164 addresses
++ - fixed net/atm/proc.c:svc_addr (too many bugs to mention)
++ - atmarpd didn't check for ARP traffic on inbound connections
++ - atmarpd didn't properly merge incoming connections with existing entries
++ - various other ATMARP fixes
++ - free list was too short in ENI driver for worst case fragmentation on
++ 2 MB boards
++ - signaling didn't set ISO/IEC TR9577 IPI and NLPID correctly in active open
++ - getname looked at *sockaddr_len, which is uninitialized (need to fix this
++ later in the common socket code)
++ - SSCOP generated incorrect error code ("1" instead of "B") for BGN PDU
++ problems
++
++New features
++------------
++
++ - new ioctls ATM_GETADDR, ATM_RSTADDR, ATM_ADDADDR, and ATM_DELADDR to
++ manage local ATM addresses
++ - signaling now handles incoming RESTART, SAAL failure, and SAAL
++ re-establishment
++ - ATMARP now times out idle connection; ATMARP_MKIP ioctl takes a timeout
++ argument
++ - ATMARP (kernel) now queues one skb per pending ARP request and limits the
++ rate of requests for the same address (default 2 req/min)
++ - atmsigd now prints cause values when receiving a RELEASE or a RELEASE
++ COMPLETE and returns more informative error codes
++ - atmarpd falls back to PVC-only operation if signaling is unavailable at
++ startup
++ - kernel can now assign next free number on IP interface creation (atmarp
++ prints the interface name)
++ - qgen -D generates a Q.2931 message dumper (see USAGE for details)
++ - qgen now checks for proper use of repetition indicator (but doesn't
++ support repeated IEs yet)
++ - protocols and device drivers can now use their own memory allocator in the
++ TX direction by changing vcc->alloc_tx
++
++Other changes
++-------------
++
++ - upgraded to kernel version 1.3.53
++ - build process now uses Perl
++ - ATM ioctls writing back data now always return the size of the data
++ structure written
++ - struct atmif_sioc now has a length field (recompile all atmarpd, ilmid,
++ debug/ed, and everything in maint)
++ - PHY driver no longer has to check validity (permissions and access) for
++ "standard" ioctls
++ - signaling should now also work on an interface > 0 (but there's still only
++ one interface using signaling per host)
++ - make install now adds /usr/include/atm.h and /usr/include/atmd.h
++ - atmarpd now also displays if SVC has been opened actively or passively
++ - atmaddr(8) now uses new ioctls and has different command-line syntax
++ and even has a man page
++ - example IP addresses in USAGE now conform to RFC1597
++ - diagnostics now also include the application name (optional)
++
++
++Version 0.5 to 0.6 (21-DEC-1995)
++==================
++
++Bug fixes
++---------
++
++ - ARP ioctls stopped working for most non-ATM devices, oops
++ - ATMTCP driver counted lack of memory as rx_err instead of rx_drop
++ - select on driver using polling may have hung
++ - atmarp man page and usage didn't indicate that the interface number is
++ optional
++ - restricted atmarpd and signaling control, and SIOCSIFATMADDR to the super
++ user
++ - atmtcp: fixed handling of VPI/VCI <= 0 for setsockopt(SO_CIRANGE)
++ - eni and zn driver had static UBR shaper pointer, making it difficult to have
++ more than one such device per system
++ - eni driver initialization didn't work properly in systems with ASIC Tonga
++ - suni.[ch]: confused MC (Master Config) and MCT (Master ConTrol) registers
++ - (SVC) accept now returns PVC -EAGAIN as -EBUSY because the operation cannot
++ be retried
++ - qgen: fixed several bugs in case handling (and made defaults work for
++ parsing)
++ - svc_dup passed PF_ATMSVC instead of AAL to svc_create
++ - plugged a few skb leaks in svc_accept
++ - text2atm didn't properly NUL-terminate E.164 addresses
++
++New features
++------------
++
++ - ZN1221 driver works partially for AAL5 (still hangs after a few dozen MB)
++ (also wrote maint/zntune to monitor/adjust free buffer pools)
++ - ENI driver now supports new Tonga ASIC boards
++ - added Scott Shumate's ILMI demon (for automatic address registration)
++ - text2atm: added wildcard support for SVCs (syntax: addr/bits)
++ - new library function atm_equal to compare SVC addresses
++ - new ioctl ATM_GETTYPE to obtain interface type name
++ - new ioctl ATM_GETESI to obtain ESI (parallels /proc/atm/devices)
++ - new ioctls SONET_SETFRAMING, SONET_GETFRAMING, and SONET_GETFRSENSE to
++ handle SONET vs. SDH framing
++ - added socket option SO_AALTYPE (SOL_AAL) to query AAL type (getsockopt
++ only)
++ - signaling demon is now notified on address changes (new message
++ as_itf_notify)
++
++Other changes
++-------------
++
++ - known bugs are now listed in a file called BUGS
++ - all utility programs (aread, awrite, atmdump, br, bw, clip, ttcp) now use
++ the notation [itf.]vpi.vci for PVCs (was itf vpi vci , except for ttcp,
++ where it was only vpi vci (no itf))
++ - all ioctl values have changed
++ Note: most programs have to be recompiled because of this
++ - sigd and arpd now register their control sockets via ioctls
++ - (old) clip now creates interfaces with an ioctl
++ - text2atm now returns the wildcard length, i.e. a non-zero return value
++ no longer implies failure
++ - push_oam now returns an int (was void)
++ - push_oam now has several flags (in a bit set) instead of the immed
++ argument
++ - the peek function must now update the statistics if it rejects a packet
++ - (ATM device) close is now only invoked after a successful open
++ - the SUNI_GETLOOP ioctl now has an int * argument (was unsigned long *)
++ - uPD98402 driver no longer tries to detect return of the signal (didn't
++ work anyway - would have to sample section errors)
++ - ATMARP no longer supports mixed PVC/SVC entries (I'm sure this will be
++ missed a lot :-)
++ - ATMARP no longer supports "IP address discovery" via InARP for PVCs
++ (maybe later)
++ - specifying an invalid AAL now yields EPROTOTYPE
++ - specifying an invalid address family (connect, bind) now yields EAFNOSUPPORT
++ - make install now also installs libraries (in /usr/lib)
++ - improved many header file comments
++ - re-arranged some comments to simplify automated document generation
++ - added copyright statement
++ - UNI 3.0 IE fields are now always recognized (but we shouldn't generate them)
++ - UNI 3.0 wants octet 5a when using BCOB-X, so we'll set it to twice "No
++ indication"
++ - aread, awrite, br, bw, ttcp, atmsigd, and atmdump now set max_sdu
++ - aread and awrite no longer print strerror(errno) on success
++
++
++Version 0.4 to 0.5 (26-OCT-1995)
++==================
++
++Bug fixes
++---------
++
++ - now only root can open a CLIP socket (thereby creating an IP interface)
++ - now only root can issue CLIP_NULENCAP and CLIP_LLCENCAP ioctls
++ - atmdump: forgot default in getopt switch
++ - eni driver: called misc_int on every interrupt
++ - Q.2931 message description: various fixes and improvements
++ - linux/atm.h: ATM_*_UNSPEC used the same value as ATM_*_ANY, oops !
++ - SSCOP is now more careful about not accessing the descriptor if it might
++ possibly have been deleted
++ - typo in SSCF leading to wrong response to AA-RECOVER.indication
++ - SSCOP now correctly copies N(PS) from POLL to STAT PDUs
++ - SSCF now discards data when not ready instead of issuing a fatal error
++ - AAL initialization failure no longer leaks memory
++ - closing an SVC without VCC no longer yields a GPF
++
++New features
++------------
++
++ - ZN1221 driver is starting to work
++ - new, ARP-based mechanism for IP over ATM (with atmarpd, atmarp, etc.)
++ - /proc/atm/pvc now displays more information for CLIP PVCs (after a patch
++ by Raghavan Menon)
++ - added max_pcr to struct atm_trafprm (also fixed a few comments in atm.h)
++ Note: all programs using sockaddr_atm* will have to be recompiled.
++ - qgen now handles value lists in named selections
++ - signaling now supports bhli/blli, plus various other minor extensions
++ - new ioctls to set/get local ATM address
++ - added library with address to/from text conversion functions
++ - finally implemented getname()
++
++Other changes
++-------------
++
++ - eni driver: avoided potential generation of superfluous code if extended
++ debugging is disabled
++ - eni driver: detects new boards using ASIC PCI chip (doesn't support them
++ yet, though)
++ - qgen: semicolon is now comment character and no longer used to terminate
++ clauses
++ - qgen: replaced term "item" with "field"
++ - linux/include/atmsap.h: removed obsolete comment "protocol cannot be fully
++ encoded in current structure". Also re-arranged some comments to simplify
++ automated document generation.
++ - saal,sscf,sscop: callbacks don't pass the pointer to the descriptor of the
++ calling protocol anymore
++ - SSCOP no longer prints a number for non-'V' errors
++ - improved handling of STATUS messages
++ - select now indicates ready for writing if max_sdu packet can be enqueued
++ without blocking
++ - select can now also be used to check status of non-blocking connect
++ - moved some common demon functions from sigd into a common demon library
++
++
++Version 0.3 to 0.4 (27-SEP-1995)
++==================
++
++Bug fixes
++---------
++
++ - various minor documentation fixes
++ - clip.c:atm_push_clip now updates statistics before forwarding the skb to
++ the upper layer (which may free and overwrite the skb)
++
++New features
++------------
++
++ - added partial UNI 3.x signaling
++ - added various adapter debugging programs to the distribution
++ - new config option CONFIG_ATM_ENI_DEBUG to enable extended debugging
++ in eni driver
++
++Other changes
++-------------
++
++ - upgraded to kernel version 1.3.24
++ - changed the distribution directory structure (programs are now in maint/,
++ test/, ip/, debug/, and sigd/, see INSTALL)
++ - ATM interfaces are no longer named, only numbered. This affects the
++ ATM_GETNAMES ioctl, all ioctls using struct atmif_sioc, the usage of atmdiag
++ and sonetdiag, and various diagnostic kernel messages.
++ - ATM socket state is now recorded in field "flags" (this also replaces the
++ SVC fields "released", "registered", and "state")
++ - added #ifdef __KERNEL__ to some header files
++ - added "int immed" argument to send_oam
++ - some minor modifications to the distribution process (mkdist)
++ - removed devmap.c
++ - SVC sockets no longer hang if the signaling demon dies
++
++
++Version 0.2 to 0.3 (8-SEP-1995)
++==================
++
++Bug fixes
++---------
++
++ - select(2) didn't work (was sleeping on sock->wait instead of
++ &ATM_SD(sock)->sleep)
++ - ENI driver did allow binding to VPI/VCI already in use
++ - ENI driver now properly handles PDUs with CRC errors
++ - ENI driver had race condition when discarding PDUs causing new PDUs to be
++ shifted in adapter memory by one word (which confused the driver quite a
++ bit)
++ - ENI driver now enables VC _after_ setting all pointers (caused crashes if
++ data was already coming in while opening VC)
++ - various bugs fixes related to SVC sockets
++ - fixed GPF (in kernel) when running atmdiag without arguments
++ - atmdiag now left-adjusts interface names
++ - fixed ttcp.atm crash when not specifying vpi.vci
++ - clip_xmit now checks for NULL vcc (e.g. after failure to connect)
++
++New features
++------------
++
++ - zatm driver now reads ESI correctly
++ - blocking svc_connect is now interruptible
++ - atmdump now also displays the numeric PTI value of incoming cells
++ - added RX/TX buffer quotas (default is 64 kB)
++ - added OAM hooks to device driver interface (but there's no OAM support yet)
++
++Other changes
++-------------
++
++ - ENI driver now checks ID field of reassembly buffer descriptors
++ - ENI driver now uses vremap
++ - ENI driver now prints more useful physical layer type information (e.g.
++ "MMF" and "UTP" instead of "UTOPIA")
++ - some redesign of the protocol used for signaling between kernel and demon
++ - disabled "Grr, servicing VCC twice" message in ENI driver
++ - device drivers now have to adapt AAL0 cell header byte order
++ - some cleanup in common.c:atm_getsockopt
++ - device drivers are now required to use the peek function; protocols now
++ must provide it
++
++
++Version 0.1 to 0.2 (15-AUG-1995)
++==================
++
++Bug fixes
++---------
++
++ - VCC family field is now correctly set to protocol family in
++ common.c:atm_create (was pvc.c:pvc_create). With protocol set to zero,
++ this created all types of strange problems, because the family field
++ is used to indicate whether an VCC slot is busy/free.
++ - fixed race condition in common.c:atm_read (reader might have blocked
++ even if data is ready)
++ - fixed dereferencing of uninitialized skb->dev pointer in
++ clip.c:atm_push_clip
++ - SIOCSIFATMTCP now refuses to attach the same socket twice
++ - zatm.c: fixed setting of the VPI/VCI mask
++ - USAGE said ttcp uses -B for the bandwidth, but it's -P
++ - mkdist didn't include man pages
++
++New features
++------------
++
++ - added some /proc/atm functionality
++ - added support for ATM_{VPI,VCI}_ANY
++ - SIOCSIFATMTCP now returns the interface number and atmtcp(8) prints it
++ - wrote atmtcp man page
++ - added kernel part of SVC support
++
++Other changes
++-------------
++
++ - common.c: only root is now allowed to bind to reserved VCIs
++ - Classical IP interfaces are now removed by downing by ifconfig; clip(8)
++ returns immediately
++ - PVC-connect for non-existing device now returns ENODEV instead of EINVAL
++ - new field (type) in struct atm_dev to indicate device type
++ - moved getsockopt(SO_CIRANGE) to common.c (removed atmtcp's own version)
++ - added ci_range to struct atm_dev (and removed it from atmtcp's private
++ structure)
++ - added code to read the ESI to zatm.c (but that code doesn't seem to work
++ yet)
+--- linux-atm-2.4.1.orig/debian/atm-tools-br2684.manpages
++++ linux-atm-2.4.1/debian/atm-tools-br2684.manpages
+@@ -0,0 +1 @@
++debian/tmp/usr/share/man/man8/br2684ctl.8
+--- linux-atm-2.4.1.orig/debian/atm-tools.atm
++++ linux-atm-2.4.1/debian/atm-tools.atm
+@@ -0,0 +1,27 @@
++#!/bin/sh
++# Start/stop the atm daemon(s).
++
++DAEMON="/sbin/atmarpd"
++
++test -f $DAEMON || exit 0
++
++case "$1" in
++start) echo -n "Starting ATM ARP Daemon: "
++ start-stop-daemon --start --quiet --exec $DAEMON -b
++ /bin/sleep 2
++ echo "atmarpd."
++ ;;
++stop) echo -n "Stopping ATM ARP Daemon: "
++ start-stop-daemon --stop --quiet --exec $DAEMON
++ echo "atmarpd."
++ ;;
++restart|force-reload) echo -n "Re-starting ATM ARP Daemon: "
++ start-stop-daemon --stop --quiet --exec $DAEMON
++ start-stop-daemon --start --quiet --exec $DAEMON -b
++ /bin/sleep 2
++ echo "atmarpd."
++ ;;
++*) echo "Usage: /etc/init.d/atm start|stop|restart|force-reload"; exit 1
++ ;;
++esac
++exit 0
+--- linux-atm-2.4.1.orig/debian/atm-tools.docs
++++ linux-atm-2.4.1/debian/atm-tools.docs
+@@ -0,0 +1,4 @@
++BUGS
++README
++doc/README.tc
++debian/README.br2684
+--- linux-atm-2.4.1.orig/debian/control.old
++++ linux-atm-2.4.1/debian/control.old
+@@ -0,0 +1,72 @@
++Source: linux-atm
++Section: net
++Priority: optional
++Maintainer: Peter De Schrijver (p2) <p2@mind.be>
++Build-Depends: debhelper (>> 4.0.0), bison, flex, perl, dpatch, automake1.4
++Standards-Version: 3.6.1
++
++Package: atm-tools
++Architecture: any
++Depends: ${shlibs:Depends}
++Description: Base programs for ATM in Linux, the net-tools for ATM
++ This package provides all the basic programs needed for setting up,
++ monitoring and tuning ATM networks. Such as:
++ * atmsigd, an ATM signal daemon that implements the ATM UNI protocol.
++ * atmtcp, a tool to setup ATM over TCP connections.
++ * atmarpd, an implementation of the ATMARP protocol (RFC1577, RFC1755)
++ * zeppelin, an ATM LAN Emulation client daemon
++ * les and bus, ATM LAN Emulation service daemons
++ .
++ Notice that upstream still flags these tools as experimental software and
++ says that there is still a number of known bugs and issues. The
++ software is, however, in productive use at a number of sites and is
++ working reliably.
++ .
++ Homepage: http://linux-atm.sourceforge.net/
++
++Package: atm-tools-br2684
++Architecture: any
++Depends: ${shlibs:Depends}
++Description: br2864ctl - RFC1483/2864 Bridge Daemon for ATM Networks
++ br2684ctl handles RFC1483/2684 bridged PDUs. This is most often
++ used in ADSL scenarios where usually the subscribers' ethernet
++ traffic is encapsulated in ATM AAL5 (by bridging ADSL modems)
++ according to RFC2684
++ .
++ The sources for br2684ctl has been pulled from linux-atm's CVS
++ repository. Warning: This is unreleased software that can break any
++ time, any place. If it does, you get to keep the pieces. linux-atm's
++ upstream flags even the released software as experimental software.
++ There is still a number of known bugs and issues.
++
++Package: atm-dev
++Depends: libatm1-dev
++Architecture: all
++Section: oldlibs
++Description: Development files for compiling ATM programs (dummy package)
++ This dummy package provides a transition from the previous atm packages.
++ It is provided for backwards compatibility only and may be removedafter
++ the upgrade has completed or when when no other package depend on it.
++
++Package: libatm1
++Section: libs
++Architecture: any
++Depends: ${shlibs:Depends}
++Conflicts: atm-tools (<< 2.4.1-6)
++Description: shared library for ATM (Asynchronous Transfer Mode)
++ Shared libraries needed by ATM (Asynchronous Transfer Mode) related programs
++ .
++ Homepage: http://linux-atm.sourceforge.net/
++
++Package: libatm1-dev
++Section: libdevel
++Architecture: any
++Depends: libc6-dev, libatm1
++Replaces: atm-dev (<< 2.4.1-7)
++Conflicts: atm-dev (<< 2.4.1-7)
++Provides: libatm-dev
++Description: Development files for compiling ATM programs
++ Header files and development libraries for compiling ATM (Asynchronous
++ Transfer Mode) related programs.
++ .
++ Homepage: http://linux-atm.sourceforge.net/
+--- linux-atm-2.4.1.orig/debian/atm-tools.install
++++ linux-atm-2.4.1/debian/atm-tools.install
+@@ -0,0 +1,18 @@
++debian/tmp/usr/share/man/*
++debian/tmp/usr/bin/*
++debian/tmp/usr/sbin/atmsigd
++debian/tmp/usr/sbin/atmaddr
++debian/tmp/usr/sbin/esi
++debian/tmp/usr/sbin/atmloop
++debian/tmp/usr/sbin/atmtcp
++debian/tmp/usr/sbin/enitune
++debian/tmp/usr/sbin/zntune
++debian/tmp/usr/sbin/atmarp sbin
++debian/tmp/usr/sbin/atmarpd sbin
++debian/tmp/usr/sbin/ilmid
++debian/tmp/usr/sbin/zeppelin
++debian/tmp/usr/sbin/les
++debian/tmp/usr/sbin/bus
++debian/tmp/usr/sbin/lecs
++debian/tmp/usr/sbin/mpcd
++debian/tmp/etc/atmsigd.conf
+--- linux-atm-2.4.1.orig/debian/atm-tools.manpages
++++ linux-atm-2.4.1/debian/atm-tools.manpages
+@@ -0,0 +1 @@
++debian/atm-tools.8
+--- linux-atm-2.4.1.orig/debian/atm-tools.pod
++++ linux-atm-2.4.1/debian/atm-tools.pod
+@@ -0,0 +1,27 @@
++=head1 NAME
++
++linux-atm - preliminary manpage
++aread
++awrite
++enitune
++ilmid
++saaldump
++sonetdiag
++ttcp_atm
++zntune
++
++=head1 DOCUMENTATION
++
++atm-tools is a package containing the basic tools that are needed for
++setting up, monitoring, and tuning ATM networks. All available
++documentation can be found in /usr/share/doc/atnm-tools in Debian
++systems, and on the Web on: http://linux-atm.sourceforge.net.
++
++=head1 BUGS
++
++Many. Be prepared to debug.
++
++=head1 AUTHOR
++
++This manpage was written by Marc Haber for linux-atm packaging in
++Debian/GNU Operating System.
+--- linux-atm-2.4.1.orig/debian/changelog
++++ linux-atm-2.4.1/debian/changelog
+@@ -0,0 +1,212 @@
++linux-atm (2.4.1-17) unstable; urgency=low
++
++ * Fix build problem with gcc 4.0 (Closes: )
++
++ -- Peter De Schrijver (p2) <p2@mind.be> Thu, 17 Mar 2005 23:02:03 +0100
++
++linux-atm (2.4.1-16) unstable; urgency=low
++
++ * Fix build problem with gcc 3.4 (Closes: #259422)
++
++ -- Peter De Schrijver (p2) <p2@mind.be> Thu, 15 Jul 2004 14:28:10 +0200
++
++linux-atm (2.4.1-15) unstable; urgency=low
++
++ * Updated descriptions (Closes: #239161)
++
++ -- Peter De Schrijver (p2) <p2@mind.be> Sun, 4 Apr 2004 21:10:20 +0200
++
++linux-atm (2.4.1-14) unstable; urgency=low
++
++ * Fix symlink for /usr/lib/libatm.so (Closes: #221011)
++
++ -- Peter De Schrijver (p2) <p2@mind.be> Sun, 7 Dec 2003 21:53:19 +0100
++
++linux-atm (2.4.1-13) unstable; urgency=low
++
++ * Previous version fixed #217259, but no changelog entry (Closes: #217259)
++ * Previous version fixed #216662, but no changelog entry (Closes: #216662)
++ * Added missing build dependency on automake1.4 (Closes: #221120, #221284)
++ * New Maintainer (Closes: #206982)
++
++ -- Peter De Schrijver (p2) <p2@mind.be> Mon, 17 Nov 2003 23:03:58 +0100
++
++linux-atm (2.4.1-12) unstable; urgency=low
++
++ * don't build atm-tools-br2684 by default. Thanks to ftpmaster for
++ not allowing the package to be in Debian.
++ * Since we don't build atm-tools-br2684 any more, revert back to
++ autotools output from 2.4.1-9
++ * Add README.br2684 documenting a way to build the package locally.
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Wed, 5 Nov 2003 21:31:42 +0000
++
++linux-atm (2.4.1-11) experimental; urgency=low
++
++ * Build-Depend on dpatch
++ * dpatch br2684 header files from later libc for old libc (woody)
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Wed, 29 Oct 2003 19:05:07 +0000
++
++linux-atm (2.4.1-10) experimental; urgency=low
++
++ * add br2684 to package (closes: #216663)
++ * autoreconf to actually build br2684
++ * have libatm1-dev provide libatm-dev (closes: #216662)
++ * move lib symlink to libatm1-dev as well (closes: #217259)
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Thu, 23 Oct 2003 17:55:43 +0000
++
++linux-atm (2.4.1-9) unstable; urgency=low
++
++ * put libatm1-dev in libdevel (closes: #213170)
++ * make sure that new descriptions actually make it into the package
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Thu, 9 Oct 2003 17:08:10 +0000
++
++linux-atm (2.4.1-8) unstable; urgency=low
++
++ * build arch-indep package as targets of binary-indep (closes: #212124)
++ * use dh_installdocs to install files to libatm1-dev/docs
++ * symlink shared lib to usr/bin (closes: #213146)
++ * Use better long descriptions. Thanks to Javier (closes: #209427)
++ Fernandez-Sanguino (closes: #209612)
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Sun, 28 Sep 2003 19:29:08 +0000
++
++linux-atm (2.4.1-7) unstable; urgency=low
++
++ * libatm1 now conflicts with atm-tools (<< 2.4.1-6) (closes: #208170)
++ * armarp now writes output to stdout.
++ * add atm-dev as empty transitional package to help upgrades
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Tue, 2 Sep 2003 09:20:33 +0000
++
++linux-atm (2.4.1-6) unstable; urgency=low
++
++ * split off shared libraries to libatm1
++ * rename atm-dev to libatm1-dev
++ * Standards-Version: 3.6.1
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Tue, 26 Aug 2003 15:46:27 +0000
++
++linux-atm (2.4.1-5) unstable; urgency=low
++
++ * move *.a and *.la to usr/lib (closes: #199506).
++ * let atm-dev depend on atm-tools to avoid dangling /lib/libatm.so
++ symlink.
++ * Standards-Version: 3.5.6
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Wed, 30 Jul 2003 11:46:19 +0000
++
++linux-atm (2.4.1-4) unstable; urgency=low
++
++ * add Build-Depends: on automake1.4
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Wed, 11 Jun 2003 16:58:21 +0000
++
++linux-atm (2.4.1-3) unstable; urgency=low
++
++ * rebuilding libtool broke src/test/Makefile.in. Applied fix to
++ Makefile.am and re-built again.
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Wed, 11 Jun 2003 11:05:26 +0000
++
++linux-atm (2.4.1-2) unstable; urgency=low
++
++ * rebuild configure script with new libtool (closes: #196909)
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Tue, 10 Jun 2003 21:01:50 +0000
++
++linux-atm (2.4.1-1) unstable; urgency=low
++
++ * new upstream source
++ * remove atmarp and atmarpd from /usr/sbin as they are already in
++ /sbin (closes: #196216)
++ * lintian fixes
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Mon, 9 Jun 2003 16:03:45 +0000
++
++linux-atm (2.4.0-5) unstable; urgency=low
++
++ * Fix for src/test/Makefile.in to allow building on hppa and ia64
++ which the fix introduced to 2.4.0-4 broke. Thanks to Goswin
++ Brederlow.
++ * Move init.d priority to that atmarpd is started before network
++ interfaces are started.
++ * Move atmarpd and libatm to /sbin and /lib to allow atmarpd to be
++ started before /usr is mounted.
++ * use dh_install instead of dh_movefiles.
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Sat, 24 Aug 2002 15:13:48 +0000
++
++linux-atm (2.4.0-4) unstable; urgency=low
++
++ * new maintainer
++ * Fix for src/test/Makefile.in to allow building on sparc.
++ Thanks to Patrick Mauritz. (closes: #144225).
++ * added pseudo-manpage for manpage-less binaries.
++ * removed rpath by changing configure and make install paramaters
++
++ -- Marc Haber <mh+debian-packages@zugschlus.de> Fri, 16 Aug 2002 20:39:05 +0000
++
++linux-atm (2.4.0-3) unstable; urgency=HIGH
++
++ * Re-ran libtoolize.
++ Closes: #143522
++
++ * Previous version Closes: #135328
++
++ -- Russell Coker <russell@coker.com.au> Fri, 19 Apr 2002 01:55:00 +0200
++
++linux-atm (2.4.0-2) unstable; urgency=HIGH
++
++ * Put a "grep -v EMAXERRNO" into the build process to deal with mipsel and
++ the "#ifdef __KERNEL__" it has in it's /usr/include/asm/errno.h .
++
++ -- Russell Coker <russell@coker.com.au> Thu, 18 Apr 2002 19:56:00 +0200
++
++linux-atm (2.4.0-1) unstable; urgency=HIGH
++
++ * New upstream version which changes source package name.
++ Closes: #138911
++
++ -- Russell Coker <russell@coker.com.au> Mon, 18 Mar 2002 17:42:00 +0100
++
++atm (0.79-4) unstable; urgency=low
++
++ * Added build-depends on flex.
++ Closes: #111072
++
++ * Made the atm tools use a shared object to save space.
++
++ * Fixed the copyright file and put all copyright details in both packages.
++
++ * Added support for easy building with different kernel headers.
++ Closes: #110249
++
++ -- Russell Coker <russell@coker.com.au> Sun, 7 Oct 2001 14:11:33 +0200
++
++atm (0.79-3) unstable; urgency=low
++
++ * Created /etc/init.d/atm to start and stop atmarpd.
++ Closes: #110252
++
++ * Added build-depends on bison.
++ Closes: #110576
++
++ -- Russell Coker <russell@coker.com.au> Fri, 31 Aug 2001 15:21:44 +0200
++
++atm (0.79-2) unstable; urgency=low
++
++ * Changed the main package name to atm-tools to indicate that it doesn't
++ provide ATM (gotta have the kernel support), it just has the daemons and
++ utilities.
++
++ -- Russell Coker <russell@coker.com.au> Sat, 25 Aug 2001 17:55:00 +0200
++
++atm (0.79-1) unstable; urgency=low
++
++ * Initial Release.
++
++ -- Russell Coker <russell@coker.com.au> Fri, 24 Aug 2001 17:31:00 +0200
+--- linux-atm-2.4.1.orig/debian/checkout-br2684
++++ linux-atm-2.4.1/debian/checkout-br2684
+@@ -0,0 +1,25 @@
++#!/bin/bash -x
++
++set -e
++
++# check out br2684 from upstream CVS. We need to jump through hoops if
++# the local source package is under cvs control as well.
++
++CVSDIR=":pserver:anonymous:@cvs.linux-atm.sourceforge.net.:/cvsroot/linux-atm"
++DIR="br2684"
++TMPDIR="/tmp"
++TARGETDIR="src"
++
++cvs -d${CVSDIR} login
++
++mkdir -p $TMPDIR
++pushd $TMPDIR
++cvs -z6 -d${CVSDIR} export -d $DIR -r V2_5_0 linux-atm/src/br2684
++
++popd
++
++mv $TMPDIR/$DIR/* $TARGETDIR/$DIR
++rm -rf $TMPDIR/$DIR
++
++autoreconf -i -f
++
+--- linux-atm-2.4.1.orig/debian/copyright.header
++++ linux-atm-2.4.1/debian/copyright.header
+@@ -0,0 +1,18 @@
++This package was debianized by Russell Coker <russell@coker.com.au> on
++Fri, 24 Aug 2001 16:11:12 +0200 and is now maintained by Marc Haber
++<mh+debian-packages@zugschlus.de>.
++
++It was downloaded from http://www.sourceforge.net/projects/linux-atm/
++
++See also http://linux-atm.sourceforge.net/dist.php
++
++Upstream Authors:
++Werner Almesberger EPFL ICA <Werner.Almesberger@epfl.ch>
++Mitchell Blank Jr. <mitch@sfgoth.com>
++Paul B Schroeder <paulsch@us.ibm.com>
++
++Copyright:
++
++GPL 2.0
++
++See /usr/share/common-licenses/GPL-2
+--- linux-atm-2.4.1.orig/debian/libatm1-dev.dirs
++++ linux-atm-2.4.1/debian/libatm1-dev.dirs
+@@ -0,0 +1,2 @@
++usr/lib
++usr/include
+--- linux-atm-2.4.1.orig/debian/libatm1-dev.docs
++++ linux-atm-2.4.1/debian/libatm1-dev.docs
+@@ -0,0 +1,2 @@
++doc/README.CLP
++doc/atm-linux-howto.txt
+--- linux-atm-2.4.1.orig/debian/libatm1-dev.install
++++ linux-atm-2.4.1/debian/libatm1-dev.install
+@@ -0,0 +1,2 @@
++debian/tmp/usr/include/*
++debian/tmp/usr/lib/*.a usr/lib
+--- linux-atm-2.4.1.orig/debian/libatm1-dev.links
++++ linux-atm-2.4.1/debian/libatm1-dev.links
+@@ -0,0 +1 @@
++lib/libatm.so.1 usr/lib/libatm.so
+--- linux-atm-2.4.1.orig/debian/libatm1.dirs
++++ linux-atm-2.4.1/debian/libatm1.dirs
+@@ -0,0 +1 @@
++/lib
+--- linux-atm-2.4.1.orig/debian/libatm1.install
++++ linux-atm-2.4.1/debian/libatm1.install
+@@ -0,0 +1 @@
++debian/tmp/usr/lib/libatm.so.* lib
diff --git a/package/linux-atm/patches/100-br2684.patch b/package/linux-atm/patches/100-br2684.patch
new file mode 100644
index 0000000000..dfb1de0205
--- /dev/null
+++ b/package/linux-atm/patches/100-br2684.patch
@@ -0,0 +1,488 @@
+diff -ruN linux-atm-2.4.1/configure.in linux-atm-2.4.1.new/configure.in
+--- linux-atm-2.4.1/configure.in 2003-04-25 04:17:05.000000000 +0200
++++ linux-atm-2.4.1.new/configure.in 2005-07-27 15:45:49.532396543 +0200
+@@ -153,26 +153,6 @@
+ src/Makefile \
+ src/include/Makefile \
+ src/lib/Makefile \
+- src/test/Makefile \
+- src/debug/Makefile \
+- src/qgen/Makefile \
+- src/saal/Makefile \
+- src/sigd/Makefile \
+- src/maint/Makefile \
+- src/arpd/Makefile \
+- src/ilmid/Makefile \
+- src/ilmid/asn1/Makefile \
+- src/man/Makefile \
+- src/led/Makefile \
+- src/lane/Makefile \
+- src/mpoad/Makefile \
+- src/switch/Makefile \
+- src/switch/debug/Makefile \
+- src/switch/tcp/Makefile \
+- src/config/Makefile \
+- src/config/init-redhat/Makefile \
+- src/extra/Makefile \
+- src/extra/linux-atm.spec \
+- src/extra/ANS/Makefile
++ src/br2684/Makefile \
+ )
+
+diff -ruN linux-atm-2.4.1/src/br2684/Makefile linux-atm-2.4.1.new/src/br2684/Makefile
+--- linux-atm-2.4.1/src/br2684/Makefile 1970-01-01 02:00:00.000000000 +0200
++++ linux-atm-2.4.1.new/src/br2684/Makefile 2002-07-15 23:44:25.000000000 +0200
+@@ -0,0 +1,13 @@
++PREFIX=${TI_FILESYSTEM}
++
++all: br2684ctl
++
++br2684ctl: br2684ctl.c
++ gcc -latm -o br2684ctl br2684ctl.c
++ strip br2684ctl
++
++install: br2684ctl
++ cp br2684ctl $(PREFIX)/usr/sbin/
++
++clean:
++ rm -rf br2684ctl *.o
+diff -ruN linux-atm-2.4.1/src/Makefile.am linux-atm-2.4.1.new/src/Makefile.am
+--- linux-atm-2.4.1/src/Makefile.am 2001-10-03 23:14:53.000000000 +0200
++++ linux-atm-2.4.1.new/src/Makefile.am 2005-07-27 15:33:52.389309711 +0200
+@@ -1,3 +1,2 @@
+-SUBDIRS = include lib test debug qgen saal sigd maint arpd ilmid man led lane \
+- mpoad switch config extra
++SUBDIRS = include lib br2684
+
+
+diff -Nur linux-atm-2.4.1.orig/src/include/linux/atmbr2684.h linux-atm-2.4.1/src/include/linux/atmbr2684.h
+--- linux-atm-2.4.1.orig/src/include/linux/atmbr2684.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-atm-2.4.1/src/include/linux/atmbr2684.h 2005-11-13 00:06:42.000000000 +0100
+@@ -0,0 +1,117 @@
++#ifndef _LINUX_ATMBR2684_H
++#define _LINUX_ATMBR2684_H
++
++#include <linux/atm.h>
++#include <linux/if.h> /* For IFNAMSIZ */
++#include <linux/if_ether.h> /* ETH_P_* */
++
++/*
++ * Type of media we're bridging (ethernet, token ring, etc) Currently only
++ * ethernet is supported
++ */
++#define BR2684_MEDIA_ETHERNET (0) /* 802.3 */
++#define BR2684_MEDIA_802_4 (1) /* 802.4 */
++#define BR2684_MEDIA_TR (2) /* 802.5 - token ring */
++#define BR2684_MEDIA_FDDI (3)
++#define BR2684_MEDIA_802_6 (4) /* 802.6 */
++
++/*
++ * Is there FCS inbound on this VC? This currently isn't supported.
++ */
++#define BR2684_FCSIN_NO (0)
++#define BR2684_FCSIN_IGNORE (1)
++#define BR2684_FCSIN_VERIFY (2)
++
++/*
++ * Is there FCS outbound on this VC? This currently isn't supported.
++ */
++#define BR2684_FCSOUT_NO (0)
++#define BR2684_FCSOUT_SENDZERO (1)
++#define BR2684_FCSOUT_GENERATE (2)
++
++/*
++ * Does this VC include LLC encapsulation?
++ */
++#define BR2684_ENCAPS_VC (0) /* VC-mux */
++#define BR2684_ENCAPS_LLC (1)
++#define BR2684_ENCAPS_AUTODETECT (2) /* Unsuported */
++
++/*
++ * Is this VC bridged or routed?
++ */
++
++#define BR2684_PAYLOAD_ROUTED (0)
++#define BR2684_PAYLOAD_BRIDGED (1)
++
++
++/*
++ * This is for the ATM_NEWBACKENDIF call - these are like socket families:
++ * the first element of the structure is the backend number and the rest
++ * is per-backend specific
++ */
++struct atm_newif_br2684 {
++ atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */
++ int media; /* BR2684_MEDIA_* */
++ char ifname[IFNAMSIZ];
++ int mtu;
++ int payload; /* bridged or routed */
++};
++
++/*
++ * This structure is used to specify a br2684 interface - either by a
++ * positive integer (returned by ATM_NEWBACKENDIF) or the interfaces name
++ */
++#define BR2684_FIND_BYNOTHING (0)
++#define BR2684_FIND_BYNUM (1)
++#define BR2684_FIND_BYIFNAME (2)
++struct br2684_if_spec {
++ int method; /* BR2684_FIND_* */
++ union {
++ char ifname[IFNAMSIZ];
++ int devnum;
++ } spec;
++};
++
++/*
++ * This is for the ATM_SETBACKEND call - these are like socket families:
++ * the first element of the structure is the backend number and the rest
++ * is per-backend specific
++ */
++struct atm_backend_br2684 {
++ atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */
++ struct br2684_if_spec ifspec;
++ int fcs_in; /* BR2684_FCSIN_* */
++ int fcs_out; /* BR2684_FCSOUT_* */
++ int fcs_auto; /* 1: fcs_{in,out} disabled if no FCS rx'ed */
++ int encaps; /* BR2684_ENCAPS_* */
++ int payload; /* BR2684_PAYLOAD_* */
++ int has_vpiid; /* 1: use vpn_id - Unsupported */
++ __u8 vpn_id[7];
++ int send_padding; /* unsupported */
++ int min_size; /* we will pad smaller packets than this */
++};
++
++/*
++ * The BR2684_SETFILT ioctl is an experimental mechanism for folks
++ * terminating a large number of IP-only vcc's. When netfilter allows
++ * efficient per-if in/out filters, this support will be removed
++ */
++struct br2684_filter {
++ __u32 prefix; /* network byte order */
++ __u32 netmask; /* 0 = disable filter */
++};
++
++struct br2684_filter_set {
++ struct br2684_if_spec ifspec;
++ struct br2684_filter filter;
++};
++
++enum br2684_payload {
++ p_routed = BR2684_PAYLOAD_ROUTED,
++ p_bridged = BR2684_PAYLOAD_BRIDGED,
++};
++
++#define BR2684_SETFILT _IOW( 'a', ATMIOC_BACKEND + 0, \
++ struct br2684_filter_set)
++
++#endif /* _LINUX_ATMBR2684_H */
+--- linux-atm-2.4.1/src/br2684/br2684ctl.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-atm-2.4.1.new/src/br2684/br2684ctl.c 2006-02-07 14:19:42.000000000 +0100
+@@ -0,0 +1,307 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <errno.h>
++#include <sys/ioctl.h>
++#include <string.h>
++#include <syslog.h>
++#include <atm.h>
++#include <linux/atmdev.h>
++#include <linux/atmbr2684.h>
++
++/* Written by Marcell GAL <cell@sch.bme.hu> to make use of the */
++/* ioctls defined in the br2684... kernel patch */
++/* Compile with cc -o br2684ctl br2684ctl.c -latm */
++
++/*
++ Modified feb 2001 by Stephen Aaskov (saa@lasat.com)
++ - Added daemonization code
++ - Added syslog
++
++ TODO: Delete interfaces after exit?
++*/
++
++
++#define LOG_NAME "RFC1483/2684 bridge"
++#define LOG_OPTION LOG_PERROR
++#define LOG_FACILITY LOG_LOCAL0
++
++
++int lastsock, lastitf;
++
++void fatal(char *str, int i)
++{
++ syslog(LOG_ERR, "Fatal: %s", str);
++ exit(-2);
++};
++
++
++void exitFunc(void)
++{
++ syslog(LOG_PID, "Daemon terminated\n");
++}
++
++
++int create_pidfile(char *nstr)
++{
++ FILE *pidfile = NULL;
++ char name[20];
++ int num;
++
++ if (nstr == NULL)
++ return -1;
++ num = atoi(nstr);
++ if (num < 0)
++ return -1;
++
++ snprintf(name, 20, "/var/run/nas%d.pid", num);
++ pidfile = fopen(name, "w");
++ if (pidfile == NULL)
++ return -1;
++ fprintf(pidfile, "%d", getpid());
++ fclose(pidfile);
++
++ return 0;
++}
++
++int create_br(char *nstr, int payload)
++{
++ int num, err;
++
++ if (lastsock < 0) {
++ lastsock = socket(PF_ATMPVC, SOCK_DGRAM, ATM_AAL5);
++ }
++ if (lastsock < 0) {
++ syslog(LOG_ERR, "socket creation failed: %s",
++ strerror(errno));
++ } else {
++ /* create the device with ioctl: */
++ num = atoi(nstr);
++ if (num >= 0 && num < 1234567890) {
++ struct atm_newif_br2684 ni;
++ ni.backend_num = ATM_BACKEND_BR2684;
++ ni.media = BR2684_MEDIA_ETHERNET;
++ ni.mtu = 1500;
++ ni.payload = payload; /* bridged or routed */
++ sprintf(ni.ifname, "nas%d", num);
++ err = ioctl(lastsock, ATM_NEWBACKENDIF, &ni);
++
++ if (err == 0)
++ syslog(LOG_INFO,
++ "Interface \"%s\" (mtu=%d, payload=%s) created sucessfully\n",
++ ni.ifname, ni.mtu,ni.payload ? "bridged" : "routed");
++ else
++ syslog(LOG_INFO,
++ "Interface \"%s\" could not be created, reason: %s\n",
++ ni.ifname, strerror(errno));
++ lastitf = num; /* even if we didn't create, because existed, assign_vcc wil want to know it! */
++ } else {
++ syslog(LOG_ERR, "err: strange interface number %d",
++ num);
++ }
++ }
++ return 0;
++}
++
++
++int assign_vcc(char *astr, int encap, int payload, int bufsize)
++{
++ int err, errno;
++ struct atm_qos qos;
++ struct sockaddr_atmpvc addr;
++ int fd;
++ struct atm_backend_br2684 be;
++
++ memset(&addr, 0, sizeof(addr));
++ err =
++ text2atm(astr, (struct sockaddr *) (&addr), sizeof(addr),
++ T2A_PVC);
++ if (err != 0)
++ syslog(LOG_ERR,
++ "Could not parse ATM parameters (error=%d)\n", err);
++
++#if 0
++ addr.sap_family = AF_ATMPVC;
++ addr.sap_addr.itf = itf;
++ addr.sap_addr.vpi = 0;
++ addr.sap_addr.vci = vci;
++#endif
++ syslog(LOG_INFO,
++ "Communicating over ATM %d.%d.%d, encapsulation: %s\n",
++ addr.sap_addr.itf, addr.sap_addr.vpi, addr.sap_addr.vci,
++ encap ? "VC mux" : "LLC");
++
++ if ((fd = socket(PF_ATMPVC, SOCK_DGRAM, ATM_AAL5)) < 0)
++ syslog(LOG_ERR, "failed to create socket %d, reason: %s",
++ errno, strerror(errno));
++
++
++ memset(&qos, 0, sizeof(qos));
++ qos.aal = ATM_AAL5;
++ qos.txtp.traffic_class = ATM_UBR;
++ qos.txtp.max_sdu = 1524;
++ qos.txtp.pcr = ATM_MAX_PCR;
++ qos.rxtp = qos.txtp;
++
++ if ((err =
++ setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bufsize,
++ sizeof(bufsize))))
++ syslog(LOG_ERR, "setsockopt SO_SNDBUF: (%d) %s\n", err,
++ strerror(err));
++
++ if (setsockopt(fd, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos)) < 0)
++ syslog(LOG_ERR, "setsockopt SO_ATMQOS %d", errno);
++
++ err =
++ connect(fd, (struct sockaddr *) &addr,
++ sizeof(struct sockaddr_atmpvc));
++
++ if (err < 0)
++ fatal("failed to connect on socket", err);
++
++ /* attach the vcc to device: */
++
++ be.backend_num = ATM_BACKEND_BR2684;
++ be.ifspec.method = BR2684_FIND_BYIFNAME;
++ sprintf(be.ifspec.spec.ifname, "nas%d", lastitf);
++ be.fcs_in = BR2684_FCSIN_NO;
++ be.fcs_out = BR2684_FCSOUT_NO;
++ be.fcs_auto = 0;
++ be.encaps = encap ? BR2684_ENCAPS_VC : BR2684_ENCAPS_LLC;
++ be.payload = payload;
++ be.has_vpiid = 0;
++ be.send_padding = 0;
++ be.min_size = 0;
++ err = ioctl(fd, ATM_SETBACKEND, &be);
++ if (err == 0)
++ syslog(LOG_INFO, "Interface configured");
++ else {
++ syslog(LOG_ERR, "Could not configure interface:%s",
++ strerror(errno));
++ exit(2);
++ }
++ return fd;
++}
++
++
++
++void usage(char *s)
++{
++ printf("usage: %s [-b] [[-c number] [-e 0|1] [-p 0|1] [-s num] [-a [itf.]vpi.vci]*]*\n"
++ " -b = run in background (daemonize)\n"
++ " -c <num> = use interface nas<num>\n"
++ " -e 0|1 = encapsulation (0=LLC, 1=VC Mux)\n"
++ " -p 0|1 = payload type (0=routed,1=bridged)\n"
++ " -s <num> = set sndbuf (send buffer) size (default 8192)\n"
++ " -a [itf.]vpi.vci = ATM interface no, VPI, VCI\n",
++ s);
++ exit(1);
++}
++
++
++
++int main(int argc, char **argv)
++{
++ int c, background = 0, encap = 0, sndbuf = 8192, payload = 1;
++ char *itfnum = NULL;
++
++ lastsock = -1;
++ lastitf = 0;
++
++ openlog(LOG_NAME, LOG_OPTION, LOG_FACILITY);
++ if (argc > 1)
++ while ((c = getopt(argc, argv, "a:bc:e:s:p:t:?h")) != EOF)
++ switch (c) {
++ case 'a':
++ assign_vcc(optarg, encap, payload, sndbuf);
++ break;
++ case 'b':
++ background = 1;
++ break;
++ case 'c':
++ create_br(optarg, payload);
++ itfnum = strdup(optarg);
++ break;
++ case 'e':
++ encap = (atoi(optarg));
++ if (encap < 0) {
++ syslog(LOG_ERR,
++ "invalid encapsulation: %s:\n",
++ optarg);
++ encap = 0;
++ }
++ break;
++ case 's':
++ sndbuf = (atoi(optarg));
++ if (sndbuf < 0) {
++ syslog(LOG_ERR,
++ "Invalid sndbuf: %s, using size of 8192 instead\n",
++ optarg);
++ sndbuf = 8192;
++ }
++ break;
++ case 'p': /* payload type: routed (0) or bridged (1) */
++ payload = atoi(optarg);
++ break;
++ case '?':
++ case 'h':
++ default:
++ usage(argv[0]);
++ } else
++ usage(argv[0]);
++
++ if (argc != optind)
++ usage(argv[0]);
++
++ if (lastsock >= 0)
++ close(lastsock);
++
++ if (background) {
++ pid_t pid;
++
++ pid = fork();
++ if (pid < 0) {
++ fprintf(stderr, "Error detaching\n");
++ exit(2);
++ } else if (pid)
++ exit(0); // This is the parent
++
++ // Become a process group and session group leader
++ if (setsid() < 0) {
++ fprintf(stderr, "Could not set process group\n");
++ exit(2);
++ }
++ // Fork again to let process group leader exit
++ pid = fork();
++ if (pid < 0) {
++ fprintf(stderr,
++ "Error detaching during second fork\n");
++ exit(2);
++ } else if (pid)
++ exit(0); // This is the parent
++
++ // Now we're ready for buisness
++ chdir("/"); // Don't keep directories in use
++ close(0);
++ close(1);
++ close(2); // Close stdin, -out and -error
++ /*
++ Note that this implementation does not keep an open
++ stdout/err.
++ If we need them they can be opened now
++ */
++
++ }
++
++ if (itfnum != NULL) {
++ create_pidfile(itfnum);
++ free(itfnum);
++ }
++
++ syslog(LOG_INFO, "RFC 1483/2684 bridge daemon started\n");
++ atexit(exitFunc);
++
++ while (1)
++ sleep(30); /* to keep the sockets... */
++ return 0;
++}
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 0000000000..1b538b2a3b
--- /dev/null
+++ b/package/linux-atm/patches/200-no_libfl.patch
@@ -0,0 +1,193 @@
+diff -ruN linux-atm-2.4.1/src/qgen/Makefile.am linux-atm-2.4.1.new/src/qgen/Makefile.am
+--- linux-atm-2.4.1/src/qgen/Makefile.am 2001-09-03 20:41:05.000000000 +0200
++++ linux-atm-2.4.1.new/src/qgen/Makefile.am 2005-07-26 14:49:05.000000000 +0200
+@@ -3,7 +3,7 @@
+
+ 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 =
+
+ q_dump_SOURCES = common.c
+ q_dump_LDADD = qd.dump.standalone.o
+diff -ruN linux-atm-2.4.1/src/qgen/Makefile.in linux-atm-2.4.1.new/src/qgen/Makefile.in
+--- linux-atm-2.4.1/src/qgen/Makefile.in 2003-04-30 16:44:01.000000000 +0200
++++ linux-atm-2.4.1.new/src/qgen/Makefile.in 2005-07-26 14:49:13.000000000 +0200
+@@ -91,7 +91,7 @@
+ 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 =
+
+ q_dump_SOURCES = common.c
+ q_dump_LDADD = qd.dump.standalone.o
+diff -ruN linux-atm-2.4.1/src/qgen/ql_l.c linux-atm-2.4.1.new/src/qgen/ql_l.c
+--- linux-atm-2.4.1/src/qgen/ql_l.c 2003-04-24 21:46:49.000000000 +0200
++++ linux-atm-2.4.1.new/src/qgen/ql_l.c 2005-07-26 20:45:40.000000000 +0200
+@@ -11,6 +11,11 @@
+ #include <stdio.h>
+ #include <unistd.h>
+
++int yywrap(void)
++{
++ return 1;
++}
++
+
+ /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+ #ifdef c_plusplus
+diff -ruN linux-atm-2.4.1/src/sigd/cfg_l.c linux-atm-2.4.1.new/src/sigd/cfg_l.c
+--- linux-atm-2.4.1/src/sigd/cfg_l.c 2003-04-24 21:47:21.000000000 +0200
++++ linux-atm-2.4.1.new/src/sigd/cfg_l.c 2005-07-26 22:04:13.000000000 +0200
+@@ -11,6 +11,10 @@
+ #include <stdio.h>
+ #include <unistd.h>
+
++int yywrap(void)
++{
++ return 1;
++}
+
+ /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+ #ifdef c_plusplus
+diff -ruN linux-atm-2.4.1/src/sigd/Makefile.am linux-atm-2.4.1.new/src/sigd/Makefile.am
+--- linux-atm-2.4.1/src/sigd/Makefile.am 2001-10-04 23:17:26.000000000 +0200
++++ linux-atm-2.4.1.new/src/sigd/Makefile.am 2005-07-26 14:49:44.000000000 +0200
+@@ -8,7 +8,7 @@
+ $(top_builddir)/src/qgen/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
+diff -ruN linux-atm-2.4.1/src/sigd/Makefile.in linux-atm-2.4.1.new/src/sigd/Makefile.in
+--- linux-atm-2.4.1/src/sigd/Makefile.in 2003-04-30 16:44:03.000000000 +0200
++++ linux-atm-2.4.1.new/src/sigd/Makefile.in 2005-07-26 14:49:48.000000000 +0200
+@@ -97,7 +97,7 @@
+ $(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
+diff -ruN linux-atm-2.4.1/src/switch/debug/debug.c linux-atm-2.4.1.new/src/switch/debug/debug.c
+--- linux-atm-2.4.1/src/switch/debug/debug.c 2001-09-03 20:41:06.000000000 +0200
++++ linux-atm-2.4.1.new/src/switch/debug/debug.c 2005-07-26 22:06:53.000000000 +0200
+@@ -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 */
+diff -ruN linux-atm-2.4.1/src/switch/debug/Makefile.am linux-atm-2.4.1.new/src/switch/debug/Makefile.am
+--- linux-atm-2.4.1/src/switch/debug/Makefile.am 2001-10-04 23:17:26.000000000 +0200
++++ linux-atm-2.4.1.new/src/switch/debug/Makefile.am 2005-07-26 14:50:03.000000000 +0200
+@@ -5,7 +5,7 @@
+ 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)
+
+diff -ruN linux-atm-2.4.1/src/switch/debug/Makefile.in linux-atm-2.4.1.new/src/switch/debug/Makefile.in
+--- linux-atm-2.4.1/src/switch/debug/Makefile.in 2003-04-30 16:44:13.000000000 +0200
++++ linux-atm-2.4.1.new/src/switch/debug/Makefile.in 2005-07-26 14:50:08.000000000 +0200
+@@ -93,7 +93,7 @@
+ 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)
+
+diff -ruN linux-atm-2.4.1/src/switch/tcp/Makefile.am linux-atm-2.4.1.new/src/switch/tcp/Makefile.am
+--- linux-atm-2.4.1/src/switch/tcp/Makefile.am 2001-10-04 23:17:27.000000000 +0200
++++ linux-atm-2.4.1.new/src/switch/tcp/Makefile.am 2005-07-26 14:50:16.000000000 +0200
+@@ -5,7 +5,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
+diff -ruN linux-atm-2.4.1/src/switch/tcp/Makefile.in linux-atm-2.4.1.new/src/switch/tcp/Makefile.in
+--- linux-atm-2.4.1/src/switch/tcp/Makefile.in 2003-04-30 16:44:14.000000000 +0200
++++ linux-atm-2.4.1.new/src/switch/tcp/Makefile.in 2005-07-26 14:50:19.000000000 +0200
+@@ -93,7 +93,7 @@
+ 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
+diff -ruN linux-atm-2.4.1/src/switch/tcp/tcpsw.c linux-atm-2.4.1.new/src/switch/tcp/tcpsw.c
+--- linux-atm-2.4.1/src/switch/tcp/tcpsw.c 2001-09-03 20:41:06.000000000 +0200
++++ linux-atm-2.4.1.new/src/switch/tcp/tcpsw.c 2005-07-26 22:08:25.000000000 +0200
+@@ -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 */
+diff -ruN linux-atm-2.4.1/src/test/ispl_l.c linux-atm-2.4.1.new/src/test/ispl_l.c
+--- linux-atm-2.4.1/src/test/ispl_l.c 2003-04-24 21:46:39.000000000 +0200
++++ linux-atm-2.4.1.new/src/test/ispl_l.c 2005-07-26 20:45:19.000000000 +0200
+@@ -11,6 +11,11 @@
+ #include <stdio.h>
+ #include <unistd.h>
+
++int yywrap(void)
++{
++ return 1;
++}
++
+
+ /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+ #ifdef c_plusplus
+diff -ruN linux-atm-2.4.1/src/test/Makefile.am linux-atm-2.4.1.new/src/test/Makefile.am
+--- linux-atm-2.4.1/src/test/Makefile.am 2001-10-04 23:17:27.000000000 +0200
++++ linux-atm-2.4.1.new/src/test/Makefile.am 2005-07-26 14:49:27.000000000 +0200
+@@ -15,7 +15,7 @@
+ 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) errnos.inc
+ window_SOURCES = window.c
+
+diff -ruN linux-atm-2.4.1/src/test/Makefile.in linux-atm-2.4.1.new/src/test/Makefile.in
+--- linux-atm-2.4.1/src/test/Makefile.in 2003-04-30 16:43:59.000000000 +0200
++++ linux-atm-2.4.1.new/src/test/Makefile.in 2005-07-26 14:49:32.000000000 +0200
+@@ -102,7 +102,7 @@
+ 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) errnos.inc
+ window_SOURCES = window.c
+
diff --git a/package/linux-atm/patches/300-no_autotools.patch b/package/linux-atm/patches/300-no_autotools.patch
new file mode 100644
index 0000000000..73427296c9
--- /dev/null
+++ b/package/linux-atm/patches/300-no_autotools.patch
@@ -0,0 +1,12014 @@
+diff -urN linux-atm.old/aclocal.m4 linux-atm.dev/aclocal.m4
+--- linux-atm.old/aclocal.m4 2005-08-23 01:12:10.833789000 +0200
++++ linux-atm.dev/aclocal.m4 2005-08-23 01:12:44.813623720 +0200
+@@ -10,6 +10,825 @@
+ dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ dnl PARTICULAR PURPOSE.
+
++# lib-prefix.m4 serial 4 (gettext-0.14.2)
++dnl Copyright (C) 2001-2005 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 From Bruno Haible.
++
++dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and
++dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't
++dnl require excessive bracketing.
++ifdef([AC_HELP_STRING],
++[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])],
++[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])])
++
++dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed
++dnl to access previously installed libraries. The basic assumption is that
++dnl a user will want packages to use other packages he previously installed
++dnl with the same --prefix option.
++dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate
++dnl libraries, but is otherwise very convenient.
++AC_DEFUN([AC_LIB_PREFIX],
++[
++ AC_BEFORE([$0], [AC_LIB_LINKFLAGS])
++ AC_REQUIRE([AC_PROG_CC])
++ AC_REQUIRE([AC_CANONICAL_HOST])
++ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
++ dnl By default, look in $includedir and $libdir.
++ use_additional=yes
++ AC_LIB_WITH_FINAL_PREFIX([
++ eval additional_includedir=\"$includedir\"
++ eval additional_libdir=\"$libdir\"
++ ])
++ AC_LIB_ARG_WITH([lib-prefix],
++[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib
++ --without-lib-prefix don't search for libraries in includedir and libdir],
++[
++ if test "X$withval" = "Xno"; then
++ use_additional=no
++ else
++ if test "X$withval" = "X"; then
++ AC_LIB_WITH_FINAL_PREFIX([
++ eval additional_includedir=\"$includedir\"
++ eval additional_libdir=\"$libdir\"
++ ])
++ else
++ additional_includedir="$withval/include"
++ additional_libdir="$withval/lib"
++ fi
++ fi
++])
++ if test $use_additional = yes; then
++ dnl Potentially add $additional_includedir to $CPPFLAGS.
++ dnl But don't add it
++ dnl 1. if it's the standard /usr/include,
++ dnl 2. if it's already present in $CPPFLAGS,
++ dnl 3. if it's /usr/local/include and we are using GCC on Linux,
++ dnl 4. if it doesn't exist as a directory.
++ if test "X$additional_includedir" != "X/usr/include"; then
++ haveit=
++ for x in $CPPFLAGS; do
++ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
++ if test "X$x" = "X-I$additional_includedir"; then
++ haveit=yes
++ break
++ fi
++ done
++ if test -z "$haveit"; then
++ if test "X$additional_includedir" = "X/usr/local/include"; then
++ if test -n "$GCC"; then
++ case $host_os in
++ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
++ esac
++ fi
++ fi
++ if test -z "$haveit"; then
++ if test -d "$additional_includedir"; then
++ dnl Really add $additional_includedir to $CPPFLAGS.
++ CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir"
++ fi
++ fi
++ fi
++ fi
++ dnl Potentially add $additional_libdir to $LDFLAGS.
++ dnl But don't add it
++ dnl 1. if it's the standard /usr/lib,
++ dnl 2. if it's already present in $LDFLAGS,
++ dnl 3. if it's /usr/local/lib and we are using GCC on Linux,
++ dnl 4. if it doesn't exist as a directory.
++ if test "X$additional_libdir" != "X/usr/lib"; then
++ haveit=
++ for x in $LDFLAGS; do
++ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
++ if test "X$x" = "X-L$additional_libdir"; then
++ haveit=yes
++ break
++ fi
++ done
++ if test -z "$haveit"; then
++ if test "X$additional_libdir" = "X/usr/local/lib"; then
++ if test -n "$GCC"; then
++ case $host_os in
++ linux*) haveit=yes;;
++ esac
++ fi
++ fi
++ if test -z "$haveit"; then
++ if test -d "$additional_libdir"; then
++ dnl Really add $additional_libdir to $LDFLAGS.
++ LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir"
++ fi
++ fi
++ fi
++ fi
++ fi
++])
++
++dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix,
++dnl acl_final_exec_prefix, containing the values to which $prefix and
++dnl $exec_prefix will expand at the end of the configure script.
++AC_DEFUN([AC_LIB_PREPARE_PREFIX],
++[
++ dnl Unfortunately, prefix and exec_prefix get only finally determined
++ dnl at the end of configure.
++ if test "X$prefix" = "XNONE"; then
++ acl_final_prefix="$ac_default_prefix"
++ else
++ acl_final_prefix="$prefix"
++ fi
++ if test "X$exec_prefix" = "XNONE"; then
++ acl_final_exec_prefix='${prefix}'
++ else
++ acl_final_exec_prefix="$exec_prefix"
++ fi
++ acl_save_prefix="$prefix"
++ prefix="$acl_final_prefix"
++ eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
++ prefix="$acl_save_prefix"
++])
++
++dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the
++dnl variables prefix and exec_prefix bound to the values they will have
++dnl at the end of the configure script.
++AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX],
++[
++ acl_save_prefix="$prefix"
++ prefix="$acl_final_prefix"
++ acl_save_exec_prefix="$exec_prefix"
++ exec_prefix="$acl_final_exec_prefix"
++ $1
++ exec_prefix="$acl_save_exec_prefix"
++ prefix="$acl_save_prefix"
++])
++
++# lib-link.m4 serial 6 (gettext-0.14.3)
++dnl Copyright (C) 2001-2005 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 From Bruno Haible.
++
++AC_PREREQ(2.50)
++
++dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and
++dnl the libraries corresponding to explicit and implicit dependencies.
++dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and
++dnl augments the CPPFLAGS variable.
++AC_DEFUN([AC_LIB_LINKFLAGS],
++[
++ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
++ AC_REQUIRE([AC_LIB_RPATH])
++ define([Name],[translit([$1],[./-], [___])])
++ define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
++ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
++ AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [
++ AC_LIB_LINKFLAGS_BODY([$1], [$2])
++ ac_cv_lib[]Name[]_libs="$LIB[]NAME"
++ ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME"
++ ac_cv_lib[]Name[]_cppflags="$INC[]NAME"
++ ])
++ LIB[]NAME="$ac_cv_lib[]Name[]_libs"
++ LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs"
++ INC[]NAME="$ac_cv_lib[]Name[]_cppflags"
++ AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
++ AC_SUBST([LIB]NAME)
++ AC_SUBST([LTLIB]NAME)
++ dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the
++ dnl results of this search when this library appears as a dependency.
++ HAVE_LIB[]NAME=yes
++ undefine([Name])
++ undefine([NAME])
++])
++
++dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode)
++dnl searches for libname and the libraries corresponding to explicit and
++dnl implicit dependencies, together with the specified include files and
++dnl the ability to compile and link the specified testcode. If found, it
++dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and
++dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and
++dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs
++dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty.
++AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
++[
++ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
++ AC_REQUIRE([AC_LIB_RPATH])
++ define([Name],[translit([$1],[./-], [___])])
++ define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
++ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
++
++ dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME
++ dnl accordingly.
++ AC_LIB_LINKFLAGS_BODY([$1], [$2])
++
++ dnl Add $INC[]NAME to CPPFLAGS before performing the following checks,
++ dnl because if the user has installed lib[]Name and not disabled its use
++ dnl via --without-lib[]Name-prefix, he wants to use it.
++ ac_save_CPPFLAGS="$CPPFLAGS"
++ AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
++
++ AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [
++ ac_save_LIBS="$LIBS"
++ LIBS="$LIBS $LIB[]NAME"
++ AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no])
++ LIBS="$ac_save_LIBS"
++ ])
++ if test "$ac_cv_lib[]Name" = yes; then
++ HAVE_LIB[]NAME=yes
++ AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.])
++ AC_MSG_CHECKING([how to link with lib[]$1])
++ AC_MSG_RESULT([$LIB[]NAME])
++ else
++ HAVE_LIB[]NAME=no
++ dnl If $LIB[]NAME didn't lead to a usable library, we don't need
++ dnl $INC[]NAME either.
++ CPPFLAGS="$ac_save_CPPFLAGS"
++ LIB[]NAME=
++ LTLIB[]NAME=
++ fi
++ AC_SUBST([HAVE_LIB]NAME)
++ AC_SUBST([LIB]NAME)
++ AC_SUBST([LTLIB]NAME)
++ undefine([Name])
++ undefine([NAME])
++])
++
++dnl Determine the platform dependent parameters needed to use rpath:
++dnl libext, shlibext, hardcode_libdir_flag_spec, hardcode_libdir_separator,
++dnl hardcode_direct, hardcode_minus_L.
++AC_DEFUN([AC_LIB_RPATH],
++[
++ dnl Tell automake >= 1.10 to complain if config.rpath is missing.
++ m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])])
++ AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS
++ AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld
++ AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host
++ AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir
++ AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [
++ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
++ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
++ . ./conftest.sh
++ rm -f ./conftest.sh
++ acl_cv_rpath=done
++ ])
++ wl="$acl_cv_wl"
++ libext="$acl_cv_libext"
++ shlibext="$acl_cv_shlibext"
++ hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
++ hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
++ hardcode_direct="$acl_cv_hardcode_direct"
++ hardcode_minus_L="$acl_cv_hardcode_minus_L"
++ dnl Determine whether the user wants rpath handling at all.
++ AC_ARG_ENABLE(rpath,
++ [ --disable-rpath do not hardcode runtime library paths],
++ :, enable_rpath=yes)
++])
++
++dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and
++dnl the libraries corresponding to explicit and implicit dependencies.
++dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables.
++AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
++[
++ define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
++ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
++ dnl By default, look in $includedir and $libdir.
++ use_additional=yes
++ AC_LIB_WITH_FINAL_PREFIX([
++ eval additional_includedir=\"$includedir\"
++ eval additional_libdir=\"$libdir\"
++ ])
++ AC_LIB_ARG_WITH([lib$1-prefix],
++[ --with-lib$1-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib
++ --without-lib$1-prefix don't search for lib$1 in includedir and libdir],
++[
++ if test "X$withval" = "Xno"; then
++ use_additional=no
++ else
++ if test "X$withval" = "X"; then
++ AC_LIB_WITH_FINAL_PREFIX([
++ eval additional_includedir=\"$includedir\"
++ eval additional_libdir=\"$libdir\"
++ ])
++ else
++ additional_includedir="$withval/include"
++ additional_libdir="$withval/lib"
++ fi
++ fi
++])
++ dnl Search the library and its dependencies in $additional_libdir and
++ dnl $LDFLAGS. Using breadth-first-seach.
++ LIB[]NAME=
++ LTLIB[]NAME=
++ INC[]NAME=
++ rpathdirs=
++ ltrpathdirs=
++ names_already_handled=
++ names_next_round='$1 $2'
++ while test -n "$names_next_round"; do
++ names_this_round="$names_next_round"
++ names_next_round=
++ for name in $names_this_round; do
++ already_handled=
++ for n in $names_already_handled; do
++ if test "$n" = "$name"; then
++ already_handled=yes
++ break
++ fi
++ done
++ if test -z "$already_handled"; then
++ names_already_handled="$names_already_handled $name"
++ dnl See if it was already located by an earlier AC_LIB_LINKFLAGS
++ dnl or AC_LIB_HAVE_LINKFLAGS call.
++ uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
++ eval value=\"\$HAVE_LIB$uppername\"
++ if test -n "$value"; then
++ if test "$value" = yes; then
++ eval value=\"\$LIB$uppername\"
++ test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value"
++ eval value=\"\$LTLIB$uppername\"
++ test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value"
++ else
++ dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined
++ dnl that this library doesn't exist. So just drop it.
++ :
++ fi
++ else
++ dnl Search the library lib$name in $additional_libdir and $LDFLAGS
++ dnl and the already constructed $LIBNAME/$LTLIBNAME.
++ found_dir=
++ found_la=
++ found_so=
++ found_a=
++ if test $use_additional = yes; then
++ if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then
++ found_dir="$additional_libdir"
++ found_so="$additional_libdir/lib$name.$shlibext"
++ if test -f "$additional_libdir/lib$name.la"; then
++ found_la="$additional_libdir/lib$name.la"
++ fi
++ else
++ if test -f "$additional_libdir/lib$name.$libext"; then
++ found_dir="$additional_libdir"
++ found_a="$additional_libdir/lib$name.$libext"
++ if test -f "$additional_libdir/lib$name.la"; then
++ found_la="$additional_libdir/lib$name.la"
++ fi
++ fi
++ fi
++ fi
++ if test "X$found_dir" = "X"; then
++ for x in $LDFLAGS $LTLIB[]NAME; do
++ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
++ case "$x" in
++ -L*)
++ dir=`echo "X$x" | sed -e 's/^X-L//'`
++ if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then
++ found_dir="$dir"
++ found_so="$dir/lib$name.$shlibext"
++ if test -f "$dir/lib$name.la"; then
++ found_la="$dir/lib$name.la"
++ fi
++ else
++ if test -f "$dir/lib$name.$libext"; then
++ found_dir="$dir"
++ found_a="$dir/lib$name.$libext"
++ if test -f "$dir/lib$name.la"; then
++ found_la="$dir/lib$name.la"
++ fi
++ fi
++ fi
++ ;;
++ esac
++ if test "X$found_dir" != "X"; then
++ break
++ fi
++ done
++ fi
++ if test "X$found_dir" != "X"; then
++ dnl Found the library.
++ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name"
++ if test "X$found_so" != "X"; then
++ dnl Linking with a shared library. We attempt to hardcode its
++ dnl directory into the executable's runpath, unless it's the
++ dnl standard /usr/lib.
++ if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then
++ dnl No hardcoding is needed.
++ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
++ else
++ dnl Use an explicit option to hardcode DIR into the resulting
++ dnl binary.
++ dnl Potentially add DIR to ltrpathdirs.
++ dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
++ haveit=
++ for x in $ltrpathdirs; do
++ if test "X$x" = "X$found_dir"; then
++ haveit=yes
++ break
++ fi
++ done
++ if test -z "$haveit"; then
++ ltrpathdirs="$ltrpathdirs $found_dir"
++ fi
++ dnl The hardcoding into $LIBNAME is system dependent.
++ if test "$hardcode_direct" = yes; then
++ dnl Using DIR/libNAME.so during linking hardcodes DIR into the
++ dnl resulting binary.
++ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
++ else
++ if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then
++ dnl Use an explicit option to hardcode DIR into the resulting
++ dnl binary.
++ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
++ dnl Potentially add DIR to rpathdirs.
++ dnl The rpathdirs will be appended to $LIBNAME at the end.
++ haveit=
++ for x in $rpathdirs; do
++ if test "X$x" = "X$found_dir"; then
++ haveit=yes
++ break
++ fi
++ done
++ if test -z "$haveit"; then
++ rpathdirs="$rpathdirs $found_dir"
++ fi
++ else
++ dnl Rely on "-L$found_dir".
++ dnl But don't add it if it's already contained in the LDFLAGS
++ dnl or the already constructed $LIBNAME
++ haveit=
++ for x in $LDFLAGS $LIB[]NAME; do
++ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
++ if test "X$x" = "X-L$found_dir"; then
++ haveit=yes
++ break
++ fi
++ done
++ if test -z "$haveit"; then
++ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir"
++ fi
++ if test "$hardcode_minus_L" != no; then
++ dnl FIXME: Not sure whether we should use
++ dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
++ dnl here.
++ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
++ else
++ dnl We cannot use $hardcode_runpath_var and LD_RUN_PATH
++ dnl here, because this doesn't fit in flags passed to the
++ dnl compiler. So give up. No hardcoding. This affects only
++ dnl very old systems.
++ dnl FIXME: Not sure whether we should use
++ dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
++ dnl here.
++ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
++ fi
++ fi
++ fi
++ fi
++ else
++ if test "X$found_a" != "X"; then
++ dnl Linking with a static library.
++ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a"
++ else
++ dnl We shouldn't come here, but anyway it's good to have a
++ dnl fallback.
++ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name"
++ fi
++ fi
++ dnl Assume the include files are nearby.
++ additional_includedir=
++ case "$found_dir" in
++ */lib | */lib/)
++ basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'`
++ additional_includedir="$basedir/include"
++ ;;
++ esac
++ if test "X$additional_includedir" != "X"; then
++ dnl Potentially add $additional_includedir to $INCNAME.
++ dnl But don't add it
++ dnl 1. if it's the standard /usr/include,
++ dnl 2. if it's /usr/local/include and we are using GCC on Linux,
++ dnl 3. if it's already present in $CPPFLAGS or the already
++ dnl constructed $INCNAME,
++ dnl 4. if it doesn't exist as a directory.
++ if test "X$additional_includedir" != "X/usr/include"; then
++ haveit=
++ if test "X$additional_includedir" = "X/usr/local/include"; then
++ if test -n "$GCC"; then
++ case $host_os in
++ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
++ esac
++ fi
++ fi
++ if test -z "$haveit"; then
++ for x in $CPPFLAGS $INC[]NAME; do
++ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
++ if test "X$x" = "X-I$additional_includedir"; then
++ haveit=yes
++ break
++ fi
++ done
++ if test -z "$haveit"; then
++ if test -d "$additional_includedir"; then
++ dnl Really add $additional_includedir to $INCNAME.
++ INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir"
++ fi
++ fi
++ fi
++ fi
++ fi
++ dnl Look for dependencies.
++ if test -n "$found_la"; then
++ dnl Read the .la file. It defines the variables
++ dnl dlname, library_names, old_library, dependency_libs, current,
++ dnl age, revision, installed, dlopen, dlpreopen, libdir.
++ save_libdir="$libdir"
++ case "$found_la" in
++ */* | *\\*) . "$found_la" ;;
++ *) . "./$found_la" ;;
++ esac
++ libdir="$save_libdir"
++ dnl We use only dependency_libs.
++ for dep in $dependency_libs; do
++ case "$dep" in
++ -L*)
++ additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
++ dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME.
++ dnl But don't add it
++ dnl 1. if it's the standard /usr/lib,
++ dnl 2. if it's /usr/local/lib and we are using GCC on Linux,
++ dnl 3. if it's already present in $LDFLAGS or the already
++ dnl constructed $LIBNAME,
++ dnl 4. if it doesn't exist as a directory.
++ if test "X$additional_libdir" != "X/usr/lib"; then
++ haveit=
++ if test "X$additional_libdir" = "X/usr/local/lib"; then
++ if test -n "$GCC"; then
++ case $host_os in
++ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
++ esac
++ fi
++ fi
++ if test -z "$haveit"; then
++ haveit=
++ for x in $LDFLAGS $LIB[]NAME; do
++ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
++ if test "X$x" = "X-L$additional_libdir"; then
++ haveit=yes
++ break
++ fi
++ done
++ if test -z "$haveit"; then
++ if test -d "$additional_libdir"; then
++ dnl Really add $additional_libdir to $LIBNAME.
++ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir"
++ fi
++ fi
++ haveit=
++ for x in $LDFLAGS $LTLIB[]NAME; do
++ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
++ if test "X$x" = "X-L$additional_libdir"; then
++ haveit=yes
++ break
++ fi
++ done
++ if test -z "$haveit"; then
++ if test -d "$additional_libdir"; then
++ dnl Really add $additional_libdir to $LTLIBNAME.
++ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir"
++ fi
++ fi
++ fi
++ fi
++ ;;
++ -R*)
++ dir=`echo "X$dep" | sed -e 's/^X-R//'`
++ if test "$enable_rpath" != no; then
++ dnl Potentially add DIR to rpathdirs.
++ dnl The rpathdirs will be appended to $LIBNAME at the end.
++ haveit=
++ for x in $rpathdirs; do
++ if test "X$x" = "X$dir"; then
++ haveit=yes
++ break
++ fi
++ done
++ if test -z "$haveit"; then
++ rpathdirs="$rpathdirs $dir"
++ fi
++ dnl Potentially add DIR to ltrpathdirs.
++ dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
++ haveit=
++ for x in $ltrpathdirs; do
++ if test "X$x" = "X$dir"; then
++ haveit=yes
++ break
++ fi
++ done
++ if test -z "$haveit"; then
++ ltrpathdirs="$ltrpathdirs $dir"
++ fi
++ fi
++ ;;
++ -l*)
++ dnl Handle this in the next round.
++ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
++ ;;
++ *.la)
++ dnl Handle this in the next round. Throw away the .la's
++ dnl directory; it is already contained in a preceding -L
++ dnl option.
++ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
++ ;;
++ *)
++ dnl Most likely an immediate library name.
++ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep"
++ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep"
++ ;;
++ esac
++ done
++ fi
++ else
++ dnl Didn't find the library; assume it is in the system directories
++ dnl known to the linker and runtime loader. (All the system
++ dnl directories known to the linker should also be known to the
++ dnl runtime loader, otherwise the system is severely misconfigured.)
++ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
++ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name"
++ fi
++ fi
++ fi
++ done
++ done
++ if test "X$rpathdirs" != "X"; then
++ if test -n "$hardcode_libdir_separator"; then
++ dnl Weird platform: only the last -rpath option counts, the user must
++ dnl pass all path elements in one option. We can arrange that for a
++ dnl single library, but not when more than one $LIBNAMEs are used.
++ alldirs=
++ for found_dir in $rpathdirs; do
++ alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir"
++ done
++ dnl Note: hardcode_libdir_flag_spec uses $libdir and $wl.
++ acl_save_libdir="$libdir"
++ libdir="$alldirs"
++ eval flag=\"$hardcode_libdir_flag_spec\"
++ libdir="$acl_save_libdir"
++ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
++ else
++ dnl The -rpath options are cumulative.
++ for found_dir in $rpathdirs; do
++ acl_save_libdir="$libdir"
++ libdir="$found_dir"
++ eval flag=\"$hardcode_libdir_flag_spec\"
++ libdir="$acl_save_libdir"
++ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
++ done
++ fi
++ fi
++ if test "X$ltrpathdirs" != "X"; then
++ dnl When using libtool, the option that works for both libraries and
++ dnl executables is -R. The -R options are cumulative.
++ for found_dir in $ltrpathdirs; do
++ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir"
++ done
++ fi
++])
++
++dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR,
++dnl unless already present in VAR.
++dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes
++dnl contains two or three consecutive elements that belong together.
++AC_DEFUN([AC_LIB_APPENDTOVAR],
++[
++ for element in [$2]; do
++ haveit=
++ for x in $[$1]; do
++ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
++ if test "X$x" = "X$element"; then
++ haveit=yes
++ break
++ fi
++ done
++ if test -z "$haveit"; then
++ [$1]="${[$1]}${[$1]:+ }$element"
++ fi
++ done
++])
++
++# lib-ld.m4 serial 3 (gettext-0.13)
++dnl Copyright (C) 1996-2003 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 Subroutines of libtool.m4,
++dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision
++dnl with libtool.m4.
++
++dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no.
++AC_DEFUN([AC_LIB_PROG_LD_GNU],
++[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld,
++[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
++case `$LD -v 2>&1 </dev/null` in
++*GNU* | *'with BFD'*)
++ acl_cv_prog_gnu_ld=yes ;;
++*)
++ acl_cv_prog_gnu_ld=no ;;
++esac])
++with_gnu_ld=$acl_cv_prog_gnu_ld
++])
++
++dnl From libtool-1.4. Sets the variable LD.
++AC_DEFUN([AC_LIB_PROG_LD],
++[AC_ARG_WITH(gnu-ld,
++[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
++test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
++AC_REQUIRE([AC_PROG_CC])dnl
++AC_REQUIRE([AC_CANONICAL_HOST])dnl
++# Prepare PATH_SEPARATOR.
++# The user is always right.
++if test "${PATH_SEPARATOR+set}" != set; then
++ echo "#! /bin/sh" >conf$$.sh
++ echo "exit 0" >>conf$$.sh
++ chmod +x conf$$.sh
++ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
++ PATH_SEPARATOR=';'
++ else
++ PATH_SEPARATOR=:
++ fi
++ rm -f conf$$.sh
++fi
++ac_prog=ld
++if test "$GCC" = yes; then
++ # Check if gcc -print-prog-name=ld gives a path.
++ AC_MSG_CHECKING([for ld used by GCC])
++ case $host in
++ *-*-mingw*)
++ # gcc leaves a trailing carriage return which upsets mingw
++ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
++ *)
++ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
++ esac
++ case $ac_prog in
++ # Accept absolute paths.
++ [[\\/]* | [A-Za-z]:[\\/]*)]
++ [re_direlt='/[^/][^/]*/\.\./']
++ # Canonicalize the path of ld
++ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
++ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
++ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
++ done
++ test -z "$LD" && LD="$ac_prog"
++ ;;
++ "")
++ # If it fails, then pretend we aren't using GCC.
++ ac_prog=ld
++ ;;
++ *)
++ # If it is relative, then search for the first ld in PATH.
++ with_gnu_ld=unknown
++ ;;
++ esac
++elif test "$with_gnu_ld" = yes; then
++ AC_MSG_CHECKING([for GNU ld])
++else
++ AC_MSG_CHECKING([for non-GNU ld])
++fi
++AC_CACHE_VAL(acl_cv_path_LD,
++[if test -z "$LD"; then
++ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
++ for ac_dir in $PATH; do
++ test -z "$ac_dir" && ac_dir=.
++ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
++ acl_cv_path_LD="$ac_dir/$ac_prog"
++ # Check to see if the program is GNU ld. I'd rather use --version,
++ # but apparently some GNU ld's only accept -v.
++ # Break only if it was the GNU/non-GNU ld that we prefer.
++ case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in
++ *GNU* | *'with BFD'*)
++ test "$with_gnu_ld" != no && break ;;
++ *)
++ test "$with_gnu_ld" != yes && break ;;
++ esac
++ fi
++ done
++ IFS="$ac_save_ifs"
++else
++ acl_cv_path_LD="$LD" # Let the user override the test with a path.
++fi])
++LD="$acl_cv_path_LD"
++if test -n "$LD"; then
++ AC_MSG_RESULT($LD)
++else
++ AC_MSG_RESULT(no)
++fi
++test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
++AC_LIB_PROG_LD_GNU
++])
++
+ # Like AC_CONFIG_HEADER, but automatically create stamp file.
+
+ AC_DEFUN([AM_CONFIG_HEADER],
+@@ -164,12 +983,64 @@
+ AC_PROG_LEX
+ AC_DECL_YYTEXT])
+
+-# libtool.m4 - Configure libtool for the host system. -*-Shell-script-*-
++# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+
+-# serial 46 AC_PROG_LIBTOOL
++# serial 47 AC_PROG_LIBTOOL
++# Debian $Rev$
+
++
++# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED)
++# -----------------------------------------------------------
++# If this macro is not defined by Autoconf, define it here.
++m4_ifdef([AC_PROVIDE_IFELSE],
++ [],
++ [m4_define([AC_PROVIDE_IFELSE],
++ [m4_ifdef([AC_PROVIDE_$1],
++ [$2], [$3])])])
++
++
++# AC_PROG_LIBTOOL
++# ---------------
+ AC_DEFUN([AC_PROG_LIBTOOL],
++[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl
++dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX
++dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX.
++ AC_PROVIDE_IFELSE([AC_PROG_CXX],
++ [AC_LIBTOOL_CXX],
++ [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX
++ ])])
++dnl And a similar setup for Fortran 77 support
++ AC_PROVIDE_IFELSE([AC_PROG_F77],
++ [AC_LIBTOOL_F77],
++ [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77
++])])
++
++dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly.
++dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run
++dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both.
++ AC_PROVIDE_IFELSE([AC_PROG_GCJ],
++ [AC_LIBTOOL_GCJ],
++ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
++ [AC_LIBTOOL_GCJ],
++ [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],
++ [AC_LIBTOOL_GCJ],
++ [ifdef([AC_PROG_GCJ],
++ [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])
++ ifdef([A][M_PROG_GCJ],
++ [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])])
++ ifdef([LT_AC_PROG_GCJ],
++ [define([LT_AC_PROG_GCJ],
++ defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])])
++])])# AC_PROG_LIBTOOL
++
++
++# _AC_PROG_LIBTOOL
++# ----------------
++AC_DEFUN([_AC_PROG_LIBTOOL],
+ [AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
++AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl
++AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl
++AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl
+
+ # This can be used to rebuild libtool when needed
+ LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+@@ -180,10 +1051,13 @@
+
+ # Prevent multiple expansion
+ define([AC_PROG_LIBTOOL], [])
+-])
++])# _AC_PROG_LIBTOOL
+
++
++# AC_LIBTOOL_SETUP
++# ----------------
+ AC_DEFUN([AC_LIBTOOL_SETUP],
+-[AC_PREREQ(2.13)dnl
++[AC_PREREQ(2.50)dnl
+ AC_REQUIRE([AC_ENABLE_SHARED])dnl
+ AC_REQUIRE([AC_ENABLE_STATIC])dnl
+ AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
+@@ -193,15 +1067,103 @@
+ AC_REQUIRE([AC_PROG_LD])dnl
+ AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl
+ AC_REQUIRE([AC_PROG_NM])dnl
+-AC_REQUIRE([LT_AC_PROG_SED])dnl
+
+ AC_REQUIRE([AC_PROG_LN_S])dnl
+ AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl
++# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
+ AC_REQUIRE([AC_OBJEXT])dnl
+ AC_REQUIRE([AC_EXEEXT])dnl
+ dnl
+
++AC_LIBTOOL_SYS_MAX_CMD_LEN
++AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
++AC_LIBTOOL_OBJDIR
++
++AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+ _LT_AC_PROG_ECHO_BACKSLASH
++
++case $host_os in
++aix3*)
++ # AIX sometimes has problems with the GCC collect2 program. For some
++ # reason, if we set the COLLECT_NAMES environment variable, the problems
++ # vanish in a puff of smoke.
++ if test "X${COLLECT_NAMES+set}" != Xset; then
++ COLLECT_NAMES=
++ export COLLECT_NAMES
++ fi
++ ;;
++esac
++
++# Sed substitution that helps us do robust quoting. It backslashifies
++# metacharacters that are still active within double-quoted strings.
++Xsed='sed -e s/^X//'
++[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g']
++
++# Same as above, but do not quote variable references.
++[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g']
++
++# Sed substitution to delay expansion of an escaped shell variable in a
++# double_quote_subst'ed string.
++delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
++
++# Sed substitution to avoid accidental globbing in evaled expressions
++no_glob_subst='s/\*/\\\*/g'
++
++# Constants:
++rm="rm -f"
++
++# Global variables:
++default_ofile=libtool
++can_build_shared=yes
++
++# All known linkers require a `.a' archive for static linking (except M$VC,
++# which needs '.lib').
++libext=a
++ltmain="$ac_aux_dir/ltmain.sh"
++ofile="$default_ofile"
++with_gnu_ld="$lt_cv_prog_gnu_ld"
++
++AC_CHECK_TOOL(AR, ar, false)
++AC_CHECK_TOOL(RANLIB, ranlib, :)
++AC_CHECK_TOOL(STRIP, strip, :)
++
++old_CC="$CC"
++old_CFLAGS="$CFLAGS"
++
++# Set sane defaults for various variables
++test -z "$AR" && AR=ar
++test -z "$AR_FLAGS" && AR_FLAGS=cru
++test -z "$AS" && AS=as
++test -z "$CC" && CC=cc
++test -z "$LTCC" && LTCC=$CC
++test -z "$DLLTOOL" && DLLTOOL=dlltool
++test -z "$LD" && LD=ld
++test -z "$LN_S" && LN_S="ln -s"
++test -z "$MAGIC_CMD" && MAGIC_CMD=file
++test -z "$NM" && NM=nm
++test -z "$SED" && SED=sed
++test -z "$OBJDUMP" && OBJDUMP=objdump
++test -z "$RANLIB" && RANLIB=:
++test -z "$STRIP" && STRIP=:
++test -z "$ac_objext" && ac_objext=o
++
++# Determine commands to create old-style static archives.
++old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
++old_postinstall_cmds='chmod 644 $oldlib'
++old_postuninstall_cmds=
++
++if test -n "$RANLIB"; then
++ case $host_os in
++ openbsd*)
++ old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds"
++ ;;
++ *)
++ old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
++ ;;
++ esac
++ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
++fi
++
+ # Only perform the check for file, if the check method requires it
+ case $deplibs_check_method in
+ file_magic*)
+@@ -211,327 +1173,78 @@
+ ;;
+ esac
+
+-AC_CHECK_TOOL(RANLIB, ranlib, :)
+-AC_CHECK_TOOL(STRIP, strip, :)
+-
+-ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no)
+-ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
++AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no)
++AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+ enable_win32_dll=yes, enable_win32_dll=no)
+
+-AC_ARG_ENABLE(libtool-lock,
+- [ --disable-libtool-lock avoid locking (might break parallel builds)])
++AC_ARG_ENABLE([libtool-lock],
++ [AC_HELP_STRING([--disable-libtool-lock],
++ [avoid locking (might break parallel builds)])])
+ test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+-# Some flags need to be propagated to the compiler or linker for good
+-# libtool support.
+-case $host in
+-*-*-irix6*)
+- # Find out which ABI we are using.
+- echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+- if AC_TRY_EVAL(ac_compile); then
+- case `/usr/bin/file conftest.$ac_objext` in
+- *32-bit*)
+- LD="${LD-ld} -32"
+- ;;
+- *N32*)
+- LD="${LD-ld} -n32"
+- ;;
+- *64-bit*)
+- LD="${LD-ld} -64"
+- ;;
+- esac
+- fi
+- rm -rf conftest*
+- ;;
++AC_ARG_WITH([pic],
++ [AC_HELP_STRING([--with-pic],
++ [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
++ [pic_mode="$withval"],
++ [pic_mode=default])
++test -z "$pic_mode" && pic_mode=default
+
+-*-*-sco3.2v5*)
+- # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+- SAVE_CFLAGS="$CFLAGS"
+- CFLAGS="$CFLAGS -belf"
+- AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+- [AC_LANG_SAVE
+- AC_LANG_C
+- AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+- AC_LANG_RESTORE])
+- if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+- # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+- CFLAGS="$SAVE_CFLAGS"
+- fi
+- ;;
++# Use C for the default configuration in the libtool script
++tagname=
++AC_LIBTOOL_LANG_C_CONFIG
++_LT_AC_TAGCONFIG
++])# AC_LIBTOOL_SETUP
+
+-ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
+-[*-*-cygwin* | *-*-mingw* | *-*-pw32*)
+- AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+- AC_CHECK_TOOL(AS, as, false)
+- AC_CHECK_TOOL(OBJDUMP, objdump, false)
+
+- # recent cygwin and mingw systems supply a stub DllMain which the user
+- # can override, but on older systems we have to supply one
+- AC_CACHE_CHECK([if libtool should supply DllMain function], lt_cv_need_dllmain,
+- [AC_TRY_LINK([],
+- [extern int __attribute__((__stdcall__)) DllMain(void*, int, void*);
+- DllMain (0, 0, 0);],
+- [lt_cv_need_dllmain=no],[lt_cv_need_dllmain=yes])])
+-
+- case $host/$CC in
+- *-*-cygwin*/gcc*-mno-cygwin*|*-*-mingw*)
+- # old mingw systems require "-dll" to link a DLL, while more recent ones
+- # require "-mdll"
+- SAVE_CFLAGS="$CFLAGS"
+- CFLAGS="$CFLAGS -mdll"
+- AC_CACHE_CHECK([how to link DLLs], lt_cv_cc_dll_switch,
+- [AC_TRY_LINK([], [], [lt_cv_cc_dll_switch=-mdll],[lt_cv_cc_dll_switch=-dll])])
+- CFLAGS="$SAVE_CFLAGS" ;;
+- *-*-cygwin* | *-*-pw32*)
+- # cygwin systems need to pass --dll to the linker, and not link
+- # crt.o which will require a WinMain@16 definition.
+- lt_cv_cc_dll_switch="-Wl,--dll -nostartfiles" ;;
+- esac
+- ;;
+- ])
+-esac
++# _LT_AC_SYS_COMPILER
++# -------------------
++AC_DEFUN([_LT_AC_SYS_COMPILER],
++[AC_REQUIRE([AC_PROG_CC])dnl
+
+-_LT_AC_LTCONFIG_HACK
++# If no C compiler was specified, use CC.
++LTCC=${LTCC-"$CC"}
+
+-])
+-
+-# AC_LIBTOOL_HEADER_ASSERT
+-# ------------------------
+-AC_DEFUN([AC_LIBTOOL_HEADER_ASSERT],
+-[AC_CACHE_CHECK([whether $CC supports assert without backlinking],
+- [lt_cv_func_assert_works],
+- [case $host in
+- *-*-solaris*)
+- if test "$GCC" = yes && test "$with_gnu_ld" != yes; then
+- case `$CC --version 2>/dev/null` in
+- [[12]].*) lt_cv_func_assert_works=no ;;
+- *) lt_cv_func_assert_works=yes ;;
+- esac
+- fi
+- ;;
+- esac])
+-
+-if test "x$lt_cv_func_assert_works" = xyes; then
+- AC_CHECK_HEADERS(assert.h)
+-fi
+-])# AC_LIBTOOL_HEADER_ASSERT
+-
+-# _LT_AC_CHECK_DLFCN
+-# --------------------
+-AC_DEFUN([_LT_AC_CHECK_DLFCN],
+-[AC_CHECK_HEADERS(dlfcn.h)
+-])# _LT_AC_CHECK_DLFCN
+-
+-# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+-# ---------------------------------
+-AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE],
+-[AC_REQUIRE([AC_CANONICAL_HOST])
+-AC_REQUIRE([AC_PROG_NM])
+-AC_REQUIRE([AC_OBJEXT])
+-# Check for command to grab the raw symbol name followed by C symbol from nm.
+-AC_MSG_CHECKING([command to parse $NM output])
+-AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [dnl
+-
+-# These are sane defaults that work on at least a few old systems.
+-# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+-
+-# Character class describing NM global symbol codes.
+-symcode='[[BCDEGRST]]'
+-
+-# Regexp to match symbols that can be accessed directly from C.
+-sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+-
+-# Transform the above into a raw symbol and a C symbol.
+-symxfrm='\1 \2\3 \3'
+-
+-# Transform an extracted symbol line into a proper C declaration
+-lt_cv_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
+-
+-# Transform an extracted symbol line into symbol name and symbol address
+-lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+-
+-# Define system-specific variables.
+-case $host_os in
+-aix*)
+- symcode='[[BCDT]]'
+- ;;
+-cygwin* | mingw* | pw32*)
+- symcode='[[ABCDGISTW]]'
+- ;;
+-hpux*) # Its linker distinguishes data from code symbols
+- lt_cv_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+- lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+- ;;
+-irix* | nonstopux*)
+- symcode='[[BCDEGRST]]'
+- ;;
+-osf*)
+- symcode='[[BCDEGQRST]]'
+- ;;
+-solaris* | sysv5*)
+- symcode='[[BDT]]'
+- ;;
+-sysv4)
+- symcode='[[DFNSTU]]'
+- ;;
+-esac
+-
+-# Handle CRLF in mingw tool chain
+-opt_cr=
+-case $host_os in
+-mingw*)
+- opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+- ;;
+-esac
+-
+-# If we're using GNU nm, then use its standard symbol codes.
+-if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+- symcode='[[ABCDGISTW]]'
+-fi
+-
+-# Try without a prefix undercore, then with it.
+-for ac_symprfx in "" "_"; do
+-
+- # Write the raw and C identifiers.
+-lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'"
+-
+- # Check to see that the pipe works correctly.
+- pipe_works=no
+- rm -f conftest*
+- cat > conftest.$ac_ext <<EOF
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-char nm_test_var;
+-void nm_test_func(){}
+-#ifdef __cplusplus
+-}
+-#endif
+-int main(){nm_test_var='a';nm_test_func();return(0);}
+-EOF
+-
+- if AC_TRY_EVAL(ac_compile); then
+- # Now try to grab the symbols.
+- nlist=conftest.nm
+- if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+- # Try sorting and uniquifying the output.
+- if sort "$nlist" | uniq > "$nlist"T; then
+- mv -f "$nlist"T "$nlist"
+- else
+- rm -f "$nlist"T
+- fi
+-
+- # Make sure that we snagged all the symbols we need.
+- if egrep ' nm_test_var$' "$nlist" >/dev/null; then
+- if egrep ' nm_test_func$' "$nlist" >/dev/null; then
+- cat <<EOF > conftest.$ac_ext
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-EOF
+- # Now generate the symbol file.
+- eval "$lt_cv_global_symbol_to_cdecl"' < "$nlist" >> conftest.$ac_ext'
+-
+- cat <<EOF >> conftest.$ac_ext
+-#if defined (__STDC__) && __STDC__
+-# define lt_ptr void *
+-#else
+-# define lt_ptr char *
+-# define const
+-#endif
+-
+-/* The mapping between symbol names and symbols. */
+-const struct {
+- const char *name;
+- lt_ptr address;
+-}
+-lt_preloaded_symbols[[]] =
+-{
+-EOF
+- sed "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr) \&\2},/" < "$nlist" >> conftest.$ac_ext
+- cat <<\EOF >> conftest.$ac_ext
+- {0, (lt_ptr) 0}
+-};
++# Allow CC to be a program name with arguments.
++compiler=$CC
++])# _LT_AC_SYS_COMPILER
+
+-#ifdef __cplusplus
+-}
+-#endif
+-EOF
+- # Now try linking the two files.
+- mv conftest.$ac_objext conftstm.$ac_objext
+- save_LIBS="$LIBS"
+- save_CFLAGS="$CFLAGS"
+- LIBS="conftstm.$ac_objext"
+- CFLAGS="$CFLAGS$no_builtin_flag"
+- if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then
+- pipe_works=yes
+- fi
+- LIBS="$save_LIBS"
+- CFLAGS="$save_CFLAGS"
+- else
+- echo "cannot find nm_test_func in $nlist" >&AC_FD_CC
+- fi
+- else
+- echo "cannot find nm_test_var in $nlist" >&AC_FD_CC
+- fi
+- else
+- echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AC_FD_CC
+- fi
+- else
+- echo "$progname: failed program was:" >&AC_FD_CC
+- cat conftest.$ac_ext >&5
+- fi
+- rm -f conftest* conftst*
+
+- # Do not use the global_symbol_pipe unless it works.
+- if test "$pipe_works" = yes; then
+- break
+- else
+- lt_cv_sys_global_symbol_pipe=
+- fi
+-done
+-])
+-global_symbol_pipe="$lt_cv_sys_global_symbol_pipe"
+-if test -z "$lt_cv_sys_global_symbol_pipe"; then
+- global_symbol_to_cdecl=
+- global_symbol_to_c_name_address=
+-else
+- global_symbol_to_cdecl="$lt_cv_global_symbol_to_cdecl"
+- global_symbol_to_c_name_address="$lt_cv_global_symbol_to_c_name_address"
+-fi
+-if test -z "$global_symbol_pipe$global_symbol_to_cdec$global_symbol_to_c_name_address";
+-then
+- AC_MSG_RESULT(failed)
+-else
+- AC_MSG_RESULT(ok)
+-fi
+-]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
++# _LT_AC_SYS_LIBPATH_AIX
++# ----------------------
++# Links a minimal program and checks the executable
++# for the system default hardcoded library path. In most cases,
++# this is /usr/lib:/lib, but when the MPI compilers are used
++# the location of the communication and MPI libs are included too.
++# If we don't find anything, use the default library path according
++# to the aix ld manual.
++AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX],
++[AC_LINK_IFELSE(AC_LANG_PROGRAM,[
++aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
++}'`
++# Check for a 64-bit object if we didn't find anything.
++if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
++}'`; fi],[])
++if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
++])# _LT_AC_SYS_LIBPATH_AIX
++
++
++# _LT_AC_SHELL_INIT(ARG)
++# ----------------------
++AC_DEFUN([_LT_AC_SHELL_INIT],
++[ifdef([AC_DIVERSION_NOTICE],
++ [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
++ [AC_DIVERT_PUSH(NOTICE)])
++$1
++AC_DIVERT_POP
++])# _LT_AC_SHELL_INIT
+
+-# _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR
+-# ---------------------------------
+-AC_DEFUN([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR],
+-[# Find the correct PATH separator. Usually this is `:', but
+-# DJGPP uses `;' like DOS.
+-if test "X${PATH_SEPARATOR+set}" != Xset; then
+- UNAME=${UNAME-`uname 2>/dev/null`}
+- case X$UNAME in
+- *-DOS) lt_cv_sys_path_separator=';' ;;
+- *) lt_cv_sys_path_separator=':' ;;
+- esac
+- PATH_SEPARATOR=$lt_cv_sys_path_separator
+-fi
+-])# _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR
+
+ # _LT_AC_PROG_ECHO_BACKSLASH
+ # --------------------------
+ # Add some code to the start of the generated configure script which
+ # will find an echo command which doesn't interpret backslashes.
+ AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH],
+-[ifdef([AC_DIVERSION_NOTICE], [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+- [AC_DIVERT_PUSH(NOTICE)])
+-_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR
+-
++[_LT_AC_SHELL_INIT([
+ # Check that we are running under the correct shell.
+ SHELL=${CONFIG_SHELL-/bin/sh}
+
+@@ -549,7 +1262,7 @@
+ elif test "X[$]1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+-elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
++elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
+ # Yippee, $echo works!
+ :
+ else
+@@ -561,7 +1274,7 @@
+ # used as fallback echo
+ shift
+ cat <<EOF
+-$*
++[$]*
+ EOF
+ exit 0
+ fi
+@@ -595,8 +1308,9 @@
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+- IFS="${IFS= }"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR
++ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
++ IFS="$lt_save_ifs"
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+@@ -605,7 +1319,7 @@
+ break
+ fi
+ done
+- IFS="$save_ifs"
++ IFS="$lt_save_ifs"
+
+ if test "X$echo" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+@@ -678,47 +1392,328 @@
+ fi
+
+ AC_SUBST(ECHO)
+-AC_DIVERT_POP
+-])# _LT_AC_PROG_ECHO_BACKSLASH
++])])# _LT_AC_PROG_ECHO_BACKSLASH
+
+-# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+-# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+-# ------------------------------------------------------------------
+-AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF],
+-[if test "$cross_compiling" = yes; then :
+- [$4]
+-else
+- AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+- lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+- lt_status=$lt_dlunknown
+- cat > conftest.$ac_ext <<EOF
+-[#line __oline__ "configure"
+-#include "confdefs.h"
+
+-#if HAVE_DLFCN_H
+-#include <dlfcn.h>
+-#endif
++# _LT_AC_LOCK
++# -----------
++AC_DEFUN([_LT_AC_LOCK],
++[AC_ARG_ENABLE([libtool-lock],
++ [AC_HELP_STRING([--disable-libtool-lock],
++ [avoid locking (might break parallel builds)])])
++test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+-#include <stdio.h>
++# Some flags need to be propagated to the compiler or linker for good
++# libtool support.
++case $host in
++ia64-*-hpux*)
++ # Find out which ABI we are using.
++ echo 'int i;' > conftest.$ac_ext
++ if AC_TRY_EVAL(ac_compile); then
++ case `/usr/bin/file conftest.$ac_objext` in
++ *ELF-32*)
++ HPUX_IA64_MODE="32"
++ ;;
++ *ELF-64*)
++ HPUX_IA64_MODE="64"
++ ;;
++ esac
++ fi
++ rm -rf conftest*
++ ;;
++*-*-irix6*)
++ # Find out which ABI we are using.
++ echo '[#]line __oline__ "configure"' > conftest.$ac_ext
++ if AC_TRY_EVAL(ac_compile); then
++ if test "$lt_cv_prog_gnu_ld" = yes; then
++ case `/usr/bin/file conftest.$ac_objext` in
++ *32-bit*)
++ LD="${LD-ld} -melf32bsmip"
++ ;;
++ *N32*)
++ LD="${LD-ld} -melf32bmipn32"
++ ;;
++ *64-bit*)
++ LD="${LD-ld} -melf64bmip"
++ ;;
++ esac
++ else
++ case `/usr/bin/file conftest.$ac_objext` in
++ *32-bit*)
++ LD="${LD-ld} -32"
++ ;;
++ *N32*)
++ LD="${LD-ld} -n32"
++ ;;
++ *64-bit*)
++ LD="${LD-ld} -64"
++ ;;
++ esac
++ fi
++ fi
++ rm -rf conftest*
++ ;;
+
+-#ifdef RTLD_GLOBAL
+-# define LT_DLGLOBAL RTLD_GLOBAL
+-#else
+-# ifdef DL_GLOBAL
+-# define LT_DLGLOBAL DL_GLOBAL
+-# else
+-# define LT_DLGLOBAL 0
+-# endif
+-#endif
++x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
++ # Find out which ABI we are using.
++ echo 'int i;' > conftest.$ac_ext
++ if AC_TRY_EVAL(ac_compile); then
++ case "`/usr/bin/file conftest.o`" in
++ *32-bit*)
++ case $host in
++ x86_64-*linux*)
++ LD="${LD-ld} -m elf_i386"
++ ;;
++ ppc64-*linux*|powerpc64-*linux*)
++ LD="${LD-ld} -m elf32ppclinux"
++ ;;
++ s390x-*linux*)
++ LD="${LD-ld} -m elf_s390"
++ ;;
++ sparc64-*linux*)
++ LD="${LD-ld} -m elf32_sparc"
++ ;;
++ esac
++ ;;
++ *64-bit*)
++ case $host in
++ x86_64-*linux*)
++ LD="${LD-ld} -m elf_x86_64"
++ ;;
++ ppc*-*linux*|powerpc*-*linux*)
++ LD="${LD-ld} -m elf64ppc"
++ ;;
++ s390*-*linux*)
++ LD="${LD-ld} -m elf64_s390"
++ ;;
++ sparc*-*linux*)
++ LD="${LD-ld} -m elf64_sparc"
++ ;;
++ esac
++ ;;
++ esac
++ fi
++ rm -rf conftest*
++ ;;
+
+-/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+- find out it does not work in some platform. */
+-#ifndef LT_DLLAZY_OR_NOW
+-# ifdef RTLD_LAZY
+-# define LT_DLLAZY_OR_NOW RTLD_LAZY
+-# else
+-# ifdef DL_LAZY
+-# define LT_DLLAZY_OR_NOW DL_LAZY
++*-*-sco3.2v5*)
++ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
++ SAVE_CFLAGS="$CFLAGS"
++ CFLAGS="$CFLAGS -belf"
++ AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
++ [AC_LANG_PUSH(C)
++ AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
++ AC_LANG_POP])
++ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
++ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
++ CFLAGS="$SAVE_CFLAGS"
++ fi
++ ;;
++AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
++[*-*-cygwin* | *-*-mingw* | *-*-pw32*)
++ AC_CHECK_TOOL(DLLTOOL, dlltool, false)
++ AC_CHECK_TOOL(AS, as, false)
++ AC_CHECK_TOOL(OBJDUMP, objdump, false)
++ ;;
++ ])
++esac
++
++need_locks="$enable_libtool_lock"
++
++])# _LT_AC_LOCK
++
++
++# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
++# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
++# ----------------------------------------------------------------
++# Check whether the given compiler option works
++AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION],
++[AC_REQUIRE([LT_AC_PROG_SED])
++AC_CACHE_CHECK([$1], [$2],
++ [$2=no
++ ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
++ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
++ lt_compiler_flag="$3"
++ # Insert the option either (1) after the last *FLAGS variable, or
++ # (2) before a word containing "conftest.", or (3) at the end.
++ # Note that $ac_compile itself does not contain backslashes and begins
++ # with a dollar sign (not a hyphen), so the echo should work correctly.
++ # The option is referenced via a variable to avoid confusing sed.
++ lt_compile=`echo "$ac_compile" | $SED \
++ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
++ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
++ -e 's:$: $lt_compiler_flag:'`
++ (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
++ (eval "$lt_compile" 2>conftest.err)
++ ac_status=$?
++ cat conftest.err >&AS_MESSAGE_LOG_FD
++ echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
++ if (exit $ac_status) && test -s "$ac_outfile"; then
++ # The compiler can only warn and ignore the option if not recognized
++ # So say no if there are warnings
++ if test ! -s conftest.err; then
++ $2=yes
++ fi
++ fi
++ $rm conftest*
++])
++
++if test x"[$]$2" = xyes; then
++ ifelse([$5], , :, [$5])
++else
++ ifelse([$6], , :, [$6])
++fi
++])# AC_LIBTOOL_COMPILER_OPTION
++
++
++# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
++# [ACTION-SUCCESS], [ACTION-FAILURE])
++# ------------------------------------------------------------
++# Check whether the given compiler option works
++AC_DEFUN([AC_LIBTOOL_LINKER_OPTION],
++[AC_CACHE_CHECK([$1], [$2],
++ [$2=no
++ save_LDFLAGS="$LDFLAGS"
++ LDFLAGS="$LDFLAGS $3"
++ printf "$lt_simple_link_test_code" > conftest.$ac_ext
++ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
++ # The compiler can only warn and ignore the option if not recognized
++ # So say no if there are warnings
++ if test -s conftest.err; then
++ # Append any errors to the config.log.
++ cat conftest.err 1>&AS_MESSAGE_LOG_FD
++ else
++ $2=yes
++ fi
++ fi
++ $rm conftest*
++ LDFLAGS="$save_LDFLAGS"
++])
++
++if test x"[$]$2" = xyes; then
++ ifelse([$4], , :, [$4])
++else
++ ifelse([$5], , :, [$5])
++fi
++])# AC_LIBTOOL_LINKER_OPTION
++
++
++# AC_LIBTOOL_SYS_MAX_CMD_LEN
++# --------------------------
++AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN],
++[# find the maximum length of command line arguments
++AC_MSG_CHECKING([the maximum length of command line arguments])
++AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
++ i=0
++ teststring="ABCD"
++
++ case $build_os in
++ msdosdjgpp*)
++ # On DJGPP, this test can blow up pretty badly due to problems in libc
++ # (any single argument exceeding 2000 bytes causes a buffer overrun
++ # during glob expansion). Even if it were fixed, the result of this
++ # check would be larger than it should be.
++ lt_cv_sys_max_cmd_len=12288; # 12K is about right
++ ;;
++
++ gnu*)
++ # Under GNU Hurd, this test is not required because there is
++ # no limit to the length of command line arguments.
++ # Libtool will interpret -1 as no limit whatsoever
++ lt_cv_sys_max_cmd_len=-1;
++ ;;
++
++ cygwin* | mingw*)
++ # On Win9x/ME, this test blows up -- it succeeds, but takes
++ # about 5 minutes as the teststring grows exponentially.
++ # Worse, since 9x/ME are not pre-emptively multitasking,
++ # you end up with a "frozen" computer, even though with patience
++ # the test eventually succeeds (with a max line length of 256k).
++ # Instead, let's just punt: use the minimum linelength reported by
++ # all of the supported platforms: 8192 (on NT/2K/XP).
++ lt_cv_sys_max_cmd_len=8192;
++ ;;
++
++ amigaos*)
++ # On AmigaOS with pdksh, this test takes hours, literally.
++ # So we just punt and use a minimum line length of 8192.
++ lt_cv_sys_max_cmd_len=8192;
++ ;;
++
++ *)
++ # If test is not a shell built-in, we'll probably end up computing a
++ # maximum length that is only half of the actual maximum length, but
++ # we can't tell.
++ while (test "X"`$CONFIG_SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \
++ = "XX$teststring") >/dev/null 2>&1 &&
++ new_result=`expr "X$teststring" : ".*" 2>&1` &&
++ lt_cv_sys_max_cmd_len=$new_result &&
++ test $i != 17 # 1/2 MB should be enough
++ do
++ i=`expr $i + 1`
++ teststring=$teststring$teststring
++ done
++ teststring=
++ # Add a significant safety factor because C++ compilers can tack on massive
++ # amounts of additional arguments before passing them to the linker.
++ # It appears as though 1/2 is a usable value.
++ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
++ ;;
++ esac
++])
++if test -n $lt_cv_sys_max_cmd_len ; then
++ AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
++else
++ AC_MSG_RESULT(none)
++fi
++])# AC_LIBTOOL_SYS_MAX_CMD_LEN
++
++
++# _LT_AC_CHECK_DLFCN
++# --------------------
++AC_DEFUN([_LT_AC_CHECK_DLFCN],
++[AC_CHECK_HEADERS(dlfcn.h)dnl
++])# _LT_AC_CHECK_DLFCN
++
++
++# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
++# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
++# ------------------------------------------------------------------
++AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF],
++[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
++if test "$cross_compiling" = yes; then :
++ [$4]
++else
++ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
++ lt_status=$lt_dlunknown
++ cat > conftest.$ac_ext <<EOF
++[#line __oline__ "configure"
++#include "confdefs.h"
++
++#if HAVE_DLFCN_H
++#include <dlfcn.h>
++#endif
++
++#include <stdio.h>
++
++#ifdef RTLD_GLOBAL
++# define LT_DLGLOBAL RTLD_GLOBAL
++#else
++# ifdef DL_GLOBAL
++# define LT_DLGLOBAL DL_GLOBAL
++# else
++# define LT_DLGLOBAL 0
++# endif
++#endif
++
++/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
++ find out it does not work in some platform. */
++#ifndef LT_DLLAZY_OR_NOW
++# ifdef RTLD_LAZY
++# define LT_DLLAZY_OR_NOW RTLD_LAZY
++# else
++# ifdef DL_LAZY
++# define LT_DLLAZY_OR_NOW DL_LAZY
+ # else
+ # ifdef RTLD_NOW
+ # define LT_DLLAZY_OR_NOW RTLD_NOW
+@@ -769,10 +1764,12 @@
+ rm -fr conftest*
+ ])# _LT_AC_TRY_DLOPEN_SELF
+
++
+ # AC_LIBTOOL_DLOPEN_SELF
+ # -------------------
+ AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF],
+-[if test "x$enable_dlopen" != xyes; then
++[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
++if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+@@ -787,24 +1784,39 @@
+ lt_cv_dlopen_self=yes
+ ;;
+
+- cygwin* | mingw* | pw32*)
++ mingw* | pw32*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
++ cygwin*)
++ lt_cv_dlopen="dlopen"
++ lt_cv_dlopen_libs=
++ ;;
++
++ darwin*)
++ # if libdl is installed we need to link against it
++ AC_CHECK_LIB([dl], [dlopen],
++ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
++ lt_cv_dlopen="dyld"
++ lt_cv_dlopen_libs=
++ lt_cv_dlopen_self=yes
++ ])
++ ;;
++
+ *)
+ AC_CHECK_FUNC([shl_load],
+- [lt_cv_dlopen="shl_load"],
++ [lt_cv_dlopen="shl_load"],
+ [AC_CHECK_LIB([dld], [shl_load],
+- [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"],
++ [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"],
+ [AC_CHECK_FUNC([dlopen],
+ [lt_cv_dlopen="dlopen"],
+ [AC_CHECK_LIB([dl], [dlopen],
+- [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
++ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+ [AC_CHECK_LIB([svld], [dlopen],
+- [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
++ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+ [AC_CHECK_LIB([dld], [dld_link],
+- [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"])
++ [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"])
+ ])
+ ])
+ ])
+@@ -822,7 +1834,6 @@
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+- AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+@@ -866,707 +1877,1838 @@
+ fi
+ ])# AC_LIBTOOL_DLOPEN_SELF
+
+-AC_DEFUN([_LT_AC_LTCONFIG_HACK],
+-[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])dnl
+-# Sed substitution that helps us do robust quoting. It backslashifies
+-# metacharacters that are still active within double-quoted strings.
+-Xsed='sed -e s/^X//'
+-sed_quote_subst='s/\([[\\"\\`$\\\\]]\)/\\\1/g'
+-
+-# Same as above, but do not quote variable references.
+-double_quote_subst='s/\([[\\"\\`\\\\]]\)/\\\1/g'
+-
+-# Sed substitution to delay expansion of an escaped shell variable in a
+-# double_quote_subst'ed string.
+-delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+-# Constants:
+-rm="rm -f"
++# AC_LIBTOOL_PROG_CC_C_O([TAGNAME])
++# ---------------------------------
++# Check to see if options -c and -o are simultaneously supported by compiler
++AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O],
++[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
++AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
++ [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
++ [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
++ $rm -r conftest 2>/dev/null
++ mkdir conftest
++ cd conftest
++ mkdir out
++ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
++
++ lt_compiler_flag="-o out/conftest2.$ac_objext"
++ # Insert the option either (1) after the last *FLAGS variable, or
++ # (2) before a word containing "conftest.", or (3) at the end.
++ # Note that $ac_compile itself does not contain backslashes and begins
++ # with a dollar sign (not a hyphen), so the echo should work correctly.
++ lt_compile=`echo "$ac_compile" | $SED \
++ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
++ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
++ -e 's:$: $lt_compiler_flag:'`
++ (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
++ (eval "$lt_compile" 2>out/conftest.err)
++ ac_status=$?
++ cat out/conftest.err >&AS_MESSAGE_LOG_FD
++ echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
++ if (exit $ac_status) && test -s out/conftest2.$ac_objext
++ then
++ # The compiler can only warn and ignore the option if not recognized
++ # So say no if there are warnings
++ if test ! -s out/conftest.err; then
++ _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
++ fi
++ fi
++ chmod u+w .
++ $rm conftest*
++ # SGI C++ compiler will create directory out/ii_files/ for
++ # template instantiation
++ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
++ $rm out/* && rmdir out
++ cd ..
++ rmdir conftest
++ $rm conftest*
++])
++])# AC_LIBTOOL_PROG_CC_C_O
+
+-# Global variables:
+-default_ofile=libtool
+-can_build_shared=yes
+
+-# All known linkers require a `.a' archive for static linking (except M$VC,
+-# which needs '.lib').
+-libext=a
+-ltmain="$ac_aux_dir/ltmain.sh"
+-ofile="$default_ofile"
+-with_gnu_ld="$lt_cv_prog_gnu_ld"
+-need_locks="$enable_libtool_lock"
++# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME])
++# -----------------------------------------
++# Check to see if we can do hard links to lock some files if needed
++AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS],
++[AC_REQUIRE([_LT_AC_LOCK])dnl
+
+-old_CC="$CC"
+-old_CFLAGS="$CFLAGS"
++hard_links="nottested"
++if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
++ # do not overwrite the value of need_locks provided by the user
++ AC_MSG_CHECKING([if we can lock with hard links])
++ hard_links=yes
++ $rm conftest*
++ ln conftest.a conftest.b 2>/dev/null && hard_links=no
++ touch conftest.a
++ ln conftest.a conftest.b 2>&5 || hard_links=no
++ ln conftest.a conftest.b 2>/dev/null && hard_links=no
++ AC_MSG_RESULT([$hard_links])
++ if test "$hard_links" = no; then
++ AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
++ need_locks=warn
++ fi
++else
++ need_locks=no
++fi
++])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS
+
+-# Set sane defaults for various variables
+-test -z "$AR" && AR=ar
+-test -z "$AR_FLAGS" && AR_FLAGS=cru
+-test -z "$AS" && AS=as
+-test -z "$CC" && CC=cc
+-test -z "$DLLTOOL" && DLLTOOL=dlltool
+-test -z "$LD" && LD=ld
+-test -z "$LN_S" && LN_S="ln -s"
+-test -z "$MAGIC_CMD" && MAGIC_CMD=file
+-test -z "$NM" && NM=nm
+-test -z "$OBJDUMP" && OBJDUMP=objdump
+-test -z "$RANLIB" && RANLIB=:
+-test -z "$STRIP" && STRIP=:
+-test -z "$ac_objext" && ac_objext=o
+
+-if test x"$host" != x"$build"; then
+- ac_tool_prefix=${host_alias}-
++# AC_LIBTOOL_OBJDIR
++# -----------------
++AC_DEFUN([AC_LIBTOOL_OBJDIR],
++[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
++[rm -f .libs 2>/dev/null
++mkdir .libs 2>/dev/null
++if test -d .libs; then
++ lt_cv_objdir=.libs
+ else
+- ac_tool_prefix=
++ # MS-DOS does not allow filenames that begin with a dot.
++ lt_cv_objdir=_libs
+ fi
++rmdir .libs 2>/dev/null])
++objdir=$lt_cv_objdir
++])# AC_LIBTOOL_OBJDIR
+
+-# Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+-case $host_os in
+-linux-gnu*) ;;
+-linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+-esac
+
+-case $host_os in
+-aix3*)
+- # AIX sometimes has problems with the GCC collect2 program. For some
+- # reason, if we set the COLLECT_NAMES environment variable, the problems
+- # vanish in a puff of smoke.
+- if test "X${COLLECT_NAMES+set}" != Xset; then
+- COLLECT_NAMES=
+- export COLLECT_NAMES
++# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME])
++# ----------------------------------------------
++# Check hardcoding attributes.
++AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH],
++[AC_MSG_CHECKING([how to hardcode library paths into programs])
++_LT_AC_TAGVAR(hardcode_action, $1)=
++if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \
++ test -n "$_LT_AC_TAGVAR(runpath_var $1)" || \
++ test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)"="Xyes" ; then
++
++ # We can hardcode non-existant directories.
++ if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no &&
++ # If the only mechanism to avoid hardcoding is shlibpath_var, we
++ # have to relink, otherwise we might link with an installed library
++ # when we should be linking with a yet-to-be-installed one
++ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
++ test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then
++ # Linking always hardcodes the temporary library directory.
++ _LT_AC_TAGVAR(hardcode_action, $1)=relink
++ else
++ # We can link without hardcoding, and we can hardcode nonexisting dirs.
++ _LT_AC_TAGVAR(hardcode_action, $1)=immediate
+ fi
+- ;;
+-esac
++else
++ # We cannot hardcode anything, or else we can only hardcode existing
++ # directories.
++ _LT_AC_TAGVAR(hardcode_action, $1)=unsupported
++fi
++AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)])
+
+-# Determine commands to create old-style static archives.
+-old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
+-old_postinstall_cmds='chmod 644 $oldlib'
+-old_postuninstall_cmds=
++if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then
++ # Fast installation is not supported
++ enable_fast_install=no
++elif test "$shlibpath_overrides_runpath" = yes ||
++ test "$enable_shared" = no; then
++ # Fast installation is not necessary
++ enable_fast_install=needless
++fi
++])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH
+
+-if test -n "$RANLIB"; then
++
++# AC_LIBTOOL_SYS_LIB_STRIP
++# ------------------------
++AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP],
++[striplib=
++old_striplib=
++AC_MSG_CHECKING([whether stripping libraries is possible])
++if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
++ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
++ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
++ AC_MSG_RESULT([yes])
++else
++# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+- openbsd*)
+- old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds"
+- ;;
+- *)
+- old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
++ darwin*)
++ if test -n "$STRIP" ; then
++ striplib="$STRIP -x"
++ AC_MSG_RESULT([yes])
++ else
++ AC_MSG_RESULT([no])
++fi
++ ;;
++ *)
++ AC_MSG_RESULT([no])
+ ;;
+ esac
+- old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+ fi
++])# AC_LIBTOOL_SYS_LIB_STRIP
+
+-# Allow CC to be a program name with arguments.
+-set dummy $CC
+-compiler="[$]2"
+
+-AC_MSG_CHECKING([for objdir])
+-rm -f .libs 2>/dev/null
+-mkdir .libs 2>/dev/null
+-if test -d .libs; then
+- objdir=.libs
++# AC_LIBTOOL_SYS_DYNAMIC_LINKER
++# -----------------------------
++# PORTME Fill in your ld.so characteristics
++AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER],
++[AC_MSG_CHECKING([dynamic linker characteristics])
++library_names_spec=
++libname_spec='lib$name'
++soname_spec=
++shrext_cmds=".so"
++postinstall_cmds=
++postuninstall_cmds=
++finish_cmds=
++finish_eval=
++shlibpath_var=
++shlibpath_overrides_runpath=unknown
++version_type=none
++dynamic_linker="$host_os ld.so"
++sys_lib_dlsearch_path_spec="/lib /usr/lib"
++if test "$GCC" = yes; then
++ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
++ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
++ # if the path contains ";" then we assume it to be the separator
++ # otherwise default to the standard path separator (i.e. ":") - it is
++ # assumed that no part of a normal pathname contains ";" but that should
++ # okay in the real world where ";" in dirpaths is itself problematic.
++ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
++ else
++ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
++ fi
+ else
+- # MS-DOS does not allow filenames that begin with a dot.
+- objdir=_libs
++ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+ fi
+-rmdir .libs 2>/dev/null
+-AC_MSG_RESULT($objdir)
+-
++need_lib_prefix=unknown
++hardcode_into_libs=no
+
+-AC_ARG_WITH(pic,
+-[ --with-pic try to use only PIC/non-PIC objects [default=use both]],
+-pic_mode="$withval", pic_mode=default)
+-test -z "$pic_mode" && pic_mode=default
++# when you set need_version to no, make sure it does not cause -set_version
++# flags to be left without arguments
++need_version=unknown
+
+-# We assume here that the value for lt_cv_prog_cc_pic will not be cached
+-# in isolation, and that seeing it set (from the cache) indicates that
+-# the associated values are set (in the cache) correctly too.
+-AC_MSG_CHECKING([for $compiler option to produce PIC])
+-AC_CACHE_VAL(lt_cv_prog_cc_pic,
+-[ lt_cv_prog_cc_pic=
+- lt_cv_prog_cc_shlib=
+- lt_cv_prog_cc_wl=
+- lt_cv_prog_cc_static=
+- lt_cv_prog_cc_no_builtin=
+- lt_cv_prog_cc_can_build_shared=$can_build_shared
++case $host_os in
++aix3*)
++ version_type=linux
++ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
++ shlibpath_var=LIBPATH
+
+- if test "$GCC" = yes; then
+- lt_cv_prog_cc_wl='-Wl,'
+- lt_cv_prog_cc_static='-static'
++ # AIX 3 has no versioning support, so we append a major version to the name.
++ soname_spec='${libname}${release}${shared_ext}$major'
++ ;;
+
+- case $host_os in
+- aix*)
+- # Below there is a dirty hack to force normal static linking with -ldl
+- # The problem is because libdl dynamically linked with both libc and
+- # libC (AIX C++ library), which obviously doesn't included in libraries
+- # list by gcc. This cause undefined symbols with -static flags.
+- # This hack allows C programs to be linked with "-static -ldl", but
+- # not sure about C++ programs.
+- lt_cv_prog_cc_static="$lt_cv_prog_cc_static ${lt_cv_prog_cc_wl}-lC"
+- ;;
+- amigaos*)
+- # FIXME: we need at least 68020 code to build shared libraries, but
+- # adding the `-m68020' flag to GCC prevents building anything better,
+- # like `-m68040'.
+- lt_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4'
+- ;;
+- beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+- # PIC is the default for these OSes.
+- ;;
+- darwin* | rhapsody*)
+- # PIC is the default on this platform
+- # Common symbols not allowed in MH_DYLIB files
+- lt_cv_prog_cc_pic='-fno-common'
+- ;;
+- cygwin* | mingw* | pw32* | os2*)
+- # This hack is so that the source file can tell whether it is being
+- # built for inclusion in a dll (and should export symbols for example).
+- lt_cv_prog_cc_pic='-DDLL_EXPORT'
+- ;;
+- sysv4*MP*)
+- if test -d /usr/nec; then
+- lt_cv_prog_cc_pic=-Kconform_pic
+- fi
+- ;;
+- *)
+- lt_cv_prog_cc_pic='-fPIC'
+- ;;
+- esac
++aix4* | aix5*)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ hardcode_into_libs=yes
++ if test "$host_cpu" = ia64; then
++ # AIX 5 supports IA64
++ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
++ shlibpath_var=LD_LIBRARY_PATH
+ else
+- # PORTME Check for PIC flags for the system compiler.
++ # With GCC up to 2.95.x, collect2 would create an import file
++ # for dependence libraries. The import file would start with
++ # the line `#! .'. This would cause the generated library to
++ # depend on `.', always an invalid library. This was fixed in
++ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+- aix3* | aix4* | aix5*)
+- lt_cv_prog_cc_wl='-Wl,'
+- # All AIX code is PIC.
+- if test "$host_cpu" = ia64; then
+- # AIX 5 now supports IA64 processor
+- lt_cv_prog_cc_static='-Bstatic'
++ aix4 | aix4.[[01]] | aix4.[[01]].*)
++ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
++ echo ' yes '
++ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
++ :
+ else
+- lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp'
++ can_build_shared=no
+ fi
+ ;;
++ esac
++ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
++ # soname into executable. Probably we can add versioning support to
++ # collect2, so additional links can be useful in future.
++ if test "$aix_use_runtimelinking" = yes; then
++ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
++ # instead of lib<name>.a to let people know that these are not
++ # typical AIX shared libraries.
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++ else
++ # We preserve .a as extension for shared libraries through AIX4.2
++ # and later when we are not doing run time linking.
++ library_names_spec='${libname}${release}.a $libname.a'
++ soname_spec='${libname}${release}${shared_ext}$major'
++ fi
++ shlibpath_var=LIBPATH
++ fi
++ ;;
+
+- hpux9* | hpux10* | hpux11*)
+- # Is there a better lt_cv_prog_cc_static that works with the bundled CC?
+- lt_cv_prog_cc_wl='-Wl,'
+- lt_cv_prog_cc_static="${lt_cv_prog_cc_wl}-a ${lt_cv_prog_cc_wl}archive"
+- lt_cv_prog_cc_pic='+Z'
+- ;;
+-
+- irix5* | irix6* | nonstopux*)
+- lt_cv_prog_cc_wl='-Wl,'
+- lt_cv_prog_cc_static='-non_shared'
+- # PIC (with -KPIC) is the default.
+- ;;
+-
+- cygwin* | mingw* | pw32* | os2*)
+- # This hack is so that the source file can tell whether it is being
+- # built for inclusion in a dll (and should export symbols for example).
+- lt_cv_prog_cc_pic='-DDLL_EXPORT'
+- ;;
+-
+- newsos6)
+- lt_cv_prog_cc_pic='-KPIC'
+- lt_cv_prog_cc_static='-Bstatic'
+- ;;
+-
+- osf3* | osf4* | osf5*)
+- # All OSF/1 code is PIC.
+- lt_cv_prog_cc_wl='-Wl,'
+- lt_cv_prog_cc_static='-non_shared'
+- ;;
++amigaos*)
++ library_names_spec='$libname.ixlibrary $libname.a'
++ # Create ${libname}_ixlibrary.a entries in /sys/libs.
++ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
++ ;;
+
+- sco3.2v5*)
+- lt_cv_prog_cc_pic='-Kpic'
+- lt_cv_prog_cc_static='-dn'
+- lt_cv_prog_cc_shlib='-belf'
+- ;;
++beos*)
++ library_names_spec='${libname}${shared_ext}'
++ dynamic_linker="$host_os ld.so"
++ shlibpath_var=LIBRARY_PATH
++ ;;
+
+- solaris*)
+- lt_cv_prog_cc_pic='-KPIC'
+- lt_cv_prog_cc_static='-Bstatic'
+- lt_cv_prog_cc_wl='-Wl,'
+- ;;
++bsdi4*)
++ version_type=linux
++ need_version=no
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++ soname_spec='${libname}${release}${shared_ext}$major'
++ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
++ shlibpath_var=LD_LIBRARY_PATH
++ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
++ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
++ # the default ld.so.conf also contains /usr/contrib/lib and
++ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
++ # libtool to hard-code these into programs
++ ;;
+
+- sunos4*)
+- lt_cv_prog_cc_pic='-PIC'
+- lt_cv_prog_cc_static='-Bstatic'
+- lt_cv_prog_cc_wl='-Qoption ld '
+- ;;
++cygwin* | mingw* | pw32*)
++ version_type=windows
++ shrext_cmds=".dll"
++ need_version=no
++ need_lib_prefix=no
+
+- sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+- lt_cv_prog_cc_pic='-KPIC'
+- lt_cv_prog_cc_static='-Bstatic'
+- lt_cv_prog_cc_wl='-Wl,'
+- ;;
++ case $GCC,$host_os in
++ yes,cygwin* | yes,mingw* | yes,pw32*)
++ library_names_spec='$libname.dll.a'
++ # DLL is installed to $(libdir)/../bin by postinstall_cmds
++ postinstall_cmds='base_file=`basename \${file}`~
++ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
++ dldir=$destdir/`dirname \$dlpath`~
++ test -d \$dldir || mkdir -p \$dldir~
++ $install_prog $dir/$dlname \$dldir/$dlname'
++ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
++ dlpath=$dir/\$dldll~
++ $rm \$dlpath'
++ shlibpath_overrides_runpath=yes
+
+- uts4*)
+- lt_cv_prog_cc_pic='-pic'
+- lt_cv_prog_cc_static='-Bstatic'
++ case $host_os in
++ cygwin*)
++ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
++ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
++ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+-
+- sysv4*MP*)
+- if test -d /usr/nec ;then
+- lt_cv_prog_cc_pic='-Kconform_pic'
+- lt_cv_prog_cc_static='-Bstatic'
++ mingw*)
++ # MinGW DLLs use traditional 'lib' prefix
++ soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
++ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
++ if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then
++ # It is most probably a Windows format PATH printed by
++ # mingw gcc, but we are running on Cygwin. Gcc prints its search
++ # path with ; separators, and with drive letters. We can handle the
++ # drive letters (cygwin fileutils understands them), so leave them,
++ # especially as we might pass files found there to a mingw objdump,
++ # which wouldn't understand a cygwinified path. Ahh.
++ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
++ else
++ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+-
+- *)
+- lt_cv_prog_cc_can_build_shared=no
++ pw32*)
++ # pw32 DLLs use 'pw' prefix rather than 'lib'
++ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+- fi
+-])
+-if test -z "$lt_cv_prog_cc_pic"; then
+- AC_MSG_RESULT([none])
+-else
+- AC_MSG_RESULT([$lt_cv_prog_cc_pic])
+-
+- # Check to make sure the pic_flag actually works.
+- AC_MSG_CHECKING([if $compiler PIC flag $lt_cv_prog_cc_pic works])
+- AC_CACHE_VAL(lt_cv_prog_cc_pic_works, [dnl
+- save_CFLAGS="$CFLAGS"
+- CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC"
+- AC_TRY_COMPILE([], [], [dnl
+- case $host_os in
+- hpux9* | hpux10* | hpux11*)
+- # On HP-UX, both CC and GCC only warn that PIC is supported... then
+- # they create non-PIC objects. So, if there were any warnings, we
+- # assume that PIC is not supported.
+- if test -s conftest.err; then
+- lt_cv_prog_cc_pic_works=no
+- else
+- lt_cv_prog_cc_pic_works=yes
+- fi
+- ;;
+- *)
+- lt_cv_prog_cc_pic_works=yes
+- ;;
+- esac
+- ], [dnl
+- lt_cv_prog_cc_pic_works=no
+- ])
+- CFLAGS="$save_CFLAGS"
+- ])
+-
+- if test "X$lt_cv_prog_cc_pic_works" = Xno; then
+- lt_cv_prog_cc_pic=
+- lt_cv_prog_cc_can_build_shared=no
+- else
+- lt_cv_prog_cc_pic=" $lt_cv_prog_cc_pic"
+- fi
+-
+- AC_MSG_RESULT([$lt_cv_prog_cc_pic_works])
+-fi
+-
+-# Check for any special shared library compilation flags.
+-if test -n "$lt_cv_prog_cc_shlib"; then
+- AC_MSG_WARN([\`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries])
+- if echo "$old_CC $old_CFLAGS " | egrep -e "[[ ]]$lt_cv_prog_cc_shlib[[ ]]" >/dev/null; then :
+- else
+- AC_MSG_WARN([add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure])
+- lt_cv_prog_cc_can_build_shared=no
+- fi
+-fi
+-
+-AC_MSG_CHECKING([if $compiler static flag $lt_cv_prog_cc_static works])
+-AC_CACHE_VAL([lt_cv_prog_cc_static_works], [dnl
+- lt_cv_prog_cc_static_works=no
+- save_LDFLAGS="$LDFLAGS"
+- LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static"
+- AC_TRY_LINK([], [], [lt_cv_prog_cc_static_works=yes])
+- LDFLAGS="$save_LDFLAGS"
+-])
+-
+-# Belt *and* braces to stop my trousers falling down:
+-test "X$lt_cv_prog_cc_static_works" = Xno && lt_cv_prog_cc_static=
+-AC_MSG_RESULT([$lt_cv_prog_cc_static_works])
+-
+-pic_flag="$lt_cv_prog_cc_pic"
+-special_shlib_compile_flags="$lt_cv_prog_cc_shlib"
+-wl="$lt_cv_prog_cc_wl"
+-link_static_flag="$lt_cv_prog_cc_static"
+-no_builtin_flag="$lt_cv_prog_cc_no_builtin"
+-can_build_shared="$lt_cv_prog_cc_can_build_shared"
+-
+-
+-# Check to see if options -o and -c are simultaneously supported by compiler
+-AC_MSG_CHECKING([if $compiler supports -c -o file.$ac_objext])
+-AC_CACHE_VAL([lt_cv_compiler_c_o], [
+-$rm -r conftest 2>/dev/null
+-mkdir conftest
+-cd conftest
+-echo "int some_variable = 0;" > conftest.$ac_ext
+-mkdir out
+-# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
+-# that will create temporary files in the current directory regardless of
+-# the output directory. Thus, making CWD read-only will cause this test
+-# to fail, enabling locking or at least warning the user not to do parallel
+-# builds.
+-chmod -w .
+-save_CFLAGS="$CFLAGS"
+-CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
+-compiler_c_o=no
+-if { (eval echo configure:__oline__: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+- # The compiler can only warn and ignore the option if not recognized
+- # So say no if there are warnings
+- if test -s out/conftest.err; then
+- lt_cv_compiler_c_o=no
+- else
+- lt_cv_compiler_c_o=yes
+- fi
+-else
+- # Append any errors to the config.log.
+- cat out/conftest.err 1>&AC_FD_CC
+- lt_cv_compiler_c_o=no
+-fi
+-CFLAGS="$save_CFLAGS"
+-chmod u+w .
+-$rm conftest* out/*
+-rmdir out
+-cd ..
+-rmdir conftest
+-$rm -r conftest 2>/dev/null
+-])
+-compiler_c_o=$lt_cv_compiler_c_o
+-AC_MSG_RESULT([$compiler_c_o])
+-
+-if test x"$compiler_c_o" = x"yes"; then
+- # Check to see if we can write to a .lo
+- AC_MSG_CHECKING([if $compiler supports -c -o file.lo])
+- AC_CACHE_VAL([lt_cv_compiler_o_lo], [
+- lt_cv_compiler_o_lo=no
+- save_CFLAGS="$CFLAGS"
+- CFLAGS="$CFLAGS -c -o conftest.lo"
+- save_objext="$ac_objext"
+- ac_objext=lo
+- AC_TRY_COMPILE([], [int some_variable = 0;], [dnl
+- # The compiler can only warn and ignore the option if not recognized
+- # So say no if there are warnings
+- if test -s conftest.err; then
+- lt_cv_compiler_o_lo=no
+- else
+- lt_cv_compiler_o_lo=yes
+- fi
+- ])
+- ac_objext="$save_objext"
+- CFLAGS="$save_CFLAGS"
+- ])
+- compiler_o_lo=$lt_cv_compiler_o_lo
+- AC_MSG_RESULT([$compiler_o_lo])
+-else
+- compiler_o_lo=no
+-fi
+-
+-# Check to see if we can do hard links to lock some files if needed
+-hard_links="nottested"
+-if test "$compiler_c_o" = no && test "$need_locks" != no; then
+- # do not overwrite the value of need_locks provided by the user
+- AC_MSG_CHECKING([if we can lock with hard links])
+- hard_links=yes
+- $rm conftest*
+- ln conftest.a conftest.b 2>/dev/null && hard_links=no
+- touch conftest.a
+- ln conftest.a conftest.b 2>&5 || hard_links=no
+- ln conftest.a conftest.b 2>/dev/null && hard_links=no
+- AC_MSG_RESULT([$hard_links])
+- if test "$hard_links" = no; then
+- AC_MSG_WARN([\`$CC' does not support \`-c -o', so \`make -j' may be unsafe])
+- need_locks=warn
+- fi
+-else
+- need_locks=no
+-fi
++ ;;
+
+-if test "$GCC" = yes; then
+- # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
+- AC_MSG_CHECKING([if $compiler supports -fno-rtti -fno-exceptions])
+- echo "int some_variable = 0;" > conftest.$ac_ext
+- save_CFLAGS="$CFLAGS"
+- CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext"
+- compiler_rtti_exceptions=no
+- AC_TRY_COMPILE([], [int some_variable = 0;], [dnl
+- # The compiler can only warn and ignore the option if not recognized
+- # So say no if there are warnings
+- if test -s conftest.err; then
+- compiler_rtti_exceptions=no
+- else
+- compiler_rtti_exceptions=yes
+- fi
+- ])
+- CFLAGS="$save_CFLAGS"
+- AC_MSG_RESULT([$compiler_rtti_exceptions])
++ *)
++ library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
++ ;;
++ esac
++ dynamic_linker='Win32 ld.exe'
++ # FIXME: first we should search . and the directory the executable is in
++ shlibpath_var=PATH
++ ;;
+
+- if test "$compiler_rtti_exceptions" = "yes"; then
+- no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
++darwin* | rhapsody*)
++ dynamic_linker="$host_os dyld"
++ version_type=darwin
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
++ soname_spec='${libname}${release}${major}$shared_ext'
++ shlibpath_overrides_runpath=yes
++ shlibpath_var=DYLD_LIBRARY_PATH
++ shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)'
++ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
++ if test "$GCC" = yes; then
++ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+- no_builtin_flag=' -fno-builtin'
++ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+-fi
+-
+-# See if the linker supports building shared libraries.
+-AC_MSG_CHECKING([whether the linker ($LD) supports shared libraries])
+-
+-allow_undefined_flag=
+-no_undefined_flag=
+-need_lib_prefix=unknown
+-need_version=unknown
+-# when you set need_version to no, make sure it does not cause -set_version
+-# flags to be left without arguments
+-archive_cmds=
+-archive_expsym_cmds=
+-old_archive_from_new_cmds=
+-old_archive_from_expsyms_cmds=
+-export_dynamic_flag_spec=
+-whole_archive_flag_spec=
+-thread_safe_flag_spec=
+-hardcode_into_libs=no
+-hardcode_libdir_flag_spec=
+-hardcode_libdir_separator=
+-hardcode_direct=no
+-hardcode_minus_L=no
+-hardcode_shlibpath_var=unsupported
+-runpath_var=
+-link_all_deplibs=unknown
+-always_export_symbols=no
+-export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols'
+-# include_expsyms should be a list of space-separated symbols to be *always*
+-# included in the symbol list
+-include_expsyms=
+-# exclude_expsyms can be an egrep regular expression of symbols to exclude
+-# it will be wrapped by ` (' and `)$', so one must not match beginning or
+-# end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+-# as well as any symbol that contains `d'.
+-exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+-# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+-# platforms (ab)use it in PIC code, but their linkers get confused if
+-# the symbol is explicitly referenced. Since portable code cannot
+-# rely on this symbol name, it's probably fine to never include it in
+-# preloaded symbol tables.
+-extract_expsyms_cmds=
++ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
++ ;;
+
+-case $host_os in
+-cygwin* | mingw* | pw32*)
+- # FIXME: the MSVC++ port hasn't been tested in a loooong time
+- # When not using gcc, we currently assume that we are using
+- # Microsoft Visual C++.
+- if test "$GCC" != yes; then
+- with_gnu_ld=no
+- fi
++dgux*)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
++ soname_spec='${libname}${release}${shared_ext}$major'
++ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+-openbsd*)
+- with_gnu_ld=no
++
++freebsd1*)
++ dynamic_linker=no
+ ;;
+-esac
+
+-ld_shlibs=yes
+-if test "$with_gnu_ld" = yes; then
+- # If archive_cmds runs LD, not CC, wlarc should be empty
+- wlarc='${wl}'
++kfreebsd*-gnu)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
++ soname_spec='${libname}${release}${shared_ext}$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ hardcode_into_libs=yes
++ dynamic_linker='GNU ld.so'
++ ;;
+
+- # See if GNU ld supports shared libraries.
++freebsd*)
++ objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
++ version_type=freebsd-$objformat
++ case $version_type in
++ freebsd-elf*)
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
++ need_version=no
++ need_lib_prefix=no
++ ;;
++ freebsd-*)
++ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
++ need_version=yes
++ ;;
++ esac
++ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+- aix3* | aix4* | aix5*)
+- # On AIX, the GNU linker is very broken
+- # Note:Check GNU linker on AIX 5-IA64 when/if it becomes available.
+- ld_shlibs=no
+- cat <<EOF 1>&2
+-
+-*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+-*** to be unable to reliably create shared libraries on AIX.
+-*** Therefore, libtool is disabling shared libraries support. If you
+-*** really care for shared libraries, you may want to modify your PATH
+-*** so that a non-GNU linker is found, and then restart.
+-
+-EOF
++ freebsd2*)
++ shlibpath_overrides_runpath=yes
+ ;;
+-
+- amigaos*)
+- archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+- hardcode_libdir_flag_spec='-L$libdir'
+- hardcode_minus_L=yes
+-
+- # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+- # that the semantics of dynamic libraries on AmigaOS, at least up
+- # to version 4, is to share data among multiple programs linked
+- # with the same dynamic library. Since this doesn't match the
+- # behavior of shared libraries on other platforms, we can use
+- # them.
+- ld_shlibs=no
++ freebsd3.[01]* | freebsdelf3.[01]*)
++ shlibpath_overrides_runpath=yes
++ hardcode_into_libs=yes
+ ;;
+-
+- beos*)
+- if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+- allow_undefined_flag=unsupported
+- # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+- # support --undefined. This deserves some investigation. FIXME
+- archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+- else
+- ld_shlibs=no
+- fi
++ *) # from 3.2 on
++ shlibpath_overrides_runpath=no
++ hardcode_into_libs=yes
+ ;;
++ esac
++ ;;
+
+- cygwin* | mingw* | pw32*)
+- # hardcode_libdir_flag_spec is actually meaningless, as there is
+- # no search path for DLLs.
+- hardcode_libdir_flag_spec='-L$libdir'
+- allow_undefined_flag=unsupported
+- always_export_symbols=yes
+-
+- extract_expsyms_cmds='test -f $output_objdir/impgen.c || \
+- sed -e "/^# \/\* impgen\.c starts here \*\//,/^# \/\* impgen.c ends here \*\// { s/^# //;s/^# *$//; p; }" -e d < $''0 > $output_objdir/impgen.c~
+- test -f $output_objdir/impgen.exe || (cd $output_objdir && \
+- if test "x$HOST_CC" != "x" ; then $HOST_CC -o impgen impgen.c ; \
+- else $CC -o impgen impgen.c ; fi)~
+- $output_objdir/impgen $dir/$soroot > $output_objdir/$soname-def'
+-
+- old_archive_from_expsyms_cmds='$DLLTOOL --as=$AS --dllname $soname --def $output_objdir/$soname-def --output-lib $output_objdir/$newlib'
+-
+- # cygwin and mingw dlls have different entry points and sets of symbols
+- # to exclude.
+- # FIXME: what about values for MSVC?
+- dll_entry=__cygwin_dll_entry@12
+- dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12~
+- case $host_os in
+- mingw*)
+- # mingw values
+- dll_entry=_DllMainCRTStartup@12
+- dll_exclude_symbols=DllMain@12,DllMainCRTStartup@12,DllEntryPoint@12~
+- ;;
+- esac
+-
+- # mingw and cygwin differ, and it's simplest to just exclude the union
+- # of the two symbol sets.
+- dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12
+-
+- # recent cygwin and mingw systems supply a stub DllMain which the user
+- # can override, but on older systems we have to supply one (in ltdll.c)
+- if test "x$lt_cv_need_dllmain" = "xyes"; then
+- ltdll_obj='$output_objdir/$soname-ltdll.'"$ac_objext "
+- ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $''0 > $output_objdir/$soname-ltdll.c~
+- test -f $output_objdir/$soname-ltdll.$ac_objext || (cd $output_objdir && $CC -c $soname-ltdll.c)~'
+- else
+- ltdll_obj=
+- ltdll_cmds=
+- fi
+-
+- # Extract the symbol export list from an `--export-all' def file,
+- # then regenerate the def file from the symbol export list, so that
+- # the compiled dll only exports the symbol export list.
+- # Be careful not to strip the DATA tag left be newer dlltools.
+- export_symbols_cmds="$ltdll_cmds"'
+- $DLLTOOL --export-all --exclude-symbols '$dll_exclude_symbols' --output-def $output_objdir/$soname-def '$ltdll_obj'$libobjs $convenience~
+- sed -e "1,/EXPORTS/d" -e "s/ @ [[0-9]]*//" -e "s/ *;.*$//" < $output_objdir/$soname-def > $export_symbols'
+-
+- # If the export-symbols file already is a .def file (1st line
+- # is EXPORTS), use it as is.
+- # If DATA tags from a recent dlltool are present, honour them!
+- archive_expsym_cmds='if test "x`sed 1q $export_symbols`" = xEXPORTS; then
+- cp $export_symbols $output_objdir/$soname-def;
+- else
+- echo EXPORTS > $output_objdir/$soname-def;
+- _lt_hint=1;
+- cat $export_symbols | while read symbol; do
+- set dummy \$symbol;
+- case \[$]# in
+- 2) echo " \[$]2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;;
+- 4) echo " \[$]2 \[$]3 \[$]4 ; " >> $output_objdir/$soname-def; _lt_hint=`expr \$_lt_hint - 1`;;
+- *) echo " \[$]2 @ \$_lt_hint \[$]3 ; " >> $output_objdir/$soname-def;;
+- esac;
+- _lt_hint=`expr 1 + \$_lt_hint`;
+- done;
+- fi~
+- '"$ltdll_cmds"'
+- $CC -Wl,--base-file,$output_objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~
+- $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp~
+- $CC -Wl,--base-file,$output_objdir/$soname-base $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~
+- $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp --output-lib $output_objdir/$libname.dll.a~
+- $CC $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags'
++gnu*)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
++ soname_spec='${libname}${release}${shared_ext}$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ hardcode_into_libs=yes
++ ;;
++
++hpux9* | hpux10* | hpux11*)
++ # Give a soname corresponding to the major version so that dld.sl refuses to
++ # link against other versions.
++ version_type=sunos
++ need_lib_prefix=no
++ need_version=no
++ case "$host_cpu" in
++ ia64*)
++ shrext_cmds='.so'
++ hardcode_into_libs=yes
++ dynamic_linker="$host_os dld.so"
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++ soname_spec='${libname}${release}${shared_ext}$major'
++ if test "X$HPUX_IA64_MODE" = X32; then
++ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
++ else
++ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
++ fi
++ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++ ;;
++ hppa*64*)
++ shrext_cmds='.sl'
++ hardcode_into_libs=yes
++ dynamic_linker="$host_os dld.sl"
++ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
++ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++ soname_spec='${libname}${release}${shared_ext}$major'
++ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
++ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++ ;;
++ *)
++ shrext_cmds='.sl'
++ dynamic_linker="$host_os dld.sl"
++ shlibpath_var=SHLIB_PATH
++ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++ soname_spec='${libname}${release}${shared_ext}$major'
++ ;;
++ esac
++ # HP-UX runs *really* slowly unless shared libraries are mode 555.
++ postinstall_cmds='chmod 555 $lib'
++ ;;
++
++irix5* | irix6* | nonstopux*)
++ case $host_os in
++ nonstopux*) version_type=nonstopux ;;
++ *)
++ if test "$lt_cv_prog_gnu_ld" = yes; then
++ version_type=linux
++ else
++ version_type=irix
++ fi ;;
++ esac
++ need_lib_prefix=no
++ need_version=no
++ soname_spec='${libname}${release}${shared_ext}$major'
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
++ case $host_os in
++ irix5* | nonstopux*)
++ libsuff= shlibsuff=
++ ;;
++ *)
++ case $LD in # libtool.m4 will add one of these switches to LD
++ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
++ libsuff= shlibsuff= libmagic=32-bit;;
++ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
++ libsuff=32 shlibsuff=N32 libmagic=N32;;
++ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
++ libsuff=64 shlibsuff=64 libmagic=64-bit;;
++ *) libsuff= shlibsuff= libmagic=never-match;;
++ esac
++ ;;
++ esac
++ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
++ shlibpath_overrides_runpath=no
++ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
++ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
++ hardcode_into_libs=yes
++ ;;
++
++# No shared lib support for Linux oldld, aout, or coff.
++linux*oldld* | linux*aout* | linux*coff*)
++ dynamic_linker=no
++ ;;
++
++# This must be Linux ELF.
++linux*)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++ soname_spec='${libname}${release}${shared_ext}$major'
++ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ # This implies no fast_install, which is unacceptable.
++ # Some rework will be needed to allow for fast_install
++ # before this can be enabled.
++ hardcode_into_libs=yes
++
++ # Append ld.so.conf contents to the search path
++ if test -f /etc/ld.so.conf; then
++ lt_ld_extra=`$SED -e 's/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g' /etc/ld.so.conf | tr '\n' ' '`
++ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
++ fi
++
++ # We used to test for /lib/ld.so.1 and disable shared libraries on
++ # powerpc, because MkLinux only supported shared libraries with the
++ # GNU dynamic linker. Since this was broken with cross compilers,
++ # most powerpc-linux boxes support dynamic linking these days and
++ # people can always --disable-shared, the test was removed, and we
++ # assume the GNU/Linux dynamic linker is in use.
++ dynamic_linker='GNU/Linux ld.so'
++ ;;
++
++netbsdelf*-gnu)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
++ soname_spec='${libname}${release}${shared_ext}$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ hardcode_into_libs=yes
++ dynamic_linker='NetBSD ld.elf_so'
++ ;;
++
++knetbsd*-gnu)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
++ soname_spec='${libname}${release}${shared_ext}$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ hardcode_into_libs=yes
++ dynamic_linker='GNU ld.so'
++ ;;
++
++netbsd*)
++ version_type=sunos
++ need_lib_prefix=no
++ need_version=no
++ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
++ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
++ dynamic_linker='NetBSD (a.out) ld.so'
++ else
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
++ soname_spec='${libname}${release}${shared_ext}$major'
++ dynamic_linker='NetBSD ld.elf_so'
++ fi
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=yes
++ hardcode_into_libs=yes
++ ;;
++
++newsos6)
++ version_type=linux
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=yes
++ ;;
++
++nto-qnx*)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++ soname_spec='${libname}${release}${shared_ext}$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=yes
++ ;;
++
++openbsd*)
++ version_type=sunos
++ need_lib_prefix=no
++ need_version=yes
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
++ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
++ shlibpath_var=LD_LIBRARY_PATH
++ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
++ case $host_os in
++ openbsd2.[[89]] | openbsd2.[[89]].*)
++ shlibpath_overrides_runpath=no
++ ;;
++ *)
++ shlibpath_overrides_runpath=yes
++ ;;
++ esac
++ else
++ shlibpath_overrides_runpath=yes
++ fi
++ ;;
++
++os2*)
++ libname_spec='$name'
++ shrext_cmds=".dll"
++ need_lib_prefix=no
++ library_names_spec='$libname${shared_ext} $libname.a'
++ dynamic_linker='OS/2 ld.exe'
++ shlibpath_var=LIBPATH
++ ;;
++
++osf3* | osf4* | osf5*)
++ version_type=osf
++ need_lib_prefix=no
++ need_version=no
++ soname_spec='${libname}${release}${shared_ext}$major'
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++ shlibpath_var=LD_LIBRARY_PATH
++ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
++ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
++ ;;
++
++sco3.2v5*)
++ version_type=osf
++ soname_spec='${libname}${release}${shared_ext}$major'
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++ shlibpath_var=LD_LIBRARY_PATH
++ ;;
++
++solaris*)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++ soname_spec='${libname}${release}${shared_ext}$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=yes
++ hardcode_into_libs=yes
++ # ldd complains unless libraries are executable
++ postinstall_cmds='chmod +x $lib'
++ ;;
++
++sunos4*)
++ version_type=sunos
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
++ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=yes
++ if test "$with_gnu_ld" = yes; then
++ need_lib_prefix=no
++ fi
++ need_version=yes
++ ;;
++
++sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
++ version_type=linux
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++ soname_spec='${libname}${release}${shared_ext}$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ case $host_vendor in
++ sni)
++ shlibpath_overrides_runpath=no
++ need_lib_prefix=no
++ export_dynamic_flag_spec='${wl}-Blargedynsym'
++ runpath_var=LD_RUN_PATH
++ ;;
++ siemens)
++ need_lib_prefix=no
++ ;;
++ motorola)
++ need_lib_prefix=no
++ need_version=no
++ shlibpath_overrides_runpath=no
++ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
++ ;;
++ esac
++ ;;
++
++sysv4*MP*)
++ if test -d /usr/nec ;then
++ version_type=linux
++ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
++ soname_spec='$libname${shared_ext}.$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ fi
++ ;;
++
++uts4*)
++ version_type=linux
++ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++ soname_spec='${libname}${release}${shared_ext}$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ ;;
++
++*)
++ dynamic_linker=no
++ ;;
++esac
++AC_MSG_RESULT([$dynamic_linker])
++test "$dynamic_linker" = no && can_build_shared=no
++])# AC_LIBTOOL_SYS_DYNAMIC_LINKER
++
++
++# _LT_AC_TAGCONFIG
++# ----------------
++AC_DEFUN([_LT_AC_TAGCONFIG],
++[AC_ARG_WITH([tags],
++ [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@],
++ [include additional configurations @<:@automatic@:>@])],
++ [tagnames="$withval"])
++
++if test -f "$ltmain" && test -n "$tagnames"; then
++ if test ! -f "${ofile}"; then
++ AC_MSG_WARN([output file `$ofile' does not exist])
++ fi
++
++ if test -z "$LTCC"; then
++ eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
++ if test -z "$LTCC"; then
++ AC_MSG_WARN([output file `$ofile' does not look like a libtool script])
++ else
++ AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile'])
++ fi
++ fi
++
++ # Extract list of available tagged configurations in $ofile.
++ # Note that this assumes the entire list is on one line.
++ available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
++
++ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
++ for tagname in $tagnames; do
++ IFS="$lt_save_ifs"
++ # Check whether tagname contains only valid characters
++ case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in
++ "") ;;
++ *) AC_MSG_ERROR([invalid tag name: $tagname])
++ ;;
++ esac
++
++ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
++ then
++ AC_MSG_ERROR([tag name \"$tagname\" already exists])
++ fi
++
++ # Update the list of available tags.
++ if test -n "$tagname"; then
++ echo appending configuration tag \"$tagname\" to $ofile
++
++ case $tagname in
++ CXX)
++ if test -n "$CXX" && test "X$CXX" != "Xno"; then
++ AC_LIBTOOL_LANG_CXX_CONFIG
++ else
++ tagname=""
++ fi
++ ;;
++
++ F77)
++ if test -n "$F77" && test "X$F77" != "Xno"; then
++ AC_LIBTOOL_LANG_F77_CONFIG
++ else
++ tagname=""
++ fi
++ ;;
++
++ GCJ)
++ if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
++ AC_LIBTOOL_LANG_GCJ_CONFIG
++ else
++ tagname=""
++ fi
++ ;;
++
++ RC)
++ AC_LIBTOOL_LANG_RC_CONFIG
++ ;;
++
++ *)
++ AC_MSG_ERROR([Unsupported tag name: $tagname])
++ ;;
++ esac
++
++ # Append the new tag name to the list of available tags.
++ if test -n "$tagname" ; then
++ available_tags="$available_tags $tagname"
++ fi
++ fi
++ done
++ IFS="$lt_save_ifs"
++
++ # Now substitute the updated list of available tags.
++ if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
++ mv "${ofile}T" "$ofile"
++ chmod +x "$ofile"
++ else
++ rm -f "${ofile}T"
++ AC_MSG_ERROR([unable to update list of available tagged configurations.])
++ fi
++fi
++])# _LT_AC_TAGCONFIG
++
++
++# AC_LIBTOOL_DLOPEN
++# -----------------
++# enable checks for dlopen support
++AC_DEFUN([AC_LIBTOOL_DLOPEN],
++ [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])
++])# AC_LIBTOOL_DLOPEN
++
++
++# AC_LIBTOOL_WIN32_DLL
++# --------------------
++# declare package support for building win32 dll's
++AC_DEFUN([AC_LIBTOOL_WIN32_DLL],
++[AC_BEFORE([$0], [AC_LIBTOOL_SETUP])
++])# AC_LIBTOOL_WIN32_DLL
++
++
++# AC_ENABLE_SHARED([DEFAULT])
++# ---------------------------
++# implement the --enable-shared flag
++# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
++AC_DEFUN([AC_ENABLE_SHARED],
++[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
++AC_ARG_ENABLE([shared],
++ [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
++ [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])],
++ [p=${PACKAGE-default}
++ case $enableval in
++ yes) enable_shared=yes ;;
++ no) enable_shared=no ;;
++ *)
++ enable_shared=no
++ # Look at the argument we got. We use all the common list separators.
++ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
++ for pkg in $enableval; do
++ IFS="$lt_save_ifs"
++ if test "X$pkg" = "X$p"; then
++ enable_shared=yes
++ fi
++ done
++ IFS="$lt_save_ifs"
++ ;;
++ esac],
++ [enable_shared=]AC_ENABLE_SHARED_DEFAULT)
++])# AC_ENABLE_SHARED
++
++
++# AC_DISABLE_SHARED
++# -----------------
++#- set the default shared flag to --disable-shared
++AC_DEFUN([AC_DISABLE_SHARED],
++[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
++AC_ENABLE_SHARED(no)
++])# AC_DISABLE_SHARED
++
++
++# AC_ENABLE_STATIC([DEFAULT])
++# ---------------------------
++# implement the --enable-static flag
++# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
++AC_DEFUN([AC_ENABLE_STATIC],
++[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
++AC_ARG_ENABLE([static],
++ [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@],
++ [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])],
++ [p=${PACKAGE-default}
++ case $enableval in
++ yes) enable_static=yes ;;
++ no) enable_static=no ;;
++ *)
++ enable_static=no
++ # Look at the argument we got. We use all the common list separators.
++ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
++ for pkg in $enableval; do
++ IFS="$lt_save_ifs"
++ if test "X$pkg" = "X$p"; then
++ enable_static=yes
++ fi
++ done
++ IFS="$lt_save_ifs"
++ ;;
++ esac],
++ [enable_static=]AC_ENABLE_STATIC_DEFAULT)
++])# AC_ENABLE_STATIC
++
++
++# AC_DISABLE_STATIC
++# -----------------
++# set the default static flag to --disable-static
++AC_DEFUN([AC_DISABLE_STATIC],
++[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
++AC_ENABLE_STATIC(no)
++])# AC_DISABLE_STATIC
++
++
++# AC_ENABLE_FAST_INSTALL([DEFAULT])
++# ---------------------------------
++# implement the --enable-fast-install flag
++# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
++AC_DEFUN([AC_ENABLE_FAST_INSTALL],
++[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
++AC_ARG_ENABLE([fast-install],
++ [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
++ [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
++ [p=${PACKAGE-default}
++ case $enableval in
++ yes) enable_fast_install=yes ;;
++ no) enable_fast_install=no ;;
++ *)
++ enable_fast_install=no
++ # Look at the argument we got. We use all the common list separators.
++ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
++ for pkg in $enableval; do
++ IFS="$lt_save_ifs"
++ if test "X$pkg" = "X$p"; then
++ enable_fast_install=yes
++ fi
++ done
++ IFS="$lt_save_ifs"
++ ;;
++ esac],
++ [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT)
++])# AC_ENABLE_FAST_INSTALL
++
++
++# AC_DISABLE_FAST_INSTALL
++# -----------------------
++# set the default to --disable-fast-install
++AC_DEFUN([AC_DISABLE_FAST_INSTALL],
++[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
++AC_ENABLE_FAST_INSTALL(no)
++])# AC_DISABLE_FAST_INSTALL
++
++
++# AC_LIBTOOL_PICMODE([MODE])
++# --------------------------
++# implement the --with-pic flag
++# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
++AC_DEFUN([AC_LIBTOOL_PICMODE],
++[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
++pic_mode=ifelse($#,1,$1,default)
++])# AC_LIBTOOL_PICMODE
++
++
++# AC_PROG_EGREP
++# -------------
++# This is predefined starting with Autoconf 2.54, so this conditional
++# definition can be removed once we require Autoconf 2.54 or later.
++m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP],
++[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep],
++ [if echo a | (grep -E '(a|b)') >/dev/null 2>&1
++ then ac_cv_prog_egrep='grep -E'
++ else ac_cv_prog_egrep='egrep'
++ fi])
++ EGREP=$ac_cv_prog_egrep
++ AC_SUBST([EGREP])
++])])
++
++
++# AC_PATH_TOOL_PREFIX
++# -------------------
++# find a file program which can recognise shared library
++AC_DEFUN([AC_PATH_TOOL_PREFIX],
++[AC_REQUIRE([AC_PROG_EGREP])dnl
++AC_MSG_CHECKING([for $1])
++AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
++[case $MAGIC_CMD in
++[[\\/*] | ?:[\\/]*])
++ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
++ ;;
++*)
++ lt_save_MAGIC_CMD="$MAGIC_CMD"
++ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
++dnl $ac_dummy forces splitting on constant user-supplied paths.
++dnl POSIX.2 word splitting is done only on the output of word expansions,
++dnl not every word. This closes a longstanding sh security hole.
++ ac_dummy="ifelse([$2], , $PATH, [$2])"
++ for ac_dir in $ac_dummy; do
++ IFS="$lt_save_ifs"
++ test -z "$ac_dir" && ac_dir=.
++ if test -f $ac_dir/$1; then
++ lt_cv_path_MAGIC_CMD="$ac_dir/$1"
++ if test -n "$file_magic_test_file"; then
++ case $deplibs_check_method in
++ "file_magic "*)
++ file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
++ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
++ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
++ $EGREP "$file_magic_regex" > /dev/null; then
++ :
++ else
++ cat <<EOF 1>&2
++
++*** Warning: the command libtool uses to detect shared libraries,
++*** $file_magic_cmd, produces output that libtool cannot recognize.
++*** The result is that libtool may fail to recognize shared libraries
++*** as such. This will affect the creation of libtool libraries that
++*** depend on shared libraries, but programs linked with such libtool
++*** libraries will work regardless of this problem. Nevertheless, you
++*** may want to report the problem to your system manager and/or to
++*** bug-libtool@gnu.org
++
++EOF
++ fi ;;
++ esac
++ fi
++ break
++ fi
++ done
++ IFS="$lt_save_ifs"
++ MAGIC_CMD="$lt_save_MAGIC_CMD"
++ ;;
++esac])
++MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
++if test -n "$MAGIC_CMD"; then
++ AC_MSG_RESULT($MAGIC_CMD)
++else
++ AC_MSG_RESULT(no)
++fi
++])# AC_PATH_TOOL_PREFIX
++
++
++# AC_PATH_MAGIC
++# -------------
++# find a file program which can recognise a shared library
++AC_DEFUN([AC_PATH_MAGIC],
++[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
++if test -z "$lt_cv_path_MAGIC_CMD"; then
++ if test -n "$ac_tool_prefix"; then
++ AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
++ else
++ MAGIC_CMD=:
++ fi
++fi
++])# AC_PATH_MAGIC
++
++
++# AC_PROG_LD
++# ----------
++# find the pathname to the GNU or non-GNU linker
++AC_DEFUN([AC_PROG_LD],
++[AC_ARG_WITH([gnu-ld],
++ [AC_HELP_STRING([--with-gnu-ld],
++ [assume the C compiler uses GNU ld @<:@default=no@:>@])],
++ [test "$withval" = no || with_gnu_ld=yes],
++ [with_gnu_ld=no])
++AC_REQUIRE([LT_AC_PROG_SED])dnl
++AC_REQUIRE([AC_PROG_CC])dnl
++AC_REQUIRE([AC_CANONICAL_HOST])dnl
++AC_REQUIRE([AC_CANONICAL_BUILD])dnl
++ac_prog=ld
++if test "$GCC" = yes; then
++ # Check if gcc -print-prog-name=ld gives a path.
++ AC_MSG_CHECKING([for ld used by $CC])
++ case $host in
++ *-*-mingw*)
++ # gcc leaves a trailing carriage return which upsets mingw
++ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
++ *)
++ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
++ esac
++ case $ac_prog in
++ # Accept absolute paths.
++ [[\\/]]* | ?:[[\\/]]*)
++ re_direlt='/[[^/]][[^/]]*/\.\./'
++ # Canonicalize the pathname of ld
++ ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
++ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
++ ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
++ done
++ test -z "$LD" && LD="$ac_prog"
++ ;;
++ "")
++ # If it fails, then pretend we aren't using GCC.
++ ac_prog=ld
++ ;;
++ *)
++ # If it is relative, then search for the first ld in PATH.
++ with_gnu_ld=unknown
++ ;;
++ esac
++elif test "$with_gnu_ld" = yes; then
++ AC_MSG_CHECKING([for GNU ld])
++else
++ AC_MSG_CHECKING([for non-GNU ld])
++fi
++AC_CACHE_VAL(lt_cv_path_LD,
++[if test -z "$LD"; then
++ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
++ for ac_dir in $PATH; do
++ IFS="$lt_save_ifs"
++ test -z "$ac_dir" && ac_dir=.
++ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
++ lt_cv_path_LD="$ac_dir/$ac_prog"
++ # Check to see if the program is GNU ld. I'd rather use --version,
++ # but apparently some GNU ld's only accept -v.
++ # Break only if it was the GNU/non-GNU ld that we prefer.
++ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
++ *GNU* | *'with BFD'*)
++ test "$with_gnu_ld" != no && break
++ ;;
++ *)
++ test "$with_gnu_ld" != yes && break
++ ;;
++ esac
++ fi
++ done
++ IFS="$lt_save_ifs"
++else
++ lt_cv_path_LD="$LD" # Let the user override the test with a path.
++fi])
++LD="$lt_cv_path_LD"
++if test -n "$LD"; then
++ AC_MSG_RESULT($LD)
++else
++ AC_MSG_RESULT(no)
++fi
++test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
++AC_PROG_LD_GNU
++])# AC_PROG_LD
++
++
++# AC_PROG_LD_GNU
++# --------------
++AC_DEFUN([AC_PROG_LD_GNU],
++[AC_REQUIRE([AC_PROG_EGREP])dnl
++AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
++[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
++case `$LD -v 2>&1 </dev/null` in
++*GNU* | *'with BFD'*)
++ lt_cv_prog_gnu_ld=yes
++ ;;
++*)
++ lt_cv_prog_gnu_ld=no
++ ;;
++esac])
++with_gnu_ld=$lt_cv_prog_gnu_ld
++])# AC_PROG_LD_GNU
++
++
++# AC_PROG_LD_RELOAD_FLAG
++# ----------------------
++# find reload flag for linker
++# -- PORTME Some linkers may need a different reload flag.
++AC_DEFUN([AC_PROG_LD_RELOAD_FLAG],
++[AC_CACHE_CHECK([for $LD option to reload object files],
++ lt_cv_ld_reload_flag,
++ [lt_cv_ld_reload_flag='-r'])
++reload_flag=$lt_cv_ld_reload_flag
++case $reload_flag in
++"" | " "*) ;;
++*) reload_flag=" $reload_flag" ;;
++esac
++reload_cmds='$LD$reload_flag -o $output$reload_objs'
++])# AC_PROG_LD_RELOAD_FLAG
++
++
++# AC_DEPLIBS_CHECK_METHOD
++# -----------------------
++# how to check for library dependencies
++# -- PORTME fill in with the dynamic library characteristics
++AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
++[AC_CACHE_CHECK([how to recognise dependent libraries],
++lt_cv_deplibs_check_method,
++[lt_cv_file_magic_cmd='$MAGIC_CMD'
++lt_cv_file_magic_test_file=
++lt_cv_deplibs_check_method='unknown'
++# Need to set the preceding variable on all platforms that support
++# interlibrary dependencies.
++# 'none' -- dependencies not supported.
++# `unknown' -- same as none, but documents that we really don't know.
++# 'pass_all' -- all dependencies passed with no checks.
++# 'test_compile' -- check by making test program.
++# 'file_magic [[regex]]' -- check by looking for files in library path
++# which responds to the $file_magic_cmd with a given extended regex.
++# If you have `file' or equivalent on your system and you're not sure
++# whether `pass_all' will *always* work, you probably want this one.
++
++case $host_os in
++aix4* | aix5*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++beos*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++bsdi4*)
++ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
++ lt_cv_file_magic_cmd='/usr/bin/file -L'
++ lt_cv_file_magic_test_file=/shlib/libc.so
++ ;;
++
++cygwin*)
++ # func_win32_libid is a shell function defined in ltmain.sh
++ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
++ lt_cv_file_magic_cmd='func_win32_libid'
++ ;;
++
++mingw* | pw32*)
++ # Base MSYS/MinGW do not provide the 'file' command needed by
++ # func_win32_libid shell function, so use a weaker test based on 'objdump'.
++ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
++ lt_cv_file_magic_cmd='$OBJDUMP -f'
++ ;;
++
++darwin* | rhapsody*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++freebsd* | kfreebsd*-gnu)
++ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
++ case $host_cpu in
++ i*86 )
++ # Not sure whether the presence of OpenBSD here was a mistake.
++ # Let's accept both of them until this is cleared up.
++ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library'
++ lt_cv_file_magic_cmd=/usr/bin/file
++ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
++ ;;
++ esac
++ else
++ lt_cv_deplibs_check_method=pass_all
++ fi
++ ;;
++
++gnu*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++hpux10.20* | hpux11*)
++ lt_cv_file_magic_cmd=/usr/bin/file
++ case "$host_cpu" in
++ ia64*)
++ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
++ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
++ ;;
++ hppa*64*)
++ [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
++ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
++ ;;
++ *)
++ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
++ lt_cv_file_magic_test_file=/usr/lib/libc.sl
++ ;;
++ esac
++ ;;
++
++irix5* | irix6* | nonstopux*)
++ case $LD in
++ *-32|*"-32 ") libmagic=32-bit;;
++ *-n32|*"-n32 ") libmagic=N32;;
++ *-64|*"-64 ") libmagic=64-bit;;
++ *) libmagic=never-match;;
++ esac
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++# This must be Linux ELF.
++linux*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
++ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
++ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
++ else
++ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
++ fi
++ ;;
++
++newos6*)
++ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
++ lt_cv_file_magic_cmd=/usr/bin/file
++ lt_cv_file_magic_test_file=/usr/lib/libnls.so
++ ;;
++
++nto-qnx*)
++ lt_cv_deplibs_check_method=unknown
++ ;;
++
++openbsd*)
++ lt_cv_file_magic_cmd=/usr/bin/file
++ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
++ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
++ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object'
++ else
++ lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library'
++ fi
++ ;;
++
++osf3* | osf4* | osf5*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++sco3.2v5*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++solaris*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
++ case $host_vendor in
++ motorola)
++ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
++ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
++ ;;
++ ncr)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++ sequent)
++ lt_cv_file_magic_cmd='/bin/file'
++ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
++ ;;
++ sni)
++ lt_cv_file_magic_cmd='/bin/file'
++ lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
++ lt_cv_file_magic_test_file=/lib/libc.so
++ ;;
++ siemens)
++ lt_cv_deplibs_check_method=pass_all
+ ;;
++ esac
++ ;;
++
++sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7* | sysv4*uw2*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++esac
++])
++file_magic_cmd=$lt_cv_file_magic_cmd
++deplibs_check_method=$lt_cv_deplibs_check_method
++test -z "$deplibs_check_method" && deplibs_check_method=unknown
++])# AC_DEPLIBS_CHECK_METHOD
+
+- netbsd*)
+- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+- archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+- wlarc=
+- else
+- archive_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+- archive_expsym_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
++
++# AC_PROG_NM
++# ----------
++# find the pathname to a BSD-compatible name lister
++AC_DEFUN([AC_PROG_NM],
++[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM,
++[if test -n "$NM"; then
++ # Let the user override the test.
++ lt_cv_path_NM="$NM"
++else
++ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
++ for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
++ IFS="$lt_save_ifs"
++ test -z "$ac_dir" && ac_dir=.
++ tmp_nm="$ac_dir/${ac_tool_prefix}nm"
++ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
++ # Check to see if the nm accepts a BSD-compat flag.
++ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
++ # nm: unknown option "B" ignored
++ # Tru64's nm complains that /dev/null is an invalid object file
++ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
++ */dev/null* | *'Invalid file or object type'*)
++ lt_cv_path_NM="$tmp_nm -B"
++ break
++ ;;
++ *)
++ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
++ */dev/null*)
++ lt_cv_path_NM="$tmp_nm -p"
++ break
++ ;;
++ *)
++ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
++ continue # so that we can try to find one that supports BSD flags
++ ;;
++ esac
++ esac
+ fi
+- ;;
++ done
++ IFS="$lt_save_ifs"
++ test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
++fi])
++NM="$lt_cv_path_NM"
++])# AC_PROG_NM
+
+- solaris* | sysv5*)
+- if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
+- ld_shlibs=no
+- cat <<EOF 1>&2
+
+-*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+-*** create shared libraries on Solaris systems. Therefore, libtool
+-*** is disabling shared libraries support. We urge you to upgrade GNU
+-*** binutils to release 2.9.1 or newer. Another option is to modify
+-*** your PATH or compiler configuration so that the native linker is
+-*** used, and then restart.
++# AC_CHECK_LIBM
++# -------------
++# check for math library
++AC_DEFUN([AC_CHECK_LIBM],
++[AC_REQUIRE([AC_CANONICAL_HOST])dnl
++LIBM=
++case $host in
++*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
++ # These system don't have libm, or don't need it
++ ;;
++*-ncr-sysv4.3*)
++ AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
++ AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
++ ;;
++*)
++ AC_CHECK_LIB(m, cos, LIBM="-lm")
++ ;;
++esac
++])# AC_CHECK_LIBM
+
+-EOF
+- elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+- archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+- else
+- ld_shlibs=no
+- fi
+- ;;
+
+- sunos4*)
+- archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+- wlarc=
+- hardcode_direct=yes
+- hardcode_shlibpath_var=no
+- ;;
++# AC_LIBLTDL_CONVENIENCE([DIRECTORY])
++# -----------------------------------
++# sets LIBLTDL to the link flags for the libltdl convenience library and
++# LTDLINCL to the include flags for the libltdl header and adds
++# --enable-ltdl-convenience to the configure arguments. Note that LIBLTDL
++# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If
++# DIRECTORY is not provided, it is assumed to be `libltdl'. LIBLTDL will
++# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed with
++# '${top_srcdir}/' (note the single quotes!). If your package is not
++# flat and you're not using automake, define top_builddir and
++# top_srcdir appropriately in the Makefiles.
++AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
++[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
++ case $enable_ltdl_convenience in
++ no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
++ "") enable_ltdl_convenience=yes
++ ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
++ esac
++ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
++ LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
++ # For backwards non-gettext consistent compatibility...
++ INCLTDL="$LTDLINCL"
++])# AC_LIBLTDL_CONVENIENCE
+
+- *)
+- if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+- archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+- else
+- ld_shlibs=no
+- fi
++
++# AC_LIBLTDL_INSTALLABLE([DIRECTORY])
++# -----------------------------------
++# sets LIBLTDL to the link flags for the libltdl installable library and
++# LTDLINCL to the include flags for the libltdl header and adds
++# --enable-ltdl-install to the configure arguments. Note that LIBLTDL
++# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If
++# DIRECTORY is not provided and an installed libltdl is not found, it is
++# assumed to be `libltdl'. LIBLTDL will be prefixed with '${top_builddir}/'
++# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single
++# quotes!). If your package is not flat and you're not using automake,
++# define top_builddir and top_srcdir appropriately in the Makefiles.
++# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
++AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
++[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
++ AC_CHECK_LIB(ltdl, lt_dlinit,
++ [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
++ [if test x"$enable_ltdl_install" = xno; then
++ AC_MSG_WARN([libltdl not installed, but installation disabled])
++ else
++ enable_ltdl_install=yes
++ fi
++ ])
++ if test x"$enable_ltdl_install" = x"yes"; then
++ ac_configure_args="$ac_configure_args --enable-ltdl-install"
++ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
++ LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
++ else
++ ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
++ LIBLTDL="-lltdl"
++ LTDLINCL=
++ fi
++ # For backwards non-gettext consistent compatibility...
++ INCLTDL="$LTDLINCL"
++])# AC_LIBLTDL_INSTALLABLE
++
++
++# AC_LIBTOOL_CXX
++# --------------
++# enable support for C++ libraries
++AC_DEFUN([AC_LIBTOOL_CXX],
++[AC_REQUIRE([_LT_AC_LANG_CXX])
++])# AC_LIBTOOL_CXX
++
++
++# _LT_AC_LANG_CXX
++# ---------------
++AC_DEFUN([_LT_AC_LANG_CXX],
++[AC_REQUIRE([AC_PROG_CXX])
++AC_REQUIRE([AC_PROG_CXXCPP])
++_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX])
++])# _LT_AC_LANG_CXX
++
++
++# AC_LIBTOOL_F77
++# --------------
++# enable support for Fortran 77 libraries
++AC_DEFUN([AC_LIBTOOL_F77],
++[AC_REQUIRE([_LT_AC_LANG_F77])
++])# AC_LIBTOOL_F77
++
++
++# _LT_AC_LANG_F77
++# ---------------
++AC_DEFUN([_LT_AC_LANG_F77],
++[AC_REQUIRE([AC_PROG_F77])
++_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77])
++])# _LT_AC_LANG_F77
++
++
++# AC_LIBTOOL_GCJ
++# --------------
++# enable support for GCJ libraries
++AC_DEFUN([AC_LIBTOOL_GCJ],
++[AC_REQUIRE([_LT_AC_LANG_GCJ])
++])# AC_LIBTOOL_GCJ
++
++
++# _LT_AC_LANG_GCJ
++# ---------------
++AC_DEFUN([_LT_AC_LANG_GCJ],
++[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[],
++ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[],
++ [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[],
++ [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])],
++ [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])],
++ [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])])
++_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ])
++])# _LT_AC_LANG_GCJ
++
++
++# AC_LIBTOOL_RC
++# --------------
++# enable support for Windows resource files
++AC_DEFUN([AC_LIBTOOL_RC],
++[AC_REQUIRE([LT_AC_PROG_RC])
++_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC])
++])# AC_LIBTOOL_RC
++
++
++# AC_LIBTOOL_LANG_C_CONFIG
++# ------------------------
++# Ensure that the configuration vars for the C compiler are
++# suitably defined. Those variables are subsequently used by
++# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
++AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG])
++AC_DEFUN([_LT_AC_LANG_C_CONFIG],
++[lt_save_CC="$CC"
++AC_LANG_PUSH(C)
++
++# Source file extension for C test sources.
++ac_ext=c
++
++# Object file extension for compiled C test sources.
++objext=o
++_LT_AC_TAGVAR(objext, $1)=$objext
++
++# Code to be used in simple compile tests
++lt_simple_compile_test_code="int some_variable = 0;\n"
++
++# Code to be used in simple link tests
++lt_simple_link_test_code='int main(){return(0);}\n'
++
++_LT_AC_SYS_COMPILER
++
++#
++# Check for any special shared library compilation flags.
++#
++_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)=
++if test "$GCC" = no; then
++ case $host_os in
++ sco3.2v5*)
++ _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)='-belf'
+ ;;
+ esac
++fi
++if test -n "$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)"; then
++ AC_MSG_WARN([`$CC' requires `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to build shared libraries])
++ if echo "$old_CC $old_CFLAGS " | grep "[[ ]]$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)[[ ]]" >/dev/null; then :
++ else
++ AC_MSG_WARN([add `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to the CC or CFLAGS env variable and reconfigure])
++ _LT_AC_TAGVAR(lt_cv_prog_cc_can_build_shared, $1)=no
++ fi
++fi
+
+- if test "$ld_shlibs" = yes; then
+- runpath_var=LD_RUN_PATH
+- hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+- export_dynamic_flag_spec='${wl}--export-dynamic'
+- case $host_os in
+- cygwin* | mingw* | pw32*)
+- # dlltool doesn't understand --whole-archive et. al.
+- whole_archive_flag_spec=
++
++#
++# Check to make sure the static flag actually works.
++#
++AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $_LT_AC_TAGVAR(lt_prog_compiler_static, $1) works],
++ _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1),
++ $_LT_AC_TAGVAR(lt_prog_compiler_static, $1),
++ [],
++ [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=])
++
++
++AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
++AC_LIBTOOL_PROG_COMPILER_PIC($1)
++AC_LIBTOOL_PROG_CC_C_O($1)
++AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
++AC_LIBTOOL_PROG_LD_SHLIBS($1)
++AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
++AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
++AC_LIBTOOL_SYS_LIB_STRIP
++AC_LIBTOOL_DLOPEN_SELF($1)
++
++# Report which librarie types wil actually be built
++AC_MSG_CHECKING([if libtool supports shared libraries])
++AC_MSG_RESULT([$can_build_shared])
++
++AC_MSG_CHECKING([whether to build shared libraries])
++test "$can_build_shared" = "no" && enable_shared=no
++
++# On AIX, shared libraries and static libraries use the same namespace, and
++# are all built from PIC.
++case "$host_os" in
++aix3*)
++ test "$enable_shared" = yes && enable_static=no
++ if test -n "$RANLIB"; then
++ archive_cmds="$archive_cmds~\$RANLIB \$lib"
++ postinstall_cmds='$RANLIB $lib'
++ fi
++ ;;
++
++aix4* | aix5*)
++ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
++ test "$enable_shared" = yes && enable_static=no
++ fi
++ ;;
++ darwin* | rhapsody*)
++ if test "$GCC" = yes; then
++ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
++ case "$host_os" in
++ rhapsody* | darwin1.[[012]])
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress'
+ ;;
+- *)
+- # ancient GNU ld didn't support --whole-archive et. al.
+- if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then
+- whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
++ *) # Darwin 1.3 on
++ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress'
+ else
+- whole_archive_flag_spec=
++ case ${MACOSX_DEPLOYMENT_TARGET} in
++ 10.[[012]])
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress'
++ ;;
++ 10.*)
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup'
++ ;;
++ esac
+ fi
+ ;;
+ esac
++ output_verbose_link_cmd='echo'
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring'
++ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
++ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
++ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
++ _LT_AC_TAGVAR(hardcode_direct, $1)=no
++ _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience'
++ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
++ else
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
++ ;;
++esac
++AC_MSG_RESULT([$enable_shared])
++
++AC_MSG_CHECKING([whether to build static libraries])
++# Make sure either enable_shared or enable_static is yes.
++test "$enable_shared" = yes || enable_static=yes
++AC_MSG_RESULT([$enable_static])
++
++AC_LIBTOOL_CONFIG($1)
++
++AC_LANG_POP
++CC="$lt_save_CC"
++])# AC_LIBTOOL_LANG_C_CONFIG
++
++
++# AC_LIBTOOL_LANG_CXX_CONFIG
++# --------------------------
++# Ensure that the configuration vars for the C compiler are
++# suitably defined. Those variables are subsequently used by
++# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
++AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)])
++AC_DEFUN([_LT_AC_LANG_CXX_CONFIG],
++[AC_LANG_PUSH(C++)
++AC_REQUIRE([AC_PROG_CXX])
++AC_REQUIRE([AC_PROG_CXXCPP])
++
++_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
++_LT_AC_TAGVAR(allow_undefined_flag, $1)=
++_LT_AC_TAGVAR(always_export_symbols, $1)=no
++_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
++_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
++_LT_AC_TAGVAR(hardcode_direct, $1)=no
++_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
++_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
++_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
++_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
++_LT_AC_TAGVAR(hardcode_automatic, $1)=no
++_LT_AC_TAGVAR(module_cmds, $1)=
++_LT_AC_TAGVAR(module_expsym_cmds, $1)=
++_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
++_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
++_LT_AC_TAGVAR(no_undefined_flag, $1)=
++_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
++_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
++
++# Dependencies to place before and after the object being linked:
++_LT_AC_TAGVAR(predep_objects, $1)=
++_LT_AC_TAGVAR(postdep_objects, $1)=
++_LT_AC_TAGVAR(predeps, $1)=
++_LT_AC_TAGVAR(postdeps, $1)=
++_LT_AC_TAGVAR(compiler_lib_search_path, $1)=
++
++# Source file extension for C++ test sources.
++ac_ext=cc
++
++# Object file extension for compiled C++ test sources.
++objext=o
++_LT_AC_TAGVAR(objext, $1)=$objext
++
++# Code to be used in simple compile tests
++lt_simple_compile_test_code="int some_variable = 0;\n"
++
++# Code to be used in simple link tests
++lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n'
++
++# ltmain only uses $CC for tagged configurations so make sure $CC is set.
++_LT_AC_SYS_COMPILER
++
++# Allow CC to be a program name with arguments.
++lt_save_CC=$CC
++lt_save_LD=$LD
++lt_save_GCC=$GCC
++GCC=$GXX
++lt_save_with_gnu_ld=$with_gnu_ld
++lt_save_path_LD=$lt_cv_path_LD
++if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
++ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+ else
+- # PORTME fill in a description of your system's linker (not GNU ld)
+- case $host_os in
+- aix3*)
+- allow_undefined_flag=unsupported
+- always_export_symbols=yes
+- archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+- # Note: this linker hardcodes the directories in LIBPATH if there
+- # are no directories specified by -L.
+- hardcode_minus_L=yes
+- if test "$GCC" = yes && test -z "$link_static_flag"; then
+- # Neither direct hardcoding nor static linking is supported with a
+- # broken collect2.
+- hardcode_direct=unsupported
++ unset lt_cv_prog_gnu_ld
++fi
++if test -n "${lt_cv_path_LDCXX+set}"; then
++ lt_cv_path_LD=$lt_cv_path_LDCXX
++else
++ unset lt_cv_path_LD
++fi
++test -z "${LDCXX+set}" || LD=$LDCXX
++CC=${CXX-"c++"}
++compiler=$CC
++_LT_AC_TAGVAR(compiler, $1)=$CC
++cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'`
++
++# We don't want -fno-exception wen compiling C++ code, so set the
++# no_builtin_flag separately
++if test "$GXX" = yes; then
++ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
++else
++ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
++fi
++
++if test "$GXX" = yes; then
++ # Set up default GNU C++ configuration
++
++ AC_PROG_LD
++
++ # Check if GNU C++ uses GNU ld as the underlying linker, since the
++ # archiving commands below assume that GNU ld is being used.
++ if test "$with_gnu_ld" = yes; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
++
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
++ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
++
++ # If archive_cmds runs LD, not CC, wlarc should be empty
++ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
++ # investigate it a little bit more. (MM)
++ wlarc='${wl}'
++
++ # ancient GNU ld didn't support --whole-archive et. al.
++ if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
++ grep 'no-whole-archive' > /dev/null; then
++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
++ else
++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+- ;;
++ else
++ with_gnu_ld=no
++ wlarc=
++
++ # A generic and very simple default shared library creation
++ # command for GNU C++ for the case where it uses the native
++ # linker, instead of GNU ld. If possible, this setting should
++ # overridden to take advantage of the native linker features on
++ # the platform it is being used on.
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
++ fi
++
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
++
++else
++ GXX=no
++ with_gnu_ld=no
++ wlarc=
++fi
+
++# PORTME: fill in a description of your system's C++ link characteristics
++AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
++_LT_AC_TAGVAR(ld_shlibs, $1)=yes
++case $host_os in
++ aix3*)
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+@@ -1586,7 +3728,7 @@
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+- ;;
++ ;;
+ esac
+ done
+ esac
+@@ -1601,34 +3743,39 @@
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+- hardcode_direct=yes
+- archive_cmds=''
+- hardcode_libdir_separator=':'
+- if test "$GCC" = yes; then
+- case $host_os in aix4.[[012]]|aix4.[[012]].*)
++ _LT_AC_TAGVAR(archive_cmds, $1)=''
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
++ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
++
++ if test "$GXX" = yes; then
++ case $host_os in aix4.[012]|aix4.[012].*)
++ # We only want to do this on AIX 4.2 and lower, the check
++ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+- strings "$collect2name" | grep resolve_lib_name >/dev/null
++ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+- hardcode_direct=yes
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ else
+ # We have old collect2
+- hardcode_direct=unsupported
++ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+- hardcode_minus_L=yes
+- hardcode_libdir_flag_spec='-L$libdir'
+- hardcode_libdir_separator=
++ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ esac
+-
+ shared_flag='-shared'
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+- shared_flag='${wl}-G'
++ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
++ # chokes on -Wl,-G. The following line is correct:
++ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+@@ -1638,833 +3785,867 @@
+ fi
+ fi
+
+- # It seems that -bexpall can do strange things, so it is better to
+- # generate a list of symbols to export.
+- always_export_symbols=yes
++ # It seems that -bexpall does not export symbols beginning with
++ # underscore (_), so it is better to generate a list of symbols to export.
++ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+- allow_undefined_flag='-berok'
+- hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib'
+- archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+- else
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
++ # Determine the default libpath from the value encoded in an empty executable.
++ _LT_AC_SYS_LIBPATH_AIX
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
++
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
++ else
+ if test "$host_cpu" = ia64; then
+- hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+- allow_undefined_flag="-z nodefs"
+- archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname ${wl}-h$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
+ else
+- hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib'
++ # Determine the default libpath from the value encoded in an empty executable.
++ _LT_AC_SYS_LIBPATH_AIX
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+- allow_undefined_flag='${wl}-berok'
+- # This is a bit strange, but is similar to how AIX traditionally builds
+- # it's shared libraries.
+- archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"' ~$AR -crlo $output_objdir/$libname$release.a $output_objdir/$soname'
++ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
++ # -bexpall does not export symbols beginning with underscore (_)
++ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
++ # Exported symbols can be pulled into shared objects from archives
++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' '
++ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
++ # This is similar to how AIX traditionally builds it's shared libraries.
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+-
+- amigaos*)
+- archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+- hardcode_libdir_flag_spec='-L$libdir'
+- hardcode_minus_L=yes
+- # see comment about different semantics on the GNU ld section
+- ld_shlibs=no
++ chorus*)
++ case $cc_basename in
++ *)
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ esac
+ ;;
+
+ cygwin* | mingw* | pw32*)
+- # When not using gcc, we currently assume that we are using
+- # Microsoft Visual C++.
+- # hardcode_libdir_flag_spec is actually meaningless, as there is
+- # no search path for DLLs.
+- hardcode_libdir_flag_spec=' '
+- allow_undefined_flag=unsupported
+- # Tell ltmain to make .lib files, not .a files.
+- libext=lib
+- # FIXME: Setting linknames here is a bad hack.
+- archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+- # The linker will automatically build a .lib file if we build a DLL.
+- old_archive_from_new_cmds='true'
+- # FIXME: Should let the user specify the lib program.
+- old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs'
+- fix_srcfile_path='`cygpath -w "$srcfile"`'
+- ;;
++ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
++ # as there is no search path for DLLs.
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
++ _LT_AC_TAGVAR(always_export_symbols, $1)=no
++ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++
++ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
++ # If the export-symbols file already is a .def file (1st line
++ # is EXPORTS), use it as is; otherwise, prepend...
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
++ cp $export_symbols $output_objdir/$soname.def;
++ else
++ echo EXPORTS > $output_objdir/$soname.def;
++ cat $export_symbols >> $output_objdir/$soname.def;
++ fi~
++ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
++ else
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
+
+ darwin* | rhapsody*)
++ if test "$GXX" = yes; then
++ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ case "$host_os" in
+ rhapsody* | darwin1.[[012]])
+- allow_undefined_flag='-undefined suppress'
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress'
+ ;;
+ *) # Darwin 1.3 on
+- allow_undefined_flag='-flat_namespace -undefined suppress'
+- ;;
+- esac
+- # FIXME: Relying on posixy $() will cause problems for
+- # cross-compilation, but unfortunately the echo tests do not
+- # yet detect zsh echo's removal of \ escapes. Also zsh mangles
+- # `"' quotes if we put them in here... so don't!
+- archive_cmds='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs && $CC $(test .$module = .yes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib ${lib}-master.o $deplibs$linker_flags $(test .$module != .yes && echo -install_name $rpath/$soname $verstring)'
+- # We need to add '_' to the symbols in $export_symbols first
+- #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols'
+- hardcode_direct=yes
+- hardcode_shlibpath_var=no
+- whole_archive_flag_spec='-all_load $convenience'
+- ;;
+-
+- freebsd1*)
+- ld_shlibs=no
+- ;;
+-
+- # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+- # support. Future versions do this automatically, but an explicit c++rt0.o
+- # does not break anything, and helps significantly (at the cost of a little
+- # extra space).
+- freebsd2.2*)
+- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+- hardcode_libdir_flag_spec='-R$libdir'
+- hardcode_direct=yes
+- hardcode_shlibpath_var=no
+- ;;
+-
+- # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+- freebsd2*)
+- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+- hardcode_direct=yes
+- hardcode_minus_L=yes
+- hardcode_shlibpath_var=no
+- ;;
+-
+- # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+- freebsd*)
+- archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+- hardcode_libdir_flag_spec='-R$libdir'
+- hardcode_direct=yes
+- hardcode_shlibpath_var=no
+- ;;
+-
+- hpux9* | hpux10* | hpux11*)
+- case $host_os in
+- hpux9*) archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' ;;
+- *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;;
+- esac
+- hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+- hardcode_libdir_separator=:
+- hardcode_direct=yes
+- hardcode_minus_L=yes # Not in the search PATH, but as the default
+- # location of the library.
+- export_dynamic_flag_spec='${wl}-E'
+- ;;
+-
+- irix5* | irix6* | nonstopux*)
+- if test "$GCC" = yes; then
+- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+- else
+- archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+- hardcode_libdir_flag_spec='-rpath $libdir'
+- fi
+- hardcode_libdir_separator=:
+- link_all_deplibs=yes
+- ;;
+-
+- netbsd*)
+- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+- else
+- archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+- fi
+- hardcode_libdir_flag_spec='-R$libdir'
+- hardcode_direct=yes
+- hardcode_shlibpath_var=no
+- ;;
+-
+- newsos6)
+- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+- hardcode_direct=yes
+- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+- hardcode_libdir_separator=:
+- hardcode_shlibpath_var=no
+- ;;
+-
+- openbsd*)
+- hardcode_direct=yes
+- hardcode_shlibpath_var=no
+- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+- archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+- hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+- export_dynamic_flag_spec='${wl}-E'
+- else
+- case "$host_os" in
+- openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+- hardcode_libdir_flag_spec='-R$libdir'
+- ;;
+- *)
+- archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+- hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+- ;;
+- esac
++ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress'
++ else
++ case ${MACOSX_DEPLOYMENT_TARGET} in
++ 10.[[012]])
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress'
++ ;;
++ 10.*)
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup'
++ ;;
++ esac
++ fi
++ ;;
++ esac
++ lt_int_apple_cc_single_mod=no
++ output_verbose_link_cmd='echo'
++ if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then
++ lt_int_apple_cc_single_mod=yes
+ fi
+- ;;
+-
+- os2*)
+- hardcode_libdir_flag_spec='-L$libdir'
+- hardcode_minus_L=yes
+- allow_undefined_flag=unsupported
+- archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+- old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+- ;;
+-
+- osf3*)
+- if test "$GCC" = yes; then
+- allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+- archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
++ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ else
+- allow_undefined_flag=' -expect_unresolved \*'
+- archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ fi
+- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+- hardcode_libdir_separator=:
+- ;;
++ _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+
+- osf4* | osf5*) # as osf3* with the addition of -msym flag
+- if test "$GCC" = yes; then
+- allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+- archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
++ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
++ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+- allow_undefined_flag=' -expect_unresolved \*'
+- archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+- archive_expsym_cmds='for i in `cat $export_symbols`; do printf "-exported_symbol " >> $lib.exp; echo "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+- $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp'
+-
+- #Both c and cxx compiler support -rpath directly
+- hardcode_libdir_flag_spec='-rpath $libdir'
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ fi
+- hardcode_libdir_separator=:
+- ;;
+-
+- sco3.2v5*)
+- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+- hardcode_shlibpath_var=no
+- runpath_var=LD_RUN_PATH
+- hardcode_runpath_var=yes
+- export_dynamic_flag_spec='${wl}-Bexport'
++ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
++ _LT_AC_TAGVAR(hardcode_direct, $1)=no
++ _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience'
++ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
++ else
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ fi
+ ;;
+
+- solaris*)
+- # gcc --version < 3.0 without binutils cannot create self contained
+- # shared libraries reliably, requiring libgcc.a to resolve some of
+- # the object symbols generated in some cases. Libraries that use
+- # assert need libgcc.a to resolve __eprintf, for example. Linking
+- # a copy of libgcc.a into every shared library to guarantee resolving
+- # such symbols causes other problems: According to Tim Van Holder
+- # <tim.van.holder@pandora.be>, C++ libraries end up with a separate
+- # (to the application) exception stack for one thing.
+- no_undefined_flag=' -z defs'
+- if test "$GCC" = yes; then
+- case `$CC --version 2>/dev/null` in
+- [[12]].*)
+- cat <<EOF 1>&2
+-
+-*** Warning: Releases of GCC earlier than version 3.0 cannot reliably
+-*** create self contained shared libraries on Solaris systems, without
+-*** introducing a dependency on libgcc.a. Therefore, libtool is disabling
+-*** -no-undefined support, which will at least allow you to build shared
+-*** libraries. However, you may find that when you link such libraries
+-*** into an application without using GCC, you have to manually add
+-*** \`gcc --print-libgcc-file-name\` to the link command. We urge you to
+-*** upgrade to a newer version of GCC. Another option is to rebuild your
+-*** current GCC to use the GNU linker from GNU binutils 2.9.1 or newer.
+-
+-EOF
+- no_undefined_flag=
++ dgux*)
++ case $cc_basename in
++ ec++)
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ ghcx)
++ # Green Hills C++ Compiler
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ *)
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+- esac
+- fi
+- # $CC -shared without GNU ld will not create a library from C++
+- # object files and a static libstdc++, better avoid it by now
+- archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+- archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+- $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+- hardcode_libdir_flag_spec='-R$libdir'
+- hardcode_shlibpath_var=no
+- case $host_os in
+- solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+- *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+- whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
+ esac
+- link_all_deplibs=yes
+ ;;
+-
+- sunos4*)
+- if test "x$host_vendor" = xsequent; then
+- # Use $CC to link under sequent, because it throws in some extra .o
+- # files that make .init and .fini sections work.
+- archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+- else
+- archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+- fi
+- hardcode_libdir_flag_spec='-L$libdir'
+- hardcode_direct=yes
+- hardcode_minus_L=yes
+- hardcode_shlibpath_var=no
++ freebsd[12]*)
++ # C++ shared libraries reported to be fairly broken before switch to ELF
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ freebsd-elf*)
++ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
++ ;;
++ freebsd* | kfreebsd*-gnu)
++ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
++ # conventions
++ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
++ ;;
++ gnu*)
++ ;;
++ hpux9*)
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
++ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
++ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
++ # but as the default
++ # location of the library.
++
++ case $cc_basename in
++ CC)
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ aCC)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ #
++ # There doesn't appear to be a way to prevent this compiler from
++ # explicitly linking system object files so we need to strip them
++ # from the output so that they don't get included in the library
++ # dependencies.
++ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
++ ;;
++ *)
++ if test "$GXX" = yes; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
++ else
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
++ esac
+ ;;
+-
+- sysv4)
+- case $host_vendor in
+- sni)
+- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+- hardcode_direct=yes # is this really true???
++ hpux10*|hpux11*)
++ if test $with_gnu_ld = no; then
++ case "$host_cpu" in
++ hppa*64*)
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+- siemens)
+- ## LD is ld it makes a PLAMLIB
+- ## CC just makes a GrossModule.
+- archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+- reload_cmds='$CC -r -o $output$reload_objs'
+- hardcode_direct=no
++ ia64*)
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ ;;
+- motorola)
+- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+- hardcode_direct=no #Motorola manual says yes, but my tests say they lie
++ *)
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
++ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ ;;
++ esac
++ fi
++ case "$host_cpu" in
++ hppa*64*)
++ _LT_AC_TAGVAR(hardcode_direct, $1)=no
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++ ia64*)
++ _LT_AC_TAGVAR(hardcode_direct, $1)=no
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
++ # but as the default
++ # location of the library.
++ ;;
++ *)
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
++ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
++ # but as the default
++ # location of the library.
++ ;;
+ esac
+- runpath_var='LD_RUN_PATH'
+- hardcode_shlibpath_var=no
+- ;;
+
+- sysv4.3*)
+- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+- hardcode_shlibpath_var=no
+- export_dynamic_flag_spec='-Bexport'
+- ;;
+-
+- sysv5*)
+- no_undefined_flag=' -z text'
+- # $CC -shared without GNU ld will not create a library from C++
+- # object files and a static libstdc++, better avoid it by now
+- archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+- archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+- $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+- hardcode_libdir_flag_spec=
+- hardcode_shlibpath_var=no
+- runpath_var='LD_RUN_PATH'
+- ;;
+-
+- uts4*)
+- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+- hardcode_libdir_flag_spec='-L$libdir'
+- hardcode_shlibpath_var=no
++ case $cc_basename in
++ CC)
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ aCC)
++ case "$host_cpu" in
++ hppa*64*|ia64*)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs'
++ ;;
++ *)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++ ;;
++ esac
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ #
++ # There doesn't appear to be a way to prevent this compiler from
++ # explicitly linking system object files so we need to strip them
++ # from the output so that they don't get included in the library
++ # dependencies.
++ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
++ ;;
++ *)
++ if test "$GXX" = yes; then
++ if test $with_gnu_ld = no; then
++ case "$host_cpu" in
++ ia64*|hppa*64*)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs'
++ ;;
++ *)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++ ;;
++ esac
++ fi
++ else
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
++ esac
+ ;;
+-
+- dgux*)
+- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+- hardcode_libdir_flag_spec='-L$libdir'
+- hardcode_shlibpath_var=no
++ irix5* | irix6*)
++ case $cc_basename in
++ CC)
++ # SGI C++
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
++
++ # Archives containing C++ object files must be created using
++ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
++ # necessary to make sure instantiated templates are included
++ # in the archive.
++ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
++ ;;
++ *)
++ if test "$GXX" = yes; then
++ if test "$with_gnu_ld" = no; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
++ else
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
++ fi
++ fi
++ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
++ ;;
++ esac
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+-
+- sysv4*MP*)
+- if test -d /usr/nec; then
+- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+- hardcode_shlibpath_var=no
+- runpath_var=LD_RUN_PATH
+- hardcode_runpath_var=yes
+- ld_shlibs=yes
+- fi
++ linux*)
++ case $cc_basename in
++ KCC)
++ # Kuck and Associates, Inc. (KAI) C++ Compiler
++
++ # KCC will only create a shared library if the output file
++ # ends with ".so" (or ".sl" for HP-UX), so rename the library
++ # to its proper name (with version) after linking.
++ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ #
++ # There doesn't appear to be a way to prevent this compiler from
++ # explicitly linking system object files so we need to strip them
++ # from the output so that they don't get included in the library
++ # dependencies.
++ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
++
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir'
++ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
++
++ # Archives containing C++ object files must be created using
++ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
++ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
++ ;;
++ icpc)
++ # Intel C++
++ with_gnu_ld=yes
++ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
++ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
++ ;;
++ cxx)
++ # Compaq C++
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
++
++ runpath_var=LD_RUN_PATH
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
++
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ #
++ # There doesn't appear to be a way to prevent this compiler from
++ # explicitly linking system object files so we need to strip them
++ # from the output so that they don't get included in the library
++ # dependencies.
++ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
++ ;;
++ esac
+ ;;
+-
+- sysv4.2uw2*)
+- archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+- hardcode_direct=yes
+- hardcode_minus_L=no
+- hardcode_shlibpath_var=no
+- hardcode_runpath_var=yes
+- runpath_var=LD_RUN_PATH
++ lynxos*)
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ m88k*)
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ mvs*)
++ case $cc_basename in
++ cxx)
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ *)
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ esac
+ ;;
+-
+- sysv5uw7* | unixware7*)
+- no_undefined_flag='${wl}-z ${wl}text'
+- if test "$GCC" = yes; then
+- archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+- else
+- archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
++ netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
++ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
++ wlarc=
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ fi
+- runpath_var='LD_RUN_PATH'
+- hardcode_shlibpath_var=no
+- ;;
+-
+- *)
+- ld_shlibs=no
++ # Workaround some broken pre-1.5 toolchains
++ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+- esac
+-fi
+-AC_MSG_RESULT([$ld_shlibs])
+-test "$ld_shlibs" = no && can_build_shared=no
+-
+-# Check hardcoding attributes.
+-AC_MSG_CHECKING([how to hardcode library paths into programs])
+-hardcode_action=
+-if test -n "$hardcode_libdir_flag_spec" || \
+- test -n "$runpath_var"; then
+-
+- # We can hardcode non-existant directories.
+- if test "$hardcode_direct" != no &&
+- # If the only mechanism to avoid hardcoding is shlibpath_var, we
+- # have to relink, otherwise we might link with an installed library
+- # when we should be linking with a yet-to-be-installed one
+- ## test "$hardcode_shlibpath_var" != no &&
+- test "$hardcode_minus_L" != no; then
+- # Linking always hardcodes the temporary library directory.
+- hardcode_action=relink
+- else
+- # We can link without hardcoding, and we can hardcode nonexisting dirs.
+- hardcode_action=immediate
+- fi
+-else
+- # We cannot hardcode anything, or else we can only hardcode existing
+- # directories.
+- hardcode_action=unsupported
+-fi
+-AC_MSG_RESULT([$hardcode_action])
+-
+-striplib=
+-old_striplib=
+-AC_MSG_CHECKING([whether stripping libraries is possible])
+-if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+- test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+- test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+- AC_MSG_RESULT([yes])
+-else
+- AC_MSG_RESULT([no])
+-fi
+-
+-reload_cmds='$LD$reload_flag -o $output$reload_objs'
+-test -z "$deplibs_check_method" && deplibs_check_method=unknown
+-
+-# PORTME Fill in your ld.so characteristics
+-AC_MSG_CHECKING([dynamic linker characteristics])
+-library_names_spec=
+-libname_spec='lib$name'
+-soname_spec=
+-postinstall_cmds=
+-postuninstall_cmds=
+-finish_cmds=
+-finish_eval=
+-shlibpath_var=
+-shlibpath_overrides_runpath=unknown
+-version_type=none
+-dynamic_linker="$host_os ld.so"
+-sys_lib_dlsearch_path_spec="/lib /usr/lib"
+-sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+-
+-case $host_os in
+-aix3*)
+- version_type=linux
+- library_names_spec='${libname}${release}.so$versuffix $libname.a'
+- shlibpath_var=LIBPATH
++ osf3*)
++ case $cc_basename in
++ KCC)
++ # Kuck and Associates, Inc. (KAI) C++ Compiler
++
++ # KCC will only create a shared library if the output file
++ # ends with ".so" (or ".sl" for HP-UX), so rename the library
++ # to its proper name (with version) after linking.
++ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
++
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
++
++ # Archives containing C++ object files must be created using
++ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
++ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+
+- # AIX has no versioning support, so we append a major version to the name.
+- soname_spec='${libname}${release}.so$major'
+- ;;
++ ;;
++ RCC)
++ # Rational C++ 2.4.1
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ cxx)
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
++
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
++
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ #
++ # There doesn't appear to be a way to prevent this compiler from
++ # explicitly linking system object files so we need to strip them
++ # from the output so that they don't get included in the library
++ # dependencies.
++ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
++ ;;
++ *)
++ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
++
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
++
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+-aix4* | aix5*)
+- version_type=linux
+- need_lib_prefix=no
+- need_version=no
+- hardcode_into_libs=yes
+- if test "$host_cpu" = ia64; then
+- # AIX 5 supports IA64
+- library_names_spec='${libname}${release}.so$major ${libname}${release}.so$versuffix $libname.so'
+- shlibpath_var=LD_LIBRARY_PATH
+- else
+- # With GCC up to 2.95.x, collect2 would create an import file
+- # for dependence libraries. The import file would start with
+- # the line `#! .'. This would cause the generated library to
+- # depend on `.', always an invalid library. This was fixed in
+- # development snapshots of GCC prior to 3.0.
+- case $host_os in
+- aix4 | aix4.[[01]] | aix4.[[01]].*)
+- if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+- echo ' yes '
+- echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+- :
+ else
+- can_build_shared=no
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+- # AIX (on Power*) has no versioning support, so currently we can
+- # not hardcode correct soname into executable. Probably we can
+- # add versioning support to collect2, so additional links can
+- # be useful in future.
+- if test "$aix_use_runtimelinking" = yes; then
+- # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+- # instead of lib<name>.a to let people know that these are not
+- # typical AIX shared libraries.
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+- else
+- # We preserve .a as extension for shared libraries through AIX4.2
+- # and later when we are not doing run time linking.
+- library_names_spec='${libname}${release}.a $libname.a'
+- soname_spec='${libname}${release}.so$major'
+- fi
+- shlibpath_var=LIBPATH
+- fi
+- hardcode_into_libs=yes
+- ;;
+-
+-amigaos*)
+- library_names_spec='$libname.ixlibrary $libname.a'
+- # Create ${libname}_ixlibrary.a entries in /sys/libs.
+- finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
+- ;;
+-
+-beos*)
+- library_names_spec='${libname}.so'
+- dynamic_linker="$host_os ld.so"
+- shlibpath_var=LIBRARY_PATH
+- ;;
+-
+-bsdi4*)
+- version_type=linux
+- need_version=no
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+- soname_spec='${libname}${release}.so$major'
+- finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+- shlibpath_var=LD_LIBRARY_PATH
+- sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+- sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+- export_dynamic_flag_spec=-rdynamic
+- # the default ld.so.conf also contains /usr/contrib/lib and
+- # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+- # libtool to hard-code these into programs
+- ;;
+-
+-cygwin* | mingw* | pw32*)
+- version_type=windows
+- need_version=no
+- need_lib_prefix=no
+- case $GCC,$host_os in
+- yes,cygwin*)
+- library_names_spec='$libname.dll.a'
+- soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll'
+- postinstall_cmds='dlpath=`bash 2>&1 -c '\''. $dir/${file}i;echo \$dlname'\''`~
+- dldir=$destdir/`dirname \$dlpath`~
+- test -d \$dldir || mkdir -p \$dldir~
+- $install_prog .libs/$dlname \$dldir/$dlname'
+- postuninstall_cmds='dldll=`bash 2>&1 -c '\''. $file; echo \$dlname'\''`~
+- dlpath=$dir/\$dldll~
+- $rm \$dlpath'
+- ;;
+- yes,mingw*)
+- library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll'
+- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g" -e "s,=/,/,g"`
+- ;;
+- yes,pw32*)
+- library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll'
+ ;;
+- *)
+- library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll $libname.lib'
+- ;;
+- esac
+- dynamic_linker='Win32 ld.exe'
+- # FIXME: first we should search . and the directory the executable is in
+- shlibpath_var=PATH
+- ;;
+-
+-darwin* | rhapsody*)
+- dynamic_linker="$host_os dyld"
+- version_type=darwin
+- need_lib_prefix=no
+- need_version=no
+- # FIXME: Relying on posixy $() will cause problems for
+- # cross-compilation, but unfortunately the echo tests do not
+- # yet detect zsh echo's removal of \ escapes.
+- library_names_spec='${libname}${release}${versuffix}.$(test .$module = .yes && echo so || echo dylib) ${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib) ${libname}.$(test .$module = .yes && echo so || echo dylib)'
+- soname_spec='${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib)'
+- shlibpath_overrides_runpath=yes
+- shlibpath_var=DYLD_LIBRARY_PATH
+- ;;
+-
+-freebsd1*)
+- dynamic_linker=no
+- ;;
+-
+-freebsd*-gnu*)
+- version_type=linux
+- need_lib_prefix=no
+- need_version=no
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+- soname_spec='${libname}${release}.so$major'
+- shlibpath_var=LD_LIBRARY_PATH
+- shlibpath_overrides_runpath=no
+- hardcode_into_libs=yes
+- dynamic_linker='GNU/FreeBSD ld.so'
+- ;;
++ osf4* | osf5*)
++ case $cc_basename in
++ KCC)
++ # Kuck and Associates, Inc. (KAI) C++ Compiler
++
++ # KCC will only create a shared library if the output file
++ # ends with ".so" (or ".sl" for HP-UX), so rename the library
++ # to its proper name (with version) after linking.
++ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
++
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
++
++ # Archives containing C++ object files must be created using
++ # the KAI C++ compiler.
++ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs'
++ ;;
++ RCC)
++ # Rational C++ 2.4.1
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ cxx)
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
++ echo "-hidden">> $lib.exp~
++ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~
++ $rm $lib.exp'
++
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
++
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ #
++ # There doesn't appear to be a way to prevent this compiler from
++ # explicitly linking system object files so we need to strip them
++ # from the output so that they don't get included in the library
++ # dependencies.
++ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
++ ;;
++ *)
++ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
++
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
++
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+-freebsd*)
+- objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+- version_type=freebsd-$objformat
+- case $version_type in
+- freebsd-elf*)
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+- need_version=no
+- need_lib_prefix=no
+- ;;
+- freebsd-*)
+- library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix'
+- need_version=yes
+- ;;
+- esac
+- shlibpath_var=LD_LIBRARY_PATH
+- case $host_os in
+- freebsd2*)
+- shlibpath_overrides_runpath=yes
++ else
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
++ esac
+ ;;
+- *)
+- shlibpath_overrides_runpath=no
+- hardcode_into_libs=yes
++ psos*)
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ sco*)
++ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
++ case $cc_basename in
++ CC)
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ *)
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ esac
+ ;;
+- esac
+- ;;
++ sunos4*)
++ case $cc_basename in
++ CC)
++ # Sun C++ 4.x
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ lcc)
++ # Lucid
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ *)
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ esac
++ ;;
++ solaris*)
++ case $cc_basename in
++ CC)
++ # Sun C++ 4.2, 5.x and Centerline C++
++ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs'
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
++ $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
++
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ case $host_os in
++ solaris2.[0-5] | solaris2.[0-5].*) ;;
++ *)
++ # The C++ compiler is used as linker so we must use $wl
++ # flag to pass the commands to the underlying system
++ # linker.
++ # Supported since Solaris 2.6 (maybe 2.5.1?)
++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
++ ;;
++ esac
++ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+-gnu*)
+- version_type=linux
+- need_lib_prefix=no
+- need_version=no
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so'
+- soname_spec='${libname}${release}.so$major'
+- shlibpath_var=LD_LIBRARY_PATH
+- hardcode_into_libs=yes
+- ;;
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ #
++ # There doesn't appear to be a way to prevent this compiler from
++ # explicitly linking system object files so we need to strip them
++ # from the output so that they don't get included in the library
++ # dependencies.
++ output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[[LR]]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
++
++ # Archives containing C++ object files must be created using
++ # "CC -xar", where "CC" is the Sun C++ compiler. This is
++ # necessary to make sure instantiated templates are included
++ # in the archive.
++ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
++ ;;
++ gcx)
++ # Green Hills C++ Compiler
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+-hpux9* | hpux10* | hpux11*)
+- # Give a soname corresponding to the major version so that dld.sl refuses to
+- # link against other versions.
+- dynamic_linker="$host_os dld.sl"
+- version_type=sunos
+- need_lib_prefix=no
+- need_version=no
+- shlibpath_var=SHLIB_PATH
+- shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+- library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl'
+- soname_spec='${libname}${release}.sl$major'
+- # HP-UX runs *really* slowly unless shared libraries are mode 555.
+- postinstall_cmds='chmod 555 $lib'
+- ;;
++ # The C++ compiler must be used to create the archive.
++ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
++ ;;
++ *)
++ # GNU C++ compiler with Solaris linker
++ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
++ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
++ if $CC --version | grep -v '^2\.7' > /dev/null; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
++ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
++
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
++ else
++ # g++ 2.7 appears to require `-G' NOT `-shared' on this
++ # platform.
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
++ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
++
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
++ fi
+
+-irix5* | irix6* | nonstopux*)
+- case $host_os in
+- nonstopux*) version_type=nonstopux ;;
+- *) version_type=irix ;;
+- esac
+- need_lib_prefix=no
+- need_version=no
+- soname_spec='${libname}${release}.so$major'
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so $libname.so'
+- case $host_os in
+- irix5* | nonstopux*)
+- libsuff= shlibsuff=
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
++ fi
++ ;;
++ esac
+ ;;
+- *)
+- case $LD in # libtool.m4 will add one of these switches to LD
+- *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;;
+- *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;;
+- *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;;
+- *) libsuff= shlibsuff= libmagic=never-match;;
++ sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*)
++ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
++ ;;
++ tandem*)
++ case $cc_basename in
++ NCC)
++ # NonStop-UX NCC 3.20
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ *)
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
+ esac
+ ;;
+- esac
+- shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+- shlibpath_overrides_runpath=no
+- sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+- sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+- ;;
+-
+-# No shared lib support for Linux oldld, aout, or coff.
+-linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
+- dynamic_linker=no
+- ;;
++ vxworks*)
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ *)
++ # FIXME: insert proper C++ library support
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++esac
++AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
++test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+-# This must be Linux ELF.
+-linux-gnu*)
+- version_type=linux
+- need_lib_prefix=no
+- need_version=no
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+- soname_spec='${libname}${release}.so$major'
+- finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+- shlibpath_var=LD_LIBRARY_PATH
+- shlibpath_overrides_runpath=no
+- # This implies no fast_install, which is unacceptable.
+- # Some rework will be needed to allow for fast_install
+- # before this can be enabled.
+- hardcode_into_libs=yes
++_LT_AC_TAGVAR(GCC, $1)="$GXX"
++_LT_AC_TAGVAR(LD, $1)="$LD"
+
+- # We used to test for /lib/ld.so.1 and disable shared libraries on
+- # powerpc, because MkLinux only supported shared libraries with the
+- # GNU dynamic linker. Since this was broken with cross compilers,
+- # most powerpc-linux boxes support dynamic linking these days and
+- # people can always --disable-shared, the test was removed, and we
+- # assume the GNU/Linux dynamic linker is in use.
+- dynamic_linker='GNU/Linux ld.so'
+- ;;
++AC_LIBTOOL_POSTDEP_PREDEP($1)
++AC_LIBTOOL_PROG_COMPILER_PIC($1)
++AC_LIBTOOL_PROG_CC_C_O($1)
++AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
++AC_LIBTOOL_PROG_LD_SHLIBS($1)
++AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
++AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
++AC_LIBTOOL_SYS_LIB_STRIP
++AC_LIBTOOL_DLOPEN_SELF($1)
++
++AC_LIBTOOL_CONFIG($1)
++
++AC_LANG_POP
++CC=$lt_save_CC
++LDCXX=$LD
++LD=$lt_save_LD
++GCC=$lt_save_GCC
++with_gnu_ldcxx=$with_gnu_ld
++with_gnu_ld=$lt_save_with_gnu_ld
++lt_cv_path_LDCXX=$lt_cv_path_LD
++lt_cv_path_LD=$lt_save_path_LD
++lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
++lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
++])# AC_LIBTOOL_LANG_CXX_CONFIG
+
+-netbsd*)
+- version_type=sunos
+- need_lib_prefix=no
+- need_version=no
+- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+- library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+- dynamic_linker='NetBSD (a.out) ld.so'
+- else
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so'
+- soname_spec='${libname}${release}.so$major'
+- dynamic_linker='NetBSD ld.elf_so'
+- fi
+- shlibpath_var=LD_LIBRARY_PATH
+- shlibpath_overrides_runpath=yes
+- hardcode_into_libs=yes
+- ;;
++# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME])
++# ------------------------
++# Figure out "hidden" library dependencies from verbose
++# compiler output when linking a shared library.
++# Parse the compiler output and extract the necessary
++# objects, libraries and library flags.
++AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[
++dnl we can't use the lt_simple_compile_test_code here,
++dnl because it contains code intended for an executable,
++dnl not a library. It's possible we should let each
++dnl tag define a new lt_????_link_test_code variable,
++dnl but it's only used here...
++ifelse([$1],[],[cat > conftest.$ac_ext <<EOF
++int a;
++void foo (void) { a = 0; }
++EOF
++],[$1],[CXX],[cat > conftest.$ac_ext <<EOF
++class Foo
++{
++public:
++ Foo (void) { a = 0; }
++private:
++ int a;
++};
++EOF
++],[$1],[F77],[cat > conftest.$ac_ext <<EOF
++ subroutine foo
++ implicit none
++ integer*4 a
++ a=0
++ return
++ end
++EOF
++],[$1],[GCJ],[cat > conftest.$ac_ext <<EOF
++public class foo {
++ private int a;
++ public void bar (void) {
++ a = 0;
++ }
++};
++EOF
++])
++dnl Parse the compiler output and extract the necessary
++dnl objects, libraries and library flags.
++if AC_TRY_EVAL(ac_compile); then
++ # Parse the compiler output and extract the necessary
++ # objects, libraries and library flags.
++
++ # Sentinel used to keep track of whether or not we are before
++ # the conftest object file.
++ pre_test_object_deps_done=no
++
++ # The `*' in the case matches for architectures that use `case' in
++ # $output_verbose_cmd can trigger glob expansion during the loop
++ # eval without this substitution.
++ output_verbose_link_cmd="`$echo \"X$output_verbose_link_cmd\" | $Xsed -e \"$no_glob_subst\"`"
++
++ for p in `eval $output_verbose_link_cmd`; do
++ case $p in
++
++ -L* | -R* | -l*)
++ # Some compilers place space between "-{L,R}" and the path.
++ # Remove the space.
++ if test $p = "-L" \
++ || test $p = "-R"; then
++ prev=$p
++ continue
++ else
++ prev=
++ fi
++
++ if test "$pre_test_object_deps_done" = no; then
++ case $p in
++ -L* | -R*)
++ # Internal compiler library paths should come after those
++ # provided the user. The postdeps already come after the
++ # user supplied libs so there is no need to process them.
++ if test -z "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then
++ _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
++ else
++ _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${_LT_AC_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
++ fi
++ ;;
++ # The "-l" case would never come before the object being
++ # linked, so don't bother handling this case.
++ esac
++ else
++ if test -z "$_LT_AC_TAGVAR(postdeps, $1)"; then
++ _LT_AC_TAGVAR(postdeps, $1)="${prev}${p}"
++ else
++ _LT_AC_TAGVAR(postdeps, $1)="${_LT_AC_TAGVAR(postdeps, $1)} ${prev}${p}"
++ fi
++ fi
++ ;;
++
++ *.$objext)
++ # This assumes that the test object file only shows up
++ # once in the compiler output.
++ if test "$p" = "conftest.$objext"; then
++ pre_test_object_deps_done=yes
++ continue
++ fi
++
++ if test "$pre_test_object_deps_done" = no; then
++ if test -z "$_LT_AC_TAGVAR(predep_objects, $1)"; then
++ _LT_AC_TAGVAR(predep_objects, $1)="$p"
++ else
++ _LT_AC_TAGVAR(predep_objects, $1)="$_LT_AC_TAGVAR(predep_objects, $1) $p"
++ fi
++ else
++ if test -z "$_LT_AC_TAGVAR(postdep_objects, $1)"; then
++ _LT_AC_TAGVAR(postdep_objects, $1)="$p"
++ else
++ _LT_AC_TAGVAR(postdep_objects, $1)="$_LT_AC_TAGVAR(postdep_objects, $1) $p"
++ fi
++ fi
++ ;;
+
+-newsos6)
+- version_type=linux
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+- shlibpath_var=LD_LIBRARY_PATH
+- shlibpath_overrides_runpath=yes
+- ;;
++ *) ;; # Ignore the rest.
+
+-openbsd*)
+- version_type=sunos
+- need_lib_prefix=no
+- need_version=no
+- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+- case "$host_os" in
+- openbsd2.[[89]] | openbsd2.[[89]].*)
+- shlibpath_overrides_runpath=no
+- ;;
+- *)
+- shlibpath_overrides_runpath=yes
+- ;;
+ esac
+- else
+- shlibpath_overrides_runpath=yes
+- fi
+- library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+- shlibpath_var=LD_LIBRARY_PATH
+- ;;
+-
+-os2*)
+- libname_spec='$name'
+- need_lib_prefix=no
+- library_names_spec='$libname.dll $libname.a'
+- dynamic_linker='OS/2 ld.exe'
+- shlibpath_var=LIBPATH
+- ;;
+-
+-osf3* | osf4* | osf5*)
+- version_type=osf
+- need_version=no
+- need_lib_prefix=no
+- soname_spec='${libname}${release}.so$major'
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+- shlibpath_var=LD_LIBRARY_PATH
+- sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+- sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+- hardcode_into_libs=yes
+- ;;
++ done
+
+-sco3.2v5*)
+- version_type=osf
+- soname_spec='${libname}${release}.so$major'
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+- shlibpath_var=LD_LIBRARY_PATH
+- ;;
++ # Clean up.
++ rm -f a.out a.exe
++else
++ echo "libtool.m4: error: problem compiling $1 test program"
++fi
+
+-solaris*)
+- version_type=linux
+- need_lib_prefix=no
+- need_version=no
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+- soname_spec='${libname}${release}.so$major'
+- shlibpath_var=LD_LIBRARY_PATH
+- shlibpath_overrides_runpath=yes
+- hardcode_into_libs=yes
+- # ldd complains unless libraries are executable
+- postinstall_cmds='chmod +x $lib'
+- ;;
++$rm -f confest.$objext
+
+-sunos4*)
+- version_type=sunos
+- library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+- finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+- shlibpath_var=LD_LIBRARY_PATH
+- shlibpath_overrides_runpath=yes
+- if test "$with_gnu_ld" = yes; then
+- need_lib_prefix=no
+- fi
+- need_version=yes
+- ;;
++case " $_LT_AC_TAGVAR(postdeps, $1) " in
++*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;;
++esac
++])# AC_LIBTOOL_POSTDEP_PREDEP
+
+-sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+- version_type=linux
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+- soname_spec='${libname}${release}.so$major'
+- shlibpath_var=LD_LIBRARY_PATH
+- case $host_vendor in
+- sni)
+- shlibpath_overrides_runpath=no
+- need_lib_prefix=no
+- export_dynamic_flag_spec='${wl}-Blargedynsym'
+- runpath_var=LD_RUN_PATH
+- ;;
+- siemens)
+- need_lib_prefix=no
+- ;;
+- motorola)
+- need_lib_prefix=no
+- need_version=no
+- shlibpath_overrides_runpath=no
+- sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+- ;;
+- esac
+- ;;
++# AC_LIBTOOL_LANG_F77_CONFIG
++# ------------------------
++# Ensure that the configuration vars for the C compiler are
++# suitably defined. Those variables are subsequently used by
++# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
++AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)])
++AC_DEFUN([_LT_AC_LANG_F77_CONFIG],
++[AC_REQUIRE([AC_PROG_F77])
++AC_LANG_PUSH(Fortran 77)
++
++_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
++_LT_AC_TAGVAR(allow_undefined_flag, $1)=
++_LT_AC_TAGVAR(always_export_symbols, $1)=no
++_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
++_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
++_LT_AC_TAGVAR(hardcode_direct, $1)=no
++_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
++_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
++_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
++_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
++_LT_AC_TAGVAR(hardcode_automatic, $1)=no
++_LT_AC_TAGVAR(module_cmds, $1)=
++_LT_AC_TAGVAR(module_expsym_cmds, $1)=
++_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
++_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
++_LT_AC_TAGVAR(no_undefined_flag, $1)=
++_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
++_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
++
++# Source file extension for f77 test sources.
++ac_ext=f
++
++# Object file extension for compiled f77 test sources.
++objext=o
++_LT_AC_TAGVAR(objext, $1)=$objext
+
+-uts4*)
+- version_type=linux
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+- soname_spec='${libname}${release}.so$major'
+- shlibpath_var=LD_LIBRARY_PATH
+- ;;
++# Code to be used in simple compile tests
++lt_simple_compile_test_code=" subroutine t\n return\n end\n"
+
+-dgux*)
+- version_type=linux
+- need_lib_prefix=no
+- need_version=no
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+- soname_spec='${libname}${release}.so$major'
+- shlibpath_var=LD_LIBRARY_PATH
+- ;;
++# Code to be used in simple link tests
++lt_simple_link_test_code=" program t\n end\n"
+
+-sysv4*MP*)
+- if test -d /usr/nec ;then
+- version_type=linux
+- library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+- soname_spec='$libname.so.$major'
+- shlibpath_var=LD_LIBRARY_PATH
+- fi
+- ;;
++# ltmain only uses $CC for tagged configurations so make sure $CC is set.
++_LT_AC_SYS_COMPILER
+
+-*)
+- dynamic_linker=no
+- ;;
+-esac
+-AC_MSG_RESULT([$dynamic_linker])
+-test "$dynamic_linker" = no && can_build_shared=no
++# Allow CC to be a program name with arguments.
++lt_save_CC="$CC"
++CC=${F77-"f77"}
++compiler=$CC
++_LT_AC_TAGVAR(compiler, $1)=$CC
++cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'`
+
+-# Report the final consequences.
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+@@ -2481,125 +4662,206 @@
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
++aix4* | aix5*)
++ test "$enable_shared" = yes && enable_static=no
++ ;;
++esac
++AC_MSG_RESULT([$enable_shared])
++
++AC_MSG_CHECKING([whether to build static libraries])
++# Make sure either enable_shared or enable_static is yes.
++test "$enable_shared" = yes || enable_static=yes
++AC_MSG_RESULT([$enable_static])
++
++test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
++
++_LT_AC_TAGVAR(GCC, $1)="$G77"
++_LT_AC_TAGVAR(LD, $1)="$LD"
++
++AC_LIBTOOL_PROG_COMPILER_PIC($1)
++AC_LIBTOOL_PROG_CC_C_O($1)
++AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
++AC_LIBTOOL_PROG_LD_SHLIBS($1)
++AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
++AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
++AC_LIBTOOL_SYS_LIB_STRIP
++
++
++AC_LIBTOOL_CONFIG($1)
++
++AC_LANG_POP
++CC="$lt_save_CC"
++])# AC_LIBTOOL_LANG_F77_CONFIG
++
++
++# AC_LIBTOOL_LANG_GCJ_CONFIG
++# --------------------------
++# Ensure that the configuration vars for the C compiler are
++# suitably defined. Those variables are subsequently used by
++# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
++AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)])
++AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG],
++[AC_LANG_SAVE
++
++# Source file extension for Java test sources.
++ac_ext=java
++
++# Object file extension for compiled Java test sources.
++objext=o
++_LT_AC_TAGVAR(objext, $1)=$objext
++
++# Code to be used in simple compile tests
++lt_simple_compile_test_code="class foo {}\n"
++
++# Code to be used in simple link tests
++lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n'
++
++# ltmain only uses $CC for tagged configurations so make sure $CC is set.
++_LT_AC_SYS_COMPILER
++
++# Allow CC to be a program name with arguments.
++lt_save_CC="$CC"
++CC=${GCJ-"gcj"}
++compiler=$CC
++_LT_AC_TAGVAR(compiler, $1)=$CC
++
++# GCJ did not exist at the time GCC didn't implicitly link libc in.
++_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
++
++AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
++AC_LIBTOOL_PROG_COMPILER_PIC($1)
++AC_LIBTOOL_PROG_CC_C_O($1)
++AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
++AC_LIBTOOL_PROG_LD_SHLIBS($1)
++AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
++AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
++AC_LIBTOOL_SYS_LIB_STRIP
++AC_LIBTOOL_DLOPEN_SELF($1)
++
++AC_LIBTOOL_CONFIG($1)
++
++AC_LANG_RESTORE
++CC="$lt_save_CC"
++])# AC_LIBTOOL_LANG_GCJ_CONFIG
++
++
++# AC_LIBTOOL_LANG_RC_CONFIG
++# --------------------------
++# Ensure that the configuration vars for the Windows resource compiler are
++# suitably defined. Those variables are subsequently used by
++# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
++AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)])
++AC_DEFUN([_LT_AC_LANG_RC_CONFIG],
++[AC_LANG_SAVE
++
++# Source file extension for RC test sources.
++ac_ext=rc
++
++# Object file extension for compiled RC test sources.
++objext=o
++_LT_AC_TAGVAR(objext, $1)=$objext
+
+-aix4*)
+- if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+- test "$enable_shared" = yes && enable_static=no
+- fi
+- ;;
+-esac
+-AC_MSG_RESULT([$enable_shared])
++# Code to be used in simple compile tests
++lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n'
+
+-AC_MSG_CHECKING([whether to build static libraries])
+-# Make sure either enable_shared or enable_static is yes.
+-test "$enable_shared" = yes || enable_static=yes
+-AC_MSG_RESULT([$enable_static])
++# Code to be used in simple link tests
++lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+-if test "$hardcode_action" = relink; then
+- # Fast installation is not supported
+- enable_fast_install=no
+-elif test "$shlibpath_overrides_runpath" = yes ||
+- test "$enable_shared" = no; then
+- # Fast installation is not necessary
+- enable_fast_install=needless
+-fi
++# ltmain only uses $CC for tagged configurations so make sure $CC is set.
++_LT_AC_SYS_COMPILER
+
+-variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+-if test "$GCC" = yes; then
+- variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+-fi
++# Allow CC to be a program name with arguments.
++lt_save_CC="$CC"
++CC=${RC-"windres"}
++compiler=$CC
++_LT_AC_TAGVAR(compiler, $1)=$CC
++_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+-AC_LIBTOOL_DLOPEN_SELF
++AC_LIBTOOL_CONFIG($1)
++
++AC_LANG_RESTORE
++CC="$lt_save_CC"
++])# AC_LIBTOOL_LANG_RC_CONFIG
+
+-if test "$enable_shared" = yes && test "$GCC" = yes; then
+- case $archive_cmds in
+- *'~'*)
+- # FIXME: we may have to deal with multi-command sequences.
+- ;;
+- '$CC '*)
+- # Test whether the compiler implicitly links with -lc since on some
+- # systems, -lgcc has to come before -lc. If gcc already passes -lc
+- # to ld, don't add -lc before -lgcc.
+- AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+- AC_CACHE_VAL([lt_cv_archive_cmds_need_lc],
+- [$rm conftest*
+- echo 'static int dummy;' > conftest.$ac_ext
+-
+- if AC_TRY_EVAL(ac_compile); then
+- soname=conftest
+- lib=conftest
+- libobjs=conftest.$ac_objext
+- deplibs=
+- wl=$lt_cv_prog_cc_wl
+- compiler_flags=-v
+- linker_flags=-v
+- verstring=
+- output_objdir=.
+- libname=conftest
+- save_allow_undefined_flag=$allow_undefined_flag
+- allow_undefined_flag=
+- if AC_TRY_EVAL(archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1)
+- then
+- lt_cv_archive_cmds_need_lc=no
+- else
+- lt_cv_archive_cmds_need_lc=yes
+- fi
+- allow_undefined_flag=$save_allow_undefined_flag
+- else
+- cat conftest.err 1>&5
+- fi])
+- AC_MSG_RESULT([$lt_cv_archive_cmds_need_lc])
+- ;;
+- esac
+-fi
+-need_lc=${lt_cv_archive_cmds_need_lc-yes}
+
+-# The second clause should only fire when bootstrapping the
++# AC_LIBTOOL_CONFIG([TAGNAME])
++# ----------------------------
++# If TAGNAME is not passed, then create an initial libtool script
++# with a default configuration from the untagged config vars. Otherwise
++# add code to config.status for appending the configuration named by
++# TAGNAME from the matching tagged config vars.
++AC_DEFUN([AC_LIBTOOL_CONFIG],
++[# The else clause should only fire when bootstrapping the
+ # libtool distribution, otherwise you forgot to ship ltmain.sh
+ # with your package, and you will get complaints that there are
+ # no rules to generate ltmain.sh.
+ if test -f "$ltmain"; then
+- :
+-else
+- # If there is no Makefile yet, we rely on a make rule to execute
+- # `config.status --recheck' to rerun these tests and create the
+- # libtool script then.
+- test -f Makefile && make "$ltmain"
+-fi
+-
+-if test -f "$ltmain"; then
+- trap "$rm \"${ofile}T\"; exit 1" 1 2 15
+- $rm -f "${ofile}T"
+-
+- echo creating $ofile
+-
++ # See if we are running on zsh, and set the options which allow our commands through
++ # without removal of \ escapes.
++ if test -n "${ZSH_VERSION+set}" ; then
++ setopt NO_GLOB_SUBST
++ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+- for var in echo old_CC old_CFLAGS SED \
+- AR AR_FLAGS CC LD LN_S NM SHELL \
+- reload_flag reload_cmds wl \
+- pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
+- thread_safe_flag_spec whole_archive_flag_spec libname_spec \
+- library_names_spec soname_spec \
+- RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
+- old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds \
+- postuninstall_cmds extract_expsyms_cmds old_archive_from_expsyms_cmds \
+- old_striplib striplib file_magic_cmd export_symbols_cmds \
+- deplibs_check_method allow_undefined_flag no_undefined_flag \
+- finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
+- global_symbol_to_c_name_address \
+- hardcode_libdir_flag_spec hardcode_libdir_separator \
++ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \
++ SED SHELL STRIP \
++ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
++ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
++ deplibs_check_method reload_flag reload_cmds need_locks \
++ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
++ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+- compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
++ old_postinstall_cmds old_postuninstall_cmds \
++ _LT_AC_TAGVAR(compiler, $1) \
++ _LT_AC_TAGVAR(CC, $1) \
++ _LT_AC_TAGVAR(LD, $1) \
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \
++ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \
++ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \
++ _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \
++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \
++ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \
++ _LT_AC_TAGVAR(old_archive_cmds, $1) \
++ _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \
++ _LT_AC_TAGVAR(predep_objects, $1) \
++ _LT_AC_TAGVAR(postdep_objects, $1) \
++ _LT_AC_TAGVAR(predeps, $1) \
++ _LT_AC_TAGVAR(postdeps, $1) \
++ _LT_AC_TAGVAR(compiler_lib_search_path, $1) \
++ _LT_AC_TAGVAR(archive_cmds, $1) \
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1) \
++ _LT_AC_TAGVAR(postinstall_cmds, $1) \
++ _LT_AC_TAGVAR(postuninstall_cmds, $1) \
++ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \
++ _LT_AC_TAGVAR(allow_undefined_flag, $1) \
++ _LT_AC_TAGVAR(no_undefined_flag, $1) \
++ _LT_AC_TAGVAR(export_symbols_cmds, $1) \
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \
++ _LT_AC_TAGVAR(hardcode_automatic, $1) \
++ _LT_AC_TAGVAR(module_cmds, $1) \
++ _LT_AC_TAGVAR(module_expsym_cmds, $1) \
++ _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \
++ _LT_AC_TAGVAR(exclude_expsyms, $1) \
++ _LT_AC_TAGVAR(include_expsyms, $1); do
+
+ case $var in
+- reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
+- old_postinstall_cmds | old_postuninstall_cmds | \
+- export_symbols_cmds | archive_cmds | archive_expsym_cmds | \
+- extract_expsyms_cmds | old_archive_from_expsyms_cmds | \
++ _LT_AC_TAGVAR(old_archive_cmds, $1) | \
++ _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \
++ _LT_AC_TAGVAR(archive_cmds, $1) | \
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \
++ _LT_AC_TAGVAR(module_cmds, $1) | \
++ _LT_AC_TAGVAR(module_expsym_cmds, $1) | \
++ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \
++ _LT_AC_TAGVAR(export_symbols_cmds, $1) | \
++ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+- finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
++ old_postinstall_cmds | old_postuninstall_cmds | \
++ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+@@ -2609,14 +4871,31 @@
+ esac
+ done
+
+- cat <<__EOF__ > "${ofile}T"
+-#! $SHELL
++ case $lt_echo in
++ *'\[$]0 --fallback-echo"')
++ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'`
++ ;;
++ esac
+
+-# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
++ifelse([$1], [],
++ [cfgfile="${ofile}T"
++ trap "$rm \"$cfgfile\"; exit 1" 1 2 15
++ $rm -f "$cfgfile"
++ AC_MSG_NOTICE([creating $ofile])],
++ [cfgfile="$ofile"])
++
++ cat <<__EOF__ >> "$cfgfile"
++ifelse([$1], [],
++[#! $SHELL
++
++# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+ # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+ # NOTE: Changes made to this file will be lost: look at ltmain.sh.
+ #
+-# Copyright (C) 1996-2000 Free Software Foundation, Inc.
++# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
++# Free Software Foundation, Inc.
++#
++# This file is part of GNU Libtool:
+ # Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+ #
+ # This program is free software; you can redistribute it and/or modify
+@@ -2638,17 +4917,21 @@
+ # configuration script generated by Autoconf, you may include it under
+ # the same distribution terms that you use for the rest of that program.
+
+-# A sed that does not truncate output.
++# A sed program that does not truncate output.
+ SED=$lt_SED
+
+ # Sed that helps us avoid accidentally triggering echo(1) options like -n.
+-Xsed="${SED} -e s/^X//"
++Xsed="$SED -e s/^X//"
+
+ # The HP-UX ksh and POSIX shell print the target directory to stdout
+ # if CDPATH is set.
+ if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+-# ### BEGIN LIBTOOL CONFIG
++# The names of the tagged configurations supported by this script.
++available_tags=
++
++# ### BEGIN LIBTOOL CONFIG],
++[# ### BEGIN LIBTOOL TAG CONFIG: $tagname])
+
+ # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+@@ -2662,7 +4945,10 @@
+ build_old_libs=$enable_static
+
+ # Whether or not to add -lc for building shared libraries.
+-build_libtool_need_lc=$need_lc
++build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)
++
++# Whether or not to disallow shared libs when runtime libs are static
++allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)
+
+ # Whether or not to optimize for fast installation.
+ fast_install=$enable_fast_install
+@@ -2678,14 +4964,20 @@
+ AR=$lt_AR
+ AR_FLAGS=$lt_AR_FLAGS
+
+-# The default C compiler.
+-CC=$lt_CC
++# A C compiler.
++LTCC=$lt_LTCC
++
++# A language-specific compiler.
++CC=$lt_[]_LT_AC_TAGVAR(compiler, $1)
+
+ # Is the compiler the GNU C compiler?
+-with_gcc=$GCC
++with_gcc=$_LT_AC_TAGVAR(GCC, $1)
++
++# An ERE matcher.
++EGREP=$lt_EGREP
+
+ # The linker used to build libraries.
+-LD=$lt_LD
++LD=$lt_[]_LT_AC_TAGVAR(LD, $1)
+
+ # Whether we need hard or soft links.
+ LN_S=$lt_LN_S
+@@ -2694,7 +4986,7 @@
+ NM=$lt_NM
+
+ # A symbol stripping program
+-STRIP=$STRIP
++STRIP=$lt_STRIP
+
+ # Used to examine libraries when file_magic_cmd begins "file"
+ MAGIC_CMD=$MAGIC_CMD
+@@ -2716,7 +5008,7 @@
+ reload_cmds=$lt_reload_cmds
+
+ # How to pass a linker flag through the compiler.
+-wl=$lt_wl
++wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+
+ # Object file suffix (normally "o").
+ objext="$ac_objext"
+@@ -2724,18 +5016,21 @@
+ # Old archive suffix (normally "a").
+ libext="$libext"
+
++# Shared library suffix (normally ".so").
++shrext_cmds='$shrext_cmds'
++
+ # Executable file suffix (normally "").
+ exeext="$exeext"
+
+ # Additional compiler flags for building library objects.
+-pic_flag=$lt_pic_flag
++pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
+ pic_mode=$pic_mode
+
+-# Does compiler simultaneously support -c and -o options?
+-compiler_c_o=$lt_compiler_c_o
++# What is the maximum length of a command?
++max_cmd_len=$lt_cv_sys_max_cmd_len
+
+-# Can we write directly to a .lo ?
+-compiler_o_lo=$lt_compiler_o_lo
++# Does compiler simultaneously support -c and -o options?
++compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)
+
+ # Must we lock files when doing compilation ?
+ need_locks=$lt_need_locks
+@@ -2756,946 +5051,1770 @@
+ dlopen_self_static=$enable_dlopen_self_static
+
+ # Compiler flag to prevent dynamic linking.
+-link_static_flag=$lt_link_static_flag
++link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1)
+
+ # Compiler flag to turn off builtin functions.
+-no_builtin_flag=$lt_no_builtin_flag
++no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)
+
+ # Compiler flag to allow reflexive dlopens.
+-export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
++export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)
+
+ # Compiler flag to generate shared objects directly from archives.
+-whole_archive_flag_spec=$lt_whole_archive_flag_spec
++whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1)
+
+ # Compiler flag to generate thread-safe objects.
+-thread_safe_flag_spec=$lt_thread_safe_flag_spec
++thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1)
++
++# Library versioning type.
++version_type=$version_type
++
++# Format of library name prefix.
++libname_spec=$lt_libname_spec
++
++# List of archive names. First name is the real one, the rest are links.
++# The last name is the one that the linker finds with -lNAME.
++library_names_spec=$lt_library_names_spec
++
++# The coded name of the library, if different from the real name.
++soname_spec=$lt_soname_spec
++
++# Commands used to build and install an old-style archive.
++RANLIB=$lt_RANLIB
++old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1)
++old_postinstall_cmds=$lt_old_postinstall_cmds
++old_postuninstall_cmds=$lt_old_postuninstall_cmds
++
++# Create an old-style archive from a shared archive.
++old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1)
++
++# Create a temporary old-style archive to link instead of a shared archive.
++old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)
++
++# Commands used to build and install a shared archive.
++archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1)
++archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1)
++postinstall_cmds=$lt_postinstall_cmds
++postuninstall_cmds=$lt_postuninstall_cmds
++
++# Commands used to build a loadable module (assumed same as above if empty)
++module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1)
++module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1)
++
++# Commands to strip libraries.
++old_striplib=$lt_old_striplib
++striplib=$lt_striplib
++
++# Dependencies to place before the objects being linked to create a
++# shared library.
++predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1)
++
++# Dependencies to place after the objects being linked to create a
++# shared library.
++postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1)
++
++# Dependencies to place before the objects being linked to create a
++# shared library.
++predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1)
++
++# Dependencies to place after the objects being linked to create a
++# shared library.
++postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1)
++
++# The library search path used internally by the compiler when linking
++# a shared library.
++compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1)
++
++# Method to check whether dependent libraries are shared objects.
++deplibs_check_method=$lt_deplibs_check_method
++
++# Command to use when deplibs_check_method == file_magic.
++file_magic_cmd=$lt_file_magic_cmd
++
++# Flag that allows shared libraries with undefined symbols to be built.
++allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1)
++
++# Flag that forces no undefined symbols.
++no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1)
++
++# Commands used to finish a libtool library installation in a directory.
++finish_cmds=$lt_finish_cmds
++
++# Same as above, but a single script fragment to be evaled but not shown.
++finish_eval=$lt_finish_eval
++
++# Take the output of nm and produce a listing of raw symbols and C names.
++global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
++
++# Transform the output of nm in a proper C declaration
++global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
++
++# Transform the output of nm in a C name address pair
++global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
++
++# This is the shared library runtime path variable.
++runpath_var=$runpath_var
++
++# This is the shared library path variable.
++shlibpath_var=$shlibpath_var
++
++# Is shlibpath searched before the hard-coded library search path?
++shlibpath_overrides_runpath=$shlibpath_overrides_runpath
++
++# How to hardcode a shared library path into an executable.
++hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1)
++
++# Whether we should hardcode library paths into libraries.
++hardcode_into_libs=$hardcode_into_libs
++
++# Flag to hardcode \$libdir into a binary during linking.
++# This must work even if \$libdir does not exist.
++hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)
++
++# If ld is used when linking, flag to hardcode \$libdir into
++# a binary during linking. This must work even if \$libdir does
++# not exist.
++hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)
++
++# Whether we need a single -rpath flag with a separated argument.
++hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1)
++
++# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
++# resulting binary.
++hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1)
++
++# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
++# resulting binary.
++hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1)
++
++# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
++# the resulting binary.
++hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)
++
++# Set to yes if building a shared library automatically hardcodes DIR into the library
++# and all subsequent libraries and executables linked against it.
++hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1)
++
++# Variables whose values should be saved in libtool wrapper scripts and
++# restored at relink time.
++variables_saved_for_relink="$variables_saved_for_relink"
++
++# Whether libtool must link a program against all its dependency libraries.
++link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1)
++
++# Compile-time system search path for libraries
++sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
++
++# Run-time system search path for libraries
++sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
++
++# Fix the shell variable \$srcfile for the compiler.
++fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)"
++
++# Set to yes if exported symbols are required.
++always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1)
++
++# The commands to list exported symbols.
++export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1)
++
++# The commands to extract the exported symbol list from a shared archive.
++extract_expsyms_cmds=$lt_extract_expsyms_cmds
++
++# Symbols that should not be listed in the preloaded symbols.
++exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1)
++
++# Symbols that must always be exported.
++include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1)
++
++ifelse([$1],[],
++[# ### END LIBTOOL CONFIG],
++[# ### END LIBTOOL TAG CONFIG: $tagname])
++
++__EOF__
++
++ifelse([$1],[], [
++ case $host_os in
++ aix3*)
++ cat <<\EOF >> "$cfgfile"
++
++# AIX sometimes has problems with the GCC collect2 program. For some
++# reason, if we set the COLLECT_NAMES environment variable, the problems
++# vanish in a puff of smoke.
++if test "X${COLLECT_NAMES+set}" != Xset; then
++ COLLECT_NAMES=
++ export COLLECT_NAMES
++fi
++EOF
++ ;;
++ esac
++
++ # We use sed instead of cat because bash on DJGPP gets confused if
++ # if finds mixed CR/LF and LF-only lines. Since sed operates in
++ # text mode, it properly converts lines to CR/LF. This bash problem
++ # is reportedly fixed, but why not run on old versions too?
++ sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
++
++ mv -f "$cfgfile" "$ofile" || \
++ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
++ chmod +x "$ofile"
++])
++else
++ # If there is no Makefile yet, we rely on a make rule to execute
++ # `config.status --recheck' to rerun these tests and create the
++ # libtool script then.
++ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
++ if test -f "$ltmain_in"; then
++ test -f Makefile && make "$ltmain"
++ fi
++fi
++])# AC_LIBTOOL_CONFIG
++
++
++# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME])
++# -------------------------------------------
++AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI],
++[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
++
++_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
++
++if test "$GCC" = yes; then
++ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
++
++ AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
++ lt_cv_prog_compiler_rtti_exceptions,
++ [-fno-rtti -fno-exceptions], [],
++ [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
++fi
++])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI
++
++
++# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
++# ---------------------------------
++AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE],
++[AC_REQUIRE([AC_CANONICAL_HOST])
++AC_REQUIRE([AC_PROG_NM])
++AC_REQUIRE([AC_OBJEXT])
++# Check for command to grab the raw symbol name followed by C symbol from nm.
++AC_MSG_CHECKING([command to parse $NM output from $compiler object])
++AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
++[
++# These are sane defaults that work on at least a few old systems.
++# [They come from Ultrix. What could be older than Ultrix?!! ;)]
++
++# Character class describing NM global symbol codes.
++symcode='[[BCDEGRST]]'
++
++# Regexp to match symbols that can be accessed directly from C.
++sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
++
++# Transform the above into a raw symbol and a C symbol.
++symxfrm='\1 \2\3 \3'
++
++# Transform an extracted symbol line into a proper C declaration
++lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
++
++# Transform an extracted symbol line into symbol name and symbol address
++lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
++
++# Define system-specific variables.
++case $host_os in
++aix*)
++ symcode='[[BCDT]]'
++ ;;
++cygwin* | mingw* | pw32*)
++ symcode='[[ABCDGISTW]]'
++ ;;
++hpux*) # Its linker distinguishes data from code symbols
++ if test "$host_cpu" = ia64; then
++ symcode='[[ABCDEGRST]]'
++ fi
++ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
++ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
++ ;;
++irix* | nonstopux*)
++ symcode='[[BCDEGRST]]'
++ ;;
++osf*)
++ symcode='[[BCDEGQRST]]'
++ ;;
++solaris* | sysv5*)
++ symcode='[[BDRT]]'
++ ;;
++sysv4)
++ symcode='[[DFNSTU]]'
++ ;;
++esac
++
++# Handle CRLF in mingw tool chain
++opt_cr=
++case $build_os in
++mingw*)
++ opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
++ ;;
++esac
+
+-# Library versioning type.
+-version_type=$version_type
++# If we're using GNU nm, then use its standard symbol codes.
++case `$NM -V 2>&1` in
++*GNU* | *'with BFD'*)
++ symcode='[[ABCDGIRSTW]]' ;;
++esac
+
+-# Format of library name prefix.
+-libname_spec=$lt_libname_spec
++# Try without a prefix undercore, then with it.
++for ac_symprfx in "" "_"; do
+
+-# List of archive names. First name is the real one, the rest are links.
+-# The last name is the one that the linker finds with -lNAME.
+-library_names_spec=$lt_library_names_spec
++ # Write the raw and C identifiers.
++ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'"
+
+-# The coded name of the library, if different from the real name.
+-soname_spec=$lt_soname_spec
++ # Check to see that the pipe works correctly.
++ pipe_works=no
+
+-# Commands used to build and install an old-style archive.
+-RANLIB=$lt_RANLIB
+-old_archive_cmds=$lt_old_archive_cmds
+-old_postinstall_cmds=$lt_old_postinstall_cmds
+-old_postuninstall_cmds=$lt_old_postuninstall_cmds
++ rm -f conftest*
++ cat > conftest.$ac_ext <<EOF
++#ifdef __cplusplus
++extern "C" {
++#endif
++char nm_test_var;
++void nm_test_func(){}
++#ifdef __cplusplus
++}
++#endif
++int main(){nm_test_var='a';nm_test_func();return(0);}
++EOF
+
+-# Create an old-style archive from a shared archive.
+-old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
++ if AC_TRY_EVAL(ac_compile); then
++ # Now try to grab the symbols.
++ nlist=conftest.nm
++ if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
++ # Try sorting and uniquifying the output.
++ if sort "$nlist" | uniq > "$nlist"T; then
++ mv -f "$nlist"T "$nlist"
++ else
++ rm -f "$nlist"T
++ fi
+
+-# Create a temporary old-style archive to link instead of a shared archive.
+-old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
++ # Make sure that we snagged all the symbols we need.
++ if grep ' nm_test_var$' "$nlist" >/dev/null; then
++ if grep ' nm_test_func$' "$nlist" >/dev/null; then
++ cat <<EOF > conftest.$ac_ext
++#ifdef __cplusplus
++extern "C" {
++#endif
+
+-# Commands used to build and install a shared archive.
+-archive_cmds=$lt_archive_cmds
+-archive_expsym_cmds=$lt_archive_expsym_cmds
+-postinstall_cmds=$lt_postinstall_cmds
+-postuninstall_cmds=$lt_postuninstall_cmds
++EOF
++ # Now generate the symbol file.
++ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
+
+-# Commands to strip libraries.
+-old_striplib=$lt_old_striplib
+-striplib=$lt_striplib
++ cat <<EOF >> conftest.$ac_ext
++#if defined (__STDC__) && __STDC__
++# define lt_ptr_t void *
++#else
++# define lt_ptr_t char *
++# define const
++#endif
+
+-# Method to check whether dependent libraries are shared objects.
+-deplibs_check_method=$lt_deplibs_check_method
++/* The mapping between symbol names and symbols. */
++const struct {
++ const char *name;
++ lt_ptr_t address;
++}
++lt_preloaded_symbols[[]] =
++{
++EOF
++ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
++ cat <<\EOF >> conftest.$ac_ext
++ {0, (lt_ptr_t) 0}
++};
+
+-# Command to use when deplibs_check_method == file_magic.
+-file_magic_cmd=$lt_file_magic_cmd
++#ifdef __cplusplus
++}
++#endif
++EOF
++ # Now try linking the two files.
++ mv conftest.$ac_objext conftstm.$ac_objext
++ lt_save_LIBS="$LIBS"
++ lt_save_CFLAGS="$CFLAGS"
++ LIBS="conftstm.$ac_objext"
++ CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
++ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
++ pipe_works=yes
++ fi
++ LIBS="$lt_save_LIBS"
++ CFLAGS="$lt_save_CFLAGS"
++ else
++ echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
++ fi
++ else
++ echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
++ fi
++ else
++ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
++ fi
++ else
++ echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
++ cat conftest.$ac_ext >&5
++ fi
++ rm -f conftest* conftst*
+
+-# Flag that allows shared libraries with undefined symbols to be built.
+-allow_undefined_flag=$lt_allow_undefined_flag
++ # Do not use the global_symbol_pipe unless it works.
++ if test "$pipe_works" = yes; then
++ break
++ else
++ lt_cv_sys_global_symbol_pipe=
++ fi
++done
++])
++if test -z "$lt_cv_sys_global_symbol_pipe"; then
++ lt_cv_sys_global_symbol_to_cdecl=
++fi
++if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
++ AC_MSG_RESULT(failed)
++else
++ AC_MSG_RESULT(ok)
++fi
++]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+
+-# Flag that forces no undefined symbols.
+-no_undefined_flag=$lt_no_undefined_flag
+
+-# Commands used to finish a libtool library installation in a directory.
+-finish_cmds=$lt_finish_cmds
++# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME])
++# ---------------------------------------
++AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC],
++[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)=
++_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
++_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=
+
+-# Same as above, but a single script fragment to be evaled but not shown.
+-finish_eval=$lt_finish_eval
++AC_MSG_CHECKING([for $compiler option to produce PIC])
++ ifelse([$1],[CXX],[
++ # C++ specific cases for pic, static, wl, etc.
++ if test "$GXX" = yes; then
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+-# Take the output of nm and produce a listing of raw symbols and C names.
+-global_symbol_pipe=$lt_global_symbol_pipe
++ case $host_os in
++ aix*)
++ # All AIX code is PIC.
++ if test "$host_cpu" = ia64; then
++ # AIX 5 now supports IA64 processor
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ fi
++ ;;
++ amigaos*)
++ # FIXME: we need at least 68020 code to build shared libraries, but
++ # adding the `-m68020' flag to GCC prevents building anything better,
++ # like `-m68040'.
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
++ ;;
++ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
++ # PIC is the default for these OSes.
++ ;;
++ mingw* | os2* | pw32*)
++ # This hack is so that the source file can tell whether it is being
++ # built for inclusion in a dll (and should export symbols for example).
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
++ ;;
++ darwin* | rhapsody*)
++ # PIC is the default on this platform
++ # Common symbols not allowed in MH_DYLIB files
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
++ ;;
++ *djgpp*)
++ # DJGPP does not support shared libraries at all
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
++ ;;
++ sysv4*MP*)
++ if test -d /usr/nec; then
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
++ fi
++ ;;
++ hpux*)
++ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
++ # not for PA HP-UX.
++ case "$host_cpu" in
++ hppa*64*|ia64*)
++ ;;
++ *)
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ ;;
++ esac
++ ;;
++ *)
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ ;;
++ esac
++ else
++ case $host_os in
++ aix4* | aix5*)
++ # All AIX code is PIC.
++ if test "$host_cpu" = ia64; then
++ # AIX 5 now supports IA64 processor
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ else
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
++ fi
++ ;;
++ chorus*)
++ case $cc_basename in
++ cxch68)
++ # Green Hills C++ Compiler
++ # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
++ ;;
++ esac
++ ;;
++ dgux*)
++ case $cc_basename in
++ ec++)
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ ;;
++ ghcx)
++ # Green Hills C++ Compiler
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ freebsd* | kfreebsd*-gnu)
++ # FreeBSD uses GNU C++
++ ;;
++ hpux9* | hpux10* | hpux11*)
++ case $cc_basename in
++ CC)
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive"
++ if test "$host_cpu" != ia64; then
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
++ fi
++ ;;
++ aCC)
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive"
++ case "$host_cpu" in
++ hppa*64*|ia64*)
++ # +Z the default
++ ;;
++ *)
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
++ ;;
++ esac
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ irix5* | irix6* | nonstopux*)
++ case $cc_basename in
++ CC)
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++ # CC pic flag -KPIC is the default.
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ linux*)
++ case $cc_basename in
++ KCC)
++ # KAI C++ Compiler
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ ;;
++ icpc)
++ # Intel C++
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
++ ;;
++ cxx)
++ # Compaq C++
++ # Make sure the PIC flag is empty. It appears that all Alpha
++ # Linux and Compaq Tru64 Unix objects are PIC.
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ lynxos*)
++ ;;
++ m88k*)
++ ;;
++ mvs*)
++ case $cc_basename in
++ cxx)
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
++ ;;
++ osf3* | osf4* | osf5*)
++ case $cc_basename in
++ KCC)
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
++ ;;
++ RCC)
++ # Rational C++ 2.4.1
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
++ ;;
++ cxx)
++ # Digital/Compaq C++
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ # Make sure the PIC flag is empty. It appears that all Alpha
++ # Linux and Compaq Tru64 Unix objects are PIC.
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ psos*)
++ ;;
++ sco*)
++ case $cc_basename in
++ CC)
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ solaris*)
++ case $cc_basename in
++ CC)
++ # Sun C++ 4.2, 5.x and Centerline C++
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
++ ;;
++ gcx)
++ # Green Hills C++ Compiler
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ sunos4*)
++ case $cc_basename in
++ CC)
++ # Sun C++ 4.x
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
++ lcc)
++ # Lucid
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ tandem*)
++ case $cc_basename in
++ NCC)
++ # NonStop-UX NCC 3.20
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ unixware*)
++ ;;
++ vxworks*)
++ ;;
++ *)
++ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
++ ;;
++ esac
++ fi
++],
++[
++ if test "$GCC" = yes; then
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+-# Transform the output of nm in a proper C declaration
+-global_symbol_to_cdecl=$lt_global_symbol_to_cdecl
++ case $host_os in
++ aix*)
++ # All AIX code is PIC.
++ if test "$host_cpu" = ia64; then
++ # AIX 5 now supports IA64 processor
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ fi
++ ;;
+
+-# Transform the output of nm in a C name address pair
+-global_symbol_to_c_name_address=$lt_global_symbol_to_c_name_address
++ amigaos*)
++ # FIXME: we need at least 68020 code to build shared libraries, but
++ # adding the `-m68020' flag to GCC prevents building anything better,
++ # like `-m68040'.
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
++ ;;
+
+-# This is the shared library runtime path variable.
+-runpath_var=$runpath_var
++ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
++ # PIC is the default for these OSes.
++ ;;
+
+-# This is the shared library path variable.
+-shlibpath_var=$shlibpath_var
++ mingw* | pw32* | os2*)
++ # This hack is so that the source file can tell whether it is being
++ # built for inclusion in a dll (and should export symbols for example).
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
++ ;;
+
+-# Is shlibpath searched before the hard-coded library search path?
+-shlibpath_overrides_runpath=$shlibpath_overrides_runpath
++ darwin* | rhapsody*)
++ # PIC is the default on this platform
++ # Common symbols not allowed in MH_DYLIB files
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
++ ;;
+
+-# How to hardcode a shared library path into an executable.
+-hardcode_action=$hardcode_action
++ msdosdjgpp*)
++ # Just because we use GCC doesn't mean we suddenly get shared libraries
++ # on systems that don't support them.
++ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
++ enable_shared=no
++ ;;
+
+-# Whether we should hardcode library paths into libraries.
+-hardcode_into_libs=$hardcode_into_libs
++ sysv4*MP*)
++ if test -d /usr/nec; then
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
++ fi
++ ;;
+
+-# Flag to hardcode \$libdir into a binary during linking.
+-# This must work even if \$libdir does not exist.
+-hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
++ hpux*)
++ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
++ # not for PA HP-UX.
++ case "$host_cpu" in
++ hppa*64*|ia64*)
++ # +Z the default
++ ;;
++ *)
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ ;;
++ esac
++ ;;
+
+-# Whether we need a single -rpath flag with a separated argument.
+-hardcode_libdir_separator=$lt_hardcode_libdir_separator
++ *)
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ ;;
++ esac
++ else
++ # PORTME Check for flag to pass linker flags through the system compiler.
++ case $host_os in
++ aix*)
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ if test "$host_cpu" = ia64; then
++ # AIX 5 now supports IA64 processor
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ else
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
++ fi
++ ;;
+
+-# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+-# resulting binary.
+-hardcode_direct=$hardcode_direct
++ mingw* | pw32* | os2*)
++ # This hack is so that the source file can tell whether it is being
++ # built for inclusion in a dll (and should export symbols for example).
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
++ ;;
+
+-# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+-# resulting binary.
+-hardcode_minus_L=$hardcode_minus_L
++ hpux9* | hpux10* | hpux11*)
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
++ # not for PA HP-UX.
++ case "$host_cpu" in
++ hppa*64*|ia64*)
++ # +Z the default
++ ;;
++ *)
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
++ ;;
++ esac
++ # Is there a better lt_prog_compiler_static that works with the bundled CC?
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
++ ;;
+
+-# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+-# the resulting binary.
+-hardcode_shlibpath_var=$hardcode_shlibpath_var
++ irix5* | irix6* | nonstopux*)
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ # PIC (with -KPIC) is the default.
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++ ;;
+
+-# Variables whose values should be saved in libtool wrapper scripts and
+-# restored at relink time.
+-variables_saved_for_relink="$variables_saved_for_relink"
++ newsos6)
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
+
+-# Whether libtool must link a program against all its dependency libraries.
+-link_all_deplibs=$link_all_deplibs
++ linux*)
++ case $CC in
++ icc* | ecc*)
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
++ ;;
++ ccc*)
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ # All Alpha code is PIC.
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++ ;;
++ esac
++ ;;
+
+-# Compile-time system search path for libraries
+-sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
++ osf3* | osf4* | osf5*)
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ # All OSF/1 code is PIC.
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++ ;;
+
+-# Run-time system search path for libraries
+-sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
++ sco3.2v5*)
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kpic'
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-dn'
++ ;;
+
+-# Fix the shell variable \$srcfile for the compiler.
+-fix_srcfile_path="$fix_srcfile_path"
++ solaris*)
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
+
+-# Set to yes if exported symbols are required.
+-always_export_symbols=$always_export_symbols
++ sunos4*)
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
+
+-# The commands to list exported symbols.
+-export_symbols_cmds=$lt_export_symbols_cmds
++ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
+
+-# The commands to extract the exported symbol list from a shared archive.
+-extract_expsyms_cmds=$lt_extract_expsyms_cmds
++ sysv4*MP*)
++ if test -d /usr/nec ;then
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ fi
++ ;;
+
+-# Symbols that should not be listed in the preloaded symbols.
+-exclude_expsyms=$lt_exclude_expsyms
++ uts4*)
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
+
+-# Symbols that must always be exported.
+-include_expsyms=$lt_include_expsyms
++ *)
++ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
++ ;;
++ esac
++ fi
++])
++AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)])
+
+-# ### END LIBTOOL CONFIG
++#
++# Check to make sure the PIC flag actually works.
++#
++if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then
++ AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works],
++ _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1),
++ [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [],
++ [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in
++ "" | " "*) ;;
++ *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;;
++ esac],
++ [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
++ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
++fi
++case "$host_os" in
++ # For platforms which do not support PIC, -DPIC is meaningless:
++ *djgpp*)
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
++ ;;
++ *)
++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])"
++ ;;
++esac
++])
+
+-__EOF__
+
++# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME])
++# ------------------------------------
++# See if the linker supports building shared libraries.
++AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS],
++[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
++ifelse([$1],[CXX],[
++ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ case $host_os in
+- aix3*)
+- cat <<\EOF >> "${ofile}T"
+-
+-# AIX sometimes has problems with the GCC collect2 program. For some
+-# reason, if we set the COLLECT_NAMES environment variable, the problems
+-# vanish in a puff of smoke.
+-if test "X${COLLECT_NAMES+set}" != Xset; then
+- COLLECT_NAMES=
+- export COLLECT_NAMES
+-fi
+-EOF
++ aix4* | aix5*)
++ # If we're using GNU nm, then we don't want the "-C" option.
++ # -C means demangle to AIX nm, but means don't demangle with GNU nm
++ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
++ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
++ else
++ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
++ fi
+ ;;
++ pw32*)
++ _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
++ ;;
++ cygwin* | mingw*)
++ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols'
++ ;;
++ linux*)
++ _LT_AC_TAGVAR(link_all_deplibs, $1)=no
++ ;;
++ *)
++ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
++ ;;
+ esac
++],[
++ runpath_var=
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=
++ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
++ _LT_AC_TAGVAR(archive_cmds, $1)=
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)=
++ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)=
++ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)=
++ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
++ _LT_AC_TAGVAR(thread_safe_flag_spec, $1)=
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
++ _LT_AC_TAGVAR(hardcode_direct, $1)=no
++ _LT_AC_TAGVAR(hardcode_minus_L, $1)=no
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
++ _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
++ _LT_AC_TAGVAR(hardcode_automatic, $1)=no
++ _LT_AC_TAGVAR(module_cmds, $1)=
++ _LT_AC_TAGVAR(module_expsym_cmds, $1)=
++ _LT_AC_TAGVAR(always_export_symbols, $1)=no
++ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
++ # include_expsyms should be a list of space-separated symbols to be *always*
++ # included in the symbol list
++ _LT_AC_TAGVAR(include_expsyms, $1)=
++ # exclude_expsyms can be an extended regexp of symbols to exclude
++ # it will be wrapped by ` (' and `)$', so one must not match beginning or
++ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
++ # as well as any symbol that contains `d'.
++ _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_"
++ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
++ # platforms (ab)use it in PIC code, but their linkers get confused if
++ # the symbol is explicitly referenced. Since portable code cannot
++ # rely on this symbol name, it's probably fine to never include it in
++ # preloaded symbol tables.
++ extract_expsyms_cmds=
+
+ case $host_os in
+- cygwin* | mingw* | pw32* | os2*)
+- cat <<'EOF' >> "${ofile}T"
+- # This is a source program that is used to create dlls on Windows
+- # Don't remove nor modify the starting and closing comments
+-# /* ltdll.c starts here */
+-# #define WIN32_LEAN_AND_MEAN
+-# #include <windows.h>
+-# #undef WIN32_LEAN_AND_MEAN
+-# #include <stdio.h>
+-#
+-# #ifndef __CYGWIN__
+-# # ifdef __CYGWIN32__
+-# # define __CYGWIN__ __CYGWIN32__
+-# # endif
+-# #endif
+-#
+-# #ifdef __cplusplus
+-# extern "C" {
+-# #endif
+-# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+-# #ifdef __cplusplus
+-# }
+-# #endif
+-#
+-# #ifdef __CYGWIN__
+-# #include <cygwin/cygwin_dll.h>
+-# DECLARE_CYGWIN_DLL( DllMain );
+-# #endif
+-# HINSTANCE __hDllInstance_base;
+-#
+-# BOOL APIENTRY
+-# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+-# {
+-# __hDllInstance_base = hInst;
+-# return TRUE;
+-# }
+-# /* ltdll.c ends here */
+- # This is a source program that is used to create import libraries
+- # on Windows for dlls which lack them. Don't remove nor modify the
+- # starting and closing comments
+-# /* impgen.c starts here */
+-# /* Copyright (C) 1999-2000 Free Software Foundation, Inc.
+-#
+-# This file is part of GNU libtool.
+-#
+-# 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> /* for printf() */
+-# #include <unistd.h> /* for open(), lseek(), read() */
+-# #include <fcntl.h> /* for O_RDONLY, O_BINARY */
+-# #include <string.h> /* for strdup() */
+-#
+-# /* O_BINARY isn't required (or even defined sometimes) under Unix */
+-# #ifndef O_BINARY
+-# #define O_BINARY 0
+-# #endif
+-#
+-# static unsigned int
+-# pe_get16 (fd, offset)
+-# int fd;
+-# int offset;
+-# {
+-# unsigned char b[2];
+-# lseek (fd, offset, SEEK_SET);
+-# read (fd, b, 2);
+-# return b[0] + (b[1]<<8);
+-# }
+-#
+-# static unsigned int
+-# pe_get32 (fd, offset)
+-# int fd;
+-# int offset;
+-# {
+-# unsigned char b[4];
+-# lseek (fd, offset, SEEK_SET);
+-# read (fd, b, 4);
+-# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+-# }
+-#
+-# static unsigned int
+-# pe_as32 (ptr)
+-# void *ptr;
+-# {
+-# unsigned char *b = ptr;
+-# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+-# }
+-#
+-# int
+-# main (argc, argv)
+-# int argc;
+-# char *argv[];
+-# {
+-# int dll;
+-# unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
+-# unsigned long export_rva, export_size, nsections, secptr, expptr;
+-# unsigned long name_rvas, nexp;
+-# unsigned char *expdata, *erva;
+-# char *filename, *dll_name;
+-#
+-# filename = argv[1];
+-#
+-# dll = open(filename, O_RDONLY|O_BINARY);
+-# if (dll < 1)
+-# return 1;
+-#
+-# dll_name = filename;
+-#
+-# for (i=0; filename[i]; i++)
+-# if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':')
+-# dll_name = filename + i +1;
+-#
+-# pe_header_offset = pe_get32 (dll, 0x3c);
+-# opthdr_ofs = pe_header_offset + 4 + 20;
+-# num_entries = pe_get32 (dll, opthdr_ofs + 92);
+-#
+-# if (num_entries < 1) /* no exports */
+-# return 1;
+-#
+-# export_rva = pe_get32 (dll, opthdr_ofs + 96);
+-# export_size = pe_get32 (dll, opthdr_ofs + 100);
+-# nsections = pe_get16 (dll, pe_header_offset + 4 +2);
+-# secptr = (pe_header_offset + 4 + 20 +
+-# pe_get16 (dll, pe_header_offset + 4 + 16));
+-#
+-# expptr = 0;
+-# for (i = 0; i < nsections; i++)
+-# {
+-# char sname[8];
+-# unsigned long secptr1 = secptr + 40 * i;
+-# unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
+-# unsigned long vsize = pe_get32 (dll, secptr1 + 16);
+-# unsigned long fptr = pe_get32 (dll, secptr1 + 20);
+-# lseek(dll, secptr1, SEEK_SET);
+-# read(dll, sname, 8);
+-# if (vaddr <= export_rva && vaddr+vsize > export_rva)
+-# {
+-# expptr = fptr + (export_rva - vaddr);
+-# if (export_rva + export_size > vaddr + vsize)
+-# export_size = vsize - (export_rva - vaddr);
+-# break;
+-# }
+-# }
+-#
+-# expdata = (unsigned char*)malloc(export_size);
+-# lseek (dll, expptr, SEEK_SET);
+-# read (dll, expdata, export_size);
+-# erva = expdata - export_rva;
+-#
+-# nexp = pe_as32 (expdata+24);
+-# name_rvas = pe_as32 (expdata+32);
+-#
+-# printf ("EXPORTS\n");
+-# for (i = 0; i<nexp; i++)
+-# {
+-# unsigned long name_rva = pe_as32 (erva+name_rvas+i*4);
+-# printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i);
+-# }
+-#
+-# return 0;
+-# }
+-# /* impgen.c ends here */
+-
+-EOF
++ cygwin* | mingw* | pw32*)
++ # FIXME: the MSVC++ port hasn't been tested in a loooong time
++ # When not using gcc, we currently assume that we are using
++ # Microsoft Visual C++.
++ if test "$GCC" != yes; then
++ with_gnu_ld=no
++ fi
++ ;;
++ openbsd*)
++ with_gnu_ld=no
+ ;;
+ esac
+
+- # We use sed instead of cat because bash on DJGPP gets confused if
+- # if finds mixed CR/LF and LF-only lines. Since sed operates in
+- # text mode, it properly converts lines to CR/LF. This bash problem
+- # is reportedly fixed, but why not run on old versions too?
+- sed '$q' "$ltmain" >> "${ofile}T" || (rm -f "${ofile}T"; exit 1)
++ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
++ if test "$with_gnu_ld" = yes; then
++ # If archive_cmds runs LD, not CC, wlarc should be empty
++ wlarc='${wl}'
+
+- mv -f "${ofile}T" "$ofile" || \
+- (rm -f "$ofile" && cp "${ofile}T" "$ofile" && rm -f "${ofile}T")
+- chmod +x "$ofile"
+-fi
++ # See if GNU ld supports shared libraries.
++ case $host_os in
++ aix3* | aix4* | aix5*)
++ # On AIX/PPC, the GNU linker is very broken
++ if test "$host_cpu" != ia64; then
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ cat <<EOF 1>&2
+
+-])# _LT_AC_LTCONFIG_HACK
++*** Warning: the GNU linker, at least up to release 2.9.1, is reported
++*** to be unable to reliably create shared libraries on AIX.
++*** Therefore, libtool is disabling shared libraries support. If you
++*** really care for shared libraries, you may want to modify your PATH
++*** so that a non-GNU linker is found, and then restart.
+
+-# AC_LIBTOOL_DLOPEN - enable checks for dlopen support
+-AC_DEFUN([AC_LIBTOOL_DLOPEN], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])])
++EOF
++ fi
++ ;;
+
+-# AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's
+-AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])])
++ amigaos*)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
++
++ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
++ # that the semantics of dynamic libraries on AmigaOS, at least up
++ # to version 4, is to share data among multiple programs linked
++ # with the same dynamic library. Since this doesn't match the
++ # behavior of shared libraries on other platforms, we can't use
++ # them.
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
+
+-# AC_ENABLE_SHARED - implement the --enable-shared flag
+-# Usage: AC_ENABLE_SHARED[(DEFAULT)]
+-# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to
+-# `yes'.
+-AC_DEFUN([AC_ENABLE_SHARED],
+-[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+-AC_ARG_ENABLE(shared,
+-changequote(<<, >>)dnl
+-<< --enable-shared[=PKGS] build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT],
+-changequote([, ])dnl
+-[p=${PACKAGE-default}
+-case $enableval in
+-yes) enable_shared=yes ;;
+-no) enable_shared=no ;;
+-*)
+- enable_shared=no
+- # Look at the argument we got. We use all the common list separators.
+- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+- for pkg in $enableval; do
+- if test "X$pkg" = "X$p"; then
+- enable_shared=yes
+- fi
+- done
+- IFS="$ac_save_ifs"
+- ;;
+-esac],
+-enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl
+-])
++ beos*)
++ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
++ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
++ # support --undefined. This deserves some investigation. FIXME
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
++ else
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
+
+-# AC_DISABLE_SHARED - set the default shared flag to --disable-shared
+-AC_DEFUN([AC_DISABLE_SHARED],
+-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+-AC_ENABLE_SHARED(no)])
++ cygwin* | mingw* | pw32*)
++ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
++ # as there is no search path for DLLs.
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
++ _LT_AC_TAGVAR(always_export_symbols, $1)=no
++ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols'
++
++ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
++ # If the export-symbols file already is a .def file (1st line
++ # is EXPORTS), use it as is; otherwise, prepend...
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
++ cp $export_symbols $output_objdir/$soname.def;
++ else
++ echo EXPORTS > $output_objdir/$soname.def;
++ cat $export_symbols >> $output_objdir/$soname.def;
++ fi~
++ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
++ else
++ ld_shlibs=no
++ fi
++ ;;
+
+-# AC_ENABLE_STATIC - implement the --enable-static flag
+-# Usage: AC_ENABLE_STATIC[(DEFAULT)]
+-# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to
+-# `yes'.
+-AC_DEFUN([AC_ENABLE_STATIC],
+-[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+-AC_ARG_ENABLE(static,
+-changequote(<<, >>)dnl
+-<< --enable-static[=PKGS] build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT],
+-changequote([, ])dnl
+-[p=${PACKAGE-default}
+-case $enableval in
+-yes) enable_static=yes ;;
+-no) enable_static=no ;;
+-*)
+- enable_static=no
+- # Look at the argument we got. We use all the common list separators.
+- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+- for pkg in $enableval; do
+- if test "X$pkg" = "X$p"; then
+- enable_static=yes
+- fi
+- done
+- IFS="$ac_save_ifs"
+- ;;
+-esac],
+-enable_static=AC_ENABLE_STATIC_DEFAULT)dnl
+-])
++ netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
++ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
++ wlarc=
++ else
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
++ fi
++ ;;
+
+-# AC_DISABLE_STATIC - set the default static flag to --disable-static
+-AC_DEFUN([AC_DISABLE_STATIC],
+-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+-AC_ENABLE_STATIC(no)])
++ solaris* | sysv5*)
++ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ cat <<EOF 1>&2
++
++*** Warning: The releases 2.8.* of the GNU linker cannot reliably
++*** create shared libraries on Solaris systems. Therefore, libtool
++*** is disabling shared libraries support. We urge you to upgrade GNU
++*** binutils to release 2.9.1 or newer. Another option is to modify
++*** your PATH or compiler configuration so that the native linker is
++*** used, and then restart.
+
++EOF
++ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
++ else
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
+
+-# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag
+-# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)]
+-# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to
+-# `yes'.
+-AC_DEFUN([AC_ENABLE_FAST_INSTALL],
+-[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+-AC_ARG_ENABLE(fast-install,
+-changequote(<<, >>)dnl
+-<< --enable-fast-install[=PKGS] optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT],
+-changequote([, ])dnl
+-[p=${PACKAGE-default}
+-case $enableval in
+-yes) enable_fast_install=yes ;;
+-no) enable_fast_install=no ;;
+-*)
+- enable_fast_install=no
+- # Look at the argument we got. We use all the common list separators.
+- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+- for pkg in $enableval; do
+- if test "X$pkg" = "X$p"; then
+- enable_fast_install=yes
++ sunos4*)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
++ wlarc=
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++
++ linux*)
++ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
++ tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
++ _LT_AC_TAGVAR(archive_cmds, $1)="$tmp_archive_cmds"
++ supports_anon_versioning=no
++ case `$LD -v 2>/dev/null` in
++ *\ [01].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
++ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
++ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
++ *\ 2.11.*) ;; # other 2.11 versions
++ *) supports_anon_versioning=yes ;;
++ esac
++ if test $supports_anon_versioning = yes; then
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~
++cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
++$echo "local: *; };" >> $output_objdir/$libname.ver~
++ $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
++ else
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="$tmp_archive_cmds"
++ fi
++ _LT_AC_TAGVAR(link_all_deplibs, $1)=no
++ else
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+- done
+- IFS="$ac_save_ifs"
+- ;;
+-esac],
+-enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl
+-])
++ ;;
+
+-# AC_DISABLE_FAST_INSTALL - set the default to --disable-fast-install
+-AC_DEFUN([AC_DISABLE_FAST_INSTALL],
+-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+-AC_ENABLE_FAST_INSTALL(no)])
++ *)
++ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
++ else
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
++ esac
++
++ if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = yes; then
++ runpath_var=LD_RUN_PATH
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
++ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
++ # ancient GNU ld didn't support --whole-archive et. al.
++ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
++ else
++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
++ fi
++ fi
++ else
++ # PORTME fill in a description of your system's linker (not GNU ld)
++ case $host_os in
++ aix3*)
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
++ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
++ # Note: this linker hardcodes the directories in LIBPATH if there
++ # are no directories specified by -L.
++ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
++ if test "$GCC" = yes && test -z "$link_static_flag"; then
++ # Neither direct hardcoding nor static linking is supported with a
++ # broken collect2.
++ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
++ fi
++ ;;
++
++ aix4* | aix5*)
++ if test "$host_cpu" = ia64; then
++ # On IA64, the linker does run time linking by default, so we don't
++ # have to do anything special.
++ aix_use_runtimelinking=no
++ exp_sym_flag='-Bexport'
++ no_entry_flag=""
++ else
++ # If we're using GNU nm, then we don't want the "-C" option.
++ # -C means demangle to AIX nm, but means don't demangle with GNU nm
++ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
++ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
++ else
++ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
++ fi
++ aix_use_runtimelinking=no
+
+-# AC_LIBTOOL_PICMODE - implement the --with-pic flag
+-# Usage: AC_LIBTOOL_PICMODE[(MODE)]
+-# Where MODE is either `yes' or `no'. If omitted, it defaults to
+-# `both'.
+-AC_DEFUN([AC_LIBTOOL_PICMODE],
+-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+-pic_mode=ifelse($#,1,$1,default)])
++ # Test if we are trying to use run time linking or normal
++ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
++ # need to do runtime linking.
++ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
++ for ld_flag in $LDFLAGS; do
++ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
++ aix_use_runtimelinking=yes
++ break
++ fi
++ done
++ esac
+
++ exp_sym_flag='-bexport'
++ no_entry_flag='-bnoentry'
++ fi
+
+-# AC_PATH_TOOL_PREFIX - find a file program which can recognise shared library
+-AC_DEFUN([AC_PATH_TOOL_PREFIX],
+-[AC_MSG_CHECKING([for $1])
+-AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+-[case $MAGIC_CMD in
+- /*)
+- lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+- ;;
+- ?:/*)
+- lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path.
+- ;;
+- *)
+- ac_save_MAGIC_CMD="$MAGIC_CMD"
+- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+-dnl $ac_dummy forces splitting on constant user-supplied paths.
+-dnl POSIX.2 word splitting is done only on the output of word expansions,
+-dnl not every word. This closes a longstanding sh security hole.
+- ac_dummy="ifelse([$2], , $PATH, [$2])"
+- for ac_dir in $ac_dummy; do
+- test -z "$ac_dir" && ac_dir=.
+- if test -f $ac_dir/$1; then
+- lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+- if test -n "$file_magic_test_file"; then
+- case $deplibs_check_method in
+- "file_magic "*)
+- file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+- MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+- if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+- egrep "$file_magic_regex" > /dev/null; then
+- :
++ # When large executables or shared objects are built, AIX ld can
++ # have problems creating the table of contents. If linking a library
++ # or program results in "error TOC overflow" add -mminimal-toc to
++ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
++ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
++
++ _LT_AC_TAGVAR(archive_cmds, $1)=''
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
++ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
++
++ if test "$GCC" = yes; then
++ case $host_os in aix4.[012]|aix4.[012].*)
++ # We only want to do this on AIX 4.2 and lower, the check
++ # below for broken collect2 doesn't work under 4.3+
++ collect2name=`${CC} -print-prog-name=collect2`
++ if test -f "$collect2name" && \
++ strings "$collect2name" | grep resolve_lib_name >/dev/null
++ then
++ # We have reworked collect2
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ else
+- cat <<EOF 1>&2
+-
+-*** Warning: the command libtool uses to detect shared libraries,
+-*** $file_magic_cmd, produces output that libtool cannot recognize.
+-*** The result is that libtool may fail to recognize shared libraries
+-*** as such. This will affect the creation of libtool libraries that
+-*** depend on shared libraries, but programs linked with such libtool
+-*** libraries will work regardless of this problem. Nevertheless, you
+-*** may want to report the problem to your system manager and/or to
+-*** bug-libtool@gnu.org
+-
+-EOF
+- fi ;;
++ # We have old collect2
++ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
++ # It fails to find uninstalled libraries when the uninstalled
++ # path is not listed in the libpath. Setting hardcode_minus_L
++ # to unsupported forces relinking
++ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
++ fi
+ esac
++ shared_flag='-shared'
++ else
++ # not using gcc
++ if test "$host_cpu" = ia64; then
++ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
++ # chokes on -Wl,-G. The following line is correct:
++ shared_flag='-G'
++ else
++ if test "$aix_use_runtimelinking" = yes; then
++ shared_flag='${wl}-G'
++ else
++ shared_flag='${wl}-bM:SRE'
++ fi
++ fi
+ fi
+- break
+- fi
+- done
+- IFS="$ac_save_ifs"
+- MAGIC_CMD="$ac_save_MAGIC_CMD"
+- ;;
+-esac])
+-MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+-if test -n "$MAGIC_CMD"; then
+- AC_MSG_RESULT($MAGIC_CMD)
+-else
+- AC_MSG_RESULT(no)
+-fi
+-])
+
++ # It seems that -bexpall does not export symbols beginning with
++ # underscore (_), so it is better to generate a list of symbols to export.
++ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
++ if test "$aix_use_runtimelinking" = yes; then
++ # Warning - without using the other runtime loading flags (-brtl),
++ # -berok will link without error, but may produce a broken library.
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
++ # Determine the default libpath from the value encoded in an empty executable.
++ _LT_AC_SYS_LIBPATH_AIX
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
++ else
++ if test "$host_cpu" = ia64; then
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
++ else
++ # Determine the default libpath from the value encoded in an empty executable.
++ _LT_AC_SYS_LIBPATH_AIX
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
++ # Warning - without using the other run time loading flags,
++ # -berok will link without error, but may produce a broken library.
++ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
++ # -bexpall does not export symbols beginning with underscore (_)
++ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
++ # Exported symbols can be pulled into shared objects from archives
++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' '
++ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
++ # This is similar to how AIX traditionally builds it's shared libraries.
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
++ fi
++ fi
++ ;;
+
+-# AC_PATH_MAGIC - find a file program which can recognise a shared library
+-AC_DEFUN([AC_PATH_MAGIC],
+-[AC_REQUIRE([AC_CHECK_TOOL_PREFIX])dnl
+-AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin:$PATH)
+-if test -z "$lt_cv_path_MAGIC_CMD"; then
+- if test -n "$ac_tool_prefix"; then
+- AC_PATH_TOOL_PREFIX(file, /usr/bin:$PATH)
+- else
+- MAGIC_CMD=:
+- fi
+-fi
+-])
++ amigaos*)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
++ # see comment about different semantics on the GNU ld section
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
+
++ bsdi4*)
++ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
++ ;;
+
+-# AC_PROG_LD - find the path to the GNU or non-GNU linker
+-AC_DEFUN([AC_PROG_LD],
+-[AC_ARG_WITH(gnu-ld,
+-[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
+-test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+-AC_REQUIRE([AC_PROG_CC])dnl
+-AC_REQUIRE([AC_CANONICAL_HOST])dnl
+-AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+-AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl
+-ac_prog=ld
+-if test "$GCC" = yes; then
+- # Check if gcc -print-prog-name=ld gives a path.
+- AC_MSG_CHECKING([for ld used by GCC])
+- case $host in
+- *-*-mingw*)
+- # gcc leaves a trailing carriage return which upsets mingw
+- ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+- *)
+- ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+- esac
+- case $ac_prog in
+- # Accept absolute paths.
+- [[\\/]]* | [[A-Za-z]]:[[\\/]]*)
+- re_direlt='/[[^/]][[^/]]*/\.\./'
+- # Canonicalize the path of ld
+- ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+- while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+- ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+- done
+- test -z "$LD" && LD="$ac_prog"
++ cygwin* | mingw* | pw32*)
++ # When not using gcc, we currently assume that we are using
++ # Microsoft Visual C++.
++ # hardcode_libdir_flag_spec is actually meaningless, as there is
++ # no search path for DLLs.
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
++ # Tell ltmain to make .lib files, not .a files.
++ libext=lib
++ # Tell ltmain to make .dll files, not .so files.
++ shrext_cmds=".dll"
++ # FIXME: Setting linknames here is a bad hack.
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
++ # The linker will automatically build a .lib file if we build a DLL.
++ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true'
++ # FIXME: Should let the user specify the lib program.
++ _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs'
++ fix_srcfile_path='`cygpath -w "$srcfile"`'
++ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+- "")
+- # If it fails, then pretend we aren't using GCC.
+- ac_prog=ld
+- ;;
+- *)
+- # If it is relative, then search for the first ld in PATH.
+- with_gnu_ld=unknown
+- ;;
+- esac
+-elif test "$with_gnu_ld" = yes; then
+- AC_MSG_CHECKING([for GNU ld])
+-else
+- AC_MSG_CHECKING([for non-GNU ld])
+-fi
+-AC_CACHE_VAL(lt_cv_path_LD,
+-[if test -z "$LD"; then
+- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+- for ac_dir in $PATH; do
+- test -z "$ac_dir" && ac_dir=.
+- if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+- lt_cv_path_LD="$ac_dir/$ac_prog"
+- # Check to see if the program is GNU ld. I'd rather use --version,
+- # but apparently some GNU ld's only accept -v.
+- # Break only if it was the GNU/non-GNU ld that we prefer.
+- if "$lt_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+- test "$with_gnu_ld" != no && break
++
++ darwin* | rhapsody*)
++ if test "$GXX" = yes ; then
++ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
++ case "$host_os" in
++ rhapsody* | darwin1.[[012]])
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress'
++ ;;
++ *) # Darwin 1.3 on
++ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress'
+ else
+- test "$with_gnu_ld" != yes && break
++ case ${MACOSX_DEPLOYMENT_TARGET} in
++ 10.[[012]])
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress'
++ ;;
++ 10.*)
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup'
++ ;;
++ esac
+ fi
++ ;;
++ esac
++ lt_int_apple_cc_single_mod=no
++ output_verbose_link_cmd='echo'
++ if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then
++ lt_int_apple_cc_single_mod=yes
++ fi
++ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
++ else
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
++ fi
++ _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
++ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
++ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
++ else
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
++ fi
++ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
++ _LT_AC_TAGVAR(hardcode_direct, $1)=no
++ _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience'
++ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
++ else
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+- done
+- IFS="$ac_save_ifs"
+-else
+- lt_cv_path_LD="$LD" # Let the user override the test with a path.
+-fi])
+-LD="$lt_cv_path_LD"
+-if test -n "$LD"; then
+- AC_MSG_RESULT($LD)
+-else
+- AC_MSG_RESULT(no)
+-fi
+-test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+-AC_PROG_LD_GNU
+-])
++ ;;
+
+-# AC_PROG_LD_GNU -
+-AC_DEFUN([AC_PROG_LD_GNU],
+-[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+-[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+-if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+- lt_cv_prog_gnu_ld=yes
+-else
+- lt_cv_prog_gnu_ld=no
+-fi])
+-with_gnu_ld=$lt_cv_prog_gnu_ld
+-])
++ dgux*)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
+
+-# AC_PROG_LD_RELOAD_FLAG - find reload flag for linker
+-# -- PORTME Some linkers may need a different reload flag.
+-AC_DEFUN([AC_PROG_LD_RELOAD_FLAG],
+-[AC_CACHE_CHECK([for $LD option to reload object files], lt_cv_ld_reload_flag,
+-[lt_cv_ld_reload_flag='-r'])
+-reload_flag=$lt_cv_ld_reload_flag
+-test -n "$reload_flag" && reload_flag=" $reload_flag"
+-])
++ freebsd1*)
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
+
+-# AC_DEPLIBS_CHECK_METHOD - how to check for library dependencies
+-# -- PORTME fill in with the dynamic library characteristics
+-AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
+-[AC_CACHE_CHECK([how to recognise dependent libraries],
+-lt_cv_deplibs_check_method,
+-[lt_cv_file_magic_cmd='$MAGIC_CMD'
+-lt_cv_file_magic_test_file=
+-lt_cv_deplibs_check_method='unknown'
+-# Need to set the preceding variable on all platforms that support
+-# interlibrary dependencies.
+-# 'none' -- dependencies not supported.
+-# `unknown' -- same as none, but documents that we really don't know.
+-# 'pass_all' -- all dependencies passed with no checks.
+-# 'test_compile' -- check by making test program.
+-# 'file_magic [[regex]]' -- check by looking for files in library path
+-# which responds to the $file_magic_cmd with a given egrep regex.
+-# If you have `file' or equivalent on your system and you're not sure
+-# whether `pass_all' will *always* work, you probably want this one.
++ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
++ # support. Future versions do this automatically, but an explicit c++rt0.o
++ # does not break anything, and helps significantly (at the cost of a little
++ # extra space).
++ freebsd2.2*)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
+
+-case $host_os in
+-aix4* | aix5*)
+- lt_cv_deplibs_check_method=pass_all
+- ;;
++ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
++ freebsd2*)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
++ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
+
+-beos*)
+- lt_cv_deplibs_check_method=pass_all
+- ;;
++ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
++ freebsd* | kfreebsd*-gnu)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
+
+-bsdi4*)
+- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+- lt_cv_file_magic_cmd='/usr/bin/file -L'
+- lt_cv_file_magic_test_file=/shlib/libc.so
+- ;;
++ hpux9*)
++ if test "$GCC" = yes; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
++ else
++ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
++ fi
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
++
++ # hardcode_minus_L: Not really in the search PATH,
++ # but as the default location of the library.
++ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
++ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
++ ;;
+
+-cygwin* | mingw* | pw32*)
+- lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+- lt_cv_file_magic_cmd='$OBJDUMP -f'
+- ;;
++ hpux10* | hpux11*)
++ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
++ case "$host_cpu" in
++ hppa*64*|ia64*)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
++ ;;
++ *)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
++ ;;
++ esac
++ else
++ case "$host_cpu" in
++ hppa*64*|ia64*)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags'
++ ;;
++ *)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
++ ;;
++ esac
++ fi
++ if test "$with_gnu_ld" = no; then
++ case "$host_cpu" in
++ hppa*64*)
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
++ _LT_AC_TAGVAR(hardcode_direct, $1)=no
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++ ia64*)
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_AC_TAGVAR(hardcode_direct, $1)=no
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++
++ # hardcode_minus_L: Not really in the search PATH,
++ # but as the default location of the library.
++ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
++ ;;
++ *)
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
++ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
++
++ # hardcode_minus_L: Not really in the search PATH,
++ # but as the default location of the library.
++ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
++ ;;
++ esac
++ fi
++ ;;
+
+-darwin* | rhapsody*)
+- lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library'
+- lt_cv_file_magic_cmd='/usr/bin/file -L'
+- case "$host_os" in
+- rhapsody* | darwin1.[[012]])
+- lt_cv_file_magic_test_file=`echo /System/Library/Frameworks/System.framework/Versions/*/System | head -1`
+- ;;
+- *) # Darwin 1.3 on
+- lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib'
+- ;;
+- esac
+- ;;
++ irix5* | irix6* | nonstopux*)
++ if test "$GCC" = yes; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
++ else
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
++ fi
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
++ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
++ ;;
+
+-freebsd*)
+- if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+- case $host_cpu in
+- i*86 )
+- # Not sure whether the presence of OpenBSD here was a mistake.
+- # Let's accept both of them until this is cleared up.
+- lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library'
+- lt_cv_file_magic_cmd=/usr/bin/file
+- lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
++ netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
++ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
++ else
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
++ fi
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++
++ newsos6)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++
++ openbsd*)
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
++ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
++ else
++ case $host_os in
++ openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++ ;;
++ *)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
++ ;;
++ esac
++ fi
++ ;;
++
++ os2*)
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
++ _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
++ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
++ ;;
++
++ osf3*)
++ if test "$GCC" = yes; then
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
++ else
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
++ fi
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+- esac
+- else
+- lt_cv_deplibs_check_method=pass_all
+- fi
+- ;;
+
+-gnu*)
+- lt_cv_deplibs_check_method=pass_all
+- ;;
++ osf4* | osf5*) # as osf3* with the addition of -msym flag
++ if test "$GCC" = yes; then
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
++ else
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
++ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp'
+
+-hpux10.20*|hpux11*)
+- lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+- lt_cv_file_magic_cmd=/usr/bin/file
+- lt_cv_file_magic_test_file=/usr/lib/libc.sl
+- ;;
++ # Both c and cxx compiler support -rpath directly
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
++ fi
++ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
++ ;;
+
+-irix5* | irix6* | nonstopux*)
+- case $host_os in
+- irix5* | nonstopux*)
+- # this will be overridden with pass_all, but let us keep it just in case
+- lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
+- ;;
+- *)
+- case $LD in
+- *-32|*"-32 ") libmagic=32-bit;;
+- *-n32|*"-n32 ") libmagic=N32;;
+- *-64|*"-64 ") libmagic=64-bit;;
+- *) libmagic=never-match;;
+- esac
+- # this will be overridden with pass_all, but let us keep it just in case
+- lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[[1234]] dynamic lib MIPS - version 1"
+- ;;
+- esac
+- lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*`
+- lt_cv_deplibs_check_method=pass_all
+- ;;
++ sco3.2v5*)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
++ runpath_var=LD_RUN_PATH
++ hardcode_runpath_var=yes
++ ;;
+
+-# This must be Linux ELF.
+-linux-gnu*)
+- case $host_cpu in
+- alpha* | hppa* | i*86 | mips | mipsel | powerpc* | sparc* | ia64* | arm* | m68k)
+- lt_cv_deplibs_check_method=pass_all ;;
+- *)
+- # glibc up to 2.1.1 does not perform some relocations on ARM
+- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;;
+- esac
+- lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+- ;;
++ solaris*)
++ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text'
++ if test "$GCC" = yes; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
++ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
++ else
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
++ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
++ fi
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ case $host_os in
++ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
++ *) # Supported since Solaris 2.6 (maybe 2.5.1?)
++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;;
++ esac
++ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
++ ;;
+
+-netbsd*)
+- if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+- lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so\.[[0-9]]+\.[[0-9]]+$'
+- else
+- lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so$'
+- fi
+- ;;
++ sunos4*)
++ if test "x$host_vendor" = xsequent; then
++ # Use $CC to link under sequent, because it throws in some extra .o
++ # files that make .init and .fini sections work.
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
++ else
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
++ fi
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
++ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
+
+-newos6*)
+- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+- lt_cv_file_magic_cmd=/usr/bin/file
+- lt_cv_file_magic_test_file=/usr/lib/libnls.so
+- ;;
++ sysv4)
++ case $host_vendor in
++ sni)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true???
++ ;;
++ siemens)
++ ## LD is ld it makes a PLAMLIB
++ ## CC just makes a GrossModule.
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
++ _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
++ _LT_AC_TAGVAR(hardcode_direct, $1)=no
++ ;;
++ motorola)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
++ ;;
++ esac
++ runpath_var='LD_RUN_PATH'
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
+
+-openbsd*)
+- lt_cv_file_magic_cmd=/usr/bin/file
+- lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object'
+- else
+- lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library'
+- fi
+- ;;
++ sysv4.3*)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
++ ;;
+
+-osf3* | osf4* | osf5*)
+- # this will be overridden with pass_all, but let us keep it just in case
+- lt_cv_deplibs_check_method='file_magic COFF format alpha shared library'
+- lt_cv_file_magic_test_file=/shlib/libc.so
+- lt_cv_deplibs_check_method=pass_all
+- ;;
++ sysv4*MP*)
++ if test -d /usr/nec; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ runpath_var=LD_RUN_PATH
++ hardcode_runpath_var=yes
++ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
++ fi
++ ;;
+
+-sco3.2v5*)
+- lt_cv_deplibs_check_method=pass_all
+- ;;
++ sysv4.2uw2*)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
++ _LT_AC_TAGVAR(hardcode_minus_L, $1)=no
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ hardcode_runpath_var=yes
++ runpath_var=LD_RUN_PATH
++ ;;
+
+-solaris*)
+- lt_cv_deplibs_check_method=pass_all
+- lt_cv_file_magic_test_file=/lib/libc.so
+- ;;
++ sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*)
++ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z ${wl}text'
++ if test "$GCC" = yes; then
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
++ else
++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
++ fi
++ runpath_var='LD_RUN_PATH'
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
+
+-sysv5uw[[78]]* | sysv4*uw2*)
+- lt_cv_deplibs_check_method=pass_all
+- ;;
++ sysv5*)
++ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text'
++ # $CC -shared without GNU ld will not create a library from C++
++ # object files and a static libstdc++, better avoid it by now
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
++ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ runpath_var='LD_RUN_PATH'
++ ;;
+
+-sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+- case $host_vendor in
+- motorola)
+- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+- lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+- ;;
+- ncr)
+- lt_cv_deplibs_check_method=pass_all
+- ;;
+- sequent)
+- lt_cv_file_magic_cmd='/bin/file'
+- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+- ;;
+- sni)
+- lt_cv_file_magic_cmd='/bin/file'
+- lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+- lt_cv_file_magic_test_file=/lib/libc.so
+- ;;
+- siemens)
+- lt_cv_deplibs_check_method=pass_all
+- ;;
+- esac
+- ;;
+-esac
+-])
+-file_magic_cmd=$lt_cv_file_magic_cmd
+-deplibs_check_method=$lt_cv_deplibs_check_method
++ uts4*)
++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++
++ *)
++ _LT_AC_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ esac
++ fi
+ ])
++AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
++test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
++variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
++if test "$GCC" = yes; then
++ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
++fi
+
+-# AC_PROG_NM - find the path to a BSD-compatible name lister
+-AC_DEFUN([AC_PROG_NM],
+-[AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl
+-AC_MSG_CHECKING([for BSD-compatible nm])
+-AC_CACHE_VAL(lt_cv_path_NM,
+-[if test -n "$NM"; then
+- # Let the user override the test.
+- lt_cv_path_NM="$NM"
+-else
+- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+- for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+- test -z "$ac_dir" && ac_dir=.
+- tmp_nm=$ac_dir/${ac_tool_prefix}nm
+- if test -f $tmp_nm || test -f $tmp_nm$ac_exeext ; then
+- # Check to see if the nm accepts a BSD-compat flag.
+- # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+- # nm: unknown option "B" ignored
+- # Tru64's nm complains that /dev/null is an invalid object file
+- if ($tmp_nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep '(/dev/null|Invalid file or object type)' >/dev/null; then
+- lt_cv_path_NM="$tmp_nm -B"
+- break
+- elif ($tmp_nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+- lt_cv_path_NM="$tmp_nm -p"
+- break
++#
++# Do we need to explicitly link libc?
++#
++case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in
++x|xyes)
++ # Assume -lc should be added
++ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
++
++ if test "$enable_shared" = yes && test "$GCC" = yes; then
++ case $_LT_AC_TAGVAR(archive_cmds, $1) in
++ *'~'*)
++ # FIXME: we may have to deal with multi-command sequences.
++ ;;
++ '$CC '*)
++ # Test whether the compiler implicitly links with -lc since on some
++ # systems, -lgcc has to come before -lc. If gcc already passes -lc
++ # to ld, don't add -lc before -lgcc.
++ AC_MSG_CHECKING([whether -lc should be explicitly linked in])
++ $rm conftest*
++ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
++
++ if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
++ soname=conftest
++ lib=conftest
++ libobjs=conftest.$ac_objext
++ deplibs=
++ wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
++ compiler_flags=-v
++ linker_flags=-v
++ verstring=
++ output_objdir=.
++ libname=conftest
++ lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1)
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=
++ if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1)
++ then
++ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
++ else
++ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
++ fi
++ _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+ else
+- lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+- continue # so that we can try to find one that supports BSD flags
++ cat conftest.err 1>&5
+ fi
+- fi
+- done
+- IFS="$ac_save_ifs"
+- test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+-fi])
+-NM="$lt_cv_path_NM"
+-AC_MSG_RESULT([$NM])
+-])
+-
+-# AC_CHECK_LIBM - check for math library
+-AC_DEFUN([AC_CHECK_LIBM],
+-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+-LIBM=
+-case $host in
+-*-*-beos* | *-*-cygwin* | *-*-pw32*)
+- # These system don't have libm
+- ;;
+-*-ncr-sysv4.3*)
+- AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+- AC_CHECK_LIB(m, main, LIBM="$LIBM -lm")
+- ;;
+-*)
+- AC_CHECK_LIB(m, main, LIBM="-lm")
++ $rm conftest*
++ AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)])
++ ;;
++ esac
++ fi
+ ;;
+ esac
+-])
++])# AC_LIBTOOL_PROG_LD_SHLIBS
+
+-# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for
+-# the libltdl convenience library and LTDLINCL to the include flags for
+-# the libltdl header and adds --enable-ltdl-convenience to the
+-# configure arguments. Note that LIBLTDL and LTDLINCL are not
+-# AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If DIR is not
+-# provided, it is assumed to be `libltdl'. LIBLTDL will be prefixed
+-# with '${top_builddir}/' and LTDLINCL will be prefixed with
+-# '${top_srcdir}/' (note the single quotes!). If your package is not
+-# flat and you're not using automake, define top_builddir and
+-# top_srcdir appropriately in the Makefiles.
+-AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
+-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+- case $enable_ltdl_convenience in
+- no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+- "") enable_ltdl_convenience=yes
+- ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+- esac
+- LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
+- LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+- # For backwards non-gettext consistent compatibility...
+- INCLTDL="$LTDLINCL"
+-])
+
+-# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
+-# the libltdl installable library and LTDLINCL to the include flags for
+-# the libltdl header and adds --enable-ltdl-install to the configure
+-# arguments. Note that LIBLTDL and LTDLINCL are not AC_SUBSTed, nor is
+-# AC_CONFIG_SUBDIRS called. If DIR is not provided and an installed
+-# libltdl is not found, it is assumed to be `libltdl'. LIBLTDL will
+-# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed
+-# with '${top_srcdir}/' (note the single quotes!). If your package is
+-# not flat and you're not using automake, define top_builddir and
+-# top_srcdir appropriately in the Makefiles.
+-# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+-AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
+-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+- AC_CHECK_LIB(ltdl, main,
+- [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
+- [if test x"$enable_ltdl_install" = xno; then
+- AC_MSG_WARN([libltdl not installed, but installation disabled])
+- else
+- enable_ltdl_install=yes
+- fi
+- ])
+- if test x"$enable_ltdl_install" = x"yes"; then
+- ac_configure_args="$ac_configure_args --enable-ltdl-install"
+- LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
+- LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+- else
+- ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+- LIBLTDL="-lltdl"
+- LTDLINCL=
+- fi
+- # For backwards non-gettext consistent compatibility...
+- INCLTDL="$LTDLINCL"
+-])
++# _LT_AC_FILE_LTDLL_C
++# -------------------
++# Be careful that the start marker always follows a newline.
++AC_DEFUN([_LT_AC_FILE_LTDLL_C], [
++# /* ltdll.c starts here */
++# #define WIN32_LEAN_AND_MEAN
++# #include <windows.h>
++# #undef WIN32_LEAN_AND_MEAN
++# #include <stdio.h>
++#
++# #ifndef __CYGWIN__
++# # ifdef __CYGWIN32__
++# # define __CYGWIN__ __CYGWIN32__
++# # endif
++# #endif
++#
++# #ifdef __cplusplus
++# extern "C" {
++# #endif
++# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
++# #ifdef __cplusplus
++# }
++# #endif
++#
++# #ifdef __CYGWIN__
++# #include <cygwin/cygwin_dll.h>
++# DECLARE_CYGWIN_DLL( DllMain );
++# #endif
++# HINSTANCE __hDllInstance_base;
++#
++# BOOL APIENTRY
++# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
++# {
++# __hDllInstance_base = hInst;
++# return TRUE;
++# }
++# /* ltdll.c ends here */
++])# _LT_AC_FILE_LTDLL_C
++
++
++# _LT_AC_TAGVAR(VARNAME, [TAGNAME])
++# ---------------------------------
++AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])])
++
+
+ # old names
+ AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL])
+@@ -3709,6 +6828,16 @@
+ # This is just to silence aclocal about the macro not being used
+ ifelse([AC_DISABLE_FAST_INSTALL])
+
++AC_DEFUN([LT_AC_PROG_GCJ],
++[AC_CHECK_TOOL(GCJ, gcj, no)
++ test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
++ AC_SUBST(GCJFLAGS)
++])
++
++AC_DEFUN([LT_AC_PROG_RC],
++[AC_CHECK_TOOL(RC, windres, no)
++])
++
+ # NOTE: This macro has been submitted for inclusion into #
+ # GNU Autoconf as AC_PROG_SED. When it is available in #
+ # a released version of Autoconf we should remove this #
+@@ -3722,79 +6851,51 @@
+ AC_CACHE_VAL(lt_cv_path_SED,
+ [# Loop through the user's path and test for sed and gsed.
+ # Then use that list of sed's as ones to test for truncation.
+-as_executable_p="test -f"
+ 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_prog in sed gsed; do
++ for lt_ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+- if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+- _sed_list="$_sed_list $as_dir/$ac_prog$ac_exec_ext"
++ if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
++ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+ fi
+ done
+ done
+ done
+-
+- # Create a temporary directory, and hook for its removal unless debugging.
+-$debug ||
+-{
+- trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+- trap '{ (exit 1); exit 1; }' 1 2 13 15
+-}
+-
+-# Create a (secure) tmp directory for tmp files.
+-: ${TMPDIR=/tmp}
+-{
+- tmp=`(umask 077 && mktemp -d -q "$TMPDIR/sedXXXXXX") 2>/dev/null` &&
+- test -n "$tmp" && test -d "$tmp"
+-} ||
+-{
+- tmp=$TMPDIR/sed$$-$RANDOM
+- (umask 077 && mkdir $tmp)
+-} ||
+-{
+- echo "$me: cannot create a temporary directory in $TMPDIR" >&2
+- { (exit 1); exit 1; }
+-}
+- _max=0
+- _count=0
+- # Add /usr/xpg4/bin/sed as it is typically found on Solaris
+- # along with /bin/sed that truncates output.
+- for _sed in $_sed_list /usr/xpg4/bin/sed; do
+- test ! -f ${_sed} && break
+- cat /dev/null > "$tmp/sed.in"
+- _count=0
+- echo ${ECHO_N-$ac_n} "0123456789${ECHO_C-$ac_c}" >"$tmp/sed.in"
+- # Check for GNU sed and select it if it is found.
+- if "${_sed}" --version 2>&1 < /dev/null | egrep '(GNU)' > /dev/null; then
+- lt_cv_path_SED=${_sed}
+- break
++lt_ac_max=0
++lt_ac_count=0
++# Add /usr/xpg4/bin/sed as it is typically found on Solaris
++# along with /bin/sed that truncates output.
++for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
++ test ! -f $lt_ac_sed && break
++ cat /dev/null > conftest.in
++ lt_ac_count=0
++ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
++ # Check for GNU sed and select it if it is found.
++ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
++ lt_cv_path_SED=$lt_ac_sed
++ break
++ fi
++ while true; do
++ cat conftest.in conftest.in >conftest.tmp
++ mv conftest.tmp conftest.in
++ cp conftest.in conftest.nl
++ echo >>conftest.nl
++ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
++ cmp -s conftest.out conftest.nl || break
++ # 10000 chars as input seems more than enough
++ test $lt_ac_count -gt 10 && break
++ lt_ac_count=`expr $lt_ac_count + 1`
++ if test $lt_ac_count -gt $lt_ac_max; then
++ lt_ac_max=$lt_ac_count
++ lt_cv_path_SED=$lt_ac_sed
+ fi
+- while true; do
+- cat "$tmp/sed.in" "$tmp/sed.in" >"$tmp/sed.tmp"
+- mv "$tmp/sed.tmp" "$tmp/sed.in"
+- cp "$tmp/sed.in" "$tmp/sed.nl"
+- echo >>"$tmp/sed.nl"
+- ${_sed} -e 's/a$//' < "$tmp/sed.nl" >"$tmp/sed.out" || break
+- cmp -s "$tmp/sed.out" "$tmp/sed.nl" || break
+- # 40000 chars as input seems more than enough
+- test $_count -gt 10 && break
+- _count=`expr $_count + 1`
+- if test $_count -gt $_max; then
+- _max=$_count
+- lt_cv_path_SED=$_sed
+- fi
+- done
+ done
+- rm -rf "$tmp"
++done
++SED=$lt_cv_path_SED
+ ])
+-if test "X$SED" != "X"; then
+- lt_cv_path_SED=$SED
+-else
+- SED=$lt_cv_path_SED
+-fi
+ AC_MSG_RESULT([$SED])
+ ])
+
+diff -urN linux-atm.old/configure linux-atm.dev/configure
+--- linux-atm.old/configure 2005-08-23 01:12:10.846787000 +0200
++++ linux-atm.dev/configure 2005-08-23 01:12:41.187175024 +0200
+@@ -1,9 +1,8 @@
+ #! /bin/sh
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.57.
++# Generated by GNU Autoconf 2.59.
+ #
+-# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+-# Free Software Foundation, Inc.
++# Copyright (C) 2003 Free Software Foundation, Inc.
+ # This configure script is free software; the Free Software Foundation
+ # gives unlimited permission to copy, distribute and modify it.
+ ## --------------------- ##
+@@ -20,9 +19,10 @@
+ elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+ fi
++DUALCASE=1; export DUALCASE # for MKS sh
+
+ # Support unset when possible.
+-if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
++if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+ else
+ as_unset=false
+@@ -41,7 +41,7 @@
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+ do
+- if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then
++ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+@@ -218,16 +218,17 @@
+ if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+ else
++ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+ fi
+
+ as_executable_p="test -f"
+
+ # Sed expression to map a string onto a valid CPP name.
+-as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
++as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+ # Sed expression to map a string onto a valid variable name.
+-as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
++as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+ # IFS
+@@ -826,7 +827,7 @@
+
+ # Be sure to have absolute paths.
+ for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+- localstatedir libdir includedir oldincludedir infodir mandir
++ localstatedir libdir includedir oldincludedir infodir mandir
+ do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+@@ -866,10 +867,10 @@
+ # Try the directory containing this script, then its parent.
+ ac_confdir=`(dirname "$0") 2>/dev/null ||
+ $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+- X"$0" : 'X\(//\)[^/]' \| \
+- X"$0" : 'X\(//\)$' \| \
+- X"$0" : 'X\(/\)' \| \
+- . : '\(.\)' 2>/dev/null ||
++ X"$0" : 'X\(//\)[^/]' \| \
++ X"$0" : 'X\(//\)$' \| \
++ X"$0" : 'X\(/\)' \| \
++ . : '\(.\)' 2>/dev/null ||
+ echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+@@ -961,9 +962,9 @@
+ cat <<_ACEOF
+ Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+- [$ac_default_prefix]
++ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+- [PREFIX]
++ [PREFIX]
+
+ By default, \`make install' will install all the files in
+ \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+@@ -1071,12 +1072,45 @@
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+ esac
+-# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+-# absolute.
+-ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+-ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
+-ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+-ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
++
++# Do not use `cd foo && pwd` to compute absolute paths, because
++# the directories may not exist.
++case `pwd` in
++.) ac_abs_builddir="$ac_dir";;
++*)
++ case "$ac_dir" in
++ .) ac_abs_builddir=`pwd`;;
++ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
++ *) ac_abs_builddir=`pwd`/"$ac_dir";;
++ esac;;
++esac
++case $ac_abs_builddir in
++.) ac_abs_top_builddir=${ac_top_builddir}.;;
++*)
++ case ${ac_top_builddir}. in
++ .) ac_abs_top_builddir=$ac_abs_builddir;;
++ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
++ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
++ esac;;
++esac
++case $ac_abs_builddir in
++.) ac_abs_srcdir=$ac_srcdir;;
++*)
++ case $ac_srcdir in
++ .) ac_abs_srcdir=$ac_abs_builddir;;
++ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
++ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
++ esac;;
++esac
++case $ac_abs_builddir in
++.) ac_abs_top_srcdir=$ac_top_srcdir;;
++*)
++ case $ac_top_srcdir in
++ .) ac_abs_top_srcdir=$ac_abs_builddir;;
++ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
++ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
++ esac;;
++esac
+
+ cd $ac_dir
+ # Check for guested configure; otherwise get Cygnus style configure.
+@@ -1087,13 +1121,13 @@
+ echo
+ $SHELL $ac_srcdir/configure --help=recursive
+ elif test -f $ac_srcdir/configure.ac ||
+- test -f $ac_srcdir/configure.in; then
++ test -f $ac_srcdir/configure.in; then
+ echo
+ $ac_configure --help
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi
+- cd $ac_popdir
++ cd "$ac_popdir"
+ done
+ fi
+
+@@ -1101,8 +1135,7 @@
+ if $ac_init_version; then
+ cat <<\_ACEOF
+
+-Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+-Free Software Foundation, Inc.
++Copyright (C) 2003 Free Software Foundation, Inc.
+ This configure script is free software; the Free Software Foundation
+ gives unlimited permission to copy, distribute and modify it.
+ _ACEOF
+@@ -1114,7 +1147,7 @@
+ running configure, to aid debugging if configure makes a mistake.
+
+ It was created by $as_me, which was
+-generated by GNU Autoconf 2.57. Invocation command line was
++generated by GNU Autoconf 2.59. Invocation command line was
+
+ $ $0 $@
+
+@@ -1191,19 +1224,19 @@
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+- ac_must_keep_next=false # Got value, back to normal.
++ ac_must_keep_next=false # Got value, back to normal.
+ else
+- case $ac_arg in
+- *=* | --config-cache | -C | -disable-* | --disable-* \
+- | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+- | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+- | -with-* | --with-* | -without-* | --without-* | --x)
+- case "$ac_configure_args0 " in
+- "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+- esac
+- ;;
+- -* ) ac_must_keep_next=true ;;
+- esac
++ case $ac_arg in
++ *=* | --config-cache | -C | -disable-* | --disable-* \
++ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
++ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
++ | -with-* | --with-* | -without-* | --without-* | --x)
++ case "$ac_configure_args0 " in
++ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
++ esac
++ ;;
++ -* ) ac_must_keep_next=true ;;
++ esac
+ fi
+ ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+ # Get rid of the leading space.
+@@ -1237,12 +1270,12 @@
+ case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ sed -n \
+- "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
++ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
++ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+ ;;
+ *)
+ sed -n \
+- "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
++ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+ }
+@@ -1271,7 +1304,7 @@
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=$`echo $ac_var`
+- echo "$ac_var='"'"'$ac_val'"'"'"
++ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+ fi
+@@ -1370,7 +1403,7 @@
+ # value.
+ ac_cache_corrupted=false
+ for ac_var in `(set) 2>&1 |
+- sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
++ sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+@@ -1387,13 +1420,13 @@
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+- { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
++ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+ echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+- { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
++ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+ echo "$as_me: former value: $ac_old_val" >&2;}
+- { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
++ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+ echo "$as_me: current value: $ac_new_val" >&2;}
+- ac_cache_corrupted=:
++ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+@@ -1567,6 +1600,7 @@
+ # 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"
++# OS/2's system install, which has a completely different semantic
+ # ./install, which can be erroneously created by make from ./install.sh.
+ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+ echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+@@ -1583,6 +1617,7 @@
+ case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
++ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+@@ -1590,20 +1625,20 @@
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+- if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+- if test $ac_prog = install &&
+- grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+- # AIX install. It has an incompatible calling convention.
+- :
+- elif test $ac_prog = install &&
+- grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+- # program-specific install script used by HP pwplus--don't use.
+- :
+- else
+- ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+- break 3
+- fi
+- fi
++ if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
++ if test $ac_prog = install &&
++ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
++ # AIX install. It has an incompatible calling convention.
++ :
++ elif test $ac_prog = install &&
++ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
++ # program-specific install script used by HP pwplus--don't use.
++ :
++ else
++ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
++ break 3
++ fi
++ fi
+ done
+ done
+ ;;
+@@ -1693,7 +1728,7 @@
+
+ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+ echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
+-set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'`
++set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'`
+ if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+@@ -2163,7 +2198,6 @@
+ (exit $ac_status); }
+
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -2183,8 +2217,8 @@
+ # Try to create an executable without -o first, disregard a.out.
+ # It will help us diagnose broken compilers, and finding out an intuition
+ # of exeext.
+-echo "$as_me:$LINENO: checking for C compiler default output" >&5
+-echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6
++echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
++echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+ if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+ (eval $ac_link_default) 2>&5
+@@ -2204,23 +2238,23 @@
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+- ;;
++ ;;
+ conftest.$ac_ext )
+- # This is the source file.
+- ;;
++ # This is the source file.
++ ;;
+ [ab].out )
+- # We found the default executable, but exeext='' is most
+- # certainly right.
+- break;;
++ # We found the default executable, but exeext='' is most
++ # certainly right.
++ break;;
+ *.* )
+- ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+- # FIXME: I believe we export ac_cv_exeext for Libtool,
+- # but it would be cool to find out if it's true. Does anybody
+- # maintain Libtool? --akim.
+- export ac_cv_exeext
+- break;;
++ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
++ # FIXME: I believe we export ac_cv_exeext for Libtool,
++ # but it would be cool to find out if it's true. Does anybody
++ # maintain Libtool? --akim.
++ export ac_cv_exeext
++ break;;
+ * )
+- break;;
++ break;;
+ esac
+ done
+ else
+@@ -2294,8 +2328,8 @@
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+- export ac_cv_exeext
+- break;;
++ export ac_cv_exeext
++ break;;
+ * ) break;;
+ esac
+ done
+@@ -2320,7 +2354,6 @@
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -2371,7 +2404,6 @@
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -2391,11 +2423,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+- (eval $ac_compile) 2>&5
++ (eval $ac_compile) 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); } &&
+- { ac_try='test -s conftest.$ac_objext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -2408,7 +2449,7 @@
+
+ ac_compiler_gnu=no
+ fi
+-rm -f conftest.$ac_objext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+ fi
+@@ -2424,7 +2465,6 @@
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -2441,11 +2481,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+- (eval $ac_compile) 2>&5
++ (eval $ac_compile) 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); } &&
+- { ac_try='test -s conftest.$ac_objext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -2458,7 +2507,7 @@
+
+ ac_cv_prog_cc_g=no
+ fi
+-rm -f conftest.$ac_objext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+ echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+@@ -2485,7 +2534,6 @@
+ ac_cv_prog_cc_stdc=no
+ ac_save_CC=$CC
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -2513,6 +2561,16 @@
+ va_end (v);
+ return s;
+ }
++
++/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
++ function prototypes and stuff, but not '\xHH' hex character constants.
++ These don't provoke an error unfortunately, instead are silently treated
++ as 'x'. The following induces an error, until -std1 is added to get
++ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
++ array size at least. It's necessary to write '\x00'==0 to get something
++ that's true only with -std1. */
++int osf4_cc_array ['\x00' == 0 ? 1 : -1];
++
+ int test (int i, double x);
+ struct s1 {int (*f) (int a);};
+ struct s2 {int (*f) (double a);};
+@@ -2539,11 +2597,20 @@
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+- (eval $ac_compile) 2>&5
++ (eval $ac_compile) 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); } &&
+- { ac_try='test -s conftest.$ac_objext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -2556,7 +2623,7 @@
+ sed 's/^/| /' conftest.$ac_ext >&5
+
+ fi
+-rm -f conftest.$ac_objext
++rm -f conftest.err conftest.$ac_objext
+ done
+ rm -f conftest.$ac_ext conftest.$ac_objext
+ CC=$ac_save_CC
+@@ -2584,11 +2651,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+- (eval $ac_compile) 2>&5
++ (eval $ac_compile) 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); } &&
+- { ac_try='test -s conftest.$ac_objext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -2603,7 +2679,6 @@
+ 'void exit (int);'
+ do
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -2621,11 +2696,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+- (eval $ac_compile) 2>&5
++ (eval $ac_compile) 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); } &&
+- { ac_try='test -s conftest.$ac_objext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -2638,9 +2722,8 @@
+
+ continue
+ fi
+-rm -f conftest.$ac_objext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -2657,11 +2740,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+- (eval $ac_compile) 2>&5
++ (eval $ac_compile) 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); } &&
+- { ac_try='test -s conftest.$ac_objext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -2673,7 +2765,7 @@
+ sed 's/^/| /' conftest.$ac_ext >&5
+
+ fi
+-rm -f conftest.$ac_objext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+ rm -f conftest*
+ if test -n "$ac_declaration"; then
+@@ -2687,7 +2779,7 @@
+ sed 's/^/| /' conftest.$ac_ext >&5
+
+ fi
+-rm -f conftest.$ac_objext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_ext=c
+ ac_cpp='$CPP $CPPFLAGS'
+ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+@@ -2788,7 +2880,6 @@
+ ac_check_lib_save_LIBS=$LIBS
+ LIBS="-lfl $LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -2812,11 +2903,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+- (eval $ac_link) 2>&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); } &&
+- { ac_try='test -s conftest$ac_exeext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -2829,7 +2929,8 @@
+
+ ac_cv_lib_fl_yywrap=no
+ fi
+-rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext \
++ conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_check_lib_save_LIBS
+ fi
+ echo "$as_me:$LINENO: result: $ac_cv_lib_fl_yywrap" >&5
+@@ -2845,7 +2946,6 @@
+ ac_check_lib_save_LIBS=$LIBS
+ LIBS="-ll $LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -2869,11 +2969,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+- (eval $ac_link) 2>&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); } &&
+- { ac_try='test -s conftest$ac_exeext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -2886,7 +2995,8 @@
+
+ ac_cv_lib_l_yywrap=no
+ fi
+-rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext \
++ conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_check_lib_save_LIBS
+ fi
+ echo "$as_me:$LINENO: result: $ac_cv_lib_l_yywrap" >&5
+@@ -2948,11 +3058,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+- (eval $ac_link) 2>&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); } &&
+- { ac_try='test -s conftest$ac_exeext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -2964,7 +3083,8 @@
+ sed 's/^/| /' conftest.$ac_ext >&5
+
+ fi
+-rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext \
++ conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_save_LIBS
+ rm -f "${LEX_OUTPUT_ROOT}.c"
+
+@@ -3033,6 +3153,7 @@
+ # 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"
++# OS/2's system install, which has a completely different semantic
+ # ./install, which can be erroneously created by make from ./install.sh.
+ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+ echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+@@ -3049,6 +3170,7 @@
+ case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
++ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+@@ -3056,20 +3178,20 @@
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+- if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+- if test $ac_prog = install &&
+- grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+- # AIX install. It has an incompatible calling convention.
+- :
+- elif test $ac_prog = install &&
+- grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+- # program-specific install script used by HP pwplus--don't use.
+- :
+- else
+- ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+- break 3
+- fi
+- fi
++ if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
++ if test $ac_prog = install &&
++ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
++ # AIX install. It has an incompatible calling convention.
++ :
++ elif test $ac_prog = install &&
++ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
++ # program-specific install script used by HP pwplus--don't use.
++ :
++ else
++ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
++ break 3
++ fi
++ fi
+ done
+ done
+ ;;
+@@ -3842,7 +3964,6 @@
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -3853,7 +3974,7 @@
+ #else
+ # include <assert.h>
+ #endif
+- Syntax error
++ Syntax error
+ _ACEOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+@@ -3865,6 +3986,7 @@
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
++ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+@@ -3885,7 +4007,6 @@
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -3903,6 +4024,7 @@
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
++ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+@@ -3949,7 +4071,6 @@
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -3960,7 +4081,7 @@
+ #else
+ # include <assert.h>
+ #endif
+- Syntax error
++ Syntax error
+ _ACEOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+@@ -3972,6 +4093,7 @@
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
++ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+@@ -3992,7 +4114,6 @@
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -4010,6 +4131,7 @@
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
++ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+@@ -4070,7 +4192,6 @@
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -4091,11 +4212,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+- (eval $ac_compile) 2>&5
++ (eval $ac_compile) 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); } &&
+- { ac_try='test -s conftest.$ac_objext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -4108,12 +4238,11 @@
+
+ ac_cv_header_stdc=no
+ fi
+-rm -f conftest.$ac_objext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -4135,7 +4264,6 @@
+ 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 <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -4160,7 +4288,6 @@
+ :
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -4172,9 +4299,9 @@
+ # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+ #else
+ # define ISLOWER(c) \
+- (('a' <= (c) && (c) <= 'i') \
+- || ('j' <= (c) && (c) <= 'r') \
+- || ('s' <= (c) && (c) <= 'z'))
++ (('a' <= (c) && (c) <= 'i') \
++ || ('j' <= (c) && (c) <= 'r') \
++ || ('s' <= (c) && (c) <= 'z'))
+ # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+ #endif
+
+@@ -4185,7 +4312,7 @@
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+- || toupper (i) != TOUPPER (i))
++ || toupper (i) != TOUPPER (i))
+ exit(2);
+ exit (0);
+ }
+@@ -4235,7 +4362,7 @@
+
+
+ for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+- inttypes.h stdint.h unistd.h
++ inttypes.h stdint.h unistd.h
+ do
+ as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+@@ -4244,7 +4371,6 @@
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -4256,11 +4382,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+- (eval $ac_compile) 2>&5
++ (eval $ac_compile) 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); } &&
+- { ac_try='test -s conftest.$ac_objext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -4273,7 +4408,7 @@
+
+ eval "$as_ac_Header=no"
+ fi
+-rm -f conftest.$ac_objext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+ echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+@@ -4304,7 +4439,6 @@
+ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+ echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -4315,11 +4449,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+- (eval $ac_compile) 2>&5
++ (eval $ac_compile) 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); } &&
+- { ac_try='test -s conftest.$ac_objext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -4332,7 +4475,7 @@
+
+ ac_header_compiler=no
+ fi
+-rm -f conftest.$ac_objext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+ echo "${ECHO_T}$ac_header_compiler" >&6
+
+@@ -4340,7 +4483,6 @@
+ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+ echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -4358,6 +4500,7 @@
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
++ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+@@ -4377,33 +4520,32 @@
+ echo "${ECHO_T}$ac_header_preproc" >&6
+
+ # So? What about this header?
+-case $ac_header_compiler:$ac_header_preproc in
+- yes:no )
++case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
++ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+ echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+- (
+- cat <<\_ASBOX
+-## ------------------------------------ ##
+-## Report this to bug-autoconf@gnu.org. ##
+-## ------------------------------------ ##
+-_ASBOX
+- ) |
+- sed "s/^/$as_me: WARNING: /" >&2
++ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
++echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
++ ac_header_preproc=yes
+ ;;
+- no:yes )
++ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+ echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
++ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
++echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
++ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
++echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
++ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
++echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+ echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
++ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
++echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+-## ------------------------------------ ##
+-## Report this to bug-autoconf@gnu.org. ##
+-## ------------------------------------ ##
++## ------------------------------------------ ##
++## Report this to the AC_PACKAGE_NAME lists. ##
++## ------------------------------------------ ##
+ _ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+@@ -4414,7 +4556,7 @@
+ if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+- eval "$as_ac_Header=$ac_header_preproc"
++ eval "$as_ac_Header=\$ac_header_preproc"
+ fi
+ echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+ echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+@@ -4749,7 +4891,7 @@
+ case $host in
+ *-*-irix6*)
+ # Find out which ABI we are using.
+- echo '#line 4752 "configure"' > conftest.$ac_ext
++ echo '#line 4894 "configure"' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+@@ -4788,7 +4930,6 @@
+ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -4805,11 +4946,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+- (eval $ac_link) 2>&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); } &&
+- { ac_try='test -s conftest$ac_exeext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -4822,7 +4972,8 @@
+
+ lt_cv_cc_needs_belf=no
+ fi
+-rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext \
++ conftest$ac_exeext conftest.$ac_ext
+ ac_ext=c
+ ac_cpp='$CPP $CPPFLAGS'
+ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+@@ -5117,7 +5268,6 @@
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC"
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -5134,11 +5284,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+- (eval $ac_compile) 2>&5
++ (eval $ac_compile) 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); } &&
+- { ac_try='test -s conftest.$ac_objext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -5167,7 +5326,7 @@
+ lt_cv_prog_cc_pic_works=no
+
+ fi
+-rm -f conftest.$ac_objext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ fi
+@@ -5205,7 +5364,6 @@
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static"
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -5222,11 +5380,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+- (eval $ac_link) 2>&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); } &&
+- { ac_try='test -s conftest$ac_exeext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -5238,7 +5405,8 @@
+ sed 's/^/| /' conftest.$ac_ext >&5
+
+ fi
+-rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext \
++ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS="$save_LDFLAGS"
+
+ fi
+@@ -5278,7 +5446,7 @@
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
+ compiler_c_o=no
+-if { (eval echo configure:5281: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
++if { (eval echo configure:5449: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s out/conftest.err; then
+@@ -5319,7 +5487,6 @@
+ save_objext="$ac_objext"
+ ac_objext=lo
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -5336,11 +5503,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+- (eval $ac_compile) 2>&5
++ (eval $ac_compile) 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); } &&
+- { ac_try='test -s conftest.$ac_objext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -5359,7 +5535,7 @@
+ sed 's/^/| /' conftest.$ac_ext >&5
+
+ fi
+-rm -f conftest.$ac_objext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_objext="$save_objext"
+ CFLAGS="$save_CFLAGS"
+
+@@ -5404,7 +5580,6 @@
+ CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext"
+ compiler_rtti_exceptions=no
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -5421,11 +5596,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+- (eval $ac_compile) 2>&5
++ (eval $ac_compile) 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); } &&
+- { ac_try='test -s conftest.$ac_objext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -5444,7 +5628,7 @@
+ sed 's/^/| /' conftest.$ac_ext >&5
+
+ fi
+-rm -f conftest.$ac_objext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+ echo "$as_me:$LINENO: result: $compiler_rtti_exceptions" >&5
+ echo "${ECHO_T}$compiler_rtti_exceptions" >&6
+@@ -6704,21 +6888,28 @@
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+ cat >>conftest.$ac_ext <<_ACEOF
+ /* end confdefs.h. */
++/* Define shl_load to an innocuous variant, in case <limits.h> declares shl_load.
++ For example, HP-UX 11i <limits.h> declares gettimeofday. */
++#define shl_load innocuous_shl_load
++
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char shl_load (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
++
+ #ifdef __STDC__
+ # include <limits.h>
+ #else
+ # include <assert.h>
+ #endif
++
++#undef shl_load
++
+ /* Override any gcc2 internal prototype to avoid an error. */
+ #ifdef __cplusplus
+ extern "C"
+@@ -6749,11 +6940,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+- (eval $ac_link) 2>&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); } &&
+- { ac_try='test -s conftest$ac_exeext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -6766,7 +6966,8 @@
+
+ ac_cv_func_shl_load=no
+ fi
+-rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext \
++ conftest$ac_exeext conftest.$ac_ext
+ fi
+ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
+ echo "${ECHO_T}$ac_cv_func_shl_load" >&6
+@@ -6781,7 +6982,6 @@
+ ac_check_lib_save_LIBS=$LIBS
+ LIBS="-ldld $LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -6805,11 +7005,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+- (eval $ac_link) 2>&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); } &&
+- { ac_try='test -s conftest$ac_exeext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -6822,7 +7031,8 @@
+
+ ac_cv_lib_dld_shl_load=no
+ fi
+-rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext \
++ conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_check_lib_save_LIBS
+ fi
+ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
+@@ -6836,21 +7046,28 @@
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+ cat >>conftest.$ac_ext <<_ACEOF
+ /* end confdefs.h. */
++/* Define dlopen to an innocuous variant, in case <limits.h> declares dlopen.
++ For example, HP-UX 11i <limits.h> declares gettimeofday. */
++#define dlopen innocuous_dlopen
++
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char dlopen (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
++
+ #ifdef __STDC__
+ # include <limits.h>
+ #else
+ # include <assert.h>
+ #endif
++
++#undef dlopen
++
+ /* Override any gcc2 internal prototype to avoid an error. */
+ #ifdef __cplusplus
+ extern "C"
+@@ -6881,11 +7098,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+- (eval $ac_link) 2>&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); } &&
+- { ac_try='test -s conftest$ac_exeext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -6898,7 +7124,8 @@
+
+ ac_cv_func_dlopen=no
+ fi
+-rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext \
++ conftest$ac_exeext conftest.$ac_ext
+ fi
+ echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5
+ echo "${ECHO_T}$ac_cv_func_dlopen" >&6
+@@ -6913,7 +7140,6 @@
+ ac_check_lib_save_LIBS=$LIBS
+ LIBS="-ldl $LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -6937,11 +7163,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+- (eval $ac_link) 2>&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); } &&
+- { ac_try='test -s conftest$ac_exeext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -6954,7 +7189,8 @@
+
+ ac_cv_lib_dl_dlopen=no
+ fi
+-rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext \
++ conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_check_lib_save_LIBS
+ fi
+ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+@@ -6970,7 +7206,6 @@
+ ac_check_lib_save_LIBS=$LIBS
+ LIBS="-lsvld $LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -6994,11 +7229,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+- (eval $ac_link) 2>&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); } &&
+- { ac_try='test -s conftest$ac_exeext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -7011,7 +7255,8 @@
+
+ ac_cv_lib_svld_dlopen=no
+ fi
+-rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext \
++ conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_check_lib_save_LIBS
+ fi
+ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
+@@ -7027,7 +7272,6 @@
+ ac_check_lib_save_LIBS=$LIBS
+ LIBS="-ldld $LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -7051,11 +7295,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+- (eval $ac_link) 2>&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); } &&
+- { ac_try='test -s conftest$ac_exeext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -7068,7 +7321,8 @@
+
+ ac_cv_lib_dld_dld_link=no
+ fi
+-rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext \
++ conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_check_lib_save_LIBS
+ fi
+ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
+@@ -7123,7 +7377,7 @@
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+-#line 7126 "configure"
++#line 7380 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+@@ -7221,7 +7475,7 @@
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+-#line 7224 "configure"
++#line 7478 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+@@ -8005,7 +8259,6 @@
+ echo "$as_me:$LINENO: checking asm/errno.h usability" >&5
+ echo $ECHO_N "checking asm/errno.h usability... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -8016,11 +8269,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+- (eval $ac_compile) 2>&5
++ (eval $ac_compile) 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); } &&
+- { ac_try='test -s conftest.$ac_objext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -8033,7 +8295,7 @@
+
+ ac_header_compiler=no
+ fi
+-rm -f conftest.$ac_objext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+ echo "${ECHO_T}$ac_header_compiler" >&6
+
+@@ -8041,7 +8303,6 @@
+ echo "$as_me:$LINENO: checking asm/errno.h presence" >&5
+ echo $ECHO_N "checking asm/errno.h presence... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -8059,6 +8320,7 @@
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
++ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+@@ -8078,33 +8340,32 @@
+ echo "${ECHO_T}$ac_header_preproc" >&6
+
+ # So? What about this header?
+-case $ac_header_compiler:$ac_header_preproc in
+- yes:no )
++case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
++ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: asm/errno.h: accepted by the compiler, rejected by the preprocessor!" >&5
+ echo "$as_me: WARNING: asm/errno.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+- { echo "$as_me:$LINENO: WARNING: asm/errno.h: proceeding with the preprocessor's result" >&5
+-echo "$as_me: WARNING: asm/errno.h: proceeding with the preprocessor's result" >&2;}
+- (
+- cat <<\_ASBOX
+-## ------------------------------------ ##
+-## Report this to bug-autoconf@gnu.org. ##
+-## ------------------------------------ ##
+-_ASBOX
+- ) |
+- sed "s/^/$as_me: WARNING: /" >&2
++ { echo "$as_me:$LINENO: WARNING: asm/errno.h: proceeding with the compiler's result" >&5
++echo "$as_me: WARNING: asm/errno.h: proceeding with the compiler's result" >&2;}
++ ac_header_preproc=yes
+ ;;
+- no:yes )
++ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: asm/errno.h: present but cannot be compiled" >&5
+ echo "$as_me: WARNING: asm/errno.h: present but cannot be compiled" >&2;}
+- { echo "$as_me:$LINENO: WARNING: asm/errno.h: check for missing prerequisite headers?" >&5
+-echo "$as_me: WARNING: asm/errno.h: check for missing prerequisite headers?" >&2;}
++ { echo "$as_me:$LINENO: WARNING: asm/errno.h: check for missing prerequisite headers?" >&5
++echo "$as_me: WARNING: asm/errno.h: check for missing prerequisite headers?" >&2;}
++ { echo "$as_me:$LINENO: WARNING: asm/errno.h: see the Autoconf documentation" >&5
++echo "$as_me: WARNING: asm/errno.h: see the Autoconf documentation" >&2;}
++ { echo "$as_me:$LINENO: WARNING: asm/errno.h: section \"Present But Cannot Be Compiled\"" >&5
++echo "$as_me: WARNING: asm/errno.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: asm/errno.h: proceeding with the preprocessor's result" >&5
+ echo "$as_me: WARNING: asm/errno.h: proceeding with the preprocessor's result" >&2;}
++ { echo "$as_me:$LINENO: WARNING: asm/errno.h: in the future, the compiler will take precedence" >&5
++echo "$as_me: WARNING: asm/errno.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+-## ------------------------------------ ##
+-## Report this to bug-autoconf@gnu.org. ##
+-## ------------------------------------ ##
++## ------------------------------------------ ##
++## Report this to the AC_PACKAGE_NAME lists. ##
++## ------------------------------------------ ##
+ _ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+@@ -8145,7 +8406,6 @@
+ echo "$as_me:$LINENO: checking linux/atmsap.h usability" >&5
+ echo $ECHO_N "checking linux/atmsap.h usability... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -8156,11 +8416,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+- (eval $ac_compile) 2>&5
++ (eval $ac_compile) 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); } &&
+- { ac_try='test -s conftest.$ac_objext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -8173,7 +8442,7 @@
+
+ ac_header_compiler=no
+ fi
+-rm -f conftest.$ac_objext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+ echo "${ECHO_T}$ac_header_compiler" >&6
+
+@@ -8181,7 +8450,6 @@
+ echo "$as_me:$LINENO: checking linux/atmsap.h presence" >&5
+ echo $ECHO_N "checking linux/atmsap.h presence... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -8199,6 +8467,7 @@
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
++ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+@@ -8218,33 +8487,32 @@
+ echo "${ECHO_T}$ac_header_preproc" >&6
+
+ # So? What about this header?
+-case $ac_header_compiler:$ac_header_preproc in
+- yes:no )
++case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
++ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: linux/atmsap.h: accepted by the compiler, rejected by the preprocessor!" >&5
+ echo "$as_me: WARNING: linux/atmsap.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+- { echo "$as_me:$LINENO: WARNING: linux/atmsap.h: proceeding with the preprocessor's result" >&5
+-echo "$as_me: WARNING: linux/atmsap.h: proceeding with the preprocessor's result" >&2;}
+- (
+- cat <<\_ASBOX
+-## ------------------------------------ ##
+-## Report this to bug-autoconf@gnu.org. ##
+-## ------------------------------------ ##
+-_ASBOX
+- ) |
+- sed "s/^/$as_me: WARNING: /" >&2
++ { echo "$as_me:$LINENO: WARNING: linux/atmsap.h: proceeding with the compiler's result" >&5
++echo "$as_me: WARNING: linux/atmsap.h: proceeding with the compiler's result" >&2;}
++ ac_header_preproc=yes
+ ;;
+- no:yes )
++ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: linux/atmsap.h: present but cannot be compiled" >&5
+ echo "$as_me: WARNING: linux/atmsap.h: present but cannot be compiled" >&2;}
+- { echo "$as_me:$LINENO: WARNING: linux/atmsap.h: check for missing prerequisite headers?" >&5
+-echo "$as_me: WARNING: linux/atmsap.h: check for missing prerequisite headers?" >&2;}
++ { echo "$as_me:$LINENO: WARNING: linux/atmsap.h: check for missing prerequisite headers?" >&5
++echo "$as_me: WARNING: linux/atmsap.h: check for missing prerequisite headers?" >&2;}
++ { echo "$as_me:$LINENO: WARNING: linux/atmsap.h: see the Autoconf documentation" >&5
++echo "$as_me: WARNING: linux/atmsap.h: see the Autoconf documentation" >&2;}
++ { echo "$as_me:$LINENO: WARNING: linux/atmsap.h: section \"Present But Cannot Be Compiled\"" >&5
++echo "$as_me: WARNING: linux/atmsap.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: linux/atmsap.h: proceeding with the preprocessor's result" >&5
+ echo "$as_me: WARNING: linux/atmsap.h: proceeding with the preprocessor's result" >&2;}
++ { echo "$as_me:$LINENO: WARNING: linux/atmsap.h: in the future, the compiler will take precedence" >&5
++echo "$as_me: WARNING: linux/atmsap.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+-## ------------------------------------ ##
+-## Report this to bug-autoconf@gnu.org. ##
+-## ------------------------------------ ##
++## ------------------------------------------ ##
++## Report this to the AC_PACKAGE_NAME lists. ##
++## ------------------------------------------ ##
+ _ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+@@ -8281,7 +8549,6 @@
+ ac_check_lib_save_LIBS=$LIBS
+ LIBS="-lresolv $LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -8299,11 +8566,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+- (eval $ac_link) 2>&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); } &&
+- { ac_try='test -s conftest$ac_exeext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -8316,7 +8592,8 @@
+
+ ac_cv_lib_resolv_main=no
+ fi
+-rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext \
++ conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_check_lib_save_LIBS
+ fi
+ echo "$as_me:$LINENO: result: $ac_cv_lib_resolv_main" >&5
+@@ -8477,7 +8754,6 @@
+ ac_check_lib_save_LIBS=$LIBS
+ LIBS="-lmpr $LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+-#line $LINENO "configure"
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -8495,11 +8771,20 @@
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+- (eval $ac_link) 2>&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); } &&
+- { ac_try='test -s conftest$ac_exeext'
++ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; } &&
++ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -8512,7 +8797,8 @@
+
+ ac_cv_lib_mpr_main=no
+ fi
+-rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++rm -f conftest.err conftest.$ac_objext \
++ conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_check_lib_save_LIBS
+ fi
+ echo "$as_me:$LINENO: result: $ac_cv_lib_mpr_main" >&5
+@@ -8539,7 +8825,7 @@
+ fi;
+
+
+- ac_config_files="$ac_config_files Makefile doc/Makefile m4/Makefile src/Makefile src/include/Makefile src/lib/Makefile src/test/Makefile src/debug/Makefile src/qgen/Makefile src/saal/Makefile src/sigd/Makefile src/maint/Makefile src/arpd/Makefile src/ilmid/Makefile src/ilmid/asn1/Makefile src/man/Makefile src/led/Makefile src/lane/Makefile src/mpoad/Makefile src/switch/Makefile src/switch/debug/Makefile src/switch/tcp/Makefile src/config/Makefile src/config/init-redhat/Makefile src/extra/Makefile src/extra/linux-atm.spec src/extra/ANS/Makefile"
++ ac_config_files="$ac_config_files Makefile doc/Makefile m4/Makefile src/Makefile src/include/Makefile src/lib/Makefile src/br2684/Makefile"
+ cat >confcache <<\_ACEOF
+ # This file is a shell script that caches the results of configure
+ # tests run on this system so they can be shared between configure
+@@ -8568,13 +8854,13 @@
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+- "s/'/'\\\\''/g;
+- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
++ "s/'/'\\\\''/g;
++ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n \
+- "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
++ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+ } |
+@@ -8604,13 +8890,13 @@
+ # trailing colons and then remove the whole line if VPATH becomes empty
+ # (actually we leave an empty line to preserve line numbers).
+ if test "x$srcdir" = x.; then
+- ac_vpsub='/^[ ]*VPATH[ ]*=/{
++ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+ s/:*\$(srcdir):*/:/;
+ s/:*\${srcdir}:*/:/;
+ s/:*@srcdir@:*/:/;
+-s/^\([^=]*=[ ]*\):*/\1/;
++s/^\([^=]*=[ ]*\):*/\1/;
+ s/:*$//;
+-s/^[^=]*=[ ]*$//;
++s/^[^=]*=[ ]*$//;
+ }'
+ fi
+
+@@ -8621,7 +8907,7 @@
+ for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_i=`echo "$ac_i" |
+- sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
++ sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+ # 2. Add them.
+ ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+@@ -8665,9 +8951,10 @@
+ elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+ fi
++DUALCASE=1; export DUALCASE # for MKS sh
+
+ # Support unset when possible.
+-if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
++if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+ else
+ as_unset=false
+@@ -8686,7 +8973,7 @@
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+ do
+- if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then
++ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+@@ -8865,16 +9152,17 @@
+ if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+ else
++ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+ fi
+
+ as_executable_p="test -f"
+
+ # Sed expression to map a string onto a valid CPP name.
+-as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
++as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+ # Sed expression to map a string onto a valid variable name.
+-as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
++as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+ # IFS
+@@ -8901,7 +9189,7 @@
+ cat >&5 <<_CSEOF
+
+ This file was extended by $as_me, which was
+-generated by GNU Autoconf 2.57. Invocation command line was
++generated by GNU Autoconf 2.59. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+@@ -8945,9 +9233,9 @@
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+- instantiate the configuration file FILE
++ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+- instantiate the configuration header FILE
++ instantiate the configuration header FILE
+
+ Configuration files:
+ $config_files
+@@ -8964,11 +9252,10 @@
+ cat >>$CONFIG_STATUS <<_ACEOF
+ ac_cs_version="\\
+ config.status
+-configured by $0, generated by GNU Autoconf 2.57,
++configured by $0, generated by GNU Autoconf 2.59,
+ with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+-Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+-Free Software Foundation, Inc.
++Copyright (C) 2003 Free Software Foundation, Inc.
+ This config.status script is free software; the Free Software Foundation
+ gives unlimited permission to copy, distribute and modify it."
+ srcdir=$srcdir
+@@ -9080,27 +9367,7 @@
+ "src/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
+ "src/include/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/include/Makefile" ;;
+ "src/lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/lib/Makefile" ;;
+- "src/test/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/test/Makefile" ;;
+- "src/debug/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/debug/Makefile" ;;
+- "src/qgen/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/qgen/Makefile" ;;
+- "src/saal/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/saal/Makefile" ;;
+- "src/sigd/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/sigd/Makefile" ;;
+- "src/maint/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/maint/Makefile" ;;
+- "src/arpd/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/arpd/Makefile" ;;
+- "src/ilmid/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/ilmid/Makefile" ;;
+- "src/ilmid/asn1/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/ilmid/asn1/Makefile" ;;
+- "src/man/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/man/Makefile" ;;
+- "src/led/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/led/Makefile" ;;
+- "src/lane/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/lane/Makefile" ;;
+- "src/mpoad/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/mpoad/Makefile" ;;
+- "src/switch/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/switch/Makefile" ;;
+- "src/switch/debug/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/switch/debug/Makefile" ;;
+- "src/switch/tcp/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/switch/tcp/Makefile" ;;
+- "src/config/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/config/Makefile" ;;
+- "src/config/init-redhat/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/config/init-redhat/Makefile" ;;
+- "src/extra/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/extra/Makefile" ;;
+- "src/extra/linux-atm.spec" ) CONFIG_FILES="$CONFIG_FILES src/extra/linux-atm.spec" ;;
+- "src/extra/ANS/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/extra/ANS/Makefile" ;;
++ "src/br2684/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/br2684/Makefile" ;;
+ "default-1" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
+ "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+@@ -9267,9 +9534,9 @@
+ (echo ':t
+ /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+ if test -z "$ac_sed_cmds"; then
+- ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
++ ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+ else
+- ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
++ ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+ fi
+ ac_sed_frag=`expr $ac_sed_frag + 1`
+ ac_beg=$ac_end
+@@ -9287,21 +9554,21 @@
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+- cat >$tmp/stdin
+- ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+- ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
++ cat >$tmp/stdin
++ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
++ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+- ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
++ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+ $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+- X"$ac_file" : 'X\(//\)[^/]' \| \
+- X"$ac_file" : 'X\(//\)$' \| \
+- X"$ac_file" : 'X\(/\)' \| \
+- . : '\(.\)' 2>/dev/null ||
++ X"$ac_file" : 'X\(//\)[^/]' \| \
++ X"$ac_file" : 'X\(//\)$' \| \
++ X"$ac_file" : 'X\(/\)' \| \
++ . : '\(.\)' 2>/dev/null ||
+ echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+@@ -9317,10 +9584,10 @@
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+- X"$as_dir" : 'X\(//\)[^/]' \| \
+- X"$as_dir" : 'X\(//\)$' \| \
+- X"$as_dir" : 'X\(/\)' \| \
+- . : '\(.\)' 2>/dev/null ||
++ X"$as_dir" : 'X\(//\)[^/]' \| \
++ X"$as_dir" : 'X\(//\)$' \| \
++ X"$as_dir" : 'X\(/\)' \| \
++ . : '\(.\)' 2>/dev/null ||
+ echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+@@ -9358,12 +9625,45 @@
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+ esac
+-# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+-# absolute.
+-ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+-ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
+-ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+-ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
++
++# Do not use `cd foo && pwd` to compute absolute paths, because
++# the directories may not exist.
++case `pwd` in
++.) ac_abs_builddir="$ac_dir";;
++*)
++ case "$ac_dir" in
++ .) ac_abs_builddir=`pwd`;;
++ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
++ *) ac_abs_builddir=`pwd`/"$ac_dir";;
++ esac;;
++esac
++case $ac_abs_builddir in
++.) ac_abs_top_builddir=${ac_top_builddir}.;;
++*)
++ case ${ac_top_builddir}. in
++ .) ac_abs_top_builddir=$ac_abs_builddir;;
++ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
++ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
++ esac;;
++esac
++case $ac_abs_builddir in
++.) ac_abs_srcdir=$ac_srcdir;;
++*)
++ case $ac_srcdir in
++ .) ac_abs_srcdir=$ac_abs_builddir;;
++ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
++ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
++ esac;;
++esac
++case $ac_abs_builddir in
++.) ac_abs_top_srcdir=$ac_top_srcdir;;
++*)
++ case $ac_top_srcdir in
++ .) ac_abs_top_srcdir=$ac_abs_builddir;;
++ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
++ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
++ esac;;
++esac
+
+
+ case $INSTALL in
+@@ -9371,11 +9671,6 @@
+ *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+ esac
+
+- if test x"$ac_file" != x-; then
+- { echo "$as_me:$LINENO: creating $ac_file" >&5
+-echo "$as_me: creating $ac_file" >&6;}
+- rm -f "$ac_file"
+- fi
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+@@ -9385,7 +9680,7 @@
+ configure_input="$ac_file. "
+ fi
+ configure_input=$configure_input"Generated from `echo $ac_file_in |
+- sed 's,.*/,,'` by configure."
++ sed 's,.*/,,'` by configure."
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+@@ -9394,26 +9689,32 @@
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+- # Absolute (can't be DOS-style, as IFS=:)
+- test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
++ # Absolute (can't be DOS-style, as IFS=:)
++ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+ echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+- echo $f;;
++ echo "$f";;
+ *) # Relative
+- if test -f "$f"; then
+- # Build tree
+- echo $f
+- elif test -f "$srcdir/$f"; then
+- # Source tree
+- echo $srcdir/$f
+- else
+- # /dev/null tree
+- { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
++ if test -f "$f"; then
++ # Build tree
++ echo "$f"
++ elif test -f "$srcdir/$f"; then
++ # Source tree
++ echo "$srcdir/$f"
++ else
++ # /dev/null tree
++ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+ echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+- fi;;
++ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
++
++ if test x"$ac_file" != x-; then
++ { echo "$as_me:$LINENO: creating $ac_file" >&5
++echo "$as_me: creating $ac_file" >&6;}
++ rm -f "$ac_file"
++ fi
+ _ACEOF
+ cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+@@ -9453,12 +9754,12 @@
+ # 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_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)'
++ac_dB='[ ].*$,\1#\2'
+ ac_dC=' '
+ ac_dD=',;t'
+ # ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+-ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
++ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ ac_uB='$,\1#\2define\3'
+ ac_uC=' '
+ ac_uD=',;t'
+@@ -9467,11 +9768,11 @@
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+- cat >$tmp/stdin
+- ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+- ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
++ cat >$tmp/stdin
++ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
++ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+- ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
++ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+@@ -9485,28 +9786,29 @@
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+- # Absolute (can't be DOS-style, as IFS=:)
+- test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
++ # Absolute (can't be DOS-style, as IFS=:)
++ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+ echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+- echo $f;;
++ # Do quote $f, to prevent DOS paths from being IFS'd.
++ echo "$f";;
+ *) # Relative
+- if test -f "$f"; then
+- # Build tree
+- echo $f
+- elif test -f "$srcdir/$f"; then
+- # Source tree
+- echo $srcdir/$f
+- else
+- # /dev/null tree
+- { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
++ if test -f "$f"; then
++ # Build tree
++ echo "$f"
++ elif test -f "$srcdir/$f"; then
++ # Source tree
++ echo "$srcdir/$f"
++ else
++ # /dev/null tree
++ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+ echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+- fi;;
++ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+ # Remove the trailing spaces.
+- sed 's/[ ]*$//' $ac_file_inputs >$tmp/in
++ sed 's/[ ]*$//' $ac_file_inputs >$tmp/in
+
+ _ACEOF
+
+@@ -9529,9 +9831,9 @@
+ s,[\\$`],\\&,g
+ t clear
+ : clear
+-s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
++s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+ t end
+-s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
++s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+ : end
+ _ACEOF
+ # If some macros were called several times there might be several times
+@@ -9545,13 +9847,13 @@
+ # 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.undefs <<\_ACEOF
+-s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
++s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+ _ACEOF
+
+ # Break up conftest.defines because some shells have a limit on the size
+ # of here documents, and old seds have small limits too (100 cmds).
+ echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+-echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
++echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+ echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+ echo ' :' >>$CONFIG_STATUS
+ rm -f conftest.tail
+@@ -9560,7 +9862,7 @@
+ # Write a limited-size here document to $tmp/defines.sed.
+ echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#define' lines.
+- echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS
++ echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+@@ -9587,7 +9889,7 @@
+ # Write a limited-size here document to $tmp/undefs.sed.
+ echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#undef'
+- echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS
++ echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+@@ -9621,10 +9923,10 @@
+ else
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+ $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+- X"$ac_file" : 'X\(//\)[^/]' \| \
+- X"$ac_file" : 'X\(//\)$' \| \
+- X"$ac_file" : 'X\(/\)' \| \
+- . : '\(.\)' 2>/dev/null ||
++ X"$ac_file" : 'X\(//\)[^/]' \| \
++ X"$ac_file" : 'X\(//\)$' \| \
++ X"$ac_file" : 'X\(/\)' \| \
++ . : '\(.\)' 2>/dev/null ||
+ echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+@@ -9640,10 +9942,10 @@
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+- X"$as_dir" : 'X\(//\)[^/]' \| \
+- X"$as_dir" : 'X\(//\)$' \| \
+- X"$as_dir" : 'X\(/\)' \| \
+- . : '\(.\)' 2>/dev/null ||
++ X"$as_dir" : 'X\(//\)[^/]' \| \
++ X"$as_dir" : 'X\(//\)$' \| \
++ X"$as_dir" : 'X\(/\)' \| \
++ . : '\(.\)' 2>/dev/null ||
+ echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+@@ -9675,16 +9977,41 @@
+ ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_dir=`(dirname "$ac_dest") 2>/dev/null ||
+ $as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+- X"$ac_dest" : 'X\(//\)[^/]' \| \
+- X"$ac_dest" : 'X\(//\)$' \| \
+- X"$ac_dest" : 'X\(/\)' \| \
+- . : '\(.\)' 2>/dev/null ||
++ X"$ac_dest" : 'X\(//\)[^/]' \| \
++ X"$ac_dest" : 'X\(//\)$' \| \
++ X"$ac_dest" : 'X\(/\)' \| \
++ . : '\(.\)' 2>/dev/null ||
+ echo X"$ac_dest" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
++ { if $as_mkdir_p; then
++ mkdir -p "$ac_dir"
++ else
++ as_dir="$ac_dir"
++ as_dirs=
++ while test ! -d "$as_dir"; do
++ as_dirs="$as_dir $as_dirs"
++ as_dir=`(dirname "$as_dir") 2>/dev/null ||
++$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
++ X"$as_dir" : 'X\(//\)[^/]' \| \
++ X"$as_dir" : 'X\(//\)$' \| \
++ X"$as_dir" : 'X\(/\)' \| \
++ . : '\(.\)' 2>/dev/null ||
++echo X"$as_dir" |
++ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
++ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
++ /^X\(\/\/\)$/{ s//\1/; q; }
++ /^X\(\/\).*/{ s//\1/; q; }
++ s/.*/./; q'`
++ done
++ test ! -n "$as_dirs" || mkdir $as_dirs
++ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
++echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
++ { (exit 1); exit 1; }; }; }
++
+ ac_builddir=.
+
+ if test "$ac_dir" != .; then
+@@ -9710,12 +10037,45 @@
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+ esac
+-# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+-# absolute.
+-ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+-ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
+-ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+-ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
++
++# Do not use `cd foo && pwd` to compute absolute paths, because
++# the directories may not exist.
++case `pwd` in
++.) ac_abs_builddir="$ac_dir";;
++*)
++ case "$ac_dir" in
++ .) ac_abs_builddir=`pwd`;;
++ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
++ *) ac_abs_builddir=`pwd`/"$ac_dir";;
++ esac;;
++esac
++case $ac_abs_builddir in
++.) ac_abs_top_builddir=${ac_top_builddir}.;;
++*)
++ case ${ac_top_builddir}. in
++ .) ac_abs_top_builddir=$ac_abs_builddir;;
++ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
++ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
++ esac;;
++esac
++case $ac_abs_builddir in
++.) ac_abs_srcdir=$ac_srcdir;;
++*)
++ case $ac_srcdir in
++ .) ac_abs_srcdir=$ac_abs_builddir;;
++ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
++ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
++ esac;;
++esac
++case $ac_abs_builddir in
++.) ac_abs_top_srcdir=$ac_top_srcdir;;
++*)
++ case $ac_top_srcdir in
++ .) ac_abs_top_srcdir=$ac_abs_builddir;;
++ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
++ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
++ esac;;
++esac
+
+
+ { echo "$as_me:$LINENO: executing $ac_dest commands" >&5
+diff -urN linux-atm.old/doc/Makefile.in linux-atm.dev/doc/Makefile.in
+--- linux-atm.old/doc/Makefile.in 2005-08-23 01:12:10.885781000 +0200
++++ linux-atm.dev/doc/Makefile.in 2005-08-23 01:12:46.551359544 +0200
+@@ -63,24 +63,35 @@
+ host_triplet = @host@
+ target_alias = @target_alias@
+ target_triplet = @target@
++AR = @AR@
+ AS = @AS@
+ CC = @CC@
++CXX = @CXX@
++CXXCPP = @CXXCPP@
+ DLLTOOL = @DLLTOOL@
+ ECHO = @ECHO@
++EGREP = @EGREP@
+ EXEEXT = @EXEEXT@
++F77 = @F77@
++GCJ = @GCJ@
++GCJFLAGS = @GCJFLAGS@
++HAVE_LIB = @HAVE_LIB@
+ LEX = @LEX@
++LIB = @LIB@
+ LIBTOOL = @LIBTOOL@
+ LIBTOOL_DEPS = @LIBTOOL_DEPS@
+ LIBVER_AGE = @LIBVER_AGE@
+ LIBVER_CURRENT = @LIBVER_CURRENT@
+ LIBVER_REVISION = @LIBVER_REVISION@
+ LN_S = @LN_S@
++LTLIB = @LTLIB@
+ MAKEINFO = @MAKEINFO@
+ OBJDUMP = @OBJDUMP@
+ OBJEXT = @OBJEXT@
+ PACKAGE = @PACKAGE@
+ PERL = @PERL@
+ RANLIB = @RANLIB@
++RC = @RC@
+ STRIP = @STRIP@
+ VERSION = @VERSION@
+ YACC = @YACC@
+diff -urN linux-atm.old/m4/Makefile.in linux-atm.dev/m4/Makefile.in
+--- linux-atm.old/m4/Makefile.in 2005-08-23 01:12:10.850786000 +0200
++++ linux-atm.dev/m4/Makefile.in 2005-08-23 01:12:46.559358328 +0200
+@@ -63,24 +63,35 @@
+ host_triplet = @host@
+ target_alias = @target_alias@
+ target_triplet = @target@
++AR = @AR@
+ AS = @AS@
+ CC = @CC@
++CXX = @CXX@
++CXXCPP = @CXXCPP@
+ DLLTOOL = @DLLTOOL@
+ ECHO = @ECHO@
++EGREP = @EGREP@
+ EXEEXT = @EXEEXT@
++F77 = @F77@
++GCJ = @GCJ@
++GCJFLAGS = @GCJFLAGS@
++HAVE_LIB = @HAVE_LIB@
+ LEX = @LEX@
++LIB = @LIB@
+ LIBTOOL = @LIBTOOL@
+ LIBTOOL_DEPS = @LIBTOOL_DEPS@
+ LIBVER_AGE = @LIBVER_AGE@
+ LIBVER_CURRENT = @LIBVER_CURRENT@
+ LIBVER_REVISION = @LIBVER_REVISION@
+ LN_S = @LN_S@
++LTLIB = @LTLIB@
+ MAKEINFO = @MAKEINFO@
+ OBJDUMP = @OBJDUMP@
+ OBJEXT = @OBJEXT@
+ PACKAGE = @PACKAGE@
+ PERL = @PERL@
+ RANLIB = @RANLIB@
++RC = @RC@
+ STRIP = @STRIP@
+ VERSION = @VERSION@
+ YACC = @YACC@
+diff -urN linux-atm.old/Makefile.in linux-atm.dev/Makefile.in
+--- linux-atm.old/Makefile.in 2005-08-23 01:12:10.830789000 +0200
++++ linux-atm.dev/Makefile.in 2005-08-23 01:12:46.542360912 +0200
+@@ -63,24 +63,35 @@
+ host_triplet = @host@
+ target_alias = @target_alias@
+ target_triplet = @target@
++AR = @AR@
+ AS = @AS@
+ CC = @CC@
++CXX = @CXX@
++CXXCPP = @CXXCPP@
+ DLLTOOL = @DLLTOOL@
+ ECHO = @ECHO@
++EGREP = @EGREP@
+ EXEEXT = @EXEEXT@
++F77 = @F77@
++GCJ = @GCJ@
++GCJFLAGS = @GCJFLAGS@
++HAVE_LIB = @HAVE_LIB@
+ LEX = @LEX@
++LIB = @LIB@
+ LIBTOOL = @LIBTOOL@
+ LIBTOOL_DEPS = @LIBTOOL_DEPS@
+ LIBVER_AGE = @LIBVER_AGE@
+ LIBVER_CURRENT = @LIBVER_CURRENT@
+ LIBVER_REVISION = @LIBVER_REVISION@
+ LN_S = @LN_S@
++LTLIB = @LTLIB@
+ MAKEINFO = @MAKEINFO@
+ OBJDUMP = @OBJDUMP@
+ OBJEXT = @OBJEXT@
+ PACKAGE = @PACKAGE@
+ PERL = @PERL@
+ RANLIB = @RANLIB@
++RC = @RC@
+ STRIP = @STRIP@
+ VERSION = @VERSION@
+ YACC = @YACC@
+diff -urN linux-atm.old/src/br2684/Makefile.in linux-atm.dev/src/br2684/Makefile.in
+--- linux-atm.old/src/br2684/Makefile.in 2005-08-23 01:12:10.884781000 +0200
++++ linux-atm.dev/src/br2684/Makefile.in 2005-08-23 01:12:46.632347232 +0200
+@@ -57,11 +57,15 @@
+ NORMAL_UNINSTALL = :
+ PRE_UNINSTALL = :
+ POST_UNINSTALL = :
++build_alias = @build_alias@
++build_triplet = @build@
+ host_alias = @host_alias@
+ host_triplet = @host@
++target_alias = @target_alias@
++target_triplet = @target@
+ AR = @AR@
+ AS = @AS@
+-CC = /usr/src/openwrt/staging_dir_mipsel/bin/mipsel-linux-gcc
++CC = @CC@
+ CXX = @CXX@
+ CXXCPP = @CXXCPP@
+ DLLTOOL = @DLLTOOL@
+@@ -117,9 +121,9 @@
+ br2684ctl_DEPENDENCIES = $(top_builddir)/src/lib/libatm.la
+ br2684ctl_LDFLAGS =
+ CFLAGS = @CFLAGS@
+-COMPILE = $(TARGET_CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+-LTCOMPILE = $(LIBTOOL) --mode=compile $(TARGET_CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+-CCLD = $(TARGET_CC)
++COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
++LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
++CCLD = $(CC)
+ LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+ man8dir = $(mandir)/man8
+ MANS = $(man_MANS)
+diff -urN linux-atm.old/src/include/Makefile.in linux-atm.dev/src/include/Makefile.in
+--- linux-atm.old/src/include/Makefile.in 2005-08-23 01:12:10.851786000 +0200
++++ linux-atm.dev/src/include/Makefile.in 2005-08-23 01:12:46.585354376 +0200
+@@ -63,24 +63,35 @@
+ host_triplet = @host@
+ target_alias = @target_alias@
+ target_triplet = @target@
++AR = @AR@
+ AS = @AS@
+ CC = @CC@
++CXX = @CXX@
++CXXCPP = @CXXCPP@
+ DLLTOOL = @DLLTOOL@
+ ECHO = @ECHO@
++EGREP = @EGREP@
+ EXEEXT = @EXEEXT@
++F77 = @F77@
++GCJ = @GCJ@
++GCJFLAGS = @GCJFLAGS@
++HAVE_LIB = @HAVE_LIB@
+ LEX = @LEX@
++LIB = @LIB@
+ LIBTOOL = @LIBTOOL@
+ LIBTOOL_DEPS = @LIBTOOL_DEPS@
+ LIBVER_AGE = @LIBVER_AGE@
+ LIBVER_CURRENT = @LIBVER_CURRENT@
+ LIBVER_REVISION = @LIBVER_REVISION@
+ LN_S = @LN_S@
++LTLIB = @LTLIB@
+ MAKEINFO = @MAKEINFO@
+ OBJDUMP = @OBJDUMP@
+ OBJEXT = @OBJEXT@
+ PACKAGE = @PACKAGE@
+ PERL = @PERL@
+ RANLIB = @RANLIB@
++RC = @RC@
+ STRIP = @STRIP@
+ VERSION = @VERSION@
+ YACC = @YACC@
+diff -urN linux-atm.old/src/lib/Makefile.in linux-atm.dev/src/lib/Makefile.in
+--- linux-atm.old/src/lib/Makefile.in 2005-08-23 01:12:10.852786000 +0200
++++ linux-atm.dev/src/lib/Makefile.in 2005-08-23 01:12:46.607351032 +0200
+@@ -65,24 +65,35 @@
+ host_triplet = @host@
+ target_alias = @target_alias@
+ target_triplet = @target@
++AR = @AR@
+ AS = @AS@
+ CC = @CC@
++CXX = @CXX@
++CXXCPP = @CXXCPP@
+ DLLTOOL = @DLLTOOL@
+ ECHO = @ECHO@
++EGREP = @EGREP@
+ EXEEXT = @EXEEXT@
++F77 = @F77@
++GCJ = @GCJ@
++GCJFLAGS = @GCJFLAGS@
++HAVE_LIB = @HAVE_LIB@
+ LEX = @LEX@
++LIB = @LIB@
+ LIBTOOL = @LIBTOOL@
+ LIBTOOL_DEPS = @LIBTOOL_DEPS@
+ LIBVER_AGE = @LIBVER_AGE@
+ LIBVER_CURRENT = @LIBVER_CURRENT@
+ LIBVER_REVISION = @LIBVER_REVISION@
+ LN_S = @LN_S@
++LTLIB = @LTLIB@
+ MAKEINFO = @MAKEINFO@
+ OBJDUMP = @OBJDUMP@
+ OBJEXT = @OBJEXT@
+ PACKAGE = @PACKAGE@
+ PERL = @PERL@
+ RANLIB = @RANLIB@
++RC = @RC@
+ STRIP = @STRIP@
+ VERSION = @VERSION@
+ YACC = @YACC@
+diff -urN linux-atm.old/src/Makefile.in linux-atm.dev/src/Makefile.in
+--- linux-atm.old/src/Makefile.in 2005-08-23 01:12:10.851786000 +0200
++++ linux-atm.dev/src/Makefile.in 2005-08-23 01:12:46.572356352 +0200
+@@ -63,30 +63,40 @@
+ host_triplet = @host@
+ target_alias = @target_alias@
+ target_triplet = @target@
++AR = @AR@
+ AS = @AS@
+ CC = @CC@
++CXX = @CXX@
++CXXCPP = @CXXCPP@
+ DLLTOOL = @DLLTOOL@
+ ECHO = @ECHO@
++EGREP = @EGREP@
+ EXEEXT = @EXEEXT@
++F77 = @F77@
++GCJ = @GCJ@
++GCJFLAGS = @GCJFLAGS@
++HAVE_LIB = @HAVE_LIB@
+ LEX = @LEX@
++LIB = @LIB@
+ LIBTOOL = @LIBTOOL@
+ LIBTOOL_DEPS = @LIBTOOL_DEPS@
+ LIBVER_AGE = @LIBVER_AGE@
+ LIBVER_CURRENT = @LIBVER_CURRENT@
+ LIBVER_REVISION = @LIBVER_REVISION@
+ LN_S = @LN_S@
++LTLIB = @LTLIB@
+ MAKEINFO = @MAKEINFO@
+ OBJDUMP = @OBJDUMP@
+ OBJEXT = @OBJEXT@
+ PACKAGE = @PACKAGE@
+ PERL = @PERL@
+ RANLIB = @RANLIB@
++RC = @RC@
+ STRIP = @STRIP@
+ VERSION = @VERSION@
+ YACC = @YACC@
+
+-SUBDIRS = include lib
+-
++SUBDIRS = include lib br2684
+ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+ CONFIG_HEADER = ../config.h
+ CONFIG_CLEAN_FILES =
diff --git a/package/linux-atm/patches/400-stdint_local_instead_of_host.patch b/package/linux-atm/patches/400-stdint_local_instead_of_host.patch
new file mode 100644
index 0000000000..7c1e8c14f4
--- /dev/null
+++ b/package/linux-atm/patches/400-stdint_local_instead_of_host.patch
@@ -0,0 +1,12 @@
+diff -ur linux-atm.old/src/include/stdint.h linux-atm.dev/src/include/stdint.h
+--- linux-atm.old/src/include/stdint.h 2001-09-03 20:41:06.000000000 +0200
++++ linux-atm.dev/src/include/stdint.h 2006-09-27 19:13:56.000000000 +0200
+@@ -6,7 +6,7 @@
+
+ #if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
+
+-#include "/usr/include/stdint.h"
++#include_next <stdint.h>
+
+ #elif __GLIBC__ >= 2
+
diff --git a/package/madwifi/Makefile b/package/madwifi/Makefile
new file mode 100644
index 0000000000..a4180063f4
--- /dev/null
+++ b/package/madwifi/Makefile
@@ -0,0 +1,133 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=madwifi
+PKG_VERSION:=0.9.2
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=@SF/$(PKG_NAME)
+PKG_MD5SUM:=a75baacbe07085ddc5cb28e1fb43edbb
+PKG_CAT:=bzcat
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/kmod-madwifi
+ SECTION:=kernel
+ CATEGORY:=Kernel drivers
+ DEFAULT:=y if LINUX_2_6_BRCM || LINUX_2_6_ARUBA || LINUX_2_4_AR531X || LINUX_2_6_XSCALE, m if ALL
+ TITLE:=Driver for Atheros wireless chipsets
+ DESCRIPTION:=\
+ This package contains a driver for Atheros 802.11a/b/g chipsets.
+ URL:=http://madwifi.org/
+ VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE)
+endef
+
+RATE_CONTROL:=sample
+
+ifeq ($(ARCH),mips)
+ HAL_TARGET:=mips-be-elf
+endif
+ifeq ($(ARCH),mipsel)
+ HAL_TARGET:=mips-le-elf
+endif
+ifeq ($(ARCH),i386)
+ HAL_TARGET:=i386-elf
+endif
+ifeq ($(ARCH),armeb)
+ HAL_TARGET:=xscale-be-elf
+endif
+ifeq ($(ARCH),powerpc)
+ HAL_TARGET:=powerpc-be-elf
+endif
+
+BUS:=PCI
+ifneq ($(CONFIG_LINUX_2_4_AR531X),)
+ BUS:=AHB
+endif
+ifneq ($(CONFIG_LINUX_2_6_ARUBA),)
+ BUS:=PCI AHB # no suitable HAL for AHB yet.
+endif
+
+BUS_MODULES:=
+ifeq ($(findstring AHB,$(BUS)),AHB)
+ BUS_MODULES+=$(PKG_BUILD_DIR)/ath/ath_ahb.$(LINUX_KMOD_SUFFIX)
+endif
+ifeq ($(findstring PCI,$(BUS)),PCI)
+ BUS_MODULES+=$(PKG_BUILD_DIR)/ath/ath_pci.$(LINUX_KMOD_SUFFIX)
+endif
+
+MADWIFI_MAKEOPTS= -C $(PKG_BUILD_DIR) \
+ PATH="$(TARGET_PATH)" \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ TARGET="$(HAL_TARGET)" \
+ TOOLPREFIX="$(KERNEL_CROSS)" \
+ TOOLPATH="$(KERNEL_CROSS)" \
+ KERNELPATH="$(LINUX_DIR)" \
+ LDOPTS=" " \
+ ATH_RATE="ath_rate/$(RATE_CONTROL)" \
+ DOMULTI=1
+
+ifeq ($(findstring AHB,$(BUS)),AHB)
+ define Build/Compile/ahb
+ $(MAKE) $(MADWIFI_MAKEOPTS) BUS="AHB" all
+ endef
+endif
+
+ifeq ($(findstring PCI,$(BUS)),PCI)
+ define Build/Compile/pci
+ $(MAKE) $(MADWIFI_MAKEOPTS) BUS="PCI" all
+ endef
+endif
+
+define Build/Compile
+ $(call Build/Compile/ahb)
+ $(call Build/Compile/pci)
+endef
+
+define Build/InstallDev
+ mkdir -p $(STAGING_DIR)/usr/include/madwifi
+ $(CP) $(PKG_BUILD_DIR)/include $(STAGING_DIR)/usr/include/madwifi/
+ mkdir -p $(STAGING_DIR)/usr/include/madwifi/net80211
+ $(CP) $(PKG_BUILD_DIR)/net80211/*.h $(STAGING_DIR)/usr/include/madwifi/net80211/
+endef
+
+define Build/UninstallDev
+ rm -rf $(STAGING_DIR)/usr/include/madwifi
+endef
+
+define Package/kmod-madwifi/install
+ mkdir -p $(1)/etc/modules.d
+ mkdir -p $(1)/etc/init.d
+ mkdir -p $(1)/lib/modules/$(LINUX_VERSION)
+ mkdir -p $(1)/usr/sbin
+ install -m0644 ./files/madwifi.modules $(1)/etc/modules.d/20-madwifi
+ echo ath_rate_$(RATE_CONTROL) >> $(1)/etc/modules.d/20-madwifi
+ifeq ($(findstring AHB,$(BUS)),AHB)
+ echo ath_ahb >> $(1)/etc/modules.d/20-madwifi
+endif
+ifeq ($(findstring PCI,$(BUS)),PCI)
+ echo ath_pci >> $(1)/etc/modules.d/20-madwifi
+endif
+ install -m0755 ./files/madwifi.init $(1)/etc/init.d/S20madwifi
+ $(CP) \
+ $(PKG_BUILD_DIR)/ath/ath_hal.$(LINUX_KMOD_SUFFIX) \
+ $(BUS_MODULES) \
+ $(PKG_BUILD_DIR)/ath_rate/$(RATE_CONTROL)/ath_rate_$(RATE_CONTROL).$(LINUX_KMOD_SUFFIX) \
+ $(PKG_BUILD_DIR)/net80211/wlan*.$(LINUX_KMOD_SUFFIX) \
+ $(1)/lib/modules/$(LINUX_VERSION)/
+ $(CP) $(PKG_BUILD_DIR)/tools/{madwifi_multi,80211debug,80211stats,athchans,athctrl,athdebug,athkey,athstats,wlanconfig} $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,kmod-madwifi))
diff --git a/package/madwifi/files/madwifi.init b/package/madwifi/files/madwifi.init
new file mode 100644
index 0000000000..73eb11017e
--- /dev/null
+++ b/package/madwifi/files/madwifi.init
@@ -0,0 +1,4 @@
+#!/bin/sh /etc/rc.common
+start() {
+ iwpriv ath0 mode 3
+}
diff --git a/package/madwifi/files/madwifi.modules b/package/madwifi/files/madwifi.modules
new file mode 100644
index 0000000000..515c1e9aa1
--- /dev/null
+++ b/package/madwifi/files/madwifi.modules
@@ -0,0 +1,10 @@
+wlan
+wlan_scan_ap
+wlan_scan_sta
+ath_hal
+ath_rate_sample
+wlan_acl
+wlan_ccmp
+wlan_tkip
+wlan_wep
+wlan_xauth
diff --git a/package/madwifi/patches/100-kernel_cflags.patch b/package/madwifi/patches/100-kernel_cflags.patch
new file mode 100644
index 0000000000..39ac1437e1
--- /dev/null
+++ b/package/madwifi/patches/100-kernel_cflags.patch
@@ -0,0 +1,42 @@
+diff -ur madwifi.old/hal/public/mips-be-elf.inc madwifi.dev/hal/public/mips-be-elf.inc
+--- madwifi.old/hal/public/mips-be-elf.inc 2006-05-27 04:48:16.000000000 +0200
++++ madwifi.dev/hal/public/mips-be-elf.inc 2006-08-29 18:17:44.000000000 +0200
+@@ -71,5 +71,5 @@
+
+ LDOPTS= -EB
+ COPTS+= -DAH_BYTE_ORDER=AH_BIG_ENDIAN
+-COPTS+= -G 0 -EB -mno-abicalls -fno-pic -mips2 -Wa,--trap \
++COPTS+= -G 0 -mno-abicalls -fno-pic -mips32 -Wa,--trap \
+ -fno-strict-aliasing -fno-common -fomit-frame-pointer -mlong-calls
+diff -ur madwifi.old/hal/public/mips-le-elf.inc madwifi.dev/hal/public/mips-le-elf.inc
+--- madwifi.old/hal/public/mips-le-elf.inc 2006-05-27 04:48:16.000000000 +0200
++++ madwifi.dev/hal/public/mips-le-elf.inc 2006-08-29 18:17:57.000000000 +0200
+@@ -68,5 +68,5 @@
+
+ LDOPTS= -EL
+ COPTS+= -DAH_BYTE_ORDER=AH_LITTLE_ENDIAN
+-COPTS+= -G 0 -EL -mno-abicalls -fno-pic -mips2 -Wa,--trap \
++COPTS+= -G 0 -mno-abicalls -fno-pic -mips32 -Wa,--trap \
+ -fno-strict-aliasing -fno-common -fomit-frame-pointer -mlong-calls
+diff -ur madwifi.old/hal/public/xscale-be-elf.inc madwifi.dev/hal/public/xscale-be-elf.inc
+--- madwifi.old/hal/public/xscale-be-elf.inc 2006-05-27 04:48:16.000000000 +0200
++++ madwifi.dev/hal/public/xscale-be-elf.inc 2006-08-29 18:01:39.000000000 +0200
+@@ -77,5 +77,5 @@
+
+ LDOPTS= -EB
+ COPTS+= -DAH_BYTE_ORDER=AH_BIG_ENDIAN
+-COPTS+= -march=armv4 -mbig-endian -fno-strict-aliasing -fno-common -mapcs-32 \
++COPTS+= -march=armv5te -mtune=xscale -mbig-endian -fno-strict-aliasing -fno-common \
+ -mtune=xscale -mshort-load-bytes -msoft-float -mfp=2
+diff -ur madwifi.old/Makefile madwifi.dev/Makefile
+--- madwifi.old/Makefile 2006-07-14 07:15:56.000000000 +0200
++++ madwifi.dev/Makefile 2006-08-29 18:01:39.000000000 +0200
+@@ -54,7 +54,7 @@
+
+ all: modules tools
+
+-modules: configcheck svnversion.h
++modules: svnversion.h
+ ifdef LINUX24
+ for i in $(DIRS_MODULES); do \
+ $(MAKE) -C $$i || exit 1; \
diff --git a/package/madwifi/patches/101-no_werror.patch b/package/madwifi/patches/101-no_werror.patch
new file mode 100644
index 0000000000..d71021eb0e
--- /dev/null
+++ b/package/madwifi/patches/101-no_werror.patch
@@ -0,0 +1,11 @@
+--- madwifi.old/Makefile.inc 2006-07-14 07:15:56.000000000 +0200
++++ madwifi.dev/Makefile.inc 2006-08-30 05:20:27.000000000 +0200
+@@ -181,7 +181,7 @@
+ #
+ TOOLS= $(DEPTH)/tools
+
+-COPTS+= -Werror
++# COPTS+= -Werror
+ INCS= -include $(obj)/$(DEPTH)/include/compat.h -I$(obj)/$(DEPTH)/include
+
+ ifeq ($(strip $(BUS)),AHB)
diff --git a/package/madwifi/patches/102-multicall_binary.patch b/package/madwifi/patches/102-multicall_binary.patch
new file mode 100644
index 0000000000..8fa65676d4
--- /dev/null
+++ b/package/madwifi/patches/102-multicall_binary.patch
@@ -0,0 +1,369 @@
+diff -urN madwifi-0.9.2.old/tools/80211debug.c madwifi-0.9.2.dev/tools/80211debug.c
+--- madwifi-0.9.2.old/tools/80211debug.c 2006-03-10 14:23:50.000000000 +0100
++++ madwifi-0.9.2.dev/tools/80211debug.c 2006-08-29 17:49:50.000000000 +0200
+@@ -49,6 +49,10 @@
+ #include <getopt.h>
+ #include <err.h>
+
++#ifdef DOMULTI
++#include "do_multi.h"
++#endif
++
+ #define N(a) (sizeof(a)/sizeof(a[0]))
+
+ const char *progname;
+@@ -180,9 +184,19 @@
+ }
+ #endif /* __linux__ */
+
++#ifdef DOMULTI
++
++int
++a80211debug_init(int argc, char *argv[])
++{
++
++#else
++
+ int
+ main(int argc, char *argv[])
+ {
++
++#endif
+ const char *ifname = "ath0";
+ const char *cp, *tp;
+ const char *sep;
+diff -urN madwifi-0.9.2.old/tools/80211stats.c madwifi-0.9.2.dev/tools/80211stats.c
+--- madwifi-0.9.2.old/tools/80211stats.c 2006-05-27 08:21:18.000000000 +0200
++++ madwifi-0.9.2.dev/tools/80211stats.c 2006-08-29 17:49:50.000000000 +0200
+@@ -58,6 +58,10 @@
+ #include "net80211/ieee80211_crypto.h"
+ #include "net80211/ieee80211_ioctl.h"
+
++#ifdef DOMULTI
++#include "do_multi.h"
++#endif
++
+ #ifndef SIOCG80211STATS
+ #define SIOCG80211STATS (SIOCDEVPRIVATE + 2)
+ #endif
+@@ -241,9 +245,19 @@
+ #undef STAT
+ }
+
++#ifdef DOMULTI
++
++int
++a80211stats_init(int argc, char *argv[])
++{
++
++#else
++
+ int
+ main(int argc, char *argv[])
+ {
++
++#endif
+ int c, len;
+ struct ieee80211req_sta_info *si;
+ u_int8_t buf[24*1024], *cp;
+diff -urN madwifi-0.9.2.old/tools/athchans.c madwifi-0.9.2.dev/tools/athchans.c
+--- madwifi-0.9.2.old/tools/athchans.c 2006-02-01 21:07:11.000000000 +0100
++++ madwifi-0.9.2.dev/tools/athchans.c 2006-08-29 17:49:50.000000000 +0200
+@@ -57,6 +57,10 @@
+ #include "net80211/ieee80211_crypto.h"
+ #include "net80211/ieee80211_ioctl.h"
+
++#ifdef DOMULTI
++#include "do_multi.h"
++#endif
++
+ static int s = -1;
+ const char *progname;
+
+@@ -134,9 +138,20 @@
+ }
+
+ #define MAXCHAN ((int)(sizeof(struct ieee80211req_chanlist) * NBBY))
++
++#ifdef DOMULTI
++
++int
++athchans_init(int argc, char *argv[])
++{
++
++#else
++
+ int
+ main(int argc, char *argv[])
+ {
++
++#endif
+ const char *ifname = "wifi0";
+ struct ieee80211req_chanlist chanlist;
+ int c;
+diff -urN madwifi-0.9.2.old/tools/athctrl.c madwifi-0.9.2.dev/tools/athctrl.c
+--- madwifi-0.9.2.old/tools/athctrl.c 2006-02-03 13:03:03.000000000 +0100
++++ madwifi-0.9.2.dev/tools/athctrl.c 2006-08-29 17:49:50.000000000 +0200
+@@ -53,6 +53,10 @@
+
+ #include <net/if.h>
+
++#ifdef DOMULTI
++#include "do_multi.h"
++#endif
++
+ static int
+ setsysctrl(const char *dev, const char *control , u_long value)
+ {
+@@ -87,9 +91,19 @@
+ exit(1);
+ }
+
++#ifdef DOMULTI
++
++int
++athctrl_init(int argc, char *argv[])
++{
++
++#else
++
+ int
+ main(int argc, char *argv[])
+ {
++
++#endif
+ char device[IFNAMSIZ + 1];
+ int distance = -1;
+ int c;
+diff -urN madwifi-0.9.2.old/tools/athdebug.c madwifi-0.9.2.dev/tools/athdebug.c
+--- madwifi-0.9.2.old/tools/athdebug.c 2006-05-05 06:17:59.000000000 +0200
++++ madwifi-0.9.2.dev/tools/athdebug.c 2006-08-29 17:49:50.000000000 +0200
+@@ -52,6 +52,10 @@
+ #include <getopt.h>
+ #include <err.h>
+
++#ifdef DOMULTI
++#include "do_multi.h"
++#endif
++
+ #define N(a) (sizeof(a)/sizeof(a[0]))
+
+ const char *progname;
+@@ -179,9 +183,20 @@
+ }
+ #endif /* __linux__ */
+
++#ifdef DOMULTI
++
++int
++athdebug_init(int argc, char *argv[])
++{
++
++#else
++
+ int
+ main(int argc, char *argv[])
+ {
++
++#endif
++
+ #ifdef __linux__
+ const char *ifname = "wifi0";
+ #else
+diff -urN madwifi-0.9.2.old/tools/athkey.c madwifi-0.9.2.dev/tools/athkey.c
+--- madwifi-0.9.2.old/tools/athkey.c 2006-02-01 21:07:11.000000000 +0100
++++ madwifi-0.9.2.dev/tools/athkey.c 2006-08-29 17:49:50.000000000 +0200
+@@ -57,6 +57,10 @@
+ #include "net80211/ieee80211_crypto.h"
+ #include "net80211/ieee80211_ioctl.h"
+
++#ifdef DOMULTI
++#include "do_multi.h"
++#endif
++
+ static int s = -1;
+ const char *progname;
+
+@@ -207,9 +211,19 @@
+ exit(-1);
+ }
+
++#ifdef DOMULTI
++
++int
++athkey_init(int argc, char *argv[])
++{
++
++#else
++
+ int
+ main(int argc, char *argv[])
+ {
++
++#endif
+ const char *ifname = "wifi0";
+ struct ieee80211req_key setkey;
+ struct ieee80211req_del_key delkey;
+diff -urN madwifi-0.9.2.old/tools/athstats.c madwifi-0.9.2.dev/tools/athstats.c
+--- madwifi-0.9.2.old/tools/athstats.c 2006-05-05 06:20:50.000000000 +0200
++++ madwifi-0.9.2.dev/tools/athstats.c 2006-08-29 17:49:50.000000000 +0200
+@@ -64,6 +64,10 @@
+ #include "ah_desc.h"
+ #include "if_athioctl.h"
+
++#ifdef DOMULTI
++#include "do_multi.h"
++#endif
++
+ static const struct {
+ u_int phyerr;
+ const char* desc;
+@@ -227,9 +231,20 @@
+ signalled = 1;
+ }
+
++#ifdef DOMULTI
++
++int
++athstats_init(int argc, char *argv[])
++{
++
++#else
++
+ int
+ main(int argc, char *argv[])
+ {
++
++#endif
++
+ #ifdef __linux__
+ const char *ifname = "wifi0";
+ #else
+diff -urN madwifi-0.9.2.old/tools/do_multi.c madwifi-0.9.2.dev/tools/do_multi.c
+--- madwifi-0.9.2.old/tools/do_multi.c 1970-01-01 01:00:00.000000000 +0100
++++ madwifi-0.9.2.dev/tools/do_multi.c 2006-08-29 17:49:50.000000000 +0200
+@@ -0,0 +1,30 @@
++#include <string.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);
++
++ return ret;
++}
+diff -urN madwifi-0.9.2.old/tools/do_multi.h madwifi-0.9.2.dev/tools/do_multi.h
+--- madwifi-0.9.2.old/tools/do_multi.h 1970-01-01 01:00:00.000000000 +0100
++++ madwifi-0.9.2.dev/tools/do_multi.h 2006-08-29 17:49:50.000000000 +0200
+@@ -0,0 +1,9 @@
++
++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[]);
+diff -urN madwifi-0.9.2.old/tools/Makefile madwifi-0.9.2.dev/tools/Makefile
+--- madwifi-0.9.2.old/tools/Makefile 2006-07-14 07:15:56.000000000 +0200
++++ madwifi-0.9.2.dev/tools/Makefile 2006-08-29 17:49:50.000000000 +0200
+@@ -49,6 +49,12 @@
+
+ ALL= athstats 80211stats athkey athchans athctrl \
+ athdebug 80211debug wlanconfig
++
++ifdef DOMULTI
++OBJS= do_multi.o athstats.o 80211stats.o athkey.o athchans.o athctrl.o \
++ athdebug.o 80211debug.o wlanconfig.o
++ALL= ${OBJS} madwifi_multi
++endif
+
+ all: $(ALL)
+
+@@ -59,6 +65,30 @@
+
+ all: $(ALL)
+
++athstats.o: athstats.c
++ ${CC} -c -o athstats.o -DDOMULTI=1 ${ALL_CFLAGS} -I../ath athstats.c
++80211stats.o: 80211stats.c
++ ${CC} -c -o 80211stats.o -DDOMULTI=1 ${ALL_CFLAGS} 80211stats.c
++athkey.o: athkey.c
++ ${CC} -c -o athkey.o -DDOMULTI=1 ${ALL_CFLAGS} athkey.c
++athchans.o: athchans.c
++ ${CC} -c -o athchans.o -DDOMULTI=1 ${ALL_CFLAGS} athchans.c
++athctrl.o: athctrl.c
++ ${CC} -c -o athctrl.o -DDOMULTI=1 ${ALL_CFLAGS} athctrl.c
++athdebug.o: athdebug.c
++ ${CC} -c -o athdebug.o -DDOMULTI=1 ${ALL_CFLAGS} athdebug.c
++wlanconfig.o: wlanconfig.c
++ ${CC} -c -o wlanconfig.o -DDOMULTI=1 ${ALL_CFLAGS} wlanconfig.c
++80211debug.o: 80211debug.c
++ ${CC} -c -o 80211debug.o -DDOMULTI=1 ${ALL_CFLAGS} 80211debug.c
++do_multi.o: do_multi.c
++ ${CC} -c -o do_multi.o -DDOMULTI=1 ${ALL_CFLAGS} do_multi.c
++madwifi_multi:
++ ${CC} -o madwifi_multi ${LDFLAGS} ${OBJS}
++ for i in athstats 80211stats athkey athchans athctrl athdebug wlanconfig 80211debug; do \
++ ln -s -f madwifi_multi $$i; \
++ done
++
+ athstats: athstats.c
+ $(CC) -o athstats $(ALL_CFLAGS) -I../ath $(LDFLAGS) athstats.c
+ 80211stats: 80211stats.c
+diff -urN madwifi-0.9.2.old/tools/wlanconfig.c madwifi-0.9.2.dev/tools/wlanconfig.c
+--- madwifi-0.9.2.old/tools/wlanconfig.c 2006-05-14 09:17:29.000000000 +0200
++++ madwifi-0.9.2.dev/tools/wlanconfig.c 2006-08-29 17:49:50.000000000 +0200
+@@ -60,6 +60,10 @@
+ #include "net80211/ieee80211_crypto.h"
+ #include "net80211/ieee80211_ioctl.h"
+
++#ifdef DOMULTI
++#include "do_multi.h"
++#endif
++
+ /*
+ * These are taken from ieee80211_node.h
+ */
+@@ -96,9 +100,19 @@
+
+ int verbose = 0;
+
++#ifdef DOMULTI
++
++int
++wlanconfig_init(int argc, char *argv[])
++{
++
++#else
++
+ int
+ main(int argc, char *argv[])
+ {
++
++#endif
+ const char *ifname, *cmd;
+ unsigned char bnounit = 0;
+ char *if_base = NULL;
diff --git a/package/madwifi/patches/103-disable_rfkill.patch b/package/madwifi/patches/103-disable_rfkill.patch
new file mode 100644
index 0000000000..80a45e31d3
--- /dev/null
+++ b/package/madwifi/patches/103-disable_rfkill.patch
@@ -0,0 +1,12 @@
+diff -urN madwifi-0.9.2.old/ath/if_ath.c madwifi-0.9.2.dev/ath/if_ath.c
+--- madwifi-0.9.2.old/ath/if_ath.c 2006-07-08 08:47:19.000000000 +0200
++++ madwifi-0.9.2.dev/ath/if_ath.c 2006-08-29 17:49:50.000000000 +0200
+@@ -251,7 +251,7 @@
+ static int ath_outdoor = AH_FALSE; /* enable outdoor use */
+ static int ath_xchanmode = AH_TRUE; /* enable extended channels */
+ static char *autocreate = NULL;
+-static int rfkill = -1;
++static int rfkill = 0;
+ static int countrycode = -1;
+ static int outdoor = -1;
+ static int xchanmode = -1;
diff --git a/package/madwifi/patches/104-apmode_by_default.patch b/package/madwifi/patches/104-apmode_by_default.patch
new file mode 100644
index 0000000000..fc5cb978b0
--- /dev/null
+++ b/package/madwifi/patches/104-apmode_by_default.patch
@@ -0,0 +1,12 @@
+diff -urN madwifi-0.9.2.old/ath/if_ath.c madwifi-0.9.2.dev/ath/if_ath.c
+--- madwifi-0.9.2.old/ath/if_ath.c 2006-08-29 17:49:50.000000000 +0200
++++ madwifi-0.9.2.dev/ath/if_ath.c 2006-08-29 17:49:50.000000000 +0200
+@@ -387,7 +387,7 @@
+ struct ath_hal *ah;
+ HAL_STATUS status;
+ int error = 0, i;
+- int autocreatemode = IEEE80211_M_STA;
++ int autocreatemode = IEEE80211_M_HOSTAP;
+ u_int8_t csz;
+
+ sc->devid = devid;
diff --git a/package/mini_fo/Makefile b/package/mini_fo/Makefile
new file mode 100644
index 0000000000..38ad63754b
--- /dev/null
+++ b/package/mini_fo/Makefile
@@ -0,0 +1,50 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=mini_fo
+PKG_VERSION:=0.6.2pre1
+PKG_RELEASE:=1
+
+PKG_SOURCE:=mini_fo-0-6-2-pre1.tar.bz2
+PKG_SOURCE_URL:=http://www.denx.de/twiki/pub/Know/MiniFOHome/
+PKG_MD5SUM:=acd12157be25d7b3c8df90914049403e
+PKG_CAT:=bzcat
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/mini_fo-0-6-2-pre1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/kmod-mini-fo
+ SECTION:=kernel
+ CATEGORY:=Kernel drivers
+ TITLE:=The mini fanout overlay file system
+ URL:=http://www.denx.de/wiki/Know.MiniFOHome
+ VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE)
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ KERNELVERSION="$(KERNEL)" \
+ KERNEL_SRC="$(LINUX_DIR)" \
+ all
+endef
+
+define Package/kmod-mini-fo/install
+ install -m0755 -d $(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) $(PKG_BUILD_DIR)/mini_fo.$(LINUX_KMOD_SUFFIX) \
+ $(1)/lib/modules/$(LINUX_VERSION)/
+ install -m0755 -d $(1)/etc/modules.d
+ echo "mini_fo" > $(1)/etc/modules.d/15-mini-fo
+endef
+
+$(eval $(call BuildPackage,kmod-mini-fo))
diff --git a/package/mini_fo/patches/101-kmod_build.patch b/package/mini_fo/patches/101-kmod_build.patch
new file mode 100644
index 0000000000..9b47a69ab7
--- /dev/null
+++ b/package/mini_fo/patches/101-kmod_build.patch
@@ -0,0 +1,52 @@
+diff -Nur mini_fo-0-6-2-pre1/Makefile mini_fo-0-6-2-pre1.patched/Makefile
+--- mini_fo-0-6-2-pre1/Makefile 2005-10-15 12:49:43.000000000 +0200
++++ mini_fo-0-6-2-pre1.patched/Makefile 2005-12-25 14:03:36.864205250 +0100
+@@ -26,36 +26,29 @@
+ # allow custom override of TOPINC for fistgen developers
+ -include fistdev.mk
+
++obj-m := mini_fo.o
++mini_fo-objs := meta.o dentry.o file.o inode.o main.o super.o state.o aux.o
++
+ ifeq ($(KERNELVERSION),2.4)
+-CFLAGS = -D__KERNEL__ -DMODULE -DFISTGEN -I. ${TOPINC} -O2 -Wall -Wno-unused -g -fno-common -fno-schedule-insns -fno-schedule-insns2 -fno-strict-aliasing -msoft-float -Werror
+-ifeq ($(ARCH),um)
+-CFLAGS += $(shell cd $(KERNEL_SRC) ; make script 'SCRIPT=@echo $$(CFLAGS)' ARCH=um)
+-endif
+-UCFLAGS = -DFISTGEN -I. ${TOPINC} -g -O2 -Wall -Wno-unused -Werror
+-endif
+
+-CC = $(CROSS_COMPILE)gcc
+-LD = $(CROSS_COMPILE)ld
++O_TARGET := $(obj-m)
++obj-y := $(mini_fo-objs)
+
+-obj-m := mini_fo.o
+-mini_fo-objs := meta.o dentry.o file.o inode.o main.o super.o state.o aux.o
++-include $(TOPDIR)/Rules.make
++
++endif
+
+ all: mini_fo$(KERNELVERSION)
+
+-mini_fo2.4: ${obj-m}
++mini_fo2.4:
++ $(MAKE) -C ${KERNEL_SRC} TOPDIR="${KERNEL_SRC}" SUBDIRS=$(shell pwd) modules
+
+ mini_fo2.6:
+- make -C ${KERNEL_SRC} SUBDIRS=$(PWD) modules
+-
+-${obj-m}: ${mini_fo-objs}
+- $(LD) -o ${obj-m} -r ${mini_fo-objs}
+-
+-tags:
+- ctags -R -e
++ $(MAKE) -C ${KERNEL_SRC} SUBDIRS=$(shell pwd) modules
+
+ clean:
+ ifeq ($(KERNELVERSION),2.6)
+- -make -C ${KERNEL_SRC} SUBDIRS=$(PWD) clean
++ -$(MAKE) -C ${KERNEL_SRC} SUBDIRS=$(shell pwd) clean
+ endif
+ rm -f ${obj-m} ${mini_fo-objs} ${obj-m:.o=.ko} *.d .*.flags *~
+ rm -f TAGS
diff --git a/package/mini_fo/patches/102-mutex_change.patch b/package/mini_fo/patches/102-mutex_change.patch
new file mode 100644
index 0000000000..4dec47bf5e
--- /dev/null
+++ b/package/mini_fo/patches/102-mutex_change.patch
@@ -0,0 +1,602 @@
+From: <mk@mary.denx.de>
+Date: Tue, 24 Jan 2006 14:09:21 +0000 (+0100)
+Subject: Support for new mutex infrastructure
+X-Git-Url: http://www.denx.de/cgi-bin/gitweb.cgi?p=mini_fo.git;a=commitdiff;h=1dcc028729060ea83ea662155634b33ae8e2c493
+
+ Support for new mutex infrastructure
+ (7892f2f48d165a34b0b8130c8a195dfd807b8cb6)
+---
+
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,13 @@
++2006-01-24 Markus Klotzbuecher <mk@mary.denx.de>
++
++ * Add tons of ugly ifdefs to Ed L. Cashin's mutex patch to
++ retain backwards compatibility.
++
++2006-01-24 Ed L. Cashin <ecashin@coraid.com>
++
++ * Support for the new mutex infrastructure
++ (7892f2f48d165a34b0b8130c8a195dfd807b8cb6)
++
+ 2005-10-15 Markus Klotzbuecher <mk@localhost.localdomain>
+
+ * Bugfix for a serious memory leak in mini_fo_follow_link.
+--- a/aux.c
++++ b/aux.c
+@@ -435,8 +435,11 @@ int build_sto_structure(dentry_t *dir, d
+
+ /* was: hidden_sto_dir_dentry = lock_parent(hidden_sto_dentry); */
+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_sto_dir_dentry->d_inode->i_sem);
+-
++#endif
+ /* lets be safe */
+ if(dtohd2(dir) != hidden_sto_dir_dentry) {
+ printk(KERN_CRIT "mini_fo: build_sto_structure: invalid parameter or meta data corruption [2].\n");
+@@ -457,7 +460,11 @@ int build_sto_structure(dentry_t *dir, d
+ if(err) {
+ printk(KERN_CRIT "mini_fo: build_sto_structure: failed to create storage dir [1].\n");
+ /* was: unlock_dir(dir); */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&dir->d_inode->i_mutex);
++#else
+ up(&dir->d_inode->i_sem);
++#endif
+ dput(dir);
+ return err;
+ }
+@@ -466,7 +473,11 @@ int build_sto_structure(dentry_t *dir, d
+ if(!dtohd2(dentry)->d_inode) {
+ printk(KERN_CRIT "mini_fo: build_sto_structure: failed to create storage dir [2].\n");
+ /* was: unlock_dir(dir); */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&dir->d_inode->i_mutex);
++#else
+ up(&dir->d_inode->i_sem);
++#endif
+ dput(dir);
+ return 1;
+ }
+@@ -485,7 +496,11 @@ int build_sto_structure(dentry_t *dir, d
+ hidden_sto_dir_dentry->d_inode);
+ dir->d_inode->i_nlink++;
+ /* was: unlock_dir(hidden_sto_dir_dentry); */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+ dput(hidden_sto_dir_dentry);
+ return 0;
+ }
+--- a/file.c
++++ b/file.c
+@@ -613,18 +613,34 @@ mini_fo_fsync(file_t *file, dentry_t *de
+ if ((hidden_file = ftohf(file)) != NULL) {
+ hidden_dentry = dtohd(dentry);
+ if (hidden_file->f_op && hidden_file->f_op->fsync) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_dentry->d_inode->i_sem);
++#endif
+ err1 = hidden_file->f_op->fsync(hidden_file, hidden_dentry, datasync);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_dentry->d_inode->i_sem);
++#endif
+ }
+ }
+
+ if ((hidden_file = ftohf2(file)) != NULL) {
+ hidden_dentry = dtohd2(dentry);
+ if (hidden_file->f_op && hidden_file->f_op->fsync) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_dentry->d_inode->i_sem);
++#endif
+ err2 = hidden_file->f_op->fsync(hidden_file, hidden_dentry, datasync);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_dentry->d_inode->i_sem);
++#endif
+ }
+ }
+ else
+--- a/inode.c
++++ b/inode.c
+@@ -355,7 +355,11 @@ mini_fo_link(dentry_t *old_dentry, inode
+
+ /* was: hidden_dir_dentry = lock_parent(hidden_new_dentry); */
+ hidden_dir_dentry = dget(hidden_new_dentry->d_parent);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_dir_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_dir_dentry->d_inode->i_sem);
++#endif
+
+ err = vfs_link(hidden_old_dentry,
+ hidden_dir_dentry->d_inode,
+@@ -374,7 +378,11 @@ mini_fo_link(dentry_t *old_dentry, inode
+
+ out_lock:
+ /* was: unlock_dir(hidden_dir_dentry); */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_dir_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_dir_dentry->d_inode->i_sem);
++#endif
+ dput(hidden_dir_dentry);
+
+ dput(hidden_new_dentry);
+@@ -452,7 +460,11 @@ mini_fo_symlink(inode_t *dir, dentry_t *
+ dget(hidden_sto_dentry);
+ /* was: hidden_sto_dir_dentry = lock_parent(hidden_sto_dentry); */
+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ mode = S_IALLUGO;
+@@ -481,7 +493,11 @@ mini_fo_symlink(inode_t *dir, dentry_t *
+
+ out_lock:
+ /* was: unlock_dir(hidden_sto_dir_dentry); */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+ dput(hidden_sto_dir_dentry);
+
+ dput(hidden_sto_dentry);
+@@ -524,7 +540,11 @@ mini_fo_rmdir(inode_t *dir, dentry_t *de
+
+ /* was:hidden_sto_dir_dentry = lock_parent(hidden_sto_dentry); */
+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+
+ /* avoid destroying the hidden inode if the file is in use */
+ dget(hidden_sto_dentry);
+@@ -572,7 +592,11 @@ mini_fo_rmdir(inode_t *dir, dentry_t *de
+ dentry->d_name.len);
+ }
+ /* was: unlock_dir(hidden_sto_dir_dentry); */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+ dput(hidden_sto_dir_dentry);
+ goto out;
+ }
+@@ -602,7 +626,12 @@ mini_fo_rmdir(inode_t *dir, dentry_t *de
+
+ /* was: hidden_sto_dir_dentry = lock_parent(hidden_sto_dentry);*/
+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+
+ /* avoid destroying the hidden inode if the file is in use */
+ dget(hidden_sto_dentry);
+@@ -630,7 +659,11 @@ mini_fo_rmdir(inode_t *dir, dentry_t *de
+ dtopd(dentry)->state = NON_EXISTANT;
+
+ /* was: unlock_dir(hidden_sto_dir_dentry); */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+ dput(hidden_sto_dir_dentry);
+
+ goto out;
+@@ -641,7 +674,12 @@ mini_fo_rmdir(inode_t *dir, dentry_t *de
+
+ /* was: hidden_sto_dir_dentry = lock_parent(hidden_sto_dentry);*/
+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+
+ /* avoid destroying the hidden inode if the file is in use */
+ dget(hidden_sto_dentry);
+@@ -668,7 +706,12 @@ mini_fo_rmdir(inode_t *dir, dentry_t *de
+ dentry->d_inode->i_nlink = itohi2(dentry->d_inode)->i_nlink;
+ dtopd(dentry)->state = DELETED;
+ /* was: unlock_dir(hidden_sto_dir_dentry); */
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+ dput(hidden_sto_dir_dentry);
+ goto out;
+ }
+@@ -1294,11 +1337,19 @@ mini_fo_getxattr(struct dentry *dentry,
+ encoded_name = (char *)name;
+ encoded_value = (char *)value;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_dentry->d_inode->i_sem);
++#endif
+ /* lock_kernel() already done by caller. */
+ err = hidden_dentry->d_inode->i_op->getxattr(hidden_dentry, encoded_name, encoded_value, size);
+ /* unlock_kernel() will be done by caller. */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_dentry->d_inode->i_sem);
++#endif
+ }
+ return err;
+ }
+@@ -1340,11 +1391,19 @@ mini_fo_setxattr(struct dentry *dentry,
+ encoded_name = (char *)name;
+ encoded_value = (char *)value;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_dentry->d_inode->i_sem);
++#endif
+ /* lock_kernel() already done by caller. */
+ err = hidden_dentry->d_inode->i_op->setxattr(hidden_dentry, encoded_name, encoded_value, size, flags);
+ /* unlock_kernel() will be done by caller. */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_dentry->d_inode->i_sem);
++#endif
+ }
+ return err;
+ }
+@@ -1372,11 +1431,19 @@ mini_fo_removexattr(struct dentry *dentr
+ if (hidden_dentry->d_inode->i_op->removexattr) {
+ encoded_name = (char *)name;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_dentry->d_inode->i_sem);
++#endif
+ /* lock_kernel() already done by caller. */
+ err = hidden_dentry->d_inode->i_op->removexattr(hidden_dentry, encoded_name);
+ /* unlock_kernel() will be done by caller. */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_dentry->d_inode->i_sem);
++#endif
+ }
+ return err;
+ }
+@@ -1403,11 +1470,20 @@ mini_fo_listxattr(struct dentry *dentry,
+
+ if (hidden_dentry->d_inode->i_op->listxattr) {
+ encoded_list = list;
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_dentry->d_inode->i_sem);
++#endif
+ /* lock_kernel() already done by caller. */
+ err = hidden_dentry->d_inode->i_op->listxattr(hidden_dentry, encoded_list, size);
+ /* unlock_kernel() will be done by caller. */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_dentry->d_inode->i_sem);
++#endif
+ }
+ return err;
+ }
+--- a/meta.c
++++ b/meta.c
+@@ -650,9 +650,20 @@ int meta_sync_d_list(dentry_t *dentry, i
+ struct iattr newattrs;
+ newattrs.ia_size = 0;
+ newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&meta_dentry->d_inode->i_mutex);
++#else
+ down(&meta_dentry->d_inode->i_sem);
++#endif
+ err = notify_change(meta_dentry, &newattrs);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&meta_dentry->d_inode->i_mutex);
++#else
+ up(&meta_dentry->d_inode->i_sem);
++#endif
++
+ if(err || meta_dentry->d_inode->i_size != 0) {
+ printk(KERN_CRIT "mini_fo: meta_sync_d_list: \
+ ERROR truncating meta file.\n");
+@@ -780,9 +791,19 @@ int meta_sync_r_list(dentry_t *dentry, i
+ struct iattr newattrs;
+ newattrs.ia_size = 0;
+ newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&meta_dentry->d_inode->i_mutex);
++#else
+ down(&meta_dentry->d_inode->i_sem);
++#endif
+ err = notify_change(meta_dentry, &newattrs);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&meta_dentry->d_inode->i_mutex);
++#else
+ up(&meta_dentry->d_inode->i_sem);
++#endif
+ if(err || meta_dentry->d_inode->i_size != 0) {
+ printk(KERN_CRIT "mini_fo: meta_sync_r_list: \
+ ERROR truncating meta file.\n");
+--- a/mini_fo.h
++++ b/mini_fo.h
+@@ -433,6 +433,33 @@ fist_copy_attr_all(inode_t *dest, const
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ /* copied from linux/fs.h */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++static inline void double_lock(struct dentry *d1, struct dentry *d2)
++{
++ struct mutex *m1 = &d1->d_inode->i_mutex;
++ struct mutex *m2 = &d2->d_inode->i_mutex;
++ if (m1 != m2) {
++ if ((unsigned long) m1 < (unsigned long) m2) {
++ struct mutex *tmp = m2;
++ m2 = m1; m1 = tmp;
++ }
++ mutex_lock(m1);
++ }
++ mutex_lock(m2);
++}
++
++static inline void double_unlock(struct dentry *d1, struct dentry *d2)
++{
++ struct mutex *m1 = &d1->d_inode->i_mutex;
++ struct mutex *m2 = &d2->d_inode->i_mutex;
++ mutex_unlock(m1);
++ if (m1 != m2)
++ mutex_unlock(m2);
++ dput(d1);
++ dput(d2);
++}
++
++#else
+ static inline void double_down(struct semaphore *s1, struct semaphore *s2)
+ {
+ if (s1 != s2) {
+@@ -463,8 +490,8 @@ static inline void double_unlock(struct
+ dput(d1);
+ dput(d2);
+ }
+-
+-#endif
++#endif /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) */
++#endif /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */
+ #endif /* __KERNEL__ */
+
+ /*
+--- a/mmap.c
++++ b/mmap.c
+@@ -478,7 +478,11 @@ mini_fo_commit_write(file_t *file, page_
+ if (ftopd(file) != NULL)
+ hidden_file = ftohf(file);
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_inode->i_mutex);
++#else
+ down(&hidden_inode->i_sem);
++#endif
+ /* find lower page (returns a locked page) */
+ hidden_page = grab_cache_page(hidden_inode->i_mapping, page->index);
+ if (!hidden_page)
+@@ -556,7 +560,12 @@ mini_fo_commit_write(file_t *file, page_
+ ClearPageUptodate(page);
+ else
+ SetPageUptodate(page);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_inode->i_mutex);
++#else
+ up(&hidden_inode->i_sem);
++#endif
+ print_exit_status(err);
+ return err; /* assume all is ok */
+ }
+--- a/state.c
++++ b/state.c
+@@ -44,7 +44,12 @@ int create_sto_reg_file(dentry_t *dentry
+
+ /* lock parent */
+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+
+ err = PTR_ERR(hidden_sto_dir_dentry);
+ if (IS_ERR(hidden_sto_dir_dentry))
+@@ -97,7 +102,11 @@ int create_sto_reg_file(dentry_t *dentry
+ hidden_sto_dir_dentry->d_inode);
+
+ out_lock:
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+ dput(hidden_sto_dir_dentry);
+ out:
+ return err;
+@@ -130,7 +139,12 @@ n");
+
+ /* was: hidden_sto_dir_dentry = lock_parent(hidden_sto_dentry); */
+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+
+ err = PTR_ERR(hidden_sto_dir_dentry);
+ if (IS_ERR(hidden_sto_dir_dentry))
+@@ -184,7 +198,11 @@ n");
+
+ out_lock:
+ /* was: unlock_dir(hidden_sto_dir_dentry); */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+ dput(hidden_sto_dir_dentry);
+ out:
+ return err;
+@@ -217,7 +235,12 @@ int create_sto_nod(dentry_t *dentry, int
+
+ /* lock parent */
+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+
+ err = PTR_ERR(hidden_sto_dir_dentry);
+ if (IS_ERR(hidden_sto_dir_dentry))
+@@ -260,7 +283,11 @@ int create_sto_nod(dentry_t *dentry, int
+ fist_copy_attr_timesizes(dir, hidden_sto_dir_dentry->d_inode);
+
+ out_lock:
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+ dput(hidden_sto_dir_dentry);
+ out:
+ return err;
+@@ -314,7 +341,12 @@ int nondir_unmod_to_mod(dentry_t *dentry
+
+ /* lock parent */
+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+
+ err = PTR_ERR(hidden_sto_dir_dentry);
+ if (IS_ERR(hidden_sto_dir_dentry))
+@@ -365,7 +397,12 @@ int nondir_unmod_to_mod(dentry_t *dentry
+ if((cp_flag == 1) && S_ISREG(dentry->d_inode->i_mode)) {
+
+ /* unlock first */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
++
+ dput(hidden_sto_dir_dentry);
+
+ tgt_dentry = dtohd2(dentry);
+@@ -383,7 +420,11 @@ int nondir_unmod_to_mod(dentry_t *dentry
+ }
+
+ out_lock:
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+ dput(hidden_sto_dir_dentry);
+ out:
+ return err;
+@@ -420,7 +461,12 @@ int nondir_creat_to_del(dentry_t *dentry
+
+ /* was: hidden_sto_dir_dentry = lock_parent(hidden_sto_dentry);*/
+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+
+ /* avoid destroying the hidden inode if the file is in use */
+ dget(hidden_sto_dentry);
+@@ -435,7 +481,11 @@ int nondir_creat_to_del(dentry_t *dentry
+ dtost(dentry) = NON_EXISTANT;
+
+ /* was: unlock_dir(hidden_sto_dir_dentry); */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+ dput(hidden_sto_dir_dentry);
+
+ out:
+@@ -464,7 +514,12 @@ int nondir_mod_to_del(dentry_t *dentry)
+
+ /* was hidden_sto_dir_dentry = lock_parent(hidden_sto_dentry); */
+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ down(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+
+ /* avoid destroying the hidden inode if the file is in use */
+ dget(hidden_sto_dentry);
+@@ -488,7 +543,11 @@ int nondir_mod_to_del(dentry_t *dentry)
+ dentry->d_name.len);
+
+ /* was: unlock_dir(hidden_sto_dir_dentry); */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex);
++#else
+ up(&hidden_sto_dir_dentry->d_inode->i_sem);
++#endif
+ dput(hidden_sto_dir_dentry);
+
+ out:
+
diff --git a/package/mini_fo/patches/103-remove_dead_code.patch b/package/mini_fo/patches/103-remove_dead_code.patch
new file mode 100644
index 0000000000..cf81601741
--- /dev/null
+++ b/package/mini_fo/patches/103-remove_dead_code.patch
@@ -0,0 +1,47 @@
+From: Markus Klotzbuecher <mk@creamnet.de>
+Date: Tue, 20 Jun 2006 14:50:26 +0000 (+0200)
+Subject: Removed some dead code (mini_fo_lock) that caused compiling to fail on
+X-Git-Url: http://www.denx.de/cgi-bin/gitweb.cgi?p=mini_fo.git;a=commitdiff;h=240ede43ad8342334494d36d6d762666f75a1c8e
+
+Removed some dead code (mini_fo_lock) that caused compiling to fail on
+recent kernels.
+---
+
+--- a/file.c
++++ b/file.c
+@@ -668,35 +668,6 @@ mini_fo_fasync(int fd, file_t *file, int
+ return (err1 || err2);
+ }
+
+-
+-STATIC int
+-mini_fo_lock(file_t *file, int cmd, struct file_lock *fl)
+-{
+- int err = -EINVAL;
+- file_t *hidden_file = NULL;
+-
+- if(!check_mini_fo_file(file))
+- goto out;
+-
+- /* which file shall we lock? */
+- if(ftohf2(file))
+- hidden_file = ftohf2(file);
+- else
+- hidden_file = ftohf(file);
+-
+- if (hidden_file->f_op->lock) {
+- fl->fl_file = hidden_file;
+- err = hidden_file->f_op->lock(hidden_file, F_GETLK, fl);
+- fl->fl_file = file;
+- } else {
+- if(posix_test_lock(hidden_file, fl))
+- err = 0;
+- }
+- out:
+- return err;
+-}
+-
+-
+ struct file_operations mini_fo_dir_fops =
+ {
+ llseek: mini_fo_llseek,
diff --git a/package/mtd/Makefile b/package/mtd/Makefile
new file mode 100644
index 0000000000..00d347fad5
--- /dev/null
+++ b/package/mtd/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.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mtd
+PKG_RELEASE:=4
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/mtd
+ SECTION:=utils
+ CATEGORY:=Base system
+ DEFAULT:=y
+ TITLE:=Update utility for trx firmware images
+ 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
+
+define Package/mtd/install
+ install -d -m0755 $(1)/sbin
+ install -m0755 $(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 0000000000..b9f256ad0c
--- /dev/null
+++ b/package/mtd/src/Makefile
@@ -0,0 +1,12 @@
+# $Id$
+
+all: mtd
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $^
+
+mtd: mtd.o
+ $(CC) -o $@ $^
+
+clean:
+ rm -f *.o mtd
diff --git a/package/mtd/src/mtd.c b/package/mtd/src/mtd.c
new file mode 100644
index 0000000000..23e99160a1
--- /dev/null
+++ b/package/mtd/src/mtd.c
@@ -0,0 +1,475 @@
+/*
+ * mtd - simple memory technology device manipulation tool
+ *
+ * Copyright (C) 2005 Waldemar Brodkorb <wbx@dass-it.de>,
+ * 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.
+ *
+ * $Id$
+ *
+ * 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 <fcntl.h>
+#include <errno.h>
+#include <error.h>
+#include <time.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 <string.h>
+
+#include <linux/mtd/mtd.h>
+
+#define TRX_MAGIC 0x30524448 /* "HDR0" */
+#define BUFSIZE (16 * 1024)
+#define MAX_ARGS 8
+
+#define DEBUG
+
+#define SYSTYPE_UNKNOWN 0
+#define SYSTYPE_BROADCOM 1
+/* to be continued */
+
+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 */
+};
+
+char buf[BUFSIZE];
+int buflen;
+
+int
+image_check_bcom(int imagefd, const char *mtd)
+{
+ struct trx_header *trx = (struct trx_header *) buf;
+ struct mtd_info_user mtdInfo;
+ int fd;
+
+ buflen = read(imagefd, buf, 32);
+ if (buflen < 32) {
+ fprintf(stdout, "Could not get image header, file too small (%ld bytes)\n", buflen);
+ return 0;
+ }
+
+ switch(trx->magic) {
+ case 0x47343557: /* W54G */
+ case 0x53343557: /* W54S */
+ case 0x73343557: /* W54s */
+ case 0x46343557: /* W54F */
+ case 0x55343557: /* W54U */
+ /* ignore the first 32 bytes */
+ buflen = read(imagefd, buf, sizeof(struct trx_header));
+ break;
+ }
+
+ if (trx->magic != TRX_MAGIC || trx->len < sizeof(struct trx_header)) {
+ fprintf(stderr, "Bad trx header\n");
+ fprintf(stderr, "If this is a firmware in bin format, like some of the\n"
+ "original firmware files are, use following command to convert to trx:\n"
+ "dd if=firmware.bin of=firmware.trx bs=32 skip=1\n");
+ return 0;
+ }
+
+ /* check if image fits to mtd device */
+ fd = mtd_open(mtd, O_RDWR | O_SYNC);
+ if(fd < 0) {
+ fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+ exit(1);
+ }
+
+ if(ioctl(fd, MEMGETINFO, &mtdInfo)) {
+ fprintf(stderr, "Could not get MTD device info from %s\n", mtd);
+ exit(1);
+ }
+
+ if(mtdInfo.size < trx->len) {
+ fprintf(stderr, "Image too big for partition: %s\n", mtd);
+ close(fd);
+ return 0;
+ }
+
+ close(fd);
+ return 1;
+}
+
+int
+image_check(int imagefd, const char *mtd)
+{
+ int fd, systype;
+ size_t count;
+ char *c;
+ FILE *f;
+
+ systype = SYSTYPE_UNKNOWN;
+ f = fopen("/proc/cpuinfo", "r");
+ while (!feof(f) && (fgets(buf, BUFSIZE - 1, f) != NULL)) {
+ if ((strncmp(buf, "system type", 11) == 0) && (c = strchr(buf, ':'))) {
+ c += 2;
+ if (strncmp(c, "Broadcom BCM947XX", 17) == 0)
+ systype = SYSTYPE_BROADCOM;
+ }
+ }
+ fclose(f);
+
+ switch(systype) {
+ case SYSTYPE_BROADCOM:
+ return image_check_bcom(imagefd, mtd);
+ default:
+ return 1;
+ }
+}
+
+int mtd_check(char *mtd)
+{
+ struct mtd_info_user mtdInfo;
+ int fd;
+
+ fd = mtd_open(mtd, O_RDWR | O_SYNC);
+ if(fd < 0) {
+ fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+ return 0;
+ }
+
+ if(ioctl(fd, MEMGETINFO, &mtdInfo)) {
+ fprintf(stderr, "Could not get MTD device info from %s\n", mtd);
+ close(fd);
+ return 0;
+ }
+
+ close(fd);
+ return 1;
+}
+
+int
+mtd_unlock(const char *mtd)
+{
+ int fd;
+ struct mtd_info_user mtdInfo;
+ struct erase_info_user mtdLockInfo;
+
+ fd = mtd_open(mtd, O_RDWR | O_SYNC);
+ if(fd < 0) {
+ fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+ exit(1);
+ }
+
+ if(ioctl(fd, MEMGETINFO, &mtdInfo)) {
+ fprintf(stderr, "Could not get MTD device info from %s\n", mtd);
+ close(fd);
+ exit(1);
+ }
+
+ mtdLockInfo.start = 0;
+ mtdLockInfo.length = mtdInfo.size;
+ if(ioctl(fd, MEMUNLOCK, &mtdLockInfo)) {
+ close(fd);
+ return 0;
+ }
+
+ close(fd);
+ return 0;
+}
+
+int
+mtd_open(const char *mtd, int flags)
+{
+ FILE *fp;
+ char dev[PATH_MAX];
+ int i;
+
+ 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/%d", i);
+ fclose(fp);
+ return open(dev, flags);
+ }
+ }
+ fclose(fp);
+ }
+
+ return open(mtd, flags);
+}
+
+int
+mtd_erase(const char *mtd)
+{
+ int fd;
+ struct mtd_info_user mtdInfo;
+ struct erase_info_user mtdEraseInfo;
+
+ fd = mtd_open(mtd, O_RDWR | O_SYNC);
+ if(fd < 0) {
+ fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+ exit(1);
+ }
+
+ if(ioctl(fd, MEMGETINFO, &mtdInfo)) {
+ fprintf(stderr, "Could not get MTD device info from %s\n", mtd);
+ close(fd);
+ exit(1);
+ }
+
+ mtdEraseInfo.length = mtdInfo.erasesize;
+
+ for (mtdEraseInfo.start = 0;
+ mtdEraseInfo.start < mtdInfo.size;
+ mtdEraseInfo.start += mtdInfo.erasesize) {
+
+ ioctl(fd, MEMUNLOCK, &mtdEraseInfo);
+ if(ioctl(fd, MEMERASE, &mtdEraseInfo)) {
+ fprintf(stderr, "Could not erase MTD device: %s\n", mtd);
+ close(fd);
+ exit(1);
+ }
+ }
+
+ close(fd);
+ return 0;
+
+}
+
+int
+mtd_write(int imagefd, const char *mtd, int quiet)
+{
+ int fd, i, result;
+ size_t r, w, e;
+ struct mtd_info_user mtdInfo;
+ struct erase_info_user mtdEraseInfo;
+ int ret = 0;
+
+ fd = mtd_open(mtd, O_RDWR | O_SYNC);
+ if(fd < 0) {
+ fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+ exit(1);
+ }
+
+ if(ioctl(fd, MEMGETINFO, &mtdInfo)) {
+ fprintf(stderr, "Could not get MTD device info from %s\n", mtd);
+ close(fd);
+ exit(1);
+ }
+
+ r = w = e = 0;
+ if (!quiet)
+ fprintf(stderr, " [ ]");
+
+ for (;;) {
+ /* buffer may contain data already (from trx check) */
+ r = buflen;
+ r += read(imagefd, buf + buflen, BUFSIZE - buflen);
+ w += r;
+
+ /* EOF */
+ if (r <= 0) break;
+
+ /* need to erase the next block before writing data to it */
+ while (w > e) {
+ mtdEraseInfo.start = e;
+ mtdEraseInfo.length = mtdInfo.erasesize;
+
+ if (!quiet)
+ fprintf(stderr, "\b\b\b[e]");
+ /* erase the chunk */
+ if (ioctl (fd,MEMERASE,&mtdEraseInfo) < 0) {
+ fprintf(stderr, "Erasing mtd failed: %s\n", mtd);
+ exit(1);
+ }
+ e += mtdInfo.erasesize;
+ }
+
+ if (!quiet)
+ fprintf(stderr, "\b\b\b[w]");
+
+ if ((result = write(fd, buf, r)) < r) {
+ if (result < 0) {
+ fprintf(stderr, "Error writing image.\n");
+ exit(1);
+ } else {
+ fprintf(stderr, "Insufficient space.\n");
+ exit(1);
+ }
+ }
+
+ buflen = 0;
+ }
+ if (!quiet)
+ fprintf(stderr, "\b\b\b\b");
+
+ close(fd);
+ return 0;
+}
+
+void usage(void)
+{
+ fprintf(stderr, "Usage: mtd [<options> ...] <command> [<arguments> ...] <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"
+ " erase erase all data on device\n"
+ " write <imagefile>|- write <imagefile> (use - for stdin) to device\n"
+ "Following options are available:\n"
+ " -q quiet mode (once: no [w] on writing,\n"
+ " twice: no status messages)\n"
+ " -r reboot after successful command\n"
+ " -f force write without trx checks\n"
+ " -e <device> erase <device> before executing the command\n\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);
+}
+
+int main (int argc, char **argv)
+{
+ int ch, i, boot, unlock, imagefd, force, quiet, unlocked;
+ char *erase[MAX_ARGS], *device, *imagefile;
+ enum {
+ CMD_ERASE,
+ CMD_WRITE,
+ CMD_UNLOCK
+ } cmd;
+
+ erase[0] = NULL;
+ boot = 0;
+ force = 0;
+ buflen = 0;
+ quiet = 0;
+
+ while ((ch = getopt(argc, argv, "frqe:")) != -1)
+ switch (ch) {
+ case 'f':
+ force = 1;
+ break;
+ case 'r':
+ boot = 1;
+ 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 '?':
+ 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], "erase") == 0) && (argc == 2)) {
+ cmd = CMD_ERASE;
+ 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);
+ }
+ }
+
+ /* check trx file before erasing or writing anything */
+ if (!image_check(imagefd, device)) {
+ if ((quiet < 2) || !force)
+ fprintf(stderr, "TRX check failed!\n");
+ if (!force)
+ exit(1);
+ } else {
+ 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) {
+ if (quiet < 2)
+ fprintf(stderr, "Unlocking %s ...\n", erase[i]);
+ mtd_unlock(erase[i]);
+ if (quiet < 2)
+ fprintf(stderr, "Erasing %s ...\n", erase[i]);
+ mtd_erase(erase[i]);
+ if (strcmp(erase[i], device) == 0)
+ unlocked = 1;
+ i++;
+ }
+
+ if (!unlocked) {
+ if (quiet < 2)
+ fprintf(stderr, "Unlocking %s ...\n", device);
+ mtd_unlock(device);
+ }
+
+ switch (cmd) {
+ case CMD_UNLOCK:
+ break;
+ case CMD_ERASE:
+ if (quiet < 2)
+ fprintf(stderr, "Erasing %s ...\n", device);
+ mtd_erase(device);
+ break;
+ case CMD_WRITE:
+ if (quiet < 2)
+ fprintf(stderr, "Writing from %s to %s ... ", imagefile, device);
+ mtd_write(imagefd, device, quiet);
+ if (quiet < 2)
+ fprintf(stderr, "\n");
+ break;
+ }
+
+ sync();
+
+ if (boot)
+ kill(1, 15); // send SIGTERM to init for reboot
+
+ return 0;
+}
diff --git a/package/nvram/Makefile b/package/nvram/Makefile
new file mode 100644
index 0000000000..ab33c11514
--- /dev/null
+++ b/package/nvram/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.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=nvram
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/nvram
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=@LINUX_2_4_BRCM
+ TITLE:=Broadcom config utility
+ DESCRIPTION:=\
+ This package contains an utility to control broadcom's 'nvram' config \\\
+ area.
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)
+endef
+
+define Build/InstallDev
+ mkdir -p $(STAGING_DIR)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/lib{nvram,shared}*.so $(STAGING_DIR)/usr/lib/
+endef
+
+define Build/UninstallDev
+ rm -f $(STAGING_DIR)/usr/lib/lib{nvram,shared}*.so
+endef
+
+define Package/nvram/install
+ install -d -m0755 $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/lib{nvram,shared}*.so $(1)/usr/lib/
+ install -d -m0755 $(1)/usr/sbin
+ install -m0755 $(PKG_BUILD_DIR)/nvram $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,nvram))
diff --git a/package/nvram/src/Makefile b/package/nvram/src/Makefile
new file mode 100644
index 0000000000..3d98209e85
--- /dev/null
+++ b/package/nvram/src/Makefile
@@ -0,0 +1,21 @@
+# $Id$
+
+LIBSHARED_OBJS := shutils.o wl.o wl_linux.o defaults.o linux_timer.o
+LIBNVRAM_OBJS := nvram_linux.o nvram_convert.o
+
+all: libshared.so libnvram.so nvram
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -I. -Iinclude -o $@ $^
+
+libshared.so: $(LIBSHARED_OBJS)
+ $(CC) -shared -o $@ $^
+
+libnvram.so: $(LIBNVRAM_OBJS)
+ $(CC) -shared -o $@ $^
+
+nvram: main.o
+ $(CC) -o $@ $^ -L. -lnvram
+
+clean:
+ rm -f *.o *.so nvram
diff --git a/package/nvram/src/bcmtimer.h b/package/nvram/src/bcmtimer.h
new file mode 100644
index 0000000000..3db9e624f9
--- /dev/null
+++ b/package/nvram/src/bcmtimer.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ *
+ * Low resolution timer interface. Timer handlers may be called
+ * in a deferred manner in a different task context after the
+ * timer expires or in the task context from which the timer
+ * was created, depending on the implementation.
+ *
+ * $Id$
+ */
+#ifndef __bcmtimer_h__
+#define __bcmtimer_h__
+
+/* ANSI headers */
+#include <time.h>
+
+/* timer ID */
+typedef unsigned int bcm_timer_module_id;
+typedef unsigned int bcm_timer_id;
+
+/* timer callback */
+typedef void (*bcm_timer_cb)(bcm_timer_id id, int data);
+
+/* OS-independant interfaces, applications should call these functions only */
+int bcm_timer_module_init(int timer_entries, bcm_timer_module_id *module_id);
+int bcm_timer_module_cleanup(bcm_timer_module_id module_id);
+int bcm_timer_module_enable(bcm_timer_module_id module_id, int enable);
+int bcm_timer_create(bcm_timer_module_id module_id, bcm_timer_id *timer_id);
+int bcm_timer_delete(bcm_timer_id timer_id);
+int bcm_timer_gettime(bcm_timer_id timer_id, struct itimerspec *value);
+int bcm_timer_settime(bcm_timer_id timer_id, const struct itimerspec *value);
+int bcm_timer_connect(bcm_timer_id timer_id, bcm_timer_cb func, int data);
+int bcm_timer_cancel(bcm_timer_id timer_id);
+int bcm_timer_change_expirytime(bcm_timer_id timer_id, const struct itimerspec *timer_spec);
+
+#endif /* #ifndef __bcmtimer_h__ */
diff --git a/package/nvram/src/defaults.c b/package/nvram/src/defaults.c
new file mode 100644
index 0000000000..119eaac72e
--- /dev/null
+++ b/package/nvram/src/defaults.c
@@ -0,0 +1,179 @@
+/*
+ * Router default NVRAM values
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#include <epivers.h>
+#include <string.h>
+#include <bcmnvram.h>
+#include <typedefs.h>
+#include <wlioctl.h>
+
+#define XSTR(s) STR(s)
+#define STR(s) #s
+
+struct nvram_tuple router_defaults[] = {
+ /* OS parameters */
+ { "os_name", "", 0 }, /* OS name string */
+ { "os_version", EPI_VERSION_STR, 0 }, /* OS revision */
+ { "os_date", __DATE__, 0 }, /* OS date */
+
+ /* Miscellaneous parameters */
+ { "timer_interval", "3600", 0 }, /* Timer interval in seconds */
+ { "ntp_server", "192.5.41.40 192.5.41.41 133.100.9.2", 0 }, /* NTP server */
+ { "time_zone", "PST8PDT", 0 }, /* Time zone (GNU TZ format) */
+ { "log_level", "0", 0 }, /* Bitmask 0:off 1:denied 2:accepted */
+ { "upnp_enable", "0", 0 }, /* Start UPnP */
+ { "ezc_enable", "1", 0 }, /* Enable EZConfig updates */
+ { "ezc_version", "1", 0 }, /* EZConfig version */
+ { "is_default", "1", 0 }, /* is it default setting: 1:yes 0:no*/
+ { "os_server", "", 0 }, /* URL for getting upgrades */
+ { "stats_server", "", 0 }, /* URL for posting stats */
+ { "console_loglevel", "1", 0 }, /* Kernel panics only */
+
+ /* Big switches */
+ { "router_disable", "0", 0 }, /* lan_proto=static lan_stp=0 wan_proto=disabled */
+ { "fw_disable", "0", 0 }, /* Disable firewall (allow new connections from the WAN) */
+
+ { "log_ipaddr", "", 0 }, /* syslog recipient */
+
+ /* LAN H/W parameters */
+ { "lan_ifname", "", 0 }, /* LAN interface name */
+ { "lan_ifnames", "", 0 }, /* Enslaved LAN interfaces */
+ { "lan_hwnames", "", 0 }, /* LAN driver names (e.g. et0) */
+ { "lan_hwaddr", "", 0 }, /* LAN interface MAC address */
+
+ /* LAN TCP/IP parameters */
+ { "lan_proto", "dhcp", 0 }, /* [static|dhcp] */
+ { "lan_ipaddr", "192.168.1.1", 0 }, /* LAN IP address */
+ { "lan_netmask", "255.255.255.0", 0 }, /* LAN netmask */
+ { "lan_stp", "0", 0 }, /* LAN spanning tree protocol */
+ { "lan_wins", "", 0 }, /* x.x.x.x x.x.x.x ... */
+ { "lan_domain", "", 0 }, /* LAN domain name */
+ { "lan_lease", "86400", 0 }, /* LAN lease time in seconds */
+
+ /* WAN H/W parameters */
+ { "wan_ifname", "", 0 }, /* WAN interface name */
+ { "wan_ifnames", "", 0 }, /* WAN interface names */
+ { "wan_hwname", "", 0 }, /* WAN driver name (e.g. et1) */
+ { "wan_hwaddr", "", 0 }, /* WAN interface MAC address */
+
+ /* WAN TCP/IP parameters */
+ { "wan_proto", "dhcp", 0 }, /* [static|dhcp|pppoe|disabled] */
+ { "wan_ipaddr", "0.0.0.0", 0 }, /* WAN IP address */
+ { "wan_netmask", "0.0.0.0", 0 }, /* WAN netmask */
+ { "wan_gateway", "0.0.0.0", 0 }, /* WAN gateway */
+ { "wan_dns", "", 0 }, /* x.x.x.x x.x.x.x ... */
+ { "wan_wins", "", 0 }, /* x.x.x.x x.x.x.x ... */
+ { "wan_hostname", "", 0 }, /* WAN hostname */
+ { "wan_domain", "", 0 }, /* WAN domain name */
+ { "wan_lease", "86400", 0 }, /* WAN lease time in seconds */
+
+ /* PPPoE parameters */
+ { "wan_pppoe_ifname", "", 0 }, /* PPPoE enslaved interface */
+ { "wan_pppoe_username", "", 0 }, /* PPP username */
+ { "wan_pppoe_passwd", "", 0 }, /* PPP password */
+ { "wan_pppoe_idletime", "60", 0 }, /* Dial on demand max idle time (seconds) */
+ { "wan_pppoe_keepalive", "0", 0 }, /* Restore link automatically */
+ { "wan_pppoe_demand", "0", 0 }, /* Dial on demand */
+ { "wan_pppoe_mru", "1492", 0 }, /* Negotiate MRU to this value */
+ { "wan_pppoe_mtu", "1492", 0 }, /* Negotiate MTU to the smaller of this value or the peer MRU */
+ { "wan_pppoe_service", "", 0 }, /* PPPoE service name */
+ { "wan_pppoe_ac", "", 0 }, /* PPPoE access concentrator name */
+
+ /* Misc WAN parameters */
+ { "wan_desc", "", 0 }, /* WAN connection description */
+ { "wan_route", "", 0 }, /* Static routes (ipaddr:netmask:gateway:metric:ifname ...) */
+ { "wan_primary", "0", 0 }, /* Primary wan connection */
+
+ { "wan_unit", "0", 0 }, /* Last configured connection */
+
+ /* Filters */
+ { "filter_maclist", "", 0 }, /* xx:xx:xx:xx:xx:xx ... */
+ { "filter_macmode", "deny", 0 }, /* "allow" only, "deny" only, or "disabled" (allow all) */
+ { "filter_client0", "", 0 }, /* [lan_ipaddr0-lan_ipaddr1|*]:lan_port0-lan_port1,proto,enable,day_start-day_end,sec_start-sec_end,desc */
+
+ /* Port forwards */
+ { "dmz_ipaddr", "", 0 }, /* x.x.x.x (equivalent to 0-60999>dmz_ipaddr:0-60999) */
+ { "forward_port0", "", 0 }, /* wan_port0-wan_port1>lan_ipaddr:lan_port0-lan_port1[:,]proto[:,]enable[:,]desc */
+ { "autofw_port0", "", 0 }, /* out_proto:out_port,in_proto:in_port0-in_port1>to_port0-to_port1,enable,desc */
+
+ /* DHCP server parameters */
+ { "dhcp_start", "192.168.1.100", 0 }, /* First assignable DHCP address */
+ { "dhcp_end", "192.168.1.150", 0 }, /* Last assignable DHCP address */
+ { "dhcp_domain", "wan", 0 }, /* Use WAN domain name first if available (wan|lan) */
+ { "dhcp_wins", "wan", 0 }, /* Use WAN WINS first if available (wan|lan) */
+
+ /* Web server parameters */
+ { "http_username", "", 0 }, /* Username */
+ { "http_passwd", "admin", 0 }, /* Password */
+ { "http_wanport", "", 0 }, /* WAN port to listen on */
+ { "http_lanport", "80", 0 }, /* LAN port to listen on */
+
+ /* Wireless parameters */
+ { "wl_ifname", "", 0 }, /* Interface name */
+ { "wl_hwaddr", "", 0 }, /* MAC address */
+ { "wl_phytype", "g", 0 }, /* Current wireless band ("a" (5 GHz), "b" (2.4 GHz), or "g" (2.4 GHz)) */
+ { "wl_corerev", "", 0 }, /* Current core revision */
+ { "wl_phytypes", "", 0 }, /* List of supported wireless bands (e.g. "ga") */
+ { "wl_radioids", "", 0 }, /* List of radio IDs */
+ { "wl_ssid", "OpenWrt", 0 }, /* Service set ID (network name) */
+ { "wl_country", "", 0 }, /* Country (default obtained from driver) */
+ { "wl_radio", "1", 0 }, /* Enable (1) or disable (0) radio */
+ { "wl_closed", "0", 0 }, /* Closed (hidden) network */
+ { "wl_ap_isolate", "0", 0 }, /* AP isolate mode */
+ { "wl_mode", "ap", 0 }, /* AP mode (ap|sta|wds) */
+ { "wl_lazywds", "0", 0 }, /* Enable "lazy" WDS mode (0|1) */
+ { "wl_wds", "", 0 }, /* xx:xx:xx:xx:xx:xx ... */
+ { "wl_wep", "disabled", 0 }, /* WEP data encryption (enabled|disabled) */
+ { "wl_auth", "0", 0 }, /* Shared key authentication optional (0) or required (1) */
+ { "wl_key", "1", 0 }, /* Current WEP key */
+ { "wl_key1", "", 0 }, /* 5/13 char ASCII or 10/26 char hex */
+ { "wl_key2", "", 0 }, /* 5/13 char ASCII or 10/26 char hex */
+ { "wl_key3", "", 0 }, /* 5/13 char ASCII or 10/26 char hex */
+ { "wl_key4", "", 0 }, /* 5/13 char ASCII or 10/26 char hex */
+ { "wl_maclist", "", 0 }, /* xx:xx:xx:xx:xx:xx ... */
+ { "wl_macmode", "disabled", 0 }, /* "allow" only, "deny" only, or "disabled" (allow all) */
+ { "wl_channel", "11", 0 }, /* Channel number */
+ { "wl_rate", "0", 0 }, /* Rate (bps, 0 for auto) */
+ { "wl_rateset", "default", 0 }, /* "default" or "all" or "12" */
+ { "wl_frag", "2346", 0 }, /* Fragmentation threshold */
+ { "wl_rts", "2347", 0 }, /* RTS threshold */
+ { "wl_dtim", "1", 0 }, /* DTIM period */
+ { "wl_bcn", "100", 0 }, /* Beacon interval */
+ { "wl_plcphdr", "long", 0 }, /* 802.11b PLCP preamble type */
+ { "wl_net_mode", "mixed", 0 }, /* 54g mode */
+ { "wl_gmode", "6", 0 }, /* 54g mode */
+ { "wl_gmode_protection", "auto", 0 }, /* 802.11g RTS/CTS protection (off|auto) */
+ { "wl_afterburner", "auto", 0 }, /* AfterBurner */
+ { "wl_frameburst", "off", 0 }, /* BRCM Frambursting mode (off|on) */
+ { "wl_antdiv", "-1", 0 }, /* Antenna Diversity (-1|0|1|3) */
+ { "wl_infra", "1", 0 }, /* Network Type (BSS/IBSS) */
+
+ /* WPA parameters */
+ { "security_mode", "open", 0 },
+ { "wl_auth_mode", "open", 0 }, /* Network authentication mode (open|shared|radius|wpa|psk) */
+ { "wl_wpa_psk", "", 0 }, /* WPA pre-shared key */
+ { "wl_wpa_gtk_rekey", "3600", 0 }, /* GTK rotation interval */
+ { "wl_radius_ipaddr", "", 0 }, /* RADIUS server IP address */
+ { "wl_radius_key", "", 0 }, /* RADIUS shared secret */
+ { "wl_radius_port", "1812", 0 }, /* RADIUS server UDP port */
+ { "wl_crypto", "tkip", 0 }, /* WPA data encryption */
+
+
+ { "wl_unit", "0", 0 }, /* Last configured interface */
+
+ /* Restore defaults */
+ { "restore_defaults", "0", 0 }, /* Set to 0 to not restore defaults on boot */
+
+ { 0, 0, 0 }
+};
diff --git a/package/nvram/src/include/bcmnvram.h b/package/nvram/src/include/bcmnvram.h
new file mode 100644
index 0000000000..3c452634e8
--- /dev/null
+++ b/package/nvram/src/include/bcmnvram.h
@@ -0,0 +1,148 @@
+/*
+ * NVRAM variable manipulation
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#ifndef _bcmnvram_h_
+#define _bcmnvram_h_
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+#include <typedefs.h>
+
+struct nvram_header {
+ uint32 magic;
+ uint32 len;
+ uint32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:27 init, mem. test 28, 29-31 reserved */
+ uint32 config_refresh; /* 0:15 config, 16:31 refresh */
+ uint32 config_ncdl; /* ncdl values for memc */
+};
+
+struct nvram_tuple {
+ char *name;
+ char *value;
+ struct nvram_tuple *next;
+};
+
+/*
+ * Initialize NVRAM access. May be unnecessary or undefined on certain
+ * platforms.
+ */
+extern int nvram_init(void *sbh);
+
+/*
+ * Disable NVRAM access. May be unnecessary or undefined on certain
+ * platforms.
+ */
+extern void nvram_exit(void);
+
+/*
+ * Get the value of an NVRAM variable. The pointer returned may be
+ * invalid after a set.
+ * @param name name of variable to get
+ * @return value of variable or NULL if undefined
+ */
+extern char * nvram_get(const char *name);
+
+/*
+ * Get the value of an NVRAM variable.
+ * @param name name of variable to get
+ * @return value of variable or NUL if undefined
+ */
+#define nvram_safe_get(name) (nvram_get(name) ? : "")
+
+#define nvram_safe_unset(name) ({ \
+ if(nvram_get(name)) \
+ nvram_unset(name); \
+})
+
+#define nvram_safe_set(name, value) ({ \
+ if(!nvram_get(name) || strcmp(nvram_get(name), value)) \
+ nvram_set(name, value); \
+})
+
+/*
+ * Match an NVRAM variable.
+ * @param name name of variable to match
+ * @param match value to compare against value of variable
+ * @return TRUE if variable is defined and its value is string equal
+ * to match or FALSE otherwise
+ */
+static INLINE int
+nvram_match(char *name, char *match) {
+ const char *value = nvram_get(name);
+ return (value && !strcmp(value, match));
+}
+
+/*
+ * Inversely match an NVRAM variable.
+ * @param name name of variable to match
+ * @param match value to compare against value of variable
+ * @return TRUE if variable is defined and its value is not string
+ * equal to invmatch or FALSE otherwise
+ */
+static INLINE int
+nvram_invmatch(char *name, char *invmatch) {
+ const char *value = nvram_get(name);
+ return (value && strcmp(value, invmatch));
+}
+
+/*
+ * Set the value of an NVRAM variable. The name and value strings are
+ * copied into private storage. Pointers to previously set values
+ * may become invalid. The new value may be immediately
+ * retrieved but will not be permanently stored until a commit.
+ * @param name name of variable to set
+ * @param value value of variable
+ * @return 0 on success and errno on failure
+ */
+extern int nvram_set(const char *name, const char *value);
+
+/*
+ * Unset an NVRAM variable. Pointers to previously set values
+ * remain valid until a set.
+ * @param name name of variable to unset
+ * @return 0 on success and errno on failure
+ * NOTE: use nvram_commit to commit this change to flash.
+ */
+extern int nvram_unset(const char *name);
+
+/*
+ * Commit NVRAM variables to permanent storage. All pointers to values
+ * may be invalid after a commit.
+ * NVRAM values are undefined after a commit.
+ * @return 0 on success and errno on failure
+ */
+extern int nvram_commit(void);
+
+/*
+ * Get all NVRAM variables (format name=value\0 ... \0\0).
+ * @param buf buffer to store variables
+ * @param count size of buffer in bytes
+ * @return 0 on success and errno on failure
+ */
+extern int nvram_getall(char *buf, int count);
+
+extern int file2nvram(char *filename, char *varname);
+extern int nvram2file(char *varname, char *filename);
+
+#endif /* _LANGUAGE_ASSEMBLY */
+
+#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */
+#define NVRAM_VERSION 1
+#define NVRAM_HEADER_SIZE 20
+#define NVRAM_SPACE 0x8000
+#define FLASH_BASE 0xbfc00000 /* Extif core */
+#define FLASH_MIN 0x00100000 /* Minimum flash size */
+#define FLASH_MAX 0x00400000 /* Maximum flash size with extif */
+
+#endif /* _bcmnvram_h_ */
diff --git a/package/nvram/src/include/bcmutils.h b/package/nvram/src/include/bcmutils.h
new file mode 100644
index 0000000000..05ad41d9d8
--- /dev/null
+++ b/package/nvram/src/include/bcmutils.h
@@ -0,0 +1,157 @@
+/*
+ * Misc useful os-independent macros and functions.
+ *
+ * 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.
+ * $Id$
+ */
+
+#ifndef _bcmutils_h_
+#define _bcmutils_h_
+
+#ifndef MIN
+#define MIN(a, b) (((a)<(b))?(a):(b))
+#endif
+
+#ifndef MAX
+#define MAX(a, b) (((a)>(b))?(a):(b))
+#endif
+
+#define CEIL(x, y) (((x) + ((y)-1)) / (y))
+#define ROUNDUP(x, y) ((((ulong)(x)+((y)-1))/(y))*(y))
+#define ISALIGNED(a, x) (((uint)(a) & ((x)-1)) == 0)
+#define ISPOWEROF2(x) ((((x)-1)&(x))==0)
+#define OFFSETOF(type, member) ((uint) &((type *)0)->member)
+#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
+
+/* bit map related macros */
+#ifndef setbit
+#define NBBY 8 /* 8 bits per byte */
+#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
+#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
+#define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
+#define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
+#endif
+
+#define NBITS(type) (sizeof (type) * 8)
+
+#define _BCM_U 0x01 /* upper */
+#define _BCM_L 0x02 /* lower */
+#define _BCM_D 0x04 /* digit */
+#define _BCM_C 0x08 /* cntrl */
+#define _BCM_P 0x10 /* punct */
+#define _BCM_S 0x20 /* white space (space/lf/tab) */
+#define _BCM_X 0x40 /* hex digit */
+#define _BCM_SP 0x80 /* hard space (0x20) */
+
+extern unsigned char bcm_ctype[];
+#define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)])
+
+#define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0)
+#define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0)
+#define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0)
+#define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0)
+#define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0)
+#define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0)
+#define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0)
+#define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0)
+#define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0)
+#define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0)
+#define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0)
+
+/*
+ * Spin at most 'us' microseconds while 'exp' is true.
+ * Caller should explicitly test 'exp' when this completes
+ * and take appropriate error action if 'exp' is still true.
+ */
+#define SPINWAIT(exp, us) { \
+ uint countdown = (us) + 9; \
+ while ((exp) && (countdown >= 10)) {\
+ OSL_DELAY(10); \
+ countdown -= 10; \
+ } \
+}
+
+/* generic osl packet queue */
+struct pktq {
+ void *head; /* first packet to dequeue */
+ void *tail; /* last packet to dequeue */
+ uint len; /* number of queued packets */
+ uint maxlen; /* maximum number of queued packets */
+ bool priority; /* enqueue by packet priority */
+};
+#define DEFAULT_QLEN 128
+
+#define pktq_len(q) ((q)->len)
+#define pktq_avail(q) ((q)->maxlen - (q)->len)
+#define pktq_head(q) ((q)->head)
+#define pktq_full(q) ((q)->len >= (q)->maxlen)
+
+/* crc defines */
+#define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */
+#define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */
+#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */
+#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */
+#define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */
+#define CRC32_GOOD_VALUE 0xdebb20e3 /* Good final CRC32 checksum value */
+
+/* tag_ID/length/value_buffer tuple */
+typedef struct bcm_tlv {
+ uint8 id;
+ uint8 len;
+ uint8 data[1];
+} bcm_tlv_t;
+
+/* Check that bcm_tlv_t fits into the given buflen */
+#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (buflen) >= 2 + (elt)->len)
+
+/* buffer length for ethernet address from bcm_ether_ntoa() */
+#define ETHER_ADDR_STR_LEN 18
+
+/*
+* load 32-bit value from unaligned byte array
+*/
+#ifdef IL_BIGENDIAN
+#define load32_ua(a) ((((uint8 *)(a))[0] << 24) + (((uint8 *)(a))[1] << 16) + \
+ (((uint8 *)(a))[2] << 8) + ((uint8 *)(a))[3])
+#else
+#define load32_ua(a) ((((uint8 *)(a))[3] << 24) + (((uint8 *)(a))[2] << 16) + \
+ (((uint8 *)(a))[1] << 8) + ((uint8 *)(a))[0])
+#endif
+
+/* externs */
+extern uint bcm_atoi(char *s);
+extern uchar bcm_toupper(uchar c);
+extern ulong bcm_strtoul(char *cp, char **endp, uint base);
+extern void deadbeef(char *p, uint len);
+extern void prhex(char *msg, uchar *buf, uint len);
+extern void prpkt(char *msg, void *drv, void *p0);
+extern uint pktcopy(void *drv, void *p, uint offset, int len, uchar *buf);
+extern uint pkttotlen(void *drv, void *);
+extern uchar *bcm_ether_ntoa(char *ea, char *buf);
+extern int bcm_ether_atoe(char *p, char *ea);
+extern void bcm_mdelay(uint ms);
+extern char *getvar(char *vars, char *name);
+extern int getintvar(char *vars, char *name);
+extern char *bcmstrstr(char *haystack, char *needle);
+
+extern uint8 crc8(uint8 *p, uint nbytes, uint8 crc);
+extern uint16 crc16(uint8 *p, uint nbytes, uint16 crc);
+extern uint32 crc32(uint8 *p, uint nbytes, uint32 crc);
+extern bcm_tlv_t *bcm_next_tlv(bcm_tlv_t *elt, int *buflen);
+extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key);
+extern bcm_tlv_t *bcm_parse_ordered_tlvs(void *buf, int buflen, uint key);
+extern void pktq_init(struct pktq *q, uint maxlen, bool priority);
+extern bool pktenq(struct pktq *q, void *p, bool lifo);
+extern void *pktdeq(struct pktq *q);
+
+#define bcmlog(fmt, a1, a2)
+#define bcmdumplog(buf, size) *buf = '\0'
+#define bcmdumplogent(buf, idx) -1
+
+#endif /* _bcmutils_h_ */
diff --git a/package/nvram/src/include/cy_conf.h b/package/nvram/src/include/cy_conf.h
new file mode 100644
index 0000000000..dbe387b83b
--- /dev/null
+++ b/package/nvram/src/include/cy_conf.h
@@ -0,0 +1,69 @@
+
+#define DNSMASQ_SUPPORT 1
+#define CONFIG_DNSMASQ y
+#define UDHCPD_SUPPORT 1
+#define CONFIG_UDHCPD y
+#define UDHCPC_SUPPORT 1
+#define CONFIG_UDHCPC y
+#define PPPOE_SUPPORT 1
+#define CONFIG_PPPOE y
+#define PPTP_SUPPORT 1
+#define CONFIG_PPTP y
+#define L2TP_SUPPORT 1
+#define CONFIG_L2TP y
+#define PPPD_SUPPORT 1
+#define CONFIG_PPPD y
+#define ZEBRA_SUPPORT 1
+#define CONFIG_ZEBRA y
+#define TFTPD_SUPPORT 1
+#define CONFIG_TFTPD y
+#define DDNS_SUPPORT 1
+#define CONFIG_DDNS y
+#define CRON_SUPPORT 1
+#define CONFIG_CRON y
+#define HTTPD_SUPPORT 1
+#define CONFIG_HTTPD y
+#define GET_POST_SUPPORT 1
+#define CONFIG_GET_POST y
+
+#if 1
+#define HEARTBEAT_SUPPORT 1
+#define CONFIG_HEARTBEAT y
+#define MULTICAST_SUPPORT 1
+#define CONFIG_MULTICAST y
+#define SETUP_WIZARD_SUPPORT 1
+#define CONFIG_SETUP_WIZARD y
+#define PARENTAL_CONTROL_SUPPORT 1
+#define CONFIG_PARENTAL_CONTROL y
+#define HTTPS_SUPPORT 1
+#define CONFIG_HTTPS y
+#define EOU_SUPPORT 1
+#define CONFIG_EOU y
+#define EZC_SUPPORT 1
+#define CONFIG_EZC y
+#define WRITE_MAC_SUPPORT 1
+#define CONFIG_WRITE_MAC y
+#define DIAG_SUPPORT 1
+#define CONFIG_DIAG y
+#endif
+
+#define SPEED_BOOSTER_SUPPORT 1
+#define CONFIG_SPEED_BOOSTER y
+#define XBOX_SUPPORT 1
+#define CONFIG_XBOX y
+
+#if 0
+#define MPPPOE_SUPPORT 1
+#define CONFIG_MPPPOE y
+#define UNNUMBERIP_SUPPORT 1
+#define CONFIG_UNNUMBERIP y
+#endif
+
+#define WL_STA_SUPPORT 1
+#define CONFIG_WL_STA y
+#define BACKUP_RESTORE_SUPPORT 1
+#define CONFIG_BACKUP_RESTORE y
+#define PORT_TRIGGER_SUPPORT 1
+#define CONFIG_PORT_TRIGGER y
+#define HW_QOS_SUPPORT 1
+#define CONFIG_HW_QOS y
diff --git a/package/nvram/src/include/epivers.h b/package/nvram/src/include/epivers.h
new file mode 100644
index 0000000000..e174fb50d8
--- /dev/null
+++ b/package/nvram/src/include/epivers.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ *
+ * $Id$
+ *
+*/
+
+#ifndef _epivers_h_
+#define _epivers_h_
+
+#ifdef linux
+#include <linux/config.h>
+#endif
+
+/* Vendor Name, ASCII, 32 chars max */
+#ifdef COMPANYNAME
+#define HPNA_VENDOR COMPANYNAME
+#else
+#define HPNA_VENDOR "Broadcom Corporation"
+#endif
+
+/* Driver Date, ASCII, 32 chars max */
+#define HPNA_DRV_BUILD_DATE __DATE__
+
+/* Hardware Manufacture Date, ASCII, 32 chars max */
+#define HPNA_HW_MFG_DATE "Not Specified"
+
+/* See documentation for Device Type values, 32 values max */
+#ifndef HPNA_DEV_TYPE
+
+#if defined(CONFIG_BRCM_VJ)
+#define HPNA_DEV_TYPE { CDCF_V0_DEVICE_DISPLAY }
+
+#elif defined(CONFIG_BCRM_93725)
+#define HPNA_DEV_TYPE { CDCF_V0_DEVICE_CM_BRIDGE, CDCF_V0_DEVICE_DISPLAY }
+
+#else
+#define HPNA_DEV_TYPE { CDCF_V0_DEVICE_PCINIC }
+
+#endif
+
+#endif /* !HPNA_DEV_TYPE */
+
+
+#define EPI_MAJOR_VERSION 3
+
+#define EPI_MINOR_VERSION 60
+
+#define EPI_RC_NUMBER 13
+
+#define EPI_INCREMENTAL_NUMBER 0
+
+#define EPI_BUILD_NUMBER 0
+
+#define EPI_VERSION 3,60,13,0
+
+#define EPI_VERSION_NUM 0x033c0d00
+
+/* Driver Version String, ASCII, 32 chars max */
+#define EPI_VERSION_STR "3.60.13.0"
+#define EPI_ROUTER_VERSION_STR "3.61.13.0"
+
+#endif /* _epivers_h_ */
diff --git a/package/nvram/src/include/proto/802.11.h b/package/nvram/src/include/proto/802.11.h
new file mode 100644
index 0000000000..ea57850ce5
--- /dev/null
+++ b/package/nvram/src/include/proto/802.11.h
@@ -0,0 +1,852 @@
+/*
+ * 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.
+ *
+ * Fundamental types and constants relating to 802.11
+ *
+ * $Id$
+ */
+
+#ifndef _802_11_H_
+#define _802_11_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+#ifndef _NET_ETHERNET_H_
+#include <proto/ethernet.h>
+#endif
+
+/* enable structure packing */
+#if !defined(__GNUC__)
+#pragma pack(1)
+#endif
+
+/* some platforms require stronger medicine */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#define PACKED
+#endif
+
+
+#define DOT11_TU_TO_US 1024 /* 802.11 Time Unit is 1024 microseconds */
+
+/* Generic 802.11 frame constants */
+#define DOT11_A3_HDR_LEN 24
+#define DOT11_A4_HDR_LEN 30
+#define DOT11_MAC_HDR_LEN DOT11_A3_HDR_LEN
+#define DOT11_FCS_LEN 4
+#define DOT11_ICV_LEN 4
+#define DOT11_ICV_AES_LEN 8
+#define DOT11_QOS_LEN 2
+
+#define DOT11_KEY_INDEX_SHIFT 6
+#define DOT11_IV_LEN 4
+#define DOT11_IV_TKIP_LEN 8
+#define DOT11_IV_AES_OCB_LEN 4
+#define DOT11_IV_AES_CCM_LEN 8
+
+/* Includes MIC */
+#define DOT11_MAX_MPDU_BODY_LEN 2304
+/* A4 header + QoS + CCMP + PDU + ICV + FCS = 2352 */
+#define DOT11_MAX_MPDU_LEN (DOT11_A4_HDR_LEN + \
+ DOT11_QOS_LEN + \
+ DOT11_IV_AES_CCM_LEN + \
+ DOT11_MAX_MPDU_BODY_LEN + \
+ DOT11_ICV_LEN + \
+ DOT11_FCS_LEN)
+
+#define DOT11_MAX_SSID_LEN 32
+
+/* dot11RTSThreshold */
+#define DOT11_DEFAULT_RTS_LEN 2347
+#define DOT11_MAX_RTS_LEN 2347
+
+/* dot11FragmentationThreshold */
+#define DOT11_MIN_FRAG_LEN 256
+#define DOT11_MAX_FRAG_LEN 2346 /* Max frag is also limited by aMPDUMaxLength of the attached PHY */
+#define DOT11_DEFAULT_FRAG_LEN 2346
+
+/* dot11BeaconPeriod */
+#define DOT11_MIN_BEACON_PERIOD 1
+#define DOT11_MAX_BEACON_PERIOD 0xFFFF
+
+/* dot11DTIMPeriod */
+#define DOT11_MIN_DTIM_PERIOD 1
+#define DOT11_MAX_DTIM_PERIOD 0xFF
+
+/* 802.2 LLC/SNAP header used by 802.11 per 802.1H */
+#define DOT11_LLC_SNAP_HDR_LEN 8
+#define DOT11_OUI_LEN 3
+struct dot11_llc_snap_header {
+ uint8 dsap; /* always 0xAA */
+ uint8 ssap; /* always 0xAA */
+ uint8 ctl; /* always 0x03 */
+ uint8 oui[DOT11_OUI_LEN]; /* RFC1042: 0x00 0x00 0x00
+ Bridge-Tunnel: 0x00 0x00 0xF8 */
+ uint16 type; /* ethertype */
+} PACKED;
+
+/* RFC1042 header used by 802.11 per 802.1H */
+#define RFC1042_HDR_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN)
+
+/* Generic 802.11 MAC header */
+/*
+ * N.B.: This struct reflects the full 4 address 802.11 MAC header.
+ * The fields are defined such that the shorter 1, 2, and 3
+ * address headers just use the first k fields.
+ */
+struct dot11_header {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr a1; /* address 1 */
+ struct ether_addr a2; /* address 2 */
+ struct ether_addr a3; /* address 3 */
+ uint16 seq; /* sequence control */
+ struct ether_addr a4; /* address 4 */
+} PACKED;
+
+/* Control frames */
+
+struct dot11_rts_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+ struct ether_addr ta; /* transmitter address */
+} PACKED;
+#define DOT11_RTS_LEN 16
+
+struct dot11_cts_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+} PACKED;
+#define DOT11_CTS_LEN 10
+
+struct dot11_ack_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+} PACKED;
+#define DOT11_ACK_LEN 10
+
+struct dot11_ps_poll_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* AID */
+ struct ether_addr bssid; /* receiver address, STA in AP */
+ struct ether_addr ta; /* transmitter address */
+} PACKED;
+#define DOT11_PS_POLL_LEN 16
+
+struct dot11_cf_end_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+ struct ether_addr bssid; /* transmitter address, STA in AP */
+} PACKED;
+#define DOT11_CS_END_LEN 16
+
+/* Management frame header */
+struct dot11_management_header {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr da; /* receiver address */
+ struct ether_addr sa; /* transmitter address */
+ struct ether_addr bssid; /* BSS ID */
+ uint16 seq; /* sequence control */
+} PACKED;
+#define DOT11_MGMT_HDR_LEN 24
+
+/* Management frame payloads */
+
+struct dot11_bcn_prb {
+ uint32 timestamp[2];
+ uint16 beacon_interval;
+ uint16 capability;
+} PACKED;
+#define DOT11_BCN_PRB_LEN 12
+
+struct dot11_auth {
+ uint16 alg; /* algorithm */
+ uint16 seq; /* sequence control */
+ uint16 status; /* status code */
+} PACKED;
+#define DOT11_AUTH_FIXED_LEN 6 /* length of auth frame without challenge info elt */
+
+struct dot11_assoc_req {
+ uint16 capability; /* capability information */
+ uint16 listen; /* listen interval */
+} PACKED;
+
+struct dot11_assoc_resp {
+ uint16 capability; /* capability information */
+ uint16 status; /* status code */
+ uint16 aid; /* association ID */
+} PACKED;
+
+struct dot11_action_measure {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} PACKED;
+#define DOT11_ACTION_MEASURE_LEN 3
+
+/**************
+ 802.11h related definitions.
+**************/
+typedef struct {
+ uint8 id;
+ uint8 len;
+ uint8 power;
+} dot11_power_cnst_t;
+
+typedef struct {
+ uint8 min;
+ uint8 max;
+} dot11_power_cap_t;
+
+typedef struct {
+ uint8 id;
+ uint8 len;
+ uint8 tx_pwr;
+ uint8 margin;
+} dot11_tpc_rep_t;
+#define DOT11_MNG_IE_TPC_REPORT_LEN 2 /* length of IE data, not including 2 byte header */
+
+typedef struct {
+ uint8 id;
+ uint8 len;
+ uint8 first_channel;
+ uint8 num_channels;
+} dot11_supp_channels_t;
+
+struct dot11_channel_switch {
+ uint8 id;
+ uint8 len;
+ uint8 mode;
+ uint8 channel;
+ uint8 count;
+} PACKED;
+typedef struct dot11_channel_switch dot11_channel_switch_t;
+
+/* 802.11h Measurement Request/Report IEs */
+/* Measurement Type field */
+#define DOT11_MEASURE_TYPE_BASIC 0
+#define DOT11_MEASURE_TYPE_CCA 1
+#define DOT11_MEASURE_TYPE_RPI 2
+
+/* Measurement Mode field */
+
+/* Measurement Request Modes */
+#define DOT11_MEASURE_MODE_ENABLE (1<<1)
+#define DOT11_MEASURE_MODE_REQUEST (1<<2)
+#define DOT11_MEASURE_MODE_REPORT (1<<3)
+/* Measurement Report Modes */
+#define DOT11_MEASURE_MODE_LATE (1<<0)
+#define DOT11_MEASURE_MODE_INCAPABLE (1<<1)
+#define DOT11_MEASURE_MODE_REFUSED (1<<2)
+/* Basic Measurement Map bits */
+#define DOT11_MEASURE_BASIC_MAP_BSS ((uint8)(1<<0))
+#define DOT11_MEASURE_BASIC_MAP_OFDM ((uint8)(1<<1))
+#define DOT11_MEASURE_BASIC_MAP_UKNOWN ((uint8)(1<<2))
+#define DOT11_MEASURE_BASIC_MAP_RADAR ((uint8)(1<<3))
+#define DOT11_MEASURE_BASIC_MAP_UNMEAS ((uint8)(1<<4))
+
+typedef struct {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+} dot11_meas_req_t;
+#define DOT11_MNG_IE_MREQ_LEN 14
+/* length of Measure Request IE data not including variable len */
+#define DOT11_MNG_IE_MREQ_FIXED_LEN 3
+
+struct dot11_meas_rep {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ union
+ {
+ struct {
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+ uint8 map;
+ } PACKED basic;
+ uint8 data[1];
+ } PACKED rep;
+} PACKED;
+typedef struct dot11_meas_rep dot11_meas_rep_t;
+
+/* length of Measure Report IE data not including variable len */
+#define DOT11_MNG_IE_MREP_FIXED_LEN 3
+
+struct dot11_meas_rep_basic {
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+ uint8 map;
+} PACKED;
+typedef struct dot11_meas_rep_basic dot11_meas_rep_basic_t;
+#define DOT11_MEASURE_BASIC_REP_LEN 12
+
+struct dot11_quiet {
+ uint8 id;
+ uint8 len;
+ uint8 count; /* TBTTs until beacon interval in quiet starts */
+ uint8 period; /* Beacon intervals between periodic quiet periods ? */
+ uint16 duration;/* Length of quiet period, in TU's */
+ uint16 offset; /* TU's offset from TBTT in Count field */
+} PACKED;
+typedef struct dot11_quiet dot11_quiet_t;
+
+typedef struct {
+ uint8 channel;
+ uint8 map;
+} chan_map_tuple_t;
+
+typedef struct {
+ uint8 id;
+ uint8 len;
+ uint8 eaddr[ETHER_ADDR_LEN];
+ uint8 interval;
+ chan_map_tuple_t map[1];
+} dot11_ibss_dfs_t;
+
+/* WME Elements */
+#define WME_OUI "\x00\x50\xf2"
+#define WME_VER 1
+#define WME_TYPE 2
+#define WME_SUBTYPE_IE 0 /* Information Element */
+#define WME_SUBTYPE_PARAM_IE 1 /* Parameter Element */
+#define WME_SUBTYPE_TSPEC 2 /* Traffic Specification */
+
+/* WME Access Category Indices (ACIs) */
+#define AC_BE 0 /* Best Effort */
+#define AC_BK 1 /* Background */
+#define AC_VI 2 /* Video */
+#define AC_VO 3 /* Voice */
+#define AC_MAX 4
+
+/* WME Information Element (IE) */
+struct wme_ie {
+ uint8 oui[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 version;
+ uint8 acinfo;
+} PACKED;
+typedef struct wme_ie wme_ie_t;
+#define WME_IE_LEN 7
+
+struct wme_acparam {
+ uint8 ACI;
+ uint8 ECW;
+ uint16 TXOP; /* stored in network order (ls octet first) */
+} PACKED;
+typedef struct wme_acparam wme_acparam_t;
+
+/* WME Parameter Element (PE) */
+struct wme_params {
+ uint8 oui[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 version;
+ uint8 acinfo;
+ uint8 rsvd;
+ wme_acparam_t acparam[4];
+} PACKED;
+typedef struct wme_params wme_params_t;
+#define WME_PARAMS_IE_LEN 24
+
+/* acinfo */
+#define WME_COUNT_MASK 0x0f
+/* ACI */
+#define WME_AIFS_MASK 0x0f
+#define WME_ACM_MASK 0x10
+#define WME_ACI_MASK 0x60
+#define WME_ACI_SHIFT 5
+/* ECW */
+#define WME_CWMIN_MASK 0x0f
+#define WME_CWMAX_MASK 0xf0
+#define WME_CWMAX_SHIFT 4
+
+#define WME_TXOP_UNITS 32
+
+/* WME Traffic Specification (TSPEC) element */
+#define WME_SUBTYPE_TSPEC 2
+#define WME_TSPEC_HDR_LEN 2
+#define WME_TSPEC_BODY_OFF 2
+struct wme_tspec {
+ uint8 oui[DOT11_OUI_LEN]; /* WME_OUI */
+ uint8 type; /* WME_TYPE */
+ uint8 subtype; /* WME_SUBTYPE_TSPEC */
+ uint8 version; /* WME_VERSION */
+ uint16 ts_info; /* TS Info */
+ uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */
+ uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */
+ uint32 min_service_interval; /* Minimum Service Interval (us) */
+ uint32 max_service_interval; /* Maximum Service Interval (us) */
+ uint32 inactivity_interval; /* Inactivity Interval (us) */
+ uint32 service_start; /* Service Start Time (us) */
+ uint32 min_rate; /* Minimum Data Rate (bps) */
+ uint32 mean_rate; /* Mean Data Rate (bps) */
+ uint32 max_burst_size; /* Maximum Burst Size (bytes) */
+ uint32 min_phy_rate; /* Minimum PHY Rate (bps) */
+ uint32 peak_rate; /* Peak Data Rate (bps) */
+ uint32 delay_bound; /* Delay Bound (us) */
+ uint16 surplus_bandwidth; /* Surplus Bandwidth Allowance Factor */
+ uint16 medium_time; /* Medium Time (32 us/s periods) */
+} PACKED;
+typedef struct wme_tspec wme_tspec_t;
+#define WME_TSPEC_LEN 56 /* not including 2-byte header */
+
+/* ts_info */
+/* 802.1D priority is duplicated - bits 13-11 AND bits 3-1 */
+#define TS_INFO_PRIO_SHIFT_HI 11
+#define TS_INFO_PRIO_MASK_HI (0x7 << TS_INFO_PRIO_SHIFT_HI)
+#define TS_INFO_PRIO_SHIFT_LO 1
+#define TS_INFO_PRIO_MASK_LO (0x7 << TS_INFO_PRIO_SHIFT_LO)
+#define TS_INFO_CONTENTION_SHIFT 7
+#define TS_INFO_CONTENTION_MASK (0x1 << TS_INFO_CONTENTION_SHIFT)
+#define TS_INFO_DIRECTION_SHIFT 5
+#define TS_INFO_DIRECTION_MASK (0x3 << TS_INFO_DIRECTION_SHIFT)
+#define TS_INFO_UPLINK (0 << TS_INFO_DIRECTION_SHIFT)
+#define TS_INFO_DOWNLINK (1 << TS_INFO_DIRECTION_SHIFT)
+#define TS_INFO_BIDIRECTIONAL (3 << TS_INFO_DIRECTION_SHIFT)
+
+/* nom_msdu_size */
+#define FIXED_MSDU_SIZE 0x8000 /* MSDU size is fixed */
+#define MSDU_SIZE_MASK 0x7fff /* (Nominal or fixed) MSDU size */
+
+/* surplus_bandwidth */
+/* Represented as 3 bits of integer, binary point, 13 bits fraction */
+#define INTEGER_SHIFT 13
+#define FRACTION_MASK 0x1FFF
+
+/* Management Notification Frame */
+struct dot11_management_notification {
+ uint8 category; /* DOT11_ACTION_NOTIFICATION */
+ uint8 action;
+ uint8 token;
+ uint8 status;
+ uint8 data[1]; /* Elements */
+} PACKED;
+#define DOT11_MGMT_NOTIFICATION_LEN 4 /* Fixed length */
+
+/* WME Action Codes */
+#define WME_SETUP_REQUEST 0
+#define WME_SETUP_RESPONSE 1
+#define WME_TEARDOWN 2
+
+/* WME Setup Response Status Codes */
+#define WME_ADMISSION_ACCEPTED 0
+#define WME_INVALID_PARAMETERS 1
+#define WME_ADMISSION_REFUSED 3
+
+/* Macro to take a pointer to a beacon or probe response
+ * header and return the char* pointer to the SSID info element
+ */
+#define BCN_PRB_SSID(hdr) ((char*)(hdr) + DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_LEN)
+
+/* Authentication frame payload constants */
+#define DOT11_OPEN_SYSTEM 0
+#define DOT11_SHARED_KEY 1
+#define DOT11_CHALLENGE_LEN 128
+
+/* Frame control macros */
+#define FC_PVER_MASK 0x3
+#define FC_PVER_SHIFT 0
+#define FC_TYPE_MASK 0xC
+#define FC_TYPE_SHIFT 2
+#define FC_SUBTYPE_MASK 0xF0
+#define FC_SUBTYPE_SHIFT 4
+#define FC_TODS 0x100
+#define FC_TODS_SHIFT 8
+#define FC_FROMDS 0x200
+#define FC_FROMDS_SHIFT 9
+#define FC_MOREFRAG 0x400
+#define FC_MOREFRAG_SHIFT 10
+#define FC_RETRY 0x800
+#define FC_RETRY_SHIFT 11
+#define FC_PM 0x1000
+#define FC_PM_SHIFT 12
+#define FC_MOREDATA 0x2000
+#define FC_MOREDATA_SHIFT 13
+#define FC_WEP 0x4000
+#define FC_WEP_SHIFT 14
+#define FC_ORDER 0x8000
+#define FC_ORDER_SHIFT 15
+
+/* sequence control macros */
+#define SEQNUM_SHIFT 4
+#define FRAGNUM_MASK 0xF
+
+/* Frame Control type/subtype defs */
+
+/* FC Types */
+#define FC_TYPE_MNG 0
+#define FC_TYPE_CTL 1
+#define FC_TYPE_DATA 2
+
+/* Management Subtypes */
+#define FC_SUBTYPE_ASSOC_REQ 0
+#define FC_SUBTYPE_ASSOC_RESP 1
+#define FC_SUBTYPE_REASSOC_REQ 2
+#define FC_SUBTYPE_REASSOC_RESP 3
+#define FC_SUBTYPE_PROBE_REQ 4
+#define FC_SUBTYPE_PROBE_RESP 5
+#define FC_SUBTYPE_BEACON 8
+#define FC_SUBTYPE_ATIM 9
+#define FC_SUBTYPE_DISASSOC 10
+#define FC_SUBTYPE_AUTH 11
+#define FC_SUBTYPE_DEAUTH 12
+#define FC_SUBTYPE_ACTION 13
+
+/* Control Subtypes */
+#define FC_SUBTYPE_PS_POLL 10
+#define FC_SUBTYPE_RTS 11
+#define FC_SUBTYPE_CTS 12
+#define FC_SUBTYPE_ACK 13
+#define FC_SUBTYPE_CF_END 14
+#define FC_SUBTYPE_CF_END_ACK 15
+
+/* Data Subtypes */
+#define FC_SUBTYPE_DATA 0
+#define FC_SUBTYPE_DATA_CF_ACK 1
+#define FC_SUBTYPE_DATA_CF_POLL 2
+#define FC_SUBTYPE_DATA_CF_ACK_POLL 3
+#define FC_SUBTYPE_NULL 4
+#define FC_SUBTYPE_CF_ACK 5
+#define FC_SUBTYPE_CF_POLL 6
+#define FC_SUBTYPE_CF_ACK_POLL 7
+#define FC_SUBTYPE_QOS_DATA 8
+#define FC_SUBTYPE_QOS_NULL 12
+
+/* type-subtype combos */
+#define FC_KIND_MASK (FC_TYPE_MASK | FC_SUBTYPE_MASK)
+
+#define FC_KIND(t, s) (((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT))
+
+#define FC_ASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_REQ)
+#define FC_ASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP)
+#define FC_REASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ)
+#define FC_REASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP)
+#define FC_PROBE_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ)
+#define FC_PROBE_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP)
+#define FC_BEACON FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON)
+#define FC_DISASSOC FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC)
+#define FC_AUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH)
+#define FC_DEAUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH)
+#define FC_ACTION FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION)
+
+#define FC_PS_POLL FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL)
+#define FC_RTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS)
+#define FC_CTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS)
+#define FC_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_ACK)
+#define FC_CF_END FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END)
+#define FC_CF_END_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END_ACK)
+
+#define FC_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA)
+#define FC_NULL_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_NULL)
+#define FC_DATA_CF_ACK FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA_CF_ACK)
+#define FC_QOS_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_DATA)
+#define FC_QOS_NULL FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_NULL)
+
+/* QoS Control Field */
+
+/* 802.1D Tag */
+#define QOS_PRIO_SHIFT 0
+#define QOS_PRIO_MASK 0x0007
+#define QOS_PRIO(qos) (((qos) & QOS_PRIO_MASK) >> QOS_PRIO_SHIFT)
+
+/* Ack Policy (0 means Acknowledge) */
+#define QOS_ACK_SHIFT 5
+#define QOS_ACK_MASK 0x0060
+#define QOS_ACK(qos) (((qos) & QOS_ACK_MASK) >> QOS_ACK_SHIFT)
+
+/* Management Frames */
+
+/* Management Frame Constants */
+
+/* Fixed fields */
+#define DOT11_MNG_AUTH_ALGO_LEN 2
+#define DOT11_MNG_AUTH_SEQ_LEN 2
+#define DOT11_MNG_BEACON_INT_LEN 2
+#define DOT11_MNG_CAP_LEN 2
+#define DOT11_MNG_AP_ADDR_LEN 6
+#define DOT11_MNG_LISTEN_INT_LEN 2
+#define DOT11_MNG_REASON_LEN 2
+#define DOT11_MNG_AID_LEN 2
+#define DOT11_MNG_STATUS_LEN 2
+#define DOT11_MNG_TIMESTAMP_LEN 8
+
+/* DUR/ID field in assoc resp is 0xc000 | AID */
+#define DOT11_AID_MASK 0x3fff
+
+/* Reason Codes */
+#define DOT11_RC_RESERVED 0
+#define DOT11_RC_UNSPECIFIED 1 /* Unspecified reason */
+#define DOT11_RC_AUTH_INVAL 2 /* Previous authentication no longer valid */
+#define DOT11_RC_DEAUTH_LEAVING 3 /* Deauthenticated because sending station is
+ leaving (or has left) IBSS or ESS */
+#define DOT11_RC_INACTIVITY 4 /* Disassociated due to inactivity */
+#define DOT11_RC_BUSY 5 /* Disassociated because AP is unable to handle
+ all currently associated stations */
+#define DOT11_RC_INVAL_CLASS_2 6 /* Class 2 frame received from
+ nonauthenticated station */
+#define DOT11_RC_INVAL_CLASS_3 7 /* Class 3 frame received from
+ nonassociated station */
+#define DOT11_RC_DISASSOC_LEAVING 8 /* Disassociated because sending station is
+ leaving (or has left) BSS */
+#define DOT11_RC_NOT_AUTH 9 /* Station requesting (re)association is
+ not authenticated with responding station */
+#define DOT11_RC_MAX 23 /* Reason codes > 23 are reserved */
+
+/* Status Codes */
+#define DOT11_STATUS_SUCCESS 0 /* Successful */
+#define DOT11_STATUS_FAILURE 1 /* Unspecified failure */
+#define DOT11_STATUS_CAP_MISMATCH 10 /* Cannot support all requested capabilities
+ in the Capability Information field */
+#define DOT11_STATUS_REASSOC_FAIL 11 /* Reassociation denied due to inability to
+ confirm that association exists */
+#define DOT11_STATUS_ASSOC_FAIL 12 /* Association denied due to reason outside
+ the scope of this standard */
+#define DOT11_STATUS_AUTH_MISMATCH 13 /* Responding station does not support the
+ specified authentication algorithm */
+#define DOT11_STATUS_AUTH_SEQ 14 /* Received an Authentication frame with
+ authentication transaction sequence number
+ out of expected sequence */
+#define DOT11_STATUS_AUTH_CHALLENGE_FAIL 15 /* Authentication rejected because of challenge failure */
+#define DOT11_STATUS_AUTH_TIMEOUT 16 /* Authentication rejected due to timeout waiting
+ for next frame in sequence */
+#define DOT11_STATUS_ASSOC_BUSY_FAIL 17 /* Association denied because AP is unable to
+ handle additional associated stations */
+#define DOT11_STATUS_ASSOC_RATE_MISMATCH 18 /* Association denied due to requesting station
+ not supporting all of the data rates in the
+ BSSBasicRateSet parameter */
+#define DOT11_STATUS_ASSOC_SHORT_REQUIRED 19 /* Association denied due to requesting station
+ not supporting the Short Preamble option */
+#define DOT11_STATUS_ASSOC_PBCC_REQUIRED 20 /* Association denied due to requesting station
+ not supporting the PBCC Modulation option */
+#define DOT11_STATUS_ASSOC_AGILITY_REQUIRED 21 /* Association denied due to requesting station
+ not supporting the Channel Agility option */
+#define DOT11_STATUS_ASSOC_SPECTRUM_REQUIRED 22 /* Association denied because Spectrum Management
+ capability is required. */
+#define DOT11_STATUS_ASSOC_BAD_POWER_CAP 23 /* Association denied because the info in the
+ Power Cap element is unacceptable. */
+#define DOT11_STATUS_ASSOC_BAD_SUP_CHANNELS 24 /* Association denied because the info in the
+ Supported Channel element is unacceptable */
+#define DOT11_STATUS_ASSOC_SHORTSLOT_REQUIRED 25 /* Association denied due to requesting station
+ not supporting the Short Slot Time option */
+#define DOT11_STATUS_ASSOC_ERPBCC_REQUIRED 26 /* Association denied due to requesting station
+ not supporting the ER-PBCC Modulation option */
+#define DOT11_STATUS_ASSOC_DSSOFDM_REQUIRED 27 /* Association denied due to requesting station
+ not supporting the DSS-OFDM option */
+
+/* Info Elts, length of INFORMATION portion of Info Elts */
+#define DOT11_MNG_DS_PARAM_LEN 1
+#define DOT11_MNG_IBSS_PARAM_LEN 2
+
+/* TIM Info element has 3 bytes fixed info in INFORMATION field,
+ * followed by 1 to 251 bytes of Partial Virtual Bitmap */
+#define DOT11_MNG_TIM_FIXED_LEN 3
+#define DOT11_MNG_TIM_DTIM_COUNT 0
+#define DOT11_MNG_TIM_DTIM_PERIOD 1
+#define DOT11_MNG_TIM_BITMAP_CTL 2
+#define DOT11_MNG_TIM_PVB 3
+
+/* TLV defines */
+#define TLV_TAG_OFF 0
+#define TLV_LEN_OFF 1
+#define TLV_HDR_LEN 2
+#define TLV_BODY_OFF 2
+
+/* Management Frame Information Element IDs */
+#define DOT11_MNG_SSID_ID 0
+#define DOT11_MNG_RATES_ID 1
+#define DOT11_MNG_FH_PARMS_ID 2
+#define DOT11_MNG_DS_PARMS_ID 3
+#define DOT11_MNG_CF_PARMS_ID 4
+#define DOT11_MNG_TIM_ID 5
+#define DOT11_MNG_IBSS_PARMS_ID 6
+#define DOT11_MNG_COUNTRY_ID 7
+#define DOT11_MNG_HOPPING_PARMS_ID 8
+#define DOT11_MNG_HOPPING_TABLE_ID 9
+#define DOT11_MNG_REQUEST_ID 10
+#define DOT11_MNG_CHALLENGE_ID 16
+#define DOT11_MNG_PWR_CONSTRAINT_ID 32 /* 11H PowerConstraint */
+#define DOT11_MNG_PWR_CAP_ID 33 /* 11H PowerCapability */
+#define DOT11_MNG_TPC_REQUEST_ID 34 /* 11H TPC Request */
+#define DOT11_MNG_TPC_REPORT_ID 35 /* 11H TPC Report */
+#define DOT11_MNG_SUPP_CHANNELS_ID 36 /* 11H Supported Channels */
+#define DOT11_MNG_CHANNEL_SWITCH_ID 37 /* 11H ChannelSwitch Announcement*/
+#define DOT11_MNG_MEASURE_REQUEST_ID 38 /* 11H MeasurementRequest */
+#define DOT11_MNG_MEASURE_REPORT_ID 39 /* 11H MeasurementReport */
+#define DOT11_MNG_QUIET_ID 40 /* 11H Quiet */
+#define DOT11_MNG_IBSS_DFS_ID 41 /* 11H IBSS_DFS */
+#define DOT11_MNG_ERP_ID 42
+#define DOT11_MNG_NONERP_ID 47
+#define DOT11_MNG_EXT_RATES_ID 50
+#define DOT11_MNG_WPA_ID 221
+#define DOT11_MNG_PROPR_ID 221
+
+/* ERP info element bit values */
+#define DOT11_MNG_ERP_LEN 1 /* ERP is currently 1 byte long */
+#define DOT11_MNG_NONERP_PRESENT 0x01 /* NonERP (802.11b) STAs are present in the BSS */
+#define DOT11_MNG_USE_PROTECTION 0x02 /* Use protection mechanisms for ERP-OFDM frames */
+#define DOT11_MNG_BARKER_PREAMBLE 0x04 /* Short Preambles: 0 == allowed, 1 == not allowed */
+
+/* Capability Information Field */
+#define DOT11_CAP_ESS 0x0001
+#define DOT11_CAP_IBSS 0x0002
+#define DOT11_CAP_POLLABLE 0x0004
+#define DOT11_CAP_POLL_RQ 0x0008
+#define DOT11_CAP_PRIVACY 0x0010
+#define DOT11_CAP_SHORT 0x0020
+#define DOT11_CAP_PBCC 0x0040
+#define DOT11_CAP_AGILITY 0x0080
+#define DOT11_CAP_SPECTRUM 0x0100
+#define DOT11_CAP_SHORTSLOT 0x0400
+#define DOT11_CAP_CCK_OFDM 0x2000
+
+/* Action Frame Constants */
+#define DOT11_ACTION_CAT_ERR_MASK 0x80
+#define DOT11_ACTION_CAT_SPECT_MNG 0x00
+#define DOT11_ACTION_NOTIFICATION 0x11 /* 17 */
+
+#define DOT11_ACTION_ID_M_REQ 0
+#define DOT11_ACTION_ID_M_REP 1
+#define DOT11_ACTION_ID_TPC_REQ 2
+#define DOT11_ACTION_ID_TPC_REP 3
+#define DOT11_ACTION_ID_CHANNEL_SWITCH 4
+
+/* MLME Enumerations */
+#define DOT11_BSSTYPE_INFRASTRUCTURE 0
+#define DOT11_BSSTYPE_INDEPENDENT 1
+#define DOT11_BSSTYPE_ANY 2
+#define DOT11_SCANTYPE_ACTIVE 0
+#define DOT11_SCANTYPE_PASSIVE 1
+
+/* 802.11 A PHY constants */
+#define APHY_SLOT_TIME 9
+#define APHY_SIFS_TIME 16
+#define APHY_DIFS_TIME (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME))
+#define APHY_PREAMBLE_TIME 16
+#define APHY_SIGNAL_TIME 4
+#define APHY_SYMBOL_TIME 4
+#define APHY_SERVICE_NBITS 16
+#define APHY_TAIL_NBITS 6
+#define APHY_CWMIN 15
+
+/* 802.11 B PHY constants */
+#define BPHY_SLOT_TIME 20
+#define BPHY_SIFS_TIME 10
+#define BPHY_DIFS_TIME 50
+#define BPHY_PLCP_TIME 192
+#define BPHY_PLCP_SHORT_TIME 96
+#define BPHY_CWMIN 31
+
+/* 802.11 G constants */
+#define DOT11_OFDM_SIGNAL_EXTENSION 6
+
+#define PHY_CWMAX 1023
+
+#define DOT11_MAXNUMFRAGS 16 /* max # fragments per MSDU */
+
+/* dot11Counters Table - 802.11 spec., Annex D */
+typedef struct d11cnt {
+ uint32 txfrag; /* dot11TransmittedFragmentCount */
+ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */
+ uint32 txfail; /* dot11FailedCount */
+ uint32 txretry; /* dot11RetryCount */
+ uint32 txretrie; /* dot11MultipleRetryCount */
+ uint32 rxdup; /* dot11FrameduplicateCount */
+ uint32 txrts; /* dot11RTSSuccessCount */
+ uint32 txnocts; /* dot11RTSFailureCount */
+ uint32 txnoack; /* dot11ACKFailureCount */
+ uint32 rxfrag; /* dot11ReceivedFragmentCount */
+ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */
+ uint32 rxcrc; /* dot11FCSErrorCount */
+ uint32 txfrmsnt; /* dot11TransmittedFrameCount */
+ uint32 rxundec; /* dot11WEPUndecryptableCount */
+} d11cnt_t;
+
+/* BRCM OUI */
+#define BRCM_OUI "\x00\x10\x18"
+
+/* BRCM info element */
+struct brcm_ie {
+ uchar id;
+ uchar len;
+ uchar oui[3];
+ uchar ver;
+ uchar assoc; /* # of assoc STAs */
+ uchar flags; /* misc flags */
+} PACKED;
+#define BRCM_IE_LEN 8
+typedef struct brcm_ie brcm_ie_t;
+#define BRCM_IE_VER 1
+
+/* brcm_ie flags */
+#define BRF_ABCAP 0x1 /* afterburner capable */
+#define BRF_ABRQRD 0x2 /* afterburner requested */
+
+/* WPA definitions */
+#define WPA_VERSION 1
+#define WPA_OUI "\x00\x50\xF2"
+
+#define WPA_OUI_LEN 3
+
+/* WPA authentication modes */
+#define WPA_AUTH_NONE 0 /* None */
+#define WPA_AUTH_UNSPECIFIED 1 /* Unspecified authentication over 802.1X: default for WPA */
+#define WPA_AUTH_PSK 2 /* Pre-shared Key over 802.1X */
+#define WPA_AUTH_DISABLED 255 /* Legacy (i.e., non-WPA) */
+
+#define IS_WPA_AUTH(auth) ((auth) == WPA_AUTH_NONE || \
+ (auth) == WPA_AUTH_UNSPECIFIED || \
+ (auth) == WPA_AUTH_PSK)
+
+
+/* Key related defines */
+#define DOT11_MAX_DEFAULT_KEYS 4 /* number of default keys */
+#define DOT11_MAX_KEY_SIZE 32 /* max size of any key */
+#define DOT11_MAX_IV_SIZE 16 /* max size of any IV */
+#define DOT11_EXT_IV_FLAG (1<<5) /* flag to indicate IV is > 4 bytes */
+
+#define WEP1_KEY_SIZE 5 /* max size of any WEP key */
+#define WEP1_KEY_HEX_SIZE 10 /* size of WEP key in hex. */
+#define WEP128_KEY_SIZE 13 /* max size of any WEP key */
+#define WEP128_KEY_HEX_SIZE 26 /* size of WEP key in hex. */
+#define TKIP_MIC_SIZE 8 /* size of TKIP MIC */
+#define TKIP_EOM_SIZE 7 /* max size of TKIP EOM */
+#define TKIP_EOM_FLAG 0x5a /* TKIP EOM flag byte */
+#define TKIP_KEY_SIZE 32 /* size of any TKIP key */
+#define TKIP_MIC_AUTH_TX 16 /* offset to Authenticator MIC TX key */
+#define TKIP_MIC_AUTH_RX 24 /* offset to Authenticator MIC RX key */
+#define TKIP_MIC_SUP_RX 16 /* offset to Supplicant MIC RX key */
+#define TKIP_MIC_SUP_TX 24 /* offset to Supplicant MIC TX key */
+#define AES_KEY_SIZE 16 /* size of AES key */
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#endif /* _802_11_H_ */
diff --git a/package/nvram/src/include/proto/ethernet.h b/package/nvram/src/include/proto/ethernet.h
new file mode 100644
index 0000000000..173464af63
--- /dev/null
+++ b/package/nvram/src/include/proto/ethernet.h
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * $Id$
+ * 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.
+ * From FreeBSD 2.2.7: Fundamental constants relating to ethernet.
+ ******************************************************************************/
+
+#ifndef _NET_ETHERNET_H_ /* use native BSD ethernet.h when available */
+#define _NET_ETHERNET_H_
+
+#ifndef _TYPEDEFS_H_
+#include "typedefs.h"
+#endif
+
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#define PACKED
+#endif
+
+/*
+ * The number of bytes in an ethernet (MAC) address.
+ */
+#ifndef ETHER_ADDR_LEN
+#define ETHER_ADDR_LEN 6
+#endif
+
+/*
+ * The number of bytes in the type field.
+ */
+#ifndef ETHER_TYPE_LEN
+#define ETHER_TYPE_LEN 2
+#endif
+
+/*
+ * The number of bytes in the trailing CRC field.
+ */
+#ifndef ETHER_CRC_LEN
+#define ETHER_CRC_LEN 4
+#endif
+
+/*
+ * The length of the combined header.
+ */
+#ifndef ETHER_HDR_LEN
+#define ETHER_HDR_LEN (ETHER_ADDR_LEN*2+ETHER_TYPE_LEN)
+#endif
+
+/*
+ * The minimum packet length.
+ */
+#ifndef ETHER_MIN_LEN
+#define ETHER_MIN_LEN 64
+#endif
+
+/*
+ * The minimum packet user data length.
+ */
+#ifndef ETHER_MIN_DATA
+#define ETHER_MIN_DATA 46
+#endif
+
+/*
+ * The maximum packet length.
+ */
+#ifndef ETHER_MAX_LEN
+#define ETHER_MAX_LEN 1518
+#endif
+
+/*
+ * The maximum packet user data length.
+ */
+#define ETHER_MAX_DATA 1500
+
+/*
+ * Used to uniquely identify a 802.1q VLAN-tagged header.
+ */
+#define VLAN_TAG 0x8100
+
+/*
+ * Located after dest & src address in ether header.
+ */
+#define VLAN_FIELDS_OFFSET (ETHER_ADDR_LEN * 2)
+
+/*
+ * 4 bytes of vlan field info.
+ */
+#define VLAN_FIELDS_SIZE 4
+
+/* location of bits in 16-bit vlan fields */
+#define VLAN_PRI_SHIFT 13 /* user priority */
+#define VLAN_CFI_SHIFT 12 /* canonical format indicator bit */
+
+/* 3 bits of priority */
+#define VLAN_PRI_MASK 7
+/* 12 bits of vlan identfier (VID) */
+#define VLAN_VID_MASK 0xFFF /* VLAN identifier (VID) field */
+
+struct vlan_tags {
+ uint16 tag_type; /* 0x8100 for VLAN */
+ uint16 tag_control; /* prio | cfi | vid */
+} PACKED ;
+
+/* 802.1X ethertype */
+
+#define ETHER_TYPE_IP 0x0800 /* IP */
+#define ETHER_TYPE_BRCM 0x886c /* Broadcom Corp. */
+#define ETHER_TYPE_802_1X 0x888e /* 802.1x */
+
+#define ETHER_BRCM_SUBTYPE_LEN 4 /* Broadcom 4byte subtype follows ethertype */
+#define ETHER_BRCM_CRAM 0x1 /* Broadcom subtype cram protocol */
+
+/*
+ * A macro to validate a length with
+ */
+#define ETHER_IS_VALID_LEN(foo) \
+ ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN)
+
+#ifndef __NET_ETHERNET_H
+#ifndef __INCif_etherh /* Quick and ugly hack for VxWorks */
+/*
+ * Structure of a 10Mb/s Ethernet header.
+ */
+struct ether_header {
+ uint8 ether_dhost[ETHER_ADDR_LEN];
+ uint8 ether_shost[ETHER_ADDR_LEN];
+ uint16 ether_type;
+} PACKED ;
+
+/*
+ * Structure of a 48-bit Ethernet address.
+ */
+struct ether_addr {
+ uint8 octet[ETHER_ADDR_LEN];
+} PACKED ;
+#endif
+#endif
+
+/*
+ * Takes a pointer, returns true if a 48-bit multicast address
+ * (including broadcast, since it is all ones)
+ */
+#define ETHER_ISMULTI(ea) (((uint8 *)(ea))[0] & 1)
+
+/*
+ * Takes a pointer, returns true if a 48-bit broadcast (all ones)
+ */
+#define ETHER_ISBCAST(ea) ((((uint8 *)(ea))[0] & \
+ ((uint8 *)(ea))[1] & \
+ ((uint8 *)(ea))[2] & \
+ ((uint8 *)(ea))[3] & \
+ ((uint8 *)(ea))[4] & \
+ ((uint8 *)(ea))[5]) == 0xff)
+
+static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}};
+
+/*
+ * Takes a pointer, returns true if a 48-bit null address (all zeros)
+ */
+#define ETHER_ISNULLADDR(ea) ((((uint8 *)(ea))[0] | \
+ ((uint8 *)(ea))[1] | \
+ ((uint8 *)(ea))[2] | \
+ ((uint8 *)(ea))[3] | \
+ ((uint8 *)(ea))[4] | \
+ ((uint8 *)(ea))[5]) == 0)
+
+/* Differentiated Services Codepoint - lower 6 bits of tos in iphdr */
+#define DSCP_PRI_MASK 0x3F /* bits 0-6 */
+#define DSCP_WME_PRI_MASK 0x38 /* bits 3-6 */
+#define DSCP_WME_PRI_SHIFT 3
+
+#undef PACKED
+
+#endif /* _NET_ETHERNET_H_ */
diff --git a/package/nvram/src/include/shutils.h b/package/nvram/src/include/shutils.h
new file mode 100644
index 0000000000..783ee9ede1
--- /dev/null
+++ b/package/nvram/src/include/shutils.h
@@ -0,0 +1,200 @@
+/*
+ * Shell-like utility functions
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#ifndef _shutils_h_
+#define _shutils_h_
+#include <string.h>
+/*
+ * Reads file and returns contents
+ * @param fd file descriptor
+ * @return contents of file or NULL if an error occurred
+ */
+extern char * fd2str(int fd);
+
+/*
+ * Reads file and returns contents
+ * @param path path to file
+ * @return contents of file or NULL if an error occurred
+ */
+extern char * file2str(const char *path);
+
+/*
+ * Waits for a file descriptor to become available for reading or unblocked signal
+ * @param fd file descriptor
+ * @param timeout seconds to wait before timing out or 0 for no timeout
+ * @return 1 if descriptor changed status or 0 if timed out or -1 on error
+ */
+extern int waitfor(int fd, int timeout);
+
+/*
+ * Concatenates NULL-terminated list of arguments into a single
+ * commmand and executes it
+ * @param argv argument list
+ * @param path NULL, ">output", or ">>output"
+ * @param timeout seconds to wait before timing out or 0 for no timeout
+ * @param ppid NULL to wait for child termination or pointer to pid
+ * @return return value of executed command or errno
+ */
+extern int _eval(char *const argv[], char *path, int timeout, pid_t *ppid);
+
+/*
+ * Concatenates NULL-terminated list of arguments into a single
+ * commmand and executes it
+ * @param argv argument list
+ * @return stdout of executed command or NULL if an error occurred
+ */
+extern char * _backtick(char *const argv[]);
+
+/*
+ * Kills process whose PID is stored in plaintext in pidfile
+ * @param pidfile PID file
+ * @return 0 on success and errno on failure
+ */
+extern int kill_pidfile(char *pidfile);
+
+/*
+ * fread() with automatic retry on syscall interrupt
+ * @param ptr location to store to
+ * @param size size of each element of data
+ * @param nmemb number of elements
+ * @param stream file stream
+ * @return number of items successfully read
+ */
+extern int safe_fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
+
+/*
+ * fwrite() with automatic retry on syscall interrupt
+ * @param ptr location to read from
+ * @param size size of each element of data
+ * @param nmemb number of elements
+ * @param stream file stream
+ * @return number of items successfully written
+ */
+extern int safe_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
+
+/*
+ * Convert Ethernet address string representation to binary data
+ * @param a string in xx:xx:xx:xx:xx:xx notation
+ * @param e binary data
+ * @return TRUE if conversion was successful and FALSE otherwise
+ */
+extern int ether_atoe(const char *a, unsigned char *e);
+
+/*
+ * Convert Ethernet address binary data to string representation
+ * @param e binary data
+ * @param a string in xx:xx:xx:xx:xx:xx notation
+ * @return a
+ */
+extern char * ether_etoa(const unsigned char *e, char *a);
+
+/*
+ * Concatenate two strings together into a caller supplied buffer
+ * @param s1 first string
+ * @param s2 second string
+ * @param buf buffer large enough to hold both strings
+ * @return buf
+ */
+static inline char * strcat_r(const char *s1, const char *s2, char *buf)
+{
+ strcpy(buf, s1);
+ strcat(buf, s2);
+ return buf;
+}
+
+/* Check for a blank character; that is, a space or a tab */
+#define isblank(c) ((c) == ' ' || (c) == '\t')
+
+/* Strip trailing CR/NL from string <s> */
+#define chomp(s) ({ \
+ char *c = (s) + strlen((s)) - 1; \
+ while ((c > (s)) && (*c == '\n' || *c == '\r' || *c == ' ')) \
+ *c-- = '\0'; \
+ s; \
+})
+
+/* Simple version of _backtick() */
+#define backtick(cmd, args...) ({ \
+ char *argv[] = { cmd, ## args, NULL }; \
+ _backtick(argv); \
+})
+
+/* Simple version of _eval() (no timeout and wait for child termination) */
+#define eval(cmd, args...) ({ \
+ char *argv[] = { cmd, ## args, NULL }; \
+ _eval(argv, ">/dev/console", 0, NULL); \
+})
+
+/* Copy each token in wordlist delimited by space into word */
+#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, ' '))
+
+/* Return NUL instead of NULL if undefined */
+#define safe_getenv(s) (getenv(s) ? : "")
+
+/* Print directly to the console */
+#define cprintf(fmt, args...) do { \
+ FILE *fp = fopen("/dev/console", "w"); \
+ if (fp) { \
+ fprintf(fp, fmt, ## args); \
+ fclose(fp); \
+ } \
+} while (0)
+
+/* Debug print */
+#ifdef DEBUG
+#define dprintf(fmt, args...) cprintf("%s: " fmt, __FUNCTION__, ## args)
+#else
+#define dprintf(fmt, args...)
+#endif
+
+#ifdef vxworks
+
+#include <inetLib.h>
+#define inet_aton(a, n) ((inet_aton((a), (n)) == ERROR) ? 0 : 1)
+#define inet_ntoa(n) ({ char a[INET_ADDR_LEN]; inet_ntoa_b ((n), a); a; })
+
+#include <typedefs.h>
+#include <bcmutils.h>
+#define ether_atoe(a, e) bcm_ether_atoe((a), (e))
+#define ether_etoa(e, a) bcm_ether_ntoa((e), (a))
+
+/* These declarations are not available where you would expect them */
+extern int vsnprintf (char *, size_t, const char *, va_list);
+extern int snprintf(char *str, size_t count, const char *fmt, ...);
+extern char *strdup(const char *);
+extern char *strsep(char **stringp, char *delim);
+extern int strcasecmp(const char *s1, const char *s2);
+extern int strncasecmp(const char *s1, const char *s2, size_t n);
+
+/* Neither are socket() and connect() */
+#include <sockLib.h>
+
+#ifdef DEBUG
+#undef dprintf
+#define dprintf printf
+#endif
+#endif
+
+#endif /* _shutils_h_ */
diff --git a/package/nvram/src/include/typedefs.h b/package/nvram/src/include/typedefs.h
new file mode 100644
index 0000000000..6b0c25e042
--- /dev/null
+++ b/package/nvram/src/include/typedefs.h
@@ -0,0 +1,293 @@
+/*
+ * 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.
+ * $Id$
+ */
+
+#ifndef _TYPEDEFS_H_
+#define _TYPEDEFS_H_
+
+
+/* Define 'SITE_TYPEDEFS' in the compile to include a site specific
+ * typedef file "site_typedefs.h".
+ *
+ * If 'SITE_TYPEDEFS' is not defined, then the "Inferred Typedefs"
+ * section of this file makes inferences about the compile environment
+ * based on defined symbols and possibly compiler pragmas.
+ *
+ * Following these two sections is the "Default Typedefs"
+ * section. This section is only prcessed if 'USE_TYPEDEF_DEFAULTS' is
+ * defined. This section has a default set of typedefs and a few
+ * proprocessor symbols (TRUE, FALSE, NULL, ...).
+ */
+
+#ifdef SITE_TYPEDEFS
+
+/*******************************************************************************
+ * Site Specific Typedefs
+ *******************************************************************************/
+
+#include "site_typedefs.h"
+
+#else
+
+/*******************************************************************************
+ * Inferred Typedefs
+ *******************************************************************************/
+
+/* Infer the compile environment based on preprocessor symbols and pramas.
+ * Override type definitions as needed, and include configuration dependent
+ * header files to define types.
+ */
+
+#ifdef __cplusplus
+
+#define TYPEDEF_BOOL
+#ifndef FALSE
+#define FALSE false
+#endif
+#ifndef TRUE
+#define TRUE true
+#endif
+
+#else /* ! __cplusplus */
+
+/* for Windows build, define bool as a uchar instead of the default int */
+#if defined(_WIN32)
+
+#define TYPEDEF_BOOL
+typedef unsigned char bool;
+
+#endif /* _WIN32 */
+
+#endif /* ! __cplusplus */
+
+#ifdef _MSC_VER /* Microsoft C */
+#define TYPEDEF_INT64
+#define TYPEDEF_UINT64
+typedef signed __int64 int64;
+typedef unsigned __int64 uint64;
+#endif
+
+#if defined(MACOSX) && defined(KERNEL)
+#define TYPEDEF_BOOL
+#endif
+
+
+#if defined(linux)
+#define TYPEDEF_UINT
+#define TYPEDEF_USHORT
+#define TYPEDEF_ULONG
+#endif
+
+#if !defined(linux) && !defined(_WIN32) && !defined(PMON) && !defined(_CFE_)
+#define TYPEDEF_UINT
+#define TYPEDEF_USHORT
+#endif
+
+
+/* Do not support the (u)int64 types with strict ansi for GNU C */
+#if defined(__GNUC__) && defined(__STRICT_ANSI__)
+#define TYPEDEF_INT64
+#define TYPEDEF_UINT64
+#endif
+
+/* ICL accepts unsigned 64 bit type only, and complains in ANSI mode
+ * for singned or unsigned */
+#if defined(__ICL)
+
+#define TYPEDEF_INT64
+
+#if defined(__STDC__)
+#define TYPEDEF_UINT64
+#endif
+
+#endif /* __ICL */
+
+
+#if !defined(_WIN32) && !defined(PMON) && !defined(_CFE_)
+
+/* pick up ushort & uint from standard types.h */
+#if defined(linux) && defined(__KERNEL__)
+
+#include <linux/types.h> /* sys/types.h and linux/types.h are oil and water */
+
+#else
+
+#include <sys/types.h>
+
+#endif
+
+#endif /* !_WIN32 && !PMON && !_CFE_ */
+
+#if defined(MACOSX) && defined(KERNEL)
+#include <IOKit/IOTypes.h>
+#endif
+
+
+/* use the default typedefs in the next section of this file */
+#define USE_TYPEDEF_DEFAULTS
+
+#endif /* SITE_TYPEDEFS */
+
+
+/*******************************************************************************
+ * Default Typedefs
+ *******************************************************************************/
+
+#ifdef USE_TYPEDEF_DEFAULTS
+#undef USE_TYPEDEF_DEFAULTS
+
+#ifndef TYPEDEF_BOOL
+typedef int bool;
+#endif
+
+/*----------------------- define uchar, ushort, uint, ulong ----------------*/
+
+#ifndef TYPEDEF_UCHAR
+typedef unsigned char uchar;
+#endif
+
+#ifndef TYPEDEF_USHORT
+typedef unsigned short ushort;
+#endif
+
+#ifndef TYPEDEF_UINT
+typedef unsigned int uint;
+#endif
+
+#ifndef TYPEDEF_ULONG
+typedef unsigned long ulong;
+#endif
+
+/*----------------------- define [u]int8/16/32/64 --------------------------*/
+
+#ifndef TYPEDEF_UINT8
+typedef unsigned char uint8;
+#endif
+
+#ifndef TYPEDEF_UINT16
+typedef unsigned short uint16;
+#endif
+
+#ifndef TYPEDEF_UINT32
+typedef unsigned int uint32;
+#endif
+
+#ifndef TYPEDEF_UINT64
+typedef unsigned long long uint64;
+#endif
+
+#ifndef TYPEDEF_INT8
+typedef signed char int8;
+#endif
+
+#ifndef TYPEDEF_INT16
+typedef signed short int16;
+#endif
+
+#ifndef TYPEDEF_INT32
+typedef signed int int32;
+#endif
+
+#ifndef TYPEDEF_INT64
+typedef signed long long int64;
+#endif
+
+/*----------------------- define float32/64, float_t -----------------------*/
+
+#ifndef TYPEDEF_FLOAT32
+typedef float float32;
+#endif
+
+#ifndef TYPEDEF_FLOAT64
+typedef double float64;
+#endif
+
+/*
+ * abstracted floating point type allows for compile time selection of
+ * single or double precision arithmetic. Compiling with -DFLOAT32
+ * selects single precision; the default is double precision.
+ */
+
+#ifndef TYPEDEF_FLOAT_T
+
+#if defined(FLOAT32)
+typedef float32 float_t;
+#else /* default to double precision floating point */
+typedef float64 float_t;
+#endif
+
+#endif /* TYPEDEF_FLOAT_T */
+
+/*----------------------- define macro values -----------------------------*/
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef OFF
+#define OFF 0
+#endif
+
+#ifndef ON
+#define ON 1
+#endif
+
+/*----------------------- define PTRSZ, INLINE ----------------------------*/
+
+#ifndef PTRSZ
+#define PTRSZ sizeof (char*)
+#endif
+
+#ifndef INLINE
+
+#ifdef _MSC_VER
+
+#define INLINE __inline
+
+#elif __GNUC__
+
+#define INLINE __inline__
+
+#else
+
+#define INLINE
+
+#endif /* _MSC_VER */
+
+#endif /* INLINE */
+
+#undef TYPEDEF_BOOL
+#undef TYPEDEF_UCHAR
+#undef TYPEDEF_USHORT
+#undef TYPEDEF_UINT
+#undef TYPEDEF_ULONG
+#undef TYPEDEF_UINT8
+#undef TYPEDEF_UINT16
+#undef TYPEDEF_UINT32
+#undef TYPEDEF_UINT64
+#undef TYPEDEF_INT8
+#undef TYPEDEF_INT16
+#undef TYPEDEF_INT32
+#undef TYPEDEF_INT64
+#undef TYPEDEF_FLOAT32
+#undef TYPEDEF_FLOAT64
+#undef TYPEDEF_FLOAT_T
+
+#endif /* USE_TYPEDEF_DEFAULTS */
+
+#endif /* _TYPEDEFS_H_ */
diff --git a/package/nvram/src/include/utils.h b/package/nvram/src/include/utils.h
new file mode 100644
index 0000000000..b8d1cdb7bf
--- /dev/null
+++ b/package/nvram/src/include/utils.h
@@ -0,0 +1,131 @@
+#include <cy_conf.h>
+
+extern int diag_led(int type, int act);
+extern int C_led(int i);
+extern int get_single_ip(char *ipaddr, int which);
+extern char *get_mac_from_ip(char *ip);
+extern struct dns_lists *get_dns_list(int no);
+extern int dns_to_resolv(void);
+extern char *get_wan_face(void);
+extern int check_wan_link(int num);
+extern char *get_complete_lan_ip(char *ip);
+extern int get_int_len(int num);
+extern int file_to_buf(char *path, char *buf, int len);
+extern int buf_to_file(char *path, char *buf);
+extern pid_t* find_pid_by_name( char* pidName);
+extern int find_pid_by_ps(char* pidName);
+extern int *find_all_pid_by_ps(char* pidName);
+extern char *find_name_by_proc(int pid);
+extern int get_ppp_pid(char *file);
+extern long convert_ver(char *ver);
+extern int check_flash(void);
+extern int check_action(void);
+extern int check_now_boot(void);
+extern int check_hw_type(void);
+extern int is_exist(char *filename);
+extern void set_ip_forward(char c);
+struct mtu_lists *get_mtu(char *proto);
+extern void set_host_domain_name(void);
+
+extern void encode(char *buf, int len);
+extern void decode(char *buf, int len);
+
+extern int sys_netdev_ioctl(int family, int socket, char *if_name, int cmd, struct ifreq *ifr);
+
+int ct_openlog(const char *ident, int option, int facility, char *log_name);
+void ct_syslog(int level, int enable, const char *fmt,...);
+void ct_logger(int level, const char *fmt,...);
+struct wl_assoc_mac * get_wl_assoc_mac(int *c);
+
+
+
+enum { DMZ, SESSION, DIAG , WL};
+
+enum { START_LED, STOP_LED };
+
+typedef enum { ACT_IDLE,
+ ACT_TFTP_UPGRADE,
+ ACT_WEB_UPGRADE,
+ ACT_WEBS_UPGRADE,
+ ACT_SW_RESTORE,
+ ACT_HW_RESTORE } ACTION;
+
+enum { UNKNOWN_BOOT = -1, PMON_BOOT, CFE_BOOT };
+
+enum { BCM4702_CHIP, BCM4712_CHIP, BCM5325E_CHIP };
+
+enum { FIRST, SECOND };
+
+enum { SYSLOG_LOG=1, SYSLOG_DEBUG, CONSOLE_ONLY, LOG_CONSOLE, DEBUG_CONSOLE };
+
+#define ACTION(cmd) buf_to_file(ACTION_FILE, cmd)
+
+struct dns_lists {
+ int num_servers;
+ char dns_server[4][16];
+};
+
+#define NOT_USING 0
+#define USING 1
+
+struct wl_assoc_mac
+{
+ char mac[18];
+};
+
+struct mtu_lists {
+ char *proto; /* protocol */
+ char *min; /* min mtu */
+ char *max; /* max mtu */
+};
+
+
+#define PPP_PSEUDO_IP "10.64.64.64"
+#define PPP_PSEUDO_NM "255.255.255.255"
+#define PPP_PSEUDO_GW "10.112.112.112"
+
+#define PING_TMP "/tmp/ping.log"
+#define TRACEROUTE_TMP "/tmp/traceroute.log"
+#define MAX_BUF_LEN 254
+
+#define RESOLV_FILE "/tmp/resolv.conf"
+#define HOSTS_FILE "/tmp/hosts"
+
+#define LOG_FILE "/var/log/mess"
+
+#define ACTION_FILE "/tmp/action"
+
+
+#define split(word, wordlist, next, delim) \
+ for (next = wordlist, \
+ strncpy(word, next, sizeof(word)), \
+ word[(next=strstr(next, delim)) ? strstr(word, delim) - word : sizeof(word) - 1] = '\0', \
+ next = next ? next + sizeof(delim) - 1 : NULL ; \
+ strlen(word); \
+ next = next ? : "", \
+ strncpy(word, next, sizeof(word)), \
+ word[(next=strstr(next, delim)) ? strstr(word, delim) - word : sizeof(word) - 1] = '\0', \
+ next = next ? next + sizeof(delim) - 1 : NULL)
+
+#define STRUCT_LEN(name) sizeof(name)/sizeof(name[0])
+
+#define printHEX(str,len) { \
+ int i; \
+ for (i=0 ; i<len ; i++) { \
+ printf("%02X ", (unsigned char)*(str+i)); \
+ if(((i+1)%16) == 0) printf("- "); \
+ if(((i+1)%32) == 0) printf("\n"); \
+ } \
+ printf("\n\n"); \
+}
+
+
+#define printASC(str,len) { \
+ int i; \
+ for (i=0 ; i<len ; i++) { \
+ printf("%c", (unsigned char)*(str+i)); \
+ if(((i+1)%16) == 0) printf("- "); \
+ if(((i+1)%32) == 0) printf("\n"); \
+ } \
+ printf("\n\n"); \
+}
diff --git a/package/nvram/src/include/wlcompat.h b/package/nvram/src/include/wlcompat.h
new file mode 100644
index 0000000000..a4fc13439d
--- /dev/null
+++ b/package/nvram/src/include/wlcompat.h
@@ -0,0 +1,36 @@
+/*
+ * wlcompat.h
+ *
+ * Copyright (C) 2005 Felix Fietkau <nbd@vd-s.ath.cx>
+ *
+ * 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.
+ *
+ * $Id$
+ */
+#include <linux/wireless.h>
+
+#ifndef WLCOMPAT_H
+#define WLCOMPAT_H
+
+#define WLCOMPAT_SET_MONITOR SIOCIWFIRSTPRIV + 0
+#define WLCOMPAT_GET_MONITOR SIOCIWFIRSTPRIV + 1
+#define WLCOMPAT_SET_TXPWR_LIMIT SIOCIWFIRSTPRIV + 2
+#define WLCOMPAT_GET_TXPWR_LIMIT SIOCIWFIRSTPRIV + 3
+#define WLCOMPAT_SET_ANTDIV SIOCIWFIRSTPRIV + 4
+#define WLCOMPAT_GET_ANTDIV SIOCIWFIRSTPRIV + 5
+#define WLCOMPAT_SET_TXANT SIOCIWFIRSTPRIV + 6
+#define WLCOMPAT_GET_TXANT SIOCIWFIRSTPRIV + 7
+
+#endif
diff --git a/package/nvram/src/include/wlioctl.h b/package/nvram/src/include/wlioctl.h
new file mode 100644
index 0000000000..66783cc44d
--- /dev/null
+++ b/package/nvram/src/include/wlioctl.h
@@ -0,0 +1,1097 @@
+/*
+ * Custom OID/ioctl definitions for
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Definitions subject to change without notice.
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#ifndef _wlioctl_h_
+#define _wlioctl_h_
+
+#include <typedefs.h>
+#include <proto/ethernet.h>
+#include <proto/802.11.h>
+
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#define PACKED
+#endif
+
+#define WLC_ESSID_MAX_SIZE 32
+
+#define WL_NUMRATES 255 /* max # of rates in a rateset */
+
+typedef struct wl_rateset {
+ uint32 count; /* # rates in this set */
+ uint8 rates[WL_NUMRATES]; /* rates in 500kbps units w/hi bit set if basic */
+} wl_rateset_t;
+
+#define WL_CHANSPEC_CHAN_MASK 0x0fff
+#define WL_CHANSPEC_BAND_MASK 0xf000
+#define WL_CHANSPEC_BAND_SHIFT 12
+#define WL_CHANSPEC_BAND_A 0x1000
+#define WL_CHANSPEC_BAND_B 0x2000
+
+/*
+ * Per-bss information structure.
+ */
+
+#define WL_LEGACY_BSS_INFO_VERSION 106 /* an older supported version of wl_bss_info struct */
+#define WL_BSS_INFO_VERSION 107 /* current version of wl_bss_info struct */
+
+typedef struct wl_bss_info106 {
+ uint version; /* version field */
+ struct ether_addr BSSID;
+ uint8 SSID_len;
+ uint8 SSID[32];
+ uint8 Privacy; /* 0=No WEP, 1=Use WEP */
+ int16 RSSI; /* receive signal strength (in dBm) */
+ uint16 beacon_period; /* units are Kusec */
+ uint16 atim_window; /* units are Kusec */
+ uint8 channel; /* Channel no. */
+ int8 infra; /* 0=IBSS, 1=infrastructure, 2=unknown */
+ struct {
+ uint count; /* # rates in this set */
+ uint8 rates[12]; /* rates in 500kbps units w/hi bit set if basic */
+ } rateset; /* supported rates */
+ uint8 dtim_period; /* DTIM period */
+ int8 phy_noise; /* noise right after tx (in dBm) */
+ uint16 capability; /* Capability information */
+ struct dot11_bcn_prb *prb; /* probe response frame (ioctl na) */
+ uint16 prb_len; /* probe response frame length (ioctl na) */
+ struct {
+ uint8 supported; /* wpa supported */
+ uint8 multicast; /* multicast cipher */
+ uint8 ucount; /* count of unicast ciphers */
+ uint8 unicast[4]; /* unicast ciphers */
+ uint8 acount; /* count of auth modes */
+ uint8 auth[4]; /* Authentication modes */
+ } wpa;
+} wl_bss_info106_t;
+
+typedef struct wl_bss_info {
+ uint32 version; /* version field */
+ uint32 length; /* byte length of data in this record, starting at version and including IEs */
+ struct ether_addr BSSID;
+ uint16 beacon_period; /* units are Kusec */
+ uint16 capability; /* Capability information */
+ uint8 SSID_len;
+ uint8 SSID[32];
+ struct {
+ uint count; /* # rates in this set */
+ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */
+ } rateset; /* supported rates */
+ uint8 channel; /* Channel no. */
+ uint16 atim_window; /* units are Kusec */
+ uint8 dtim_period; /* DTIM period */
+ int16 RSSI; /* receive signal strength (in dBm) */
+ int8 phy_noise; /* noise (in dBm) */
+ uint32 ie_length; /* byte length of Information Elements */
+ /* variable length Information Elements */
+} wl_bss_info_t;
+
+typedef struct wlc_ssid {
+ uint32 SSID_len;
+ uchar SSID[32];
+} wlc_ssid_t;
+
+typedef struct wl_scan_params {
+ wlc_ssid_t ssid; /* default is {0, ""} */
+ struct ether_addr bssid;/* default is bcast */
+ int8 bss_type; /* default is any, DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT */
+ int8 scan_type; /* -1 use default, DOT11_SCANTYPE_ACTIVE/PASSIVE */
+ int32 nprobes; /* -1 use default, number of probes per channel */
+ int32 active_time; /* -1 use default, dwell time per channel for active scanning */
+ int32 passive_time; /* -1 use default, dwell time per channel for passive scanning */
+ int32 home_time; /* -1 use default, dwell time for the home channel between channel scans */
+ int32 channel_num; /* 0 use default (all available channels), count of channels in channel_list */
+ uint16 channel_list[1]; /* list of chanspecs */
+} wl_scan_params_t;
+/* size of wl_scan_params not including variable length array */
+#define WL_SCAN_PARAMS_FIXED_SIZE 64
+
+typedef struct wl_scan_results {
+ uint32 buflen;
+ uint32 version;
+ uint32 count;
+ wl_bss_info_t bss_info[1];
+} wl_scan_results_t;
+/* size of wl_scan_results not including variable length array */
+#define WL_SCAN_RESULTS_FIXED_SIZE 12
+
+/* uint32 list */
+typedef struct wl_uint32_list {
+ /* in - # of elements, out - # of entries */
+ uint32 count;
+ /* variable length uint32 list */
+ uint32 element[1];
+} wl_uint32_list_t;
+
+#define WLC_CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NULL */
+
+typedef struct wl_channels_in_country {
+ uint32 buflen;
+ uint32 band;
+ char country_abbrev[WLC_CNTRY_BUF_SZ];
+ uint32 count;
+ uint32 channel[1];
+} wl_channels_in_country_t;
+
+typedef struct wl_country_list {
+ uint32 buflen;
+ uint32 band_set;
+ uint32 band;
+ uint32 count;
+ char country_abbrev[1];
+} wl_country_list_t;
+
+#define WL_RM_TYPE_BASIC 1
+#define WL_RM_TYPE_CCA 2
+#define WL_RM_TYPE_RPI 3
+
+#define WL_RM_FLAG_PARALLEL (1<<0)
+
+#define WL_RM_FLAG_LATE (1<<1)
+#define WL_RM_FLAG_INCAPABLE (1<<2)
+#define WL_RM_FLAG_REFUSED (1<<3)
+
+typedef struct wl_rm_req_elt {
+ int8 type;
+ int8 flags;
+ uint16 chanspec;
+ uint32 token; /* token for this measurement */
+ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */
+ uint32 tsf_l; /* TSF low 32-bits */
+ uint32 dur; /* TUs */
+} wl_rm_req_elt_t;
+
+typedef struct wl_rm_req {
+ uint32 token; /* overall measurement set token */
+ uint32 count; /* number of measurement reqests */
+ wl_rm_req_elt_t req[1]; /* variable length block of requests */
+} wl_rm_req_t;
+#define WL_RM_REQ_FIXED_LEN 8
+
+typedef struct wl_rm_rep_elt {
+ int8 type;
+ int8 flags;
+ uint16 chanspec;
+ uint32 token; /* token for this measurement */
+ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */
+ uint32 tsf_l; /* TSF low 32-bits */
+ uint32 dur; /* TUs */
+ uint32 len; /* byte length of data block */
+ uint8 data[1]; /* variable length data block */
+} wl_rm_rep_elt_t;
+#define WL_RM_REP_ELT_FIXED_LEN 24 /* length excluding data block */
+
+#define WL_RPI_REP_BIN_NUM 8
+typedef struct wl_rm_rpi_rep {
+ uint8 rpi[WL_RPI_REP_BIN_NUM];
+ int8 rpi_max[WL_RPI_REP_BIN_NUM];
+} wl_rm_rpi_rep_t;
+
+typedef struct wl_rm_rep {
+ uint32 token; /* overall measurement set token */
+ uint32 len; /* length of measurement report block */
+ wl_rm_rep_elt_t rep[1]; /* variable length block of reports */
+} wl_rm_rep_t;
+#define WL_RM_REP_FIXED_LEN 8
+
+
+#define WLC_MAX_KEY_SIZE 32 /* max size of any key */
+#define WLC_MAX_IV_SIZE 16 /* max size of any IV */
+#define WLC_EXT_IV_FLAG (1<<5) /* flag to indicate IV is > 4 bytes */
+#define WLC_MAX_DEFAULT_KEYS 4 /* # of default WEP keys */
+#define WLC_MAX_KEYS 54 /* Max # of WEP keys */
+#define WLC_WEP1_KEY_SIZE 5 /* max size of any WEP key */
+#define WLC_WEP1_KEY_HEX_SIZE 10 /* size of WEP key in hex. */
+#define WLC_WEP128_KEY_SIZE 13 /* max size of any WEP key */
+#define WLC_WEP128_KEY_HEX_SIZE 26 /* size of WEP key in hex. */
+#define WLC_TKIP_MIC_SIZE 8 /* size of TKIP MIC */
+#define WLC_TKIP_EOM_SIZE 7 /* max size of TKIP EOM */
+#define WLC_TKIP_EOM_FLAG 0x5a /* TKIP EOM flag byte */
+#define WLC_TKIP_KEY_SIZE 32 /* size of any TKIP key */
+#define WLC_TKIP_MIC_AUTH_TX 16 /* offset to Authenticator MIC TX key */
+#define WLC_TKIP_MIC_AUTH_RX 24 /* offset to Authenticator MIC RX key */
+#define WLC_TKIP_MIC_SUP_RX 16 /* offset to Supplicant MIC RX key */
+#define WLC_TKIP_MIC_SUP_TX 24 /* offset to Supplicant MIC TX key */
+#define WLC_TKIP_P1_KEY_SIZE 10 /* size of TKHash Phase1 output, in bytes */
+#define WLC_TKIP_P2_KEY_SIZE 16 /* size of TKHash Phase2 output */
+#define WLC_AES_KEY_SIZE 16 /* size of AES key */
+
+
+typedef enum sup_auth_status {
+ WLC_SUP_DISCONNECTED = 0,
+ WLC_SUP_CONNECTING,
+ WLC_SUP_IDREQUIRED,
+ WLC_SUP_AUTHENTICATING,
+ WLC_SUP_AUTHENTICATED,
+ WLC_SUP_KEYXCHANGE,
+ WLC_SUP_KEYED
+} sup_auth_status_t;
+
+/* Enumerate crypto algorithms */
+#define CRYPTO_ALGO_OFF 0
+#define CRYPTO_ALGO_WEP1 1
+#define CRYPTO_ALGO_TKIP 2
+#define CRYPTO_ALGO_WEP128 3
+#define CRYPTO_ALGO_AES_CCM 4
+#define CRYPTO_ALGO_AES_OCB_MSDU 5
+#define CRYPTO_ALGO_AES_OCB_MPDU 6
+#define CRYPTO_ALGO_NALG 7
+
+#define WSEC_GEN_MIC_ERROR 0x0001
+#define WSEC_GEN_REPLAY 0x0002
+
+#define WL_SOFT_KEY (1 << 0) /* Indicates this key is using soft encrypt */
+#define WL_PRIMARY_KEY (1 << 1) /* Indicates this key is the primary (ie tx) key */
+#define WL_KF_RES_4 (1 << 4) /* Reserved for backward compat */
+#define WL_KF_RES_5 (1 << 5) /* Reserved for backward compat */
+
+
+typedef struct wlc_tkip_info {
+ uint16 phase1[WLC_TKIP_P1_KEY_SIZE/sizeof(uint16)]; /* tkhash phase1 result */
+ uint8 phase2[WLC_TKIP_P2_KEY_SIZE]; /* tkhash phase2 result */
+ uint32 micl;
+ uint32 micr;
+} tkip_info_t;
+
+typedef struct _wsec_iv {
+ uint32 hi; /* upper 32 bits of IV */
+ uint16 lo; /* lower 16 bits of IV */
+} wsec_iv_t;
+
+typedef struct wsec_key {
+ uint32 index; /* key index */
+ uint32 len; /* key length */
+ uint8 data[WLC_MAX_KEY_SIZE]; /* key data */
+ tkip_info_t tkip_tx; /* tkip transmit state */
+ tkip_info_t tkip_rx; /* tkip receive state */
+ uint32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+ uint32 flags; /* misc flags */
+ uint32 algo_hw; /* cache for hw register*/
+ uint32 aes_mode; /* cache for hw register*/
+ int iv_len; /* IV length */
+ int iv_initialized; /* has IV been initialized already? */
+ int icv_len; /* ICV length */
+ wsec_iv_t rxiv; /* Rx IV */
+ wsec_iv_t txiv; /* Tx IV */
+ struct ether_addr ea; /* per station */
+} wsec_key_t;
+
+
+
+typedef struct wl_wsec_key {
+ uint32 index; /* key index */
+ uint32 len; /* key length */
+ uint8 data[DOT11_MAX_KEY_SIZE]; /* key data */
+ uint32 pad_1[18];
+ uint32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+ uint32 flags; /* misc flags */
+ uint32 pad_2[2];
+ int pad_3;
+ int iv_initialized; /* has IV been initialized already? */
+ int pad_4;
+ /* Rx IV */
+ struct {
+ uint32 hi; /* upper 32 bits of IV */
+ uint16 lo; /* lower 16 bits of IV */
+ } rxiv;
+ uint32 pad_5[2];
+ struct ether_addr ea; /* per station */
+} wl_wsec_key_t;
+
+/* For use with wlc_wep_key.flags */
+#define WSEC_PRIMARY_KEY (1 << 1) /* Indicates this key is the primary (ie tx) key */
+#define WSEC_TKIP_ERROR (1 << 2) /* Provoke deliberate error */
+
+#define WSEC_MIN_PSK_LEN 8
+#define WSEC_MAX_PSK_LEN 64
+
+/* Flag for key material needing passhash'ing */
+#define WSEC_PASSPHRASE (1<<0)
+
+/* recepticle for WLC_SET_WSEC_PMK parameter */
+typedef struct {
+ ushort key_len; /* octets in key material */
+ ushort flags; /* key handling qualification */
+ uint8 key[WSEC_MAX_PSK_LEN]; /* PMK material */
+} wsec_pmk_t;
+
+/* wireless security bitvec */
+#define WEP_ENABLED 1
+#define TKIP_ENABLED 2
+#define AES_ENABLED 4
+#define WSEC_SWFLAG 8
+
+#define WSEC_SW(wsec) ((wsec) & WSEC_SWFLAG)
+#define WSEC_HW(wsec) (!WSEC_SW(wsec))
+#define WSEC_WEP_ENABLED(wsec) ((wsec) & WEP_ENABLED)
+#define WSEC_TKIP_ENABLED(wsec) ((wsec) & TKIP_ENABLED)
+#define WSEC_AES_ENABLED(wsec) ((wsec) & AES_ENABLED)
+#define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
+
+
+/* wireless authentication bit vector */
+#define WPA_ENABLED 1
+#define PSK_ENABLED 2
+
+#define WAUTH_WPA_ENABLED(wauth) ((wauth) & WPA_ENABLED)
+#define WAUTH_PSK_ENABLED(wauth) ((wauth) & PSK_ENABLED)
+#define WAUTH_ENABLED(wauth) ((wauth) & (WPA_ENABLED | PSK_ENABLED))
+
+/* group/mcast cipher */
+#define WPA_MCAST_CIPHER(wsec) (((wsec) & TKIP_ENABLED) ? WPA_CIPHER_TKIP : \
+ ((wsec) & AES_ENABLED) ? WPA_CIPHER_AES_CCM : \
+ WPA_CIPHER_NONE)
+
+
+typedef struct wl_led_info {
+ uint32 index; /* led index */
+ uint32 behavior;
+ bool activehi;
+} wl_led_info_t;
+
+/*
+ * definitions for driver messages passed from WL to NAS.
+ */
+/* Use this to recognize wpa and 802.1x driver messages. */
+static const uint8 wl_wpa_snap_template[] =
+ { 0xaa, 0xaa, 0x03, 0x00, 0x90, 0x4c };
+
+#define WL_WPA_MSG_IFNAME_MAX 16
+
+/* WPA driver message */
+typedef struct wl_wpa_header {
+ struct ether_header eth;
+ struct dot11_llc_snap_header snap;
+ uint8 version;
+ uint8 type;
+ /* version 2 additions */
+ char ifname[WL_WPA_MSG_IFNAME_MAX];
+ /* version specific data */
+ /* uint8 data[1]; */
+} wl_wpa_header_t PACKED;
+
+/*
+ * definitions for 802.2 messages passed from WL to NAS.
+ */
+/* This seems not to be defined outside the kernel on linux. */
+#ifndef ETH_P_802_2
+#define ETH_P_802_2 4
+#endif
+
+#define WL_WPA_HEADER_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN + 2 + WL_WPA_MSG_IFNAME_MAX)
+
+/* WPA driver message ethertype - private between wlc and nas */
+#define WL_WPA_ETHER_TYPE 0x9999
+
+/* WPA driver message current version */
+#define WL_WPA_MSG_VERSION 2
+
+/* Type field values for the 802.2 driver messages for WPA. */
+#define WLC_ASSOC_MSG 1
+#define WLC_DISASSOC_MSG 2
+#define WLC_PTK_MIC_MSG 3
+#define WLC_GTK_MIC_MSG 4
+
+/* Use this to recognize 802.2 driver messages. */
+static const uint8 wpa_snap_template[] =
+ { 0xaa, 0xaa, 0x03, 0x00, 0x90, 0x4c };
+
+
+/* 802.1x driver message */
+typedef struct wl_eapol_header {
+ struct ether_header eth;
+ struct dot11_llc_snap_header snap;
+ uint8 version;
+ uint8 reserved;
+ char ifname[WL_WPA_MSG_IFNAME_MAX];
+ /* version specific data */
+ /* uint8 802_1x_msg[1]; */
+} wl_eapol_header_t PACKED;
+
+#define WL_EAPOL_HEADER_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN + 2 + WL_WPA_MSG_IFNAME_MAX)
+
+/* 802.1x driver message ethertype - private between wlc and nas */
+#define WL_EAPOL_ETHER_TYPE 0x999A
+
+/* 802.1x driver message current version */
+#define WL_EAPOL_MSG_VERSION 1
+
+/* srom read/write struct passed through ioctl */
+typedef struct {
+ uint byteoff; /* byte offset */
+ uint nbytes; /* number of bytes */
+ uint16 buf[1];
+} srom_rw_t;
+
+/* R_REG and W_REG struct passed through ioctl */
+typedef struct {
+ uint32 byteoff; /* byte offset of the field in d11regs_t */
+ uint32 val; /* read/write value of the field */
+ uint32 size; /* sizeof the field */
+} rw_reg_t;
+
+/* Structure used by GET/SET_ATTEN ioctls */
+typedef struct {
+ uint16 auto_ctrl; /* 1: Automatic control, 0: overriden */
+ uint16 bb; /* Baseband attenuation */
+ uint16 radio; /* Radio attenuation */
+ uint16 txctl1; /* Radio TX_CTL1 value */
+} atten_t;
+
+/* Used to get specific STA parameters */
+typedef struct {
+ uint32 val;
+ struct ether_addr ea;
+} scb_val_t;
+
+/* callback registration data types */
+
+typedef struct _mac_event_params {
+ uint msg;
+ struct ether_addr *addr;
+ uint result;
+ uint status;
+ uint auth_type;
+} mac_event_params_t;
+
+typedef struct _mic_error_params {
+ struct ether_addr *ea;
+ bool group;
+ bool flush_txq;
+} mic_error_params_t;
+
+typedef enum _wl_callback {
+ WL_MAC_EVENT_CALLBACK = 0,
+ WL_LINK_UP_CALLBACK,
+ WL_LINK_DOWN_CALLBACK,
+ WL_MIC_ERROR_CALLBACK,
+ WL_LAST_CALLBACK
+} wl_callback_t;
+
+typedef struct _callback {
+ void (*fn)(void *, void *);
+ void *context;
+} callback_t;
+
+typedef struct _scan_callback {
+ void (*fn)(void *);
+ void *context;
+} scan_callback_t;
+
+/* used to register an arbitrary callback via the IOCTL interface */
+typedef struct _set_callback {
+ int index;
+ callback_t callback;
+} set_callback_t;
+
+
+
+/* Event data type */
+typedef struct {
+ uint msg; /* Message (see below) */
+ struct ether_addr *addr; /* Station address (if applicable) */
+ uint status; /* Status code (see below) */
+ uint reason; /* Reason code (if applicable) */
+ uint auth_type; /* WLC_E_AUTH */
+ bool link; /* WLC_E_LINK */
+ bool group; /* WLC_E_MIC_ERROR */
+ bool flush_txq; /* WLC_E_MIC_ERROR */
+} wlc_event_t;
+
+typedef struct {
+ uint16 ver; /* version of this struct */
+ uint16 cap; /* sta's advertized capabilities */
+ uint32 flags; /* flags defined below */
+ uint32 idle; /* time since data pkt rx'd from sta */
+ struct ether_addr ea; /* Station address */
+ wl_rateset_t rateset; /* rateset in use */
+} sta_info_t;
+
+#define WL_STA_INFO_LEN 300
+#define WL_STA_VER 1
+
+/* flags fields */
+#define WL_STA_BRCM 0x01
+#define WL_STA_WME 0x02
+#define WL_STA_ABCAP 0x04
+#define WL_STA_AUTHE 0x08
+#define WL_STA_ASSOC 0x10
+#define WL_STA_AUTHO 0x20
+
+/* Event messages */
+#define WLC_E_SET_SSID 1
+#define WLC_E_JOIN 2
+#define WLC_E_START 3
+#define WLC_E_AUTH 4
+#define WLC_E_AUTH_IND 5
+#define WLC_E_DEAUTH 6
+#define WLC_E_DEAUTH_IND 7
+#define WLC_E_ASSOC 8
+#define WLC_E_ASSOC_IND 9
+#define WLC_E_REASSOC 10
+#define WLC_E_REASSOC_IND 11
+#define WLC_E_DISASSOC 12
+#define WLC_E_DISASSOC_IND 13
+#define WLC_E_QUIET_START 14 /* 802.11h Quiet period started */
+#define WLC_E_QUIET_END 15 /* 802.11h Quiet period ended */
+#define WLC_E_GOT_BEACONS 16
+#define WLC_E_LINK 17 /* Link indication */
+#define WLC_E_MIC_ERROR 18 /* TKIP MIC error occurred */
+#define WLC_E_NDIS_LINK 19 /* NDIS style link indication */
+#define WLC_E_ROAM 20
+#define WLC_E_LAST 21
+
+/* Event status codes */
+#define WLC_E_STATUS_SUCCESS 0
+#define WLC_E_STATUS_FAIL 1
+#define WLC_E_STATUS_TIMEOUT 2
+#define WLC_E_STATUS_NO_NETWORKS 3
+#define WLC_E_STATUS_ABORT 4
+
+typedef struct wlc_event_cb {
+ uint msg; /* Event message or 0 for all */
+ void (*fn)(void *, wlc_event_t *); /* Callback function */
+ void *context; /* Passed to callback function */
+ struct wlc_event_cb *next; /* Next in the chain */
+} wlc_event_cb_t;
+
+/*
+ * Country locale determines which channels are available to us.
+ */
+typedef enum _wlc_locale {
+ WLC_WW = 0, /* Worldwide */
+ WLC_THA, /* Thailand */
+ WLC_ISR, /* Israel */
+ WLC_JDN, /* Jordan */
+ WLC_PRC, /* China */
+ WLC_JPN, /* Japan */
+ WLC_FCC, /* USA */
+ WLC_EUR, /* Europe */
+ WLC_USL, /* US Low Band only */
+ WLC_JPH, /* Japan High Band only */
+ WLC_ALL, /* All the channels in this band */
+ WLC_11D, /* Represents locale recieved by 11d beacons */
+ WLC_LAST_LOCALE,
+ WLC_UNDEFINED_LOCALE = 0xf
+} wlc_locale_t;
+
+/* channel encoding */
+typedef struct channel_info {
+ int hw_channel;
+ int target_channel;
+ int scan_channel;
+} channel_info_t;
+
+/* For ioctls that take a list of MAC addresses */
+struct maclist {
+ uint count; /* number of MAC addresses */
+ struct ether_addr ea[1]; /* variable length array of MAC addresses */
+};
+
+/* get pkt count struct passed through ioctl */
+typedef struct get_pktcnt {
+ uint rx_good_pkt;
+ uint rx_bad_pkt;
+ uint tx_good_pkt;
+ uint tx_bad_pkt;
+} get_pktcnt_t;
+
+/* Linux network driver ioctl encoding */
+typedef struct wl_ioctl {
+ uint cmd; /* common ioctl definition */
+ void *buf; /* pointer to user buffer */
+ uint len; /* length of user buffer */
+ bool set; /* get or set request (optional) */
+ uint used; /* bytes read or written (optional) */
+ uint needed; /* bytes needed (optional) */
+} wl_ioctl_t;
+
+/*
+ * Structure for passing hardware and software
+ * revision info up from the driver.
+ */
+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;
+
+/* check this magic number */
+#define WLC_IOCTL_MAGIC 0x14e46c77
+
+/* bump this number if you change the ioctl interface */
+#define WLC_IOCTL_VERSION 1
+
+/* maximum length buffer required */
+#define WLC_IOCTL_MAXLEN 8192
+
+/* maximum length buffer required */
+#define WLC_IOCTL_SMLEN 256
+
+/* common ioctl definitions */
+#define WLC_GET_MAGIC 0
+#define WLC_GET_VERSION 1
+#define WLC_UP 2
+#define WLC_DOWN 3
+#define WLC_GET_LOOP 4
+#define WLC_SET_LOOP 5
+#define WLC_DUMP 6
+#define WLC_GET_MSGLEVEL 7
+#define WLC_SET_MSGLEVEL 8
+#define WLC_GET_PROMISC 9
+#define WLC_SET_PROMISC 10
+#define WLC_OBSOLETE 11
+#define WLC_GET_RATE 12
+#define WLC_SET_RATE 13
+#define WLC_GET_INSTANCE 14
+#define WLC_GET_FRAG 15
+#define WLC_SET_FRAG 16
+#define WLC_GET_RTS 17
+#define WLC_SET_RTS 18
+#define WLC_GET_INFRA 19
+#define WLC_SET_INFRA 20
+#define WLC_GET_AUTH 21
+#define WLC_SET_AUTH 22
+#define WLC_GET_BSSID 23
+#define WLC_SET_BSSID 24
+#define WLC_GET_SSID 25
+#define WLC_SET_SSID 26
+#define WLC_RESTART 27
+#define WLC_DUMP_SCB 28
+#define WLC_GET_CHANNEL 29
+#define WLC_SET_CHANNEL 30
+#define WLC_GET_SRL 31
+#define WLC_SET_SRL 32
+#define WLC_GET_LRL 33
+#define WLC_SET_LRL 34
+#define WLC_GET_PLCPHDR 35
+#define WLC_SET_PLCPHDR 36
+#define WLC_GET_RADIO 37
+#define WLC_SET_RADIO 38
+#define WLC_GET_PHYTYPE 39
+#define WLC_DUMP_RATE 40
+#define WLC_SET_RATE_PARAMS 41
+#define WLC_GET_WEP 42
+#define WLC_SET_WEP 43
+#define WLC_GET_KEY 44
+#define WLC_SET_KEY 45
+#define WLC_GET_REGULATORY 46
+#define WLC_SET_REGULATORY 47
+#define WLC_GET_PASSIVE 48 /* added by nbd */
+#define WLC_SET_PASSIVE 49 /* added by nbd */
+#define WLC_SCAN 50
+#define WLC_SCAN_RESULTS 51
+#define WLC_DISASSOC 52
+#define WLC_REASSOC 53
+#define WLC_GET_ROAM_TRIGGER 54
+#define WLC_SET_ROAM_TRIGGER 55
+#define WLC_GET_ROAM_DELTA 56
+#define WLC_SET_ROAM_DELTA 57
+#define WLC_GET_ROAM_SCAN_PERIOD 58
+#define WLC_SET_ROAM_SCAN_PERIOD 59
+#define WLC_EVM 60
+#define WLC_GET_TXANT 61
+#define WLC_SET_TXANT 62
+#define WLC_GET_ANTDIV 63
+#define WLC_SET_ANTDIV 64
+#define WLC_GET_TXPWR 65
+#define WLC_SET_TXPWR 66
+#define WLC_GET_CLOSED 67
+#define WLC_SET_CLOSED 68
+#define WLC_GET_MACLIST 69
+#define WLC_SET_MACLIST 70
+#define WLC_GET_RATESET 71
+#define WLC_SET_RATESET 72
+#define WLC_GET_LOCALE 73
+#define WLC_SET_LOCALE 74
+#define WLC_GET_BCNPRD 75
+#define WLC_SET_BCNPRD 76
+#define WLC_GET_DTIMPRD 77
+#define WLC_SET_DTIMPRD 78
+#define WLC_GET_SROM 79
+#define WLC_SET_SROM 80
+#define WLC_GET_WEP_RESTRICT 81
+#define WLC_SET_WEP_RESTRICT 82
+#define WLC_GET_COUNTRY 83
+#define WLC_SET_COUNTRY 84
+#define WLC_GET_PM 85
+#define WLC_SET_PM 86
+#define WLC_GET_WAKE 87
+#define WLC_SET_WAKE 88
+#define WLC_GET_D11CNTS 89
+#define WLC_GET_FORCELINK 90 /* ndis only */
+#define WLC_SET_FORCELINK 91 /* ndis only */
+#define WLC_FREQ_ACCURACY 92
+#define WLC_CARRIER_SUPPRESS 93
+#define WLC_GET_PHYREG 94
+#define WLC_SET_PHYREG 95
+#define WLC_GET_RADIOREG 96
+#define WLC_SET_RADIOREG 97
+#define WLC_GET_REVINFO 98
+#define WLC_GET_UCANTDIV 99
+#define WLC_SET_UCANTDIV 100
+#define WLC_R_REG 101
+#define WLC_W_REG 102
+#define WLC_DIAG_LOOPBACK 103
+#define WLC_RESET_D11CNTS 104
+#define WLC_GET_MACMODE 105
+#define WLC_SET_MACMODE 106
+#define WLC_GET_MONITOR 107 /* added by nbd */
+#define WLC_SET_MONITOR 108 /* added by nbd */
+#define WLC_GET_GMODE 109
+#define WLC_SET_GMODE 110
+#define WLC_GET_LEGACY_ERP 111
+#define WLC_SET_LEGACY_ERP 112
+#define WLC_GET_RX_ANT 113
+#define WLC_GET_CURR_RATESET 114 /* current rateset */
+#define WLC_GET_SCANSUPPRESS 115
+#define WLC_SET_SCANSUPPRESS 116
+#define WLC_GET_AP 117
+#define WLC_SET_AP 118
+#define WLC_GET_EAP_RESTRICT 119
+#define WLC_SET_EAP_RESTRICT 120
+#define WLC_SCB_AUTHORIZE 121
+#define WLC_SCB_DEAUTHORIZE 122
+#define WLC_GET_WDSLIST 123
+#define WLC_SET_WDSLIST 124
+#define WLC_GET_ATIM 125
+#define WLC_SET_ATIM 126
+#define WLC_GET_RSSI 127
+#define WLC_GET_PHYANTDIV 128
+#define WLC_SET_PHYANTDIV 129
+#define WLC_AP_RX_ONLY 130
+#define WLC_GET_TX_PATH_PWR 131
+#define WLC_SET_TX_PATH_PWR 132
+#define WLC_GET_WSEC 133
+#define WLC_SET_WSEC 134
+#define WLC_GET_PHY_NOISE 135
+#define WLC_GET_BSS_INFO 136
+#define WLC_GET_PKTCNTS 137
+#define WLC_GET_LAZYWDS 138
+#define WLC_SET_LAZYWDS 139
+#define WLC_GET_BANDLIST 140
+#define WLC_GET_BAND 141
+#define WLC_SET_BAND 142
+#define WLC_SCB_DEAUTHENTICATE 143
+#define WLC_GET_SHORTSLOT 144
+#define WLC_GET_SHORTSLOT_OVERRIDE 145
+#define WLC_SET_SHORTSLOT_OVERRIDE 146
+#define WLC_GET_SHORTSLOT_RESTRICT 147
+#define WLC_SET_SHORTSLOT_RESTRICT 148
+#define WLC_GET_GMODE_PROTECTION 149
+#define WLC_GET_GMODE_PROTECTION_OVERRIDE 150
+#define WLC_SET_GMODE_PROTECTION_OVERRIDE 151
+#define WLC_UPGRADE 152
+#define WLC_GET_MRATE 153
+#define WLC_SET_MRATE 154
+#define WLC_GET_IGNORE_BCNS 155
+#define WLC_SET_IGNORE_BCNS 156
+#define WLC_GET_SCB_TIMEOUT 157
+#define WLC_SET_SCB_TIMEOUT 158
+#define WLC_GET_ASSOCLIST 159
+#define WLC_GET_CLK 160
+#define WLC_SET_CLK 161
+#define WLC_GET_UP 162
+#define WLC_OUT 163
+#define WLC_GET_WPA_AUTH 164
+#define WLC_SET_WPA_AUTH 165
+#define WLC_GET_UCFLAGS 166
+#define WLC_SET_UCFLAGS 167
+#define WLC_GET_PWRIDX 168
+#define WLC_SET_PWRIDX 169
+#define WLC_GET_TSSI 170
+#define WLC_GET_SUP_RATESET_OVERRIDE 171
+#define WLC_SET_SUP_RATESET_OVERRIDE 172
+#define WLC_SET_FAST_TIMER 173
+#define WLC_GET_FAST_TIMER 174
+#define WLC_SET_SLOW_TIMER 175
+#define WLC_GET_SLOW_TIMER 176
+#define WLC_DUMP_PHYREGS 177
+#define WLC_GET_GMODE_PROTECTION_CONTROL 178
+#define WLC_SET_GMODE_PROTECTION_CONTROL 179
+#define WLC_GET_PHYLIST 180
+#define WLC_ENCRYPT_STRENGTH 181 /* ndis only */
+#define WLC_DECRYPT_STATUS 182 /* ndis only */
+#define WLC_GET_KEY_SEQ 183
+#define WLC_GET_SCAN_CHANNEL_TIME 184
+#define WLC_SET_SCAN_CHANNEL_TIME 185
+#define WLC_GET_SCAN_UNASSOC_TIME 186
+#define WLC_SET_SCAN_UNASSOC_TIME 187
+#define WLC_GET_SCAN_HOME_TIME 188
+#define WLC_SET_SCAN_HOME_TIME 189
+#define WLC_GET_SCAN_PASSES 190
+#define WLC_SET_SCAN_PASSES 191
+#define WLC_GET_PRB_RESP_TIMEOUT 192
+#define WLC_SET_PRB_RESP_TIMEOUT 193
+#define WLC_GET_ATTEN 194
+#define WLC_SET_ATTEN 195
+#define WLC_GET_SHMEM 196 /* diag */
+#define WLC_SET_SHMEM 197 /* diag */
+#define WLC_GET_GMODE_PROTECTION_CTS 198
+#define WLC_SET_GMODE_PROTECTION_CTS 199
+#define WLC_SET_TKIP_MIC_FLAG 200
+#define WLC_SCB_DEAUTHENTICATE_FOR_REASON 201
+#define WLC_TKIP_COUNTERMEASURES 202
+#define WLC_GET_PIOMODE 203
+#define WLC_SET_PIOMODE 204
+#define WLC_SET_LED 209
+#define WLC_GET_LED 210
+#define WLC_GET_INTERFERENCE_MODE 211
+#define WLC_SET_INTERFERENCE_MODE 212
+#define WLC_GET_CHANNEL_QA 213
+#define WLC_START_CHANNEL_QA 214
+#define WLC_GET_CHANNEL_SEL 215
+#define WLC_START_CHANNEL_SEL 216
+#define WLC_GET_VALID_CHANNELS 217
+#define WLC_GET_FAKEFRAG 218
+#define WLC_SET_FAKEFRAG 219
+#define WLC_GET_PWROUT_PERCENTAGE 220
+#define WLC_SET_PWROUT_PERCENTAGE 221
+#define WLC_SET_BAD_FRAME_PREEMPT 222
+#define WLC_GET_BAD_FRAME_PREEMPT 223
+#define WLC_SET_LEAP_LIST 224
+#define WLC_GET_LEAP_LIST 225
+#define WLC_GET_CWMIN 226
+#define WLC_SET_CWMIN 227
+#define WLC_GET_CWMAX 228
+#define WLC_SET_CWMAX 229
+#define WLC_GET_WET 230
+#define WLC_SET_WET 231
+#define WLC_GET_KEY_PRIMARY 235
+#define WLC_SET_KEY_PRIMARY 236
+#define WLC_SCAN_WITH_CALLBACK 240
+#define WLC_WDS_GET_REMOTE_HWADDR 246 /* currently handled in wl_linux.c/wl_vx.c */
+#define WLC_SET_CS_SCAN_TIMER 248
+#define WLC_GET_CS_SCAN_TIMER 249
+#define WLC_CURRENT_PWR 256
+#define WLC_GET_CHANNELS_IN_COUNTRY 260
+#define WLC_GET_COUNTRY_LIST 261
+#define WLC_GET_VAR 262 /* get value of named variable */
+#define WLC_SET_VAR 263 /* set named variable to value */
+#define WLC_NVRAM_GET 264
+#define WLC_NVRAM_SET 265
+#define WLC_SET_WSEC_PMK 268
+#define WLC_GET_AUTH_MODE 269
+#define WLC_SET_AUTH_MODE 270
+#define WLC_LAST 273 /* do not change - use get_var/set_var */
+
+/*
+ * Minor kludge alert:
+ * Duplicate a few definitions that irelay requires from epiioctl.h here
+ * so caller doesn't have to include this file and epiioctl.h .
+ * If this grows any more, it would be time to move these irelay-specific
+ * definitions out of the epiioctl.h and into a separate driver common file.
+ */
+#ifndef EPICTRL_COOKIE
+#define EPICTRL_COOKIE 0xABADCEDE
+#endif
+
+/* vx wlc ioctl's offset */
+#define CMN_IOCTL_OFF 0x180
+
+/*
+ * custom OID support
+ *
+ * 0xFF - implementation specific OID
+ * 0xE4 - first byte of Broadcom PCI vendor ID
+ * 0x14 - second byte of Broadcom PCI vendor ID
+ * 0xXX - the custom OID number
+ */
+
+/* begin 0x1f values beyond the start of the ET driver range. */
+#define WL_OID_BASE 0xFFE41420
+
+/* NDIS overrides */
+#define OID_WL_GETINSTANCE (WL_OID_BASE + WLC_GET_INSTANCE)
+#define OID_WL_GET_FORCELINK (WL_OID_BASE + WLC_GET_FORCELINK)
+#define OID_WL_SET_FORCELINK (WL_OID_BASE + WLC_SET_FORCELINK)
+#define OID_WL_ENCRYPT_STRENGTH (WL_OID_BASE + WLC_ENCRYPT_STRENGTH)
+#define OID_WL_DECRYPT_STATUS (WL_OID_BASE + WLC_DECRYPT_STATUS)
+
+#define WL_DECRYPT_STATUS_SUCCESS 1
+#define WL_DECRYPT_STATUS_FAILURE 2
+#define WL_DECRYPT_STATUS_UNKNOWN 3
+
+/* allows user-mode app to poll the status of USB image upgrade */
+#define WLC_UPGRADE_SUCCESS 0
+#define WLC_UPGRADE_PENDING 1
+
+/* Bit masks for radio disabled status - returned by WL_GET_RADIO */
+#define WL_RADIO_SW_DISABLE (1<<0)
+#define WL_RADIO_HW_DISABLE (1<<1)
+
+/* Override bit for WLC_SET_TXPWR. if set, ignore other level limits */
+#define WL_TXPWR_OVERRIDE (1<<31)
+
+
+/* Bus types */
+#define WL_SB_BUS 0 /* Silicon Backplane */
+#define WL_PCI_BUS 1 /* PCI target */
+#define WL_PCMCIA_BUS 2 /* PCMCIA target */
+
+/* band types */
+#define WLC_BAND_AUTO 0 /* auto-select */
+#define WLC_BAND_A 1 /* "a" band (5 Ghz) */
+#define WLC_BAND_B 2 /* "b" band (2.4 Ghz) */
+
+/* MAC list modes */
+#define WLC_MACMODE_DISABLED 0 /* MAC list disabled */
+#define WLC_MACMODE_DENY 1 /* Deny specified (i.e. allow unspecified) */
+#define WLC_MACMODE_ALLOW 2 /* Allow specified (i.e. deny unspecified) */
+
+
+/* 54g modes (basic bits may still be overridden) */
+#define GMODE_LEGACY_B 0 /* Rateset: 1b, 2b, 5.5, 11 */
+ /* Preamble: Long */
+ /* Shortslot: Off */
+#define GMODE_AUTO 1 /* Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 */
+ /* Extended Rateset: 6, 9, 12, 48 */
+ /* Preamble: Long */
+ /* Shortslot: Auto */
+#define GMODE_ONLY 2 /* Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54 */
+ /* Extended Rateset: 6b, 9, 12b, 48 */
+ /* Preamble: Short required */
+ /* Shortslot: Auto */
+#define GMODE_B_DEFERRED 3 /* Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 */
+ /* Extended Rateset: 6, 9, 12, 48 */
+ /* Preamble: Long */
+ /* Shortslot: On */
+#define GMODE_PERFORMANCE 4 /* Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54 */
+ /* Preamble: Short required */
+ /* Shortslot: On and required */
+#define GMODE_LRS 5 /* Rateset: 1b, 2b, 5.5b, 11b */
+ /* Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54 */
+ /* Preamble: Long */
+ /* Shortslot: Auto */
+#define GMODE_MAX 6
+
+
+/* values for PLCPHdr_override */
+#define WLC_PLCP_AUTO -1
+#define WLC_PLCP_SHORT 0
+#define WLC_PLCP_LONG 1
+
+/* values for g_protection_override */
+#define WLC_G_PROTECTION_AUTO -1
+#define WLC_G_PROTECTION_OFF 0
+#define WLC_G_PROTECTION_ON 1
+
+/* values for g_protection_control */
+#define WLC_G_PROTECTION_CTL_OFF 0
+#define WLC_G_PROTECTION_CTL_LOCAL 1
+#define WLC_G_PROTECTION_CTL_OVERLAP 2
+
+/* Values for PM */
+#define PM_OFF 0
+#define PM_MAX 1
+#define PM_FAST 2
+
+/* interference mitigation options */
+#define INTERFERE_NONE 0 /* off */
+#define NON_WLAN 1 /* foreign/non 802.11 interference, no auto detect */
+#define WLAN_MANUAL 2 /* ACI: no auto detection */
+#define WLAN_AUTO 3 /* ACI: auto - detact */
+
+/* Message levels */
+#define WL_ERROR_VAL 0x0001
+#define WL_TRACE_VAL 0x0002
+#define WL_PRHDRS_VAL 0x0004
+#define WL_PRPKT_VAL 0x0008
+#define WL_INFORM_VAL 0x0010
+#define WL_TMP_VAL 0x0020
+#define WL_OID_VAL 0x0040
+#define WL_RATE_VAL 0x0080
+#define WL_ASSOC_VAL 0x0100
+#define WL_PRUSR_VAL 0x0200
+#define WL_PS_VAL 0x0400
+#define WL_TXPWR_VAL 0x0800
+#define WL_GMODE_VAL 0x1000
+#define WL_DUAL_VAL 0x2000
+#define WL_WSEC_VAL 0x4000
+#define WL_WSEC_DUMP_VAL 0x8000
+#define WL_LOG_VAL 0x10000
+#define WL_NRSSI_VAL 0x20000
+#define WL_LOFT_VAL 0x40000
+#define WL_REGULATORY_VAL 0x80000
+#define WL_ACI_VAL 0x100000
+
+
+/* 802.11h enforcement levels */
+#define SPECT_MNGMT_OFF 0 /* 11h disabled */
+#define SPECT_MNGMT_LOOSE 1 /* Allow scan lists to contain non-11h AP */
+ /* when 11h is enabled */
+#define SPECT_MNGMT_STRICT 2 /* Prine out non-11h APs from scan list */
+
+
+
+/* max # of leds supported by GPIO (gpio pin# == led index#) */
+#define WL_LED_NUMGPIO 16 /* gpio 0-15 */
+
+/* led per-pin behaviors */
+#define WL_LED_OFF 0 /* always off */
+#define WL_LED_ON 1 /* always on */
+#define WL_LED_ACTIVITY 2 /* activity */
+#define WL_LED_RADIO 3 /* radio enabled */
+#define WL_LED_ARADIO 4 /* 5 Ghz radio enabled */
+#define WL_LED_BRADIO 5 /* 2.4Ghz radio enabled */
+#define WL_LED_BGMODE 6 /* on if gmode, off if bmode */
+#define WL_LED_WI1 7
+#define WL_LED_WI2 8
+#define WL_LED_WI3 9
+#define WL_LED_ASSOC 10 /* associated state indicator */
+#define WL_LED_INACTIVE 11 /* null behavior (clears default behavior) */
+#define WL_LED_NUMBEHAVIOR 12
+
+/* led behavior numeric value format */
+#define WL_LED_BEH_MASK 0x7f /* behavior mask */
+#define WL_LED_AL_MASK 0x80 /* activelow (polarity) bit */
+
+
+/* maximum channels */
+#define WL_NUMCHANNELS 64 /* max # of channels in the band */
+
+/* rate check */
+#define WL_RATE_OFDM(r) (((r) & 0x7f) == 12 || ((r) & 0x7f) == 18 || \
+ ((r) & 0x7f) == 24 || ((r) & 0x7f) == 36 || \
+ ((r) & 0x7f) == 48 || ((r) & 0x7f) == 72 || \
+ ((r) & 0x7f) == 96 || ((r) & 0x7f) == 108)
+
+/* WDS link local endpoint WPA role */
+#define WL_WDS_WPA_ROLE_AUTH 0 /* authenticator */
+#define WL_WDS_WPA_ROLE_SUP 1 /* supplicant */
+#define WL_WDS_WPA_ROLE_AUTO 255 /* auto, based on mac addr value */
+
+/* afterburner_override */
+#define ABO_AUTO -1 /* auto - no override */
+#define ABO_OFF 0 /* force afterburner off */
+#define ABO_ON 1 /* force afterburner on */
+
+#define GMODE_AFTERBURNER 6
+
+#undef PACKED
+
+#endif /* _wlioctl_h_ */
diff --git a/package/nvram/src/include/wlutils.h b/package/nvram/src/include/wlutils.h
new file mode 100644
index 0000000000..07e2536ca3
--- /dev/null
+++ b/package/nvram/src/include/wlutils.h
@@ -0,0 +1,59 @@
+/*
+ * Broadcom wireless network adapter utility functions
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#ifndef _wlutils_h_
+#define _wlutils_h_
+
+#include <typedefs.h>
+#include <wlioctl.h>
+
+/*
+ * Pass a wlioctl request to the specified interface.
+ * @param name interface name
+ * @param cmd WLC_GET_MAGIC <= cmd < WLC_LAST
+ * @param buf buffer for passing in and/or receiving data
+ * @param len length of buf
+ * @return >= 0 if successful or < 0 otherwise
+ */
+extern int wl_ioctl(char *name, int cmd, void *buf, int len);
+
+/*
+ * Get the MAC (hardware) address of the specified interface.
+ * @param name interface name
+ * @param hwaddr 6-byte buffer for receiving address
+ * @return >= 0 if successful or < 0 otherwise
+ */
+extern int wl_hwaddr(char *name, unsigned char *hwaddr);
+
+/*
+ * Probe the specified interface.
+ * @param name interface name
+ * @return >= 0 if a Broadcom wireless device or < 0 otherwise
+ */
+extern int wl_probe(char *name);
+
+/*
+ * Set/Get named variable.
+ * @param name interface name
+ * @param var variable name
+ * @param val variable value/buffer
+ * @param len variable value/buffer length
+ * @return success == 0, failure != 0
+ */
+extern int wl_set_val(char *name, char *var, void *val, int len);
+extern int wl_get_val(char *name, char *var, void *val, int len);
+extern int wl_set_int(char *name, char *var, int val);
+extern int wl_get_int(char *name, char *var, int *val);
+
+#endif /* _wlutils_h_ */
diff --git a/package/nvram/src/linux_timer.c b/package/nvram/src/linux_timer.c
new file mode 100644
index 0000000000..0402e44378
--- /dev/null
+++ b/package/nvram/src/linux_timer.c
@@ -0,0 +1,738 @@
+/*
+ * 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.
+ *
+ * Low resolution timer interface linux specific implementation.
+ *
+ * $Id$
+ */
+
+/*
+* debug facilities
+*/
+#define TIMER_DEBUG 0
+#if TIMER_DEBUG
+#define TIMERDBG(fmt, args...) printf("%s: " fmt "\n" , __FUNCTION__ , ## args)
+#else
+#define TIMERDBG(fmt, args...)
+#endif
+
+
+/*
+ * POSIX timer support for Linux. Taken from linux_timer.c in upnp
+ */
+
+#define __USE_GNU
+
+
+#include <stdlib.h> // for malloc, free, etc.
+#include <string.h> // for memset, strncasecmp, etc.
+#include <assert.h> // for assert, of course.
+#include <signal.h> // for sigemptyset, etc.
+#include <stdio.h> // for printf, etc.
+#include <sys/time.h>
+#include <time.h>
+
+/* define TIMER_PROFILE to enable code which guages how accurate the timer functions are.
+ For each expiring timer the code will print the expected time interval and the actual time interval.
+#define TIMER_PROFILE
+*/
+#undef TIMER_PROFILE
+
+/*
+timer_cancel( ) - cancel a timer
+timer_connect( ) - connect a user routine to the timer signal
+timer_create( ) - allocate a timer using the specified clock for a timing base (POSIX)
+timer_delete( ) - remove a previously created timer (POSIX)
+timer_gettime( ) - get the remaining time before expiration and the reload value (POSIX)
+timer_getoverrun( ) - return the timer expiration overrun (POSIX)
+timer_settime( ) - set the time until the next expiration and arm timer (POSIX)
+nanosleep( ) - suspend the current task until the time interval elapses (POSIX)
+*/
+
+#define MS_PER_SEC 1000
+#define US_PER_SEC 1000000
+#define US_PER_MS 1000
+#define UCLOCKS_PER_SEC 1000000
+
+typedef void (*event_callback_t)(timer_t, int);
+
+#ifndef TIMESPEC_TO_TIMEVAL
+# define TIMESPEC_TO_TIMEVAL(tv, ts) { \
+ (tv)->tv_sec = (ts)->tv_sec; \
+ (tv)->tv_usec = (ts)->tv_nsec / 1000; \
+}
+#endif
+
+#ifndef TIMEVAL_TO_TIMESPEC
+# define TIMEVAL_TO_TIMESPEC(tv, ts) { \
+ (ts)->tv_sec = (tv)->tv_sec; \
+ (ts)->tv_nsec = (tv)->tv_usec * 1000; \
+}
+#endif
+
+#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y))
+
+#define timerroundup(t,g) \
+ do { \
+ if (!timerisset(t)) (t)->tv_usec=1; \
+ if ((t)->tv_sec == 0) (t)->tv_usec=ROUNDUP((t)->tv_usec, g); \
+ } while (0)
+
+typedef long uclock_t;
+
+#define TFLAG_NONE 0
+#define TFLAG_CANCELLED (1<<0)
+#define TFLAG_DELETED (1<<1)
+
+struct event {
+ struct timeval it_interval;
+ struct timeval it_value;
+ event_callback_t func;
+ int arg;
+ unsigned short flags;
+ struct event *next;
+#ifdef TIMER_PROFILE
+ uint expected_ms;
+ uclock_t start;
+#endif
+};
+
+void timer_cancel(timer_t timerid);
+
+static void alarm_handler(int i);
+static void check_event_queue();
+static void print_event_queue();
+static void check_timer();
+#if THIS_FINDS_USE
+static int count_queue(struct event *);
+#endif
+static int timer_change_settime(timer_t timer_id, const struct itimerspec *timer_spec);
+void block_timer();
+void unblock_timer();
+
+static struct event *event_queue = NULL;
+static struct event *event_freelist;
+static uint g_granularity;
+static int g_maxevents = 0;
+
+uclock_t uclock()
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ return ((tv.tv_sec * US_PER_SEC) + tv.tv_usec);
+}
+
+
+void init_event_queue(int n)
+{
+ int i;
+ struct itimerval tv;
+
+ g_maxevents = n;
+ event_freelist = (struct event *) malloc(n * sizeof(struct event));
+ memset(event_freelist, 0, n * sizeof(struct event));
+
+ for (i = 0; i < (n-1); i++)
+ event_freelist[i].next = &event_freelist[i+1];
+
+ event_freelist[i].next = NULL;
+
+ tv.it_interval.tv_sec = 0;
+ tv.it_interval.tv_usec = 1;
+ tv.it_value.tv_sec = 0;
+ tv.it_value.tv_usec = 0;
+ setitimer (ITIMER_REAL, &tv, 0);
+ setitimer (ITIMER_REAL, 0, &tv);
+ g_granularity = tv.it_interval.tv_usec;
+
+ signal(SIGALRM, alarm_handler);
+}
+
+
+int clock_gettime(
+ clockid_t clock_id, /* clock ID (always CLOCK_REALTIME) */
+ struct timespec * tp /* where to store current time */
+)
+{
+ struct timeval tv;
+ int n;
+
+
+ n = gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, tp);
+
+ return n;
+}
+
+
+int timer_create(
+ clockid_t clock_id, /* clock ID (always CLOCK_REALTIME) */
+ struct sigevent * evp, /* user event handler */
+ timer_t * pTimer /* ptr to return value */
+)
+{
+ struct event *event;
+
+ if (clock_id != CLOCK_REALTIME) {
+ TIMERDBG("timer_create can only support clock id CLOCK_REALTIME");
+ exit(1);
+ }
+
+ if (evp != NULL) {
+ if (evp->sigev_notify != SIGEV_SIGNAL || evp->sigev_signo != SIGALRM) {
+ TIMERDBG("timer_create can only support signalled alarms using SIGALRM");
+ exit(1);
+ }
+ }
+
+ event = event_freelist;
+ if (event == NULL) {
+ print_event_queue();
+ }
+ assert(event != NULL);
+
+ event->flags = TFLAG_NONE;
+
+ event_freelist = event->next;
+ event->next = NULL;
+
+ check_event_queue();
+
+ *pTimer = (timer_t) event;
+
+ return 0;
+}
+
+int timer_delete(
+ timer_t timerid /* timer ID */
+)
+{
+ struct event *event = (struct event *) timerid;
+
+ if (event->flags & TFLAG_DELETED) {
+ TIMERDBG("Cannot delete a deleted event");
+ return 1;
+ }
+
+ timer_cancel(timerid);
+
+ event->flags |= TFLAG_DELETED;
+
+ event->next = event_freelist;
+ event_freelist = event;
+
+ return 0;
+}
+
+int timer_connect
+(
+ timer_t timerid, /* timer ID */
+ void (*routine)(timer_t, int), /* user routine */
+ int arg /* user argument */
+)
+{
+ struct event *event = (struct event *) timerid;
+
+ assert(routine != NULL);
+ event->func = routine;
+ event->arg = arg;
+
+ return 0;
+}
+
+/*
+ * Please Call this function only from the call back functions of the alarm_handler.
+ * This is just a hack
+*/
+int timer_change_settime
+(
+ timer_t timerid, /* timer ID */
+ const struct itimerspec * value /* time to be set */
+)
+{
+ struct event *event = (struct event *) timerid;
+
+ TIMESPEC_TO_TIMEVAL(&event->it_interval, &value->it_interval);
+ TIMESPEC_TO_TIMEVAL(&event->it_value, &value->it_value);
+
+ return 1;
+}
+
+int timer_settime
+(
+ timer_t timerid, /* timer ID */
+ int flags, /* absolute or relative */
+ const struct itimerspec * value, /* time to be set */
+ struct itimerspec * ovalue /* previous time set (NULL=no result) */
+)
+{
+ struct itimerval itimer;
+ struct event *event = (struct event *) timerid;
+ struct event **ppevent;
+
+ TIMESPEC_TO_TIMEVAL(&event->it_interval, &value->it_interval);
+ TIMESPEC_TO_TIMEVAL(&event->it_value, &value->it_value);
+
+ /* if .it_value is zero, the timer is disarmed */
+ if (!timerisset(&event->it_value)) {
+ timer_cancel(timerid);
+ return 0;
+ }
+
+ block_timer();
+
+#ifdef TIMER_PROFILE
+ event->expected_ms = (event->it_value.tv_sec * MS_PER_SEC) + (event->it_value.tv_usec / US_PER_MS);
+ event->start = uclock();
+#endif
+ if (event->next) {
+ TIMERDBG("calling timer_settime with a timer that is already on the queue.");
+ }
+
+
+ /* We always want to make sure that the event at the head of the
+ queue has a timeout greater than the itimer granularity.
+ Otherwise we end up with the situation that the time remaining
+ on an itimer is greater than the time at the head of the queue
+ in the first place. */
+ timerroundup(&event->it_value, g_granularity);
+
+ timerclear(&itimer.it_value);
+ getitimer(ITIMER_REAL, &itimer);
+ if (timerisset(&itimer.it_value)) {
+ // reset the top timer to have an interval equal to the remaining interval
+ // when the timer was cancelled.
+ if (event_queue) {
+ if (timercmp(&(itimer.it_value), &(event_queue->it_value), >)) {
+ // it is an error if the amount of time remaining is more than the amount of time
+ // requested by the top event.
+ //
+ TIMERDBG("timer_settime: TIMER ERROR!");
+
+ } else {
+ // some portion of the top event has already expired.
+ // Reset the interval of the top event to remaining
+ // time left in that interval.
+ //
+ event_queue->it_value = itimer.it_value;
+
+ // if we were the earliest timer before now, we are still the earliest timer now.
+ // we do not need to reorder the list.
+ }
+ }
+ }
+
+ // Now, march down the list, decrementing the new timer by the
+ // current it_value of each event on the queue.
+ ppevent = &event_queue;
+ while (*ppevent) {
+ if ( timercmp(&(event->it_value), &((*ppevent)->it_value), <) ) {
+ // if the proposed event will trigger sooner than the next event
+ // in the queue, we will insert the new event just before the next one.
+ //
+ // we also need to adjust the delta value to the next event.
+ timersub(&((*ppevent)->it_value), &(event->it_value), &((*ppevent)->it_value));
+ break;
+ }
+ // subtract the interval of the next event from the proposed interval.
+ timersub(&(event->it_value), &((*ppevent)->it_value), &(event->it_value));
+
+ ppevent = &((*ppevent)->next);
+ }
+
+ // we have found our proper place in the queue,
+ // link our new event into the pending event queue.
+ event->next = *ppevent;
+ *ppevent = event;
+
+ check_event_queue();
+
+ // if our new event ended up at the front of the queue, reissue the timer.
+ if (event == event_queue) {
+ timerroundup(&event_queue->it_value, g_granularity);
+ timerclear(&itimer.it_interval);
+ itimer.it_value = event_queue->it_value;
+
+ // we want to be sure to never turn off the timer completely,
+ // so if the next interval is zero, set it to some small value.
+ if (!timerisset(&(itimer.it_value)))
+ itimer.it_value = (struct timeval) { 0, 1 };
+
+ assert(!timerisset(&itimer.it_interval));
+ assert(itimer.it_value.tv_sec > 0 || itimer.it_value.tv_usec >= g_granularity);
+ assert(event_queue->it_value.tv_sec > 0 || event_queue->it_value.tv_usec >= g_granularity);
+ setitimer(ITIMER_REAL, &itimer, NULL);
+ check_timer();
+ }
+
+ event->flags &= ~TFLAG_CANCELLED;
+
+ unblock_timer();
+
+ return 0;
+}
+
+static void check_timer()
+{
+ struct itimerval itimer;
+
+ getitimer(ITIMER_REAL, &itimer);
+ if (timerisset(&itimer.it_interval)) {
+ TIMERDBG("ERROR timer interval is set.");
+ }
+ if (timercmp(&(itimer.it_value), &(event_queue->it_value), >)) {
+ TIMERDBG("ERROR timer expires later than top event.");
+ }
+}
+
+
+static void check_event_queue()
+{
+ struct timeval sum;
+ struct event *event;
+ int i = 0;
+
+#ifdef notdef
+ int nfree = 0;
+ struct event *p;
+ for (p = event_freelist; p; p = p->next)
+ nfree++;
+ printf("%d free events\n", nfree);
+#endif
+
+ timerclear(&sum);
+ for (event = event_queue; event; event = event->next) {
+ if (i > g_maxevents) {
+ TIMERDBG("timer queue looks like it loops back on itself!");
+ print_event_queue();
+ exit(1);
+ }
+ i++;
+ }
+}
+
+#if THIS_FINDS_USE
+/* The original upnp version has this unused function, so I left it in
+ to maintain the resemblance. */
+static int count_queue(struct event *event_queue)
+{
+ struct event *event;
+ int i = 0;
+ for (event = event_queue; event; event = event->next)
+ i++;
+ return i;
+}
+#endif
+
+static void print_event_queue()
+{
+ struct event *event;
+ int i = 0;
+
+ for (event = event_queue; event; event = event->next) {
+ printf("#%d (0x%x)->0x%x: \t%d sec %d usec\t%p\n",
+ i++, (unsigned int) event, (unsigned int) event->next, (int) event->it_value.tv_sec, (int) event->it_value.tv_usec, event->func);
+ if (i > g_maxevents) {
+ printf("...(giving up)\n");
+ break;
+ }
+ }
+}
+
+// The top element of the event queue must have expired.
+// Remove that element, run its function, and reset the timer.
+// if there is no interval, recycle the event structure.
+static void alarm_handler(int i)
+{
+ struct event *event, **ppevent;
+ struct itimerval itimer;
+ struct timeval small_interval = { 0, g_granularity/2 };
+#ifdef TIMER_PROFILE
+ uint junk;
+ uclock_t end;
+ uint actual;
+#endif
+
+ block_timer();
+
+ // Loop through the event queue and remove the first event plus any
+ // subsequent events that will expire very soon thereafter (within 'small_interval'}.
+ //
+ do {
+ // remove the top event.
+ event = event_queue;
+ event_queue = event_queue->next;
+ event->next = NULL;
+
+#ifdef TIMER_PROFILE
+ end = uclock();
+ actual = ((end-event->start)/((uclock_t)UCLOCKS_PER_SEC/1000));
+ if (actual < 0)
+ junk = end;
+ TIMERDBG("expected %d ms actual %d ms", event->expected_ms, ((end-event->start)/((uclock_t)UCLOCKS_PER_SEC/1000)));
+#endif
+
+ // call the event callback function
+ (*(event->func))((timer_t) event, (int)event->arg);
+
+ /* If the event has been cancelled, do NOT put it back on the queue. */
+ if ( !(event->flags & TFLAG_CANCELLED) ) {
+
+ // if the event is a recurring event, reset the timer and
+ // find its correct place in the sorted list of events.
+ //
+ if (timerisset(&event->it_interval)) {
+ // event is recurring...
+ //
+ event->it_value = event->it_interval;
+#ifdef TIMER_PROFILE
+ event->expected_ms = (event->it_value.tv_sec * MS_PER_SEC) + (event->it_value.tv_usec / US_PER_MS);
+ event->start = uclock();
+#endif
+ timerroundup(&event->it_value, g_granularity);
+
+ // Now, march down the list, decrementing the new timer by the
+ // current delta of each event on the queue.
+ ppevent = &event_queue;
+ while (*ppevent) {
+ if ( timercmp(&(event->it_value), &((*ppevent)->it_value), <) ) {
+ // if the proposed event will trigger sooner than the next event
+ // in the queue, we will insert the new event just before the next one.
+ //
+ // we also need to adjust the delta value to the next event.
+ timersub(&((*ppevent)->it_value), &(event->it_value), &((*ppevent)->it_value));
+ break;
+ }
+ timersub(&(event->it_value), &((*ppevent)->it_value), &(event->it_value));
+ ppevent = &((*ppevent)->next);
+ }
+
+ // we have found our proper place in the queue,
+ // link our new event into the pending event queue.
+ event->next = *ppevent;
+ *ppevent = event;
+ } else {
+ // there is no interval, so recycle the event structure.
+ //timer_delete((timer_t) event);
+ }
+ }
+
+ check_event_queue();
+
+ } while (event_queue && timercmp(&event_queue->it_value, &small_interval, <));
+
+ // re-issue the timer...
+ if (event_queue) {
+ timerroundup(&event_queue->it_value, g_granularity);
+
+ timerclear(&itimer.it_interval);
+ itimer.it_value = event_queue->it_value;
+ // we want to be sure to never turn off the timer completely,
+ // so if the next interval is zero, set it to some small value.
+ if (!timerisset(&(itimer.it_value)))
+ itimer.it_value = (struct timeval) { 0, 1 };
+
+ setitimer(ITIMER_REAL, &itimer, NULL);
+ check_timer();
+ } else {
+ TIMERDBG("There are no events in the queue - timer not reset.");
+ }
+
+ unblock_timer();
+}
+
+static int block_count = 0;
+
+void block_timer()
+{
+ sigset_t set;
+
+ if (block_count++ == 0) {
+ sigemptyset(&set);
+ sigaddset(&set, SIGALRM);
+ sigprocmask(SIG_BLOCK, &set, NULL);
+ }
+}
+
+void unblock_timer()
+{
+ sigset_t set;
+
+ if (--block_count == 0) {
+ sigemptyset(&set);
+ sigaddset(&set, SIGALRM);
+ sigprocmask(SIG_UNBLOCK, &set, NULL);
+ }
+}
+
+void timer_cancel_all()
+{
+ struct itimerval timeroff = { { 0, 0 }, { 0, 0} };
+ struct event *event;
+ struct event **ppevent;
+
+ setitimer(ITIMER_REAL, &timeroff, NULL);
+
+ ppevent = &event_queue;
+ while (*ppevent) {
+ event = *ppevent;
+ *ppevent = event->next;
+ event->next = NULL;
+ }
+}
+
+
+
+void timer_cancel(timer_t timerid)
+{
+ struct itimerval itimer;
+ struct itimerval timeroff = { { 0, 0 }, { 0, 0} };
+ struct event *event = (struct event *) timerid;
+ struct event **ppevent;
+
+ if (event->flags & TFLAG_CANCELLED) {
+ TIMERDBG("Cannot cancel a cancelled event");
+ return;
+ }
+
+ block_timer();
+
+ ppevent = &event_queue;
+ while (*ppevent) {
+ if ( *ppevent == event ) {
+
+ /* RACE CONDITION - if the alarm goes off while we are in
+ this loop, and if the timer we want to cancel is the
+ next to expire, the alarm will end up firing
+ after this routine is complete, causing it to go off early. */
+
+ /* If the cancelled timer is the next to expire,
+ we need to do something special to clean up correctly. */
+ if (event == event_queue && event->next != NULL) {
+ timerclear(&itimer.it_value);
+ getitimer(ITIMER_REAL, &itimer);
+
+ /* subtract the time that has already passed while waiting for this timer... */
+ timersub(&(event->it_value), &(itimer.it_value), &(event->it_value));
+
+ /* and add any remainder to the next timer in the list */
+ timeradd(&(event->next->it_value), &(event->it_value), &(event->next->it_value));
+ }
+
+ *ppevent = event->next;
+ event->next = NULL;
+
+ if (event_queue) {
+ timerroundup(&event_queue->it_value, g_granularity);
+ timerclear(&itimer.it_interval);
+ itimer.it_value = event_queue->it_value;
+
+ /* We want to be sure to never turn off the timer
+ completely if there are more events on the queue,
+ so if the next interval is zero, set it to some
+ small value. */
+
+ if (!timerisset(&(itimer.it_value)))
+ itimer.it_value = (struct timeval) { 0, 1 };
+
+ assert(itimer.it_value.tv_sec > 0 || itimer.it_value.tv_usec >= g_granularity);
+ assert(event_queue->it_value.tv_sec > 0 || event_queue->it_value.tv_usec >= g_granularity);
+ setitimer(ITIMER_REAL, &itimer, NULL);
+ check_timer();
+ } else {
+ setitimer(ITIMER_REAL, &timeroff, NULL);
+ }
+ break;
+ }
+ ppevent = &((*ppevent)->next);
+ }
+
+ event->flags |= TFLAG_CANCELLED;
+
+ unblock_timer();
+}
+
+/*
+* timer related headers
+*/
+#include "bcmtimer.h"
+
+/*
+* locally used global variables and constants
+*/
+
+/*
+* Initialize internal resources used in the timer module. It must be called
+* before any other timer function calls. The param 'timer_entries' is used
+* to pre-allocate fixed number of timer entries.
+*/
+int bcm_timer_module_init(int timer_entries, bcm_timer_module_id *module_id)
+{
+ init_event_queue(timer_entries);
+ *module_id = (bcm_timer_module_id)event_freelist;
+ return 0;
+}
+
+/*
+* Cleanup internal resources used by this timer module. It deletes all
+* pending timer entries from the backend timer system as well.
+*/
+int bcm_timer_module_cleanup(bcm_timer_module_id module_id)
+{
+ module_id = 0;
+ return 0;
+}
+
+/* Enable/Disable timer module */
+int bcm_timer_module_enable(bcm_timer_module_id module_id, int enable)
+{
+ if (enable)
+ unblock_timer();
+ else
+ block_timer();
+ return 0;
+}
+
+int bcm_timer_create(bcm_timer_module_id module_id, bcm_timer_id *timer_id)
+{
+ module_id = 0;
+ return timer_create(CLOCK_REALTIME, NULL, (timer_t *)timer_id);
+}
+
+int bcm_timer_delete(bcm_timer_id timer_id)
+{
+ return timer_delete((timer_t)timer_id);
+}
+
+int bcm_timer_gettime(bcm_timer_id timer_id, struct itimerspec *timer_spec)
+{
+ return -1;
+}
+
+int bcm_timer_settime(bcm_timer_id timer_id, const struct itimerspec *timer_spec)
+{
+ return timer_settime((timer_t)timer_id, 0, timer_spec, NULL);
+}
+
+int bcm_timer_connect(bcm_timer_id timer_id, bcm_timer_cb func, int data)
+{
+ return timer_connect((timer_t)timer_id, (void *)func, data);
+}
+
+int bcm_timer_cancel(bcm_timer_id timer_id)
+{
+ timer_cancel((timer_t)timer_id);
+ return 0;
+}
+int bcm_timer_change_expirytime(bcm_timer_id timer_id, const struct itimerspec *timer_spec)
+{
+ timer_change_settime((timer_t)timer_id, timer_spec);
+ return 1;
+}
diff --git a/package/nvram/src/main.c b/package/nvram/src/main.c
new file mode 100644
index 0000000000..7af26729d9
--- /dev/null
+++ b/package/nvram/src/main.c
@@ -0,0 +1,88 @@
+/*
+ * Frontend command-line utility for Linux NVRAM layer
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <typedefs.h>
+#include <bcmnvram.h>
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: nvram [get name] [set name=value] [unset name] [show]\n");
+ exit(0);
+}
+
+/* hack for some PMON default nvram values which have '\r' appended */
+void
+puts_trim_cr(char *str)
+{
+ int len= strlen(str);
+ if (len && (str[len-1] == '\r')) len--;
+ printf("%.*s\n", len, str);
+}
+
+/* NVRAM utility */
+int
+main(int argc, char **argv)
+{
+ char *name, *value, buf[NVRAM_SPACE];
+ int size;
+
+ /* Skip program name */
+ --argc;
+ ++argv;
+
+ if (!*argv)
+ usage();
+
+ /* Process the remaining arguments. */
+ for (; *argv; argv++) {
+ if (!strncmp(*argv, "get", 3)) {
+ if (*++argv) {
+ if ((value = nvram_get(*argv))) {
+ puts_trim_cr(value);
+ }
+ }
+ }
+ else if (!strncmp(*argv, "set", 3)) {
+ if (*++argv) {
+ strncpy(value = buf, *argv, sizeof(buf));
+ name = strsep(&value, "=");
+ nvram_set(name, value);
+ }
+ }
+ else if (!strncmp(*argv, "unset", 5)) {
+ if (*++argv)
+ nvram_unset(*argv);
+ }
+ else if (!strncmp(*argv, "commit", 5)) {
+ nvram_commit();
+ }
+ else if (!strncmp(*argv, "show", 4) ||
+ !strncmp(*argv, "getall", 6)) {
+ nvram_getall(buf, sizeof(buf));
+ for (name = buf; *name; name += strlen(name) + 1)
+ puts_trim_cr(name);
+ size = sizeof(struct nvram_header) + (int) name - (int) buf;
+ fprintf(stderr, "size: %d bytes (%d left)\n", size, NVRAM_SPACE - size);
+ }
+ if (!*argv)
+ break;
+ }
+
+ return 0;
+}
diff --git a/package/nvram/src/nvram_convert.c b/package/nvram/src/nvram_convert.c
new file mode 100644
index 0000000000..485909026c
--- /dev/null
+++ b/package/nvram/src/nvram_convert.c
@@ -0,0 +1,77 @@
+
+#define WL(a) "wl_"a
+#define WL0(a) "wl0_"a
+#define D11G(a) "d11g_"a
+
+#define PPP(a) "ppp_"a
+#define PPPOE(a) "pppoe_"a
+
+struct nvram_convert {
+ char *name; // for WEB
+ char *wl0_name; // for driver
+ char *d11g_name; // for old nv name
+};
+
+struct nvram_convert nvram_converts[] = {
+ // Bellow change from 3.11.48.7
+ { WL("ssid"), WL0("ssid"), ""},
+ { WL("radio"), WL0("mode"), ""},
+ { WL("mode"), WL0("mode"), ""},
+ { WL("wds"), WL0("wds"), ""},
+ { WL("auth"), WL0("auth"), ""},
+ { WL("key"), WL0("key"), ""},
+ { WL("key1"), WL0("key1"), ""},
+ { WL("key2"), WL0("key2"), ""},
+ { WL("key3"), WL0("key3"), ""},
+ { WL("key4"), WL0("key4"), ""},
+ { WL("maclist"), WL0("maclist"), ""},
+ { WL("channel"), WL0("channel"), D11G("channel")},
+ { WL("rateset"), WL0("rateset"), D11G("rateset")},
+ { WL("rts"), WL0("rts"), D11G("rts")},
+ { WL("bcn"), WL0("bcn"), D11G("bcn")},
+ { WL("gmode"), WL0("gmode"), "d11g_mode"},
+ { WL("unit"), WL0("unit"), ""},
+ { WL("ifname"), WL0("ifname"), ""},
+ { WL("phytype"), WL0("phytype"), ""},
+ { WL("country"), WL0("country"), ""},
+ { WL("closed"), WL0("closed"), ""},
+ { WL("lazywds"), WL0("lazywds"), ""},
+ { WL("wep"), WL0("wep"), ""},
+ { WL("macmode"), WL0("macmode"), ""},
+ { WL("rate"), WL0("rate"), D11G("rate")},
+ { WL("frag"), WL0("frag"), D11G("frag")},
+ { WL("dtim"), WL0("dtim"), D11G("dtim")},
+ { WL("plcphdr"), WL0("plcphdr"), ""},
+ { WL("gmode_protection"), WL0("gmode_protection"), ""},
+ { WL("radio"), WL0("radio"), ""},
+ // Bellow change from 3.21.9.0
+ { WL("auth_mode"), WL0("auth_mode"), ""},
+ { WL("radius_ipaddr"), WL0("radius_ipaddr"), ""},
+ { WL("radius_port"), WL0("radius_port"), ""},
+ { WL("radius_key"), WL0("radius_key"), ""},
+ { WL("wpa_psk"), WL0("wpa_psk"), ""},
+ { WL("wpa_gtk_rekey"), WL0("wpa_gtk_rekey"), ""},
+ { WL("frameburst"), WL0("frameburst"), ""},
+ { WL("crypto"), WL0("crypto"), ""},
+ { WL("ap_isolate"), WL0("ap_isolate"), ""},
+ { WL("afterburner"), WL0("afterburner"), ""},
+ // for PPPoE
+ { PPP("username"), PPPOE("username"), ""},
+ { PPP("passwd"), PPPOE("passwd"), ""},
+ { PPP("idletime"), PPPOE("idletime"), ""},
+ { PPP("keepalive"), PPPOE("keepalive"), ""},
+ { PPP("demand"), PPPOE("demand"), ""},
+ { PPP("service"), PPPOE("service"), ""},
+ { PPP("ac"), PPPOE("ac"), ""},
+ { PPP("static"), PPPOE("static"), ""},
+ { PPP("static_ip"), PPPOE("static_ip"), ""},
+ { PPP("username_1"), PPPOE("username_1"), ""},
+ { PPP("passwd_1"), PPPOE("passwd_1"), ""},
+ { PPP("idletime_1"), PPPOE("idletime_1"), ""},
+ { PPP("keepalive_1"), PPPOE("keepalive_1"), ""},
+ { PPP("demand_1"), PPPOE("demand_1"), ""},
+ { PPP("service_1"), PPPOE("service_1"), ""},
+ { PPP("ac_1"), PPPOE("ac_1"), ""},
+
+ { 0, 0, 0},
+};
diff --git a/package/nvram/src/nvram_convert.h b/package/nvram/src/nvram_convert.h
new file mode 100644
index 0000000000..70e12327d1
--- /dev/null
+++ b/package/nvram/src/nvram_convert.h
@@ -0,0 +1,7 @@
+
+struct nvram_convert {
+ char *name;
+ char *wl0_name;
+ char *d11g_name;
+};
+
diff --git a/package/nvram/src/nvram_linux.c b/package/nvram/src/nvram_linux.c
new file mode 100644
index 0000000000..c41e32118a
--- /dev/null
+++ b/package/nvram/src/nvram_linux.c
@@ -0,0 +1,320 @@
+/*
+ * NVRAM variable manipulation (Linux user mode half)
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <error.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include <typedefs.h>
+#include <bcmnvram.h>
+#include <nvram_convert.h>
+#include <shutils.h>
+#include <utils.h>
+
+#define PATH_DEV_NVRAM "/dev/nvram"
+
+/* Globals */
+static int nvram_fd = -1;
+static char *nvram_buf = NULL;
+int check_action(void);
+int file_to_buf(char *path, char *buf, int len);
+
+int
+nvram_init(void *unused)
+{
+ if ((nvram_fd = open(PATH_DEV_NVRAM, O_RDWR)) < 0)
+ goto err;
+
+ /* Map kernel string buffer into user space */
+ if ((nvram_buf = mmap(NULL, NVRAM_SPACE, PROT_READ, MAP_SHARED, nvram_fd, 0)) == MAP_FAILED) {
+ close(nvram_fd);
+ nvram_fd = -1;
+ goto err;
+ }
+
+ return 0;
+
+ err:
+ perror(PATH_DEV_NVRAM);
+ return errno;
+}
+
+char *
+nvram_get(const char *name)
+{
+ size_t count = strlen(name) + 1;
+ char tmp[100], *value;
+ unsigned long *off = (unsigned long *) tmp;
+
+ if (nvram_fd < 0)
+ if (nvram_init(NULL))
+ return NULL;
+
+ if (count > sizeof(tmp)) {
+ if (!(off = malloc(count)))
+ return NULL;
+ }
+
+ /* Get offset into mmap() space */
+ strcpy((char *) off, name);
+
+ count = read(nvram_fd, off, count);
+
+ if (count == sizeof(unsigned long))
+ value = &nvram_buf[*off];
+ else
+ value = NULL;
+
+ if (count < 0)
+ perror(PATH_DEV_NVRAM);
+
+ if (off != (unsigned long *) tmp)
+ free(off);
+
+ return value;
+}
+
+int
+nvram_getall(char *buf, int count)
+{
+ int ret;
+
+ if (nvram_fd < 0)
+ if ((ret = nvram_init(NULL)))
+ return ret;
+
+ if (count == 0)
+ return 0;
+
+ /* Get all variables */
+ *buf = '\0';
+
+ ret = read(nvram_fd, buf, count);
+
+ if (ret < 0)
+ perror(PATH_DEV_NVRAM);
+
+ return (ret == count) ? 0 : ret;
+}
+
+static int
+_nvram_set(const char *name, const char *value)
+{
+ size_t count = strlen(name) + 1;
+ char tmp[100], *buf = tmp;
+ int ret;
+
+ if (nvram_fd < 0)
+ if ((ret = nvram_init(NULL)))
+ return ret;
+
+ /* Unset if value is NULL */
+ if (value)
+ count += strlen(value) + 1;
+
+ if (count > sizeof(tmp)) {
+ if (!(buf = malloc(count)))
+ return -ENOMEM;
+ }
+
+ if (value)
+ sprintf(buf, "%s=%s", name, value);
+ else
+ strcpy(buf, name);
+
+ ret = write(nvram_fd, buf, count);
+
+ if (ret < 0)
+ perror(PATH_DEV_NVRAM);
+
+ if (buf != tmp)
+ free(buf);
+
+ return (ret == count) ? 0 : ret;
+}
+
+int
+nvram_set(const char *name, const char *value)
+{
+ extern struct nvram_convert nvram_converts[];
+ struct nvram_convert *v;
+ int ret;
+
+ ret = _nvram_set(name, value);
+
+ for(v = nvram_converts ; v->name ; v++) {
+ if(!strcmp(v->name, name)){
+ if(strcmp(v->wl0_name,"")) _nvram_set(v->wl0_name, value);
+ if(strcmp(v->d11g_name,"")) _nvram_set(v->d11g_name, value);
+ }
+ }
+
+ return ret;
+}
+
+int
+nvram_unset(const char *name)
+{
+ return _nvram_set(name, NULL);
+}
+
+int
+nvram_commit(void)
+{
+ int ret;
+
+ cprintf("nvram_commit(): start\n");
+
+ if((check_action() == ACT_IDLE) ||
+ (check_action() == ACT_SW_RESTORE) ||
+ (check_action() == ACT_HW_RESTORE)){
+ if (nvram_fd < 0)
+ if ((ret = nvram_init(NULL)))
+ return ret;
+
+ ret = ioctl(nvram_fd, NVRAM_MAGIC, NULL);
+
+ if (ret < 0)
+ perror(PATH_DEV_NVRAM);
+
+ cprintf("nvram_commit(): end\n");
+ }
+ else
+ cprintf("nvram_commit(): nothing to do...\n");
+
+ return ret;
+}
+
+int file2nvram(char *filename, char *varname) {
+ FILE *fp;
+ int c,count;
+ int i=0,j=0;
+ char mem[10000],buf[30000];
+
+ if ( !(fp=fopen(filename,"rb") ))
+ return 0;
+
+ count=fread(mem,1,sizeof(mem),fp);
+ fclose(fp);
+ for (j=0;j<count;j++) {
+ if (i > sizeof(buf)-3 )
+ break;
+ c=mem[j];
+ if (c >= 32 && c <= 126 && c != '\\' && c != '~') {
+ buf[i++]=(unsigned char) c;
+ } else if (c==0) {
+ buf[i++]='~';
+ } else {
+ buf[i++]='\\';
+ sprintf(buf+i,"%02X",c);
+ i+=2;
+ }
+ }
+ if (i==0) return 0;
+ buf[i]=0;
+ //fprintf(stderr,"================ > file2nvram %s = [%s] \n",varname,buf);
+ nvram_set(varname,buf);
+ //nvram_commit(); //Barry adds for test
+}
+
+int nvram2file(char *varname, char *filename) {
+ FILE *fp;
+ int c,tmp;
+ int i=0,j=0;
+ char *buf;
+ char mem[10000];
+
+ if ( !(fp=fopen(filename,"wb") ))
+ return 0;
+
+ buf=strdup(nvram_safe_get(varname));
+ //fprintf(stderr,"=================> nvram2file %s = [%s] \n",varname,buf);
+ while ( buf[i] && j < sizeof(mem)-3 ) {
+ if (buf[i] == '\\') {
+ i++;
+ tmp=buf[i+2];
+ buf[i+2]=0;
+ sscanf(buf+i,"%02X",&c);
+ buf[i+2]=tmp;
+ i+=2;
+ mem[j]=c;j++;
+ } else if (buf[i] == '~') {
+ mem[j]=0;j++;
+ i++;
+ } else {
+ mem[j]=buf[i];j++;
+ i++;
+ }
+ }
+ if (j<=0) return j;
+ j=fwrite(mem,1,j,fp);
+ fclose(fp);
+ free(buf);
+ return j;
+}
+
+int
+check_action(void)
+{
+ char buf[80] = "";
+
+ if(file_to_buf(ACTION_FILE, buf, sizeof(buf))){
+ if(!strcmp(buf, "ACT_TFTP_UPGRADE")){
+ cprintf("Upgrading from tftp now, quiet exit....\n");
+ return ACT_TFTP_UPGRADE;
+ }
+ else if(!strcmp(buf, "ACT_WEBS_UPGRADE")){
+ cprintf("Upgrading from web (https) now, quiet exit....\n");
+ return ACT_WEBS_UPGRADE;
+ }
+ else if(!strcmp(buf, "ACT_WEB_UPGRADE")){
+ cprintf("Upgrading from web (http) now, quiet exit....\n");
+ return ACT_WEB_UPGRADE;
+ }
+ else if(!strcmp(buf, "ACT_SW_RESTORE")){
+ cprintf("Receive restore command from web, quiet exit....\n");
+ return ACT_SW_RESTORE;
+ }
+ else if(!strcmp(buf, "ACT_HW_RESTORE")){
+ cprintf("Receive restore commond from resetbutton, quiet exit....\n");
+ return ACT_HW_RESTORE;
+ }
+ }
+ //fprintf(stderr, "Waiting for upgrading....\n");
+ return ACT_IDLE;
+}
+
+int
+file_to_buf(char *path, char *buf, int len)
+{
+ FILE *fp;
+
+ memset(buf, 0 , len);
+
+ if ((fp = fopen(path, "r"))) {
+ fgets(buf, len, fp);
+ fclose(fp);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/package/nvram/src/shutils.c b/package/nvram/src/shutils.c
new file mode 100644
index 0000000000..49ad41af81
--- /dev/null
+++ b/package/nvram/src/shutils.c
@@ -0,0 +1,329 @@
+/*
+ * Shell-like utility functions
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <error.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <net/ethernet.h>
+
+#include <shutils.h>
+
+/*
+ * Reads file and returns contents
+ * @param fd file descriptor
+ * @return contents of file or NULL if an error occurred
+ */
+char *
+fd2str(int fd)
+{
+ char *buf = NULL;
+ size_t count = 0, n;
+
+ do {
+ buf = realloc(buf, count + 512);
+ n = read(fd, buf + count, 512);
+ if (n < 0) {
+ free(buf);
+ buf = NULL;
+ }
+ count += n;
+ } while (n == 512);
+
+ close(fd);
+ if (buf)
+ buf[count] = '\0';
+ return buf;
+}
+
+/*
+ * Reads file and returns contents
+ * @param path path to file
+ * @return contents of file or NULL if an error occurred
+ */
+char *
+file2str(const char *path)
+{
+ int fd;
+
+ if ((fd = open(path, O_RDONLY)) == -1) {
+ perror(path);
+ return NULL;
+ }
+
+ return fd2str(fd);
+}
+
+/*
+ * Waits for a file descriptor to change status or unblocked signal
+ * @param fd file descriptor
+ * @param timeout seconds to wait before timing out or 0 for no timeout
+ * @return 1 if descriptor changed status or 0 if timed out or -1 on error
+ */
+int
+waitfor(int fd, int timeout)
+{
+ fd_set rfds;
+ struct timeval tv = { timeout, 0 };
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+ return select(fd + 1, &rfds, NULL, NULL, (timeout > 0) ? &tv : NULL);
+}
+
+/*
+ * Concatenates NULL-terminated list of arguments into a single
+ * commmand and executes it
+ * @param argv argument list
+ * @param path NULL, ">output", or ">>output"
+ * @param timeout seconds to wait before timing out or 0 for no timeout
+ * @param ppid NULL to wait for child termination or pointer to pid
+ * @return return value of executed command or errno
+ */
+int
+_eval(char *const argv[], char *path, int timeout, int *ppid)
+{
+ pid_t pid;
+ int status;
+ int fd;
+ int flags;
+ int sig;
+ char buf[254]="";
+ int i;
+
+ switch (pid = fork()) {
+ case -1: /* error */
+ perror("fork");
+ return errno;
+ case 0: /* child */
+ /* Reset signal handlers set for parent process */
+ for (sig = 0; sig < (_NSIG-1); sig++)
+ signal(sig, SIG_DFL);
+
+ /* Clean up */
+ ioctl(0, TIOCNOTTY, 0);
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+ setsid();
+
+ /* We want to check the board if exist UART? , add by honor 2003-12-04 */
+ if ((fd = open("/dev/console", O_RDWR)) < 0) {
+ (void) open("/dev/null", O_RDONLY);
+ (void) open("/dev/null", O_WRONLY);
+ (void) open("/dev/null", O_WRONLY);
+ }
+ else{
+ close(fd);
+ (void) open("/dev/console", O_RDONLY);
+ (void) open("/dev/console", O_WRONLY);
+ (void) open("/dev/console", O_WRONLY);
+ }
+
+ /* Redirect stdout to <path> */
+ if (path) {
+ flags = O_WRONLY | O_CREAT;
+ if (!strncmp(path, ">>", 2)) {
+ /* append to <path> */
+ flags |= O_APPEND;
+ path += 2;
+ } else if (!strncmp(path, ">", 1)) {
+ /* overwrite <path> */
+ flags |= O_TRUNC;
+ path += 1;
+ }
+ if ((fd = open(path, flags, 0644)) < 0)
+ perror(path);
+ else {
+ dup2(fd, STDOUT_FILENO);
+ close(fd);
+ }
+ }
+
+ /* execute command */
+ for(i=0 ; argv[i] ; i++)
+ snprintf(buf+strlen(buf), sizeof(buf), "%s ", argv[i]);
+ dprintf("cmd=[%s]\n", buf);
+ setenv("PATH", "/sbin:/bin:/usr/sbin:/usr/bin", 1);
+ alarm(timeout);
+ execvp(argv[0], argv);
+ perror(argv[0]);
+ exit(errno);
+ default: /* parent */
+ if (ppid) {
+ *ppid = pid;
+ return 0;
+ } else {
+ waitpid(pid, &status, 0);
+ if (WIFEXITED(status))
+ return WEXITSTATUS(status);
+ else
+ return status;
+ }
+ }
+}
+
+/*
+ * Concatenates NULL-terminated list of arguments into a single
+ * commmand and executes it
+ * @param argv argument list
+ * @return stdout of executed command or NULL if an error occurred
+ */
+char *
+_backtick(char *const argv[])
+{
+ int filedes[2];
+ pid_t pid;
+ int status;
+ char *buf = NULL;
+
+ /* create pipe */
+ if (pipe(filedes) == -1) {
+ perror(argv[0]);
+ return NULL;
+ }
+
+ switch (pid = fork()) {
+ case -1: /* error */
+ return NULL;
+ case 0: /* child */
+ close(filedes[0]); /* close read end of pipe */
+ dup2(filedes[1], 1); /* redirect stdout to write end of pipe */
+ close(filedes[1]); /* close write end of pipe */
+ execvp(argv[0], argv);
+ exit(errno);
+ break;
+ default: /* parent */
+ close(filedes[1]); /* close write end of pipe */
+ buf = fd2str(filedes[0]);
+ waitpid(pid, &status, 0);
+ break;
+ }
+
+ return buf;
+}
+
+/*
+ * Kills process whose PID is stored in plaintext in pidfile
+ * @param pidfile PID file
+ * @return 0 on success and errno on failure
+ */
+int
+kill_pidfile(char *pidfile)
+{
+ FILE *fp = fopen(pidfile, "r");
+ char buf[256];
+
+ if (fp && fgets(buf, sizeof(buf), fp)) {
+ pid_t pid = strtoul(buf, NULL, 0);
+ fclose(fp);
+ return kill(pid, SIGTERM);
+ } else
+ return errno;
+}
+
+/*
+ * fread() with automatic retry on syscall interrupt
+ * @param ptr location to store to
+ * @param size size of each element of data
+ * @param nmemb number of elements
+ * @param stream file stream
+ * @return number of items successfully read
+ */
+int
+safe_fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+ size_t ret = 0;
+
+ do {
+ clearerr(stream);
+ ret += fread((char *)ptr + (ret * size), size, nmemb - ret, stream);
+ } while (ret < nmemb && ferror(stream) && errno == EINTR);
+
+ return ret;
+}
+
+/*
+ * fwrite() with automatic retry on syscall interrupt
+ * @param ptr location to read from
+ * @param size size of each element of data
+ * @param nmemb number of elements
+ * @param stream file stream
+ * @return number of items successfully written
+ */
+int
+safe_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+ size_t ret = 0;
+
+ do {
+ clearerr(stream);
+ ret += fwrite((char *)ptr + (ret * size), size, nmemb - ret, stream);
+ } while (ret < nmemb && ferror(stream) && errno == EINTR);
+
+ return ret;
+}
+
+/*
+ * Convert Ethernet address string representation to binary data
+ * @param a string in xx:xx:xx:xx:xx:xx notation
+ * @param e binary data
+ * @return TRUE if conversion was successful and FALSE otherwise
+ */
+int
+ether_atoe(const char *a, unsigned char *e)
+{
+ char *c = (char *) a;
+ int i = 0;
+
+ memset(e, 0, ETHER_ADDR_LEN);
+ for (;;) {
+ e[i++] = (unsigned char) strtoul(c, &c, 16);
+ if (!*c++ || i == ETHER_ADDR_LEN)
+ break;
+ }
+ return (i == ETHER_ADDR_LEN);
+}
+
+/*
+ * Convert Ethernet address binary data to string representation
+ * @param e binary data
+ * @param a string in xx:xx:xx:xx:xx:xx notation
+ * @return a
+ */
+char *
+ether_etoa(const unsigned char *e, char *a)
+{
+ char *c = a;
+ int i;
+
+ for (i = 0; i < ETHER_ADDR_LEN; i++) {
+ if (i)
+ *c++ = ':';
+ c += sprintf(c, "%02X", e[i] & 0xff);
+ }
+ return a;
+}
diff --git a/package/nvram/src/wl.c b/package/nvram/src/wl.c
new file mode 100644
index 0000000000..5738e2cd04
--- /dev/null
+++ b/package/nvram/src/wl.c
@@ -0,0 +1,299 @@
+/*
+ * Wireless network adapter utilities
+ *
+ * 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.
+ *
+ * $Id$
+ */
+#include <string.h>
+
+#include <typedefs.h>
+#include <wlutils.h>
+
+int
+wl_probe(char *name)
+{
+ int ret, val;
+
+ /* Check interface */
+ if ((ret = wl_ioctl(name, WLC_GET_MAGIC, &val, sizeof(val))))
+ return ret;
+ if (val != WLC_IOCTL_MAGIC)
+ return -1;
+ if ((ret = wl_ioctl(name, WLC_GET_VERSION, &val, sizeof(val))))
+ return ret;
+ if (val > WLC_IOCTL_VERSION)
+ return -1;
+
+ return ret;
+}
+
+int
+wl_set_val(char *name, char *var, void *val, int len)
+{
+ char buf[128];
+ int buf_len;
+
+ /* check for overflow */
+ if ((buf_len = strlen(var)) + 1 + len > sizeof(buf))
+ return -1;
+
+ strcpy(buf, var);
+ buf_len += 1;
+
+ /* append int value onto the end of the name string */
+ memcpy(&buf[buf_len], val, len);
+ buf_len += len;
+
+ return wl_ioctl(name, WLC_SET_VAR, buf, buf_len);
+}
+
+int
+wl_get_val(char *name, char *var, void *val, int len)
+{
+ char buf[128];
+ int ret;
+
+ /* check for overflow */
+ if (strlen(var) + 1 > sizeof(buf) || len > sizeof(buf))
+ return -1;
+
+ strcpy(buf, var);
+ if ((ret = wl_ioctl(name, WLC_GET_VAR, buf, sizeof(buf))))
+ return ret;
+
+ memcpy(val, buf, len);
+ return 0;
+}
+
+int
+wl_set_int(char *name, char *var, int val)
+{
+ return wl_set_val(name, var, &val, sizeof(val));
+}
+
+int
+wl_get_int(char *name, char *var, int *val)
+{
+ return wl_get_val(name, var, val, sizeof(*val));
+}
+
+/**************************************************************************
+ * The following code is from Broadcom (wl.c) *
+ **************************************************************************/
+
+int
+wl_iovar_getbuf(char *ifname, char *iovar, void *param,
+ int paramlen, void *bufptr, int buflen)
+{
+ int err;
+ uint namelen;
+ uint iolen;
+
+ namelen = strlen(iovar) + 1; /* length of iovar name plus null */
+ iolen = namelen + paramlen;
+
+ /* check for overflow */
+ if (iolen > buflen)
+ return (-1);
+
+ memcpy(bufptr, iovar, namelen); /* copy iovar name including null */
+ memcpy((int8*)bufptr + namelen, param, paramlen);
+
+ err = wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen);
+
+ return (err);
+}
+
+int
+wl_iovar_setbuf(char *ifname, char *iovar, void *param,
+ int paramlen, void *bufptr, int buflen)
+{
+ uint namelen;
+ uint iolen;
+
+ namelen = strlen(iovar) + 1; /* length of iovar name plus null */
+ iolen = namelen + paramlen;
+
+ /* check for overflow */
+ if (iolen > buflen)
+ return (-1);
+
+ memcpy(bufptr, iovar, namelen); /* copy iovar name including null */
+ memcpy((int8*)bufptr + namelen, param, paramlen);
+
+ return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen);
+}
+
+int
+wl_iovar_set(char *ifname, char *iovar, void *param, int paramlen)
+{
+ char smbuf[WLC_IOCTL_SMLEN];
+
+ return wl_iovar_setbuf(ifname, iovar, param, paramlen, smbuf, sizeof(smbuf));
+}
+
+int
+wl_iovar_get(char *ifname, char *iovar, void *bufptr, int buflen)
+{
+ char smbuf[WLC_IOCTL_SMLEN];
+ int ret;
+
+ /* use the return buffer if it is bigger than what we have on the stack */
+ if (buflen > sizeof(smbuf)) {
+ ret = wl_iovar_getbuf(ifname, iovar, NULL, 0, bufptr, buflen);
+ } else {
+ ret = wl_iovar_getbuf(ifname, iovar, NULL, 0, smbuf, sizeof(smbuf));
+ if (ret == 0)
+ memcpy(bufptr, smbuf, buflen);
+ }
+
+ return ret;
+}
+
+/*
+ * set named driver variable to int value
+ * calling example: wl_iovar_setint(ifname, "arate", rate)
+*/
+int
+wl_iovar_setint(char *ifname, char *iovar, int val)
+{
+ return wl_iovar_set(ifname, iovar, &val, sizeof(val));
+}
+
+/*
+ * get named driver variable to int value and return error indication
+ * calling example: wl_iovar_getint(ifname, "arate", &rate)
+ */
+int
+wl_iovar_getint(char *ifname, char *iovar, int *val)
+{
+ return wl_iovar_get(ifname, iovar, val, sizeof(int));
+}
+
+/*
+ * format a bsscfg indexed iovar buffer
+ */
+static int
+wl_bssiovar_mkbuf(char *iovar, int bssidx, void *param,
+ int paramlen, void *bufptr, int buflen, int *plen)
+{
+ char *prefix = "bsscfg:";
+ int8* p;
+ uint prefixlen;
+ uint namelen;
+ uint iolen;
+
+ prefixlen = strlen(prefix); /* length of bsscfg prefix */
+ namelen = strlen(iovar) + 1; /* length of iovar name + null */
+ iolen = prefixlen + namelen + sizeof(int) + paramlen;
+
+ /* check for overflow */
+ if (buflen < 0 || iolen > (uint)buflen) {
+ *plen = 0;
+ return -1;
+ }
+
+ p = (int8*)bufptr;
+
+ /* copy prefix, no null */
+ memcpy(p, prefix, prefixlen);
+ p += prefixlen;
+
+ /* copy iovar name including null */
+ memcpy(p, iovar, namelen);
+ p += namelen;
+
+ /* bss config index as first param */
+ memcpy(p, &bssidx, sizeof(int32));
+ p += sizeof(int32);
+
+ /* parameter buffer follows */
+ if (paramlen)
+ memcpy(p, param, paramlen);
+
+ *plen = iolen;
+ return 0;
+}
+
+/*
+ * set named & bss indexed driver variable to buffer value
+ */
+int
+wl_bssiovar_setbuf(char *ifname, char *iovar, int bssidx, void *param,
+ int paramlen, void *bufptr, int buflen)
+{
+ int err;
+ uint iolen;
+
+ err = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &iolen);
+ if (err)
+ return err;
+
+ return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen);
+}
+
+/*
+ * get named & bss indexed driver variable buffer value
+ */
+int
+wl_bssiovar_getbuf(char *ifname, char *iovar, int bssidx, void *param,
+ int paramlen, void *bufptr, int buflen)
+{
+ int err;
+ uint iolen;
+
+ err = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &iolen);
+ if (err)
+ return err;
+
+ return wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen);
+}
+
+/*
+ * set named & bss indexed driver variable to buffer value
+ */
+int
+wl_bssiovar_set(char *ifname, char *iovar, int bssidx, void *param, int paramlen)
+{
+ char smbuf[WLC_IOCTL_SMLEN];
+
+ return wl_bssiovar_setbuf(ifname, iovar, bssidx, param, paramlen, smbuf, sizeof(smbuf));
+}
+
+/*
+ * get named & bss indexed driver variable buffer value
+ */
+int
+wl_bssiovar_get(char *ifname, char *iovar, int bssidx, void *outbuf, int len)
+{
+ char smbuf[WLC_IOCTL_SMLEN];
+ int err;
+
+ /* use the return buffer if it is bigger than what we have on the stack */
+ if (len > (int)sizeof(smbuf)) {
+ err = wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, outbuf, len);
+ } else {
+ memset(smbuf, 0, sizeof(smbuf));
+ err = wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, smbuf, sizeof(smbuf));
+ if (err == 0)
+ memcpy(outbuf, smbuf, len);
+ }
+
+ return err;
+}
+
+/*
+ * set named & bss indexed driver variable to int value
+ */
+int
+wl_bssiovar_setint(char *ifname, char *iovar, int bssidx, int val)
+{
+ return wl_bssiovar_set(ifname, iovar, bssidx, &val, sizeof(int));
+}
diff --git a/package/nvram/src/wl_linux.c b/package/nvram/src/wl_linux.c
new file mode 100644
index 0000000000..126a40b4b3
--- /dev/null
+++ b/package/nvram/src/wl_linux.c
@@ -0,0 +1,77 @@
+/*
+ * Wireless network adapter utilities (linux-specific)
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+
+#include <typedefs.h>
+#include <wlioctl.h>
+#include <wlutils.h>
+
+int
+wl_ioctl(char *name, int cmd, void *buf, int len)
+{
+ struct ifreq ifr;
+ wl_ioctl_t ioc;
+ int ret = 0;
+ int s;
+
+ /* open socket to kernel */
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("socket");
+ return errno;
+ }
+
+ /* do it */
+ ioc.cmd = cmd;
+ ioc.buf = buf;
+ ioc.len = len;
+ strncpy(ifr.ifr_name, name, IFNAMSIZ);
+ ifr.ifr_data = (caddr_t) &ioc;
+ if ((ret = ioctl(s, SIOCDEVPRIVATE, &ifr)) < 0)
+ if (cmd != WLC_GET_MAGIC)
+ perror(ifr.ifr_name);
+
+ /* cleanup */
+ close(s);
+ return ret;
+}
+
+int
+wl_hwaddr(char *name, unsigned char *hwaddr)
+{
+ struct ifreq ifr;
+ int ret = 0;
+ int s;
+
+ /* open socket to kernel */
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("socket");
+ return errno;
+ }
+
+ /* do it */
+ strncpy(ifr.ifr_name, name, IFNAMSIZ);
+ if ((ret = ioctl(s, SIOCGIFHWADDR, &ifr)) == 0)
+ memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
+
+ /* cleanup */
+ close(s);
+ return ret;
+}
+
diff --git a/package/openssl/Makefile b/package/openssl/Makefile
new file mode 100644
index 0000000000..54b4aac089
--- /dev/null
+++ b/package/openssl/Makefile
@@ -0,0 +1,134 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=openssl
+PKG_VERSION:=0.9.8d
+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:=8ed1853538e1d05a1f5ada61ebf8bffa
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/openssl/Default
+ TITLE:=Open source SSL toolkit
+ 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.
+ URL:=http://www.openssl.org/
+endef
+
+define Package/libopenssl
+ $(call Package/openssl/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ DEPENDS:=+zlib
+ TITLE+= (libraries)
+ 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)
+ DESCRIPTION+=\\\
+ \\\
+ This package contains the OpenSSL command-line utility.
+endef
+
+define Package/openssl-util/conffiles
+/etc/ssl/openssl.cnf
+endef
+
+OPENSSL_NO_CIPHERS:= no-idea no-md2 no-mdc2 no-rc5 no-sha0 no-rmd160 no-aes192
+OPENSSL_OPTIONS:= shared no-ec no-err no-fips no-hw no-krb5 no-threads zlib-dynamic no-engines
+
+define Build/Configure
+ (cd $(PKG_BUILD_DIR); \
+ ./Configure linux-openwrt \
+ --prefix=/usr \
+ --openssldir=/etc/ssl \
+ -I$(STAGING_DIR)/usr/include \
+ -L$(STAGING_DIR)/usr/lib -ldl \
+ -DOPENSSL_SMALL_FOOTPRINT \
+ $(OPENSSL_NO_CIPHERS) \
+ $(OPENSSL_OPTIONS) \
+ )
+endef
+
+define Build/Compile
+ rm -rf $(PKG_INSTALL_DIR)
+ mkdir -p $(PKG_INSTALL_DIR)
+ $(MAKE) -C $(PKG_BUILD_DIR) -j1 \
+ MAKEDEPPROG="$(TARGET_CROSS)gcc" \
+ OPENWRT_OPTIMIZATION_FLAGS="$(TARGET_CFLAGS)" \
+ depend
+ $(MAKE) -C $(PKG_BUILD_DIR) -j1 \
+ CC="$(TARGET_CC)" \
+ AR="$(TARGET_CROSS)ar r" \
+ RANLIB="$(TARGET_CROSS)ranlib" \
+ OPENWRT_OPTIMIZATION_FLAGS="$(TARGET_CFLAGS)" \
+ all 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) -j1 \
+ CC="$(TARGET_CC)" \
+ OPENWRT_OPTIMIZATION_FLAGS="$(TARGET_CFLAGS)" \
+ do_linux-shared
+ $(MAKE) -C $(PKG_BUILD_DIR) -j1 \
+ INSTALL_PREFIX="$(PKG_INSTALL_DIR)" \
+ install
+endef
+
+define Build/InstallDev
+ mkdir -p $(STAGING_DIR)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/openssl $(STAGING_DIR)/usr/include/
+ mkdir -p $(STAGING_DIR)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/lib{crypto,ssl}.{a,so*} $(STAGING_DIR)/usr/lib/
+endef
+
+define Build/UninstallDev
+ rm -rf $(STAGING_DIR)/usr/include/openssl \
+ $(STAGING_DIR)/usr/lib/lib{crypto,ssl}.{a,so*}
+endef
+
+define Package/libopenssl/install
+ install -d -m0755 $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/lib{crypto,ssl}.so.* $(1)/usr/lib/
+ chmod 0644 $(1)/usr/lib/*
+endef
+
+define Package/openssl-util/install
+ install -d -m0755 $(1)/etc/ssl
+ $(CP) $(PKG_INSTALL_DIR)/etc/ssl/openssl.cnf $(1)/etc/ssl/
+ install -d -m0755 $(1)/etc/ssl/certs
+ install -d -m0755 $(1)/etc/ssl/private
+ chmod 0700 $(1)/etc/ssl/private
+ install -d -m0755 $(1)/usr/bin
+ $(CP) $(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 0000000000..8c78b6a01c
--- /dev/null
+++ b/package/openssl/patches/110-optimize-for-size.patch
@@ -0,0 +1,12 @@
+diff -ur openssl-0.9.8a/Configure openssl-0.9.8a-owrt/Configure
+--- openssl-0.9.8a/Configure 2005-08-02 12:59:42.000000000 +0200
++++ openssl-0.9.8a-owrt/Configure 2006-03-23 14:16:35.000000000 +0100
+@@ -353,6 +353,8 @@
+ "linux-alpha+bwx-gcc","gcc:-O3 -DL_ENDIAN -DTERMIO::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+ "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:${no_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:${no_asm}",
++# OpenWrt targets
++"linux-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)",
+
+ #### *BSD [do see comment about ${BSDthreads} above!]
+ "BSD-generic32","gcc:-DTERMIOS -O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
diff --git a/package/openssl/patches/120-makedepend.patch b/package/openssl/patches/120-makedepend.patch
new file mode 100644
index 0000000000..c802fe4adc
--- /dev/null
+++ b/package/openssl/patches/120-makedepend.patch
@@ -0,0 +1,28 @@
+diff -ruN openssl-0.9.7g-old/util/domd openssl-0.9.7g-new/util/domd
+--- openssl-0.9.7g-old/util/domd 2004-05-11 14:46:18.000000000 +0200
++++ openssl-0.9.7g-new/util/domd 2005-05-30 20:20:04.000000000 +0200
+@@ -1,4 +1,4 @@
+-#!/bin/sh
++#!/bin/bash
+ # Do a makedepend, only leave out the standard headers
+ # Written by Ben Laurie <ben@algroup.co.uk> 19 Jan 1999
+
+@@ -14,7 +14,8 @@
+ cp Makefile Makefile.save
+ # fake the presence of Kerberos
+ touch $TOP/krb5.h
+-if [ "$MAKEDEPEND" = "gcc" ]; then
++D=${MAKEDEPEND/%*gcc/gcc}
++if [ "$D" = "gcc" ]; then
+ args=""
+ while [ $# -gt 0 ]; do
+ if [ "$1" != "--" ]; then args="$args $1"; fi
+@@ -22,7 +23,7 @@
+ done
+ sed -e '/^# DO NOT DELETE.*/,$d' < Makefile > Makefile.tmp
+ echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' >> Makefile.tmp
+- gcc -D OPENSSL_DOING_MAKEDEPEND -M $args >> Makefile.tmp
++ ${MAKEDEPEND} -D OPENSSL_DOING_MAKEDEPEND -M $args >> Makefile.tmp
+ ${PERL} $TOP/util/clean-depend.pl < Makefile.tmp > Makefile.new
+ rm -f Makefile.tmp
+ else
diff --git a/package/openssl/patches/130-perl-path.patch b/package/openssl/patches/130-perl-path.patch
new file mode 100644
index 0000000000..42467b8388
--- /dev/null
+++ b/package/openssl/patches/130-perl-path.patch
@@ -0,0 +1,72 @@
+diff -Nur openssl-0.9.7f/Configure openssl-0.9.7f.new/Configure
+--- openssl-0.9.7f/Configure 2005-03-12 12:28:21.000000000 +0100
++++ openssl-0.9.7f.new/Configure 2005-04-03 20:32:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-:
++#!/usr/bin/perl
+ eval 'exec perl -S $0 ${1+"$@"}'
+ if $running_under_some_shell;
+ ##
+diff -Nur openssl-0.9.7f/tools/c_rehash.in openssl-0.9.7f.new/tools/c_rehash.in
+--- openssl-0.9.7f/tools/c_rehash.in 2002-10-11 22:35:45.000000000 +0200
++++ openssl-0.9.7f.new/tools/c_rehash.in 2005-04-03 20:41:17.000000000 +0200
+@@ -1,4 +1,4 @@
+-#!/usr/local/bin/perl
++#!/usr/bin/perl
+
+
+ # Perl c_rehash script, scan all files in a directory
+diff -Nur openssl-0.9.7f/util/clean-depend.pl openssl-0.9.7f.new/util/clean-depend.pl
+--- openssl-0.9.7f/util/clean-depend.pl 2001-10-10 10:27:28.000000000 +0200
++++ openssl-0.9.7f.new/util/clean-depend.pl 2005-04-03 20:41:38.000000000 +0200
+@@ -1,4 +1,4 @@
+-#!/usr/local/bin/perl -w
++#!/usr/bin/perl -w
+ # Clean the dependency list in a makefile of standard includes...
+ # Written by Ben Laurie <ben@algroup.co.uk> 19 Jan 1999
+
+diff -Nur openssl-0.9.7f/util/mkdef.pl openssl-0.9.7f.new/util/mkdef.pl
+--- openssl-0.9.7f/util/mkdef.pl 2005-02-05 18:19:23.000000000 +0100
++++ openssl-0.9.7f.new/util/mkdef.pl 2005-04-03 20:42:49.000000000 +0200
+@@ -1,4 +1,4 @@
+-#!/usr/local/bin/perl -w
++#!/usr/bin/perl
+ #
+ # generate a .def file
+ #
+diff -Nur openssl-0.9.7f/util/mkerr.pl openssl-0.9.7f.new/util/mkerr.pl
+--- openssl-0.9.7f/util/mkerr.pl 2005-01-31 02:28:17.000000000 +0100
++++ openssl-0.9.7f.new/util/mkerr.pl 2005-04-03 20:43:02.000000000 +0200
+@@ -1,4 +1,4 @@
+-#!/usr/local/bin/perl -w
++#!/usr/bin/perl
+
+ my $config = "crypto/err/openssl.ec";
+ my $debug = 0;
+diff -Nur openssl-0.9.7f/util/mkstack.pl openssl-0.9.7f.new/util/mkstack.pl
+--- openssl-0.9.7f/util/mkstack.pl 2004-10-04 18:27:36.000000000 +0200
++++ openssl-0.9.7f.new/util/mkstack.pl 2005-04-03 20:43:18.000000000 +0200
+@@ -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
+diff -Nur openssl-0.9.7f/util/pod2man.pl openssl-0.9.7f.new/util/pod2man.pl
+--- openssl-0.9.7f/util/pod2man.pl 2002-05-30 17:30:21.000000000 +0200
++++ openssl-0.9.7f.new/util/pod2man.pl 2005-04-03 20:43:52.000000000 +0200
+@@ -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;
+
+diff -Nur openssl-0.9.7f/util/selftest.pl openssl-0.9.7f.new/util/selftest.pl
+--- openssl-0.9.7f/util/selftest.pl 2004-05-11 14:46:19.000000000 +0200
++++ openssl-0.9.7f.new/util/selftest.pl 2005-04-03 20:44:10.000000000 +0200
+@@ -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 0000000000..89022e0c6c
--- /dev/null
+++ b/package/openssl/patches/140-makefile-dirs.patch
@@ -0,0 +1,11 @@
+--- openssl-0.9.8a/Makefile.org 2006-02-21 20:57:45.000000000 -0800
++++ openssl-0.9.8a-new/Makefile.org 2006-02-21 21:37:11.000000000 -0800
+@@ -100,7 +100,7 @@
+ KRB5_INCLUDES=
+ LIBKRB5=
+
+-DIRS= crypto ssl engines apps test tools
++DIRS= crypto ssl apps
+ SHLIBDIRS= crypto ssl
+
+ # dirs in crypto to build
diff --git a/package/openssl/patches/150-no_engines.patch b/package/openssl/patches/150-no_engines.patch
new file mode 100644
index 0000000000..b928fbcc61
--- /dev/null
+++ b/package/openssl/patches/150-no_engines.patch
@@ -0,0 +1,83 @@
+diff -udrNP openssl-0.9.8-stable-SNAP-20050703.orig/util/libeay.num openssl-0.9.8-stable-SNAP-20050703/util/libeay.num
+--- openssl-0.9.8-stable-SNAP-20050703.orig/util/libeay.num 2005-07-04 00:27:14.653639088 +0200
++++ openssl-0.9.8-stable-SNAP-20050703/util/libeay.num 2005-07-04 22:50:07.986576664 +0200
+@@ -2071,7 +2071,6 @@
+ UI_add_error_string 2633 EXIST::FUNCTION:
+ KRB5_CHECKSUM_free 2634 EXIST::FUNCTION:
+ OCSP_REQUEST_get_ext 2635 EXIST::FUNCTION:
+-ENGINE_load_ubsec 2636 EXIST::FUNCTION:ENGINE,STATIC_ENGINE
+ ENGINE_register_all_digests 2637 EXIST::FUNCTION:ENGINE
+ PKEY_USAGE_PERIOD_it 2638 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
+ PKEY_USAGE_PERIOD_it 2638 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
+@@ -2545,7 +2544,6 @@
+ AES_set_encrypt_key 3024 EXIST::FUNCTION:AES
+ OCSP_resp_count 3025 EXIST::FUNCTION:
+ KRB5_CHECKSUM_new 3026 EXIST::FUNCTION:
+-ENGINE_load_cswift 3027 EXIST::FUNCTION:ENGINE,STATIC_ENGINE
+ OCSP_onereq_get0_id 3028 EXIST::FUNCTION:
+ ENGINE_set_default_ciphers 3029 EXIST::FUNCTION:ENGINE
+ NOTICEREF_it 3030 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
+@@ -2576,7 +2574,6 @@
+ i2d_EXTENDED_KEY_USAGE 3052 EXIST::FUNCTION:
+ i2d_OCSP_SIGNATURE 3053 EXIST::FUNCTION:
+ asn1_enc_save 3054 EXIST::FUNCTION:
+-ENGINE_load_nuron 3055 EXIST::FUNCTION:ENGINE,STATIC_ENGINE
+ _ossl_old_des_pcbc_encrypt 3056 EXIST::FUNCTION:DES
+ PKCS12_MAC_DATA_it 3057 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
+ PKCS12_MAC_DATA_it 3057 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
+@@ -2600,7 +2597,6 @@
+ i2d_KRB5_CHECKSUM 3072 EXIST::FUNCTION:
+ ENGINE_set_table_flags 3073 EXIST::FUNCTION:ENGINE
+ AES_options 3074 EXIST::FUNCTION:AES
+-ENGINE_load_chil 3075 EXIST::FUNCTION:ENGINE,STATIC_ENGINE
+ OCSP_id_cmp 3076 EXIST::FUNCTION:
+ OCSP_BASICRESP_new 3077 EXIST::FUNCTION:
+ OCSP_REQUEST_get_ext_by_NID 3078 EXIST::FUNCTION:
+@@ -2667,7 +2663,6 @@
+ OCSP_CRLID_it 3127 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
+ i2d_KRB5_AUTHENTBODY 3128 EXIST::FUNCTION:
+ OCSP_REQUEST_get_ext_count 3129 EXIST::FUNCTION:
+-ENGINE_load_atalla 3130 EXIST::FUNCTION:ENGINE,STATIC_ENGINE
+ X509_NAME_it 3131 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
+ X509_NAME_it 3131 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
+ USERNOTICE_it 3132 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
+@@ -2762,8 +2757,6 @@
+ DES_read_password 3207 EXIST::FUNCTION:DES
+ UI_UTIL_read_pw 3208 EXIST::FUNCTION:
+ UI_UTIL_read_pw_string 3209 EXIST::FUNCTION:
+-ENGINE_load_aep 3210 EXIST::FUNCTION:ENGINE,STATIC_ENGINE
+-ENGINE_load_sureware 3211 EXIST::FUNCTION:ENGINE,STATIC_ENGINE
+ OPENSSL_add_all_algorithms_noconf 3212 EXIST:!VMS:FUNCTION:
+ OPENSSL_add_all_algo_noconf 3212 EXIST:VMS:FUNCTION:
+ OPENSSL_add_all_algorithms_conf 3213 EXIST:!VMS:FUNCTION:
+@@ -2772,7 +2765,6 @@
+ AES_ofb128_encrypt 3215 EXIST::FUNCTION:AES
+ AES_ctr128_encrypt 3216 EXIST::FUNCTION:AES
+ AES_cfb128_encrypt 3217 EXIST::FUNCTION:AES
+-ENGINE_load_4758cca 3218 EXIST::FUNCTION:ENGINE,STATIC_ENGINE
+ _ossl_096_des_random_seed 3219 EXIST::FUNCTION:DES
+ EVP_aes_256_ofb 3220 EXIST::FUNCTION:AES
+ EVP_aes_192_ofb 3221 EXIST::FUNCTION:AES
+@@ -3107,7 +3099,6 @@
+ STORE_method_set_modify_function 3530 EXIST:!VMS:FUNCTION:
+ STORE_meth_set_modify_fn 3530 EXIST:VMS:FUNCTION:
+ STORE_parse_attrs_next 3531 EXIST::FUNCTION:
+-ENGINE_load_padlock 3532 EXIST::FUNCTION:ENGINE
+ EC_GROUP_set_curve_name 3533 EXIST::FUNCTION:EC
+ X509_CERT_PAIR_it 3534 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
+ X509_CERT_PAIR_it 3534 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
+diff -udrNP openssl-0.9.8-stable-SNAP-20050703.orig/Configure openssl-0.9.8-stable-SNAP-20050703/Configure
+--- openssl-0.9.8-stable-SNAP-20050703.orig/Configure 2005-07-04 00:27:11.169168808 +0200
++++ openssl-0.9.8-stable-SNAP-20050703/Configure 2005-07-05 00:02:12.590136992 +0200
+@@ -1623,6 +1624,11 @@
+ close(OUT);
+ }
+
++# ugly hack to disable engines
++if($target eq "mingwx") {
++ system("sed -e s/^LIB/XLIB/g -i engines/Makefile");
++}
++
+ print <<EOF;
+
+ Configured for $target.
diff --git a/package/openssl/patches/160-disable_doc_tests.patch b/package/openssl/patches/160-disable_doc_tests.patch
new file mode 100644
index 0000000000..27e2033475
--- /dev/null
+++ b/package/openssl/patches/160-disable_doc_tests.patch
@@ -0,0 +1,60 @@
+diff -urN openssl-0.9.8a/Makefile openssl-0.9.8a.new/Makefile
+--- openssl-0.9.8a/Makefile 2005-10-11 12:21:48.000000000 +0200
++++ openssl-0.9.8a.new/Makefile 2006-03-29 15:23:28.107586680 +0200
+@@ -102,7 +102,7 @@
+ KRB5_INCLUDES=
+ LIBKRB5=
+
+-DIRS= crypto ssl engines apps test tools
++DIRS= crypto ssl engines apps tools
+ SHLIBDIRS= crypto ssl
+
+ # dirs in crypto to build
+@@ -119,7 +119,7 @@
+
+ # tests to perform. "alltests" is a special word indicating that all tests
+ # should be performed.
+-TESTS = alltests
++TESTS =
+
+ MAKEFILE= Makefile
+
+@@ -131,7 +131,7 @@
+
+ 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)
+@@ -204,7 +204,7 @@
+ @[ -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
+
+@@ -454,7 +454,7 @@
+ 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 -urN openssl-0.9.8b/Makefile.org openssl-0.9.8b.new/Makefile.org
+--- openssl-0.9.8b/Makefile.org 2006-09-01 19:34:51.000000000 +0200
++++ openssl-0.9.8b.new/Makefile.org 2006-09-01 19:36:38.000000000 +0200
+@@ -473,7 +473,7 @@
+ 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/openswan/Makefile b/package/openswan/Makefile
new file mode 100644
index 0000000000..54b565efdd
--- /dev/null
+++ b/package/openswan/Makefile
@@ -0,0 +1,94 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=openswan
+PKG_VERSION:=2.4.6
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://www.openswan.org/download
+PKG_MD5SUM:=b34d71ca49dedad017879b0e912d40dd
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+PKG_INIT_PRIO:=60
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/openswan/Default
+ TITLE:=Openswan
+ DESCRIPTION:=\
+ Openswan is an IPsec implementation for Linux.
+ URL:=http://www.openswan.org/
+endef
+
+define Package/openswan
+ $(call Package/openswan/Default)
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=+kmod-openswan +libgmp
+ TITLE+= (daemon)
+ DESCRIPTION+=\\\
+ \\\
+ This package contains the Openswan user-land daemon.
+ URL:=http://www.openswan.org/
+endef
+
+define Package/kmod-openswan
+ $(call Package/openswan/Default)
+ SECTION:=kernel
+ CATEGORY:=Kernel drivers
+ TITLE+= (kernel module)
+ DESCRIPTION+=\\\
+ \\\
+ This package contains the Openswan kernel module.
+ VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE)
+endef
+
+PKG_MAKE_OPTS:= \
+ LINUX_RELEASE="$(LINUX_RELEASE)" \
+ KERNELSRC="$(LINUX_DIR)" \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ USERCOMPILE="$(TARGET_CFLAGS) -I./linux/include -I$(STAGING_DIR)/usr/include -L$(STAGING_DIR)/usr/lib" \
+ IPSECDIR="/usr/lib/ipsec" \
+ INC_USRLOCAL="/usr" \
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ $(PKG_MAKE_OPTS) \
+ LDFLAGS="-L$(STAGING_DIR)/usr/lib -L$(STAGING_DIR)/lib" \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ programs module install
+endef
+
+define Package/openswan/install
+ $(CP) $(PKG_INSTALL_DIR)/* $(1)
+ install -d -m0755 $(1)/etc/init.d
+ $(CP) $(1)/etc/rc.d/init.d/ipsec $(1)/etc/init.d/S$(PKG_INIT_PRIO)ipsec
+ rm -rf $(1)/usr/share
+ rm -rf $(1)/usr/man
+ rm -rf $(1)/var
+ rm -rf $(1)/etc/rc.d
+ find $(1) -name \*.old | xargs rm -rf
+endef
+
+define Package/kmod-openswan/install
+ mkdir -p $(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) $(PKG_BUILD_DIR)/modobj*/ipsec.$(LINUX_KMOD_SUFFIX) \
+ $(1)/lib/modules/$(LINUX_VERSION)/
+endef
+
+$(eval $(call BuildPackage,openswan))
+$(eval $(call BuildPackage,kmod-openswan))
diff --git a/package/openswan/patches/100-pluto_includes.patch b/package/openswan/patches/100-pluto_includes.patch
new file mode 100644
index 0000000000..8cd1398d4a
--- /dev/null
+++ b/package/openswan/patches/100-pluto_includes.patch
@@ -0,0 +1,12 @@
+diff -Nur openswan-2.4.0.orig/programs/pluto/Makefile openswan-2.4.0/programs/pluto/Makefile
+--- openswan-2.4.0.orig/programs/pluto/Makefile 2005-08-12 03:12:38.000000000 +0200
++++ openswan-2.4.0/programs/pluto/Makefile 2005-09-29 13:41:14.016377750 +0200
+@@ -271,7 +271,7 @@
+ LIBSPLUTO+=$(HAVE_THREADS_LIBS) ${XAUTHPAM_LIBS}
+ LIBSPLUTO+=${CURL_LIBS}
+ LIBSPLUTO+=${EXTRA_CRYPTO_LIBS}
+-LIBSPLUTO+= -lgmp -lresolv # -lefence
++LIBSPLUTO+=$(EXTRA_LIBS) -lgmp -lresolv # -lefence
+
+ ifneq ($(LD_LIBRARY_PATH),)
+ LDFLAGS=-L$(LD_LIBRARY_PATH)
diff --git a/package/openswan/patches/110-scripts.patch b/package/openswan/patches/110-scripts.patch
new file mode 100644
index 0000000000..ed8eba92cf
--- /dev/null
+++ b/package/openswan/patches/110-scripts.patch
@@ -0,0 +1,243 @@
+diff -urN openswan.old/programs/loggerfix openswan.dev/programs/loggerfix
+--- openswan.old/programs/loggerfix 1970-01-01 01:00:00.000000000 +0100
++++ openswan.dev/programs/loggerfix 2006-10-08 20:41:08.000000000 +0200
+@@ -0,0 +1,5 @@
++#!/bin/sh
++# use filename instead of /dev/null to log, but dont log to flash or ram
++# pref. log to nfs mount
++echo "$*" >> /dev/null
++exit 0
+diff -urN openswan.old/programs/look/look.in openswan.dev/programs/look/look.in
+--- openswan.old/programs/look/look.in 2006-10-08 20:43:21.000000000 +0200
++++ openswan.dev/programs/look/look.in 2006-10-08 20:41:08.000000000 +0200
+@@ -84,7 +84,7 @@
+ then
+ pat="$pat|$defaultroutephys\$|$defaultroutevirt\$"
+ else
+- for i in `echo "$IPSECinterfaces" | sed 's/=/ /'`
++ for i in `echo "$IPSECinterfaces" | tr '=' ' '`
+ do
+ pat="$pat|$i\$"
+ done
+diff -urN openswan.old/programs/_plutorun/_plutorun.in openswan.dev/programs/_plutorun/_plutorun.in
+--- openswan.old/programs/_plutorun/_plutorun.in 2006-10-08 20:43:21.000000000 +0200
++++ openswan.dev/programs/_plutorun/_plutorun.in 2006-10-08 20:41:08.000000000 +0200
+@@ -147,7 +147,7 @@
+ exit 1
+ fi
+ else
+- if test ! -w "`dirname $stderrlog`"
++ if test ! -w "`echo $stderrlog | sed -r 's/(^.*\/)(.*$)/\1/'`"
+ then
+ echo Cannot write to directory to create \"$stderrlog\".
+ exit 1
+diff -urN openswan.old/programs/_realsetup/_realsetup.in openswan.dev/programs/_realsetup/_realsetup.in
+--- openswan.old/programs/_realsetup/_realsetup.in 2006-10-08 20:43:21.000000000 +0200
++++ openswan.dev/programs/_realsetup/_realsetup.in 2006-10-08 20:41:08.000000000 +0200
+@@ -232,7 +232,7 @@
+
+ # misc pre-Pluto setup
+
+- perform test -d `dirname $subsyslock` "&&" touch $subsyslock
++ perform test -d `echo $subsyslock | sed -r 's/(^.*\/)(.*$)/\1/'` "&&" touch $subsyslock "&&" rm -f $subsyslock
+
+ if test " $IPSECforwardcontrol" = " yes"
+ then
+diff -urN openswan.old/programs/send-pr/send-pr.in openswan.dev/programs/send-pr/send-pr.in
+--- openswan.old/programs/send-pr/send-pr.in 2006-10-08 20:43:21.000000000 +0200
++++ openswan.dev/programs/send-pr/send-pr.in 2006-10-08 20:41:08.000000000 +0200
+@@ -402,7 +402,7 @@
+ else
+ if [ "$fieldname" != "Category" ]
+ then
+- values=`${BINDIR}/query-pr --valid-values $fieldname | sed ':a;N;$!ba;s/\n/ /g' | sed 's/ *$//g;s/ / | /g;s/^/[ /;s/$/ ]/;'`
++ values=`${BINDIR}/query-pr --valid-values $fieldname | tr '\n' ' ' | sed 's/ *$//g;s/ / | /g;s/^/[ /;s/$/ ]/;'`
+ valslen=`echo "$values" | wc -c`
+ else
+ values="choose from a category listed above"
+@@ -414,7 +414,7 @@
+ else
+ desc="<${values} (one line)>";
+ fi
+- dpat=`echo "$desc" | sed 's/[][*+^$|\()&/]/./g'`
++ dpat=`echo "$desc" | tr '\]\[*+^$|\()&/' '............'`
+ echo "/^>${fieldname}:/ s/${dpat}//" >> $FIXFIL
+ fi
+ echo "${fmtname}${desc}" >> $file
+@@ -425,7 +425,7 @@
+ desc=" $default_val";
+ else
+ desc=" <`${BINDIR}/query-pr --field-description $fieldname` (multiple lines)>";
+- dpat=`echo "$desc" | sed 's/[][*+^$|\()&/]/./g'`
++ dpat=`echo "$desc" | tr '\]\[*+^$|\()&/' '............'`
+ echo "s/^${dpat}//" >> $FIXFIL
+ fi
+ echo "${fmtname}" >> $file;
+@@ -437,7 +437,7 @@
+ desc="${default_val}"
+ else
+ desc="<`${BINDIR}/query-pr --field-description $fieldname` (one line)>"
+- dpat=`echo "$desc" | sed 's/[][*+^$|\()&/]/./g'`
++ dpat=`echo "$desc" | tr '\]\[*+^$|\()&/' '............'`
+ echo "/^>${fieldname}:/ s/${dpat}//" >> $FIXFIL
+ fi
+ echo "${fmtname}${desc}" >> $file
+diff -urN openswan.old/programs/setup/setup.in openswan.dev/programs/setup/setup.in
+--- openswan.old/programs/setup/setup.in 2006-10-08 20:43:21.000000000 +0200
++++ openswan.dev/programs/setup/setup.in 2006-10-08 20:41:08.000000000 +0200
+@@ -117,12 +117,21 @@
+ # do it
+ case "$1" in
+ start|--start|stop|--stop|_autostop|_autostart)
+- if test " `id -u`" != " 0"
++ if [ "x${USER}" != "xroot" ]
+ then
+ echo "permission denied (must be superuser)" |
+ logger -s -p $IPSECsyslog -t ipsec_setup 2>&1
+ exit 1
+ fi
++ # make sure all required directories exist
++ if [ ! -d /var/run/pluto ]
++ then
++ mkdir -p /var/run/pluto
++ fi
++ if [ ! -d /var/lock/subsys ]
++ then
++ mkdir -p /var/lock/subsys
++ fi
+ tmp=/var/run/pluto/ipsec_setup.st
+ outtmp=/var/run/pluto/ipsec_setup.out
+ (
+diff -urN openswan.old/programs/showhostkey/showhostkey.in openswan.dev/programs/showhostkey/showhostkey.in
+--- openswan.old/programs/showhostkey/showhostkey.in 2006-10-08 20:43:21.000000000 +0200
++++ openswan.dev/programs/showhostkey/showhostkey.in 2006-10-08 20:41:08.000000000 +0200
+@@ -63,7 +63,7 @@
+ exit 1
+ fi
+
+-host="`hostname --fqdn`"
++host="`cat /proc/sys/kernel/hostname`"
+
+ awk ' BEGIN {
+ inkey = 0
+@@ -81,7 +81,7 @@
+ os = "[ \t]*"
+ x = "[^ \t]+"
+ oc = "(#.*)?"
+- suffix = ":" os "[rR][sS][aA]" os "{" os oc "$"
++ suffix = ":" os "[rR][sS][aA]" os "\0173" os oc "$"
+ if (id == "") {
+ pat = "^" suffix
+ printid = "default"
+diff -urN openswan.old/programs/starter/klips.c openswan.dev/programs/starter/klips.c
+--- openswan.old/programs/starter/klips.c 2006-10-08 20:43:21.000000000 +0200
++++ openswan.dev/programs/starter/klips.c 2006-10-08 20:41:08.000000000 +0200
+@@ -83,7 +83,7 @@
+ if (stat(PROC_MODULES,&stb)==0) {
+ unsetenv("MODPATH");
+ unsetenv("MODULECONF");
+- system("depmod -a >/dev/null 2>&1 && modprobe ipsec");
++ system("depmod -a >/dev/null 2>&1 && insmod ipsec");
+ }
+ if (stat(PROC_IPSECVERSION,&stb)==0) {
+ _klips_module_loaded = 1;
+diff -urN openswan.old/programs/starter/netkey.c openswan.dev/programs/starter/netkey.c
+--- openswan.old/programs/starter/netkey.c 2006-10-08 20:43:21.000000000 +0200
++++ openswan.dev/programs/starter/netkey.c 2006-10-08 20:41:08.000000000 +0200
+@@ -75,7 +75,7 @@
+ if (stat(PROC_MODULES,&stb)==0) {
+ unsetenv("MODPATH");
+ unsetenv("MODULECONF");
+- system("depmod -a >/dev/null 2>&1 && modprobe xfrm4_tunnel esp4 ah4 af_key");
++ system("depmod -a >/dev/null 2>&1 && insmod xfrm4_tunnel esp4 ah4 af_key");
+ }
+ if (stat(PROC_NETKEY,&stb)==0) {
+ _netkey_module_loaded = 1;
+diff -urN openswan.old/programs/_startklips/_startklips.in openswan.dev/programs/_startklips/_startklips.in
+--- openswan.old/programs/_startklips/_startklips.in 2006-10-08 20:43:21.000000000 +0200
++++ openswan.dev/programs/_startklips/_startklips.in 2006-10-08 20:41:46.000000000 +0200
+@@ -242,7 +242,7 @@
+ fi
+ if test -f $moduleinstplace/$wantgoo
+ then
+- echo "modprobe failed, but found matching template module $wantgoo."
++ echo "insmod failed, but found matching template module $wantgoo."
+ echo "Copying $moduleinstplace/$wantgoo to $module."
+ rm -f $module
+ mkdir -p $moduleplace
+@@ -262,15 +262,15 @@
+ echo "FATAL ERROR: Both KLIPS and NETKEY IPsec code is present in kernel"
+ exit
+ fi
+-if test ! -f $ipsecversion && test ! -f $netkey && modprobe -qn ipsec
++if test ! -f $ipsecversion && test ! -f $netkey && insmod -q ipsec
+ then
+ # statically compiled KLIPS/NETKEY not found; try to load the module
+- modprobe ipsec
++ insmod ipsec
+ fi
+
+ if test ! -f $ipsecversion && test ! -f $netkey
+ then
+- modprobe -v af_key
++ insmod -v af_key
+ fi
+
+ if test -f $netkey
+@@ -278,25 +278,25 @@
+ klips=false
+ if test -f $modules
+ then
+- modprobe -qv ah4
+- modprobe -qv esp4
+- modprobe -qv ipcomp
++ insmod -qv ah4
++ insmod -qv esp4
++ insmod -qv ipcomp
+ # xfrm4_tunnel is needed by ipip and ipcomp
+- modprobe -qv xfrm4_tunnel
++ insmod -qv xfrm4_tunnel
+ # xfrm_user contains netlink support for IPsec
+- modprobe -qv xfrm_user
++ insmod -qv xfrm_user
+ if [ -n "`cat /proc/cpuinfo |grep Nehemiah`" ]
+ then
+ echo "VIA Nehemiah detected, probing for PadLock"
+- modprobe -qv hw_random
++ insmod -qv hw_random
+ # padlock must load before aes module
+- modprobe -qv padlock
++ insmod -qv padlock
+ fi
+ # load the most common ciphers/algo's
+- modprobe -qv sha1
+- modprobe -qv md5
+- modprobe -qv des
+- modprobe -qv aes
++ insmod -qv sha1
++ insmod -qv md5
++ insmod -qv des
++ insmod -qv aes
+ fi
+ fi
+
+@@ -312,10 +312,16 @@
+ fi
+ unset MODPATH MODULECONF # no user overrides!
+ depmod -a >/dev/null 2>&1
+- modprobe -qv hw_random
++ insmod -qv hw_random
+ # padlock must load before aes module
+- modprobe -qv padlock
+- modprobe -v ipsec
++ insmod -qv padlock
++ if [ -f insmod ]
++ then
++ insmod -v ipsec
++ elif [ -f insmod ]
++ then
++ insmod ipsec
++ fi
+ fi
+ if test ! -f $ipsecversion
+ then
diff --git a/package/openswan/patches/120-use_dev_urandom.patch b/package/openswan/patches/120-use_dev_urandom.patch
new file mode 100644
index 0000000000..1a19884584
--- /dev/null
+++ b/package/openswan/patches/120-use_dev_urandom.patch
@@ -0,0 +1,36 @@
+diff -urN openswan-2.3.1dr6.old/programs/ranbits/ranbits.c openswan-2.3.1dr6.dev/programs/ranbits/ranbits.c
+--- openswan-2.3.1dr6.old/programs/ranbits/ranbits.c 2004-04-04 03:50:56.000000000 +0200
++++ openswan-2.3.1dr6.dev/programs/ranbits/ranbits.c 2005-04-05 17:37:16.000000000 +0200
+@@ -29,7 +29,7 @@
+ #include <openswan.h>
+
+ #ifndef DEVICE
+-#define DEVICE "/dev/random"
++#define DEVICE "/dev/urandom"
+ #endif
+ #ifndef QDEVICE
+ #define QDEVICE "/dev/urandom"
+diff -urN openswan-2.3.1dr6.old/programs/rsasigkey/rsasigkey.c openswan-2.3.1dr6.dev/programs/rsasigkey/rsasigkey.c
+--- openswan-2.3.1dr6.old/programs/rsasigkey/rsasigkey.c 2004-05-23 23:32:03.000000000 +0200
++++ openswan-2.3.1dr6.dev/programs/rsasigkey/rsasigkey.c 2005-04-05 17:38:00.000000000 +0200
+@@ -31,7 +31,7 @@
+ #include <gmp.h>
+
+ #ifndef DEVICE
+-#define DEVICE "/dev/random"
++#define DEVICE "/dev/urandom"
+ #endif
+ #ifndef MAXBITS
+ #define MAXBITS 20000
+diff -urN openswan-2.3.1dr6.old/programs/starter/files.h openswan-2.3.1dr6.dev/programs/starter/files.h
+--- openswan-2.3.1dr6.old/programs/starter/files.h 2005-01-11 18:52:51.000000000 +0100
++++ openswan-2.3.1dr6.dev/programs/starter/files.h 2005-04-05 17:38:16.000000000 +0200
+@@ -36,7 +36,7 @@
+
+ #define MY_PID_FILE "/var/run/pluto/ipsec-starter.pid"
+
+-#define DEV_RANDOM "/dev/random"
++#define DEV_RANDOM "/dev/urandom"
+ #define DEV_URANDOM "/dev/urandom"
+
+ #define PROC_IPSECVERSION "/proc/net/ipsec_version"
diff --git a/package/pcmcia-cs/Makefile b/package/pcmcia-cs/Makefile
new file mode 100644
index 0000000000..78419de75d
--- /dev/null
+++ b/package/pcmcia-cs/Makefile
@@ -0,0 +1,68 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=pcmcia-cs
+PKG_VERSION:=3.2.8
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/$(PKG_NAME)
+PKG_MD5SUM:=0d6d65be8896eff081aee996049afaa5
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/pcmcia-cs
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=@PCMCIA_SUPPORT
+ TITLE:=PCMCIA/Cardbus management utilities
+ URL:=http://pcmcia-cs.sourceforge.net/
+endef
+
+define Build/Configure
+ ( cd $(PKG_BUILD_DIR); \
+ ./Configure \
+ --noprompt \
+ --kernel="$(LINUX_DIR)" \
+ --target="$(PKG_INSTALL_DIR)" \
+ --arch="$(ARCH)" \
+ --ucc="$(TARGET_CC)" \
+ --uflags="$(TARGET_CFLAGS)" \
+ --srctree \
+ --cardbus \
+ --noapm \
+ --nopnp \
+ --notrust \
+ --nox11 \
+ --rcdir="/etc" \
+ --sysv \
+ )
+endef
+
+define Build/Compile
+ $(call Build/Compile/Default, \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ all install \
+ )
+endef
+
+define Package/pcmcia-cs/install
+ install -d -m0755 $(1)/etc
+ $(CP) $(PKG_INSTALL_DIR)/etc/pcmcia $(1)/etc/
+ install -d -m0755 $(1)/usr/sbin
+ $(CP) $(PKG_INSTALL_DIR)/sbin/cardctl $(1)/usr/sbin/
+ $(CP) $(PKG_INSTALL_DIR)/sbin/cardmgr $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,pcmcia-cs))
diff --git a/package/pcmcia-cs/patches/001-config-novatel_merlin_u630.patch b/package/pcmcia-cs/patches/001-config-novatel_merlin_u630.patch
new file mode 100644
index 0000000000..071a697298
--- /dev/null
+++ b/package/pcmcia-cs/patches/001-config-novatel_merlin_u630.patch
@@ -0,0 +1,14 @@
+diff -ruN pcmcia-cs-3.2.8-old/etc/config pcmcia-cs-3.2.8-new/etc/config
+--- pcmcia-cs-3.2.8-old/etc/config 2004-07-16 18:38:25.000000000 +0200
++++ pcmcia-cs-3.2.8-new/etc/config 2005-11-21 08:52:54.000000000 +0100
+@@ -2413,6 +2413,10 @@
+ pci 0x115d, 0x0101
+ bind "serial_cb"
+
++card "Novatel Wireless - Merlin U630 UMTS Modem"
++ manfid 0x00a4, 0x0276
++ bind "serial_cs" to 0, "serial_cs" to 1
++
+ # Include configuration files for add-on drivers
+
+ source ./*.conf
diff --git a/package/ppp/Makefile b/package/ppp/Makefile
new file mode 100644
index 0000000000..b5a317bd03
--- /dev/null
+++ b/package/ppp/Makefile
@@ -0,0 +1,182 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ppp
+PKG_VERSION:=2.4.3
+PKG_RELEASE:=7
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=ftp://ftp.samba.org/pub/ppp/
+PKG_MD5SUM:=848f6c3cafeb6074ffeb293c3af79b7c
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+PKG_BUILDDEP:=libpcap linux-atm
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+define Package/ppp/Default
+ SECTION:=net
+ CATEGORY:=Network
+ URL:=http://ppp.samba.org/
+endef
+
+define Package/ppp
+ $(call Package/ppp/Default)
+ DEFAULT:=y
+ DEPENDS:=+kmod-ppp
+ TITLE:=PPP daemon
+ DESCRIPTION:=\
+ This package contains the PPP (Point-to-Point Protocol) daemon.
+ MENU:=1
+endef
+
+define Package/ppp-mod-pppoa
+ $(call Package/ppp/Default)
+ DEPENDS:=ppp +linux-atm +kmod-pppoa
+ TITLE:=PPPoA plugin
+ DESCRIPTION:=\
+ This package contains a PPPoA (PPP over ATM) plugin for ppp.
+endef
+
+define Package/ppp-mod-pppoe
+ $(call Package/ppp/Default)
+ DEFAULT:=y
+ DEPENDS:=ppp +kmod-pppoe
+ TITLE:=PPPoE plugin
+ DESCRIPTION:=\
+ This package contains a PPPoE (PPP over Ethernet) plugin for ppp.
+endef
+
+define Package/ppp-mod-radius
+ $(call Package/ppp/Default)
+ DEPENDS:=ppp
+ TITLE:=RADIUS plugin
+ DESCRIPTION:=\
+ This package contains a RADIUS (Remote Authentication Dial-In User \\\
+ Service) plugin for ppp.
+endef
+
+define Package/chat
+ $(call Package/ppp/Default)
+ DEPENDS:=ppp
+ TITLE:=Establish conversation with a modem
+ 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:=ppp
+ TITLE:=Read PPP record file
+ DESCRIPTION:=\
+ This package contains an utility to read PPP record file.
+endef
+
+define Package/pppstats
+ $(call Package/ppp/Default)
+ DEPENDS:=ppp
+ TITLE:=Report PPP statistics
+ 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)" \
+)
+endef
+
+define Build/Compile
+ rm -rf $(PKG_INSTALL_DIR)
+ mkdir -p $(PKG_INSTALL_DIR)/usr
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ COPTS="$(TARGET_CFLAGS)" \
+ PRECOMPILED_FILTER=1 \
+ STAGING_DIR="$(STAGING_DIR)" \
+ DESTDIR="$(PKG_INSTALL_DIR)/usr" \
+ all install
+endef
+
+define Package/ppp/install
+ install -d -m0755 $(1)/usr/lib/pppd/$(PKG_VERSION)
+ install -d -m0755 $(1)/usr/sbin
+ install -m0755 $(PKG_INSTALL_DIR)/usr/sbin/pppd $(1)/usr/sbin/
+ install -d -m0755 $(1)/lib/network
+ install -m0755 ./files/ppp.sh $(1)/lib/network/
+ install -d -m0755 $(1)/etc/ppp
+ install -m0600 ./files/etc/ppp/chap-secrets $(1)/etc/ppp/
+ install -m0644 ./files/etc/ppp/filter $(1)/etc/ppp/
+ install -m0755 ./files/etc/ppp/ip-up $(1)/etc/ppp/
+ install -d -m0755 $(1)/etc/ppp/ip-up.d
+ install -m0755 ./files/etc/ppp/ip-down $(1)/etc/ppp/
+ install -d -m0755 $(1)/etc/ppp/ip-down.d
+ install -m0644 ./files/etc/ppp/options $(1)/etc/ppp/
+ ln -sf /tmp/resolv.conf $(1)/etc/ppp/resolv.conf
+endef
+
+define Package/ppp-mod-pppoa/install
+ install -d -m0755 $(1)/usr/lib/pppd/$(PKG_VERSION)
+ install -m0755 $(PKG_INSTALL_DIR)/usr/lib/pppd/$(PKG_VERSION)/pppoatm.so \
+ $(1)/usr/lib/pppd/$(PKG_VERSION)/
+ install -d -m0755 $(1)/lib/network
+ install -m0755 ./files/pppoa.sh $(1)/lib/network/
+endef
+
+define Package/ppp-mod-pppoe/install
+ install -d -m0755 $(1)/usr/lib/pppd/$(PKG_VERSION)
+ install -m0755 $(PKG_INSTALL_DIR)/usr/lib/pppd/$(PKG_VERSION)/rp-pppoe.so \
+ $(1)/usr/lib/pppd/$(PKG_VERSION)/
+ install -d -m0755 $(1)/lib/network
+ install -m0755 ./files/pppoe.sh $(1)/lib/network/
+endef
+
+define Package/ppp-mod-radius/install
+ install -d -m0755 $(1)/usr/lib/pppd/$(PKG_VERSION)
+ install -m0755 $(PKG_INSTALL_DIR)/usr/lib/pppd/$(PKG_VERSION)/radius.so \
+ $(1)/usr/lib/pppd/$(PKG_VERSION)/
+ install -d -m0755 $(1)/etc/ppp
+ install -m0644 ./files/etc/ppp/radius.conf $(1)/etc/ppp/
+ install -d -m0755 $(1)/etc/ppp/radius
+ install -m0644 ./files/etc/ppp/radius/dictionary* \
+ $(1)/etc/ppp/radius/
+ install -m0600 ./files/etc/ppp/radius/servers \
+ $(1)/etc/ppp/radius/
+endef
+
+define Package/chat/install
+ install -d -m0755 $(1)/usr/sbin
+ install -m0755 $(PKG_INSTALL_DIR)/usr/sbin/chat $(1)/usr/sbin/
+endef
+
+define Package/pppdump/install
+ install -d -m0755 $(1)/usr/sbin
+ install -m0755 $(PKG_INSTALL_DIR)/usr/sbin/pppdump $(1)/usr/sbin/
+endef
+
+define Package/pppstats/install
+ install -d -m0755 $(1)/usr/sbin
+ install -m0755 $(PKG_INSTALL_DIR)/usr/sbin/pppstats $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,ppp))
+$(eval $(call BuildPackage,ppp-mod-pppoa))
+$(eval $(call BuildPackage,ppp-mod-pppoe))
+$(eval $(call BuildPackage,ppp-mod-radius))
+$(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 0000000000..6ab76e49e9
--- /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 0000000000..ec72a81a01
--- /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/ip-down b/package/ppp/files/etc/ppp/ip-down
new file mode 100755
index 0000000000..334bcb885a
--- /dev/null
+++ b/package/ppp/files/etc/ppp/ip-down
@@ -0,0 +1,9 @@
+#!/bin/sh
+[ -z "$6" ] || env -i ACTION="ifdown" INTERFACE="$6" PROTO=ppp /sbin/hotplug "iface"
+
+[ -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/etc/ppp/ip-up b/package/ppp/files/etc/ppp/ip-up
new file mode 100755
index 0000000000..34b4b50e15
--- /dev/null
+++ b/package/ppp/files/etc/ppp/ip-up
@@ -0,0 +1,9 @@
+#!/bin/sh
+[ -z "$6" ] || env -i ACTION="ifup" INTERFACE="$6" PROTO=ppp /sbin/hotplug "iface"
+
+[ -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/etc/ppp/options b/package/ppp/files/etc/ppp/options
new file mode 100644
index 0000000000..d74de79306
--- /dev/null
+++ b/package/ppp/files/etc/ppp/options
@@ -0,0 +1,6 @@
+#debug
+noaccomp
+nopcomp
+nocrtscts
+lock
+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 0000000000..0f24a8c7f7
--- /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 0000000000..706d1ce99c
--- /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 0000000000..337d1e1407
--- /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 0000000000..09fdbba63f
--- /dev/null
+++ b/package/ppp/files/etc/ppp/radius/dictionary.microsoft
@@ -0,0 +1,81 @@
+#
+# Microsoft's VSA's, from RFC 2548
+#
+# $Id$
+#
+
+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 0000000000..0d4f0691d0
--- /dev/null
+++ b/package/ppp/files/etc/ppp/radius/servers
@@ -0,0 +1,2 @@
+# SERVER SECRET
+localhost secret
diff --git a/package/ppp/files/ppp.sh b/package/ppp/files/ppp.sh
new file mode 100644
index 0000000000..343223af1b
--- /dev/null
+++ b/package/ppp/files/ppp.sh
@@ -0,0 +1,29 @@
+scan_ppp() {
+ config_get ifname "$1" ifname
+ pppdev="${pppdev:-0}"
+ config_set "$1" ifname "ppp$pppdev"
+ config_set "$1" unit "$pppdev"
+}
+
+start_pppd() {
+ local cfg="$1"; shift
+ config_get device "$cfg" device
+ config_get unit "$cfg" unit
+ config_get username "$cfg" username
+ config_get password "$cfg" password
+ config_get keepalive "$cfg" keepalive
+ interval="${keepalive%%*[, ]}"
+ [ "$interval" != "$keepalive" ] || interval=5
+
+ config_get demand "$cfg" demand
+ [ -n "$demand" ] && echo "nameserver 1.1.1.1" > /tmp/resolv.conf
+ /usr/sbin/pppd "$@" \
+ ${keepalive:+lcp-echo-interval $interval lcp-echo-failure ${keepalive##[, ]*}} \
+ ${demand:+precompiled-active-filter /etc/ppp/filter demand idle }${demand:-persist} \
+ usepeerdns \
+ defaultroute \
+ replacedefaultroute \
+ ${username:+user "$username" password "$password"} \
+ linkname "$cfg" \
+ ipparam "$cfg"
+}
diff --git a/package/ppp/files/pppoa.sh b/package/ppp/files/pppoa.sh
new file mode 100644
index 0000000000..e6530b073e
--- /dev/null
+++ b/package/ppp/files/pppoa.sh
@@ -0,0 +1,20 @@
+scan_pppoa() {
+ scan_ppp "$@"
+}
+
+setup_interface_pppoa() {
+ local iface="$1"
+ local config="$2"
+
+ config_get device "$config" device
+
+ for module in slhc ppp_generic pppoatm; do
+ /sbin/insmod $module 2>&- >&-
+ done
+
+ config_get mtu "$cfg" mtu
+ mtu=${mtu:-1492}
+ start_pppd "$config" \
+ plugin pppoatm.so ${atm_vpi:-8}.${atm_vci:-35} \
+ mtu $mtu mru $mtu
+}
diff --git a/package/ppp/files/pppoe.sh b/package/ppp/files/pppoe.sh
new file mode 100644
index 0000000000..f263caaeef
--- /dev/null
+++ b/package/ppp/files/pppoe.sh
@@ -0,0 +1,21 @@
+scan_pppoe() {
+ scan_ppp "$@"
+}
+
+setup_interface_pppoe() {
+ local iface="$1"
+ local config="$2"
+
+ config_get device "$config" device
+
+ for module in slhc ppp_generic pppox pppoe; do
+ /sbin/insmod $module 2>&- >&-
+ done
+
+ config_get mtu "$cfg" mtu
+ mtu=${mtu:-1480}
+ start_pppd "$config" \
+ plugin rp-pppoe.so \
+ mtu $mtu mru $mtu \
+ "nic-$device"
+}
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 0000000000..56439a6122
--- /dev/null
+++ b/package/ppp/patches/010-use_target_for_configure.patch
@@ -0,0 +1,20 @@
+
+ Use values exported from $(TOPDIR)/rules.mk for determining
+ the target system instead of the host configuration
+
+--- ppp-2.4.3/configure.orig Sat Nov 6 11:36:32 2004
++++ ppp-2.4.3/configure Sun Jun 18 23:40:46 2006
+@@ -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_close_dev_ppp.patch b/package/ppp/patches/100-debian_close_dev_ppp.patch
new file mode 100644
index 0000000000..4e50118e87
--- /dev/null
+++ b/package/ppp/patches/100-debian_close_dev_ppp.patch
@@ -0,0 +1,34 @@
+From: Simon Peter <dn.tlp@gmx.net>
+Subject: Bug#306261: pppd does not properly close /dev/ppp on persist
+
+When using the kernel PPPoE driver, pppd never
+closes /dev/ppp when the link has come down.
+
+It opens superfluous fds to the device each time it re-opens the
+connection, with the unclosed ones falsely reported always ready for
+data by select().
+
+This makes pppd eat up 100% CPU time after the first persist because of
+the always instantly returning select() on the unclosed fds.
+
+The problem also occurs with the upstream version, but does not occur
+when a pty/tty device is used for the ppp connection.
+
+
+diff -u -r ppp-2.4.3/pppd/sys-linux.c ppp-2.4.3/pppd/sys-linux.c
+--- ppp-2.4.3/pppd/sys-linux.c 2005-04-29 20:08:37.000000000 +0200
++++ ppp-2.4.3/pppd/sys-linux.c 2005-04-29 20:07:03.000000000 +0200
+@@ -455,6 +455,13 @@
+ 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/101-debian_ip-up_option.patch b/package/ppp/patches/101-debian_ip-up_option.patch
new file mode 100644
index 0000000000..6033fda247
--- /dev/null
+++ b/package/ppp/patches/101-debian_ip-up_option.patch
@@ -0,0 +1,88 @@
+diff -ruNp ppp-2.4.3.orig/pppd/ipcp.c ppp-2.4.3/pppd/ipcp.c
+--- ppp-2.4.3.orig/pppd/ipcp.c 2004-11-13 13:03:26.000000000 +0100
++++ ppp-2.4.3/pppd/ipcp.c 2005-02-20 18:45:22.241810136 +0100
+@@ -1846,7 +1846,7 @@ ipcp_up(f)
+ */
+ if (ipcp_script_state == s_down && ipcp_script_pid == 0) {
+ ipcp_script_state = s_up;
+- ipcp_script(_PATH_IPUP);
++ ipcp_script(path_ipup);
+ }
+ }
+
+@@ -1896,7 +1896,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);
++ ipcp_script(path_ipdown);
+ }
+ }
+
+@@ -1950,13 +1950,13 @@ ipcp_script_done(arg)
+ case s_up:
+ if (ipcp_fsm[0].state != OPENED) {
+ ipcp_script_state = s_down;
+- ipcp_script(_PATH_IPDOWN);
++ ipcp_script(path_ipdown);
+ }
+ break;
+ case s_down:
+ if (ipcp_fsm[0].state == OPENED) {
+ ipcp_script_state = s_up;
+- ipcp_script(_PATH_IPUP);
++ ipcp_script(path_ipup);
+ }
+ break;
+ }
+diff -ruNp ppp-2.4.3.orig/pppd/main.c ppp-2.4.3/pppd/main.c
+--- ppp-2.4.3.orig/pppd/main.c 2005-02-20 18:46:14.409879384 +0100
++++ ppp-2.4.3/pppd/main.c 2005-02-20 18:45:22.243809832 +0100
+@@ -314,6 +314,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);
+
+diff -ruNp ppp-2.4.3.orig/pppd/options.c ppp-2.4.3/pppd/options.c
+--- ppp-2.4.3.orig/pppd/options.c 2005-02-20 18:46:14.410879232 +0100
++++ ppp-2.4.3/pppd/options.c 2005-02-20 18:46:02.154742448 +0100
+@@ -108,6 +108,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 */
+@@ -276,6 +278,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 },
+diff -ruNp ppp-2.4.3.orig/pppd/pppd.h ppp-2.4.3/pppd/pppd.h
+--- ppp-2.4.3.orig/pppd/pppd.h 2005-02-20 18:46:14.414878624 +0100
++++ ppp-2.4.3/pppd/pppd.h 2005-02-20 18:45:22.247809224 +0100
+@@ -312,6 +312,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/102-debian_pppoe_multicast_pado.patch b/package/ppp/patches/102-debian_pppoe_multicast_pado.patch
new file mode 100644
index 0000000000..ea5275c461
--- /dev/null
+++ b/package/ppp/patches/102-debian_pppoe_multicast_pado.patch
@@ -0,0 +1,14 @@
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/discovery.c ppp-2.4.3/pppd/plugins/rp-pppoe/discovery.c
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/discovery.c 2004-11-04 11:07:37.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/discovery.c 2005-02-24 21:00:11.586697752 +0100
+@@ -365,8 +365,8 @@ waitForPADO(PPPoEConnection *conn, int t
+ if (!packetIsForMe(conn, &packet)) continue;
+
+ if (packet.code == CODE_PADO) {
+- if (NOT_UNICAST(packet.ethHdr.h_source)) {
+- printErr("Ignoring PADO packet from non-unicast MAC address");
++ if (BROADCAST(packet.ethHdr.h_source)) {
++ printErr("Ignoring PADO packet from broadcast MAC address");
+ continue;
+ }
+ parsePacket(&packet, parsePADOTags, &pc);
diff --git a/package/ppp/patches/103-debian_pppoe_cleanup.patch b/package/ppp/patches/103-debian_pppoe_cleanup.patch
new file mode 100644
index 0000000000..8a97a0b2e5
--- /dev/null
+++ b/package/ppp/patches/103-debian_pppoe_cleanup.patch
@@ -0,0 +1,1079 @@
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/common.c ppp-2.4.3/pppd/plugins/rp-pppoe/common.c
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/common.c 2004-02-02 04:36:46.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/common.c 2005-03-11 02:09:19.000000000 +0100
+@@ -18,10 +18,6 @@ static char const RCSID[] =
+
+ #include "pppoe.h"
+
+-#ifdef HAVE_SYSLOG_H
+-#include <syslog.h>
+-#endif
+-
+ #include <string.h>
+ #include <errno.h>
+ #include <stdlib.h>
+@@ -50,17 +46,17 @@ parsePacket(PPPoEPacket *packet, ParseFu
+ UINT16_t tagType, tagLen;
+
+ if (packet->ver != 1) {
+- syslog(LOG_ERR, "Invalid PPPoE version (%d)", (int) packet->ver);
++ error("Invalid PPPoE version (%u)", packet->ver);
+ return -1;
+ }
+ if (packet->type != 1) {
+- syslog(LOG_ERR, "Invalid PPPoE type (%d)", (int) packet->type);
++ error("Invalid PPPoE type (%u)", packet->type);
+ return -1;
+ }
+
+ /* Do some sanity checks on packet */
+ if (len > ETH_DATA_LEN - 6) { /* 6-byte overhead for PPPoE header */
+- syslog(LOG_ERR, "Invalid PPPoE packet length (%u)", len);
++ error("Invalid PPPoE packet length (%u)", len);
+ return -1;
+ }
+
+@@ -76,7 +72,7 @@ parsePacket(PPPoEPacket *packet, ParseFu
+ return 0;
+ }
+ if ((curTag - packet->payload) + tagLen + TAG_HDR_SIZE > len) {
+- syslog(LOG_ERR, "Invalid PPPoE tag length (%u)", tagLen);
++ error("Invalid PPPoE tag length (%u)", tagLen);
+ return -1;
+ }
+ func(tagType, tagLen, curTag+TAG_HDR_SIZE, extra);
+@@ -105,17 +101,17 @@ findTag(PPPoEPacket *packet, UINT16_t ty
+ UINT16_t tagType, tagLen;
+
+ if (packet->ver != 1) {
+- syslog(LOG_ERR, "Invalid PPPoE version (%d)", (int) packet->ver);
++ error("Invalid PPPoE version (%u)", packet->ver);
+ return NULL;
+ }
+ if (packet->type != 1) {
+- syslog(LOG_ERR, "Invalid PPPoE type (%d)", (int) packet->type);
++ error("Invalid PPPoE type (%u)", packet->type);
+ return NULL;
+ }
+
+ /* Do some sanity checks on packet */
+ if (len > ETH_DATA_LEN - 6) { /* 6-byte overhead for PPPoE header */
+- syslog(LOG_ERR, "Invalid PPPoE packet length (%u)", len);
++ error("Invalid PPPoE packet length (%u)", len);
+ return NULL;
+ }
+
+@@ -131,7 +127,7 @@ findTag(PPPoEPacket *packet, UINT16_t ty
+ return NULL;
+ }
+ if ((curTag - packet->payload) + tagLen + TAG_HDR_SIZE > len) {
+- syslog(LOG_ERR, "Invalid PPPoE tag length (%u)", tagLen);
++ error("Invalid PPPoE tag length (%u)", tagLen);
+ return NULL;
+ }
+ if (tagType == type) {
+@@ -143,6 +139,7 @@ findTag(PPPoEPacket *packet, UINT16_t ty
+ return NULL;
+ }
+
++#ifdef unused
+ /**********************************************************************
+ *%FUNCTION: printErr
+ *%ARGUMENTS:
+@@ -158,6 +155,7 @@ printErr(char const *str)
+ fprintf(stderr, "pppoe: %s\n", str);
+ syslog(LOG_ERR, "%s", str);
+ }
++#endif
+
+
+ /**********************************************************************
+@@ -172,7 +170,7 @@ strDup(char const *str)
+ {
+ char *copy = malloc(strlen(str)+1);
+ if (!copy) {
+- rp_fatal("strdup failed");
++ fatal("strdup failed");
+ }
+ strcpy(copy, str);
+ return copy;
+@@ -467,9 +465,10 @@ sendPADT(PPPoEConnection *conn, char con
+ fprintf(conn->debugFile, "\n");
+ fflush(conn->debugFile);
+ }
+- syslog(LOG_INFO,"Sent PADT");
++ info("Sent PADT");
+ }
+
++#ifdef unused
+ /**********************************************************************
+ *%FUNCTION: parseLogErrs
+ *%ARGUMENTS:
+@@ -501,4 +500,5 @@ parseLogErrs(UINT16_t type, UINT16_t len
+ break;
+ }
+ }
++#endif
+
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/discovery.c ppp-2.4.3/pppd/plugins/rp-pppoe/discovery.c
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/discovery.c 2005-03-11 02:12:52.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/discovery.c 2005-03-10 12:24:19.000000000 +0100
+@@ -13,10 +13,6 @@ static char const RCSID[] =
+
+ #include "pppoe.h"
+
+-#ifdef HAVE_SYSLOG_H
+-#include <syslog.h>
+-#endif
+-
+ #include <string.h>
+ #include <stdlib.h>
+ #include <errno.h>
+@@ -167,24 +163,21 @@ parsePADOTags(UINT16_t type, UINT16_t le
+ if (conn->printACNames) {
+ printf("Got a Service-Name-Error tag: %.*s\n", (int) len, data);
+ } else {
+- syslog(LOG_ERR, "PADO: Service-Name-Error: %.*s", (int) len, data);
+- exit(1);
++ fatal("PADO: Service-Name-Error: %.*s", (int) len, data);
+ }
+ break;
+ case TAG_AC_SYSTEM_ERROR:
+ if (conn->printACNames) {
+ printf("Got a System-Error tag: %.*s\n", (int) len, data);
+ } else {
+- syslog(LOG_ERR, "PADO: System-Error: %.*s", (int) len, data);
+- exit(1);
++ fatal("PADO: System-Error: %.*s", (int) len, data);
+ }
+ break;
+ case TAG_GENERIC_ERROR:
+ if (conn->printACNames) {
+ printf("Got a Generic-Error tag: %.*s\n", (int) len, data);
+ } else {
+- syslog(LOG_ERR, "PADO: Generic-Error: %.*s", (int) len, data);
+- exit(1);
++ fatal("PADO: Generic-Error: %.*s", (int) len, data);
+ }
+ break;
+ }
+@@ -209,20 +202,14 @@ parsePADSTags(UINT16_t type, UINT16_t le
+ PPPoEConnection *conn = (PPPoEConnection *) extra;
+ switch(type) {
+ case TAG_SERVICE_NAME:
+- syslog(LOG_DEBUG, "PADS: Service-Name: '%.*s'", (int) len, data);
++ dbglog("PADS: Service-Name: '%.*s'", (int) len, data);
+ break;
+ case TAG_SERVICE_NAME_ERROR:
+- syslog(LOG_ERR, "PADS: Service-Name-Error: %.*s", (int) len, data);
+- fprintf(stderr, "PADS: Service-Name-Error: %.*s\n", (int) len, data);
+- exit(1);
++ fatal("PADS: Service-Name-Error: %.*s", (int) len, data);
+ case TAG_AC_SYSTEM_ERROR:
+- syslog(LOG_ERR, "PADS: System-Error: %.*s", (int) len, data);
+- fprintf(stderr, "PADS: System-Error: %.*s\n", (int) len, data);
+- exit(1);
++ fatal("PADS: System-Error: %.*s", (int) len, data);
+ case TAG_GENERIC_ERROR:
+- syslog(LOG_ERR, "PADS: Generic-Error: %.*s", (int) len, data);
+- fprintf(stderr, "PADS: Generic-Error: %.*s\n", (int) len, data);
+- exit(1);
++ fatal("PADS: Generic-Error: %.*s", (int) len, data);
+ case TAG_RELAY_SESSION_ID:
+ conn->relayId.type = htons(type);
+ conn->relayId.length = htons(len);
+@@ -336,7 +323,7 @@ waitForPADO(PPPoEConnection *conn, int t
+ if (r >= 0 || errno != EINTR) break;
+ }
+ if (r < 0) {
+- fatalSys("select (waitForPADO)");
++ fatal("waitForPADO: select: %m");
+ }
+ if (r == 0) return; /* Timed out */
+ }
+@@ -346,8 +333,7 @@ waitForPADO(PPPoEConnection *conn, int t
+
+ /* Check length */
+ if (ntohs(packet.length) + HDR_SIZE > len) {
+- syslog(LOG_ERR, "Bogus PPPoE length field (%u)",
+- (unsigned int) ntohs(packet.length));
++ error("Bogus PPPoE length field (%u)", ntohs(packet.length));
+ continue;
+ }
+
+@@ -366,16 +352,16 @@ waitForPADO(PPPoEConnection *conn, int t
+
+ if (packet.code == CODE_PADO) {
+ if (BROADCAST(packet.ethHdr.h_source)) {
+- printErr("Ignoring PADO packet from broadcast MAC address");
++ error("Ignoring PADO packet from broadcast MAC address");
+ continue;
+ }
+ parsePacket(&packet, parsePADOTags, &pc);
+ if (!pc.seenACName) {
+- printErr("Ignoring PADO packet with no AC-Name tag");
++ error("Ignoring PADO packet with no AC-Name tag");
+ continue;
+ }
+ if (!pc.seenServiceName) {
+- printErr("Ignoring PADO packet with no Service-Name tag");
++ error("Ignoring PADO packet with no Service-Name tag");
+ continue;
+ }
+ conn->numPADOs++;
+@@ -513,7 +499,7 @@ waitForPADS(PPPoEConnection *conn, int t
+ if (r >= 0 || errno != EINTR) break;
+ }
+ if (r < 0) {
+- fatalSys("select (waitForPADS)");
++ fatal("waitForPADS: select: %m");
+ }
+ if (r == 0) return;
+ }
+@@ -523,8 +509,7 @@ waitForPADS(PPPoEConnection *conn, int t
+
+ /* Check length */
+ if (ntohs(packet.length) + HDR_SIZE > len) {
+- syslog(LOG_ERR, "Bogus PPPoE length field (%u)",
+- (unsigned int) ntohs(packet.length));
++ error("Bogus PPPoE length field (%u)", ntohs(packet.length));
+ continue;
+ }
+
+@@ -556,11 +541,12 @@ waitForPADS(PPPoEConnection *conn, int t
+ /* Don't bother with ntohs; we'll just end up converting it back... */
+ conn->session = packet.session;
+
+- syslog(LOG_INFO, "PPP session is %d", (int) ntohs(conn->session));
++ info("PPP session is %d", ntohs(conn->session));
+
+ /* RFC 2516 says session id MUST NOT be zero or 0xFFFF */
+ if (ntohs(conn->session) == 0 || ntohs(conn->session) == 0xFFFF) {
+- syslog(LOG_ERR, "Access concentrator used a session value of %x -- the AC is violating RFC 2516", (unsigned int) ntohs(conn->session));
++ error("Access concentrator used a session value of 0x%x"
++ " -- the AC is violating RFC 2516", ntohs(conn->session));
+ }
+ }
+
+@@ -620,7 +606,7 @@ discovery(PPPoEConnection *conn)
+
+ /* If we're only printing access concentrator names, we're done */
+ if (conn->printACNames) {
+- die(0);
++ exit(0);
+ }
+
+ timeout = PADI_TIMEOUT;
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/if.c ppp-2.4.3/pppd/plugins/rp-pppoe/if.c
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/if.c 2001-12-14 03:55:20.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/if.c 2005-03-10 13:32:43.000000000 +0100
+@@ -40,10 +40,6 @@ static char const RCSID[] =
+ #include <sys/ioctl.h>
+ #endif
+
+-#ifdef HAVE_SYSLOG_H
+-#include <syslog.h>
+-#endif
+-
+ #include <errno.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -127,7 +123,7 @@ etherType(PPPoEPacket *packet)
+ {
+ UINT16_t type = (UINT16_t) ntohs(packet->ethHdr.h_proto);
+ if (type != Eth_PPPOE_Discovery && type != Eth_PPPOE_Session) {
+- syslog(LOG_ERR, "Invalid ether type 0x%x", type);
++ error("Invalid ethernet type 0x%x", type);
+ }
+ return type;
+ }
+@@ -156,7 +152,7 @@ getHWaddr(int sock, char const *ifname,
+ ifc.ifc_len = sizeof(inbuf);
+ ifc.ifc_buf = inbuf;
+ if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
+- fatalSys("SIOCGIFCONF");
++ fatal("SIOCGIFCONF: %m");
+ }
+ ifr = ifc.ifc_req;
+ ifreq.ifr_name[0] = '\0';
+@@ -172,9 +168,7 @@ getHWaddr(int sock, char const *ifname,
+ (sdl->sdl_alen == ETH_ALEN) &&
+ !strncmp(ifname, ifr->ifr_name, sizeof(ifr->ifr_name))) {
+ if (found) {
+- char buffer[256];
+- sprintf(buffer, "interface %.16s has more than one ethernet address", ifname);
+- rp_fatal(buffer);
++ fatal("interface %s has more than one ethernet address", ifname);
+ } else {
+ found = 1;
+ memcpy(hwaddr, LLADDR(sdl), ETH_ALEN);
+@@ -183,9 +177,7 @@ getHWaddr(int sock, char const *ifname,
+ }
+ }
+ if (!found) {
+- char buffer[256];
+- sprintf(buffer, "interface %.16s has no ethernet address", ifname);
+- rp_fatal(buffer);
++ fatal("interface %s has no ethernet address", ifname);
+ }
+ }
+
+@@ -252,7 +244,7 @@ initFilter(int fd, UINT16_t type, unsign
+
+ /* Apply the filter */
+ if (ioctl(fd, BIOCSETF, &bpfProgram) < 0) {
+- fatalSys("ioctl(BIOCSETF)");
++ fatal("ioctl(BIOCSETF): %m");
+ }
+ }
+ }
+@@ -298,42 +290,36 @@ openInterface(char const *ifname, UINT16
+ if (fd < 0) {
+ switch (errno) {
+ case EACCES: /* permission denied */
+- {
+- char buffer[256];
+- sprintf(buffer, "Cannot open %.32s -- pppoe must be run as root.", bpfName);
+- rp_fatal(buffer);
+- }
++ fatal("Cannot open %s -- pppoe must be run as root.", bpfName);
+ break;
+ case EBUSY:
+ case ENOENT: /* no such file */
+ if (i == 0) {
+- rp_fatal("No /dev/bpf* devices (check your kernel configuration for BPF support)");
++ fatal("No /dev/bpf* devices (check your kernel configuration for BPF support)");
+ } else {
+- rp_fatal("All /dev/bpf* devices are in use");
++ fatal("All /dev/bpf* devices are in use");
+ }
+ break;
+ }
+- fatalSys(bpfName);
++ fatal("%s: %m", bpfName);
+ }
+
+ if ((sock = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) {
+- fatalSys("socket");
++ fatal("socket: %m");
+ }
+
+ /* Check that the interface is up */
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
+- fatalSys("ioctl(SIOCGIFFLAGS)");
++ fatal("ioctl(SIOCGIFFLAGS): %m");
+ }
+ if ((ifr.ifr_flags & IFF_UP) == 0) {
+- char buffer[256];
+- sprintf(buffer, "Interface %.16s is not up\n", ifname);
+- rp_fatal(buffer);
++ fatal("Interface %s is not up", ifname);
+ }
+
+ /* Fill in hardware address and initialize the packet filter rules */
+ if (hwaddr == NULL) {
+- rp_fatal("openInterface: no hwaddr arg.");
++ fatal("openInterface: no hwaddr arg.");
+ }
+ getHWaddr(sock, ifname, hwaddr);
+ initFilter(fd, type, hwaddr);
+@@ -342,58 +328,52 @@ openInterface(char const *ifname, UINT16
+ #if !defined(__OpenBSD__)
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(sock, SIOCGIFMTU, &ifr) < 0) {
+- fatalSys("ioctl(SIOCGIFMTU)");
++ fatal("ioctl(SIOCGIFMTU): %m");
+ }
+ if (ifr.ifr_mtu < ETH_DATA_LEN) {
+- char buffer[256];
+- sprintf(buffer, "Interface %.16s has MTU of %d -- should be %d. You may have serious connection problems.",
++ error("Interface %s has MTU of %d -- should be %d."
++ " You may have serious connection problems.",
+ ifname, ifr.ifr_mtu, ETH_DATA_LEN);
+- printErr(buffer);
+ }
+ #endif
+
+ /* done with the socket */
+ if (close(sock) < 0) {
+- fatalSys("close");
++ fatal("close: %m");
+ }
+
+ /* Check the BPF version number */
+ if (ioctl(fd, BIOCVERSION, &bpf_ver) < 0) {
+- fatalSys("ioctl(BIOCVERSION)");
++ fatal("ioctl(BIOCVERSION): %m");
+ }
+ if ((bpf_ver.bv_major != BPF_MAJOR_VERSION) ||
+ (bpf_ver.bv_minor < BPF_MINOR_VERSION)) {
+- char buffer[256];
+- sprintf(buffer, "Unsupported BPF version: %d.%d (kernel: %d.%d)",
++ fatal("Unsupported BPF version: %d.%d (kernel: %d.%d)",
+ BPF_MAJOR_VERSION, BPF_MINOR_VERSION,
+ bpf_ver.bv_major, bpf_ver.bv_minor);
+- rp_fatal(buffer);
+ }
+
+ /* allocate a receive packet buffer */
+ if (ioctl(fd, BIOCGBLEN, &bpfLength) < 0) {
+- fatalSys("ioctl(BIOCGBLEN)");
++ fatal("ioctl(BIOCGBLEN): %m");
+ }
+ if (!(bpfBuffer = (unsigned char *) malloc(bpfLength))) {
+- rp_fatal("malloc");
++ fatal("malloc");
+ }
+
+ /* reads should return as soon as there is a packet available */
+ optval = 1;
+ if (ioctl(fd, BIOCIMMEDIATE, &optval) < 0) {
+- fatalSys("ioctl(BIOCIMMEDIATE)");
++ fatal("ioctl(BIOCIMMEDIATE): %m");
+ }
+
+ /* Bind the interface to the filter */
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(fd, BIOCSETIF, &ifr) < 0) {
+- char buffer[256];
+- sprintf(buffer, "ioctl(BIOCSETIF) can't select interface %.16s",
+- ifname);
+- rp_fatal(buffer);
++ fatal("ioctl(BIOCSETIF) can't select interface %s: %m", ifname);
+ }
+
+- syslog(LOG_INFO, "Interface=%.16s HWaddr=%02X:%02X:%02X:%02X:%02X:%02X Device=%.32s Buffer size=%d",
++ info("Interface=%s HWaddr=%02X:%02X:%02X:%02X:%02X:%02X Device=%s Buffer size=%d",
+ ifname,
+ hwaddr[0], hwaddr[1], hwaddr[2],
+ hwaddr[3], hwaddr[4], hwaddr[5],
+@@ -442,48 +422,41 @@ openInterface(char const *ifname, UINT16
+ if ((fd = socket(domain, stype, htons(type))) < 0) {
+ /* Give a more helpful message for the common error case */
+ if (errno == EPERM) {
+- rp_fatal("Cannot create raw socket -- pppoe must be run as root.");
++ fatal("Cannot create raw socket -- pppoe must be run as root.");
+ }
+- fatalSys("socket");
++ fatal("cannot create the raw socket: %m");
+ }
+
+ if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) < 0) {
+- fatalSys("setsockopt");
++ fatal("setsockopt(SOL_SOCKET, SO_BROADCAST): %m");
+ }
+
+ /* Fill in hardware address */
+ if (hwaddr) {
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+- if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
+- fatalSys("ioctl(SIOCGIFHWADDR)");
+- }
++ if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0)
++ fatal("ioctl(SIOCGIFHWADDR): %m");
+ memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+ #ifdef ARPHRD_ETHER
+ if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
+- char buffer[256];
+- sprintf(buffer, "Interface %.16s is not Ethernet", ifname);
+- rp_fatal(buffer);
++ fatal("Interface %s is not Ethernet", ifname);
+ }
+ #endif
+ if (NOT_UNICAST(hwaddr)) {
+- char buffer[256];
+- sprintf(buffer,
+- "Interface %.16s has broadcast/multicast MAC address??",
++ fatal("Interface %s has broadcast/multicast MAC address",
+ ifname);
+- rp_fatal(buffer);
+ }
+ }
+
+ /* Sanity check on MTU */
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(fd, SIOCGIFMTU, &ifr) < 0) {
+- fatalSys("ioctl(SIOCGIFMTU)");
++ fatal("ioctl(SIOCGIFMTU): %m");
+ }
+ if (ifr.ifr_mtu < ETH_DATA_LEN) {
+- char buffer[256];
+- sprintf(buffer, "Interface %.16s has MTU of %d -- should be %d. You may have serious connection problems.",
++ error("Interface %s has MTU of %d -- should be %d."
++ " You may have serious connection problems.",
+ ifname, ifr.ifr_mtu, ETH_DATA_LEN);
+- printErr(buffer);
+ }
+
+ #ifdef HAVE_STRUCT_SOCKADDR_LL
+@@ -493,7 +466,7 @@ openInterface(char const *ifname, UINT16
+
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
+- fatalSys("ioctl(SIOCFIGINDEX): Could not get interface index");
++ fatal("ioctl(SIOCFIGINDEX): Could not get interface index: %m");
+ }
+ sa.sll_ifindex = ifr.ifr_ifindex;
+
+@@ -503,7 +476,7 @@ openInterface(char const *ifname, UINT16
+
+ /* We're only interested in packets on specified interface */
+ if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
+- fatalSys("bind");
++ fatal("bind: %m");
+ }
+
+ return fd;
+@@ -527,13 +500,11 @@ sendPacket(PPPoEConnection *conn, int so
+ {
+ #if defined(USE_BPF)
+ if (write(sock, pkt, size) < 0) {
+- sysErr("write (sendPacket)");
+- return -1;
++ fatal("sendPacket: write: %m");
+ }
+ #elif defined(HAVE_STRUCT_SOCKADDR_LL)
+ if (send(sock, pkt, size, 0) < 0) {
+- sysErr("send (sendPacket)");
+- return -1;
++ fatal("sendPacket: send: %m");
+ }
+ #else
+ #ifdef USE_DLPI
+@@ -577,12 +548,11 @@ sendPacket(PPPoEConnection *conn, int so
+ struct sockaddr sa;
+
+ if (!conn) {
+- rp_fatal("relay and server not supported on Linux 2.0 kernels");
++ fatal("relay and server not supported on Linux 2.0 kernels");
+ }
+ strcpy(sa.sa_data, conn->ifName);
+ if (sendto(sock, pkt, size, 0, &sa, sizeof(sa)) < 0) {
+- sysErr("sendto (sendPacket)");
+- return -1;
++ fatal("sendPacket: sendto: %m");
+ }
+ #endif
+ #endif
+@@ -632,26 +602,24 @@ receivePacket(int sock, PPPoEPacket *pkt
+ if (bpfSize <= 0) {
+ bpfOffset = 0;
+ if ((bpfSize = read(sock, bpfBuffer, bpfLength)) < 0) {
+- sysErr("read (receivePacket)");
+- return -1;
++ fatal("receivePacket: read: %m");
+ }
+ }
+ if (bpfSize < sizeof(hdr)) {
+- syslog(LOG_ERR, "Truncated bpf packet header: len=%d", bpfSize);
++ error("Truncated bpf packet header: len=%d", bpfSize);
+ clearPacketHeader(pkt); /* resets bpfSize and bpfOffset */
+ return 0;
+ }
+ memcpy(&hdr, bpfBuffer + bpfOffset, sizeof(hdr));
+ if (hdr.bh_caplen != hdr.bh_datalen) {
+- syslog(LOG_ERR, "Truncated bpf packet: caplen=%d, datalen=%d",
++ error("Truncated bpf packet: caplen=%d, datalen=%d",
+ hdr.bh_caplen, hdr.bh_datalen);
+ clearPacketHeader(pkt); /* resets bpfSize and bpfOffset */
+ return 0;
+ }
+ seglen = hdr.bh_hdrlen + hdr.bh_caplen;
+ if (seglen > bpfSize) {
+- syslog(LOG_ERR, "Truncated bpf packet: seglen=%d, bpfSize=%d",
+- seglen, bpfSize);
++ error("Truncated bpf packet: seglen=%d, bpfSize=%d", seglen, bpfSize);
+ clearPacketHeader(pkt); /* resets bpfSize and bpfOffset */
+ return 0;
+ }
+@@ -676,16 +644,14 @@ receivePacket(int sock, PPPoEPacket *pkt
+ data.len = 0;
+
+ if ((retval = getmsg(sock, NULL, &data, &flags)) < 0) {
+- sysErr("read (receivePacket)");
+- return -1;
++ fatal("receivePacket: getmsg: %m");
+ }
+
+ *size = data.len;
+
+ #else
+ if ((*size = recv(sock, pkt, sizeof(PPPoEPacket), 0)) < 0) {
+- sysErr("recv (receivePacket)");
+- return -1;
++ fatal("receivePacket: recv: %m");
+ }
+ #endif
+ #endif
+@@ -716,7 +682,7 @@ openInterface(char const *ifname, UINT16
+ int ppa;
+
+ if(strlen(ifname) > PATH_MAX) {
+- rp_fatal("socket: string to long");
++ fatal("openInterface: interface name too long");
+ }
+
+ ppa = atoi(&ifname[strlen(ifname)-1]);
+@@ -729,9 +695,9 @@ openInterface(char const *ifname, UINT16
+ if (( fd = open(base_dev, O_RDWR)) < 0) {
+ /* Give a more helpful message for the common error case */
+ if (errno == EPERM) {
+- rp_fatal("Cannot create raw socket -- pppoe must be run as root.");
++ fatal("Cannot create raw socket -- pppoe must be run as root.");
+ }
+- fatalSys("socket");
++ fatal("open(%s): %m", base_dev);
+ }
+
+ /* rearranged order of DLPI code - delphys 20010803 */
+@@ -747,17 +713,18 @@ openInterface(char const *ifname, UINT16
+ dl_abssaplen = ABS(dlp->info_ack.dl_sap_length);
+ dl_saplen = dlp->info_ack.dl_sap_length;
+ if (ETHERADDRL != (dlp->info_ack.dl_addr_length - dl_abssaplen))
+- fatalSys("invalid destination physical address length");
++ fatal("invalid destination physical address length");
+ dl_addrlen = dl_abssaplen + ETHERADDRL;
+
+ /* ethernet address retrieved as part of DL_INFO_ACK - delphys 20010803 */
+ memcpy(hwaddr, (u_char*)((char*)(dlp) + (int)(dlp->info_ack.dl_addr_offset)), ETHERADDRL);
+
+ if ( strioctl(fd, DLIOCRAW, -1, 0, NULL) < 0 ) {
+- fatalSys("DLIOCRAW");
++ fatal("DLIOCRAW: %m");
+ }
+
+- if (ioctl(fd, I_FLUSH, FLUSHR) < 0) fatalSys("I_FLUSH");
++ if (ioctl(fd, I_FLUSH, FLUSHR) < 0)
++ fatal("I_FLUSH: %m");
+
+ return fd;
+ }
+@@ -780,7 +747,7 @@ void dlpromisconreq(int fd, u_long level
+ flags = 0;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+- fatalSys("dlpromiscon: putmsg");
++ fatal("dlpromiscon: putmsg: %m");
+
+ }
+
+@@ -799,7 +766,7 @@ void dlinforeq(int fd)
+ flags = RS_HIPRI;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+- fatalSys("dlinforeq: putmsg");
++ fatal("dlinforeq: putmsg: %m");
+ }
+
+ void dlunitdatareq(int fd, u_char *addrp, int addrlen, u_long minpri, u_long maxpri, u_char *datap, int datalen)
+@@ -827,7 +794,7 @@ void dlunitdatareq(int fd, u_char *addrp
+ data.buf = (char *) datap;
+
+ if (putmsg(fd, &ctl, &data, 0) < 0)
+- fatalSys("dlunitdatareq: putmsg");
++ fatal("dlunitdatareq: putmsg: %m");
+ }
+
+ void dlinfoack(int fd, char *bufp)
+@@ -847,18 +814,14 @@ void dlinfoack(int fd, char *bufp)
+ expecting(DL_INFO_ACK, dlp);
+
+ if (ctl.len < sizeof (dl_info_ack_t)) {
+- char buffer[256];
+- sprintf(buffer, "dlinfoack: response ctl.len too short: %d", ctl.len);
+- rp_fatal(buffer);
++ fatal("dlinfoack: response ctl.len too short: %d", ctl.len);
+ }
+
+ if (flags != RS_HIPRI)
+- rp_fatal("dlinfoack: DL_INFO_ACK was not M_PCPROTO");
++ fatal("dlinfoack: DL_INFO_ACK was not M_PCPROTO");
+
+ if (ctl.len < sizeof (dl_info_ack_t)) {
+- char buffer[256];
+- sprintf(buffer, "dlinfoack: short response ctl.len: %d", ctl.len);
+- rp_fatal(buffer);
++ fatal("dlinfoack: short response ctl.len: %d", ctl.len);
+ }
+ }
+
+@@ -882,7 +845,7 @@ void dlbindreq(int fd, u_long sap, u_lon
+ flags = 0;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+- fatalSys("dlbindreq: putmsg");
++ fatal("dlbindreq: putmsg: %m");
+ }
+
+ void dlattachreq(int fd, u_long ppa)
+@@ -901,7 +864,7 @@ void dlattachreq(int fd, u_long ppa)
+ flags = 0;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+- fatalSys("dlattachreq: putmsg");
++ fatal("dlattachreq: putmsg: %m");
+ }
+
+ void dlokack(int fd, char *bufp)
+@@ -921,18 +884,14 @@ void dlokack(int fd, char *bufp)
+ expecting(DL_OK_ACK, dlp);
+
+ if (ctl.len < sizeof (dl_ok_ack_t)) {
+- char buffer[256];
+- sprintf(buffer, "dlokack: response ctl.len too short: %d", ctl.len);
+- rp_fatal(buffer);
++ fatal("dlokack: response ctl.len too short: %d", ctl.len);
+ }
+
+ if (flags != RS_HIPRI)
+- rp_fatal("dlokack: DL_OK_ACK was not M_PCPROTO");
++ fatal("dlokack: DL_OK_ACK was not M_PCPROTO");
+
+ if (ctl.len < sizeof (dl_ok_ack_t)) {
+- char buffer[256];
+- sprintf(buffer, "dlokack: short response ctl.len: %d", ctl.len);
+- rp_fatal(buffer);
++ fatal("dlokack: short response ctl.len: %d", ctl.len);
+ }
+ }
+
+@@ -953,12 +912,10 @@ void dlbindack(int fd, char *bufp)
+ expecting(DL_BIND_ACK, dlp);
+
+ if (flags != RS_HIPRI)
+- rp_fatal("dlbindack: DL_OK_ACK was not M_PCPROTO");
++ fatal("dlbindack: DL_OK_ACK was not M_PCPROTO");
+
+ if (ctl.len < sizeof (dl_bind_ack_t)) {
+- char buffer[256];
+- sprintf(buffer, "dlbindack: short response ctl.len: %d", ctl.len);
+- rp_fatal(buffer);
++ fatal("dlbindack: short response ctl.len: %d", ctl.len);
+ }
+ }
+
+@@ -989,8 +946,7 @@ void strgetmsg(int fd, struct strbuf *ct
+ */
+ (void) signal(SIGALRM, sigalrm);
+ if (alarm(MAXWAIT) < 0) {
+- (void) sprintf(errmsg, "%s: alarm", caller);
+- fatalSys(errmsg);
++ fatal("%s: alarm", caller);
+ }
+
+ /*
+@@ -998,61 +954,48 @@ void strgetmsg(int fd, struct strbuf *ct
+ */
+ *flagsp = 0;
+ if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) {
+- (void) sprintf(errmsg, "%s: getmsg", caller);
+- fatalSys(errmsg);
++ fatal(errmsg, "%s: getmsg: %m", caller);
+ }
+
+ /*
+ * Stop timer.
+ */
+ if (alarm(0) < 0) {
+- (void) sprintf(errmsg, "%s: alarm", caller);
+- fatalSys(errmsg);
++ fatal("%s: alarm", caller);
+ }
+
+ /*
+ * Check for MOREDATA and/or MORECTL.
+ */
+ if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA)) {
+- char buffer[256];
+- sprintf(buffer, "%s: MORECTL|MOREDATA", caller);
+- rp_fatal(buffer);
++ fatal("%s: MORECTL|MOREDATA", caller);
+ }
+
+ if (rc & MORECTL) {
+- char buffer[256];
+- sprintf(buffer, "%s: MORECTL", caller);
+- rp_fatal(buffer);
++ fatal("%s: MORECTL", caller);
+ }
+
+ if (rc & MOREDATA) {
+- char buffer[256];
+- sprintf(buffer, "%s: MOREDATA", caller);
+- rp_fatal(buffer);
++ fatal("%s: MOREDATA", caller);
+ }
+
+ /*
+ * Check for at least sizeof (long) control data portion.
+ */
+ if (ctlp->len < sizeof (long)) {
+- char buffer[256];
+- sprintf(buffer, "getmsg: control portion length < sizeof (long): %d", ctlp->len);
+- rp_fatal(buffer);
++ fatal("getmsg: control portion length < sizeof (long): %d", ctlp->len);
+ }
+ }
+
+ void sigalrm(int sig)
+ {
+- (void) rp_fatal("sigalrm: TIMEOUT");
++ fatal("sigalrm: TIMEOUT");
+ }
+
+ void expecting(int prim, union DL_primitives *dlp)
+ {
+ if (dlp->dl_primitive != (u_long)prim) {
+- char buffer[256];
+- sprintf(buffer, "expected %s got %s", dlprim(prim), dlprim(dlp->dl_primitive));
+- rp_fatal(buffer);
+- exit(1);
++ fatal("expected %s got %s", dlprim(prim), dlprim(dlp->dl_primitive));
+ }
+ }
+
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/Makefile.linux ppp-2.4.3/pppd/plugins/rp-pppoe/Makefile.linux
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/Makefile.linux 2004-11-14 08:58:37.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/Makefile.linux 2005-03-11 01:48:27.000000000 +0100
+@@ -28,8 +28,8 @@ COPTS=-O2 -g
+ CFLAGS=$(COPTS) -I../../../include/linux
+ all: rp-pppoe.so pppoe-discovery
+
+-pppoe-discovery: libplugin.a pppoe-discovery.o
+- $(CC) -o pppoe-discovery pppoe-discovery.o libplugin.a
++pppoe-discovery: pppoe-discovery.o utils.o libplugin.a
++ $(CC) -o pppoe-discovery pppoe-discovery.o utils.o libplugin.a
+
+ pppoe-discovery.o: pppoe-discovery.c
+ $(CC) $(CFLAGS) '-DVERSION="$(VERSION)"' -c -o pppoe-discovery.o pppoe-discovery.c
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/plugin.c ppp-2.4.3/pppd/plugins/rp-pppoe/plugin.c
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/plugin.c 2004-11-04 11:07:37.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/plugin.c 2005-03-11 02:12:39.000000000 +0100
+@@ -35,7 +35,6 @@ static char const RCSID[] =
+ #include "pppd/pathnames.h"
+
+ #include <linux/types.h>
+-#include <syslog.h>
+ #include <sys/ioctl.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+@@ -173,10 +172,8 @@ PPPOEConnectDevice(void)
+ (unsigned) conn->peerEth[5]);
+
+ if (connect(conn->sessionSocket, (struct sockaddr *) &sp,
+- sizeof(struct sockaddr_pppox)) < 0) {
++ sizeof(struct sockaddr_pppox)) < 0)
+ fatal("Failed to connect PPPoE socket: %d %m", errno);
+- return -1;
+- }
+
+ return conn->sessionSocket;
+ }
+@@ -365,11 +362,9 @@ plugin_init(void)
+ }
+
+ add_options(Options);
+-
+- info("RP-PPPoE plugin version %s compiled against pppd %s",
+- RP_VERSION, VERSION);
+ }
+
++#ifdef unused
+ /**********************************************************************
+ *%FUNCTION: fatalSys
+ *%ARGUMENTS:
+@@ -423,6 +418,7 @@ sysErr(char const *str)
+ {
+ rp_fatal(str);
+ }
++#endif
+
+
+ struct channel pppoe_channel = {
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/pppoe-discovery.c ppp-2.4.3/pppd/plugins/rp-pppoe/pppoe-discovery.c
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/pppoe-discovery.c 2004-11-13 13:12:05.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/pppoe-discovery.c 2005-03-11 02:06:13.000000000 +0100
+@@ -17,14 +17,8 @@
+
+ #include "pppoe.h"
+
+-char *xstrdup(const char *s);
+ void usage(void);
+
+-void die(int status)
+-{
+- exit(status);
+-}
+-
+ int main(int argc, char *argv[])
+ {
+ int opt;
+@@ -32,17 +26,17 @@ int main(int argc, char *argv[])
+
+ conn = malloc(sizeof(PPPoEConnection));
+ if (!conn)
+- fatalSys("malloc");
++ fatal("malloc");
+
+ memset(conn, 0, sizeof(PPPoEConnection));
+
+ while ((opt = getopt(argc, argv, "I:D:VUAS:C:h")) > 0) {
+ switch(opt) {
+ case 'S':
+- conn->serviceName = xstrdup(optarg);
++ conn->serviceName = strDup(optarg);
+ break;
+ case 'C':
+- conn->acName = xstrdup(optarg);
++ conn->acName = strDup(optarg);
+ break;
+ case 'U':
+ conn->useHostUniq = 1;
+@@ -57,7 +51,7 @@ int main(int argc, char *argv[])
+ fprintf(conn->debugFile, "pppoe-discovery %s\n", VERSION);
+ break;
+ case 'I':
+- conn->ifName = xstrdup(optarg);
++ conn->ifName = strDup(optarg);
+ break;
+ case 'A':
+ /* this is the default */
+@@ -74,7 +68,7 @@ int main(int argc, char *argv[])
+
+ /* default interface name */
+ if (!conn->ifName)
+- conn->ifName = strdup("eth0");
++ conn->ifName = strDup("eth0");
+
+ conn->discoverySocket = -1;
+ conn->sessionSocket = -1;
+@@ -84,39 +78,6 @@ int main(int argc, char *argv[])
+ exit(0);
+ }
+
+-void rp_fatal(char const *str)
+-{
+- char buf[1024];
+-
+- printErr(str);
+- sprintf(buf, "pppoe-discovery: %.256s", str);
+- exit(1);
+-}
+-
+-void fatalSys(char const *str)
+-{
+- char buf[1024];
+- int i = errno;
+-
+- sprintf(buf, "%.256s: %.256s", str, strerror(i));
+- printErr(buf);
+- sprintf(buf, "pppoe-discovery: %.256s: %.256s", str, strerror(i));
+- exit(1);
+-}
+-
+-void sysErr(char const *str)
+-{
+- rp_fatal(str);
+-}
+-
+-char *xstrdup(const char *s)
+-{
+- register char *ret = strdup(s);
+- if (!ret)
+- sysErr("strdup");
+- return ret;
+-}
+-
+ void usage(void)
+ {
+ fprintf(stderr, "Usage: pppoe-discovery [options]\n");
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/pppoe.h ppp-2.4.3/pppd/plugins/rp-pppoe/pppoe.h
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/pppoe.h 2004-11-04 11:07:37.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/pppoe.h 2005-03-11 02:08:00.000000000 +0100
+@@ -307,12 +307,18 @@ void discovery(PPPoEConnection *conn);
+ unsigned char *findTag(PPPoEPacket *packet, UINT16_t tagType,
+ PPPoETag *tag);
+
++void dbglog(char *, ...); /* log a debug message */
++void info(char *, ...); /* log an informational message */
++void warn(char *, ...); /* log a warning message */
++void error(char *, ...); /* log an error message */
++void fatal(char *, ...); /* log an error message and die(1) */
++
+ #define SET_STRING(var, val) do { if (var) free(var); var = strDup(val); } while(0);
+
+ #define CHECK_ROOM(cursor, start, len) \
+ do {\
+ if (((cursor)-(start))+(len) > MAX_PPPOE_PAYLOAD) { \
+- syslog(LOG_ERR, "Would create too-long packet"); \
++ error("Would create too-long packet"); \
+ return; \
+ } \
+ } while(0)
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/utils.c ppp-2.4.3/pppd/plugins/rp-pppoe/utils.c
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/utils.c 1970-01-01 01:00:00.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/utils.c 2005-03-11 02:07:57.000000000 +0100
+@@ -0,0 +1,62 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <stdarg.h>
++#include <syslog.h>
++
++void dbglog(const char *fmt, ...)
++{
++ va_list ap;
++
++ va_start(ap, fmt);
++ vsyslog(LOG_DEBUG, fmt, ap);
++ vfprintf(stderr, fmt, ap);
++ fputs("\n", stderr);
++ va_end(ap);
++}
++
++void info(const char *fmt, ...)
++{
++ va_list ap;
++
++ va_start(ap, fmt);
++ vsyslog(LOG_INFO, fmt, ap);
++ vfprintf(stderr, fmt, ap);
++ fputs("\n", stderr);
++ va_end(ap);
++}
++
++void warn(const char *fmt, ...)
++{
++ va_list ap;
++
++ va_start(ap, fmt);
++ vsyslog(LOG_WARNING, fmt, ap);
++ vfprintf(stderr, fmt, ap);
++ fputs("\n", stderr);
++ va_end(ap);
++}
++
++void error(const char *fmt, ...)
++{
++ va_list ap;
++
++ va_start(ap, fmt);
++ vsyslog(LOG_ERR, fmt, ap);
++ vfprintf(stderr, fmt, ap);
++ fputs("\n", stderr);
++ va_end(ap);
++}
++
++void fatal(const char *fmt, ...)
++{
++ va_list ap;
++
++ va_start(ap, fmt);
++ vsyslog(LOG_ERR, fmt, ap);
++ vfprintf(stderr, fmt, ap);
++ fputs("\n", stderr);
++ va_end(ap);
++ exit(1);
++}
++
diff --git a/package/ppp/patches/104-debian_fix_linkpidfile.patch b/package/ppp/patches/104-debian_fix_linkpidfile.patch
new file mode 100644
index 0000000000..9e32adcae1
--- /dev/null
+++ b/package/ppp/patches/104-debian_fix_linkpidfile.patch
@@ -0,0 +1,43 @@
+Subject: Bug#284382: ppp: linkpidfile is not created upon detachment
+From: <herbert@gondor.apana.org.au>
+
+Package: ppp
+Version: 2.4.2+20040428-2
+Severity: wishlist
+
+When pppd detaches from the parent normally, that is, without nodetach
+or updetach set, the linkpidfile is not created even when linkname is
+set.
+
+This is because the create_linkpidfile call in detach() is only made
+if the linkpidfile is filled in. However, linkpidfile is never filled
+in until create_linkpidfile has been called.
+
+IMHO the call should be made uncondtionally in detach() since
+create_linkpidfile does its own check on linkname anyway.
+
+Please note that the version of pppd in woody always wrote the
+linkpidfile after detaching. It did so in main() however. That
+call has now been removed which is why I'm seeing this problem.
+
+[...]
+
+--
+Index: pppd/main.c
+===================================================================
+RCS file: /var/cvs/snwb/packages/ppp/pppd/main.c,v
+retrieving revision 1.11
+diff -u -r1.11 main.c
+--- ppp/pppd/main.c 29 Nov 2004 22:49:23 -0000 1.11
++++ ppp/pppd/main.c 5 Dec 2004 23:59:58 -0000
+@@ -819,8 +819,7 @@
+ /* 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_pppoatm_cleanup.patch b/package/ppp/patches/105-debian_pppoatm_cleanup.patch
new file mode 100644
index 0000000000..2437a12003
--- /dev/null
+++ b/package/ppp/patches/105-debian_pppoatm_cleanup.patch
@@ -0,0 +1,95 @@
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/pppoatm/pppoatm.c ppp-2.4.3/pppd/plugins/pppoatm/pppoatm.c
+--- ppp-2.4.3.orig/pppd/plugins/pppoatm/pppoatm.c 2005-03-22 14:44:18.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/pppoatm/pppoatm.c 2005-03-22 14:44:02.000000000 +0100
+@@ -70,18 +70,20 @@ static int setdevname_pppoatm(const char
+ {
+ struct sockaddr_atmpvc addr;
+ extern struct stat devstat;
++
+ if (device_got_set)
+ return 0;
+- //info("PPPoATM setdevname_pppoatm: '%s'", cp);
++
+ memset(&addr, 0, sizeof addr);
+ if (text2atm(cp, (struct sockaddr *) &addr, sizeof(addr),
+ T2A_PVC | T2A_NAME) < 0) {
+- if(doit)
+- info("atm does not recognize: %s", cp);
++ if (doit)
++ info("cannot parse the ATM address: %s", cp);
+ return 0;
+- }
+- if (!doit) return 1;
+- //if (!dev_set_ok()) return -1;
++ }
++ if (!doit)
++ return 1;
++
+ memcpy(&pvcaddr, &addr, sizeof pvcaddr);
+ strlcpy(devnam, cp, sizeof devnam);
+ devstat.st_mode = S_IFSOCK;
+@@ -93,7 +95,6 @@ static int setdevname_pppoatm(const char
+ lcp_allowoptions[0].neg_asyncmap = 0;
+ lcp_wantoptions[0].neg_pcompression = 0;
+ }
+- info("PPPoATM setdevname_pppoatm - SUCCESS:%s", cp);
+ device_got_set = 1;
+ return 1;
+ }
+@@ -108,6 +109,7 @@ static void no_device_given_pppoatm(void
+ static void set_line_discipline_pppoatm(int fd)
+ {
+ struct atm_backend_ppp be;
++
+ be.backend_num = ATM_BACKEND_PPP;
+ if (!llc_encaps)
+ be.encaps = PPPOATM_ENCAPS_VC;
+@@ -115,6 +117,7 @@ static void set_line_discipline_pppoatm(
+ be.encaps = PPPOATM_ENCAPS_LLC;
+ else
+ be.encaps = PPPOATM_ENCAPS_AUTODETECT;
++
+ if (ioctl(fd, ATM_SETBACKEND, &be) < 0)
+ fatal("ioctl(ATM_SETBACKEND): %m");
+ }
+@@ -179,16 +182,19 @@ static void send_config_pppoa(int mtu,
+ {
+ int sock;
+ struct ifreq ifr;
++
+ if (mtu > pppoatm_max_mtu)
+ error("Couldn't increase MTU to %d", mtu);
++
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0)
+ fatal("Couldn't create IP socket: %m");
++
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ ifr.ifr_mtu = mtu;
+ if (ioctl(sock, SIOCSIFMTU, (caddr_t) &ifr) < 0)
+ fatal("ioctl(SIOCSIFMTU): %m");
+- (void) close (sock);
++ close(sock);
+ }
+
+ static void recv_config_pppoa(int mru,
+@@ -202,7 +208,7 @@ static void recv_config_pppoa(int mru,
+
+ void plugin_init(void)
+ {
+-#if defined(__linux__)
++#ifdef linux
+ extern int new_style_driver; /* From sys-linux.c */
+ if (!ppp_available() && !new_style_driver)
+ fatal("Kernel doesn't support ppp_generic - "
+@@ -210,9 +216,9 @@ void plugin_init(void)
+ #else
+ fatal("No PPPoATM support on this OS");
+ #endif
+- info("PPPoATM plugin_init");
+ add_options(pppoa_options);
+ }
++
+ struct channel pppoa_channel = {
+ options: pppoa_options,
+ process_extra_options: NULL,
diff --git a/package/ppp/patches/106-debian_pppoatm_fix_mtu.patch b/package/ppp/patches/106-debian_pppoatm_fix_mtu.patch
new file mode 100644
index 0000000000..ef28b5cf2b
--- /dev/null
+++ b/package/ppp/patches/106-debian_pppoatm_fix_mtu.patch
@@ -0,0 +1,31 @@
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/pppoatm/pppoatm.c ppp-2.4.3/pppd/plugins/pppoatm/pppoatm.c
+--- ppp-2.4.3.orig/pppd/plugins/pppoatm/pppoatm.c 2005-05-04 02:00:28.000000000 +0200
++++ ppp-2.4.3/pppd/plugins/pppoatm/pppoatm.c 2005-05-04 01:59:11.000000000 +0200
+@@ -183,8 +183,11 @@ static void send_config_pppoa(int mtu,
+ int sock;
+ struct ifreq ifr;
+
+- if (mtu > pppoatm_max_mtu)
+- error("Couldn't increase MTU to %d", mtu);
++ if (pppoatm_max_mtu && mtu > pppoatm_max_mtu) {
++ warn("Couldn't increase MTU to %d. Using %d",
++ mtu, pppoatm_max_mtu);
++ mtu = pppoatm_max_mtu;
++ }
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0)
+@@ -202,8 +205,11 @@ static void recv_config_pppoa(int mru,
+ int pcomp,
+ int accomp)
+ {
+- if (mru > pppoatm_max_mru)
+- error("Couldn't increase MRU to %d", mru);
++ if (pppoatm_max_mru && mru > pppoatm_max_mru) {
++ warn("Couldn't increase MRU to %d. Using %d",
++ mru, pppoatm_max_mru);
++ mru = pppoatm_max_mru;
++ }
+ }
+
+ void plugin_init(void)
diff --git a/package/ppp/patches/107-debian_stripMSdomain.patch b/package/ppp/patches/107-debian_stripMSdomain.patch
new file mode 100644
index 0000000000..d52e38645d
--- /dev/null
+++ b/package/ppp/patches/107-debian_stripMSdomain.patch
@@ -0,0 +1,35 @@
+diff -ruN ppp.orig/pppd/chap-new.c ppp/pppd/chap-new.c
+--- ppp.orig/pppd/chap-new.c 2003-11-27 23:25:17.000000000 +0100
++++ ppp/pppd/chap-new.c 2003-12-02 12:26:21.000000000 +0100
+@@ -57,6 +57,7 @@
+ int chap_timeout_time = 3;
+ int chap_max_transmits = 10;
+ int chap_rechallenge_time = 0;
++int chapms_strip_domain = 0;
+
+ /*
+ * Command-line options.
+@@ -68,6 +69,8 @@
+ "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 }
+ };
+
+@@ -338,6 +341,14 @@
+ /* 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/108-debian_defaultroute.patch b/package/ppp/patches/108-debian_defaultroute.patch
new file mode 100644
index 0000000000..76b444e4b2
--- /dev/null
+++ b/package/ppp/patches/108-debian_defaultroute.patch
@@ -0,0 +1,253 @@
+--- ppp/pppd/ipcp.c Wed May 31 17:20:41 2000
++++ ppp/pppd/ipcp.c Wed May 31 17:27:19 2000
+@@ -145,7 +145,17 @@
+ { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route,
+ "disable defaultroute option", OPT_A2COPY,
+ &ipcp_wantoptions[0].default_route },
+
++#ifdef __linux__
++ { "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 },
++#endif
+ { "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,
+@@ -195,7 +205,7 @@
+ 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 *)); /* Run an up/down script */
+ static void ipcp_script_done __P((void *));
+
+@@ -1344,7 +1354,12 @@
+ if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
+ return 0;
+ if (wo->default_route)
++#ifndef __linux__
+ if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
++#else
++ if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr,
++ wo->replace_default_route))
++#endif
+ default_route_set[u] = 1;
+ if (wo->proxy_arp)
+ if (sifproxyarp(u, wo->hisaddr))
+@@ -1420,7 +1435,8 @@
+ */
+ 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));
+@@ -1445,7 +1461,12 @@
+
+ /* assign a default route through the interface if required */
+ if (ipcp_wantoptions[f->unit].default_route)
++#ifndef __linux__
+ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
++#else
++ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
++ wo->replace_default_route))
++#endif
+ default_route_set[f->unit] = 1;
+
+ /* Make a proxy ARP entry if requested. */
+@@ -1492,7 +1513,12 @@
+
+ /* assign a default route through the interface if required */
+ if (ipcp_wantoptions[f->unit].default_route)
++#ifndef __linux__
+ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
++#else
++ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
++ wo->replace_default_route))
++#endif
+ default_route_set[f->unit] = 1;
+
+ /* Make a proxy ARP entry if requested. */
+@@ -1559,7 +1585,7 @@
+ 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 */
+@@ -1575,16 +1601,25 @@
+ * 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;
+ }
+--- ppp/pppd/ipcp.h Wed May 31 17:20:41 2000
++++ ppp/pppd/ipcp.h Wed May 31 15:56:17 2000
+@@ -47,6 +47,7 @@
+ 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? */
+--- ppp/pppd/pppd.h Wed May 31 17:20:41 2000
++++ ppp/pppd/pppd.h Wed May 31 15:56:17 2000
+@@ -416,7 +416,11 @@
+ int cif6addr __P((int, eui64_t, eui64_t));
+ /* Remove an IPv6 address from i/f */
+ #endif
++#ifndef __linux__
+ int sifdefaultroute __P((int, u_int32_t, u_int32_t));
++#else
++int sifdefaultroute __P((int, u_int32_t, u_int32_t, bool replace_default_rt));
++#endif
+ /* Create default route through i/f */
+ int cifdefaultroute __P((int, u_int32_t, u_int32_t));
+ /* Delete default route through i/f */
+--- ppp/pppd/sys-linux.c Wed May 31 17:20:41 2000
++++ ppp/pppd/sys-linux.c Wed May 31 17:37:23 2000
+@@ -143,6 +143,8 @@
+
+ static int if_is_up; /* Interface has been marked up */
+ static u_int32_t default_route_gateway; /* 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 */
+@@ -1209,6 +1211,9 @@
+ 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);
+@@ -1278,19 +1283,53 @@
+ /********************************************************************
+ *
+ * sifdefaultroute - assign a default route through the address given.
++ *
++ * 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)
++int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway, bool replace)
+ {
+- struct rtentry rt;
+-
+- if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0) {
+- u_int32_t old_gateway = SIN_ADDR(rt.rt_gateway);
++ struct rtentry rt, tmp_rt;
++ struct rtentry *del_rt = NULL;
+
+- if (old_gateway != gateway)
+- error("not replacing existing default route to %s [%I]",
+- rt.rt_dev, old_gateway);
+- return 0;
++
++ 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:
++ */
++ u_int32_t old_gateway = SIN_ADDR(old_def_rt.rt_gateway);
++
++ if (old_gateway != gateway) {
++ if (!replace) {
++ error("not replacing default route to %s [%I]",
++ old_def_rt.rt_dev, old_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, old_gateway);
++ default_rt_repl_rest = 1;
++ del_rt = &old_def_rt;
++ }
++ }
+ }
+
+ memset (&rt, '\0', sizeof (rt));
+@@ -1310,6 +1349,12 @@
+ error("default route ioctl(SIOCADDRT): %m(%d)", errno);
+ 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(%d)", errno);
++ return 0;
++ }
+
+ default_route_gateway = gateway;
+ return 1;
+@@ -1344,6 +1389,16 @@
+ error("default route ioctl(SIOCDELRT): %m (%d)", errno);
+ 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(%d)", errno);
++ return 0;
++ }
++ default_rt_repl_rest = 0;
+ }
+
+ return 1;
diff --git a/package/ppp/patches/109-debian_demand.patch b/package/ppp/patches/109-debian_demand.patch
new file mode 100644
index 0000000000..e024696697
--- /dev/null
+++ b/package/ppp/patches/109-debian_demand.patch
@@ -0,0 +1,172 @@
+--- ppp/pppd/demand.c
++++ ppp/pppd/demand.c 2000/06/28 14:54:04
+@@ -25,6 +25,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>
+@@ -32,6 +34,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 <net/if.h>
+ #include <net/bpf.h>
+@@ -210,6 +214,14 @@
+ 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) {
+@@ -288,17 +300,102 @@
+ * 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 {
+--- ppp/pppd/ipcp.c
++++ ppp/pppd/ipcp.c 2000/06/28 12:32:05
+@@ -1454,7 +1454,7 @@
+ proxy_arp_set[f->unit] = 1;
+
+ }
+- demand_rexmit(PPP_IP);
++ demand_rexmit(PPP_IP,go->ouraddr);
+ sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
+
+ } else {
+--- ppp/pppd/ipv6cp.c
++++ ppp/pppd/ipv6cp.c 2000/06/28 12:32:06
+@@ -1153,7 +1153,7 @@
+ }
+
+ }
+- demand_rexmit(PPP_IPV6);
++ demand_rexmit(PPP_IPV6,0);
+ sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS);
+
+ } else {
+--- ppp/pppd/pppd.h
++++ ppp/pppd/pppd.h 2000/06/28 12:32:06
+@@ -359,7 +359,7 @@
+ 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/200-makefile.patch b/package/ppp/patches/200-makefile.patch
new file mode 100644
index 0000000000..5bbf8602d1
--- /dev/null
+++ b/package/ppp/patches/200-makefile.patch
@@ -0,0 +1,53 @@
+diff -ruN ppp-2.4.3-orig/pppd/Makefile.linux ppp-2.4.3-3/pppd/Makefile.linux
+--- ppp-2.4.3-orig/pppd/Makefile.linux 2004-11-13 13:02:22.000000000 +0100
++++ ppp-2.4.3-3/pppd/Makefile.linux 2004-12-16 04:43:41.000000000 +0100
+@@ -48,19 +48,19 @@
+ # 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
+ # of pppd!
+-HAVE_MULTILINK=y
++#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
+
+@@ -77,7 +77,7 @@
+
+ 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)
+
+@@ -117,12 +117,12 @@
+ #LIBS += -lshadow $(LIBS)
+ endif
+
+-ifneq ($(wildcard /usr/include/crypt.h),)
++#ifneq ($(wildcard /usr/include/crypt.h),)
+ CFLAGS += -DHAVE_CRYPT_H=1
+-endif
+-ifneq ($(wildcard /usr/lib/libcrypt.*),)
++#endif
++#ifneq ($(wildcard /usr/lib/libcrypt.*),)
+ 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 0000000000..7e09f1a792
--- /dev/null
+++ b/package/ppp/patches/201-mppe_mppc_1.1.patch
@@ -0,0 +1,1585 @@
+diff -ruN ppp-2.4.3.orig/include/linux/ppp-comp.h ppp-2.4.3/include/linux/ppp-comp.h
+--- ppp-2.4.3.orig/include/linux/ppp-comp.h 2002-12-06 10:49:15.000000000 +0100
++++ ppp-2.4.3/include/linux/ppp-comp.h 2004-11-21 13:54:09.000000000 +0100
+@@ -36,7 +36,7 @@
+ */
+
+ /*
+- * ==FILEVERSION 20020319==
++ * ==FILEVERSION 20020715==
+ *
+ * NOTE TO MAINTAINERS:
+ * If you modify this file at all, please set the above date.
+@@ -86,7 +86,7 @@
+
+ /* Compress a packet */
+ int (*compress) (void *state, unsigned char *rptr,
+- unsigned char *obuf, int isize, int osize);
++ unsigned char *obuf, int isize, int osize);
+
+ /* Return compression statistics */
+ void (*comp_stat) (void *state, struct compstat *stats);
+@@ -107,7 +107,7 @@
+
+ /* Decompress a packet. */
+ int (*decompress) (void *state, unsigned char *ibuf, int isize,
+- unsigned char *obuf, int osize);
++ unsigned char *obuf, int osize);
+
+ /* Update state for an incompressible packet received */
+ void (*incomp) (void *state, unsigned char *ibuf, int icnt);
+@@ -288,6 +288,33 @@
+ opts |= MPPE_OPT_UNKNOWN; \
+ } while (/* CONSTCOND */ 0)
+
++/* 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.
+ */
+diff -ruN ppp-2.4.3.orig/include/net/ppp-comp.h ppp-2.4.3/include/net/ppp-comp.h
+--- ppp-2.4.3.orig/include/net/ppp-comp.h 2002-12-06 10:49:15.000000000 +0100
++++ ppp-2.4.3/include/net/ppp-comp.h 2004-11-21 13:54:09.000000000 +0100
+@@ -255,6 +255,33 @@
+ opts |= MPPE_OPT_UNKNOWN; \
+ } while (/* CONSTCOND */ 0)
+
++/* 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.
+ */
+diff -ruN ppp-2.4.3.orig/pppd/ccp.c ppp-2.4.3/pppd/ccp.c
+--- ppp-2.4.3.orig/pppd/ccp.c 2004-11-13 03:28:15.000000000 +0100
++++ ppp-2.4.3/pppd/ccp.c 2004-11-21 13:54:09.000000000 +0100
+@@ -62,12 +62,10 @@
+ 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 @@
+ "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 @@
+ */
+ #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 @@
+ 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_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 @@
+ 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 @@
+ 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 @@
+ 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 @@
+ 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 @@
+ * 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 @@
+ + (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 @@
+ {
+ 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 @@
+ * 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_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 @@
+ 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)
+@@ -891,7 +1070,7 @@
+
+ /*
+ * ccp_nakci - process received configure-nak.
+- * Returns 1 iff the nak was OK.
++ * Returns 1 if the nak was OK.
+ */
+ static int
+ ccp_nakci(f, p, len, treat_as_reject)
+@@ -900,6 +1079,8 @@
+ int len;
+ {
+ 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 */
+
+@@ -907,28 +1088,100 @@
+ 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) {
+@@ -1001,14 +1254,50 @@
+ 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)
+@@ -1072,14 +1361,15 @@
+ 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;
+@@ -1102,103 +1392,305 @@
+ 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;
++ 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;
+ }
+
+- /* 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");
++ 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;
+- break;
++ if (wo->mppe || ao->mppe) {
++ p[5] &= ~MPPE_MPPC;
++ newret = CONFNAK;
++ }
++ }
++ }
++
++ 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;
+ }
+ }
+
+- /* 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. */
++ if ((p[5] & ~MPPE_MPPC) == (MPPE_40BIT|MPPE_56BIT|MPPE_128BIT)) {
+ 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;
++ 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;
+ }
+- } else if (ho->mppe & MPPE_OPT_128) {
+- if (!(ao->mppe & MPPE_OPT_128)) {
+- newret = CONFREJ;
+- break;
++ 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;
+ }
+- } else if (ho->mppe & MPPE_OPT_40) {
+- if (!(ao->mppe & MPPE_OPT_40)) {
+- newret = CONFREJ;
+- break;
++ 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. */
++ /* 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;
+ }
+
+- /* 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;
+- }
++ /*
++ * 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 have accepted MPPE or are willing to negotiate
+- * MPPE parameters. A CONFREJ is due to subsequent
+- * (non-MPPE) processing.
++ * 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.
+ */
+- rej_for_ci_mppe = 0;
++/*
++ 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
+@@ -1340,12 +1832,6 @@
+ 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;
+ }
+
+@@ -1367,24 +1853,35 @@
+ 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)
+@@ -1440,12 +1937,12 @@
+ } 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 */
+ }
+
+ /*
+@@ -1468,7 +1965,7 @@
+ lcp_close(f->unit, "MPPE disabled");
+ }
+ }
+-#endif
++#endif /* MPPE */
+ }
+
+ /*
+@@ -1528,24 +2025,28 @@
+ #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) {
+@@ -1631,6 +2132,7 @@
+ 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.
+ */
+@@ -1638,9 +2140,18 @@
+ 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.
+@@ -1671,4 +2182,3 @@
+ } else
+ ccp_localstate[f->unit] &= ~RACK_PENDING;
+ }
+-
+diff -ruN ppp-2.4.3.orig/pppd/ccp.h ppp-2.4.3/pppd/ccp.h
+--- ppp-2.4.3.orig/pppd/ccp.h 2004-11-04 11:02:26.000000000 +0100
++++ ppp-2.4.3/pppd/ccp.h 2004-11-21 13:54:09.000000000 +0100
+@@ -37,9 +37,17 @@
+ 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;
+
+diff -ruN ppp-2.4.3.orig/pppd/chap_ms.c ppp-2.4.3/pppd/chap_ms.c
+--- ppp-2.4.3.orig/pppd/chap_ms.c 2004-11-12 10:57:43.000000000 +0100
++++ ppp-2.4.3/pppd/chap_ms.c 2004-11-21 13:54:09.000000000 +0100
+@@ -895,13 +895,17 @@
+ /*
+ * 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 -ruN ppp-2.4.3.orig/pppd/pppd.8 ppp-2.4.3/pppd/pppd.8
+--- ppp-2.4.3.orig/pppd/pppd.8 2004-11-13 13:22:49.000000000 +0100
++++ ppp-2.4.3/pppd/pppd.8 2004-11-21 14:24:47.000000000 +0100
+@@ -622,9 +622,29 @@
+ Enables the use of PPP multilink; this is an alias for the `multilink'
+ option. This option is currently only available under Linux.
+ .TP
+-.B mppe\-stateful
+-Allow MPPE to use stateful mode. Stateless mode is still attempted first.
+-The default is to disallow stateful mode.
++.B mppc
++Enables MPPC (Microsoft Point to Point Compression). This is the default.
++.TP
++.B mppe \fIsubopt1[,subopt2[,subopt3[..]]]
++Modify MPPE (Microsoft Point to Point Encryption) parameters. In order
++for MPPE to successfully come up, you must have authenticated with either
++MS-CHAP or MS-CHAPv2. By default MPPE is optional, it means that pppd will
++not propose MPPE to the peer, but will negotiate MPPE if peer wants that.
++You can change this using \fIrequired\fR suboption.
++This option is presently only supported under Linux, and only if your
++kernel has been configured to include MPPE support.
++.IP
++MPPE suboptions:
++.br
++\fIrequired\fR - require MPPE; disconnect if peer doesn't support it,
++.br
++\fIstateless\fR - try to negotiate stateless mode; default is stateful,
++.br
++\fIno40\fR - disable 40 bit keys,
++.br
++\fIno56\fR - disable 56 bit keys,
++.br
++\fIno128\fR - disable 128 bit keys
+ .TP
+ .B mpshortseq
+ Enables the use of short (12-bit) sequence numbers in multilink
+@@ -757,17 +777,11 @@
+ Disables the use of PPP multilink. This option is currently only
+ available under Linux.
+ .TP
+-.B nomppe
+-Disables MPPE (Microsoft Point to Point Encryption). This is the default.
+-.TP
+-.B nomppe\-40
+-Disable 40-bit encryption with MPPE.
++.B nomppc
++Disables MPPC (Microsoft Point to Point Compression).
+ .TP
+-.B nomppe\-128
+-Disable 128-bit encryption with MPPE.
+-.TP
+-.B nomppe\-stateful
+-Disable MPPE stateful mode. This is the default.
++.B nomppe
++Disables MPPE (Microsoft Point to Point Encryption).
+ .TP
+ .B nompshortseq
+ Disables the use of short (12-bit) sequence numbers in the PPP
+@@ -948,19 +962,6 @@
+ Require the peer to authenticate itself using CHAP [Challenge
+ Handshake Authentication Protocol] authentication.
+ .TP
+-.B require\-mppe
+-Require the use of MPPE (Microsoft Point to Point Encryption). This
+-option disables all other compression types. This option enables
+-both 40-bit and 128-bit encryption. In order for MPPE to successfully
+-come up, you must have authenticated with either MS\-CHAP or MS\-CHAPv2.
+-This option is presently only supported under Linux, and only if your
+-kernel has been configured to include MPPE support.
+-.TP
+-.B require\-mppe\-40
+-Require the use of MPPE, with 40-bit encryption.
+-.TP
+-.B require\-mppe\-128
+-Require the use of MPPE, with 128-bit encryption.
+ .TP
+ .B require\-mschap
+ Require the peer to authenticate itself using MS\-CHAP [Microsoft Challenge
diff --git a/package/ppp/patches/202-atm_fix.patch b/package/ppp/patches/202-atm_fix.patch
new file mode 100644
index 0000000000..40d9d595cf
--- /dev/null
+++ b/package/ppp/patches/202-atm_fix.patch
@@ -0,0 +1,11 @@
+--- ppp-2.4.3/pppd/plugins/pppoatm/pppoatm.c 2005-08-26 15:18:55.000000000 +0200
++++ ppp-2.4.3/pppd/plugins/pppoatm/pppoatm.c 2005-08-26 15:19:51.000000000 +0200
+@@ -136,8 +136,6 @@
+ int fd;
+ struct atm_qos qos;
+
+- system ("/sbin/modprobe pppoatm");
+-
+ if (!device_got_set)
+ no_device_given_pppoatm();
+ fd = socket(AF_ATMPVC, SOCK_DGRAM, 0);
diff --git a/package/ppp/patches/203-no_strip.patch b/package/ppp/patches/203-no_strip.patch
new file mode 100644
index 0000000000..216973cf59
--- /dev/null
+++ b/package/ppp/patches/203-no_strip.patch
@@ -0,0 +1,86 @@
+diff -ruN ppp-2.4.3-orig/chat/Makefile.linux ppp-2.4.3-3/chat/Makefile.linux
+--- ppp-2.4.3-orig/chat/Makefile.linux 2004-11-03 12:51:47.000000000 +0100
++++ ppp-2.4.3-3/chat/Makefile.linux 2004-12-05 17:42:43.000000000 +0100
+@@ -25,7 +25,7 @@
+
+ install: chat
+ mkdir -p $(BINDIR)
+- $(INSTALL) -s -c chat $(BINDIR)
++ $(INSTALL) -c chat $(BINDIR)
+ $(INSTALL) -c -m 644 chat.8 $(MANDIR)
+
+ clean:
+diff -ruN ppp-2.4.3-orig/pppd/Makefile.linux ppp-2.4.3-3/pppd/Makefile.linux
+--- ppp-2.4.3-orig/pppd/Makefile.linux 2004-11-13 13:02:22.000000000 +0100
++++ ppp-2.4.3-3/pppd/Makefile.linux 2004-12-16 04:43:41.000000000 +0100
+@@ -99,7 +99,7 @@
+ 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
+@@ -202,7 +202,7 @@
+ 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)
+diff -ruN ppp-2.4.3-orig/pppd/plugins/radius/Makefile.linux ppp-2.4.3-3/pppd/plugins/radius/Makefile.linux
+--- ppp-2.4.3-orig/pppd/plugins/radius/Makefile.linux 2004-11-14 08:02:31.000000000 +0100
++++ ppp-2.4.3-3/pppd/plugins/radius/Makefile.linux 2004-12-05 17:43:17.000000000 +0100
+@@ -36,9 +37,9 @@
+
+ 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)
+
+diff -ruN ppp-2.4.3-orig/pppd/plugins/rp-pppoe/Makefile.linux ppp-2.4.3-3/pppd/plugins/rp-pppoe/Makefile.linux
+--- ppp-2.4.3-orig/pppd/plugins/rp-pppoe/Makefile.linux 2004-11-14 08:58:37.000000000 +0100
++++ ppp-2.4.3-3/pppd/plugins/rp-pppoe/Makefile.linux 2004-12-05 17:43:23.000000000 +0100
+@@ -39,9 +39,9 @@
+
+ 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
+diff -ruN ppp-2.4.3-orig/pppdump/Makefile.linux ppp-2.4.3-3/pppdump/Makefile.linux
+--- ppp-2.4.3-orig/pppdump/Makefile.linux 2004-10-31 02:36:52.000000000 +0200
++++ ppp-2.4.3-3/pppdump/Makefile.linux 2004-12-05 17:50:34.000000000 +0100
+@@ -17,5 +18,5 @@
+
+ install:
+ mkdir -p $(BINDIR) $(MANDIR)
+- $(INSTALL) -s -c pppdump $(BINDIR)
++ $(INSTALL) -c pppdump $(BINDIR)
+ $(INSTALL) -c -m 444 pppdump.8 $(MANDIR)
+diff -ruN ppp-2.4.3-orig/pppstats/Makefile.linux ppp-2.4.3-3/pppstats/Makefile.linux
+--- ppp-2.4.3-orig/pppstats/Makefile.linux 2004-10-31 23:09:03.000000000 +0100
++++ ppp-2.4.3-3/pppstats/Makefile.linux 2004-12-05 17:43:38.000000000 +0100
+@@ -22,7 +22,7 @@
+
+ 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/204-opt_flags.patch b/package/ppp/patches/204-opt_flags.patch
new file mode 100644
index 0000000000..200e76b5b5
--- /dev/null
+++ b/package/ppp/patches/204-opt_flags.patch
@@ -0,0 +1,26 @@
+diff -ruN ppp-2.4.3-orig/pppd/plugins/radius/Makefile.linux ppp-2.4.3-3/pppd/plugins/radius/Makefile.linux
+--- ppp-2.4.3-orig/pppd/plugins/radius/Makefile.linux 2004-11-14 08:02:31.000000000 +0100
++++ ppp-2.4.3-3/pppd/plugins/radius/Makefile.linux 2004-12-05 17:43:17.000000000 +0100
+@@ -12,7 +12,8 @@
+ 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.
+diff -ruN ppp-2.4.3-orig/pppdump/Makefile.linux ppp-2.4.3-3/pppdump/Makefile.linux
+--- ppp-2.4.3-orig/pppdump/Makefile.linux 2004-10-31 02:36:52.000000000 +0200
++++ ppp-2.4.3-3/pppdump/Makefile.linux 2004-12-05 17:50:34.000000000 +0100
+@@ -2,7 +2,8 @@
+ 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/205-pppoe_iface_name.patch b/package/ppp/patches/205-pppoe_iface_name.patch
new file mode 100644
index 0000000000..0961eca623
--- /dev/null
+++ b/package/ppp/patches/205-pppoe_iface_name.patch
@@ -0,0 +1,12 @@
+diff -ruN ppp-2.4.3-orig/pppd/plugins/rp-pppoe/plugin.c ppp-2.4.3-3/pppd/plugins/rp-pppoe/plugin.c
+--- ppp-2.4.3-orig/pppd/plugins/rp-pppoe/plugin.c 2004-11-04 11:07:37.000000000 +0100
++++ ppp-2.4.3-3/pppd/plugins/rp-pppoe/plugin.c 2004-12-16 01:07:22.000000000 +0100
+@@ -286,7 +286,7 @@
+ /* Strip off "nic-" */
+ cmd += 4;
+ } else if (strlen(cmd) < 4
+- || (strncmp(cmd, "eth", 3) && strncmp(cmd, "nas", 3)
++ || (strncmp(cmd, "eth", 3) && strncmp(cmd, "nas", 3) && strncmp(cmd, "vlan", 4) && strncmp(cmd, "ath", 3)
+ && strncmp(cmd, "tap", 3) && strncmp(cmd, "br", 2))) {
+ return 0;
+ }
diff --git a/package/ppp/patches/206-radius_config.patch b/package/ppp/patches/206-radius_config.patch
new file mode 100644
index 0000000000..90c02af4c1
--- /dev/null
+++ b/package/ppp/patches/206-radius_config.patch
@@ -0,0 +1,74 @@
+diff -ruN ppp-2.4.3-orig/pppd/plugins/radius/config.c ppp-2.4.3-3/pppd/plugins/radius/config.c
+--- ppp-2.4.3-orig/pppd/plugins/radius/config.c 2004-11-14 08:26:26.000000000 +0100
++++ ppp-2.4.3-3/pppd/plugins/radius/config.c 2004-12-16 04:03:46.000000000 +0100
+@@ -369,31 +369,37 @@
+ }
+ #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;
+ }
+diff -ruN ppp-2.4.3-orig/pppd/plugins/radius/options.h ppp-2.4.3-3/pppd/plugins/radius/options.h
+--- ppp-2.4.3-orig/pppd/plugins/radius/options.h 2004-11-14 08:26:26.000000000 +0100
++++ ppp-2.4.3-3/pppd/plugins/radius/options.h 2004-12-16 04:09:16.000000000 +0100
+@@ -31,24 +31,21 @@
+ 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/207-ppp_reconnect.patch b/package/ppp/patches/207-ppp_reconnect.patch
new file mode 100644
index 0000000000..9311c9ef4e
--- /dev/null
+++ b/package/ppp/patches/207-ppp_reconnect.patch
@@ -0,0 +1,129 @@
+diff -urN -x'*.swp' ppp.old/pppd/auth.c ppp.dev/pppd/auth.c
+--- ppp.old/pppd/auth.c 2004-11-12 11:30:51.000000000 +0100
++++ ppp.dev/pppd/auth.c 2005-07-13 14:54:23.000000000 +0200
+@@ -532,6 +532,12 @@
+ link_required(unit)
+ int unit;
+ {
++}
++
++void
++start_link(unit)
++ int unit;
++{
+ new_phase(PHASE_SERIALCONN);
+
+ devfd = the_channel->connect();
+@@ -984,10 +990,12 @@
+ int unit, protocol, prot_flavor;
+ {
+ int bit;
++ const char *prot = "";
+
+ switch (protocol) {
+ case PPP_CHAP:
+ bit = CHAP_WITHPEER;
++ prot = "CHAP";
+ switch (prot_flavor) {
+ case CHAP_MD5:
+ bit |= CHAP_MD5_WITHPEER;
+@@ -1006,15 +1014,19 @@
+ if (passwd_from_file)
+ BZERO(passwd, MAXSECRETLEN);
+ bit = PAP_WITHPEER;
++ prot = "PAP";
+ break;
+ case PPP_EAP:
+ bit = EAP_WITHPEER;
++ prot = "EAP";
+ break;
+ default:
+ warn("auth_withpeer_success: unknown protocol %x", protocol);
+ bit = 0;
+ }
+
++ notice("%s authentication succeeded", prot);
++
+ /* Save the authentication method for later. */
+ auth_done[unit] |= bit;
+
+@@ -1648,6 +1660,7 @@
+ static void
+ plogout()
+ {
++ char *tty;
+ #ifdef USE_PAM
+ int pam_error;
+
+@@ -1658,14 +1671,12 @@
+ }
+ /* Apparently the pam stuff does closelog(). */
+ reopen_log();
+-#else /* ! USE_PAM */
+- char *tty;
++#endif /* USE_PAM */
+
+ tty = devnam;
+ if (strncmp(tty, "/dev/", 5) == 0)
+ tty += 5;
+ logwtmp(tty, "", ""); /* Wipe out utmp logout entry */
+-#endif /* ! USE_PAM */
+ logged_in = 0;
+ }
+
+diff -urN -x'*.swp' ppp.old/pppd/main.c ppp.dev/pppd/main.c
+--- ppp.old/pppd/main.c 2005-07-13 11:34:28.000000000 +0200
++++ ppp.dev/pppd/main.c 2005-07-13 14:49:06.000000000 +0200
+@@ -537,6 +537,7 @@
+ script_unsetenv("BYTES_RCVD");
+
+ lcp_open(0); /* Start protocol */
++ start_link(0);
+ while (phase != PHASE_DEAD) {
+ handle_events();
+ get_input();
+diff -urN -x'*.swp' ppp.old/pppd/pppd.h ppp.dev/pppd/pppd.h
+--- ppp.old/pppd/pppd.h 2005-07-13 11:34:28.000000000 +0200
++++ ppp.dev/pppd/pppd.h 2005-07-13 14:48:56.000000000 +0200
+@@ -526,6 +526,7 @@
+
+ /* Procedures exported from auth.c */
+ void link_required __P((int)); /* we are starting to use the link */
++void start_link __P((int)); /* bring the link up now */
+ void link_terminated __P((int)); /* we are finished with the link */
+ void link_down __P((int)); /* the LCP layer has left the Opened state */
+ void upper_layers_down __P((int));/* take all NCPs down */
+diff -urN -x'*.swp' ppp.old/pppd/tty.c ppp.dev/pppd/tty.c
+--- ppp.old/pppd/tty.c 2004-11-13 13:07:29.000000000 +0100
++++ ppp.dev/pppd/tty.c 2005-07-13 14:46:57.000000000 +0200
+@@ -755,14 +755,6 @@
+ close(pty_master);
+ pty_master = -1;
+ }
+- if (pty_slave >= 0) {
+- close(pty_slave);
+- pty_slave = -1;
+- }
+- if (real_ttyfd >= 0) {
+- close(real_ttyfd);
+- real_ttyfd = -1;
+- }
+ ttyfd = -1;
+ if (got_sigterm)
+ asked_to_quit = 1;
+@@ -781,6 +773,7 @@
+ } else {
+ info("Serial link disconnected.");
+ }
++ stop_charshunt(NULL, 0);
+ }
+
+ void tty_close_fds()
+@@ -944,7 +937,6 @@
+ exit(0);
+ }
+ charshunt_pid = cpid;
+- add_notifier(&sigreceived, stop_charshunt, 0);
+ record_child(cpid, "pppd (charshunt)", charshunt_done, NULL);
+ return 1;
+ }
diff --git a/package/ppp/patches/208-no_exponential_timeout.patch b/package/ppp/patches/208-no_exponential_timeout.patch
new file mode 100644
index 0000000000..d6c986a7ed
--- /dev/null
+++ b/package/ppp/patches/208-no_exponential_timeout.patch
@@ -0,0 +1,28 @@
+diff -urN ppp.old/pppd/plugins/rp-pppoe/discovery.c ppp.dev/pppd/plugins/rp-pppoe/discovery.c
+--- ppp.old/pppd/plugins/rp-pppoe/discovery.c 2005-09-05 15:25:35.917232000 +0200
++++ ppp.dev/pppd/plugins/rp-pppoe/discovery.c 2005-09-05 15:29:17.233586872 +0200
+@@ -593,12 +593,14 @@
+ conn->discoveryState = STATE_SENT_PADI;
+ waitForPADO(conn, timeout);
+
++#if 0
+ /* If we're just probing for access concentrators, don't do
+ exponential backoff. This reduces the time for an unsuccessful
+ probe to 15 seconds. */
+ if (!conn->printACNames) {
+ timeout *= 2;
+ }
++#endif
+ if (conn->printACNames && conn->numPADOs) {
+ break;
+ }
+@@ -621,7 +623,9 @@
+ 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/209-compensate_time_change.patch b/package/ppp/patches/209-compensate_time_change.patch
new file mode 100644
index 0000000000..f43085ab11
--- /dev/null
+++ b/package/ppp/patches/209-compensate_time_change.patch
@@ -0,0 +1,82 @@
+diff -urN ppp.old/pppd/main.c ppp.dev/pppd/main.c
+--- ppp.old/pppd/main.c 2005-11-11 19:19:28.177790000 +0100
++++ ppp.dev/pppd/main.c 2005-11-11 20:18:05.957363000 +0100
+@@ -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"
+@@ -227,6 +228,7 @@
+
+ /* 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));
+@@ -531,6 +533,7 @@
+ info("Starting link");
+ }
+
++ check_time();
+ gettimeofday(&start_time, NULL);
+ script_unsetenv("CONNECT_TIME");
+ script_unsetenv("BYTES_SENT");
+@@ -1195,6 +1198,36 @@
+
+ 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.
+@@ -1265,6 +1298,8 @@
+ {
+ struct callout *p;
+
++ check_time();
++
+ while (callout != NULL) {
+ p = callout;
+
+@@ -1292,6 +1327,8 @@
+ {
+ 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/210-lcp_mtu_max.patch b/package/ppp/patches/210-lcp_mtu_max.patch
new file mode 100644
index 0000000000..2056a87325
--- /dev/null
+++ b/package/ppp/patches/210-lcp_mtu_max.patch
@@ -0,0 +1,17 @@
+--- ppp-2.4.3/pppd/lcp.c.old 2006-10-10 14:19:11.000000000 +0200
++++ ppp-2.4.3/pppd/lcp.c 2006-10-10 14:19:55.000000000 +0200
+@@ -1891,12 +1891,12 @@
+ * 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/300-filter-pcap-includes-lib.patch b/package/ppp/patches/300-filter-pcap-includes-lib.patch
new file mode 100644
index 0000000000..3f6247d6ef
--- /dev/null
+++ b/package/ppp/patches/300-filter-pcap-includes-lib.patch
@@ -0,0 +1,14 @@
+diff -urN ppp-2.4.3.orig/pppd/Makefile.linux ppp-2.4.3/pppd/Makefile.linux
+--- ppp-2.4.3.orig/pppd/Makefile.linux 2006-02-05 20:13:06.000000000 +0100
++++ ppp-2.4.3/pppd/Makefile.linux 2006-02-05 20:24:22.000000000 +0100
+@@ -172,8 +172,8 @@
+
+ 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-precompiled_filter.patch b/package/ppp/patches/310-precompiled_filter.patch
new file mode 100644
index 0000000000..df9452c379
--- /dev/null
+++ b/package/ppp/patches/310-precompiled_filter.patch
@@ -0,0 +1,231 @@
+diff -urN ppp.old/pppd/Makefile.linux ppp.dev/pppd/Makefile.linux
+--- ppp.old/pppd/Makefile.linux 2006-03-18 15:58:00.000000000 +0100
++++ ppp.dev/pppd/Makefile.linux 2006-03-18 16:52:01.000000000 +0100
+@@ -50,6 +50,9 @@
+ # 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!
+@@ -177,6 +180,14 @@
+ 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
+diff -urN ppp.old/pppd/demand.c ppp.dev/pppd/demand.c
+--- ppp.old/pppd/demand.c 2006-03-18 15:58:00.000000000 +0100
++++ ppp.dev/pppd/demand.c 2006-03-18 18:09:16.000000000 +0100
+@@ -438,12 +438,14 @@
+ return 0;
+ proto = PPP_PROTOCOL(p);
+ #ifdef PPP_FILTER
++ *p = 1; /* set outbound for the filter rule */
+ if (pass_filter.bf_len != 0
+ && bpf_filter(pass_filter.bf_insns, p, len, len) == 0)
+ return 0;
+ if (active_filter.bf_len != 0
+ && bpf_filter(active_filter.bf_insns, p, len, len) == 0)
+ return 0;
++ *p = 0xff; /* restore original ppp header */
+ #endif
+ for (i = 0; (protp = protocols[i]) != NULL; ++i) {
+ if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
+diff -urN ppp.old/pppd/options.c ppp.dev/pppd/options.c
+--- ppp.old/pppd/options.c 2006-03-18 15:58:00.000000000 +0100
++++ ppp.dev/pppd/options.c 2006-03-18 18:05:58.000000000 +0100
+@@ -57,14 +57,7 @@
+
+ #ifdef PPP_FILTER
+ #include <pcap.h>
+-/*
+- * DLT_PPP_WITH_DIRECTION is in current libpcap cvs, and should be in
+- * libpcap-0.8.4. Until that is released, use DLT_PPP - but that means
+- * we lose the inbound and outbound qualifiers.
+- */
+-#ifndef DLT_PPP_WITH_DIRECTION
+-#define DLT_PPP_WITH_DIRECTION DLT_PPP
+-#endif
++#include <pcap-bpf.h>
+ #endif
+
+ #include "pppd.h"
+@@ -155,6 +148,13 @@
+ 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 **));
+@@ -312,6 +312,14 @@
+ "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",
+@@ -1447,6 +1455,29 @@
+ 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
+@@ -1458,7 +1489,7 @@
+ pcap_t *pc;
+ int ret = 0;
+
+- pc = pcap_open_dead(DLT_PPP_WITH_DIRECTION, 65535);
++ pc = pcap_open_dead(DLT_PPP_PPPD, 65535);
+ if (pcap_compile(pc, &pass_filter, *argv, 1, netmask) == -1) {
+ option_error("error in pass-filter expression: %s\n",
+ pcap_geterr(pc));
+@@ -1479,7 +1510,7 @@
+ pcap_t *pc;
+ int ret = 0;
+
+- pc = pcap_open_dead(DLT_PPP_WITH_DIRECTION, 65535);
++ pc = pcap_open_dead(DLT_PPP_PPPD, 65535);
+ if (pcap_compile(pc, &active_filter, *argv, 1, netmask) == -1) {
+ option_error("error in active-filter expression: %s\n",
+ pcap_geterr(pc));
+diff -urN ppp.old/pppd/pcap_pcc.c ppp.dev/pppd/pcap_pcc.c
+--- ppp.old/pppd/pcap_pcc.c 1970-01-01 01:00:00.000000000 +0100
++++ ppp.dev/pppd/pcap_pcc.c 2006-03-18 16:51:31.000000000 +0100
+@@ -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;
++}
+diff -urN ppp.old/pppd/pcap_pcc.h ppp.dev/pppd/pcap_pcc.h
+--- ppp.old/pppd/pcap_pcc.h 1970-01-01 01:00:00.000000000 +0100
++++ ppp.dev/pppd/pcap_pcc.h 2006-03-18 15:59:14.000000000 +0100
+@@ -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/utils/pfc.c b/package/ppp/utils/pfc.c
new file mode 100644
index 0000000000..5476be170a
--- /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/pptp/Makefile b/package/pptp/Makefile
new file mode 100644
index 0000000000..bb0710419b
--- /dev/null
+++ b/package/pptp/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.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=pptp
+PKG_VERSION:=1.6.0
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/pptpclient
+PKG_MD5SUM:=9a706327fb9827541d7c86d48ceb9631
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/pptp
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=PPTP client
+ DESCRIPTION:=\
+ This package contains a PPTP (Point-to-Point Tunneling Protocol) client.
+ URL:=http://pptpclient.sourceforge.net/
+endef
+
+define Package/pptp/install
+ install -d -m0755 $(1)/usr/sbin
+ install -m0755 $(PKG_BUILD_DIR)/pptp $(1)/usr/sbin/
+ install -d -m0755 $(1)/etc/ppp
+ install -m0644 ./files/options.pptp $(1)/etc/ppp/
+ install -d -m0755 $(1)/lib/network
+ install -m0755 ./files/pptp.sh $(1)/lib/network/
+endef
+
+$(eval $(call BuildPackage,pptp))
diff --git a/package/pptp/files/options.pptp b/package/pptp/files/options.pptp
new file mode 100644
index 0000000000..5332445e78
--- /dev/null
+++ b/package/pptp/files/options.pptp
@@ -0,0 +1,7 @@
+lock
+noauth
+nobsdcomp
+nodeflate
+idle 0
+defaultroute
+maxfail 0
diff --git a/package/pptp/files/pptp.sh b/package/pptp/files/pptp.sh
new file mode 100644
index 0000000000..fffa625a2f
--- /dev/null
+++ b/package/pptp/files/pptp.sh
@@ -0,0 +1,23 @@
+scan_pptp() {
+ scan_ppp "$@"
+}
+
+setup_interface_pptp() {
+ local iface="$1"
+ local config="$2"
+
+ config_get device "$config" device
+
+ for module in slhc ppp_generic ppp_async ip_gre; do
+ /sbin/insmod $module 2>&- >&-
+ done
+ setup_interface "$iface" "$config" "dhcp"
+
+ config_get mtu "$cfg" mtu
+ config_get server "$cfg" server
+ mtu=${mtu:-1452}
+ start_pppd "$config" \
+ pty "/usr/sbin/pptp $server --loglevel 0 --nolaunchpppd"
+ file /etc/ppp/options.pptp
+ mtu $mtu mru $mtu
+}
diff --git a/package/qos-scripts/Makefile b/package/qos-scripts/Makefile
new file mode 100644
index 0000000000..444009791c
--- /dev/null
+++ b/package/qos-scripts/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.
+#
+# $Id: Makefile 4823 2006-09-23 13:45:49Z nico $
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=qos-scripts
+PKG_VERSION:=0.9.2
+PKG_RELEASE:=1
+
+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 +iptables-mod-filter +iptables-mod-ipopt +iptables-mod-extra +iptables-mod-conntrack +iptables-mod-imq
+ TITLE:=QoS scripts
+ DESCRIPTION:=QoS scripts \\\
+ A set of scripts that abstract QoS configuration \\\
+ into a simple configuration file supporting stanzas that specify \\\
+ any number of QoS entries.
+endef
+
+define Build/Prepare
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+endef
+
+define Package/qos-scripts/install
+ mkdir -p $(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 0000000000..1bf991766c
--- /dev/null
+++ b/package/qos-scripts/files/etc/config/qos
@@ -0,0 +1,94 @@
+# QoS configuration for OpenWrt
+
+# INTERFACES:
+config interface wan
+ option classgroup "Default"
+ option enabled 1
+ option upload 128
+ option download 1024
+
+# RULES:
+config classify
+ option target "Bulk"
+ option ipp2p "all"
+config classify
+ option target "Bulk"
+ option layer7 "edonkey"
+config classify
+ option target "Bulk"
+ option layer7 "bittorrent"
+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 300
+ option packetdelay 10
+ option maxsize 400
+ option avgrate 40
+ option linksharing 75
+config class "Priority_down"
+ option packetsize 1500
+ option avgrate 20
+
+
+config class "Express"
+ option packetsize 1300
+ option packetdelay 15
+ option maxsize 800
+ option avgrate 30
+ option linksharing 80
+
+
+config class "Normal"
+ option packetsize 1500
+ option packetdelay 150
+ option avgrate 20
+ option linksharing 30
+config class "Normal_down"
+ option avgrate 30
+
+
+config class "Bulk"
+ option linksharing 10
+config class "Bulk_down"
+ option avgrate 15
+ option limitrate 85
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 0000000000..0682db145c
--- /dev/null
+++ b/package/qos-scripts/files/etc/hotplug.d/iface/10-qos
@@ -0,0 +1,2 @@
+#!/bin/sh
+[ "$ACTION" = ifup ] && /usr/lib/qos.sh interface "$INTERFACE" | sh
diff --git a/package/qos-scripts/files/etc/init.d/S50qos b/package/qos-scripts/files/etc/init.d/S50qos
new file mode 100755
index 0000000000..87e18fb28d
--- /dev/null
+++ b/package/qos-scripts/files/etc/init.d/S50qos
@@ -0,0 +1,18 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+boot() {
+ /usr/lib/qos.sh firewall | sh
+}
+
+start() {
+# FIXME: after init script migration
+# qos-start
+#
+
+ boot
+}
+
+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 0000000000..347ca46b90
--- /dev/null
+++ b/package/qos-scripts/files/usr/bin/qos-start
@@ -0,0 +1,4 @@
+#!/bin/sh
+qos-stop
+/usr/lib/qos.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 0000000000..fc940a8218
--- /dev/null
+++ b/package/qos-scripts/files/usr/bin/qos-stat
@@ -0,0 +1,16 @@
+#!/bin/sh
+echo '#################'
+echo '# EGRESS STATUS #'
+echo '#################'
+echo
+for iface in $(tc qdisc show | grep hfsc | awk '{print $5}' | grep -v imq); do
+ tc -s class show dev "$iface"
+done
+
+echo '##################'
+echo '# INGRESS STATUS #'
+echo '##################'
+echo
+for iface in $(tc qdisc show | grep hfsc | awk '{print $5}' | grep imq); do
+ tc -s class show dev "$iface"
+done
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 0000000000..2275ea12dc
--- /dev/null
+++ b/package/qos-scripts/files/usr/bin/qos-stop
@@ -0,0 +1,6 @@
+#!/bin/sh
+for iface in $(tc qdisc show | grep hfsc | awk '{print $5}'); do
+ tc qdisc del dev "$iface" root
+done
+iptables -t mangle -F
+iptables -t mangle -X
diff --git a/package/qos-scripts/files/usr/lib/qos.sh b/package/qos-scripts/files/usr/lib/qos.sh
new file mode 100755
index 0000000000..bc04807031
--- /dev/null
+++ b/package/qos-scripts/files/usr/lib/qos.sh
@@ -0,0 +1,495 @@
+#!/bin/sh
+. /etc/functions.sh
+
+insmod="insmod"
+[ -f /sbin/modprobe ] && insmod="modprobe"
+
+add_insmod() {
+ eval "export isset=\${insmod_$1}"
+ case "$isset" in
+ 1) ;;
+ *) append INSMOD "$insmod $* >&- 2>&-" "$N"; export insmod_$1=1;;
+ esac
+}
+
+find_ifname() {(
+ include /lib/network
+ scan_interfaces
+ config_get "$1" ifname
+)}
+
+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";;
+ default) pkt=1; append "$var" "-m mark --mark 0";;
+ 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"
+ ;;
+ *:ipp2p)
+ add_insmod ipt_ipp2p
+ append "$var" "-m ipp2p"
+ case "$value" in
+ all) append "$var" "--edk --dc --kazaa --gnu --bit";;
+ *) append "$var" "--$value";;
+ esac
+ ;;
+ *:layer7)
+ add_insmod ipt_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
+ ;;
+ 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";;
+ *) append "$var" "-m mark --mark $class";;
+ esac
+ 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 "$1" "classgroup" "Default"
+ config_set "$1" "upload" "128"
+ config_set "$1" "download" "1024"
+ ;;
+ classify|default|reclassify)
+ option_cb() {
+ append options "$1"
+ }
+ ;;
+ esac
+
+ # Section end
+ config_get TYPE "$CONFIG_SECTION" TYPE
+ case "$TYPE" in
+ interface)
+ config_get enabled "$CONFIG_SECTION" enabled
+ config_get download "$CONFIG_SECTION" download
+ config_get classgroup "$CONFIG_SECTION" classgroup
+ config_set "$CONFIG_SECTION" imqdev "$C"
+ [ -z "$enabled" -o "$(($enabled))" -eq 0 ] || {
+ C=$(($C+1))
+ INTERFACES="$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
+}
+
+class_main_qdisc() {
+ local device="$1"
+ awk -f - <<EOF
+BEGIN {
+ limit = int("$maxrate")
+ m2 = int("$m2")
+ dmax = int("$dmax")
+ umax = int("$umax")
+ share = int("$share")
+
+ if (!(m2 > 0)) {
+ dmax = 500
+ umax = 1500
+ m2 = 10
+ rt = 0
+ } else {
+ rt = 1
+ }
+
+ cdata = ""
+ pdmax = int (dmax + (umax * 8 / limit))
+ if (rt == 1) {
+ if (share > 0) cdata = " rt"
+ else cdata = " ls"
+ if ((umax > 0) && (dmax > 0)) {
+ cdata = cdata " umax " umax "b dmax " pdmax "ms"
+ }
+ cdata = cdata " rate " m2 "kbit"
+ }
+ if (share > 0) {
+ if ((m2 > 0) && (umax > 0) && (dmax > 0)) {
+ cdata = cdata " ls umax " umax "b dmax " pdmax "ms rate " share "kbit"
+ } else {
+ cdata = cdata " ls m1 " share "kbit d 500ms m2 " share "kbit"
+ }
+ }
+
+ print "tc class add dev $device parent 1:1 classid 1:${classnr}0 hfsc" cdata " ul rate " limit "kbit"
+}
+EOF
+}
+
+class_leaf_qdisc() {
+ local device="$1"
+ awk -f - <<EOF
+
+function qlen(rate, m2, umax, dmax, qb, qr, qt, ql) {
+ qlen_min = 5 # minimum queue length
+ qlen_base = 1.7 # base value - queueing time in seconds
+ qlen_avgr = 0.7 # avgrate modifier
+ qlen_dmax = 0.0 # dmax modifier
+
+ # bits in a packet
+ qb = 1500
+ if ((m2 > 0) && (umax > 0)) qb -= int((1500 - umax) * qlen_pkt)
+ qb *= 8
+
+ # rate in bits/s
+ qr = rate
+ qr -= int((rate - m2) * qlen_avgr)
+ qr *= 1024
+
+ # queue time
+ qt = qlen_base + qlen_dmax * (dmax / 1000)
+
+ # queue length
+ ql = int(qr * qt / qb)
+ if (ql < qlen_min) ql = qlen_min
+
+ return ql
+}
+
+BEGIN {
+ sfq_dthresh = 25 # use sfq for download if pktdelay set to this or lower
+
+ limit = int("$maxrate")
+ m2 = int("$m2")
+ dmax = int("$dmax")
+ umax = int("$umax")
+
+ if (!(m2 > 0)) {
+ dmax = 500
+ umax = 1500
+ m2 = 10
+ }
+
+ cqlen = ${dl_mode:+2 * }qlen(limit, m2, umax, dmax)
+
+ printf "tc qdisc add dev $device parent 1:${classnr}0 handle ${classnr}00: "
+ if (("$dir" != "down") || ((dmax > 0) && (dmax <= sfq_dthresh))) {
+ print "sfq perturb 10 limit " cqlen
+ } else {
+ avpkt = 1200
+ min = int(limit * 1024 / 8 * 0.1)
+ dqb = cqlen * 1500
+ max = int(min + (dqb - min) * 0.25)
+ burst = int((2 * min + max) / (3 * avpkt))
+
+ print "red min " min " max " max " burst " burst " avpkt " avpkt " limit " dqb " probability 0.04 ecn"
+ }
+}
+EOF
+}
+
+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}"
+}
+
+start_interface() {
+ local iface="$1"
+ local num_imq="$2"
+ config_get device "$iface" device
+ config_get enabled "$iface" enabled
+ [ -z "$device" -o -z "$enabled" ] && exit
+ config_get upload "$iface" upload
+ config_get halfduplex "$iface" halfduplex
+ config_get download "$iface" download
+ config_get classgroup "$iface" classgroup
+
+ download="${download:-${halfduplex:+$upload}}"
+ enum_classes "$classgroup"
+ for dir in up${halfduplex} ${download:+down}; do
+ case "$dir" in
+ up)
+ upload=$(($upload * 98 / 100 - 10))
+ dev="$device"
+ rate="$upload"
+ dl_mode=""
+ prefix="cls"
+ ;;
+ down)
+ add_insmod imq numdevs="$num_imq"
+ config_get imqdev "$iface" imqdev
+ download=$(($download * 96 / 100 - 64))
+ dev="imq$imqdev"
+ rate="$download"
+ dl_mode=1
+ prefix="d_cls"
+ ;;
+ *) continue;;
+ esac
+ for class in $classes; do
+ cls_var umax "$class" packetsize $dir 1500
+ cls_var dmax "$class" packetdelay $dir 500
+
+ cls_var maxrate "$class" limitrate $dir 100
+ cls_var share "$class" linksharing $dir 0
+ cls_var m2 "$class" avgrate $dir 0
+ maxrate=$(($maxrate * $rate / 100))
+ share=$(($share * $rate / 100))
+ m2=$(($m2 * $rate / 100))
+
+ config_get classnr "$class" classnr
+ append ${prefix}q "$(class_main_qdisc "$dev" "$iface")" "$N"
+ append ${prefix}l "$(class_leaf_qdisc "$dev" "$iface")" "$N"
+ append ${prefix}f "tc filter add dev $dev parent 1: prio $classnr protocol ip handle $classnr fw flowid 1:${classnr}0" "$N"
+ done
+ 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
+ add_insmod cls_fw
+ add_insmod sch_hfsc
+ add_insmod sch_sfq
+ add_insmod sch_red
+ cat <<EOF
+${INSMOD:+$INSMOD$N}${dev_up:+$dev_up
+$clsq
+$clsl
+$clsf
+}${imqdev:+$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
+ parse_matching_rule iptrule "$rule" "$options" "$prefix" "-j MARK --set-mark $target"
+ append "$var" "$iptrule" "$N"
+ done
+}
+
+start_cg() {
+ local cg="$1"
+ local iptrules
+ local pktrules
+ local sizerules
+ local download
+ enum_classes "$cg"
+ add_rules iptrules "$ctrules" "iptables -t mangle -A ${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 ${cg} -m mark --mark $mark -m length --length $maxsize: -j MARK --set-mark 0" "$N"
+ }
+ done
+ add_rules pktrules "$rules" "iptables -t mangle -A ${cg}"
+ for iface in $INTERFACES; do
+ config_get classgroup "$iface" classgroup
+ config_get device "$iface" device
+ config_get imqdev "$iface" imqdev
+ config_get dl "$iface" download
+ config_get halfduplex "$iface" halfduplex
+ add_insmod ipt_IMQ
+ append up "iptables -t mangle -A OUTPUT -o $device -j ${cg}" "$N"
+ append up "iptables -t mangle -A FORWARD -o $device -j ${cg}" "$N"
+ [ -z "$dl" ] || {
+ [ -z "$halfduplex" ] || {
+ append down "iptables -t mangle -A POSTROUTING -o $device -j IMQ --todev $imqdev" "$N"
+ }
+ append down "iptables -t mangle -A PREROUTING -i $device -j ${cg}" "$N"
+ append down "iptables -t mangle -A PREROUTING -i $device -j IMQ --todev $imqdev" "$N"
+ }
+ done
+ cat <<EOF
+$INSMOD
+iptables -t mangle -N ${cg} >&- 2>&-
+iptables -t mangle -N ${cg}_ct >&- 2>&-
+${iptrules:+${iptrules}${N}iptables -t mangle -A ${cg}_ct -j CONNMARK --save-mark}
+iptables -t mangle -A ${cg} -j CONNMARK --restore-mark
+iptables -t mangle -A ${cg} -m mark --mark 0 -j ${cg}_ct
+$pktrules
+$up$N${down:+${down}$N}
+EOF
+ unset INSMOD
+}
+
+start_firewall() {
+ add_insmod ipt_multiport
+ add_insmod ipt_CONNMARK
+ cat <<EOF
+iptables -t mangle -F
+iptables -t mangle -X
+EOF
+ for group in $CG; do
+ start_cg $group
+ done
+}
+
+C="0"
+INTERFACES=""
+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)
+ start_firewall
+ ;;
+esac
diff --git a/package/robocfg/Makefile b/package/robocfg/Makefile
new file mode 100644
index 0000000000..c0e7e2c21e
--- /dev/null
+++ b/package/robocfg/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.
+#
+# $Id$
+
+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
+ 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 -d -m0755 $(1)/sbin
+ install -m0755 $(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 0000000000..fa763edbc8
--- /dev/null
+++ b/package/robocfg/src/Makefile
@@ -0,0 +1,12 @@
+# $Id$
+
+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 0000000000..4e1f8ad8a2
--- /dev/null
+++ b/package/robocfg/src/etc53xx.h
@@ -0,0 +1,620 @@
+/*
+ * 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.
+ * $Id$
+ */
+
+#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 0000000000..b8fc49f499
--- /dev/null
+++ b/package/robocfg/src/robocfg.c
@@ -0,0 +1,533 @@
+/*
+ * 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 <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);
+}
+
+int
+main(int argc, char *argv[])
+{
+ u16 val16;
+ u16 mac[3];
+ int i = 0, j;
+ int robo5350 = 0;
+ u32 phyid;
+
+ static robo_t robo;
+ struct ethtool_drvinfo info;
+
+ if ((robo.fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("socket");
+ exit(1);
+ }
+
+ /* the only interface for now */
+ strcpy(robo.ifr.ifr_name, "eth0");
+
+ memset(&info, 0, sizeof(info));
+ info.cmd = ETHTOOL_GDRVINFO;
+ robo.ifr.ifr_data = (caddr_t)&info;
+ if (ioctl(robo.fd, SIOCETHTOOL, (caddr_t)&robo.ifr) < 0) {
+ perror("SIOCETHTOOL: your ethernet module is either unsupported or outdated");
+// exit(1);
+ } else
+ if (strcmp(info.driver, "et0") && strcmp(info.driver, "b44")) {
+ fprintf(stderr, "No suitable module found for %s (managed by %s)\n",
+ robo.ifr.ifr_name, info.driver);
+ exit(1);
+ }
+
+ /* try access using MII ioctls - get phy address */
+ if (ioctl(robo.fd, SIOCGMIIPHY, &robo.ifr) < 0) {
+ robo.et = 1;
+ } else {
+ /* got phy address check for robo address */
+ struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&robo.ifr.ifr_data;
+ if (mii->phy_id != ROBO_PHY_ADDR) {
+ fprintf(stderr, "Invalid phy address (%d)\n", mii->phy_id);
+ exit(1);
+ }
+ }
+
+ phyid = mdio_read(&robo, ROBO_PHY_ADDR, 0x2) |
+ (mdio_read(&robo, ROBO_PHY_ADDR, 0x3) << 16);
+
+ if (phyid == 0xffffffff || phyid == 0x55210022) {
+ fprintf(stderr, "No Robo switch in managed mode found\n");
+ 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/shfs/Makefile b/package/shfs/Makefile
new file mode 100644
index 0000000000..f4383a3f96
--- /dev/null
+++ b/package/shfs/Makefile
@@ -0,0 +1,93 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=shfs
+PKG_VERSION:=0.35
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/shfs
+PKG_MD5SUM:=016f49d71bc32eee2b5d11fc1600cfbe
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/shfs/Default
+ TITLE:=ShFS
+ DESCRIPTION:=\
+ ShFS is a simple and easy to use Linux kernel module which allows you to \\\
+ mount remote filesystems using a plain shell (SSH) connection. When using \\\
+ ShFS, you can access all remote files just like the local ones, only the \\\
+ access is governed through the transport security of SSH.
+ URL:=http://shfs.sourceforge.net/
+endef
+
+define Package/kmod-shfs
+ $(call Package/shfs/Default)
+ SECTION:=kernel
+ CATEGORY:=Kernel drivers
+ DEPENDS:=
+ TITLE+= (kernel module)
+ DESCRIPTION+=\\\
+ \\\
+ This package contains the ShFS kernel module.
+ VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE)
+endef
+
+define Package/shfs-utils
+ $(call Package/shfs/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+kmod-shfs
+ TITLE+= (utilities)
+ DESCRIPTION+=\\\
+ \\\
+ This package contains the ShFS utilities.
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ OFLAGS="$(TARGET_CFLAGS)" \
+ CC="$(TARGET_CC)" \
+ LINKER="$(TARGET_CC)" \
+ KERNEL="$(LINUX_VERSION)" \
+ KERNEL_SOURCES="$(LINUX_DIR)" \
+ ROOT="$(PKG_INSTALL_DIR)" \
+ module module-install
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ OFLAGS="$(TARGET_CFLAGS)" \
+ CC="$(TARGET_CC)" \
+ LINKER="$(TARGET_CC)" \
+ KERNEL_SOURCES="$(LINUX_DIR)" \
+ ROOT="$(PKG_INSTALL_DIR)" \
+ utils utils-install
+endef
+
+define Package/kmod-shfs/install
+ install -m0755 -d $(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) $(PKG_INSTALL_DIR)/lib/modules/$(LINUX_VERSION)/kernel/fs/shfs/shfs.$(LINUX_KMOD_SUFFIX) \
+ $(1)/lib/modules/$(LINUX_VERSION)/
+endef
+
+define Package/shfs-utils/install
+ install -m0755 -d $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/shfs{,u}mount $(1)/usr/bin/
+ install -m0755 -d $(1)/sbin
+ $(CP) $(PKG_INSTALL_DIR)/sbin/mount.shfs $(1)/sbin/
+endef
+
+$(eval $(call BuildPackage,kmod-shfs))
+$(eval $(call BuildPackage,shfs-utils))
diff --git a/package/shfs/patches/101-kmod_build.patch b/package/shfs/patches/101-kmod_build.patch
new file mode 100644
index 0000000000..11701033f5
--- /dev/null
+++ b/package/shfs/patches/101-kmod_build.patch
@@ -0,0 +1,98 @@
+--- shfs-0.35-orig/shfs/Linux-2.4/Makefile 2004-06-01 15:16:19.000000000 +0200
++++ shfs-0.35-2/shfs/Linux-2.4/Makefile 2005-04-09 02:34:35.000000000 +0200
+@@ -1,3 +1,13 @@
++#
++# the original Makefile was trashed and replaced by this one
++# The main reason is that loadable modules should be built with
++# the same compile flags the kernel was built with, so we'd better
++# let the kernel tree build the module for us, like that :
++#
++# make -C $(KERNEL_DIR) SUBDIRS="$(shell pwd)" modules
++# make -C $(KERNEL_DIR) SUBDIRS="$(shell pwd)" modules_install
++#
++
+ ifndef KERNEL
+ KERNEL=$(shell uname -r)
+ endif
+@@ -10,67 +24,29 @@
+ KERNEL_SOURCES=${MODULESDIR}/build
+ endif
+
+-ifeq (${MODVERSIONS},detect)
+- ifeq ($(shell test -e ${KERNEL_SOURCES}/include/linux/modversions.h; echo $$?),0)
+- MODVERSIONS=yes
+- endif
+-endif
+-
+-ifeq (${MODVERSIONS},yes)
+-MVER=-DMODVERSIONS -DEXPORT_SYMTAB
+-endif
+-
+-LINVER=linux-${KERNEL}
+-
+-ALL_TARGETS := shfs.o
+-
+-SEARCHDIRS := -I- -I. -I${KERNEL_SOURCES}/include #-I/usr/src/linux/include/
++all: all-y
+
+-CC := gcc
+-CFLAGS = -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe -Wall ${SEARCHDIRS} -DMODULE ${MVER} -D__KERNEL__ -DLINUX
+-LINKER := ld
+-LDFLAGS = -r
+-LOADLIBES :=
++O_TARGET := shfs.o
+
+-all: ${ALL_TARGETS}
++shfs-objs := dcache.o dir.o fcache.o file.o inode.o ioctl.o proc.o shell.o symlink.o
+
+-%.o: %.c $(wildcard *.h)
+- ${CC} ${CFLAGS} -c $< -o $@
++obj-y := $(shfs-objs)
++obj-m := $(O_TARGET)
+
+-shfs.o: dcache.o dir.o fcache.o file.o inode.o ioctl.o proc.o shell.o symlink.o
+- ${LINKER} ${LDFLAGS} -o $@ ${filter-out %.a %.so, $^} ${LOADLIBES}
+-
+-tidy:
+- ${RM} core dcache.o dir.o fcache.o file.o inode.o ioctl.o proc.o shell.o symlink.o
+-
+-clean: tidy patch-clean
+- ${RM} shfs.o
++-include $(TOPDIR)/Rules.make
+
++all-y:
++ make -C ${KERNEL_SOURCES} TOPDIR="${KERNEL_SOURCES}" SUBDIRS="$(shell pwd)" modules
++
+ install: shfs.o
+ rm -f ${MODULESDIR}/kernel/fs/shfs/shfs.o
+ install -m644 -b -D shfs.o ${MODULESDIR}/kernel/fs/shfs/shfs.o
+- if [ -x /sbin/depmod -a "${ROOT}" = "/" ]; then /sbin/depmod -aq; fi
+
+ uninstall:
+ rm -rf ${MODULESDIR}/kernel/fs/shfs
+- if [ -x /sbin/depmod -a "${ROOT}" = "/" ]; then /sbin/depmod -aq; fi
+
+-patch:
+- rm -rf ${LINVER} ${LINVER}.orig; mkdir ${LINVER};
+- for i in Documentation fs/shfs include/linux; do \
+- mkdir -p ${LINVER}/$$i; \
+- done
+- cp ${KERNEL_SOURCES}/Documentation/Configure.help ${LINVER}/Documentation
+- cp ${KERNEL_SOURCES}/fs/{Makefile,Config.in} ${LINVER}/fs
+- cp -r ${LINVER} ${LINVER}.orig
+- cp ../../Changelog *.c shfs_debug.h proc.h ${LINVER}/fs/shfs/
+- cp shfs.h shfs_fs* ${LINVER}/include/linux/
+- (cd ${LINVER}; patch -p1 <../kernel-config.diff)
+- find . -type f -name "*.orig" -print | xargs rm -f
+- diff -urN ${LINVER}.orig ${LINVER} >${LINVER}.diff; true
+-
+-patch-clean:
+- rm -rf ${LINVER} ${LINVER}.orig;
+- rm -f ${LINVER}.diff
+-
+-.PHONY : all tidy clean install uninstall patch patch-clean
++clean:
++ rm -f core *.o *.a *.s
++
++shfs.o: $(shfs-objs)
++
diff --git a/package/shfs/patches/102-gcc4_fix.patch b/package/shfs/patches/102-gcc4_fix.patch
new file mode 100644
index 0000000000..c4fd36629b
--- /dev/null
+++ b/package/shfs/patches/102-gcc4_fix.patch
@@ -0,0 +1,23 @@
+diff -ur shfs-0.35/shfs/Linux-2.6/dir.c shfs-0.35-new/shfs/Linux-2.6/dir.c
+--- shfs-0.35/shfs/Linux-2.6/dir.c 2004-06-01 09:16:19.000000000 -0400
++++ shfs-0.35-new/shfs/Linux-2.6/dir.c 2005-02-11 18:12:00.000000000 -0500
+@@ -19,6 +19,8 @@
+ #include "shfs_debug.h"
+ #include "proc.h"
+
++static struct dentry_operations shfs_dentry_operations;
++
+ static int
+ shfs_dir_open(struct inode *inode, struct file *filp)
+ {
+diff -ur shfs-0.35/shfs/Linux-2.6/shfs_fs.h shfs-0.35-new/shfs/Linux-2.6/shfs_fs.h
+--- shfs-0.35/shfs/Linux-2.6/shfs_fs.h 2004-06-01 09:16:19.000000000 -0400
++++ shfs-0.35-new/shfs/Linux-2.6/shfs_fs.h 2005-02-11 18:12:03.000000000 -0500
+@@ -50,7 +50,6 @@
+ #define ROUND_TO_MINS(x) do { (x).tv_sec = ((x).tv_sec / 60) * 60; (x).tv_nsec = 0; } while (0)
+
+ /* shfs/dir.c */
+-extern struct dentry_operations shfs_dentry_operations;
+ extern struct file_operations shfs_dir_operations;
+ extern struct inode_operations shfs_dir_inode_operations;
+ extern void shfs_new_dentry(struct dentry *dentry);
diff --git a/package/shfs/patches/103-dentry.patch b/package/shfs/patches/103-dentry.patch
new file mode 100644
index 0000000000..83a406a268
--- /dev/null
+++ b/package/shfs/patches/103-dentry.patch
@@ -0,0 +1,21 @@
+diff -urN shfs-0.35.orig/shfs/Linux-2.6/dcache.c shfs-0.35/shfs/Linux-2.6/dcache.c
+--- shfs-0.35.orig/shfs/Linux-2.6/dcache.c 2004-06-01 09:16:19.000000000 -0400
++++ shfs-0.35/shfs/Linux-2.6/dcache.c 2006-03-25 07:08:57.950752296 -0500
+@@ -68,7 +68,7 @@
+ spin_lock(&dcache_lock);
+ next = parent->d_subdirs.next;
+ while (next != &parent->d_subdirs) {
+- dentry = list_entry(next, struct dentry, d_child);
++ dentry = list_entry(next, struct dentry, d_u.d_child);
+ dentry->d_fsdata = NULL;
+ shfs_age_dentry(info, dentry);
+ next = next->next;
+@@ -101,7 +101,7 @@
+ spin_lock(&dcache_lock);
+ next = parent->d_subdirs.next;
+ while (next != &parent->d_subdirs) {
+- dent = list_entry(next, struct dentry, d_child);
++ dent = list_entry(next, struct dentry, d_u.d_child);
+ if ((unsigned long)dent->d_fsdata == fpos) {
+ if (dent->d_inode)
+ dget_locked(dent);
diff --git a/package/spca5xx/Makefile b/package/spca5xx/Makefile
new file mode 100644
index 0000000000..643e5863f4
--- /dev/null
+++ b/package/spca5xx/Makefile
@@ -0,0 +1,52 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=spca5xx
+PKG_VERSION:=20060501
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://mxhaard.free.fr/spca50x/Download/
+PKG_MD5SUM:=8fcec25715aea10f9ebec5728c37e752
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+#FIXME: add proper dependency handling on kmod-usb-core & kmod-videodev packages
+define Package/kmod-spca5xx
+ SECTION:=kernel
+ CATEGORY:=Kernel drivers
+ DEPENDS:=@PACKAGE_KMOD_USB&&PACKAGE_KMOD_VIDEODEV
+ TITLE:=Driver for SPCA5xx based USB cameras
+ URL:=http://mxhaard.free.fr/
+ VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE)
+endef
+
+define Build/Compile
+ $(MAKE) -C $(LINUX_DIR) \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ KERNELVERSION="$(KERNEL)" \
+ KERNEL_VERSION="$(LINUX_VERSION)" \
+ KERNELDIR="$(LINUX_DIR)" \
+ SUBDIRS="$(PKG_BUILD_DIR)" \
+ modules
+endef
+
+define Package/kmod-spca5xx/install
+ install -m0755 -d $(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) $(PKG_BUILD_DIR)/spca5xx.$(LINUX_KMOD_SUFFIX) \
+ $(1)/lib/modules/$(LINUX_VERSION)/
+endef
+
+$(eval $(call BuildPackage,kmod-spca5xx))
diff --git a/package/spca5xx/patches/01-kmod-build.patch b/package/spca5xx/patches/01-kmod-build.patch
new file mode 100644
index 0000000000..304df92047
--- /dev/null
+++ b/package/spca5xx/patches/01-kmod-build.patch
@@ -0,0 +1,177 @@
+diff -Nur spca5xx-20051212/Makefile spca5xx-20051212.patched/Makefile
+--- spca5xx-20051212/Makefile 2005-12-10 17:05:51.000000000 +0100
++++ spca5xx-20051212.patched/Makefile 2005-12-25 02:41:29.910720750 +0100
+@@ -33,7 +33,9 @@
+ DEFINES += -DCONFIG_USB_SPCA5XX_MODULE=1 -DMODULE -D__KERNEL__
+ DEFINES += -DVID_HARDWARE_SPCA5XX=0xFF -DSPCA5XX_VERSION=\"$(VERSION)\"
+
+-ifneq ($(shell uname -r | cut -d. -f1,2), 2.4)
++KERNELVERSION=$(shell uname -r | cut -d. -f1,2)
++
++ifneq ($(KERNELVERSION), 2.4)
+
+ ifneq ($(KERNELRELEASE),) # We were called by kbuild
+ CFLAGS += $(DEFINES)
+@@ -68,152 +70,16 @@
+
+ else # kernel version test
+
+-#############################################################################
+-# For Linux 2.4 users.
+-# Change the following lines according to your system configuration.
+-# It is important to configure your particular source tree ("make dep") before
+-# compiling this module!
+-#############################################################################
+-###
+-# This makefile will build the spca50x driver module external to the kernel
+-# source tree. It makes it easier to swap kernels.
+-
+-
+-KERNEL_VERSION = `uname -r`
+-
+-###
+-# Location of the header files (most importantly the config files)
+-# for the kernel you want to build the module against.
+-# This should be correct for the currently installed kernel on your machine.
+-KINCLUDE = /lib/modules/$(KERNEL_VERSION)/build/include
+-KERNEL_ACFILE = $(KINCLUDE)/linux/autoconf.h
+-KERNEL_MODVERSIONSFILE = $(KINCLUDE)/linux/modversions.h
+-MODULE_INSTALLDIR = /lib/modules/$(KERNEL_VERSION)/kernel/drivers/usb/
+-
+-# Detect module versioning support
+-ifneq ($(strip $(shell grep 'define CONFIG_MODVERSIONS 1' $(KERNEL_ACFILE))),)
+- DEFINES += -DMODVERSIONS -include $(KERNEL_MODVERSIONSFILE)
+-endif
+-
+-# Detect SMP support
+-ifneq ($(strip $(shell grep 'define CONFIG_SMP 1' $(KERNEL_ACFILE))),)
+- DEFINES += -D__SMP__ -DSMP
+-endif
+-
+-# Setup the tools
+-CC = gcc
+-LD = ld
+-
+-# Setup compiler warnings
+-WARNINGS = -Wall -Wpointer-arith
+-WARNINGS += -Wcast-align -Wwrite-strings -Wstrict-prototypes
+-WARNINGS += -Wuninitialized -Wreturn-type -Wunused -Wparentheses
+-
+-# Setup compiler flags
+-CFLAGS = -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe
+-CFLAGS += -mpreferred-stack-boundary=2
+-CFLAGS += -I$(KINCLUDE) -Idrivers/usb
+-
+-# Setup link flags
+-LDFLAGS = --strip-debug -r
+-
+-# Setup the list of files to be included in a distribution
+-DIST_FILES = CHANGELOG \
+- README \
+- Makefile \
+- drivers/usb/Config.in \
+- drivers/usb/spcadecoder.c \
+- drivers/usb/spcadecoder.h \
+- drivers/usb/spcagamma.h \
+- drivers/usb/spcaCompat.h \
+- drivers/usb/spcausb.h \
+- drivers/usb/spca500_init.h \
+- drivers/usb/spca501_init.h \
+- drivers/usb/sp5xxfw2.dat \
+- drivers/usb/sp5xxfw2.h \
+- drivers/usb/spca505_init.h \
+- drivers/usb/spca506.h \
+- drivers/usb/spca508_init.h \
+- drivers/usb/spca561.h \
+- drivers/usb/sonix.h \
+- drivers/usb/cs2102.h \
+- drivers/usb/hv7131b.h \
+- drivers/usb/icm105a.h \
+- drivers/usb/hv7131c.h \
+- drivers/usb/hdcs2020.h \
+- drivers/usb/pb0330.h \
+- drivers/usb/tas5130c.h \
+- drivers/usb/zc3xx.h\
+- drivers/usb/tv8532.h\
+- drivers/usb/cxlib.h\
+- drivers/usb/sn9cxxx.h\
+- drivers/usb/cx11646.h\
+- drivers/usb/pac207.h\
+- drivers/usb/spca5xx.c \
+- drivers/usb/spca5xx.h
+-
+-OBJS = drivers/usb/spcadecoder.o \
+- drivers/usb/spca5xx.o
+-
+-BINARY = spca5xx.o
+-
+-###
+-# Targets follow here
+-
+-binary: $(OBJS)
+- @echo Linking $(BINARY)
+- @$(LD) $(LDFLAGS) -o $(BINARY) $(OBJS)
+-
+-install: binary
+- @echo Installing.. Your root password may be required.
+- su -c "make install-root"
+-
+-install-root:
+- @echo Installing..
+- @mkdir -p /lib/modules/`uname -r`/kernel/drivers/usb
+- @rm -f /lib/modules/`uname -r`/kernel/drivers/usb/spca50x.o
+- @rm -f /lib/modules/`uname -r`/kernel/drivers/usb/et61x.o
+- @cp spca5xx.o /lib/modules/`uname -r`/kernel/drivers/usb/spca5xx.o
+- @/sbin/depmod
+-
+-dist: clean binary
+- @echo Making distributable archives
+- @rm -f spca5xx-src-$(VERSION).tar.gz
+- @tar zcf spca5xx-src-$(VERSION).tar.gz $(DIST_FILES)
+- @rm -f spca5xx-module-$(VERSION).tar.gz
+- @cp $(BINARY) spca5xx-$(VERSION).o
+- @tar zcf spca5xx-module-$(VERSION).tar.gz spca5xx-$(VERSION).o README
+- @rm spca5xx-$(VERSION).o
+-
+-.c.o: Makefile $*.c
+- @echo Compiling $*.c
+- @$(CC) $(CFLAGS) $(WARNINGS) $(DEFINES) -c $*.c -o $*.o
+-
+-###
+-# Dependencies follow here
+-
+-drivers/usb/spca5xx.o: drivers/usb/spca5xx.h \
+- drivers/usb/spcaCompat.h \
+- drivers/usb/spcausb.h \
+- drivers/usb/sonix.h \
+- drivers/usb/spca500_init.h \
+- drivers/usb/spca501_init.h \
+- drivers/usb/sp5xxfw2.h \
+- drivers/usb/spca505_init.h \
+- drivers/usb/spca506.h \
+- drivers/usb/spca508_init.h \
+- drivers/usb/spca561.h \
+- drivers/usb/zc3xx.h\
+- drivers/usb/tv8532.h\
+- drivers/usb/cx11646.h\
+- drivers/usb/mr97311.h\
+- drivers/usb/sn9cxxx.h\
+- drivers/usb/pac207.h\
+-
+-
+-drivers/usb/spcadecoder.o: drivers/usb/spcadecoder.h \
+- drivers/usb/spcagamma.h \
+-
++EXTRA_CFLAGS += $(DEFINES)
++
++spca5xx-objs := drivers/usb/spca5xx.o drivers/usb/spcadecoder.o
++
++obj-m += spca5xx.o
++obj-y := $(spca5xx-objs)
++
++O_TARGET := $(obj-m)
++
++-include $(TOPDIR)/Rules.make
+
+ endif # End kernel version test
+
diff --git a/package/spca5xx/patches/02-seq_bug.patch b/package/spca5xx/patches/02-seq_bug.patch
new file mode 100644
index 0000000000..ec1003e700
--- /dev/null
+++ b/package/spca5xx/patches/02-seq_bug.patch
@@ -0,0 +1,14 @@
+diff -Nur spca5xx-20060501/drivers/usb/spca5xx.c.orig spca5xx-20060501/drivers/usb/spca5xx.c
+--- spca5xx-20060501/drivers/usb/spca5xx.c.orig 2006-08-16 11:56:33.000000000 -0700
++++ spca5xx-20060501/drivers/usb/spca5xx.c 2006-08-16 11:55:41.000000000 -0700
+@@ -1092,8 +1092,8 @@
+ // spca50x->avg_lum, spca50x->avg_lum);
+ for (i = 0; i < SPCA50X_NUMFRAMES; i++) {
+ out += sprintf(out, "frame : %d\n", i);
+- out +=
+- sprintf(out, " sequence : %d\n", spca50x->frame[i].seq);
++// out +=
++// sprintf(out, " sequence : %d\n", spca50x->frame[i].seq);
+ out +=
+ sprintf(out, " grabstate : %d\n",
+ spca50x->frame[i].grabstate);
diff --git a/package/switch/Makefile b/package/switch/Makefile
new file mode 100644
index 0000000000..75f3129402
--- /dev/null
+++ b/package/switch/Makefile
@@ -0,0 +1,54 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id:$
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=kmod-switch
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/kmod-switch
+ SECTION:=kernel
+ CATEGORY:=Kernel drivers
+ DEPENDS:=@LINUX_2_6_BRCM||LINUX_2_4_BRCM
+ DEFAULT:=y
+ TITLE:=Switch drivers
+ DESCRIPTION:=\
+ This package contains switch drivers for ADM6996L and BCM53XX RoboSwitch.
+ VERSION:=$(LINUX_VERSION)-$(BOARD)-$(PKG_RELEASE)
+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="-DBCMGPIO2" \
+ modules
+endef
+
+define Package/kmod-switch/install
+ install -m0755 -d $(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) $(PKG_BUILD_DIR)/*.$(LINUX_KMOD_SUFFIX) \
+ $(1)/lib/modules/$(LINUX_VERSION)
+ install -m0755 -d $(1)/lib/network/
+ install -m0755 ./files/switch.sh $(1)/lib/network/
+ install -m0755 -d $(1)/etc/modules.d/
+ printf 'switch-core\nswitch-robo\nswitch-adm\n' > $(1)/etc/modules.d/20-switch
+endef
+
+$(eval $(call BuildPackage,kmod-switch))
diff --git a/package/switch/files/switch.sh b/package/switch/files/switch.sh
new file mode 100644
index 0000000000..a787a8cf38
--- /dev/null
+++ b/package/switch/files/switch.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+setup_switch_vlan() {
+ DIR="/proc/switch/$CONFIG_SECTION/vlan/$1"
+ [ -d "$DIR" ] || return 0
+
+ config_get ports "$CONFIG_SECTION" "vlan$1"
+ echo "$ports" > "$DIR/ports"
+}
+
+setup_switch() {
+ config_cb() {
+ case "$1" in
+ switch)
+ [ -n "$2" -a -d "/proc/switch/$2" ] && {
+ echo 1 > "/proc/switch/$2/reset"
+ echo 1 > "/proc/switch/$2/enable"
+ echo 1 > "/proc/switch/$2/enable_vlan"
+ option_cb() {
+ case "$1" in
+ vlan*) setup_switch_vlan "${1##vlan}";;
+ esac
+ }
+ }
+ ;;
+ *)
+ option_cb() { return 0; }
+ ;;
+ esac
+ }
+ config_load network
+}
diff --git a/package/switch/src/Makefile b/package/switch/src/Makefile
new file mode 100644
index 0000000000..4c5f911ea2
--- /dev/null
+++ b/package/switch/src/Makefile
@@ -0,0 +1,19 @@
+# $Id$
+#
+# 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 0000000000..12d94a5d03
--- /dev/null
+++ b/package/switch/src/etc53xx.h
@@ -0,0 +1,620 @@
+/*
+ * 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.
+ * $Id: etc53xx.h,v 1.1 2005/05/14 13:15:46 nbd Exp $
+ */
+
+#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 0000000000..800ae25a9f
--- /dev/null
+++ b/package/switch/src/gpio.h
@@ -0,0 +1,52 @@
+/*
+ * 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
+
+#if defined(BCMGPIO2)
+
+#ifdef LINUX_2_4
+#define sbh bcm947xx_sbh
+extern void *bcm947xx_sbh;
+#else
+extern void *sbh;
+#endif
+
+extern __u32 sb_gpioin(void *sbh);
+extern __u32 sb_gpiointpolarity(void *sbh, __u32 mask, __u32 val, __u8 prio);
+extern __u32 sb_gpiointmask(void *sbh, __u32 mask, __u32 val, __u8 prio);
+extern __u32 sb_gpioouten(void *sbh, __u32 mask, __u32 val, __u8 prio);
+extern __u32 sb_gpioout(void *sbh, __u32 mask, __u32 val, __u8 prio);
+
+#define gpioin() sb_gpioin(sbh)
+#define gpiointpolarity(mask,val) sb_gpiointpolarity(sbh, mask, val, 0)
+#define gpiointmask(mask,val) sb_gpiointmask(sbh, mask, val, 0)
+#define gpioouten(mask,val) sb_gpioouten(sbh, mask, val, 0)
+#define gpioout(mask,val) sb_gpioout(sbh, mask, val, 0)
+
+#elif defined(BCMGPIO)
+
+#define sbh bcm947xx_sbh
+extern void *bcm947xx_sbh;
+extern __u32 sb_gpioin(void *sbh);
+extern __u32 sb_gpiointpolarity(void *sbh, __u32 mask, __u32 val);
+extern __u32 sb_gpiointmask(void *sbh, __u32 mask, __u32 val);
+extern __u32 sb_gpioouten(void *sbh, __u32 mask, __u32 val);
+extern __u32 sb_gpioout(void *sbh, __u32 mask, __u32 val);
+
+#define gpioin() sb_gpioin(sbh)
+#define gpiointpolarity(mask,val) sb_gpiointpolarity(sbh, mask, val)
+#define gpiointmask(mask,val) sb_gpiointmask(sbh, mask, val)
+#define gpioouten(mask,val) sb_gpioouten(sbh, mask, val)
+#define gpioout(mask,val) sb_gpioout(sbh, mask, val)
+
+#else
+#error Unsupported/unknown GPIO configuration
+#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 0000000000..083b6ebc47
--- /dev/null
+++ b/package/switch/src/switch-adm.c
@@ -0,0 +1,579 @@
+/*
+ * 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/config.h>
+#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"
+
+#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");
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,52)
+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);
+#else
+MODULE_PARM(eecs, "i");
+MODULE_PARM(eesk, "i");
+MODULE_PARM(eedi, "i");
+MODULE_PARM(eerc, "i");
+MODULE_PARM(force, "i");
+#endif
+
+/* 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)
+
+#if defined(BCMGPIO2) || defined(BCMGPIO)
+extern char *nvram_get(char *name);
+
+/* 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 getgpiopin(char *pin_name, unsigned int def_pin)
+{
+ char name[] = "gpioXXXX";
+ char *val;
+ unsigned int pin;
+
+ /* Go thru all possibilities till a match in pin name */
+ for (pin = 0; pin < 16; pin ++) {
+ sprintf(name, "gpio%d", pin);
+ val = nvram_get(name);
+ if (val && !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;
+
+ gpioout(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 */
+ gpioout(eesk, 0);
+ udelay(EECK_EDGE_TIME);
+
+ /* Output on rising edge */
+ gpioout(eedi, ((mask & buf[i]) ? eedi : 0));
+ udelay(EEDI_SETUP_TIME);
+
+ /* Clock high */
+ gpioout(eesk, eesk);
+ udelay(EECK_EDGE_TIME);
+ }
+ }
+
+ /* Clock low */
+ gpioout(eesk, 0);
+ udelay(EECK_EDGE_TIME);
+
+ if (cs)
+ gpioout(eecs, 0);
+}
+
+
+static void adm_read(int cs, char *buf, unsigned int bits)
+{
+ int i, len = (bits + 7) / 8;
+ __u8 mask;
+
+ gpioout(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 */
+ gpioout(eesk, 0);
+ udelay(EECK_EDGE_TIME);
+
+ /* Input on rising edge */
+ gp = gpioin();
+ if (gp & eedi)
+ byte |= mask;
+
+ /* Clock high */
+ gpioout(eesk, eesk);
+ udelay(EECK_EDGE_TIME);
+ }
+
+ *buf++ = byte;
+ }
+
+ /* Clock low */
+ gpioout(eesk, 0);
+ udelay(EECK_EDGE_TIME);
+
+ if (cs)
+ gpioout(eecs, 0);
+}
+
+
+/* Enable outputs with specified value to the chip */
+static void adm_enout(__u8 pins, __u8 val)
+{
+ /* Prepare GPIO output value */
+ gpioout(pins, val);
+
+ /* Enable GPIO outputs */
+ gpioouten(pins, pins);
+ udelay(EECK_EDGE_TIME);
+}
+
+
+/* Disable outputs to the chip */
+static void adm_disout(__u8 pins)
+{
+ /* Disable GPIO outputs */
+ gpioouten(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 */
+ gpioout(eesk, eesk);
+ udelay(EECK_EDGE_TIME);
+
+ /* Clock low */
+ gpioout(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&62)<<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);
+
+ 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;
+
+#if defined(BCMGPIO2) || defined(BCMGPIO)
+ int boardflags = atoi(nvram_get("boardflags"));
+
+ if ((boardflags & 0x80) || force) {
+ ret = 1;
+
+ eecs = getgpiopin("adm_eecs", 2);
+ eesk = getgpiopin("adm_eesk", 3);
+ eedi = getgpiopin("adm_eedi", 4);
+ eerc = getgpiopin("adm_rc", 0);
+
+ } else if ((strcmp(nvram_get("boardtype") ?: "", "bcm94710dev") == 0) &&
+ (strncmp(nvram_get("boardnum") ?: "", "42", 2) == 0)) {
+ /* WRT54G v1.1 hack */
+ eecs = 2;
+ eesk = 3;
+ eedi = 5;
+
+ ret = 1;
+ } else
+ printk("BFL_ENETADM not set in boardflags. Use force=1 to ignore.\n");
+
+ 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 0000000000..7bf705afe4
--- /dev/null
+++ b/package/switch/src/switch-core.c
@@ -0,0 +1,466 @@
+/*
+ * 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.
+ *
+ * $Id: $
+ *
+ * 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/config.h>
+#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)
+{
+#ifdef LINUX_2_4
+ struct inode *inode = file->f_dentry->d_inode;
+ struct proc_dir_entry *dent = inode->u.generic_ip;
+#else
+ struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode);
+#endif
+ 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;
+ }
+
+ return len;
+}
+
+
+static ssize_t switch_proc_write(struct file *file, const char *buf, size_t count, void *data)
+{
+#ifdef LINUX_2_4
+ struct inode *inode = file->f_dentry->d_inode;
+ struct proc_dir_entry *dent = inode->u.generic_ip;
+#else
+ struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode);
+#endif
+ 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)
+{
+ char *name = ((switch_driver *) driver)->name;
+ return sprintf(buf, "%s\n", name);
+}
+
+static int handle_driver_version(void *driver, char *buf, int nr)
+{
+ char *version = ((switch_driver *) driver)->version;
+ strcpy(buf, version);
+ return sprintf(buf, "%s\n", version);
+}
+
+static void add_handler(switch_driver *driver, 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);
+ 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, 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];
+
+ if ((priv = kmalloc(sizeof(switch_priv), GFP_KERNEL)) == NULL)
+ return -ENOBUFS;
+ driver->data = (void *) priv;
+
+ 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);
+ priv->ports = kmalloc((driver->ports + 1) * sizeof(struct proc_dir_entry *), GFP_KERNEL);
+ 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);
+ priv->vlans = kmalloc((driver->vlans + 1) * sizeof(struct proc_dir_entry *), GFP_KERNEL);
+ 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 = kmalloc(sizeof(switch_vlan_config), GFP_KERNEL);
+ memset(c, 0, sizeof(switch_vlan_config));
+
+ 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) return NULL;
+
+ c->port &= (1 << driver->ports) - 1;
+ c->untag &= (1 << driver->ports) - 1;
+ c->pvid &= (1 << driver->ports) - 1;
+
+ return c;
+}
+
+
+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);
+ 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_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 0000000000..5292469c01
--- /dev/null
+++ b/package/switch/src/switch-core.h
@@ -0,0 +1,59 @@
+#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
+
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#define LINUX_2_4
+#endif
+
+typedef int (*switch_handler)(void *driver, char *buf, int nr);
+
+typedef struct {
+ char *name;
+ switch_handler read, write;
+} switch_config;
+
+typedef struct {
+ struct list_head list;
+ char *name;
+ char *version;
+ char *interface;
+ int cpuport;
+ int ports;
+ int vlans;
+ 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_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(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 0000000000..32cf2b3960
--- /dev/null
+++ b/package/switch/src/switch-robo.c
@@ -0,0 +1,484 @@
+/*
+ * Broadcom BCM5325E/536x switch configuration module
+ *
+ * Copyright (C) 2005 Felix Fietkau <nbd@nbd.name>
+ * 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/config.h>
+#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 <asm/uaccess.h>
+
+#include "switch-core.h"
+#include "etc53xx.h"
+
+#define DRIVER_NAME "bcm53xx"
+#define DRIVER_VERSION "0.01"
+
+#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)
+
+static char *device;
+static int use_et = 0;
+static int is_5350 = 0;
+static struct ifreq ifr;
+static struct net_device *dev;
+static unsigned char port[6] = { 0, 1, 2, 3, 4, 8 };
+
+static int do_ioctl(int cmd, void *buf)
+{
+ mm_segment_t old_fs = get_fs();
+ int ret;
+
+ if (buf != NULL)
+ ifr.ifr_data = (caddr_t) buf;
+
+ set_fs(KERNEL_DS);
+ ret = dev->do_ioctl(dev, &ifr, cmd);
+ set_fs(old_fs);
+
+ return ret;
+}
+
+static u16 mdio_read(__u16 phy_id, __u8 reg)
+{
+ if (use_et) {
+ int args[2] = { reg };
+
+ if (phy_id != ROBO_PHY_ADDR) {
+ printk(
+ "Access to real 'phy' registers unavaliable.\n"
+ "Upgrade kernel driver.\n");
+
+ return 0xffff;
+ }
+
+
+ if (do_ioctl(SIOCGETCPHYRD, &args) < 0) {
+ printk("[%s:%d] SIOCGETCPHYRD failed!\n", __FILE__, __LINE__);
+ return 0xffff;
+ }
+
+ return args[1];
+ } else {
+ struct mii_ioctl_data *mii = (struct mii_ioctl_data *) &ifr.ifr_data;
+ mii->phy_id = phy_id;
+ mii->reg_num = reg;
+
+ if (do_ioctl(SIOCGMIIREG, NULL) < 0) {
+ printk("[%s:%d] SIOCGMIIREG failed!\n", __FILE__, __LINE__);
+
+ return 0xffff;
+ }
+
+ return mii->val_out;
+ }
+}
+
+static void mdio_write(__u16 phy_id, __u8 reg, __u16 val)
+{
+ if (use_et) {
+ int args[2] = { reg, val };
+
+ if (phy_id != ROBO_PHY_ADDR) {
+ printk(
+ "Access to real 'phy' registers unavaliable.\n"
+ "Upgrade kernel driver.\n");
+
+ return;
+ }
+
+ if (do_ioctl(SIOCSETCPHYWR, args) < 0) {
+ printk("[%s:%d] SIOCGETCPHYWR failed!\n", __FILE__, __LINE__);
+ return;
+ }
+ } else {
+ struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&ifr.ifr_data;
+
+ mii->phy_id = phy_id;
+ mii->reg_num = reg;
+ mii->val_in = val;
+
+ if (do_ioctl(SIOCSMIIREG, NULL) < 0) {
+ printk("[%s:%d] SIOCSMIIREG failed!\n", __FILE__, __LINE__);
+ 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("[%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_probe(char *devname)
+{
+ struct ethtool_drvinfo info;
+/*
+ int i;
+*/
+ __u32 phyid;
+
+ printk("Probing device %s: ", devname);
+ strcpy(ifr.ifr_name, devname);
+
+ if ((dev = dev_get_by_name(devname)) == NULL) {
+ printk("No such device\n");
+ return 1;
+ }
+
+ info.cmd = ETHTOOL_GDRVINFO;
+ if (do_ioctl(SIOCETHTOOL, (void *) &info) < 0) {
+ printk("SIOCETHTOOL: not supported\n");
+ return 1;
+ }
+
+ /* try access using MII ioctls - get phy address */
+ if (do_ioctl(SIOCGMIIPHY, NULL) < 0) {
+ use_et = 1;
+ } else {
+ /* got phy address check for robo address */
+ struct mii_ioctl_data *mii = (struct mii_ioctl_data *) &ifr.ifr_data;
+ if (mii->phy_id != ROBO_PHY_ADDR) {
+ printk("Invalid phy address (%d)\n", mii->phy_id);
+ return 1;
+ }
+ }
+
+ 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\n");
+ return 1;
+ }
+
+ is_5350 = robo_vlan5350();
+
+ printk("found!\n");
+ return 0;
+}
+
+
+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 (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 */
+ val16 = (nr) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */;
+ if (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);
+ }
+
+ 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 :
+ (1 << 1) | (1 << 2) | (1 << 3) /* RSV multicast */);
+ 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;
+ switch_vlan_config *c = switch_parse_vlan(d, buf);
+ int j;
+ __u16 val16;
+
+ if (c == NULL)
+ return -EINVAL;
+
+ /* disable switching */
+ set_switch(0);
+
+ /* reset vlans */
+ for (j = 0; j <= (is_5350 ? VLAN_ID_MAX5350 : VLAN_ID_MAX); j++) {
+ /* write config now */
+ val16 = (j) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */;
+ if (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, (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, 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;
+
+ device = strdup("ethX");
+ for (device[3] = '0'; (device[3] <= '3') && notfound; device[3]++) {
+ notfound = robo_probe(device);
+ }
+ device[3]--;
+
+ if (notfound) {
+ kfree(device);
+ return -ENODEV;
+ } else {
+ switch_config cfg[] = {
+ {"enable", handle_enable_read, handle_enable_write},
+ {"enable_vlan", handle_enable_vlan_read, handle_enable_vlan_write},
+ {"reset", NULL, handle_reset},
+ {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: device,
+ cpuport: 5,
+ ports: 6,
+ vlans: 16,
+ driver_handlers: cfg,
+ port_handlers: NULL,
+ vlan_handlers: vlan,
+ };
+
+ return switch_register_driver(&driver);
+ }
+}
+
+static void __exit robo_exit(void)
+{
+ switch_unregister_driver(DRIVER_NAME);
+ kfree(device);
+}
+
+
+MODULE_AUTHOR("Felix Fietkau <openwrt@nbd.name>");
+MODULE_LICENSE("GPL");
+
+module_init(robo_init);
+module_exit(robo_exit);
diff --git a/package/udev/Makefile b/package/udev/Makefile
new file mode 100644
index 0000000000..830ea6a664
--- /dev/null
+++ b/package/udev/Makefile
@@ -0,0 +1,69 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=udev
+PKG_VERSION:=077
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=ftp://ftp.kernel.org/pub/linux/utils/kernel/hotplug/ \
+ http://ftp.kernel.org/pub/linux/utils/kernel/hotplug/ \
+ ftp://ftp.de.kernel.org/pub/linux/utils/kernel/hotplug/ \
+ http://ftp.de.kernel.org/pub/linux/utils/kernel/hotplug/ \
+ ftp://ftp.fr.kernel.org/pub/linux/utils/kernel/hotplug/ \
+ http://ftp.fr.kernel.org/pub/linux/utils/kernel/hotplug/
+PKG_MD5SUM:=61ec646daf7795e9777e8f33975408fe
+PKG_CAT:=bzcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/udev
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=@LINUX_2_6
+ TITLE:=Dynamic device management subsystem
+ DESCRIPTION:=\
+ udev provides a dynamic device directory containing only the files for \\\
+ actually present devices. It creates or removes device node files in \\\
+ the /dev directory, or it renames network interfaces.
+ URL:=http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CROSS="$(TARGET_CROSS)" \
+ STRIP="/bin/true" \
+ OPTFLAGS="$(TARGET_CFLAGS)" \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ INSTALL="install -c" \
+ all install
+endef
+
+define Package/udev/install
+ install -d -m0775 $(1)/etc/udev
+ $(CP) $(PKG_INSTALL_DIR)/etc/udev/* $(1)/etc/udev/
+ install -d -m0775 $(1)/lib/udev
+ install -d -m0775 $(1)/sbin/
+ $(CP) $(PKG_INSTALL_DIR)/sbin/udev $(1)/sbin/
+ $(CP) $(PKG_INSTALL_DIR)/sbin/udevcontrol $(1)/sbin/
+ $(CP) $(PKG_INSTALL_DIR)/sbin/udevd $(1)/sbin/
+ $(CP) $(PKG_INSTALL_DIR)/sbin/udevsend $(1)/sbin/
+ $(CP) $(PKG_INSTALL_DIR)/sbin/udevstart $(1)/sbin/
+ install -d -m0775 $(1)/usr/bin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/udevinfo $(1)/usr/bin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/udevtest $(1)/usr/bin/
+ install -d -m0775 $(1)/usr/sbin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/udevmonitor $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,udev))
diff --git a/package/udev/patches/01-no_debug.patch b/package/udev/patches/01-no_debug.patch
new file mode 100644
index 0000000000..dcbc1051a9
--- /dev/null
+++ b/package/udev/patches/01-no_debug.patch
@@ -0,0 +1,21 @@
+diff -ruN udev-077-old/Makefile udev-077-new/Makefile
+--- udev-077-old/Makefile 2005-12-04 03:01:48.000000000 +0100
++++ udev-077-new/Makefile 2005-12-07 16:48:11.000000000 +0100
+@@ -136,7 +136,7 @@
+ # check if compiler option is supported
+ cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi;}
+
+-CFLAGS = -g -Wall -pipe -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64
++CFLAGS = -Wall -pipe -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64
+ WARNINGS = -Wstrict-prototypes -Wsign-compare -Wshadow \
+ -Wchar-subscripts -Wmissing-declarations -Wnested-externs \
+ -Wpointer-arith -Wcast-align -Wsign-compare -Wmissing-prototypes
+@@ -159,7 +159,7 @@
+
+ # if DEBUG is enabled, then we do not strip
+ ifeq ($(strip $(DEBUG)),true)
+- CFLAGS += -DDEBUG
++ CFLAGS += -g -DDEBUG
+ STRIPCMD =
+ endif
+
diff --git a/package/ueagle-atm/Makefile b/package/ueagle-atm/Makefile
new file mode 100644
index 0000000000..7e93fe1acd
--- /dev/null
+++ b/package/ueagle-atm/Makefile
@@ -0,0 +1,55 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 2767 2005-12-25 02:10:14Z wbx $
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=ueagle-atm
+PKG_VERSION:=1.0d1
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://castet.matthieu.free.fr/eagle/release/
+PKG_MD5SUM:=5da1fceb15168f4c7ad407a3e38ddecb
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+#FIXME: add dependency on kmod-usb-core
+define Package/kmod-ueagle-atm
+ SECTION:=kernel
+ CATEGORY:=Kernel drivers
+ DEPENDS:=@LINUX_2_6_BRCM @PACKAGE_KMOD_USB
+ TITLE:=Driver for Eagle 8051 based USB ADSL modems
+ URL:=http://www.eagle-usb.org/
+ VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE)
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ TARGET="$(HAL_TARGET)" \
+ KERNELDIR="$(LINUX_DIR)" \
+ all
+endef
+
+define Package/kmod-ueagle-atm/install
+ install -d -m0755 $(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) $(PKG_BUILD_DIR)/driver/ueagle-atm.$(LINUX_KMOD_SUFFIX) \
+ $(PKG_BUILD_DIR)/usbatm_iso/usbatm.$(LINUX_KMOD_SUFFIX) \
+ $(1)/lib/modules/$(LINUX_VERSION)/
+ install -d -m0755 $(1)/etc/modules.d
+ install -m0644 ./files/$(PKG_NAME).modules \
+ $(1)/etc/modules.d/10-$(PKG_NAME)
+endef
+
+$(eval $(call BuildPackage,kmod-ueagle-atm))
diff --git a/package/ueagle-atm/files/ueagle-atm.modules b/package/ueagle-atm/files/ueagle-atm.modules
new file mode 100644
index 0000000000..6343f50e73
--- /dev/null
+++ b/package/ueagle-atm/files/ueagle-atm.modules
@@ -0,0 +1,2 @@
+usbatm
+ueagle-atm
diff --git a/package/ueagle-atm/patches/100-compile_fix.patch b/package/ueagle-atm/patches/100-compile_fix.patch
new file mode 100644
index 0000000000..b8e70a2ff3
--- /dev/null
+++ b/package/ueagle-atm/patches/100-compile_fix.patch
@@ -0,0 +1,11 @@
+diff -Nur ueagle-atm-1.0d1/driver/ueagle.c ueagle-atm-1.0d1.patched/driver/ueagle.c
+--- ueagle-atm-1.0d1/driver/ueagle.c 2005-11-19 18:36:04.000000000 +0100
++++ ueagle-atm-1.0d1.patched/driver/ueagle.c 2006-03-29 02:03:43.000000000 +0200
+@@ -1652,7 +1652,6 @@
+ * USB driver descriptor
+ */
+ static struct usb_driver uea_driver = {
+- .owner = THIS_MODULE,
+ .name = "ueagle-atm",
+ .id_table = uea_ids,
+ .probe = uea_probe,
diff --git a/package/util-linux/Makefile b/package/util-linux/Makefile
new file mode 100644
index 0000000000..8ca8052ea1
--- /dev/null
+++ b/package/util-linux/Makefile
@@ -0,0 +1,93 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 3822 2006-05-24 07:01:52Z nico $
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=util-linux
+PKG_VERSION:=2.12r
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=ftp://ftp.kernel.org/pub/linux/utils/$(PKG_NAME)/ \
+ http://ftp.kernel.org/pub/linux/utils/$(PKG_NAME)/ \
+ ftp://ftp.de.kernel.org/pub/linux/utils/$(PKG_NAME)/ \
+ http://ftp.de.kernel.org/pub/linux/utils/$(PKG_NAME)/
+PKG_MD5SUM:=c261230b27fc0fbcc287c76884caf2d3
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+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
+
+define Package/fdisk
+ $(call Package/util-linux/Default)
+ TITLE:=Partition table manipulation utility
+ DESCRIPTION:=\
+ This package contains an utility for managing disk partition tables.
+ URL:=http://www.kernel.org/pub/linux/utils/util-linux/
+endef
+
+define Package/losetup
+ $(call Package/util-linux/Default)
+ TITLE:=Loopback devices setup and control utility
+ DESCRIPTION:=\
+ This package contains an utility for managing loopback devices.
+endef
+
+define Package/swap-utils
+ $(call Package/util-linux/Default)
+ TITLE:=Swap space management utilities
+ DESCRIPTION:=\
+ This package contains a collection of tools for managing swap space: \\\
+ - mkswap\\\
+ - swapon\\\
+ - swapoff
+endef
+
+define Build/Compile
+ $(call Build/Compile/Default, \
+ OPT="$(TARGET_CFLAGS)" \
+ INSTALLSUID="install -m 4755" \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ all install \
+ )
+endef
+
+define Package/Template
+ @if [ \! -f "$(PKG_INSTALL_DIR)/$(1)" ]; then \
+ rm -f $(PKG_BUILD_DIR)/.built; \
+ $(MAKE) $(PKG_BUILD_DIR)/.built; \
+ fi
+ install -d -m0755 $(2)
+ $(CP) $(PKG_INSTALL_DIR)/$(1) $(2)/
+endef
+
+define Package/fdisk/install
+ $(call Package/Template,sbin/fdisk,$(1)/usr/sbin)
+endef
+
+define Package/losetup/install
+ $(call Package/Template,sbin/losetup,$(1)/usr/sbin)
+endef
+
+define Package/swap-utils/install
+ $(call Package/Template,sbin/mkswap,$(1)/usr/sbin)
+ $(call Package/Template,sbin/swapon,$(1)/usr/sbin)
+ $(call Package/Template,sbin/swapoff,$(1)/usr/sbin)
+endef
+
+$(eval $(call BuildPackage,fdisk))
+$(eval $(call BuildPackage,losetup))
+$(eval $(call BuildPackage,swap-utils))
diff --git a/package/util-linux/patches/501-mconfig.patch b/package/util-linux/patches/501-mconfig.patch
new file mode 100644
index 0000000000..67e6530de9
--- /dev/null
+++ b/package/util-linux/patches/501-mconfig.patch
@@ -0,0 +1,68 @@
+--- util-linux-2.12r-orig/MCONFIG 2004-12-13 00:15:48.000000000 +0100
++++ util-linux-2.12r/MCONFIG 2005-10-03 17:54:15.945049312 +0200
+@@ -16,8 +16,8 @@
+ # Select for ARCH one of intel, alpha, sparc, arm, m68k, mips
+ # Select for CPU i386 if the binaries must be able to run on an intel 386
+ # (by default i486 code is generated, see below)
+-CPU=$(shell uname -m)
+-ARCH=$(shell echo $(CPU) | sed 's/i.86/intel/;s/arm.*/arm/')
++CPU=
++ARCH=mips
+
+ # If HAVE_PAM is set to "yes", then login, chfn, chsh, and newgrp
+ # will use PAM for authentication. Additionally, passwd will not be
+@@ -64,12 +64,12 @@
+ # If HAVE_WRITE is set to "yes", then write will not be built or
+ # installed from the misc-utils subdirectory.
+ # (There is a network aware write in netwrite from NetKit 0.16 or later.)
+-HAVE_WRITE=no
++HAVE_WRITE=yes
+
+ # If HAVE_GETTY is set to "yes", then agetty will not be built or
+ # installed from the login-utils subdirectory. Note that agetty can
+ # co-exist with other gettys, so this option should never be used.
+-HAVE_GETTY=no
++HAVE_GETTY=yes
+
+ # If USE_TTY_GROUP is set to "yes", then wall and write will be installed
+ # setgid to the "tty" group, and mesg will only set the group write bit.
+@@ -82,13 +82,13 @@
+ # If HAVE_KILL is set to "yes", then kill will not be built or
+ # installed from the misc-utils subdirectory.
+ # (There is also a kill in the procps package.)
+-HAVE_KILL=no
++HAVE_KILL=yes
+
+ # If ALLOW_VCS_USE is set to "yes", then login will chown /dev/vcsN
+ # to the current user, allowing her to make a screendump and do other
+ # nifty things on the console, but also allowing him to keep an open
+ # file descriptor after logging out to trick the next user.
+-ALLOW_VCS_USE=yes
++ALLOW_VCS_USE=no
+
+ # If DO_STAT_MAIL is set to "yes", then login will stat() the mailbox
+ # and tell the user that she has new mail. This can hang the login if
+@@ -102,19 +102,19 @@
+ # If HAVE_SLN is set to "yes", then sln won't be installed
+ # (but the man page sln.8 will be installed anyway).
+ # sln also comes with libc and glibc.
+-HAVE_SLN=no
++HAVE_SLN=yes
+
+ # If HAVE_FDUTILS is set to "yes", then setfdprm won't be installed.
+-HAVE_FDUTILS=no
++HAVE_FDUTILS=yes
+
+ # If SILENT_PG is set to "yes", then pg will not ring the bell
+ # when an invalid key is pressed
+-SILENT_PG=no
++SILENT_PG=yes
+
+ # If configure decides that Native Language Support (NLS) is available,
+ # it sets MAY_ENABLE_NLS in defines.h. If you don't want NLS, set
+ # DISABLE_NLS to "yes".
+-DISABLE_NLS=no
++DISABLE_NLS=yes
+
+ # Different optimizations for different cpus.
+ # Before gcc 2.8.0 only -m486
diff --git a/package/util-linux/patches/601-util-linux-2.12r-umount-no-special.patch b/package/util-linux/patches/601-util-linux-2.12r-umount-no-special.patch
new file mode 100644
index 0000000000..d79598fc84
--- /dev/null
+++ b/package/util-linux/patches/601-util-linux-2.12r-umount-no-special.patch
@@ -0,0 +1,11 @@
+--- util-linux-2.12r.old/mount/umount.c
++++ util-linux-2.12r/mount/umount.c
+@@ -31,7 +31,7 @@
+ #include <arpa/inet.h>
+ #endif
+
+-#if defined(MNT_FORCE) && !defined(__sparc__) && !defined(__arm__)
++#if defined(MNT_FORCE)
+ /* Interesting ... it seems libc knows about MNT_FORCE and presumably
+ about umount2 as well -- need not do anything */
+ #else /* MNT_FORCE */
diff --git a/package/wireless-tools/Makefile b/package/wireless-tools/Makefile
new file mode 100644
index 0000000000..c19ff7613d
--- /dev/null
+++ b/package/wireless-tools/Makefile
@@ -0,0 +1,70 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=wireless-tools
+PKG_VERSION:=28
+PKG_RELEASE:=1
+
+PKG_SOURCE:=wireless_tools.$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux
+PKG_MD5SUM:=599c94497f9c9073c7b052d3dcb7cd16
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/wireless_tools.28
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/wireless-tools
+ SECTION:=net
+ CATEGORY:=Base system
+ DEFAULT:=y
+ TITLE:=Tools for manipulating Linux Wireless Extensions
+ DESCRIPTION:=\
+ This package contains a collection of tools for configuring wireless \\\
+ adapters implementing the "Linux Wireless Extensions".
+ URL:=http://hplabs.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html
+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." \
+ libiw.so.28 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 $(STAGING_DIR)/usr/include
+ $(CP) $(PKG_BUILD_DIR)/{iwlib,wireless}.h $(STAGING_DIR)/usr/include/
+ mkdir -p $(STAGING_DIR)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/libiw.so* $(STAGING_DIR)/usr/lib/
+ ln -sf libiw.so.28 $(STAGING_DIR)/usr/lib/libiw.so
+endef
+
+define Build/UninstallDev
+ rm -f $(STAGING_DIR)/usr/include/{iwlib,wireless}.h \
+ $(STAGING_DIR)/usr/lib/libiw.so*
+endef
+
+define Package/wireless-tools/install
+ install -d -m0755 $(1)/usr/lib
+ install -m0755 $(PKG_BUILD_DIR)/libiw.so.28 $(1)/usr/lib/
+ install -d -m0755 $(1)/usr/sbin
+ install -m0755 $(PKG_INSTALL_DIR)/usr/sbin/iw{config,getid,list,priv,spy} $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,wireless-tools))
diff --git a/package/wireless-tools/patches/debian-2.patch b/package/wireless-tools/patches/debian-2.patch
new file mode 100644
index 0000000000..ba8755b705
--- /dev/null
+++ b/package/wireless-tools/patches/debian-2.patch
@@ -0,0 +1,35 @@
+--- wireless-tools-27.orig/iwlib.c
++++ wireless-tools-27/iwlib.c
+@@ -622,6 +622,7 @@
+ {
+ struct iwreq wrq;
+
++ memset((char *) &wrq, 0, sizeof(struct iwreq));
+ memset((char *) info, 0, sizeof(struct wireless_config));
+
+ /* Get wireless name */
+--- wireless-tools-27.orig/Makefile
++++ wireless-tools-27/Makefile
+@@ -64,8 +64,8 @@
+ # 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
+@@ -81,9 +81,9 @@
+ 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)
+ PICFLAG=-fPIC
diff --git a/package/wlcompat/Makefile b/package/wlcompat/Makefile
new file mode 100644
index 0000000000..fc66c90f50
--- /dev/null
+++ b/package/wlcompat/Makefile
@@ -0,0 +1,77 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=kmod-wlcompat
+PKG_RELEASE:=4
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/kmod-wlcompat/Default
+ SECTION:=kernel
+ CATEGORY:=Kernel drivers
+ DEPENDS:=kmod-brcm-wl
+ TITLE:=Broadcom wl wrapper module
+ DESCRIPTION:=\
+ This package contains a wrapper module, that provides Wireless Extension \\\
+ support for the proprietary Broadcom wl module.
+ VERSION:=$(LINUX_VERSION)+$(BOARD)-$(PKG_RELEASE)
+endef
+
+define Package/kmod-wlcompat
+ $(call Package/kmod-wlcompat/Default)
+ DEFAULT:=y
+endef
+
+define Package/kmod-wlcompat-debug
+ $(call Package/kmod-wlcompat/Default)
+ TITLE+= (debug)
+ DESCRIPTION+=\\\
+ \\\
+ This is a debugging version.
+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="-DDEBUG -I$(LINUX_DIR)/arch/mips/bcm947xx/include -I$(PKG_BUILD_DIR)/include" \
+ modules
+ mv $(PKG_BUILD_DIR)/wlcompat.o $(PKG_BUILD_DIR)/wlcompat-debug.o
+ $(MAKE) -C "$(LINUX_DIR)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ ARCH="$(LINUX_KARCH)" \
+ SUBDIRS="$(PKG_BUILD_DIR)" \
+ EXTRA_CFLAGS="-I$(LINUX_DIR)/arch/mips/bcm947xx/include -I$(PKG_BUILD_DIR)/include" \
+ modules
+endef
+
+define Package/kmod-wlcompat/install
+ install -d -m0755 $(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) $(PKG_BUILD_DIR)/wlcompat.o $(1)/lib/modules/$(LINUX_VERSION)/
+ install -d -m0755 $(1)/etc/modules.d
+ echo "wlcompat" > $(1)/etc/modules.d/30-wlcompat
+endef
+
+define Package/kmod-wlcompat-debug/install
+ install -d -m0755 $(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) $(PKG_BUILD_DIR)/wlcompat-debug.o $(1)/lib/modules/$(LINUX_VERSION)/
+endef
+
+$(eval $(call BuildPackage,kmod-wlcompat))
+$(eval $(call BuildPackage,kmod-wlcompat-debug))
diff --git a/package/wlcompat/src/Makefile b/package/wlcompat/src/Makefile
new file mode 100644
index 0000000000..4290d9a33a
--- /dev/null
+++ b/package/wlcompat/src/Makefile
@@ -0,0 +1,19 @@
+# $Id$
+#
+# 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 := wlcompat.o
+
+ifeq ($(MAKING_MODULES),1)
+export-objs := wlcompat.o
+
+-include $(TOPDIR)/Rules.make
+endif
diff --git a/package/wlcompat/src/include/bcmnvram.h b/package/wlcompat/src/include/bcmnvram.h
new file mode 100644
index 0000000000..3c452634e8
--- /dev/null
+++ b/package/wlcompat/src/include/bcmnvram.h
@@ -0,0 +1,148 @@
+/*
+ * NVRAM variable manipulation
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#ifndef _bcmnvram_h_
+#define _bcmnvram_h_
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+#include <typedefs.h>
+
+struct nvram_header {
+ uint32 magic;
+ uint32 len;
+ uint32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:27 init, mem. test 28, 29-31 reserved */
+ uint32 config_refresh; /* 0:15 config, 16:31 refresh */
+ uint32 config_ncdl; /* ncdl values for memc */
+};
+
+struct nvram_tuple {
+ char *name;
+ char *value;
+ struct nvram_tuple *next;
+};
+
+/*
+ * Initialize NVRAM access. May be unnecessary or undefined on certain
+ * platforms.
+ */
+extern int nvram_init(void *sbh);
+
+/*
+ * Disable NVRAM access. May be unnecessary or undefined on certain
+ * platforms.
+ */
+extern void nvram_exit(void);
+
+/*
+ * Get the value of an NVRAM variable. The pointer returned may be
+ * invalid after a set.
+ * @param name name of variable to get
+ * @return value of variable or NULL if undefined
+ */
+extern char * nvram_get(const char *name);
+
+/*
+ * Get the value of an NVRAM variable.
+ * @param name name of variable to get
+ * @return value of variable or NUL if undefined
+ */
+#define nvram_safe_get(name) (nvram_get(name) ? : "")
+
+#define nvram_safe_unset(name) ({ \
+ if(nvram_get(name)) \
+ nvram_unset(name); \
+})
+
+#define nvram_safe_set(name, value) ({ \
+ if(!nvram_get(name) || strcmp(nvram_get(name), value)) \
+ nvram_set(name, value); \
+})
+
+/*
+ * Match an NVRAM variable.
+ * @param name name of variable to match
+ * @param match value to compare against value of variable
+ * @return TRUE if variable is defined and its value is string equal
+ * to match or FALSE otherwise
+ */
+static INLINE int
+nvram_match(char *name, char *match) {
+ const char *value = nvram_get(name);
+ return (value && !strcmp(value, match));
+}
+
+/*
+ * Inversely match an NVRAM variable.
+ * @param name name of variable to match
+ * @param match value to compare against value of variable
+ * @return TRUE if variable is defined and its value is not string
+ * equal to invmatch or FALSE otherwise
+ */
+static INLINE int
+nvram_invmatch(char *name, char *invmatch) {
+ const char *value = nvram_get(name);
+ return (value && strcmp(value, invmatch));
+}
+
+/*
+ * Set the value of an NVRAM variable. The name and value strings are
+ * copied into private storage. Pointers to previously set values
+ * may become invalid. The new value may be immediately
+ * retrieved but will not be permanently stored until a commit.
+ * @param name name of variable to set
+ * @param value value of variable
+ * @return 0 on success and errno on failure
+ */
+extern int nvram_set(const char *name, const char *value);
+
+/*
+ * Unset an NVRAM variable. Pointers to previously set values
+ * remain valid until a set.
+ * @param name name of variable to unset
+ * @return 0 on success and errno on failure
+ * NOTE: use nvram_commit to commit this change to flash.
+ */
+extern int nvram_unset(const char *name);
+
+/*
+ * Commit NVRAM variables to permanent storage. All pointers to values
+ * may be invalid after a commit.
+ * NVRAM values are undefined after a commit.
+ * @return 0 on success and errno on failure
+ */
+extern int nvram_commit(void);
+
+/*
+ * Get all NVRAM variables (format name=value\0 ... \0\0).
+ * @param buf buffer to store variables
+ * @param count size of buffer in bytes
+ * @return 0 on success and errno on failure
+ */
+extern int nvram_getall(char *buf, int count);
+
+extern int file2nvram(char *filename, char *varname);
+extern int nvram2file(char *varname, char *filename);
+
+#endif /* _LANGUAGE_ASSEMBLY */
+
+#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */
+#define NVRAM_VERSION 1
+#define NVRAM_HEADER_SIZE 20
+#define NVRAM_SPACE 0x8000
+#define FLASH_BASE 0xbfc00000 /* Extif core */
+#define FLASH_MIN 0x00100000 /* Minimum flash size */
+#define FLASH_MAX 0x00400000 /* Maximum flash size with extif */
+
+#endif /* _bcmnvram_h_ */
diff --git a/package/wlcompat/src/include/bcmutils.h b/package/wlcompat/src/include/bcmutils.h
new file mode 100644
index 0000000000..05ad41d9d8
--- /dev/null
+++ b/package/wlcompat/src/include/bcmutils.h
@@ -0,0 +1,157 @@
+/*
+ * Misc useful os-independent macros and functions.
+ *
+ * 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.
+ * $Id$
+ */
+
+#ifndef _bcmutils_h_
+#define _bcmutils_h_
+
+#ifndef MIN
+#define MIN(a, b) (((a)<(b))?(a):(b))
+#endif
+
+#ifndef MAX
+#define MAX(a, b) (((a)>(b))?(a):(b))
+#endif
+
+#define CEIL(x, y) (((x) + ((y)-1)) / (y))
+#define ROUNDUP(x, y) ((((ulong)(x)+((y)-1))/(y))*(y))
+#define ISALIGNED(a, x) (((uint)(a) & ((x)-1)) == 0)
+#define ISPOWEROF2(x) ((((x)-1)&(x))==0)
+#define OFFSETOF(type, member) ((uint) &((type *)0)->member)
+#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
+
+/* bit map related macros */
+#ifndef setbit
+#define NBBY 8 /* 8 bits per byte */
+#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
+#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
+#define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
+#define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
+#endif
+
+#define NBITS(type) (sizeof (type) * 8)
+
+#define _BCM_U 0x01 /* upper */
+#define _BCM_L 0x02 /* lower */
+#define _BCM_D 0x04 /* digit */
+#define _BCM_C 0x08 /* cntrl */
+#define _BCM_P 0x10 /* punct */
+#define _BCM_S 0x20 /* white space (space/lf/tab) */
+#define _BCM_X 0x40 /* hex digit */
+#define _BCM_SP 0x80 /* hard space (0x20) */
+
+extern unsigned char bcm_ctype[];
+#define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)])
+
+#define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0)
+#define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0)
+#define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0)
+#define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0)
+#define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0)
+#define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0)
+#define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0)
+#define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0)
+#define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0)
+#define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0)
+#define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0)
+
+/*
+ * Spin at most 'us' microseconds while 'exp' is true.
+ * Caller should explicitly test 'exp' when this completes
+ * and take appropriate error action if 'exp' is still true.
+ */
+#define SPINWAIT(exp, us) { \
+ uint countdown = (us) + 9; \
+ while ((exp) && (countdown >= 10)) {\
+ OSL_DELAY(10); \
+ countdown -= 10; \
+ } \
+}
+
+/* generic osl packet queue */
+struct pktq {
+ void *head; /* first packet to dequeue */
+ void *tail; /* last packet to dequeue */
+ uint len; /* number of queued packets */
+ uint maxlen; /* maximum number of queued packets */
+ bool priority; /* enqueue by packet priority */
+};
+#define DEFAULT_QLEN 128
+
+#define pktq_len(q) ((q)->len)
+#define pktq_avail(q) ((q)->maxlen - (q)->len)
+#define pktq_head(q) ((q)->head)
+#define pktq_full(q) ((q)->len >= (q)->maxlen)
+
+/* crc defines */
+#define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */
+#define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */
+#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */
+#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */
+#define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */
+#define CRC32_GOOD_VALUE 0xdebb20e3 /* Good final CRC32 checksum value */
+
+/* tag_ID/length/value_buffer tuple */
+typedef struct bcm_tlv {
+ uint8 id;
+ uint8 len;
+ uint8 data[1];
+} bcm_tlv_t;
+
+/* Check that bcm_tlv_t fits into the given buflen */
+#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (buflen) >= 2 + (elt)->len)
+
+/* buffer length for ethernet address from bcm_ether_ntoa() */
+#define ETHER_ADDR_STR_LEN 18
+
+/*
+* load 32-bit value from unaligned byte array
+*/
+#ifdef IL_BIGENDIAN
+#define load32_ua(a) ((((uint8 *)(a))[0] << 24) + (((uint8 *)(a))[1] << 16) + \
+ (((uint8 *)(a))[2] << 8) + ((uint8 *)(a))[3])
+#else
+#define load32_ua(a) ((((uint8 *)(a))[3] << 24) + (((uint8 *)(a))[2] << 16) + \
+ (((uint8 *)(a))[1] << 8) + ((uint8 *)(a))[0])
+#endif
+
+/* externs */
+extern uint bcm_atoi(char *s);
+extern uchar bcm_toupper(uchar c);
+extern ulong bcm_strtoul(char *cp, char **endp, uint base);
+extern void deadbeef(char *p, uint len);
+extern void prhex(char *msg, uchar *buf, uint len);
+extern void prpkt(char *msg, void *drv, void *p0);
+extern uint pktcopy(void *drv, void *p, uint offset, int len, uchar *buf);
+extern uint pkttotlen(void *drv, void *);
+extern uchar *bcm_ether_ntoa(char *ea, char *buf);
+extern int bcm_ether_atoe(char *p, char *ea);
+extern void bcm_mdelay(uint ms);
+extern char *getvar(char *vars, char *name);
+extern int getintvar(char *vars, char *name);
+extern char *bcmstrstr(char *haystack, char *needle);
+
+extern uint8 crc8(uint8 *p, uint nbytes, uint8 crc);
+extern uint16 crc16(uint8 *p, uint nbytes, uint16 crc);
+extern uint32 crc32(uint8 *p, uint nbytes, uint32 crc);
+extern bcm_tlv_t *bcm_next_tlv(bcm_tlv_t *elt, int *buflen);
+extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key);
+extern bcm_tlv_t *bcm_parse_ordered_tlvs(void *buf, int buflen, uint key);
+extern void pktq_init(struct pktq *q, uint maxlen, bool priority);
+extern bool pktenq(struct pktq *q, void *p, bool lifo);
+extern void *pktdeq(struct pktq *q);
+
+#define bcmlog(fmt, a1, a2)
+#define bcmdumplog(buf, size) *buf = '\0'
+#define bcmdumplogent(buf, idx) -1
+
+#endif /* _bcmutils_h_ */
diff --git a/package/wlcompat/src/include/cy_conf.h b/package/wlcompat/src/include/cy_conf.h
new file mode 100644
index 0000000000..dbe387b83b
--- /dev/null
+++ b/package/wlcompat/src/include/cy_conf.h
@@ -0,0 +1,69 @@
+
+#define DNSMASQ_SUPPORT 1
+#define CONFIG_DNSMASQ y
+#define UDHCPD_SUPPORT 1
+#define CONFIG_UDHCPD y
+#define UDHCPC_SUPPORT 1
+#define CONFIG_UDHCPC y
+#define PPPOE_SUPPORT 1
+#define CONFIG_PPPOE y
+#define PPTP_SUPPORT 1
+#define CONFIG_PPTP y
+#define L2TP_SUPPORT 1
+#define CONFIG_L2TP y
+#define PPPD_SUPPORT 1
+#define CONFIG_PPPD y
+#define ZEBRA_SUPPORT 1
+#define CONFIG_ZEBRA y
+#define TFTPD_SUPPORT 1
+#define CONFIG_TFTPD y
+#define DDNS_SUPPORT 1
+#define CONFIG_DDNS y
+#define CRON_SUPPORT 1
+#define CONFIG_CRON y
+#define HTTPD_SUPPORT 1
+#define CONFIG_HTTPD y
+#define GET_POST_SUPPORT 1
+#define CONFIG_GET_POST y
+
+#if 1
+#define HEARTBEAT_SUPPORT 1
+#define CONFIG_HEARTBEAT y
+#define MULTICAST_SUPPORT 1
+#define CONFIG_MULTICAST y
+#define SETUP_WIZARD_SUPPORT 1
+#define CONFIG_SETUP_WIZARD y
+#define PARENTAL_CONTROL_SUPPORT 1
+#define CONFIG_PARENTAL_CONTROL y
+#define HTTPS_SUPPORT 1
+#define CONFIG_HTTPS y
+#define EOU_SUPPORT 1
+#define CONFIG_EOU y
+#define EZC_SUPPORT 1
+#define CONFIG_EZC y
+#define WRITE_MAC_SUPPORT 1
+#define CONFIG_WRITE_MAC y
+#define DIAG_SUPPORT 1
+#define CONFIG_DIAG y
+#endif
+
+#define SPEED_BOOSTER_SUPPORT 1
+#define CONFIG_SPEED_BOOSTER y
+#define XBOX_SUPPORT 1
+#define CONFIG_XBOX y
+
+#if 0
+#define MPPPOE_SUPPORT 1
+#define CONFIG_MPPPOE y
+#define UNNUMBERIP_SUPPORT 1
+#define CONFIG_UNNUMBERIP y
+#endif
+
+#define WL_STA_SUPPORT 1
+#define CONFIG_WL_STA y
+#define BACKUP_RESTORE_SUPPORT 1
+#define CONFIG_BACKUP_RESTORE y
+#define PORT_TRIGGER_SUPPORT 1
+#define CONFIG_PORT_TRIGGER y
+#define HW_QOS_SUPPORT 1
+#define CONFIG_HW_QOS y
diff --git a/package/wlcompat/src/include/epivers.h b/package/wlcompat/src/include/epivers.h
new file mode 100644
index 0000000000..e174fb50d8
--- /dev/null
+++ b/package/wlcompat/src/include/epivers.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ *
+ * $Id$
+ *
+*/
+
+#ifndef _epivers_h_
+#define _epivers_h_
+
+#ifdef linux
+#include <linux/config.h>
+#endif
+
+/* Vendor Name, ASCII, 32 chars max */
+#ifdef COMPANYNAME
+#define HPNA_VENDOR COMPANYNAME
+#else
+#define HPNA_VENDOR "Broadcom Corporation"
+#endif
+
+/* Driver Date, ASCII, 32 chars max */
+#define HPNA_DRV_BUILD_DATE __DATE__
+
+/* Hardware Manufacture Date, ASCII, 32 chars max */
+#define HPNA_HW_MFG_DATE "Not Specified"
+
+/* See documentation for Device Type values, 32 values max */
+#ifndef HPNA_DEV_TYPE
+
+#if defined(CONFIG_BRCM_VJ)
+#define HPNA_DEV_TYPE { CDCF_V0_DEVICE_DISPLAY }
+
+#elif defined(CONFIG_BCRM_93725)
+#define HPNA_DEV_TYPE { CDCF_V0_DEVICE_CM_BRIDGE, CDCF_V0_DEVICE_DISPLAY }
+
+#else
+#define HPNA_DEV_TYPE { CDCF_V0_DEVICE_PCINIC }
+
+#endif
+
+#endif /* !HPNA_DEV_TYPE */
+
+
+#define EPI_MAJOR_VERSION 3
+
+#define EPI_MINOR_VERSION 60
+
+#define EPI_RC_NUMBER 13
+
+#define EPI_INCREMENTAL_NUMBER 0
+
+#define EPI_BUILD_NUMBER 0
+
+#define EPI_VERSION 3,60,13,0
+
+#define EPI_VERSION_NUM 0x033c0d00
+
+/* Driver Version String, ASCII, 32 chars max */
+#define EPI_VERSION_STR "3.60.13.0"
+#define EPI_ROUTER_VERSION_STR "3.61.13.0"
+
+#endif /* _epivers_h_ */
diff --git a/package/wlcompat/src/include/proto/802.11.h b/package/wlcompat/src/include/proto/802.11.h
new file mode 100644
index 0000000000..ea57850ce5
--- /dev/null
+++ b/package/wlcompat/src/include/proto/802.11.h
@@ -0,0 +1,852 @@
+/*
+ * 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.
+ *
+ * Fundamental types and constants relating to 802.11
+ *
+ * $Id$
+ */
+
+#ifndef _802_11_H_
+#define _802_11_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+#ifndef _NET_ETHERNET_H_
+#include <proto/ethernet.h>
+#endif
+
+/* enable structure packing */
+#if !defined(__GNUC__)
+#pragma pack(1)
+#endif
+
+/* some platforms require stronger medicine */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#define PACKED
+#endif
+
+
+#define DOT11_TU_TO_US 1024 /* 802.11 Time Unit is 1024 microseconds */
+
+/* Generic 802.11 frame constants */
+#define DOT11_A3_HDR_LEN 24
+#define DOT11_A4_HDR_LEN 30
+#define DOT11_MAC_HDR_LEN DOT11_A3_HDR_LEN
+#define DOT11_FCS_LEN 4
+#define DOT11_ICV_LEN 4
+#define DOT11_ICV_AES_LEN 8
+#define DOT11_QOS_LEN 2
+
+#define DOT11_KEY_INDEX_SHIFT 6
+#define DOT11_IV_LEN 4
+#define DOT11_IV_TKIP_LEN 8
+#define DOT11_IV_AES_OCB_LEN 4
+#define DOT11_IV_AES_CCM_LEN 8
+
+/* Includes MIC */
+#define DOT11_MAX_MPDU_BODY_LEN 2304
+/* A4 header + QoS + CCMP + PDU + ICV + FCS = 2352 */
+#define DOT11_MAX_MPDU_LEN (DOT11_A4_HDR_LEN + \
+ DOT11_QOS_LEN + \
+ DOT11_IV_AES_CCM_LEN + \
+ DOT11_MAX_MPDU_BODY_LEN + \
+ DOT11_ICV_LEN + \
+ DOT11_FCS_LEN)
+
+#define DOT11_MAX_SSID_LEN 32
+
+/* dot11RTSThreshold */
+#define DOT11_DEFAULT_RTS_LEN 2347
+#define DOT11_MAX_RTS_LEN 2347
+
+/* dot11FragmentationThreshold */
+#define DOT11_MIN_FRAG_LEN 256
+#define DOT11_MAX_FRAG_LEN 2346 /* Max frag is also limited by aMPDUMaxLength of the attached PHY */
+#define DOT11_DEFAULT_FRAG_LEN 2346
+
+/* dot11BeaconPeriod */
+#define DOT11_MIN_BEACON_PERIOD 1
+#define DOT11_MAX_BEACON_PERIOD 0xFFFF
+
+/* dot11DTIMPeriod */
+#define DOT11_MIN_DTIM_PERIOD 1
+#define DOT11_MAX_DTIM_PERIOD 0xFF
+
+/* 802.2 LLC/SNAP header used by 802.11 per 802.1H */
+#define DOT11_LLC_SNAP_HDR_LEN 8
+#define DOT11_OUI_LEN 3
+struct dot11_llc_snap_header {
+ uint8 dsap; /* always 0xAA */
+ uint8 ssap; /* always 0xAA */
+ uint8 ctl; /* always 0x03 */
+ uint8 oui[DOT11_OUI_LEN]; /* RFC1042: 0x00 0x00 0x00
+ Bridge-Tunnel: 0x00 0x00 0xF8 */
+ uint16 type; /* ethertype */
+} PACKED;
+
+/* RFC1042 header used by 802.11 per 802.1H */
+#define RFC1042_HDR_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN)
+
+/* Generic 802.11 MAC header */
+/*
+ * N.B.: This struct reflects the full 4 address 802.11 MAC header.
+ * The fields are defined such that the shorter 1, 2, and 3
+ * address headers just use the first k fields.
+ */
+struct dot11_header {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr a1; /* address 1 */
+ struct ether_addr a2; /* address 2 */
+ struct ether_addr a3; /* address 3 */
+ uint16 seq; /* sequence control */
+ struct ether_addr a4; /* address 4 */
+} PACKED;
+
+/* Control frames */
+
+struct dot11_rts_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+ struct ether_addr ta; /* transmitter address */
+} PACKED;
+#define DOT11_RTS_LEN 16
+
+struct dot11_cts_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+} PACKED;
+#define DOT11_CTS_LEN 10
+
+struct dot11_ack_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+} PACKED;
+#define DOT11_ACK_LEN 10
+
+struct dot11_ps_poll_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* AID */
+ struct ether_addr bssid; /* receiver address, STA in AP */
+ struct ether_addr ta; /* transmitter address */
+} PACKED;
+#define DOT11_PS_POLL_LEN 16
+
+struct dot11_cf_end_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+ struct ether_addr bssid; /* transmitter address, STA in AP */
+} PACKED;
+#define DOT11_CS_END_LEN 16
+
+/* Management frame header */
+struct dot11_management_header {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr da; /* receiver address */
+ struct ether_addr sa; /* transmitter address */
+ struct ether_addr bssid; /* BSS ID */
+ uint16 seq; /* sequence control */
+} PACKED;
+#define DOT11_MGMT_HDR_LEN 24
+
+/* Management frame payloads */
+
+struct dot11_bcn_prb {
+ uint32 timestamp[2];
+ uint16 beacon_interval;
+ uint16 capability;
+} PACKED;
+#define DOT11_BCN_PRB_LEN 12
+
+struct dot11_auth {
+ uint16 alg; /* algorithm */
+ uint16 seq; /* sequence control */
+ uint16 status; /* status code */
+} PACKED;
+#define DOT11_AUTH_FIXED_LEN 6 /* length of auth frame without challenge info elt */
+
+struct dot11_assoc_req {
+ uint16 capability; /* capability information */
+ uint16 listen; /* listen interval */
+} PACKED;
+
+struct dot11_assoc_resp {
+ uint16 capability; /* capability information */
+ uint16 status; /* status code */
+ uint16 aid; /* association ID */
+} PACKED;
+
+struct dot11_action_measure {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} PACKED;
+#define DOT11_ACTION_MEASURE_LEN 3
+
+/**************
+ 802.11h related definitions.
+**************/
+typedef struct {
+ uint8 id;
+ uint8 len;
+ uint8 power;
+} dot11_power_cnst_t;
+
+typedef struct {
+ uint8 min;
+ uint8 max;
+} dot11_power_cap_t;
+
+typedef struct {
+ uint8 id;
+ uint8 len;
+ uint8 tx_pwr;
+ uint8 margin;
+} dot11_tpc_rep_t;
+#define DOT11_MNG_IE_TPC_REPORT_LEN 2 /* length of IE data, not including 2 byte header */
+
+typedef struct {
+ uint8 id;
+ uint8 len;
+ uint8 first_channel;
+ uint8 num_channels;
+} dot11_supp_channels_t;
+
+struct dot11_channel_switch {
+ uint8 id;
+ uint8 len;
+ uint8 mode;
+ uint8 channel;
+ uint8 count;
+} PACKED;
+typedef struct dot11_channel_switch dot11_channel_switch_t;
+
+/* 802.11h Measurement Request/Report IEs */
+/* Measurement Type field */
+#define DOT11_MEASURE_TYPE_BASIC 0
+#define DOT11_MEASURE_TYPE_CCA 1
+#define DOT11_MEASURE_TYPE_RPI 2
+
+/* Measurement Mode field */
+
+/* Measurement Request Modes */
+#define DOT11_MEASURE_MODE_ENABLE (1<<1)
+#define DOT11_MEASURE_MODE_REQUEST (1<<2)
+#define DOT11_MEASURE_MODE_REPORT (1<<3)
+/* Measurement Report Modes */
+#define DOT11_MEASURE_MODE_LATE (1<<0)
+#define DOT11_MEASURE_MODE_INCAPABLE (1<<1)
+#define DOT11_MEASURE_MODE_REFUSED (1<<2)
+/* Basic Measurement Map bits */
+#define DOT11_MEASURE_BASIC_MAP_BSS ((uint8)(1<<0))
+#define DOT11_MEASURE_BASIC_MAP_OFDM ((uint8)(1<<1))
+#define DOT11_MEASURE_BASIC_MAP_UKNOWN ((uint8)(1<<2))
+#define DOT11_MEASURE_BASIC_MAP_RADAR ((uint8)(1<<3))
+#define DOT11_MEASURE_BASIC_MAP_UNMEAS ((uint8)(1<<4))
+
+typedef struct {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+} dot11_meas_req_t;
+#define DOT11_MNG_IE_MREQ_LEN 14
+/* length of Measure Request IE data not including variable len */
+#define DOT11_MNG_IE_MREQ_FIXED_LEN 3
+
+struct dot11_meas_rep {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ union
+ {
+ struct {
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+ uint8 map;
+ } PACKED basic;
+ uint8 data[1];
+ } PACKED rep;
+} PACKED;
+typedef struct dot11_meas_rep dot11_meas_rep_t;
+
+/* length of Measure Report IE data not including variable len */
+#define DOT11_MNG_IE_MREP_FIXED_LEN 3
+
+struct dot11_meas_rep_basic {
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+ uint8 map;
+} PACKED;
+typedef struct dot11_meas_rep_basic dot11_meas_rep_basic_t;
+#define DOT11_MEASURE_BASIC_REP_LEN 12
+
+struct dot11_quiet {
+ uint8 id;
+ uint8 len;
+ uint8 count; /* TBTTs until beacon interval in quiet starts */
+ uint8 period; /* Beacon intervals between periodic quiet periods ? */
+ uint16 duration;/* Length of quiet period, in TU's */
+ uint16 offset; /* TU's offset from TBTT in Count field */
+} PACKED;
+typedef struct dot11_quiet dot11_quiet_t;
+
+typedef struct {
+ uint8 channel;
+ uint8 map;
+} chan_map_tuple_t;
+
+typedef struct {
+ uint8 id;
+ uint8 len;
+ uint8 eaddr[ETHER_ADDR_LEN];
+ uint8 interval;
+ chan_map_tuple_t map[1];
+} dot11_ibss_dfs_t;
+
+/* WME Elements */
+#define WME_OUI "\x00\x50\xf2"
+#define WME_VER 1
+#define WME_TYPE 2
+#define WME_SUBTYPE_IE 0 /* Information Element */
+#define WME_SUBTYPE_PARAM_IE 1 /* Parameter Element */
+#define WME_SUBTYPE_TSPEC 2 /* Traffic Specification */
+
+/* WME Access Category Indices (ACIs) */
+#define AC_BE 0 /* Best Effort */
+#define AC_BK 1 /* Background */
+#define AC_VI 2 /* Video */
+#define AC_VO 3 /* Voice */
+#define AC_MAX 4
+
+/* WME Information Element (IE) */
+struct wme_ie {
+ uint8 oui[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 version;
+ uint8 acinfo;
+} PACKED;
+typedef struct wme_ie wme_ie_t;
+#define WME_IE_LEN 7
+
+struct wme_acparam {
+ uint8 ACI;
+ uint8 ECW;
+ uint16 TXOP; /* stored in network order (ls octet first) */
+} PACKED;
+typedef struct wme_acparam wme_acparam_t;
+
+/* WME Parameter Element (PE) */
+struct wme_params {
+ uint8 oui[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 version;
+ uint8 acinfo;
+ uint8 rsvd;
+ wme_acparam_t acparam[4];
+} PACKED;
+typedef struct wme_params wme_params_t;
+#define WME_PARAMS_IE_LEN 24
+
+/* acinfo */
+#define WME_COUNT_MASK 0x0f
+/* ACI */
+#define WME_AIFS_MASK 0x0f
+#define WME_ACM_MASK 0x10
+#define WME_ACI_MASK 0x60
+#define WME_ACI_SHIFT 5
+/* ECW */
+#define WME_CWMIN_MASK 0x0f
+#define WME_CWMAX_MASK 0xf0
+#define WME_CWMAX_SHIFT 4
+
+#define WME_TXOP_UNITS 32
+
+/* WME Traffic Specification (TSPEC) element */
+#define WME_SUBTYPE_TSPEC 2
+#define WME_TSPEC_HDR_LEN 2
+#define WME_TSPEC_BODY_OFF 2
+struct wme_tspec {
+ uint8 oui[DOT11_OUI_LEN]; /* WME_OUI */
+ uint8 type; /* WME_TYPE */
+ uint8 subtype; /* WME_SUBTYPE_TSPEC */
+ uint8 version; /* WME_VERSION */
+ uint16 ts_info; /* TS Info */
+ uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */
+ uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */
+ uint32 min_service_interval; /* Minimum Service Interval (us) */
+ uint32 max_service_interval; /* Maximum Service Interval (us) */
+ uint32 inactivity_interval; /* Inactivity Interval (us) */
+ uint32 service_start; /* Service Start Time (us) */
+ uint32 min_rate; /* Minimum Data Rate (bps) */
+ uint32 mean_rate; /* Mean Data Rate (bps) */
+ uint32 max_burst_size; /* Maximum Burst Size (bytes) */
+ uint32 min_phy_rate; /* Minimum PHY Rate (bps) */
+ uint32 peak_rate; /* Peak Data Rate (bps) */
+ uint32 delay_bound; /* Delay Bound (us) */
+ uint16 surplus_bandwidth; /* Surplus Bandwidth Allowance Factor */
+ uint16 medium_time; /* Medium Time (32 us/s periods) */
+} PACKED;
+typedef struct wme_tspec wme_tspec_t;
+#define WME_TSPEC_LEN 56 /* not including 2-byte header */
+
+/* ts_info */
+/* 802.1D priority is duplicated - bits 13-11 AND bits 3-1 */
+#define TS_INFO_PRIO_SHIFT_HI 11
+#define TS_INFO_PRIO_MASK_HI (0x7 << TS_INFO_PRIO_SHIFT_HI)
+#define TS_INFO_PRIO_SHIFT_LO 1
+#define TS_INFO_PRIO_MASK_LO (0x7 << TS_INFO_PRIO_SHIFT_LO)
+#define TS_INFO_CONTENTION_SHIFT 7
+#define TS_INFO_CONTENTION_MASK (0x1 << TS_INFO_CONTENTION_SHIFT)
+#define TS_INFO_DIRECTION_SHIFT 5
+#define TS_INFO_DIRECTION_MASK (0x3 << TS_INFO_DIRECTION_SHIFT)
+#define TS_INFO_UPLINK (0 << TS_INFO_DIRECTION_SHIFT)
+#define TS_INFO_DOWNLINK (1 << TS_INFO_DIRECTION_SHIFT)
+#define TS_INFO_BIDIRECTIONAL (3 << TS_INFO_DIRECTION_SHIFT)
+
+/* nom_msdu_size */
+#define FIXED_MSDU_SIZE 0x8000 /* MSDU size is fixed */
+#define MSDU_SIZE_MASK 0x7fff /* (Nominal or fixed) MSDU size */
+
+/* surplus_bandwidth */
+/* Represented as 3 bits of integer, binary point, 13 bits fraction */
+#define INTEGER_SHIFT 13
+#define FRACTION_MASK 0x1FFF
+
+/* Management Notification Frame */
+struct dot11_management_notification {
+ uint8 category; /* DOT11_ACTION_NOTIFICATION */
+ uint8 action;
+ uint8 token;
+ uint8 status;
+ uint8 data[1]; /* Elements */
+} PACKED;
+#define DOT11_MGMT_NOTIFICATION_LEN 4 /* Fixed length */
+
+/* WME Action Codes */
+#define WME_SETUP_REQUEST 0
+#define WME_SETUP_RESPONSE 1
+#define WME_TEARDOWN 2
+
+/* WME Setup Response Status Codes */
+#define WME_ADMISSION_ACCEPTED 0
+#define WME_INVALID_PARAMETERS 1
+#define WME_ADMISSION_REFUSED 3
+
+/* Macro to take a pointer to a beacon or probe response
+ * header and return the char* pointer to the SSID info element
+ */
+#define BCN_PRB_SSID(hdr) ((char*)(hdr) + DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_LEN)
+
+/* Authentication frame payload constants */
+#define DOT11_OPEN_SYSTEM 0
+#define DOT11_SHARED_KEY 1
+#define DOT11_CHALLENGE_LEN 128
+
+/* Frame control macros */
+#define FC_PVER_MASK 0x3
+#define FC_PVER_SHIFT 0
+#define FC_TYPE_MASK 0xC
+#define FC_TYPE_SHIFT 2
+#define FC_SUBTYPE_MASK 0xF0
+#define FC_SUBTYPE_SHIFT 4
+#define FC_TODS 0x100
+#define FC_TODS_SHIFT 8
+#define FC_FROMDS 0x200
+#define FC_FROMDS_SHIFT 9
+#define FC_MOREFRAG 0x400
+#define FC_MOREFRAG_SHIFT 10
+#define FC_RETRY 0x800
+#define FC_RETRY_SHIFT 11
+#define FC_PM 0x1000
+#define FC_PM_SHIFT 12
+#define FC_MOREDATA 0x2000
+#define FC_MOREDATA_SHIFT 13
+#define FC_WEP 0x4000
+#define FC_WEP_SHIFT 14
+#define FC_ORDER 0x8000
+#define FC_ORDER_SHIFT 15
+
+/* sequence control macros */
+#define SEQNUM_SHIFT 4
+#define FRAGNUM_MASK 0xF
+
+/* Frame Control type/subtype defs */
+
+/* FC Types */
+#define FC_TYPE_MNG 0
+#define FC_TYPE_CTL 1
+#define FC_TYPE_DATA 2
+
+/* Management Subtypes */
+#define FC_SUBTYPE_ASSOC_REQ 0
+#define FC_SUBTYPE_ASSOC_RESP 1
+#define FC_SUBTYPE_REASSOC_REQ 2
+#define FC_SUBTYPE_REASSOC_RESP 3
+#define FC_SUBTYPE_PROBE_REQ 4
+#define FC_SUBTYPE_PROBE_RESP 5
+#define FC_SUBTYPE_BEACON 8
+#define FC_SUBTYPE_ATIM 9
+#define FC_SUBTYPE_DISASSOC 10
+#define FC_SUBTYPE_AUTH 11
+#define FC_SUBTYPE_DEAUTH 12
+#define FC_SUBTYPE_ACTION 13
+
+/* Control Subtypes */
+#define FC_SUBTYPE_PS_POLL 10
+#define FC_SUBTYPE_RTS 11
+#define FC_SUBTYPE_CTS 12
+#define FC_SUBTYPE_ACK 13
+#define FC_SUBTYPE_CF_END 14
+#define FC_SUBTYPE_CF_END_ACK 15
+
+/* Data Subtypes */
+#define FC_SUBTYPE_DATA 0
+#define FC_SUBTYPE_DATA_CF_ACK 1
+#define FC_SUBTYPE_DATA_CF_POLL 2
+#define FC_SUBTYPE_DATA_CF_ACK_POLL 3
+#define FC_SUBTYPE_NULL 4
+#define FC_SUBTYPE_CF_ACK 5
+#define FC_SUBTYPE_CF_POLL 6
+#define FC_SUBTYPE_CF_ACK_POLL 7
+#define FC_SUBTYPE_QOS_DATA 8
+#define FC_SUBTYPE_QOS_NULL 12
+
+/* type-subtype combos */
+#define FC_KIND_MASK (FC_TYPE_MASK | FC_SUBTYPE_MASK)
+
+#define FC_KIND(t, s) (((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT))
+
+#define FC_ASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_REQ)
+#define FC_ASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP)
+#define FC_REASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ)
+#define FC_REASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP)
+#define FC_PROBE_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ)
+#define FC_PROBE_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP)
+#define FC_BEACON FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON)
+#define FC_DISASSOC FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC)
+#define FC_AUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH)
+#define FC_DEAUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH)
+#define FC_ACTION FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION)
+
+#define FC_PS_POLL FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL)
+#define FC_RTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS)
+#define FC_CTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS)
+#define FC_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_ACK)
+#define FC_CF_END FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END)
+#define FC_CF_END_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END_ACK)
+
+#define FC_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA)
+#define FC_NULL_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_NULL)
+#define FC_DATA_CF_ACK FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA_CF_ACK)
+#define FC_QOS_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_DATA)
+#define FC_QOS_NULL FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_NULL)
+
+/* QoS Control Field */
+
+/* 802.1D Tag */
+#define QOS_PRIO_SHIFT 0
+#define QOS_PRIO_MASK 0x0007
+#define QOS_PRIO(qos) (((qos) & QOS_PRIO_MASK) >> QOS_PRIO_SHIFT)
+
+/* Ack Policy (0 means Acknowledge) */
+#define QOS_ACK_SHIFT 5
+#define QOS_ACK_MASK 0x0060
+#define QOS_ACK(qos) (((qos) & QOS_ACK_MASK) >> QOS_ACK_SHIFT)
+
+/* Management Frames */
+
+/* Management Frame Constants */
+
+/* Fixed fields */
+#define DOT11_MNG_AUTH_ALGO_LEN 2
+#define DOT11_MNG_AUTH_SEQ_LEN 2
+#define DOT11_MNG_BEACON_INT_LEN 2
+#define DOT11_MNG_CAP_LEN 2
+#define DOT11_MNG_AP_ADDR_LEN 6
+#define DOT11_MNG_LISTEN_INT_LEN 2
+#define DOT11_MNG_REASON_LEN 2
+#define DOT11_MNG_AID_LEN 2
+#define DOT11_MNG_STATUS_LEN 2
+#define DOT11_MNG_TIMESTAMP_LEN 8
+
+/* DUR/ID field in assoc resp is 0xc000 | AID */
+#define DOT11_AID_MASK 0x3fff
+
+/* Reason Codes */
+#define DOT11_RC_RESERVED 0
+#define DOT11_RC_UNSPECIFIED 1 /* Unspecified reason */
+#define DOT11_RC_AUTH_INVAL 2 /* Previous authentication no longer valid */
+#define DOT11_RC_DEAUTH_LEAVING 3 /* Deauthenticated because sending station is
+ leaving (or has left) IBSS or ESS */
+#define DOT11_RC_INACTIVITY 4 /* Disassociated due to inactivity */
+#define DOT11_RC_BUSY 5 /* Disassociated because AP is unable to handle
+ all currently associated stations */
+#define DOT11_RC_INVAL_CLASS_2 6 /* Class 2 frame received from
+ nonauthenticated station */
+#define DOT11_RC_INVAL_CLASS_3 7 /* Class 3 frame received from
+ nonassociated station */
+#define DOT11_RC_DISASSOC_LEAVING 8 /* Disassociated because sending station is
+ leaving (or has left) BSS */
+#define DOT11_RC_NOT_AUTH 9 /* Station requesting (re)association is
+ not authenticated with responding station */
+#define DOT11_RC_MAX 23 /* Reason codes > 23 are reserved */
+
+/* Status Codes */
+#define DOT11_STATUS_SUCCESS 0 /* Successful */
+#define DOT11_STATUS_FAILURE 1 /* Unspecified failure */
+#define DOT11_STATUS_CAP_MISMATCH 10 /* Cannot support all requested capabilities
+ in the Capability Information field */
+#define DOT11_STATUS_REASSOC_FAIL 11 /* Reassociation denied due to inability to
+ confirm that association exists */
+#define DOT11_STATUS_ASSOC_FAIL 12 /* Association denied due to reason outside
+ the scope of this standard */
+#define DOT11_STATUS_AUTH_MISMATCH 13 /* Responding station does not support the
+ specified authentication algorithm */
+#define DOT11_STATUS_AUTH_SEQ 14 /* Received an Authentication frame with
+ authentication transaction sequence number
+ out of expected sequence */
+#define DOT11_STATUS_AUTH_CHALLENGE_FAIL 15 /* Authentication rejected because of challenge failure */
+#define DOT11_STATUS_AUTH_TIMEOUT 16 /* Authentication rejected due to timeout waiting
+ for next frame in sequence */
+#define DOT11_STATUS_ASSOC_BUSY_FAIL 17 /* Association denied because AP is unable to
+ handle additional associated stations */
+#define DOT11_STATUS_ASSOC_RATE_MISMATCH 18 /* Association denied due to requesting station
+ not supporting all of the data rates in the
+ BSSBasicRateSet parameter */
+#define DOT11_STATUS_ASSOC_SHORT_REQUIRED 19 /* Association denied due to requesting station
+ not supporting the Short Preamble option */
+#define DOT11_STATUS_ASSOC_PBCC_REQUIRED 20 /* Association denied due to requesting station
+ not supporting the PBCC Modulation option */
+#define DOT11_STATUS_ASSOC_AGILITY_REQUIRED 21 /* Association denied due to requesting station
+ not supporting the Channel Agility option */
+#define DOT11_STATUS_ASSOC_SPECTRUM_REQUIRED 22 /* Association denied because Spectrum Management
+ capability is required. */
+#define DOT11_STATUS_ASSOC_BAD_POWER_CAP 23 /* Association denied because the info in the
+ Power Cap element is unacceptable. */
+#define DOT11_STATUS_ASSOC_BAD_SUP_CHANNELS 24 /* Association denied because the info in the
+ Supported Channel element is unacceptable */
+#define DOT11_STATUS_ASSOC_SHORTSLOT_REQUIRED 25 /* Association denied due to requesting station
+ not supporting the Short Slot Time option */
+#define DOT11_STATUS_ASSOC_ERPBCC_REQUIRED 26 /* Association denied due to requesting station
+ not supporting the ER-PBCC Modulation option */
+#define DOT11_STATUS_ASSOC_DSSOFDM_REQUIRED 27 /* Association denied due to requesting station
+ not supporting the DSS-OFDM option */
+
+/* Info Elts, length of INFORMATION portion of Info Elts */
+#define DOT11_MNG_DS_PARAM_LEN 1
+#define DOT11_MNG_IBSS_PARAM_LEN 2
+
+/* TIM Info element has 3 bytes fixed info in INFORMATION field,
+ * followed by 1 to 251 bytes of Partial Virtual Bitmap */
+#define DOT11_MNG_TIM_FIXED_LEN 3
+#define DOT11_MNG_TIM_DTIM_COUNT 0
+#define DOT11_MNG_TIM_DTIM_PERIOD 1
+#define DOT11_MNG_TIM_BITMAP_CTL 2
+#define DOT11_MNG_TIM_PVB 3
+
+/* TLV defines */
+#define TLV_TAG_OFF 0
+#define TLV_LEN_OFF 1
+#define TLV_HDR_LEN 2
+#define TLV_BODY_OFF 2
+
+/* Management Frame Information Element IDs */
+#define DOT11_MNG_SSID_ID 0
+#define DOT11_MNG_RATES_ID 1
+#define DOT11_MNG_FH_PARMS_ID 2
+#define DOT11_MNG_DS_PARMS_ID 3
+#define DOT11_MNG_CF_PARMS_ID 4
+#define DOT11_MNG_TIM_ID 5
+#define DOT11_MNG_IBSS_PARMS_ID 6
+#define DOT11_MNG_COUNTRY_ID 7
+#define DOT11_MNG_HOPPING_PARMS_ID 8
+#define DOT11_MNG_HOPPING_TABLE_ID 9
+#define DOT11_MNG_REQUEST_ID 10
+#define DOT11_MNG_CHALLENGE_ID 16
+#define DOT11_MNG_PWR_CONSTRAINT_ID 32 /* 11H PowerConstraint */
+#define DOT11_MNG_PWR_CAP_ID 33 /* 11H PowerCapability */
+#define DOT11_MNG_TPC_REQUEST_ID 34 /* 11H TPC Request */
+#define DOT11_MNG_TPC_REPORT_ID 35 /* 11H TPC Report */
+#define DOT11_MNG_SUPP_CHANNELS_ID 36 /* 11H Supported Channels */
+#define DOT11_MNG_CHANNEL_SWITCH_ID 37 /* 11H ChannelSwitch Announcement*/
+#define DOT11_MNG_MEASURE_REQUEST_ID 38 /* 11H MeasurementRequest */
+#define DOT11_MNG_MEASURE_REPORT_ID 39 /* 11H MeasurementReport */
+#define DOT11_MNG_QUIET_ID 40 /* 11H Quiet */
+#define DOT11_MNG_IBSS_DFS_ID 41 /* 11H IBSS_DFS */
+#define DOT11_MNG_ERP_ID 42
+#define DOT11_MNG_NONERP_ID 47
+#define DOT11_MNG_EXT_RATES_ID 50
+#define DOT11_MNG_WPA_ID 221
+#define DOT11_MNG_PROPR_ID 221
+
+/* ERP info element bit values */
+#define DOT11_MNG_ERP_LEN 1 /* ERP is currently 1 byte long */
+#define DOT11_MNG_NONERP_PRESENT 0x01 /* NonERP (802.11b) STAs are present in the BSS */
+#define DOT11_MNG_USE_PROTECTION 0x02 /* Use protection mechanisms for ERP-OFDM frames */
+#define DOT11_MNG_BARKER_PREAMBLE 0x04 /* Short Preambles: 0 == allowed, 1 == not allowed */
+
+/* Capability Information Field */
+#define DOT11_CAP_ESS 0x0001
+#define DOT11_CAP_IBSS 0x0002
+#define DOT11_CAP_POLLABLE 0x0004
+#define DOT11_CAP_POLL_RQ 0x0008
+#define DOT11_CAP_PRIVACY 0x0010
+#define DOT11_CAP_SHORT 0x0020
+#define DOT11_CAP_PBCC 0x0040
+#define DOT11_CAP_AGILITY 0x0080
+#define DOT11_CAP_SPECTRUM 0x0100
+#define DOT11_CAP_SHORTSLOT 0x0400
+#define DOT11_CAP_CCK_OFDM 0x2000
+
+/* Action Frame Constants */
+#define DOT11_ACTION_CAT_ERR_MASK 0x80
+#define DOT11_ACTION_CAT_SPECT_MNG 0x00
+#define DOT11_ACTION_NOTIFICATION 0x11 /* 17 */
+
+#define DOT11_ACTION_ID_M_REQ 0
+#define DOT11_ACTION_ID_M_REP 1
+#define DOT11_ACTION_ID_TPC_REQ 2
+#define DOT11_ACTION_ID_TPC_REP 3
+#define DOT11_ACTION_ID_CHANNEL_SWITCH 4
+
+/* MLME Enumerations */
+#define DOT11_BSSTYPE_INFRASTRUCTURE 0
+#define DOT11_BSSTYPE_INDEPENDENT 1
+#define DOT11_BSSTYPE_ANY 2
+#define DOT11_SCANTYPE_ACTIVE 0
+#define DOT11_SCANTYPE_PASSIVE 1
+
+/* 802.11 A PHY constants */
+#define APHY_SLOT_TIME 9
+#define APHY_SIFS_TIME 16
+#define APHY_DIFS_TIME (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME))
+#define APHY_PREAMBLE_TIME 16
+#define APHY_SIGNAL_TIME 4
+#define APHY_SYMBOL_TIME 4
+#define APHY_SERVICE_NBITS 16
+#define APHY_TAIL_NBITS 6
+#define APHY_CWMIN 15
+
+/* 802.11 B PHY constants */
+#define BPHY_SLOT_TIME 20
+#define BPHY_SIFS_TIME 10
+#define BPHY_DIFS_TIME 50
+#define BPHY_PLCP_TIME 192
+#define BPHY_PLCP_SHORT_TIME 96
+#define BPHY_CWMIN 31
+
+/* 802.11 G constants */
+#define DOT11_OFDM_SIGNAL_EXTENSION 6
+
+#define PHY_CWMAX 1023
+
+#define DOT11_MAXNUMFRAGS 16 /* max # fragments per MSDU */
+
+/* dot11Counters Table - 802.11 spec., Annex D */
+typedef struct d11cnt {
+ uint32 txfrag; /* dot11TransmittedFragmentCount */
+ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */
+ uint32 txfail; /* dot11FailedCount */
+ uint32 txretry; /* dot11RetryCount */
+ uint32 txretrie; /* dot11MultipleRetryCount */
+ uint32 rxdup; /* dot11FrameduplicateCount */
+ uint32 txrts; /* dot11RTSSuccessCount */
+ uint32 txnocts; /* dot11RTSFailureCount */
+ uint32 txnoack; /* dot11ACKFailureCount */
+ uint32 rxfrag; /* dot11ReceivedFragmentCount */
+ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */
+ uint32 rxcrc; /* dot11FCSErrorCount */
+ uint32 txfrmsnt; /* dot11TransmittedFrameCount */
+ uint32 rxundec; /* dot11WEPUndecryptableCount */
+} d11cnt_t;
+
+/* BRCM OUI */
+#define BRCM_OUI "\x00\x10\x18"
+
+/* BRCM info element */
+struct brcm_ie {
+ uchar id;
+ uchar len;
+ uchar oui[3];
+ uchar ver;
+ uchar assoc; /* # of assoc STAs */
+ uchar flags; /* misc flags */
+} PACKED;
+#define BRCM_IE_LEN 8
+typedef struct brcm_ie brcm_ie_t;
+#define BRCM_IE_VER 1
+
+/* brcm_ie flags */
+#define BRF_ABCAP 0x1 /* afterburner capable */
+#define BRF_ABRQRD 0x2 /* afterburner requested */
+
+/* WPA definitions */
+#define WPA_VERSION 1
+#define WPA_OUI "\x00\x50\xF2"
+
+#define WPA_OUI_LEN 3
+
+/* WPA authentication modes */
+#define WPA_AUTH_NONE 0 /* None */
+#define WPA_AUTH_UNSPECIFIED 1 /* Unspecified authentication over 802.1X: default for WPA */
+#define WPA_AUTH_PSK 2 /* Pre-shared Key over 802.1X */
+#define WPA_AUTH_DISABLED 255 /* Legacy (i.e., non-WPA) */
+
+#define IS_WPA_AUTH(auth) ((auth) == WPA_AUTH_NONE || \
+ (auth) == WPA_AUTH_UNSPECIFIED || \
+ (auth) == WPA_AUTH_PSK)
+
+
+/* Key related defines */
+#define DOT11_MAX_DEFAULT_KEYS 4 /* number of default keys */
+#define DOT11_MAX_KEY_SIZE 32 /* max size of any key */
+#define DOT11_MAX_IV_SIZE 16 /* max size of any IV */
+#define DOT11_EXT_IV_FLAG (1<<5) /* flag to indicate IV is > 4 bytes */
+
+#define WEP1_KEY_SIZE 5 /* max size of any WEP key */
+#define WEP1_KEY_HEX_SIZE 10 /* size of WEP key in hex. */
+#define WEP128_KEY_SIZE 13 /* max size of any WEP key */
+#define WEP128_KEY_HEX_SIZE 26 /* size of WEP key in hex. */
+#define TKIP_MIC_SIZE 8 /* size of TKIP MIC */
+#define TKIP_EOM_SIZE 7 /* max size of TKIP EOM */
+#define TKIP_EOM_FLAG 0x5a /* TKIP EOM flag byte */
+#define TKIP_KEY_SIZE 32 /* size of any TKIP key */
+#define TKIP_MIC_AUTH_TX 16 /* offset to Authenticator MIC TX key */
+#define TKIP_MIC_AUTH_RX 24 /* offset to Authenticator MIC RX key */
+#define TKIP_MIC_SUP_RX 16 /* offset to Supplicant MIC RX key */
+#define TKIP_MIC_SUP_TX 24 /* offset to Supplicant MIC TX key */
+#define AES_KEY_SIZE 16 /* size of AES key */
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#endif /* _802_11_H_ */
diff --git a/package/wlcompat/src/include/proto/ethernet.h b/package/wlcompat/src/include/proto/ethernet.h
new file mode 100644
index 0000000000..173464af63
--- /dev/null
+++ b/package/wlcompat/src/include/proto/ethernet.h
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * $Id$
+ * 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.
+ * From FreeBSD 2.2.7: Fundamental constants relating to ethernet.
+ ******************************************************************************/
+
+#ifndef _NET_ETHERNET_H_ /* use native BSD ethernet.h when available */
+#define _NET_ETHERNET_H_
+
+#ifndef _TYPEDEFS_H_
+#include "typedefs.h"
+#endif
+
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#define PACKED
+#endif
+
+/*
+ * The number of bytes in an ethernet (MAC) address.
+ */
+#ifndef ETHER_ADDR_LEN
+#define ETHER_ADDR_LEN 6
+#endif
+
+/*
+ * The number of bytes in the type field.
+ */
+#ifndef ETHER_TYPE_LEN
+#define ETHER_TYPE_LEN 2
+#endif
+
+/*
+ * The number of bytes in the trailing CRC field.
+ */
+#ifndef ETHER_CRC_LEN
+#define ETHER_CRC_LEN 4
+#endif
+
+/*
+ * The length of the combined header.
+ */
+#ifndef ETHER_HDR_LEN
+#define ETHER_HDR_LEN (ETHER_ADDR_LEN*2+ETHER_TYPE_LEN)
+#endif
+
+/*
+ * The minimum packet length.
+ */
+#ifndef ETHER_MIN_LEN
+#define ETHER_MIN_LEN 64
+#endif
+
+/*
+ * The minimum packet user data length.
+ */
+#ifndef ETHER_MIN_DATA
+#define ETHER_MIN_DATA 46
+#endif
+
+/*
+ * The maximum packet length.
+ */
+#ifndef ETHER_MAX_LEN
+#define ETHER_MAX_LEN 1518
+#endif
+
+/*
+ * The maximum packet user data length.
+ */
+#define ETHER_MAX_DATA 1500
+
+/*
+ * Used to uniquely identify a 802.1q VLAN-tagged header.
+ */
+#define VLAN_TAG 0x8100
+
+/*
+ * Located after dest & src address in ether header.
+ */
+#define VLAN_FIELDS_OFFSET (ETHER_ADDR_LEN * 2)
+
+/*
+ * 4 bytes of vlan field info.
+ */
+#define VLAN_FIELDS_SIZE 4
+
+/* location of bits in 16-bit vlan fields */
+#define VLAN_PRI_SHIFT 13 /* user priority */
+#define VLAN_CFI_SHIFT 12 /* canonical format indicator bit */
+
+/* 3 bits of priority */
+#define VLAN_PRI_MASK 7
+/* 12 bits of vlan identfier (VID) */
+#define VLAN_VID_MASK 0xFFF /* VLAN identifier (VID) field */
+
+struct vlan_tags {
+ uint16 tag_type; /* 0x8100 for VLAN */
+ uint16 tag_control; /* prio | cfi | vid */
+} PACKED ;
+
+/* 802.1X ethertype */
+
+#define ETHER_TYPE_IP 0x0800 /* IP */
+#define ETHER_TYPE_BRCM 0x886c /* Broadcom Corp. */
+#define ETHER_TYPE_802_1X 0x888e /* 802.1x */
+
+#define ETHER_BRCM_SUBTYPE_LEN 4 /* Broadcom 4byte subtype follows ethertype */
+#define ETHER_BRCM_CRAM 0x1 /* Broadcom subtype cram protocol */
+
+/*
+ * A macro to validate a length with
+ */
+#define ETHER_IS_VALID_LEN(foo) \
+ ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN)
+
+#ifndef __NET_ETHERNET_H
+#ifndef __INCif_etherh /* Quick and ugly hack for VxWorks */
+/*
+ * Structure of a 10Mb/s Ethernet header.
+ */
+struct ether_header {
+ uint8 ether_dhost[ETHER_ADDR_LEN];
+ uint8 ether_shost[ETHER_ADDR_LEN];
+ uint16 ether_type;
+} PACKED ;
+
+/*
+ * Structure of a 48-bit Ethernet address.
+ */
+struct ether_addr {
+ uint8 octet[ETHER_ADDR_LEN];
+} PACKED ;
+#endif
+#endif
+
+/*
+ * Takes a pointer, returns true if a 48-bit multicast address
+ * (including broadcast, since it is all ones)
+ */
+#define ETHER_ISMULTI(ea) (((uint8 *)(ea))[0] & 1)
+
+/*
+ * Takes a pointer, returns true if a 48-bit broadcast (all ones)
+ */
+#define ETHER_ISBCAST(ea) ((((uint8 *)(ea))[0] & \
+ ((uint8 *)(ea))[1] & \
+ ((uint8 *)(ea))[2] & \
+ ((uint8 *)(ea))[3] & \
+ ((uint8 *)(ea))[4] & \
+ ((uint8 *)(ea))[5]) == 0xff)
+
+static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}};
+
+/*
+ * Takes a pointer, returns true if a 48-bit null address (all zeros)
+ */
+#define ETHER_ISNULLADDR(ea) ((((uint8 *)(ea))[0] | \
+ ((uint8 *)(ea))[1] | \
+ ((uint8 *)(ea))[2] | \
+ ((uint8 *)(ea))[3] | \
+ ((uint8 *)(ea))[4] | \
+ ((uint8 *)(ea))[5]) == 0)
+
+/* Differentiated Services Codepoint - lower 6 bits of tos in iphdr */
+#define DSCP_PRI_MASK 0x3F /* bits 0-6 */
+#define DSCP_WME_PRI_MASK 0x38 /* bits 3-6 */
+#define DSCP_WME_PRI_SHIFT 3
+
+#undef PACKED
+
+#endif /* _NET_ETHERNET_H_ */
diff --git a/package/wlcompat/src/include/shutils.h b/package/wlcompat/src/include/shutils.h
new file mode 100644
index 0000000000..783ee9ede1
--- /dev/null
+++ b/package/wlcompat/src/include/shutils.h
@@ -0,0 +1,200 @@
+/*
+ * Shell-like utility functions
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#ifndef _shutils_h_
+#define _shutils_h_
+#include <string.h>
+/*
+ * Reads file and returns contents
+ * @param fd file descriptor
+ * @return contents of file or NULL if an error occurred
+ */
+extern char * fd2str(int fd);
+
+/*
+ * Reads file and returns contents
+ * @param path path to file
+ * @return contents of file or NULL if an error occurred
+ */
+extern char * file2str(const char *path);
+
+/*
+ * Waits for a file descriptor to become available for reading or unblocked signal
+ * @param fd file descriptor
+ * @param timeout seconds to wait before timing out or 0 for no timeout
+ * @return 1 if descriptor changed status or 0 if timed out or -1 on error
+ */
+extern int waitfor(int fd, int timeout);
+
+/*
+ * Concatenates NULL-terminated list of arguments into a single
+ * commmand and executes it
+ * @param argv argument list
+ * @param path NULL, ">output", or ">>output"
+ * @param timeout seconds to wait before timing out or 0 for no timeout
+ * @param ppid NULL to wait for child termination or pointer to pid
+ * @return return value of executed command or errno
+ */
+extern int _eval(char *const argv[], char *path, int timeout, pid_t *ppid);
+
+/*
+ * Concatenates NULL-terminated list of arguments into a single
+ * commmand and executes it
+ * @param argv argument list
+ * @return stdout of executed command or NULL if an error occurred
+ */
+extern char * _backtick(char *const argv[]);
+
+/*
+ * Kills process whose PID is stored in plaintext in pidfile
+ * @param pidfile PID file
+ * @return 0 on success and errno on failure
+ */
+extern int kill_pidfile(char *pidfile);
+
+/*
+ * fread() with automatic retry on syscall interrupt
+ * @param ptr location to store to
+ * @param size size of each element of data
+ * @param nmemb number of elements
+ * @param stream file stream
+ * @return number of items successfully read
+ */
+extern int safe_fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
+
+/*
+ * fwrite() with automatic retry on syscall interrupt
+ * @param ptr location to read from
+ * @param size size of each element of data
+ * @param nmemb number of elements
+ * @param stream file stream
+ * @return number of items successfully written
+ */
+extern int safe_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
+
+/*
+ * Convert Ethernet address string representation to binary data
+ * @param a string in xx:xx:xx:xx:xx:xx notation
+ * @param e binary data
+ * @return TRUE if conversion was successful and FALSE otherwise
+ */
+extern int ether_atoe(const char *a, unsigned char *e);
+
+/*
+ * Convert Ethernet address binary data to string representation
+ * @param e binary data
+ * @param a string in xx:xx:xx:xx:xx:xx notation
+ * @return a
+ */
+extern char * ether_etoa(const unsigned char *e, char *a);
+
+/*
+ * Concatenate two strings together into a caller supplied buffer
+ * @param s1 first string
+ * @param s2 second string
+ * @param buf buffer large enough to hold both strings
+ * @return buf
+ */
+static inline char * strcat_r(const char *s1, const char *s2, char *buf)
+{
+ strcpy(buf, s1);
+ strcat(buf, s2);
+ return buf;
+}
+
+/* Check for a blank character; that is, a space or a tab */
+#define isblank(c) ((c) == ' ' || (c) == '\t')
+
+/* Strip trailing CR/NL from string <s> */
+#define chomp(s) ({ \
+ char *c = (s) + strlen((s)) - 1; \
+ while ((c > (s)) && (*c == '\n' || *c == '\r' || *c == ' ')) \
+ *c-- = '\0'; \
+ s; \
+})
+
+/* Simple version of _backtick() */
+#define backtick(cmd, args...) ({ \
+ char *argv[] = { cmd, ## args, NULL }; \
+ _backtick(argv); \
+})
+
+/* Simple version of _eval() (no timeout and wait for child termination) */
+#define eval(cmd, args...) ({ \
+ char *argv[] = { cmd, ## args, NULL }; \
+ _eval(argv, ">/dev/console", 0, NULL); \
+})
+
+/* Copy each token in wordlist delimited by space into word */
+#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, ' '))
+
+/* Return NUL instead of NULL if undefined */
+#define safe_getenv(s) (getenv(s) ? : "")
+
+/* Print directly to the console */
+#define cprintf(fmt, args...) do { \
+ FILE *fp = fopen("/dev/console", "w"); \
+ if (fp) { \
+ fprintf(fp, fmt, ## args); \
+ fclose(fp); \
+ } \
+} while (0)
+
+/* Debug print */
+#ifdef DEBUG
+#define dprintf(fmt, args...) cprintf("%s: " fmt, __FUNCTION__, ## args)
+#else
+#define dprintf(fmt, args...)
+#endif
+
+#ifdef vxworks
+
+#include <inetLib.h>
+#define inet_aton(a, n) ((inet_aton((a), (n)) == ERROR) ? 0 : 1)
+#define inet_ntoa(n) ({ char a[INET_ADDR_LEN]; inet_ntoa_b ((n), a); a; })
+
+#include <typedefs.h>
+#include <bcmutils.h>
+#define ether_atoe(a, e) bcm_ether_atoe((a), (e))
+#define ether_etoa(e, a) bcm_ether_ntoa((e), (a))
+
+/* These declarations are not available where you would expect them */
+extern int vsnprintf (char *, size_t, const char *, va_list);
+extern int snprintf(char *str, size_t count, const char *fmt, ...);
+extern char *strdup(const char *);
+extern char *strsep(char **stringp, char *delim);
+extern int strcasecmp(const char *s1, const char *s2);
+extern int strncasecmp(const char *s1, const char *s2, size_t n);
+
+/* Neither are socket() and connect() */
+#include <sockLib.h>
+
+#ifdef DEBUG
+#undef dprintf
+#define dprintf printf
+#endif
+#endif
+
+#endif /* _shutils_h_ */
diff --git a/package/wlcompat/src/include/typedefs.h b/package/wlcompat/src/include/typedefs.h
new file mode 100644
index 0000000000..6b0c25e042
--- /dev/null
+++ b/package/wlcompat/src/include/typedefs.h
@@ -0,0 +1,293 @@
+/*
+ * 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.
+ * $Id$
+ */
+
+#ifndef _TYPEDEFS_H_
+#define _TYPEDEFS_H_
+
+
+/* Define 'SITE_TYPEDEFS' in the compile to include a site specific
+ * typedef file "site_typedefs.h".
+ *
+ * If 'SITE_TYPEDEFS' is not defined, then the "Inferred Typedefs"
+ * section of this file makes inferences about the compile environment
+ * based on defined symbols and possibly compiler pragmas.
+ *
+ * Following these two sections is the "Default Typedefs"
+ * section. This section is only prcessed if 'USE_TYPEDEF_DEFAULTS' is
+ * defined. This section has a default set of typedefs and a few
+ * proprocessor symbols (TRUE, FALSE, NULL, ...).
+ */
+
+#ifdef SITE_TYPEDEFS
+
+/*******************************************************************************
+ * Site Specific Typedefs
+ *******************************************************************************/
+
+#include "site_typedefs.h"
+
+#else
+
+/*******************************************************************************
+ * Inferred Typedefs
+ *******************************************************************************/
+
+/* Infer the compile environment based on preprocessor symbols and pramas.
+ * Override type definitions as needed, and include configuration dependent
+ * header files to define types.
+ */
+
+#ifdef __cplusplus
+
+#define TYPEDEF_BOOL
+#ifndef FALSE
+#define FALSE false
+#endif
+#ifndef TRUE
+#define TRUE true
+#endif
+
+#else /* ! __cplusplus */
+
+/* for Windows build, define bool as a uchar instead of the default int */
+#if defined(_WIN32)
+
+#define TYPEDEF_BOOL
+typedef unsigned char bool;
+
+#endif /* _WIN32 */
+
+#endif /* ! __cplusplus */
+
+#ifdef _MSC_VER /* Microsoft C */
+#define TYPEDEF_INT64
+#define TYPEDEF_UINT64
+typedef signed __int64 int64;
+typedef unsigned __int64 uint64;
+#endif
+
+#if defined(MACOSX) && defined(KERNEL)
+#define TYPEDEF_BOOL
+#endif
+
+
+#if defined(linux)
+#define TYPEDEF_UINT
+#define TYPEDEF_USHORT
+#define TYPEDEF_ULONG
+#endif
+
+#if !defined(linux) && !defined(_WIN32) && !defined(PMON) && !defined(_CFE_)
+#define TYPEDEF_UINT
+#define TYPEDEF_USHORT
+#endif
+
+
+/* Do not support the (u)int64 types with strict ansi for GNU C */
+#if defined(__GNUC__) && defined(__STRICT_ANSI__)
+#define TYPEDEF_INT64
+#define TYPEDEF_UINT64
+#endif
+
+/* ICL accepts unsigned 64 bit type only, and complains in ANSI mode
+ * for singned or unsigned */
+#if defined(__ICL)
+
+#define TYPEDEF_INT64
+
+#if defined(__STDC__)
+#define TYPEDEF_UINT64
+#endif
+
+#endif /* __ICL */
+
+
+#if !defined(_WIN32) && !defined(PMON) && !defined(_CFE_)
+
+/* pick up ushort & uint from standard types.h */
+#if defined(linux) && defined(__KERNEL__)
+
+#include <linux/types.h> /* sys/types.h and linux/types.h are oil and water */
+
+#else
+
+#include <sys/types.h>
+
+#endif
+
+#endif /* !_WIN32 && !PMON && !_CFE_ */
+
+#if defined(MACOSX) && defined(KERNEL)
+#include <IOKit/IOTypes.h>
+#endif
+
+
+/* use the default typedefs in the next section of this file */
+#define USE_TYPEDEF_DEFAULTS
+
+#endif /* SITE_TYPEDEFS */
+
+
+/*******************************************************************************
+ * Default Typedefs
+ *******************************************************************************/
+
+#ifdef USE_TYPEDEF_DEFAULTS
+#undef USE_TYPEDEF_DEFAULTS
+
+#ifndef TYPEDEF_BOOL
+typedef int bool;
+#endif
+
+/*----------------------- define uchar, ushort, uint, ulong ----------------*/
+
+#ifndef TYPEDEF_UCHAR
+typedef unsigned char uchar;
+#endif
+
+#ifndef TYPEDEF_USHORT
+typedef unsigned short ushort;
+#endif
+
+#ifndef TYPEDEF_UINT
+typedef unsigned int uint;
+#endif
+
+#ifndef TYPEDEF_ULONG
+typedef unsigned long ulong;
+#endif
+
+/*----------------------- define [u]int8/16/32/64 --------------------------*/
+
+#ifndef TYPEDEF_UINT8
+typedef unsigned char uint8;
+#endif
+
+#ifndef TYPEDEF_UINT16
+typedef unsigned short uint16;
+#endif
+
+#ifndef TYPEDEF_UINT32
+typedef unsigned int uint32;
+#endif
+
+#ifndef TYPEDEF_UINT64
+typedef unsigned long long uint64;
+#endif
+
+#ifndef TYPEDEF_INT8
+typedef signed char int8;
+#endif
+
+#ifndef TYPEDEF_INT16
+typedef signed short int16;
+#endif
+
+#ifndef TYPEDEF_INT32
+typedef signed int int32;
+#endif
+
+#ifndef TYPEDEF_INT64
+typedef signed long long int64;
+#endif
+
+/*----------------------- define float32/64, float_t -----------------------*/
+
+#ifndef TYPEDEF_FLOAT32
+typedef float float32;
+#endif
+
+#ifndef TYPEDEF_FLOAT64
+typedef double float64;
+#endif
+
+/*
+ * abstracted floating point type allows for compile time selection of
+ * single or double precision arithmetic. Compiling with -DFLOAT32
+ * selects single precision; the default is double precision.
+ */
+
+#ifndef TYPEDEF_FLOAT_T
+
+#if defined(FLOAT32)
+typedef float32 float_t;
+#else /* default to double precision floating point */
+typedef float64 float_t;
+#endif
+
+#endif /* TYPEDEF_FLOAT_T */
+
+/*----------------------- define macro values -----------------------------*/
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef OFF
+#define OFF 0
+#endif
+
+#ifndef ON
+#define ON 1
+#endif
+
+/*----------------------- define PTRSZ, INLINE ----------------------------*/
+
+#ifndef PTRSZ
+#define PTRSZ sizeof (char*)
+#endif
+
+#ifndef INLINE
+
+#ifdef _MSC_VER
+
+#define INLINE __inline
+
+#elif __GNUC__
+
+#define INLINE __inline__
+
+#else
+
+#define INLINE
+
+#endif /* _MSC_VER */
+
+#endif /* INLINE */
+
+#undef TYPEDEF_BOOL
+#undef TYPEDEF_UCHAR
+#undef TYPEDEF_USHORT
+#undef TYPEDEF_UINT
+#undef TYPEDEF_ULONG
+#undef TYPEDEF_UINT8
+#undef TYPEDEF_UINT16
+#undef TYPEDEF_UINT32
+#undef TYPEDEF_UINT64
+#undef TYPEDEF_INT8
+#undef TYPEDEF_INT16
+#undef TYPEDEF_INT32
+#undef TYPEDEF_INT64
+#undef TYPEDEF_FLOAT32
+#undef TYPEDEF_FLOAT64
+#undef TYPEDEF_FLOAT_T
+
+#endif /* USE_TYPEDEF_DEFAULTS */
+
+#endif /* _TYPEDEFS_H_ */
diff --git a/package/wlcompat/src/include/utils.h b/package/wlcompat/src/include/utils.h
new file mode 100644
index 0000000000..b8d1cdb7bf
--- /dev/null
+++ b/package/wlcompat/src/include/utils.h
@@ -0,0 +1,131 @@
+#include <cy_conf.h>
+
+extern int diag_led(int type, int act);
+extern int C_led(int i);
+extern int get_single_ip(char *ipaddr, int which);
+extern char *get_mac_from_ip(char *ip);
+extern struct dns_lists *get_dns_list(int no);
+extern int dns_to_resolv(void);
+extern char *get_wan_face(void);
+extern int check_wan_link(int num);
+extern char *get_complete_lan_ip(char *ip);
+extern int get_int_len(int num);
+extern int file_to_buf(char *path, char *buf, int len);
+extern int buf_to_file(char *path, char *buf);
+extern pid_t* find_pid_by_name( char* pidName);
+extern int find_pid_by_ps(char* pidName);
+extern int *find_all_pid_by_ps(char* pidName);
+extern char *find_name_by_proc(int pid);
+extern int get_ppp_pid(char *file);
+extern long convert_ver(char *ver);
+extern int check_flash(void);
+extern int check_action(void);
+extern int check_now_boot(void);
+extern int check_hw_type(void);
+extern int is_exist(char *filename);
+extern void set_ip_forward(char c);
+struct mtu_lists *get_mtu(char *proto);
+extern void set_host_domain_name(void);
+
+extern void encode(char *buf, int len);
+extern void decode(char *buf, int len);
+
+extern int sys_netdev_ioctl(int family, int socket, char *if_name, int cmd, struct ifreq *ifr);
+
+int ct_openlog(const char *ident, int option, int facility, char *log_name);
+void ct_syslog(int level, int enable, const char *fmt,...);
+void ct_logger(int level, const char *fmt,...);
+struct wl_assoc_mac * get_wl_assoc_mac(int *c);
+
+
+
+enum { DMZ, SESSION, DIAG , WL};
+
+enum { START_LED, STOP_LED };
+
+typedef enum { ACT_IDLE,
+ ACT_TFTP_UPGRADE,
+ ACT_WEB_UPGRADE,
+ ACT_WEBS_UPGRADE,
+ ACT_SW_RESTORE,
+ ACT_HW_RESTORE } ACTION;
+
+enum { UNKNOWN_BOOT = -1, PMON_BOOT, CFE_BOOT };
+
+enum { BCM4702_CHIP, BCM4712_CHIP, BCM5325E_CHIP };
+
+enum { FIRST, SECOND };
+
+enum { SYSLOG_LOG=1, SYSLOG_DEBUG, CONSOLE_ONLY, LOG_CONSOLE, DEBUG_CONSOLE };
+
+#define ACTION(cmd) buf_to_file(ACTION_FILE, cmd)
+
+struct dns_lists {
+ int num_servers;
+ char dns_server[4][16];
+};
+
+#define NOT_USING 0
+#define USING 1
+
+struct wl_assoc_mac
+{
+ char mac[18];
+};
+
+struct mtu_lists {
+ char *proto; /* protocol */
+ char *min; /* min mtu */
+ char *max; /* max mtu */
+};
+
+
+#define PPP_PSEUDO_IP "10.64.64.64"
+#define PPP_PSEUDO_NM "255.255.255.255"
+#define PPP_PSEUDO_GW "10.112.112.112"
+
+#define PING_TMP "/tmp/ping.log"
+#define TRACEROUTE_TMP "/tmp/traceroute.log"
+#define MAX_BUF_LEN 254
+
+#define RESOLV_FILE "/tmp/resolv.conf"
+#define HOSTS_FILE "/tmp/hosts"
+
+#define LOG_FILE "/var/log/mess"
+
+#define ACTION_FILE "/tmp/action"
+
+
+#define split(word, wordlist, next, delim) \
+ for (next = wordlist, \
+ strncpy(word, next, sizeof(word)), \
+ word[(next=strstr(next, delim)) ? strstr(word, delim) - word : sizeof(word) - 1] = '\0', \
+ next = next ? next + sizeof(delim) - 1 : NULL ; \
+ strlen(word); \
+ next = next ? : "", \
+ strncpy(word, next, sizeof(word)), \
+ word[(next=strstr(next, delim)) ? strstr(word, delim) - word : sizeof(word) - 1] = '\0', \
+ next = next ? next + sizeof(delim) - 1 : NULL)
+
+#define STRUCT_LEN(name) sizeof(name)/sizeof(name[0])
+
+#define printHEX(str,len) { \
+ int i; \
+ for (i=0 ; i<len ; i++) { \
+ printf("%02X ", (unsigned char)*(str+i)); \
+ if(((i+1)%16) == 0) printf("- "); \
+ if(((i+1)%32) == 0) printf("\n"); \
+ } \
+ printf("\n\n"); \
+}
+
+
+#define printASC(str,len) { \
+ int i; \
+ for (i=0 ; i<len ; i++) { \
+ printf("%c", (unsigned char)*(str+i)); \
+ if(((i+1)%16) == 0) printf("- "); \
+ if(((i+1)%32) == 0) printf("\n"); \
+ } \
+ printf("\n\n"); \
+}
diff --git a/package/wlcompat/src/include/wlcompat.h b/package/wlcompat/src/include/wlcompat.h
new file mode 100644
index 0000000000..a4fc13439d
--- /dev/null
+++ b/package/wlcompat/src/include/wlcompat.h
@@ -0,0 +1,36 @@
+/*
+ * wlcompat.h
+ *
+ * Copyright (C) 2005 Felix Fietkau <nbd@vd-s.ath.cx>
+ *
+ * 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.
+ *
+ * $Id$
+ */
+#include <linux/wireless.h>
+
+#ifndef WLCOMPAT_H
+#define WLCOMPAT_H
+
+#define WLCOMPAT_SET_MONITOR SIOCIWFIRSTPRIV + 0
+#define WLCOMPAT_GET_MONITOR SIOCIWFIRSTPRIV + 1
+#define WLCOMPAT_SET_TXPWR_LIMIT SIOCIWFIRSTPRIV + 2
+#define WLCOMPAT_GET_TXPWR_LIMIT SIOCIWFIRSTPRIV + 3
+#define WLCOMPAT_SET_ANTDIV SIOCIWFIRSTPRIV + 4
+#define WLCOMPAT_GET_ANTDIV SIOCIWFIRSTPRIV + 5
+#define WLCOMPAT_SET_TXANT SIOCIWFIRSTPRIV + 6
+#define WLCOMPAT_GET_TXANT SIOCIWFIRSTPRIV + 7
+
+#endif
diff --git a/package/wlcompat/src/include/wlioctl.h b/package/wlcompat/src/include/wlioctl.h
new file mode 100644
index 0000000000..d5ef11f9ed
--- /dev/null
+++ b/package/wlcompat/src/include/wlioctl.h
@@ -0,0 +1,1094 @@
+/*
+ * Custom OID/ioctl definitions for
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Definitions subject to change without notice.
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#ifndef _wlioctl_h_
+#define _wlioctl_h_
+
+#include <typedefs.h>
+#include <proto/ethernet.h>
+#include <proto/802.11.h>
+
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#define PACKED
+#endif
+
+#define WLC_ESSID_MAX_SIZE 32
+
+#define WL_NUMRATES 255 /* max # of rates in a rateset */
+
+typedef struct wl_rateset {
+ uint32 count; /* # rates in this set */
+ uint8 rates[WL_NUMRATES]; /* rates in 500kbps units w/hi bit set if basic */
+} wl_rateset_t;
+
+#define WL_CHANSPEC_CHAN_MASK 0x0fff
+#define WL_CHANSPEC_BAND_MASK 0xf000
+#define WL_CHANSPEC_BAND_SHIFT 12
+#define WL_CHANSPEC_BAND_A 0x1000
+#define WL_CHANSPEC_BAND_B 0x2000
+
+/*
+ * Per-bss information structure.
+ */
+
+#define WL_LEGACY_BSS_INFO_VERSION 106 /* an older supported version of wl_bss_info struct */
+#define WL_BSS_INFO_VERSION 107 /* current version of wl_bss_info struct */
+
+typedef struct wl_bss_info106 {
+ uint version; /* version field */
+ struct ether_addr BSSID;
+ uint8 SSID_len;
+ uint8 SSID[32];
+ uint8 Privacy; /* 0=No WEP, 1=Use WEP */
+ int16 RSSI; /* receive signal strength (in dBm) */
+ uint16 beacon_period; /* units are Kusec */
+ uint16 atim_window; /* units are Kusec */
+ uint8 channel; /* Channel no. */
+ int8 infra; /* 0=IBSS, 1=infrastructure, 2=unknown */
+ struct {
+ uint count; /* # rates in this set */
+ uint8 rates[12]; /* rates in 500kbps units w/hi bit set if basic */
+ } rateset; /* supported rates */
+ uint8 dtim_period; /* DTIM period */
+ int8 phy_noise; /* noise right after tx (in dBm) */
+ uint16 capability; /* Capability information */
+ struct dot11_bcn_prb *prb; /* probe response frame (ioctl na) */
+ uint16 prb_len; /* probe response frame length (ioctl na) */
+ struct {
+ uint8 supported; /* wpa supported */
+ uint8 multicast; /* multicast cipher */
+ uint8 ucount; /* count of unicast ciphers */
+ uint8 unicast[4]; /* unicast ciphers */
+ uint8 acount; /* count of auth modes */
+ uint8 auth[4]; /* Authentication modes */
+ } wpa;
+} wl_bss_info106_t;
+
+typedef struct wl_bss_info {
+ uint32 version; /* version field */
+ uint32 length; /* byte length of data in this record, starting at version and including IEs */
+ struct ether_addr BSSID;
+ uint16 beacon_period; /* units are Kusec */
+ uint16 capability; /* Capability information */
+ uint8 SSID_len;
+ uint8 SSID[32];
+ struct {
+ uint count; /* # rates in this set */
+ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */
+ } rateset; /* supported rates */
+ uint8 channel; /* Channel no. */
+ uint16 atim_window; /* units are Kusec */
+ uint8 dtim_period; /* DTIM period */
+ int16 RSSI; /* receive signal strength (in dBm) */
+ int8 phy_noise; /* noise (in dBm) */
+ uint32 ie_length; /* byte length of Information Elements */
+ /* variable length Information Elements */
+} wl_bss_info_t;
+
+typedef struct wlc_ssid {
+ uint32 SSID_len;
+ uchar SSID[32];
+} wlc_ssid_t;
+
+typedef struct wl_scan_params {
+ wlc_ssid_t ssid; /* default is {0, ""} */
+ struct ether_addr bssid;/* default is bcast */
+ int8 bss_type; /* default is any, DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT */
+ int8 scan_type; /* -1 use default, DOT11_SCANTYPE_ACTIVE/PASSIVE */
+ int32 nprobes; /* -1 use default, number of probes per channel */
+ int32 active_time; /* -1 use default, dwell time per channel for active scanning */
+ int32 passive_time; /* -1 use default, dwell time per channel for passive scanning */
+ int32 home_time; /* -1 use default, dwell time for the home channel between channel scans */
+ int32 channel_num; /* 0 use default (all available channels), count of channels in channel_list */
+ uint16 channel_list[1]; /* list of chanspecs */
+} wl_scan_params_t;
+/* size of wl_scan_params not including variable length array */
+#define WL_SCAN_PARAMS_FIXED_SIZE 64
+
+typedef struct wl_scan_results {
+ uint32 buflen;
+ uint32 version;
+ uint32 count;
+ wl_bss_info_t bss_info[1];
+} wl_scan_results_t;
+/* size of wl_scan_results not including variable length array */
+#define WL_SCAN_RESULTS_FIXED_SIZE 12
+
+/* uint32 list */
+typedef struct wl_uint32_list {
+ /* in - # of elements, out - # of entries */
+ uint32 count;
+ /* variable length uint32 list */
+ uint32 element[1];
+} wl_uint32_list_t;
+
+#define WLC_CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NULL */
+
+typedef struct wl_channels_in_country {
+ uint32 buflen;
+ uint32 band;
+ char country_abbrev[WLC_CNTRY_BUF_SZ];
+ uint32 count;
+ uint32 channel[1];
+} wl_channels_in_country_t;
+
+typedef struct wl_country_list {
+ uint32 buflen;
+ uint32 band_set;
+ uint32 band;
+ uint32 count;
+ char country_abbrev[1];
+} wl_country_list_t;
+
+#define WL_RM_TYPE_BASIC 1
+#define WL_RM_TYPE_CCA 2
+#define WL_RM_TYPE_RPI 3
+
+#define WL_RM_FLAG_PARALLEL (1<<0)
+
+#define WL_RM_FLAG_LATE (1<<1)
+#define WL_RM_FLAG_INCAPABLE (1<<2)
+#define WL_RM_FLAG_REFUSED (1<<3)
+
+typedef struct wl_rm_req_elt {
+ int8 type;
+ int8 flags;
+ uint16 chanspec;
+ uint32 token; /* token for this measurement */
+ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */
+ uint32 tsf_l; /* TSF low 32-bits */
+ uint32 dur; /* TUs */
+} wl_rm_req_elt_t;
+
+typedef struct wl_rm_req {
+ uint32 token; /* overall measurement set token */
+ uint32 count; /* number of measurement reqests */
+ wl_rm_req_elt_t req[1]; /* variable length block of requests */
+} wl_rm_req_t;
+#define WL_RM_REQ_FIXED_LEN 8
+
+typedef struct wl_rm_rep_elt {
+ int8 type;
+ int8 flags;
+ uint16 chanspec;
+ uint32 token; /* token for this measurement */
+ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */
+ uint32 tsf_l; /* TSF low 32-bits */
+ uint32 dur; /* TUs */
+ uint32 len; /* byte length of data block */
+ uint8 data[1]; /* variable length data block */
+} wl_rm_rep_elt_t;
+#define WL_RM_REP_ELT_FIXED_LEN 24 /* length excluding data block */
+
+#define WL_RPI_REP_BIN_NUM 8
+typedef struct wl_rm_rpi_rep {
+ uint8 rpi[WL_RPI_REP_BIN_NUM];
+ int8 rpi_max[WL_RPI_REP_BIN_NUM];
+} wl_rm_rpi_rep_t;
+
+typedef struct wl_rm_rep {
+ uint32 token; /* overall measurement set token */
+ uint32 len; /* length of measurement report block */
+ wl_rm_rep_elt_t rep[1]; /* variable length block of reports */
+} wl_rm_rep_t;
+#define WL_RM_REP_FIXED_LEN 8
+
+
+#define WLC_MAX_KEY_SIZE 32 /* max size of any key */
+#define WLC_MAX_IV_SIZE 16 /* max size of any IV */
+#define WLC_EXT_IV_FLAG (1<<5) /* flag to indicate IV is > 4 bytes */
+#define WLC_MAX_DEFAULT_KEYS 4 /* # of default WEP keys */
+#define WLC_MAX_KEYS 54 /* Max # of WEP keys */
+#define WLC_WEP1_KEY_SIZE 5 /* max size of any WEP key */
+#define WLC_WEP1_KEY_HEX_SIZE 10 /* size of WEP key in hex. */
+#define WLC_WEP128_KEY_SIZE 13 /* max size of any WEP key */
+#define WLC_WEP128_KEY_HEX_SIZE 26 /* size of WEP key in hex. */
+#define WLC_TKIP_MIC_SIZE 8 /* size of TKIP MIC */
+#define WLC_TKIP_EOM_SIZE 7 /* max size of TKIP EOM */
+#define WLC_TKIP_EOM_FLAG 0x5a /* TKIP EOM flag byte */
+#define WLC_TKIP_KEY_SIZE 32 /* size of any TKIP key */
+#define WLC_TKIP_MIC_AUTH_TX 16 /* offset to Authenticator MIC TX key */
+#define WLC_TKIP_MIC_AUTH_RX 24 /* offset to Authenticator MIC RX key */
+#define WLC_TKIP_MIC_SUP_RX 16 /* offset to Supplicant MIC RX key */
+#define WLC_TKIP_MIC_SUP_TX 24 /* offset to Supplicant MIC TX key */
+#define WLC_TKIP_P1_KEY_SIZE 10 /* size of TKHash Phase1 output, in bytes */
+#define WLC_TKIP_P2_KEY_SIZE 16 /* size of TKHash Phase2 output */
+#define WLC_AES_KEY_SIZE 16 /* size of AES key */
+
+
+typedef enum sup_auth_status {
+ WLC_SUP_DISCONNECTED = 0,
+ WLC_SUP_CONNECTING,
+ WLC_SUP_IDREQUIRED,
+ WLC_SUP_AUTHENTICATING,
+ WLC_SUP_AUTHENTICATED,
+ WLC_SUP_KEYXCHANGE,
+ WLC_SUP_KEYED
+} sup_auth_status_t;
+
+/* Enumerate crypto algorithms */
+#define CRYPTO_ALGO_OFF 0
+#define CRYPTO_ALGO_WEP1 1
+#define CRYPTO_ALGO_TKIP 2
+#define CRYPTO_ALGO_WEP128 3
+#define CRYPTO_ALGO_AES_CCM 4
+#define CRYPTO_ALGO_AES_OCB_MSDU 5
+#define CRYPTO_ALGO_AES_OCB_MPDU 6
+#define CRYPTO_ALGO_NALG 7
+
+#define WSEC_GEN_MIC_ERROR 0x0001
+#define WSEC_GEN_REPLAY 0x0002
+
+#define WL_SOFT_KEY (1 << 0) /* Indicates this key is using soft encrypt */
+#define WL_PRIMARY_KEY (1 << 1) /* Indicates this key is the primary (ie tx) key */
+#define WL_KF_RES_4 (1 << 4) /* Reserved for backward compat */
+#define WL_KF_RES_5 (1 << 5) /* Reserved for backward compat */
+
+
+typedef struct wlc_tkip_info {
+ uint16 phase1[WLC_TKIP_P1_KEY_SIZE/sizeof(uint16)]; /* tkhash phase1 result */
+ uint8 phase2[WLC_TKIP_P2_KEY_SIZE]; /* tkhash phase2 result */
+ uint32 micl;
+ uint32 micr;
+} tkip_info_t;
+
+typedef struct _wsec_iv {
+ uint32 hi; /* upper 32 bits of IV */
+ uint16 lo; /* lower 16 bits of IV */
+} wsec_iv_t;
+
+typedef struct wsec_key {
+ uint32 index; /* key index */
+ uint32 len; /* key length */
+ uint8 data[WLC_MAX_KEY_SIZE]; /* key data */
+ tkip_info_t tkip_tx; /* tkip transmit state */
+ tkip_info_t tkip_rx; /* tkip receive state */
+ uint32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+ uint32 flags; /* misc flags */
+ uint32 algo_hw; /* cache for hw register*/
+ uint32 aes_mode; /* cache for hw register*/
+ int iv_len; /* IV length */
+ int iv_initialized; /* has IV been initialized already? */
+ int icv_len; /* ICV length */
+ wsec_iv_t rxiv; /* Rx IV */
+ wsec_iv_t txiv; /* Tx IV */
+ struct ether_addr ea; /* per station */
+} wsec_key_t;
+
+
+
+typedef struct wl_wsec_key {
+ uint32 index; /* key index */
+ uint32 len; /* key length */
+ uint8 data[DOT11_MAX_KEY_SIZE]; /* key data */
+ uint32 pad_1[18];
+ uint32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+ uint32 flags; /* misc flags */
+ uint32 pad_2[2];
+ int pad_3;
+ int iv_initialized; /* has IV been initialized already? */
+ int pad_4;
+ /* Rx IV */
+ struct {
+ uint32 hi; /* upper 32 bits of IV */
+ uint16 lo; /* lower 16 bits of IV */
+ } rxiv;
+ uint32 pad_5[2];
+ struct ether_addr ea; /* per station */
+} wl_wsec_key_t;
+
+/* For use with wlc_wep_key.flags */
+#define WSEC_PRIMARY_KEY (1 << 1) /* Indicates this key is the primary (ie tx) key */
+#define WSEC_TKIP_ERROR (1 << 2) /* Provoke deliberate error */
+
+#define WSEC_MIN_PSK_LEN 8
+#define WSEC_MAX_PSK_LEN 64
+
+/* Flag for key material needing passhash'ing */
+#define WSEC_PASSPHRASE (1<<0)
+
+/* recepticle for WLC_SET_WSEC_PMK parameter */
+typedef struct {
+ ushort key_len; /* octets in key material */
+ ushort flags; /* key handling qualification */
+ uint8 key[WSEC_MAX_PSK_LEN]; /* PMK material */
+} wsec_pmk_t;
+
+/* wireless security bitvec */
+#define WEP_ENABLED 1
+#define TKIP_ENABLED 2
+#define AES_ENABLED 4
+#define WSEC_SWFLAG 8
+
+#define WSEC_SW(wsec) ((wsec) & WSEC_SWFLAG)
+#define WSEC_HW(wsec) (!WSEC_SW(wsec))
+#define WSEC_WEP_ENABLED(wsec) ((wsec) & WEP_ENABLED)
+#define WSEC_TKIP_ENABLED(wsec) ((wsec) & TKIP_ENABLED)
+#define WSEC_AES_ENABLED(wsec) ((wsec) & AES_ENABLED)
+#define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
+
+
+/* wireless authentication bit vector */
+#define WPA_ENABLED 1
+#define PSK_ENABLED 2
+
+#define WAUTH_WPA_ENABLED(wauth) ((wauth) & WPA_ENABLED)
+#define WAUTH_PSK_ENABLED(wauth) ((wauth) & PSK_ENABLED)
+#define WAUTH_ENABLED(wauth) ((wauth) & (WPA_ENABLED | PSK_ENABLED))
+
+/* group/mcast cipher */
+#define WPA_MCAST_CIPHER(wsec) (((wsec) & TKIP_ENABLED) ? WPA_CIPHER_TKIP : \
+ ((wsec) & AES_ENABLED) ? WPA_CIPHER_AES_CCM : \
+ WPA_CIPHER_NONE)
+
+
+typedef struct wl_led_info {
+ uint32 index; /* led index */
+ uint32 behavior;
+ bool activehi;
+} wl_led_info_t;
+
+/*
+ * definitions for driver messages passed from WL to NAS.
+ */
+/* Use this to recognize wpa and 802.1x driver messages. */
+static const uint8 wl_wpa_snap_template[] =
+ { 0xaa, 0xaa, 0x03, 0x00, 0x90, 0x4c };
+
+#define WL_WPA_MSG_IFNAME_MAX 16
+
+/* WPA driver message */
+typedef struct wl_wpa_header {
+ struct ether_header eth;
+ struct dot11_llc_snap_header snap;
+ uint8 version;
+ uint8 type;
+ /* version 2 additions */
+ char ifname[WL_WPA_MSG_IFNAME_MAX];
+ /* version specific data */
+ /* uint8 data[1]; */
+} wl_wpa_header_t PACKED;
+
+/*
+ * definitions for 802.2 messages passed from WL to NAS.
+ */
+/* This seems not to be defined outside the kernel on linux. */
+#ifndef ETH_P_802_2
+#define ETH_P_802_2 4
+#endif
+
+#define WL_WPA_HEADER_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN + 2 + WL_WPA_MSG_IFNAME_MAX)
+
+/* WPA driver message ethertype - private between wlc and nas */
+#define WL_WPA_ETHER_TYPE 0x9999
+
+/* WPA driver message current version */
+#define WL_WPA_MSG_VERSION 2
+
+/* Type field values for the 802.2 driver messages for WPA. */
+#define WLC_ASSOC_MSG 1
+#define WLC_DISASSOC_MSG 2
+#define WLC_PTK_MIC_MSG 3
+#define WLC_GTK_MIC_MSG 4
+
+/* Use this to recognize 802.2 driver messages. */
+static const uint8 wpa_snap_template[] =
+ { 0xaa, 0xaa, 0x03, 0x00, 0x90, 0x4c };
+
+
+/* 802.1x driver message */
+typedef struct wl_eapol_header {
+ struct ether_header eth;
+ struct dot11_llc_snap_header snap;
+ uint8 version;
+ uint8 reserved;
+ char ifname[WL_WPA_MSG_IFNAME_MAX];
+ /* version specific data */
+ /* uint8 802_1x_msg[1]; */
+} wl_eapol_header_t PACKED;
+
+#define WL_EAPOL_HEADER_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN + 2 + WL_WPA_MSG_IFNAME_MAX)
+
+/* 802.1x driver message ethertype - private between wlc and nas */
+#define WL_EAPOL_ETHER_TYPE 0x999A
+
+/* 802.1x driver message current version */
+#define WL_EAPOL_MSG_VERSION 1
+
+/* srom read/write struct passed through ioctl */
+typedef struct {
+ uint byteoff; /* byte offset */
+ uint nbytes; /* number of bytes */
+ uint16 buf[1];
+} srom_rw_t;
+
+/* R_REG and W_REG struct passed through ioctl */
+typedef struct {
+ uint32 byteoff; /* byte offset of the field in d11regs_t */
+ uint32 val; /* read/write value of the field */
+ uint32 size; /* sizeof the field */
+} rw_reg_t;
+
+/* Structure used by GET/SET_ATTEN ioctls */
+typedef struct {
+ uint16 auto_ctrl; /* 1: Automatic control, 0: overriden */
+ uint16 bb; /* Baseband attenuation */
+ uint16 radio; /* Radio attenuation */
+ uint16 txctl1; /* Radio TX_CTL1 value */
+} atten_t;
+
+/* Used to get specific STA parameters */
+typedef struct {
+ uint32 val;
+ struct ether_addr ea;
+} scb_val_t;
+
+/* callback registration data types */
+
+typedef struct _mac_event_params {
+ uint msg;
+ struct ether_addr *addr;
+ uint result;
+ uint status;
+ uint auth_type;
+} mac_event_params_t;
+
+typedef struct _mic_error_params {
+ struct ether_addr *ea;
+ bool group;
+ bool flush_txq;
+} mic_error_params_t;
+
+typedef enum _wl_callback {
+ WL_MAC_EVENT_CALLBACK = 0,
+ WL_LINK_UP_CALLBACK,
+ WL_LINK_DOWN_CALLBACK,
+ WL_MIC_ERROR_CALLBACK,
+ WL_LAST_CALLBACK
+} wl_callback_t;
+
+typedef struct _callback {
+ void (*fn)(void *, void *);
+ void *context;
+} callback_t;
+
+typedef struct _scan_callback {
+ void (*fn)(void *);
+ void *context;
+} scan_callback_t;
+
+/* used to register an arbitrary callback via the IOCTL interface */
+typedef struct _set_callback {
+ int index;
+ callback_t callback;
+} set_callback_t;
+
+
+
+/* Event data type */
+typedef struct {
+ uint msg; /* Message (see below) */
+ struct ether_addr *addr; /* Station address (if applicable) */
+ uint status; /* Status code (see below) */
+ uint reason; /* Reason code (if applicable) */
+ uint auth_type; /* WLC_E_AUTH */
+ bool link; /* WLC_E_LINK */
+ bool group; /* WLC_E_MIC_ERROR */
+ bool flush_txq; /* WLC_E_MIC_ERROR */
+} wlc_event_t;
+
+typedef struct {
+ uint16 ver; /* version of this struct */
+ uint16 cap; /* sta's advertized capabilities */
+ uint32 flags; /* flags defined below */
+ uint32 idle; /* time since data pkt rx'd from sta */
+ struct ether_addr ea; /* Station address */
+ wl_rateset_t rateset; /* rateset in use */
+} sta_info_t;
+
+#define WL_STA_INFO_LEN 300
+#define WL_STA_VER 1
+
+/* flags fields */
+#define WL_STA_BRCM 0x01
+#define WL_STA_WME 0x02
+#define WL_STA_ABCAP 0x04
+#define WL_STA_AUTHE 0x08
+#define WL_STA_ASSOC 0x10
+#define WL_STA_AUTHO 0x20
+
+/* Event messages */
+#define WLC_E_SET_SSID 1
+#define WLC_E_JOIN 2
+#define WLC_E_START 3
+#define WLC_E_AUTH 4
+#define WLC_E_AUTH_IND 5
+#define WLC_E_DEAUTH 6
+#define WLC_E_DEAUTH_IND 7
+#define WLC_E_ASSOC 8
+#define WLC_E_ASSOC_IND 9
+#define WLC_E_REASSOC 10
+#define WLC_E_REASSOC_IND 11
+#define WLC_E_DISASSOC 12
+#define WLC_E_DISASSOC_IND 13
+#define WLC_E_QUIET_START 14 /* 802.11h Quiet period started */
+#define WLC_E_QUIET_END 15 /* 802.11h Quiet period ended */
+#define WLC_E_GOT_BEACONS 16
+#define WLC_E_LINK 17 /* Link indication */
+#define WLC_E_MIC_ERROR 18 /* TKIP MIC error occurred */
+#define WLC_E_NDIS_LINK 19 /* NDIS style link indication */
+#define WLC_E_ROAM 20
+#define WLC_E_LAST 21
+
+/* Event status codes */
+#define WLC_E_STATUS_SUCCESS 0
+#define WLC_E_STATUS_FAIL 1
+#define WLC_E_STATUS_TIMEOUT 2
+#define WLC_E_STATUS_NO_NETWORKS 3
+#define WLC_E_STATUS_ABORT 4
+
+typedef struct wlc_event_cb {
+ uint msg; /* Event message or 0 for all */
+ void (*fn)(void *, wlc_event_t *); /* Callback function */
+ void *context; /* Passed to callback function */
+ struct wlc_event_cb *next; /* Next in the chain */
+} wlc_event_cb_t;
+
+/*
+ * Country locale determines which channels are available to us.
+ */
+typedef enum _wlc_locale {
+ WLC_WW = 0, /* Worldwide */
+ WLC_THA, /* Thailand */
+ WLC_ISR, /* Israel */
+ WLC_JDN, /* Jordan */
+ WLC_PRC, /* China */
+ WLC_JPN, /* Japan */
+ WLC_FCC, /* USA */
+ WLC_EUR, /* Europe */
+ WLC_USL, /* US Low Band only */
+ WLC_JPH, /* Japan High Band only */
+ WLC_ALL, /* All the channels in this band */
+ WLC_11D, /* Represents locale recieved by 11d beacons */
+ WLC_LAST_LOCALE,
+ WLC_UNDEFINED_LOCALE = 0xf
+} wlc_locale_t;
+
+/* channel encoding */
+typedef struct channel_info {
+ int hw_channel;
+ int target_channel;
+ int scan_channel;
+} channel_info_t;
+
+/* For ioctls that take a list of MAC addresses */
+struct maclist {
+ uint count; /* number of MAC addresses */
+ struct ether_addr ea[1]; /* variable length array of MAC addresses */
+};
+
+/* get pkt count struct passed through ioctl */
+typedef struct get_pktcnt {
+ uint rx_good_pkt;
+ uint rx_bad_pkt;
+ uint tx_good_pkt;
+ uint tx_bad_pkt;
+} get_pktcnt_t;
+
+/* Linux network driver ioctl encoding */
+typedef struct wl_ioctl {
+ uint cmd; /* common ioctl definition */
+ void *buf; /* pointer to user buffer */
+ uint len; /* length of user buffer */
+ bool set; /* get or set request (optional) */
+ uint used; /* bytes read or written (optional) */
+ uint needed; /* bytes needed (optional) */
+} wl_ioctl_t;
+
+/*
+ * Structure for passing hardware and software
+ * revision info up from the driver.
+ */
+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;
+
+/* check this magic number */
+#define WLC_IOCTL_MAGIC 0x14e46c77
+
+/* bump this number if you change the ioctl interface */
+#define WLC_IOCTL_VERSION 1
+
+/* maximum length buffer required */
+#define WLC_IOCTL_MAXLEN 8192
+
+/* common ioctl definitions */
+#define WLC_GET_MAGIC 0
+#define WLC_GET_VERSION 1
+#define WLC_UP 2
+#define WLC_DOWN 3
+#define WLC_GET_LOOP 4
+#define WLC_SET_LOOP 5
+#define WLC_DUMP 6
+#define WLC_GET_MSGLEVEL 7
+#define WLC_SET_MSGLEVEL 8
+#define WLC_GET_PROMISC 9
+#define WLC_SET_PROMISC 10
+#define WLC_OBSOLETE 11
+#define WLC_GET_RATE 12
+#define WLC_SET_RATE 13
+#define WLC_GET_INSTANCE 14
+#define WLC_GET_FRAG 15
+#define WLC_SET_FRAG 16
+#define WLC_GET_RTS 17
+#define WLC_SET_RTS 18
+#define WLC_GET_INFRA 19
+#define WLC_SET_INFRA 20
+#define WLC_GET_AUTH 21
+#define WLC_SET_AUTH 22
+#define WLC_GET_BSSID 23
+#define WLC_SET_BSSID 24
+#define WLC_GET_SSID 25
+#define WLC_SET_SSID 26
+#define WLC_RESTART 27
+#define WLC_DUMP_SCB 28
+#define WLC_GET_CHANNEL 29
+#define WLC_SET_CHANNEL 30
+#define WLC_GET_SRL 31
+#define WLC_SET_SRL 32
+#define WLC_GET_LRL 33
+#define WLC_SET_LRL 34
+#define WLC_GET_PLCPHDR 35
+#define WLC_SET_PLCPHDR 36
+#define WLC_GET_RADIO 37
+#define WLC_SET_RADIO 38
+#define WLC_GET_PHYTYPE 39
+#define WLC_DUMP_RATE 40
+#define WLC_SET_RATE_PARAMS 41
+#define WLC_GET_WEP 42
+#define WLC_SET_WEP 43
+#define WLC_GET_KEY 44
+#define WLC_SET_KEY 45
+#define WLC_GET_REGULATORY 46
+#define WLC_SET_REGULATORY 47
+#define WLC_GET_PASSIVE 48 /* added by nbd */
+#define WLC_SET_PASSIVE 49 /* added by nbd */
+#define WLC_SCAN 50
+#define WLC_SCAN_RESULTS 51
+#define WLC_DISASSOC 52
+#define WLC_REASSOC 53
+#define WLC_GET_ROAM_TRIGGER 54
+#define WLC_SET_ROAM_TRIGGER 55
+#define WLC_GET_ROAM_DELTA 56
+#define WLC_SET_ROAM_DELTA 57
+#define WLC_GET_ROAM_SCAN_PERIOD 58
+#define WLC_SET_ROAM_SCAN_PERIOD 59
+#define WLC_EVM 60
+#define WLC_GET_TXANT 61
+#define WLC_SET_TXANT 62
+#define WLC_GET_ANTDIV 63
+#define WLC_SET_ANTDIV 64
+#define WLC_GET_TXPWR 65
+#define WLC_SET_TXPWR 66
+#define WLC_GET_CLOSED 67
+#define WLC_SET_CLOSED 68
+#define WLC_GET_MACLIST 69
+#define WLC_SET_MACLIST 70
+#define WLC_GET_RATESET 71
+#define WLC_SET_RATESET 72
+#define WLC_GET_LOCALE 73
+#define WLC_SET_LOCALE 74
+#define WLC_GET_BCNPRD 75
+#define WLC_SET_BCNPRD 76
+#define WLC_GET_DTIMPRD 77
+#define WLC_SET_DTIMPRD 78
+#define WLC_GET_SROM 79
+#define WLC_SET_SROM 80
+#define WLC_GET_WEP_RESTRICT 81
+#define WLC_SET_WEP_RESTRICT 82
+#define WLC_GET_COUNTRY 83
+#define WLC_SET_COUNTRY 84
+#define WLC_GET_PM 85
+#define WLC_SET_PM 86
+#define WLC_GET_WAKE 87
+#define WLC_SET_WAKE 88
+#define WLC_GET_D11CNTS 89
+#define WLC_GET_FORCELINK 90 /* ndis only */
+#define WLC_SET_FORCELINK 91 /* ndis only */
+#define WLC_FREQ_ACCURACY 92
+#define WLC_CARRIER_SUPPRESS 93
+#define WLC_GET_PHYREG 94
+#define WLC_SET_PHYREG 95
+#define WLC_GET_RADIOREG 96
+#define WLC_SET_RADIOREG 97
+#define WLC_GET_REVINFO 98
+#define WLC_GET_UCANTDIV 99
+#define WLC_SET_UCANTDIV 100
+#define WLC_R_REG 101
+#define WLC_W_REG 102
+#define WLC_DIAG_LOOPBACK 103
+#define WLC_RESET_D11CNTS 104
+#define WLC_GET_MACMODE 105
+#define WLC_SET_MACMODE 106
+#define WLC_GET_MONITOR 107 /* added by nbd */
+#define WLC_SET_MONITOR 108 /* added by nbd */
+#define WLC_GET_GMODE 109
+#define WLC_SET_GMODE 110
+#define WLC_GET_LEGACY_ERP 111
+#define WLC_SET_LEGACY_ERP 112
+#define WLC_GET_RX_ANT 113
+#define WLC_GET_CURR_RATESET 114 /* current rateset */
+#define WLC_GET_SCANSUPPRESS 115
+#define WLC_SET_SCANSUPPRESS 116
+#define WLC_GET_AP 117
+#define WLC_SET_AP 118
+#define WLC_GET_EAP_RESTRICT 119
+#define WLC_SET_EAP_RESTRICT 120
+#define WLC_SCB_AUTHORIZE 121
+#define WLC_SCB_DEAUTHORIZE 122
+#define WLC_GET_WDSLIST 123
+#define WLC_SET_WDSLIST 124
+#define WLC_GET_ATIM 125
+#define WLC_SET_ATIM 126
+#define WLC_GET_RSSI 127
+#define WLC_GET_PHYANTDIV 128
+#define WLC_SET_PHYANTDIV 129
+#define WLC_AP_RX_ONLY 130
+#define WLC_GET_TX_PATH_PWR 131
+#define WLC_SET_TX_PATH_PWR 132
+#define WLC_GET_WSEC 133
+#define WLC_SET_WSEC 134
+#define WLC_GET_PHY_NOISE 135
+#define WLC_GET_BSS_INFO 136
+#define WLC_GET_PKTCNTS 137
+#define WLC_GET_LAZYWDS 138
+#define WLC_SET_LAZYWDS 139
+#define WLC_GET_BANDLIST 140
+#define WLC_GET_BAND 141
+#define WLC_SET_BAND 142
+#define WLC_SCB_DEAUTHENTICATE 143
+#define WLC_GET_SHORTSLOT 144
+#define WLC_GET_SHORTSLOT_OVERRIDE 145
+#define WLC_SET_SHORTSLOT_OVERRIDE 146
+#define WLC_GET_SHORTSLOT_RESTRICT 147
+#define WLC_SET_SHORTSLOT_RESTRICT 148
+#define WLC_GET_GMODE_PROTECTION 149
+#define WLC_GET_GMODE_PROTECTION_OVERRIDE 150
+#define WLC_SET_GMODE_PROTECTION_OVERRIDE 151
+#define WLC_UPGRADE 152
+#define WLC_GET_MRATE 153
+#define WLC_SET_MRATE 154
+#define WLC_GET_IGNORE_BCNS 155
+#define WLC_SET_IGNORE_BCNS 156
+#define WLC_GET_SCB_TIMEOUT 157
+#define WLC_SET_SCB_TIMEOUT 158
+#define WLC_GET_ASSOCLIST 159
+#define WLC_GET_CLK 160
+#define WLC_SET_CLK 161
+#define WLC_GET_UP 162
+#define WLC_OUT 163
+#define WLC_GET_WPA_AUTH 164
+#define WLC_SET_WPA_AUTH 165
+#define WLC_GET_UCFLAGS 166
+#define WLC_SET_UCFLAGS 167
+#define WLC_GET_PWRIDX 168
+#define WLC_SET_PWRIDX 169
+#define WLC_GET_TSSI 170
+#define WLC_GET_SUP_RATESET_OVERRIDE 171
+#define WLC_SET_SUP_RATESET_OVERRIDE 172
+#define WLC_SET_FAST_TIMER 173
+#define WLC_GET_FAST_TIMER 174
+#define WLC_SET_SLOW_TIMER 175
+#define WLC_GET_SLOW_TIMER 176
+#define WLC_DUMP_PHYREGS 177
+#define WLC_GET_GMODE_PROTECTION_CONTROL 178
+#define WLC_SET_GMODE_PROTECTION_CONTROL 179
+#define WLC_GET_PHYLIST 180
+#define WLC_ENCRYPT_STRENGTH 181 /* ndis only */
+#define WLC_DECRYPT_STATUS 182 /* ndis only */
+#define WLC_GET_KEY_SEQ 183
+#define WLC_GET_SCAN_CHANNEL_TIME 184
+#define WLC_SET_SCAN_CHANNEL_TIME 185
+#define WLC_GET_SCAN_UNASSOC_TIME 186
+#define WLC_SET_SCAN_UNASSOC_TIME 187
+#define WLC_GET_SCAN_HOME_TIME 188
+#define WLC_SET_SCAN_HOME_TIME 189
+#define WLC_GET_SCAN_PASSES 190
+#define WLC_SET_SCAN_PASSES 191
+#define WLC_GET_PRB_RESP_TIMEOUT 192
+#define WLC_SET_PRB_RESP_TIMEOUT 193
+#define WLC_GET_ATTEN 194
+#define WLC_SET_ATTEN 195
+#define WLC_GET_SHMEM 196 /* diag */
+#define WLC_SET_SHMEM 197 /* diag */
+#define WLC_GET_GMODE_PROTECTION_CTS 198
+#define WLC_SET_GMODE_PROTECTION_CTS 199
+#define WLC_SET_TKIP_MIC_FLAG 200
+#define WLC_SCB_DEAUTHENTICATE_FOR_REASON 201
+#define WLC_TKIP_COUNTERMEASURES 202
+#define WLC_GET_PIOMODE 203
+#define WLC_SET_PIOMODE 204
+#define WLC_SET_LED 209
+#define WLC_GET_LED 210
+#define WLC_GET_INTERFERENCE_MODE 211
+#define WLC_SET_INTERFERENCE_MODE 212
+#define WLC_GET_CHANNEL_QA 213
+#define WLC_START_CHANNEL_QA 214
+#define WLC_GET_CHANNEL_SEL 215
+#define WLC_START_CHANNEL_SEL 216
+#define WLC_GET_VALID_CHANNELS 217
+#define WLC_GET_FAKEFRAG 218
+#define WLC_SET_FAKEFRAG 219
+#define WLC_GET_PWROUT_PERCENTAGE 220
+#define WLC_SET_PWROUT_PERCENTAGE 221
+#define WLC_SET_BAD_FRAME_PREEMPT 222
+#define WLC_GET_BAD_FRAME_PREEMPT 223
+#define WLC_SET_LEAP_LIST 224
+#define WLC_GET_LEAP_LIST 225
+#define WLC_GET_CWMIN 226
+#define WLC_SET_CWMIN 227
+#define WLC_GET_CWMAX 228
+#define WLC_SET_CWMAX 229
+#define WLC_GET_WET 230
+#define WLC_SET_WET 231
+#define WLC_GET_KEY_PRIMARY 235
+#define WLC_SET_KEY_PRIMARY 236
+#define WLC_SCAN_WITH_CALLBACK 240
+#define WLC_WDS_GET_REMOTE_HWADDR 246 /* currently handled in wl_linux.c/wl_vx.c */
+#define WLC_SET_CS_SCAN_TIMER 248
+#define WLC_GET_CS_SCAN_TIMER 249
+#define WLC_CURRENT_PWR 256
+#define WLC_GET_CHANNELS_IN_COUNTRY 260
+#define WLC_GET_COUNTRY_LIST 261
+#define WLC_GET_VAR 262 /* get value of named variable */
+#define WLC_SET_VAR 263 /* set named variable to value */
+#define WLC_NVRAM_GET 264
+#define WLC_NVRAM_SET 265
+#define WLC_SET_WSEC_PMK 268
+#define WLC_GET_AUTH_MODE 269
+#define WLC_SET_AUTH_MODE 270
+#define WLC_LAST 273 /* do not change - use get_var/set_var */
+
+/*
+ * Minor kludge alert:
+ * Duplicate a few definitions that irelay requires from epiioctl.h here
+ * so caller doesn't have to include this file and epiioctl.h .
+ * If this grows any more, it would be time to move these irelay-specific
+ * definitions out of the epiioctl.h and into a separate driver common file.
+ */
+#ifndef EPICTRL_COOKIE
+#define EPICTRL_COOKIE 0xABADCEDE
+#endif
+
+/* vx wlc ioctl's offset */
+#define CMN_IOCTL_OFF 0x180
+
+/*
+ * custom OID support
+ *
+ * 0xFF - implementation specific OID
+ * 0xE4 - first byte of Broadcom PCI vendor ID
+ * 0x14 - second byte of Broadcom PCI vendor ID
+ * 0xXX - the custom OID number
+ */
+
+/* begin 0x1f values beyond the start of the ET driver range. */
+#define WL_OID_BASE 0xFFE41420
+
+/* NDIS overrides */
+#define OID_WL_GETINSTANCE (WL_OID_BASE + WLC_GET_INSTANCE)
+#define OID_WL_GET_FORCELINK (WL_OID_BASE + WLC_GET_FORCELINK)
+#define OID_WL_SET_FORCELINK (WL_OID_BASE + WLC_SET_FORCELINK)
+#define OID_WL_ENCRYPT_STRENGTH (WL_OID_BASE + WLC_ENCRYPT_STRENGTH)
+#define OID_WL_DECRYPT_STATUS (WL_OID_BASE + WLC_DECRYPT_STATUS)
+
+#define WL_DECRYPT_STATUS_SUCCESS 1
+#define WL_DECRYPT_STATUS_FAILURE 2
+#define WL_DECRYPT_STATUS_UNKNOWN 3
+
+/* allows user-mode app to poll the status of USB image upgrade */
+#define WLC_UPGRADE_SUCCESS 0
+#define WLC_UPGRADE_PENDING 1
+
+/* Bit masks for radio disabled status - returned by WL_GET_RADIO */
+#define WL_RADIO_SW_DISABLE (1<<0)
+#define WL_RADIO_HW_DISABLE (1<<1)
+
+/* Override bit for WLC_SET_TXPWR. if set, ignore other level limits */
+#define WL_TXPWR_OVERRIDE (1<<31)
+
+
+/* Bus types */
+#define WL_SB_BUS 0 /* Silicon Backplane */
+#define WL_PCI_BUS 1 /* PCI target */
+#define WL_PCMCIA_BUS 2 /* PCMCIA target */
+
+/* band types */
+#define WLC_BAND_AUTO 0 /* auto-select */
+#define WLC_BAND_A 1 /* "a" band (5 Ghz) */
+#define WLC_BAND_B 2 /* "b" band (2.4 Ghz) */
+
+/* MAC list modes */
+#define WLC_MACMODE_DISABLED 0 /* MAC list disabled */
+#define WLC_MACMODE_DENY 1 /* Deny specified (i.e. allow unspecified) */
+#define WLC_MACMODE_ALLOW 2 /* Allow specified (i.e. deny unspecified) */
+
+
+/* 54g modes (basic bits may still be overridden) */
+#define GMODE_LEGACY_B 0 /* Rateset: 1b, 2b, 5.5, 11 */
+ /* Preamble: Long */
+ /* Shortslot: Off */
+#define GMODE_AUTO 1 /* Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 */
+ /* Extended Rateset: 6, 9, 12, 48 */
+ /* Preamble: Long */
+ /* Shortslot: Auto */
+#define GMODE_ONLY 2 /* Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54 */
+ /* Extended Rateset: 6b, 9, 12b, 48 */
+ /* Preamble: Short required */
+ /* Shortslot: Auto */
+#define GMODE_B_DEFERRED 3 /* Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 */
+ /* Extended Rateset: 6, 9, 12, 48 */
+ /* Preamble: Long */
+ /* Shortslot: On */
+#define GMODE_PERFORMANCE 4 /* Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54 */
+ /* Preamble: Short required */
+ /* Shortslot: On and required */
+#define GMODE_LRS 5 /* Rateset: 1b, 2b, 5.5b, 11b */
+ /* Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54 */
+ /* Preamble: Long */
+ /* Shortslot: Auto */
+#define GMODE_MAX 6
+
+
+/* values for PLCPHdr_override */
+#define WLC_PLCP_AUTO -1
+#define WLC_PLCP_SHORT 0
+#define WLC_PLCP_LONG 1
+
+/* values for g_protection_override */
+#define WLC_G_PROTECTION_AUTO -1
+#define WLC_G_PROTECTION_OFF 0
+#define WLC_G_PROTECTION_ON 1
+
+/* values for g_protection_control */
+#define WLC_G_PROTECTION_CTL_OFF 0
+#define WLC_G_PROTECTION_CTL_LOCAL 1
+#define WLC_G_PROTECTION_CTL_OVERLAP 2
+
+/* Values for PM */
+#define PM_OFF 0
+#define PM_MAX 1
+#define PM_FAST 2
+
+/* interference mitigation options */
+#define INTERFERE_NONE 0 /* off */
+#define NON_WLAN 1 /* foreign/non 802.11 interference, no auto detect */
+#define WLAN_MANUAL 2 /* ACI: no auto detection */
+#define WLAN_AUTO 3 /* ACI: auto - detact */
+
+/* Message levels */
+#define WL_ERROR_VAL 0x0001
+#define WL_TRACE_VAL 0x0002
+#define WL_PRHDRS_VAL 0x0004
+#define WL_PRPKT_VAL 0x0008
+#define WL_INFORM_VAL 0x0010
+#define WL_TMP_VAL 0x0020
+#define WL_OID_VAL 0x0040
+#define WL_RATE_VAL 0x0080
+#define WL_ASSOC_VAL 0x0100
+#define WL_PRUSR_VAL 0x0200
+#define WL_PS_VAL 0x0400
+#define WL_TXPWR_VAL 0x0800
+#define WL_GMODE_VAL 0x1000
+#define WL_DUAL_VAL 0x2000
+#define WL_WSEC_VAL 0x4000
+#define WL_WSEC_DUMP_VAL 0x8000
+#define WL_LOG_VAL 0x10000
+#define WL_NRSSI_VAL 0x20000
+#define WL_LOFT_VAL 0x40000
+#define WL_REGULATORY_VAL 0x80000
+#define WL_ACI_VAL 0x100000
+
+
+/* 802.11h enforcement levels */
+#define SPECT_MNGMT_OFF 0 /* 11h disabled */
+#define SPECT_MNGMT_LOOSE 1 /* Allow scan lists to contain non-11h AP */
+ /* when 11h is enabled */
+#define SPECT_MNGMT_STRICT 2 /* Prine out non-11h APs from scan list */
+
+
+
+/* max # of leds supported by GPIO (gpio pin# == led index#) */
+#define WL_LED_NUMGPIO 16 /* gpio 0-15 */
+
+/* led per-pin behaviors */
+#define WL_LED_OFF 0 /* always off */
+#define WL_LED_ON 1 /* always on */
+#define WL_LED_ACTIVITY 2 /* activity */
+#define WL_LED_RADIO 3 /* radio enabled */
+#define WL_LED_ARADIO 4 /* 5 Ghz radio enabled */
+#define WL_LED_BRADIO 5 /* 2.4Ghz radio enabled */
+#define WL_LED_BGMODE 6 /* on if gmode, off if bmode */
+#define WL_LED_WI1 7
+#define WL_LED_WI2 8
+#define WL_LED_WI3 9
+#define WL_LED_ASSOC 10 /* associated state indicator */
+#define WL_LED_INACTIVE 11 /* null behavior (clears default behavior) */
+#define WL_LED_NUMBEHAVIOR 12
+
+/* led behavior numeric value format */
+#define WL_LED_BEH_MASK 0x7f /* behavior mask */
+#define WL_LED_AL_MASK 0x80 /* activelow (polarity) bit */
+
+
+/* maximum channels */
+#define WL_NUMCHANNELS 64 /* max # of channels in the band */
+
+/* rate check */
+#define WL_RATE_OFDM(r) (((r) & 0x7f) == 12 || ((r) & 0x7f) == 18 || \
+ ((r) & 0x7f) == 24 || ((r) & 0x7f) == 36 || \
+ ((r) & 0x7f) == 48 || ((r) & 0x7f) == 72 || \
+ ((r) & 0x7f) == 96 || ((r) & 0x7f) == 108)
+
+/* WDS link local endpoint WPA role */
+#define WL_WDS_WPA_ROLE_AUTH 0 /* authenticator */
+#define WL_WDS_WPA_ROLE_SUP 1 /* supplicant */
+#define WL_WDS_WPA_ROLE_AUTO 255 /* auto, based on mac addr value */
+
+/* afterburner_override */
+#define ABO_AUTO -1 /* auto - no override */
+#define ABO_OFF 0 /* force afterburner off */
+#define ABO_ON 1 /* force afterburner on */
+
+#define GMODE_AFTERBURNER 6
+
+#undef PACKED
+
+#endif /* _wlioctl_h_ */
diff --git a/package/wlcompat/src/include/wlutils.h b/package/wlcompat/src/include/wlutils.h
new file mode 100644
index 0000000000..07e2536ca3
--- /dev/null
+++ b/package/wlcompat/src/include/wlutils.h
@@ -0,0 +1,59 @@
+/*
+ * Broadcom wireless network adapter utility functions
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#ifndef _wlutils_h_
+#define _wlutils_h_
+
+#include <typedefs.h>
+#include <wlioctl.h>
+
+/*
+ * Pass a wlioctl request to the specified interface.
+ * @param name interface name
+ * @param cmd WLC_GET_MAGIC <= cmd < WLC_LAST
+ * @param buf buffer for passing in and/or receiving data
+ * @param len length of buf
+ * @return >= 0 if successful or < 0 otherwise
+ */
+extern int wl_ioctl(char *name, int cmd, void *buf, int len);
+
+/*
+ * Get the MAC (hardware) address of the specified interface.
+ * @param name interface name
+ * @param hwaddr 6-byte buffer for receiving address
+ * @return >= 0 if successful or < 0 otherwise
+ */
+extern int wl_hwaddr(char *name, unsigned char *hwaddr);
+
+/*
+ * Probe the specified interface.
+ * @param name interface name
+ * @return >= 0 if a Broadcom wireless device or < 0 otherwise
+ */
+extern int wl_probe(char *name);
+
+/*
+ * Set/Get named variable.
+ * @param name interface name
+ * @param var variable name
+ * @param val variable value/buffer
+ * @param len variable value/buffer length
+ * @return success == 0, failure != 0
+ */
+extern int wl_set_val(char *name, char *var, void *val, int len);
+extern int wl_get_val(char *name, char *var, void *val, int len);
+extern int wl_set_int(char *name, char *var, int val);
+extern int wl_get_int(char *name, char *var, int *val);
+
+#endif /* _wlutils_h_ */
diff --git a/package/wlcompat/src/wlcompat.c b/package/wlcompat/src/wlcompat.c
new file mode 100644
index 0000000000..23b0d50a81
--- /dev/null
+++ b/package/wlcompat/src/wlcompat.c
@@ -0,0 +1,1056 @@
+/*
+ * wlcompat.c
+ *
+ * Copyright (C) 2005 Mike Baker,
+ * 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.
+ *
+ * $Id$
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/if_arp.h>
+#include <asm/uaccess.h>
+#include <linux/wireless.h>
+#include <linux/timer.h>
+
+#include <net/iw_handler.h>
+#include <wlioctl.h>
+
+static struct net_device *dev;
+static unsigned short bss_force;
+static struct iw_statistics wstats;
+static int random = 1;
+char buf[WLC_IOCTL_MAXLEN];
+
+/* The frequency of each channel in MHz */
+const long channel_frequency[] = {
+ 2412, 2417, 2422, 2427, 2432, 2437, 2442,
+ 2447, 2452, 2457, 2462, 2467, 2472, 2484
+};
+#define NUM_CHANNELS ( sizeof(channel_frequency) / sizeof(channel_frequency[0]) )
+
+#define RNG_POLL_FREQ 20
+
+typedef struct internal_wsec_key {
+ uint8 index; // 0x00
+ uint8 unknown_1; // 0x01
+ uint8 type; // 0x02
+ uint8 unknown_2[7]; // 0x03
+ uint8 len; // 0x0a
+ uint8 pad[3];
+ char data[32]; // 0x0e
+} wkey;
+
+
+static int wlcompat_private_ioctl(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra);
+#ifdef DEBUG
+void print_buffer(int len, unsigned char *buf);
+#endif
+
+static int wl_ioctl(struct net_device *dev, int cmd, void *buf, int len)
+{
+ mm_segment_t old_fs = get_fs();
+ struct ifreq ifr;
+ int ret;
+ wl_ioctl_t ioc;
+ ioc.cmd = cmd;
+ ioc.buf = buf;
+ ioc.len = len;
+ strncpy(ifr.ifr_name, dev->name, IFNAMSIZ);
+ ifr.ifr_data = (caddr_t) &ioc;
+ set_fs(KERNEL_DS);
+ ret = dev->do_ioctl(dev,&ifr,SIOCDEVPRIVATE);
+ set_fs (old_fs);
+ return ret;
+}
+
+static int wl_set_val(struct net_device *dev, char *var, void *val, int len)
+{
+ char buf[128];
+ int buf_len;
+ int ret;
+
+ /* check for overflow */
+ if ((buf_len = strlen(var)) + 1 + len > sizeof(buf))
+ return -1;
+
+ strcpy(buf, var);
+ buf_len += 1;
+
+ /* append int value onto the end of the name string */
+ memcpy(&(buf[buf_len]), val, len);
+ buf_len += len;
+
+ ret = wl_ioctl(dev, WLC_SET_VAR, buf, buf_len);
+ return ret;
+}
+
+static int wl_get_val(struct net_device *dev, char *var, void *val, int len)
+{
+ char buf[128];
+ int buf_len;
+ int ret;
+
+ /* check for overflow */
+ if ((buf_len = strlen(var)) + 1 > sizeof(buf) || len > sizeof(buf))
+ return -1;
+
+ strcpy(buf, var);
+ if (ret = wl_ioctl(dev, WLC_GET_VAR, buf, buf_len + len))
+ return ret;
+
+ memcpy(val, buf, len);
+ return 0;
+}
+
+int get_primary_key(struct net_device *dev)
+{
+ int key, val;
+
+ for (key = val = 0; (key < 4) && (val == 0); key++) {
+ val = key;
+ if (wl_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val)) < 0)
+ return -EINVAL;
+ }
+ return key;
+}
+
+
+static int wlcompat_ioctl_getiwrange(struct net_device *dev,
+ char *extra)
+{
+ int i, k;
+ struct iw_range *range;
+
+ range = (struct iw_range *) extra;
+ bzero(extra, sizeof(struct iw_range));
+
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = WIRELESS_EXT;
+
+ range->min_nwid = range->max_nwid = 0;
+
+ range->num_channels = NUM_CHANNELS;
+ k = 0;
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ range->freq[k].i = i + 1;
+ range->freq[k].m = channel_frequency[i] * 100000;
+ range->freq[k].e = 1;
+ k++;
+ if (k >= IW_MAX_FREQUENCIES)
+ break;
+ }
+ range->num_frequency = k;
+ range->sensitivity = 3;
+
+ /* nbd: don't know what this means, but other drivers set it this way */
+ range->pmp_flags = IW_POWER_PERIOD;
+ range->pmt_flags = IW_POWER_TIMEOUT;
+ range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;
+
+ range->min_pmp = 0;
+ range->max_pmp = 65535000;
+ range->min_pmt = 0;
+ range->max_pmt = 65535 * 1000;
+
+ range->max_qual.qual = 0;
+ range->max_qual.level = 0;
+ range->max_qual.noise = 0;
+
+ range->min_rts = 0;
+ if (wl_ioctl(dev, WLC_GET_RTS, &range->max_rts, sizeof(int)) < 0)
+ range->max_rts = 2347;
+
+ range->min_frag = 256;
+
+ if (wl_ioctl(dev, WLC_GET_FRAG, &range->max_frag, sizeof(int)) < 0)
+ range->max_frag = 2346;
+
+ range->txpower_capa = IW_TXPOW_DBM;
+
+ return 0;
+}
+
+
+static int wlcompat_set_scan(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ int ap = 0, oldap = 0;
+ wl_scan_params_t params;
+
+ memset(&params, 0, sizeof(params));
+
+ /* use defaults (same parameters as wl scan) */
+ memset(&params.bssid, 0xff, sizeof(params.bssid));
+ params.bss_type = DOT11_BSSTYPE_ANY;
+ params.scan_type = -1;
+ params.nprobes = -1;
+ params.active_time = -1;
+ params.passive_time = -1;
+ params.home_time = -1;
+
+ /* can only scan in STA mode */
+ wl_ioctl(dev, WLC_GET_AP, &oldap, sizeof(oldap));
+ if (oldap > 0)
+ wl_ioctl(dev, WLC_SET_AP, &ap, sizeof(ap));
+
+ if (wl_ioctl(dev, WLC_SCAN, &params, 64) < 0)
+ return -EINVAL;
+
+ if (oldap > 0)
+ wl_ioctl(dev, WLC_SET_AP, &oldap, sizeof(oldap));
+
+ return 0;
+}
+
+
+struct iw_statistics *wlcompat_get_wireless_stats(struct net_device *dev)
+{
+ wl_bss_info_t *bss_info = (wl_bss_info_t *) buf;
+ get_pktcnt_t pkt;
+ unsigned int rssi, noise, ap;
+
+ memset(&wstats, 0, sizeof(wstats));
+ memset(&pkt, 0, sizeof(pkt));
+ memset(buf, 0, sizeof(buf));
+ bss_info->version = 0x2000;
+ wl_ioctl(dev, WLC_GET_BSS_INFO, bss_info, WLC_IOCTL_MAXLEN);
+ wl_ioctl(dev, WLC_GET_PKTCNTS, &pkt, sizeof(pkt));
+
+ rssi = 0;
+ if ((wl_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap)) < 0) || ap) {
+ if (wl_ioctl(dev, WLC_GET_PHY_NOISE, &noise, sizeof(noise)) < 0)
+ noise = 0;
+ } else {
+ // somehow the structure doesn't fit here
+ rssi = buf[82];
+ noise = buf[84];
+ }
+ rssi = (rssi == 0 ? 1 : rssi);
+ wstats.qual.updated = 0x10;
+ if (rssi <= 1)
+ wstats.qual.updated |= 0x20;
+ if (noise <= 1)
+ wstats.qual.updated |= 0x40;
+
+ if ((wstats.qual.updated & 0x60) == 0x60)
+ return NULL;
+
+ wstats.qual.level = rssi;
+ wstats.qual.noise = noise;
+ wstats.discard.misc = pkt.rx_bad_pkt;
+ wstats.discard.retries = pkt.tx_bad_pkt;
+
+ return &wstats;
+}
+
+static int wlcompat_get_scan(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ wl_scan_results_t *results = (wl_scan_results_t *) buf;
+ wl_bss_info_t *bss_info;
+ char *info_ptr;
+ char *current_ev = extra;
+ char *current_val;
+ char *end_buf = extra + IW_SCAN_MAX_DATA;
+ struct iw_event iwe;
+ int i, j;
+ int rssi, noise;
+
+ results->buflen = WLC_IOCTL_MAXLEN - sizeof(wl_scan_results_t);
+
+ if (wl_ioctl(dev, WLC_SCAN_RESULTS, buf, WLC_IOCTL_MAXLEN) < 0)
+ return -EAGAIN;
+
+ bss_info = &(results->bss_info[0]);
+ info_ptr = (char *) bss_info;
+ for (i = 0; i < results->count; i++) {
+
+ /* send the cell address (must be sent first) */
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(&iwe.u.ap_addr.sa_data, &bss_info->BSSID, sizeof(bss_info->BSSID));
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
+
+ /* send the ESSID */
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.length = bss_info->SSID_len;
+ if (iwe.u.data.length > IW_ESSID_MAX_SIZE)
+ iwe.u.data.length = IW_ESSID_MAX_SIZE;
+ iwe.u.data.flags = 1;
+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss_info->SSID);
+
+ /* send frequency/channel info */
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.e = 0;
+ iwe.u.freq.m = bss_info->channel;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
+
+ /* add quality statistics */
+ iwe.cmd = IWEVQUAL;
+ iwe.u.qual.qual = 0;
+ iwe.u.qual.level = bss_info->RSSI;
+ iwe.u.qual.noise = bss_info->phy_noise;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
+
+ /* send rate information */
+ iwe.cmd = SIOCGIWRATE;
+ current_val = current_ev + IW_EV_LCP_LEN;
+ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+
+ for(j = 0 ; j < bss_info->rateset.count ; j++) {
+ iwe.u.bitrate.value = ((bss_info->rateset.rates[j] & 0x7f) * 500000);
+ current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
+ }
+ if((current_val - current_ev) > IW_EV_LCP_LEN)
+ current_ev = current_val;
+
+ info_ptr += sizeof(wl_bss_info_t);
+ if (bss_info->ie_length % 4)
+ info_ptr += bss_info->ie_length + 4 - (bss_info->ie_length % 4);
+ else
+ info_ptr += bss_info->ie_length;
+ bss_info = (wl_bss_info_t *) info_ptr;
+ }
+
+ wrqu->data.length = (current_ev - extra);
+ wrqu->data.flags = 0;
+
+ return 0;
+}
+
+static int wlcompat_ioctl(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ switch (info->cmd) {
+ case SIOCGIWNAME:
+ strcpy(wrqu->name, "IEEE 802.11-DS");
+ break;
+ case SIOCGIWFREQ:
+ {
+ channel_info_t ci;
+
+ if (wl_ioctl(dev,WLC_GET_CHANNEL, &ci, sizeof(ci)) < 0)
+ return -EINVAL;
+
+ wrqu->freq.m = ci.target_channel;
+ wrqu->freq.e = 0;
+ break;
+ }
+ case SIOCSIWFREQ:
+ {
+ if (wrqu->freq.m == -1) {
+ wrqu->freq.m = 0;
+ if (wl_ioctl(dev, WLC_SET_CHANNEL, &wrqu->freq.m, sizeof(int)) < 0)
+ return -EINVAL;
+ } else {
+ if (wrqu->freq.e == 1) {
+ int channel = 0;
+ int f = wrqu->freq.m / 100000;
+ while ((channel < NUM_CHANNELS + 1) && (f != channel_frequency[channel]))
+ channel++;
+
+ if (channel == NUM_CHANNELS) // channel not found
+ return -EINVAL;
+
+ wrqu->freq.e = 0;
+ wrqu->freq.m = channel + 1;
+ }
+ if ((wrqu->freq.e == 0) && (wrqu->freq.m < 1000)) {
+ if (wl_ioctl(dev, WLC_SET_CHANNEL, &wrqu->freq.m, sizeof(int)) < 0)
+ return -EINVAL;
+ } else {
+ return -EINVAL;
+ }
+ }
+ break;
+ }
+ case SIOCSIWAP:
+ {
+ int ap = 0;
+ int infra = 0;
+ rw_reg_t reg;
+
+ memset(&reg, 0, sizeof(reg));
+
+ if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
+ return -EINVAL;
+
+ if (wl_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap)) < 0)
+ return -EINVAL;
+
+ if (wl_ioctl(dev, WLC_GET_INFRA, &infra, sizeof(infra)) < 0)
+ return -EINVAL;
+
+ if (!infra) {
+ wl_ioctl(dev, WLC_SET_BSSID, wrqu->ap_addr.sa_data, 6);
+
+ reg.size = 4;
+ reg.byteoff = 0x184;
+ reg.val = bss_force << 16 | bss_force;
+ wl_ioctl(dev, WLC_W_REG, &reg, sizeof(reg));
+
+ reg.byteoff = 0x180;
+ wl_ioctl(dev, WLC_R_REG, &reg, sizeof(reg));
+ reg.val = bss_force << 16;
+ wl_ioctl(dev, WLC_W_REG, &reg, sizeof(reg));
+ }
+
+ if (wl_ioctl(dev, ((ap || !infra) ? WLC_SET_BSSID : WLC_REASSOC), wrqu->ap_addr.sa_data, 6) < 0)
+ return -EINVAL;
+
+ break;
+ }
+ case SIOCGIWAP:
+ {
+#ifdef DEBUG
+ rw_reg_t reg;
+ memset(&reg, 0, sizeof(reg));
+
+ reg.size = 4;
+ reg.byteoff = 0x184;
+ wl_ioctl(dev, WLC_R_REG, &reg, sizeof(reg));
+ printk("bss time = 0x%08x", reg.val);
+
+ reg.byteoff = 0x180;
+ wl_ioctl(dev, WLC_R_REG, &reg, sizeof(reg));
+ printk("%08x\n", reg.val);
+#endif
+
+ wrqu->ap_addr.sa_family = ARPHRD_ETHER;
+ if (wl_ioctl(dev,WLC_GET_BSSID,wrqu->ap_addr.sa_data,6) < 0)
+ return -EINVAL;
+ break;
+ }
+ case SIOCGIWESSID:
+ {
+ wlc_ssid_t ssid;
+
+ if (wl_ioctl(dev,WLC_GET_SSID, &ssid, sizeof(wlc_ssid_t)) < 0)
+ return -EINVAL;
+
+ wrqu->essid.flags = wrqu->data.flags = 1;
+ wrqu->essid.length = wrqu->data.length = ssid.SSID_len + 1;
+ memcpy(extra,ssid.SSID,ssid.SSID_len + 1);
+ break;
+ }
+ case SIOCSIWESSID:
+ {
+ wlc_ssid_t ssid;
+ memset(&ssid, 0, sizeof(ssid));
+ ssid.SSID_len = strlen(extra);
+ if (ssid.SSID_len > WLC_ESSID_MAX_SIZE)
+ ssid.SSID_len = WLC_ESSID_MAX_SIZE;
+ memcpy(ssid.SSID, extra, ssid.SSID_len);
+ if (wl_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid)) < 0)
+ return -EINVAL;
+ break;
+ }
+ case SIOCGIWRTS:
+ {
+ if (wl_ioctl(dev,WLC_GET_RTS,&(wrqu->rts.value),sizeof(int)) < 0)
+ return -EINVAL;
+ break;
+ }
+ case SIOCSIWRTS:
+ {
+ if (wl_ioctl(dev,WLC_SET_RTS,&(wrqu->rts.value),sizeof(int)) < 0)
+ return -EINVAL;
+ break;
+ }
+ case SIOCGIWFRAG:
+ {
+ if (wl_ioctl(dev,WLC_GET_FRAG,&(wrqu->frag.value),sizeof(int)) < 0)
+ return -EINVAL;
+ break;
+ }
+ case SIOCSIWFRAG:
+ {
+ if (wl_ioctl(dev,WLC_SET_FRAG,&(wrqu->frag.value),sizeof(int)) < 0)
+ return -EINVAL;
+ break;
+ }
+ case SIOCGIWTXPOW:
+ {
+ int radio, override;
+
+ wl_ioctl(dev, WLC_GET_RADIO, &radio, sizeof(int));
+
+ if (wl_get_val(dev, "qtxpower", &(wrqu->txpower.value), sizeof(int)) < 0)
+ return -EINVAL;
+
+ override = (wrqu->txpower.value & WL_TXPWR_OVERRIDE) == WL_TXPWR_OVERRIDE;
+ wrqu->txpower.value &= ~WL_TXPWR_OVERRIDE;
+ if (!override && (wrqu->txpower.value > 76))
+ wrqu->txpower.value = 76;
+ wrqu->txpower.value /= 4;
+
+ wrqu->txpower.fixed = 0;
+ wrqu->txpower.disabled = radio;
+ wrqu->txpower.flags = IW_TXPOW_DBM;
+ break;
+ }
+ case SIOCSIWTXPOW:
+ {
+ /* This is weird: WLC_SET_RADIO with 1 as argument disables the radio */
+ int radio = wrqu->txpower.disabled;
+
+ wl_ioctl(dev, WLC_SET_RADIO, &radio, sizeof(int));
+
+ if (!wrqu->txpower.disabled && (wrqu->txpower.value > 0)) {
+ int value;
+
+ if (wl_get_val(dev, "qtxpower", &value, sizeof(int)) < 0)
+ return -EINVAL;
+
+ value &= WL_TXPWR_OVERRIDE;
+ wrqu->txpower.value *= 4;
+ wrqu->txpower.value |= value;
+
+ if (wrqu->txpower.flags != IW_TXPOW_DBM)
+ return -EINVAL;
+
+ if (wrqu->txpower.value > 0)
+ if (wl_set_val(dev, "qtxpower", &(wrqu->txpower.value), sizeof(int)) < 0)
+ return -EINVAL;
+ }
+ break;
+ }
+ case SIOCSIWENCODE:
+ {
+ int val = 0, wep = 1, wrestrict = 1;
+ int index = (wrqu->data.flags & IW_ENCODE_INDEX) - 1;
+
+ if (index < 0)
+ index = get_primary_key(dev);
+
+ if (wrqu->data.flags & IW_ENCODE_DISABLED) {
+ wep = 0;
+ if (wl_ioctl(dev, WLC_SET_WSEC, &wep, sizeof(val)) < 0)
+ return -EINVAL;
+ return 0;
+ }
+
+ if (wl_ioctl(dev, WLC_SET_WSEC, &wep, sizeof(val)) < 0)
+ return -EINVAL;
+
+ if (wrqu->data.flags & IW_ENCODE_OPEN)
+ wrestrict = 0;
+
+ if (wrqu->data.pointer && (wrqu->data.length > 0) && (wrqu->data.length <= 16)) {
+ wl_wsec_key_t key;
+ memset(&key, 0, sizeof(key));
+
+ key.flags = WL_PRIMARY_KEY;
+ key.len = wrqu->data.length;
+ key.index = index;
+ memcpy(key.data, wrqu->data.pointer, wrqu->data.length);
+
+ if (wl_ioctl(dev, WLC_SET_KEY, &key, sizeof(key)) < 0)
+ return -EINVAL;
+ }
+
+ if (index >= 0)
+ wl_ioctl(dev, WLC_SET_KEY_PRIMARY, &index, sizeof(index));
+
+ if (wrestrict >= 0)
+ wl_ioctl(dev, WLC_SET_WEP_RESTRICT, &wrestrict, sizeof(wrestrict));
+
+ break;
+ }
+ case SIOCGIWENCODE:
+ {
+ int val;
+
+ if (wl_ioctl(dev, WLC_GET_WEP, &val, sizeof(val)) < 0)
+ return -EINVAL;
+
+
+ if (val > 0) {
+ int key = get_primary_key(dev);
+
+ wrqu->data.flags = IW_ENCODE_ENABLED;
+ if (key-- > 0) {
+ int *info_addr;
+ wkey *wep_key;
+
+ info_addr = (int *) dev->priv;
+ wep_key = (wkey *) ((*info_addr) + 0x2752 + (key * 0x110));
+
+ wrqu->data.flags |= key + 1;
+ wrqu->data.length = wep_key->len;
+
+ memset(extra, 0, 16);
+ memcpy(extra, wep_key->data, 16);
+ } else {
+ wrqu->data.flags |= IW_ENCODE_NOKEY;
+ }
+ } else {
+ wrqu->data.flags = IW_ENCODE_DISABLED;
+ }
+
+ break;
+ }
+ case SIOCGIWRANGE:
+ {
+ return wlcompat_ioctl_getiwrange(dev, extra);
+ break;
+ }
+ case SIOCSIWMODE:
+ {
+ int ap = -1, infra = -1, passive = 0, wet = 0;
+
+ switch (wrqu->mode) {
+ case IW_MODE_MONITOR:
+ passive = 1;
+ break;
+ case IW_MODE_ADHOC:
+ infra = 0;
+ ap = 0;
+ break;
+ case IW_MODE_MASTER:
+ infra = 1;
+ ap = 1;
+ break;
+ case IW_MODE_INFRA:
+ infra = 1;
+ ap = 0;
+ break;
+ case IW_MODE_REPEAT:
+ infra = 1;
+ ap = 0;
+ wet = 1;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ wl_ioctl(dev, WLC_SET_PASSIVE, &passive, sizeof(passive));
+ wl_ioctl(dev, WLC_SET_MONITOR, &passive, sizeof(passive));
+ wl_ioctl(dev, WLC_SET_WET, &wet, sizeof(wet));
+ if (ap >= 0)
+ wl_ioctl(dev, WLC_SET_AP, &ap, sizeof(ap));
+ if (infra >= 0)
+ wl_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra));
+
+ break;
+
+ }
+ case SIOCGIWMODE:
+ {
+ int ap, infra, wet, passive;
+
+ if (wl_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap)) < 0)
+ return -EINVAL;
+ if (wl_ioctl(dev, WLC_GET_INFRA, &infra, sizeof(infra)) < 0)
+ return -EINVAL;
+ if (wl_ioctl(dev, WLC_GET_PASSIVE, &passive, sizeof(passive)) < 0)
+ return -EINVAL;
+ if (wl_ioctl(dev, WLC_GET_WET, &wet, sizeof(wet)) < 0)
+ return -EINVAL;
+
+ if (passive) {
+ wrqu->mode = IW_MODE_MONITOR;
+ } else if (!infra) {
+ wrqu->mode = IW_MODE_ADHOC;
+ } else {
+ if (ap) {
+ wrqu->mode = IW_MODE_MASTER;
+ } else {
+ if (wet) {
+ wrqu->mode = IW_MODE_REPEAT;
+ } else {
+ wrqu->mode = IW_MODE_INFRA;
+ }
+ }
+ }
+ break;
+ }
+ default:
+ {
+ if (info->cmd >= SIOCIWFIRSTPRIV)
+ return wlcompat_private_ioctl(dev, info, wrqu, extra);
+
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static const iw_handler wlcompat_handler[] = {
+ NULL, /* SIOCSIWCOMMIT */
+ wlcompat_ioctl, /* SIOCGIWNAME */
+ NULL, /* SIOCSIWNWID */
+ NULL, /* SIOCGIWNWID */
+ wlcompat_ioctl, /* SIOCSIWFREQ */
+ wlcompat_ioctl, /* SIOCGIWFREQ */
+ wlcompat_ioctl, /* SIOCSIWMODE */
+ wlcompat_ioctl, /* SIOCGIWMODE */
+ NULL, /* SIOCSIWSENS */
+ NULL, /* SIOCGIWSENS */
+ NULL, /* SIOCSIWRANGE, unused */
+ wlcompat_ioctl, /* SIOCGIWRANGE */
+ NULL, /* SIOCSIWPRIV */
+ NULL, /* SIOCGIWPRIV */
+ NULL, /* SIOCSIWSTATS */
+ NULL, /* SIOCGIWSTATS */
+ iw_handler_set_spy, /* SIOCSIWSPY */
+ iw_handler_get_spy, /* SIOCGIWSPY */
+ iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
+ iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
+ wlcompat_ioctl, /* SIOCSIWAP */
+ wlcompat_ioctl, /* SIOCGIWAP */
+ NULL, /* -- hole -- */
+ NULL, /* SIOCGIWAPLIST */
+ wlcompat_set_scan, /* SIOCSIWSCAN */
+ wlcompat_get_scan, /* SIOCGIWSCAN */
+ wlcompat_ioctl, /* SIOCSIWESSID */
+ wlcompat_ioctl, /* SIOCGIWESSID */
+ NULL, /* SIOCSIWNICKN */
+ NULL, /* SIOCGIWNICKN */
+ NULL, /* -- hole -- */
+ NULL, /* -- hole -- */
+ NULL, /* SIOCSIWRATE */
+ NULL, /* SIOCGIWRATE */
+ wlcompat_ioctl, /* SIOCSIWRTS */
+ wlcompat_ioctl, /* SIOCGIWRTS */
+ wlcompat_ioctl, /* SIOCSIWFRAG */
+ wlcompat_ioctl, /* SIOCGIWFRAG */
+ wlcompat_ioctl, /* SIOCSIWTXPOW */
+ wlcompat_ioctl, /* SIOCGIWTXPOW */
+ NULL, /* SIOCSIWRETRY */
+ NULL, /* SIOCGIWRETRY */
+ wlcompat_ioctl, /* SIOCSIWENCODE */
+ wlcompat_ioctl, /* SIOCGIWENCODE */
+};
+
+
+#define WLCOMPAT_SET_MONITOR SIOCIWFIRSTPRIV + 0
+#define WLCOMPAT_GET_MONITOR SIOCIWFIRSTPRIV + 1
+#define WLCOMPAT_SET_TXPWR_LIMIT SIOCIWFIRSTPRIV + 2
+#define WLCOMPAT_GET_TXPWR_LIMIT SIOCIWFIRSTPRIV + 3
+#define WLCOMPAT_SET_ANTDIV SIOCIWFIRSTPRIV + 4
+#define WLCOMPAT_GET_ANTDIV SIOCIWFIRSTPRIV + 5
+#define WLCOMPAT_SET_TXANT SIOCIWFIRSTPRIV + 6
+#define WLCOMPAT_GET_TXANT SIOCIWFIRSTPRIV + 7
+#define WLCOMPAT_SET_BSS_FORCE SIOCIWFIRSTPRIV + 8
+#define WLCOMPAT_GET_BSS_FORCE SIOCIWFIRSTPRIV + 9
+
+
+static int wlcompat_private_ioctl(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ int *value = (int *) wrqu->name;
+
+ switch (info->cmd) {
+ case WLCOMPAT_SET_MONITOR:
+ {
+ if (wl_ioctl(dev, WLC_SET_MONITOR, value, sizeof(int)) < 0)
+ return -EINVAL;
+
+ break;
+ }
+ case WLCOMPAT_GET_MONITOR:
+ {
+ if (wl_ioctl(dev, WLC_GET_MONITOR, extra, sizeof(int)) < 0)
+ return -EINVAL;
+
+ break;
+ }
+ case WLCOMPAT_SET_TXPWR_LIMIT:
+ {
+ int val;
+
+
+ if (wl_get_val(dev, "qtxpower", &val, sizeof(int)) < 0)
+ return -EINVAL;
+
+ if (*extra > 0)
+ val |= WL_TXPWR_OVERRIDE;
+ else
+ val &= ~WL_TXPWR_OVERRIDE;
+
+ if (wl_set_val(dev, "qtxpower", &val, sizeof(int)) < 0)
+ return -EINVAL;
+
+ break;
+ }
+ case WLCOMPAT_GET_TXPWR_LIMIT:
+ {
+ if (wl_get_val(dev, "qtxpower", value, sizeof(int)) < 0)
+ return -EINVAL;
+
+ *value = ((*value & WL_TXPWR_OVERRIDE) == WL_TXPWR_OVERRIDE ? 1 : 0);
+
+ break;
+ }
+ case WLCOMPAT_SET_ANTDIV:
+ {
+ if (wl_ioctl(dev, WLC_SET_ANTDIV, value, sizeof(int)) < 0)
+ return -EINVAL;
+
+ break;
+ }
+ case WLCOMPAT_GET_ANTDIV:
+ {
+ if (wl_ioctl(dev, WLC_GET_ANTDIV, extra, sizeof(int)) < 0)
+ return -EINVAL;
+
+ break;
+ }
+ case WLCOMPAT_SET_TXANT:
+ {
+ if (wl_ioctl(dev, WLC_SET_TXANT, value, sizeof(int)) < 0)
+ return -EINVAL;
+
+ break;
+ }
+ case WLCOMPAT_GET_TXANT:
+ {
+ if (wl_ioctl(dev, WLC_GET_TXANT, extra, sizeof(int)) < 0)
+ return -EINVAL;
+
+ break;
+ }
+ case WLCOMPAT_SET_BSS_FORCE:
+ {
+ bss_force = (unsigned short) *value;
+ break;
+ }
+ case WLCOMPAT_GET_BSS_FORCE:
+ {
+ *extra = (int) bss_force;
+ break;
+ }
+ default:
+ {
+ return -EINVAL;
+ }
+
+ }
+ return 0;
+}
+
+static const struct iw_priv_args wlcompat_private_args[] =
+{
+ { WLCOMPAT_SET_MONITOR,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_monitor"
+ },
+ { WLCOMPAT_GET_MONITOR,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "get_monitor"
+ },
+ { WLCOMPAT_SET_TXPWR_LIMIT,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_txpwr_force"
+ },
+ { WLCOMPAT_GET_TXPWR_LIMIT,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "get_txpwr_force"
+ },
+ { WLCOMPAT_SET_ANTDIV,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_antdiv"
+ },
+ { WLCOMPAT_GET_ANTDIV,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "get_antdiv"
+ },
+ { WLCOMPAT_SET_TXANT,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_txant"
+ },
+ { WLCOMPAT_GET_TXANT,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "get_txant"
+ },
+ { WLCOMPAT_SET_BSS_FORCE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_bss_force"
+ },
+ { WLCOMPAT_GET_BSS_FORCE,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "get_bss_force"
+ },
+};
+
+static const iw_handler wlcompat_private[] =
+{
+ wlcompat_private_ioctl,
+ NULL
+};
+
+
+static const struct iw_handler_def wlcompat_handler_def =
+{
+ .standard = (iw_handler *) wlcompat_handler,
+ .num_standard = sizeof(wlcompat_handler)/sizeof(iw_handler),
+ .private = wlcompat_private,
+ .num_private = 1,
+ .private_args = wlcompat_private_args,
+ .num_private_args = sizeof(wlcompat_private_args) / sizeof(wlcompat_private_args[0])
+};
+
+
+#ifdef DEBUG
+void print_buffer(int len, unsigned char *buf) {
+ int x;
+ if (buf != NULL) {
+ for (x=0;x<len && x<180 ;x++) {
+ if ((x % 4) == 0)
+ printk(" ");
+ printk("%02X",buf[x]);
+ }
+ } else {
+ printk(" NULL");
+ }
+ printk("\n");
+
+}
+#endif
+static int (*old_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd);
+static int new_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) {
+ int ret = 0;
+ struct iwreq *iwr = (struct iwreq *) ifr;
+ struct iw_request_info info;
+
+#ifdef DEBUG
+ printk("dev: %s ioctl: 0x%04x\n",dev->name,cmd);
+#endif
+
+ if (cmd >= SIOCIWFIRSTPRIV) {
+ info.cmd = cmd;
+ info.flags = 0;
+ ret = wlcompat_private_ioctl(dev, &info, &(iwr->u), (char *) &(iwr->u));
+#ifdef DEBUG
+ } else if (cmd==SIOCDEVPRIVATE) {
+ wl_ioctl_t *ioc = (wl_ioctl_t *)ifr->ifr_data;
+ unsigned char *buf = ioc->buf;
+ printk(" cmd: %d buf: 0x%08x len: %d\n",ioc->cmd,&(ioc->buf),ioc->len);
+ printk(" send: ->");
+ print_buffer(ioc->len, buf);
+ ret = old_ioctl(dev,ifr,cmd);
+ printk(" recv: ->");
+ print_buffer(ioc->len, buf);
+ printk(" ret: %d\n", ret);
+#endif
+ } else {
+ ret = old_ioctl(dev,ifr,cmd);
+ }
+ return ret;
+}
+
+static struct timer_list rng_timer;
+
+static void rng_timer_tick(unsigned long n)
+{
+ struct net_device *dev = (struct net_device *) n;
+ u16 data[4];
+ int i, ret;
+
+ ret = 0;
+ for (i = 0; i < 3; i++) {
+ ret |= wl_get_val(dev, "rand", &data[i], sizeof(u16));
+ }
+ if (!ret)
+ batch_entropy_store(*((u32 *) &data[0]), *((u32 *) &data[2]), (jiffies % 255));
+
+ mod_timer(&rng_timer, jiffies + (HZ/RNG_POLL_FREQ));
+}
+
+
+static int __init wlcompat_init()
+{
+ int found = 0, i;
+ char devname[4] = "wl0";
+ bss_force = 0;
+
+ while (!found && (dev = dev_get_by_name(devname))) {
+ if ((dev->wireless_handlers == NULL) && ((wl_ioctl(dev, WLC_GET_MAGIC, &i, sizeof(i)) == 0) && i == WLC_IOCTL_MAGIC))
+ found = 1;
+ devname[2]++;
+ }
+
+ if (!found) {
+ printk("No Broadcom devices found.\n");
+ return -ENODEV;
+ }
+
+
+ old_ioctl = dev->do_ioctl;
+ dev->do_ioctl = new_ioctl;
+ dev->wireless_handlers = (struct iw_handler_def *)&wlcompat_handler_def;
+ dev->get_wireless_stats = wlcompat_get_wireless_stats;
+
+ if (random) {
+ init_timer(&rng_timer);
+ rng_timer.function = rng_timer_tick;
+ rng_timer.data = (unsigned long) dev;
+ rng_timer_tick((unsigned long) dev);
+ }
+
+#ifdef DEBUG
+ printk("broadcom driver private data: 0x%08x\n", dev->priv);
+#endif
+ return 0;
+}
+
+static void __exit wlcompat_exit()
+{
+ if (random)
+ del_timer(&rng_timer);
+ dev->get_wireless_stats = NULL;
+ dev->wireless_handlers = NULL;
+ dev->do_ioctl = old_ioctl;
+ return;
+}
+
+EXPORT_NO_SYMBOLS;
+MODULE_AUTHOR("openwrt.org");
+MODULE_LICENSE("GPL");
+
+module_param(random, int, 0);
+module_init(wlcompat_init);
+module_exit(wlcompat_exit);
diff --git a/package/yamonenv/Makefile b/package/yamonenv/Makefile
new file mode 100644
index 0000000000..dfb9bbb59a
--- /dev/null
+++ b/package/yamonenv/Makefile
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 4091 2006-06-27 00:35:46Z mbm $
+
+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://meshcube.org/nylon/stable/sources/
+PKG_MD5SUM:=a3e4f24155aa3ba5aa502bc63fdaa6ad
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/yamonenv
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=@LINUX_2_6_AU1000@
+ TITLE:=YAMON configuration utility
+ URL:=http://meshcube.org/nylon/stable/sources/
+endef
+
+define Build/Configure
+endef
+
+define Package/yamonenv/install
+ install -d -m0755 $(1)/usr/sbin
+ $(CP) $(PKG_BUILD_DIR)/src/$(PKG_NAME) $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,yamonenv))
diff --git a/package/zd1211/Makefile b/package/zd1211/Makefile
new file mode 100644
index 0000000000..e5d2c2724f
--- /dev/null
+++ b/package/zd1211/Makefile
@@ -0,0 +1,63 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 3297 2006-03-02 23:42:52Z florian $
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=zd1211
+PKG_VERSION:=r69
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-driver-$(PKG_VERSION).tgz
+PKG_SOURCE_URL:=http://zd1211.ath.cx/download/
+PKG_MD5SUM:=c14133a3d5b27927402a492e84d2467a
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-driver-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+#FIXME: add proper dependency handling on kmod-usb-core packages
+define Package/kmod-zd1211
+ SECTION:=kernel
+ CATEGORY:=Kernel drivers
+ DEPENDS:=@LINUX_2_6&&!LINUX_2_6_UML
+ TITLE:=Driver for Zydas 1211 based USB devices
+ DESCRIPTION:=\
+ This package contains a Linux driver for the ZyDAS ZD1211 802.11b/g \\\
+ USB-WLAN-Chip.\\\
+ Initially contributed by ZyDAS, this driver is actively maintained by the \\\
+ open source community.
+ URL:=http://zd1211.ath.cx/
+ VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE)
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ CC="$(TARGET_CC)" \
+ CPP="$(TARGET_CC)" \
+ LD="$(TARGET_CROSS)ld" \
+ KERNELVERSION="$(KERNEL)" \
+ KERNEL_SOURCE="$(LINUX_DIR)" \
+ KDIR="$(LINUX_DIR)" \
+ all
+ $(TARGET_CC) $(PKG_BUILD_DIR)/apdbg.c -o $(PKG_BUILD_DIR)/apdbg
+endef
+
+define Package/kmod-zd1211/install
+ install -d -m0755 $(1)/lib/modules/$(LINUX_VERSION)
+ $(CP) $(PKG_BUILD_DIR)/zd1211.$(LINUX_KMOD_SUFFIX) \
+ $(1)/lib/modules/$(LINUX_VERSION)/
+ install -d -m0755 $(1)/usr/sbin
+ $(CP) $(PKG_BUILD_DIR)/apdbg $(1)/usr/sbin/
+ $(CP) $(PKG_BUILD_DIR)/sta $(1)/usr/sbin/$(PKG_NAME)-sta
+endef
+
+$(eval $(call BuildPackage,kmod-zd1211))
diff --git a/package/zlib/Makefile b/package/zlib/Makefile
new file mode 100644
index 0000000000..df4a4753ff
--- /dev/null
+++ b/package/zlib/Makefile
@@ -0,0 +1,73 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=zlib
+PKG_VERSION:=1.2.3
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://www.zlib.net @SF/zlib
+PKG_MD5SUM:=dee233bf288ee795ac96a98cc2e369b6
+PKG_CAT:=bzcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+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) $(CFLAGS_LARGEFILE)" \
+ ./configure \
+ --prefix=/usr \
+ --shared \
+ );
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS) $(CFLAGS_LARGEFILE)" \
+ libz.a libz.so
+ mkdir -p $(PKG_INSTALL_DIR)
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ install
+endef
+
+define Build/InstallDev
+ mkdir -p $(STAGING_DIR)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/z{conf,lib}.h \
+ $(STAGING_DIR)/usr/include/
+ mkdir -p $(STAGING_DIR)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libz.{a,so*} \
+ $(STAGING_DIR)/usr/lib/
+endef
+
+define Build/UninstallDev
+ rm -rf $(STAGING_DIR)/usr/include/z{conf,lib}.h \
+ $(STAGING_DIR)/usr/lib/libz.{a,so*}
+endef
+
+define Package/zlib/install
+ install -d -m0755 $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libz.so.* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,zlib))
diff --git a/package/zlib/patches/zlib.patch b/package/zlib/patches/zlib.patch
new file mode 100644
index 0000000000..1325462ba5
--- /dev/null
+++ b/package/zlib/patches/zlib.patch
@@ -0,0 +1,206 @@
+diff -ruN zlib-1.2.3-orig/Makefile.in zlib-1.2.3-2/Makefile.in
+--- zlib-1.2.3-orig/Makefile.in 2004-09-15 16:27:20.000000000 +0200
++++ zlib-1.2.3-2/Makefile.in 2004-11-13 13:38:12.000000000 +0100
+@@ -25,20 +25,23 @@
+ # -Wstrict-prototypes -Wmissing-prototypes
+
+ LDFLAGS=libz.a
+-LDSHARED=$(CC)
++LDSHARED=$(CC) -shared -Wl,-soname,$(SHAREDLIBM)
+ CPP=$(CC) -E
+
+-LIBS=libz.a
++LIBS=
++STATICLIB=libz.a
+ SHAREDLIB=libz.so
+ SHAREDLIBV=libz.so.1.2.3
+ SHAREDLIBM=libz.so.1
+
+-AR=ar rc
++AR=ar
+ RANLIB=ranlib
+ TAR=tar
+ SHELL=/bin/sh
+ EXE=
+
++DESTDIR =
++
+ prefix = /usr/local
+ exec_prefix = ${prefix}
+ libdir = ${exec_prefix}/lib
+@@ -67,8 +70,8 @@
+ echo ' *** zlib test FAILED ***'; \
+ fi
+
+-libz.a: $(OBJS) $(OBJA)
+- $(AR) $@ $(OBJS) $(OBJA)
++$(STATICLIB): $(OBJS) $(OBJA)
++ $(AR) rc $@ $(OBJS) $(OBJA)
+ -@ ($(RANLIB) $@ || true) >/dev/null 2>&1
+
+ match.o: match.S
+@@ -77,8 +80,10 @@
+ mv _match.o match.o
+ rm -f _match.s
+
++$(SHAREDLIB): $(SHAREDLIBV)
++
+ $(SHAREDLIBV): $(OBJS)
+- $(LDSHARED) -o $@ $(OBJS)
++ $(LDSHARED) -lc -o $@ $(OBJS)
+ rm -f $(SHAREDLIB) $(SHAREDLIBM)
+ ln -s $@ $(SHAREDLIB)
+ ln -s $@ $(SHAREDLIBM)
+@@ -90,23 +95,23 @@
+ $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
+
+ install: $(LIBS)
+- -@if [ ! -d $(exec_prefix) ]; then mkdir -p $(exec_prefix); fi
+- -@if [ ! -d $(includedir) ]; then mkdir -p $(includedir); fi
+- -@if [ ! -d $(libdir) ]; then mkdir -p $(libdir); fi
+- -@if [ ! -d $(man3dir) ]; then mkdir -p $(man3dir); fi
+- cp zlib.h zconf.h $(includedir)
+- chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h
+- cp $(LIBS) $(libdir)
+- cd $(libdir); chmod 755 $(LIBS)
+- -@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1
+- cd $(libdir); if test -f $(SHAREDLIBV); then \
++ -@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi
++ -@if [ ! -d $(DESTDIR)$(includedir) ]; then mkdir -p $(DESTDIR)$(includedir); fi
++ -@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi
++ -@if [ ! -d $(DESTDIR)$(man3dir) ]; then mkdir -p $(DESTDIR)$(man3dir); fi
++ cp zlib.h zconf.h $(DESTDIR)$(includedir)
++ chmod 644 $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h
++ cp $(STATICLIB) $(SHAREDLIBV) $(DESTDIR)$(libdir)
++ cd $(DESTDIR)$(libdir); chmod 755 $(LIBS)
++ -@(cd $(DESTDIR)$(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1
++ cd $(DESTDIR)$(libdir); if test -f $(SHAREDLIBV); then \
+ rm -f $(SHAREDLIB) $(SHAREDLIBM); \
+ ln -s $(SHAREDLIBV) $(SHAREDLIB); \
+ ln -s $(SHAREDLIBV) $(SHAREDLIBM); \
+ (ldconfig || true) >/dev/null 2>&1; \
+ fi
+- cp zlib.3 $(man3dir)
+- chmod 644 $(man3dir)/zlib.3
++ cp zlib.3 $(DESTDIR)$(man3dir)
++ chmod 644 $(DESTDIR)$(man3dir)/zlib.3
+ # The ranlib in install is needed on NeXTSTEP which checks file times
+ # ldconfig is for Linux
+
+diff -ruN zlib-1.2.3-orig/configure zlib-1.2.3-2/configure
+--- zlib-1.2.3-orig/configure 2004-09-07 07:50:06.000000000 +0200
++++ zlib-1.2.3-2/configure 2004-11-13 12:37:43.000000000 +0100
+@@ -23,7 +23,7 @@
+ VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`
+ VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < zlib.h`
+ VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < zlib.h`
+-AR=${AR-"ar rc"}
++AR=${AR-"ar"}
+ RANLIB=${RANLIB-"ranlib"}
+ prefix=${prefix-/usr/local}
+ exec_prefix=${exec_prefix-'${prefix}'}
+@@ -73,7 +73,7 @@
+
+ if test "$gcc" -eq 1 && ($cc -c $cflags $test.c) 2>/dev/null; then
+ CC="$cc"
+- SFLAGS=${CFLAGS-"-fPIC -O3"}
++ SFLAGS=${CFLAGS-"-D_REENTRANT -fPIC -O3"}
+ CFLAGS="$cflags"
+ case `(uname -s || echo unknown) 2>/dev/null` in
+ Linux | linux | GNU | GNU/*) LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1"};;
+@@ -408,6 +408,29 @@
+ echo Checking for mmap support... No.
+ fi
+
++cat > $test.c <<EOF
++#include <stdio.h>
++int main() { char buf[10]; snprintf(buf, sizeof(buf), "%s", "F"); return 0; }
++EOF
++if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
++ echo "Checking for snprintf... Yes."
++ CFLAGS="$CFLAGS -DHAS_snprintf"
++else
++ echo "Checking for snprintf.. No."
++fi
++
++cat > $test.c <<EOF
++#include <stdio.h>
++#include <stdarg.h>
++int main(void) { va_list a; vsnprintf(0, 0, "", a); return 0; }
++EOF
++if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
++ echo "Checking for vsnprintf... Yes."
++ CFLAGS="$CFLAGS -DHAS_vsnprintf"
++else
++ echo "Checking for vsnprintf.. No."
++fi
++
+ CPP=${CPP-"$CC -E"}
+ case $CFLAGS in
+ *ASMV*)
+@@ -424,20 +447,21 @@
+ # udpate Makefile
+ sed < Makefile.in "
+ /^CC *=/s#=.*#=$CC#
+-/^CFLAGS *=/s#=.*#=$CFLAGS#
+-/^CPP *=/s#=.*#=$CPP#
+-/^LDSHARED *=/s#=.*#=$LDSHARED#
+-/^LIBS *=/s#=.*#=$LIBS#
+-/^SHAREDLIB *=/s#=.*#=$SHAREDLIB#
+-/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV#
+-/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM#
+-/^AR *=/s#=.*#=$AR#
+-/^RANLIB *=/s#=.*#=$RANLIB#
+-/^EXE *=/s#=.*#=$EXE#
+-/^prefix *=/s#=.*#=$prefix#
+-/^exec_prefix *=/s#=.*#=$exec_prefix#
+-/^libdir *=/s#=.*#=$libdir#
+-/^includedir *=/s#=.*#=$includedir#
+-/^mandir *=/s#=.*#=$mandir#
+-/^LDFLAGS *=/s#=.*#=$LDFLAGS#
++/^CC *=/s%=.*%= $CC%
++/^CFLAGS *=/s%=.*%= $CFLAGS%
++/^CPP *=/s%=.*%= $CPP%
++/^LDSHARED *=/s%=.*%= $LDSHARED%
++/^LIBS *=/s%=.*%= $LIBS%
++/^SHAREDLIB *=/s%=.*%= $SHAREDLIB%
++/^SHAREDLIBV *=/s%=.*%= $SHAREDLIBV%
++/^SHAREDLIBM *=/s%=.*%= $SHAREDLIBM%
++/^AR *=/s%=.*%= $AR%
++/^RANLIB *=/s%=.*%= $RANLIB%
++/^EXE *=/s%=.*%= $EXE%
++/^prefix *=/s%=.*%= $prefix%
++/^exec_prefix *=/s%=.*%= $exec_prefix%
++/^libdir *=/s%=.*%= $libdir%
++/^includedir *=/s%=.*%= $includedir%
++/^mandir *=/s%=.*%= $mandir%
++/^LDFLAGS *=/s%=.*%= $LDFLAGS%
+ " > Makefile
+diff -ruN zlib-1.2.3-orig/contrib/minizip/Makefile zlib-1.2.3-2/contrib/minizip/Makefile
+--- zlib-1.2.3-orig/contrib/minizip/Makefile 2003-09-10 20:00:16.000000000 +0200
++++ zlib-1.2.3-2/contrib/minizip/Makefile 2004-11-13 12:37:43.000000000 +0100
+@@ -1,8 +1,8 @@
+ CC=cc
+-CFLAGS=-O -I../..
++CFLAGS=-O2 -g -I../.. -Dunix
+
+-UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a
+-ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a
++UNZ_OBJS = miniunz.o unzip.o ioapi.o
++ZIP_OBJS = minizip.o zip.o ioapi.o
+
+ .c.o:
+ $(CC) -c $(CFLAGS) $*.c
+@@ -10,10 +10,10 @@
+ all: miniunz minizip
+
+ miniunz: $(UNZ_OBJS)
+- $(CC) $(CFLAGS) -o $@ $(UNZ_OBJS)
++ $(CC) $(CFLAGS) -o $@ $(UNZ_OBJS) -L ../.. -lz
+
+ minizip: $(ZIP_OBJS)
+- $(CC) $(CFLAGS) -o $@ $(ZIP_OBJS)
++ $(CC) $(CFLAGS) -o $@ $(ZIP_OBJS) -L ../.. -lz
+
+ test: miniunz minizip
+ ./minizip test readme.txt
diff --git a/rules.mk b/rules.mk
new file mode 100644
index 0000000000..be269e77f3
--- /dev/null
+++ b/rules.mk
@@ -0,0 +1,117 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+-include $(TOPDIR)/.config
+include $(TOPDIR)/include/verbose.mk
+
+export SHELL=/usr/bin/env bash -c '. $(TOPDIR)/include/shell.sh; eval "$$2"' --
+export BASH=$(shell which bash)
+
+ARCH:=$(strip $(subst ",, $(CONFIG_ARCH)))
+TARGET_OPTIMIZATION:=$(strip $(subst ",, $(CONFIG_TARGET_OPTIMIZATION)))
+WGET:=$(strip $(subst ",, $(CONFIG_WGET)))
+#"))"))")) # fix vim's broken syntax highlighting
+
+OPTIMIZE_FOR_CPU:=$(ARCH)
+
+# DIRECTORIES #
+
+DL_DIR:=$(TOPDIR)/dl
+INCLUDE_DIR:=$(TOPDIR)/include
+SCRIPT_DIR:=$(TOPDIR)/scripts
+TOOL_BUILD_DIR:=$(TOPDIR)/tool_build
+TOOLCHAIN_BUILD_DIR:=$(TOPDIR)/toolchain_build_$(ARCH)
+STAGING_DIR:=$(TOPDIR)/staging_dir_$(ARCH)
+BIN_DIR:=$(TOPDIR)/bin
+PACKAGE_DIR:=$(BIN_DIR)/packages
+IPKG_TARGET_DIR:=$(PACKAGE_DIR)
+BUILD_DIR:=$(TOPDIR)/build_$(ARCH)
+TMP_DIR:=$(BUILD_DIR)/tmp
+STAMP_DIR:=$(BUILD_DIR)/stamp
+TARGET_DIR:=$(BUILD_DIR)/root
+IPKG_STATE_DIR:=$(TARGET_DIR)/usr/lib/ipkg
+
+ifeq ($(CONFIG_NATIVE_TOOLCHAIN),)
+ REAL_GNU_TARGET_NAME=$(OPTIMIZE_FOR_CPU)-linux-uclibc
+ GNU_TARGET_NAME=$(OPTIMIZE_FOR_CPU)-linux
+ TARGET_CROSS:=$(OPTIMIZE_FOR_CPU)-linux-uclibc-
+endif
+
+IMAGE:=$(BUILD_DIR)/root_fs_$(ARCH)
+
+TARGET_PATH:=$(STAGING_DIR)/usr/bin:$(STAGING_DIR)/bin:$(PATH)
+TARGET_CFLAGS:=$(TARGET_OPTIMIZATION)
+
+export PATH:=$(TARGET_PATH)
+
+LINUX_DIR:=$(BUILD_DIR)/linux
+LINUX_HEADERS_DIR:=$(TOOLCHAIN_BUILD_DIR)/linux
+
+# APPLICATIONS #
+HOSTCC:=gcc
+TARGET_CC:=$(TARGET_CROSS)gcc
+STRIP:=$(STAGING_DIR)/bin/sstrip
+PATCH:=$(SCRIPT_DIR)/patch-kernel.sh
+SED:=$(STAGING_DIR)/bin/sed -i -e
+CP:=cp -fpR
+
+ifneq ($(CONFIG_CCACHE),)
+ # FIXME: move this variable to a better location
+ export CCACHE_DIR=$(STAGING_DIR)/ccache
+ TARGET_CC:= ccache $(TARGET_CC)
+endif
+
+TARGET_CONFIGURE_OPTS:= \
+ AR=$(TARGET_CROSS)ar \
+ AS="$(TARGET_CC) -c $(TARGET_CFLAGS)" \
+ LD=$(TARGET_CROSS)ld \
+ NM=$(TARGET_CROSS)nm \
+ CC="$(TARGET_CC)" \
+ GCC="$(TARGET_CC)" \
+ CXX=$(TARGET_CROSS)g++ \
+ RANLIB=$(TARGET_CROSS)ranlib \
+ STRIP=$(TARGET_CROSS)strip
+
+# strip an entire directory
+RSTRIP:= \
+ STRIP="$(STRIP)" \
+ STRIP_KMOD="$(TARGET_CROSS)strip --strip-unneeded --remove-section=.comment" \
+ $(SCRIPT_DIR)/rstrip.sh
+
+# where to build (and put) .ipk packages
+IPKG:= \
+ PATH="$(STAGING_DIR)/bin:$(PATH)" \
+ IPKG_TMP=$(BUILD_DIR)/tmp \
+ IPKG_INSTROOT=$(TARGET_DIR) \
+ IPKG_CONF_DIR=$(STAGING_DIR)/etc \
+ IPKG_OFFLINE_ROOT=$(BUILD_DIR)/root \
+ $(SCRIPT_DIR)/ipkg -force-defaults -force-depends
+
+# invoke ipkg-build with some default options
+IPKG_BUILD:= \
+ ipkg-build -c -o 0 -g 0
+
+ifeq ($(CONFIG_ENABLE_LOCALE),true)
+ DISABLE_NLS:=
+else
+ DISABLE_NLS:=--disable-nls
+endif
+
+ifneq ($(CONFIG_LARGEFILE),y)
+ DISABLE_LARGEFILE= --disable-largefile
+endif
+
+ifeq ($(CONFIG_TAR_VERBOSITY),y)
+ TAR_OPTIONS=-xvf
+else
+ TAR_OPTIONS=-xf
+endif
+
+all:
+FORCE: ;
+.PHONY: FORCE
+%: ;
diff --git a/scripts/adam2flash.pl b/scripts/adam2flash.pl
new file mode 100755
index 0000000000..bd0fa69a61
--- /dev/null
+++ b/scripts/adam2flash.pl
@@ -0,0 +1,174 @@
+#!/usr/bin/perl
+#
+# D-Link DSL-G6x4T flash utility
+#
+# Copyright (C) 2005 Felix Fietkau <mailto@nbd.name>
+# based on fbox recovery util by Enrik Berkhan
+#
+# 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
+#
+
+use IO::Socket::INET;
+use Socket;
+use strict;
+use warnings;
+
+sub usage() {
+ print STDERR "Usage: $0 <ip> [firmware.bin]\n\n";
+ exit 0;
+}
+
+my $ip = shift @ARGV;
+$ip and $ip =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/ or usage();
+
+my $probe = IO::Socket::INET->new(Proto => 'udp',
+ Broadcast => 1,
+ LocalPort => 5035) or die "socket: $!";
+my $setip = unpack("N", inet_aton($ip));
+$setip > 0 or usage();
+
+my @packets;
+foreach my $ver ([18, 1], [22, 2]) {
+ push @packets, pack("vCCVNV", 0, @$ver, 1, $setip, 0);
+}
+print STDERR "Looking for device: ";
+my $broadcast = sockaddr_in(5035, INADDR_BROADCAST);
+my $scanning;
+my $box;
+
+$SIG{"ALRM"} = sub {
+ return if --$scanning <= 0;
+ foreach my $packet (@packets) {
+ $probe->send($packet, 0, $broadcast);
+ }
+ print STDERR ".";
+};
+
+$scanning = 10;
+foreach my $packet (@packets) {
+ $probe->send($packet, 0, $broadcast);
+}
+print STDERR ".";
+
+while($scanning) {
+ my $reply;
+
+ alarm(1);
+ if (my $peer = $probe->recv($reply, 16)) {
+ next if (length($reply) < 16);
+ my ($port, $addr) = sockaddr_in($peer);
+ my ($major, $minor1, $minor2, $code, $addr2) = unpack("vCCVV", $reply);
+ $addr2 = pack("N", $addr2);
+ if ($code == 2) {
+ $scanning = 0;
+ printf STDERR " found!\nADAM2 version $major.$minor1.$minor2 at %s (%s)\n", inet_ntoa($addr), inet_ntoa($addr2);
+ $box = inet_ntoa($addr);
+ }
+ }
+}
+
+$box or die " not found!\n";
+
+{
+ package ADAM2FTP;
+ use base qw(Net::FTP);
+
+ # ADAM2 requires upper case commands, some brain dead firewall doesn't ;-)
+ sub _USER {
+ shift->command("USER",@_)->response()
+ }
+
+ sub _GETENV {
+ my $ftp = shift;
+ my ($ok, $name, $value);
+
+ $ftp->command("GETENV",@_);
+ while(length($ok = $ftp->response()) < 1) {
+ my $line = $ftp->getline();
+ unless (defined($value)) {
+ chomp($line);
+ ($name, $value) = split(/\s+/, $line, 2);
+ }
+ }
+ $ftp->debug_print(0, "getenv: $value\n")
+ if $ftp->debug();
+ return $value;
+ }
+
+ sub getenv {
+ my $ftp = shift;
+ my $name = shift;
+ return $ftp->_GETENV($name);
+ }
+
+ sub _REBOOT {
+ shift->command("REBOOT")->response() == Net::FTP::CMD_OK
+ }
+
+ sub reboot {
+ my $ftp = shift;
+ $ftp->_REBOOT;
+ $ftp->close;
+ }
+}
+
+my $file = shift @ARGV;
+$file || exit 0;
+
+open FILE, "<$file" or die "can't open firmware file\n";
+my $ftp = ADAM2FTP->new($box, Debug => 0, Timeout => 600) or die "can't open control connection\n";
+$ftp->login("adam2", "adam2") or die "can't login\n";
+
+my $mtd0 = $ftp->getenv("mtd0");
+my $mtd1 = $ftp->getenv("mtd1");
+my ($ksize, $fssize);
+
+$mtd1 =~ /^(0x\w+),(0x\w+)$/ and $ksize = hex($2) - hex($1);
+$mtd0 =~ /^(0x\w+),(0x\w+)$/ and $fssize = hex($2) - hex($1);
+$ksize and $fssize or die 'cannot read partition offsets';
+printf STDERR "Available flash space: 0x%08x (0x%08x + 0x%08x)\n", $ksize + $fssize, $ksize, $fssize;
+
+$ftp->command("MEDIA FLSH")->response();
+$ftp->binary();
+print STDERR "Writing to mtd1...\n";
+
+my $dc = $ftp->stor("fs mtd1");
+$dc or die "can't open data connection\n";
+my $rbytes = 1;
+
+while (($ksize > 0) and ($rbytes > 0)) {
+ my $buffer;
+ my $len = ($ksize > 1024 ? 1024 : $ksize);
+ $rbytes = read FILE, $buffer, $len;
+ $rbytes and $ksize -= $dc->write($buffer, $rbytes, 600);
+}
+
+$dc->close();
+$rbytes or die "no more data left to write\n";
+
+print STDERR "Writing to mtd0...\n";
+
+$dc = $ftp->stor("fs mtd0");
+$dc or die "can't open data connection\n";
+
+while (($fssize > 0) and ($rbytes > 0)) {
+ my $buffer;
+ my $len = ($fssize > 1024 ? 1024 : $fssize);
+ $rbytes = read FILE, $buffer, $len;
+ $rbytes and $fssize -= $dc->write($buffer, $rbytes, 600);
+}
+
+$dc->close();
+$ftp->reboot();
diff --git a/scripts/config.guess b/scripts/config.guess
new file mode 100755
index 0000000000..45bee13987
--- /dev/null
+++ b/scripts/config.guess
@@ -0,0 +1,1465 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-04-22'
+
+# This file 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.
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit 0 ;;
+ amd64:OpenBSD:*:*)
+ echo x86_64-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ cats:OpenBSD:*:*)
+ echo arm-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ luna88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvmeppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mips64-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:MirBSD:*:*)
+ echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit 0 ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit 0;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit 0 ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit 0 ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit 0 ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit 0 ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7 && exit 0 ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit 0 ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit 0 ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c \
+ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && exit 0
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit 0 ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ # avoid double evaluation of $set_cc_for_build
+ test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit 0 ;;
+ x86:Interix*:[34]*)
+ echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+ exit 0 ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit 0 ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit 0 ;;
+ amd64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit 0 ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit 0 ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit 0 ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit 0 ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit 0 ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit 0 ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit 0 ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit 0 ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit 0 ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit 0 ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit 0 ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit 0 ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit 0 ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit 0 ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit 0 ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+ test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit 0 ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit 0 ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit 0 ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit 0 ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit 0 ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit 0 ;;
+ i*86:*:5:[78]*)
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit 0 ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit 0 ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit 0 ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit 0 ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ *86) UNAME_PROCESSOR=i686 ;;
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit 0 ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit 0 ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit 0 ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit 0 ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit 0 ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit 0 ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit 0 ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit 0 ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit 0 ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit 0 ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit 0 ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit 0 ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit 0 ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit 0 ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms && exit 0 ;;
+ I*) echo ia64-dec-vms && exit 0 ;;
+ V*) echo vax-dec-vms && exit 0 ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/scripts/config/Makefile b/scripts/config/Makefile
new file mode 100644
index 0000000000..5ef8b5488b
--- /dev/null
+++ b/scripts/config/Makefile
@@ -0,0 +1,55 @@
+# ===========================================================================
+# OpenWrt configuration targets
+# These targets are used from top-level makefile
+
+# ===========================================================================
+# Shared Makefile for the various kconfig executables:
+# conf: Used for defconfig, oldconfig and related targets
+# mconf: Used for the mconfig target.
+# Utilizes the lxdialog package
+# object files used by all kconfig flavours
+
+
+# Platform specific fixes
+#
+# FreeBSD
+export CFLAGS+=-DKBUILD_NO_NLS
+
+conf-objs := conf.o zconf.tab.o
+mconf-objs := mconf.o zconf.tab.o
+
+clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \
+ .tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c
+
+all: conf mconf lxdialog
+
+.PHONY: lxdialog
+lxdialog:
+ $(MAKE) -C lxdialog
+
+conf: $(conf-objs)
+mconf: $(mconf-objs)
+
+clean:
+ rm -f *.o $(clean-files) conf mconf
+ $(MAKE) -C lxdialog clean
+
+zconf.tab.o: lex.zconf.c zconf.hash.c
+
+kconfig_load.o: lkc_defs.h
+
+lkc_defs.h: $(src)/lkc_proto.h
+ sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/'
+
+zconf.tab.c: zconf.y
+lex.zconf.c: zconf.l
+zconf.hash.c: zconf.gperf
+
+%.tab.c: %.y
+ cp $@_shipped $@ || bison -l -b $* -p $(notdir $*) $<
+
+lex.%.c: %.l
+ cp $@_shipped $@ || flex -L -P$(notdir $*) -o$@ $<
+
+%.hash.c: %.gperf
+ cp $@_shipped $@ || gperf < $< > $@
diff --git a/scripts/config/README b/scripts/config/README
new file mode 100644
index 0000000000..54aaefb598
--- /dev/null
+++ b/scripts/config/README
@@ -0,0 +1,2 @@
+These files were taken from the Linux 2.6.16.7 Kernel
+Configuration System and modified for the OpenWrt Buildroot.
diff --git a/scripts/config/conf.c b/scripts/config/conf.c
new file mode 100644
index 0000000000..cb2093691e
--- /dev/null
+++ b/scripts/config/conf.c
@@ -0,0 +1,626 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/stat.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+static void conf(struct menu *menu);
+static void check_conf(struct menu *menu);
+
+enum {
+ ask_all,
+ ask_new,
+ ask_silent,
+ set_default,
+ set_yes,
+ set_mod,
+ set_no,
+ set_random
+} input_mode = ask_all;
+char *defconfig_file;
+
+static int indent = 1;
+static int valid_stdin = 1;
+static int conf_cnt;
+static char line[128];
+static struct menu *rootEntry;
+
+static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
+
+static void strip(char *str)
+{
+ char *p = str;
+ int l;
+
+ while ((isspace(*p)))
+ p++;
+ l = strlen(p);
+ if (p != str)
+ memmove(str, p, l + 1);
+ if (!l)
+ return;
+ p = str + l - 1;
+ while ((isspace(*p)))
+ *p-- = 0;
+}
+
+static void check_stdin(void)
+{
+ if (!valid_stdin && input_mode == ask_silent) {
+ printf(_("aborted!\n\n"));
+ printf(_("Console input/output is redirected. "));
+ printf(_("Run 'make oldconfig' to update configuration.\n\n"));
+ exit(1);
+ }
+}
+
+static char *fgets_check_stream(char *s, int size, FILE *stream)
+{
+ char *ret = fgets(s, size, stream);
+
+ if (ret == NULL && feof(stream)) {
+ printf(_("aborted!\n\n"));
+ printf(_("Console input is closed. "));
+ printf(_("Run 'make oldconfig' to update configuration.\n\n"));
+ exit(1);
+ }
+
+ return ret;
+}
+
+static void conf_askvalue(struct symbol *sym, const char *def)
+{
+ enum symbol_type type = sym_get_type(sym);
+ tristate val;
+
+ if (!sym_has_value(sym))
+ printf("(NEW) ");
+
+ line[0] = '\n';
+ line[1] = 0;
+
+ if (!sym_is_changable(sym)) {
+ printf("%s\n", def);
+ line[0] = '\n';
+ line[1] = 0;
+ return;
+ }
+
+ switch (input_mode) {
+ case set_no:
+ case set_mod:
+ case set_yes:
+ case set_random:
+ if (sym_has_value(sym)) {
+ printf("%s\n", def);
+ return;
+ }
+ break;
+ case ask_new:
+ case ask_silent:
+ if (sym_has_value(sym)) {
+ printf("%s\n", def);
+ return;
+ }
+ check_stdin();
+ case ask_all:
+ fflush(stdout);
+ fgets_check_stream(line, 128, stdin);
+ return;
+ case set_default:
+ printf("%s\n", def);
+ return;
+ default:
+ break;
+ }
+
+ switch (type) {
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ printf("%s\n", def);
+ return;
+ default:
+ ;
+ }
+ switch (input_mode) {
+ case set_yes:
+ if (sym_tristate_within_range(sym, yes)) {
+ line[0] = 'y';
+ line[1] = '\n';
+ line[2] = 0;
+ break;
+ }
+ case set_mod:
+ if (type == S_TRISTATE) {
+ if (sym_tristate_within_range(sym, mod)) {
+ line[0] = 'm';
+ line[1] = '\n';
+ line[2] = 0;
+ break;
+ }
+ } else {
+ if (sym_tristate_within_range(sym, yes)) {
+ line[0] = 'y';
+ line[1] = '\n';
+ line[2] = 0;
+ break;
+ }
+ }
+ case set_no:
+ if (sym_tristate_within_range(sym, no)) {
+ line[0] = 'n';
+ line[1] = '\n';
+ line[2] = 0;
+ break;
+ }
+ case set_random:
+ do {
+ val = (tristate)(random() % 3);
+ } while (!sym_tristate_within_range(sym, val));
+ switch (val) {
+ case no: line[0] = 'n'; break;
+ case mod: line[0] = 'm'; break;
+ case yes: line[0] = 'y'; break;
+ }
+ line[1] = '\n';
+ line[2] = 0;
+ break;
+ default:
+ break;
+ }
+ printf("%s", line);
+}
+
+int conf_string(struct menu *menu)
+{
+ struct symbol *sym = menu->sym;
+ const char *def, *help;
+
+ while (1) {
+ printf("%*s%s ", indent - 1, "", menu->prompt->text);
+ printf("(%s) ", sym->name);
+ def = sym_get_string_value(sym);
+ if (sym_get_string_value(sym))
+ printf("[%s] ", def);
+ conf_askvalue(sym, def);
+ switch (line[0]) {
+ case '\n':
+ break;
+ case '?':
+ /* print help */
+ if (line[1] == '\n') {
+ help = nohelp_text;
+ if (menu->sym->help)
+ help = menu->sym->help;
+ printf("\n%s\n", menu->sym->help);
+ def = NULL;
+ break;
+ }
+ default:
+ line[strlen(line)-1] = 0;
+ def = line;
+ }
+ if (def && sym_set_string_value(sym, def))
+ return 0;
+ }
+}
+
+static int conf_sym(struct menu *menu)
+{
+ struct symbol *sym = menu->sym;
+ int type;
+ tristate oldval, newval;
+ const char *help;
+
+ while (1) {
+ printf("%*s%s ", indent - 1, "", menu->prompt->text);
+ if (sym->name)
+ printf("(%s) ", sym->name);
+ type = sym_get_type(sym);
+ putchar('[');
+ oldval = sym_get_tristate_value(sym);
+ switch (oldval) {
+ case no:
+ putchar('N');
+ break;
+ case mod:
+ putchar('M');
+ break;
+ case yes:
+ putchar('Y');
+ break;
+ }
+ if (oldval != no && sym_tristate_within_range(sym, no))
+ printf("/n");
+ if (oldval != mod && sym_tristate_within_range(sym, mod))
+ printf("/m");
+ if (oldval != yes && sym_tristate_within_range(sym, yes))
+ printf("/y");
+ if (sym->help)
+ printf("/?");
+ printf("] ");
+ conf_askvalue(sym, sym_get_string_value(sym));
+ strip(line);
+
+ switch (line[0]) {
+ case 'n':
+ case 'N':
+ newval = no;
+ if (!line[1] || !strcmp(&line[1], "o"))
+ break;
+ continue;
+ case 'm':
+ case 'M':
+ newval = mod;
+ if (!line[1])
+ break;
+ continue;
+ case 'y':
+ case 'Y':
+ newval = yes;
+ if (!line[1] || !strcmp(&line[1], "es"))
+ break;
+ continue;
+ case 0:
+ newval = oldval;
+ break;
+ case '?':
+ goto help;
+ default:
+ continue;
+ }
+ if (sym_set_tristate_value(sym, newval))
+ return 0;
+help:
+ help = nohelp_text;
+ if (sym->help)
+ help = sym->help;
+ printf("\n%s\n", help);
+ }
+}
+
+static int conf_choice(struct menu *menu)
+{
+ struct symbol *sym, *def_sym;
+ struct menu *child;
+ int type;
+ bool is_new;
+
+ sym = menu->sym;
+ type = sym_get_type(sym);
+ is_new = !sym_has_value(sym);
+ if (sym_is_changable(sym)) {
+ conf_sym(menu);
+ sym_calc_value(sym);
+ switch (sym_get_tristate_value(sym)) {
+ case no:
+ return 1;
+ case mod:
+ return 0;
+ case yes:
+ break;
+ }
+ } else {
+ switch (sym_get_tristate_value(sym)) {
+ case no:
+ return 1;
+ case mod:
+ printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
+ return 0;
+ case yes:
+ break;
+ }
+ }
+
+ while (1) {
+ int cnt, def;
+
+ printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
+ def_sym = sym_get_choice_value(sym);
+ cnt = def = 0;
+ line[0] = '0';
+ line[1] = 0;
+ for (child = menu->list; child; child = child->next) {
+ if (!menu_is_visible(child))
+ continue;
+ if (!child->sym) {
+ printf("%*c %s\n", indent, '*', menu_get_prompt(child));
+ continue;
+ }
+ cnt++;
+ if (child->sym == def_sym) {
+ def = cnt;
+ printf("%*c", indent, '>');
+ } else
+ printf("%*c", indent, ' ');
+ printf(" %d. %s", cnt, menu_get_prompt(child));
+ if (child->sym->name)
+ printf(" (%s)", child->sym->name);
+ if (!sym_has_value(child->sym))
+ printf(" (NEW)");
+ printf("\n");
+ }
+ printf("%*schoice", indent - 1, "");
+ if (cnt == 1) {
+ printf("[1]: 1\n");
+ goto conf_childs;
+ }
+ printf("[1-%d", cnt);
+ if (sym->help)
+ printf("?");
+ printf("]: ");
+ switch (input_mode) {
+ case ask_new:
+ case ask_silent:
+ if (!is_new) {
+ cnt = def;
+ printf("%d\n", cnt);
+ break;
+ }
+ check_stdin();
+ case ask_all:
+ fflush(stdout);
+ fgets_check_stream(line, 128, stdin);
+ strip(line);
+ if (line[0] == '?') {
+ printf("\n%s\n", menu->sym->help ?
+ menu->sym->help : nohelp_text);
+ continue;
+ }
+ if (!line[0])
+ cnt = def;
+ else if (isdigit(line[0]))
+ cnt = atoi(line);
+ else
+ continue;
+ break;
+ case set_random:
+ def = (random() % cnt) + 1;
+ case set_default:
+ case set_yes:
+ case set_mod:
+ case set_no:
+ cnt = def;
+ printf("%d\n", cnt);
+ break;
+ }
+
+ conf_childs:
+ for (child = menu->list; child; child = child->next) {
+ if (!child->sym || !menu_is_visible(child))
+ continue;
+ if (!--cnt)
+ break;
+ }
+ if (!child)
+ continue;
+ if (line[strlen(line) - 1] == '?') {
+ printf("\n%s\n", child->sym->help ?
+ child->sym->help : nohelp_text);
+ continue;
+ }
+ sym_set_choice_value(sym, child->sym);
+ if (child->list) {
+ indent += 2;
+ conf(child->list);
+ indent -= 2;
+ }
+ return 1;
+ }
+}
+
+static void conf(struct menu *menu)
+{
+ struct symbol *sym;
+ struct property *prop;
+ struct menu *child;
+
+ if (!menu_is_visible(menu))
+ return;
+
+ sym = menu->sym;
+ prop = menu->prompt;
+ if (prop) {
+ const char *prompt;
+
+ switch (prop->type) {
+ case P_MENU:
+ if (input_mode == ask_silent && rootEntry != menu) {
+ check_conf(menu);
+ return;
+ }
+ case P_COMMENT:
+ prompt = menu_get_prompt(menu);
+ if (prompt)
+ printf("%*c\n%*c %s\n%*c\n",
+ indent, '*',
+ indent, '*', prompt,
+ indent, '*');
+ default:
+ ;
+ }
+ }
+
+ if (!sym)
+ goto conf_childs;
+
+ if (sym_is_choice(sym)) {
+ conf_choice(menu);
+ if (sym->curr.tri != mod)
+ return;
+ goto conf_childs;
+ }
+
+ switch (sym->type) {
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ conf_string(menu);
+ break;
+ default:
+ conf_sym(menu);
+ break;
+ }
+
+conf_childs:
+ if (sym)
+ indent += 2;
+ for (child = menu->list; child; child = child->next)
+ conf(child);
+ if (sym)
+ indent -= 2;
+}
+
+static void check_conf(struct menu *menu)
+{
+ struct symbol *sym;
+ struct menu *child;
+
+ if (!menu_is_visible(menu))
+ return;
+
+ sym = menu->sym;
+ if (sym && !sym_has_value(sym)) {
+ if (sym_is_changable(sym) ||
+ (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
+ if (!conf_cnt++)
+ printf(_("*\n* Restart config...\n*\n"));
+ rootEntry = menu_get_parent_menu(menu);
+ conf(rootEntry);
+ }
+ }
+
+ for (child = menu->list; child; child = child->next)
+ check_conf(child);
+}
+
+int main(int ac, char **av)
+{
+ int i = 1;
+ const char *name;
+ struct stat tmpstat;
+
+ if (ac > i && av[i][0] == '-') {
+ switch (av[i++][1]) {
+ case 'o':
+ input_mode = ask_new;
+ break;
+ case 's':
+ input_mode = ask_silent;
+ valid_stdin = isatty(0) && isatty(1) && isatty(2);
+ break;
+ case 'd':
+ input_mode = set_default;
+ break;
+ case 'D':
+ input_mode = set_default;
+ defconfig_file = av[i++];
+ if (!defconfig_file) {
+ printf(_("%s: No default config file specified\n"),
+ av[0]);
+ exit(1);
+ }
+ break;
+ case 'n':
+ input_mode = set_no;
+ break;
+ case 'm':
+ input_mode = set_mod;
+ break;
+ case 'y':
+ input_mode = set_yes;
+ break;
+ case 'r':
+ input_mode = set_random;
+ srandom(time(NULL));
+ break;
+ case 'h':
+ case '?':
+ printf("%s [-o|-s] config\n", av[0]);
+ exit(0);
+ }
+ }
+ name = av[i];
+ if (!name) {
+ printf(_("%s: Kconfig file missing\n"), av[0]);
+ }
+ conf_parse(name);
+ //zconfdump(stdout);
+ switch (input_mode) {
+ case set_default:
+ if (!defconfig_file)
+ defconfig_file = conf_get_default_confname();
+ if (conf_read(defconfig_file)) {
+ printf("***\n"
+ "*** Can't find default configuration \"%s\"!\n"
+ "***\n", defconfig_file);
+ exit(1);
+ }
+ break;
+ case ask_silent:
+ if (stat(".config", &tmpstat)) {
+ printf(_("***\n"
+ "*** You have not yet configured your build!\n"
+ "***\n"
+ "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
+ "*** \"make menuconfig\" or \"make xconfig\").\n"
+ "***\n"));
+ exit(1);
+ }
+ case ask_all:
+ case ask_new:
+ conf_read(NULL);
+ break;
+ case set_no:
+ case set_mod:
+ case set_yes:
+ case set_random:
+ name = getenv("KCONFIG_ALLCONFIG");
+ if (name && !stat(name, &tmpstat)) {
+ conf_read_simple(name);
+ break;
+ }
+ switch (input_mode) {
+ case set_no: name = "allno.config"; break;
+ case set_mod: name = "allmod.config"; break;
+ case set_yes: name = "allyes.config"; break;
+ case set_random: name = "allrandom.config"; break;
+ default: break;
+ }
+ if (!stat(name, &tmpstat))
+ conf_read_simple(name);
+ else if (!stat("all.config", &tmpstat))
+ conf_read_simple("all.config");
+ break;
+ default:
+ break;
+ }
+
+ if (input_mode != ask_silent) {
+ rootEntry = &rootmenu;
+ conf(&rootmenu);
+ if (input_mode == ask_all) {
+ input_mode = ask_silent;
+ valid_stdin = 1;
+ }
+ }
+ do {
+ conf_cnt = 0;
+ check_conf(&rootmenu);
+ } while (conf_cnt);
+ if (conf_write(NULL)) {
+ fprintf(stderr, _("\n*** Error during writing of the build configuration.\n\n"));
+ return 1;
+ }
+ return 0;
+}
diff --git a/scripts/config/confdata.c b/scripts/config/confdata.c
new file mode 100644
index 0000000000..641aa48915
--- /dev/null
+++ b/scripts/config/confdata.c
@@ -0,0 +1,553 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <sys/stat.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+static void conf_warning(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+static const char *conf_filename;
+static int conf_lineno, conf_warnings, conf_unsaved;
+
+const char conf_def_filename[] = ".config";
+
+const char conf_defname[] = "scripts/config/defconfig";
+
+const char *conf_confnames[] = {
+ ".config",
+ conf_defname,
+ NULL,
+};
+
+static void conf_warning(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ conf_warnings++;
+}
+
+static char *conf_expand_value(const char *in)
+{
+ struct symbol *sym;
+ const char *src;
+ static char res_value[SYMBOL_MAXLENGTH];
+ char *dst, name[SYMBOL_MAXLENGTH];
+
+ res_value[0] = 0;
+ dst = name;
+ while ((src = strchr(in, '$'))) {
+ strncat(res_value, in, src - in);
+ src++;
+ dst = name;
+ while (isalnum(*src) || *src == '_')
+ *dst++ = *src++;
+ *dst = 0;
+ sym = sym_lookup(name, 0);
+ sym_calc_value(sym);
+ strcat(res_value, sym_get_string_value(sym));
+ in = src;
+ }
+ strcat(res_value, in);
+
+ return res_value;
+}
+
+char *conf_get_default_confname(void)
+{
+ struct stat buf;
+ static char fullname[PATH_MAX+1];
+ char *env, *name;
+
+ name = conf_expand_value(conf_defname);
+ env = getenv(SRCTREE);
+ if (env) {
+ sprintf(fullname, "%s/%s", env, name);
+ if (!stat(fullname, &buf))
+ return fullname;
+ }
+ return name;
+}
+
+void conf_reset(void)
+{
+ struct symbol *sym;
+ int i;
+
+ for_all_symbols(i, sym) {
+ sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
+ if (sym_is_choice(sym))
+ sym->flags &= ~SYMBOL_NEW;
+ sym->flags &= ~SYMBOL_VALID;
+ switch (sym->type) {
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ if (sym->user.val)
+ free(sym->user.val);
+ default:
+ sym->user.val = NULL;
+ sym->user.tri = no;
+ }
+ }
+}
+
+int conf_read_simple(const char *name)
+{
+ FILE *in = NULL;
+ char line[1024];
+ char *p, *p2;
+ struct symbol *sym;
+ int i;
+
+ if (name) {
+ in = zconf_fopen(name);
+ } else {
+ const char **names = conf_confnames;
+ while ((name = *names++)) {
+ name = conf_expand_value(name);
+ in = zconf_fopen(name);
+ if (in) {
+ printf(_("#\n"
+ "# using defaults found in %s\n"
+ "#\n"), name);
+ break;
+ }
+ }
+ }
+ if (!in)
+ return 1;
+
+ conf_filename = name;
+ conf_lineno = 0;
+ conf_warnings = 0;
+ conf_unsaved = 0;
+
+ for_all_symbols(i, sym) {
+ sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
+ if (sym_is_choice(sym))
+ sym->flags &= ~SYMBOL_NEW;
+ sym->flags &= ~SYMBOL_VALID;
+ switch (sym->type) {
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ if (sym->user.val)
+ free(sym->user.val);
+ default:
+ sym->user.val = NULL;
+ sym->user.tri = no;
+ }
+ }
+
+ while (fgets(line, sizeof(line), in)) {
+ conf_lineno++;
+ sym = NULL;
+ switch (line[0]) {
+ case '#':
+ if (memcmp(line + 2, "CONFIG_", 7))
+ continue;
+ p = strchr(line + 9, ' ');
+ if (!p)
+ continue;
+ *p++ = 0;
+ if (strncmp(p, "is not set", 10))
+ continue;
+ sym = sym_find(line + 9);
+ if (!sym) {
+ conf_warning("trying to assign nonexistent symbol %s", line + 9);
+ break;
+ } else if (!(sym->flags & SYMBOL_NEW)) {
+ conf_warning("trying to reassign symbol %s", sym->name);
+ break;
+ }
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ sym->user.tri = no;
+ sym->flags &= ~SYMBOL_NEW;
+ break;
+ default:
+ ;
+ }
+ break;
+ case 'C':
+ if (memcmp(line, "CONFIG_", 7)) {
+ conf_warning("unexpected data");
+ continue;
+ }
+ p = strchr(line + 7, '=');
+ if (!p)
+ continue;
+ *p++ = 0;
+ p2 = strchr(p, '\n');
+ if (p2)
+ *p2 = 0;
+ sym = sym_find(line + 7);
+ if (!sym) {
+ conf_warning("trying to assign nonexistent symbol %s", line + 7);
+ break;
+ } else if (!(sym->flags & SYMBOL_NEW)) {
+ conf_warning("trying to reassign symbol %s", sym->name);
+ break;
+ }
+ switch (sym->type) {
+ case S_TRISTATE:
+ if (p[0] == 'm') {
+ sym->user.tri = mod;
+ sym->flags &= ~SYMBOL_NEW;
+ break;
+ }
+ case S_BOOLEAN:
+ if (p[0] == 'y') {
+ sym->user.tri = yes;
+ sym->flags &= ~SYMBOL_NEW;
+ break;
+ }
+ if (p[0] == 'n') {
+ sym->user.tri = no;
+ sym->flags &= ~SYMBOL_NEW;
+ break;
+ }
+ conf_warning("symbol value '%s' invalid for %s", p, sym->name);
+ break;
+ case S_STRING:
+ if (*p++ != '"')
+ break;
+ for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
+ if (*p2 == '"') {
+ *p2 = 0;
+ break;
+ }
+ memmove(p2, p2 + 1, strlen(p2));
+ }
+ if (!p2) {
+ conf_warning("invalid string found");
+ continue;
+ }
+ case S_INT:
+ case S_HEX:
+ if (sym_string_valid(sym, p)) {
+ sym->user.val = strdup(p);
+ sym->flags &= ~SYMBOL_NEW;
+ } else {
+ conf_warning("symbol value '%s' invalid for %s", p, sym->name);
+ continue;
+ }
+ break;
+ default:
+ ;
+ }
+ break;
+ case '\n':
+ break;
+ default:
+ conf_warning("unexpected data");
+ continue;
+ }
+ if (sym && sym_is_choice_value(sym)) {
+ struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
+ switch (sym->user.tri) {
+ case no:
+ break;
+ case mod:
+ if (cs->user.tri == yes) {
+ conf_warning("%s creates inconsistent choice state", sym->name);
+ cs->flags |= SYMBOL_NEW;
+ }
+ break;
+ case yes:
+ if (cs->user.tri != no) {
+ conf_warning("%s creates inconsistent choice state", sym->name);
+ cs->flags |= SYMBOL_NEW;
+ } else
+ cs->user.val = sym;
+ break;
+ }
+ cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
+ }
+ }
+ fclose(in);
+
+ if (modules_sym)
+ sym_calc_value(modules_sym);
+ return 0;
+}
+
+int conf_read(const char *name)
+{
+ struct symbol *sym;
+ struct property *prop;
+ struct expr *e;
+ int i;
+
+ if (conf_read_simple(name))
+ return 1;
+
+ for_all_symbols(i, sym) {
+ sym_calc_value(sym);
+ if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
+ goto sym_ok;
+ if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
+ /* check that calculated value agrees with saved value */
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ if (sym->user.tri != sym_get_tristate_value(sym))
+ break;
+ if (!sym_is_choice(sym))
+ goto sym_ok;
+ default:
+ if (!strcmp(sym->curr.val, sym->user.val))
+ goto sym_ok;
+ break;
+ }
+ } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
+ /* no previous value and not saved */
+ goto sym_ok;
+ conf_unsaved++;
+ /* maybe print value in verbose mode... */
+ sym_ok:
+ if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
+ if (sym->visible == no)
+ sym->flags |= SYMBOL_NEW;
+ switch (sym->type) {
+ case S_STRING:
+ case S_INT:
+ case S_HEX:
+ if (!sym_string_within_range(sym, sym->user.val)) {
+ sym->flags |= SYMBOL_NEW;
+ sym->flags &= ~SYMBOL_VALID;
+ }
+ default:
+ break;
+ }
+ }
+ if (!sym_is_choice(sym))
+ continue;
+ prop = sym_get_choice_prop(sym);
+ for (e = prop->expr; e; e = e->left.expr)
+ if (e->right.sym->visible != no)
+ sym->flags |= e->right.sym->flags & SYMBOL_NEW;
+ }
+
+ sym_change_count = conf_warnings && conf_unsaved;
+
+ return 0;
+}
+
+int conf_write(const char *name)
+{
+ FILE *out, *out_h;
+ struct symbol *sym;
+ struct menu *menu;
+ const char *basename;
+ char dirname[128], tmpname[128], newname[128];
+ int type, l;
+ const char *str;
+ time_t now;
+ int use_timestamp = 1;
+ char *env;
+
+ dirname[0] = 0;
+ if (name && name[0]) {
+ struct stat st;
+ char *slash;
+
+ if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
+ strcpy(dirname, name);
+ strcat(dirname, "/");
+ basename = conf_def_filename;
+ } else if ((slash = strrchr(name, '/'))) {
+ int size = slash - name + 1;
+ memcpy(dirname, name, size);
+ dirname[size] = 0;
+ if (slash[1])
+ basename = slash + 1;
+ else
+ basename = conf_def_filename;
+ } else
+ basename = name;
+ } else
+ basename = conf_def_filename;
+
+ sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid());
+ out = fopen(newname, "w");
+ if (!out)
+ return 1;
+ out_h = NULL;
+ if (!name) {
+ out_h = fopen(".tmpconfig.h", "w");
+ if (!out_h)
+ return 1;
+ }
+ sym = sym_lookup("OPENWRTVERSION", 0);
+ sym_calc_value(sym);
+ time(&now);
+ env = getenv("KCONFIG_NOTIMESTAMP");
+ if (env && *env)
+ use_timestamp = 0;
+
+ fprintf(out, _("#\n"
+ "# Automatically generated make config: don't edit\n"
+ "# OpenWrt version: %s\n"
+ "%s%s"
+ "#\n"),
+ sym_get_string_value(sym),
+ use_timestamp ? "# " : "",
+ use_timestamp ? ctime(&now) : "");
+ if (out_h)
+ fprintf(out_h, "/*\n"
+ " * Automatically generated C config: don't edit\n"
+ " * OpenWrt version: %s\n"
+ "%s%s"
+ " */\n"
+ "#define AUTOCONF_INCLUDED\n",
+ sym_get_string_value(sym),
+ use_timestamp ? " * " : "",
+ use_timestamp ? ctime(&now) : "");
+
+ if (!sym_change_count)
+ sym_clear_all_valid();
+
+ menu = rootmenu.list;
+ while (menu) {
+ sym = menu->sym;
+ if (!sym) {
+ if (!menu_is_visible(menu))
+ goto next;
+ str = menu_get_prompt(menu);
+ fprintf(out, "\n"
+ "#\n"
+ "# %s\n"
+ "#\n", str);
+ if (out_h)
+ fprintf(out_h, "\n"
+ "/*\n"
+ " * %s\n"
+ " */\n", str);
+ } else if (!(sym->flags & SYMBOL_CHOICE)) {
+ sym_calc_value(sym);
+ if (!(sym->flags & SYMBOL_WRITE))
+ goto next;
+ sym->flags &= ~SYMBOL_WRITE;
+ type = sym->type;
+ if (type == S_TRISTATE) {
+ sym_calc_value(modules_sym);
+/* tristate always enabled */
+#if 0
+ if (modules_sym->curr.tri == no)
+ type = S_BOOLEAN;
+#endif
+ }
+ switch (type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (sym_get_tristate_value(sym)) {
+ case no:
+ fprintf(out, "# CONFIG_%s is not set\n", sym->name);
+ if (out_h)
+ fprintf(out_h, "#undef CONFIG_%s\n", sym->name);
+ break;
+ case mod:
+ fprintf(out, "CONFIG_%s=m\n", sym->name);
+ if (out_h)
+ fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
+ break;
+ case yes:
+ fprintf(out, "CONFIG_%s=y\n", sym->name);
+ if (out_h)
+ fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
+ break;
+ }
+ break;
+ case S_STRING:
+ // fix me
+ str = sym_get_string_value(sym);
+ fprintf(out, "CONFIG_%s=\"", sym->name);
+ if (out_h)
+ fprintf(out_h, "#define CONFIG_%s \"", sym->name);
+ do {
+ l = strcspn(str, "\"\\");
+ if (l) {
+ fwrite(str, l, 1, out);
+ if (out_h)
+ fwrite(str, l, 1, out_h);
+ }
+ str += l;
+ while (*str == '\\' || *str == '"') {
+ fprintf(out, "\\%c", *str);
+ if (out_h)
+ fprintf(out_h, "\\%c", *str);
+ str++;
+ }
+ } while (*str);
+ fputs("\"\n", out);
+ if (out_h)
+ fputs("\"\n", out_h);
+ break;
+ case S_HEX:
+ str = sym_get_string_value(sym);
+ if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
+ fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
+ if (out_h)
+ fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
+ break;
+ }
+ case S_INT:
+ str = sym_get_string_value(sym);
+ fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
+ if (out_h)
+ fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
+ break;
+ }
+ }
+
+ next:
+ if (menu->list) {
+ menu = menu->list;
+ continue;
+ }
+ if (menu->next)
+ menu = menu->next;
+ else while ((menu = menu->parent)) {
+ if (menu->next) {
+ menu = menu->next;
+ break;
+ }
+ }
+ }
+ fclose(out);
+ if (out_h) {
+ fclose(out_h);
+ rename(".tmpconfig.h", "include/linux/autoconf.h");
+ file_write_dep(NULL);
+ }
+ if (!name || basename != conf_def_filename) {
+ if (!name)
+ name = conf_def_filename;
+ sprintf(tmpname, "%s.old", name);
+ rename(name, tmpname);
+ }
+ sprintf(tmpname, "%s%s", dirname, basename);
+ if (rename(newname, tmpname))
+ return 1;
+
+ sym_change_count = 0;
+
+ return 0;
+}
diff --git a/scripts/config/expr.c b/scripts/config/expr.c
new file mode 100644
index 0000000000..30e4f9d69c
--- /dev/null
+++ b/scripts/config/expr.c
@@ -0,0 +1,1099 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+#define DEBUG_EXPR 0
+
+struct expr *expr_alloc_symbol(struct symbol *sym)
+{
+ struct expr *e = malloc(sizeof(*e));
+ memset(e, 0, sizeof(*e));
+ e->type = E_SYMBOL;
+ e->left.sym = sym;
+ return e;
+}
+
+struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
+{
+ struct expr *e = malloc(sizeof(*e));
+ memset(e, 0, sizeof(*e));
+ e->type = type;
+ e->left.expr = ce;
+ return e;
+}
+
+struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
+{
+ struct expr *e = malloc(sizeof(*e));
+ memset(e, 0, sizeof(*e));
+ e->type = type;
+ e->left.expr = e1;
+ e->right.expr = e2;
+ return e;
+}
+
+struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
+{
+ struct expr *e = malloc(sizeof(*e));
+ memset(e, 0, sizeof(*e));
+ e->type = type;
+ e->left.sym = s1;
+ e->right.sym = s2;
+ return e;
+}
+
+struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
+{
+ if (!e1)
+ return e2;
+ return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
+}
+
+struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
+{
+ if (!e1)
+ return e2;
+ return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
+}
+
+struct expr *expr_copy(struct expr *org)
+{
+ struct expr *e;
+
+ if (!org)
+ return NULL;
+
+ e = malloc(sizeof(*org));
+ memcpy(e, org, sizeof(*org));
+ switch (org->type) {
+ case E_SYMBOL:
+ e->left = org->left;
+ break;
+ case E_NOT:
+ e->left.expr = expr_copy(org->left.expr);
+ break;
+ case E_EQUAL:
+ case E_UNEQUAL:
+ e->left.sym = org->left.sym;
+ e->right.sym = org->right.sym;
+ break;
+ case E_AND:
+ case E_OR:
+ case E_CHOICE:
+ e->left.expr = expr_copy(org->left.expr);
+ e->right.expr = expr_copy(org->right.expr);
+ break;
+ default:
+ printf("can't copy type %d\n", e->type);
+ free(e);
+ e = NULL;
+ break;
+ }
+
+ return e;
+}
+
+void expr_free(struct expr *e)
+{
+ if (!e)
+ return;
+
+ switch (e->type) {
+ case E_SYMBOL:
+ break;
+ case E_NOT:
+ expr_free(e->left.expr);
+ return;
+ case E_EQUAL:
+ case E_UNEQUAL:
+ break;
+ case E_OR:
+ case E_AND:
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ break;
+ default:
+ printf("how to free type %d?\n", e->type);
+ break;
+ }
+ free(e);
+}
+
+static int trans_count;
+
+#define e1 (*ep1)
+#define e2 (*ep2)
+
+static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
+{
+ if (e1->type == type) {
+ __expr_eliminate_eq(type, &e1->left.expr, &e2);
+ __expr_eliminate_eq(type, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->type == type) {
+ __expr_eliminate_eq(type, &e1, &e2->left.expr);
+ __expr_eliminate_eq(type, &e1, &e2->right.expr);
+ return;
+ }
+ if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
+ e1->left.sym == e2->left.sym && (e1->left.sym->flags & (SYMBOL_YES|SYMBOL_NO)))
+ return;
+ if (!expr_eq(e1, e2))
+ return;
+ trans_count++;
+ expr_free(e1); expr_free(e2);
+ switch (type) {
+ case E_OR:
+ e1 = expr_alloc_symbol(&symbol_no);
+ e2 = expr_alloc_symbol(&symbol_no);
+ break;
+ case E_AND:
+ e1 = expr_alloc_symbol(&symbol_yes);
+ e2 = expr_alloc_symbol(&symbol_yes);
+ break;
+ default:
+ ;
+ }
+}
+
+void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
+{
+ if (!e1 || !e2)
+ return;
+ switch (e1->type) {
+ case E_OR:
+ case E_AND:
+ __expr_eliminate_eq(e1->type, ep1, ep2);
+ default:
+ ;
+ }
+ if (e1->type != e2->type) switch (e2->type) {
+ case E_OR:
+ case E_AND:
+ __expr_eliminate_eq(e2->type, ep1, ep2);
+ default:
+ ;
+ }
+ e1 = expr_eliminate_yn(e1);
+ e2 = expr_eliminate_yn(e2);
+}
+
+#undef e1
+#undef e2
+
+int expr_eq(struct expr *e1, struct expr *e2)
+{
+ int res, old_count;
+
+ if (e1->type != e2->type)
+ return 0;
+ switch (e1->type) {
+ case E_EQUAL:
+ case E_UNEQUAL:
+ return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
+ case E_SYMBOL:
+ return e1->left.sym == e2->left.sym;
+ case E_NOT:
+ return expr_eq(e1->left.expr, e2->left.expr);
+ case E_AND:
+ case E_OR:
+ e1 = expr_copy(e1);
+ e2 = expr_copy(e2);
+ old_count = trans_count;
+ expr_eliminate_eq(&e1, &e2);
+ res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
+ e1->left.sym == e2->left.sym);
+ expr_free(e1);
+ expr_free(e2);
+ trans_count = old_count;
+ return res;
+ case E_CHOICE:
+ case E_RANGE:
+ case E_NONE:
+ /* panic */;
+ }
+
+ if (DEBUG_EXPR) {
+ expr_fprint(e1, stdout);
+ printf(" = ");
+ expr_fprint(e2, stdout);
+ printf(" ?\n");
+ }
+
+ return 0;
+}
+
+struct expr *expr_eliminate_yn(struct expr *e)
+{
+ struct expr *tmp;
+
+ if (e) switch (e->type) {
+ case E_AND:
+ e->left.expr = expr_eliminate_yn(e->left.expr);
+ e->right.expr = expr_eliminate_yn(e->right.expr);
+ if (e->left.expr->type == E_SYMBOL) {
+ if (e->left.expr->left.sym == &symbol_no) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_no;
+ e->right.expr = NULL;
+ return e;
+ } else if (e->left.expr->left.sym == &symbol_yes) {
+ free(e->left.expr);
+ tmp = e->right.expr;
+ *e = *(e->right.expr);
+ free(tmp);
+ return e;
+ }
+ }
+ if (e->right.expr->type == E_SYMBOL) {
+ if (e->right.expr->left.sym == &symbol_no) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_no;
+ e->right.expr = NULL;
+ return e;
+ } else if (e->right.expr->left.sym == &symbol_yes) {
+ free(e->right.expr);
+ tmp = e->left.expr;
+ *e = *(e->left.expr);
+ free(tmp);
+ return e;
+ }
+ }
+ break;
+ case E_OR:
+ e->left.expr = expr_eliminate_yn(e->left.expr);
+ e->right.expr = expr_eliminate_yn(e->right.expr);
+ if (e->left.expr->type == E_SYMBOL) {
+ if (e->left.expr->left.sym == &symbol_no) {
+ free(e->left.expr);
+ tmp = e->right.expr;
+ *e = *(e->right.expr);
+ free(tmp);
+ return e;
+ } else if (e->left.expr->left.sym == &symbol_yes) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_yes;
+ e->right.expr = NULL;
+ return e;
+ }
+ }
+ if (e->right.expr->type == E_SYMBOL) {
+ if (e->right.expr->left.sym == &symbol_no) {
+ free(e->right.expr);
+ tmp = e->left.expr;
+ *e = *(e->left.expr);
+ free(tmp);
+ return e;
+ } else if (e->right.expr->left.sym == &symbol_yes) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_yes;
+ e->right.expr = NULL;
+ return e;
+ }
+ }
+ break;
+ default:
+ ;
+ }
+ return e;
+}
+
+/*
+ * bool FOO!=n => FOO
+ */
+struct expr *expr_trans_bool(struct expr *e)
+{
+ if (!e)
+ return NULL;
+ switch (e->type) {
+ case E_AND:
+ case E_OR:
+ case E_NOT:
+ e->left.expr = expr_trans_bool(e->left.expr);
+ e->right.expr = expr_trans_bool(e->right.expr);
+ break;
+ case E_UNEQUAL:
+ // FOO!=n -> FOO
+ if (e->left.sym->type == S_TRISTATE) {
+ if (e->right.sym == &symbol_no) {
+ e->type = E_SYMBOL;
+ e->right.sym = NULL;
+ }
+ }
+ break;
+ default:
+ ;
+ }
+ return e;
+}
+
+/*
+ * e1 || e2 -> ?
+ */
+struct expr *expr_join_or(struct expr *e1, struct expr *e2)
+{
+ struct expr *tmp;
+ struct symbol *sym1, *sym2;
+
+ if (expr_eq(e1, e2))
+ return expr_copy(e1);
+ if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
+ return NULL;
+ if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
+ return NULL;
+ if (e1->type == E_NOT) {
+ tmp = e1->left.expr;
+ if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
+ return NULL;
+ sym1 = tmp->left.sym;
+ } else
+ sym1 = e1->left.sym;
+ if (e2->type == E_NOT) {
+ if (e2->left.expr->type != E_SYMBOL)
+ return NULL;
+ sym2 = e2->left.expr->left.sym;
+ } else
+ sym2 = e2->left.sym;
+ if (sym1 != sym2)
+ return NULL;
+ if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
+ return NULL;
+ if (sym1->type == S_TRISTATE) {
+ if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
+ (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
+ // (a='y') || (a='m') -> (a!='n')
+ return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
+ }
+ if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
+ // (a='y') || (a='n') -> (a!='m')
+ return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
+ }
+ if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
+ ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
+ // (a='m') || (a='n') -> (a!='y')
+ return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
+ }
+ }
+ if (sym1->type == S_BOOLEAN && sym1 == sym2) {
+ if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
+ (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
+ return expr_alloc_symbol(&symbol_yes);
+ }
+
+ if (DEBUG_EXPR) {
+ printf("optimize (");
+ expr_fprint(e1, stdout);
+ printf(") || (");
+ expr_fprint(e2, stdout);
+ printf(")?\n");
+ }
+ return NULL;
+}
+
+struct expr *expr_join_and(struct expr *e1, struct expr *e2)
+{
+ struct expr *tmp;
+ struct symbol *sym1, *sym2;
+
+ if (expr_eq(e1, e2))
+ return expr_copy(e1);
+ if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
+ return NULL;
+ if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
+ return NULL;
+ if (e1->type == E_NOT) {
+ tmp = e1->left.expr;
+ if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
+ return NULL;
+ sym1 = tmp->left.sym;
+ } else
+ sym1 = e1->left.sym;
+ if (e2->type == E_NOT) {
+ if (e2->left.expr->type != E_SYMBOL)
+ return NULL;
+ sym2 = e2->left.expr->left.sym;
+ } else
+ sym2 = e2->left.sym;
+ if (sym1 != sym2)
+ return NULL;
+ if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
+ return NULL;
+
+ if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
+ (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
+ // (a) && (a='y') -> (a='y')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
+
+ if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
+ (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
+ // (a) && (a!='n') -> (a)
+ return expr_alloc_symbol(sym1);
+
+ if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
+ (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
+ // (a) && (a!='m') -> (a='y')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
+
+ if (sym1->type == S_TRISTATE) {
+ if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
+ // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
+ sym2 = e1->right.sym;
+ if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
+ return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
+ : expr_alloc_symbol(&symbol_no);
+ }
+ if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
+ // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
+ sym2 = e2->right.sym;
+ if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
+ return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
+ : expr_alloc_symbol(&symbol_no);
+ }
+ if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
+ // (a!='y') && (a!='n') -> (a='m')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
+
+ if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
+ (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
+ // (a!='y') && (a!='m') -> (a='n')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
+
+ if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
+ ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
+ // (a!='m') && (a!='n') -> (a='m')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
+
+ if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
+ (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
+ (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
+ (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
+ return NULL;
+ }
+
+ if (DEBUG_EXPR) {
+ printf("optimize (");
+ expr_fprint(e1, stdout);
+ printf(") && (");
+ expr_fprint(e2, stdout);
+ printf(")?\n");
+ }
+ return NULL;
+}
+
+static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+ struct expr *tmp;
+
+ if (e1->type == type) {
+ expr_eliminate_dups1(type, &e1->left.expr, &e2);
+ expr_eliminate_dups1(type, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->type == type) {
+ expr_eliminate_dups1(type, &e1, &e2->left.expr);
+ expr_eliminate_dups1(type, &e1, &e2->right.expr);
+ return;
+ }
+ if (e1 == e2)
+ return;
+
+ switch (e1->type) {
+ case E_OR: case E_AND:
+ expr_eliminate_dups1(e1->type, &e1, &e1);
+ default:
+ ;
+ }
+
+ switch (type) {
+ case E_OR:
+ tmp = expr_join_or(e1, e2);
+ if (tmp) {
+ expr_free(e1); expr_free(e2);
+ e1 = expr_alloc_symbol(&symbol_no);
+ e2 = tmp;
+ trans_count++;
+ }
+ break;
+ case E_AND:
+ tmp = expr_join_and(e1, e2);
+ if (tmp) {
+ expr_free(e1); expr_free(e2);
+ e1 = expr_alloc_symbol(&symbol_yes);
+ e2 = tmp;
+ trans_count++;
+ }
+ break;
+ default:
+ ;
+ }
+#undef e1
+#undef e2
+}
+
+static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+ struct expr *tmp, *tmp1, *tmp2;
+
+ if (e1->type == type) {
+ expr_eliminate_dups2(type, &e1->left.expr, &e2);
+ expr_eliminate_dups2(type, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->type == type) {
+ expr_eliminate_dups2(type, &e1, &e2->left.expr);
+ expr_eliminate_dups2(type, &e1, &e2->right.expr);
+ }
+ if (e1 == e2)
+ return;
+
+ switch (e1->type) {
+ case E_OR:
+ expr_eliminate_dups2(e1->type, &e1, &e1);
+ // (FOO || BAR) && (!FOO && !BAR) -> n
+ tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
+ tmp2 = expr_copy(e2);
+ tmp = expr_extract_eq_and(&tmp1, &tmp2);
+ if (expr_is_yes(tmp1)) {
+ expr_free(e1);
+ e1 = expr_alloc_symbol(&symbol_no);
+ trans_count++;
+ }
+ expr_free(tmp2);
+ expr_free(tmp1);
+ expr_free(tmp);
+ break;
+ case E_AND:
+ expr_eliminate_dups2(e1->type, &e1, &e1);
+ // (FOO && BAR) || (!FOO || !BAR) -> y
+ tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
+ tmp2 = expr_copy(e2);
+ tmp = expr_extract_eq_or(&tmp1, &tmp2);
+ if (expr_is_no(tmp1)) {
+ expr_free(e1);
+ e1 = expr_alloc_symbol(&symbol_yes);
+ trans_count++;
+ }
+ expr_free(tmp2);
+ expr_free(tmp1);
+ expr_free(tmp);
+ break;
+ default:
+ ;
+ }
+#undef e1
+#undef e2
+}
+
+struct expr *expr_eliminate_dups(struct expr *e)
+{
+ int oldcount;
+ if (!e)
+ return e;
+
+ oldcount = trans_count;
+ while (1) {
+ trans_count = 0;
+ switch (e->type) {
+ case E_OR: case E_AND:
+ expr_eliminate_dups1(e->type, &e, &e);
+ expr_eliminate_dups2(e->type, &e, &e);
+ default:
+ ;
+ }
+ if (!trans_count)
+ break;
+ e = expr_eliminate_yn(e);
+ }
+ trans_count = oldcount;
+ return e;
+}
+
+struct expr *expr_transform(struct expr *e)
+{
+ struct expr *tmp;
+
+ if (!e)
+ return NULL;
+ switch (e->type) {
+ case E_EQUAL:
+ case E_UNEQUAL:
+ case E_SYMBOL:
+ case E_CHOICE:
+ break;
+ default:
+ e->left.expr = expr_transform(e->left.expr);
+ e->right.expr = expr_transform(e->right.expr);
+ }
+
+ switch (e->type) {
+ case E_EQUAL:
+ if (e->left.sym->type != S_BOOLEAN)
+ break;
+ if (e->right.sym == &symbol_no) {
+ e->type = E_NOT;
+ e->left.expr = expr_alloc_symbol(e->left.sym);
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_mod) {
+ printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_no;
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_yes) {
+ e->type = E_SYMBOL;
+ e->right.sym = NULL;
+ break;
+ }
+ break;
+ case E_UNEQUAL:
+ if (e->left.sym->type != S_BOOLEAN)
+ break;
+ if (e->right.sym == &symbol_no) {
+ e->type = E_SYMBOL;
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_mod) {
+ printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_yes;
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_yes) {
+ e->type = E_NOT;
+ e->left.expr = expr_alloc_symbol(e->left.sym);
+ e->right.sym = NULL;
+ break;
+ }
+ break;
+ case E_NOT:
+ switch (e->left.expr->type) {
+ case E_NOT:
+ // !!a -> a
+ tmp = e->left.expr->left.expr;
+ free(e->left.expr);
+ free(e);
+ e = tmp;
+ e = expr_transform(e);
+ break;
+ case E_EQUAL:
+ case E_UNEQUAL:
+ // !a='x' -> a!='x'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
+ break;
+ case E_OR:
+ // !(a || b) -> !a && !b
+ tmp = e->left.expr;
+ e->type = E_AND;
+ e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
+ tmp->type = E_NOT;
+ tmp->right.expr = NULL;
+ e = expr_transform(e);
+ break;
+ case E_AND:
+ // !(a && b) -> !a || !b
+ tmp = e->left.expr;
+ e->type = E_OR;
+ e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
+ tmp->type = E_NOT;
+ tmp->right.expr = NULL;
+ e = expr_transform(e);
+ break;
+ case E_SYMBOL:
+ if (e->left.expr->left.sym == &symbol_yes) {
+ // !'y' -> 'n'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_no;
+ break;
+ }
+ if (e->left.expr->left.sym == &symbol_mod) {
+ // !'m' -> 'm'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_mod;
+ break;
+ }
+ if (e->left.expr->left.sym == &symbol_no) {
+ // !'n' -> 'y'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_yes;
+ break;
+ }
+ break;
+ default:
+ ;
+ }
+ break;
+ default:
+ ;
+ }
+ return e;
+}
+
+int expr_contains_symbol(struct expr *dep, struct symbol *sym)
+{
+ if (!dep)
+ return 0;
+
+ switch (dep->type) {
+ case E_AND:
+ case E_OR:
+ return expr_contains_symbol(dep->left.expr, sym) ||
+ expr_contains_symbol(dep->right.expr, sym);
+ case E_SYMBOL:
+ return dep->left.sym == sym;
+ case E_EQUAL:
+ case E_UNEQUAL:
+ return dep->left.sym == sym ||
+ dep->right.sym == sym;
+ case E_NOT:
+ return expr_contains_symbol(dep->left.expr, sym);
+ default:
+ ;
+ }
+ return 0;
+}
+
+bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
+{
+ if (!dep)
+ return false;
+
+ switch (dep->type) {
+ case E_AND:
+ return expr_depends_symbol(dep->left.expr, sym) ||
+ expr_depends_symbol(dep->right.expr, sym);
+ case E_SYMBOL:
+ return dep->left.sym == sym;
+ case E_EQUAL:
+ if (dep->left.sym == sym) {
+ if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
+ return true;
+ }
+ break;
+ case E_UNEQUAL:
+ if (dep->left.sym == sym) {
+ if (dep->right.sym == &symbol_no)
+ return true;
+ }
+ break;
+ default:
+ ;
+ }
+ return false;
+}
+
+struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2)
+{
+ struct expr *tmp = NULL;
+ expr_extract_eq(E_AND, &tmp, ep1, ep2);
+ if (tmp) {
+ *ep1 = expr_eliminate_yn(*ep1);
+ *ep2 = expr_eliminate_yn(*ep2);
+ }
+ return tmp;
+}
+
+struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2)
+{
+ struct expr *tmp = NULL;
+ expr_extract_eq(E_OR, &tmp, ep1, ep2);
+ if (tmp) {
+ *ep1 = expr_eliminate_yn(*ep1);
+ *ep2 = expr_eliminate_yn(*ep2);
+ }
+ return tmp;
+}
+
+void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+ if (e1->type == type) {
+ expr_extract_eq(type, ep, &e1->left.expr, &e2);
+ expr_extract_eq(type, ep, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->type == type) {
+ expr_extract_eq(type, ep, ep1, &e2->left.expr);
+ expr_extract_eq(type, ep, ep1, &e2->right.expr);
+ return;
+ }
+ if (expr_eq(e1, e2)) {
+ *ep = *ep ? expr_alloc_two(type, *ep, e1) : e1;
+ expr_free(e2);
+ if (type == E_AND) {
+ e1 = expr_alloc_symbol(&symbol_yes);
+ e2 = expr_alloc_symbol(&symbol_yes);
+ } else if (type == E_OR) {
+ e1 = expr_alloc_symbol(&symbol_no);
+ e2 = expr_alloc_symbol(&symbol_no);
+ }
+ }
+#undef e1
+#undef e2
+}
+
+struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
+{
+ struct expr *e1, *e2;
+
+ if (!e) {
+ e = expr_alloc_symbol(sym);
+ if (type == E_UNEQUAL)
+ e = expr_alloc_one(E_NOT, e);
+ return e;
+ }
+ switch (e->type) {
+ case E_AND:
+ e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
+ e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
+ if (sym == &symbol_yes)
+ e = expr_alloc_two(E_AND, e1, e2);
+ if (sym == &symbol_no)
+ e = expr_alloc_two(E_OR, e1, e2);
+ if (type == E_UNEQUAL)
+ e = expr_alloc_one(E_NOT, e);
+ return e;
+ case E_OR:
+ e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
+ e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
+ if (sym == &symbol_yes)
+ e = expr_alloc_two(E_OR, e1, e2);
+ if (sym == &symbol_no)
+ e = expr_alloc_two(E_AND, e1, e2);
+ if (type == E_UNEQUAL)
+ e = expr_alloc_one(E_NOT, e);
+ return e;
+ case E_NOT:
+ return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
+ case E_UNEQUAL:
+ case E_EQUAL:
+ if (type == E_EQUAL) {
+ if (sym == &symbol_yes)
+ return expr_copy(e);
+ if (sym == &symbol_mod)
+ return expr_alloc_symbol(&symbol_no);
+ if (sym == &symbol_no)
+ return expr_alloc_one(E_NOT, expr_copy(e));
+ } else {
+ if (sym == &symbol_yes)
+ return expr_alloc_one(E_NOT, expr_copy(e));
+ if (sym == &symbol_mod)
+ return expr_alloc_symbol(&symbol_yes);
+ if (sym == &symbol_no)
+ return expr_copy(e);
+ }
+ break;
+ case E_SYMBOL:
+ return expr_alloc_comp(type, e->left.sym, sym);
+ case E_CHOICE:
+ case E_RANGE:
+ case E_NONE:
+ /* panic */;
+ }
+ return NULL;
+}
+
+tristate expr_calc_value(struct expr *e)
+{
+ tristate val1, val2;
+ const char *str1, *str2;
+
+ if (!e)
+ return yes;
+
+ switch (e->type) {
+ case E_SYMBOL:
+ sym_calc_value(e->left.sym);
+ return e->left.sym->curr.tri;
+ case E_AND:
+ val1 = expr_calc_value(e->left.expr);
+ val2 = expr_calc_value(e->right.expr);
+ return E_AND(val1, val2);
+ case E_OR:
+ val1 = expr_calc_value(e->left.expr);
+ val2 = expr_calc_value(e->right.expr);
+ return E_OR(val1, val2);
+ case E_NOT:
+ val1 = expr_calc_value(e->left.expr);
+ return E_NOT(val1);
+ case E_EQUAL:
+ sym_calc_value(e->left.sym);
+ sym_calc_value(e->right.sym);
+ str1 = sym_get_string_value(e->left.sym);
+ str2 = sym_get_string_value(e->right.sym);
+ return !strcmp(str1, str2) ? yes : no;
+ case E_UNEQUAL:
+ sym_calc_value(e->left.sym);
+ sym_calc_value(e->right.sym);
+ str1 = sym_get_string_value(e->left.sym);
+ str2 = sym_get_string_value(e->right.sym);
+ return !strcmp(str1, str2) ? no : yes;
+ default:
+ printf("expr_calc_value: %d?\n", e->type);
+ return no;
+ }
+}
+
+int expr_compare_type(enum expr_type t1, enum expr_type t2)
+{
+#if 0
+ return 1;
+#else
+ if (t1 == t2)
+ return 0;
+ switch (t1) {
+ case E_EQUAL:
+ case E_UNEQUAL:
+ if (t2 == E_NOT)
+ return 1;
+ case E_NOT:
+ if (t2 == E_AND)
+ return 1;
+ case E_AND:
+ if (t2 == E_OR)
+ return 1;
+ case E_OR:
+ if (t2 == E_CHOICE)
+ return 1;
+ case E_CHOICE:
+ if (t2 == 0)
+ return 1;
+ default:
+ return -1;
+ }
+ printf("[%dgt%d?]", t1, t2);
+ return 0;
+#endif
+}
+
+void expr_print(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken)
+{
+ if (!e) {
+ fn(data, "y");
+ return;
+ }
+
+ if (expr_compare_type(prevtoken, e->type) > 0)
+ fn(data, "(");
+ switch (e->type) {
+ case E_SYMBOL:
+ if (e->left.sym->name)
+ fn(data, e->left.sym->name);
+ else
+ fn(data, "<choice>");
+ break;
+ case E_NOT:
+ fn(data, "!");
+ expr_print(e->left.expr, fn, data, E_NOT);
+ break;
+ case E_EQUAL:
+ fn(data, e->left.sym->name);
+ fn(data, "=");
+ fn(data, e->right.sym->name);
+ break;
+ case E_UNEQUAL:
+ fn(data, e->left.sym->name);
+ fn(data, "!=");
+ fn(data, e->right.sym->name);
+ break;
+ case E_OR:
+ expr_print(e->left.expr, fn, data, E_OR);
+ fn(data, " || ");
+ expr_print(e->right.expr, fn, data, E_OR);
+ break;
+ case E_AND:
+ expr_print(e->left.expr, fn, data, E_AND);
+ fn(data, " && ");
+ expr_print(e->right.expr, fn, data, E_AND);
+ break;
+ case E_CHOICE:
+ fn(data, e->right.sym->name);
+ if (e->left.expr) {
+ fn(data, " ^ ");
+ expr_print(e->left.expr, fn, data, E_CHOICE);
+ }
+ break;
+ case E_RANGE:
+ fn(data, "[");
+ fn(data, e->left.sym->name);
+ fn(data, " ");
+ fn(data, e->right.sym->name);
+ fn(data, "]");
+ break;
+ default:
+ {
+ char buf[32];
+ sprintf(buf, "<unknown type %d>", e->type);
+ fn(data, buf);
+ break;
+ }
+ }
+ if (expr_compare_type(prevtoken, e->type) > 0)
+ fn(data, ")");
+}
+
+static void expr_print_file_helper(void *data, const char *str)
+{
+ fwrite(str, strlen(str), 1, data);
+}
+
+void expr_fprint(struct expr *e, FILE *out)
+{
+ expr_print(e, expr_print_file_helper, out, E_NONE);
+}
+
+static void expr_print_gstr_helper(void *data, const char *str)
+{
+ str_append((struct gstr*)data, str);
+}
+
+void expr_gstr_print(struct expr *e, struct gstr *gs)
+{
+ expr_print(e, expr_print_gstr_helper, gs, E_NONE);
+}
diff --git a/scripts/config/expr.h b/scripts/config/expr.h
new file mode 100644
index 0000000000..1b36ef18c4
--- /dev/null
+++ b/scripts/config/expr.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#ifndef EXPR_H
+#define EXPR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
+
+struct file {
+ struct file *next;
+ struct file *parent;
+ char *name;
+ int lineno;
+ int flags;
+};
+
+#define FILE_BUSY 0x0001
+#define FILE_SCANNED 0x0002
+#define FILE_PRINTED 0x0004
+
+typedef enum tristate {
+ no, mod, yes
+} tristate;
+
+enum expr_type {
+ E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_CHOICE, E_SYMBOL, E_RANGE
+};
+
+union expr_data {
+ struct expr *expr;
+ struct symbol *sym;
+};
+
+struct expr {
+ enum expr_type type;
+ union expr_data left, right;
+};
+
+#define E_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2))
+#define E_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2))
+#define E_NOT(dep) (2-(dep))
+
+struct expr_value {
+ struct expr *expr;
+ tristate tri;
+};
+
+struct symbol_value {
+ void *val;
+ tristate tri;
+};
+
+enum symbol_type {
+ S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER
+};
+
+struct symbol {
+ struct symbol *next;
+ char *name;
+ char *help;
+ enum symbol_type type;
+ struct symbol_value curr, user;
+ tristate visible;
+ int flags;
+ struct property *prop;
+ struct expr *dep, *dep2;
+ struct expr_value rev_dep;
+};
+
+#define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
+
+#define SYMBOL_YES 0x0001
+#define SYMBOL_MOD 0x0002
+#define SYMBOL_NO 0x0004
+#define SYMBOL_CONST 0x0007
+#define SYMBOL_CHECK 0x0008
+#define SYMBOL_CHOICE 0x0010
+#define SYMBOL_CHOICEVAL 0x0020
+#define SYMBOL_PRINTED 0x0040
+#define SYMBOL_VALID 0x0080
+#define SYMBOL_OPTIONAL 0x0100
+#define SYMBOL_WRITE 0x0200
+#define SYMBOL_CHANGED 0x0400
+#define SYMBOL_NEW 0x0800
+#define SYMBOL_AUTO 0x1000
+#define SYMBOL_CHECKED 0x2000
+#define SYMBOL_WARNED 0x8000
+
+#define SYMBOL_MAXLENGTH 256
+#define SYMBOL_HASHSIZE 257
+#define SYMBOL_HASHMASK 0xff
+
+enum prop_type {
+ P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE, P_SELECT, P_RANGE
+};
+
+struct property {
+ struct property *next;
+ struct symbol *sym;
+ enum prop_type type;
+ const char *text;
+ struct expr_value visible;
+ struct expr *expr;
+ struct menu *menu;
+ struct file *file;
+ int lineno;
+};
+
+#define for_all_properties(sym, st, tok) \
+ for (st = sym->prop; st; st = st->next) \
+ if (st->type == (tok))
+#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)
+#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)
+#define for_all_prompts(sym, st) \
+ for (st = sym->prop; st; st = st->next) \
+ if (st->text)
+
+struct menu {
+ struct menu *next;
+ struct menu *parent;
+ struct menu *list;
+ struct symbol *sym;
+ struct property *prompt;
+ struct expr *dep;
+ unsigned int flags;
+ //char *help;
+ struct file *file;
+ int lineno;
+ void *data;
+};
+
+#define MENU_CHANGED 0x0001
+#define MENU_ROOT 0x0002
+
+#ifndef SWIG
+
+extern struct file *file_list;
+extern struct file *current_file;
+struct file *lookup_file(const char *name);
+
+extern struct symbol symbol_yes, symbol_no, symbol_mod;
+extern struct symbol *modules_sym;
+extern int cdebug;
+struct expr *expr_alloc_symbol(struct symbol *sym);
+struct expr *expr_alloc_one(enum expr_type type, struct expr *ce);
+struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2);
+struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);
+struct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
+struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
+struct expr *expr_copy(struct expr *org);
+void expr_free(struct expr *e);
+int expr_eq(struct expr *e1, struct expr *e2);
+void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
+tristate expr_calc_value(struct expr *e);
+struct expr *expr_eliminate_yn(struct expr *e);
+struct expr *expr_trans_bool(struct expr *e);
+struct expr *expr_eliminate_dups(struct expr *e);
+struct expr *expr_transform(struct expr *e);
+int expr_contains_symbol(struct expr *dep, struct symbol *sym);
+bool expr_depends_symbol(struct expr *dep, struct symbol *sym);
+struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2);
+struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2);
+void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2);
+struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
+
+void expr_fprint(struct expr *e, FILE *out);
+struct gstr; /* forward */
+void expr_gstr_print(struct expr *e, struct gstr *gs);
+
+static inline int expr_is_yes(struct expr *e)
+{
+ return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);
+}
+
+static inline int expr_is_no(struct expr *e)
+{
+ return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EXPR_H */
diff --git a/scripts/config/kconfig_load.c b/scripts/config/kconfig_load.c
new file mode 100644
index 0000000000..dbdcaad823
--- /dev/null
+++ b/scripts/config/kconfig_load.c
@@ -0,0 +1,35 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "lkc.h"
+
+#define P(name,type,arg) type (*name ## _p) arg
+#include "lkc_proto.h"
+#undef P
+
+void kconfig_load(void)
+{
+ void *handle;
+ char *error;
+
+ handle = dlopen("./libkconfig.so", RTLD_LAZY);
+ if (!handle) {
+ handle = dlopen("./scripts/kconfig/libkconfig.so", RTLD_LAZY);
+ if (!handle) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(1);
+ }
+ }
+
+#define P(name,type,arg) \
+{ \
+ name ## _p = dlsym(handle, #name); \
+ if ((error = dlerror())) { \
+ fprintf(stderr, "%s\n", error); \
+ exit(1); \
+ } \
+}
+#include "lkc_proto.h"
+#undef P
+}
diff --git a/scripts/config/lex.backup b/scripts/config/lex.backup
new file mode 100644
index 0000000000..afb1b53c7b
--- /dev/null
+++ b/scripts/config/lex.backup
@@ -0,0 +1 @@
+No backing up.
diff --git a/scripts/config/lex.zconf.c_shipped b/scripts/config/lex.zconf.c_shipped
new file mode 100644
index 0000000000..5e01ee5318
--- /dev/null
+++ b/scripts/config/lex.zconf.c_shipped
@@ -0,0 +1,2338 @@
+
+#line 3 "lex.zconf.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 31
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <glob.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE zconfrestart(zconfin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int zconfleng;
+
+extern FILE *zconfin, *zconfout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ #define YY_LESS_LINENO(n)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up zconftext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = (yy_hold_char); \
+ YY_RESTORE_YY_MORE_OFFSET \
+ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up zconftext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr) )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef unsigned int yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via zconfrestart()), so that the user can continue scanning by
+ * just pointing zconfin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when zconftext is formed. */
+static char yy_hold_char;
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+int zconfleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow zconfwrap()'s to do buffer switches
+ * instead of setting up a fresh zconfin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void zconfrestart (FILE *input_file );
+void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer );
+YY_BUFFER_STATE zconf_create_buffer (FILE *file,int size );
+void zconf_delete_buffer (YY_BUFFER_STATE b );
+void zconf_flush_buffer (YY_BUFFER_STATE b );
+void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer );
+void zconfpop_buffer_state (void );
+
+static void zconfensure_buffer_stack (void );
+static void zconf_load_buffer_state (void );
+static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file );
+
+#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size );
+YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str );
+YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len );
+
+void *zconfalloc (yy_size_t );
+void *zconfrealloc (void *,yy_size_t );
+void zconffree (void * );
+
+#define yy_new_buffer zconf_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ zconfensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ zconf_create_buffer(zconfin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ zconfensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ zconf_create_buffer(zconfin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define zconfwrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+FILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int zconflineno;
+
+int zconflineno = 1;
+
+extern char *zconftext;
+#define yytext_ptr zconftext
+static yyconst flex_int16_t yy_nxt[][17] =
+ {
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0
+ },
+
+ {
+ 11, 12, 13, 14, 12, 12, 15, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12
+ },
+
+ {
+ 11, 12, 13, 14, 12, 12, 15, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12
+ },
+
+ {
+ 11, 16, 16, 17, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 18, 16, 16, 16
+ },
+
+ {
+ 11, 16, 16, 17, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 18, 16, 16, 16
+
+ },
+
+ {
+ 11, 19, 20, 21, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19
+ },
+
+ {
+ 11, 19, 20, 21, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19
+ },
+
+ {
+ 11, 22, 22, 23, 22, 24, 22, 22, 24, 22,
+ 22, 22, 22, 22, 22, 25, 22
+ },
+
+ {
+ 11, 22, 22, 23, 22, 24, 22, 22, 24, 22,
+ 22, 22, 22, 22, 22, 25, 22
+ },
+
+ {
+ 11, 26, 26, 27, 28, 29, 30, 31, 29, 32,
+ 33, 34, 35, 35, 36, 37, 38
+
+ },
+
+ {
+ 11, 26, 26, 27, 28, 29, 30, 31, 29, 32,
+ 33, 34, 35, 35, 36, 37, 38
+ },
+
+ {
+ -11, -11, -11, -11, -11, -11, -11, -11, -11, -11,
+ -11, -11, -11, -11, -11, -11, -11
+ },
+
+ {
+ 11, -12, -12, -12, -12, -12, -12, -12, -12, -12,
+ -12, -12, -12, -12, -12, -12, -12
+ },
+
+ {
+ 11, -13, 39, 40, -13, -13, 41, -13, -13, -13,
+ -13, -13, -13, -13, -13, -13, -13
+ },
+
+ {
+ 11, -14, -14, -14, -14, -14, -14, -14, -14, -14,
+ -14, -14, -14, -14, -14, -14, -14
+
+ },
+
+ {
+ 11, 42, 42, 43, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42
+ },
+
+ {
+ 11, -16, -16, -16, -16, -16, -16, -16, -16, -16,
+ -16, -16, -16, -16, -16, -16, -16
+ },
+
+ {
+ 11, -17, -17, -17, -17, -17, -17, -17, -17, -17,
+ -17, -17, -17, -17, -17, -17, -17
+ },
+
+ {
+ 11, -18, -18, -18, -18, -18, -18, -18, -18, -18,
+ -18, -18, -18, 44, -18, -18, -18
+ },
+
+ {
+ 11, 45, 45, -19, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45
+
+ },
+
+ {
+ 11, -20, 46, 47, -20, -20, -20, -20, -20, -20,
+ -20, -20, -20, -20, -20, -20, -20
+ },
+
+ {
+ 11, 48, -21, -21, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48
+ },
+
+ {
+ 11, 49, 49, 50, 49, -22, 49, 49, -22, 49,
+ 49, 49, 49, 49, 49, -22, 49
+ },
+
+ {
+ 11, -23, -23, -23, -23, -23, -23, -23, -23, -23,
+ -23, -23, -23, -23, -23, -23, -23
+ },
+
+ {
+ 11, -24, -24, -24, -24, -24, -24, -24, -24, -24,
+ -24, -24, -24, -24, -24, -24, -24
+
+ },
+
+ {
+ 11, 51, 51, 52, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51
+ },
+
+ {
+ 11, -26, -26, -26, -26, -26, -26, -26, -26, -26,
+ -26, -26, -26, -26, -26, -26, -26
+ },
+
+ {
+ 11, -27, -27, -27, -27, -27, -27, -27, -27, -27,
+ -27, -27, -27, -27, -27, -27, -27
+ },
+
+ {
+ 11, -28, -28, -28, -28, -28, -28, -28, -28, -28,
+ -28, -28, -28, -28, 53, -28, -28
+ },
+
+ {
+ 11, -29, -29, -29, -29, -29, -29, -29, -29, -29,
+ -29, -29, -29, -29, -29, -29, -29
+
+ },
+
+ {
+ 11, 54, 54, -30, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54
+ },
+
+ {
+ 11, -31, -31, -31, -31, -31, -31, 55, -31, -31,
+ -31, -31, -31, -31, -31, -31, -31
+ },
+
+ {
+ 11, -32, -32, -32, -32, -32, -32, -32, -32, -32,
+ -32, -32, -32, -32, -32, -32, -32
+ },
+
+ {
+ 11, -33, -33, -33, -33, -33, -33, -33, -33, -33,
+ -33, -33, -33, -33, -33, -33, -33
+ },
+
+ {
+ 11, -34, -34, -34, -34, -34, -34, -34, -34, -34,
+ -34, 56, 57, 57, -34, -34, -34
+
+ },
+
+ {
+ 11, -35, -35, -35, -35, -35, -35, -35, -35, -35,
+ -35, 57, 57, 57, -35, -35, -35
+ },
+
+ {
+ 11, -36, -36, -36, -36, -36, -36, -36, -36, -36,
+ -36, -36, -36, -36, -36, -36, -36
+ },
+
+ {
+ 11, -37, -37, 58, -37, -37, -37, -37, -37, -37,
+ -37, -37, -37, -37, -37, -37, -37
+ },
+
+ {
+ 11, -38, -38, -38, -38, -38, -38, -38, -38, -38,
+ -38, -38, -38, -38, -38, -38, 59
+ },
+
+ {
+ 11, -39, 39, 40, -39, -39, 41, -39, -39, -39,
+ -39, -39, -39, -39, -39, -39, -39
+
+ },
+
+ {
+ 11, -40, -40, -40, -40, -40, -40, -40, -40, -40,
+ -40, -40, -40, -40, -40, -40, -40
+ },
+
+ {
+ 11, 42, 42, 43, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42
+ },
+
+ {
+ 11, 42, 42, 43, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42
+ },
+
+ {
+ 11, -43, -43, -43, -43, -43, -43, -43, -43, -43,
+ -43, -43, -43, -43, -43, -43, -43
+ },
+
+ {
+ 11, -44, -44, -44, -44, -44, -44, -44, -44, -44,
+ -44, -44, -44, 44, -44, -44, -44
+
+ },
+
+ {
+ 11, 45, 45, -45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45
+ },
+
+ {
+ 11, -46, 46, 47, -46, -46, -46, -46, -46, -46,
+ -46, -46, -46, -46, -46, -46, -46
+ },
+
+ {
+ 11, 48, -47, -47, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48
+ },
+
+ {
+ 11, -48, -48, -48, -48, -48, -48, -48, -48, -48,
+ -48, -48, -48, -48, -48, -48, -48
+ },
+
+ {
+ 11, 49, 49, 50, 49, -49, 49, 49, -49, 49,
+ 49, 49, 49, 49, 49, -49, 49
+
+ },
+
+ {
+ 11, -50, -50, -50, -50, -50, -50, -50, -50, -50,
+ -50, -50, -50, -50, -50, -50, -50
+ },
+
+ {
+ 11, -51, -51, 52, -51, -51, -51, -51, -51, -51,
+ -51, -51, -51, -51, -51, -51, -51
+ },
+
+ {
+ 11, -52, -52, -52, -52, -52, -52, -52, -52, -52,
+ -52, -52, -52, -52, -52, -52, -52
+ },
+
+ {
+ 11, -53, -53, -53, -53, -53, -53, -53, -53, -53,
+ -53, -53, -53, -53, -53, -53, -53
+ },
+
+ {
+ 11, 54, 54, -54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54
+
+ },
+
+ {
+ 11, -55, -55, -55, -55, -55, -55, -55, -55, -55,
+ -55, -55, -55, -55, -55, -55, -55
+ },
+
+ {
+ 11, -56, -56, -56, -56, -56, -56, -56, -56, -56,
+ -56, 60, 57, 57, -56, -56, -56
+ },
+
+ {
+ 11, -57, -57, -57, -57, -57, -57, -57, -57, -57,
+ -57, 57, 57, 57, -57, -57, -57
+ },
+
+ {
+ 11, -58, -58, -58, -58, -58, -58, -58, -58, -58,
+ -58, -58, -58, -58, -58, -58, -58
+ },
+
+ {
+ 11, -59, -59, -59, -59, -59, -59, -59, -59, -59,
+ -59, -59, -59, -59, -59, -59, -59
+
+ },
+
+ {
+ 11, -60, -60, -60, -60, -60, -60, -60, -60, -60,
+ -60, 57, 57, 57, -60, -60, -60
+ },
+
+ } ;
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[] );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up zconftext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ (yytext_ptr) = yy_bp; \
+ zconfleng = (size_t) (yy_cp - yy_bp); \
+ (yy_hold_char) = *yy_cp; \
+ *yy_cp = '\0'; \
+ (yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 33
+#define YY_END_OF_BUFFER 34
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[61] =
+ { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 34, 5, 4, 2, 3, 7, 8, 6, 32, 29,
+ 31, 24, 28, 27, 26, 22, 17, 13, 16, 20,
+ 22, 11, 12, 19, 19, 14, 22, 22, 4, 2,
+ 3, 3, 1, 6, 32, 29, 31, 30, 24, 23,
+ 26, 25, 15, 20, 9, 19, 19, 21, 10, 18
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 4, 5, 6, 1, 1, 7, 8, 9,
+ 10, 1, 1, 1, 11, 12, 12, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 1, 1, 1,
+ 14, 1, 1, 1, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 1, 15, 1, 1, 13, 1, 13, 13, 13, 13,
+
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 1, 16, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+extern int zconf_flex_debug;
+int zconf_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *zconftext;
+
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+#define START_STRSIZE 16
+
+static struct {
+ struct file *file;
+ int lineno;
+} current_pos;
+
+static char *text;
+static int text_size, text_asize;
+
+struct buffer {
+ struct buffer *parent;
+ YY_BUFFER_STATE state;
+};
+
+struct buffer *current_buf;
+
+static int last_ts, first_ts;
+
+static void zconf_endhelp(void);
+static void zconf_endfile(void);
+
+void new_string(void)
+{
+ text = malloc(START_STRSIZE);
+ text_asize = START_STRSIZE;
+ text_size = 0;
+ *text = 0;
+}
+
+void append_string(const char *str, int size)
+{
+ int new_size = text_size + size + 1;
+ if (new_size > text_asize) {
+ new_size += START_STRSIZE - 1;
+ new_size &= -START_STRSIZE;
+ text = realloc(text, new_size);
+ text_asize = new_size;
+ }
+ memcpy(text + text_size, str, size);
+ text_size += size;
+ text[text_size] = 0;
+}
+
+void alloc_string(const char *str, int size)
+{
+ text = malloc(size + 1);
+ memcpy(text, str, size);
+ text[size] = 0;
+}
+
+#define INITIAL 0
+#define COMMAND 1
+#define HELP 2
+#define STRING 3
+#define PARAM 4
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int zconfwrap (void );
+#else
+extern int zconfwrap (void );
+#endif
+#endif
+
+ static void yyunput (int c,char *buf_ptr );
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( zconftext, zconfleng, 1, zconfout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ errno=0; \
+ while ( (result = read( fileno(zconfin), (char *) buf, max_size )) < 0 ) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(zconfin); \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int zconflex (void);
+
+#define YY_DECL int zconflex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after zconftext and zconfleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+ int str = 0;
+ int ts, i;
+
+ if ( (yy_init) )
+ {
+ (yy_init) = 0;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! (yy_start) )
+ (yy_start) = 1; /* first start state */
+
+ if ( ! zconfin )
+ zconfin = stdin;
+
+ if ( ! zconfout )
+ zconfout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ zconfensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ zconf_create_buffer(zconfin,YY_BUF_SIZE );
+ }
+
+ zconf_load_buffer_state( );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = (yy_c_buf_p);
+
+ /* Support of zconftext. */
+ *yy_cp = (yy_hold_char);
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = (yy_start);
+yy_match:
+ while ( (yy_current_state = yy_nxt[yy_current_state][ yy_ec[YY_SC_TO_UI(*yy_cp)] ]) > 0 )
+ ++yy_cp;
+
+ yy_current_state = -yy_current_state;
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+
+ YY_DO_BEFORE_ACTION;
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+case 1:
+/* rule 1 can match eol */
+case 2:
+/* rule 2 can match eol */
+YY_RULE_SETUP
+{
+ current_file->lineno++;
+ return T_EOL;
+}
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+{
+ BEGIN(COMMAND);
+}
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+{
+ unput(zconftext[0]);
+ BEGIN(COMMAND);
+}
+ YY_BREAK
+
+case 6:
+YY_RULE_SETUP
+{
+ struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
+ BEGIN(PARAM);
+ current_pos.file = current_file;
+ current_pos.lineno = current_file->lineno;
+ if (id && id->flags & TF_COMMAND) {
+ zconflval.id = id;
+ return id->token;
+ }
+ alloc_string(zconftext, zconfleng);
+ zconflval.string = text;
+ return T_WORD;
+ }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+
+ YY_BREAK
+case 8:
+/* rule 8 can match eol */
+YY_RULE_SETUP
+{
+ BEGIN(INITIAL);
+ current_file->lineno++;
+ return T_EOL;
+ }
+ YY_BREAK
+
+case 9:
+YY_RULE_SETUP
+return T_AND;
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+return T_OR;
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+return T_OPEN_PAREN;
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+return T_CLOSE_PAREN;
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+return T_NOT;
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+return T_EQUAL;
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+return T_UNEQUAL;
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+{
+ str = zconftext[0];
+ new_string();
+ BEGIN(STRING);
+ }
+ YY_BREAK
+case 17:
+/* rule 17 can match eol */
+YY_RULE_SETUP
+BEGIN(INITIAL); current_file->lineno++; return T_EOL;
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+/* ignore */
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+{
+ struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
+ if (id && id->flags & TF_PARAM) {
+ zconflval.id = id;
+ return id->token;
+ }
+ alloc_string(zconftext, zconfleng);
+ zconflval.string = text;
+ return T_WORD;
+ }
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+/* comment */
+ YY_BREAK
+case 21:
+/* rule 21 can match eol */
+YY_RULE_SETUP
+current_file->lineno++;
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+
+ YY_BREAK
+case YY_STATE_EOF(PARAM):
+{
+ BEGIN(INITIAL);
+ }
+ YY_BREAK
+
+case 23:
+/* rule 23 can match eol */
+*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up zconftext again */
+YY_RULE_SETUP
+{
+ append_string(zconftext, zconfleng);
+ zconflval.string = text;
+ return T_WORD_QUOTE;
+ }
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+{
+ append_string(zconftext, zconfleng);
+ }
+ YY_BREAK
+case 25:
+/* rule 25 can match eol */
+*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up zconftext again */
+YY_RULE_SETUP
+{
+ append_string(zconftext + 1, zconfleng - 1);
+ zconflval.string = text;
+ return T_WORD_QUOTE;
+ }
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+{
+ append_string(zconftext + 1, zconfleng - 1);
+ }
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+{
+ if (str == zconftext[0]) {
+ BEGIN(PARAM);
+ zconflval.string = text;
+ return T_WORD_QUOTE;
+ } else
+ append_string(zconftext, 1);
+ }
+ YY_BREAK
+case 28:
+/* rule 28 can match eol */
+YY_RULE_SETUP
+{
+ printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
+ current_file->lineno++;
+ BEGIN(INITIAL);
+ return T_EOL;
+ }
+ YY_BREAK
+case YY_STATE_EOF(STRING):
+{
+ BEGIN(INITIAL);
+ }
+ YY_BREAK
+
+case 29:
+YY_RULE_SETUP
+{
+ ts = 0;
+ for (i = 0; i < zconfleng; i++) {
+ if (zconftext[i] == '\t')
+ ts = (ts & ~7) + 8;
+ else
+ ts++;
+ }
+ last_ts = ts;
+ if (first_ts) {
+ if (ts < first_ts) {
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+ ts -= first_ts;
+ while (ts > 8) {
+ append_string(" ", 8);
+ ts -= 8;
+ }
+ append_string(" ", ts);
+ }
+ }
+ YY_BREAK
+case 30:
+/* rule 30 can match eol */
+*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up zconftext again */
+YY_RULE_SETUP
+{
+ current_file->lineno++;
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+ YY_BREAK
+case 31:
+/* rule 31 can match eol */
+YY_RULE_SETUP
+{
+ current_file->lineno++;
+ append_string("\n", 1);
+ }
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+{
+ append_string(zconftext, zconfleng);
+ if (!first_ts)
+ first_ts = last_ts;
+ }
+ YY_BREAK
+case YY_STATE_EOF(HELP):
+{
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+ YY_BREAK
+
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(COMMAND):
+{
+ if (current_file) {
+ zconf_endfile();
+ return T_EOL;
+ }
+ fclose(zconfin);
+ yyterminate();
+}
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+YY_FATAL_ERROR( "flex scanner jammed" );
+ YY_BREAK
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = (yy_hold_char);
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed zconfin at a new source and called
+ * zconflex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = zconfin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++(yy_c_buf_p);
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = (yy_c_buf_p);
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ (yy_did_buffer_switch_on_eof) = 0;
+
+ if ( zconfwrap( ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * zconftext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) =
+ (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ (yy_c_buf_p) =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of zconflex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = (yytext_ptr);
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+ else
+ {
+ size_t num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+ int yy_c_buf_p_offset =
+ (int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ zconfrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ (yy_n_chars), num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ if ( (yy_n_chars) == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ zconfrestart(zconfin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ (yy_n_chars) += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+ (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (void)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = (yy_start);
+
+ for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+ {
+ yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
+{
+ register int yy_is_jam;
+
+ yy_current_state = yy_nxt[yy_current_state][1];
+ yy_is_jam = (yy_current_state <= 0);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+ static void yyunput (int c, register char * yy_bp )
+{
+ register char *yy_cp;
+
+ yy_cp = (yy_c_buf_p);
+
+ /* undo effects of setting up zconftext */
+ *yy_cp = (yy_hold_char);
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = (yy_n_chars) + 2;
+ register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+ register char *source =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+ (yytext_ptr) = yy_bp;
+ (yy_hold_char) = *yy_cp;
+ (yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (void)
+#else
+ static int input (void)
+#endif
+
+{
+ int c;
+
+ *(yy_c_buf_p) = (yy_hold_char);
+
+ if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ /* This was really a NUL. */
+ *(yy_c_buf_p) = '\0';
+
+ else
+ { /* need more input */
+ int offset = (yy_c_buf_p) - (yytext_ptr);
+ ++(yy_c_buf_p);
+
+ switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ zconfrestart(zconfin );
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( zconfwrap( ) )
+ return EOF;
+
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) = (yytext_ptr) + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+ *(yy_c_buf_p) = '\0'; /* preserve zconftext */
+ (yy_hold_char) = *++(yy_c_buf_p);
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ *
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void zconfrestart (FILE * input_file )
+{
+
+ if ( ! YY_CURRENT_BUFFER ){
+ zconfensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ zconf_create_buffer(zconfin,YY_BUF_SIZE );
+ }
+
+ zconf_init_buffer(YY_CURRENT_BUFFER,input_file );
+ zconf_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ *
+ */
+ void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer )
+{
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * zconfpop_buffer_state();
+ * zconfpush_buffer_state(new_buffer);
+ */
+ zconfensure_buffer_stack ();
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ zconf_load_buffer_state( );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (zconfwrap()) processing, but the only time this flag
+ * is looked at is after zconfwrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void zconf_load_buffer_state (void)
+{
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ zconfin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ (yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ *
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE zconf_create_buffer (FILE * file, int size )
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) zconfalloc(b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ zconf_init_buffer(b,file );
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with zconf_create_buffer()
+ *
+ */
+ void zconf_delete_buffer (YY_BUFFER_STATE b )
+{
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ zconffree((void *) b->yy_ch_buf );
+
+ zconffree((void *) b );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a zconfrestart() or at EOF.
+ */
+ static void zconf_init_buffer (YY_BUFFER_STATE b, FILE * file )
+
+{
+ int oerrno = errno;
+
+ zconf_flush_buffer(b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then zconf_init_buffer was _probably_
+ * called from zconfrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ *
+ */
+ void zconf_flush_buffer (YY_BUFFER_STATE b )
+{
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ zconf_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ *
+ */
+void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+ if (new_buffer == NULL)
+ return;
+
+ zconfensure_buffer_stack();
+
+ /* This block is copied from zconf_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ (yy_buffer_stack_top)++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from zconf_switch_to_buffer. */
+ zconf_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ *
+ */
+void zconfpop_buffer_state (void)
+{
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ zconf_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if ((yy_buffer_stack_top) > 0)
+ --(yy_buffer_stack_top);
+
+ if (YY_CURRENT_BUFFER) {
+ zconf_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void zconfensure_buffer_stack (void)
+{
+ int num_to_alloc;
+
+ if (!(yy_buffer_stack)) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ (yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+
+ memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ (yy_buffer_stack_max) = num_to_alloc;
+ (yy_buffer_stack_top) = 0;
+ return;
+ }
+
+ if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = (yy_buffer_stack_max) + grow_size;
+ (yy_buffer_stack) = (struct yy_buffer_state**)zconfrealloc
+ ((yy_buffer_stack),
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+
+ /* zero only the new slots.*/
+ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+ (yy_buffer_stack_max) = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size )
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ zconf_switch_to_buffer(b );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to zconflex() will
+ * scan from a @e copy of @a str.
+ * @param str a NUL-terminated string to scan
+ *
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * zconf_scan_bytes() instead.
+ */
+YY_BUFFER_STATE zconf_scan_string (yyconst char * yy_str )
+{
+
+ return zconf_scan_bytes(yy_str,strlen(yy_str) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to zconflex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE zconf_scan_bytes (yyconst char * bytes, int len )
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = len + 2;
+ buf = (char *) zconfalloc(n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" );
+
+ for ( i = 0; i < len; ++i )
+ buf[i] = bytes[i];
+
+ buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = zconf_scan_buffer(buf,n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in zconf_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up zconftext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ zconftext[zconfleng] = (yy_hold_char); \
+ (yy_c_buf_p) = zconftext + yyless_macro_arg; \
+ (yy_hold_char) = *(yy_c_buf_p); \
+ *(yy_c_buf_p) = '\0'; \
+ zconfleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ *
+ */
+int zconfget_lineno (void)
+{
+
+ return zconflineno;
+}
+
+/** Get the input stream.
+ *
+ */
+FILE *zconfget_in (void)
+{
+ return zconfin;
+}
+
+/** Get the output stream.
+ *
+ */
+FILE *zconfget_out (void)
+{
+ return zconfout;
+}
+
+/** Get the length of the current token.
+ *
+ */
+int zconfget_leng (void)
+{
+ return zconfleng;
+}
+
+/** Get the current token.
+ *
+ */
+
+char *zconfget_text (void)
+{
+ return zconftext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ *
+ */
+void zconfset_lineno (int line_number )
+{
+
+ zconflineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ *
+ * @see zconf_switch_to_buffer
+ */
+void zconfset_in (FILE * in_str )
+{
+ zconfin = in_str ;
+}
+
+void zconfset_out (FILE * out_str )
+{
+ zconfout = out_str ;
+}
+
+int zconfget_debug (void)
+{
+ return zconf_flex_debug;
+}
+
+void zconfset_debug (int bdebug )
+{
+ zconf_flex_debug = bdebug ;
+}
+
+/* zconflex_destroy is for both reentrant and non-reentrant scanners. */
+int zconflex_destroy (void)
+{
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ zconf_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ zconfpop_buffer_state();
+ }
+
+ /* Destroy the stack itself. */
+ zconffree((yy_buffer_stack) );
+ (yy_buffer_stack) = NULL;
+
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *zconfalloc (yy_size_t size )
+{
+ return (void *) malloc( size );
+}
+
+void *zconfrealloc (void * ptr, yy_size_t size )
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void zconffree (void * ptr )
+{
+ free( (char *) ptr ); /* see zconfrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#undef YY_NEW_FILE
+#undef YY_FLUSH_BUFFER
+#undef yy_set_bol
+#undef yy_new_buffer
+#undef yy_set_interactive
+#undef yytext_ptr
+#undef YY_DO_BEFORE_ACTION
+
+#ifdef YY_DECL_IS_OURS
+#undef YY_DECL_IS_OURS
+#undef YY_DECL
+#endif
+
+void zconf_starthelp(void)
+{
+ new_string();
+ last_ts = first_ts = 0;
+ BEGIN(HELP);
+}
+
+static void zconf_endhelp(void)
+{
+ zconflval.string = text;
+ BEGIN(INITIAL);
+}
+
+/*
+ * Try to open specified file with following names:
+ * ./name
+ * $(srctree)/name
+ * The latter is used when srctree is separate from objtree
+ * when compiling the kernel.
+ * Return NULL if file is not found.
+ */
+FILE *zconf_fopen(const char *name)
+{
+ char *env, fullname[PATH_MAX+1];
+ FILE *f;
+
+ f = fopen(name, "r");
+ if (!f && name[0] != '/') {
+ env = getenv(SRCTREE);
+ if (env) {
+ sprintf(fullname, "%s/%s", env, name);
+ f = fopen(fullname, "r");
+ }
+ }
+ return f;
+}
+
+void zconf_initscan(const char *name)
+{
+ zconfin = zconf_fopen(name);
+ if (!zconfin) {
+ printf("can't find file %s\n", name);
+ exit(1);
+ }
+
+ current_buf = malloc(sizeof(*current_buf));
+ memset(current_buf, 0, sizeof(*current_buf));
+
+ current_file = file_lookup(name);
+ current_file->lineno = 1;
+ current_file->flags = FILE_BUSY;
+}
+
+void zconf_nextfile(const char *name)
+{
+ size_t i;
+ int retval;
+ glob_t files;
+ char *filename;
+ struct file *file;
+ struct buffer *buf;
+
+ retval = glob(name, GLOB_ERR | GLOB_MARK, NULL, &files);
+ if (retval == GLOB_NOSPACE || retval == GLOB_ABORTED || retval == GLOB_NOMATCH) {
+ printf("%s:%d: glob failed: %s \"%s\"\n", zconf_curname(), zconf_lineno(),
+ retval == GLOB_NOSPACE ? "failed to allocate memory" :
+ retval == GLOB_ABORTED ? "read error" : "no match",
+ name);
+ exit(1);
+ }
+
+ for (i = files.gl_pathc-1; i != (size_t)-1; --i) {
+ filename = files.gl_pathv[i];
+
+ file = file_lookup(filename);
+ buf = malloc(sizeof(*buf));
+ memset(buf, 0, sizeof(*buf));
+ current_buf->state = YY_CURRENT_BUFFER;
+ zconfin = zconf_fopen(filename);
+ if (!zconfin) {
+ printf("%s:%d: can't open file \"%s\"\n",
+ zconf_curname(), zconf_lineno(), filename);
+ exit(1);
+ }
+ zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE));
+ buf->parent = current_buf;
+ current_buf = buf;
+
+ if (file->flags & FILE_BUSY) {
+ printf("recursive scan (%s)?\n", filename);
+ exit(1);
+ }
+ if (file->flags & FILE_SCANNED) {
+ printf("file %s already scanned?\n", filename);
+ exit(1);
+ }
+ file->flags |= FILE_BUSY;
+ file->lineno = 1;
+ file->parent = current_file;
+ current_file = file;
+ }
+}
+
+static void zconf_endfile(void)
+{
+ struct buffer *parent;
+
+ current_file->flags |= FILE_SCANNED;
+ current_file->flags &= ~FILE_BUSY;
+ current_file = current_file->parent;
+
+ parent = current_buf->parent;
+ if (parent) {
+ fclose(zconfin);
+ zconf_delete_buffer(YY_CURRENT_BUFFER);
+ zconf_switch_to_buffer(parent->state);
+ }
+ free(current_buf);
+ current_buf = parent;
+}
+
+int zconf_lineno(void)
+{
+ return current_pos.lineno;
+}
+
+char *zconf_curname(void)
+{
+ return current_pos.file ? current_pos.file->name : "<none>";
+}
+
diff --git a/scripts/config/lkc.h b/scripts/config/lkc.h
new file mode 100644
index 0000000000..527f60c99c
--- /dev/null
+++ b/scripts/config/lkc.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#ifndef LKC_H
+#define LKC_H
+
+#include "expr.h"
+
+#ifndef KBUILD_NO_NLS
+# include <libintl.h>
+#else
+# define gettext(Msgid) ((const char *) (Msgid))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef LKC_DIRECT_LINK
+#define P(name,type,arg) extern type name arg
+#else
+#include "lkc_defs.h"
+#define P(name,type,arg) extern type (*name ## _p) arg
+#endif
+#include "lkc_proto.h"
+#undef P
+
+#define SRCTREE "srctree"
+
+#define PACKAGE "linux"
+#define LOCALEDIR "/usr/share/locale"
+
+#define _(text) gettext(text)
+#define N_(text) (text)
+
+
+#define TF_COMMAND 0x0001
+#define TF_PARAM 0x0002
+
+struct kconf_id {
+ int name;
+ int token;
+ unsigned int flags;
+ enum symbol_type stype;
+};
+
+int zconfparse(void);
+void zconfdump(FILE *out);
+
+extern int zconfdebug;
+void zconf_starthelp(void);
+FILE *zconf_fopen(const char *name);
+void zconf_initscan(const char *name);
+void zconf_nextfile(const char *name);
+int zconf_lineno(void);
+char *zconf_curname(void);
+
+/* confdata.c */
+extern const char conf_def_filename[];
+
+char *conf_get_default_confname(void);
+
+/* kconfig_load.c */
+void kconfig_load(void);
+
+/* menu.c */
+void menu_init(void);
+struct menu *menu_add_menu(void);
+void menu_end_menu(void);
+void menu_add_entry(struct symbol *sym);
+void menu_end_entry(void);
+void menu_add_dep(struct expr *dep);
+struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep);
+struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
+void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
+void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
+void menu_finalize(struct menu *parent);
+void menu_set_type(int type);
+
+/* util.c */
+struct file *file_lookup(const char *name);
+int file_write_dep(const char *name);
+
+struct gstr {
+ size_t len;
+ char *s;
+};
+struct gstr str_new(void);
+struct gstr str_assign(const char *s);
+void str_free(struct gstr *gs);
+void str_append(struct gstr *gs, const char *s);
+void str_printf(struct gstr *gs, const char *fmt, ...);
+const char *str_get(struct gstr *gs);
+
+/* symbol.c */
+void sym_init(void);
+void sym_clear_all_valid(void);
+void sym_set_changed(struct symbol *sym);
+struct symbol *sym_check_deps(struct symbol *sym);
+struct property *prop_alloc(enum prop_type type, struct symbol *sym);
+struct symbol *prop_get_symbol(struct property *prop);
+
+static inline tristate sym_get_tristate_value(struct symbol *sym)
+{
+ return sym->curr.tri;
+}
+
+
+static inline struct symbol *sym_get_choice_value(struct symbol *sym)
+{
+ return (struct symbol *)sym->curr.val;
+}
+
+static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval)
+{
+ return sym_set_tristate_value(chval, yes);
+}
+
+static inline bool sym_is_choice(struct symbol *sym)
+{
+ return sym->flags & SYMBOL_CHOICE ? true : false;
+}
+
+static inline bool sym_is_choice_value(struct symbol *sym)
+{
+ return sym->flags & SYMBOL_CHOICEVAL ? true : false;
+}
+
+static inline bool sym_is_optional(struct symbol *sym)
+{
+ return sym->flags & SYMBOL_OPTIONAL ? true : false;
+}
+
+static inline bool sym_has_value(struct symbol *sym)
+{
+ return sym->flags & SYMBOL_NEW ? false : true;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LKC_H */
diff --git a/scripts/config/lkc_proto.h b/scripts/config/lkc_proto.h
new file mode 100644
index 0000000000..15fafd01b0
--- /dev/null
+++ b/scripts/config/lkc_proto.h
@@ -0,0 +1,42 @@
+
+/* confdata.c */
+P(conf_parse,void,(const char *name));
+P(conf_read,int,(const char *name));
+P(conf_reset,void,(void));
+P(conf_read_simple,int,(const char *name));
+P(conf_write,int,(const char *name));
+
+/* menu.c */
+P(rootmenu,struct menu,);
+
+P(menu_is_visible,bool,(struct menu *menu));
+P(menu_get_prompt,const char *,(struct menu *menu));
+P(menu_get_root_menu,struct menu *,(struct menu *menu));
+P(menu_get_parent_menu,struct menu *,(struct menu *menu));
+
+/* symbol.c */
+P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
+P(sym_change_count,int,);
+
+P(sym_lookup,struct symbol *,(const char *name, int isconst));
+P(sym_find,struct symbol *,(const char *name));
+P(sym_re_search,struct symbol **,(const char *pattern));
+P(sym_type_name,const char *,(enum symbol_type type));
+P(sym_calc_value,void,(struct symbol *sym));
+P(sym_get_type,enum symbol_type,(struct symbol *sym));
+P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri));
+P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri));
+P(sym_toggle_tristate_value,tristate,(struct symbol *sym));
+P(sym_string_valid,bool,(struct symbol *sym, const char *newval));
+P(sym_string_within_range,bool,(struct symbol *sym, const char *str));
+P(sym_set_string_value,bool,(struct symbol *sym, const char *newval));
+P(sym_is_changable,bool,(struct symbol *sym));
+P(sym_get_choice_prop,struct property *,(struct symbol *sym));
+P(sym_get_default_prop,struct property *,(struct symbol *sym));
+P(sym_get_string_value,const char *,(struct symbol *sym));
+
+P(prop_get_type_name,const char *,(enum prop_type type));
+
+/* expr.c */
+P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2));
+P(expr_print,void,(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken));
diff --git a/scripts/config/lxdialog/BIG.FAT.WARNING b/scripts/config/lxdialog/BIG.FAT.WARNING
new file mode 100644
index 0000000000..a8999d82bd
--- /dev/null
+++ b/scripts/config/lxdialog/BIG.FAT.WARNING
@@ -0,0 +1,4 @@
+This is NOT the official version of dialog. This version has been
+significantly modified from the original. It is for use by the Linux
+kernel configuration script. Please do not bother Savio Lam with
+questions about this program.
diff --git a/scripts/config/lxdialog/Makefile b/scripts/config/lxdialog/Makefile
new file mode 100644
index 0000000000..a82b2bac99
--- /dev/null
+++ b/scripts/config/lxdialog/Makefile
@@ -0,0 +1,20 @@
+# Makefile to build lxdialog package
+#
+
+all: lxdialog
+
+# Use reursively expanded variables so we do not call gcc unless
+# we really need to do so. (Do not call gcc as part of make mrproper)
+CFLAGS := $(shell sh check-lxdialog.sh -ccflags)
+LIBS := $(shell sh check-lxdialog.sh -ldflags gcc)
+
+always := $(hostprogs-y) dochecklxdialog
+
+%.o: %.c
+ $(CC) -c $(CFLAGS) -o $@ $<
+
+lxdialog: checklist.o menubox.o textbox.o yesno.o inputbox.o util.o lxdialog.o msgbox.o
+ $(CC) -o $@ $^ $(LIBS)
+
+clean:
+ rm -f *.o lxdialog
diff --git a/scripts/config/lxdialog/check-lxdialog.sh b/scripts/config/lxdialog/check-lxdialog.sh
new file mode 100644
index 0000000000..275e395422
--- /dev/null
+++ b/scripts/config/lxdialog/check-lxdialog.sh
@@ -0,0 +1,90 @@
+#!/bin/sh
+# Check ncurses compatibility
+
+# What library to link
+ldflags()
+{
+ for ext in so dylib; do
+ for dir in "" /usr/local/lib /opt/local/lib; do
+ $cc ${dir:+-L$dir} -print-file-name=libncursesw.$ext | grep -q /
+ if [ $? -eq 0 ]; then
+ echo $dir '-lncursesw'
+ exit
+ fi
+ $cc ${dir:+-L$dir} -print-file-name=libncurses.$ext | grep -q /
+ if [ $? -eq 0 ]; then
+ echo $dir '-lncurses'
+ exit
+ fi
+ $cc ${dir:+-L$dir} -print-file-name=libcurses.$ext | grep -q /
+ if [ $? -eq 0 ]; then
+ echo $dir '-lcurses'
+ exit
+ fi
+ done
+ done
+ exit 1
+}
+
+# Where is ncurses.h?
+ccflags()
+{
+ if [ -f /usr/include/ncurses/ncurses.h ]; then
+ echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
+ elif [ -f /usr/include/ncurses/curses.h ]; then
+ echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"'
+ elif [ -f /opt/local/include/ncurses/ncurses.h ]; then
+ echo '-I/opt/local/include/ncurses -DCURSES_LOC="<ncurses/ncurses.h>"'
+ elif [ -f /usr/include/ncurses.h ]; then
+ echo '-DCURSES_LOC="<ncurses.h>"'
+ else
+ echo '-DCURSES_LOC="<curses.h>"'
+ fi
+}
+
+# Temp file, try to clean up after us
+tmp=.lxdialog.tmp
+trap "rm -f $tmp" 0 1 2 3 15
+
+# Check if we can link to ncurses
+check() {
+ echo "main() {}" | $cc -xc - -o $tmp 2> /dev/null
+ if [ $? != 0 ]; then
+ echo " *** Unable to find the ncurses libraries." 1>&2
+ echo " *** make menuconfig require the ncurses libraries" 1>&2
+ echo " *** " 1>&2
+ echo " *** Install ncurses (ncurses-devel) and try again" 1>&2
+ echo " *** " 1>&2
+ exit 1
+ fi
+}
+
+usage() {
+ printf "Usage: $0 [-check compiler options|-header|-library]\n"
+}
+
+if [ $# -eq 0 ]; then
+ usage
+ exit 1
+fi
+
+cc=""
+case "$1" in
+ "-check")
+ shift
+ cc="$@"
+ check
+ ;;
+ "-ccflags")
+ ccflags
+ ;;
+ "-ldflags")
+ shift
+ cc="$@"
+ ldflags
+ ;;
+ "*")
+ usage
+ exit 1
+ ;;
+esac
diff --git a/scripts/config/lxdialog/checklist.c b/scripts/config/lxdialog/checklist.c
new file mode 100644
index 0000000000..db07ae73e0
--- /dev/null
+++ b/scripts/config/lxdialog/checklist.c
@@ -0,0 +1,334 @@
+/*
+ * checklist.c -- implements the checklist box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
+ * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+static int list_width, check_x, item_x;
+
+/*
+ * Print list item
+ */
+static void print_item(WINDOW * win, const char *item, int status, int choice,
+ int selected)
+{
+ int i;
+
+ /* Clear 'residue' of last item */
+ wattrset(win, menubox_attr);
+ wmove(win, choice, 0);
+ for (i = 0; i < list_width; i++)
+ waddch(win, ' ');
+
+ wmove(win, choice, check_x);
+ wattrset(win, selected ? check_selected_attr : check_attr);
+ wprintw(win, "(%c)", status ? 'X' : ' ');
+
+ wattrset(win, selected ? tag_selected_attr : tag_attr);
+ mvwaddch(win, choice, item_x, item[0]);
+ wattrset(win, selected ? item_selected_attr : item_attr);
+ waddstr(win, (char *)item + 1);
+ if (selected) {
+ wmove(win, choice, check_x + 1);
+ wrefresh(win);
+ }
+}
+
+/*
+ * Print the scroll indicators.
+ */
+static void print_arrows(WINDOW * win, int choice, int item_no, int scroll,
+ int y, int x, int height)
+{
+ wmove(win, y, x);
+
+ if (scroll > 0) {
+ wattrset(win, uarrow_attr);
+ waddch(win, ACS_UARROW);
+ waddstr(win, "(-)");
+ } else {
+ wattrset(win, menubox_attr);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ }
+
+ y = y + height + 1;
+ wmove(win, y, x);
+
+ if ((height < item_no) && (scroll + choice < item_no - 1)) {
+ wattrset(win, darrow_attr);
+ waddch(win, ACS_DARROW);
+ waddstr(win, "(+)");
+ } else {
+ wattrset(win, menubox_border_attr);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ }
+}
+
+/*
+ * Display the termination buttons
+ */
+static void print_buttons(WINDOW * dialog, int height, int width, int selected)
+{
+ int x = width / 2 - 11;
+ int y = height - 2;
+
+ print_button(dialog, "Select", y, x, selected == 0);
+ print_button(dialog, " Help ", y, x + 14, selected == 1);
+
+ wmove(dialog, y, x + 1 + 14 * selected);
+ wrefresh(dialog);
+}
+
+/*
+ * Display a dialog box with a list of options that can be turned on or off
+ * in the style of radiolist (only one option turned on at a time).
+ */
+int dialog_checklist(const char *title, const char *prompt, int height,
+ int width, int list_height, int item_no,
+ const char *const *items)
+{
+ int i, x, y, box_x, box_y;
+ int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status;
+ WINDOW *dialog, *list;
+
+ /* Allocate space for storing item on/off status */
+ if ((status = malloc(sizeof(int) * item_no)) == NULL) {
+ endwin();
+ fprintf(stderr,
+ "\nCan't allocate memory in dialog_checklist().\n");
+ exit(-1);
+ }
+
+ /* Initializes status */
+ for (i = 0; i < item_no; i++) {
+ status[i] = !strcasecmp(items[i * 3 + 2], "on");
+ if ((!choice && status[i])
+ || !strcasecmp(items[i * 3 + 2], "selected"))
+ choice = i + 1;
+ }
+ if (choice)
+ choice--;
+
+ max_choice = MIN(list_height, item_no);
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow(stdscr, y, x, height, width);
+
+ dialog = newwin(height, width, y, x);
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset(dialog, border_attr);
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+
+ print_title(dialog, title, width);
+
+ wattrset(dialog, dialog_attr);
+ print_autowrap(dialog, prompt, width - 2, 1, 3);
+
+ list_width = width - 6;
+ box_y = height - list_height - 5;
+ box_x = (width - list_width) / 2 - 1;
+
+ /* create new window for the list */
+ list = subwin(dialog, list_height, list_width, y + box_y + 1,
+ x + box_x + 1);
+
+ keypad(list, TRUE);
+
+ /* draw a box around the list items */
+ draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2,
+ menubox_border_attr, menubox_attr);
+
+ /* Find length of longest item in order to center checklist */
+ check_x = 0;
+ for (i = 0; i < item_no; i++)
+ check_x = MAX(check_x, +strlen(items[i * 3 + 1]) + 4);
+
+ check_x = (list_width - check_x) / 2;
+ item_x = check_x + 4;
+
+ if (choice >= list_height) {
+ scroll = choice - list_height + 1;
+ choice -= scroll;
+ }
+
+ /* Print the list */
+ for (i = 0; i < max_choice; i++) {
+ print_item(list, items[(scroll + i) * 3 + 1],
+ status[i + scroll], i, i == choice);
+ }
+
+ print_arrows(dialog, choice, item_no, scroll,
+ box_y, box_x + check_x + 5, list_height);
+
+ print_buttons(dialog, height, width, 0);
+
+ wnoutrefresh(list);
+ wnoutrefresh(dialog);
+ doupdate();
+
+ while (key != ESC) {
+ key = wgetch(dialog);
+
+ for (i = 0; i < max_choice; i++)
+ if (toupper(key) ==
+ toupper(items[(scroll + i) * 3 + 1][0]))
+ break;
+
+ if (i < max_choice || key == KEY_UP || key == KEY_DOWN ||
+ key == '+' || key == '-') {
+ if (key == KEY_UP || key == '-') {
+ if (!choice) {
+ if (!scroll)
+ continue;
+ /* Scroll list down */
+ if (list_height > 1) {
+ /* De-highlight current first item */
+ print_item(list, items[scroll * 3 + 1],
+ status[scroll], 0, FALSE);
+ scrollok(list, TRUE);
+ wscrl(list, -1);
+ scrollok(list, FALSE);
+ }
+ scroll--;
+ print_item(list, items[scroll * 3 + 1], status[scroll], 0, TRUE);
+ wnoutrefresh(list);
+
+ print_arrows(dialog, choice, item_no,
+ scroll, box_y, box_x + check_x + 5, list_height);
+
+ wrefresh(dialog);
+
+ continue; /* wait for another key press */
+ } else
+ i = choice - 1;
+ } else if (key == KEY_DOWN || key == '+') {
+ if (choice == max_choice - 1) {
+ if (scroll + choice >= item_no - 1)
+ continue;
+ /* Scroll list up */
+ if (list_height > 1) {
+ /* De-highlight current last item before scrolling up */
+ print_item(list, items[(scroll + max_choice - 1) * 3 + 1],
+ status[scroll + max_choice - 1],
+ max_choice - 1, FALSE);
+ scrollok(list, TRUE);
+ wscrl(list, 1);
+ scrollok(list, FALSE);
+ }
+ scroll++;
+ print_item(list, items[(scroll + max_choice - 1) * 3 + 1],
+ status[scroll + max_choice - 1], max_choice - 1, TRUE);
+ wnoutrefresh(list);
+
+ print_arrows(dialog, choice, item_no,
+ scroll, box_y, box_x + check_x + 5, list_height);
+
+ wrefresh(dialog);
+
+ continue; /* wait for another key press */
+ } else
+ i = choice + 1;
+ }
+ if (i != choice) {
+ /* De-highlight current item */
+ print_item(list, items[(scroll + choice) * 3 + 1],
+ status[scroll + choice], choice, FALSE);
+ /* Highlight new item */
+ choice = i;
+ print_item(list, items[(scroll + choice) * 3 + 1],
+ status[scroll + choice], choice, TRUE);
+ wnoutrefresh(list);
+ wrefresh(dialog);
+ }
+ continue; /* wait for another key press */
+ }
+ switch (key) {
+ case 'H':
+ case 'h':
+ case '?':
+ fprintf(stderr, "%s", items[(scroll + choice) * 3]);
+ delwin(dialog);
+ free(status);
+ return 1;
+ case TAB:
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ button = ((key == KEY_LEFT ? --button : ++button) < 0)
+ ? 1 : (button > 1 ? 0 : button);
+
+ print_buttons(dialog, height, width, button);
+ wrefresh(dialog);
+ break;
+ case 'S':
+ case 's':
+ case ' ':
+ case '\n':
+ if (!button) {
+ if (!status[scroll + choice]) {
+ for (i = 0; i < item_no; i++)
+ status[i] = 0;
+ status[scroll + choice] = 1;
+ for (i = 0; i < max_choice; i++)
+ print_item(list, items[(scroll + i) * 3 + 1],
+ status[scroll + i], i, i == choice);
+ }
+ wnoutrefresh(list);
+ wrefresh(dialog);
+
+ for (i = 0; i < item_no; i++)
+ if (status[i])
+ fprintf(stderr, "%s", items[i * 3]);
+ } else
+ fprintf(stderr, "%s", items[(scroll + choice) * 3]);
+ delwin(dialog);
+ free(status);
+ return button;
+ case 'X':
+ case 'x':
+ key = ESC;
+ case ESC:
+ break;
+ }
+
+ /* Now, update everything... */
+ doupdate();
+ }
+
+ delwin(dialog);
+ free(status);
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/config/lxdialog/colors.h b/scripts/config/lxdialog/colors.h
new file mode 100644
index 0000000000..db071df12b
--- /dev/null
+++ b/scripts/config/lxdialog/colors.h
@@ -0,0 +1,154 @@
+/*
+ * colors.h -- color attribute definitions
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * 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.
+ */
+
+/*
+ * Default color definitions
+ *
+ * *_FG = foreground
+ * *_BG = background
+ * *_HL = highlight?
+ */
+#define SCREEN_FG COLOR_CYAN
+#define SCREEN_BG COLOR_BLUE
+#define SCREEN_HL TRUE
+
+#define SHADOW_FG COLOR_BLACK
+#define SHADOW_BG COLOR_BLACK
+#define SHADOW_HL TRUE
+
+#define DIALOG_FG COLOR_BLACK
+#define DIALOG_BG COLOR_WHITE
+#define DIALOG_HL FALSE
+
+#define TITLE_FG COLOR_YELLOW
+#define TITLE_BG COLOR_WHITE
+#define TITLE_HL TRUE
+
+#define BORDER_FG COLOR_WHITE
+#define BORDER_BG COLOR_WHITE
+#define BORDER_HL TRUE
+
+#define BUTTON_ACTIVE_FG COLOR_WHITE
+#define BUTTON_ACTIVE_BG COLOR_BLUE
+#define BUTTON_ACTIVE_HL TRUE
+
+#define BUTTON_INACTIVE_FG COLOR_BLACK
+#define BUTTON_INACTIVE_BG COLOR_WHITE
+#define BUTTON_INACTIVE_HL FALSE
+
+#define BUTTON_KEY_ACTIVE_FG COLOR_WHITE
+#define BUTTON_KEY_ACTIVE_BG COLOR_BLUE
+#define BUTTON_KEY_ACTIVE_HL TRUE
+
+#define BUTTON_KEY_INACTIVE_FG COLOR_RED
+#define BUTTON_KEY_INACTIVE_BG COLOR_WHITE
+#define BUTTON_KEY_INACTIVE_HL FALSE
+
+#define BUTTON_LABEL_ACTIVE_FG COLOR_YELLOW
+#define BUTTON_LABEL_ACTIVE_BG COLOR_BLUE
+#define BUTTON_LABEL_ACTIVE_HL TRUE
+
+#define BUTTON_LABEL_INACTIVE_FG COLOR_BLACK
+#define BUTTON_LABEL_INACTIVE_BG COLOR_WHITE
+#define BUTTON_LABEL_INACTIVE_HL TRUE
+
+#define INPUTBOX_FG COLOR_BLACK
+#define INPUTBOX_BG COLOR_WHITE
+#define INPUTBOX_HL FALSE
+
+#define INPUTBOX_BORDER_FG COLOR_BLACK
+#define INPUTBOX_BORDER_BG COLOR_WHITE
+#define INPUTBOX_BORDER_HL FALSE
+
+#define SEARCHBOX_FG COLOR_BLACK
+#define SEARCHBOX_BG COLOR_WHITE
+#define SEARCHBOX_HL FALSE
+
+#define SEARCHBOX_TITLE_FG COLOR_YELLOW
+#define SEARCHBOX_TITLE_BG COLOR_WHITE
+#define SEARCHBOX_TITLE_HL TRUE
+
+#define SEARCHBOX_BORDER_FG COLOR_WHITE
+#define SEARCHBOX_BORDER_BG COLOR_WHITE
+#define SEARCHBOX_BORDER_HL TRUE
+
+#define POSITION_INDICATOR_FG COLOR_YELLOW
+#define POSITION_INDICATOR_BG COLOR_WHITE
+#define POSITION_INDICATOR_HL TRUE
+
+#define MENUBOX_FG COLOR_BLACK
+#define MENUBOX_BG COLOR_WHITE
+#define MENUBOX_HL FALSE
+
+#define MENUBOX_BORDER_FG COLOR_WHITE
+#define MENUBOX_BORDER_BG COLOR_WHITE
+#define MENUBOX_BORDER_HL TRUE
+
+#define ITEM_FG COLOR_BLACK
+#define ITEM_BG COLOR_WHITE
+#define ITEM_HL FALSE
+
+#define ITEM_SELECTED_FG COLOR_WHITE
+#define ITEM_SELECTED_BG COLOR_BLUE
+#define ITEM_SELECTED_HL TRUE
+
+#define TAG_FG COLOR_YELLOW
+#define TAG_BG COLOR_WHITE
+#define TAG_HL TRUE
+
+#define TAG_SELECTED_FG COLOR_YELLOW
+#define TAG_SELECTED_BG COLOR_BLUE
+#define TAG_SELECTED_HL TRUE
+
+#define TAG_KEY_FG COLOR_YELLOW
+#define TAG_KEY_BG COLOR_WHITE
+#define TAG_KEY_HL TRUE
+
+#define TAG_KEY_SELECTED_FG COLOR_YELLOW
+#define TAG_KEY_SELECTED_BG COLOR_BLUE
+#define TAG_KEY_SELECTED_HL TRUE
+
+#define CHECK_FG COLOR_BLACK
+#define CHECK_BG COLOR_WHITE
+#define CHECK_HL FALSE
+
+#define CHECK_SELECTED_FG COLOR_WHITE
+#define CHECK_SELECTED_BG COLOR_BLUE
+#define CHECK_SELECTED_HL TRUE
+
+#define UARROW_FG COLOR_GREEN
+#define UARROW_BG COLOR_WHITE
+#define UARROW_HL TRUE
+
+#define DARROW_FG COLOR_GREEN
+#define DARROW_BG COLOR_WHITE
+#define DARROW_HL TRUE
+
+/* End of default color definitions */
+
+#define C_ATTR(x,y) ((x ? A_BOLD : 0) | COLOR_PAIR((y)))
+#define COLOR_NAME_LEN 10
+#define COLOR_COUNT 8
+
+/*
+ * Global variables
+ */
+
+extern int color_table[][3];
diff --git a/scripts/config/lxdialog/dialog.h b/scripts/config/lxdialog/dialog.h
new file mode 100644
index 0000000000..af3cf716e2
--- /dev/null
+++ b/scripts/config/lxdialog/dialog.h
@@ -0,0 +1,177 @@
+/*
+ * dialog.h -- common declarations for all dialog modules
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * 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 <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __sun__
+#define CURS_MACROS
+#endif
+#include CURSES_LOC
+
+/*
+ * Colors in ncurses 1.9.9e do not work properly since foreground and
+ * background colors are OR'd rather than separately masked. This version
+ * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible
+ * with standard curses. The simplest fix (to make this work with standard
+ * curses) uses the wbkgdset() function, not used in the original hack.
+ * Turn it off if we're building with 1.9.9e, since it just confuses things.
+ */
+#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
+#define OLD_NCURSES 1
+#undef wbkgdset
+#define wbkgdset(w,p) /*nothing */
+#else
+#define OLD_NCURSES 0
+#endif
+
+#define TR(params) _tracef params
+
+#define ESC 27
+#define TAB 9
+#define MAX_LEN 2048
+#define BUF_SIZE (10*1024)
+#define MIN(x,y) (x < y ? x : y)
+#define MAX(x,y) (x > y ? x : y)
+
+#ifndef ACS_ULCORNER
+#define ACS_ULCORNER '+'
+#endif
+#ifndef ACS_LLCORNER
+#define ACS_LLCORNER '+'
+#endif
+#ifndef ACS_URCORNER
+#define ACS_URCORNER '+'
+#endif
+#ifndef ACS_LRCORNER
+#define ACS_LRCORNER '+'
+#endif
+#ifndef ACS_HLINE
+#define ACS_HLINE '-'
+#endif
+#ifndef ACS_VLINE
+#define ACS_VLINE '|'
+#endif
+#ifndef ACS_LTEE
+#define ACS_LTEE '+'
+#endif
+#ifndef ACS_RTEE
+#define ACS_RTEE '+'
+#endif
+#ifndef ACS_UARROW
+#define ACS_UARROW '^'
+#endif
+#ifndef ACS_DARROW
+#define ACS_DARROW 'v'
+#endif
+
+/*
+ * Attribute names
+ */
+#define screen_attr attributes[0]
+#define shadow_attr attributes[1]
+#define dialog_attr attributes[2]
+#define title_attr attributes[3]
+#define border_attr attributes[4]
+#define button_active_attr attributes[5]
+#define button_inactive_attr attributes[6]
+#define button_key_active_attr attributes[7]
+#define button_key_inactive_attr attributes[8]
+#define button_label_active_attr attributes[9]
+#define button_label_inactive_attr attributes[10]
+#define inputbox_attr attributes[11]
+#define inputbox_border_attr attributes[12]
+#define searchbox_attr attributes[13]
+#define searchbox_title_attr attributes[14]
+#define searchbox_border_attr attributes[15]
+#define position_indicator_attr attributes[16]
+#define menubox_attr attributes[17]
+#define menubox_border_attr attributes[18]
+#define item_attr attributes[19]
+#define item_selected_attr attributes[20]
+#define tag_attr attributes[21]
+#define tag_selected_attr attributes[22]
+#define tag_key_attr attributes[23]
+#define tag_key_selected_attr attributes[24]
+#define check_attr attributes[25]
+#define check_selected_attr attributes[26]
+#define uarrow_attr attributes[27]
+#define darrow_attr attributes[28]
+
+/* number of attributes */
+#define ATTRIBUTE_COUNT 29
+
+/*
+ * Global variables
+ */
+extern bool use_colors;
+extern bool use_shadow;
+
+extern chtype attributes[];
+
+extern const char *backtitle;
+
+/*
+ * Function prototypes
+ */
+extern void create_rc(const char *filename);
+extern int parse_rc(void);
+
+void init_dialog(void);
+void end_dialog(void);
+void attr_clear(WINDOW * win, int height, int width, chtype attr);
+void dialog_clear(void);
+void color_setup(void);
+void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x);
+void print_button(WINDOW * win, const char *label, int y, int x, int selected);
+void print_title(WINDOW *dialog, const char *title, int width);
+void draw_box(WINDOW * win, int y, int x, int height, int width, chtype box,
+ chtype border);
+void draw_shadow(WINDOW * win, int y, int x, int height, int width);
+
+int first_alpha(const char *string, const char *exempt);
+int dialog_yesno(const char *title, const char *prompt, int height, int width);
+int dialog_msgbox(const char *title, const char *prompt, int height,
+ int width, int pause);
+int dialog_textbox(const char *title, const char *file, int height, int width);
+int dialog_menu(const char *title, const char *prompt, int height, int width,
+ int menu_height, const char *choice, int item_no,
+ const char *const *items);
+int dialog_checklist(const char *title, const char *prompt, int height,
+ int width, int list_height, int item_no,
+ const char *const *items);
+extern char dialog_input_result[];
+int dialog_inputbox(const char *title, const char *prompt, int height,
+ int width, const char *init);
+
+/*
+ * This is the base for fictitious keys, which activate
+ * the buttons.
+ *
+ * Mouse-generated keys are the following:
+ * -- the first 32 are used as numbers, in addition to '0'-'9'
+ * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
+ * -- uppercase chars are used to invoke the button (M_EVENT + 'O')
+ */
+#define M_EVENT (KEY_MAX+1)
diff --git a/scripts/config/lxdialog/inputbox.c b/scripts/config/lxdialog/inputbox.c
new file mode 100644
index 0000000000..779503726b
--- /dev/null
+++ b/scripts/config/lxdialog/inputbox.c
@@ -0,0 +1,224 @@
+/*
+ * inputbox.c -- implements the input box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+char dialog_input_result[MAX_LEN + 1];
+
+/*
+ * Print the termination buttons
+ */
+static void print_buttons(WINDOW * dialog, int height, int width, int selected)
+{
+ int x = width / 2 - 11;
+ int y = height - 2;
+
+ print_button(dialog, " Ok ", y, x, selected == 0);
+ print_button(dialog, " Help ", y, x + 14, selected == 1);
+
+ wmove(dialog, y, x + 1 + 14 * selected);
+ wrefresh(dialog);
+}
+
+/*
+ * Display a dialog box for inputing a string
+ */
+int dialog_inputbox(const char *title, const char *prompt, int height, int width,
+ const char *init)
+{
+ int i, x, y, box_y, box_x, box_width;
+ int input_x = 0, scroll = 0, key = 0, button = -1;
+ char *instr = dialog_input_result;
+ WINDOW *dialog;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow(stdscr, y, x, height, width);
+
+ dialog = newwin(height, width, y, x);
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset(dialog, border_attr);
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+
+ print_title(dialog, title, width);
+
+ wattrset(dialog, dialog_attr);
+ print_autowrap(dialog, prompt, width - 2, 1, 3);
+
+ /* Draw the input field box */
+ box_width = width - 6;
+ getyx(dialog, y, x);
+ box_y = y + 2;
+ box_x = (width - box_width) / 2;
+ draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, border_attr, dialog_attr);
+
+ print_buttons(dialog, height, width, 0);
+
+ /* Set up the initial value */
+ wmove(dialog, box_y, box_x);
+ wattrset(dialog, inputbox_attr);
+
+ if (!init)
+ instr[0] = '\0';
+ else
+ strcpy(instr, init);
+
+ input_x = strlen(instr);
+
+ if (input_x >= box_width) {
+ scroll = input_x - box_width + 1;
+ input_x = box_width - 1;
+ for (i = 0; i < box_width - 1; i++)
+ waddch(dialog, instr[scroll + i]);
+ } else {
+ waddstr(dialog, instr);
+ }
+
+ wmove(dialog, box_y, box_x + input_x);
+
+ wrefresh(dialog);
+
+ while (key != ESC) {
+ key = wgetch(dialog);
+
+ if (button == -1) { /* Input box selected */
+ switch (key) {
+ case TAB:
+ case KEY_UP:
+ case KEY_DOWN:
+ break;
+ case KEY_LEFT:
+ continue;
+ case KEY_RIGHT:
+ continue;
+ case KEY_BACKSPACE:
+ case 127:
+ if (input_x || scroll) {
+ wattrset(dialog, inputbox_attr);
+ if (!input_x) {
+ scroll = scroll < box_width - 1 ? 0 : scroll - (box_width - 1);
+ wmove(dialog, box_y, box_x);
+ for (i = 0; i < box_width; i++)
+ waddch(dialog,
+ instr[scroll + input_x + i] ?
+ instr[scroll + input_x + i] : ' ');
+ input_x = strlen(instr) - scroll;
+ } else
+ input_x--;
+ instr[scroll + input_x] = '\0';
+ mvwaddch(dialog, box_y, input_x + box_x, ' ');
+ wmove(dialog, box_y, input_x + box_x);
+ wrefresh(dialog);
+ }
+ continue;
+ default:
+ if (key < 0x100 && isprint(key)) {
+ if (scroll + input_x < MAX_LEN) {
+ wattrset(dialog, inputbox_attr);
+ instr[scroll + input_x] = key;
+ instr[scroll + input_x + 1] = '\0';
+ if (input_x == box_width - 1) {
+ scroll++;
+ wmove(dialog, box_y, box_x);
+ for (i = 0; i < box_width - 1; i++)
+ waddch(dialog, instr [scroll + i]);
+ } else {
+ wmove(dialog, box_y, input_x++ + box_x);
+ waddch(dialog, key);
+ }
+ wrefresh(dialog);
+ } else
+ flash(); /* Alarm user about overflow */
+ continue;
+ }
+ }
+ }
+ switch (key) {
+ case 'O':
+ case 'o':
+ delwin(dialog);
+ return 0;
+ case 'H':
+ case 'h':
+ delwin(dialog);
+ return 1;
+ case KEY_UP:
+ case KEY_LEFT:
+ switch (button) {
+ case -1:
+ button = 1; /* Indicates "Cancel" button is selected */
+ print_buttons(dialog, height, width, 1);
+ break;
+ case 0:
+ button = -1; /* Indicates input box is selected */
+ print_buttons(dialog, height, width, 0);
+ wmove(dialog, box_y, box_x + input_x);
+ wrefresh(dialog);
+ break;
+ case 1:
+ button = 0; /* Indicates "OK" button is selected */
+ print_buttons(dialog, height, width, 0);
+ break;
+ }
+ break;
+ case TAB:
+ case KEY_DOWN:
+ case KEY_RIGHT:
+ switch (button) {
+ case -1:
+ button = 0; /* Indicates "OK" button is selected */
+ print_buttons(dialog, height, width, 0);
+ break;
+ case 0:
+ button = 1; /* Indicates "Cancel" button is selected */
+ print_buttons(dialog, height, width, 1);
+ break;
+ case 1:
+ button = -1; /* Indicates input box is selected */
+ print_buttons(dialog, height, width, 0);
+ wmove(dialog, box_y, box_x + input_x);
+ wrefresh(dialog);
+ break;
+ }
+ break;
+ case ' ':
+ case '\n':
+ delwin(dialog);
+ return (button == -1 ? 0 : button);
+ case 'X':
+ case 'x':
+ key = ESC;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin(dialog);
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/config/lxdialog/lxdialog.c b/scripts/config/lxdialog/lxdialog.c
new file mode 100644
index 0000000000..79f6c5fb5c
--- /dev/null
+++ b/scripts/config/lxdialog/lxdialog.c
@@ -0,0 +1,204 @@
+/*
+ * dialog - Display simple dialog boxes from shell scripts
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+static void Usage(const char *name);
+
+typedef int (jumperFn) (const char *title, int argc, const char *const *argv);
+
+struct Mode {
+ char *name;
+ int argmin, argmax, argmod;
+ jumperFn *jumper;
+};
+
+jumperFn j_menu, j_radiolist, j_yesno, j_textbox, j_inputbox;
+jumperFn j_msgbox, j_infobox;
+
+static struct Mode modes[] = {
+ {"--menu", 9, 0, 3, j_menu},
+ {"--radiolist", 9, 0, 3, j_radiolist},
+ {"--yesno", 5, 5, 1, j_yesno},
+ {"--textbox", 5, 5, 1, j_textbox},
+ {"--inputbox", 5, 6, 1, j_inputbox},
+ {"--msgbox", 5, 5, 1, j_msgbox},
+ {"--infobox", 5, 5, 1, j_infobox},
+ {NULL, 0, 0, 0, NULL}
+};
+
+static struct Mode *modePtr;
+
+#ifdef LOCALE
+#include <locale.h>
+#endif
+
+int main(int argc, const char *const *argv)
+{
+ int offset = 0, opt_clear = 0, end_common_opts = 0, retval;
+ const char *title = NULL;
+
+#ifdef LOCALE
+ (void)setlocale(LC_ALL, "");
+#endif
+
+#ifdef TRACE
+ trace(TRACE_CALLS | TRACE_UPDATE);
+#endif
+ if (argc < 2) {
+ Usage(argv[0]);
+ exit(-1);
+ }
+
+ while (offset < argc - 1 && !end_common_opts) { /* Common options */
+ if (!strcmp(argv[offset + 1], "--title")) {
+ if (argc - offset < 3 || title != NULL) {
+ Usage(argv[0]);
+ exit(-1);
+ } else {
+ title = argv[offset + 2];
+ offset += 2;
+ }
+ } else if (!strcmp(argv[offset + 1], "--backtitle")) {
+ if (backtitle != NULL) {
+ Usage(argv[0]);
+ exit(-1);
+ } else {
+ backtitle = argv[offset + 2];
+ offset += 2;
+ }
+ } else if (!strcmp(argv[offset + 1], "--clear")) {
+ if (opt_clear) { /* Hey, "--clear" can't appear twice! */
+ Usage(argv[0]);
+ exit(-1);
+ } else if (argc == 2) { /* we only want to clear the screen */
+ init_dialog();
+ refresh(); /* init_dialog() will clear the screen for us */
+ end_dialog();
+ return 0;
+ } else {
+ opt_clear = 1;
+ offset++;
+ }
+ } else /* no more common options */
+ end_common_opts = 1;
+ }
+
+ if (argc - 1 == offset) { /* no more options */
+ Usage(argv[0]);
+ exit(-1);
+ }
+ /* use a table to look for the requested mode, to avoid code duplication */
+
+ for (modePtr = modes; modePtr->name; modePtr++) /* look for the mode */
+ if (!strcmp(argv[offset + 1], modePtr->name))
+ break;
+
+ if (!modePtr->name)
+ Usage(argv[0]);
+ if (argc - offset < modePtr->argmin)
+ Usage(argv[0]);
+ if (modePtr->argmax && argc - offset > modePtr->argmax)
+ Usage(argv[0]);
+
+ init_dialog();
+ retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset);
+
+ if (opt_clear) { /* clear screen before exit */
+ attr_clear(stdscr, LINES, COLS, screen_attr);
+ refresh();
+ }
+ end_dialog();
+
+ exit(retval);
+}
+
+/*
+ * Print program usage
+ */
+static void Usage(const char *name)
+{
+ fprintf(stderr, "\
+\ndialog, by Savio Lam (lam836@cs.cuhk.hk).\
+\n patched by Stuart Herbert (S.Herbert@shef.ac.uk)\
+\n modified/gutted for use as a Linux kernel config tool by \
+\n William Roadcap (roadcapw@cfw.com)\
+\n\
+\n* Display dialog boxes from shell scripts *\
+\n\
+\nUsage: %s --clear\
+\n %s [--title <title>] [--backtitle <backtitle>] --clear <Box options>\
+\n\
+\nBox options:\
+\n\
+\n --menu <text> <height> <width> <menu height> <tag1> <item1>...\
+\n --radiolist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
+\n --textbox <file> <height> <width>\
+\n --inputbox <text> <height> <width> [<init>]\
+\n --yesno <text> <height> <width>\
+\n", name, name);
+ exit(-1);
+}
+
+/*
+ * These are the program jumpers
+ */
+
+int j_menu(const char *t, int ac, const char *const *av)
+{
+ return dialog_menu(t, av[2], atoi(av[3]), atoi(av[4]),
+ atoi(av[5]), av[6], (ac - 6) / 2, av + 7);
+}
+
+int j_radiolist(const char *t, int ac, const char *const *av)
+{
+ return dialog_checklist(t, av[2], atoi(av[3]), atoi(av[4]),
+ atoi(av[5]), (ac - 6) / 3, av + 6);
+}
+
+int j_textbox(const char *t, int ac, const char *const *av)
+{
+ return dialog_textbox(t, av[2], atoi(av[3]), atoi(av[4]));
+}
+
+int j_yesno(const char *t, int ac, const char *const *av)
+{
+ return dialog_yesno(t, av[2], atoi(av[3]), atoi(av[4]));
+}
+
+int j_inputbox(const char *t, int ac, const char *const *av)
+{
+ int ret = dialog_inputbox(t, av[2], atoi(av[3]), atoi(av[4]),
+ ac == 6 ? av[5] : (char *)NULL);
+ if (ret == 0)
+ fprintf(stderr, dialog_input_result);
+ return ret;
+}
+
+int j_msgbox(const char *t, int ac, const char *const *av)
+{
+ return dialog_msgbox(t, av[2], atoi(av[3]), atoi(av[4]), 1);
+}
+
+int j_infobox(const char *t, int ac, const char *const *av)
+{
+ return dialog_msgbox(t, av[2], atoi(av[3]), atoi(av[4]), 0);
+}
diff --git a/scripts/config/lxdialog/menubox.c b/scripts/config/lxdialog/menubox.c
new file mode 100644
index 0000000000..09512b5443
--- /dev/null
+++ b/scripts/config/lxdialog/menubox.c
@@ -0,0 +1,425 @@
+/*
+ * menubox.c -- implements the menu box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Changes by Clifford Wolf (god@clifford.at)
+ *
+ * [ 1998-06-13 ]
+ *
+ * *) A bugfix for the Page-Down problem
+ *
+ * *) Formerly when I used Page Down and Page Up, the cursor would be set
+ * to the first position in the menu box. Now lxdialog is a bit
+ * smarter and works more like other menu systems (just have a look at
+ * it).
+ *
+ * *) Formerly if I selected something my scrolling would be broken because
+ * lxdialog is re-invoked by the Menuconfig shell script, can't
+ * remember the last scrolling position, and just sets it so that the
+ * cursor is at the bottom of the box. Now it writes the temporary file
+ * lxdialog.scrltmp which contains this information. The file is
+ * deleted by lxdialog if the user leaves a submenu or enters a new
+ * one, but it would be nice if Menuconfig could make another "rm -f"
+ * just to be sure. Just try it out - you will recognise a difference!
+ *
+ * [ 1998-06-14 ]
+ *
+ * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
+ * and menus change their size on the fly.
+ *
+ * *) If for some reason the last scrolling position is not saved by
+ * lxdialog, it sets the scrolling so that the selected item is in the
+ * middle of the menu box, not at the bottom.
+ *
+ * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
+ * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
+ * This fixes a bug in Menuconfig where using ' ' to descend into menus
+ * would leave mis-synchronized lxdialog.scrltmp files lying around,
+ * fscanf would read in 'scroll', and eventually that value would get used.
+ */
+
+#include "dialog.h"
+
+#define ITEM_IDENT 1 /* Indent of menu entries. Fixed for all menus */
+static int menu_width;
+
+/*
+ * Print menu item
+ */
+static void do_print_item(WINDOW * win, const char *item, int choice,
+ int selected, int hotkey)
+{
+ int j;
+ char *menu_item = malloc(menu_width + 1);
+
+ strncpy(menu_item, item, menu_width - ITEM_IDENT);
+ menu_item[menu_width] = 0;
+ j = first_alpha(menu_item, "YyNnMmHh");
+
+ /* Clear 'residue' of last item */
+ wattrset(win, menubox_attr);
+ wmove(win, choice, 0);
+#if OLD_NCURSES
+ {
+ int i;
+ for (i = 0; i < menu_width; i++)
+ waddch(win, ' ');
+ }
+#else
+ wclrtoeol(win);
+#endif
+ wattrset(win, selected ? item_selected_attr : item_attr);
+ mvwaddstr(win, choice, ITEM_IDENT, menu_item);
+ if (hotkey) {
+ wattrset(win, selected ? tag_key_selected_attr : tag_key_attr);
+ mvwaddch(win, choice, ITEM_IDENT + j, menu_item[j]);
+ }
+ if (selected) {
+ wmove(win, choice, ITEM_IDENT + 1);
+ }
+ free(menu_item);
+ wrefresh(win);
+}
+
+#define print_item(index, choice, selected) \
+do {\
+ int hotkey = (items[(index) * 2][0] != ':'); \
+ do_print_item(menu, items[(index) * 2 + 1], choice, selected, hotkey); \
+} while (0)
+
+/*
+ * Print the scroll indicators.
+ */
+static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
+ int height)
+{
+ int cur_y, cur_x;
+
+ getyx(win, cur_y, cur_x);
+
+ wmove(win, y, x);
+
+ if (scroll > 0) {
+ wattrset(win, uarrow_attr);
+ waddch(win, ACS_UARROW);
+ waddstr(win, "(-)");
+ } else {
+ wattrset(win, menubox_attr);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ }
+
+ y = y + height + 1;
+ wmove(win, y, x);
+ wrefresh(win);
+
+ if ((height < item_no) && (scroll + height < item_no)) {
+ wattrset(win, darrow_attr);
+ waddch(win, ACS_DARROW);
+ waddstr(win, "(+)");
+ } else {
+ wattrset(win, menubox_border_attr);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ }
+
+ wmove(win, cur_y, cur_x);
+ wrefresh(win);
+}
+
+/*
+ * Display the termination buttons.
+ */
+static void print_buttons(WINDOW * win, int height, int width, int selected)
+{
+ int x = width / 2 - 16;
+ int y = height - 2;
+
+ print_button(win, "Select", y, x, selected == 0);
+ print_button(win, " Exit ", y, x + 12, selected == 1);
+ print_button(win, " Help ", y, x + 24, selected == 2);
+
+ wmove(win, y, x + 1 + 12 * selected);
+ wrefresh(win);
+}
+
+/* scroll up n lines (n may be negative) */
+static void do_scroll(WINDOW *win, int *scroll, int n)
+{
+ /* Scroll menu up */
+ scrollok(win, TRUE);
+ wscrl(win, n);
+ scrollok(win, FALSE);
+ *scroll = *scroll + n;
+ wrefresh(win);
+}
+
+/*
+ * Display a menu for choosing among a number of options
+ */
+int dialog_menu(const char *title, const char *prompt, int height, int width,
+ int menu_height, const char *current, int item_no,
+ const char *const *items)
+{
+ int i, j, x, y, box_x, box_y;
+ int key = 0, button = 0, scroll = 0, choice = 0;
+ int first_item = 0, max_choice;
+ WINDOW *dialog, *menu;
+ FILE *f;
+
+ max_choice = MIN(menu_height, item_no);
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow(stdscr, y, x, height, width);
+
+ dialog = newwin(height, width, y, x);
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset(dialog, border_attr);
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ wbkgdset(dialog, dialog_attr & A_COLOR);
+ waddch(dialog, ACS_RTEE);
+
+ print_title(dialog, title, width);
+
+ wattrset(dialog, dialog_attr);
+ print_autowrap(dialog, prompt, width - 2, 1, 3);
+
+ menu_width = width - 6;
+ box_y = height - menu_height - 5;
+ box_x = (width - menu_width) / 2 - 1;
+
+ /* create new window for the menu */
+ menu = subwin(dialog, menu_height, menu_width,
+ y + box_y + 1, x + box_x + 1);
+ keypad(menu, TRUE);
+
+ /* draw a box around the menu items */
+ draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2,
+ menubox_border_attr, menubox_attr);
+
+ /* Set choice to default item */
+ for (i = 0; i < item_no; i++)
+ if (strcmp(current, items[i * 2]) == 0)
+ choice = i;
+
+ /* get the scroll info from the temp file */
+ if ((f = fopen("lxdialog.scrltmp", "r")) != NULL) {
+ if ((fscanf(f, "%d\n", &scroll) == 1) && (scroll <= choice) &&
+ (scroll + max_choice > choice) && (scroll >= 0) &&
+ (scroll + max_choice <= item_no)) {
+ first_item = scroll;
+ choice = choice - scroll;
+ fclose(f);
+ } else {
+ scroll = 0;
+ remove("lxdialog.scrltmp");
+ fclose(f);
+ f = NULL;
+ }
+ }
+ if ((choice >= max_choice) || (f == NULL && choice >= max_choice / 2)) {
+ if (choice >= item_no - max_choice / 2)
+ scroll = first_item = item_no - max_choice;
+ else
+ scroll = first_item = choice - max_choice / 2;
+ choice = choice - scroll;
+ }
+
+ /* Print the menu */
+ for (i = 0; i < max_choice; i++) {
+ print_item(first_item + i, i, i == choice);
+ }
+
+ wnoutrefresh(menu);
+
+ print_arrows(dialog, item_no, scroll,
+ box_y, box_x + ITEM_IDENT + 1, menu_height);
+
+ print_buttons(dialog, height, width, 0);
+ wmove(menu, choice, ITEM_IDENT + 1);
+ wrefresh(menu);
+
+ while (key != ESC) {
+ key = wgetch(menu);
+
+ if (key < 256 && isalpha(key))
+ key = tolower(key);
+
+ if (strchr("ynmh", key))
+ i = max_choice;
+ else {
+ for (i = choice + 1; i < max_choice; i++) {
+ j = first_alpha(items[(scroll + i) * 2 + 1], "YyNnMmHh");
+ if (key == tolower(items[(scroll + i) * 2 + 1][j]))
+ break;
+ }
+ if (i == max_choice)
+ for (i = 0; i < max_choice; i++) {
+ j = first_alpha(items [(scroll + i) * 2 + 1], "YyNnMmHh");
+ if (key == tolower(items[(scroll + i) * 2 + 1][j]))
+ break;
+ }
+ }
+
+ if (i < max_choice ||
+ key == KEY_UP || key == KEY_DOWN ||
+ key == '-' || key == '+' ||
+ key == KEY_PPAGE || key == KEY_NPAGE) {
+ /* Remove highligt of current item */
+ print_item(scroll + choice, choice, FALSE);
+
+ if (key == KEY_UP || key == '-') {
+ if (choice < 2 && scroll) {
+ /* Scroll menu down */
+ do_scroll(menu, &scroll, -1);
+
+ print_item(scroll, 0, FALSE);
+ } else
+ choice = MAX(choice - 1, 0);
+
+ } else if (key == KEY_DOWN || key == '+') {
+ print_item(scroll+choice, choice, FALSE);
+
+ if ((choice > max_choice - 3) &&
+ (scroll + max_choice < item_no)) {
+ /* Scroll menu up */
+ do_scroll(menu, &scroll, 1);
+
+ print_item(scroll+max_choice - 1,
+ max_choice - 1, FALSE);
+ } else
+ choice = MIN(choice + 1, max_choice - 1);
+
+ } else if (key == KEY_PPAGE) {
+ scrollok(menu, TRUE);
+ for (i = 0; (i < max_choice); i++) {
+ if (scroll > 0) {
+ do_scroll(menu, &scroll, -1);
+ print_item(scroll, 0, FALSE);
+ } else {
+ if (choice > 0)
+ choice--;
+ }
+ }
+
+ } else if (key == KEY_NPAGE) {
+ for (i = 0; (i < max_choice); i++) {
+ if (scroll + max_choice < item_no) {
+ do_scroll(menu, &scroll, 1);
+ print_item(scroll+max_choice-1,
+ max_choice - 1, FALSE);
+ } else {
+ if (choice + 1 < max_choice)
+ choice++;
+ }
+ }
+ } else
+ choice = i;
+
+ print_item(scroll + choice, choice, TRUE);
+
+ print_arrows(dialog, item_no, scroll,
+ box_y, box_x + ITEM_IDENT + 1, menu_height);
+
+ wnoutrefresh(dialog);
+ wrefresh(menu);
+
+ continue; /* wait for another key press */
+ }
+
+ switch (key) {
+ case KEY_LEFT:
+ case TAB:
+ case KEY_RIGHT:
+ button = ((key == KEY_LEFT ? --button : ++button) < 0)
+ ? 2 : (button > 2 ? 0 : button);
+
+ print_buttons(dialog, height, width, button);
+ wrefresh(menu);
+ break;
+ case ' ':
+ case 's':
+ case 'y':
+ case 'n':
+ case 'm':
+ case '/':
+ /* save scroll info */
+ if ((f = fopen("lxdialog.scrltmp", "w")) != NULL) {
+ fprintf(f, "%d\n", scroll);
+ fclose(f);
+ }
+ delwin(dialog);
+ fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
+ switch (key) {
+ case 's':
+ return 3;
+ case 'y':
+ return 3;
+ case 'n':
+ return 4;
+ case 'm':
+ return 5;
+ case ' ':
+ return 6;
+ case '/':
+ return 7;
+ }
+ return 0;
+ case 'h':
+ case '?':
+ button = 2;
+ case '\n':
+ delwin(dialog);
+ if (button == 2)
+ fprintf(stderr, "%s \"%s\"\n",
+ items[(scroll + choice) * 2],
+ items[(scroll + choice) * 2 + 1] +
+ first_alpha(items [(scroll + choice) * 2 + 1], ""));
+ else
+ fprintf(stderr, "%s\n",
+ items[(scroll + choice) * 2]);
+
+ remove("lxdialog.scrltmp");
+ return button;
+ case 'e':
+ case 'x':
+ key = ESC;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin(dialog);
+ remove("lxdialog.scrltmp");
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/config/lxdialog/msgbox.c b/scripts/config/lxdialog/msgbox.c
new file mode 100644
index 0000000000..7323f5471f
--- /dev/null
+++ b/scripts/config/lxdialog/msgbox.c
@@ -0,0 +1,71 @@
+/*
+ * msgbox.c -- implements the message box and info box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+/*
+ * Display a message box. Program will pause and display an "OK" button
+ * if the parameter 'pause' is non-zero.
+ */
+int dialog_msgbox(const char *title, const char *prompt, int height, int width,
+ int pause)
+{
+ int i, x, y, key = 0;
+ WINDOW *dialog;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow(stdscr, y, x, height, width);
+
+ dialog = newwin(height, width, y, x);
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+
+ print_title(dialog, title, width);
+
+ wattrset(dialog, dialog_attr);
+ print_autowrap(dialog, prompt, width - 2, 1, 2);
+
+ if (pause) {
+ wattrset(dialog, border_attr);
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+
+ print_button(dialog, " Ok ", height - 2, width / 2 - 4, TRUE);
+
+ wrefresh(dialog);
+ while (key != ESC && key != '\n' && key != ' ' &&
+ key != 'O' && key != 'o' && key != 'X' && key != 'x')
+ key = wgetch(dialog);
+ } else {
+ key = '\n';
+ wrefresh(dialog);
+ }
+
+ delwin(dialog);
+ return key == ESC ? -1 : 0;
+}
diff --git a/scripts/config/lxdialog/textbox.c b/scripts/config/lxdialog/textbox.c
new file mode 100644
index 0000000000..77848bb8e0
--- /dev/null
+++ b/scripts/config/lxdialog/textbox.c
@@ -0,0 +1,533 @@
+/*
+ * textbox.c -- implements the text box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+static void back_lines(int n);
+static void print_page(WINDOW * win, int height, int width);
+static void print_line(WINDOW * win, int row, int width);
+static char *get_line(void);
+static void print_position(WINDOW * win, int height, int width);
+
+static int hscroll, fd, file_size, bytes_read;
+static int begin_reached = 1, end_reached, page_length;
+static char *buf, *page;
+
+/*
+ * Display text from a file in a dialog box.
+ */
+int dialog_textbox(const char *title, const char *file, int height, int width)
+{
+ int i, x, y, cur_x, cur_y, fpos, key = 0;
+ int passed_end;
+ char search_term[MAX_LEN + 1];
+ WINDOW *dialog, *text;
+
+ search_term[0] = '\0'; /* no search term entered yet */
+
+ /* Open input file for reading */
+ if ((fd = open(file, O_RDONLY)) == -1) {
+ endwin();
+ fprintf(stderr, "\nCan't open input file in dialog_textbox().\n");
+ exit(-1);
+ }
+ /* Get file size. Actually, 'file_size' is the real file size - 1,
+ since it's only the last byte offset from the beginning */
+ if ((file_size = lseek(fd, 0, SEEK_END)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError getting file size in dialog_textbox().\n");
+ exit(-1);
+ }
+ /* Restore file pointer to beginning of file after getting file size */
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
+ exit(-1);
+ }
+ /* Allocate space for read buffer */
+ if ((buf = malloc(BUF_SIZE + 1)) == NULL) {
+ endwin();
+ fprintf(stderr, "\nCan't allocate memory in dialog_textbox().\n");
+ exit(-1);
+ }
+ if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in dialog_textbox().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0'; /* mark end of valid data */
+ page = buf; /* page is pointer to start of page to be displayed */
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow(stdscr, y, x, height, width);
+
+ dialog = newwin(height, width, y, x);
+ keypad(dialog, TRUE);
+
+ /* Create window for text region, used for scrolling text */
+ text = subwin(dialog, height - 4, width - 2, y + 1, x + 1);
+ wattrset(text, dialog_attr);
+ wbkgdset(text, dialog_attr & A_COLOR);
+
+ keypad(text, TRUE);
+
+ /* register the new window, along with its borders */
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+
+ wattrset(dialog, border_attr);
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ wbkgdset(dialog, dialog_attr & A_COLOR);
+ waddch(dialog, ACS_RTEE);
+
+ print_title(dialog, title, width);
+
+ print_button(dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
+ wnoutrefresh(dialog);
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+
+ /* Print first page of text */
+ attr_clear(text, height - 4, width - 2, dialog_attr);
+ print_page(text, height - 4, width - 2);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+
+ while ((key != ESC) && (key != '\n')) {
+ key = wgetch(dialog);
+ switch (key) {
+ case 'E': /* Exit */
+ case 'e':
+ case 'X':
+ case 'x':
+ delwin(dialog);
+ free(buf);
+ close(fd);
+ return 0;
+ case 'g': /* First page */
+ case KEY_HOME:
+ if (!begin_reached) {
+ begin_reached = 1;
+ /* First page not in buffer? */
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
+ exit(-1);
+ }
+ if (fpos > bytes_read) { /* Yes, we have to read it in */
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in "
+ "dialog_textbox().\n");
+ exit(-1);
+ }
+ if ((bytes_read =
+ read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in dialog_textbox().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0';
+ }
+ page = buf;
+ print_page(text, height - 4, width - 2);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ }
+ break;
+ case 'G': /* Last page */
+ case KEY_END:
+
+ end_reached = 1;
+ /* Last page not in buffer? */
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
+ exit(-1);
+ }
+ if (fpos < file_size) { /* Yes, we have to read it in */
+ if (lseek(fd, -BUF_SIZE, SEEK_END) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
+ exit(-1);
+ }
+ if ((bytes_read =
+ read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in dialog_textbox().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0';
+ }
+ page = buf + bytes_read;
+ back_lines(height - 4);
+ print_page(text, height - 4, width - 2);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ break;
+ case 'K': /* Previous line */
+ case 'k':
+ case KEY_UP:
+ if (!begin_reached) {
+ back_lines(page_length + 1);
+
+ /* We don't call print_page() here but use scrolling to ensure
+ faster screen update. However, 'end_reached' and
+ 'page_length' should still be updated, and 'page' should
+ point to start of next page. This is done by calling
+ get_line() in the following 'for' loop. */
+ scrollok(text, TRUE);
+ wscrl(text, -1); /* Scroll text region down one line */
+ scrollok(text, FALSE);
+ page_length = 0;
+ passed_end = 0;
+ for (i = 0; i < height - 4; i++) {
+ if (!i) {
+ /* print first line of page */
+ print_line(text, 0, width - 2);
+ wnoutrefresh(text);
+ } else
+ /* Called to update 'end_reached' and 'page' */
+ get_line();
+ if (!passed_end)
+ page_length++;
+ if (end_reached && !passed_end)
+ passed_end = 1;
+ }
+
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ }
+ break;
+ case 'B': /* Previous page */
+ case 'b':
+ case KEY_PPAGE:
+ if (begin_reached)
+ break;
+ back_lines(page_length + height - 4);
+ print_page(text, height - 4, width - 2);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x);
+ wrefresh(dialog);
+ break;
+ case 'J': /* Next line */
+ case 'j':
+ case KEY_DOWN:
+ if (!end_reached) {
+ begin_reached = 0;
+ scrollok(text, TRUE);
+ scroll(text); /* Scroll text region up one line */
+ scrollok(text, FALSE);
+ print_line(text, height - 5, width - 2);
+ wnoutrefresh(text);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ }
+ break;
+ case KEY_NPAGE: /* Next page */
+ case ' ':
+ if (end_reached)
+ break;
+
+ begin_reached = 0;
+ print_page(text, height - 4, width - 2);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x);
+ wrefresh(dialog);
+ break;
+ case '0': /* Beginning of line */
+ case 'H': /* Scroll left */
+ case 'h':
+ case KEY_LEFT:
+ if (hscroll <= 0)
+ break;
+
+ if (key == '0')
+ hscroll = 0;
+ else
+ hscroll--;
+ /* Reprint current page to scroll horizontally */
+ back_lines(page_length);
+ print_page(text, height - 4, width - 2);
+ wmove(dialog, cur_y, cur_x);
+ wrefresh(dialog);
+ break;
+ case 'L': /* Scroll right */
+ case 'l':
+ case KEY_RIGHT:
+ if (hscroll >= MAX_LEN)
+ break;
+ hscroll++;
+ /* Reprint current page to scroll horizontally */
+ back_lines(page_length);
+ print_page(text, height - 4, width - 2);
+ wmove(dialog, cur_y, cur_x);
+ wrefresh(dialog);
+ break;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin(dialog);
+ free(buf);
+ close(fd);
+ return -1; /* ESC pressed */
+}
+
+/*
+ * Go back 'n' lines in text file. Called by dialog_textbox().
+ * 'page' will be updated to point to the desired line in 'buf'.
+ */
+static void back_lines(int n)
+{
+ int i, fpos;
+
+ begin_reached = 0;
+ /* We have to distinguish between end_reached and !end_reached
+ since at end of file, the line is not ended by a '\n'.
+ The code inside 'if' basically does a '--page' to move one
+ character backward so as to skip '\n' of the previous line */
+ if (!end_reached) {
+ /* Either beginning of buffer or beginning of file reached? */
+ if (page == buf) {
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in "
+ "back_lines().\n");
+ exit(-1);
+ }
+ if (fpos > bytes_read) { /* Not beginning of file yet */
+ /* We've reached beginning of buffer, but not beginning of
+ file yet, so read previous part of file into buffer.
+ Note that we only move backward for BUF_SIZE/2 bytes,
+ but not BUF_SIZE bytes to avoid re-reading again in
+ print_page() later */
+ /* Really possible to move backward BUF_SIZE/2 bytes? */
+ if (fpos < BUF_SIZE / 2 + bytes_read) {
+ /* No, move less then */
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in "
+ "back_lines().\n");
+ exit(-1);
+ }
+ page = buf + fpos - bytes_read;
+ } else { /* Move backward BUF_SIZE/2 bytes */
+ if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer "
+ "in back_lines().\n");
+ exit(-1);
+ }
+ page = buf + BUF_SIZE / 2;
+ }
+ if ((bytes_read =
+ read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in back_lines().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0';
+ } else { /* Beginning of file reached */
+ begin_reached = 1;
+ return;
+ }
+ }
+ if (*(--page) != '\n') { /* '--page' here */
+ /* Something's wrong... */
+ endwin();
+ fprintf(stderr, "\nInternal error in back_lines().\n");
+ exit(-1);
+ }
+ }
+ /* Go back 'n' lines */
+ for (i = 0; i < n; i++)
+ do {
+ if (page == buf) {
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in back_lines().\n");
+ exit(-1);
+ }
+ if (fpos > bytes_read) {
+ /* Really possible to move backward BUF_SIZE/2 bytes? */
+ if (fpos < BUF_SIZE / 2 + bytes_read) {
+ /* No, move less then */
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer "
+ "in back_lines().\n");
+ exit(-1);
+ }
+ page = buf + fpos - bytes_read;
+ } else { /* Move backward BUF_SIZE/2 bytes */
+ if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer"
+ " in back_lines().\n");
+ exit(-1);
+ }
+ page = buf + BUF_SIZE / 2;
+ }
+ if ((bytes_read =
+ read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in "
+ "back_lines().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0';
+ } else { /* Beginning of file reached */
+ begin_reached = 1;
+ return;
+ }
+ }
+ } while (*(--page) != '\n');
+ page++;
+}
+
+/*
+ * Print a new page of text. Called by dialog_textbox().
+ */
+static void print_page(WINDOW * win, int height, int width)
+{
+ int i, passed_end = 0;
+
+ page_length = 0;
+ for (i = 0; i < height; i++) {
+ print_line(win, i, width);
+ if (!passed_end)
+ page_length++;
+ if (end_reached && !passed_end)
+ passed_end = 1;
+ }
+ wnoutrefresh(win);
+}
+
+/*
+ * Print a new line of text. Called by dialog_textbox() and print_page().
+ */
+static void print_line(WINDOW * win, int row, int width)
+{
+ int y, x;
+ char *line;
+
+ line = get_line();
+ line += MIN(strlen(line), hscroll); /* Scroll horizontally */
+ wmove(win, row, 0); /* move cursor to correct line */
+ waddch(win, ' ');
+ waddnstr(win, line, MIN(strlen(line), width - 2));
+
+ getyx(win, y, x);
+ /* Clear 'residue' of previous line */
+#if OLD_NCURSES
+ {
+ int i;
+ for (i = 0; i < width - x; i++)
+ waddch(win, ' ');
+ }
+#else
+ wclrtoeol(win);
+#endif
+}
+
+/*
+ * Return current line of text. Called by dialog_textbox() and print_line().
+ * 'page' should point to start of current line before calling, and will be
+ * updated to point to start of next line.
+ */
+static char *get_line(void)
+{
+ int i = 0, fpos;
+ static char line[MAX_LEN + 1];
+
+ end_reached = 0;
+ while (*page != '\n') {
+ if (*page == '\0') {
+ /* Either end of file or end of buffer reached */
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in "
+ "get_line().\n");
+ exit(-1);
+ }
+ if (fpos < file_size) { /* Not end of file yet */
+ /* We've reached end of buffer, but not end of file yet,
+ so read next part of file into buffer */
+ if ((bytes_read =
+ read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in get_line().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0';
+ page = buf;
+ } else {
+ if (!end_reached)
+ end_reached = 1;
+ break;
+ }
+ } else if (i < MAX_LEN)
+ line[i++] = *(page++);
+ else {
+ /* Truncate lines longer than MAX_LEN characters */
+ if (i == MAX_LEN)
+ line[i++] = '\0';
+ page++;
+ }
+ }
+ if (i <= MAX_LEN)
+ line[i] = '\0';
+ if (!end_reached)
+ page++; /* move pass '\n' */
+
+ return line;
+}
+
+/*
+ * Print current position
+ */
+static void print_position(WINDOW * win, int height, int width)
+{
+ int fpos, percent;
+
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in print_position().\n");
+ exit(-1);
+ }
+ wattrset(win, position_indicator_attr);
+ wbkgdset(win, position_indicator_attr & A_COLOR);
+ percent = !file_size ?
+ 100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
+ wmove(win, height - 3, width - 9);
+ wprintw(win, "(%3d%%)", percent);
+}
diff --git a/scripts/config/lxdialog/util.c b/scripts/config/lxdialog/util.c
new file mode 100644
index 0000000000..f82cebb9ff
--- /dev/null
+++ b/scripts/config/lxdialog/util.c
@@ -0,0 +1,362 @@
+/*
+ * util.c
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+/* use colors by default? */
+bool use_colors = 1;
+
+const char *backtitle = NULL;
+
+/*
+ * Attribute values, default is for mono display
+ */
+chtype attributes[] = {
+ A_NORMAL, /* screen_attr */
+ A_NORMAL, /* shadow_attr */
+ A_NORMAL, /* dialog_attr */
+ A_BOLD, /* title_attr */
+ A_NORMAL, /* border_attr */
+ A_REVERSE, /* button_active_attr */
+ A_DIM, /* button_inactive_attr */
+ A_REVERSE, /* button_key_active_attr */
+ A_BOLD, /* button_key_inactive_attr */
+ A_REVERSE, /* button_label_active_attr */
+ A_NORMAL, /* button_label_inactive_attr */
+ A_NORMAL, /* inputbox_attr */
+ A_NORMAL, /* inputbox_border_attr */
+ A_NORMAL, /* searchbox_attr */
+ A_BOLD, /* searchbox_title_attr */
+ A_NORMAL, /* searchbox_border_attr */
+ A_BOLD, /* position_indicator_attr */
+ A_NORMAL, /* menubox_attr */
+ A_NORMAL, /* menubox_border_attr */
+ A_NORMAL, /* item_attr */
+ A_REVERSE, /* item_selected_attr */
+ A_BOLD, /* tag_attr */
+ A_REVERSE, /* tag_selected_attr */
+ A_BOLD, /* tag_key_attr */
+ A_REVERSE, /* tag_key_selected_attr */
+ A_BOLD, /* check_attr */
+ A_REVERSE, /* check_selected_attr */
+ A_BOLD, /* uarrow_attr */
+ A_BOLD /* darrow_attr */
+};
+
+#include "colors.h"
+
+/*
+ * Table of color values
+ */
+int color_table[][3] = {
+ {SCREEN_FG, SCREEN_BG, SCREEN_HL},
+ {SHADOW_FG, SHADOW_BG, SHADOW_HL},
+ {DIALOG_FG, DIALOG_BG, DIALOG_HL},
+ {TITLE_FG, TITLE_BG, TITLE_HL},
+ {BORDER_FG, BORDER_BG, BORDER_HL},
+ {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL},
+ {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL},
+ {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL},
+ {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG,
+ BUTTON_KEY_INACTIVE_HL},
+ {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG,
+ BUTTON_LABEL_ACTIVE_HL},
+ {BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG,
+ BUTTON_LABEL_INACTIVE_HL},
+ {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL},
+ {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL},
+ {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL},
+ {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL},
+ {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL},
+ {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL},
+ {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL},
+ {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL},
+ {ITEM_FG, ITEM_BG, ITEM_HL},
+ {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL},
+ {TAG_FG, TAG_BG, TAG_HL},
+ {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL},
+ {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL},
+ {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL},
+ {CHECK_FG, CHECK_BG, CHECK_HL},
+ {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL},
+ {UARROW_FG, UARROW_BG, UARROW_HL},
+ {DARROW_FG, DARROW_BG, DARROW_HL},
+}; /* color_table */
+
+/*
+ * Set window to attribute 'attr'
+ */
+void attr_clear(WINDOW * win, int height, int width, chtype attr)
+{
+ int i, j;
+
+ wattrset(win, attr);
+ for (i = 0; i < height; i++) {
+ wmove(win, i, 0);
+ for (j = 0; j < width; j++)
+ waddch(win, ' ');
+ }
+ touchwin(win);
+}
+
+void dialog_clear(void)
+{
+ attr_clear(stdscr, LINES, COLS, screen_attr);
+ /* Display background title if it exists ... - SLH */
+ if (backtitle != NULL) {
+ int i;
+
+ wattrset(stdscr, screen_attr);
+ mvwaddstr(stdscr, 0, 1, (char *)backtitle);
+ wmove(stdscr, 1, 1);
+ for (i = 1; i < COLS - 1; i++)
+ waddch(stdscr, ACS_HLINE);
+ }
+ wnoutrefresh(stdscr);
+}
+
+/*
+ * Do some initialization for dialog
+ */
+void init_dialog(void)
+{
+ initscr(); /* Init curses */
+ keypad(stdscr, TRUE);
+ cbreak();
+ noecho();
+
+ if (use_colors) /* Set up colors */
+ color_setup();
+
+ dialog_clear();
+}
+
+/*
+ * Setup for color display
+ */
+void color_setup(void)
+{
+ int i;
+
+ if (has_colors()) { /* Terminal supports color? */
+ start_color();
+
+ /* Initialize color pairs */
+ for (i = 0; i < ATTRIBUTE_COUNT; i++)
+ init_pair(i + 1, color_table[i][0], color_table[i][1]);
+
+ /* Setup color attributes */
+ for (i = 0; i < ATTRIBUTE_COUNT; i++)
+ attributes[i] = C_ATTR(color_table[i][2], i + 1);
+ }
+}
+
+/*
+ * End using dialog functions.
+ */
+void end_dialog(void)
+{
+ endwin();
+}
+
+/* Print the title of the dialog. Center the title and truncate
+ * tile if wider than dialog (- 2 chars).
+ **/
+void print_title(WINDOW *dialog, const char *title, int width)
+{
+ if (title) {
+ int tlen = MIN(width - 2, strlen(title));
+ wattrset(dialog, title_attr);
+ mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' ');
+ mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen);
+ waddch(dialog, ' ');
+ }
+}
+
+/*
+ * Print a string of text in a window, automatically wrap around to the
+ * next line if the string is too long to fit on one line. Newline
+ * characters '\n' are replaced by spaces. We start on a new line
+ * if there is no room for at least 4 nonblanks following a double-space.
+ */
+void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
+{
+ int newl, cur_x, cur_y;
+ int i, prompt_len, room, wlen;
+ char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
+
+ strcpy(tempstr, prompt);
+
+ prompt_len = strlen(tempstr);
+
+ /*
+ * Remove newlines
+ */
+ for (i = 0; i < prompt_len; i++) {
+ if (tempstr[i] == '\n')
+ tempstr[i] = ' ';
+ }
+
+ if (prompt_len <= width - x * 2) { /* If prompt is short */
+ wmove(win, y, (width - prompt_len) / 2);
+ waddstr(win, tempstr);
+ } else {
+ cur_x = x;
+ cur_y = y;
+ newl = 1;
+ word = tempstr;
+ while (word && *word) {
+ sp = index(word, ' ');
+ if (sp)
+ *sp++ = 0;
+
+ /* Wrap to next line if either the word does not fit,
+ or it is the first word of a new sentence, and it is
+ short, and the next word does not fit. */
+ room = width - cur_x;
+ wlen = strlen(word);
+ if (wlen > room ||
+ (newl && wlen < 4 && sp
+ && wlen + 1 + strlen(sp) > room
+ && (!(sp2 = index(sp, ' '))
+ || wlen + 1 + (sp2 - sp) > room))) {
+ cur_y++;
+ cur_x = x;
+ }
+ wmove(win, cur_y, cur_x);
+ waddstr(win, word);
+ getyx(win, cur_y, cur_x);
+ cur_x++;
+ if (sp && *sp == ' ') {
+ cur_x++; /* double space */
+ while (*++sp == ' ') ;
+ newl = 1;
+ } else
+ newl = 0;
+ word = sp;
+ }
+ }
+}
+
+/*
+ * Print a button
+ */
+void print_button(WINDOW * win, const char *label, int y, int x, int selected)
+{
+ int i, temp;
+
+ wmove(win, y, x);
+ wattrset(win, selected ? button_active_attr : button_inactive_attr);
+ waddstr(win, "<");
+ temp = strspn(label, " ");
+ label += temp;
+ wattrset(win, selected ? button_label_active_attr
+ : button_label_inactive_attr);
+ for (i = 0; i < temp; i++)
+ waddch(win, ' ');
+ wattrset(win, selected ? button_key_active_attr
+ : button_key_inactive_attr);
+ waddch(win, label[0]);
+ wattrset(win, selected ? button_label_active_attr
+ : button_label_inactive_attr);
+ waddstr(win, (char *)label + 1);
+ wattrset(win, selected ? button_active_attr : button_inactive_attr);
+ waddstr(win, ">");
+ wmove(win, y, x + temp + 1);
+}
+
+/*
+ * Draw a rectangular box with line drawing characters
+ */
+void
+draw_box(WINDOW * win, int y, int x, int height, int width,
+ chtype box, chtype border)
+{
+ int i, j;
+
+ wattrset(win, 0);
+ for (i = 0; i < height; i++) {
+ wmove(win, y + i, x);
+ for (j = 0; j < width; j++)
+ if (!i && !j)
+ waddch(win, border | ACS_ULCORNER);
+ else if (i == height - 1 && !j)
+ waddch(win, border | ACS_LLCORNER);
+ else if (!i && j == width - 1)
+ waddch(win, box | ACS_URCORNER);
+ else if (i == height - 1 && j == width - 1)
+ waddch(win, box | ACS_LRCORNER);
+ else if (!i)
+ waddch(win, border | ACS_HLINE);
+ else if (i == height - 1)
+ waddch(win, box | ACS_HLINE);
+ else if (!j)
+ waddch(win, border | ACS_VLINE);
+ else if (j == width - 1)
+ waddch(win, box | ACS_VLINE);
+ else
+ waddch(win, box | ' ');
+ }
+}
+
+/*
+ * Draw shadows along the right and bottom edge to give a more 3D look
+ * to the boxes
+ */
+void draw_shadow(WINDOW * win, int y, int x, int height, int width)
+{
+ int i;
+
+ if (has_colors()) { /* Whether terminal supports color? */
+ wattrset(win, shadow_attr);
+ wmove(win, y + height, x + 2);
+ for (i = 0; i < width; i++)
+ waddch(win, winch(win) & A_CHARTEXT);
+ for (i = y + 1; i < y + height + 1; i++) {
+ wmove(win, i, x + width);
+ waddch(win, winch(win) & A_CHARTEXT);
+ waddch(win, winch(win) & A_CHARTEXT);
+ }
+ wnoutrefresh(win);
+ }
+}
+
+/*
+ * Return the position of the first alphabetic character in a string.
+ */
+int first_alpha(const char *string, const char *exempt)
+{
+ int i, in_paren = 0, c;
+
+ for (i = 0; i < strlen(string); i++) {
+ c = tolower(string[i]);
+
+ if (strchr("<[(", c))
+ ++in_paren;
+ if (strchr(">])", c) && in_paren > 0)
+ --in_paren;
+
+ if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0)
+ return i;
+ }
+
+ return 0;
+}
diff --git a/scripts/config/lxdialog/yesno.c b/scripts/config/lxdialog/yesno.c
new file mode 100644
index 0000000000..cb2568aae3
--- /dev/null
+++ b/scripts/config/lxdialog/yesno.c
@@ -0,0 +1,102 @@
+/*
+ * yesno.c -- implements the yes/no box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+/*
+ * Display termination buttons
+ */
+static void print_buttons(WINDOW * dialog, int height, int width, int selected)
+{
+ int x = width / 2 - 10;
+ int y = height - 2;
+
+ print_button(dialog, " Yes ", y, x, selected == 0);
+ print_button(dialog, " No ", y, x + 13, selected == 1);
+
+ wmove(dialog, y, x + 1 + 13 * selected);
+ wrefresh(dialog);
+}
+
+/*
+ * Display a dialog box with two buttons - Yes and No
+ */
+int dialog_yesno(const char *title, const char *prompt, int height, int width)
+{
+ int i, x, y, key = 0, button = 0;
+ WINDOW *dialog;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow(stdscr, y, x, height, width);
+
+ dialog = newwin(height, width, y, x);
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset(dialog, border_attr);
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+
+ print_title(dialog, title, width);
+
+ wattrset(dialog, dialog_attr);
+ print_autowrap(dialog, prompt, width - 2, 1, 3);
+
+ print_buttons(dialog, height, width, 0);
+
+ while (key != ESC) {
+ key = wgetch(dialog);
+ switch (key) {
+ case 'Y':
+ case 'y':
+ delwin(dialog);
+ return 0;
+ case 'N':
+ case 'n':
+ delwin(dialog);
+ return 1;
+
+ case TAB:
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button);
+
+ print_buttons(dialog, height, width, button);
+ wrefresh(dialog);
+ break;
+ case ' ':
+ case '\n':
+ delwin(dialog);
+ return button;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin(dialog);
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/config/mconf.c b/scripts/config/mconf.c
new file mode 100644
index 0000000000..b3709fe80d
--- /dev/null
+++ b/scripts/config/mconf.c
@@ -0,0 +1,1102 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ * Introduced single menu mode (show all sub-menus in one large tree).
+ * 2002-11-06 Petr Baudis <pasky@ucw.cz>
+ *
+ * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ */
+
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <locale.h>
+
+#define BUFSIZE 32768
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+static char menu_backtitle[128];
+static const char mconf_readme[] = N_(
+"Overview\n"
+"--------\n"
+"Some OpenWrt features may be built directly into the image.\n"
+"Some may be made into installable ipkg packages. Some features\n"
+"may be completely removed altogether.\n"
+"\n"
+"Menu items beginning with [*], <M> or [ ] represent features\n"
+"configured to be included, built as package or removed respectively.\n"
+"Pointed brackets <> represent packaging capable features.\n"
+"\n"
+"To change any of these features, highlight it with the cursor\n"
+"keys and press <Y> to include it, <M> to make it a package or\n"
+"<N> to remove it. You may also press the <Space Bar> to cycle\n"
+"through the available options (ie. Y->N->M->Y).\n"
+"\n"
+"Some additional keyboard hints:\n"
+"\n"
+"Menus\n"
+"----------\n"
+"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
+" you wish to change or submenu wish to select and press <Enter>.\n"
+" Submenus are designated by \"--->\".\n"
+"\n"
+" Shortcut: Press the option's highlighted letter (hotkey).\n"
+" Pressing a hotkey more than once will sequence\n"
+" through all visible items which use that hotkey.\n"
+"\n"
+" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
+" unseen options into view.\n"
+"\n"
+"o To exit a menu use the cursor keys to highlight the <Exit> button\n"
+" and press <ENTER>.\n"
+"\n"
+" Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
+" using those letters. You may press a single <ESC>, but\n"
+" there is a delayed response which you may find annoying.\n"
+"\n"
+" Also, the <TAB> and cursor keys will cycle between <Select>,\n"
+" <Exit> and <Help>\n"
+"\n"
+"o To get help with an item, use the cursor keys to highlight <Help>\n"
+" and Press <ENTER>.\n"
+"\n"
+" Shortcut: Press <H> or <?>.\n"
+"\n"
+"\n"
+"Radiolists (Choice lists)\n"
+"-----------\n"
+"o Use the cursor keys to select the option you wish to set and press\n"
+" <S> or the <SPACE BAR>.\n"
+"\n"
+" Shortcut: Press the first letter of the option you wish to set then\n"
+" press <S> or <SPACE BAR>.\n"
+"\n"
+"o To see available help for the item, use the cursor keys to highlight\n"
+" <Help> and Press <ENTER>.\n"
+"\n"
+" Shortcut: Press <H> or <?>.\n"
+"\n"
+" Also, the <TAB> and cursor keys will cycle between <Select> and\n"
+" <Help>\n"
+"\n"
+"\n"
+"Data Entry\n"
+"-----------\n"
+"o Enter the requested information and press <ENTER>\n"
+" If you are entering hexadecimal values, it is not necessary to\n"
+" add the '0x' prefix to the entry.\n"
+"\n"
+"o For help, use the <TAB> or cursor keys to highlight the help option\n"
+" and press <ENTER>. You can try <TAB><H> as well.\n"
+"\n"
+"\n"
+"Text Box (Help Window)\n"
+"--------\n"
+"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
+" keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n"
+" who are familiar with less and lynx.\n"
+"\n"
+"o Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n"
+"\n"
+"\n"
+"Alternate Configuration Files\n"
+"-----------------------------\n"
+"Menuconfig supports the use of alternate configuration files for\n"
+"those who, for various reasons, find it necessary to switch\n"
+"between different OpenWrt configurations.\n"
+"\n"
+"At the end of the main menu you will find two options. One is\n"
+"for saving the current configuration to a file of your choosing.\n"
+"The other option is for loading a previously saved alternate\n"
+"configuration.\n"
+"\n"
+"Even if you don't use alternate configuration files, but you\n"
+"find during a Menuconfig session that you have completely messed\n"
+"up your settings, you may use the \"Load Alternate...\" option to\n"
+"restore your previously saved settings from \".config\" without\n"
+"restarting Menuconfig.\n"
+"\n"
+"Other information\n"
+"-----------------\n"
+"If you use Menuconfig in an XTERM window make sure you have your\n"
+"$TERM variable set to point to a xterm definition which supports color.\n"
+"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n"
+"display correctly in a RXVT window because rxvt displays only one\n"
+"intensity of color, bright.\n"
+"\n"
+"Menuconfig will display larger menus on screens or xterms which are\n"
+"set to display more than the standard 25 row by 80 column geometry.\n"
+"In order for this to work, the \"stty size\" command must be able to\n"
+"display the screen's current row and column geometry. I STRONGLY\n"
+"RECOMMEND that you make sure you do NOT have the shell variables\n"
+"LINES and COLUMNS exported into your environment. Some distributions\n"
+"export those variables via /etc/profile. Some ncurses programs can\n"
+"become confused when those variables (LINES & COLUMNS) don't reflect\n"
+"the true screen size.\n"
+"\n"
+"Optional personality available\n"
+"------------------------------\n"
+"If you prefer to have all of the build options listed in a single\n"
+"menu, rather than the default multimenu hierarchy, run the menuconfig\n"
+"with MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
+"\n"
+"make MENUCONFIG_MODE=single_menu menuconfig\n"
+"\n"
+"<Enter> will then unroll the appropriate category, or enfold it if it\n"
+"is already unrolled.\n"
+"\n"
+"Note that this mode can eventually be a little more CPU expensive\n"
+"(especially with a larger number of unrolled categories) than the\n"
+"default mode.\n"),
+menu_instructions[] = N_(
+ "Arrow keys navigate the menu. "
+ "<Enter> selects submenus --->. "
+ "Highlighted letters are hotkeys. "
+ "Pressing <Y> includes, <N> excludes, <M> builds as package. "
+ "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
+ "Legend: [*] built-in [ ] excluded <M> package < > package capable"),
+radiolist_instructions[] = N_(
+ "Use the arrow keys to navigate this window or "
+ "press the hotkey of the item you wish to select "
+ "followed by the <SPACE BAR>. "
+ "Press <?> for additional information about this option."),
+inputbox_instructions_int[] = N_(
+ "Please enter a decimal value. "
+ "Fractions will not be accepted. "
+ "Use the <TAB> key to move from the input field to the buttons below it."),
+inputbox_instructions_hex[] = N_(
+ "Please enter a hexadecimal value. "
+ "Use the <TAB> key to move from the input field to the buttons below it."),
+inputbox_instructions_string[] = N_(
+ "Please enter a string value. "
+ "Use the <TAB> key to move from the input field to the buttons below it."),
+setmod_text[] = N_(
+ "This feature depends on another which has been configured as a package.\n"
+ "As a result, this feature will be built as a package."),
+nohelp_text[] = N_(
+ "There is no help available for this config option.\n"),
+load_config_text[] = N_(
+ "Enter the name of the configuration file you wish to load. "
+ "Accept the name shown to restore the configuration you "
+ "last retrieved. Leave blank to abort."),
+load_config_help[] = N_(
+ "\n"
+ "For various reasons, one may wish to keep several different OpenWrt\n"
+ "configurations available on a single machine.\n"
+ "\n"
+ "If you have saved a previous configuration in a file other than\n"
+ "OpenWrt's default, entering the name of the file here will allow you\n"
+ "to modify that configuration.\n"
+ "\n"
+ "If you are uncertain, then you have probably never used alternate\n"
+ "configuration files. You should therefor leave this blank to abort.\n"),
+save_config_text[] = N_(
+ "Enter a filename to which this configuration should be saved "
+ "as an alternate. Leave blank to abort."),
+save_config_help[] = N_(
+ "\n"
+ "For various reasons, one may wish to keep different OpenWrt\n"
+ "configurations available on a single machine.\n"
+ "\n"
+ "Entering a file name here will allow you to later retrieve, modify\n"
+ "and use the current configuration as an alternate to whatever\n"
+ "configuration options you have selected at that time.\n"
+ "\n"
+ "If you are uncertain what all this means then you should probably\n"
+ "leave this blank.\n"),
+search_help[] = N_(
+ "\n"
+ "Search for CONFIG_ symbols and display their relations.\n"
+ "Regular expressions are allowed.\n"
+ "Example: search for \"^FOO\"\n"
+ "Result:\n"
+ "-----------------------------------------------------------------\n"
+ "Symbol: FOO [=m]\n"
+ "Prompt: Foo bus is used to drive the bar HW\n"
+ "Defined at drivers/pci/Kconfig:47\n"
+ "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
+ "Location:\n"
+ " -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
+ " -> PCI support (PCI [=y])\n"
+ " -> PCI access mode (<choice> [=y])\n"
+ "Selects: LIBCRC32\n"
+ "Selected by: BAR\n"
+ "-----------------------------------------------------------------\n"
+ "o The line 'Prompt:' shows the text used in the menu structure for\n"
+ " this CONFIG_ symbol\n"
+ "o The 'Defined at' line tell at what file / line number the symbol\n"
+ " is defined\n"
+ "o The 'Depends on:' line tell what symbols needs to be defined for\n"
+ " this symbol to be visible in the menu (selectable)\n"
+ "o The 'Location:' lines tell where in the menu structure this symbol\n"
+ " is located\n"
+ " A location followed by a [=y] indicate that this is a selectable\n"
+ " menu item - and current value is displayed inside brackets.\n"
+ "o The 'Selects:' line tell what symbol will be automatically\n"
+ " selected if this symbol is selected (y or m)\n"
+ "o The 'Selected by' line tell what symbol has selected this symbol\n"
+ "\n"
+ "Only relevant lines are shown.\n"
+ "\n\n"
+ "Search examples:\n"
+ "Examples: USB => find all CONFIG_ symbols containing USB\n"
+ " ^USB => find all CONFIG_ symbols starting with USB\n"
+ " USB$ => find all CONFIG_ symbols ending with USB\n"
+ "\n");
+
+static char buf[BUFSIZE], *bufptr = buf;
+static char input_buf[BUFSIZE];
+static char filename[PATH_MAX+1] = ".config";
+static char *args[BUFSIZE], **argptr = args;
+static int indent;
+static struct termios ios_org;
+static int rows = 0, cols = 0;
+static struct menu *current_menu;
+static int child_count;
+static int do_resize;
+static int single_menu_mode;
+
+static void conf(struct menu *menu);
+static void conf_choice(struct menu *menu);
+static void conf_string(struct menu *menu);
+static void conf_load(void);
+static void conf_save(void);
+static void show_textbox(const char *title, const char *text, int r, int c);
+static void show_helptext(const char *title, const char *text);
+static void show_help(struct menu *menu);
+static void show_file(const char *filename, const char *title, int r, int c);
+
+static void cprint_init(void);
+static int cprint1(const char *fmt, ...);
+static void cprint_done(void);
+static int cprint(const char *fmt, ...);
+
+static void init_wsize(void)
+{
+ struct winsize ws;
+ char *env;
+
+ if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)) {
+ rows = ws.ws_row;
+ cols = ws.ws_col;
+ }
+
+ if (!rows) {
+ env = getenv("LINES");
+ if (env)
+ rows = atoi(env);
+ if (!rows)
+ rows = 24;
+ }
+ if (!cols) {
+ env = getenv("COLUMNS");
+ if (env)
+ cols = atoi(env);
+ if (!cols)
+ cols = 80;
+ }
+
+ if (rows < 19 || cols < 80) {
+ fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
+ fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
+ exit(1);
+ }
+
+ rows -= 4;
+ cols -= 5;
+}
+
+static void cprint_init(void)
+{
+ bufptr = buf;
+ argptr = args;
+ memset(args, 0, sizeof(args));
+ indent = 0;
+ child_count = 0;
+ cprint("./scripts/config/lxdialog/lxdialog");
+ cprint("--backtitle");
+ cprint(menu_backtitle);
+}
+
+static int cprint1(const char *fmt, ...)
+{
+ va_list ap;
+ int res;
+
+ if (!*argptr)
+ *argptr = bufptr;
+ va_start(ap, fmt);
+ res = vsprintf(bufptr, fmt, ap);
+ va_end(ap);
+ bufptr += res;
+
+ return res;
+}
+
+static void cprint_done(void)
+{
+ *bufptr++ = 0;
+ argptr++;
+}
+
+static int cprint(const char *fmt, ...)
+{
+ va_list ap;
+ int res;
+
+ *argptr++ = bufptr;
+ va_start(ap, fmt);
+ res = vsprintf(bufptr, fmt, ap);
+ va_end(ap);
+ bufptr += res;
+ *bufptr++ = 0;
+
+ return res;
+}
+
+static void get_prompt_str(struct gstr *r, struct property *prop)
+{
+ int i, j;
+ struct menu *submenu[8], *menu;
+
+ str_printf(r, "Prompt: %s\n", prop->text);
+ str_printf(r, " Defined at %s:%d\n", prop->menu->file->name,
+ prop->menu->lineno);
+ if (!expr_is_yes(prop->visible.expr)) {
+ str_append(r, " Depends on: ");
+ expr_gstr_print(prop->visible.expr, r);
+ str_append(r, "\n");
+ }
+ menu = prop->menu->parent;
+ for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
+ submenu[i++] = menu;
+ if (i > 0) {
+ str_printf(r, " Location:\n");
+ for (j = 4; --i >= 0; j += 2) {
+ menu = submenu[i];
+ str_printf(r, "%*c-> %s", j, ' ', menu_get_prompt(menu));
+ if (menu->sym) {
+ str_printf(r, " (%s [=%s])", menu->sym->name ?
+ menu->sym->name : "<choice>",
+ sym_get_string_value(menu->sym));
+ }
+ str_append(r, "\n");
+ }
+ }
+}
+
+static void get_symbol_str(struct gstr *r, struct symbol *sym)
+{
+ bool hit;
+ struct property *prop;
+
+ str_printf(r, "Symbol: %s [=%s]\n", sym->name,
+ sym_get_string_value(sym));
+ for_all_prompts(sym, prop)
+ get_prompt_str(r, prop);
+ hit = false;
+ for_all_properties(sym, prop, P_SELECT) {
+ if (!hit) {
+ str_append(r, " Selects: ");
+ hit = true;
+ } else
+ str_printf(r, " && ");
+ expr_gstr_print(prop->expr, r);
+ }
+ if (hit)
+ str_append(r, "\n");
+ if (sym->rev_dep.expr) {
+ str_append(r, " Selected by: ");
+ expr_gstr_print(sym->rev_dep.expr, r);
+ str_append(r, "\n");
+ }
+ str_append(r, "\n\n");
+}
+
+static struct gstr get_relations_str(struct symbol **sym_arr)
+{
+ struct symbol *sym;
+ struct gstr res = str_new();
+ int i;
+
+ for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
+ get_symbol_str(&res, sym);
+ if (!i)
+ str_append(&res, "No matches found.\n");
+ return res;
+}
+
+pid_t pid;
+
+static void winch_handler(int sig)
+{
+ if (!do_resize) {
+ kill(pid, SIGINT);
+ do_resize = 1;
+ }
+}
+
+static int exec_conf(void)
+{
+ int pipefd[2], stat, size;
+ struct sigaction sa;
+ sigset_t sset, osset;
+
+ sigemptyset(&sset);
+ sigaddset(&sset, SIGINT);
+ sigprocmask(SIG_BLOCK, &sset, &osset);
+
+ signal(SIGINT, SIG_DFL);
+
+ sa.sa_handler = winch_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sigaction(SIGWINCH, &sa, NULL);
+
+ *argptr++ = NULL;
+
+ pipe(pipefd);
+ pid = fork();
+ if (pid == 0) {
+ sigprocmask(SIG_SETMASK, &osset, NULL);
+ dup2(pipefd[1], 2);
+ close(pipefd[0]);
+ close(pipefd[1]);
+ execv(args[0], args);
+ _exit(EXIT_FAILURE);
+ }
+
+ close(pipefd[1]);
+ bufptr = input_buf;
+ while (1) {
+ size = input_buf + sizeof(input_buf) - bufptr;
+ size = read(pipefd[0], bufptr, size);
+ if (size <= 0) {
+ if (size < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ perror("read");
+ }
+ break;
+ }
+ bufptr += size;
+ }
+ *bufptr++ = 0;
+ close(pipefd[0]);
+ waitpid(pid, &stat, 0);
+
+ if (do_resize) {
+ init_wsize();
+ do_resize = 0;
+ sigprocmask(SIG_SETMASK, &osset, NULL);
+ return -1;
+ }
+ if (WIFSIGNALED(stat)) {
+ printf("\finterrupted(%d)\n", WTERMSIG(stat));
+ exit(1);
+ }
+#if 0
+ printf("\fexit state: %d\nexit data: '%s'\n", WEXITSTATUS(stat), input_buf);
+ sleep(1);
+#endif
+ sigpending(&sset);
+ if (sigismember(&sset, SIGINT)) {
+ printf("\finterrupted\n");
+ exit(1);
+ }
+ sigprocmask(SIG_SETMASK, &osset, NULL);
+
+ return WEXITSTATUS(stat);
+}
+
+static void search_conf(void)
+{
+ struct symbol **sym_arr;
+ int stat;
+ struct gstr res;
+
+again:
+ cprint_init();
+ cprint("--title");
+ cprint(_("Search Configuration Parameter"));
+ cprint("--inputbox");
+ cprint(_("Enter CONFIG_ (sub)string to search for (omit CONFIG_)"));
+ cprint("10");
+ cprint("75");
+ cprint("");
+ stat = exec_conf();
+ if (stat < 0)
+ goto again;
+ switch (stat) {
+ case 0:
+ break;
+ case 1:
+ show_helptext(_("Search Configuration"), search_help);
+ goto again;
+ default:
+ return;
+ }
+
+ sym_arr = sym_re_search(input_buf);
+ res = get_relations_str(sym_arr);
+ free(sym_arr);
+ show_textbox(_("Search Results"), str_get(&res), 0, 0);
+ str_free(&res);
+}
+
+static void build_conf(struct menu *menu)
+{
+ struct symbol *sym;
+ struct property *prop;
+ struct menu *child;
+ int type, tmp, doint = 2;
+ tristate val;
+ char ch;
+
+ if (!menu_is_visible(menu))
+ return;
+
+ sym = menu->sym;
+ prop = menu->prompt;
+ if (!sym) {
+ if (prop && menu != current_menu) {
+ const char *prompt = menu_get_prompt(menu);
+ switch (prop->type) {
+ case P_MENU:
+ child_count++;
+ cprint("m%p", menu);
+
+ if (single_menu_mode) {
+ cprint1("%s%*c%s",
+ menu->data ? "-->" : "++>",
+ indent + 1, ' ', prompt);
+ } else
+ cprint1(" %*c%s --->", indent + 1, ' ', prompt);
+
+ cprint_done();
+ if (single_menu_mode && menu->data)
+ goto conf_childs;
+ return;
+ default:
+ if (prompt) {
+ child_count++;
+ cprint(":%p", menu);
+ cprint("---%*c%s", indent + 1, ' ', prompt);
+ }
+ }
+ } else
+ doint = 0;
+ goto conf_childs;
+ }
+
+ type = sym_get_type(sym);
+ if (sym_is_choice(sym)) {
+ struct symbol *def_sym = sym_get_choice_value(sym);
+ struct menu *def_menu = NULL;
+
+ child_count++;
+ for (child = menu->list; child; child = child->next) {
+ if (menu_is_visible(child) && child->sym == def_sym)
+ def_menu = child;
+ }
+
+ val = sym_get_tristate_value(sym);
+ if (sym_is_changable(sym)) {
+ cprint("t%p", menu);
+ switch (type) {
+ case S_BOOLEAN:
+ cprint1("[%c]", val == no ? ' ' : '*');
+ break;
+ case S_TRISTATE:
+ switch (val) {
+ case yes: ch = '*'; break;
+ case mod: ch = 'M'; break;
+ default: ch = ' '; break;
+ }
+ cprint1("<%c>", ch);
+ break;
+ }
+ } else {
+ cprint("%c%p", def_menu ? 't' : ':', menu);
+ cprint1(" ");
+ }
+
+ cprint1("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
+ if (val == yes) {
+ if (def_menu) {
+ cprint1(" (%s)", menu_get_prompt(def_menu));
+ cprint1(" --->");
+ cprint_done();
+ if (def_menu->list) {
+ indent += 2;
+ build_conf(def_menu);
+ indent -= 2;
+ }
+ } else
+ cprint_done();
+ return;
+ }
+ cprint_done();
+ } else {
+ if (menu == current_menu) {
+ cprint(":%p", menu);
+ cprint("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
+ goto conf_childs;
+ }
+ child_count++;
+ val = sym_get_tristate_value(sym);
+ if (sym_is_choice_value(sym) && val == yes) {
+ cprint(":%p", menu);
+ cprint1(" ");
+ } else {
+ switch (type) {
+ case S_BOOLEAN:
+ cprint("t%p", menu);
+ if (sym_is_changable(sym))
+ cprint1("[%c]", val == no ? ' ' : '*');
+ else
+ cprint1("---");
+ break;
+ case S_TRISTATE:
+ cprint("t%p", menu);
+ switch (val) {
+ case yes: ch = '*'; break;
+ case mod: ch = 'M'; break;
+ default: ch = ' '; break;
+ }
+ if (sym_is_changable(sym))
+ cprint1("<%c>", ch);
+ else
+ cprint1("---");
+ break;
+ default:
+ cprint("s%p", menu);
+ tmp = cprint1("(%s)", sym_get_string_value(sym));
+ tmp = indent - tmp + 4;
+ if (tmp < 0)
+ tmp = 0;
+ cprint1("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
+ (sym_has_value(sym) || !sym_is_changable(sym)) ?
+ "" : " (NEW)");
+ cprint_done();
+ goto conf_childs;
+ }
+ }
+ cprint1("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
+ (sym_has_value(sym) || !sym_is_changable(sym)) ?
+ "" : " (NEW)");
+ if (menu->prompt->type == P_MENU) {
+ cprint1(" --->");
+ cprint_done();
+ return;
+ }
+ cprint_done();
+ }
+
+conf_childs:
+ indent += doint;
+ for (child = menu->list; child; child = child->next)
+ build_conf(child);
+ indent -= doint;
+}
+
+static void conf(struct menu *menu)
+{
+ struct menu *submenu;
+ const char *prompt = menu_get_prompt(menu);
+ struct symbol *sym;
+ char active_entry[40];
+ int stat, type, i;
+
+ unlink("lxdialog.scrltmp");
+ active_entry[0] = 0;
+ while (1) {
+ cprint_init();
+ cprint("--title");
+ cprint("%s", prompt ? prompt : _("Main Menu"));
+ cprint("--menu");
+ cprint(_(menu_instructions));
+ cprint("%d", rows);
+ cprint("%d", cols);
+ cprint("%d", rows - 10);
+ cprint("%s", active_entry);
+ current_menu = menu;
+ build_conf(menu);
+ if (!child_count)
+ break;
+ if (menu == &rootmenu) {
+ cprint(":");
+ cprint("--- ");
+ cprint("D");
+ cprint(_(" Reset to defaults"));
+ cprint("L");
+ cprint(_(" Load an Alternate Configuration File"));
+ cprint("S");
+ cprint(_(" Save Configuration to an Alternate File"));
+ }
+ stat = exec_conf();
+ if (stat < 0)
+ continue;
+
+ if (stat == 1 || stat == 255)
+ break;
+
+ type = input_buf[0];
+ if (!type)
+ continue;
+
+ for (i = 0; input_buf[i] && !isspace(input_buf[i]); i++)
+ ;
+ if (i >= sizeof(active_entry))
+ i = sizeof(active_entry) - 1;
+ input_buf[i] = 0;
+ strcpy(active_entry, input_buf);
+
+ sym = NULL;
+ submenu = NULL;
+ if (sscanf(input_buf + 1, "%p", &submenu) == 1)
+ sym = submenu->sym;
+
+ switch (stat) {
+ case 0:
+ switch (type) {
+ case 'm':
+ if (single_menu_mode)
+ submenu->data = (void *) (long) !submenu->data;
+ else
+ conf(submenu);
+ break;
+ case 't':
+ if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
+ conf_choice(submenu);
+ else if (submenu->prompt->type == P_MENU)
+ conf(submenu);
+ break;
+ case 's':
+ conf_string(submenu);
+ break;
+ case 'D':
+ conf_reset();
+ break;
+ case 'L':
+ conf_load();
+ break;
+ case 'S':
+ conf_save();
+ break;
+ }
+ break;
+ case 2:
+ if (sym)
+ show_help(submenu);
+ else
+ show_helptext("README", _(mconf_readme));
+ break;
+ case 3:
+ if (type == 't') {
+ if (sym_set_tristate_value(sym, yes))
+ break;
+ if (sym_set_tristate_value(sym, mod))
+ show_textbox(NULL, setmod_text, 6, 74);
+ }
+ break;
+ case 4:
+ if (type == 't')
+ sym_set_tristate_value(sym, no);
+ break;
+ case 5:
+ if (type == 't')
+ sym_set_tristate_value(sym, mod);
+ break;
+ case 6:
+ if (type == 't')
+ sym_toggle_tristate_value(sym);
+ else if (type == 'm')
+ conf(submenu);
+ break;
+ case 7:
+ search_conf();
+ break;
+ }
+ }
+}
+
+static void show_textbox(const char *title, const char *text, int r, int c)
+{
+ int fd;
+
+ fd = creat(".help.tmp", 0777);
+ write(fd, text, strlen(text));
+ close(fd);
+ show_file(".help.tmp", title, r, c);
+ unlink(".help.tmp");
+}
+
+static void show_helptext(const char *title, const char *text)
+{
+ show_textbox(title, text, 0, 0);
+}
+
+static void show_help(struct menu *menu)
+{
+ struct gstr help = str_new();
+ struct symbol *sym = menu->sym;
+
+ if (sym->help)
+ {
+ if (sym->name) {
+ str_printf(&help, "CONFIG_%s:\n\n", sym->name);
+ str_append(&help, _(sym->help));
+ str_append(&help, "\n");
+ }
+ } else {
+ str_append(&help, nohelp_text);
+ }
+ get_symbol_str(&help, sym);
+ show_helptext(menu_get_prompt(menu), str_get(&help));
+ str_free(&help);
+}
+
+static void show_file(const char *filename, const char *title, int r, int c)
+{
+ do {
+ cprint_init();
+ if (title) {
+ cprint("--title");
+ cprint("%s", title);
+ }
+ cprint("--textbox");
+ cprint("%s", filename);
+ cprint("%d", r ? r : rows);
+ cprint("%d", c ? c : cols);
+ } while (exec_conf() < 0);
+}
+
+static void conf_choice(struct menu *menu)
+{
+ const char *prompt = menu_get_prompt(menu);
+ struct menu *child;
+ struct symbol *active;
+ int stat;
+
+ active = sym_get_choice_value(menu->sym);
+ while (1) {
+ cprint_init();
+ cprint("--title");
+ cprint("%s", prompt ? prompt : _("Main Menu"));
+ cprint("--radiolist");
+ cprint(_(radiolist_instructions));
+ cprint("15");
+ cprint("70");
+ cprint("6");
+
+ current_menu = menu;
+ for (child = menu->list; child; child = child->next) {
+ if (!menu_is_visible(child))
+ continue;
+ cprint("%p", child);
+ cprint("%s", menu_get_prompt(child));
+ if (child->sym == sym_get_choice_value(menu->sym))
+ cprint("ON");
+ else if (child->sym == active)
+ cprint("SELECTED");
+ else
+ cprint("OFF");
+ }
+
+ stat = exec_conf();
+ switch (stat) {
+ case 0:
+ if (sscanf(input_buf, "%p", &child) != 1)
+ break;
+ sym_set_tristate_value(child->sym, yes);
+ return;
+ case 1:
+ if (sscanf(input_buf, "%p", &child) == 1) {
+ show_help(child);
+ active = child->sym;
+ } else
+ show_help(menu);
+ break;
+ case 255:
+ return;
+ }
+ }
+}
+
+static void conf_string(struct menu *menu)
+{
+ const char *prompt = menu_get_prompt(menu);
+ int stat;
+
+ while (1) {
+ cprint_init();
+ cprint("--title");
+ cprint("%s", prompt ? prompt : _("Main Menu"));
+ cprint("--inputbox");
+ switch (sym_get_type(menu->sym)) {
+ case S_INT:
+ cprint(_(inputbox_instructions_int));
+ break;
+ case S_HEX:
+ cprint(_(inputbox_instructions_hex));
+ break;
+ case S_STRING:
+ cprint(_(inputbox_instructions_string));
+ break;
+ default:
+ /* panic? */;
+ }
+ cprint("10");
+ cprint("75");
+ cprint("%s", sym_get_string_value(menu->sym));
+ stat = exec_conf();
+ switch (stat) {
+ case 0:
+ if (sym_set_string_value(menu->sym, input_buf))
+ return;
+ show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
+ break;
+ case 1:
+ show_help(menu);
+ break;
+ case 255:
+ return;
+ }
+ }
+}
+
+static void conf_load(void)
+{
+ int stat;
+
+ while (1) {
+ cprint_init();
+ cprint("--inputbox");
+ cprint(load_config_text);
+ cprint("11");
+ cprint("55");
+ cprint("%s", filename);
+ stat = exec_conf();
+ switch(stat) {
+ case 0:
+ if (!input_buf[0])
+ return;
+ if (!conf_read(input_buf))
+ return;
+ show_textbox(NULL, _("File does not exist!"), 5, 38);
+ break;
+ case 1:
+ show_helptext(_("Load Alternate Configuration"), load_config_help);
+ break;
+ case 255:
+ return;
+ }
+ }
+}
+
+static void conf_save(void)
+{
+ int stat;
+
+ while (1) {
+ cprint_init();
+ cprint("--inputbox");
+ cprint(save_config_text);
+ cprint("11");
+ cprint("55");
+ cprint("%s", filename);
+ stat = exec_conf();
+ switch(stat) {
+ case 0:
+ if (!input_buf[0])
+ return;
+ if (!conf_write(input_buf))
+ return;
+ show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
+ break;
+ case 1:
+ show_helptext(_("Save Alternate Configuration"), save_config_help);
+ break;
+ case 255:
+ return;
+ }
+ }
+}
+
+static void conf_cleanup(void)
+{
+ tcsetattr(1, TCSAFLUSH, &ios_org);
+ unlink(".help.tmp");
+ unlink("lxdialog.scrltmp");
+}
+
+int main(int ac, char **av)
+{
+ struct symbol *sym;
+ char *mode;
+ int stat;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ conf_parse(av[1]);
+ conf_read(NULL);
+
+ sym = sym_lookup("OPENWRTVERSION", 0);
+ sym_calc_value(sym);
+ sprintf(menu_backtitle, _("OpenWrt %s Configuration"),
+ sym_get_string_value(sym));
+
+ mode = getenv("MENUCONFIG_MODE");
+ if (mode) {
+ if (!strcasecmp(mode, "single_menu"))
+ single_menu_mode = 1;
+ }
+
+ tcgetattr(1, &ios_org);
+ atexit(conf_cleanup);
+ init_wsize();
+ conf(&rootmenu);
+
+ do {
+ cprint_init();
+ cprint("--yesno");
+ cprint(_("Do you wish to save your new OpenWrt configuration?"));
+ cprint("5");
+ cprint("60");
+ stat = exec_conf();
+ } while (stat < 0);
+
+ if (stat == 0) {
+ if (conf_write(NULL)) {
+ fprintf(stderr, _("\n\n"
+ "Error during writing of the OpenWrt configuration.\n"
+ "Your configuration changes were NOT saved."
+ "\n\n"));
+ return 1;
+ }
+ printf(_("\n\n"
+ "*** End of OpenWrt configuration.\n"
+ "*** Execute 'make' to build the OpenWrt or try 'make help'."
+ "\n\n"));
+ } else {
+ fprintf(stderr, _("\n\n"
+ "Your configuration changes were NOT saved."
+ "\n\n"));
+ }
+
+ return 0;
+}
diff --git a/scripts/config/menu.c b/scripts/config/menu.c
new file mode 100644
index 0000000000..20fda9b2fc
--- /dev/null
+++ b/scripts/config/menu.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+struct menu rootmenu;
+static struct menu **last_entry_ptr;
+
+struct file *file_list;
+struct file *current_file;
+
+static void menu_warn(struct menu *menu, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+
+static void prop_warn(struct property *prop, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+
+void menu_init(void)
+{
+ current_entry = current_menu = &rootmenu;
+ last_entry_ptr = &rootmenu.list;
+}
+
+void menu_add_entry(struct symbol *sym)
+{
+ struct menu *menu;
+
+ menu = malloc(sizeof(*menu));
+ memset(menu, 0, sizeof(*menu));
+ menu->sym = sym;
+ menu->parent = current_menu;
+ menu->file = current_file;
+ menu->lineno = zconf_lineno();
+
+ *last_entry_ptr = menu;
+ last_entry_ptr = &menu->next;
+ current_entry = menu;
+}
+
+void menu_end_entry(void)
+{
+}
+
+struct menu *menu_add_menu(void)
+{
+ menu_end_entry();
+ last_entry_ptr = &current_entry->list;
+ return current_menu = current_entry;
+}
+
+void menu_end_menu(void)
+{
+ last_entry_ptr = &current_menu->next;
+ current_menu = current_menu->parent;
+}
+
+struct expr *menu_check_dep(struct expr *e)
+{
+ if (!e)
+ return e;
+
+ switch (e->type) {
+ case E_NOT:
+ e->left.expr = menu_check_dep(e->left.expr);
+ break;
+ case E_OR:
+ case E_AND:
+ e->left.expr = menu_check_dep(e->left.expr);
+ e->right.expr = menu_check_dep(e->right.expr);
+ break;
+/* tristate always enabled */
+#if 0
+ case E_SYMBOL:
+ /* change 'm' into 'm' && MODULES */
+ if (e->left.sym == &symbol_mod)
+ return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
+ break;
+#endif
+ default:
+ break;
+ }
+ return e;
+}
+
+void menu_add_dep(struct expr *dep)
+{
+ current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
+}
+
+void menu_set_type(int type)
+{
+ struct symbol *sym = current_entry->sym;
+
+ if (sym->type == type)
+ return;
+ if (sym->type == S_UNKNOWN) {
+ sym->type = type;
+ return;
+ }
+ menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'\n",
+ sym->name ? sym->name : "<choice>",
+ sym_type_name(sym->type), sym_type_name(type));
+}
+
+struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
+{
+ struct property *prop = prop_alloc(type, current_entry->sym);
+
+ prop->menu = current_entry;
+ prop->text = prompt;
+ prop->expr = expr;
+ prop->visible.expr = menu_check_dep(dep);
+
+ if (prompt) {
+ if (current_entry->prompt)
+ menu_warn(current_entry, "prompt redefined\n");
+ current_entry->prompt = prop;
+ }
+
+ return prop;
+}
+
+struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
+{
+ return menu_add_prop(type, prompt, NULL, dep);
+}
+
+void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
+{
+ menu_add_prop(type, NULL, expr, dep);
+}
+
+void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
+{
+ menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
+}
+
+static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2)
+{
+ return sym2->type == S_INT || sym2->type == S_HEX ||
+ (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
+}
+
+void sym_check_prop(struct symbol *sym)
+{
+ struct property *prop;
+ struct symbol *sym2;
+ for (prop = sym->prop; prop; prop = prop->next) {
+ switch (prop->type) {
+ case P_DEFAULT:
+ if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
+ prop->expr->type != E_SYMBOL)
+ prop_warn(prop,
+ "default for config symbol '%'"
+ " must be a single symbol", sym->name);
+ break;
+ case P_SELECT:
+ sym2 = prop_get_symbol(prop);
+ if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
+ prop_warn(prop,
+ "config symbol '%s' uses select, but is "
+ "not boolean or tristate", sym->name);
+ else if (sym2->type == S_UNKNOWN)
+ prop_warn(prop,
+ "'select' used by config symbol '%s' "
+ "refer to undefined symbol '%s'",
+ sym->name, sym2->name);
+ else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE)
+ prop_warn(prop,
+ "'%s' has wrong type. 'select' only "
+ "accept arguments of boolean and "
+ "tristate type", sym2->name);
+ break;
+ case P_RANGE:
+ if (sym->type != S_INT && sym->type != S_HEX)
+ prop_warn(prop, "range is only allowed "
+ "for int or hex symbols");
+ if (!menu_range_valid_sym(sym, prop->expr->left.sym) ||
+ !menu_range_valid_sym(sym, prop->expr->right.sym))
+ prop_warn(prop, "range is invalid");
+ break;
+ default:
+ ;
+ }
+ }
+}
+
+void menu_finalize(struct menu *parent)
+{
+ struct menu *menu, *last_menu;
+ struct symbol *sym;
+ struct property *prop;
+ struct expr *parentdep, *basedep, *dep, *dep2, **ep;
+
+ sym = parent->sym;
+ if (parent->list) {
+ if (sym && sym_is_choice(sym)) {
+ /* find the first choice value and find out choice type */
+ for (menu = parent->list; menu; menu = menu->next) {
+ if (menu->sym) {
+ current_entry = parent;
+ menu_set_type(menu->sym->type);
+ current_entry = menu;
+ menu_set_type(sym->type);
+ break;
+ }
+ }
+ parentdep = expr_alloc_symbol(sym);
+ } else if (parent->prompt)
+ parentdep = parent->prompt->visible.expr;
+ else
+ parentdep = parent->dep;
+
+ for (menu = parent->list; menu; menu = menu->next) {
+ basedep = expr_transform(menu->dep);
+ basedep = expr_alloc_and(expr_copy(parentdep), basedep);
+ basedep = expr_eliminate_dups(basedep);
+ menu->dep = basedep;
+ if (menu->sym)
+ prop = menu->sym->prop;
+ else
+ prop = menu->prompt;
+ for (; prop; prop = prop->next) {
+ if (prop->menu != menu)
+ continue;
+ dep = expr_transform(prop->visible.expr);
+ dep = expr_alloc_and(expr_copy(basedep), dep);
+ dep = expr_eliminate_dups(dep);
+ if (menu->sym && menu->sym->type != S_TRISTATE)
+ dep = expr_trans_bool(dep);
+ prop->visible.expr = dep;
+ if (prop->type == P_SELECT) {
+ struct symbol *es = prop_get_symbol(prop);
+ es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
+ expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
+ }
+ }
+ }
+ for (menu = parent->list; menu; menu = menu->next)
+ menu_finalize(menu);
+ } else if (sym) {
+ basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
+ basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
+ basedep = expr_eliminate_dups(expr_transform(basedep));
+ last_menu = NULL;
+ for (menu = parent->next; menu; menu = menu->next) {
+ dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
+ if (!expr_contains_symbol(dep, sym))
+ break;
+ if (expr_depends_symbol(dep, sym))
+ goto next;
+ dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
+ dep = expr_eliminate_dups(expr_transform(dep));
+ dep2 = expr_copy(basedep);
+ expr_eliminate_eq(&dep, &dep2);
+ expr_free(dep);
+ if (!expr_is_yes(dep2)) {
+ expr_free(dep2);
+ break;
+ }
+ expr_free(dep2);
+ next:
+ menu_finalize(menu);
+ menu->parent = parent;
+ last_menu = menu;
+ }
+ if (last_menu) {
+ parent->list = parent->next;
+ parent->next = last_menu->next;
+ last_menu->next = NULL;
+ }
+ }
+ for (menu = parent->list; menu; menu = menu->next) {
+ if (sym && sym_is_choice(sym) && menu->sym) {
+ menu->sym->flags |= SYMBOL_CHOICEVAL;
+ if (!menu->prompt)
+ menu_warn(menu, "choice value must have a prompt");
+ for (prop = menu->sym->prop; prop; prop = prop->next) {
+ if (prop->type == P_PROMPT && prop->menu != menu) {
+ prop_warn(prop, "choice values "
+ "currently only support a "
+ "single prompt");
+ }
+ if (prop->type == P_DEFAULT)
+ prop_warn(prop, "defaults for choice "
+ "values not supported");
+ }
+ current_entry = menu;
+ menu_set_type(sym->type);
+ menu_add_symbol(P_CHOICE, sym, NULL);
+ prop = sym_get_choice_prop(sym);
+ for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
+ ;
+ *ep = expr_alloc_one(E_CHOICE, NULL);
+ (*ep)->right.sym = menu->sym;
+ }
+ if (menu->list && (!menu->prompt || !menu->prompt->text)) {
+ for (last_menu = menu->list; ; last_menu = last_menu->next) {
+ last_menu->parent = parent;
+ if (!last_menu->next)
+ break;
+ }
+ last_menu->next = menu->next;
+ menu->next = menu->list;
+ menu->list = NULL;
+ }
+ }
+
+ if (sym && !(sym->flags & SYMBOL_WARNED)) {
+ if (sym->type == S_UNKNOWN)
+ menu_warn(parent, "config symbol defined "
+ "without type\n");
+
+ if (sym_is_choice(sym) && !parent->prompt)
+ menu_warn(parent, "choice must have a prompt\n");
+
+ /* Check properties connected to this symbol */
+ sym_check_prop(sym);
+ sym->flags |= SYMBOL_WARNED;
+ }
+
+ if (sym && !sym_is_optional(sym) && parent->prompt) {
+ sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
+ expr_alloc_and(parent->prompt->visible.expr,
+ expr_alloc_symbol(&symbol_mod)));
+ }
+}
+
+bool menu_is_visible(struct menu *menu)
+{
+ struct menu *child;
+ struct symbol *sym;
+ tristate visible;
+
+ if (!menu->prompt)
+ return false;
+ sym = menu->sym;
+ if (sym) {
+ sym_calc_value(sym);
+ visible = menu->prompt->visible.tri;
+ } else
+ visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
+
+ if (visible != no)
+ return true;
+ if (!sym || sym_get_tristate_value(menu->sym) == no)
+ return false;
+
+ for (child = menu->list; child; child = child->next)
+ if (menu_is_visible(child))
+ return true;
+ return false;
+}
+
+const char *menu_get_prompt(struct menu *menu)
+{
+ if (menu->prompt)
+ return _(menu->prompt->text);
+ else if (menu->sym)
+ return _(menu->sym->name);
+ return NULL;
+}
+
+struct menu *menu_get_root_menu(struct menu *menu)
+{
+ return &rootmenu;
+}
+
+struct menu *menu_get_parent_menu(struct menu *menu)
+{
+ enum prop_type type;
+
+ for (; menu != &rootmenu; menu = menu->parent) {
+ type = menu->prompt ? menu->prompt->type : 0;
+ if (type == P_MENU)
+ break;
+ }
+ return menu;
+}
+
diff --git a/scripts/config/symbol.c b/scripts/config/symbol.c
new file mode 100644
index 0000000000..b79d81ac13
--- /dev/null
+++ b/scripts/config/symbol.c
@@ -0,0 +1,891 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <regex.h>
+#include <sys/utsname.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+struct symbol symbol_yes = {
+ .name = "y",
+ .curr = { "y", yes },
+ .flags = SYMBOL_YES|SYMBOL_VALID,
+}, symbol_mod = {
+ .name = "m",
+ .curr = { "m", mod },
+ .flags = SYMBOL_MOD|SYMBOL_VALID,
+}, symbol_no = {
+ .name = "n",
+ .curr = { "n", no },
+ .flags = SYMBOL_NO|SYMBOL_VALID,
+}, symbol_empty = {
+ .name = "",
+ .curr = { "", no },
+ .flags = SYMBOL_VALID,
+};
+
+int sym_change_count;
+struct symbol *modules_sym;
+tristate modules_val;
+
+void sym_add_default(struct symbol *sym, const char *def)
+{
+ struct property *prop = prop_alloc(P_DEFAULT, sym);
+
+ prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
+}
+
+void sym_init(void)
+{
+ struct symbol *sym;
+ struct utsname uts;
+ char *p;
+ static bool inited = false;
+
+ if (inited)
+ return;
+ inited = true;
+
+ uname(&uts);
+
+ sym = sym_lookup("ARCH", 0);
+ sym->type = S_STRING;
+ sym->flags |= SYMBOL_AUTO;
+ p = getenv("ARCH");
+ if (p)
+ sym_add_default(sym, p);
+
+ sym = sym_lookup("OPENWRTVERSION", 0);
+ sym->type = S_STRING;
+ sym->flags |= SYMBOL_AUTO;
+ p = getenv("OPENWRTVERSION");
+ if (p)
+ sym_add_default(sym, p);
+
+ sym = sym_lookup("UNAME_RELEASE", 0);
+ sym->type = S_STRING;
+ sym->flags |= SYMBOL_AUTO;
+ sym_add_default(sym, uts.release);
+}
+
+enum symbol_type sym_get_type(struct symbol *sym)
+{
+ enum symbol_type type = sym->type;
+
+ if (type == S_TRISTATE) {
+ if (sym_is_choice_value(sym) && sym->visible == yes)
+ type = S_BOOLEAN;
+/* tristate always enabled */
+#if 0
+ else if (modules_val == no)
+ type = S_BOOLEAN;
+#endif
+ }
+ return type;
+}
+
+const char *sym_type_name(enum symbol_type type)
+{
+ switch (type) {
+ case S_BOOLEAN:
+ return "boolean";
+ case S_TRISTATE:
+ return "tristate";
+ case S_INT:
+ return "integer";
+ case S_HEX:
+ return "hex";
+ case S_STRING:
+ return "string";
+ case S_UNKNOWN:
+ return "unknown";
+ case S_OTHER:
+ break;
+ }
+ return "???";
+}
+
+struct property *sym_get_choice_prop(struct symbol *sym)
+{
+ struct property *prop;
+
+ for_all_choices(sym, prop)
+ return prop;
+ return NULL;
+}
+
+struct property *sym_get_default_prop(struct symbol *sym)
+{
+ struct property *prop;
+
+ for_all_defaults(sym, prop) {
+ prop->visible.tri = expr_calc_value(prop->visible.expr);
+ if (prop->visible.tri != no)
+ return prop;
+ }
+ return NULL;
+}
+
+struct property *sym_get_range_prop(struct symbol *sym)
+{
+ struct property *prop;
+
+ for_all_properties(sym, prop, P_RANGE) {
+ prop->visible.tri = expr_calc_value(prop->visible.expr);
+ if (prop->visible.tri != no)
+ return prop;
+ }
+ return NULL;
+}
+
+static int sym_get_range_val(struct symbol *sym, int base)
+{
+ sym_calc_value(sym);
+ switch (sym->type) {
+ case S_INT:
+ base = 10;
+ break;
+ case S_HEX:
+ base = 16;
+ break;
+ default:
+ break;
+ }
+ return strtol(sym->curr.val, NULL, base);
+}
+
+static void sym_validate_range(struct symbol *sym)
+{
+ struct property *prop;
+ int base, val, val2;
+ char str[64];
+
+ switch (sym->type) {
+ case S_INT:
+ base = 10;
+ break;
+ case S_HEX:
+ base = 16;
+ break;
+ default:
+ return;
+ }
+ prop = sym_get_range_prop(sym);
+ if (!prop)
+ return;
+ val = strtol(sym->curr.val, NULL, base);
+ val2 = sym_get_range_val(prop->expr->left.sym, base);
+ if (val >= val2) {
+ val2 = sym_get_range_val(prop->expr->right.sym, base);
+ if (val <= val2)
+ return;
+ }
+ if (sym->type == S_INT)
+ sprintf(str, "%d", val2);
+ else
+ sprintf(str, "0x%x", val2);
+ sym->curr.val = strdup(str);
+}
+
+static void sym_calc_visibility(struct symbol *sym)
+{
+ struct property *prop;
+ tristate tri;
+
+ /* any prompt visible? */
+ tri = no;
+ for_all_prompts(sym, prop) {
+ prop->visible.tri = expr_calc_value(prop->visible.expr);
+ tri = E_OR(tri, prop->visible.tri);
+ }
+/* tristate always enabled */
+#if 0
+ if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
+#else
+ if (tri == mod && (sym->type != S_TRISTATE))
+#endif
+ tri = yes;
+ if (sym->visible != tri) {
+ sym->visible = tri;
+ sym_set_changed(sym);
+ }
+ if (sym_is_choice_value(sym))
+ return;
+ tri = no;
+ if (sym->rev_dep.expr)
+ tri = expr_calc_value(sym->rev_dep.expr);
+ if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
+ tri = yes;
+ if (sym->rev_dep.tri != tri) {
+ sym->rev_dep.tri = tri;
+ sym_set_changed(sym);
+ }
+}
+
+static struct symbol *sym_calc_choice(struct symbol *sym)
+{
+ struct symbol *def_sym;
+ struct property *prop;
+ struct expr *e;
+
+ /* is the user choice visible? */
+ def_sym = sym->user.val;
+ if (def_sym) {
+ sym_calc_visibility(def_sym);
+ if (def_sym->visible != no)
+ return def_sym;
+ }
+
+ /* any of the defaults visible? */
+ for_all_defaults(sym, prop) {
+ prop->visible.tri = expr_calc_value(prop->visible.expr);
+ if (prop->visible.tri == no)
+ continue;
+ def_sym = prop_get_symbol(prop);
+ sym_calc_visibility(def_sym);
+ if (def_sym->visible != no)
+ return def_sym;
+ }
+
+ /* just get the first visible value */
+ prop = sym_get_choice_prop(sym);
+ for (e = prop->expr; e; e = e->left.expr) {
+ def_sym = e->right.sym;
+ sym_calc_visibility(def_sym);
+ if (def_sym->visible != no)
+ return def_sym;
+ }
+
+ /* no choice? reset tristate value */
+ sym->curr.tri = no;
+ return NULL;
+}
+
+void sym_calc_value(struct symbol *sym)
+{
+ struct symbol_value newval, oldval;
+ struct property *prop;
+ struct expr *e;
+
+ if (!sym)
+ return;
+
+ if (sym->flags & SYMBOL_VALID)
+ return;
+ sym->flags |= SYMBOL_VALID;
+
+ oldval = sym->curr;
+
+ switch (sym->type) {
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ newval = symbol_empty.curr;
+ break;
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ newval = symbol_no.curr;
+ break;
+ default:
+ sym->curr.val = sym->name;
+ sym->curr.tri = no;
+ return;
+ }
+ if (!sym_is_choice_value(sym))
+ sym->flags &= ~SYMBOL_WRITE;
+
+ sym_calc_visibility(sym);
+
+ /* set default if recursively called */
+ sym->curr = newval;
+
+ switch (sym_get_type(sym)) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ if (sym_is_choice_value(sym) && sym->visible == yes) {
+ prop = sym_get_choice_prop(sym);
+ newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
+ } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
+ sym->flags |= SYMBOL_WRITE;
+ if (sym_has_value(sym))
+ newval.tri = sym->user.tri;
+ else if (!sym_is_choice(sym)) {
+ prop = sym_get_default_prop(sym);
+ if (prop)
+ newval.tri = expr_calc_value(prop->expr);
+ }
+ newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri);
+ } else if (!sym_is_choice(sym)) {
+ prop = sym_get_default_prop(sym);
+ if (prop) {
+ sym->flags |= SYMBOL_WRITE;
+ newval.tri = expr_calc_value(prop->expr);
+ }
+ }
+ if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
+ newval.tri = yes;
+ break;
+ case S_STRING:
+ case S_HEX:
+ case S_INT:
+ if (sym->visible != no) {
+ sym->flags |= SYMBOL_WRITE;
+ if (sym_has_value(sym)) {
+ newval.val = sym->user.val;
+ break;
+ }
+ }
+ prop = sym_get_default_prop(sym);
+ if (prop) {
+ struct symbol *ds = prop_get_symbol(prop);
+ if (ds) {
+ sym->flags |= SYMBOL_WRITE;
+ sym_calc_value(ds);
+ newval.val = ds->curr.val;
+ }
+ }
+ break;
+ default:
+ ;
+ }
+
+ sym->curr = newval;
+ if (sym_is_choice(sym) && newval.tri == yes)
+ sym->curr.val = sym_calc_choice(sym);
+ sym_validate_range(sym);
+
+ if (memcmp(&oldval, &sym->curr, sizeof(oldval)))
+ sym_set_changed(sym);
+
+ if (modules_sym == sym)
+ modules_val = modules_sym->curr.tri;
+
+ if (sym_is_choice(sym)) {
+ int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
+ prop = sym_get_choice_prop(sym);
+ for (e = prop->expr; e; e = e->left.expr) {
+ e->right.sym->flags |= flags;
+ if (flags & SYMBOL_CHANGED)
+ sym_set_changed(e->right.sym);
+ }
+ }
+}
+
+void sym_clear_all_valid(void)
+{
+ struct symbol *sym;
+ int i;
+
+ for_all_symbols(i, sym)
+ sym->flags &= ~SYMBOL_VALID;
+ sym_change_count++;
+ if (modules_sym)
+ sym_calc_value(modules_sym);
+}
+
+void sym_set_changed(struct symbol *sym)
+{
+ struct property *prop;
+
+ sym->flags |= SYMBOL_CHANGED;
+ for (prop = sym->prop; prop; prop = prop->next) {
+ if (prop->menu)
+ prop->menu->flags |= MENU_CHANGED;
+ }
+}
+
+void sym_set_all_changed(void)
+{
+ struct symbol *sym;
+ int i;
+
+ for_all_symbols(i, sym)
+ sym_set_changed(sym);
+}
+
+bool sym_tristate_within_range(struct symbol *sym, tristate val)
+{
+ int type = sym_get_type(sym);
+
+ if (sym->visible == no)
+ return false;
+
+ if (type != S_BOOLEAN && type != S_TRISTATE)
+ return false;
+
+ if (type == S_BOOLEAN && val == mod)
+ return false;
+ if (sym->visible <= sym->rev_dep.tri)
+ return false;
+ if (sym_is_choice_value(sym) && sym->visible == yes)
+ return val == yes;
+ return val >= sym->rev_dep.tri && val <= sym->visible;
+}
+
+bool sym_set_tristate_value(struct symbol *sym, tristate val)
+{
+ tristate oldval = sym_get_tristate_value(sym);
+
+ if (oldval != val && !sym_tristate_within_range(sym, val))
+ return false;
+
+ if (sym->flags & SYMBOL_NEW) {
+ sym->flags &= ~SYMBOL_NEW;
+ sym_set_changed(sym);
+ }
+ /*
+ * setting a choice value also resets the new flag of the choice
+ * symbol and all other choice values.
+ */
+ if (sym_is_choice_value(sym) && val == yes) {
+ struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
+ struct property *prop;
+ struct expr *e;
+
+ cs->user.val = sym;
+ cs->flags &= ~SYMBOL_NEW;
+ prop = sym_get_choice_prop(cs);
+ for (e = prop->expr; e; e = e->left.expr) {
+ if (e->right.sym->visible != no)
+ e->right.sym->flags &= ~SYMBOL_NEW;
+ }
+ }
+
+ sym->user.tri = val;
+ if (oldval != val) {
+ sym_clear_all_valid();
+ if (sym == modules_sym)
+ sym_set_all_changed();
+ }
+
+ return true;
+}
+
+tristate sym_toggle_tristate_value(struct symbol *sym)
+{
+ tristate oldval, newval;
+
+ oldval = newval = sym_get_tristate_value(sym);
+ do {
+ switch (newval) {
+ case no:
+ newval = mod;
+ break;
+ case mod:
+ newval = yes;
+ break;
+ case yes:
+ newval = no;
+ break;
+ }
+ if (sym_set_tristate_value(sym, newval))
+ break;
+ } while (oldval != newval);
+ return newval;
+}
+
+bool sym_string_valid(struct symbol *sym, const char *str)
+{
+ signed char ch;
+
+ switch (sym->type) {
+ case S_STRING:
+ return true;
+ case S_INT:
+ ch = *str++;
+ if (ch == '-')
+ ch = *str++;
+ if (!isdigit(ch))
+ return false;
+ if (ch == '0' && *str != 0)
+ return false;
+ while ((ch = *str++)) {
+ if (!isdigit(ch))
+ return false;
+ }
+ return true;
+ case S_HEX:
+ if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
+ str += 2;
+ ch = *str++;
+ do {
+ if (!isxdigit(ch))
+ return false;
+ } while ((ch = *str++));
+ return true;
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (str[0]) {
+ case 'y': case 'Y':
+ case 'm': case 'M':
+ case 'n': case 'N':
+ return true;
+ }
+ return false;
+ default:
+ return false;
+ }
+}
+
+bool sym_string_within_range(struct symbol *sym, const char *str)
+{
+ struct property *prop;
+ int val;
+
+ switch (sym->type) {
+ case S_STRING:
+ return sym_string_valid(sym, str);
+ case S_INT:
+ if (!sym_string_valid(sym, str))
+ return false;
+ prop = sym_get_range_prop(sym);
+ if (!prop)
+ return true;
+ val = strtol(str, NULL, 10);
+ return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
+ val <= sym_get_range_val(prop->expr->right.sym, 10);
+ case S_HEX:
+ if (!sym_string_valid(sym, str))
+ return false;
+ prop = sym_get_range_prop(sym);
+ if (!prop)
+ return true;
+ val = strtol(str, NULL, 16);
+ return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
+ val <= sym_get_range_val(prop->expr->right.sym, 16);
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (str[0]) {
+ case 'y': case 'Y':
+ return sym_tristate_within_range(sym, yes);
+ case 'm': case 'M':
+ return sym_tristate_within_range(sym, mod);
+ case 'n': case 'N':
+ return sym_tristate_within_range(sym, no);
+ }
+ return false;
+ default:
+ return false;
+ }
+}
+
+bool sym_set_string_value(struct symbol *sym, const char *newval)
+{
+ const char *oldval;
+ char *val;
+ int size;
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (newval[0]) {
+ case 'y': case 'Y':
+ return sym_set_tristate_value(sym, yes);
+ case 'm': case 'M':
+ return sym_set_tristate_value(sym, mod);
+ case 'n': case 'N':
+ return sym_set_tristate_value(sym, no);
+ }
+ return false;
+ default:
+ ;
+ }
+
+ if (!sym_string_within_range(sym, newval))
+ return false;
+
+ if (sym->flags & SYMBOL_NEW) {
+ sym->flags &= ~SYMBOL_NEW;
+ sym_set_changed(sym);
+ }
+
+ oldval = sym->user.val;
+ size = strlen(newval) + 1;
+ if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
+ size += 2;
+ sym->user.val = val = malloc(size);
+ *val++ = '0';
+ *val++ = 'x';
+ } else if (!oldval || strcmp(oldval, newval))
+ sym->user.val = val = malloc(size);
+ else
+ return true;
+
+ strcpy(val, newval);
+ free((void *)oldval);
+ sym_clear_all_valid();
+
+ return true;
+}
+
+const char *sym_get_string_value(struct symbol *sym)
+{
+ tristate val;
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ val = sym_get_tristate_value(sym);
+ switch (val) {
+ case no:
+ return "n";
+ case mod:
+ return "m";
+ case yes:
+ return "y";
+ }
+ break;
+ default:
+ ;
+ }
+ return (const char *)sym->curr.val;
+}
+
+bool sym_is_changable(struct symbol *sym)
+{
+ return sym->visible > sym->rev_dep.tri;
+}
+
+struct symbol *sym_lookup(const char *name, int isconst)
+{
+ struct symbol *symbol;
+ const char *ptr;
+ char *new_name;
+ int hash = 0;
+
+ if (name) {
+ if (name[0] && !name[1]) {
+ switch (name[0]) {
+ case 'y': return &symbol_yes;
+ case 'm': return &symbol_mod;
+ case 'n': return &symbol_no;
+ }
+ }
+ for (ptr = name; *ptr; ptr++)
+ hash += *ptr;
+ hash &= 0xff;
+
+ for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
+ if (!strcmp(symbol->name, name)) {
+ if ((isconst && symbol->flags & SYMBOL_CONST) ||
+ (!isconst && !(symbol->flags & SYMBOL_CONST)))
+ return symbol;
+ }
+ }
+ new_name = strdup(name);
+ } else {
+ new_name = NULL;
+ hash = 256;
+ }
+
+ symbol = malloc(sizeof(*symbol));
+ memset(symbol, 0, sizeof(*symbol));
+ symbol->name = new_name;
+ symbol->type = S_UNKNOWN;
+ symbol->flags = SYMBOL_NEW;
+ if (isconst)
+ symbol->flags |= SYMBOL_CONST;
+
+ symbol->next = symbol_hash[hash];
+ symbol_hash[hash] = symbol;
+
+ return symbol;
+}
+
+struct symbol *sym_find(const char *name)
+{
+ struct symbol *symbol = NULL;
+ const char *ptr;
+ int hash = 0;
+
+ if (!name)
+ return NULL;
+
+ if (name[0] && !name[1]) {
+ switch (name[0]) {
+ case 'y': return &symbol_yes;
+ case 'm': return &symbol_mod;
+ case 'n': return &symbol_no;
+ }
+ }
+ for (ptr = name; *ptr; ptr++)
+ hash += *ptr;
+ hash &= 0xff;
+
+ for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
+ if (!strcmp(symbol->name, name) &&
+ !(symbol->flags & SYMBOL_CONST))
+ break;
+ }
+
+ return symbol;
+}
+
+struct symbol **sym_re_search(const char *pattern)
+{
+ struct symbol *sym, **sym_arr = NULL;
+ int i, cnt, size;
+ regex_t re;
+
+ cnt = size = 0;
+ /* Skip if empty */
+ if (strlen(pattern) == 0)
+ return NULL;
+ if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
+ return NULL;
+
+ for_all_symbols(i, sym) {
+ if (sym->flags & SYMBOL_CONST || !sym->name)
+ continue;
+ if (regexec(&re, sym->name, 0, NULL, 0))
+ continue;
+ if (cnt + 1 >= size) {
+ void *tmp = sym_arr;
+ size += 16;
+ sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
+ if (!sym_arr) {
+ free(tmp);
+ return NULL;
+ }
+ }
+ sym_arr[cnt++] = sym;
+ }
+ if (sym_arr)
+ sym_arr[cnt] = NULL;
+ regfree(&re);
+
+ return sym_arr;
+}
+
+
+struct symbol *sym_check_deps(struct symbol *sym);
+
+static struct symbol *sym_check_expr_deps(struct expr *e)
+{
+ struct symbol *sym;
+
+ if (!e)
+ return NULL;
+ switch (e->type) {
+ case E_OR:
+ case E_AND:
+ sym = sym_check_expr_deps(e->left.expr);
+ if (sym)
+ return sym;
+ return sym_check_expr_deps(e->right.expr);
+ case E_NOT:
+ return sym_check_expr_deps(e->left.expr);
+ case E_EQUAL:
+ case E_UNEQUAL:
+ sym = sym_check_deps(e->left.sym);
+ if (sym)
+ return sym;
+ return sym_check_deps(e->right.sym);
+ case E_SYMBOL:
+ return sym_check_deps(e->left.sym);
+ default:
+ break;
+ }
+ printf("Oops! How to check %d?\n", e->type);
+ return NULL;
+}
+
+struct symbol *sym_check_deps(struct symbol *sym)
+{
+ struct symbol *sym2;
+ struct property *prop;
+
+ if (sym->flags & SYMBOL_CHECK) {
+ printf("Warning! Found recursive dependency: %s", sym->name);
+ return sym;
+ }
+ if (sym->flags & SYMBOL_CHECKED)
+ return NULL;
+
+ sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
+ sym2 = sym_check_expr_deps(sym->rev_dep.expr);
+ if (sym2)
+ goto out;
+
+ for (prop = sym->prop; prop; prop = prop->next) {
+ if (prop->type == P_CHOICE || prop->type == P_SELECT)
+ continue;
+ sym2 = sym_check_expr_deps(prop->visible.expr);
+ if (sym2)
+ goto out;
+ if (prop->type != P_DEFAULT || sym_is_choice(sym))
+ continue;
+ sym2 = sym_check_expr_deps(prop->expr);
+ if (sym2)
+ goto out;
+ }
+out:
+ if (sym2) {
+ printf(" %s", sym->name);
+ if (sym2 == sym) {
+ printf("\n");
+ sym2 = NULL;
+ }
+ }
+ sym->flags &= ~SYMBOL_CHECK;
+ return sym2;
+}
+
+struct property *prop_alloc(enum prop_type type, struct symbol *sym)
+{
+ struct property *prop;
+ struct property **propp;
+
+ prop = malloc(sizeof(*prop));
+ memset(prop, 0, sizeof(*prop));
+ prop->type = type;
+ prop->sym = sym;
+ prop->file = current_file;
+ prop->lineno = zconf_lineno();
+
+ /* append property to the prop list of symbol */
+ if (sym) {
+ for (propp = &sym->prop; *propp; propp = &(*propp)->next)
+ ;
+ *propp = prop;
+ }
+
+ return prop;
+}
+
+struct symbol *prop_get_symbol(struct property *prop)
+{
+ if (prop->expr && (prop->expr->type == E_SYMBOL ||
+ prop->expr->type == E_CHOICE))
+ return prop->expr->left.sym;
+ return NULL;
+}
+
+const char *prop_get_type_name(enum prop_type type)
+{
+ switch (type) {
+ case P_PROMPT:
+ return "prompt";
+ case P_COMMENT:
+ return "comment";
+ case P_MENU:
+ return "menu";
+ case P_DEFAULT:
+ return "default";
+ case P_CHOICE:
+ return "choice";
+ case P_SELECT:
+ return "select";
+ case P_RANGE:
+ return "range";
+ case P_UNKNOWN:
+ break;
+ }
+ return "unknown";
+}
diff --git a/scripts/config/util.c b/scripts/config/util.c
new file mode 100644
index 0000000000..656d2c87d6
--- /dev/null
+++ b/scripts/config/util.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org>
+ * Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org>
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <string.h>
+#include "lkc.h"
+
+/* file already present in list? If not add it */
+struct file *file_lookup(const char *name)
+{
+ struct file *file;
+
+ for (file = file_list; file; file = file->next) {
+ if (!strcmp(name, file->name))
+ return file;
+ }
+
+ file = malloc(sizeof(*file));
+ memset(file, 0, sizeof(*file));
+ file->name = strdup(name);
+ file->next = file_list;
+ file_list = file;
+ return file;
+}
+
+/* write a dependency file as used by kbuild to track dependencies */
+int file_write_dep(const char *name)
+{
+ struct file *file;
+ FILE *out;
+
+ if (!name)
+ name = ".kconfig.d";
+ out = fopen("..config.tmp", "w");
+ if (!out)
+ return 1;
+ fprintf(out, "deps_config := \\\n");
+ for (file = file_list; file; file = file->next) {
+ if (file->next)
+ fprintf(out, "\t%s \\\n", file->name);
+ else
+ fprintf(out, "\t%s\n", file->name);
+ }
+ fprintf(out, "\n.config include/linux/autoconf.h: $(deps_config)\n\n$(deps_config):\n");
+ fclose(out);
+ rename("..config.tmp", name);
+ return 0;
+}
+
+
+/* Allocate initial growable sting */
+struct gstr str_new(void)
+{
+ struct gstr gs;
+ gs.s = malloc(sizeof(char) * 64);
+ gs.len = 16;
+ strcpy(gs.s, "\0");
+ return gs;
+}
+
+/* Allocate and assign growable string */
+struct gstr str_assign(const char *s)
+{
+ struct gstr gs;
+ gs.s = strdup(s);
+ gs.len = strlen(s) + 1;
+ return gs;
+}
+
+/* Free storage for growable string */
+void str_free(struct gstr *gs)
+{
+ if (gs->s)
+ free(gs->s);
+ gs->s = NULL;
+ gs->len = 0;
+}
+
+/* Append to growable string */
+void str_append(struct gstr *gs, const char *s)
+{
+ size_t l = strlen(gs->s) + strlen(s) + 1;
+ if (l > gs->len) {
+ gs->s = realloc(gs->s, l);
+ gs->len = l;
+ }
+ strcat(gs->s, s);
+}
+
+/* Append printf formatted string to growable string */
+void str_printf(struct gstr *gs, const char *fmt, ...)
+{
+ va_list ap;
+ char s[10000]; /* big enough... */
+ va_start(ap, fmt);
+ vsnprintf(s, sizeof(s), fmt, ap);
+ str_append(gs, s);
+ va_end(ap);
+}
+
+/* Retrieve value of growable string */
+const char *str_get(struct gstr *gs)
+{
+ return gs->s;
+}
+
diff --git a/scripts/config/zconf.gperf b/scripts/config/zconf.gperf
new file mode 100644
index 0000000000..b03220600b
--- /dev/null
+++ b/scripts/config/zconf.gperf
@@ -0,0 +1,43 @@
+%language=ANSI-C
+%define hash-function-name kconf_id_hash
+%define lookup-function-name kconf_id_lookup
+%define string-pool-name kconf_id_strings
+%compare-strncmp
+%enum
+%pic
+%struct-type
+
+struct kconf_id;
+
+%%
+mainmenu, T_MAINMENU, TF_COMMAND
+menu, T_MENU, TF_COMMAND
+endmenu, T_ENDMENU, TF_COMMAND
+source, T_SOURCE, TF_COMMAND
+choice, T_CHOICE, TF_COMMAND
+endchoice, T_ENDCHOICE, TF_COMMAND
+comment, T_COMMENT, TF_COMMAND
+config, T_CONFIG, TF_COMMAND
+menuconfig, T_MENUCONFIG, TF_COMMAND
+help, T_HELP, TF_COMMAND
+if, T_IF, TF_COMMAND|TF_PARAM
+endif, T_ENDIF, TF_COMMAND
+depends, T_DEPENDS, TF_COMMAND
+requires, T_REQUIRES, TF_COMMAND
+optional, T_OPTIONAL, TF_COMMAND
+default, T_DEFAULT, TF_COMMAND, S_UNKNOWN
+prompt, T_PROMPT, TF_COMMAND
+tristate, T_TYPE, TF_COMMAND, S_TRISTATE
+def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE
+bool, T_TYPE, TF_COMMAND, S_BOOLEAN
+boolean, T_TYPE, TF_COMMAND, S_BOOLEAN
+def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN
+def_boolean, T_DEFAULT, TF_COMMAND, S_BOOLEAN
+int, T_TYPE, TF_COMMAND, S_INT
+hex, T_TYPE, TF_COMMAND, S_HEX
+string, T_TYPE, TF_COMMAND, S_STRING
+select, T_SELECT, TF_COMMAND
+enable, T_SELECT, TF_COMMAND
+range, T_RANGE, TF_COMMAND
+on, T_ON, TF_PARAM
+%%
diff --git a/scripts/config/zconf.hash.c_shipped b/scripts/config/zconf.hash.c_shipped
new file mode 100644
index 0000000000..345f0fc07c
--- /dev/null
+++ b/scripts/config/zconf.hash.c_shipped
@@ -0,0 +1,231 @@
+/* ANSI-C code produced by gperf version 3.0.1 */
+/* Command-line: gperf */
+/* Computed positions: -k'1,3' */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646. */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
+#endif
+
+struct kconf_id;
+/* maximum key range = 45, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+kconf_id_hash (register const char *str, register unsigned int len)
+{
+ static unsigned char asso_values[] =
+ {
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 25, 10, 15,
+ 0, 0, 5, 47, 0, 0, 47, 47, 0, 10,
+ 0, 20, 20, 20, 5, 0, 0, 20, 47, 47,
+ 20, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47
+ };
+ register int hval = len;
+
+ switch (hval)
+ {
+ default:
+ hval += asso_values[(unsigned char)str[2]];
+ /*FALLTHROUGH*/
+ case 2:
+ case 1:
+ hval += asso_values[(unsigned char)str[0]];
+ break;
+ }
+ return hval;
+}
+
+struct kconf_id_strings_t
+ {
+ char kconf_id_strings_str2[sizeof("if")];
+ char kconf_id_strings_str3[sizeof("int")];
+ char kconf_id_strings_str4[sizeof("help")];
+ char kconf_id_strings_str5[sizeof("endif")];
+ char kconf_id_strings_str6[sizeof("select")];
+ char kconf_id_strings_str7[sizeof("endmenu")];
+ char kconf_id_strings_str8[sizeof("tristate")];
+ char kconf_id_strings_str9[sizeof("endchoice")];
+ char kconf_id_strings_str10[sizeof("range")];
+ char kconf_id_strings_str11[sizeof("string")];
+ char kconf_id_strings_str12[sizeof("default")];
+ char kconf_id_strings_str13[sizeof("def_bool")];
+ char kconf_id_strings_str14[sizeof("menu")];
+ char kconf_id_strings_str16[sizeof("def_boolean")];
+ char kconf_id_strings_str17[sizeof("def_tristate")];
+ char kconf_id_strings_str18[sizeof("mainmenu")];
+ char kconf_id_strings_str20[sizeof("menuconfig")];
+ char kconf_id_strings_str21[sizeof("config")];
+ char kconf_id_strings_str22[sizeof("on")];
+ char kconf_id_strings_str23[sizeof("hex")];
+ char kconf_id_strings_str26[sizeof("source")];
+ char kconf_id_strings_str27[sizeof("depends")];
+ char kconf_id_strings_str28[sizeof("optional")];
+ char kconf_id_strings_str31[sizeof("enable")];
+ char kconf_id_strings_str32[sizeof("comment")];
+ char kconf_id_strings_str33[sizeof("requires")];
+ char kconf_id_strings_str34[sizeof("bool")];
+ char kconf_id_strings_str37[sizeof("boolean")];
+ char kconf_id_strings_str41[sizeof("choice")];
+ char kconf_id_strings_str46[sizeof("prompt")];
+ };
+static struct kconf_id_strings_t kconf_id_strings_contents =
+ {
+ "if",
+ "int",
+ "help",
+ "endif",
+ "select",
+ "endmenu",
+ "tristate",
+ "endchoice",
+ "range",
+ "string",
+ "default",
+ "def_bool",
+ "menu",
+ "def_boolean",
+ "def_tristate",
+ "mainmenu",
+ "menuconfig",
+ "config",
+ "on",
+ "hex",
+ "source",
+ "depends",
+ "optional",
+ "enable",
+ "comment",
+ "requires",
+ "bool",
+ "boolean",
+ "choice",
+ "prompt"
+ };
+#define kconf_id_strings ((const char *) &kconf_id_strings_contents)
+#ifdef __GNUC__
+__inline
+#endif
+struct kconf_id *
+kconf_id_lookup (register const char *str, register unsigned int len)
+{
+ enum
+ {
+ TOTAL_KEYWORDS = 30,
+ MIN_WORD_LENGTH = 2,
+ MAX_WORD_LENGTH = 12,
+ MIN_HASH_VALUE = 2,
+ MAX_HASH_VALUE = 46
+ };
+
+ static struct kconf_id wordlist[] =
+ {
+ {-1}, {-1},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_IF, TF_COMMAND|TF_PARAM},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_TYPE, TF_COMMAND, S_INT},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str4, T_HELP, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_SELECT, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_ENDMENU, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_TYPE, TF_COMMAND, S_TRISTATE},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9, T_ENDCHOICE, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10, T_RANGE, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11, T_TYPE, TF_COMMAND, S_STRING},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_UNKNOWN},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_MENU, TF_COMMAND},
+ {-1},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_DEFAULT, TF_COMMAND, S_BOOLEAN},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_DEFAULT, TF_COMMAND, S_TRISTATE},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_MAINMENU, TF_COMMAND},
+ {-1},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str20, T_MENUCONFIG, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_CONFIG, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_ON, TF_PARAM},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_TYPE, TF_COMMAND, S_HEX},
+ {-1}, {-1},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_SOURCE, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_DEPENDS, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_OPTIONAL, TF_COMMAND},
+ {-1}, {-1},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SELECT, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_REQUIRES, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str34, T_TYPE, TF_COMMAND, S_BOOLEAN},
+ {-1}, {-1},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_TYPE, TF_COMMAND, S_BOOLEAN},
+ {-1}, {-1}, {-1},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_CHOICE, TF_COMMAND},
+ {-1}, {-1}, {-1}, {-1},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46, T_PROMPT, TF_COMMAND}
+ };
+
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register int key = kconf_id_hash (str, len);
+
+ if (key <= MAX_HASH_VALUE && key >= 0)
+ {
+ register int o = wordlist[key].name;
+ if (o >= 0)
+ {
+ register const char *s = o + kconf_id_strings;
+
+ if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
+ return &wordlist[key];
+ }
+ }
+ }
+ return 0;
+}
+
diff --git a/scripts/config/zconf.l b/scripts/config/zconf.l
new file mode 100644
index 0000000000..7acb60f8e7
--- /dev/null
+++ b/scripts/config/zconf.l
@@ -0,0 +1,371 @@
+%option backup nostdinit noyywrap never-interactive full ecs
+%option 8bit backup nodefault perf-report perf-report
+%x COMMAND HELP STRING PARAM
+%{
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <glob.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+#define START_STRSIZE 16
+
+static struct {
+ struct file *file;
+ int lineno;
+} current_pos;
+
+static char *text;
+static int text_size, text_asize;
+
+struct buffer {
+ struct buffer *parent;
+ YY_BUFFER_STATE state;
+};
+
+struct buffer *current_buf;
+
+static int last_ts, first_ts;
+
+static void zconf_endhelp(void);
+static void zconf_endfile(void);
+
+void new_string(void)
+{
+ text = malloc(START_STRSIZE);
+ text_asize = START_STRSIZE;
+ text_size = 0;
+ *text = 0;
+}
+
+void append_string(const char *str, int size)
+{
+ int new_size = text_size + size + 1;
+ if (new_size > text_asize) {
+ new_size += START_STRSIZE - 1;
+ new_size &= -START_STRSIZE;
+ text = realloc(text, new_size);
+ text_asize = new_size;
+ }
+ memcpy(text + text_size, str, size);
+ text_size += size;
+ text[text_size] = 0;
+}
+
+void alloc_string(const char *str, int size)
+{
+ text = malloc(size + 1);
+ memcpy(text, str, size);
+ text[size] = 0;
+}
+%}
+
+ws [ \n\t]
+n [A-Za-z0-9_]
+
+%%
+ int str = 0;
+ int ts, i;
+
+[ \t]*#.*\n |
+[ \t]*\n {
+ current_file->lineno++;
+ return T_EOL;
+}
+[ \t]*#.*
+
+
+[ \t]+ {
+ BEGIN(COMMAND);
+}
+
+. {
+ unput(yytext[0]);
+ BEGIN(COMMAND);
+}
+
+
+<COMMAND>{
+ {n}+ {
+ struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
+ BEGIN(PARAM);
+ current_pos.file = current_file;
+ current_pos.lineno = current_file->lineno;
+ if (id && id->flags & TF_COMMAND) {
+ zconflval.id = id;
+ return id->token;
+ }
+ alloc_string(yytext, yyleng);
+ zconflval.string = text;
+ return T_WORD;
+ }
+ .
+ \n {
+ BEGIN(INITIAL);
+ current_file->lineno++;
+ return T_EOL;
+ }
+}
+
+<PARAM>{
+ "&&" return T_AND;
+ "||" return T_OR;
+ "(" return T_OPEN_PAREN;
+ ")" return T_CLOSE_PAREN;
+ "!" return T_NOT;
+ "=" return T_EQUAL;
+ "!=" return T_UNEQUAL;
+ \"|\' {
+ str = yytext[0];
+ new_string();
+ BEGIN(STRING);
+ }
+ \n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
+ --- /* ignore */
+ ({n}|[-/.])+ {
+ struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
+ if (id && id->flags & TF_PARAM) {
+ zconflval.id = id;
+ return id->token;
+ }
+ alloc_string(yytext, yyleng);
+ zconflval.string = text;
+ return T_WORD;
+ }
+ #.* /* comment */
+ \\\n current_file->lineno++;
+ .
+ <<EOF>> {
+ BEGIN(INITIAL);
+ }
+}
+
+<STRING>{
+ [^'"\\\n]+/\n {
+ append_string(yytext, yyleng);
+ zconflval.string = text;
+ return T_WORD_QUOTE;
+ }
+ [^'"\\\n]+ {
+ append_string(yytext, yyleng);
+ }
+ \\.?/\n {
+ append_string(yytext + 1, yyleng - 1);
+ zconflval.string = text;
+ return T_WORD_QUOTE;
+ }
+ \\.? {
+ append_string(yytext + 1, yyleng - 1);
+ }
+ \'|\" {
+ if (str == yytext[0]) {
+ BEGIN(PARAM);
+ zconflval.string = text;
+ return T_WORD_QUOTE;
+ } else
+ append_string(yytext, 1);
+ }
+ \n {
+ printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
+ current_file->lineno++;
+ BEGIN(INITIAL);
+ return T_EOL;
+ }
+ <<EOF>> {
+ BEGIN(INITIAL);
+ }
+}
+
+<HELP>{
+ [ \t]+ {
+ ts = 0;
+ for (i = 0; i < yyleng; i++) {
+ if (yytext[i] == '\t')
+ ts = (ts & ~7) + 8;
+ else
+ ts++;
+ }
+ last_ts = ts;
+ if (first_ts) {
+ if (ts < first_ts) {
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+ ts -= first_ts;
+ while (ts > 8) {
+ append_string(" ", 8);
+ ts -= 8;
+ }
+ append_string(" ", ts);
+ }
+ }
+ [ \t]*\n/[^ \t\n] {
+ current_file->lineno++;
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+ [ \t]*\n {
+ current_file->lineno++;
+ append_string("\n", 1);
+ }
+ [^ \t\n].* {
+ append_string(yytext, yyleng);
+ if (!first_ts)
+ first_ts = last_ts;
+ }
+ <<EOF>> {
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+}
+
+<<EOF>> {
+ if (current_file) {
+ zconf_endfile();
+ return T_EOL;
+ }
+ fclose(yyin);
+ yyterminate();
+}
+
+%%
+void zconf_starthelp(void)
+{
+ new_string();
+ last_ts = first_ts = 0;
+ BEGIN(HELP);
+}
+
+static void zconf_endhelp(void)
+{
+ zconflval.string = text;
+ BEGIN(INITIAL);
+}
+
+
+/*
+ * Try to open specified file with following names:
+ * ./name
+ * $(srctree)/name
+ * The latter is used when srctree is separate from objtree
+ * when compiling the kernel.
+ * Return NULL if file is not found.
+ */
+FILE *zconf_fopen(const char *name)
+{
+ char *env, fullname[PATH_MAX+1];
+ FILE *f;
+
+ f = fopen(name, "r");
+ if (!f && name[0] != '/') {
+ env = getenv(SRCTREE);
+ if (env) {
+ sprintf(fullname, "%s/%s", env, name);
+ f = fopen(fullname, "r");
+ }
+ }
+ return f;
+}
+
+void zconf_initscan(const char *name)
+{
+ yyin = zconf_fopen(name);
+ if (!yyin) {
+ printf("can't find file %s\n", name);
+ exit(1);
+ }
+
+ current_buf = malloc(sizeof(*current_buf));
+ memset(current_buf, 0, sizeof(*current_buf));
+
+ current_file = file_lookup(name);
+ current_file->lineno = 1;
+ current_file->flags = FILE_BUSY;
+}
+
+void zconf_nextfile(const char *name)
+{
+ size_t i;
+ int retval;
+ glob_t files;
+ char *filename;
+ struct file *file;
+ struct buffer *buf;
+
+ retval = glob(name, GLOB_ERR | GLOB_MARK, NULL, &files);
+ if (retval == GLOB_NOSPACE || retval == GLOB_ABORTED || retval == GLOB_NOMATCH) {
+ printf("%s:%d: glob failed: %s \"%s\"\n", zconf_curname(), zconf_lineno(),
+ retval == GLOB_NOSPACE ? "failed to allocate memory" :
+ retval == GLOB_ABORTED ? "read error" : "no match",
+ name);
+ exit(1);
+ }
+
+ for (i = files.gl_pathc-1; i != (size_t)-1; --i) {
+ filename = files.gl_pathv[i];
+
+ file = file_lookup(filename);
+ buf = malloc(sizeof(*buf));
+ memset(buf, 0, sizeof(*buf));
+ current_buf->state = YY_CURRENT_BUFFER;
+ zconfin = zconf_fopen(filename);
+ if (!zconfin) {
+ printf("%s:%d: can't open file \"%s\"\n",
+ zconf_curname(), zconf_lineno(), filename);
+ exit(1);
+ }
+ zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE));
+ buf->parent = current_buf;
+ current_buf = buf;
+
+ if (file->flags & FILE_BUSY) {
+ printf("recursive scan (%s)?\n", filename);
+ exit(1);
+ }
+ if (file->flags & FILE_SCANNED) {
+ printf("file %s already scanned?\n", filename);
+ exit(1);
+ }
+ file->flags |= FILE_BUSY;
+ file->lineno = 1;
+ file->parent = current_file;
+ current_file = file;
+ }
+}
+
+static void zconf_endfile(void)
+{
+ struct buffer *parent;
+
+ current_file->flags |= FILE_SCANNED;
+ current_file->flags &= ~FILE_BUSY;
+ current_file = current_file->parent;
+
+ parent = current_buf->parent;
+ if (parent) {
+ fclose(yyin);
+ yy_delete_buffer(YY_CURRENT_BUFFER);
+ yy_switch_to_buffer(parent->state);
+ }
+ free(current_buf);
+ current_buf = parent;
+}
+
+int zconf_lineno(void)
+{
+ return current_pos.lineno;
+}
+
+char *zconf_curname(void)
+{
+ return current_pos.file ? current_pos.file->name : "<none>";
+}
diff --git a/scripts/config/zconf.tab.c_shipped b/scripts/config/zconf.tab.c_shipped
new file mode 100644
index 0000000000..8060dc6a06
--- /dev/null
+++ b/scripts/config/zconf.tab.c_shipped
@@ -0,0 +1,2146 @@
+/* A Bison parser, made by GNU Bison 1.875d. */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+ Copyright (C) 1984, 1989, 1990, 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.
+
+ 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, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* Written by Richard Stallman by simplifying the original so called
+ ``semantic'' parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+/* If NAME_PREFIX is specified substitute the variables and functions
+ names. */
+#define yyparse zconfparse
+#define yylex zconflex
+#define yyerror zconferror
+#define yylval zconflval
+#define yychar zconfchar
+#define yydebug zconfdebug
+#define yynerrs zconfnerrs
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ T_MAINMENU = 258,
+ T_MENU = 259,
+ T_ENDMENU = 260,
+ T_SOURCE = 261,
+ T_CHOICE = 262,
+ T_ENDCHOICE = 263,
+ T_COMMENT = 264,
+ T_CONFIG = 265,
+ T_MENUCONFIG = 266,
+ T_HELP = 267,
+ T_HELPTEXT = 268,
+ T_IF = 269,
+ T_ENDIF = 270,
+ T_DEPENDS = 271,
+ T_REQUIRES = 272,
+ T_OPTIONAL = 273,
+ T_PROMPT = 274,
+ T_TYPE = 275,
+ T_DEFAULT = 276,
+ T_SELECT = 277,
+ T_RANGE = 278,
+ T_ON = 279,
+ T_WORD = 280,
+ T_WORD_QUOTE = 281,
+ T_UNEQUAL = 282,
+ T_CLOSE_PAREN = 283,
+ T_OPEN_PAREN = 284,
+ T_EOL = 285,
+ T_OR = 286,
+ T_AND = 287,
+ T_EQUAL = 288,
+ T_NOT = 289
+ };
+#endif
+#define T_MAINMENU 258
+#define T_MENU 259
+#define T_ENDMENU 260
+#define T_SOURCE 261
+#define T_CHOICE 262
+#define T_ENDCHOICE 263
+#define T_COMMENT 264
+#define T_CONFIG 265
+#define T_MENUCONFIG 266
+#define T_HELP 267
+#define T_HELPTEXT 268
+#define T_IF 269
+#define T_ENDIF 270
+#define T_DEPENDS 271
+#define T_REQUIRES 272
+#define T_OPTIONAL 273
+#define T_PROMPT 274
+#define T_TYPE 275
+#define T_DEFAULT 276
+#define T_SELECT 277
+#define T_RANGE 278
+#define T_ON 279
+#define T_WORD 280
+#define T_WORD_QUOTE 281
+#define T_UNEQUAL 282
+#define T_CLOSE_PAREN 283
+#define T_OPEN_PAREN 284
+#define T_EOL 285
+#define T_OR 286
+#define T_AND 287
+#define T_EQUAL 288
+#define T_NOT 289
+
+
+
+
+/* Copy the first part of user declarations. */
+
+
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+#include "zconf.hash.c"
+
+#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
+
+#define PRINTD 0x0001
+#define DEBUG_PARSE 0x0002
+
+int cdebug = PRINTD;
+
+extern int zconflex(void);
+static void zconfprint(const char *err, ...);
+static void zconf_error(const char *err, ...);
+static void zconferror(const char *err);
+static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken);
+
+struct symbol *symbol_hash[257];
+
+static struct menu *current_menu, *current_entry;
+
+#define YYDEBUG 0
+#if YYDEBUG
+#define YYERROR_VERBOSE
+#endif
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+
+typedef union YYSTYPE {
+ char *string;
+ struct file *file;
+ struct symbol *symbol;
+ struct expr *expr;
+ struct menu *menu;
+ struct kconf_id *id;
+} YYSTYPE;
+/* Line 191 of yacc.c. */
+
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 214 of yacc.c. */
+
+
+#if ! defined (yyoverflow) || YYERROR_VERBOSE
+
+# ifndef YYFREE
+# define YYFREE free
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# endif
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# define YYSTACK_ALLOC alloca
+# endif
+# else
+# if defined (alloca) || defined (_ALLOCA_H)
+# define YYSTACK_ALLOC alloca
+# else
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# endif
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# endif
+#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+
+
+#if (! defined (yyoverflow) \
+ && (! defined (__cplusplus) \
+ || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ short int yyss;
+ YYSTYPE yyvs;
+ };
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined (__GNUC__) && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ register YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (0)
+
+#endif
+
+#if defined (__STDC__) || defined (__cplusplus)
+ typedef signed char yysigned_char;
+#else
+ typedef short int yysigned_char;
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 3
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 264
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 35
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 42
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 104
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 175
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 289
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const unsigned char yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 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, 26, 27, 28, 29, 30, 31, 32, 33, 34
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const unsigned short int yyprhs[] =
+{
+ 0, 0, 3, 5, 6, 9, 12, 15, 20, 23,
+ 28, 33, 37, 39, 41, 43, 45, 47, 49, 51,
+ 53, 55, 57, 59, 61, 63, 67, 70, 74, 77,
+ 81, 84, 85, 88, 91, 94, 97, 100, 104, 109,
+ 114, 119, 125, 128, 131, 133, 137, 138, 141, 144,
+ 147, 150, 153, 158, 162, 165, 170, 171, 174, 178,
+ 180, 184, 185, 188, 191, 194, 198, 201, 203, 207,
+ 208, 211, 214, 217, 221, 225, 228, 231, 234, 235,
+ 238, 241, 244, 249, 253, 257, 258, 261, 263, 265,
+ 268, 271, 274, 276, 279, 280, 283, 285, 289, 293,
+ 297, 300, 304, 308, 310
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yysigned_char yyrhs[] =
+{
+ 36, 0, -1, 37, -1, -1, 37, 39, -1, 37,
+ 50, -1, 37, 61, -1, 37, 3, 71, 73, -1,
+ 37, 72, -1, 37, 25, 1, 30, -1, 37, 38,
+ 1, 30, -1, 37, 1, 30, -1, 16, -1, 19,
+ -1, 20, -1, 22, -1, 18, -1, 23, -1, 21,
+ -1, 30, -1, 56, -1, 65, -1, 42, -1, 44,
+ -1, 63, -1, 25, 1, 30, -1, 1, 30, -1,
+ 10, 25, 30, -1, 41, 45, -1, 11, 25, 30,
+ -1, 43, 45, -1, -1, 45, 46, -1, 45, 69,
+ -1, 45, 67, -1, 45, 40, -1, 45, 30, -1,
+ 20, 70, 30, -1, 19, 71, 74, 30, -1, 21,
+ 75, 74, 30, -1, 22, 25, 74, 30, -1, 23,
+ 76, 76, 74, 30, -1, 7, 30, -1, 47, 51,
+ -1, 72, -1, 48, 53, 49, -1, -1, 51, 52,
+ -1, 51, 69, -1, 51, 67, -1, 51, 30, -1,
+ 51, 40, -1, 19, 71, 74, 30, -1, 20, 70,
+ 30, -1, 18, 30, -1, 21, 25, 74, 30, -1,
+ -1, 53, 39, -1, 14, 75, 73, -1, 72, -1,
+ 54, 57, 55, -1, -1, 57, 39, -1, 57, 61,
+ -1, 57, 50, -1, 4, 71, 30, -1, 58, 68,
+ -1, 72, -1, 59, 62, 60, -1, -1, 62, 39,
+ -1, 62, 61, -1, 62, 50, -1, 6, 71, 30,
+ -1, 9, 71, 30, -1, 64, 68, -1, 12, 30,
+ -1, 66, 13, -1, -1, 68, 69, -1, 68, 30,
+ -1, 68, 40, -1, 16, 24, 75, 30, -1, 16,
+ 75, 30, -1, 17, 75, 30, -1, -1, 71, 74,
+ -1, 25, -1, 26, -1, 5, 30, -1, 8, 30,
+ -1, 15, 30, -1, 30, -1, 73, 30, -1, -1,
+ 14, 75, -1, 76, -1, 76, 33, 76, -1, 76,
+ 27, 76, -1, 29, 75, 28, -1, 34, 75, -1,
+ 75, 31, 75, -1, 75, 32, 75, -1, 25, -1,
+ 26, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const unsigned short int yyrline[] =
+{
+ 0, 103, 103, 105, 107, 108, 109, 110, 111, 112,
+ 113, 117, 121, 121, 121, 121, 121, 121, 121, 125,
+ 126, 127, 128, 129, 130, 134, 135, 141, 149, 155,
+ 163, 173, 175, 176, 177, 178, 179, 182, 190, 196,
+ 206, 212, 220, 229, 234, 242, 245, 247, 248, 249,
+ 250, 251, 254, 260, 271, 277, 287, 289, 294, 302,
+ 310, 313, 315, 316, 317, 322, 329, 334, 342, 345,
+ 347, 348, 349, 352, 360, 367, 374, 380, 387, 389,
+ 390, 391, 394, 399, 404, 412, 414, 419, 420, 423,
+ 424, 425, 429, 430, 433, 434, 437, 438, 439, 440,
+ 441, 442, 443, 446, 447
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE
+/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU",
+ "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG",
+ "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS",
+ "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT",
+ "T_SELECT", "T_RANGE", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
+ "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL",
+ "T_NOT", "$accept", "input", "stmt_list", "option_name", "common_stmt",
+ "option_error", "config_entry_start", "config_stmt",
+ "menuconfig_entry_start", "menuconfig_stmt", "config_option_list",
+ "config_option", "choice", "choice_entry", "choice_end", "choice_stmt",
+ "choice_option_list", "choice_option", "choice_block", "if_entry",
+ "if_end", "if_stmt", "if_block", "menu", "menu_entry", "menu_end",
+ "menu_stmt", "menu_block", "source_stmt", "comment", "comment_stmt",
+ "help_start", "help", "depends_list", "depends", "prompt_stmt_opt",
+ "prompt", "end", "nl", "if_expr", "expr", "symbol", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const unsigned short int yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const unsigned char yyr1[] =
+{
+ 0, 35, 36, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 38, 38, 38, 38, 38, 38, 38, 39,
+ 39, 39, 39, 39, 39, 40, 40, 41, 42, 43,
+ 44, 45, 45, 45, 45, 45, 45, 46, 46, 46,
+ 46, 46, 47, 48, 49, 50, 51, 51, 51, 51,
+ 51, 51, 52, 52, 52, 52, 53, 53, 54, 55,
+ 56, 57, 57, 57, 57, 58, 59, 60, 61, 62,
+ 62, 62, 62, 63, 64, 65, 66, 67, 68, 68,
+ 68, 68, 69, 69, 69, 70, 70, 71, 71, 72,
+ 72, 72, 73, 73, 74, 74, 75, 75, 75, 75,
+ 75, 75, 75, 76, 76
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const unsigned char yyr2[] =
+{
+ 0, 2, 1, 0, 2, 2, 2, 4, 2, 4,
+ 4, 3, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 3, 2, 3, 2, 3,
+ 2, 0, 2, 2, 2, 2, 2, 3, 4, 4,
+ 4, 5, 2, 2, 1, 3, 0, 2, 2, 2,
+ 2, 2, 4, 3, 2, 4, 0, 2, 3, 1,
+ 3, 0, 2, 2, 2, 3, 2, 1, 3, 0,
+ 2, 2, 2, 3, 3, 2, 2, 2, 0, 2,
+ 2, 2, 4, 3, 3, 0, 2, 1, 1, 2,
+ 2, 2, 1, 2, 0, 2, 1, 3, 3, 3,
+ 2, 3, 3, 1, 1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const unsigned char yydefact[] =
+{
+ 3, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 12, 16, 13, 14,
+ 18, 15, 17, 0, 19, 0, 4, 31, 22, 31,
+ 23, 46, 56, 5, 61, 20, 78, 69, 6, 24,
+ 78, 21, 8, 11, 87, 88, 0, 0, 89, 0,
+ 42, 90, 0, 0, 0, 103, 104, 0, 0, 0,
+ 96, 91, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 92, 7, 65, 73, 74, 27, 29, 0,
+ 100, 0, 0, 58, 0, 0, 9, 10, 0, 0,
+ 0, 0, 0, 85, 0, 0, 0, 0, 36, 35,
+ 32, 0, 34, 33, 0, 0, 85, 0, 50, 51,
+ 47, 49, 48, 57, 45, 44, 62, 64, 60, 63,
+ 59, 80, 81, 79, 70, 72, 68, 71, 67, 93,
+ 99, 101, 102, 98, 97, 26, 76, 0, 0, 0,
+ 94, 0, 94, 94, 94, 0, 0, 77, 54, 94,
+ 0, 94, 0, 83, 84, 0, 0, 37, 86, 0,
+ 0, 94, 25, 0, 53, 0, 82, 95, 38, 39,
+ 40, 0, 52, 55, 41
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const short int yydefgoto[] =
+{
+ -1, 1, 2, 25, 26, 99, 27, 28, 29, 30,
+ 64, 100, 31, 32, 114, 33, 66, 110, 67, 34,
+ 118, 35, 68, 36, 37, 126, 38, 70, 39, 40,
+ 41, 101, 102, 69, 103, 141, 142, 42, 73, 156,
+ 59, 60
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -78
+static const short int yypact[] =
+{
+ -78, 2, 159, -78, -21, 0, 0, -12, 0, 1,
+ 4, 0, 27, 38, 60, 58, -78, -78, -78, -78,
+ -78, -78, -78, 100, -78, 104, -78, -78, -78, -78,
+ -78, -78, -78, -78, -78, -78, -78, -78, -78, -78,
+ -78, -78, -78, -78, -78, -78, 86, 113, -78, 114,
+ -78, -78, 125, 127, 128, -78, -78, 60, 60, 210,
+ 65, -78, 141, 142, 39, 103, 182, 200, 6, 66,
+ 6, 131, -78, 146, -78, -78, -78, -78, -78, 196,
+ -78, 60, 60, 146, 40, 40, -78, -78, 155, 156,
+ -2, 60, 0, 0, 60, 105, 40, 194, -78, -78,
+ -78, 206, -78, -78, 183, 0, 0, 195, -78, -78,
+ -78, -78, -78, -78, -78, -78, -78, -78, -78, -78,
+ -78, -78, -78, -78, -78, -78, -78, -78, -78, -78,
+ -78, 197, -78, -78, -78, -78, -78, 60, 213, 216,
+ 212, 203, 212, 190, 212, 40, 208, -78, -78, 212,
+ 222, 212, 219, -78, -78, 60, 223, -78, -78, 224,
+ 225, 212, -78, 226, -78, 227, -78, 47, -78, -78,
+ -78, 228, -78, -78, -78
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const short int yypgoto[] =
+{
+ -78, -78, -78, -78, 164, -36, -78, -78, -78, -78,
+ 230, -78, -78, -78, -78, 29, -78, -78, -78, -78,
+ -78, -78, -78, -78, -78, -78, 59, -78, -78, -78,
+ -78, -78, 198, 220, 24, 157, -5, 169, 202, 74,
+ -53, -77
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -76
+static const short int yytable[] =
+{
+ 46, 47, 3, 49, 79, 80, 52, 133, 134, 43,
+ 6, 7, 8, 9, 10, 11, 12, 13, 48, 145,
+ 14, 15, 137, 55, 56, 44, 45, 57, 131, 132,
+ 109, 50, 58, 122, 51, 122, 24, 138, 139, -28,
+ 88, 143, -28, -28, -28, -28, -28, -28, -28, -28,
+ -28, 89, 53, -28, -28, 90, 91, -28, 92, 93,
+ 94, 95, 96, 54, 97, 55, 56, 88, 161, 98,
+ -66, -66, -66, -66, -66, -66, -66, -66, 81, 82,
+ -66, -66, 90, 91, 152, 55, 56, 140, 61, 57,
+ 112, 97, 84, 123, 58, 123, 121, 117, 85, 125,
+ 149, 62, 167, -30, 88, 63, -30, -30, -30, -30,
+ -30, -30, -30, -30, -30, 89, 72, -30, -30, 90,
+ 91, -30, 92, 93, 94, 95, 96, 119, 97, 127,
+ 144, -75, 88, 98, -75, -75, -75, -75, -75, -75,
+ -75, -75, -75, 74, 75, -75, -75, 90, 91, -75,
+ -75, -75, -75, -75, -75, 76, 97, 77, 78, -2,
+ 4, 121, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 86, 87, 14, 15, 16, 129, 17, 18, 19,
+ 20, 21, 22, 88, 23, 135, 136, -43, -43, 24,
+ -43, -43, -43, -43, 89, 146, -43, -43, 90, 91,
+ 104, 105, 106, 107, 155, 7, 8, 97, 10, 11,
+ 12, 13, 108, 148, 14, 15, 158, 159, 160, 147,
+ 151, 81, 82, 163, 130, 165, 155, 81, 82, 82,
+ 24, 113, 116, 157, 124, 171, 115, 120, 162, 128,
+ 72, 81, 82, 153, 81, 82, 154, 81, 82, 166,
+ 81, 82, 164, 168, 169, 170, 172, 173, 174, 65,
+ 71, 83, 0, 150, 111
+};
+
+static const short int yycheck[] =
+{
+ 5, 6, 0, 8, 57, 58, 11, 84, 85, 30,
+ 4, 5, 6, 7, 8, 9, 10, 11, 30, 96,
+ 14, 15, 24, 25, 26, 25, 26, 29, 81, 82,
+ 66, 30, 34, 69, 30, 71, 30, 90, 91, 0,
+ 1, 94, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 25, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 25, 25, 25, 26, 1, 145, 30,
+ 4, 5, 6, 7, 8, 9, 10, 11, 31, 32,
+ 14, 15, 16, 17, 137, 25, 26, 92, 30, 29,
+ 66, 25, 27, 69, 34, 71, 30, 68, 33, 70,
+ 105, 1, 155, 0, 1, 1, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 30, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 68, 25, 70,
+ 25, 0, 1, 30, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 30, 30, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 30, 25, 30, 30, 0,
+ 1, 30, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 30, 30, 14, 15, 16, 30, 18, 19, 20,
+ 21, 22, 23, 1, 25, 30, 30, 5, 6, 30,
+ 8, 9, 10, 11, 12, 1, 14, 15, 16, 17,
+ 18, 19, 20, 21, 14, 5, 6, 25, 8, 9,
+ 10, 11, 30, 30, 14, 15, 142, 143, 144, 13,
+ 25, 31, 32, 149, 28, 151, 14, 31, 32, 32,
+ 30, 67, 68, 30, 70, 161, 67, 68, 30, 70,
+ 30, 31, 32, 30, 31, 32, 30, 31, 32, 30,
+ 31, 32, 30, 30, 30, 30, 30, 30, 30, 29,
+ 40, 59, -1, 106, 66
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const unsigned char yystos[] =
+{
+ 0, 36, 37, 0, 1, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 14, 15, 16, 18, 19, 20,
+ 21, 22, 23, 25, 30, 38, 39, 41, 42, 43,
+ 44, 47, 48, 50, 54, 56, 58, 59, 61, 63,
+ 64, 65, 72, 30, 25, 26, 71, 71, 30, 71,
+ 30, 30, 71, 25, 25, 25, 26, 29, 34, 75,
+ 76, 30, 1, 1, 45, 45, 51, 53, 57, 68,
+ 62, 68, 30, 73, 30, 30, 30, 30, 30, 75,
+ 75, 31, 32, 73, 27, 33, 30, 30, 1, 12,
+ 16, 17, 19, 20, 21, 22, 23, 25, 30, 40,
+ 46, 66, 67, 69, 18, 19, 20, 21, 30, 40,
+ 52, 67, 69, 39, 49, 72, 39, 50, 55, 61,
+ 72, 30, 40, 69, 39, 50, 60, 61, 72, 30,
+ 28, 75, 75, 76, 76, 30, 30, 24, 75, 75,
+ 71, 70, 71, 75, 25, 76, 1, 13, 30, 71,
+ 70, 25, 75, 30, 30, 14, 74, 30, 74, 74,
+ 74, 76, 30, 74, 30, 74, 30, 75, 30, 30,
+ 30, 74, 30, 30, 30
+};
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror ("syntax error: cannot back up");\
+ YYERROR; \
+ } \
+while (0)
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+ are run). */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ ((Current).first_line = (Rhs)[1].first_line, \
+ (Current).first_column = (Rhs)[1].first_column, \
+ (Current).last_line = (Rhs)[N].last_line, \
+ (Current).last_column = (Rhs)[N].last_column)
+#endif
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+# define YYDSYMPRINT(Args) \
+do { \
+ if (yydebug) \
+ yysymprint Args; \
+} while (0)
+
+# define YYDSYMPRINTF(Title, Token, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yysymprint (stderr, \
+ Token, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_stack_print (short int *bottom, short int *top)
+#else
+static void
+yy_stack_print (bottom, top)
+ short int *bottom;
+ short int *top;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (/* Nothing. */; bottom <= top; ++bottom)
+ YYFPRINTF (stderr, " %d", *bottom);
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_reduce_print (int yyrule)
+#else
+static void
+yy_reduce_print (yyrule)
+ int yyrule;
+#endif
+{
+ int yyi;
+ unsigned int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+ yyrule - 1, yylno);
+ /* Print the symbols being reduced, and their result. */
+ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
+ YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
+ YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (Rule); \
+} while (0)
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YYDSYMPRINT(Args)
+# define YYDSYMPRINTF(Title, Token, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined (__GLIBC__) && defined (_STRING_H)
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+static YYSIZE_T
+# if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+# else
+yystrlen (yystr)
+ const char *yystr;
+# endif
+{
+ register const char *yys = yystr;
+
+ while (*yys++ != '\0')
+ continue;
+
+ return yys - yystr - 1;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+static char *
+# if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+# else
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+# endif
+{
+ register char *yyd = yydest;
+ register const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+#endif /* !YYERROR_VERBOSE */
+
+
+
+#if YYDEBUG
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yysymprint (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ /* Pacify ``unused variable'' warnings. */
+ (void) yyvaluep;
+
+ if (yytype < YYNTOKENS)
+ {
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+# ifdef YYPRINT
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+ }
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+ YYFPRINTF (yyoutput, ")");
+}
+
+#endif /* ! YYDEBUG */
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yydestruct (int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yytype, yyvaluep)
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ /* Pacify ``unused variable'' warnings. */
+ (void) yyvaluep;
+
+ switch (yytype)
+ {
+ case 48: /* choice_entry */
+
+ {
+ fprintf(stderr, "%s:%d: missing end statement for this entry\n",
+ yyvaluep->menu->file->name, yyvaluep->menu->lineno);
+ if (current_menu == yyvaluep->menu)
+ menu_end_menu();
+};
+
+ break;
+ case 54: /* if_entry */
+
+ {
+ fprintf(stderr, "%s:%d: missing end statement for this entry\n",
+ yyvaluep->menu->file->name, yyvaluep->menu->lineno);
+ if (current_menu == yyvaluep->menu)
+ menu_end_menu();
+};
+
+ break;
+ case 59: /* menu_entry */
+
+ {
+ fprintf(stderr, "%s:%d: missing end statement for this entry\n",
+ yyvaluep->menu->file->name, yyvaluep->menu->lineno);
+ if (current_menu == yyvaluep->menu)
+ menu_end_menu();
+};
+
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes. */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM);
+# else
+int yyparse ();
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM)
+# else
+int yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+
+ register int yystate;
+ register int yyn;
+ int yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken = 0;
+
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ short int yyssa[YYINITDEPTH];
+ short int *yyss = yyssa;
+ register short int *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ register YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK (yyvsp--, yyssp--)
+
+ YYSIZE_T yystacksize = YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+
+ /* When reducing, the number of symbols on the RHS of the reduced
+ rule. */
+ int yylen;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks.
+ */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short int *yyss1 = yyss;
+
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow ("parser stack overflow",
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyoverflowlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyoverflowlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ short int *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyoverflowlab;
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a lookahead token if we need one and don't already have one. */
+/* yyresume: */
+
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+ YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 8:
+
+ { zconf_error("unexpected end statement"); ;}
+ break;
+
+ case 9:
+
+ { zconf_error("unknown statement \"%s\"", yyvsp[-2].string); ;}
+ break;
+
+ case 10:
+
+ {
+ zconf_error("unexpected option \"%s\"", kconf_id_strings + yyvsp[-2].id->name);
+;}
+ break;
+
+ case 11:
+
+ { zconf_error("invalid statement"); ;}
+ break;
+
+ case 25:
+
+ { zconf_error("unknown option \"%s\"", yyvsp[-2].string); ;}
+ break;
+
+ case 26:
+
+ { zconf_error("invalid option"); ;}
+ break;
+
+ case 27:
+
+ {
+ struct symbol *sym = sym_lookup(yyvsp[-1].string, 0);
+ sym->flags |= SYMBOL_OPTIONAL;
+ menu_add_entry(sym);
+ printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string);
+;}
+ break;
+
+ case 28:
+
+ {
+ menu_end_entry();
+ printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 29:
+
+ {
+ struct symbol *sym = sym_lookup(yyvsp[-1].string, 0);
+ sym->flags |= SYMBOL_OPTIONAL;
+ menu_add_entry(sym);
+ printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string);
+;}
+ break;
+
+ case 30:
+
+ {
+ if (current_entry->prompt)
+ current_entry->prompt->type = P_MENU;
+ else
+ zconfprint("warning: menuconfig statement without prompt");
+ menu_end_entry();
+ printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 37:
+
+ {
+ menu_set_type(yyvsp[-2].id->stype);
+ printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
+ zconf_curname(), zconf_lineno(),
+ yyvsp[-2].id->stype);
+;}
+ break;
+
+ case 38:
+
+ {
+ menu_add_prompt(P_PROMPT, yyvsp[-2].string, yyvsp[-1].expr);
+ printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 39:
+
+ {
+ menu_add_expr(P_DEFAULT, yyvsp[-2].expr, yyvsp[-1].expr);
+ if (yyvsp[-3].id->stype != S_UNKNOWN)
+ menu_set_type(yyvsp[-3].id->stype);
+ printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
+ zconf_curname(), zconf_lineno(),
+ yyvsp[-3].id->stype);
+;}
+ break;
+
+ case 40:
+
+ {
+ menu_add_symbol(P_SELECT, sym_lookup(yyvsp[-2].string, 0), yyvsp[-1].expr);
+ printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 41:
+
+ {
+ menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,yyvsp[-3].symbol, yyvsp[-2].symbol), yyvsp[-1].expr);
+ printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 42:
+
+ {
+ struct symbol *sym = sym_lookup(NULL, 0);
+ sym->flags |= SYMBOL_CHOICE;
+ menu_add_entry(sym);
+ menu_add_expr(P_CHOICE, NULL, NULL);
+ printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 43:
+
+ {
+ yyval.menu = menu_add_menu();
+;}
+ break;
+
+ case 44:
+
+ {
+ if (zconf_endtoken(yyvsp[0].id, T_CHOICE, T_ENDCHOICE)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
+ }
+;}
+ break;
+
+ case 52:
+
+ {
+ menu_add_prompt(P_PROMPT, yyvsp[-2].string, yyvsp[-1].expr);
+ printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 53:
+
+ {
+ if (yyvsp[-2].id->stype == S_BOOLEAN || yyvsp[-2].id->stype == S_TRISTATE) {
+ menu_set_type(yyvsp[-2].id->stype);
+ printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
+ zconf_curname(), zconf_lineno(),
+ yyvsp[-2].id->stype);
+ } else
+ YYERROR;
+;}
+ break;
+
+ case 54:
+
+ {
+ current_entry->sym->flags |= SYMBOL_OPTIONAL;
+ printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 55:
+
+ {
+ if (yyvsp[-3].id->stype == S_UNKNOWN) {
+ menu_add_symbol(P_DEFAULT, sym_lookup(yyvsp[-2].string, 0), yyvsp[-1].expr);
+ printd(DEBUG_PARSE, "%s:%d:default\n",
+ zconf_curname(), zconf_lineno());
+ } else
+ YYERROR;
+;}
+ break;
+
+ case 58:
+
+ {
+ printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
+ menu_add_entry(NULL);
+ menu_add_dep(yyvsp[-1].expr);
+ yyval.menu = menu_add_menu();
+;}
+ break;
+
+ case 59:
+
+ {
+ if (zconf_endtoken(yyvsp[0].id, T_IF, T_ENDIF)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
+ }
+;}
+ break;
+
+ case 65:
+
+ {
+ menu_add_entry(NULL);
+ menu_add_prompt(P_MENU, yyvsp[-1].string, NULL);
+ printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 66:
+
+ {
+ yyval.menu = menu_add_menu();
+;}
+ break;
+
+ case 67:
+
+ {
+ if (zconf_endtoken(yyvsp[0].id, T_MENU, T_ENDMENU)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
+ }
+;}
+ break;
+
+ case 73:
+
+ {
+ printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string);
+ zconf_nextfile(yyvsp[-1].string);
+;}
+ break;
+
+ case 74:
+
+ {
+ menu_add_entry(NULL);
+ menu_add_prompt(P_COMMENT, yyvsp[-1].string, NULL);
+ printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 75:
+
+ {
+ menu_end_entry();
+;}
+ break;
+
+ case 76:
+
+ {
+ printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
+ zconf_starthelp();
+;}
+ break;
+
+ case 77:
+
+ {
+ current_entry->sym->help = yyvsp[0].string;
+;}
+ break;
+
+ case 82:
+
+ {
+ menu_add_dep(yyvsp[-1].expr);
+ printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 83:
+
+ {
+ menu_add_dep(yyvsp[-1].expr);
+ printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 84:
+
+ {
+ menu_add_dep(yyvsp[-1].expr);
+ printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 86:
+
+ {
+ menu_add_prompt(P_PROMPT, yyvsp[-1].string, yyvsp[0].expr);
+;}
+ break;
+
+ case 89:
+
+ { yyval.id = yyvsp[-1].id; ;}
+ break;
+
+ case 90:
+
+ { yyval.id = yyvsp[-1].id; ;}
+ break;
+
+ case 91:
+
+ { yyval.id = yyvsp[-1].id; ;}
+ break;
+
+ case 94:
+
+ { yyval.expr = NULL; ;}
+ break;
+
+ case 95:
+
+ { yyval.expr = yyvsp[0].expr; ;}
+ break;
+
+ case 96:
+
+ { yyval.expr = expr_alloc_symbol(yyvsp[0].symbol); ;}
+ break;
+
+ case 97:
+
+ { yyval.expr = expr_alloc_comp(E_EQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); ;}
+ break;
+
+ case 98:
+
+ { yyval.expr = expr_alloc_comp(E_UNEQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); ;}
+ break;
+
+ case 99:
+
+ { yyval.expr = yyvsp[-1].expr; ;}
+ break;
+
+ case 100:
+
+ { yyval.expr = expr_alloc_one(E_NOT, yyvsp[0].expr); ;}
+ break;
+
+ case 101:
+
+ { yyval.expr = expr_alloc_two(E_OR, yyvsp[-2].expr, yyvsp[0].expr); ;}
+ break;
+
+ case 102:
+
+ { yyval.expr = expr_alloc_two(E_AND, yyvsp[-2].expr, yyvsp[0].expr); ;}
+ break;
+
+ case 103:
+
+ { yyval.symbol = sym_lookup(yyvsp[0].string, 0); free(yyvsp[0].string); ;}
+ break;
+
+ case 104:
+
+ { yyval.symbol = sym_lookup(yyvsp[0].string, 1); free(yyvsp[0].string); ;}
+ break;
+
+
+ }
+
+/* Line 1010 of yacc.c. */
+
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+
+
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+ if (YYPACT_NINF < yyn && yyn < YYLAST)
+ {
+ YYSIZE_T yysize = 0;
+ int yytype = YYTRANSLATE (yychar);
+ const char* yyprefix;
+ char *yymsg;
+ int yyx;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 0;
+
+ yyprefix = ", expecting ";
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
+ yycount += 1;
+ if (yycount == 5)
+ {
+ yysize = 0;
+ break;
+ }
+ }
+ yysize += (sizeof ("syntax error, unexpected ")
+ + yystrlen (yytname[yytype]));
+ yymsg = (char *) YYSTACK_ALLOC (yysize);
+ if (yymsg != 0)
+ {
+ char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
+ yyp = yystpcpy (yyp, yytname[yytype]);
+
+ if (yycount < 5)
+ {
+ yyprefix = ", expecting ";
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ yyp = yystpcpy (yyp, yyprefix);
+ yyp = yystpcpy (yyp, yytname[yyx]);
+ yyprefix = " or ";
+ }
+ }
+ yyerror (yymsg);
+ YYSTACK_FREE (yymsg);
+ }
+ else
+ yyerror ("syntax error; also virtual memory exhausted");
+ }
+ else
+#endif /* YYERROR_VERBOSE */
+ yyerror ("syntax error");
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* If at end of input, pop the error token,
+ then the rest of the stack, then return failure. */
+ if (yychar == YYEOF)
+ for (;;)
+ {
+ YYPOPSTACK;
+ if (yyssp == yyss)
+ YYABORT;
+ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+ yydestruct (yystos[*yyssp], yyvsp);
+ }
+ }
+ else
+ {
+ YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
+ yydestruct (yytoken, &yylval);
+ yychar = YYEMPTY;
+
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+#ifdef __GNUC__
+ /* Pacify GCC when the user code never invokes YYERROR and the label
+ yyerrorlab therefore never appears in user code. */
+ if (0)
+ goto yyerrorlab;
+#endif
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+ yydestruct (yystos[yystate], yyvsp);
+ YYPOPSTACK;
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ YYDPRINTF ((stderr, "Shifting error token, "));
+
+ *++yyvsp = yylval;
+
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#ifndef yyoverflow
+/*----------------------------------------------.
+| yyoverflowlab -- parser overflow comes here. |
+`----------------------------------------------*/
+yyoverflowlab:
+ yyerror ("parser stack overflow");
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+ return yyresult;
+}
+
+
+
+
+
+void conf_parse(const char *name)
+{
+ struct symbol *sym;
+ int i;
+
+ zconf_initscan(name);
+
+ sym_init();
+ menu_init();
+ modules_sym = sym_lookup("MODULES", 0);
+ rootmenu.prompt = menu_add_prompt(P_MENU, "OpenWrt Configuration", NULL);
+
+#if YYDEBUG
+ if (getenv("ZCONF_DEBUG"))
+ zconfdebug = 1;
+#endif
+ zconfparse();
+ if (zconfnerrs)
+ exit(1);
+ menu_finalize(&rootmenu);
+ for_all_symbols(i, sym) {
+ sym_check_deps(sym);
+ }
+
+ sym_change_count = 1;
+}
+
+const char *zconf_tokenname(int token)
+{
+ switch (token) {
+ case T_MENU: return "menu";
+ case T_ENDMENU: return "endmenu";
+ case T_CHOICE: return "choice";
+ case T_ENDCHOICE: return "endchoice";
+ case T_IF: return "if";
+ case T_ENDIF: return "endif";
+ case T_DEPENDS: return "depends";
+ }
+ return "<token>";
+}
+
+static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken)
+{
+ if (id->token != endtoken) {
+ zconf_error("unexpected '%s' within %s block",
+ kconf_id_strings + id->name, zconf_tokenname(starttoken));
+ zconfnerrs++;
+ return false;
+ }
+ if (current_menu->file != current_file) {
+ zconf_error("'%s' in different file than '%s'",
+ kconf_id_strings + id->name, zconf_tokenname(starttoken));
+ fprintf(stderr, "%s:%d: location of the '%s'\n",
+ current_menu->file->name, current_menu->lineno,
+ zconf_tokenname(starttoken));
+ zconfnerrs++;
+ return false;
+ }
+ return true;
+}
+
+static void zconfprint(const char *err, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
+ va_start(ap, err);
+ vfprintf(stderr, err, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+}
+
+static void zconf_error(const char *err, ...)
+{
+ va_list ap;
+
+ zconfnerrs++;
+ fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
+ va_start(ap, err);
+ vfprintf(stderr, err, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+}
+
+static void zconferror(const char *err)
+{
+#if YYDEBUG
+ fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
+#endif
+}
+
+void print_quoted_string(FILE *out, const char *str)
+{
+ const char *p;
+ int len;
+
+ putc('"', out);
+ while ((p = strchr(str, '"'))) {
+ len = p - str;
+ if (len)
+ fprintf(out, "%.*s", len, str);
+ fputs("\\\"", out);
+ str = p + 1;
+ }
+ fputs(str, out);
+ putc('"', out);
+}
+
+void print_symbol(FILE *out, struct menu *menu)
+{
+ struct symbol *sym = menu->sym;
+ struct property *prop;
+
+ if (sym_is_choice(sym))
+ fprintf(out, "choice\n");
+ else
+ fprintf(out, "config %s\n", sym->name);
+ switch (sym->type) {
+ case S_BOOLEAN:
+ fputs(" boolean\n", out);
+ break;
+ case S_TRISTATE:
+ fputs(" tristate\n", out);
+ break;
+ case S_STRING:
+ fputs(" string\n", out);
+ break;
+ case S_INT:
+ fputs(" integer\n", out);
+ break;
+ case S_HEX:
+ fputs(" hex\n", out);
+ break;
+ default:
+ fputs(" ???\n", out);
+ break;
+ }
+ for (prop = sym->prop; prop; prop = prop->next) {
+ if (prop->menu != menu)
+ continue;
+ switch (prop->type) {
+ case P_PROMPT:
+ fputs(" prompt ", out);
+ print_quoted_string(out, prop->text);
+ if (!expr_is_yes(prop->visible.expr)) {
+ fputs(" if ", out);
+ expr_fprint(prop->visible.expr, out);
+ }
+ fputc('\n', out);
+ break;
+ case P_DEFAULT:
+ fputs( " default ", out);
+ expr_fprint(prop->expr, out);
+ if (!expr_is_yes(prop->visible.expr)) {
+ fputs(" if ", out);
+ expr_fprint(prop->visible.expr, out);
+ }
+ fputc('\n', out);
+ break;
+ case P_CHOICE:
+ fputs(" #choice value\n", out);
+ break;
+ default:
+ fprintf(out, " unknown prop %d!\n", prop->type);
+ break;
+ }
+ }
+ if (sym->help) {
+ int len = strlen(sym->help);
+ while (sym->help[--len] == '\n')
+ sym->help[len] = 0;
+ fprintf(out, " help\n%s\n", sym->help);
+ }
+ fputc('\n', out);
+}
+
+void zconfdump(FILE *out)
+{
+ struct property *prop;
+ struct symbol *sym;
+ struct menu *menu;
+
+ menu = rootmenu.list;
+ while (menu) {
+ if ((sym = menu->sym))
+ print_symbol(out, menu);
+ else if ((prop = menu->prompt)) {
+ switch (prop->type) {
+ case P_COMMENT:
+ fputs("\ncomment ", out);
+ print_quoted_string(out, prop->text);
+ fputs("\n", out);
+ break;
+ case P_MENU:
+ fputs("\nmenu ", out);
+ print_quoted_string(out, prop->text);
+ fputs("\n", out);
+ break;
+ default:
+ ;
+ }
+ if (!expr_is_yes(prop->visible.expr)) {
+ fputs(" depends ", out);
+ expr_fprint(prop->visible.expr, out);
+ fputc('\n', out);
+ }
+ fputs("\n", out);
+ }
+
+ if (menu->list)
+ menu = menu->list;
+ else if (menu->next)
+ menu = menu->next;
+ else while ((menu = menu->parent)) {
+ if (menu->prompt && menu->prompt->type == P_MENU)
+ fputs("\nendmenu\n", out);
+ if (menu->next) {
+ menu = menu->next;
+ break;
+ }
+ }
+ }
+}
+
+#include "lex.zconf.c"
+#include "util.c"
+#include "confdata.c"
+#include "expr.c"
+#include "symbol.c"
+#include "menu.c"
+
+
diff --git a/scripts/config/zconf.y b/scripts/config/zconf.y
new file mode 100644
index 0000000000..83243f5efe
--- /dev/null
+++ b/scripts/config/zconf.y
@@ -0,0 +1,681 @@
+%{
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+#include "zconf.hash.c"
+
+#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
+
+#define PRINTD 0x0001
+#define DEBUG_PARSE 0x0002
+
+int cdebug = PRINTD;
+
+extern int zconflex(void);
+static void zconfprint(const char *err, ...);
+static void zconf_error(const char *err, ...);
+static void zconferror(const char *err);
+static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken);
+
+struct symbol *symbol_hash[257];
+
+static struct menu *current_menu, *current_entry;
+
+#define YYDEBUG 0
+#if YYDEBUG
+#define YYERROR_VERBOSE
+#endif
+%}
+%expect 26
+
+%union
+{
+ char *string;
+ struct file *file;
+ struct symbol *symbol;
+ struct expr *expr;
+ struct menu *menu;
+ struct kconf_id *id;
+}
+
+%token <id>T_MAINMENU
+%token <id>T_MENU
+%token <id>T_ENDMENU
+%token <id>T_SOURCE
+%token <id>T_CHOICE
+%token <id>T_ENDCHOICE
+%token <id>T_COMMENT
+%token <id>T_CONFIG
+%token <id>T_MENUCONFIG
+%token <id>T_HELP
+%token <string> T_HELPTEXT
+%token <id>T_IF
+%token <id>T_ENDIF
+%token <id>T_DEPENDS
+%token <id>T_REQUIRES
+%token <id>T_OPTIONAL
+%token <id>T_PROMPT
+%token <id>T_TYPE
+%token <id>T_DEFAULT
+%token <id>T_SELECT
+%token <id>T_RANGE
+%token <id>T_ON
+%token <string> T_WORD
+%token <string> T_WORD_QUOTE
+%token T_UNEQUAL
+%token T_CLOSE_PAREN
+%token T_OPEN_PAREN
+%token T_EOL
+
+%left T_OR
+%left T_AND
+%left T_EQUAL T_UNEQUAL
+%nonassoc T_NOT
+
+%type <string> prompt
+%type <symbol> symbol
+%type <expr> expr
+%type <expr> if_expr
+%type <id> end
+%type <id> option_name
+%type <menu> if_entry menu_entry choice_entry
+
+%destructor {
+ fprintf(stderr, "%s:%d: missing end statement for this entry\n",
+ $$->file->name, $$->lineno);
+ if (current_menu == $$)
+ menu_end_menu();
+} if_entry menu_entry choice_entry
+
+%%
+input: stmt_list;
+
+stmt_list:
+ /* empty */
+ | stmt_list common_stmt
+ | stmt_list choice_stmt
+ | stmt_list menu_stmt
+ | stmt_list T_MAINMENU prompt nl
+ | stmt_list end { zconf_error("unexpected end statement"); }
+ | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
+ | stmt_list option_name error T_EOL
+{
+ zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name);
+}
+ | stmt_list error T_EOL { zconf_error("invalid statement"); }
+;
+
+option_name:
+ T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT
+;
+
+common_stmt:
+ T_EOL
+ | if_stmt
+ | comment_stmt
+ | config_stmt
+ | menuconfig_stmt
+ | source_stmt
+;
+
+option_error:
+ T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); }
+ | error T_EOL { zconf_error("invalid option"); }
+;
+
+
+/* config/menuconfig entry */
+
+config_entry_start: T_CONFIG T_WORD T_EOL
+{
+ struct symbol *sym = sym_lookup($2, 0);
+ sym->flags |= SYMBOL_OPTIONAL;
+ menu_add_entry(sym);
+ printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
+};
+
+config_stmt: config_entry_start config_option_list
+{
+ menu_end_entry();
+ printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+};
+
+menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL
+{
+ struct symbol *sym = sym_lookup($2, 0);
+ sym->flags |= SYMBOL_OPTIONAL;
+ menu_add_entry(sym);
+ printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
+};
+
+menuconfig_stmt: menuconfig_entry_start config_option_list
+{
+ if (current_entry->prompt)
+ current_entry->prompt->type = P_MENU;
+ else
+ zconfprint("warning: menuconfig statement without prompt");
+ menu_end_entry();
+ printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+};
+
+config_option_list:
+ /* empty */
+ | config_option_list config_option
+ | config_option_list depends
+ | config_option_list help
+ | config_option_list option_error
+ | config_option_list T_EOL
+;
+
+config_option: T_TYPE prompt_stmt_opt T_EOL
+{
+ menu_set_type($1->stype);
+ printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
+ zconf_curname(), zconf_lineno(),
+ $1->stype);
+};
+
+config_option: T_PROMPT prompt if_expr T_EOL
+{
+ menu_add_prompt(P_PROMPT, $2, $3);
+ printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_DEFAULT expr if_expr T_EOL
+{
+ menu_add_expr(P_DEFAULT, $2, $3);
+ if ($1->stype != S_UNKNOWN)
+ menu_set_type($1->stype);
+ printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
+ zconf_curname(), zconf_lineno(),
+ $1->stype);
+};
+
+config_option: T_SELECT T_WORD if_expr T_EOL
+{
+ menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
+ printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_RANGE symbol symbol if_expr T_EOL
+{
+ menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
+ printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
+};
+
+/* choice entry */
+
+choice: T_CHOICE T_EOL
+{
+ struct symbol *sym = sym_lookup(NULL, 0);
+ sym->flags |= SYMBOL_CHOICE;
+ menu_add_entry(sym);
+ menu_add_expr(P_CHOICE, NULL, NULL);
+ printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
+};
+
+choice_entry: choice choice_option_list
+{
+ $$ = menu_add_menu();
+};
+
+choice_end: end
+{
+ if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
+ }
+};
+
+choice_stmt: choice_entry choice_block choice_end
+;
+
+choice_option_list:
+ /* empty */
+ | choice_option_list choice_option
+ | choice_option_list depends
+ | choice_option_list help
+ | choice_option_list T_EOL
+ | choice_option_list option_error
+;
+
+choice_option: T_PROMPT prompt if_expr T_EOL
+{
+ menu_add_prompt(P_PROMPT, $2, $3);
+ printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+};
+
+choice_option: T_TYPE prompt_stmt_opt T_EOL
+{
+ if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) {
+ menu_set_type($1->stype);
+ printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
+ zconf_curname(), zconf_lineno(),
+ $1->stype);
+ } else
+ YYERROR;
+};
+
+choice_option: T_OPTIONAL T_EOL
+{
+ current_entry->sym->flags |= SYMBOL_OPTIONAL;
+ printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
+};
+
+choice_option: T_DEFAULT T_WORD if_expr T_EOL
+{
+ if ($1->stype == S_UNKNOWN) {
+ menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
+ printd(DEBUG_PARSE, "%s:%d:default\n",
+ zconf_curname(), zconf_lineno());
+ } else
+ YYERROR;
+};
+
+choice_block:
+ /* empty */
+ | choice_block common_stmt
+;
+
+/* if entry */
+
+if_entry: T_IF expr nl
+{
+ printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
+ menu_add_entry(NULL);
+ menu_add_dep($2);
+ $$ = menu_add_menu();
+};
+
+if_end: end
+{
+ if (zconf_endtoken($1, T_IF, T_ENDIF)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
+ }
+};
+
+if_stmt: if_entry if_block if_end
+;
+
+if_block:
+ /* empty */
+ | if_block common_stmt
+ | if_block menu_stmt
+ | if_block choice_stmt
+;
+
+/* menu entry */
+
+menu: T_MENU prompt T_EOL
+{
+ menu_add_entry(NULL);
+ menu_add_prompt(P_MENU, $2, NULL);
+ printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
+};
+
+menu_entry: menu depends_list
+{
+ $$ = menu_add_menu();
+};
+
+menu_end: end
+{
+ if (zconf_endtoken($1, T_MENU, T_ENDMENU)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
+ }
+};
+
+menu_stmt: menu_entry menu_block menu_end
+;
+
+menu_block:
+ /* empty */
+ | menu_block common_stmt
+ | menu_block menu_stmt
+ | menu_block choice_stmt
+;
+
+source_stmt: T_SOURCE prompt T_EOL
+{
+ printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
+ zconf_nextfile($2);
+};
+
+/* comment entry */
+
+comment: T_COMMENT prompt T_EOL
+{
+ menu_add_entry(NULL);
+ menu_add_prompt(P_COMMENT, $2, NULL);
+ printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
+};
+
+comment_stmt: comment depends_list
+{
+ menu_end_entry();
+};
+
+/* help option */
+
+help_start: T_HELP T_EOL
+{
+ printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
+ zconf_starthelp();
+};
+
+help: help_start T_HELPTEXT
+{
+ current_entry->sym->help = $2;
+};
+
+/* depends option */
+
+depends_list:
+ /* empty */
+ | depends_list depends
+ | depends_list T_EOL
+ | depends_list option_error
+;
+
+depends: T_DEPENDS T_ON expr T_EOL
+{
+ menu_add_dep($3);
+ printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
+}
+ | T_DEPENDS expr T_EOL
+{
+ menu_add_dep($2);
+ printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
+}
+ | T_REQUIRES expr T_EOL
+{
+ menu_add_dep($2);
+ printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
+};
+
+/* prompt statement */
+
+prompt_stmt_opt:
+ /* empty */
+ | prompt if_expr
+{
+ menu_add_prompt(P_PROMPT, $1, $2);
+};
+
+prompt: T_WORD
+ | T_WORD_QUOTE
+;
+
+end: T_ENDMENU T_EOL { $$ = $1; }
+ | T_ENDCHOICE T_EOL { $$ = $1; }
+ | T_ENDIF T_EOL { $$ = $1; }
+;
+
+nl:
+ T_EOL
+ | nl T_EOL
+;
+
+if_expr: /* empty */ { $$ = NULL; }
+ | T_IF expr { $$ = $2; }
+;
+
+expr: symbol { $$ = expr_alloc_symbol($1); }
+ | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
+ | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
+ | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; }
+ | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); }
+ | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); }
+ | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); }
+;
+
+symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
+ | T_WORD_QUOTE { $$ = sym_lookup($1, 1); free($1); }
+;
+
+%%
+
+void conf_parse(const char *name)
+{
+ struct symbol *sym;
+ int i;
+
+ zconf_initscan(name);
+
+ sym_init();
+ menu_init();
+ modules_sym = sym_lookup("MODULES", 0);
+ rootmenu.prompt = menu_add_prompt(P_MENU, "OpenWrt Configuration", NULL);
+
+#if YYDEBUG
+ if (getenv("ZCONF_DEBUG"))
+ zconfdebug = 1;
+#endif
+ zconfparse();
+ if (zconfnerrs)
+ exit(1);
+ menu_finalize(&rootmenu);
+ for_all_symbols(i, sym) {
+ sym_check_deps(sym);
+ }
+
+ sym_change_count = 1;
+}
+
+const char *zconf_tokenname(int token)
+{
+ switch (token) {
+ case T_MENU: return "menu";
+ case T_ENDMENU: return "endmenu";
+ case T_CHOICE: return "choice";
+ case T_ENDCHOICE: return "endchoice";
+ case T_IF: return "if";
+ case T_ENDIF: return "endif";
+ case T_DEPENDS: return "depends";
+ }
+ return "<token>";
+}
+
+static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken)
+{
+ if (id->token != endtoken) {
+ zconf_error("unexpected '%s' within %s block",
+ kconf_id_strings + id->name, zconf_tokenname(starttoken));
+ zconfnerrs++;
+ return false;
+ }
+ if (current_menu->file != current_file) {
+ zconf_error("'%s' in different file than '%s'",
+ kconf_id_strings + id->name, zconf_tokenname(starttoken));
+ fprintf(stderr, "%s:%d: location of the '%s'\n",
+ current_menu->file->name, current_menu->lineno,
+ zconf_tokenname(starttoken));
+ zconfnerrs++;
+ return false;
+ }
+ return true;
+}
+
+static void zconfprint(const char *err, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
+ va_start(ap, err);
+ vfprintf(stderr, err, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+}
+
+static void zconf_error(const char *err, ...)
+{
+ va_list ap;
+
+ zconfnerrs++;
+ fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
+ va_start(ap, err);
+ vfprintf(stderr, err, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+}
+
+static void zconferror(const char *err)
+{
+#if YYDEBUG
+ fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
+#endif
+}
+
+void print_quoted_string(FILE *out, const char *str)
+{
+ const char *p;
+ int len;
+
+ putc('"', out);
+ while ((p = strchr(str, '"'))) {
+ len = p - str;
+ if (len)
+ fprintf(out, "%.*s", len, str);
+ fputs("\\\"", out);
+ str = p + 1;
+ }
+ fputs(str, out);
+ putc('"', out);
+}
+
+void print_symbol(FILE *out, struct menu *menu)
+{
+ struct symbol *sym = menu->sym;
+ struct property *prop;
+
+ if (sym_is_choice(sym))
+ fprintf(out, "choice\n");
+ else
+ fprintf(out, "config %s\n", sym->name);
+ switch (sym->type) {
+ case S_BOOLEAN:
+ fputs(" boolean\n", out);
+ break;
+ case S_TRISTATE:
+ fputs(" tristate\n", out);
+ break;
+ case S_STRING:
+ fputs(" string\n", out);
+ break;
+ case S_INT:
+ fputs(" integer\n", out);
+ break;
+ case S_HEX:
+ fputs(" hex\n", out);
+ break;
+ default:
+ fputs(" ???\n", out);
+ break;
+ }
+ for (prop = sym->prop; prop; prop = prop->next) {
+ if (prop->menu != menu)
+ continue;
+ switch (prop->type) {
+ case P_PROMPT:
+ fputs(" prompt ", out);
+ print_quoted_string(out, prop->text);
+ if (!expr_is_yes(prop->visible.expr)) {
+ fputs(" if ", out);
+ expr_fprint(prop->visible.expr, out);
+ }
+ fputc('\n', out);
+ break;
+ case P_DEFAULT:
+ fputs( " default ", out);
+ expr_fprint(prop->expr, out);
+ if (!expr_is_yes(prop->visible.expr)) {
+ fputs(" if ", out);
+ expr_fprint(prop->visible.expr, out);
+ }
+ fputc('\n', out);
+ break;
+ case P_CHOICE:
+ fputs(" #choice value\n", out);
+ break;
+ default:
+ fprintf(out, " unknown prop %d!\n", prop->type);
+ break;
+ }
+ }
+ if (sym->help) {
+ int len = strlen(sym->help);
+ while (sym->help[--len] == '\n')
+ sym->help[len] = 0;
+ fprintf(out, " help\n%s\n", sym->help);
+ }
+ fputc('\n', out);
+}
+
+void zconfdump(FILE *out)
+{
+ struct property *prop;
+ struct symbol *sym;
+ struct menu *menu;
+
+ menu = rootmenu.list;
+ while (menu) {
+ if ((sym = menu->sym))
+ print_symbol(out, menu);
+ else if ((prop = menu->prompt)) {
+ switch (prop->type) {
+ case P_COMMENT:
+ fputs("\ncomment ", out);
+ print_quoted_string(out, prop->text);
+ fputs("\n", out);
+ break;
+ case P_MENU:
+ fputs("\nmenu ", out);
+ print_quoted_string(out, prop->text);
+ fputs("\n", out);
+ break;
+ default:
+ ;
+ }
+ if (!expr_is_yes(prop->visible.expr)) {
+ fputs(" depends ", out);
+ expr_fprint(prop->visible.expr, out);
+ fputc('\n', out);
+ }
+ fputs("\n", out);
+ }
+
+ if (menu->list)
+ menu = menu->list;
+ else if (menu->next)
+ menu = menu->next;
+ else while ((menu = menu->parent)) {
+ if (menu->prompt && menu->prompt->type == P_MENU)
+ fputs("\nendmenu\n", out);
+ if (menu->next) {
+ menu = menu->next;
+ break;
+ }
+ }
+ }
+}
+
+#include "lex.zconf.c"
+#include "util.c"
+#include "confdata.c"
+#include "expr.c"
+#include "symbol.c"
+#include "menu.c"
diff --git a/scripts/configtest.pl b/scripts/configtest.pl
new file mode 100755
index 0000000000..289b2fecc0
--- /dev/null
+++ b/scripts/configtest.pl
@@ -0,0 +1,35 @@
+#!/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.
+#
+
+my %change = (
+ '^BUSYBOX' => 'make package/busybox-clean',
+ 'OPENVPN_' => 'make package/openvpn-clean',
+ 'SYSCONF_' => 'make package/base-files-clean target_clean',
+ '' => 'make target_clean'
+);
+
+my @configfiles = (
+# ['package/linux/linux.config', 'build_mipsel/linux/.config' =>
+# 'make -C package linux-clean']
+);
+
+
+
+foreach my $change (keys %change) {
+ my $v1 = `grep '$change' .config.test`;
+ my $v2 = `grep '$change' .config`;
+ $v1 eq $v2 or system($change{$change});
+}
+
+foreach my $file (@configfiles) {
+ if ((-f $file->[0]) and (-f $file->[1])) {
+ my @s1 = stat $file->[0];
+ my @s2 = stat $file->[1];
+ $s1[9] > $s2[9] and system($file->[2]);
+ }
+}
diff --git a/scripts/download.pl b/scripts/download.pl
new file mode 100755
index 0000000000..f636cca7eb
--- /dev/null
+++ b/scripts/download.pl
@@ -0,0 +1,112 @@
+#!/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;
+use warnings;
+
+my $target = shift @ARGV;
+my $filename = shift @ARGV;
+my $md5sum = shift @ARGV;
+my @mirrors;
+
+my $ok;
+
+@ARGV > 0 or die "Syntax: $0 <target dir> <filename> <md5sum> <mirror> [<mirror> ...]\n";
+
+my $md5cmd = `which md5sum`;
+$md5cmd or $md5cmd = `which md5`;
+$md5cmd or die 'no md5 checksum program found, please install md5 or md5sum';
+chomp $md5cmd;
+
+sub download
+{
+ my $mirror = shift;
+
+ open WGET, "wget -t1 --timeout=20 -O- \"$mirror/$filename\" |" or die "Cannot launch wget.\n";
+ open MD5SUM, "| $md5cmd > \"$target/$filename.md5sum\"" or die "Cannot launch md5sum.\n";
+ open OUTPUT, "> $target/$filename.dl" or die "Cannot create file $target/$filename.dl: $!\n";
+ my $buffer;
+ while (read WGET, $buffer, 1048576) {
+ print MD5SUM $buffer;
+ print OUTPUT $buffer;
+ }
+ close MD5SUM;
+ close WGET;
+ close OUTPUT;
+
+ if (($? >> 8) != 0 ) {
+ print STDERR "Download failed.\n";
+ cleanup();
+ return;
+ }
+
+ my $sum = `cat "$target/$filename.md5sum"`;
+ $sum =~ /^(\w+)\s*/ or die "Could not generate md5sum\n";
+ $sum = $1;
+
+ if (($md5sum =~ /\w{32}/) and ($sum ne $md5sum)) {
+ print STDERR "MD5 sum of the downloaded file does not match - deleting download.\n";
+ cleanup();
+ return;
+ }
+
+ unlink "$target/$filename";
+ system("mv \"$target/$filename.dl\" \"$target/$filename\"");
+ cleanup();
+}
+
+sub cleanup
+{
+ unlink "$target/$filename.dl";
+ unlink "$target/$filename.md5sum";
+}
+
+foreach my $mirror (@ARGV) {
+ if ($mirror =~ /^\@SF\/(.+)$/) {
+ my $sfpath = $1;
+ open SF, "wget -t1 -q -O- 'http://prdownloads.sourceforge.net/$sfpath/$filename' |";
+ while (<SF>) {
+ /RADIO NAME=use_default VALUE=(\w+) OnClick="form\.submit\(\)">/ or
+ /type="radio" name="use_default" value="(\w+)" onclick="form\.submit\(\)"\/>/ and do {
+ push @mirrors, "http://$1.dl.sourceforge.net/sourceforge/$sfpath";
+ };
+ /<a href="\/.+\?use_mirror=(\w+)"><b>Download/ and do {
+ push @mirrors, "http://$1.dl.sourceforge.net/sourceforge/$sfpath";
+ };
+ }
+ push @mirrors, "http://dl.sourceforge.net/sourceforge/$sfpath";
+ close SF;
+ } elsif ($mirror =~ /^\@GNU\/(.+)$/) {
+ my $gnupath = $1;
+ push @mirrors, "ftp://ftp.gnu.org/gnu/$gnupath";
+ push @mirrors, "ftp://ftp.belnet.be/mirror/ftp.gnu.org/gnu/$gnupath";
+ push @mirrors, "ftp://ftp.mirror.nl/pub/mirror/gnu/$gnupath";
+ push @mirrors, "http://mirror.switch.ch/ftp/mirror/gnu/$gnupath";
+ push @mirrors, "ftp://ftp.uu.net/archive/systems/gnu/$gnupath";
+ push @mirrors, "ftp://ftp.eu.uu.net/pub/gnu/$gnupath";
+ push @mirrors, "ftp://ftp.leo.org/pub/comp/os/unix/gnu/$gnupath";
+ push @mirrors, "ftp://ftp.digex.net/pub/gnu/$gnupath";
+ } else {
+ push @mirrors, $mirror;
+ }
+}
+
+#push @mirrors, 'http://mirror1.openwrt.org/';
+push @mirrors, 'http://mirror2.openwrt.org/sources';
+push @mirrors, 'http://downloads.openwrt.org/sources/';
+
+while (!$ok) {
+ my $mirror = shift @mirrors;
+ $mirror or die "No more mirrors to try - giving up.\n";
+
+ download($mirror);
+ -f "$target/$filename" and $ok = 1;
+}
+
+$SIG{INT} = \&cleanup;
+
diff --git a/scripts/flash.sh b/scripts/flash.sh
new file mode 100644
index 0000000000..8841c35684
--- /dev/null
+++ b/scripts/flash.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+#
+# tftp flash script for wireless routers
+#
+# Copyright (C) 2004 by Oleg I. Vdovikin <oleg@cs.msu.su>
+# Copyright (C) 2005 by Waldemar Brodkorb <wbx@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
+#
+
+if [ -z "$1" ] || [ ! -f $1 ] || [ -z $2 ]; then
+ echo Usage: $0 firmware vendor
+cat << EOF
+IMPORTANT:
+Notes for Linksys / Asus WL500gx router:
+ be sure you have set boot_wait to yes. Power on your router
+ after executing this script.
+
+Notes for Asus WL500g router:
+ be sure POWER led is flashing (If this is not the case
+ poweroff the device, push the reset button & power on
+ it again, then release button)
+
+1) connect your pc to the LAN port
+2) be sure your link is up and has an address in the
+ 192.168.1.0/24 address range (and not the 192.168.1.1)
+
+Notes for Toshiba router:
+ boot_wait is enabled by default on these units.
+
+1) connect your pc to any of the four LAN ports
+2) be sure your link is up and has an address in the
+ 192.168.10.1/24 address range (and not the 192.168.10.1)
+3) run this script (unit will only accept .trx images)
+4) Turn unit power on.
+
+EOF
+ exit 0
+fi
+if [ "$2" == "asus" ]; then
+echo Confirming IP address setting...
+echo -en "get ASUSSPACELINK\x01\x01\xa8\xc0 /dev/null\nquit\n" | tftp 192.168.1.1
+echo Flashing 192.168.1.1 using $1...
+echo -en "binary\nput $1 ASUSSPACELINK\nquit\n" | tftp 192.168.1.1
+echo Please wait until leds stops flashing.
+elif [ "$2" == "linksys" ]; then
+echo Flashing 192.168.1.1 using $1...
+echo -en "rexmt 1\ntrace\nbinary\nput $1\nquit\n" | tftp 192.168.1.1
+echo Please wait until power led stops flashing. Do not poweroff! Then you can login via telnet 192.168.1.1.
+elif [ "$2" == "toshiba" ]; then
+echo Flashing 192.168.10.1 using $1...
+echo -en "rexmt 1\ntrace\nbinary\nput $1\nquit\n" | tftp 192.168.10.1
+echo Unit will automatically reboot within 5 minutes. Do not power off. Then you can login via telnet 192.168.10.1.
+fi
diff --git a/scripts/gen_busybox_config.pl b/scripts/gen_busybox_config.pl
new file mode 100755
index 0000000000..9360052d29
--- /dev/null
+++ b/scripts/gen_busybox_config.pl
@@ -0,0 +1,29 @@
+#!/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 $line;
+my $l1 = '';
+my $l2 = '=y';
+while (<>) {
+ chomp;
+ /^(# )CONFIG_LARGEFILE(.+)$/ and do {
+ $l1 = $1;
+ $l2 = $2;
+ };
+ /^(# )?CONFIG_BUSYBOX_(.+)/ and do {
+ my $p1 = $1;
+ my $p2 = $2;
+ $p2 =~ /(CONFIG_LFS|FDISK_SUPPORT_LARGE_DISKS)/ and do {
+ $p1 = $l1;
+ $p2 = "$1$l2";
+ };
+ print "$p1$p2\n";
+ }
+}
diff --git a/scripts/gen_busybox_menuconfig.pl b/scripts/gen_busybox_menuconfig.pl
new file mode 100644
index 0000000000..5fe64783eb
--- /dev/null
+++ b/scripts/gen_busybox_menuconfig.pl
@@ -0,0 +1,76 @@
+#!/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>) {
+ /^([\w_]+)=([ym])/ and $config{$1} = $2;
+ /^([\w_]+)=(\d+)/ and $config{$1} = $2;
+ /^([\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 CONFIG_FEATURE_BUFFERS_USE_MALLOC/default CONFIG_FEATURE_BUFFERS_GO_ON_STACK/;
+ $line =~ s/default BUSYBOX_CONFIG_FEATURE_SH_IS_NONE/default BUSYBOX_CONFIG_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+)((CONFIG|FDISK|USING|CROSS|EXTRA|PREFIX|FEATURE|HAVE|BUSYBOX)[\w_]*)/$1BUSYBOX_$2/g;
+
+ if ($cur) {
+ ($cur !~ /^CONFIG/ or $cur eq 'CONFIG_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/scripts/gen_deps.pl b/scripts/gen_deps.pl
new file mode 100755
index 0000000000..745d31c7d0
--- /dev/null
+++ b/scripts/gen_deps.pl
@@ -0,0 +1,91 @@
+#!/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 $name;
+my $src;
+my $makefile;
+my %conf;
+my %pkg;
+my %prereq;
+my %dep;
+my %options;
+my $opt;
+
+while ($opt = shift @ARGV) {
+ $opt =~ /^-s/ and $options{SDK} = 1;
+}
+
+my $line;
+while ($line = <>) {
+ chomp $line;
+ $line =~ /^Source-Makefile: \s*(.+\/([^\/]+)\/Makefile)\s*$/ and do {
+ $makefile = $1;
+ $src = $2;
+ };
+ $line =~ /^Package: \s*(.+)\s*$/ and do {
+ $name = $1;
+ defined $pkg{$name} or $pkg{$name} = {};
+ $pkg{$name}->{src} = $src;
+ };
+ $line =~ /^Prereq-Check:/ and !defined $prereq{$src} and do {
+ $pkg{$name}->{prereq} = 1;
+ };
+ $line =~ /^(Build-)?Depends: \s*(.+)\s*$/ and do {
+ $pkg{$name}->{depends} ||= [];
+ foreach my $v (split /\s+/, $2) {
+ next if $v =~ /^[\+]?@/;
+ $v =~ s/^\+//;
+ push @{$pkg{$name}->{depends}}, $v;
+ }
+ };
+}
+
+$line="";
+
+foreach $name (sort {uc($a) cmp uc($b)} keys %pkg) {
+ my $config;
+
+ if ($options{SDK}) {
+ $conf{$pkg{$name}->{src}} or do {
+ $config = 'm';
+ $conf{$pkg{$name}->{src}} = 1;
+ };
+ } else {
+ $config = "\$(CONFIG_PACKAGE_$name)"
+ }
+ if ($config) {
+ print "package-$config += $pkg{$name}->{src}\n";
+ $pkg{$name}->{prereq} and print "prereq-$config += $pkg{$name}->{src}\n";
+ }
+
+ my $hasdeps = 0;
+ my $depline = "";
+ foreach my $dep (@{$pkg{$name}->{depends}}) {
+ my $idx;
+ if (defined $pkg{$dep}->{src}) {
+ ($pkg{$name}->{src} ne $pkg{$dep}->{src}) and $idx = $pkg{$dep}->{src};
+ } elsif (defined($pkg{$dep}) && !$options{SDK}) {
+ $idx = $dep;
+ }
+ undef $idx if $idx =~ /^(kernel)|(base-files)$/;
+ if ($idx) {
+ next if $dep{$pkg{$name}->{src}."->".$idx};
+ $depline .= " $idx\-compile";
+ $dep{$pkg{$name}->{src}."->".$idx} = 1;
+ }
+ }
+ if ($depline ne "") {
+ $line .= "$pkg{$name}->{src}-compile: $depline\n";
+ }
+}
+
+if ($line ne "") {
+ print "\n$line";
+}
diff --git a/scripts/gen_menuconfig.pl b/scripts/gen_menuconfig.pl
new file mode 100755
index 0000000000..fe01310928
--- /dev/null
+++ b/scripts/gen_menuconfig.pl
@@ -0,0 +1,133 @@
+#!/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 $src;
+my $makefile;
+my $pkg;
+my %category;
+my $cur_menu;
+my $cur_menu_dep;
+
+sub close_submenu {
+ if ($cur_menu) {
+ print "endmenu\n";
+ $cur_menu_dep and do {
+ print "endif\n";
+ $cur_menu_dep = undef;
+ };
+ undef $cur_menu;
+ }
+}
+
+sub print_category($) {
+ my $cat = shift;
+
+ return unless $category{$cat};
+
+ print "menu \"$cat\"\n\n";
+ my %spkg = %{$category{$cat}};
+ foreach my $spkg (sort {uc($a) cmp uc($b)} keys %spkg) {
+ foreach my $pkg (@{$spkg{$spkg}}) {
+ if ($cur_menu ne $pkg->{submenu}) {
+ close_submenu();
+ if ($pkg->{submenu}) {
+ $cur_menu = $pkg->{submenu};
+ $cur_menu_dep = $pkg->{submenudep} and print "if $cur_menu_dep\n";
+ print "menu \"$cur_menu\"\n";
+ }
+ }
+ my $title = $pkg->{name};
+ my $c = (72 - length($pkg->{name}) - length($pkg->{title}));
+ if ($c > 0) {
+ $title .= ("." x $c). " ". $pkg->{title};
+ }
+ print "\t";
+ $pkg->{menu} and print "menu";
+ print "config PACKAGE_".$pkg->{name}."\n";
+ print "\t\ttristate \"$title\"\n";
+ foreach my $default (split /\s*,\s*/, $pkg->{default}) {
+ print "\t\tdefault $default\n";
+ }
+ foreach my $depend (@{$pkg->{depends}}) {
+ my $m = "depends";
+ $depend =~ s/^([@\+]+)//;
+ my $flags = $1;
+ $flags =~ /@/ or $depend = "PACKAGE_$depend";
+ $flags =~ /\+/ and $m = "select";
+ print "\t\t$m $depend\n";
+ }
+ print "\t\thelp\n";
+ print $pkg->{description};
+ print "\n";
+
+ $pkg->{config} and print $pkg->{config}."\n";
+ }
+ }
+ close_submenu();
+ print "endmenu\n\n";
+
+ undef $category{$cat};
+}
+
+my $line;
+while ($line = <>) {
+ chomp $line;
+ $line =~ /^Source-Makefile: \s*(.+\/([^\/]+)\/Makefile)\s*$/ and do {
+ $makefile = $1;
+ $src = $2;
+ undef $pkg;
+ };
+ $line =~ /^Package: \s*(.+)\s*$/ and do {
+ $pkg = {};
+ $pkg->{src} = $src;
+ $pkg->{makefile} = $makefile;
+ $pkg->{name} = $1;
+ $pkg->{default} = "m if ALL";
+ };
+ $line =~ /^Version: \s*(.+)\s*$/ and $pkg->{version} = $1;
+ $line =~ /^Title: \s*(.+)\s*$/ and $pkg->{title} = $1;
+ $line =~ /^Menu: \s*(.+)\s*$/ and $pkg->{menu} = $1;
+ $line =~ /^Submenu: \s*(.+)\s*$/ and $pkg->{submenu} = $1;
+ $line =~ /^Submenu-Depends: \s*(.+)\s*$/ and $pkg->{submenudep} = $1;
+ $line =~ /^Default: \s*(.+)\s*$/ and $pkg->{default} = $1;
+ $line =~ /^Depends: \s*(.+)\s*$/ and do {
+ my @dep = split /\s+/, $1;
+ $pkg->{depends} = \@dep;
+ };
+ $line =~ /^Category: \s*(.+)\s*$/ and do {
+ $pkg->{category} = $1;
+ defined $category{$1} or $category{$1} = {};
+ defined $category{$1}->{$src} or $category{$1}->{$src} = [];
+ push @{$category{$1}->{$src}}, $pkg;
+ };
+ $line =~ /^Description: \s*(.*)\s*$/ and do {
+ my $desc = "\t\t$1\n\n";
+ my $line;
+ while ($line = <>) {
+ last if $line =~ /^@@/;
+ $desc .= "\t\t$line";
+ }
+ $pkg->{description} = $desc;
+ };
+ $line =~ /^Config: \s*(.*)\s*$/ and do {
+ my $conf = "$1\n";
+ my $line;
+ while ($line = <>) {
+ last if $line =~ /^@@/;
+ $conf .= "$line";
+ }
+ $pkg->{config} = $conf;
+ }
+}
+
+print_category 'Base system';
+foreach my $cat (keys %category) {
+ print_category $cat;
+}
diff --git a/scripts/ipkg b/scripts/ipkg
new file mode 100755
index 0000000000..97a3151425
--- /dev/null
+++ b/scripts/ipkg
@@ -0,0 +1,1187 @@
+#!/bin/sh
+# ipkg - the itsy package management system
+#
+# Copyright (C) 2001 Carl D. Worth
+#
+# 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.
+
+set -e
+
+# By default do not do globbing. Any command wanting globbing should
+# explicitly enable it first and disable it afterwards.
+set -o noglob
+
+ipkg_is_upgrade () {
+ local A B a b
+ A=$(echo $1 | sed -r "s/([0-9]+)[^[:alnum:]]*/ \1 /g").
+ B=$(echo $2 | sed -r "s/([0-9]+)[^[:alnum:]]*/ \1 /g").
+ while [ \! -z "$A" ] && [ \! -z "$B" ]; do {
+ set $A; a=$1; shift; A=$*
+ set $B; b=$1; shift; B=$*
+ [ "$a" -lt "$b" ] 2>&- && return 1
+ { [ "$a" -gt "$b" ] 2>&- || [ "$a" ">" "$b" ]; } && return
+ }; done
+ return 1
+}
+
+which md5sum 2>&1 >/dev/null || alias md5sum=md5
+
+ipkg_srcs() {
+ local srcre="$1"
+ sed -ne "s/^src[[:space:]]\+$srcre[[:space:]]\+//p" < $IPKG_CONF
+}
+
+ipkg_src_names() {
+ sed -ne "s/^src[[:space:]]\+\([^[:space:]]\+\).*/\1/p" < $IPKG_CONF
+}
+
+ipkg_src_byname() {
+ local src="$1"
+ ipkg_srcs $src | head -n 1
+}
+
+ipkg_dests() {
+ local destre="`echo $1 | ipkg_protect_slashes`"
+ sed -ne "/^dest[[:space:]]\+$destre/{
+s/^dest[[:space:]]\+[^[:space:]]\+[[:space:]]\+//
+s/^/`echo $IPKG_OFFLINE_ROOT | ipkg_protect_slashes`/
+p
+}" < $IPKG_CONF
+}
+
+ipkg_dest_names() {
+ sed -ne "s/^dest[[:space:]]\+\([^[:space:]]\+\).*/\1/p" < $IPKG_CONF
+}
+
+ipkg_dests_all() {
+ ipkg_dests '.*'
+}
+
+ipkg_state_dirs() {
+ ipkg_dests_all | sed "s|\$|/$IPKG_DIR_PREFIX|"
+}
+
+ipkg_dest_default() {
+ ipkg_dests_all | head -n 1
+}
+
+ipkg_dest_default_name() {
+ ipkg_dest_names | head -n 1
+}
+
+ipkg_dest_byname() {
+ local dest="$1"
+ ipkg_dests $dest | head -n 1
+}
+
+ipkg_option() {
+ local option="$1"
+ sed -ne "s/^option[[:space:]]\+$option[[:space:]]\+//p" < $IPKG_CONF
+}
+
+ipkg_load_configuration() {
+ if [ -z "$IPKG_CONF_DIR" ]; then
+ IPKG_CONF_DIR=/etc
+ fi
+
+ IPKG_CONF="$IPKG_CONF_DIR/ipkg.conf"
+
+ if [ -z "$IPKG_OFFLINE_ROOT" ]; then
+ IPKG_OFFLINE_ROOT="`ipkg_option offline_root`"
+ fi
+ # Export IPKG_OFFLINE_ROOT for use by update-alternatives
+ export IPKG_OFFLINE_ROOT
+ if [ -n "$DEST_NAME" ]; then
+ IPKG_ROOT="`ipkg_dest_byname $DEST_NAME`"
+ if [ -z "$IPKG_ROOT" ]; then
+ if [ -d "$IPKG_OFFLINE_ROOT$DEST_NAME" ]; then
+ IPKG_ROOT="$IPKG_OFFLINE_ROOT$DEST_NAME";
+ else
+ echo "ipkg: invalid destination specification: $DEST_NAME
+Valid destinations are directories or one of the dest names from $IPKG_CONF:" >&2
+ ipkg_dest_names >&2
+ return 1
+ fi
+ fi
+ else
+ IPKG_ROOT="`ipkg_dest_default`"
+ fi
+
+ # Global ipkg state directories
+ IPKG_DIR_PREFIX=usr/lib/ipkg
+ IPKG_LISTS_DIR=$IPKG_OFFLINE_ROOT/$IPKG_DIR_PREFIX/lists
+ IPKG_PENDING_DIR=$IPKG_OFFLINE_ROOT/$IPKG_DIR_PREFIX/pending
+ if [ -z "$IPKG_TMP" ]; then
+ IPKG_TMP=$IPKG_ROOT/tmp/ipkg
+ fi
+
+ [ -e "$IPKG_TMP" ] || mkdir -p $IPKG_TMP
+
+ # Destination specific ipkg meta-data directory
+ IPKG_STATE_DIR=$IPKG_ROOT/$IPKG_DIR_PREFIX
+
+ # Proxy Support
+ IPKG_PROXY_USERNAME="`ipkg_option proxy_username`"
+ IPKG_PROXY_PASSWORD="`ipkg_option proxy_password`"
+ IPKG_HTTP_PROXY="`ipkg_option http_proxy`"
+ IPKG_FTP_PROXY="`ipkg_option ftp_proxy`"
+ IPKG_NO_PROXY="`ipkg_option no_proxy`"
+ if [ -n "$IPKG_HTTP_PROXY" ]; then
+ export http_proxy="$IPKG_HTTP_PROXY"
+ fi
+
+ if [ -n "$IPKG_FTP_PROXY" ]; then
+ export ftp_proxy="$IPKG_FTP_PROXY"
+ fi
+
+ if [ -n "$IPKG_NO_PROXY" ]; then
+ export no_proxy="$IPKG_NO_PROXY"
+ fi
+
+ IPKG_STATUS_FIELDS='\(Package\|Status\|Essential\|Version\|Conffiles\|Root\)'
+}
+
+ipkg_usage() {
+ [ $# -gt 0 ] && echo "ipkg: $*"
+ echo "
+usage: ipkg [options...] sub-command [arguments...]
+where sub-command is one of:
+
+Package Manipulation:
+ update Update list of available packages
+ upgrade Upgrade all installed packages to latest version
+ install <pkg> Download and install <pkg> (and dependencies)
+ install <file.ipk> Install package <file.ipk>
+ install <file.deb> Install package <file.deb>
+ remove <pkg> Remove package <pkg>
+
+Informational Commands:
+ list List available packages and descriptions
+ files <pkg> List all files belonging to <pkg>
+ search <file> Search for a packaging providing <file>
+ info [pkg [<field>]] Display all/some info fields for <pkg> or all
+ status [pkg [<field>]] Display all/some status fields for <pkg> or all
+ depends <pkg> Print uninstalled package dependencies for <pkg>
+
+Options:
+ -d <dest_name> Use <dest_name> as the the root directory for
+ -dest <dest_name> package installation, removal, upgrading.
+ <dest_name> should be a defined dest name from the
+ configuration file, (but can also be a directory
+ name in a pinch).
+ -o <offline_root> Use <offline_root> as the root for offline installation.
+ -offline <offline_root>
+
+Force Options (use when ipkg is too smart for its own good):
+ -force-depends Make dependency checks warnings instead of errors
+ -force-defaults Use default options for questions asked by ipkg.
+ (no prompts). Note that this will not prevent
+ package installation scripts from prompting.
+" >&2
+ exit 1
+}
+
+ipkg_dir_part() {
+ local dir="`echo $1 | sed -ne 's/\(.*\/\).*/\1/p'`"
+ if [ -z "$dir" ]; then
+ dir="./"
+ fi
+ echo $dir
+}
+
+ipkg_file_part() {
+ echo $1 | sed 's/.*\///'
+}
+
+ipkg_protect_slashes() {
+ sed -e 's/\//\\\//g'
+}
+
+ipkg_download() {
+ local src="$1"
+ local dest="$2"
+
+ local src_file="`ipkg_file_part $src`"
+ local dest_dir="`ipkg_dir_part $dest`"
+ if [ -z "$dest_dir" ]; then
+ dest_dir="$IPKG_TMP"
+ fi
+
+ local dest_file="`ipkg_file_part $dest`"
+ if [ -z "$dest_file" ]; then
+ dest_file="$src_file"
+ fi
+
+ # Proxy support
+ local proxyuser=""
+ local proxypassword=""
+ local proxyoption=""
+
+ if [ -n "$IPKG_PROXY_USERNAME" ]; then
+ proxyuser="--proxy-user=\"$IPKG_PROXY_USERNAME\""
+ proxypassword="--proxy-passwd=\"$IPKG_PROXY_PASSWORD\""
+ fi
+
+ if [ -n "$IPKG_PROXY_HTTP" -o -n "$IPKG_PROXY_FTP" ]; then
+ proxyoption="--proxy=on"
+ fi
+
+ echo "Downloading $src ..."
+ rm -f $IPKG_TMP/$src_file
+ case "$src" in
+ http://* | ftp://*)
+ if ! wget --passive-ftp $proxyoption $proxyuser $proxypassword -P $IPKG_TMP $src; then
+ echo "ipkg_download: ERROR: Failed to retrieve $src, returning $err"
+ return 1
+ fi
+ mv $IPKG_TMP/$src_file $dest_dir/$dest_file 2>/dev/null
+ ;;
+ file:/* )
+ ln -s `echo $src | sed 's/^file://'` $dest_dir/$dest_file 2>/dev/null
+ ;;
+ *)
+ echo "DEBUG: $src"
+ ;;
+ esac
+
+ echo "Done."
+ return 0
+}
+
+ipkg_update() {
+ if [ ! -e "$IPKG_LISTS_DIR" ]; then
+ mkdir -p $IPKG_LISTS_DIR
+ fi
+
+ local err=
+ for src_name in `ipkg_src_names`; do
+ local src="`ipkg_src_byname $src_name`"
+ if ! ipkg_download $src/Packages $IPKG_LISTS_DIR/$src_name; then
+ echo "ipkg_update: Error downloading $src/Packages to $IPKG_LISTS_DIR/$src_name" >&2
+ err=t
+ else
+ echo "Updated list of available packages in $IPKG_LISTS_DIR/$src_name"
+ fi
+ done
+
+ [ -n "$err" ] && return 1
+
+ return 0
+}
+
+ipkg_list() {
+ for src in `ipkg_src_names`; do
+ if ipkg_require_list $src; then
+# black magic...
+sed -ne "
+/^Package:/{
+s/^Package:[[:space:]]*\<\([a-z0-9.+-]*$1[a-z0-9.+-]*\).*/\1/
+h
+}
+/^Description:/{
+s/^Description:[[:space:]]*\(.*\)/\1/
+H
+g
+s/\\
+/ - /
+p
+}
+" $IPKG_LISTS_DIR/$src
+ fi
+ done
+}
+
+ipkg_extract_paragraph() {
+ local pkg="$1"
+ sed -ne "/Package:[[:space:]]*$pkg[[:space:]]*\$/,/^\$/p"
+}
+
+ipkg_extract_field() {
+ local field="$1"
+# blacker magic...
+ sed -ne "
+: TOP
+/^$field:/{
+p
+n
+b FIELD
+}
+d
+: FIELD
+/^$/b TOP
+/^[^[:space:]]/b TOP
+p
+n
+b FIELD
+"
+}
+
+ipkg_extract_value() {
+ sed -e "s/^[^:]*:[[:space:]]*//"
+}
+
+ipkg_require_list() {
+ [ $# -lt 1 ] && return 1
+ local src="$1"
+ if [ ! -f "$IPKG_LISTS_DIR/$src" ]; then
+ echo "ERROR: File not found: $IPKG_LISTS_DIR/$src" >&2
+ echo " You probably want to run \`ipkg update'" >&2
+ return 1
+ fi
+ return 0
+}
+
+ipkg_info() {
+ for src in `ipkg_src_names`; do
+ if ipkg_require_list $src; then
+ case $# in
+ 0)
+ cat $IPKG_LISTS_DIR/$src
+ ;;
+ 1)
+ ipkg_extract_paragraph $1 < $IPKG_LISTS_DIR/$src
+ ;;
+ *)
+ ipkg_extract_paragraph $1 < $IPKG_LISTS_DIR/$src | ipkg_extract_field $2
+ ;;
+ esac
+ fi
+ done
+}
+
+ipkg_status_sd() {
+ [ $# -lt 1 ] && return 0
+ sd="$1"
+ shift
+ if [ -f $sd/status ]; then
+ case $# in
+ 0)
+ cat $sd/status
+ ;;
+ 1)
+ ipkg_extract_paragraph $1 < $sd/status
+ ;;
+ *)
+ ipkg_extract_paragraph $1 < $sd/status | ipkg_extract_field $2
+ ;;
+ esac
+ fi
+ return 0
+}
+
+ipkg_status_all() {
+ for sd in `ipkg_state_dirs`; do
+ ipkg_status_sd $sd $*
+ done
+}
+
+ipkg_status() {
+ if [ -n "$DEST_NAME" ]; then
+ ipkg_status_sd $IPKG_STATE_DIR $*
+ else
+ ipkg_status_all $*
+ fi
+}
+
+ipkg_status_matching_sd() {
+ local sd="$1"
+ local re="$2"
+ if [ -f $sd/status ]; then
+ sed -ne "
+: TOP
+/^Package:/{
+s/^Package:[[:space:]]*//
+s/[[:space:]]*$//
+h
+}
+/$re/{
+g
+p
+b NEXT
+}
+d
+: NEXT
+/^$/b TOP
+n
+b NEXT
+" < $sd/status
+ fi
+ return 0
+}
+
+ipkg_status_matching_all() {
+ for sd in `ipkg_state_dirs`; do
+ ipkg_status_matching_sd $sd $*
+ done
+}
+
+ipkg_status_matching() {
+ if [ -n "$DEST_NAME" ]; then
+ ipkg_status_matching_sd $IPKG_STATE_DIR $*
+ else
+ ipkg_status_matching_all $*
+ fi
+}
+
+ipkg_status_installed_sd() {
+ local sd="$1"
+ local pkg="$2"
+ ipkg_status_sd $sd $pkg Status | grep -q "Status: install ok installed"
+}
+
+ipkg_status_installed_all() {
+ local ret=1
+ for sd in `ipkg_state_dirs`; do
+ if `ipkg_status_installed_sd $sd $*`; then
+ ret=0
+ fi
+ done
+ return $ret
+}
+
+ipkg_status_mentioned_sd() {
+ local sd="$1"
+ local pkg="$2"
+ [ -n "`ipkg_status_sd $sd $pkg Status`" ]
+}
+
+ipkg_files() {
+ local pkg="$1"
+ if [ -n "$DEST_NAME" ]; then
+ dests=$IPKG_ROOT
+ else
+ dests="`ipkg_dests_all`"
+ fi
+ for dest in $dests; do
+ if [ -f $dest/$IPKG_DIR_PREFIX/info/$pkg.list ]; then
+ dest_sed="`echo $dest | ipkg_protect_slashes`"
+ sed -e "s/^/$dest_sed/" < $dest/$IPKG_DIR_PREFIX/info/$pkg.list
+ fi
+ done
+}
+
+ipkg_search() {
+ local pattern="$1"
+
+ for dest_name in `ipkg_dest_names`; do
+ dest="`ipkg_dest_byname $dest_name`"
+ dest_sed="`echo $dest | ipkg_protect_slashes`"
+
+ set +o noglob
+ local list_files="`ls -1 $dest/$IPKG_DIR_PREFIX/info/*.list 2>/dev/null`"
+ set -o noglob
+ for file in $list_files; do
+ if sed "s/^/$dest_sed/" $file | grep -q $pattern; then
+ local pkg="`echo $file | sed "s/^.*\/\(.*\)\.list/\1/"`"
+ [ "$dest_name" != `ipkg_dest_default_name` ] && pkg="$pkg ($dest_name)"
+ sed "s/^/$dest_sed/" $file | grep $pattern | sed "s/^/$pkg: /"
+ fi
+ done
+ done
+}
+
+ipkg_status_remove_sd() {
+ local sd="$1"
+ local pkg="$2"
+
+ if [ ! -f $sd/status ]; then
+ mkdir -p $sd
+ touch $sd/status
+ fi
+ sed -ne "/Package:[[:space:]]*$pkg[[:space:]]*\$/,/^\$/!p" < $sd/status > $sd/status.new
+ mv $sd/status.new $sd/status
+}
+
+ipkg_status_remove_all() {
+ for sd in `ipkg_state_dirs`; do
+ ipkg_status_remove_sd $sd $*
+ done
+}
+
+ipkg_status_remove() {
+ if [ -n "$DEST_NAME" ]; then
+ ipkg_status_remove_sd $IPKG_STATE_DIR $*
+ else
+ ipkg_status_remove_all $*
+ fi
+}
+
+ipkg_status_update_sd() {
+ local sd="$1"
+ local pkg="$2"
+
+ ipkg_status_remove_sd $sd $pkg
+ ipkg_extract_field "$IPKG_STATUS_FIELDS" >> $sd/status
+ echo "" >> $sd/status
+}
+
+ipkg_status_update() {
+ ipkg_status_update_sd $IPKG_STATE_DIR $*
+}
+
+ipkg_unsatisfied_dependences() {
+ local pkg=$1
+ local deps="`ipkg_get_depends $pkg`"
+ local remaining_deps=
+ for dep in $deps; do
+ local installed="`ipkg_get_installed $dep`"
+ if [ "$installed" != "installed" ] ; then
+ remaining_deps="$remaining_deps $dep"
+ fi
+ done
+ ## echo "ipkg_unsatisfied_dependences pkg=$pkg $remaining_deps" > /dev/console
+ echo $remaining_deps
+}
+
+ipkg_safe_pkg_name() {
+ local pkg=$1
+ local spkg="`echo pkg_$pkg | sed -e y/-+./___/`"
+ echo $spkg
+}
+
+ipkg_set_depends() {
+ local pkg=$1; shift
+ local new_deps="$*"
+ pkg="`ipkg_safe_pkg_name $pkg`"
+ ## setvar ${pkg}_depends "$new_deps"
+ echo $new_deps > $IPKG_TMP/${pkg}.depends
+}
+
+ipkg_get_depends() {
+ local pkg=$1
+ pkg="`ipkg_safe_pkg_name $pkg`"
+ cat $IPKG_TMP/${pkg}.depends
+ ## eval "echo \$${pkg}_depends"
+}
+
+ipkg_set_installed() {
+ local pkg=$1
+ pkg="`ipkg_safe_pkg_name $pkg`"
+ echo installed > $IPKG_TMP/${pkg}.installed
+ ## setvar ${pkg}_installed "installed"
+}
+
+ipkg_set_uninstalled() {
+ local pkg=$1
+ pkg="`ipkg_safe_pkg_name $pkg`"
+ ### echo ipkg_set_uninstalled $pkg > /dev/console
+ echo uninstalled > $IPKG_TMP/${pkg}.installed
+ ## setvar ${pkg}_installed "uninstalled"
+}
+
+ipkg_get_installed() {
+ local pkg=$1
+ pkg="`ipkg_safe_pkg_name $pkg`"
+ if [ -f $IPKG_TMP/${pkg}.installed ]; then
+ cat $IPKG_TMP/${pkg}.installed
+ fi
+ ## eval "echo \$${pkg}_installed"
+}
+
+ipkg_depends() {
+ local new_pkgs="$*"
+ local all_deps=
+ local installed_pkgs="`ipkg_status_matching_all 'Status:.*[[:space:]]installed'`"
+ for pkg in $installed_pkgs; do
+ ipkg_set_installed $pkg
+ done
+ while [ -n "$new_pkgs" ]; do
+ all_deps="$all_deps $new_pkgs"
+ local new_deps=
+ for pkg in $new_pkgs; do
+ if echo $pkg | grep -q '[^a-z0-9.+-]'; then
+ echo "ipkg_depends: ERROR: Package name $pkg contains illegal characters (should be [a-z0-9.+-])" >&2
+ return 1
+ fi
+ # TODO: Fix this. For now I am ignoring versions and alternations in dependencies.
+ new_deps="$new_deps "`ipkg_info $pkg '\(Pre-\)\?Depends' | ipkg_extract_value | sed -e 's/([^)]*)//g
+s/\(|[[:space:]]*[a-z0-9.+-]\+[[:space:]]*\)\+//g
+s/,/ /g
+s/ \+/ /g'`
+ ipkg_set_depends $pkg $new_deps
+ done
+
+ new_deps=`echo $new_deps | sed -e 's/[[:space:]]\+/\n/g' | sort | uniq`
+
+ local maybe_new_pkgs=
+ for pkg in $new_deps; do
+ if ! echo $installed_pkgs | grep -q "\<$pkg\>"; then
+ maybe_new_pkgs="$maybe_new_pkgs $pkg"
+ fi
+ done
+
+ new_pkgs=
+ for pkg in $maybe_new_pkgs; do
+ if ! echo $all_deps | grep -q "\<$pkg\>"; then
+ if [ -z "`ipkg_info $pkg`" ]; then
+ echo "ipkg_depends: Warning: $pkg mentioned in dependency but no package found in $IPKG_LISTS_DIR" >&2
+ ipkg_set_installed $pkg
+ else
+ new_pkgs="$new_pkgs $pkg"
+ ipkg_set_uninstalled $pkg
+ fi
+ else
+ ipkg_set_uninstalled $pkg
+ fi
+ done
+ done
+
+ echo $all_deps
+}
+
+ipkg_get_install_dest() {
+ local dest="$1"
+ shift
+ local sd=$dest/$IPKG_DIR_PREFIX
+ local info_dir=$sd/info
+
+ local requested_pkgs="$*"
+ local pkgs="`ipkg_depends $*`"
+
+ mkdir -p $info_dir
+ for pkg in $pkgs; do
+ if ! ipkg_status_mentioned_sd $sd $pkg; then
+ echo "Package: $pkg
+Status: install ok not-installed" | ipkg_status_update_sd $sd $pkg
+ fi
+ done
+ ## mark the packages that we were directly requested to install as uninstalled
+ for pkg in $requested_pkgs; do ipkg_set_uninstalled $pkg; done
+
+ local new_pkgs=
+ local pkgs_installed=0
+ while [ -n "pkgs" ]; do
+ curcheck=0
+ ## echo "pkgs to install: {$pkgs}" > /dev/console
+ for pkg in $pkgs; do
+ curcheck="`expr $curcheck + 1`"
+ local is_installed="`ipkg_get_installed $pkg`"
+ if [ "$is_installed" = "installed" ]; then
+ echo "$pkg is installed" > /dev/console
+ continue
+ fi
+
+ local remaining_deps="`ipkg_unsatisfied_dependences $pkg`"
+ if [ -n "$remaining_deps" ]; then
+ new_pkgs="$new_pkgs $pkg"
+ ### echo "Dependences not satisfied for $pkg: $remaining_deps"
+ if [ $curcheck -ne `echo $pkgs|wc -w` ]; then
+ continue
+ fi
+ fi
+
+ local filename=
+ for src in `ipkg_src_names`; do
+ if ipkg_require_list $src; then
+ filename="`ipkg_extract_paragraph $pkg < $IPKG_LISTS_DIR/$src | ipkg_extract_field Filename | ipkg_extract_value`"
+ [ -n "$filename" ] && break
+ fi
+ done
+
+ if [ -z "$filename" ]; then
+ echo "ipkg_get_install: ERROR: Cannot find package $pkg in $IPKG_LISTS_DIR"
+ echo "ipkg_get_install: Check the spelling and maybe run \`ipkg update'."
+ ipkg_status_remove_sd $sd $pkg
+ return 1;
+ fi
+
+ echo ""
+ local tmp_pkg_file="$IPKG_TMP/"`ipkg_file_part $filename`
+ if ! ipkg_download `ipkg_src_byname $src`/$filename $tmp_pkg_file; then
+ echo "ipkg_get_install: Perhaps you need to run \`ipkg update'?"
+ return 1
+ fi
+
+ if ! ipkg_install_file_dest $dest $tmp_pkg_file; then
+ echo "ipkg_get_install: ERROR: Failed to install $tmp_pkg_file"
+ echo "ipkg_get_install: I'll leave it there for you to try a manual installation"
+ return 1
+ fi
+
+ ipkg_set_installed $pkg
+ pkgs_installed="`expr $pkgs_installed + 1`"
+ rm $tmp_pkg_file
+ done
+ ### echo "Installed $pkgs_installed package(s) this round"
+ if [ $pkgs_installed -eq 0 ]; then
+ if [ -z "$new_pkgs" ]; then
+ break
+ fi
+ fi
+ pkgs_installed=0
+ pkgs="$new_pkgs"
+ new_pkgs=
+ curcheck=0
+ done
+}
+
+ipkg_get_install() {
+ ipkg_get_install_dest $IPKG_ROOT $*
+}
+
+ipkg_install_file_dest() {
+ local dest="$1"
+ local filename="$2"
+ local sd=$dest/$IPKG_DIR_PREFIX
+ local info_dir=$sd/info
+
+ if [ ! -f "$filename" ]; then
+ echo "ipkg_install_file: ERROR: File $filename not found"
+ return 1
+ fi
+
+ local pkg="`ipkg_file_part $filename | sed 's/\([a-z0-9.+-]\+\)_.*/\1/'`"
+ local ext="`echo $filename | sed 's/.*\.//'`"
+ local pkg_extract_stdout
+ if [ "$ext" = "ipk" ]; then
+ pkg_extract_stdout="tar -xzOf"
+ elif [ "$ext" = "deb" ]; then
+ pkg_extract_stdout="ar p"
+ else
+ echo "ipkg_install_file: ERROR: File $filename has unknown extension $ext (not .ipk or .deb)"
+ return 1
+ fi
+
+ # Check dependencies
+ local depends="`ipkg_depends $pkg | sed -e "s/\<$pkg\>//"`"
+
+ # Don't worry about deps that are scheduled for installation
+ local missing_deps=
+ for dep in $depends; do
+ if ! ipkg_status_all $dep | grep -q 'Status:[[:space:]]install'; then
+ missing_deps="$missing_deps $dep"
+ fi
+ done
+
+ if [ ! -z "$missing_deps" ]; then
+ if [ -n "$FORCE_DEPENDS" ]; then
+ echo "ipkg_install_file: Warning: $pkg depends on the following uninstalled programs: $missing_deps"
+ else
+ echo "ipkg_install_file: ERROR: $pkg depends on the following uninstalled programs:
+ $missing_deps"
+ echo "ipkg_install_file: You may want to use \`ipkg install' to install these."
+ return 1
+ fi
+ fi
+
+ mkdir -p $IPKG_TMP/$pkg/control
+ mkdir -p $IPKG_TMP/$pkg/data
+ mkdir -p $info_dir
+
+ if ! $pkg_extract_stdout $filename ./control.tar.gz | (cd $IPKG_TMP/$pkg/control; tar -xzf - ) ; then
+ echo "ipkg_install_file: ERROR unpacking control.tar.gz from $filename"
+ return 1
+ fi
+
+ if [ -n "$IPKG_OFFLINE_ROOT" ]; then
+ if grep -q '^InstallsOffline:[[:space:]]*no' $IPKG_TMP/$pkg/control/control; then
+ echo "*** Warning: Package $pkg may not be installed in offline mode"
+ echo "*** Warning: Scheduling $filename for pending installation (installing into $IPKG_PENDING_DIR)"
+ echo "Package: $pkg
+Status: install ok pending" | ipkg_status_update_sd $sd $pkg
+ mkdir -p $IPKG_PENDING_DIR
+ cp -f $filename $IPKG_PENDING_DIR
+ rm -r $IPKG_TMP/$pkg/control
+ rm -r $IPKG_TMP/$pkg/data
+ rmdir $IPKG_TMP/$pkg
+ return 0
+ fi
+ fi
+
+
+ echo -n "Unpacking $pkg..."
+ set +o noglob
+ for file in $IPKG_TMP/$pkg/control/*; do
+ local base_file="`ipkg_file_part $file`"
+ mv $file $info_dir/$pkg.$base_file
+ done
+ set -o noglob
+ rm -r $IPKG_TMP/$pkg/control
+
+ if ! $pkg_extract_stdout $filename ./data.tar.gz | (cd $IPKG_TMP/$pkg/data; tar -xzf - ) ; then
+ echo "ipkg_install_file: ERROR unpacking data.tar.gz from $filename"
+ return 1
+ fi
+ echo "Done."
+
+ echo -n "Configuring $pkg..."
+ export PKG_ROOT=$dest
+ if [ -x "$info_dir/$pkg.preinst" ]; then
+ if ! $info_dir/$pkg.preinst install; then
+ echo "$info_dir/$pkg.preinst failed. Aborting installation of $pkg"
+ rm -rf $IPKG_TMP/$pkg/data
+ rmdir $IPKG_TMP/$pkg
+ return 1
+ fi
+ fi
+
+ local old_conffiles="`ipkg_status_sd $sd $pkg Conffiles | ipkg_extract_value`"
+ local new_conffiles=
+ if [ -f "$info_dir/$pkg.conffiles" ]; then
+ for conffile in `cat $info_dir/$pkg.conffiles`; do
+ if [ -f "$dest/$conffile" ] && ! echo " $old_conffiles " | grep -q " $conffile "`md5sum $dest/$conffile | sed 's/ .*//'`; then
+ local use_maintainers_conffile=
+ if [ -z "$FORCE_DEFAULTS" ]; then
+ while true; do
+ echo -n "Configuration file \`$conffile'
+ ==> File on system created by you or by a script.
+ ==> File also in package provided by package maintainer.
+ What would you like to do about it ? Your options are:
+ Y or I : install the package maintainer's version
+ N or O : keep your currently-installed version
+ D : show the differences between the versions (if diff is installed)
+ The default action is to keep your current version.
+*** `ipkg_file_part $conffile` (Y/I/N/O/D) [default=N] ? "
+ read response
+ case "$response" in
+ [YyIi] | [Yy][Ee][Ss])
+ use_maintainers_conffile=t
+ break
+ ;;
+ [Dd])
+ echo "
+diff -u $dest/$conffile $IPKG_TMP/$pkg/data/$conffile"
+ diff -u $dest/$conffile $IPKG_TMP/$pkg/data/$conffile || true
+ echo "[Press ENTER to continue]"
+ read junk
+ ;;
+ *)
+ break
+ ;;
+ esac
+ done
+ fi
+ if [ -n "$use_maintainers_conffile" ]; then
+ local md5sum="`md5sum $IPKG_TMP/$pkg/data/$conffile | sed 's/ .*//'`"
+ new_conffiles="$new_conffiles $conffile $md5sum"
+ else
+ new_conffiles="$new_conffiles $conffile <custom>"
+ rm $IPKG_TMP/$pkg/data/$conffile
+ fi
+ else
+ md5sum="`md5sum $IPKG_TMP/$pkg/data/$conffile | sed 's/ .*//'`"
+ new_conffiles="$new_conffiles $conffile $md5sum"
+ fi
+ done
+ fi
+
+ local owd="`pwd`"
+ (cd $IPKG_TMP/$pkg/data/; tar cf - . | (cd $owd; cd $dest; tar xf -))
+ rm -rf $IPKG_TMP/$pkg/data
+ rmdir $IPKG_TMP/$pkg
+ rm -f $info_dir/$pkg.list
+ $pkg_extract_stdout $filename ./data.tar.gz | tar tzf - | sed -e 's/^\.//' > $info_dir/$pkg.list
+
+ if [ -x "$info_dir/$pkg.postinst" ]; then
+ $info_dir/$pkg.postinst configure
+ fi
+
+ if [ -n "$new_conffiles" ]; then
+ new_conffiles='Conffiles: '`echo $new_conffiles | ipkg_protect_slashes`
+ fi
+ local sed_safe_offline_root="`echo ${IPKG_OFFLINE_ROOT} | ipkg_protect_slashes`"
+ local sed_safe_root="`echo $dest | sed -e "s/^${sed_safe_offline_root}//" | ipkg_protect_slashes`"
+ sed -e "s/\(Package:.*\)/\1\\
+Status: install ok installed\\
+Root: ${sed_safe_root}\\
+${new_conffiles}/" $info_dir/$pkg.control | ipkg_status_update_sd $sd $pkg
+
+ rm -f $info_dir/$pkg.control
+ rm -f $info_dir/$pkg.conffiles
+ rm -f $info_dir/$pkg.preinst
+ rm -f $info_dir/$pkg.postinst
+
+ echo "Done."
+}
+
+ipkg_install_file() {
+ ipkg_install_file_dest $IPKG_ROOT $*
+}
+
+ipkg_install() {
+
+ while [ $# -gt 0 ]; do
+ local pkg="$1"
+ shift
+
+ case "$pkg" in
+ http://* | ftp://*)
+ local tmp_pkg_file="$IPKG_TMP/"`ipkg_file_part $pkg`
+ if ipkg_download $pkg $tmp_pkg_file; then
+ ipkg_install_file $tmp_pkg_file
+ rm $tmp_pkg_file
+ fi
+ ;;
+ file:/*.ipk | file://*.deb)
+ local ipkg_filename="`echo $pkg|sed 's/^file://'`"
+ ipkg_install_file $ipkg_filename
+ ;;
+ *.ipk | *.deb)
+ ipkg_install_file $pkg
+ ;;
+ *)
+ ipkg_get_install $pkg || true
+ ;;
+ esac
+ done
+}
+
+ipkg_install_pending() {
+ [ -n "$IPKG_OFFLINE_ROOT" ] && return 0
+
+ if [ -d "$IPKG_PENDING_DIR" ]; then
+ set +o noglob
+ local pending="`ls -1d $IPKG_PENDING_DIR/*.ipk 2> /dev/null`" || true
+ set -o noglob
+ if [ -n "$pending" ]; then
+ echo "The following packages in $IPKG_PENDING_DIR will now be installed:"
+ echo $pending
+ for filename in $pending; do
+ if ipkg_install_file $filename; then
+ rm $filename
+ fi
+ done
+ fi
+ fi
+ return 0
+}
+
+ipkg_install_wanted() {
+ local wanted="`ipkg_status_matching 'Status:[[:space:]]*install.*not-installed'`"
+
+ if [ -n "$wanted" ]; then
+ echo "The following package were previously requested but have not been installed:"
+ echo $wanted
+
+ if [ -n "$FORCE_DEFAULTS" ]; then
+ echo "Installing them now."
+ else
+ echo -n "Install them now [Y/n] ? "
+ read response
+ case "$response" in
+ [Nn] | [Nn][Oo])
+ return 0
+ ;;
+ esac
+ fi
+
+ ipkg_install $wanted
+ fi
+
+ return 0
+}
+
+ipkg_upgrade_pkg() {
+ local pkg="$1"
+ local avail_ver="`ipkg_info $pkg Version | ipkg_extract_value | head -n 1`"
+
+ is_installed=
+ for dest_name in `ipkg_dest_names`; do
+ local dest="`ipkg_dest_byname $dest_name`"
+ local sd=$dest/$IPKG_DIR_PREFIX
+ local inst_ver="`ipkg_status_sd $sd $pkg Version | ipkg_extract_value`"
+ if [ -n "$inst_ver" ]; then
+ is_installed=t
+
+ if [ -z "$avail_ver" ]; then
+ echo "Assuming locally installed package $pkg ($inst_ver) is up to date"
+ return 0
+ fi
+
+ if [ "$avail_ver" = "$inst_ver" ]; then
+ echo "Package $pkg ($inst_ver) installed in $dest_name is up to date"
+ elif ipkg_is_upgrade "$avail_ver" "$inst_ver"; then
+ echo "Upgrading $pkg ($dest_name) from $inst_ver to $avail_ver"
+ ipkg_get_install_dest $dest $pkg
+ else
+ echo "Not downgrading package $pkg from $inst_ver to $avail_ver"
+ fi
+ fi
+ done
+
+ if [ -z "$is_installed" ]; then
+ echo "Package $pkg does not appear to be installed"
+ return 0
+ fi
+
+}
+
+ipkg_upgrade() {
+ if [ $# -lt 1 ]; then
+ local pkgs="`ipkg_status_matching 'Status:.*[[:space:]]installed'`"
+ else
+ pkgs="$*"
+ fi
+
+ for pkg in $pkgs; do
+ ipkg_upgrade_pkg $pkg
+ done
+}
+
+ipkg_remove_pkg_dest() {
+ local dest="$1"
+ local pkg="$2"
+ local sd=$dest/$IPKG_DIR_PREFIX
+ local info_dir=$sd/info
+
+ if ! ipkg_status_installed_sd $sd $pkg; then
+ echo "ipkg_remove: Package $pkg does not appear to be installed in $dest"
+ if ipkg_status_mentioned_sd $sd $pkg; then
+ echo "Purging mention of $pkg from the ipkg database"
+ ipkg_status_remove_sd $sd $pkg
+ fi
+ return 1
+ fi
+
+ echo "ipkg_remove: Removing $pkg... "
+
+ local files="`cat $info_dir/$pkg.list`"
+
+ export PKG_ROOT=$dest
+ if [ -x "$info_dir/$pkg.prerm" ]; then
+ $info_dir/$pkg.prerm remove
+ fi
+
+ local conffiles="`ipkg_status_sd $sd $pkg Conffiles | ipkg_extract_value`"
+
+ local dirs_to_remove=
+ for file in $files; do
+ if [ -d "$dest/$file" ]; then
+ dirs_to_remove="$dirs_to_remove $dest/$file"
+ else
+ if echo " $conffiles " | grep -q " $file "; then
+ if echo " $conffiles " | grep -q " $file "`md5sum $dest/$file | sed 's/ .*//'`; then
+ rm -f $dest/$file
+ fi
+ else
+ rm -f $dest/$file
+ fi
+ fi
+ done
+
+ local removed_a_dir=t
+ while [ -n "$removed_a_dir" ]; do
+ removed_a_dir=
+ local new_dirs_to_remove=
+ for dir in $dirs_to_remove; do
+ if rmdir $dir >/dev/null 2>&1; then
+ removed_a_dir=t
+ else
+ new_dirs_to_remove="$new_dirs_to_remove $dir"
+ fi
+ done
+ dirs_to_remove="$new_dirs_to_remove"
+ done
+
+ if [ -n "$dirs_to_remove" ]; then
+ echo "ipkg_remove: Warning: Not removing the following directories since they are not empty:" >&2
+ echo "$dirs_to_remove" | sed -e 's/\/[/]\+/\//g' >&2
+ fi
+
+ if [ -x "$info_dir/$pkg.postrm" ]; then
+ $info_dir/$pkg.postrm remove
+ fi
+
+ ipkg_status_remove_sd $sd $pkg
+ set +o noglob
+ rm -f $info_dir/$pkg.*
+ set -o noglob
+
+ echo "Done."
+}
+
+ipkg_remove_pkg() {
+ local pkg="$1"
+ for dest in `ipkg_dests_all`; do
+ local sd=$dest/$IPKG_DIR_PREFIX
+ if ipkg_status_mentioned_sd $sd $pkg; then
+ ipkg_remove_pkg_dest $dest $pkg
+ fi
+ done
+}
+
+ipkg_remove() {
+ while [ $# -gt 0 ]; do
+ local pkg="$1"
+ shift
+ if [ -n "$DEST_NAME" ]; then
+ ipkg_remove_pkg_dest $IPKG_ROOT $pkg
+ else
+ ipkg_remove_pkg $pkg
+ fi
+ done
+}
+
+###########
+# ipkg main
+###########
+
+# Parse options
+while [ $# -gt 0 ]; do
+ arg="$1"
+ case $arg in
+ -d | -dest)
+ [ $# -gt 1 ] || ipkg_usage "option $arg requires an argument"
+ DEST_NAME="$2"
+ shift
+ ;;
+ -o | -offline)
+ [ $# -gt 1 ] || ipkg_usage "option $arg requires an argument"
+ IPKG_OFFLINE_ROOT="$2"
+ shift
+ ;;
+ -force-depends)
+ FORCE_DEPENDS=t
+ ;;
+ -force-defaults)
+ FORCE_DEFAULTS=t
+ ;;
+ -*)
+ ipkg_usage "unknown option $arg"
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+done
+
+[ $# -lt 1 ] && ipkg_usage "ipkg must have one sub-command argument"
+cmd="$1"
+shift
+
+ipkg_load_configuration
+mkdir -p /tmp/ipkg
+
+case "$cmd" in
+update|upgrade|list|info|status|install_pending)
+ ;;
+install|depends|remove|files|search)
+ [ $# -lt 1 ] && ipkg_usage "ERROR: the \`\`$cmd'' command requires an argument"
+ ;;
+*)
+ echo "ERROR: unknown sub-command \`$cmd'"
+ ipkg_usage
+ ;;
+esac
+
+# Only install pending if we have an interactive sub-command
+case "$cmd" in
+upgrade|install)
+ ipkg_install_pending
+ ipkg_install_wanted
+ ;;
+esac
+
+ipkg_$cmd $*
+for a in `ls $IPKG_TMP`; do
+ rm -rf $IPKG_TMP/$a
+done
diff --git a/scripts/ipkg-make-index.sh b/scripts/ipkg-make-index.sh
new file mode 100755
index 0000000000..46051045ae
--- /dev/null
+++ b/scripts/ipkg-make-index.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+set -e
+
+pkg_dir=$1
+
+if [ -z $pkg_dir ] || [ ! -d $pkg_dir ]; then
+ echo "Usage: ipkg-make-index <package_directory>"
+ exit 1
+fi
+
+which md5sum 2>&1 >/dev/null || alias md5sum=md5
+
+for pkg in `find $pkg_dir -name '*.ipk' | sort`; do
+ echo "Generating index for package $pkg" >&2
+ file_size=$(ls -l $pkg | awk '{print $5}')
+ md5sum=$(md5sum $pkg | awk '{print $1}')
+ # Take pains to make variable value sed-safe
+ sed_safe_pkg=`echo $pkg | sed -e 's/\\//\\\\\\//g'`
+ tar -xzOf $pkg ./control.tar.gz | tar xzOf - ./control | sed -e "s/^Description:/Filename: $sed_safe_pkg\\
+Size: $file_size\\
+MD5Sum: $md5sum\\
+Description:/"
+ echo ""
+done
diff --git a/scripts/make-ipkg-dir.sh b/scripts/make-ipkg-dir.sh
new file mode 100755
index 0000000000..902a4b526b
--- /dev/null
+++ b/scripts/make-ipkg-dir.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+BASE=http://svn.openwrt.org/openwrt/trunk/openwrt
+TARGET=$1
+CONTROL=$2
+VERSION=$3
+ARCH=$4
+
+WD=$(pwd)
+
+mkdir -p "$TARGET/CONTROL"
+grep '^[^(Version|Architecture)]' "$CONTROL" > "$TARGET/CONTROL/control"
+grep '^Maintainer' "$CONTROL" 2>&1 >/dev/null || \
+ echo "Maintainer: OpenWrt Developers Team <openwrt-devel@openwrt.org>" >> "$TARGET/CONTROL/control"
+grep '^Source' "$CONTROL" 2>&1 >/dev/null || {
+ pkgbase=$(echo "$WD" | sed -e "s|^$TOPDIR/||g")
+ [ "$pkgbase" = "$WD" ] && src="N/A" || src="$BASE/$pkgbase"
+ echo "Source: $src" >> "$TARGET/CONTROL/control"
+}
+echo "Version: $VERSION" >> "$TARGET/CONTROL/control"
+echo "Architecture: $ARCH" >> "$TARGET/CONTROL/control"
+chmod 644 "$TARGET/CONTROL/control"
diff --git a/scripts/patch-kernel.sh b/scripts/patch-kernel.sh
new file mode 100755
index 0000000000..5455a0cf8d
--- /dev/null
+++ b/scripts/patch-kernel.sh
@@ -0,0 +1,54 @@
+#! /bin/sh
+# A little script I whipped up to make it easy to
+# patch source trees and have sane error handling
+# -Erik
+#
+# (c) 2002 Erik Andersen <andersen@codepoet.org>
+
+# Set directories from arguments, or use defaults.
+targetdir=${1-.}
+patchdir=${2-../kernel-patches}
+patchpattern=${3-*}
+
+if [ ! -d "${targetdir}" ] ; then
+ echo "Aborting. '${targetdir}' is not a directory."
+ exit 1
+fi
+if [ ! -d "${patchdir}" ] ; then
+ echo "Aborting. '${patchdir}' is not a directory."
+ exit 1
+fi
+
+for i in ${patchdir}/${patchpattern} ; do
+ case "$i" in
+ *.gz)
+ type="gzip"; uncomp="gunzip -dc"; ;;
+ *.bz)
+ type="bzip"; uncomp="bunzip -dc"; ;;
+ *.bz2)
+ type="bzip2"; uncomp="bunzip2 -dc"; ;;
+ *.zip)
+ type="zip"; uncomp="unzip -d"; ;;
+ *.Z)
+ type="compress"; uncomp="uncompress -c"; ;;
+ *)
+ type="plaintext"; uncomp="cat"; ;;
+ esac
+ [ -d "${i}" ] && echo "Ignoring subdirectory ${i}" && continue
+ echo ""
+ echo "Applying ${i} using ${type}: "
+ ${uncomp} ${i} | patch -p1 -E -d ${targetdir}
+ if [ $? != 0 ] ; then
+ echo "Patch failed! Please fix $i!"
+ exit 1
+ fi
+done
+
+# Check for rejects...
+if [ "`find $targetdir/ '(' -name '*.rej' -o -name '.*.rej' ')' -print`" ] ; then
+ echo "Aborting. Reject files found."
+ exit 1
+fi
+
+# Remove backup files
+find $targetdir/ '(' -name '*.orig' -o -name '.*.orig' ')' -exec rm -f {} \;
diff --git a/scripts/rstrip.sh b/scripts/rstrip.sh
new file mode 100755
index 0000000000..09a2f9f551
--- /dev/null
+++ b/scripts/rstrip.sh
@@ -0,0 +1,35 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+
+SELF=${0##*/}
+
+[ -z "$STRIP" ] && {
+ echo "$SELF: strip command not defined (STRIP variable not set)"
+ exit 1
+}
+
+TARGETS=$*
+
+[ -z "$TARGETS" ] && {
+ echo "$SELF: no directories / files specified"
+ echo "usage: $SELF [PATH...]"
+ exit 1
+}
+
+find $TARGETS -type f -a -exec file {} \; | \
+ sed -n -e 's/^\(.*\):.*ELF.*\(executable\|relocatable\|shared object\).*,.* stripped/\1:\2/p' | \
+(
+ IFS=":"
+ while read F S; do
+ echo "$SELF: $F:$S"
+ [ "${F##*\.}" = "o" -o "${F##*\.}" = "ko" ] && \
+ eval "$STRIP_KMOD $F" || \
+ eval "$STRIP $F"
+ done
+)
diff --git a/scripts/timestamp.pl b/scripts/timestamp.pl
new file mode 100755
index 0000000000..a3aa50cb0d
--- /dev/null
+++ b/scripts/timestamp.pl
@@ -0,0 +1,64 @@
+#!/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;
+
+sub get_ts($$) {
+ my $path = shift;
+ my $options = shift;
+ my $ts = 0;
+ my $fn = "";
+ open FIND, "find $path -not -path \\*.svn\\* -and -not -path \\*CVS\\* $options 2>/dev/null |";
+ while (<FIND>) {
+ chomp;
+ my $file = $_;
+ open FILE, "<$file";
+ my @stat = stat FILE;
+ close FILE;
+ if ($stat[9] > $ts) {
+ $ts = $stat[9];
+ $fn = $file;
+ }
+ }
+ close FIND;
+ return ($ts, $fn);
+}
+
+(@ARGV > 0) or push @ARGV, ".";
+my $ts = 0;
+my $n = ".";
+my %options;
+while (@ARGV > 0) {
+ my $path = shift @ARGV;
+ if ($path =~ /^-x/) {
+ my $str = shift @ARGV;
+ $options{"findopts"} .= " -and -not -path \\*".$str."\\*"
+ } elsif ($path =~ /^-f/) {
+ $options{"findopts"} .= " -follow";
+ } elsif ($path =~ /^-/) {
+ $options{$path} = 1;
+ } else {
+ my ($tmp, $fname) = get_ts($path, $options{"findopts"});
+ if ($tmp > $ts) {
+ if ($options{'-f'}) {
+ $n = $fname;
+ } else {
+ $n = $path;
+ }
+ $ts = $tmp;
+ }
+ }
+}
+
+if ($options{"-p"}) {
+ print "$n\n";
+} elsif ($options{"-t"}) {
+ print "$ts\n";
+} else {
+ print "$n\t$ts\n";
+}
diff --git a/target/Config.in b/target/Config.in
new file mode 100644
index 0000000000..effd9d7aa8
--- /dev/null
+++ b/target/Config.in
@@ -0,0 +1,272 @@
+choice
+ prompt "Target System"
+ default LINUX_2_4_BRCM
+
+config LINUX_2_6_AU1000
+ bool "AMD Alchemy AUxx [2.6]"
+ select mipsel
+ select LINUX_2_6
+ select PCI_SUPPORT
+ select USB_SUPPORT
+ select USES_JFFS2
+ help
+ Build firmware for AMD Alchemy 1500 boards
+ (e.g. 4G-Systems Mesh/Access Cube ...)
+
+config LINUX_2_6_ARUBA
+ bool "Aruba [2.6]"
+ select mips
+ select LINUX_2_6
+ select PCI_SUPPORT
+ select USB_SUPPORT
+ select USES_JFFS2
+ help
+ Build firmware images for Aruba boards
+
+config LINUX_2_4_AR531X
+ bool "Atheros AR531x [2.4]"
+ depends BROKEN
+ select mips
+ select LINUX_2_4
+ select USES_JFFS2
+ help
+ Build firmware images for Atheros AR531x based boards
+ (e.g. Netgear WGT624, Linksys WRT55AG)
+
+config LINUX_2_4_BRCM
+ bool "Broadcom BCM47xx/53xx [2.4]"
+ select mipsel
+ select PCI_SUPPORT
+ select USB_SUPPORT
+ select PCMCIA_SUPPORT
+ select USES_SQUASHFS
+ select USES_JFFS2
+ help
+ Build firmware images for Broadcom based routers
+ (e.g. Linksys WRT54G(S), Asus WL-500g, Motorola WR850G)
+
+ This one builds the generic .trx images, activate one of the
+ options below for creating device specific files for use
+ with TFTP client too.
+
+config LINUX_2_6_BRCM
+ bool "Broadcom BCM47xx/53xx [2.6]"
+ select mipsel
+ select LINUX_2_6
+ select PCI_SUPPORT
+ select USB_SUPPORT
+ #select PCMCIA_SUPPORT
+ select USES_SQUASHFS
+ select USES_JFFS2
+ help
+ Build firmware images for Broadcom based routers
+ (e.g. Netgear WGT634u)
+
+config LINUX_2_6_BRCM63XX
+ bool "Broadcom BCM63xx [2.6]"
+ depends BROKEN
+ select mips
+ select LINUX_2_6
+ select PCI_SUPPORT
+ select USB_SUPPORT
+ select PCMCIA_SUPPORT
+ select USES_SQUASHFS
+ select USES_JFFS2
+ help
+ Build firmware images for Broadcom based xDSL/routers
+ (e.g. Inventel Livebox, Siemens SE515)
+
+config LINUX_2_6_XSCALE
+ bool "Intel XScale [2.6]"
+ select armeb
+ select LINUX_2_6
+ select PCI_SUPPORT
+ select USB_SUPPORT
+ select USES_JFFS2
+
+config LINUX_2_6_MAGICBOX
+ bool "Magicbox [2.6]"
+ select powerpc
+ select LINUX_2_6
+ select PCI_SUPPORT
+ select USES_JFFS2
+
+config LINUX_2_6_RB532
+ bool "Mikrotik RB532 [2.6]"
+ select mipsel
+ select LINUX_2_6
+ select PCI_SUPPORT
+ select USES_JFFS2
+
+config LINUX_2_4_AR7
+ bool "TI AR7 [2.4]"
+ select mipsel
+ select USES_SQUASHFS
+ select USES_JFFS2
+ help
+ Build firmware images for TI AR7 based routers (w.g. Linksys WAG54G v2)
+
+config LINUX_2_6_X86
+ bool "x86 [2.6]"
+ select i386
+ select LINUX_2_6
+ select PCI_SUPPORT
+ select USB_SUPPORT
+ select PCMCIA_SUPPORT
+ select USES_JFFS2
+ help
+ Build firmware images for x86 based boards
+ (e.g. Soekris net4521 and net4801, PC Engines WRAP...)
+
+config LINUX_2_6_UML
+ bool "x86 [uml]"
+ select i386
+ select LINUX_2_6
+ help
+ Build uml targetted images
+
+if DEVEL
+
+config LINUX_2_6_ARM
+ bool "UNSUPPORTED little-endian arm platform"
+ depends BROKEN
+ select LINUX_2_6
+ select arm
+
+config LINUX_2_6_CRIS
+ bool "UNSUPPORTED cris platform"
+ depends BROKEN
+ select LINUX_2_6
+ select cris
+
+config LINUX_2_6_M68K
+ bool "UNSUPPORTED m68k platform"
+ depends BROKEN
+ select LINUX_2_6
+ select m68k
+
+config LINUX_2_6_SH3
+ bool "UNSUPPORTED little-endian sh3 platform"
+ depends BROKEN
+ select LINUX_2_6
+ select sh3
+
+config LINUX_2_6_SH3EB
+ bool "UNSUPPORTED big-endian sh3 platform"
+ depends BROKEN
+ select LINUX_2_6
+ select sh3eb
+
+config LINUX_2_6_SH4
+ bool "UNSUPPORTED little-endian sh4 platform"
+ depends BROKEN
+ select LINUX_2_6
+ select sh4
+
+config LINUX_2_6_SH4EB
+ bool "UNSUPPORTED big-endian sh4 platform"
+ depends BROKEN
+ select LINUX_2_6
+ select sh4eb
+
+config LINUX_2_6_SPARC
+ bool "UNSUPPORTED sparc platform"
+ depends BROKEN
+ select LINUX_2_6
+ select sparc
+
+endif
+
+endchoice
+
+
+# Kernel/Hardware features
+
+config LINUX_2_4
+ bool
+
+config LINUX_2_6
+ bool
+
+config PCI_SUPPORT
+ bool
+
+config PCMCIA_SUPPORT
+ bool
+
+config USB_SUPPORT
+ bool
+
+config BIG_ENDIAN
+ bool
+
+config USES_SQUASHFS
+ bool
+
+config USES_JFFS2
+ bool
+
+# Architecture selection
+
+config i386
+ bool
+
+config mips
+ select BIG_ENDIAN
+ bool
+
+config mipsel
+ bool
+
+config arm
+ bool
+
+config armeb
+ select BIG_ENDIAN
+ bool
+
+config cris
+ bool
+
+config m68k
+ bool
+
+config powerpc
+ select BIG_ENDIAN
+ bool
+
+config sh3
+ bool
+
+config sh3eb
+ select BIG_ENDIAN
+ bool
+
+config sh4
+ bool
+
+config sh4eb
+ select BIG_ENDIAN
+ bool
+
+config sparc
+ select BIG_ENDIAN
+ bool
+
+config ARCH
+ string
+ default "arm" if arm
+ default "armeb" if armeb
+ default "cris" if cris
+ default "i386" if i386
+ default "m68k" if m68k
+ default "mips" if mips
+ default "mipsel" if mipsel
+ default "powerpc" if powerpc
+ default "sh3" if sh3
+ default "sh3eb" if sh3eb
+ default "sh4" if sh4
+ default "sh4eb" if sh4eb
+ default "sparc" if sparc
+ default "mipsel" if !DEVEL
+
diff --git a/target/Makefile b/target/Makefile
new file mode 100644
index 0000000000..195878e665
--- /dev/null
+++ b/target/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
+include $(INCLUDE_DIR)/target.mk
+
+all: install
+
+$(BIN_DIR):
+ mkdir -p $(BIN_DIR)
+
+TARGETS-y := linux utils
+TARGETS-$(CONFIG_SDK) += sdk
+
+linux-compile: utils-install
+linux-install: $(BIN_DIR)
+sdk-compile: linux-install
+image_install: linux-install
+
+download: $(patsubst %,%-download,$(TARGETS-y))
+prepare: linux-prepare
+compile: linux-compile image_compile
+install: image_clean $(patsubst %,%-install,$(TARGETS-y)) image_install
+clean: $(patsubst %,%-clean,$(TARGETS-y)) image_clean
+
+image_clean: FORCE
+ $(MAKE) -C image/$(BOARD) clean
+ rm -f $(BIN_DIR)/openwrt-*
+
+image_compile: FORCE
+ $(MAKE) -C image/$(BOARD) compile
+
+image_install: image_compile
+ $(MAKE) -C image/$(BOARD) install
+
+%-clean: FORCE
+ $(MAKE) -C $(patsubst %-clean,%,$@) clean
+%-download: FORCE
+ $(MAKE) -C $(patsubst %-download,%,$@) download
+%-prepare: FORCE
+ $(MAKE) -C $(patsubst %-prepare,%,$@) prepare
+%-compile: %-prepare
+ $(MAKE) -C $(patsubst %-compile,%,$@) compile
+%-install: %-compile
+ $(MAKE) -C $(patsubst %-install,%,$@) install
+
diff --git a/target/image/ar7/Makefile b/target/image/ar7/Makefile
new file mode 100644
index 0000000000..d2af2d9a81
--- /dev/null
+++ b/target/image/ar7/Makefile
@@ -0,0 +1,102 @@
+#
+# 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)/image.mk
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/ar7loader
+
+LOADADDR := 0x94020000
+OUTPUT_FORMAT := elf32-tradlittlemips
+
+CFLAGS := -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -Os \
+ -fno-strict-aliasing -fno-common -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic \
+ -pipe -mlong-calls -fno-common \
+ -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap \
+ -DLOADADDR=$(LOADADDR)
+
+$(PKG_BUILD_DIR)/cksum.o: $(PKG_BUILD_DIR)/cksum.c
+ $(HOSTCC) -o $@ $<
+
+$(PKG_BUILD_DIR)/ckmain.o: $(PKG_BUILD_DIR)/ckmain.c
+ $(HOSTCC) -o $@ $<
+
+$(PKG_BUILD_DIR)/tichksum: $(PKG_BUILD_DIR)/ckmain.o $(PKG_BUILD_DIR)/cksum.o
+ $(HOSTCC) -o $@ $<
+
+$(PKG_BUILD_DIR)/LzmaDecode.o: src/LzmaDecode.c
+ $(TARGET_CC) $(CFLAGS) -c -o $@ $<
+
+$(PKG_BUILD_DIR)/loader.o: src/loader.c
+ $(TARGET_CC) $(CFLAGS) -c -o $@ $<
+
+$(STAGING_DIR)/bin/srec2bin: src/srec2bin.c
+ $(HOSTCC) -o $@ $<
+
+
+define Build/Compile
+ mkdir -p $(PKG_BUILD_DIR)
+ sed -e 's/@@OUTPUT_FORMAT@@/$(OUTPUT_FORMAT)/' \
+ -e 's/@@LOADADDR@@/$(LOADADDR)/' \
+ < src/zimage.script.in \
+ > $(PKG_BUILD_DIR)/zimage.script
+ sed -e 's/@@OUTPUT_FORMAT@@/$(OUTPUT_FORMAT)/' \
+ -e 's/@@LOADADDR@@/$(LOADADDR)/' \
+ < src/ld.script.in \
+ > $(PKG_BUILD_DIR)/ld.script
+ $(MAKE) $(PKG_BUILD_DIR)/loader.o $(PKG_BUILD_DIR)/LzmaDecode.o $(STAGING_DIR)/bin/srec2bin
+endef
+
+define Build/Clean
+ rm -rf $(PKG_BUILD_DIR)
+endef
+
+define Image/Prepare
+ cat $(KDIR)/vmlinux | $(STAGING_DIR)/bin/lzma e -si -so -eos -lc1 -lp2 -pb2 > $(KDIR)/vmlinux.lzma
+ $(TARGET_CROSS)ld -T $(PKG_BUILD_DIR)/zimage.script -r -b binary $(KDIR)/vmlinux.lzma -o $(KDIR)/zimage.o
+ $(TARGET_CROSS)ld -static -G 0 --defsym kernel_entry=0x$${shell nm $(KDIR)/linux-*/vmlinux | grep kernel_entry | cut -d' ' -f1} -T $(PKG_BUILD_DIR)/ld.script \
+ $(PKG_BUILD_DIR)/loader.o \
+ $(PKG_BUILD_DIR)/LzmaDecode.o \
+ $(KDIR)/zimage.o \
+ -o $(KDIR)/loader
+ $(TARGET_CROSS)objcopy -O srec $(KDIR)/loader $(KDIR)/ram_zimage.sre
+ $(STAGING_DIR)/bin/srec2bin $(KDIR)/ram_zimage.sre $(KDIR)/vmlinux.bin
+endef
+
+define align/jffs2-64k
+bs=65536 conv=sync
+endef
+
+define align/jffs2-128k
+bs=131072 conv=sync
+endef
+
+define Image/Build/CyberTAN
+ (dd if=/dev/zero bs=16 count=1; cat $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).bin) | \
+ $(STAGING_DIR)/bin/addpattern -p $(3) -o $(BIN_DIR)/openwrt-$(2)-$(KERNEL)-$(4).bin
+endef
+
+define Image/Build/sErCoMm
+ cat sercomm/adam2.bin "$(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).bin" > "$(BIN_DIR)/openwrt-$(2)-$(KERNEL)-$(3).img"
+ dd if=sercomm/$(2) of="$(KDIR)/dgfw.tmp" bs=$$$$((0x3e0000 - 80)) seek=1 conv=notrunc
+ $(STAGING_DIR)/bin/dgfirmware -f -w "$(BIN_DIR)/openwrt-$(2)-$(KERNEL)-$(3).img" "$(KDIR)/dgfw.tmp"
+ rm -f "$(KDIR)/dgfw.tmp"
+endef
+
+define Image/Build
+ dd if=$(KDIR)/vmlinux.bin $(call align/$(1)) > $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).bin
+ cat $(BUILD_DIR)/linux-$(KERNEL)-$(BOARD)/root.$(1) >> $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).bin
+ $(call Image/Build/CyberTAN,$(1),AG1B,AG1B,$(1))
+ $(call Image/Build/CyberTAN,$(1),WA21,WA21,$(1))
+ $(call Image/Build/CyberTAN,$(1),WA22,WA22,$(1))
+ $(call Image/Build/CyberTAN,$(1),WAG2,WAG2,$(1))
+ $(call Image/Build/CyberTAN,$(1),WA31,WA31 -b,$(1))
+ $(call Image/Build/CyberTAN,$(1),WA32,WA32 -b,$(1))
+ $(call Image/Build/sErCoMm,$(1),dg834,$(1))
+ $(call Image/Build/sErCoMm,$(1),jdr454wb,$(1))
+endef
+
+$(eval $(call BuildImage))
diff --git a/target/image/ar7/sercomm/adam2.bin b/target/image/ar7/sercomm/adam2.bin
new file mode 100644
index 0000000000..d4aa0cd2d3
--- /dev/null
+++ b/target/image/ar7/sercomm/adam2.bin
Binary files differ
diff --git a/target/image/ar7/sercomm/dg834 b/target/image/ar7/sercomm/dg834
new file mode 100644
index 0000000000..61fe336e85
--- /dev/null
+++ b/target/image/ar7/sercomm/dg834
Binary files differ
diff --git a/target/image/ar7/sercomm/jdr454wb b/target/image/ar7/sercomm/jdr454wb
new file mode 100644
index 0000000000..821ff1c1af
--- /dev/null
+++ b/target/image/ar7/sercomm/jdr454wb
Binary files differ
diff --git a/target/image/ar7/src/LzmaDecode.c b/target/image/ar7/src/LzmaDecode.c
new file mode 100644
index 0000000000..951700bddf
--- /dev/null
+++ b/target/image/ar7/src/LzmaDecode.c
@@ -0,0 +1,663 @@
+/*
+ LzmaDecode.c
+ LZMA Decoder
+
+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#ifndef Byte
+#define Byte unsigned char
+#endif
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+typedef struct _CRangeDecoder
+{
+ Byte *Buffer;
+ Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback;
+ int Result;
+ #endif
+ int ExtraBytes;
+} CRangeDecoder;
+
+Byte RangeDecoderReadByte(CRangeDecoder *rd)
+{
+ if (rd->Buffer == rd->BufferLim)
+ {
+ #ifdef _LZMA_IN_CB
+ UInt32 size;
+ rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
+ rd->BufferLim = rd->Buffer + size;
+ if (size == 0)
+ #endif
+ {
+ rd->ExtraBytes = 1;
+ return 0xFF;
+ }
+ }
+ return (*rd->Buffer++);
+}
+
+/* #define ReadByte (*rd->Buffer++) */
+#define ReadByte (RangeDecoderReadByte(rd))
+
+void RangeDecoderInit(CRangeDecoder *rd,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback
+ #else
+ Byte *stream, UInt32 bufferSize
+ #endif
+ )
+{
+ int i;
+ #ifdef _LZMA_IN_CB
+ rd->InCallback = inCallback;
+ rd->Buffer = rd->BufferLim = 0;
+ #else
+ rd->Buffer = stream;
+ rd->BufferLim = stream + bufferSize;
+ #endif
+ rd->ExtraBytes = 0;
+ rd->Code = 0;
+ rd->Range = (0xFFFFFFFF);
+ for(i = 0; i < 5; i++)
+ rd->Code = (rd->Code << 8) | ReadByte;
+}
+
+#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;
+#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
+#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
+
+UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
+{
+ RC_INIT_VAR
+ UInt32 result = 0;
+ int i;
+ for (i = numTotalBits; i > 0; i--)
+ {
+ /* UInt32 t; */
+ range >>= 1;
+
+ result <<= 1;
+ if (code >= range)
+ {
+ code -= range;
+ result |= 1;
+ }
+ /*
+ t = (code - range) >> 31;
+ t &= 1;
+ code -= range & (t - 1);
+ result = (result + result) | (1 - t);
+ */
+ RC_NORMALIZE
+ }
+ RC_FLUSH_VAR
+ return result;
+}
+
+int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
+{
+ UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
+ if (rd->Code < bound)
+ {
+ rd->Range = bound;
+ *prob += (kBitModelTotal - *prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 0;
+ }
+ else
+ {
+ rd->Range -= bound;
+ rd->Code -= bound;
+ *prob -= (*prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 1;
+ }
+}
+
+#define RC_GET_BIT2(prob, mi, A0, A1) \
+ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
+ if (code < bound) \
+ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
+ else \
+ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
+ RC_NORMALIZE
+
+#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
+
+int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = numLevels; i > 0; i--)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT(prob, mi)
+ #else
+ mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return mi - (1 << numLevels);
+}
+
+int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ int symbol = 0;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = 0; i < numLevels; i++)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
+ #else
+ int bit = RangeDecoderBitDecode(probs + mi, rd);
+ mi = mi + mi + bit;
+ symbol |= (bit << i);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ int bit;
+ int matchBit = (matchByte >> 7) & 1;
+ matchByte <<= 1;
+ #ifdef _LZMA_LOC_OPT
+ {
+ CProb *prob = probs + ((1 + matchBit) << 8) + symbol;
+ RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
+ }
+ #else
+ bit = RangeDecoderBitDecode(probs + ((1 + matchBit) << 8) + symbol, rd);
+ symbol = (symbol << 1) | bit;
+ #endif
+ if (matchBit != bit)
+ {
+ while (symbol < 0x100)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ break;
+ }
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
+{
+ if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
+ return RangeDecoderBitTreeDecode(p + LenLow +
+ (posState << kLenNumLowBits), kLenNumLowBits, rd);
+ if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
+ return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
+ (posState << kLenNumMidBits), kLenNumMidBits, rd);
+ return kLenNumLowSymbols + kLenNumMidSymbols +
+ RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
+}
+
+#define kNumStates 12
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+#ifdef _LZMA_OUT_READ
+
+typedef struct _LzmaVarState
+{
+ CRangeDecoder RangeDecoder;
+ Byte *Dictionary;
+ UInt32 DictionarySize;
+ UInt32 DictionaryPos;
+ UInt32 GlobalPos;
+ UInt32 Reps[4];
+ int lc;
+ int lp;
+ int pb;
+ int State;
+ int PreviousIsMatch;
+ int RemainLen;
+} LzmaVarState;
+
+int LzmaDecoderInit(
+ unsigned char *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ unsigned char *dictionary, UInt32 dictionarySize,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback
+ #else
+ unsigned char *inStream, UInt32 inSize
+ #endif
+ )
+{
+ LzmaVarState *vs = (LzmaVarState *)buffer;
+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
+ UInt32 i;
+ if (bufferSize < numProbs * sizeof(CProb) + sizeof(LzmaVarState))
+ return LZMA_RESULT_NOT_ENOUGH_MEM;
+ vs->Dictionary = dictionary;
+ vs->DictionarySize = dictionarySize;
+ vs->DictionaryPos = 0;
+ vs->GlobalPos = 0;
+ vs->Reps[0] = vs->Reps[1] = vs->Reps[2] = vs->Reps[3] = 1;
+ vs->lc = lc;
+ vs->lp = lp;
+ vs->pb = pb;
+ vs->State = 0;
+ vs->PreviousIsMatch = 0;
+ vs->RemainLen = 0;
+ dictionary[dictionarySize - 1] = 0;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ RangeDecoderInit(&vs->RangeDecoder,
+ #ifdef _LZMA_IN_CB
+ inCallback
+ #else
+ inStream, inSize
+ #endif
+ );
+ return LZMA_RESULT_OK;
+}
+
+int LzmaDecode(unsigned char *buffer,
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed)
+{
+ LzmaVarState *vs = (LzmaVarState *)buffer;
+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
+ CRangeDecoder rd = vs->RangeDecoder;
+ int state = vs->State;
+ int previousIsMatch = vs->PreviousIsMatch;
+ Byte previousByte;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ UInt32 nowPos = 0;
+ UInt32 posStateMask = (1 << (vs->pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->lp)) - 1;
+ int lc = vs->lc;
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+
+ Byte *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ if (len == -1)
+ {
+ *outSizeProcessed = 0;
+ return LZMA_RESULT_OK;
+ }
+
+ while(len > 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+#else
+
+int LzmaDecode(
+ Byte *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ unsigned char *inStream, UInt32 inSize,
+ #endif
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed)
+{
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
+ CProb *p = (CProb *)buffer;
+ CRangeDecoder rd;
+ UInt32 i;
+ int state = 0;
+ int previousIsMatch = 0;
+ Byte previousByte = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ UInt32 nowPos = 0;
+ UInt32 posStateMask = (1 << pb) - 1;
+ UInt32 literalPosMask = (1 << lp) - 1;
+ int len = 0;
+ if (bufferSize < numProbs * sizeof(CProb))
+ return LZMA_RESULT_NOT_ENOUGH_MEM;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ RangeDecoderInit(&rd,
+ #ifdef _LZMA_IN_CB
+ inCallback
+ #else
+ inStream, inSize
+ #endif
+ );
+#endif
+
+ *outSizeProcessed = 0;
+ while(nowPos < outSize)
+ {
+ int posState = (int)(
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & posStateMask);
+ #ifdef _LZMA_IN_CB
+ if (rd.Result != LZMA_RESULT_OK)
+ return rd.Result;
+ #endif
+ if (rd.ExtraBytes != 0)
+ return LZMA_RESULT_DATA_ERROR;
+ if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ CProb *probs = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ if (previousIsMatch)
+ {
+ Byte matchByte;
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ #else
+ matchByte = outStream[nowPos - rep0];
+ #endif
+ previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
+ previousIsMatch = 0;
+ }
+ else
+ previousByte = LzmaLiteralDecode(probs, &rd);
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #endif
+ }
+ else
+ {
+ previousIsMatch = 1;
+ if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
+ {
+ if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
+ {
+ if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos;
+ #endif
+ if (
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ == 0)
+ return LZMA_RESULT_DATA_ERROR;
+ state = state < 7 ? 9 : 11;
+ #ifdef _LZMA_OUT_READ
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ continue;
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
+ distance = rep1;
+ else
+ {
+ if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
+ distance = rep2;
+ else
+ {
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
+ state = state < 7 ? 8 : 11;
+ }
+ else
+ {
+ int posSlot;
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < 7 ? 7 : 10;
+ len = LzmaLenDecode(p + LenCoder, &rd, posState);
+ posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits), kNumPosSlotBits, &rd);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 += RangeDecoderReverseBitTreeDecode(
+ p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
+ }
+ else
+ {
+ rep0 += RangeDecoderDecodeDirectBits(&rd,
+ numDirectBits - kNumAlignBits) << kNumAlignBits;
+ rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
+ }
+ }
+ else
+ rep0 = posSlot;
+ rep0++;
+ }
+ if (rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = -1;
+ break;
+ }
+ if (rep0 > nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ {
+ return LZMA_RESULT_DATA_ERROR;
+ }
+ len += kMatchMinLen;
+ do
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ len--;
+ }
+ while(len > 0 && nowPos < outSize);
+ }
+ }
+
+ #ifdef _LZMA_OUT_READ
+ vs->RangeDecoder = rd;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = globalPos + nowPos;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->PreviousIsMatch = previousIsMatch;
+ vs->RemainLen = len;
+ #endif
+
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
diff --git a/target/image/ar7/src/LzmaDecode.h b/target/image/ar7/src/LzmaDecode.h
new file mode 100644
index 0000000000..f58944e3c3
--- /dev/null
+++ b/target/image/ar7/src/LzmaDecode.h
@@ -0,0 +1,100 @@
+/*
+ LzmaDecode.h
+ LZMA Decoder interface
+
+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMADECODE_H
+#define __LZMADECODE_H
+
+/* #define _LZMA_IN_CB */
+/* Use callback for input data */
+
+/* #define _LZMA_OUT_READ */
+/* Use read function for output data */
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case */
+
+/* #define _LZMA_LOC_OPT */
+/* Enable local speed optimizations inside code */
+
+#ifndef UInt32
+#ifdef _LZMA_UINT32_IS_ULONG
+#define UInt32 unsigned long
+#else
+#define UInt32 unsigned int
+#endif
+#endif
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb unsigned short
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+#define LZMA_RESULT_NOT_ENOUGH_MEM 2
+
+#ifdef _LZMA_IN_CB
+typedef struct _ILzmaInCallback
+{
+ int (*Read)(void *object, unsigned char **buffer, UInt32 *bufferSize);
+} ILzmaInCallback;
+#endif
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+/*
+bufferSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)))* sizeof(CProb)
+bufferSize += 100 in case of _LZMA_OUT_READ
+by default CProb is unsigned short,
+but if specify _LZMA_PROB_32, CProb will be UInt32(unsigned int)
+*/
+
+#ifdef _LZMA_OUT_READ
+int LzmaDecoderInit(
+ unsigned char *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ unsigned char *dictionary, UInt32 dictionarySize,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback
+ #else
+ unsigned char *inStream, UInt32 inSize
+ #endif
+);
+#endif
+
+int LzmaDecode(
+ unsigned char *buffer,
+ #ifndef _LZMA_OUT_READ
+ UInt32 bufferSize,
+ int lc, int lp, int pb,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ unsigned char *inStream, UInt32 inSize,
+ #endif
+ #endif
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed);
+
+#endif
diff --git a/target/image/ar7/src/gzip.h b/target/image/ar7/src/gzip.h
new file mode 100644
index 0000000000..917e66655c
--- /dev/null
+++ b/target/image/ar7/src/gzip.h
@@ -0,0 +1,51 @@
+//bvb#include "timemmap.h"
+
+#define OF(args) args
+#define STATIC static
+
+#define WSIZE 0x8000 /* Slideing window size (defined as var
+ * "window" below) must be at least 32k,
+ * and a power of two. This is the
+ * data work window used for input buffer
+ * by the input routine */
+
+typedef unsigned char uch;
+typedef unsigned short ush;
+typedef unsigned long ulg;
+
+
+static char *output_data;
+static ulg output_ptr;
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define NOMEMCPY /* Does routine memcpy exist? */
+
+//bvb static uch *inbuf; /* input buffer */
+static uch *window;
+
+//bvb static uch outwin[WSIZE];
+
+//bvb static unsigned insize; /* valid bytes in inbuf */
+static unsigned inptr; /* index of next byte to process in inbuf */
+
+static unsigned outcnt; /* bytes in output buffer */
+
+/* gzip flag byte */
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
+#define RESERVED 0xC0 /* bit 6,7: reserved */
+
+/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+#define BMAX 16 /* maximum bit length of any code (16 for explode) */
+#define N_MAX 288 /* maximum number of codes in any set */
+
+static char *input_data;
+
+static void *freememstart;
diff --git a/target/image/ar7/src/ld.script.in b/target/image/ar7/src/ld.script.in
new file mode 100644
index 0000000000..40389e644f
--- /dev/null
+++ b/target/image/ar7/src/ld.script.in
@@ -0,0 +1,34 @@
+ OUTPUT_FORMAT("@@OUTPUT_FORMAT@@")
+ OUTPUT_ARCH(mips)
+ENTRY(tikernelunzip)
+ SECTIONS
+{
+
+ /* Allocate memory space on top of kernel bss space */
+ . = 0x94200000;
+ .text :
+ {
+ *(.text)
+ *(.rodata)
+ *(.rodata1)
+ *(.gnu.warning)
+ *(.text.init)
+ *(.data.init)
+ }
+
+ .data :
+ {
+ *(*)
+ }
+
+ .bss :
+ {
+ *(.dynbss)
+ *(COMMON)
+ *(.bss)
+ *(.sbss)
+ *(.scommon)
+ . = ALIGN (0x8000);
+ workspace = .;
+ }
+}
diff --git a/target/image/ar7/src/loader.c b/target/image/ar7/src/loader.c
new file mode 100644
index 0000000000..22b909d7e9
--- /dev/null
+++ b/target/image/ar7/src/loader.c
@@ -0,0 +1,140 @@
+/* inflate.c -- Not copyrighted 1992 by Mark Adler
+ version c10p1, 10 January 1993 */
+
+/*
+ * Adapted for booting Linux by Hannu Savolainen 1993
+ * based on gzip-1.0.3
+ *
+ * Nicolas Pitre <nico@visuaide.com>, 1999/04/14 :
+ * Little mods for all variable to reside either into rodata or bss segments
+ * by marking constant variables with 'const' and initializing all the others
+ * at run-time only. This allows for the kernel uncompressor to run
+ * directly from Flash or ROM memory on embeded systems.
+ */
+
+#include <linux/config.h>
+#include "gzip.h"
+#include "LzmaDecode.h"
+
+/* Function prototypes */
+unsigned char get_byte(void);
+int tikernelunzip(int,char *[], char *[]);
+static int tidecompress(uch *, uch *);
+
+void kernel_entry(int, char *[], char *[]);
+void (*ke)(int, char *[], char *[]); /* Gen reference to kernel function */
+void (*prnt)(unsigned int, char *); /* Gen reference to Yamon print function */
+void printf(char *ptr); /* Generate our own printf */
+
+int tikernelunzip(int argc, char *argv[], char *arge[])
+{
+ extern unsigned int _ftext;
+ extern uch kernelimage[];
+ uch *in, *out;
+ int status;
+
+ printf("Launching kernel decompressor.\n");
+
+ out = (unsigned char *) LOADADDR;
+ in = &(kernelimage[0]);
+
+ status = tidecompress(in, out);
+
+ if (status == 0) {
+ printf("Kernel decompressor was successful ... launching kernel.\n");
+
+ ke = ( void(*)(int, char *[],char*[]))kernel_entry;
+ (*ke)(argc,argv,arge);
+
+ return (0);
+ } else {
+ printf("Error in decompression.\n");
+ return(1);
+ }
+}
+
+#if 0
+char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+void print_i(int i)
+{
+ int j;
+ char buf[11];
+
+ buf[0] = '0';
+ buf[1] = 'x';
+ buf[10] = 0;
+
+ for (j = 0; j < 8; j++)
+ {
+ buf[2 + 7 - j] = hex[i & 0xf];
+ i = i >> 4;
+ }
+
+ printf(buf);
+}
+#endif
+
+int tidecompress(uch *indata, uch *outdata)
+{
+ extern unsigned int workspace;
+ extern unsigned char kernelimage[], kernelimage_end[];
+ unsigned int i; /* temp value */
+ unsigned int lc; /* literal context bits */
+ unsigned int lp; /* literal pos state bits */
+ unsigned int pb; /* pos state bits */
+ unsigned int osize; /* uncompressed size */
+ unsigned int wsize; /* window size */
+ unsigned int insize = kernelimage_end - kernelimage;
+ int status;
+
+ output_ptr = 0;
+ output_data = outdata;
+ input_data = indata;
+
+ /* lzma args */
+ i = get_byte();
+ lc = i % 9, i = i / 9;
+ lp = i % 5, pb = i / 5;
+
+ /* skip rest of the LZMA coder property */
+ for (i = 0; i < 4; i++)
+ get_byte();
+
+ /* read the lower half of uncompressed size in the header */
+ osize = ((unsigned int)get_byte()) +
+ ((unsigned int)get_byte() << 8) +
+ ((unsigned int)get_byte() << 16) +
+ ((unsigned int)get_byte() << 24);
+
+ /* skip rest of the header (upper half of uncompressed size) */
+ for (i = 0; i < 4; i++)
+ get_byte();
+
+ i = 0;
+ wsize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp))) * sizeof(CProb);
+
+ if ((status = LzmaDecode((unsigned char *) &workspace, wsize, lc, lp, pb,
+ indata + 13, insize - 13, (unsigned char *) output_data, osize, &i)) == LZMA_RESULT_OK)
+ return 0;
+
+ return status;
+}
+
+
+void printf(char *ptr)
+{
+ unsigned int *tempptr = (unsigned int *)0x90000534;
+ prnt = ( void (*)(unsigned int, char *)) *tempptr;
+ (*prnt)(0,ptr);
+}
+
+unsigned char get_byte()
+{
+ unsigned char c;
+
+ c = *input_data;
+ input_data++;
+
+ return c;
+}
+
diff --git a/target/image/ar7/src/srec2bin.c b/target/image/ar7/src/srec2bin.c
new file mode 100644
index 0000000000..0eb8b2023a
--- /dev/null
+++ b/target/image/ar7/src/srec2bin.c
@@ -0,0 +1,523 @@
+#include <stdio.h>
+#include <ctype.h>
+
+//Rev 0.1 Original
+// 8 Jan 2001 MJH Added code to write data to Binary file
+// note: outputfile is name.bin, where name is first part
+// of input file. ie tmp.rec -> tmp.bin
+//
+// srec2bin <input SREC file> <Output Binary File> <If Present, Big Endian>
+//
+// TAG
+// bit32u TAG_BIG = 0xDEADBE42;
+// bit32u TAG_LITTLE = 0xFEEDFA42;
+//
+// File Structure
+//
+// TAG : 32 Bits
+// [DATA RECORDS]
+//
+// Data Records Structure
+//
+// LENGTH : 32 Bits <- Length of DATA, excludes ADDRESS and CHECKSUM
+// ADDRESS : 32 Bits
+// DATA : 8 Bits * LENGTH
+// CHECKSUM: 32 Bits <- 0 - (Sum of Length --> End of Data)
+//
+// Note : If Length == 0, Address will be Program Start
+//
+//
+//
+//
+//
+
+#define MajRevNum 0
+#define MinRevNum 2
+
+
+#define EndianSwitch(x) ((x >> 24) | (x << 24) | ((x << 8) & (0x00FF0000)) | ((x >> 8) & (0x0000FF00)) )
+
+typedef unsigned char bit8u;
+typedef unsigned int bit32u;
+typedef int bit32;
+
+#define FALSE 0
+#define TRUE (!FALSE)
+
+
+bit32u CheckSum;
+int RecStart;
+int debug;
+int verbose;
+
+FILE *OpenOutputFile( char *Name );
+FILE *fOut;
+bit32u RecLength=0;
+
+bit32u AddressCurrent;
+
+bit32u gh(char *cp,int nibs);
+
+int BigEndian;
+
+int inputline;
+
+// char buf[16*1024];
+
+char buffer[2048];
+char *cur_ptr;
+int cur_line=0;
+int cur_len=0;
+
+int s1s2s3_total=0;
+
+bit32u PBVal;
+int PBValid;
+bit32u PBAdr;
+
+
+void dumpfTell(char *s, bit32u Value)
+{
+ int Length;
+ Length = (int) RecLength;
+ if (debug)
+ printf("[%s ] ftell()[0x%08lX] Length[0x%4X] Length[%4d] Value[0x%08x]\n",
+ s, ftell(fOut), Length, Length, Value);
+}
+
+void DispHex(bit32u Hex)
+{
+// printf("%X", Hex);
+}
+
+void WaitDisplay(void)
+{
+ static int Count=0;
+ static int Index=0;
+ char iline[]={"-\\|/"};
+
+ Count++;
+ if ((Count % 32)==0)
+ {
+ if (verbose)
+ printf("%c%c",iline[Index++],8);
+ Index &= 3;
+ }
+}
+
+
+void binOut32 ( bit32u Data )
+{
+// On UNIX machine all 32bit writes need ENDIAN switched
+// Data = EndianSwitch(Data);
+// fwrite( &Data, sizeof(bit32u), 1, fOut);
+
+ char sdat[4];
+ int i;
+
+ for(i=0;i<4;i++)
+ sdat[i]=(char)(Data>>(i*8));
+ fwrite( sdat, 1, 4, fOut);
+ dumpfTell("Out32" , Data);
+}
+
+// Only update RecLength on Byte Writes
+// All 32 bit writes will be for Length etc
+
+void binOut8 ( bit8u Data )
+{
+ int n;
+ dumpfTell("B4Data" , (bit32u) (Data & 0xFF) );
+ n = fwrite( &Data, sizeof(bit8u), 1, fOut);
+ if (n != 1)
+ printf("Error in writing %X for Address 0x%8X\n", Data, AddressCurrent);
+ RecLength += 1;
+}
+
+// Currently ONLY used for outputting Program Start
+
+void binRecStart(bit32u Address)
+{
+ RecLength = 0;
+ CheckSum = Address;
+ RecStart = TRUE;
+
+ if (debug)
+ printf("[RecStart] CheckSum[0x%08X] Length[%4d] Address[0x%08X]\n",
+ CheckSum, RecLength, Address);
+
+
+ dumpfTell("RecLength", RecLength);
+ binOut32( RecLength );
+ dumpfTell("Address", Address);
+ binOut32( Address );
+}
+
+void binRecEnd(void)
+{
+ long RecEnd;
+
+ if (!RecStart) // if no record started, do not end it
+ {
+ return;
+ }
+
+ RecStart = FALSE;
+
+
+ RecEnd = ftell(fOut); // Save Current position
+
+ if (debug)
+ printf("[RecEnd ] CheckSum[0x%08X] Length[%4d] Length[0x%X] RecEnd[0x%08lX]\n",
+ CheckSum, RecLength, RecLength, RecEnd);
+
+ fseek( fOut, -((long) RecLength), SEEK_CUR); // move back Start Of Data
+
+ dumpfTell("Data ", -1);
+
+ fseek( fOut, -4, SEEK_CUR); // move back Start Of Address
+
+ dumpfTell("Address ", -1);
+
+ fseek( fOut, -4, SEEK_CUR); // move back Start Of Length
+
+ dumpfTell("Length ", -1);
+
+ binOut32( RecLength );
+
+ fseek( fOut, RecEnd, SEEK_SET); // move to end of Record
+
+ CheckSum += RecLength;
+
+ CheckSum = ~CheckSum + 1; // Two's complement
+
+ binOut32( CheckSum );
+
+ if (verbose)
+ printf("[Created Record of %d Bytes with CheckSum [0x%8X]\n", RecLength, CheckSum);
+}
+
+void binRecOutProgramStart(bit32u Address)
+{
+ if (Address != (AddressCurrent+1))
+ {
+ binRecEnd();
+ binRecStart(Address);
+ }
+ AddressCurrent = Address;
+}
+void binRecOutByte(bit32u Address, bit8u Data)
+{
+ // If Address is one after Current Address, output Byte
+ // If not, close out last record, update Length, write checksum
+ // Then Start New Record, updating Current Address
+
+ if (Address != (AddressCurrent+1))
+ {
+ binRecEnd();
+ binRecStart(Address);
+ }
+ AddressCurrent = Address;
+ CheckSum += Data;
+ binOut8( Data );
+}
+
+//=============================================================================
+// SUPPORT FUNCTIONS
+//=============================================================================
+int readline(FILE *fil,char *buf,int len)
+{
+ int rlen;
+
+ rlen=0;
+ if (len==0) return(0);
+ while(1)
+ {
+ if (cur_len==0)
+ {
+ cur_len=fread(buffer, 1, sizeof(buffer), fil);
+ if (cur_len==0)
+ {
+ if (rlen)
+ {
+ *buf=0;
+ return(rlen);
+ }
+ return(-1);
+ }
+ cur_ptr=buffer;
+ }
+ if (cur_len)
+ {
+ if (*cur_ptr=='\n')
+ {
+ *buf=0;
+ cur_ptr++;
+ cur_len--;
+ return(rlen);
+ }
+ else
+ {
+ if ((len>1)&&(*cur_ptr!='\r'))
+ {
+ *buf++=*cur_ptr++;
+ len--;
+ }
+ else
+ cur_ptr++;
+
+ rlen++;
+ cur_len--;
+ }
+ }
+ else
+ {
+ *buf=0;
+ cur_ptr++;
+ cur_len--;
+ return(rlen);
+ }
+ }
+}
+
+
+int SRLerrorout(char *c1,char *c2)
+{
+ printf("\nERROR: %s - '%s'.",c1,c2);
+ return(FALSE);
+}
+
+
+int checksum(char *cp,int count)
+{
+ char *scp;
+ int cksum;
+ int dum;
+
+ scp=cp;
+ while(*scp)
+ {
+ if (!isxdigit(*scp++))
+ return(SRLerrorout("Invalid hex digits",cp));
+ }
+ scp=cp;
+
+ cksum=count;
+
+ while(count)
+ {
+ cksum += gh(scp,2);
+ if (count == 2)
+ dum = ~cksum;
+ scp += 2;
+ count--;
+ }
+ cksum&=0x0ff;
+ // printf("\nCk:%02x",cksum);
+ return(cksum==0x0ff);
+}
+
+bit32u gh(char *cp,int nibs)
+{
+ int i;
+ bit32u j;
+
+ j=0;
+
+ for(i=0;i<nibs;i++)
+ {
+ j<<=4;
+ if ((*cp>='a')&&(*cp<='z')) *cp &= 0x5f;
+ if ((*cp>='0')&&(*cp<='9'))
+ j += (*cp-0x30);
+ else
+ if ((*cp>='A')&&(*cp<='F'))
+ j += (*cp-0x37);
+ else
+ SRLerrorout("Bad Hex char", cp);
+ cp++;
+ }
+ return(j);
+}
+
+
+//=============================================================================
+// PROCESS SREC LINE
+//=============================================================================
+
+int srecLine(char *pSrecLine)
+{
+ char *scp,ch;
+ int itmp,count,dat;
+ bit32u adr;
+ static bit32u RecordCounter=0;
+
+ cur_line++;
+ scp=pSrecLine;
+
+ if (*pSrecLine!='S')
+ return(SRLerrorout("Not an Srecord file",scp));
+ pSrecLine++;
+ if (strlen(pSrecLine)<4)
+ return(SRLerrorout("Srecord too short",scp));
+
+ ch=*pSrecLine++;
+
+ count=gh(pSrecLine,2);
+
+ pSrecLine += 2;
+
+ // if(debug)
+ // printf("count %d, strlen(pSrecLine) = %d, pSrecLine =[%s]\n", count, strlen(pSrecLine), pSrecLine);
+ RecordCounter++;
+ DispHex(RecordCounter);
+
+ if ((count*2) != strlen(pSrecLine)) return(SRLerrorout("Count field larger than record",scp));
+
+ if (!checksum(pSrecLine, count)) return(SRLerrorout("Bad Checksum",scp));
+
+ switch(ch)
+ {
+ case '0': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
+ itmp=gh(pSrecLine,4); pSrecLine+=4; count-=2;
+ if (itmp) return(SRLerrorout("Srecord 1 address not zero",scp));
+ break;
+ case '1': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
+ return(SRLerrorout("Srecord Not valid for MIPS",scp));
+ break;
+ case '2': if (count<4) return(SRLerrorout("Invalid Srecord count field",scp));
+ return(SRLerrorout("Srecord Not valid for MIPS",scp));
+ break;
+ case '3': if (count<5) return(SRLerrorout("Invalid Srecord count field",scp));
+ adr=gh(pSrecLine,8); pSrecLine+=8; count-=4;
+ count--;
+ while(count)
+ {
+ dat=gh(pSrecLine,2); pSrecLine+=2; count--;
+ binRecOutByte(adr, (char) (dat & 0xFF));
+ adr++;
+ }
+ s1s2s3_total++;
+ break;
+ case '4': return(SRLerrorout("Invalid Srecord type",scp));
+ break;
+ case '5': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
+ itmp=gh(pSrecLine,4); pSrecLine+=4; count-=2;
+ if (itmp|=s1s2s3_total) return(SRLerrorout("Incorrect number of S3 Record processed",scp));
+ break;
+ case '6': return(SRLerrorout("Invalid Srecord type",scp));
+ break;
+ case '7': // PROGRAM START
+ if (count<5) return(SRLerrorout("Invalid Srecord count field",scp));
+ adr=gh(pSrecLine,8); pSrecLine+=8; count-=4;
+ if (count!=1) return(SRLerrorout("Invalid Srecord count field",scp));
+ binRecOutProgramStart(adr);
+ break;
+ case '8': if (count<4) return(SRLerrorout("Invalid Srecord count field",scp));
+ return(SRLerrorout("Srecord Not valid for MIPS",scp));
+ break;
+ case '9': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
+ return(SRLerrorout("Srecord Not valid for MIPS",scp));
+ break;
+ default:
+ break;
+ }
+ return(TRUE);
+}
+
+
+//=============================================================================
+// MAIN LOGIC, READS IN LINE AND OUTPUTS BINARY
+//=============================================================================
+
+int srec2bin(int argc,char *argv[],int verbose)
+{
+ int i,rlen,sts;
+ FILE *fp;
+ char ac;
+ char buff[256];
+ bit32u TAG_BIG = 0xDEADBE42;
+ bit32u TAG_LITTLE = 0xFEEDFA42;
+
+ bit32u Tag;
+
+
+ if(argc < 3)
+ {
+ printf("\nError: <srec2bin <srec input file> <bin output file>\n\n");
+ return(0);
+ }
+
+ if (argc > 3) BigEndian=TRUE; else BigEndian=FALSE;
+
+ if (BigEndian)
+ Tag = TAG_BIG;
+ else
+ Tag = TAG_LITTLE;
+
+ if (verbose)
+ printf("\nEndian: %s, Tag is 0x%8X\n",(BigEndian)?"BIG":"LITTLE", Tag);
+
+ fp = fopen(argv[1],"rt");
+
+ if (fp==NULL)
+ {
+ printf("\nError: Opening input file, %s.", argv[1]);
+ return(0);
+ }
+
+ fOut = fopen( argv[2], "wb");
+
+ if (fOut==NULL)
+ {
+ printf("\nError: Opening Output file, %s.", argv[2]);
+ if(fp) fclose(fp);
+ return(0);
+ }
+
+ RecStart = FALSE;
+
+ AddressCurrent = 0xFFFFFFFFL;
+
+ // Setup Tag
+
+ dumpfTell("Tag", Tag);
+
+ binOut32(Tag);
+
+
+ inputline=0;
+ sts=TRUE;
+
+ rlen = readline(fp,buff,sizeof buff);
+
+ while( (sts) && (rlen != -1))
+ {
+ if (strlen(buff))
+ {
+ sts &= srecLine(buff);
+ WaitDisplay();
+ }
+ rlen = readline(fp,buff,sizeof buff);
+ }
+
+
+ // printf("PC: 0x%08X, Length 0x%08X, Tag 0x%08X\n", ProgramStart, RecLength, TAG_LITTLE);
+
+ binRecEnd();
+
+ if(fp) fclose(fp);
+ if(fOut) fclose(fOut);
+
+ return(1);
+}
+
+main(int argc, char *argv[])
+{
+ debug = TRUE;
+ debug = FALSE;
+ verbose = FALSE;
+ srec2bin(argc,argv,verbose);
+ return 0;
+}
+
diff --git a/target/image/ar7/src/zimage.script.in b/target/image/ar7/src/zimage.script.in
new file mode 100644
index 0000000000..1a0865b086
--- /dev/null
+++ b/target/image/ar7/src/zimage.script.in
@@ -0,0 +1,11 @@
+ OUTPUT_FORMAT("@@OUTPUT_FORMAT@@")
+OUTPUT_ARCH(mips)
+ SECTIONS
+{
+ .data :
+ {
+ kernelimage = .;
+ *(.data)
+ kernelimage_end = .;
+ }
+}
diff --git a/target/image/aruba/Makefile b/target/image/aruba/Makefile
new file mode 100644
index 0000000000..09aa8eabd4
--- /dev/null
+++ b/target/image/aruba/Makefile
@@ -0,0 +1,43 @@
+#
+# 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)/image.mk
+
+LOADADDR = 0x81000000 # RAM start + 16M
+KERNEL_ENTRY = 0x80100000
+RAMSIZE = 0x00100000 # 1MB
+
+LOADER_MAKEOPTS= \
+ KDIR=$(KDIR) \
+ LOADADDR=$(LOADADDR) \
+ KERNEL_ENTRY=$(KERNEL_ENTRY) \
+ RAMSIZE=$(RAMSIZE)
+
+define Build/Clean
+ $(MAKE) -C ../generic/lzma-loader $(LOADER_MAKEOPTS) clean
+endef
+
+define Image/Prepare
+ cat $(KDIR)/vmlinux | $(STAGING_DIR)/bin/lzma e -si -so -eos -lc1 -lp2 -pb2 > $(KDIR)/vmlinux.lzma
+ $(MAKE) -C ../generic/lzma-loader $(LOADER_MAKEOPTS) clean compile
+endef
+
+define Image/BuildKernel
+ ./addVersion -n ArubaOS $(KDIR)/loader.elf $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL).ari version
+endef
+
+define Image/Build/jffs2-64k
+ @dd if=$(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL).ari of=$(KDIR)/image.tmp bs=655360 conv=sync
+ @cat $(KDIR)/root.$(1) >> $(KDIR)/image.tmp
+ mv $(KDIR)/image.tmp $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(patsubst jffs2-%,jffs2,$(1)).bin
+endef
+
+define Image/Build
+ $(call Image/Build/$(1),$(1))
+endef
+
+$(eval $(call BuildImage))
diff --git a/target/image/aruba/addVersion b/target/image/aruba/addVersion
new file mode 100755
index 0000000000..796f73ad1b
--- /dev/null
+++ b/target/image/aruba/addVersion
Binary files differ
diff --git a/target/image/aruba/version b/target/image/aruba/version
new file mode 100644
index 0000000000..fff5589e14
--- /dev/null
+++ b/target/image/aruba/version
@@ -0,0 +1 @@
+3.0.0.0
diff --git a/target/image/au1000/Makefile b/target/image/au1000/Makefile
new file mode 100644
index 0000000000..0fb3cb2229
--- /dev/null
+++ b/target/image/au1000/Makefile
@@ -0,0 +1,22 @@
+#
+# 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)/image.mk
+
+define Build/Clean
+endef
+
+define Image/Prepare
+endef
+
+define Image/Build
+ $(TARGET_CROSS)objcopy -O srec -I binary --adjust-vma 0xbe000000 $(KDIR)/root.$(1) $(KDIR)/root.$(1).srec
+ grep -v S7 $(KDIR)/root.$(1).srec > $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).img
+ grep -v S0 $(LINUX_DIR)/arch/mips/boot/compressed/images/zImage.flash.srec >> $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).img
+endef
+
+$(eval $(call BuildImage))
diff --git a/target/image/brcm/Makefile b/target/image/brcm/Makefile
new file mode 100644
index 0000000000..2dc599daea
--- /dev/null
+++ b/target/image/brcm/Makefile
@@ -0,0 +1,69 @@
+#
+# 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)/image.mk
+
+define Build/Compile
+ rm -f $(KDIR)/loader.gz
+ $(MAKE) -C lzma-loader \
+ BUILD_DIR="$(KDIR)" \
+ TARGET="$(KDIR)" \
+ install
+ echo -ne "\\x00" >> $(KDIR)/loader.gz
+endef
+
+define Build/Clean
+ $(MAKE) -C lzma-loader clean
+endef
+
+define Image/Prepare
+ cat $(KDIR)/vmlinux | $(STAGING_DIR)/bin/lzma e -si -so -eos -lc1 -lp2 -pb2 > $(KDIR)/vmlinux.lzma
+endef
+
+define Image/Build/wgt634u
+ dd if=$(KDIR)/loader.elf of=$(BIN_DIR)/openwrt-wgt634u-$(KERNEL)-$(2).bin bs=131072 conv=sync
+ cat $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).trx >> $(BIN_DIR)/openwrt-wgt634u-$(KERNEL)-$(2).bin
+endef
+
+define Image/Build/CyberTAN
+ $(STAGING_DIR)/bin/addpattern -4 -p $(3) -v v$(4) -i $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).trx -o $(BIN_DIR)/openwrt-$(2)-$(KERNEL)-$(5).bin
+endef
+
+define Image/Build/Motorola
+ $(STAGING_DIR)/bin/motorola-bin -$(3) $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).trx $(BIN_DIR)/openwrt-$(2)-$(4).bin
+endef
+
+define trxalign/jffs2-128k
+-a 0x20000
+endef
+define trxalign/jffs2-64k
+-a 0x10000
+endef
+define trxalign/squashfs
+-a 1024
+endef
+
+define Image/Build
+ $(STAGING_DIR)/bin/trx -o $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).trx -f $(KDIR)/loader.gz -f $(KDIR)/vmlinux.lzma $(call trxalign/$(1)) -f $(KDIR)/root.$(1)
+ifneq ($(1),jffs2-128k)
+ $(call Image/Build/CyberTAN,$(1),wrt54g3g,W54F,1.99.5,$(patsubst jffs2-%,jffs2,$(1)))
+ $(call Image/Build/CyberTAN,$(1),wrt54g,W54G,4.40.1,$(patsubst jffs2-%,jffs2,$(1)))
+ $(call Image/Build/CyberTAN,$(1),wrt54gs_v4,W54s,1.09.1,$(patsubst jffs2-%,jffs2,$(1)))
+ $(call Image/Build/Motorola,$(1),wa840g,2,$(patsubst jffs2-%,jffs2,$(1)))
+ $(call Image/Build/Motorola,$(1),we800g,3,$(patsubst jffs2-%,jffs2,$(1)))
+endif
+ifneq ($(1),jffs2-64k)
+ $(call Image/Build/CyberTAN,$(1),wrt54gs,W54S,4.80.1,$(patsubst jffs2-%,jffs2,$(1)))
+ $(call Image/Build/CyberTAN,$(1),wrtsl54gs,W54U,2.00.5,$(patsubst jffs2-%,jffs2,$(1)))
+ifeq ($(KERNEL),2.6)
+ $(call Image/Build/wgt634u,$(1),$(patsubst jffs2-%,jffs2,$(1)))
+endif
+endif
+ $(call Image/Build/Motorola,$(1),wr850g,1,$(1))
+endef
+
+$(eval $(call BuildImage))
diff --git a/target/image/brcm/lzma-loader/Makefile b/target/image/brcm/lzma-loader/Makefile
new file mode 100644
index 0000000000..b56cbaab0f
--- /dev/null
+++ b/target/image/brcm/lzma-loader/Makefile
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME := lzma-loader
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+$(PKG_BUILD_DIR)/.prepared:
+ mkdir $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+ touch $@
+
+$(PKG_BUILD_DIR)/loader.gz: $(PKG_BUILD_DIR)/.prepared
+ $(MAKE) -C $(PKG_BUILD_DIR) CC="$(TARGET_CC)" \
+ LD="$(TARGET_CROSS)ld" CROSS_COMPILE="$(TARGET_CROSS)"
+
+download:
+prepare: $(PKG_BUILD_DIR)/.prepared
+compile: $(PKG_BUILD_DIR)/loader.gz
+install:
+
+ifneq ($(TARGET),)
+install: compile
+ $(CP) $(PKG_BUILD_DIR)/loader.gz $(PKG_BUILD_DIR)/loader.elf $(TARGET)/
+endif
+
+clean:
+ rm -rf $(PKG_BUILD_DIR)
diff --git a/target/image/brcm/lzma-loader/src/LzmaDecode.c b/target/image/brcm/lzma-loader/src/LzmaDecode.c
new file mode 100644
index 0000000000..951700bddf
--- /dev/null
+++ b/target/image/brcm/lzma-loader/src/LzmaDecode.c
@@ -0,0 +1,663 @@
+/*
+ LzmaDecode.c
+ LZMA Decoder
+
+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#ifndef Byte
+#define Byte unsigned char
+#endif
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+typedef struct _CRangeDecoder
+{
+ Byte *Buffer;
+ Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback;
+ int Result;
+ #endif
+ int ExtraBytes;
+} CRangeDecoder;
+
+Byte RangeDecoderReadByte(CRangeDecoder *rd)
+{
+ if (rd->Buffer == rd->BufferLim)
+ {
+ #ifdef _LZMA_IN_CB
+ UInt32 size;
+ rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
+ rd->BufferLim = rd->Buffer + size;
+ if (size == 0)
+ #endif
+ {
+ rd->ExtraBytes = 1;
+ return 0xFF;
+ }
+ }
+ return (*rd->Buffer++);
+}
+
+/* #define ReadByte (*rd->Buffer++) */
+#define ReadByte (RangeDecoderReadByte(rd))
+
+void RangeDecoderInit(CRangeDecoder *rd,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback
+ #else
+ Byte *stream, UInt32 bufferSize
+ #endif
+ )
+{
+ int i;
+ #ifdef _LZMA_IN_CB
+ rd->InCallback = inCallback;
+ rd->Buffer = rd->BufferLim = 0;
+ #else
+ rd->Buffer = stream;
+ rd->BufferLim = stream + bufferSize;
+ #endif
+ rd->ExtraBytes = 0;
+ rd->Code = 0;
+ rd->Range = (0xFFFFFFFF);
+ for(i = 0; i < 5; i++)
+ rd->Code = (rd->Code << 8) | ReadByte;
+}
+
+#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;
+#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
+#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
+
+UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
+{
+ RC_INIT_VAR
+ UInt32 result = 0;
+ int i;
+ for (i = numTotalBits; i > 0; i--)
+ {
+ /* UInt32 t; */
+ range >>= 1;
+
+ result <<= 1;
+ if (code >= range)
+ {
+ code -= range;
+ result |= 1;
+ }
+ /*
+ t = (code - range) >> 31;
+ t &= 1;
+ code -= range & (t - 1);
+ result = (result + result) | (1 - t);
+ */
+ RC_NORMALIZE
+ }
+ RC_FLUSH_VAR
+ return result;
+}
+
+int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
+{
+ UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
+ if (rd->Code < bound)
+ {
+ rd->Range = bound;
+ *prob += (kBitModelTotal - *prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 0;
+ }
+ else
+ {
+ rd->Range -= bound;
+ rd->Code -= bound;
+ *prob -= (*prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 1;
+ }
+}
+
+#define RC_GET_BIT2(prob, mi, A0, A1) \
+ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
+ if (code < bound) \
+ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
+ else \
+ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
+ RC_NORMALIZE
+
+#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
+
+int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = numLevels; i > 0; i--)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT(prob, mi)
+ #else
+ mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return mi - (1 << numLevels);
+}
+
+int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ int symbol = 0;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = 0; i < numLevels; i++)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
+ #else
+ int bit = RangeDecoderBitDecode(probs + mi, rd);
+ mi = mi + mi + bit;
+ symbol |= (bit << i);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ int bit;
+ int matchBit = (matchByte >> 7) & 1;
+ matchByte <<= 1;
+ #ifdef _LZMA_LOC_OPT
+ {
+ CProb *prob = probs + ((1 + matchBit) << 8) + symbol;
+ RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
+ }
+ #else
+ bit = RangeDecoderBitDecode(probs + ((1 + matchBit) << 8) + symbol, rd);
+ symbol = (symbol << 1) | bit;
+ #endif
+ if (matchBit != bit)
+ {
+ while (symbol < 0x100)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ break;
+ }
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
+{
+ if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
+ return RangeDecoderBitTreeDecode(p + LenLow +
+ (posState << kLenNumLowBits), kLenNumLowBits, rd);
+ if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
+ return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
+ (posState << kLenNumMidBits), kLenNumMidBits, rd);
+ return kLenNumLowSymbols + kLenNumMidSymbols +
+ RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
+}
+
+#define kNumStates 12
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+#ifdef _LZMA_OUT_READ
+
+typedef struct _LzmaVarState
+{
+ CRangeDecoder RangeDecoder;
+ Byte *Dictionary;
+ UInt32 DictionarySize;
+ UInt32 DictionaryPos;
+ UInt32 GlobalPos;
+ UInt32 Reps[4];
+ int lc;
+ int lp;
+ int pb;
+ int State;
+ int PreviousIsMatch;
+ int RemainLen;
+} LzmaVarState;
+
+int LzmaDecoderInit(
+ unsigned char *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ unsigned char *dictionary, UInt32 dictionarySize,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback
+ #else
+ unsigned char *inStream, UInt32 inSize
+ #endif
+ )
+{
+ LzmaVarState *vs = (LzmaVarState *)buffer;
+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
+ UInt32 i;
+ if (bufferSize < numProbs * sizeof(CProb) + sizeof(LzmaVarState))
+ return LZMA_RESULT_NOT_ENOUGH_MEM;
+ vs->Dictionary = dictionary;
+ vs->DictionarySize = dictionarySize;
+ vs->DictionaryPos = 0;
+ vs->GlobalPos = 0;
+ vs->Reps[0] = vs->Reps[1] = vs->Reps[2] = vs->Reps[3] = 1;
+ vs->lc = lc;
+ vs->lp = lp;
+ vs->pb = pb;
+ vs->State = 0;
+ vs->PreviousIsMatch = 0;
+ vs->RemainLen = 0;
+ dictionary[dictionarySize - 1] = 0;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ RangeDecoderInit(&vs->RangeDecoder,
+ #ifdef _LZMA_IN_CB
+ inCallback
+ #else
+ inStream, inSize
+ #endif
+ );
+ return LZMA_RESULT_OK;
+}
+
+int LzmaDecode(unsigned char *buffer,
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed)
+{
+ LzmaVarState *vs = (LzmaVarState *)buffer;
+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
+ CRangeDecoder rd = vs->RangeDecoder;
+ int state = vs->State;
+ int previousIsMatch = vs->PreviousIsMatch;
+ Byte previousByte;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ UInt32 nowPos = 0;
+ UInt32 posStateMask = (1 << (vs->pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->lp)) - 1;
+ int lc = vs->lc;
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+
+ Byte *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ if (len == -1)
+ {
+ *outSizeProcessed = 0;
+ return LZMA_RESULT_OK;
+ }
+
+ while(len > 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+#else
+
+int LzmaDecode(
+ Byte *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ unsigned char *inStream, UInt32 inSize,
+ #endif
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed)
+{
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
+ CProb *p = (CProb *)buffer;
+ CRangeDecoder rd;
+ UInt32 i;
+ int state = 0;
+ int previousIsMatch = 0;
+ Byte previousByte = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ UInt32 nowPos = 0;
+ UInt32 posStateMask = (1 << pb) - 1;
+ UInt32 literalPosMask = (1 << lp) - 1;
+ int len = 0;
+ if (bufferSize < numProbs * sizeof(CProb))
+ return LZMA_RESULT_NOT_ENOUGH_MEM;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ RangeDecoderInit(&rd,
+ #ifdef _LZMA_IN_CB
+ inCallback
+ #else
+ inStream, inSize
+ #endif
+ );
+#endif
+
+ *outSizeProcessed = 0;
+ while(nowPos < outSize)
+ {
+ int posState = (int)(
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & posStateMask);
+ #ifdef _LZMA_IN_CB
+ if (rd.Result != LZMA_RESULT_OK)
+ return rd.Result;
+ #endif
+ if (rd.ExtraBytes != 0)
+ return LZMA_RESULT_DATA_ERROR;
+ if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ CProb *probs = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ if (previousIsMatch)
+ {
+ Byte matchByte;
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ #else
+ matchByte = outStream[nowPos - rep0];
+ #endif
+ previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
+ previousIsMatch = 0;
+ }
+ else
+ previousByte = LzmaLiteralDecode(probs, &rd);
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #endif
+ }
+ else
+ {
+ previousIsMatch = 1;
+ if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
+ {
+ if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
+ {
+ if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos;
+ #endif
+ if (
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ == 0)
+ return LZMA_RESULT_DATA_ERROR;
+ state = state < 7 ? 9 : 11;
+ #ifdef _LZMA_OUT_READ
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ continue;
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
+ distance = rep1;
+ else
+ {
+ if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
+ distance = rep2;
+ else
+ {
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
+ state = state < 7 ? 8 : 11;
+ }
+ else
+ {
+ int posSlot;
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < 7 ? 7 : 10;
+ len = LzmaLenDecode(p + LenCoder, &rd, posState);
+ posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits), kNumPosSlotBits, &rd);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 += RangeDecoderReverseBitTreeDecode(
+ p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
+ }
+ else
+ {
+ rep0 += RangeDecoderDecodeDirectBits(&rd,
+ numDirectBits - kNumAlignBits) << kNumAlignBits;
+ rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
+ }
+ }
+ else
+ rep0 = posSlot;
+ rep0++;
+ }
+ if (rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = -1;
+ break;
+ }
+ if (rep0 > nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ {
+ return LZMA_RESULT_DATA_ERROR;
+ }
+ len += kMatchMinLen;
+ do
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ len--;
+ }
+ while(len > 0 && nowPos < outSize);
+ }
+ }
+
+ #ifdef _LZMA_OUT_READ
+ vs->RangeDecoder = rd;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = globalPos + nowPos;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->PreviousIsMatch = previousIsMatch;
+ vs->RemainLen = len;
+ #endif
+
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
diff --git a/target/image/brcm/lzma-loader/src/LzmaDecode.h b/target/image/brcm/lzma-loader/src/LzmaDecode.h
new file mode 100644
index 0000000000..f58944e3c3
--- /dev/null
+++ b/target/image/brcm/lzma-loader/src/LzmaDecode.h
@@ -0,0 +1,100 @@
+/*
+ LzmaDecode.h
+ LZMA Decoder interface
+
+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMADECODE_H
+#define __LZMADECODE_H
+
+/* #define _LZMA_IN_CB */
+/* Use callback for input data */
+
+/* #define _LZMA_OUT_READ */
+/* Use read function for output data */
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case */
+
+/* #define _LZMA_LOC_OPT */
+/* Enable local speed optimizations inside code */
+
+#ifndef UInt32
+#ifdef _LZMA_UINT32_IS_ULONG
+#define UInt32 unsigned long
+#else
+#define UInt32 unsigned int
+#endif
+#endif
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb unsigned short
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+#define LZMA_RESULT_NOT_ENOUGH_MEM 2
+
+#ifdef _LZMA_IN_CB
+typedef struct _ILzmaInCallback
+{
+ int (*Read)(void *object, unsigned char **buffer, UInt32 *bufferSize);
+} ILzmaInCallback;
+#endif
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+/*
+bufferSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)))* sizeof(CProb)
+bufferSize += 100 in case of _LZMA_OUT_READ
+by default CProb is unsigned short,
+but if specify _LZMA_PROB_32, CProb will be UInt32(unsigned int)
+*/
+
+#ifdef _LZMA_OUT_READ
+int LzmaDecoderInit(
+ unsigned char *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ unsigned char *dictionary, UInt32 dictionarySize,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback
+ #else
+ unsigned char *inStream, UInt32 inSize
+ #endif
+);
+#endif
+
+int LzmaDecode(
+ unsigned char *buffer,
+ #ifndef _LZMA_OUT_READ
+ UInt32 bufferSize,
+ int lc, int lp, int pb,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ unsigned char *inStream, UInt32 inSize,
+ #endif
+ #endif
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed);
+
+#endif
diff --git a/target/image/brcm/lzma-loader/src/Makefile b/target/image/brcm/lzma-loader/src/Makefile
new file mode 100644
index 0000000000..85a864674b
--- /dev/null
+++ b/target/image/brcm/lzma-loader/src/Makefile
@@ -0,0 +1,77 @@
+#
+# Makefile for Broadcom BCM947XX boards
+#
+# Copyright 2001-2003, 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.
+#
+# Copyright 2004 Manuel Novoa III <mjn3@codepoet.org>
+# Modified to support bzip'd kernels.
+# Of course, it would be better to integrate bunzip capability into CFE.
+#
+# Copyright 2005 Oleg I. Vdovikin <oleg@cs.msu.su>
+# Cleaned up, modified for lzma support, removed from kernel
+#
+
+TEXT_START := 0x80001000
+BZ_TEXT_START := 0x80300000
+
+OBJCOPY := $(CROSS_COMPILE)objcopy -O binary -R .reginfo -R .note -R .comment -R .mdebug -S
+
+CFLAGS = -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -Os \
+ -fno-strict-aliasing -fno-common -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic \
+ -ffunction-sections -pipe -mlong-calls -fno-common \
+ -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap
+CFLAGS += -DLOADADDR=$(TEXT_START) -D_LZMA_IN_CB
+
+ASFLAGS = $(CFLAGS) -D__ASSEMBLY__ -DBZ_TEXT_START=$(BZ_TEXT_START)
+
+SEDFLAGS := s/BZ_TEXT_START/$(BZ_TEXT_START)/;s/TEXT_START/$(TEXT_START)/
+
+OBJECTS := head.o data.o
+
+all: loader.gz loader.elf
+
+# Don't build dependencies, this may die if $(CC) isn't gcc
+dep:
+
+install:
+
+loader.gz: loader
+ gzip -nc9 $< > $@
+
+loader.elf: loader.o
+ cp $< $@
+
+loader: loader.o
+ $(OBJCOPY) $< $@
+
+loader.o: loader.lds $(OBJECTS)
+ $(LD) -static --gc-sections -no-warn-mismatch -T loader.lds -o $@ $(OBJECTS)
+
+loader.lds: loader.lds.in Makefile
+ @sed "$(SEDFLAGS)" < $< > $@
+
+data.o: data.lds decompress.image
+ $(LD) -no-warn-mismatch -T data.lds -r -o $@ -b binary decompress.image -b elf32-tradlittlemips
+
+data.lds:
+ @echo "SECTIONS { .data : { code_start = .; *(.data) code_stop = .; }}" > $@
+
+decompress.image: decompress
+ $(OBJCOPY) $< $@
+
+decompress: decompress.lds decompress.o LzmaDecode.o
+ $(LD) -static --gc-sections -no-warn-mismatch -T decompress.lds -o $@ decompress.o LzmaDecode.o
+
+decompress.lds: decompress.lds.in Makefile
+ @sed "$(SEDFLAGS)" < $< > $@
+
+mrproper: clean
+
+clean:
+ rm -f loader.gz loader decompress *.lds *.o *.image
diff --git a/target/image/brcm/lzma-loader/src/README b/target/image/brcm/lzma-loader/src/README
new file mode 100644
index 0000000000..16649e9500
--- /dev/null
+++ b/target/image/brcm/lzma-loader/src/README
@@ -0,0 +1,55 @@
+/*
+ * LZMA compressed kernel decompressor for bcm947xx boards
+ *
+ * Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
+ *
+ * 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 code is intended to decompress kernel, being compressed using lzma utility
+build using 7zip LZMA SDK. This utility is located in the LZMA_Alone directory
+
+decompressor code expects that your .trx file consist of three partitions:
+
+1) decompressor itself (this is gziped code which pmon/cfe will extract and run
+on boot-up instead of real kernel)
+2) LZMA compressed kernel (both streamed and regular modes are supported now)
+3) Root filesystem
+
+Please be sure to apply the following patch for use this new trx layout (it will
+allow using both new and old trx files for root filesystem lookup code)
+
+--- linuz/arch/mips/brcm-boards/bcm947xx/setup.c 2005-01-23 19:24:27.503322896 +0300
++++ linux/arch/mips/brcm-boards/bcm947xx/setup.c 2005-01-23 19:29:05.237100944 +0300
+@@ -221,7 +221,9 @@
+ /* Try looking at TRX header for rootfs offset */
+ if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
+ bcm947xx_parts[1].offset = off;
+- if (le32_to_cpu(trx->offsets[1]) > off)
++ if (le32_to_cpu(trx->offsets[2]) > off)
++ off = le32_to_cpu(trx->offsets[2]);
++ else if (le32_to_cpu(trx->offsets[1]) > off)
+ off = le32_to_cpu(trx->offsets[1]);
+ continue;
+ }
+
+
+Revision history:
+ 0.02 Initial release
+ 0.03 Added Mineharu Takahara <mtakahar@yahoo.com> patch to pass actual
+ output size to decoder (stream mode compressed input is not
+ a requirement anymore)
+ 0.04 Reordered functions using lds script
diff --git a/target/image/brcm/lzma-loader/src/decompress.c b/target/image/brcm/lzma-loader/src/decompress.c
new file mode 100644
index 0000000000..ec510e21e3
--- /dev/null
+++ b/target/image/brcm/lzma-loader/src/decompress.c
@@ -0,0 +1,175 @@
+/*
+ * LZMA compressed kernel decompressor for bcm947xx boards
+ *
+ * Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
+ *
+ * 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
+ *
+ *
+ * Please note, this was code based on the bunzip2 decompressor code
+ * by Manuel Novoa III (mjn3@codepoet.org), although the only thing left
+ * is an idea and part of original vendor code
+ *
+ *
+ * 12-Mar-2005 Mineharu Takahara <mtakahar@yahoo.com>
+ * pass actual output size to decoder (stream mode
+ * compressed input is not a requirement anymore)
+ *
+ * 24-Apr-2005 Oleg I. Vdovikin
+ * reordered functions using lds script, removed forward decl
+ *
+ */
+
+#include "LzmaDecode.h"
+
+#define BCM4710_FLASH 0x1fc00000 /* Flash */
+
+#define KSEG0 0x80000000
+#define KSEG1 0xa0000000
+
+#define KSEG1ADDR(a) ((((unsigned)(a)) & 0x1fffffffU) | KSEG1)
+
+#define Index_Invalidate_I 0x00
+#define Index_Writeback_Inv_D 0x01
+
+#define cache_unroll(base,op) \
+ __asm__ __volatile__( \
+ ".set noreorder;\n" \
+ ".set mips3;\n" \
+ "cache %1, (%0);\n" \
+ ".set mips0;\n" \
+ ".set reorder\n" \
+ : \
+ : "r" (base), \
+ "i" (op));
+
+static __inline__ void blast_icache(unsigned long size, unsigned long lsize)
+{
+ unsigned long start = KSEG0;
+ unsigned long end = (start + size);
+
+ while(start < end) {
+ cache_unroll(start,Index_Invalidate_I);
+ start += lsize;
+ }
+}
+
+static __inline__ void blast_dcache(unsigned long size, unsigned long lsize)
+{
+ unsigned long start = KSEG0;
+ unsigned long end = (start + size);
+
+ while(start < end) {
+ cache_unroll(start,Index_Writeback_Inv_D);
+ start += lsize;
+ }
+}
+
+#define TRX_MAGIC 0x30524448 /* "HDR0" */
+
+struct trx_header {
+ unsigned int magic; /* "HDR0" */
+ unsigned int len; /* Length of file including header */
+ unsigned int crc32; /* 32-bit CRC from flag_version to end of file */
+ unsigned int flag_version; /* 0:15 flags, 16:31 version */
+ unsigned int offsets[3]; /* Offsets of partitions from start of header */
+};
+
+/* beyound the image end, size not known in advance */
+extern unsigned char workspace[];
+
+unsigned int offset;
+unsigned char *data;
+
+/* flash access should be aligned, so wrapper is used */
+/* read byte from the flash, all accesses are 32-bit aligned */
+static int read_byte(void *object, unsigned char **buffer, UInt32 *bufferSize)
+{
+ static unsigned int val;
+
+ if (((unsigned int)offset % 4) == 0) {
+ val = *(unsigned int *)data;
+ data += 4;
+ }
+
+ *bufferSize = 1;
+ *buffer = ((unsigned char *)&val) + (offset++ & 3);
+
+ return LZMA_RESULT_OK;
+}
+
+static __inline__ unsigned char get_byte(void)
+{
+ unsigned char *buffer;
+ UInt32 fake;
+
+ return read_byte(0, &buffer, &fake), *buffer;
+}
+
+/* should be the first function */
+void entry(unsigned long icache_size, unsigned long icache_lsize,
+ unsigned long dcache_size, unsigned long dcache_lsize)
+{
+ unsigned int i; /* temp value */
+ unsigned int lc; /* literal context bits */
+ unsigned int lp; /* literal pos state bits */
+ unsigned int pb; /* pos state bits */
+ unsigned int osize; /* uncompressed size */
+
+ ILzmaInCallback callback;
+ callback.Read = read_byte;
+
+ /* look for trx header, 32-bit data access */
+ for (data = ((unsigned char *) KSEG1ADDR(BCM4710_FLASH));
+ ((struct trx_header *)data)->magic != TRX_MAGIC; data += 65536);
+
+ /* compressed kernel is in the partition 0 or 1 */
+ if (((struct trx_header *)data)->offsets[1] > 65536)
+ data += ((struct trx_header *)data)->offsets[0];
+ else
+ data += ((struct trx_header *)data)->offsets[1];
+
+ offset = 0;
+
+ /* lzma args */
+ i = get_byte();
+ lc = i % 9, i = i / 9;
+ lp = i % 5, pb = i / 5;
+
+ /* skip rest of the LZMA coder property */
+ for (i = 0; i < 4; i++)
+ get_byte();
+
+ /* read the lower half of uncompressed size in the header */
+ osize = ((unsigned int)get_byte()) +
+ ((unsigned int)get_byte() << 8) +
+ ((unsigned int)get_byte() << 16) +
+ ((unsigned int)get_byte() << 24);
+
+ /* skip rest of the header (upper half of uncompressed size) */
+ for (i = 0; i < 4; i++)
+ get_byte();
+
+ /* decompress kernel */
+ if (LzmaDecode(workspace, ~0, lc, lp, pb, &callback,
+ (unsigned char*)LOADADDR, osize, &i) == LZMA_RESULT_OK)
+ {
+ blast_dcache(dcache_size, dcache_lsize);
+ blast_icache(icache_size, icache_lsize);
+
+ /* Jump to load address */
+ ((void (*)(void)) LOADADDR)();
+ }
+}
diff --git a/target/image/brcm/lzma-loader/src/decompress.lds.in b/target/image/brcm/lzma-loader/src/decompress.lds.in
new file mode 100644
index 0000000000..33f56f8a09
--- /dev/null
+++ b/target/image/brcm/lzma-loader/src/decompress.lds.in
@@ -0,0 +1,20 @@
+OUTPUT_ARCH(mips)
+ENTRY(entry)
+SECTIONS {
+ . = BZ_TEXT_START;
+ .text : {
+ *(.text.entry)
+ *(.text)
+ *(.rodata)
+ }
+
+ .data : {
+ *(.data)
+ }
+
+ .bss : {
+ *(.bss)
+ }
+
+ workspace = .;
+}
diff --git a/target/image/brcm/lzma-loader/src/head.S b/target/image/brcm/lzma-loader/src/head.S
new file mode 100644
index 0000000000..9bfbd53d51
--- /dev/null
+++ b/target/image/brcm/lzma-loader/src/head.S
@@ -0,0 +1,155 @@
+/* Copyright 2005 Oleg I. Vdovikin (oleg@cs.msu.su) */
+/* cache manipulation adapted from Broadcom code */
+/* idea taken from original bunzip2 decompressor code */
+/* Copyright 2004 Manuel Novoa III (mjn3@codepoet.org) */
+/* Licensed under the linux kernel's version of the GPL.*/
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+#define KSEG0 0x80000000
+
+#define C0_CONFIG $16
+#define C0_TAGLO $28
+#define C0_TAGHI $29
+
+#define CONF1_DA_SHIFT 7 /* D$ associativity */
+#define CONF1_DA_MASK 0x00000380
+#define CONF1_DA_BASE 1
+#define CONF1_DL_SHIFT 10 /* D$ line size */
+#define CONF1_DL_MASK 0x00001c00
+#define CONF1_DL_BASE 2
+#define CONF1_DS_SHIFT 13 /* D$ sets/way */
+#define CONF1_DS_MASK 0x0000e000
+#define CONF1_DS_BASE 64
+#define CONF1_IA_SHIFT 16 /* I$ associativity */
+#define CONF1_IA_MASK 0x00070000
+#define CONF1_IA_BASE 1
+#define CONF1_IL_SHIFT 19 /* I$ line size */
+#define CONF1_IL_MASK 0x00380000
+#define CONF1_IL_BASE 2
+#define CONF1_IS_SHIFT 22 /* Instruction cache sets/way */
+#define CONF1_IS_MASK 0x01c00000
+#define CONF1_IS_BASE 64
+
+#define Index_Invalidate_I 0x00
+#define Index_Writeback_Inv_D 0x01
+
+ .text
+ LEAF(startup)
+ .set noreorder
+
+ /* Copy decompressor code to the right place */
+ li t2, BZ_TEXT_START
+ add a0, t2, 0
+ la a1, code_start
+ la a2, code_stop
+$L1:
+ lw t0, 0(a1)
+ sw t0, 0(a0)
+ add a1, 4
+ add a0, 4
+ blt a1, a2, $L1
+ nop
+
+ /* At this point we need to invalidate dcache and */
+ /* icache before jumping to new code */
+
+1: /* Get cache sizes */
+ .set mips32
+ mfc0 s0,C0_CONFIG,1
+ .set mips0
+
+ li s1,CONF1_DL_MASK
+ and s1,s0
+ beq s1,zero,nodc
+ nop
+
+ srl s1,CONF1_DL_SHIFT
+ li t0,CONF1_DL_BASE
+ sll s1,t0,s1 /* s1 has D$ cache line size */
+
+ li s2,CONF1_DA_MASK
+ and s2,s0
+ srl s2,CONF1_DA_SHIFT
+ addiu s2,CONF1_DA_BASE /* s2 now has D$ associativity */
+
+ li t0,CONF1_DS_MASK
+ and t0,s0
+ srl t0,CONF1_DS_SHIFT
+ li s3,CONF1_DS_BASE
+ sll s3,s3,t0 /* s3 has D$ sets per way */
+
+ multu s2,s3 /* sets/way * associativity */
+ mflo t0 /* total cache lines */
+
+ multu s1,t0 /* D$ linesize * lines */
+ mflo s2 /* s2 is now D$ size in bytes */
+
+ /* Initilize the D$: */
+ mtc0 zero,C0_TAGLO
+ mtc0 zero,C0_TAGHI
+
+ li t0,KSEG0 /* Just an address for the first $ line */
+ addu t1,t0,s2 /* + size of cache == end */
+
+ .set mips3
+1: cache Index_Writeback_Inv_D,0(t0)
+ .set mips0
+ bne t0,t1,1b
+ addu t0,s1
+
+nodc:
+ /* Now we get to do it all again for the I$ */
+
+ move s3,zero /* just in case there is no icache */
+ move s4,zero
+
+ li t0,CONF1_IL_MASK
+ and t0,s0
+ beq t0,zero,noic
+ nop
+
+ srl t0,CONF1_IL_SHIFT
+ li s3,CONF1_IL_BASE
+ sll s3,t0 /* s3 has I$ cache line size */
+
+ li t0,CONF1_IA_MASK
+ and t0,s0
+ srl t0,CONF1_IA_SHIFT
+ addiu s4,t0,CONF1_IA_BASE /* s4 now has I$ associativity */
+
+ li t0,CONF1_IS_MASK
+ and t0,s0
+ srl t0,CONF1_IS_SHIFT
+ li s5,CONF1_IS_BASE
+ sll s5,t0 /* s5 has I$ sets per way */
+
+ multu s4,s5 /* sets/way * associativity */
+ mflo t0 /* s4 is now total cache lines */
+
+ multu s3,t0 /* I$ linesize * lines */
+ mflo s4 /* s4 is cache size in bytes */
+
+ /* Initilize the I$: */
+ mtc0 zero,C0_TAGLO
+ mtc0 zero,C0_TAGHI
+
+ li t0,KSEG0 /* Just an address for the first $ line */
+ addu t1,t0,s4 /* + size of cache == end */
+
+ .set mips3
+1: cache Index_Invalidate_I,0(t0)
+ .set mips0
+ bne t0,t1,1b
+ addu t0,s3
+
+noic:
+ move a0,s3 /* icache line size */
+ move a1,s4 /* icache size */
+ move a2,s1 /* dcache line size */
+ jal t2
+ move a3,s2 /* dcache size */
+
+ .set reorder
+ END(startup)
diff --git a/target/image/brcm/lzma-loader/src/loader.lds.in b/target/image/brcm/lzma-loader/src/loader.lds.in
new file mode 100644
index 0000000000..20f2ea98ec
--- /dev/null
+++ b/target/image/brcm/lzma-loader/src/loader.lds.in
@@ -0,0 +1,17 @@
+OUTPUT_ARCH(mips)
+ENTRY(startup)
+SECTIONS {
+ . = TEXT_START;
+ .text : {
+ *(.text)
+ *(.rodata)
+ }
+
+ .data : {
+ *(.data)
+ }
+
+ .bss : {
+ *(.bss)
+ }
+}
diff --git a/target/image/brcm63xx/Makefile b/target/image/brcm63xx/Makefile
new file mode 100644
index 0000000000..6aa72c2920
--- /dev/null
+++ b/target/image/brcm63xx/Makefile
@@ -0,0 +1,33 @@
+#
+# 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)/image.mk
+
+LOADADDR = 0x8108c8f4 # RAM start + 16M
+KERNEL_ENTRY = 0x80100000 # Default kernel entry in arch/mips/Makefile
+RAMSIZE = 0x01000000 # 64MB
+
+LOADER_MAKEOPTS= \
+ KDIR=$(KDIR) \
+ LOADADDR=$(LOADADDR) \
+ KERNEL_ENTRY=$(KERNEL_ENTRY) \
+ RAMSIZE=$(RAMSIZE)
+
+define Build/Clean
+ $(MAKE) -C ../generic/lzma-loader $(LOADER_MAKEOPTS) clean
+endef
+
+define Image/Prepare
+ cat $(KDIR)/vmlinux | $(STAGING_DIR)/bin/lzma e -si -so -eos -lc1 -lp2 -pb2 > $(KDIR)/vmlinux.lzma
+ $(MAKE) -C ../generic/lzma-loader $(LOADER_MAKEOPTS) compile
+endef
+
+define Image/Build
+ cp $(KDIR)/vmlinux $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).img
+endef
+
+$(eval $(call BuildImage))
diff --git a/target/image/generic/Makefile b/target/image/generic/Makefile
new file mode 100644
index 0000000000..64b294d76e
--- /dev/null
+++ b/target/image/generic/Makefile
@@ -0,0 +1,12 @@
+#
+# 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)/image.mk
+
+# use default targets for everything
+
+$(eval $(call BuildImage))
diff --git a/target/image/generic/lzma-loader/Makefile b/target/image/generic/lzma-loader/Makefile
new file mode 100644
index 0000000000..5bd01eefb6
--- /dev/null
+++ b/target/image/generic/lzma-loader/Makefile
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 1823 2005-09-01 20:07:42Z nbd $
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME := loader
+PKG_VERSION := 0.05
+
+PKG_BUILD_DIR := $(KDIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+$(PKG_BUILD_DIR)/.prepared:
+ mkdir $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+ touch $@
+
+$(PKG_BUILD_DIR)/lzma.elf: $(PKG_BUILD_DIR)/.prepared $(PKG_BUILD_DIR)/vmlinux.lzma
+ PATH="$(TARGET_PATH)" $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" CROSS_COMPILE="$(TARGET_CROSS)" \
+ RAMSIZE=$(RAMSIZE) \
+ LOADADDR=$(LOADADDR) \
+ KERNEL_ENTRY=$(KERNEL_ENTRY) \
+ IMAGE_COPY=$(IMAGE_COPY)
+
+
+$(PKG_BUILD_DIR)/vmlinux.lzma: $(KDIR)/vmlinux.lzma
+ $(CP) $< $@
+
+$(KDIR)/loader.elf: $(PKG_BUILD_DIR)/lzma.elf
+ $(CP) $< $@
+
+download:
+prepare: $(PKG_BUILD_DIR)/.prepared
+compile: $(KDIR)/loader.elf
+install:
+
+clean:
+ rm -rf $(PKG_BUILD_DIR)
+ rm -f $(KDIR)/loader.elf
diff --git a/target/image/generic/lzma-loader/src/LzmaDecode.c b/target/image/generic/lzma-loader/src/LzmaDecode.c
new file mode 100644
index 0000000000..c90a0d3ef4
--- /dev/null
+++ b/target/image/generic/lzma-loader/src/LzmaDecode.c
@@ -0,0 +1,590 @@
+/*
+ LzmaDecode.c
+ LZMA Decoder (optimized for Speed version)
+
+ LZMA SDK 4.22 Copyright (c) 1999-2005 Igor Pavlov (2005-06-10)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this Code, expressly permits you to
+ statically or dynamically link your Code (or bind by name) to the
+ interfaces of this file without subjecting your linked Code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#ifndef Byte
+#define Byte unsigned char
+#endif
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_READ_BYTE (*Buffer++)
+
+#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
+ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
+
+#ifdef _LZMA_IN_CB
+
+#define RC_TEST { if (Buffer == BufferLim) \
+ { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
+ BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
+
+#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
+
+#else
+
+#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
+
+#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
+
+#endif
+
+#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+
+#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
+ { UpdateBit0(p); mi <<= 1; A0; } else \
+ { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
+
+#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
+
+#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
+ { int i = numLevels; res = 1; \
+ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
+ res -= (1 << numLevels); }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+#if 0
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+ unsigned char prop0;
+ if (size < LZMA_PROPERTIES_SIZE)
+ return LZMA_RESULT_DATA_ERROR;
+ prop0 = propsData[0];
+ if (prop0 >= (9 * 5 * 5))
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+ propsRes->lc = prop0;
+ /*
+ unsigned char remainder = (unsigned char)(prop0 / 9);
+ propsRes->lc = prop0 % 9;
+ propsRes->pb = remainder / 5;
+ propsRes->lp = remainder % 5;
+ */
+ }
+
+ #ifdef _LZMA_OUT_READ
+ {
+ int i;
+ propsRes->DictionarySize = 0;
+ for (i = 0; i < 4; i++)
+ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+ if (propsRes->DictionarySize == 0)
+ propsRes->DictionarySize = 1;
+ }
+ #endif
+ return LZMA_RESULT_OK;
+}
+#endif
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
+{
+ CProb *p = vs->Probs;
+ SizeT nowPos = 0;
+ Byte previousByte = 0;
+ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+ int lc = vs->Properties.lc;
+
+ #ifdef _LZMA_OUT_READ
+
+ UInt32 Range = vs->Range;
+ UInt32 Code = vs->Code;
+ #ifdef _LZMA_IN_CB
+ const Byte *Buffer = vs->Buffer;
+ const Byte *BufferLim = vs->BufferLim;
+ #else
+ const Byte *Buffer = inStream;
+ const Byte *BufferLim = inStream + inSize;
+ #endif
+ int state = vs->State;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+ UInt32 distanceLimit = vs->DistanceLimit;
+
+ Byte *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->Properties.DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ Byte tempDictionary[4];
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+ if (len == kLzmaStreamWasFinishedId)
+ return LZMA_RESULT_OK;
+
+ if (dictionarySize == 0)
+ {
+ dictionary = tempDictionary;
+ dictionarySize = 1;
+ tempDictionary[0] = vs->TempDictionary[0];
+ }
+
+ if (len == kLzmaNeedInitId)
+ {
+ {
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ UInt32 i;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ rep0 = rep1 = rep2 = rep3 = 1;
+ state = 0;
+ globalPos = 0;
+ distanceLimit = 0;
+ dictionaryPos = 0;
+ dictionary[dictionarySize - 1] = 0;
+ #ifdef _LZMA_IN_CB
+ RC_INIT;
+ #else
+ RC_INIT(inStream, inSize);
+ #endif
+ }
+ len = 0;
+ }
+ while(len != 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+
+ #else /* if !_LZMA_OUT_READ */
+
+ int state = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ int len = 0;
+ const Byte *Buffer;
+ const Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+
+ {
+ UInt32 i;
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ }
+
+ #ifdef _LZMA_IN_CB
+ RC_INIT;
+ #else
+ RC_INIT(inStream, inSize);
+ #endif
+
+ #endif /* _LZMA_OUT_READ */
+
+ while(nowPos < outSize)
+ {
+ CProb *prob;
+ UInt32 bound;
+ int posState = (int)(
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & posStateMask);
+
+ prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ int symbol = 1;
+ UpdateBit0(prob)
+ prob = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state >= kNumLitStates)
+ {
+ int matchByte;
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ #else
+ matchByte = outStream[nowPos - rep0];
+ #endif
+ do
+ {
+ int bit;
+ CProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & 0x100);
+ probLit = prob + 0x100 + bit + symbol;
+ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
+ }
+ while (symbol < 0x100);
+ }
+ while (symbol < 0x100)
+ {
+ CProb *probLit = prob + symbol;
+ RC_GET_BIT(probLit, symbol)
+ }
+ previousByte = (Byte)symbol;
+
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #endif
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRep + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < kNumLitStates ? 0 : 3;
+ prob = p + LenCoder;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG0 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos;
+ #endif
+ UpdateBit0(prob);
+
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit == 0)
+ #else
+ if (nowPos == 0)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ state = state < kNumLitStates ? 9 : 11;
+ #ifdef _LZMA_OUT_READ
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+ #endif
+
+ continue;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ UpdateBit1(prob);
+ prob = p + IsRepG1 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep1;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG2 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep2;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ state = state < kNumLitStates ? 8 : 11;
+ prob = p + RepLenCoder;
+ }
+ {
+ int numBits, offset;
+ CProb *probLen = prob + LenChoice;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ numBits = kLenNumLowBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenChoice2;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ numBits = kLenNumMidBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ numBits = kLenNumHighBits;
+ }
+ }
+ RangeDecoderBitTreeDecode(probLen, numBits, len);
+ len += offset;
+ }
+
+ if (state < 4)
+ {
+ int posSlot;
+ state += kNumLitStates;
+ prob = p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits);
+ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = (2 | ((UInt32)posSlot & 1));
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 <<= numDirectBits;
+ prob = p + SpecPos + rep0 - posSlot - 1;
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ RC_NORMALIZE
+ Range >>= 1;
+ rep0 <<= 1;
+ if (Code >= Range)
+ {
+ Code -= Range;
+ rep0 |= 1;
+ }
+ }
+ while (--numDirectBits != 0);
+ prob = p + Align;
+ rep0 <<= kNumAlignBits;
+ numDirectBits = kNumAlignBits;
+ }
+ {
+ int i = 1;
+ int mi = 1;
+ do
+ {
+ CProb *prob3 = prob + mi;
+ RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
+ i <<= 1;
+ }
+ while(--numDirectBits != 0);
+ }
+ }
+ else
+ rep0 = posSlot;
+ if (++rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = kLzmaStreamWasFinishedId;
+ break;
+ }
+ }
+
+ len += kMatchMinLen;
+ #ifdef _LZMA_OUT_READ
+ if (rep0 > distanceLimit)
+ #else
+ if (rep0 > nowPos)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ #ifdef _LZMA_OUT_READ
+ if (dictionarySize - distanceLimit > (UInt32)len)
+ distanceLimit += len;
+ else
+ distanceLimit = dictionarySize;
+ #endif
+
+ do
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ len--;
+ outStream[nowPos++] = previousByte;
+ }
+ while(len != 0 && nowPos < outSize);
+ }
+ }
+ RC_NORMALIZE;
+
+ #ifdef _LZMA_OUT_READ
+ vs->Range = Range;
+ vs->Code = Code;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = globalPos + (UInt32)nowPos;
+ vs->DistanceLimit = distanceLimit;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->RemainLen = len;
+ vs->TempDictionary[0] = tempDictionary[0];
+ #endif
+
+ #ifdef _LZMA_IN_CB
+ vs->Buffer = Buffer;
+ vs->BufferLim = BufferLim;
+ #else
+ *inSizeProcessed = (SizeT)(Buffer - inStream);
+ #endif
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
diff --git a/target/image/generic/lzma-loader/src/LzmaDecode.h b/target/image/generic/lzma-loader/src/LzmaDecode.h
new file mode 100644
index 0000000000..213062af12
--- /dev/null
+++ b/target/image/generic/lzma-loader/src/LzmaDecode.h
@@ -0,0 +1,131 @@
+/*
+ LzmaDecode.h
+ LZMA Decoder interface
+
+ LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMADECODE_H
+#define __LZMADECODE_H
+
+/* #define _LZMA_IN_CB */
+/* Use callback for input data */
+
+/* #define _LZMA_OUT_READ */
+/* Use read function for output data */
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case */
+
+/* #define _LZMA_LOC_OPT */
+/* Enable local speed optimizations inside code */
+
+/* #define _LZMA_SYSTEM_SIZE_T */
+/* Use system's size_t. You can use it to enable 64-bit sizes supporting*/
+
+#ifndef UInt32
+#ifdef _LZMA_UINT32_IS_ULONG
+#define UInt32 unsigned long
+#else
+#define UInt32 unsigned int
+#endif
+#endif
+
+#ifndef SizeT
+#ifdef _LZMA_SYSTEM_SIZE_T
+#include <stddef.h>
+#define SizeT size_t
+#else
+#define SizeT UInt32
+#endif
+#endif
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb unsigned short
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+#ifdef _LZMA_IN_CB
+typedef struct _ILzmaInCallback
+{
+ int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
+} ILzmaInCallback;
+#endif
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_PROPERTIES_SIZE 5
+
+typedef struct _CLzmaProperties
+{
+ int lc;
+ int lp;
+ int pb;
+ #ifdef _LZMA_OUT_READ
+ UInt32 DictionarySize;
+ #endif
+}CLzmaProperties;
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
+
+#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
+
+#define kLzmaNeedInitId (-2)
+
+typedef struct _CLzmaDecoderState
+{
+ CLzmaProperties Properties;
+ CProb *Probs;
+
+ #ifdef _LZMA_IN_CB
+ const unsigned char *Buffer;
+ const unsigned char *BufferLim;
+ #endif
+
+ #ifdef _LZMA_OUT_READ
+ unsigned char *Dictionary;
+ UInt32 Range;
+ UInt32 Code;
+ UInt32 DictionaryPos;
+ UInt32 GlobalPos;
+ UInt32 DistanceLimit;
+ UInt32 Reps[4];
+ int State;
+ int RemainLen;
+ unsigned char TempDictionary[4];
+ #endif
+} CLzmaDecoderState;
+
+#ifdef _LZMA_OUT_READ
+#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
+#endif
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
+
+#endif
diff --git a/target/image/generic/lzma-loader/src/Makefile b/target/image/generic/lzma-loader/src/Makefile
new file mode 100644
index 0000000000..d4a100df4b
--- /dev/null
+++ b/target/image/generic/lzma-loader/src/Makefile
@@ -0,0 +1,63 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+LOADADDR = 0x80400000 # RAM start + 4M
+KERNEL_ENTRY = 0x80001000
+RAMSIZE = 0x00100000 # 1MB
+IMAGE_COPY:=0
+
+CROSS_COMPILE = mips-linux-
+
+OBJCOPY:= $(CROSS_COMPILE)objcopy -O binary -R .reginfo -R .note -R .comment -R .mdebug -S
+CFLAGS := -fno-builtin -Os -G 0 -ffunction-sections -mno-abicalls -fno-pic -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap -Wall -DRAMSIZE=${RAMSIZE} -DKERNEL_ENTRY=${KERNEL_ENTRY} -D_LZMA_IN_CB
+ifeq ($(IMAGE_COPY),1)
+CFLAGS += -DLOADADDR=${LOADADDR} -DIMAGE_COPY=1
+endif
+
+.S.s:
+ $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+ $(CC) $(CFLAGS) -c $< -o $*.o
+.c.o:
+ $(CC) $(CFLAGS) -c $< -o $*.o
+
+CC = $(CROSS_COMPILE)gcc
+LD = $(CROSS_COMPILE)ld
+OBJDUMP = $(CROSS_COMPILE)objdump
+
+O_FORMAT = $(shell $(OBJDUMP) -i | head -2 | grep elf32)
+
+# Drop some uninteresting sections in the kernel.
+# This is only relevant for ELF kernels but doesn't hurt a.out
+drop-sections = .reginfo .mdebug .comment
+strip-flags = $(addprefix --remove-section=,$(drop-sections))
+
+all : lzma.elf
+
+lzma.lds: lzma.lds.in
+ sed -e 's,@LOADADDR@,$(LOADADDR),g' -e 's,@ENTRY@,_start,g' $< >$@
+
+kernel.o: vmlinux.lzma lzma.lds
+ $(LD) -r -b binary --oformat $(O_FORMAT) -o $@ $<
+
+ifeq ($(IMAGE_COPY),1)
+lzma.o: decompress.o LzmaDecode.o kernel.o
+ sed -e 's,@LOADADDR@,$(LOADADDR),g' -e 's,@ENTRY@,entry,g' lzma.lds.in >lzma-stage2.lds
+ $(LD) -static --no-warn-mismatch -e entry -Tlzma-stage2.lds -o temp-$@ $^
+ $(OBJCOPY) temp-$@ lzma.tmp
+ @echo "SECTIONS { .data : { code_start = .; *(.data) code_stop = .; }}" > lzma-data.lds
+ $(LD) -no-warn-mismatch -T lzma-data.lds -r -o $@ -b binary lzma.tmp --oformat $(O_FORMAT)
+
+lzma.elf: start.o lzma.o
+ sed -e 's,@LOADADDR@,$(KERNEL_ENTRY),g' lzma-copy.lds.in >lzma-copy.lds
+ $(LD) -s -Tlzma-copy.lds -o $@ $^
+else
+lzma.elf: start.o decompress.o LzmaDecode.o kernel.o
+ $(LD) -s -Tlzma.lds -o $@ $^
+endif
+
+clean:
+ rm -f *.o lzma.elf *.tmp *.lds
diff --git a/target/image/generic/lzma-loader/src/decompress.c b/target/image/generic/lzma-loader/src/decompress.c
new file mode 100644
index 0000000000..4ed432d1a5
--- /dev/null
+++ b/target/image/generic/lzma-loader/src/decompress.c
@@ -0,0 +1,154 @@
+/*
+ * LZMA compressed kernel decompressor for bcm947xx boards
+ *
+ * Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
+ *
+ * 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
+ *
+ *
+ * Please note, this was code based on the bunzip2 decompressor code
+ * by Manuel Novoa III (mjn3@codepoet.org), although the only thing left
+ * is an idea and part of original vendor code
+ *
+ *
+ * 12-Mar-2005 Mineharu Takahara <mtakahar@yahoo.com>
+ * pass actual output size to decoder (stream mode
+ * compressed input is not a requirement anymore)
+ *
+ * 24-Apr-2005 Oleg I. Vdovikin
+ * reordered functions using lds script, removed forward decl
+ *
+ * ??-Nov-2005 Mike Baker
+ * reorder the script as an lzma wrapper; do not depend on flash access
+ */
+
+#include "LzmaDecode.h"
+
+#define KSEG0 0x80000000
+#define KSEG1 0xa0000000
+
+#define KSEG1ADDR(a) ((((unsigned)(a)) & 0x1fffffffU) | KSEG1)
+
+#define Index_Invalidate_I 0x00
+#define Index_Writeback_Inv_D 0x01
+
+#define cache_unroll(base,op) \
+ __asm__ __volatile__( \
+ ".set noreorder;\n" \
+ ".set mips3;\n" \
+ "cache %1, (%0);\n" \
+ ".set mips0;\n" \
+ ".set reorder\n" \
+ : \
+ : "r" (base), \
+ "i" (op));
+
+
+static __inline__ void blast_icache(unsigned long size, unsigned long lsize)
+{
+ unsigned long start = KSEG0;
+ unsigned long end = (start + size);
+
+ while(start < end) {
+ cache_unroll(start,Index_Invalidate_I);
+ start += lsize;
+ }
+}
+
+static __inline__ void blast_dcache(unsigned long size, unsigned long lsize)
+{
+ unsigned long start = KSEG0;
+ unsigned long end = (start + size);
+
+ while(start < end) {
+ cache_unroll(start,Index_Writeback_Inv_D);
+ start += lsize;
+ }
+}
+
+unsigned char *data;
+
+static int read_byte(void *object, unsigned char **buffer, UInt32 *bufferSize)
+{
+ *bufferSize = 1;
+ *buffer = data;
+ ++data;
+ return LZMA_RESULT_OK;
+}
+
+static __inline__ unsigned char get_byte(void)
+{
+ unsigned char *buffer;
+ UInt32 fake;
+
+ return read_byte(0, &buffer, &fake), *buffer;
+}
+
+static char *buffer = (char *)0x80C00000;
+extern char lzma_start[];
+extern char lzma_end[];
+
+/* should be the first function */
+void entry(unsigned long icache_size, unsigned long icache_lsize,
+ unsigned long dcache_size, unsigned long dcache_lsize)
+{
+ unsigned int i; /* temp value */
+ unsigned int osize; /* uncompressed size */
+ volatile unsigned int arg0, arg1, arg2, arg3;
+
+ /* restore argument registers */
+ __asm__ __volatile__ ("ori %0, $12, 0":"=r"(arg0));
+ __asm__ __volatile__ ("ori %0, $13, 0":"=r"(arg1));
+ __asm__ __volatile__ ("ori %0, $14, 0":"=r"(arg2));
+ __asm__ __volatile__ ("ori %0, $15, 0":"=r"(arg3));
+
+ ILzmaInCallback callback;
+ CLzmaDecoderState vs;
+ callback.Read = read_byte;
+
+ data = lzma_start;
+
+ /* lzma args */
+ i = get_byte();
+ vs.Properties.lc = i % 9, i = i / 9;
+ vs.Properties.lp = i % 5, vs.Properties.pb = i / 5;
+
+ vs.Probs = (CProb *)buffer;
+
+ /* skip rest of the LZMA coder property */
+ for (i = 0; i < 4; i++)
+ get_byte();
+
+ /* read the lower half of uncompressed size in the header */
+ osize = ((unsigned int)get_byte()) +
+ ((unsigned int)get_byte() << 8) +
+ ((unsigned int)get_byte() << 16) +
+ ((unsigned int)get_byte() << 24);
+
+ /* skip rest of the header (upper half of uncompressed size) */
+ for (i = 0; i < 4; i++)
+ get_byte();
+
+ /* decompress kernel */
+ if ((i = LzmaDecode(&vs, &callback,
+ (unsigned char*)KERNEL_ENTRY, osize, &osize)) == LZMA_RESULT_OK)
+ {
+ blast_dcache(dcache_size, dcache_lsize);
+ blast_icache(icache_size, icache_lsize);
+
+ /* Jump to load address */
+ ((void (*)(int a0, int a1, int a2, int a3)) KERNEL_ENTRY)(arg0, arg1, arg2, arg3);
+ }
+}
diff --git a/target/image/generic/lzma-loader/src/lzma-copy.lds.in b/target/image/generic/lzma-loader/src/lzma-copy.lds.in
new file mode 100644
index 0000000000..fbc87ab8e2
--- /dev/null
+++ b/target/image/generic/lzma-loader/src/lzma-copy.lds.in
@@ -0,0 +1,20 @@
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = @LOADADDR@;
+ .text :
+ {
+ _ftext = . ;
+ *(.text)
+ *(.rodata)
+ } =0
+
+ .reginfo : { *(.reginfo) }
+
+ .bss :
+ {
+ *(.bss)
+ }
+}
diff --git a/target/image/generic/lzma-loader/src/lzma.lds.in b/target/image/generic/lzma-loader/src/lzma.lds.in
new file mode 100644
index 0000000000..6021cec014
--- /dev/null
+++ b/target/image/generic/lzma-loader/src/lzma.lds.in
@@ -0,0 +1,24 @@
+OUTPUT_ARCH(mips)
+ENTRY(@ENTRY@)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = @LOADADDR@;
+ .text :
+ {
+ _ftext = . ;
+ *(.text.entry)
+ *(.text)
+ *(.rodata)
+ lzma_start = .;
+ kernel.o
+ lzma_end = .;
+ } =0
+
+ .reginfo : { *(.reginfo) }
+
+ .bss :
+ {
+ *(.bss)
+ }
+}
diff --git a/target/image/generic/lzma-loader/src/print.c b/target/image/generic/lzma-loader/src/print.c
new file mode 100644
index 0000000000..950687beff
--- /dev/null
+++ b/target/image/generic/lzma-loader/src/print.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.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.
+ *
+ */
+
+#include "print.h"
+
+/* macros */
+#define IsDigit(x) ( ((x) >= '0') && ((x) <= '9') )
+#define Ctod(x) ( (x) - '0')
+
+/* forward declaration */
+extern int PrintChar(char *, char, int, int);
+extern int PrintString(char *, char *, int, int);
+extern int PrintNum(char *, unsigned long, int, int, int, int, char, int);
+
+/* private variable */
+static const char theFatalMsg[] = "fatal error in lp_Print!";
+
+/* -*-
+ * A low level printf() function.
+ */
+void
+lp_Print(void (*output)(void *, char *, int),
+ void * arg,
+ char *fmt,
+ va_list ap)
+{
+
+#define OUTPUT(arg, s, l) \
+ { if (((l) < 0) || ((l) > LP_MAX_BUF)) { \
+ (*output)(arg, (char*)theFatalMsg, sizeof(theFatalMsg)-1); for(;;); \
+ } else { \
+ (*output)(arg, s, l); \
+ } \
+ }
+
+ char buf[LP_MAX_BUF];
+
+ char c;
+ char *s;
+ long int num;
+
+ int longFlag;
+ int negFlag;
+ int width;
+ int prec;
+ int ladjust;
+ char padc;
+
+ int length;
+
+ for(;;) {
+ {
+ /* scan for the next '%' */
+ char *fmtStart = fmt;
+ while ( (*fmt != '\0') && (*fmt != '%')) {
+ fmt ++;
+ }
+
+ /* flush the string found so far */
+ OUTPUT(arg, fmtStart, fmt-fmtStart);
+
+ /* are we hitting the end? */
+ if (*fmt == '\0') break;
+ }
+
+ /* we found a '%' */
+ fmt ++;
+
+ /* check for long */
+ if (*fmt == 'l') {
+ longFlag = 1;
+ fmt ++;
+ } else {
+ longFlag = 0;
+ }
+
+ /* check for other prefixes */
+ width = 0;
+ prec = -1;
+ ladjust = 0;
+ padc = ' ';
+
+ if (*fmt == '-') {
+ ladjust = 1;
+ fmt ++;
+ }
+
+ if (*fmt == '0') {
+ padc = '0';
+ fmt++;
+ }
+
+ if (IsDigit(*fmt)) {
+ while (IsDigit(*fmt)) {
+ width = 10 * width + Ctod(*fmt++);
+ }
+ }
+
+ if (*fmt == '.') {
+ fmt ++;
+ if (IsDigit(*fmt)) {
+ prec = 0;
+ while (IsDigit(*fmt)) {
+ prec = prec*10 + Ctod(*fmt++);
+ }
+ }
+ }
+
+
+ /* check format flag */
+ negFlag = 0;
+ switch (*fmt) {
+ case 'b':
+ if (longFlag) {
+ num = va_arg(ap, long int);
+ } else {
+ num = va_arg(ap, int);
+ }
+ length = PrintNum(buf, num, 2, 0, width, ladjust, padc, 0);
+ OUTPUT(arg, buf, length);
+ break;
+
+ case 'd':
+ case 'D':
+ if (longFlag) {
+ num = va_arg(ap, long int);
+ } else {
+ num = va_arg(ap, int);
+ }
+ if (num < 0) {
+ num = - num;
+ negFlag = 1;
+ }
+ length = PrintNum(buf, num, 10, negFlag, width, ladjust, padc, 0);
+ OUTPUT(arg, buf, length);
+ break;
+
+ case 'o':
+ case 'O':
+ if (longFlag) {
+ num = va_arg(ap, long int);
+ } else {
+ num = va_arg(ap, int);
+ }
+ length = PrintNum(buf, num, 8, 0, width, ladjust, padc, 0);
+ OUTPUT(arg, buf, length);
+ break;
+
+ case 'u':
+ case 'U':
+ if (longFlag) {
+ num = va_arg(ap, long int);
+ } else {
+ num = va_arg(ap, int);
+ }
+ length = PrintNum(buf, num, 10, 0, width, ladjust, padc, 0);
+ OUTPUT(arg, buf, length);
+ break;
+
+ case 'x':
+ if (longFlag) {
+ num = va_arg(ap, long int);
+ } else {
+ num = va_arg(ap, int);
+ }
+ length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 0);
+ OUTPUT(arg, buf, length);
+ break;
+
+ case 'X':
+ if (longFlag) {
+ num = va_arg(ap, long int);
+ } else {
+ num = va_arg(ap, int);
+ }
+ length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 1);
+ OUTPUT(arg, buf, length);
+ break;
+
+ case 'c':
+ c = (char)va_arg(ap, int);
+ length = PrintChar(buf, c, width, ladjust);
+ OUTPUT(arg, buf, length);
+ break;
+
+ case 's':
+ s = (char*)va_arg(ap, char *);
+ length = PrintString(buf, s, width, ladjust);
+ OUTPUT(arg, buf, length);
+ break;
+
+ case '\0':
+ fmt --;
+ break;
+
+ default:
+ /* output this char as it is */
+ OUTPUT(arg, fmt, 1);
+ } /* switch (*fmt) */
+
+ fmt ++;
+ } /* for(;;) */
+
+ /* special termination call */
+ OUTPUT(arg, "\0", 1);
+}
+
+
+/* --------------- local help functions --------------------- */
+int
+PrintChar(char * buf, char c, int length, int ladjust)
+{
+ int i;
+
+ if (length < 1) length = 1;
+ if (ladjust) {
+ *buf = c;
+ for (i=1; i< length; i++) buf[i] = ' ';
+ } else {
+ for (i=0; i< length-1; i++) buf[i] = ' ';
+ buf[length - 1] = c;
+ }
+ return length;
+}
+
+int
+PrintString(char * buf, char* s, int length, int ladjust)
+{
+ int i;
+ int len=0;
+ char* s1 = s;
+ while (*s1++) len++;
+ if (length < len) length = len;
+
+ if (ladjust) {
+ for (i=0; i< len; i++) buf[i] = s[i];
+ for (i=len; i< length; i++) buf[i] = ' ';
+ } else {
+ for (i=0; i< length-len; i++) buf[i] = ' ';
+ for (i=length-len; i < length; i++) buf[i] = s[i-length+len];
+ }
+ return length;
+}
+
+int
+PrintNum(char * buf, unsigned long u, int base, int negFlag,
+ int length, int ladjust, char padc, int upcase)
+{
+ /* algorithm :
+ * 1. prints the number from left to right in reverse form.
+ * 2. fill the remaining spaces with padc if length is longer than
+ * the actual length
+ * TRICKY : if left adjusted, no "0" padding.
+ * if negtive, insert "0" padding between "0" and number.
+ * 3. if (!ladjust) we reverse the whole string including paddings
+ * 4. otherwise we only reverse the actual string representing the num.
+ */
+
+ int actualLength =0;
+ char *p = buf;
+ int i;
+
+ do {
+ int tmp = u %base;
+ if (tmp <= 9) {
+ *p++ = '0' + tmp;
+ } else if (upcase) {
+ *p++ = 'A' + tmp - 10;
+ } else {
+ *p++ = 'a' + tmp - 10;
+ }
+ u /= base;
+ } while (u != 0);
+
+ if (negFlag) {
+ *p++ = '-';
+ }
+
+ /* figure out actual length and adjust the maximum length */
+ actualLength = p - buf;
+ if (length < actualLength) length = actualLength;
+
+ /* add padding */
+ if (ladjust) {
+ padc = ' ';
+ }
+ if (negFlag && !ladjust && (padc == '0')) {
+ for (i = actualLength-1; i< length-1; i++) buf[i] = padc;
+ buf[length -1] = '-';
+ } else {
+ for (i = actualLength; i< length; i++) buf[i] = padc;
+ }
+
+
+ /* prepare to reverse the string */
+ {
+ int begin = 0;
+ int end;
+ if (ladjust) {
+ end = actualLength - 1;
+ } else {
+ end = length -1;
+ }
+
+ while (end > begin) {
+ char tmp = buf[begin];
+ buf[begin] = buf[end];
+ buf[end] = tmp;
+ begin ++;
+ end --;
+ }
+ }
+
+ /* adjust the string pointer */
+ return length;
+}
diff --git a/target/image/generic/lzma-loader/src/print.h b/target/image/generic/lzma-loader/src/print.h
new file mode 100644
index 0000000000..b051463909
--- /dev/null
+++ b/target/image/generic/lzma-loader/src/print.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.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.
+ *
+ */
+
+#ifndef _print_h_
+#define _print_h_
+
+#include <stdarg.h>
+
+/* this is the maximum width for a variable */
+#define LP_MAX_BUF 80
+
+/* -*-
+ * output function takes an void pointer which is passed in as the
+ * second argument in lp_Print(). This black-box argument gives output
+ * function a way to track state.
+ *
+ * The second argument in output function is a pointer to char buffer.
+ * The third argument specifies the number of chars to outputed.
+ *
+ * output function cannot assume the buffer is null-terminated after
+ * l number of chars.
+ */
+void lp_Print(void (*output)(void *, char *, int),
+ void * arg,
+ char *fmt,
+ va_list ap);
+
+#endif
diff --git a/target/image/generic/lzma-loader/src/printf.c b/target/image/generic/lzma-loader/src/printf.c
new file mode 100644
index 0000000000..49bd50d7c7
--- /dev/null
+++ b/target/image/generic/lzma-loader/src/printf.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.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.
+ *
+ */
+
+#include "printf.h"
+#include "print.h"
+#include "uart16550.h"
+
+static void myoutput(void *arg, char *s, int l)
+{
+ int i;
+
+ // special termination call
+ if ((l==1) && (s[0] == '\0')) return;
+
+ for (i=0; i< l; i++) {
+ Uart16550Put(s[i]);
+ if (s[i] == '\n') Uart16550Put('\r');
+ }
+}
+
+void printf(char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ lp_Print(myoutput, 0, fmt, ap);
+ va_end(ap);
+}
diff --git a/target/image/generic/lzma-loader/src/printf.h b/target/image/generic/lzma-loader/src/printf.h
new file mode 100644
index 0000000000..9b1c1df232
--- /dev/null
+++ b/target/image/generic/lzma-loader/src/printf.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.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.
+ *
+ */
+
+#ifndef _printf_h_
+#define _printf_h_
+
+#include <stdarg.h>
+void printf(char *fmt, ...);
+
+#endif /* _printf_h_ */
diff --git a/target/image/generic/lzma-loader/src/start.S b/target/image/generic/lzma-loader/src/start.S
new file mode 100644
index 0000000000..9a85c4c357
--- /dev/null
+++ b/target/image/generic/lzma-loader/src/start.S
@@ -0,0 +1,160 @@
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+#define KSEG0 0x80000000
+
+#define C0_CONFIG $16
+#define C0_TAGLO $28
+#define C0_TAGHI $29
+
+#define CONF1_DA_SHIFT 7 /* D$ associativity */
+#define CONF1_DA_MASK 0x00000380
+#define CONF1_DA_BASE 1
+#define CONF1_DL_SHIFT 10 /* D$ line size */
+#define CONF1_DL_MASK 0x00001c00
+#define CONF1_DL_BASE 2
+#define CONF1_DS_SHIFT 13 /* D$ sets/way */
+#define CONF1_DS_MASK 0x0000e000
+#define CONF1_DS_BASE 64
+#define CONF1_IA_SHIFT 16 /* I$ associativity */
+#define CONF1_IA_MASK 0x00070000
+#define CONF1_IA_BASE 1
+#define CONF1_IL_SHIFT 19 /* I$ line size */
+#define CONF1_IL_MASK 0x00380000
+#define CONF1_IL_BASE 2
+#define CONF1_IS_SHIFT 22 /* Instruction cache sets/way */
+#define CONF1_IS_MASK 0x01c00000
+#define CONF1_IS_BASE 64
+
+#define Index_Invalidate_I 0x00
+#define Index_Writeback_Inv_D 0x01
+
+LEAF(_start)
+
+ .set mips32
+ .set noreorder
+
+ /* save argument registers */
+ move t4, a0
+ move t5, a1
+ move t6, a2
+ move t7, a3
+
+ /* set up stack */
+ li sp, 0xa0000000 + RAMSIZE - 16
+
+#ifdef IMAGE_COPY
+ /* Copy decompressor code to the right place */
+ li t2, LOADADDR
+ add a0, t2, 0
+ la a1, code_start
+ la a2, code_stop
+$L1:
+ lw t0, 0(a1)
+ sw t0, 0(a0)
+ add a1, 4
+ add a0, 4
+ blt a1, a2, $L1
+ nop
+#endif
+
+ /* At this point we need to invalidate dcache and */
+ /* icache before jumping to new code */
+
+1: /* Get cache sizes */
+ mfc0 s0,C0_CONFIG,1
+
+ li s1,CONF1_DL_MASK
+ and s1,s0
+ beq s1,zero,nodc
+ nop
+
+ srl s1,CONF1_DL_SHIFT
+ li t0,CONF1_DL_BASE
+ sll s1,t0,s1 /* s1 has D$ cache line size */
+
+ li s2,CONF1_DA_MASK
+ and s2,s0
+ srl s2,CONF1_DA_SHIFT
+ addiu s2,CONF1_DA_BASE /* s2 now has D$ associativity */
+
+ li t0,CONF1_DS_MASK
+ and t0,s0
+ srl t0,CONF1_DS_SHIFT
+ li s3,CONF1_DS_BASE
+ sll s3,s3,t0 /* s3 has D$ sets per way */
+
+ multu s2,s3 /* sets/way * associativity */
+ mflo t0 /* total cache lines */
+
+ multu s1,t0 /* D$ linesize * lines */
+ mflo s2 /* s2 is now D$ size in bytes */
+
+ /* Initilize the D$: */
+ mtc0 zero,C0_TAGLO
+ mtc0 zero,C0_TAGHI
+
+ li t0,KSEG0 /* Just an address for the first $ line */
+ addu t1,t0,s2 /* + size of cache == end */
+
+1: cache Index_Writeback_Inv_D,0(t0)
+ bne t0,t1,1b
+ addu t0,s1
+
+nodc:
+ /* Now we get to do it all again for the I$ */
+
+ move s3,zero /* just in case there is no icache */
+ move s4,zero
+
+ li t0,CONF1_IL_MASK
+ and t0,s0
+ beq t0,zero,noic
+ nop
+
+ srl t0,CONF1_IL_SHIFT
+ li s3,CONF1_IL_BASE
+ sll s3,t0 /* s3 has I$ cache line size */
+
+ li t0,CONF1_IA_MASK
+ and t0,s0
+ srl t0,CONF1_IA_SHIFT
+ addiu s4,t0,CONF1_IA_BASE /* s4 now has I$ associativity */
+
+ li t0,CONF1_IS_MASK
+ and t0,s0
+ srl t0,CONF1_IS_SHIFT
+ li s5,CONF1_IS_BASE
+ sll s5,t0 /* s5 has I$ sets per way */
+
+ multu s4,s5 /* sets/way * associativity */
+ mflo t0 /* s4 is now total cache lines */
+
+ multu s3,t0 /* I$ linesize * lines */
+ mflo s4 /* s4 is cache size in bytes */
+
+ /* Initilize the I$: */
+ mtc0 zero,C0_TAGLO
+ mtc0 zero,C0_TAGHI
+
+ li t0,KSEG0 /* Just an address for the first $ line */
+ addu t1,t0,s4 /* + size of cache == end */
+
+1: cache Index_Invalidate_I,0(t0)
+ bne t0,t1,1b
+ addu t0,s3
+noic:
+ /* jump to main */
+ move a0,s3 /* icache line size */
+ move a1,s4 /* icache size */
+ move a2,s1 /* dcache line size */
+#ifdef IMAGE_COPY
+ jal t2
+#else
+ jal entry
+#endif
+ move a3,s2 /* dcache size */
+
+ .set reorder
+END(_start)
+
diff --git a/target/image/generic/lzma-loader/src/uart16550.c b/target/image/generic/lzma-loader/src/uart16550.c
new file mode 100644
index 0000000000..7df5727600
--- /dev/null
+++ b/target/image/generic/lzma-loader/src/uart16550.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.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.
+ *
+ */
+
+
+#include "uart16550.h"
+
+/* === CONFIG === */
+
+#define BASE 0xb8058000
+#define MAX_BAUD 1152000
+#define REG_OFFSET 4
+
+/* === END OF CONFIG === */
+
+/* register offset */
+#define OFS_RCV_BUFFER (0*REG_OFFSET)
+#define OFS_TRANS_HOLD (0*REG_OFFSET)
+#define OFS_SEND_BUFFER (0*REG_OFFSET)
+#define OFS_INTR_ENABLE (1*REG_OFFSET)
+#define OFS_INTR_ID (2*REG_OFFSET)
+#define OFS_DATA_FORMAT (3*REG_OFFSET)
+#define OFS_LINE_CONTROL (3*REG_OFFSET)
+#define OFS_MODEM_CONTROL (4*REG_OFFSET)
+#define OFS_RS232_OUTPUT (4*REG_OFFSET)
+#define OFS_LINE_STATUS (5*REG_OFFSET)
+#define OFS_MODEM_STATUS (6*REG_OFFSET)
+#define OFS_RS232_INPUT (6*REG_OFFSET)
+#define OFS_SCRATCH_PAD (7*REG_OFFSET)
+
+#define OFS_DIVISOR_LSB (0*REG_OFFSET)
+#define OFS_DIVISOR_MSB (1*REG_OFFSET)
+
+
+/* memory-mapped read/write of the port */
+#define UART16550_READ(y) (*((volatile uint32*)(BASE + y)))
+#define UART16550_WRITE(y, z) ((*((volatile uint32*)(BASE + y))) = z)
+
+#define DEBUG_LED (*(unsigned short*)0xb7ffffc0)
+#define OutputLED(x) (DEBUG_LED = x)
+
+void Uart16550Init(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+ /* disable interrupts */
+ UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+ /* set up buad rate */
+ {
+ uint32 divisor;
+
+ /* set DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+ /* set divisor */
+ divisor = MAX_BAUD / baud;
+ UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+ UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00)>>8);
+
+ /* clear DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+ }
+
+ /* set data format */
+ UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+uint8 Uart16550GetPoll()
+{
+ while((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
+ return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+
+void Uart16550Put(uint8 byte)
+{
+ while ((UART16550_READ(OFS_LINE_STATUS) &0x20) == 0);
+ UART16550_WRITE(OFS_SEND_BUFFER, byte);
+}
+
diff --git a/target/image/generic/lzma-loader/src/uart16550.h b/target/image/generic/lzma-loader/src/uart16550.h
new file mode 100644
index 0000000000..b3fd6fdd75
--- /dev/null
+++ b/target/image/generic/lzma-loader/src/uart16550.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.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.
+ *
+ */
+
+#ifndef _uart16550_h_
+#define _uart16550_h_
+
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+
+#define UART16550_BAUD_2400 2400
+#define UART16550_BAUD_4800 4800
+#define UART16550_BAUD_9600 9600
+#define UART16550_BAUD_19200 19200
+#define UART16550_BAUD_38400 38400
+#define UART16550_BAUD_57600 57600
+#define UART16550_BAUD_115200 115200
+
+#define UART16550_PARITY_NONE 0
+#define UART16550_PARITY_ODD 0x08
+#define UART16550_PARITY_EVEN 0x18
+#define UART16550_PARITY_MARK 0x28
+#define UART16550_PARITY_SPACE 0x38
+
+#define UART16550_DATA_5BIT 0x0
+#define UART16550_DATA_6BIT 0x1
+#define UART16550_DATA_7BIT 0x2
+#define UART16550_DATA_8BIT 0x3
+
+#define UART16550_STOP_1BIT 0x0
+#define UART16550_STOP_2BIT 0x4
+
+void Uart16550Init(uint32 baud, uint8 data, uint8 parity, uint8 stop);
+
+/* blocking call */
+uint8 Uart16550GetPoll();
+
+void Uart16550Put(uint8 byte);
+
+#endif
diff --git a/target/image/magicbox/Makefile b/target/image/magicbox/Makefile
new file mode 100644
index 0000000000..10f71df2a9
--- /dev/null
+++ b/target/image/magicbox/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
+include $(INCLUDE_DIR)/image.mk
+
+define Build/Clean
+endef
+
+define Image/Prepare
+endef
+
+define Image/BuildKernel
+ cp $(LINUX_DIR)/arch/ppc/boot/images/uImage $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-uImage
+endef
+
+define Image/Build
+ $(call Image/Build/$(1),$(1))
+endef
+
+define Image/Build/jffs2-64k
+ ( \
+ dd if=$(LINUX_DIR)/arch/ppc/boot/images/uImage bs=65536 conv=sync; \
+ dd if=$(KDIR)/root.$(1) bs=65536 conv=sync; \
+ ) > $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).img
+endef
+
+#define Image/Build/jffs2-128k
+# ( \
+# dd if=$(LINUX_DIR)/arch/ppc/boot/images/uImage bs=131072 conv=sync; \
+# dd if=$(KDIR)/root.$(1) bs=131072 conv=sync; \
+# ) > $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).img
+#endef
+
+$(eval $(call BuildImage))
diff --git a/target/image/rb532/Makefile b/target/image/rb532/Makefile
new file mode 100644
index 0000000000..2a61a484dc
--- /dev/null
+++ b/target/image/rb532/Makefile
@@ -0,0 +1,57 @@
+#
+# 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)/image.mk
+
+LOADADDR = 0x81000000 # RAM start + 16M
+KERNEL_ENTRY = 0x80101000
+RAMSIZE = 0x00100000 # 1MB
+IMAGE_COPY = 1
+
+LOADER_MAKEOPTS= \
+ KDIR=$(KDIR) \
+ LOADADDR=$(LOADADDR) \
+ KERNEL_ENTRY=$(KERNEL_ENTRY) \
+ RAMSIZE=$(RAMSIZE) \
+ IMAGE_COPY=$(IMAGE_COPY)
+
+define Build/Clean
+ $(MAKE) -C ../generic/lzma-loader $(LOADER_MAKEOPTS) clean
+endef
+
+define Image/Prepare
+ cat $(KDIR)/vmlinux | $(STAGING_DIR)/bin/lzma e -si -so -eos -lc1 -lp2 -pb2 > $(KDIR)/vmlinux.lzma
+ $(MAKE) -C ../generic/lzma-loader $(LOADER_MAKEOPTS) clean compile
+endef
+
+define Image/BuildKernel
+ $(CP) $(KDIR)/loader.elf $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-vmlinux
+endef
+
+PARTITION1=\x80\x01\x01\x00\x27\x01\x20\x7b\x20\x00\x00\x00\xe0\x1e\x00\x00# 4 MB (kernel part)
+PARTITION2=\x00\x00\x01\x7c\x83\x01\xa0\x64\x00\x1f\x00\x00\x40\x7a\x00\x00# 16 MB (rootfs part)
+
+define Image/Build/jffs2-128k
+ ( \
+ echo -ne OWRT | dd bs=$$$$((0x1be)) conv=sync; \
+ ( \
+ echo -ne '$(strip $(PARTITION1))'; \
+ echo -ne '$(strip $(PARTITION2))'; \
+ ) | dd bs=$$$$((0x40)) conv=sync; \
+ echo -ne '\x55\xaa'; \
+ dd if=/dev/zero bs=$$$$((0x3e00)) conv=sync count=1; \
+ dd if=$(KDIR)/loader.elf bs=$$$$((0x3dc000)) conv=sync; \
+ cat $(KDIR)/root.$(1); \
+ echo -ne '\xde\xad\xc0\xde'; \
+ ) > $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).bin
+endef
+
+define Image/Build
+ $(call Image/Build/$(1),$(1))
+endef
+
+$(eval $(call BuildImage))
diff --git a/target/image/uml/Makefile b/target/image/uml/Makefile
new file mode 100755
index 0000000000..6af4b8b816
--- /dev/null
+++ b/target/image/uml/Makefile
@@ -0,0 +1,15 @@
+#
+# 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)/image.mk
+
+define Image/Build
+ cp $(KDIR)/root.$(1) $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).img
+ cp $(LINUX_DIR)/linux $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-vmlinux
+endef
+
+$(eval $(call BuildImage))
diff --git a/target/image/x86/Config.in b/target/image/x86/Config.in
new file mode 100644
index 0000000000..fa61468c96
--- /dev/null
+++ b/target/image/x86/Config.in
@@ -0,0 +1,20 @@
+config X86_GRUB_IMAGES
+ bool "Build GRUB images (Linux x86 or x86_64 host only)"
+ depends LINUX_2_6_X86
+ depends TARGET_ROOTFS_EXT2FS || TARGET_ROOTFS_JFFS2
+ default y
+
+config X86_GRUB_BAUDRATE
+ int "Serial port baud rate"
+ depends X86_GRUB_IMAGES
+ default 38400
+
+config X86_GRUB_KERNELPART
+ int "Kernel partition size (in MB)"
+ depends X86_GRUB_IMAGES
+ default 4
+
+config X86_GRUB_FSPART
+ int "Filesystem partition size (in MB)"
+ depends X86_GRUB_IMAGES
+ default 16
diff --git a/target/image/x86/Makefile b/target/image/x86/Makefile
new file mode 100644
index 0000000000..b836f3ace6
--- /dev/null
+++ b/target/image/x86/Makefile
@@ -0,0 +1,54 @@
+#
+# 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)/image.mk
+
+ifeq ($(CONFIG_X86_GRUB_IMAGES),y)
+ define Build/Compile
+ $(MAKE) -C grub compile
+ endef
+
+ define Build/Clean
+ $(MAKE) -C grub clean
+ endef
+
+ define Image/cmdline/jffs2-64k
+ block2mtd.block2mtd=/dev/hda2,65536 root=/dev/mtdblock0 rootfstype=jffs2
+ endef
+
+ define Image/cmdline/jffs2-128k
+ block2mtd.block2mtd=/dev/hda2,131072 root=/dev/mtdblock0 rootfstype=jffs2
+ endef
+
+ define Image/cmdline/ext2
+ root=/dev/hda2 rootfstype=ext2
+ endef
+
+ define Image/Build/grub
+ mkdir -p $(KDIR)/root.grub/boot/grub
+ $(CP) \
+ $(STAGING_DIR)/usr/lib/grub/i386-pc/stage1 \
+ $(STAGING_DIR)/usr/lib/grub/i386-pc/stage2 \
+ $(STAGING_DIR)/usr/lib/grub/i386-pc/e2fs_stage1_5 \
+ $(KDIR)/root.grub/boot/grub/
+ $(CP) $(LINUX_DIR)/arch/i386/boot/bzImage $(KDIR)/root.grub/boot/vmlinuz
+ sed \
+ -e 's#@CMDLINE@#$(strip $(call Image/cmdline/$(1)))#g' \
+ -e 's#@BAUDRATE@#$(CONFIG_X86_GRUB_BAUDRATE)#g' \
+ ./grub/menu.lst > $(KDIR)/root.grub/boot/grub/menu.lst
+ PATH="$(STAGING_DIR)/usr/sbin:$(STAGING_DIR)/bin:$(PATH)" ./gen_image.sh $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).image $(CONFIG_X86_GRUB_KERNELPART) $(KDIR)/root.grub $(CONFIG_X86_GRUB_FSPART) $(KDIR)/root.$(1)
+ endef
+endif
+
+define Image/Build
+ $(call Image/Build/grub,$(1))
+ cp $(KDIR)/root.$(1) $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).fs
+ cp $(LINUX_DIR)/arch/i386/boot/bzImage $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-vmlinuz
+endef
+
+
+$(eval $(call BuildImage))
diff --git a/target/image/x86/gen_image.sh b/target/image/x86/gen_image.sh
new file mode 100755
index 0000000000..95be6cc8ef
--- /dev/null
+++ b/target/image/x86/gen_image.sh
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+# Copyright (C) 2006 OpenWrt.org
+
+[ $# == 5 ] || {
+ echo "SYNTAX: $0 <file> <kernel size> <kernel directory> <rootfs size> <rootfs image>"
+ exit 1
+}
+
+file="$1"
+part1s="$2"
+part1d="$3"
+part2s="$4"
+part2f="$5"
+
+head=16
+sect=63
+cyl=$(( ($part1s + $part2s) * 1024 * 1024 / ($head * $sect * 512)))
+
+dd if=/dev/zero of="$file" bs=1M count=$(($part1s + $part2s)) 2>/dev/null || exit
+fdisk -u -C $cyl -H $head -S $sect "$file" > /dev/null 2>/dev/null <<EOF
+n
+p
+1
+
++${part1s}M
+n
+p
+2
+
++${part2s}M
+w
+q
+EOF
+
+block() {
+ echo -e 'p\nq' | fdisk -u -C $cyl -H $head -S $sect "$file" | awk -v file="$file$1" -v n="$(($2 + 2))" '
+$1 == file {
+ print $n * 512
+}'
+}
+
+start="$(block 1 0)"
+end="$(block 1 1)"
+blocks="$(( ($end - $start) / 1024 ))"
+
+genext2fs -d "$part1d" -b "$blocks" "$file.kernel"
+dd if="$file.kernel" of="$file" bs=512 seek="$(($start / 512))" conv=notrunc
+rm -f "$file.kernel"
+
+start="$(block 2 0)"
+dd if="$part2f" of="$file" bs=512 seek="$(($start / 512))" conv=notrunc
+
+which chpax >/dev/null && chpax -zp $(which grub)
+grub --device-map=/dev/null <<EOF
+device (hd0) $file
+geometry (hd0) $cyl $head $sect
+root (hd0,0)
+setup (hd0)
+EOF
+
diff --git a/target/image/x86/grub/Makefile b/target/image/x86/grub/Makefile
new file mode 100644
index 0000000000..86a90016ac
--- /dev/null
+++ b/target/image/x86/grub/Makefile
@@ -0,0 +1,58 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 4855 2006-09-24 20:49:31Z nico $
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=grub
+PKG_VERSION:=0.97
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=ftp://alpha.gnu.org/gnu/grub
+PKG_MD5SUM:=cd3f3eb54446be6003156158d51f4884
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/grub-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Build/Configure
+ (cd $(PKG_BUILD_DIR); \
+ LDFLAGS="-static" \
+ ./configure \
+ --target=$(GNU_TARGET_NAME) \
+ --host=$(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 \
+ --datadir=/usr/share \
+ --localstatedir=/var \
+ --mandir=/usr/man \
+ --infodir=/usr/info \
+ $(DISABLE_NLS) \
+ )
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR)
+endef
+
+define Build/InstallDev
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ DESTDIR="$(STAGING_DIR)" \
+ install
+endef
+
+$(eval $(call Build/DefaultTargets))
diff --git a/target/image/x86/grub/menu.lst b/target/image/x86/grub/menu.lst
new file mode 100644
index 0000000000..590a7d5e3a
--- /dev/null
+++ b/target/image/x86/grub/menu.lst
@@ -0,0 +1,11 @@
+serial --unit=0 --speed=@BAUDRATE@ --word=8 --parity=no --stop=1
+terminal --timeout=10 serial
+
+default 0
+timeout 5
+
+title OpenWrt
+root (hd0,0)
+kernel /boot/vmlinuz @CMDLINE@ noinitrd console=ttyS0,@BAUDRATE@n8 reboot=bios
+boot
+
diff --git a/target/image/xscale/Makefile b/target/image/xscale/Makefile
new file mode 100644
index 0000000000..23a0644338
--- /dev/null
+++ b/target/image/xscale/Makefile
@@ -0,0 +1,32 @@
+#
+# 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)/image.mk
+
+define Build/Clean
+endef
+
+define Image/Prepare
+endef
+
+define Image/BuildKernel
+ cp $(LINUX_DIR)/arch/arm/boot/zImage $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-zImage
+endef
+
+define Image/Build
+ $(call Image/Build/$(1),$(1))
+endef
+
+define Image/Build/jffs2-64k
+ dd if=$(KDIR)/root.$(1) of=$(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).img bs=65536 conv=sync
+endef
+
+define Image/Build/jffs2-128k
+ dd if=$(KDIR)/root.$(1) of=$(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).img bs=131072 conv=sync
+endef
+
+$(eval $(call BuildImage))
diff --git a/target/linux/Config.in b/target/linux/Config.in
new file mode 100644
index 0000000000..20099fee42
--- /dev/null
+++ b/target/linux/Config.in
@@ -0,0 +1,492 @@
+menu "Kernel Configuration / Device Support"
+
+comment "Device specific configuration"
+
+source "target/linux/*-2.[46]/Config.in"
+
+comment "Kernel modules"
+
+menu "Networking modules"
+
+config PACKAGE_KMOD_ATM
+ prompt "kmod-atm.......................... ATM support"
+ tristate
+ default y if LINUX_2_4_AR7
+ default m
+ help
+ ATM support
+
+config PACKAGE_KMOD_IPIP
+ prompt "kmod-ipip......................... IP in IP encapsulation support"
+ tristate
+ default m
+ help
+ Kernel module for IP in IP encapsulation
+
+config PACKAGE_KMOD_RING
+ prompt "kmod-ring......................... PF Ring"
+ tristate
+ default m
+ help
+ PF Ring
+
+config PACKAGE_KMOD_TUN
+ prompt "kmod-tun.......................... Universal TUN/TAP driver"
+ tristate
+ default m
+ help
+ Kernel support for the TUN/TAP tunneling device
+
+endmenu
+
+menu "Block devices support"
+
+config PACKAGE_kmod-ide-core
+ prompt "kmod-ide-core..................... IDE support"
+ tristate
+ default m
+ depends LINUX_2_4_X86 || LINUX_2_6_X86 || LINUX_2_4_BRCM || LINUX_2_6_BRCM
+ help
+ Kernel modules for IDE support
+ useful for usb mass storage devices (e.g. on WL-HDD)
+
+ Includes:
+ - ide-core
+ - ide-detect
+ - ide-disk
+
+config PACKAGE_kmod-ide-pdc202xx
+ prompt "kmod-ide-pdc202xx................. PDC202xx driver"
+ tristate
+ default m
+ depends PACKAGE_kmod-ide-core
+ depends LINUX_2_4_X86 || LINUX_2_6_X86 || LINUX_2_4_BRCM || LINUX_2_6_BRCM
+ help
+ Kernel modules for IDE support
+ useful for usb mass storage devices (e.g. on WL-HDD)
+
+ Includes:
+ - ide-core
+ - ide-detect
+ - ide-disk
+
+config PACKAGE_KMOD_LOOP
+ prompt "kmod-loop......................... Loop mount support"
+ tristate
+ default m
+ help
+ Kernel module for loop mount support
+
+config PACKAGE_KMOD_NBD
+ prompt "kmod-nbd.......................... Network Block Device"
+ tristate
+ default m
+ help
+ Kernel module for network block device
+
+endmenu
+
+menu "Filesystems support"
+
+config PACKAGE_KMOD_FS_CIFS
+ prompt "kmod-fs-cifs...................... CIFS support"
+ tristate
+ default m
+ help
+ Kernel modules for CIFS support
+
+config PACKAGE_KMOD_FS_EXT2
+ prompt "kmod-fs-ext2...................... EXT2 filesystem support"
+ tristate
+ default m
+ help
+ Kernel modules for EXT2 filesystem support
+
+config PACKAGE_KMOD_FS_EXT3
+ prompt "kmod-fs-ext3...................... EXT3 filesystem support"
+ tristate
+ default m
+ help
+ Kernel modules for EXT3 filesystem support
+
+config PACKAGE_KMOD_FS_HFSPLUS
+ prompt "kmod-fs-hfsplus................... HFS+ filesystem support"
+ tristate
+ default m
+ help
+ Kernel modules for HFS+ filesystem support
+
+config PACKAGE_KMOD_FS_NFS
+ prompt "kmod-fs-nfs....................... NFS support"
+ tristate
+ default m
+ help
+ Kernel modules for NFS support
+ Includes lockd, nfs and sunrpc
+
+config PACKAGE_KMOD_FS_VFAT
+ prompt "kmod-fs-vfat...................... VFAT filesystem support"
+ tristate
+ default m
+ help
+ Kernel modules for VFAT filesystem support
+ useful for usb mass storage devices
+
+config PACKAGE_KMOD_FS_XFS
+ prompt "kmod-fs-xfs....................... XFS filesystem support"
+ tristate
+ default m
+ help
+ Kernel modules for XFS filesystem support
+
+endmenu
+
+menu "Multimedia devices support"
+
+config PACKAGE_KMOD_PWC
+ prompt "kmod-pwc.......................... Kernel driver for USB Philips Cameras"
+ tristate
+ depends PACKAGE_KMOD_USB
+ default m
+
+config PACKAGE_KMOD_SOUNDCORE
+ prompt "kmod-soundcore.................... Soundcard support"
+ tristate
+ default n
+ help
+ Base support for soundcards
+ Requires either USB soundcard support (OSS) or ALSA package to be useful
+
+config PACKAGE_KMOD_VIDEODEV
+ prompt "kmod-videodev..................... Video (For Linux) kernel support"
+ tristate
+ default m
+
+endmenu
+
+menu "Native Language support"
+
+config PACKAGE_KMOD_NLS_BASE
+ prompt "kmod-nls-base..................... Native Language support"
+ tristate
+ default m
+ help
+ Kernel native language support
+
+config PACKAGE_KMOD_NLS_CP437
+ prompt "kmod-nls-cp437.................. Codepage 437 (United States, Canada)"
+ tristate
+ default m
+ depends PACKAGE_KMOD_NLS_BASE
+ help
+ Kernel native language support
+
+config PACKAGE_KMOD_NLS_CP850
+ prompt "kmod-nls-cp850.................. Codepage 850 (Europe)"
+ tristate
+ default m
+ depends PACKAGE_KMOD_NLS_BASE
+ help
+ Kernel native language support
+
+config PACKAGE_KMOD_NLS_ISO8859_1
+ prompt "kmod-nls-iso8859-1.............. NLS ISO 8859-1 (Latin 1; Western European Languages)"
+ tristate
+ default m
+ depends PACKAGE_KMOD_NLS_BASE
+ help
+ Kernel native language support
+
+config PACKAGE_KMOD_NLS_ISO8859_15
+ prompt "kmod-nls-iso8859-15............. NLS ISO 8859-15 (Latin 15; Western European Languages with Euro)"
+ tristate
+ default m
+ depends PACKAGE_KMOD_NLS_BASE
+ help
+ Kernel native language support
+
+config PACKAGE_KMOD_NLS_UTF8
+ prompt "kmod-nls-utf8................... NLS UTF8"
+ tristate
+ default m
+ depends PACKAGE_KMOD_NLS_BASE
+ help
+ Kernel native language support
+
+endmenu
+
+menu "Network devices support"
+ depends LINUX_2_4_X86 || LINUX_2_6_X86
+
+
+config PACKAGE_KMOD_NET_AIRO
+ prompt "kmod-net-airo..................... Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards kernel support"
+ tristate
+ depends LINUX_2_4_X86 || LINUX_2_6_X86
+ default m
+ help
+ This is the standard Linux driver to support Cisco/Aironet ISA and
+ PCI 802.11 wireless cards.
+ It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X
+ - with or without encryption) as well as card before the Cisco
+ acquisition (Aironet 4500, Aironet 4800, Aironet 4800B).
+
+ This driver support both the standard Linux Wireless Extensions
+ and Cisco proprietary API, so both the Linux Wireless Tools and the
+ Cisco Linux utilities can be used to configure the card.
+
+
+config PACKAGE_KMOD_NET_HERMES
+ prompt "kmod-net-hermes................... Hermes chipset 802.11b support (Orinoco/Prism2/Symbol) kernel support"
+ tristate
+ depends LINUX_2_4_X86 || LINUX_2_6_X86
+ default m
+ help
+ A driver for 802.11b wireless cards based based on the "Hermes" or
+ Intersil HFA384x (Prism 2) MAC controller. This includes the vast
+ majority of the PCMCIA 802.11b cards (which are nearly all rebadges)
+ - except for the Cisco/Aironet cards. Cards supported include the
+ Apple Airport (not a PCMCIA card), WavelanIEEE/Orinoco,
+ Cabletron/EnteraSys Roamabout, ELSA AirLancer, MELCO Buffalo, Avaya,
+ IBM High Rate Wireless, Farralon Syyline, Samsung MagicLAN, Netgear
+ MA401, LinkSys WPC-11, D-Link DWL-650, 3Com AirConnect, Intel
+ PRO/Wireless, and Symbol Spectrum24 High Rate amongst others.
+
+config PACKAGE_KMOD_NET_HERMES_PCI
+ prompt "kmod-net-hermes-pci............. Intersil Prism 2.5 PCI 802.11b adaptor support"
+ tristate
+ default m
+ depends PACKAGE_KMOD_NET_HERMES
+ help
+ Enable support for PCI and mini-PCI 802.11b wireless NICs based on
+ the Prism 2.5 chipset. These are true PCI cards, not the 802.11b
+ PCMCIA cards bundled with PCI<->PCMCIA adaptors which are also
+ common. Some of the built-in wireless adaptors in laptops are of
+ this variety.
+
+config PACKAGE_KMOD_NET_HERMES_PLX
+ prompt "kmod-net-hermes-plx............. Hermes in PLX9052 based PCI adaptor (Netgear MA301, etc.) kernel support"
+ tristate
+ default m
+ depends PACKAGE_KMOD_NET_HERMES
+ help
+ Enable support for PCMCIA cards supported by the "Hermes" (aka
+ orinoco_cs) driver when used in PLX9052 based PCI adaptors. These
+ adaptors are not a full PCMCIA controller but act as a more limited
+ PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that
+ 802.11b PCMCIA cards can be used in desktop machines. The Netgear
+ MA301 is such an adaptor.
+
+
+
+config PACKAGE_KMOD_NET_PRISM54
+ prompt "kmod-net-prism54.................. Intersil Prism GT/Duette/Indigo PCI/PCMCIA cards kernel support"
+ tristate
+ depends LINUX_2_4_X86 || LINUX_2_6_X86 || LINUX_2_4_BRCM || LINUX_2_6_BRCM
+ default m
+ help
+ Enable PCI and Cardbus support for the following chipset based cards:
+
+ * ISL3880 - Prism GT 802.11 b/g
+ * ISL3877 - Prism Indigo 802.11 a
+ * ISL3890 - Prism Duette 802.11 a/b/g
+
+ For a complete list of supported cards visit <http://prism54.org>.
+ Here is the latest confirmed list of supported cards:
+
+ * 3com OfficeConnect 11g Cardbus Card aka 3CRWE154G72
+ * Allnet ALL0271 PCI Card
+ * Compex WL54G Cardbus Card
+ * Corega CG-WLCB54GT Cardbus Card
+ * D-Link Air Plus Xtreme G A1 Cardbus Card aka DWL-g650
+ * I-O Data WN-G54/CB Cardbus Card
+ * Kobishi XG-300 aka Z-Com Cardbus Card
+ * Netgear WG511 Cardbus Card
+ * Ovislink WL-5400PCI PCI Card
+ * Peabird WLG-PCI PCI Card
+ * Sitecom WL-100i Cardbus Card
+ * Sitecom WL-110i PCI Card
+ * SMC2802W - EZ Connect g 2.4GHz 54 Mbps Wireless PCI Card
+ * SMC2835W - EZ Connect g 2.4GHz 54 Mbps Wireless Cardbus Card
+ * Z-Com XG-900 PCI Card
+ * Zyxel G-100 Cardbus Card
+
+ If you enable this, you require a firmware file as well.
+ You will need to copy this to /usr/lib/hotplug/firmware/isl3890.
+ You can get this non-GPL'd firmware file from the Prism54 project page:
+ <http://prism54.org>.
+
+ Note: You need a motherboard with DMA support to use any of these cards.
+
+endmenu
+
+menu "PCMCIA/CardBus support"
+ depends PCMCIA_SUPPORT
+
+config PACKAGE_KMOD_PCMCIA_CORE
+ prompt "kmod-pcmcia-core.................. PCMCIA/CardBus support"
+ tristate
+ default m
+
+config PACKAGE_KMOD_PCMCIA_SERIAL
+ prompt "kmod-pcmcia-serial.............. PCMCIA/CardBus serial device support"
+ tristate
+ default m
+ depends PACKAGE_KMOD_PCMCIA_CORE
+
+endmenu
+
+menu "USB support"
+ depends USB_SUPPORT
+
+config PACKAGE_KMOD_USB
+ prompt "kmod-usb-core..................... USB support"
+ tristate
+ default m
+
+config PACKAGE_KMOD_USB_UHCI
+ prompt "kmod-usb-uhci................... Support for UHCI controllers"
+ tristate
+ default n if LINUX_2_6_AU1000
+ depends PACKAGE_KMOD_USB
+ select PACKAGE_KMOD_USB_CONTROLLER
+
+config PACKAGE_KMOD_USB_OHCI
+ prompt "kmod-usb-ohci................... Support for OHCI controllers"
+ tristate
+ default m
+ depends PACKAGE_KMOD_USB
+ select PACKAGE_KMOD_USB_CONTROLLER
+
+config PACKAGE_KMOD_USB2
+ prompt "kmod-usb2....................... Support for USB 2.0 controllers"
+ tristate
+ default n if LINUX_2_6_AU1000
+ depends PACKAGE_KMOD_USB
+ select PACKAGE_KMOD_USB_CONTROLLER
+
+config PACKAGE_KMOD_USB_CONTROLLER
+ tristate
+ depends on PACKAGE_KMOD_USB_UHCI || PACKAGE_KMOD_USB_OHCI || PACKAGE_KMOD_USB2
+ default n
+
+config PACKAGE_KMOD_USB_ACM
+ prompt "kmod-usb-acm...................... Support for USB modems/isdn controllers"
+ tristate
+ default m
+ depends PACKAGE_KMOD_USB_CONTROLLER
+
+config PACKAGE_KMOD_USB_AUDIO
+ prompt "kmod-usb-audio.................... Support for USB soundcards"
+ tristate
+ default m
+ depends PACKAGE_KMOD_USB_CONTROLLER
+ select PACKAGE_KMOD_SOUNDCORE
+
+config PACKAGE_KMOD_USB_PRINTER
+ prompt "kmod-usb-printer.................. Support for USB printers"
+ tristate
+ default m
+ depends PACKAGE_KMOD_USB_CONTROLLER
+
+config PACKAGE_KMOD_USB_SERIAL
+ prompt "kmod-usb-serial................... Support for USB-to-serial converters"
+ tristate
+ default m
+ depends PACKAGE_KMOD_USB_CONTROLLER
+
+config PACKAGE_KMOD_USB_SERIAL_BELKIN
+ prompt "kmod-usb-serial-belkin.......... Support for Belkin USB-to-serial converters"
+ tristate
+ default m
+ depends PACKAGE_KMOD_USB_SERIAL
+
+config PACKAGE_KMOD_USB_SERIAL_FTDI
+ prompt "kmod-usb-serial-ftdi............ Support for FTDI USB-to-serial converterr"
+ tristate
+ default m
+ depends PACKAGE_KMOD_USB_SERIAL
+
+config PACKAGE_KMOD_USB_SERIAL_MCT_U232
+ prompt "kmod-usb-serial-mct-u232........ Support for Magic Control Technology USB-to-Serial converters"
+ tristate
+ default m
+ depends PACKAGE_KMOD_USB_SERIAL
+
+config PACKAGE_KMOD_USB_SERIAL_PL2303
+ prompt "kmod-usb-serial-pl2303.......... Support for Prolific PL2303 USB-to-Serial converters"
+ tristate
+ default m
+ depends PACKAGE_KMOD_USB_SERIAL
+
+config PACKAGE_KMOD_USB_SERIAL_VISOR
+ prompt "kmod-usb-serial-visor........... Support for Handspring Visor / Palm m50x / Sony Clie Driver"
+ tristate
+ default m
+ depends PACKAGE_KMOD_USB_SERIAL
+
+config PACKAGE_KMOD_USB_STORAGE
+ prompt "kmod-usb-storage.................. Support for USB storage devices"
+ tristate
+ default m
+ depends PACKAGE_KMOD_USB_CONTROLLER
+
+config PACKAGE_KMOD_USB_ATM
+ prompt "kmod-usb-atm...................... Support for USB ATM devices"
+ tristate
+ default m
+ depends PACKAGE_KMOD_USB_CONTROLLER
+
+config PACKAGE_KMOD_USB_ATM_SPEEDTOUCH
+ prompt "kmod-usb-atm-speedtouch......... Support for USB Speedtouch ADSL modem"
+ tristate
+ default m
+ depends PACKAGE_KMOD_USB_ATM
+
+endmenu
+
+menu "Misc. devices support"
+
+config PACKAGE_KMOD_AX25
+ prompt "kmod-ax25......................... AX25 support"
+ tristate
+ default m
+ help
+ Kernel modules for AX25 protocol family
+
+ This package contains both the AX25 layer 2 support (ax25) and AX25 KISS driver (mkiss)
+
+config PACKAGE_KMOD_BLUETOOTH
+ prompt "kmod-bluetooth.................... Bluetooth drivers and network stack"
+ tristate
+ depends PCI_SUPPORT || USB_SUPPORT
+ default m
+ help
+ Bluetooth drivers and network stack
+
+config PACKAGE_KMOD_LP
+ prompt "kmod-lp........................... Parallel port and lp support"
+ tristate
+ default m
+ help
+ Kernel modules for line printer and parallel port support
+
+config PACKAGE_KMOD_SOFTDOG
+ prompt "kmod-softdog...................... Software watchdog"
+ tristate
+ default m
+ help
+ Kernel modules for software watchdog driver
+
+config PACKAGE_KMOD_WD1100
+ prompt "kmod-wd1100....................... Soekris net4801 watchdog"
+ tristate
+ default y
+ depends LINUX_2_4_X86
+ help
+ Driver for the NatSemi SC1x00 series Watchdog
+ found on Soekris net4801 boards
+
+endmenu
+
+endmenu
diff --git a/target/linux/Makefile b/target/linux/Makefile
new file mode 100644
index 0000000000..8682fc2b9b
--- /dev/null
+++ b/target/linux/Makefile
@@ -0,0 +1,24 @@
+#
+# 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)/target.mk
+
+download:
+ $(MAKE) -C $(BOARD)-$(KERNEL) download
+
+prepare:
+ rm -f $(TOPDIR)/.kernel.mk
+ $(MAKE) -C $(BOARD)-$(KERNEL) prepare
+
+compile:
+ $(MAKE) -C $(BOARD)-$(KERNEL) compile
+
+install:
+ $(MAKE) -C $(BOARD)-$(KERNEL) install
+
+clean:
+ $(MAKE) -C $(BOARD)-$(KERNEL) clean
diff --git a/target/linux/ar531x-2.4/Makefile b/target/linux/ar531x-2.4/Makefile
new file mode 100644
index 0000000000..33cb47cf50
--- /dev/null
+++ b/target/linux/ar531x-2.4/Makefile
@@ -0,0 +1,22 @@
+#
+# 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
+
+LINUX_VERSION:=2.4.32
+LINUX_RELEASE:=1
+LINUX_KERNEL_MD5SUM:=38f4d0830e95a20f4bfed17622d5557c
+
+include ./config
+include $(INCLUDE_DIR)/kernel.mk
+include $(INCLUDE_DIR)/kernel-build.mk
+
+$(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked
+ [ -d ../generic-$(KERNEL)/patches ] && $(PATCH) $(LINUX_DIR) ../generic-$(KERNEL)/patches
+ [ -d ./patches ] && $(PATCH) $(LINUX_DIR) ./patches
+ @$(CP) config $(LINUX_DIR)/.config
+ touch $@
+
diff --git a/target/linux/ar531x-2.4/config b/target/linux/ar531x-2.4/config
new file mode 100644
index 0000000000..782d1de4c7
--- /dev/null
+++ b/target/linux/ar531x-2.4/config
@@ -0,0 +1,1164 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+CONFIG_MIPS32=y
+# CONFIG_MIPS64 is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_ACER_PICA_61 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_FICMMP is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_HYDROGEN3 is not set
+CONFIG_AR531X=y
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_COGENT_CSB250 is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_CASIO_E55 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MAGNUM_4000 is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_BIG_SUR is not set
+# CONFIG_PMC_STRETCH is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_NEC_EAGLE is not set
+# CONFIG_OLIVETTI_M700 is not set
+# CONFIG_NINO is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TANBAC_TB0226 is not set
+# CONFIG_TANBAC_TB0229 is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_IRQ_CPU=y
+CONFIG_CPU_R4X00=y
+CONFIG_SERIAL=y
+CONFIG_NEW_IRQ=y
+CONFIG_NEW_TIME_C=y
+CONFIG_NONCOHERENT_IO=y
+CONFIG_EARLY_PRINTK_HACK=y
+# CONFIG_SCSI is not set
+
+#
+# Board selection
+#
+# CONFIG_APUNKNOWN is not set
+CONFIG_AP30=y
+# CONFIG_AP31 is not set
+# CONFIG_AP33 is not set
+# CONFIG_AP38 is not set
+# CONFIG_AP43 is not set
+# CONFIG_AP48 is not set
+# CONFIG_AP51 is not set
+# CONFIG_AP30ASK is not set
+CONFIG_MTD_PHYSMAP_BUSWIDTH=2
+
+#
+# Flash Selection
+#
+CONFIG_FLASH_2MB=y
+# CONFIG_FLASH_4MB is not set
+# CONFIG_MIPS_AU1000 is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+CONFIG_CPU_R4X00=y
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+CONFIG_CPU_ADVANCED=y
+# CONFIG_CPU_HAS_LLSC is not set
+# CONFIG_CPU_HAS_LLDSCD is not set
+# CONFIG_CPU_HAS_WB is not set
+CONFIG_CPU_HAS_SYNC=y
+
+#
+# General setup
+#
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+# CONFIG_BUILD_ELF64 is not set
+# CONFIG_BINFMT_IRIX is not set
+CONFIG_NET=y
+# CONFIG_PCI is not set
+# CONFIG_PCI_NEW is not set
+CONFIG_PCI_AUTO=y
+# CONFIG_ISA is not set
+# CONFIG_TC is not set
+# CONFIG_MCA is not set
+# CONFIG_SBUS is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+# CONFIG_HOTPLUG_PCI is not set
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_ELF_AOUT is not set
+# CONFIG_MIPS32_COMPAT is not set
+# CONFIG_MIPS32_O32 is not set
+# CONFIG_MIPS32_N32 is not set
+# CONFIG_BINFMT_ELF32 is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_OOM_KILLER is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_CFI_B1 is not set
+CONFIG_MTD_CFI_B2=y
+# CONFIG_MTD_CFI_B4 is not set
+# CONFIG_MTD_CFI_B8 is not set
+CONFIG_MTD_CFI_I1=y
+# CONFIG_MTD_CFI_I2 is not set
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_SSTSTD=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+CONFIG_MTD_OBSOLETE_CHIPS=y
+CONFIG_MTD_AMDSTD=y
+# CONFIG_MTD_SHARP is not set
+CONFIG_MTD_JEDEC=y
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xbe000000
+CONFIG_MTD_PHYSMAP_LEN=200000
+CONFIG_MTD_PHYSMAP_BUSWIDTH=2
+# CONFIG_MTD_PB1000 is not set
+# CONFIG_MTD_PB1500 is not set
+# CONFIG_MTD_PB1100 is not set
+# CONFIG_MTD_BOSPORUS is not set
+# CONFIG_MTD_XXS1500 is not set
+# CONFIG_MTD_MTX1 is not set
+# CONFIG_MTD_DB1X00 is not set
+# CONFIG_MTD_PB1550 is not set
+# CONFIG_MTD_HYDROGEN3 is not set
+# CONFIG_MTD_MIRAGE is not set
+# CONFIG_MTD_CSTM_MIPS_IXX is not set
+# CONFIG_MTD_OCELOT is not set
+# CONFIG_MTD_LASAT is not set
+# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PCMCIA is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+# CONFIG_PARPORT_PC is not set
+# CONFIG_PARPORT_AMIGA is not set
+# CONFIG_PARPORT_MFC3 is not set
+# CONFIG_PARPORT_ATARI is not set
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_SUNBPP is not set
+# CONFIG_PARPORT_IP22 is not set
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=3072
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_BLK_STATS is not set
+
+#
+# MIPS initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_FILTER=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_NAT=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_TOS=y
+# CONFIG_IP_ROUTE_VERBOSE is not set
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_FTP=y
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_IRC=y
+CONFIG_IP_NF_CT_ACCT=m
+CONFIG_IP_NF_MATCH_CONNBYTES=m
+CONFIG_IP_NF_CT_PROTO_GRE=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_RTSP=m
+CONFIG_IP_NF_MMS=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_QUOTA=m
+CONFIG_IP_NF_SET=m
+CONFIG_IP_NF_SET_MAX=256
+CONFIG_IP_NF_SET_HASHSIZE=1024
+CONFIG_IP_NF_MATCH_SET=m
+CONFIG_IP_NF_TARGET_SET=m
+CONFIG_IP_NF_SET_IPMAP=m
+CONFIG_IP_NF_SET_PORTMAP=m
+CONFIG_IP_NF_SET_MACIPMAP=m
+CONFIG_IP_NF_SET_IPHASH=m
+CONFIG_IP_NF_SET_NETHASH=m
+CONFIG_IP_NF_SET_IPTREE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=y
+CONFIG_IP_NF_MATCH_MULTIPORT=y
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TIME=m
+CONFIG_IP_NF_MATCH_CONDITION=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_IPP2P=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=y
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_UNCLEAN=m
+CONFIG_IP_NF_MATCH_STRING=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_LAYER7=m
+# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_MIRROR=m
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_PROTO_GRE=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_RTSP=m
+CONFIG_IP_NF_NAT_MMS=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=y
+CONFIG_IP_NF_NAT_FTP=y
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=y
+CONFIG_IP_NF_TARGET_IMQ=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=y
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_CONDITION=m
+CONFIG_IP6_NF_MATCH_MAC=m
+# CONFIG_IP6_NF_MATCH_RT is not set
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
+# CONFIG_IP6_NF_MATCH_AHESP is not set
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_TARGET_IMQ=m
+# CONFIG_KHTTPD is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+CONFIG_VLAN_8021Q=y
+
+#
+#
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+CONFIG_BRIDGE=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_CSZ=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+# CONFIG_NET_SCH_NETEM is not set
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_POLICE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_IPSEC_NAT_TRAVERSAL=y
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+# CONFIG_PHONE_IXJ is not set
+# CONFIG_PHONE_IXJ_PCMCIA is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=m
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_IDEDISK_STROKE=y
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_DELKIN is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_BLK_DEV_ATARAID_MEDLEY is not set
+# CONFIG_BLK_DEV_ATARAID_SII is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_BOOT is not set
+# CONFIG_FUSION_ISENSE is not set
+# CONFIG_FUSION_CTL is not set
+# CONFIG_FUSION_LAN is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_IMQ=m
+CONFIG_TUN=m
+CONFIG_NET_RANDOM=y
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_VENETDEV is not set
+# CONFIG_NET_ATHEROS_ETHER is not set
+CONFIG_MARVELL_ENET_PHY=y
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE_MPPC=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_STRIP is not set
+# CONFIG_WAVELAN is not set
+# CONFIG_ARLAN is not set
+# CONFIG_AIRONET4500 is not set
+# CONFIG_AIRONET4500_NONCS is not set
+# CONFIG_AIRONET4500_PROC is not set
+# CONFIG_HERMES is not set
+
+#
+# Prism54 PCI/PCMCIA GT/Duette Driver - 802.11(a/b/g)
+#
+# CONFIG_PRISM54 is not set
+# CONFIG_NET_WIRELESS is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+CONFIG_SHAPER=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+CONFIG_AX25=m
+# CONFIG_AX25_DAMA_SLAVE is not set
+# CONFIG_NETROM is not set
+# CONFIG_ROSE is not set
+
+#
+# AX.25 network device drivers
+#
+
+#
+# AX.25 network device drivers
+#
+CONFIG_MKISS=m
+# CONFIG_6PACK is not set
+# CONFIG_BPQETHER is not set
+# CONFIG_SCC_DELAY is not set
+# CONFIG_SCC_TRXECHO is not set
+# CONFIG_BAYCOM_SER_FDX is not set
+# CONFIG_BAYCOM_SER_HDX is not set
+# CONFIG_BAYCOM_PAR is not set
+# CONFIG_BAYCOM_EPP is not set
+# CONFIG_SOUNDMODEM is not set
+# CONFIG_YAM is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_UINPUT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=128
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+CONFIG_PPDEV=m
+# CONFIG_TIPAR is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+
+#
+# Input core support is needed for gameports
+#
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_IPMI_PANIC_EVENT is not set
+# CONFIG_IPMI_DEVICE_INTERFACE is not set
+# CONFIG_IPMI_KCS is not set
+# CONFIG_IPMI_WATCHDOG is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+# CONFIG_ALIM1535_WDT is not set
+# CONFIG_ALIM7101_WDT is not set
+# CONFIG_SC520_WDT is not set
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+# CONFIG_WAFER_WDT is not set
+# CONFIG_I810_TCO is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_SC1200_WDT is not set
+# CONFIG_SCx200_WDT is not set
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_W83877F_WDT is not set
+# CONFIG_WDT is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_MACHZ_WDT is not set
+# CONFIG_SCx200 is not set
+# CONFIG_SCx200_GPIO is not set
+# CONFIG_AMD_PM768 is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
+# CONFIG_DRM is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+CONFIG_EXT3_FS=m
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FAT_FS=m
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=m
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_BBC_ARMLIB is not set
+# CONFIG_JFFS2_BBC_LZO is not set
+CONFIG_JFFS2_BBC_LZARI=y
+# CONFIG_JFFS2_BBC_LZHD is not set
+# CONFIG_JFFS2_BBC_LZSS is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_MINIX_FS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=m
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_SUNRPC=m
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_POSIX=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SMB_NLS is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+CONFIG_VIDEO_PROC_FS=y
+# CONFIG_I2C_PARPORT is not set
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_BWQCAM is not set
+# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN_BUZ is not set
+# CONFIG_VIDEO_ZORAN_DC10 is not set
+# CONFIG_VIDEO_ZORAN_LML33 is not set
+# CONFIG_VIDEO_ZR36120 is not set
+# CONFIG_VIDEO_MEYE is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_MIROPCM20 is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+# CONFIG_SOUND_ALI5455 is not set
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_MIDI_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_FORTE is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_MIDI_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+# CONFIG_SOUND_WM97XX is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+CONFIG_BLUEZ=m
+CONFIG_BLUEZ_L2CAP=m
+CONFIG_BLUEZ_SCO=m
+CONFIG_BLUEZ_RFCOMM=m
+CONFIG_BLUEZ_RFCOMM_TTY=y
+CONFIG_BLUEZ_BNEP=m
+CONFIG_BLUEZ_BNEP_MC_FILTER=y
+CONFIG_BLUEZ_BNEP_PROTO_FILTER=y
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BLUEZ_HCIUSB is not set
+CONFIG_BLUEZ_HCIUART=m
+CONFIG_BLUEZ_HCIUART_H4=y
+CONFIG_BLUEZ_HCIUART_BCSP=y
+CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y
+# CONFIG_BLUEZ_HCIBFUSB is not set
+# CONFIG_BLUEZ_HCIDTL1 is not set
+# CONFIG_BLUEZ_HCIBT3C is not set
+# CONFIG_BLUEZ_HCIBLUECARD is not set
+# CONFIG_BLUEZ_HCIBTUART is not set
+# CONFIG_BLUEZ_HCIVHCI is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+# CONFIG_RUNTIME_DEBUG is not set
+# CONFIG_KGDB is not set
+# CONFIG_GDB_CONSOLE is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_MIPS_UNCACHED is not set
+CONFIG_LOG_BUF_SHIFT=0
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/target/linux/ar531x-2.4/patches/000-atheros-support.patch b/target/linux/ar531x-2.4/patches/000-atheros-support.patch
new file mode 100644
index 0000000000..de7115b46a
--- /dev/null
+++ b/target/linux/ar531x-2.4/patches/000-atheros-support.patch
@@ -0,0 +1,11411 @@
+diff -urN linux-mips/arch/mips/ar531x/ar531xdbg_io.c mips-linux-2.4.25/arch/mips/ar531x/ar531xdbg_io.c
+--- linux-mips/arch/mips/ar531x/ar531xdbg_io.c 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531xdbg_io.c 2005-12-30 17:26:30.606883840 +0000
+@@ -0,0 +1,234 @@
++/*
++ * 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 MontaVista Software Inc
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * Basic support for polled character input/output
++ * using the AR531X's serial port.
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/serial.h>
++#include <linux/types.h>
++#include <linux/string.h>
++
++#include <asm/reboot.h>
++#include <asm/io.h>
++#include <asm/time.h>
++#include <asm/pgtable.h>
++#include <asm/processor.h>
++#include <asm/reboot.h>
++#include <asm/system.h>
++#include <asm/serial.h>
++#include <asm/gdb-stub.h>
++
++#include "ar531xlnx.h"
++
++#if CONFIG_EARLY_PRINTK_HACK || CONFIG_KGDB
++/* base addr of uart and clock timing */
++#if CONFIG_AR5315
++#define BASE AR5315_UART0
++#else
++#define BASE AR531X_UART0
++#endif
++
++/* distance in bytes between two serial registers */
++#define REG_OFFSET 4
++
++/*
++ * 0 - we need to do serial init
++ * 1 - skip serial init
++ */
++static int serialPortInitialized = 0;
++
++/*
++ * * the default baud rate *if* we do serial init
++ * */
++#define BAUD_DEFAULT UART16550_BAUD_9600
++
++/* === END OF CONFIG === */
++
++#define UART16550_BAUD_2400 2400
++#define UART16550_BAUD_4800 4800
++#define UART16550_BAUD_9600 9600
++#define UART16550_BAUD_19200 19200
++#define UART16550_BAUD_38400 38400
++#define UART16550_BAUD_57600 57600
++#define UART16550_BAUD_115200 115200
++
++#define UART16550_PARITY_NONE 0
++#define UART16550_PARITY_ODD 0x08
++#define UART16550_PARITY_EVEN 0x18
++#define UART16550_PARITY_MARK 0x28
++#define UART16550_PARITY_SPACE 0x38
++
++#define UART16550_DATA_5BIT 0x0
++#define UART16550_DATA_6BIT 0x1
++#define UART16550_DATA_7BIT 0x2
++#define UART16550_DATA_8BIT 0x3
++
++#define UART16550_STOP_1BIT 0x0
++#define UART16550_STOP_2BIT 0x4
++
++/* register offset */
++#define OFS_RCV_BUFFER (0*REG_OFFSET)
++#define OFS_TRANS_HOLD (0*REG_OFFSET)
++#define OFS_SEND_BUFFER (0*REG_OFFSET)
++#define OFS_INTR_ENABLE (1*REG_OFFSET)
++#define OFS_INTR_ID (2*REG_OFFSET)
++#define OFS_DATA_FORMAT (3*REG_OFFSET)
++#define OFS_LINE_CONTROL (3*REG_OFFSET)
++#define OFS_MODEM_CONTROL (4*REG_OFFSET)
++#define OFS_RS232_OUTPUT (4*REG_OFFSET)
++#define OFS_LINE_STATUS (5*REG_OFFSET)
++#define OFS_MODEM_STATUS (6*REG_OFFSET)
++#define OFS_RS232_INPUT (6*REG_OFFSET)
++#define OFS_SCRATCH_PAD (7*REG_OFFSET)
++
++#define OFS_DIVISOR_LSB (0*REG_OFFSET)
++#define OFS_DIVISOR_MSB (1*REG_OFFSET)
++
++
++/* memory-mapped read/write of the port */
++#define UART16550_READ(y) (*((volatile u8*)(BASE + y)))
++#define UART16550_WRITE(y, z) ((*((volatile u8*)(BASE + y))) = z)
++
++void
++debugPortInit(u32 baud, u8 data, u8 parity, u8 stop)
++{
++ /* Pull UART out of reset */
++#if CONFIG_AR5315
++ sysRegWrite(AR5315_RESET,
++ sysRegRead(AR5315_RESET) & ~(RESET_UART0));
++#else
++ sysRegWrite(AR531X_RESET,
++ sysRegRead(AR531X_RESET) & ~(AR531X_RESET_UART0));
++#endif
++
++ /* disable interrupts */
++ UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
++ UART16550_WRITE(OFS_INTR_ENABLE, 0);
++
++ /* set up buad rate */
++ {
++ u32 divisor;
++#if CONFIG_AR5315
++ u32 uart_clock_rate = ar531x_apb_frequency();
++#else
++ u32 uart_clock_rate = ar531x_cpu_frequency() / 4;
++#endif
++ u32 base_baud = uart_clock_rate / 16;
++
++ /* set DIAB bit */
++ UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
++
++ /* set divisor */
++ divisor = base_baud / baud;
++ UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
++ UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00)>>8);
++
++ /* clear DIAB bit */
++ UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
++ }
++
++ /* set data format */
++ UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
++}
++
++u8
++getDebugChar(void)
++{
++ if (!serialPortInitialized) {
++ serialPortInitialized = 1;
++ debugPortInit(BAUD_DEFAULT,
++ UART16550_DATA_8BIT,
++ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
++ }
++
++ while((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
++ return UART16550_READ(OFS_RCV_BUFFER);
++}
++
++#if CONFIG_KGDB
++/*
++ * Peek at the most recently received character.
++ * Don't wait for a new character to be received.
++ */
++u8
++peekDebugChar(void)
++{
++ return UART16550_READ(OFS_RCV_BUFFER);
++}
++
++static int kgdbInitialized = 0;
++
++void
++kgdbInit(void)
++{
++#if CONFIG_AR5315
++ sysRegWrite(AR5315_WDC, WDC_IGNORE_EXPIRATION);
++#else
++ sysRegWrite(AR531X_WD_CTRL, AR531X_WD_CTRL_IGNORE_EXPIRATION);
++#endif
++
++ if (!kgdbInitialized) {
++ printk("Setting debug traps - please connect the remote debugger.\n");
++ set_debug_traps();
++ kgdbInitialized = 1;
++ }
++ breakpoint();
++}
++
++int
++kgdbEnabled(void)
++{
++ return kgdbInitialized;
++}
++
++#define DEBUG_CHAR '\001';
++
++int
++kgdbInterrupt(void)
++{
++ if (!kgdbInitialized) {
++ return 0;
++ }
++
++ /*
++ * Try to avoid swallowing too much input: Only consume
++ * a character if nothing new has arrived. Yes, there's
++ * still a small hole here, and we may lose an input
++ * character now and then.
++ */
++ if (UART16550_READ(OFS_LINE_STATUS) & 1) {
++ return 0;
++ } else {
++ return UART16550_READ(OFS_RCV_BUFFER) == DEBUG_CHAR;
++ }
++}
++#endif
++
++
++void
++putDebugChar(char byte)
++{
++ if (!serialPortInitialized) {
++ serialPortInitialized = 1;
++ debugPortInit(BAUD_DEFAULT,
++ UART16550_DATA_8BIT,
++ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
++ }
++
++ while ((UART16550_READ(OFS_LINE_STATUS) &0x20) == 0);
++ UART16550_WRITE(OFS_SEND_BUFFER, byte);
++ }
++#endif /* CONFIG_EARLY_PRINTK_HACK || CONFIG_KGDB */
+diff -urN linux-mips/arch/mips/ar531x/ar531xgpio.c mips-linux-2.4.25/arch/mips/ar531x/ar531xgpio.c
+--- linux-mips/arch/mips/ar531x/ar531xgpio.c 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531xgpio.c 2005-12-30 17:26:30.606883840 +0000
+@@ -0,0 +1,147 @@
++/*
++ * 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.
++ */
++
++/*
++ * Support for GPIO -- General Purpose Input/Output Pins
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/signal.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++
++#include "ar531xlnx.h"
++
++/* GPIO Interrupt Support */
++
++/* Turn on the specified AR531X_GPIO_IRQ interrupt */
++static unsigned int
++ar531x_gpio_intr_startup(unsigned int irq)
++{
++ ar531x_gpio_intr_enable(irq);
++ return 0;
++}
++
++/* Turn off the specified AR531X_GPIO_IRQ interrupt */
++static void
++ar531x_gpio_intr_shutdown(unsigned int irq)
++{
++ ar531x_gpio_intr_disable(irq);
++}
++
++u32 gpioIntMask = 0;
++
++/* Enable the specified AR531X_GPIO_IRQ interrupt */
++void
++ar531x_gpio_intr_enable(unsigned int irq)
++{
++ u32 reg;
++ int gpio;
++
++#ifndef CONFIG_AR5315
++ gpio = irq - AR531X_GPIO_IRQ_BASE;
++ gpioIntMask |= gpio;
++
++ reg = sysRegRead(AR531X_GPIO_CR);
++ reg &= ~(GPIO_CR_M(gpio) | GPIO_CR_UART(gpio) | GPIO_CR_INT(gpio));
++ reg |= GPIO_CR_I(gpio);
++ reg |= GPIO_CR_INT(gpio);
++
++ sysRegWrite(AR531X_GPIO_CR, reg);
++ (void)sysRegRead(AR531X_GPIO_CR); /* flush to hardware */
++#endif
++}
++
++/* Disable the specified AR531X_GPIO_IRQ interrupt */
++void
++ar531x_gpio_intr_disable(unsigned int irq)
++{
++ u32 reg;
++ int gpio;
++
++#ifndef CONFIG_AR5315
++ gpio = irq - AR531X_GPIO_IRQ_BASE;
++ reg = sysRegRead(AR531X_GPIO_CR);
++ reg &= ~(GPIO_CR_M(gpio) | GPIO_CR_UART(gpio) | GPIO_CR_INT(gpio));
++ reg |= GPIO_CR_I(gpio);
++ /* No GPIO_CR_INT bit */
++
++ sysRegWrite(AR531X_GPIO_CR, reg);
++ (void)sysRegRead(AR531X_GPIO_CR); /* flush to hardware */
++
++ gpioIntMask &= ~gpio;
++#endif
++}
++
++static void
++ar531x_gpio_intr_ack(unsigned int irq)
++{
++ ar531x_gpio_intr_disable(irq);
++}
++
++static void
++ar531x_gpio_intr_end(unsigned int irq)
++{
++ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
++ ar531x_gpio_intr_enable(irq);
++}
++
++static void
++ar531x_gpio_intr_set_affinity(unsigned int irq, unsigned long mask)
++{
++ /* Only 1 CPU; ignore affinity request */
++}
++
++int ar531x_gpio_irq_base;
++
++struct hw_interrupt_type ar531x_gpio_intr_controller = {
++ "AR531X GPIO",
++ ar531x_gpio_intr_startup,
++ ar531x_gpio_intr_shutdown,
++ ar531x_gpio_intr_enable,
++ ar531x_gpio_intr_disable,
++ ar531x_gpio_intr_ack,
++ ar531x_gpio_intr_end,
++ ar531x_gpio_intr_set_affinity,
++};
++
++void
++ar531x_gpio_intr_init(int irq_base)
++{
++ int i;
++
++ for (i = irq_base; i < irq_base + AR531X_GPIO_IRQ_COUNT; i++) {
++ irq_desc[i].status = IRQ_DISABLED;
++ irq_desc[i].action = NULL;
++ irq_desc[i].depth = 1;
++ irq_desc[i].handler = &ar531x_gpio_intr_controller;
++ }
++
++ ar531x_gpio_irq_base = irq_base;
++}
++
++/* ARGSUSED */
++void
++spurious_gpio_handler(int cpl, void *dev_id, struct pt_regs *regs)
++{
++ u32 gpioDataIn;
++#if CONFIG_AR5315
++ gpioDataIn = sysRegRead(AR5315_GPIO_DI) & gpioIntMask;
++#else
++ gpioDataIn = sysRegRead(AR531X_GPIO_DI) & gpioIntMask;
++#endif
++
++ printk("spurious_gpio_handler: 0x%x di=0x%8.8x gpioIntMask=0x%8.8x\n",
++ cpl, gpioDataIn, gpioIntMask);
++}
++
++struct irqaction spurious_gpio =
++ {spurious_gpio_handler, SA_INTERRUPT, 0, "spurious_gpio",
++ NULL, NULL};
++
+diff -urN linux-mips/arch/mips/ar531x/ar531x.h mips-linux-2.4.25/arch/mips/ar531x/ar531x.h
+--- linux-mips/arch/mips/ar531x/ar531x.h 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531x.h 2005-12-30 17:26:30.605883992 +0000
+@@ -0,0 +1,1018 @@
++/*
++ * 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.
++ */
++
++#ifndef AR531X_H
++#define AR531X_H 1
++
++#ifndef CONFIG_AR5315
++
++#include <asm/addrspace.h>
++
++/* Address Map */
++#define AR531X_WLAN0 0x18000000
++#define AR531X_WLAN1 0x18500000
++#define AR531X_ENET0 0x18100000
++#define AR531X_ENET1 0x18200000
++#define AR531X_SDRAMCTL 0x18300000
++#define AR531X_FLASHCTL 0x18400000
++#define AR531X_APBBASE 0x1c000000
++#define AR531X_FLASH 0x1e000000
++#define AR531X_UART0 0xbc000003 /* UART MMR */
++
++/*
++ * AR531X_NUM_ENET_MAC defines the number of ethernet MACs that
++ * should be considered available. The AR5312 supports 2 enet MACS,
++ * even though many reference boards only actually use 1 of them
++ * (i.e. Only MAC 0 is actually connected to an enet PHY or PHY switch.
++ * The AR2312 supports 1 enet MAC.
++ */
++#define AR531X_NUM_ENET_MAC 2
++
++/*
++ * Need these defines to determine true number of ethernet MACs
++ */
++#define AR5212_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
++#define AR5212_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
++#define AR5212_AR2313_REV8 0x0058 /* AR2313 WMAC (AP43-030) */
++#define AR531X_RADIO_MASK_OFF 0xc8
++#define AR531X_RADIO0_MASK 0x0003
++#define AR531X_RADIO1_MASK 0x000c
++#define AR531X_RADIO1_S 2
++
++/*
++ * AR531X_NUM_WMAC defines the number of Wireless MACs that\
++ * should be considered available.
++ */
++#define AR531X_NUM_WMAC 2
++
++/* Reset/Timer Block Address Map */
++#define AR531X_RESETTMR (AR531X_APBBASE + 0x3000)
++#define AR531X_TIMER (AR531X_RESETTMR + 0x0000) /* countdown timer */
++#define AR531X_WD_CTRL (AR531X_RESETTMR + 0x0008) /* watchdog cntrl */
++#define AR531X_WD_TIMER (AR531X_RESETTMR + 0x000c) /* watchdog timer */
++#define AR531X_ISR (AR531X_RESETTMR + 0x0010) /* Intr Status Reg */
++#define AR531X_IMR (AR531X_RESETTMR + 0x0014) /* Intr Mask Reg */
++#define AR531X_RESET (AR531X_RESETTMR + 0x0020)
++#define AR5312_CLOCKCTL1 (AR531X_RESETTMR + 0x0064)
++#define AR5312_SCRATCH (AR531X_RESETTMR + 0x006c)
++#define AR531X_PROCADDR (AR531X_RESETTMR + 0x0070)
++#define AR531X_PROC1 (AR531X_RESETTMR + 0x0074)
++#define AR531X_DMAADDR (AR531X_RESETTMR + 0x0078)
++#define AR531X_DMA1 (AR531X_RESETTMR + 0x007c)
++#define AR531X_ENABLE (AR531X_RESETTMR + 0x0080) /* interface enb */
++#define AR531X_REV (AR531X_RESETTMR + 0x0090) /* revision */
++
++/* AR531X_WD_CTRL register bit field definitions */
++#define AR531X_WD_CTRL_IGNORE_EXPIRATION 0x0000
++#define AR531X_WD_CTRL_NMI 0x0001
++#define AR531X_WD_CTRL_RESET 0x0002
++
++/* AR531X_ISR register bit field definitions */
++#define AR531X_ISR_NONE 0x0000
++#define AR531X_ISR_TIMER 0x0001
++#define AR531X_ISR_AHBPROC 0x0002
++#define AR531X_ISR_AHBDMA 0x0004
++#define AR531X_ISR_GPIO 0x0008
++#define AR531X_ISR_UART0 0x0010
++#define AR531X_ISR_UART0DMA 0x0020
++#define AR531X_ISR_WD 0x0040
++#define AR531X_ISR_LOCAL 0x0080
++
++/* AR531X_RESET register bit field definitions */
++#define AR531X_RESET_SYSTEM 0x00000001 /* cold reset full system */
++#define AR531X_RESET_PROC 0x00000002 /* cold reset MIPS core */
++#define AR531X_RESET_WLAN0 0x00000004 /* cold reset WLAN MAC and BB */
++#define AR531X_RESET_EPHY0 0x00000008 /* cold reset ENET0 phy */
++#define AR531X_RESET_EPHY1 0x00000010 /* cold reset ENET1 phy */
++#define AR531X_RESET_ENET0 0x00000020 /* cold reset ENET0 mac */
++#define AR531X_RESET_ENET1 0x00000040 /* cold reset ENET1 mac */
++#define AR531X_RESET_UART0 0x00000100 /* cold reset UART0 (high speed) */
++#define AR531X_RESET_WLAN1 0x00000200 /* cold reset WLAN MAC/BB */
++#define AR531X_RESET_APB 0x00000400 /* cold reset APB (ar5312) */
++#define AR531X_RESET_WARM_PROC 0x00001000 /* warm reset MIPS core */
++#define AR531X_RESET_WARM_WLAN0_MAC 0x00002000 /* warm reset WLAN0 MAC */
++#define AR531X_RESET_WARM_WLAN0_BB 0x00004000 /* warm reset WLAN0 BaseBand */
++#define AR531X_RESET_NMI 0x00010000 /* send an NMI to the processor */
++#define AR531X_RESET_WARM_WLAN1_MAC 0x00020000 /* warm reset WLAN1 mac */
++#define AR531X_RESET_WARM_WLAN1_BB 0x00040000 /* warm reset WLAN1 baseband */
++#define AR531X_RESET_LOCAL_BUS 0x00080000 /* reset local bus */
++#define AR531X_RESET_WDOG 0x00100000 /* last reset was a watchdog */
++
++#define AR531X_RESET_WMAC0_BITS \
++ AR531X_RESET_WLAN0 |\
++ AR531X_RESET_WARM_WLAN0_MAC |\
++ AR531X_RESET_WARM_WLAN0_BB
++
++#define AR531X_RESERT_WMAC1_BITS \
++ AR531X_RESET_WLAN1 |\
++ AR531X_RESET_WARM_WLAN1_MAC |\
++ AR531X_RESET_WARM_WLAN1_BB
++
++/* AR5312_CLOCKCTL1 register bit field definitions */
++#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030
++#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4
++#define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00
++#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8
++#define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000
++
++/* Valid for AR5312 and AR2312 */
++#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030
++#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4
++#define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00
++#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8
++#define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000
++
++/* Valid for AR2313 */
++#define AR2313_CLOCKCTL1_PREDIVIDE_MASK 0x00003000
++#define AR2313_CLOCKCTL1_PREDIVIDE_SHIFT 12
++#define AR2313_CLOCKCTL1_MULTIPLIER_MASK 0x001f0000
++#define AR2313_CLOCKCTL1_MULTIPLIER_SHIFT 16
++#define AR2313_CLOCKCTL1_DOUBLER_MASK 0x00000000
++
++
++/* AR531X_ENABLE register bit field definitions */
++#define AR531X_ENABLE_WLAN0 0x0001
++#define AR531X_ENABLE_ENET0 0x0002
++#define AR531X_ENABLE_ENET1 0x0004
++#define AR531X_ENABLE_UART_AND_WLAN1_PIO 0x0008 /* UART, and WLAN1 PIOs */
++#define AR531X_ENABLE_WLAN1_DMA 0x0010 /* WLAN1 DMAs */
++#define AR531X_ENABLE_WLAN1 \
++ (AR531X_ENABLE_UART_AND_WLAN1_PIO | AR531X_ENABLE_WLAN1_DMA)
++
++/* AR531X_REV register bit field definitions */
++#define AR531X_REV_WMAC_MAJ 0xf000
++#define AR531X_REV_WMAC_MAJ_S 12
++#define AR531X_REV_WMAC_MIN 0x0f00
++#define AR531X_REV_WMAC_MIN_S 8
++#define AR531X_REV_MAJ 0x00f0
++#define AR531X_REV_MAJ_S 4
++#define AR531X_REV_MIN 0x000f
++#define AR531X_REV_MIN_S 0
++#define AR531X_REV_CHIP (REV_MAJ|REV_MIN)
++
++/* Major revision numbers, bits 7..4 of Revision ID register */
++#define AR531X_REV_MAJ_AR5312 0x4
++#define AR531X_REV_MAJ_AR2313 0x5
++
++/* Minor revision numbers, bits 3..0 of Revision ID register */
++#define AR5312_REV_MIN_DUAL 0x0 /* Dual WLAN version */
++#define AR5312_REV_MIN_SINGLE 0x1 /* Single WLAN version */
++
++/* AR531X_FLASHCTL register bit field definitions */
++#define FLASHCTL_IDCY 0x0000000f /* Idle cycle turn around time */
++#define FLASHCTL_IDCY_S 0
++#define FLASHCTL_WST1 0x000003e0 /* Wait state 1 */
++#define FLASHCTL_WST1_S 5
++#define FLASHCTL_RBLE 0x00000400 /* Read byte lane enable */
++#define FLASHCTL_WST2 0x0000f800 /* Wait state 2 */
++#define FLASHCTL_WST2_S 11
++#define FLASHCTL_AC 0x00070000 /* Flash address check (added) */
++#define FLASHCTL_AC_S 16
++#define FLASHCTL_AC_128K 0x00000000
++#define FLASHCTL_AC_256K 0x00010000
++#define FLASHCTL_AC_512K 0x00020000
++#define FLASHCTL_AC_1M 0x00030000
++#define FLASHCTL_AC_2M 0x00040000
++#define FLASHCTL_AC_4M 0x00050000
++#define FLASHCTL_AC_8M 0x00060000
++#define FLASHCTL_AC_RES 0x00070000 /* 16MB is not supported */
++#define FLASHCTL_E 0x00080000 /* Flash bank enable (added) */
++#define FLASHCTL_BUSERR 0x01000000 /* Bus transfer error status flag */
++#define FLASHCTL_WPERR 0x02000000 /* Write protect error status flag */
++#define FLASHCTL_WP 0x04000000 /* Write protect */
++#define FLASHCTL_BM 0x08000000 /* Burst mode */
++#define FLASHCTL_MW 0x30000000 /* Memory width */
++#define FLASHCTL_MWx8 0x00000000 /* Memory width x8 */
++#define FLASHCTL_MWx16 0x10000000 /* Memory width x16 */
++#define FLASHCTL_MWx32 0x20000000 /* Memory width x32 (not supported) */
++#define FLASHCTL_ATNR 0x00000000 /* Access type == no retry */
++#define FLASHCTL_ATR 0x80000000 /* Access type == retry every */
++#define FLASHCTL_ATR4 0xc0000000 /* Access type == retry every 4 */
++
++/* ARM Flash Controller -- 3 flash banks with either x8 or x16 devices. */
++#define AR531X_FLASHCTL0 (AR531X_FLASHCTL + 0x00)
++#define AR531X_FLASHCTL1 (AR531X_FLASHCTL + 0x04)
++#define AR531X_FLASHCTL2 (AR531X_FLASHCTL + 0x08)
++
++/* ARM SDRAM Controller -- just enough to determine memory size */
++#define AR531X_MEM_CFG1 (AR531X_SDRAMCTL + 0x04)
++#define MEM_CFG1_AC0 0x00000700 /* bank 0: SDRAM addr check (added) */
++#define MEM_CFG1_AC0_S 8
++#define MEM_CFG1_AC1 0x00007000 /* bank 1: SDRAM addr check (added) */
++#define MEM_CFG1_AC1_S 12
++
++/* GPIO Address Map */
++#define AR531X_GPIO (AR531X_APBBASE + 0x2000)
++#define AR531X_GPIO_DO (AR531X_GPIO + 0x00) /* output register */
++#define AR531X_GPIO_DI (AR531X_GPIO + 0x04) /* intput register */
++#define AR531X_GPIO_CR (AR531X_GPIO + 0x08) /* control register */
++
++/* GPIO Control Register bit field definitions */
++#define GPIO_CR_M(x) (1 << (x)) /* mask for i/o */
++#define GPIO_CR_O(x) (0 << (x)) /* mask for output */
++#define GPIO_CR_I(x) (1 << (x)) /* mask for input */
++#define GPIO_CR_INT(x) (1 << ((x)+8)) /* mask for interrupt */
++#define GPIO_CR_UART(x) (1 << ((x)+16)) /* uart multiplex */
++
++
++typedef unsigned int AR531X_REG;
++
++#define sysRegRead(phys) \
++ (*(volatile AR531X_REG *)PHYS_TO_K1(phys))
++
++#define sysRegWrite(phys, val) \
++ ((*(volatile AR531X_REG *)PHYS_TO_K1(phys)) = (val))
++
++
++/*
++ * This is board-specific data that is stored in a "fixed" location in flash.
++ * It is shared across operating systems, so it should not be changed lightly.
++ * The main reason we need it is in order to extract the ethernet MAC
++ * address(es).
++ */
++struct ar531x_boarddata {
++ u32 magic; /* board data is valid */
++#define AR531X_BD_MAGIC 0x35333131 /* "5311", for all 531x platforms */
++ u16 cksum; /* checksum (starting with BD_REV 2) */
++ u16 rev; /* revision of this struct */
++#define BD_REV 4
++ char boardName[64]; /* Name of board */
++ u16 major; /* Board major number */
++ u16 minor; /* Board minor number */
++ u32 config; /* Board configuration */
++#define BD_ENET0 0x00000001 /* ENET0 is stuffed */
++#define BD_ENET1 0x00000002 /* ENET1 is stuffed */
++#define BD_UART1 0x00000004 /* UART1 is stuffed */
++#define BD_UART0 0x00000008 /* UART0 is stuffed (dma) */
++#define BD_RSTFACTORY 0x00000010 /* Reset factory defaults stuffed */
++#define BD_SYSLED 0x00000020 /* System LED stuffed */
++#define BD_EXTUARTCLK 0x00000040 /* External UART clock */
++#define BD_CPUFREQ 0x00000080 /* cpu freq is valid in nvram */
++#define BD_SYSFREQ 0x00000100 /* sys freq is set in nvram */
++#define BD_WLAN0 0x00000200 /* Enable WLAN0 */
++#define BD_MEMCAP 0x00000400 /* CAP SDRAM @ memCap for testing */
++#define BD_DISWATCHDOG 0x00000800 /* disable system watchdog */
++#define BD_WLAN1 0x00001000 /* Enable WLAN1 (ar5212) */
++#define BD_ISCASPER 0x00002000 /* FLAG for AR2312 */
++#define BD_WLAN0_2G_EN 0x00004000 /* FLAG for radio0_2G */
++#define BD_WLAN0_5G_EN 0x00008000 /* FLAG for radio0_2G */
++#define BD_WLAN1_2G_EN 0x00020000 /* FLAG for radio0_2G */
++#define BD_WLAN1_5G_EN 0x00040000 /* FLAG for radio0_2G */
++ u16 resetConfigGpio; /* Reset factory GPIO pin */
++ u16 sysLedGpio; /* System LED GPIO pin */
++
++ u32 cpuFreq; /* CPU core frequency in Hz */
++ u32 sysFreq; /* System frequency in Hz */
++ u32 cntFreq; /* Calculated C0_COUNT frequency */
++
++ u8 wlan0Mac[6];
++ u8 enet0Mac[6];
++ u8 enet1Mac[6];
++
++ u16 pciId; /* Pseudo PCIID for common code */
++ u16 memCap; /* cap bank1 in MB */
++
++ /* version 3 */
++ u8 wlan1Mac[6]; /* (ar5212) */
++};
++
++#else
++
++/*
++ * Address map
++ */
++#define AR5315_SDRAM0 0x00000000 /* DRAM */
++#define AR5315_SPI_READ 0x08000000 /* SPI FLASH */
++#define AR5315_WLAN0 0xB0000000 /* Wireless MMR */
++#define AR5315_PCI 0xB0100000 /* PCI MMR */
++#define AR5315_SDRAMCTL 0xB0300000 /* SDRAM MMR */
++#define AR5315_LOCAL 0xB0400000 /* LOCAL BUS MMR */
++#define AR5315_ENET0 0xB0500000 /* ETHERNET MMR */
++#define AR5315_DSLBASE 0xB1000000 /* RESET CONTROL MMR */
++#define AR5315_UART0 0xB1100003 /* UART MMR */
++#define AR5315_SPI 0xB1300000 /* SPI FLASH MMR */
++#define AR5315_FLASHBT 0xBfc00000 /* ro boot alias to FLASH */
++#define AR5315_RAM1 0x40000000 /* ram alias */
++#define AR5315_PCIEXT 0x80000000 /* pci external */
++#define AR5315_RAM2 0xc0000000 /* ram alias */
++#define AR5315_RAM3 0xe0000000 /* ram alias */
++
++/*
++ * Reset Register
++ */
++#define AR5315_COLD_RESET (AR5315_DSLBASE + 0x0000)
++
++/* Cold Reset */
++#define RESET_COLD_AHB 0x00000001
++#define RESET_COLD_APB 0x00000002
++#define RESET_COLD_CPU 0x00000004
++#define RESET_COLD_CPUWARM 0x00000008
++#define RESET_SYSTEM (RESET_COLD_CPU | RESET_COLD_APB | RESET_COLD_AHB) /* full system */
++
++/* Warm Reset */
++
++#define AR5315_RESET (AR5315_DSLBASE + 0x0004)
++
++#define RESET_WARM_WLAN0_MAC 0x00000001 /* warm reset WLAN0 MAC */
++#define RESET_WARM_WLAN0_BB 0x00000002 /* warm reset WLAN0 BaseBand */
++#define RESET_MPEGTS_RSVD 0x00000004 /* warm reset MPEG-TS */
++#define RESET_PCIDMA 0x00000008 /* warm reset PCI ahb/dma */
++#define RESET_MEMCTL 0x00000010 /* warm reset memory controller */
++#define RESET_LOCAL 0x00000020 /* warm reset local bus */
++#define RESET_I2C_RSVD 0x00000040 /* warm reset I2C bus */
++#define RESET_SPI 0x00000080 /* warm reset SPI interface */
++#define RESET_UART0 0x00000100 /* warm reset UART0 */
++#define RESET_IR_RSVD 0x00000200 /* warm reset IR interface */
++#define RESET_EPHY0 0x00000400 /* cold reset ENET0 phy */
++#define RESET_ENET0 0x00000800 /* cold reset ENET0 mac */
++
++/*
++ * AHB master arbitration control
++ */
++#define AR5315_AHB_ARB_CTL (AR5315_DSLBASE + 0x0008)
++
++#define ARB_CPU 0x00000001 /* CPU, default */
++#define ARB_WLAN 0x00000002 /* WLAN */
++#define ARB_MPEGTS_RSVD 0x00000004 /* MPEG-TS */
++#define ARB_LOCAL 0x00000008 /* LOCAL */
++#define ARB_PCI 0x00000010 /* PCI */
++#define ARB_ETHERNET 0x00000020 /* Ethernet */
++#define ARB_RETRY 0x00000100 /* retry policy, debug only */
++
++/*
++ * Config Register
++ */
++#define AR5315_ENDIAN_CTL (AR5315_DSLBASE + 0x000c)
++
++#define CONFIG_AHB 0x00000001 /* EC - AHB bridge endianess */
++#define CONFIG_WLAN 0x00000002 /* WLAN byteswap */
++#define CONFIG_MPEGTS_RSVD 0x00000004 /* MPEG-TS byteswap */
++#define CONFIG_PCI 0x00000008 /* PCI byteswap */
++#define CONFIG_MEMCTL 0x00000010 /* Memory controller endianess */
++#define CONFIG_LOCAL 0x00000020 /* Local bus byteswap */
++#define CONFIG_ETHERNET 0x00000040 /* Ethernet byteswap */
++
++#define CONFIG_MERGE 0x00000200 /* CPU write buffer merge */
++#define CONFIG_CPU 0x00000400 /* CPU big endian */
++#define CONFIG_PCIAHB 0x00000800
++#define CONFIG_PCIAHB_BRIDGE 0x00001000
++#define CONFIG_SPI 0x00008000 /* SPI byteswap */
++#define CONFIG_CPU_DRAM 0x00010000
++#define CONFIG_CPU_PCI 0x00020000
++#define CONFIG_CPU_MMR 0x00040000
++#define CONFIG_BIG 0x00000400
++
++
++/*
++ * NMI control
++ */
++#define AR5315_NMI_CTL (AR5315_DSLBASE + 0x0010)
++
++#define NMI_EN 1
++
++/*
++ * Revision Register - Initial value is 0x3010 (WMAC 3.0, AR531X 1.0).
++ */
++#define AR5315_SREV (AR5315_DSLBASE + 0x0014)
++
++#define REV_MAJ 0x00f0
++#define REV_MAJ_S 4
++#define REV_MIN 0x000f
++#define REV_MIN_S 0
++#define REV_CHIP (REV_MAJ|REV_MIN)
++
++/*
++ * Interface Enable
++ */
++#define AR5315_IF_CTL (AR5315_DSLBASE + 0x0018)
++
++#define IF_MASK 0x00000007
++#define IF_DISABLED 0
++#define IF_PCI 1
++#define IF_TS_LOCAL 2
++#define IF_ALL 3 /* only for emulation with separate pins */
++#define IF_LOCAL_HOST 0x00000008
++#define IF_PCI_HOST 0x00000010
++#define IF_PCI_INTR 0x00000020
++#define IF_PCI_CLK_MASK 0x00030000
++#define IF_PCI_CLK_INPUT 0
++#define IF_PCI_CLK_OUTPUT_LOW 1
++#define IF_PCI_CLK_OUTPUT_CLK 2
++#define IF_PCI_CLK_OUTPUT_HIGH 3
++#define IF_PCI_CLK_SHIFT 16
++
++
++/* Major revision numbers, bits 7..4 of Revision ID register */
++#define REV_MAJ_AR5311 0x01
++#define REV_MAJ_AR5312 0x04
++#define REV_MAJ_AR5315 0x0B
++
++/*
++ * APB Interrupt control
++ */
++
++#define AR5315_ISR (AR5315_DSLBASE + 0x0020)
++#define AR5315_IMR (AR5315_DSLBASE + 0x0024)
++#define AR5315_GISR (AR5315_DSLBASE + 0x0028)
++
++#define ISR_UART0 0x0001 /* high speed UART */
++#define ISR_I2C_RSVD 0x0002 /* I2C bus */
++#define ISR_SPI 0x0004 /* SPI bus */
++#define ISR_AHB 0x0008 /* AHB error */
++#define ISR_APB 0x0010 /* APB error */
++#define ISR_TIMER 0x0020 /* timer */
++#define ISR_GPIO 0x0040 /* GPIO */
++#define ISR_WD 0x0080 /* watchdog */
++#define ISR_IR_RSVD 0x0100 /* IR */
++
++#define IMR_UART0 ISR_UART0
++#define IMR_I2C_RSVD ISR_I2C_RSVD
++#define IMR_SPI ISR_SPI
++#define IMR_AHB ISR_AHB
++#define IMR_APB ISR_APB
++#define IMR_TIMER ISR_TIMER
++#define IMR_GPIO ISR_GPIO
++#define IMR_WD ISR_WD
++#define IMR_IR_RSVD ISR_IR_RSVD
++
++#define GISR_MISC 0x0001
++#define GISR_WLAN0 0x0002
++#define GISR_MPEGTS_RSVD 0x0004
++#define GISR_LOCALPCI 0x0008
++#define GISR_WMACPOLL 0x0010
++#define GISR_TIMER 0x0020
++#define GISR_ETHERNET 0x0040
++
++/*
++ * Interrupt routing from IO to the processor IP bits
++ * Define our inter mask and level
++ */
++#define AR5315_INTR_MISCIO SR_IBIT3
++#define AR5315_INTR_WLAN0 SR_IBIT4
++#define AR5315_INTR_ENET0 SR_IBIT5
++#define AR5315_INTR_LOCALPCI SR_IBIT6
++#define AR5315_INTR_WMACPOLL SR_IBIT7
++#define AR5315_INTR_COMPARE SR_IBIT8
++
++/*
++ * Timers
++ */
++#define AR5315_TIMER (AR5315_DSLBASE + 0x0030)
++#define AR5315_RELOAD (AR5315_DSLBASE + 0x0034)
++#define AR5315_WD (AR5315_DSLBASE + 0x0038)
++#define AR5315_WDC (AR5315_DSLBASE + 0x003c)
++
++#define WDC_RESET 0x00000002 /* reset on watchdog */
++#define WDC_NMI 0x00000001 /* NMI on watchdog */
++#define WDC_IGNORE_EXPIRATION 0x00000000
++
++/*
++ * Interface Debug
++ */
++#define AR531X_FLASHDBG (AR531X_RESETTMR + 0x0040)
++#define AR531X_MIIDBG (AR531X_RESETTMR + 0x0044)
++
++
++/*
++ * CPU Performance Counters
++ */
++#define AR5315_PERFCNT0 (AR5315_DSLBASE + 0x0048)
++#define AR5315_PERFCNT1 (AR5315_DSLBASE + 0x004c)
++
++#define PERF_DATAHIT 0x0001 /* Count Data Cache Hits */
++#define PERF_DATAMISS 0x0002 /* Count Data Cache Misses */
++#define PERF_INSTHIT 0x0004 /* Count Instruction Cache Hits */
++#define PERF_INSTMISS 0x0008 /* Count Instruction Cache Misses */
++#define PERF_ACTIVE 0x0010 /* Count Active Processor Cycles */
++#define PERF_WBHIT 0x0020 /* Count CPU Write Buffer Hits */
++#define PERF_WBMISS 0x0040 /* Count CPU Write Buffer Misses */
++
++#define PERF_EB_ARDY 0x0001 /* Count EB_ARdy signal */
++#define PERF_EB_AVALID 0x0002 /* Count EB_AValid signal */
++#define PERF_EB_WDRDY 0x0004 /* Count EB_WDRdy signal */
++#define PERF_EB_RDVAL 0x0008 /* Count EB_RdVal signal */
++#define PERF_VRADDR 0x0010 /* Count valid read address cycles */
++#define PERF_VWADDR 0x0020 /* Count valid write address cycles */
++#define PERF_VWDATA 0x0040 /* Count valid write data cycles */
++
++/*
++ * AHB Error Reporting.
++ */
++#define AR5315_AHB_ERR0 (AR5315_DSLBASE + 0x0050) /* error */
++#define AR5315_AHB_ERR1 (AR5315_DSLBASE + 0x0054) /* haddr */
++#define AR5315_AHB_ERR2 (AR5315_DSLBASE + 0x0058) /* hwdata */
++#define AR5315_AHB_ERR3 (AR5315_DSLBASE + 0x005c) /* hrdata */
++#define AR5315_AHB_ERR4 (AR5315_DSLBASE + 0x0060) /* status */
++
++#define AHB_ERROR_DET 1 /* AHB Error has been detected, */
++ /* write 1 to clear all bits in ERR0 */
++#define AHB_ERROR_OVR 2 /* AHB Error overflow has been detected */
++#define AHB_ERROR_WDT 4 /* AHB Error due to wdt instead of hresp */
++
++#define PROCERR_HMAST 0x0000000f
++#define PROCERR_HMAST_DFLT 0
++#define PROCERR_HMAST_WMAC 1
++#define PROCERR_HMAST_ENET 2
++#define PROCERR_HMAST_PCIENDPT 3
++#define PROCERR_HMAST_LOCAL 4
++#define PROCERR_HMAST_CPU 5
++#define PROCERR_HMAST_PCITGT 6
++
++#define PROCERR_HMAST_S 0
++#define PROCERR_HWRITE 0x00000010
++#define PROCERR_HSIZE 0x00000060
++#define PROCERR_HSIZE_S 5
++#define PROCERR_HTRANS 0x00000180
++#define PROCERR_HTRANS_S 7
++#define PROCERR_HBURST 0x00000e00
++#define PROCERR_HBURST_S 9
++
++
++
++/*
++ * Clock Control
++ */
++#define AR5315_PLLC_CTL (AR5315_DSLBASE + 0x0064)
++#define AR5315_PLLV_CTL (AR5315_DSLBASE + 0x0068)
++#define AR5315_CPUCLK (AR5315_DSLBASE + 0x006c)
++#define AR5315_AMBACLK (AR5315_DSLBASE + 0x0070)
++#define AR5315_SYNCCLK (AR5315_DSLBASE + 0x0074)
++#define AR5315_DSL_SLEEP_CTL (AR5315_DSLBASE + 0x0080)
++#define AR5315_DSL_SLEEP_DUR (AR5315_DSLBASE + 0x0084)
++
++/* PLLc Control fields */
++#define PLLC_REF_DIV_M 0x00000003
++#define PLLC_REF_DIV_S 0
++#define PLLC_FDBACK_DIV_M 0x0000007C
++#define PLLC_FDBACK_DIV_S 2
++#define PLLC_ADD_FDBACK_DIV_M 0x00000080
++#define PLLC_ADD_FDBACK_DIV_S 7
++#define PLLC_CLKC_DIV_M 0x0001c000
++#define PLLC_CLKC_DIV_S 14
++#define PLLC_CLKM_DIV_M 0x00700000
++#define PLLC_CLKM_DIV_S 20
++
++/* CPU CLK Control fields */
++#define CPUCLK_CLK_SEL_M 0x00000003
++#define CPUCLK_CLK_SEL_S 0
++#define CPUCLK_CLK_DIV_M 0x0000000c
++#define CPUCLK_CLK_DIV_S 2
++
++/* AMBA CLK Control fields */
++#define AMBACLK_CLK_SEL_M 0x00000003
++#define AMBACLK_CLK_SEL_S 0
++#define AMBACLK_CLK_DIV_M 0x0000000c
++#define AMBACLK_CLK_DIV_S 2
++
++#if defined(COBRA_EMUL)
++#define AR5315_AMBA_CLOCK_RATE 20000000
++#define AR5315_CPU_CLOCK_RATE 40000000
++#else
++#if defined(DEFAULT_PLL)
++#define AR5315_AMBA_CLOCK_RATE 40000000
++#define AR5315_CPU_CLOCK_RATE 40000000
++#else
++#define AR5315_AMBA_CLOCK_RATE 92000000
++#define AR5315_CPU_CLOCK_RATE 184000000
++#endif /* ! DEFAULT_PLL */
++#endif /* ! COBRA_EMUL */
++
++#define AR5315_UART_CLOCK_RATE AR5315_AMBA_CLOCK_RATE
++#define AR5315_SDRAM_CLOCK_RATE AR5315_AMBA_CLOCK_RATE
++
++/*
++ * The UART computes baud rate as:
++ * baud = clock / (16 * divisor)
++ * where divisor is specified as a High Byte (DLM) and a Low Byte (DLL).
++ */
++#define DESIRED_BAUD_RATE 38400
++
++/*
++ * The WATCHDOG value is computed as
++ * 10 seconds * AR531X_WATCHDOG_CLOCK_RATE
++ */
++#define DESIRED_WATCHDOG_SECONDS 10
++#define AR531X_WATCHDOG_TIME \
++ (DESIRED_WATCHDOG_SECONDS * AR531X_WATCHDOG_CLOCK_RATE)
++
++
++#define CLOCKCTL_UART0 0x0010 /* enable UART0 external clock */
++
++
++ /*
++ * Applicable "PCICFG" bits for WLAN(s). Assoc status and LED mode.
++ */
++#define AR531X_PCICFG (AR531X_RESETTMR + 0x00b0)
++#define ASSOC_STATUS_M 0x00000003
++#define ASSOC_STATUS_NONE 0
++#define ASSOC_STATUS_PENDING 1
++#define ASSOC_STATUS_ASSOCIATED 2
++#define LED_MODE_M 0x0000001c
++#define LED_BLINK_THRESHOLD_M 0x000000e0
++#define LED_SLOW_BLINK_MODE 0x00000100
++
++/*
++ * GPIO
++ */
++
++#define AR5315_GPIO_DI (AR5315_DSLBASE + 0x0088)
++#define AR5315_GPIO_DO (AR5315_DSLBASE + 0x0090)
++#define AR5315_GPIO_CR (AR5315_DSLBASE + 0x0098)
++#define AR5315_GPIO_INT (AR5315_DSLBASE + 0x00a0)
++
++#define GPIO_CR_M(x) (1 << (x)) /* mask for i/o */
++#define GPIO_CR_O(x) (1 << (x)) /* output */
++#define GPIO_CR_I(x) (0 << (x)) /* input */
++
++#define GPIO_INT(x,Y) ((x) << (8 * (Y))) /* interrupt enable */
++#define GPIO_INT_M(Y) ((0x3F) << (8 * (Y))) /* mask for int */
++#define GPIO_INT_LVL(x,Y) ((x) << (8 * (Y) + 6)) /* interrupt level */
++#define GPIO_INT_LVL_M(Y) ((0x3) << (8 * (Y) + 6)) /* mask for int level */
++
++#define AR5315_RESET_GPIO 5
++#define AR5315_NUM_GPIO 22
++
++
++/*
++ * PCI Clock Control
++ */
++
++#define AR5315_PCICLK (AR5315_DSLBASE + 0x00a4)
++
++#define PCICLK_INPUT_M 0x3
++#define PCICLK_INPUT_S 0
++
++#define PCICLK_PLLC_CLKM 0
++#define PCICLK_PLLC_CLKM1 1
++#define PCICLK_PLLC_CLKC 2
++#define PCICLK_REF_CLK 3
++
++#define PCICLK_DIV_M 0xc
++#define PCICLK_DIV_S 2
++
++#define PCICLK_IN_FREQ 0
++#define PCICLK_IN_FREQ_DIV_6 1
++#define PCICLK_IN_FREQ_DIV_8 2
++#define PCICLK_IN_FREQ_DIV_10 3
++
++/*
++ * Observation Control Register
++ */
++#define AR5315_OCR (AR5315_DSLBASE + 0x00b0)
++#define OCR_GPIO0_IRIN 0x0040
++#define OCR_GPIO1_IROUT 0x0080
++#define OCR_GPIO3_RXCLR 0x0200
++
++/*
++ * General Clock Control
++ */
++
++#define AR5315_MISCCLK (AR5315_DSLBASE + 0x00b4)
++#define MISCCLK_PLLBYPASS_EN 0x00000001
++#define MISCCLK_PROCREFCLK 0x00000002
++
++/*
++ * SDRAM Controller
++ * - No read or write buffers are included.
++ */
++#define AR5315_MEM_CFG (AR5315_SDRAMCTL + 0x00)
++#define AR5315_MEM_CTRL (AR5315_SDRAMCTL + 0x0c)
++#define AR5315_MEM_REF (AR5315_SDRAMCTL + 0x10)
++
++#define SDRAM_DATA_WIDTH_M 0x00006000
++#define SDRAM_DATA_WIDTH_S 13
++
++#define SDRAM_COL_WIDTH_M 0x00001E00
++#define SDRAM_COL_WIDTH_S 9
++
++#define SDRAM_ROW_WIDTH_M 0x000001E0
++#define SDRAM_ROW_WIDTH_S 5
++
++#define SDRAM_BANKADDR_BITS_M 0x00000018
++#define SDRAM_BANKADDR_BITS_S 3
++
++
++/*
++ * SDRAM Memory Refresh (MEM_REF) value is computed as:
++ * MEMCTL_SREFR = (Tr * hclk_freq) / R
++ * where Tr is max. time of refresh of any single row
++ * R is number of rows in the DRAM
++ * For most 133MHz SDRAM parts, Tr=64ms, R=4096 or 8192
++ */
++#if defined(COBRA_EMUL)
++#define AR5315_SDRAM_MEMORY_REFRESH_VALUE 0x96
++#else
++#if defined(DEFAULT_PLL)
++#define AR5315_SDRAM_MEMORY_REFRESH_VALUE 0x200
++#else
++#define AR5315_SDRAM_MEMORY_REFRESH_VALUE 0x61a
++#endif /* ! DEFAULT_PLL */
++#endif
++
++#if defined(AR5315)
++
++#define AR5315_SDRAM_DDR_SDRAM 0 /* Not DDR SDRAM */
++#define AR5315_SDRAM_DATA_WIDTH 16 /* bits */
++#define AR5315_SDRAM_COL_WIDTH 8
++#define AR5315_SDRAM_ROW_WIDTH 12
++
++#else
++
++#define AR5315_SDRAM_DDR_SDRAM 0 /* Not DDR SDRAM */
++#define AR5315_SDRAM_DATA_WIDTH 16
++#define AR5315_SDRAM_COL_WIDTH 8
++#define AR5315_SDRAM_ROW_WIDTH 12
++
++#endif /* ! AR5315 */
++
++/*
++ * SPI Flash Interface Registers
++ */
++
++#define AR5315_SPI_CTL (AR5315_SPI + 0x00)
++#define AR5315_SPI_OPCODE (AR5315_SPI + 0x04)
++#define AR5315_SPI_DATA (AR5315_SPI + 0x08)
++
++#define SPI_CTL_START 0x00000100
++#define SPI_CTL_BUSY 0x00010000
++#define SPI_CTL_TXCNT_MASK 0x0000000f
++#define SPI_CTL_RXCNT_MASK 0x000000f0
++#define SPI_CTL_TX_RX_CNT_MASK 0x000000ff
++#define SPI_CTL_SIZE_MASK 0x00060000
++
++#define SPI_CTL_CLK_SEL_MASK 0x03000000
++#define SPI_OPCODE_MASK 0x000000ff
++
++/*
++ * PCI-MAC Configuration registers
++ */
++#define PCI_MAC_RC (AR5315_PCI + 0x4000)
++#define PCI_MAC_SCR (AR5315_PCI + 0x4004)
++#define PCI_MAC_INTPEND (AR5315_PCI + 0x4008)
++#define PCI_MAC_SFR (AR5315_PCI + 0x400C)
++#define PCI_MAC_PCICFG (AR5315_PCI + 0x4010)
++#define PCI_MAC_SREV (AR5315_PCI + 0x4020)
++
++#define PCI_MAC_RC_MAC 0x00000001
++#define PCI_MAC_RC_BB 0x00000002
++
++#define PCI_MAC_SCR_SLMODE_M 0x00030000
++#define PCI_MAC_SCR_SLMODE_S 16
++#define PCI_MAC_SCR_SLM_FWAKE 0
++#define PCI_MAC_SCR_SLM_FSLEEP 1
++#define PCI_MAC_SCR_SLM_NORMAL 2
++
++#define PCI_MAC_SFR_SLEEP 0x00000001
++
++#define PCI_MAC_PCICFG_SPWR_DN 0x00010000
++
++
++
++
++/*
++ * PCI Bus Interface Registers
++ */
++#define AR5315_PCI_1MS_REG (AR5315_PCI + 0x0008)
++#define AR5315_PCI_1MS_MASK 0x3FFFF /* # of AHB clk cycles in 1ms */
++
++#define AR5315_PCI_MISC_CONFIG (AR5315_PCI + 0x000c)
++#define AR5315_PCIMISC_TXD_EN 0x00000001 /* Enable TXD for fragments */
++#define AR5315_PCIMISC_CFG_SEL 0x00000002 /* mem or config cycles */
++#define AR5315_PCIMISC_GIG_MASK 0x0000000C /* bits 31-30 for pci req */
++#define AR5315_PCIMISC_RST_MODE 0x00000030
++#define AR5315_PCIRST_INPUT 0x00000000 /* 4:5=0 rst is input */
++#define AR5315_PCIRST_LOW 0x00000010 /* 4:5=1 rst to GND */
++#define AR5315_PCIRST_HIGH 0x00000020 /* 4:5=2 rst to VDD */
++#define AR5315_PCIGRANT_EN 0x00000000 /* 6:7=0 early grant en */
++#define AR5315_PCIGRANT_FRAME 0x00000040 /* 6:7=1 grant waits 4 frame */
++#define AR5315_PCIGRANT_IDLE 0x00000080 /* 6:7=2 grant waits 4 idle */
++#define AR5315_PCIGRANT_GAP 0x00000000 /* 6:7=2 grant waits 4 idle */
++#define AR5315_PCICACHE_DIS 0x00001000 /* PCI external access cache disable */
++
++#define AR5315_PCI_OUT_TSTAMP (AR5315_PCI + 0x0010)
++
++#define AR5315_PCI_UNCACHE_CFG (AR5315_PCI + 0x0014)
++
++#define AR5315_PCI_IN_EN (AR5315_PCI + 0x0100)
++#define AR5315_PCI_IN_EN0 0x01 /* Enable chain 0 */
++#define AR5315_PCI_IN_EN1 0x02 /* Enable chain 1 */
++#define AR5315_PCI_IN_EN2 0x04 /* Enable chain 2 */
++#define AR5315_PCI_IN_EN3 0x08 /* Enable chain 3 */
++
++#define AR5315_PCI_IN_DIS (AR5315_PCI + 0x0104)
++#define AR5315_PCI_IN_DIS0 0x01 /* Disable chain 0 */
++#define AR5315_PCI_IN_DIS1 0x02 /* Disable chain 1 */
++#define AR5315_PCI_IN_DIS2 0x04 /* Disable chain 2 */
++#define AR5315_PCI_IN_DIS3 0x08 /* Disable chain 3 */
++
++#define AR5315_PCI_IN_PTR (AR5315_PCI + 0x0200)
++
++#define AR5315_PCI_OUT_EN (AR5315_PCI + 0x0400)
++#define AR5315_PCI_OUT_EN0 0x01 /* Enable chain 0 */
++
++#define AR5315_PCI_OUT_DIS (AR5315_PCI + 0x0404)
++#define AR5315_PCI_OUT_DIS0 0x01 /* Disable chain 0 */
++
++#define AR5315_PCI_OUT_PTR (AR5315_PCI + 0x0408)
++
++#define AR5315_PCI_INT_STATUS (AR5315_PCI + 0x0500) /* write one to clr */
++#define AR5315_PCI_TXINT 0x00000001 /* Desc In Completed */
++#define AR5315_PCI_TXOK 0x00000002 /* Desc In OK */
++#define AR5315_PCI_TXERR 0x00000004 /* Desc In ERR */
++#define AR5315_PCI_TXEOL 0x00000008 /* Desc In End-of-List */
++#define AR5315_PCI_RXINT 0x00000010 /* Desc Out Completed */
++#define AR5315_PCI_RXOK 0x00000020 /* Desc Out OK */
++#define AR5315_PCI_RXERR 0x00000040 /* Desc Out ERR */
++#define AR5315_PCI_RXEOL 0x00000080 /* Desc Out EOL */
++#define AR5315_PCI_TXOOD 0x00000200 /* Desc In Out-of-Desc */
++#define AR5315_PCI_MASK 0x0000FFFF /* Desc Mask */
++#define AR5315_PCI_EXT_INT 0x02000000
++#define AR5315_PCI_ABORT_INT 0x04000000
++
++#define AR5315_PCI_INT_MASK (AR5315_PCI + 0x0504) /* same as INT_STATUS */
++
++#define AR5315_PCI_INTEN_REG (AR5315_PCI + 0x0508)
++#define AR5315_PCI_INT_DISABLE 0x00 /* disable pci interrupts */
++#define AR5315_PCI_INT_ENABLE 0x01 /* enable pci interrupts */
++
++#define AR5315_PCI_HOST_IN_EN (AR5315_PCI + 0x0800)
++#define AR5315_PCI_HOST_IN_DIS (AR5315_PCI + 0x0804)
++#define AR5315_PCI_HOST_IN_PTR (AR5315_PCI + 0x0810)
++#define AR5315_PCI_HOST_OUT_EN (AR5315_PCI + 0x0900)
++#define AR5315_PCI_HOST_OUT_DIS (AR5315_PCI + 0x0904)
++#define AR5315_PCI_HOST_OUT_PTR (AR5315_PCI + 0x0908)
++
++
++/*
++ * Local Bus Interface Registers
++ */
++#define AR5315_LB_CONFIG (AR5315_LOCAL + 0x0000)
++#define AR5315_LBCONF_OE 0x00000001 /* =1 OE is low-true */
++#define AR5315_LBCONF_CS0 0x00000002 /* =1 first CS is low-true */
++#define AR5315_LBCONF_CS1 0x00000004 /* =1 2nd CS is low-true */
++#define AR5315_LBCONF_RDY 0x00000008 /* =1 RDY is low-true */
++#define AR5315_LBCONF_WE 0x00000010 /* =1 Write En is low-true */
++#define AR5315_LBCONF_WAIT 0x00000020 /* =1 WAIT is low-true */
++#define AR5315_LBCONF_ADS 0x00000040 /* =1 Adr Strobe is low-true */
++#define AR5315_LBCONF_MOT 0x00000080 /* =0 Intel, =1 Motorola */
++#define AR5315_LBCONF_8CS 0x00000100 /* =1 8 bits CS, 0= 16bits */
++#define AR5315_LBCONF_8DS 0x00000200 /* =1 8 bits Data S, 0=16bits */
++#define AR5315_LBCONF_ADS_EN 0x00000400 /* =1 Enable ADS */
++#define AR5315_LBCONF_ADR_OE 0x00000800 /* =1 Adr cap on OE, WE or DS */
++#define AR5315_LBCONF_ADDT_MUX 0x00001000 /* =1 Adr and Data share bus */
++#define AR5315_LBCONF_DATA_OE 0x00002000 /* =1 Data cap on OE, WE, DS */
++#define AR5315_LBCONF_16DATA 0x00004000 /* =1 Data is 16 bits wide */
++#define AR5315_LBCONF_SWAPDT 0x00008000 /* =1 Byte swap data */
++#define AR5315_LBCONF_SYNC 0x00010000 /* =1 Bus synchronous to clk */
++#define AR5315_LBCONF_INT 0x00020000 /* =1 Intr is low true */
++#define AR5315_LBCONF_INT_CTR0 0x00000000 /* GND high-Z, Vdd is high-Z */
++#define AR5315_LBCONF_INT_CTR1 0x00040000 /* GND drive, Vdd is high-Z */
++#define AR5315_LBCONF_INT_CTR2 0x00080000 /* GND high-Z, Vdd drive */
++#define AR5315_LBCONF_INT_CTR3 0x000C0000 /* GND drive, Vdd drive */
++#define AR5315_LBCONF_RDY_WAIT 0x00100000 /* =1 RDY is negative of WAIT */
++#define AR5315_LBCONF_INT_PULSE 0x00200000 /* =1 Interrupt is a pulse */
++#define AR5315_LBCONF_ENABLE 0x00400000 /* =1 Falcon respond to LB */
++
++#define AR5315_LB_CLKSEL (AR5315_LOCAL + 0x0004)
++#define AR5315_LBCLK_EXT 0x0001 /* use external clk for lb */
++
++#define AR5315_LB_1MS (AR5315_LOCAL + 0x0008)
++#define AR5315_LB1MS_MASK 0x3FFFF /* # of AHB clk cycles in 1ms */
++
++#define AR5315_LB_MISCCFG (AR5315_LOCAL + 0x000C)
++#define AR5315_LBM_TXD_EN 0x00000001 /* Enable TXD for fragments */
++#define AR5315_LBM_RX_INTEN 0x00000002 /* Enable LB ints on RX ready */
++#define AR5315_LBM_MBOXWR_INTEN 0x00000004 /* Enable LB ints on mbox wr */
++#define AR5315_LBM_MBOXRD_INTEN 0x00000008 /* Enable LB ints on mbox rd */
++#define AR5315_LMB_DESCSWAP_EN 0x00000010 /* Byte swap desc enable */
++#define AR5315_LBM_TIMEOUT_MASK 0x00FFFF80
++#define AR5315_LBM_TIMEOUT_SHFT 7
++#define AR5315_LBM_PORTMUX 0x07000000
++
++
++#define AR5315_LB_RXTSOFF (AR5315_LOCAL + 0x0010)
++
++#define AR5315_LB_TX_CHAIN_EN (AR5315_LOCAL + 0x0100)
++#define AR5315_LB_TXEN_0 0x01
++#define AR5315_LB_TXEN_1 0x02
++#define AR5315_LB_TXEN_2 0x04
++#define AR5315_LB_TXEN_3 0x08
++
++#define AR5315_LB_TX_CHAIN_DIS (AR5315_LOCAL + 0x0104)
++#define AR5315_LB_TX_DESC_PTR (AR5315_LOCAL + 0x0200)
++
++#define AR5315_LB_RX_CHAIN_EN (AR5315_LOCAL + 0x0400)
++#define AR5315_LB_RXEN 0x01
++
++#define AR5315_LB_RX_CHAIN_DIS (AR5315_LOCAL + 0x0404)
++#define AR5315_LB_RX_DESC_PTR (AR5315_LOCAL + 0x0408)
++
++#define AR5315_LB_INT_STATUS (AR5315_LOCAL + 0x0500)
++#define AR5315_INT_TX_DESC 0x0001
++#define AR5315_INT_TX_OK 0x0002
++#define AR5315_INT_TX_ERR 0x0004
++#define AR5315_INT_TX_EOF 0x0008
++#define AR5315_INT_RX_DESC 0x0010
++#define AR5315_INT_RX_OK 0x0020
++#define AR5315_INT_RX_ERR 0x0040
++#define AR5315_INT_RX_EOF 0x0080
++#define AR5315_INT_TX_TRUNC 0x0100
++#define AR5315_INT_TX_STARVE 0x0200
++#define AR5315_INT_LB_TIMEOUT 0x0400
++#define AR5315_INT_LB_ERR 0x0800
++#define AR5315_INT_MBOX_WR 0x1000
++#define AR5315_INT_MBOX_RD 0x2000
++
++/* Bit definitions for INT MASK are the same as INT_STATUS */
++#define AR5315_LB_INT_MASK (AR5315_LOCAL + 0x0504)
++
++#define AR5315_LB_INT_EN (AR5315_LOCAL + 0x0508)
++#define AR5315_LB_MBOX (AR5315_LOCAL + 0x0600)
++
++
++
++/*
++ * IR Interface Registers
++ */
++#define AR5315_IR_PKTDATA (AR5315_IR + 0x0000)
++
++#define AR5315_IR_PKTLEN (AR5315_IR + 0x07fc) /* 0 - 63 */
++
++#define AR5315_IR_CONTROL (AR5315_IR + 0x0800)
++#define AR5315_IRCTL_TX 0x00000000 /* use as tranmitter */
++#define AR5315_IRCTL_RX 0x00000001 /* use as receiver */
++#define AR5315_IRCTL_SAMPLECLK_MASK 0x00003ffe /* Sample clk divisor mask */
++#define AR5315_IRCTL_SAMPLECLK_SHFT 1
++#define AR5315_IRCTL_OUTPUTCLK_MASK 0x03ffc000 /* Output clk divisor mask */
++#define AR5315_IRCTL_OUTPUTCLK_SHFT 14
++
++#define AR5315_IR_STATUS (AR5315_IR + 0x0804)
++#define AR5315_IRSTS_RX 0x00000001 /* receive in progress */
++#define AR5315_IRSTS_TX 0x00000002 /* transmit in progress */
++
++#define AR5315_IR_CONFIG (AR5315_IR + 0x0808)
++#define AR5315_IRCFG_INVIN 0x00000001 /* invert input polarity */
++#define AR5315_IRCFG_INVOUT 0x00000002 /* invert output polarity */
++#define AR5315_IRCFG_SEQ_START_WIN_SEL 0x00000004 /* 1 => 28, 0 => 7 */
++#define AR5315_IRCFG_SEQ_START_THRESH 0x000000f0 /* */
++#define AR5315_IRCFG_SEQ_END_UNIT_SEL 0x00000100 /* */
++#define AR5315_IRCFG_SEQ_END_UNIT_THRESH 0x00007e00 /* */
++#define AR5315_IRCFG_SEQ_END_WIN_SEL 0x00008000 /* */
++#define AR5315_IRCFG_SEQ_END_WIN_THRESH 0x001f0000 /* */
++#define AR5315_IRCFG_NUM_BACKOFF_WORDS 0x01e00000 /* */
++
++/*
++ * PCI memory constants: Memory area 1 and 2 are the same size -
++ * (twice the PCI_TLB_PAGE_SIZE). The definition of
++ * CPU_TO_PCI_MEM_SIZE is coupled with the TLB setup routine
++ * sysLib.c/sysTlbInit(), in that it assumes that 2 pages of size
++ * PCI_TLB_PAGE_SIZE are set up in the TLB for each PCI memory space.
++ */
++
++#define CPU_TO_PCI_MEM_BASE1 0xE0000000
++#define CPU_TO_PCI_MEM_SIZE1 (2*PCI_TLB_PAGE_SIZE)
++
++
++/* TLB attributes for PCI transactions */
++
++#define PCI_MMU_PAGEMASK 0x00003FFF
++#define MMU_PAGE_UNCACHED 0x00000010
++#define MMU_PAGE_DIRTY 0x00000004
++#define MMU_PAGE_VALID 0x00000002
++#define MMU_PAGE_GLOBAL 0x00000001
++#define PCI_MMU_PAGEATTRIB (MMU_PAGE_UNCACHED|MMU_PAGE_DIRTY|\
++ MMU_PAGE_VALID|MMU_PAGE_GLOBAL)
++#define PCI_MEMORY_SPACE1_VIRT 0xE0000000 /* Used for non-prefet mem */
++#define PCI_MEMORY_SPACE1_PHYS 0x80000000
++#define PCI_TLB_PAGE_SIZE 0x01000000
++#define TLB_HI_MASK 0xFFFFE000
++#define TLB_LO_MASK 0x3FFFFFFF
++#define PAGEMASK_SHIFT 11
++#define TLB_LO_SHIFT 6
++
++#define PCI_MAX_LATENCY 0xFFF /* Max PCI latency */
++
++#define HOST_PCI_DEV_ID 3
++#define HOST_PCI_MBAR0 0x10000000
++#define HOST_PCI_MBAR1 0x20000000
++#define HOST_PCI_MBAR2 0x30000000
++
++#define HOST_PCI_SDRAM_BASEADDR HOST_PCI_MBAR1
++#define PCI_DEVICE_MEM_SPACE 0x800000
++
++
++typedef unsigned int AR531X_REG;
++
++#define sysRegRead(phys) \
++ (*(volatile AR531X_REG *)PHYS_TO_K1(phys))
++
++#define sysRegWrite(phys, val) \
++ ((*(volatile AR531X_REG *)PHYS_TO_K1(phys)) = (val))
++#endif
++
++#endif
+diff -urN linux-mips/arch/mips/ar531x/ar531xintr.S mips-linux-2.4.25/arch/mips/ar531x/ar531xintr.S
+--- linux-mips/arch/mips/ar531x/ar531xintr.S 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531xintr.S 2005-12-30 17:26:31.000823952 +0000
+@@ -0,0 +1,30 @@
++/*
++ * 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.
++ */
++
++#include <asm/asm.h>
++#include <asm/mipsregs.h>
++#include <asm/regdef.h>
++#include <asm/stackframe.h>
++
++/*
++ * Glue code to save registers and get us to the interrupt dispatcher
++ */
++ .text
++ .set noat
++ .align 5
++NESTED(ar531x_interrupt_receive, PT_SIZE, sp)
++ SAVE_ALL
++ CLI
++ .set at
++
++ move a0, sp
++ jal ar531x_irq_dispatch
++
++ j ret_from_irq
++
++ END(ar531x_interrupt_receive)
+diff -urN linux-mips/arch/mips/ar531x/ar531xirq.c mips-linux-2.4.25/arch/mips/ar531x/ar531xirq.c
+--- linux-mips/arch/mips/ar531x/ar531xirq.c 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531xirq.c 2005-12-30 17:26:31.000823952 +0000
+@@ -0,0 +1,442 @@
++/*
++ * 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.
++ */
++
++/*
++ * Interrupt support for AR531X WiSOC.
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/kernel_stat.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/slab.h>
++#include <linux/random.h>
++#include <linux/pm.h>
++#include <linux/delay.h>
++#include <linux/reboot.h>
++
++#include <asm/irq.h>
++#include <asm/mipsregs.h>
++#include <asm/gdb-stub.h>
++
++#include "ar531xlnx.h"
++#include <asm/irq_cpu.h>
++
++extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
++
++static void ar531x_misc_intr_enable(unsigned int irq);
++static void ar531x_misc_intr_disable(unsigned int irq);
++
++/* Turn on the specified AR531X_MISC_IRQ interrupt */
++static unsigned int
++ar531x_misc_intr_startup(unsigned int irq)
++{
++ ar531x_misc_intr_enable(irq);
++ return 0;
++}
++
++/* Turn off the specified AR531X_MISC_IRQ interrupt */
++static void
++ar531x_misc_intr_shutdown(unsigned int irq)
++{
++ ar531x_misc_intr_disable(irq);
++}
++
++/* Enable the specified AR531X_MISC_IRQ interrupt */
++static void
++ar531x_misc_intr_enable(unsigned int irq)
++{
++ unsigned int imr;
++
++#if CONFIG_AR5315
++ imr = sysRegRead(AR5315_IMR);
++ switch(irq)
++ {
++ case AR531X_MISC_IRQ_TIMER:
++ imr |= IMR_TIMER;
++ break;
++
++ case AR531X_MISC_IRQ_AHB_PROC:
++ imr |= IMR_AHB;
++ break;
++
++ case AR531X_MISC_IRQ_AHB_DMA:
++ imr |= 0/* ?? */;
++ break;
++ /*
++ case AR531X_ISR_GPIO:
++ imr |= IMR_GPIO;
++ break;
++ */
++
++ case AR531X_MISC_IRQ_UART0:
++ imr |= IMR_UART0;
++ break;
++
++
++ case AR531X_MISC_IRQ_WATCHDOG:
++ imr |= IMR_WD;
++ break;
++
++ case AR531X_MISC_IRQ_LOCAL:
++ imr |= 0/* ?? */;
++ break;
++
++ }
++ sysRegWrite(AR5315_IMR, imr);
++ imr=sysRegRead(AR5315_IMR); /* flush write buffer */
++ //printk("enable Interrupt irq 0x%x imr 0x%x \n",irq,imr);
++
++#else
++ imr = sysRegRead(AR531X_IMR);
++ imr |= (1 << (irq - AR531X_MISC_IRQ_BASE - 1));
++ sysRegWrite(AR531X_IMR, imr);
++ sysRegRead(AR531X_IMR); /* flush write buffer */
++#endif
++}
++
++/* Disable the specified AR531X_MISC_IRQ interrupt */
++static void
++ar531x_misc_intr_disable(unsigned int irq)
++{
++ unsigned int imr;
++
++#if CONFIG_AR5315
++ imr = sysRegRead(AR5315_IMR);
++ switch(irq)
++ {
++ case AR531X_MISC_IRQ_TIMER:
++ imr &= (~IMR_TIMER);
++ break;
++
++ case AR531X_MISC_IRQ_AHB_PROC:
++ imr &= (~IMR_AHB);
++ break;
++
++ case AR531X_MISC_IRQ_AHB_DMA:
++ imr &= 0/* ?? */;
++ break;
++ /*
++ case AR531X_ISR_GPIO:
++ imr &= ~IMR_GPIO;
++ break;
++ */
++
++ case AR531X_MISC_IRQ_UART0:
++ imr &= (~IMR_UART0);
++ break;
++
++ case AR531X_MISC_IRQ_WATCHDOG:
++ imr &= (~IMR_WD);
++ break;
++
++ case AR531X_MISC_IRQ_LOCAL:
++ imr &= ~0/* ?? */;
++ break;
++
++ }
++ sysRegWrite(AR5315_IMR, imr);
++ sysRegRead(AR5315_IMR); /* flush write buffer */
++#else
++ imr = sysRegRead(AR531X_IMR);
++ imr &= ~(1 << (irq - AR531X_MISC_IRQ_BASE - 1));
++ sysRegWrite(AR531X_IMR, imr);
++ sysRegRead(AR531X_IMR); /* flush write buffer */
++#endif
++}
++
++static void
++ar531x_misc_intr_ack(unsigned int irq)
++{
++ ar531x_misc_intr_disable(irq);
++}
++
++static void
++ar531x_misc_intr_end(unsigned int irq)
++{
++ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
++ ar531x_misc_intr_enable(irq);
++}
++
++static void
++ar531x_misc_intr_set_affinity(unsigned int irq, unsigned long mask)
++{
++ /* Only 1 CPU; ignore affinity request */
++}
++
++struct hw_interrupt_type ar531x_misc_intr_controller = {
++ "AR531X MISC",
++ ar531x_misc_intr_startup,
++ ar531x_misc_intr_shutdown,
++ ar531x_misc_intr_enable,
++ ar531x_misc_intr_disable,
++ ar531x_misc_intr_ack,
++ ar531x_misc_intr_end,
++ ar531x_misc_intr_set_affinity,
++};
++
++int ar531x_misc_irq_base;
++
++/*
++ * Determine interrupt source among interrupts that use IP6
++ */
++void
++ar531x_misc_intr_init(int irq_base)
++{
++ int i;
++
++ for (i = irq_base; i < irq_base + AR531X_MISC_IRQ_COUNT; i++) {
++ irq_desc[i].status = IRQ_DISABLED;
++ irq_desc[i].action = NULL;
++ irq_desc[i].depth = 1;
++ irq_desc[i].handler = &ar531x_misc_intr_controller;
++ }
++
++ ar531x_misc_irq_base = irq_base;
++}
++
++/* ARGSUSED */
++void
++spurious_irq_handler(int cpl, void *dev_id, struct pt_regs *regs)
++{
++ /*
++ printk("spurious_irq_handler: %d cause=0x%8.8x status=0x%8.8x\n",
++ cpl, cause_intrs, status_intrs);
++ */
++}
++
++/* ARGSUSED */
++void
++spurious_misc_handler(int cpl, void *dev_id, struct pt_regs *regs)
++{
++ /*
++ printk("spurious_misc_handler: 0x%x isr=0x%8.8x imr=0x%8.8x\n",
++ cpl, ar531x_isr, ar531x_imr);
++ */
++}
++
++void
++ar531x_timer_handler(int cpl, void *dev_id, struct pt_regs *regs)
++{
++#if CONFIG_AR5315
++ (void)sysRegRead(AR5315_TIMER); /* clear interrupt */
++#else
++ (void)sysRegRead(AR531X_TIMER); /* clear interrupt */
++#endif
++}
++
++void
++ar531x_ahb_proc_handler(int cpl, void *dev_id, struct pt_regs *regs)
++{
++ u32 procAddr;
++ u32 proc1;
++ u32 dmaAddr;
++ u32 dma1;
++#if CONFIG_AR5315
++ sysRegWrite(AR5315_AHB_ERR0,AHB_ERROR_DET);
++ sysRegRead(AR5315_AHB_ERR1);
++#else
++ proc1 = sysRegRead(AR531X_PROC1);
++ procAddr = sysRegRead(AR531X_PROCADDR); /* clears error state */
++ dma1 = sysRegRead(AR531X_DMA1);
++ dmaAddr = sysRegRead(AR531X_DMAADDR); /* clears error state */
++#endif
++
++ printk("AHB interrupt: PROCADDR=0x%8.8x PROC1=0x%8.8x DMAADDR=0x%8.8x DMA1=0x%8.8x\n",
++ procAddr, proc1, dmaAddr, dma1);
++
++ machine_restart("AHB error"); /* Catastrophic failure */
++}
++
++static struct irqaction cascade =
++ {no_action, SA_INTERRUPT, 0, "cascade",
++ NULL, NULL};
++
++static struct irqaction spurious_irq =
++ {spurious_irq_handler, SA_INTERRUPT, 0, "spurious_irq",
++ NULL, NULL};
++
++static struct irqaction spurious_misc =
++ {spurious_misc_handler, SA_INTERRUPT, 0, "spurious_misc",
++ NULL, NULL};
++
++static struct irqaction ar531x_timer_interrupt =
++ {ar531x_timer_handler, SA_INTERRUPT, 0, "ar531x_timer_interrupt",
++ NULL, NULL};
++
++static struct irqaction ar531x_ahb_proc_interrupt =
++ {ar531x_ahb_proc_handler, SA_INTERRUPT, 0, "ar531x_ahb_proc_interrupt",
++ NULL, NULL};
++
++extern asmlinkage void ar531x_interrupt_receive(void);
++
++/*
++ * Called when an interrupt is received, this function
++ * determines exactly which interrupt it was, and it
++ * invokes the appropriate handler.
++ *
++ * Implicitly, we also define interrupt priority by
++ * choosing which to dispatch first.
++ */
++extern void dump_uart(void *);
++
++#if CONFIG_AR5315
++
++void
++ar531x_irq_dispatch(struct pt_regs *regs)
++{
++ int cause_intrs = regs->cp0_cause;
++ int status_intrs = regs->cp0_status;
++ int pending = cause_intrs & status_intrs;
++
++ if (pending & CAUSEF_IP3) {
++ do_IRQ(AR531X_IRQ_WLAN0_INTRS, regs);
++ }
++ else if (pending & CAUSEF_IP4) {
++ do_IRQ(AR531X_IRQ_ENET0_INTRS, regs);
++ }
++ else if (pending & CAUSEF_IP2) {
++ AR531X_REG ar531x_isr = sysRegRead(AR5315_ISR);
++ AR531X_REG ar531x_imr = sysRegRead(AR5315_IMR);
++ unsigned int ar531x_misc_intrs = ar531x_isr & ar531x_imr;
++
++ if (ar531x_misc_intrs & ISR_TIMER)
++ do_IRQ(AR531X_MISC_IRQ_TIMER, regs);
++ else if (ar531x_misc_intrs & ISR_AHB)
++ do_IRQ(AR531X_MISC_IRQ_AHB_PROC, regs);
++ else if (ar531x_misc_intrs & ISR_GPIO)
++ {
++ int i;
++ u32 gpioIntPending;
++
++ gpioIntPending = sysRegRead(AR5315_GPIO_DI) & gpioIntMask;
++ for (i=0; i<AR531X_GPIO_IRQ_COUNT; i++) {
++ if (gpioIntPending & (1 << i))
++ do_IRQ(AR531X_GPIO_IRQ(i), regs);
++ }
++ }
++ else if (ar531x_misc_intrs & ISR_UART0) {
++ do_IRQ(AR531X_MISC_IRQ_UART0, regs);
++#if CONFIG_KGDB
++ if (kgdbInterrupt()) {
++ if (!user_mode(regs))
++ set_async_breakpoint((unsigned long *)&regs->cp0_epc);
++ }
++#endif /* CONFIG_KGDB */
++ }
++ else if (ar531x_misc_intrs & ISR_WD)
++ do_IRQ(AR531X_MISC_IRQ_WATCHDOG, regs);
++ else
++ do_IRQ(AR531X_MISC_IRQ_NONE, regs);
++ } else if (pending & CAUSEF_IP7) {
++ do_IRQ(AR531X_IRQ_CPU_CLOCK, regs);
++ }
++ else {
++ do_IRQ(AR531X_IRQ_NONE, regs);
++ }
++}
++
++#else
++
++void
++ar531x_irq_dispatch(struct pt_regs *regs)
++{
++ int cause_intrs = regs->cp0_cause;
++ int status_intrs = regs->cp0_status;
++ int pending = cause_intrs & status_intrs;
++
++ if (pending & CAUSEF_IP2) {
++ do_IRQ(AR531X_IRQ_WLAN0_INTRS, regs);
++ }
++ else if (pending & CAUSEF_IP3) {
++ do_IRQ(AR531X_IRQ_ENET0_INTRS, regs);
++ }
++ else if (pending & CAUSEF_IP4) {
++ do_IRQ(AR531X_IRQ_ENET1_INTRS, regs);
++ }
++ else if (pending & CAUSEF_IP5) {
++ do_IRQ(AR531X_IRQ_WLAN1_INTRS, regs);
++ }
++ else if (pending & CAUSEF_IP6) {
++ AR531X_REG ar531x_isr = sysRegRead(AR531X_ISR);
++ AR531X_REG ar531x_imr = sysRegRead(AR531X_IMR);
++ unsigned int ar531x_misc_intrs = ar531x_isr & ar531x_imr;
++
++ if (ar531x_misc_intrs & AR531X_ISR_TIMER)
++ do_IRQ(AR531X_MISC_IRQ_TIMER, regs);
++ else if (ar531x_misc_intrs & AR531X_ISR_AHBPROC)
++ do_IRQ(AR531X_MISC_IRQ_AHB_PROC, regs);
++ else if (ar531x_misc_intrs & AR531X_ISR_AHBDMA)
++ do_IRQ(AR531X_MISC_IRQ_AHB_DMA, regs);
++ else if (ar531x_misc_intrs & AR531X_ISR_GPIO)
++ {
++ int i;
++ u32 gpioIntPending;
++
++ gpioIntPending = sysRegRead(AR531X_GPIO_DI) & gpioIntMask;
++ for (i=0; i<AR531X_GPIO_IRQ_COUNT; i++) {
++ if (gpioIntPending & (1 << i))
++ do_IRQ(AR531X_GPIO_IRQ(i), regs);
++ }
++ }
++ else if ((ar531x_misc_intrs & AR531X_ISR_UART0) ||
++ (ar531x_misc_intrs & AR531X_ISR_UART0DMA)) {
++ do_IRQ(AR531X_MISC_IRQ_UART0, regs);
++#if CONFIG_KGDB
++ if (kgdbInterrupt()) {
++ if (!user_mode(regs))
++ set_async_breakpoint((unsigned long *)&regs->cp0_epc);
++ }
++#endif /* CONFIG_KGDB */
++ }
++ else if (ar531x_misc_intrs & AR531X_ISR_WD)
++ do_IRQ(AR531X_MISC_IRQ_WATCHDOG, regs);
++ else if (ar531x_misc_intrs & AR531X_ISR_LOCAL)
++ do_IRQ(AR531X_MISC_IRQ_LOCAL, regs);
++ else
++ do_IRQ(AR531X_MISC_IRQ_NONE, regs);
++ } else if (pending & CAUSEF_IP7) {
++ do_IRQ(AR531X_IRQ_CPU_CLOCK, regs);
++ } else
++ do_IRQ(AR531X_IRQ_NONE, regs);
++}
++
++#endif
++
++void __init init_IRQ(void)
++{
++ init_generic_irq();
++ set_except_vector(0, ar531x_interrupt_receive);
++
++ /* Initialize interrupt controllers */
++ mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
++ ar531x_misc_intr_init(AR531X_MISC_IRQ_BASE);
++ ar531x_gpio_intr_init(AR531X_GPIO_IRQ_BASE);
++ setup_irq(AR531X_IRQ_MISC_INTRS, &cascade);
++ /*
++ * AR531X_IRQ_CPU_CLOCK is setup by ar531x_timer_setup.
++ */
++
++ /* Default "spurious interrupt" handlers */
++ setup_irq(AR531X_IRQ_NONE, &spurious_irq);
++ setup_irq(AR531X_MISC_IRQ_NONE, &spurious_misc);
++ setup_irq(AR531X_GPIO_IRQ_NONE, &spurious_gpio);
++#ifndef CONFIG_AR5315
++ setup_irq(AR531X_MISC_IRQ_TIMER, &ar531x_timer_interrupt);
++#endif
++ setup_irq(AR531X_MISC_IRQ_AHB_PROC, &ar531x_ahb_proc_interrupt);
++ setup_irq(AR531X_MISC_IRQ_GPIO, &cascade);
++
++#ifdef CONFIG_KGDB
++#if CONFIG_EARLY_STOP
++ kgdbInit();
++#endif
++#endif
++}
+diff -urN linux-mips/arch/mips/ar531x/ar531xksyms.c mips-linux-2.4.25/arch/mips/ar531x/ar531xksyms.c
+--- linux-mips/arch/mips/ar531x/ar531xksyms.c 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531xksyms.c 2005-12-30 17:26:31.001823800 +0000
+@@ -0,0 +1,17 @@
++/*
++ * 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.
++ */
++
++#include <linux/module.h>
++#include "asm/atheros/ar531xbsp.h"
++
++#ifdef CONFIG_KGDB
++EXPORT_SYMBOL(kgdbInit);
++EXPORT_SYMBOL(kgdbEnabled);
++#endif
++EXPORT_SYMBOL(ar531x_sys_frequency);
++EXPORT_SYMBOL(get_system_type);
+diff -urN linux-mips/arch/mips/ar531x/ar531xlnx.h mips-linux-2.4.25/arch/mips/ar531x/ar531xlnx.h
+--- linux-mips/arch/mips/ar531x/ar531xlnx.h 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531xlnx.h 2005-12-30 17:26:31.001823800 +0000
+@@ -0,0 +1,135 @@
++/*
++ * 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.
++ */
++
++/*
++ * This file contains definitions needed in order to compile
++ * AR531X products for linux. Definitions that are largely
++ * AR531X-specific and independent of operating system belong
++ * in ar531x.h rather than this file.
++ */
++#include "ar531x.h"
++
++#define MIPS_CPU_IRQ_BASE 0x00
++#define AR531X_HIGH_PRIO 0x10
++#define AR531X_MISC_IRQ_BASE 0x20
++#define AR531X_GPIO_IRQ_BASE 0x30
++
++/* Software's idea of interrupts handled by "CPU Interrupt Controller" */
++#if CONFIG_AR5315
++#define AR531X_IRQ_NONE MIPS_CPU_IRQ_BASE+0
++#define AR531X_IRQ_MISC_INTRS MIPS_CPU_IRQ_BASE+2 /* C0_CAUSE: 0x0400 */
++#define AR531X_IRQ_WLAN0_INTRS MIPS_CPU_IRQ_BASE+3 /* C0_CAUSE: 0x0800 */
++#define AR531X_IRQ_ENET0_INTRS MIPS_CPU_IRQ_BASE+4 /* C0_CAUSE: 0x1000 */
++#define AR531X_IRQ_LCBUS_PCI MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
++#define AR531X_IRQ_WLAN0_POLL MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
++#define AR531X_IRQ_CPU_CLOCK MIPS_CPU_IRQ_BASE+7 /* C0_CAUSE: 0x8000 */
++#else
++#define AR531X_IRQ_NONE MIPS_CPU_IRQ_BASE+0
++#define AR531X_IRQ_WLAN0_INTRS MIPS_CPU_IRQ_BASE+2 /* C0_CAUSE: 0x0400 */
++#define AR531X_IRQ_ENET0_INTRS MIPS_CPU_IRQ_BASE+3 /* C0_CAUSE: 0x0800 */
++#define AR531X_IRQ_ENET1_INTRS MIPS_CPU_IRQ_BASE+4 /* C0_CAUSE: 0x1000 */
++#define AR531X_IRQ_WLAN1_INTRS MIPS_CPU_IRQ_BASE+5 /* C0_CAUSE: 0x2000 */
++#define AR531X_IRQ_MISC_INTRS MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
++#define AR531X_IRQ_CPU_CLOCK MIPS_CPU_IRQ_BASE+7 /* C0_CAUSE: 0x8000 */
++#endif
++/* Miscellaneous interrupts, which share IP6 */
++#define AR531X_MISC_IRQ_NONE AR531X_MISC_IRQ_BASE+0
++#define AR531X_MISC_IRQ_TIMER AR531X_MISC_IRQ_BASE+1
++#define AR531X_MISC_IRQ_AHB_PROC AR531X_MISC_IRQ_BASE+2
++#define AR531X_MISC_IRQ_AHB_DMA AR531X_MISC_IRQ_BASE+3
++#define AR531X_MISC_IRQ_GPIO AR531X_MISC_IRQ_BASE+4
++#define AR531X_MISC_IRQ_UART0 AR531X_MISC_IRQ_BASE+5
++#define AR531X_MISC_IRQ_UART0_DMA AR531X_MISC_IRQ_BASE+6
++#define AR531X_MISC_IRQ_WATCHDOG AR531X_MISC_IRQ_BASE+7
++#define AR531X_MISC_IRQ_LOCAL AR531X_MISC_IRQ_BASE+8
++#define AR531X_MISC_IRQ_COUNT 9
++
++/* GPIO Interrupts [0..7], share AR531X_MISC_IRQ_GPIO */
++#define AR531X_GPIO_IRQ_NONE AR531X_MISC_IRQ_BASE+0
++#define AR531X_GPIO_IRQ(n) AR531X_MISC_IRQ_BASE+(n)+1
++#ifdef CONFIG_AR5315
++#define AR531X_GPIO_IRQ_COUNT 2
++#else
++#define AR531X_GPIO_IRQ_COUNT 9
++#endif
++
++#define PHYS_TO_K1(physaddr) KSEG1ADDR(physaddr)
++#define PHYS_TO_K0(physaddr) KSEG0ADDR(physaddr)
++#define UNMAPPED_TO_PHYS(vaddr) PHYSADDR(vaddr)
++#define IS_UNMAPPED_VADDR(vaddr) \
++ ((KSEGX(vaddr) == KSEG0) || (KSEGX(vaddr) == KSEG1))
++
++/* IOCTL commands for /proc/ar531x */
++#define AR531X_CTRL_DO_BREAKPOINT 1
++#define AR531X_CTRL_DO_MADWIFI 2
++
++/*
++ * Definitions for operating system portability.
++ * These are vxWorks-->Linux translations.
++ */
++#define LOCAL static
++#define BOOL int
++#define TRUE 1
++#define FALSE 0
++#define UINT8 u8
++#define UINT16 u16
++#define UINT32 u32
++#define PRINTF printk
++#if /* DEBUG */ 1
++#define DEBUG_PRINTF printk
++#define INLINE
++#else
++DEBUG_PRINTF while (0) printk
++#define INLINE inline
++#endif
++#define sysUDelay(usecs) udelay(usecs)
++#define sysMsDelay(msecs) mdelay(msecs)
++typedef volatile UINT8 *VIRT_ADDR;
++#define MALLOC(sz) kmalloc(sz, GFP_KERNEL)
++#define MALLOC_NOSLEEP(sz) kmalloc(sz, GFP_ATOMIC)
++#define FREE(ptr) kfree((void *)ptr)
++#define BSP_BUG() do { printk("kernel BSP BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0=0; } while (0)
++#define BSP_BUG_ON(condition) do { if (unlikely((condition)!=0)) BSP_BUG(); } while(0)
++#define ASSERT(x) BSP_BUG_ON(!(x))
++
++extern struct ar531x_boarddata *ar531x_board_configuration;
++extern char *ar531x_radio_configuration;
++extern char *enet_mac_address_get(int MACUnit);
++
++extern void kgdbInit(void);
++extern int kgdbEnabled(void);
++extern void breakpoint(void);
++extern int kgdbInterrupt(void);
++extern unsigned int ar531x_cpu_frequency(void);
++extern unsigned int ar531x_sys_frequency(void);
++
++/* GPIO support */
++extern struct irqaction spurious_gpio;
++extern unsigned int gpioIntMask;
++extern void ar531x_gpio_intr_init(int irq_base);
++extern void ar531x_gpio_ctrl_output(int gpio);
++extern void ar531x_gpio_ctrl_input(int gpio);
++extern void ar531x_gpio_set(int gpio, int val);
++extern int ar531x_gpio_get(int gpio);
++extern void ar531x_gpio_intr_enable(unsigned int irq);
++extern void ar531x_gpio_intr_disable(unsigned int irq);
++
++/* Watchdog Timer support */
++extern int watchdog_start(unsigned int milliseconds);
++extern int watchdog_stop(void);
++extern int watchdog_is_enabled(void);
++extern unsigned int watchdog_min_timer_reached(void);
++extern void watchdog_notify_alive(void);
++
++#define A_DATA_CACHE_INVAL(start, length) \
++ dma_cache_inv((UINT32)(start),(length))
++
++#define sysWbFlush() mb()
++
++#define intDisable(x) cli()
++#define intEnable(x) sti()
+diff -urN linux-mips/arch/mips/ar531x/ar531xprom.c mips-linux-2.4.25/arch/mips/ar531x/ar531xprom.c
+--- linux-mips/arch/mips/ar531x/ar531xprom.c 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531xprom.c 2005-12-30 17:26:31.001823800 +0000
+@@ -0,0 +1,88 @@
++/*
++ * 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 MontaVista Software Inc
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * Prom setup file for ar531x
++ */
++
++#include <linux/init.h>
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/bootmem.h>
++
++#include <asm/bootinfo.h>
++#include <asm/addrspace.h>
++
++#include "ar531xlnx.h"
++
++#define COMMAND_LINE_SIZE 512
++
++char arcs_cmdline[COMMAND_LINE_SIZE];
++
++void __init prom_init(int argc, char *argv[])
++{
++ int i;
++ unsigned int memcfg1;
++ int bank0AC, bank1AC;
++ int memsz_in_mb;
++ strcpy(arcs_cmdline, "console=ttyS0,9600");
++ for (i=0; i<argc; i++) {
++ strcat(arcs_cmdline, " ");
++ strcat(arcs_cmdline, argv[i]);
++ }
++
++ mips_machgroup = MACH_GROUP_AR531X;
++#ifdef CONFIG_APUNUSED
++ mips_machtype = MACH_ATHEROS_UNUSED;
++#endif
++#ifdef CONFIG_AP30
++ mips_machtype = MACH_ATHEROS_AP30;
++#endif
++#ifdef CONFIG_AP33
++ mips_machtype = MACH_ATHEROS_AP33;
++#endif
++#ifdef CONFIG_AP38
++ mips_machtype = MACH_ATHEROS_AP38;
++#endif
++#ifdef CONFIG_AP43
++ mips_machtype = MACH_ATHEROS_AP43;
++#endif
++#ifdef CONFIG_AP48
++ mips_machtype = MACH_ATHEROS_AP48;
++#endif
++#ifdef CONFIG_PB32
++ mips_machtype = MACH_ATHEROS_PB32;
++#endif
++
++
++ /* Determine SDRAM size based on Address Checks done at startup */
++#if CONFIG_AR5315
++ /* TO-DO : compute the SDRAM size */
++ memsz_in_mb=8;
++#else
++ memcfg1 = sysRegRead(AR531X_MEM_CFG1);
++ bank0AC = (memcfg1 & MEM_CFG1_AC0) >> MEM_CFG1_AC0_S;
++ bank1AC = (memcfg1 & MEM_CFG1_AC1) >> MEM_CFG1_AC1_S;
++ memsz_in_mb = (bank0AC ? (1 << (bank0AC+1)) : 0)
++ + (bank1AC ? (1 << (bank1AC+1)) : 0);
++#endif
++
++ /*
++ * By default, use all available memory. You can override this
++ * to use, say, 8MB by specifying "mem=8M" as an argument on the
++ * linux bootup command line.
++ */
++ add_memory_region(0, memsz_in_mb << 20, BOOT_MEM_RAM);
++}
++
++void __init prom_free_prom_memory(void)
++{
++}
+diff -urN linux-mips/arch/mips/ar531x/ar531xsetup.c mips-linux-2.4.25/arch/mips/ar531x/ar531xsetup.c
+--- linux-mips/arch/mips/ar531x/ar531xsetup.c 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531xsetup.c 2005-12-30 17:26:31.002823648 +0000
+@@ -0,0 +1,406 @@
++/*
++ * 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.
++ */
++
++/*
++ * Initialization for ar531x SOC.
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/serial.h>
++#include <linux/types.h>
++#include <linux/string.h>
++
++#include <asm/reboot.h>
++#include <asm/io.h>
++#include <asm/time.h>
++#include <asm/pgtable.h>
++#include <asm/processor.h>
++#include <asm/reboot.h>
++#include <asm/system.h>
++#include <asm/serial.h>
++
++#include "ar531xlnx.h"
++
++void
++ar531x_restart(char *command)
++{
++ for(;;) {
++#if CONFIG_AR5315
++ /*
++ ** Cold reset does not work,work around is to use the GPIO reset bit.
++ */
++ unsigned int reg;
++ reg = sysRegRead(AR5315_GPIO_DO);
++ reg &= ~(1 << AR5315_RESET_GPIO);
++ sysRegWrite(AR5315_GPIO_DO, reg);
++ (void)sysRegRead(AR5315_GPIO_DO); /* flush write to hardware */
++
++#else
++ sysRegWrite(AR531X_RESET, AR531X_RESET_SYSTEM);
++#endif
++ }
++}
++
++void
++ar531x_halt(void)
++{
++ printk(KERN_NOTICE "\n** You can safely turn off the power\n");
++ while (1);
++}
++
++void
++ar531x_power_off(void)
++{
++ ar531x_halt();
++}
++
++const char *
++get_system_type(void)
++{
++#if CONFIG_AR5315
++ return "Atheros AR5315";
++#else
++ return "Atheros AR531X";
++#endif
++}
++
++/*
++ * This table is indexed by bits 5..4 of the CLOCKCTL1 register
++ * to determine the predevisor value.
++ */
++static int CLOCKCTL1_PREDIVIDE_TABLE[4] = {
++ 1,
++ 2,
++ 4,
++ 5
++};
++
++#if CONFIG_AR5315
++static int PLLC_DIVIDE_TABLE[5] = {
++ 2,
++ 3,
++ 4,
++ 6,
++ 3
++};
++
++unsigned int
++ar531x_cpu_frequency(void)
++{
++ static unsigned int ar531x_calculated_cpu_freq=0;
++ unsigned int clockCtl,pllcCtrl,cpuDiv;
++ unsigned int pllcOut,refdiv,fdiv,divby2;
++
++ if(ar531x_calculated_cpu_freq)
++ return ar531x_calculated_cpu_freq;
++
++
++ pllcCtrl = sysRegRead(AR5315_PLLC_CTL);
++ refdiv = (pllcCtrl & PLLC_REF_DIV_M) >> PLLC_REF_DIV_S;
++ refdiv = CLOCKCTL1_PREDIVIDE_TABLE[refdiv];
++ fdiv = (pllcCtrl & PLLC_FDBACK_DIV_M) >> PLLC_FDBACK_DIV_S;
++ divby2 = (pllcCtrl & PLLC_ADD_FDBACK_DIV_M) >> PLLC_ADD_FDBACK_DIV_S;
++ divby2 += 1;
++ pllcOut = (40000000/refdiv)*(2*divby2)*fdiv;
++
++ clockCtl = sysRegRead(AR5315_CPUCLK);
++
++ /* clkm input selected */
++ if((clockCtl & CPUCLK_CLK_SEL_M) == 0 || (clockCtl & CPUCLK_CLK_SEL_M) == 1 ) {
++ unsigned int clkMdiv;
++ clkMdiv = (pllcCtrl & PLLC_CLKM_DIV_M) >> PLLC_CLKM_DIV_S;
++ clkMdiv = PLLC_DIVIDE_TABLE[clkMdiv];
++
++ cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;
++ if(cpuDiv) cpuDiv *= 2;
++ else cpuDiv=1;
++
++ ar531x_calculated_cpu_freq= (pllcOut/(clkMdiv * cpuDiv)) ;
++
++ return ar531x_calculated_cpu_freq;
++ }
++
++ /* clkc input selected */
++ if((clockCtl & CPUCLK_CLK_SEL_M) == 2 ) {
++ unsigned int clkCdiv;
++ clkCdiv = (pllcCtrl & PLLC_CLKC_DIV_M) >> PLLC_CLKC_DIV_S;
++ clkCdiv = PLLC_DIVIDE_TABLE[clkCdiv];
++
++ cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;
++ if(cpuDiv) cpuDiv *= 2;
++ else cpuDiv=1;
++
++ ar531x_calculated_cpu_freq= (pllcOut/(clkCdiv * cpuDiv)) ;
++
++ return ar531x_calculated_cpu_freq;
++ } else { /* ref_clk selected */
++
++ cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;
++ if(cpuDiv) cpuDiv *= 2;
++ else cpuDiv=1;
++
++ ar531x_calculated_cpu_freq= (40000000/(cpuDiv)) ;
++ return ar531x_calculated_cpu_freq;
++ }
++}
++
++unsigned int
++ar531x_apb_frequency(void)
++{
++ static unsigned int ar531x_calculated_cpu_freq=0;
++ unsigned int clockCtl,pllcCtrl,cpuDiv;
++ unsigned int pllcOut,refdiv,fdiv,divby2;
++
++ if(ar531x_calculated_cpu_freq)
++ return ar531x_calculated_cpu_freq;
++
++
++ pllcCtrl = sysRegRead(AR5315_PLLC_CTL);
++ refdiv = (pllcCtrl & PLLC_REF_DIV_M) >> PLLC_REF_DIV_S;
++ refdiv = CLOCKCTL1_PREDIVIDE_TABLE[refdiv];
++ fdiv = (pllcCtrl & PLLC_FDBACK_DIV_M) >> PLLC_FDBACK_DIV_S;
++ divby2 = (pllcCtrl & PLLC_ADD_FDBACK_DIV_M) >> PLLC_ADD_FDBACK_DIV_S;
++ divby2 += 1;
++ pllcOut = (40000000/refdiv)*(2*divby2)*fdiv;
++
++ clockCtl = sysRegRead(AR5315_AMBACLK);
++
++ /* clkm input selected */
++ if((clockCtl & CPUCLK_CLK_SEL_M) == 0 || (clockCtl & CPUCLK_CLK_SEL_M) == 1 ) {
++ unsigned int clkMdiv;
++ clkMdiv = (pllcCtrl & PLLC_CLKM_DIV_M) >> PLLC_CLKM_DIV_S;
++ clkMdiv = PLLC_DIVIDE_TABLE[clkMdiv];
++
++ cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;
++ if(cpuDiv) cpuDiv *= 2;
++ else cpuDiv=1;
++
++ ar531x_calculated_cpu_freq= (pllcOut/(clkMdiv * cpuDiv)) ;
++
++ return ar531x_calculated_cpu_freq;
++ }
++
++ /* clkc input selected */
++ if((clockCtl & CPUCLK_CLK_SEL_M) == 2 ) {
++ unsigned int clkCdiv;
++ clkCdiv = (pllcCtrl & PLLC_CLKC_DIV_M) >> PLLC_CLKC_DIV_S;
++ clkCdiv = PLLC_DIVIDE_TABLE[clkCdiv];
++
++ cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;
++ if(cpuDiv) cpuDiv *= 2;
++ else cpuDiv=1;
++
++ ar531x_calculated_cpu_freq= (pllcOut/(clkCdiv * cpuDiv)) ;
++
++ return ar531x_calculated_cpu_freq;
++ } else { /* ref_clk selected */
++
++ cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;
++ if(cpuDiv) cpuDiv *= 2;
++ else cpuDiv=1;
++
++ ar531x_calculated_cpu_freq= (40000000/(cpuDiv)) ;
++ return ar531x_calculated_cpu_freq;
++ }
++}
++
++#else
++unsigned int
++ar531x_cpu_frequency(void)
++{
++ static unsigned int ar531x_calculated_cpu_freq;
++ unsigned int clockctl1_predivide_mask;
++ unsigned int clockctl1_predivide_shift;
++ unsigned int clockctl1_multiplier_mask;
++ unsigned int clockctl1_multiplier_shift;
++ unsigned int clockctl1_doubler_mask;
++ int wisoc_revision;
++
++ /*
++ * Trust the bootrom's idea of cpu frequency.
++ */
++ ar531x_calculated_cpu_freq = sysRegRead(AR5312_SCRATCH);
++ if (ar531x_calculated_cpu_freq)
++ return ar531x_calculated_cpu_freq;
++
++ wisoc_revision = (sysRegRead(AR531X_REV) & AR531X_REV_MAJ) >> AR531X_REV_MAJ_S;
++
++ if (wisoc_revision == AR531X_REV_MAJ_AR2313) {
++ clockctl1_predivide_mask = AR2313_CLOCKCTL1_PREDIVIDE_MASK;
++ clockctl1_predivide_shift = AR2313_CLOCKCTL1_PREDIVIDE_SHIFT;
++ clockctl1_multiplier_mask = AR2313_CLOCKCTL1_MULTIPLIER_MASK;
++ clockctl1_multiplier_shift = AR2313_CLOCKCTL1_MULTIPLIER_SHIFT;
++ clockctl1_doubler_mask = AR2313_CLOCKCTL1_DOUBLER_MASK;
++ } else { /* AR5312 and AR2312 */
++ clockctl1_predivide_mask = AR5312_CLOCKCTL1_PREDIVIDE_MASK;
++ clockctl1_predivide_shift = AR5312_CLOCKCTL1_PREDIVIDE_SHIFT;
++ clockctl1_multiplier_mask = AR5312_CLOCKCTL1_MULTIPLIER_MASK;
++ clockctl1_multiplier_shift = AR5312_CLOCKCTL1_MULTIPLIER_SHIFT;
++ clockctl1_doubler_mask = AR5312_CLOCKCTL1_DOUBLER_MASK;
++ }
++
++ /*
++ * Clocking is derived from a fixed 40MHz input clock.
++ * cpuFreq = InputClock * MULT (where MULT is PLL multiplier)
++ *
++ * sysFreq = cpuFreq / 4 (used for APB clock, serial,
++ * flash, Timer, Watchdog Timer)
++ *
++ * cntFreq = cpuFreq / 2 (use for CPU count/compare)
++ *
++ * So, for example, with a PLL multiplier of 5, we have
++ * cpuFrez = 200MHz
++ * sysFreq = 50MHz
++ * cntFreq = 100MHz
++ *
++ * We compute the CPU frequency, based on PLL settings.
++ */
++ if (ar531x_calculated_cpu_freq == 0) {
++ unsigned int clockCtl1 = sysRegRead(AR5312_CLOCKCTL1);
++
++ int preDivideSelect = (clockCtl1 & clockctl1_predivide_mask) >>
++ clockctl1_predivide_shift;
++
++ int preDivisor = CLOCKCTL1_PREDIVIDE_TABLE[preDivideSelect];
++
++ int multiplier = (clockCtl1 & clockctl1_multiplier_mask) >>
++ clockctl1_multiplier_shift;
++
++ if (clockCtl1 & clockctl1_doubler_mask) {
++ multiplier = multiplier << 1;
++ }
++
++ ar531x_calculated_cpu_freq = (40000000 / preDivisor) * multiplier;
++ }
++
++ return ar531x_calculated_cpu_freq;
++}
++#endif
++
++unsigned int
++ar531x_sys_frequency(void)
++{
++ static unsigned int ar531x_calculated_sys_freq = 0;
++
++ if (ar531x_calculated_sys_freq == 0) {
++ ar531x_calculated_sys_freq = ar531x_cpu_frequency() / 4;
++ }
++
++ return ar531x_calculated_sys_freq;
++}
++
++static void __init
++flash_setup(void)
++{
++ UINT32 flash_ctl;
++#ifndef CONFIG_AR5315
++ /* Configure flash bank 0 */
++ flash_ctl = FLASHCTL_E |
++ FLASHCTL_AC_8M |
++ FLASHCTL_RBLE |
++ (0x01 << FLASHCTL_IDCY_S) |
++ (0x07 << FLASHCTL_WST1_S) |
++ (0x07 << FLASHCTL_WST2_S) |
++ (sysRegRead(AR531X_FLASHCTL0) & FLASHCTL_MW);
++
++ sysRegWrite(AR531X_FLASHCTL0, flash_ctl);
++
++ /* Disable other flash banks */
++ sysRegWrite(AR531X_FLASHCTL1,
++ sysRegRead(AR531X_FLASHCTL1) & ~(FLASHCTL_E | FLASHCTL_AC));
++
++ sysRegWrite(AR531X_FLASHCTL2,
++ sysRegRead(AR531X_FLASHCTL2) & ~(FLASHCTL_E | FLASHCTL_AC));
++#endif
++}
++
++
++
++void __init
++serial_setup(void)
++{
++ struct serial_struct s;
++
++ memset(&s, 0, sizeof(s));
++
++ s.flags = STD_COM_FLAGS;
++ s.io_type = SERIAL_IO_MEM;
++#if CONFIG_AR5315
++ s.baud_base = ar531x_apb_frequency()/16;
++#else
++ s.baud_base = ar531x_sys_frequency()/16;
++#endif
++ s.irq = AR531X_MISC_IRQ_UART0;
++ s.iomem_reg_shift = 2;
++#if CONFIG_AR5315
++ s.iomem_base = (u8 *)AR5315_UART0;
++#else
++ s.iomem_base = (u8 *)AR531X_UART0;
++#endif
++
++ if (early_serial_setup(&s) != 0)
++ printk(KERN_ERR "early_serial_setup failed\n");
++}
++
++extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
++static void __init
++ar531x_timer_setup(struct irqaction *irq)
++{
++ unsigned int count;
++
++ /* Usually irq is timer_irqaction (timer_interrupt) */
++ setup_irq(AR531X_IRQ_CPU_CLOCK, irq);
++
++ /* to generate the first CPU timer interrupt */
++ count = read_c0_count();
++ write_c0_compare(count + 1000);
++}
++
++extern void (*board_time_init)(void);
++
++static void __init
++ar531x_time_init(void)
++{
++ mips_hpt_frequency = ar531x_cpu_frequency() / 2;
++}
++
++void __init
++ar531x_setup(void)
++{
++ /* Clear any lingering AHB errors */
++#if CONFIG_AR5315
++ unsigned int config = read_c0_config();
++ write_c0_config(config & ~0x3);
++ sysRegWrite(AR5315_AHB_ERR0,AHB_ERROR_DET);
++ sysRegRead(AR5315_AHB_ERR1);
++ sysRegWrite(AR5315_WDC, WDC_IGNORE_EXPIRATION);
++#else
++ sysRegRead(AR531X_PROCADDR);
++ sysRegRead(AR531X_DMAADDR);
++
++ sysRegWrite(AR531X_WD_CTRL, AR531X_WD_CTRL_IGNORE_EXPIRATION);
++
++#endif
++
++ /* Disable data watchpoints */
++ write_c0_watchlo0(0);
++
++ board_time_init = ar531x_time_init;
++ board_timer_setup = ar531x_timer_setup;
++
++ _machine_restart = ar531x_restart;
++ _machine_halt = ar531x_halt;
++ _machine_power_off = ar531x_power_off;
++
++ flash_setup();
++ serial_setup();
++}
+diff -urN linux-mips/arch/mips/ar531x/Makefile mips-linux-2.4.25/arch/mips/ar531x/Makefile
+--- linux-mips/arch/mips/ar531x/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/Makefile 2005-12-30 17:26:29.912989328 +0000
+@@ -0,0 +1,33 @@
++#
++# 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.
++#
++
++# Makefile for Atheros ar531x boards
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++
++.S.s:
++ $(CPP) $(CFLAGS) $< -o $*.s
++.S.o:
++ $(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $*.o
++
++O_TARGET:= ar531x.o
++
++export-objs = ar531xksyms.o
++
++obj-y := ar531xdbg_io.o \
++ ar531xsetup.o \
++ ar531xprom.o \
++ ar531xirq.o \
++ ar531xintr.o \
++ ar531xgpio.o \
++ ar531xksyms.o
++
++include $(TOPDIR)/Rules.make
+diff -urN linux-mips/arch/mips/ar531x/README mips-linux-2.4.25/arch/mips/ar531x/README
+--- linux-mips/arch/mips/ar531x/README 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/README 2005-12-30 17:26:30.478903296 +0000
+@@ -0,0 +1,68 @@
++Basic information for the AR531X Board Support Package
++
++This directory contains the "LBSP" -- Linux Board Support Package --
++for Linux on the Atheros AR531X Wireless System-On-a-Chip. It is intended
++primarily as a building block for wireless products. At this time, the
++AR531X Linux BSP is experimental code, and is actively UNDER CONSTRUCTION.
++
++Some components that are supported by this LBSP along with a standard 2.4
++Linux MIPS kernel include
++ R4Kc CPU
++ instruction and data caches
++ SDRAM
++ flash (Macronix, AMD, STS, etc.)
++ 16550 serial port
++ ethernet MACs
++ ethernet PHY or PHY Switch (RealTek, Kendin, Marvell)
++ General-Purpose I/O pins
++ kernel debugging with kgdb
++
++This LBSP code does NOT include drivers for the wireless components of the
++chip/boards! Drivers for those components may be distributed separately.
++In particular, the MADWiFi project under SourceForge supports (not yet!)
++wireless functions on the AR531X chipset. See
++ http://www.sourceforge.net/projects/madwifi
++
++Files included in this BSP:
++ae531xlnx.c - Linux-specific portions of the ethernet driver
++ae531xmac.c - OS-independent AR531X ethernet MAC code
++ae531xmac.h - OS-independent AR531X ethernet MAC software definitions
++ae531xreg.h - OS-independent AR531X ethernet MAC hardware definitions
++ar531x.h - OS-independent AR531X system hardware definitions
++ar531xlnx.h - Linux-specific AR531X system definitions and externs
++defconfig-ar531x - Default Linux configuration file
++intr_recv.S - Linux interrupt "glue" code
++ar531xirq.c - Linux Interrupt Request management
++Makefile - Linux makefile
++mvPhy.c - OS-independent ethernet PHY code for Marvell Switch
++mvPhy.h - OS-independent ethernet PHY definitions for Marvell Switch
++ar531xprom.c - Linux prom "glue" code
++ar531xsetup.c - Linux startup code
++ar531xdbg_io.c - Support for kgdb-based debugging and for EARLY_PRINTK_HACK
++ar531xproc.c - Pseudo-device driver for /proc/ar531x device
++ar531xgpio.c - Support for General Purpose I/O pins
++ar531xwmacsl.c - Wireless MAC Support Layer
++
++Additional files, distributed with the BSP:
++README - This file
++README.BUILD - Instructions for building a linux kernel from source
++README.EXECUTE - Instructions for testing your linux kernel
++README.RAMDISK - Instructions for building a root ramdisk image
++
++ramdisk.gz - A binary ramdisk image, suitable for use with AR531X.
++DIFFS - Directory that contains "patch" files (See README.BUILD)
++
++
++There are several ways to boot a vmlinux image on an AR531X board:
++ -You can boot in over ethernet from the vxWorks bootrom, which is preloaded
++ on all Atheros boards
++ -You can use an ICE (e.g. VisionICE) to load the vmlinux image. You will
++ need appropriate register initialization (e.g. AP30.ini file)
++ -You can use the eCos RedBoot bootrom loader. This is a full-featured
++ bootrom which as been ported to AR531x. It can boot vmlinux over ethernet
++ or from flash. Source code is available from Atheros.
++
++Please send comments, corrections, complaints, criticisms, suggestions,
++enhancements, requests, or any other reasonable communications regarding
++this effort, to "linux@atheros.com". Your email will be received by a
++couple of engineers, and redirected as appropriate.
+diff -urN linux-mips/arch/mips/ar531x/README.BUILD mips-linux-2.4.25/arch/mips/ar531x/README.BUILD
+--- linux-mips/arch/mips/ar531x/README.BUILD 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/README.BUILD 2005-12-30 17:26:30.478903296 +0000
+@@ -0,0 +1,47 @@
++ How to BUILD a linux kernel for an AR531X system
++
++It is expected that you will build Linux on an existing Linux system, which
++has all of the standard Linux tools.
++
++01) Obtain a MIPS BigEndian ELF gcc-compatible toolchain. For example,
++ if you're cross-compiling on a x86 Linux system, you could use:
++ ftp://ftp.mips.com/pub/tools/software/sde-for-linux/sdelinux-5.01-4eb.i386.rpm
++
++02) Obtain the latest working MIPS Linux kernel
++ cvs -d :pserver:cvs@ftp.linux-mips.org:/home/cvs login (password "cvs")
++ cvs -d :pserver:cvs@ftp.linux-mips.org:/home/cvs co -r linux_2_4 linux
++
++ Now "cd linux". The remainder of these instructions assume
++ that you are in the linux directory.
++
++03) Place the contents of this directory at arch/mips/ar531x.
++
++04) Use the patch command to patch generic linux files according
++ to the DIFFS directory
++ for i in arch/mips/ar531x/DIFFS/*.diff
++ do
++ patch -p1 < $i
++ done
++ NOTE: This version of the AR531X Linux BSP was tested with
++ MIPS Linux 2.4.22 as of 11/14/03. If you use a different
++ (e.g. more recent) version of Linux source, you may need to
++ resolve some minor patch and compilation issues.
++
++05) Set up a RAMDISK image.
++ See the instructions in README.RAMDISK.
++
++06) Set up a linux configuration using ar531x/defconfig-ar531x.
++ cp arch/mips/ar531x/defconfig-ar531x .config
++ make oldconfig (answer all questions that are asked)
++ NOTE: For development/debug purposes, you may want to
++ enable CONFIG_RUNTIME_DEBUG and CONFIG_KGDB.
++
++07) Make dependencies.
++ make dep
++
++08) Build the linux kernel
++ make
++
++09) The linux image you just built is in vmlinux.
++ See instructions in README.EXECUTE to run your vmlinux
++ image on an AP531X-based board.
+diff -urN linux-mips/arch/mips/ar531x/README.EXECUTE mips-linux-2.4.25/arch/mips/ar531x/README.EXECUTE
+--- linux-mips/arch/mips/ar531x/README.EXECUTE 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/README.EXECUTE 2005-12-30 17:26:30.479903144 +0000
+@@ -0,0 +1,23 @@
++ How to EXECUTE a linux image on an AR531X system
++
++There are currently three ways to run you vmlinux image:
++ 1) Load it using the vxWorks bootrom that is supplied with the board.
++ You can load it over ethernet or from the TFFS file system, if you
++ have sufficient flash to store the image.
++ 2) Load it using an ICE (e.g. VisionICE).
++ 3) Use a bootrom loader, such as eCos RedBoot.
++
++After you have booted linux:
++ By default, the root filesystem on ramdisk is read-only.
++ To make it writable, use "mount -o remount w /".
++
++ The user-level commands are slightly non-standard, as they
++ are based on "busybox".
++
++ The "wget" command is included. You can use wget to fetch
++ files from any ftp server. So, for instance, you can fetch
++ a kernel module and then "insmod" it.
++
++Note that the standard source-level kernel debugger, kgdb, works well
++over the serial line with this port. We use kgdb and the kgdb_demux perl
++script -- available over the www -- for debugging.
+diff -urN linux-mips/arch/mips/ar531x/README.VERSION mips-linux-2.4.25/arch/mips/ar531x/README.VERSION
+--- linux-mips/arch/mips/ar531x/README.VERSION 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/README.VERSION 2005-12-30 17:26:30.479903144 +0000
+@@ -0,0 +1 @@
++Source release last modified: 12/16/03
+diff -urN linux-mips/arch/mips/config-shared.in mips-linux-2.4.25/arch/mips/config-shared.in
+--- linux-mips/arch/mips/config-shared.in 2005-12-24 15:11:15.963885864 +0000
++++ mips-linux-2.4.25/arch/mips/config-shared.in 2005-12-30 17:26:31.611731080 +0000
+@@ -34,6 +34,7 @@
+ dep_bool 'Support for Alchemy PB1550 board' CONFIG_MIPS_PB1550 $CONFIG_MIPS32
+ dep_bool 'Support for Alchemy PB1200 board' CONFIG_MIPS_PB1200 $CONFIG_MIPS32
+ dep_bool 'Support for Alchemy Hydrogen3 board' CONFIG_MIPS_HYDROGEN3 $CONFIG_MIPS32
++dep_bool 'Support for Atheros AR5312/AR2312 WiSoC (EXPERIMENTAL)' CONFIG_AR531X $CONFIG_AR531X $CONFIG_EXPERIMENTAL
+ dep_bool 'Support for MyCable XXS1500 board' CONFIG_MIPS_XXS1500 $CONFIG_MIPS32
+ dep_bool 'Support for 4G Systems MTX-1 board' CONFIG_MIPS_MTX1 $CONFIG_MIPS32
+ dep_bool 'Support for Cogent CSB250 board' CONFIG_COGENT_CSB250 $CONFIG_MIPS32
+@@ -238,6 +239,63 @@
+ define_bool CONFIG_PC_KEYB y
+ define_bool CONFIG_OLD_TIME_C y
+ fi
++if [ "$CONFIG_AR531X" = "y" ]; then
++ define_bool CONFIG_IRQ_CPU y
++ define_bool CONFIG_CPU_R4X00 y
++ define_bool CONFIG_SERIAL y
++ define_bool CONFIG_NEW_IRQ y
++ define_bool CONFIG_NEW_TIME_C y
++ define_bool CONFIG_AR5312
++ define_bool CONFIG_NONCOHERENT_IO y
++ bool 'Enable early printk hack' CONFIG_EARLY_PRINTK_HACK
++ define_bool CONFIG_SCSI n
++ mainmenu_option next_comment
++ comment 'Board selection'
++ choice 'Board type' \
++ "UNKNOWN CONFIG_APUNKNOWN \
++ AP30 CONFIG_AP30 \
++ AP31 CONFIG_AP31 \
++ AP33 CONFIG_AP33 \
++ AP38 CONFIG_AP38 \
++ AP43 CONFIG_AP43 \
++ AP48 CONFIG_AP48 \
++ AP51 CONFIG_AP51 \
++ AP30-ASK CONFIG_AP30ASK" AP30
++ if [ "$CONFIG_AP30" = "y" -o "$CONFIG_AP30ASK" = "y" ]; then
++ define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 2
++ fi
++ if [ "$CONFIG_AP33" = "y" ]; then
++ define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
++ fi
++ if [ "$CONFIG_AP38" = "y" ]; then
++ define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
++ fi
++ if [ "$CONFIG_AP43" = "y" ]; then
++ define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
++ fi
++ if [ "$CONFIG_AP48" = "y" ]; then
++ define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
++ fi
++ if [ "$CONFIG_AP51" = "y" ]; then
++ define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
++ define_bool CONFIG_MTD_REDBOOT_PARTS y
++ define_bool CONFIG_AR5315 y
++ define_bool CONFIG_MTD_SPIFLASH y
++ define_bool CONFIG_MTD_CFI n
++ define_bool CONFIG_MTD_JEDECPROBE n
++ define_bool CONFIG_MTD_CFI_INTELEXT n
++ define_bool CONFIG_MTD_CFI_AMDSTD n
++ define_bool CONFIG_MTD_OBSOLETE_CHIPS n
++ define_bool CONFIG_MTD_AMDSTD n
++ define_bool CONFIG_MTD_JEDEC n
++ define_bool CONFIG_MTD_PHYSMAP n
++ fi
++ mainmenu_option next_comment
++ comment 'Flash Selection'
++ choice 'Flash Size' \
++ "2MB CONFIG_FLASH_2MB \
++ 4MB CONFIG_FLASH_4MB" 2MB
++fi
+ if [ "$CONFIG_CASIO_E55" = "y" ]; then
+ define_bool CONFIG_IRQ_CPU y
+ define_bool CONFIG_NEW_TIME_C y
+
+diff -urN linux-mips/arch/mips/kernel/setup.c mips-linux-2.4.25/arch/mips/kernel/setup.c
+--- linux-mips/arch/mips/kernel/setup.c 2005-12-24 15:11:16.188851664 +0000
++++ mips-linux-2.4.25/arch/mips/kernel/setup.c 2005-12-30 17:26:33.536438480 +0000
+@@ -496,6 +496,7 @@
+ void hp_setup(void);
+ void au1x00_setup(void);
+ void frame_info_init(void);
++ void ar531x_setup(void);
+
+ frame_info_init();
+ #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
+@@ -693,6 +694,12 @@
+ pmc_yosemite_setup();
+ break;
+ #endif
++
++#ifdef CONFIG_AR531X
++ case MACH_GROUP_AR531X:
++ ar531x_setup();
++ break;
++#endif
+ default:
+ panic("Unsupported architecture");
+ }
+diff -urN linux-mips/arch/mips/Makefile mips-linux-2.4.25/arch/mips/Makefile
+--- linux-mips/arch/mips/Makefile 2005-12-24 15:11:15.903894984 +0000
++++ mips-linux-2.4.25/arch/mips/Makefile 2005-12-30 17:26:29.911989480 +0000
+@@ -701,6 +701,17 @@
+ LOADADDR += 0x80020000
+ endif
+
++ifdef CONFIG_AR531X
++SUBDIRS += arch/mips/ar531x
++LIBS += arch/mips/ar531x/ar531x.o
++ifdef CONFIG_AP51
++LOADADDR += 0x80041000
++else
++LOADADDR += 0x80002000
++endif
++
++endif
++
+ #
+ # Choosing incompatible machines durings configuration will result in
+ # error messages during linking. Select a default linkscript if
+diff -urN linux-mips/ath_version.mk mips-linux-2.4.25/ath_version.mk
+--- linux-mips/ath_version.mk 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/ath_version.mk 2005-12-30 17:27:00.579327336 +0000
+@@ -0,0 +1 @@
++EXTRAVERSION=-LSDK-5.0.0-RC5
+diff -urN linux-mips/drivers/char/serial.c mips-linux-2.4.25/drivers/char/serial.c
+--- linux-mips/drivers/char/serial.c 2005-12-24 15:11:21.796999096 +0000
++++ mips-linux-2.4.25/drivers/char/serial.c 2005-12-30 17:27:10.815771160 +0000
+@@ -3441,7 +3441,7 @@
+
+ static _INLINE_ void show_serial_version(void)
+ {
+- printk(KERN_INFO "%s version %s%s (%s) with%s", serial_name,
++ printk(KERN_INFO "%s version %s%s (%s) with%s\n", serial_name,
+ serial_version, LOCAL_VERSTRING, serial_revdate,
+ serial_options);
+ }
+@@ -5567,7 +5567,7 @@
+ printk(KERN_INFO"ttyS%02d%s at 0x%p (irq = %d) is a %s\n",
+ state->line + SERIAL_DEV_OFFSET,
+ (state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
+- state->iomem_base, state->irq,
++ (void *)state->iomem_base, state->irq,
+ uart_config[state->type].name);
+ }
+ else {
+diff -urN linux-mips/drivers/mtd/chips/cfi_cmdset_0002.c mips-linux-2.4.25/drivers/mtd/chips/cfi_cmdset_0002.c
+--- linux-mips/drivers/mtd/chips/cfi_cmdset_0002.c 2005-12-24 15:11:25.102496584 +0000
++++ mips-linux-2.4.25/drivers/mtd/chips/cfi_cmdset_0002.c 2005-12-30 17:27:21.333172272 +0000
+@@ -511,7 +511,7 @@
+ or tells us why it failed. */
+ dq6 = CMD(1<<6);
+ dq5 = CMD(1<<5);
+- timeo = jiffies + (HZ/1000); /* setting timeout to 1ms for now */
++ timeo = jiffies + (HZ/1000) + 1; /* setting timeout to 1ms for now */
+
+ oldstatus = cfi_read(map, adr);
+ status = cfi_read(map, adr);
+@@ -536,16 +536,18 @@
+ if( (status & dq5) == dq5 ) {
+ /* When DQ5 raises, we must check once again
+ if DQ6 is toggling. If not, the erase has been
+- completed OK. If not, reset chip. */
++ completed OK. But if so, reset chip. */
+ oldstatus = cfi_read(map, adr);
+ status = cfi_read(map, adr);
+
+ if ( (oldstatus & 0x00FF) == (status & 0x00FF) ) {
++#if 0
+ printk(KERN_WARNING "Warning: DQ5 raised while program operation was in progress, however operation completed OK\n" );
++#endif
+ } else {
+ /* DQ5 is active so we can do a reset and stop the erase */
+ cfi_write(map, CMD(0xF0), chip->start);
+- printk(KERN_WARNING "Internal flash device timeout occurred or write operation was performed while flash was programming.\n" );
++ printk(KERN_WARNING "Internal flash device timeout pt A occurred or write operation was performed while flash was programming. timeout=%d\n",chip->word_write_time );
+ }
+ } else {
+ printk(KERN_WARNING "Waiting for write to complete timed out in do_write_oneword.");
+@@ -959,7 +961,7 @@
+ {
+ /* DQ5 is active so we can do a reset and stop the erase */
+ cfi_write(map, CMD(0xF0), chip->start);
+- printk( KERN_WARNING "Internal flash device timeout occured or write operation was performed while flash was erasing\n" );
++ printk( KERN_WARNING "Internal flash device timeout pt B occured or write operation was performed while flash was erasing\n" );
+ }
+ }
+ else
+diff -urN linux-mips/drivers/mtd/chips/cfi_probe.c mips-linux-2.4.25/drivers/mtd/chips/cfi_probe.c
+--- linux-mips/drivers/mtd/chips/cfi_probe.c 2005-12-24 15:11:25.103496432 +0000
++++ mips-linux-2.4.25/drivers/mtd/chips/cfi_probe.c 2005-12-30 17:27:21.507145824 +0000
+@@ -51,7 +51,7 @@
+ struct flchip *chips, struct cfi_private *cfi)
+ {
+ int i;
+-
++
+ if ((base + 0) >= map->size) {
+ printk(KERN_NOTICE
+ "Probe at base[0x00](0x%08lx) past the end of the map(0x%08lx)\n",
+@@ -221,12 +221,10 @@
+
+ static void print_cfi_ident(struct cfi_ident *cfip)
+ {
+-#if 0
+ if (cfip->qry[0] != 'Q' || cfip->qry[1] != 'R' || cfip->qry[2] != 'Y') {
+ printk("Invalid CFI ident structure.\n");
+ return;
+ }
+-#endif
+ printk("Primary Vendor Command Set: %4.4X (%s)\n", cfip->P_ID, vendorname(cfip->P_ID));
+ if (cfip->P_ADR)
+ printk("Primary Algorithm Table at %4.4X\n", cfip->P_ADR);
+diff -urN linux-mips/drivers/mtd/chips/jedec_probe.c mips-linux-2.4.25/drivers/mtd/chips/jedec_probe.c
+--- linux-mips/drivers/mtd/chips/jedec_probe.c 2005-12-24 15:11:25.126492936 +0000
++++ mips-linux-2.4.25/drivers/mtd/chips/jedec_probe.c 2005-12-30 17:27:21.532142024 +0000
+@@ -104,6 +104,7 @@
+ #define SST29LE512 0x003d
+ #define SST39LF800 0x2781
+ #define SST39LF160 0x2782
++#define SST39LF1601 0x234b
+ #define SST39LF512 0x00D4
+ #define SST39LF010 0x00D5
+ #define SST39LF020 0x00D6
+@@ -113,6 +114,8 @@
+ #define SST49LF030A 0x001C
+ #define SST49LF040A 0x0051
+ #define SST49LF080A 0x005B
++#define SST39VF3201 0x235B
++#define SST39VF3202 0x235A
+
+ /* Toshiba */
+ #define TC58FVT160 0x00C2
+@@ -900,7 +903,43 @@
+ NumEraseRegions: 1,
+ regions: {ERASEINFO(0x01000,256),
+ }
+- }
++ }, {
++ mfr_id: MANUFACTURER_SST,
++ dev_id: SST39LF160,
++ name: "SST 39LF160",
++ DevSize: SIZE_2MiB,
++ CmdSet: P_ID_AMD_STD,
++ NumEraseRegions: 1,
++ regions: {ERASEINFO(0x01000,512),
++ }
++ }, {
++ mfr_id: MANUFACTURER_SST,
++ dev_id: SST39LF1601,
++ name: "SST 39LF1601",
++ DevSize: SIZE_2MiB,
++ CmdSet: P_ID_AMD_STD,
++ NumEraseRegions: 1,
++ regions: {ERASEINFO(0x01000,512),
++ }
++ }, {
++ mfr_id: MANUFACTURER_SST,
++ dev_id: SST39VF3201,
++ name: "SST 39VF3201",
++ DevSize: SIZE_4MiB,
++ CmdSet: P_ID_AMD_STD,
++ NumEraseRegions: 1,
++ regions: {ERASEINFO(0x01000,1024),
++ }
++ }, {
++ mfr_id: MANUFACTURER_SST,
++ dev_id: SST39VF3202,
++ name: "SST 39VF3202",
++ DevSize: SIZE_4MiB,
++ CmdSet: P_ID_AMD_STD,
++ NumEraseRegions: 1,
++ regions: {ERASEINFO(0x01000,1024),
++ }
++ }
+ };
+
+
+@@ -967,6 +1006,35 @@
+ p_cfi->cfiq->DevSize = jedec_table[index].DevSize;
+ p_cfi->cfi_mode = CFI_MODE_JEDEC;
+
++ /*
++ * Add the following code to set the flash timing parameters.
++ * Maybe this is done in a table somwehere else? I can't find it.
++ */
++
++
++ switch(jedec_table[index].dev_id) {
++ case SST39VF3201:
++ case SST39VF3202:
++ p_cfi->cfiq->WordWriteTimeoutTyp = 3; /* 8 us */
++ p_cfi->cfiq->WordWriteTimeoutMax = 4; /* 16 us */
++ p_cfi->cfiq->BlockEraseTimeoutTyp = 15; /* Actually 18ms, max 25 */
++ p_cfi->cfiq->BlockEraseTimeoutMax = 15; /* Actually 25ms */
++ p_cfi->cfiq->ChipEraseTimeoutTyp = 16; /* Max is 50ms, typical is 40ms */
++ p_cfi->cfiq->ChipEraseTimeoutMax = 16;
++ break;
++ case SST39LF160:
++ case SST39LF1601:
++ p_cfi->cfiq->WordWriteTimeoutTyp = 4; /* 14 us */
++ p_cfi->cfiq->WordWriteTimeoutMax = 5; /* 20 us */
++ p_cfi->cfiq->BlockEraseTimeoutTyp = 15; /* Actually 18ms, max 25 */
++ p_cfi->cfiq->BlockEraseTimeoutMax = 15; /* Actually 25ms */
++ p_cfi->cfiq->ChipEraseTimeoutTyp = 17; /* Max is 70ms, typical is 40ms */
++ p_cfi->cfiq->ChipEraseTimeoutMax = 17;
++ break;
++ }
++
++
++
+ for (i=0; i<num_erase_regions; i++){
+ p_cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i];
+ }
+diff -urN linux-mips/drivers/mtd/Config.in mips-linux-2.4.25/drivers/mtd/Config.in
+--- linux-mips/drivers/mtd/Config.in 2005-12-24 15:11:25.091498256 +0000
++++ mips-linux-2.4.25/drivers/mtd/Config.in 2005-12-30 17:27:21.182195224 +0000
+@@ -14,6 +14,9 @@
+ dep_tristate ' MTD partitioning support' CONFIG_MTD_PARTITIONS $CONFIG_MTD
+ dep_tristate ' MTD concatenating support' CONFIG_MTD_CONCAT $CONFIG_MTD
+ dep_tristate ' RedBoot partition table parsing' CONFIG_MTD_REDBOOT_PARTS $CONFIG_MTD_PARTITIONS
++ if [ "$CONFIG_MTD_END_RESERVED" != "" ]; then
++ define_int CONFIG_MTD_END_RESERVED $CONFIG_MTD_END_RESERVED
++ fi
+ dep_tristate ' Command line partition table parsing' CONFIG_MTD_CMDLINE_PARTS $CONFIG_MTD_PARTITIONS
+ if [ "$CONFIG_ARM" = "y" ]; then
+ dep_tristate ' ARM Firmware Suite partition parsing' CONFIG_MTD_AFS_PARTS $CONFIG_MTD_PARTITIONS
+diff -urN linux-mips/drivers/mtd/devices/Makefile mips-linux-2.4.25/drivers/mtd/devices/Makefile
+--- linux-mips/drivers/mtd/devices/Makefile 2005-12-24 15:11:25.128492632 +0000
++++ mips-linux-2.4.25/drivers/mtd/devices/Makefile 2005-12-30 17:27:21.561137616 +0000
+@@ -22,5 +22,6 @@
+ obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
+ obj-$(CONFIG_MTD_LART) += lart.o
+ obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o
++obj-$(CONFIG_MTD_SPIFLASH) += spiflash.o
+
+ include $(TOPDIR)/Rules.make
+diff -urN linux-mips/drivers/mtd/devices/spiflash.c mips-linux-2.4.25/drivers/mtd/devices/spiflash.c
+--- linux-mips/drivers/mtd/devices/spiflash.c 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/drivers/mtd/devices/spiflash.c 2005-12-30 17:27:21.652123784 +0000
+@@ -0,0 +1,506 @@
++
++/*
++ * MTD driver for the SPI Flash Memory support.
++ *
++ * $Id: //depot/sw/releases/linuxsrc/src/kernels/mips-linux-2.4.25/drivers/mtd/devices/spiflash.c#3 $
++ *
++ *
++ * Copyright (c) 2005-2006 Atheros Communications Inc.
++ *
++ * This code 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.
++ *
++ */
++
++/*===========================================================================
++** !!!! VERY IMPORTANT NOTICE !!!! FLASH DATA STORED IN LITTLE ENDIAN FORMAT
++**
++** This module contains the Serial Flash access routines for the Atheros SOC.
++** The Atheros SOC integrates a SPI flash controller that is used to access
++** serial flash parts. The SPI flash controller executes in "Little Endian"
++** mode. THEREFORE, all WRITES and READS from the MIPS CPU must be
++** BYTESWAPPED! The SPI Flash controller hardware by default performs READ
++** ONLY byteswapping when accessed via the SPI Flash Alias memory region
++** (Physical Address 0x0800_0000 - 0x0fff_ffff). The data stored in the
++** flash sectors is stored in "Little Endian" format.
++**
++** The spiflash_write() routine performs byteswapping on all write
++** operations.
++**===========================================================================*/
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/version.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <asm/delay.h>
++#include <asm/io.h>
++#include "spiflash.h"
++
++/* debugging */
++/* #define SPIFLASH_DEBUG */
++
++#ifndef __BIG_ENDIAN
++#error This driver currently only works with big endian CPU.
++#endif
++
++static char module_name[] = "spiflash";
++
++#define MIN(a,b) ((a) < (b) ? (a) : (b))
++#define FALSE 0
++#define TRUE 1
++
++#define ROOTFS_NAME "rootfs"
++
++static __u32 spiflash_regread32(int reg);
++static void spiflash_regwrite32(int reg, __u32 data);
++static __u32 spiflash_sendcmd (int op);
++
++int __init spiflash_init (void);
++void __exit spiflash_exit (void);
++static int spiflash_probe (void);
++static int spiflash_erase (struct mtd_info *mtd,struct erase_info *instr);
++static int spiflash_read (struct mtd_info *mtd, loff_t from,size_t len,size_t *retlen,u_char *buf);
++static int spiflash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf);
++
++/* Flash configuration table */
++struct flashconfig {
++ __u32 byte_cnt;
++ __u32 sector_cnt;
++ __u32 sector_size;
++ __u32 cs_addrmask;
++} flashconfig_tbl[MAX_FLASH] =
++ {
++ { 0, 0, 0, 0},
++ { STM_1MB_BYTE_COUNT, STM_1MB_SECTOR_COUNT, STM_1MB_SECTOR_SIZE, 0x0},
++ { STM_2MB_BYTE_COUNT, STM_2MB_SECTOR_COUNT, STM_2MB_SECTOR_SIZE, 0x0},
++ { STM_4MB_BYTE_COUNT, STM_4MB_SECTOR_COUNT, STM_4MB_SECTOR_SIZE, 0x0}
++ };
++
++/* Mapping of generic opcodes to STM serial flash opcodes */
++struct opcodes {
++ __u16 code;
++ __s8 tx_cnt;
++ __s8 rx_cnt;
++} stm_opcodes[] = {
++ {STM_OP_WR_ENABLE, 1, 0},
++ {STM_OP_WR_DISABLE, 1, 0},
++ {STM_OP_RD_STATUS, 1, 1},
++ {STM_OP_WR_STATUS, 1, 0},
++ {STM_OP_RD_DATA, 4, 4},
++ {STM_OP_FAST_RD_DATA, 1, 0},
++ {STM_OP_PAGE_PGRM, 8, 0},
++ {STM_OP_SECTOR_ERASE, 4, 0},
++ {STM_OP_BULK_ERASE, 1, 0},
++ {STM_OP_DEEP_PWRDOWN, 1, 0},
++ {STM_OP_RD_SIG, 4, 1}
++};
++
++/* Driver private data structure */
++struct spiflash_data {
++ struct mtd_info *mtd;
++ struct mtd_partition *parsed_parts; /* parsed partitions */
++ void *spiflash_readaddr; /* memory mapped data for read */
++ void *spiflash_mmraddr; /* memory mapped register space */
++};
++
++static struct spiflash_data *spidata;
++
++extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
++
++/***************************************************************************************************/
++
++static __u32
++spiflash_regread32(int reg)
++{
++ volatile __u32 *data = (__u32 *)(spidata->spiflash_mmraddr + reg);
++
++ return (*data);
++}
++
++static void
++spiflash_regwrite32(int reg, __u32 data)
++{
++ volatile __u32 *addr = (__u32 *)(spidata->spiflash_mmraddr + reg);
++
++ *addr = data;
++ return;
++}
++
++static __u32
++spiflash_sendcmd (int op)
++{
++ __u32 reg;
++ __u32 mask;
++ struct opcodes *ptr_opcode;
++
++ ptr_opcode = &stm_opcodes[op];
++
++ do {
++ reg = spiflash_regread32(SPI_FLASH_CTL);
++ } while (reg & SPI_CTL_BUSY);
++
++ spiflash_regwrite32(SPI_FLASH_OPCODE, ptr_opcode->code);
++
++ reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | ptr_opcode->tx_cnt |
++ (ptr_opcode->rx_cnt << 4) | SPI_CTL_START;
++
++ spiflash_regwrite32(SPI_FLASH_CTL, reg);
++
++ if (ptr_opcode->rx_cnt > 0) {
++ do {
++ reg = spiflash_regread32(SPI_FLASH_CTL);
++ } while (reg & SPI_CTL_BUSY);
++
++ reg = (__u32) spiflash_regread32(SPI_FLASH_DATA);
++
++ switch (ptr_opcode->rx_cnt) {
++ case 1:
++ mask = 0x000000ff;
++ break;
++ case 2:
++ mask = 0x0000ffff;
++ break;
++ case 3:
++ mask = 0x00ffffff;
++ break;
++ default:
++ mask = 0xffffffff;
++ break;
++ }
++
++ reg &= mask;
++ }
++ else {
++ reg = 0;
++ }
++
++ return reg;
++}
++
++/* Probe SPI flash device
++ * Function returns 0 for failure.
++ * and flashconfig_tbl array index for success.
++ */
++static int
++spiflash_probe (void)
++{
++ __u32 sig;
++ int flash_size;
++
++ /* Read the signature on the flash device */
++ sig = spiflash_sendcmd(SPI_RD_SIG);
++
++ switch (sig) {
++ case STM_8MBIT_SIGNATURE:
++ flash_size = FLASH_1MB;
++ break;
++ case STM_16MBIT_SIGNATURE:
++ flash_size = FLASH_2MB;
++ break;
++ case STM_32MBIT_SIGNATURE:
++ flash_size = FLASH_4MB;
++ break;
++ default:
++ printk (KERN_WARNING "%s: Read of flash device signature failed!\n", module_name);
++ return (0);
++ }
++
++ return (flash_size);
++}
++
++
++static int
++spiflash_erase (struct mtd_info *mtd,struct erase_info *instr)
++{
++ struct opcodes *ptr_opcode;
++ __u32 temp, reg;
++ int finished = FALSE;
++
++#ifdef SPIFLASH_DEBUG
++ printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n",__FUNCTION__,instr->addr,instr->len);
++#endif
++
++ /* sanity checks */
++ if (instr->addr + instr->len > mtd->size) return (-EINVAL);
++
++ ptr_opcode = &stm_opcodes[SPI_SECTOR_ERASE];
++
++ temp = ((__u32)instr->addr << 8) | (__u32)(ptr_opcode->code);
++ spiflash_sendcmd(SPI_WRITE_ENABLE);
++ do {
++ reg = spiflash_regread32(SPI_FLASH_CTL);
++ } while (reg & SPI_CTL_BUSY);
++
++ spiflash_regwrite32(SPI_FLASH_OPCODE, temp);
++
++ reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | ptr_opcode->tx_cnt | SPI_CTL_START;
++ spiflash_regwrite32(SPI_FLASH_CTL, reg);
++
++ do {
++ reg = spiflash_sendcmd(SPI_RD_STATUS);
++ if (!(reg & SPI_STATUS_WIP)) {
++ finished = TRUE;
++ }
++ } while (!finished);
++
++ instr->state = MTD_ERASE_DONE;
++ if (instr->callback) instr->callback (instr);
++
++#ifdef SPIFLASH_DEBUG
++ printk (KERN_DEBUG "%s return\n",__FUNCTION__);
++#endif
++ return (0);
++}
++
++static int
++spiflash_read (struct mtd_info *mtd, loff_t from,size_t len,size_t *retlen,u_char *buf)
++{
++ u_char *read_addr;
++
++#ifdef SPIFLASH_DEBUG
++ printk (KERN_DEBUG "%s(from = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) from,(int)len);
++#endif
++
++ /* sanity checks */
++ if (!len) return (0);
++ if (from + len > mtd->size) return (-EINVAL);
++
++
++ /* we always read len bytes */
++ *retlen = len;
++
++ read_addr = (u_char *)(spidata->spiflash_readaddr + from);
++ memcpy(buf, read_addr, len);
++
++ return (0);
++}
++
++static int
++spiflash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf)
++{
++ int done = FALSE, page_offset, bytes_left, finished;
++ __u32 xact_len, spi_data = 0, opcode, reg;
++
++#ifdef SPIFLASH_DEBUG
++ printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) to,len);
++#endif
++
++ *retlen = 0;
++
++ /* sanity checks */
++ if (!len) return (0);
++ if (to + len > mtd->size) return (-EINVAL);
++
++ opcode = stm_opcodes[SPI_PAGE_PROGRAM].code;
++ bytes_left = len;
++
++ while (done == FALSE) {
++ xact_len = MIN(bytes_left, sizeof(__u32));
++
++ /* 32-bit writes cannot span across a page boundary
++ * (256 bytes). This types of writes require two page
++ * program operations to handle it correctly. The STM part
++ * will write the overflow data to the beginning of the
++ * current page as opposed to the subsequent page.
++ */
++ page_offset = (to & (STM_PAGE_SIZE - 1)) + xact_len;
++
++ if (page_offset > STM_PAGE_SIZE) {
++ xact_len -= (page_offset - STM_PAGE_SIZE);
++ }
++
++ spiflash_sendcmd(SPI_WRITE_ENABLE);
++
++ do {
++ reg = spiflash_regread32(SPI_FLASH_CTL);
++ } while (reg & SPI_CTL_BUSY);
++
++ switch (xact_len) {
++ case 1:
++ (__u8)spi_data = *buf;
++ break;
++ case 2:
++ spi_data = (buf[1] << 8) | buf[0];
++ break;
++ case 3:
++ spi_data = (buf[2] << 16) | (buf[1] << 8) | buf[0];
++ break;
++ case 4:
++ spi_data = (buf[3] << 24) | (buf[2] << 16) |
++ (buf[1] << 8) | buf[0];
++ break;
++ default:
++ printk("spiflash_write: default case\n");
++ break;
++ }
++
++ spiflash_regwrite32(SPI_FLASH_DATA, spi_data);
++ opcode = (opcode & SPI_OPCODE_MASK) | ((__u32)to << 8);
++ spiflash_regwrite32(SPI_FLASH_OPCODE, opcode);
++
++ reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | (xact_len + 4) | SPI_CTL_START;
++ spiflash_regwrite32(SPI_FLASH_CTL, reg);
++ finished = FALSE;
++
++ do {
++ udelay(1);
++ reg = spiflash_sendcmd(SPI_RD_STATUS);
++ if (!(reg & SPI_STATUS_WIP)) {
++ finished = TRUE;
++ }
++ } while (!finished);
++
++ bytes_left -= xact_len;
++ to += xact_len;
++ buf += xact_len;
++
++ *retlen += xact_len;
++
++ if (bytes_left == 0) {
++ done = TRUE;
++ }
++ }
++
++ return (0);
++}
++
++
++int __init
++spiflash_init (void)
++{
++ int result, i;
++ int index, num_parts;
++ struct mtd_info *mtd;
++ struct mtd_partition *mtd_parts;
++
++ spidata = kmalloc(sizeof(struct spiflash_data), GFP_KERNEL);
++ if (!spidata)
++ return (-ENXIO);
++
++ spidata->spiflash_mmraddr = ioremap_nocache(SPI_FLASH_MMR, SPI_FLASH_MMR_SIZE);
++ if (!spidata->spiflash_mmraddr) {
++ printk (KERN_WARNING "%s: Failed to map flash device\n", module_name);
++ kfree(spidata);
++ return (-ENXIO);
++ }
++
++ mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
++ if (!mtd) {
++ kfree(spidata);
++ return (-ENXIO);
++ }
++
++ memset (mtd,0,sizeof (*mtd));
++
++ printk ("MTD driver for SPI flash.\n");
++ printk ("%s: Probing for Serial flash ...\n", module_name);
++ if (!(index = spiflash_probe ())) {
++ printk (KERN_WARNING "%s: Found no serial flash device\n", module_name);
++ kfree(mtd);
++ kfree(spidata);
++ return (-ENXIO);
++ }
++ printk ("%s: Found SPI serial Flash.\n", module_name);
++ printk ("%d: size\n", flashconfig_tbl[index].byte_cnt);
++
++ spidata->spiflash_readaddr = ioremap_nocache(SPI_FLASH_READ, flashconfig_tbl[index].byte_cnt);
++ if (!spidata->spiflash_readaddr) {
++ printk (KERN_WARNING "%s: Failed to map flash device\n", module_name);
++ kfree(mtd);
++ kfree(spidata);
++ return (-ENXIO);
++ }
++
++ mtd->name = module_name;
++ mtd->type = MTD_NORFLASH;
++ mtd->flags = (MTD_CAP_NORFLASH|MTD_WRITEABLE);
++ mtd->size = flashconfig_tbl[index].byte_cnt;
++ mtd->erasesize = flashconfig_tbl[index].sector_size;
++ mtd->numeraseregions = 0;
++ mtd->eraseregions = NULL;
++ mtd->module = THIS_MODULE;
++ mtd->erase = spiflash_erase;
++ mtd->read = spiflash_read;
++ mtd->write = spiflash_write;
++
++#ifdef SPIFLASH_DEBUG
++ printk (KERN_DEBUG
++ "mtd->name = %s\n"
++ "mtd->size = 0x%.8x (%uM)\n"
++ "mtd->erasesize = 0x%.8x (%uK)\n"
++ "mtd->numeraseregions = %d\n",
++ mtd->name,
++ mtd->size, mtd->size / (1024*1024),
++ mtd->erasesize, mtd->erasesize / 1024,
++ mtd->numeraseregions);
++
++ if (mtd->numeraseregions) {
++ for (result = 0; result < mtd->numeraseregions; result++) {
++ printk (KERN_DEBUG
++ "\n\n"
++ "mtd->eraseregions[%d].offset = 0x%.8x\n"
++ "mtd->eraseregions[%d].erasesize = 0x%.8x (%uK)\n"
++ "mtd->eraseregions[%d].numblocks = %d\n",
++ result,mtd->eraseregions[result].offset,
++ result,mtd->eraseregions[result].erasesize,mtd->eraseregions[result].erasesize / 1024,
++ result,mtd->eraseregions[result].numblocks);
++ }
++ }
++#endif
++
++#ifndef CONFIG_BLK_DEV_INITRD
++ /* parse redboot partitions */
++ num_parts = parse_redboot_partitions(mtd, &spidata->parsed_parts);
++
++#ifdef SPIFLASH_DEBUG
++ printk (KERN_DEBUG "Found %d redboot partitions\n", num_parts);
++#endif
++
++ if (num_parts) {
++ result = add_mtd_partitions(mtd, spidata->parsed_parts, num_parts);
++ /* Find root partition */
++ mtd_parts = spidata->parsed_parts;
++ for (i=0; i < num_parts; i++) {
++ if (!strcmp(mtd_parts[i].name, ROOTFS_NAME)) {
++ /* Create root device */
++ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, i);
++ break;
++ }
++ }
++ } else {
++#ifdef SPIFLASH_DEBUG
++ printk (KERN_DEBUG "Did not find any redboot partitions\n");
++#endif
++ kfree(mtd);
++ kfree(spidata);
++ return (-ENXIO);
++ }
++#endif
++
++ spidata->mtd = mtd;
++
++ return (result);
++}
++
++void __exit
++spiflash_exit (void)
++{
++ if (spidata && spidata->parsed_parts) {
++ del_mtd_partitions (spidata->mtd);
++ kfree(spidata->mtd);
++ kfree(spidata);
++ }
++}
++
++module_init (spiflash_init);
++module_exit (spiflash_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Atheros Communications Inc");
++MODULE_DESCRIPTION("MTD driver for SPI Flash on Atheros SOC");
++
+diff -urN linux-mips/drivers/mtd/devices/spiflash.h mips-linux-2.4.25/drivers/mtd/devices/spiflash.h
+--- linux-mips/drivers/mtd/devices/spiflash.h 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/drivers/mtd/devices/spiflash.h 2005-12-30 17:27:21.652123784 +0000
+@@ -0,0 +1,113 @@
++/*
++ * SPI Flash Memory support header file.
++ *
++ * $Id: //depot/sw/releases/linuxsrc/src/kernels/mips-linux-2.4.25/drivers/mtd/devices/spiflash.h#3 $
++ *
++ *
++ * Copyright (c) 2005, Atheros Communications Inc.
++ *
++ * This code 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.
++ *
++ */
++#define FLASH_1MB 1
++#define FLASH_2MB 2
++#define FLASH_4MB 3
++#define MAX_FLASH 4
++
++#define STM_PAGE_SIZE 256
++
++#define STM_8MBIT_SIGNATURE 0x13
++#define STM_M25P80_BYTE_COUNT 1048576
++#define STM_M25P80_SECTOR_COUNT 16
++#define STM_M25P80_SECTOR_SIZE 0x10000
++
++#define STM_16MBIT_SIGNATURE 0x14
++#define STM_M25P16_BYTE_COUNT 2097152
++#define STM_M25P16_SECTOR_COUNT 32
++#define STM_M25P16_SECTOR_SIZE 0x10000
++
++#define STM_32MBIT_SIGNATURE 0x15
++#define STM_M25P32_BYTE_COUNT 4194304
++#define STM_M25P32_SECTOR_COUNT 64
++#define STM_M25P32_SECTOR_SIZE 0x10000
++
++#define STM_1MB_BYTE_COUNT STM_M25P80_BYTE_COUNT
++#define STM_1MB_SECTOR_COUNT STM_M25P80_SECTOR_COUNT
++#define STM_1MB_SECTOR_SIZE STM_M25P80_SECTOR_SIZE
++#define STM_2MB_BYTE_COUNT STM_M25P16_BYTE_COUNT
++#define STM_2MB_SECTOR_COUNT STM_M25P16_SECTOR_COUNT
++#define STM_2MB_SECTOR_SIZE STM_M25P16_SECTOR_SIZE
++#define STM_4MB_BYTE_COUNT STM_M25P32_BYTE_COUNT
++#define STM_4MB_SECTOR_COUNT STM_M25P32_SECTOR_COUNT
++#define STM_4MB_SECTOR_SIZE STM_M25P32_SECTOR_SIZE
++
++#define SPI_WRITE_ENABLE 0
++#define SPI_WRITE_DISABLE 1
++#define SPI_RD_STATUS 2
++#define SPI_WR_STATUS 3
++#define SPI_RD_DATA 4
++#define SPI_FAST_RD_DATA 5
++#define SPI_PAGE_PROGRAM 6
++#define SPI_SECTOR_ERASE 7
++#define SPI_BULK_ERASE 8
++#define SPI_DEEP_PWRDOWN 9
++#define SPI_RD_SIG 10
++#define SPI_MAX_OPCODES 11
++
++#define SFI_WRITE_BUFFER_SIZE 4
++#define SFI_FLASH_ADDR_MASK 0x00ffffff
++
++/*
++ * ST Microelectronics Opcodes for Serial Flash
++ */
++
++#define STM_OP_WR_ENABLE 0x06 /* Write Enable */
++#define STM_OP_WR_DISABLE 0x04 /* Write Disable */
++#define STM_OP_RD_STATUS 0x05 /* Read Status */
++#define STM_OP_WR_STATUS 0x01 /* Write Status */
++#define STM_OP_RD_DATA 0x03 /* Read Data */
++#define STM_OP_FAST_RD_DATA 0x0b /* Fast Read Data */
++#define STM_OP_PAGE_PGRM 0x02 /* Page Program */
++#define STM_OP_SECTOR_ERASE 0xd8 /* Sector Erase */
++#define STM_OP_BULK_ERASE 0xc7 /* Bulk Erase */
++#define STM_OP_DEEP_PWRDOWN 0xb9 /* Deep Power-Down Mode */
++#define STM_OP_RD_SIG 0xab /* Read Electronic Signature */
++
++#define STM_STATUS_WIP 0x01 /* Write-In-Progress */
++#define STM_STATUS_WEL 0x02 /* Write Enable Latch */
++#define STM_STATUS_BP0 0x04 /* Block Protect 0 */
++#define STM_STATUS_BP1 0x08 /* Block Protect 1 */
++#define STM_STATUS_BP2 0x10 /* Block Protect 2 */
++#define STM_STATUS_SRWD 0x80 /* Status Register Write Disable */
++
++/*
++ * SPI Flash Interface Registers
++ */
++#define AR531XPLUS_SPI_READ 0x1fc00000
++#define AR531XPLUS_SPI_MMR 0x11300000
++#define AR531XPLUS_SPI_MMR_SIZE 12
++
++#define AR531XPLUS_SPI_CTL 0x00
++#define AR531XPLUS_SPI_OPCODE 0x04
++#define AR531XPLUS_SPI_DATA 0x08
++
++#define SPI_FLASH_READ AR531XPLUS_SPI_READ
++#define SPI_FLASH_MMR AR531XPLUS_SPI_MMR
++#define SPI_FLASH_MMR_SIZE AR531XPLUS_SPI_MMR_SIZE
++#define SPI_FLASH_CTL AR531XPLUS_SPI_CTL
++#define SPI_FLASH_OPCODE AR531XPLUS_SPI_OPCODE
++#define SPI_FLASH_DATA AR531XPLUS_SPI_DATA
++
++#define SPI_CTL_START 0x00000100
++#define SPI_CTL_BUSY 0x00010000
++#define SPI_CTL_TXCNT_MASK 0x0000000f
++#define SPI_CTL_RXCNT_MASK 0x000000f0
++#define SPI_CTL_TX_RX_CNT_MASK 0x000000ff
++#define SPI_CTL_SIZE_MASK 0x00060000
++
++#define SPI_CTL_CLK_SEL_MASK 0x03000000
++#define SPI_OPCODE_MASK 0x000000ff
++
++#define SPI_STATUS_WIP STM_STATUS_WIP
+diff -urN linux-mips/drivers/mtd/maps/Config.in mips-linux-2.4.25/drivers/mtd/maps/Config.in
+--- linux-mips/drivers/mtd/maps/Config.in 2005-12-24 15:11:25.158488072 +0000
++++ mips-linux-2.4.25/drivers/mtd/maps/Config.in 2005-12-30 17:27:21.660122568 +0000
+@@ -9,7 +9,14 @@
+ dep_tristate ' CFI Flash device in physical memory map' CONFIG_MTD_PHYSMAP $CONFIG_MTD_GEN_PROBE
+ if [ "$CONFIG_MTD_PHYSMAP" = "y" -o "$CONFIG_MTD_PHYSMAP" = "m" ]; then
+ hex ' Physical start address of flash mapping' CONFIG_MTD_PHYSMAP_START 0x8000000
+- hex ' Physical length of flash mapping' CONFIG_MTD_PHYSMAP_LEN 0x4000000
++ if [ "$CONFIG_FLASH_2MB" = "y" ]; then
++ define_hex CONFIG_MTD_PHYSMAP_LEN 200000
++ fi
++ if [ "$CONFIG_FLASH_4MB" = "y" ]; then
++ define_hex CONFIG_MTD_PHYSMAP_LEN 400000
++ fi
++
++# hex ' Physical length of flash mapping' CONFIG_MTD_PHYSMAP_LEN 0x4000000
+ int ' Bus width in octets' CONFIG_MTD_PHYSMAP_BUSWIDTH 2
+ fi
+
+diff -urN linux-mips/drivers/mtd/maps/physmap.c mips-linux-2.4.25/drivers/mtd/maps/physmap.c
+--- linux-mips/drivers/mtd/maps/physmap.c 2005-12-24 15:11:25.217479104 +0000
++++ mips-linux-2.4.25/drivers/mtd/maps/physmap.c 2005-12-30 17:27:22.044064200 +0000
+@@ -80,12 +80,25 @@
+ };
+
+ #ifdef CONFIG_MTD_PARTITIONS
+-#ifdef CONFIG_MTD_CMDLINE_PARTS
++#if defined(CONFIG_MTD_CMDLINE_PARTS) || defined(CONFIG_MTD_REDBOOT_PARTS)
+ static struct mtd_partition *mtd_parts = 0;
+ static int mtd_parts_nb = 0;
+ #else
+ static struct mtd_partition physmap_partitions[] = {
+ /* Put your own partition definitions here */
++ {
++ name: "rootfs",
++#ifdef CONFIG_FLASH_2MB
++ size: 0x000e0000,
++ offset: 0x000f0000,
++#endif
++#ifdef CONFIG_FLASH_4MB
++ size: 0x002dd000,
++ offset: 0x00100000,
++#endif
++
++ /* Allow file system to be mounted for writing */
++ }
+ #if 0
+ {
+ name: "bootROM",
+@@ -138,6 +151,22 @@
+
+ add_mtd_device(mymtd);
+ #ifdef CONFIG_MTD_PARTITIONS
++#ifdef CONFIG_MTD_REDBOOT_PARTS
++ {
++ extern int parse_redboot_partitions(struct mtd_info *master,
++ struct mtd_partition **pparts);
++
++ struct mtd_partition *rb_parts = 0;
++ int rb_parts_nb = 0;
++
++ rb_parts_nb = parse_redboot_partitions(mymtd, &rb_parts);
++ if (rb_parts_nb > 0) {
++ printk(KERN_NOTICE
++ "Using redboot flash partitioning");
++ add_mtd_partitions (mymtd, rb_parts, rb_parts_nb);
++ }
++ }
++#endif
+ #ifdef CONFIG_MTD_CMDLINE_PARTS
+ mtd_parts_nb = parse_cmdline_partitions(mymtd, &mtd_parts,
+ "phys");
+@@ -147,7 +176,8 @@
+ "Using command line partition definition\n");
+ add_mtd_partitions (mymtd, mtd_parts, mtd_parts_nb);
+ }
+-#else
++#endif
++#if !defined(CONFIG_MTD_CMDLINE_PARTS) && !defined(CONFIG_MTD_REDBOOT_PARTS)
+ if (NUM_PARTITIONS != 0)
+ {
+ printk(KERN_NOTICE
+diff -urN linux-mips/drivers/mtd/redboot.c mips-linux-2.4.25/drivers/mtd/redboot.c
+--- linux-mips/drivers/mtd/redboot.c 2005-12-24 15:11:25.249474240 +0000
++++ mips-linux-2.4.25/drivers/mtd/redboot.c 2005-12-30 17:27:22.517992152 +0000
+@@ -51,8 +51,14 @@
+ return -ENOMEM;
+
+ /* Read the start of the last erase block */
+- ret = master->read(master, master->size - master->erasesize,
++ {
++ u_int32_t part_table_start = master->size - master->erasesize;
++#if defined(CONFIG_MTD_END_RESERVED)
++ part_table_start -= CONFIG_MTD_END_RESERVED;
++#endif
++ ret = master->read(master, part_table_start,
+ PAGE_SIZE, &retlen, (void *)buf);
++ }
+
+ if (ret)
+ goto out;
+diff -urN linux-mips/drivers/net/Config.in mips-linux-2.4.25/drivers/net/Config.in
+--- linux-mips/drivers/net/Config.in 2005-12-24 15:11:25.725401888 +0000
++++ mips-linux-2.4.25/drivers/net/Config.in 2005-12-30 17:27:22.684966768 +0000
+@@ -24,6 +24,18 @@
+ comment 'Ethernet (10 or 100Mbit)'
+ bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET
+ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
++ define_bool CONFIG_VENETDEV n
++ tristate ' BUILT-IN ATHEROS ENET DRIVER' CONFIG_NET_ATHEROS_ETHER
++ if [ "$CONFIG_AP38" = "y" -o "$CONFIG_AP48" = "y" ]; then
++ define_bool CONFIG_KENDIN_ENET_PHY y
++ elif [ "$CONFIG_AP30ASK" = "y" ]; then
++ define_bool CONFIG_KENDIN_KS8995XA_ENET_PHY y
++ bool 'Multiple Ethernet address hack ' CONFIG_ASK_MULT_MAC_HACK
++ elif [ "$CONFIG_AP51" = "y" ]; then
++ define_bool CONFIG_ICPLUS_ENET_PHY y
++ else
++ define_bool CONFIG_MARVELL_ENET_PHY y
++ fi
+ if [ "$CONFIG_ARM" = "y" ]; then
+ dep_bool ' ARM EBSA110 AM79C961A support' CONFIG_ARM_AM79C961A $CONFIG_ARCH_EBSA110
+ tristate ' Cirrus Logic CS8900A support' CONFIG_ARM_CIRRUS
+diff -urN linux-mips/drivers/net/Makefile mips-linux-2.4.25/drivers/net/Makefile
+--- linux-mips/drivers/net/Makefile 2005-12-24 15:11:25.726401736 +0000
++++ mips-linux-2.4.25/drivers/net/Makefile 2005-12-30 17:27:22.709962968 +0000
+@@ -31,6 +31,10 @@
+ obj-y += e1000/e1000.o
+ endif
+
++ifeq ($(CONFIG_NET_ATHEROS_ETHER),y)
++ obj-y += ath/ae531x.o
++endif
++
+ ifeq ($(CONFIG_BONDING),y)
+ obj-y += bonding/bonding.o
+ endif
+@@ -53,8 +57,13 @@
+ subdir-$(CONFIG_SKFP) += skfp
+ subdir-$(CONFIG_E100) += e100
+ subdir-$(CONFIG_E1000) += e1000
++subdir-$(CONFIG_NET_ATHEROS_ETHER) += ath
+ subdir-$(CONFIG_BONDING) += bonding
+
++ifeq ($(CONFIG_ATHAP33),y)
++subdir-$(CONFIG_ATHAP33) += athap33
++endif
++
+ #
+ # link order important here
+ #
+@@ -242,6 +251,10 @@
+ obj-$(CONFIG_R8169) += r8169.o
+ obj-$(CONFIG_AMD8111_ETH) += amd8111e.o mii.o
+
++ifeq ($(CONFIG_ATHAP33),y)
++obj-$(CONFIG_ATHAP33) += athap33/ath_ap_mips.o
++endif
++
+ # non-drivers/net drivers who want mii lib
+ obj-$(CONFIG_PCMCIA_SMC91C92) += mii.o
+ obj-$(CONFIG_USB_USBNET) += mii.o
+diff -urN linux-mips/fs/jffs2/nodelist.h mips-linux-2.4.25/fs/jffs2/nodelist.h
+--- linux-mips/fs/jffs2/nodelist.h 2005-12-24 15:11:50.407649616 +0000
++++ mips-linux-2.4.25/fs/jffs2/nodelist.h 2005-12-30 17:27:51.289618200 +0000
+@@ -31,7 +31,7 @@
+ * provisions above, a recipient may use your version of this file
+ * under either the RHEPL or the GPL.
+ *
+- * $Id: nodelist.h,v 1.46.2.5 2003/11/02 13:54:20 dwmw2 Exp $
++ * $Id: //depot/sw/releases/linuxsrc/src/kernels/mips-linux-2.4.25/fs/jffs2/nodelist.h#3 $
+ *
+ */
+
+@@ -222,8 +222,8 @@
+ #define ALLOC_DELETION 1 /* Deletion node. Best to allow it */
+ #define ALLOC_GC 2 /* Space requested for GC. Give it or die */
+
+-#define JFFS2_RESERVED_BLOCKS_BASE 3 /* Number of free blocks there must be before we... */
+-#define JFFS2_RESERVED_BLOCKS_WRITE (JFFS2_RESERVED_BLOCKS_BASE + 2) /* ... allow a normal filesystem write */
++#define JFFS2_RESERVED_BLOCKS_BASE 2 /* Number of free blocks there must be before we... */
++#define JFFS2_RESERVED_BLOCKS_WRITE (JFFS2_RESERVED_BLOCKS_BASE + 1) /* ... allow a normal filesystem write */
+ #define JFFS2_RESERVED_BLOCKS_DELETION (JFFS2_RESERVED_BLOCKS_BASE + 1) /* ... allow a normal filesystem deletion */
+ #define JFFS2_RESERVED_BLOCKS_GCTRIGGER (JFFS2_RESERVED_BLOCKS_BASE + 3) /* ... wake up the GC thread */
+ #define JFFS2_RESERVED_BLOCKS_GCBAD (JFFS2_RESERVED_BLOCKS_BASE + 1) /* ... pick a block from the bad_list to GC */
+diff -urN linux-mips/fs/partitions/Config.in mips-linux-2.4.25/fs/partitions/Config.in
+--- linux-mips/fs/partitions/Config.in 2005-12-24 15:11:52.366351848 +0000
++++ mips-linux-2.4.25/fs/partitions/Config.in 2005-12-30 17:27:52.279467720 +0000
+@@ -39,7 +39,7 @@
+ fi
+ if [ "$CONFIG_AMIGA" != "y" -a "$CONFIG_ATARI" != "y" -a \
+ "$CONFIG_MAC" != "y" -a "$CONFIG_SGI_IP22" != "y" -a \
+- "$CONFIG_SGI_IP27" != "y" ]; then
++ "$CONFIG_SGI_IP27" != "y" -a "$CONFIG_AR531X" != "y" ]; then
+ define_bool CONFIG_MSDOS_PARTITION y
+ fi
+ if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_AFFS_FS" = "y" ]; then
+diff -urN linux-mips/include/asm-mips/atheros/ar531xbsp.h mips-linux-2.4.25/include/asm-mips/atheros/ar531xbsp.h
+--- linux-mips/include/asm-mips/atheros/ar531xbsp.h 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/include/asm-mips/atheros/ar531xbsp.h 2005-12-30 17:28:01.523062480 +0000
+@@ -0,0 +1,17 @@
++#ifndef __ASM_ATHEROS_BSP_SUPPORT_H
++#define __ASM_ATHEROS_BSP_SUPPORT_H
++/*
++ * These are definitions and functions provided by the bsp to support the
++ * AR5312 WiSoC running LSDK. For different BSP implementations, different
++ * BSP functions will be needed.
++ */
++
++extern unsigned int ar531x_sys_frequency(void);
++extern const char* get_system_type(void);
++
++#ifdef CONFIG_KGDB
++extern void kgdbInit(void);
++extern int kgdbEnabled(void);
++#endif
++
++#endif /* __ASM_ATHEROS_BSP_SUPPORT_H */
+diff -urN linux-mips/include/asm-mips/bootinfo.h mips-linux-2.4.25/include/asm-mips/bootinfo.h
+--- linux-mips/include/asm-mips/bootinfo.h 2005-12-24 15:12:00.645093288 +0000
++++ mips-linux-2.4.25/include/asm-mips/bootinfo.h 2005-12-30 17:28:01.534060808 +0000
+@@ -37,6 +37,7 @@
+ #define MACH_GROUP_HP_LJ 20 /* Hewlett Packard LaserJet */
+ #define MACH_GROUP_LASAT 21
+ #define MACH_GROUP_TITAN 22 /* PMC-Sierra Titan */
++#define MACH_GROUP_AR531X 23 /* Atheros AR531X */
+
+ /*
+ * Valid machtype values for group unknown (low order halfword of mips_machtype)
+@@ -198,6 +199,17 @@
+ */
+ #define MACH_TITAN_YOSEMITE 1 /* PMC-Sierra Yosemite */
+
++/*
++ * Valid machtype for group MACH_GROUP_AR5312
++ */
++#define MACH_ATHEROS_UNUSED 0
++#define MACH_ATHEROS_AP30 1 /* AP30 */
++#define MACH_ATHEROS_AP33 2 /* AP33 */
++#define MACH_ATHEROS_AP38 3 /* AP38 */
++#define MACH_ATHEROS_AP43 4 /* AP43 */
++#define MACH_ATHEROS_AP48 5 /* AP48 */
++#define MACH_ATHEROS_PB32 6 /* PB32 */
++
+ #define CL_SIZE (256)
+
+ const char *get_system_type(void);
+diff -urN linux-mips/include/asm-mips/page.h mips-linux-2.4.25/include/asm-mips/page.h
+--- linux-mips/include/asm-mips/page.h 2005-12-24 15:12:01.097024584 +0000
++++ mips-linux-2.4.25/include/asm-mips/page.h 2005-12-30 17:28:01.898005480 +0000
+@@ -13,7 +13,6 @@
+ #include <linux/config.h>
+ #include <asm/break.h>
+
+-#ifdef __KERNEL__
+
+ /*
+ * PAGE_SHIFT determines the page size
+@@ -30,6 +29,7 @@
+ #define PAGE_SIZE (1L << PAGE_SHIFT)
+ #define PAGE_MASK (~(PAGE_SIZE-1))
+
++#ifdef __KERNEL__
+ #ifndef __ASSEMBLY__
+
+ #include <asm/cacheflush.h>
+diff -urN linux-mips/include/asm-mips/serial.h mips-linux-2.4.25/include/asm-mips/serial.h
+--- linux-mips/include/asm-mips/serial.h 2005-12-24 15:12:01.130019568 +0000
++++ mips-linux-2.4.25/include/asm-mips/serial.h 2005-12-30 17:28:02.143968088 +0000
+@@ -410,6 +410,11 @@
+ #define DDB5477_SERIAL_PORT_DEFNS
+ #endif
+
++#if defined(CONFIG_AR531X)
++#undef RS_TABLE_SIZE
++#define RS_TABLE_SIZE 1
++#endif
++
+ #define SERIAL_PORT_DFNS \
+ ATLAS_SERIAL_PORT_DEFNS \
+ AU1000_SERIAL_PORT_DEFNS \
+diff -urN linux-mips/kernel/printk.c mips-linux-2.4.25/kernel/printk.c
+--- linux-mips/kernel/printk.c 2005-12-24 15:12:09.361768152 +0000
++++ mips-linux-2.4.25/kernel/printk.c 2005-12-30 17:28:11.943478336 +0000
+@@ -383,6 +383,18 @@
+ _call_console_drivers(start_print, end, msg_level);
+ }
+
++#if CONFIG_EARLY_PRINTK_HACK
++void putDebugChar(char byte);
++static void emit_log_char(char c)
++{
++ if (c == '\n') {
++ putDebugChar('\r');
++ putDebugChar('\n');
++ } else {
++ putDebugChar(c);
++ }
++}
++#else
+ static void emit_log_char(char c)
+ {
+ LOG_BUF(log_end) = c;
+@@ -394,6 +406,7 @@
+ if (logged_chars < LOG_BUF_LEN)
+ logged_chars++;
+ }
++#endif
+
+ /*
+ * This is printk. It can be called from any context. We want it to work.
+@@ -696,3 +709,4 @@
+ tty->driver.write(tty, 0, msg, strlen(msg));
+ return;
+ }
++
+diff -urN linux-mips-orig/drivers/net/ath/ae531x.h linux-mips-new/drivers/net/ath/ae531x.h
+--- linux-mips-orig/drivers/net/ath/ae531x.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ae531x.h 2005-12-31 12:33:57.672538976 +0000
+@@ -0,0 +1,43 @@
++#ifndef __AE531X_H
++#define __AE531X_H
++
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <asm/io.h>
++
++#include "ar531xlnx.h"
++#include "ae531xreg.h"
++#include "ae531xmac.h"
++
++extern void *ae531x_rxbuf_alloc(ae531x_MAC_t *MACInfo, char **rxBuffp,
++ int *rxBuffSizep);
++extern void ae531x_swptr_free(VIRT_ADDR desc);
++extern BOOL ae531x_twisted_enet(void);
++extern void ae531x_MiiWrite(UINT32 phyBase, UINT32 phyAddr, UINT8 reg,
++ UINT16 data);
++extern UINT16 ae531x_MiiRead(UINT32 phyBase, UINT32 phyAddr, UINT8 reg);
++extern void ae531x_unitLinkGained(int ethUnit);
++extern void ae531x_unitLinkLost(int ethUnit);
++extern void ae531x_WriteDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data);
++extern void ae531x_MACReset(ae531x_MAC_t *MACInfo);
++extern void ae531x_DisableComm(ae531x_MAC_t *MACInfo);
++extern void ae531x_FreeQueues(ae531x_MAC_t *MACInfo);
++extern void ae531x_reset(ae531x_MAC_t *MACInfo);
++extern int ae531x_AllocateQueues(ae531x_MAC_t *MACInfo);
++extern void ae531x_EnableComm(ae531x_MAC_t *MACInfo);
++extern void ae531x_DmaIntEnable(ae531x_MAC_t *MACInfo);
++extern void ae531x_DmaIntDisable(ae531x_MAC_t *MACInfo);
++extern void ae531x_DmaReset(ae531x_MAC_t *MACInfo);
++extern void ae531x_BeginResetMode(ae531x_MAC_t *MACInfo);
++extern void ae531x_AckIntr(ae531x_MAC_t *MACInfo, UINT32 data);
++extern void ae531x_SetDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
++extern BOOL ae531x_IsInResetMode(ae531x_MAC_t *MACInfo);
++extern UINT32 ae531x_ReadDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg);
++extern void ae531x_ClearDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
++
++#endif /* __AE531X_H */
+diff -urN linux-mips-orig/drivers/net/ath/ae531xlnx.c linux-mips-new/drivers/net/ath/ae531xlnx.c
+--- linux-mips-orig/drivers/net/ath/ae531xlnx.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ae531xlnx.c 2005-12-31 12:33:57.673538824 +0000
+@@ -0,0 +1,1303 @@
++/*
++ * 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.
++ */
++
++/*
++ * Ethernet driver for Atheros' ae531x ethernet MAC.
++ * This is a fairly generic driver, but it's intended
++ * for use in typical Atheros products.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <asm/io.h>
++
++#include "ar531xlnx.h"
++#include "ae531xreg.h"
++#include "ae531xmac.h"
++#include "ae531x.h"
++
++#ifndef EXPORT_SYMTAB
++#define EXPORT_SYMTAB
++#endif
++
++#ifdef DEBUG
++void my_mvPhyShow(int ethUnit);
++#endif
++
++static struct ar531x_boarddata *ar531x_boardConfig=NULL;
++
++static char *radioConfig=NULL;
++
++#define AE531X_LAN_PORT 0
++#define AE531X_DEV_PER_MAC 1
++
++/*
++ * ae531x_MAC_state contains driver-specific linux-specific per-MAC information.
++ * The OSinfo member of ae531x_MAC_t points to one of these.
++ */
++typedef struct ae531x_MAC_state {
++ int irq;
++ struct tq_struct restart_task;
++ struct net_device_stats stats;
++ struct ae531x_dev_sw_state *dev_sw_state[AE531X_DEV_PER_MAC];
++ int primary_dev;
++ ae531x_MAC_t MACInfo; /* hardware state */
++} ae531x_MAC_state_t;
++
++/*
++ * ae531x_dev_sw_state contains driver-specific linux-specific per-device
++ * information. The net_device priv member points to one of these, and
++ * this structure contains a pointer to the associated MAC information.
++ */
++
++typedef struct ae531x_dev_sw_state {
++ int enetUnit; /* system unit number "eth%d" */
++ int unit_on_MAC; /* MAC-relative unit number */
++ struct net_device *dev;
++ ae531x_MAC_state_t *MAC_state; /* underlying MAC hw/sw state */
++} ae531x_dev_sw_state_t;
++
++/*
++ * Driver-independent linux-specific per-ethernet device software information.
++ */
++static struct net_device *ae531x_MAC_dev[AR531X_NUM_ENET_MAC * AE531X_DEV_PER_MAC];
++
++/* Driver-dependent per-MAC information */
++static ae531x_MAC_state_t per_MAC_info[AR531X_NUM_ENET_MAC];
++
++/*
++ * Receive buffers need enough room to hold the following:
++ * 1) a max MTU-sized packet.
++ * 2) space for an ethernet header
++ * 3) room at the beginning of the receive buffer in order
++ * to facilitate cooperating drivers that need to PREpend
++ * data.
++ * 4) Depending on configuration, we may need some additional
++ * room at the END of the rx buffer for phy-supplied
++ * trailers (if any). (c.f. CONFIG_VENETDEV)
++ *
++ * The DMA engine insists on 32-bit aligned RX buffers.
++ * TBDXXX: With current code, the IP stack ends up looking
++ * at misaligned headers with word operations. The misaligned
++ * reads are software-emulated via handle_adel_int. We'd
++ * rather align the buffers on a 16-bit boundary, but the
++ * DMA engine doesn't permit it???
++ */
++#define ETH_MAX_MTU 1518
++#define AE531X_RX_BUF_SIZE \
++ (((RXBUFF_RESERVE + ETH_HLEN + ETH_MAX_MTU + PHY_TRAILER_SIZE) + 3) & ~3)
++
++/* Forward references to local functions */
++static void ae531x_TxReap(ae531x_MAC_state_t *MAC_state);
++static int ae531x_phy_poll(void *data);
++static int ae531x_MAC_stop(struct net_device *dev);
++static int ae531x_MAC_open(struct net_device *dev);
++
++/*******************************************************************************
++* ae531x_MAC_poll checks for received packets, and sends data
++* up the stack.
++*/
++int
++ae531x_MAC_poll(struct net_device *dev, int *budget)
++{
++ struct sk_buff *skb;
++ struct sk_buff *newskb;
++ char *rxBufp;
++ int unused_length;
++ VIRT_ADDR rxDesc;
++ int length;
++ ae531x_dev_sw_state_t *dev_sw_state;
++ ae531x_MAC_state_t *MAC_state;
++ ae531x_MAC_t *MACInfo;
++ u32 cmdsts;
++ int rx_limit;
++ int rx_received;
++ int rxDescCount;
++ struct net_device *rxdev;
++ int early_stop;
++ int retval;
++#ifdef DEBUG
++ static int rxDescCountMax = 0;
++#endif
++
++ ARRIVE();
++
++ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
++ MAC_state = dev_sw_state->MAC_state;
++ MACInfo = &MAC_state->MACInfo;
++ rx_limit = MAC_state->dev_sw_state[MAC_state->primary_dev]->dev->quota;
++ rx_received = 0;
++
++ rxDescCount = 0;
++
++ early_stop = 0;
++ do {
++ ae531x_AckIntr(MACInfo, DmaIntRxCompleted);
++
++ for(;!early_stop;) {
++ rxDesc = MACInfo->rxQueue.curDescAddr;
++ cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(rxDesc));
++
++ AE531X_PRINT(AE531X_DEBUG_RX,
++ ("examine rxDesc %p with cmdsts=0x%x\n",
++ (void *)rxDesc, cmdsts));
++
++ if (cmdsts & DescOwnByDma) {
++ /* There's nothing left to process in the RX ring */
++ goto rx_all_done;
++ }
++
++ rxDescCount++;
++
++ AE531X_CONSUME_DESC((&MACInfo->rxQueue));
++
++ A_DATA_CACHE_INVAL(rxDesc, AE531X_DESC_SIZE);
++
++ /* Process a packet */
++ length = AE531X_DESC_STATUS_RX_SIZE(cmdsts) - ETH_CRC_LEN;
++ if ( (cmdsts & (DescRxFirst |DescRxLast | DescRxErrors)) ==
++ (DescRxFirst | DescRxLast) ) {
++ /* Descriptor status indicates "NO errors" */
++ skb = AE531X_DESC_SWPTR_GET(rxDesc);
++
++ /*
++ * Allocate a replacement skb.
++ * We want to get another buffer ready for Rx ASAP.
++ */
++ newskb = (struct sk_buff *)ae531x_rxbuf_alloc(MACInfo, &rxBufp, &unused_length);
++ if(newskb == NULL ) {
++ /*
++ * Give this descriptor back to the DMA engine,
++ * and drop the received packet.
++ */
++ MAC_state->stats.rx_dropped++;
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("Can't allocate new skb\n"));
++ } else {
++ AE531X_DESC_BUFPTR_SET(rxDesc, virt_to_bus(rxBufp));
++ AE531X_DESC_SWPTR_SET(rxDesc, newskb);
++ }
++
++ AE531X_DESC_STATUS_SET(rxDesc, DescOwnByDma);
++ rxDesc = NULL; /* sanity -- cannot use rxDesc now */
++ sysWbFlush();
++
++ if (newskb == NULL) {
++ retval = 1;
++ goto rx_no_skbs;
++ } else {
++ /* Sync data cache w.r.t. DMA */
++ A_DATA_CACHE_INVAL(skb->data, length);
++
++ rxdev = dev_sw_state->dev;
++
++ if (rxdev == NULL) {
++ /*
++ * We received a packet for a virtual enet device
++ * that is no longer up. Ignore it.
++ */
++ kfree_skb(skb);
++ continue;
++ }
++
++ /* Advance data pointer to show that there's data here */
++ skb_put(skb, length);
++ skb->protocol = eth_type_trans(skb, rxdev);
++ skb->dev = rxdev;
++ rxdev->last_rx = jiffies;
++ rxdev->quota--;
++
++ if (rx_limit-- < 0) {
++ early_stop=1;
++ /* We've done enough for now -- more later */
++ AE531X_PRINT(AE531X_DEBUG_RX_STOP,
++ ("Enet%d RX early stop. Quota=%d rxDescCount=%d budget=%d\n",
++ MACInfo->unit, dev->quota, rxDescCount, *budget));
++ }
++ rx_received++;
++
++ /* Send the data up the stack */
++ AE531X_PRINT(AE531X_DEBUG_RX,
++ ("Send data up stack: skb=%p data=%p length=%d\n",
++ (void *)skb, (void *)skb->data, length));
++
++ netif_receive_skb(skb);
++
++ MAC_state->stats.rx_packets++;
++ MAC_state->stats.rx_bytes += length;
++ }
++ } else {
++ /* Descriptor status indicates ERRORS */
++ MAC_state->stats.rx_errors++;
++
++ if (cmdsts & (DescRxRunt | DescRxLateColl)) {
++ MAC_state->stats.collisions++;
++ }
++
++ if (cmdsts & DescRxLengthError) {
++ MAC_state->stats.rx_length_errors++;
++ }
++
++ if (cmdsts & DescRxCrc) {
++ MAC_state->stats.rx_crc_errors++;
++ }
++
++ if (cmdsts & DescRxDribbling) {
++ MAC_state->stats.rx_frame_errors++;
++ }
++
++ AE531X_DESC_STATUS_SET(rxDesc, DescOwnByDma);
++
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("Bad receive. rxDesc=%p cmdsts=0x%8.8x\n",
++ (void *)rxDesc, cmdsts));
++ }
++ }
++ } while ((!early_stop) &&
++ ae531x_ReadDmaReg(MACInfo, DmaStatus) & DmaIntRxCompleted);
++
++rx_all_done:
++ AE531X_PRINT(AE531X_DEBUG_RX,
++ ("rx done (%d)\n", rxDescCount));
++ *budget -= rxDescCount;
++
++ if (!early_stop) {
++ netif_rx_complete(dev);
++
++ ae531x_SetDmaReg(MACInfo, DmaIntrEnb,
++ DmaIeRxCompleted | DmaIeRxNoBuffer);
++ ae531x_WriteDmaReg(MACInfo, DmaRxPollDemand, 0);
++ }
++
++ retval = early_stop;
++
++rx_no_skbs:
++
++ LEAVE();
++
++#ifdef DEBUG
++ if (rxDescCount > rxDescCountMax) {
++ printk("max rx %d\n", rxDescCount);
++ rxDescCountMax = rxDescCount;
++ }
++#endif
++
++ return retval;
++}
++
++/*******************************************************************************
++* ae531x_restart stops all ethernet devices associated with a physical MAC,
++* then shuts down the MAC. Then it re-opens all devices that were in use.
++* TBDXXX: needs testing!
++*/
++static void
++ae531x_restart(void *data)
++{
++ ae531x_MAC_t *MACInfo = (ae531x_MAC_t *)data;
++ ae531x_MAC_state_t *MAC_state = (ae531x_MAC_state_t *)MACInfo->OSinfo;
++ struct net_device *saved_dev[AE531X_DEV_PER_MAC];
++ int i;
++
++ for (i=0; i<AE531X_DEV_PER_MAC; i++) {
++ if ((saved_dev[i] = MAC_state->dev_sw_state[i]->dev) != NULL) {
++ ae531x_MAC_stop(saved_dev[i]);
++ }
++ }
++
++ for (i=0; i<AE531X_DEV_PER_MAC; i++) {
++ if (saved_dev[i])
++ ae531x_MAC_open(saved_dev[i]);
++ }
++}
++
++/*******************************************************************************
++* ae531x_MAC_intr handle interrupts from an ethernet MAC.
++* It checks MAC status registers, and dispatches as appropriate.
++*/
++void
++ae531x_MAC_intr(int cpl, void *dev_id, struct pt_regs *regs)
++{
++ ae531x_MAC_state_t *MAC_state;
++ ae531x_MAC_t *MACInfo;
++ u32 regIsr;
++ u32 regImr;
++ u32 pendIntrs;
++
++ ARRIVE();
++ MACInfo = (ae531x_MAC_t *)dev_id;
++ MAC_state = (ae531x_MAC_state_t *)MACInfo->OSinfo;
++ for(;;) {
++ /* Clear any unhandled intr causes. */
++ ae531x_WriteDmaReg(MACInfo, DmaStatus, UnhandledIntrMask);
++
++ regIsr = ae531x_ReadDmaReg(MACInfo, DmaStatus);
++ regImr = ae531x_ReadDmaReg(MACInfo, DmaIntrEnb);
++ pendIntrs = regIsr & regImr;
++
++ AE531X_PRINT(AE531X_DEBUG_INT,
++ ("ethmac%d: intIsr=0x%8.8x intImr=0x%8.8x pendIntrs=0x%8.8x\n",
++ MACInfo->unit, regIsr, regImr, pendIntrs ));
++
++ if ((pendIntrs & DmaAllIntCauseMask) == 0)
++ break;
++
++ if ((pendIntrs & DmaIntRxCompleted) ||
++ (pendIntrs & DmaIntRxNoBuffer)) {
++ if (netif_rx_schedule_prep(MAC_state->dev_sw_state[MAC_state->primary_dev]->dev)) {
++ ae531x_ClearDmaReg(MACInfo,
++ DmaIntrEnb,
++ DmaIeRxCompleted | DmaIeRxNoBuffer);
++ ae531x_AckIntr(MACInfo,
++ DmaIntRxCompleted | DmaIntRxNoBuffer);
++ (void)ae531x_ReadDmaReg(MACInfo, DmaIntrEnb);
++ __netif_rx_schedule(MAC_state->dev_sw_state[MAC_state->primary_dev]->dev);
++ } else {
++#if 0
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("%s: Interrupt (0x%8.8x/0x%8.8x) while in poll. regs@%p, pc=%p, ra=%p\n",
++ __FILE__,
++ regIsr,
++ ae531x_ReadDmaReg(MACInfo, DmaIntrEnb),
++ (void *)regs,
++ (void *)regs->cp0_epc,
++ (void *)regs->regs[31]));
++#endif
++ ae531x_AckIntr(MACInfo,
++ DmaIntRxCompleted | DmaIntRxNoBuffer);
++ }
++ }
++
++ if (pendIntrs &
++ (DmaIntTxStopped | DmaIntTxJabber | DmaIntTxUnderflow)) {
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("ethmac%d: TX Error Intr (0x%x)\n",
++ MACInfo->unit, pendIntrs));
++ ae531x_AckIntr(MACInfo,
++ (DmaIntTxStopped | DmaIntTxJabber | DmaIntTxUnderflow));
++ }
++
++ if (pendIntrs & DmaIntBusError) {
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("ethmac%d: DMA Bus Error Intr (0x%x)\n",
++ MACInfo->unit, pendIntrs));
++ ae531x_AckIntr(MACInfo, DmaIntBusError);
++ /* Reset the chip, if it's not already being done */
++ if (ae531x_IsInResetMode(MACInfo)) {
++ goto intr_done;
++ }
++ ae531x_BeginResetMode(MACInfo);
++ schedule_task(&MAC_state->restart_task);
++ }
++
++ if (pendIntrs & DmaIntRxStopped) {
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("ethmac%d: RX Stopped Intr (0x%x)\n",
++ MACInfo->unit, pendIntrs));
++ ae531x_AckIntr(MACInfo, DmaIntRxStopped);
++ }
++ }
++
++ intr_done:
++ LEAVE();
++}
++
++/*******************************************************************************
++* ae531x_MAC_get_stats returns statistics for a specified device
++*/
++static struct net_device_stats*
++ae531x_MAC_get_stats(struct net_device *dev)
++{
++ ae531x_dev_sw_state_t *dev_sw_state;
++ ae531x_MAC_state_t *MAC_state;
++
++ ARRIVE();
++ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
++ MAC_state = dev_sw_state->MAC_state;
++
++ LEAVE();
++ return &MAC_state->stats;
++}
++
++#define AE531X_PHY_POLL_SECONDS 2
++
++#if CONFIG_AR5315
++
++/*******************************************************************************
++* ae531x_getMACInfo returns the MACInfo of the interface given by unit
++*/
++ae531x_MAC_t *ae531x_getMAcInfo(int ethUnit)
++{
++ int i,j;
++ for(i=0;i<AR531X_NUM_ENET_MAC;++i) {
++ if(per_MAC_info[i].dev_sw_state) {
++ for(j=0;j<AE531X_DEV_PER_MAC;++j) {
++ if(per_MAC_info[i].dev_sw_state[j]
++ && per_MAC_info[i].dev_sw_state[j]->enetUnit == ethUnit)
++ return (&(per_MAC_info[i].MACInfo));
++ }
++ }
++ }
++ return NULL;
++}
++
++
++#endif
++
++/*******************************************************************************
++* ae531x_phy_poll periodically checks for changes in phy status
++* (e.g. dropped link).
++*/
++static int
++ae531x_phy_poll(void *data)
++{
++ ae531x_dev_sw_state_t *dev_sw_state = (ae531x_dev_sw_state_t *)data;
++ ae531x_MAC_t *MACInfo = &dev_sw_state->MAC_state->MACInfo;
++ int unit = dev_sw_state->enetUnit;
++
++ while(dev_sw_state->dev!=NULL) {
++ if (MACInfo->port_is_up) {
++ phyCheckStatusChange(unit);
++ }
++
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout(AE531X_PHY_POLL_SECONDS * HZ);
++ }
++
++ return 0;
++}
++
++
++static char invalid_enet_MAC_addr[] = {0, 0, 0, 0, 0, 0};
++
++/*
++ * Fetch a pointer to an ethernet's MAC address
++ * in the Board Configuration data (in flash).
++ */
++char *
++ae531x_enet_mac_address_get(int MACUnit)
++{
++ /* XXX: Hack for poorly configured boards.
++ * Cannot setup bridging properly (brctl) when both enet
++ * interfaces share the same MAC address.
++ *
++ */
++
++#ifdef CONFIG_ASK_MULT_MAC_HACK
++ static u8 enet0Mac[6] = {0x00, 0x0d, 0x0b, 0x13, 0x6b, 0x16};
++ static u8 enet1Mac[6] = {0x00, 0x0d, 0x0b, 0x13, 0x6b, 0x17};
++#endif
++
++ if (!ar531x_boardConfig)
++ return invalid_enet_MAC_addr;
++ if (MACUnit == 0) {
++#ifndef CONFIG_ASK_MULT_MAC_HACK
++ return ar531x_boardConfig->enet0Mac;
++#else
++ return enet0Mac;
++#endif
++ }
++ if (MACUnit == 1) {
++#ifndef CONFIG_ASK_MULT_MAC_HACK
++ return ar531x_boardConfig->enet1Mac;
++#else
++ return enet1Mac;
++#endif
++ }
++ printk("Invalid ethernet MAC unit number (%d)!\n", MACUnit);
++ return invalid_enet_MAC_addr;
++}
++
++
++
++/*******************************************************************************
++* ae531x_MAC_open is the standard Linux open function. It puts
++* hardware into a known good state, allocates queues, starts
++* the phy polling task, and arranges for interrupts to be handled.
++*/
++static int
++ae531x_MAC_open(struct net_device *dev)
++{
++ ae531x_dev_sw_state_t *dev_sw_state;
++ ae531x_MAC_state_t *MAC_state;
++ ae531x_MAC_t *MACInfo;
++ u8 *MACAddr;
++ int rv;
++ struct tq_struct *restart_task;
++ pid_t phy_poll_pid;
++ ARRIVE();
++
++ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
++ dev_sw_state->dev = dev;
++ MAC_state = dev_sw_state->MAC_state;
++ MACInfo = &MAC_state->MACInfo;
++
++ restart_task = &MAC_state->restart_task;
++ restart_task->routine = ae531x_restart;
++ restart_task->data = (void *)MACInfo;
++
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ae531x_MAC_open eth%d ethmac%d macBase=0x%x dmaBase=0x%x irq=0x%x\n",
++ dev_sw_state->enetUnit,
++ MACInfo->unit,
++ MACInfo->macBase,
++ MACInfo->dmaBase,
++ MAC_state->irq));
++
++ /* Default MAC address */
++ MACAddr = ae531x_enet_mac_address_get(MACInfo->unit);
++ memcpy(dev->dev_addr, MACAddr, dev->addr_len );
++
++ if (!MACInfo->port_is_up) {
++ /* Bring MAC and PHY out of reset */
++ ae531x_reset(MACInfo);
++
++ /* Attach interrupt handler */
++ rv = request_irq(MAC_state->irq, ae531x_MAC_intr, SA_INTERRUPT,
++ "ae531x_MAC_intr", (void *)MACInfo);
++ if (rv < 0) {
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("request_irq(0x%x) failed (%d)\n",
++ MAC_state->irq, rv));
++ goto open_failure;
++ }
++
++ /* Initialize PHY */
++ AE531X_PRINT(AE531X_DEBUG_RESET, ("\n --- phyBase: %08x\n", MACInfo->phyBase));
++ phySetup(MACInfo->unit, MACInfo->phyBase);
++
++ /* Start thread to poll for phy link status changes */
++ phy_poll_pid = kernel_thread(ae531x_phy_poll, dev_sw_state, 0);
++ if (phy_poll_pid < 0) {
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("ethmac%d unable to start Phy Poll thread\n",
++ MACInfo->unit));
++ }
++
++ /* Allocate RX/TX Queues */
++ if (ae531x_AllocateQueues(MACInfo) < 0) {
++ AE531X_PRINT(AE531X_DEBUG_RESET, ("Queue allocation failed"));
++ free_irq(MAC_state->irq, (void *)MACInfo);
++ goto open_failure;
++ }
++
++ /* Initialize DMA and descriptors */
++ ae531x_DmaReset(MACInfo);
++
++ /* Initialize MAC */
++ ae531x_MACReset(MACInfo);
++
++ /* Enable Receive/Transmit */
++ ae531x_EnableComm(MACInfo);
++
++ MAC_state->primary_dev = dev_sw_state->unit_on_MAC;
++ MACInfo->port_is_up = TRUE;
++ }
++
++ dev->trans_start = jiffies;
++ SET_MODULE_OWNER(dev);
++
++ LEAVE();
++ return 0;
++
++open_failure:
++ LEAVE();
++ return -1;
++}
++
++/*
++ * Shut down MAC hardware.
++ */
++static void
++ae531x_MAC_shutdown(ae531x_MAC_state_t *MAC_state)
++{
++ ae531x_MAC_t *MACInfo;
++
++ MACInfo = &MAC_state->MACInfo;
++ MACInfo->port_is_up = FALSE;
++
++ /* Disable Receive/Transmit */
++ ae531x_DisableComm(MACInfo);
++
++ /* Disable Interrupts */
++ ae531x_DmaIntDisable(MACInfo);
++ sysWbFlush();
++ free_irq(MAC_state->irq, (void *)MACInfo);
++
++ /* Free Transmit & Receive skb's/descriptors */
++ ae531x_TxReap(MAC_state); /* one last time */
++ ae531x_FreeQueues(MACInfo);
++}
++
++/*******************************************************************************
++* ae531x_MAC_stop is the standard Linux stop function. It undoes
++* everything set up by ae531x_MAC_open.
++*/
++static int
++ae531x_MAC_stop(struct net_device *dev)
++{
++ ae531x_dev_sw_state_t *dev_sw_state;
++ ae531x_MAC_state_t *MAC_state;
++ ae531x_MAC_t *MACInfo;
++ int i;
++
++ ARRIVE();
++
++ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
++ MAC_state = dev_sw_state->MAC_state;
++ MACInfo = &MAC_state->MACInfo;
++
++ for (i=0; i<AE531X_DEV_PER_MAC; i++) {
++ if ((MAC_state->dev_sw_state[i]->dev) &&
++ (MAC_state->dev_sw_state[i]->dev != dev_sw_state->dev)) {
++ break;
++ }
++ }
++
++ if (i < AE531X_DEV_PER_MAC) {
++ /* Physical MAC is still in use */
++ if (MAC_state->primary_dev == dev_sw_state->unit_on_MAC) {
++ /*
++ * If the primary_dev is being stopped
++ * then we need to assign a new one.
++ */
++ MAC_state->primary_dev = i;
++ }
++ } else {
++ /* Physical MAC is no longer in use */
++ ae531x_MAC_shutdown(MAC_state);
++ }
++
++ dev_sw_state->dev = NULL;
++ LEAVE();
++ return 0;
++}
++
++/*******************************************************************************
++* ae531x_rxbuf_alloc - Allocate an skb to be associated with an RX descriptor.
++*
++* RETURNS: A pointer to the skb. Also returns a pointer to the underlying
++* buffer and the size of that buffer.
++*/
++void *
++ae531x_rxbuf_alloc(ae531x_MAC_t *MACInfo, char **rxBuffp, int *rxBuffSizep)
++{
++ int buf_size;
++ struct sk_buff *skb;
++ char *rxBuff;
++ int rxBuffSize;
++
++ buf_size = AE531X_RX_BUF_SIZE;
++
++ skb = dev_alloc_skb(buf_size);
++ if (skb) {
++ /* skb->dev = dev; */
++ skb_reserve(skb, RXBUFF_RESERVE);
++
++ rxBuffSize = skb_tailroom(skb);
++ rxBuff = skb->tail;
++
++ *rxBuffp = rxBuff;
++ *rxBuffSizep = rxBuffSize;
++ }
++
++ return skb;
++}
++
++/*******************************************************************************
++* ae531x_swptr_free - Free the skb, if any, associated with a descriptor.
++*/
++void
++ae531x_swptr_free(VIRT_ADDR desc)
++{
++ struct sk_buff *skb;
++
++ skb = (struct sk_buff *)AE531X_DESC_SWPTR_GET(desc);
++ if (skb) {
++ AE531X_DESC_SWPTR_SET(desc, NULL);
++ kfree_skb(skb);
++ }
++}
++
++/*******************************************************************************
++*
++* ae531x_TxReap - the driver Tx completion routine.
++*
++* This routine reaps sk_buffs which have already been transmitted.
++*
++*/
++static void
++ae531x_TxReap(ae531x_MAC_state_t *MAC_state)
++{
++ AE531X_QUEUE *txq;
++ VIRT_ADDR txDesc;
++ UINT32 cmdsts;
++ struct sk_buff *skb;
++ int reaped;
++ ae531x_MAC_t *MACInfo;
++ static int aeUselessReap = 0;
++#ifdef DEBUG
++ static int aeMaxReap = 0;
++#endif
++ ARRIVE();
++
++ MACInfo = &MAC_state->MACInfo;
++ txq = &MACInfo->txQueue;
++ reaped = 0;
++
++ while (1) {
++
++ txDesc = AE531X_QUEUE_ELE_NEXT_GET(txq, txq->reapDescAddr);
++ if (txDesc == txq->curDescAddr) {
++ break;
++ }
++
++ cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(txDesc));
++ if (cmdsts & DescOwnByDma) {
++ break;
++ }
++
++ /* Release sk_buff associated with completed transmit */
++ skb = (struct sk_buff *)AE531X_DESC_SWPTR_GET(txDesc);
++ if (skb) {
++ kfree_skb(skb);
++ AE531X_DESC_SWPTR_SET(txDesc, NULL);
++ }
++
++ /* Update statistics according to completed transmit desc */
++ if (cmdsts & DescTxErrors) {
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("enetmac%d Tx prior error: 0x%8.8x <0x%8.8x> 0x%8.8x\n",
++ MACInfo->unit,
++ cmdsts,
++ DescTxErrors,
++ (int)txDesc));
++#ifdef DEBUG
++ //my_mvPhyShow(MACInfo->unit);
++ printk ("ae531xMacControl: 0x%08x\tMacFlowControl: 0x%08x\n",
++ ae531x_ReadMacReg(MACInfo, MacControl),
++ ae531x_ReadMacReg(MACInfo, MacFlowControl));
++#endif
++ MAC_state->stats.tx_errors++;
++ if (cmdsts & (DescTxLateCollision | DescTxExcCollisions)) {
++ MAC_state->stats.tx_aborted_errors++;
++ }
++ if (cmdsts & (DescTxLostCarrier | DescTxNoCarrier)) {
++ MAC_state->stats.tx_carrier_errors++;
++ }
++ } else {
++ MAC_state->stats.tx_bytes += AE531X_DESC_STATUS_RX_SIZE(cmdsts);
++ MAC_state->stats.tx_packets++;
++ }
++
++ MAC_state->stats.collisions +=
++ ((cmdsts & DescTxCollMask) >> DescTxCollShift);
++
++ txq->reapDescAddr = txDesc;
++ reaped++;
++ }
++
++ if (reaped > 0) {
++ int i;
++
++#ifdef DEBUG
++ if (reaped > aeMaxReap) {
++ aeMaxReap = reaped;
++ printk("max reaped = %d\n", reaped);
++ }
++#endif
++ AE531X_PRINT(AE531X_DEBUG_TX_REAP,
++ ("reaped %d\n", reaped));
++
++ /*
++ * Re-start transmit queues for all ethernet devices
++ * associated with this MAC.
++ */
++ for (i=0; i<AE531X_DEV_PER_MAC; i++) {
++ if (MAC_state->dev_sw_state[i]->dev)
++ netif_start_queue(MAC_state->dev_sw_state[i]->dev);
++ }
++ } else {
++ aeUselessReap++;
++ }
++
++ LEAVE();
++}
++
++
++/*******************************************************************************
++* ae531x_MAC_start_xmit sends a packet.
++*/
++static int
++ae531x_MAC_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ ae531x_dev_sw_state_t *dev_sw_state;
++ ae531x_MAC_state_t *MAC_state;
++ ae531x_MAC_t *MACInfo;
++ u32 buf;
++ u32 ctrlen;
++ u32 length;
++ int mtu;
++ int max_buf_size;
++ VIRT_ADDR txDesc;
++
++ ARRIVE();
++
++ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
++ MAC_state = dev_sw_state->MAC_state;
++ MACInfo = &MAC_state->MACInfo;
++
++ length = skb->len;
++
++ /* Check if this port is up, else toss packet */
++ if (!MACInfo->port_is_up) {
++ buf = virt_to_bus(skb->data);
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("eth%d Tx Down, dropping buf=0x%8.8x, length=0x%8.8x, skb=%p\n",
++ dev_sw_state->enetUnit, buf, length, (void *)skb));
++
++ MAC_state->stats.tx_dropped++;
++ MAC_state->stats.tx_carrier_errors++;
++ goto dropFrame;
++ }
++
++ if (ae531x_IsInResetMode(MACInfo)) {
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("eth%d Tx: In Chip reset - drop frame\n",
++ dev_sw_state->enetUnit));
++
++ MAC_state->stats.tx_dropped++;
++ MAC_state->stats.tx_aborted_errors++;
++ goto dropFrame;
++ }
++
++ /* Check if we can transport this packet */
++ length = max((u32)60, length); /* total length */
++ mtu = dev->mtu;
++ max_buf_size = mtu + ETH_HLEN;
++ if (length > max_buf_size) {
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("eth%d Tx: length %d too long. mtu=%d, trailer=%d\n",
++ dev_sw_state->enetUnit, length, mtu, PHY_TRAILER_SIZE));
++
++ MAC_state->stats.tx_errors++;
++ MAC_state->stats.tx_aborted_errors++;
++
++ goto dropFrame;
++ }
++
++ /* Reap any old, completed Tx descriptors */
++ ae531x_TxReap(MAC_state);
++
++ txDesc = MACInfo->txQueue.curDescAddr;
++ if (txDesc == MACInfo->txQueue.reapDescAddr) {
++ int i;
++
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("eth%d Tx: cannot get txDesc\n",
++ dev_sw_state->enetUnit));
++
++ MAC_state->stats.tx_dropped++;
++ MAC_state->stats.tx_fifo_errors++;
++
++ /*
++ * Stop transmit queues for any ethernet devices
++ * associated with this MAC.
++ */
++#if 0 /* XXX: no way to recover from queue stop until ae531x_MAC_tx_timeout()
++ * is rewritten to avoid calls to shedule().
++ */
++ for (i=0; i<AE531X_DEV_PER_MAC; i++) {
++ if (MAC_state->dev_sw_state[i]->dev)
++ netif_stop_queue(MAC_state->dev_sw_state[i]->dev);
++ }
++#endif
++ goto dropFrame;
++ }
++
++ /* We won't fail now; so consume this descriptor */
++ AE531X_CONSUME_DESC((&MACInfo->txQueue));
++
++ /* Update the descriptor */
++ buf = virt_to_bus(skb->data);
++ AE531X_DESC_BUFPTR_SET(txDesc, buf);
++ AE531X_DESC_SWPTR_SET(txDesc, skb);
++ ctrlen = AE531X_DESC_CTRLEN_GET(txDesc);
++ ctrlen = (ctrlen & (DescEndOfRing)) |
++ DescTxFirst |
++ DescTxLast |
++ DescTxIntEnable;
++
++ ctrlen |= ((length << DescSize1Shift) & DescSize1Mask);
++
++ AE531X_DESC_CTRLEN_SET(txDesc, ctrlen);
++ AE531X_DESC_STATUS_SET(txDesc, DescOwnByDma);
++
++ /* Alert DMA engine to resume Tx */
++ ae531x_WriteDmaReg(MACInfo, DmaTxPollDemand, 0);
++ sysWbFlush();
++
++ AE531X_PRINT(AE531X_DEBUG_TX,
++ ("eth%d Tx: Desc=0x%8.8x, L=0x%8.8x, D=0x%8.8x, d=0x%8.8x, length=0x%8.8x\n",
++ dev_sw_state->enetUnit,
++ (UINT32)txDesc,
++ AE531X_DESC_CTRLEN_GET(txDesc),
++ buf,
++ AE531X_DESC_LNKBUF_GET(txDesc),
++ length));
++
++ /* Tell upper layers to keep it coming */
++ dev->trans_start = jiffies;
++
++ LEAVE();
++
++ return 0;
++
++dropFrame:
++ kfree_skb(skb);
++ LEAVE();
++ return 0;
++}
++
++
++/*******************************************************************************
++* ae531x_MAC_tx_timeout handles transmit timeouts
++*/
++static void
++ae531x_MAC_tx_timeout(struct net_device *dev)
++{
++ ae531x_dev_sw_state_t *dev_sw_state;
++ ae531x_MAC_state_t *MAC_state;
++ ae531x_MAC_t *MACInfo;
++
++ ARRIVE();
++
++ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
++ MAC_state = dev_sw_state->MAC_state;
++ MACInfo = &MAC_state->MACInfo;
++
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("enet%d: Tx timeout\n", dev_sw_state->enetUnit));
++
++ ae531x_restart(MACInfo);
++
++ LEAVE();
++}
++
++
++/*******************************************************************************
++* ae531x_MAC_do_ioctl is a placeholder for future ioctls.
++*/
++static int
++ae531x_MAC_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
++{
++ int rv;
++ ae531x_MAC_t *MACInfo;
++ struct ioctl_data {
++ u32 unit;
++ u32 addr;
++ u32 data;
++ } *req;
++ ae531x_dev_sw_state_t *dev_sw_state;
++ ae531x_MAC_state_t *MAC_state;
++
++ ARRIVE();
++
++ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
++ MAC_state = dev_sw_state->MAC_state;
++ MACInfo = &MAC_state->MACInfo;
++
++ req = (struct ioctl_data *)ifr->ifr_data;
++
++ switch( cmd ) {
++ default:
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("Unsupported ioctl: 0x%x\n", cmd));
++ rv = -EOPNOTSUPP;
++ }
++
++ LEAVE();
++ return rv;
++}
++
++static void
++ae531x_MAC_setup_fntable(struct net_device *dev)
++{
++ ARRIVE();
++
++ dev->get_stats = ae531x_MAC_get_stats;
++ dev->open = ae531x_MAC_open;
++ dev->stop = ae531x_MAC_stop;
++ dev->hard_start_xmit = ae531x_MAC_start_xmit;
++ dev->do_ioctl = ae531x_MAC_do_ioctl;
++ dev->poll = ae531x_MAC_poll;
++ dev->weight = 16;
++#if 0 /* XXX: currently, ae531x_MAC_tx_timeout() will call functions
++ * that in turn call schedule(). this is BAD, since the
++ * timeout call runs at interrupt time. until ae531x_MAC_tx_timeout
++ * is rewritten to avoid schedule() calls, we do not use it.
++ */
++ dev->tx_timeout = ae531x_MAC_tx_timeout;
++#else
++ dev->tx_timeout = NULL;
++#endif
++ dev->features = NETIF_F_HW_CSUM |\
++ NETIF_F_HIGHDMA;
++
++ LEAVE();
++}
++
++static void
++ar5312EepromRead(char *EepromAddr, u_int16_t id, unsigned int off,
++ unsigned int nbytes, char *data)
++{
++ int i;
++
++ for (i=0; i<nbytes; i++, off++) {
++ data[i] = EepromAddr[off];
++ }
++}
++
++int
++ae531x_get_numMACs(void)
++{
++ int devid;
++ u16 radioMask;
++
++ /* Probe to find out the silicon revision and enable the
++ correct number of macs */
++ devid = ((u_int16_t) ((sysRegRead(AR531X_REV) >>8) &
++ (AR531X_REV_MAJ | AR531X_REV_MIN)));
++ switch (devid) {
++ case AR5212_AR5312_REV2:
++ case AR5212_AR5312_REV7:
++ /* Need to determine if we have a 5312 or a 2312 since they
++ have the same Silicon Rev ID*/
++ ar5312EepromRead(radioConfig,0,2*AR531X_RADIO_MASK_OFF,2,
++ (char *) &radioMask);
++ if ((radioMask & AR531X_RADIO0_MASK) != 0) {
++ return 2;
++ }
++ return 1;
++ case AR5212_AR2313_REV8:
++ return 1;
++ }
++
++ /* default to 1 */
++ return 1;
++}
++
++BOOL
++ae531x_twisted_enet(void)
++{
++ int wisoc_revision;
++
++ wisoc_revision = (sysRegRead(AR531X_REV) & AR531X_REV_MAJ) >> AR531X_REV_MAJ_S;
++ if ( (wisoc_revision == AR531X_REV_MAJ_AR2313) ||
++ /* next clause is used to determine AR2312, based on number of MACs.
++ * must do this since revision is same for 5312 and 2312.
++ */
++ (wisoc_revision == AR531X_REV_MAJ_AR5312 && ae531x_get_numMACs() == 1) ) {
++ return TRUE;
++ } else {
++ return FALSE;
++ }
++}
++
++int
++ae531x_get_board_config(void)
++{
++ int dataFound;
++ char *bd_config;
++
++ /*
++ * Find start of Board Configuration data, using heuristics:
++ * Search back from the (aliased) end of flash by 0x1000 bytes
++ * at a time until we find the string "5311", which marks the
++ * start of Board Configuration. Give up if we've searched
++ * more than 500KB.
++ */
++ dataFound = 0;
++ for (bd_config = (char *)0xbffff000;
++ bd_config > (char *)0xbff80000;
++ bd_config -= 0x1000)
++ {
++ if ( *(int *)bd_config == AR531X_BD_MAGIC) {
++ dataFound = 1;
++ break;
++ }
++ }
++
++ if (!dataFound) {
++ printk("Could not find Board Configuration Data\n");
++ bd_config = NULL;
++ }
++
++ ar531x_boardConfig = (struct ar531x_boarddata *) bd_config;
++
++ return(dataFound);
++}
++
++int
++ae531x_get_radio_config(void)
++{
++ int dataFound;
++ char *radio_config;
++
++ /*
++ * Now find the start of Radio Configuration data, using heuristics:
++ * Search forward from Board Configuration data by 0x1000 bytes
++ * at a time until we find non-0xffffffff.
++ */
++ dataFound = 0;
++ for (radio_config = ((char *) ar531x_boardConfig) + 0x1000;
++ radio_config < (char *)0xbffff000;
++ radio_config += 0x1000)
++ {
++ if (*(int *)radio_config != 0xffffffff) {
++ dataFound = 1;
++ break;
++ }
++ }
++
++ if (!dataFound) { /* AR2316 relocates radio config to new location */
++ dataFound = 0;
++ for (radio_config = ((char *) ar531x_boardConfig) + 0xf8;
++ radio_config < (char *)0xbffff0f8;
++ radio_config += 0x1000)
++ {
++ if (*(int *)radio_config != 0xffffffff) {
++ dataFound = 1;
++ break;
++ }
++ }
++ }
++
++ if (!dataFound) {
++ printk("Could not find Radio Configuration data\n");
++ radio_config = NULL;
++ }
++ radioConfig = radio_config;
++ return(dataFound);
++}
++
++static int __init
++ae531x_MAC_setup(void)
++{
++ int next_dev, i;
++ struct net_device *dev;
++ ae531x_dev_sw_state_t *dev_sw_state;
++ ae531x_MAC_state_t *MAC_state;
++ ae531x_MAC_t *MACInfo;
++ char *addr;
++
++ ARRIVE();
++
++ MOD_INC_USE_COUNT;
++ for (i=0;i<AR531X_NUM_ENET_MAC * AE531X_DEV_PER_MAC; i++) {
++ ae531x_MAC_dev[i] = NULL;
++ }
++
++ if (!ae531x_get_board_config()) {
++ LEAVE();
++ return -1;
++ }
++ if (!ae531x_get_radio_config()) {
++ LEAVE();
++ return(-1);
++ }
++ for(i=0, next_dev = AR531X_NUM_ENET_MAC-1;
++ i<ae531x_get_numMACs() && next_dev>=0;
++ i++, next_dev--){
++
++ /* if MAC is bogus in config data, skip */
++ addr = ae531x_enet_mac_address_get(next_dev);
++ if((*(u32 *)addr == 0xffffffff) && (*(u16 *)(addr+4)==0xffff)){
++ /* bogus MAC config data */
++ continue;
++ }
++
++ dev = ae531x_MAC_dev[next_dev] =
++ init_etherdev(NULL, sizeof(ae531x_dev_sw_state_t));
++
++ if (dev == NULL) {
++ LEAVE();
++ return -1;
++ }
++
++ ae531x_MAC_setup_fntable(dev);
++
++ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
++ dev_sw_state->enetUnit = next_dev;
++ dev_sw_state->unit_on_MAC = 0;
++ MAC_state = &per_MAC_info[next_dev];
++ dev_sw_state->MAC_state = MAC_state;
++ MAC_state->dev_sw_state[AE531X_LAN_PORT] = dev_sw_state;
++ MAC_state->primary_dev = -1;
++
++ /* Initialize per-MAC information */
++ MACInfo = &MAC_state->MACInfo;
++
++ MACInfo->unit = next_dev;
++
++ if (MACInfo->unit == 0) {
++ MACInfo->macBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_MAC_OFFSET);
++ MACInfo->dmaBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_DMA_OFFSET);
++ MACInfo->phyBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);
++ MAC_state->irq = AR531X_IRQ_ENET0_INTRS;
++ } else {
++#ifndef CONFIG_AR5315
++ MACInfo->macBase = (u32) (PHYS_TO_K1(AR531X_ENET1)+AE531X_MAC_OFFSET);
++ MACInfo->dmaBase = (u32) (PHYS_TO_K1(AR531X_ENET1)+AE531X_DMA_OFFSET);
++ if (ae531x_twisted_enet()) {
++ MACInfo->phyBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);
++ } else {
++ MACInfo->phyBase = (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_PHY_OFFSET);
++ }
++ MAC_state->irq = AR531X_IRQ_ENET1_INTRS;
++#endif
++ }
++
++ MACInfo->OSinfo = (void *)MAC_state;
++
++ }
++
++ LEAVE();
++ return 0;
++}
++module_init(ae531x_MAC_setup);
++
++/*******************************************************************************
++* ae531x_MAC_unload is the module unload function
++*/
++static void __exit
++ae531x_MAC_unload(void)
++{
++ int i;
++
++ for (i=0;i<AR531X_NUM_ENET_MAC * AE531X_DEV_PER_MAC; i++) {
++ if (ae531x_MAC_dev[i] != NULL) {
++ if( (((ae531x_dev_sw_state_t *)ae531x_MAC_dev[i]->priv)->dev) != NULL)
++ ae531x_MAC_stop(ae531x_MAC_dev[i]);
++ ae531x_MAC_dev[i] = NULL;
++ }
++ }
++ MOD_DEC_USE_COUNT;
++}
++
++MODULE_AUTHOR("Atheros Communications, Inc.");
++MODULE_DESCRIPTION("Support for Atheros WiSoC Ethernet device");
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("Atheros");
++#endif
++module_exit(ae531x_MAC_unload);
+diff -urN linux-mips-orig/drivers/net/ath/ae531xmac.c linux-mips-new/drivers/net/ath/ae531xmac.c
+--- linux-mips-orig/drivers/net/ath/ae531xmac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ae531xmac.c 2005-12-31 12:33:57.673538824 +0000
+@@ -0,0 +1,951 @@
++/*
++ * 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.
++ */
++
++
++/*
++ * Ethernet driver for Atheros' ae531x ethernet MAC.
++ */
++
++#if linux
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/init.h>
++#include <asm/io.h>
++
++#include "ar531xlnx.h"
++#endif /* linux */
++
++#include "ae531xreg.h"
++#include "ae531xmac.h"
++
++#ifdef DEBUG
++int ae531x_MAC_debug = AE531X_DEBUG_ERROR;
++#else
++int ae531x_MAC_debug = 0;
++#endif
++
++extern char *ae531x_enet_mac_address_get(int);
++
++/* Forward references to local functions */
++static void ae531x_QueueDestroy(AE531X_QUEUE *q);
++
++
++/******************************************************************************
++*
++* ae531x_ReadMacReg - read AE MAC register
++*
++* RETURNS: register value
++*/
++UINT32
++ae531x_ReadMacReg(ae531x_MAC_t *MACInfo, UINT32 reg)
++{
++ UINT32 addr = MACInfo->macBase+reg;
++ UINT32 data;
++
++ data = RegRead(addr);
++ return data;
++}
++
++
++/******************************************************************************
++*
++* ae531x_WriteMacReg - write AE MAC register
++*
++* RETURNS: N/A
++*/
++void
++ae531x_WriteMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data)
++{
++ UINT32 addr = MACInfo->macBase+reg;
++
++ RegWrite(data, addr);
++}
++
++
++/******************************************************************************
++*
++* ae531x_SetMacReg - set bits in AE MAC register
++*
++* RETURNS: N/A
++*/
++void
++ae531x_SetMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
++{
++ UINT32 addr = MACInfo->macBase+reg;
++ UINT32 data = RegRead(addr);
++
++ data |= val;
++ RegWrite(data, addr);
++}
++
++
++/******************************************************************************
++*
++* ae531x_ClearMacReg - clear bits in AE MAC register
++*
++* RETURNS: N/A
++*/
++void
++ae531x_ClearMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
++{
++ UINT32 addr = MACInfo->macBase+reg;
++ UINT32 data = RegRead(addr);
++
++ data &= ~val;
++ RegWrite(data, addr);
++}
++
++
++/******************************************************************************
++*
++* ae531x_ReadDmaReg - read AE DMA register
++*
++* RETURNS: register value
++*/
++UINT32
++ae531x_ReadDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg)
++{
++ UINT32 addr = MACInfo->dmaBase+reg;
++ UINT32 data = RegRead(addr);
++
++ return data;
++}
++
++
++/******************************************************************************
++*
++* ae531x_WriteDmaReg - write AE DMA register
++*
++* RETURNS: N/A
++*/
++void
++ae531x_WriteDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data)
++{
++ UINT32 addr = MACInfo->dmaBase+reg;
++
++ RegWrite(data, addr);
++}
++
++
++/******************************************************************************
++ *
++ * ae531x_AckIntr - clear interrupt bits in the status register.
++ * Note: Interrupt bits are *cleared* by writing a 1.
++ */
++void
++ae531x_AckIntr(ae531x_MAC_t *MACInfo, UINT32 data)
++{
++ ae531x_WriteDmaReg(MACInfo, DmaStatus, data);
++}
++
++
++/******************************************************************************
++*
++* ae531x_SetDmaReg - set bits in an AE DMA register
++*
++* RETURNS: N/A
++*/
++void
++ae531x_SetDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
++{
++ UINT32 addr = MACInfo->dmaBase+reg;
++ UINT32 data = RegRead(addr);
++
++ data |= val;
++ RegWrite(data, addr);
++}
++
++
++/******************************************************************************
++*
++* ae531x_ClearDmaReg - clear bits in an AE DMA register
++*
++* RETURNS: N/A
++*/
++void
++ae531x_ClearDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
++{
++ UINT32 addr = MACInfo->dmaBase+reg;
++ UINT32 data = RegRead(addr);
++
++ data &= ~val;
++ RegWrite(data, addr);
++}
++
++
++/******************************************************************************
++*
++* ae531x_ReadMiiReg - read PHY registers via AE MAC Mii addr/data registers
++*
++* RETURNS: register value
++*/
++UINT32
++ae531x_ReadMiiReg(UINT32 phyBase, UINT32 reg)
++{
++ UINT32 data;
++ UINT32 addr = phyBase+reg;
++
++ data = RegRead(addr);
++ return data;
++}
++
++
++/******************************************************************************
++*
++* ae531x_WriteMiiReg - write PHY registers via AE MAC Mii addr/data registers
++*
++* RETURNS: N/A
++*/
++void
++ae531x_WriteMiiReg(UINT32 phyBase, UINT32 reg, UINT32 data)
++{
++ UINT32 addr = phyBase+reg;
++
++ RegWrite(data, addr);
++}
++
++
++/******************************************************************************
++*
++* ae531x_MiiRead - read AE Mii register
++*
++* RETURNS: register value
++*/
++UINT16
++ae531x_MiiRead(UINT32 phyBase, UINT32 phyAddr, UINT8 reg)
++{
++ UINT32 addr;
++ UINT16 data;
++
++ addr = ((phyAddr << MiiDevShift) & MiiDevMask) | ((reg << MiiRegShift) & MiiRegMask);
++
++ ae531x_WriteMiiReg(phyBase, MacMiiAddr, addr );
++ do {
++ /* nop */
++ } while ((ae531x_ReadMiiReg(phyBase, MacMiiAddr ) & MiiBusy) == MiiBusy);
++
++ data = ae531x_ReadMiiReg(phyBase, MacMiiData) & 0xFFFF;
++
++ return data;
++}
++
++
++/******************************************************************************
++*
++* ae531x_MiiWrite - write AE Mii register
++*
++* RETURNS: N/A
++*/
++void
++ae531x_MiiWrite(UINT32 phyBase, UINT32 phyAddr, UINT8 reg, UINT16 data)
++{
++ UINT32 addr;
++
++ ae531x_WriteMiiReg(phyBase, MacMiiData, data );
++
++ addr = ((phyAddr << MiiDevShift) & MiiDevMask) |
++ ((reg << MiiRegShift) & MiiRegMask) | MiiWrite;
++ ae531x_WriteMiiReg(phyBase, MacMiiAddr, addr );
++
++ do {
++ /* nop */
++ } while ((ae531x_ReadMiiReg(phyBase, MacMiiAddr ) & MiiBusy) == MiiBusy);
++}
++
++
++/*******************************************************************************
++* ae531x_BeginResetMode - enter a special "reset mode" in which
++* -no interrupts are expected from the device
++* -the device will not transmit nor receive
++* -attempts to send or receive will return with an error and
++* -the device will be reset at the next convenient opportunity.
++*/
++void
++ae531x_BeginResetMode(ae531x_MAC_t *MACInfo)
++{
++ /* Set the reset flag */
++ MACInfo->aeProcessRst = 1;
++}
++
++
++/*******************************************************************************
++* ae531x_EndResetMode - exit the special "reset mode" entered
++* earlier via a call to ae531x_BeginResetMode.
++*/
++void
++ae531x_EndResetMode(ae531x_MAC_t *MACInfo)
++{
++ MACInfo->aeProcessRst = 0;
++}
++
++
++/*******************************************************************************
++* ae531x_IsInResetMode - determine whether or not the device is
++* currently in "reset mode" (i.e. that a device reset is pending)
++*/
++BOOL
++ae531x_IsInResetMode(ae531x_MAC_t *MACInfo)
++{
++ return MACInfo->aeProcessRst;
++}
++
++
++/******************************************************************************
++*
++* ae531x_DmaRxStart - Start Rx
++*
++* RETURNS: N/A
++*/
++static void
++ae531x_DmaRxStart(ae531x_MAC_t *MACInfo)
++{
++ ae531x_SetDmaReg(MACInfo, DmaControl, DmaRxStart);
++ sysWbFlush();
++}
++
++
++/******************************************************************************
++*
++* ae531x_DmaRxStop - Stop Rx
++*
++* RETURNS: N/A
++*/
++void
++ae531x_DmaRxStop(ae531x_MAC_t *MACInfo)
++{
++ ae531x_ClearDmaReg(MACInfo, DmaControl, DmaRxStart);
++ sysWbFlush();
++}
++
++
++/******************************************************************************
++*
++* ae531x_DmaTxStart - Start Tx
++*
++* RETURNS: N/A
++*/
++void
++ae531x_DmaTxStart(ae531x_MAC_t *MACInfo)
++{
++ ae531x_SetDmaReg(MACInfo, DmaControl, DmaTxStart);
++ sysWbFlush();
++}
++
++
++/******************************************************************************
++*
++* ae531x_DmaTxStop - Stop Tx
++*
++* RETURNS: N/A
++*/
++void
++ae531x_DmaTxStop(ae531x_MAC_t *MACInfo)
++{
++ ae531x_ClearDmaReg(MACInfo, DmaControl, DmaTxStart);
++ sysWbFlush();
++}
++
++
++/******************************************************************************
++*
++* ae531x_DmaIntEnable - Enable DMA interrupts
++*
++* RETURNS: N/A
++*/
++void
++ae531x_DmaIntEnable(ae531x_MAC_t *MACInfo)
++{
++ ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntEnable);
++}
++
++
++/******************************************************************************
++*
++* ae531x_DmaIntDisable - Disable DMA interrupts
++*
++* RETURNS: N/A
++*/
++void
++ae531x_DmaIntDisable(ae531x_MAC_t *MACInfo)
++{
++ ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntDisable);
++}
++
++
++/******************************************************************************
++*
++* ae531x_DmaIntClear - Clear DMA interrupts
++*
++* RETURNS: N/A
++*/
++static void
++ae531x_DmaIntClear(ae531x_MAC_t *MACInfo)
++{
++ /* clear all interrupt requests */
++ ae531x_WriteDmaReg(MACInfo, DmaStatus,
++ ae531x_ReadDmaReg(MACInfo, DmaStatus));
++}
++
++
++/******************************************************************************
++* Initialize generic queue data
++*/
++void
++ae531x_QueueInit(AE531X_QUEUE *q, char *pMem, int count)
++{
++ ARRIVE();
++ q->firstDescAddr = pMem;
++ q->lastDescAddr = (VIRT_ADDR)((UINT32)q->firstDescAddr +
++ (count - 1) * AE531X_QUEUE_ELE_SIZE);
++ q->curDescAddr = q->firstDescAddr;
++ q->count = count;
++ LEAVE();
++}
++
++
++/******************************************************************************
++* ae531x_TxQueueCreate - create a circular queue of descriptors for Transmit
++*/
++static int
++ae531x_TxQueueCreate(ae531x_MAC_t *MACInfo,
++ AE531X_QUEUE *q,
++ char *pMem,
++ int count)
++{
++ int i;
++ VIRT_ADDR descAddr;
++
++ ARRIVE();
++
++ ae531x_QueueInit(q, pMem, count);
++ q->reapDescAddr = q->lastDescAddr;
++
++ /* Initialize Tx buffer descriptors. */
++ for (i=0, descAddr=q->firstDescAddr;
++ i<count;
++ i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE))
++ {
++ /* Update the size, BUFPTR, and SWPTR fields */
++
++ AE531X_DESC_STATUS_SET(descAddr, 0);
++ AE531X_DESC_CTRLEN_SET(descAddr, 0);
++
++ AE531X_DESC_BUFPTR_SET(descAddr, (UINT32)0);
++ AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);
++ AE531X_DESC_SWPTR_SET(descAddr, (void *)0);
++ } /* for each desc */
++
++ /* Make the queue circular */
++ AE531X_DESC_CTRLEN_SET(q->lastDescAddr,
++ DescEndOfRing|AE531X_DESC_CTRLEN_GET(q->lastDescAddr));
++
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d Txbuf begin = %x, end = %x\n",
++ MACInfo->unit,
++ (UINT32)q->firstDescAddr,
++ (UINT32)q->lastDescAddr));
++
++ LEAVE();
++ return 0;
++}
++
++
++/******************************************************************************
++* ae531x_RxQueueCreate - create a circular queue of Rx descriptors
++*/
++int
++ae531x_RxQueueCreate(ae531x_MAC_t *MACInfo,
++ AE531X_QUEUE *q,
++ char *pMem,
++ int count)
++{
++ int i;
++ VIRT_ADDR descAddr;
++
++ ARRIVE();
++
++ ae531x_QueueInit(q, pMem, count);
++ q->reapDescAddr = NULL;
++
++
++ /* Initialize Rx buffer descriptors */
++ for (i=0, descAddr=q->firstDescAddr;
++ i<count;
++ i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE))
++ {
++ void *swptr;
++ char *rxBuffer;
++ int rxBufferSize;
++
++ swptr = ae531x_rxbuf_alloc(MACInfo, &rxBuffer, &rxBufferSize);
++ if (swptr == NULL) {
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d RX queue: ae531x_rxbuf_alloc failed\n",
++ MACInfo->unit));
++ ae531x_QueueDestroy(q);
++ return -1;
++ }
++ AE531X_DESC_SWPTR_SET(descAddr, swptr);
++
++ AE531X_DESC_STATUS_SET(descAddr, DescOwnByDma);
++ AE531X_DESC_CTRLEN_SET(descAddr, rxBufferSize);
++ AE531X_DESC_BUFPTR_SET(descAddr, virt_to_bus(rxBuffer));
++ AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);
++ } /* for each desc */
++
++ /* Make the queue circular */
++ AE531X_DESC_CTRLEN_SET(q->lastDescAddr,
++ DescEndOfRing|AE531X_DESC_CTRLEN_GET(q->lastDescAddr));
++
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d Rxbuf begin = %x, end = %x\n",
++ MACInfo->unit,
++ (UINT32)q->firstDescAddr,
++ (UINT32)q->lastDescAddr));
++
++ LEAVE();
++ return 0;
++}
++
++
++/******************************************************************************
++* ae531x_QueueDestroy -- Free all buffers and descriptors associated
++* with a queue.
++*/
++static void
++ae531x_QueueDestroy(AE531X_QUEUE *q)
++{
++ int i;
++ int count;
++ VIRT_ADDR descAddr;
++
++ ARRIVE();
++
++ count = q->count;
++
++ for (i=0, descAddr=q->firstDescAddr;
++ i<count;
++ i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE)) {
++
++ AE531X_DESC_STATUS_SET(descAddr, 0);
++ AE531X_DESC_CTRLEN_SET(descAddr, 0);
++ AE531X_DESC_BUFPTR_SET(descAddr, (UINT32)0);
++ AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);
++
++ ae531x_swptr_free(descAddr); /* Free OS-specific software pointer */
++ }
++
++ LEAVE();
++}
++
++static void
++ae531x_TxQueueDestroy(ae531x_MAC_t *MACInfo)
++{
++ ae531x_QueueDestroy(&MACInfo->txQueue);
++}
++
++static void
++ae531x_RxQueueDestroy(ae531x_MAC_t *MACInfo)
++{
++ ae531x_QueueDestroy(&MACInfo->rxQueue);
++}
++
++
++/******************************************************************************
++* ae531x_AllocateQueues - Allocate receive and transmit queues
++*/
++int
++ae531x_AllocateQueues(ae531x_MAC_t *MACInfo)
++{
++ size_t QMemSize;
++ char *pTxBuf = NULL;
++ char *pRxBuf = NULL;
++
++ ARRIVE();
++
++ MACInfo->txDescCount = AE531X_TX_DESC_COUNT_DEFAULT;
++ QMemSize = AE531X_QUEUE_ELE_SIZE * MACInfo->txDescCount;
++ pTxBuf = MALLOC(QMemSize);
++ if (pTxBuf == NULL) {
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d Failed to allocate TX queue\n", MACInfo->unit));
++ goto AllocQFail;
++ }
++
++ if (ae531x_TxQueueCreate(MACInfo, &MACInfo->txQueue, pTxBuf,
++ MACInfo->txDescCount) < 0)
++ {
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d Failed to create TX queue\n", MACInfo->unit));
++ goto AllocQFail;
++ }
++
++ MACInfo->rxDescCount = AE531X_RX_DESC_COUNT_DEFAULT;
++ QMemSize = AE531X_QUEUE_ELE_SIZE * MACInfo->rxDescCount;
++ pRxBuf = MALLOC(QMemSize);
++ if (pRxBuf == NULL) {
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d Failed to allocate RX queue\n", MACInfo->unit));
++ goto AllocQFail;
++ }
++
++ if (ae531x_RxQueueCreate(MACInfo, &MACInfo->rxQueue, pRxBuf,
++ MACInfo->rxDescCount) < 0)
++ {
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d Failed to create RX queue\n", MACInfo->unit));
++ goto AllocQFail;
++ }
++
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d Memory setup complete.\n", MACInfo->unit));
++
++ LEAVE();
++ return 0;
++
++AllocQFail:
++ MACInfo->txDescCount = 0; /* sanity */
++ MACInfo->rxDescCount = 0; /* sanity */
++
++ if (pTxBuf) {
++ FREE(pTxBuf);
++ }
++ if (pRxBuf) {
++ FREE(pRxBuf);
++ }
++
++ LEAVE();
++ return -1;
++}
++
++
++/******************************************************************************
++*
++* ae531x_FreeQueues - Free Transmit & Receive queues
++*/
++void
++ae531x_FreeQueues(ae531x_MAC_t *MACInfo)
++{
++ ae531x_TxQueueDestroy(MACInfo);
++ FREE(MACInfo->txQueue.firstDescAddr);
++
++ ae531x_RxQueueDestroy(MACInfo);
++ FREE(MACInfo->rxQueue.firstDescAddr);
++}
++
++/******************************************************************************
++*
++* ae531x_DmaReset - Reset DMA and TLI controllers
++*
++* RETURNS: N/A
++*/
++void
++ae531x_DmaReset(ae531x_MAC_t *MACInfo)
++{
++ int i;
++ UINT32 descAddr;
++
++ ARRIVE();
++
++ /* Disable device interrupts prior to any errors during stop */
++ intDisable(MACInfo->ilevel);
++
++ /* Disable MAC rx and tx */
++ ae531x_ClearMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));
++
++ udelay(1);
++
++ /* Reset dma controller */
++
++ ae531x_WriteDmaReg(MACInfo, DmaBusMode, DmaResetOn);
++
++ /* Delay 2 usec */
++ sysUDelay(2);
++
++ /* Flush the rx queue */
++ descAddr = (UINT32)MACInfo->rxQueue.firstDescAddr;
++ MACInfo->rxQueue.curDescAddr = MACInfo->rxQueue.firstDescAddr;
++ for (i=0;
++ i<(MACInfo->rxDescCount);
++ i++, descAddr += AE531X_QUEUE_ELE_SIZE) {
++ AE531X_DESC_STATUS_SET(descAddr, DescOwnByDma);
++ }
++
++ /* Flush the tx queue */
++ descAddr = (UINT32)MACInfo->txQueue.firstDescAddr;
++ MACInfo->txQueue.curDescAddr = MACInfo->txQueue.firstDescAddr;
++ MACInfo->txQueue.reapDescAddr = MACInfo->txQueue.lastDescAddr;
++ for (i=0;
++ i<(MACInfo->txDescCount);
++ i++, descAddr += AE531X_QUEUE_ELE_SIZE) {
++ AE531X_DESC_STATUS_SET (descAddr, 0);
++ }
++
++ /* Set init register values */
++ ae531x_WriteDmaReg(MACInfo, DmaBusMode, DmaBusModeInit);
++
++ /* Install the first Tx and Rx queues on the device */
++ ae531x_WriteDmaReg(MACInfo, DmaRxBaseAddr,
++ virt_to_bus(MACInfo->rxQueue.firstDescAddr));
++ ae531x_WriteDmaReg(MACInfo, DmaTxBaseAddr,
++ virt_to_bus(MACInfo->txQueue.firstDescAddr));
++
++
++ ae531x_WriteDmaReg(MACInfo, DmaControl, DmaStoreAndForward);
++
++ ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntDisable);
++
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d: DMA RESET!\n", MACInfo->unit));
++
++ /* Turn on device interrupts -- enable most errors */
++ ae531x_DmaIntClear(MACInfo); /* clear interrupt requests */
++ ae531x_DmaIntEnable(MACInfo); /* enable interrupts */
++
++ ae531x_EndResetMode(MACInfo);
++
++ intEnable(MACInfo->ilevel);
++
++ LEAVE();
++}
++
++
++/******************************************************************************
++*
++* ae531x_MACAddressSet - Set the ethernet address
++*
++* Sets the ethernet address according to settings in flash.
++*
++* RETURNS: void
++*/
++static void
++ae531x_MACAddressSet(ae531x_MAC_t *MACInfo)
++{
++ unsigned int data;
++ UINT8 *macAddr;
++
++ ARRIVE();
++
++ macAddr = ae531x_enet_mac_address_get(MACInfo->unit);
++
++ /* set our MAC address */
++ data = (macAddr[5]<<8) | macAddr[4];
++ ae531x_WriteMacReg(MACInfo, MacAddrHigh, data );
++
++ data = (macAddr[3]<<24) | (macAddr[2]<<16) | (macAddr[1]<<8) | macAddr[0];
++ ae531x_WriteMacReg(MACInfo, MacAddrLow, data );
++
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d Verify MAC address %8.8X %8.8X \n",
++ MACInfo->unit,
++ ae531x_ReadMacReg(MACInfo, MacAddrLow),
++ ae531x_ReadMacReg(MACInfo, MacAddrHigh)));
++
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ (" sb = %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
++ 0xff&macAddr[0],
++ 0xff&macAddr[1],
++ 0xff&macAddr[2],
++ 0xff&macAddr[3],
++ 0xff&macAddr[4],
++ 0xff&macAddr[5]));
++ LEAVE();
++}
++
++
++/******************************************************************************
++*
++* ae_SetMACFromPhy - read Phy settings and update Mac
++* with current duplex and speed.
++*
++* RETURNS:
++*/
++static void
++ae531x_SetMACFromPhy(ae531x_MAC_t *MACInfo)
++{
++ UINT32 macCtl;
++ BOOL fullDuplex;
++ UINT32 timeout;
++
++ ARRIVE();
++
++ timeout = jiffies+(HZ/1000)*AE531X_NEGOT_TIMEOUT;
++
++ /* Get duplex mode from Phy */
++ while (((fullDuplex = phyIsFullDuplex(MACInfo->unit)) == -1) &&
++ (jiffies <= timeout));
++
++ /* Flag is set for full duplex mode, else cleared */
++ macCtl = ae531x_ReadMacReg(MACInfo, MacControl);
++
++ if (fullDuplex) {
++ /* set values of control registers */
++ macCtl &= ~MacDisableRxOwn;
++ macCtl |= MacFullDuplex;
++ ae531x_WriteMacReg(MACInfo, MacControl, macCtl);
++ ae531x_WriteMacReg(MACInfo, MacFlowControl, MacFlowControlInitFdx);
++ } else {
++ /* set values of control registers */
++ ae531x_WriteMacReg(MACInfo, MacFlowControl, MacFlowControlInitHdx);
++ macCtl |= MacDisableRxOwn;
++ macCtl &= ~MacFullDuplex;
++ ae531x_WriteMacReg(MACInfo, MacControl, macCtl);
++ }
++
++ LEAVE();
++}
++
++
++/******************************************************************************
++* ae531x_MACReset -- sets MAC address and duplex.
++*/
++void
++ae531x_MACReset(ae531x_MAC_t *MACInfo)
++{
++ ae531x_MACAddressSet(MACInfo);
++#ifndef CONFIG_AR5315
++ ae531x_SetMACFromPhy(MACInfo);
++#endif
++}
++
++
++/******************************************************************************
++* ae531x_EnableComm -- enable Transmit and Receive
++*/
++void
++ae531x_EnableComm(ae531x_MAC_t *MACInfo)
++{
++ ae531x_SetMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));
++ ae531x_DmaRxStart(MACInfo); /* start receiver */
++ ae531x_DmaTxStart(MACInfo); /* start transmitter */
++}
++
++
++/******************************************************************************
++* ae531x_DisableComm -- disable Transmit and Receive
++*/
++void
++ae531x_DisableComm(ae531x_MAC_t *MACInfo)
++{
++ ae531x_ClearMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));
++}
++
++
++/******************************************************************************
++* ae531x_reset -- Cold reset ethernet interface
++*/
++void
++ae531x_reset(ae531x_MAC_t *MACInfo)
++{
++ UINT32 mask = 0;
++ UINT32 regtmp;
++#ifndef CONFIG_AR5315
++
++ if (MACInfo->unit == 0) {
++ mask = AR531X_RESET_ENET0 | AR531X_RESET_EPHY0;
++ } else {
++ mask = AR531X_RESET_ENET1 | AR531X_RESET_EPHY1;
++ }
++
++ /* Put into reset */
++ regtmp = sysRegRead(AR531X_RESET);
++ sysRegWrite(AR531X_RESET, regtmp | mask);
++ sysMsDelay(15);
++
++ /* Pull out of reset */
++ regtmp = sysRegRead(AR531X_RESET);
++ sysRegWrite(AR531X_RESET, regtmp & ~mask);
++ sysUDelay(25);
++
++ /* Enable */
++ if (MACInfo->unit == 0) {
++ mask = AR531X_ENABLE_ENET0;
++ } else {
++ mask = AR531X_ENABLE_ENET1;
++ }
++ regtmp = sysRegRead(AR531X_ENABLE);
++ sysRegWrite(AR531X_ENABLE, regtmp | mask);
++#else
++ if (MACInfo->unit == 0) {
++ mask = AR531X_RESET_ENET0 | AR531X_RESET_EPHY0;
++ }
++ /* Enable Arbitration for Ethernet bus */
++ regtmp = sysRegRead(AR531XPLUS_AHB_ARB_CTL);
++ regtmp |= ARB_ETHERNET;
++ sysRegWrite(AR531XPLUS_AHB_ARB_CTL, regtmp);
++
++ /* Put into reset */
++ regtmp = sysRegRead(AR531X_RESET);
++ sysRegWrite(AR531X_RESET, regtmp | mask);
++ sysMsDelay(10);
++
++ /* Pull out of reset */
++ regtmp = sysRegRead(AR531X_RESET);
++ sysRegWrite(AR531X_RESET, regtmp & ~mask);
++ sysMsDelay(10);
++
++ regtmp = sysRegRead(AR531XPLUS_IF_CTL);
++ regtmp |= IF_TS_LOCAL;
++ sysRegWrite(AR531XPLUS_IF_CTL, regtmp);
++#endif
++}
++
++
++/******************************************************************************
++* ae531x_unitLinkLost -- Called from PHY layer to notify the MAC layer
++* that there are no longer any live links associated with a MAC.
++*/
++void
++ae531x_unitLinkLost(int ethUnit)
++{
++ AE531X_PRINT(AE531X_DEBUG_LINK_CHANGE,
++ ("enetmac%d link down\n", ethUnit));
++}
++
++
++/******************************************************************************
++* ae531x_unitLinkGained -- Called from PHY layer to notify the MAC layer
++* that there are 1 or more live links associated with a MAC.
++*/
++void
++ae531x_unitLinkGained(int ethUnit)
++{
++#if CONFIG_AR5315
++#define AE531X_POLL_MILLI_SECONDS 200
++ ae531x_MAC_t *MACInfo = ae531x_getMAcInfo(ethUnit);
++ while(!MACInfo || !MACInfo->port_is_up)
++ {
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout((AE531X_POLL_MILLI_SECONDS * HZ)/1000);
++ MACInfo = ae531x_getMAcInfo(ethUnit);
++ }
++ ae531x_SetMACFromPhy(MACInfo);
++#endif
++ AE531X_PRINT(AE531X_DEBUG_LINK_CHANGE,
++ ("enet%d link up\n", ethUnit));
++}
++
++/******************************************************************************
++* ae531x_ethMacDefault -- Called from PHY layer to determine the default
++* ethernet MAC. On some "twisted" platforms, the only usable MAC is 1,
++* while on others the usable MAC is 0. Future boards may allow both MACs
++* to be used; in this case, return -1 to indicate that there IS NO default
++* MAC.
++*/
++int
++ae531x_ethMacDefault(void)
++{
++ if (ae531x_twisted_enet())
++ return 1;
++
++ return 0;
++
++}
+diff -urN linux-mips-orig/drivers/net/ath/ae531xmac.h linux-mips-new/drivers/net/ath/ae531xmac.h
+--- linux-mips-orig/drivers/net/ath/ae531xmac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ae531xmac.h 2005-12-31 12:33:57.674538672 +0000
+@@ -0,0 +1,229 @@
++/*
++ * 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.
++ */
++
++/*
++ * See README to understand the decomposition of the ethernet driver.
++ *
++ * This file contains OS-independent pure software definitions for
++ * ethernet support on the AR531X platform.
++ */
++
++#ifndef _AE531XMAC_H_
++#define _AE531XMAC_H_
++
++#include <linux/config.h>
++#include <linux/module.h>
++
++/*
++ * DEBUG switches to control verbosity.
++ * Just modify the value of ae531x_MAC_debug.
++ */
++#define AE531X_DEBUG_ALL 0xffffffff
++#define AE531X_DEBUG_ERROR 0x00000001 /* Unusual conditions and Errors */
++#define AE531X_DEBUG_ARRIVE 0x00000002 /* Arrive into a function */
++#define AE531X_DEBUG_LEAVE 0x00000004 /* Leave a function */
++#define AE531X_DEBUG_RESET 0x00000008 /* Reset */
++#define AE531X_DEBUG_TX 0x00000010 /* Transmit */
++#define AE531X_DEBUG_TX_REAP 0x00000020 /* Transmit Descriptor Reaping */
++#define AE531X_DEBUG_RX 0x00000040 /* Receive */
++#define AE531X_DEBUG_RX_STOP 0x00000080 /* Receive Early Stop */
++#define AE531X_DEBUG_INT 0x00000100 /* Interrupts */
++#define AE531X_DEBUG_LINK_CHANGE 0x00000200 /* PHY Link status changed */
++
++#define AE531X_NEGOT_TIMEOUT 500 /* ms to wait for autonegotiation */
++
++extern int ae531x_MAC_debug;
++
++#define AE531X_PRINT(FLG, X) \
++{ \
++ if (ae531x_MAC_debug & (FLG)) { \
++ DEBUG_PRINTF("%s#%d:%s ", \
++ __FILE__, \
++ __LINE__, \
++ __FUNCTION__); \
++ DEBUG_PRINTF X; \
++ } \
++}
++
++#define ARRIVE() AE531X_PRINT(AE531X_DEBUG_ARRIVE, ("Arrive{\n"))
++#define LEAVE() AE531X_PRINT(AE531X_DEBUG_LEAVE, ("}Leave\n"))
++
++#define RegRead(addr) \
++ (*(volatile unsigned int *)(addr))
++
++#define RegWrite(val,addr) \
++ ((*(volatile unsigned int *)(addr)) = (val))
++
++/*****************************************************************
++ * Phy code is broken out into a separate layer, so that different
++ * PHY hardware can easily be supported.
++ *
++ * These functions are provided by the PHY layer for use by the MAC layer.
++ * phySetup -- Set phy hardware appropriately for a MAC unit
++ *
++ * phyCheckStatusChange -- Look for dropped/initiated links on any
++ * phy port associated with a MAC unit
++ *
++ * phyIsSpeed100 -- Determines whether or not a PHY is up and
++ * running at 100Mbit
++ *
++ * phyIsFullDuplex -- Determines whether or not a PHY is up and
++ * running in Full Duplex mode
++ *
++ */
++#if CONFIG_MARVELL_ENET_PHY
++/*
++ * Mapping of generic phy APIs to Marvell Ethernet Switch phy functions.
++ */
++#include "mvPhy.h"
++#define phySetup(ethUnit, phyBase) mv_phySetup((ethUnit), (phyBase))
++#define phyCheckStatusChange(ethUnit) mv_phyCheckStatusChange(ethUnit)
++#define phyIsSpeed100(ethUnit) mv_phyIsSpeed100(ethUnit)
++#define phyIsFullDuplex(ethUnit) mv_phyIsFullDuplex(ethUnit)
++
++#if CONFIG_VENETDEV
++#define PHY_TRAILER_SIZE MV_PHY_TRAILER_SIZE
++extern void mv_phyDetermineSource(char *data, int len, int *pFromLAN);
++extern void mv_phySetDestinationPort(char *data, int len, int fromLAN);
++#define phyDetermineSource(data, len, pFromLAN) mv_phyDetermineSource((data), (len), (pFromLAN))
++#define phySetDestinationPort(data, len, fromLAN) mv_phySetDestinationPort((data), (len), (fromLAN))
++#else
++#define PHY_TRAILER_SIZE 0
++#endif
++#endif /* CONFIG_MARVELL_ENET_PHY */
++
++#if CONFIG_KENDIN_ENET_PHY || CONFIG_REALTEK_ENET_PHY || CONFIG_KENDIN_KS8995XA_ENET_PHY
++/*
++ * Mapping of generic phy APIs to Kendin KS8721B and RealTek RTL8201BL phys.
++ */
++#include "rtPhy.h"
++#define phySetup(ethUnit, phyBase) rt_phySetup((ethUnit), (phyBase))
++#define phyCheckStatusChange(ethUnit) rt_phyCheckStatusChange(ethUnit)
++#define phyIsSpeed100(ethUnit) rt_phyIsSpeed100(ethUnit)
++#define phyIsFullDuplex(ethUnit) rt_phyIsFullDuplex(ethUnit)
++#endif
++
++#if CONFIG_ICPLUS_ENET_PHY
++/*
++ * Mapping of generic phy APIs to Icplus phys.
++ */
++#include "ipPhy.h"
++#define phySetup(ethUnit, phyBase) ip_phySetup((ethUnit), (phyBase))
++#define phyCheckStatusChange(ethUnit) ip_phyCheckStatusChange(ethUnit)
++#define phyIsSpeed100(ethUnit) ip_phyIsSpeed100(ethUnit)
++#define phyIsFullDuplex(ethUnit) ip_phyIsFullDuplex(ethUnit)
++#endif
++
++#if !defined(PHY_TRAILER_SIZE)
++#define PHY_TRAILER_SIZE 0
++#endif
++
++/*****************************************************************
++ * MAC-independent interface to be used by PHY code
++ *
++ * These functions are provided by the MAC layer for use by the PHY layer.
++ */
++#define phyRegRead ae531x_MiiRead
++#define phyRegWrite ae531x_MiiWrite
++#define phyLinkLost(ethUnit) ae531x_unitLinkLost(ethUnit)
++#define phyLinkGained(ethUnit) ae531x_unitLinkGained(ethUnit)
++#define phyEthMacDefault() ae531x_ethMacDefault()
++
++void ae531x_unitLinkLost(int unit);
++void ae531x_unitLinkGained(int unit);
++int ae531x_ethMacDefault(void);
++
++
++/*
++ * RXBUFF_RESERVE enables building header on WLAN-side in place
++ * NB: Divisible by 2 but NOT 4. Otherwise handle_adel_int() will
++ * be used by the ip layer for misaligned word accesses and
++ * performance will suffer - a lot.
++ */
++#define ETH_CRC_LEN 4
++#define RXBUFF_RESERVE 98
++// #define RXBUFF_RESERVE 98
++
++/*****************************************************************
++ * Descriptor queue
++ */
++typedef struct ae531x_queue {
++ VIRT_ADDR firstDescAddr; /* descriptor array address */
++ VIRT_ADDR lastDescAddr; /* last descriptor address */
++ VIRT_ADDR curDescAddr; /* current descriptor address */
++ VIRT_ADDR reapDescAddr; /* current tail of tx descriptors reaped */
++ UINT16 count; /* number of elements */
++} AE531X_QUEUE;
++
++/* Given a descriptor, return the next one in a circular list */
++#define AE531X_QUEUE_ELE_NEXT_GET(q, descAddr) \
++ ((descAddr) == (q)->lastDescAddr) ? (q)->firstDescAddr : \
++ (VIRT_ADDR)((UINT32)(descAddr) + AE531X_QUEUE_ELE_SIZE)
++
++/* Move the "current descriptor" forward to the next one */
++#define AE531X_CONSUME_DESC(q) \
++ q->curDescAddr = AE531X_QUEUE_ELE_NEXT_GET(q, q->curDescAddr)
++
++/*****************************************************************
++ * Per-ethernet-MAC OS-independent information
++ */
++typedef struct ae531x_MAC_s {
++ u32 unit; /* MAC unit ID */
++ u32 macBase; /* MAC base address */
++ u32 dmaBase; /* DMA base address */
++ u32 phyBase; /* PHY base address */
++ AE531X_QUEUE txQueue; /* Transmit descriptor queue */
++ AE531X_QUEUE rxQueue; /* Receive descriptor queue */
++ UINT16 txDescCount; /* Transmit descriptor count */
++ UINT16 rxDescCount; /* Receive descriptor count */
++ BOOL aeProcessRst; /* flag to indicate reset in progress */
++ BOOL port_is_up; /* flag to indicate port is up */
++ void *OSinfo; /* OS-dependent data */
++} ae531x_MAC_t;
++
++#define AE531X_TX_DESC_COUNT_DEFAULT 128 /* Transmit descriptors */
++#define AE531X_RX_DESC_COUNT_DEFAULT 128 /* Receive descriptors */
++
++
++/*****************************************************************
++ * Interfaces exported by the OS-independent MAC layer
++ */
++void ae531x_BeginResetMode(ae531x_MAC_t *MACInfo);
++void ae531x_EndResetMode(ae531x_MAC_t *MACInfo);
++BOOL ae531x_IsInResetMode(ae531x_MAC_t *MACInfo);
++int ae531x_RxQueueCreate(ae531x_MAC_t *MACInfo, AE531X_QUEUE *q,
++ char *pMem, int count);
++int ae531x_QueueDelete(struct ae531x_queue *q);
++void ae531x_DmaReset(ae531x_MAC_t *MACInfo);
++void ae531x_MACReset(ae531x_MAC_t *MACInfo);
++void ae531x_EnableComm(ae531x_MAC_t *MACInfo);
++void ae531x_DisableComm(ae531x_MAC_t *MACInfo);
++void ae531x_reset(ae531x_MAC_t *MACInfo);
++int ae531x_AllocateQueues(ae531x_MAC_t *MACInfo);
++void ae531x_FreeQueues(ae531x_MAC_t *MACInfo);
++void ae531x_QueueInit(AE531X_QUEUE *q, char *pMem, int count);
++UINT32 ae531x_ReadMacReg(ae531x_MAC_t *MACInfo, UINT32 reg);
++void ae531x_WriteMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data);
++void ae531x_SetMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
++void ae531x_ClearMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
++void ae531x_SetDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
++void ae531x_ClearDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
++UINT32 ae531x_ReadDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg);
++void ae531x_WriteDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data);
++UINT32 ae531x_ReadMiiReg(UINT32 phyBase, UINT32 reg);
++void ae531x_WriteMiiReg(UINT32 phyBase, UINT32 reg, UINT32 data);
++UINT16 ae531x_MiiRead(UINT32 phyBase, UINT32 phyAddr, UINT8 reg);
++void ae531x_MiiWrite(UINT32 phyBase, UINT32 phyAddr, UINT8 reg, UINT16 data);
++void ae531x_DmaIntEnable(ae531x_MAC_t *MACInfo);
++void ae531x_DmaIntDisable(ae531x_MAC_t *MACInfo);
++void ae531x_AckIntr(ae531x_MAC_t *MACInfo, UINT32 val);
++void *ae531x_rxbuf_alloc(ae531x_MAC_t *MACInfo, char **rxBptr, int *rxBSize);
++void ae531x_swptr_free(VIRT_ADDR txDesc);
++BOOL ae531x_twisted_enet(void);
++
++#endif /* _AE531XMAC_H_ */
+diff -urN linux-mips-orig/drivers/net/ath/ae531xreg.h linux-mips-new/drivers/net/ath/ae531xreg.h
+--- linux-mips-orig/drivers/net/ath/ae531xreg.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ae531xreg.h 2005-12-31 12:33:57.675538520 +0000
+@@ -0,0 +1,439 @@
++/*
++ * 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.
++ */
++
++/*
++ * See README to understand the decomposition of the ethernet driver.
++ *
++ * Register definitions for Atheros AR531X Ethernet MAC.
++ */
++
++#ifndef _AE531XREG_H_
++#define _AE531XREG_H_
++
++#define AE531X_MAC_OFFSET 0x0000
++#define AE531X_PHY_OFFSET 0x0000 /* Same as MAC offset */
++#define AE531X_DMA_OFFSET 0x1000
++
++/***********************************************************/
++/* MAC110 registers, base address is BAR+AE531X_MAC_OFFSET */
++/***********************************************************/
++#define MacControl 0x00 /* control */
++#define MacAddrHigh 0x04 /* address high */
++#define MacAddrLow 0x08 /* address low */
++#define MacMultiHashHigh 0x0C /* multicast hash table high */
++#define MacMultiHashLow 0x10 /* multicast hash table low */
++#define MacMiiAddr 0x14 /* MII address */
++#define MacMiiData 0x18 /* MII data */
++#define MacFlowControl 0x1C /* Flow control */
++#define MacVlan1Tag 0x4C /* VLAN1 tag */
++#define MacVlan2Tag 0x50 /* VLAN2 tag */
++
++
++/***************************************************************/
++/* DMA engine registers, base address is BAR+AE531X_DMA_OFFSET */
++/***************************************************************/
++#define DmaBusMode 0x00 /* CSR0 - Bus Mode */
++#define DmaTxPollDemand 0x04 /* CSR1 - Transmit Poll Demand */
++#define DmaRxPollDemand 0x08 /* CSR2 - Receive Poll Demand */
++#define DmaRxBaseAddr 0x0C /* CSR3 - Receive list base address */
++#define DmaTxBaseAddr 0x10 /* CSR4 - Transmit list base address */
++#define DmaStatus 0x14 /* CSR5 - Dma status */
++#define DmaControl 0x18 /* CSR6 - Dma control */
++#define DmaIntrEnb 0x1C /* CSR7 - Interrupt enable */
++#define DmaOverflowCnt 0x20 /* CSR8 - Missed Frame and Buff Overflow counter */
++#define DmaTxCurrAddr 0x50 /* CSR20 - Current host transmit buffer address */
++#define DmaRxCurrAddr 0x54 /* CSR21 - Current host receive buffer address */
++
++/**********************************************************/
++/* MAC Control register layout */
++/**********************************************************/
++#define MacFilterOff 0x80000000 /* Receive all incoming packets RW */
++#define MacFilterOn 0 /* Receive filtered packets only 0 */
++#define MacBigEndian 0x40000000 /* Big endian mode RW */
++#define MacLittleEndian 0 /* Little endian 0 */
++#define MacHeartBeatOff 0x10000000 /* Heartbeat signal qual disable RW*/
++#define MacHeartBeatOn 0 /* Heartbeat signal qual enable 0 */
++#define MacSelectSrl 0x08000000 /* Select SRL port RW */
++#define MacSelectMii 0 /* Select MII port 0 */
++#define MacDisableRxOwn 0x00800000 /* Disable receive own packets RW */
++#define MacEnableRxOwn 0 /* Enable receive own packets 0 */
++#define MacLoopbackExt 0x00400000 /* External loopback RW */
++#define MacLoopbackInt 0x00200000 /* Internal loopback */
++#define MacLoopbackOff 0 /* Normal mode 00 */
++#define MacFullDuplex 0x00100000 /* Full duplex mode RW */
++#define MacHalfDuplex 0 /* Half duplex mode 0 */
++#define MacMulticastFilterOff 0x00080000 /* Pass all multicast packets RW */
++#define MacMulticastFilterOn 0 /* Pass filtered mcast packets 0 */
++#define MacPromiscuousModeOn 0x00040000 /* Receive all valid packets RW 1 */
++#define MacPromiscuousModeOff 0 /* Receive filtered packets only */
++#define MacFilterInverse 0x00020000 /* Inverse filtering RW */
++#define MacFilterNormal 0 /* Normal filtering 0 */
++#define MacBadFramesEnable 0x00010000 /* Pass bad frames RW */
++#define MacBadFramesDisable 0 /* Do not pass bad frames 0 */
++#define MacPerfectFilterOff 0x00008000 /* Hash filtering only RW */
++#define MacPerfectFilterOn 0 /* Both perfect and hash filtering 0 */
++#define MacHashFilterOn 0x00002000 /* perform hash filtering RW */
++#define MacHashFilterOff 0 /* perfect filtering only 0 */
++#define MacLateCollisionOn 0x00001000 /* Enable late collision control RW */
++#define MacLateCollisionOff 0 /* Disable late collision control 0 */
++#define MacBroadcastDisable 0x00000800 /* Disable reception of bcast frames RW */
++#define MacBroadcastEnable 0 /* Enable broadcast frames 0 */
++#define MacRetryDisable 0x00000400 /* Disable retransmission RW */
++#define MacRetryEnable 0 /* Enable retransmission 0 */
++#define MacPadStripEnable 0x00000100 /* Pad stripping enable RW */
++#define MacPadStripDisable 0 /* Pad stripping disable 0 */
++#define MacBackoff 0 /* Backoff Limit RW 00 */
++#define MacDeferralCheckEnable 0x00000020 /* Deferral check enable RW */
++#define MacDeferralCheckDisable 0 /* Deferral check disable 0 */
++#define MacTxEnable 0x00000008 /* Transmitter enable RW */
++#define MacTxDisable 0 /* Transmitter disable 0 */
++#define MacRxEnable 0x00000004 /* Receiver enable RW */
++#define MacRxDisable 0 /* Receiver disable 0 */
++
++
++/**********************************************************/
++/* MII address register layout */
++/**********************************************************/
++#define MiiDevMask 0x0000F800 /* MII device address */
++#define MiiDevShift 11
++#define MiiRegMask 0x000007C0 /* MII register */
++#define MiiRegShift 6
++#define MiiWrite 0x00000002 /* Write to register */
++#define MiiRead 0 /* Read from register */
++#define MiiBusy 0x00000001 /* MII interface is busy */
++
++/**********************************************************/
++/* MII Data register layout */
++/**********************************************************/
++#define MiiDataMask 0x0000FFFF /* MII Data */
++
++/**********************************************************/
++/* MAC flow control register layout */
++/**********************************************************/
++#define MacPauseTimeMask 0xFFFF0000 /* PAUSE TIME field in ctrl frame */
++#define MacPauseTimeShift 15
++#define MacControlFrameEnable 0x00000004 /* Enable pass ctrl frames to host */
++#define MacControlFrameDisable 0 /* Do not pass ctrl frames to host */
++#define MacFlowControlEnable 0x00000002 /* Enable flow control */
++#define MacFlowControlDisable 0 /* Disable flow control */
++#define MacSendPauseFrame 0x00000001 /* send pause frame */
++
++/**********************************************************/
++/* DMA bus mode register layout */
++/**********************************************************/
++#define DmaRxAlign16 0x01000000 /* Force all rx buffers to align on odd hw bndry */
++#define DmaBigEndianDes 0x00100000 /* Big endian data buffer descriptors RW */
++#define DmaLittleEndianDesc 0 /* Little endian data descriptors */
++#define DmaBurstLength32 0x00002000 /* Dma burst length 32 RW */
++#define DmaBurstLength16 0x00001000 /* Dma burst length 16 */
++#define DmaBurstLength8 0x00000800 /* Dma burst length 8 */
++#define DmaBurstLength4 0x00000400 /* Dma burst length 4 */
++#define DmaBurstLength2 0x00000200 /* Dma burst length 2 */
++#define DmaBurstLength1 0x00000100 /* Dma burst length 1 */
++#define DmaBurstLength0 0x00000000 /* Dma burst length 0 */
++#define DmaBigEndianData 0x00000080 /* Big endian data buffers RW */
++#define DmaLittleEndianData 0 /* Little endian data buffers 0 */
++#define DmaDescriptorSkip16 0x00000040 /* number of dwords to skip RW */
++#define DmaDescriptorSkip8 0x00000020 /* between two unchained descriptors */
++#define DmaDescriptorSkip4 0x00000010
++#define DmaDescriptorSkip2 0x00000008
++#define DmaDescriptorSkip1 0x00000004
++#define DmaDescriptorSkip0 0
++#define DmaReceivePriorityOff 0x00000002 /* equal rx and tx priorities RW */
++#define DmaReceivePriorityOn 0 /* Rx has prioryty over Tx 0 */
++#define DmaResetOn 0x00000001 /* Reset DMA engine RW */
++#define DmaResetOff 0
++
++/**********************************************************/
++/* DMA Status register layout */
++/**********************************************************/
++#define DmaRxAbort 0x01000000 /* receiver bus abort R 0 */
++#define DmaTxAbort 0x00800000 /* transmitter bus abort R 0 */
++#define DmaTxState 0x00700000 /* Transmit process state R 000 */
++#define DmaTxStopped 0x00000000 /* Stopped */
++#define DmaTxFetching 0x00100000 /* Running - fetching the descriptor */
++#define DmaTxWaiting 0x00200000 /* Running - waiting for end of transmission */
++#define DmaTxReading 0x00300000 /* Running - reading the data from memory */
++#define DmaTxSuspended 0x00600000 /* Suspended */
++#define DmaTxClosing 0x00700000 /* Running - closing descriptor */
++#define DmaRxState 0x000E0000 /* Receive process state 000 */
++#define DmaRxStopped 0x00000000 /* Stopped */
++#define DmaRxFetching 0x00020000 /* Running - fetching the descriptor */
++#define DmaRxChecking 0x00040000 /* Running - checking for end of packet */
++#define DmaRxWaiting 0x00060000 /* Running - waiting for packet */
++#define DmaRxSuspended 0x00080000 /* Suspended */
++#define DmaRxClosing 0x000A0000 /* Running - closing descriptor */
++#define DmaRxFlushing 0x000C0000 /* Running - flushing the current frame */
++#define DmaRxQueuing 0x000E0000 /* Running - queuing the recieve frame into host memory */
++#define DmaIntNormal 0x00010000 /* Normal interrupt summary RW 0 */
++#define DmaIntAbnormal 0x00008000 /* Abnormal interrupt summary RW 0 */
++#define DmaIntEarlyRx 0x00004000 /* Early receive interrupt (Normal) RW 0 */
++#define DmaIntBusError 0x00002000 /* Fatal bus error (Abnormal) RW 0 */
++#define DmaIntEarlyTx 0x00000400 /* Early transmit interrupt RW 0 */
++#define DmaIntRxStopped 0x00000100 /* Receive process stopped (Abnormal) RW 0 */
++#define DmaIntRxNoBuffer 0x00000080 /* Receive buffer unavailable (Abnormal) RW 0*/
++#define DmaIntRxCompleted 0x00000040 /* Completion of frame reception(Normal) RW 0*/
++#define DmaIntTxUnderflow 0x00000020 /* Transmit underflow (Abnormal) RW 0 */
++#define DmaIntTxJabber 0x00000008 /* Transmit Jabber Timeout (Abnormal) RW 0 */
++#define DmaIntTxNoBuffer 0x00000004 /* Transmit buffer unavailable (Normal) RW 0*/
++#define DmaIntTxStopped 0x00000002 /* Transmit process stopped (Abnormal) RW 0 */
++#define DmaIntTxCompleted 0x00000001 /* Transmit completed (Normal) RW 0 */
++
++/**********************************************************/
++/* DMA control register layout */
++/**********************************************************/
++#define DmaStoreAndForward 0x00000000 /* Store and forward RW 0 */
++#define DmaTxThreshCtl256 0x0000c000 /* Non-SF threshold is 256 words */
++#define DmaTxThreshCtl128 0x00008000 /* Non-SF threshold is 128 words */
++#define DmaTxThreshCtl064 0x00004000 /* Non-SF threshold is 64 words */
++#define DmaTxThreshCtl032 0x00000000 /* Non-SF threshold is 32 words */
++#define DmaTxStart 0x00002000 /* Start/Stop transmission RW 0 */
++#define DmaTxSecondFrame 0x00000004 /* Operate on second frame RW 0 */
++#define DmaRxStart 0x00000002 /* Start/Stop reception RW 0 */
++
++/**********************************************************/
++/* DMA interrupt enable register layout */
++/**********************************************************/
++#define DmaIeNormal DmaIntNormal /* Normal interrupt enable RW 0 */
++#define DmaIeAbnormal DmaIntAbnormal /* Abnormal interrupt enable RW 0 */
++#define DmaIeEarlyRx DmaIntEarlyRx /* Early receive interrupt enable RW 0 */
++#define DmaIeBusError DmaIntBusError /* Fatal bus error enable RW 0 */
++#define DmaIeEarlyTx DmaIntEarlyTx /* Early transmit interrupt enable RW 0 */
++#define DmaIeRxStopped DmaIntRxStopped /* Receive process stopped enable RW 0 */
++#define DmaIeRxNoBuffer DmaIntRxNoBuffer /* Receive buffer unavailable enable RW 0 */
++#define DmaIeRxCompleted DmaIntRxCompleted /* Completion of frame reception enable RW 0 */
++#define DmaIeTxUnderflow DmaIntTxUnderflow /* Transmit underflow enable RW 0 */
++#define DmaIeTxJabber DmaIntTxJabber /* Transmit jabber timeout RW 0 */
++#define DmaIeTxNoBuffer DmaIntTxNoBuffer /* Transmit buffer unavailable enable RW 0 */
++#define DmaIeTxStopped DmaIntTxStopped /* Transmit process stopped enable RW 0 */
++#define DmaIeTxCompleted DmaIntTxCompleted /* Transmit completed enable RW 0 */
++
++/****************************************************************/
++/* DMA Missed Frame and Buffer Overflow Counter register layout */
++/****************************************************************/
++#define DmaRxBufferMissedFrame 0xffff0000 /* cleared on read */
++#define DmaMissedFrameShift 16
++#define DmaRxBufferOverflowCnt 0x0000ffff /* cleared on read */
++#define DmaMissedFrameCountMask 0x0000ffff
++
++/**********************************************************/
++/* DMA Engine descriptor layout */
++/**********************************************************/
++/* status word of DMA descriptor */
++#define DescOwnByDma 0x80000000 /* Descriptor is owned by DMA engine */
++#define DescFrameLengthMask 0x3FFF0000 /* Receive descriptor frame length */
++#define DescFrameLengthShift 16
++#define DescError 0x00008000 /* Error summary bit OR of following bits */
++#define DescRxTruncated 0x00004000 /* Rx - no more descs for receive frame */
++#define DescRxLengthError 0x00001000 /* Rx - frame size not matching with length field */
++#define DescRxRunt 0x00000800 /* Rx - runt frame, damaged by a
++ collision or term before 64 bytes */
++#define DescRxMulticast 0x00000400 /* Rx - received frame is multicast */
++#define DescRxFirst 0x00000200 /* Rx - first descriptor of the frame */
++#define DescRxLast 0x00000100 /* Rx - last descriptor of the frame */
++#define DescRxLongFrame 0x00000080 /* Rx - frame is longer than 1518 bytes */
++#define DescRxLateColl 0x00000040 /* Rx - frame was damaged by a late collision */
++#define DescRxFrameEther 0x00000020 /* Rx - Frame type Ethernet 802.3*/
++#define DescRxMiiError 0x00000008 /* Rx - error reported by MII interface */
++#define DescRxDribbling 0x00000004 /* Rx - frame contains noninteger multiple of 8 bits */
++#define DescRxCrc 0x00000002 /* Rx - CRC error */
++#define DescTxTimeout 0x00004000 /* Tx - Transmit jabber timeout */
++#define DescTxLostCarrier 0x00000800 /* Tx - carrier lost during tramsmission */
++#define DescTxNoCarrier 0x00000400 /* Tx - no carrier signal from tranceiver */
++#define DescTxLateCollision 0x00000200 /* Tx - transmission aborted due to collision */
++#define DescTxExcCollisions 0x00000100 /* Tx - transmission aborted after 16 collisions */
++#define DescTxHeartbeatFail 0x00000080 /* Tx - heartbeat collision check failure */
++#define DescTxCollMask 0x00000078 /* Tx - Collision count */
++#define DescTxCollShift 3
++#define DescTxExcDeferral 0x00000004 /* Tx - excessive deferral */
++#define DescTxUnderflow 0x00000002 /* Tx - late data arrival from memory */
++#define DescTxDeferred 0x00000001 /* Tx - frame transmision deferred */
++
++/* length word of DMA descriptor */
++#define DescTxIntEnable 0x80000000 /* Tx - interrupt on completion */
++#define DescTxLast 0x40000000 /* Tx - Last segment of the frame */
++#define DescTxFirst 0x20000000 /* Tx - First segment of the frame */
++#define DescTxDisableCrc 0x04000000 /* Tx - Add CRC disabled (first segment only) */
++#define DescEndOfRing 0x02000000 /* End of descriptors ring */
++#define DescChain 0x01000000 /* Second buffer address is chain address */
++#define DescTxDisablePadd 0x00800000 /* disable padding */
++#define DescSize2Mask 0x003FF800 /* Buffer 2 size */
++#define DescSize2Shift 11
++#define DescSize1Mask 0x000007FF /* Buffer 1 size */
++#define DescSize1Shift 0
++
++/**********************************************************/
++/* Initial register values */
++/**********************************************************/
++/* Full-duplex mode with perfect filter on */
++#define MacControlInitFdx \
++ ( MacFilterOn \
++ | MacLittleEndian \
++ | MacHeartBeatOn \
++ | MacSelectMii \
++ | MacEnableRxOwn \
++ | MacLoopbackOff \
++ | MacFullDuplex \
++ | MacMulticastFilterOn \
++ | MacPromiscuousModeOff \
++ | MacFilterNormal \
++ | MacBadFramesDisable \
++ | MacPerfectFilterOn \
++ | MacHashFilterOff \
++ | MacLateCollisionOff \
++ | MacBroadcastEnable \
++ | MacRetryEnable \
++ | MacPadStripDisable \
++ | MacDeferralCheckDisable \
++ | MacTxEnable \
++ | MacRxEnable)
++
++/* Full-duplex mode */
++#define MacFlowControlInitFdx \
++ ( MacControlFrameDisable \
++ | MacFlowControlEnable)
++
++/* Half-duplex mode with perfect filter on */
++#define MacControlInitHdx \
++ ( MacFilterOn \
++ | MacLittleEndian \
++ | MacHeartBeatOn \
++ | MacSelectMii \
++ | MacDisableRxOwn \
++ | MacLoopbackOff \
++ | MacHalfDuplex \
++ | MacMulticastFilterOn \
++ | MacPromiscuousModeOff \
++ | MacFilterNormal \
++ | MacBadFramesDisable \
++ | MacPerfectFilterOn \
++ | MacHashFilterOff \
++ | MacLateCollisionOff \
++ | MacBroadcastEnable \
++ | MacRetryEnable \
++ | MacPadStripDisable \
++ | MacDeferralCheckDisable \
++ | MacTxEnable \
++ | MacRxEnable)
++
++/* Half-duplex mode */
++#define MacFlowControlInitHdx \
++ ( MacControlFrameDisable \
++ | MacFlowControlDisable)
++
++/* Bus Mode Rx odd half word align */
++#define DmaBusModeInit \
++ ( DmaLittleEndianDesc \
++ | DmaRxAlign16 \
++ | DmaBurstLength32 \
++ | DmaBigEndianData \
++ | DmaDescriptorSkip1 \
++ | DmaReceivePriorityOn \
++ | DmaResetOff)
++
++#define DmaControlInit (DmaStoreAndForward)
++
++/* Interrupt groups */
++#define DmaIntEnable \
++ ( DmaIeNormal \
++ | DmaIeAbnormal \
++ | DmaIntBusError \
++ | DmaIntRxStopped \
++ | DmaIntRxNoBuffer \
++ | DmaIntRxCompleted \
++ | DmaIntTxUnderflow \
++ | DmaIntTxStopped)
++
++#define DmaIntDisable 0
++
++#define DmaAllIntCauseMask \
++ ( DmaIeNormal \
++ | DmaIeAbnormal \
++ | DmaIntEarlyRx \
++ | DmaIntBusError \
++ | DmaIntEarlyTx \
++ | DmaIntRxStopped \
++ | DmaIntRxNoBuffer \
++ | DmaIntRxCompleted \
++ | DmaIntTxUnderflow \
++ | DmaIntTxJabber \
++ | DmaIntTxNoBuffer \
++ | DmaIntTxStopped \
++ | DmaIntTxCompleted)
++
++#define UnhandledIntrMask \
++ (DmaAllIntCauseMask \
++ & ~(DmaIntRxNoBuffer \
++ | DmaIntTxStopped \
++ | DmaIntTxJabber \
++ | DmaIntTxUnderflow \
++ | DmaIntBusError \
++ | DmaIntRxCompleted ))
++
++#define DescRxErrors \
++ (DescRxTruncated \
++ | DescRxRunt \
++ | DescRxLateColl \
++ | DescRxMiiError \
++ | DescRxCrc)
++
++#define DescTxErrors \
++ ( DescTxTimeout \
++ | DescTxLateCollision \
++ | DescTxExcCollisions \
++ | DescTxExcDeferral \
++ | DescTxUnderflow)
++
++/**********************************************************/
++/* Descriptor Layout */
++/**********************************************************/
++#define AE531X_DESC_STATUS 0x00 /* Status offset */
++#define AE531X_DESC_CTRLEN 0x04 /* Control and Length offset */
++#define AE531X_DESC_BUFPTR 0x08 /* Buffer pointer offset */
++#define AE531X_DESC_LNKBUF 0x0c /* Link field offset, or ptr to 2nd buf */
++#define AE531X_DESC_SWPTR 0x10 /* OS-Dependent software pointer */
++
++#define AE531X_DESC_SIZE 0x10 /* 4 words, 16 bytes */
++#define AE531X_QUEUE_ELE_SIZE 0x14 /* with software pointer extension */
++
++/* Accessors to the dma descriptor fields */
++#define AE531X_DESC_STATUS_GET(ptr) \
++ *(volatile UINT32 *)((UINT32)(ptr) + AE531X_DESC_STATUS)
++
++#define AE531X_DESC_STATUS_SET(ptr, val) \
++ AE531X_DESC_STATUS_GET(ptr) = (val)
++
++#define AE531X_DESC_CTRLEN_GET(ptr) \
++ *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_CTRLEN)
++
++#define AE531X_DESC_CTRLEN_SET(ptr, val) \
++ AE531X_DESC_CTRLEN_GET(ptr) = (val)
++
++#define AE531X_DESC_BUFPTR_GET(ptr) \
++ *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_BUFPTR)
++
++#define AE531X_DESC_BUFPTR_SET(ptr,val) \
++ AE531X_DESC_BUFPTR_GET(ptr) = (UINT32)(val)
++
++#define AE531X_DESC_LNKBUF_GET(ptr) \
++ *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_LNKBUF)
++
++#define AE531X_DESC_LNKBUF_SET(ptr, val) \
++ AE531X_DESC_LNKBUF_GET(ptr) = (val)
++
++#define AE531X_DESC_SWPTR_GET(ptr) \
++ (void *)(*(volatile UINT32 *) ((UINT32)ptr + AE531X_DESC_SWPTR))
++
++#define AE531X_DESC_SWPTR_SET(ptr,val) \
++ AE531X_DESC_SWPTR_GET(ptr) = (void *)(val)
++
++/* Get size of Rx data from desc, in bytes */
++#define AE531X_DESC_STATUS_RX_SIZE(x) \
++ (((x) & DescFrameLengthMask) >> DescFrameLengthShift)
++
++#endif /* _AE531XREG_H_ */
+diff -urN linux-mips-orig/drivers/net/ath/ar531x.h linux-mips-new/drivers/net/ath/ar531x.h
+--- linux-mips-orig/drivers/net/ath/ar531x.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ar531x.h 2005-12-31 12:33:57.676538368 +0000
+@@ -0,0 +1,1124 @@
++/*
++ * 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.
++ */
++
++#ifndef AR531X_H
++#define AR531X_H 1
++
++
++#ifndef CONFIG_AR5315
++
++#include <asm/addrspace.h>
++
++/* Address Map */
++#define AR531X_WLAN0 0x18000000
++#define AR531X_WLAN1 0x18500000
++#define AR531X_ENET0 0x18100000
++#define AR531X_ENET1 0x18200000
++#define AR531X_SDRAMCTL 0x18300000
++#define AR531X_FLASHCTL 0x18400000
++#define AR531X_APBBASE 0x1c000000
++#define AR531X_FLASH 0x1e000000
++
++/*
++ * AR531X_NUM_ENET_MAC defines the number of ethernet MACs that
++ * should be considered available. The AR5312 supports 2 enet MACS,
++ * even though many reference boards only actually use 1 of them
++ * (i.e. Only MAC 0 is actually connected to an enet PHY or PHY switch.
++ * The AR2312 supports 1 enet MAC.
++ */
++#define AR531X_NUM_ENET_MAC 2
++
++/*
++ * Need these defines to determine true number of ethernet MACs
++ */
++#define AR5212_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
++#define AR5212_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
++#define AR5212_AR2313_REV8 0x0058 /* AR2313 WMAC (AP43-030) */
++#define AR531X_RADIO_MASK_OFF 0xc8
++#define AR531X_RADIO0_MASK 0x0003
++#define AR531X_RADIO1_MASK 0x000c
++#define AR531X_RADIO1_S 2
++
++/*
++ * AR531X_NUM_WMAC defines the number of Wireless MACs that\
++ * should be considered available.
++ */
++#define AR531X_NUM_WMAC 2
++
++/* Reset/Timer Block Address Map */
++#define AR531X_RESETTMR (AR531X_APBBASE + 0x3000)
++#define AR531X_TIMER (AR531X_RESETTMR + 0x0000) /* countdown timer */
++#define AR531X_WD_CTRL (AR531X_RESETTMR + 0x0008) /* watchdog cntrl */
++#define AR531X_WD_TIMER (AR531X_RESETTMR + 0x000c) /* watchdog timer */
++#define AR531X_ISR (AR531X_RESETTMR + 0x0010) /* Intr Status Reg */
++#define AR531X_IMR (AR531X_RESETTMR + 0x0014) /* Intr Mask Reg */
++#define AR531X_RESET (AR531X_RESETTMR + 0x0020)
++#define AR5312_CLOCKCTL1 (AR531X_RESETTMR + 0x0064)
++#define AR5312_SCRATCH (AR531X_RESETTMR + 0x006c)
++#define AR531X_PROCADDR (AR531X_RESETTMR + 0x0070)
++#define AR531X_PROC1 (AR531X_RESETTMR + 0x0074)
++#define AR531X_DMAADDR (AR531X_RESETTMR + 0x0078)
++#define AR531X_DMA1 (AR531X_RESETTMR + 0x007c)
++#define AR531X_ENABLE (AR531X_RESETTMR + 0x0080) /* interface enb */
++#define AR531X_REV (AR531X_RESETTMR + 0x0090) /* revision */
++
++/* AR531X_WD_CTRL register bit field definitions */
++#define AR531X_WD_CTRL_IGNORE_EXPIRATION 0x0000
++#define AR531X_WD_CTRL_NMI 0x0001
++#define AR531X_WD_CTRL_RESET 0x0002
++
++/* AR531X_ISR register bit field definitions */
++#define AR531X_ISR_NONE 0x0000
++#define AR531X_ISR_TIMER 0x0001
++#define AR531X_ISR_AHBPROC 0x0002
++#define AR531X_ISR_AHBDMA 0x0004
++#define AR531X_ISR_GPIO 0x0008
++#define AR531X_ISR_UART0 0x0010
++#define AR531X_ISR_UART0DMA 0x0020
++#define AR531X_ISR_WD 0x0040
++#define AR531X_ISR_LOCAL 0x0080
++
++/* AR531X_RESET register bit field definitions */
++#define AR531X_RESET_SYSTEM 0x00000001 /* cold reset full system */
++#define AR531X_RESET_PROC 0x00000002 /* cold reset MIPS core */
++#define AR531X_RESET_WLAN0 0x00000004 /* cold reset WLAN MAC and BB */
++#define AR531X_RESET_EPHY0 0x00000008 /* cold reset ENET0 phy */
++#define AR531X_RESET_EPHY1 0x00000010 /* cold reset ENET1 phy */
++#define AR531X_RESET_ENET0 0x00000020 /* cold reset ENET0 mac */
++#define AR531X_RESET_ENET1 0x00000040 /* cold reset ENET1 mac */
++#define AR531X_RESET_UART0 0x00000100 /* cold reset UART0 (high speed) */
++#define AR531X_RESET_WLAN1 0x00000200 /* cold reset WLAN MAC/BB */
++#define AR531X_RESET_APB 0x00000400 /* cold reset APB (ar5312) */
++#define AR531X_RESET_WARM_PROC 0x00001000 /* warm reset MIPS core */
++#define AR531X_RESET_WARM_WLAN0_MAC 0x00002000 /* warm reset WLAN0 MAC */
++#define AR531X_RESET_WARM_WLAN0_BB 0x00004000 /* warm reset WLAN0 BaseBand */
++#define AR531X_RESET_NMI 0x00010000 /* send an NMI to the processor */
++#define AR531X_RESET_WARM_WLAN1_MAC 0x00020000 /* warm reset WLAN1 mac */
++#define AR531X_RESET_WARM_WLAN1_BB 0x00040000 /* warm reset WLAN1 baseband */
++#define AR531X_RESET_LOCAL_BUS 0x00080000 /* reset local bus */
++#define AR531X_RESET_WDOG 0x00100000 /* last reset was a watchdog */
++
++#define AR531X_RESET_WMAC0_BITS \
++ AR531X_RESET_WLAN0 |\
++ AR531X_RESET_WARM_WLAN0_MAC |\
++ AR531X_RESET_WARM_WLAN0_BB
++
++#define AR531X_RESERT_WMAC1_BITS \
++ AR531X_RESET_WLAN1 |\
++ AR531X_RESET_WARM_WLAN1_MAC |\
++ AR531X_RESET_WARM_WLAN1_BB
++
++/* AR5312_CLOCKCTL1 register bit field definitions */
++#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030
++#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4
++#define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00
++#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8
++#define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000
++
++/* Valid for AR5312 and AR2312 */
++#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030
++#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4
++#define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00
++#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8
++#define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000
++
++/* Valid for AR2313 */
++#define AR2313_CLOCKCTL1_PREDIVIDE_MASK 0x00003000
++#define AR2313_CLOCKCTL1_PREDIVIDE_SHIFT 12
++#define AR2313_CLOCKCTL1_MULTIPLIER_MASK 0x001f0000
++#define AR2313_CLOCKCTL1_MULTIPLIER_SHIFT 16
++#define AR2313_CLOCKCTL1_DOUBLER_MASK 0x00000000
++
++
++/* AR531X_ENABLE register bit field definitions */
++#define AR531X_ENABLE_WLAN0 0x0001
++#define AR531X_ENABLE_ENET0 0x0002
++#define AR531X_ENABLE_ENET1 0x0004
++#define AR531X_ENABLE_UART_AND_WLAN1_PIO 0x0008 /* UART, and WLAN1 PIOs */
++#define AR531X_ENABLE_WLAN1_DMA 0x0010 /* WLAN1 DMAs */
++#define AR531X_ENABLE_WLAN1 \
++ (AR531X_ENABLE_UART_AND_WLAN1_PIO | AR531X_ENABLE_WLAN1_DMA)
++
++/* AR531X_REV register bit field definitions */
++#define AR531X_REV_WMAC_MAJ 0xf000
++#define AR531X_REV_WMAC_MAJ_S 12
++#define AR531X_REV_WMAC_MIN 0x0f00
++#define AR531X_REV_WMAC_MIN_S 8
++#define AR531X_REV_MAJ 0x00f0
++#define AR531X_REV_MAJ_S 4
++#define AR531X_REV_MIN 0x000f
++#define AR531X_REV_MIN_S 0
++#define AR531X_REV_CHIP (REV_MAJ|REV_MIN)
++
++/* Major revision numbers, bits 7..4 of Revision ID register */
++#define AR531X_REV_MAJ_AR5312 0x4
++#define AR531X_REV_MAJ_AR2313 0x5
++
++/* Minor revision numbers, bits 3..0 of Revision ID register */
++#define AR5312_REV_MIN_DUAL 0x0 /* Dual WLAN version */
++#define AR5312_REV_MIN_SINGLE 0x1 /* Single WLAN version */
++
++/* AR531X_FLASHCTL register bit field definitions */
++#define FLASHCTL_IDCY 0x0000000f /* Idle cycle turn around time */
++#define FLASHCTL_IDCY_S 0
++#define FLASHCTL_WST1 0x000003e0 /* Wait state 1 */
++#define FLASHCTL_WST1_S 5
++#define FLASHCTL_RBLE 0x00000400 /* Read byte lane enable */
++#define FLASHCTL_WST2 0x0000f800 /* Wait state 2 */
++#define FLASHCTL_WST2_S 11
++#define FLASHCTL_AC 0x00070000 /* Flash address check (added) */
++#define FLASHCTL_AC_S 16
++#define FLASHCTL_AC_128K 0x00000000
++#define FLASHCTL_AC_256K 0x00010000
++#define FLASHCTL_AC_512K 0x00020000
++#define FLASHCTL_AC_1M 0x00030000
++#define FLASHCTL_AC_2M 0x00040000
++#define FLASHCTL_AC_4M 0x00050000
++#define FLASHCTL_AC_8M 0x00060000
++#define FLASHCTL_AC_RES 0x00070000 /* 16MB is not supported */
++#define FLASHCTL_E 0x00080000 /* Flash bank enable (added) */
++#define FLASHCTL_BUSERR 0x01000000 /* Bus transfer error status flag */
++#define FLASHCTL_WPERR 0x02000000 /* Write protect error status flag */
++#define FLASHCTL_WP 0x04000000 /* Write protect */
++#define FLASHCTL_BM 0x08000000 /* Burst mode */
++#define FLASHCTL_MW 0x30000000 /* Memory width */
++#define FLASHCTL_MWx8 0x00000000 /* Memory width x8 */
++#define FLASHCTL_MWx16 0x10000000 /* Memory width x16 */
++#define FLASHCTL_MWx32 0x20000000 /* Memory width x32 (not supported) */
++#define FLASHCTL_ATNR 0x00000000 /* Access type == no retry */
++#define FLASHCTL_ATR 0x80000000 /* Access type == retry every */
++#define FLASHCTL_ATR4 0xc0000000 /* Access type == retry every 4 */
++
++/* ARM Flash Controller -- 3 flash banks with either x8 or x16 devices. */
++#define AR531X_FLASHCTL0 (AR531X_FLASHCTL + 0x00)
++#define AR531X_FLASHCTL1 (AR531X_FLASHCTL + 0x04)
++#define AR531X_FLASHCTL2 (AR531X_FLASHCTL + 0x08)
++
++/* ARM SDRAM Controller -- just enough to determine memory size */
++#define AR531X_MEM_CFG1 (AR531X_SDRAMCTL + 0x04)
++#define MEM_CFG1_AC0 0x00000700 /* bank 0: SDRAM addr check (added) */
++#define MEM_CFG1_AC0_S 8
++#define MEM_CFG1_AC1 0x00007000 /* bank 1: SDRAM addr check (added) */
++#define MEM_CFG1_AC1_S 12
++
++/* GPIO Address Map */
++#define AR531X_GPIO (AR531X_APBBASE + 0x2000)
++#define AR531X_GPIO_DO (AR531X_GPIO + 0x00) /* output register */
++#define AR531X_GPIO_DI (AR531X_GPIO + 0x04) /* intput register */
++#define AR531X_GPIO_CR (AR531X_GPIO + 0x08) /* control register */
++
++/* GPIO Control Register bit field definitions */
++#define GPIO_CR_M(x) (1 << (x)) /* mask for i/o */
++#define GPIO_CR_O(x) (0 << (x)) /* mask for output */
++#define GPIO_CR_I(x) (1 << (x)) /* mask for input */
++#define GPIO_CR_INT(x) (1 << ((x)+8)) /* mask for interrupt */
++#define GPIO_CR_UART(x) (1 << ((x)+16)) /* uart multiplex */
++
++
++typedef unsigned int AR531X_REG;
++
++#define sysRegRead(phys) \
++ (*(volatile AR531X_REG *)PHYS_TO_K1(phys))
++
++#define sysRegWrite(phys, val) \
++ ((*(volatile AR531X_REG *)PHYS_TO_K1(phys)) = (val))
++
++
++/*
++ * This is board-specific data that is stored in a "fixed" location in flash.
++ * It is shared across operating systems, so it should not be changed lightly.
++ * The main reason we need it is in order to extract the ethernet MAC
++ * address(es).
++ */
++struct ar531x_boarddata {
++ u32 magic; /* board data is valid */
++#define AR531X_BD_MAGIC 0x35333131 /* "5311", for all 531x platforms */
++ u16 cksum; /* checksum (starting with BD_REV 2) */
++ u16 rev; /* revision of this struct */
++#define BD_REV 4
++ char boardName[64]; /* Name of board */
++ u16 major; /* Board major number */
++ u16 minor; /* Board minor number */
++ u32 config; /* Board configuration */
++#define BD_ENET0 0x00000001 /* ENET0 is stuffed */
++#define BD_ENET1 0x00000002 /* ENET1 is stuffed */
++#define BD_UART1 0x00000004 /* UART1 is stuffed */
++#define BD_UART0 0x00000008 /* UART0 is stuffed (dma) */
++#define BD_RSTFACTORY 0x00000010 /* Reset factory defaults stuffed */
++#define BD_SYSLED 0x00000020 /* System LED stuffed */
++#define BD_EXTUARTCLK 0x00000040 /* External UART clock */
++#define BD_CPUFREQ 0x00000080 /* cpu freq is valid in nvram */
++#define BD_SYSFREQ 0x00000100 /* sys freq is set in nvram */
++#define BD_WLAN0 0x00000200 /* Enable WLAN0 */
++#define BD_MEMCAP 0x00000400 /* CAP SDRAM @ memCap for testing */
++#define BD_DISWATCHDOG 0x00000800 /* disable system watchdog */
++#define BD_WLAN1 0x00001000 /* Enable WLAN1 (ar5212) */
++#define BD_ISCASPER 0x00002000 /* FLAG for AR2312 */
++#define BD_WLAN0_2G_EN 0x00004000 /* FLAG for radio0_2G */
++#define BD_WLAN0_5G_EN 0x00008000 /* FLAG for radio0_2G */
++#define BD_WLAN1_2G_EN 0x00020000 /* FLAG for radio0_2G */
++#define BD_WLAN1_5G_EN 0x00040000 /* FLAG for radio0_2G */
++ u16 resetConfigGpio; /* Reset factory GPIO pin */
++ u16 sysLedGpio; /* System LED GPIO pin */
++
++ u32 cpuFreq; /* CPU core frequency in Hz */
++ u32 sysFreq; /* System frequency in Hz */
++ u32 cntFreq; /* Calculated C0_COUNT frequency */
++
++ u8 wlan0Mac[6];
++ u8 enet0Mac[6];
++ u8 enet1Mac[6];
++
++ u16 pciId; /* Pseudo PCIID for common code */
++ u16 memCap; /* cap bank1 in MB */
++
++ /* version 3 */
++ u8 wlan1Mac[6]; /* (ar5212) */
++};
++
++#else
++
++/*
++ * Add support for Cobra
++ *
++ * AR531XPLUSreg.h Register definitions for Atheros AR5311 and AR5312 chipsets.
++ * - WLAN registers are listed in
++ * hal/ar5211/ar5211Reg.h
++ * hal/ar5212/ar5212Reg.h
++ * - Ethernet registers are listed in ar531xenet.h
++ * - Standard UART is 16550 compatible.
++ */
++
++
++/*
++ * Address map
++ */
++#define AR531XPLUS_SDRAM0 0x00000000 /* DRAM */
++#define AR531XPLUS_SPI_READ 0x08000000 /* SPI FLASH */
++#define AR531XPLUS_WLAN0 0xB0000000 /* Wireless MMR */
++#define AR531XPLUS_PCI 0xB0100000 /* PCI MMR */
++#define AR531XPLUS_SDRAMCTL 0xB0300000 /* SDRAM MMR */
++#define AR531XPLUS_LOCAL 0xB0400000 /* LOCAL BUS MMR */
++#define AR531XPLUS_ENET0 0xB0500000 /* ETHERNET MMR */
++#define AR531XPLUS_DSLBASE 0xB1000000 /* RESET CONTROL MMR */
++#define AR531XPLUS_UART0 0xB1100003 /* UART MMR */
++#define AR531XPLUS_SPI 0xB1300000 /* SPI FLASH MMR */
++#define AR531XPLUS_FLASHBT 0xBfc00000 /* ro boot alias to FLASH */
++#define AR531XPLUS_RAM1 0x40000000 /* ram alias */
++#define AR531XPLUS_PCIEXT 0x80000000 /* pci external */
++#define AR531XPLUS_RAM2 0xc0000000 /* ram alias */
++#define AR531XPLUS_RAM3 0xe0000000 /* ram alias */
++
++#define AR531X_ENET0 AR531XPLUS_ENET0
++#define AR531X_ENET1 0
++/*
++ * Reset Register
++ */
++#define AR531XPLUS_COLD_RESET (AR531XPLUS_DSLBASE + 0x0000)
++
++/* Cold Reset */
++#define RESET_COLD_AHB 0x00000001
++#define RESET_COLD_APB 0x00000002
++#define RESET_COLD_CPU 0x00000004
++#define RESET_COLD_CPUWARM 0x00000008
++#define RESET_SYSTEM (RESET_COLD_CPU | RESET_COLD_APB | RESET_COLD_AHB) /* full system */
++
++/* Warm Reset */
++
++#define AR531XPLUS_RESET (AR531XPLUS_DSLBASE + 0x0004)
++#define AR531X_RESET AR531XPLUS_RESET
++
++#define RESET_WARM_WLAN0_MAC 0x00000001 /* warm reset WLAN0 MAC */
++#define RESET_WARM_WLAN0_BB 0x00000002 /* warm reset WLAN0 BaseBand */
++#define RESET_MPEGTS_RSVD 0x00000004 /* warm reset MPEG-TS */
++#define RESET_PCIDMA 0x00000008 /* warm reset PCI ahb/dma */
++#define RESET_MEMCTL 0x00000010 /* warm reset memory controller */
++#define RESET_LOCAL 0x00000020 /* warm reset local bus */
++#define RESET_I2C_RSVD 0x00000040 /* warm reset I2C bus */
++#define RESET_SPI 0x00000080 /* warm reset SPI interface */
++#define RESET_UART0 0x00000100 /* warm reset UART0 */
++#define RESET_IR_RSVD 0x00000200 /* warm reset IR interface */
++#define RESET_EPHY0 0x00000400 /* cold reset ENET0 phy */
++#define RESET_ENET0 0x00000800 /* cold reset ENET0 mac */
++
++#define AR531X_RESET_ENET0 RESET_ENET0
++#define AR531X_RESET_EPHY0 RESET_EPHY0
++#define AR531X_RESET_ENET1 0
++#define AR531X_RESET_EPHY1 0
++
++/*
++ * AHB master arbitration control
++ */
++#define AR531XPLUS_AHB_ARB_CTL (AR531XPLUS_DSLBASE + 0x0008)
++
++#define ARB_CPU 0x00000001 /* CPU, default */
++#define ARB_WLAN 0x00000002 /* WLAN */
++#define ARB_MPEGTS_RSVD 0x00000004 /* MPEG-TS */
++#define ARB_LOCAL 0x00000008 /* LOCAL */
++#define ARB_PCI 0x00000010 /* PCI */
++#define ARB_ETHERNET 0x00000020 /* Ethernet */
++#define ARB_RETRY 0x00000100 /* retry policy, debug only */
++
++/*
++ * Config Register
++ */
++#define AR531XPLUS_ENDIAN_CTL (AR531XPLUS_DSLBASE + 0x000c)
++
++#define CONFIG_AHB 0x00000001 /* EC - AHB bridge endianess */
++#define CONFIG_WLAN 0x00000002 /* WLAN byteswap */
++#define CONFIG_MPEGTS_RSVD 0x00000004 /* MPEG-TS byteswap */
++#define CONFIG_PCI 0x00000008 /* PCI byteswap */
++#define CONFIG_MEMCTL 0x00000010 /* Memory controller endianess */
++#define CONFIG_LOCAL 0x00000020 /* Local bus byteswap */
++#define CONFIG_ETHERNET 0x00000040 /* Ethernet byteswap */
++
++#define CONFIG_MERGE 0x00000200 /* CPU write buffer merge */
++#define CONFIG_CPU 0x00000400 /* CPU big endian */
++#define CONFIG_PCIAHB 0x00000800
++#define CONFIG_PCIAHB_BRIDGE 0x00001000
++#define CONFIG_SPI 0x00008000 /* SPI byteswap */
++#define CONFIG_CPU_DRAM 0x00010000
++#define CONFIG_CPU_PCI 0x00020000
++#define CONFIG_CPU_MMR 0x00040000
++#define CONFIG_BIG 0x00000400
++
++
++/*
++ * NMI control
++ */
++#define AR531XPLUS_NMI_CTL (AR531XPLUS_DSLBASE + 0x0010)
++
++#define NMI_EN 1
++
++/*
++ * Revision Register - Initial value is 0x3010 (WMAC 3.0, AR531X 1.0).
++ */
++#define AR531XPLUS_SREV (AR531XPLUS_DSLBASE + 0x0014)
++
++#define AR531X_REV AR531XPLUS_SREV
++
++#define REV_MAJ 0x00f0
++#define REV_MAJ_S 4
++#define REV_MIN 0x000f
++#define REV_MIN_S 0
++#define REV_CHIP (REV_MAJ|REV_MIN)
++
++#define AR531X_REV_MAJ REV_MAJ
++#define AR531X_REV_MAJ_S REV_MAJ_S
++#define AR531X_REV_MIN REV_MIN
++#define AR531X_REV_MIN_S REV_MIN_S
++#define REV_CHIP (REV_MAJ|REV_MIN)
++/*
++ * Need these defines to determine true number of ethernet MACs
++ */
++#define AR5212_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
++#define AR5212_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
++#define AR5212_AR2313_REV8 0x0058 /* AR2313 WMAC (AP43-030) */
++#define AR531X_RADIO_MASK_OFF 0xc8
++#define AR531X_RADIO0_MASK 0x0003
++#define AR531X_RADIO1_MASK 0x000c
++#define AR531X_RADIO1_S 2
++
++/* Major revision numbers, bits 7..4 of Revision ID register */
++#define AR531X_REV_MAJ_AR5312 0x4
++#define AR531X_REV_MAJ_AR2313 0x5
++
++/*
++ * AR531X_NUM_ENET_MAC defines the number of ethernet MACs that
++ * should be considered available. The AR5312 supports 2 enet MACS,
++ * even though many reference boards only actually use 1 of them
++ * (i.e. Only MAC 0 is actually connected to an enet PHY or PHY switch.
++ * The AR2312 supports 1 enet MAC.
++ */
++#define AR531X_NUM_ENET_MAC 1
++
++/*
++ * Interface Enable
++ */
++#define AR531XPLUS_IF_CTL (AR531XPLUS_DSLBASE + 0x0018)
++
++#define IF_MASK 0x00000007
++#define IF_DISABLED 0
++#define IF_PCI 1
++#define IF_TS_LOCAL 2
++#define IF_ALL 3 /* only for emulation with separate pins */
++#define IF_LOCAL_HOST 0x00000008
++#define IF_PCI_HOST 0x00000010
++#define IF_PCI_INTR 0x00000020
++#define IF_PCI_CLK_MASK 0x00030000
++#define IF_PCI_CLK_INPUT 0
++#define IF_PCI_CLK_OUTPUT_LOW 1
++#define IF_PCI_CLK_OUTPUT_CLK 2
++#define IF_PCI_CLK_OUTPUT_HIGH 3
++#define IF_PCI_CLK_SHIFT 16
++
++
++/* Major revision numbers, bits 7..4 of Revision ID register */
++#define REV_MAJ_AR5311 0x01
++#define REV_MAJ_AR5312 0x04
++#define REV_MAJ_AR5315 0x0B
++
++/*
++ * APB Interrupt control
++ */
++
++#define AR531XPLUS_ISR (AR531XPLUS_DSLBASE + 0x0020)
++#define AR531XPLUS_IMR (AR531XPLUS_DSLBASE + 0x0024)
++#define AR531XPLUS_GISR (AR531XPLUS_DSLBASE + 0x0028)
++
++#define ISR_UART0 0x0001 /* high speed UART */
++#define ISR_I2C_RSVD 0x0002 /* I2C bus */
++#define ISR_SPI 0x0004 /* SPI bus */
++#define ISR_AHB 0x0008 /* AHB error */
++#define ISR_APB 0x0010 /* APB error */
++#define ISR_TIMER 0x0020 /* timer */
++#define ISR_GPIO 0x0040 /* GPIO */
++#define ISR_WD 0x0080 /* watchdog */
++#define ISR_IR_RSVD 0x0100 /* IR */
++
++#define IMR_UART0 ISR_UART0
++#define IMR_I2C_RSVD ISR_I2C_RSVD
++#define IMR_SPI ISR_SPI
++#define IMR_AHB ISR_AHB
++#define IMR_APB ISR_APB
++#define IMR_TIMER ISR_TIMER
++#define IMR_GPIO ISR_GPIO
++#define IMR_WD ISR_WD
++#define IMR_IR_RSVD ISR_IR_RSVD
++
++#define GISR_MISC 0x0001
++#define GISR_WLAN0 0x0002
++#define GISR_MPEGTS_RSVD 0x0004
++#define GISR_LOCALPCI 0x0008
++#define GISR_WMACPOLL 0x0010
++#define GISR_TIMER 0x0020
++#define GISR_ETHERNET 0x0040
++
++/*
++ * Interrupt routing from IO to the processor IP bits
++ * Define our inter mask and level
++ */
++#define AR531XPLUS_INTR_MISCIO SR_IBIT3
++#define AR531XPLUS_INTR_WLAN0 SR_IBIT4
++#define AR531XPLUS_INTR_ENET0 SR_IBIT5
++#define AR531XPLUS_INTR_LOCALPCI SR_IBIT6
++#define AR531XPLUS_INTR_WMACPOLL SR_IBIT7
++#define AR531XPLUS_INTR_COMPARE SR_IBIT8
++
++/*
++ * Timers
++ */
++#define AR531XPLUS_TIMER (AR531XPLUS_DSLBASE + 0x0030)
++#define AR531XPLUS_RELOAD (AR531XPLUS_DSLBASE + 0x0034)
++#define AR531XPLUS_WD (AR531XPLUS_DSLBASE + 0x0038)
++#define AR531XPLUS_WDC (AR531XPLUS_DSLBASE + 0x003c)
++
++#define WDC_RESET 0x00000002 /* reset on watchdog */
++#define WDC_NMI 0x00000001 /* NMI on watchdog */
++#define WDC_IGNORE_EXPIRATION 0x00000000
++
++/*
++ * Interface Debug
++ */
++#define AR531X_FLASHDBG (AR531X_RESETTMR + 0x0040)
++#define AR531X_MIIDBG (AR531X_RESETTMR + 0x0044)
++
++
++/*
++ * CPU Performance Counters
++ */
++#define AR531XPLUS_PERFCNT0 (AR531XPLUS_DSLBASE + 0x0048)
++#define AR531XPLUS_PERFCNT1 (AR531XPLUS_DSLBASE + 0x004c)
++
++#define PERF_DATAHIT 0x0001 /* Count Data Cache Hits */
++#define PERF_DATAMISS 0x0002 /* Count Data Cache Misses */
++#define PERF_INSTHIT 0x0004 /* Count Instruction Cache Hits */
++#define PERF_INSTMISS 0x0008 /* Count Instruction Cache Misses */
++#define PERF_ACTIVE 0x0010 /* Count Active Processor Cycles */
++#define PERF_WBHIT 0x0020 /* Count CPU Write Buffer Hits */
++#define PERF_WBMISS 0x0040 /* Count CPU Write Buffer Misses */
++
++#define PERF_EB_ARDY 0x0001 /* Count EB_ARdy signal */
++#define PERF_EB_AVALID 0x0002 /* Count EB_AValid signal */
++#define PERF_EB_WDRDY 0x0004 /* Count EB_WDRdy signal */
++#define PERF_EB_RDVAL 0x0008 /* Count EB_RdVal signal */
++#define PERF_VRADDR 0x0010 /* Count valid read address cycles */
++#define PERF_VWADDR 0x0020 /* Count valid write address cycles */
++#define PERF_VWDATA 0x0040 /* Count valid write data cycles */
++
++/*
++ * AHB Error Reporting.
++ */
++#define AR531XPLUS_AHB_ERR0 (AR531XPLUS_DSLBASE + 0x0050) /* error */
++#define AR531XPLUS_AHB_ERR1 (AR531XPLUS_DSLBASE + 0x0054) /* haddr */
++#define AR531XPLUS_AHB_ERR2 (AR531XPLUS_DSLBASE + 0x0058) /* hwdata */
++#define AR531XPLUS_AHB_ERR3 (AR531XPLUS_DSLBASE + 0x005c) /* hrdata */
++#define AR531XPLUS_AHB_ERR4 (AR531XPLUS_DSLBASE + 0x0060) /* status */
++
++#define AHB_ERROR_DET 1 /* AHB Error has been detected, */
++ /* write 1 to clear all bits in ERR0 */
++#define AHB_ERROR_OVR 2 /* AHB Error overflow has been detected */
++#define AHB_ERROR_WDT 4 /* AHB Error due to wdt instead of hresp */
++
++#define PROCERR_HMAST 0x0000000f
++#define PROCERR_HMAST_DFLT 0
++#define PROCERR_HMAST_WMAC 1
++#define PROCERR_HMAST_ENET 2
++#define PROCERR_HMAST_PCIENDPT 3
++#define PROCERR_HMAST_LOCAL 4
++#define PROCERR_HMAST_CPU 5
++#define PROCERR_HMAST_PCITGT 6
++
++#define PROCERR_HMAST_S 0
++#define PROCERR_HWRITE 0x00000010
++#define PROCERR_HSIZE 0x00000060
++#define PROCERR_HSIZE_S 5
++#define PROCERR_HTRANS 0x00000180
++#define PROCERR_HTRANS_S 7
++#define PROCERR_HBURST 0x00000e00
++#define PROCERR_HBURST_S 9
++
++
++
++/*
++ * Clock Control
++ */
++#define AR531XPLUS_PLLC_CTL (AR531XPLUS_DSLBASE + 0x0064)
++#define AR531XPLUS_PLLV_CTL (AR531XPLUS_DSLBASE + 0x0068)
++#define AR531XPLUS_CPUCLK (AR531XPLUS_DSLBASE + 0x006c)
++#define AR531XPLUS_AMBACLK (AR531XPLUS_DSLBASE + 0x0070)
++#define AR531XPLUS_SYNCCLK (AR531XPLUS_DSLBASE + 0x0074)
++#define AR531XPLUS_DSL_SLEEP_CTL (AR531XPLUS_DSLBASE + 0x0080)
++#define AR531XPLUS_DSL_SLEEP_DUR (AR531XPLUS_DSLBASE + 0x0084)
++
++/* PLLc Control fields */
++#define PLLC_REF_DIV_M 0x00000003
++#define PLLC_REF_DIV_S 0
++#define PLLC_FDBACK_DIV_M 0x0000007C
++#define PLLC_FDBACK_DIV_S 2
++#define PLLC_ADD_FDBACK_DIV_M 0x00000080
++#define PLLC_ADD_FDBACK_DIV_S 7
++#define PLLC_CLKC_DIV_M 0x0001c000
++#define PLLC_CLKC_DIV_S 14
++#define PLLC_CLKM_DIV_M 0x00700000
++#define PLLC_CLKM_DIV_S 20
++
++/* CPU CLK Control fields */
++#define CPUCLK_CLK_SEL_M 0x00000003
++#define CPUCLK_CLK_SEL_S 0
++#define CPUCLK_CLK_DIV_M 0x0000000c
++#define CPUCLK_CLK_DIV_S 2
++
++/* AMBA CLK Control fields */
++#define AMBACLK_CLK_SEL_M 0x00000003
++#define AMBACLK_CLK_SEL_S 0
++#define AMBACLK_CLK_DIV_M 0x0000000c
++#define AMBACLK_CLK_DIV_S 2
++
++#if defined(COBRA_EMUL)
++#define AR531XPLUS_AMBA_CLOCK_RATE 20000000
++#define AR531XPLUS_CPU_CLOCK_RATE 40000000
++#else
++#if defined(DEFAULT_PLL)
++#define AR531XPLUS_AMBA_CLOCK_RATE 40000000
++#define AR531XPLUS_CPU_CLOCK_RATE 40000000
++#else
++#define AR531XPLUS_AMBA_CLOCK_RATE 92000000
++#define AR531XPLUS_CPU_CLOCK_RATE 184000000
++#endif /* ! DEFAULT_PLL */
++#endif /* ! COBRA_EMUL */
++
++#define AR531XPLUS_UART_CLOCK_RATE AR531XPLUS_AMBA_CLOCK_RATE
++#define AR531XPLUS_SDRAM_CLOCK_RATE AR531XPLUS_AMBA_CLOCK_RATE
++
++/*
++ * The UART computes baud rate as:
++ * baud = clock / (16 * divisor)
++ * where divisor is specified as a High Byte (DLM) and a Low Byte (DLL).
++ */
++#define DESIRED_BAUD_RATE 38400
++
++/*
++ * The WATCHDOG value is computed as
++ * 10 seconds * AR531X_WATCHDOG_CLOCK_RATE
++ */
++#define DESIRED_WATCHDOG_SECONDS 10
++#define AR531X_WATCHDOG_TIME \
++ (DESIRED_WATCHDOG_SECONDS * AR531X_WATCHDOG_CLOCK_RATE)
++
++
++#define CLOCKCTL_UART0 0x0010 /* enable UART0 external clock */
++
++
++ /*
++ * Applicable "PCICFG" bits for WLAN(s). Assoc status and LED mode.
++ */
++#define AR531X_PCICFG (AR531X_RESETTMR + 0x00b0)
++#define ASSOC_STATUS_M 0x00000003
++#define ASSOC_STATUS_NONE 0
++#define ASSOC_STATUS_PENDING 1
++#define ASSOC_STATUS_ASSOCIATED 2
++#define LED_MODE_M 0x0000001c
++#define LED_BLINK_THRESHOLD_M 0x000000e0
++#define LED_SLOW_BLINK_MODE 0x00000100
++
++/*
++ * GPIO
++ */
++
++#define AR531XPLUS_GPIO_DI (AR531XPLUS_DSLBASE + 0x0088)
++#define AR531XPLUS_GPIO_DO (AR531XPLUS_DSLBASE + 0x0090)
++#define AR531XPLUS_GPIO_CR (AR531XPLUS_DSLBASE + 0x0098)
++#define AR531XPLUS_GPIO_INT (AR531XPLUS_DSLBASE + 0x00a0)
++
++#define GPIO_CR_M(x) (1 << (x)) /* mask for i/o */
++#define GPIO_CR_O(x) (1 << (x)) /* output */
++#define GPIO_CR_I(x) (0 << (x)) /* input */
++
++#define GPIO_INT(x,Y) ((x) << (8 * (Y))) /* interrupt enable */
++#define GPIO_INT_M(Y) ((0x3F) << (8 * (Y))) /* mask for int */
++#define GPIO_INT_LVL(x,Y) ((x) << (8 * (Y) + 6)) /* interrupt level */
++#define GPIO_INT_LVL_M(Y) ((0x3) << (8 * (Y) + 6)) /* mask for int level */
++
++#define AR531XPLUS_RESET_GPIO 5
++#define AR531XPLUS_NUM_GPIO 22
++
++
++/*
++ * PCI Clock Control
++ */
++
++#define AR531XPLUS_PCICLK (AR531XPLUS_DSLBASE + 0x00a4)
++
++#define PCICLK_INPUT_M 0x3
++#define PCICLK_INPUT_S 0
++
++#define PCICLK_PLLC_CLKM 0
++#define PCICLK_PLLC_CLKM1 1
++#define PCICLK_PLLC_CLKC 2
++#define PCICLK_REF_CLK 3
++
++#define PCICLK_DIV_M 0xc
++#define PCICLK_DIV_S 2
++
++#define PCICLK_IN_FREQ 0
++#define PCICLK_IN_FREQ_DIV_6 1
++#define PCICLK_IN_FREQ_DIV_8 2
++#define PCICLK_IN_FREQ_DIV_10 3
++
++/*
++ * Observation Control Register
++ */
++#define AR531XPLUS_OCR (AR531XPLUS_DSLBASE + 0x00b0)
++#define OCR_GPIO0_IRIN 0x0040
++#define OCR_GPIO1_IROUT 0x0080
++#define OCR_GPIO3_RXCLR 0x0200
++
++/*
++ * General Clock Control
++ */
++
++#define AR531XPLUS_MISCCLK (AR531XPLUS_DSLBASE + 0x00b4)
++#define MISCCLK_PLLBYPASS_EN 0x00000001
++#define MISCCLK_PROCREFCLK 0x00000002
++
++/*
++ * SDRAM Controller
++ * - No read or write buffers are included.
++ */
++#define AR531XPLUS_MEM_CFG (AR531XPLUS_SDRAMCTL + 0x00)
++#define AR531XPLUS_MEM_CTRL (AR531XPLUS_SDRAMCTL + 0x0c)
++#define AR531XPLUS_MEM_REF (AR531XPLUS_SDRAMCTL + 0x10)
++
++#define SDRAM_DATA_WIDTH_M 0x00006000
++#define SDRAM_DATA_WIDTH_S 13
++
++#define SDRAM_COL_WIDTH_M 0x00001E00
++#define SDRAM_COL_WIDTH_S 9
++
++#define SDRAM_ROW_WIDTH_M 0x000001E0
++#define SDRAM_ROW_WIDTH_S 5
++
++#define SDRAM_BANKADDR_BITS_M 0x00000018
++#define SDRAM_BANKADDR_BITS_S 3
++
++
++/*
++ * SDRAM Memory Refresh (MEM_REF) value is computed as:
++ * MEMCTL_SREFR = (Tr * hclk_freq) / R
++ * where Tr is max. time of refresh of any single row
++ * R is number of rows in the DRAM
++ * For most 133MHz SDRAM parts, Tr=64ms, R=4096 or 8192
++ */
++#if defined(COBRA_EMUL)
++#define AR531XPLUS_SDRAM_MEMORY_REFRESH_VALUE 0x96
++#else
++#if defined(DEFAULT_PLL)
++#define AR531XPLUS_SDRAM_MEMORY_REFRESH_VALUE 0x200
++#else
++#define AR531XPLUS_SDRAM_MEMORY_REFRESH_VALUE 0x61a
++#endif /* ! DEFAULT_PLL */
++#endif
++
++#if defined(AR531XPLUS)
++
++#define AR531XPLUS_SDRAM_DDR_SDRAM 0 /* Not DDR SDRAM */
++#define AR531XPLUS_SDRAM_DATA_WIDTH 16 /* bits */
++#define AR531XPLUS_SDRAM_COL_WIDTH 8
++#define AR531XPLUS_SDRAM_ROW_WIDTH 12
++
++#else
++
++#define AR531XPLUS_SDRAM_DDR_SDRAM 0 /* Not DDR SDRAM */
++#define AR531XPLUS_SDRAM_DATA_WIDTH 16
++#define AR531XPLUS_SDRAM_COL_WIDTH 8
++#define AR531XPLUS_SDRAM_ROW_WIDTH 12
++
++#endif /* ! AR531XPLUS */
++
++/*
++ * SPI Flash Interface Registers
++ */
++
++#define AR531XPLUS_SPI_CTL (AR531XPLUS_SPI + 0x00)
++#define AR531XPLUS_SPI_OPCODE (AR531XPLUS_SPI + 0x04)
++#define AR531XPLUS_SPI_DATA (AR531XPLUS_SPI + 0x08)
++
++#define SPI_CTL_START 0x00000100
++#define SPI_CTL_BUSY 0x00010000
++#define SPI_CTL_TXCNT_MASK 0x0000000f
++#define SPI_CTL_RXCNT_MASK 0x000000f0
++#define SPI_CTL_TX_RX_CNT_MASK 0x000000ff
++#define SPI_CTL_SIZE_MASK 0x00060000
++
++#define SPI_CTL_CLK_SEL_MASK 0x03000000
++#define SPI_OPCODE_MASK 0x000000ff
++
++/*
++ * PCI-MAC Configuration registers
++ */
++#define PCI_MAC_RC (AR531XPLUS_PCI + 0x4000)
++#define PCI_MAC_SCR (AR531XPLUS_PCI + 0x4004)
++#define PCI_MAC_INTPEND (AR531XPLUS_PCI + 0x4008)
++#define PCI_MAC_SFR (AR531XPLUS_PCI + 0x400C)
++#define PCI_MAC_PCICFG (AR531XPLUS_PCI + 0x4010)
++#define PCI_MAC_SREV (AR531XPLUS_PCI + 0x4020)
++
++#define PCI_MAC_RC_MAC 0x00000001
++#define PCI_MAC_RC_BB 0x00000002
++
++#define PCI_MAC_SCR_SLMODE_M 0x00030000
++#define PCI_MAC_SCR_SLMODE_S 16
++#define PCI_MAC_SCR_SLM_FWAKE 0
++#define PCI_MAC_SCR_SLM_FSLEEP 1
++#define PCI_MAC_SCR_SLM_NORMAL 2
++
++#define PCI_MAC_SFR_SLEEP 0x00000001
++
++#define PCI_MAC_PCICFG_SPWR_DN 0x00010000
++
++
++
++
++/*
++ * PCI Bus Interface Registers
++ */
++#define AR531XPLUS_PCI_1MS_REG (AR531XPLUS_PCI + 0x0008)
++#define AR531XPLUS_PCI_1MS_MASK 0x3FFFF /* # of AHB clk cycles in 1ms */
++
++#define AR531XPLUS_PCI_MISC_CONFIG (AR531XPLUS_PCI + 0x000c)
++#define AR531XPLUS_PCIMISC_TXD_EN 0x00000001 /* Enable TXD for fragments */
++#define AR531XPLUS_PCIMISC_CFG_SEL 0x00000002 /* mem or config cycles */
++#define AR531XPLUS_PCIMISC_GIG_MASK 0x0000000C /* bits 31-30 for pci req */
++#define AR531XPLUS_PCIMISC_RST_MODE 0x00000030
++#define AR531XPLUS_PCIRST_INPUT 0x00000000 /* 4:5=0 rst is input */
++#define AR531XPLUS_PCIRST_LOW 0x00000010 /* 4:5=1 rst to GND */
++#define AR531XPLUS_PCIRST_HIGH 0x00000020 /* 4:5=2 rst to VDD */
++#define AR531XPLUS_PCIGRANT_EN 0x00000000 /* 6:7=0 early grant en */
++#define AR531XPLUS_PCIGRANT_FRAME 0x00000040 /* 6:7=1 grant waits 4 frame */
++#define AR531XPLUS_PCIGRANT_IDLE 0x00000080 /* 6:7=2 grant waits 4 idle */
++#define AR531XPLUS_PCIGRANT_GAP 0x00000000 /* 6:7=2 grant waits 4 idle */
++#define AR531XPLUS_PCICACHE_DIS 0x00001000 /* PCI external access cache disable */
++
++#define AR531XPLUS_PCI_OUT_TSTAMP (AR531XPLUS_PCI + 0x0010)
++
++#define AR531XPLUS_PCI_UNCACHE_CFG (AR531XPLUS_PCI + 0x0014)
++
++#define AR531XPLUS_PCI_IN_EN (AR531XPLUS_PCI + 0x0100)
++#define AR531XPLUS_PCI_IN_EN0 0x01 /* Enable chain 0 */
++#define AR531XPLUS_PCI_IN_EN1 0x02 /* Enable chain 1 */
++#define AR531XPLUS_PCI_IN_EN2 0x04 /* Enable chain 2 */
++#define AR531XPLUS_PCI_IN_EN3 0x08 /* Enable chain 3 */
++
++#define AR531XPLUS_PCI_IN_DIS (AR531XPLUS_PCI + 0x0104)
++#define AR531XPLUS_PCI_IN_DIS0 0x01 /* Disable chain 0 */
++#define AR531XPLUS_PCI_IN_DIS1 0x02 /* Disable chain 1 */
++#define AR531XPLUS_PCI_IN_DIS2 0x04 /* Disable chain 2 */
++#define AR531XPLUS_PCI_IN_DIS3 0x08 /* Disable chain 3 */
++
++#define AR531XPLUS_PCI_IN_PTR (AR531XPLUS_PCI + 0x0200)
++
++#define AR531XPLUS_PCI_OUT_EN (AR531XPLUS_PCI + 0x0400)
++#define AR531XPLUS_PCI_OUT_EN0 0x01 /* Enable chain 0 */
++
++#define AR531XPLUS_PCI_OUT_DIS (AR531XPLUS_PCI + 0x0404)
++#define AR531XPLUS_PCI_OUT_DIS0 0x01 /* Disable chain 0 */
++
++#define AR531XPLUS_PCI_OUT_PTR (AR531XPLUS_PCI + 0x0408)
++
++#define AR531XPLUS_PCI_INT_STATUS (AR531XPLUS_PCI + 0x0500) /* write one to clr */
++#define AR531XPLUS_PCI_TXINT 0x00000001 /* Desc In Completed */
++#define AR531XPLUS_PCI_TXOK 0x00000002 /* Desc In OK */
++#define AR531XPLUS_PCI_TXERR 0x00000004 /* Desc In ERR */
++#define AR531XPLUS_PCI_TXEOL 0x00000008 /* Desc In End-of-List */
++#define AR531XPLUS_PCI_RXINT 0x00000010 /* Desc Out Completed */
++#define AR531XPLUS_PCI_RXOK 0x00000020 /* Desc Out OK */
++#define AR531XPLUS_PCI_RXERR 0x00000040 /* Desc Out ERR */
++#define AR531XPLUS_PCI_RXEOL 0x00000080 /* Desc Out EOL */
++#define AR531XPLUS_PCI_TXOOD 0x00000200 /* Desc In Out-of-Desc */
++#define AR531XPLUS_PCI_MASK 0x0000FFFF /* Desc Mask */
++#define AR531XPLUS_PCI_EXT_INT 0x02000000
++#define AR531XPLUS_PCI_ABORT_INT 0x04000000
++
++#define AR531XPLUS_PCI_INT_MASK (AR531XPLUS_PCI + 0x0504) /* same as INT_STATUS */
++
++#define AR531XPLUS_PCI_INTEN_REG (AR531XPLUS_PCI + 0x0508)
++#define AR531XPLUS_PCI_INT_DISABLE 0x00 /* disable pci interrupts */
++#define AR531XPLUS_PCI_INT_ENABLE 0x01 /* enable pci interrupts */
++
++#define AR531XPLUS_PCI_HOST_IN_EN (AR531XPLUS_PCI + 0x0800)
++#define AR531XPLUS_PCI_HOST_IN_DIS (AR531XPLUS_PCI + 0x0804)
++#define AR531XPLUS_PCI_HOST_IN_PTR (AR531XPLUS_PCI + 0x0810)
++#define AR531XPLUS_PCI_HOST_OUT_EN (AR531XPLUS_PCI + 0x0900)
++#define AR531XPLUS_PCI_HOST_OUT_DIS (AR531XPLUS_PCI + 0x0904)
++#define AR531XPLUS_PCI_HOST_OUT_PTR (AR531XPLUS_PCI + 0x0908)
++
++
++/*
++ * Local Bus Interface Registers
++ */
++#define AR531XPLUS_LB_CONFIG (AR531XPLUS_LOCAL + 0x0000)
++#define AR531XPLUS_LBCONF_OE 0x00000001 /* =1 OE is low-true */
++#define AR531XPLUS_LBCONF_CS0 0x00000002 /* =1 first CS is low-true */
++#define AR531XPLUS_LBCONF_CS1 0x00000004 /* =1 2nd CS is low-true */
++#define AR531XPLUS_LBCONF_RDY 0x00000008 /* =1 RDY is low-true */
++#define AR531XPLUS_LBCONF_WE 0x00000010 /* =1 Write En is low-true */
++#define AR531XPLUS_LBCONF_WAIT 0x00000020 /* =1 WAIT is low-true */
++#define AR531XPLUS_LBCONF_ADS 0x00000040 /* =1 Adr Strobe is low-true */
++#define AR531XPLUS_LBCONF_MOT 0x00000080 /* =0 Intel, =1 Motorola */
++#define AR531XPLUS_LBCONF_8CS 0x00000100 /* =1 8 bits CS, 0= 16bits */
++#define AR531XPLUS_LBCONF_8DS 0x00000200 /* =1 8 bits Data S, 0=16bits */
++#define AR531XPLUS_LBCONF_ADS_EN 0x00000400 /* =1 Enable ADS */
++#define AR531XPLUS_LBCONF_ADR_OE 0x00000800 /* =1 Adr cap on OE, WE or DS */
++#define AR531XPLUS_LBCONF_ADDT_MUX 0x00001000 /* =1 Adr and Data share bus */
++#define AR531XPLUS_LBCONF_DATA_OE 0x00002000 /* =1 Data cap on OE, WE, DS */
++#define AR531XPLUS_LBCONF_16DATA 0x00004000 /* =1 Data is 16 bits wide */
++#define AR531XPLUS_LBCONF_SWAPDT 0x00008000 /* =1 Byte swap data */
++#define AR531XPLUS_LBCONF_SYNC 0x00010000 /* =1 Bus synchronous to clk */
++#define AR531XPLUS_LBCONF_INT 0x00020000 /* =1 Intr is low true */
++#define AR531XPLUS_LBCONF_INT_CTR0 0x00000000 /* GND high-Z, Vdd is high-Z */
++#define AR531XPLUS_LBCONF_INT_CTR1 0x00040000 /* GND drive, Vdd is high-Z */
++#define AR531XPLUS_LBCONF_INT_CTR2 0x00080000 /* GND high-Z, Vdd drive */
++#define AR531XPLUS_LBCONF_INT_CTR3 0x000C0000 /* GND drive, Vdd drive */
++#define AR531XPLUS_LBCONF_RDY_WAIT 0x00100000 /* =1 RDY is negative of WAIT */
++#define AR531XPLUS_LBCONF_INT_PULSE 0x00200000 /* =1 Interrupt is a pulse */
++#define AR531XPLUS_LBCONF_ENABLE 0x00400000 /* =1 Falcon respond to LB */
++
++#define AR531XPLUS_LB_CLKSEL (AR531XPLUS_LOCAL + 0x0004)
++#define AR531XPLUS_LBCLK_EXT 0x0001 /* use external clk for lb */
++
++#define AR531XPLUS_LB_1MS (AR531XPLUS_LOCAL + 0x0008)
++#define AR531XPLUS_LB1MS_MASK 0x3FFFF /* # of AHB clk cycles in 1ms */
++
++#define AR531XPLUS_LB_MISCCFG (AR531XPLUS_LOCAL + 0x000C)
++#define AR531XPLUS_LBM_TXD_EN 0x00000001 /* Enable TXD for fragments */
++#define AR531XPLUS_LBM_RX_INTEN 0x00000002 /* Enable LB ints on RX ready */
++#define AR531XPLUS_LBM_MBOXWR_INTEN 0x00000004 /* Enable LB ints on mbox wr */
++#define AR531XPLUS_LBM_MBOXRD_INTEN 0x00000008 /* Enable LB ints on mbox rd */
++#define AR531XPLUS_LMB_DESCSWAP_EN 0x00000010 /* Byte swap desc enable */
++#define AR531XPLUS_LBM_TIMEOUT_MASK 0x00FFFF80
++#define AR531XPLUS_LBM_TIMEOUT_SHFT 7
++#define AR531XPLUS_LBM_PORTMUX 0x07000000
++
++
++#define AR531XPLUS_LB_RXTSOFF (AR531XPLUS_LOCAL + 0x0010)
++
++#define AR531XPLUS_LB_TX_CHAIN_EN (AR531XPLUS_LOCAL + 0x0100)
++#define AR531XPLUS_LB_TXEN_0 0x01
++#define AR531XPLUS_LB_TXEN_1 0x02
++#define AR531XPLUS_LB_TXEN_2 0x04
++#define AR531XPLUS_LB_TXEN_3 0x08
++
++#define AR531XPLUS_LB_TX_CHAIN_DIS (AR531XPLUS_LOCAL + 0x0104)
++#define AR531XPLUS_LB_TX_DESC_PTR (AR531XPLUS_LOCAL + 0x0200)
++
++#define AR531XPLUS_LB_RX_CHAIN_EN (AR531XPLUS_LOCAL + 0x0400)
++#define AR531XPLUS_LB_RXEN 0x01
++
++#define AR531XPLUS_LB_RX_CHAIN_DIS (AR531XPLUS_LOCAL + 0x0404)
++#define AR531XPLUS_LB_RX_DESC_PTR (AR531XPLUS_LOCAL + 0x0408)
++
++#define AR531XPLUS_LB_INT_STATUS (AR531XPLUS_LOCAL + 0x0500)
++#define AR531XPLUS_INT_TX_DESC 0x0001
++#define AR531XPLUS_INT_TX_OK 0x0002
++#define AR531XPLUS_INT_TX_ERR 0x0004
++#define AR531XPLUS_INT_TX_EOF 0x0008
++#define AR531XPLUS_INT_RX_DESC 0x0010
++#define AR531XPLUS_INT_RX_OK 0x0020
++#define AR531XPLUS_INT_RX_ERR 0x0040
++#define AR531XPLUS_INT_RX_EOF 0x0080
++#define AR531XPLUS_INT_TX_TRUNC 0x0100
++#define AR531XPLUS_INT_TX_STARVE 0x0200
++#define AR531XPLUS_INT_LB_TIMEOUT 0x0400
++#define AR531XPLUS_INT_LB_ERR 0x0800
++#define AR531XPLUS_INT_MBOX_WR 0x1000
++#define AR531XPLUS_INT_MBOX_RD 0x2000
++
++/* Bit definitions for INT MASK are the same as INT_STATUS */
++#define AR531XPLUS_LB_INT_MASK (AR531XPLUS_LOCAL + 0x0504)
++
++#define AR531XPLUS_LB_INT_EN (AR531XPLUS_LOCAL + 0x0508)
++#define AR531XPLUS_LB_MBOX (AR531XPLUS_LOCAL + 0x0600)
++
++
++
++/*
++ * IR Interface Registers
++ */
++#define AR531XPLUS_IR_PKTDATA (AR531XPLUS_IR + 0x0000)
++
++#define AR531XPLUS_IR_PKTLEN (AR531XPLUS_IR + 0x07fc) /* 0 - 63 */
++
++#define AR531XPLUS_IR_CONTROL (AR531XPLUS_IR + 0x0800)
++#define AR531XPLUS_IRCTL_TX 0x00000000 /* use as tranmitter */
++#define AR531XPLUS_IRCTL_RX 0x00000001 /* use as receiver */
++#define AR531XPLUS_IRCTL_SAMPLECLK_MASK 0x00003ffe /* Sample clk divisor mask */
++#define AR531XPLUS_IRCTL_SAMPLECLK_SHFT 1
++#define AR531XPLUS_IRCTL_OUTPUTCLK_MASK 0x03ffc000 /* Output clk divisor mask */
++#define AR531XPLUS_IRCTL_OUTPUTCLK_SHFT 14
++
++#define AR531XPLUS_IR_STATUS (AR531XPLUS_IR + 0x0804)
++#define AR531XPLUS_IRSTS_RX 0x00000001 /* receive in progress */
++#define AR531XPLUS_IRSTS_TX 0x00000002 /* transmit in progress */
++
++#define AR531XPLUS_IR_CONFIG (AR531XPLUS_IR + 0x0808)
++#define AR531XPLUS_IRCFG_INVIN 0x00000001 /* invert input polarity */
++#define AR531XPLUS_IRCFG_INVOUT 0x00000002 /* invert output polarity */
++#define AR531XPLUS_IRCFG_SEQ_START_WIN_SEL 0x00000004 /* 1 => 28, 0 => 7 */
++#define AR531XPLUS_IRCFG_SEQ_START_THRESH 0x000000f0 /* */
++#define AR531XPLUS_IRCFG_SEQ_END_UNIT_SEL 0x00000100 /* */
++#define AR531XPLUS_IRCFG_SEQ_END_UNIT_THRESH 0x00007e00 /* */
++#define AR531XPLUS_IRCFG_SEQ_END_WIN_SEL 0x00008000 /* */
++#define AR531XPLUS_IRCFG_SEQ_END_WIN_THRESH 0x001f0000 /* */
++#define AR531XPLUS_IRCFG_NUM_BACKOFF_WORDS 0x01e00000 /* */
++
++/*
++ * PCI memory constants: Memory area 1 and 2 are the same size -
++ * (twice the PCI_TLB_PAGE_SIZE). The definition of
++ * CPU_TO_PCI_MEM_SIZE is coupled with the TLB setup routine
++ * sysLib.c/sysTlbInit(), in that it assumes that 2 pages of size
++ * PCI_TLB_PAGE_SIZE are set up in the TLB for each PCI memory space.
++ */
++
++#define CPU_TO_PCI_MEM_BASE1 0xE0000000
++#define CPU_TO_PCI_MEM_SIZE1 (2*PCI_TLB_PAGE_SIZE)
++
++
++/* TLB attributes for PCI transactions */
++
++#define PCI_MMU_PAGEMASK 0x00003FFF
++#define MMU_PAGE_UNCACHED 0x00000010
++#define MMU_PAGE_DIRTY 0x00000004
++#define MMU_PAGE_VALID 0x00000002
++#define MMU_PAGE_GLOBAL 0x00000001
++#define PCI_MMU_PAGEATTRIB (MMU_PAGE_UNCACHED|MMU_PAGE_DIRTY|\
++ MMU_PAGE_VALID|MMU_PAGE_GLOBAL)
++#define PCI_MEMORY_SPACE1_VIRT 0xE0000000 /* Used for non-prefet mem */
++#define PCI_MEMORY_SPACE1_PHYS 0x80000000
++#define PCI_TLB_PAGE_SIZE 0x01000000
++#define TLB_HI_MASK 0xFFFFE000
++#define TLB_LO_MASK 0x3FFFFFFF
++#define PAGEMASK_SHIFT 11
++#define TLB_LO_SHIFT 6
++
++#define PCI_MAX_LATENCY 0xFFF /* Max PCI latency */
++
++#define HOST_PCI_DEV_ID 3
++#define HOST_PCI_MBAR0 0x10000000
++#define HOST_PCI_MBAR1 0x20000000
++#define HOST_PCI_MBAR2 0x30000000
++
++#define HOST_PCI_SDRAM_BASEADDR HOST_PCI_MBAR1
++#define PCI_DEVICE_MEM_SPACE 0x800000
++
++
++typedef unsigned int AR531X_REG;
++
++#define sysRegRead(phys) \
++ (*(volatile AR531X_REG *)PHYS_TO_K1(phys))
++
++#define sysRegWrite(phys, val) \
++ ((*(volatile AR531X_REG *)PHYS_TO_K1(phys)) = (val))
++
++
++
++/*
++ * This is board-specific data that is stored in a "fixed" location in flash.
++ * It is shared across operating systems, so it should not be changed lightly.
++ * The main reason we need it is in order to extract the ethernet MAC
++ * address(es).
++ */
++struct ar531x_boarddata {
++ u32 magic; /* board data is valid */
++#define AR531X_BD_MAGIC 0x35333131 /* "5311", for all 531x platforms */
++ u16 cksum; /* checksum (starting with BD_REV 2) */
++ u16 rev; /* revision of this struct */
++#define BD_REV 4
++ char boardName[64]; /* Name of board */
++ u16 major; /* Board major number */
++ u16 minor; /* Board minor number */
++ u32 config; /* Board configuration */
++#define BD_ENET0 0x00000001 /* ENET0 is stuffed */
++#define BD_ENET1 0x00000002 /* ENET1 is stuffed */
++#define BD_UART1 0x00000004 /* UART1 is stuffed */
++#define BD_UART0 0x00000008 /* UART0 is stuffed (dma) */
++#define BD_RSTFACTORY 0x00000010 /* Reset factory defaults stuffed */
++#define BD_SYSLED 0x00000020 /* System LED stuffed */
++#define BD_EXTUARTCLK 0x00000040 /* External UART clock */
++#define BD_CPUFREQ 0x00000080 /* cpu freq is valid in nvram */
++#define BD_SYSFREQ 0x00000100 /* sys freq is set in nvram */
++#define BD_WLAN0 0x00000200 /* Enable WLAN0 */
++#define BD_MEMCAP 0x00000400 /* CAP SDRAM @ memCap for testing */
++#define BD_DISWATCHDOG 0x00000800 /* disable system watchdog */
++#define BD_WLAN1 0x00001000 /* Enable WLAN1 (ar5212) */
++#define BD_ISCASPER 0x00002000 /* FLAG for AR2312 */
++#define BD_WLAN0_2G_EN 0x00004000 /* FLAG for radio0_2G */
++#define BD_WLAN0_5G_EN 0x00008000 /* FLAG for radio0_2G */
++#define BD_WLAN1_2G_EN 0x00020000 /* FLAG for radio0_2G */
++#define BD_WLAN1_5G_EN 0x00040000 /* FLAG for radio0_2G */
++ u16 resetConfigGpio; /* Reset factory GPIO pin */
++ u16 sysLedGpio; /* System LED GPIO pin */
++
++ u32 cpuFreq; /* CPU core frequency in Hz */
++ u32 sysFreq; /* System frequency in Hz */
++ u32 cntFreq; /* Calculated C0_COUNT frequency */
++
++ u8 wlan0Mac[6];
++ u8 enet0Mac[6];
++ u8 enet1Mac[6];
++
++ u16 pciId; /* Pseudo PCIID for common code */
++ u16 memCap; /* cap bank1 in MB */
++
++ /* version 3 */
++ u8 wlan1Mac[6]; /* (ar5212) */
++};
++
++#endif
++
++#endif /* AR531X_H */
+diff -urN linux-mips-orig/drivers/net/ath/ar531xlnx.h linux-mips-new/drivers/net/ath/ar531xlnx.h
+--- linux-mips-orig/drivers/net/ath/ar531xlnx.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ar531xlnx.h 2005-12-31 12:33:57.676538368 +0000
+@@ -0,0 +1,137 @@
++/*
++ * 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.
++ */
++
++/*
++ * This file contains definitions needed in order to compile
++ * AR531X products for linux. Definitions that are largely
++ * AR531X-specific and independent of operating system belong
++ * in ar531x.h rather than this file.
++ */
++#ifndef __AR531XLNX_H
++#define __AR531XLNX_H
++#include "ar531x.h"
++
++#define MIPS_CPU_IRQ_BASE 0x00
++#define AR531X_HIGH_PRIO 0x10
++#define AR531X_MISC_IRQ_BASE 0x20
++#define AR531X_GPIO_IRQ_BASE 0x30
++
++/* Software's idea of interrupts handled by "CPU Interrupt Controller" */
++#if CONFIG_AR5315
++#define AR531X_IRQ_NONE MIPS_CPU_IRQ_BASE+0
++#define AR531X_IRQ_MISC_INTRS MIPS_CPU_IRQ_BASE+2 /* C0_CAUSE: 0x0400 */
++#define AR531X_IRQ_WLAN0_INTRS MIPS_CPU_IRQ_BASE+3 /* C0_CAUSE: 0x0800 */
++#define AR531X_IRQ_ENET0_INTRS MIPS_CPU_IRQ_BASE+4 /* C0_CAUSE: 0x1000 */
++#define AR531X_IRQ_LCBUS_PCI MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
++#define AR531X_IRQ_WLAN0_POLL MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
++#define AR531X_IRQ_CPU_CLOCK MIPS_CPU_IRQ_BASE+7 /* C0_CAUSE: 0x8000 */
++#else
++#define AR531X_IRQ_NONE MIPS_CPU_IRQ_BASE+0
++#define AR531X_IRQ_WLAN0_INTRS MIPS_CPU_IRQ_BASE+2 /* C0_CAUSE: 0x0400 */
++#define AR531X_IRQ_ENET0_INTRS MIPS_CPU_IRQ_BASE+3 /* C0_CAUSE: 0x0800 */
++#define AR531X_IRQ_ENET1_INTRS MIPS_CPU_IRQ_BASE+4 /* C0_CAUSE: 0x1000 */
++#define AR531X_IRQ_WLAN1_INTRS MIPS_CPU_IRQ_BASE+5 /* C0_CAUSE: 0x2000 */
++#define AR531X_IRQ_MISC_INTRS MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
++#define AR531X_IRQ_CPU_CLOCK MIPS_CPU_IRQ_BASE+7 /* C0_CAUSE: 0x8000 */
++#endif
++
++/* Miscellaneous interrupts, which share IP6 or IP2 */
++#define AR531X_MISC_IRQ_NONE AR531X_MISC_IRQ_BASE+0
++#define AR531X_MISC_IRQ_TIMER AR531X_MISC_IRQ_BASE+1
++#define AR531X_MISC_IRQ_AHB_PROC AR531X_MISC_IRQ_BASE+2
++#define AR531X_MISC_IRQ_AHB_DMA AR531X_MISC_IRQ_BASE+3
++#define AR531X_MISC_IRQ_GPIO AR531X_MISC_IRQ_BASE+4
++#define AR531X_MISC_IRQ_UART0 AR531X_MISC_IRQ_BASE+5
++#define AR531X_MISC_IRQ_UART0_DMA AR531X_MISC_IRQ_BASE+6
++#define AR531X_MISC_IRQ_WATCHDOG AR531X_MISC_IRQ_BASE+7
++#define AR531X_MISC_IRQ_LOCAL AR531X_MISC_IRQ_BASE+8
++#define AR531X_MISC_IRQ_COUNT 9
++
++/* GPIO Interrupts [0..7], share AR531X_MISC_IRQ_GPIO */
++#define AR531X_GPIO_IRQ_NONE AR531X_MISC_IRQ_BASE+0
++#define AR531X_GPIO_IRQ(n) AR531X_MISC_IRQ_BASE+(n)+1
++#define AR531X_GPIO_IRQ_COUNT 9
++
++#define PHYS_TO_K1(physaddr) KSEG1ADDR(physaddr)
++#define PHYS_TO_K0(physaddr) KSEG0ADDR(physaddr)
++#define UNMAPPED_TO_PHYS(vaddr) PHYSADDR(vaddr)
++#define IS_UNMAPPED_VADDR(vaddr) \
++ ((KSEGX(vaddr) == KSEG0) || (KSEGX(vaddr) == KSEG1))
++
++/* IOCTL commands for /proc/ar531x */
++#define AR531X_CTRL_DO_BREAKPOINT 1
++#define AR531X_CTRL_DO_MADWIFI 2
++
++/*
++ * Definitions for operating system portability.
++ * These are vxWorks-->Linux translations.
++ */
++#define LOCAL static
++#define BOOL int
++#define TRUE 1
++#define FALSE 0
++#define UINT8 u8
++#define UINT16 u16
++#define UINT32 u32
++#define PRINTF printk
++#if /* DEBUG */ 1
++#define DEBUG_PRINTF printk
++#define printf printk
++#define INLINE
++#else
++DEBUG_PRINTF while (0) printk
++#define INLINE inline
++#endif
++#define sysUDelay(usecs) udelay(usecs)
++#define sysMsDelay(msecs) mdelay(msecs)
++typedef volatile UINT8 *VIRT_ADDR;
++#define MALLOC(sz) kmalloc(sz, GFP_KERNEL)
++#define MALLOC_NOSLEEP(sz) kmalloc(sz, GFP_ATOMIC)
++#define FREE(ptr) kfree((void *)ptr)
++#define BSP_BUG() do { printk("kernel BSP BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0=0; } while (0)
++#define BSP_BUG_ON(condition) do { if (unlikely((condition)!=0)) BSP_BUG(); } while(0)
++#define ASSERT(x) BSP_BUG_ON(!(x))
++
++extern struct ar531x_boarddata *ar531x_board_configuration;
++extern char *ar531x_radio_configuration;
++extern char *enet_mac_address_get(int MACUnit);
++
++extern void kgdbInit(void);
++extern int kgdbEnabled(void);
++extern void breakpoint(void);
++extern int kgdbInterrupt(void);
++extern unsigned int ar531x_cpu_frequency(void);
++extern unsigned int ar531x_sys_frequency(void);
++
++/* GPIO support */
++extern struct irqaction spurious_gpio;
++extern unsigned int gpioIntMask;
++extern void ar531x_gpio_intr_init(int irq_base);
++extern void ar531x_gpio_ctrl_output(int gpio);
++extern void ar531x_gpio_ctrl_input(int gpio);
++extern void ar531x_gpio_set(int gpio, int val);
++extern int ar531x_gpio_get(int gpio);
++extern void ar531x_gpio_intr_enable(unsigned int irq);
++extern void ar531x_gpio_intr_disable(unsigned int irq);
++
++/* Watchdog Timer support */
++extern int watchdog_start(unsigned int milliseconds);
++extern int watchdog_stop(void);
++extern int watchdog_is_enabled(void);
++extern unsigned int watchdog_min_timer_reached(void);
++extern void watchdog_notify_alive(void);
++
++#define A_DATA_CACHE_INVAL(start, length) \
++ dma_cache_inv((UINT32)(start),(length))
++
++#define sysWbFlush() mb()
++
++#define intDisable(x) cli()
++#define intEnable(x) sti()
++
++#endif /* __AR531XLNX_H */
+diff -urN linux-mips-orig/drivers/net/ath/ipPhy.c linux-mips-new/drivers/net/ath/ipPhy.c
+--- linux-mips-orig/drivers/net/ath/ipPhy.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ipPhy.c 2005-12-31 12:33:57.677538216 +0000
+@@ -0,0 +1,833 @@
++/*
++ * 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 ICPLUS ethernet PHY.
++ *
++ * All definitions in this file are operating system independent!
++ */
++
++#if defined(linux)
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++
++#include "ar531xlnx.h"
++#endif
++
++#include "ae531xmac.h"
++#include "ae531xreg.h"
++#include "ipPhy.h"
++
++/* 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
++
++#if DRV_DEBUG
++#define DRV_DEBUG_PHYERROR 0x00000001
++#define DRV_DEBUG_PHYCHANGE 0x00000002
++#define DRV_DEBUG_PHYSETUP 0x00000004
++
++int ipPhyDebug = DRV_DEBUG_PHYERROR;
++
++#define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) \
++{ \
++ if (ipPhyDebug & (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 (ipPhyDebug & (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 IP_LAN_PORT_VLAN 1
++#define IP_WAN_PORT_VLAN 2
++
++#define ENET_UNIT_DEFAULT 0
++
++/*
++ * 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 phyBase;
++ UINT32 phyAddr; /* PHY registers associated with this phy port */
++ UINT32 VLANTableSetting; /* Value to be written to VLAN table */
++} ipPhyInfo_t;
++
++/*
++ * Per-PHY information, indexed by PHY unit number.
++ */
++ipPhyInfo_t ipPhyInfo[] = {
++ /*
++ * On AP30/AR5312, all PHYs are associated with MAC0.
++ * AP30/AR5312's MAC1 isn't used for anything.
++ * CONFIG_VENETDEV==1 (router) configuration:
++ * Ports 0,1,2, and 3 are "LAN ports"
++ * Port 4 is a WAN port
++ * Port 5 connects to MAC0 in the AR5312
++ * CONFIG_VENETDEV==0 (bridge) configuration:
++ * Ports 0,1,2,3,4 are "LAN ports"
++ * Port 5 connects to the MAC0 in the AR5312
++ */
++ {TRUE, /* phy port 0 -- LAN port 0 */
++ FALSE,
++ ENET_UNIT_DEFAULT,
++ (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
++ IP_PHY0_ADDR,
++ IP_LAN_PORT_VLAN
++ },
++
++ {TRUE, /* phy port 1 -- LAN port 1 */
++ FALSE,
++ ENET_UNIT_DEFAULT,
++ (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
++ IP_PHY1_ADDR,
++ IP_LAN_PORT_VLAN
++ },
++
++ {TRUE, /* phy port 2 -- LAN port 2 */
++ FALSE,
++ ENET_UNIT_DEFAULT,
++ (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
++ IP_PHY2_ADDR,
++ IP_LAN_PORT_VLAN
++ },
++
++ {TRUE, /* phy port 3 -- LAN port 3 */
++ FALSE,
++ ENET_UNIT_DEFAULT,
++ (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
++ IP_PHY3_ADDR,
++ IP_LAN_PORT_VLAN
++ },
++
++ {TRUE, /* phy port 4 -- WAN port or LAN port 4 */
++ FALSE,
++ ENET_UNIT_DEFAULT,
++ (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
++ IP_PHY4_ADDR,
++ IP_LAN_PORT_VLAN /* Send to all ports */
++ },
++
++ {FALSE, /* phy port 5 -- CPU port (no RJ45 connector) */
++ TRUE,
++ ENET_UNIT_DEFAULT,
++ (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
++ 0x00,
++ IP_LAN_PORT_VLAN /* Send to all ports */
++ },
++};
++
++#define IP_GLOBALREGBASE ((UINT32) (PHYS_TO_K1(AR531X_ENET0)))
++
++#define IP_PHY_MAX (sizeof(ipPhyInfo) / sizeof(ipPhyInfo[0]))
++
++/* Range of valid PHY IDs is [MIN..MAX] */
++#define IP_ID_MIN 0
++#define IP_ID_MAX (IP_PHY_MAX-1)
++
++/* Convenience macros to access myPhyInfo */
++#define IP_IS_ENET_PORT(phyUnit) (ipPhyInfo[phyUnit].isEnetPort)
++#define IP_IS_PHY_ALIVE(phyUnit) (ipPhyInfo[phyUnit].isPhyAlive)
++#define IP_ETHUNIT(phyUnit) (ipPhyInfo[phyUnit].ethUnit)
++#define IP_PHYBASE(phyUnit) (ipPhyInfo[phyUnit].phyBase)
++#define IP_PHYADDR(phyUnit) (ipPhyInfo[phyUnit].phyAddr)
++#define IP_VLAN_TABLE_SETTING(phyUnit) (ipPhyInfo[phyUnit].VLANTableSetting)
++
++
++#define IP_IS_ETHUNIT(phyUnit, ethUnit) \
++ (IP_IS_ENET_PORT(phyUnit) && \
++ IP_ETHUNIT(phyUnit) == (ethUnit))
++
++/* Forward references */
++BOOL ip_phyIsLinkAlive(int phyUnit);
++LOCAL void ip_VLANInit(int ethUnit);
++LOCAL void ip_verifyReady(int ethUnit);
++#if DEBUG
++void ip_phyShow(int phyUnit);
++void ip_phySet(int phyUnit, UINT32 regnum, UINT32 value);
++void ip_globalSet(UINT32 phyAddr, UINT32 regnum, UINT32 value);
++#endif
++
++/******************************************************************************
++*
++* ip_phyIsLinkAlive - test to see if the specified link is alive
++*
++* RETURNS:
++* TRUE --> link is alive
++* FALSE --> link is down
++*/
++BOOL
++ip_phyIsLinkAlive(int phyUnit)
++{
++ UINT16 phyHwStatus;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, IP_PHY_STATUS);
++
++ if (phyHwStatus & IP_STATUS_LINK_PASS) {
++ return TRUE;
++ } else {
++ return FALSE;
++ }
++}
++
++/******************************************************************************
++*
++* ip_VLANInit - initialize "port-based VLANs" for the specified enet unit.
++*/
++LOCAL void
++ip_VLANInit(int ethUnit)
++{
++ int phyUnit;
++ UINT32 phyBase;
++ UINT32 phyReg;
++
++ phyBase = IP_GLOBALREGBASE;
++
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (IP_ETHUNIT(phyUnit) != ethUnit) {
++ continue;
++ }
++ phyRegWrite(phyBase, IP_GLOBAL_PHY29_ADDR,
++ IP_GLOBAL_PHY29_24_REG + ((phyUnit == 5) ? (phyUnit + 1) : phyUnit),
++ IP_VLAN_TABLE_SETTING(phyUnit));
++
++ /* Send all packets to all ports */
++ phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG);
++ phyReg = phyReg | ((1 << phyUnit) << IP_VLAN1_OUTPUT_PORT_MASK_S);
++ phyRegWrite(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG, phyReg);
++ }
++ phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_9_REG);
++ phyReg = phyReg | TAG_VLAN_ENABLE;
++ phyReg = phyReg & ~VID_INDX_SEL_M;
++ phyRegWrite(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_9_REG, phyReg);
++
++}
++
++
++LOCAL void
++ip_verifyReady(int ethUnit)
++{
++ int phyUnit;
++ UINT32 phyBase = 0;
++ UINT32 phyAddr;
++ UINT16 phyID1;
++ UINT16 phyID2;
++
++ /*
++ * The first read to the Phy port registers always fails and
++ * returns 0. So get things started with a bogus read.
++ */
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyID1 = phyRegRead(phyBase, phyAddr, IP_PHY_ID1); /* returns 0 */
++ break;
++ }
++
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ /*******************/
++ /* Verify phy port */
++ /*******************/
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyID1 = phyRegRead(phyBase, phyAddr, IP_PHY_ID1);
++ if (phyID1 != IP_PHY_ID1_EXPECTATION) {
++ DRV_PRINT(DRV_DEBUG_PHYERROR,
++ ("Invalid PHY ID1 for enet%d port%d. Expected 0x%04x, read 0x%04x\n",
++ ethUnit,
++ phyUnit,
++ IP_PHY_ID1_EXPECTATION,
++ phyID1));
++ return;
++ }
++
++ phyID2 = phyRegRead(phyBase, phyAddr, IP_PHY_ID2);
++ if ((phyID2 & IP_OUI_LSB_MASK) != IP_OUI_LSB_EXPECTATION) {
++ DRV_PRINT(DRV_DEBUG_PHYERROR,
++ ("Invalid PHY ID2 for enet%d port %d. Expected 0x%04x, read 0x%04x\n",
++ ethUnit,
++ phyUnit,
++ IP_OUI_LSB_EXPECTATION,
++ phyID2));
++ return;
++ }
++
++ DRV_PRINT(DRV_DEBUG_PHYSETUP,
++ ("Found PHY enet%d port%d: model 0x%x revision 0x%x\n",
++ ethUnit,
++ phyUnit,
++ (phyID2 & IP_MODEL_NUM_MASK) >> IP_MODEL_NUM_SHIFT,
++ (phyID2 & IP_REV_NUM_MASK) >> IP_REV_NUM_SHIFT));
++
++ }
++}
++
++
++/******************************************************************************
++*
++* ip_phySetup - 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
++ip_phySetup(int ethUnit, UINT32 _phyBase)
++{
++ int phyUnit;
++ UINT16 phyHwStatus;
++ UINT16 timeout;
++ int liveLinks = 0;
++ UINT32 phyBase = 0;
++ BOOL foundPhy = FALSE;
++ UINT32 phyAddr;
++
++ /* Reset PHYs*/
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyRegWrite(phyBase, phyAddr, IP_PHY_CONTROL,
++ IP_CTRL_SOFTWARE_RESET);
++ }
++ /*
++ * After the phy is reset, it takes a little while before
++ * it can respond properly.
++ */
++ sysMsDelay(300);
++ /* Verify that the switch is what we think it is, and that it's ready */
++ ip_verifyReady(ethUnit);
++
++ /* See if there's any configuration data for this enet */
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (IP_ETHUNIT(phyUnit) != ethUnit) {
++ continue;
++ }
++
++ phyBase = IP_PHYBASE(phyUnit);
++ foundPhy = TRUE;
++ break;
++ }
++
++ if (!foundPhy) {
++ return FALSE; /* No PHY's configured for this ethUnit */
++ }
++
++#ifdef COBRA_TODO
++ /* Initialize global switch settings */
++
++ /* Initialize the aging time */
++
++ /* Set the learning properties */
++#endif
++
++ /* start auto negogiation on each phy */
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyRegWrite(phyBase, phyAddr, IP_AUTONEG_ADVERT,
++ IP_ADVERTISE_ALL);
++ phyRegWrite(phyBase, phyAddr, IP_PHY_CONTROL,
++ IP_CTRL_AUTONEGOTIATION_ENABLE | IP_CTRL_START_AUTONEGOTIATION);
++ }
++
++ /*
++ * 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.
++ */
++ timeout=5;
++ for (phyUnit=0; (phyUnit < IP_PHY_MAX) /*&& (timeout > 0) */; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++ for (;;) {
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, IP_PHY_STATUS);
++
++ if (IP_AUTONEG_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 < IP_PHY_MAX; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ if (ip_phyIsLinkAlive(phyUnit)) {
++ liveLinks++;
++ IP_IS_PHY_ALIVE(phyUnit) = TRUE;
++ } else {
++ IP_IS_PHY_ALIVE(phyUnit) = FALSE;
++ }
++
++ DRV_PRINT(DRV_DEBUG_PHYSETUP,
++ ("eth%d: Phy Status=%4.4x\n",
++ ethUnit,
++ phyRegRead(IP_PHYBASE(phyUnit),
++ IP_PHYADDR(phyUnit),
++ IP_PHY_STATUS)));
++ }
++#if 0
++ /* XXX Divy. Disable WAN/LAN seggregation. See bug 17866 */
++ ip_VLANInit(ethUnit);
++#endif
++ return (liveLinks > 0);
++}
++
++/******************************************************************************
++*
++* ip_phyIsDuplexFull - Determines whether the phy ports associated with the
++* specified device are FULL or HALF duplex.
++*
++* RETURNS:
++* 1 --> FULL
++* 0 --> HALF
++*/
++int
++ip_phyIsFullDuplex(int ethUnit)
++{
++ int phyUnit;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++ UINT16 phyHwStatus;
++
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ if (ip_phyIsLinkAlive(phyUnit)) {
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, IP_LINK_PARTNER_ABILITY);
++ printk("ipPhy.c: phyHwStatus 0x%x\n",phyHwStatus);
++ if ((phyHwStatus & IP_LINK_100BASETX_FULL_DUPLEX) ||
++ (phyHwStatus & IP_LINK_10BASETX_FULL_DUPLEX)) {
++ return TRUE;
++ }
++ }
++ return -1;
++ }
++
++ return FALSE;
++
++}
++
++
++/******************************************************************************
++*
++* ip_phyIsSpeed100 - Determines the speed of phy ports associated with the
++* specified device.
++*
++* RETURNS:
++* TRUE --> 100Mbit
++* FALSE --> 10Mbit
++*/
++
++BOOL
++ip_phyIsSpeed100(int ethUnit)
++{
++ int phyUnit;
++ UINT16 phyHwStatus;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ if (ip_phyIsLinkAlive(phyUnit)) {
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, IP_LINK_PARTNER_ABILITY);
++
++ if (phyHwStatus & IP_LINK_100BASETX) {
++ return TRUE;
++ }
++ }
++ }
++
++ return FALSE;
++}
++
++/*****************************************************************************
++*
++* ip_phyCheckStatusChange -- 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.
++*/
++
++void
++ip_phyCheckStatusChange(int ethUnit)
++{
++
++ int phyUnit;
++ UINT16 phyHwStatus;
++ ipPhyInfo_t *lastStatus;
++ int linkCount = 0;
++ int lostLinks = 0;
++ int gainedLinks = 0;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ lastStatus = &ipPhyInfo[phyUnit];
++ phyHwStatus = phyRegRead(phyBase, phyAddr, IP_PHY_STATUS);
++
++ if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */
++ /* See if we've lost link */
++ if (phyHwStatus & IP_STATUS_LINK_PASS) {
++ linkCount++;
++ } else {
++ lostLinks++;
++#ifdef COBRA_TODO
++ mv_flushATUDB(phyUnit);
++#endif
++ 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 AutoNegotiation complete */
++ if (IP_AUTONEG_DONE(phyHwStatus)) {
++ gainedLinks++;
++ linkCount++;
++ DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d up\n",
++ ethUnit, phyUnit));
++ lastStatus->isPhyAlive = TRUE;
++ }
++ }
++ }
++
++ 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);
++ }
++ }
++
++}
++
++#if DEBUG
++
++/* Define the registers of interest for a phyShow command */
++typedef struct ipRegisterTableEntry_s {
++ UINT32 regNum;
++ char *regIdString;
++} ipRegisterTableEntry_t;
++
++ipRegisterTableEntry_t ipPhyRegisterTable[] = {
++ {IP_PHY_CONTROL, "PHY Control "},
++ {IP_PHY_STATUS, "PHY Status "},
++ {IP_PHY_ID1, "PHY Identifier 1 "},
++ {IP_PHY_ID2, "PHY Identifier 2 "},
++ {IP_AUTONEG_ADVERT, "Auto-Negotiation Advertisement "},
++ {IP_LINK_PARTNER_ABILITY, "Link Partner Ability "},
++ {IP_AUTONEG_EXPANSION, "Auto-Negotiation Expansion "},
++};
++int ipPhyNumRegs = sizeof(ipPhyRegisterTable) / sizeof(ipPhyRegisterTable[0]);
++
++
++ipRegisterTableEntry_t ipPhy29GlobalRegisterTable[] = {
++ {IP_GLOBAL_PHY29_18_REG, "29_18_REG "},
++ {IP_GLOBAL_PHY29_19_REG, "29_19_REG "},
++ {IP_GLOBAL_PHY29_20_REG, "29_20_REG "},
++ {IP_GLOBAL_PHY29_21_REG, "29_21_REG "},
++ {IP_GLOBAL_PHY29_22_REG, "29_22_REG "},
++ {IP_GLOBAL_PHY29_23_REG, "29_23_REG "},
++ {IP_GLOBAL_PHY29_24_REG, "29_24_REG "},
++ {IP_GLOBAL_PHY29_25_REG, "29_25_REG "},
++ {IP_GLOBAL_PHY29_26_REG, "29_26_REG "},
++ {IP_GLOBAL_PHY29_27_REG, "29_27_REG "},
++ {IP_GLOBAL_PHY29_28_REG, "29_28_REG "},
++ {IP_GLOBAL_PHY29_29_REG, "29_29_REG "},
++ {IP_GLOBAL_PHY29_30_REG, "29_30_REG "},
++ {IP_GLOBAL_PHY29_31_REG, "29_31_REG "},
++};
++int ipPhy29GlobalNumRegs =
++ sizeof(ipPhy29GlobalRegisterTable) / sizeof(ipPhy29GlobalRegisterTable[0]);
++
++
++ipRegisterTableEntry_t ipPhy30GlobalRegisterTable[] = {
++ {IP_GLOBAL_PHY30_0_REG, "30_0_REG "},
++ {IP_GLOBAL_PHY30_1_REG, "30_1_REG "},
++ {IP_GLOBAL_PHY30_2_REG, "30_2_REG "},
++ {IP_GLOBAL_PHY30_3_REG, "30_3_REG "},
++ {IP_GLOBAL_PHY30_4_REG, "30_4_REG "},
++ {IP_GLOBAL_PHY30_5_REG, "30_5_REG "},
++ {IP_GLOBAL_PHY30_6_REG, "30_6_REG "},
++ {IP_GLOBAL_PHY30_7_REG, "30_7_REG "},
++ {IP_GLOBAL_PHY30_8_REG, "30_8_REG "},
++ {IP_GLOBAL_PHY30_9_REG, "30_9_REG "},
++ {IP_GLOBAL_PHY30_10_REG, "30_10_REG "},
++ {IP_GLOBAL_PHY30_11_REG, "30_11_REG "},
++ {IP_GLOBAL_PHY30_12_REG, "30_12_REG "},
++ {IP_GLOBAL_PHY30_13_REG, "30_13_REG "},
++ {IP_GLOBAL_PHY30_16_REG, "30_16_REG "},
++ {IP_GLOBAL_PHY30_17_REG, "30_17_REG "},
++ {IP_GLOBAL_PHY30_18_REG, "30_18_REG "},
++ {IP_GLOBAL_PHY30_20_REG, "30_20_REG "},
++ {IP_GLOBAL_PHY30_21_REG, "30_21_REG "},
++ {IP_GLOBAL_PHY30_22_REG, "30_22_REG "},
++ {IP_GLOBAL_PHY30_23_REG, "30_23_REG "},
++ {IP_GLOBAL_PHY30_24_REG, "30_24_REG "},
++ {IP_GLOBAL_PHY30_25_REG, "30_25_REG "},
++ {IP_GLOBAL_PHY30_26_REG, "30_26_REG "},
++ {IP_GLOBAL_PHY30_27_REG, "30_27_REG "},
++ {IP_GLOBAL_PHY30_28_REG, "30_28_REG "},
++ {IP_GLOBAL_PHY30_29_REG, "30_29_REG "},
++ {IP_GLOBAL_PHY30_30_REG, "30_30_REG "},
++ {IP_GLOBAL_PHY30_31_REG, "30_31_REG "},
++};
++int ipPhy30GlobalNumRegs =
++ sizeof(ipPhy30GlobalRegisterTable) / sizeof(ipPhy30GlobalRegisterTable[0]);
++
++ipRegisterTableEntry_t ipPhy31GlobalRegisterTable[] = {
++ {IP_GLOBAL_PHY31_0_REG, "31_0_REG "},
++ {IP_GLOBAL_PHY31_1_REG, "31_1_REG "},
++ {IP_GLOBAL_PHY31_2_REG, "31_2_REG "},
++ {IP_GLOBAL_PHY31_3_REG, "31_3_REG "},
++ {IP_GLOBAL_PHY31_4_REG, "31_4_REG "},
++ {IP_GLOBAL_PHY31_5_REG, "31_5_REG "},
++ {IP_GLOBAL_PHY31_6_REG, "31_6_REG "},
++};
++
++int ipPhy31GlobalNumRegs =
++ sizeof(ipPhy31GlobalRegisterTable) / sizeof(ipPhy31GlobalRegisterTable[0]);
++
++
++/*****************************************************************************
++*
++* ip_phyShow - Dump the state of a PHY.
++* There are two sets of registers for each phy port:
++* "phy registers" and
++* "switch port registers"
++* We dump 'em all, plus the switch global registers.
++*/
++void
++ip_phyShow(int phyUnit)
++{
++ int i;
++ UINT16 value;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ if (!ip_validPhyId(phyUnit)) {
++ return;
++ }
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ printf("PHY state for PHY%d (enet%d, phyBase 0x%8x, phyAddr 0x%x)\n",
++ phyUnit,
++ IP_ETHUNIT(phyUnit),
++ IP_PHYBASE(phyUnit),
++ IP_PHYADDR(phyUnit));
++
++ printf("PHY Registers:\n");
++ for (i=0; i < ipPhyNumRegs; i++) {
++
++ value = phyRegRead(phyBase, phyAddr, ipPhyRegisterTable[i].regNum);
++
++ printf("Reg %02d (0x%02x) %s = 0x%08x\n",
++ ipPhyRegisterTable[i].regNum,
++ ipPhyRegisterTable[i].regNum,
++ ipPhyRegisterTable[i].regIdString,
++ value);
++ }
++
++ phyBase = IP_GLOBALREGBASE;
++
++ printf("Switch Global Registers:\n");
++ printf("Phy29 Registers:\n");
++ for (i=0; i < ipPhy29GlobalNumRegs; i++) {
++
++ value = phyRegRead(phyBase, IP_GLOBAL_PHY29_ADDR,
++ ipPhy29GlobalRegisterTable[i].regNum);
++
++ printf("Reg %02d (0x%02x) %s = 0x%08x\n",
++ ipPhy29GlobalRegisterTable[i].regNum,
++ ipPhy29GlobalRegisterTable[i].regNum,
++ ipPhy29GlobalRegisterTable[i].regIdString,
++ value);
++ }
++
++ printf("Phy30 Registers:\n");
++ for (i=0; i < ipPhy30GlobalNumRegs; i++) {
++
++ value = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR,
++ ipPhy30GlobalRegisterTable[i].regNum);
++
++ printf("Reg %02d (0x%02x) %s = 0x%08x\n",
++ ipPhy30GlobalRegisterTable[i].regNum,
++ ipPhy30GlobalRegisterTable[i].regNum,
++ ipPhy30GlobalRegisterTable[i].regIdString,
++ value);
++ }
++ printf("Phy31 Registers:\n");
++ for (i=0; i < ipPhy31GlobalNumRegs; i++) {
++
++ value = phyRegRead(phyBase, IP_GLOBAL_PHY31_ADDR,
++ ipPhy31GlobalRegisterTable[i].regNum);
++
++ printf("Reg %02d (0x%02x) %s = 0x%08x\n",
++ ipPhy31GlobalRegisterTable[i].regNum,
++ ipPhy31GlobalRegisterTable[i].regNum,
++ ipPhy31GlobalRegisterTable[i].regIdString,
++ value);
++ }
++}
++
++/*****************************************************************************
++*
++* ip_phySet - Modify the value of a PHY register (debug only).
++*/
++void
++ip_phySet(int phyUnit, UINT32 regnum, UINT32 value)
++{
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ if (ip_validPhyId(phyUnit)) {
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyRegWrite(phyBase, phyAddr, regnum, value);
++ }
++}
++
++/*****************************************************************************
++*
++* ip_globalSet - Modify the value of a global register
++* (debug only).
++*/
++void
++ip_globalSet(UINT32 phyAddr, UINT32 regnum, UINT32 value)
++{
++ UINT32 phyBase;
++
++ phyBase = IP_GLOBALREGBASE;
++
++ phyRegWrite(phyBase, phyAddr, regnum, value);
++}
++
++
++#endif
+diff -urN linux-mips-orig/drivers/net/ath/ipPhy.h linux-mips-new/drivers/net/ath/ipPhy.h
+--- linux-mips-orig/drivers/net/ath/ipPhy.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ipPhy.h 2005-12-31 12:33:57.678538064 +0000
+@@ -0,0 +1,172 @@
++/*
++ * 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.
++ */
++
++/*
++ * icPhy.h - definitions for the ethernet PHY.
++ * This code supports a simple 1-port ethernet phy, ICPLUS,
++ * All definitions in this file are operating system independent!
++ */
++
++#ifndef IPPHY_H
++#define IPPHY_H
++
++/*****************/
++/* PHY Registers */
++/*****************/
++#define IP_PHY_CONTROL 0
++#define IP_PHY_STATUS 1
++#define IP_PHY_ID1 2
++#define IP_PHY_ID2 3
++#define IP_AUTONEG_ADVERT 4
++#define IP_LINK_PARTNER_ABILITY 5
++#define IP_AUTONEG_EXPANSION 6
++
++
++/* IP_PHY_CONTROL fields */
++#define IP_CTRL_SOFTWARE_RESET 0x8000
++#define IP_CTRL_SPEED_100 0x2000
++#define IP_CTRL_AUTONEGOTIATION_ENABLE 0x1000
++#define IP_CTRL_START_AUTONEGOTIATION 0x0200
++#define IP_CTRL_SPEED_FULL_DUPLEX 0x0100
++
++/* Phy status fields */
++#define IP_STATUS_AUTO_NEG_DONE 0x0020
++#define IP_STATUS_LINK_PASS 0x0004
++
++#define IP_AUTONEG_DONE(ip_phy_status) \
++ (((ip_phy_status) & \
++ (IP_STATUS_AUTO_NEG_DONE)) == \
++ (IP_STATUS_AUTO_NEG_DONE))
++
++/* ICPLUS_PHY_ID1 fields */
++#define IP_PHY_ID1_EXPECTATION 0x0243 /* OUI >> 6 */
++
++/* ICPLUS_PHY_ID2 fields */
++#define IP_OUI_LSB_MASK 0xfc00
++#define IP_OUI_LSB_EXPECTATION 0x0c00
++#define IP_OUI_LSB_SHIFT 10
++#define IP_MODEL_NUM_MASK 0x03f0
++#define IP_MODEL_NUM_SHIFT 4
++#define IP_REV_NUM_MASK 0x000f
++#define IP_REV_NUM_SHIFT 0
++
++/* Link Partner ability */
++#define IP_LINK_100BASETX_FULL_DUPLEX 0x0100
++#define IP_LINK_100BASETX 0x0080
++#define IP_LINK_10BASETX_FULL_DUPLEX 0x0040
++#define IP_LINK_10BASETX 0x0020
++
++/* Advertisement register. */
++#define IP_ADVERTISE_100FULL 0x0100
++#define IP_ADVERTISE_100HALF 0x0080
++#define IP_ADVERTISE_10FULL 0x0040
++#define IP_ADVERTISE_10HALF 0x0020
++
++#define IP_ADVERTISE_ALL (IP_ADVERTISE_10HALF | IP_ADVERTISE_10FULL | \
++ IP_ADVERTISE_100HALF | IP_ADVERTISE_100FULL)
++
++
++#define IP_VLAN_TAG_VALID 0x81
++#define IP_VLAN_TAG_SIZE 4
++#define IP_VLAN_TAG_OFFSET 12 /* After DA & SA */
++#define IP_SPECIAL_TAG_VALID 0x81
++
++/****************************/
++/* Global Control Registers */
++/****************************/
++/* IP Global register doesn't have names based on functionality
++ * hence has to live with this names for now */
++#define IP_GLOBAL_PHY29_18_REG 18
++#define IP_GLOBAL_PHY29_19_REG 19
++#define IP_GLOBAL_PHY29_20_REG 20
++#define IP_GLOBAL_PHY29_21_REG 21
++#define IP_GLOBAL_PHY29_22_REG 22
++#define IP_GLOBAL_PHY29_23_REG 23
++#define IP_GLOBAL_PHY29_24_REG 24
++#define IP_GLOBAL_PHY29_25_REG 25
++#define IP_GLOBAL_PHY29_26_REG 26
++#define IP_GLOBAL_PHY29_27_REG 27
++#define IP_GLOBAL_PHY29_28_REG 28
++#define IP_GLOBAL_PHY29_29_REG 29
++#define IP_GLOBAL_PHY29_30_REG 30
++#define IP_GLOBAL_PHY29_31_REG 31
++
++
++#define IP_GLOBAL_PHY30_0_REG 0
++#define IP_GLOBAL_PHY30_1_REG 1
++#define IP_GLOBAL_PHY30_2_REG 2
++#define IP_GLOBAL_PHY30_3_REG 3
++#define IP_GLOBAL_PHY30_4_REG 4
++#define IP_GLOBAL_PHY30_5_REG 5
++#define IP_GLOBAL_PHY30_6_REG 6
++#define IP_GLOBAL_PHY30_7_REG 7
++#define IP_GLOBAL_PHY30_8_REG 8
++#define IP_GLOBAL_PHY30_9_REG 9
++#define IP_GLOBAL_PHY30_10_REG 10
++#define IP_GLOBAL_PHY30_11_REG 11
++#define IP_GLOBAL_PHY30_12_REG 12
++#define IP_GLOBAL_PHY30_13_REG 13
++#define IP_GLOBAL_PHY30_16_REG 16
++#define IP_GLOBAL_PHY30_17_REG 17
++#define IP_GLOBAL_PHY30_18_REG 18
++#define IP_GLOBAL_PHY30_20_REG 20
++#define IP_GLOBAL_PHY30_21_REG 21
++#define IP_GLOBAL_PHY30_22_REG 22
++#define IP_GLOBAL_PHY30_23_REG 23
++#define IP_GLOBAL_PHY30_24_REG 24
++#define IP_GLOBAL_PHY30_25_REG 25
++#define IP_GLOBAL_PHY30_26_REG 26
++#define IP_GLOBAL_PHY30_27_REG 27
++#define IP_GLOBAL_PHY30_28_REG 28
++#define IP_GLOBAL_PHY30_29_REG 29
++#define IP_GLOBAL_PHY30_30_REG 30
++#define IP_GLOBAL_PHY30_31_REG 31
++
++#define IP_GLOBAL_PHY31_0_REG 0
++#define IP_GLOBAL_PHY31_1_REG 1
++#define IP_GLOBAL_PHY31_2_REG 2
++#define IP_GLOBAL_PHY31_3_REG 3
++#define IP_GLOBAL_PHY31_4_REG 4
++#define IP_GLOBAL_PHY31_5_REG 5
++#define IP_GLOBAL_PHY31_6_REG 6
++
++#define IP_GLOBAL_PHY29_31_REG 31
++
++
++#define IP_VLAN0_OUTPUT_PORT_MASK_S 0
++#define IP_VLAN1_OUTPUT_PORT_MASK_S 8
++#define IP_VLAN2_OUTPUT_PORT_MASK_S 0
++#define IP_VLAN3_OUTPUT_PORT_MASK_S 8
++
++/* Masks and shifts for 29.23 register */
++#define IP_PORTX_ADD_TAG_S 11
++#define IP_PORTX_REMOVE_TAG_S 6
++#define IP_PORT5_ADD_TAG_S 1
++#define IP_PORT5_REMOVE_TAG_S 0
++
++/*
++ * 30.9 Definitions
++ */
++#define TAG_VLAN_ENABLE 0x0080
++#define VID_INDX_SEL_M 0x0070
++#define VID_INDX_SEL_S 4
++
++
++/* PHY Addresses */
++#define IP_PHY0_ADDR 0
++#define IP_PHY1_ADDR 1
++#define IP_PHY2_ADDR 2
++#define IP_PHY3_ADDR 3
++#define IP_PHY4_ADDR 4
++
++#define IP_GLOBAL_PHY29_ADDR 29
++#define IP_GLOBAL_PHY30_ADDR 30
++#define IP_GLOBAL_PHY31_ADDR 31
++
++
++#endif
+diff -urN linux-mips-orig/drivers/net/ath/kendSwitchPhy.c linux-mips-new/drivers/net/ath/kendSwitchPhy.c
+--- linux-mips-orig/drivers/net/ath/kendSwitchPhy.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/kendSwitchPhy.c 2005-12-31 12:33:57.678538064 +0000
+@@ -0,0 +1,286 @@
++/*
++ * 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 ethernet PHY.
++ * This code supports a simple 1-port ethernet phy, Realtek RTL8201BL,
++ * and compatible PHYs, such as the Kendin KS8721B.
++ * All definitions in this file are operating system independent!
++ */
++
++#if defined(linux)
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++
++#include "ar531xlnx.h"
++#endif
++
++#if defined(__ECOS)
++#include "ae531xecos.h"
++#endif
++
++
++#include "ae531xmac.h"
++#include "ae531xreg.h"
++#include "rtPhy.h"
++
++#define RT_MAX_PORTS 5 /* max addressable ports per MIIM */
++
++#if /* DEBUG */ 1
++#define RT_DEBUG_ERROR 0x00000001
++#define RT_DEBUG_PHYSETUP 0x00000002
++#define RT_DEBUG_PHYCHANGE 0x00000004
++
++/* XXX: must hardcode this since same MIIM for all ethUnits */
++const UINT32 phyBase = 0xb8100000;
++
++int rtPhyDebug = RT_DEBUG_ERROR;
++
++#define RT_PRINT(FLG, X) \
++{ \
++ if (rtPhyDebug & (FLG)) { \
++ DEBUG_PRINTF X; \
++ } \
++}
++#else
++#define RT_PRINT(FLG, X)
++#endif
++
++/*
++ * Track per-PHY state.
++ */
++static BOOL rtPhyAlive[RT_MAX_PORTS];
++
++
++/******************************************************************************
++*
++* rt_phySetup - 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
++rt_phySetup(int ethUnit, UINT32 phyBaseIgnored)
++{
++ BOOL linkAlive = FALSE;
++
++ /* Reset phy */
++ if (ethUnit == 0) {
++ int i;
++ for (i=1; i<5; i++) {
++ phyRegWrite(phyBase, i, GEN_ctl, AUTONEGENA);
++ sysMsDelay(200);
++ if (phyRegRead(phyBase, i, GEN_sts) & (AUTOCMPLT | LINK)) {
++ rtPhyAlive[i] = TRUE;
++ }
++ else {
++ rtPhyAlive[i] = FALSE;
++ }
++ }
++ }
++ else {
++ phyRegWrite(phyBase, 5, GEN_ctl, AUTONEGENA);
++ sysMsDelay(200);
++ if (phyRegRead(phyBase, 5, GEN_sts) & (AUTOCMPLT | LINK)) {
++ rtPhyAlive[5] = TRUE;
++ }
++ else {
++ rtPhyAlive[5] = FALSE;
++ }
++ }
++
++ return linkAlive;
++}
++
++/******************************************************************************
++*
++* rt_phyIsDuplexFull - Determines whether the phy ports associated with the
++* specified device are FULL or HALF duplex.
++*
++* RETURNS:
++* 1 --> FULL
++* 0 --> HALF
++*/
++int
++rt_phyIsFullDuplex(int ethUnit)
++{
++ UINT16 phyLpa = 0;
++
++ if (ethUnit == 0) {
++ int i;
++ /* 4 ports connected. If any are half-duplex report half. */
++ for (i=1; i<5; i++) {
++ phyLpa = phyRegRead(phyBase, i, AN_lpa);
++ if ( (!(phyLpa & (LPA_TXFD | LPA_10FD))) &&
++ (phyLpa & (LPA_TX | LPA_10)) ) {
++ return 0;
++ }
++ }
++ return 1;
++ }
++ else {
++ phyLpa = phyRegRead(phyBase, 5, AN_lpa);
++ if (phyLpa & (LPA_TXFD | LPA_10FD) ) {
++ return 1;
++ }
++ else {
++ return 0;
++ }
++ }
++}
++
++/******************************************************************************
++*
++* rt_phyIsSpeed100 - Determines the speed of phy ports associated with the
++* specified device.
++*
++* RETURNS:
++* TRUE --> 100Mbit
++* FALSE --> 10Mbit
++*/
++BOOL
++rt_phyIsSpeed100(int ethUnit)
++{
++ UINT16 phyLpa;
++
++ if (ethUnit == 0) {
++ int i;
++ /* 4 ports connected. If any are not 100 report 10. */
++ for (i=1; i<5; i++) {
++ phyLpa = phyRegRead(phyBase, i, AN_lpa);
++ if ( (!(phyLpa & (LPA_TXFD | LPA_TX))) &&
++ (phyLpa & (LPA_10FD | LPA_10)) ) {
++ printk("10\n");
++ return FALSE;
++ }
++ }
++ printk("100\n");
++ return TRUE;
++ }
++ else {
++ phyLpa = phyRegRead(phyBase, 5, AN_lpa);
++ if (phyLpa & (LPA_TXFD | LPA_TX) ) {
++ printk("100\n");
++ return TRUE;
++ }
++ else {
++ printk("10\n");
++ return FALSE;
++ }
++ }
++}
++
++/*****************************************************************************
++*
++* rt_phyCheckStatusChange -- 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.
++*/
++void
++rt_phyCheckStatusChange(int ethUnit)
++{
++ UINT16 phyHwStatus;
++ int i, loopLower, loopUpper;
++
++ if (ethUnit == 0) {
++ loopLower = 1;
++ loopUpper = 4;
++ }
++ else {
++ loopLower = 5;
++ loopUpper = 5;
++ }
++
++ for (i=loopLower; i<=loopUpper; i++) {
++ phyHwStatus = phyRegRead(phyBase, i, GEN_sts);
++
++ if (rtPhyAlive[i]) { /* last known status was ALIVE */
++ /* See if we've lost link */
++ if (!(phyHwStatus & LINK)) {
++ RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link down\n", ethUnit));
++ rtPhyAlive[i] = FALSE;
++ phyLinkLost(ethUnit);
++ }
++ } else { /* last known status was DEAD */
++ /* Check for AN complete */
++ if ((phyHwStatus & (AUTOCMPLT | LINK)) == (AUTOCMPLT | LINK)) {
++ RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link up\n", ethUnit));
++ rtPhyAlive[i] = TRUE;
++ phyLinkGained(ethUnit);
++ }
++ }
++ }
++}
++
++#if DEBUG
++
++/* Define the PHY registers of interest for a phyShow command */
++struct rtRegisterTable_s {
++ UINT32 regNum;
++ char *regIdString;
++} rtRegisterTable[] =
++{
++ {GEN_ctl, "Basic Mode Control (GEN_ctl) "},
++ {GEN_sts, "Basic Mode Status (GEN_sts) "},
++ {GEN_id_hi, "PHY Identifier 1 (GET_id_hi) "},
++ {GEN_id_lo, "PHY Identifier 2 (GET_id_lo) "},
++ {AN_adv, "Auto-Neg Advertisement (AN_adv) "},
++ {AN_lpa, "Auto-Neg Link Partner Ability "},
++ {AN_exp, "Auto-Neg Expansion "},
++};
++
++int rtNumRegs = sizeof(rtRegisterTable) / sizeof(rtRegisterTable[0]);
++
++/*
++ * Dump the state of a PHY.
++ */
++void
++rt_phyShow(int phyUnit)
++{
++ int i;
++ UINT16 value;
++ int j, loopLower, loopUpper;
++
++ printf("PHY state for ethphy%d\n", phyUnit);
++
++ if (phyUnit == 0) {
++ loopLower = 1;
++ loopUpper = 4;
++ }
++ else {
++ loopLower = 5;
++ loopUpper = 5;
++ }
++
++ for (j=loopLower; j<=loopUpper; j++) {
++ printk("PHY port %d:\n", j);
++ for (i=0; i<rtNumRegs; i++) {
++
++ value = phyRegRead(phyBase, j, rtRegisterTable[i].regNum);
++
++ printf("Reg %02d (0x%02x) %s = 0x%08x\n",
++ rtRegisterTable[i].regNum, rtRegisterTable[i].regNum,
++ rtRegisterTable[i].regIdString, value);
++ }
++ }
++}
++
++#endif
+diff -urN linux-mips-orig/drivers/net/ath/Makefile linux-mips-new/drivers/net/ath/Makefile
+--- linux-mips-orig/drivers/net/ath/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/Makefile 2005-12-31 12:33:57.678538064 +0000
+@@ -0,0 +1,78 @@
++################################################################################
++#
++# 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 © 2004 Atheros Communications, Inc., All Rights Reserved.
++#
++# Makefile for Atheros ar531x ethernet driver
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++################################################################################
++
++#
++# Makefile for the Atheros ar531x ethernet driver
++#
++
++obj= .
++
++obj-m += ae531x.o
++ae531x-objs := ae531xlnx.o ae531xmac.o
++export-objs := ae531xlnx.o
++list-multi := ae531x.o
++
++ifeq ($(CONFIG_KENDIN_ENET_PHY),y)
++ ae531x-objs += rtPhy.o
++endif
++ifeq ($(CONFIG_KENDIN_KS8995XA_ENET_PHY),y)
++ ae531x-objs += kendSwitchPhy.o
++endif
++ifeq ($(CONFIG_MARVELL_ENET_PHY),y)
++ ae531x-objs += mvPhy.o
++endif
++ifeq ($(CONFIG_ICPLUS_ENET_PHY),y)
++ ae531x-objs += ipPhy.o
++endif
++
++#
++# If building directly into kernel
++#
++ifneq ($(MAKING_MODULES),1)
++obj-$(CONFIG_NET_ATHEROS_ETHER) := ae531x.o $(ae531x-objs)
++O_TARGET := ae531x.o
++endif
++
++INCS += -I.
++
++EXTRA_CFLAGS+=$(INCS) ${COPTS} -g
++ifeq ($(DEBUG_BUILD),1)
++EXTRA_CFLAGS+=-DDEBUG
++endif
++
++# release tag versioning
++-include $(KERNELPATH)/ath_version.mk
++
++-include $(TOPDIR)/Rules.make
++STRIP= ${TOOLPREFIX}strip
++
++ifndef MODPATH
++MODPATH = ${KERNELPATH}/arch/mips/ar531x/ROOTDISK/rootdir/lib/modules/${KERNELRELEASE}/
++endif
++
++all:
++ $(MAKE) -C ${KERNELPATH} SUBDIRS=$(shell pwd) modules
++
++install: all
++ $(STRIP) -S ae531x.o
++ cp ae531x.o ${KERNELPATH}/arch/mips/ar531x/ROOTDISK/rootdir/lib/modules/$(strip $(shell head -n 1 $(KERNELPATH)/Makefile | cut -f 2 -d'=')).$(strip $(shell head -n 2 $(KERNELPATH)/Makefile | tail -1 | cut -f 2 -d'=')).$(strip $(shell head -n 3 $(KERNELPATH)/Makefile | tail -1 | cut -f 2 -d'='))${EXTRAVERSION}/net/.
++
++clean:
++ -rm -f *~ *.o *.ko *.mod.c
++ -rm -f .version .*.o.flags .*.o.d .*.o.cmd .*.ko.cmd
++
++ae531x.o : $(ae531x-objs)
++ $(LD) -o ae531x.o -r $(ae531x-objs)
+diff -urN linux-mips-orig/drivers/net/ath/mvPhy.c linux-mips-new/drivers/net/ath/mvPhy.c
+--- linux-mips-orig/drivers/net/ath/mvPhy.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/mvPhy.c 2005-12-31 12:33:57.726530768 +0000
+@@ -0,0 +1,1230 @@
++/*
++ * 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 ethernet PHY switch, Marvell 88E6060.
++*
++* This module is intended to be largely OS and platform-independent.
++*/
++
++#if defined(linux)
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++
++#include "ar531xlnx.h"
++#endif
++
++#if defined(__ECOS)
++#include "ae531xecos.h"
++#endif
++
++
++#include "ae531xmac.h"
++#include "ae531xreg.h"
++#include "mvPhy.h"
++
++#if /* DEBUG */ 1
++#define MV_DEBUG_ERROR 0x00000001
++#define MV_DEBUG_PHYSETUP 0x00000002
++#define MV_DEBUG_PHYCHANGE 0x00000004
++
++int mvPhyDebug = MV_DEBUG_ERROR;
++
++#define MV_PRINT(FLG, X) \
++{ \
++ if (mvPhyDebug & (FLG)) { \
++ DEBUG_PRINTF X; \
++ } \
++}
++#else
++#define MV_PRINT(FLG, X)
++#endif
++
++#if CONFIG_VENETDEV
++/*
++ * On AR5312 with CONFIG_VENETDEV==1,
++ * ports 0..3 are LAN ports (accessed through ae0)
++ * port 4 is the WAN port. (accessed through ae1)
++ *
++ * The phy switch settings in the mvPhyInfo table are set accordingly.
++ */
++#define MV_WAN_PORT 4
++#define MV_IS_LAN_PORT(port) ((port) < MV_WAN_PORT)
++#define MV_IS_WAN_PORT(port) ((port) == MV_WAN_PORT)
++#endif
++
++/*
++ * 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 phyBase;
++ UINT32 phyAddr; /* PHY registers associated with this phy port */
++ UINT32 switchPortAddr; /* switch port regs assoc'ed with this phy port */
++ UINT32 VLANTableSetting; /* Value to be written to VLAN table */
++} mvPhyInfo_t;
++
++/******************************************************************************
++ * Per-PHY information, indexed by PHY unit number.
++ *
++ * This table is board-dependent. It includes information
++ * about which enet MAC controls which PHY port.
++ */
++mvPhyInfo_t mvPhyInfo[] = {
++ /*
++ * On AP30/AR5312, all PHYs are associated with MAC0.
++ * AP30/AR5312's MAC1 isn't used for anything.
++ * CONFIG_VENETDEV==1 (router) configuration:
++ * Ports 0,1,2, and 3 are "LAN ports"
++ * Port 4 is a WAN port
++ * Port 5 connects to MAC0 in the AR5312
++ * CONFIG_VENETDEV==0 (bridge) configuration:
++ * Ports 0,1,2,3,4 are "LAN ports"
++ * Port 5 connects to the MAC0 in the AR5312
++ */
++ {isEnetPort: TRUE, /* phy port 0 -- LAN port 0 */
++ isPhyAlive: FALSE,
++ ethUnit: 0,
++ phyBase: 0,
++ phyAddr: 0x10,
++ switchPortAddr: 0x18,
++#if CONFIG_VENETDEV
++ VLANTableSetting: 0x2e
++#else
++ VLANTableSetting: 0x3e
++#endif
++ },
++
++ {isEnetPort: TRUE, /* phy port 1 -- LAN port 1 */
++ isPhyAlive: FALSE,
++ ethUnit: 0,
++ phyBase: 0,
++ phyAddr: 0x11,
++ switchPortAddr: 0x19,
++#if CONFIG_VENETDEV
++ VLANTableSetting: 0x2d
++#else
++ VLANTableSetting: 0x3d
++#endif
++ },
++
++ {isEnetPort: TRUE, /* phy port 2 -- LAN port 2 */
++ isPhyAlive: FALSE,
++ ethUnit: 0,
++ phyBase: 0,
++ phyAddr: 0x12,
++ switchPortAddr: 0x1a,
++#if CONFIG_VENETDEV
++ VLANTableSetting: 0x2b
++#else
++ VLANTableSetting: 0x3b
++#endif
++ },
++
++ {isEnetPort: TRUE, /* phy port 3 -- LAN port 3 */
++ isPhyAlive: FALSE,
++ ethUnit: 0,
++ phyBase: 0,
++ phyAddr: 0x13,
++ switchPortAddr: 0x1b,
++#if CONFIG_VENETDEV
++ VLANTableSetting: 0x27
++#else
++ VLANTableSetting: 0x37
++#endif
++ },
++
++ {isEnetPort: TRUE, /* phy port 4 -- WAN port or LAN port 4 */
++ isPhyAlive: FALSE,
++ ethUnit: 0,
++ phyBase: 0,
++ phyAddr: 0x14,
++ switchPortAddr: 0x1c,
++#if CONFIG_VENETDEV
++ VLANTableSetting: 0x1020 /* WAN port */
++#else
++ VLANTableSetting: 0x2f /* LAN port 4 */
++#endif
++ },
++
++ {isEnetPort: FALSE, /* phy port 5 -- CPU port (no RJ45 connector) */
++ isPhyAlive: TRUE,
++ ethUnit: 0,
++ phyBase: 0,
++ phyAddr: 0x15,
++ switchPortAddr: 0x1d,
++#if CONFIG_VENETDEV
++ VLANTableSetting: 0x0f /* Send only to LAN ports */
++#else
++ VLANTableSetting: 0x1f /* Send to all ports */
++#endif
++ },
++};
++
++#define MV_PHY_MAX (sizeof(mvPhyInfo) / sizeof(mvPhyInfo[0]))
++
++/* Range of valid PHY IDs is [MIN..MAX] */
++#define MV_ID_MIN 0
++#define MV_ID_MAX (MV_PHY_MAX-1)
++
++/* Convenience macros to access myPhyInfo */
++#define MV_IS_ENET_PORT(phyUnit) (mvPhyInfo[phyUnit].isEnetPort)
++#define MV_IS_PHY_ALIVE(phyUnit) (mvPhyInfo[phyUnit].isPhyAlive)
++#define MV_ETHUNIT(phyUnit) (mvPhyInfo[phyUnit].ethUnit)
++#define MV_PHYBASE(phyUnit) (mvPhyInfo[phyUnit].phyBase)
++#define MV_PHYADDR(phyUnit) (mvPhyInfo[phyUnit].phyAddr)
++#define MV_SWITCH_PORT_ADDR(phyUnit) (mvPhyInfo[phyUnit].switchPortAddr)
++#define MV_VLAN_TABLE_SETTING(phyUnit) (mvPhyInfo[phyUnit].VLANTableSetting)
++
++#define MV_IS_ETHUNIT(phyUnit, ethUnit) \
++ (MV_IS_ENET_PORT(phyUnit) && \
++ MV_ETHUNIT(phyUnit) == (ethUnit))
++
++
++/* Forward references */
++BOOL mv_phyIsLinkAlive(int phyUnit);
++LOCAL void mv_VLANInit(int ethUnit);
++LOCAL void mv_enableConfiguredPorts(int ethUnit);
++LOCAL void mv_verifyReady(int ethUnit);
++BOOL mv_phySetup(int ethUnit, UINT32 phyBase);
++int mv_phyIsFullDuplex(int ethUnit);
++BOOL mv_phyIsSpeed100(int phyUnit);
++LOCAL BOOL mv_validPhyId(int phyUnit);
++void mv_flushATUDB(int phyUnit);
++void mv_phyCheckStatusChange(int ethUnit);
++#if DEBUG
++void mv_phyShow(int phyUnit);
++void mv_phySet(int phyUnit, UINT32 regnum, UINT32 value);
++void mv_switchPortSet(int phyUnit, UINT32 regnum, UINT32 value);
++void mv_switchGlobalSet(int phyUnit, UINT32 regnum, UINT32 value);
++void mv_showATUDB(int phyUnit);
++void mv_countGoodFrames(int phyUnit);
++void mv_countBadFrames(int phyUnit);
++void mv_showFrameCounts(int phyUnit);
++#endif
++
++
++/******************************************************************************
++*
++* mv_phyIsLinkAlive - test to see if the specified link is alive
++*
++* RETURNS:
++* TRUE --> link is alive
++* FALSE --> link is down
++*/
++BOOL
++mv_phyIsLinkAlive(int phyUnit)
++{
++ UINT16 phyHwStatus;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
++
++ if (phyHwStatus & MV_STATUS_REAL_TIME_LINK_UP) {
++ return TRUE;
++ } else {
++ return FALSE;
++ }
++}
++
++/******************************************************************************
++*
++* mv_VLANInit - initialize "port-based VLANs" for the specified enet unit.
++*/
++LOCAL void
++mv_VLANInit(int ethUnit)
++{
++ int phyUnit;
++ UINT32 phyBase;
++ UINT32 switchPortAddr;
++
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ if (MV_ETHUNIT(phyUnit) != ethUnit) {
++ continue;
++ }
++
++ phyBase = MV_PHYBASE(phyUnit);
++ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
++
++ phyRegWrite(phyBase, switchPortAddr, MV_PORT_BASED_VLAN_MAP,
++ MV_VLAN_TABLE_SETTING(phyUnit));
++ }
++}
++
++#define phyPortConfigured(phyUnit) TRUE /* TBDFREEDOM2 */
++
++/******************************************************************************
++*
++* mv_enableConfiguredPorts - enable whichever PHY ports are supposed
++* to be enabled according to administrative configuration.
++*/
++LOCAL void
++mv_enableConfiguredPorts(int ethUnit)
++{
++ int phyUnit;
++ UINT32 phyBase;
++ UINT32 switchPortAddr;
++ UINT16 portControl;
++ UINT16 portAssociationVector;
++
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ if (MV_ETHUNIT(phyUnit) != ethUnit) {
++ continue;
++ }
++
++ phyBase = MV_PHYBASE(phyUnit);
++ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
++
++ if (phyPortConfigured(phyUnit)) {
++
++ portControl = MV_PORT_CONTROL_PORT_STATE_FORWARDING;
++#if CONFIG_VENETDEV
++ if (!MV_IS_ENET_PORT(phyUnit)) { /* CPU port */
++ portControl |= MV_PORT_CONTROL_INGRESS_TRAILER
++ | MV_PORT_CONTROL_EGRESS_MODE;
++ }
++#endif
++ phyRegWrite(phyBase, switchPortAddr, MV_PORT_CONTROL, portControl);
++
++ portAssociationVector = 1 << phyUnit;
++
++ phyRegWrite(phyBase, switchPortAddr,
++ MV_PORT_ASSOCIATION_VECTOR, portAssociationVector);
++ }
++ }
++}
++
++/******************************************************************************
++*
++* mv_verifyReady - validates that we're dealing with the device
++* we think we're dealing with, and that it's ready.
++*/
++LOCAL void
++mv_verifyReady(int ethUnit)
++{
++ int phyUnit;
++ UINT16 globalStatus;
++ UINT32 phyBase = 0;
++ UINT32 phyAddr;
++ UINT32 switchPortAddr;
++ UINT16 phyID1;
++ UINT16 phyID2;
++ UINT16 switchID;
++
++ /*
++ * The first read to the Phy port registers always fails and
++ * returns 0. So get things started with a bogus read.
++ */
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ (void)phyRegRead(phyBase, phyAddr, MV_PHY_ID1); /* returns 0 */
++ break;
++ }
++
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ /*******************/
++ /* Verify phy port */
++ /*******************/
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ phyID1 = phyRegRead(phyBase, phyAddr, MV_PHY_ID1);
++ if (phyID1 != MV_PHY_ID1_EXPECTATION) {
++ MV_PRINT(MV_DEBUG_PHYSETUP,
++ ("Invalid PHY ID1 for ethmac%d port%d. Expected 0x%04x, read 0x%04x\n",
++ ethUnit,
++ phyUnit,
++ MV_PHY_ID1_EXPECTATION,
++ phyID1));
++ return;
++ }
++
++ phyID2 = phyRegRead(phyBase, phyAddr, MV_PHY_ID2);
++ if ((phyID2 & MV_OUI_LSB_MASK) != MV_OUI_LSB_EXPECTATION) {
++ MV_PRINT(MV_DEBUG_PHYSETUP,
++ ("Invalid PHY ID2 for ethmac%d port %d. Expected 0x%04x, read 0x%04x\n",
++ ethUnit,
++ phyUnit,
++ MV_OUI_LSB_EXPECTATION,
++ phyID2));
++ return;
++ }
++
++ MV_PRINT(MV_DEBUG_PHYSETUP,
++ ("Found PHY ethmac%d port%d: model 0x%x revision 0x%x\n",
++ ethUnit,
++ phyUnit,
++ (phyID2 & MV_MODEL_NUM_MASK) >> MV_MODEL_NUM_SHIFT,
++ (phyID2 & MV_REV_NUM_MASK) >> MV_REV_NUM_SHIFT));
++
++
++ /**********************/
++ /* Verify switch port */
++ /**********************/
++ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
++
++ switchID = phyRegRead(phyBase, switchPortAddr, MV_SWITCH_ID);
++ if ((switchID & MV_SWITCH_ID_DEV_MASK) !=
++ MV_SWITCH_ID_DEV_EXPECTATION) {
++
++ MV_PRINT(MV_DEBUG_PHYSETUP,
++ ("Invalid switch ID for ethmac%d port %d. Expected 0x%04x, read 0x%04x\n",
++ ethUnit,
++ phyUnit,
++ MV_SWITCH_ID_DEV_EXPECTATION,
++ switchID));
++ return;
++ }
++
++ MV_PRINT(MV_DEBUG_PHYSETUP,
++ ("Found PHY switch for enet %d port %d deviceID 0x%x revision 0x%x\n",
++ ethUnit,
++ phyUnit,
++ (switchID & MV_SWITCH_ID_DEV_MASK) >> MV_SWITCH_ID_DEV_SHIFT,
++ (switchID & MV_SWITCH_ID_REV_MASK) >> MV_SWITCH_ID_REV_SHIFT))
++ }
++
++ /*******************************/
++ /* Verify that switch is ready */
++ /*******************************/
++ if (phyBase) {
++ globalStatus = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ MV_SWITCH_GLOBAL_STATUS);
++
++ if (!(globalStatus & MV_SWITCH_STATUS_READY_MASK)) {
++ MV_PRINT(MV_DEBUG_PHYSETUP,
++ ("PHY switch for ethmac%d NOT ready!\n",
++ ethUnit));
++ }
++ } else {
++ MV_PRINT(MV_DEBUG_PHYSETUP,
++ ("No ports configured for ethmac%d\n", ethUnit));
++ }
++}
++
++/******************************************************************************
++*
++* mv_phySetup - reset and setup the PHY switch.
++*
++* Resets each PHY port.
++*
++* RETURNS:
++* TRUE --> at least 1 PHY with LINK
++* FALSE --> no LINKs on this ethernet unit
++*/
++BOOL
++mv_phySetup(int ethUnit, UINT32 phyBase)
++{
++ int phyUnit;
++ int liveLinks = 0;
++ BOOL foundPhy = FALSE;
++ UINT32 phyAddr;
++ UINT16 atuControl;
++
++ /*
++ * Allow platform-specific code to determine the default Ethernet MAC
++ * at run-time. If phyEthMacDefault returns a negative value, use the
++ * static mvPhyInfo table "as is". But if phyEthMacDefault returns a
++ * non-negative value, use it as the default ethernet unit.
++ */
++ {
++ int ethMacDefault = phyEthMacDefault();
++
++ if (ethMacDefault >= 0) {
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ MV_ETHUNIT(phyUnit)=ethMacDefault;
++ }
++ }
++ }
++
++ /*
++ * See if there's any configuration data for this enet,
++ * and set up phyBase in table.
++ */
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ if (MV_ETHUNIT(phyUnit) != ethUnit) {
++ continue;
++ }
++
++ MV_PHYBASE(phyUnit) = phyBase;
++ foundPhy = TRUE;
++ }
++
++ if (!foundPhy) {
++ return FALSE; /* No PHY's configured for this ethUnit */
++ }
++
++ /* Verify that the switch is what we think it is, and that it's ready */
++ mv_verifyReady(ethUnit);
++
++ /* Initialize global switch settings */
++ atuControl = MV_ATUCTRL_AGE_TIME_DEFAULT << MV_ATUCTRL_AGE_TIME_SHIFT;
++ atuControl |= MV_ATUCTRL_ATU_SIZE_DEFAULT << MV_ATUCTRL_ATU_SIZE_SHIFT;
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_CONTROL, atuControl);
++
++ /* Reset PHYs and start autonegoation on each. */
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ if (MV_ETHUNIT(phyUnit) != ethUnit) {
++ continue;
++ }
++
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ phyRegWrite(phyBase, phyAddr, MV_PHY_CONTROL,
++ MV_CTRL_SOFTWARE_RESET | MV_CTRL_AUTONEGOTIATION_ENABLE);
++ }
++
++#if 0 /* Don't wait -- we'll detect shortly after the link comes up */
++{
++ int timeout;
++ UINT16 phyHwStatus;
++
++ /*
++ * Wait 5 seconds for ALL associated PHYs to finish autonegotiation.
++ */
++ timeout=50;
++ for (phyUnit=0; (phyUnit < MV_PHY_MAX) && (timeout > 0); phyUnit++) {
++ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++ for (;;) {
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
++
++ if (MV_AUTONEG_DONE(phyHwStatus)) {
++ break;
++ }
++
++ if (--timeout == 0) {
++ break;
++ }
++
++ sysMsDelay(100);
++ }
++ }
++}
++#endif
++
++ /*
++ * 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 < MV_PHY_MAX; phyUnit++) {
++ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ if (mv_phyIsLinkAlive(phyUnit)) {
++ liveLinks++;
++ MV_IS_PHY_ALIVE(phyUnit) = TRUE;
++ } else {
++ MV_IS_PHY_ALIVE(phyUnit) = FALSE;
++ }
++
++ MV_PRINT(MV_DEBUG_PHYSETUP,
++ ("ethmac%d: Phy Status=%4.4x\n",
++ ethUnit,
++ phyRegRead(MV_PHYBASE(phyUnit),
++ MV_PHYADDR(phyUnit),
++ MV_PHY_SPECIFIC_STATUS)));
++ }
++
++ mv_VLANInit(ethUnit);
++
++ mv_enableConfiguredPorts(ethUnit);
++
++ return (liveLinks > 0);
++}
++
++
++/******************************************************************************
++*
++* mv_phyIsDuplexFull - Determines whether the phy ports associated with the
++* specified device are FULL or HALF duplex.
++*
++* RETURNS:
++* 1 --> at least one associated PHY in FULL DUPLEX
++* 0 --> all half duplex
++* -1 --> No links
++*/
++int
++mv_phyIsFullDuplex(int ethUnit)
++{
++ int phyUnit;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++ UINT16 phyHwStatus;
++ int oneIsReady=0;
++
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ if (mv_phyIsLinkAlive(phyUnit)) {
++ oneIsReady = 1;
++
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
++
++ if (phyHwStatus & MV_STATUS_RESOLVED_DUPLEX_FULL) {
++ return 1;
++ }
++ }
++ }
++ if (oneIsReady)
++ return 0;
++ else
++ return -1;
++}
++
++/******************************************************************************
++*
++* mv_phyIsSpeed100 - Determines the speed of a phy port
++*
++* RETURNS:
++* TRUE --> PHY operating at 100 Mbit
++* FALSE --> link down, or not operating at 100 Mbit
++*/
++BOOL
++mv_phyIsSpeed100(int phyUnit)
++{
++ UINT16 phyHwStatus;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ if (MV_IS_ENET_PORT(phyUnit)) {
++ if (mv_phyIsLinkAlive(phyUnit)) {
++
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
++
++ if (phyHwStatus & MV_STATUS_RESOLVED_SPEED_100) {
++ return TRUE;
++ }
++ }
++ }
++
++ return FALSE;
++}
++
++#if CONFIG_VENETDEV
++/******************************************************************************
++*
++* mv_phyDetermineSource - Examine a received frame's Egress Trailer
++* to determine whether it came from a LAN or WAN port.
++*
++* RETURNS:
++* Sets *pFromLAN: 1-->LAN, 0-->WAN
++* Modifies *pLen to remove PHY trailer from frame
++*/
++void
++mv_phyDetermineSource(char *data, int len, int *pFromLAN)
++{
++ unsigned char *phyTrailer;
++ unsigned char incomingPort;
++
++ phyTrailer = &data[len - MV_PHY_TRAILER_SIZE];
++ ASSERT(phyTrailer[0] == MV_EGRESS_TRAILER_VALID);
++
++ incomingPort = phyTrailer[1];
++ if (MV_IS_LAN_PORT(incomingPort)) {
++ *pFromLAN = 1;
++ } else {
++ ASSERT(MV_IS_WAN_PORT(incomingPort));
++ *pFromLAN = 0;
++ }
++}
++
++
++/******************************************************************************
++*
++* mv_phySetDestinationPort - Set the Ingress Trailer to force the
++* frame to be sent to LAN or WAN, as specified.
++*
++*/
++void
++mv_phySetDestinationPort(char *data, int len, int fromLAN)
++{
++ char *phyTrailer;
++
++ phyTrailer = &data[len];
++ if (fromLAN) {
++ /* LAN ports: Use default settings, as per mvPhyInfo */
++ phyTrailer[0] = 0x00;
++ phyTrailer[1] = 0x00;
++ } else {
++ /* WAN port: Direct to WAN port */
++ phyTrailer[0] = MV_INGRESS_TRAILER_OVERRIDE;
++ phyTrailer[1] = 1 << MV_WAN_PORT;
++ }
++ phyTrailer[2] = 0x00;
++ phyTrailer[3] = 0x00;
++}
++#endif
++
++
++/*****************************************************************************
++*
++* Validate that the specified PHY unit number is a valid PHY ID.
++* Print a message if it is invalid.
++* RETURNS
++* TRUE --> valid
++* FALSE --> invalid
++*/
++LOCAL BOOL
++mv_validPhyId(int phyUnit)
++{
++ if ((phyUnit >= MV_ID_MIN) && (phyUnit <= MV_ID_MAX)) {
++ return TRUE;
++ } else {
++ PRINTF("PHY unit number must be in the range [%d..%d]\n",
++ MV_ID_MIN, MV_ID_MAX);
++ return FALSE;
++ }
++}
++
++
++/*****************************************************************************
++*
++* mv_waitWhileATUBusy - spins until the ATU completes
++* its previous operation.
++*/
++LOCAL void
++mv_waitWhileATUBusy(UINT32 phyBase)
++{
++ BOOL isBusy;
++ UINT16 ATUOperation;
++
++ do {
++
++ ATUOperation = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ MV_ATU_OPERATION);
++
++ isBusy = (ATUOperation & MV_ATU_BUSY_MASK) == MV_ATU_IS_BUSY;
++
++ } while(isBusy);
++}
++
++/*****************************************************************************
++*
++* mv_flushATUDB - flushes ALL entries in the Address Translation Unit
++* DataBase associated with phyUnit. [Since we use a single DB for
++* all PHYs, this flushes the entire shared DataBase.]
++*
++* The current implementation flushes even more than absolutely needed --
++* it flushes all entries for all phyUnits on the same ethernet as the
++* specified phyUnit.
++*
++* It is called only when a link failure is detected on a port that was
++* previously working. In other words, when the cable is unplugged.
++*/
++void
++mv_flushATUDB(int phyUnit)
++{
++ UINT32 phyBase;
++
++ if (!mv_validPhyId(phyUnit)) {
++ PRINTF("Invalid port number: %d\n", phyUnit);
++ return;
++ }
++
++ phyBase = MV_PHYBASE(phyUnit);
++
++ /* Wait for previous operation (if any) to complete */
++ mv_waitWhileATUBusy(phyBase);
++
++ /* Tell hardware to flush all entries */
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_OPERATION,
++ MV_ATU_OP_FLUSH_ALL | MV_ATU_IS_BUSY);
++
++ mv_waitWhileATUBusy(phyBase);
++}
++
++/*****************************************************************************
++*
++* mv_phyCheckStatusChange -- 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)
++*/
++void
++mv_phyCheckStatusChange(int ethUnit)
++{
++ int phyUnit;
++ UINT16 phyHwStatus;
++ mvPhyInfo_t *lastStatus;
++ int linkCount = 0;
++ int lostLinks = 0;
++ int gainedLinks = 0;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ lastStatus = &mvPhyInfo[phyUnit];
++ phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
++
++ if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */
++ /* See if we've lost link */
++ if (phyHwStatus & MV_STATUS_REAL_TIME_LINK_UP) {
++ linkCount++;
++ } else {
++ lostLinks++;
++ mv_flushATUDB(phyUnit);
++ MV_PRINT(MV_DEBUG_PHYCHANGE,("\nethmac%d port%d down\n",
++ ethUnit, phyUnit));
++ lastStatus->isPhyAlive = FALSE;
++ }
++ } else { /* last known link status was DEAD */
++ /* Check for AutoNegotiation complete */
++ if (MV_AUTONEG_DONE(phyHwStatus)) {
++ gainedLinks++;
++ linkCount++;
++ MV_PRINT(MV_DEBUG_PHYCHANGE,("\nethmac%d port%d up\n",
++ ethUnit, phyUnit));
++ lastStatus->isPhyAlive = TRUE;
++ }
++ }
++ }
++
++ 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);
++ }
++ }
++}
++
++#if DEBUG
++
++/* Define the registers of interest for a phyShow command */
++typedef struct mvRegisterTableEntry_s {
++ UINT32 regNum;
++ char *regIdString;
++} mvRegisterTableEntry_t;
++
++mvRegisterTableEntry_t mvPhyRegisterTable[] = {
++ {MV_PHY_CONTROL, "PHY Control "},
++ {MV_PHY_STATUS, "PHY Status "},
++ {MV_PHY_ID1, "PHY Identifier 1 "},
++ {MV_PHY_ID2, "PHY Identifier 2 "},
++ {MV_AUTONEG_ADVERT, "Auto-Negotiation Advertisement "},
++ {MV_LINK_PARTNER_ABILITY, "Link Partner Ability "},
++ {MV_AUTONEG_EXPANSION, "Auto-Negotiation Expansion "},
++ {MV_NEXT_PAGE_TRANSMIT, "Next Page Transmit "},
++ {MV_LINK_PARTNER_NEXT_PAGE, "Link Partner Next Page "},
++ {MV_PHY_SPECIFIC_CONTROL_1, "PHY-Specific Control Register 1 "},
++ {MV_PHY_SPECIFIC_STATUS, "PHY-Specific Status "},
++ {MV_PHY_INTERRUPT_ENABLE, "PHY Interrupt Enable "},
++ {MV_PHY_INTERRUPT_STATUS, "PHY Interrupt Status "},
++ {MV_PHY_INTERRUPT_PORT_SUMMARY, "PHY Interrupt Port Summary "},
++ {MV_RECEIVE_ERROR_COUNTER, "Receive Error Counter "},
++ {MV_LED_PARALLEL_SELECT, "LED Parallel Select "},
++ {MV_LED_STREAM_SELECT_LEDS, "LED Stream Select "},
++ {MV_PHY_LED_CONTROL, "PHY LED Control "},
++ {MV_PHY_MANUAL_LED_OVERRIDE, "PHY Manual LED Override "},
++ {MV_VCT_CONTROL, "VCT Control "},
++ {MV_VCT_STATUS, "VCT Status "},
++ {MV_PHY_SPECIFIC_CONTROL_2, "PHY-Specific Control Register 2 "},
++};
++int mvPhyNumRegs = sizeof(mvPhyRegisterTable) / sizeof(mvPhyRegisterTable[0]);
++
++
++mvRegisterTableEntry_t mvSwitchPortRegisterTable[] = {
++ {MV_PORT_STATUS, "Port Status "},
++ {MV_SWITCH_ID, "Switch ID "},
++ {MV_PORT_CONTROL, "Port Control "},
++ {MV_PORT_BASED_VLAN_MAP, "Port-Based VLAN Map "},
++ {MV_PORT_ASSOCIATION_VECTOR, "Port Association Vector "},
++ {MV_RX_COUNTER, "RX Counter "},
++ {MV_TX_COUNTER, "TX Counter "},
++};
++int mvSwitchPortNumRegs =
++ sizeof(mvSwitchPortRegisterTable) / sizeof(mvSwitchPortRegisterTable[0]);
++
++
++mvRegisterTableEntry_t mvSwitchGlobalRegisterTable[] = {
++ {MV_SWITCH_GLOBAL_STATUS, "Switch Global Status "},
++ {MV_SWITCH_MAC_ADDR0, "Switch MAC Addr 0 & 1 "},
++ {MV_SWITCH_MAC_ADDR2, "Switch MAC Addr 2 & 3 "},
++ {MV_SWITCH_MAC_ADDR4, "Switch MAC Addr 4 & 5 "},
++ {MV_SWITCH_GLOBAL_CONTROL, "Switch Global Control "},
++ {MV_ATU_CONTROL, "ATU Control "},
++ {MV_ATU_OPERATION, "ATU Operation "},
++ {MV_ATU_DATA, "ATU Data "},
++ {MV_ATU_MAC_ADDR0, "ATU MAC Addr 0 & 1 "},
++ {MV_ATU_MAC_ADDR2, "ATU MAC Addr 2 & 3 "},
++ {MV_ATU_MAC_ADDR4, "ATU MAC Addr 4 & 5 "},
++};
++int mvSwitchGlobalNumRegs =
++ sizeof(mvSwitchGlobalRegisterTable) / sizeof(mvSwitchGlobalRegisterTable[0]);
++
++void my_mvPhyShow(int ethUnit)
++{
++ int phyUnit;
++ for (phyUnit=0; (phyUnit < MV_PHY_MAX); phyUnit++) {
++ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++ mv_phyShow(phyUnit);
++ }
++}
++
++/*****************************************************************************
++*
++* mv_phyShow - Dump the state of a PHY.
++* There are two sets of registers for each phy port:
++* "phy registers" and
++* "switch port registers"
++* We dump 'em all, plus the switch global registers.
++*/
++void
++mv_phyShow(int phyUnit)
++{
++ int i;
++ UINT16 value;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++ UINT32 switchPortAddr;
++
++ if (!mv_validPhyId(phyUnit)) {
++ return;
++ }
++
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
++
++ printk("PHY state for PHY%d (ethmac%d, phyBase 0x%8x, phyAddr 0x%x, switchAddr 0x%x)\n",
++ phyUnit,
++ MV_ETHUNIT(phyUnit),
++ MV_PHYBASE(phyUnit),
++ MV_PHYADDR(phyUnit),
++ MV_SWITCH_PORT_ADDR(phyUnit));
++
++ printk("PHY Registers:\n");
++ for (i=0; i < mvPhyNumRegs; i++) {
++
++ value = phyRegRead(phyBase, phyAddr, mvPhyRegisterTable[i].regNum);
++
++ printk("Reg %02d (0x%02x) %s = 0x%08x\n",
++ mvPhyRegisterTable[i].regNum,
++ mvPhyRegisterTable[i].regNum,
++ mvPhyRegisterTable[i].regIdString,
++ value);
++ }
++
++ printk("Switch Port Registers:\n");
++ for (i=0; i < mvSwitchPortNumRegs; i++) {
++
++ value = phyRegRead(phyBase, switchPortAddr,
++ mvSwitchPortRegisterTable[i].regNum);
++
++ printk("Reg %02d (0x%02x) %s = 0x%08x\n",
++ mvSwitchPortRegisterTable[i].regNum,
++ mvSwitchPortRegisterTable[i].regNum,
++ mvSwitchPortRegisterTable[i].regIdString,
++ value);
++ }
++
++ printk("Switch Global Registers:\n");
++ for (i=0; i < mvSwitchGlobalNumRegs; i++) {
++
++ value = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ mvSwitchGlobalRegisterTable[i].regNum);
++
++ printk("Reg %02d (0x%02x) %s = 0x%08x\n",
++ mvSwitchGlobalRegisterTable[i].regNum,
++ mvSwitchGlobalRegisterTable[i].regNum,
++ mvSwitchGlobalRegisterTable[i].regIdString,
++ value);
++ }
++}
++
++/*****************************************************************************
++*
++* mv_phySet - Modify the value of a PHY register (debug only).
++*/
++void
++mv_phySet(int phyUnit, UINT32 regnum, UINT32 value)
++{
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ if (mv_validPhyId(phyUnit)) {
++
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ phyRegWrite(phyBase, phyAddr, regnum, value);
++ }
++}
++
++
++/*****************************************************************************
++*
++* mv_switchPortSet - Modify the value of a switch port register (debug only).
++*/
++void
++mv_switchPortSet(int phyUnit, UINT32 regnum, UINT32 value)
++{
++ UINT32 phyBase;
++ UINT32 switchPortAddr;
++
++ if (mv_validPhyId(phyUnit)) {
++
++ phyBase = MV_PHYBASE(phyUnit);
++ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
++
++ phyRegWrite(phyBase, switchPortAddr, regnum, value);
++ }
++}
++
++/*****************************************************************************
++*
++* mv_switchGlobalSet - Modify the value of a switch global register
++* (debug only).
++*/
++void
++mv_switchGlobalSet(int phyUnit, UINT32 regnum, UINT32 value)
++{
++ UINT32 phyBase;
++
++ if (mv_validPhyId(phyUnit)) {
++
++ phyBase = MV_PHYBASE(phyUnit);
++
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, regnum, value);
++ }
++}
++
++/*****************************************************************************
++*
++* mv_showATUDB - Dump the contents of the Address Translation Unit DataBase
++* for the PHY switch associated with the specified phy.
++*/
++void
++mv_showATUDB(int phyUnit)
++{
++ UINT32 phyBase;
++ UINT16 ATUData;
++ UINT16 ATUMac0;
++ UINT16 ATUMac2;
++ UINT16 ATUMac4;
++ int portVec;
++ int entryState;
++
++ if (!mv_validPhyId(phyUnit)) {
++ printk("Invalid port number: %d\n", phyUnit);
++ return;
++ }
++
++ phyBase = MV_PHYBASE(phyUnit);
++
++ /* Wait for previous operation (if any) to complete */
++ mv_waitWhileATUBusy(phyBase);
++
++ /* Initialize ATU MAC to all 1's */
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR0, 0xffff);
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR2, 0xffff);
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR4, 0xffff);
++
++ printk(" MAC ADDRESS EntryState PortVector\n");
++
++ for(;;) {
++ /* Tell hardware to get next MAC info */
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_OPERATION,
++ MV_ATU_OP_GET_NEXT | MV_ATU_IS_BUSY);
++
++ mv_waitWhileATUBusy(phyBase);
++
++ ATUData = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_DATA);
++ entryState = (ATUData & MV_ENTRYSTATE_MASK) >> MV_ENTRYSTATE_SHIFT;
++
++ if (entryState == 0) {
++ /* We've hit the end of the list */
++ break;
++ }
++
++ ATUMac0 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR0);
++ ATUMac2 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR2);
++ ATUMac4 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR4);
++
++ portVec = (ATUData & MV_PORTVEC_MASK) >> MV_PORTVEC_SHIFT;
++
++ printk("%02x:%02x:%02x:%02x:%02x:%02x 0x%02x 0x%02x\n",
++ ATUMac0 >> 8, /* MAC byte 0 */
++ ATUMac0 & 0xff, /* MAC byte 1 */
++ ATUMac2 >> 8, /* MAC byte 2 */
++ ATUMac2 & 0xff, /* MAC byte 3 */
++ ATUMac4 >> 8, /* MAC byte 4 */
++ ATUMac4 & 0xff, /* MAC byte 5 */
++ entryState,
++ portVec);
++ }
++}
++
++LOCAL BOOL countingGoodFrames;
++
++/*****************************************************************************
++*
++* mv_countGoodFrames - starts counting GOOD RX/TX frames per port
++*/
++void
++mv_countGoodFrames(int phyUnit)
++{
++ UINT32 phyBase;
++ UINT16 globalControl;
++
++ if (mv_validPhyId(phyUnit)) {
++ /*
++ * Guarantee that counters are cleared by
++ * forcing CtrMode to toggle and end on GOODFRAMES.
++ */
++
++ phyBase = MV_PHYBASE(phyUnit);
++
++ /* Read current Switch Global Control Register */
++ globalControl = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ MV_SWITCH_GLOBAL_CONTROL);
++
++ /* Set CtrMode to count BAD frames */
++ globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
++ MV_CTRMODE_BADFRAMES);
++
++ /* Push new value out to hardware */
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ MV_SWITCH_GLOBAL_CONTROL, globalControl);
++
++ /* Now toggle CtrMode to count GOOD frames */
++ globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
++ MV_CTRMODE_GOODFRAMES);
++
++ /* Push new value out to hardware */
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ MV_SWITCH_GLOBAL_CONTROL, globalControl);
++
++ countingGoodFrames = TRUE;
++ }
++}
++
++/*****************************************************************************
++*
++* mv_countBadFrames - starts counting BAD RX/TX frames per port
++*/
++void
++mv_countBadFrames(int phyUnit)
++{
++ UINT32 phyBase;
++ UINT16 globalControl;
++
++ if (mv_validPhyId(phyUnit)) {
++ /*
++ * Guarantee that counters are cleared by
++ * forcing CtrMode to toggle and end on BADFRAMES.
++ */
++
++ phyBase = MV_PHYBASE(phyUnit);
++
++ /* Read current Switch Global Control Register */
++ globalControl = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ MV_SWITCH_GLOBAL_CONTROL);
++
++ /* Set CtrMode to count GOOD frames */
++ globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
++ MV_CTRMODE_GOODFRAMES);
++
++ /* Push new value out to hardware */
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ MV_SWITCH_GLOBAL_CONTROL, globalControl);
++
++ /* Now toggle CtrMode to count BAD frames */
++ globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
++ MV_CTRMODE_BADFRAMES);
++
++ /* Push new value out to hardware */
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ MV_SWITCH_GLOBAL_CONTROL, globalControl);
++
++ countingGoodFrames = FALSE;
++ }
++}
++
++/*****************************************************************************
++*
++* mv_showFrameCounts - shows current GOOD/BAD Frame counts
++*/
++void
++mv_showFrameCounts(int phyUnit)
++{
++ UINT16 rxCounter;
++ UINT16 txCounter;
++ UINT32 phyBase;
++ UINT32 switchPortAddr;
++
++ if (!mv_validPhyId(phyUnit)) {
++ return;
++ }
++
++ phyBase = MV_PHYBASE(phyUnit);
++ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
++
++ rxCounter = phyRegRead(phyBase, switchPortAddr, MV_RX_COUNTER);
++
++ txCounter = phyRegRead(phyBase, switchPortAddr, MV_TX_COUNTER);
++
++ printk("port%d %s frames: receive: %05d transmit: %05d\n",
++ phyUnit,
++ (countingGoodFrames ? "good" : "error"),
++ rxCounter,
++ txCounter);
++}
++#endif
+diff -urN linux-mips-orig/drivers/net/ath/mvPhy.h linux-mips-new/drivers/net/ath/mvPhy.h
+--- linux-mips-orig/drivers/net/ath/mvPhy.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/mvPhy.h 2005-12-31 12:33:57.727530616 +0000
+@@ -0,0 +1,162 @@
++/*
++ * 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.
++ */
++
++/*
++ * mvPhy.h - definitions for the ethernet PHY -- Marvell 88E6060
++ * All definitions in this file are operating system independent!
++ */
++
++#ifndef MVPHY_H
++#define MVPHY_H
++
++/*****************/
++/* PHY Registers */
++/*****************/
++#define MV_PHY_CONTROL 0
++#define MV_PHY_STATUS 1
++#define MV_PHY_ID1 2
++#define MV_PHY_ID2 3
++#define MV_AUTONEG_ADVERT 4
++#define MV_LINK_PARTNER_ABILITY 5
++#define MV_AUTONEG_EXPANSION 6
++#define MV_NEXT_PAGE_TRANSMIT 7
++#define MV_LINK_PARTNER_NEXT_PAGE 8
++#define MV_PHY_SPECIFIC_CONTROL_1 16
++#define MV_PHY_SPECIFIC_STATUS 17
++#define MV_PHY_INTERRUPT_ENABLE 18
++#define MV_PHY_INTERRUPT_STATUS 19
++#define MV_PHY_INTERRUPT_PORT_SUMMARY 20
++#define MV_RECEIVE_ERROR_COUNTER 21
++#define MV_LED_PARALLEL_SELECT 22
++#define MV_LED_STREAM_SELECT_LEDS 23
++#define MV_PHY_LED_CONTROL 24
++#define MV_PHY_MANUAL_LED_OVERRIDE 25
++
++#define MV_VCT_CONTROL 26
++#define MV_VCT_STATUS 27
++#define MV_PHY_SPECIFIC_CONTROL_2 28
++
++/* MV_PHY_CONTROL fields */
++#define MV_CTRL_SOFTWARE_RESET 0x8000
++#define MV_CTRL_AUTONEGOTIATION_ENABLE 0x1000
++#define MV_CTRL_FULL_DUPLEX 0x0100
++#define MV_CTRL_100_MBPS 0x2000
++
++/* MV_PHY_ID1 fields */
++#define MV_PHY_ID1_EXPECTATION 0x0141 /* OUI >> 6 */
++
++/* MV_PHY_ID2 fields */
++#define MV_OUI_LSB_MASK 0xfc00
++#define MV_OUI_LSB_EXPECTATION 0x0c00
++#define MV_OUI_LSB_SHIFT 10
++#define MV_MODEL_NUM_MASK 0x03f0
++#define MV_MODEL_NUM_SHIFT 4
++#define MV_REV_NUM_MASK 0x000f
++#define MV_REV_NUM_SHIFT 0
++
++/* MV_PHY_SPECIFIC_STATUS fields */
++#define MV_STATUS_RESOLVED_SPEED_100 0x4000
++#define MV_STATUS_RESOLVED_DUPLEX_FULL 0x2000
++#define MV_STATUS_RESOLVED 0x0800
++#define MV_STATUS_REAL_TIME_LINK_UP 0x0400
++
++/* Check if autonegotiation is complete and link is up */
++#define MV_AUTONEG_DONE(mv_phy_specific_status) \
++ (((mv_phy_specific_status) & \
++ (MV_STATUS_RESOLVED | MV_STATUS_REAL_TIME_LINK_UP)) == \
++ (MV_STATUS_RESOLVED | MV_STATUS_REAL_TIME_LINK_UP))
++
++
++/*************************/
++/* Switch Port Registers */
++/*************************/
++#define MV_PORT_STATUS 0
++#define MV_SWITCH_ID 3
++#define MV_PORT_CONTROL 4
++#define MV_PORT_BASED_VLAN_MAP 6
++#define MV_PORT_ASSOCIATION_VECTOR 11
++#define MV_RX_COUNTER 16
++#define MV_TX_COUNTER 17
++
++/* MV_SWITCH_ID fields */
++#define MV_SWITCH_ID_DEV_MASK 0xfff0
++#define MV_SWITCH_ID_DEV_EXPECTATION 0x0600
++#define MV_SWITCH_ID_DEV_SHIFT 4
++#define MV_SWITCH_ID_REV_MASK 0x000f
++#define MV_SWITCH_ID_REV_SHIFT 0
++
++/* MV_PORT_CONTROL fields */
++#define MV_PORT_CONTROL_PORT_STATE_MASK 0x0003
++#define MV_PORT_CONTROL_PORT_STATE_DISABLED 0x0000
++#define MV_PORT_CONTROL_PORT_STATE_FORWARDING 0x0003
++
++#define MV_PORT_CONTROL_EGRESS_MODE 0x0100 /* Receive */
++#define MV_PORT_CONTROL_INGRESS_TRAILER 0x4000 /* Transmit */
++
++#define MV_EGRESS_TRAILER_VALID 0x80
++#define MV_INGRESS_TRAILER_OVERRIDE 0x80
++
++#define MV_PHY_TRAILER_SIZE 4
++
++
++/***************************/
++/* Switch Global Registers */
++/***************************/
++#define MV_SWITCH_GLOBAL_STATUS 0
++#define MV_SWITCH_MAC_ADDR0 1
++#define MV_SWITCH_MAC_ADDR2 2
++#define MV_SWITCH_MAC_ADDR4 3
++#define MV_SWITCH_GLOBAL_CONTROL 4
++#define MV_ATU_CONTROL 10
++#define MV_ATU_OPERATION 11
++#define MV_ATU_DATA 12
++#define MV_ATU_MAC_ADDR0 13
++#define MV_ATU_MAC_ADDR2 14
++#define MV_ATU_MAC_ADDR4 15
++
++/* MV_SWITCH_GLOBAL_STATUS fields */
++#define MV_SWITCH_STATUS_READY_MASK 0x0800
++
++/* MV_SWITCH_GLOBAL_CONTROL fields */
++#define MV_CTRMODE_MASK 0x0100
++#define MV_CTRMODE_GOODFRAMES 0x0000
++#define MV_CTRMODE_BADFRAMES 0x0100
++
++/* MV_ATU_CONTROL fields */
++#define MV_ATUCTRL_ATU_SIZE_MASK 0x3000
++#define MV_ATUCTRL_ATU_SIZE_SHIFT 12
++#define MV_ATUCTRL_ATU_SIZE_DEFAULT 2 /* 1024 entry database */
++#define MV_ATUCTRL_AGE_TIME_MASK 0x0ff0
++#define MV_ATUCTRL_AGE_TIME_SHIFT 4
++#define MV_ATUCTRL_AGE_TIME_DEFAULT 19 /* 19 * 16 = 304 seconds */
++
++/* MV_ATU_OPERATION fields */
++#define MV_ATU_BUSY_MASK 0x8000
++#define MV_ATU_IS_BUSY 0x8000
++#define MV_ATU_IS_FREE 0x0000
++#define MV_ATU_OP_MASK 0x7000
++#define MV_ATU_OP_FLUSH_ALL 0x1000
++#define MV_ATU_OP_GET_NEXT 0x4000
++
++/* MV_ATU_DATA fields */
++#define MV_ENTRYPRI_MASK 0xc000
++#define MV_ENTRYPRI_SHIFT 14
++#define MV_PORTVEC_MASK 0x03f0
++#define MV_PORTVEC_SHIFT 4
++#define MV_ENTRYSTATE_MASK 0x000f
++#define MV_ENTRYSTATE_SHIFT 0
++
++/* PHY Address for the switch itself */
++#define MV_SWITCH_GLOBAL_ADDR 0x1f
++
++BOOL mv_phySetup(int ethUnit, UINT32 phyBase);
++void mv_phyCheckStatusChange(int ethUnit);
++BOOL mv_phyIsSpeed100(int ethUnit);
++int mv_phyIsFullDuplex(int ethUnit);
++
++#endif /* MVPHY_H */
+diff -urN linux-mips-orig/drivers/net/ath/rtPhy.c linux-mips-new/drivers/net/ath/rtPhy.c
+--- linux-mips-orig/drivers/net/ath/rtPhy.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/rtPhy.c 2005-12-31 12:33:57.727530616 +0000
+@@ -0,0 +1,272 @@
++/*
++ * 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 ethernet PHY.
++ * This code supports a simple 1-port ethernet phy, Realtek RTL8201BL,
++ * and compatible PHYs, such as the Kendin KS8721B.
++ * All definitions in this file are operating system independent!
++ */
++
++#if defined(linux)
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++
++#include "ar531xlnx.h"
++#endif
++
++#if defined(__ECOS)
++#include "ae531xecos.h"
++#endif
++
++
++#include "ae531xmac.h"
++#include "ae531xreg.h"
++#include "rtPhy.h"
++
++#if /* DEBUG */ 1
++#define RT_DEBUG_ERROR 0x00000001
++#define RT_DEBUG_PHYSETUP 0x00000002
++#define RT_DEBUG_PHYCHANGE 0x00000004
++
++int rtPhyDebug = RT_DEBUG_ERROR;
++
++#define RT_PRINT(FLG, X) \
++{ \
++ if (rtPhyDebug & (FLG)) { \
++ DEBUG_PRINTF X; \
++ } \
++}
++#else
++#define RT_PRINT(FLG, X)
++#endif
++
++/*
++ * Track per-PHY port information.
++ */
++typedef struct {
++ BOOL phyAlive; /* last known state of link */
++ UINT32 phyBase;
++ UINT32 phyAddr;
++} rtPhyInfo_t;
++
++#define ETH_PHY_ADDR 1
++
++/*
++ * This table defines the mapping from phy units to
++ * per-PHY information.
++ *
++ * This table is somewhat board-dependent.
++ */
++rtPhyInfo_t rtPhyInfo[] = {
++ {phyAlive: FALSE, /* PHY 0 */
++ phyBase: 0, /* filled in by rt_phySetup */
++ phyAddr: ETH_PHY_ADDR},
++
++ {phyAlive: FALSE, /* PHY 1 */
++ phyBase: 0, /* filled in by rt_phySetup */
++ phyAddr: ETH_PHY_ADDR}
++};
++
++/* Convert from phy unit# to (phyBase, phyAddr) pair */
++#define RT_PHYBASE(phyUnit) (rtPhyInfo[phyUnit].phyBase)
++#define RT_PHYADDR(phyUnit) (rtPhyInfo[phyUnit].phyAddr)
++
++
++/******************************************************************************
++*
++* rt_phySetup - 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
++rt_phySetup(int ethUnit, UINT32 phyBase)
++{
++ BOOL linkAlive = FALSE;
++ UINT32 phyAddr;
++
++ RT_PHYBASE(ethUnit) = phyBase;
++
++ phyAddr = RT_PHYADDR(ethUnit);
++
++ /* Reset phy */
++ phyRegWrite(phyBase, phyAddr, GEN_ctl, PHY_SW_RST | AUTONEGENA);
++
++ sysMsDelay(1500);
++
++ return linkAlive;
++}
++
++/******************************************************************************
++*
++* rt_phyIsDuplexFull - Determines whether the phy ports associated with the
++* specified device are FULL or HALF duplex.
++*
++* RETURNS:
++* 1 --> FULL
++* 0 --> HALF
++*/
++int
++rt_phyIsFullDuplex(int ethUnit)
++{
++ UINT16 phyCtl;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ phyBase = RT_PHYBASE(ethUnit);
++ phyAddr = RT_PHYADDR(ethUnit);
++
++ phyCtl = phyRegRead(phyBase, phyAddr, GEN_ctl);
++
++ if (phyCtl & DUPLEX) {
++ return 1;
++ } else {
++ return 0;
++ }
++}
++
++/******************************************************************************
++*
++* rt_phyIsSpeed100 - Determines the speed of phy ports associated with the
++* specified device.
++*
++* RETURNS:
++* TRUE --> 100Mbit
++* FALSE --> 10Mbit
++*/
++BOOL
++rt_phyIsSpeed100(int phyUnit)
++{
++ UINT16 phyLpa;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ phyBase = RT_PHYBASE(phyUnit);
++ phyAddr = RT_PHYADDR(phyUnit);
++
++ phyLpa = phyRegRead(phyBase, phyAddr, AN_lpa);
++
++ if (phyLpa & (LPA_TXFD | LPA_TX)) {
++ return TRUE;
++ } else {
++ return FALSE;
++ }
++}
++
++/*****************************************************************************
++*
++* rt_phyCheckStatusChange -- 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)
++*
++* On AR5311, there is a 1-to-1 mapping of ethernet units to PHYs.
++* When a PHY is plugged in, phyLinkGained is called.
++* When a PHY is unplugged, phyLinkLost is called.
++*/
++void
++rt_phyCheckStatusChange(int ethUnit)
++{
++ UINT16 phyHwStatus;
++ rtPhyInfo_t *lastStatus = &rtPhyInfo[ethUnit];
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ phyBase = RT_PHYBASE(ethUnit);
++ phyAddr = RT_PHYADDR(ethUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, GEN_sts);
++
++ if (lastStatus->phyAlive) { /* last known status was ALIVE */
++ /* See if we've lost link */
++ if (!(phyHwStatus & LINK)) {
++ RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link down\n", ethUnit));
++ lastStatus->phyAlive = FALSE;
++ phyLinkLost(ethUnit);
++ }
++ } else { /* last known status was DEAD */
++ /* Check for AN complete */
++ if ((phyHwStatus & (AUTOCMPLT | LINK)) == (AUTOCMPLT | LINK)) {
++ RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link up\n", ethUnit));
++ lastStatus->phyAlive = TRUE;
++ phyLinkGained(ethUnit);
++ }
++ }
++}
++
++#if DEBUG
++
++/* Define the PHY registers of interest for a phyShow command */
++struct rtRegisterTable_s {
++ UINT32 regNum;
++ char *regIdString;
++} rtRegisterTable[] =
++{
++ {GEN_ctl, "Basic Mode Control (GEN_ctl) "},
++ {GEN_sts, "Basic Mode Status (GEN_sts) "},
++ {GEN_id_hi, "PHY Identifier 1 (GET_id_hi) "},
++ {GEN_id_lo, "PHY Identifier 2 (GET_id_lo) "},
++ {AN_adv, "Auto-Neg Advertisement (AN_adv) "},
++ {AN_lpa, "Auto-Neg Link Partner Ability "},
++ {AN_exp, "Auto-Neg Expansion "},
++};
++
++int rtNumRegs = sizeof(rtRegisterTable) / sizeof(rtRegisterTable[0]);
++
++/*
++ * Dump the state of a PHY.
++ */
++void
++rt_phyShow(int phyUnit)
++{
++ int i;
++ UINT16 value;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ phyBase = RT_PHYBASE(phyUnit);
++ phyAddr = RT_PHYADDR(phyUnit);
++
++ printf("PHY state for ethphy%d\n", phyUnit);
++
++ for (i=0; i<rtNumRegs; i++) {
++
++ value = phyRegRead(phyBase, phyAddr, rtRegisterTable[i].regNum);
++
++ printf("Reg %02d (0x%02x) %s = 0x%08x\n",
++ rtRegisterTable[i].regNum, rtRegisterTable[i].regNum,
++ rtRegisterTable[i].regIdString, value);
++ }
++}
++
++/*
++ * Modify the value of a PHY register.
++ * This makes it a bit easier to modify PHY values during debug.
++ */
++void
++rt_phySet(int phyUnit, UINT32 regnum, UINT32 value)
++{
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ phyBase = RT_PHYBASE(phyUnit);
++ phyAddr = RT_PHYADDR(phyUnit);
++
++ phyRegWrite(phyBase, phyAddr, regnum, value);
++}
++#endif
+diff -urN linux-mips-orig/drivers/net/ath/rtPhy.h linux-mips-new/drivers/net/ath/rtPhy.h
+--- linux-mips-orig/drivers/net/ath/rtPhy.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/rtPhy.h 2005-12-31 12:33:57.727530616 +0000
+@@ -0,0 +1,50 @@
++/*
++ * 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.
++ */
++
++/*
++ * rtPhy.h - definitions for the ethernet PHY.
++ * This code supports a simple 1-port ethernet phy, Realtek RTL8201BL,
++ * and compatible PHYs, such as the Kendin KS8721B.
++ * All definitions in this file are operating system independent!
++ */
++
++#ifndef RTPHY_H
++#define RTPHY_H
++
++/* MII Registers */
++
++#define GEN_ctl 00
++#define GEN_sts 01
++#define GEN_id_hi 02
++#define GEN_id_lo 03
++#define AN_adv 04
++#define AN_lpa 05
++#define AN_exp 06
++
++/* GEN_ctl */
++#define PHY_SW_RST 0x8000
++#define LOOPBACK 0x4000
++#define SPEED 0x2000 /* 100 Mbit/s */
++#define AUTONEGENA 0x1000
++#define DUPLEX 0x0100 /* Duplex mode */
++
++
++/* GEN_sts */
++#define AUTOCMPLT 0x0020 /* Autonegotiation completed */
++#define LINK 0x0004 /* Link status */
++
++/* GEN_ids */
++#define RT_PHY_ID1_EXPECTATION 0x22
++
++/* AN_lpa */
++#define LPA_TXFD 0x0100 /* Link partner supports 100 TX Full Duplex */
++#define LPA_TX 0x0080 /* Link partner supports 100 TX Half Duplex */
++#define LPA_10FD 0x0040 /* Link partner supports 10 BT Full Duplex */
++#define LPA_10 0x0020 /* Link partner supports 10 BT Half Duplex */
++
++#endif /* RTPHY_H */
+diff -urN linux-mips/include/linux/raid/md_p.h mips-linux-2.4.25/include/linux/raid/md_p.h
+--- linux-mips/include/linux/raid/md_p.h 2005-12-24 15:12:07.189098448 +0000
++++ mips-linux-2.4.25/include/linux/raid/md_p.h 2005-12-30 17:28:10.345721232 +0000
+@@ -151,10 +151,12 @@
+ */
+ mdp_disk_t disks[MD_SB_DISKS];
+
++#if MD_SB_RESERVED_WORDS
+ /*
+ * Reserved
+ */
+ __u32 reserved[MD_SB_RESERVED_WORDS];
++#endif
+
+ /*
+ * Active descriptor
diff --git a/target/linux/ar7-2.4/Config.in b/target/linux/ar7-2.4/Config.in
new file mode 100644
index 0000000000..57d06c01b5
--- /dev/null
+++ b/target/linux/ar7-2.4/Config.in
@@ -0,0 +1,29 @@
+config PACKAGE_KMOD_CPMAC
+ prompt "kmod-cpmac........................ AR7 CPMAC Network Driver"
+ tristate
+ default y
+ depends LINUX_2_4_AR7
+ help
+ Driver for the AR7 CPMAC network chip
+
+config PACKAGE_KMOD_SANGAM_ATM_A
+ prompt "kmod-sangam-atm-annex-a........... AR7 Sangam ADSL Driver (Annex A)"
+ tristate
+ default m
+ depends LINUX_2_4_AR7
+ select PACKAGE_KMOD_ATM
+ help
+ ATM driver for the Sangam ADSL chip on AR7
+ Annex A version
+
+config PACKAGE_KMOD_SANGAM_ATM_B
+ prompt "kmod-sangam-atm-annex-b........... AR7 Sangam ADSL Driver (Annex B)"
+ tristate
+ default y
+ depends LINUX_2_4_AR7
+ select PACKAGE_KMOD_ATM
+ help
+ ATM driver for the Sangam ADSL chip on AR7
+ Annex B version
+
+
diff --git a/target/linux/ar7-2.4/Makefile b/target/linux/ar7-2.4/Makefile
new file mode 100644
index 0000000000..d385722e03
--- /dev/null
+++ b/target/linux/ar7-2.4/Makefile
@@ -0,0 +1,72 @@
+#
+# 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
+
+LINUX_VERSION:=2.4.32
+LINUX_RELEASE:=1
+LINUX_KERNEL_MD5SUM:=38f4d0830e95a20f4bfed17622d5557c
+
+include ./config
+include $(INCLUDE_DIR)/kernel.mk
+
+ATM_FIRMWARE_VERSION:=0.4
+ATM_FIRMWARE_DIR=sangam-atm-firmware-$(ATM_FIRMWARE_VERSION)
+
+$(eval $(call KMOD_template,SANGAM_ATM_A,sangam-atm-annex-a,\
+ $(MODULES_DIR)/kernel/drivers/atm/tiatm.o \
+,CONFIG_MIPS_SANGAM_ATM,kmod-atm,60,tiatm, \
+ $(CP) $(BUILD_DIR)/$(ATM_FIRMWARE_DIR)/ar0700xx_a.bin $$(I_SANGAM_ATM_A)/lib/modules/ar0700xx.bin \
+))
+
+$(eval $(call KMOD_template,SANGAM_ATM_B,sangam-atm-annex-b,\
+ $(MODULES_DIR)/kernel/drivers/atm/tiatm.o \
+,CONFIG_MIPS_SANGAM_ATM,kmod-atm,60,tiatm, \
+ $(CP) $(BUILD_DIR)/$(ATM_FIRMWARE_DIR)/ar0700xx_b.bin $$(I_SANGAM_ATM_B)/lib/modules/ar0700xx.bin \
+))
+
+$(eval $(call KMOD_template,CPMAC,cpmac,\
+ $(MODULES_DIR)/kernel/drivers/net/avalanche_cpmac/avalanche_cpmac.o \
+,CONFIG_MIPS_AVALANCHE_CPMAC,,10,avalanche_cpmac))
+
+include $(INCLUDE_DIR)/kernel-build.mk
+
+
+$(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked
+ [ -d ../generic-$(KERNEL)/patches ] && $(PATCH) $(LINUX_DIR) ../generic-$(KERNEL)/patches
+ [ -d ./patches ] && $(PATCH) $(LINUX_DIR) ./patches
+ @$(CP) config $(LINUX_DIR)/.config
+ touch $@
+
+
+###############################################
+# ATM firmware for the DSL modem
+###############################################
+
+DOWNLOAD_SITE=http://openwrt.org/downloads/downloads
+# extracted from netgear DG834B V1.0.5 GPL release
+ATM_FIRMWARE_FILE=$(ATM_FIRMWARE_DIR).tar.gz
+ATM_FIRMWARE_MD5SUM=8bfcb31109796502d66b11baaeb2fba6
+
+$(DL_DIR)/$(ATM_FIRMWARE_FILE):
+ $(SCRIPT_DIR)/download.pl $(DL_DIR) $(ATM_FIRMWARE_FILE) $(ATM_FIRMWARE_MD5SUM) $(DOWNLOAD_SITE)
+
+download: $(DL_DIR)/$(ATM_FIRMWARE_FILE)
+$(LINUX_DIR)/.unpacked: $(DL_DIR)/$(ATM_FIRMWARE_FILE)
+$(LINUX_DIR)/.depend_done: $(LINUX_DIR)/.drivers-unpacked
+$(LINUX_DIR)/.modules_done: $(LINUX_DIR)/.drivers-unpacked
+
+$(LINUX_DIR)/.drivers-unpacked: $(LINUX_DIR)/.unpacked
+ -mkdir -p $(BUILD_DIR)
+ zcat $(DL_DIR)/$(ATM_FIRMWARE_FILE) | tar -C $(BUILD_DIR) $(TAR_OPTIONS) -
+ touch $@
+
+linux-dirclean: drivers-clean
+
+drivers-clean: FORCE
+ rm -rf $(BUILD_DIR)/$(ATM_FIRMWARE_DIR)
+
+
diff --git a/target/linux/ar7-2.4/config b/target/linux/ar7-2.4/config
new file mode 100644
index 0000000000..5f7a1513b7
--- /dev/null
+++ b/target/linux/ar7-2.4/config
@@ -0,0 +1,1080 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+CONFIG_MIPS32=y
+# CONFIG_MIPS64 is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
+
+#
+# Machine selection
+#
+# CONFIG_ACER_PICA_61 is not set
+CONFIG_AR7=y
+# CONFIG_AR7DB is not set
+# CONFIG_AR7RD is not set
+CONFIG_AR7WRD=y
+CONFIG_AR7_CPU=150
+CONFIG_AR7_SYS=125
+CONFIG_AR7_MEMORY=0x14000000
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_FICMMP is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_HYDROGEN3 is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_COGENT_CSB250 is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_CASIO_E55 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MAGNUM_4000 is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_BIG_SUR is not set
+# CONFIG_PMC_STRETCH is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_NEC_EAGLE is not set
+# CONFIG_OLIVETTI_M700 is not set
+# CONFIG_NINO is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TANBAC_TB0226 is not set
+# CONFIG_TANBAC_TB0229 is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_IRQ_CPU=y
+CONFIG_NONCOHERENT_IO=y
+CONFIG_SWAP_IO_SPACE=y
+# CONFIG_MIPS_AU1000 is not set
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_VTAG_ICACHE is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_LLDSCD is not set
+# CONFIG_CPU_HAS_WB is not set
+CONFIG_CPU_HAS_SYNC=y
+
+#
+# General setup
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_BUILD_ELF64 is not set
+CONFIG_NET=y
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_TC is not set
+# CONFIG_MCA is not set
+# CONFIG_SBUS is not set
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+# CONFIG_PCMCIA is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_HOTPLUG_PCI_COMPAQ is not set
+# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set
+# CONFIG_HOTPLUG_PCI_PCIE is not set
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_ELF_AOUT is not set
+# CONFIG_MIPS32_COMPAT is not set
+# CONFIG_MIPS32_O32 is not set
+# CONFIG_MIPS32_N32 is not set
+# CONFIG_BINFMT_ELF32 is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_OOM_KILLER is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=squashfs,jffs2 init=/etc/preinit noinitrd"
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_CFI_B1 is not set
+CONFIG_MTD_CFI_B2=y
+# CONFIG_MTD_CFI_B4 is not set
+# CONFIG_MTD_CFI_B8 is not set
+CONFIG_MTD_CFI_I1=y
+# CONFIG_MTD_CFI_I2 is not set
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+# CONFIG_MTD_CFI_SSTSTD is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_AMDSTD is not set
+# CONFIG_MTD_SHARP is not set
+# CONFIG_MTD_JEDEC is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_AR7=y
+CONFIG_MTD_AR7_DEFAULTS=y
+CONFIG_MTD_AR7_START=0x10000000
+CONFIG_MTD_AR7_LEN=0x400000
+CONFIG_MTD_AR7_BUSWIDTH=2
+# CONFIG_MTD_PB1000 is not set
+# CONFIG_MTD_PB1500 is not set
+# CONFIG_MTD_PB1100 is not set
+# CONFIG_MTD_BOSPORUS is not set
+# CONFIG_MTD_XXS1500 is not set
+# CONFIG_MTD_MTX1 is not set
+# CONFIG_MTD_DB1X00 is not set
+# CONFIG_MTD_PB1550 is not set
+# CONFIG_MTD_HYDROGEN3 is not set
+# CONFIG_MTD_MIRAGE is not set
+# CONFIG_MTD_CSTM_MIPS_IXX is not set
+# CONFIG_MTD_OCELOT is not set
+# CONFIG_MTD_LASAT is not set
+# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PCMCIA is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_STATS is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_NAT=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_TOS=y
+# CONFIG_IP_ROUTE_VERBOSE is not set
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_FTP=y
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_IRC=y
+CONFIG_IP_NF_CT_ACCT=m
+CONFIG_IP_NF_MATCH_CONNBYTES=m
+CONFIG_IP_NF_CT_PROTO_GRE=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_MMS=m
+CONFIG_IP_NF_RTSP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_QUOTA=m
+CONFIG_IP_NF_SET=m
+CONFIG_IP_NF_SET_MAX=256
+CONFIG_IP_NF_SET_HASHSIZE=1024
+CONFIG_IP_NF_MATCH_SET=m
+CONFIG_IP_NF_TARGET_SET=m
+CONFIG_IP_NF_SET_IPMAP=m
+CONFIG_IP_NF_SET_PORTMAP=m
+CONFIG_IP_NF_SET_MACIPMAP=m
+CONFIG_IP_NF_SET_IPHASH=m
+CONFIG_IP_NF_SET_NETHASH=m
+CONFIG_IP_NF_SET_IPTREE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=y
+CONFIG_IP_NF_MATCH_MULTIPORT=y
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TIME=m
+CONFIG_IP_NF_MATCH_CONDITION=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_IPP2P=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=y
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_UNCLEAN=m
+CONFIG_IP_NF_MATCH_STRING=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_LAYER7=m
+# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
+CONFIG_IP_NF_MATCH_LAYER7_MAXDATALEN=2048
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_MIRROR=m
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_PROTO_GRE=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_MMS=m
+CONFIG_IP_NF_NAT_RTSP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=y
+CONFIG_IP_NF_NAT_FTP=y
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=y
+CONFIG_IP_NF_TARGET_IMQ=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=y
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_CONDITION=m
+CONFIG_IP6_NF_MATCH_MAC=m
+# CONFIG_IP6_NF_MATCH_RT is not set
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
+# CONFIG_IP6_NF_MATCH_AHESP is not set
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_TARGET_IMQ=m
+# CONFIG_KHTTPD is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+CONFIG_ATM=m
+# CONFIG_ATM_CLIP is not set
+# CONFIG_ATM_LANE is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_VLAN_8021Q=y
+
+#
+#
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+CONFIG_BRIDGE=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_CSZ=m
+CONFIG_NET_SCH_HFSC=m
+# CONFIG_NET_SCH_ATM is not set
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+# CONFIG_NET_SCH_NETEM is not set
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_POLICE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_IPSEC_NAT_TRAVERSAL=y
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+# CONFIG_PHONE_IXJ is not set
+# CONFIG_PHONE_IXJ_PCMCIA is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+CONFIG_SCSI=m
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_SD_EXTRA_DEVS=5
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_DEBUG_QUEUES is not set
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_MEGARAID2 is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_SATA_AHCI is not set
+# CONFIG_SCSI_SATA_SVW is not set
+# CONFIG_SCSI_ATA_PIIX is not set
+# CONFIG_SCSI_SATA_NV is not set
+# CONFIG_SCSI_SATA_QSTOR is not set
+# CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_SX4 is not set
+# CONFIG_SCSI_SATA_SIL is not set
+# CONFIG_SCSI_SATA_SIS is not set
+# CONFIG_SCSI_SATA_ULI is not set
+# CONFIG_SCSI_SATA_VIA is not set
+# CONFIG_SCSI_SATA_VITESSE is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_DMA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_BOOT is not set
+# CONFIG_FUSION_ISENSE is not set
+# CONFIG_FUSION_CTL is not set
+# CONFIG_FUSION_LAN is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_IMQ=m
+CONFIG_TUN=m
+CONFIG_NET_RANDOM=y
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MIPS_AVALANCHE_CPMAC=m
+CONFIG_MIPS_CPMAC_INIT_BUF_MALLOC=y
+CONFIG_MIPS_CPMAC_PORTS=1
+CONFIG_AVALANCHE_CPMAC_AUTO=y
+# CONFIG_AVALANCHE_LOW_CPMAC is not set
+# CONFIG_AVALANCHE_HIGH_CPMAC is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE_MPPC=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_STRIP is not set
+# CONFIG_WAVELAN is not set
+# CONFIG_ARLAN is not set
+# CONFIG_AIRONET4500 is not set
+# CONFIG_AIRONET4500_NONCS is not set
+# CONFIG_AIRONET4500_PROC is not set
+# CONFIG_HERMES is not set
+
+#
+# Prism54 PCI/PCMCIA GT/Duette Driver - 802.11(a/b/g)
+#
+# CONFIG_PRISM54 is not set
+# CONFIG_NET_WIRELESS is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+CONFIG_SHAPER=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_TCP is not set
+CONFIG_MIPS_SANGAM_ATM=m
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_UINPUT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_AR7_LED=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=128
+CONFIG_AR7_VLYNQ=y
+CONFIG_VLYNQ_CLK_LOCAL=y
+CONFIG_AR7_VLYNQ_PORTS=2
+CONFIG_AR7_ADAM2=y
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+
+#
+# Input core support is needed for gameports
+#
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_IPMI_PANIC_EVENT is not set
+# CONFIG_IPMI_DEVICE_INTERFACE is not set
+# CONFIG_IPMI_KCS is not set
+# CONFIG_IPMI_WATCHDOG is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_AR7_WDT=y
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_SCx200 is not set
+# CONFIG_SCx200_GPIO is not set
+# CONFIG_AMD_PM768 is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
+# CONFIG_DRM is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+CONFIG_EXT3_FS=m
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FAT_FS=m
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=m
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_BBC_ARMLIB is not set
+# CONFIG_JFFS2_BBC_LZO is not set
+CONFIG_JFFS2_BBC_LZARI=y
+# CONFIG_JFFS2_BBC_LZHD is not set
+# CONFIG_JFFS2_BBC_LZSS is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=m
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_SUNRPC=m
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_POSIX=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SMB_NLS is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+CONFIG_BLUEZ=m
+CONFIG_BLUEZ_L2CAP=m
+CONFIG_BLUEZ_SCO=m
+CONFIG_BLUEZ_RFCOMM=m
+CONFIG_BLUEZ_RFCOMM_TTY=y
+CONFIG_BLUEZ_BNEP=m
+CONFIG_BLUEZ_BNEP_MC_FILTER=y
+CONFIG_BLUEZ_BNEP_PROTO_FILTER=y
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BLUEZ_HCIUSB is not set
+CONFIG_BLUEZ_HCIUART=m
+CONFIG_BLUEZ_HCIUART_H4=y
+CONFIG_BLUEZ_HCIUART_BCSP=y
+CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y
+# CONFIG_BLUEZ_HCIBFUSB is not set
+# CONFIG_BLUEZ_HCIDTL1 is not set
+# CONFIG_BLUEZ_HCIBT3C is not set
+# CONFIG_BLUEZ_HCIBLUECARD is not set
+# CONFIG_BLUEZ_HCIBTUART is not set
+# CONFIG_BLUEZ_HCIVHCI is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+# CONFIG_RUNTIME_DEBUG is not set
+# CONFIG_KGDB is not set
+# CONFIG_GDB_CONSOLE is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_MIPS_UNCACHED is not set
+CONFIG_LOG_BUF_SHIFT=0
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+# CONFIG_FW_LOADER is not set
diff --git a/target/linux/ar7-2.4/patches/000-ar7_support.patch b/target/linux/ar7-2.4/patches/000-ar7_support.patch
new file mode 100644
index 0000000000..0c9c0d3028
--- /dev/null
+++ b/target/linux/ar7-2.4/patches/000-ar7_support.patch
@@ -0,0 +1,9549 @@
+diff -urN linux.old/arch/mips/Makefile linux.dev/arch/mips/Makefile
+--- linux.old/arch/mips/Makefile 2005-10-21 16:43:16.316951500 +0200
++++ linux.dev/arch/mips/Makefile 2005-11-10 01:10:45.775570250 +0100
+@@ -369,6 +369,16 @@
+ endif
+
+ #
++# Texas Instruments AR7
++#
++
++ifdef CONFIG_AR7
++LIBS += arch/mips/ar7/ar7.o
++SUBDIRS += arch/mips/ar7
++LOADADDR += 0x94020000
++endif
++
++#
+ # DECstation family
+ #
+ ifdef CONFIG_DECSTATION
+diff -urN linux.old/arch/mips/ar7/Makefile linux.dev/arch/mips/ar7/Makefile
+--- linux.old/arch/mips/ar7/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/ar7/Makefile 2005-11-10 01:13:51.443173750 +0100
+@@ -0,0 +1,14 @@
++.S.s:
++ $(CPP) $(AFLAGS) $< -o $*.s
++
++.S.o:
++ $(CC) $(AFLAGS) -c $< -o $*.o
++
++EXTRA_CFLAGS := -I$(TOPDIR)/include/asm/ar7 -DLITTLE_ENDIAN -D_LINK_KSEG0_
++O_TARGET := ar7.o
++
++obj-y := tnetd73xx_misc.o misc.o
++export-objs := misc.o irq.o init.o
++obj-y += setup.o irq.o int-handler.o reset.o init.o psp_env.o memory.o promlib.o cmdline.o
++
++include $(TOPDIR)/Rules.make
+diff -urN linux.old/arch/mips/ar7/cmdline.c linux.dev/arch/mips/ar7/cmdline.c
+--- linux.old/arch/mips/ar7/cmdline.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/ar7/cmdline.c 2005-11-10 01:14:16.372731750 +0100
+@@ -0,0 +1,88 @@
++/*
++ * Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
++ *
++ * This program is free software; you can distribute 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 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.
++ *
++ * Kernel command line creation using the prom monitor (YAMON) argc/argv.
++ */
++#include <linux/init.h>
++#include <linux/string.h>
++
++#include <asm/bootinfo.h>
++
++extern int prom_argc;
++extern int *_prom_argv;
++
++/*
++ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
++ * This macro take care of sign extension.
++ */
++#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)]))
++
++char arcs_cmdline[CL_SIZE];
++#ifdef CONFIG_CMDLINE_BOOL
++char __initdata cfg_cmdline[] = CONFIG_CMDLINE;
++#endif
++
++char * __init prom_getcmdline(void)
++{
++ return &(arcs_cmdline[0]);
++}
++
++
++void __init prom_init_cmdline(void)
++{
++ char *cp, *end;
++ int actr;
++ char *env_cmdline = prom_getenv("kernel_args");
++ size_t len;
++
++ actr = 1; /* Always ignore argv[0] */
++
++ cp = end = &(arcs_cmdline[0]);
++ end += sizeof(arcs_cmdline);
++
++ if (env_cmdline) {
++ len = strlen(env_cmdline);
++ if (len > end - cp - 1)
++ len = end - cp - 1;
++ strncpy(cp, env_cmdline, len);
++ cp += len;
++ *cp++ = ' ';
++ }
++#ifdef CONFIG_CMDLINE_BOOL
++ else {
++ len = strlen(cfg_cmdline);
++ if (len > end - cp - 1)
++ len = end - cp - 1;
++ strncpy(cp, cfg_cmdline, len);
++ cp += len;
++ *cp++ = ' ';
++ }
++#endif
++
++ while(actr < prom_argc) {
++ len = strlen(prom_argv(actr));
++ if (len > end - cp - 1)
++ break;
++ strncpy(cp, prom_argv(actr), len);
++ cp += len;
++ *cp++ = ' ';
++ actr++;
++ }
++ if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
++ --cp;
++ *cp = '\0';
++}
+diff -urN linux.old/arch/mips/ar7/init.c linux.dev/arch/mips/ar7/init.c
+--- linux.old/arch/mips/ar7/init.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/ar7/init.c 2005-11-10 01:10:45.795571500 +0100
+@@ -0,0 +1,199 @@
++/*
++ * Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
++ *
++ * This program is free software; you can distribute 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 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.
++ *
++ * PROM library initialisation code.
++ */
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++
++#include <asm/io.h>
++#include <asm/mips-boards/prom.h>
++#include <asm/mips-boards/generic.h>
++
++#include <asm/ar7/adam2_env.h>
++
++int prom_argc;
++int *_prom_argv, *_prom_envp;
++
++/* max # of Adam2 environment variables */
++#define MAX_ENV_ENTRY 80
++
++static t_env_var local_envp[MAX_ENV_ENTRY];
++static int env_type = 0;
++int init_debug = 0;
++
++unsigned int max_env_entry;
++
++extern char *prom_psp_getenv(char *envname);
++
++static inline char *prom_adam2_getenv(char *envname)
++{
++ /*
++ * Return a pointer to the given environment variable.
++ * In 64-bit mode: we're using 64-bit pointers, but all pointers
++ * in the PROM structures are only 32-bit, so we need some
++ * workarounds, if we are running in 64-bit mode.
++ */
++ int i;
++ t_env_var *env = (t_env_var *) local_envp;
++
++ if (strcmp("bootloader", envname) == 0)
++ return "Adam2";
++
++ i = strlen(envname);
++ while (env->name) {
++ if(strncmp(envname, env->name, i) == 0) {
++ return(env->val);
++ }
++ env++;
++ }
++
++ return NULL;
++}
++
++/* XXX "bootloader" won't be returned.
++ * Better make it an element of local_envp */
++static inline t_env_var *
++prom_adam2_iterenv(t_env_var *env) {
++ if (!env)
++ env = local_envp;
++ else
++ env++;
++ if (env - local_envp > MAX_ENV_ENTRY || !env->name)
++ return 0;
++ return env;
++}
++
++char *prom_getenv(char *envname)
++{
++ if (env_type == 1)
++ return prom_psp_getenv(envname);
++ else
++ return prom_adam2_getenv(envname);
++}
++
++t_env_var *
++prom_iterenv(t_env_var *last)
++{
++ if (env_type == 1)
++ return 0; /* not yet implemented */
++ return prom_adam2_iterenv(last);
++}
++
++static inline unsigned char str2hexnum(unsigned char c)
++{
++ if (c >= '0' && c <= '9')
++ return c - '0';
++ if (c >= 'a' && c <= 'f')
++ return c - 'a' + 10;
++ return 0; /* foo */
++}
++
++static inline void str2eaddr(unsigned char *ea, unsigned char *str)
++{
++ int i;
++
++ for (i = 0; i < 6; i++) {
++ unsigned char num;
++
++ if((*str == '.') || (*str == ':'))
++ str++;
++ num = str2hexnum(*str++) << 4;
++ num |= (str2hexnum(*str++));
++ ea[i] = num;
++ }
++}
++
++int get_ethernet_addr(char *ethernet_addr)
++{
++ char *ethaddr_str;
++
++ ethaddr_str = prom_getenv("ethaddr");
++ if (!ethaddr_str) {
++ printk("ethaddr not set in boot prom\n");
++ return -1;
++ }
++ str2eaddr(ethernet_addr, ethaddr_str);
++
++ if (init_debug > 1) {
++ int i;
++ printk("get_ethernet_addr: ");
++ for (i=0; i<5; i++)
++ printk("%02x:", (unsigned char)*(ethernet_addr+i));
++ printk("%02x\n", *(ethernet_addr+i));
++ }
++
++ return 0;
++}
++
++struct psbl_rec {
++ unsigned int psbl_size;
++ unsigned int env_base;
++ unsigned int env_size;
++ unsigned int ffs_base;
++ unsigned int ffs_size;
++};
++
++static const char psp_env_version[] = "TIENV0.8";
++
++int __init prom_init(int argc, char **argv, char **envp)
++{
++ int i;
++
++ t_env_var *env = (t_env_var *) envp;
++ struct psbl_rec *psbl = (struct psbl_rec *)(KSEG1ADDR(0x94000300));
++ void *psp_env = (void *)KSEG1ADDR(psbl->env_base);
++
++ prom_argc = argc;
++ _prom_argv = (int *)argv;
++ _prom_envp = (int *)envp;
++
++ if(strcmp(psp_env, psp_env_version) == 0) {
++ /* PSPBOOT */
++
++ env_type = 1;
++ _prom_envp = psp_env;
++ max_env_entry = (psbl->env_size / 16) - 1;
++ } else {
++ /* Copy what we need locally so we are not dependent on
++ * bootloader RAM. In Adam2, the environment parameters
++ * are in flash but the table that references them is in
++ * RAM
++ */
++
++ for(i=0; i < MAX_ENV_ENTRY; i++, env++) {
++ if (env->name) {
++ local_envp[i].name = env->name;
++ local_envp[i].val = env->val;
++ } else {
++ local_envp[i].name = NULL;
++ local_envp[i].val = NULL;
++ }
++ }
++ }
++
++ set_io_port_base(0);
++
++ prom_printf("\nLINUX started...\n");
++ prom_init_cmdline();
++ prom_meminit();
++
++ return 0;
++}
+diff -urN linux.old/arch/mips/ar7/int-handler.S linux.dev/arch/mips/ar7/int-handler.S
+--- linux.old/arch/mips/ar7/int-handler.S 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/ar7/int-handler.S 2005-11-10 01:12:43.938955000 +0100
+@@ -0,0 +1,63 @@
++/*
++ * Copyright 2004 PMC-Sierra Inc.
++ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
++ * Adaption for AR7: Enrik Berkhan <enrik@akk.org>
++ *
++ * First-level interrupt dispatcher for the TI AR7
++ *
++ * 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.
++ */
++#define __ASSEMBLY__
++#include <linux/config.h>
++#include <asm/asm.h>
++#include <asm/mipsregs.h>
++#include <asm/addrspace.h>
++#include <asm/regdef.h>
++#include <asm/stackframe.h>
++
++/*
++ * First level interrupt dispatcher for TI AR7 based boards
++ */
++
++ .align 5
++ NESTED(ar7IRQ, PT_SIZE, sp)
++ SAVE_ALL
++ CLI
++ .set at
++
++ mfc0 t0, CP0_CAUSE
++ mfc0 t2, CP0_STATUS
++
++ and t0, t2
++
++ andi t1, t0, STATUSF_IP2 /* hw0 hardware interrupt */
++ bnez t1, ll_hw0_irq
++
++ andi t1, t0, STATUSF_IP7 /* R4k CPU timer */
++ bnez t1, ll_timer_irq
++
++ .set reorder
++
++ /* wrong alarm or masked ... */
++ j spurious_interrupt
++ nop
++ END(ar7IRQ)
++
++ .align 5
++
++ll_hw0_irq:
++ li a0, 2
++ move a1, sp
++ jal do_IRQ
++ j ret_from_irq
++
++ll_timer_irq:
++ li a0, 7
++ move a1, sp
++ jal do_IRQ
++ j ret_from_irq
++
++
+diff -urN linux.old/arch/mips/ar7/irq.c linux.dev/arch/mips/ar7/irq.c
+--- linux.old/arch/mips/ar7/irq.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/ar7/irq.c 2005-11-10 01:12:43.938955000 +0100
+@@ -0,0 +1,427 @@
++/*
++ * Nitin Dhingra, iamnd@ti.com
++ * Copyright (C) 2002 Texas Instruments, Inc. All rights reserved.
++ *
++ * ########################################################################
++ *
++ * This program is free software; you can distribute 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 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.
++ *
++ * ########################################################################
++ *
++ * Routines for generic manipulation of the interrupts found on the Texas
++ * Instruments avalanche board
++ *
++ */
++
++#include <linux/init.h>
++#include <linux/interrupt.h>
++
++#include <asm/irq.h>
++#include <asm/mipsregs.h>
++#include <asm/ar7/ar7.h>
++#include <asm/ar7/avalanche_intc.h>
++
++#define shutdown_avalanche_irq disable_avalanche_irq
++#define mask_and_ack_avalanche_irq disable_avalanche_irq
++
++static unsigned int startup_avalanche_irq(unsigned int irq);
++static void end_avalanche_irq(unsigned int irq);
++void enable_avalanche_irq(unsigned int irq_nr);
++void disable_avalanche_irq(unsigned int irq_nr);
++void ar7_hw0_interrupt(int interrupt, void *dev, struct pt_regs *regs);
++
++static struct hw_interrupt_type avalanche_irq_type = {
++ "AR7",
++ startup_avalanche_irq,
++ shutdown_avalanche_irq,
++ enable_avalanche_irq,
++ disable_avalanche_irq,
++ mask_and_ack_avalanche_irq,
++ end_avalanche_irq,
++ NULL
++};
++
++static int ar7_irq_base;
++
++static struct irqaction ar7_hw0_action = {
++ ar7_hw0_interrupt, 0, 0, "AR7 on hw0", NULL, NULL
++};
++
++struct avalanche_ictrl_regs *avalanche_hw0_icregs; /* Interrupt control regs (primary) */
++struct avalanche_exctrl_regs *avalanche_hw0_ecregs; /* Exception control regs (secondary) */
++struct avalanche_ipace_regs *avalanche_hw0_ipaceregs;
++struct avalanche_channel_int_number *avalanche_hw0_chregs; /* Channel control registers */
++
++/*
++ This remaps interrupts to exist on other channels than the default
++ channels. essentially we can use the line # as the index for this
++ array
++ */
++
++static unsigned long line_to_channel[AVINTNUM(AVALANCHE_INT_END_PRIMARY)];
++unsigned long uni_secondary_interrupt = 0;
++
++static void end_avalanche_irq(unsigned int irq)
++{
++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
++ enable_avalanche_irq(irq);
++}
++
++void disable_avalanche_irq(unsigned int irq_nr)
++{
++ unsigned long flags;
++ unsigned long chan_nr=0;
++
++ save_and_cli(flags);
++
++ /* irq_nr represents the line number for the interrupt. We must
++ * disable the channel number associated with that line number.
++ */
++
++ if(irq_nr > AVALANCHE_INT_END_PRIMARY_REG2)
++ chan_nr = AVINTNUM(irq_nr); /*CHECK THIS ALSO*/
++ else
++ chan_nr = line_to_channel[AVINTNUM(irq_nr)];/* WE NEED A LINE TO CHANNEL MAPPING FUNCTION HERE*/
++
++ /* disable the interrupt channel bit */
++
++ /* primary interrupt #'s 0-31 */
++
++ if(chan_nr <= AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG1))
++ avalanche_hw0_icregs->intecr1 = (1 << chan_nr);
++
++ /* primary interrupt #'s 32-39 */
++
++ else if ((chan_nr <= AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG2)) &&
++ (chan_nr > AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG1)))
++ avalanche_hw0_icregs->intecr2 = (1 << (chan_nr - AVINTNUM(AVALANCHE_INT_END_SECONDARY)));
++
++ else /* secondary interrupt #'s 0-31 */
++ avalanche_hw0_ecregs->exiecr = (1 << (chan_nr - AVINTNUM(AVALANCHE_INT_END_PRIMARY)));
++
++ restore_flags(flags);
++}
++
++void enable_avalanche_irq(unsigned int irq_nr)
++{
++ unsigned long flags;
++ unsigned long chan_nr=0;
++
++ save_and_cli(flags);
++
++ /* irq_nr represents the line number for the interrupt. We must
++ * disable the channel number associated with that line number.
++ */
++
++ if(irq_nr > AVALANCHE_INT_END_PRIMARY_REG2)
++ chan_nr = AVINTNUM(irq_nr);
++ else
++ chan_nr = line_to_channel[AVINTNUM(irq_nr)];
++
++ /* enable the interrupt channel bit */
++
++ /* primary interrupt #'s 0-31 */
++ if(chan_nr <= AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG1))
++ avalanche_hw0_icregs->intesr1 = (1 << chan_nr);
++
++ /* primary interrupt #'s 32 throuth 39 */
++ else if ((chan_nr <= AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG2)) &&
++ (chan_nr > AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG1)))
++ avalanche_hw0_icregs->intesr2 = (1 << (chan_nr - AVINTNUM(AVALANCHE_INT_END_SECONDARY)));
++
++ else /* secondary interrupt #'s 0-31 */
++ avalanche_hw0_ecregs->exiesr = (1 << (chan_nr - AVINTNUM(AVALANCHE_INT_END_PRIMARY)));
++
++ restore_flags(flags);
++}
++
++static unsigned int startup_avalanche_irq(unsigned int irq)
++{
++ enable_avalanche_irq(irq);
++ return 0; /* never anything pending */
++}
++
++void __init ar7_irq_init(int base)
++{
++ int i;
++
++ avalanche_hw0_icregs = (struct avalanche_ictrl_regs *)AVALANCHE_ICTRL_REGS_BASE;
++ avalanche_hw0_ecregs = (struct avalanche_exctrl_regs *)AVALANCHE_ECTRL_REGS_BASE;
++ avalanche_hw0_ipaceregs = (struct avalanche_ipace_regs *)AVALANCHE_IPACE_REGS_BASE;
++ avalanche_hw0_chregs = (struct avalanche_channel_int_number *)AVALANCHE_CHCTRL_REGS_BASE;
++
++ /* Disable interrupts and clear pending
++ */
++
++ avalanche_hw0_icregs->intecr1 = 0xffffffff; /* disable interrupts 0:31 */
++ avalanche_hw0_icregs->intcr1 = 0xffffffff; /* clear interrupts 0:31 */
++ avalanche_hw0_icregs->intecr2 = 0xff; /* disable interrupts 32:39 */
++ avalanche_hw0_icregs->intcr2 = 0xff; /* clear interrupts 32:39 */
++ avalanche_hw0_ecregs->exiecr = 0xffffffff; /* disable secondary interrupts 0:31 */
++ avalanche_hw0_ecregs->excr = 0xffffffff; /* clear secondary interrupts 0:31 */
++
++
++ // avalanche_hw0_ipaceregs->ipacep = (2*get_avalanche_vbus_freq()/1000000)*4;
++ /* hack for speeding up the pacing. */
++ printk("the pacing pre-scalar has been set as 600.\n");
++ avalanche_hw0_ipaceregs->ipacep = 600;
++ /* Channel to line mapping, Line to Channel mapping */
++
++ for(i = 0; i < 40; i++)
++ avalanche_int_set(i,i);
++
++ ar7_irq_base = base;
++ for (i = base; i <= base+40; i++)
++ {
++ irq_desc[i].status = IRQ_DISABLED;
++ irq_desc[i].action = 0;
++ irq_desc[i].depth = 1;
++ irq_desc[i].handler = &avalanche_irq_type;
++ }
++
++ setup_irq(2, &ar7_hw0_action);
++ set_c0_status(IE_IRQ0);
++
++ return;
++}
++
++void ar7_hw0_interrupt(int interrupt, void *dev, struct pt_regs *regs)
++{
++ int irq;
++ unsigned long int_line_number, status;
++ int i, chan_nr = 0;
++
++ int_line_number = ((avalanche_hw0_icregs->pintir >> 16) & 0x3F);
++ chan_nr = ((avalanche_hw0_icregs->pintir) & 0x3F);
++
++ if(chan_nr < 32) /* primary 0-31 */
++ {
++ if( chan_nr != uni_secondary_interrupt)
++ avalanche_hw0_icregs->intcr1 = (1<<chan_nr);
++
++ }
++
++ if((chan_nr < 40) && (chan_nr > 31)) /* primary 32-39 */
++ {
++ avalanche_hw0_icregs->intcr2 = (1<<(chan_nr-32));
++ }
++
++
++ /* If the Priority Interrupt Index Register returns 40 then no
++ * interrupts are pending
++ */
++
++ if(chan_nr == 40)
++ return;
++
++ if(chan_nr == uni_secondary_interrupt) /* secondary 0-31 */
++ {
++ status = avalanche_hw0_ecregs->exsr;
++ for(i=0; i < 32; i++)
++ {
++ if (status & 1<<i)
++ {
++ /* clear secondary interrupt */
++ avalanche_hw0_ecregs->excr = 1 << i;
++ break;
++ }
++ }
++ irq = i+40;
++
++ /* clear the universal secondary interrupt */
++ avalanche_hw0_icregs->intcr1 = 1 << uni_secondary_interrupt;
++
++ }
++ else
++ irq = chan_nr;
++
++ do_IRQ(irq + ar7_irq_base, regs);
++ return;
++}
++
++void avalanche_int_set(int channel, int line)
++{
++ switch(channel)
++ {
++ case(0):
++ avalanche_hw0_chregs->cintnr0 = line;
++ break;
++ case(1):
++ avalanche_hw0_chregs->cintnr1 = line;
++ break;
++ case(2):
++ avalanche_hw0_chregs->cintnr2 = line;
++ break;
++ case(3):
++ avalanche_hw0_chregs->cintnr3 = line;
++ break;
++ case(4):
++ avalanche_hw0_chregs->cintnr4 = line;
++ break;
++ case(5):
++ avalanche_hw0_chregs->cintnr5 = line;
++ break;
++ case(6):
++ avalanche_hw0_chregs->cintnr6 = line;
++ break;
++ case(7):
++ avalanche_hw0_chregs->cintnr7 = line;
++ break;
++ case(8):
++ avalanche_hw0_chregs->cintnr8 = line;
++ break;
++ case(9):
++ avalanche_hw0_chregs->cintnr9 = line;
++ break;
++ case(10):
++ avalanche_hw0_chregs->cintnr10 = line;
++ break;
++ case(11):
++ avalanche_hw0_chregs->cintnr11 = line;
++ break;
++ case(12):
++ avalanche_hw0_chregs->cintnr12 = line;
++ break;
++ case(13):
++ avalanche_hw0_chregs->cintnr13 = line;
++ break;
++ case(14):
++ avalanche_hw0_chregs->cintnr14 = line;
++ break;
++ case(15):
++ avalanche_hw0_chregs->cintnr15 = line;
++ break;
++ case(16):
++ avalanche_hw0_chregs->cintnr16 = line;
++ break;
++ case(17):
++ avalanche_hw0_chregs->cintnr17 = line;
++ break;
++ case(18):
++ avalanche_hw0_chregs->cintnr18 = line;
++ break;
++ case(19):
++ avalanche_hw0_chregs->cintnr19 = line;
++ break;
++ case(20):
++ avalanche_hw0_chregs->cintnr20 = line;
++ break;
++ case(21):
++ avalanche_hw0_chregs->cintnr21 = line;
++ break;
++ case(22):
++ avalanche_hw0_chregs->cintnr22 = line;
++ break;
++ case(23):
++ avalanche_hw0_chregs->cintnr23 = line;
++ break;
++ case(24):
++ avalanche_hw0_chregs->cintnr24 = line;
++ break;
++ case(25):
++ avalanche_hw0_chregs->cintnr25 = line;
++ break;
++ case(26):
++ avalanche_hw0_chregs->cintnr26 = line;
++ break;
++ case(27):
++ avalanche_hw0_chregs->cintnr27 = line;
++ break;
++ case(28):
++ avalanche_hw0_chregs->cintnr28 = line;
++ break;
++ case(29):
++ avalanche_hw0_chregs->cintnr29 = line;
++ break;
++ case(30):
++ avalanche_hw0_chregs->cintnr30 = line;
++ break;
++ case(31):
++ avalanche_hw0_chregs->cintnr31 = line;
++ break;
++ case(32):
++ avalanche_hw0_chregs->cintnr32 = line;
++ break;
++ case(33):
++ avalanche_hw0_chregs->cintnr33 = line;
++ break;
++ case(34):
++ avalanche_hw0_chregs->cintnr34 = line;
++ break;
++ case(35):
++ avalanche_hw0_chregs->cintnr35 = line;
++ break;
++ case(36):
++ avalanche_hw0_chregs->cintnr36 = line;
++ break;
++ case(37):
++ avalanche_hw0_chregs->cintnr37 = line;
++ break;
++ case(38):
++ avalanche_hw0_chregs->cintnr38 = line;
++ break;
++ case(39):
++ avalanche_hw0_chregs->cintnr39 = line;
++ break;
++ default:
++ printk("Error: Unknown Avalanche interrupt channel\n");
++ }
++
++ line_to_channel[line] = channel; /* Suraj check */
++
++ if (channel == UNIFIED_SECONDARY_INTERRUPT)
++ uni_secondary_interrupt = line;
++
++}
++
++
++#define AVALANCHE_MAX_PACING_BLK 3
++#define AVALANCHE_PACING_LOW_VAL 2
++#define AVALANCHE_PACING_HIGH_VAL 63
++
++int avalanche_request_pacing(int irq_nr, unsigned int blk_num,
++ unsigned int pace_value)
++{
++ unsigned int blk_offset;
++ unsigned long flags;
++
++ if(irq_nr < MIPS_EXCEPTION_OFFSET &&
++ irq_nr >= AVALANCHE_INT_END_PRIMARY)
++ return (0);
++
++ if(blk_num > AVALANCHE_MAX_PACING_BLK)
++ return(-1);
++
++ if(pace_value > AVALANCHE_PACING_HIGH_VAL &&
++ pace_value < AVALANCHE_PACING_LOW_VAL)
++ return(-1);
++
++ blk_offset = blk_num*8;
++
++ save_and_cli(flags);
++
++ /* disable the interrupt pacing, if enabled previously */
++ avalanche_hw0_ipaceregs->ipacemax &= ~(0xff << blk_offset);
++
++ /* clear the pacing map */
++ avalanche_hw0_ipaceregs->ipacemap &= ~(0xff << blk_offset);
++
++ /* setup the new values */
++ avalanche_hw0_ipaceregs->ipacemap |= ((AVINTNUM(irq_nr)) << blk_offset);
++ avalanche_hw0_ipaceregs->ipacemax |= ((0x80 | pace_value) << blk_offset);
++
++ restore_flags(flags);
++
++ return(0);
++}
+diff -urN linux.old/arch/mips/ar7/memory.c linux.dev/arch/mips/ar7/memory.c
+--- linux.old/arch/mips/ar7/memory.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/ar7/memory.c 2005-11-10 01:14:16.372731750 +0100
+@@ -0,0 +1,103 @@
++/*
++ * Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
++ *
++ * ########################################################################
++ *
++ * This program is free software; you can distribute 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 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/config.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/bootmem.h>
++
++#include <asm/bootinfo.h>
++#include <asm/page.h>
++#include <asm/mips-boards/prom.h>
++
++extern char _ftext;
++extern int preserve_adam2;
++
++void __init prom_meminit(void)
++{
++ char *memsize_str;
++ unsigned long memsize, adam2size;
++
++ /* assume block before kernel is used by bootloader */
++ adam2size = __pa(&_ftext) - PHYS_OFFSET;
++
++ memsize_str = prom_getenv("memsize");
++ if (!memsize_str) {
++ memsize = 0x02000000;
++ } else {
++ memsize = simple_strtol(memsize_str, NULL, 0);
++ }
++
++#if 0
++ add_memory_region(0x00000000, PHYS_OFFSET, BOOT_MEM_RESERVED);
++#endif
++ add_memory_region(PHYS_OFFSET, adam2size, BOOT_MEM_ROM_DATA);
++ add_memory_region(PHYS_OFFSET+adam2size, memsize-adam2size,
++ BOOT_MEM_RAM);
++}
++
++unsigned long __init prom_free_prom_memory (void)
++{
++ int i;
++ unsigned long freed = 0;
++ unsigned long addr;
++
++ if (preserve_adam2) {
++ char *firstfree_str = prom_getenv("firstfreeaddress");
++ unsigned long firstfree = 0;
++
++ if (firstfree_str)
++ firstfree = simple_strtol(firstfree_str, NULL, 0);
++
++ if (firstfree && firstfree < (unsigned long)&_ftext) {
++ printk("Preserving ADAM2 memory.\n");
++ } else if (firstfree) {
++ printk("Can't preserve ADAM2 memory, "
++ "firstfreeaddress = %08lx.\n", firstfree);
++ preserve_adam2 = 0;
++ } else {
++ printk("Can't preserve ADAM2 memory, "
++ "firstfreeaddress unknown!\n");
++ preserve_adam2 = 0;
++ }
++ }
++
++ if (!preserve_adam2) {
++ for (i = 0; i < boot_mem_map.nr_map; i++) {
++ if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
++ continue;
++
++ addr = boot_mem_map.map[i].addr;
++ while (addr < boot_mem_map.map[i].addr
++ + boot_mem_map.map[i].size) {
++ ClearPageReserved(virt_to_page(__va(addr)));
++ set_page_count(virt_to_page(__va(addr)), 1);
++ free_page((unsigned long)__va(addr));
++ addr += PAGE_SIZE;
++ freed += PAGE_SIZE;
++ }
++ }
++ printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
++ }
++ return freed >> PAGE_SHIFT;
++}
+diff -urN linux.old/arch/mips/ar7/misc.c linux.dev/arch/mips/ar7/misc.c
+--- linux.old/arch/mips/ar7/misc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/ar7/misc.c 2005-11-10 01:12:43.946955500 +0100
+@@ -0,0 +1,322 @@
++#include <asm/ar7/sangam.h>
++#include <asm/ar7/avalanche_misc.h>
++#include <linux/module.h>
++#include <linux/spinlock.h>
++
++#define TRUE 1
++
++static unsigned int avalanche_vbus_freq;
++
++REMOTE_VLYNQ_DEV_RESET_CTRL_FN p_remote_vlynq_dev_reset_ctrl = NULL;
++
++/*****************************************************************************
++ * Reset Control Module.
++ *****************************************************************************/
++void avalanche_reset_ctrl(unsigned int module_reset_bit,
++ AVALANCHE_RESET_CTRL_T reset_ctrl)
++{
++ volatile unsigned int *reset_reg = (unsigned int*) AVALANCHE_RST_CTRL_PRCR;
++
++ if(module_reset_bit >= 32 && module_reset_bit < 64)
++ return;
++
++ if(module_reset_bit >= 64)
++ {
++ if(p_remote_vlynq_dev_reset_ctrl) {
++ p_remote_vlynq_dev_reset_ctrl(module_reset_bit - 64, reset_ctrl);
++ return;
++ }
++ else
++ return;
++ }
++
++ if(reset_ctrl == OUT_OF_RESET)
++ *reset_reg |= 1 << module_reset_bit;
++ else
++ *reset_reg &= ~(1 << module_reset_bit);
++ return;
++}
++
++AVALANCHE_RESET_CTRL_T avalanche_get_reset_status(unsigned int module_reset_bit)
++{
++ volatile unsigned int *reset_reg = (unsigned int*) AVALANCHE_RST_CTRL_PRCR;
++
++ return (((*reset_reg) & (1 << module_reset_bit)) ? OUT_OF_RESET : IN_RESET );
++}
++
++void avalanche_sys_reset(AVALANCHE_SYS_RST_MODE_T mode)
++{
++ volatile unsigned int *sw_reset_reg = (unsigned int*) AVALANCHE_RST_CTRL_SWRCR;
++ *sw_reset_reg = mode;
++}
++
++#define AVALANCHE_RST_CTRL_RSR_MASK 0x3
++
++AVALANCHE_SYS_RESET_STATUS_T avalanche_get_sys_last_reset_status()
++{
++ volatile unsigned int *sys_reset_status = (unsigned int*) AVALANCHE_RST_CTRL_RSR;
++
++ return ( (AVALANCHE_SYS_RESET_STATUS_T) (*sys_reset_status & AVALANCHE_RST_CTRL_RSR_MASK) );
++}
++
++
++/*****************************************************************************
++ * Power Control Module
++ *****************************************************************************/
++#define AVALANCHE_GLOBAL_POWER_DOWN_MASK 0x3FFFFFFF /* bit 31, 30 masked */
++#define AVALANCHE_GLOBAL_POWER_DOWN_BIT 30 /* shift to bit 30, 31 */
++
++
++void avalanche_power_ctrl(unsigned int module_power_bit, AVALANCHE_POWER_CTRL_T power_ctrl)
++{
++ volatile unsigned int *power_reg = (unsigned int*)AVALANCHE_POWER_CTRL_PDCR;
++
++ if (power_ctrl == POWER_CTRL_POWER_DOWN)
++ /* power down the module */
++ *power_reg |= (1 << module_power_bit);
++ else
++ /* power on the module */
++ *power_reg &= (~(1 << module_power_bit));
++}
++
++AVALANCHE_POWER_CTRL_T avalanche_get_power_status(unsigned int module_power_bit)
++{
++ volatile unsigned int *power_status_reg = (unsigned int*)AVALANCHE_POWER_CTRL_PDCR;
++
++ return (((*power_status_reg) & (1 << module_power_bit)) ? POWER_CTRL_POWER_DOWN : POWER_CTRL_POWER_UP);
++}
++
++void avalanche_set_global_power_mode(AVALANCHE_SYS_POWER_MODE_T power_mode)
++{
++ volatile unsigned int *power_status_reg = (unsigned int*)AVALANCHE_POWER_CTRL_PDCR;
++
++ *power_status_reg &= AVALANCHE_GLOBAL_POWER_DOWN_MASK;
++ *power_status_reg |= ( power_mode << AVALANCHE_GLOBAL_POWER_DOWN_BIT);
++}
++
++AVALANCHE_SYS_POWER_MODE_T avalanche_get_global_power_mode(void)
++{
++ volatile unsigned int *power_status_reg = (unsigned int*)AVALANCHE_POWER_CTRL_PDCR;
++
++ return((AVALANCHE_SYS_POWER_MODE_T) (((*power_status_reg) & (~AVALANCHE_GLOBAL_POWER_DOWN_MASK))
++ >> AVALANCHE_GLOBAL_POWER_DOWN_BIT));
++}
++
++/*****************************************************************************
++ * GPIO Control
++ *****************************************************************************/
++
++/****************************************************************************
++ * FUNCTION: avalanche_gpio_init
++ ***************************************************************************/
++void avalanche_gpio_init(void)
++{
++ spinlock_t closeLock;
++ unsigned int closeFlag;
++ volatile unsigned int *reset_reg = (unsigned int*) AVALANCHE_RST_CTRL_PRCR;
++ spin_lock_irqsave(&closeLock, closeFlag);
++ *reset_reg |= (1 << AVALANCHE_GPIO_RESET_BIT);
++ spin_unlock_irqrestore(&closeLock, closeFlag);
++}
++
++/****************************************************************************
++ * FUNCTION: avalanche_gpio_ctrl
++ ***************************************************************************/
++int avalanche_gpio_ctrl(unsigned int gpio_pin,
++ AVALANCHE_GPIO_PIN_MODE_T pin_mode,
++ AVALANCHE_GPIO_PIN_DIRECTION_T pin_direction)
++{
++ spinlock_t closeLock;
++ unsigned int closeFlag;
++ volatile unsigned int *gpio_ctrl = (unsigned int*)AVALANCHE_GPIO_ENBL;
++
++ if(gpio_pin >= 32)
++ return(-1);
++
++ spin_lock_irqsave(&closeLock, closeFlag);
++
++ if(pin_mode == GPIO_PIN)
++ {
++ *gpio_ctrl |= (1 << gpio_pin);
++
++ gpio_ctrl = (unsigned int*)AVALANCHE_GPIO_DIR;
++
++ if(pin_direction == GPIO_INPUT_PIN)
++ *gpio_ctrl |= (1 << gpio_pin);
++ else
++ *gpio_ctrl &= ~(1 << gpio_pin);
++ }
++ else /* FUNCTIONAL PIN */
++ {
++ *gpio_ctrl &= ~(1 << gpio_pin);
++ }
++
++ spin_unlock_irqrestore(&closeLock, closeFlag);
++
++ return (0);
++}
++
++/****************************************************************************
++ * FUNCTION: avalanche_gpio_out
++ ***************************************************************************/
++int avalanche_gpio_out_bit(unsigned int gpio_pin, int value)
++{
++ spinlock_t closeLock;
++ unsigned int closeFlag;
++ volatile unsigned int *gpio_out = (unsigned int*) AVALANCHE_GPIO_DATA_OUT;
++
++ if(gpio_pin >= 32)
++ return(-1);
++
++ spin_lock_irqsave(&closeLock, closeFlag);
++ if(value == TRUE)
++ *gpio_out |= 1 << gpio_pin;
++ else
++ *gpio_out &= ~(1 << gpio_pin);
++ spin_unlock_irqrestore(&closeLock, closeFlag);
++
++ return(0);
++}
++
++/****************************************************************************
++ * FUNCTION: avalanche_gpio_in
++ ***************************************************************************/
++int avalanche_gpio_in_bit(unsigned int gpio_pin)
++{
++ spinlock_t closeLock;
++ unsigned int closeFlag;
++ volatile unsigned int *gpio_in = (unsigned int*) AVALANCHE_GPIO_DATA_IN;
++ int ret_val = 0;
++
++ if(gpio_pin >= 32)
++ return(-1);
++
++ spin_lock_irqsave(&closeLock, closeFlag);
++ ret_val = ((*gpio_in) & (1 << gpio_pin));
++ spin_unlock_irqrestore(&closeLock, closeFlag);
++
++ return (ret_val);
++}
++
++/****************************************************************************
++ * FUNCTION: avalanche_gpio_out_val
++ ***************************************************************************/
++int avalanche_gpio_out_value(unsigned int out_val, unsigned int out_mask,
++ unsigned int reg_index)
++{
++ spinlock_t closeLock;
++ unsigned int closeFlag;
++ volatile unsigned int *gpio_out = (unsigned int*) AVALANCHE_GPIO_DATA_OUT;
++
++ if(reg_index > 0)
++ return(-1);
++
++ spin_lock_irqsave(&closeLock, closeFlag);
++ *gpio_out &= ~out_mask;
++ *gpio_out |= out_val;
++ spin_unlock_irqrestore(&closeLock, closeFlag);
++
++ return(0);
++}
++
++/****************************************************************************
++ * FUNCTION: avalanche_gpio_in_value
++ ***************************************************************************/
++int avalanche_gpio_in_value(unsigned int* in_val, unsigned int reg_index)
++{
++ spinlock_t closeLock;
++ unsigned int closeFlag;
++ volatile unsigned int *gpio_in = (unsigned int*) AVALANCHE_GPIO_DATA_IN;
++
++ if(reg_index > 0)
++ return(-1);
++
++ spin_lock_irqsave(&closeLock, closeFlag);
++ *in_val = *gpio_in;
++ spin_unlock_irqrestore(&closeLock, closeFlag);
++
++ return (0);
++}
++
++/***********************************************************************
++ *
++ * Wakeup Control Module for TNETV1050 Communication Processor
++ *
++ ***********************************************************************/
++
++#define AVALANCHE_WAKEUP_POLARITY_BIT 16
++
++void avalanche_wakeup_ctrl(AVALANCHE_WAKEUP_INTERRUPT_T wakeup_int,
++ AVALANCHE_WAKEUP_CTRL_T wakeup_ctrl,
++ AVALANCHE_WAKEUP_POLARITY_T wakeup_polarity)
++{
++ volatile unsigned int *wakeup_status_reg = (unsigned int*) AVALANCHE_WAKEUP_CTRL_WKCR;
++
++ /* enable/disable */
++ if (wakeup_ctrl == WAKEUP_ENABLED)
++ /* enable wakeup */
++ *wakeup_status_reg |= wakeup_int;
++ else
++ /* disable wakeup */
++ *wakeup_status_reg &= (~wakeup_int);
++
++ /* set polarity */
++ if (wakeup_polarity == WAKEUP_ACTIVE_LOW)
++ *wakeup_status_reg |= (wakeup_int << AVALANCHE_WAKEUP_POLARITY_BIT);
++ else
++ *wakeup_status_reg &= ~(wakeup_int << AVALANCHE_WAKEUP_POLARITY_BIT);
++}
++
++void avalanche_set_vbus_freq(unsigned int new_vbus_freq)
++{
++ avalanche_vbus_freq = new_vbus_freq;
++}
++
++unsigned int avalanche_get_vbus_freq()
++{
++ return(avalanche_vbus_freq);
++}
++
++unsigned int avalanche_get_chip_version_info()
++{
++ return(*(volatile unsigned int*)AVALANCHE_CVR);
++}
++
++SET_MDIX_ON_CHIP_FN_T p_set_mdix_on_chip_fn = NULL;
++
++int avalanche_set_mdix_on_chip(unsigned int base_addr, unsigned int operation)
++{
++ if(p_set_mdix_on_chip_fn)
++ return (p_set_mdix_on_chip_fn(base_addr, operation));
++ else
++ return(-1);
++}
++
++unsigned int avalanche_is_mdix_on_chip(void)
++{
++ return(p_set_mdix_on_chip_fn ? 1:0);
++}
++
++EXPORT_SYMBOL(avalanche_reset_ctrl);
++EXPORT_SYMBOL(avalanche_get_reset_status);
++EXPORT_SYMBOL(avalanche_sys_reset);
++EXPORT_SYMBOL(avalanche_get_sys_last_reset_status);
++EXPORT_SYMBOL(avalanche_power_ctrl);
++EXPORT_SYMBOL(avalanche_get_power_status);
++EXPORT_SYMBOL(avalanche_set_global_power_mode);
++EXPORT_SYMBOL(avalanche_get_global_power_mode);
++EXPORT_SYMBOL(avalanche_set_mdix_on_chip);
++EXPORT_SYMBOL(avalanche_is_mdix_on_chip);
++
++EXPORT_SYMBOL(avalanche_gpio_init);
++EXPORT_SYMBOL(avalanche_gpio_ctrl);
++EXPORT_SYMBOL(avalanche_gpio_out_bit);
++EXPORT_SYMBOL(avalanche_gpio_in_bit);
++EXPORT_SYMBOL(avalanche_gpio_out_value);
++EXPORT_SYMBOL(avalanche_gpio_in_value);
++
++EXPORT_SYMBOL(avalanche_set_vbus_freq);
++EXPORT_SYMBOL(avalanche_get_vbus_freq);
++
++EXPORT_SYMBOL(avalanche_get_chip_version_info);
++
+diff -urN linux.old/arch/mips/ar7/platform.h linux.dev/arch/mips/ar7/platform.h
+--- linux.old/arch/mips/ar7/platform.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/ar7/platform.h 2005-11-10 01:10:45.799571750 +0100
+@@ -0,0 +1,65 @@
++#ifndef _PLATFORM_H_
++#define _PLATFORM_H_
++
++#include <linux/config.h>
++
++
++/* Important: The definition of ENV_SPACE_SIZE should match with that in
++ * PSPBoot. (/psp_boot/inc/psbl/env.h)
++ */
++#ifdef CONFIG_MIPS_AVALANCHE_TICFG
++#define ENV_SPACE_SIZE (10 * 1024)
++#endif
++
++#ifdef CONFIG_MIPS_TNETV1050SDB
++#define TNETV1050SDB
++#define DUAL_FLASH
++#endif
++
++#ifdef CONFIG_MIPS_AR7DB
++#define TNETD73XX_BOARD
++#define AR7DB
++#endif
++
++#ifdef CONFIG_MIPS_AR7RD
++#define TNETD73XX_BOARD
++#define AR7RD
++#endif
++
++#ifdef CONFIG_AR7WRD
++#define TNETD73XX_BOARD
++#define AR7WRD
++#endif
++
++#ifdef CONFIG_MIPS_AR7VWI
++#define TNETD73XX_BOARD
++#define AR7VWi
++#endif
++
++/* Merging from the DEV_DSL-PSPL4.3.2.7_Patch release. */
++#ifdef CONFIG_MIPS_AR7VW
++#define TNETD73XX_BOARD
++#define AR7WRD
++#endif
++
++#ifdef CONFIG_MIPS_AR7WI
++#define TNETD73XX_BOARD
++#define AR7Wi
++#endif
++
++#ifdef CONFIG_MIPS_AR7V
++#define TNETD73XX_BOARD
++#define AR7V
++#endif
++
++#ifdef CONFIG_MIPS_AR7V
++#define TNETD73XX_BOARD
++#define AR7V
++#endif
++
++#ifdef CONFIG_MIPS_WA1130
++#define AVALANCHE
++#define WLAN
++#endif
++
++#endif
+diff -urN linux.old/arch/mips/ar7/promlib.c linux.dev/arch/mips/ar7/promlib.c
+--- linux.old/arch/mips/ar7/promlib.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/ar7/promlib.c 2005-11-10 01:14:16.372731750 +0100
+@@ -0,0 +1,48 @@
++/*
++ * Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
++ *
++ * This program is free software; you can distribute 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 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.
++ *
++ * Putting things on the screen/serial line using Adam2 facilities.
++ */
++
++#include <linux/types.h>
++#include <asm/addrspace.h>
++
++#define AVALANCHE_YAMON_FUNCTION_BASE (KSEG1ADDR(0x10000500))
++#define AVALANCHE_YAMON_PROM_PRINT_COUNT_ADDR \
++ (AVALANCHE_YAMON_FUNCTION_BASE + 1 * 0x4)
++#define AVALANCHE_YAMON_PROM_EXIT \
++ (AVALANCHE_YAMON_FUNCTION_BASE + 8 * 0x4)
++
++void prom_putchar(char c)
++{
++ static char buf[1];
++ void (*prom_print_str)(unsigned int dummy, char *s, int len) =
++ (void *)(*(uint32_t *)AVALANCHE_YAMON_PROM_PRINT_COUNT_ADDR);
++
++ buf[0] = c;
++ prom_print_str(1, buf, 1);
++ return;
++}
++
++void adam2_exit(int retval)
++{
++ void (*yamon_exit)(int retval) =
++ (void *)(*(uint32_t *)AVALANCHE_YAMON_PROM_EXIT);
++
++ yamon_exit(retval);
++ return;
++}
+diff -urN linux.old/arch/mips/ar7/psp_env.c linux.dev/arch/mips/ar7/psp_env.c
+--- linux.old/arch/mips/ar7/psp_env.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/ar7/psp_env.c 2005-11-10 01:10:45.799571750 +0100
+@@ -0,0 +1,350 @@
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <asm/io.h>
++
++#include "platform.h"
++
++#define ENV_CELL_SIZE 16
++
++/* control field decode */
++#define ENV_GARBAGE_BIT 0x01 /* Env is garbage if this bit is off */
++#define ENV_DYNAMIC_BIT 0x02 /* Env is dynamic if this bit is off */
++
++#define ENV_CTRL_MASK 0x03
++#define ENV_PREFINED (ENV_GARBAGE_BIT | ENV_DYNAMIC_BIT)
++#define ENV_DYNAMIC (ENV_GARBAGE_BIT)
++
++struct env_variable {
++ unsigned char varNum;
++ unsigned char ctrl;
++ unsigned short chksum;
++ unsigned char numCells;
++ unsigned char data[ENV_CELL_SIZE - 5]; /* The data section starts
++ * here, continues for
++ * numCells.
++ */
++};
++
++extern unsigned int max_env_entry;
++
++/* Internal macros */
++#define get_next_block(var) ((struct env_variable *)( (char*)(var) + (var)->numCells * ENV_CELL_SIZE))
++
++typedef enum ENV_VARS {
++ env_vars_start = 0,
++ CPUFREQ,
++ MEMSZ,
++ FLASHSZ,
++ MODETTY0,
++ MODETTY1,
++ PROMPT,
++ BOOTCFG,
++ HWA_0,
++#if !defined (AVALANCHE) || defined(TNETC401B)
++ HWA_1,
++#endif
++#if !defined(TNETV1020_BOARD)
++ HWA_RNDIS,
++#endif
++#if defined (TNETD73XX_BOARD)
++ HWA_3,
++#endif
++ IPA,
++ IPA_SVR,
++ BLINE_MAC0,
++#if !defined (AVALANCHE) || defined(TNETC401B)
++ BLINE_MAC1,
++#endif
++#if !defined(TNETV1020_BOARD)
++ BLINE_RNDIS,
++#endif
++#if defined (TNETD73XX_BOARD)
++ BLINE_ATM,
++#endif
++#if !defined(TNETV1020_BOARD)
++ USB_PID,
++ USB_VID,
++ USB_EPPOLLI,
++#endif
++ IPA_GATEWAY,
++ SUBNET_MASK,
++#if defined (TNETV1050_BOARD)
++ BLINE_ESWITCH,
++#endif
++#if !defined(TNETV1020_BOARD)
++ USB_SERIAL,
++ HWA_HRNDIS, /* Host (PC) side RNDIS address */
++#endif
++ REMOTE_USER,
++ REMOTE_PASS,
++ REMOTE_DIR,
++ SYSFREQ,
++ LINK_TIMEOUT,
++#ifndef AVALANCHE /* Avalanche boards use only one mac port */
++ MAC_PORT,
++#endif
++ PATH,
++ HOSTNAME,
++#ifdef WLAN
++ HW_REV_MAJOR,
++ HW_REV_MINOR,
++ HW_PATCH,
++ SW_PATCH,
++ SERIAL_NUMBER,
++#endif
++ TFTPCFG,
++#if defined (TNETV1050_BOARD)
++ HWA_ESWITCH,
++#endif
++ /*
++ * Add new env variables here.
++ * NOTE: New environment variables should always be placed at the end, ie
++ * just before env_vars_end.
++ */
++
++ env_vars_end
++} ENV_VARS;
++
++
++struct env_description {
++ ENV_VARS idx;
++ char *nm;
++ char *alias;
++};
++
++#define ENVSTR(x) #x
++#define _ENV_ENTRY(x) {.idx = x, .nm = ENVSTR(x), .alias = NULL}
++
++struct env_description env_ns[] = {
++ _ENV_ENTRY(env_vars_start), /* start. */
++ _ENV_ENTRY(CPUFREQ),
++ _ENV_ENTRY(MEMSZ),
++ _ENV_ENTRY(FLASHSZ),
++ _ENV_ENTRY(MODETTY0),
++ _ENV_ENTRY(MODETTY1),
++ _ENV_ENTRY(PROMPT),
++ _ENV_ENTRY(BOOTCFG),
++ _ENV_ENTRY(HWA_0),
++#if !defined (AVALANCHE) || defined(TNETC401B)
++ _ENV_ENTRY(HWA_1),
++#endif
++#if !defined(TNETV1020_BOARD)
++ _ENV_ENTRY(HWA_RNDIS),
++#endif
++#if defined (TNETD73XX_BOARD)
++ _ENV_ENTRY(HWA_3),
++#endif
++ _ENV_ENTRY(IPA),
++ _ENV_ENTRY(IPA_SVR),
++ _ENV_ENTRY(IPA_GATEWAY),
++ _ENV_ENTRY(SUBNET_MASK),
++ _ENV_ENTRY(BLINE_MAC0),
++#if !defined (AVALANCHE) || defined(TNETC401B)
++ _ENV_ENTRY(BLINE_MAC1),
++#endif
++#if !defined(TNETV1020_BOARD)
++ _ENV_ENTRY(BLINE_RNDIS),
++#endif
++#if defined (TNETD73XX_BOARD)
++ _ENV_ENTRY(BLINE_ATM),
++#endif
++#if !defined(TNETV1020_BOARD)
++ _ENV_ENTRY(USB_PID),
++ _ENV_ENTRY(USB_VID),
++ _ENV_ENTRY(USB_EPPOLLI),
++#endif
++#if defined (TNETV1050_BOARD)
++ _ENV_ENTRY(BLINE_ESWITCH),
++#endif
++#if !defined(TNETV1020_BOARD)
++ _ENV_ENTRY(USB_SERIAL),
++ _ENV_ENTRY(HWA_HRNDIS),
++#endif
++ _ENV_ENTRY(REMOTE_USER),
++ _ENV_ENTRY(REMOTE_PASS),
++ _ENV_ENTRY(REMOTE_DIR),
++ _ENV_ENTRY(SYSFREQ),
++ _ENV_ENTRY(LINK_TIMEOUT),
++#ifndef AVALANCHE /* Avalanche boards use only one mac port */
++ _ENV_ENTRY(MAC_PORT),
++#endif
++ _ENV_ENTRY(PATH),
++ _ENV_ENTRY(HOSTNAME),
++#ifdef WLAN
++ _ENV_ENTRY(HW_REV_MAJOR),
++ _ENV_ENTRY(HW_REV_MINOR),
++ _ENV_ENTRY(HW_PATCH),
++ _ENV_ENTRY(SW_PATCH),
++ _ENV_ENTRY(SERIAL_NUMBER),
++#endif
++ _ENV_ENTRY(TFTPCFG),
++#if defined (TNETV1050_BOARD)
++ _ENV_ENTRY(HWA_ESWITCH),
++#endif
++ /*
++ * Add new entries below this.
++ */
++ /* Adam2 environment name alias. */
++ { .idx = IPA, .nm = "my_ipaddress" },
++ { .idx = CPUFREQ, .nm = "cpufrequency" },
++ { .idx = SYSFREQ, .nm = "sysfrequency" },
++ { .idx = HWA_0, .nm = "maca" },
++#ifndef AVALANCHE
++ { .idx = HWA_1, .nm = "macb" },
++#endif
++ { .idx = MODETTY0, .nm = "modetty0" },
++ { .idx = MODETTY1, .nm = "modetty1" },
++ { .idx = MEMSZ, .nm = "memsize" },
++
++ _ENV_ENTRY(env_vars_end) /* delimiter. */
++};
++
++static inline int var_to_idx(const char* var)
++{
++ int ii;
++
++ /* go over the list of pre-defined environment variables */
++ for (ii = env_vars_start; env_ns[ii].idx != env_vars_end; ii++){
++ /* check if the env variable is listed */
++ if (strcmp(env_ns[ii].nm, var) == 0) {
++ return env_ns[ii].idx;
++ }
++
++ /* if an alias is present, check if the alias matches
++ * the description
++ */
++ if (env_ns[ii].alias != NULL) {
++ if (strcmp(env_ns[ii].alias, var) == 0) {
++ return env_ns[ii].idx;
++ }
++ }
++ }
++ return 0;
++}
++
++extern int *_prom_envp;
++
++/* FIXME: reading from the flash is extremly unstable. Sometime a read returns garbage,
++ * the next read some seconds later is ok. It looks like something is hidding or
++ * overlay the flash address at 0xb0000000. Is this possible?
++ *
++ * The readb() and while() usage below is a attempt of a workarround - with limited success.
++ */
++
++static inline struct env_variable* get_var_by_number(int index)
++{
++ struct env_variable *env_var = (struct env_variable *)_prom_envp;
++ volatile unsigned char nr;
++ int i;
++
++ env_var++; /* skip signature */
++
++ i = 0;
++ nr = readb(&(env_var->varNum));
++
++ while (i < max_env_entry && nr != 0xFF) {
++ if ((env_var->ctrl & ENV_CTRL_MASK) == ENV_PREFINED) {
++ if (nr == index) {
++ return env_var;
++ }
++ }
++ i++;
++ env_var = get_next_block(env_var);
++ nr = readb(&(env_var->varNum));
++ }
++
++ return NULL;
++}
++
++static inline struct env_variable* get_var_by_name(char *var)
++{
++ struct env_variable *env_var = (struct env_variable *)_prom_envp;
++ volatile unsigned char nr;
++ int i;
++
++ env_var++; /* skip signature */
++
++ nr = readb(&(env_var->varNum));
++ i = 0;
++
++ while (i < max_env_entry && nr != 0xFF) {
++ if ((env_var->ctrl & ENV_CTRL_MASK) == ENV_DYNAMIC) {
++ if (strcmp(var, env_var->data) == 0)
++ return env_var;
++ }
++ i++;
++ env_var = get_next_block(env_var);
++ nr = readb(&(env_var->varNum));
++ }
++ return NULL;
++}
++
++static inline struct env_variable* get_var(char *var)
++{
++ int index = var_to_idx(var);
++
++ if (index)
++ return get_var_by_number(index);
++ else
++ return get_var_by_name(var);
++
++ return NULL;
++}
++
++static inline char *get_value(struct env_variable* env_var)
++{
++ unsigned char *name;
++ unsigned char *value;
++ unsigned short chksum;
++ int i;
++
++ chksum = env_var->varNum + env_var->ctrl + env_var->numCells;
++
++ if ((env_var->ctrl & ENV_CTRL_MASK) == ENV_DYNAMIC) {
++ name = env_var->data;
++ value = env_var->data + strlen(name) + 1;
++
++ for(i = 0; i < strlen(name); i++)
++ chksum += name[i];
++ } else
++ value = env_var->data;
++
++ for (i = 0; i < strlen(value); i++)
++ chksum += value[i];
++
++ chksum += env_var->chksum;
++ chksum = ~(chksum);
++
++ if(chksum != 0) {
++ return NULL;
++ }
++
++ return value;
++}
++
++struct psbl_rec {
++ unsigned int psbl_size;
++ unsigned int env_base;
++ unsigned int env_size;
++ unsigned int ffs_base;
++ unsigned int ffs_size;
++};
++
++char *prom_psp_getenv(char *envname)
++{
++ struct env_variable* env_var;
++ char *value;
++
++ if (strcmp("bootloader", envname) == 0)
++ return "PSPBoot";
++
++ if (!(env_var = get_var(envname)))
++ return NULL;
++
++ value = get_value(env_var);
++
++ return value;
++}
+diff -urN linux.old/arch/mips/ar7/reset.c linux.dev/arch/mips/ar7/reset.c
+--- linux.old/arch/mips/ar7/reset.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/ar7/reset.c 2005-11-10 01:14:16.372731750 +0100
+@@ -0,0 +1,98 @@
++/*
++ * Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
++ *
++ * ########################################################################
++ *
++ * This program is free software; you can distribute 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 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.
++ *
++ * ########################################################################
++ *
++ * Reset the AR7 boards.
++ *
++ */
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/types.h>
++
++#include <asm/mipsregs.h>
++#include <asm/reboot.h>
++#include <asm/addrspace.h>
++
++int preserve_adam2 = 1;
++
++extern void adam2_exit(int retval);
++
++static void ar7_machine_restart(char *command);
++static void ar7_machine_halt(void);
++static void ar7_machine_power_off(void);
++
++static void ar7_machine_restart(char *command)
++{
++ volatile uint32_t *softres_reg = (void *)(KSEG1ADDR(0x08611600 + 0x4));
++
++ *softres_reg = 1;
++}
++
++static void ar7_machine_halt(void)
++{
++
++ if (preserve_adam2) {
++ set_c0_status(ST0_BEV);
++ adam2_exit(0);
++ } else {
++ /* I'd like to have Alt-SysRq-b work in this state.
++ * What's missing here? The timer interrupt is still running.
++ * Why doesn't the UART work anymore? */
++ while(1) {
++ __asm__(".set\tmips3\n\t"
++ "wait\n\t"
++ ".set\tmips0");
++ }
++ }
++}
++
++static void ar7_machine_power_off(void)
++{
++ volatile uint32_t *power_reg = (void *)(KSEG1ADDR(0x08610A00));
++ uint32_t power_state = *power_reg;
++
++ /* add something to turn LEDs off? */
++
++ power_state &= ~(3 << 30);
++ power_state |= (3 << 30); /* power down */
++ *power_reg = power_state;
++
++ printk("after power down?\n");
++}
++
++void ar7_reboot_setup(void)
++{
++ _machine_restart = ar7_machine_restart;
++ _machine_halt = ar7_machine_halt;
++ _machine_power_off = ar7_machine_power_off;
++}
++
++static int __init ar7_do_preserve_adam2(char *s)
++{
++ if (!strcmp(s, "no") || !strcmp(s, "0"))
++ preserve_adam2 = 0;
++ else
++ preserve_adam2 = 1;
++ return 1;
++}
++
++__setup("adam2=", ar7_do_preserve_adam2);
+diff -urN linux.old/arch/mips/ar7/setup.c linux.dev/arch/mips/ar7/setup.c
+--- linux.old/arch/mips/ar7/setup.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/ar7/setup.c 2005-11-10 01:12:43.946955500 +0100
+@@ -0,0 +1,143 @@
++/*
++ * Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
++ *
++ * This program is free software; you can distribute 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 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/config.h>
++#include <linux/init.h>
++#include <linux/string.h>
++#include <linux/irq.h>
++
++#include <asm/processor.h>
++#include <asm/irq.h>
++#include <asm/irq_cpu.h>
++#include <asm/time.h>
++#include <asm/mipsregs.h>
++#include <asm/mips-boards/prom.h>
++
++#ifdef CONFIG_KGDB
++extern void rs_kgdb_hook(int);
++extern void breakpoint(void);
++int remote_debug = 0;
++#endif
++
++extern void ar7_reboot_setup(void);
++extern void ar7_irq_init(int);
++extern asmlinkage void ar7IRQ(void);
++
++void ar7_time_init(void)
++{
++ /* XXX runtime */
++ mips_hpt_frequency = CONFIG_AR7_CPU * 500000;
++}
++
++void ar7_timer_setup(struct irqaction *irq)
++{
++ setup_irq(7, irq);
++ set_c0_status(IE_IRQ5);
++}
++
++void __init init_IRQ(void)
++{
++ init_generic_irq();
++ mips_cpu_irq_init(0);
++ ar7_irq_init(8);
++
++ /* Now safe to set the exception vector. */
++ set_except_vector(0, ar7IRQ);
++
++#ifdef CONFIG_KGDB
++ if (remote_debug)
++ {
++ set_debug_traps();
++ breakpoint();
++ }
++#endif
++}
++
++const char *get_system_type(void)
++{
++ return "Texas Instruments AR7";
++}
++
++void __init ar7_setup(void)
++{
++#ifdef CONFIG_KGDB
++ int rs_putDebugChar(char);
++ char rs_getDebugChar(void);
++ extern int (*generic_putDebugChar)(char);
++ extern char (*generic_getDebugChar)(void);
++#endif
++ char *argptr;
++#ifdef CONFIG_SERIAL_CONSOLE
++ argptr = prom_getcmdline();
++ if ((argptr = strstr(argptr, "console=")) == NULL) {
++ char console[20];
++ char *s;
++ int i = 0;
++
++ s = prom_getenv("modetty0");
++ strcpy(console, "38400");
++
++ if (s != NULL) {
++ while (s[i] >= '0' && s[i] <= '9')
++ i++;
++
++ if (i > 0) {
++ strncpy(console, s, i);
++ console[i] = 0;
++ }
++ }
++
++ argptr = prom_getcmdline();
++ strcat(argptr, " console=ttyS0,");
++ strcat(argptr, console);
++ }
++#endif
++
++#ifdef CONFIG_KGDB
++ argptr = prom_getcmdline();
++ if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
++ int line;
++ argptr += strlen("kgdb=ttyS");
++ if (*argptr != '0' && *argptr != '1')
++ printk("KGDB: Uknown serial line /dev/ttyS%c, "
++ "falling back to /dev/ttyS1\n", *argptr);
++ line = *argptr == '0' ? 0 : 1;
++ printk("KGDB: Using serial line /dev/ttyS%d for session\n",
++ line ? 1 : 0);
++
++ rs_kgdb_hook(line);
++ generic_putDebugChar = rs_putDebugChar;
++ generic_getDebugChar = rs_getDebugChar;
++
++ prom_printf("KGDB: Using serial line /dev/ttyS%d for session, "
++ "please connect your debugger\n", line ? 1 : 0);
++
++ remote_debug = 1;
++ /* Breakpoints are in init_IRQ() */
++ }
++#endif
++
++ argptr = prom_getcmdline();
++ if ((argptr = strstr(argptr, "nofpu")) != NULL)
++ cpu_data[0].options &= ~MIPS_CPU_FPU;
++
++ ar7_reboot_setup();
++
++ board_time_init = ar7_time_init;
++ board_timer_setup = ar7_timer_setup;
++}
+diff -urN linux.old/arch/mips/ar7/tnetd73xx_misc.c linux.dev/arch/mips/ar7/tnetd73xx_misc.c
+--- linux.old/arch/mips/ar7/tnetd73xx_misc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/ar7/tnetd73xx_misc.c 2005-11-10 01:12:43.946955500 +0100
+@@ -0,0 +1,921 @@
++/******************************************************************************
++ * FILE PURPOSE: TNETD73xx Misc modules API Source
++ ******************************************************************************
++ * FILE NAME: tnetd73xx_misc.c
++ *
++ * DESCRIPTION: Clock Control, Reset Control, Power Management, GPIO
++ * FSER Modules API
++ * As per TNETD73xx specifications
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - Sharath Kumar PSP TII
++ * 14 Feb 03 - Anant Gole PSP TII
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++#include <linux/types.h>
++#include <asm/ar7/tnetd73xx.h>
++#include <asm/ar7/tnetd73xx_misc.h>
++
++/* TNETD73XX Revision */
++u32 tnetd73xx_get_revision(void)
++{
++ /* Read Chip revision register - This register is from GPIO module */
++ return ( (u32) REG32_DATA(TNETD73XX_CVR));
++}
++
++/*****************************************************************************
++ * Reset Control Module
++ *****************************************************************************/
++
++
++void tnetd73xx_reset_ctrl(TNETD73XX_RESET_MODULE_T reset_module, TNETD73XX_RESET_CTRL_T reset_ctrl)
++{
++ u32 reset_status;
++
++ /* read current reset register */
++ REG32_READ(TNETD73XX_RST_CTRL_PRCR, reset_status);
++
++ if (reset_ctrl == OUT_OF_RESET)
++ {
++ /* bring module out of reset */
++ reset_status |= (1 << reset_module);
++ }
++ else
++ {
++ /* put module in reset */
++ reset_status &= (~(1 << reset_module));
++ }
++
++ /* write to the reset register */
++ REG32_WRITE(TNETD73XX_RST_CTRL_PRCR, reset_status);
++}
++
++
++TNETD73XX_RESET_CTRL_T tnetd73xx_get_reset_status (TNETD73XX_RESET_MODULE_T reset_module)
++{
++ u32 reset_status;
++
++ REG32_READ(TNETD73XX_RST_CTRL_PRCR, reset_status);
++ return ( (reset_status & (1 << reset_module)) ? OUT_OF_RESET : IN_RESET );
++}
++
++void tnetd73xx_sys_reset(TNETD73XX_SYS_RST_MODE_T mode)
++{
++ REG32_WRITE(TNETD73XX_RST_CTRL_SWRCR, mode);
++}
++
++#define TNETD73XX_RST_CTRL_RSR_MASK 0x3
++
++TNETD73XX_SYS_RESET_STATUS_T tnetd73xx_get_sys_last_reset_status()
++{
++ u32 sys_reset_status;
++
++ REG32_READ(TNETD73XX_RST_CTRL_RSR, sys_reset_status);
++
++ return ( (TNETD73XX_SYS_RESET_STATUS_T) (sys_reset_status & TNETD73XX_RST_CTRL_RSR_MASK) );
++}
++
++
++/*****************************************************************************
++ * Power Control Module
++ *****************************************************************************/
++#define TNETD73XX_GLOBAL_POWER_DOWN_MASK 0x3FFFFFFF /* bit 31, 30 masked */
++#define TNETD73XX_GLOBAL_POWER_DOWN_BIT 30 /* shift to bit 30, 31 */
++
++
++void tnetd73xx_power_ctrl(TNETD73XX_POWER_MODULE_T power_module, TNETD73XX_POWER_CTRL_T power_ctrl)
++{
++ u32 power_status;
++
++ /* read current power down control register */
++ REG32_READ(TNETD73XX_POWER_CTRL_PDCR, power_status);
++
++ if (power_ctrl == POWER_CTRL_POWER_DOWN)
++ {
++ /* power down the module */
++ power_status |= (1 << power_module);
++ }
++ else
++ {
++ /* power on the module */
++ power_status &= (~(1 << power_module));
++ }
++
++ /* write to the reset register */
++ REG32_WRITE(TNETD73XX_POWER_CTRL_PDCR, power_status);
++}
++
++TNETD73XX_POWER_CTRL_T tnetd73xx_get_pwr_status(TNETD73XX_POWER_MODULE_T power_module)
++{
++ u32 power_status;
++
++ /* read current power down control register */
++ REG32_READ(TNETD73XX_POWER_CTRL_PDCR, power_status);
++
++ return ( (power_status & (1 << power_module)) ? POWER_CTRL_POWER_DOWN : POWER_CTRL_POWER_UP );
++}
++
++void tnetd73xx_set_global_pwr_mode(TNETD73XX_SYS_POWER_MODE_T power_mode)
++{
++ u32 power_status;
++
++ /* read current power down control register */
++ REG32_READ(TNETD73XX_POWER_CTRL_PDCR, power_status);
++
++ power_status &= TNETD73XX_GLOBAL_POWER_DOWN_MASK;
++ power_status |= ( power_mode << TNETD73XX_GLOBAL_POWER_DOWN_BIT);
++
++ /* write to power down control register */
++ REG32_WRITE(TNETD73XX_POWER_CTRL_PDCR, power_status);
++}
++
++TNETD73XX_SYS_POWER_MODE_T tnetd73xx_get_global_pwr_mode()
++{
++ u32 power_status;
++
++ /* read current power down control register */
++ REG32_READ(TNETD73XX_POWER_CTRL_PDCR, power_status);
++
++ power_status &= (~TNETD73XX_GLOBAL_POWER_DOWN_MASK);
++ power_status = ( power_status >> TNETD73XX_GLOBAL_POWER_DOWN_BIT);
++
++ return ( (TNETD73XX_SYS_POWER_MODE_T) power_status );
++}
++
++
++/*****************************************************************************
++ * Wakeup Control
++ *****************************************************************************/
++
++#define TNETD73XX_WAKEUP_POLARITY_BIT 16
++
++void tnetd73xx_wakeup_ctrl(TNETD73XX_WAKEUP_INTERRUPT_T wakeup_int,
++ TNETD73XX_WAKEUP_CTRL_T wakeup_ctrl,
++ TNETD73XX_WAKEUP_POLARITY_T wakeup_polarity)
++{
++ u32 wakeup_status;
++
++ /* read the wakeup control register */
++ REG32_READ(TNETD73XX_POWER_CTRL_WKCR, wakeup_status);
++
++ /* enable/disable */
++ if (wakeup_ctrl == WAKEUP_ENABLED)
++ {
++ /* enable wakeup */
++ wakeup_status |= wakeup_int;
++ }
++ else
++ {
++ /* disable wakeup */
++ wakeup_status &= (~wakeup_int);
++ }
++
++ /* set polarity */
++ if (wakeup_polarity == WAKEUP_ACTIVE_LOW)
++ {
++ wakeup_status |= (wakeup_int << TNETD73XX_WAKEUP_POLARITY_BIT);
++ }
++ else
++ {
++ wakeup_status &= ~(wakeup_int << TNETD73XX_WAKEUP_POLARITY_BIT);
++ }
++
++ /* write the wakeup control register */
++ REG32_WRITE(TNETD73XX_POWER_CTRL_WKCR, wakeup_status);
++}
++
++
++/*****************************************************************************
++ * FSER Control
++ *****************************************************************************/
++
++void tnetd73xx_fser_ctrl(TNETD73XX_FSER_MODE_T fser_mode)
++{
++ REG32_WRITE(TNETD73XX_FSER_BASE, fser_mode);
++}
++
++/*****************************************************************************
++ * Clock Control
++ *****************************************************************************/
++
++#define MIN(x,y) ( ((x) < (y)) ? (x) : (y) )
++#define MAX(x,y) ( ((x) > (y)) ? (x) : (y) )
++#define ABS(x) ( ((signed)(x) > 0) ? (x) : (-(x)) )
++#define CEIL(x,y) ( ((x) + (y) / 2) / (y) )
++
++#define CLKC_CLKCR(x) (TNETD73XX_CLOCK_CTRL_BASE + 0x20 + (0x20 * (x)))
++#define CLKC_CLKPLLCR(x) (TNETD73XX_CLOCK_CTRL_BASE + 0x30 + (0x20 * (x)))
++
++#define CLKC_PRE_DIVIDER 0x0000001F
++#define CLKC_POST_DIVIDER 0x001F0000
++
++#define CLKC_PLL_STATUS 0x1
++#define CLKC_PLL_FACTOR 0x0000F000
++
++#define BOOTCR_PLL_BYPASS (1 << 5)
++#define BOOTCR_MIPS_ASYNC_MODE (1 << 25)
++
++#define MIPS_PLL_SELECT 0x00030000
++#define SYSTEM_PLL_SELECT 0x0000C000
++#define USB_PLL_SELECT 0x000C0000
++#define ADSLSS_PLL_SELECT 0x00C00000
++
++#define MIPS_AFECLKI_SELECT 0x00000000
++#define MIPS_REFCLKI_SELECT 0x00010000
++#define MIPS_XTAL3IN_SELECT 0x00020000
++
++#define SYSTEM_AFECLKI_SELECT 0x00000000
++#define SYSTEM_REFCLKI_SELECT 0x00004000
++#define SYSTEM_XTAL3IN_SELECT 0x00008000
++#define SYSTEM_MIPSPLL_SELECT 0x0000C000
++
++#define USB_SYSPLL_SELECT 0x00000000
++#define USB_REFCLKI_SELECT 0x00040000
++#define USB_XTAL3IN_SELECT 0x00080000
++#define USB_MIPSPLL_SELECT 0x000C0000
++
++#define ADSLSS_AFECLKI_SELECT 0x00000000
++#define ADSLSS_REFCLKI_SELECT 0x00400000
++#define ADSLSS_XTAL3IN_SELECT 0x00800000
++#define ADSLSS_MIPSPLL_SELECT 0x00C00000
++
++#define SYS_MAX CLK_MHZ(150)
++#define SYS_MIN CLK_MHZ(1)
++
++#define MIPS_SYNC_MAX SYS_MAX
++#define MIPS_ASYNC_MAX CLK_MHZ(160)
++#define MIPS_MIN CLK_MHZ(1)
++
++#define USB_MAX CLK_MHZ(100)
++#define USB_MIN CLK_MHZ(1)
++
++#define ADSL_MAX CLK_MHZ(180)
++#define ADSL_MIN CLK_MHZ(1)
++
++#define PLL_MUL_MAXFACTOR 15
++#define MAX_DIV_VALUE 32
++#define MIN_DIV_VALUE 1
++
++#define MIN_PLL_INP_FREQ CLK_MHZ(8)
++#define MAX_PLL_INP_FREQ CLK_MHZ(100)
++
++#define DIVIDER_LOCK_TIME 10100
++#define PLL_LOCK_TIME 10100 * 75
++
++
++
++ /****************************************************************************
++ * DATA PURPOSE: PRIVATE Variables
++ **************************************************************************/
++ static u32 *clk_src[4];
++ static u32 mips_pll_out;
++ static u32 sys_pll_out;
++ static u32 afeclk_inp;
++ static u32 refclk_inp;
++ static u32 xtal_inp;
++ static u32 present_min;
++ static u32 present_max;
++
++ /* Forward References */
++ static u32 find_gcd(u32 min, u32 max);
++ static u32 compute_prediv( u32 divider, u32 min, u32 max);
++ static void get_val(u32 base_freq, u32 output_freq,u32 *multiplier, u32 *divider);
++ static u32 get_base_frequency(TNETD73XX_CLKC_ID_T clk_id);
++ static void find_approx(u32 *,u32 *,u32);
++
++ /****************************************************************************
++ * FUNCTION: tnetd73xx_clkc_init
++ ****************************************************************************
++ * Description: The routine initializes the internal variables depending on
++ * on the sources selected for different clocks.
++ ***************************************************************************/
++void tnetd73xx_clkc_init(u32 afeclk, u32 refclk, u32 xtal3in)
++{
++
++ u32 choice;
++
++ afeclk_inp = afeclk;
++ refclk_inp = refclk;
++ xtal_inp = xtal3in;
++
++ choice = REG32_DATA(TNETD73XX_DCL_BOOTCR) & MIPS_PLL_SELECT;
++ switch(choice)
++ {
++ case MIPS_AFECLKI_SELECT:
++ clk_src[CLKC_MIPS] = &afeclk_inp;
++ break;
++
++ case MIPS_REFCLKI_SELECT:
++ clk_src[CLKC_MIPS] = &refclk_inp;
++ break;
++
++ case MIPS_XTAL3IN_SELECT:
++ clk_src[CLKC_MIPS] = &xtal_inp;
++ break;
++
++ default :
++ clk_src[CLKC_MIPS] = 0;
++
++ }
++
++ choice = REG32_DATA(TNETD73XX_DCL_BOOTCR) & SYSTEM_PLL_SELECT;
++ switch(choice)
++ {
++ case SYSTEM_AFECLKI_SELECT:
++ clk_src[CLKC_SYS] = &afeclk_inp;
++ break;
++
++ case SYSTEM_REFCLKI_SELECT:
++ clk_src[CLKC_SYS] = &refclk_inp;
++ break;
++
++ case SYSTEM_XTAL3IN_SELECT:
++ clk_src[CLKC_SYS] = &xtal_inp;
++ break;
++
++ case SYSTEM_MIPSPLL_SELECT:
++ clk_src[CLKC_SYS] = &mips_pll_out;
++ break;
++
++ default :
++ clk_src[CLKC_SYS] = 0;
++
++ }
++
++
++ choice = REG32_DATA(TNETD73XX_DCL_BOOTCR) & ADSLSS_PLL_SELECT;
++ switch(choice)
++ {
++ case ADSLSS_AFECLKI_SELECT:
++ clk_src[CLKC_ADSLSS] = &afeclk_inp;
++ break;
++
++ case ADSLSS_REFCLKI_SELECT:
++ clk_src[CLKC_ADSLSS] = &refclk_inp;
++ break;
++
++ case ADSLSS_XTAL3IN_SELECT:
++ clk_src[CLKC_ADSLSS] = &xtal_inp;
++ break;
++
++ case ADSLSS_MIPSPLL_SELECT:
++ clk_src[CLKC_ADSLSS] = &mips_pll_out;
++ break;
++
++ default :
++ clk_src[CLKC_ADSLSS] = 0;
++
++ }
++
++
++ choice = REG32_DATA(TNETD73XX_DCL_BOOTCR) & USB_PLL_SELECT;
++ switch(choice)
++ {
++ case USB_SYSPLL_SELECT:
++ clk_src[CLKC_USB] = &sys_pll_out ;
++ break;
++
++ case USB_REFCLKI_SELECT:
++ clk_src[CLKC_USB] = &refclk_inp;
++ break;
++
++ case USB_XTAL3IN_SELECT:
++ clk_src[CLKC_USB] = &xtal_inp;
++ break;
++
++ case USB_MIPSPLL_SELECT:
++ clk_src[CLKC_USB] = &mips_pll_out;
++ break;
++
++ default :
++ clk_src[CLKC_USB] = 0;
++
++ }
++}
++
++
++
++/****************************************************************************
++ * FUNCTION: tnetd73xx_clkc_set_freq
++ ****************************************************************************
++ * Description: The above routine is called to set the output_frequency of the
++ * selected clock(using clk_id) to the required value given
++ * by the variable output_freq.
++ ***************************************************************************/
++TNETD73XX_ERR tnetd73xx_clkc_set_freq
++(
++ TNETD73XX_CLKC_ID_T clk_id,
++ u32 output_freq
++ )
++{
++ u32 base_freq;
++ u32 multiplier;
++ u32 divider;
++ u32 min_prediv;
++ u32 max_prediv;
++ u32 prediv;
++ u32 postdiv;
++ u32 temp;
++
++ /* check if PLLs are bypassed*/
++ if(REG32_DATA(TNETD73XX_DCL_BOOTCR) & BOOTCR_PLL_BYPASS)
++ {
++ return TNETD73XX_ERR_ERROR;
++ }
++
++ /*check if the requested output_frequency is in valid range*/
++ switch( clk_id )
++ {
++ case CLKC_SYS:
++ if( output_freq < SYS_MIN || output_freq > SYS_MAX)
++ {
++ return TNETD73XX_ERR_ERROR;
++ }
++ present_min = SYS_MIN;
++ present_max = SYS_MAX;
++ break;
++
++ case CLKC_MIPS:
++ if((output_freq < MIPS_MIN) ||
++ (output_freq > ((REG32_DATA(TNETD73XX_DCL_BOOTCR) & BOOTCR_MIPS_ASYNC_MODE) ? MIPS_ASYNC_MAX: MIPS_SYNC_MAX)))
++ {
++ return TNETD73XX_ERR_ERROR;
++ }
++ present_min = MIPS_MIN;
++ present_max = (REG32_DATA(TNETD73XX_DCL_BOOTCR) & BOOTCR_MIPS_ASYNC_MODE) ? MIPS_ASYNC_MAX: MIPS_SYNC_MAX;
++ break;
++
++ case CLKC_USB:
++ if( output_freq < USB_MIN || output_freq > USB_MAX)
++ {
++ return TNETD73XX_ERR_ERROR;
++ }
++ present_min = USB_MIN;
++ present_max = USB_MAX;
++ break;
++
++ case CLKC_ADSLSS:
++ if( output_freq < ADSL_MIN || output_freq > ADSL_MAX)
++ {
++ return TNETD73XX_ERR_ERROR;
++ }
++ present_min = ADSL_MIN;
++ present_max = ADSL_MAX;
++ break;
++ }
++
++
++ base_freq = get_base_frequency(clk_id);
++
++
++ /* check for minimum base frequency value */
++ if( base_freq < MIN_PLL_INP_FREQ)
++ {
++ return TNETD73XX_ERR_ERROR;
++ }
++
++ get_val(output_freq, base_freq, &multiplier, &divider);
++
++ /* check multiplier range */
++ if( (multiplier > PLL_MUL_MAXFACTOR) || (multiplier <= 0) )
++ {
++ return TNETD73XX_ERR_ERROR;
++ }
++
++ /* check divider value */
++ if( divider == 0 )
++ {
++ return TNETD73XX_ERR_ERROR;
++ }
++
++ /*compute minimum and maximum predivider values */
++ min_prediv = MAX(base_freq / MAX_PLL_INP_FREQ + 1, divider / MAX_DIV_VALUE + 1);
++ max_prediv = MIN(base_freq / MIN_PLL_INP_FREQ, MAX_DIV_VALUE);
++
++ /*adjust the value of divider so that it not less than minimum predivider value*/
++ if (divider < min_prediv)
++ {
++ temp = CEIL(min_prediv, divider);
++ if ((temp * multiplier) > PLL_MUL_MAXFACTOR)
++ {
++ return TNETD73XX_ERR_ERROR ;
++ }
++ else
++ {
++ multiplier = temp * multiplier;
++ divider = min_prediv;
++ }
++
++ }
++
++ /* compute predivider and postdivider values */
++ prediv = compute_prediv (divider, min_prediv, max_prediv);
++ postdiv = CEIL(divider,prediv);
++
++ /*return fail if postdivider value falls out of range */
++ if(postdiv > MAX_DIV_VALUE)
++ {
++ return TNETD73XX_ERR_ERROR;
++ }
++
++
++ /*write predivider and postdivider values*/
++ /* pre-Divider and post-divider are 5 bit N+1 dividers */
++ REG32_WRITE(CLKC_CLKCR(clk_id), ((postdiv -1) & 0x1F) << 16 | ((prediv -1) & 0x1F) );
++
++ /*wait for divider output to stabilise*/
++ for(temp =0; temp < DIVIDER_LOCK_TIME; temp++);
++
++ /*write to PLL clock register*/
++
++ if(clk_id == CLKC_SYS)
++ {
++ /* but before writing put DRAM to hold mode */
++ REG32_DATA(TNETD73XX_EMIF_SDRAM_CFG) |= 0x80000000;
++ }
++ /*Bring PLL into div mode */
++ REG32_WRITE(CLKC_CLKPLLCR(clk_id), 0x4);
++
++ /*compute the word to be written to PLLCR
++ *corresponding to multiplier value
++ */
++ multiplier = (((multiplier - 1) & 0xf) << 12)| ((255 <<3) | 0x0e);
++
++ /* wait till PLL enters div mode */
++ while(REG32_DATA(CLKC_CLKPLLCR(clk_id)) & CLKC_PLL_STATUS)
++ /*nothing*/;
++
++ REG32_WRITE(CLKC_CLKPLLCR(clk_id), multiplier);
++
++ while(!REG32_DATA(CLKC_CLKPLLCR(clk_id)) & CLKC_PLL_STATUS)
++ /*nothing*/;
++
++
++ /*wait for External pll to lock*/
++ for(temp =0; temp < PLL_LOCK_TIME; temp++);
++
++ if(clk_id == CLKC_SYS)
++ {
++ /* Bring DRAM out of hold */
++ REG32_DATA(TNETD73XX_EMIF_SDRAM_CFG) &= ~0x80000000;
++ }
++
++ return TNETD73XX_ERR_OK ;
++}
++
++/****************************************************************************
++ * FUNCTION: tnetd73xx_clkc_get_freq
++ ****************************************************************************
++ * Description: The above routine is called to get the output_frequency of the
++ * selected clock( clk_id)
++ ***************************************************************************/
++u32 tnetd73xx_clkc_get_freq
++(
++ TNETD73XX_CLKC_ID_T clk_id
++ )
++{
++
++ u32 clk_ctrl_register;
++ u32 clk_pll_setting;
++ u32 clk_predivider;
++ u32 clk_postdivider;
++ u16 pll_factor;
++ u32 base_freq;
++ u32 divider;
++
++ base_freq = get_base_frequency(clk_id);
++
++ clk_ctrl_register = REG32_DATA(CLKC_CLKCR(clk_id));
++
++ /* pre-Divider and post-divider are 5 bit N+1 dividers */
++ clk_predivider = (CLKC_PRE_DIVIDER & clk_ctrl_register) + 1;
++ clk_postdivider = ((CLKC_POST_DIVIDER & clk_ctrl_register) >> 16) + 1;
++
++ divider = clk_predivider * clk_postdivider;
++
++
++ if( (REG32_DATA(TNETD73XX_DCL_BOOTCR) & BOOTCR_PLL_BYPASS))
++ {
++ return (CEIL(base_freq, divider)); /* PLLs bypassed.*/
++ }
++
++
++ else
++ {
++ /* return the current clock speed based upon the PLL setting */
++ clk_pll_setting = REG32_DATA(CLKC_CLKPLLCR(clk_id));
++
++ /* Get the PLL multiplication factor */
++ pll_factor = ((clk_pll_setting & CLKC_PLL_FACTOR) >> 12) + 1;
++
++ /* Check if we're in divide mode or multiply mode */
++ if((clk_pll_setting & 0x1) == 0)
++ {
++ /* We're in divide mode */
++ if(pll_factor < 0x10)
++ return (CEIL(base_freq >> 1, divider));
++ else
++ return (CEIL(base_freq >> 2, divider));
++ }
++
++ else /* We're in PLL mode */
++ {
++ /* See if PLLNDIV & PLLDIV are set */
++ if((clk_pll_setting & 0x0800) && (clk_pll_setting & 0x2))
++ {
++ if(clk_pll_setting & 0x1000)
++ {
++ /* clk = base_freq * k/2 */
++ return(CEIL((base_freq * pll_factor) >> 1, divider));
++ }
++ else
++ {
++ /* clk = base_freq * (k-1) / 4)*/
++ return(CEIL((base_freq * (pll_factor - 1)) >>2, divider));
++ }
++ }
++ else
++ {
++ if(pll_factor < 0x10)
++ {
++ /* clk = base_freq * k */
++ return(CEIL(base_freq * pll_factor, divider));
++ }
++
++ else
++ {
++ /* clk = base_freq */
++ return(CEIL(base_freq, divider));
++ }
++ }
++ }
++ return(0); /* Should never reach here */
++
++ }
++
++}
++
++
++/* local helper functions */
++
++/****************************************************************************
++ * FUNCTION: get_base_frequency
++ ****************************************************************************
++ * Description: The above routine is called to get base frequency of the clocks.
++ ***************************************************************************/
++
++static u32 get_base_frequency(TNETD73XX_CLKC_ID_T clk_id)
++{
++ /* update the current MIPs PLL output value, if the required
++ * source is MIPS PLL
++ */
++ if ( clk_src[clk_id] == &mips_pll_out)
++ {
++ *clk_src[clk_id] = tnetd73xx_clkc_get_freq(CLKC_MIPS);
++ }
++
++
++ /* update the current System PLL output value, if the required
++ * source is system PLL
++ */
++ if ( clk_src[clk_id] == &sys_pll_out)
++ {
++ *clk_src[clk_id] = tnetd73xx_clkc_get_freq(CLKC_SYS);
++ }
++
++ return (*clk_src[clk_id]);
++
++}
++
++
++
++/****************************************************************************
++ * FUNCTION: find_gcd
++ ****************************************************************************
++ * Description: The above routine is called to find gcd of 2 numbers.
++ ***************************************************************************/
++static u32 find_gcd
++(
++ u32 min,
++ u32 max
++ )
++{
++ if (max % min == 0)
++ {
++ return min;
++ }
++ else
++ {
++ return find_gcd(max % min, min);
++ }
++}
++
++/****************************************************************************
++ * FUNCTION: compute_prediv
++ ****************************************************************************
++ * Description: The above routine is called to compute predivider value
++ ***************************************************************************/
++static u32 compute_prediv(u32 divider, u32 min, u32 max)
++{
++ u16 prediv;
++
++ /* return the divider itself it it falls within the range of predivider*/
++ if (min <= divider && divider <= max)
++ {
++ return divider;
++ }
++
++ /* find a value for prediv such that it is a factor of divider */
++ for (prediv = max; prediv >= min ; prediv--)
++ {
++ if ( (divider % prediv) == 0 )
++ {
++ return prediv;
++ }
++ }
++
++ /* No such factor exists, return min as prediv */
++ return min;
++}
++
++/****************************************************************************
++ * FUNCTION: get_val
++ ****************************************************************************
++ * Description: This routine is called to get values of divider and multiplier.
++ ***************************************************************************/
++
++static void get_val(u32 output_freq, u32 base_freq,u32 *multiplier, u32 *divider)
++{
++ u32 temp_mul;
++ u32 temp_div;
++ u32 gcd;
++ u32 min_freq;
++ u32 max_freq;
++
++ /* find gcd of base_freq, output_freq */
++ min_freq = (base_freq < output_freq) ? base_freq : output_freq;
++ max_freq = (base_freq > output_freq) ? base_freq : output_freq;
++ gcd = find_gcd(min_freq , max_freq);
++
++ if(gcd == 0)
++ return; /* ERROR */
++
++ /* compute values of multiplier and divider */
++ temp_mul = output_freq / gcd;
++ temp_div = base_freq / gcd;
++
++
++ /* set multiplier such that 1 <= multiplier <= PLL_MUL_MAXFACTOR */
++ if( temp_mul > PLL_MUL_MAXFACTOR )
++ {
++ if((temp_mul / temp_div) > PLL_MUL_MAXFACTOR)
++ return;
++
++ find_approx(&temp_mul,&temp_div,base_freq);
++ }
++
++ *multiplier = temp_mul;
++ *divider = temp_div;
++}
++
++/****************************************************************************
++ * FUNCTION: find_approx
++ ****************************************************************************
++ * Description: This function gets the approx value of num/denom.
++ ***************************************************************************/
++
++static void find_approx(u32 *num,u32 *denom,u32 base_freq)
++{
++ u32 num1;
++ u32 denom1;
++ u32 num2;
++ u32 denom2;
++ int32_t closest;
++ int32_t prev_closest;
++ u32 temp_num;
++ u32 temp_denom;
++ u32 normalize;
++ u32 gcd;
++ u32 output_freq;
++
++ num1 = *num;
++ denom1 = *denom;
++
++ prev_closest = 0x7fffffff; /* maximum possible value */
++ num2 = num1;
++ denom2 = denom1;
++
++ /* start with max */
++ for(temp_num = 15; temp_num >=1; temp_num--)
++ {
++
++ temp_denom = CEIL(temp_num * denom1, num1);
++ output_freq = (temp_num * base_freq) / temp_denom;
++
++ if(temp_denom < 1)
++ {
++ break;
++ }
++ else
++ {
++ normalize = CEIL(num1,temp_num);
++ closest = (ABS((num1 * (temp_denom) ) - (temp_num * denom1))) * normalize;
++ if(closest < prev_closest && output_freq > present_min && output_freq <present_max)
++ {
++ prev_closest = closest;
++ num2 = temp_num;
++ denom2 = temp_denom;
++ }
++
++ }
++
++ }
++
++ gcd = find_gcd(num2,denom2);
++ num2 = num2 / gcd;
++ denom2 = denom2 /gcd;
++
++ *num = num2;
++ *denom = denom2;
++}
++
++
++/*****************************************************************************
++ * GPIO Control
++ *****************************************************************************/
++
++/****************************************************************************
++ * FUNCTION: tnetd73xx_gpio_init
++ ***************************************************************************/
++void tnetd73xx_gpio_init()
++{
++ /* Bring module out of reset */
++ tnetd73xx_reset_ctrl(RESET_MODULE_GPIO, OUT_OF_RESET);
++ REG32_WRITE(TNETD73XX_GPIOENR, 0xFFFFFFFF);
++}
++
++/****************************************************************************
++ * FUNCTION: tnetd73xx_gpio_ctrl
++ ***************************************************************************/
++void tnetd73xx_gpio_ctrl(TNETD73XX_GPIO_PIN_T gpio_pin,
++ TNETD73XX_GPIO_PIN_MODE_T pin_mode,
++ TNETD73XX_GPIO_PIN_DIRECTION_T pin_direction)
++{
++ u32 pin_status;
++ REG32_READ(TNETD73XX_GPIOENR, pin_status);
++ if (pin_mode == GPIO_PIN)
++ {
++ pin_status |= (1 << gpio_pin);
++ REG32_WRITE(TNETD73XX_GPIOENR, pin_status);
++
++ /* Set pin direction */
++ REG32_READ(TNETD73XX_GPIOPDIRR, pin_status);
++ if (pin_direction == GPIO_INPUT_PIN)
++ {
++ pin_status |= (1 << gpio_pin);
++ }
++ else /* GPIO_OUTPUT_PIN */
++ {
++ pin_status &= (~(1 << gpio_pin));
++ }
++ REG32_WRITE(TNETD73XX_GPIOPDIRR, pin_status);
++ }
++ else /* FUNCTIONAL PIN */
++ {
++ pin_status &= (~(1 << gpio_pin));
++ REG32_WRITE(TNETD73XX_GPIOENR, pin_status);
++ }
++
++}
++
++/****************************************************************************
++ * FUNCTION: tnetd73xx_gpio_out
++ ***************************************************************************/
++void tnetd73xx_gpio_out(TNETD73XX_GPIO_PIN_T gpio_pin, int value)
++{
++ u32 pin_value;
++
++ REG32_READ(TNETD73XX_GPIODOUTR, pin_value);
++ if (value == 1)
++ {
++ pin_value |= (1 << gpio_pin);
++ }
++ else
++ {
++ pin_value &= (~(1 << gpio_pin));
++ }
++ REG32_WRITE(TNETD73XX_GPIODOUTR, pin_value);
++}
++
++/****************************************************************************
++ * FUNCTION: tnetd73xx_gpio_in
++ ***************************************************************************/
++int tnetd73xx_gpio_in(TNETD73XX_GPIO_PIN_T gpio_pin)
++{
++ u32 pin_value;
++ REG32_READ(TNETD73XX_GPIODINR, pin_value);
++ return ( (pin_value & (1 << gpio_pin)) ? 1 : 0 );
++}
++
+diff -urN linux.old/arch/mips/config-shared.in linux.dev/arch/mips/config-shared.in
+--- linux.old/arch/mips/config-shared.in 2005-10-21 16:43:18.917114000 +0200
++++ linux.dev/arch/mips/config-shared.in 2005-11-10 01:12:43.950955750 +0100
+@@ -20,6 +20,16 @@
+ mainmenu_option next_comment
+ comment 'Machine selection'
+ dep_bool 'Support for Acer PICA 1 chipset (EXPERIMENTAL)' CONFIG_ACER_PICA_61 $CONFIG_EXPERIMENTAL
++dep_bool 'Support for Texas Instruments AR7 (EXPERIMENTAL)' CONFIG_AR7 $CONFIG_MIPS32 $CONFIG_EXPERIMENTAL
++if [ "$CONFIG_AR7" = "y" ]; then
++ choice 'Texas Instruments Reference Platform' \
++ "AR7DB CONFIG_AR7DB \
++ AR7RD CONFIG_AR7RD \
++ AR7WRD CONFIG_AR7WRD" AR7DB
++ int 'Texas Instruments AR7 CPU Frequency' CONFIG_AR7_CPU 150
++ int 'Texas Instruments AR7 System Frequency' CONFIG_AR7_SYS 125
++ hex 'Texas Instruments AR7 SDRAM Start' CONFIG_AR7_MEMORY 0x14000000
++fi
+ dep_bool 'Support for Alchemy Bosporus board' CONFIG_MIPS_BOSPORUS $CONFIG_MIPS32
+ dep_bool 'Support for FIC Multimedia Player board' CONFIG_MIPS_FICMMP $CONFIG_MIPS32
+ dep_bool 'Support for Alchemy Mirage board' CONFIG_MIPS_MIRAGE $CONFIG_MIPS32
+@@ -239,6 +249,11 @@
+ define_bool CONFIG_NONCOHERENT_IO y
+ define_bool CONFIG_PC_KEYB y
+ fi
++if [ "$CONFIG_AR7" = "y" ]; then
++ define_bool CONFIG_IRQ_CPU y
++ define_bool CONFIG_NONCOHERENT_IO y
++ define_bool CONFIG_SWAP_IO_SPACE y
++fi
+ if [ "$CONFIG_CASIO_E55" = "y" ]; then
+ define_bool CONFIG_IRQ_CPU y
+ define_bool CONFIG_NONCOHERENT_IO y
+@@ -736,6 +751,7 @@
+ mainmenu_option next_comment
+ comment 'General setup'
+ if [ "$CONFIG_ACER_PICA_61" = "y" -o \
++ "$CONFIG_AR7" = "y" -o \
+ "$CONFIG_CASIO_E55" = "y" -o \
+ "$CONFIG_DDB5074" = "y" -o \
+ "$CONFIG_DDB5476" = "y" -o \
+@@ -797,6 +813,7 @@
+ bool 'Networking support' CONFIG_NET
+
+ if [ "$CONFIG_ACER_PICA_61" = "y" -o \
++ "$CONFIG_AR7" = "y" -o \
+ "$CONFIG_CASIO_E55" = "y" -o \
+ "$CONFIG_DECSTATION" = "y" -o \
+ "$CONFIG_IBM_WORKPAD" = "y" -o \
+diff -urN linux.old/arch/mips/kernel/head.S linux.dev/arch/mips/kernel/head.S
+--- linux.old/arch/mips/kernel/head.S 2005-10-21 16:43:16.396956500 +0200
++++ linux.dev/arch/mips/kernel/head.S 2005-11-10 01:10:45.807572250 +0100
+@@ -75,11 +75,11 @@
+ * size!
+ */
+ NESTED(except_vec4, 0, sp)
+- .set push
+- .set noreorder
+-1: j 1b /* Dummy, will be replaced */
+- nop
+- .set pop
++ .set mips2
++ lui k0, 0x9400
++ ori k0, 0x200
++ jr k0
++ nop
+ END(except_vec4)
+
+ /*
+diff -urN linux.old/arch/mips/kernel/mips_ksyms.c linux.dev/arch/mips/kernel/mips_ksyms.c
+--- linux.old/arch/mips/kernel/mips_ksyms.c 2004-02-18 14:36:30.000000000 +0100
++++ linux.dev/arch/mips/kernel/mips_ksyms.c 2005-11-10 01:10:45.811572500 +0100
+@@ -40,6 +40,12 @@
+ extern long __strnlen_user_nocheck_asm(const char *s);
+ extern long __strnlen_user_asm(const char *s);
+
++#ifdef CONFIG_AR7
++#include <asm/ar7/adam2_env.h>
++int avalanche_request_pacing(int irq_nr, unsigned int blk_num, unsigned int pace_value);
++#endif
++
++
+ EXPORT_SYMBOL(mips_machtype);
+ #ifdef CONFIG_EISA
+ EXPORT_SYMBOL(EISA_bus);
+@@ -103,3 +109,10 @@
+ #endif
+
+ EXPORT_SYMBOL(get_wchan);
++
++#ifdef CONFIG_AR7
++EXPORT_SYMBOL_NOVERS(avalanche_request_pacing);
++EXPORT_SYMBOL_NOVERS(prom_getenv);
++EXPORT_SYMBOL_NOVERS(prom_iterenv);
++#endif
++
+diff -urN linux.old/arch/mips/kernel/setup.c linux.dev/arch/mips/kernel/setup.c
+--- linux.old/arch/mips/kernel/setup.c 2005-10-21 16:43:16.396956500 +0200
++++ linux.dev/arch/mips/kernel/setup.c 2005-11-10 01:14:16.376732000 +0100
+@@ -38,6 +38,7 @@
+ #include <asm/io.h>
+ #include <asm/ptrace.h>
+ #include <asm/system.h>
++#include <asm/addrspace.h>
+
+ struct cpuinfo_mips cpu_data[NR_CPUS];
+ EXPORT_SYMBOL(cpu_data);
+@@ -88,7 +89,7 @@
+ struct boot_mem_map boot_mem_map;
+
+ unsigned char aux_device_present;
+-extern char _ftext, _etext, _fdata, _edata, _end;
++extern char _ftext, _etext, _fdata, _edata, _fbss, _end;
+
+ static char command_line[CL_SIZE];
+ char saved_command_line[CL_SIZE];
+@@ -116,6 +117,7 @@
+
+ static struct resource code_resource = { "Kernel code" };
+ static struct resource data_resource = { "Kernel data" };
++static struct resource bss_resource = { "Kernel bss" };
+
+ asmlinkage void __init
+ init_arch(int argc, char **argv, char **envp, int *prom_vec)
+@@ -272,7 +274,7 @@
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ unsigned long start, end;
+
+- if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
++ if (boot_mem_map.map[i].type == BOOT_MEM_RESERVED)
+ continue;
+
+ start = PFN_UP(boot_mem_map.map[i].addr);
+@@ -320,7 +322,8 @@
+ #endif
+
+ /* Initialize the boot-time allocator with low memory only. */
+- bootmap_size = init_bootmem(first_usable_pfn, max_low_pfn);
++ bootmap_size = init_bootmem_node(NODE_DATA(0), first_usable_pfn,
++ PFN_UP(PHYS_OFFSET), max_low_pfn);
+
+ /*
+ * Register fully available low RAM pages with the bootmem allocator.
+@@ -371,11 +374,12 @@
+ continue;
+
+ /* Register lowmem ranges */
+- free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
++ free_bootmem_node(NODE_DATA(0), PFN_PHYS(curr_pfn),
++ size<<PAGE_SHIFT);
+ }
+
+ /* Reserve the bootmap memory. */
+- reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size);
++ reserve_bootmem_node(NODE_DATA(0), PFN_PHYS(first_usable_pfn), bootmap_size);
+
+ #ifdef CONFIG_BLK_DEV_INITRD
+ /* Board specific code should have set up initrd_start and initrd_end */
+@@ -409,6 +413,8 @@
+ code_resource.end = virt_to_bus(&_etext) - 1;
+ data_resource.start = virt_to_bus(&_fdata);
+ data_resource.end = virt_to_bus(&_edata) - 1;
++ bss_resource.start = virt_to_bus(&_fbss);
++ bss_resource.end = virt_to_bus(&_end) - 1;
+
+ /*
+ * Request address space for all standard RAM.
+@@ -448,6 +454,7 @@
+ */
+ request_resource(res, &code_resource);
+ request_resource(res, &data_resource);
++ request_resource(res, &bss_resource);
+ }
+ }
+
+@@ -494,6 +501,7 @@
+ void hp_setup(void);
+ void au1x00_setup(void);
+ void frame_info_init(void);
++ void ar7_setup(void);
+
+ frame_info_init();
+ #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
+@@ -691,6 +699,11 @@
+ pmc_yosemite_setup();
+ break;
+ #endif
++#ifdef CONFIG_AR7
++ case MACH_GROUP_UNKNOWN:
++ ar7_setup();
++ break;
++#endif
+ default:
+ panic("Unsupported architecture");
+ }
+diff -urN linux.old/arch/mips/kernel/time.c linux.dev/arch/mips/kernel/time.c
+--- linux.old/arch/mips/kernel/time.c 2005-01-19 15:09:29.000000000 +0100
++++ linux.dev/arch/mips/kernel/time.c 2005-11-10 01:12:43.950955750 +0100
+@@ -143,7 +143,6 @@
+ expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy;
+ write_c0_count(expirelo - cycles_per_jiffy);
+ write_c0_compare(expirelo);
+- write_c0_count(count);
+ }
+
+ int (*mips_timer_state)(void);
+diff -urN linux.old/arch/mips/kernel/traps.c linux.dev/arch/mips/kernel/traps.c
+--- linux.old/arch/mips/kernel/traps.c 2005-10-21 16:43:16.400956750 +0200
++++ linux.dev/arch/mips/kernel/traps.c 2005-11-10 01:13:28.301727500 +0100
+@@ -869,9 +869,24 @@
+
+ exception_handlers[n] = handler;
+ if (n == 0 && cpu_has_divec) {
++ printk(KERN_DEBUG "%s: using long jump via k0 to reach %08x\n",
++ __FUNCTION__, handler);
++ /* where does the 8 byte limit mentioned in head.S come from??? */
++ if (handler > 0x0fffffff) { /* maximum for single J instruction */
++ /* lui k0, 0x0000 */
++ *(volatile u32 *)(KSEG0+0x200) = 0x3c1a0000 | (handler >> 16);
++ /* ori k0, 0x0000 */
++ *(volatile u32 *)(KSEG0+0x204) = 0x375a0000 | (handler & 0xffff);
++ /* jr k0 */
++ *(volatile u32 *)(KSEG0+0x208) = 0x03400008;
++ /* nop */
++ *(volatile u32 *)(KSEG0+0x20C) = 0x00000000;
++ flush_icache_range(KSEG0+0x200, KSEG0+0x210);
++ } else {
+ *(volatile u32 *)(KSEG0+0x200) = 0x08000000 |
+ (0x03ffffff & (handler >> 2));
+- flush_icache_range(KSEG0+0x200, KSEG0 + 0x204);
++ flush_icache_range(KSEG0+0x200, KSEG0+0x204);
++ }
+ }
+ return (void *)old_handler;
+ }
+diff -urN linux.old/arch/mips/mm/init.c linux.dev/arch/mips/mm/init.c
+--- linux.old/arch/mips/mm/init.c 2004-02-18 14:36:30.000000000 +0100
++++ linux.dev/arch/mips/mm/init.c 2005-11-10 01:14:16.376732000 +0100
+@@ -235,10 +235,13 @@
+ #endif
+ }
+
++#define START_PFN (NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT)
++#define MAX_LOW_PFN (NODE_DATA(0)->bdata->node_low_pfn)
++
+ void __init paging_init(void)
+ {
+ unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+- unsigned long max_dma, high, low;
++ unsigned long max_dma, high, low, start;
+
+ pagetable_init();
+
+@@ -247,7 +250,8 @@
+ #endif
+
+ max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+- low = max_low_pfn;
++ start = START_PFN;
++ low = MAX_LOW_PFN - start;
+ high = highend_pfn;
+
+ #ifdef CONFIG_ISA
+@@ -270,7 +274,8 @@
+ zones_size[ZONE_HIGHMEM] = high - low;
+ #endif
+
+- free_area_init(zones_size);
++ free_area_init_node(0, NODE_DATA(0), 0, zones_size,
++ start << PAGE_SHIFT, 0);
+ }
+
+ #define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
+@@ -283,7 +288,7 @@
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ unsigned long addr, end;
+
+- if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
++ if (boot_mem_map.map[i].type == BOOT_MEM_RESERVED)
+ /* not usable memory */
+ continue;
+
+@@ -313,16 +318,17 @@
+ max_mapnr = num_physpages = highend_pfn;
+ num_mappedpages = max_low_pfn;
+ #else
+- max_mapnr = num_mappedpages = num_physpages = max_low_pfn;
++ max_mapnr = num_mappedpages = num_physpages = MAX_LOW_PFN - START_PFN;
+ #endif
+- high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
+-
+- totalram_pages += free_all_bootmem();
++
++ high_memory = (void *) __va(MAX_LOW_PFN * PAGE_SIZE);
++
++ totalram_pages += free_all_bootmem_node(NODE_DATA(0));
+ totalram_pages -= setup_zero_pages(); /* Setup zeroed pages. */
+
+ reservedpages = ram = 0;
+- for (tmp = 0; tmp < max_low_pfn; tmp++)
+- if (page_is_ram(tmp)) {
++ for (tmp = 0; tmp < max_mapnr; tmp++)
++ if (page_is_ram(START_PFN + tmp)) {
+ ram++;
+ if (PageReserved(mem_map+tmp))
+ reservedpages++;
+@@ -377,13 +383,13 @@
+ #endif
+
+ extern char __init_begin, __init_end;
+-extern void prom_free_prom_memory(void) __init;
++extern unsigned long prom_free_prom_memory(void) __init;
+
+ void free_initmem(void)
+ {
+ unsigned long addr;
+
+- prom_free_prom_memory ();
++ totalram_pages += prom_free_prom_memory ();
+
+ addr = (unsigned long) &__init_begin;
+ while (addr < (unsigned long) &__init_end) {
+diff -urN linux.old/drivers/char/Config.in linux.dev/drivers/char/Config.in
+--- linux.old/drivers/char/Config.in 2005-10-21 16:43:16.440959250 +0200
++++ linux.dev/drivers/char/Config.in 2005-11-10 01:10:45.843574500 +0100
+@@ -188,6 +188,14 @@
+ tristate 'Total Impact briQ front panel driver' CONFIG_BRIQ_PANEL
+ fi
+
++if [ "$CONFIG_AR7" = "y" ]; then
++ bool 'VLYNQ support for the TI SOC' CONFIG_AR7_VLYNQ
++ dep_bool 'VLYNQ clock source Internal' CONFIG_VLYNQ_CLK_LOCAL $CONFIG_AR7_VLYNQ
++
++ define_int CONFIG_AR7_VLYNQ_PORTS 2
++ tristate 'ADAM2 environment support (read-only)' CONFIG_AR7_ADAM2
++fi
++
+ source drivers/i2c/Config.in
+
+ mainmenu_option next_comment
+diff -urN linux.old/drivers/char/Config.in.orig linux.dev/drivers/char/Config.in.orig
+--- linux.old/drivers/char/Config.in.orig 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/char/Config.in.orig 2005-11-10 01:10:45.863575750 +0100
+@@ -0,0 +1,414 @@
++#
++# Character device configuration
++#
++mainmenu_option next_comment
++comment 'Character devices'
++
++bool 'Virtual terminal' CONFIG_VT
++if [ "$CONFIG_VT" = "y" ]; then
++ bool ' Support for console on virtual terminal' CONFIG_VT_CONSOLE
++ if [ "$CONFIG_GSC_LASI" = "y" ]; then
++ bool ' Support for Lasi/Dino PS2 port' CONFIG_GSC_PS2
++ fi
++fi
++tristate 'Standard/generic (8250/16550 and compatible UARTs) serial support' CONFIG_SERIAL
++if [ "$CONFIG_SERIAL" = "y" ]; then
++ bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE
++ if [ "$CONFIG_GSC_LASI" = "y" ]; then
++ bool ' serial port on GSC support' CONFIG_SERIAL_GSC
++ fi
++ if [ "$CONFIG_IA64" = "y" ]; then
++ bool ' Support for serial port described by EFI HCDP table' CONFIG_SERIAL_HCDP
++ fi
++ if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
++ tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL
++ tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL
++ fi
++fi
++dep_mbool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED $CONFIG_SERIAL
++if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then
++ bool ' Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS
++ bool ' Support for sharing serial interrupts' CONFIG_SERIAL_SHARE_IRQ
++ bool ' Autodetect IRQ on standard ports (unsafe)' CONFIG_SERIAL_DETECT_IRQ
++ bool ' Support special multiport boards' CONFIG_SERIAL_MULTIPORT
++ bool ' Support the Bell Technologies HUB6 card' CONFIG_HUB6
++fi
++bool 'Non-standard serial port support' CONFIG_SERIAL_NONSTANDARD
++if [ "$CONFIG_SERIAL_NONSTANDARD" = "y" ]; then
++ tristate ' Computone IntelliPort Plus serial support' CONFIG_COMPUTONE
++ tristate ' Comtrol Rocketport support' CONFIG_ROCKETPORT
++ tristate ' Cyclades async mux support' CONFIG_CYCLADES
++ if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_CYCLADES" != "n" ]; then
++ bool ' Cyclades-Z interrupt mode operation (EXPERIMENTAL)' CONFIG_CYZ_INTR
++ fi
++ if [ "$CONFIG_X86_64" != "y" ]; then
++ tristate ' Digiboard Intelligent Async Support' CONFIG_DIGIEPCA
++ if [ "$CONFIG_DIGIEPCA" = "n" ]; then
++ tristate ' Digiboard PC/Xx Support' CONFIG_DIGI
++ fi
++ fi
++ dep_tristate ' Hayes ESP serial port support' CONFIG_ESPSERIAL $CONFIG_ISA
++ tristate ' Moxa Intellio support' CONFIG_MOXA_INTELLIO
++ tristate ' Moxa SmartIO support' CONFIG_MOXA_SMARTIO
++ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
++ dep_tristate ' Multi-Tech multiport card support (EXPERIMENTAL)' CONFIG_ISI m
++ fi
++ tristate ' Microgate SyncLink card support' CONFIG_SYNCLINK
++ tristate ' SyncLink Multiport support' CONFIG_SYNCLINKMP
++ tristate ' HDLC line discipline support' CONFIG_N_HDLC
++ tristate ' SDL RISCom/8 card support' CONFIG_RISCOM8
++ if [ "$CONFIG_X86_64" != "y" ]; then
++ tristate ' Specialix IO8+ card support' CONFIG_SPECIALIX
++ if [ "$CONFIG_SPECIALIX" != "n" ]; then
++ bool ' Specialix DTR/RTS pin is RTS' CONFIG_SPECIALIX_RTSCTS
++ fi
++ tristate ' Specialix SX (and SI) card support' CONFIG_SX
++ tristate ' Specialix RIO system support' CONFIG_RIO
++ if [ "$CONFIG_RIO" != "n" ]; then
++ bool ' Support really old RIO/PCI cards' CONFIG_RIO_OLDPCI
++ fi
++ fi
++ bool ' Stallion multiport serial support' CONFIG_STALDRV
++ if [ "$CONFIG_STALDRV" = "y" ]; then
++ tristate ' Stallion EasyIO or EC8/32 support' CONFIG_STALLION
++ tristate ' Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION
++ fi
++ if [ "$CONFIG_PARISC" = "y" ]; then
++ if [ "$CONFIG_PDC_CONSOLE" != "y" ]; then
++ bool ' Serial MUX support' CONFIG_SERIAL_MUX CONFIG_SERIAL_NONSTANDARD
++ fi
++ if [ "$CONFIG_SERIAL_MUX" != "y" ]; then
++ bool ' PDC software console support' CONFIG_PDC_CONSOLE CONFIG_SERIAL_NONSTANDARD
++ fi
++ fi
++ if [ "$CONFIG_MIPS" = "y" ]; then
++ bool ' TX3912/PR31700 serial port support' CONFIG_SERIAL_TX3912
++ dep_bool ' Console on TX3912/PR31700 serial port' CONFIG_SERIAL_TX3912_CONSOLE $CONFIG_SERIAL_TX3912
++ bool ' TMPTX39XX/49XX serial port support' CONFIG_SERIAL_TXX9
++ dep_bool ' Console on TMPTX39XX/49XX serial port' CONFIG_SERIAL_TXX9_CONSOLE $CONFIG_SERIAL_TXX9
++ if [ "$CONFIG_SOC_AU1X00" = "y" ]; then
++ bool ' Enable Au1x00 UART Support' CONFIG_AU1X00_UART
++ if [ "$CONFIG_AU1X00_UART" = "y" ]; then
++ bool ' Enable Au1x00 serial console' CONFIG_AU1X00_SERIAL_CONSOLE
++ fi
++ dep_tristate ' Au1x00 USB TTY Device support' CONFIG_AU1X00_USB_TTY $CONFIG_SOC_AU1X00
++ if [ "$CONFIG_AU1000_USB_TTY" != "y" ]; then
++ dep_tristate ' Au1x00 USB Raw Device support' CONFIG_AU1X00_USB_RAW $CONFIG_SOC_AU1X00
++ fi
++ if [ "$CONFIG_AU1X00_USB_TTY" != "n" -o \
++ "$CONFIG_AU1X00_USB_RAW" != "n" ]; then
++ define_bool CONFIG_AU1X00_USB_DEVICE y
++ fi
++ fi
++ bool ' TXx927 SIO support' CONFIG_TXX927_SERIAL
++ if [ "$CONFIG_TXX927_SERIAL" = "y" ]; then
++ bool ' TXx927 SIO Console support' CONFIG_TXX927_SERIAL_CONSOLE
++ fi
++ if [ "$CONFIG_SIBYTE_SB1xxx_SOC" = "y" ]; then
++ bool ' Support for BCM1xxx onchip DUART' CONFIG_SIBYTE_SB1250_DUART
++ if [ "$CONFIG_SIBYTE_SB1250_DUART" = "y" ]; then
++ bool ' Console on BCM1xxx DUART' CONFIG_SIBYTE_SB1250_DUART_CONSOLE
++ if [ "$CONFIG_SIBYTE_SB1250_DUART_CONSOLE" = "y" ]; then
++ define_bool CONFIG_SERIAL_CONSOLE y
++ fi
++ fi
++ fi
++ fi
++ if [ "$CONFIG_DECSTATION" = "y" ]; then
++ bool ' DECstation serial support' CONFIG_SERIAL_DEC
++ dep_bool ' Support for console on a DECstation serial port' CONFIG_SERIAL_DEC_CONSOLE $CONFIG_SERIAL_DEC
++ dep_bool ' DZ11 serial support' CONFIG_DZ $CONFIG_SERIAL_DEC $CONFIG_MIPS32
++ dep_bool ' Z85C30 serial support' CONFIG_ZS $CONFIG_SERIAL_DEC $CONFIG_TC
++ fi
++ if [ "$CONFIG_SGI_IP22" = "y" ]; then
++ bool ' SGI Zilog85C30 serial support' CONFIG_IP22_SERIAL
++ fi
++ if [ "$CONFIG_IA64" = "y" ]; then
++ bool ' SGI SN2 l1 serial port support' CONFIG_SGI_L1_SERIAL
++ if [ "$CONFIG_SGI_L1_SERIAL" = "y" ]; then
++ bool ' SGI SN2 l1 Console support' CONFIG_SGI_L1_SERIAL_CONSOLE
++ fi
++ if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_SGI_SN2" = "y" ]; then
++ bool ' SGI SN2 IOC4 serial port support' CONFIG_SGI_IOC4_SERIAL
++ fi
++ fi
++fi
++if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_ZORRO" = "y" ]; then
++ tristate 'Commodore A2232 serial support (EXPERIMENTAL)' CONFIG_A2232
++fi
++if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
++ bool 'DC21285 serial port support' CONFIG_SERIAL_21285
++ if [ "$CONFIG_SERIAL_21285" = "y" ]; then
++ if [ "$CONFIG_OBSOLETE" = "y" ]; then
++ bool ' Use /dev/ttyS0 device (OBSOLETE)' CONFIG_SERIAL_21285_OLD
++ fi
++ bool ' Console on DC21285 serial port' CONFIG_SERIAL_21285_CONSOLE
++ fi
++ if [ "$CONFIG_PARISC" = "y" ]; then
++ bool ' PDC software console support' CONFIG_PDC_CONSOLE
++ fi
++fi
++if [ "$CONFIG_MIPS_ITE8172" = "y" ]; then
++ bool 'Enable Qtronix 990P Keyboard Support' CONFIG_QTRONIX_KEYBOARD
++ if [ "$CONFIG_QTRONIX_KEYBOARD" = "y" ]; then
++ define_bool CONFIG_IT8172_CIR y
++ else
++ bool ' Enable PS2 Keyboard Support' CONFIG_PC_KEYB
++ fi
++ bool 'Enable Smart Card Reader 0 Support ' CONFIG_IT8172_SCR0
++ bool 'Enable Smart Card Reader 1 Support ' CONFIG_IT8172_SCR1
++fi
++if [ "$CONFIG_MIPS_IVR" = "y" ]; then
++ bool 'Enable Qtronix 990P Keyboard Support' CONFIG_QTRONIX_KEYBOARD
++ if [ "$CONFIG_QTRONIX_KEYBOARD" = "y" ]; then
++ define_bool CONFIG_IT8172_CIR y
++ fi
++ bool 'Enable Smart Card Reader 0 Support ' CONFIG_IT8172_SCR0
++fi
++if [ "$CONFIG_CPU_VR41XX" = "y" ]; then
++ bool 'NEC VR4100 series Keyboard Interface Unit Support ' CONFIG_VR41XX_KIU
++fi
++bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
++if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
++ int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
++fi
++if [ "$CONFIG_PARPORT" != "n" ]; then
++ dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
++ if [ "$CONFIG_PRINTER" != "n" ]; then
++ bool ' Support for console on line printer' CONFIG_LP_CONSOLE
++ fi
++ dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT
++ dep_tristate 'Texas Instruments parallel link cable support' CONFIG_TIPAR $CONFIG_PARPORT
++fi
++
++if [ "$CONFIG_PPC64" = "y" ] ; then
++ bool 'pSeries Hypervisor Virtual Console support' CONFIG_HVC_CONSOLE
++fi
++if [ "$CONFIG_ALL_PPC" = "y" ]; then
++ tristate 'Total Impact briQ front panel driver' CONFIG_BRIQ_PANEL
++fi
++
++if [ "$CONFIG_AR7" = "y" ]; then
++ bool 'VLYNQ support for the TI SOC' CONFIG_AR7_VLYNQ
++ dep_bool 'VLYNQ clock source Internal' CONFIG_VLYNQ_CLK_LOCAL $CONFIG_AR7_VLYNQ
++
++ define_int CONFIG_AR7_VLYNQ_PORTS 2
++fi
++
++source drivers/i2c/Config.in
++
++mainmenu_option next_comment
++comment 'Mice'
++tristate 'Bus Mouse Support' CONFIG_BUSMOUSE
++if [ "$CONFIG_BUSMOUSE" != "n" ]; then
++ dep_tristate ' ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE $CONFIG_BUSMOUSE
++ dep_tristate ' Logitech busmouse support' CONFIG_LOGIBUSMOUSE $CONFIG_BUSMOUSE
++ dep_tristate ' Microsoft busmouse support' CONFIG_MS_BUSMOUSE $CONFIG_BUSMOUSE
++ if [ "$CONFIG_ADB" = "y" -a "$CONFIG_ADB_KEYBOARD" = "y" ]; then
++ dep_tristate ' Apple Desktop Bus mouse support (old driver)' CONFIG_ADBMOUSE $CONFIG_BUSMOUSE
++ fi
++# if [ "$CONFIG_DECSTATION" = "y" ]; then
++# dep_bool ' MAXINE Access.Bus mouse (VSXXX-BB/GB) support' CONFIG_DTOP_MOUSE $CONFIG_ACCESSBUS
++# fi
++fi
++
++tristate 'Mouse Support (not serial and bus mice)' CONFIG_MOUSE
++if [ "$CONFIG_MOUSE" != "n" ]; then
++ bool ' PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
++ tristate ' C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE
++ tristate ' PC110 digitizer pad support' CONFIG_PC110_PAD
++ tristate ' MK712 touch screen support' CONFIG_MK712_MOUSE
++fi
++endmenu
++
++source drivers/char/joystick/Config.in
++
++tristate 'QIC-02 tape support' CONFIG_QIC02_TAPE
++if [ "$CONFIG_QIC02_TAPE" != "n" ]; then
++ bool ' Do you want runtime configuration for QIC-02' CONFIG_QIC02_DYNCONF
++ if [ "$CONFIG_QIC02_DYNCONF" != "y" ]; then
++ comment ' Edit configuration parameters in ./include/linux/tpqic02.h!'
++ else
++ comment ' Setting runtime QIC-02 configuration is done with qic02conf'
++ comment ' from the tpqic02-support package. It is available at'
++ comment ' metalab.unc.edu or ftp://titus.cfw.com/pub/Linux/util/'
++ fi
++fi
++
++tristate 'IPMI top-level message handler' CONFIG_IPMI_HANDLER
++dep_mbool ' Generate a panic event to all BMCs on a panic' CONFIG_IPMI_PANIC_EVENT $CONFIG_IPMI_HANDLER
++dep_tristate ' Device interface for IPMI' CONFIG_IPMI_DEVICE_INTERFACE $CONFIG_IPMI_HANDLER
++dep_tristate ' IPMI KCS handler' CONFIG_IPMI_KCS $CONFIG_IPMI_HANDLER
++dep_tristate ' IPMI Watchdog Timer' CONFIG_IPMI_WATCHDOG $CONFIG_IPMI_HANDLER
++
++mainmenu_option next_comment
++comment 'Watchdog Cards'
++bool 'Watchdog Timer Support' CONFIG_WATCHDOG
++if [ "$CONFIG_WATCHDOG" != "n" ]; then
++ bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT
++ tristate ' Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT
++ tristate ' Advantech SBC Watchdog Timer' CONFIG_ADVANTECH_WDT
++ tristate ' ALi M7101 PMU on ALi 1535D+ Watchdog Timer' CONFIG_ALIM1535_WDT
++ tristate ' ALi M7101 PMU Watchdog Timer' CONFIG_ALIM7101_WDT
++ tristate ' AMD "Elan" SC520 Watchdog Timer' CONFIG_SC520_WDT
++ tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
++ if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
++ tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG
++ if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then
++ tristate ' NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG
++ fi
++ fi
++ tristate ' Eurotech CPU-1220/1410 Watchdog Timer' CONFIG_EUROTECH_WDT
++ tristate ' IB700 SBC Watchdog Timer' CONFIG_IB700_WDT
++ tristate ' ICP ELectronics Wafer 5823 Watchdog' CONFIG_WAFER_WDT
++ tristate ' Intel i810 TCO timer / Watchdog' CONFIG_I810_TCO
++ tristate ' Mixcom Watchdog' CONFIG_MIXCOMWD
++ tristate ' SBC-60XX Watchdog Timer' CONFIG_60XX_WDT
++ dep_tristate ' SC1200 Watchdog Timer (EXPERIMENTAL)' CONFIG_SC1200_WDT $CONFIG_EXPERIMENTAL
++ tristate ' NatSemi SCx200 Watchdog' CONFIG_SCx200_WDT
++ tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG
++ tristate ' W83877F (EMACS) Watchdog Timer' CONFIG_W83877F_WDT
++ tristate ' WDT Watchdog timer' CONFIG_WDT
++ tristate ' WDT PCI Watchdog timer' CONFIG_WDTPCI
++ if [ "$CONFIG_WDT" != "n" ]; then
++ bool ' WDT501 features' CONFIG_WDT_501
++ if [ "$CONFIG_WDT_501" = "y" ]; then
++ bool ' Fan Tachometer' CONFIG_WDT_501_FAN
++ fi
++ fi
++ tristate ' ZF MachZ Watchdog' CONFIG_MACHZ_WDT
++ if [ "$CONFIG_SGI_IP22" = "y" ]; then
++ dep_tristate ' Indy/I2 Hardware Watchdog' CONFIG_INDYDOG $CONFIG_SGI_IP22
++ fi
++ if [ "$CONFIG_8xx" = "y" ]; then
++ tristate ' MPC8xx Watchdog Timer' CONFIG_8xx_WDT
++ fi
++fi
++endmenu
++
++if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then
++ tristate 'NetWinder thermometer support' CONFIG_DS1620
++ tristate 'NetWinder Button' CONFIG_NWBUTTON
++ if [ "$CONFIG_NWBUTTON" != "n" ]; then
++ bool ' Reboot Using Button' CONFIG_NWBUTTON_REBOOT
++ fi
++ tristate 'NetWinder flash support' CONFIG_NWFLASH
++fi
++tristate 'NatSemi SCx200 Support' CONFIG_SCx200
++dep_tristate ' NatSemi SCx200 GPIO Support' CONFIG_SCx200_GPIO $CONFIG_SCx200
++
++if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_SGI_SN2" = "y" ] ; then
++ bool 'SGI SN2 fetchop support' CONFIG_FETCHOP
++fi
++
++if [ "$CONFIG_X86" = "y" -o "$CONFIG_X86_64" = "y" ]; then
++ dep_tristate 'AMD 768/8111 Random Number Generator support' CONFIG_AMD_RNG $CONFIG_PCI
++fi
++if [ "$CONFIG_X86" = "y" -o "$CONFIG_IA64" = "y" ]; then
++ dep_tristate 'Intel i8x0 Random Number Generator support' CONFIG_INTEL_RNG $CONFIG_PCI
++fi
++if [ "$CONFIG_X86" = "y" -o "$CONFIG_IA64" = "y" -o \
++ "$CONFIG_X86_64" = "y" ]; then
++ dep_tristate 'Intel/AMD/VIA HW Random Number Generator support' CONFIG_HW_RANDOM $CONFIG_PCI
++fi
++dep_tristate 'AMD 76x native power management (Experimental)' CONFIG_AMD_PM768 $CONFIG_PCI
++tristate '/dev/nvram support' CONFIG_NVRAM
++tristate 'Enhanced Real Time Clock Support' CONFIG_RTC
++if [ "$CONFIG_IA64" = "y" ]; then
++ bool 'EFI Real Time Clock Services' CONFIG_EFI_RTC
++fi
++if [ "$CONFIG_OBSOLETE" = "y" -a "$CONFIG_ALPHA_BOOK1" = "y" ]; then
++ bool 'Tadpole ANA H8 Support (OBSOLETE)' CONFIG_H8
++fi
++if [ "$CONFIG_SGI_IP22" = "y" ]; then
++ tristate 'Dallas DS1286 RTC support' CONFIG_DS1286
++fi
++if [ "$CONFIG_SGI_IP27" = "y" ]; then
++ tristate 'SGI M48T35 RTC support' CONFIG_SGI_IP27_RTC
++fi
++if [ "$CONFIG_TOSHIBA_RBTX4927" = "y" -o "$CONFIG_TOSHIBA_JMR3927" = "y" ]; then
++ tristate 'Dallas DS1742 RTC support' CONFIG_DS1742
++fi
++
++tristate 'Double Talk PC internal speech card support' CONFIG_DTLK
++tristate 'Siemens R3964 line discipline' CONFIG_R3964
++tristate 'Applicom intelligent fieldbus card support' CONFIG_APPLICOM
++if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_X86" = "y" -a "$CONFIG_X86_64" != "y" ]; then
++ dep_tristate 'Sony Vaio Programmable I/O Control Device support (EXPERIMENTAL)' CONFIG_SONYPI $CONFIG_PCI
++fi
++
++mainmenu_option next_comment
++comment 'Ftape, the floppy tape device driver'
++tristate 'Ftape (QIC-80/Travan) support' CONFIG_FTAPE
++if [ "$CONFIG_FTAPE" != "n" ]; then
++ source drivers/char/ftape/Config.in
++fi
++
++endmenu
++
++if [ "$CONFIG_GART_IOMMU" = "y" ]; then
++ bool '/dev/agpgart (AGP Support)' CONFIG_AGP
++ define_bool CONFIG_AGP_AMD_K8 y
++else
++ tristate '/dev/agpgart (AGP Support)' CONFIG_AGP
++fi
++if [ "$CONFIG_AGP" != "n" ]; then
++ bool ' Intel 440LX/BX/GX and I815/I820/I830M/I830MP/I840/I845/I850/I860 support' CONFIG_AGP_INTEL
++ bool ' Intel I810/I815/I830M (on-board) support' CONFIG_AGP_I810
++ bool ' VIA chipset support' CONFIG_AGP_VIA
++ bool ' AMD Irongate, 761, and 762 support' CONFIG_AGP_AMD
++ if [ "$CONFIG_GART_IOMMU" != "y" ]; then
++ bool ' AMD Opteron/Athlon64 on-CPU GART support' CONFIG_AGP_AMD_K8
++ fi
++ bool ' Generic SiS support' CONFIG_AGP_SIS
++ bool ' ALI chipset support' CONFIG_AGP_ALI
++ bool ' Serverworks LE/HE support' CONFIG_AGP_SWORKS
++ if [ "$CONFIG_X86" = "y" ]; then
++ bool ' NVIDIA chipset support' CONFIG_AGP_NVIDIA
++ fi
++ if [ "$CONFIG_IA64" = "y" ]; then
++ bool ' Intel 460GX support' CONFIG_AGP_I460
++ bool ' HP ZX1 AGP support' CONFIG_AGP_HP_ZX1
++ fi
++ bool ' ATI IGP chipset support' CONFIG_AGP_ATI
++fi
++
++mainmenu_option next_comment
++comment 'Direct Rendering Manager (XFree86 DRI support)'
++bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM
++if [ "$CONFIG_DRM" = "y" ]; then
++ bool ' Build drivers for old (XFree 4.0) DRM' CONFIG_DRM_OLD
++ if [ "$CONFIG_DRM_OLD" = "y" ]; then
++ comment 'DRM 4.0 drivers'
++ source drivers/char/drm-4.0/Config.in
++ else
++ comment 'DRM 4.1 drivers'
++ define_bool CONFIG_DRM_NEW y
++ source drivers/char/drm/Config.in
++ fi
++fi
++
++if [ "$CONFIG_X86" = "y" ]; then
++ tristate 'ACP Modem (Mwave) support' CONFIG_MWAVE
++fi
++
++endmenu
++
++if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then
++ source drivers/char/pcmcia/Config.in
++fi
++if [ "$CONFIG_SOC_AU1X00" = "y" ]; then
++ tristate ' Alchemy Au1x00 GPIO device support' CONFIG_AU1X00_GPIO
++ tristate ' Au1000/ADS7846 touchscreen support' CONFIG_TS_AU1X00_ADS7846
++ #tristate ' Alchemy Au1550 PSC SPI support' CONFIG_AU1550_PSC_SPI
++fi
++if [ "$CONFIG_MIPS_ITE8172" = "y" ]; then
++ tristate ' ITE GPIO' CONFIG_ITE_GPIO
++fi
++
++if [ "$CONFIG_X86" = "y" ]; then
++ tristate 'ACP Modem (Mwave) support' CONFIG_MWAVE
++ dep_tristate 'HP OB600 C/CT Pop-up mouse support' CONFIG_OBMOUSE $CONFIG_INPUT_MOUSEDEV
++fi
++
++endmenu
+diff -urN linux.old/drivers/char/Makefile linux.dev/drivers/char/Makefile
+--- linux.old/drivers/char/Makefile 2005-10-21 16:43:16.460960500 +0200
++++ linux.dev/drivers/char/Makefile 2005-11-10 01:10:45.871576250 +0100
+@@ -240,6 +240,13 @@
+ obj-y += joystick/js.o
+ endif
+
++#
++# Texas Intruments VLYNQ driver
++#
++
++subdir-$(CONFIG_AR7_VLYNQ) += avalanche_vlynq
++obj-$(CONFIG_AR7_VLYNQ) += avalanche_vlynq/avalanche_vlynq.o
++
+ obj-$(CONFIG_FETCHOP) += fetchop.o
+ obj-$(CONFIG_BUSMOUSE) += busmouse.o
+ obj-$(CONFIG_DTLK) += dtlk.o
+@@ -340,6 +347,11 @@
+ obj-y += ipmi/ipmi.o
+ endif
+
++subdir-$(CONFIG_AR7_ADAM2) += ticfg
++ifeq ($(CONFIG_AR7_ADAM2),y)
++ obj-y += ticfg/ticfg.o
++endif
++
+ include $(TOPDIR)/Rules.make
+
+ fastdep:
+diff -urN linux.old/drivers/char/Makefile.orig linux.dev/drivers/char/Makefile.orig
+--- linux.old/drivers/char/Makefile.orig 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/char/Makefile.orig 2005-11-10 01:10:45.871576250 +0100
+@@ -0,0 +1,374 @@
++#
++# Makefile for the kernel character device drivers.
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definitions are now inherited from the
++# parent makes..
++#
++
++#
++# This file contains the font map for the default (hardware) font
++#
++FONTMAPFILE = cp437.uni
++
++O_TARGET := char.o
++
++obj-y += mem.o tty_io.o n_tty.o tty_ioctl.o raw.o pty.o misc.o random.o
++
++# All of the (potential) objects that export symbols.
++# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
++
++export-objs := busmouse.o console.o keyboard.o sysrq.o \
++ misc.o pty.o random.o selection.o serial.o \
++ sonypi.o tty_io.o tty_ioctl.o generic_serial.o \
++ au1000_gpio.o vac-serial.o hp_psaux.o nvram.o \
++ scx200.o fetchop.o
++
++mod-subdirs := joystick ftape drm drm-4.0 pcmcia
++
++list-multi :=
++
++KEYMAP =defkeymap.o
++KEYBD =pc_keyb.o
++CONSOLE =console.o
++SERIAL =serial.o
++
++ifeq ($(ARCH),s390)
++ KEYMAP =
++ KEYBD =
++ CONSOLE =
++ SERIAL =
++endif
++
++ifeq ($(ARCH),mips)
++ ifneq ($(CONFIG_PC_KEYB),y)
++ KEYBD =
++ endif
++ ifeq ($(CONFIG_VR41XX_KIU),y)
++ ifeq ($(CONFIG_IBM_WORKPAD),y)
++ KEYMAP = ibm_workpad_keymap.o
++ endif
++ ifeq ($(CONFIG_VICTOR_MPC30X),y)
++ KEYMAP = victor_mpc30x_keymap.o
++ endif
++ KEYBD = vr41xx_keyb.o
++ endif
++endif
++
++ifeq ($(ARCH),s390x)
++ KEYMAP =
++ KEYBD =
++ CONSOLE =
++ SERIAL =
++endif
++
++ifeq ($(ARCH),m68k)
++ ifdef CONFIG_AMIGA
++ KEYBD = amikeyb.o
++ else
++ ifndef CONFIG_MAC
++ KEYBD =
++ endif
++ endif
++ SERIAL =
++endif
++
++ifeq ($(ARCH),parisc)
++ ifdef CONFIG_GSC_PS2
++ KEYBD = hp_psaux.o hp_keyb.o
++ else
++ KEYBD =
++ endif
++ ifdef CONFIG_SERIAL_MUX
++ CONSOLE += mux.o
++ endif
++ ifdef CONFIG_PDC_CONSOLE
++ CONSOLE += pdc_console.o
++ endif
++endif
++
++ifdef CONFIG_Q40
++ KEYBD += q40_keyb.o
++ SERIAL = serial.o
++endif
++
++ifdef CONFIG_APOLLO
++ KEYBD += dn_keyb.o
++endif
++
++ifeq ($(ARCH),parisc)
++ ifdef CONFIG_GSC_PS2
++ KEYBD = hp_psaux.o hp_keyb.o
++ else
++ KEYBD =
++ endif
++ ifdef CONFIG_PDC_CONSOLE
++ CONSOLE += pdc_console.o
++ endif
++endif
++
++ifeq ($(ARCH),arm)
++ ifneq ($(CONFIG_PC_KEYMAP),y)
++ KEYMAP =
++ endif
++ ifneq ($(CONFIG_PC_KEYB),y)
++ KEYBD =
++ endif
++endif
++
++ifeq ($(ARCH),sh)
++ KEYMAP =
++ KEYBD =
++ CONSOLE =
++ ifeq ($(CONFIG_SH_HP600),y)
++ KEYMAP = defkeymap.o
++ KEYBD = scan_keyb.o hp600_keyb.o
++ CONSOLE = console.o
++ endif
++ ifeq ($(CONFIG_SH_DMIDA),y)
++ # DMIDA does not connect the HD64465 PS/2 keyboard port
++ # but we allow for USB keyboards to be plugged in.
++ KEYMAP = defkeymap.o
++ KEYBD = # hd64465_keyb.o pc_keyb.o
++ CONSOLE = console.o
++ endif
++ ifeq ($(CONFIG_SH_EC3104),y)
++ KEYMAP = defkeymap.o
++ KEYBD = ec3104_keyb.o
++ CONSOLE = console.o
++ endif
++ ifeq ($(CONFIG_SH_DREAMCAST),y)
++ KEYMAP = defkeymap.o
++ KEYBD =
++ CONSOLE = console.o
++ endif
++endif
++
++ifeq ($(CONFIG_DECSTATION),y)
++ KEYMAP =
++ KEYBD =
++endif
++
++ifeq ($(CONFIG_BAGET_MIPS),y)
++ KEYBD =
++ SERIAL = vac-serial.o
++endif
++
++ifeq ($(CONFIG_NINO),y)
++ SERIAL =
++endif
++
++ifneq ($(CONFIG_SUN_SERIAL),)
++ SERIAL =
++endif
++
++ifeq ($(CONFIG_QTRONIX_KEYBOARD),y)
++ KEYBD = qtronix.o
++ KEYMAP = qtronixmap.o
++endif
++
++ifeq ($(CONFIG_DUMMY_KEYB),y)
++ KEYBD = dummy_keyb.o
++endif
++
++obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o
++obj-$(CONFIG_SERIAL) += $(SERIAL)
++obj-$(CONFIG_PARPORT_SERIAL) += parport_serial.o
++obj-$(CONFIG_SERIAL_HCDP) += hcdp_serial.o
++obj-$(CONFIG_SERIAL_21285) += serial_21285.o
++obj-$(CONFIG_SERIAL_SA1100) += serial_sa1100.o
++obj-$(CONFIG_SERIAL_AMBA) += serial_amba.o
++obj-$(CONFIG_TS_AU1X00_ADS7846) += au1000_ts.o
++obj-$(CONFIG_SERIAL_DEC) += decserial.o
++
++ifndef CONFIG_SUN_KEYBOARD
++ obj-$(CONFIG_VT) += keyboard.o $(KEYMAP) $(KEYBD)
++else
++ obj-$(CONFIG_PCI) += keyboard.o $(KEYMAP)
++endif
++
++obj-$(CONFIG_HIL) += hp_keyb.o
++obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
++obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
++obj-$(CONFIG_ROCKETPORT) += rocket.o
++obj-$(CONFIG_MOXA_SMARTIO) += mxser.o
++obj-$(CONFIG_MOXA_INTELLIO) += moxa.o
++obj-$(CONFIG_DIGI) += pcxx.o
++obj-$(CONFIG_DIGIEPCA) += epca.o
++obj-$(CONFIG_CYCLADES) += cyclades.o
++obj-$(CONFIG_STALLION) += stallion.o
++obj-$(CONFIG_ISTALLION) += istallion.o
++obj-$(CONFIG_SIBYTE_SB1250_DUART) += sb1250_duart.o
++obj-$(CONFIG_COMPUTONE) += ip2.o ip2main.o
++obj-$(CONFIG_RISCOM8) += riscom8.o
++obj-$(CONFIG_ISI) += isicom.o
++obj-$(CONFIG_ESPSERIAL) += esp.o
++obj-$(CONFIG_SYNCLINK) += synclink.o
++obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o
++obj-$(CONFIG_N_HDLC) += n_hdlc.o
++obj-$(CONFIG_SPECIALIX) += specialix.o
++obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
++obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o
++obj-$(CONFIG_SX) += sx.o generic_serial.o
++obj-$(CONFIG_RIO) += rio/rio.o generic_serial.o
++obj-$(CONFIG_SH_SCI) += sh-sci.o generic_serial.o
++obj-$(CONFIG_SERIAL167) += serial167.o
++obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o
++obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o
++obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o
++obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o
++obj-$(CONFIG_SERIAL_TX3912) += generic_serial.o serial_tx3912.o
++obj-$(CONFIG_TXX927_SERIAL) += serial_txx927.o
++obj-$(CONFIG_SERIAL_TXX9) += generic_serial.o serial_txx9.o
++obj-$(CONFIG_IP22_SERIAL) += sgiserial.o
++obj-$(CONFIG_AU1X00_UART) += au1x00-serial.o
++obj-$(CONFIG_SGI_L1_SERIAL) += sn_serial.o
++
++subdir-$(CONFIG_RIO) += rio
++subdir-$(CONFIG_INPUT) += joystick
++
++obj-$(CONFIG_ATIXL_BUSMOUSE) += atixlmouse.o
++obj-$(CONFIG_LOGIBUSMOUSE) += logibusmouse.o
++obj-$(CONFIG_PRINTER) += lp.o
++obj-$(CONFIG_TIPAR) += tipar.o
++obj-$(CONFIG_OBMOUSE) += obmouse.o
++
++ifeq ($(CONFIG_INPUT),y)
++obj-y += joystick/js.o
++endif
++
++#
++# Texas Intruments VLYNQ driver
++#
++
++subdir-$(CONFIG_AR7_VLYNQ) += avalanche_vlynq
++obj-$(CONFIG_AR7_VLYNQ) += avalanche_vlynq/avalanche_vlynq.o
++
++obj-$(CONFIG_FETCHOP) += fetchop.o
++obj-$(CONFIG_BUSMOUSE) += busmouse.o
++obj-$(CONFIG_DTLK) += dtlk.o
++obj-$(CONFIG_R3964) += n_r3964.o
++obj-$(CONFIG_APPLICOM) += applicom.o
++obj-$(CONFIG_SONYPI) += sonypi.o
++obj-$(CONFIG_MS_BUSMOUSE) += msbusmouse.o
++obj-$(CONFIG_82C710_MOUSE) += qpmouse.o
++obj-$(CONFIG_AMIGAMOUSE) += amigamouse.o
++obj-$(CONFIG_ATARIMOUSE) += atarimouse.o
++obj-$(CONFIG_ADBMOUSE) += adbmouse.o
++obj-$(CONFIG_PC110_PAD) += pc110pad.o
++obj-$(CONFIG_MK712_MOUSE) += mk712.o
++obj-$(CONFIG_RTC) += rtc.o
++obj-$(CONFIG_GEN_RTC) += genrtc.o
++obj-$(CONFIG_EFI_RTC) += efirtc.o
++obj-$(CONFIG_MIPS_RTC) += mips_rtc.o
++obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
++ifeq ($(CONFIG_PPC),)
++ obj-$(CONFIG_NVRAM) += nvram.o
++endif
++obj-$(CONFIG_TOSHIBA) += toshiba.o
++obj-$(CONFIG_I8K) += i8k.o
++obj-$(CONFIG_DS1286) += ds1286.o
++obj-$(CONFIG_DS1620) += ds1620.o
++obj-$(CONFIG_DS1742) += ds1742.o
++obj-$(CONFIG_INTEL_RNG) += i810_rng.o
++obj-$(CONFIG_AMD_RNG) += amd768_rng.o
++obj-$(CONFIG_HW_RANDOM) += hw_random.o
++obj-$(CONFIG_AMD_PM768) += amd76x_pm.o
++obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o
++
++obj-$(CONFIG_ITE_GPIO) += ite_gpio.o
++obj-$(CONFIG_AU1X00_GPIO) += au1000_gpio.o
++obj-$(CONFIG_AU1550_PSC_SPI) += au1550_psc_spi.o
++obj-$(CONFIG_AU1X00_USB_TTY) += au1000_usbtty.o
++obj-$(CONFIG_AU1X00_USB_RAW) += au1000_usbraw.o
++obj-$(CONFIG_COBALT_LCD) += lcd.o
++
++obj-$(CONFIG_QIC02_TAPE) += tpqic02.o
++
++subdir-$(CONFIG_FTAPE) += ftape
++subdir-$(CONFIG_DRM_OLD) += drm-4.0
++subdir-$(CONFIG_DRM_NEW) += drm
++subdir-$(CONFIG_PCMCIA) += pcmcia
++subdir-$(CONFIG_AGP) += agp
++
++ifeq ($(CONFIG_FTAPE),y)
++obj-y += ftape/ftape.o
++endif
++
++obj-$(CONFIG_H8) += h8.o
++obj-$(CONFIG_PPDEV) += ppdev.o
++obj-$(CONFIG_DZ) += dz.o
++obj-$(CONFIG_NWBUTTON) += nwbutton.o
++obj-$(CONFIG_NWFLASH) += nwflash.o
++obj-$(CONFIG_SCx200) += scx200.o
++obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
++
++# Only one watchdog can succeed. We probe the hardware watchdog
++# drivers first, then the softdog driver. This means if your hardware
++# watchdog dies or is 'borrowed' for some reason the software watchdog
++# still gives you some cover.
++
++obj-$(CONFIG_PCWATCHDOG) += pcwd.o
++obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
++obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
++obj-$(CONFIG_IB700_WDT) += ib700wdt.o
++obj-$(CONFIG_MIXCOMWD) += mixcomwd.o
++obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
++obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
++obj-$(CONFIG_SC520_WDT) += sc520_wdt.o
++obj-$(CONFIG_WDT) += wdt.o
++obj-$(CONFIG_WDTPCI) += wdt_pci.o
++obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
++obj-$(CONFIG_977_WATCHDOG) += wdt977.o
++obj-$(CONFIG_I810_TCO) += i810-tco.o
++obj-$(CONFIG_MACHZ_WDT) += machzwd.o
++obj-$(CONFIG_SH_WDT) += shwdt.o
++obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
++obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
++obj-$(CONFIG_ALIM1535_WDT) += alim1535d_wdt.o
++obj-$(CONFIG_INDYDOG) += indydog.o
++obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
++obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
++obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
++obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
++obj-$(CONFIG_INDYDOG) += indydog.o
++obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
++
++subdir-$(CONFIG_MWAVE) += mwave
++ifeq ($(CONFIG_MWAVE),y)
++ obj-y += mwave/mwave.o
++endif
++
++subdir-$(CONFIG_IPMI_HANDLER) += ipmi
++ifeq ($(CONFIG_IPMI_HANDLER),y)
++ obj-y += ipmi/ipmi.o
++endif
++
++include $(TOPDIR)/Rules.make
++
++fastdep:
++
++conmakehash: conmakehash.c
++ $(HOSTCC) $(HOSTCFLAGS) -o conmakehash conmakehash.c
++
++consolemap_deftbl.c: $(FONTMAPFILE) conmakehash
++ ./conmakehash $(FONTMAPFILE) > consolemap_deftbl.c
++
++consolemap_deftbl.o: consolemap_deftbl.c $(TOPDIR)/include/linux/types.h
++
++.DELETE_ON_ERROR:
++
++defkeymap.c: defkeymap.map
++ set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@
++
++qtronixmap.c: qtronixmap.map
++ set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@
++
++ibm_workpad_keymap.c: ibm_workpad_keymap.map
++ set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@
++
++victor_mpc30x_keymap.c: victor_mpc30x_keymap.map
++ set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@
+diff -urN linux.old/drivers/char/avalanche_vlynq/Makefile linux.dev/drivers/char/avalanche_vlynq/Makefile
+--- linux.old/drivers/char/avalanche_vlynq/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/char/avalanche_vlynq/Makefile 2005-11-10 01:10:45.871576250 +0100
+@@ -0,0 +1,16 @@
++#
++# Makefile for the linux kernel.
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definitions are now in the main makefile...
++
++O_TARGET := avalanche_vlynq.o
++
++export-objs := vlynq_board.o
++
++obj-y += vlynq_drv.o vlynq_hal.o vlynq_board.o
++
++include $(TOPDIR)/Rules.make
+diff -urN linux.old/drivers/char/avalanche_vlynq/vlynq_board.c linux.dev/drivers/char/avalanche_vlynq/vlynq_board.c
+--- linux.old/drivers/char/avalanche_vlynq/vlynq_board.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/char/avalanche_vlynq/vlynq_board.c 2005-11-10 01:10:45.871576250 +0100
+@@ -0,0 +1,184 @@
++/*
++ * Jeff Harrell, jharrell@ti.com
++ * Copyright (C) 2001 Texas Instruments, Inc. All rights reserved.
++ *
++ * This program is free software; you can distribute 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 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.
++ *
++ * Texas Instruments Sangam specific setup.
++ */
++#include <linux/config.h>
++#include <linux/module.h>
++#include <asm/ar7/sangam.h>
++#include <asm/ar7/avalanche_misc.h>
++#include <asm/ar7/vlynq.h>
++
++#define SYS_VLYNQ_LOCAL_INTERRUPT_VECTOR 30 /* MSB - 1 bit */
++#define SYS_VLYNQ_REMOTE_INTERRUPT_VECTOR 31 /* MSB bit */
++#define SYS_VLYNQ_OPTIONS 0x7F; /* all options*/
++
++/* These defines are board specific */
++
++
++#define VLYNQ0_REMOTE_WINDOW1_OFFSET (0x0C000000)
++#define VLYNQ0_REMOTE_WINDOW1_SIZE (0x500)
++
++
++#define VLYNQ1_REMOTE_WINDOW1_OFFSET (0x0C000000)
++#define VLYNQ1_REMOTE_WINDOW1_SIZE (0x500)
++
++
++extern VLYNQ_DEV vlynqDevice0, vlynqDevice1;
++int vlynq_init_status[2] = {0, 0};
++EXPORT_SYMBOL(vlynq_init_status);
++static int reset_hack = 1;
++
++void vlynq_ar7wrd_dev_init()
++{
++ *(unsigned long*) AVALANCHE_GPIO_ENBL |= (1<<18);
++ vlynq_delay(20000);
++ *(unsigned long*) AVALANCHE_GPIO_DIR &= ~(1<<18);
++ vlynq_delay(20000);
++ *(unsigned long*) AVALANCHE_GPIO_DATA_OUT&= ~(1<<18);
++ vlynq_delay(50000);
++ *(unsigned long*) AVALANCHE_GPIO_DATA_OUT|= (1<<18);
++ vlynq_delay(50000);
++
++ /* Initialize the MIPS host vlynq driver for a given vlynq interface */
++ vlynqDevice0.dev_idx = 0; /* first vlynq module - this parameter is for reference only */
++ vlynqDevice0.module_base = AVALANCHE_LOW_VLYNQ_CONTROL_BASE; /* vlynq0 module base address */
++
++#if defined(CONFIG_VLYNQ_CLK_LOCAL)
++ vlynqDevice0.clk_source = VLYNQ_CLK_SOURCE_LOCAL;
++#else
++ vlynqDevice0.clk_source = VLYNQ_CLK_SOURCE_REMOTE;
++#endif
++ vlynqDevice0.clk_div = 0x01; /* board/hardware specific */
++ vlynqDevice0.state = VLYNQ_DRV_STATE_UNINIT; /* uninitialized module */
++
++ /* Populate vlynqDevice0.local_mem & Vlynq0.remote_mem based on system configuration */
++ /*Local memory configuration */
++
++ /* Demiurg : not good !*/
++#if 0
++ vlynqDevice0.local_mem.Txmap= AVALANCHE_LOW_VLYNQ_MEM_MAP_BASE & ~(0xc0000000) ; /* physical address */
++ vlynqDevice0.remote_mem.RxOffset[0]= VLYNQ0_REMOTE_WINDOW1_OFFSET; /* This is specific to the board on the other end */
++ vlynqDevice0.remote_mem.RxSize[0]=VLYNQ0_REMOTE_WINDOW1_SIZE;
++#endif
++
++ /* Demiurg : This is how it should be ! */
++ vlynqDevice0.local_mem.Txmap = PHYSADDR(AVALANCHE_LOW_VLYNQ_MEM_MAP_BASE);
++#define VLYNQ_ACX111_MEM_OFFSET 0xC0000000 /* Physical address of ACX111 memory */
++#define VLYNQ_ACX111_MEM_SIZE 0x00040000 /* Total size of the ACX111 memory */
++#define VLYNQ_ACX111_REG_OFFSET 0xF0000000 /* PHYS_ADDR of ACX111 control registers */
++#define VLYNQ_ACX111_REG_SIZE 0x00022000 /* Size of ACX111 registers area, MAC+PHY */
++#define ACX111_VL1_REMOTE_SIZE 0x1000000
++ vlynqDevice0.remote_mem.RxOffset[0] = VLYNQ_ACX111_MEM_OFFSET;
++ vlynqDevice0.remote_mem.RxSize[0] = VLYNQ_ACX111_MEM_SIZE ;
++ vlynqDevice0.remote_mem.RxOffset[1] = VLYNQ_ACX111_REG_OFFSET;
++ vlynqDevice0.remote_mem.RxSize[1] = VLYNQ_ACX111_REG_SIZE ;
++ vlynqDevice0.remote_mem.Txmap = 0;
++ vlynqDevice0.local_mem.RxOffset[0] = AVALANCHE_SDRAM_BASE;
++ vlynqDevice0.local_mem.RxSize[0] = ACX111_VL1_REMOTE_SIZE;
++
++
++ /* Local interrupt configuration */
++ vlynqDevice0.local_irq.intLocal = VLYNQ_INT_LOCAL; /* Host handles vlynq interrupts*/
++ vlynqDevice0.local_irq.intRemote = VLYNQ_INT_ROOT_ISR; /* vlynq root isr used */
++ vlynqDevice0.local_irq.map_vector = SYS_VLYNQ_LOCAL_INTERRUPT_VECTOR;
++ vlynqDevice0.local_irq.intr_ptr = 0; /* Since remote interrupts part of vlynq root isr this is unused */
++
++ /* Remote interrupt configuration */
++ vlynqDevice0.remote_irq.intLocal = VLYNQ_INT_REMOTE; /* MIPS handles interrupts */
++ vlynqDevice0.remote_irq.intRemote = VLYNQ_INT_ROOT_ISR; /* Not significant since MIPS handles interrupts */
++ vlynqDevice0.remote_irq.map_vector = SYS_VLYNQ_REMOTE_INTERRUPT_VECTOR;
++ vlynqDevice0. remote_irq.intr_ptr = AVALANCHE_INTC_BASE; /* Not significant since MIPS handles interrupts */
++
++ if(reset_hack != 1)
++ printk("About to re-init the VLYNQ.\n");
++
++ if(vlynq_init(&vlynqDevice0,VLYNQ_INIT_PERFORM_ALL)== 0)
++ {
++ /* Suraj added the following to keep the 1130 going. */
++ vlynq_interrupt_vector_set(&vlynqDevice0, 0 /* intr vector line running into 1130 vlynq */,
++ 0 /* intr mapped onto the interrupt register on remote vlynq and this vlynq */,
++ VLYNQ_REMOTE_DVC, 0 /* polarity active high */, 0 /* interrupt Level triggered */);
++
++ /* System wide interrupt is 80 for 1130, please note. */
++ vlynq_init_status[0] = 1;
++ reset_hack = 2;
++ }
++ else
++ {
++ if(reset_hack == 1)
++ printk("VLYNQ INIT FAILED: Please try cold reboot. \n");
++ else
++ printk("Failed to initialize the VLYNQ interface at insmod.\n");
++
++ }
++}
++
++void vlynq_dev_init(void)
++{
++ volatile unsigned int *reset_base = (unsigned int *) AVALANCHE_RESET_CONTROL_BASE;
++
++ *reset_base &= ~((1 << AVALANCHE_LOW_VLYNQ_RESET_BIT)); /* | (1 << AVALANCHE_HIGH_VLYNQ_RESET_BIT)); */
++
++ vlynq_delay(20000);
++
++ /* Bring vlynq out of reset if not already done */
++ *reset_base |= (1 << AVALANCHE_LOW_VLYNQ_RESET_BIT); /* | (1 << AVALANCHE_HIGH_VLYNQ_RESET_BIT); */
++ vlynq_delay(20000); /* Allowing sufficient time to VLYNQ to settle down.*/
++
++ vlynq_ar7wrd_dev_init( );
++
++}
++
++/* This function is board specific and should be ported for each board. */
++void remote_vlynq_dev_reset_ctrl(unsigned int module_reset_bit,
++ AVALANCHE_RESET_CTRL_T reset_ctrl)
++{
++ if(module_reset_bit >= 32)
++ return;
++
++ switch(module_reset_bit)
++ {
++ case 0:
++ if(OUT_OF_RESET == reset_ctrl)
++ {
++ if(reset_hack) return;
++
++ vlynq_delay(20000);
++ printk("Un-resetting the remote device.\n");
++ vlynq_dev_init();
++ printk("Re-initialized the VLYNQ.\n");
++ reset_hack = 2;
++ }
++ else if(IN_RESET == reset_ctrl)
++ {
++ *(unsigned long*) AVALANCHE_GPIO_DATA_OUT &= ~(1<<18);
++
++ vlynq_delay(20000);
++ printk("Resetting the remote device.\n");
++ reset_hack = 0;
++ }
++ else
++ ;
++ break;
++
++ default:
++ break;
++
++ }
++}
++
+diff -urN linux.old/drivers/char/avalanche_vlynq/vlynq_drv.c linux.dev/drivers/char/avalanche_vlynq/vlynq_drv.c
+--- linux.old/drivers/char/avalanche_vlynq/vlynq_drv.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/char/avalanche_vlynq/vlynq_drv.c 2005-11-10 01:10:45.891577500 +0100
+@@ -0,0 +1,243 @@
++/******************************************************************************
++ * FILE PURPOSE: Vlynq Linux Device Driver Source
++ ******************************************************************************
++ * FILE NAME: vlynq_drv.c
++ *
++ * DESCRIPTION: Vlynq Linux Device Driver Source
++ *
++ * REVISION HISTORY:
++ *
++ * Date Description Author
++ *-----------------------------------------------------------------------------
++ * 17 July 2003 Initial Creation Anant Gole
++ * 17 Dec 2003 Updates Sharath Kumar
++ *
++ * (C) Copyright 2003, Texas Instruments, Inc
++ *******************************************************************************/
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/miscdevice.h>
++#include <linux/smp_lock.h>
++#include <linux/delay.h>
++#include <linux/proc_fs.h>
++#include <linux/capability.h>
++#include <asm/ar7/avalanche_intc.h>
++#include <asm/ar7/sangam.h>
++#include <asm/ar7/vlynq.h>
++
++
++#define TI_VLYNQ_VERSION "0.2"
++
++/* debug on ? */
++#define VLYNQ_DEBUG
++
++/* Macro for debug and error printf's */
++#ifdef VLYNQ_DEBUG
++#define DBGPRINT printk
++#else
++#define DBGPRINT(x)
++#endif
++
++#define ERRPRINT printk
++
++/* Define the max vlynq ports this driver will support.
++ Device name strings are statically added here */
++#define MAX_VLYNQ_PORTS 2
++
++
++/* Type define for VLYNQ private structure */
++typedef struct vlynqPriv{
++ int irq;
++ VLYNQ_DEV *vlynqDevice;
++}VLYNQ_PRIV;
++
++extern int vlynq_init_status[2];
++
++/* Extern Global variable for vlynq devices used in initialization of the vlynq device
++ * These variables need to be populated/initialized by the system as part of initialization
++ * process. The vlynq enumerator can run at initialization and populate these globals
++ */
++
++VLYNQ_DEV vlynqDevice0;
++VLYNQ_DEV vlynqDevice1;
++
++/* Defining dummy macro AVALANCHE_HIGH_VLYNQ_INT to take
++ * care of compilation in case of single vlynq device
++ */
++
++#ifndef AVALANCHE_HIGH_VLYNQ_INT
++#define AVALANCHE_HIGH_VLYNQ_INT 0
++#endif
++
++
++
++/* vlynq private object */
++VLYNQ_PRIV vlynq_priv[CONFIG_AR7_VLYNQ_PORTS] = {
++ { LNXINTNUM(AVALANCHE_LOW_VLYNQ_INT),&vlynqDevice0},
++ { LNXINTNUM(AVALANCHE_HIGH_VLYNQ_INT),&vlynqDevice1},
++};
++
++extern void vlynq_dev_init(void);
++
++
++/* =================================== all the operations */
++
++static int
++vlynq_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
++{
++ return 0;
++}
++
++static struct file_operations vlynq_fops = {
++ owner: THIS_MODULE,
++ ioctl: vlynq_ioctl,
++};
++
++/* Vlynq device object */
++static struct miscdevice vlynq_dev [MAX_VLYNQ_PORTS] = {
++ { MISC_DYNAMIC_MINOR , "vlynq0", &vlynq_fops },
++ { MISC_DYNAMIC_MINOR , "vlynq1", &vlynq_fops },
++};
++
++
++/* Proc read function */
++static int
++vlynq_read_link_proc(char *buf, char **start, off_t offset, int count, int *eof, void *unused)
++{
++ int instance;
++ int len = 0;
++
++ len += sprintf(buf +len,"VLYNQ Devices : %d\n",CONFIG_AR7_VLYNQ_PORTS);
++
++ for(instance =0;instance < CONFIG_AR7_VLYNQ_PORTS;instance++)
++ {
++ int link_state;
++ char *link_msg[] = {" DOWN "," UP "};
++
++ if(vlynq_init_status[instance] == 0)
++ link_state = 0;
++
++ else if (vlynq_link_check(vlynq_priv[instance].vlynqDevice))
++ link_state = 1;
++
++ else
++ link_state = 0;
++
++ len += sprintf(buf + len, "VLYNQ %d: Link state: %s\n",instance,link_msg[link_state]);
++
++ }
++ /* Print info about vlynq device 1 */
++
++ return len;
++}
++
++
++/* Proc function to display driver version */
++static int
++vlynq_read_ver_proc(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++{
++ int instance;
++ int len=0;
++
++ len += sprintf(buf +len,"\nTI Linux VLYNQ Driver Version %s\n",TI_VLYNQ_VERSION);
++ return len;
++}
++
++
++
++
++/* Wrapper for vlynq ISR */
++static void lnx_vlynq_root_isr(int irq, void * arg, struct pt_regs *regs)
++{
++ vlynq_root_isr(arg);
++}
++
++/* =================================== init and cleanup */
++
++int vlynq_init_module(void)
++{
++ int ret;
++ int unit = 0;
++ int instance_count = CONFIG_AR7_VLYNQ_PORTS;
++ volatile int *ptr;
++
++ vlynq_dev_init();
++
++ DBGPRINT("Vlynq CONFIG_AR7_VLYNQ_PORTS=%d\n", CONFIG_AR7_VLYNQ_PORTS);
++ /* If num of configured vlynq ports > supported by driver return error */
++ if (instance_count > MAX_VLYNQ_PORTS)
++ {
++ ERRPRINT("ERROR: vlynq_init_module(): Max %d supported\n", MAX_VLYNQ_PORTS);
++ return (-1);
++ }
++
++ /* register the misc device */
++ for (unit = 0; unit < CONFIG_AR7_VLYNQ_PORTS; unit++)
++ {
++ ret = misc_register(&vlynq_dev[unit]);
++
++ if(ret < 0)
++ {
++ ERRPRINT("ERROR:Could not register vlynq device:%d\n",unit);
++ continue;
++ }
++ else
++ DBGPRINT("Vlynq Device %s registered with minor no %d as misc device. Result=%d\n",
++ vlynq_dev[unit].name, vlynq_dev[unit].minor, ret);
++#if 0
++
++ DBGPRINT("Calling vlynq init\n");
++
++ /* Read the global variable for VLYNQ device structure and initialize vlynq driver */
++ ret = vlynq_init(vlynq_priv[unit].vlynqDevice,VLYNQ_INIT_PERFORM_ALL );
++#endif
++
++ if(vlynq_init_status[unit] == 0)
++ {
++ printk("VLYNQ %d : init failed\n",unit);
++ continue;
++ }
++
++ /* Check link before proceeding */
++ if (!vlynq_link_check(vlynq_priv[unit].vlynqDevice))
++ {
++ DBGPRINT("\nError: Vlynq link not available.trying once before Exiting");
++ }
++ else
++ {
++ DBGPRINT("Vlynq instance:%d Link UP\n",unit);
++
++ /* Install the vlynq local root ISR */
++ request_irq(vlynq_priv[unit].irq,lnx_vlynq_root_isr,0,vlynq_dev[unit].name,vlynq_priv[unit].vlynqDevice);
++ }
++ }
++
++ proc_mkdir("avalanche", NULL);
++ /* Creating proc entry for the devices */
++ create_proc_read_entry("avalanche/vlynq_link", 0, NULL, vlynq_read_link_proc, NULL);
++ create_proc_read_entry("avalanche/vlynq_ver", 0, NULL, vlynq_read_ver_proc, NULL);
++
++ return 0;
++}
++
++void vlynq_cleanup_module(void)
++{
++ int unit = 0;
++
++ for (unit = 0; unit < CONFIG_AR7_VLYNQ_PORTS; unit++)
++ {
++ DBGPRINT("vlynq_cleanup_module(): Unregistring misc device %s\n",vlynq_dev[unit].name);
++ misc_deregister(&vlynq_dev[unit]);
++ }
++
++ remove_proc_entry("avalanche/vlynq_link", NULL);
++ remove_proc_entry("avalanche/vlynq_ver", NULL);
++}
++
++
++module_init(vlynq_init_module);
++module_exit(vlynq_cleanup_module);
++
+diff -urN linux.old/drivers/char/avalanche_vlynq/vlynq_hal.c linux.dev/drivers/char/avalanche_vlynq/vlynq_hal.c
+--- linux.old/drivers/char/avalanche_vlynq/vlynq_hal.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/char/avalanche_vlynq/vlynq_hal.c 2005-11-10 01:10:45.975582750 +0100
+@@ -0,0 +1,1214 @@
++/***************************************************************************
++**+----------------------------------------------------------------------+**
++**| **** |**
++**| **** |**
++**| ******o*** |**
++**| ********_///_**** |**
++**| ***** /_//_/ **** |**
++**| ** ** (__/ **** |**
++**| ********* |**
++**| **** |**
++**| *** |**
++**| |**
++**| Copyright (c) 2003 Texas Instruments Incorporated |**
++**| ALL RIGHTS RESERVED |**
++**| |**
++**| Permission is hereby granted to licensees of Texas Instruments |**
++**| Incorporated (TI) products to use this computer program for the sole |**
++**| purpose of implementing a licensee product based on TI products. |**
++**| No other rights to reproduce, use, or disseminate this computer |**
++**| program, whether in part or in whole, are granted. |**
++**| |**
++**| TI makes no representation or warranties with respect to the |**
++**| performance of this computer program, and specifically disclaims |**
++**| any responsibility for any damages, special or consequential, |**
++**| connected with the use of this program. |**
++**| |**
++**+----------------------------------------------------------------------+**
++***************************************************************************/
++
++/***************************************************************************
++ * ------------------------------------------------------------------------------
++ * Module : vlynq_hal.c
++ * Description : This file implements VLYNQ HAL API.
++ * ------------------------------------------------------------------------------
++ ***************************************************************************/
++
++#include <linux/stddef.h>
++#include <linux/types.h>
++#include <asm/ar7/vlynq.h>
++
++/**** Local Function prototypes *******/
++static int vlynqInterruptInit(VLYNQ_DEV *pdev);
++static void vlynq_configClock(VLYNQ_DEV *pdev);
++
++/*** Second argument must be explicitly type casted to
++ * (VLYNQ_DEV*) inside the following functions */
++static void vlynq_local_module_isr(void *arg1, void *arg2, void *arg3);
++static void vlynq_remote_module_isr(void *arg1, void *arg2, void *arg3);
++
++
++volatile int vlynq_delay_value = 0;
++
++/* Code adopted from original vlynq driver */
++void vlynq_delay(unsigned int clktime)
++{
++ int i = 0;
++ volatile int *ptr = &vlynq_delay_value;
++ *ptr = 0;
++
++ /* We are assuming that the each cycle takes about
++ * 23 assembly instructions. */
++ for(i = 0; i < (clktime + 23)/23; i++)
++ {
++ *ptr = *ptr + 1;
++ }
++}
++
++
++/* ----------------------------------------------------------------------------
++ * Function : vlynq_configClock()
++ * Description: Configures clock settings based on input parameters
++ * Adapted from original vlyna driver from Cable
++ */
++static void vlynq_configClock(VLYNQ_DEV * pdev)
++{
++ unsigned int tmp;
++
++ switch( pdev->clk_source)
++ {
++ case VLYNQ_CLK_SOURCE_LOCAL: /* we output the clock, clk_div in range [1..8]. */
++ tmp = ((pdev->clk_div - 1) << 16) | VLYNQ_CTL_CLKDIR_MASK ;
++ VLYNQ_CTRL_REG = tmp;
++ VLYNQ_R_CTRL_REG = 0ul;
++ break;
++ case VLYNQ_CLK_SOURCE_REMOTE: /* we need to set the clock pin as input */
++ VLYNQ_CTRL_REG = 0ul;
++ tmp = ((pdev->clk_div - 1) << 16) | VLYNQ_CTL_CLKDIR_MASK ;
++ VLYNQ_R_CTRL_REG = tmp;
++ break;
++ default: /* do nothing about the clock, but clear other bits. */
++ tmp = ~(VLYNQ_CTL_CLKDIR_MASK | VLYNQ_CTL_CLKDIV_MASK);
++ VLYNQ_CTRL_REG &= tmp;
++ break;
++ }
++}
++
++ /* ----------------------------------------------------------------------------
++ * Function : vlynq_link_check()
++ * Description: This function checks the current VLYNQ for a link.
++ * An arbitrary amount of time is allowed for the link to come up .
++ * Returns 0 for "no link / failure " and 1 for "link available".
++ * -----------------------------------------------------------------------------
++ */
++unsigned int vlynq_link_check( VLYNQ_DEV * pdev)
++{
++ /*sleep for 64 cycles, allow link to come up*/
++ vlynq_delay(64);
++
++ /* check status register return OK if link is found. */
++ if (VLYNQ_STATUS_REG & VLYNQ_STS_LINK_MASK)
++ {
++ return 1; /* Link Available */
++ }
++ else
++ {
++ return 0; /* Link Failure */
++ }
++}
++
++/* ----------------------------------------------------------------------------
++ * Function : vlynq_init()
++ * Description: Initialization function accepting paramaters for VLYNQ module
++ * initialization. The Options bitmap decides what operations are performed
++ * as a part of initialization. The Input parameters are obtained through the
++ * sub fields of VLYNQ_DEV structure.
++ */
++
++int vlynq_init(VLYNQ_DEV *pdev, VLYNQ_INIT_OPTIONS options)
++{
++ unsigned int map;
++ unsigned int val=0,cnt,tmp;
++ unsigned int counter=0;
++ VLYNQ_INTERRUPT_CNTRL *intSetting=NULL;
++
++ /* validate arguments */
++ if( VLYNQ_OUTRANGE(pdev->clk_source, VLYNQ_CLK_SOURCE_REMOTE, VLYNQ_CLK_SOURCE_NONE) ||
++ VLYNQ_OUTRANGE(pdev->clk_div, 8, 1) )
++ {
++ return VLYNQ_INVALID_ARG;
++ }
++
++ /** perform all sanity checks first **/
++ if(pdev->state != VLYNQ_DRV_STATE_UNINIT)
++ return VLYNQ_INVALID_DRV_STATE;
++
++ /** Initialize local and remote register set addresses- additional
++ * provision to access the registers directly if need be */
++ pdev->local = (VLYNQ_REG_SET*)pdev->module_base;
++ pdev->remote = (VLYNQ_REG_SET*) (pdev->module_base + VLYNQ_REMOTE_REGS_OFFSET);
++
++ /* Detect faulty int configuration that might induce int pkt looping */
++ if ( (options & VLYNQ_INIT_LOCAL_INTERRUPTS) && (options & VLYNQ_INIT_REMOTE_INTERRUPTS) )
++ {
++ /* case when both local and remote are configured */
++ if((pdev->local_irq.intLocal== VLYNQ_INT_REMOTE ) /* interrupts transfered to remote from local */
++ && (pdev->remote_irq.intLocal== VLYNQ_INT_REMOTE) /* interrupts transfered from remote to local */
++ && ((pdev->local_irq.intRemote == VLYNQ_INT_ROOT_ISR) || (pdev->remote_irq.intRemote == VLYNQ_INT_ROOT_ISR)) )
++ {
++ return (VLYNQ_INT_CONFIG_ERR);
++ }
++ }
++
++ pdev->state = VLYNQ_DRV_STATE_ININIT;
++ pdev->intCount = 0;
++ pdev->isrCount = 0;
++
++ /*** Its assumed that the vlynq module has been brought out of reset
++ * before invocation of vlynq_init. Since, this operation is board specific
++ * it must be handled outside this generic driver */
++
++ /* Assert reset the remote device, call reset_cb,
++ * reset CB holds Reset according to the device needs. */
++ VLYNQ_RESETCB(VLYNQ_RESET_ASSERT);
++
++ /* Handle VLYNQ clock, HW default (Sense On Reset) is
++ * usually input for all the devices. */
++ if (options & VLYNQ_INIT_CONFIG_CLOCK)
++ {
++ vlynq_configClock(pdev);
++ }
++
++ /* Call reset_cb again. It will release the remote device
++ * from reset, and wait for a while. */
++ VLYNQ_RESETCB(VLYNQ_RESET_DEASSERT);
++
++ if(options & VLYNQ_INIT_CHECK_LINK )
++ {
++ /* Check for link up during initialization*/
++ while( counter < 25 )
++ {
++ /* loop around giving a chance for link status to settle down */
++ counter++;
++ if(vlynq_link_check(pdev))
++ {
++ /* Link is up exit loop*/
++ break;
++ }
++
++ vlynq_delay(4000);
++ }/*end of while counter loop */
++
++ if(!vlynq_link_check(pdev))
++ {
++ /* Handle this case as abort */
++ pdev->state = VLYNQ_DRV_STATE_ERROR;
++ VLYNQ_RESETCB( VLYNQ_RESET_INITFAIL);
++ return VLYNQ_LINK_DOWN;
++ }/* end of if not vlynq_link_check conditional block */
++
++ }/*end of if options & VLYNQ_INIT_CHECK_LINK conditional block */
++
++
++ if (options & VLYNQ_INIT_LOCAL_MEM_REGIONS)
++ {
++ /* Initialise local memory regions . This initialization lets
++ * the local host access remote device memory regions*/
++ int i;
++
++ /* configure the VLYNQ portal window to a PHYSICAL
++ * address of the local CPU */
++ VLYNQ_ALIGN4(pdev->local_mem.Txmap);
++ VLYNQ_TXMAP_REG = (pdev->local_mem.Txmap);
++
++ /*This code assumes input parameter is itself a physical address */
++ for(i=0; i < VLYNQ_MAX_MEMORY_REGIONS ; i++)
++ {
++ /* Physical address on the remote */
++ map = i+1;
++ VLYNQ_R_RXMAP_SIZE_REG(map) = 0;
++ if( pdev->remote_mem.RxSize[i])
++ {
++ VLYNQ_ALIGN4(pdev->remote_mem.RxOffset[i]);
++ VLYNQ_ALIGN4(pdev->remote_mem.RxSize[i]);
++ VLYNQ_R_RXMAP_OFFSET_REG(map) = pdev->remote_mem.RxOffset[i];
++ VLYNQ_R_RXMAP_SIZE_REG(map) = pdev->remote_mem.RxSize[i];
++ }
++ }
++ }
++
++ if(options & VLYNQ_INIT_REMOTE_MEM_REGIONS )
++ {
++ int i;
++
++ /* Initialise remote memory regions. This initialization lets remote
++ * device access local host memory regions. It configures the VLYNQ portal
++ * window to a PHYSICAL address of the remote */
++ VLYNQ_ALIGN4(pdev->remote_mem.Txmap);
++ VLYNQ_R_TXMAP_REG = pdev->remote_mem.Txmap;
++
++ for( i=0; i<VLYNQ_MAX_MEMORY_REGIONS; i++)
++ {
++ /* Physical address on the local */
++ map = i+1;
++ VLYNQ_RXMAP_SIZE_REG(map) = 0;
++ if( pdev->local_mem.RxSize[i])
++ {
++ VLYNQ_ALIGN4(pdev->local_mem.RxOffset[i]);
++ VLYNQ_ALIGN4(pdev->local_mem.RxSize[i]);
++ VLYNQ_RXMAP_OFFSET_REG(map) = (pdev->local_mem.RxOffset[i]);
++ VLYNQ_RXMAP_SIZE_REG(map) = (pdev->local_mem.RxSize[i]);
++ }
++ }
++ }
++
++ /* Adapted from original vlynq driver from cable - Calculate VLYNQ bus width */
++ pdev->width = 3 + VLYNQ_STATUS_FLD_WIDTH(VLYNQ_STATUS_REG)
++ + VLYNQ_STATUS_FLD_WIDTH(VLYNQ_R_STATUS_REG);
++
++ /* chance to initialize the device, e.g. to boost VLYNQ
++ * clock by modifying pdev->clk_div or and verify the width. */
++ VLYNQ_RESETCB(VLYNQ_RESET_LINKESTABLISH);
++
++ /* Handle VLYNQ clock, HW default (Sense On Reset) is
++ * usually input for all the devices. */
++ if(options & VLYNQ_INIT_CONFIG_CLOCK )
++ {
++ vlynq_configClock(pdev);
++ }
++
++ /* last check for link*/
++ if(options & VLYNQ_INIT_CHECK_LINK )
++ {
++ /* Final Check for link during initialization*/
++ while( counter < 25 )
++ {
++ /* loop around giving a chance for link status to settle down */
++ counter++;
++ if(vlynq_link_check(pdev))
++ {
++ /* Link is up exit loop*/
++ break;
++ }
++
++ vlynq_delay(4000);
++ }/*end of while counter loop */
++
++ if(!vlynq_link_check(pdev))
++ {
++ /* Handle this case as abort */
++ pdev->state = VLYNQ_DRV_STATE_ERROR;
++ VLYNQ_RESETCB( VLYNQ_RESET_INITFAIL);
++ return VLYNQ_LINK_DOWN;
++ }/* end of if not vlynq_link_check conditional block */
++
++ } /* end of if options & VLYNQ_INIT_CHECK_LINK */
++
++ if(options & VLYNQ_INIT_LOCAL_INTERRUPTS )
++ {
++ /* Configure local interrupt settings */
++ intSetting = &(pdev->local_irq);
++
++ /* Map local module status interrupts to interrupt vector*/
++ val = intSetting->map_vector << VLYNQ_CTL_INTVEC_SHIFT ;
++
++ /* enable local module status interrupts */
++ val |= 0x01 << VLYNQ_CTL_INTEN_SHIFT;
++
++ if ( intSetting->intLocal == VLYNQ_INT_LOCAL )
++ {
++ /*set the intLocal bit*/
++ val |= 0x01 << VLYNQ_CTL_INTLOCAL_SHIFT;
++ }
++
++ /* Irrespective of whether interrupts are handled locally, program
++ * int2Cfg. Error checking for accidental loop(when intLocal=0 and int2Cfg=1
++ * i.e remote packets are set intPending register->which will result in
++ * same packet being sent out) has been done already
++ */
++
++ if (intSetting->intRemote == VLYNQ_INT_ROOT_ISR)
++ {
++ /* Set the int2Cfg register, so that remote interrupt
++ * packets are written to intPending register */
++ val |= 0x01 << VLYNQ_CTL_INT2CFG_SHIFT;
++
++ /* Set intPtr register to point to intPending register */
++ VLYNQ_INT_PTR_REG = VLYNQ_INT_PENDING_REG_PTR ;
++ }
++ else
++ {
++ /*set the interrupt pointer register*/
++ VLYNQ_INT_PTR_REG = intSetting->intr_ptr;
++ /* Dont bother to modify int2Cfg as it would be zero */
++ }
++
++ /** Clear bits related to INT settings in control register **/
++ VLYNQ_CTRL_REG = VLYNQ_CTRL_REG & (~VLYNQ_CTL_INTFIELDS_CLEAR_MASK);
++
++ /** Or the bits to be set with Control register **/
++ VLYNQ_CTRL_REG = VLYNQ_CTRL_REG | val;
++
++ /* initialise local ICB */
++ if(vlynqInterruptInit(pdev)==VLYNQ_MEMALLOC_FAIL)
++ return VLYNQ_MEMALLOC_FAIL;
++
++ /* Install handler for local module status interrupts. By default when
++ * local interrupt setting is initialised, the local module status are
++ * enabled and handler hooked up */
++ if(vlynq_install_isr(pdev, intSetting->map_vector, vlynq_local_module_isr,
++ pdev, NULL, NULL) == VLYNQ_INVALID_ARG)
++ return VLYNQ_INVALID_ARG;
++ } /* end of init local interrupts */
++
++ if(options & VLYNQ_INIT_REMOTE_INTERRUPTS )
++ {
++ /* Configure remote interrupt settings from configuration */
++ intSetting = &(pdev->remote_irq);
++
++ /* Map remote module status interrupts to remote interrupt vector*/
++ val = intSetting->map_vector << VLYNQ_CTL_INTVEC_SHIFT ;
++ /* enable remote module status interrupts */
++ val |= 0x01 << VLYNQ_CTL_INTEN_SHIFT;
++
++ if ( intSetting->intLocal == VLYNQ_INT_LOCAL )
++ {
++ /*set the intLocal bit*/
++ val |= 0x01 << VLYNQ_CTL_INTLOCAL_SHIFT;
++ }
++
++ /* Irrespective of whether interrupts are handled locally, program
++ * int2Cfg. Error checking for accidental loop(when intLocal=0 and int2Cfg=1
++ * i.e remote packets are set intPending register->which will result in
++ * same packet being sent out) has been done already
++ */
++
++ if (intSetting->intRemote == VLYNQ_INT_ROOT_ISR)
++ {
++ /* Set the int2Cfg register, so that remote interrupt
++ * packets are written to intPending register */
++ val |= 0x01 << VLYNQ_CTL_INT2CFG_SHIFT;
++ /* Set intPtr register to point to intPending register */
++ VLYNQ_R_INT_PTR_REG = VLYNQ_R_INT_PENDING_REG_PTR ;
++ }
++ else
++ {
++ /*set the interrupt pointer register*/
++ VLYNQ_R_INT_PTR_REG = intSetting->intr_ptr;
++ /* Dont bother to modify int2Cfg as it would be zero */
++ }
++
++ if( (intSetting->intLocal == VLYNQ_INT_REMOTE) &&
++ (options & VLYNQ_INIT_LOCAL_INTERRUPTS) &&
++ (pdev->local_irq.intRemote == VLYNQ_INT_ROOT_ISR) )
++ {
++ /* Install handler for remote module status interrupts. By default when
++ * remote interrupts are forwarded to local root_isr then remote_module_isr is
++ * enabled and handler hooked up */
++ if(vlynq_install_isr(pdev,intSetting->map_vector,vlynq_remote_module_isr,
++ pdev, NULL, NULL) == VLYNQ_INVALID_ARG)
++ return VLYNQ_INVALID_ARG;
++ }
++
++
++ /** Clear bits related to INT settings in control register **/
++ VLYNQ_R_CTRL_REG = VLYNQ_R_CTRL_REG & (~VLYNQ_CTL_INTFIELDS_CLEAR_MASK);
++
++ /** Or the bits to be set with the remote Control register **/
++ VLYNQ_R_CTRL_REG = VLYNQ_R_CTRL_REG | val;
++
++ } /* init remote interrupt settings*/
++
++ if(options & VLYNQ_INIT_CLEAR_ERRORS )
++ {
++ /* Clear errors during initialization */
++ tmp = VLYNQ_STATUS_REG & (VLYNQ_STS_RERROR_MASK | VLYNQ_STS_LERROR_MASK);
++ VLYNQ_STATUS_REG = tmp;
++ tmp = VLYNQ_R_STATUS_REG & (VLYNQ_STS_RERROR_MASK | VLYNQ_STS_LERROR_MASK);
++ VLYNQ_R_STATUS_REG = tmp;
++ }
++
++ /* clear int status */
++ val = VLYNQ_INT_STAT_REG;
++ VLYNQ_INT_STAT_REG = val;
++
++ /* finish initialization */
++ pdev->state = VLYNQ_DRV_STATE_RUN;
++ VLYNQ_RESETCB( VLYNQ_RESET_INITOK);
++ return VLYNQ_SUCCESS;
++
++}
++
++
++/* ----------------------------------------------------------------------------
++ * Function : vlynqInterruptInit()
++ * Description: This local function is used to set up the ICB table for the
++ * VLYNQ_STATUS_REG vlynq module. The input parameter "pdev" points the vlynq
++ * device instance whose ICB is allocated.
++ * Return : returns VLYNQ_SUCCESS or vlynq error for failure
++ * -----------------------------------------------------------------------------
++ */
++static int vlynqInterruptInit(VLYNQ_DEV *pdev)
++{
++ int i, numslots;
++
++ /* Memory allocated statically.
++ * Initialise ICB,free list.Indicate primary slot empty.
++ * Intialise intVector <==> map_vector translation table*/
++ for(i=0; i < VLYNQ_NUM_INT_BITS; i++)
++ {
++ pdev->pIntrCB[i].isr = NULL;
++ pdev->pIntrCB[i].next = NULL; /*nothing chained */
++ pdev->vector_map[i] = -1; /* indicates unmapped */
++ }
++
++ /* In the ICB slots, [VLYNQ_NUM_INT_BITS i.e 32 to ICB array size) are expansion slots
++ * required only when interrupt chaining/sharing is supported. In case
++ * of chained interrupts the list starts from primary slot and the
++ * additional slots are obtained from the common free area */
++
++ /* Initialise freelist */
++
++ numslots = VLYNQ_NUM_INT_BITS + VLYNQ_IVR_CHAIN_SLOTS;
++
++ if (numslots > VLYNQ_NUM_INT_BITS)
++ {
++ pdev->freelist = &(pdev->pIntrCB[VLYNQ_NUM_INT_BITS]);
++
++ for(i = VLYNQ_NUM_INT_BITS; i < (numslots-1) ; i++)
++ {
++ pdev->pIntrCB[i].next = &(pdev->pIntrCB[i+1]);
++ pdev->pIntrCB[i].isr = NULL;
++ }
++ pdev->pIntrCB[i].next=NULL; /* Indicate end of freelist*/
++ pdev->pIntrCB[i].isr=NULL;
++ }
++ else
++ {
++ pdev->freelist = NULL;
++ }
++
++ /** Reset mapping for IV 0-7 **/
++ VLYNQ_IVR_03TO00_REG = 0;
++ VLYNQ_IVR_07TO04_REG = 0;
++
++ return VLYNQ_SUCCESS;
++}
++
++/** remember that hooking up of root ISR handler with the interrupt controller
++ * is not done as a part of this driver. Typically, it must be done after
++ * invoking vlynq_init*/
++
++
++ /* ----------------------------------------------------------------------------
++ * ISR with the SOC interrupt controller. This ISR typically scans
++ * the Int PENDING/SET register in the VLYNQ module and calls the
++ * appropriate ISR associated with the correponding vector number.
++ * -----------------------------------------------------------------------------
++ */
++void vlynq_root_isr(void *arg)
++{
++ int source; /* Bit position of pending interrupt, start from 0 */
++ unsigned int interrupts, clrInterrupts;
++ VLYNQ_DEV * pdev;
++ VLYNQ_INTR_CNTRL_ICB *entry;
++
++ pdev=(VLYNQ_DEV*)(arg); /*obtain the vlynq device pointer*/
++
++ interrupts = VLYNQ_INT_STAT_REG; /* Get the list of pending interrupts */
++ VLYNQ_INT_STAT_REG = interrupts; /* clear the int CR register */
++ clrInterrupts = interrupts; /* save them for further analysis */
++
++ debugPrint("vlynq_root_isr: dev %u. INTCR = 0x%08lx\n", pdev->dev_idx, clrInterrupts,0,0,0,0);
++
++ /* Scan interrupt bits */
++ source =0;
++ while( clrInterrupts != 0)
++ {
++ /* test if bit is set? */
++ if( 0x1ul & clrInterrupts)
++ {
++ entry = &(pdev->pIntrCB[source]); /* Get the ISR entry */
++ pdev->intCount++; /* update interrupt count */
++ if(entry->isr != NULL)
++ {
++ do
++ {
++ pdev->isrCount++; /* update isr invocation count */
++ /* Call the user ISR and update the count for ISR */
++ entry->isrCount++;
++ entry->isr(entry->arg1, entry->arg2, entry->arg3);
++ if (entry->next == NULL) break;
++ entry = entry->next;
++
++ } while (entry->isr != NULL);
++ }
++ else
++ {
++ debugPrint(" ISR not installed for vlynq vector:%d\n",source,0,0,0,0,0);
++ }
++ }
++ clrInterrupts >>= 1; /* Next source bit */
++ ++source;
++ } /* endWhile clrInterrupts != 0 */
++}
++
++
++ /* ----------------------------------------------------------------------------
++ * Function : vlynq_local__module_isr()
++ * Description: This ISR is attached to the local VLYNQ interrupt vector
++ * by the Vlynq Driver when local interrupts are being handled. i.e.
++ * intLocal=1. This ISR handles local Vlynq module status interrupts only
++ * AS a part of this ISR, user callback in VLYNQ_DEV structure
++ * is invoked.
++ * VLYNQ_DEV is passed as arg1. arg2 and arg3 are unused.
++ * -----------------------------------------------------------------------------
++ */
++static void vlynq_local_module_isr(void *arg1,void *arg2, void *arg3)
++{
++ VLYNQ_REPORT_CB func;
++ unsigned int dwStatRegVal;
++ VLYNQ_DEV * pdev;
++
++ pdev = (VLYNQ_DEV*) arg1;
++ /* Callback function is read from the device pointer that is passed as an argument */
++ func = pdev->report_cb;
++
++ /* read local status register */
++ dwStatRegVal = VLYNQ_STATUS_REG;
++
++ /* clear pending events */
++ VLYNQ_STATUS_REG = dwStatRegVal;
++
++ /* invoke user callback */
++ if( func != NULL)
++ func( pdev, VLYNQ_LOCAL_DVC, dwStatRegVal);
++
++}
++
++ /* ----------------------------------------------------------------------------
++ * Function : vlynq_remote_module_isr()
++ * Description: This ISR is attached to the remote VLYNQ interrupt vector
++ * by the Vlynq Driver when remote interrupts are being handled locally. i.e.
++ * intLocal=1. This ISR handles local Vlynq module status interrupts only
++ * AS a part of this ISR, user callback in VLYNQ_DEV structure
++ * is invoked.
++ * The parameters irq,regs ar unused.
++ * -----------------------------------------------------------------------------
++ */
++static void vlynq_remote_module_isr(void *arg1,void *arg2, void *arg3)
++{
++ VLYNQ_REPORT_CB func;
++ unsigned int dwStatRegVal;
++ VLYNQ_DEV * pdev;
++
++
++ pdev = (VLYNQ_DEV*) arg1;
++
++ /* Callback function is read from the device pointer that is passed as an argument */
++ func = pdev->report_cb;
++
++ /* read local status register */
++ dwStatRegVal = VLYNQ_R_STATUS_REG;
++
++ /* clear pending events */
++ VLYNQ_R_STATUS_REG = dwStatRegVal;
++
++ /* invoke user callback */
++ if( func != NULL)
++ func( pdev, VLYNQ_REMOTE_DVC, dwStatRegVal);
++
++}
++
++/* ----------------------------------------------------------------------------
++ * Function : vlynq_interrupt_get_count()
++ * Description: This function returns the number of times a particular intr
++ * has been invoked.
++ *
++ * It returns 0, if erroneous map_vector is specified or if the corres isr
++ * has not been registered with VLYNQ.
++ */
++unsigned int vlynq_interrupt_get_count(VLYNQ_DEV *pdev,
++ unsigned int map_vector)
++{
++ VLYNQ_INTR_CNTRL_ICB *entry;
++ unsigned int count = 0;
++
++ if (map_vector > (VLYNQ_NUM_INT_BITS-1))
++ return count;
++
++ entry = &(pdev->pIntrCB[map_vector]);
++
++ if (entry)
++ count = entry->isrCount;
++
++ return (count);
++}
++
++
++/* ----------------------------------------------------------------------------
++ * Function : vlynq_install_isr()
++ * Description: This function installs ISR for Vlynq interrupt vector
++ * bits(in IntPending register). This function should be used only when
++ * Vlynq interrupts are being handled locally(remote may be programmed to send
++ * interrupt packets).Also, the int2cfg should be 1 and the least significant
++ * 8 bits of the Interrupt Pointer Register must point to Interrupt
++ * Pending/Set Register).
++ * If host int2cfg=0 and the Interrupt Pointer register contains
++ * the address of the interrupt set register in the interrupt controller
++ * module of the local device , then the ISR for the remote interrupt must be
++ * directly registered with the Interrupt controller and must not use this API
++ * Note: this function simply installs the ISR in ICB It doesnt modify
++ * any register settings
++ */
++int
++vlynq_install_isr(VLYNQ_DEV *pdev,
++ unsigned int map_vector,
++ VLYNQ_INTR_CNTRL_ISR isr,
++ void *arg1, void *arg2, void *arg3)
++{
++ VLYNQ_INTR_CNTRL_ICB *entry;
++
++ if ( (map_vector > (VLYNQ_NUM_INT_BITS-1)) || (isr == NULL) )
++ return VLYNQ_INVALID_ARG;
++
++ entry = &(pdev->pIntrCB[map_vector]);
++
++ if(entry->isr == NULL)
++ {
++ entry->isr = isr;
++ entry->arg1 = arg1;
++ entry->arg2 = arg2;
++ entry->arg3 = arg3;
++ entry->next = NULL;
++ }
++ else
++ {
++ /** No more empty slots,return error */
++ if(pdev->freelist == NULL)
++ return VLYNQ_MEMALLOC_FAIL;
++
++ while(entry->next != NULL)
++ {
++ entry = entry->next;
++ }
++
++ /* Append new node to the chain */
++ entry->next = pdev->freelist;
++ /* Remove the appended node from freelist */
++ pdev->freelist = pdev->freelist->next;
++ entry= entry->next;
++
++ /*** Set the ICB fields ***/
++ entry->isr = isr;
++ entry->arg1 = arg1;
++ entry->arg2 = arg2;
++ entry->arg3 = arg3;
++ entry->next = NULL;
++ }
++
++ return VLYNQ_SUCCESS;
++}
++
++
++
++/* ----------------------------------------------------------------------------
++ * Function : vlynq_uninstall_isr
++ * Description: This function is used to uninstall a previously
++ * registered ISR. In case of shared/chained interrupts, the
++ * void * arg parameter must uniquely identify the ISR to be
++ * uninstalled.
++ * Note: this function simply uninstalls the ISR in ICB
++ * It doesnt modify any register settings
++ */
++int
++vlynq_uninstall_isr(VLYNQ_DEV *pdev,
++ unsigned int map_vector,
++ void *arg1, void *arg2, void *arg3)
++{
++ VLYNQ_INTR_CNTRL_ICB *entry,*temp;
++
++ if (map_vector > (VLYNQ_NUM_INT_BITS-1))
++ return VLYNQ_INVALID_ARG;
++
++ entry = &(pdev->pIntrCB[map_vector]);
++
++ if(entry->isr == NULL )
++ return VLYNQ_ISR_NON_EXISTENT;
++
++ if ( (entry->arg1 == arg1) && (entry->arg2 == arg2) && (entry->arg3 == arg3) )
++ {
++ if(entry->next == NULL)
++ {
++ entry->isr=NULL;
++ return VLYNQ_SUCCESS;
++ }
++ else
++ {
++ temp = entry->next;
++ /* Copy next node in the chain to prim.slot */
++ entry->isr = temp->isr;
++ entry->arg1 = temp->arg1;
++ entry->arg2 = temp->arg2;
++ entry->arg3 = temp->arg3;
++ entry->next = temp->next;
++ /* Free the just copied node */
++ temp->isr = NULL;
++ temp->arg1 = NULL;
++ temp->arg2 = NULL;
++ temp->arg3 = NULL;
++ temp->next = pdev->freelist;
++ pdev->freelist = temp;
++ return VLYNQ_SUCCESS;
++ }
++ }
++ else
++ {
++ temp = entry;
++ while ( (entry = temp->next) != NULL)
++ {
++ if ( (entry->arg1 == arg1) && (entry->arg2 == arg2) && (entry->arg3 == arg3) )
++ {
++ /* remove node from chain */
++ temp->next = entry->next;
++ /* Add the removed node to freelist */
++ entry->isr = NULL;
++ entry->arg1 = NULL;
++ entry->arg2 = NULL;
++ entry->arg3 = NULL;
++ entry->next = pdev->freelist;
++ entry->isrCount = 0;
++ pdev->freelist = entry;
++ return VLYNQ_SUCCESS;
++ }
++ temp = entry;
++ }
++
++ return VLYNQ_ISR_NON_EXISTENT;
++ }
++}
++
++
++
++
++/* ----------------------------------------------------------------------------
++ * function : vlynq_interrupt_vector_set()
++ * description:configures interrupt vector mapping,interrupt type
++ * polarity -all in one go.
++ */
++int
++vlynq_interrupt_vector_set(VLYNQ_DEV *pdev, /* vlynq device */
++ unsigned int int_vector, /* int vector on vlynq device */
++ unsigned int map_vector, /* bit for this interrupt */
++ VLYNQ_DEV_TYPE dev_type, /* local or remote device */
++ VLYNQ_INTR_POLARITY pol, /* polarity of interrupt */
++ VLYNQ_INTR_TYPE type) /* pulsed/level interrupt */
++{
++ volatile unsigned int * vecreg;
++ unsigned int val=0;
++ unsigned int bytemask=0XFF;
++
++ /* use the lower 8 bits of val to set the value , shift it to
++ * appropriate byte position in the ivr and write it to the
++ * corresponding register */
++
++ /* validate the number of interrupts supported */
++ if (int_vector >= VLYNQ_IVR_MAXIVR)
++ return VLYNQ_INVALID_ARG;
++
++ if(map_vector > (VLYNQ_NUM_INT_BITS - 1) )
++ return VLYNQ_INVALID_ARG;
++
++ if (dev_type == VLYNQ_LOCAL_DVC)
++ {
++ vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
++ }
++ else
++ {
++ vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
++ }
++
++ /* Update the intVector<==> bit position translation table */
++ pdev->vector_map[map_vector] = int_vector;
++
++ /* val has been initialised to zero. we only have to turn on appropriate bits*/
++ if(type == VLYNQ_INTR_PULSED)
++ val |= VLYNQ_IVR_INTTYPE_MASK;
++
++ if(pol == VLYNQ_INTR_ACTIVE_LOW)
++ val |= VLYNQ_IVR_INTPOL_MASK;
++
++ val |= map_vector;
++
++ /** clear the correct byte position and then or val **/
++ *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) );
++
++ /** write to correct byte position in vecreg*/
++ *vecreg = (*vecreg) | (val << ( (int_vector % 4)*8) ) ;
++
++ /* Setting a interrupt vector, leaves the interrupt disabled
++ * which must be enabled subsequently */
++
++ return VLYNQ_SUCCESS;
++}
++
++
++/* ----------------------------------------------------------------------------
++ * Function : vlynq_interrupt_vector_cntl()
++ * Description:enables/disable interrupt
++ */
++int vlynq_interrupt_vector_cntl( VLYNQ_DEV *pdev,
++ unsigned int int_vector,
++ VLYNQ_DEV_TYPE dev_type,
++ unsigned int enable)
++{
++ volatile unsigned int *vecReg;
++ unsigned int val=0;
++ unsigned int intenMask=0x80;
++
++ /* validate the number of interrupts supported */
++ if (int_vector >= VLYNQ_IVR_MAXIVR)
++ return VLYNQ_INVALID_ARG;
++
++ if (dev_type == VLYNQ_LOCAL_DVC)
++ {
++ vecReg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
++ }
++ else
++ {
++ vecReg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
++ }
++
++ /** Clear the correct byte position and then or val **/
++ *vecReg = (*vecReg) & ( ~(intenMask << ( (int_vector %4)*8) ) );
++
++ if(enable)
++ {
++ val |= VLYNQ_IVR_INTEN_MASK;
++ /** Write to correct byte position in vecReg*/
++ *vecReg = (*vecReg) | (val << ( (int_vector % 4)*8) ) ;
++ }
++
++ return VLYNQ_SUCCESS;
++
++}/* end of function vlynq_interrupt_vector_cntl */
++
++
++
++/* ----------------------------------------------------------------------------
++ * Function : vlynq_interrupt_vector_map()
++ * Description:Configures interrupt vector mapping alone
++ */
++int
++vlynq_interrupt_vector_map( VLYNQ_DEV *pdev,
++ VLYNQ_DEV_TYPE dev_type,
++ unsigned int int_vector,
++ unsigned int map_vector)
++{
++ volatile unsigned int * vecreg;
++ unsigned int val=0;
++ unsigned int bytemask=0x1f; /* mask to turn off bits corresponding to int vector */
++
++ /* use the lower 8 bits of val to set the value , shift it to
++ * appropriate byte position in the ivr and write it to the
++ * corresponding register */
++
++ /* validate the number of interrupts supported */
++ if (int_vector >= VLYNQ_IVR_MAXIVR)
++ return VLYNQ_INVALID_ARG;
++
++ if(map_vector > (VLYNQ_NUM_INT_BITS - 1) )
++ return VLYNQ_INVALID_ARG;
++
++ if (dev_type == VLYNQ_LOCAL_DVC)
++ {
++ vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
++ }
++ else
++ {
++ vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
++ }
++
++ /* Update the intVector<==> bit position translation table */
++ pdev->vector_map[map_vector] = int_vector;
++
++ /** val has been initialised to zero. we only have to turn on
++ * appropriate bits*/
++ val |= map_vector;
++
++ /** clear the correct byte position and then or val **/
++ *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) );
++
++ /** write to correct byte position in vecreg*/
++ *vecreg = (*vecreg) | (val << ( (int_vector % 4)*8) ) ;
++
++ return VLYNQ_SUCCESS;
++}
++
++
++/* ----------------------------------------------------------------------------
++ * function : vlynq_interrupt_set_polarity()
++ * description:configures interrupt polarity .
++ */
++int
++vlynq_interrupt_set_polarity( VLYNQ_DEV *pdev ,
++ VLYNQ_DEV_TYPE dev_type,
++ unsigned int map_vector,
++ VLYNQ_INTR_POLARITY pol)
++{
++ volatile unsigned int * vecreg;
++ int int_vector;
++ unsigned int val=0;
++ unsigned int bytemask=0x20; /** mask to turn off bits corresponding to int polarity */
++
++ /* get the int_vector from map_vector */
++ int_vector = pdev->vector_map[map_vector];
++
++ if(int_vector == -1)
++ return VLYNQ_INTVEC_MAP_NOT_FOUND;
++
++ /* use the lower 8 bits of val to set the value , shift it to
++ * appropriate byte position in the ivr and write it to the
++ * corresponding register */
++
++ if (dev_type == VLYNQ_LOCAL_DVC)
++ {
++ vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
++ }
++ else
++ {
++ vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
++ }
++
++ /* val has been initialised to zero. we only have to turn on
++ * appropriate bits, if need be*/
++
++ /** clear the correct byte position and then or val **/
++ *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) );
++
++ if( pol == VLYNQ_INTR_ACTIVE_LOW)
++ {
++ val |= VLYNQ_IVR_INTPOL_MASK;
++ /** write to correct byte position in vecreg*/
++ *vecreg = (*vecreg) | (val << ( (int_vector % 4)*8) ) ;
++ }
++
++ return VLYNQ_SUCCESS;
++}
++
++int vlynq_interrupt_get_polarity( VLYNQ_DEV *pdev ,
++ VLYNQ_DEV_TYPE dev_type,
++ unsigned int map_vector)
++{
++ volatile unsigned int * vecreg;
++ int int_vector;
++ unsigned int val=0;
++
++ /* get the int_vector from map_vector */
++ int_vector = pdev->vector_map[map_vector];
++
++ if (map_vector > (VLYNQ_NUM_INT_BITS-1))
++ return(-1);
++
++ if(int_vector == -1)
++ return VLYNQ_INTVEC_MAP_NOT_FOUND;
++
++ /* use the lower 8 bits of val to set the value , shift it to
++ * appropriate byte position in the ivr and write it to the
++ * corresponding register */
++
++ if (dev_type == VLYNQ_LOCAL_DVC)
++ {
++ vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
++ }
++ else
++ {
++ vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
++ }
++
++ /** read the information into val **/
++ val = (*vecreg) & ((VLYNQ_IVR_INTPOL_MASK << ( (int_vector %4)*8) ) );
++
++ return (val ? (VLYNQ_INTR_ACTIVE_LOW) : (VLYNQ_INTR_ACTIVE_HIGH));
++}
++
++
++/* ----------------------------------------------------------------------------
++ * function : vlynq_interrupt_set_type()
++ * description:configures interrupt type .
++ */
++int vlynq_interrupt_set_type( VLYNQ_DEV *pdev,
++ VLYNQ_DEV_TYPE dev_type,
++ unsigned int map_vector,
++ VLYNQ_INTR_TYPE type)
++{
++ volatile unsigned int * vecreg;
++ unsigned int val=0;
++ int int_vector;
++
++ /** mask to turn off bits corresponding to interrupt type */
++ unsigned int bytemask=0x40;
++
++ /* get the int_vector from map_vector */
++ int_vector = pdev->vector_map[map_vector];
++ if(int_vector == -1)
++ return VLYNQ_INTVEC_MAP_NOT_FOUND;
++
++ /* use the lower 8 bits of val to set the value , shift it to
++ * appropriate byte position in the ivr and write it to the
++ * corresponding register */
++ if (dev_type == VLYNQ_LOCAL_DVC)
++ {
++ vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
++ }
++ else
++ {
++ vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
++ }
++
++ /** val has been initialised to zero. we only have to turn on
++ * appropriate bits if need be*/
++
++ /** clear the correct byte position and then or val **/
++ *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) );
++
++ if( type == VLYNQ_INTR_PULSED)
++ {
++ val |= VLYNQ_IVR_INTTYPE_MASK;
++ /** write to correct byte position in vecreg*/
++ *vecreg = (*vecreg) | (val << ( (int_vector % 4)*8) ) ;
++ }
++
++ return VLYNQ_SUCCESS;
++}
++
++/* ----------------------------------------------------------------------------
++ * function : vlynq_interrupt_get_type()
++ * description:returns interrupt type .
++ */
++int vlynq_interrupt_get_type( VLYNQ_DEV *pdev, VLYNQ_DEV_TYPE dev_type,
++ unsigned int map_vector)
++{
++ volatile unsigned int * vecreg;
++ unsigned int val=0;
++ int int_vector;
++
++ if (map_vector > (VLYNQ_NUM_INT_BITS-1))
++ return(-1);
++
++ /* get the int_vector from map_vector */
++ int_vector = pdev->vector_map[map_vector];
++ if(int_vector == -1)
++ return VLYNQ_INTVEC_MAP_NOT_FOUND;
++
++ /* use the lower 8 bits of val to set the value , shift it to
++ * appropriate byte position in the ivr and write it to the
++ * corresponding register */
++ if (dev_type == VLYNQ_LOCAL_DVC)
++ {
++ vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
++ }
++ else
++ {
++ vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
++ }
++
++ /** Read the correct bit position into val **/
++ val = (*vecreg) & ((VLYNQ_IVR_INTTYPE_MASK << ( (int_vector %4)*8) ) );
++
++ return (val ? (VLYNQ_INTR_PULSED) : (VLYNQ_INTR_LEVEL));
++}
++
++/* ----------------------------------------------------------------------------
++ * function : vlynq_interrupt_enable()
++ * description:Enable interrupt by writing to IVR register.
++ */
++int vlynq_interrupt_enable( VLYNQ_DEV *pdev,
++ VLYNQ_DEV_TYPE dev_type,
++ unsigned int map_vector)
++{
++ volatile unsigned int * vecreg;
++ unsigned int val=0;
++ int int_vector;
++
++ /** mask to turn off bits corresponding to interrupt enable */
++ unsigned int bytemask=0x80;
++
++ /* get the int_vector from map_vector */
++ int_vector = pdev->vector_map[map_vector];
++ if(int_vector == -1)
++ return VLYNQ_INTVEC_MAP_NOT_FOUND;
++
++ /* use the lower 8 bits of val to set the value , shift it to
++ * appropriate byte position in the ivr and write it to the
++ * corresponding register */
++
++ if (dev_type == VLYNQ_LOCAL_DVC)
++ {
++ vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
++ }
++ else
++ {
++ vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
++ }
++
++ /** val has been initialised to zero. we only have to turn on
++ * bit corresponding to interrupt enable*/
++ val |= VLYNQ_IVR_INTEN_MASK;
++
++ /** clear the correct byte position and then or val **/
++ *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) );
++
++ /** write to correct byte position in vecreg*/
++ *vecreg = (*vecreg) | (val << ( (int_vector % 4)*8) ) ;
++
++ return VLYNQ_SUCCESS;
++}
++
++
++/* ----------------------------------------------------------------------------
++ * function : vlynq_interrupt_disable()
++ * description:Disable interrupt by writing to IVR register.
++ */
++int
++vlynq_interrupt_disable( VLYNQ_DEV *pdev,
++ VLYNQ_DEV_TYPE dev_type,
++ unsigned int map_vector)
++{
++ volatile unsigned int * vecreg;
++ int int_vector;
++
++ /** mask to turn off bits corresponding to interrupt enable */
++ unsigned int bytemask=0x80;
++
++ /* get the int_vector from map_vector */
++ int_vector = pdev->vector_map[map_vector];
++ if(int_vector == -1)
++ return VLYNQ_INTVEC_MAP_NOT_FOUND;
++
++ /* use the lower 8 bits of val to set the value , shift it to
++ * appropriate byte position in the ivr and write it to the
++ * corresponding register */
++ if (dev_type == VLYNQ_LOCAL_DVC)
++ {
++ vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
++ }
++ else
++ {
++ vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
++ }
++
++ /* We disable the interrupt by simply turning off the bit
++ * corresponding to Interrupt enable.
++ * Clear the interrupt enable bit in the correct byte position **/
++ *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) );
++
++ /* Dont have to set any bit positions */
++
++ return VLYNQ_SUCCESS;
++
++}
++
++
++
++
+diff -urN linux.old/drivers/char/serial.c linux.dev/drivers/char/serial.c
+--- linux.old/drivers/char/serial.c 2005-10-21 16:43:20.709226000 +0200
++++ linux.dev/drivers/char/serial.c 2005-11-10 01:10:46.015585250 +0100
+@@ -419,7 +419,40 @@
+ return 0;
+ }
+
+-#if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_SEAD)
++#if defined(CONFIG_AR7)
++
++static _INLINE_ unsigned int serial_in(struct async_struct *info, int offset)
++{
++ return (inb(info->port + (offset * 4)) & 0xff);
++}
++
++
++static _INLINE_ unsigned int serial_inp(struct async_struct *info, int offset)
++{
++#ifdef CONFIG_SERIAL_NOPAUSE_IO
++ return (inb(info->port + (offset * 4)) & 0xff);
++#else
++ return (inb_p(info->port + (offset * 4)) & 0xff);
++#endif
++}
++
++static _INLINE_ void serial_out(struct async_struct *info, int offset, int value)
++{
++ outb(value, info->port + (offset * 4));
++}
++
++
++static _INLINE_ void serial_outp(struct async_struct *info, int offset,
++ int value)
++{
++#ifdef CONFIG_SERIAL_NOPAUSE_IO
++ outb(value, info->port + (offset * 4));
++#else
++ outb_p(value, info->port + (offset * 4));
++#endif
++}
++
++#elif defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_SEAD)
+
+ #include <asm/mips-boards/atlas.h>
+
+@@ -478,8 +511,10 @@
+ * needed for certain old 386 machines, I've left these #define's
+ * in....
+ */
++#ifndef CONFIG_AR7
+ #define serial_inp(info, offset) serial_in(info, offset)
+ #define serial_outp(info, offset, value) serial_out(info, offset, value)
++#endif
+
+
+ /*
+@@ -1728,7 +1763,15 @@
+ /* Special case since 134 is really 134.5 */
+ quot = (2*baud_base / 269);
+ else if (baud)
++#ifdef CONFIG_AR7
++ quot = (CONFIG_AR7_SYS*500000) / baud;
++
++ if ((quot%16)>7)
++ quot += 8;
++ quot /=16;
++#else
+ quot = baud_base / baud;
++#endif
+ }
+ /* If the quotient is zero refuse the change */
+ if (!quot && old_termios) {
+@@ -5540,8 +5583,10 @@
+ state->irq = irq_cannonicalize(state->irq);
+ if (state->hub6)
+ state->io_type = SERIAL_IO_HUB6;
++#ifndef CONFIG_AR7
+ if (state->port && check_region(state->port,8))
+ continue;
++#endif
+ #ifdef CONFIG_MCA
+ if ((state->flags & ASYNC_BOOT_ONLYMCA) && !MCA_bus)
+ continue;
+@@ -5997,7 +6042,15 @@
+ info->io_type = state->io_type;
+ info->iomem_base = state->iomem_base;
+ info->iomem_reg_shift = state->iomem_reg_shift;
++#ifdef CONFIG_AR7
++ quot = (CONFIG_AR7_SYS*500000) / baud;
++
++ if ((quot%16)>7)
++ quot += 8;
++ quot /=16;
++#else
+ quot = state->baud_base / baud;
++#endif
+ cval = cflag & (CSIZE | CSTOPB);
+ #if defined(__powerpc__) || defined(__alpha__)
+ cval >>= 8;
+diff -urN linux.old/drivers/char/ticfg/Makefile linux.dev/drivers/char/ticfg/Makefile
+--- linux.old/drivers/char/ticfg/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/char/ticfg/Makefile 2005-11-10 01:10:46.051587500 +0100
+@@ -0,0 +1,6 @@
++
++O_TARGET := ticfg.o
++
++obj-$(CONFIG_AR7_ADAM2) := adam2_env.o
++
++include $(TOPDIR)/Rules.make
+diff -urN linux.old/drivers/char/ticfg/adam2_env.c linux.dev/drivers/char/ticfg/adam2_env.c
+--- linux.old/drivers/char/ticfg/adam2_env.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/char/ticfg/adam2_env.c 2005-11-10 01:10:46.051587500 +0100
+@@ -0,0 +1,85 @@
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/proc_fs.h>
++#include <linux/fcntl.h>
++#include <linux/init.h>
++
++#include <asm/ar7/adam2_env.h>
++
++#undef ADAM2_ENV_DEBUG
++
++#ifdef ADAM2_ENV_DEBUG
++#define DPRINTK(args...) do { printk(args); } while(0);
++#else
++#define DPRINTK(args...) do { } while(0);
++#endif
++
++#define ADAM2_ENV_DIR "ticfg"
++#define ADAM2_ENV_NAME "env"
++
++static struct proc_dir_entry *adam2_env_proc_dir;
++static struct proc_dir_entry *adam2_env_proc_ent;
++
++static int
++adam2_proc_read_env(char *page, char **start, off_t pos, int count,
++ int *eof, void *data)
++{
++ int len;
++ t_env_var *env;
++
++ if (pos > 0)
++ return 0;
++
++ len=0;
++ for (env = prom_iterenv(0); env; env = prom_iterenv(env)) {
++ if (env->val) {
++ /* XXX check for page len */
++ len += sprintf(page + len, "%s\t%s\n",
++ env->name, env->val);
++ }
++ }
++
++ *eof=1;
++ return len;
++}
++
++static int __init
++adam2_env_init(void)
++{
++
++ DPRINTK("%s\n", __FUNCTION__);
++
++ adam2_env_proc_dir = proc_mkdir(ADAM2_ENV_DIR, NULL);
++ if (!adam2_env_proc_dir) {
++ printk(KERN_ERR "%s: Unable to create /proc/%s entry\n",
++ __FUNCTION__, ADAM2_ENV_DIR);
++ return -ENOMEM;
++ }
++
++ adam2_env_proc_ent =
++ create_proc_entry(ADAM2_ENV_NAME, 0444, adam2_env_proc_dir);
++ if (!adam2_env_proc_ent) {
++ printk(KERN_ERR "%s: Unable to create /proc/%s/%s entry\n",
++ __FUNCTION__, ADAM2_ENV_DIR, ADAM2_ENV_NAME);
++ remove_proc_entry(ADAM2_ENV_DIR, NULL);
++ return -ENOMEM;
++ }
++ adam2_env_proc_ent->read_proc = adam2_proc_read_env;
++
++ return 0;
++}
++
++static
++void __exit
++adam2_env_cleanup(void)
++{
++ remove_proc_entry(ADAM2_ENV_NAME, adam2_env_proc_dir);
++ remove_proc_entry(ADAM2_ENV_DIR, NULL);
++}
++
++module_init(adam2_env_init);
++module_exit(adam2_env_cleanup);
++
++MODULE_LICENSE("GPL");
+diff -urN linux.old/include/asm-mips/addrspace.h linux.dev/include/asm-mips/addrspace.h
+--- linux.old/include/asm-mips/addrspace.h 2002-11-29 00:53:15.000000000 +0100
++++ linux.dev/include/asm-mips/addrspace.h 2005-11-10 01:14:16.400733500 +0100
+@@ -11,6 +11,8 @@
+ #ifndef __ASM_MIPS_ADDRSPACE_H
+ #define __ASM_MIPS_ADDRSPACE_H
+
++#include <linux/config.h>
++
+ /*
+ * Configure language
+ */
+@@ -102,4 +104,11 @@
+ #define XKPHYS_TO_PHYS(p) ((p) & TO_PHYS_MASK)
+ #define PHYS_TO_XKPHYS(cm,a) (0x8000000000000000 | ((cm)<<59) | (a))
+
++#ifdef CONFIG_AR7_MEMORY
++#define PHYS_OFFSET ((unsigned long)(CONFIG_AR7_MEMORY))
++#else
++#define PHYS_OFFSET (0)
++#endif
++#define PHYS_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT)
++
+ #endif /* __ASM_MIPS_ADDRSPACE_H */
+diff -urN linux.old/include/asm-mips/ar7/adam2_env.h linux.dev/include/asm-mips/ar7/adam2_env.h
+--- linux.old/include/asm-mips/ar7/adam2_env.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/adam2_env.h 2005-11-10 01:10:46.067588500 +0100
+@@ -0,0 +1,13 @@
++#ifndef _INCLUDE_ASM_AR7_ADAM2_ENV_H_
++#define _INCLUDE_ASM_AR7_ADAM2_ENV_H_
++
++/* Environment variable */
++typedef struct {
++ char *name;
++ char *val;
++} t_env_var;
++
++char *prom_getenv(char *);
++t_env_var *prom_iterenv(t_env_var *);
++
++#endif /* _INCLUDE_ASM_AR7_ADAM2_ENV_H_ */
+diff -urN linux.old/include/asm-mips/ar7/ar7.h linux.dev/include/asm-mips/ar7/ar7.h
+--- linux.old/include/asm-mips/ar7/ar7.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/ar7.h 2005-11-10 01:10:46.067588500 +0100
+@@ -0,0 +1,33 @@
++/*
++ * $Id$
++ * Copyright (C) $Date$ $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 St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ */
++
++#ifndef _AR7_H
++#define _AR7_H
++
++#include <asm/addrspace.h>
++#include <linux/config.h>
++
++#define AVALANCHE_VECS_KSEG0 (KSEG0ADDR(CONFIG_AR7_MEMORY))
++
++#define AR7_UART0_REGS_BASE (KSEG1ADDR(0x08610E00))
++#define AR7_UART1_REGS_BASE (KSEG1ADDR(0x08610F00))
++#define AR7_BASE_BAUD ( 3686400 / 16 )
++
++#endif
+diff -urN linux.old/include/asm-mips/ar7/avalanche_intc.h linux.dev/include/asm-mips/ar7/avalanche_intc.h
+--- linux.old/include/asm-mips/ar7/avalanche_intc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/avalanche_intc.h 2005-11-10 01:10:46.067588500 +0100
+@@ -0,0 +1,292 @@
++ /*
++ * Nitin Dhingra, iamnd@ti.com
++ * Copyright (C) 2000 Texas Instruments Inc.
++ *
++ *
++ * ########################################################################
++ *
++ * This program is free software; you can distribute 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 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.
++ *
++ * ########################################################################
++ *
++ * Defines of the Sead board specific address-MAP, registers, etc.
++ *
++ */
++#ifndef _AVALANCHE_INTC_H
++#define _AVALANCHE_INTC_H
++
++#include <linux/config.h>
++
++/* ----- */
++
++#define KSEG1_BASE 0xA0000000
++#define KSEG_INV_MASK 0x1FFFFFFF /* Inverted mask for kseg address */
++#define PHYS_ADDR(addr) ((addr) & KSEG_INV_MASK)
++#define PHYS_TO_K1(addr) (PHYS_ADDR(addr)|KSEG1_BASE)
++#define AVALANCHE_INTC_BASE PHYS_TO_K1(0x08612400)
++
++/* ----- */
++
++#define MIPS_EXCEPTION_OFFSET 8
++
++/******************************************************************************
++ Avalanche Interrupt number
++******************************************************************************/
++#define AVINTNUM(x) ((x) - MIPS_EXCEPTION_OFFSET)
++
++/*******************************************************************************
++*Linux Interrupt number
++*******************************************************************************/
++#define LNXINTNUM(x)((x) + MIPS_EXCEPTION_OFFSET)
++
++
++
++#define AVALANCHE_INT_END_PRIMARY (40 + MIPS_EXCEPTION_OFFSET)
++#define AVALANCHE_INT_END_SECONDARY (32 + MIPS_EXCEPTION_OFFSET)
++
++#define AVALANCHE_INT_END_PRIMARY_REG1 (31 + MIPS_EXCEPTION_OFFSET)
++#define AVALANCHE_INT_END_PRIMARY_REG2 (39 + MIPS_EXCEPTION_OFFSET)
++
++#define AVALANCHE_INTC_END (AVINTNUM(AVALANCHE_INT_END_PRIMARY) + \
++ AVINTNUM(AVALANCHE_INT_END_SECONDARY) + \
++ MIPS_EXCEPTION_OFFSET)
++
++#if defined(CONFIG_AR7_VLYNQ)
++#define AVALANCHE_INT_END_LOW_VLYNQ (AVALANCHE_INTC_END + 32)
++#define AVALANCHE_INT_END_VLYNQ (AVALANCHE_INTC_END + 32 * CONFIG_AR7_VLYNQ_PORTS)
++#define AVALANCHE_INT_END AVALANCHE_INT_END_VLYNQ
++#else
++#define AVALANCHE_INT_END AVALANCHE_INTC_END
++#endif
++
++
++/*
++ * Avalanche interrupt controller register base (primary)
++ */
++#define AVALANCHE_ICTRL_REGS_BASE AVALANCHE_INTC_BASE
++
++/******************************************************************************
++ * Avalanche exception controller register base (secondary)
++ ******************************************************************************/
++#define AVALANCHE_ECTRL_REGS_BASE (AVALANCHE_ICTRL_REGS_BASE + 0x80)
++
++
++/******************************************************************************
++ * Avalanche Interrupt pacing register base (secondary)
++ ******************************************************************************/
++#define AVALANCHE_IPACE_REGS_BASE (AVALANCHE_ICTRL_REGS_BASE + 0xA0)
++
++
++
++/******************************************************************************
++ * Avalanche Interrupt Channel Control register base
++ *****************************************************************************/
++#define AVALANCHE_CHCTRL_REGS_BASE (AVALANCHE_ICTRL_REGS_BASE + 0x200)
++
++
++struct avalanche_ictrl_regs /* Avalanche Interrupt control registers */
++{
++ volatile unsigned long intsr1; /* Interrupt Status/Set Register 1 0x00 */
++ volatile unsigned long intsr2; /* Interrupt Status/Set Register 2 0x04 */
++ volatile unsigned long unused1; /*0x08 */
++ volatile unsigned long unused2; /*0x0C */
++ volatile unsigned long intcr1; /* Interrupt Clear Register 1 0x10 */
++ volatile unsigned long intcr2; /* Interrupt Clear Register 2 0x14 */
++ volatile unsigned long unused3; /*0x18 */
++ volatile unsigned long unused4; /*0x1C */
++ volatile unsigned long intesr1; /* Interrupt Enable (Set) Register 1 0x20 */
++ volatile unsigned long intesr2; /* Interrupt Enable (Set) Register 2 0x24 */
++ volatile unsigned long unused5; /*0x28 */
++ volatile unsigned long unused6; /*0x2C */
++ volatile unsigned long intecr1; /* Interrupt Enable Clear Register 1 0x30 */
++ volatile unsigned long intecr2; /* Interrupt Enable Clear Register 2 0x34 */
++ volatile unsigned long unused7; /* 0x38 */
++ volatile unsigned long unused8; /* 0x3c */
++ volatile unsigned long pintir; /* Priority Interrupt Index Register 0x40 */
++ volatile unsigned long intmsr; /* Priority Interrupt Mask Index Reg 0x44 */
++ volatile unsigned long unused9; /* 0x48 */
++ volatile unsigned long unused10; /* 0x4C */
++ volatile unsigned long intpolr1; /* Interrupt Polarity Mask register 10x50 */
++ volatile unsigned long intpolr2; /* Interrupt Polarity Mask register 20x54 */
++ volatile unsigned long unused11; /* 0x58 */
++ volatile unsigned long unused12; /*0x5C */
++ volatile unsigned long inttypr1; /* Interrupt Type Mask register 10x60 */
++ volatile unsigned long inttypr2; /* Interrupt Type Mask register 20x64 */
++};
++
++struct avalanche_exctrl_regs /* Avalanche Exception control registers */
++{
++ volatile unsigned long exsr; /* Exceptions Status/Set register 0x80 */
++ volatile unsigned long reserved; /*0x84 */
++ volatile unsigned long excr; /* Exceptions Clear Register 0x88 */
++ volatile unsigned long reserved1; /*0x8c */
++ volatile unsigned long exiesr; /* Exceptions Interrupt Enable (set) 0x90 */
++ volatile unsigned long reserved2; /*0x94 */
++ volatile unsigned long exiecr; /* Exceptions Interrupt Enable(clear)0x98 */
++};
++struct avalanche_ipace_regs
++{
++
++ volatile unsigned long ipacep; /* Interrupt pacing register 0xa0 */
++ volatile unsigned long ipacemap; /*Interrupt Pacing Map Register 0xa4 */
++ volatile unsigned long ipacemax; /*Interrupt Pacing Max Register 0xa8 */
++};
++struct avalanche_channel_int_number
++{
++ volatile unsigned long cintnr0; /* Channel Interrupt Number Register0x200 */
++ volatile unsigned long cintnr1; /* Channel Interrupt Number Register0x204 */
++ volatile unsigned long cintnr2; /* Channel Interrupt Number Register0x208 */
++ volatile unsigned long cintnr3; /* Channel Interrupt Number Register0x20C */
++ volatile unsigned long cintnr4; /* Channel Interrupt Number Register0x210 */
++ volatile unsigned long cintnr5; /* Channel Interrupt Number Register0x214 */
++ volatile unsigned long cintnr6; /* Channel Interrupt Number Register0x218 */
++ volatile unsigned long cintnr7; /* Channel Interrupt Number Register0x21C */
++ volatile unsigned long cintnr8; /* Channel Interrupt Number Register0x220 */
++ volatile unsigned long cintnr9; /* Channel Interrupt Number Register0x224 */
++ volatile unsigned long cintnr10; /* Channel Interrupt Number Register0x228 */
++ volatile unsigned long cintnr11; /* Channel Interrupt Number Register0x22C */
++ volatile unsigned long cintnr12; /* Channel Interrupt Number Register0x230 */
++ volatile unsigned long cintnr13; /* Channel Interrupt Number Register0x234 */
++ volatile unsigned long cintnr14; /* Channel Interrupt Number Register0x238 */
++ volatile unsigned long cintnr15; /* Channel Interrupt Number Register0x23C */
++ volatile unsigned long cintnr16; /* Channel Interrupt Number Register0x240 */
++ volatile unsigned long cintnr17; /* Channel Interrupt Number Register0x244 */
++ volatile unsigned long cintnr18; /* Channel Interrupt Number Register0x248 */
++ volatile unsigned long cintnr19; /* Channel Interrupt Number Register0x24C */
++ volatile unsigned long cintnr20; /* Channel Interrupt Number Register0x250 */
++ volatile unsigned long cintnr21; /* Channel Interrupt Number Register0x254 */
++ volatile unsigned long cintnr22; /* Channel Interrupt Number Register0x358 */
++ volatile unsigned long cintnr23; /* Channel Interrupt Number Register0x35C */
++ volatile unsigned long cintnr24; /* Channel Interrupt Number Register0x260 */
++ volatile unsigned long cintnr25; /* Channel Interrupt Number Register0x264 */
++ volatile unsigned long cintnr26; /* Channel Interrupt Number Register0x268 */
++ volatile unsigned long cintnr27; /* Channel Interrupt Number Register0x26C */
++ volatile unsigned long cintnr28; /* Channel Interrupt Number Register0x270 */
++ volatile unsigned long cintnr29; /* Channel Interrupt Number Register0x274 */
++ volatile unsigned long cintnr30; /* Channel Interrupt Number Register0x278 */
++ volatile unsigned long cintnr31; /* Channel Interrupt Number Register0x27C */
++ volatile unsigned long cintnr32; /* Channel Interrupt Number Register0x280 */
++ volatile unsigned long cintnr33; /* Channel Interrupt Number Register0x284 */
++ volatile unsigned long cintnr34; /* Channel Interrupt Number Register0x288 */
++ volatile unsigned long cintnr35; /* Channel Interrupt Number Register0x28C */
++ volatile unsigned long cintnr36; /* Channel Interrupt Number Register0x290 */
++ volatile unsigned long cintnr37; /* Channel Interrupt Number Register0x294 */
++ volatile unsigned long cintnr38; /* Channel Interrupt Number Register0x298 */
++ volatile unsigned long cintnr39; /* Channel Interrupt Number Register0x29C */
++};
++
++struct avalanche_interrupt_line_to_channel
++{
++ unsigned long int_line0; /* Start of primary interrupts */
++ unsigned long int_line1;
++ unsigned long int_line2;
++ unsigned long int_line3;
++ unsigned long int_line4;
++ unsigned long int_line5;
++ unsigned long int_line6;
++ unsigned long int_line7;
++ unsigned long int_line8;
++ unsigned long int_line9;
++ unsigned long int_line10;
++ unsigned long int_line11;
++ unsigned long int_line12;
++ unsigned long int_line13;
++ unsigned long int_line14;
++ unsigned long int_line15;
++ unsigned long int_line16;
++ unsigned long int_line17;
++ unsigned long int_line18;
++ unsigned long int_line19;
++ unsigned long int_line20;
++ unsigned long int_line21;
++ unsigned long int_line22;
++ unsigned long int_line23;
++ unsigned long int_line24;
++ unsigned long int_line25;
++ unsigned long int_line26;
++ unsigned long int_line27;
++ unsigned long int_line28;
++ unsigned long int_line29;
++ unsigned long int_line30;
++ unsigned long int_line31;
++ unsigned long int_line32;
++ unsigned long int_line33;
++ unsigned long int_line34;
++ unsigned long int_line35;
++ unsigned long int_line36;
++ unsigned long int_line37;
++ unsigned long int_line38;
++ unsigned long int_line39;
++};
++
++
++/* Interrupt Line #'s (Sangam peripherals) */
++
++/*------------------------------*/
++/* Sangam primary interrupts */
++/*------------------------------*/
++
++#define UNIFIED_SECONDARY_INTERRUPT 0
++#define AVALANCHE_EXT_INT_0 1
++#define AVALANCHE_EXT_INT_1 2
++/* Line #3 Reserved */
++/* Line #4 Reserved */
++#define AVALANCHE_TIMER_0_INT 5
++#define AVALANCHE_TIMER_1_INT 6
++#define AVALANCHE_UART0_INT 7
++#define AVALANCHE_UART1_INT 8
++#define AVALANCHE_PDMA_INT0 9
++#define AVALANCHE_PDMA_INT1 10
++/* Line #11 Reserved */
++/* Line #12 Reserved */
++/* Line #13 Reserved */
++/* Line #14 Reserved */
++#define AVALANCHE_ATM_SAR_INT 15
++/* Line #16 Reserved */
++/* Line #17 Reserved */
++/* Line #18 Reserved */
++#define AVALANCHE_MAC0_INT 19
++/* Line #20 Reserved */
++#define AVALANCHE_VLYNQ0_INT 21
++#define AVALANCHE_CODEC_WAKE_INT 22
++/* Line #23 Reserved */
++#define AVALANCHE_USB_INT 24
++#define AVALANCHE_VLYNQ1_INT 25
++/* Line #26 Reserved */
++/* Line #27 Reserved */
++#define AVALANCHE_MAC1_INT 28
++#define AVALANCHE_I2CM_INT 29
++#define AVALANCHE_PDMA_INT2 30
++#define AVALANCHE_PDMA_INT3 31
++/* Line #32 Reserved */
++/* Line #33 Reserved */
++/* Line #34 Reserved */
++/* Line #35 Reserved */
++/* Line #36 Reserved */
++#define AVALANCHE_VDMA_VT_RX_INT 37
++#define AVALANCHE_VDMA_VT_TX_INT 38
++#define AVALANCHE_ADSLSS_INT 39
++
++/*-----------------------------------*/
++/* Sangam Secondary Interrupts */
++/*-----------------------------------*/
++#define PRIMARY_INTS 40
++
++#define EMIF_INT (7 + PRIMARY_INTS)
++
++
++extern void avalanche_int_set(int channel, int line);
++
++
++#endif /* _AVALANCHE_INTC_H */
+diff -urN linux.old/include/asm-mips/ar7/avalanche_misc.h linux.dev/include/asm-mips/ar7/avalanche_misc.h
+--- linux.old/include/asm-mips/ar7/avalanche_misc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/avalanche_misc.h 2005-11-10 01:10:46.067588500 +0100
+@@ -0,0 +1,174 @@
++#ifndef _AVALANCHE_MISC_H_
++#define _AVALANCHE_MISC_H_
++
++typedef enum AVALANCHE_ERR_t
++{
++ AVALANCHE_ERR_OK = 0, /* OK or SUCCESS */
++ AVALANCHE_ERR_ERROR = -1, /* Unspecified/Generic ERROR */
++
++ /* Pointers and args */
++ AVALANCHE_ERR_INVARG = -2, /* Invaild argument to the call */
++ AVALANCHE_ERR_NULLPTR = -3, /* NULL pointer */
++ AVALANCHE_ERR_BADPTR = -4, /* Bad (out of mem) pointer */
++
++ /* Memory issues */
++ AVALANCHE_ERR_ALLOC_FAIL = -10, /* allocation failed */
++ AVALANCHE_ERR_FREE_FAIL = -11, /* free failed */
++ AVALANCHE_ERR_MEM_CORRUPT = -12, /* corrupted memory */
++ AVALANCHE_ERR_BUF_LINK = -13, /* buffer linking failed */
++
++ /* Device issues */
++ AVALANCHE_ERR_DEVICE_TIMEOUT = -20, /* device timeout on read/write */
++ AVALANCHE_ERR_DEVICE_MALFUNC = -21, /* device malfunction */
++
++ AVALANCHE_ERR_INVID = -30 /* Invalid ID */
++
++} AVALANCHE_ERR;
++
++/*****************************************************************************
++ * Reset Control Module
++ *****************************************************************************/
++
++typedef enum AVALANCHE_RESET_MODULE_tag
++{
++ RESET_MODULE_UART0 = 0,
++ RESET_MODULE_UART1 = 1,
++ RESET_MODULE_I2C = 2,
++ RESET_MODULE_TIMER0 = 3,
++ RESET_MODULE_TIMER1 = 4,
++ RESET_MODULE_GPIO = 6,
++ RESET_MODULE_ADSLSS = 7,
++ RESET_MODULE_USBS = 8,
++ RESET_MODULE_SAR = 9,
++ RESET_MODULE_VDMA_VT = 11,
++ RESET_MODULE_FSER = 12,
++ RESET_MODULE_VLYNQ1 = 16,
++ RESET_MODULE_EMAC0 = 17,
++ RESET_MODULE_DMA = 18,
++ RESET_MODULE_BIST = 19,
++ RESET_MODULE_VLYNQ0 = 20,
++ RESET_MODULE_EMAC1 = 21,
++ RESET_MODULE_MDIO = 22,
++ RESET_MODULE_ADSLSS_DSP = 23,
++ RESET_MODULE_EPHY = 26
++} AVALANCHE_RESET_MODULE_T;
++
++typedef enum AVALANCHE_RESET_CTRL_tag
++{
++ IN_RESET = 0,
++ OUT_OF_RESET
++} AVALANCHE_RESET_CTRL_T;
++
++typedef enum AVALANCHE_SYS_RST_MODE_tag
++{
++ RESET_SOC_WITH_MEMCTRL = 1, /* SW0 bit in SWRCR register */
++ RESET_SOC_WITHOUT_MEMCTRL = 2 /* SW1 bit in SWRCR register */
++} AVALANCHE_SYS_RST_MODE_T;
++
++typedef enum AVALANCHE_SYS_RESET_STATUS_tag
++{
++ HARDWARE_RESET = 0,
++ SOFTWARE_RESET0, /* Caused by writing 1 to SW0 bit in SWRCR register */
++ WATCHDOG_RESET,
++ SOFTWARE_RESET1 /* Caused by writing 1 to SW1 bit in SWRCR register */
++} AVALANCHE_SYS_RESET_STATUS_T;
++
++AVALANCHE_RESET_CTRL_T avalanche_get_reset_status(AVALANCHE_RESET_MODULE_T reset_module);
++void avalanche_sys_reset(AVALANCHE_SYS_RST_MODE_T mode);
++AVALANCHE_SYS_RESET_STATUS_T avalanche_get_sys_last_reset_status(void);
++
++typedef int (*REMOTE_VLYNQ_DEV_RESET_CTRL_FN)(unsigned int reset_module, AVALANCHE_RESET_CTRL_T reset_ctrl);
++
++/*****************************************************************************
++ * Power Control Module
++ *****************************************************************************/
++
++typedef enum AVALANCHE_POWER_CTRL_tag
++{
++ POWER_CTRL_POWER_UP = 0,
++ POWER_CTRL_POWER_DOWN
++} AVALANCHE_POWER_CTRL_T;
++
++typedef enum AVALANCHE_SYS_POWER_MODE_tag
++{
++ GLOBAL_POWER_MODE_RUN = 0, /* All system is up */
++ GLOBAL_POWER_MODE_IDLE, /* MIPS is power down, all peripherals working */
++ GLOBAL_POWER_MODE_STANDBY, /* Chip in power down, but clock to ADSKL subsystem is running */
++ GLOBAL_POWER_MODE_POWER_DOWN /* Total chip is powered down */
++} AVALANCHE_SYS_POWER_MODE_T;
++
++void avalanche_power_ctrl(unsigned int power_module, AVALANCHE_POWER_CTRL_T power_ctrl);
++AVALANCHE_POWER_CTRL_T avalanche_get_power_status(unsigned int power_module);
++void avalanche_set_global_power_mode(AVALANCHE_SYS_POWER_MODE_T power_mode);
++AVALANCHE_SYS_POWER_MODE_T avalanche_get_global_power_mode(void);
++
++/*****************************************************************************
++ * Wakeup Control
++ *****************************************************************************/
++
++typedef enum AVALANCHE_WAKEUP_INTERRUPT_tag
++{
++ WAKEUP_INT0 = 1,
++ WAKEUP_INT1 = 2,
++ WAKEUP_INT2 = 4,
++ WAKEUP_INT3 = 8
++} AVALANCHE_WAKEUP_INTERRUPT_T;
++
++typedef enum TNETV1050_WAKEUP_CTRL_tag
++{
++ WAKEUP_DISABLED = 0,
++ WAKEUP_ENABLED
++} AVALANCHE_WAKEUP_CTRL_T;
++
++typedef enum TNETV1050_WAKEUP_POLARITY_tag
++{
++ WAKEUP_ACTIVE_HIGH = 0,
++ WAKEUP_ACTIVE_LOW
++} AVALANCHE_WAKEUP_POLARITY_T;
++
++void avalanche_wakeup_ctrl(AVALANCHE_WAKEUP_INTERRUPT_T wakeup_int,
++ AVALANCHE_WAKEUP_CTRL_T wakeup_ctrl,
++ AVALANCHE_WAKEUP_POLARITY_T wakeup_polarity);
++
++/*****************************************************************************
++ * GPIO Control
++ *****************************************************************************/
++
++typedef enum AVALANCHE_GPIO_PIN_MODE_tag
++{
++ FUNCTIONAL_PIN = 0,
++ GPIO_PIN = 1
++} AVALANCHE_GPIO_PIN_MODE_T;
++
++typedef enum AVALANCHE_GPIO_PIN_DIRECTION_tag
++{
++ GPIO_OUTPUT_PIN = 0,
++ GPIO_INPUT_PIN = 1
++} AVALANCHE_GPIO_PIN_DIRECTION_T;
++
++typedef enum { GPIO_FALSE, GPIO_TRUE } AVALANCHE_GPIO_BOOL_T;
++
++void avalanche_gpio_init(void);
++int avalanche_gpio_ctrl(unsigned int gpio_pin,
++ AVALANCHE_GPIO_PIN_MODE_T pin_mode,
++ AVALANCHE_GPIO_PIN_DIRECTION_T pin_direction);
++int avalanche_gpio_ctrl_with_link_count(unsigned int gpio_pin,
++ AVALANCHE_GPIO_PIN_MODE_T pin_mode,
++ AVALANCHE_GPIO_PIN_DIRECTION_T pin_direction);
++int avalanche_gpio_out_bit(unsigned int gpio_pin, int value);
++int avalanche_gpio_in_bit(unsigned int gpio_pin);
++int avalanche_gpio_out_value(unsigned int out_val, unsigned int set_mask, unsigned int reg_index);
++int avalanche_gpio_out_value_with_link_count(unsigned int out_val, unsigned int set_mask, unsigned int reg_index);
++int avalanche_gpio_in_value(unsigned int *in_val, unsigned int reg_index);
++
++unsigned int avalanche_get_chip_version_info(void);
++
++unsigned int avalanche_get_vbus_freq(void);
++void avalanche_set_vbus_freq(unsigned int);
++
++
++typedef int (*SET_MDIX_ON_CHIP_FN_T)(unsigned int base_addr, unsigned int operation);
++int avalanche_set_mdix_on_chip(unsigned int base_addr, unsigned int operation);
++unsigned int avalanche_is_mdix_on_chip(void);
++
++#endif
+diff -urN linux.old/include/asm-mips/ar7/avalanche_regs.h linux.dev/include/asm-mips/ar7/avalanche_regs.h
+--- linux.old/include/asm-mips/ar7/avalanche_regs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/avalanche_regs.h 2005-11-10 01:10:46.071588750 +0100
+@@ -0,0 +1,567 @@
++/*
++ * $Id$
++ * Avalanche Register Descriptions
++ *
++ * Jeff Harrell, jharrell@ti.com
++ * 2000 (c) Texas Instruments Inc.
++ */
++
++#ifndef __AVALANCHE_REGS_H
++#define __AVALANCHE_REGS_H
++
++#include <asm/addrspace.h>
++#include <linux/config.h>
++
++/*----------------------------------------*/
++/* Base offsets within the Avalanche ASIC */
++/*----------------------------------------*/
++
++#define BBIF_SPACE0 (KSEG1ADDR(0x01000000))
++#define BBIF_SPACE1 (KSEG1ADDR(0x01800000))
++#define BBIF_CONTROL (KSEG1ADDR(0x02000000))
++#define ATM_SAR_BASE (KSEG1ADDR(0x03000000))
++#define USB_MCU_BASE (KSEG1ADDR(0x03400000))
++#define DES_BASE (KSEG1ADDR(0x08600000))
++#define ETH_MACA_BASE (KSEG1ADDR(0x08610000))
++#define ETH_MACB_BASE (KSEG1ADDR(0x08612800))
++#define MEM_CTRLR_BASE (KSEG1ADDR(0x08610800))
++#define GPIO_BASE (KSEG1ADDR(0x08610900))
++#define CLK_CTRL_BASE (KSEG1ADDR(0x08610A00))
++#define WATCH_DOG_BASE (KSEG1ADDR(0x08610B00))
++#define TMR1_BASE (KSEG1ADDR(0x08610C00))
++#define TRM2_BASE (KSEG1ADDR(0x08610D00))
++#define UARTA_BASE (KSEG1ADDR(0x08610E00))
++#define UARTB_BASE (KSEG1ADDR(0x08610F00))
++#define I2C_BASE (KSEG1ADDR(0x08611000))
++#define DEV_ID_BASE (KSEG1ADDR(0x08611100))
++#define USB_BASE (KSEG1ADDR(0x08611200))
++#define PCI_CONFIG_BASE (KSEG1ADDR(0x08611300))
++#define DMA_BASE (KSEG1ADDR(0x08611400))
++#define RESET_CTRL_BASE (KSEG1ADDR(0x08611600))
++#define DSL_IF_BASE (KSEG1ADDR(0x08611B00))
++#define INT_CTL_BASE (KSEG1ADDR(0x08612400))
++#define PHY_BASE (KSEG1ADDR(0x1E000000))
++
++/*---------------------------------*/
++/* Device ID, chip version number */
++/*---------------------------------*/
++
++#define AVALANCHE_CHVN (*(volatile unsigned int *)(DEV_ID_BASE+0x14))
++#define AVALANCHE_DEVID1 (*(volatile unsigned int *)(DEV_ID_BASE+0x18))
++#define AVALANCHE_DEVID2 (*(volatile unsigned int *)(DEV_ID_BASE+0x1C))
++
++/*----------------------------------*/
++/* Reset Control VW changed to ptrs */
++/*----------------------------------*/
++
++#define AVALANCHE_PRCR (*(volatile unsigned int *)(RESET_CTRL_BASE + 0x0)) /* Peripheral reset control */
++#define AVALANCHE_SWRCR (*(volatile unsigned int *)(RESET_CTRL_BASE + 0x4)) /* Software reset control */
++#define AVALANCHE_RSR (*(volatile unsigned int *)(RESET_CTRL_BASE + 0x8)) /* Reset status register */
++
++/* reset control bits */
++
++#define AV_RST_UART0 (1<<0) /* Brings UART0 out of reset */
++#define AV_RST_UART1 (1<<1) /* Brings UART1 out of reset */
++#define AV_RST_IICM (1<<2) /* Brings the I2CM out of reset */
++#define AV_RST_TIMER0 (1<<3) /* Brings Timer 0 out of reset */
++#define AV_RST_TIMER1 (1<<4) /* Brings Timer 1 out of reset */
++#define AV_RST_DES (1<<5) /* Brings the DES module out of reset */
++#define AV_RST_GPIO (1<<6) /* Brings the GPIO module out of reset (see note below) */
++/*
++ JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE
++ If you reset the GPIO interface all of the directions (i/o) of the UART B
++ interface pins are inputs and must be reconfigured so as not to lose the
++ serial console interface
++ JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE
++*/
++#define AV_RST_BBIF (1<<7) /* Brings the Broadband interface out of reset */
++#define AV_RST_USB (1<<8) /* Brings the USB module out of reset */
++#define AV_RST_SAR (1<<9) /* Brings the SAR out of reset */
++#define AV_RST_HDLC (1<<10) /* Brings the HDLC module out of reset */
++#define AV_RST_PCI (1<<16) /* Brings the PCI module out of reset */
++#define AV_RST_ETH_MAC0 (1<<17) /* Brings the Ethernet MAC0 out of reset */
++#define AV_RST_PICO_DMA (1<<18) /* Brings the PICO DMA module out of reset */
++#define AV_RST_BIST (1<<19) /* Brings the BIST module out of reset */
++#define AV_RST_DSP (1<<20) /* Brings the DSP sub system out of reset */
++#define AV_RST_ETH_MAC1 (1<<21) /* Brings the Ethernet MAC1 out of reset */
++
++/*----------------------*/
++/* Physical interfaces */
++/*----------------------*/
++
++/* Phy loopback */
++#define PHY_LOOPBACK 1
++
++
++/* Phy 0 */
++#define PHY0BASE (PHY_BASE)
++#define PHY0RST (*(volatile unsigned char *) (PHY0BASE)) /* reset */
++#define PHY0CTRL (*(volatile unsigned char *) (PHY0BASE+0x5)) /* control */
++#define PHY0RACPCTRL (*(volatile unsigned char *) (PHY0BASE+0x50)) /* RACP control/status */
++#define PHY0TACPCTRL (*(volatile unsigned char *) (PHY0BASE+0x60)) /* TACP idle/unassigned cell hdr */
++#define PHY0RACPINT (*(volatile unsigned char *) (PHY0BASE+0x51)) /* RACP interrupt enable/Status */
++
++
++/* Phy 1 */
++
++#define PHY1BASE (PHY_BASE + 0x100000)
++#define PHY1RST (*(volatile unsigned char *) (PHY1BASE)) /* reset */
++#define PHY1CTRL (*(volatile unsigned char *) (PHY1BASE+0x5)) /* control */
++#define PHY1RACPCTRL (*(volatile unsigned char *) (PHY1BASE+0x50))
++#define PHY1TACPCTRL (*(volatile unsigned char *) (PHY1BASE+0x60))
++#define PHY1RACPINT (*(volatile unsigned char *) (PHY1BASE+0x51))
++
++/* Phy 2 */
++
++#define PHY2BASE (PHY_BASE + 0x200000)
++#define PHY2RST (*(volatile unsigned char *) (PHY2BASE)) /* reset */
++#define PHY2CTRL (*(volatile unsigned char *) (PHY2BASE+0x5)) /* control */
++#define PHY2RACPCTRL (*(volatile unsigned char *) (PHY2BASE+0x50))
++#define PHY2TACPCTRL (*(volatile unsigned char *) (PHY2BASE+0x60))
++#define PHY2RACPINT (*(volatile unsigned char *) (PHY2BASE+0x51))
++
++/*-------------------*/
++/* Avalanche ATM SAR */
++/*-------------------*/
++
++#define AVSAR_SYSCONFIG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000000)) /* SAR system config register */
++#define AVSAR_SYSSTATUS (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000004)) /* SAR system status register */
++#define AVSAR_INT_ENABLE (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000008)) /* SAR interrupt enable register */
++#define AVSAR_CONN_VPI_VCI (*(volatile unsigned int*)(ATM_SAR_BASE+0x0000000c)) /* VPI/VCI connection config */
++#define AVSAR_CONN_CONFIG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000010)) /* Connection config register */
++#define AVSAR_OAM_CONFIG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000018)) /* OAM configuration register */
++
++/* Transmit completion ring registers */
++
++#define AVSAR_TCRAPTR (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000100))
++#define AVSAR_TCRASIZE (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000104))
++#define AVSAR_TCRAINTTHRESH (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000108))
++#define AVSAR_TCRATOTENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000010c))
++#define AVSAR_TCRAFREEENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000110))
++#define AVSAR_TCRAPENDENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000114))
++#define AVSAR_TCRAENTINC (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000118))
++#define AVSAR_TCRBPTR (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000011c))
++#define AVSAR_TCRBSIZE (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000120))
++#define AVSAR_TCRBINTTHRESH (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000124))
++#define AVSAR_TCRBTOTENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000128))
++#define AVSAR_TCRBFREEENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000012c))
++#define AVSAR_TCRBPENDENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000130))
++#define AVSAR_TCRBENTINC (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000134))
++
++/* Transmit Queue Packet registers */
++#define AVSAR_TXQUEUE_PKT0 (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000140))
++#define AVSAR_TXQUEUE_PKT1 (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000144))
++#define AVSAR_TXQUEUE_PKT2 (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000148))
++#define AVSAR_TX_FLUSH (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000014C))
++/* Receive completion ring registers */
++
++#define AVSAR_RCRAPTR (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000200))
++#define AVSAR_RCRASIZE (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000204))
++#define AVSAR_RCRAINTTHRESH (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000208))
++#define AVSAR_RCRATOTENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000020c))
++#define AVSAR_RCRAFREEENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000210))
++#define AVSAR_RCRAPENDENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000214))
++#define AVSAR_RCRAENTINC (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000218))
++#define AVSAR_RCRBPTR (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000021c))
++#define AVSAR_RCRBSIZE (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000220))
++#define AVSAR_RCRBINTTHRESH (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000224))
++#define AVSAR_RCRBTOTENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000228))
++#define AVSAR_RCRBFREEENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000022c))
++#define AVSAR_RCRBPENDENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000230))
++#define AVSAR_RCRBENTINC (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000234))
++
++#define AVSAR_RXFBL_ADD0 (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000240)) /* Rx Free buffer list add 0 */
++#define AVSAR_RXFBL_ADD1 (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000244)) /* Rx Free buffer list add 1 */
++#define AVSAR_RXFBL_ADD2 (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000248)) /* Rx Free buffer list add 2 */
++#define AVSAR_RXFBLSIZE_0 (*(volatile unsigned int*)(ATM_SAR_BASE+0x0000028c)) /* Rx Free buffer list size 0 */
++#define AVSAR_RXFBLSIZE_1 (*(volatile unsigned int*)(ATM_SAR_BASE+0x0000029c)) /* Rx Free buffer list size 1 */
++#define AVSAR_RXFBLSIZE_2 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000002ac)) /* Rx Free buffer list size 2 */
++#define AVSAR_RXFBLSIZE_3 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000002bc)) /* Rx Free buffer list size 3 */
++
++
++#if defined(CONFIG_MIPS_EVM3D) || defined(CONFIG_MIPS_AR5D01) || defined(CONFIG_MIPS_AR5W01)
++
++#define AVSAR_SAR_FREQUENCY (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010480))
++#define AVSAR_OAM_CC_SINK (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010484))
++#define AVSAR_OAM_AIS_RDI_RX (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010488))
++#define AVSAR_OAM_CPID0 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104E0))
++#define AVSAR_OAM_LLID0 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104F0))
++#define AVSAR_OAM_CPID1 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104E4))
++#define AVSAR_OAM_LLID1 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104F4))
++#define AVSAR_OAM_CPID2 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104E8))
++#define AVSAR_OAM_LLID2 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104F8))
++#define AVSAR_OAM_CPID3 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104EC))
++#define AVSAR_OAM_LLID3 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104FC))
++#define AVSAR_OAM_CORR_TAG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010500))
++#define AVSAR_OAM_FAR_COUNT (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010520))
++#define AVSAR_OAM_NEAR_COUNT (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010540))
++#define AVSAR_OAM_CONFIG_REG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000018))
++#define AVSAR_FAIRNESS_REG (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104B8))
++#define AVSAR_UBR_PCR_REG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010490))
++
++
++/*
++
++#define OAM_CPID_ADD 0xa30104e0
++
++#define OAM_LLID_ADD 0xa30104f0
++
++#define OAM_LLID_VAL 0xffffffff
++
++#define OAM_CORR_TAG 0xa3010500
++
++#define OAM_FAR_COUNT_ADD 0xa3010520
++
++#define OAM_NEAR_COUNT_ADD 0xa3010540
++
++#define OAM_CONFIG_REG_ADD 0xa3000018
++*/
++
++
++#else /* CONFIG_MIPS_EVM3 || CONFIG_MIPS_ACPEP */
++
++#define AVSAR_SAR_FREQUENCY (*(volatile unsigned int*)(ATM_SAR_BASE+0x00012000))
++#define AVSAR_OAM_CC_SINK (*(volatile unsigned int*)(ATM_SAR_BASE+0x00012004))
++#define AVSAR_OAM_AIS_RDI_RX (*(volatile unsigned int*)(ATM_SAR_BASE+0x00012008))
++#define AVSAR_OAM_CPID (*(volatile unsigned int*)(ATM_SAR_BASE+0x00012300))
++
++#endif /* CONFIG_MIPS_EVM3D || CONFIG_MIPS_AR5D01 || CONFIG_MIPS_AR5W01 */
++
++
++#define AVSAR_STATE_RAM (ATM_SAR_BASE + 0x010000) /* SAR state RAM */
++#define AVSAR_PDSP_BASE (ATM_SAR_BASE + 0x020000) /* SAR PDSP base address */
++#define AVSAR_TXDMA_BASE (ATM_SAR_BASE + 0x030000) /* Transmit DMA state base */
++#define AVSAR_TDMASTATE6 0x18 /* Transmit DMA state word 6 */
++#define AVSAR_RXDMA_BASE (ATM_SAR_BASE + 0x040000) /* Receive DMA state base */
++#define AVSAR_RDMASTATE0 0x0 /* Receive DMA state word 0 */
++
++/*------------------------------------------*/
++/* DSL Interface */
++/*------------------------------------------*/
++
++#define AVDSL_TX_EN (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000000))
++#define AVDSL_RX_EN (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000004))
++#define AVDSL_POLL (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000008))
++
++/* Fast */
++
++#define AVDSL_TX_FIFO_ADDR0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x0000000C))
++#define AVDSL_TX_FIFO_BASE0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000010))
++#define AVDSL_TX_FIFO_LEN0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000014))
++#define AVDSL_TX_FIFO_PR0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000018))
++#define AVDSL_RX_FIFO_ADDR0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x0000001C))
++#define AVDSL_RX_FIFO_BASE0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000020))
++#define AVDSL_RX_FIFO_LEN0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000024))
++#define AVDSL_RX_FIFO_PR0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000028))
++
++/* Interleaved */
++
++#define AVDSL_TX_FIFO_ADDR1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x0000002C))
++#define AVDSL_TX_FIFO_BASE1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000030))
++#define AVDSL_TX_FIFO_LEN1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000034))
++#define AVDSL_TX_FIFO_PR1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000038))
++#define AVDSL_RX_FIFO_ADDR1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x0000003C))
++#define AVDSL_RX_FIFO_BASE1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000040))
++#define AVDSL_RX_FIFO_LEN1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000044))
++#define AVDSL_RX_FIFO_PR1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000048))
++
++/*------------------------------------------*/
++/* Broadband I/F */
++/*------------------------------------------*/
++
++#define AVBBIF_BBIF_CNTRL (*(volatile unsigned int *)(BBIF_CONTROL + 0x00000000))
++#define AVBBIF_ADDR_TRANS_0 (*(volatile unsigned int *)(BBIF_CONTROL + 0x00000004))
++#define AVBBIF_ADDR_TRANS_1 (*(volatile unsigned int *)(BBIF_CONTROL + 0x00000008))
++#define AVBBIF_ADDR_XB_MX_BL (*(volatile unsigned int *)(BBIF_CONTROL + 0x0000000C))
++#define AVBBIF_INFIFO_LVL (*(volatile unsigned int *)(BBIF_CONTROL + 0x00000010))
++#define AVBBIF_OUTFIFO_LVL (*(volatile unsigned int *)(BBIF_CONTROL + 0x00000014))
++
++#define AVBBIF_DISABLED 0x0
++#define AVBBIF_LBT4040_INT 0x1
++#define AVBBIF_XBUS 0x2
++#define AVBBIF_LBT4040_EXT 0x4
++
++#define AVBBIF_ADDR_MASK0 0xff000000 /* handles upper bits of BBIF 0 address */
++#define AVBBIF_ADDR_MASK1 0xff800000 /* handles upper bits of BBIF 1 address */
++#define AVBBIF_TRANS_MASK 0xff000000
++/*------------------------------------------*/
++/* GPIO I/F */
++/*------------------------------------------*/
++
++#define GPIO_DATA_INPUT (*(volatile unsigned int *)(GPIO_BASE + 0x00000000))
++#define GPIO_DATA_OUTPUT (*(volatile unsigned int *)(GPIO_BASE + 0x00000004))
++#define GPIO_DATA_DIR (*(volatile unsigned int *)(GPIO_BASE + 0x00000008)) /* 0=output 1=input */
++#define GPIO_DATA_ENABLE (*(volatile unsigned int *)(GPIO_BASE + 0x0000000C)) /* 0=GPIO Mux 1=GPIO */
++
++#define GPIO_0 (1<<21)
++#define GPIO_1 (1<<22)
++#define GPIO_2 (1<<23)
++#define GPIO_3 (1<<24)
++#define EINT_1 (1<<18)
++
++/*
++ JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE
++ If you reset the GPIO interface all of the directions (i/o) of the UART B
++ interface pins are inputs and must be reconfigured so as not to lose the
++ serial console interface
++ JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE
++*/
++
++/*------------------------------------------*/
++/* CLK_CTRL */
++/*------------------------------------------*/
++#define PERIPH_CLK_CTL (*(volatile unsigned int *)(CLK_CTRL_BASE + 0x00000004))
++
++#define PCLK_0_HALF_VBUS (0<<16)
++#define PCLK_EQ_INPUT (1<<16)
++#define BBIF_CLK_HALF_VBUS (0<<17)
++#define BBIF_CLK_EQ_VBUS (1<<17)
++#define BBIF_CLK_EQ_BBCLK (3<<17)
++#define DSP_MODCLK_DSPCLKI (0<<20)
++#define DSP_MODCLK_REFCLKI (1<<20)
++#define USB_CLK_EQ_USBCLKI (0<<21)
++#define USB_CLK_EQ_REFCLKI (1<<21)
++
++/*------------------------------------------*/
++/* PCI Control Registers */
++/*------------------------------------------*/
++#define PCIC_CONTROL (*(volatile unsigned int *)(PCI_CONFIG_BASE))
++#define PCIC_CONTROL_CFG_DONE (1<<0)
++#define PCIC_CONTROL_DIS_SLAVE_TO (1<<1)
++#define PCIC_CONTROL_FORCE_DELAY_READ (1<<2)
++#define PCIC_CONTROL_FORCE_DELAY_READ_LINE (1<<3)
++#define PCIC_CONTROL_FORCE_DELAY_READ_MULT (1<<4)
++#define PCIC_CONTROL_MEM_SPACE_EN (1<<5)
++#define PCIC_CONTROL_MEM_MASK (1<<6)
++#define PCIC_CONTROL_IO_SPACE_EN (1<<7)
++#define PCIC_CONTROL_IO_MASK (1<<8)
++/* PCIC_CONTROL_RESERVED (1<<9) */
++#define PCIC_CONTROL_BASE0_EN (1<<10)
++#define PCIC_CONTROL_BASE1_EN (1<<11)
++#define PCIC_CONTROL_BASE2_EN (1<<12)
++#define PCIC_CONTROL_HOLD_MASTER_WRITE (1<<13)
++#define PCIC_CONTROL_ARBITER_EN (1<<14)
++#define PCIC_INT_SOURCE (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000004))
++#define PCIC_INT_SOURCE_PWR_MGMT (1<<0)
++#define PCIC_INT_SOURCE_PCI_TARGET (1<<1)
++#define PCIC_INT_SOURCE_PCI_MASTER (1<<2)
++#define PCIC_INT_SOURCE_POWER_WAKEUP (1<<3)
++#define PCIC_INT_SOURCE_PMEIN (1<<4)
++/* PCIC_INT_SOURCE_RESERVED (1<<5) */
++/* PCIC_INT_SOURCE_RESERVED (1<<6) */
++#define PCIC_INT_SOURCE_PIC_INTA (1<<7)
++#define PCIC_INT_SOURCE_PIC_INTB (1<<8)
++#define PCIC_INT_SOURCE_PIC_INTC (1<<9)
++#define PCIC_INT_SOURCE_PIC_INTD (1<<10)
++#define PCIC_INT_SOURCE_SOFT_INT0 (1<<11)
++#define PCIC_INT_SOURCE_SOFT_INT1 (1<<12)
++#define PCIC_INT_SOURCE_SOFT_INT2 (1<<13)
++#define PCIC_INT_SOURCE_SOFT_INT3 (1<<14)
++#define PCIC_INT_CLEAR (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000008))
++#define PCIC_INT_CLEAR_PM (1<<0)
++#define PCIC_INT_CLEAR_PCI_TARGET (1<<1)
++#define PCIC_INT_CLEAR_PCI_MASTER (1<<2)
++/* PCIC_INT_CLEAR_RESERVED (1<<3) */
++#define PCIC_INT_CLEAR_PMEIN (1<<4)
++/* PCIC_INT_CLEAR_RESERVED (1<<5) */
++/* PCIC_INT_CLEAR_RESERVED (1<<6) */
++#define PCIC_INT_CLEAR_PCI_INTA (1<<7)
++#define PCIC_INT_CLEAR_PCI_INTB (1<<8)
++#define PCIC_INT_CLEAR_PCI_INTC (1<<9)
++#define PCIC_INT_CLEAR_PCI_INTD (1<<10)
++#define PCIC_INT_CLEAR_SOFT_INT0 (1<<11)
++#define PCIC_INT_CLEAR_SOFT_INT1 (1<<12)
++#define PCIC_INT_CLEAR_SOFT_INT2 (1<<13)
++#define PCIC_INT_CLEAR_SOFT_INT3 (1<<14)
++#define PCIC_INT_EN_AVAL (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000000c))
++#define PCIC_INT_EN_AVAL_PM (1<<0)
++#define PCIC_INT_EN_AVAL_PCI_TARGET (1<<1)
++#define PCIC_INT_EN_AVAL_PCI_MASTER (1<<2)
++/* PCIC_INT_EN_AVAL_RESERVED (1<<3) */
++#define PCIC_INT_EN_AVAL_PMEIN (1<<4)
++/* PCIC_INT_EN_AVAL_RESERVED (1<<5) */
++/* PCIC_INT_EN_AVAL_RESERVED (1<<6) */
++#define PCIC_INT_EN_AVAL_PCI_INTA (1<<7)
++#define PCIC_INT_EN_AVAL_PCI_INTB (1<<8)
++#define PCIC_INT_EN_AVAL_PCI_INTC (1<<9)
++#define PCIC_INT_EN_AVAL_PCI_INTD (1<<10)
++#define PCIC_INT_EN_AVAL_SOFT_INT0 (1<<11)
++#define PCIC_INT_EN_AVAL_SOFT_INT1 (1<<12)
++#define PCIC_INT_EN_AVAL_SOFT_INT2 (1<<13)
++#define PCIC_INT_EN_AVAL_SOFT_INT3 (1<<14)
++#define PCIC_INT_EN_PCI (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000010))
++#define PCIC_INT_EN_PCI_PM (1<<0)
++#define PCIC_INT_EN_PCI_PCI_TARGET (1<<1)
++#define PCIC_INT_EN_PCI_PCI_MASTER (1<<2)
++/* PCIC_INT_EN_PCI_RESERVED (1<<3) */
++#define PCIC_INT_EN_PCI_PMEIN (1<<4)
++/* PCIC_INT_EN_PCI_RESERVED (1<<5) */
++/* PCIC_INT_EN_PCI_RESERVED (1<<6) */
++#define PCIC_INT_EN_PCI_PCI_INTA (1<<7)
++#define PCIC_INT_EN_PCI_PCI_INTB (1<<8)
++#define PCIC_INT_EN_PCI_PCI_INTC (1<<9)
++#define PCIC_INT_EN_PCI_PCI_INTD (1<<10)
++#define PCIC_INT_EN_PCI_SOFT_INT0 (1<<11)
++#define PCIC_INT_EN_PCI_SOFT_INT1 (1<<12)
++#define PCIC_INT_EN_PCI_SOFT_INT2 (1<<13)
++#define PCIC_INT_EN_PCI_SOFT_INT3 (1<<14)
++#define PCIC_INT_SWSET (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000014))
++#define PCIC_INT_SWSET_SOFT_INT0 (1<<0)
++#define PCIC_INT_SWSET_SOFT_INT1 (1<<1)
++#define PCIC_INT_SWSET_SOFT_INT2 (1<<2)
++#define PCIC_INT_SWSET_SOFT_INT3 (1<<3)
++#define PCIC_PM_CTL (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000018))
++#define PCIC_PM_CTL_PWR_STATE_MASK (0x02)
++/* PCIC_PM_CTL_RESERVED (1<<2) */
++/* PCIC_PM_CTL_RESERVED (1<<3) */
++/* PCIC_PM_CTL_RESERVED (1<<4) */
++/* PCIC_PM_CTL_RESERVED (1<<5) */
++/* PCIC_PM_CTL_RESERVED (1<<6) */
++/* PCIC_PM_CTL_RESERVED (1<<7) */
++/* PCIC_PM_CTL_RESERVED (1<<8) */
++/* PCIC_PM_CTL_RESERVED (1<<9) */
++#define PCIC_PM_CTL_PWR_SUPPORT (1<<10)
++#define PCIC_PM_CTL_PMEIN (1<<11)
++#define PCIC_PM_CTL_CAP_MASK (*(volatile unsigned short int *)(PCI_CONFIG_BASE + 0x0000001a))
++#define PCIC_PM_CONSUME (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000001c))
++#define PCIC_PM_CONSUME_D0 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x0000001c))
++#define PCIC_PM_CONSUME_D1 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x0000001d))
++#define PCIC_PM_CONSUME_D2 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x0000001e))
++#define PCIC_PM_CONSUME_D3 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x0000001f))
++#define PCIC_PM_DISSAPATED (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000020))
++#define PCIC_PM_DISSAPATED_D0 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x00000020))
++#define PCIC_PM_DISSAPATED_D1 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x00000021))
++#define PCIC_PM_DISSAPATED_D2 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x00000022))
++#define PCIC_PM_DISSAPATED_D3 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x00000023))
++#define PCIC_PM_DATA_SCALE (*(volatile unsigned short int *)(PCI_CONFIG_BASE + 0x00000024))
++#define PCIC_VEND_DEV_ID (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000028))
++#define PCIC_SUB_VEND_DEV_ID (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000002c))
++#define PCIC_CLASS_REV_ID (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000030))
++#define PCIC_MAX_MIN (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000034))
++#define PCIC_MAST_MEM_AT0 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000003c))
++#define PCIC_MAST_MEM_AT1 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000040))
++#define PCIC_MAST_MEM_AT2 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000044))
++#define PCIC_SLAVE_MASK0 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000004c))
++#define PCIC_SLAVE_MASK1 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000050))
++#define PCIC_SLAVE_MASK2 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000054))
++#define PCIC_SLAVE_BASE_AT0 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000058))
++#define PCIC_SLAVE_BASE_AT1 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000005c))
++#define PCIC_SLAVE_BASE_AT2 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000060))
++#define PCIC_CONF_COMMAND (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000090))
++#define PCIC_CONF_ADDR (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000094))
++#define PCIC_CONF_DATA (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000098))
++
++/*------------------------------------------*/
++/* IIC_INTERFACE */
++/*------------------------------------------*/
++#define I2C_DATA_HI (*(volatile unsigned int *)(I2C_BASE + 0x0))
++#define I2C_DATA_LOW (*(volatile unsigned int *)(I2C_BASE + 0x4))
++#define I2C_CONFIG (*(volatile unsigned int *)(I2C_BASE + 0x8))
++#define I2C_DATA_READ (*(volatile unsigned int *)(I2C_BASE + 0xC))
++#define I2C_CLOCK_DIV (*(volatile unsigned int *)(I2C_BASE + 0x10))
++
++#define I2CWRITE 0x200
++#define I2CREAD 0x300
++#define I2C_END_BURST 0x400
++
++/* read bits */
++#define I2C_READ_ERROR 0x8000
++#define I2C_READ_COMPLETE 0x4000
++#define I2C_READ_BUSY 0x2000
++
++/* device types */
++#define I2C_IO_EXPANDER 0x2
++#define I2C_RTC 0xd
++
++/* device Addresses on I2C bus (EVM3) */
++#define SEVEN_SEGMENT_DISP 0x23 /* Device type = 0x2, Addr = 3 */
++#define EVM3_RTC 0xd0 /* Device type = 0xd, Addr = 0 */
++#define EVM3_RTC_I2C_ADDR 0x0
++
++/*------------------------------------------*/
++/* Ethernet MAC register offset definitions */
++/*------------------------------------------*/
++#define VMAC_DMACONFIG(X) (*(volatile unsigned int *)(X + 0x00000000))
++#define VMAC_INTSTS(X) (*(volatile unsigned int *)(X + 0x00000004))
++#define VMAC_INTMASK(X) (*(volatile unsigned int *)(X + 0x00000008))
++
++#define VMAC_WRAPCLK(X) (*(volatile unsigned int *)(X + 0x00000340))
++#define VMAC_STATSBASE(X) (*(volatile unsigned int *)(X + 0x00000400))
++
++#define VMAC_TCRPTR(X) (*(volatile unsigned int *)(X + 0x00000100))
++#define VMAC_TCRSIZE(X) (*(volatile unsigned int *)(X + 0x00000104))
++#define VMAC_TCRINTTHRESH(X) (*(volatile unsigned int *)(X + 0x00000108))
++#define VMAC_TCRTOTENT(X) (*(volatile unsigned int *)(X + 0x0000010C))
++#define VMAC_TCRFREEENT(X) (*(volatile unsigned int *)(X + 0x00000110))
++#define VMAC_TCRPENDENT(X) (*(volatile unsigned int *)(X + 0x00000114))
++#define VMAC_TCRENTINC(X) (*(volatile unsigned int *)(X + 0x00000118))
++#define VMAC_TXISRPACE(X) (*(volatile unsigned int *)(X + 0x0000011c))
++
++
++#define VMAC_TDMASTATE0(X) (*(volatile unsigned int *)(X + 0x00000120))
++#define VMAC_TDMASTATE1(X) (*(volatile unsigned int *)(X + 0x00000124))
++#define VMAC_TDMASTATE2(X) (*(volatile unsigned int *)(X + 0x00000128))
++#define VMAC_TDMASTATE3(X) (*(volatile unsigned int *)(X + 0x0000012C))
++#define VMAC_TDMASTATE4(X) (*(volatile unsigned int *)(X + 0x00000130))
++#define VMAC_TDMASTATE5(X) (*(volatile unsigned int *)(X + 0x00000134))
++#define VMAC_TDMASTATE6(X) (*(volatile unsigned int *)(X + 0x00000138))
++#define VMAC_TDMASTATE7(X) (*(volatile unsigned int *)(X + 0x0000013C))
++#define VMAC_TXPADDCNT(X) (*(volatile unsigned int *)(X + 0x00000140))
++#define VMAC_TXPADDSTART(X) (*(volatile unsigned int *)(X + 0x00000144))
++#define VMAC_TXPADDEND(X) (*(volatile unsigned int *)(X + 0x00000148))
++#define VMAC_TXQFLUSH(X) (*(volatile unsigned int *)(X + 0x0000014C))
++
++#define VMAC_RCRPTR(X) (*(volatile unsigned int *)(X + 0x00000200))
++#define VMAC_RCRSIZE(X) (*(volatile unsigned int *)(X + 0x00000204))
++#define VMAC_RCRINTTHRESH(X) (*(volatile unsigned int *)(X + 0x00000208))
++#define VMAC_RCRTOTENT(X) (*(volatile unsigned int *)(X + 0x0000020C))
++#define VMAC_RCRFREEENT(X) (*(volatile unsigned int *)(X + 0x00000210))
++#define VMAC_RCRPENDENT(X) (*(volatile unsigned int *)(X + 0x00000214))
++#define VMAC_RCRENTINC(X) (*(volatile unsigned int *)(X + 0x00000218))
++#define VMAC_RXISRPACE(X) (*(volatile unsigned int *)(X + 0x0000021c))
++
++#define VMAC_RDMASTATE0(X) (*(volatile unsigned int *)(X + 0x00000220))
++#define VMAC_RDMASTATE1(X) (*(volatile unsigned int *)(X + 0x00000224))
++#define VMAC_RDMASTATE2(X) (*(volatile unsigned int *)(X + 0x00000228))
++#define VMAC_RDMASTATE3(X) (*(volatile unsigned int *)(X + 0x0000022C))
++#define VMAC_RDMASTATE4(X) (*(volatile unsigned int *)(X + 0x00000230))
++#define VMAC_RDMASTATE5(X) (*(volatile unsigned int *)(X + 0x00000234))
++#define VMAC_RDMASTATE6(X) (*(volatile unsigned int *)(X + 0x00000238))
++#define VMAC_RDMASTATE7(X) (*(volatile unsigned int *)(X + 0x0000023C))
++#define VMAC_FBLADDCNT(X) (*(volatile unsigned int *)(X + 0x00000240))
++#define VMAC_FBLADDSTART(X) (*(volatile unsigned int *)(X + 0x00000244))
++#define VMAC_FBLADDEND(X) (*(volatile unsigned int *)(X + 0x00000248))
++#define VMAC_RXONOFF(X) (*(volatile unsigned int *)(X + 0x0000024C))
++
++#define VMAC_FBL0NEXTD(X) (*(volatile unsigned int *)(X + 0x00000280))
++#define VMAC_FBL0LASTD(X) (*(volatile unsigned int *)(X + 0x00000284))
++#define VMAC_FBL0COUNTD(X) (*(volatile unsigned int *)(X + 0x00000288))
++#define VMAC_FBL0BUFSIZE(X) (*(volatile unsigned int *)(X + 0x0000028C))
++
++#define VMAC_MACCONTROL(X) (*(volatile unsigned int *)(X + 0x00000300))
++#define VMAC_MACSTATUS(X) (*(volatile unsigned int *)(X + 0x00000304))
++#define VMAC_MACADDRHI(X) (*(volatile unsigned int *)(X + 0x00000308))
++#define VMAC_MACADDRLO(X) (*(volatile unsigned int *)(X + 0x0000030C))
++#define VMAC_MACHASH1(X) (*(volatile unsigned int *)(X + 0x00000310))
++#define VMAC_MACHASH2(X) (*(volatile unsigned int *)(X + 0x00000314))
++
++#define VMAC_WRAPCLK(X) (*(volatile unsigned int *)(X + 0x00000340))
++#define VMAC_BOFTEST(X) (*(volatile unsigned int *)(X + 0x00000344))
++#define VMAC_PACTEST(X) (*(volatile unsigned int *)(X + 0x00000348))
++#define VMAC_PAUSEOP(X) (*(volatile unsigned int *)(X + 0x0000034C))
++
++#define VMAC_MDIOCONTROL(X) (*(volatile unsigned int *)(X + 0x00000380))
++#define VMAC_MDIOUSERACCESS(X) (*(volatile unsigned int *)(X +0x00000384))
++#define VMAC_MDIOACK(X) (*(volatile unsigned int *)(X + 0x00000388))
++#define VMAC_MDIOLINK(X) (*(volatile unsigned int *)(X + 0x0000038C))
++#define VMAC_MDIOMACPHY(X) (*(volatile unsigned int *)(X + 0x00000390))
++
++#define VMAC_STATS_BASE(X) (X + 0x00000400)
++
++#endif __AVALANCHE_REGS_H
++
++
++
++
++
++
+diff -urN linux.old/include/asm-mips/ar7/avalanche_types.h linux.dev/include/asm-mips/ar7/avalanche_types.h
+--- linux.old/include/asm-mips/ar7/avalanche_types.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/avalanche_types.h 2005-11-10 01:10:46.071588750 +0100
+@@ -0,0 +1,126 @@
++/*------------------------------------------------------------------------------------------*\
++\*------------------------------------------------------------------------------------------*/
++#ifndef _avalanche_types_h_
++#define _avalanche_types_h_
++
++/*--- #include <asm/avalanche/generic/hal_modules/haltypes.h> ---*/
++#ifndef TRUE
++#define TRUE 1
++#endif
++#ifndef FALSE
++#define FALSE 0
++#endif
++#ifndef NULL
++#define NULL (void *)0
++#endif
++
++/*------------------------------------------------------------------------------------------*\
++ * Typen für Texas GPL Module
++\*------------------------------------------------------------------------------------------*/
++#ifndef __UINT8_T__
++typedef unsigned char UINT8;
++#define __UINT8_T__
++#endif
++
++#ifndef __UCHAR_T__
++typedef unsigned char UCHAR;
++#define __UCHAR_T__
++#endif
++
++#ifndef __INT8_T__
++typedef signed char INT8;
++#define __INT8_T__
++#endif
++
++#ifndef __UINT16_T__
++typedef unsigned short UINT16;
++#define __UINT16_T__
++#endif
++
++#ifndef __USHORT_T__
++typedef unsigned short USHORT;
++#define __USHORT_T__
++#endif
++
++#ifndef __INT16_T__
++typedef signed short INT16;
++#define __INT16_T__
++#endif
++
++#ifndef __UINT32_T__
++typedef unsigned int UINT32;
++#define __UINT32_T__
++#endif
++
++#ifndef __UINT_T__
++typedef unsigned int UINT;
++#define __UINT_T__
++#endif
++
++#ifndef __INT32_T__
++typedef signed int INT32;
++#define __INT32_T__
++#endif
++
++#ifndef __ULONG_T__
++typedef unsigned long ULONG;
++#define __ULONG_T__
++#endif
++
++#ifndef __BOOL_T__
++typedef int BOOL;
++#define __BOOL_T__
++#endif
++
++#ifndef __STATUS_T__
++typedef int STATUS;
++#define __STATUS_T__
++#endif
++
++/*------------------------------------------------------------------------------------------*\
++\*------------------------------------------------------------------------------------------*/
++typedef void (*p_vlynq_intr_cntrl_isr_t)(void *,void *,void *);
++typedef INT32 (*p_vlynq_interrupt_vector_set_t)(void *, UINT32, UINT32, INT32, INT32, INT32);
++typedef INT32 (*p_vlynq_interrupt_vector_cntl_t)(void *, UINT32, INT32, UINT32);
++typedef UINT32 (*p_vlynq_interrupt_get_count_t)(void *, UINT32);
++typedef INT32 (*p_vlynq_install_isr_t)(void *, UINT32, p_vlynq_intr_cntrl_isr_t, void *, void *, void *);
++typedef INT32 (*p_vlynq_uninstall_isr_t)(void *, UINT32, void *, void *, void *);
++typedef void (*p_vlynq_root_isr_t)(void *);
++typedef void (*p_vlynq_delay_t)(UINT32);
++typedef INT32 (*p_vlynq_interrupt_vector_map_t)(void *, INT32, UINT32, UINT32);
++typedef INT32 (*p_vlynq_interrupt_set_polarity_t)(void *, INT32, UINT32, INT32);
++typedef INT32 (*p_vlynq_interrupt_get_polarity_t)(void *, INT32, UINT32);
++typedef INT32 (*p_vlynq_interrupt_set_type_t)(void *, INT32, UINT32, INT32);
++typedef INT32 (*p_vlynq_interrupt_get_type_t)(void *, INT32, UINT32);
++typedef INT32 (*p_vlynq_interrupt_enable_t)(void *, INT32, UINT32);
++typedef INT32 (*p_vlynq_interrupt_disable_t)(void *, INT32, UINT32);
++
++/*------------------------------------------------------------------------------------------*\
++\*------------------------------------------------------------------------------------------*/
++extern p_vlynq_interrupt_vector_set_t p_vlynq_interrupt_vector_set;
++extern p_vlynq_interrupt_vector_cntl_t p_vlynq_interrupt_vector_cntl;
++extern p_vlynq_interrupt_get_count_t p_vlynq_interrupt_get_count;
++extern p_vlynq_install_isr_t p_vlynq_install_isr;
++extern p_vlynq_uninstall_isr_t p_vlynq_uninstall_isr;
++extern p_vlynq_root_isr_t p_vlynq_root_isr;
++extern p_vlynq_delay_t p_vlynq_delay;
++extern p_vlynq_interrupt_vector_map_t p_vlynq_interrupt_vector_map;
++extern p_vlynq_interrupt_set_polarity_t p_vlynq_interrupt_set_polarity;
++extern p_vlynq_interrupt_get_polarity_t p_vlynq_interrupt_get_polarity;
++extern p_vlynq_interrupt_set_type_t p_vlynq_interrupt_set_type;
++extern p_vlynq_interrupt_get_type_t p_vlynq_interrupt_get_type;
++extern p_vlynq_interrupt_enable_t p_vlynq_interrupt_enable;
++extern p_vlynq_interrupt_disable_t p_vlynq_interrupt_disable;
++extern void *p_vlynqDevice0;
++extern void *p_vlynqDevice1;
++
++/*------------------------------------------------------------------------------------------*\
++\*------------------------------------------------------------------------------------------*/
++enum _avalanche_need_ {
++ avalanche_need_vlynq,
++ avalanche_need_auto_mdix
++};
++
++int avalanche_need(enum _avalanche_need_);
++
++#endif /*--- #ifndef _avalanche_types_h_ ---*/
+diff -urN linux.old/include/asm-mips/ar7/if_port.h linux.dev/include/asm-mips/ar7/if_port.h
+--- linux.old/include/asm-mips/ar7/if_port.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/if_port.h 2005-11-10 01:10:46.071588750 +0100
+@@ -0,0 +1,26 @@
++/*******************************************************************************
++ * FILE PURPOSE: Interface port id Header file
++ *******************************************************************************
++ * FILE NAME: if_port.h
++ *
++ * DESCRIPTION: Header file carrying information about port ids of interfaces
++ *
++ *
++ * (C) Copyright 2003, Texas Instruments, Inc
++ ******************************************************************************/
++#ifndef _IF_PORT_H_
++#define _IF_PORT_H_
++
++#define AVALANCHE_CPMAC_LOW_PORT_ID 0
++#define AVALANCHE_CPMAC_HIGH_PORT_ID 1
++#define AVALANCHE_USB_PORT_ID 2
++#define AVALANCHE_WLAN_PORT_ID 3
++
++
++#define AVALANCHE_MARVELL_BASE_PORT_ID 4
++
++/* The marvell ports occupy port ids from 4 to 8 */
++/* so the next port id number should start at 9 */
++
++
++#endif /* _IF_PORT_H_ */
+diff -urN linux.old/include/asm-mips/ar7/sangam.h linux.dev/include/asm-mips/ar7/sangam.h
+--- linux.old/include/asm-mips/ar7/sangam.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/sangam.h 2005-11-10 01:10:46.071588750 +0100
+@@ -0,0 +1,180 @@
++#ifndef _SANGAM_H_
++#define _SANGAM_H_
++
++#include <linux/config.h>
++#include <asm/addrspace.h>
++
++/*----------------------------------------------------
++ * Sangam's Module Base Addresses
++ *--------------------------------------------------*/
++#define AVALANCHE_ADSL_SUB_SYS_MEM_BASE (KSEG1ADDR(0x01000000)) /* AVALANCHE ADSL Mem Base */
++#define AVALANCHE_BROADBAND_INTERFACE__BASE (KSEG1ADDR(0x02000000)) /* AVALANCHE BBIF */
++#define AVALANCHE_ATM_SAR_BASE (KSEG1ADDR(0x03000000)) /* AVALANCHE ATM SAR */
++#define AVALANCHE_USB_SLAVE_BASE (KSEG1ADDR(0x03400000)) /* AVALANCHE USB SLAVE */
++#define AVALANCHE_LOW_VLYNQ_MEM_MAP_BASE (KSEG1ADDR(0x04000000)) /* AVALANCHE VLYNQ 0 Mem map */
++#define AVALANCHE_LOW_CPMAC_BASE (KSEG1ADDR(0x08610000)) /* AVALANCHE CPMAC 0 */
++#define AVALANCHE_EMIF_CONTROL_BASE (KSEG1ADDR(0x08610800)) /* AVALANCHE EMIF */
++#define AVALANCHE_GPIO_BASE (KSEG1ADDR(0x08610900)) /* AVALANCHE GPIO */
++#define AVALANCHE_CLOCK_CONTROL_BASE (KSEG1ADDR(0x08610A00)) /* AVALANCHE Clock Control */
++#define AVALANCHE_WATCHDOG_TIMER_BASE (KSEG1ADDR(0x08610B00)) /* AVALANCHE Watch Dog Timer */
++#define AVALANCHE_TIMER0_BASE (KSEG1ADDR(0x08610C00)) /* AVALANCHE Timer 1 */
++#define AVALANCHE_TIMER1_BASE (KSEG1ADDR(0x08610D00)) /* AVALANCHE Timer 2 */
++#define AVALANCHE_UART0_REGS_BASE (KSEG1ADDR(0x08610E00)) /* AVALANCHE UART 0 */
++#define AVALANCHE_UART1_REGS_BASE (KSEG1ADDR(0x08610F00)) /* AVALANCHE UART 0 */
++#define AVALANCHE_I2C_BASE (KSEG1ADDR(0x08611000)) /* AVALANCHE I2C */
++#define AVALANCHE_USB_SLAVE_CONTROL_BASE (KSEG1ADDR(0x08611200)) /* AVALANCHE USB DMA */
++#define AVALANCHE_MCDMA0_CTRL_BASE (KSEG1ADDR(0x08611400)) /* AVALANCHE MC DMA 0 (channels 0-3) */
++#define AVALANCHE_RESET_CONTROL_BASE (KSEG1ADDR(0x08611600)) /* AVALANCHE Reset Control */
++#define AVALANCHE_BIST_CONTROL_BASE (KSEG1ADDR(0x08611700)) /* AVALANCHE BIST Control */
++#define AVALANCHE_LOW_VLYNQ_CONTROL_BASE (KSEG1ADDR(0x08611800)) /* AVALANCHE VLYNQ0 Control */
++#define AVALANCHE_DEVICE_CONFIG_LATCH_BASE (KSEG1ADDR(0x08611A00)) /* AVALANCHE Device Config Latch */
++#define AVALANCHE_HIGH_VLYNQ_CONTROL_BASE (KSEG1ADDR(0x08611C00)) /* AVALANCHE VLYNQ1 Control */
++#define AVALANCHE_MDIO_BASE (KSEG1ADDR(0x08611E00)) /* AVALANCHE MDIO */
++#define AVALANCHE_FSER_BASE (KSEG1ADDR(0x08612000)) /* AVALANCHE FSER base */
++#define AVALANCHE_INTC_BASE (KSEG1ADDR(0x08612400)) /* AVALANCHE INTC */
++#define AVALANCHE_HIGH_CPMAC_BASE (KSEG1ADDR(0x08612800)) /* AVALANCHE CPMAC 1 */
++#define AVALANCHE_HIGH_VLYNQ_MEM_MAP_BASE (KSEG1ADDR(0x0C000000)) /* AVALANCHE VLYNQ 1 Mem map */
++
++#define AVALANCHE_SDRAM_BASE 0x14000000UL
++
++
++/*----------------------------------------------------
++ * Sangam Interrupt Map (Primary Interrupts)
++ *--------------------------------------------------*/
++
++#define AVALANCHE_UNIFIED_SECONDARY_INT 0
++#define AVALANCHE_EXT_INT_0 1
++#define AVALANCHE_EXT_INT_1 2
++/* Line# 3 to 4 are reserved */
++#define AVALANCHE_TIMER_0_INT 5
++#define AVALANCHE_TIMER_1_INT 6
++#define AVALANCHE_UART0_INT 7
++#define AVALANCHE_UART1_INT 8
++#define AVALANCHE_DMA_INT0 9
++#define AVALANCHE_DMA_INT1 10
++/* Line# 11 to 14 are reserved */
++#define AVALANCHE_ATM_SAR_INT 15
++/* Line# 16 to 18 are reserved */
++#define AVALANCHE_LOW_CPMAC_INT 19
++/* Line# 20 is reserved */
++#define AVALANCHE_LOW_VLYNQ_INT 21
++#define AVALANCHE_CODEC_WAKEUP_INT 22
++/* Line# 23 is reserved */
++#define AVALANCHE_USB_SLAVE_INT 24
++#define AVALANCHE_HIGH_VLYNQ_INT 25
++/* Line# 26 to 27 are reserved */
++#define AVALANCHE_UNIFIED_PHY_INT 28
++#define AVALANCHE_I2C_INT 29
++#define AVALANCHE_DMA_INT2 30
++#define AVALANCHE_DMA_INT3 31
++/* Line# 32 is reserved */
++#define AVALANCHE_HIGH_CPMAC_INT 33
++/* Line# 34 to 36 is reserved */
++#define AVALANCHE_VDMA_VT_RX_INT 37
++#define AVALANCHE_VDMA_VT_TX_INT 38
++#define AVALANCHE_ADSL_SUB_SYSTEM_INT 39
++
++
++#define AVALANCHE_EMIF_INT 47
++
++
++
++/*-----------------------------------------------------------
++ * Sangam's Reset Bits
++ *---------------------------------------------------------*/
++
++#define AVALANCHE_UART0_RESET_BIT 0
++#define AVALANCHE_UART1_RESET_BIT 1
++#define AVALANCHE_I2C_RESET_BIT 2
++#define AVALANCHE_TIMER0_RESET_BIT 3
++#define AVALANCHE_TIMER1_RESET_BIT 4
++/* Reset bit 5 is reserved. */
++#define AVALANCHE_GPIO_RESET_BIT 6
++#define AVALANCHE_ADSL_SUB_SYS_RESET_BIT 7
++#define AVALANCHE_USB_SLAVE_RESET_BIT 8
++#define AVALANCHE_ATM_SAR_RESET_BIT 9
++/* Reset bit 10 is reserved. */
++#define AVALANCHE_VDMA_VT_RESET_BIT 11
++#define AVALANCHE_FSER_RESET_BIT 12
++/* Reset bit 13 to 15 are reserved */
++#define AVALANCHE_HIGH_VLYNQ_RESET_BIT 16
++#define AVALANCHE_LOW_CPMAC_RESET_BIT 17
++#define AVALANCHE_MCDMA_RESET_BIT 18
++#define AVALANCHE_BIST_RESET_BIT 19
++#define AVALANCHE_LOW_VLYNQ_RESET_BIT 20
++#define AVALANCHE_HIGH_CPMAC_RESET_BIT 21
++#define AVALANCHE_MDIO_RESET_BIT 22
++#define AVALANCHE_ADSL_SUB_SYS_DSP_RESET_BIT 23
++/* Reset bit 24 to 25 are reserved */
++#define AVALANCHE_LOW_EPHY_RESET_BIT 26
++/* Reset bit 27 to 31 are reserved */
++
++
++#define AVALANCHE_POWER_MODULE_USBSP 0
++#define AVALANCHE_POWER_MODULE_WDTP 1
++#define AVALANCHE_POWER_MODULE_UT0P 2
++#define AVALANCHE_POWER_MODULE_UT1P 3
++#define AVALANCHE_POWER_MODULE_IICP 4
++#define AVALANCHE_POWER_MODULE_VDMAP 5
++#define AVALANCHE_POWER_MODULE_GPIOP 6
++#define AVALANCHE_POWER_MODULE_VLYNQ1P 7
++#define AVALANCHE_POWER_MODULE_SARP 8
++#define AVALANCHE_POWER_MODULE_ADSLP 9
++#define AVALANCHE_POWER_MODULE_EMIFP 10
++#define AVALANCHE_POWER_MODULE_ADSPP 12
++#define AVALANCHE_POWER_MODULE_RAMP 13
++#define AVALANCHE_POWER_MODULE_ROMP 14
++#define AVALANCHE_POWER_MODULE_DMAP 15
++#define AVALANCHE_POWER_MODULE_BISTP 16
++#define AVALANCHE_POWER_MODULE_TIMER0P 18
++#define AVALANCHE_POWER_MODULE_TIMER1P 19
++#define AVALANCHE_POWER_MODULE_EMAC0P 20
++#define AVALANCHE_POWER_MODULE_EMAC1P 22
++#define AVALANCHE_POWER_MODULE_EPHYP 24
++#define AVALANCHE_POWER_MODULE_VLYNQ0P 27
++
++
++
++
++
++/*
++ * Sangam board vectors
++ */
++
++#define AVALANCHE_VECS (KSEG1ADDR(AVALANCHE_SDRAM_BASE))
++#define AVALANCHE_VECS_KSEG0 (KSEG0ADDR(AVALANCHE_SDRAM_BASE))
++
++/*-----------------------------------------------------------------------------
++ * Sangam's system register.
++ *
++ *---------------------------------------------------------------------------*/
++#define AVALANCHE_DCL_BOOTCR (KSEG1ADDR(0x08611A00))
++#define AVALANCHE_EMIF_SDRAM_CFG (AVALANCHE_EMIF_CONTROL_BASE + 0x8)
++#define AVALANCHE_RST_CTRL_PRCR (KSEG1ADDR(0x08611600))
++#define AVALANCHE_RST_CTRL_SWRCR (KSEG1ADDR(0x08611604))
++#define AVALANCHE_RST_CTRL_RSR (KSEG1ADDR(0x08611600))
++
++#define AVALANCHE_POWER_CTRL_PDCR (KSEG1ADDR(0x08610A00))
++#define AVALANCHE_WAKEUP_CTRL_WKCR (KSEG1ADDR(0x08610A0C))
++
++#define AVALANCHE_GPIO_DATA_IN (AVALANCHE_GPIO_BASE + 0x0)
++#define AVALANCHE_GPIO_DATA_OUT (AVALANCHE_GPIO_BASE + 0x4)
++#define AVALANCHE_GPIO_DIR (AVALANCHE_GPIO_BASE + 0x8)
++#define AVALANCHE_GPIO_ENBL (AVALANCHE_GPIO_BASE + 0xC)
++#define AVALANCHE_CVR (AVALANCHE_GPIO_BASE + 0x14)
++
++/*
++ * Yamon Prom print address.
++ */
++#define AVALANCHE_YAMON_FUNCTION_BASE (KSEG1ADDR(0x10000500))
++#define AVALANCHE_YAMON_PROM_PRINT_COUNT_ADDR (AVALANCHE_YAMON_FUNCTION_BASE + 0x4) /* print_count function */
++#define AVALANCHE_YAMON_PROM_PRINT_ADDR (AVALANCHE_YAMON_FUNCTION_BASE + 0x34)
++
++#define AVALANCHE_BASE_BAUD ( 3686400 / 16 )
++
++#define AVALANCHE_GPIO_PIN_COUNT 32
++#define AVALANCHE_GPIO_OFF_MAP {0xF34FFFC0}
++
++#include "sangam_boards.h"
++
++#endif /*_SANGAM_H_ */
+diff -urN linux.old/include/asm-mips/ar7/sangam_boards.h linux.dev/include/asm-mips/ar7/sangam_boards.h
+--- linux.old/include/asm-mips/ar7/sangam_boards.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/sangam_boards.h 2005-11-10 01:10:46.071588750 +0100
+@@ -0,0 +1,77 @@
++#ifndef _SANGAM_BOARDS_H
++#define _SANGAM_BOARDS_H
++
++// Let us define board specific information here.
++
++
++#if defined(CONFIG_AR7DB)
++
++#define AFECLK_FREQ 35328000
++#define REFCLK_FREQ 25000000
++#define OSC3_FREQ 24000000
++#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000
++#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x55555555
++#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000
++
++#endif
++
++
++#if defined(CONFIG_AR7RD)
++#define AFECLK_FREQ 35328000
++#define REFCLK_FREQ 25000000
++#define OSC3_FREQ 24000000
++#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000
++#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x2
++#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000
++#endif
++
++
++#if defined(CONFIG_AR7WI)
++#define AFECLK_FREQ 35328000
++#define REFCLK_FREQ 25000000
++#define OSC3_FREQ 24000000
++#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000
++#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x2
++#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000
++#endif
++
++
++#if defined(CONFIG_AR7V)
++#define AFECLK_FREQ 35328000
++#define REFCLK_FREQ 25000000
++#define OSC3_FREQ 24000000
++#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000
++#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x2
++#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000
++#endif
++
++
++#if defined(CONFIG_AR7WRD)
++#define AFECLK_FREQ 35328000
++#define REFCLK_FREQ 25000000
++#define OSC3_FREQ 24000000
++#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000
++#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x00010000
++#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000
++#endif
++
++
++#if defined(CONFIG_AR7VWI)
++#define AFECLK_FREQ 35328000
++#define REFCLK_FREQ 25000000
++#define OSC3_FREQ 24000000
++#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000
++#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x00010000
++#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000
++#endif
++
++
++#if defined CONFIG_SEAD2
++#define AVALANCHE_LOW_CPMAC_PHY_MASK 0xAAAAAAAA
++#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x55555555
++#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0
++#include <asm/mips-boards/sead.h>
++#endif
++
++
++#endif
+diff -urN linux.old/include/asm-mips/ar7/tnetd73xx.h linux.dev/include/asm-mips/ar7/tnetd73xx.h
+--- linux.old/include/asm-mips/ar7/tnetd73xx.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/tnetd73xx.h 2005-11-10 01:10:46.075589000 +0100
+@@ -0,0 +1,338 @@
++/******************************************************************************
++ * FILE PURPOSE: TNETD73xx Common Header File
++ ******************************************************************************
++ * FILE NAME: tnetd73xx.h
++ *
++ * DESCRIPTION: shared typedef's, constants and API for TNETD73xx
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++/*
++ *
++ *
++ * These are const, typedef, and api definitions for tnetd73xx.
++ *
++ * NOTES:
++ * 1. This file may be included into both C and Assembly files.
++ * - for .s files, please do #define _ASMLANGUAGE in your ASM file to
++ * avoid C data types (typedefs) below;
++ * - for .c files, you don't have to do anything special.
++ *
++ * 2. This file has a number of sections for each SOC subsystem. When adding
++ * a new constant, find the subsystem you are working on and follow the
++ * name pattern. If you are adding another typedef for your interface, please,
++ * place it with other typedefs and function prototypes.
++ *
++ * 3. Please, DO NOT add any macros or types that are local to a subsystem to avoid
++ * cluttering. Include such items directly into the module's .c file or have a
++ * local .h file to pass data between smaller modules. This file defines only
++ * shared items.
++ */
++
++#ifndef __TNETD73XX_H__
++#define __TNETD73XX_H__
++
++#ifndef _ASMLANGUAGE /* This part not for assembly language */
++
++extern unsigned int tnetd73xx_mips_freq;
++extern unsigned int tnetd73xx_vbus_freq;
++
++#include "tnetd73xx_err.h"
++
++#endif /* _ASMLANGUAGE */
++
++
++/*******************************************************************************************
++* Emerald core specific
++******************************************************************************************** */
++
++#ifdef BIG_ENDIAN
++#elif defined(LITTLE_ENDIAN)
++#else
++#error Need to define endianism
++#endif
++
++#ifndef KSEG_MSK
++#define KSEG_MSK 0xE0000000 /* Most significant 3 bits denote kseg choice */
++#endif
++
++#ifndef KSEG_INV_MASK
++#define KSEG_INV_MASK 0x1FFFFFFF /* Inverted mask for kseg address */
++#endif
++
++#ifndef KSEG0_BASE
++#define KSEG0_BASE 0x80000000
++#endif
++
++#ifndef KSEG1_BASE
++#define KSEG1_BASE 0xA0000000
++#endif
++
++#ifndef KSEG0
++#define KSEG0(addr) (((__u32)(addr) & ~KSEG_MSK) | KSEG0_BASE)
++#endif
++
++#ifndef KSEG1
++#define KSEG1(addr) (((__u32)(addr) & ~KSEG_MSK) | KSEG1_BASE)
++#endif
++
++#ifndef KUSEG
++#define KUSEG(addr) ((__u32)(addr) & ~KSEG_MSK)
++#endif
++
++#ifndef PHYS_ADDR
++#define PHYS_ADDR(addr) ((addr) & KSEG_INV_MASK)
++#endif
++
++#ifndef PHYS_TO_K0
++#define PHYS_TO_K0(addr) (PHYS_ADDR(addr)|KSEG0_BASE)
++#endif
++
++#ifndef PHYS_TO_K1
++#define PHYS_TO_K1(addr) (PHYS_ADDR(addr)|KSEG1_BASE)
++#endif
++
++#ifndef REG8_ADDR
++#define REG8_ADDR(addr) (volatile __u8 *)(PHYS_TO_K1(addr))
++#define REG8_DATA(addr) (*(volatile __u8 *)(PHYS_TO_K1(addr)))
++#define REG8_WRITE(addr, data) REG8_DATA(addr) = data;
++#define REG8_READ(addr, data) data = (__u8) REG8_DATA(addr);
++#endif
++
++#ifndef REG16_ADDR
++#define REG16_ADDR(addr) (volatile __u16 *)(PHYS_TO_K1(addr))
++#define REG16_DATA(addr) (*(volatile __u16 *)(PHYS_TO_K1(addr)))
++#define REG16_WRITE(addr, data) REG16_DATA(addr) = data;
++#define REG16_READ(addr, data) data = (__u16) REG16_DATA(addr);
++#endif
++
++#ifndef REG32_ADDR
++#define REG32_ADDR(addr) (volatile __u32 *)(PHYS_TO_K1(addr))
++#define REG32_DATA(addr) (*(volatile __u32 *)(PHYS_TO_K1(addr)))
++#define REG32_WRITE(addr, data) REG32_DATA(addr) = data;
++#define REG32_READ(addr, data) data = (__u32) REG32_DATA(addr);
++#endif
++
++#ifdef _LINK_KSEG0_ /* Application is linked into KSEG0 space */
++#define VIRT_ADDR(addr) PHYS_TO_K0(PHYS_ADDR(addr))
++#endif
++
++#ifdef _LINK_KSEG1_ /* Application is linked into KSEG1 space */
++#define VIRT_ADDR(addr) PHYS_TO_K1(PHYS_ADDR(addr))
++#endif
++
++#if !defined(_LINK_KSEG0_) && !defined(_LINK_KSEG1_)
++#error You must define _LINK_KSEG0_ or _LINK_KSEG1_ to compile the code.
++#endif
++
++/* TNETD73XX chip definations */
++
++#define FREQ_1MHZ 1000000
++#define TNETD73XX_MIPS_FREQ tnetd73xx_mips_freq /* CPU clock frequency */
++#define TNETD73XX_VBUS_FREQ tnetd73xx_vbus_freq /* originally (TNETD73XX_MIPS_FREQ/2) */
++
++#ifdef AR7SEAD2
++#define TNETD73XX_MIPS_FREQ_DEFAULT 25000000 /* 25 Mhz for sead2 board crystal */
++#else
++#define TNETD73XX_MIPS_FREQ_DEFAULT 125000000 /* 125 Mhz */
++#endif
++#define TNETD73XX_VBUS_FREQ_DEFAULT (TNETD73XX_MIPS_FREQ_DEFAULT / 2) /* Sync mode */
++
++
++
++/* Module base addresses */
++#define TNETD73XX_ADSLSS_BASE PHYS_TO_K1(0x01000000) /* ADSLSS Module */
++#define TNETD73XX_BBIF_CTRL_BASE PHYS_TO_K1(0x02000000) /* BBIF Control */
++#define TNETD73XX_ATMSAR_BASE PHYS_TO_K1(0x03000000) /* ATM SAR */
++#define TNETD73XX_USB_BASE PHYS_TO_K1(0x03400000) /* USB Module */
++#define TNETD73XX_VLYNQ0_BASE PHYS_TO_K1(0x04000000) /* VLYNQ0 Module */
++#define TNETD73xx_EMAC0_BASE PHYS_TO_K1(0x08610000) /* EMAC0 Module*/
++#define TNETD73XX_EMIF_BASE PHYS_TO_K1(0x08610800) /* EMIF Module */
++#define TNETD73XX_GPIO_BASE PHYS_TO_K1(0x08610900) /* GPIO control */
++#define TNETD73XX_CLOCK_CTRL_BASE PHYS_TO_K1(0x08610A00) /* Clock Control */
++#define TNETD73XX_WDTIMER_BASE PHYS_TO_K1(0x08610B00) /* WDTIMER Module */
++#define TNETD73XX_TIMER0_BASE PHYS_TO_K1(0x08610C00) /* TIMER0 Module */
++#define TNETD73XX_TIMER1_BASE PHYS_TO_K1(0x08610D00) /* TIMER1 Module */
++#define TNETD73XX_UARTA_BASE PHYS_TO_K1(0x08610E00) /* UART A */
++#define TNETD73XX_UARTB_BASE PHYS_TO_K1(0x08610F00) /* UART B */
++#define TNETD73XX_I2C_BASE PHYS_TO_K1(0x08611000) /* I2C Module */
++#define TNETD73XX_USB_DMA_BASE PHYS_TO_K1(0x08611200) /* USB Module */
++#define TNETD73XX_MCDMA_BASE PHYS_TO_K1(0x08611400) /* MC-DMA */
++#define TNETD73xx_VDMAVT_BASE PHYS_TO_K1(0x08611500) /* VDMAVT Control */
++#define TNETD73XX_RST_CTRL_BASE PHYS_TO_K1(0x08611600) /* Reset Control */
++#define TNETD73xx_BIST_CTRL_BASE PHYS_TO_K1(0x08611700) /* BIST Control */
++#define TNETD73xx_VLYNQ0_CTRL_BASE PHYS_TO_K1(0x08611800) /* VLYNQ0 Control */
++#define TNETD73XX_DCL_BASE PHYS_TO_K1(0x08611A00) /* Device Configuration Latch */
++#define TNETD73xx_VLYNQ1_CTRL_BASE PHYS_TO_K1(0x08611C00) /* VLYNQ1 Control */
++#define TNETD73xx_MDIO_BASE PHYS_TO_K1(0x08611E00) /* MDIO Control */
++#define TNETD73XX_FSER_BASE PHYS_TO_K1(0x08612000) /* FSER Control */
++#define TNETD73XX_INTC_BASE PHYS_TO_K1(0x08612400) /* Interrupt Controller */
++#define TNETD73xx_EMAC1_BASE PHYS_TO_K1(0x08612800) /* EMAC1 Module*/
++#define TNETD73XX_VLYNQ1_BASE PHYS_TO_K1(0x0C000000) /* VLYNQ1 Module */
++
++/* BBIF Registers */
++#define TNETD73XX_BBIF_ADSLADR (TNETD73XX_BBIF_CTRL_BASE + 0x0)
++
++/* Device Configuration Latch Registers */
++#define TNETD73XX_DCL_BOOTCR (TNETD73XX_DCL_BASE + 0x0)
++#define TNETD73XX_DCL_DPLLSELR (TNETD73XX_DCL_BASE + 0x10)
++#define TNETD73XX_DCL_SPEEDCTLR (TNETD73XX_DCL_BASE + 0x14)
++#define TNETD73XX_DCL_SPEEDPWDR (TNETD73XX_DCL_BASE + 0x18)
++#define TNETD73XX_DCL_SPEEDCAPR (TNETD73XX_DCL_BASE + 0x1C)
++
++/* GPIO Control */
++#define TNETD73XX_GPIODINR (TNETD73XX_GPIO_BASE + 0x0)
++#define TNETD73XX_GPIODOUTR (TNETD73XX_GPIO_BASE + 0x4)
++#define TNETD73XX_GPIOPDIRR (TNETD73XX_GPIO_BASE + 0x8)
++#define TNETD73XX_GPIOENR (TNETD73XX_GPIO_BASE + 0xC)
++#define TNETD73XX_CVR (TNETD73XX_GPIO_BASE + 0x14)
++#define TNETD73XX_DIDR1 (TNETD73XX_GPIO_BASE + 0x18)
++#define TNETD73XX_DIDR2 (TNETD73XX_GPIO_BASE + 0x1C)
++
++/* Reset Control */
++#define TNETD73XX_RST_CTRL_PRCR (TNETD73XX_RST_CTRL_BASE + 0x0)
++#define TNETD73XX_RST_CTRL_SWRCR (TNETD73XX_RST_CTRL_BASE + 0x4)
++#define TNETD73XX_RST_CTRL_RSR (TNETD73XX_RST_CTRL_BASE + 0x8)
++
++/* Power Control */
++#define TNETD73XX_POWER_CTRL_PDCR (TNETD73XX_CLOCK_CTRL_BASE + 0x0)
++#define TNETD73XX_POWER_CTRL_PCLKCR (TNETD73XX_CLOCK_CTRL_BASE + 0x4)
++#define TNETD73XX_POWER_CTRL_PDUCR (TNETD73XX_CLOCK_CTRL_BASE + 0x8)
++#define TNETD73XX_POWER_CTRL_WKCR (TNETD73XX_CLOCK_CTRL_BASE + 0xC)
++
++/* Clock Control */
++#define TNETD73XX_CLK_CTRL_SCLKCR (TNETD73XX_CLOCK_CTRL_BASE + 0x20)
++#define TNETD73XX_CLK_CTRL_SCLKPLLCR (TNETD73XX_CLOCK_CTRL_BASE + 0x30)
++#define TNETD73XX_CLK_CTRL_MCLKCR (TNETD73XX_CLOCK_CTRL_BASE + 0x40)
++#define TNETD73XX_CLK_CTRL_MCLKPLLCR (TNETD73XX_CLOCK_CTRL_BASE + 0x50)
++#define TNETD73XX_CLK_CTRL_UCLKCR (TNETD73XX_CLOCK_CTRL_BASE + 0x60)
++#define TNETD73XX_CLK_CTRL_UCLKPLLCR (TNETD73XX_CLOCK_CTRL_BASE + 0x70)
++#define TNETD73XX_CLK_CTRL_ACLKCR0 (TNETD73XX_CLOCK_CTRL_BASE + 0x80)
++#define TNETD73XX_CLK_CTRL_ACLKPLLCR0 (TNETD73XX_CLOCK_CTRL_BASE + 0x90)
++#define TNETD73XX_CLK_CTRL_ACLKCR1 (TNETD73XX_CLOCK_CTRL_BASE + 0xA0)
++#define TNETD73XX_CLK_CTRL_ACLKPLLCR1 (TNETD73XX_CLOCK_CTRL_BASE + 0xB0)
++
++/* EMIF control */
++#define TNETD73XX_EMIF_SDRAM_CFG ( TNETD73XX_EMIF_BASE + 0x08 )
++
++/* UART */
++#ifdef AR7SEAD2
++#define TNETD73XX_UART_FREQ 3686400
++#else
++#define TNETD73XX_UART_FREQ TNETD73XX_VBUS_FREQ
++#endif
++
++/* Interrupt Controller */
++
++/* Primary interrupts */
++#define TNETD73XX_INTC_UNIFIED_SECONDARY 0 /* Unified secondary interrupt */
++#define TNETD73XX_INTC_EXTERNAL0 1 /* External Interrupt Line 0 */
++#define TNETD73XX_INTC_EXTERNAL1 2 /* External Interrupt Line 1 */
++#define TNETD73XX_INTC_RESERVED3 3 /* Reserved */
++#define TNETD73XX_INTC_RESERVED4 4 /* Reserved */
++#define TNETD73XX_INTC_TIMER0 5 /* TIMER 0 int */
++#define TNETD73XX_INTC_TIMER1 6 /* TIMER 1 int */
++#define TNETD73XX_INTC_UART0 7 /* UART 0 int */
++#define TNETD73XX_INTC_UART1 8 /* UART 1 int */
++#define TNETD73XX_INTC_MCDMA0 9 /* MCDMA 0 int */
++#define TNETD73XX_INTC_MCDMA1 10 /* MCDMA 1 int */
++#define TNETD73XX_INTC_RESERVED11 11 /* Reserved */
++#define TNETD73XX_INTC_RESERVED12 12 /* Reserved */
++#define TNETD73XX_INTC_RESERVED13 13 /* Reserved */
++#define TNETD73XX_INTC_RESERVED14 14 /* Reserved */
++#define TNETD73XX_INTC_ATMSAR 15 /* ATM SAR int */
++#define TNETD73XX_INTC_RESERVED16 16 /* Reserved */
++#define TNETD73XX_INTC_RESERVED17 17 /* Reserved */
++#define TNETD73XX_INTC_RESERVED18 18 /* Reserved */
++#define TNETD73XX_INTC_EMAC0 19 /* EMAC 0 int */
++#define TNETD73XX_INTC_RESERVED20 20 /* Reserved */
++#define TNETD73XX_INTC_VLYNQ0 21 /* VLYNQ 0 int */
++#define TNETD73XX_INTC_CODEC 22 /* CODEC int */
++#define TNETD73XX_INTC_RESERVED23 23 /* Reserved */
++#define TNETD73XX_INTC_USBSLAVE 24 /* USB Slave int */
++#define TNETD73XX_INTC_VLYNQ1 25 /* VLYNQ 1 int */
++#define TNETD73XX_INTC_RESERVED26 26 /* Reserved */
++#define TNETD73XX_INTC_RESERVED27 27 /* Reserved */
++#define TNETD73XX_INTC_ETH_PHY 28 /* Ethernet PHY */
++#define TNETD73XX_INTC_I2C 29 /* I2C int */
++#define TNETD73XX_INTC_MCDMA2 30 /* MCDMA 2 int */
++#define TNETD73XX_INTC_MCDMA3 31 /* MCDMA 3 int */
++#define TNETD73XX_INTC_RESERVED32 32 /* Reserved */
++#define TNETD73XX_INTC_EMAC1 33 /* EMAC 1 int */
++#define TNETD73XX_INTC_RESERVED34 34 /* Reserved */
++#define TNETD73XX_INTC_RESERVED35 35 /* Reserved */
++#define TNETD73XX_INTC_RESERVED36 36 /* Reserved */
++#define TNETD73XX_INTC_VDMAVTRX 37 /* VDMAVTRX */
++#define TNETD73XX_INTC_VDMAVTTX 38 /* VDMAVTTX */
++#define TNETD73XX_INTC_ADSLSS 39 /* ADSLSS */
++
++/* Secondary interrupts */
++#define TNETD73XX_INTC_SEC0 40 /* Secondary */
++#define TNETD73XX_INTC_SEC1 41 /* Secondary */
++#define TNETD73XX_INTC_SEC2 42 /* Secondary */
++#define TNETD73XX_INTC_SEC3 43 /* Secondary */
++#define TNETD73XX_INTC_SEC4 44 /* Secondary */
++#define TNETD73XX_INTC_SEC5 45 /* Secondary */
++#define TNETD73XX_INTC_SEC6 46 /* Secondary */
++#define TNETD73XX_INTC_EMIF 47 /* EMIF */
++#define TNETD73XX_INTC_SEC8 48 /* Secondary */
++#define TNETD73XX_INTC_SEC9 49 /* Secondary */
++#define TNETD73XX_INTC_SEC10 50 /* Secondary */
++#define TNETD73XX_INTC_SEC11 51 /* Secondary */
++#define TNETD73XX_INTC_SEC12 52 /* Secondary */
++#define TNETD73XX_INTC_SEC13 53 /* Secondary */
++#define TNETD73XX_INTC_SEC14 54 /* Secondary */
++#define TNETD73XX_INTC_SEC15 55 /* Secondary */
++#define TNETD73XX_INTC_SEC16 56 /* Secondary */
++#define TNETD73XX_INTC_SEC17 57 /* Secondary */
++#define TNETD73XX_INTC_SEC18 58 /* Secondary */
++#define TNETD73XX_INTC_SEC19 59 /* Secondary */
++#define TNETD73XX_INTC_SEC20 60 /* Secondary */
++#define TNETD73XX_INTC_SEC21 61 /* Secondary */
++#define TNETD73XX_INTC_SEC22 62 /* Secondary */
++#define TNETD73XX_INTC_SEC23 63 /* Secondary */
++#define TNETD73XX_INTC_SEC24 64 /* Secondary */
++#define TNETD73XX_INTC_SEC25 65 /* Secondary */
++#define TNETD73XX_INTC_SEC26 66 /* Secondary */
++#define TNETD73XX_INTC_SEC27 67 /* Secondary */
++#define TNETD73XX_INTC_SEC28 68 /* Secondary */
++#define TNETD73XX_INTC_SEC29 69 /* Secondary */
++#define TNETD73XX_INTC_SEC30 70 /* Secondary */
++#define TNETD73XX_INTC_SEC31 71 /* Secondary */
++
++/* These ugly macros are to access the -1 registers, like config1 */
++#define MFC0_SEL1_OPCODE(dst, src)\
++ .word (0x40000000 | ((dst)<<16) | ((src)<<11) | 1);\
++ nop; \
++ nop; \
++ nop
++
++#define MTC0_SEL1_OPCODE(dst, src)\
++ .word (0x40800000 | ((dst)<<16) | ((src)<<11) | 1);\
++ nop; \
++ nop; \
++ nop
++
++
++/* Below are Jade core specific */
++#define CFG0_4K_IL_MASK 0x00380000
++#define CFG0_4K_IL_SHIFT 19
++#define CFG0_4K_IA_MASK 0x00070000
++#define CFG0_4K_IA_SHIFT 16
++#define CFG0_4K_IS_MASK 0x01c00000
++#define CFG0_4K_IS_SHIFT 22
++
++#define CFG0_4K_DL_MASK 0x00001c00
++#define CFG0_4K_DL_SHIFT 10
++#define CFG0_4K_DA_MASK 0x00000380
++#define CFG0_4K_DA_SHIFT 7
++#define CFG0_4K_DS_MASK 0x0000E000
++#define CFG0_4K_DS_SHIFT 13
++
++
++
++#endif /* __TNETD73XX_H_ */
+diff -urN linux.old/include/asm-mips/ar7/tnetd73xx_err.h linux.dev/include/asm-mips/ar7/tnetd73xx_err.h
+--- linux.old/include/asm-mips/ar7/tnetd73xx_err.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/tnetd73xx_err.h 2005-11-10 01:10:46.075589000 +0100
+@@ -0,0 +1,42 @@
++/******************************************************************************
++ * FILE PURPOSE: TNETD73xx Error Definations Header File
++ ******************************************************************************
++ * FILE NAME: tnetd73xx_err.h
++ *
++ * DESCRIPTION: Error definations for TNETD73XX
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++
++#ifndef __TNETD73XX_ERR_H__
++#define __TNETD73XX_ERR_H__
++
++typedef enum TNETD73XX_ERR_t
++{
++ TNETD73XX_ERR_OK = 0, /* OK or SUCCESS */
++ TNETD73XX_ERR_ERROR = -1, /* Unspecified/Generic ERROR */
++
++ /* Pointers and args */
++ TNETD73XX_ERR_INVARG = -2, /* Invaild argument to the call */
++ TNETD73XX_ERR_NULLPTR = -3, /* NULL pointer */
++ TNETD73XX_ERR_BADPTR = -4, /* Bad (out of mem) pointer */
++
++ /* Memory issues */
++ TNETD73XX_ERR_ALLOC_FAIL = -10, /* allocation failed */
++ TNETD73XX_ERR_FREE_FAIL = -11, /* free failed */
++ TNETD73XX_ERR_MEM_CORRUPT = -12, /* corrupted memory */
++ TNETD73XX_ERR_BUF_LINK = -13, /* buffer linking failed */
++
++ /* Device issues */
++ TNETD73XX_ERR_DEVICE_TIMEOUT = -20, /* device timeout on read/write */
++ TNETD73XX_ERR_DEVICE_MALFUNC = -21, /* device malfunction */
++
++ TNETD73XX_ERR_INVID = -30 /* Invalid ID */
++
++} TNETD73XX_ERR;
++
++#endif /* __TNETD73XX_ERR_H__ */
+diff -urN linux.old/include/asm-mips/ar7/tnetd73xx_misc.h linux.dev/include/asm-mips/ar7/tnetd73xx_misc.h
+--- linux.old/include/asm-mips/ar7/tnetd73xx_misc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/tnetd73xx_misc.h 2005-11-10 01:10:46.075589000 +0100
+@@ -0,0 +1,239 @@
++/******************************************************************************
++ * FILE PURPOSE: TNETD73xx Misc modules API Header
++ ******************************************************************************
++ * FILE NAME: tnetd73xx_misc.h
++ *
++ * DESCRIPTION: Clock Control, Reset Control, Power Management, GPIO
++ * FSER Modules API
++ * As per TNETD73xx specifications
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - Sharath Kumar PSP TII
++ * 14 Feb 03 - Anant Gole PSP TII
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++#ifndef __TNETD73XX_MISC_H__
++#define __TNETD73XX_MISC_H__
++
++/*****************************************************************************
++ * Reset Control Module
++ *****************************************************************************/
++
++typedef enum TNETD73XX_RESET_MODULE_tag
++{
++ RESET_MODULE_UART0 = 0,
++ RESET_MODULE_UART1 = 1,
++ RESET_MODULE_I2C = 2,
++ RESET_MODULE_TIMER0 = 3,
++ RESET_MODULE_TIMER1 = 4,
++ RESET_MODULE_GPIO = 6,
++ RESET_MODULE_ADSLSS = 7,
++ RESET_MODULE_USBS = 8,
++ RESET_MODULE_SAR = 9,
++ RESET_MODULE_VDMA_VT = 11,
++ RESET_MODULE_FSER = 12,
++ RESET_MODULE_VLYNQ1 = 16,
++ RESET_MODULE_EMAC0 = 17,
++ RESET_MODULE_DMA = 18,
++ RESET_MODULE_BIST = 19,
++ RESET_MODULE_VLYNQ0 = 20,
++ RESET_MODULE_EMAC1 = 21,
++ RESET_MODULE_MDIO = 22,
++ RESET_MODULE_ADSLSS_DSP = 23,
++ RESET_MODULE_EPHY = 26
++} TNETD73XX_RESET_MODULE_T;
++
++typedef enum TNETD73XX_RESET_CTRL_tag
++{
++ IN_RESET = 0,
++ OUT_OF_RESET
++} TNETD73XX_RESET_CTRL_T;
++
++typedef enum TNETD73XX_SYS_RST_MODE_tag
++{
++ RESET_SOC_WITH_MEMCTRL = 1, /* SW0 bit in SWRCR register */
++ RESET_SOC_WITHOUT_MEMCTRL = 2 /* SW1 bit in SWRCR register */
++} TNETD73XX_SYS_RST_MODE_T;
++
++typedef enum TNETD73XX_SYS_RESET_STATUS_tag
++{
++ HARDWARE_RESET = 0,
++ SOFTWARE_RESET0, /* Caused by writing 1 to SW0 bit in SWRCR register */
++ WATCHDOG_RESET,
++ SOFTWARE_RESET1 /* Caused by writing 1 to SW1 bit in SWRCR register */
++} TNETD73XX_SYS_RESET_STATUS_T;
++
++void tnetd73xx_reset_ctrl(TNETD73XX_RESET_MODULE_T reset_module,
++ TNETD73XX_RESET_CTRL_T reset_ctrl);
++TNETD73XX_RESET_CTRL_T tnetd73xx_get_reset_status(TNETD73XX_RESET_MODULE_T reset_module);
++void tnetd73xx_sys_reset(TNETD73XX_SYS_RST_MODE_T mode);
++TNETD73XX_SYS_RESET_STATUS_T tnetd73xx_get_sys_last_reset_status(void);
++
++/*****************************************************************************
++ * Power Control Module
++ *****************************************************************************/
++
++typedef enum TNETD73XX_POWER_MODULE_tag
++{
++ POWER_MODULE_USBSP = 0,
++ POWER_MODULE_WDTP = 1,
++ POWER_MODULE_UT0P = 2,
++ POWER_MODULE_UT1P = 3,
++ POWER_MODULE_IICP = 4,
++ POWER_MODULE_VDMAP = 5,
++ POWER_MODULE_GPIOP = 6,
++ POWER_MODULE_VLYNQ1P = 7,
++ POWER_MODULE_SARP = 8,
++ POWER_MODULE_ADSLP = 9,
++ POWER_MODULE_EMIFP = 10,
++ POWER_MODULE_ADSPP = 12,
++ POWER_MODULE_RAMP = 13,
++ POWER_MODULE_ROMP = 14,
++ POWER_MODULE_DMAP = 15,
++ POWER_MODULE_BISTP = 16,
++ POWER_MODULE_TIMER0P = 18,
++ POWER_MODULE_TIMER1P = 19,
++ POWER_MODULE_EMAC0P = 20,
++ POWER_MODULE_EMAC1P = 22,
++ POWER_MODULE_EPHYP = 24,
++ POWER_MODULE_VLYNQ0P = 27,
++} TNETD73XX_POWER_MODULE_T;
++
++typedef enum TNETD73XX_POWER_CTRL_tag
++{
++ POWER_CTRL_POWER_UP = 0,
++ POWER_CTRL_POWER_DOWN
++} TNETD73XX_POWER_CTRL_T;
++
++typedef enum TNETD73XX_SYS_POWER_MODE_tag
++{
++ GLOBAL_POWER_MODE_RUN = 0, /* All system is up */
++ GLOBAL_POWER_MODE_IDLE, /* MIPS is power down, all peripherals working */
++ GLOBAL_POWER_MODE_STANDBY, /* Chip in power down, but clock to ADSKL subsystem is running */
++ GLOBAL_POWER_MODE_POWER_DOWN /* Total chip is powered down */
++} TNETD73XX_SYS_POWER_MODE_T;
++
++void tnetd73xx_power_ctrl(TNETD73XX_POWER_MODULE_T power_module, TNETD73XX_POWER_CTRL_T power_ctrl);
++TNETD73XX_POWER_CTRL_T tnetd73xx_get_pwr_status(TNETD73XX_POWER_MODULE_T power_module);
++void tnetd73xx_set_global_pwr_mode(TNETD73XX_SYS_POWER_MODE_T power_mode);
++TNETD73XX_SYS_POWER_MODE_T tnetd73xx_get_global_pwr_mode(void);
++
++/*****************************************************************************
++ * Wakeup Control
++ *****************************************************************************/
++
++typedef enum TNETD73XX_WAKEUP_INTERRUPT_tag
++{
++ WAKEUP_INT0 = 1,
++ WAKEUP_INT1 = 2,
++ WAKEUP_INT2 = 4,
++ WAKEUP_INT3 = 8
++} TNETD73XX_WAKEUP_INTERRUPT_T;
++
++typedef enum TNETD73XX_WAKEUP_CTRL_tag
++{
++ WAKEUP_DISABLED = 0,
++ WAKEUP_ENABLED
++} TNETD73XX_WAKEUP_CTRL_T;
++
++typedef enum TNETD73XX_WAKEUP_POLARITY_tag
++{
++ WAKEUP_ACTIVE_HIGH = 0,
++ WAKEUP_ACTIVE_LOW
++} TNETD73XX_WAKEUP_POLARITY_T;
++
++void tnetd73xx_wakeup_ctrl(TNETD73XX_WAKEUP_INTERRUPT_T wakeup_int,
++ TNETD73XX_WAKEUP_CTRL_T wakeup_ctrl,
++ TNETD73XX_WAKEUP_POLARITY_T wakeup_polarity);
++
++/*****************************************************************************
++ * FSER Control
++ *****************************************************************************/
++
++typedef enum TNETD73XX_FSER_MODE_tag
++{
++ FSER_I2C = 0,
++ FSER_UART = 1
++} TNETD73XX_FSER_MODE_T;
++
++void tnetd73xx_fser_ctrl(TNETD73XX_FSER_MODE_T fser_mode);
++
++/*****************************************************************************
++ * Clock Control
++ *****************************************************************************/
++
++#define CLK_MHZ(x) ( (x) * 1000000 )
++
++typedef enum TNETD73XX_CLKC_ID_tag
++{
++ CLKC_SYS = 0,
++ CLKC_MIPS,
++ CLKC_USB,
++ CLKC_ADSLSS
++} TNETD73XX_CLKC_ID_T;
++
++void tnetd73xx_clkc_init(__u32 afeclk, __u32 refclk, __u32 xtal3in);
++TNETD73XX_ERR tnetd73xx_clkc_set_freq(TNETD73XX_CLKC_ID_T clk_id, __u32 output_freq);
++__u32 tnetd73xx_clkc_get_freq(TNETD73XX_CLKC_ID_T clk_id);
++
++/*****************************************************************************
++ * GPIO Control
++ *****************************************************************************/
++
++typedef enum TNETD73XX_GPIO_PIN_tag
++{
++ GPIO_UART0_RD = 0,
++ GPIO_UART0_TD = 1,
++ GPIO_UART0_RTS = 2,
++ GPIO_UART0_CTS = 3,
++ GPIO_FSER_CLK = 4,
++ GPIO_FSER_D = 5,
++ GPIO_EXT_AFE_SCLK = 6,
++ GPIO_EXT_AFE_TX_FS = 7,
++ GPIO_EXT_AFE_TXD = 8,
++ GPIO_EXT_AFE_RS_FS = 9,
++ GPIO_EXT_AFE_RXD1 = 10,
++ GPIO_EXT_AFE_RXD0 = 11,
++ GPIO_EXT_AFE_CDIN = 12,
++ GPIO_EXT_AFE_CDOUT = 13,
++ GPIO_EPHY_SPEED100 = 14,
++ GPIO_EPHY_LINKON = 15,
++ GPIO_EPHY_ACTIVITY = 16,
++ GPIO_EPHY_FDUPLEX = 17,
++ GPIO_EINT0 = 18,
++ GPIO_EINT1 = 19,
++ GPIO_MBSP0_TCLK = 20,
++ GPIO_MBSP0_RCLK = 21,
++ GPIO_MBSP0_RD = 22,
++ GPIO_MBSP0_TD = 23,
++ GPIO_MBSP0_RFS = 24,
++ GPIO_MBSP0_TFS = 25,
++ GPIO_MII_DIO = 26,
++ GPIO_MII_DCLK = 27,
++} TNETD73XX_GPIO_PIN_T;
++
++typedef enum TNETD73XX_GPIO_PIN_MODE_tag
++{
++ FUNCTIONAL_PIN = 0,
++ GPIO_PIN = 1
++} TNETD73XX_GPIO_PIN_MODE_T;
++
++typedef enum TNETD73XX_GPIO_PIN_DIRECTION_tag
++{
++ GPIO_OUTPUT_PIN = 0,
++ GPIO_INPUT_PIN = 1
++} TNETD73XX_GPIO_PIN_DIRECTION_T;
++
++void tnetd73xx_gpio_init(void);
++void tnetd73xx_gpio_ctrl(TNETD73XX_GPIO_PIN_T gpio_pin,
++ TNETD73XX_GPIO_PIN_MODE_T pin_mode,
++ TNETD73XX_GPIO_PIN_DIRECTION_T pin_direction);
++void tnetd73xx_gpio_out(TNETD73XX_GPIO_PIN_T gpio_pin, int value);
++int tnetd73xx_gpio_in(TNETD73XX_GPIO_PIN_T gpio_pin);
++
++/* TNETD73XX Revision */
++__u32 tnetd73xx_get_revision(void);
++
++#endif /* __TNETD73XX_MISC_H__ */
+diff -urN linux.old/include/asm-mips/ar7/vlynq.h linux.dev/include/asm-mips/ar7/vlynq.h
+--- linux.old/include/asm-mips/ar7/vlynq.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/vlynq.h 2005-11-10 01:10:46.095590250 +0100
+@@ -0,0 +1,610 @@
++/***************************************************************************
++**+----------------------------------------------------------------------+**
++**| **** |**
++**| **** |**
++**| ******o*** |**
++**| ********_///_**** |**
++**| ***** /_//_/ **** |**
++**| ** ** (__/ **** |**
++**| ********* |**
++**| **** |**
++**| *** |**
++**| |**
++**| Copyright (c) 2003 Texas Instruments Incorporated |**
++**| ALL RIGHTS RESERVED |**
++**| |**
++**| Permission is hereby granted to licensees of Texas Instruments |**
++**| Incorporated (TI) products to use this computer program for the sole |**
++**| purpose of implementing a licensee product based on TI products. |**
++**| No other rights to reproduce, use, or disseminate this computer |**
++**| program, whether in part or in whole, are granted. |**
++**| |**
++**| TI makes no representation or warranties with respect to the |**
++**| performance of this computer program, and specifically disclaims |**
++**| any responsibility for any damages, special or consequential, |**
++**| connected with the use of this program. |**
++**| |**
++**+----------------------------------------------------------------------+**
++***************************************************************************/
++
++/*********************************************************************************
++ * ------------------------------------------------------------------------------
++ * Module : vlynq_hal.h
++ * Description :
++ * This header file provides the set of functions exported by the
++ * VLYNQ HAL. This file is included from the SOC specific VLYNQ driver wrapper.
++ * ------------------------------------------------------------------------------
++ *********************************************************************************/
++
++#ifndef _VLYNQ_HAL_H_
++#define _VLYNQ_HAL_H_
++
++/* Enable/Disable debug feature */
++#undef VLYNQ_DEBUG
++
++#ifdef VLYNQ_DEBUG /* This needs to be OS abstracted - for testing use vxworks/linux calls */
++#define debugPrint(format,args...)
++#else
++#define debugPrint(format,args...)
++#endif
++
++ /* number of VLYNQ memory regions supported */
++#define VLYNQ_MAX_MEMORY_REGIONS 0x04
++
++ /* Max.number of external interrupt inputs supported by VLYNQ module */
++#define VLYNQ_IVR_MAXIVR 0x08
++
++#define VLYNQ_CLK_DIV_MAX 0x08
++#define VLYNQ_CLK_DIV_MIN 0x01
++
++
++/*** the total number of entries allocated for ICB would be
++ * 32(for 32 bits in IntPending register) + VLYNQ_IVR_CHAIN_SLOTS*/
++#define VLYNQ_IVR_CHAIN_SLOTS 10
++
++
++/* Error defines */
++#define VLYNQ_SUCCESS 0
++
++#define VLYNQ_ERRCODE_BASE 0 /* Chosen by system */
++#define VLYNQ_INVALID_ARG -(VLYNQ_ERRCODE_BASE+1)
++#define VLYNQ_INVALID_DRV_STATE -(VLYNQ_ERRCODE_BASE+2)
++#define VLYNQ_INT_CONFIG_ERR -(VLYNQ_ERRCODE_BASE+3)
++#define VLYNQ_LINK_DOWN -(VLYNQ_ERRCODE_BASE+4)
++#define VLYNQ_MEMALLOC_FAIL -(VLYNQ_ERRCODE_BASE+5)
++#define VLYNQ_ISR_NON_EXISTENT -(VLYNQ_ERRCODE_BASE+6)
++#define VLYNQ_INTVEC_MAP_NOT_FOUND -(VLYNQ_ERRCODE_BASE+7)
++
++/* Vlynq Defines and Macros */
++
++#define VLYNQ_NUM_INT_BITS 32 /* 32 bit interrupt staus register */
++
++/* Base address of module */
++#define VLYNQ_BASE (pdev->module_base)
++
++#define VLYNQ_REMOTE_REGS_OFFSET 0x0080
++
++#define VLYNQ_REV_OFFSET 0x0000
++#define VLYNQ_CTRL_OFFSET 0x0004
++#define VLYNQ_STATUS_OFFSET 0x0008
++#define VLYNQ_INT_STAT_OFFSET 0x0010
++#define VLYNQ_INT_PEND_OFFSET 0x0014
++#define VLYNQ_INT_PTR_OFFSET 0x0018
++#define VLYNQ_TXMAP_OFFSET 0x001c
++
++#define VLYNQ_RX0MAP_SIZE_REG_OFFSET 0x0020
++#define VLYNQ_RX0MAP_OFFSET_REG_OFFSET 0x0024
++
++#define VLYNQ_CHIP_VER_OFFSET 0x0040
++#define VLYNQ_IVR_REGS_OFFSET 0x0060
++
++#define VLYNQ_INT_PENDING_REG_PTR 0x14
++#define VLYNQ_R_INT_PENDING_REG_PTR VLYNQ_REMOTE_REGS_OFFSET + 0x14
++
++#define VLYNQ_REV_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_REV_OFFSET))
++#define VLYNQ_CTRL_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_CTRL_OFFSET))
++#define VLYNQ_STATUS_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_STATUS_OFFSET))
++#define VLYNQ_INT_STAT_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_INT_STAT_OFFSET))
++#define VLYNQ_INT_PEND_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_INT_PEND_OFFSET))
++#define VLYNQ_INT_PTR_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_INT_PTR_OFFSET))
++#define VLYNQ_TXMAP_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_TXMAP_OFFSET))
++
++/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/
++#define VLYNQ_RXMAP_SIZE_REG(map) \
++ *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_RX0MAP_SIZE_REG_OFFSET+( (map-1)<<3)))
++
++/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/
++#define VLYNQ_RXMAP_OFFSET_REG(map) \
++ *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_RX0MAP_OFFSET_REG_OFFSET+( (map-1)<<3)))
++
++#define VLYNQ_CHIP_VER_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_CHIP_VER_OFFSET))
++
++/* 0 =< ivr <= 31; currently ivr < VLYNQ_IVR_MAXIVR=8) */
++#define VLYNQ_IVR_OFFSET(ivr) \
++ (VLYNQ_BASE + VLYNQ_IVR_REGS_OFFSET +((((unsigned)(ivr)) & 31) & ~3) )
++
++#define VLYNQ_IVR_03TO00_REG *((volatile unsigned int*) (VLYNQ_IVR_OFFSET(0)) )
++#define VLYNQ_IVR_07TO04_REG *((volatile unsigned int*) (VLYNQ_IVR_OFFSET(4)) )
++/*** Can be extended for 11TO08...31TO28 when all 31 are supported**/
++
++#define VLYNQ_IVR_INTEN(ivr) (((unsigned int)(0x80)) << ((((unsigned)(ivr)) % 4) * 8))
++#define VLYNQ_IVR_INTTYPE(ivr) (((unsigned int)(0x40)) << ((((unsigned)(ivr)) % 4) * 8))
++#define VLYNQ_IVR_INTPOL(ivr) (((unsigned int)(0x20)) << ((((unsigned)(ivr)) % 4) * 8))
++#define VLYNQ_IVR_INTVEC(ivr) (((unsigned int)(0x1F)) << ((((unsigned)(ivr)) % 4) * 8))
++#define VLYNQ_IVR_INTALL(ivr) (((unsigned int)(0xFF)) << ((((unsigned)(ivr)) % 4) * 8))
++
++
++
++/*********************************
++ * Remote VLYNQ register set *
++ *********************************/
++
++#define VLYNQ_R_REV_OFFSET 0x0080
++#define VLYNQ_R_CTRL_OFFSET 0x0084
++#define VLYNQ_R_STATUS_OFFSET 0x0088
++#define VLYNQ_R_INT_STAT_OFFSET 0x0090
++#define VLYNQ_R_INT_PEND_OFFSET 0x0094
++#define VLYNQ_R_INT_PTR_OFFSET 0x0098
++#define VLYNQ_R_TXMAP_OFFSET 0x009c
++
++#define VLYNQ_R_RX0MAP_SIZE_REG_OFFSET 0x00A0
++#define VLYNQ_R_RX0MAP_OFFSET_REG_OFFSET 0x00A4
++
++#define VLYNQ_R_CHIP_VER_OFFSET 0x00C0
++#define VLYNQ_R_IVR_REGS_OFFSET 0x00E0
++
++#define VLYNQ_R_REV_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_REV_OFFSET))
++#define VLYNQ_R_CTRL_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_CTRL_OFFSET))
++#define VLYNQ_R_STATUS_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_STATUS_OFFSET))
++#define VLYNQ_R_INT_STAT_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_INT_STAT_OFFSET))
++#define VLYNQ_R_INT_PEND_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_INT_PEND_OFFSET))
++#define VLYNQ_R_INT_PTR_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_INT_PTR_OFFSET))
++#define VLYNQ_R_TXMAP_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_TXMAP_OFFSET))
++
++/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/
++#define VLYNQ_R_RXMAP_SIZE_REG(map) \
++ *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_RX0MAP_SIZE_REG_OFFSET + ((map-1)<<3)))
++
++/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/
++#define VLYNQ_R_RXMAP_OFFSET_REG(map) \
++ *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_RX0MAP_OFFSET_REG_OFFSET + ((map-1)<<3)))
++
++#define VLYNQ_R_CHIP_VER_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_CHIP_VER_OFFSET)
++
++#define VLYNQ_R_IVR_OFFSET(ivr) \
++ (VLYNQ_BASE + VLYNQ_R_IVR_REGS_OFFSET +((((unsigned)(ivr)) & 31) & ~3))
++
++
++/*** Can be extended for 11TO08...31TO28 when all 31 are supported**/
++#define VLYNQ_R_IVR_03TO00_REG *((volatile unsigned int*) (VLYNQ_R_IVR_OFFSET(0)) )
++#define VLYNQ_R_IVR_07TO04_REG *((volatile unsigned int*) (VLYNQ_R_IVR_OFFSET(4)) )
++
++
++/****End of remote register set definition******/
++
++
++/*** Masks for individual register fields ***/
++
++#define VLYNQ_MODULE_ID_MASK 0xffff0000
++#define VLYNQ_MAJOR_REV_MASK 0x0000ff00
++#define VLYNQ_MINOR_REV_MASK 0x000000ff
++
++
++#define VLYNQ_CTL_ILOOP_MASK 0x00000002
++#define VLYNQ_CTL_INT2CFG_MASK 0x00000080
++#define VLYNQ_CTL_INTVEC_MASK 0x00001f00
++#define VLYNQ_CTL_INTEN_MASK 0x00002000
++#define VLYNQ_CTL_INTLOCAL_MASK 0x00004000
++#define VLYNQ_CTL_CLKDIR_MASK 0x00008000
++#define VLYNQ_CTL_CLKDIV_MASK 0x00070000
++#define VLYNQ_CTL_MODE_MASK 0x00e00000
++
++
++#define VLYNQ_STS_LINK_MASK 0x00000001 /* Link is active */
++#define VLYNQ_STS_MPEND_MASK 0x00000002 /* Pending master requests */
++#define VLYNQ_STS_SPEND_MASK 0x00000004 /* Pending slave requests */
++#define VLYNQ_STS_NFEMPTY0_MASK 0x00000008 /* Master data FIFO not empty */
++#define VLYNQ_STS_NFEMPTY1_MASK 0x00000010 /* Master command FIFO not empty */
++#define VLYNQ_STS_NFEMPTY2_MASK 0x00000020 /* Slave data FIFO not empty */
++#define VLYNQ_STS_NFEMPTY3_MASK 0x00000040 /* Slave command FIFO not empty */
++#define VLYNQ_STS_LERROR_MASK 0x00000080 /* Local error, w/c */
++#define VLYNQ_STS_RERROR_MASK 0x00000100 /* remote error w/c */
++#define VLYNQ_STS_OFLOW_MASK 0x00000200
++#define VLYNQ_STS_IFLOW_MASK 0x00000400
++#define VLYNQ_STS_MODESUP_MASK 0x00E00000 /* Highest mode supported */
++#define VLYNQ_STS_SWIDTH_MASK 0x07000000 /* Used for reading the width of VLYNQ bus */
++#define VLYNQ_STS_DEBUG_MASK 0xE0000000
++
++#define VLYNQ_CTL_INTVEC_SHIFT 0x08
++#define VLYNQ_CTL_INTEN_SHIFT 0x0D
++#define VLYNQ_CTL_INT2CFG_SHIFT 0x07
++#define VLYNQ_CTL_INTLOCAL_SHIFT 0x0E
++
++#define VLYNQ_CTL_INTFIELDS_CLEAR_MASK 0x7F80
++
++#define VLYNQ_CHIPVER_DEVREV_MASK 0xffff0000
++#define VLYNQ_CHIPVER_DEVID_MASK 0x0000ffff
++
++#define VLYNQ_IVR_INTEN_MASK 0x80
++#define VLYNQ_IVR_INTTYPE_MASK 0x40
++#define VLYNQ_IVR_INTPOL_MASK 0x20
++
++
++/**** Helper macros ****/
++
++#define VLYNQ_RESETCB(arg) \
++ if( pdev->reset_cb != NULL) \
++ { \
++ (pdev->reset_cb)(pdev, (arg)); \
++ }
++
++#define VLYNQ_STATUS_FLD_WIDTH(sts) (((sts) & VLYNQ_STS_SWIDTH_MASK) >> 24 )
++#define VLYNQ_CTL_INTVEC(x) (((x) & 31) << 8 )
++
++#define VLYNQ_INRANGE(x,hi,lo) (((x) <= (hi)) && ((x) >= (lo)))
++#define VLYNQ_OUTRANGE(x,hi,lo) (((x) > (hi)) || ((x) < (lo)))
++
++#define VLYNQ_ALIGN4(x) (x)=(x)&(~3)
++
++
++/*************************************
++ * Enums *
++ *************************************/
++
++/* Initialization options define what operations are
++ * undertaken during vlynq module initialization */
++typedef enum
++{
++ /* Init host local memory regions.This allows
++ * local host access remote memory regions */
++ VLYNQ_INIT_LOCAL_MEM_REGIONS = 0x01,
++ /* Init host remote memory regions.This allows
++ * remote device access local memory regions */
++ VLYNQ_INIT_REMOTE_MEM_REGIONS =0x02,
++ /* Init local interrupt config*/
++ VLYNQ_INIT_LOCAL_INTERRUPTS =0x04,
++ /* Init remote interrupt config*/
++ VLYNQ_INIT_REMOTE_INTERRUPTS =0x08,
++ /* Check link during initialization*/
++ VLYNQ_INIT_CHECK_LINK =0x10,
++ /* configure clock during init */
++ VLYNQ_INIT_CONFIG_CLOCK =0x20,
++ /* Clear errors during init */
++ VLYNQ_INIT_CLEAR_ERRORS =0x40,
++ /* All options */
++ VLYNQ_INIT_PERFORM_ALL =0x7F
++}VLYNQ_INIT_OPTIONS;
++
++
++/* VLYNQ_DEV_TYPE identifies local or remote device */
++typedef enum
++{
++ VLYNQ_LOCAL_DVC = 0, /* vlynq local device (SOC's vlynq module) */
++ VLYNQ_REMOTE_DVC = 1 /* vlynq remote device (remote vlynq module) */
++}VLYNQ_DEV_TYPE;
++
++
++/* VLYNQ_CLK_SOURCE identifies the vlynq module clock source */
++typedef enum
++{
++ VLYNQ_CLK_SOURCE_NONE = 0, /* do not initialize clock generator*/
++ VLYNQ_CLK_SOURCE_LOCAL = 1, /* clock is generated by local machine */
++ VLYNQ_CLK_SOURCE_REMOTE = 2 /* clock is generated by remote machine */
++}VLYNQ_CLK_SOURCE;
++
++
++/* VLYNQ_DRV_STATE indicates the current driver state */
++typedef enum
++{
++ VLYNQ_DRV_STATE_UNINIT = 0, /* driver is uninitialized */
++ VLYNQ_DRV_STATE_ININIT = 1, /* VLYNQ is being initialized */
++ VLYNQ_DRV_STATE_RUN = 2, /* VLYNQ is running properly */
++ VLYNQ_DRV_STATE_HOLD = 3, /* driver stopped temporarily */
++ VLYNQ_DRV_STATE_ERROR = 4 /* driver stopped on unrecoverable error */
++}VLYNQ_DRV_STATE;
++
++
++/* VLYNQ_BUS_WIDTH identifies the vlynq module bus width */
++typedef enum
++{
++ VLYNQ_BUS_WIDTH_3 = 3,
++ VLYNQ_BUS_WIDTH_5 = 5,
++ VLYNQ_BUS_WIDTH_7 = 7,
++ VLYNQ_BUS_WIDTH_9 = 9
++}VLYNQ_BUS_WIDTH;
++
++
++/* VLYNQ_LOCAL_INT_CONFIG indicates whether the local vlynq
++ * interrupts are processed by the host or passed on to the
++ * remote device.
++ */
++typedef enum
++{
++ VLYNQ_INT_REMOTE = 0, /* Interrupt packets sent to remote, intlocal=0 */
++ VLYNQ_INT_LOCAL = 1 /* Interrupts are handled locally, intlocal=1 */
++}VLYNQ_LOCAL_INT_CONFIG;
++
++
++/* VLYNQ_REMOTE_INT_CONFIG indicates whether the remote
++ * interrupts are to be handled by the SOC system ISR
++ * or via the vlynq root ISR
++ */
++typedef enum
++{
++ VLYNQ_INT_ROOT_ISR = 0, /* remote ints handled via vlynq root ISR */
++ VLYNQ_INT_SYSTEM_ISR = 1 /* remote ints handled via system ISR */
++}VLYNQ_REMOTE_INT_CONFIG;
++
++
++/* VLYNQ_INTR_POLARITY - vlynq interrupt polarity setting */
++typedef enum
++{
++ VLYNQ_INTR_ACTIVE_HIGH = 0,
++ VLYNQ_INTR_ACTIVE_LOW = 1
++}VLYNQ_INTR_POLARITY;
++
++
++/* VLYNQ_INTR_TYPE - vlynq interrupt type */
++typedef enum
++{
++ VLYNQ_INTR_LEVEL = 0,
++ VLYNQ_INTR_PULSED = 1
++}VLYNQ_INTR_TYPE;
++
++
++/* VLYNQ_RESET_MODE - vlynq reset mode */
++typedef enum
++{
++ VLYNQ_RESET_ASSERT, /* hold device in reset state */
++ VLYNQ_RESET_DEASSERT, /* release device from reset state */
++ VLYNQ_RESET_INITFAIL, /* handle the device in case driver initialization fails */
++ VLYNQ_RESET_LINKESTABLISH, /* handle the device in case driver established link */
++ VLYNQ_RESET_INITFAIL2, /* Driver initialization failed but VLYNQ link exist. */
++ VLYNQ_RESET_INITOK /* Driver initialization finished OK. */
++}VLYNQ_RESET_MODE;
++
++
++
++/*************************************
++ * Typedefs *
++ *************************************/
++
++struct VLYNQ_DEV_t; /*forward declaration*/
++
++/*--------Function Pointers defintions -----------*/
++
++/* prototype for interrupt handler definition */
++typedef void (*VLYNQ_INTR_CNTRL_ISR)(void *arg1,void *arg2,void *arg3);
++
++typedef void
++(*VLYNQ_RESET_REMOTE)(struct VLYNQ_DEV_t *pDev, VLYNQ_RESET_MODE mode);
++
++typedef void
++(*VLYNQ_REPORT_CB)( struct VLYNQ_DEV_t *pDev, /* This VLYNQ */
++ VLYNQ_DEV_TYPE aSrcDvc, /* Event Cause -local/remote? */
++ unsigned int dwStatRegVal); /* Value of the relevant status register */
++
++
++/*-------Structure Definitions------------*/
++
++typedef struct VLYNQ_MEMORY_MAP_t
++{
++ unsigned int Txmap;
++ unsigned int RxOffset[VLYNQ_MAX_MEMORY_REGIONS];
++ unsigned int RxSize[VLYNQ_MAX_MEMORY_REGIONS];
++}VLYNQ_MEMORY_MAP;
++
++
++/**VLYNQ_INTERRUPT_CNTRL - defines the vlynq module interrupt
++ * settings in vlynq Control register */
++typedef struct VLYNQ_INTERRUPT_CNTRL_t
++{
++ /* vlynq interrupts handled by host or remote - maps to
++ * intLocal bit in vlynq control register */
++ VLYNQ_LOCAL_INT_CONFIG intLocal;
++
++ /* remote interrupts handled by vlynq isr or host system
++ * interrupt controller - maps to the int2Cfg in vlynq
++ * control register */
++ VLYNQ_REMOTE_INT_CONFIG intRemote;
++
++ /* bit in pending/set register used for module interrupts*/
++ unsigned int map_vector;
++
++ /* used only if remote interrupts are to be handled by system ISR*/
++ unsigned int intr_ptr;
++
++}VLYNQ_INTERRUPT_CNTRL;
++
++
++/* VLYNQ_INTR_CNTRL_ICB - defines the Interrupt control block which hold
++ * the interrupt dispatch table. The vlynq_root_isr() indexes into this
++ * table to identify the ISR to be invoked
++ */
++typedef struct VLYNQ_INTR_CNTRL_ICB_t
++{
++ VLYNQ_INTR_CNTRL_ISR isr; /* Clear errors during initialization */
++ void *arg1 ; /* Arg 1 for the ISR */
++ void *arg2 ; /* Arg 2 for the ISR */
++ void *arg3 ; /* Arg 3 for the ISR */
++ unsigned int isrCount; /* number of ISR invocations so far */
++ struct VLYNQ_INTR_CNTRL_ICB_t *next;
++}VLYNQ_INTR_CNTRL_ICB;
++
++/* overlay of vlynq register set */
++typedef struct VLYNQ_REG_SET_t
++{
++ unsigned int revision; /*offset : 0x00 */
++ unsigned int control; /* 0x04*/
++ unsigned int status; /* 0x08*/
++ unsigned int pad1; /* 0x0c*/
++ unsigned int intStatus; /*0x10*/
++ unsigned int intPending; /*0x14*/
++ unsigned int intPtr; /*0x18*/
++ unsigned int txMap; /*0x1C*/
++ unsigned int rxSize1; /*0x20*/
++ unsigned int rxOffset1; /*0x24*/
++ unsigned int rxSize2; /*0x28*/
++ unsigned int rxOffset2; /*0x2C*/
++ unsigned int rxSize3; /*0x30*/
++ unsigned int rxOffset3; /*0x34*/
++ unsigned int rxSize4; /*0x38*/
++ unsigned int rxOffset4; /*0x3C*/
++ unsigned int chipVersion; /*0x40*/
++ unsigned int pad2[8];
++ unsigned int ivr30; /*0x60*/
++ unsigned int ivr74; /*0x64*/
++ unsigned int pad3[7];
++}VLYNQ_REG_SET;
++
++
++typedef struct VLYNQ_DEV_t
++{
++ /** module index:1,2,3... used for debugging purposes */
++ unsigned int dev_idx;
++
++ /*VLYNQ module base address */
++ unsigned int module_base;
++
++ /* clock source selection */
++ VLYNQ_CLK_SOURCE clk_source;
++
++ /* Clock Divider.Val=1 to 8. VLYNQ_clk = VBUSCLK/clk_div */
++ unsigned int clk_div;
++
++ /* State of the VLYNQ driver, set to VLYNQ_DRV_STATE_UNINIT, when initializing */
++ VLYNQ_DRV_STATE state;
++
++ /* Valid VLYNQ bus width, filled by driver */
++ VLYNQ_BUS_WIDTH width;
++
++ /* local memory mapping */
++ VLYNQ_MEMORY_MAP local_mem;
++
++ /* remote memory mapping */
++ VLYNQ_MEMORY_MAP remote_mem;
++
++ /* Local module interrupt params */
++ VLYNQ_INTERRUPT_CNTRL local_irq;
++
++ /* remote module interrupt params */
++ VLYNQ_INTERRUPT_CNTRL remote_irq;
++
++ /*** ICB related fields **/
++
++ /* Sizeof of ICB = VLYNQ_NUM_INT_BITS(for 32 bits in IntPending) +
++ * expansion slots for shared interrupts*/
++ VLYNQ_INTR_CNTRL_ICB pIntrCB[VLYNQ_NUM_INT_BITS + VLYNQ_IVR_CHAIN_SLOTS];
++ VLYNQ_INTR_CNTRL_ICB *freelist;
++
++ /* table holding mapping between intVector and the bit position the interrupt
++ * is mapped to(mapVector)*/
++ char vector_map[32];
++
++ /* user callback for vlynq events, NULL if unused */
++ VLYNQ_REPORT_CB report_cb;
++
++ /* user callback for resetting/realeasing remote device */
++ VLYNQ_RESET_REMOTE reset_cb;
++
++ /*** Handles provided for direct access to register set if need be
++ * Must be intialized to point to appropriate address during
++ * vlynq_init */
++ volatile VLYNQ_REG_SET * local;
++ volatile VLYNQ_REG_SET * remote;
++
++ unsigned int intCount; /* number of interrupts generated so far */
++ unsigned int isrCount; /* number of ISR invocations so far */
++}VLYNQ_DEV;
++
++
++typedef struct VLYNQ_ISR_ARGS_t
++{
++ int irq;
++ void * arg;
++ void * regset;
++}VLYNQ_ISR_ARGS;
++
++
++/****************************************
++ * Function Prototypes *
++ * API exported by generic vlynq driver *
++ ****************************************/
++/* Initialization function */
++int vlynq_init( VLYNQ_DEV *pdev, VLYNQ_INIT_OPTIONS options);
++
++/* Check vlynq link */
++unsigned int vlynq_link_check( VLYNQ_DEV * pdev);
++
++/* Set interrupt vector in local or remote device */
++int vlynq_interrupt_vector_set( VLYNQ_DEV *pdev,
++ unsigned int int_vector,
++ unsigned int map_vector,
++ VLYNQ_DEV_TYPE dev,
++ VLYNQ_INTR_POLARITY pol,
++ VLYNQ_INTR_TYPE type);
++
++
++int vlynq_interrupt_vector_cntl( VLYNQ_DEV *pdev,
++ unsigned int int_vector,
++ VLYNQ_DEV_TYPE dev,
++ unsigned int enable);
++
++unsigned int vlynq_interrupt_get_count( VLYNQ_DEV *pdev,
++ unsigned int map_vector);
++
++int vlynq_install_isr( VLYNQ_DEV *pdev,
++ unsigned int map_vector,
++ VLYNQ_INTR_CNTRL_ISR isr,
++ void *arg1, void *arg2, void *arg3);
++
++int vlynq_uninstall_isr( VLYNQ_DEV *pdev,
++ unsigned int map_vector,
++ void *arg1, void *arg2, void *arg3);
++
++
++void vlynq_root_isr(void *arg);
++
++void vlynq_delay(unsigned int clktime);
++
++/* The following functions, provide better granularity in setting
++ * interrupt parameters. (for better support of linux INT Controller)
++ * Note: The interrupt source is identified by "map_vector"- the bit
++ * position in interrupt status register*/
++
++int vlynq_interrupt_vector_map(VLYNQ_DEV * pdev,
++ VLYNQ_DEV_TYPE dev,
++ unsigned int int_vector,
++ unsigned int map_vector);
++
++int vlynq_interrupt_set_polarity(VLYNQ_DEV * pdev,
++ VLYNQ_DEV_TYPE dev,
++ unsigned int map_vector,
++ VLYNQ_INTR_POLARITY pol);
++
++int vlynq_interrupt_get_polarity( VLYNQ_DEV *pdev ,
++ VLYNQ_DEV_TYPE dev_type,
++ unsigned int map_vector);
++
++int vlynq_interrupt_set_type(VLYNQ_DEV * pdev,
++ VLYNQ_DEV_TYPE dev,
++ unsigned int map_vector,
++ VLYNQ_INTR_TYPE type);
++
++int vlynq_interrupt_get_type( VLYNQ_DEV *pdev,
++ VLYNQ_DEV_TYPE dev_type,
++ unsigned int map_vector);
++
++int vlynq_interrupt_enable(VLYNQ_DEV* pdev,
++ VLYNQ_DEV_TYPE dev,
++ unsigned int map_vector);
++
++int vlynq_interrupt_disable(VLYNQ_DEV * pdev,
++ VLYNQ_DEV_TYPE dev,
++ unsigned int map_vector);
++
++
++
++
++
++#endif /* _VLYNQ_HAL_H_ */
+diff -urN linux.old/include/asm-mips/ar7/vlynq_hal.h linux.dev/include/asm-mips/ar7/vlynq_hal.h
+--- linux.old/include/asm-mips/ar7/vlynq_hal.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/vlynq_hal.h 2005-11-10 01:10:46.095590250 +0100
+@@ -0,0 +1,606 @@
++/***************************************************************************
++**+----------------------------------------------------------------------+**
++**| **** |**
++**| **** |**
++**| ******o*** |**
++**| ********_///_**** |**
++**| ***** /_//_/ **** |**
++**| ** ** (__/ **** |**
++**| ********* |**
++**| **** |**
++**| *** |**
++**| |**
++**| Copyright (c) 2003 Texas Instruments Incorporated |**
++**| ALL RIGHTS RESERVED |**
++**| |**
++**| Permission is hereby granted to licensees of Texas Instruments |**
++**| Incorporated (TI) products to use this computer program for the sole |**
++**| purpose of implementing a licensee product based on TI products. |**
++**| No other rights to reproduce, use, or disseminate this computer |**
++**| program, whether in part or in whole, are granted. |**
++**| |**
++**| TI makes no representation or warranties with respect to the |**
++**| performance of this computer program, and specifically disclaims |**
++**| any responsibility for any damages, special or consequential, |**
++**| connected with the use of this program. |**
++**| |**
++**+----------------------------------------------------------------------+**
++***************************************************************************/
++
++/*********************************************************************************
++ * ------------------------------------------------------------------------------
++ * Module : vlynq_hal.h
++ * Description :
++ * This header file provides the set of functions exported by the
++ * VLYNQ HAL. This file is included from the SOC specific VLYNQ driver wrapper.
++ * ------------------------------------------------------------------------------
++ *********************************************************************************/
++
++#ifndef _VLYNQ_HAL_H_
++#define _VLYNQ_HAL_H_
++
++#include <asm/ar7/avalanche_types.h>
++#include <asm/ar7/vlynq_hal_params.h>
++
++#ifndef PRIVATE
++#define PRIVATE static
++#endif
++
++#ifndef GLOBAL
++#define GLOBAL
++#endif
++
++/* Enable/Disable debug feature */
++#undef VLYNQ_DEBUG
++
++#ifdef VLYNQ_DEBUG /* This needs to be OS abstracted - for testing use vxworks/linux calls */
++#define debugPrint(format,args...)
++#else
++#define debugPrint(format,args...)
++#endif
++
++/* Error defines */
++#define VLYNQ_SUCCESS 0
++
++#define VLYNQ_ERRCODE_BASE 0 /* Chosen by system */
++#define VLYNQ_INVALID_ARG -(VLYNQ_ERRCODE_BASE+1)
++#define VLYNQ_INVALID_DRV_STATE -(VLYNQ_ERRCODE_BASE+2)
++#define VLYNQ_INT_CONFIG_ERR -(VLYNQ_ERRCODE_BASE+3)
++#define VLYNQ_LINK_DOWN -(VLYNQ_ERRCODE_BASE+4)
++#define VLYNQ_MEMALLOC_FAIL -(VLYNQ_ERRCODE_BASE+5)
++#define VLYNQ_ISR_NON_EXISTENT -(VLYNQ_ERRCODE_BASE+6)
++#define VLYNQ_INTVEC_MAP_NOT_FOUND -(VLYNQ_ERRCODE_BASE+7)
++
++/* Vlynq Defines and Macros */
++
++#define VLYNQ_NUM_INT_BITS 32 /* 32 bit interrupt staus register */
++
++/* Base address of module */
++#define VLYNQ_BASE (pdev->module_base)
++
++#define VLYNQ_REMOTE_REGS_OFFSET 0x0080
++
++#define VLYNQ_REV_OFFSET 0x0000
++#define VLYNQ_CTRL_OFFSET 0x0004
++#define VLYNQ_STATUS_OFFSET 0x0008
++#define VLYNQ_INT_STAT_OFFSET 0x0010
++#define VLYNQ_INT_PEND_OFFSET 0x0014
++#define VLYNQ_INT_PTR_OFFSET 0x0018
++#define VLYNQ_TXMAP_OFFSET 0x001c
++
++#define VLYNQ_RX0MAP_SIZE_REG_OFFSET 0x0020
++#define VLYNQ_RX0MAP_OFFSET_REG_OFFSET 0x0024
++
++#define VLYNQ_CHIP_VER_OFFSET 0x0040
++#define VLYNQ_IVR_REGS_OFFSET 0x0060
++
++#define VLYNQ_INT_PENDING_REG_PTR 0x14
++#define VLYNQ_R_INT_PENDING_REG_PTR VLYNQ_REMOTE_REGS_OFFSET + 0x14
++
++#define VLYNQ_REV_REG *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_REV_OFFSET))
++#define VLYNQ_CTRL_REG *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_CTRL_OFFSET))
++#define VLYNQ_STATUS_REG *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_STATUS_OFFSET))
++#define VLYNQ_INT_STAT_REG *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_INT_STAT_OFFSET))
++#define VLYNQ_INT_PEND_REG *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_INT_PEND_OFFSET))
++#define VLYNQ_INT_PTR_REG *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_INT_PTR_OFFSET))
++#define VLYNQ_TXMAP_REG *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_TXMAP_OFFSET))
++
++/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/
++#define VLYNQ_RXMAP_SIZE_REG(map) \
++ *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_RX0MAP_SIZE_REG_OFFSET+( (map-1)<<3)))
++
++/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/
++#define VLYNQ_RXMAP_OFFSET_REG(map) \
++ *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_RX0MAP_OFFSET_REG_OFFSET+( (map-1)<<3)))
++
++#define VLYNQ_CHIP_VER_REG *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_CHIP_VER_OFFSET))
++
++/* 0 =< ivr <= 31; currently ivr < VLYNQ_IVR_MAXIVR=8) */
++#define VLYNQ_IVR_OFFSET(ivr) \
++ (VLYNQ_BASE + VLYNQ_IVR_REGS_OFFSET +((((unsigned)(ivr)) & 31) & ~3) )
++
++#define VLYNQ_IVR_03TO00_REG *((volatile UINT32*) (VLYNQ_IVR_OFFSET(0)) )
++#define VLYNQ_IVR_07TO04_REG *((volatile UINT32*) (VLYNQ_IVR_OFFSET(4)) )
++/*** Can be extended for 11TO08...31TO28 when all 31 are supported**/
++
++#define VLYNQ_IVR_INTEN(ivr) (((UINT32)(0x80)) << ((((unsigned)(ivr)) % 4) * 8))
++#define VLYNQ_IVR_INTTYPE(ivr) (((UINT32)(0x40)) << ((((unsigned)(ivr)) % 4) * 8))
++#define VLYNQ_IVR_INTPOL(ivr) (((UINT32)(0x20)) << ((((unsigned)(ivr)) % 4) * 8))
++#define VLYNQ_IVR_INTVEC(ivr) (((UINT32)(0x1F)) << ((((unsigned)(ivr)) % 4) * 8))
++#define VLYNQ_IVR_INTALL(ivr) (((UINT32)(0xFF)) << ((((unsigned)(ivr)) % 4) * 8))
++
++
++
++/*********************************
++ * Remote VLYNQ register set *
++ *********************************/
++
++#define VLYNQ_R_REV_OFFSET 0x0080
++#define VLYNQ_R_CTRL_OFFSET 0x0084
++#define VLYNQ_R_STATUS_OFFSET 0x0088
++#define VLYNQ_R_INT_STAT_OFFSET 0x0090
++#define VLYNQ_R_INT_PEND_OFFSET 0x0094
++#define VLYNQ_R_INT_PTR_OFFSET 0x0098
++#define VLYNQ_R_TXMAP_OFFSET 0x009c
++
++#define VLYNQ_R_RX0MAP_SIZE_REG_OFFSET 0x00A0
++#define VLYNQ_R_RX0MAP_OFFSET_REG_OFFSET 0x00A4
++
++#define VLYNQ_R_CHIP_VER_OFFSET 0x00C0
++#define VLYNQ_R_IVR_REGS_OFFSET 0x00E0
++
++#define VLYNQ_R_REV_REG *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_REV_OFFSET))
++#define VLYNQ_R_CTRL_REG *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_CTRL_OFFSET))
++#define VLYNQ_R_STATUS_REG *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_STATUS_OFFSET))
++#define VLYNQ_R_INT_STAT_REG *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_INT_STAT_OFFSET))
++#define VLYNQ_R_INT_PEND_REG *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_INT_PEND_OFFSET))
++#define VLYNQ_R_INT_PTR_REG *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_INT_PTR_OFFSET))
++#define VLYNQ_R_TXMAP_REG *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_TXMAP_OFFSET))
++
++/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/
++#define VLYNQ_R_RXMAP_SIZE_REG(map) \
++ *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_RX0MAP_SIZE_REG_OFFSET + ((map-1)<<3)))
++
++/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/
++#define VLYNQ_R_RXMAP_OFFSET_REG(map) \
++ *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_RX0MAP_OFFSET_REG_OFFSET + ((map-1)<<3)))
++
++#define VLYNQ_R_CHIP_VER_REG *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_CHIP_VER_OFFSET)
++
++#define VLYNQ_R_IVR_OFFSET(ivr) \
++ (VLYNQ_BASE + VLYNQ_R_IVR_REGS_OFFSET +((((unsigned)(ivr)) & 31) & ~3))
++
++
++/*** Can be extended for 11TO08...31TO28 when all 31 are supported**/
++#define VLYNQ_R_IVR_03TO00_REG *((volatile UINT32*) (VLYNQ_R_IVR_OFFSET(0)) )
++#define VLYNQ_R_IVR_07TO04_REG *((volatile UINT32*) (VLYNQ_R_IVR_OFFSET(4)) )
++
++
++/****End of remote register set definition******/
++
++
++/*** Masks for individual register fields ***/
++
++#define VLYNQ_MODULE_ID_MASK 0xffff0000
++#define VLYNQ_MAJOR_REV_MASK 0x0000ff00
++#define VLYNQ_MINOR_REV_MASK 0x000000ff
++
++
++#define VLYNQ_CTL_ILOOP_MASK 0x00000002
++#define VLYNQ_CTL_INT2CFG_MASK 0x00000080
++#define VLYNQ_CTL_INTVEC_MASK 0x00001f00
++#define VLYNQ_CTL_INTEN_MASK 0x00002000
++#define VLYNQ_CTL_INTLOCAL_MASK 0x00004000
++#define VLYNQ_CTL_CLKDIR_MASK 0x00008000
++#define VLYNQ_CTL_CLKDIV_MASK 0x00070000
++#define VLYNQ_CTL_MODE_MASK 0x00e00000
++
++
++#define VLYNQ_STS_LINK_MASK 0x00000001 /* Link is active */
++#define VLYNQ_STS_MPEND_MASK 0x00000002 /* Pending master requests */
++#define VLYNQ_STS_SPEND_MASK 0x00000004 /* Pending slave requests */
++#define VLYNQ_STS_NFEMPTY0_MASK 0x00000008 /* Master data FIFO not empty */
++#define VLYNQ_STS_NFEMPTY1_MASK 0x00000010 /* Master command FIFO not empty */
++#define VLYNQ_STS_NFEMPTY2_MASK 0x00000020 /* Slave data FIFO not empty */
++#define VLYNQ_STS_NFEMPTY3_MASK 0x00000040 /* Slave command FIFO not empty */
++#define VLYNQ_STS_LERROR_MASK 0x00000080 /* Local error, w/c */
++#define VLYNQ_STS_RERROR_MASK 0x00000100 /* remote error w/c */
++#define VLYNQ_STS_OFLOW_MASK 0x00000200
++#define VLYNQ_STS_IFLOW_MASK 0x00000400
++#define VLYNQ_STS_MODESUP_MASK 0x00E00000 /* Highest mode supported */
++#define VLYNQ_STS_SWIDTH_MASK 0x07000000 /* Used for reading the width of VLYNQ bus */
++#define VLYNQ_STS_DEBUG_MASK 0xE0000000
++
++#define VLYNQ_CTL_INTVEC_SHIFT 0x08
++#define VLYNQ_CTL_INTEN_SHIFT 0x0D
++#define VLYNQ_CTL_INT2CFG_SHIFT 0x07
++#define VLYNQ_CTL_INTLOCAL_SHIFT 0x0E
++
++#define VLYNQ_CTL_INTFIELDS_CLEAR_MASK 0x7F80
++
++#define VLYNQ_CHIPVER_DEVREV_MASK 0xffff0000
++#define VLYNQ_CHIPVER_DEVID_MASK 0x0000ffff
++
++#define VLYNQ_IVR_INTEN_MASK 0x80
++#define VLYNQ_IVR_INTTYPE_MASK 0x40
++#define VLYNQ_IVR_INTPOL_MASK 0x20
++
++
++/**** Helper macros ****/
++
++#define VLYNQ_RESETCB(arg) \
++ if( pdev->reset_cb != NULL) \
++ { \
++ (pdev->reset_cb)(pdev, (arg)); \
++ }
++
++#define VLYNQ_STATUS_FLD_WIDTH(sts) (((sts) & VLYNQ_STS_SWIDTH_MASK) >> 24 )
++#define VLYNQ_CTL_INTVEC(x) (((x) & 31) << 8 )
++
++#define VLYNQ_INRANGE(x,hi,lo) (((x) <= (hi)) && ((x) >= (lo)))
++#define VLYNQ_OUTRANGE(x,hi,lo) (((x) > (hi)) || ((x) < (lo)))
++
++#define VLYNQ_ALIGN4(x) (x)=(x)&(~3)
++
++
++/*************************************
++ * Enums *
++ *************************************/
++
++/* Initialization options define what operations are
++ * undertaken during vlynq module initialization */
++typedef enum
++{
++ /* Init host local memory regions.This allows
++ * local host access remote memory regions */
++ VLYNQ_INIT_LOCAL_MEM_REGIONS = 0x01,
++ /* Init host remote memory regions.This allows
++ * remote device access local memory regions */
++ VLYNQ_INIT_REMOTE_MEM_REGIONS =0x02,
++ /* Init local interrupt config*/
++ VLYNQ_INIT_LOCAL_INTERRUPTS =0x04,
++ /* Init remote interrupt config*/
++ VLYNQ_INIT_REMOTE_INTERRUPTS =0x08,
++ /* Check link during initialization*/
++ VLYNQ_INIT_CHECK_LINK =0x10,
++ /* configure clock during init */
++ VLYNQ_INIT_CONFIG_CLOCK =0x20,
++ /* Clear errors during init */
++ VLYNQ_INIT_CLEAR_ERRORS =0x40,
++ /* All options */
++ VLYNQ_INIT_PERFORM_ALL =0x7F
++}VLYNQ_INIT_OPTIONS;
++
++
++/* VLYNQ_DEV_TYPE identifies local or remote device */
++typedef enum
++{
++ VLYNQ_LOCAL_DVC = 0, /* vlynq local device (SOC's vlynq module) */
++ VLYNQ_REMOTE_DVC = 1 /* vlynq remote device (remote vlynq module) */
++}VLYNQ_DEV_TYPE;
++
++
++/* VLYNQ_CLK_SOURCE identifies the vlynq module clock source */
++typedef enum
++{
++ VLYNQ_CLK_SOURCE_NONE = 0, /* do not initialize clock generator*/
++ VLYNQ_CLK_SOURCE_LOCAL = 1, /* clock is generated by local machine */
++ VLYNQ_CLK_SOURCE_REMOTE = 2 /* clock is generated by remote machine */
++}VLYNQ_CLK_SOURCE;
++
++
++/* VLYNQ_DRV_STATE indicates the current driver state */
++typedef enum
++{
++ VLYNQ_DRV_STATE_UNINIT = 0, /* driver is uninitialized */
++ VLYNQ_DRV_STATE_ININIT = 1, /* VLYNQ is being initialized */
++ VLYNQ_DRV_STATE_RUN = 2, /* VLYNQ is running properly */
++ VLYNQ_DRV_STATE_HOLD = 3, /* driver stopped temporarily */
++ VLYNQ_DRV_STATE_ERROR = 4 /* driver stopped on unrecoverable error */
++}VLYNQ_DRV_STATE;
++
++
++/* VLYNQ_BUS_WIDTH identifies the vlynq module bus width */
++typedef enum
++{
++ VLYNQ_BUS_WIDTH_3 = 3,
++ VLYNQ_BUS_WIDTH_5 = 5,
++ VLYNQ_BUS_WIDTH_7 = 7,
++ VLYNQ_BUS_WIDTH_9 = 9
++}VLYNQ_BUS_WIDTH;
++
++
++/* VLYNQ_LOCAL_INT_CONFIG indicates whether the local vlynq
++ * interrupts are processed by the host or passed on to the
++ * remote device.
++ */
++typedef enum
++{
++ VLYNQ_INT_REMOTE = 0, /* Interrupt packets sent to remote, intlocal=0 */
++ VLYNQ_INT_LOCAL = 1 /* Interrupts are handled locally, intlocal=1 */
++}VLYNQ_LOCAL_INT_CONFIG;
++
++
++/* VLYNQ_REMOTE_INT_CONFIG indicates whether the remote
++ * interrupts are to be handled by the SOC system ISR
++ * or via the vlynq root ISR
++ */
++typedef enum
++{
++ VLYNQ_INT_ROOT_ISR = 0, /* remote ints handled via vlynq root ISR */
++ VLYNQ_INT_SYSTEM_ISR = 1 /* remote ints handled via system ISR */
++}VLYNQ_REMOTE_INT_CONFIG;
++
++
++/* VLYNQ_INTR_POLARITY - vlynq interrupt polarity setting */
++typedef enum
++{
++ VLYNQ_INTR_ACTIVE_HIGH = 0,
++ VLYNQ_INTR_ACTIVE_LOW = 1
++}VLYNQ_INTR_POLARITY;
++
++
++/* VLYNQ_INTR_TYPE - vlynq interrupt type */
++typedef enum
++{
++ VLYNQ_INTR_LEVEL = 0,
++ VLYNQ_INTR_PULSED = 1
++}VLYNQ_INTR_TYPE;
++
++
++/* VLYNQ_RESET_MODE - vlynq reset mode */
++typedef enum
++{
++ VLYNQ_RESET_ASSERT, /* hold device in reset state */
++ VLYNQ_RESET_DEASSERT, /* release device from reset state */
++ VLYNQ_RESET_INITFAIL, /* handle the device in case driver initialization fails */
++ VLYNQ_RESET_LINKESTABLISH, /* handle the device in case driver established link */
++ VLYNQ_RESET_INITFAIL2, /* Driver initialization failed but VLYNQ link exist. */
++ VLYNQ_RESET_INITOK /* Driver initialization finished OK. */
++}VLYNQ_RESET_MODE;
++
++
++
++/*************************************
++ * Typedefs *
++ *************************************/
++
++struct VLYNQ_DEV_t; /*forward declaration*/
++
++/*--------Function Pointers defintions -----------*/
++
++/* prototype for interrupt handler definition */
++typedef void (*VLYNQ_INTR_CNTRL_ISR)(void *arg1,void *arg2,void *arg3);
++
++typedef void
++(*VLYNQ_RESET_REMOTE)(struct VLYNQ_DEV_t *pDev, VLYNQ_RESET_MODE mode);
++
++typedef void
++(*VLYNQ_REPORT_CB)( struct VLYNQ_DEV_t *pDev, /* This VLYNQ */
++ VLYNQ_DEV_TYPE aSrcDvc, /* Event Cause -local/remote? */
++ UINT32 dwStatRegVal); /* Value of the relevant status register */
++
++
++/*-------Structure Definitions------------*/
++
++typedef struct VLYNQ_MEMORY_MAP_t
++{
++ UINT32 Txmap;
++ UINT32 RxOffset[VLYNQ_MAX_MEMORY_REGIONS];
++ UINT32 RxSize[VLYNQ_MAX_MEMORY_REGIONS];
++}VLYNQ_MEMORY_MAP;
++
++
++/**VLYNQ_INTERRUPT_CNTRL - defines the vlynq module interrupt
++ * settings in vlynq Control register */
++typedef struct VLYNQ_INTERRUPT_CNTRL_t
++{
++ /* vlynq interrupts handled by host or remote - maps to
++ * intLocal bit in vlynq control register */
++ VLYNQ_LOCAL_INT_CONFIG intLocal;
++
++ /* remote interrupts handled by vlynq isr or host system
++ * interrupt controller - maps to the int2Cfg in vlynq
++ * control register */
++ VLYNQ_REMOTE_INT_CONFIG intRemote;
++
++ /* bit in pending/set register used for module interrupts*/
++ UINT32 map_vector;
++
++ /* used only if remote interrupts are to be handled by system ISR*/
++ UINT32 intr_ptr;
++
++}VLYNQ_INTERRUPT_CNTRL;
++
++
++/* VLYNQ_INTR_CNTRL_ICB - defines the Interrupt control block which hold
++ * the interrupt dispatch table. The vlynq_root_isr() indexes into this
++ * table to identify the ISR to be invoked
++ */
++typedef struct VLYNQ_INTR_CNTRL_ICB_t
++{
++ VLYNQ_INTR_CNTRL_ISR isr; /* Clear errors during initialization */
++ void *arg1 ; /* Arg 1 for the ISR */
++ void *arg2 ; /* Arg 2 for the ISR */
++ void *arg3 ; /* Arg 3 for the ISR */
++ UINT32 isrCount; /* number of ISR invocations so far */
++ struct VLYNQ_INTR_CNTRL_ICB_t *next;
++}VLYNQ_INTR_CNTRL_ICB;
++
++/* overlay of vlynq register set */
++typedef struct VLYNQ_REG_SET_t
++{
++ UINT32 revision; /*offset : 0x00 */
++ UINT32 control; /* 0x04*/
++ UINT32 status; /* 0x08*/
++ UINT32 pad1; /* 0x0c*/
++ UINT32 intStatus; /*0x10*/
++ UINT32 intPending; /*0x14*/
++ UINT32 intPtr; /*0x18*/
++ UINT32 txMap; /*0x1C*/
++ UINT32 rxSize1; /*0x20*/
++ UINT32 rxOffset1; /*0x24*/
++ UINT32 rxSize2; /*0x28*/
++ UINT32 rxOffset2; /*0x2C*/
++ UINT32 rxSize3; /*0x30*/
++ UINT32 rxOffset3; /*0x34*/
++ UINT32 rxSize4; /*0x38*/
++ UINT32 rxOffset4; /*0x3C*/
++ UINT32 chipVersion; /*0x40*/
++ UINT32 pad2[8];
++ UINT32 ivr30; /*0x60*/
++ UINT32 ivr74; /*0x64*/
++ UINT32 pad3[7];
++}VLYNQ_REG_SET;
++
++
++typedef struct VLYNQ_DEV_t
++{
++ /** module index:1,2,3... used for debugging purposes */
++ UINT32 dev_idx;
++
++ /*VLYNQ module base address */
++ UINT32 module_base;
++
++ /* clock source selection */
++ VLYNQ_CLK_SOURCE clk_source;
++
++ /* Clock Divider.Val=1 to 8. VLYNQ_clk = VBUSCLK/clk_div */
++ UINT32 clk_div;
++
++ /* State of the VLYNQ driver, set to VLYNQ_DRV_STATE_UNINIT, when initializing */
++ VLYNQ_DRV_STATE state;
++
++ /* Valid VLYNQ bus width, filled by driver */
++ VLYNQ_BUS_WIDTH width;
++
++ /* local memory mapping */
++ VLYNQ_MEMORY_MAP local_mem;
++
++ /* remote memory mapping */
++ VLYNQ_MEMORY_MAP remote_mem;
++
++ /* Local module interrupt params */
++ VLYNQ_INTERRUPT_CNTRL local_irq;
++
++ /* remote module interrupt params */
++ VLYNQ_INTERRUPT_CNTRL remote_irq;
++
++ /*** ICB related fields **/
++
++ /* Sizeof of ICB = VLYNQ_NUM_INT_BITS(for 32 bits in IntPending) +
++ * expansion slots for shared interrupts*/
++ VLYNQ_INTR_CNTRL_ICB pIntrCB[VLYNQ_NUM_INT_BITS + VLYNQ_IVR_CHAIN_SLOTS];
++ VLYNQ_INTR_CNTRL_ICB *freelist;
++
++ /* table holding mapping between intVector and the bit position the interrupt
++ * is mapped to(mapVector)*/
++ INT8 vector_map[32];
++
++ /* user callback for vlynq events, NULL if unused */
++ VLYNQ_REPORT_CB report_cb;
++
++ /* user callback for resetting/realeasing remote device */
++ VLYNQ_RESET_REMOTE reset_cb;
++
++ /*** Handles provided for direct access to register set if need be
++ * Must be intialized to point to appropriate address during
++ * vlynq_init */
++ volatile VLYNQ_REG_SET * local;
++ volatile VLYNQ_REG_SET * remote;
++
++ UINT32 intCount; /* number of interrupts generated so far */
++ UINT32 isrCount; /* number of ISR invocations so far */
++}VLYNQ_DEV;
++
++
++typedef struct VLYNQ_ISR_ARGS_t
++{
++ int irq;
++ void * arg;
++ void * regset;
++}VLYNQ_ISR_ARGS;
++
++
++/****************************************
++ * Function Prototypes *
++ * API exported by generic vlynq driver *
++ ****************************************/
++/* Initialization function */
++GLOBAL INT32 vlynq_init( VLYNQ_DEV *pdev, VLYNQ_INIT_OPTIONS options);
++
++/* Check vlynq link */
++GLOBAL UINT32 vlynq_link_check( VLYNQ_DEV * pdev);
++
++/* Set interrupt vector in local or remote device */
++GLOBAL INT32 vlynq_interrupt_vector_set( VLYNQ_DEV *pdev,
++ UINT32 int_vector,
++ UINT32 map_vector,
++ VLYNQ_DEV_TYPE dev,
++ VLYNQ_INTR_POLARITY pol,
++ VLYNQ_INTR_TYPE type);
++
++
++GLOBAL INT32 vlynq_interrupt_vector_cntl( VLYNQ_DEV *pdev,
++ UINT32 int_vector,
++ VLYNQ_DEV_TYPE dev,
++ UINT32 enable);
++
++GLOBAL UINT32 vlynq_interrupt_get_count( VLYNQ_DEV *pdev,
++ UINT32 map_vector);
++
++GLOBAL INT32 vlynq_install_isr( VLYNQ_DEV *pdev,
++ UINT32 map_vector,
++ VLYNQ_INTR_CNTRL_ISR isr,
++ void *arg1, void *arg2, void *arg3);
++
++GLOBAL INT32 vlynq_uninstall_isr( VLYNQ_DEV *pdev,
++ UINT32 map_vector,
++ void *arg1, void *arg2, void *arg3);
++
++
++GLOBAL void vlynq_root_isr(void *arg);
++
++GLOBAL void vlynq_delay(UINT32 clktime);
++
++/* The following functions, provide better granularity in setting
++ * interrupt parameters. (for better support of linux INT Controller)
++ * Note: The interrupt source is identified by "map_vector"- the bit
++ * position in interrupt status register*/
++
++GLOBAL INT32 vlynq_interrupt_vector_map(VLYNQ_DEV * pdev,
++ VLYNQ_DEV_TYPE dev,
++ UINT32 int_vector,
++ UINT32 map_vector);
++
++GLOBAL INT32 vlynq_interrupt_set_polarity(VLYNQ_DEV * pdev,
++ VLYNQ_DEV_TYPE dev,
++ UINT32 map_vector,
++ VLYNQ_INTR_POLARITY pol);
++
++GLOBAL INT32 vlynq_interrupt_get_polarity( VLYNQ_DEV *pdev ,
++ VLYNQ_DEV_TYPE dev_type,
++ UINT32 map_vector);
++
++GLOBAL INT32 vlynq_interrupt_set_type(VLYNQ_DEV * pdev,
++ VLYNQ_DEV_TYPE dev,
++ UINT32 map_vector,
++ VLYNQ_INTR_TYPE type);
++
++GLOBAL INT32 vlynq_interrupt_get_type( VLYNQ_DEV *pdev,
++ VLYNQ_DEV_TYPE dev_type,
++ UINT32 map_vector);
++
++GLOBAL INT32 vlynq_interrupt_enable(VLYNQ_DEV* pdev,
++ VLYNQ_DEV_TYPE dev,
++ UINT32 map_vector);
++
++GLOBAL INT32 vlynq_interrupt_disable(VLYNQ_DEV * pdev,
++ VLYNQ_DEV_TYPE dev,
++ UINT32 map_vector);
++
++
++
++
++
++#endif /* _VLYNQ_HAL_H_ */
+diff -urN linux.old/include/asm-mips/ar7/vlynq_hal_params.h linux.dev/include/asm-mips/ar7/vlynq_hal_params.h
+--- linux.old/include/asm-mips/ar7/vlynq_hal_params.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/vlynq_hal_params.h 2005-11-10 01:10:46.095590250 +0100
+@@ -0,0 +1,50 @@
++/***************************************************************************
++**+----------------------------------------------------------------------+**
++**| **** |**
++**| **** |**
++**| ******o*** |**
++**| ********_///_**** |**
++**| ***** /_//_/ **** |**
++**| ** ** (__/ **** |**
++**| ********* |**
++**| **** |**
++**| *** |**
++**| |**
++**| Copyright (c) 2003 Texas Instruments Incorporated |**
++**| ALL RIGHTS RESERVED |**
++**| |**
++**| Permission is hereby granted to licensees of Texas Instruments |**
++**| Incorporated (TI) products to use this computer program for the sole |**
++**| purpose of implementing a licensee product based on TI products. |**
++**| No other rights to reproduce, use, or disseminate this computer |**
++**| program, whether in part or in whole, are granted. |**
++**| |**
++**| TI makes no representation or warranties with respect to the |**
++**| performance of this computer program, and specifically disclaims |**
++**| any responsibility for any damages, special or consequential, |**
++**| connected with the use of this program. |**
++**| |**
++**+----------------------------------------------------------------------+**
++***************************************************************************/
++
++/* This file defines Vlynq module parameters*/
++
++#ifndef _VLYNQ_HAL_PARAMS_H
++#define _VLYNQ_HAL_PARAMS_H
++
++ /* number of VLYNQ memory regions supported */
++#define VLYNQ_MAX_MEMORY_REGIONS 0x04
++
++ /* Max.number of external interrupt inputs supported by VLYNQ module */
++#define VLYNQ_IVR_MAXIVR 0x08
++
++#define VLYNQ_CLK_DIV_MAX 0x08
++#define VLYNQ_CLK_DIV_MIN 0x01
++
++
++/*** the total number of entries allocated for ICB would be
++ * 32(for 32 bits in IntPending register) + VLYNQ_IVR_CHAIN_SLOTS*/
++#define VLYNQ_IVR_CHAIN_SLOTS 10
++
++
++#endif /* _VLYNQ_HAL_PARAMS_H */
+diff -urN linux.old/include/asm-mips/io.h linux.dev/include/asm-mips/io.h
+--- linux.old/include/asm-mips/io.h 2003-08-25 13:44:43.000000000 +0200
++++ linux.dev/include/asm-mips/io.h 2005-11-10 01:14:16.400733500 +0100
+@@ -61,9 +61,9 @@
+ * Change "struct page" to physical address.
+ */
+ #ifdef CONFIG_64BIT_PHYS_ADDR
+-#define page_to_phys(page) ((u64)(page - mem_map) << PAGE_SHIFT)
++#define page_to_phys(page) (((u64)(page - mem_map) << PAGE_SHIFT) + PHYS_OFFSET)
+ #else
+-#define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT)
++#define page_to_phys(page) (((page - mem_map) << PAGE_SHIFT) + PHYS_OFFSET)
+ #endif
+
+ #define IO_SPACE_LIMIT 0xffff
+diff -urN linux.old/include/asm-mips/irq.h linux.dev/include/asm-mips/irq.h
+--- linux.old/include/asm-mips/irq.h 2003-08-25 13:44:43.000000000 +0200
++++ linux.dev/include/asm-mips/irq.h 2005-11-10 01:12:43.950955750 +0100
+@@ -14,7 +14,20 @@
+ #include <linux/config.h>
+ #include <linux/linkage.h>
+
++#ifdef CONFIG_AR7
++/* MIPS has 8 irqs
++ * AR7 has 40 primary and 32 secondary irqs
++ * vlynq0 has 32 irqs
++ * vlynq1 has 32 irqs
++ */
++#ifdef CONFIG_AR7_VLYNQ
++#define NR_IRQS (80 + 32 * CONFIG_AR7_VLYNQ_PORTS)
++#else
++#define NR_IRQS 80
++#endif
++#else
+ #define NR_IRQS 128 /* Largest number of ints of all machines. */
++#endif
+
+ #ifdef CONFIG_I8259
+ static inline int irq_cannonicalize(int irq)
+diff -urN linux.old/include/asm-mips/mips-boards/prom.h linux.dev/include/asm-mips/mips-boards/prom.h
+--- linux.old/include/asm-mips/mips-boards/prom.h 2001-09-09 19:43:02.000000000 +0200
++++ linux.dev/include/asm-mips/mips-boards/prom.h 2005-11-10 01:14:16.436735750 +0100
+@@ -33,7 +33,7 @@
+ extern void prom_init_cmdline(void);
+ extern void prom_meminit(void);
+ extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem);
+-extern void prom_free_prom_memory (void);
++extern unsigned long prom_free_prom_memory (void);
+ extern void mips_display_message(const char *str);
+ extern void mips_display_word(unsigned int num);
+ extern int get_ethernet_addr(char *ethernet_addr);
+diff -urN linux.old/include/asm-mips/page.h linux.dev/include/asm-mips/page.h
+--- linux.old/include/asm-mips/page.h 2004-02-18 14:36:32.000000000 +0100
++++ linux.dev/include/asm-mips/page.h 2005-11-10 01:14:16.436735750 +0100
+@@ -12,6 +12,7 @@
+
+ #include <linux/config.h>
+ #include <asm/break.h>
++#include <asm/addrspace.h>
+
+ #ifdef __KERNEL__
+
+@@ -129,7 +130,7 @@
+
+ #define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
+ #define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
+-#define virt_to_page(kaddr) (mem_map + (__pa(kaddr) >> PAGE_SHIFT))
++#define virt_to_page(kaddr) (mem_map + ((__pa(kaddr)-PHYS_OFFSET) >> PAGE_SHIFT))
+ #define VALID_PAGE(page) ((page - mem_map) < max_mapnr)
+
+ #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
+diff -urN linux.old/include/asm-mips/pgtable-32.h linux.dev/include/asm-mips/pgtable-32.h
+--- linux.old/include/asm-mips/pgtable-32.h 2004-02-18 14:36:32.000000000 +0100
++++ linux.dev/include/asm-mips/pgtable-32.h 2005-11-10 01:14:16.436735750 +0100
+@@ -108,7 +108,7 @@
+ * and a page entry and page directory to the page they refer to.
+ */
+
+-#ifdef CONFIG_CPU_VR41XX
++#if defined(CONFIG_CPU_VR41XX)
+ #define mk_pte(page, pgprot) \
+ ({ \
+ pte_t __pte; \
+@@ -123,13 +123,14 @@
+ ({ \
+ pte_t __pte; \
+ \
+- pte_val(__pte) = ((phys_t)(page - mem_map) << PAGE_SHIFT) | \
+- pgprot_val(pgprot); \
++ pte_val(__pte) = (((phys_t)(page - mem_map) << PAGE_SHIFT) + \
++ PHYS_OFFSET) | pgprot_val(pgprot); \
+ \
+ __pte; \
+ })
+ #endif
+
++
+ static inline pte_t mk_pte_phys(phys_t physpage, pgprot_t pgprot)
+ {
+ #ifdef CONFIG_CPU_VR41XX
+@@ -175,12 +176,12 @@
+ set_pte(ptep, __pte(0));
+ }
+
+-#ifdef CONFIG_CPU_VR41XX
++#if defined(CONFIG_CPU_VR41XX)
+ #define pte_page(x) (mem_map+((unsigned long)(((x).pte_low >> (PAGE_SHIFT+2)))))
+ #define __mk_pte(page_nr,pgprot) __pte(((page_nr) << (PAGE_SHIFT+2)) | pgprot_val(pgprot))
+ #else
+-#define pte_page(x) (mem_map+((unsigned long)(((x).pte_low >> PAGE_SHIFT))))
+-#define __mk_pte(page_nr,pgprot) __pte(((page_nr) << PAGE_SHIFT) | pgprot_val(pgprot))
++#define pte_page(x) (mem_map+((unsigned long)((((x).pte_low-PHYS_OFFSET) >> PAGE_SHIFT))))
++#define __mk_pte(page_nr,pgprot) __pte((((page_nr) << PAGE_SHIFT)+PHYS_OFFSET)|pgprot_val(pgprot))
+ #endif
+
+ #endif
+diff -urN linux.old/include/asm-mips/serial.h linux.dev/include/asm-mips/serial.h
+--- linux.old/include/asm-mips/serial.h 2005-01-19 15:10:12.000000000 +0100
++++ linux.dev/include/asm-mips/serial.h 2005-11-10 01:14:16.436735750 +0100
+@@ -65,6 +65,16 @@
+
+ #define C_P(card,port) (((card)<<6|(port)<<3) + 1)
+
++#ifdef CONFIG_AR7
++#include <asm/ar7/ar7.h>
++#include <asm/ar7/avalanche_intc.h>
++#define AR7_SERIAL_PORT_DEFNS \
++ { 0, AR7_BASE_BAUD, AR7_UART0_REGS_BASE, LNXINTNUM(AVALANCHE_UART0_INT), STD_COM_FLAGS }, \
++ { 0, AR7_BASE_BAUD, AR7_UART1_REGS_BASE, LNXINTNUM(AVALANCHE_UART1_INT), STD_COM_FLAGS },
++#else
++#define AR7_SERIAL_PORT_DEFNS
++#endif
++
+ #ifdef CONFIG_MIPS_JAZZ
+ #define _JAZZ_SERIAL_INIT(int, base) \
+ { .baud_base = JAZZ_BASE_BAUD, .irq = int, .flags = STD_COM_FLAGS, \
+@@ -468,6 +478,7 @@
+ #endif
+
+ #define SERIAL_PORT_DFNS \
++ AR7_SERIAL_PORT_DEFNS \
+ ATLAS_SERIAL_PORT_DEFNS \
+ AU1000_SERIAL_PORT_DEFNS \
+ COBALT_SERIAL_PORT_DEFNS \
diff --git a/target/linux/ar7-2.4/patches/001-flash_map.patch b/target/linux/ar7-2.4/patches/001-flash_map.patch
new file mode 100644
index 0000000000..0b58439c8b
--- /dev/null
+++ b/target/linux/ar7-2.4/patches/001-flash_map.patch
@@ -0,0 +1,307 @@
+diff -urN linux.old/drivers/mtd/maps/ar7-flash.c linux.dev/drivers/mtd/maps/ar7-flash.c
+--- linux.old/drivers/mtd/maps/ar7-flash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/mtd/maps/ar7-flash.c 2005-07-22 04:35:26.624453992 +0200
+@@ -0,0 +1,267 @@
++/*
++ * $Id$
++ *
++ * Normal mappings of chips in physical memory
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <asm/io.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/config.h>
++#include <linux/mtd/partitions.h>
++#include <linux/squashfs_fs.h>
++
++#define WINDOW_ADDR CONFIG_MTD_AR7_START
++#define WINDOW_SIZE CONFIG_MTD_AR7_LEN
++#define BUSWIDTH CONFIG_MTD_AR7_BUSWIDTH
++
++#include <asm/mips-boards/prom.h>
++extern char *prom_getenv(char *name);
++
++static int create_mtd_partitions(void);
++static void __exit ar7_mtd_cleanup(void);
++
++#define MAX_NUM_PARTITIONS 5
++static struct mtd_partition ar7_partinfo[MAX_NUM_PARTITIONS];
++
++static struct mtd_info *ar7_mtd_info;
++
++__u8 ar7_read8(struct map_info *map, unsigned long ofs)
++{
++ return __raw_readb(map->map_priv_1 + ofs);
++}
++
++__u16 ar7_read16(struct map_info *map, unsigned long ofs)
++{
++ return __raw_readw(map->map_priv_1 + ofs);
++}
++
++__u32 ar7_read32(struct map_info *map, unsigned long ofs)
++{
++ return __raw_readl(map->map_priv_1 + ofs);
++}
++
++void ar7_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
++{
++ memcpy_fromio(to, map->map_priv_1 + from, len);
++}
++
++void ar7_write8(struct map_info *map, __u8 d, unsigned long adr)
++{
++ __raw_writeb(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void ar7_write16(struct map_info *map, __u16 d, unsigned long adr)
++{
++ __raw_writew(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void ar7_write32(struct map_info *map, __u32 d, unsigned long adr)
++{
++ __raw_writel(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void ar7_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
++{
++ memcpy_toio(map->map_priv_1 + to, from, len);
++}
++
++struct map_info ar7_map = {
++ name: "Physically mapped flash",
++ size: WINDOW_SIZE,
++ buswidth: BUSWIDTH,
++ read8: ar7_read8,
++ read16: ar7_read16,
++ read32: ar7_read32,
++ copy_from: ar7_copy_from,
++ write8: ar7_write8,
++ write16: ar7_write16,
++ write32: ar7_write32,
++ copy_to: ar7_copy_to
++};
++
++int __init ar7_mtd_init(void)
++{
++ int partitions;
++
++ printk(KERN_NOTICE "ar7 flash device: 0x%lx at 0x%lx.\n", (unsigned long)WINDOW_SIZE, (unsigned long)WINDOW_ADDR);
++ ar7_map.map_priv_1 = (unsigned long)ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
++
++ if (!ar7_map.map_priv_1) {
++ printk("Failed to ioremap\n");
++ return -EIO;
++ }
++
++ ar7_mtd_info = do_map_probe("cfi_probe", &ar7_map);
++ if (!ar7_mtd_info)
++ {
++ ar7_mtd_cleanup();
++ return -ENXIO;
++ }
++
++ ar7_mtd_info->module = THIS_MODULE;
++
++ if (!(partitions = create_mtd_partitions()))
++ add_mtd_device(ar7_mtd_info);
++ else
++ add_mtd_partitions(ar7_mtd_info, ar7_partinfo, partitions);
++
++ return 0;
++}
++
++static char *strdup(char *str)
++{
++ int n = strlen(str)+1;
++ char *s = kmalloc(n, GFP_KERNEL);
++ if (!s) return NULL;
++ return strcpy(s, str);
++}
++
++
++static int create_mtd_partitions(void)
++{
++ unsigned int offset;
++ unsigned int size;
++ unsigned int found = 0;
++ unsigned int p = 0;
++ unsigned char *flash_base;
++ unsigned char *flash_end;
++ char *env_ptr;
++ char *base_ptr;
++ char *end_ptr;
++ unsigned int adam2_size = 0x20000;
++ unsigned int config_offset = WINDOW_SIZE;
++ unsigned int rootfs_start = 0xe0000;
++
++ printk("Parsing ADAM2 partition map...\n");
++
++ do {
++ char env_name[20];
++
++ /* get base and end addresses of flash file system from environment */
++ sprintf(env_name, "mtd%1u", p);
++ printk("Looking for mtd device :%s:\n", env_name);
++
++ env_ptr = prom_getenv(env_name);
++ if(env_ptr == NULL) {
++ /* No more partitions to find */
++ break;
++ }
++
++ /* Extract the start and stop addresses of the partition */
++ base_ptr = strtok(env_ptr, ",");
++ end_ptr = strtok(NULL, ",");
++ if ((base_ptr == NULL) || (end_ptr == NULL)) {
++ printk("ADAM2 partition error: Invalid %s start,end.\n", env_name);
++ break;
++ }
++
++ flash_base = (unsigned char*) simple_strtol(base_ptr, NULL, 0);
++ flash_end = (unsigned char*) simple_strtol(end_ptr, NULL, 0);
++ if((!flash_base) || (!flash_end)) {
++ printk("ADAM2 partition error: Invalid %s start,end.\n", env_name);
++ break;
++ }
++
++ offset = virt_to_bus(flash_base) - WINDOW_ADDR;
++ size = flash_end - flash_base;
++ printk("Found a %s image (0x%x), with size (0x%x).\n",env_name, offset, size);
++
++
++ if (offset == 0) {
++ printk("Assuming adam2 size of 0x%x\n", size);
++ adam2_size = size; // boot loader
++ } else if (offset > 0x120000) {
++ if (config_offset > offset)
++ config_offset = offset; // reserved at the end of the flash chip
++ } else if (offset > 0x30000) {
++ printk("Assuming default rootfs offset of 0x%x\n", offset);
++ rootfs_start = offset; // probably root fs
++ }
++
++ p++;
++ } while (p < MAX_NUM_PARTITIONS);
++
++ p = 0;
++
++ ar7_partinfo[p].name = strdup("adam2");
++ ar7_partinfo[p].offset = 0;
++ ar7_partinfo[p].size = adam2_size;
++ ar7_partinfo[p++].mask_flags = 0;
++
++ ar7_partinfo[p].name = strdup("linux");
++ ar7_partinfo[p].offset = adam2_size;
++ ar7_partinfo[p].size = config_offset - adam2_size;
++ ar7_partinfo[p++].mask_flags = 0;
++
++ if (ar7_read32(&ar7_map, adam2_size) == 0xfeedfa42) {
++ rootfs_start = ar7_read32(&ar7_map, adam2_size + 4) + adam2_size + 28;
++ printk("Setting new rootfs offset to %08x\n", rootfs_start);
++ }
++
++ ar7_partinfo[p].name = strdup("rootfs");
++ ar7_partinfo[p].offset = rootfs_start;
++ ar7_partinfo[p].size = config_offset - rootfs_start;
++
++ ar7_partinfo[p++].mask_flags = 0;
++
++ ar7_partinfo[p].name = strdup("config");
++ ar7_partinfo[p].offset = config_offset;
++ ar7_partinfo[p].size = WINDOW_SIZE - config_offset;
++ ar7_partinfo[p++].mask_flags = 0;
++
++ if (ar7_read32(&ar7_map, rootfs_start) == SQUASHFS_MAGIC) {
++ int newsize, newoffset;
++ struct squashfs_super_block sb;
++
++ ar7_copy_from(&ar7_map, &sb, rootfs_start, sizeof(sb));
++ printk("Squashfs detected (size = 0x%08x)\n", sb.bytes_used);
++
++ newoffset = rootfs_start + sb.bytes_used;
++
++ if ((newoffset % ar7_mtd_info->erasesize) > 0)
++ newoffset += ar7_mtd_info->erasesize - (newoffset % ar7_mtd_info->erasesize);
++
++ ar7_partinfo[p - 2].size = newoffset - rootfs_start;
++
++ ar7_partinfo[p].name = strdup("OpenWrt");
++ ar7_partinfo[p].offset = newoffset;
++ ar7_partinfo[p].size = config_offset - newoffset;
++ ar7_partinfo[p++].mask_flags = 0;
++ } else {
++ printk("Unknown filesystem. Moving rootfs partition to next erase block");
++ if ((rootfs_start % ar7_mtd_info->erasesize) > 0) {
++ ar7_partinfo[p - 2].offset += ar7_mtd_info->erasesize - (rootfs_start % ar7_mtd_info->erasesize);
++ ar7_partinfo[p - 2].size -= ar7_mtd_info->erasesize - (rootfs_start % ar7_mtd_info->erasesize);
++ }
++ }
++
++ return p;
++}
++
++static void __exit ar7_mtd_cleanup(void)
++{
++ if (ar7_mtd_info) {
++ del_mtd_partitions(ar7_mtd_info);
++ del_mtd_device(ar7_mtd_info);
++ map_destroy(ar7_mtd_info);
++ }
++
++ if (ar7_map.map_priv_1) {
++ iounmap((void *)ar7_map.map_priv_1);
++ ar7_map.map_priv_1 = 0;
++ }
++}
++
++module_init(ar7_mtd_init);
++module_exit(ar7_mtd_cleanup);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Felix Fietkau");
++MODULE_DESCRIPTION("AR7 CFI map driver");
+diff -urN linux.old/drivers/mtd/maps/Config.in linux.dev/drivers/mtd/maps/Config.in
+--- linux.old/drivers/mtd/maps/Config.in 2005-07-21 05:36:32.414242296 +0200
++++ linux.dev/drivers/mtd/maps/Config.in 2005-07-21 06:29:04.067118232 +0200
+@@ -48,6 +48,21 @@
+ fi
+
+ if [ "$CONFIG_MIPS" = "y" ]; then
++ if [ "$CONFIG_AR7" = "y" ]; then
++ dep_tristate ' Flash chip mapping on Texas Instruments AR7' CONFIG_MTD_AR7 $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS
++ dep_bool ' Use defaults for Texas Instruments AR7' CONFIG_MTD_AR7_DEFAULTS $CONFIG_MTD_AR7
++ if [ "$CONFIG_MTD_AR7" = "y" -o "$CONFIG_MTD_AR7" = "m" ]; then
++ if [ "$CONFIG_MTD_AR7_DEFAULTS" = "y" ]; then
++ define_hex CONFIG_MTD_AR7_START 0x10000000
++ define_hex CONFIG_MTD_AR7_LEN 0x400000
++ define_int CONFIG_MTD_AR7_BUSWIDTH 2
++ else
++ hex ' Physical start address of flash mapping' CONFIG_MTD_AR7_START 0x10000000
++ hex ' Physical length of flash mapping' CONFIG_MTD_AR7_LEN 0x400000
++ int ' Bus width in octets' CONFIG_MTD_AR7_BUSWIDTH 2
++ fi
++ fi
++ fi
+ dep_tristate ' Pb1000 MTD support' CONFIG_MTD_PB1000 $CONFIG_MIPS_PB1000
+ dep_tristate ' Pb1500 MTD support' CONFIG_MTD_PB1500 $CONFIG_MIPS_PB1500
+ dep_tristate ' Pb1100 MTD support' CONFIG_MTD_PB1100 $CONFIG_MIPS_PB1100
+diff -urN linux.old/drivers/mtd/maps/Makefile linux.dev/drivers/mtd/maps/Makefile
+--- linux.old/drivers/mtd/maps/Makefile 2005-07-21 05:36:32.414242296 +0200
++++ linux.dev/drivers/mtd/maps/Makefile 2005-07-21 06:56:33.265401984 +0200
+@@ -10,6 +10,7 @@
+ endif
+
+ # Chip mappings
++obj-$(CONFIG_MTD_AR7) += ar7-flash.o
+ obj-$(CONFIG_MTD_CDB89712) += cdb89712.o
+ obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o
+ obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o
diff --git a/target/linux/ar7-2.4/patches/002-led_driver.patch b/target/linux/ar7-2.4/patches/002-led_driver.patch
new file mode 100644
index 0000000000..81fe153cc3
--- /dev/null
+++ b/target/linux/ar7-2.4/patches/002-led_driver.patch
@@ -0,0 +1,1915 @@
+diff -urN linux.dev/drivers/char/Config.in linux.dev2/drivers/char/Config.in
+--- linux.dev/drivers/char/Config.in 2005-10-21 17:02:20.199991500 +0200
++++ linux.dev2/drivers/char/Config.in 2005-10-21 18:03:44.541778750 +0200
+@@ -133,6 +133,10 @@
+ fi
+ fi
+ fi
++if [ "$CONFIG_AR7" = "y" ]; then
++ bool 'Enable LED support' CONFIG_AR7_LED
++fi
++
+ if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_ZORRO" = "y" ]; then
+ tristate 'Commodore A2232 serial support (EXPERIMENTAL)' CONFIG_A2232
+ fi
+diff -urN linux.dev/drivers/char/Makefile linux.dev2/drivers/char/Makefile
+--- linux.dev/drivers/char/Makefile 2005-10-21 17:02:20.199991500 +0200
++++ linux.dev2/drivers/char/Makefile 2005-10-21 18:03:44.541778750 +0200
+@@ -190,6 +190,12 @@
+ obj-$(CONFIG_PCI) += keyboard.o $(KEYMAP)
+ endif
+
++#
++# Texas Intruments LED driver
++#
++obj-$(CONFIG_AR7_LED) += avalanche_led/avalanche_led.o
++subdir-$(CONFIG_AR7_LED) += avalanche_led
++
+ obj-$(CONFIG_HIL) += hp_keyb.o
+ obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
+ obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
+diff -urN linux.dev/drivers/char/avalanche_led/Makefile linux.dev2/drivers/char/avalanche_led/Makefile
+--- linux.dev/drivers/char/avalanche_led/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev2/drivers/char/avalanche_led/Makefile 2005-10-21 18:03:44.513777000 +0200
+@@ -0,0 +1,23 @@
++# File: drivers/char/avalanche_led/Makefile
++#
++# Makefile for the Linux LED device driver.
++#
++
++
++O_TARGET := avalanche_led.o
++obj-m := avalanche_led.o
++list-multi := avalanche_led.o
++
++EXTRA_CFLAGS := -I$(TOPDIR)/include/asm/ar7
++
++export-objs := ledmod.o leds.o
++
++avalanche_led-objs := ledmod.o gpio.o uartled.o leds.o
++
++include $(TOPDIR)/Rules.make
++
++avalanche_led.o: $(avalanche_led-objs)
++ $(LD) -r -o $@ $(avalanche_led-objs)
++
++clean:
++ rm -f core *.o *.a *.s
+diff -urN linux.dev/drivers/char/avalanche_led/gpio.c linux.dev2/drivers/char/avalanche_led/gpio.c
+--- linux.dev/drivers/char/avalanche_led/gpio.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev2/drivers/char/avalanche_led/gpio.c 2005-10-21 18:03:44.513777000 +0200
+@@ -0,0 +1,382 @@
++#include <linux/kernel.h>
++#include <asm/uaccess.h>
++#include <linux/spinlock.h>
++#include <linux/proc_fs.h>
++#include <linux/fs.h>
++#include <linux/timer.h>
++#include <linux/module.h>
++
++#include <asm/ar7/tnetd73xx_err.h>
++#include <asm/ar7/tnetd73xx_misc.h>
++#include <asm/ar7/ledapp.h>
++
++#define TRUE 1
++#define FALSE 0
++
++#if defined CONFIG_AR7WRD || defined CONFIG_AR7RD
++
++#define AR7_RESET_FILE "led_mod/ar7reset"
++#define AR7_VERSION_FILE "led_mod/hardware_version"
++#define AR7_RESET_GPIO 11
++#define RESET_POLL_TIME 1
++#define RESET_HOLD_TIME 4
++#define NO_OF_LEDS
++
++static struct proc_dir_entry *reset_file;
++static int res_state = 0;
++static int count;
++static struct timer_list *pTimer = NULL;
++static ssize_t proc_read_reset_fops(struct file *filp,
++ char *buf,size_t count , loff_t *offp);
++
++static ssize_t proc_read_hwversion_fops(struct file *filp,
++ char *buf,size_t count , loff_t *offp);
++
++struct file_operations reset_fops = {
++ read: proc_read_reset_fops
++ };
++struct file_operations hardware_version_fops = {
++ read: proc_read_hwversion_fops
++ };
++#endif
++
++static spinlock_t device_lock;
++led_reg_t temp[15];
++
++static void gpio_led_on( unsigned long param )
++{
++ unsigned int flags;
++
++ spin_lock_irqsave(&device_lock, flags);
++
++ tnetd73xx_gpio_out(param,FALSE);
++ spin_unlock_irqrestore(&device_lock, flags);
++}
++
++static void gpio_led_off ( unsigned long param )
++{
++ unsigned int flags = 0x00;
++
++ spin_lock_irqsave(&device_lock, flags);
++
++ tnetd73xx_gpio_out(param,TRUE);
++ spin_unlock_irqrestore(&device_lock, flags);
++}
++
++static void gpio_led_init( unsigned long param)
++{
++ tnetd73xx_gpio_ctrl(param,GPIO_PIN,GPIO_OUTPUT_PIN);
++}
++
++static void board_gpio_reset(void)
++{
++ /* Initialize the link mask */
++ device_lock = SPIN_LOCK_UNLOCKED;
++ return;
++}
++
++#if defined CONFIG_AR7WRD || defined CONFIG_AR7RD
++
++static ssize_t proc_read_hwversion_fops(struct file *filp, char *buf,
++ size_t count, loff_t *offp)
++{
++ char line[8];
++ int len = 0;
++ if( *offp != 0 )
++ return 0;
++
++ len = sprintf(line, "%d%d.%d%d%d%d\n", tnetd73xx_gpio_in(20),
++ tnetd73xx_gpio_in(21), tnetd73xx_gpio_in(22),
++ tnetd73xx_gpio_in(23), tnetd73xx_gpio_in(24),
++ tnetd73xx_gpio_in(25));
++
++ copy_to_user(buf, line, len);
++ *offp = len;
++ return len;
++}
++
++static ssize_t proc_read_reset_fops(struct file *filp,
++ char *buf,size_t count , loff_t *offp)
++{
++ char * pdata = NULL;
++ char line[3];
++ int len = 0;
++ if( *offp != 0 )
++ return 0;
++
++ pdata = buf;
++ len = sprintf(line,"%d\n", res_state );
++//wwzh
++// res_state = 0;
++ copy_to_user(buf,line,len );
++ *offp = len;
++ return len;
++}
++
++static void reset_timer_func(unsigned long data)
++{
++//wwzh
++#if 0
++ count = (tnetd73xx_gpio_in(AR7_RESET_GPIO) == 0) ? count + 1: 0;
++ if( count >= RESET_HOLD_TIME/RESET_POLL_TIME )
++#endif
++ if (tnetd73xx_gpio_in(AR7_RESET_GPIO) == 0)
++ res_state = 1;
++ else
++ res_state = 0;
++ pTimer->expires = jiffies + HZ*RESET_POLL_TIME;
++ add_timer (pTimer);
++ return;
++}
++
++static void hardware_version_init(void)
++{
++ static struct proc_dir_entry *hardware_version_file;
++ hardware_version_file = create_proc_entry(AR7_VERSION_FILE, 0777, NULL);
++ if(hardware_version_file == NULL)
++ return;
++
++ hardware_version_file->owner = THIS_MODULE;
++ hardware_version_file->proc_fops = &hardware_version_fops;
++
++ tnetd73xx_gpio_ctrl(20,GPIO_PIN,GPIO_INPUT_PIN);
++ tnetd73xx_gpio_ctrl(21,GPIO_PIN,GPIO_INPUT_PIN);
++ tnetd73xx_gpio_ctrl(22,GPIO_PIN,GPIO_INPUT_PIN);
++ tnetd73xx_gpio_ctrl(23,GPIO_PIN,GPIO_INPUT_PIN);
++ tnetd73xx_gpio_ctrl(24,GPIO_PIN,GPIO_INPUT_PIN);
++ tnetd73xx_gpio_ctrl(25,GPIO_PIN,GPIO_INPUT_PIN);
++
++ return;
++}
++
++static void reset_init(void)
++{
++ /* Create board reset proc file */
++ reset_file = create_proc_entry( AR7_RESET_FILE, 0777, NULL);
++ if( reset_file == NULL)
++ goto reset_file;
++ reset_file->owner = THIS_MODULE;
++ reset_file->proc_fops = &reset_fops;
++
++ /* Initialise GPIO 11 for input */
++ tnetd73xx_gpio_ctrl(AR7_RESET_GPIO,GPIO_PIN,GPIO_INPUT_PIN);
++
++ /* Create a timer which fires every seconds */
++ pTimer = kmalloc(sizeof(struct timer_list),GFP_KERNEL);
++ init_timer( pTimer );
++ pTimer->function = reset_timer_func;
++ pTimer->data = 0;
++ /* Start the timer */
++ reset_timer_func(0);
++ return ;
++
++ reset_file:
++ remove_proc_entry("AR7_RESET_FILE",NULL);
++ return;
++}
++#endif
++/*************wwzh****************/
++#if 1
++extern unsigned int sys_mod_state;
++extern unsigned int wan_mod_state;
++extern unsigned int wlan_mod_state;
++void sys_led_init(void)
++{
++ tnetd73xx_gpio_ctrl(4, GPIO_PIN, GPIO_OUTPUT_PIN);
++ tnetd73xx_gpio_ctrl(5, GPIO_PIN, GPIO_OUTPUT_PIN);
++ tnetd73xx_gpio_ctrl(8, GPIO_PIN, GPIO_OUTPUT_PIN);
++
++ tnetd73xx_gpio_out(4, FALSE);
++ tnetd73xx_gpio_out(5, TRUE);
++ tnetd73xx_gpio_out(8, TRUE);
++
++
++ sys_mod_state = 2;
++
++}
++void wan_led_init(void)
++{
++
++ tnetd73xx_gpio_ctrl(2, GPIO_PIN, GPIO_OUTPUT_PIN);
++ tnetd73xx_gpio_ctrl(3, GPIO_PIN, GPIO_OUTPUT_PIN);
++
++ tnetd73xx_gpio_out(2, FALSE);
++ tnetd73xx_gpio_out(3, FALSE);
++
++ wan_mod_state = 1;
++}
++//wwzh wireless
++#if 0
++void wlan_led_init(void)
++{
++ //unsigned long i = 0;
++ tnetd73xx_gpio_ctrl(12, GPIO_PIN, GPIO_OUTPUT_PIN);
++ tnetd73xx_gpio_ctrl(13, GPIO_PIN, GPIO_OUTPUT_PIN);
++
++ tnetd73xx_gpio_out(12, FALSE);
++ tnetd73xx_gpio_out(13, TRUE);
++ //for (i = 0; i < 0x20000000; i++);
++ wlan_mod_state = 1;
++}
++#endif
++
++#endif
++/*************end ****************/
++
++void board_gpio_init(void)
++{
++
++ board_gpio_reset();
++/**************wwzh*************/
++ sys_led_init();
++ wan_led_init();
++
++ //junzhao 2004.3.15
++ hardware_version_init();
++
++ //wlan_led_init();
++
++ /* Register Device MAX_LED_ID + 1 for reset to factory default */
++ temp[0].param = 0;
++ temp[0].init = reset_init;
++ temp[0].onfunc = 0;
++ temp[0].offfunc = 0;
++ register_led_drv( MAX_LED_ID + 1 , &temp[0]);
++//wwzh for wireless led
++#if 1
++ /* Register led 12 WiFi 6 */
++ temp[1].param = 6;
++ temp[1].init = gpio_led_init;
++ temp[1].onfunc = gpio_led_on;
++ temp[1].offfunc = gpio_led_off;
++ register_led_drv( 12 , &temp[1]);
++
++#endif
++
++#if 0
++/**************end ************/
++#if defined(CONFIG_AR5D01)
++ /* Register led 1 GPIO0 */
++ temp[0].param = GPIO_0;
++ temp[0].init = gpio_led_init;
++ temp[0].onfunc = gpio_led_on;
++ temp[0].offfunc = gpio_led_off;
++ register_led_drv( 1 , &temp[0]);
++
++ /* Register led 2 EINT1 */
++ temp[1].param = EINT_1;
++ temp[1].init = gpio_led_init;
++ temp[1].onfunc = gpio_led_on;
++ temp[1].offfunc = gpio_led_off;
++ register_led_drv( 2 , &temp[1]);
++
++ /* Register led 5 EINT1 */
++ temp[2].param = GPIO_1;
++ temp[2].init = gpio_led_init;
++ temp[2].onfunc = gpio_led_on;
++ temp[2].offfunc = gpio_led_off;
++ register_led_drv( 5 , &temp[2]);
++#endif
++
++#if defined(CONFIG_AR5W01)
++ /* Register led 5 GPIO_1 */
++ temp[0].param = GPIO_1;
++ temp[0].init = gpio_led_init;
++ temp[0].onfunc = gpio_led_on;
++ temp[0].offfunc = gpio_led_off;
++ register_led_drv( 5 , &temp[0]);
++
++ /* Register led 7 GPIO_0 */
++ temp[1].param = GPIO_0;
++ temp[1].init = gpio_led_init;
++ temp[1].onfunc = gpio_led_on;
++ temp[1].offfunc = gpio_led_off;
++ register_led_drv( 7 , &temp[1]);
++#endif
++
++//wwzh #if defined(CONFIG_AR7RD)
++#if defined CONFIG_AR7WRD || defined CONFIG_AR7RD
++ /* Register led 5 Green PPPOE GPIO 13 */
++ temp[0].param = 13;
++ temp[0].init = gpio_led_init;
++ temp[0].onfunc = gpio_led_on;
++ temp[0].offfunc = gpio_led_off;
++ register_led_drv( 5 , &temp[0]);
++
++ /* Register led 7 Green USB GPIO 12 */
++ temp[1].param = 12;
++ temp[1].init = gpio_led_init;
++ temp[1].onfunc = gpio_led_on;
++ temp[1].offfunc = gpio_led_off;
++ register_led_drv( 7 , &temp[1]);
++
++ /* Register Device MAX_LED_ID + 1 for reset to factory default */
++ temp[2].param = 0;
++ temp[2].init = reset_init;
++ temp[2].onfunc = 0;
++ temp[2].offfunc = 0;
++ register_led_drv( MAX_LED_ID + 1 , &temp[2]);
++
++ /* Register led 8 RED DSL GPIO 10 */
++ temp[3].param = 10;
++ temp[3].init = gpio_led_init;
++ temp[3].onfunc = gpio_led_on;
++ temp[3].offfunc = gpio_led_off;
++ register_led_drv( 8 , &temp[3]);
++
++ /* Register led 9 RED PPPoE down GPIO 9 */
++ temp[4].param = 9;
++ temp[4].init = gpio_led_init;
++ temp[4].onfunc = gpio_led_on;
++ temp[4].offfunc = gpio_led_off;
++ register_led_drv( 9 , &temp[4]);
++
++ /* Register led 10 DSL down GPIO 8 */
++ temp[5].param = 8;
++ temp[5].init = gpio_led_init;
++ temp[5].onfunc = gpio_led_on;
++ temp[5].offfunc = gpio_led_off;
++ register_led_drv( 10 , &temp[5]);
++
++ /* Register led 11 Power GPIO 7 */
++ temp[6].param = 7;
++ temp[6].init = gpio_led_init;
++ temp[6].onfunc = gpio_led_on;
++ temp[6].offfunc = gpio_led_off;
++ register_led_drv( 11 , &temp[6]);
++
++ /* Register led 12 WiFi 6 */
++ temp[7].param = 6;
++ temp[7].init = gpio_led_init;
++ temp[7].onfunc = gpio_led_on;
++ temp[7].offfunc = gpio_led_off;
++ register_led_drv( 12 , &temp[7]);
++
++ /* Register led 13 ELINK(AA1313) GPIO 15 */
++ temp[8].param = 15;
++ temp[8].init = gpio_led_init;
++ temp[8].onfunc = gpio_led_on;
++ temp[8].offfunc = gpio_led_off;
++ register_led_drv( 13 , &temp[8]);
++
++ /* Register led 14 EACT(Y13) GPIO 16 */
++ temp[9].param = 16;
++ temp[9].init = gpio_led_init;
++ temp[9].onfunc = gpio_led_on;
++ temp[9].offfunc = gpio_led_off;
++ register_led_drv( 14 , &temp[9]);
++
++#endif
++/**************wwzh**************/
++#endif
++/**************end **************/
++ return;
++}
++
++
++
++
++
++
++
++
+diff -urN linux.dev/drivers/char/avalanche_led/ledmod.c linux.dev2/drivers/char/avalanche_led/ledmod.c
+--- linux.dev/drivers/char/avalanche_led/ledmod.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev2/drivers/char/avalanche_led/ledmod.c 2005-10-21 18:03:44.513777000 +0200
+@@ -0,0 +1,1116 @@
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/proc_fs.h>
++#include <asm/uaccess.h>
++#include <linux/fs.h>
++#include <linux/timer.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <asm/ar7/avalanche_regs.h>
++#include <asm/ar7/ledapp.h>
++#include <linux/module.h>
++
++#define LED_ON 1
++#define LED_OFF 2
++#define LED_BLINK 3
++#define LED_FLASH 4
++
++#define LED_BLINK_UP 5
++#define LED_BLINK_DOWN 6
++
++extern void avalanche_leds_init(void);
++
++/***********wwzh**************/
++unsigned int sys_mod_state;
++unsigned int wan_mod_state;
++unsigned int wlan_mod_state;
++
++struct timer_list *pWanTimer = NULL;
++struct timer_list *pWlanTimer = NULL;
++/***********end **************/
++
++typedef struct state_entry{
++ unsigned char mode;
++ unsigned char led;
++ void (*handler)(struct state_entry *pState);
++ unsigned long param;
++}state_entry_t;
++
++typedef struct mod_entry{
++ state_entry_t *states[MAX_STATE_ID];
++}mod_entry_t;
++
++static mod_entry_t *modArr[MAX_MOD_ID];
++static struct proc_dir_entry *led_proc_dir,*led_file;
++
++/* index of the array is the led number HARDWARE SPECIFIC*/
++typedef struct led_data{
++ led_reg_t *led;
++ int state;
++ struct timer_list *pTimer;
++ unsigned char timer_running;
++ unsigned long param;
++}led_data_t;
++
++led_data_t led_arr[MAX_LED_ID + 1];
++/*!!! The last device is actually being used for ar7 reset to factory default */
++
++
++static spinlock_t config_lock;
++
++static void board_led_link_up( state_entry_t *pState );
++static void board_led_link_down( state_entry_t *pState );
++static void board_led_activity_on( state_entry_t *pState );
++static void board_led_activity_off( state_entry_t *pState );
++static void led_timer_func(unsigned long data);
++
++extern void board_gpio_init(void);
++extern void uart_led_init(void);
++
++static ssize_t proc_read_led_fops(struct file *filp,
++ char *buf,size_t count , loff_t *offp);
++static ssize_t proc_write_led_fops(struct file *filp,const char *buffer,
++ size_t count , loff_t *offp);
++static int config_led( unsigned long y);
++
++struct file_operations led_fops = {
++ read: proc_read_led_fops,
++ write: proc_write_led_fops,
++ };
++
++static int led_atoi( char *name)
++{
++ int val = 0;
++ for(;;name++)
++ {
++ switch(*name)
++ {
++ case '0'...'9':
++ val = val*10+(*name - '0');
++ break;
++ default:
++ return val;
++ }
++ }
++}
++
++static int free_memory(void)
++{
++ int i, j;
++
++ for( i = 0; i < MAX_MOD_ID ; i++)
++ {
++ if( modArr[i] != NULL )
++ {
++ for( j = 0; j < MAX_STATE_ID ; j++ )
++ {
++ if( modArr[i]->states[j] != NULL )
++ kfree( modArr[i]->states[j]);
++ }
++ kfree(modArr[i]);
++ modArr[i] = NULL;
++ }
++ }
++ return 0;
++}
++
++static int led_on( state_entry_t *pState )
++{
++ if( led_arr[pState->led].led == NULL)
++ return -1;
++ led_arr[pState->led].led->onfunc( led_arr[pState->led].led->param);
++ return 0;
++}
++
++static int led_off( state_entry_t *pState )
++{
++ if( led_arr[pState->led].led == NULL)
++ return -1;
++ led_arr[pState->led].led->offfunc( led_arr[pState->led].led->param);
++ return 0;
++}
++
++static void board_led_link_up( state_entry_t *pState )
++{
++ led_arr[pState->led].state = LED_ON;
++ if( led_arr[pState->led].timer_running == 0 )
++ led_on(pState);
++ return;
++}
++
++static void board_led_link_down( state_entry_t *pState )
++{
++ led_arr[pState->led].state = LED_OFF;
++ if( led_arr[pState->led].timer_running == 0 )
++ led_off(pState);
++ return;
++}
++
++static void add_led_timer(state_entry_t *pState)
++{
++ led_arr[pState->led].pTimer->expires = jiffies + HZ*(pState->param)/1000;
++ led_arr[pState->led].param = pState->param;
++ led_arr[pState->led].pTimer->data = pState;
++ add_timer (led_arr[pState->led].pTimer);
++}
++
++static void board_led_activity_on(state_entry_t *pState)
++{
++ if(led_arr[pState->led].timer_running == 0)
++ {
++ led_on(pState);
++ add_led_timer(pState);
++ led_arr[pState->led].timer_running = 1;
++ led_arr[pState->led].state = LED_BLINK_UP;
++ }
++ else if( led_arr[pState->led].timer_running > 0xF0)
++ {
++ led_arr[pState->led].state = LED_BLINK_UP;
++ led_arr[pState->led].pTimer->expires = jiffies + HZ*(pState->param)/1000;
++ led_arr[pState->led].param = pState->param;
++ led_arr[pState->led].pTimer->data = pState;
++ }
++ return;
++}
++
++static void board_led_activity_off(state_entry_t *pState)
++{
++ if(led_arr[pState->led].timer_running == 0)
++ {
++ led_off(pState);
++ add_led_timer(pState);
++ led_arr[pState->led].timer_running = 1;
++ led_arr[pState->led].state = LED_BLINK_UP;
++ }
++ else if( led_arr[pState->led].timer_running > 0xF0)
++ {
++ led_arr[pState->led].state = LED_BLINK_UP;
++ led_arr[pState->led].pTimer->expires = jiffies + HZ*(pState->param)/1000;
++ led_arr[pState->led].param = pState->param;
++ led_arr[pState->led].pTimer->data = pState;
++ }
++ return;
++}
++
++static void board_led_link_flash(state_entry_t *pState)
++{
++ if(led_on(pState))
++ return;
++ if(led_arr[pState->led].timer_running == 0)
++ add_led_timer(pState);
++ else
++ led_arr[pState->led].param = pState->param;
++ led_arr[pState->led].timer_running = 0xFF;
++ led_arr[pState->led].state = LED_FLASH;
++ return;
++}
++
++static void led_timer_func(unsigned long data)
++{
++ state_entry_t *pState = NULL;
++ mod_entry_t *pMod = NULL;
++ unsigned int flags;
++
++ spin_lock_irqsave(&config_lock, flags);
++
++ pState = (state_entry_t *)data;
++
++ if( led_arr[pState->led].state == LED_BLINK_DOWN )
++ {
++ led_arr[pState->led].timer_running = 0;
++ if( pState->mode == 2 )
++ led_arr[pState->led].state = LED_OFF;
++ else
++ led_arr[pState->led].state = LED_ON;
++ }
++ else if( led_arr[pState->led].state == LED_BLINK_UP )
++ {
++ led_arr[pState->led].pTimer->expires = jiffies + HZ*(led_arr[pState->led].param)/1000;
++ led_arr[pState->led].pTimer->data = pState;
++ add_timer (led_arr[pState->led].pTimer);
++ if( pState->mode == 2 )
++ {
++ led_off(pState);
++ led_arr[pState->led].state = LED_BLINK_DOWN;
++ }
++ else
++ {
++ led_on(pState);
++ led_arr[pState->led].state = LED_BLINK_DOWN;
++ }
++ led_arr[pState->led].timer_running = 1;
++ }
++ else if( led_arr[pState->led].state == LED_FLASH )
++ {
++ led_arr[pState->led].pTimer->expires = jiffies + HZ*(led_arr[pState->led].param)/1000;
++ led_arr[pState->led].pTimer->data = pState;
++ add_timer (led_arr[pState->led].pTimer);
++
++ if( led_arr[pState->led].timer_running == 0xFF )
++ {
++ led_off(pState);
++ led_arr[pState->led].timer_running--;
++ }
++ else
++ {
++ led_on(pState);
++ led_arr[pState->led].timer_running++;
++ }
++ spin_unlock_irqrestore(&config_lock, flags);
++ return;
++ }
++ else if(led_arr[pState->led].state == LED_OFF)
++ {
++ led_off(pState);
++ led_arr[pState->led].timer_running = 0;
++ }
++ else if( led_arr[pState->led].state == LED_ON )
++ {
++ led_on(pState);
++ led_arr[pState->led].timer_running = 0;
++ }
++ spin_unlock_irqrestore(&config_lock, flags);
++ return;
++}
++/************wwzh*****************/
++#if 0
++/************end *****************/
++static ssize_t proc_read_led_fops(struct file *filp,
++ char *buf,size_t count , loff_t *offp)
++{
++ char * pdata = NULL;
++ int i = 0, j = 0, len = 0, totallen = 0;
++ char line[255];
++
++ if( *offp != 0 )
++ return 0;
++
++ pdata = buf;
++ len += sprintf(line,"LEDS Registered for use are:");
++ for( i = 0; i< MAX_LED_ID; i++)
++ if( led_arr[i].led != NULL )
++ len += sprintf(&line[len]," %d ", i );
++ line[len++] = '\n';
++
++ copy_to_user(pdata, line,len );
++ pdata += len;
++ totallen += len;
++ len = 0;
++ len = sprintf(line,"USER MODULE INFORMATION:\n");
++ copy_to_user(pdata, line,len );
++ pdata += len;
++ totallen += len;
++ len = 0;
++ for( i = 0; i< MAX_MOD_ID; i++)
++ {
++ if( modArr[i] != NULL )
++ {
++ len = sprintf(line," Module ID = %d \n" , i);
++ copy_to_user(pdata, line,len );
++ pdata += len;
++ totallen += len;
++ len = 0;
++ for( j = 0; j < MAX_STATE_ID; j++)
++ {
++ if( modArr[i]->states[j] != NULL)
++ {
++ len = sprintf(line ,
++ " State = %d , Led = %d," , j , modArr[i]->states[j]->led);
++ copy_to_user(pdata, line,len );
++ pdata += len;
++ totallen += len;
++
++ len = 0;
++ switch( modArr[i]->states[j]->mode )
++ {
++ case 1:
++ len = sprintf(line ," Mode = OFF\n");
++ break;
++ case 2:
++ len = sprintf(line ," Mode = BLINK_ON , On Time(ms) = %d\n" ,
++ (unsigned int)modArr[i]->states[j]->param);
++ break;
++ case 3:
++ len = sprintf(line ," Mode = BLINK_OFF , Off Time(ms) = %d\n" ,
++ (unsigned int)modArr[i]->states[j]->param);
++ break;
++ case 4:
++ len = sprintf(line ," Mode = ON \n");
++ break;
++ case 5:
++ len = sprintf(line ," Mode = FLASH , Time Period(ms) = %d\n" ,
++ (unsigned int)modArr[i]->states[j]->param);
++ break;
++ default:
++ break;
++
++ }
++ copy_to_user(pdata, line,len );
++ pdata += len;
++ totallen += len;
++
++ len = 0;
++ }
++ }
++ }
++ }
++ /* Return with configuration information for LEDs */
++ *offp = totallen;
++ return totallen;
++}
++static ssize_t proc_write_led_fops(struct file *filp,const char *buffer,
++ size_t count , loff_t *offp)
++{
++ char *pdata = NULL, *ptemp = NULL;
++ char line[10],temp[10];
++ int i = 0;
++ int mod = 0xFFFF , state = 0xFFFF;
++ int flag = 0;
++
++ /* Check if this write is for configuring stuff */
++ if( *(int *)(buffer) == 0xFFEEDDCC )
++ {
++ printk("<1>proc write:Calling Configuration\n");
++ config_led((unsigned long)(buffer + sizeof(int)) );
++ return count;
++ }
++
++ if( count >= 10)
++ {
++ printk("<1>proc write:Input too long,max length = %d\n",10);
++ return count;
++ }
++ memset( temp, 0x00 , 10);
++ memset( line, 0x00 , 10);
++ copy_from_user(line,buffer,count);
++ line[count] = 0x00;
++ pdata = line;
++ ptemp = temp;
++ while( flag == 0)
++ {
++ if( i > 10 )
++ break;
++ if( ((*pdata) >= '0' ) && ((*pdata) <= '9') )
++ {
++ *ptemp = *pdata ;
++ ptemp++;
++ }
++ else if( (*pdata) == ',' )
++ {
++ *ptemp = 0x00;
++ flag = 1;
++ }
++ pdata++;
++ i++;
++ };
++ if( flag == 1)
++ mod = led_atoi( temp);
++ else
++ return count;
++
++ ptemp = temp;
++ *ptemp = 0x00;
++ flag = 0;
++ while( flag == 0)
++ {
++ if( i > 10 )
++ break;
++ if( ((*pdata) >= '0' ) && ((*pdata) <= '9') )
++ {
++ *ptemp = *pdata ;
++ ptemp++;
++ }
++ else if( (*pdata) == 0x00 )
++ {
++ *ptemp = 0x00;
++ flag = 1;
++ }
++ pdata++;
++ i++;
++ };
++ if( flag == 1)
++ state = led_atoi( temp);
++ else
++ return count;
++ if( (mod == 0xFFFF) || (state == 0xFFFF))
++ return count;
++ else
++ led_operation( mod , state );
++ return count;
++}
++
++/************wwzh*******************/
++#else
++
++#define TRUE 1
++#define FALSE 0
++#define FLICK_TIME (HZ*100/1000)
++static unsigned int wan_txrx_state = 0;
++static unsigned int wlan_txrx_state = 0;
++
++void led_operation( int mod , int state)
++{
++
++ unsigned int flags;
++
++ spin_lock_irqsave(&config_lock, flags);
++
++ if( (mod >= MAX_MOD_ID) || ( state >= MAX_STATE_ID) )
++ {
++ spin_unlock_irqrestore(&config_lock, flags);
++ return;
++ }
++ if ( modArr[mod] == NULL )
++ {
++ spin_unlock_irqrestore(&config_lock, flags);
++ return;
++ }
++ if( modArr[mod]->states[state] == NULL )
++ {
++ spin_unlock_irqrestore(&config_lock, flags);
++ return;
++ }
++ /* Call the function handler */
++ modArr[mod]->states[state]->handler(modArr[mod]->states[state]);
++
++ spin_unlock_irqrestore(&config_lock, flags);
++}
++
++static void wan_led_func(unsigned long data)
++{
++ if (wan_txrx_state == 0)
++ {
++ tnetd73xx_gpio_out(2, TRUE);
++ tnetd73xx_gpio_out(3, FALSE);
++ wan_txrx_state = 1;
++ }
++ else
++ {
++ tnetd73xx_gpio_out(2, FALSE);
++ tnetd73xx_gpio_out(3, FALSE);
++ wan_txrx_state = 0;
++ }
++ pWanTimer->expires = jiffies + FLICK_TIME;
++ add_timer(pWanTimer);
++}
++//wwzh for wireless
++#if 0
++static void wlan_led_func(unsigned long data)
++{
++ if (wlan_txrx_state == 0)
++ {
++ tnetd73xx_gpio_out(12, TRUE);
++ tnetd73xx_gpio_out(13, FALSE);
++ wlan_txrx_state = 1;
++ }
++ else
++ {
++ tnetd73xx_gpio_out(12, FALSE);
++ tnetd73xx_gpio_out(13, FALSE);
++ wlan_txrx_state = 0;
++
++ }
++ pWlanTimer->expires = jiffies + FLICK_TIME;
++ add_timer(pWlanTimer);
++}
++#endif
++
++void led_active(int mod, int state)
++{
++ unsigned int flags = 0;
++
++//printk("mod = %d state = %d\n", mod, state);
++ spin_lock_irqsave(&config_lock, flags);
++ if ((mod >= 5) || (state >= 5))
++ {
++ spin_unlock_irqrestore(&config_lock, flags);
++ return;
++ }
++
++ switch (mod)
++ {
++ case 2: /*system led */
++ sys_mod_state = state;
++ switch (state)
++ {
++ case 1:
++ break;
++ case 2: /*sys led flashing green */
++ tnetd73xx_gpio_out(4, FALSE);
++ tnetd73xx_gpio_out(5, TRUE);
++ tnetd73xx_gpio_out(8, TRUE);
++ break;
++ case 3: /*sys led solid green */
++ tnetd73xx_gpio_out(4, TRUE);
++ tnetd73xx_gpio_out(5, TRUE);
++ tnetd73xx_gpio_out(8, TRUE);
++
++ break;
++ case 4: /*sys fail red */
++ tnetd73xx_gpio_out(4, TRUE);
++ tnetd73xx_gpio_out(5, FALSE);
++ tnetd73xx_gpio_out(8, FALSE);
++ break;
++ default:
++ break;
++ }
++ break;
++ case 3: /*wan led */
++ wan_mod_state = state;
++ switch (state)
++ {
++ case 1: /*no wan interface*/
++ if (pWanTimer)
++ {
++ del_timer(pWanTimer);
++ kfree(pWanTimer);
++ pWanTimer = NULL;
++ }
++ tnetd73xx_gpio_out(2, FALSE);
++ tnetd73xx_gpio_out(3, FALSE);
++ break;
++ case 2: /*wan connected */
++ if (pWanTimer)
++ {
++ del_timer(pWanTimer);
++ kfree(pWanTimer);
++ pWanTimer = NULL;
++ }
++ tnetd73xx_gpio_out(2, TRUE);
++ tnetd73xx_gpio_out(3, FALSE);
++ break;
++ case 3: /*rx/tx activity */
++ if (pWanTimer != NULL)
++ break;
++
++ pWanTimer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
++ init_timer(pWanTimer);
++
++ pWanTimer->function = wan_led_func;
++ pWanTimer->data = 0;
++ pWanTimer->expires = jiffies + FLICK_TIME;
++ tnetd73xx_gpio_out(2, FALSE);
++ tnetd73xx_gpio_out(3, FALSE);
++ wan_txrx_state = 0;
++ add_timer(pWanTimer);
++
++ break;
++ case 4: /*no ipaddress */
++ if (pWanTimer)
++ {
++ del_timer(pWanTimer);
++ kfree(pWanTimer);
++ pWanTimer = NULL;
++ }
++ tnetd73xx_gpio_out(2, FALSE);
++ tnetd73xx_gpio_out(3, TRUE);
++ break;
++ default:
++ if (pWanTimer)
++ {
++ del_timer(pWanTimer);
++ kfree(pWanTimer);
++ pWanTimer = NULL;
++ }
++ break;
++ }
++ break;
++ //wwzh for wireless
++ #if 0
++ case 4: /*wlan led */
++ wlan_mod_state = state;
++ switch (state)
++ {
++ case 1: /* wlan off */
++ if (pWlanTimer)
++ {
++ del_timer(pWlanTimer);
++ kfree(pWlanTimer);
++ pWlanTimer = NULL;
++ }
++ tnetd73xx_gpio_out(12, FALSE);
++ tnetd73xx_gpio_out(13, FALSE);
++ break;
++ case 2: /* wlan ready */
++ if (pWlanTimer)
++ {
++ del_timer(pWlanTimer);
++ kfree(pWlanTimer);
++ pWlanTimer = NULL;
++ }
++ tnetd73xx_gpio_out(12, TRUE);
++ tnetd73xx_gpio_out(13, FALSE);
++ break;
++ case 3: /* wlan rx/tx activity */
++ if (pWlanTimer != NULL)
++ break;
++
++ pWlanTimer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
++ init_timer(pWlanTimer);
++
++ pWlanTimer->function = wlan_led_func;
++ pWlanTimer->data = 0;
++ pWlanTimer->expires = jiffies + FLICK_TIME;
++ tnetd73xx_gpio_out(12, FALSE);
++ tnetd73xx_gpio_out(13, FALSE);
++ wlan_txrx_state = 0;
++ add_timer(pWlanTimer);
++
++ break;
++ default:
++ if (pWlanTimer)
++ {
++ del_timer(pWlanTimer);
++ kfree(pWlanTimer);
++ pWlanTimer = NULL;
++ }
++
++ break;
++ }
++ break;
++ #endif //for wireless
++ default:
++ break;
++ }
++ spin_unlock_irqrestore(&config_lock, flags);
++}
++static ssize_t proc_read_led_fops(struct file *filp,
++ char *buf,size_t count , loff_t *offp)
++{
++ char *pdata = NULL;
++ int i = 0, j = 0, len = 0, totallen = 0;
++ char line[255];
++
++ if (*offp != 0)
++ return 0;
++ pdata = buf;
++ len = sprintf(line, "USER MODULE INFORMATION:\n");
++ copy_to_user(pdata, line, len);
++ pdata += len;
++ totallen += len;
++ len = 0;
++
++ //*******add Module 1 , this Module is ADSL ********/
++ for (i = 0; i < MAX_MOD_ID; i++)
++ {
++ if (modArr[i] != NULL)
++ {
++ len = sprintf(line, " Module ID = %d\n", i);
++ copy_to_user(pdata, line, len);
++ pdata += len;
++ totallen += len;
++ len = 0;
++ for(j = 0; j < MAX_STATE_ID; j++)
++ {
++ if (modArr[i]->states[j] != NULL)
++ {
++ len = sprintf(line, "State =%d, Led = %d,", j, modArr[i]->states[j]->led);
++ copy_to_user(pdata, line, len);
++ pdata += len;
++ totallen += len;
++ len = 0;
++ switch(modArr[i]->states[j]->mode)
++ {
++ case 1:
++ len = sprintf(line, "Mode = OFF\n");
++ break;
++ case 2:
++ len = sprintf(line, "Mode = BLINK_ON, On Time(ms) = %d\n", (unsigned int)modArr[i]->states[j]->param);
++ break;
++ case 3:
++ len = sprintf(line, "Mode = BLINK_OFF, Off Time(ms) = %d\n", (unsigned int)modArr[i]->states[j]->param);
++ break;
++ case 4:
++ len = sprintf(line, "Mode = On\n");
++ break;
++ case 5:
++ len = sprintf(line, "Mode = FLASH, Time Period(ms) = %d\n", (unsigned int)modArr[i]->states[j]->param);
++ break;
++ default:
++ break;
++ }
++ copy_to_user(pdata, line, len);
++ pdata += len;
++ totallen += len;
++ len = 0;
++ }
++ }
++ }
++
++ }
++
++ len = sprintf(line, "Module ID = 2(system led)\n");
++ copy_to_user(pdata, line, len);
++ pdata += len;
++ totallen += len;
++ len = 0;
++ switch(sys_mod_state)
++ {
++ case 1:
++ len = sprintf(line, "State = OFF\n");
++ break;
++ case 2:
++ len = sprintf(line, "State = Booting\n");
++ break;
++ case 3:
++ len = sprintf(line, "State = System Ready\n");
++ break;
++ case 4:
++ len = sprintf(line, "State = System Failure\n");
++ break;
++ default:
++ break;
++ }
++ copy_to_user(pdata, line, len);
++ pdata += len;
++ totallen += len;
++ len = 0;
++
++ len = sprintf(line, "Module ID = 3(WAN led)\n");
++ copy_to_user(pdata, line, len);
++ pdata += len;
++ totallen += len;
++ len = 0;
++ switch(wan_mod_state)
++ {
++ case 1:
++ len = sprintf(line, "State = OFF\n");
++ break;
++ case 2:
++ len = sprintf(line, "State = Wan Connected\n");
++ break;
++ case 3:
++ len = sprintf(line, "State = Wan Tx/Rx Activity\n");
++ break;
++ case 4:
++ len = sprintf(line, "State = Wan Connect Failure\n");
++ break;
++ default:
++ break;
++ }
++ copy_to_user(pdata, line, len);
++ pdata += len;
++ totallen += len;
++ len = 0;
++
++//wwzh for wireless
++#if 0
++ len = sprintf(line, "Module ID = 4(WLAN led)\n");
++ copy_to_user(pdata, line, len);
++ pdata += len;
++ totallen += len;
++ len = 0;
++ switch(wlan_mod_state)
++ {
++ case 1:
++ len = sprintf(line, "State = OFF\n");
++ break;
++ case 2:
++ len = sprintf(line, "State = wlan Ready\n");
++ break;
++ case 3:
++ len = sprintf(line, "State = wlan rx/tx activity\n");
++ break;
++ default:
++ break;
++ }
++ copy_to_user(pdata, line, len);
++ pdata += len;
++ totallen += len;
++ len = 0;
++#endif //for wireless
++
++ *offp = totallen;
++ return totallen;
++}
++static ssize_t proc_write_led_fops(struct file *filp,const char *buffer,
++ size_t count , loff_t *offp)
++{
++ char *pdata = NULL, *ptemp = NULL;
++ char line[10], temp[10];
++ int i = 0;
++ int mod = 0xffff, state = 0xffff;
++ int flag = 0;
++
++ /* Check if this write is for configuring ADSL */
++ if( *(int *)(buffer) == 0xFFEEDDCC )
++ {
++ printk("<1>proc write:Calling Configuration\n");
++ config_led((unsigned long)(buffer + sizeof(int)) );
++ return count;
++ }
++
++ if (count > 10)
++ {
++ printk("<1> proc write: Input too long, max length = 10\n");
++ return count;
++ }
++ memset(temp, 0x00, 10);
++ memset(line, 0x00, 10);
++ copy_from_user(line, buffer, count);
++ line[count] = 0x00;
++ pdata = line;
++ ptemp = temp;
++
++ while (flag == 0)
++ {
++ if (i > 10)
++ break;
++ if (((*pdata) >= '0') && ((*pdata) <= '9'))
++ {
++ *ptemp = *pdata;
++ ptemp++;
++ }
++ else if ((*pdata) == ',')
++ {
++ *ptemp = 0x00;
++ flag = 1;
++ }
++ pdata++;
++ i++;
++ }
++ if (flag == 1)
++ mod = led_atoi(temp);
++ else
++ return count;
++
++ ptemp = temp;
++ *ptemp = 0x00;
++ flag = 0;
++
++ while(flag == 0)
++ {
++ if (i > 10)
++ break;
++ if (((*pdata) >= '0') && ((*pdata) <= '9'))
++ {
++ *ptemp = *pdata;
++ ptemp++;
++ }
++ else if ((*pdata) == 0x00)
++ {
++ *ptemp = 0x00;
++ flag = 1;
++ }
++ pdata++;
++ i++;
++ }
++ if (flag == 1)
++ state = led_atoi(temp);
++ else
++ return count;
++ if ((mod == 0xFFFF) || (state == 0xFFFF))
++ return count;
++ else
++ {
++ if (mod != 4)
++ led_active(mod, state);
++ else
++ led_operation(mod, state);
++ }
++ return 1;
++}
++#endif
++/************end *******************/
++static int config_led(unsigned long y)
++{
++ config_elem_t *pcfg = NULL;
++ char *pdata = NULL;
++ int i;
++ int length = 0 , number = 0;
++ unsigned int flags;
++
++ spin_lock_irqsave(&config_lock, flags);
++
++ /* ioctl to configure */
++ length = *((int*)y);
++ pdata = (char *)y + sizeof(int);
++ number = (length - sizeof(int))/sizeof(config_elem_t);
++ pcfg = (config_elem_t *)(pdata);
++
++ /* Check if an earlier configuration exists IF yes free it up */
++ free_memory();
++
++ for ( i = 0 ; i < number ; i++ )
++ {
++ /* If no structure has been allocated for the module do so */
++ if ( modArr[pcfg->name] == NULL )
++ {
++ printk("<1>module = %d\n",pcfg->name);
++ if( pcfg->name >= MAX_MOD_ID)
++ {
++ printk("<1>Exiting Configuration: Module ID too large %d\n",pcfg->name);
++ free_memory();
++ spin_unlock_irqrestore(&config_lock, flags);
++ return -1;
++ }
++ modArr[pcfg->name] = kmalloc(sizeof(mod_entry_t),GFP_KERNEL);
++ if(modArr[pcfg->name] == NULL)
++ {
++ printk("<1>Exiting Configuration: Error in allocating memory\n");
++ free_memory();
++ spin_unlock_irqrestore(&config_lock, flags);
++ return -1;
++ }
++ memset( modArr[pcfg->name], 0x00, sizeof(mod_entry_t));
++ }
++
++ /* if no structure is allocated previously for this state
++ allocate a structure, if it's already there fill it up */
++ if( modArr[pcfg->name]->states[pcfg->state] == NULL)
++ {
++ printk("<1>STATE = %d\n",pcfg->state);
++ if( pcfg->state >= MAX_STATE_ID)
++ {
++ printk("<1>Exiting Configuration: State ID too large\n");
++ free_memory();
++ spin_unlock_irqrestore(&config_lock, flags);
++ return -1;
++ }
++ modArr[pcfg->name]->states[pcfg->state] =
++ kmalloc(sizeof(state_entry_t),GFP_KERNEL);
++ if( modArr[pcfg->name]->states[pcfg->state] == NULL)
++ {
++ free_memory();
++ spin_unlock_irqrestore(&config_lock, flags);
++ return -1;
++ }
++ memset( modArr[pcfg->name]->states[pcfg->state], 0x00, sizeof(state_entry_t));
++ }
++ /* Fill up the fields of the state */
++ if( pcfg->led >= MAX_LED_ID)
++ {
++ printk("<1>led = %d\n",pcfg->led);
++ free_memory();
++ spin_unlock_irqrestore(&config_lock, flags);
++ return -1;
++ }
++ modArr[pcfg->name]->states[pcfg->state]->led = pcfg->led;
++ modArr[pcfg->name]->states[pcfg->state]->mode = pcfg->mode;
++ modArr[pcfg->name]->states[pcfg->state]->param = pcfg->param;
++ switch(pcfg->mode)
++ {
++ case 1:
++ modArr[pcfg->name]->states[pcfg->state]->handler = board_led_link_down;
++ break;
++ case 2:
++ case 3:
++ case 5:
++ if( pcfg->mode == 2 )
++ modArr[pcfg->name]->states[pcfg->state]->handler = board_led_activity_on;
++ else if( pcfg->mode == 3)
++ modArr[pcfg->name]->states[pcfg->state]->handler = board_led_activity_off;
++ else
++ modArr[pcfg->name]->states[pcfg->state]->handler = board_led_link_flash;
++ break;
++ case 4:
++ modArr[pcfg->name]->states[pcfg->state]->handler = board_led_link_up;
++ break;
++ default:
++ printk("<1>Exiting Configuration: Unknown LED Mode\n");
++ free_memory();
++ spin_unlock_irqrestore(&config_lock, flags);
++ return -1;
++ }
++ pcfg++;
++ }
++ spin_unlock_irqrestore(&config_lock, flags);
++ return 0;
++}
++
++
++int __init led_init(void)
++{
++
++ /* Clear our memory */
++ memset(modArr,0x00,sizeof(mod_entry_t *)*MAX_MOD_ID);
++ memset(led_arr,0x00,sizeof(led_data_t *)*MAX_LED_ID);
++
++ /* Create spin lock for config data structure */
++ config_lock=SPIN_LOCK_UNLOCKED;
++
++ /* Create directory */
++ led_proc_dir = proc_mkdir("led", NULL);
++ if( led_proc_dir == NULL )
++ goto out;
++
++ /* Create adsl file */
++ led_file = create_proc_entry("led", 0777, led_proc_dir);
++ if( led_file == NULL)
++ goto led_file;
++ led_file->owner = THIS_MODULE;
++ led_file->proc_fops = &led_fops;
++
++ memset( modArr , 0x00 , sizeof(mod_entry_t *) * MAX_MOD_ID);
++ /* Reset the GPIO pins */
++ board_gpio_init();
++
++ /* Register the UART controlled LEDS */
++ uart_led_init();
++ /* Create the usb proc file */
++ avalanche_leds_init();
++ return 0;
++
++ led_file:
++ remove_proc_entry("led",led_proc_dir);
++ out:
++ return 0;
++
++}
++
++void led_exit()
++{
++ remove_proc_entry("led", led_proc_dir);
++}
++
++module_init(led_init);
++module_exit(led_exit);
++
++void register_led_drv( int device , led_reg_t *pInfo)
++{
++ unsigned int flags;
++ struct timer_list *pTimer = NULL;
++
++ spin_lock_irqsave(&config_lock, flags);
++
++ led_arr[device].led = pInfo;
++ if( led_arr[device].led->init != 0x00)
++ led_arr[device].led->init(led_arr[device].led->param);
++ if( led_arr[device].led->offfunc != 0x00)
++ led_arr[device].led->offfunc(led_arr[device].led->param);
++
++ /* Create a timer for blinking */
++ pTimer = kmalloc(sizeof(struct timer_list),GFP_KERNEL);
++ init_timer( pTimer );
++ pTimer->function = led_timer_func;
++ pTimer->data = 0;
++ led_arr[device].pTimer = pTimer;
++ led_arr[device].timer_running = 0;
++
++ spin_unlock_irqrestore(&config_lock, flags);
++
++ return;
++}
++
++void deregister_led_drv( int device)
++{
++ unsigned int flags;
++
++ spin_lock_irqsave(&config_lock, flags);
++ led_arr[device].led = NULL;
++
++ if( led_arr[device].pTimer != NULL)
++ {
++ del_timer(led_arr[device].pTimer);
++ kfree(led_arr[device].pTimer);
++ }
++ spin_unlock_irqrestore(&config_lock, flags);
++
++ return;
++}
++
++EXPORT_SYMBOL_NOVERS(led_operation);
++EXPORT_SYMBOL_NOVERS(register_led_drv);
++EXPORT_SYMBOL_NOVERS(deregister_led_drv);
++
+diff -urN linux.dev/drivers/char/avalanche_led/leds.c linux.dev2/drivers/char/avalanche_led/leds.c
+--- linux.dev/drivers/char/avalanche_led/leds.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev2/drivers/char/avalanche_led/leds.c 2005-10-21 18:03:44.513777000 +0200
+@@ -0,0 +1,133 @@
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <asm/ar7/avalanche_regs.h>
++#include <linux/spinlock.h>
++#include <linux/timer.h>
++#include <linux/sched.h>
++#include <linux/module.h>
++#include <linux/proc_fs.h>
++#include <asm/uaccess.h>
++#include <linux/fs.h>
++
++#include <asm/ar7/ledapp.h>
++
++#if defined(CONFIG_AR5D01) || defined(CONFIG_AR5W01) || defined(CONFIG_AR7)
++
++#define ETH_MASK 0x01
++#define USB_MASK 0x02
++
++static struct proc_dir_entry *usb_file;
++static ssize_t proc_read_usb_fops(struct file *filp,
++ char *buf,size_t count , loff_t *offp);
++struct file_operations usb_fops = {read: proc_read_usb_fops};
++
++typedef struct mod_states{
++ int module;
++ int activity;
++ int linkup;
++ int idle;
++}mod_states_t;
++
++mod_states_t state_arr[] = {
++ { MOD_ETH,DEF_ETH_ACTIVITY,DEF_ETH_LINK_UP,DEF_ETH_IDLE },
++ { MOD_USB,DEF_USB_ACTIVITY,DEF_USB_LINK_UP,DEF_USB_IDLE },
++ { MOD_LAN,DEF_LAN_ACTIVITY,DEF_LAN_LINK_UP,DEF_LAN_IDLE }
++ };
++
++unsigned char device_links = 0; /* Bitmask with the devices that are up */
++
++
++void avalanche_led_activity_pulse(unsigned long device)
++{
++ /* If device link is not up return */
++ if( !(device_links & (unsigned char)(1 << device)))
++ return;
++#ifdef MULTIPLEX_LED
++ led_operation( state_arr[2].module, state_arr[2].activity);
++#else
++ led_operation( state_arr[device].module, state_arr[device].activity);
++#endif
++}
++
++void avalanche_led_link_up( unsigned long device )
++{
++
++ /* If already UP ignore */
++ if( device_links & (unsigned char)(1 << device))
++ return;
++ /* Turn on the bit for the device */
++ device_links |= (unsigned char)(1 << device);
++#ifdef MULTIPLEX_LED
++ led_operation( state_arr[2].module, state_arr[2].linkup);
++#else
++ led_operation( state_arr[device].module, state_arr[device].linkup);
++#endif
++}
++
++void avalanche_led_link_down ( unsigned long device )
++{
++
++ /* If already DOWN ignore */
++ if( !(device_links & (unsigned char)(1 << device)))
++ return;
++
++ /* Turn off the bit for the device */
++ device_links &= ~(unsigned char)(1 << device);
++#ifdef MULTIPLEX_LED
++ /* If no links, then shut the LED off */
++ if(!device_links)
++ led_operation( state_arr[2].module, state_arr[2].idle);
++#else
++ led_operation( state_arr[device].module, state_arr[device].idle);
++#endif
++}
++
++static ssize_t proc_read_usb_fops(struct file *filp,
++ char *buf,size_t count , loff_t *offp)
++{
++ char * pdata = NULL;
++ char line[3];
++ if( *offp != 0 )
++ return 0;
++ pdata = buf;
++ if( device_links & USB_MASK)
++ sprintf(line,"%s\n","1");
++ else
++ sprintf(line,"%s\n","0");
++ copy_to_user(pdata,line,2);
++ *offp = 2;
++ return 2;
++}
++
++
++void avalanche_leds_init(void)
++{
++ /* Create usb link proc file */
++ usb_file = create_proc_entry("avalanche/usb_link", 0444, NULL);
++ if( usb_file == NULL)
++ return;
++ usb_file->owner = THIS_MODULE;
++ usb_file->proc_fops = &usb_fops;
++ return;
++}
++
++EXPORT_SYMBOL(avalanche_led_activity_pulse);
++EXPORT_SYMBOL(avalanche_led_link_up);
++EXPORT_SYMBOL(avalanche_led_link_down);
++
++#else
++/* We make a dummy init routine for the platforms that do not support this led
++ API
++*/
++
++void avalanche_leds_init(void)
++{
++}
++
++#endif
++
++
++
++
++
+diff -urN linux.dev/drivers/char/avalanche_led/uartled.c linux.dev2/drivers/char/avalanche_led/uartled.c
+--- linux.dev/drivers/char/avalanche_led/uartled.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev2/drivers/char/avalanche_led/uartled.c 2005-10-21 18:03:44.529778000 +0200
+@@ -0,0 +1,55 @@
++#include <linux/kernel.h>
++#include <asm/uaccess.h>
++#include <linux/spinlock.h>
++#include <asm/ar7/avalanche_regs.h>
++#include <asm/ar7/ledapp.h>
++
++#define UART_LED_REG (*(volatile unsigned int *)(UARTA_BASE + 0x10))
++
++static spinlock_t device_lock;
++led_reg_t temp1[2];
++
++static void uart_led_on(unsigned long param)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&device_lock,flags);
++ UART_LED_REG &= 0xFFFD;
++ spin_unlock_irqrestore(&device_lock, flags);
++}
++
++static void uart_led_off ( unsigned long param )
++{
++ unsigned int flags = 0x00;
++ spin_lock_irqsave(&device_lock, flags);
++ UART_LED_REG |= 0x02;
++ spin_unlock_irqrestore(&device_lock, flags);
++}
++
++void uart_led_init(void)
++{
++
++#if defined(CONFIG_AR5D01)
++ /* Register led 6 UART Pin 1 */
++ temp1[0].param = 0;
++ temp1[0].init = NULL;
++ temp1[0].onfunc = uart_led_on;
++ temp1[0].offfunc = uart_led_off;
++ register_led_drv( 6 , &temp1[0]);
++#endif
++
++#if defined(CONFIG_AR5W01)
++ /* Register led 8 UART Pin 1 */
++ temp1[0].param = 0;
++ temp1[0].init = NULL;
++ temp1[0].onfunc = uart_led_on;
++ temp1[0].offfunc = uart_led_off;
++ register_led_drv( 8 , &temp1[0]);
++#endif
++
++ /* Initialize the link mask */
++ device_lock = SPIN_LOCK_UNLOCKED;
++
++ return;
++}
++
+diff -urN linux.dev/include/asm-mips/ar7/led_config.h linux.dev2/include/asm-mips/ar7/led_config.h
+--- linux.dev/include/asm-mips/ar7/led_config.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev2/include/asm-mips/ar7/led_config.h 2005-10-21 17:02:25.568327000 +0200
+@@ -0,0 +1,55 @@
++/******************************************************************************
++ * FILE PURPOSE: - LED config Header
++ ******************************************************************************
++ * FILE NAME: led_config.h
++ *
++ * DESCRIPTION: Header file for LED configuration parameters
++ * and data structures
++ *
++ * REVISION HISTORY:
++ * 11 Oct 03 - PSP TII
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++
++#ifndef __LED_CONFIG__
++#define __LED_CONFIG__
++
++/* LED config parameters */
++#define MAX_GPIO_PIN_NUM 64
++#define MAX_GPIOS_PER_STATE 5
++#define MAX_MODULE_ENTRIES 25
++#define MAX_MODULE_INSTANCES 4
++#define MAX_STATE_ENTRIES 25
++#define MAX_LED_ENTRIES 25
++
++
++/* LED modes */
++#define LED_OFF 0
++#define LED_ON 1
++#define LED_ONESHOT_OFF 2
++#define LED_ONESHOT_ON 3
++#define LED_FLASH 4
++#define LED_BLINK_CODE0 5 /*--- param1: on time, param2: blink nr , (param2 > 100 blink off) ---*/
++#define LED_BLINK_CODE1 6
++#define LED_BLINK_CODE2 7
++
++#define NUM_LED_MODES 8
++
++
++
++/* Data structure for LED configuration */
++typedef struct led_config{
++ unsigned char name[80];
++ unsigned int instance;
++ unsigned int state;
++ unsigned int gpio[MAX_GPIOS_PER_STATE];
++ unsigned int mode[MAX_GPIOS_PER_STATE];
++ unsigned int gpio_num;
++ unsigned int param1;
++ unsigned int param2;
++}LED_CONFIG_T;
++
++
++#endif /* __LED_CONFIG__ */
+diff -urN linux.dev/include/asm-mips/ar7/led_hal.h linux.dev2/include/asm-mips/ar7/led_hal.h
+--- linux.dev/include/asm-mips/ar7/led_hal.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev2/include/asm-mips/ar7/led_hal.h 2005-10-21 17:02:25.568327000 +0200
+@@ -0,0 +1,30 @@
++/******************************************************************************
++ * FILE PURPOSE: - LED HAL module Header
++ ******************************************************************************
++ * FILE NAME: led_hal.h
++ *
++ * DESCRIPTION: LED HAL API's.
++ *
++ * REVISION HISTORY:
++ * 11 Oct 03 - PSP TII
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++#ifndef __LED_HAL__
++#define __LED_HAL__
++
++/* Interface prototypes */
++#include "led_config.h"
++
++int avalanche_led_hal_init (int *gpio_off_value, int num_gpio_pins);
++int avalanche_led_config_set (LED_CONFIG_T * led_cfg);
++int avalanche_led_config_get (LED_CONFIG_T *led_cfg,int module_id,int instance, int state);
++void *avalanche_led_register (const char *module_name, int instance_num);
++void avalanche_led_action (void *handle, int state_id);
++void avalanche_led_late_actions(void);
++int avalanche_led_unregister (void *handle);
++void avalanche_led_free_all(void);
++void avalanche_led_hal_exit (void);
++
++#endif /*__LED_HAL__ */
+diff -urN linux.dev/include/asm-mips/ar7/ledapp.h linux.dev2/include/asm-mips/ar7/ledapp.h
+--- linux.dev/include/asm-mips/ar7/ledapp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev2/include/asm-mips/ar7/ledapp.h 2005-10-21 18:03:44.573780750 +0200
+@@ -0,0 +1,59 @@
++#ifndef __LED_APP__
++#define __LED_APP__
++
++#define CONF_FILE "/etc/led.conf"
++#define LED_PROC_FILE "/proc/led_mod/led"
++
++#define CONFIG_LED_MODULE
++
++#define MAX_MOD_ID 25
++#define MAX_STATE_ID 25
++#define MAX_LED_ID 25
++
++#define MOD_ADSL 1
++#define DEF_ADSL_IDLE 1
++#define DEF_ADSL_TRAINING 2
++#define DEF_ADSL_SYNC 3
++#define DEF_ADSL_ACTIVITY 4
++
++#define MOD_WAN 2
++#define DEF_WAN_IDLE 1
++#define DEF_WAN_NEGOTIATE 2
++#define DEF_WAN_SESSION 3
++
++#define MOD_LAN 3
++#define DEF_LAN_IDLE 1
++#define DEF_LAN_LINK_UP 2
++#define DEF_LAN_ACTIVITY 3
++
++#define MOD_WLAN 4
++#define DEF_WLAN_IDLE 1
++#define DEF_WLAN_LINK_UP 2
++#define DEF_WLAN_ACTIVITY 3
++
++#define MOD_USB 5
++#define DEF_USB_IDLE 1
++#define DEF_USB_LINK_UP 2
++#define DEF_USB_ACTIVITY 3
++
++#define MOD_ETH 6
++#define DEF_ETH_IDLE 1
++#define DEF_ETH_LINK_UP 2
++#define DEF_ETH_ACTIVITY 3
++
++typedef struct config_elem{
++ unsigned char name;
++ unsigned char state;
++ unsigned char mode;
++ unsigned char led;
++ int param;
++}config_elem_t;
++
++typedef struct led_reg{
++ unsigned int param;
++ void (*init)(unsigned long param);
++ void (*onfunc)(unsigned long param);
++ void (*offfunc)(unsigned long param);
++}led_reg_t;
++
++#endif
diff --git a/target/linux/ar7-2.4/patches/003-net_driver_cpmac.patch b/target/linux/ar7-2.4/patches/003-net_driver_cpmac.patch
new file mode 100644
index 0000000000..06df07d29f
--- /dev/null
+++ b/target/linux/ar7-2.4/patches/003-net_driver_cpmac.patch
@@ -0,0 +1,13341 @@
+diff -urN linux.old/drivers/net/avalanche_cpmac/cpcommon_cpmac.c linux.dev/drivers/net/avalanche_cpmac/cpcommon_cpmac.c
+--- linux.old/drivers/net/avalanche_cpmac/cpcommon_cpmac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpcommon_cpmac.c 2005-07-12 02:48:41.996601000 +0200
+@@ -0,0 +1,728 @@
++#ifndef _INC_CPCOMMON_C
++#define _INC_CPCOMMON_C
++
++#ifdef _CPHAL_CPMAC
++#include "cpremap_cpmac.c"
++#endif
++
++#ifdef _CPHAL_AAL5
++#include "cpremap_cpaal5.c"
++#endif
++
++#ifdef _CPHAL_CPSAR
++#include "cpremap_cpsar.c"
++#endif
++
++#ifdef _CPHAL_AAL2
++#include "cpremap_cpaal2.c"
++#endif
++
++/**
++@defgroup Common_Config_Params Common Configuration Parameters
++
++This section documents the configuration parameters that are valid across
++all CPHAL devices.
++@{
++*/
++/** This is the debug level. The field is bit defined, such that the user
++should set to 1 all the bits corresponding to desired debug outputs. The following
++are the meanings for each debug bit:
++- bit0 (LSB): CPHAL Function Trace
++- b1 : OS Function call trace
++- b2 : Critical section entry/exit
++- b3 : Memory allocation/destruction
++- b4 : Detailed information in Rx path
++- b5 : Detailed information in Tx path
++- b6 : Extended error information
++- b7 : General info
++*/
++static const char pszDebug[] = "debug";
++/** CPU Frequency. */
++/*static const char pszCpuFreq[] = "CpuFreq";*/ /*MJH-030403*/
++/** Base address for the module. */
++static const char pszBase[] = "base";
++/** Reset bit for the module. */
++static const char pszResetBit[] = "reset_bit";
++/** Reset base address for the module. */
++static const char pszResetBase[] = "ResetBase";
++/** Interrupt line for the module. */
++static const char pszIntLine[] = "int_line";
++/** VLYNQ offset for the module. Disregard if not using VLYNQ. */
++static const char pszOffset[] = "offset";
++/** The OS may "Get" this parameter, which is a pointer
++ to a character string that indicates the version of CPHAL. */
++static const char pszVer[] = "Version";
++/*@}*/
++
++/**
++@defgroup Common_Control_Params Common Keys for [os]Control()
++
++This section documents the keys used with the OS @c Control() interface that
++are required by CPHAL devices.
++
++@{
++*/
++/** Used to wait for an integer number of clock ticks, given as an integer
++ pointer in the @p Value parameter. No actions are defined. */
++static const char pszSleep[] = "Sleep";
++/** Requests the OS to flush it's IO buffers. No actions are defined. */
++static const char pszSioFlush[] = "SioFlush";
++/*@}*/
++
++static const char pszStateChange[] = "StateChange";
++static const char pszStatus[] = "Status";
++
++static const char pszGET[] = "Get";
++static const char pszSET[] = "Set";
++static const char pszCLEAR[] = "Clear";
++static const char pszNULL[] = "";
++static const char pszLocator[] = "Locator";
++static const char pszOff[] = "Off";
++static const char pszOn[] = "On";
++static const char hcMaxFrags[] = "MaxFrags";
++
++#ifdef _CPHAL_CPMAC
++
++/* New method for string constants */
++const char hcClear[] = "Clear";
++const char hcGet[] = "Get";
++const char hcSet[] = "Set";
++
++const char hcTick[] = "Tick";
++
++static const CONTROL_KEY KeyCommon[] =
++ {
++ {"" , enCommonStart},
++ {pszStatus , enStatus},
++ {pszOff , enOff},
++ {pszOn , enOn},
++ {pszDebug , enDebug},
++ {hcCpuFrequency , enCpuFreq}, /*MJH~030403*/
++ {"" , enCommonEnd}
++ };
++#endif
++
++/**
++@defgroup Common_Statistics Statistics
++
++A broad array of module statistics is available. Statistics values are accessed
++through the @c Control() interface of the CPHAL. There are 5 different levels
++of statistics, each of which correspond to a unique set of data. Furthermore,
++certain statistics data is indexed by using a channel number and Tx queue number.
++The following is a brief description of each statistics level, along with the
++indexes used for the level:
++
++- Level 0: Hardware Statistics (index with channel)
++- Level 1: CPHAL Software Statistics (channel, queue)
++- Level 2: CPHAL Flags (channel, queue)
++- Level 3: CPHAL Channel Configuration (channel)
++- Level 4: CPHAL General Configuration (no index)
++
++The caller requests statistics information by providing a Key string to the
++@c Control() API in the following format: "Stats;[Level #];[Ch #];[Queue #]".
++The only valid Action parameter for statistics usage is "Get".
++
++Code Examples:
++@code
++unsigned int *StatsData;
++
++# Get Level 0 stats for Channel 1
++HalFunc->Control(OsDev->HalDev, "Stats;0;1", "Get", &StatsData);
++
++# Get Level 2 stats for Channel 0, Queue 0
++HalFunc->Control(OsDev->HalDev, "Stats;2;0;0", "Get", &StatsData);
++
++# Get Level 4 stats
++HalFunc->Control(OsDev->HalDev, "Stats;4", "Get", &StatsData);
++@endcode
++
++The information returned in the Value parameter of @c Control() is an
++array of pointers to strings. The pointers are arranged in pairs.
++The first pointer is a pointer to a name string for a particular statistic.
++The next pointer is a pointer to a string containing the representation of
++the integer statistic value corresponding to the first pointer. This is followed
++by another pair of pointers, and so on, until a NULL pointer is encountered. The
++following is example code for processing the statistics data. Note that the OS
++is responsible for freeing the memory passed back through the Value parameter of
++@c Control().
++
++@code
++unsigned int *StatsData;
++
++# Get Level 0 stats for Channel 1
++HalFunc->Control(OsDev->HalDev, "Stats;0;1", "Get", &StatsData);
++
++# output Statistics data
++PrintStats(StatsData);
++
++# the upper layer is responsible for freeing stats info
++free(&StatsPtr);
++
++...
++
++void PrintStats(unsigned int *StatsPtr)
++ {
++ while(*StatsPtr)
++ {
++ printf("%20s:", (char *)*StatsPtr);
++ StatsPtr++;
++ printf("%11s\n", (char *)*StatsPtr);
++ StatsPtr++;
++ }
++ MySioFlush();
++ }
++@endcode
++
++Within each statistics level, there are several statistics defined. The statistics that
++are common to every CPPI module are listed below. In addition, each module may define
++extra statistics in each level, which will be documented within the module-specific
++documentation appendices.
++
++- Level 0 Statistics
++ - All level 0 statistics are module-specific.
++- Level 1 Statistics (CPHAL Software Statistics)
++ - DmaLenErrors: Incremented when the port DMA's more data than expected (per channel). (AAL5 Only)
++ - TxMisQCnt: Incremented when host queues a packet for transmission as the port finishes
++transmitting the previous last packet in the queue (per channel and queue).
++ - RxMisQCnt: Incremented when host queues adds buffers to a queue as the port finished the
++reception of the previous last packet in the queue (per channel).
++ - TxEOQCnt: Number of times the port has reached the end of the transmit queue (per channel and queue).
++ - RxEOQCnt: Number of times the port has reached the end of the receive queue (per channel).
++ - RxPacketsServiced: Number of received packets (per channel).
++ - TxPacketsServiced: Number of transmitted packets (per channel and queue).
++ - RxMaxServiced: Maximum number of packets that the CPHAL receive interrupt has serviced at a time (per channel).
++ - TxMaxServiced: Maximum number of packets that the CPHAL transmit interrupt has serviced at a time (per channel and queue).
++ - RxTotal: Total number of received packets, all channels.
++ - TxTotal: Total number of transmitted packets, all channels and queues.
++- Level 2 Statistics (CPHAL Flags)
++ - RcbPool: Pointer to receive descriptor pool (per channel).
++ - RxActQueueCount: Number of buffers currently available for receive (per channel).
++ - RxActQueueHead: Pointer to first buffer in receive queue (per channel).
++ - RxActQueueTail: Pointer to last buffer in receive queue (per channel).
++ - RxActive: 0 if inactive (no buffers available), or 1 if active (buffers available).
++ - RcbStart: Pointer to block of receive descriptors.
++ - RxTeardownPending: 1 if Rx teardown is pending but incomplete, 0 otherwise.
++ - TcbPool: Pointer to transmit descriptor pool (per channel and queue).
++ - TxActQueueCount: Number of buffers currently queued to be transmitted (per channel and queue).
++ - TxActQueueHead: Pointer to first buffer in transmit queue (per channel and queue).
++ - TxActQueueTail: Pointer to last buffer in transmit queue (per channel and queue).
++ - TxActive: 0 if inactive (no buffers to send), or 1 if active (buffers queued to send).
++ - TcbStart: Pointer to block of transmit descriptors.
++ - TxTeardownPending: 1 if Tx teardown is pending but incomplete, 0 otherwise.
++- Level 3 Statistics (CPHAL Channel Configuration)
++ - RxBufSize: Rx buffer size.
++ - RxBufferOffset: Rx buffer offset.
++ - RxNumBuffers: Number of Rx buffers.
++ - RxServiceMax: Maximum number of receive packets to service at a time.
++ - TxNumBuffers: Number of Tx buffer descriptors.
++ - TxNumQueues: Number of Tx queues to use.
++ - TxServiceMax: Maximum number of transmit packets to service at a time.
++- Level 4 Statistics (CPHAL General Configuration)
++ - Base Address: Base address of the module.
++ - Offset (VLYNQ): VLYNQ relative module offset.
++ - Interrupt Line: Interrupt number.
++ - Debug: Debug flag, 1 to enable debug.
++ - Inst: Instance number.
++*/
++
++/*
++ Data Type 0 = int display
++ Data Type 1 = hex display
++ Data Type 2 = channel structure, int display
++ Data Type 3 = queue index and int display
++ Data Type 4 = queue index and hex display
++*/
++#if (defined(_CPHAL_AAL5) || defined(_CPHAL_CPMAC)) /* +GSG 030307 */
++static STATS_TABLE StatsTable0[] =
++ {
++#ifdef _CPHAL_AAL5
++ /* Name , Data Ptr, Data Type */
++ {"Crc Errors", 0, 0},
++ {"Len Errors", 0, 0},
++ {"Abort Errors", 0, 0},
++ {"Starv Errors", 0, 0}
++#endif
++#ifdef _CPHAL_CPMAC
++ {"Rx Good Frames", 0, 0}
++#endif
++ };
++
++static STATS_TABLE StatsTable1[] =
++ {
++ /* Name , Data Ptr, Data Type */
++ {"DmaLenErrors", 0, 0},
++ {"TxMisQCnt", 0, 3},
++ {"RxMisQCnt", 0, 0},
++ {"TxEOQCnt", 0, 3},
++ {"RxEOQCnt", 0, 0},
++ {"RxPacketsServiced", 0, 0},
++ {"TxPacketsServiced", 0, 3},
++ {"RxMaxServiced", 0, 0},
++ {"TxMaxServiced", 0, 3},
++ {"RxTotal", 0, 0},
++ {"TxTotal", 0, 0},
++ };
++
++static STATS_TABLE StatsTable2[] =
++ {
++ /* Name , Data Ptr, Data Type */
++ {"RcbPool", 0, 1},
++ {"RxActQueueCount", 0, 0},
++ {"RxActQueueHead", 0, 1},
++ {"RxActQueueTail", 0, 1},
++ {"RxActive", 0, 0},
++ {"RcbStart", 0, 1},
++ {"RxTeardownPending", 0, 0},
++ {"TcbPool", 0, 4},
++ {"TxActQueueCount", 0, 3},
++ {"TxActQueueHead", 0, 4},
++ {"TxActQueueTail", 0, 4},
++ {"TxActive", 0, 3},
++ {"TcbStart", 0, 4},
++ {"TxTeardownPending", 0, 0}
++ };
++
++static STATS_TABLE StatsTable3[] =
++ {
++ /* Name , Data Ptr, Data Type */
++ {"RxBufSize", 0, 2},
++ {"RxBufferOffset", 0, 2},
++ {"RxNumBuffers", 0, 2},
++ {"RxServiceMax", 0, 2},
++ {"TxNumBuffers", 0, 2},
++ {"TxNumQueues", 0, 2},
++ {"TxServiceMax", 0, 2},
++#ifdef _CPHAL_AAL5
++ {"CpcsUU", 0, 2},
++ {"Gfc", 0, 2},
++ {"Clp", 0, 2},
++ {"Pti", 0, 2},
++ {"DaMask", 0, 2},
++ {"Priority", 0, 2},
++ {"PktType", 0, 2},
++ {"Vci", 0, 2},
++ {"Vpi", 0, 2},
++ {"CellRate", 0, 2},
++ {"QosType", 0, 2},
++ {"Mbs", 0, 2},
++ {"Pcr", 0, 2}
++#endif
++ };
++
++static STATS_TABLE StatsTable4[] =
++ {
++ {"Base Address", 0, 1},
++ {"Offset (VLYNQ)", 0, 0},
++ {"Interrupt Line", 0, 0},
++ {"Debug", 0, 0},
++ {"Instance", 0, 0},
++#ifdef _CPHAL_AAL5
++ {"UniNni", 0, 0}
++#endif
++ };
++
++static STATS_DB StatsDb[] =
++ {
++ {(sizeof(StatsTable0)/sizeof(STATS_TABLE)), StatsTable0},
++ {(sizeof(StatsTable1)/sizeof(STATS_TABLE)), StatsTable1},
++ {(sizeof(StatsTable2)/sizeof(STATS_TABLE)), StatsTable2},
++ {(sizeof(StatsTable3)/sizeof(STATS_TABLE)), StatsTable3},
++ {(sizeof(StatsTable4)/sizeof(STATS_TABLE)), StatsTable4}
++ };
++#endif /* +GSG 030307 */
++
++#ifdef _CPHAL_CPMAC /* +RC 3.02 */
++static void resetWait(HAL_DEVICE *HalDev)
++ { /*+RC3.02*/
++ const int TickReset=64;
++ osfuncSleep((int*)&TickReset);
++ } /*+RC3.02*/
++#endif /* +RC 3.02 */
++
++/* I only define the reset base function for the modules
++ that can perform a reset. The AAL5 and AAL2 modules
++ do not perform a reset, that is done by the shared module
++ CPSAR */
++#if defined(_CPHAL_CPSAR) || defined(_CPHAL_CPMAC) || defined(_CPHAL_VDMAVT)
++/*
++ * Determines the reset register address to be used for a particular device.
++ * It will search the current device entry for Locator information. If the
++ * device is a root device, there will be no Locator information, and the
++ * function will find and return the root reset register. If a Locator value
++ * is found, the function will search each VLYNQ device entry in the system
++ * looking for a matching Locator. Once it finds a VLYNQ device entry with
++ * a matching Locator, it will extract the "ResetBase" parameter from that
++ * VLYNQ device entry (thus every VLYNQ entry must have the ResetBase parameter).
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ * @param ResetBase Pointer to integer address of reset register.
++ *
++ * @return 0 OK, Non-zero not OK
++ */
++static int ResetBaseGet(HAL_DEVICE *HalDev, bit32u *ResetBase)
++ {
++ char *DeviceInfo = HalDev->DeviceInfo;
++ char *MyLocator, *NextLocator;
++ int Inst=1;
++ bit32u error_code;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpcommon]ResetBaseGet(HalDev:%08x, ResetBase:%08x)\n", (bit32u)HalDev, ResetBase);
++ osfuncSioFlush();
++ }
++#endif
++
++ error_code = HalDev->OsFunc->DeviceFindParmValue(DeviceInfo, "Locator", &MyLocator);
++ if (error_code)
++ {
++ /* if no Locator value, device is on the root, so get the "reset" device */
++ error_code = HalDev->OsFunc->DeviceFindInfo(0, "reset", &DeviceInfo);
++ if (error_code)
++ {
++ return(EC_VAL_DEVICE_NOT_FOUND);
++ }
++
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, "base", ResetBase);
++ if (error_code)
++ {
++ return(EC_VAL_BASE_ADDR_NOT_FOUND);
++ }
++
++ *ResetBase = ((bit32u)PhysToVirtNoCache(*ResetBase));
++
++ /* found base address for root device, so we're done */
++ return (EC_NO_ERRORS);
++ }
++ else
++ {
++ /* we have a Locator value, so the device is remote */
++
++ /* Find a vlynq device with a matching locator value */
++ while ((HalDev->OsFunc->DeviceFindInfo(Inst, "vlynq", &DeviceInfo)) == EC_NO_ERRORS)
++ {
++ error_code = HalDev->OsFunc->DeviceFindParmValue(DeviceInfo, "Locator", &NextLocator);
++ if (error_code)
++ {
++ /* no Locator value for this VLYNQ, so move on */
++ continue;
++ }
++ if (HalDev->OsFunc->Strcmpi(MyLocator, NextLocator)==0)
++ {
++ /* we have found a VLYNQ with a matching Locator, so extract the ResetBase */
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, "ResetBase", ResetBase);
++ if (error_code)
++ {
++ return(EC_VAL_BASE_ADDR_NOT_FOUND);
++ }
++ *ResetBase = ((bit32u)PhysToVirtNoCache(*ResetBase));
++
++ /* found base address for root device, so we're done */
++ return (EC_NO_ERRORS);
++ }
++ Inst++;
++ } /* while */
++ } /* else */
++
++ return (EC_NO_ERRORS);
++ }
++#endif
++
++#ifndef _CPHAL_AAL2 /* + RC 3.02 */
++static bit32u ConfigGetCommon(HAL_DEVICE *HalDev)
++ {
++ bit32u ParmValue;
++ bit32 error_code;
++ char *DeviceInfo = HalDev->DeviceInfo;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpcommon]ConfigGetCommon(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszBase, &ParmValue);
++ if (error_code)
++ {
++ return(EC_FUNC_HAL_INIT|EC_VAL_BASE_ADDR_NOT_FOUND);
++ }
++ HalDev->dev_base = ((bit32u)PhysToVirtNoCache(ParmValue));
++
++#ifndef _CPHAL_AAL5
++#ifndef _CPHAL_AAL2
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszResetBit, &ParmValue);
++ if(error_code)
++ {
++ return(EC_FUNC_HAL_INIT|EC_VAL_RESET_BIT_NOT_FOUND);
++ }
++ HalDev->ResetBit = ParmValue;
++
++ /* Get reset base address */
++ error_code = ResetBaseGet(HalDev, &ParmValue);
++ if (error_code)
++ return(EC_FUNC_HAL_INIT|EC_VAL_RESET_BASE_NOT_FOUND);
++ HalDev->ResetBase = ParmValue;
++#endif
++#endif
++
++#ifndef _CPHAL_CPSAR
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszIntLine,&ParmValue);
++ if (error_code)
++ {
++ return(EC_FUNC_HAL_INIT|EC_VAL_INTERRUPT_NOT_FOUND);
++ }
++ HalDev->interrupt = ParmValue;
++#endif
++
++ /* only look for the offset if there is a Locator field, which indicates that
++ the module is a VLYNQ module */
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszLocator,&ParmValue);
++ if (!error_code)
++ {
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszOffset,&ParmValue);
++ if (error_code)
++ {
++ return(EC_FUNC_HAL_INIT|EC_VAL_OFFSET_NOT_FOUND);
++ }
++ HalDev->offset = ParmValue;
++ }
++ else
++ HalDev->offset = 0;
++
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszDebug, &ParmValue);
++ if (!error_code) HalDev->debug = ParmValue;
++
++ return (EC_NO_ERRORS);
++ }
++#endif /* +RC 3.02 */
++
++#ifdef _CPHAL_CPMAC /* +RC 3.02 */
++static void StatsInit(HAL_DEVICE *HalDev) /* +() RC3.02 */
++ {
++ /* even though these statistics may be for multiple channels and
++ queues, i need only configure the pointer to the beginning
++ of the array, and I can index from there if necessary */
++
++#ifdef _CPHAL_AAL5
++ StatsTable0[0].StatPtr = &HalDev->Stats.CrcErrors[0];
++ StatsTable0[1].StatPtr = &HalDev->Stats.LenErrors[0];
++ StatsTable0[2].StatPtr = &HalDev->Stats.AbortErrors[0];
++ StatsTable0[3].StatPtr = &HalDev->Stats.StarvErrors[0];
++
++ StatsTable1[0].StatPtr = &HalDev->Stats.DmaLenErrors[0];
++ StatsTable1[1].StatPtr = &HalDev->Stats.TxMisQCnt[0][0];
++ StatsTable1[2].StatPtr = &HalDev->Stats.RxMisQCnt[0];
++ StatsTable1[3].StatPtr = &HalDev->Stats.TxEOQCnt[0][0];
++ StatsTable1[4].StatPtr = &HalDev->Stats.RxEOQCnt[0];
++ StatsTable1[5].StatPtr = &HalDev->Stats.RxPacketsServiced[0];
++ StatsTable1[6].StatPtr = &HalDev->Stats.TxPacketsServiced[0][0];
++ StatsTable1[7].StatPtr = &HalDev->Stats.RxMaxServiced;
++ StatsTable1[8].StatPtr = &HalDev->Stats.TxMaxServiced[0][0];
++ StatsTable1[9].StatPtr = &HalDev->Stats.RxTotal;
++ StatsTable1[10].StatPtr = &HalDev->Stats.TxTotal;
++#endif
++
++#if (defined(_CPHAL_AAL5) || defined(_CPHAL_CPMAC))
++ StatsTable2[0].StatPtr = (bit32u *)&HalDev->RcbPool[0];
++ StatsTable2[1].StatPtr = &HalDev->RxActQueueCount[0];
++ StatsTable2[2].StatPtr = (bit32u *)&HalDev->RxActQueueHead[0];
++ StatsTable2[3].StatPtr = (bit32u *)&HalDev->RxActQueueTail[0];
++ StatsTable2[4].StatPtr = &HalDev->RxActive[0];
++ StatsTable2[5].StatPtr = (bit32u *)&HalDev->RcbStart[0];
++ StatsTable2[6].StatPtr = &HalDev->RxTeardownPending[0];
++ StatsTable2[7].StatPtr = (bit32u *)&HalDev->TcbPool[0][0];
++ StatsTable2[8].StatPtr = &HalDev->TxActQueueCount[0][0];
++ StatsTable2[9].StatPtr = (bit32u *)&HalDev->TxActQueueHead[0][0];
++ StatsTable2[10].StatPtr = (bit32u *)&HalDev->TxActQueueTail[0][0];
++ StatsTable2[11].StatPtr = &HalDev->TxActive[0][0];
++ StatsTable2[12].StatPtr = (bit32u *)&HalDev->TcbStart[0][0];
++ StatsTable2[13].StatPtr = &HalDev->TxTeardownPending[0];
++
++ StatsTable3[0].StatPtr = &HalDev->ChData[0].RxBufSize;
++ StatsTable3[1].StatPtr = &HalDev->ChData[0].RxBufferOffset;
++ StatsTable3[2].StatPtr = &HalDev->ChData[0].RxNumBuffers;
++ StatsTable3[3].StatPtr = &HalDev->ChData[0].RxServiceMax;
++ StatsTable3[4].StatPtr = &HalDev->ChData[0].TxNumBuffers;
++ StatsTable3[5].StatPtr = &HalDev->ChData[0].TxNumQueues;
++ StatsTable3[6].StatPtr = &HalDev->ChData[0].TxServiceMax;
++#ifdef _CPHAL_AAL5
++ StatsTable3[7].StatPtr = &HalDev->ChData[0].CpcsUU;
++ StatsTable3[8].StatPtr = &HalDev->ChData[0].Gfc;
++ StatsTable3[9].StatPtr = &HalDev->ChData[0].Clp;
++ StatsTable3[10].StatPtr = &HalDev->ChData[0].Pti;
++ StatsTable3[11].StatPtr = &HalDev->ChData[0].DaMask;
++ StatsTable3[12].StatPtr = &HalDev->ChData[0].Priority;
++ StatsTable3[13].StatPtr = &HalDev->ChData[0].PktType;
++ StatsTable3[14].StatPtr = &HalDev->ChData[0].Vci;
++ StatsTable3[15].StatPtr = &HalDev->ChData[0].Vpi;
++ StatsTable3[16].StatPtr = &HalDev->ChData[0].TxVc_CellRate;
++ StatsTable3[17].StatPtr = &HalDev->ChData[0].TxVc_QosType;
++ StatsTable3[18].StatPtr = &HalDev->ChData[0].TxVc_Mbs;
++ StatsTable3[19].StatPtr = &HalDev->ChData[0].TxVc_Pcr;
++#endif
++#endif
++
++ StatsTable4[0].StatPtr = &HalDev->dev_base;
++ StatsTable4[1].StatPtr = &HalDev->offset;
++ StatsTable4[2].StatPtr = &HalDev->interrupt;
++ StatsTable4[3].StatPtr = &HalDev->debug;
++ StatsTable4[4].StatPtr = &HalDev->Inst;
++ }
++#endif /* +RC 3.02 */
++
++#ifndef _CPHAL_CPSAR /* +RC 3.02 */
++#ifndef _CPHAL_AAL2 /* +RC 3.02 */
++/*
++ * Returns statistics information.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ *
++ * @return 0
++ */
++static int StatsGet(HAL_DEVICE *HalDev, void **StatPtr, int Index, int Ch, int Queue)
++ {
++ int Size;
++ bit32u *AddrPtr;
++ char *DataPtr;
++ STATS_TABLE *StatsTable;
++ int i, NumberOfStats;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpcommon]StatsGet(HalDev:%08x, StatPtr:%08x)\n",
++ (bit32u)HalDev, (bit32u)StatPtr);
++ osfuncSioFlush();
++ }
++#endif
++
++ StatsTable = StatsDb[Index].StatTable;
++ NumberOfStats = StatsDb[Index].NumberOfStats;
++
++ Size = sizeof(bit32u)*((NumberOfStats*2)+1);
++ Size += (NumberOfStats*11);
++ *StatPtr = (bit32u *)HalDev->OsFunc->Malloc(Size);
++
++ AddrPtr = (bit32u *) *StatPtr;
++ DataPtr = (char *)AddrPtr;
++ DataPtr += sizeof(bit32u)*((NumberOfStats*2)+1);
++
++ for (i=0; i<NumberOfStats; i++)
++ {
++ *AddrPtr++ = (bit32u)StatsTable[i].StatName;
++ *AddrPtr++ = (bit32u)DataPtr;
++ if (&StatsTable[i].StatPtr[Ch] != 0)
++ {
++ switch(StatsTable[i].DataType)
++ {
++ case 0:
++ HalDev->OsFunc->Sprintf(DataPtr, "%d", (bit32u *)StatsTable[i].StatPtr[Ch]);
++ break;
++ case 1:
++ HalDev->OsFunc->Sprintf(DataPtr, "0x%x", (bit32u *)StatsTable[i].StatPtr[Ch]);
++ break;
++ case 2:
++ HalDev->OsFunc->Sprintf(DataPtr, "%d", *((bit32u *)StatsTable[i].StatPtr + (Ch * (sizeof(CHANNEL_INFO)/4))));
++ break;
++ case 3:
++ HalDev->OsFunc->Sprintf(DataPtr, "%d", *((bit32u *)StatsTable[i].StatPtr + (Ch*MAX_QUEUE)+Queue));
++ break;
++ case 4:
++ HalDev->OsFunc->Sprintf(DataPtr, "0x%x", *((bit32u *)StatsTable[i].StatPtr + (Ch*MAX_QUEUE)+Queue));
++ break;
++ default:
++ /* invalid data type, due to CPHAL programming error */
++ break;
++ }
++ }
++ else
++ {
++ /* invalid statistics pointer, probably was not initialized */
++ }
++ DataPtr += HalDev->OsFunc->Strlen(DataPtr) + 1;
++ }
++
++ *AddrPtr = (bit32u) 0;
++
++ return (EC_NO_ERRORS);
++ }
++#endif /* +RC 3.02 */
++#endif /* +RC 3.02 */
++
++#ifdef _CPHAL_CPMAC
++static void gpioFunctional(int base, int bit)
++ { /*+RC3.02*/
++ bit32u GpioEnr = base + 0xC;
++ /* To make functional, set to zero */
++ *(volatile bit32u *)(GpioEnr) &= ~(1 << bit); /*+RC3.02*/
++ } /*+RC3.02*/
++
++
++/*+RC3.02*/
++/* Common function, Checks to see if GPIO should be in functional mode */
++static void gpioCheck(HAL_DEVICE *HalDev, void *moduleDeviceInfo)
++ { /*+RC3.02*/
++ int rc;
++ void *DeviceInfo;
++ char *pszMuxBits;
++ char pszMuxBit[20];
++ char *pszTmp;
++ char szMuxBit[20];
++ char *ptr;
++ int base;
++ int reset_bit;
++ int bit;
++ OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++
++ rc = OsFunc->DeviceFindParmValue(moduleDeviceInfo, "gpio_mux",&pszTmp);
++ if(rc) return;
++ /* gpio entry found, get GPIO register info and make functional */
++
++ /* temp copy until FinParmValue fixed */
++ ptr = &szMuxBit[0];
++ while ((*ptr++ = *pszTmp++));
++
++ pszMuxBits = &szMuxBit[0];
++
++ rc = OsFunc->DeviceFindInfo(0,"gpio",&DeviceInfo);
++ if(rc) return;
++
++ rc = OsFunc->DeviceFindParmUint(DeviceInfo, "base",&base);
++ if(rc) return;
++
++ rc = OsFunc->DeviceFindParmUint(DeviceInfo, "reset_bit",&reset_bit);
++ if(rc) return;
++
++ /* If GPIO still in reset, then exit */
++ if((VOLATILE32(HalDev->ResetBase) & (1 << reset_bit)) == 0)
++ return;
++ /* format for gpio_mux is gpio_mux = <int>;<int>;<int>...*/
++ while (*pszMuxBits)
++ {
++ pszTmp = &pszMuxBit[0];
++ if(*pszMuxBits == ';') pszMuxBits++;
++ while ((*pszMuxBits != ';') && (*pszMuxBits != '\0'))
++ {
++ osfuncSioFlush();
++ /*If value not a number, skip */
++ if((*pszMuxBits < '0') || (*pszMuxBits > '9'))
++ pszMuxBits++;
++ else
++ *pszTmp++ = *pszMuxBits++;
++ }
++ *pszTmp = '\0';
++ bit = OsFunc->Strtoul(pszMuxBit, &pszTmp, 10);
++ gpioFunctional(base, bit);
++ resetWait(HalDev); /* not sure if this is needed */
++ }
++ } /*+RC3.02*/
++#endif /* CPMAC */
++
++#ifdef _CPHAL_AAL5
++const char hcSarFrequency[] = "SarFreq";
++#endif
++
++#endif /* _INC */
+diff -urN linux.old/drivers/net/avalanche_cpmac/cpcommon_cpmac.h linux.dev/drivers/net/avalanche_cpmac/cpcommon_cpmac.h
+--- linux.old/drivers/net/avalanche_cpmac/cpcommon_cpmac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpcommon_cpmac.h 2005-07-12 02:48:41.996601000 +0200
+@@ -0,0 +1,79 @@
++#ifndef _INC_CPCOMMON_H
++#define _INC_CPCOMMON_H
++
++#define VOLATILE32(addr) (*(volatile bit32u *)(addr))
++#ifndef dbgPrintf
++#define dbgPrintf HalDev->OsFunc->Printf
++#endif
++
++#define ChannelUpdate(Field) if(HalChn->Field != 0xFFFFFFFF) HalDev->ChData[Ch].Field = HalChn->Field
++
++#define DBG(level) (HalDev->debug & (1<<(level)))
++/*
++#define DBG0() DBG(0)
++#define DBG1() DBG(1)
++#define DBG2() DBG(2)
++#define DBG3() DBG(3)
++#define DBG4() DBG(4)
++#define DBG5() DBG(5)
++#define DBG6() DBG(6)
++#define DBG7() DBG(7)
++*/
++
++/*
++ * List of defined actions for use with Control().
++ */
++typedef enum
++ {
++ enGET=0, /**< Get the value associated with a key */
++ enSET, /**< Set the value associates with a key */
++ enCLEAR, /**<Clear the value */
++ enNULL /**< No data action, used to initiate a service or send a message */
++ }ACTION;
++
++/*
++ * Enumerated hardware states.
++ */
++typedef enum
++ {
++ enConnected=1, enDevFound, enInitialized, enOpened
++ }DEVICE_STATE;
++
++typedef enum
++ {
++ enCommonStart=0,
++ /* General */
++ enOff, enOn, enDebug,
++ /* Module General */
++ enCpuFreq,
++ enStatus,
++ enCommonEnd
++ }COMMON_KEY;
++
++typedef struct
++ {
++ const char *strKey;
++ int enKey;
++ }CONTROL_KEY;
++
++typedef struct
++ {
++ char *StatName;
++ unsigned int *StatPtr;
++ int DataType; /* 0: int, 1: hex int, 2:channel data */
++ }STATS_TABLE;
++
++typedef struct
++ {
++ int NumberOfStats;
++ STATS_TABLE *StatTable;
++ }STATS_DB;
++
++#define osfuncSioFlush() HalDev->OsFunc->Control(HalDev->OsDev,"SioFlush",pszNULL,0)
++#define osfuncSleep(Ticks) HalDev->OsFunc->Control(HalDev->OsDev,pszSleep,pszNULL,Ticks)
++#define osfuncStateChange() HalDev->OsFunc->Control(HalDev->OsDev,pszStateChange,pszNULL,0)
++
++#define CHANNEL_NAMES {"Ch0","Ch1","Ch2","Ch3","Ch4","Ch5","Ch6","Ch7","Ch8","Ch9","Ch10","Ch11","Ch12","Ch13","Ch14","Ch15"}
++
++#endif
++
+diff -urN linux.old/drivers/net/avalanche_cpmac/cpmac.c linux.dev/drivers/net/avalanche_cpmac/cpmac.c
+--- linux.old/drivers/net/avalanche_cpmac/cpmac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpmac.c 2005-07-22 01:03:12.609318544 +0200
+@@ -0,0 +1,2504 @@
++/******************************************************************************
++ * FILE PURPOSE: CPMAC Linux Network Device Driver Source
++ ******************************************************************************
++ * FILE NAME: cpmac.c
++ *
++ * DESCRIPTION: CPMAC Network Device Driver Source
++ *
++ * REVISION HISTORY:
++ *
++ * Date Description Author
++ *-----------------------------------------------------------------------------
++ * 27 Nov 2002 Initial Creation Suraj S Iyer
++ * 09 Jun 2003 Updates for GA Suraj S Iyer
++ * 30 Sep 2003 Updates for LED, Reset stats Suraj S Iyer
++ *
++ * (C) Copyright 2003, Texas Instruments, Inc
++ *******************************************************************************/
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/proc_fs.h>
++#include <linux/ioport.h>
++#include <asm/io.h>
++
++#include <linux/skbuff.h>
++
++#include <asm/mips-boards/prom.h>
++#include <linux/string.h>
++#include <asm/uaccess.h>
++#include <linux/config.h>
++#include <asm/ar7/if_port.h>
++
++extern void build_psp_config(void);
++extern void psp_config_cleanup(void);
++
++#include "cpmacHalLx.h"
++#include "cpmac.h"
++
++static struct net_device *last_cpmac_device = NULL;
++static int cpmac_devices_installed = 0;
++
++void xdump( u_char* cp, int length, char* prefix );
++
++unsigned int cpmac_cpu_freq = 0;
++
++char cpmac_version[] = "1.5";
++
++char l3_align_array[] = {0x02, 0x01, 0x00, 0x03};
++#define L3_ALIGN(i) l3_align_array[i]
++
++char add_for_4byte_align[] = {0x04, 0x03, 0x02, 0x05};
++#define ADD_FOR_4BYTE_ALIGN(i) add_for_4byte_align[i]
++
++
++#define TPID 0x8100
++#define IS_802_1Q_FRAME(byte_ptr) (*(unsigned short*)byte_ptr == TPID)
++#define TPID_START_OFFSET 12
++#define TCI_START_OFFSET 14
++#define TCI_LENGTH 2
++#define TPID_LENGTH 2
++#define TPID_END_OFFSET (TPID_START_OFFSET + TPID_LENGTH)
++#define TCI_END_OFFSET (TCI_START_OFFSET + TCI_LENGTH)
++#define IS_VALID_VLAN_ID(byte_ptr) ((*(unsigned short*)byte_ptr) && 0xfff != 0)
++#define MAX_CLASSES 8
++#define MAX_USER_PRIORITY 8
++#define CONTROL_802_1Q_SIZE (TCI_LENGTH + TPID_LENGTH)
++
++unsigned char user_priority_to_traffic_class_map[MAX_CLASSES][MAX_USER_PRIORITY] =
++{
++ {0, 0, 0, 1, 1, 1, 1, 2},
++ {0, 0, 0, 0, 0, 0, 0, 0},
++ {0, 0, 0, 0, 0, 0, 0, 1},
++ {0, 0, 0, 1, 1, 2, 2, 3},
++ {0, 1, 1, 2, 2, 3, 3, 4},
++ {0, 1, 1, 2, 3, 4, 4, 5},
++ {0, 1, 2, 3, 4, 5, 5, 6},
++ {0, 1, 2, 3, 4, 5, 6, 7}
++};
++
++#define GET_802_1P_CHAN(x,y) user_priority_to_traffic_class_map[x][(y & 0xe0)]
++
++#if defined(CONFIG_MIPS_SEAD2)
++unsigned long temp_base_address[2] = {0xa8610000, 0xa8612800};
++unsigned long temp_reset_value[2] = { 1<< 17,1<<21};
++#define RESET_REG_PRCR (*(volatile unsigned int *)((0xa8611600 + 0x0)))
++#define VERSION(base) (*(volatile unsigned int *)(((base)|0xa0000000) + 0x0))
++#endif
++
++MODULE_AUTHOR("Maintainer: Suraj S Iyer <ssiyer@ti.com>");
++MODULE_DESCRIPTION("Driver for TI CPMAC");
++
++static int cfg_link_speed = 0;
++MODULE_PARM(cfg_link_speed, "i");
++MODULE_PARM_DESC(cfg_link_speed, "Fixed speed of the Link: <100/10>");
++
++static char *cfg_link_mode = NULL;
++MODULE_PARM(cfg_link_mode, "1-3s");
++MODULE_PARM_DESC(cfg_link_mode, "Fixed mode of the Link: <fd/hd>");
++
++int cpmac_debug_mode = 0;
++MODULE_PARM(debug_mode, "i");
++MODULE_PARM_DESC(debug_mode, "Turn on the debug info: <0/1>. Default is 0 (off)");
++
++#define dbgPrint if (cpmac_debug_mode) printk
++#define errPrint printk
++
++static int g_cfg_start_link_params = CFG_START_LINK_SPEED;
++static int g_init_enable_flag = 0;
++static int cfg_start_link_speed;
++static int cpmac_max_frame_size;
++
++static struct net_device *g_dev_array[2];
++static struct proc_dir_entry *gp_stats_file = NULL;
++
++//-----------------------------------------------------------------------------
++// Statistics related private functions.
++//-----------------------------------------------------------------------------
++static int cpmac_p_update_statistics(struct net_device *p_dev, char *buf, int limit, int *len);
++static int cpmac_p_read_rfc2665_stats(char *buf, char **start, off_t offset, int count, int *eof, void *data);
++static int cpmac_p_read_link(char *buf, char **start, off_t offset, int count, int *eof, void *data);
++static int cpmac_p_read_stats(char* buf, char **start, off_t offset, int count, int *eof, void *data);
++static int cpmac_p_write_stats (struct file *fp, const char * buf, unsigned long count, void * data);
++static int cpmac_p_reset_statistics (struct net_device *p_dev);
++static int cpmac_p_get_version(char *buf, char **start, off_t offset, int count, int *eof, void *data);
++
++static int cpmac_p_detect_manual_cfg(int, char*, int);
++static int cpmac_p_process_status_ind(CPMAC_PRIVATE_INFO_T *p_cpmac_priv);
++
++//-----------------------------------------------------------------------------
++// Timer related private functions.
++//-----------------------------------------------------------------------------
++static int cpmac_p_timer_init(CPMAC_PRIVATE_INFO_T *p_cpmac_priv);
++// static int cpmac_timer_cleanup(CPMAC_PRIVATE_INFO_T *p_cpmac_priv);
++static void cpmac_p_tick_timer_expiry(unsigned long p_cb_param);
++inline static int cpmac_p_start_timer(struct timer_list *p_timer, unsigned int delay_ticks);
++static int cpmac_p_stop_timer(struct timer_list *p_timer);
++
++//------------------------------------------------------------------------------
++// Device configuration and setup related private functions.
++//------------------------------------------------------------------------------
++static int cpmac_p_probe_and_setup_device(CPMAC_PRIVATE_INFO_T *p_cpmac_priv, unsigned long *p_dev_flags);
++static int cpmac_p_setup_driver_params(CPMAC_PRIVATE_INFO_T *p_cpmac_priv);
++inline static int cpmac_p_rx_buf_setup(CPMAC_RX_CHAN_INFO_T *p_rx_chan);
++
++//-----------------------------------------------------------------------------
++// Net device related private functions.
++//-----------------------------------------------------------------------------
++static int cpmac_dev_init(struct net_device *p_dev);
++static int cpmac_dev_open( struct net_device *dev );
++static int cpmac_dev_close(struct net_device *p_dev);
++static void cpmac_dev_mcast_set(struct net_device *p_dev);
++static int cpmac_dev_set_mac_addr(struct net_device *p_dev,void * addr);
++static int cpmac_dev_tx( struct sk_buff *skb, struct net_device *p_dev);
++static struct net_device_stats *cpmac_dev_get_net_stats (struct net_device *dev);
++
++static int cpmac_p_dev_enable( struct net_device *p_dev);
++
++
++
++/* Max. Reserved headroom in front of each packet so that the headers can be added to
++ * a packet. Worst case scenario would be PPPoE + 2684 LLC Encapsulation + Ethernet
++ * header. */
++#define MAX_RESERVED_HEADROOM 20
++
++/* This is the MAX size of the static buffer for pure data. */
++#define MAX_SIZE_STATIC_BUFFER 1600
++
++typedef struct DRIVER_BUFFER
++{
++ /* Pointer to the allocated data buffer. This is the static data buffer
++ * allocated for the TI-Cache. 60 bytes out of the below buffer are required
++ * by the SKB shared info. We always reserve at least MAX_RESERVED_HEADROOM bytes
++ * so that the packets always have sufficient headroom. */
++ char ptr_buffer[MAX_SIZE_STATIC_BUFFER + MAX_RESERVED_HEADROOM + 60];
++
++ /* List of the driver buffers. */
++ struct DRIVER_BUFFER* ptr_next;
++}DRIVER_BUFFER;
++
++typedef struct DRIVER_BUFFER_MCB
++{
++ /* List of the driver buffers. */
++ DRIVER_BUFFER* ptr_available_driver_buffers;
++
++ /* The number of available buffers. */
++ int num_available_buffers;
++}DRIVER_BUFFER_MCB;
++
++DRIVER_BUFFER_MCB driver_mcb;
++int hybrid_mode = 0;
++
++static union {
++ struct sk_buff_head list;
++ char pad[SMP_CACHE_BYTES];
++} skb_head_pool[NR_CPUS];
++
++/**************************************************************************
++ * FUNCTION NAME : ti_release_skb
++ **************************************************************************
++ * DESCRIPTION :
++ * This function is called from the ti_alloc_skb when there were no more
++ * data buffers available. The allocated SKB had to released back to the
++ * data pool. The reason why this function was moved from the fast path
++ * below was because '__skb_queue_head' is an inline function which adds
++ * a large code chunk on the fast path.
++ *
++ * NOTES :
++ * This function is called with interrupts disabled.
++ **************************************************************************/
++static void ti_release_skb (struct sk_buff_head* list, struct sk_buff* skb)
++{
++ __skb_queue_head(list, skb);
++ return;
++}
++
++/**************************************************************************
++ * FUNCTION NAME : ti_alloc_skb
++ **************************************************************************
++ * DESCRIPTION :
++ * The function is called to allocate memory from the static allocated
++ * TI-Cached memory pool.
++ *
++ * RETURNS :
++ * Allocated static memory buffer - Success
++ * NULL - Error.
++ **************************************************************************/
++struct sk_buff *ti_alloc_skb(unsigned int size,int gfp_mask)
++{
++ register struct sk_buff* skb;
++ unsigned long flags;
++ struct sk_buff_head* list;
++ DRIVER_BUFFER* ptr_node = NULL;
++
++ /* Critical Section Begin: Lock out interrupts. */
++ local_irq_save(flags);
++
++ /* Get the SKB Pool list associated with the processor and dequeue the head. */
++ list = &skb_head_pool[smp_processor_id()].list;
++ skb = __skb_dequeue(list);
++
++ /* Align the data size. */
++ size = SKB_DATA_ALIGN(size);
++
++ /* Did we get one. */
++ if (skb != NULL)
++ {
++ /* YES. Now get a data block from the head of statically allocated block. */
++ ptr_node = driver_mcb.ptr_available_driver_buffers;
++ if (ptr_node != NULL)
++ {
++ /* YES. Got a data block. Advance the free list pointer to the next available buffer. */
++ driver_mcb.ptr_available_driver_buffers = ptr_node->ptr_next;
++ ptr_node->ptr_next = NULL;
++
++ /* Decrement the number of available data buffers. */
++ driver_mcb.num_available_buffers = driver_mcb.num_available_buffers - 1;
++ }
++ else
++ {
++ /* NO. Was unable to get a data block. So put the SKB back on the free list.
++ * This is slow path. */
++#ifdef DEBUG_SKB
++ printk ("DEBUG: No Buffer memory available: Number of free buffer:%d.\n",
++ driver_mcb.num_available_buffers);
++#endif
++ ti_release_skb (list, skb);
++ }
++ }
++
++ /* Critical Section End: Unlock interrupts. */
++ local_irq_restore(flags);
++
++ /* Did we get an SKB and data buffer. Proceed only if we were succesful in getting both else drop */
++ if (skb != NULL && ptr_node != NULL)
++ {
++ /* XXX: does not include slab overhead */
++ skb->truesize = size + sizeof(struct sk_buff);
++
++ /* Load the data pointers. */
++ skb->head = ptr_node->ptr_buffer;
++ skb->data = ptr_node->ptr_buffer + MAX_RESERVED_HEADROOM;
++ skb->tail = ptr_node->ptr_buffer + MAX_RESERVED_HEADROOM;
++ skb->end = ptr_node->ptr_buffer + size + MAX_RESERVED_HEADROOM;
++
++ /* Set up other state */
++ skb->len = 0;
++ skb->cloned = 0;
++ skb->data_len = 0;
++
++ /* Mark the SKB indicating that the SKB is from the TI cache. */
++ skb->cb[45] = 1;
++
++ atomic_set(&skb->users, 1);
++ atomic_set(&(skb_shinfo(skb)->dataref), 1);
++ skb_shinfo(skb)->nr_frags = 0;
++ skb_shinfo(skb)->frag_list = NULL;
++ return skb;
++ }
++ else
++ {
++ /* Control comes here only when there is no statically allocated data buffers
++ * available. This case is handled using the mode selected
++ *
++ * 1. Hybrid Mode.
++ * In that case lets jump to the old allocation code. This way we
++ * can allocate a small number of data buffers upfront and the rest will hit
++ * this portion of the code, which is slow path. Note the number of hits here
++ * should be kept as low as possible to satisfy performance requirements.
++ *
++ * 2. Pure Static Mode.
++ * Return NULL the user should have tuned the number of static buffers for
++ * worst case scenario. So return NULL and let the drivers handle the error. */
++ if (hybrid_mode == 1)
++ {
++ /* Hybrid Mode: Old allocation. */
++ return dev_alloc_skb(size);
++ }
++ else
++ {
++ /* Pure Static Mode: No buffers available. */
++ return NULL;
++ }
++ }
++}
++
++/**************************************************************************
++ * FUNCTION NAME : ti_skb_release_fragment
++ **************************************************************************
++ * DESCRIPTION :
++ * This function is called to release fragmented packets. This is NOT in
++ * the fast path and this function requires some work.
++ **************************************************************************/
++static void ti_skb_release_fragment(struct sk_buff *skb)
++{
++ if (skb_shinfo(skb)->nr_frags)
++ {
++ /* PANKAJ TODO: This portion has not been tested. */
++ int i;
++#ifdef DEBUG_SKB
++ printk ("DEBUG: Releasing fragments in TI-Cached code.\n");
++#endif
++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
++ printk ("DEBUG: Fragmented Page = 0x%p.\n", skb_shinfo(skb)->frags[i].page);
++ }
++
++ /* Check if there were any fragments present and if so clean all the SKB's.
++ * This is required to recursivly clean the SKB's. */
++ if (skb_shinfo(skb)->frag_list)
++ skb_drop_fraglist(skb);
++
++ return;
++}
++
++/**************************************************************************
++ * FUNCTION NAME : ti_skb_release_data
++ **************************************************************************
++ * DESCRIPTION :
++ * The function is called to release the SKB back into the TI-Cached static
++ * memory pool.
++ **************************************************************************/
++static void ti_skb_release_data(struct sk_buff *skb)
++{
++ DRIVER_BUFFER* ptr_node;
++ unsigned long flags;
++
++ /* The SKB data can be cleaned only if the packet has not been cloned and we
++ * are the only one holding a reference to the data. */
++ if (!skb->cloned || atomic_dec_and_test(&(skb_shinfo(skb)->dataref)))
++ {
++ /* Are there any fragments associated with the SKB ?*/
++ if ((skb_shinfo(skb)->nr_frags != 0) || (skb_shinfo(skb)->frag_list != NULL))
++ {
++ /* Slow Path: Try and clean up the fragments. */
++ ti_skb_release_fragment (skb);
++ }
++
++ /* Cleanup the SKB data memory. This is fast path. */
++ ptr_node = (DRIVER_BUFFER *)skb->head;
++
++ /* Critical Section: Lock out interrupts. */
++ local_irq_save(flags);
++
++ /* Add the data buffer to the list of available buffers. */
++ ptr_node->ptr_next = driver_mcb.ptr_available_driver_buffers;
++ driver_mcb.ptr_available_driver_buffers = ptr_node;
++
++ /* Increment the number of available data buffers. */
++ driver_mcb.num_available_buffers = driver_mcb.num_available_buffers + 1;
++
++ /* Criticial Section: Unlock interrupts. */
++ local_irq_restore(flags);
++ }
++ return;
++}
++
++
++
++
++static unsigned char str2hexnum(unsigned char c)
++{
++ if(c >= '0' && c <= '9')
++ return c - '0';
++ if(c >= 'a' && c <= 'f')
++ return c - 'a' + 10;
++ if(c >= 'A' && c <= 'F')
++ return c - 'A' + 10;
++ return 0;
++}
++
++static void str2eaddr(unsigned char *ea, unsigned char *str)
++{
++ int i;
++ unsigned char num;
++ for(i = 0; i < 6; i++) {
++ if((*str == '.') || (*str == ':'))
++ str++;
++ num = str2hexnum(*str++) << 4;
++ num |= (str2hexnum(*str++));
++ ea[i] = num;
++ }
++}
++
++//-----------------------------------------------------------------------------
++// Statistics related private functions.
++//-----------------------------------------------------------------------------
++static int cpmac_p_update_statistics(struct net_device *p_dev, char *buf, int limit, int *p_len)
++{
++ int ret_val = -1;
++ unsigned long rx_hal_errors = 0;
++ unsigned long rx_hal_discards = 0;
++ unsigned long tx_hal_errors = 0;
++ unsigned long ifOutDiscards = 0;
++ unsigned long ifInDiscards = 0;
++ unsigned long ifOutErrors = 0;
++ unsigned long ifInErrors = 0;
++
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal;
++ CPMAC_DEVICE_MIB_T *p_device_mib = p_cpmac_priv->device_mib;
++ CPMAC_DRV_STATS_T *p_stats = p_cpmac_priv->stats;
++ CPMAC_DEVICE_MIB_T local_mib;
++ CPMAC_DEVICE_MIB_T *p_local_mib = &local_mib;
++
++ struct net_device_stats *p_net_dev_stats = &p_cpmac_priv->net_dev_stats;
++
++ int len = 0;
++ int dev_mib_elem_count = 0;
++
++ /* do not access the hardware if it is in the reset state. */
++ if(!test_bit(0, &p_cpmac_priv->set_to_close))
++ {
++ if(p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "StatsDump", "Get",
++ p_local_mib) != 0)
++ {
++ errPrint("The stats dump for %s is failing.\n", p_dev->name);
++ return(ret_val);
++ }
++
++ p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "StatsClear", "Set", NULL);
++
++ dev_mib_elem_count = sizeof(CPMAC_DEVICE_MIB_T)/sizeof(unsigned long);
++
++ /* Update the history of the stats. This takes care of any reset of the
++ * device and stats that might have taken place during the life time of
++ * the driver.
++ */
++ while(dev_mib_elem_count--)
++ {
++ *((unsigned long*) p_device_mib + dev_mib_elem_count) +=
++ *((unsigned long*) p_local_mib + dev_mib_elem_count);
++ }
++ }
++
++ /* RFC2665, section 3.2.7, page 9 */
++ rx_hal_errors = p_device_mib->ifInFragments +
++ p_device_mib->ifInCRCErrors +
++ p_device_mib->ifInAlignCodeErrors +
++ p_device_mib->ifInJabberFrames;
++
++ /* RFC2233 */
++ rx_hal_discards = p_device_mib->ifRxDMAOverruns;
++
++ /* RFC2665, section 3.2.7, page 9 */
++ tx_hal_errors = p_device_mib->ifExcessiveCollisionFrames +
++ p_device_mib->ifLateCollisions +
++ p_device_mib->ifCarrierSenseErrors +
++ p_device_mib->ifOutUnderrun;
++
++ /* if not set, the short frames (< 64 bytes) are considered as errors */
++ if(!p_cpmac_priv->flags & IFF_PRIV_SHORT_FRAMES)
++ rx_hal_errors += p_device_mib->ifInUndersizedFrames;
++
++ /* if not set, the long frames ( > 1518) are considered as errors
++ * RFC2665, section 3.2.7, page 9. */
++ if(!p_cpmac_priv->flags & IFF_PRIV_JUMBO_FRAMES)
++ rx_hal_errors += p_device_mib->ifInOversizedFrames;
++
++ /* if not in promiscous, then non addr matching frames are discarded */
++ /* CPMAC 2.0 Manual Section 2.8.1.14 */
++ if(!p_dev->flags & IFF_PROMISC)
++ {
++ ifInDiscards += p_device_mib->ifInFilteredFrames;
++ }
++
++ /* total rx discards = hal discards + driver discards. */
++ ifInDiscards = rx_hal_discards + p_net_dev_stats->rx_dropped;
++ ifInErrors = rx_hal_errors;
++
++ ifOutErrors = tx_hal_errors;
++ ifOutDiscards = p_net_dev_stats->tx_dropped;
++
++ /* Let us update the net device stats struct. To be updated in the later releases.*/
++ p_cpmac_priv->net_dev_stats.rx_errors = ifInErrors;
++ p_cpmac_priv->net_dev_stats.collisions = p_device_mib->ifCollisionFrames;
++
++ if(buf == NULL || limit == 0)
++ {
++ return(0);
++ }
++
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %ld\n", "ifSpeed", (long)p_cpmac_priv->link_speed);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "dot3StatsDuplexStatus", (long)p_cpmac_priv->link_mode);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifAdminStatus", (long)(p_dev->flags & IFF_UP ? 1:2));
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOperStatus", (long)(((p_dev->flags & IFF_UP) && netif_carrier_ok(p_dev)) ? 1:2));
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifLastChange", p_stats->start_tick);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInDiscards", ifInDiscards);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInErrors", ifInErrors);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutDiscards", ifOutDiscards);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutErrors", ifOutErrors);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInGoodFrames", p_device_mib->ifInGoodFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInBroadcasts", p_device_mib->ifInBroadcasts);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInMulticasts", p_device_mib->ifInMulticasts);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInPauseFrames", p_device_mib->ifInPauseFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInCRCErrors", p_device_mib->ifInCRCErrors);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInAlignCodeErrors", p_device_mib->ifInAlignCodeErrors);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInOversizedFrames", p_device_mib->ifInOversizedFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInJabberFrames", p_device_mib->ifInJabberFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInUndersizedFrames", p_device_mib->ifInUndersizedFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInFragments", p_device_mib->ifInFragments);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInFilteredFrames", p_device_mib->ifInFilteredFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInQosFilteredFrames", p_device_mib->ifInQosFilteredFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInOctets", p_device_mib->ifInOctets);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutGoodFrames", p_device_mib->ifOutGoodFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutBroadcasts", p_device_mib->ifOutBroadcasts);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutMulticasts", p_device_mib->ifOutMulticasts);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutPauseFrames", p_device_mib->ifOutPauseFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifDeferredTransmissions", p_device_mib->ifDeferredTransmissions);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifCollisionFrames", p_device_mib->ifCollisionFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifSingleCollisionFrames", p_device_mib->ifSingleCollisionFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifMultipleCollisionFrames", p_device_mib->ifMultipleCollisionFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifExcessiveCollisionFrames", p_device_mib->ifExcessiveCollisionFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifLateCollisions", p_device_mib->ifLateCollisions);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutUnderrun", p_device_mib->ifOutUnderrun);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifCarrierSenseErrors", p_device_mib->ifCarrierSenseErrors);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutOctets", p_device_mib->ifOutOctets);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "if64OctetFrames", p_device_mib->if64OctetFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "if65To127POctetFrames", p_device_mib->if65To127OctetFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "if128To255OctetFrames", p_device_mib->if128To255OctetFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "if256To511OctetFrames", p_device_mib->if256To511OctetFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "if512To1023OctetFrames", p_device_mib->if512To1023OctetFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "if1024ToUpOctetFrames", p_device_mib->if1024ToUPOctetFrames);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifNetOctets", p_device_mib->ifNetOctets);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifRxSofOverruns", p_device_mib->ifRxSofOverruns);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifRxMofOverruns", p_device_mib->ifRxMofOverruns);
++ if(len <= limit)
++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifRxDMAOverruns", p_device_mib->ifRxDMAOverruns);
++
++ *p_len = len;
++
++ return(0);
++}
++
++
++static int cpmac_p_read_rfc2665_stats(char* buf, char **start, off_t offset,
++ int count, int *eof, void *data)
++{
++ int limit = count - 80;
++ int len = 0;
++ struct net_device *p_dev = (struct net_device*)data;
++
++ cpmac_p_update_statistics(p_dev, buf, limit, &len);
++
++ *eof = 1;
++
++ return len;
++}
++
++static int cpmac_p_read_link(char *buf, char **start, off_t offset, int count,
++ int *eof, void *data)
++{
++ int len = 0;
++
++ struct net_device *p_dev;
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv;
++ struct net_device *cpmac_dev_list[cpmac_devices_installed];
++ CPMAC_DRV_HAL_INFO_T *p_drv_hal;
++
++ int i;
++ int phy; /* what phy are we using? */
++
++ len += sprintf(buf+len, "CPMAC devices = %d\n",cpmac_devices_installed);
++
++ p_dev = last_cpmac_device;
++
++ /* Reverse the the device link list to list eth0,eth1...in correct order */
++ for(i=0; i< cpmac_devices_installed; i++)
++ {
++ cpmac_dev_list[cpmac_devices_installed -(i+1)] = p_dev;
++ p_cpmac_priv = p_dev->priv;
++ p_dev = p_cpmac_priv->next_device;
++ }
++
++ for(i=0; i< cpmac_devices_installed; i++)
++ {
++ p_dev = cpmac_dev_list[i];
++ p_cpmac_priv = p_dev->priv;
++ p_drv_hal = p_cpmac_priv->drv_hal;
++
++ /* This prints them out from high to low because of how the devices are linked */
++ if(netif_carrier_ok(p_dev))
++ {
++ p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "PhyNum", "Get", &phy);
++
++
++ len += sprintf(buf+len,"eth%d: Link State: %s Phy:0x%x, Speed = %s, Duplex = %s\n",
++ p_cpmac_priv->instance_num, "UP", phy,
++ (p_cpmac_priv->link_speed == 100000000) ? "100":"10",
++ (p_cpmac_priv->link_mode == 2) ? "Half":"Full");
++
++ }
++ else
++ len += sprintf(buf+len,"eth%d: Link State: DOWN\n",p_cpmac_priv->instance_num);
++
++ p_dev = p_cpmac_priv->next_device;
++ }
++
++ return len;
++
++}
++
++static int cpmac_p_read_stats(char* buf, char **start, off_t offset, int count,
++ int *eof, void *data)
++{
++ struct net_device *p_dev = last_cpmac_device;
++ int len = 0;
++ int limit = count - 80;
++ int i;
++ struct net_device *cpmac_dev_list[cpmac_devices_installed];
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv;
++ CPMAC_DEVICE_MIB_T *p_device_mib;
++
++ /* Reverse the the device link list to list eth0,eth1...in correct order */
++ for(i=0; i< cpmac_devices_installed; i++)
++ {
++ cpmac_dev_list[cpmac_devices_installed - (i+1)] = p_dev;
++ p_cpmac_priv = p_dev->priv;
++ p_dev = p_cpmac_priv->next_device;
++ }
++
++ for(i=0; i< cpmac_devices_installed; i++)
++ {
++ p_dev = cpmac_dev_list[i];
++
++ if(!p_dev)
++ goto proc_error;
++
++ /* Get Stats */
++ cpmac_p_update_statistics(p_dev, NULL, 0, NULL);
++
++ p_cpmac_priv = p_dev->priv;
++ p_device_mib = p_cpmac_priv->device_mib;
++
++ /* Transmit stats */
++ if(len<=limit)
++ len+= sprintf(buf+len, "\nCpmac %d, Address %lx\n",i+1, p_dev->base_addr);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Transmit Stats\n");
++ if(len<=limit)
++ len+= sprintf(buf+len, " Tx Valid Bytes Sent :%lu\n",p_device_mib->ifOutOctets);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Good Tx Frames (Hardware) :%lu\n",p_device_mib->ifOutGoodFrames);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Good Tx Frames (Software) :%lu\n",p_cpmac_priv->net_dev_stats.tx_packets);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Good Tx Broadcast Frames :%lu\n",p_device_mib->ifOutBroadcasts);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Good Tx Multicast Frames :%lu\n",p_device_mib->ifOutMulticasts);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Pause Frames Sent :%lu\n",p_device_mib->ifOutPauseFrames);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Collisions :%lu\n",p_device_mib->ifCollisionFrames);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Tx Error Frames :%lu\n",p_cpmac_priv->net_dev_stats.tx_errors);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Carrier Sense Errors :%lu\n",p_device_mib->ifCarrierSenseErrors);
++ if(len<=limit)
++ len+= sprintf(buf+len, "\n");
++
++
++ /* Receive Stats */
++ if(len<=limit)
++ len+= sprintf(buf+len, "\nCpmac %d, Address %lx\n",i+1,p_dev->base_addr);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Receive Stats\n");
++ if(len<=limit)
++ len+= sprintf(buf+len, " Rx Valid Bytes Received :%lu\n",p_device_mib->ifInOctets);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Good Rx Frames (Hardware) :%lu\n",p_device_mib->ifInGoodFrames);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Good Rx Frames (Software) :%lu\n",p_cpmac_priv->net_dev_stats.rx_packets);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Good Rx Broadcast Frames :%lu\n",p_device_mib->ifInBroadcasts);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Good Rx Multicast Frames :%lu\n",p_device_mib->ifInMulticasts);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Pause Frames Received :%lu\n",p_device_mib->ifInPauseFrames);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Rx CRC Errors :%lu\n",p_device_mib->ifInCRCErrors);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Rx Align/Code Errors :%lu\n",p_device_mib->ifInAlignCodeErrors);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Rx Jabbers :%lu\n",p_device_mib->ifInOversizedFrames);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Rx Filtered Frames :%lu\n",p_device_mib->ifInFilteredFrames);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Rx Fragments :%lu\n",p_device_mib->ifInFragments);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Rx Undersized Frames :%lu\n",p_device_mib->ifInUndersizedFrames);
++ if(len<=limit)
++ len+= sprintf(buf+len, " Rx Overruns :%lu\n",p_device_mib->ifRxDMAOverruns);
++ }
++
++
++ return len;
++
++ proc_error:
++ *eof=1;
++ return len;
++}
++
++static int cpmac_p_write_stats (struct file *fp, const char * buf, unsigned long count, void * data)
++{
++ char local_buf[31];
++ int ret_val = 0;
++
++ if(count > 30)
++ {
++ printk("Error : Buffer Overflow\n");
++ printk("Use \"echo 0 > cpmac_stat\" to reset the statistics\n");
++ return -EFAULT;
++ }
++
++ copy_from_user(local_buf,buf,count);
++ local_buf[count-1]='\0'; /* Ignoring last \n char */
++ ret_val = count;
++
++ if(strcmp("0",local_buf)==0)
++ {
++ struct net_device *p_dev = last_cpmac_device;
++ int i;
++ struct net_device *cpmac_dev_list[cpmac_devices_installed];
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv;
++
++ /* Valid command */
++ printk("Resetting statistics for CPMAC interface.\n");
++
++ /* Reverse the the device link list to list eth0,eth1...in correct order */
++ for(i=0; i< cpmac_devices_installed; i++)
++ {
++ cpmac_dev_list[cpmac_devices_installed - (i+1)] = p_dev;
++ p_cpmac_priv = p_dev->priv;
++ p_dev = p_cpmac_priv->next_device;
++ }
++
++ for(i=0; i< cpmac_devices_installed; i++)
++ {
++ p_dev = cpmac_dev_list[i];
++ if(!p_dev)
++ {
++ ret_val = -EFAULT;
++ break;
++ }
++
++ cpmac_p_reset_statistics(p_dev);
++ }
++ }
++ else
++ {
++ printk("Error: Unknown operation on cpmac statistics\n");
++ printk("Use \"echo 0 > cpmac_stats\" to reset the statistics\n");
++ return -EFAULT;
++ }
++
++ return ret_val;
++}
++
++static int cpmac_p_reset_statistics(struct net_device *p_dev)
++{
++ int ret_val = 0;
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal;
++
++ memset(p_cpmac_priv->device_mib, 0, sizeof(CPMAC_DEVICE_MIB_T));
++ memset(p_cpmac_priv->stats, 0, sizeof(CPMAC_DRV_STATS_T));
++ memset(&p_cpmac_priv->net_dev_stats, 0, sizeof(struct net_device_stats));
++
++ p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "StatsClear", "Set", NULL);
++
++ return(ret_val);
++}
++
++static int cpmac_p_get_version(char* buf, char **start, off_t offset, int count,int *eof, void *data)
++{
++ int len = 0;
++ int limit = count - 80;
++ char *hal_version = NULL;
++ struct net_device *p_dev = last_cpmac_device;
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal;
++
++ p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "Version", "Get", &hal_version);
++
++ len += sprintf(buf+len, "Texas Instruments CPMAC driver version: %s\n", cpmac_version);
++
++ if(len <= limit && hal_version)
++ len += sprintf(buf+len, "Texas Instruments CPMAC HAL version: %s\n", hal_version);
++
++ return len;
++}
++
++static struct net_device_stats *cpmac_dev_get_net_stats (struct net_device *p_dev)
++{
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = (CPMAC_PRIVATE_INFO_T *) p_dev->priv;
++
++ cpmac_p_update_statistics(p_dev, NULL, 0, NULL);
++
++ return &p_cpmac_priv->net_dev_stats;
++}
++
++static int cpmac_p_detect_manual_cfg(int link_speed, char* link_mode, int debug)
++{
++ char *pSpeed = NULL;
++
++ if(debug == 1)
++ {
++ cpmac_debug_mode = 1;
++ dbgPrint("Enabled the debug print.\n");
++ }
++
++ if(!link_speed && !link_mode)
++ {
++ dbgPrint("No manual link params, defaulting to auto negotiation.\n");
++ return (0);
++ }
++
++ if(!link_speed || (link_speed != 10 && link_speed != 100))
++ {
++ dbgPrint("Invalid or No value of link speed specified, defaulting to auto speed.\n");
++ pSpeed = "auto";
++ }
++ else if(link_speed == 10)
++ {
++ g_cfg_start_link_params &= ~(_CPMDIO_100);
++ pSpeed = "10 Mbps";
++ }
++ else
++ {
++ g_cfg_start_link_params &= ~(_CPMDIO_10);
++ pSpeed = "100 Mbps";
++ }
++
++ if(!link_mode || (!strcmp(link_mode, "fd") && !strcmp(link_mode, "hd")))
++ {
++ dbgPrint("Invalid or No value of link mode specified, defaulting to auto mode.\n");
++ }
++ else if(!strcmp(link_mode, "hd"))
++ {
++ g_cfg_start_link_params &= ~(_CPMDIO_FD);
++ }
++ else
++ {
++ g_cfg_start_link_params &= ~(_CPMDIO_HD);
++ }
++
++ dbgPrint("Link is manually set to the speed of %s speed and %s mode.\n",
++ pSpeed, link_mode ? link_mode : "auto");
++
++ return(0);
++}
++
++//------------------------------------------------------------------------------
++// Call back from the HAL.
++//------------------------------------------------------------------------------
++static int cpmac_p_process_status_ind(CPMAC_PRIVATE_INFO_T *p_cpmac_priv)
++{
++ struct net_device *p_dev = p_cpmac_priv->owner;
++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal;
++ int status;
++
++ p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "Status", "Get", &status);
++
++ /* We do not reflect the real link status if in loopback.
++ * After all, we want the packets to reach the hardware so
++ * that Send() should work. */
++ if(p_dev->flags & IFF_LOOPBACK)
++ {
++ dbgPrint("Maintaining the link up loopback for %s.\n", p_dev->name);
++ netif_carrier_on(p_dev);
++
++//#if defined (CONFIG_MIPS_AVALANCHE_LED)
++// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_ON);
++//#endif
++
++ return(0);
++ }
++
++ if(status & CPMAC_STATUS_ADAPTER_CHECK) /* ???? */
++ {
++ ; /* what to do ? */
++ }
++ else if(status)
++ {
++ if(!netif_carrier_ok(p_dev))
++ {
++ netif_carrier_on(p_cpmac_priv->owner);
++
++//#if defined (CONFIG_MIPS_AVALANCHE_LED)
++// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_ON);
++//#endif
++ dbgPrint("Found the Link for the CPMAC instance %s.\n", p_dev->name);
++ }
++
++ if(netif_running(p_dev) & netif_queue_stopped(p_dev))
++ {
++ netif_wake_queue(p_dev);
++ }
++
++ p_cpmac_priv->link_speed = status & CPMAC_STATUS_LINK_SPEED ? 100000000:10000000;
++ p_cpmac_priv->link_mode = status & CPMAC_STATUS_LINK_DUPLEX? 3:2;
++
++ }
++ else
++ {
++ if(netif_carrier_ok(p_dev))
++ {
++ /* do we need to register synchronization issues with stats here. */
++ p_cpmac_priv->link_speed = 100000000;
++ p_cpmac_priv->link_mode = 1;
++
++ netif_carrier_off(p_dev);
++
++//#if defined (CONFIG_MIPS_AVALANCHE_LED)
++// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_OFF);
++//#endif
++
++ dbgPrint("Lost the Link for the CPMAC for %s.\n", p_dev->name);
++ }
++
++ if(!netif_queue_stopped(p_dev))
++ {
++ netif_stop_queue(p_dev); /* So that kernel does not keep on xmiting pkts. */
++ }
++ }
++
++ return(0);
++}
++
++//-----------------------------------------------------------------------------
++// Timer related private functions.
++//-----------------------------------------------------------------------------
++static int cpmac_p_timer_init(CPMAC_PRIVATE_INFO_T *p_cpmac_priv)
++{
++ struct timer_list *p_timer = p_cpmac_priv->timer;
++
++ init_timer(p_timer);
++
++ p_timer = p_cpmac_priv->timer + TICK_TIMER;
++ p_timer->expires = 0;
++ p_timer->data = (unsigned long)p_cpmac_priv;
++ p_timer->function = cpmac_p_tick_timer_expiry;
++
++ return(0);
++}
++
++#if 0
++static int cpmac_timer_cleanup(CPMAC_PRIVATE_INFO_T *p_cpmac_priv)
++{
++ struct timer_list *p_timer;
++
++ p_timer = p_cpmac_priv->timer + TICK_TIMER;
++
++ /* use spin lock to establish synchronization with the dispatch */
++ if(p_timer->function) del_timer_sync(p_timer);
++ p_timer->function = NULL;
++
++ return (0);
++}
++#endif
++
++static int cpmac_p_start_timer(struct timer_list *p_timer, unsigned int delay_ticks)
++{
++ p_timer->expires = jiffies + delay_ticks;
++
++ if(p_timer->function)
++ {
++ add_timer(p_timer);
++ }
++
++ return(0);
++}
++
++static void cpmac_p_tick_timer_expiry(unsigned long p_cb_param)
++{
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = (CPMAC_PRIVATE_INFO_T*) p_cb_param;
++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal;
++ struct timer_list *p_timer = p_cpmac_priv->timer + TICK_TIMER;
++
++ if(test_bit(0, &p_cpmac_priv->set_to_close))
++ {
++ return;
++ }
++
++ p_drv_hal->hal_funcs->Tick(p_drv_hal->hal_dev);
++
++ cpmac_p_start_timer(p_timer, p_cpmac_priv->delay_ticks);
++}
++
++static int cpmac_p_stop_timer(struct timer_list *p_timer)
++{
++ /* Ideally we need to a set flag indicating not to start the timer again
++ before del_timer_sync() is called up. But here we assume that the
++ caller has set the p_cpmac_priv->set_to_close (ok for now). */
++ del_timer_sync(p_timer);
++
++ return(0);
++}
++
++//------------------------------------------------------------------------------
++// Device configuration and setup related private functions.
++//------------------------------------------------------------------------------
++static int cpmac_p_probe_and_setup_device(CPMAC_PRIVATE_INFO_T *p_cpmac_priv,
++ unsigned long *p_dev_flags)
++{
++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal;
++ HAL_FUNCTIONS *p_hal_funcs = p_drv_hal->hal_funcs;
++ HAL_DEVICE *p_hal_dev = p_drv_hal->hal_dev;
++ CPMAC_ABILITY_INFO_T *p_capability= p_cpmac_priv->ability_info;
++ unsigned int val = 0;
++ int channel = 0;
++
++ p_cpmac_priv->flags = 0;
++
++ p_capability->promiscous = CFG_PROMISCOUS;
++ p_capability->broadcast = CFG_BROADCAST;
++ p_capability->multicast = CFG_MULTICAST;
++ p_capability->all_multi = CFG_ALL_MULTI;
++ p_capability->jumbo_frames = CFG_JUMBO_FRAMES;
++ p_capability->short_frames = CFG_SHORT_FRAMES;
++ p_capability->auto_negotiation = CFG_AUTO_NEGOTIATION;
++ p_capability->link_speed = cfg_start_link_speed;
++ p_capability->loop_back = CFG_LOOP_BACK;
++ p_capability->tx_flow_control = CFG_TX_FLOW_CNTL;
++ p_capability->rx_flow_control = CFG_RX_FLOW_CNTL;
++ p_capability->tx_pacing = CFG_TX_PACING;
++ p_capability->rx_pass_crc = CFG_RX_PASS_CRC;
++ p_capability->qos_802_1q = CFG_QOS_802_1Q;
++ p_capability->tx_num_chan = CFG_TX_NUM_CHAN;
++
++ /* Lets probe the device for the configured capabilities (netdev specific).*/
++
++ /* Following are set in the set_multi_list, when indicated by the kernel
++ * Promiscous and all multi.
++ */
++
++ if(p_capability->broadcast)
++ {
++ channel = 0;
++ val = 1;
++ if((p_hal_funcs->Control(p_hal_dev, pszRX_BROAD_EN, pszSet, &val) == 0) &&
++ (p_hal_funcs->Control(p_hal_dev, pszRX_BROAD_CH, pszSet, &channel) == 0))
++ *p_dev_flags |= IFF_BROADCAST;
++ else
++ p_capability->broadcast = 0; /* no broadcast capabilities */
++ }
++
++ if(p_capability->multicast)
++ {
++ val = 1;
++ channel = 0;
++ if((p_hal_funcs->Control(p_hal_dev, pszRX_MULT_EN, pszSet, &val) == 0) &&
++ (p_hal_funcs->Control(p_hal_dev, pszRX_MULT_CH, pszSet, &channel) == 0))
++ *p_dev_flags |= IFF_MULTICAST;
++ else
++ {
++ p_capability->multicast = 0;
++ p_capability->all_multi = 0; /* no multicast, no all-multi. */
++ }
++ }
++
++ if(p_capability->loop_back)
++ {
++ ; /* We do not put the device in loopback, if required use ioctl */
++ }
++
++ /* Lets probe the device for the configured capabilities (Non net device specific).*/
++
++ if(p_capability->jumbo_frames)
++ {
++ val = 0;
++ if(p_hal_funcs->Control(p_hal_dev, pszRX_NO_CHAIN, pszSet, &val) == 0)
++ p_cpmac_priv->flags |= IFF_PRIV_JUMBO_FRAMES;
++ else
++ p_capability->jumbo_frames = 0;
++ }
++
++ if(p_capability->short_frames)
++ {
++ val = 1;
++ if(p_hal_funcs->Control(p_hal_dev, pszRX_CSF_EN, pszSet, &val) == 0)
++ p_cpmac_priv->flags |= IFF_PRIV_SHORT_FRAMES;
++ else
++ p_capability->short_frames = 0;
++ }
++
++ val = g_cfg_start_link_params;
++
++#ifdef CONFIG_AR7_MDIX
++ if( avalanche_is_mdix_on_chip() )
++ {
++ val |= _CPMDIO_AUTOMDIX;
++ }
++#endif
++
++ if(p_hal_funcs->Control(p_hal_dev,pszMdioConnect,pszSet, &val) !=0)
++ {
++ p_capability->link_speed = 0;
++ }
++ else
++ {
++ if(g_cfg_start_link_params & (_CPMDIO_100 | _CPMDIO_HD | _CPMDIO_FD | _CPMDIO_10))
++ p_cpmac_priv->flags |= IFF_PRIV_AUTOSPEED;
++ else if(g_cfg_start_link_params & (_CPMDIO_100 | _CPMDIO_HD))
++ p_cpmac_priv->flags |= IFF_PRIV_LINK100_HD;
++ else if(g_cfg_start_link_params & (_CPMDIO_100 | _CPMDIO_FD))
++ p_cpmac_priv->flags |= IFF_PRIV_LINK100_FD;
++ else if(g_cfg_start_link_params & (_CPMDIO_10 | _CPMDIO_HD))
++ p_cpmac_priv->flags |= IFF_PRIV_LINK10_HD;
++ else if(g_cfg_start_link_params & (_CPMDIO_10 | _CPMDIO_FD))
++ p_cpmac_priv->flags |= IFF_PRIV_LINK10_FD;
++ else
++ ;
++ }
++
++ if(p_capability->tx_flow_control)
++ {
++ val = 1;
++ if(p_hal_funcs->Control(p_hal_dev,pszTX_FLOW_EN, pszSet, &val) ==0)
++ p_cpmac_priv->flags |= IFF_PRIV_TX_FLOW_CNTL;
++ else
++ p_capability->tx_flow_control = 0;
++ }
++
++ if(p_capability->rx_flow_control)
++ {
++ val = 1;
++ if(p_hal_funcs->Control(p_hal_dev, pszRX_FLOW_EN, pszSet, &val) ==0)
++ p_cpmac_priv->flags |= IFF_PRIV_RX_FLOW_CNTL;
++ else
++ p_capability->rx_flow_control = 0;
++ }
++
++ if(p_capability->tx_pacing)
++ {
++ val = 1;
++ if(p_hal_funcs->Control(p_hal_dev, pszTX_PACE, pszSet, &val) ==0)
++ p_cpmac_priv->flags |= IFF_PRIV_TX_PACING;
++ else
++ p_capability->tx_pacing = 0;
++ }
++
++ if(p_capability->rx_pass_crc)
++ {
++ val = 1;
++ if(p_hal_funcs->Control(p_hal_dev, pszRX_PASS_CRC, pszSet, &val) == 0)
++ p_cpmac_priv->flags |= IFF_PRIV_RX_PASS_CRC;
++ else
++ p_capability->rx_pass_crc = 0;
++ }
++
++ if(p_capability->qos_802_1q)
++ {
++ val = 1;
++ if(p_hal_funcs->Control(p_hal_dev, pszRX_QOS_EN, pszSet, &val) == 0)
++ p_cpmac_priv->flags |= IFF_PRIV_8021Q_EN;
++ else
++ {
++ p_capability->qos_802_1q = 0;
++ p_capability->tx_num_chan= 1;
++ }
++ }
++
++ if(p_capability->tx_num_chan > 1)
++ {
++ int cfg_tx_num_chan = p_capability->tx_num_chan;
++ val = 0;
++#ifdef TEST
++ if(p_hal_funcs->Control(p_hal_dev, pszTX_NUM_CH, pszGet, &val) == 0)
++ cfg_tx_num_chan = cfg_tx_num_chan > val ? val : cfg_tx_num_chan;
++ else
++ cfg_tx_num_chan = 1;
++#endif
++ p_capability->tx_num_chan = cfg_tx_num_chan;
++ }
++
++ return(0);
++}
++
++static int cpmac_p_setup_driver_params(CPMAC_PRIVATE_INFO_T *p_cpmac_priv)
++{
++ int i=0;
++ int threshold = CFG_TX_NUM_BUF_SERVICE;
++
++ char *tx_threshold_ptr = prom_getenv("threshold");
++
++ CPMAC_TX_CHAN_INFO_T *p_tx_chan_info = p_cpmac_priv->tx_chan_info;
++ CPMAC_RX_CHAN_INFO_T *p_rx_chan_info = p_cpmac_priv->rx_chan_info;
++ CPMAC_ABILITY_INFO_T *p_capability = p_cpmac_priv->ability_info;
++
++ /* Timer stuff */
++ p_cpmac_priv->timer_count = 1; /* should be < or = the MAX TIMER */
++ p_cpmac_priv->timer_created = 0;
++ p_cpmac_priv->timer_access_hal = 1;
++
++ for(i=0; i < MAX_TIMER; i++)
++ p_cpmac_priv->timer[i].function = NULL;
++
++ p_cpmac_priv->enable_802_1q = p_capability->qos_802_1q;
++
++ /* Tx channel related.*/
++ p_tx_chan_info->cfg_chan = p_capability->tx_num_chan;
++ p_tx_chan_info->opened_chan = 0;
++
++ if(tx_threshold_ptr)
++ threshold = simple_strtol(tx_threshold_ptr, (char **)NULL, 10);
++
++ if((threshold <= 0) && tx_threshold_ptr) /* If threshold set to 0 then Enable the TX interrupt */
++ {
++ threshold = CFG_TX_NUM_BUF_SERVICE;
++ p_tx_chan_info->tx_int_disable = 0;
++
++ }
++ else
++ {
++ p_tx_chan_info->tx_int_disable = CFG_TX_INT_DISABLE;
++ }
++
++ for(i=0; i < MAX_TX_CHAN; i++)
++ {
++
++
++
++ p_tx_chan_info->chan[i].state = CHAN_CLOSE;
++ p_tx_chan_info->chan[i].num_BD = CFG_TX_NUM_BUF_DESC;
++ p_tx_chan_info->chan[i].buffer_size = cpmac_max_frame_size;
++ p_tx_chan_info->chan[i].buffer_offset = CFG_TX_BUF_OFFSET;
++
++
++
++ p_tx_chan_info->chan[i].service_max = threshold;
++ }
++
++ if (p_tx_chan_info->tx_int_disable)
++ printk("Cpmac driver Disable TX complete interrupt setting threshold to %d.\n",threshold);
++ else
++ printk("Cpmac driver Enable TX complete interrupt\n");
++
++
++ /* Assuming just one rx channel for now */
++ p_rx_chan_info->cfg_chan = 1;
++ p_rx_chan_info->opened_chan = 0;
++ p_rx_chan_info->chan->state = CHAN_CLOSE;
++ p_rx_chan_info->chan->num_BD = CFG_RX_NUM_BUF_DESC;
++ p_rx_chan_info->chan->buffer_size = cpmac_max_frame_size;
++ p_rx_chan_info->chan->buffer_offset = CFG_RX_BUF_OFFSET;
++ p_rx_chan_info->chan->service_max = CFG_RX_NUM_BUF_SERVICE;
++
++ /* Set as per RFC 2665 */
++ p_cpmac_priv->link_speed = 100000000;
++ p_cpmac_priv->link_mode = 1;
++
++ p_cpmac_priv->loop_back = 0;
++
++ return(0);
++}
++
++inline static int cpmac_p_rx_buf_setup(CPMAC_RX_CHAN_INFO_T *p_rx_chan)
++{
++ /* Number of ethernet packets & max pkt length */
++ p_rx_chan->chan->tot_buf_size = p_rx_chan->chan->buffer_size +
++ 2*(CONTROL_802_1Q_SIZE) +
++ p_rx_chan->chan->buffer_offset +
++ ADD_FOR_4BYTE_ALIGN(p_rx_chan->chan->buffer_offset & 0x3);
++
++ p_rx_chan->chan->tot_reserve_bytes = CONTROL_802_1Q_SIZE +
++ p_rx_chan->chan->buffer_offset +
++ L3_ALIGN(p_rx_chan->chan->buffer_offset & 0x3);
++
++ return(0);
++}
++
++//-----------------------------------------------------------------------------
++// Net device related private functions.
++//-----------------------------------------------------------------------------
++
++/***************************************************************
++ * cpmac_dev_init
++ *
++ * Returns:
++ * 0 on success, error code otherwise.
++ * Parms:
++ * dev The structure of the device to be
++ * init'ed.
++ *
++ * This function completes the initialization of the
++ * device structure and driver. It reserves the IO
++ * addresses and assignes the device's methods.
++ *
++ *
++ **************************************************************/
++
++static int cpmac_dev_init(struct net_device *p_dev)
++{
++ int retVal = -1;
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++ int instance_num = p_cpmac_priv->instance_num;
++ unsigned long net_flags = 0;
++ char *mac_name = NULL;
++ char *mac_string = NULL;
++
++ CPMAC_TX_CHAN_INFO_T *p_tx_chan_info;
++ CPMAC_RX_CHAN_INFO_T *p_rx_chan_info;
++ CPMAC_DRV_HAL_INFO_T *p_drv_hal;
++ int i;
++
++ int mem_size = sizeof(CPMAC_DRV_HAL_INFO_T)
++ + sizeof(CPMAC_TX_CHAN_INFO_T)
++ + sizeof(CPMAC_RX_CHAN_INFO_T)
++ + sizeof(CPMAC_ABILITY_INFO_T)
++ + sizeof(CPMAC_DEVICE_MIB_T)
++ + sizeof(CPMAC_DRV_STATS_T);
++
++
++#if defined(CONFIG_MIPS_SEAD2)
++ int prev_reset_val = RESET_REG_PRCR;
++ /* Bring the module out of reset */
++ RESET_REG_PRCR |= temp_reset_value[p_cpmac_priv->instance_num];
++
++ /* Read the version id of the device to check if the device really exists */
++ if( VERSION(temp_base_address[p_cpmac_priv->instance_num]) == 0)
++ {
++ printk(" CPMAC:Device not found\n");
++ RESET_REG_PRCR = prev_reset_val;
++ return -ENODEV;
++ }
++
++ RESET_REG_PRCR = prev_reset_val;
++#endif
++
++
++ if((p_drv_hal = kmalloc(mem_size, GFP_KERNEL)) == NULL)
++ {
++ errPrint("Failed to allocate memory; rewinding.\n");
++ return(-1);
++ }
++
++ memset(p_drv_hal, 0, mem_size);
++
++ /* build the cpmac private object */
++ p_cpmac_priv->drv_hal = p_drv_hal;
++ p_cpmac_priv->tx_chan_info = p_tx_chan_info
++ = (CPMAC_TX_CHAN_INFO_T*)((char*)p_drv_hal
++ + sizeof(CPMAC_DRV_HAL_INFO_T));
++ p_cpmac_priv->rx_chan_info = p_rx_chan_info
++ = (CPMAC_RX_CHAN_INFO_T*)((char *)p_tx_chan_info
++ + sizeof(CPMAC_TX_CHAN_INFO_T));
++ p_cpmac_priv->ability_info = (CPMAC_ABILITY_INFO_T *)((char *)p_rx_chan_info
++ + sizeof(CPMAC_RX_CHAN_INFO_T));
++ p_cpmac_priv->device_mib = (CPMAC_DEVICE_MIB_T *)((char *)p_cpmac_priv->ability_info
++ + sizeof(CPMAC_ABILITY_INFO_T));
++ p_cpmac_priv->stats = (CPMAC_DRV_STATS_T *)((char *)p_cpmac_priv->device_mib
++ + sizeof(CPMAC_DEVICE_MIB_T));
++
++ p_drv_hal->owner = p_cpmac_priv;
++
++
++ switch(instance_num)
++ {
++
++ case 0:
++ mac_name="maca";
++
++ /* Also setting port information */
++ p_dev->if_port = AVALANCHE_CPMAC_LOW_PORT_ID;
++
++ break;
++
++ case 1:
++ mac_name="macb";
++
++ /* Also setting port information */
++ p_dev->if_port = AVALANCHE_CPMAC_HIGH_PORT_ID;
++
++ break;
++ }
++
++ if(mac_name)
++ mac_string=prom_getenv(mac_name);
++
++ if(!mac_string)
++ {
++ mac_string="08.00.28.32.06.02";
++ printk("Error getting mac from Boot enviroment for %s\n",p_dev->name);
++ printk("Using default mac address: %s\n",mac_string);
++ if(mac_name)
++ {
++ printk("Use Bootloader command:\n");
++ printk(" setenv %s xx.xx.xx.xx.xx.xx\n","<env_name>");
++ printk("to set mac address\n");
++ }
++ }
++
++ str2eaddr(p_cpmac_priv->mac_addr,mac_string);
++
++ for (i=0; i <= ETH_ALEN; i++)
++ {
++ /* This sets the hardware address */
++ p_dev->dev_addr[i] = p_cpmac_priv->mac_addr[i];
++ }
++
++ p_cpmac_priv->set_to_close = 1;
++ p_cpmac_priv->non_data_irq_expected = 0;
++
++//#if defined (CONFIG_MIPS_AVALANCHE_LED)
++// if((p_cpmac_priv->led_handle = avalanche_led_register("cpmac", instance_num)) == NULL)
++// {
++// errPrint("Could not allocate handle for CPMAC[%d] LED.\n", instance_num);
++// goto cpmac_init_mod_error;
++// }
++//#endif
++
++ if(cpmac_drv_init_module(p_drv_hal, p_dev, instance_num) != 0)
++ {
++ errPrint("Could not initialize the HAL for %s.\n", p_dev->name);
++ goto cpmac_init_mod_error;
++ }
++
++ /* initialize the CPMAC device */
++ if (cpmac_drv_init(p_drv_hal) == -1)
++ {
++ errPrint("HAL init failed for %s.\n", p_dev->name);
++ goto cpmac_init_device_error;
++ }
++
++ if(cpmac_p_probe_and_setup_device(p_cpmac_priv, &net_flags) == -1)
++ {
++ errPrint("Failed to configure up %s.\n", p_dev->name);
++ goto cpmac_init_device_error;
++ }
++
++ if(cpmac_p_setup_driver_params(p_cpmac_priv) == -1)
++ {
++ errPrint("Failed to set driver parameters for %s.\n", p_dev->name);
++ goto cpmac_init_device_error;
++ }
++
++ cpmac_p_rx_buf_setup(p_rx_chan_info);
++
++ /* initialize the timers for the net device */
++ if(cpmac_p_timer_init(p_cpmac_priv) == -1)
++ {
++ errPrint("Failed to set timer(s) for %s.\n", p_dev->name);
++ goto cpmac_timer_init_error;
++ }
++
++ p_dev->addr_len = 6;
++
++ p_dev->open = &cpmac_dev_open; /* i.e. Start Device */
++ p_dev->hard_start_xmit = &cpmac_dev_tx;
++ p_dev->stop = &cpmac_dev_close;
++ p_dev->get_stats = &cpmac_dev_get_net_stats;
++
++ p_dev->set_multicast_list = &cpmac_dev_mcast_set;
++ p_dev->set_mac_address = cpmac_dev_set_mac_addr;
++ /* Knocking off the default broadcast and multicast flags. Allowing the
++ device configuration to control the flags. */
++ p_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
++ p_dev->flags |= net_flags;
++
++ netif_carrier_off(p_dev);
++
++//#if defined (CONFIG_MIPS_AVALANCHE_LED)
++// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_OFF);
++//#endif
++
++ /* Tasklet is initialized at the isr registeration time. */
++ p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "CpmacBase", "Get", &p_dev->base_addr);
++ p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "CpmacSize", "Get", &p_cpmac_priv->dev_size);
++
++ request_mem_region(p_dev->base_addr, p_cpmac_priv->dev_size, p_dev->name);
++
++ retVal = 0;
++
++ if(g_init_enable_flag)
++ cpmac_p_dev_enable(p_dev);
++
++ return(retVal);
++
++cpmac_timer_init_error:
++cpmac_init_device_error :
++ cpmac_drv_cleanup(p_drv_hal);
++
++cpmac_init_mod_error:
++ kfree(p_drv_hal);
++
++ return (retVal);
++
++} /* cpmac_dev_init */
++
++
++/***************************************************************
++ * cpmac_p_dev_enable
++ *
++ * Returns:
++ * 0 on success, error code otherwise.
++ * Parms:
++ * dev Structure of device to be opened.
++ *
++ * This routine puts the driver and CPMAC adapter in a
++ * state where it is ready to send and receive packets.
++ *
++ *
++ **************************************************************/
++int cpmac_p_dev_enable( struct net_device *p_dev)
++{
++ int ret_val = 0;
++ int channel = 0;
++
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal;
++ CPMAC_RX_CHAN_INFO_T *p_rx_chan_info = p_cpmac_priv->rx_chan_info;
++ int max_length = p_rx_chan_info->chan->tot_buf_size;
++
++ p_cpmac_priv->set_to_close = 0;
++
++ if((ret_val = cpmac_drv_start(p_drv_hal, p_cpmac_priv->tx_chan_info,
++ p_cpmac_priv->rx_chan_info, CHAN_SETUP))==-1)
++ {
++ errPrint("%s error: failed to start the device.\n", p_dev->name);
++ ret_val = -1;
++ }
++ else if(p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev,"RX_UNICAST_SET",
++ "Set", &channel)!=0)
++ {
++ errPrint("%s error: device chan 0 could not be enabled.\n", p_dev->name);
++ ret_val = -1;
++ }
++ else if(p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, pszRX_MAXLEN, pszSet, &max_length) != 0)
++ {
++ errPrint(" CPMAC registers can't be written \n");
++ ret_val = -1;
++ }
++ else if(p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "TxIntDisable", "Set",
++ &p_cpmac_priv->tx_chan_info->tx_int_disable) != 0)
++ {
++ errPrint(" CPMAC registers can't be written \n");
++ ret_val = -1;
++ }
++ else
++ {
++ ; // Every thing went OK.
++ }
++
++ return(ret_val);
++} /* cpmac_dev_enable */
++
++
++static int cpmac_dev_open(struct net_device *p_dev)
++{
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++ CPMAC_ISR_INFO_T *p_isr_cb_param = &p_cpmac_priv->cpmac_isr;
++
++ if(!g_init_enable_flag)
++ cpmac_p_dev_enable(p_dev);
++
++ if(request_irq(p_isr_cb_param->intr, cpmac_hal_isr, SA_INTERRUPT,
++ "Cpmac Driver", p_isr_cb_param))
++ {
++ errPrint("Failed to register the irq %d for Cpmac %s.\n",
++ p_isr_cb_param->intr, p_dev->name);
++ return (-1);
++ }
++
++ netif_start_queue(p_dev);
++
++ MOD_INC_USE_COUNT;
++ p_cpmac_priv->stats->start_tick = jiffies;
++ dbgPrint("Started the network queue for %s.\n", p_dev->name);
++ return(0);
++}
++
++/***************************************************************
++ * cpmac_p_dev_disable
++ *
++ * Returns:
++ * An error code.
++ * Parms:
++ * dev The device structure of the device to
++ * close.
++ *
++ * This function shuts down the adapter.
++ *
++ **************************************************************/
++int cpmac_p_dev_disable(struct net_device *p_dev)
++{
++ int ret_val = 0;
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal;
++
++ set_bit(0, &p_cpmac_priv->set_to_close);
++ set_bit(0, &p_cpmac_priv->non_data_irq_expected);
++
++ /* The driver does not re-schedule the tasklet after kill is called. So, this
++ should take care of the bug in the kernel. */
++ tasklet_kill(&p_cpmac_priv->cpmac_isr.tasklet);
++
++ if(cpmac_drv_stop(p_drv_hal, p_cpmac_priv->tx_chan_info,
++ p_cpmac_priv->rx_chan_info,
++ CHAN_TEARDOWN | FREE_BUFFER | BLOCKING | COMPLETE) == -1)
++ {
++ ret_val = -1;
++ }
++ else
++ {
++ /* hope that the HAL closes down the tick timer.*/
++
++ dbgPrint("Device %s Closed.\n", p_dev->name);
++ p_cpmac_priv->stats->start_tick = jiffies;
++
++ p_cpmac_priv->link_speed = 100000000;
++ p_cpmac_priv->link_mode = 1;
++ netif_carrier_off(p_dev);
++
++//#if defined (CONFIG_MIPS_AVALANCHE_LED)
++// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_OFF);
++//#endif
++
++ clear_bit(0, &p_cpmac_priv->non_data_irq_expected);
++
++ }
++
++ return (ret_val);
++
++} /* cpmac_dev_close */
++
++
++/***************************************************************
++ * cpmac_dev_close
++ *
++ * Returns:
++ * An error code.
++ * Parms:
++ * dev The device structure of the device to
++ * close.
++ *
++ * This function shuts down the adapter.
++ *
++ **************************************************************/
++static int cpmac_dev_close(struct net_device *p_dev)
++{
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++ CPMAC_ISR_INFO_T *p_isr_cb_param = &p_cpmac_priv->cpmac_isr;
++
++ /* inform the upper layers. */
++ netif_stop_queue(p_dev);
++
++ if(!g_init_enable_flag)
++ cpmac_p_dev_disable(p_dev);
++ else
++ free_irq(p_isr_cb_param->intr, p_isr_cb_param);
++
++ MOD_DEC_USE_COUNT;
++
++ return(0);
++}
++
++static void cpmac_dev_mcast_set(struct net_device *p_dev)
++{
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal;
++ CPMAC_ABILITY_INFO_T *p_capability = p_cpmac_priv->ability_info;
++ HAL_FUNCTIONS *p_hal_funcs = p_drv_hal->hal_funcs;
++ HAL_DEVICE *p_hal_dev = p_drv_hal->hal_dev;
++ int val = 1;
++ int channel = 0;
++
++//#if defined (CONFIG_MIPS_AVALANCHE_LED)
++// if(netif_carrier_ok(p_dev))
++// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_ON);
++//#endif
++
++ if(p_dev->flags & IFF_PROMISC)
++ {
++ if(p_capability->promiscous)
++ {
++ /* multi mode in the HAL, check this */
++ val = 0;
++ p_hal_funcs->Control(p_hal_dev, pszRX_MULTI_ALL, "Clear", &val);
++
++ val = 1;
++ /* set the promiscous mode in the HAL */
++ p_hal_funcs->Control(p_hal_dev, pszRX_CAF_EN, pszSet, &val);
++ p_hal_funcs->Control(p_hal_dev, pszRX_PROM_CH, pszSet, &channel);
++
++ dbgPrint("%s set in the Promisc mode.\n", p_dev->name);
++ }
++ else
++ {
++ errPrint("%s not configured for Promisc mode.\n", p_dev->name);
++ }
++ }
++ else if(p_dev->flags & IFF_ALLMULTI)
++ {
++ if(p_capability->all_multi)
++ {
++ val = 0;
++ /* disable the promiscous mode in the HAL */
++ p_hal_funcs->Control(p_hal_dev, pszRX_CAF_EN, "Clear", &val);
++
++ val = 1;
++ /* set the all multi mode in the HAL */
++ p_hal_funcs->Control(p_hal_dev, pszRX_MULTI_ALL, pszSet, &val);
++ p_hal_funcs->Control(p_hal_dev, pszRX_MULT_CH, pszSet, &channel);
++
++ dbgPrint("%s has been set to the ALL_MULTI mode.\n", p_dev->name);
++ }
++ else
++ {
++ errPrint("%s not configured for ALL MULTI mode.\n", p_dev->name);
++ }
++ }
++ else if(p_dev->mc_count)
++ {
++ if(p_capability->multicast)
++ {
++ struct dev_mc_list *p_dmi = p_dev->mc_list;
++ int count;
++
++ val = 0;
++ /* clear all the previous data, we are going to populate new ones.*/
++ p_hal_funcs->Control(p_hal_dev, pszRX_MULTI_ALL, "Clear", &val);
++ /* disable the promiscous mode in the HAL */
++ p_hal_funcs->Control(p_hal_dev, pszRX_CAF_EN, pszSet, &val);
++
++ for(count = 0; count < p_dev->mc_count; count++, p_dmi = p_dmi->next)
++ {
++ p_hal_funcs->Control(p_hal_dev, "RX_MULTI_SINGLE", "Set", p_dmi->dmi_addr);
++ }
++
++ dbgPrint("%s configured for %d multicast addresses.\n", p_dev->name, p_dev->mc_count);
++ }
++ else
++ {
++ errPrint("%s has not been configuted for multicast handling.\n", p_dev->name);
++ }
++ }
++ else
++ {
++ val = 0;
++ /* clear all the previous data, we are going to populate new ones.*/
++ p_hal_funcs->Control(p_hal_dev, pszRX_MULTI_ALL, "Clear", &val);
++ /* disable the promiscous mode in the HAL */
++ p_hal_funcs->Control(p_hal_dev, pszRX_CAF_EN, pszSet, &val);
++ dbgPrint("Dev set to Unicast mode.\n");
++ }
++}
++
++static int cpmac_dev_set_mac_addr(struct net_device *p_dev,void * addr)
++{
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal;
++ HAL_FUNCTIONS *p_hal_funcs = p_drv_hal->hal_funcs;
++ HAL_DEVICE *p_hal_dev = p_drv_hal->hal_dev;
++ struct sockaddr *sa = addr;
++
++ memcpy(p_cpmac_priv->mac_addr,sa->sa_data,p_dev->addr_len);
++ memcpy(p_dev->dev_addr,sa->sa_data,p_dev->addr_len);
++ p_hal_funcs->Control(p_hal_dev, pszMacAddr, pszSet, p_cpmac_priv->mac_addr);
++
++ return 0;
++
++}
++
++/* VLAN is handled by vlan/vconfig support. Here, we just check for the
++ * 802.1q configuration of the device and en-queue the packet accordingly.
++ * We do not do any 802.1q processing here.
++ */
++static int cpmac_dev_tx( struct sk_buff *skb, struct net_device *p_dev)
++{
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal;
++ int channel = 0;
++ int ret_val = 0;
++ FRAGLIST send_frag_list[1];
++
++#ifdef CPMAC_8021Q_SUPPORT
++ if(skb->len < TCI_END_OFFSET)
++ {
++ /* Whee, frame shorter than 14 bytes !! We need to copy
++ * fragments to understand the frame. Too much work.
++ * Hmm, dump it. */
++
++ /* Free the buffer */
++ goto cpmac_dev_tx_drop_pkt;
++ }
++
++ /* 802.1p/q stuff */
++ if(IS_802_1Q_FRAME(skb->data + TPID_START_OFFSET))
++ {
++ /* IEEE 802.1q, section 8.8 and section 8.11.9 */
++ if(!p_cpmac_priv->enable_802_1q)
++ {
++ /* free the buffer */
++ goto cpmac_dev_tx_drop_pkt;
++ }
++
++ channel = GET_802_1P_CHAN(p_cpmac_priv->tx_chan_info->opened_chan,
++ skb->data[TCI_START_OFFSET]);
++
++ }
++ /* sending a non 802.1q frame, when configured for 802.1q: dump it.*/
++ else if(p_cpmac_priv->enable_802_1q)
++ {
++ /* free the buffer */
++ goto cpmac_dev_tx_drop_pkt;
++ }
++ else
++ {
++ ;/* it is the good old non 802.1q */
++ }
++#endif
++
++ send_frag_list->len = skb->len;
++ send_frag_list->data = skb->data;
++
++#ifdef CPMAC_TEST
++ xdump(skb->data, skb->len, "send");
++#endif
++
++ dma_cache_wback_inv((unsigned long)skb->data, skb->len);
++
++ if(p_drv_hal->hal_funcs->Send(p_drv_hal->hal_dev, send_frag_list, 1,
++ skb->len, skb, channel) != 0)
++ {
++ /* code here to stop the queue, when allowing tx timeout, perhaps next release.*/
++ p_cpmac_priv->net_dev_stats.tx_errors++;
++#ifndef TI_SLOW_PATH
++ /* Free the skb in case of Send return error */
++ dev_kfree_skb_any(skb);
++ p_cpmac_priv->net_dev_stats.tx_dropped++;
++ return 0;
++#endif
++ goto cpmac_dev_tx_drop_pkt;
++ }
++
++//#if defined (CONFIG_MIPS_AVALANCHE_LED)
++// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_TX_ACTIVITY);
++//#endif
++
++ return(ret_val);
++
++cpmac_dev_tx_drop_pkt:
++
++ p_cpmac_priv->net_dev_stats.tx_dropped++;
++ ret_val = -1;
++ return (ret_val);
++
++} /*cpmac_dev_tx */
++
++
++//------------------------------------------------------------------------------
++// Public functions : Called by outsiders to this file.
++//------------------------------------------------------------------------------
++
++
++void *cpmac_hal_malloc_buffer(unsigned int size, void* mem_base, unsigned int mem_range,
++ OS_SETUP *p_os_setup, HAL_RECEIVEINFO *HalReceiveInfo,
++ OS_RECEIVEINFO **osReceiveInfo, OS_DEVICE *p_dev)
++{
++ CPMAC_RX_CHAN_INFO_T *p_rx_chan_info = (CPMAC_RX_CHAN_INFO_T *)p_os_setup;
++ int tot_buf_size = p_rx_chan_info->chan->tot_buf_size;
++ int tot_reserve_bytes = p_rx_chan_info->chan->tot_reserve_bytes;
++ struct sk_buff *p_skb;
++ void *ret_ptr;
++
++ /* use TI SKB private pool */
++ p_skb = dev_alloc_skb(tot_buf_size);
++
++ if(p_skb == NULL)
++ {
++ errPrint("Failed to allocate skb for %s.\n", ((struct net_device*)p_dev)->name);
++ return (NULL);
++ }
++
++ p_skb->dev = p_dev;
++ skb_reserve(p_skb, tot_reserve_bytes);
++
++ *osReceiveInfo = p_skb;
++
++ ret_ptr = skb_put(p_skb, p_rx_chan_info->chan->buffer_size);
++
++ return(ret_ptr);
++}
++
++void cpmac_hal_isr(int irq, void *p_param, struct pt_regs *regs)
++{
++ CPMAC_ISR_INFO_T *p_cb_param = (CPMAC_ISR_INFO_T*) p_param;
++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cb_param->owner;
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_drv_hal->owner;
++ int pkts_to_handle = 0;
++
++ if(p_cpmac_priv->non_data_irq_expected)
++ {
++ p_cb_param->hal_isr(p_drv_hal->hal_dev, &pkts_to_handle);
++ p_drv_hal->hal_funcs->PacketProcessEnd(p_drv_hal->hal_dev);
++ }
++ else if(!p_cpmac_priv->set_to_close)
++ tasklet_schedule(&((CPMAC_ISR_INFO_T*) p_param)->tasklet);
++ else
++ ; // back off from doing anything more. We are closing down.
++}
++
++void cpmac_handle_tasklet(unsigned long data)
++{
++ CPMAC_ISR_INFO_T *p_cb_param = (CPMAC_ISR_INFO_T*) data;
++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cb_param->owner;
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_drv_hal->owner;
++ int pkts_to_handle;
++
++ p_cb_param->hal_isr(p_drv_hal->hal_dev, &pkts_to_handle);
++
++ if(test_bit(0, &p_cpmac_priv->non_data_irq_expected) || !pkts_to_handle)
++ p_drv_hal->hal_funcs->PacketProcessEnd(p_drv_hal->hal_dev);
++ else if(!test_bit(0, &p_cpmac_priv->set_to_close))
++ tasklet_schedule(&p_cb_param->tasklet);
++ else
++ ; // Back off from processing packets we are closing down.
++}
++
++int cpmac_hal_control(OS_DEVICE *p_dev, const char *key,
++ const char *action, void *value)
++{
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++ int ret_val = -1;
++
++ if(key == NULL)
++ {
++ dbgPrint("Encountered NULL key.\n");
++ return (-1);
++ }
++
++ if(cpmac_ci_strcmp(key, "Sleep") == 0 && value != NULL)
++ {
++ unsigned int clocks_per_tick = cpmac_cpu_freq/HZ;
++ unsigned int requested_clocks = *(unsigned int*)value;
++ unsigned int requested_ticks = (requested_clocks + clocks_per_tick - 1)/clocks_per_tick;
++ mdelay(requested_ticks);
++ ret_val = 0;
++ }
++ else if(cpmac_ci_strcmp(key, "StateChange") == 0)
++ {
++ ret_val = cpmac_p_process_status_ind(p_cpmac_priv);
++ }
++ else if(cpmac_ci_strcmp(key, "Tick") == 0 && action != NULL)
++ {
++ if(cpmac_ci_strcmp(action, "Set") == 0 && value != NULL)
++ {
++ if(*(unsigned int*)value == 0)
++ {
++ cpmac_p_stop_timer(p_cpmac_priv->timer + TICK_TIMER);
++ ret_val = 0;
++ }
++ else
++ {
++ unsigned int clocks_per_tick = cpmac_cpu_freq/HZ;
++ unsigned int requested_clocks = *(unsigned int*)value;
++ unsigned int requested_ticks = (requested_clocks + clocks_per_tick - 1)/clocks_per_tick;
++
++ p_cpmac_priv->delay_ticks = requested_ticks; /* save it for re-triggering */
++ ret_val = cpmac_p_start_timer(p_cpmac_priv->timer + TICK_TIMER,
++ p_cpmac_priv->delay_ticks);
++ }
++ }
++ else if(cpmac_ci_strcmp(action, "Clear") == 0)
++ {
++ ret_val = cpmac_p_stop_timer(p_cpmac_priv->timer + TICK_TIMER);
++ }
++ else
++ ;
++ }
++ else if(cpmac_ci_strcmp(key, "MacAddr") == 0 && action != NULL)
++ {
++ if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL)
++ {
++ *(char **)value = p_cpmac_priv->mac_addr;
++ ret_val = 0;
++ }
++ }
++ else if(cpmac_ci_strcmp(key, "CpuFreq") == 0)
++ {
++ if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL)
++ {
++ *(unsigned int *)value = cpmac_cpu_freq;
++ dbgPrint("Cpu frequency for cpmacs is %u\n",cpmac_cpu_freq);
++ ret_val = 0;
++ }
++ }
++ else if(cpmac_ci_strcmp(key, "SioFlush") == 0)
++ {
++ ret_val = 0;
++ dbgPrint("\n");
++ }
++ else if(cpmac_ci_strcmp(key, "CpmacFrequency") == 0)
++ {
++ /* For Sangam cpmac clock is off the PBUS */
++ /* OS Needs to supply CORRECT frequency */
++ if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL)
++ {
++ *(unsigned int *)value = CONFIG_AR7_SYS * 1000 * 1000;
++ ret_val = 0;
++ }
++ }
++ /* For now, providing back the default values. */
++ else if(cpmac_ci_strcmp(key, "MdioClockFrequency") == 0)
++ {
++ if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL)
++ {
++ *(unsigned int *)value = 2200000; /*DEFAULT */
++ ret_val = 0;
++ }
++ }
++ /* For now, providing back the default values. */
++ else if(cpmac_ci_strcmp(key, "MdioBusFrequency") == 0)
++ {
++ /* For Sangam MdioBusFreq is off the PBUS */
++ if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL)
++ {
++ *(unsigned int *)value = CONFIG_AR7_SYS * 1000 * 1000;
++ ret_val = 0;
++ }
++ }
++
++#if 0
++#if defined(CONFIG_AVALANCHE_AUTO_MDIX)
++ /* supporting Mdio Mdix switching */
++ else if(cpmac_ci_strcmp(key, hcMdioMdixSwitch) == 0)
++ {
++ /* For Sangam Mdio-switching action should be always "set"*/
++ if(cpmac_ci_strcmp(action, hcSet) == 0 && value != NULL )
++ {
++ unsigned int mdix = *((unsigned int *) value) ;
++
++ if(mdix)
++ avalanche_set_phy_into_mdix_mode();
++
++ else
++ avalanche_set_phy_into_mdi_mode();
++
++ ret_val = 0;
++ }
++
++ }
++#endif
++#endif
++ else if(cpmac_ci_strcmp(key, hcMdioMdixSwitch) == 0)
++ {
++ /* For Sangam Mdio-switching action should be always "set"*/
++ if(cpmac_ci_strcmp(action, hcSet) == 0 && value != NULL )
++ {
++ unsigned int mdix = *((unsigned int *) value) ;
++
++#ifdef CONFIG_AR7_MDIX
++ avalanche_set_mdix_on_chip(0xa8610000 , mdix ? 1: 0);
++#endif
++
++ ret_val = 0;
++ }
++
++ }
++
++ return(ret_val);
++}
++
++
++int cpmac_hal_receive(OS_DEVICE *p_dev, FRAGLIST *fragList,
++ unsigned int fragCount,
++ unsigned int packet_size,
++ HAL_RECEIVEINFO *hal_receive_info,
++ unsigned int mode)
++{
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal;
++ struct sk_buff *p_skb = fragList[0].OsInfo;
++ p_skb->len = fragList[0].len;
++
++ /* invalidate the cache. */
++ dma_cache_inv((unsigned long)p_skb->data, fragList[0].len);
++#ifdef CPMAC_TEST
++ xdump(p_skb->data, p_skb->len, "recv");
++#endif
++#ifdef CPMAC_8021Q_SUPPORT
++ /* 802.1q stuff, just does the basic checking here. */
++ if(!p_cpmac_priv->enable_802_1q &&
++ p_skb->len > TCI_END_OFFSET &&
++ IS_802_1Q_FRAME(p_skb->data + TPID_START_OFFSET))
++ {
++ goto cpmac_hal_recv_frame_mismatch;
++ }
++#endif
++ if(fragCount > 1)
++ {
++ int len;
++ struct sk_buff *p_temp_skb;
++ CPMAC_RX_CHAN_INFO_T *p_rx_chan_info = p_cpmac_priv->rx_chan_info;
++ int count;
++
++ dbgPrint("Recv: It is multifragment for %s.\n", p_dev->name);
++
++ p_skb = dev_alloc_skb(packet_size +
++ p_rx_chan_info->chan->tot_reserve_bytes);
++ if(p_skb == NULL)
++ {
++ p_cpmac_priv->net_dev_stats.rx_errors++;
++ goto cpmac_hal_recv_alloc_failed;
++ }
++
++ p_skb->dev = p_dev;
++ skb_reserve(p_skb, p_rx_chan_info->chan->tot_reserve_bytes);
++
++ for(count = 0; count < fragCount; count++)
++ {
++ p_temp_skb = fragList[count].OsInfo;
++ len = fragList[count].len;
++
++ dma_cache_inv((unsigned long)p_temp_skb->data, len);
++
++ memcpy(skb_put(p_skb, len), p_temp_skb->data, len);
++ dev_kfree_skb_any(p_temp_skb);
++ }
++ }
++
++
++#if defined(CONFIG_MIPS_AVALANCHE_MARVELL)
++ /* Fetch the receiving port information from EGRESS TRAILOR Bytes*/
++ p_dev->if_port = (unsigned char)p_skb->data[packet_size -(EGRESS_TRAILOR_LEN-1)] + AVALANCHE_MARVELL_BASE_PORT_ID;
++ skb_trim(p_skb, packet_size - EGRESS_TRAILOR_LEN);
++#else
++ /* set length & tail */
++ skb_trim(p_skb, packet_size);
++#endif
++
++ p_skb->protocol = eth_type_trans(p_skb, p_dev);
++
++ netif_rx(p_skb);
++
++//#if defined (CONFIG_MIPS_AVALANCHE_LED)
++// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_RX_ACTIVITY);
++//#endif
++
++ p_cpmac_priv->net_dev_stats.rx_packets++;
++ p_cpmac_priv->net_dev_stats.rx_bytes += packet_size;
++
++ p_drv_hal->hal_funcs->RxReturn(hal_receive_info,1);
++
++ return(0);
++
++cpmac_hal_recv_alloc_failed:
++
++#ifdef CPMAC_8021Q_SUPPORT
++cpmac_hal_recv_frame_mismatch:
++#endif
++
++ fragCount--;
++
++ do
++ {
++ dev_kfree_skb_any(fragList[fragCount].OsInfo);
++ }
++ while(fragCount--);
++
++ p_cpmac_priv->net_dev_stats.rx_dropped++;
++
++ return(-1);
++} /*cpmac_receive*/
++
++
++void cpmac_hal_tear_down_complete(OS_DEVICE*a, int b, int ch)
++{
++ dbgPrint("what to do with this.\n");
++}
++
++
++int cpmac_hal_send_complete(OS_SENDINFO *p_skb)
++{
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_skb->dev->priv;
++
++ p_cpmac_priv->net_dev_stats.tx_packets++;
++ p_cpmac_priv->net_dev_stats.tx_bytes += p_skb->len;
++
++ dev_kfree_skb_any(p_skb);
++
++ return(0);
++}
++
++
++int cpmac_reset(CPMAC_PRIVATE_INFO_T *p_cpmac_priv)
++{
++ // code here to reset the device/hal. Not now.
++
++ netif_wake_queue(p_cpmac_priv->owner);
++ return(0);
++}
++
++#ifdef CPMAC_TEST
++
++#define isprint(a) ((a >=' ')&&(a<= '~'))
++void xdump( u_char* cp, int length, char* prefix )
++{
++ int col, count;
++ u_char prntBuf[120];
++ u_char* pBuf = prntBuf;
++ count = 0;
++ while(count < length){
++ pBuf += sprintf( pBuf, "%s", prefix );
++ for(col = 0;count + col < length && col < 16; col++){
++ if (col != 0 && (col % 4) == 0)
++ pBuf += sprintf( pBuf, " " );
++ pBuf += sprintf( pBuf, "%02X ", cp[count + col] );
++ }
++ while(col++ < 16){ /* pad end of buffer with blanks */
++ if ((col % 4) == 0)
++ sprintf( pBuf, " " );
++ pBuf += sprintf( pBuf, " " );
++ }
++ pBuf += sprintf( pBuf, " " );
++ for(col = 0;count + col < length && col < 16; col++){
++ if (isprint((int)cp[count + col]))
++ pBuf += sprintf( pBuf, "%c", cp[count + col] );
++ else
++ pBuf += sprintf( pBuf, "." );
++ }
++ sprintf( pBuf, "\n" );
++ // SPrint(prntBuf);
++ printk(prntBuf);
++ count += col;
++ pBuf = prntBuf;
++ }
++
++} /* close xdump(... */
++#endif
++
++
++static int __init cpmac_dev_probe(void)
++{
++ int retVal = 0;
++ int unit;
++ int instance_count = CONFIG_MIPS_CPMAC_PORTS;
++
++ //cpmac_cpu_freq = avalanche_clkc_get_freq(CLKC_MIPS);
++ cpmac_cpu_freq = CONFIG_AR7_CPU * 1000 * 1000;
++
++ build_psp_config();
++
++ for(unit = 0; unit < instance_count; unit++)
++ {
++ struct net_device *p_dev;
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv;
++ size_t dev_size;
++ int failed;
++
++ dev_size = sizeof(struct net_device)
++ + sizeof(CPMAC_PRIVATE_INFO_T);
++
++
++ if((p_dev = (struct net_device *) kmalloc(dev_size, GFP_KERNEL)) == NULL)
++ {
++ dbgPrint( "Could not allocate memory for device.\n" );
++ retVal = -ENOMEM;
++ break;
++ }
++
++ memset(p_dev, 0, dev_size );
++
++ p_dev->priv = p_cpmac_priv
++ = (CPMAC_PRIVATE_INFO_T*)(((char *) p_dev) + sizeof(struct net_device));
++ p_cpmac_priv->owner = p_dev;
++
++ ether_setup(p_dev);
++
++ p_cpmac_priv->instance_num = unit;
++ p_dev->init = cpmac_dev_init;
++
++ g_dev_array[p_cpmac_priv->instance_num] = p_dev;
++
++#if defined CONFIG_MIPS_CPMAC_INIT_BUF_MALLOC
++ g_init_enable_flag = 1;
++ printk("Cpmac driver is allocating buffer memory at init time.\n");
++#endif
++
++ /* This section gives a default value by the number of PHY in order to
++ * replace the default MACRO. */
++ {
++ char *mac_port = prom_getenv("MAC_PORT"); /* Internal: 0, External: 1 */
++ if(0 == strcmp(mac_port, "1")) {
++ printk("Using the MAC with external PHY\n");
++ cfg_start_link_speed = _CPMDIO_NOPHY;
++ cpmac_max_frame_size = CPMAC_MAX_FRAME_SIZE + 4;
++ }
++ else {
++ printk("Using the MAC with internal PHY\n");
++ cfg_start_link_speed = CFG_START_LINK_SPEED;
++ cpmac_max_frame_size = CPMAC_MAX_FRAME_SIZE;
++ }
++ g_cfg_start_link_params = cfg_start_link_speed;
++ }
++
++ cpmac_p_detect_manual_cfg(cfg_link_speed, cfg_link_mode, cpmac_debug_mode);
++
++ failed = register_netdev(p_dev);
++ if (failed)
++ {
++ dbgPrint("Could not register device for inst %d because of reason \
++ code %d.\n", unit, failed);
++ retVal = -1;
++ kfree(p_dev);
++ break;
++ }
++ else
++ {
++
++ char proc_name[100];
++ int proc_category_name_len = 0;
++
++ p_cpmac_priv->next_device = last_cpmac_device;
++ last_cpmac_device = p_dev;
++
++ dbgPrint(" %s irq=%2d io=%04x\n",p_dev->name, (int) p_dev->irq,
++ (int) p_dev->base_addr);
++
++ strcpy(proc_name, "avalanche/");
++ strcat(proc_name, p_dev->name);
++ proc_category_name_len = strlen(proc_name);
++
++ strcpy(proc_name + proc_category_name_len, "_rfc2665_stats");
++ create_proc_read_entry(proc_name,0,NULL,cpmac_p_read_rfc2665_stats, p_dev);
++
++ }
++ }
++
++ if(retVal == 0)
++ {
++ /* To maintain backward compatibility with NSP. */
++ gp_stats_file = create_proc_entry("avalanche/cpmac_stats", 0644, NULL);
++ if(gp_stats_file)
++ {
++ gp_stats_file->read_proc = cpmac_p_read_stats;
++ gp_stats_file->write_proc = cpmac_p_write_stats;
++ }
++ create_proc_read_entry("avalanche/cpmac_link", 0, NULL, cpmac_p_read_link, NULL);
++ create_proc_read_entry("avalanche/cpmac_ver", 0, NULL, cpmac_p_get_version, NULL);
++
++ }
++
++ cpmac_devices_installed = unit;
++ dbgPrint("Installed %d cpmac instances.\n", unit);
++ return ( (unit >= 0 ) ? 0 : -ENODEV );
++
++} /* init_module */
++
++
++/***************************************************************
++ * cleanup_module
++ *
++ * Returns:
++ * Nothing
++ * Parms:
++ * None
++ *
++ * Goes through the CpmacDevices list and frees the device
++ * structs and memory associated with each device (lists
++ * and buffers). It also ureserves the IO port regions
++ * associated with this device.
++ *
++ **************************************************************/
++
++void cpmac_exit(void)
++{
++ struct net_device *p_dev;
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv;
++
++ while (cpmac_devices_installed)
++ {
++ char proc_name[100];
++ int proc_category_name_len = 0;
++
++ p_dev = last_cpmac_device;
++ p_cpmac_priv = (CPMAC_PRIVATE_INFO_T *) p_dev->priv;
++
++ dbgPrint("Unloading %s irq=%2d io=%04x\n",p_dev->name, (int) p_dev->irq, (int) p_dev->base_addr);
++
++ if(g_init_enable_flag)
++ cpmac_p_dev_disable(p_dev);
++
++ cpmac_drv_cleanup(p_cpmac_priv->drv_hal);
++
++//#if defined (CONFIG_MIPS_AVALANCHE_LED)
++// avalanche_led_unregister(p_cpmac_priv->led_handle);
++//#endif
++ strcpy(proc_name, "avalanche/");
++ strcat(proc_name, p_dev->name);
++ proc_category_name_len = strlen(proc_name);
++
++ strcpy(proc_name + proc_category_name_len, "_rfc2665_stats");
++ remove_proc_entry(proc_name, NULL);
++
++ release_mem_region(p_dev->base_addr, p_cpmac_priv->dev_size);
++ unregister_netdev(p_dev);
++ last_cpmac_device = p_cpmac_priv->next_device;
++
++ kfree(p_cpmac_priv->drv_hal);
++ kfree(p_dev);
++
++ cpmac_devices_installed--;
++ }
++
++ if(gp_stats_file)
++ remove_proc_entry("avalanche/cpmac_stats", NULL);
++
++ remove_proc_entry("avalanche/cpmac_link", NULL);
++ remove_proc_entry("avalanche/cpmac_ver", NULL);
++
++ psp_config_cleanup();
++}
++
++
++module_init(cpmac_dev_probe);
++module_exit(cpmac_exit);
+diff -urN linux.old/drivers/net/avalanche_cpmac/cpmac.h linux.dev/drivers/net/avalanche_cpmac/cpmac.h
+--- linux.old/drivers/net/avalanche_cpmac/cpmac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpmac.h 2005-07-12 02:48:42.043594000 +0200
+@@ -0,0 +1,379 @@
++/******************************************************************************
++ * FILE PURPOSE: CPMAC Linux Network Device Driver Header
++ ******************************************************************************
++ * FILE NAME: cpmac.h
++ *
++ * DESCRIPTION: CPMAC Network Device Driver Header
++ *
++ * REVISION HISTORY:
++ * Date Name Details
++ *-----------------------------------------------------------------------------
++ * 27 Nov 2002 Suraj S Iyer Initial Create.
++ * 09 Jun 2003 Suraj S Iyer Preparing for GA.
++ *
++ * (C) Copyright 2003, Texas Instruments, Inc
++ *******************************************************************************/
++
++#ifndef CPMAC_H
++#define CPMAC_H
++
++#include <linux/timer.h>
++#include <linux/netdevice.h>
++#include <asm/semaphore.h>
++#include <linux/ctype.h>
++#include <linux/interrupt.h>
++
++#include "cpmacHalLx.h"
++/*-----------------------------------------------------------------------------
++ * Config macros. Use these to config the driver.
++ *---------------------------------------------------------------------------*/
++#define CPMAC_MAX_FRAME_SIZE 1518
++
++#if defined(CONFIG_AR7WRD) || defined(CONFIG_AR7WI) || defined(CONFIG_AR7VWI)|| defined(CONFIG_AR7VW)
++#define CFG_RX_NUM_BUF_DESC 64
++#define CFG_RX_NUM_BUF_SERVICE 32
++#else
++#define CFG_RX_NUM_BUF_DESC 16
++#define CFG_RX_NUM_BUF_SERVICE 8
++#endif
++
++#define CFG_RX_BUF_OFFSET 0
++
++#define CFG_TX_NUM_BUF_DESC 128
++#define CFG_TX_NUM_BUF_SERVICE 20
++#define CFG_TX_BUF_OFFSET 0 /* Lets not change this. */
++#define CFG_TX_TIMEOUT 2000 /* ticks*/
++#define CFG_TX_INT_DISABLE 1 /* Disable the Tx Complete interrupt */
++
++#define CFG_JUMBO_FRAMES 1
++#define CFG_SHORT_FRAMES 1
++#define CFG_PROMISCOUS 1
++#define CFG_BROADCAST 1
++#define CFG_MULTICAST 1
++#define CFG_ALL_MULTI (1*(CFG_MULTICAST))
++#define CFG_AUTO_NEGOTIATION 1
++
++#if defined (CONFIG_MIPS_AVALANCHE_MARVELL)
++#define EGRESS_TRAILOR_LEN 4
++#define CFG_START_LINK_SPEED (_CPMDIO_NOPHY)
++#undef CPMAC_MAX_FRAME_SIZE
++#define CPMAC_MAX_FRAME_SIZE (1518 + EGRESS_TRAILOR_LEN)
++#else
++#define CFG_START_LINK_SPEED (_CPMDIO_10 | _CPMDIO_100 | _CPMDIO_HD | _CPMDIO_FD) /* auto nego */
++#endif
++
++#define CFG_LOOP_BACK 1
++#define CFG_TX_FLOW_CNTL 0
++#define CFG_RX_FLOW_CNTL 0
++#define CFG_TX_PACING 0
++#define CFG_RX_PASS_CRC 0
++#define CFG_QOS_802_1Q 0
++#define CFG_TX_NUM_CHAN 1
++
++
++/*-----------------------------------------------------------------------------
++ * Private macros.
++ *---------------------------------------------------------------------------*/
++#define MAX_TIMER 2
++#define TX_TIMER 0
++#define TICK_TIMER 0
++#define MAX_TX_CHAN 8
++
++#define CPMAC_LINK_OFF 0
++#define CPMAC_LINK_ON 1
++/*#define CPMAC_SPEED_100 2
++#define CPMAC_SPEED_10 3
++#define CPMAC_FULL_DPLX 4
++#define CPMAC_HALF_DPLX 5*/
++#define CPMAC_RX_ACTIVITY 2
++#define CPMAC_TX_ACTIVITY 3
++
++struct cpmac_timer_info;
++
++typedef int (*CPMAC_HAL_ISR_FUNC_T)(HAL_DEVICE*, int*);
++typedef int (*CPMAC_TIMEOUT_CB_T)(struct cpmac_timer_info*);
++
++typedef struct cpmac_ability_info
++{
++ int promiscous;
++ int broadcast;
++ int multicast;
++ int all_multi;
++ int loop_back;
++ int jumbo_frames;
++ int short_frames;
++ int auto_negotiation;
++ int tx_flow_control;
++ int rx_flow_control;
++ int tx_pacing;
++ int link_speed;
++ int rx_pass_crc;
++ int qos_802_1q;
++ int tx_num_chan;
++}
++CPMAC_ABILITY_INFO_T;
++
++#ifdef DEBUG
++typedef struct cpmac_timer_info
++{
++ void *owner;
++ UINT32 delay_ticks;
++ WDOG_ID timer_id;
++ UINT32 is_running;
++ UINT32 timer_set_at;
++ CPMAC_TIMEOUT_CB_T timeout_CB;
++} CPMAC_TIMER_INFO_T;
++
++typedef struct
++{
++ void *owner;
++ unsigned int num_cl_desc;
++ CL_DESC *cl_desc_tbl;
++ M_CL_CONFIG *m_cl_blk_config;
++ NET_POOL *net_pool;
++ CL_POOL_ID clPoolId;
++
++} CPMAC_NET_MEM_INFO_T;
++
++#endif
++
++typedef struct
++{
++ void *owner;
++ CPMAC_HAL_ISR_FUNC_T hal_isr;
++ struct tasklet_struct tasklet;
++ int intr;
++
++} CPMAC_ISR_INFO_T;
++
++typedef struct cpmac_chan
++{
++ int num_BD;
++ int buffer_size;
++ int buffer_offset;
++ int service_max;
++ int state;
++ int tot_buf_size;
++ int tot_reserve_bytes;
++
++} CPMAC_CHAN_T;
++
++#define CHAN_CLOSE 0
++#define CHAN_OPENED 1
++
++typedef struct
++{
++ int cfg_chan;
++ int dev_chan;
++ int opened_chan;
++ CPMAC_CHAN_T chan[1];
++ int enable_802_1q;
++
++} CPMAC_RX_CHAN_INFO_T;
++
++typedef struct
++{
++ int cfg_chan;
++ int dev_chan;
++ int opened_chan;
++ int tx_int_disable;
++ CPMAC_CHAN_T chan[MAX_TX_CHAN];
++
++} CPMAC_TX_CHAN_INFO_T;
++
++
++
++typedef struct
++{
++ void *owner;
++ HAL_FUNCTIONS *hal_funcs;
++ HAL_DEVICE *hal_dev;
++ OS_FUNCTIONS *os_funcs;
++// SEM_ID chan_teardown_sem;
++ int non_data_irq_expected;
++} CPMAC_DRV_HAL_INFO_T;
++
++
++typedef struct
++{
++ unsigned long tx_discards;
++ unsigned long rx_discards;
++ unsigned long start_tick;
++
++} CPMAC_DRV_STATS_T;
++
++typedef struct
++{
++ unsigned long ifInGoodFrames;
++ unsigned long ifInBroadcasts;
++ unsigned long ifInMulticasts;
++ unsigned long ifInPauseFrames;
++ unsigned long ifInCRCErrors;
++ unsigned long ifInAlignCodeErrors;
++ unsigned long ifInOversizedFrames;
++ unsigned long ifInJabberFrames;
++ unsigned long ifInUndersizedFrames;
++ unsigned long ifInFragments;
++ unsigned long ifInFilteredFrames;
++ unsigned long ifInQosFilteredFrames;
++ unsigned long ifInOctets;
++ unsigned long ifOutGoodFrames;
++ unsigned long ifOutBroadcasts;
++ unsigned long ifOutMulticasts;
++ unsigned long ifOutPauseFrames;
++ unsigned long ifDeferredTransmissions;
++ unsigned long ifCollisionFrames;
++ unsigned long ifSingleCollisionFrames;
++ unsigned long ifMultipleCollisionFrames;
++ unsigned long ifExcessiveCollisionFrames;
++ unsigned long ifLateCollisions;
++ unsigned long ifOutUnderrun;
++ unsigned long ifCarrierSenseErrors;
++ unsigned long ifOutOctets;
++ unsigned long if64OctetFrames;
++ unsigned long if65To127OctetFrames;
++ unsigned long if128To255OctetFrames;
++ unsigned long if256To511OctetFrames;
++ unsigned long if512To1023OctetFrames;
++ unsigned long if1024ToUPOctetFrames;
++ unsigned long ifNetOctets;
++ unsigned long ifRxSofOverruns;
++ unsigned long ifRxMofOverruns;
++ unsigned long ifRxDMAOverruns;
++
++} CPMAC_DEVICE_MIB_T;
++
++
++typedef struct
++{
++ void *owner;
++ int timer_count;
++ int timer_created;
++ struct timer_list timer[1];
++ CPMAC_DRV_HAL_INFO_T *drv_hal;
++ unsigned int num_of_intr;
++ CPMAC_ISR_INFO_T cpmac_isr;
++ unsigned int link_speed;
++ unsigned int link_mode;
++ unsigned int enable_802_1q;
++ unsigned int timer_access_hal;
++ unsigned int loop_back;
++ CPMAC_RX_CHAN_INFO_T *rx_chan_info;
++ CPMAC_TX_CHAN_INFO_T *tx_chan_info;
++ CPMAC_ABILITY_INFO_T *ability_info;
++ CPMAC_DEVICE_MIB_T *device_mib;
++ CPMAC_DRV_STATS_T *stats;
++ unsigned int flags;
++ unsigned int delay_ticks;
++ char mac_addr[6];
++ struct net_device_stats net_dev_stats;
++// rwlock_t rw_lock;
++ int set_to_close;
++ struct net_device *next_device;
++ unsigned int instance_num;
++ unsigned int non_data_irq_expected;
++ unsigned long dev_size;
++ void* led_handle;
++} CPMAC_PRIVATE_INFO_T;
++
++
++/* Private flags */
++
++/* bit 0 to 31, bit 32 is used to indicate set or reset */
++
++#define IFF_PRIV_SHORT_FRAMES 0x00010000
++#define IFF_PRIV_JUMBO_FRAMES 0x00020000
++#define IFF_PRIV_AUTOSPEED 0x00080000
++#define IFF_PRIV_LINK10_HD 0x00100000
++#define IFF_PRIV_LINK10_FD 0x00200000
++#define IFF_PRIV_LINK100_HD 0x00400000
++#define IFF_PRIV_LINK100_FD 0x00800000
++#define IFF_PRIV_8021Q_EN 0x01000000
++#define IFF_PRIV_NUM_TX_CHAN 0x02000000
++#define IFF_PRIV_TX_FLOW_CNTL 0x04000000
++#define IFF_PRIV_RX_FLOW_CNTL 0x08000000
++#define IFF_PRIV_TX_PACING 0x10000000
++#define IFF_PRIV_RX_PASS_CRC 0x20000000
++
++#define PRIVCSFLAGS 0x200
++#define PRIVCGFLAGS 0x201
++
++
++#define BLOCKING 1
++#define CHAN_TEARDOWN 2
++#define CHAN_SETUP 4
++#define COMPLETE 8
++#define FREE_BUFFER 16
++
++
++static const char pszStats0[] = "Stats0";
++static const char pszStats1[] = "Stats1";
++static const char pszStats2[] = "Stats2";
++static const char pszStats3[] = "Stats3";
++static const char pszStats4[] = "Stats4";
++static const char pszStatsDump[] = "StatsDump";
++static const char pszStatsClear[] = "StatsClear";
++static const char pszRX_PASS_CRC[] = "RX_PASS_CRC";
++static const char pszRX_QOS_EN[] = "RX_QOS_EN";
++static const char pszRX_NO_CHAIN[] = "RX_NO_CHAIN";
++static const char pszRX_CMF_EN[] = "RX_CMF_EN";
++static const char pszRX_CSF_EN[] = "RX_CSF_EN";
++static const char pszRX_CEF_EN[] = "RX_CEF_EN";
++static const char pszRX_CAF_EN[] = "RX_CAF_EN";
++static const char pszRX_PROM_CH[] = "RX_PROM_CH";
++static const char pszRX_BROAD_EN[] = "RX_BROAD_EN";
++static const char pszRX_BROAD_CH[] = "RX_BROAD_CH";
++static const char pszRX_MULT_EN[] = "RX_MULT_EN";
++static const char pszRX_MULT_CH[] = "RX_MULT_CH";
++static const char pszTX_PTYPE[] = "TX_PTYPE";
++static const char pszTX_PACE[] = "TX_PACE";
++static const char pszMII_EN[] = "MII_EN";
++static const char pszTX_FLOW_EN[] = "TX_FLOW_EN";
++static const char pszRX_FLOW_EN[] = "RX_FLOW_EN";
++static const char pszRX_MAXLEN[] = "RX_MAXLEN";
++static const char pszRX_FILTERLOWTHRESH[] = "RX_FILTERLOWTHRESH";
++static const char pszRX0_FLOWTHRESH[] = "RX0_FLOWTHRESH";
++static const char pszRX_UNICAST_SET[] = "RX_UNICAST_SET";
++static const char pszRX_UNICAST_CLEAR[] = "RX_UNICAST_CLEAR";
++static const char pszMdioConnect[] = "MdioConnect";
++static const char pszMacAddr[] = "MacAddr";
++static const char pszTick[] = "Tick";
++static const char pszRX_MULTICAST[] = "RX_MULTICAST";
++static const char pszRX_MULTI_ALL[] = "RX_MULTI_ALL";
++static const char pszRX_MULTI_SINGLE[] = "RX_MULTI_SINGLE";
++
++static const char pszSet[] = "Set";
++static const char pszGet[] = "Get";
++static const char pszClear[] = "Clear";
++
++
++void *cpmac_hal_malloc_buffer(unsigned int size, void *MemBase, unsigned int MemRange,
++ HAL_DEVICE *HalDev, HAL_RECEIVEINFO *HalReceiveInfo,
++ OS_RECEIVEINFO **OsReceiveInfo, OS_DEVICE *OsDev);
++
++void cpmac_hal_tear_down_complete(OS_DEVICE*, int, int);
++int cpmac_hal_control(OS_DEVICE *p_END_obj, const char *key,
++ const char *action, void *value);
++int cpmac_hal_receive(OS_DEVICE *p_END_obj, FRAGLIST *fragList,
++ unsigned int FragCount, unsigned int pkt_len,
++ HAL_RECEIVEINFO *halReceiveInfo,
++ unsigned int mode);
++int cpmac_hal_send_complete(OS_SENDINFO*);
++
++void cpmac_hal_isr(int irq, void *p_param, struct pt_regs *p_cb_param);
++void cpmac_handle_tasklet(unsigned long data);
++
++inline static int cpmac_ci_strcmp(const char *s1, const char *s2)
++{
++ while(*s1 && *s2)
++ {
++ if(tolower(*s1) != tolower(*s2))
++ break;
++ s1++;
++ s2++;
++ }
++
++ return(tolower(*s1) - tolower(*s2));
++}
++
++#endif
+diff -urN linux.old/drivers/net/avalanche_cpmac/cpmacHalLx.c linux.dev/drivers/net/avalanche_cpmac/cpmacHalLx.c
+--- linux.old/drivers/net/avalanche_cpmac/cpmacHalLx.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpmacHalLx.c 2005-07-12 02:48:42.044593000 +0200
+@@ -0,0 +1,492 @@
++/******************************************************************************
++ * FILE PURPOSE: CPMAC Net Driver HAL support Source
++ ******************************************************************************
++ * FILE NAME: cpmacHalLx.c
++ *
++ * DESCRIPTION: CPMAC Network Device Driver Source
++ *
++ * REVISION HISTORY:
++ *
++ * Date Description Author
++ *-----------------------------------------------------------------------------
++ * 27 Nov 2002 Initial Creation Suraj S Iyer
++ * 09 Jun 2003 Updates for GA Suraj S Iyer
++ * 18 Dec 2003 Updated for 5.7 Suraj S Iyer
++ *
++ * (C) Copyright 2003, Texas Instruments, Inc
++ *******************************************************************************/
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/proc_fs.h>
++#include <asm/io.h>
++#include <linux/string.h>
++
++#include <asm/ar7/avalanche_intc.h>
++
++#include "cpmacHalLx.h"
++#include "cpmac.h"
++
++/* PSP config headers */
++#include "psp_config_parse.h"
++#include "psp_config_mgr.h"
++
++/* debug */
++extern int cpmac_debug_mode;
++#define dbgPrint if (cpmac_debug_mode) printk
++#define errPrint printk
++
++char CpmacSignature[] = "Cpmac driver";
++static unsigned long irq_flags = 0;
++OS_SETUP *p_os_setup = NULL;
++
++extern int avalanche_request_intr_pacing(int, unsigned int, unsigned int);
++extern int avalanche_free_intr_pacing(unsigned int blk_num);
++
++/*----------------------------------------------------------------------------
++ * Parameter extracting functionalities.
++ *--------------------------------------------------------------------------*/
++static int os_find_parm_u_int(void *info_ptr, const char *param, unsigned int *val)
++{
++ int ret_val = 0;
++
++ if((ret_val = psp_config_get_param_uint(info_ptr, param, val)) == -1)
++ {
++ dbgPrint("Error: could not locate the requested \"%s\" param.\n",param);
++ ret_val = -1;
++ }
++
++ return(ret_val);
++}
++
++static int os_find_parm_val(void *info_ptr, const char *param, void *val)
++{
++ int ret_val = 0;
++
++ if(psp_config_get_param_string(info_ptr, param, val) == -1)
++ {
++ dbgPrint("Error: could not locate the requested \"%s\" param.\n",param);
++ ret_val = -1;
++ }
++
++ return(ret_val);
++}
++
++static int os_find_device(int unit, const char *find_name, void *device_info)
++{
++ int ret_val = 0;
++
++ if(psp_config_get((char *)find_name, unit, device_info) == -1)
++ {
++ dbgPrint("Error: could not locate the requested \"%s\" param.\n", find_name);
++ ret_val = -1;
++ }
++
++ return(ret_val);
++}
++
++/*---------------------------------------------------------------------------
++ * Memory related OS abstraction.
++ *--------------------------------------------------------------------------*/
++void os_free(void *mem_ptr)
++{
++ kfree(mem_ptr);
++}
++
++void os_free_buffer(OS_RECEIVEINFO *osReceiveInfo, void *mem_ptr)
++{
++ dev_kfree_skb_any(osReceiveInfo);
++}
++
++void os_free_dev(void *mem_ptr)
++{
++ kfree(mem_ptr);
++}
++
++void os_free_dma_xfer(void *mem_ptr)
++{
++ kfree(mem_ptr);
++}
++
++static void *os_malloc(unsigned int size)
++{
++ return(kmalloc(size, GFP_KERNEL));
++}
++
++static void *os_malloc_dma_xfer(unsigned int size,
++ void *mem_base,
++ unsigned int mem_range)
++{
++ return(kmalloc(size, GFP_KERNEL));
++}
++
++static void *os_malloc_dev(unsigned int size)
++{
++ return(kmalloc(size, GFP_KERNEL));
++}
++
++
++/*----------------------------------------------------------------------------
++ * CRITICAL SECTION ENABLING/DISABLING.
++ *--------------------------------------------------------------------------*/
++static void os_critical_on(void)
++{
++ save_and_cli(irq_flags);
++}
++
++static void os_critical_off(void)
++{
++ restore_flags(irq_flags);
++}
++
++/*----------------------------------------------------------------------------
++ * Cache related abstraction
++ *--------------------------------------------------------------------------*/
++static void os_cache_invalidate(void *mem_ptr, int size)
++{
++ dma_cache_inv((unsigned long)mem_ptr, size);
++}
++
++static void os_cache_writeback(void *mem_ptr, int size)
++{
++ dma_cache_wback_inv((unsigned long)mem_ptr, size);
++}
++
++/*-----------------------------------------------------------------------------
++ * Support functions.
++ *---------------------------------------------------------------------------*/
++
++static void hal_drv_unregister_isr(OS_DEVICE *p_dev, int intr)
++{
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++ CPMAC_ISR_INFO_T *p_isr_cb_param = &p_cpmac_priv->cpmac_isr;
++ intr = LNXINTNUM(intr);
++
++ free_irq(p_isr_cb_param->intr, p_isr_cb_param);
++
++ dbgPrint("cpmac_hal_unregister called for the intr %d for unit %x and isr_cb_param %x.\n",
++ intr, p_cpmac_priv->instance_num, (unsigned int )&p_cpmac_priv->cpmac_isr);
++}
++
++
++static void hal_drv_register_isr(OS_DEVICE *p_dev,
++ CPMAC_HAL_ISR_FUNC_T hal_isr, int intr)
++{
++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal;
++ CPMAC_ISR_INFO_T *p_isr_cb_param = &p_cpmac_priv->cpmac_isr;
++ intr = LNXINTNUM(intr);
++
++ dbgPrint("osRegister called for the intr %d for device %x and p_isr_cb_param %x.\n",
++ intr, (bit32u)p_dev, (bit32u)p_isr_cb_param);
++
++ p_isr_cb_param->owner = p_drv_hal;
++ p_isr_cb_param->hal_isr = hal_isr;
++ p_isr_cb_param->intr = intr;
++
++ tasklet_init(&p_isr_cb_param->tasklet, cpmac_handle_tasklet, (unsigned long)p_isr_cb_param);
++ dbgPrint("Success in registering irq %d for Cpmac unit# %d.\n", intr, p_cpmac_priv->instance_num);
++}
++
++/*---------------------------------------------------------------------------
++ * FUNCTIONS called by the CPMAC Net Device.
++ *-------------------------------------------------------------------------*/
++static int load_os_funcs(OS_FUNCTIONS *os_func)
++{
++ dbgPrint("os_init_module: Start\n");
++ if( os_func == 0 )
++ {
++ return(sizeof(OS_FUNCTIONS));
++ }
++
++ os_func->Control = cpmac_hal_control;
++ os_func->CriticalOn = os_critical_on;
++ os_func->CriticalOff = os_critical_off;
++ os_func->DataCacheHitInvalidate = os_cache_invalidate;
++ os_func->DataCacheHitWriteback = os_cache_writeback;
++ os_func->DeviceFindInfo = os_find_device;
++ os_func->DeviceFindParmUint = os_find_parm_u_int;
++ os_func->DeviceFindParmValue= os_find_parm_val;
++ os_func->Free = os_free;
++ os_func->FreeRxBuffer = os_free_buffer;
++ os_func->FreeDev = os_free_dev;
++ os_func->FreeDmaXfer = os_free_dma_xfer;
++ os_func->IsrRegister = hal_drv_register_isr;
++ os_func->IsrUnRegister = hal_drv_unregister_isr;
++ os_func->Malloc = os_malloc;
++ os_func->MallocDev = os_malloc_dev;
++ os_func->MallocDmaXfer = os_malloc_dma_xfer;
++ os_func->MallocRxBuffer = cpmac_hal_malloc_buffer;
++ os_func->Memset = memset;
++ os_func->Printf = printk;
++ os_func->Receive = cpmac_hal_receive;
++ os_func->SendComplete = cpmac_hal_send_complete;
++ os_func->Strcmpi = cpmac_ci_strcmp;
++ os_func->TeardownComplete = cpmac_hal_tear_down_complete;
++ os_func->Strstr = strstr;
++ os_func->Strtoul = simple_strtol;
++ os_func->Sprintf = sprintf;
++ os_func->Strlen = strlen;
++
++ dbgPrint("os_init_module: Leave\n");
++
++ return(0);
++}
++
++
++int cpmac_drv_init(CPMAC_DRV_HAL_INFO_T *p_drv_hal)
++{
++ HAL_DEVICE *p_hal_dev = p_drv_hal->hal_dev;
++ HAL_FUNCTIONS *p_hal_funcs = p_drv_hal->hal_funcs;
++
++ return(p_hal_funcs->Init(p_hal_dev));
++}
++
++int cpmac_drv_cleanup(CPMAC_DRV_HAL_INFO_T *p_drv_hal)
++{
++ HAL_DEVICE *p_hal_dev = p_drv_hal->hal_dev;
++ HAL_FUNCTIONS *p_hal_funcs = p_drv_hal->hal_funcs;
++
++ int ret_val = p_hal_funcs->Shutdown(p_hal_dev);
++
++#if 0
++ if(ret_val == 0)
++ kfree(p_hal_funcs);
++ else
++ ret_val = -1;
++#endif
++
++ kfree(p_drv_hal->os_funcs);
++
++ return (ret_val);
++}
++
++int cpmac_drv_tx_setup(HAL_FUNCTIONS *p_hal_funcs,
++ HAL_DEVICE *p_hal_dev,
++ CPMAC_TX_CHAN_INFO_T *p_tx_chan_info)
++{
++ int ret_val = 0;
++ int count = 0;
++ CHANNEL_INFO chan_info;
++
++ /* Let's setup the TX Channels. */
++ for(count=0; count < p_tx_chan_info->cfg_chan; count++)
++ {
++ chan_info.Channel = count;
++ chan_info.Direction = DIRECTION_TX;
++ chan_info.TxNumBuffers = p_tx_chan_info->chan[count].num_BD;
++ chan_info.TxServiceMax = p_tx_chan_info->chan[count].service_max;
++ chan_info.TxNumQueues = 0;
++
++ if((ret_val = p_hal_funcs->ChannelSetup(p_hal_dev, &chan_info,
++ NULL)) != 0)
++ {
++ errPrint("Error in opening channel %d for TX.\n", count);
++ ret_val = -1;
++ break;
++ }
++
++ p_tx_chan_info->opened_chan++;
++ }
++
++ return(ret_val);
++}
++
++int cpmac_drv_rx_setup(HAL_FUNCTIONS *p_hal_funcs,
++ HAL_DEVICE *p_hal_dev,
++ CPMAC_RX_CHAN_INFO_T *p_rx_chan_info)
++{
++ int ret_val = 0;
++ CHANNEL_INFO chan_info;
++
++ chan_info.Channel = 0;
++ chan_info.Direction = DIRECTION_RX;
++ chan_info.RxBufSize = p_rx_chan_info->chan[0].buffer_size;
++ chan_info.RxBufferOffset= p_rx_chan_info->chan[0].buffer_offset;
++ chan_info.RxNumBuffers = p_rx_chan_info->chan[0].num_BD;
++ chan_info.RxServiceMax = p_rx_chan_info->chan[0].service_max;
++
++ if(p_hal_funcs->ChannelSetup(p_hal_dev, &chan_info, p_rx_chan_info) != 0)
++ {
++ errPrint("Error in opening channel %d for RX.\n", 0);
++ ret_val = -1;
++ }
++
++ return(ret_val);
++}
++
++int cpmac_drv_start(CPMAC_DRV_HAL_INFO_T *p_drv_hal,
++ CPMAC_TX_CHAN_INFO_T *p_tx_chan_info,
++ CPMAC_RX_CHAN_INFO_T *p_rx_chan_info,
++ unsigned int flags)
++{
++ int ret_val = 0;
++ HAL_FUNCTIONS *p_hal_funcs = p_drv_hal->hal_funcs;
++ HAL_DEVICE *p_hal_dev = p_drv_hal->hal_dev;
++
++ dbgPrint("It is in cpmac_drv_start for %x.\n", (unsigned int)p_drv_hal);
++
++ if(flags & CHAN_SETUP)
++ {
++ if(cpmac_drv_tx_setup(p_hal_funcs, p_hal_dev,
++ p_tx_chan_info)!=0)
++ {
++ errPrint("Failed to set up tx channel(s).\n");
++ ret_val = -1;
++ }
++ else if(cpmac_drv_rx_setup(p_hal_funcs, p_hal_dev,
++ p_rx_chan_info)!=0)
++ {
++ errPrint("Failed to set up rx channel.\n");
++ ret_val = -1;
++ }
++ else
++ {
++ ret_val = 0;
++ }
++ }
++
++ /* Error in setting up the Channels, quit. */
++ if((ret_val == 0) && (ret_val = p_hal_funcs->Open(p_hal_dev)) != 0)
++ {
++ errPrint("failed to open the HAL!!!.\n");
++ ret_val = -1;
++ }
++
++ return (ret_val);
++} /* cpmac_drv_start */
++
++
++
++int cpmac_drv_tx_teardown(HAL_FUNCTIONS *p_hal_funcs,
++ HAL_DEVICE *p_hal_dev,
++ CPMAC_TX_CHAN_INFO_T *p_tx_chan_info,
++ unsigned int flags)
++{
++ int ret_val = 0;
++ int count = 0;
++
++ /* Let's setup the TX Channels. */
++ for(; p_tx_chan_info->opened_chan > 0;
++ p_tx_chan_info->opened_chan--, count++)
++ {
++ if(p_hal_funcs->ChannelTeardown(p_hal_dev, count, flags) != 0)
++ {
++ errPrint("Error in tearing down channel %d for TX.\n", count);
++ ret_val = -1;
++ break;
++ }
++ }
++
++ return(ret_val);
++}
++
++
++int cpmac_drv_rx_teardown(HAL_FUNCTIONS *p_hal_funcs,
++ HAL_DEVICE *p_hal_dev,
++ unsigned int flags)
++{
++ int ret_val = 0;
++
++ if(p_hal_funcs->ChannelTeardown(p_hal_dev, 0, flags) != 0)
++ {
++ errPrint("Error in tearing down channel %d for RX.\n", 0);
++ ret_val = -1;
++ }
++
++ return(ret_val);
++}
++
++int cpmac_drv_stop(CPMAC_DRV_HAL_INFO_T *p_drv_hal,
++ CPMAC_TX_CHAN_INFO_T *p_tx_chan_info,
++ CPMAC_RX_CHAN_INFO_T *p_rx_chan_info,
++ unsigned int flags)
++{
++ HAL_DEVICE *p_hal_dev = p_drv_hal->hal_dev;
++ HAL_FUNCTIONS *p_hal_funcs = p_drv_hal->hal_funcs;
++ int ret_val = 0;
++
++ if(flags & CHAN_TEARDOWN)
++ {
++ unsigned int chan_flags = 0;
++
++ if(flags & FREE_BUFFER) chan_flags |= 0x4; /* full tear down */
++ if(flags & BLOCKING) chan_flags |= 0x8; /* blocking call */
++
++ dbgPrint("The teardown flags are %d.\n", flags);
++ dbgPrint("The teardown chan flags are %d.\n", chan_flags);
++
++ if(cpmac_drv_tx_teardown(p_hal_funcs, p_hal_dev,
++ p_tx_chan_info, chan_flags | 0x1) != 0)
++ {
++ ret_val = -1;
++ errPrint("The tx channel teardown failed.\n");
++ }
++ else if(cpmac_drv_rx_teardown(p_hal_funcs, p_hal_dev, chan_flags | 0x2) != 0)
++ {
++ ret_val = -1;
++ errPrint("The rx channel teardown failed.\n");
++ }
++ else
++ {
++ ;
++ }
++ }
++
++ if(ret_val == 0)
++ {
++ int close_flags = 1;
++
++ if(flags & FREE_BUFFER) close_flags = 2;
++// if(flags & COMPLETE) close_flags = 3;
++
++ if(p_hal_funcs->Close(p_hal_dev, close_flags) != 0)
++ {
++ ret_val = -1;
++ }
++ }
++
++ return(ret_val);
++}
++
++int cpmac_drv_init_module(CPMAC_DRV_HAL_INFO_T *p_drv_hal, OS_DEVICE *p_os_dev, int inst)
++{
++ int ret_val = -1;
++ int hal_func_size;
++
++ dbgPrint("Entering the CpmacInitModule for the inst %d \n", inst);
++
++ if((p_drv_hal->os_funcs = kmalloc(sizeof(OS_FUNCTIONS), GFP_KERNEL)) == NULL)
++ {
++ errPrint("Failed to allocate memory for OS_FUNCTIONS.\n");
++ }
++ else if(load_os_funcs(p_drv_hal->os_funcs) != 0)
++ {
++ errPrint("Failed to load OS funcs.\n");
++ os_free(p_drv_hal->os_funcs);
++ }
++ else if(halCpmacInitModule(&p_drv_hal->hal_dev, p_os_dev,
++ &p_drv_hal->hal_funcs, p_drv_hal->os_funcs,
++ sizeof(*p_drv_hal->os_funcs),
++ &hal_func_size, inst) != 0)
++ {
++ errPrint("halCpmacInitModule failed for inst %d \n", inst);
++ os_free(p_drv_hal->os_funcs);
++ }
++ else if(p_drv_hal->hal_funcs->Probe(p_drv_hal->hal_dev) != 0)
++ {
++ errPrint("halCpmacProbe failed for inst %d \n", inst);
++ os_free(p_drv_hal->os_funcs);
++ }
++ else
++ {
++ /* every thing went well. */
++ ret_val = 0;
++ }
++
++ return (ret_val);
++}
+diff -urN linux.old/drivers/net/avalanche_cpmac/cpmacHalLx.h linux.dev/drivers/net/avalanche_cpmac/cpmacHalLx.h
+--- linux.old/drivers/net/avalanche_cpmac/cpmacHalLx.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpmacHalLx.h 2005-07-12 02:48:42.044593000 +0200
+@@ -0,0 +1,51 @@
++/******************************************************************************
++ * FILE PURPOSE: CPMAC Linux Device Driver HAL support Header
++ ******************************************************************************
++ * FILE NAME: cpmacHalVx.h
++ *
++ * DESCRIPTION: CPMAC Linux Device Driver Header
++ *
++ * REVISION HISTORY:
++ *
++ * Date Description Author
++ *-----------------------------------------------------------------------------
++ * 27 Nov 2002 Initial Creation Suraj S Iyer
++ * 09 Jun 2003 Updates for GA Suraj S Iyer
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++#ifndef __CPMAC_HAL_LX_H
++#define __CPMAC_HAL_LX_H
++
++
++typedef struct net_device OS_DEVICE;
++typedef struct sk_buff OS_RECEIVEINFO;
++typedef struct sk_buff OS_SENDINFO;
++
++#ifdef DEBUG
++typedef void HAL_RECEIVEINFO;
++typedef void HAL_DEVICE;
++typedef void OS_SETUP;
++#endif
++
++#define OS_SETUP void
++#define HAL_DEVICE void
++#define HAL_RECEIVEINFO void
++
++#define _CPHAL_CPMAC
++
++#include "cpswhal_cpmac.h"
++#include "cpmac.h"
++
++int cpmac_drv_start(CPMAC_DRV_HAL_INFO_T *, CPMAC_TX_CHAN_INFO_T*,
++ CPMAC_RX_CHAN_INFO_T *, unsigned int);
++int cpmac_drv_cleanup(CPMAC_DRV_HAL_INFO_T *);
++int cpmac_drv_init(CPMAC_DRV_HAL_INFO_T*);
++int cpmac_drv_close(CPMAC_DRV_HAL_INFO_T*);
++int cpmac_drv_open(CPMAC_DRV_HAL_INFO_T*);
++int cpmac_drv_init_module(CPMAC_DRV_HAL_INFO_T*, OS_DEVICE*, int);
++int cpmac_drv_stop(CPMAC_DRV_HAL_INFO_T *p_drv_hal,CPMAC_TX_CHAN_INFO_T *p_tx_chan_info,
++ CPMAC_RX_CHAN_INFO_T *p_rx_chan_info,unsigned int flags);
++
++#endif
+diff -urN linux.old/drivers/net/avalanche_cpmac/cpmac_reg.h linux.dev/drivers/net/avalanche_cpmac/cpmac_reg.h
+--- linux.old/drivers/net/avalanche_cpmac/cpmac_reg.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpmac_reg.h 2005-07-12 02:48:42.045593000 +0200
+@@ -0,0 +1,406 @@
++/****************************************************************************
++ TNETD73xx Software Support
++ Copyright(c) 2000, Texas Instruments Incorporated. All Rights Reserved.
++
++ FILE: cpmac_reg.h Register definitions for the CPMAC module
++
++ DESCRIPTION:
++ This include file contains register definitions for the
++ CPMAC module.
++
++ HISTORY:
++ 15Nov00 BEGR Original version written
++ 30May02 MICK Added bits for Int Vector
++ 19Sep02 MICK Added INT_ACK per Channel
++ 08Nov02 GDUN Updated to use base
++ 12Nov02 MICK Incorporated into CPHAL
++*****************************************************************************/
++#ifndef _INC_CPMAC_REG
++#define _INC_CPMAC_REG
++
++#ifndef MEM_PTR
++#define MEM_PTR volatile bit32u *
++#endif
++
++/***************************************************************************
++ *
++ * C P M A C M E M O R Y M A P
++ *
++ **************************************************************************/
++
++#define pCPMAC_TX_IDVER(base) ((MEM_PTR)(base+0x000))
++#define CPMAC_TX_IDVER(base) (*pCPMAC_TX_IDVER(base))
++#define pCPMAC_TX_CONTROL(base) ((MEM_PTR)(base+0x004))
++#define CPMAC_TX_CONTROL(base) (*pCPMAC_TX_CONTROL(base))
++#define pCPMAC_TX_TEARDOWN(base) ((MEM_PTR)(base+0x008))
++#define CPMAC_TX_TEARDOWN(base) (*pCPMAC_TX_TEARDOWN(base))
++#define pCPMAC_RX_IDVER(base) ((MEM_PTR)(base+0x010))
++#define CPMAC_RX_IDVER(base) (*pCPMAC_RX_IDVER(base))
++#define pCPMAC_RX_CONTROL(base) ((MEM_PTR)(base+0x014))
++#define CPMAC_RX_CONTROL(base) (*pCPMAC_RX_CONTROL(base))
++#define pCPMAC_RX_TEARDOWN(base) ((MEM_PTR)(base+0x018))
++#define CPMAC_RX_TEARDOWN(base) (*pCPMAC_RX_TEARDOWN(base))
++#define pCPMAC_RX_MBP_ENABLE(base) ((MEM_PTR)(base+0x100))
++#define CPMAC_RX_MBP_ENABLE(base) (*pCPMAC_RX_MBP_ENABLE(base))
++#define pCPMAC_RX_UNICAST_SET(base) ((MEM_PTR)(base+0x104))
++#define CPMAC_RX_UNICAST_SET(base) (*pCPMAC_RX_UNICAST_SET(base))
++#define pCPMAC_RX_UNICAST_CLEAR(base) ((MEM_PTR)(base+0x108))
++#define CPMAC_RX_UNICAST_CLEAR(base) (*pCPMAC_RX_UNICAST_CLEAR(base))
++#define pCPMAC_RX_MAXLEN(base) ((MEM_PTR)(base+0x10C))
++#define CPMAC_RX_MAXLEN(base) (*pCPMAC_RX_MAXLEN(base))
++#define pCPMAC_RX_BUFFER_OFFSET(base) ((MEM_PTR)(base+0x110))
++#define CPMAC_RX_BUFFER_OFFSET(base) (*pCPMAC_RX_BUFFER_OFFSET(base))
++#define pCPMAC_RX_FILTERLOWTHRESH(base) ((MEM_PTR)(base+0x114))
++#define CPMAC_RX_FILTERLOWTHRESH(base) (*pCPMAC_RX_FILTERLOWTHRESH(base))
++#define pCPMAC_RX0_FLOWTHRESH(base) ((MEM_PTR)(base+0x120))
++#define CPMAC_RX0_FLOWTHRESH(base) (*pCPMAC_RX0_FLOWTHRESH(base))
++#define pCPMAC_RX1_FLOWTHRESH(base) ((MEM_PTR)(base+0x124))
++#define CPMAC_RX1_FLOWTHRESH(base) (*pCPMAC_RX1_FLOWTHRESH(base))
++#define pCPMAC_RX2_FLOWTHRESH(base) ((MEM_PTR)(base+0x128))
++#define CPMAC_RX2_FLOWTHRESH(base) (*pCPMAC_RX2_FLOWTHRESH(base))
++#define pCPMAC_RX3_FLOWTHRESH(base) ((MEM_PTR)(base+0x12C))
++#define CPMAC_RX3_FLOWTHRESH(base) (*pCPMAC_RX3_FLOWTHRESH(base))
++#define pCPMAC_RX4_FLOWTHRESH(base) ((MEM_PTR)(base+0x130))
++#define CPMAC_RX4_FLOWTHRESH(base) (*pCPMAC_RX4_FLOWTHRESH(base))
++#define pCPMAC_RX5_FLOWTHRESH(base) ((MEM_PTR)(base+0x134))
++#define CPMAC_RX5_FLOWTHRESH(base) (*pCPMAC_RX5_FLOWTHRESH(base))
++#define pCPMAC_RX6_FLOWTHRESH(base) ((MEM_PTR)(base+0x138))
++#define CPMAC_RX6_FLOWTHRESH(base) (*pCPMAC_RX6_FLOWTHRESH(base))
++#define pCPMAC_RX7_FLOWTHRESH(base) ((MEM_PTR)(base+0x13C))
++#define CPMAC_RX7_FLOWTHRESH(base) (*pCPMAC_RX7_FLOWTHRESH(base))
++#define pCPMAC_RX0_FREEBUFFER(base) ((MEM_PTR)(base+0x140))
++#define CPMAC_RX0_FREEBUFFER(base) (*pCPMAC_RX0_FREEBUFFER(base))
++#define pCPMAC_RX1_FREEBUFFER(base) ((MEM_PTR)(base+0x144))
++#define CPMAC_RX1_FREEBUFFER(base) (*pCPMAC_RX1_FREEBUFFER(base))
++#define pCPMAC_RX2_FREEBUFFER(base) ((MEM_PTR)(base+0x148))
++#define CPMAC_RX2_FREEBUFFER(base) (*pCPMAC_RX2_FREEBUFFER(base))
++#define pCPMAC_RX3_FREEBUFFER(base) ((MEM_PTR)(base+0x14C))
++#define CPMAC_RX3_FREEBUFFER(base) (*pCPMAC_RX3_FREEBUFFER(base))
++#define pCPMAC_RX4_FREEBUFFER(base) ((MEM_PTR)(base+0x150))
++#define CPMAC_RX4_FREEBUFFER(base) (*pCPMAC_RX4_FREEBUFFER(base))
++#define pCPMAC_RX5_FREEBUFFER(base) ((MEM_PTR)(base+0x154))
++#define CPMAC_RX5_FREEBUFFER(base) (*pCPMAC_RX5_FREEBUFFER(base))
++#define pCPMAC_RX6_FREEBUFFER(base) ((MEM_PTR)(base+0x158))
++#define CPMAC_RX6_FREEBUFFER(base) (*pCPMAC_RX6_FREEBUFFER(base))
++#define pCPMAC_RX7_FREEBUFFER(base) ((MEM_PTR)(base+0x15C))
++#define CPMAC_RX7_FREEBUFFER(base) (*pCPMAC_RX7_FREEBUFFER(base))
++#define pCPMAC_MACCONTROL(base) ((MEM_PTR)(base+0x160))
++#define CPMAC_MACCONTROL(base) (*pCPMAC_MACCONTROL(base))
++#define pCPMAC_MACSTATUS(base) ((MEM_PTR)(base+0x164))
++#define CPMAC_MACSTATUS(base) (*pCPMAC_MACSTATUS(base))
++#define pCPMAC_EMCONTROL(base) ((MEM_PTR)(base+0x168))
++#define CPMAC_EMCONTROL(base) (*pCPMAC_EMCONTROL(base))
++#define pCPMAC_TX_INTSTAT_RAW(base) ((MEM_PTR)(base+0x170))
++#define CPMAC_TX_INTSTAT_RAW(base) (*pCPMAC_TX_INTSTAT_RAW(base))
++#define pCPMAC_TX_INTSTAT_MASKED(base) ((MEM_PTR)(base+0x174))
++#define CPMAC_TX_INTSTAT_MASKED(base) (*pCPMAC_TX_INTSTAT_MASKED(base))
++#define pCPMAC_TX_INTMASK_SET(base) ((MEM_PTR)(base+0x178))
++#define CPMAC_TX_INTMASK_SET(base) (*pCPMAC_TX_INTMASK_SET(base))
++#define pCPMAC_TX_INTMASK_CLEAR(base) ((MEM_PTR)(base+0x17C))
++#define CPMAC_TX_INTMASK_CLEAR(base) (*pCPMAC_TX_INTMASK_CLEAR(base))
++#define pCPMAC_MAC_IN_VECTOR(base) ((MEM_PTR)(base+0x180))
++#define CPMAC_MAC_IN_VECTOR(base) (*pCPMAC_MAC_IN_VECTOR(base))
++#define pCPMAC_MAC_EOI_VECTOR(base) ((MEM_PTR)(base+0x184))
++#define CPMAC_MAC_EOI_VECTOR(base) (*pCPMAC_MAC_EOI_VECTOR(base))
++#define pCPMAC_RX_INTSTAT_RAW(base) ((MEM_PTR)(base+0x190))
++#define CPMAC_RX_INTSTAT_RAW(base) (*pCPMAC_RX_INTSTAT_RAW(base))
++#define pCPMAC_RX_INTSTAT_MASKED(base) ((MEM_PTR)(base+0x194))
++#define CPMAC_RX_INTSTAT_MASKED(base) (*pCPMAC_RX_INTSTAT_MASKED(base))
++#define pCPMAC_RX_INTMASK_SET(base) ((MEM_PTR)(base+0x198))
++#define CPMAC_RX_INTMASK_SET(base) (*pCPMAC_RX_INTMASK_SET(base))
++#define pCPMAC_RX_INTMASK_CLEAR(base) ((MEM_PTR)(base+0x19C))
++#define CPMAC_RX_INTMASK_CLEAR(base) (*pCPMAC_RX_INTMASK_CLEAR(base))
++#define pCPMAC_MAC_INTSTAT_RAW(base) ((MEM_PTR)(base+0x1A0))
++#define CPMAC_MAC_INTSTAT_RAW(base) (*pCPMAC_MAC_INTSTAT_RAW(base))
++#define pCPMAC_MAC_INTSTAT_MASKED(base) ((MEM_PTR)(base+0x1A4))
++#define CPMAC_MAC_INTSTAT_MASKED(base) (*pCPMAC_MAC_INTSTAT_MASKED(base))
++#define pCPMAC_MAC_INTMASK_SET(base) ((MEM_PTR)(base+0x1A8))
++#define CPMAC_MAC_INTMASK_SET(base) (*pCPMAC_MAC_INTMASK_SET(base))
++#define pCPMAC_MAC_INTMASK_CLEAR(base) ((MEM_PTR)(base+0x1AC))
++#define CPMAC_MAC_INTMASK_CLEAR(base) (*pCPMAC_MAC_INTMASK_CLEAR(base))
++#define pCPMAC_MACADDRLO_0(base) ((MEM_PTR)(base+0x1B0))
++#define CPMAC_MACADDRLO_0(base) (*pCPMAC_MACADDRLO_0(base))
++#define pCPMAC_MACADDRLO_1(base) ((MEM_PTR)(base+0x1B4))
++#define CPMAC_MACADDRLO_1(base) (*pCPMAC_MACADDRLO_1(base))
++#define pCPMAC_MACADDRLO_2(base) ((MEM_PTR)(base+0x1B8))
++#define CPMAC_MACADDRLO_2(base) (*pCPMAC_MACADDRLO_2(base))
++#define pCPMAC_MACADDRLO_3(base) ((MEM_PTR)(base+0x1BC))
++#define CPMAC_MACADDRLO_3(base) (*pCPMAC_MACADDRLO_3(base))
++#define pCPMAC_MACADDRLO_4(base) ((MEM_PTR)(base+0x1C0))
++#define CPMAC_MACADDRLO_4(base) (*pCPMAC_MACADDRLO_4(base))
++#define pCPMAC_MACADDRLO_5(base) ((MEM_PTR)(base+0x1C4))
++#define CPMAC_MACADDRLO_5(base) (*pCPMAC_MACADDRLO_5(base))
++#define pCPMAC_MACADDRLO_6(base) ((MEM_PTR)(base+0x1C8))
++#define CPMAC_MACADDRLO_6(base) (*pCPMAC_MACADDRLO_6(base))
++#define pCPMAC_MACADDRLO_7(base) ((MEM_PTR)(base+0x1CC))
++#define CPMAC_MACADDRLO_7(base) (*pCPMAC_MACADDRLO_7(base))
++#define pCPMAC_MACADDRMID(base) ((MEM_PTR)(base+0x1D0))
++#define CPMAC_MACADDRMID(base) (*pCPMAC_MACADDRMID(base))
++#define pCPMAC_MACADDRHI(base) ((MEM_PTR)(base+0x1D4))
++#define CPMAC_MACADDRHI(base) (*pCPMAC_MACADDRHI(base))
++#define pCPMAC_MACHASH1(base) ((MEM_PTR)(base+0x1D8))
++#define CPMAC_MACHASH1(base) (*pCPMAC_MACHASH1(base))
++#define pCPMAC_MACHASH2(base) ((MEM_PTR)(base+0x1DC))
++#define CPMAC_MACHASH2(base) (*pCPMAC_MACHASH2(base))
++#define pCPMAC_BOFFTEST(base) ((MEM_PTR)(base+0x1E0))
++#define CPMAC_BOFFTEST(base) (*pCPMAC_BOFFTEST(base))
++#define pCPMAC_PACTEST(base) ((MEM_PTR)(base+0x1E4))
++#define CPMAC_PACTEST(base) (*pCPMAC_PACTEST(base))
++#define pCPMAC_RXPAUSE(base) ((MEM_PTR)(base+0x1E8))
++#define CPMAC_RXPAUSE(base) (*pCPMAC_RXPAUSE(base))
++#define pCPMAC_TXPAUSE(base) ((MEM_PTR)(base+0x1EC))
++#define CPMAC_TXPAUSE(base) (*pCPMAC_TXPAUSE(base))
++/* STATISTICS */
++#define pCPMAC_RXGOODFRAMES(base) ((MEM_PTR)(base+0x200))
++#define CPMAC_RXGOODFRAMES(base) (*pCPMAC_RXGOODFRAMES(base))
++#define pCPMAC_RXBROADCASTFRAMES(base) ((MEM_PTR)(base+0x204))
++#define CPMAC_RXBROADCASTFRAMES(base) (*pCPMAC_RXBROADCASTFRAMES(base))
++#define pCPMAC_RXMULTICASTFRAMES(base) ((MEM_PTR)(base+0x208))
++#define CPMAC_RXMULTICASTFRAMES(base) (*pCPMAC_RXMULTICASTFRAMES(base))
++#define pCPMAC_RXPAUSEFRAMES(base) ((MEM_PTR)(base+0x20C))
++#define CPMAC_RXPAUSEFRAMES(base) (*pCPMAC_RXPAUSEFRAMES(base))
++#define pCPMAC_RXCRCERRORS(base) ((MEM_PTR)(base+0x210))
++#define CPMAC_RXCRCERRORS(base) (*pCPMAC_RXCRCERRORS(base))
++#define pCPMAC_RXALIGNCODEERRORS(base) ((MEM_PTR)(base+0x214))
++#define CPMAC_RXALIGNCODEERRORS(base) (*pCPMAC_RXALIGNCODEERRORS(base))
++#define pCPMAC_RXOVERSIZEDFRAMES(base) ((MEM_PTR)(base+0x218))
++#define CPMAC_RXOVERSIZEDFRAMES(base) (*pCPMAC_RXOVERSIZEDFRAMES(base))
++#define pCPMAC_RXJABBERFRAMES(base) ((MEM_PTR)(base+0x21C))
++#define CPMAC_RXJABBERFRAMES(base) (*pCPMAC_RXJABBERFRAMES(base))
++#define pCPMAC_RXUNDERSIZEDFRAMES(base) ((MEM_PTR)(base+0x220))
++#define CPMAC_RXUNDERSIZEDFRAMES(base) (*pCPMAC_RXUNDERSIZEDFRAMES(base))
++#define pCPMAC_RXFRAGMENTS(base) ((MEM_PTR)(base+0x224))
++#define CPMAC_RXFRAGMENTS(base) (*pCPMAC_RXFRAGMENTS(base))
++#define pCPMAC_RXFILTEREDFRAMES(base) ((MEM_PTR)(base+0x228))
++#define CPMAC_RXFILTEREDFRAMES(base) (*pCPMAC_RXFILTEREDFRAMES(base))
++#define pCPMAC_RXQOSFILTEREDFRAMES(base) ((MEM_PTR)(base+0x22C))
++#define CPMAC_RXQOSFILTEREDFRAMES(base) (*pCPMAC_RXQOSFILTEREDFRAMES(base))
++#define pCPMAC_RXOCTETS(base) ((MEM_PTR)(base+0x230))
++#define CPMAC_RXOCTETS(base) (*pCPMAC_RXOCTETS(base))
++#define pCPMAC_TXGOODFRAMES(base) ((MEM_PTR)(base+0x234))
++#define CPMAC_TXGOODFRAMES(base) (*pCPMAC_TXGOODFRAMES(base))
++#define pCPMAC_TXBROADCASTFRAMES(base) ((MEM_PTR)(base+0x238))
++#define CPMAC_TXBROADCASTFRAMES(base) (*pCPMAC_TXBROADCASTFRAMES(base))
++#define pCPMAC_TXMULTICASTFRAMES(base) ((MEM_PTR)(base+0x23C))
++#define CPMAC_TXMULTICASTFRAMES(base) (*pCPMAC_TXMULTICASTFRAMES(base))
++#define pCPMAC_TXPAUSEFRAMES(base) ((MEM_PTR)(base+0x240))
++#define CPMAC_TXPAUSEFRAMES(base) (*pCPMAC_TXPAUSEFRAMES(base))
++#define pCPMAC_TXDEFERREDFRAMES(base) ((MEM_PTR)(base+0x244))
++#define CPMAC_TXDEFERREDFRAMES(base) (*pCPMAC_TXDEFERREDFRAMES(base))
++#define pCPMAC_TXCOLLISIONFRAMES(base) ((MEM_PTR)(base+0x248))
++#define CPMAC_TXCOLLISIONFRAMES(base) (*pCPMAC_TXCOLLISIONFRAMES(base))
++#define pCPMAC_TXSINGLECOLLFRAMES(base) ((MEM_PTR)(base+0x24C))
++#define CPMAC_TXSINGLECOLLFRAMES(base) (*pCPMAC_TXSINGLECOLLFRAMES(base))
++#define pCPMAC_TXMULTCOLLFRAMES(base) ((MEM_PTR)(base+0x250))
++#define CPMAC_TXMULTCOLLFRAMES(base) (*pCPMAC_TXMULTCOLLFRAMES(base))
++#define pCPMAC_TXEXCESSIVECOLLISIONS(base) ((MEM_PTR)(base+0x254))
++#define CPMAC_TXEXCESSIVECOLLISIONS(base) (*pCPMAC_TXEXCESSIVECOLLISIONS(base))
++#define pCPMAC_TXLATECOLLISIONS(base) ((MEM_PTR)(base+0x258))
++#define CPMAC_TXLATECOLLISIONS(base) (*pCPMAC_TXLATECOLLISIONS(base))
++#define pCPMAC_TXUNDERRUN(base) ((MEM_PTR)(base+0x25C))
++#define CPMAC_TXUNDERRUN(base) (*pCPMAC_TXUNDERRUN(base))
++#define pCPMAC_TXCARRIERSENSEERRORS(base) ((MEM_PTR)(base+0x260))
++#define CPMAC_TXCARRIERSENSEERRORS(base) (*pCPMAC_TXCARRIERSENSEERRORS(base))
++#define pCPMAC_TXOCTETS(base) ((MEM_PTR)(base+0x264))
++#define CPMAC_TXOCTETS(base) (*pCPMAC_TXOCTETS(base))
++#define pCPMAC_64OCTETFRAMES(base) ((MEM_PTR)(base+0x268))
++#define CPMAC_64OCTETFRAMES(base) (*pCPMAC_64OCTETFRAMES(base))
++#define pCPMAC_65T127OCTETFRAMES(base) ((MEM_PTR)(base+0x26C))
++#define CPMAC_65T127OCTETFRAMES(base) (*pCPMAC_65T127OCTETFRAMES(base))
++#define pCPMAC_128T255OCTETFRAMES(base) ((MEM_PTR)(base+0x270))
++#define CPMAC_128T255OCTETFRAMES(base) (*pCPMAC_128T255OCTETFRAMES(base))
++#define pCPMAC_256T511OCTETFRAMES(base) ((MEM_PTR)(base+0x274))
++#define CPMAC_256T511OCTETFRAMES(base) (*pCPMAC_256T511OCTETFRAMES(base))
++#define pCPMAC_512T1023OCTETFRAMES(base) ((MEM_PTR)(base+0x278))
++#define CPMAC_512T1023OCTETFRAMES(base) (*pCPMAC_512T1023OCTETFRAMES(base))
++#define pCPMAC_1024TUPOCTETFRAMES(base) ((MEM_PTR)(base+0x27C))
++#define CPMAC_1024TUPOCTETFRAMES(base) (*pCPMAC_1024TUPOCTETFRAMES(base))
++#define pCPMAC_NETOCTETS(base) ((MEM_PTR)(base+0x280))
++#define CPMAC_NETOCTETS(base) (*pCPMAC_NETOCTETS(base))
++#define pCPMAC_RXSOFOVERRUNS(base) ((MEM_PTR)(base+0x284))
++#define CPMAC_RXSOFOVERRUNS(base) (*pCPMAC_RXSOFOVERRUNS(base))
++#define pCPMAC_RXMOFOVERRUNS(base) ((MEM_PTR)(base+0x288))
++#define CPMAC_RXMOFOVERRUNS(base) (*pCPMAC_RXMOFOVERRUNS(base))
++#define pCPMAC_RXDMAOVERRUNS(base) ((MEM_PTR)(base+0x28C))
++#define CPMAC_RXDMAOVERRUNS(base) (*pCPMAC_RXDMAOVERRUNS(base))
++
++#define CPMAC_TX_HDP(base,ch) (*(MEM_PTR)(base+0x600+(4*ch)))
++#define pCPMAC_TX0_HDP(base) ((MEM_PTR)(base+0x600))
++#define CPMAC_TX0_HDP(base) (*pCPMAC_TX0_HDP(base))
++#define pCPMAC_TX1_HDP(base) ((MEM_PTR)(base+0x604))
++#define CPMAC_TX1_HDP(base) (*pCPMAC_TX1_HDP(base))
++#define pCPMAC_TX2_HDP(base) ((MEM_PTR)(base+0x608))
++#define CPMAC_TX2_HDP(base) (*pCPMAC_TX2_HDP(base))
++#define pCPMAC_TX3_HDP(base) ((MEM_PTR)(base+0x60C))
++#define CPMAC_TX3_HDP(base) (*pCPMAC_TX3_HDP(base))
++#define pCPMAC_TX4_HDP(base) ((MEM_PTR)(base+0x610))
++#define CPMAC_TX4_HDP(base) (*pCPMAC_TX4_HDP(base))
++#define pCPMAC_TX5_HDP(base) ((MEM_PTR)(base+0x614))
++#define CPMAC_TX5_HDP(base) (*pCPMAC_TX5_HDP(base))
++#define pCPMAC_TX6_HDP(base) ((MEM_PTR)(base+0x618))
++#define CPMAC_TX6_HDP(base) (*pCPMAC_TX6_HDP(base))
++#define pCPMAC_TX7_HDP(base) ((MEM_PTR)(base+0x61C))
++#define CPMAC_TX7_HDP(base) (*pCPMAC_TX7_HDP(base))
++#define CPMAC_RX_HDP(base,ch) (*(MEM_PTR)(base+0x620+(4*ch)))
++#define pCPMAC_RX0_HDP(base) ((MEM_PTR)(base+0x620))
++#define CPMAC_RX0_HDP(base) (*pCPMAC_RX0_HDP(base))
++#define pCPMAC_RX1_HDP(base) ((MEM_PTR)(base+0x624))
++#define CPMAC_RX1_HDP(base) (*pCPMAC_RX1_HDP(base))
++#define pCPMAC_RX2_HDP(base) ((MEM_PTR)(base+0x628))
++#define CPMAC_RX2_HDP(base) (*pCPMAC_RX2_HDP(base))
++#define pCPMAC_RX3_HDP(base) ((MEM_PTR)(base+0x62C))
++#define CPMAC_RX3_HDP(base) (*pCPMAC_RX3_HDP(base))
++#define pCPMAC_RX4_HDP(base) ((MEM_PTR)(base+0x630))
++#define CPMAC_RX4_HDP(base) (*pCPMAC_RX4_HDP(base))
++#define pCPMAC_RX5_HDP(base) ((MEM_PTR)(base+0x634))
++#define CPMAC_RX5_HDP(base) (*pCPMAC_RX5_HDP(base))
++#define pCPMAC_RX6_HDP(base) ((MEM_PTR)(base+0x638))
++#define CPMAC_RX6_HDP(base) (*pCPMAC_RX6_HDP(base))
++#define pCPMAC_RX7_HDP(base) ((MEM_PTR)(base+0x63C))
++#define CPMAC_RX7_HDP(base) (*pCPMAC_RX7_HDP(base))
++
++
++#define CPMAC_TX_INT_ACK(base,ch) (*(MEM_PTR)(base+0x640+(4*ch)))
++
++#define pCPMAC_TX0_INT_ACK(base) ((MEM_PTR)(base+0x640))
++#define CPMAC_TX0_INT_ACK(base) (*pCPMAC_TX0_INT_ACK(base))
++#define pCPMAC_TX1_INT_ACK(base) ((MEM_PTR)(base+0x644))
++#define CPMAC_TX1_INT_ACK(base) (*pCPMAC_TX1_INT_ACK(base))
++#define pCPMAC_TX2_INT_ACK(base) ((MEM_PTR)(base+0x648))
++#define CPMAC_TX2_INT_ACK(base) (*pCPMAC_TX2_INT_ACK(base))
++#define pCPMAC_TX3_INT_ACK(base) ((MEM_PTR)(base+0x64C))
++#define CPMAC_TX3_INT_ACK(base) (*pCPMAC_TX3_INT_ACK(base))
++#define pCPMAC_TX4_INT_ACK(base) ((MEM_PTR)(base+0x650))
++#define CPMAC_TX4_INT_ACK(base) (*pCPMAC_TX4_INT_ACK(base))
++#define pCPMAC_TX5_INT_ACK(base) ((MEM_PTR)(base+0x654))
++#define CPMAC_TX5_INT_ACK(base) (*pCPMAC_TX5_INT_ACK(base))
++#define pCPMAC_TX6_INT_ACK(base) ((MEM_PTR)(base+0x658))
++#define CPMAC_TX6_INT_ACK(base) (*pCPMAC_TX6_INT_ACK(base))
++#define pCPMAC_TX7_INT_ACK(base) ((MEM_PTR)(base+0x65C))
++#define CPMAC_TX7_INT_ACK(base) (*pCPMAC_TX7_INT_ACK(base))
++#define CPMAC_RX_INT_ACK(base,ch) (*(MEM_PTR)(base+0x660+(4*ch)))
++
++#define pCPMAC_RX0_INT_ACK(base) ((MEM_PTR)(base+0x660))
++#define CPMAC_RX0_INT_ACK(base) (*pCPMAC_RX0_INT_ACK(base))
++#define pCPMAC_RX1_INT_ACK(base) ((MEM_PTR)(base+0x664))
++#define CPMAC_RX1_INT_ACK(base) (*pCPMAC_RX1_INT_ACK(base))
++#define pCPMAC_RX2_INT_ACK(base) ((MEM_PTR)(base+0x668))
++#define CPMAC_RX2_INT_ACK(base) (*pCPMAC_RX2_INT_ACK(base))
++#define pCPMAC_RX3_INT_ACK(base) ((MEM_PTR)(base+0x66C))
++#define CPMAC_RX3_INT_ACK(base) (*pCPMAC_RX3_INT_ACK(base))
++#define pCPMAC_RX4_INT_ACK(base) ((MEM_PTR)(base+0x670))
++#define CPMAC_RX4_INT_ACK(base) (*pCPMAC_RX4_INT_ACK(base))
++#define pCPMAC_RX5_INT_ACK(base) ((MEM_PTR)(base+0x674))
++#define CPMAC_RX5_INT_ACK(base) (*pCPMAC_RX5_INT_ACK(base))
++#define pCPMAC_RX6_INT_ACK(base) ((MEM_PTR)(base+0x678))
++#define CPMAC_RX6_INT_ACK(base) (*pCPMAC_RX6_INT_ACK(base))
++#define pCPMAC_RX7_INT_ACK(base) ((MEM_PTR)(base+0x67C))
++#define CPMAC_RX7_INT_ACK(base) (*pCPMAC_RX7_INT_ACK(base))
++
++/****************************************************************************/
++/* */
++/* R E G I S T E R B I T D E F I N I T I O N S */
++/* */
++/****************************************************************************/
++
++/* TX_CONTROL */
++
++#define TX_EN (1 << 0)
++
++/* RX_CONTROL */
++
++#define RX_EN (1 << 0)
++
++/* RX_MBP_ENABLE */
++
++#define RX_PASS_CRC (1 << 30)
++#define RX_QOS_EN (1 << 29)
++#define RX_NO_CHAIN (1 << 28)
++
++#define RX_CMF_EN (1 << 24)
++#define RX_CSF_EN (1 << 23)
++#define RX_CEF_EN (1 << 22)
++#define RX_CAF_EN (1 << 21)
++
++#define RX_PROM_CH(n) (n << 16)
++#define RX_PROM_CH_MASK RX_PROM_CH(7)
++#define RX_PROM_CH_7 RX_PROM_CH(7)
++#define RX_PROM_CH_6 RX_PROM_CH(6)
++#define RX_PROM_CH_5 RX_PROM_CH(5)
++#define RX_PROM_CH_4 RX_PROM_CH(4)
++#define RX_PROM_CH_3 RX_PROM_CH(3)
++#define RX_PROM_CH_2 RX_PROM_CH(2)
++#define RX_PROM_CH_1 RX_PROM_CH(1)
++#define RX_PROM_CH_0 RX_PROM_CH(0)
++
++#define RX_BROAD_EN (1 << 13)
++
++#define RX_BROAD_CH(n) (n << 8)
++#define RX_BROAD_CH_MASK RX_BROAD_CH(7)
++#define RX_BROAD_CH_7 RX_BROAD_CH(7)
++#define RX_BROAD_CH_6 RX_BROAD_CH(6)
++#define RX_BROAD_CH_5 RX_BROAD_CH(5)
++#define RX_BROAD_CH_4 RX_BROAD_CH(4)
++#define RX_BROAD_CH_3 RX_BROAD_CH(3)
++#define RX_BROAD_CH_2 RX_BROAD_CH(2)
++#define RX_BROAD_CH_1 RX_BROAD_CH(1)
++#define RX_BROAD_CH_0 RX_BROAD_CH(0)
++
++#define RX_MULT_EN (1 << 5)
++
++#define RX_MULT_CH(n) (n << 0)
++#define RX_MULT_CH_MASK RX_MULT_CH(7)
++#define RX_MULT_CH_7 RX_MULT_CH(7)
++#define RX_MULT_CH_6 RX_MULT_CH(6)
++#define RX_MULT_CH_5 RX_MULT_CH(5)
++#define RX_MULT_CH_4 RX_MULT_CH(4)
++#define RX_MULT_CH_3 RX_MULT_CH(3)
++#define RX_MULT_CH_2 RX_MULT_CH(2)
++#define RX_MULT_CH_1 RX_MULT_CH(1)
++#define RX_MULT_CH_0 RX_MULT_CH(0)
++
++
++
++/* RX_UNICAST_SET */
++
++#define RX_CH7_EN (1 << 7)
++#define RX_CH6_EN (1 << 6)
++#define RX_CH5_EN (1 << 5)
++#define RX_CH4_EN (1 << 4)
++#define RX_CH3_EN (1 << 3)
++#define RX_CH2_EN (1 << 2)
++#define RX_CH1_EN (1 << 1)
++#define RX_CH0_EN (1 << 0)
++
++
++
++/* MAC control */
++#define TX_PTYPE (1 << 9)
++#define TX_PACE (1 << 6)
++#define MII_EN (1 << 5)
++#define TX_FLOW_EN (1 << 4)
++#define RX_FLOW_EN (1 << 3)
++#define MTEST (1 << 2)
++#define CTRL_LOOPBACK (1 << 1)
++#define FULLDUPLEX (1 << 0)
++
++
++/* IntVec definitions */
++#define MAC_IN_VECTOR_STATUS_INT (1 << 19)
++#define MAC_IN_VECTOR_HOST_INT (1 << 18)
++#define MAC_IN_VECTOR_RX_INT_OR (1 << 17)
++#define MAC_IN_VECTOR_TX_INT_OR (1 << 16)
++#define MAC_IN_VECTOR_RX_INT_VEC (7 << 8)
++#define MAC_IN_VECTOR_TX_INT_VEC (7)
++
++
++/* MacStatus */
++
++#define TX_HOST_ERR_CODE (0xF << 20)
++#define TX_ERR_CH (0x7 << 16)
++#define RX_HOST_ERR_CODE (0xF << 12)
++#define RX_ERR_CH (0x7 << 8)
++#define RX_QOS_ACT (1 << 2)
++#define RX_FLOW_ACT (1 << 1)
++#define TX_FLOW_ACT (1 << 0)
++#endif _INC_CPMAC_REG
+diff -urN linux.old/drivers/net/avalanche_cpmac/cpmdio.c linux.dev/drivers/net/avalanche_cpmac/cpmdio.c
+--- linux.old/drivers/net/avalanche_cpmac/cpmdio.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpmdio.c 2005-07-12 02:48:42.046593000 +0200
+@@ -0,0 +1,960 @@
++/***************************************************************************
++** TNETD53xx Software Support
++** Copyright(c) 2002, Texas Instruments Incorporated. All Rights Reserved.
++**
++** FILE: cpmdio.c
++**
++** DESCRIPTION:
++** MDIO Polling State Machine API. Functions will enable mii-Phy
++** negotiation.
++**
++** HISTORY:
++** 01Jan01 Denis, Bill Original
++** 27Mar02 Michael Hanrahan (modified from emacmdio.c)
++** 07May02 Michael Hanrahan replaced clockwait for code delay
++** 10Jul02 Michael Hanrahan more debug, if fallback link is selected
++*****************************************************************************/
++#define __CPHAL_CPMDIO
++
++#include "mdio_reg.h"
++
++#ifdef _CPHAL_CPMAC
++#define mdioPrintf PhyDev->HalDev->OsFunc->Printf
++#else
++#define mdioPrintf printf
++#endif
++
++typedef struct _phy_device
++{
++ bit32u miibase;
++ bit32u inst;
++ bit32u PhyState;
++ bit32u MdixMask;
++ bit32u PhyMask;
++ bit32u MLinkMask;
++ bit32u PhyMode;
++#ifdef _CPHAL_CPMAC
++ HAL_DEVICE *HalDev;
++#endif
++} _PHY_DEVICE;
++
++static void _mdioDelayEmulate(PHY_DEVICE *PhyDev, int ClockWait);
++static void _mdioWaitForAccessComplete(PHY_DEVICE *PhyDev);
++static void _mdioUserAccess(PHY_DEVICE *PhyDev, bit32u method, bit32u regadr, bit32u phyadr, bit32u data);
++static bit32u _mdioUserAccessRead(PHY_DEVICE *PhyDev, bit32u regadr, bit32u phyadr);
++static void _mdioUserAccessWrite(PHY_DEVICE *PhyDev, bit32u regadr, bit32u phyadr, bit32u data);
++
++static void _mdioDisablePhy(PHY_DEVICE *PhyDev,bit32u PhyNum);
++static void _mdioPhyTimeOut(PHY_DEVICE *PhyDev);
++static void _mdioResetPhy(PHY_DEVICE *PhyDev,bit32u PhyNum);
++
++static void _mdioDumpPhy(PHY_DEVICE *PhyDev, bit32u p);
++static void _mdioDumpState(PHY_DEVICE *PhyDev);
++
++/* Auto Mdix */
++static void _mdioMdixDelay(PHY_DEVICE *PhyDev);
++static int _mdioMdixSupported(PHY_DEVICE *PhyDev);
++
++static void _MdioDefaultState (PHY_DEVICE *PhyDev);
++static void _MdioFindingState (PHY_DEVICE *PhyDev);
++static void _MdioFoundState (PHY_DEVICE *PhyDev);
++static void _MdioInitState (PHY_DEVICE *PhyDev);
++static void _MdioLinkedState (PHY_DEVICE *PhyDev);
++static void _MdioLinkWaitState (PHY_DEVICE *PhyDev);
++static void _MdioLoopbackState (PHY_DEVICE *PhyDev);
++static void _MdioNwayStartState(PHY_DEVICE *PhyDev);
++static void _MdioNwayWaitState (PHY_DEVICE *PhyDev);
++
++
++
++#ifndef TRUE
++#define TRUE (1==1)
++#endif
++
++#ifndef FALSE
++#define FALSE (1==2)
++#endif
++
++#define PHY_NOT_FOUND 0xFFFF /* Used in Phy Detection */
++
++/*PhyState breakout */
++
++#define PHY_DEV_OFFSET (0)
++#define PHY_DEV_SIZE (5) /* 5 Bits used */
++#define PHY_DEV_MASK (0x1f<<PHY_DEV_OFFSET)
++
++#define PHY_STATE_OFFSET (PHY_DEV_SIZE+PHY_DEV_OFFSET)
++#define PHY_STATE_SIZE (5) /* 10 Bits used */
++#define PHY_STATE_MASK (0x1f<<PHY_STATE_OFFSET)
++ #define INIT (1<<PHY_STATE_OFFSET)
++ #define FINDING (2<<PHY_STATE_OFFSET)
++ #define FOUND (3<<PHY_STATE_OFFSET)
++ #define NWAY_START (4<<PHY_STATE_OFFSET)
++ #define NWAY_WAIT (5<<PHY_STATE_OFFSET)
++ #define LINK_WAIT (6<<PHY_STATE_OFFSET)
++ #define LINKED (7<<PHY_STATE_OFFSET)
++ #define LOOPBACK (8<<PHY_STATE_OFFSET)
++
++#define PHY_SPEED_OFFSET (PHY_STATE_OFFSET+PHY_STATE_SIZE)
++#define PHY_SPEED_SIZE (1) /* 11 Bits used */
++#define PHY_SPEED_MASK (1<<PHY_SPEED_OFFSET)
++
++#define PHY_DUPLEX_OFFSET (PHY_SPEED_OFFSET+PHY_SPEED_SIZE)
++#define PHY_DUPLEX_SIZE (1) /* 12 Bits used */
++#define PHY_DUPLEX_MASK (1<<PHY_DUPLEX_OFFSET)
++
++#define PHY_TIM_OFFSET (PHY_DUPLEX_OFFSET+PHY_DUPLEX_SIZE)
++#define PHY_TIM_SIZE (10) /* 22 Bits used */
++#define PHY_TIM_MASK (0x3ff<<PHY_TIM_OFFSET)
++ #define PHY_FIND_TO ( 2<<PHY_TIM_OFFSET)
++ #define PHY_RECK_TO (200<<PHY_TIM_OFFSET)
++ #define PHY_LINK_TO (500<<PHY_TIM_OFFSET)
++ #define PHY_NWST_TO (500<<PHY_TIM_OFFSET)
++ #define PHY_NWDN_TO (800<<PHY_TIM_OFFSET)
++ #define PHY_MDIX_TO (274<<PHY_TIM_OFFSET) /* 2.74 Seconds <--Spec and empirical */
++
++#define PHY_SMODE_OFFSET (PHY_TIM_OFFSET+PHY_TIM_SIZE)
++#define PHY_SMODE_SIZE (5) /* 27 Bits used */
++#define PHY_SMODE_MASK (0x1f<<PHY_SMODE_OFFSET)
++ #define SMODE_AUTO (0x10<<PHY_SMODE_OFFSET)
++ #define SMODE_FD100 (0x08<<PHY_SMODE_OFFSET)
++ #define SMODE_HD100 (0x04<<PHY_SMODE_OFFSET)
++ #define SMODE_FD10 (0x02<<PHY_SMODE_OFFSET)
++ #define SMODE_HD10 (0x01<<PHY_SMODE_OFFSET)
++ #define SMODE_ALL (0x1f<<PHY_SMODE_OFFSET)
++
++#define PHY_CHNG_OFFSET (PHY_SMODE_OFFSET+PHY_SMODE_SIZE)
++#define PHY_CHNG_SIZE (1) /* 28 Bits used */
++#define PHY_CHNG_MASK (1<<PHY_CHNG_OFFSET)
++ #define PHY_CHANGE (1<<PHY_CHNG_OFFSET)
++
++#define PHY_TIMEDOUT_OFFSET (PHY_CHNG_OFFSET+PHY_CHNG_SIZE)
++#define PHY_TIMEDOUT_SIZE (1) /* 29 Bits used */
++#define PHY_TIMEDOUT_MASK (1<<PHY_TIMEDOUT_OFFSET)
++ #define PHY_MDIX_SWITCH (1<<PHY_TIMEDOUT_OFFSET)
++
++#define PHY_MDIX_OFFSET (PHY_TIMEDOUT_OFFSET+PHY_TIMEDOUT_SIZE)
++#define PHY_MDIX_SIZE (1) /* 30 Bits used */
++#define PHY_MDIX_MASK (1<<PHY_MDIX_OFFSET)
++ #define PHY_MDIX (1<<PHY_MDIX_OFFSET)
++
++static char *lstate[]={"NULL","INIT","FINDING","FOUND","NWAY_START","NWAY_WAIT","LINK_WAIT","LINKED", "LOOPBACK"};
++static int cpMacDebug;
++
++/* Local MDIO Register Macros */
++
++#define myMDIO_ALIVE MDIO_ALIVE (PhyDev->miibase)
++#define myMDIO_CONTROL MDIO_CONTROL (PhyDev->miibase)
++#define myMDIO_LINK MDIO_LINK (PhyDev->miibase)
++#define myMDIO_LINKINT MDIO_LINKINT (PhyDev->miibase)
++#define myMDIO_USERACCESS MDIO_USERACCESS(PhyDev->miibase, PhyDev->inst)
++#define myMDIO_USERPHYSEL MDIO_USERPHYSEL(PhyDev->miibase, PhyDev->inst)
++#define myMDIO_VER MDIO_VER (PhyDev->miibase)
++
++#ifndef VOLATILE32
++#define VOLATILE32(addr) (*((volatile bit32u *)(addr)))
++#endif
++
++/************************************
++***
++*** Delays at least ClockWait cylces
++*** before returning
++***
++**************************************/
++void _mdioDelayEmulate(PHY_DEVICE *PhyDev, int ClockWait)
++ {
++#ifdef _CPHAL_CPMAC /*+RC3.02*/
++ HAL_DEVICE *HalDev = PhyDev->HalDev; /*+RC3.02*/
++ osfuncSleep((int*)&ClockWait); /*+RC3.02*/
++#else /*+RC3.02*/
++ volatile bit32u i=0;
++ while(ClockWait--)
++ {
++ i |= myMDIO_LINK; /* MDIO register access to burn cycles */
++ }
++#endif
++ }
++
++void _mdioWaitForAccessComplete(PHY_DEVICE *PhyDev)
++ {
++ while((myMDIO_USERACCESS & MDIO_USERACCESS_GO)!=0)
++ {
++ }
++ }
++
++void _mdioUserAccess(PHY_DEVICE *PhyDev, bit32u method, bit32u regadr, bit32u phyadr, bit32u data)
++ {
++ bit32u control;
++
++ control = MDIO_USERACCESS_GO |
++ (method) |
++ (((regadr) << 21) & MDIO_USERACCESS_REGADR) |
++ (((phyadr) << 16) & MDIO_USERACCESS_PHYADR) |
++ ((data) & MDIO_USERACCESS_DATA);
++
++ myMDIO_USERACCESS = control;
++ }
++
++
++
++/************************************
++***
++*** Waits for MDIO_USERACCESS to be ready and reads data
++*** If 'WaitForData' set, waits for read to complete and returns Data,
++*** otherwise returns 0
++*** Note: 'data' is 16 bits but we use 32 bits
++*** to be consistent with rest of the code.
++***
++**************************************/
++bit32u _mdioUserAccessRead(PHY_DEVICE *PhyDev, bit32u regadr, bit32u phyadr)
++ {
++
++ _mdioWaitForAccessComplete(PhyDev); /* Wait until UserAccess ready */
++ _mdioUserAccess(PhyDev, MDIO_USERACCESS_READ, regadr, phyadr, 0);
++ _mdioWaitForAccessComplete(PhyDev); /* Wait for Read to complete */
++
++ return(myMDIO_USERACCESS & MDIO_USERACCESS_DATA);
++ }
++
++
++/************************************
++***
++*** Waits for MDIO_USERACCESS to be ready and writes data
++***
++**************************************/
++void _mdioUserAccessWrite(PHY_DEVICE *PhyDev, bit32u regadr, bit32u phyadr, bit32u data)
++ {
++ _mdioWaitForAccessComplete(PhyDev); /* Wait until UserAccess ready */
++ _mdioUserAccess(PhyDev, MDIO_USERACCESS_WRITE, regadr, phyadr, data);
++ }
++
++void _mdioDumpPhyDetailed(PHY_DEVICE *PhyDev)
++{
++ bit32u *PhyState = &PhyDev->PhyState;
++ bit32u PhyNum;
++ int RegData;
++
++ PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET;
++
++ RegData = _mdioUserAccessRead(PhyDev, 0, PhyNum);
++ mdioPrintf("PhyControl: %04X, Lookback=%s, Speed=%s, Duplex=%s\n",
++ RegData,
++ RegData&PHY_LOOP?"On":"Off",
++ RegData&PHY_100?"100":"10",
++ RegData&PHY_FD?"Full":"Half");
++ RegData = _mdioUserAccessRead(PhyDev, 1, PhyNum);
++ mdioPrintf("PhyStatus: %04X, AutoNeg=%s, Link=%s\n",
++ RegData,
++ RegData&NWAY_COMPLETE?"Complete":"NotComplete",
++ RegData&PHY_LINKED?"Up":"Down");
++ RegData = _mdioUserAccessRead(PhyDev, 4, PhyNum);
++ mdioPrintf("PhyMyCapability: %04X, 100FD=%s, 100HD=%s, 10FD=%s, 10HD=%s\n",
++ RegData,
++ RegData&NWAY_FD100?"Yes":"No",
++ RegData&NWAY_HD100?"Yes":"No",
++ RegData&NWAY_FD10?"Yes":"No",
++ RegData&NWAY_HD10?"Yes":"No");
++
++ RegData = _mdioUserAccessRead(PhyDev, 5, PhyNum);
++ mdioPrintf("PhyPartnerCapability: %04X, 100FD=%s, 100HD=%s, 10FD=%s, 10HD=%s\n",
++ RegData,
++ RegData&NWAY_FD100?"Yes":"No",
++ RegData&NWAY_HD100?"Yes":"No",
++ RegData&NWAY_FD10?"Yes":"No",
++ RegData&NWAY_HD10?"Yes":"No");
++}
++void _mdioDumpPhy(PHY_DEVICE *PhyDev, bit32u p)
++ {
++ bit32u j,n,PhyAcks;
++ bit32u PhyRegAddr;
++ bit32u phy_num;
++ bit32u PhyMask = PhyDev->PhyMask;
++
++ PhyAcks=myMDIO_ALIVE;
++ PhyAcks&=PhyMask; /* Only interested in 'our' Phys */
++
++ for(phy_num=0,j=1;phy_num<32;phy_num++,j<<=1)
++ {
++ if (PhyAcks&j)
++ {
++ mdioPrintf("%2d%s:",phy_num,(phy_num==p)?">":" ");
++ for(PhyRegAddr=0;PhyRegAddr<6;PhyRegAddr++)
++ {
++ n = _mdioUserAccessRead(PhyDev, PhyRegAddr, phy_num);
++ mdioPrintf(" %04x",n&0x0ffff);
++ }
++ mdioPrintf("\n");
++ }
++ }
++ _mdioDumpPhyDetailed(PhyDev);
++ }
++
++void _mdioDumpState(PHY_DEVICE *PhyDev)
++ {
++ bit32u state = PhyDev->PhyState;
++
++ if (!cpMacDebug) return;
++
++ mdioPrintf("Phy: %d, ",(state&PHY_DEV_MASK)>>PHY_DEV_OFFSET);
++ mdioPrintf("State: %d/%s, ",(state&PHY_STATE_MASK)>>PHY_STATE_OFFSET,lstate[(state&PHY_STATE_MASK)>>PHY_STATE_OFFSET]);
++ mdioPrintf("Speed: %d, ",(state&PHY_SPEED_MASK)>>PHY_SPEED_OFFSET);
++ mdioPrintf("Dup: %d, ",(state&PHY_DUPLEX_MASK)>>PHY_DUPLEX_OFFSET);
++ mdioPrintf("Tim: %d, ",(state&PHY_TIM_MASK)>>PHY_TIM_OFFSET);
++ mdioPrintf("SMode: %d, ",(state&PHY_SMODE_MASK)>>PHY_SMODE_OFFSET);
++ mdioPrintf("Chng: %d",(state&PHY_CHNG_MASK)>>PHY_CHNG_OFFSET);
++ mdioPrintf("\n");
++
++ if (((state&PHY_STATE_MASK)!=FINDING)&&((state&PHY_STATE_MASK)!=INIT))
++ _mdioDumpPhy(PhyDev, (state&PHY_DEV_MASK)>>PHY_DEV_OFFSET);
++ }
++
++
++void _mdioResetPhy(PHY_DEVICE *PhyDev,bit32u PhyNum)
++ {
++ bit16u PhyControlReg;
++
++ _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, PHY_RESET);
++ if (cpMacDebug)
++ mdioPrintf("cpMacMdioPhYReset(%d)\n",PhyNum);
++
++ /* Read control register until Phy Reset is complete */
++ do
++ {
++ PhyControlReg = _mdioUserAccessRead(PhyDev, PHY_CONTROL_REG, PhyNum);
++ }
++ while (PhyControlReg & PHY_RESET); /* Wait for Reset to clear */
++ }
++
++void _mdioDisablePhy(PHY_DEVICE *PhyDev,bit32u PhyNum)
++ {
++ _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, PHY_ISOLATE|PHY_PDOWN);
++
++ if (cpMacDebug)
++ mdioPrintf("cpMacMdioDisablePhy(%d)\n",PhyNum);
++
++ }
++
++void _MdioInitState(PHY_DEVICE *PhyDev)
++ {
++ bit32u *PhyState = &PhyDev->PhyState;
++ bit32u CurrentState;
++
++ CurrentState=*PhyState;
++ CurrentState=(CurrentState&~PHY_TIM_MASK)|(PHY_FIND_TO);
++ CurrentState=(CurrentState&~PHY_STATE_MASK)|(FINDING);
++ CurrentState=(CurrentState&~PHY_SPEED_MASK);
++ CurrentState=(CurrentState&~PHY_DUPLEX_MASK);
++ CurrentState|=PHY_CHANGE;
++
++ *PhyState=CurrentState;
++
++ }
++
++void _MdioFindingState(PHY_DEVICE *PhyDev)
++ {
++ bit32u *PhyState = &PhyDev->PhyState;
++ bit32u PhyMask = PhyDev->PhyMask;
++ bit32u PhyNum,i,j,PhyAcks;
++
++
++ PhyNum=PHY_NOT_FOUND;
++
++ if (*PhyState&PHY_TIM_MASK)
++ {
++ *PhyState=(*PhyState&~PHY_TIM_MASK)|((*PhyState&PHY_TIM_MASK)-(1<<PHY_TIM_OFFSET));
++ }
++ else
++ {
++ PhyAcks=myMDIO_ALIVE;
++ PhyAcks&=PhyMask; /* Only interested in 'our' Phys */
++
++ for(i=0,j=1;(i<32)&&((j&PhyAcks)==0);i++,j<<=1);
++
++ if ((PhyAcks)&&(i<32)) PhyNum=i;
++ if (PhyNum!=PHY_NOT_FOUND)
++ {
++ /* Phy Found! */
++ *PhyState=(*PhyState&~PHY_DEV_MASK)|((PhyNum&PHY_DEV_MASK)<<PHY_DEV_OFFSET);
++ *PhyState=(*PhyState&~PHY_STATE_MASK)|(FOUND);
++ *PhyState|=PHY_CHANGE;
++ if (cpMacDebug)
++ mdioPrintf("cpMacMdioFindingState: PhyNum: %d\n",PhyNum);
++ }
++ else
++ {
++ if (cpMacDebug)
++ mdioPrintf("cpMacMdioFindingState: Timed Out looking for a Phy!\n");
++ *PhyState|=PHY_RECK_TO; /* This state currently has no support?*/
++ }
++ }
++ }
++
++void _MdioFoundState(PHY_DEVICE *PhyDev)
++ {
++ bit32u *PhyState = &PhyDev->PhyState;
++ bit32u PhyMask = PhyDev->PhyMask;
++ bit32u MLinkMask = PhyDev->MLinkMask;
++ bit32u PhyNum,PhyStatus,NWAYadvertise,m,phynum,i,j,PhyAcks;
++ bit32u PhySel;
++
++ if ((*PhyState&PHY_SMODE_MASK)==0) return;
++
++ PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET;
++
++ PhyAcks=myMDIO_ALIVE;
++ PhyAcks&=PhyMask; /* Only interested in 'our' Phys */
++
++ /* Will now isolate all our Phys, except the one we have decided to use */
++ for(phynum=0,j=1;phynum<32;phynum++,j<<=1)
++ {
++ if (PhyAcks&j)
++ {
++ if (phynum!=PhyNum) /* Do not disabled Found Phy */
++ _mdioDisablePhy(PhyDev,phynum);
++ }
++ }
++
++ /* Reset the Phy and proceed with auto-negotiation */
++ _mdioResetPhy(PhyDev,PhyNum);
++
++ /* Now setup the MDIOUserPhySel register */
++
++ PhySel=PhyNum; /* Set the phy address */
++
++ /* Set the way Link will be Monitored */
++ /* Check the Link Selection Method */
++ if ((1 << PhyNum) & MLinkMask)
++ PhySel |= MDIO_USERPHYSEL_LINKSEL;
++
++ myMDIO_USERPHYSEL = PhySel; /* update PHYSEL */
++
++ /* Get the Phy Status */
++ PhyStatus = _mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum);
++
++
++#ifdef _CPHAL_CPMAC
++ /* For Phy Internal loopback test, need to wait until Phy
++ found, then set Loopback */
++ if (PhyDev->HalDev->MdioConnect & _CPMDIO_LOOPBK)
++ {
++ /* Set Phy in Loopback */
++ _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, PHY_LOOP|PHY_FD);
++ /* Do a read to ensure PHY_LOOP has completed */
++ _mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum);
++ *PhyState=(*PhyState&~PHY_STATE_MASK)|(LOOPBACK);
++ *PhyState|=PHY_CHANGE;
++ return;
++ }
++#endif
++
++
++ if (cpMacDebug)
++ mdioPrintf("Enable Phy to negotiate external connection\n");
++
++ NWAYadvertise=NWAY_SEL;
++ if (*PhyState&SMODE_FD100) NWAYadvertise|=NWAY_FD100;
++ if (*PhyState&SMODE_HD100) NWAYadvertise|=NWAY_HD100;
++ if (*PhyState&SMODE_FD10) NWAYadvertise|=NWAY_FD10;
++ if (*PhyState&SMODE_HD10) NWAYadvertise|=NWAY_HD10;
++
++ *PhyState&=~(PHY_TIM_MASK|PHY_STATE_MASK);
++ if ((PhyStatus&NWAY_CAPABLE)&&(*PhyState&SMODE_AUTO)) /*NWAY Phy Detected*/
++ {
++ /*For NWAY compliant Phys */
++
++ _mdioUserAccessWrite(PhyDev, NWAY_ADVERTIZE_REG, PhyNum, NWAYadvertise);
++
++ if (cpMacDebug)
++ {
++ mdioPrintf("NWAY Advertising: ");
++ if (NWAYadvertise&NWAY_FD100) mdioPrintf("FullDuplex-100 ");
++ if (NWAYadvertise&NWAY_HD100) mdioPrintf("HalfDuplex-100 ");
++ if (NWAYadvertise&NWAY_FD10) mdioPrintf("FullDuplex-10 ");
++ if (NWAYadvertise&NWAY_HD10) mdioPrintf("HalfDuplex-10 ");
++ mdioPrintf("\n");
++ }
++
++ _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, AUTO_NEGOTIATE_EN);
++
++ _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, AUTO_NEGOTIATE_EN|RENEGOTIATE);
++
++ *PhyState|=PHY_CHANGE|PHY_NWST_TO|NWAY_START;
++ }
++ else
++ {
++ *PhyState&=~SMODE_AUTO; /*The Phy is not capable of auto negotiation! */
++ m=NWAYadvertise;
++ for(j=0x8000,i=0;(i<16)&&((j&m)==0);i++,j>>=1);
++ m=j;
++ j=0;
++ if (m&(NWAY_FD100|NWAY_HD100))
++ {
++ j=PHY_100;
++ m&=(NWAY_FD100|NWAY_HD100);
++ }
++ if (m&(NWAY_FD100|NWAY_FD10))
++ j |= PHY_FD;
++ if (cpMacDebug)
++ mdioPrintf("Requested PHY mode %s Duplex %s Mbps\n",(j&PHY_FD)?"Full":"Half",(j&PHY_100)?"100":"10");
++ _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, j);
++ *PhyState&=~PHY_SPEED_MASK;
++ if (j&PHY_100)
++ *PhyState|=(1<<PHY_SPEED_OFFSET);
++ *PhyState&=~PHY_DUPLEX_MASK;
++ if (j&PHY_FD)
++ *PhyState|=(1<<PHY_DUPLEX_OFFSET);
++ *PhyState|=PHY_CHANGE|PHY_LINK_TO|LINK_WAIT;
++ }
++ _mdioMdixDelay(PhyDev); /* If AutoMdix add delay */
++ }
++
++void _MdioNwayStartState(PHY_DEVICE *PhyDev)
++ {
++ bit32u *PhyState = &PhyDev->PhyState;
++ bit32u PhyNum,PhyMode;
++
++ PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET;
++
++ /*Wait for Negotiation to start */
++
++ PhyMode=_mdioUserAccessRead(PhyDev, PHY_CONTROL_REG, PhyNum);
++
++ if((PhyMode&RENEGOTIATE)==0)
++ {
++ _mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum); /*Flush pending latch bits*/
++ *PhyState&=~(PHY_STATE_MASK|PHY_TIM_MASK);
++ *PhyState|=PHY_CHANGE|NWAY_WAIT|PHY_NWDN_TO;
++ _mdioMdixDelay(PhyDev); /* If AutoMdix add delay */
++ }
++ else
++ {
++ if (*PhyState&PHY_TIM_MASK)
++ *PhyState=(*PhyState&~PHY_TIM_MASK)|((*PhyState&PHY_TIM_MASK)-(1<<PHY_TIM_OFFSET));
++ else
++ _mdioPhyTimeOut(PhyDev);
++ }
++ }
++
++void _MdioNwayWaitState(PHY_DEVICE *PhyDev)
++ {
++ bit32u *PhyState = &PhyDev->PhyState;
++ bit32u PhyNum,PhyStatus,NWAYadvertise,NWAYREadvertise,NegMode,i,j;
++
++ PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET;
++
++ PhyStatus=_mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum);
++
++ if (PhyStatus&NWAY_COMPLETE)
++ {
++ *PhyState|=PHY_CHANGE;
++ *PhyState&=~PHY_SPEED_MASK;
++ *PhyState&=~PHY_DUPLEX_MASK;
++
++ NWAYadvertise =_mdioUserAccessRead(PhyDev, NWAY_ADVERTIZE_REG, PhyNum);
++ NWAYREadvertise =_mdioUserAccessRead(PhyDev, NWAY_REMADVERTISE_REG, PhyNum);
++
++ /* Negotiated mode is we and the remote have in common */
++ NegMode = NWAYadvertise & NWAYREadvertise;
++
++ if (cpMacDebug)
++ {
++ mdioPrintf("Phy: %d, ",(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET);
++ mdioPrintf("NegMode %04X, NWAYadvertise %04X, NWAYREadvertise %04X\n",
++ NegMode, NWAYadvertise, NWAYREadvertise);
++ }
++
++ /* Limit negotiation to fields below */
++ NegMode &= (NWAY_FD100|NWAY_HD100|NWAY_FD10|NWAY_HD10);
++
++ if (NegMode==0)
++ {
++ NegMode=(NWAY_HD100|NWAY_HD10)&NWAYadvertise; /*or 10 ?? who knows, Phy is not MII compliant*/
++ if(cpMacDebug)
++ {
++ mdioPrintf("Mdio:WARNING: Negotiation complete but NO agreement, default is HD\n");
++ _mdioDumpPhyDetailed(PhyDev);
++ }
++ }
++ for(j=0x8000,i=0;(i<16)&&((j&NegMode)==0);i++,j>>=1);
++
++
++ NegMode=j;
++ if (cpMacDebug)
++ {
++ mdioPrintf("Negotiated connection: ");
++ if (NegMode&NWAY_FD100) mdioPrintf("FullDuplex 100 Mbs\n");
++ if (NegMode&NWAY_HD100) mdioPrintf("HalfDuplex 100 Mbs\n");
++ if (NegMode&NWAY_FD10) mdioPrintf("FullDuplex 10 Mbs\n");
++ if (NegMode&NWAY_HD10) mdioPrintf("HalfDuplex 10 Mbs\n");
++ }
++ if (NegMode!=0)
++ {
++ if (PhyStatus&PHY_LINKED)
++ *PhyState=(*PhyState&~PHY_STATE_MASK)|LINKED;
++ else
++ *PhyState=(*PhyState&~PHY_STATE_MASK)|LINK_WAIT;
++ if (NegMode&(NWAY_FD100|NWAY_HD100))
++ *PhyState=(*PhyState&~PHY_SPEED_MASK)|(1<<PHY_SPEED_OFFSET);
++ if (NegMode&(NWAY_FD100|NWAY_FD10))
++ *PhyState=(*PhyState&~PHY_DUPLEX_MASK)|(1<<PHY_DUPLEX_OFFSET);
++ }
++ }
++ else
++ {
++ if (*PhyState&PHY_TIM_MASK)
++ *PhyState=(*PhyState&~PHY_TIM_MASK)|((*PhyState&PHY_TIM_MASK)-(1<<PHY_TIM_OFFSET));
++ else
++ _mdioPhyTimeOut(PhyDev);
++ }
++ }
++
++void _MdioLinkWaitState(PHY_DEVICE *PhyDev)
++ {
++ bit32u *PhyState = &PhyDev->PhyState;
++ bit32u PhyStatus;
++ bit32u PhyNum;
++
++ PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET;
++
++ PhyStatus=_mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum);
++
++ if (PhyStatus&PHY_LINKED)
++ {
++ *PhyState=(*PhyState&~PHY_STATE_MASK)|LINKED;
++ *PhyState|=PHY_CHANGE;
++ }
++ else
++ {
++ if (*PhyState&PHY_TIM_MASK)
++ *PhyState=(*PhyState&~PHY_TIM_MASK)|((*PhyState&PHY_TIM_MASK)-(1<<PHY_TIM_OFFSET));
++ else
++ _mdioPhyTimeOut(PhyDev);
++ }
++ }
++
++void _mdioPhyTimeOut(PHY_DEVICE *PhyDev)
++ {
++ bit32u *PhyState;
++
++ if(_mdioMdixSupported(PhyDev) == 0)
++ return; /* AutoMdix not supported */
++
++ PhyState = &PhyDev->PhyState;
++
++ /* Indicate MDI/MDIX mode switch is needed */
++ *PhyState|=PHY_MDIX_SWITCH;
++
++ /* Toggle the MDIX mode indicatir */
++ if(*PhyState & PHY_MDIX)
++ *PhyState &= ~PHY_MDIX_MASK; /* Current State is MDIX, set to MDI */
++ else
++ *PhyState |= PHY_MDIX_MASK; /* Current State is MDI, set to MDIX */
++
++ /* Reset state machine to FOUND */
++ *PhyState=(*PhyState&~PHY_STATE_MASK)|(FOUND);
++ }
++
++void _MdioLoopbackState(PHY_DEVICE *PhyDev)
++ {
++ return;
++ }
++
++void _MdioLinkedState(PHY_DEVICE *PhyDev)
++ {
++ bit32u *PhyState = &PhyDev->PhyState;
++ bit32u PhyNum = (*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET;
++
++ if (myMDIO_LINK&(1<<PhyNum)) return; /* if still Linked, exit*/
++
++ /* Not Linked */
++ *PhyState&=~(PHY_STATE_MASK|PHY_TIM_MASK);
++ if (*PhyState&SMODE_AUTO)
++ *PhyState|=PHY_CHANGE|NWAY_WAIT|PHY_NWDN_TO;
++ else
++ *PhyState|=PHY_CHANGE|PHY_LINK_TO|LINK_WAIT;
++
++ _mdioMdixDelay(PhyDev); /* If AutoMdix add delay */
++ }
++
++void _MdioDefaultState(PHY_DEVICE *PhyDev)
++ {
++ bit32u *PhyState = &PhyDev->PhyState;
++ /*Awaiting a cpMacMdioInit call */
++ *PhyState|=PHY_CHANGE;
++ }
++
++
++/*User Calls********************************************************* */
++
++void cpMacMdioClose(PHY_DEVICE *PhyDev, int Full)
++ {
++ }
++
++
++int cpMacMdioInit(PHY_DEVICE *PhyDev, bit32u miibase, bit32u inst, bit32u PhyMask, bit32u MLinkMask, bit32u MdixMask, bit32u ResetReg, bit32u ResetBit, bit32u MdioBusFreq, bit32u MdioClockFreq, int verbose, void *Info)
++ {
++ bit32u HighestChannel;
++ bit32u ControlState;
++ bit32u *PhyState = &PhyDev->PhyState;
++ bit32u clkdiv; /*MJH+030328*/
++
++ cpMacDebug=verbose;
++
++ PhyDev->miibase = miibase;
++ PhyDev->inst = inst;
++ PhyDev->PhyMask = PhyMask;
++ PhyDev->MLinkMask = MLinkMask;
++ PhyDev->MdixMask = MdixMask;
++#ifdef _CPHAL_CPMAC
++ PhyDev->HalDev = (HAL_DEVICE*) Info;
++#endif
++
++ *PhyState &= ~PHY_MDIX_MASK; /* Set initial State to MDI */
++
++ /* Check that the channel supplied is within range */
++ HighestChannel = (myMDIO_CONTROL & MDIO_CONTROL_HIGHEST_USER_CHANNEL) > 8;
++ if(inst > HighestChannel)
++ return(HighestChannel);
++
++ /*Setup MII MDIO access regs */
++
++ /* Calculate the correct value for the mclkdiv */
++ /* See PITS #14 */
++ if (MdioClockFreq) /*MJH+030402*/
++ clkdiv = (MdioBusFreq / MdioClockFreq) - 1; /*MJH+030402*/
++ else /*MJH+030402*/
++ clkdiv = 0xFF; /*MJH+030402*/
++
++ ControlState = MDIO_CONTROL_ENABLE;
++ ControlState |= (clkdiv & MDIO_CONTROL_CLKDIV); /*MJH+030328*/
++
++ /*
++ If mii is not out of reset or if the Control Register is not set correctly
++ then initalize
++ */
++ if( !(VOLATILE32(ResetReg) & (1 << ResetBit)) ||
++ ((myMDIO_CONTROL & (MDIO_CONTROL_CLKDIV | MDIO_CONTROL_ENABLE)) != ControlState) )/*GSG~030404*/
++ {
++ /* MII not setup, Setup initial condition */
++ VOLATILE32(ResetReg) &= ~(1 << ResetBit);
++ _mdioDelayEmulate(PhyDev, 64);
++ VOLATILE32(ResetReg) |= (1 << ResetBit); /* take mii out of reset */
++ _mdioDelayEmulate(PhyDev, 64);
++ myMDIO_CONTROL = ControlState; /* Enable MDIO */
++ }
++
++ *PhyState=INIT;
++
++ if (cpMacDebug)
++ mdioPrintf("cpMacMdioInit\n");
++ _mdioDumpState(PhyDev);
++ return(0);
++ }
++
++void cpMacMdioSetPhyMode(PHY_DEVICE *PhyDev,bit32u PhyMode)
++ {
++ bit32u *PhyState = &PhyDev->PhyState;
++ bit32u CurrentState;
++
++ PhyDev->PhyMode = PhyMode; /* used for AUTOMIDX, planned to replace PhyState fields */
++
++ *PhyState&=~PHY_SMODE_MASK;
++
++ if (PhyMode&NWAY_AUTO) *PhyState|=SMODE_AUTO;
++ if (PhyMode&NWAY_FD100) *PhyState|=SMODE_FD100;
++ if (PhyMode&NWAY_HD100) *PhyState|=SMODE_HD100;
++ if (PhyMode&NWAY_FD10) *PhyState|=SMODE_FD10;
++ if (PhyMode&NWAY_HD10) *PhyState|=SMODE_HD10;
++
++ CurrentState=*PhyState&PHY_STATE_MASK;
++ if ((CurrentState==NWAY_START)||
++ (CurrentState==NWAY_WAIT) ||
++ (CurrentState==LINK_WAIT) ||
++ (CurrentState==LINKED) )
++ *PhyState=(*PhyState&~PHY_STATE_MASK)|FOUND|PHY_CHANGE;
++ if (cpMacDebug)
++ mdioPrintf("cpMacMdioSetPhyMode:%08X Auto:%d, FD10:%d, HD10:%d, FD100:%d, HD100:%d\n", PhyMode,
++ PhyMode&NWAY_AUTO, PhyMode&NWAY_FD10, PhyMode&NWAY_HD10, PhyMode&NWAY_FD100,
++ PhyMode&NWAY_HD100);
++ _mdioDumpState(PhyDev);
++ }
++
++/* cpMacMdioTic is called every 10 mili seconds to process Phy states */
++
++int cpMacMdioTic(PHY_DEVICE *PhyDev)
++ {
++ bit32u *PhyState = &PhyDev->PhyState;
++ bit32u CurrentState;
++
++ /*Act on current state of the Phy */
++
++ CurrentState=*PhyState;
++ switch(CurrentState&PHY_STATE_MASK)
++ {
++ case INIT: _MdioInitState(PhyDev); break;
++ case FINDING: _MdioFindingState(PhyDev); break;
++ case FOUND: _MdioFoundState(PhyDev); break;
++ case NWAY_START: _MdioNwayStartState(PhyDev); break;
++ case NWAY_WAIT: _MdioNwayWaitState(PhyDev); break;
++ case LINK_WAIT: _MdioLinkWaitState(PhyDev); break;
++ case LINKED: _MdioLinkedState(PhyDev); break;
++ case LOOPBACK: _MdioLoopbackState(PhyDev); break;
++ default: _MdioDefaultState(PhyDev); break;
++ }
++
++ /*Dump state info if a change has been detected */
++
++ if ((CurrentState&~PHY_TIM_MASK)!=(*PhyState&~PHY_TIM_MASK))
++ _mdioDumpState(PhyDev);
++
++ /* Check is MDI/MDIX mode switch is needed */
++ if(*PhyState & PHY_MDIX_SWITCH)
++ {
++ bit32u Mdix;
++
++ *PhyState &= ~PHY_MDIX_SWITCH; /* Clear Mdix Flip indicator */
++
++ if(*PhyState & PHY_MDIX)
++ Mdix = 1;
++ else
++ Mdix = 0;
++ return(_MIIMDIO_MDIXFLIP|Mdix);
++ }
++
++ /*Return state change to user */
++
++ if (*PhyState&PHY_CHNG_MASK)
++ {
++ *PhyState&=~PHY_CHNG_MASK;
++ return(1);
++ }
++ else
++ return(0);
++ }
++
++/* cpMacMdioGetDuplex is called to retrieve the Duplex info */
++
++int cpMacMdioGetDuplex(PHY_DEVICE *PhyDev)
++ {
++ bit32u *PhyState = &PhyDev->PhyState;
++ return((*PhyState&PHY_DUPLEX_MASK)?1:0); /* return 0 or a 1 */
++ }
++
++/* cpMacMdioGetSpeed is called to retreive the Speed info */
++
++int cpMacMdioGetSpeed(PHY_DEVICE *PhyDev)
++ {
++ bit32u *PhyState = &PhyDev->PhyState;
++ return(*PhyState&PHY_SPEED_MASK);
++ }
++
++/* cpMacMdioGetPhyNum is called to retreive the Phy Device Adr info */
++
++int cpMacMdioGetPhyNum(PHY_DEVICE *PhyDev)
++ {
++ bit32u *PhyState = &PhyDev->PhyState;
++ return((*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET);
++ }
++
++/* cpMacMdioGetLoopback is called to Determine if the LOOPBACK state has been reached*/
++
++int cpMacMdioGetLoopback(PHY_DEVICE *PhyDev)
++ {
++ bit32u *PhyState = &PhyDev->PhyState;
++ return((*PhyState&PHY_STATE_MASK)==LOOPBACK);
++ }
++/* cpMacMdioGetLinked is called to Determine if the LINKED state has been reached*/
++
++int cpMacMdioGetLinked(PHY_DEVICE *PhyDev)
++ {
++ bit32u *PhyState = &PhyDev->PhyState;
++ return((*PhyState&PHY_STATE_MASK)==LINKED);
++ }
++
++void cpMacMdioLinkChange(PHY_DEVICE *PhyDev)
++ {
++ bit32u *PhyState = &PhyDev->PhyState;
++ bit32u PhyNum,PhyStatus;
++
++ PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET;
++
++ if (cpMacMdioGetLinked(PhyDev))
++ {
++ PhyStatus=_mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum);
++
++ if ((PhyStatus&PHY_LINKED)==0)
++ {
++ *PhyState&=~(PHY_TIM_MASK|PHY_STATE_MASK);
++ if (*PhyState&SMODE_AUTO)
++ {
++ _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, AUTO_NEGOTIATE_EN|RENEGOTIATE);
++ *PhyState|=PHY_CHANGE|PHY_NWST_TO|NWAY_START;
++ }
++ else
++ {
++ *PhyState|=PHY_CHANGE|PHY_LINK_TO|LINK_WAIT;
++ }
++ }
++ }
++ }
++
++void cpMacMdioGetVer(bit32u miibase, bit32u *ModID, bit32u *RevMaj, bit32u *RevMin)
++ {
++ bit32u Ver;
++
++ Ver = MDIO_VER(miibase);
++
++ *ModID = (Ver & MDIO_VER_MODID) >> 16;
++ *RevMaj = (Ver & MDIO_VER_REVMAJ) >> 8;
++ *RevMin = (Ver & MDIO_VER_REVMIN);
++ }
++
++int cpMacMdioGetPhyDevSize(void)
++ {
++ return(sizeof(PHY_DEVICE));
++ }
++
++ /* returns 0 if current Phy has AutoMdix support, otherwise 0 */
++int _mdioMdixSupported(PHY_DEVICE *PhyDev)
++ {
++ bit32u *PhyState = &PhyDev->PhyState;
++ bit32u PhyNum;
++
++ if((PhyDev->PhyMode & NWAY_AUTOMDIX) == 0)
++ return(0); /* AutoMdix not turned on */
++
++ PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET;
++ if( ((1<<PhyNum) & PhyDev->MdixMask) == 0)
++ return(0); /* Phy does not support AutoMdix*/
++
++ return(1);
++ }
++
++/* If current Phy has AutoMdix support add Mdix Delay to the Timer State Value */
++void _mdioMdixDelay(PHY_DEVICE *PhyDev)
++ {
++ int Delay;
++ bit32u *PhyState = &PhyDev->PhyState;
++#ifdef _CPHAL_CPMAC
++ HAL_DEVICE *HalDev = PhyDev->HalDev;
++#endif
++
++ if(_mdioMdixSupported(PhyDev) == 0)
++ return; /* AutoMdix not supported */
++/* Currently only supported when used with the CPMAC */
++#ifdef _CPHAL_CPMAC
++ /* Get the Delay value in milli-seconds and convert to ten-milli second value */
++ Delay = cpmacRandomRange(HalDev, _AUTOMDIX_DELAY_MIN, _AUTOMDIX_DELAY_MAX);
++ Delay /= 10;
++
++ /* Add AutoMidx Random Switch Delay to AutoMdix Link Delay */
++
++ Delay += (PHY_MDIX_TO>>PHY_TIM_OFFSET);
++
++ /* Change Timeout value to AutoMdix standard */
++ *PhyState &= ~(PHY_TIM_MASK); /* Clear current Time out value */
++ *PhyState |= (Delay<<PHY_TIM_OFFSET); /* Set new value */
++#endif
++ }
++
++
+diff -urN linux.old/drivers/net/avalanche_cpmac/cpmdio.h linux.dev/drivers/net/avalanche_cpmac/cpmdio.h
+--- linux.old/drivers/net/avalanche_cpmac/cpmdio.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpmdio.h 2005-07-12 02:48:42.047593000 +0200
+@@ -0,0 +1,73 @@
++/*****************************************************************************
++** TNETD53xx Software Support
++** Copyright(c) 2002, Texas Instruments Incorporated. All Rights Reserved.
++**
++** FILE: cpmdio.h User Include for MDIO API Access
++**
++** DESCRIPTION:
++** This include file contains definitions for the the MDIO API
++**
++** HISTORY:
++** 27Mar02 Michael Hanrahan Original (modified from emacmdio.h)
++** 04Apr02 Michael Hanrahan Added Interrupt Support
++*****************************************************************************/
++#ifndef _INC_CPMDIO
++#define _INC_CPMDIO
++
++
++#ifndef __CPHAL_CPMDIO
++typedef void PHY_DEVICE;
++#endif
++
++
++/*Version Information */
++
++void cpMacMdioGetVer(bit32u miiBase, bit32u *ModID, bit32u *RevMaj, bit32u *RevMin);
++
++/*Called once at the begining of time */
++
++int cpMacMdioInit(PHY_DEVICE *PhyDev, bit32u miibase, bit32u inst, bit32u PhyMask, bit32u MLinkMask, bit32u MdixMask, bit32u ResetBase, bit32u ResetBit, bit32u MdioBusFreq, bit32u MdioClockFreq, int verbose, void *Info);
++int cpMacMdioGetPhyDevSize(void);
++
++
++/*Called every 10 mili Seconds, returns TRUE if there has been a mode change */
++
++int cpMacMdioTic(PHY_DEVICE *PhyDev);
++
++/*Called to set Phy mode */
++
++void cpMacMdioSetPhyMode(PHY_DEVICE *PhyDev,bit32u PhyMode);
++
++/*Calls to retreive info after a mode change! */
++
++int cpMacMdioGetDuplex(PHY_DEVICE *PhyDev);
++int cpMacMdioGetSpeed(PHY_DEVICE *PhyDev);
++int cpMacMdioGetPhyNum(PHY_DEVICE *PhyDev);
++int cpMacMdioGetLinked(PHY_DEVICE *PhyDev);
++void cpMacMdioLinkChange(PHY_DEVICE *PhyDev);
++
++/* Shot Down */
++
++void cpMacMdioClose(PHY_DEVICE *PhyDev, int Full);
++
++
++/* Phy Mode Values */
++#define NWAY_AUTOMDIX (1<<16)
++#define NWAY_FD100 (1<<8)
++#define NWAY_HD100 (1<<7)
++#define NWAY_FD10 (1<<6)
++#define NWAY_HD10 (1<<5)
++#define NWAY_AUTO (1<<0)
++
++/*
++ *
++ * Tic() return values
++ *
++ */
++
++#define _MIIMDIO_MDIXFLIP (1<<28)
++
++#define _AUTOMDIX_DELAY_MIN 80 /* milli-seconds*/
++#define _AUTOMDIX_DELAY_MAX 200 /* milli-seconds*/
++
++#endif /* _INC_CPMDIO */
+diff -urN linux.old/drivers/net/avalanche_cpmac/cppi_cpmac.c linux.dev/drivers/net/avalanche_cpmac/cppi_cpmac.c
+--- linux.old/drivers/net/avalanche_cpmac/cppi_cpmac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cppi_cpmac.c 2005-07-12 02:48:42.048593000 +0200
+@@ -0,0 +1,1345 @@
++/*************************************************************************
++ * TNETDxxxx Software Support
++ * Copyright (c) 2002,2003 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ * FILE: cppi.c
++ *
++ * DESCRIPTION:
++ * This file contains shared code for all CPPI modules.
++ *
++ * HISTORY:
++ * 7Aug02 Greg RC1.00 Original Version created.
++ * 27Sep02 Mick RC1.01 Merged for use by CPMAC/CPSAR
++ * 16Oct02 Mick RC1.02 Performance Tweaks (see cppihist.txt)
++ * 12Nov02 Mick RC1.02 Updated to use cpmac_reg.h
++ * 09Jan03 Mick RC3.01 Removed modification to RxBuffer ptr
++ * 28Mar03 Mick 1.03 RxReturn now returns error if Malloc Fails
++ * 10Apr03 Mick 1.03.02 Added Needs Buffer Support
++ * 11Jun03 Mick 1.06.02 halSend() errors corrected
++ * 23Aug04 Mick 1.07.08 cpmac only - Send: bypass threshold check if TxInts re-enabled
++ *
++ * @author Greg Guyotte
++ * @version 1.00
++ * @date 7-Aug-2002
++ *****************************************************************************/
++/* each CPPI module must modify this file, the rest of the
++ code in cppi.c should be totally shared *//* Each CPPI module MUST properly define all constants shown below */
++
++/* CPPI registers */
++
++/* the following defines are not CPPI specific */
++
++static int TxInt(HAL_DEVICE *HalDev, int Ch, int Queue, int *MoreWork);
++
++static void FreeRx(HAL_DEVICE *HalDev, int Ch)
++ {
++ HAL_RCB *rcb_ptr; /*+GSG 030303*/
++ int rcbSize = (sizeof(HAL_RCB)+0xf)&~0xf; /*+GSG 030303*/
++ int Num = HalDev->ChData[Ch].RxNumBuffers, i; /*+GSG 030303*/
++
++ /* Free Rx data buffers attached to descriptors, if necessary */
++ if (HalDev->RcbStart[Ch] != 0) /*+GSG 030303*/
++ { /*+GSG 030303*/
++ for(i=0;i<Num;i++) /*+GSG 030303*/
++ { /*+GSG 030303*/
++ rcb_ptr = (HAL_RCB *)(HalDev->RcbStart[Ch] + (i*rcbSize)); /*+GSG 030303*/
++
++ /* free the data buffer */
++ if (rcb_ptr->DatPtr != 0)
++ {
++
++ HalDev->OsFunc->FreeRxBuffer((void *)rcb_ptr->OsInfo, (void *)rcb_ptr->DatPtr);
++ rcb_ptr->OsInfo=0; /*MJH+030522*/
++ rcb_ptr->DatPtr=0; /*MJH+030522*/
++ }
++ } /*+GSG 030303*/
++ } /*+GSG 030303*/
++
++ /* free up all desciptors at once */
++ HalDev->OsFunc->FreeDmaXfer(HalDev->RcbStart[Ch]);
++
++ /* mark buffers as freed */
++ HalDev->RcbStart[Ch] = 0;
++ }
++
++static void FreeTx(HAL_DEVICE *HalDev, int Ch, int Queue)
++ {
++
++/*+GSG 030303*/
++
++ /* free all descriptors at once */
++ HalDev->OsFunc->FreeDmaXfer(HalDev->TcbStart[Ch][Queue]);
++
++ HalDev->TcbStart[Ch][Queue] = 0;
++ }
++
++/* return of 0 means that this code executed, -1 means the interrupt was not
++ a teardown interrupt */
++static int RxTeardownInt(HAL_DEVICE *HalDev, int Ch)
++ {
++ bit32u base = HalDev->dev_base;
++
++ /* check to see if the interrupt is a teardown interrupt */
++ if (((CPMAC_RX_INT_ACK( base , Ch )) & TEARDOWN_VAL) == TEARDOWN_VAL)
++ {
++ /* finish channel teardown */
++
++ /* Free channel resources on a FULL teardown */
++ if (HalDev->RxTeardownPending[Ch] & FULL_TEARDOWN)
++ {
++ FreeRx(HalDev, Ch);
++ }
++
++ /* bug fix - clear Rx channel pointers on teardown */
++ HalDev->RcbPool[Ch] = 0;
++ HalDev->RxActQueueHead[Ch] = 0;
++ HalDev->RxActQueueCount[Ch] = 0;
++ HalDev->RxActive[Ch] = FALSE;
++
++ /* write completion pointer */
++ (CPMAC_RX_INT_ACK( base , Ch )) = TEARDOWN_VAL;
++
++ /* use direction bit as a teardown pending bit! May be able to
++ use only one teardown pending integer in HalDev */
++
++ HalDev->RxTeardownPending[Ch] &= ~RX_TEARDOWN;
++
++ HalDev->ChIsOpen[Ch][DIRECTION_RX] = 0;
++
++ HalDev->ChIsOpen[Ch][DIRECTION_RX] = 0;
++ CPMAC_RX_INTMASK_CLEAR(HalDev->dev_base) = (1<<Ch);
++ if ((HalDev->RxTeardownPending[Ch] & BLOCKING_TEARDOWN) == 0)
++ {
++
++ HalDev->OsFunc->TeardownComplete(HalDev->OsDev, Ch, DIRECTION_RX);
++ }
++ HalDev->RxTeardownPending[Ch] = 0;
++
++ return (EC_NO_ERRORS);
++ }
++ return (-1);
++ }
++
++/* return of 0 means that this code executed, -1 means the interrupt was not
++ a teardown interrupt. Note: this code is always called with Queue == 0 (hi priority). */
++static int TxTeardownInt(HAL_DEVICE *HalDev, int Ch, int Queue)
++ {
++ bit32u base = HalDev->dev_base;
++ HAL_TCB *Last, *Curr, *First; /*+GSG 030303*/
++ int i;
++
++ if (((CPMAC_TX_INT_ACK( base , Ch )) & TEARDOWN_VAL) == TEARDOWN_VAL)
++ {
++ /* perform all actions for both queues (+GSG 040212) */
++ for (i=0; i<HalDev->ChData[Ch].TxNumQueues; i++)
++ {
++ /* return outstanding buffers to OS +RC3.02*/
++ Curr = HalDev->TxActQueueHead[Ch][i]; /*+GSG 030303*/
++ First = Curr; /*+GSG 030303*/
++ while (Curr) /*+GSG 030303*/
++ { /*+GSG 030303*/
++ /* Pop TCB(s) for packet from the stack */ /*+GSG 030303*/
++ Last = Curr->Eop; /*+GSG 030303*/
++ HalDev->TxActQueueHead[Ch][i] = Last->Next; /*+GSG 030303*/
++ /*+GSG 030303*/
++ /* return to OS */ /*+GSG 030303*/
++ HalDev->OsFunc->SendComplete(Curr->OsInfo); /*+GSG 030303*/
++ /*+GSG 030303*/
++ /* Push Tcb(s) back onto the stack */ /*+GSG 030303*/
++ Curr = Last->Next; /*+GSG 030303*/
++ Last->Next = HalDev->TcbPool[Ch][i]; /*+GSG 030303*/
++ HalDev->TcbPool[Ch][i] = First; /*+GSG 030303*/
++ /*+GSG 030303*/
++ /* set the first(SOP) pointer for the next packet */ /*+GSG 030303*/
++ First = Curr; /*+GSG 030303*/
++ } /*+GSG 030303*/
++ }
++
++ /* finish channel teardown */
++
++ if (HalDev->TxTeardownPending[Ch] & FULL_TEARDOWN)
++ {
++ FreeTx(HalDev, Ch, 0);
++
++ if (HalDev->ChData[Ch].TxNumQueues == 2)
++ FreeTx(HalDev, Ch, 1);
++ } /* if FULL teardown */
++
++ /* perform all actions for both queues (+GSG 040212) */
++ for (i=0; i<HalDev->ChData[Ch].TxNumQueues; i++)
++ {
++ /* bug fix - clear Tx channel pointers on teardown */
++ HalDev->TcbPool[Ch][i] = 0;
++ HalDev->TxActQueueHead[Ch][i] = 0;
++ HalDev->TxActQueueCount[Ch][i] = 0;
++ HalDev->TxActive[Ch][i] = FALSE;
++ }
++
++ /* write completion pointer, only needed for the high priority queue */
++ (CPMAC_TX_INT_ACK( base , Ch )) = TEARDOWN_VAL;
++
++ /* no longer pending teardown */
++ HalDev->TxTeardownPending[Ch] &= ~TX_TEARDOWN;
++
++ HalDev->ChIsOpen[Ch][DIRECTION_TX] = 0;
++
++ HalDev->ChIsOpen[Ch][DIRECTION_TX] = 0;
++ CPMAC_TX_INTMASK_CLEAR(HalDev->dev_base) = (1<<Ch);
++ if ((HalDev->TxTeardownPending[Ch] & BLOCKING_TEARDOWN) == 0)
++ {
++
++ HalDev->OsFunc->TeardownComplete(HalDev->OsDev, Ch, DIRECTION_TX);
++ }
++ HalDev->TxTeardownPending[Ch] = 0;
++
++ return (EC_NO_ERRORS);
++ }
++ return (-1);
++ }
++
++/* +GSG 030421 */
++static void AddToRxQueue(HAL_DEVICE *HalDev, HAL_RCB *FirstRcb, HAL_RCB *LastRcb, int FragCount, int Ch)
++ {
++ if (HalDev->RxActQueueHead[Ch]==0)
++ {
++
++ HalDev->RxActQueueHead[Ch]=FirstRcb;
++ HalDev->RxActQueueTail[Ch]=LastRcb;
++ if (!HalDev->RxActive[Ch])
++ {
++ /* write Rx Queue Head Descriptor Pointer */
++ ((CPMAC_RX_HDP( HalDev->dev_base , Ch )) ) = VirtToPhys(FirstRcb) - HalDev->offset;
++ HalDev->RxActive[Ch]=TRUE;
++ }
++ }
++ else
++ {
++ register HAL_RCB *OldTailRcb;
++ register bit32u rmode;
++
++ HalDev->OsFunc->CriticalOn();
++ OldTailRcb=HalDev->RxActQueueTail[Ch];
++ OldTailRcb->Next=(void *)FirstRcb;
++ OldTailRcb=VirtToVirtNoCache(OldTailRcb);
++ OldTailRcb->HNext=VirtToPhys(FirstRcb) - HalDev->offset;
++ HalDev->RxActQueueTail[Ch]=LastRcb;
++ rmode=OldTailRcb->mode;
++ if (rmode&CB_EOQ_BIT)
++ {
++ rmode&=~CB_EOQ_BIT;
++ ((CPMAC_RX_HDP( HalDev->dev_base , Ch )) ) = VirtToPhys(FirstRcb) - HalDev->offset;
++ OldTailRcb->mode=rmode;
++ }
++ HalDev->OsFunc->CriticalOff();
++ }
++ }
++
++/**
++ * @ingroup CPHAL_Functions
++ * This function is called to indicate to the CPHAL that the upper layer
++ * software has finished processing the receive data (given to it by
++ * osReceive()). The CPHAL will then return the appropriate receive buffers
++ * and buffer descriptors to the available pool.
++ *
++ * @param HalReceiveInfo Start of receive buffer descriptor chain returned to
++ * CPHAL.
++ * @param StripFlag Flag indicating whether the upper layer software has
++ * retained ownership of the receive data buffers.
++ *<BR>
++ * 'FALSE' means that the CPHAL can reuse the receive data buffers.
++ *<BR>
++ * 'TRUE' : indicates the data buffers were retained by the OS
++ *<BR>
++ * NOTE: If StripFlag is TRUE, it is the responsibility of the upper layer software to free the buffers when they are no longer needed.
++ *
++ * @return EC_NO_ERRORS (ok). <BR>
++ * Possible Error Codes:<BR>
++ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ * @ref EC_VAL_RCB_NEEDS_BUFFER "EC_VAL_RCB_NEEDS_BUFFER"<BR>
++ * @ref EC_VAL_RCB_DROPPED "EC_VAL_RCB_DROPPED"<BR>
++ */
++static int halRxReturn(HAL_RECEIVEINFO *HalReceiveInfo,
++ int StripFlag)
++ {
++ int Ch, i;
++ HAL_RCB *LastRcb;
++ HAL_DEVICE *HalDev;
++ int RcbSize;
++ int FragCount;
++
++ Ch = HalReceiveInfo->mode&0x0ff;
++ HalDev = (HAL_DEVICE *)HalReceiveInfo->Off_BLen;
++ FragCount = HalReceiveInfo->mode>>8;
++
++ if (HalDev->State != enOpened)
++ return(EC_CPMAC |EC_FUNC_RXRETURN|EC_VAL_INVALID_STATE);
++
++ LastRcb=(HAL_RCB *)HalReceiveInfo->Eop;
++ LastRcb->HNext=0;
++ LastRcb->Next=0;
++ RcbSize = HalDev->ChData[Ch].RxBufSize;
++
++ if (FragCount>1)
++ {
++ LastRcb->Off_BLen=RcbSize;
++ LastRcb->mode=CB_OWNERSHIP_BIT;
++ }
++
++ HalReceiveInfo->Off_BLen=RcbSize;
++ HalReceiveInfo->mode=CB_OWNERSHIP_BIT;
++
++ /* If OS has kept the buffers for this packet, attempt to alloc new buffers */
++ if (StripFlag)
++ {
++ int rc=0; /*MJH+030417*/
++ int GoodCount=0; /*GSG+030421*/
++ HAL_RCB *TempRcb;
++ char *pBuf;
++ HAL_RCB *CurrHeadRcb = HalReceiveInfo, *LastGoodRcb=0; /* +GSG 030421 */
++
++ TempRcb = HalReceiveInfo;
++ for (i=0; i<FragCount; i++)
++ {
++ if (TempRcb == 0)
++ {
++ dbgPrintf("Rx Return error while allocating new buffers\n");
++ dbgPrintf("Rcb = %08x, Rcb->Eop = %08x, FragCount = %d:%d\n",
++ (bit32u)HalReceiveInfo, (bit32u)HalReceiveInfo->Eop, FragCount,i);
++ osfuncSioFlush();
++
++ return(EC_CPPI|EC_FUNC_RXRETURN|EC_VAL_CORRUPT_RCB_CHAIN);
++ }
++
++ pBuf= (char *) HalDev->OsFunc->MallocRxBuffer(RcbSize,0,
++ 0xF,HalDev->ChData[Ch].OsSetup,
++ (void *)TempRcb,
++ (void *)&TempRcb->OsInfo,
++ (void *) HalDev->OsDev);
++ if (!pBuf)
++ {
++ /* malloc failed, add this RCB to Needs Buffer List */
++ (HAL_RCB *)TempRcb->Eop = TempRcb; /* GSG +030430 */
++ TempRcb->mode=1<<8|Ch;
++ TempRcb->Off_BLen=(bit32u)HalDev;
++
++ if(HalDev->NeedsCount < MAX_NEEDS) /* +MJH 030410 */
++ { /* +MJH 030410 */
++ HalDev->Needs[HalDev->NeedsCount] = (HAL_RECEIVEINFO *) TempRcb; /* +MJH 030410 */
++ HalDev->NeedsCount++; /* +MJH 030410 */
++ rc = (EC_CPPI|EC_FUNC_RXRETURN|EC_VAL_RCB_NEEDS_BUFFER); /* ~MJH 030417 */
++ } /* +MJH 030410 */
++ else /* +MJH 030410 */
++ rc = (EC_CPPI|EC_FUNC_RXRETURN|EC_VAL_RCB_DROPPED); /* ~MJH 030417 */
++
++ /* requeue any previous RCB's that were ready to go before this one */
++ if (GoodCount > 0) /* +GSG 030421 */
++ { /* +GSG 030421 */
++ LastGoodRcb->HNext=0; /* +GSG 030430 */
++ LastGoodRcb->Next=0; /* +GSG 030430 */
++ osfuncDataCacheHitWritebackAndInvalidate((void *)LastGoodRcb, 16); /* +GSG 030430 */
++
++ AddToRxQueue(HalDev, CurrHeadRcb, LastGoodRcb, GoodCount, Ch); /* +GSG 030421 */
++ GoodCount = 0; /* +GSG 030421 */
++ } /* +GSG 030421 */
++
++ CurrHeadRcb = TempRcb->Next; /* +GSG 030421 */
++ }
++ else /* +GSG 030421 */
++ { /* +GSG 030421 */
++ /* malloc succeeded, requeue the RCB to the hardware */
++ TempRcb->BufPtr=VirtToPhys(pBuf) - HalDev->offset;
++ TempRcb->DatPtr=pBuf;
++ /* Emerald fix 10/29 */
++ osfuncDataCacheHitWritebackAndInvalidate((void *)TempRcb, 16);
++
++ /* i store the last good RCB in case the malloc fails for the
++ next fragment. This ensures that I can go ahead and return
++ a partial chain of RCB's to the hardware */
++ LastGoodRcb = TempRcb; /* +GSG 030421 */
++ GoodCount++; /* +GSG 030421 */
++ } /* +GSG 030421 */
++ TempRcb = TempRcb->Next;
++ } /* end of Frag loop */
++ /* if there any good RCB's to requeue, do so here */
++ if (GoodCount > 0) /* +GSG 030421 */
++ {
++ AddToRxQueue(HalDev, CurrHeadRcb, LastGoodRcb, GoodCount, Ch); /* +GSG 030421 */
++ }
++ return(rc); /* ~GSG 030421 */
++ }
++ else
++ {
++ /* Not Stripping */
++ /* Emerald */
++ /* Write Back SOP and last RCB */
++ osfuncDataCacheHitWritebackAndInvalidate((void *)HalReceiveInfo, 16);
++
++ if (FragCount > 1)
++ {
++ osfuncDataCacheHitWritebackAndInvalidate((void *)LastRcb, 16);
++ }
++ /* if not stripping buffers, always add to queue */
++ AddToRxQueue(HalDev, HalReceiveInfo, LastRcb, FragCount, Ch); /*MJH~030520*/
++ }
++
++ return(EC_NO_ERRORS);
++ }
++
++/* +MJH 030410
++ Trys to liberate an RCB until liberation fails.
++ Note: If liberation fails then RxReturn will re-add the RCB to the
++ Needs list.
++*/
++static void NeedsCheck(HAL_DEVICE *HalDev)
++{
++ HAL_RECEIVEINFO* HalRcb;
++ int rc;
++ HalDev->OsFunc->CriticalOn();
++ while(HalDev->NeedsCount)
++ {
++ HalDev->NeedsCount--;
++ HalRcb = HalDev->Needs[HalDev->NeedsCount];
++ rc = halRxReturn(HalRcb, 1);
++ /* short circuit if RxReturn starts to fail */
++ if (rc != 0)
++ break;
++ }
++ HalDev->OsFunc->CriticalOff();
++}
++
++/*
++ * This function allocates transmit buffer descriptors (internal CPHAL function).
++ * It creates a high priority transmit queue by default for a single Tx
++ * channel. If QoS is enabled for the given CPHAL device, this function
++ * will also allocate a low priority transmit queue.
++ *
++ * @param HalDev CPHAL module instance. (set by cphalInitModule())
++ * @param Ch Channel number.
++ *
++ * @return 0 OK, Non-Zero Not OK
++ */
++static int InitTcb(HAL_DEVICE *HalDev, int Ch)
++ {
++ int i, Num = HalDev->ChData[Ch].TxNumBuffers;
++ HAL_TCB *pTcb=0;
++ char *AllTcb;
++ int tcbSize, Queue;
++ int SizeMalloc;
++
++ tcbSize = (sizeof(HAL_TCB)+0xf)&~0xf;
++ SizeMalloc = (tcbSize*Num)+0xf;
++
++ for (Queue=0; Queue < HalDev->ChData[Ch].TxNumQueues; Queue++)
++ {
++ if (HalDev->TcbStart[Ch][Queue] == 0)
++ {
++
++ /* malloc all TCBs at once */
++ AllTcb = (char *)HalDev->OsFunc->MallocDmaXfer(SizeMalloc,0,0xffffffff);
++ if (!AllTcb)
++ {
++ return(EC_CPPI|EC_FUNC_HAL_INIT|EC_VAL_TCB_MALLOC_FAILED);
++ }
++
++ HalDev->OsFunc->Memset(AllTcb, 0, SizeMalloc);
++
++ /* keep this address for freeing later */
++ HalDev->TcbStart[Ch][Queue] = AllTcb;
++ }
++ else
++ {
++ /* if the memory has already been allocated, simply reuse it! */
++ AllTcb = HalDev->TcbStart[Ch][Queue];
++ }
++
++ /* align to cache line */
++ AllTcb = (char *)(((bit32u)AllTcb + 0xf) &~ 0xf); /*PITS #143 MJH~030522*/
++
++ /* default High priority transmit queue */
++ HalDev->TcbPool[Ch][Queue]=0;
++ for(i=0;i<Num;i++)
++ {
++ /*pTcb=(HAL_TCB *) OsFunc->MallocDmaXfer(sizeof(HAL_TCB),0,0xffffffff); */
++ pTcb= (HAL_TCB *)(AllTcb + (i*tcbSize));
++ pTcb->mode=0;
++ pTcb->BufPtr=0;
++ pTcb->Next=HalDev->TcbPool[Ch][Queue];
++ pTcb->Off_BLen=0;
++ HalDev->TcbPool[Ch][Queue]=pTcb;
++ }
++ /*HalDev->TcbEnd = pTcb;*/
++ }
++
++ return(EC_NO_ERRORS);
++ }
++
++/*
++ * This function allocates receive buffer descriptors (internal CPHAL function).
++ * After allocation, the function 'queues' (gives to the hardware) the newly
++ * created receive buffers to enable packet reception.
++ *
++ * @param HalDev CPHAL module instance. (set by cphalInitModule())
++ * @param Ch Channel number.
++ *
++ * @return 0 OK, Non-Zero Not OK
++ */
++static int InitRcb(HAL_DEVICE *HalDev, int Ch)
++ {
++ int i, Num = HalDev->ChData[Ch].RxNumBuffers;
++ int Size = HalDev->ChData[Ch].RxBufSize;
++ HAL_RCB *pRcb;
++ char *pBuf;
++ char *AllRcb;
++ int rcbSize;
++ int DoMalloc = 0;
++ int SizeMalloc;
++ int MallocSize;
++
++ rcbSize = (sizeof(HAL_RCB)+0xf)&~0xf;
++ SizeMalloc = (rcbSize*Num)+0xf;
++
++ if (HalDev->RcbStart[Ch] == 0)
++ {
++ DoMalloc = 1;
++
++ /* malloc all RCBs at once */
++ AllRcb= (char *)HalDev->OsFunc->MallocDmaXfer(SizeMalloc,0,0xffffffff);
++ if (!AllRcb)
++ {
++ return(EC_CPPI|EC_FUNC_HAL_INIT|EC_VAL_RCB_MALLOC_FAILED);
++ }
++
++ HalDev->OsFunc->Memset(AllRcb, 0, SizeMalloc);
++
++ /* keep this address for freeing later */
++ HalDev->RcbStart[Ch] = AllRcb;
++ }
++ else
++ {
++ /* if the memory has already been allocated, simply reuse it! */
++ AllRcb = HalDev->RcbStart[Ch];
++ }
++
++ /* align to cache line */
++ AllRcb = (char *)(((bit32u)AllRcb + 0xf)&~0xf); /*PITS #143 MJH~030522*/
++
++ HalDev->RcbPool[Ch]=0;
++ for(i=0;i<Num;i++)
++ {
++ pRcb = (HAL_RCB *)(AllRcb + (i*rcbSize));
++
++ if (DoMalloc == 1)
++ {
++
++ MallocSize = Size; /*~3.01 */
++ pBuf= (char *) HalDev->OsFunc->MallocRxBuffer(MallocSize,0,0xF,HalDev->ChData[Ch].OsSetup, (void *)pRcb, (void *)&pRcb->OsInfo, (void *) HalDev->OsDev);
++ if(!pBuf)
++ {
++ return(EC_CPPI|EC_FUNC_HAL_INIT|EC_VAL_RX_BUFFER_MALLOC_FAILED);
++ }
++ /* -RC3.01 pBuf = (char *)(((bit32u)pBuf+0xF) & ~0xF); */
++ pRcb->BufPtr=VirtToPhys(pBuf) - HalDev->offset;
++ pRcb->DatPtr=pBuf;
++ }
++ pRcb->mode=(1<<8)|Ch; /* One Frag for Ch */
++ pRcb->Next=(void *)HalDev->RcbPool[Ch];
++ pRcb->Off_BLen=(bit32u)HalDev;
++ HalDev->RcbPool[Ch]=pRcb;
++ }
++
++ /* Give all of the Rx buffers to hardware */
++
++ while(HalDev->RcbPool[Ch])
++ {
++ pRcb=HalDev->RcbPool[Ch];
++ HalDev->RcbPool[Ch]=pRcb->Next;
++ pRcb->Eop=(void*)pRcb;
++ pRcb->mode=(1<<8)|Ch;
++ halRxReturn((HAL_RECEIVEINFO *)pRcb, 0);
++ }
++
++ return(EC_NO_ERRORS);
++ }
++
++/**
++ * @ingroup CPHAL_Functions
++ * This function transmits the data in FragList using available transmit
++ * buffer descriptors. More information on the use of the Mode parameter
++ * is available in the module-specific appendices. Note: The OS should
++ * not call Send() for a channel that has been requested to be torndown.
++ *
++ * @param HalDev CPHAL module instance. (set by cphalInitModule())
++ * @param FragList Fragment List structure.
++ * @param FragCount Number of fragments in FragList.
++ * @param PacketSize Number of bytes to transmit.
++ * @param OsSendInfo OS Send Information structure. <BR>
++ * @param Mode 32-bit value with the following bit fields: <BR>
++ * 31-16: Mode (used for module specific data). <BR>
++ * 15-08: Queue (transmit queue to send on). <BR>
++ * 07-00: Channel (channel number to send on).
++ *
++ * @return EC_NO_ERRORS (ok). <BR>
++ * Possible Error Codes:<BR>
++ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ * @ref EC_VAL_NOT_LINKED "EC_VAL_NOT_LINKED"<BR>
++ * @ref EC_VAL_INVALID_CH "EC_VAL_INVALID_CH"<BR>
++ * @ref EC_VAL_OUT_OF_TCBS "EC_VAL_OUT_OF_TCBS"<BR>
++ * @ref EC_VAL_NO_TCBS "EC_VAL_NO_TCBS"<BR>
++ */
++static int halSend(HAL_DEVICE *HalDev,FRAGLIST *FragList,
++ int FragCount,int PacketSize, OS_SENDINFO *OsSendInfo,
++ bit32u Mode)
++ {
++ HAL_TCB *tcb_ptr, *head;
++ int i;
++ int rc = EC_NO_ERRORS;
++ int Ch = Mode & 0xFF;
++ int Queue = (Mode>>8)&0xFF;
++ /*int DoThresholdCheck=1; */ /* Used when TxIntDisable is set and TxInts are re-enabled */
++
++ if (HalDev->State != enOpened)
++ return(EC_CPPI|EC_FUNC_SEND|EC_VAL_INVALID_STATE);
++
++ if (!HalDev->Linked)
++ {
++ rc = EC_CPPI|EC_FUNC_SEND|EC_VAL_NOT_LINKED;
++ return(rc);
++ }
++
++ if (HalDev->ChIsOpen[Ch][DIRECTION_TX] == 0) /*MJH~030611*/ /*PITS 148*/
++ return(EC_CPMAC |EC_FUNC_SEND|EC_VAL_INVALID_CH); /*+GSG 030303*/
++
++ HalDev->OsFunc->CriticalOn();
++
++ /* Setup Tx mode and size */
++ if (PacketSize<60)
++ {
++ FragList[FragCount-1].len += (60 - PacketSize); /*MJH~030506*//*PITS 132*/
++ PacketSize = 60; /*MJH~030506*/
++ }
++ Mode &= CB_PASSCRC_BIT;
++
++ tcb_ptr = head = HalDev->TcbPool[Ch][Queue];
++
++ if (tcb_ptr)
++ {
++
++ Mode|=PacketSize|CB_SOF_BIT|CB_OWNERSHIP_BIT;
++
++ for (i=0; i<FragCount; i++)
++
++ {
++ /* Setup Tx mode and size */
++ tcb_ptr->Off_BLen = FragList[i].len;
++
++ tcb_ptr->mode = Mode;
++ tcb_ptr->BufPtr = VirtToPhys((bit32 *)FragList[i].data) - HalDev->offset;
++ tcb_ptr->OsInfo = OsSendInfo;
++
++ if (i == (FragCount - 1))
++ {
++ /* last fragment */
++ tcb_ptr->mode |= CB_EOF_BIT;
++
++ /* since this is the last fragment, set the TcbPool pointer before
++ nulling out the Next pointers */
++
++ HalDev->TcbPool[Ch][Queue] = tcb_ptr->Next;
++
++ tcb_ptr->Next = 0;
++ tcb_ptr->HNext = 0;
++
++ /* In the Tx Interrupt handler, we will need to know which TCB is EOP,
++ so we can save that information in the SOP */
++ head->Eop = tcb_ptr;
++
++ /* Emerald fix 10/29 */
++ osfuncDataCacheHitWritebackAndInvalidate((void *)tcb_ptr, 16);
++
++ }
++ else
++ {
++ Mode=CB_OWNERSHIP_BIT;
++ tcb_ptr->HNext = VirtToPhys((bit32 *)tcb_ptr->Next) - HalDev->offset;
++
++ /* Emerald fix 10/29 */
++ osfuncDataCacheHitWritebackAndInvalidate((void *)tcb_ptr, 16);
++
++ tcb_ptr = tcb_ptr->Next; /* what about the end of TCB list?? */
++
++ if (tcb_ptr == 0)
++ {
++ rc = EC_CPPI|EC_FUNC_SEND|EC_VAL_OUT_OF_TCBS;
++ goto ExitSend;
++ }
++ }
++ } /* for */
++
++ /* put it on the high priority queue */
++ if (HalDev->TxActQueueHead[Ch][Queue] == 0)
++ {
++ HalDev->TxActQueueHead[Ch][Queue]=head;
++ HalDev->TxActQueueTail[Ch][Queue]=tcb_ptr;
++/*+GSG 030303*//*+GSG 030303*/
++ if (!HalDev->TxActive[Ch][Queue])
++ {
++
++ bit32u base = HalDev->dev_base;
++
++ /* write CPPI TX HDP */
++ (CPMAC_TX_HDP( base , Ch )) = VirtToPhys(head) - HalDev->offset;
++ HalDev->TxActive[Ch][Queue]=TRUE;
++
++ }
++ }
++ else
++ {
++ register volatile HAL_TCB *pTailTcb;
++ register bit32u tmode;
++ register bit32u pCurrentTcb;
++
++ HalDev->TxActQueueTail[Ch][Queue]->Next=head;
++ /* Emerald fix 10/29 */
++
++ pTailTcb=(HAL_TCB *)VirtToVirtNoCache(&HalDev->TxActQueueTail[Ch][Queue]->HNext);
++ pCurrentTcb=VirtToPhys(head) - HalDev->offset;
++ pTailTcb->HNext=pCurrentTcb;
++ HalDev->TxActQueueTail[Ch][Queue]=tcb_ptr;
++/*+GSG 030303*/
++ tmode=pTailTcb->mode;
++ if (tmode&CB_EOQ_BIT)
++ {
++ bit32u base = HalDev->dev_base;
++
++ tmode&=~CB_EOQ_BIT;
++ pTailTcb->mode=tmode;
++ ((CPMAC_TX_HDP( base , Ch )) ) = pCurrentTcb;
++ }
++
++ else
++ {
++ if(HalDev->TxIntDisable)
++ {
++ /* Enable Interrupts, to ensure packet goes out on wire */
++ CPMAC_TX_INTMASK_SET(HalDev->dev_base) = (1<<Ch);
++ halPacketProcessEnd(HalDev); /* Allow Interrupt to be seen at the OS */
++ /*DoThresholdCheck = 0; */ /* Disable Threshold Check */
++
++ }
++ }
++
++ }
++ rc = EC_NO_ERRORS;
++ goto ExitSend;
++ } /* if (tcb_ptr) */
++ else
++ {
++ rc = EC_CPPI|EC_FUNC_SEND|EC_VAL_NO_TCBS;
++ goto ExitSend;
++ }
++ExitSend:
++
++/* 15 June 2004 - NSP Performance Update : If Tx Ints are disabled then process them here */
++/* 29 June 2004 - NSP Performance Update : Moved to end at request of BCIL */
++/* 23 Aug 2004 - NSP Performance Update : If Tx Ints are re-enabled do not do Threshold check */
++
++ if(HalDev->TxIntDisable /*&& DoThresholdCheck*/)
++ {
++ if(--HalDev->TxIntThreshold[Ch] <= 0)
++ {
++ int MoreWork;
++ TxInt(HalDev, Ch, 0, &MoreWork);
++ HalDev->TxIntThreshold[Ch] = HalDev->TxIntThresholdMaster[Ch];
++ }
++ }
++ HalDev->OsFunc->CriticalOff();
++
++ return(rc);
++ }
++
++/*
++ * This function processes receive interrupts. It traverses the receive
++ * buffer queue, extracting the data and passing it to the upper layer software via
++ * osReceive(). It handles all error conditions and fragments without valid data by
++ * immediately returning the RCB's to the RCB pool.
++ *
++ * @param HalDev CPHAL module instance. (set by cphalInitModule())
++ * @param Ch Channel Number.
++ * @param MoreWork Flag that indicates that there is more work to do when set to 1.
++ *
++ * @return 0 if OK, non-zero otherwise.
++ */
++static int RxInt(HAL_DEVICE *HalDev, int Ch, int *MoreWork)
++ {
++ HAL_RCB *CurrentRcb, *SopRcb, *EofRcb, *EopRcb;
++ bit32u RxBufStatus,PacketsServiced, RxPktLen = 0, RxSopStatus,
++ FrmFrags, TotalFrags, FrmLen;
++ int base = HalDev->dev_base, Ret;
++ OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++ int RxServiceMax = HalDev->ChData[Ch].RxServiceMax;
++ int FragIndex; /* +GSG 030508 */
++
++ if(HalDev->NeedsCount) /* +MJH 030410 */
++ NeedsCheck(HalDev); /* +MJH 030410 */
++
++ /* Handle case of teardown interrupt */
++ if (HalDev->RxTeardownPending[Ch] != 0)
++ {
++ Ret = RxTeardownInt(HalDev, Ch);
++ if (Ret == 0)
++ { /*+GSG 030303*/
++ *MoreWork = 0;
++ return (EC_NO_ERRORS);
++ } /*+GSG 030303*/
++ }
++
++ /* Examine first RCB on the software active queue */
++ CurrentRcb=HalDev->RxActQueueHead[Ch];
++ osfuncDataCacheHitInvalidate((void*)CurrentRcb, 16);
++ RxBufStatus=CurrentRcb->mode;
++ PacketsServiced=0;
++
++ /* Process received packets until we find hardware owned descriptors
++ or until we hit RxServiceMax */
++ while((CurrentRcb)&&((RxBufStatus&CB_OWNERSHIP_BIT)==0)&&
++ (PacketsServiced<RxServiceMax)) /* ~GSG 030307 */
++ {
++
++ PacketsServiced++; /* ~GSG 030307 */
++ SopRcb=CurrentRcb;
++ RxSopStatus=RxBufStatus;
++ RxPktLen = RxSopStatus&CB_SIZE_MASK;
++
++ FrmFrags=0;
++ TotalFrags=0;
++ FragIndex=0;
++ FrmLen=0;
++ EofRcb=0;
++
++/* +GSG 030508 *//* +GSG 030508 */
++
++ /* Loop through all fragments that comprise current packet. Build
++ fraglist and exit when the end of the packet is reached, or the
++ end of the descriptor list is reached. */
++ do
++ {
++ bit32u DmaLen;
++
++
++ DmaLen=CurrentRcb->Off_BLen;
++
++ FrmLen+=DmaLen;
++ TotalFrags++;
++ if (!EofRcb)
++ {
++ HalDev->fraglist[FragIndex].data=((char *)CurrentRcb->DatPtr); /* ~GSG 030508 */
++
++ HalDev->fraglist[FragIndex].len=DmaLen; /* ~GSG 030508 */
++
++ /* GSG 12/9 */
++ HalDev->fraglist[FragIndex].OsInfo = CurrentRcb->OsInfo; /* ~GSG 030508 */
++
++ /* Upper layer must do the data invalidate */
++
++ FrmFrags++;
++ FragIndex++; /* ~GSG 030508 */
++ if (FrmLen>=RxPktLen)
++ EofRcb=CurrentRcb;
++ }
++ EopRcb=CurrentRcb;
++ CurrentRcb=EopRcb->Next;
++ if (CurrentRcb)
++ {
++ osfuncDataCacheHitInvalidate((void*)CurrentRcb,16);
++ }
++ }while(((EopRcb->mode&CB_EOF_BIT)==0)&&(CurrentRcb));
++
++ /* Write the completion pointer for interrupt acknowledgement*/
++ (CPMAC_RX_INT_ACK( base , Ch )) = VirtToPhys(EopRcb) - HalDev->offset;
++
++ EopRcb->Next=0;
++
++ if (CurrentRcb == 0)
++ {
++ /* If we are out of RCB's we must not send this packet
++ to the OS. */
++ int RcbSize = HalDev->ChData[Ch].RxBufSize;
++
++ if (TotalFrags>1)
++ {
++ EopRcb->Off_BLen=RcbSize;
++ EopRcb->mode=CB_OWNERSHIP_BIT;
++ osfuncDataCacheHitWritebackAndInvalidate((void *)EopRcb, 16);
++ }
++
++ SopRcb->Off_BLen=RcbSize;
++ SopRcb->mode=CB_OWNERSHIP_BIT;
++ osfuncDataCacheHitWritebackAndInvalidate((void *)SopRcb, 16);
++
++ ((CPMAC_RX_HDP( base , Ch )) ) = VirtToPhys(SopRcb);
++ }
++ else
++ {
++ /* Dequeue packet and send to OS */
++ int mode;
++
++ /* setup SopRcb for the packet */
++ SopRcb->Eop=(void*)EopRcb;
++
++ /* dequeue packet */
++ HalDev->RxActQueueHead[Ch]=CurrentRcb;
++
++ if (EopRcb->mode&CB_EOQ_BIT)
++ {
++ /* Next pointer is non-null and EOQ bit is set, which
++ indicates misqueue packet in CPPI protocol. */
++
++ ((CPMAC_RX_HDP( base , Ch )) ) = EopRcb->HNext;
++ }
++
++ mode = (SopRcb->mode & 0xFFFF0000) | Ch;
++
++ SopRcb->mode=(FrmFrags<<8)|Ch;
++ SopRcb->Off_BLen=(bit32u)HalDev;
++
++ /* send packet up the higher layer driver */
++ OsFunc->Receive(HalDev->OsDev,HalDev->fraglist,FragIndex,RxPktLen, /* ~GSG 030508 */
++ (HAL_RECEIVEINFO *)SopRcb,mode);
++
++ RxBufStatus=CurrentRcb->mode;
++ }
++ } /* while loop */
++
++ if ((CurrentRcb)&&((RxBufStatus&CB_OWNERSHIP_BIT)==0)) /*~GSG 030307*/
++ {
++ *MoreWork = 1;
++ }
++ else
++ {
++ *MoreWork = 0;
++ }
++
++ return (EC_NO_ERRORS);
++}
++
++/*
++ * This function processes transmit interrupts. It traverses the
++ * transmit buffer queue, detecting sent data buffers and notifying the upper
++ * layer software via osSendComplete(). (for SAR, i originally had this split
++ * into two functions, one for each queue, but joined them on 8/8/02)
++ *
++ * @param HalDev CPHAL module instance. (set by cphalInitModule())
++ * @param Queue Queue number to service (always 0 for MAC, Choose 1 for SAR to service low priority queue)
++ * @param MoreWork Flag that indicates that there is more work to do when set to 1.
++ *
++ * @return 0 if OK, non-zero otherwise.
++ */
++int TxInt(HAL_DEVICE *HalDev, int Ch, int Queue, int *MoreWork)
++ {
++ HAL_TCB *CurrentTcb,*LastTcbProcessed,*FirstTcbProcessed;
++ int PacketsServiced;
++ bit32u TxFrameStatus;
++ int base;
++ int TxServiceMax = HalDev->ChData[Ch].TxServiceMax;
++ OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++
++/*+GSG 030303*//*+GSG 030303*/
++
++ /* load the module base address */
++ base = HalDev->dev_base;
++
++ /* Handle case of teardown interrupt. This must be checked at
++ the top of the function rather than the bottom, because
++ the normal data processing can wipe out the completion
++ pointer which is used to determine teardown complete. */
++ if (HalDev->TxTeardownPending[Ch] != 0)
++ {
++ int Ret;
++
++ Ret = TxTeardownInt(HalDev, Ch, Queue);
++ if (Ret == 0)
++ { /*+GSG 030303*/
++ *MoreWork = 0; /* bug fix 1/6 */ /*+GSG 030303*/
++ return (EC_NO_ERRORS);
++ } /*+GSG 030303*/
++ }
++
++ OsFunc->CriticalOn(); /* 240904 */
++
++ CurrentTcb = HalDev->TxActQueueHead[Ch][Queue];
++ FirstTcbProcessed=CurrentTcb;
++
++ if (CurrentTcb==0)
++ {
++ /* I saw this error a couple of times when multi-channels were added */
++ dbgPrintf("[cppi TxInt()]TxH int with no TCB in queue!\n");
++ dbgPrintf(" Ch=%d, CurrentTcb = 0x%08x\n", Ch, (bit32u)CurrentTcb);
++ dbgPrintf(" HalDev = 0x%08x\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ OsFunc->CriticalOff();
++ return(EC_CPPI|EC_FUNC_TXINT|EC_VAL_NULL_TCB);
++ }
++
++ osfuncDataCacheHitInvalidate((void *)CurrentTcb, 16);
++ TxFrameStatus=CurrentTcb->mode;
++ PacketsServiced=0;
++
++ /* should the ownership bit check be inside of the loop?? could make it a
++ while-do loop and take this check away */
++ if ((TxFrameStatus&CB_OWNERSHIP_BIT)==0)
++ {
++ do
++ {
++ /* Pop TCB(s) for packet from the stack */
++ LastTcbProcessed=CurrentTcb->Eop;
++
++ /* new location for acknowledge */
++ /* Write the completion pointer */
++ (CPMAC_TX_INT_ACK( base , Ch )) = VirtToPhys(LastTcbProcessed) - HalDev->offset;
++
++ HalDev->TxActQueueHead[Ch][Queue] = LastTcbProcessed->Next;
++
++/*+GSG 030303*//*+GSG 030303*/
++
++ osfuncDataCacheHitInvalidate((void *)LastTcbProcessed, 16);
++
++ if (LastTcbProcessed->mode&CB_EOQ_BIT)
++ {
++ if (LastTcbProcessed->Next)
++ {
++ /* Misqueued packet */
++
++ (CPMAC_TX_HDP( base , Ch )) = LastTcbProcessed->HNext;
++
++ }
++ else
++ {
++ /* Tx End of Queue */
++
++ HalDev->TxActive[Ch][Queue]=FALSE;
++ }
++ }
++
++ OsFunc->SendComplete(CurrentTcb->OsInfo);
++
++ /* Push Tcb(s) back onto the stack */
++ CurrentTcb = LastTcbProcessed->Next;
++
++ LastTcbProcessed->Next=HalDev->TcbPool[Ch][Queue];
++
++ HalDev->TcbPool[Ch][Queue]=FirstTcbProcessed;
++
++ PacketsServiced++;
++
++ TxFrameStatus=CB_OWNERSHIP_BIT;
++ /* set the first(SOP) pointer for the next packet */
++ FirstTcbProcessed = CurrentTcb;
++ if (CurrentTcb)
++ {
++ osfuncDataCacheHitInvalidate((void *)CurrentTcb, 16);
++ TxFrameStatus=CurrentTcb->mode;
++ }
++
++ }while(((TxFrameStatus&CB_OWNERSHIP_BIT)==0)
++ &&(PacketsServiced<TxServiceMax));
++
++ if (((TxFrameStatus&CB_OWNERSHIP_BIT)==0)
++ &&(PacketsServiced==TxServiceMax))
++ {
++ *MoreWork = 1;
++ }
++ else
++ {
++ *MoreWork = 0;
++ }
++ }
++ OsFunc->CriticalOff();
++
++ return(EC_NO_ERRORS);
++ }
++
++/**
++ * @ingroup CPHAL_Functions
++ * This function performs a teardown for the given channel. The value of the
++ * Mode parameter controls the operation of the function, as documented below.
++ *
++ * Note: If bit 3 of Mode is set, this call is blocking, and will not return
++ * until the teardown interrupt has occurred and been processed. While waiting
++ * for a blocking teardown to complete, ChannelTeardown() will signal the OS
++ * (via Control(.."Sleep"..)) to allow the OS to perform other tasks if
++ * necessary. If and only if bit 3 of Mode is clear, the CPHAL will call the
++ * OS TeardownComplete() function to indicate that the teardown has completed.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ * @param Ch Channel number.
++ * @param Mode Bit 0 (LSB): Perform Tx teardown (if set).<BR>
++ * Bit 1: Perform Rx teardown (if set). <BR>
++ * Bit 2: If set, perform full teardown (free buffers/descriptors).
++ * If clear, perform partial teardown (keep buffers). <BR>
++ * Bit 3 (MSB): If set, call is blocking.
++ * If clear, call is non-blocking.
++ *
++ * @return EC_NO_ERRORS (ok). <BR>
++ * Possible Error Codes:<BR>
++ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ * @ref EC_VAL_INVALID_CH "EC_VAL_INVALID_CH"<BR>
++ * @ref EC_VAL_TX_TEARDOWN_ALREADY_PEND "EC_VAL_TX_TEARDOWN_ALREADY_PEND"<BR>
++ * @ref EC_VAL_RX_TEARDOWN_ALREADY_PEND "EC_VAL_RX_TEARDOWN_ALREADY_PEND"<BR>
++ * @ref EC_VAL_TX_CH_ALREADY_TORNDOWN "EC_VAL_TX_CH_ALREADY_TORNDOWN"<BR>
++ * @ref EC_VAL_RX_CH_ALREADY_TORNDOWN "EC_VAL_RX_CH_ALREADY_TORNDOWN"<BR>
++ * @ref EC_VAL_TX_TEARDOWN_TIMEOUT "EC_VAL_TX_TEARDOWN_TIMEOUT"<BR>
++ * @ref EC_VAL_RX_TEARDOWN_TIMEOUT "EC_VAL_RX_TEARDOWN_TIMEOUT"<BR>
++ * @ref EC_VAL_LUT_NOT_READY "EC_VAL_LUT_NOT_READY"<BR>
++ */
++static int halChannelTeardown(HAL_DEVICE *HalDev, int Ch, bit32 Mode)
++ {
++ int DoTx, DoRx, Sleep=2048, timeout=0; /*MJH~030306*/
++ bit32u base = HalDev->dev_base;
++
++/* Set the module, used for error returns */
++
++ DoTx = (Mode & TX_TEARDOWN);
++ DoRx = (Mode & RX_TEARDOWN);
++
++ if (HalDev->State < enInitialized)
++ return(EC_CPMAC |EC_FUNC_CHTEARDOWN|EC_VAL_INVALID_STATE);
++
++ if ((Ch < 0) || (Ch > (MAX_CHAN-1) ))
++ {
++ return(EC_CPMAC |EC_FUNC_CHTEARDOWN|EC_VAL_INVALID_CH);
++ }
++
++ /* set teardown pending bits before performing the teardown, because they
++ will be used in the int handler (this is done for AAL5) */
++ if (DoTx)
++ {
++ if (HalDev->TxTeardownPending[Ch] != 0)
++ return(EC_CPMAC |EC_FUNC_CHTEARDOWN|EC_VAL_TX_TEARDOWN_ALREADY_PEND);
++
++ /* If a full teardown, this also means that the user must
++ setup all channels again to use them */
++ if (Mode & FULL_TEARDOWN)
++ HalDev->ChIsSetup[Ch][DIRECTION_TX] = 0;
++
++ if (HalDev->State < enOpened)
++ {
++ /* if the hardware has never been opened, the channel has never actually
++ been setup in the hardware, so I just need to reset the software flag
++ and leave */
++ HalDev->ChIsSetup[Ch][DIRECTION_TX] = 0;
++ return (EC_NO_ERRORS);
++ }
++ else
++ {
++ if (HalDev->ChIsOpen[Ch][DIRECTION_TX] == 0)
++ {
++ return(EC_CPMAC |EC_FUNC_CHTEARDOWN|EC_VAL_TX_CH_ALREADY_TORNDOWN);
++ }
++
++ /* set teardown flag */
++ HalDev->TxTeardownPending[Ch] = Mode;
++ }
++ }
++
++ if (DoRx)
++ {
++ if (HalDev->RxTeardownPending[Ch] != 0)
++ return(EC_CPMAC |EC_FUNC_CHTEARDOWN|EC_VAL_RX_TEARDOWN_ALREADY_PEND);
++
++ if (Mode & FULL_TEARDOWN)
++ HalDev->ChIsSetup[Ch][DIRECTION_RX] = 0;
++
++ if (HalDev->State < enOpened)
++ {
++ HalDev->ChIsSetup[Ch][DIRECTION_RX] = 0;
++ return (EC_NO_ERRORS);
++ }
++ else
++ {
++ if (HalDev->ChIsOpen[Ch][DIRECTION_RX] == 0)
++ return(EC_CPMAC |EC_FUNC_CHTEARDOWN|EC_VAL_RX_CH_ALREADY_TORNDOWN);
++
++ HalDev->RxTeardownPending[Ch] = Mode;
++ }
++ }
++
++ /* Perform Tx Teardown Duties */
++ if ((DoTx) && (HalDev->State == enOpened))
++ {
++ /* Request TX channel teardown */
++ (CPMAC_TX_TEARDOWN( base )) = Ch;
++
++ /* wait until teardown has completed */
++ if (Mode & BLOCKING_TEARDOWN)
++ {
++ timeout = 0;
++ while (HalDev->ChIsOpen[Ch][DIRECTION_TX] == TRUE)
++ {
++ osfuncSleep(&Sleep);
++
++ timeout++;
++ if (timeout > 100000)
++ {
++ return(EC_CPMAC |EC_FUNC_CHTEARDOWN|EC_VAL_TX_TEARDOWN_TIMEOUT);
++ }
++ }
++ }
++ } /* if DoTx */
++
++ /* Perform Rx Teardown Duties */
++ if ((DoRx) && (HalDev->State == enOpened))
++ {
++
++ /* perform CPMAC specific RX channel teardown */
++ CPMAC_RX_TEARDOWN(base) = Ch;
++
++ if (Mode & BLOCKING_TEARDOWN)
++ {
++ timeout = 0;
++ while (HalDev->ChIsOpen[Ch][DIRECTION_RX] == TRUE)
++ {
++ osfuncSleep(&Sleep);
++
++ timeout++;
++ if (timeout > 100000)
++ {
++ return(EC_CPMAC |EC_FUNC_CHTEARDOWN|EC_VAL_RX_TEARDOWN_TIMEOUT);
++ }
++ }
++ }
++ } /* if DoRx */
++
++ return (EC_NO_ERRORS);
++ }
++
++/**
++ * @ingroup CPHAL_Functions
++ * This function closes the CPHAL module. The module will be reset.
++ * The Mode parameter should be used to determine the actions taken by
++ * Close().
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ * @param Mode Indicates actions to take on close. The following integer
++ * values are valid: <BR>
++ * 1: Does not free buffer resources, init parameters remain
++ * intact. User can then call Open() without calling Init()
++ * to attempt to reset the device and bring it back to the
++ * last known state.<BR>
++ * 2: Frees the buffer resources, but keeps init parameters. This
++ * option is a more aggressive means of attempting a device reset.
++ * 3: Frees the buffer resources, and clears all init parameters. <BR>
++ * At this point, the caller would have to call to completely
++ * reinitialize the device (Init()) before being able to call
++ * Open(). Use this mode if you are shutting down the module
++ * and do not plan to restart.
++ *
++ * @return EC_NO_ERRORS (ok).<BR>
++ * Possible Error Codes:<BR>
++ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ * Any error code from halChannelTeardown().<BR>
++ */
++static int halClose(HAL_DEVICE *HalDev, bit32 Mode)
++ {
++ int Ch, Inst, Ret;
++ OS_DEVICE *TmpOsDev;
++ OS_FUNCTIONS *TmpOsFunc;
++ HAL_FUNCTIONS *TmpHalFunc;
++ char *TmpDeviceInfo;
++
++ int Ticks; /*MJH~030306*/
++
++ /* Verify proper device state */
++ if (HalDev->State != enOpened)
++ return (EC_CPMAC | EC_FUNC_CLOSE|EC_VAL_INVALID_STATE);
++
++ /* Teardown all open channels */
++ for (Ch = 0; Ch <= (MAX_CHAN-1) ; Ch++)
++ {
++ if (HalDev->ChIsOpen[Ch][DIRECTION_TX] == TRUE)
++ {
++ if (Mode == 1)
++ {
++ Ret = halChannelTeardown(HalDev, Ch, TX_TEARDOWN | PARTIAL_TEARDOWN | BLOCKING_TEARDOWN);
++ if (Ret) return (Ret);
++ }
++ else
++ {
++ Ret = halChannelTeardown(HalDev, Ch, TX_TEARDOWN | FULL_TEARDOWN | BLOCKING_TEARDOWN);
++ if (Ret) return (Ret);
++ }
++ }
++
++ if (HalDev->ChIsOpen[Ch][DIRECTION_RX] == TRUE)
++ {
++ if (Mode == 1)
++ {
++ Ret = halChannelTeardown(HalDev, Ch, RX_TEARDOWN | PARTIAL_TEARDOWN | BLOCKING_TEARDOWN);
++ if (Ret) return (Ret);
++ }
++ else
++ {
++ Ret = halChannelTeardown(HalDev, Ch, RX_TEARDOWN | FULL_TEARDOWN | BLOCKING_TEARDOWN);
++ if (Ret) return (Ret);
++ }
++ }
++ }
++
++ /* free fraglist in HalDev */
++ HalDev->OsFunc->Free(HalDev->fraglist);
++ HalDev->fraglist = 0;
++
++ /* unregister the interrupt */
++ HalDev->OsFunc->IsrUnRegister(HalDev->OsDev, HalDev->interrupt);
++
++ Ticks = 0; /* Disable Tick Timer */ /*MJH+030306*/
++ HalDev->OsFunc->Control(HalDev->OsDev, hcTick, hcClear, &Ticks); /*MJH+030306*/
++
++ /* Free the Phy Information Structure */
++ if(HalDev->PhyDev)
++ {
++ HalDev->OsFunc->Free(HalDev->PhyDev); /*MJH+030513*/
++ HalDev->PhyDev = 0; /*MJH+030522*/
++ }
++
++ /* Perform CPMAC specific closing functions */
++ CPMAC_MACCONTROL(HalDev->dev_base) &= ~MII_EN;
++ CPMAC_TX_CONTROL(HalDev->dev_base) &= ~TX_EN;
++ CPMAC_RX_CONTROL(HalDev->dev_base) &= ~RX_EN;
++
++ /* put device back into reset */
++ (*(volatile bit32u *)(HalDev->ResetBase)) &=~ (1<<HalDev->ResetBit);
++ Ticks = 64; /*MJH~030306*/
++ osfuncSleep(&Ticks);
++
++ /* If mode is 3, than clear the HalDev and set next state to DevFound*/
++ if (Mode == 3)
++ {
++ /* I need to keep the HalDev parameters that were setup in InitModule */
++ TmpOsDev = HalDev->OsDev;
++ TmpOsFunc = HalDev->OsFunc;
++ TmpDeviceInfo = HalDev->DeviceInfo;
++
++ TmpHalFunc = HalDev->HalFuncPtr;
++ Inst = HalDev->Inst;
++
++ /* Clear HalDev */
++
++ HalDev->OsFunc->Memset(HalDev, 0, sizeof(HAL_DEVICE));
++
++ /* Restore key parameters */
++ HalDev->OsDev = TmpOsDev;
++ HalDev->OsFunc = TmpOsFunc;
++ HalDev->DeviceInfo = TmpDeviceInfo;
++
++ HalDev->HalFuncPtr = TmpHalFunc;
++ HalDev->Inst = Inst;
++
++ HalDev->State = enDevFound;
++ }
++ else
++ {
++ HalDev->State = enInitialized;
++ }
++
++ return(EC_NO_ERRORS);
++ }
+diff -urN linux.old/drivers/net/avalanche_cpmac/cpremap_cpmac.c linux.dev/drivers/net/avalanche_cpmac/cpremap_cpmac.c
+--- linux.old/drivers/net/avalanche_cpmac/cpremap_cpmac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpremap_cpmac.c 2005-07-12 02:48:42.049593000 +0200
+@@ -0,0 +1,28 @@
++#ifndef _INC_CPREMAP_C
++#define _INC_CPREMAP_C
++
++#ifdef __ADAM2
++static inline void osfuncDataCacheHitInvalidate(void *ptr, int Size)
++ {
++ asm(" cache 17, (%0)" : : "r" (ptr));
++ }
++
++static inline void osfuncDataCacheHitWriteback(void *ptr, int Size)
++ {
++ asm(" cache 25, (%0)" : : "r" (ptr));
++ }
++
++static inline void osfuncDataCacheHitWritebackAndInvalidate(void *ptr, int Size)
++ {
++ asm(" cache 21, (%0)" : : "r" (ptr));
++ }
++
++#else
++
++#define osfuncDataCacheHitInvalidate(MemPtr, Size) __asm__(" .set mips3; cache 17, (%0); .set mips0" : : "r" (MemPtr))
++#define osfuncDataCacheHitWritebackAndInvalidate(MemPtr, Size) __asm__(" .set mips3; cache 21, (%0); .set mips0" : : "r" (MemPtr))
++#define osfuncDataCacheHitWriteback(MemPtr, Size) __asm__(" .set mips3; cache 25, (%0); .set mips0" : : "r" (MemPtr))
++
++#endif
++
++#endif
+diff -urN linux.old/drivers/net/avalanche_cpmac/cpswhal_cpmac.h linux.dev/drivers/net/avalanche_cpmac/cpswhal_cpmac.h
+--- linux.old/drivers/net/avalanche_cpmac/cpswhal_cpmac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpswhal_cpmac.h 2005-07-12 02:48:42.050593000 +0200
+@@ -0,0 +1,632 @@
++/************************************************************************
++ * TNETDxxxx Software Support
++ * Copyright (c) 2002 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ * FILE: cphal.h
++ *
++ * DESCRIPTION:
++ * User include file, contains data definitions shared between the CPHAL
++ * and the upper-layer software.
++ *
++ * HISTORY:
++ * Date Modifier Ver Notes
++ * 28Feb02 Greg 1.00 Original
++ * 06Mar02 Greg 1.01 Documentation enhanced
++ * 18Jul02 Greg 1.02 Many updates (OAM additions, general reorg)
++ * 22Nov02 Mick RC2 Additions from Denis' input on Control
++ *
++ * author Greg Guyotte
++ * version 1.02
++ * date 18-Jul-2002
++ *****************************************************************************/
++#ifndef _INC_CPHAL_H
++#define _INC_CPHAL_H
++
++#ifdef _CPHAL_CPMAC
++#include "ec_errors_cpmac.h"
++#endif
++
++#ifdef _CPHAL_AAL5
++#include "ec_errors_cpaal5.h"
++#endif
++
++#ifdef _CPHAL_CPSAR
++#include "ec_errors_cpsar.h"
++#endif
++
++#ifdef _CPHAL_AAL2
++#include "ec_errors_cpaal2.h"
++#endif
++
++#ifndef __ADAM2
++typedef char bit8;
++typedef short bit16;
++typedef int bit32;
++
++typedef unsigned char bit8u;
++typedef unsigned short bit16u;
++typedef unsigned int bit32u;
++
++/*
++typedef char INT8;
++typedef short INT16;
++typedef int INT32;
++typedef unsigned char UINT8;
++typedef unsigned short UINT16;
++typedef unsigned int UINT32;
++*/
++/*typedef unsigned int size_t;*/
++#endif
++
++#ifdef _CPHAL
++
++#ifndef TRUE
++#define TRUE (1==1)
++#endif
++
++#ifndef FALSE
++#define FALSE (1==2)
++#endif
++
++#ifndef NULL
++#define NULL 0
++#endif
++
++#endif
++
++#define VirtToPhys(a) (((int)a)&~0xe0000000)
++#define VirtToVirtNoCache(a) ((void*)((VirtToPhys(a))|0xa0000000))
++#define VirtToVirtCache(a) ((void*)((VirtToPhys(a))|0x80000000))
++#define PhysToVirtNoCache(a) ((void*)(((int)a)|0xa0000000))
++#define PhysToVirtCache(a) ((void*)(((int)a)|0x80000000))
++/*
++#define DataCacheHitInvalidate(a) {__asm__(" cache 17, (%0)" : : "r" (a));}
++#define DataCacheHitWriteback(a) {__asm__(" cache 25, (%0)" : : "r" (a));}
++*/
++
++#define PARTIAL 1 /**< Used in @c Close() and @c ChannelTeardown() */
++#define FULL 2 /**< Used in @c Close() and @c ChannelTeardown() */
++
++/* Channel Teardown Defines */
++#define RX_TEARDOWN 2
++#define TX_TEARDOWN 1
++#define BLOCKING_TEARDOWN 8
++#define FULL_TEARDOWN 4
++#define PARTIAL_TEARDOWN 0
++
++#define MAX_DIR 2
++#define DIRECTION_TX 0
++#define DIRECTION_RX 1
++#define TX_CH 0
++#define RX_CH 1
++#define HAL_ERROR_DEVICE_NOT_FOUND 1
++#define HAL_ERROR_FAILED_MALLOC 2
++#define HAL_ERROR_OSFUNC_SIZE 3
++#define HAL_DEFAULT 0xFFFFFFFF
++#define VALID(val) (val!=HAL_DEFAULT)
++
++/*
++ERROR REPORTING
++
++HAL Module Codes. Each HAL module reporting an error code
++should OR the error code with the respective Module error code
++from the list below.
++*/
++#define EC_AAL5 EC_HAL|EC_DEV_AAL5
++#define EC_AAL2 EC_HAL|EC_DEV_AAL2
++#define EC_CPSAR EC_HAL|EC_DEV_CPSAR
++#define EC_CPMAC EC_HAL|EC_DEV_CPMAC
++#define EC_VDMA EC_HAL|EC_DEV_VDMA
++#define EC_VLYNQ EC_HAL|EC_DEV_VLYNQ
++#define EC_CPPI EC_HAL|EC_DEV_CPPI
++
++/*
++HAL Function Codes. Each HAL module reporting an error code
++should OR the error code with one of the function codes from
++the list below.
++*/
++#define EC_FUNC_HAL_INIT EC_FUNC(1)
++#define EC_FUNC_CHSETUP EC_FUNC(2)
++#define EC_FUNC_CHTEARDOWN EC_FUNC(3)
++#define EC_FUNC_RXRETURN EC_FUNC(4)
++#define EC_FUNC_SEND EC_FUNC(5)
++#define EC_FUNC_RXINT EC_FUNC(6)
++#define EC_FUNC_TXINT EC_FUNC(7)
++#define EC_FUNC_AAL2_VDMA EC_FUNC(8)
++#define EC_FUNC_OPTIONS EC_FUNC(9)
++#define EC_FUNC_PROBE EC_FUNC(10)
++#define EC_FUNC_OPEN EC_FUNC(11)
++#define EC_FUNC_CONTROL EC_FUNC(12)
++#define EC_FUNC_DEVICE_INT EC_FUNC(13)
++#define EC_FUNC_STATUS EC_FUNC(14)
++#define EC_FUNC_TICK EC_FUNC(15)
++#define EC_FUNC_CLOSE EC_FUNC(16)
++#define EC_FUNC_SHUTDOWN EC_FUNC(17)
++#define EC_FUNC_DEVICE_INT_ALT EC_FUNC(18) /* +GSG 030306 */
++
++/*
++HAL Error Codes. The list below defines every type of error
++used in all HAL modules. DO NOT CHANGE THESE VALUES! Add new
++values in integer order to the bottom of the list.
++*/
++#define EC_VAL_PDSP_LOAD_FAIL EC_ERR(0x01)|EC_CRITICAL
++#define EC_VAL_FIRMWARE_TOO_LARGE EC_ERR(0x02)|EC_CRITICAL
++#define EC_VAL_DEVICE_NOT_FOUND EC_ERR(0x03)|EC_CRITICAL
++#define EC_VAL_BASE_ADDR_NOT_FOUND EC_ERR(0x04)|EC_CRITICAL
++#define EC_VAL_RESET_BIT_NOT_FOUND EC_ERR(0x05)|EC_CRITICAL
++#define EC_VAL_CH_INFO_NOT_FOUND EC_ERR(0x06)
++#define EC_VAL_RX_STATE_RAM_NOT_CLEARED EC_ERR(0x07)|EC_CRITICAL
++#define EC_VAL_TX_STATE_RAM_NOT_CLEARED EC_ERR(0x08)|EC_CRITICAL
++#define EC_VAL_MALLOC_DEV_FAILED EC_ERR(0x09)
++#define EC_VAL_OS_VERSION_NOT_SUPPORTED EC_ERR(0x0A)|EC_CRITICAL
++#define EC_VAL_CPSAR_VERSION_NOT_SUPPORTED EC_ERR(0x0B)|EC_CRITICAL
++#define EC_VAL_NULL_CPSAR_DEV EC_ERR(0x0C)|EC_CRITICAL
++
++#define EC_VAL_LUT_NOT_READY EC_ERR(0x0D)
++#define EC_VAL_INVALID_CH EC_ERR(0x0E)
++#define EC_VAL_NULL_CH_STRUCT EC_ERR(0x0F)
++#define EC_VAL_RX_TEARDOWN_ALREADY_PEND EC_ERR(0x10)
++#define EC_VAL_TX_TEARDOWN_ALREADY_PEND EC_ERR(0x11)
++#define EC_VAL_RX_CH_ALREADY_TORNDOWN EC_ERR(0x12)
++#define EC_VAL_TX_CH_ALREADY_TORNDOWN EC_ERR(0x13)
++#define EC_VAL_TX_TEARDOWN_TIMEOUT EC_ERR(0x14)
++#define EC_VAL_RX_TEARDOWN_TIMEOUT EC_ERR(0x15)
++#define EC_VAL_CH_ALREADY_TORNDOWN EC_ERR(0x16)
++#define EC_VAL_VC_SETUP_NOT_READY EC_ERR(0x17)
++#define EC_VAL_VC_TEARDOWN_NOT_READY EC_ERR(0x18)
++#define EC_VAL_INVALID_VC EC_ERR(0x19)
++#define EC_VAL_INVALID_LC EC_ERR(0x20)
++#define EC_VAL_INVALID_VDMA_CH EC_ERR(0x21)
++#define EC_VAL_INVALID_CID EC_ERR(0x22)
++#define EC_VAL_INVALID_UUI EC_ERR(0x23)
++#define EC_VAL_INVALID_UUI_DISCARD EC_ERR(0x24)
++#define EC_VAL_CH_ALREADY_OPEN EC_ERR(0x25)
++
++#define EC_VAL_RCB_MALLOC_FAILED EC_ERR(0x26)
++#define EC_VAL_RX_BUFFER_MALLOC_FAILED EC_ERR(0x27)
++#define EC_VAL_OUT_OF_TCBS EC_ERR(0x28)
++#define EC_VAL_NO_TCBS EC_ERR(0x29)
++#define EC_VAL_NULL_RCB EC_ERR(0x30)|EC_CRITICAL
++#define EC_VAL_SOP_ERROR EC_ERR(0x31)|EC_CRITICAL
++#define EC_VAL_EOP_ERROR EC_ERR(0x32)|EC_CRITICAL
++#define EC_VAL_NULL_TCB EC_ERR(0x33)|EC_CRITICAL
++#define EC_VAL_CORRUPT_RCB_CHAIN EC_ERR(0x34)|EC_CRITICAL
++#define EC_VAL_TCB_MALLOC_FAILED EC_ERR(0x35)
++
++#define EC_VAL_DISABLE_POLLING_FAILED EC_ERR(0x36)
++#define EC_VAL_KEY_NOT_FOUND EC_ERR(0x37)
++#define EC_VAL_MALLOC_FAILED EC_ERR(0x38)
++#define EC_VAL_RESET_BASE_NOT_FOUND EC_ERR(0x39)|EC_CRITICAL
++#define EC_VAL_INVALID_STATE EC_ERR(0x40)
++#define EC_VAL_NO_TXH_WORK_TO_DO EC_ERR(0x41)
++#define EC_VAL_NO_TXL_WORK_TO_DO EC_ERR(0x42)
++#define EC_VAL_NO_RX_WORK_TO_DO EC_ERR(0x43)
++#define EC_VAL_NOT_LINKED EC_ERR(0x44)
++#define EC_VAL_INTERRUPT_NOT_FOUND EC_ERR(0x45)
++#define EC_VAL_OFFSET_NOT_FOUND EC_ERR(0x46)
++#define EC_VAL_MODULE_ALREADY_CLOSED EC_ERR(0x47)
++#define EC_VAL_MODULE_ALREADY_SHUTDOWN EC_ERR(0x48)
++#define EC_VAL_ACTION_NOT_FOUND EC_ERR(0x49)
++#define EC_VAL_RX_CH_ALREADY_SETUP EC_ERR(0x50)
++#define EC_VAL_TX_CH_ALREADY_SETUP EC_ERR(0x51)
++#define EC_VAL_RX_CH_ALREADY_OPEN EC_ERR(0x52)
++#define EC_VAL_TX_CH_ALREADY_OPEN EC_ERR(0x53)
++#define EC_VAL_CH_ALREADY_SETUP EC_ERR(0x54)
++#define EC_VAL_RCB_NEEDS_BUFFER EC_ERR(0x55) /* +GSG 030410 */
++#define EC_VAL_RCB_DROPPED EC_ERR(0x56) /* +GSG 030410 */
++#define EC_VAL_INVALID_VALUE EC_ERR(0x57)
++
++/**
++@defgroup shared_data Shared Data Structures
++
++The data structures documented here are shared by all modules.
++*/
++
++/**
++ * @ingroup shared_data
++ * This is the fragment list structure. Each fragment list entry contains a
++ * length and a data buffer.
++ */
++typedef struct
++ {
++ bit32u len; /**< Length of the fragment in bytes (lower 16 bits are valid). For SOP, upper 16 bits is the buffer offset. */
++ void *data; /**< Pointer to fragment data. */
++ void *OsInfo; /**< Pointer to OS defined data. */
++ }FRAGLIST;
++
++#if defined (_CPHAL_CPMAC)
++#define CB_PASSCRC_BIT (1<<26)
++
++/* CPMAC CPHAL STATUS */
++#define CPMAC_STATUS_LINK (1 << 0)
++#define CPMAC_STATUS_LINK_DUPLEX (1 << 1) /* 0 - HD, 1 - FD */
++#define CPMAC_STATUS_LINK_SPEED (1 << 2) /* 0 - 10, 1 - 100 */
++
++/* ADAPTER CHECK Codes */
++
++#define CPMAC_STATUS_ADAPTER_CHECK (1 << 7)
++#define CPMAC_STATUS_HOST_ERR_DIRECTION (1 << 8)
++#define CPMAC_STATUS_HOST_ERR_CODE (0xF << 9)
++#define CPMAC_STATUS_HOST_ERR_CH (0x7 << 13)
++
++#define _CPMDIO_DISABLE (1 << 0)
++#define _CPMDIO_HD (1 << 1)
++#define _CPMDIO_FD (1 << 2)
++#define _CPMDIO_10 (1 << 3)
++#define _CPMDIO_100 (1 << 4)
++#define _CPMDIO_NEG_OFF (1 << 5)
++#define _CPMDIO_LOOPBK (1 << 16)
++#define _CPMDIO_AUTOMDIX (1 << 17) /* Bit 16 and above not used by MII register */
++#define _CPMDIO_NOPHY (1 << 20)
++#endif
++
++/**
++ * @ingroup shared_data
++ * Channel specific configuration information. This structure should be
++ * populated by upper-layer software prior to calling @c ChannelSetup(). Any
++ * configuration item that can be changed on a per channel basis should
++ * be represented here. Each module may define this structure with additional
++ * module-specific members.
++ */
++typedef struct
++ {
++ int Channel; /**< Channel number. */
++ int Direction; /**< DIRECTION_RX(1) or DIRECTION_TX(0). */
++ OS_SETUP *OsSetup; /**< OS defined information associated with this channel. */
++
++#if defined(_CPHAL_AAL5) || defined (_CPHAL_CPSAR) || defined (_CPHAL_CPMAC)
++ int RxBufSize; /**< Size (in bytes) for each Rx buffer.*/
++ int RxBufferOffset; /**< Number of bytes to offset rx data from start of buffer (must be less than buffer size). */
++ int RxNumBuffers; /**< The number of Rx buffer descriptors to allocate for Ch. */
++ int RxServiceMax; /**< Maximum number of packets to service at one time. */
++
++ int TxNumBuffers; /**< The number of Tx buffer descriptors to allocate for Ch. */
++ int TxNumQueues; /**< Number of Tx queues for this channel (1-2). Choosing 2 enables a low priority SAR queue. */
++ int TxServiceMax; /**< Maximum number of packets to service at one time. */
++#endif
++
++#if defined(_CPHAL_AAL5) || defined(_CPHAL_CPSAR)
++ int CpcsUU; /**< The 2-byte CPCS UU and CPI information. */
++ int Gfc; /**< Generic Flow Control. */
++ int Clp; /**< Cell Loss Priority. */
++ int Pti; /**< Payload Type Indication. */
++#endif
++
++#if defined(_CPHAL_AAL2) || defined(_CPHAL_AAL5) || defined(_CPHAL_CPSAR)
++ int DaMask; /**< Specifies whether credit issuance is paused when Tx data not available. */
++ int Priority; /**< Priority bin this channel will be scheduled within. */
++ int PktType; /**< 0=AAL5,1=Null AAL,2=OAM,3=Transparent,4=AAL2. */
++ int Vci; /**< Virtual Channel Identifier. */
++ int Vpi; /**< Virtual Path Identifier. */
++ int FwdUnkVc; /**< Enables forwarding of unknown VCI/VPI cells to host. 1=enable, 0=disable. */
++
++ /* Tx VC State */
++ int TxVc_CellRate; /**< Tx rate, set as clock ticks between transmissions (SCR for VBR, CBR for CBR). */
++ int TxVc_QosType; /**< 0=CBR,1=VBR,2=UBR,3=UBRmcr. */
++ int TxVc_Mbs; /**< Min Burst Size in cells.*/
++ int TxVc_Pcr; /**< Peak Cell Rate for VBR in clock ticks between transmissions. */
++
++ bit32 TxVc_AtmHeader; /**< ATM Header placed on firmware gen'd OAM cells for this Tx Ch (must be big endian with 0 PTI). */
++ int TxVc_OamTc; /**< TC Path to transmit OAM cells for TX connection (0,1). */
++ int TxVc_VpOffset; /**< Offset to the OAM VP state table. */
++ /* Rx VC State */
++ int RxVc_OamCh; /**< Ch to terminate rx'd OAM cells to be forwarded to the host. */
++ int RxVc_OamToHost; /**< 0=do not pass, 1=pass. */
++ bit32 RxVc_AtmHeader; /**< ATM Header placed on firmware gen'd OAM cells for this Rx conn (must be big endian with 0 PTI). */
++ int RxVc_OamTc; /**< TC Path to transmit OAM cells for RX connection (0,1). */
++ int RxVc_VpOffset; /**< Offset to the OAM VP state table. */
++ /* Tx VP State */
++ int TxVp_OamTc; /**< TC Path to transmit OAM cells for TX VP connection (0,1). */
++ bit32 TxVp_AtmHeader; /**< ATM Header placed on firmware gen'd VP OAM cells for this Tx VP conn (must be big endian with 0 VCI). */
++ /* Rx VP State */
++ int RxVp_OamCh; /**< Ch to terminate rx'd OAM cells to be forwarded to the host. */
++ int RxVp_OamToHost; /**< 0=do not pass, 1=pass. */
++ bit32 RxVp_AtmHeader; /**< ATM Header placed on firmware gen'd OAM cells for this Rx VP conn (must be big endian with 0 VCI). */
++ int RxVp_OamTc; /**< TC Path to transmit OAM cells for RX VP connection (0,1). */
++ int RxVp_OamVcList; /**< Indicates all VC channels associated with this VP channel (one-hot encoded). */
++#endif
++
++
++#ifdef _CPHAL_VDMAVT
++ bit32u RemFifoAddr; /* Mirror mode only. */
++ bit32u FifoAddr;
++ bit32 PollInt;
++ bit32 FifoSize;
++ int Ready;
++#endif
++
++ }CHANNEL_INFO;
++
++/*
++ * This structure contains each statistic value gathered by the CPHAL.
++ * Applications may access statistics data by using the @c StatsGet() routine.
++ */
++/* STATS */
++#if defined(_CPHAL_AAL2) || defined(_CPHAL_AAL5) || defined(_CPHAL_CPSAR)
++typedef struct
++ {
++ bit32u CrcErrors[16];
++ bit32u LenErrors[16];
++ bit32u DmaLenErrors[16];
++ bit32u AbortErrors[16];
++ bit32u StarvErrors[16];
++ bit32u TxMisQCnt[16][2];
++ bit32u RxMisQCnt[16];
++ bit32u RxEOQCnt[16];
++ bit32u TxEOQCnt[16][2];
++ bit32u RxPacketsServiced[16];
++ bit32u TxPacketsServiced[16][2];
++ bit32u RxMaxServiced;
++ bit32u TxMaxServiced[16][2];
++ bit32u RxTotal;
++ bit32u TxTotal;
++ } STAT_INFO;
++#endif
++
++/*
++ * VDMA Channel specific configuration information
++ */
++#ifdef _CPHAL_AAL2
++typedef struct
++ {
++ int Ch; /**< Channel Number */
++ int RemoteEndian; /**< Endianness of remote VDMA-VT device */
++ int CpsSwap; /**< When 0, octet 0 in CPS pkt located in LS byte of 16-bit word sent to rem VDMA device. When 1, in MS byte. */
++ }VdmaChInfo;
++#endif
++
++#ifndef _CPHAL
++ typedef void HAL_DEVICE;
++ typedef void HAL_PRIVATE;
++ typedef void HAL_RCB;
++ typedef void HAL_RECEIVEINFO;
++#endif
++
++/**
++ * @ingroup shared_data
++ * The HAL_FUNCTIONS struct defines the function pointers used by upper layer
++ * software. The upper layer software receives these pointers through the
++ * call to xxxInitModule().
++ */
++typedef struct
++ {
++ int (*ChannelSetup) (HAL_DEVICE *HalDev, CHANNEL_INFO *Channel, OS_SETUP *OsSetup);
++ int (*ChannelTeardown) (HAL_DEVICE *HalDev, int Channel, int Mode);
++ int (*Close) (HAL_DEVICE *HalDev, int Mode);
++ int (*Control) (HAL_DEVICE *HalDev, const char *Key, const char *Action, void *Value);
++ int (*Init) (HAL_DEVICE *HalDev);
++ int (*Open) (HAL_DEVICE *HalDev);
++ int (*PacketProcessEnd) (HAL_DEVICE *HalDev);
++ int (*Probe) (HAL_DEVICE *HalDev);
++ int (*RxReturn) (HAL_RECEIVEINFO *HalReceiveInfo, int StripFlag);
++ int (*Send) (HAL_DEVICE *HalDev, FRAGLIST *FragList, int FragCount, int PacketSize, OS_SENDINFO *OsSendInfo, bit32u Mode);
++ int (*Shutdown) (HAL_DEVICE *HalDev);
++ int (*Tick) (HAL_DEVICE *HalDev);
++
++#ifdef _CPHAL_AAL5
++ int (*Kick) (HAL_DEVICE *HalDev, int Queue);
++ void (*OamFuncConfig) (HAL_DEVICE *HalDev, unsigned int OamConfig);
++ void (*OamLoopbackConfig) (HAL_DEVICE *HalDev, unsigned int OamConfig, unsigned int *LLID, unsigned int CorrelationTag);
++ volatile bit32u* (*RegAccess)(HAL_DEVICE *HalDev, bit32u RegOffset);
++ STAT_INFO* (*StatsGetOld)(HAL_DEVICE *HalDev);
++#endif
++ } HAL_FUNCTIONS;
++
++/**
++ * @ingroup shared_data
++ * The OS_FUNCTIONS struct defines the function pointers for all upper layer
++ * functions accessible to the CPHAL. The upper layer software is responsible
++ * for providing the correct OS-specific implementations for the following
++ * functions. It is populated by calling InitModule() (done by the CPHAL in
++ * xxxInitModule().
++ */
++typedef struct
++ {
++ int (*Control)(OS_DEVICE *OsDev, const char *Key, const char *Action, void *Value);
++ void (*CriticalOn)(void);
++ void (*CriticalOff)(void);
++ void (*DataCacheHitInvalidate)(void *MemPtr, int Size);
++ void (*DataCacheHitWriteback)(void *MemPtr, int Size);
++ int (*DeviceFindInfo)(int Inst, const char *DeviceName, void *DeviceInfo);
++ int (*DeviceFindParmUint)(void *DeviceInfo, const char *Parm, bit32u *Value);
++ int (*DeviceFindParmValue)(void *DeviceInfo, const char *Parm, void *Value);
++ void (*Free)(void *MemPtr);
++ void (*FreeRxBuffer)(OS_RECEIVEINFO *OsReceiveInfo, void *MemPtr);
++ void (*FreeDev)(void *MemPtr);
++ void (*FreeDmaXfer)(void *MemPtr);
++ void (*IsrRegister)(OS_DEVICE *OsDev, int (*halISR)(HAL_DEVICE*, int*), int InterruptBit);
++ void (*IsrUnRegister)(OS_DEVICE *OsDev, int InterruptBit);
++ void* (*Malloc)(bit32u size);
++ void* (*MallocDev)(bit32u Size);
++ void* (*MallocDmaXfer)(bit32u size, void *MemBase, bit32u MemRange);
++ void* (*MallocRxBuffer)(bit32u size, void *MemBase, bit32u MemRange,
++ OS_SETUP *OsSetup, HAL_RECEIVEINFO *HalReceiveInfo,
++ OS_RECEIVEINFO **OsReceiveInfo, OS_DEVICE *OsDev);
++ void* (*Memset)(void *Dest, int C, bit32u N);
++ int (*Printf)(const char *Format, ...);
++ int (*Receive)(OS_DEVICE *OsDev,FRAGLIST *FragList,bit32u FragCount,
++ bit32u PacketSize,HAL_RECEIVEINFO *HalReceiveInfo, bit32u Mode);
++ int (*SendComplete)(OS_SENDINFO *OsSendInfo);
++ int (*Sprintf)(char *S, const char *Format, ...);
++ int (*Strcmpi)(const char *Str1, const char *Str2);
++ unsigned int (*Strlen)(const char *S);
++ char* (*Strstr)(const char *S1, const char *S2);
++ unsigned long (*Strtoul)(const char *Str, char **Endptr, int Base);
++ void (*TeardownComplete)(OS_DEVICE *OsDev, int Ch, int Direction);
++ } OS_FUNCTIONS;
++
++/************** MODULE SPECIFIC STUFF BELOW **************/
++
++#ifdef _CPHAL_CPMAC
++
++/*
++int halCpmacInitModule(HAL_DEVICE **HalDev, OS_DEVICE *OsDev, HAL_FUNCTIONS *HalFunc, int (*osBridgeInitModule)(OS_FUNCTIONS *), void* (*osMallocDev) (bit32u), int *Size, int inst);
++*/
++
++int halCpmacInitModule(HAL_DEVICE **HalDev,
++ OS_DEVICE *OsDev,
++ HAL_FUNCTIONS **HalFunc,
++ OS_FUNCTIONS *OsFunc,
++ int OsFuncSize,
++ int *HalFuncSize,
++ int Inst);
++#endif
++
++#ifdef _CPHAL_AAL5
++/*
++ * @ingroup shared_data
++ * The AAL5_FUNCTIONS struct defines the AAL5 function pointers used by upper layer
++ * software. The upper layer software receives these pointers through the
++ * call to cphalInitModule().
++ */
++/*
++typedef struct
++ {
++ int (*ChannelSetup)(HAL_DEVICE *HalDev, CHANNEL_INFO *HalCh, OS_SETUP *OsSetup);
++ int (*ChannelTeardown)(HAL_DEVICE *HalDev, int Ch, int Mode);
++ int (*Close)(HAL_DEVICE *HalDev, int Mode);
++ int (*Init)(HAL_DEVICE *HalDev);
++ int (*ModeChange)(HAL_DEVICE *HalDev, char *DeviceParms);
++ int (*Open)(HAL_DEVICE *HalDev);
++ int (*InfoGet)(HAL_DEVICE *HalDev, int Key, void *Value);
++ int (*Probe)(HAL_DEVICE *HalDev);
++ int (*RxReturn)(HAL_RECEIVEINFO *HalReceiveInfo, int StripFlag);
++ int (*Send)(HAL_DEVICE *HalDev,FRAGLIST *FragList,int FragCount,
++ int PacketSize,OS_SENDINFO *OsSendInfo,int Ch, int Queue,
++ bit32u Mode);
++ int (*StatsClear)(HAL_DEVICE *HalDev);
++ STAT_INFO* (*StatsGet)(HAL_DEVICE *HalDev);
++ int (*Status)(HAL_DEVICE *HalDev);
++ void (*Tick)(HAL_DEVICE *HalDev);
++ int (*Kick)(HAL_DEVICE *HalDev, int Queue);
++ volatile bit32u* (*RegAccess)(HAL_DEVICE *HalDev, bit32u RegOffset);
++ } AAL5_FUNCTIONS;
++*/
++
++int cpaal5InitModule(HAL_DEVICE **HalDev,
++ OS_DEVICE *OsDev,
++ HAL_FUNCTIONS **HalFunc,
++ OS_FUNCTIONS *OsFunc,
++ int OsFuncSize,
++ int *HalFuncSize,
++ int Inst);
++#endif
++
++#ifdef _CPHAL_AAL2
++/**
++ * @ingroup shared_data
++ * The AAL2_FUNCTIONS struct defines the AAL2 function pointers used by upper layer
++ * software. The upper layer software receives these pointers through the
++ * call to cphalInitModule().
++ */
++typedef struct
++ {
++ int (*ChannelSetup)(HAL_DEVICE *HalDev, CHANNEL_INFO *HalCh, OS_SETUP *OsSetup);
++ int (*ChannelTeardown)(HAL_DEVICE *HalDev, int Ch, int Mode);
++ int (*Close)(HAL_DEVICE *HalDev, int Mode);
++ int (*Init)(HAL_DEVICE *HalDev);
++ int (*ModeChange)(HAL_DEVICE *HalDev, char *DeviceParms);
++ int (*Open)(HAL_DEVICE *HalDev);
++ int (*OptionsGet)(HAL_DEVICE *HalDev, char *Key, bit32u *Value);
++ int (*Probe)(HAL_DEVICE *HalDev);
++
++ int (*StatsClear)(HAL_DEVICE *HalDev);
++ STAT_INFO* (*StatsGet)(HAL_DEVICE *HalDev);
++ int (*Status)(HAL_DEVICE *HalDev);
++ void (*Tick)(HAL_DEVICE *HalDev);
++ int (*Aal2UuiMappingSetup)(HAL_DEVICE *HalDev, int VC, int UUI,
++ int VdmaCh, int UUIDiscard);
++ int (*Aal2RxMappingSetup)(HAL_DEVICE *HalDev, int VC, int CID,
++ int LC);
++ int (*Aal2TxMappingSetup)(HAL_DEVICE *HalDev, int VC, int LC, int VdmaCh);
++ int (*Aal2VdmaChSetup)(HAL_DEVICE *HalDev, bit32u RemVdmaVtAddr,
++ VdmaChInfo *VdmaCh);
++ volatile bit32u* (*RegAccess)(HAL_DEVICE *HalDev, bit32u RegOffset);
++ int (*Aal2ModeChange)(HAL_DEVICE *HalDev, int Vc, int RxCrossMode,
++ int RxMultiMode, int TxMultiMode, int SchedMode,
++ int TcCh);
++ void (*Aal2VdmaEnable)(HAL_DEVICE *HalDev, int Ch);
++ int (*Aal2VdmaDisable)(HAL_DEVICE *HalDev, int Ch);
++ } AAL2_FUNCTIONS;
++
++int cpaal2InitModule(HAL_DEVICE **HalDev,
++ OS_DEVICE *OsDev,
++ AAL2_FUNCTIONS **HalFunc,
++ OS_FUNCTIONS *OsFunc,
++ int OsFuncSize,
++ int *HalFuncSize,
++ int Inst);
++#endif
++
++#ifdef _CPHAL_VDMAVT
++/**
++ * @ingroup shared_data
++ * The VDMA_FUNCTIONS struct defines the HAL function pointers used by upper layer
++ * software. The upper layer software receives these pointers through the
++ * call to InitModule().
++ *
++ * Note that this list is still under definition.
++ */
++typedef struct
++ {
++ bit32 (*Init)( HAL_DEVICE *VdmaVtDev);
++ /* bit32 (*SetupTxFifo)(HAL_DEVICE *VdmaVtDev, bit32u LclRem,
++ bit32u Addr, bit32u Size, bit32u PollInt);
++ bit32 (*SetupRxFifo)(HAL_DEVICE *VdmaVtDev, bit32u LclRem,
++ bit32u Addr, bit32u Size, bit32u PollInt); */
++ bit32 (*Tx)(HAL_DEVICE *VdmaVtDev);
++ bit32 (*Rx)(HAL_DEVICE *VdmaVtDev);
++ bit32 (*SetRemoteChannel)(HAL_DEVICE *VdmaVtDev, bit32u RemAddr,
++ bit32u RemDevID);
++ bit32 (*ClearRxInt)(HAL_DEVICE *VdmaVtDev);
++ bit32 (*ClearTxInt)(HAL_DEVICE *VdmaVtDev);
++ bit32 (*Open)(HAL_DEVICE *VdmaVtDev);
++ bit32 (*Close)(HAL_DEVICE *VdmaVtDev);
++ int (*Control) (HAL_DEVICE *HalDev, const char *Key, const char *Action, void *Value);
++ int (*ChannelSetup)(HAL_DEVICE *VdmaVtDev, CHANNEL_INFO *HalCh, OS_SETUP *OsSetup);
++ int (*ChannelTeardown)(HAL_DEVICE *VdmaVtDev, int Ch, int Mode);
++ int (*Send)(HAL_DEVICE *VdmaVtDev,FRAGLIST *FragList,int FragCount,
++ int PacketSize,OS_SENDINFO *OsSendInfo,bit32u Mode);
++ } VDMA_FUNCTIONS;
++
++int VdmaInitModule(HAL_DEVICE **VdmaVt,
++ OS_DEVICE *OsDev,
++ VDMA_FUNCTIONS **VdmaVtFunc,
++ OS_FUNCTIONS *OsFunc,
++ int OsFuncSize,
++ int *HalFuncSize,
++ int Inst);
++#endif
++
++/*
++extern int cphalInitModule(MODULE_TYPE ModuleType, HAL_DEVICE **HalDev, OS_DEVICE *OsDev, HAL_FUNCTIONS *HalFunc,
++ int (*osInitModule)(OS_FUNCTIONS *), void* (*osMallocDev)(bit32u),
++ int *Size, int Inst);
++*/
++
++
++#ifdef _CPHAL_AAL5
++extern const char hcSarFrequency[];
++#endif
++
++#ifdef _CPHAL_CPMAC
++/* following will be common, once 'utl' added */
++extern const char hcClear[];
++extern const char hcGet[];
++extern const char hcSet[];
++extern const char hcTick[];
++
++extern const char hcCpuFrequency[];
++extern const char hcCpmacFrequency[];
++extern const char hcMdioBusFrequency[];
++extern const char hcMdioClockFrequency[];
++extern const char hcCpmacBase[];
++extern const char hcPhyNum[];
++extern const char hcSize[];
++extern const char hcCpmacSize[];
++extern const char hcPhyAccess[];
++extern const char hcMdixMask[];
++extern const char hcMdioMdixSwitch[];
++#endif
++
++#endif /* end of _INC_ */
+diff -urN linux.old/drivers/net/avalanche_cpmac/dox_cpmac.h linux.dev/drivers/net/avalanche_cpmac/dox_cpmac.h
+--- linux.old/drivers/net/avalanche_cpmac/dox_cpmac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/dox_cpmac.h 2005-07-12 02:48:42.050593000 +0200
+@@ -0,0 +1,842 @@
++/*****************************************************************************
++ * TNETDxxxx Software Support
++ * Copyright (c) 2002,2003 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ * FILE:
++ *
++ * DESCRIPTION:
++ * This file contains documentation for the CPMAC
++ *
++ * HISTORY:
++ * @author Michael Hanrahan/Greg Guyotte
++ * @version 1.00
++ * @date 03-Dec-2002
++ *****************************************************************************/
++#ifndef _DOX_CPMAC_H
++#define _DOX_CPMAC_H
++/**
++@page CPMAC_Implementation_Details Version
++
++@copydoc CPMAC_Version
++*/
++
++/**
++@page cpmac_intro Introduction
++
++The CPMAC implementation will support 8 channels for transmit and 8 channel for
++receive. Each of the 8 transmit channels has 1 queue associated with it. It is
++recommended that only 1 channel is used for @c Receive() per processor.
++*/
++
++/**
++@page cpmac_details API Implementation Details
++@par osReceive
++@p Mode parameter
++- The Upper 16 bits of Mode match Word 3 of the Rx Buffer Descriptor
++
++@par halSend
++@p Mode parameter
++- Bits 0-7 contain the Channel Number
++- Bits 8-25 are reserved
++- Bit 26 - if 0, the CRC will be calculated, if 1 the CRC will be Passed
++- Bits 27-31 : reserved
++@section cpmac_keys Control Keys
++
++@par StateChange
++CPHAL calls the OS when a state change is detected.
++OS should check the CPMAC Status. See the Control Key 'Status' for more details.
++
++@par Status
++OS calls the CPHAL to obtain Status information. The Returned status is as follows
++
++@par MaxFrags
++The OS may "Set" or "Get" this value. This defines the maximum
++number of fragments that can be received by the CPMAC Rx port. The default
++value for CPMAC is 2. This provides enough space to receive a maximum
++length packet (1,518 bytes) with the default buffer size of 1518 and any
++amount of RxBufferOffset. If the buffer size is configured to be smaller,
++the OS *MUST* modify this parameter according to the following formula:
++((System Max packet length)/(RxBufSize)) + 1. (The extra 1 fragment is to
++allow for RxBufferOffset)
++
++@code
++// Following defined in "cpswhal_cpmac.h"
++// CPMAC CPHAL STATUS
++#define CPMAC_STATUS_LINK (1 << 0)
++#define CPMAC_STATUS_LINK_DUPLEX (1 << 1) // 0 - HD, 1 - FD
++#define CPMAC_STATUS_LINK_SPEED (1 << 2) // 0 - 10, 1 - 100
++
++// ADAPTER CHECK Codes
++#define CPMAC_STATUS_ADAPTER_CHECK (1 << 7)
++#define CPMAC_STATUS_HOST_ERR_DIRECTION (1 << 8) // 0 - Tx, 1 - Rx
++#define CPMAC_STATUS_HOST_ERR_CODE (0xF << 9) See CPMAC Guide
++#define CPMAC_STATUS_HOST_ERR_CH (0x7 << 13) See CPMAC Guide
++@endcode
++
++@code
++void osStateChange(OS_DEVICE *OsDev)
++ {
++ int status;
++ OsDev->HalFunc->Control(OsDev->HalDev, "Status", hcGet, &status);
++ if(status & CPMAC_STATUS_ADAPTER_CHECK)
++ {
++ printf("[osStateChange[%d]] HAL notified OS of AdapterCheck (Link Status 0x%08X)\n", OsDev->port, status);
++ adaptercheck(OsDev->port);
++ }
++ else
++ {
++ printf("[osStateChange[%d]] HAL notified OS of State Change (Link Status %s)\n", OsDev->port, (status & CPMAC_STATUS_LINK) ? "Up" : "Down");
++ if(status & CPMAC_STATUS_LINK)
++ {
++ printf("Speed %s, Duplex %s\n",
++ status & CPMAC_STATUS_LINK_SPEED ? "100" : "10",
++ status & CPMAC_STATUS_LINK_DUPLEX ? "FD" : "HD");
++ }
++ }
++@endcode
++
++@par Tick
++ The CPHAL calls the OS to set the interval for calling halTick()<BR>
++ Note: Predefined value hcTick now recommended for use.
++@code
++*** Example Code ***
++
++*** CPHAL code ***
++int Ticks;
++HalDev->OsFunc->Control(HalDev->OsDev, hcTick, hcSet, &Ticks);
++
++*** OS code ***
++ ..
++ if(osStrcmpi(pszKey, hcTick) == 0)
++ {
++ if(osStrcmpi(pszAction, hcSet) == 0)
++ {
++ // Enable the Tick Interval
++ if(*(unsigned int *) ParmValue)
++ printf("osTickSet: Interval = %d ticks\n", Interval);
++ }
++ else
++ if(osStrcmpi(pszAction, hcClear) == 0)
++ {
++ // Request disabling of the Tick Timer, ParmValue is ignored
++ }
++ }
++@endcode
++
++@par The following information can be obtained by the OS via 'Get'
++
++- StatsDump : OS supplies pointer to an 36 element unsigned int array
++CPHAL will populate the array with the current Statistics values.<BR>
++Note: all hcXXXX values are predefined and should be used by the OS.
++
++- hcPhyNum : Returns the PHY number.
++- hcCpmacBase : Returns the base-address of the CPMAC device
++- hcCpmacSize : Returns size of the CPMAC memory map
++
++
++@par Phy Register Communication
++
++halControl() is used to read and write the Phy Registers via the key hcPhyAccess
++
++Both reading and writing the Phy registers involve setting the Value parameter of halControl()
++<BR>
++Value is a 32-bit value with bits partioned as follows
++<BR>
++
++ 0 - 4 Phy Number <BR>
++ 5 - 9 Phy Register <BR>
++ 10 - 15 reserved <BR>
++ 16 - 31 Data (write only)
++<BR>
++
++
++<B>Reading the Phy register</B>
++
++@code
++ bit32u Value;
++ bit32u RegAddr;
++ bit32u PhyNum;
++ bit32u PhyRegisterData;
++
++ // Read Phy 31, register 20
++
++ PhyNum = 31;
++ RegAddr = 20;
++
++ Value = (RegAddr << 5);
++ Value |= (PhyNum & 0x1F);
++
++ rc = HalFunc->Control(HalDev, hcPhyAccess, hcGet, (bit32u *) &Value)
++ If(rc == 0)
++ {
++ // Value is overwriten with the value in Register 20 of Phy number 31.
++ PhyRegisterData = Value;
++ }
++@endcode
++
++<B>Writing the Phy register</B>
++@code
++ bit32u Value;
++ bit32u RegAddr;
++ bit32u PhyNum;
++ bit32u PhyRegisterData;
++
++ // Reset Phy 23
++
++ PhyNum = 23;
++ RegAddr = 0;
++ PhyRegisterData = 0x8000; // Reset bit set
++
++ Value = (RegAddr << 5);
++ Value |= (PhyNum & 0x1F);
++ Value |= (PhyRegisterData << 16);
++
++ rc = HalFunc->Control(HalDev, hcPhyAccess, hcSet, (bit32u *) &Value)
++
++ // Check is reset if done
++
++ PhyNum = 23;
++ RegAddr = 0;
++
++ Value = (RegAddr << 5);
++ Value |= (PhyNum & 0x1F);
++
++ rc = HalFunc->Control(HalDev, hcPhyAccess, hcGet, (bit32u *) &Value)
++
++ If(rc == 0)
++ {
++ // Value is overwriten with the value in Register 0 of Phy number 23.
++ PhyRegisterData = Value;
++ if((PhyRegisterData & 0x8000) == 0)
++ ResetIsComplete;
++ }
++
++@endcode
++<B>
++*** Example Showing turning values off/on ***
++<BR>
++</B>
++
++@code
++
++int On=1;
++int Off=0;
++ # Turn On loopback
++ OsDev->HalFunc->Control(OsDev->HalDev, "CTRL_LOOPBACK", hcSet, (int*) &On);
++
++ # Turn off RX Flow
++ OsDev->HalFunc->Control(OsDev->HalDev, "RX_FLOW_EN", hcSet, (int*) &Off);
++@endcode
++
++@par CPMAC Configurable Parameters
++
++- RX_PASS_CRC : See MBP_Enable description
++- RX_QOS_EN : See MBP_Enable description
++- RX_NO_CHAIN : See MBP_Enable description
++- RX_CMF_EN : See MBP_Enable description
++- RX_CSF_EN : See MBP_Enable description
++- RX_CEF_EN : See MBP_Enable description
++- RX_CAF_EN : See MBP_Enable description
++- RX_PROM_CH : See MBP_Enable description
++- RX_BROAD_EN : See MBP_Enable description
++- RX_BROAD_CH : See MBP_Enable description
++- RX_MULT_EN : See MBP_Enable description
++- RX_MULT_CH : See MBP_Enable description
++
++- TX_PTYPE : See MacControl description
++- TX_PACE : See MacControl description
++- TX_FLOW_EN : See MacControl description
++- RX_FLOW_EN : See MacControl description
++- CTRL_LOOPBACK : See MacControl description
++
++- RX_MAXLEN : See CPMAC Guide
++- RX_FILTERLOWTHRESH : See CPMAC Guide
++- RX0_FLOWTHRESH : See CPMAC Guide
++- RX_UNICAST_SET : See CPMAC Guide
++- RX_UNICAST_CLEAR : See CPMAC Guide
++
++@par Multicast Support
++- RX_MULTI_ALL : When used with hcSet, sets all the Hash Bits. When used
++with hcClear clears all the Hash Bits.
++- RX_MULTI_SINGLE : When used with hcSet, adds the Hashed Mac Address. When used
++with hcClear deletes the Hashed Mac Address.
++Note: Support will be added to keep track of Single additions and deletions.
++
++@code
++*** Example Code ***
++
++*** OS code ***
++ bit8u MacAddress[6];
++ MacAddress[0] = 0x80;
++ MacAddress[1] = 0x12;
++ MacAddress[2] = 0x34;
++ MacAddress[3] = 0x56;
++ MacAddress[4] = 0x78;
++ MacAddress[5] = 0x78;
++ OsDev->HalFunc->Control(OsDev->HalDev, "RX_MULTI_SINGLE", hcSet, (bit8u*) &MacAddress);
++ OsDev->HalFunc->Control(OsDev->HalDev, "RX_MULTI_SINGLE", hcClear, (bit8u*) &MacAddress);
++ OsDev->HalFunc->Control(OsDev->HalDev, "RX_MULTI_ALL", hcSet, NULL);
++ OsDev->HalFunc->Control(OsDev->HalDev, "RX_MULTI_ALL", hcClear, NULL);
++@endcode
++@par MdioConnect Fields
++<BR>
++- "MdioConnect" : The OS can set the Phy connection using this key. The default connection is Auto-Negotiation ON, All modes possible.
++
++
++- _CPMDIO_HD <----- Allow Half Duplex, default is 1 (On)
++- _CPMDIO_FD <----- Allow Full Duplex, default is 1 (On)
++- _CPMDIO_10 <----- Allow 10 Mbs, default is 1 (On)
++- _CPMDIO_100 <----- Allow 100 Mbs, default is 1 (On)
++- _CPMDIO_NEG_OFF <----- Turn off Auto Negotiation, default is 0 (Auto Neg is on)
++- _CPMDIO_NOPHY <----- Set for use with Marvel-type switch, default is 0 (Phy present)
++- _CPMDIO_AUTOMDIX <---- Enables Auto Mdix (in conjunction with MdixMask), default is 1 (On)
++
++Note: When _CPMDIO_NOPHY is set, CPMAC will report being linked at 100/FD. Reported PhyNum will be 0xFFFFFFFF
++
++@par Setting CPMAC for use with a Marvel-type Switch
++@code
++ bit32u MdioConnect;
++
++ MdioConnect = _CPMDIO_NOPHY;
++ OsDev->HalFunc->Control(OsDev->HalDev, "MdioConnect", hcSet, (bit32u*) &MdioConnect);
++@endcode
++
++@par OS Support for MDIO
++@p The OS will need to supply the following values which the CPHAL will request via halControl()
++<BR>
++- MdioBusFrequency : The frequency of the BUS that MDIO is on (requested via hcMdioBusFrequency)
++<BR>
++- MdioClockFrequency : The desired Clock Frequency that MDIO qill operate at (requested via hcMdioClockFrequency)
++*/
++
++/**
++@page cpmac_conf DeviceFindxxx() Parameters
++
++These are some of the parameters that the CPMAC will request via the DeviceFindxxx() functions -
++<BR>
++- "Mlink" : bit mask indicating what link status method Phy is using. Default is MDIO state machine (0x0)
++- "PhyMask" : bit mask indicating PhyNums used by this CPMAC (e.g 0x8000000, PhyNum is 31)
++- "MdixMask" : bit mask indicating which Phys support AutoMdix. Default is 0x0 (None)
++<BR>
++@par Example cpmac definition from the options.conf for the Sangam VDB
++<BR>
++- cpmac( id=eth0, base=0xA8610000, size=0x800, reset_bit=17, int_line=19, PhyMask=0x80000000, MLink=0, MdixMask=0 )
++*/
++
++/**
++@page auto_mdix Auto Mdix Support
++
++Auto Mdix selection is controlled by two elements in the CPMAC. First the OS can turn Auto Midx On or Off by the use of the
++MdioConnect field, _CPMDIO_AUTOMDIX. This is defaulted ON. For actual Auto Mdix operation the Phy must also be Auto Mdix capable.
++This is specified by the DeviceFindxxx() field, "MdixMask" (supplied as the variable hcMdixMask).
++If both these fields are set then the CPMDIO state machine will be enabled for Auto Mdix checking.
++If a switch to MDI or MDIX mode is needed, the CPMAC will signal this to the OS via Control() using
++the hcMdioMdixSwitch key.
++
++@par OS example for responding to a Mdix Switch Request
++<BR>
++@code
++if(osStrcmpi(pszKey, hcMdioMdixSwitch) == 0) // See if key is Mdix Switch Request
++ {
++ if(osStrcmpi(pszAction, hcSet) == 0) // Only respond to Set requests
++ {
++
++ bit32u Mdix;
++
++ Mdix = *(bit32u *) ParmValue; // Extract requested Mode
++ // 0 : MDI
++ // 1 : MDIX
++ if(Mdix)
++ osSetPhyIntoMdixMode(); // Device specific logic
++ else
++ osSetPhyIntoMdiMode(); // Device specific logic
++ rc = 0; // Set return code as Successfull
++ }
++@endcode
++*/
++
++/**
++@page cpmac_stats CPMAC Specific Statistics
++
++Statistics level '0' contains all CPMAC specific statistics.
++
++
++*/
++
++/**
++@page Example_Driver_Code
++
++@section example_intro Introduction
++This section provides an in-depth code example for driver implementations. The code
++below illustrates the use of the CPMAC HAL, but is equally applicable to any CPHAL
++implementation. Note: the CPHAl constants hcGet, hcSet etc., are currently available for use with teh CPMAC module.
++Other modules should continue to use pszGET, etc. until these are made generally available.
++
++@par Pull Model Example
++
++@code
++
++#define _CPHAL_CPMAC
++
++typedef struct _os_device_s OS_DEVICE;
++typedef struct _os_receive_s OS_RECEIVEINFO;
++typedef struct _os_send_s OS_SENDINFO;
++typedef struct _os_setup_s OS_SETUP;
++
++#include "cpswhal_cpmac.h"
++
++#define dbgPrintf printf
++
++typedef struct _os_device_s
++{
++ HAL_DEVICE *HalDev;
++ HAL_FUNCTIONS *HalFunc;
++ OS_FUNCTIONS *OsFunc;
++ OS_SETUP *OsSetup;
++ bit32u Interrupt;
++ int (*halIsr)(HAL_DEVICE *HalDev, int*);
++ int ModulePort;
++ int Protocol;
++ int LinkStatus; // 0-> down, otherwise up
++}os_device_s;
++
++typedef struct _os_receive_s
++{
++ HAL_RECEIVEINFO *HalReceiveInfo;
++ char *ReceiveBuffer;
++ OS_DEVICE *OsDev;
++}os_receive_s;
++
++typedef struct _os_send_s
++{
++ OS_DEVICE *OsDev;
++}os_send_s;
++
++typedef struct _os_setup_s
++{
++ OS_DEVICE *OsDev;
++}os_setup_s;
++
++
++
++void FlowForCphal(OS_DEVICE *OsDev)
++{
++ CHANNEL_INFO ChannelInfo;
++ int nChannels = 200;
++ int halFuncSize;
++ int rc;
++
++ // Populate OsFunc structure
++ rc = osInitModule(OsDev);
++
++ if(rc)
++ {
++ sprintf(bufTmp, "%s: return code from osInitModule:'0x%08X'", __FUNCTION__, rc);
++ errorout(bufTmp);
++ }
++
++
++ // OS-Cphal handshake
++ rc = halCpmacInitModule(&OsDev->HalDev, OsDev, &OsDev->HalFunc, OsDev->OsFunc,
++ sizeof(OS_FUNCTIONS), &halFuncSize, OsDev->ModulePort);
++
++ if(rc)
++ {
++ sprintf(bufTmp, "%s: return code from halCpmacInitModule:'0x%08X'", __FUNCTION__, rc);
++ errorout(bufTmp);
++ }
++
++ // See if hardware module exists
++ rc = OsDev->HalFunc->Probe(OsDev->HalDev);
++
++ if(rc)
++ {
++ sprintf(bufTmp, "%s: return code from Probe:'0x%08X'", __FUNCTION__, rc);
++ errorout(bufTmp);
++ }
++
++ // Initialize hardware module
++ rc = OsDev->HalFunc->Init(OsDev->HalDev);
++
++ if(rc)
++ {
++ sprintf(bufTmp, "%s: return code from Init:'0x%08X'", __FUNCTION__, rc);
++ errorout(bufTmp);
++ }
++
++ // Setup Channel Information (Tranmsit, channel 0)
++ ChannelInfo.Channel = 0;
++ ChannelInfo.Direction = DIRECTION_TX;
++ ChannelInfo.TxNumBuffers = nChannels;
++ ChannelInfo.TxNumQueues = 1;
++ ChannelInfo.TxServiceMax = nChannels/3;
++
++ rc = OsDev->HalFunc->ChannelSetup(OsDev->HalDev, &ChannelInfo, OsDev->OsSetup);
++
++ // Setup Channel Information (Receive, channel 0)
++ ChannelInfo.Channel = 0;
++ ChannelInfo.Direction = DIRECTION_RX;
++ ChannelInfo.RxBufSize = 1518;
++ ChannelInfo.RxBufferOffset = 0;
++ ChannelInfo.RxNumBuffers = 2*nChannels;
++ ChannelInfo.RxServiceMax = nChannels/3;
++
++ rc = OsDev->HalFunc->ChannelSetup(OsDev->HalDev, &ChannelInfo, OsDev->OsSetup);
++
++ // Open the hardware module
++ rc = OsDev->HalFunc->Open(OsDev->HalDev);
++
++ // Module now ready to Send/Receive data
++}
++
++
++int osInitModule(OS_FUNCTIONS **pOsFunc)
++ {
++ OS_FUNCTIONS *OsFunc;
++
++ OsFunc = (OS_FUNCTIONS *) malloc(sizeof(OS_FUNCTIONS));
++ if (!OsFunc)
++ return (-1);
++
++ *pOsFunc = OsFunc;
++
++ OsFunc->CriticalOff = osCriticalOff;
++ OsFunc->CriticalOn = osCriticalOn;
++ OsFunc->DataCacheHitInvalidate = osDataCacheHitInvalidate;
++ OsFunc->DataCacheHitWriteback = osDataCacheHitWriteback;
++ OsFunc->DeviceFindInfo = osDeviceFindInfo;
++ OsFunc->DeviceFindParmUint = osDeviceFindParmUint;
++ OsFunc->DeviceFindParmValue = osDeviceFindParmValue;
++ OsFunc->Free = osFree;
++ OsFunc->FreeDev = osFreeDev;
++ OsFunc->FreeDmaXfer = osFreeDmaXfer;
++ OsFunc->FreeRxBuffer = osFreeRxBuffer;
++ OsFunc->IsrRegister = osIsrRegister;
++ OsFunc->IsrUnRegister = osIsrUnRegister;
++ OsFunc->Malloc = osMalloc;
++ OsFunc->MallocDev = osMallocDev;
++ OsFunc->MallocDmaXfer = osMallocDmaXfer;
++ OsFunc->MallocRxBuffer = osMallocRxBuffer;
++
++
++ OsFunc->Memset = memset;
++ OsFunc->Printf = printf;
++ OsFunc->Sprintf = sprintf;
++ OsFunc->Strcmpi = osStrcmpi;
++ OsFunc->Strlen = strlen;
++ OsFunc->Strstr = strstr;
++ OsFunc->Strtoul = strtoul;
++
++ OsFunc->Control = osControl;
++ OsFunc->Receive = osReceive;
++ OsFunc->SendComplete = osSendComplete;
++ OsFunc->TeardownComplete = osTearDownComplete;
++
++ return(0);
++ }
++
++
++int osReceive(OS_DEVICE *OsDev,FRAGLIST *Fraglist,bit32u FragCount,bit32u PacketSize,HAL_RECEIVEINFO *halInfo, bit32u mode)
++ {
++ OS_RECEIVEINFO *skb = (OS_RECEIVEINFO *)Fraglist[0].OsInfo;
++ dcache_i((char *)Fraglist->data, Fraglist->len);
++ OsDev->HalFunc->RxReturn(halInfo,0);
++ return(0);
++ }
++
++int osSendComplete(OS_SENDINFO *skb)
++ {
++ return(0);
++ }
++
++
++static void *osMallocRxBuffer(bit32u Size,void *MemBase, bit32u MemRange,
++ OS_SETUP *OsSetup, HAL_RECEIVEINFO *HalReceiveInfo,
++ OS_RECEIVEINFO **OsReceiveInfo, OS_DEVICE *OsDev )
++ {
++ void *HalBuffer;
++ OS_RECEIVEINFO *OsPriv;
++
++ HalBuffer=malloc(Size);
++ if (!HalBuffer)
++ {
++ return(0);
++ }
++
++ // Malloc the OS block
++ *OsReceiveInfo = malloc(sizeof(OS_RECEIVEINFO));
++ if (!*OsReceiveInfo)
++ {
++ free(HalBuffer);
++ return(0);
++ }
++
++ // Initialize the new buffer descriptor
++ OsPriv = *OsReceiveInfo;
++ OsPriv->OsDev = OsDev;
++ OsPriv->ReceiveBuffer = HalBuffer;
++ OsPriv->HalReceiveInfo = HalReceiveInfo;
++
++ return(HalBuffer);
++ }
++
++
++void SendBuffer(OS_DEVICE *OsDev, char *Buffer, int Size)
++{
++ FRAGLIST Fraglist;
++ bit32u FragCount;
++
++ tcb_pending++;
++ Fraglist.len = Size;
++ Fraglist.data = (unsigned *) Buffer;
++ FragCount = 1;
++ mode = 0; // Channel 0
++
++ dcache_wb(Fraglist.data, Fraglist.len);
++ OsDev->HalFunc->Send(OsDev->HalDev, &Fraglist, FragCount, Size, (OS_SENDINFO *) Buffer, mode);
++}
++
++
++void osStateChange(OS_DEVICE *OsDev)
++ {
++ int status;
++ int LinkStatus;
++ OsDev->HalFunc->Control(OsDev->HalDev, "Status", hcGet, &status);
++ if(status & CPMAC_STATUS_ADAPTER_CHECK)
++ {
++ // Adapter Check, take appropiate action
++ }
++ else
++ {
++ LinkStatus = status & CPMAC_STATUS_LINK;
++ if(LinkStatus != OsDev->LinkStatus)
++ {
++ dbgPrintf("\n%s:Link %s for inst %d Speed %s, Duplex %s\n",
++ __FUNCTION__,
++ LinkStatus ? "up" : "down",
++ OsDev->ModulePort,
++ status & CPMAC_STATUS_LINK_SPEED ? "100" : "10",
++ status & CPMAC_STATUS_LINK_DUPLEX ? "FD" : "HD");
++ OsDev->LinkStatus = LinkStatus;
++ }
++ }
++ }
++
++
++int osControl(OS_DEVICE *OsDev, const char *pszKey, const char* pszAction, void *ParmValue)
++ {
++ int rc=-1;
++
++ if (osStrcmpi(pszKey, hcCpuFrequency) == 0)
++ {
++ if(osStrcmpi(pszAction, hcGet) == 0)
++ {
++ *(bit32u*) ParmValue = cpufreq;
++ rc = 0;
++ }
++ }
++ if (osStrcmpi(pszKey, hcMdioBusFrequency) == 0)
++ {
++ if(osStrcmpi(pszAction, hcGet) == 0)
++ {
++ *(bit32u *)ParmValue = MdioBusFrequency;
++ rc = 0;
++ }
++ }
++if (osStrcmpi(pszKey, hcMdioClockFrequency) == 0)
++ {
++ if(osStrcmpi(pszAction, hcGet) == 0)
++ {
++ *(bit32u *)ParmValue = MdioClockFrequency;
++ rc = 0;
++ }
++ }
++
++ if (osStrcmpi(pszKey, hcTick) == 0)
++ {
++ if(osStrcmpi(pszAction, hcSet) == 0)
++ {
++ osTickSetInterval(OsDev, *(unsigned int *) ParmValue);
++ rc = 0;
++ }
++ else
++ if(osStrcmpi(pszAction, hcClear) == 0)
++ {
++ osTickDisable(OsDev);
++ rc = 0;
++ }
++ }
++
++ if (osStrcmpi(pszKey, "SioFlush") == 0)
++ {
++ MySioFlush();
++ rc = 0;
++ }
++
++ if (osStrcmpi(pszKey, "StateChange") == 0)
++ {
++ osStateChange(OsDev);
++ rc = 0;
++ }
++
++ if (osStrcmpi(pszKey, "Sleep") == 0)
++ {
++ osSleep(*(int *)ParmValue);
++ rc = 0;
++ }
++ return(rc);
++ }
++
++@endcode
++
++
++@par Push Model Example (Currently Eswitch ONLY)
++
++@code
++
++typedef struct _os_device_s OS_DEVICE;
++typedef struct _os_receive_s OS_RECEIVEINFO;
++typedef struct _os_send_s OS_SENDINFO;
++typedef struct _os_setup_s OS_SETUP;
++
++#include "cpswhal.h" //Get glogal HAL stuff
++#include "cpswhaleswitch.h" //Get device specific hal stuff
++
++
++typedef struct _os_device_s
++{
++ HAL_DEVICE *HalDev;
++ HAL_FUNCTIONS *HalFunc;
++ OS_FUNCTIONS *OsFunc;
++ OS_SETUP *OsSetup;
++ bit32u Interrupt;
++ int (*halIsr)(HAL_DEVICE *HalDev, int*);
++ int ModulePort;
++ int Protocol;
++ int LinkStatus; // 0-> down, otherwise up
++}os_device_s;
++
++typedef struct _os_receive_s
++{
++ HAL_RECEIVEINFO *HalReceiveInfo;
++ char *ReceiveBuffer;
++ OS_DEVICE *OsDev;
++}os_receive_s;
++
++typedef struct _os_send_s
++{
++ OS_DEVICE *OsDev;
++}os_send_s;
++
++typedef struct _os_setup_s
++{
++ OS_DEVICE *OsDev;
++}os_setup_s;
++
++
++
++void FlowForCphal(OS_DEVICE *OsDev)
++{
++CHANNEL_INFO ChannelInfo;
++ int nChannels = 200;
++ int halFuncSize;
++ int rc;
++
++ // Populate OsFunc structure
++ rc = osInitModule(OsDev);
++
++ if(rc)
++ {
++ sprintf(bufTmp, "%s: return code from osInitModule:'0x%08X'", __FUNCTION__, rc);
++ errorout(bufTmp);
++ }
++
++
++ // OS-Cphal handshake
++ rc = cpswHalEswitchInitModule(&OsDev->HalDev, OsDev, &OsDev->HalFunc, OsDev->OsFunc,
++ sizeof(OS_FUNCTIONS), &halFuncSize, OsDev->ModulePort);
++
++ if(rc)
++ {
++ sprintf(bufTmp, "%s: return code from cpswHalEswitchInitModule:'0x%08X'", __FUNCTION__, rc);
++ errorout(bufTmp);
++ }
++
++
++ ChannelInfo.Channel = 7;
++ ChannelInfo.Direction = DIRECTION_RX;
++ ChanInfo.Receive = osReceiveSS; // Specify function to receive data for this channel
++
++ rc = OsDev->HalFunc->ChannelSetup(OsDev->HalDev, &ChannelInfo, OsDev->OsSetup);
++
++ MyConfig.debug=0;
++ MyConfig.CpuFrequency = CpuFreq;
++ MyConfig.EswitchFrequency = EswitchFreq;
++ MyConfig.ResetBase = 0xa8611600;
++ MyConfig.MacAddress = MacAddr;
++
++ MyConfig.EswitchResetBit= 27;
++ MyConfig.Cpmac0ResetBit = 17;
++ MyConfig.Cpmac1ResetBit = 21;
++ MyConfig.MdioResetBit = 22;
++ MyConfig.Phy0ResetBit = 26;
++ MyConfig.Phy1ResetBit = 28;
++ MyConfig.HdmaResetBit = 13;
++ MyConfig.Cpmac0IntBit = 19;
++ MyConfig.Cpmac1IntBit = 33;
++ MyConfig.EswitchIntBit = 27;
++ MyConfig.EswitchBase = 0xa8640000;
++ MyConfig.EswitchBufferSize = 64;
++ MyConfig.EswitchHostBufCount = 0;
++ MyConfig.EswitchDefaultCamSize = 64;
++ MyConfig.EswitchOverFlowCount = 200;
++ MyConfig.EswitchOverFlowSize = 256;
++
++
++
++
++ rc=EswitchConfig(HalDev,HalFunc,&MyConfig);
++
++
++ // Open the hardware module
++ rc = OsDev->HalFunc->Open(OsDev->HalDev);
++
++ // Module now ready to Send/Receive data
++}
++
++
++int EswitchConfig(HAL_DEVICE *HalDev, HAL_FUNCTIONS *HalFunc, ESWITCH_CONFIG *Config)
++{
++ bit32u sts;
++ sts = 0;
++
++ sts |= cpswhalPushBin(hcdebug, Config->debug);
++ sts |= cpswhalPushBin(hcCpuFrequency , Config->CpuFrequency );
++ sts |= cpswhalPushBin(hcEswitchFrequency , Config->EswitchFrequency );
++ sts |= cpswhalPushBin(hcResetBase , Config->ResetBase );
++ sts |= cpswhalPushBin(hcMacAddress , Config->MacAddress );
++ sts |= cpswhalPushBin(hcEswitchResetBit, Config->EswitchResetBit);
++ sts |= cpswhalPushBin(hcCpmac0ResetBit , Config->Cpmac0ResetBit );
++ sts |= cpswhalPushBin(hcCpmac1ResetBit , Config->Cpmac1ResetBit );
++ sts |= cpswhalPushBin(hcMdioResetBit , Config->MdioResetBit );
++ sts |= cpswhalPushBin(hcPhy0ResetBit , Config->Phy0ResetBit );
++ sts |= cpswhalPushBin(hcPhy1ResetBit , Config->Phy1ResetBit );
++ sts |= cpswhalPushBin(hcHdmaResetBit , Config->HdmaResetBit );
++ sts |= cpswhalPushBin(hcCpmac0IntBit , Config->Cpmac0IntBit );
++ sts |= cpswhalPushBin(hcCpmac1IntBit , Config->Cpmac1IntBit );
++ sts |= cpswhalPushBin(hcEswitchIntBit , Config->EswitchIntBit );
++ sts |= cpswhalPushBin(hcEswitchBase , Config->EswitchBase );
++ sts |= cpswhalPushBin(hcEswitchBufferSize , Config->EswitchBufferSize );
++ sts |= cpswhalPushBin(hcEswitchHostBufCount , Config->EswitchHostBufCount );
++ sts |= cpswhalPushBin(hcEswitchDefaultCamSize , Config->EswitchDefaultCamSize );
++ sts |= cpswhalPushBin(hcEswitchOverFlowCount , Config->EswitchOverFlowCount );
++ sts |= cpswhalPushBin(hcEswitchOverFlowSize , Config->EswitchOverFlowSize );
++ return(sts);
++}
++
++
++
++@endcode
++*/
++
++#endif
+diff -urN linux.old/drivers/net/avalanche_cpmac/ec_errors_cpmac.h linux.dev/drivers/net/avalanche_cpmac/ec_errors_cpmac.h
+--- linux.old/drivers/net/avalanche_cpmac/ec_errors_cpmac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/ec_errors_cpmac.h 2005-07-12 02:48:42.051592000 +0200
+@@ -0,0 +1,118 @@
++/***************************************************************************
++ Copyright(c) 2001, Texas Instruments Incorporated. All Rights Reserved.
++
++ FILE: ec_errors.h
++
++ DESCRIPTION:
++ This file contains definitions and function declarations for
++ error code support.
++
++ HISTORY:
++ 14Dec00 MJH Added masking to EC_CLASS etc macros
++ 17Sep02 GSG Added HAL support (new class&devices)
++ 03Oct02 GSG Removed C++ style comments
++***************************************************************************/
++#ifndef _INC_EC_ERRORS
++#define _INC_EC_ERRORS
++
++/*
++ 31 - CRITICAL
++ 30-28 - CLASS (ie. DIAG, KERNEL, FLASH, etc)
++ 27-24 - INSTANCE (ie. 1, 2, 3, etc )
++ 23-16 - DEVICE (ie. EMAC, IIC, etc)
++ 15-08 - FUNCTION (ie. RX, TX, INIT, etc)
++ 07-00 - ERROR CODE (ie. NO_BASE, FILE_NOT_FOUND, etc )
++*/
++
++/*---------------------------------------------------------------------------
++ Useful defines for accessing fields within error code
++---------------------------------------------------------------------------*/
++#define CRITICAL_SHIFT 31
++#define CLASS_SHIFT 28
++#define INST_SHIFT 24
++#define DEVICE_SHIFT 16
++#define FUNCTION_SHIFT 8
++#define ERROR_CODE_SHIFT 0
++
++#define CRITICAL_MASK 1
++#define CLASS_MASK 0x07
++#define DEVICE_MASK 0xFF
++#define INST_MASK 0x0F
++#define FUNCTION_MASK 0xFF
++#define ERROR_CODE_MASK 0xFF
++
++#define EC_CLASS(val) ((val&CLASS_MASK) << CLASS_SHIFT)
++#define EC_DEVICE(val) ((val&DEVICE_MASK) << DEVICE_SHIFT)
++#define EC_INST(val) ((val&INST_MASK) << INST_SHIFT)
++#define EC_FUNC(val) ((val&FUNCTION_MASK) << FUNCTION_SHIFT)
++#define EC_ERR(val) ((val&ERROR_CODE_MASK) << ERROR_CODE_SHIFT)
++
++/*---------------------------------------------------------------------------
++ Operation classes
++---------------------------------------------------------------------------*/
++#define EC_HAL EC_CLASS(0)
++#define EC_DIAG EC_CLASS(8)
++
++/*---------------------------------------------------------------------------
++ Device types
++---------------------------------------------------------------------------*/
++#define EC_DEV_EMAC EC_DEVICE(1)
++#define EC_DEV_IIC EC_DEVICE(2)
++#define EC_DEV_RESET EC_DEVICE(3)
++#define EC_DEV_ATMSAR EC_DEVICE(4)
++#define EC_DEV_MEM EC_DEVICE(5)
++#define EC_DEV_DES EC_DEVICE(6)
++#define EC_DEV_DMA EC_DEVICE(7)
++#define EC_DEV_DSP EC_DEVICE(8)
++#define EC_DEV_TMR EC_DEVICE(9)
++#define EC_DEV_WDT EC_DEVICE(10)
++#define EC_DEV_DCL EC_DEVICE(11)
++#define EC_DEV_BBIF EC_DEVICE(12)
++#define EC_DEV_PCI EC_DEVICE(13)
++#define EC_DEV_XBUS EC_DEVICE(14)
++#define EC_DEV_DSLIF EC_DEVICE(15)
++#define EC_DEV_USB EC_DEVICE(16)
++#define EC_DEV_CLKC EC_DEVICE(17)
++#define EC_DEV_RAPTOR EC_DEVICE(18)
++#define EC_DEV_DSPC EC_DEVICE(19)
++#define EC_DEV_INTC EC_DEVICE(20)
++#define EC_DEV_GPIO EC_DEVICE(21)
++#define EC_DEV_BIST EC_DEVICE(22)
++#define EC_DEV_HDLC EC_DEVICE(23)
++#define EC_DEV_UART EC_DEVICE(24)
++#define EC_DEV_VOIC EC_DEVICE(25)
++/* 9.17.02 (new HAL modules) */
++#define EC_DEV_CPSAR EC_DEVICE(0x1A)
++#define EC_DEV_AAL5 EC_DEVICE(0x1B)
++#define EC_DEV_AAL2 EC_DEVICE(0x1C)
++#define EC_DEV_CPMAC EC_DEVICE(0x1D)
++#define EC_DEV_VDMA EC_DEVICE(0x1E)
++#define EC_DEV_VLYNQ EC_DEVICE(0x1F)
++#define EC_DEV_CPPI EC_DEVICE(0x20)
++#define EC_DEV_CPMDIO EC_DEVICE(0x21)
++
++/*---------------------------------------------------------------------------
++ Function types
++---------------------------------------------------------------------------*/
++#define EC_FUNC_READ_CONF EC_FUNC(1)
++#define EC_FUNC_INIT EC_FUNC(2)
++
++/*---------------------------------------------------------------------------
++ Error codes
++---------------------------------------------------------------------------*/
++#define EC_CRITICAL (1<<CRITICAL_SHIFT)
++#define EC_NO_ERRORS 0
++#define EC_VAL_NO_BASE EC_ERR(1)
++#define EC_VAL_NO_RESET_BIT EC_ERR(2)
++#define EC_VAL_NO_RESET EC_ERR(3)
++#define EC_VAL_BAD_BASE EC_ERR(4)
++#define EC_VAL_MALLOCFAILED EC_ERR(5)
++#define EC_VAL_NO_RESETBASE EC_ERR(6)
++#define EC_DEVICE_NOT_FOUND EC_ERR(7)
++
++/*---------------------------------------------------------------------------
++ Function declarations
++---------------------------------------------------------------------------*/
++extern void ec_log_error( unsigned int );
++
++#endif /* _INC_EC_ERRORS */
+diff -urN linux.old/drivers/net/avalanche_cpmac/hcpmac.c linux.dev/drivers/net/avalanche_cpmac/hcpmac.c
+--- linux.old/drivers/net/avalanche_cpmac/hcpmac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/hcpmac.c 2005-07-12 02:48:42.174574000 +0200
+@@ -0,0 +1,1878 @@
++/******************************************************************************
++ * TNETDxxxx Software Support
++ * Copyright (c) 2002-2004 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ * FILE:
++ *
++ * DESCRIPTION:
++ * This file contains the code for the HAL EMAC Bridge Test
++ *
++ * HISTORY:
++ * xxXxx01 Denis RC1.00 Original Version created.
++ * 22Jan02 Denis/Mick RC1.01 Modified for HAL EMAC API
++ * 24Jan02 Denis/Mick RC1.02 Speed Improvements
++ * 28Jan02 Denis/Mick RC1.16 Made function calls pointers
++ * 28Jan02 Mick RC1.18 Split into separate modules
++ * 29Jan02 Mick RC1.19 Hal include file cleaned up
++ * 15Jul02 Michael Hanrahan RC1.20 Synch'd with Linux Version
++ * 23Sep02 Michael Hanrahan RC1.21 Added CPPI.C
++ * 16Oct02 Michael Hanrahan RC1.22 Added CAF etc to Options.Conf
++ * 09Jan03 Michael Hanrahan RC3.01 Fixed incorrect MDIO check
++ * 01Feb03 Michael Hanrahan RC3.02 Updated for GPIO/PBUSFREQ
++ * 29Mar03 Michael Hanrahan 1.03 Corrected ChannelConfigGet
++ * 29Mar03 Michael Hanrahan 1.03 Removed user setting of TxNumQueues
++ * 23Aug04 Michael Hanrahan 1.7.8 Support for Setting Mac Address
++ * @author Michael Hanrahan
++ * @version 1.02
++ * @date 24-Jan-2002
++ *****************************************************************************/
++#define _HAL_CPMAC
++#define _CPHAL_CPMAC
++#define _CPHAL
++#define __CPHAL_CPMDIO
++
++#include "dox_cpmac.h" /* Documentation information */
++
++/* OS Data Structure definitions */
++
++typedef void OS_PRIVATE;
++typedef void OS_DEVICE;
++typedef void OS_SENDINFO;
++typedef void OS_RECEIVEINFO;
++typedef void OS_SETUP;
++
++/* HAL Data Structure definitions */
++
++typedef struct _phy_device PHY_DEVICE;
++typedef struct hal_device HAL_DEVICE;
++typedef struct hal_private HAL_PRIVATE;
++typedef struct hal_private HAL_RECEIVEINFO;
++
++#include "cpcommon_cpmac.h"
++#include "cpswhal_cpmac.h"
++#include "cpmdio.h"
++#include "hcpmac.h"
++#include "cpmac_reg.h"
++
++
++#define EC_MODULE
++
++/* MDIO Clock Frequency Default Value */
++
++/* Rcb/Tcb Constants */
++
++#define CB_SOF_BIT (1<<31)
++#define CB_EOF_BIT (1<<30)
++#define CB_SOF_AND_EOF_BIT (CB_SOF_BIT|CB_EOF_BIT)
++#define CB_OWNERSHIP_BIT (1<<29)
++#define CB_EOQ_BIT (1<<28)
++#define CB_SIZE_MASK 0x0000ffff
++#define RCB_ERRORS_MASK 0x03fe0000
++
++static char *channel_names[] = CHANNEL_NAMES; /* GSG 11/22 (may change this implementation) */
++
++#define scFound(Module) if (HalDev->State != enDevFound) return (Module|EC_FUNC_CHSETUP|EC_VAL_INVALID_STATE)
++#define scInit(Module) if (HalDev->State < enInitialized) return (Module|EC_FUNC_CHSETUP|EC_VAL_INVALID_STATE)
++#define scOpen(Module) if (HalDev->State < enOpened) return (Module|EC_FUNC_CHSETUP|EC_VAL_INVALID_STATE)
++
++
++
++/********************************************************************
++**
++** L O C A L F U N C T I O N S
++**
++********************************************************************/
++static int halIsr(HAL_DEVICE *HalDev, int *MorePackets);
++static int cpmacRandom(HAL_DEVICE *HalDev);
++static int cpmacRandomRange(HAL_DEVICE *HalDev, int min, int max);
++static int halPacketProcessEnd(HAL_DEVICE *HalDev);
++
++#include "cpcommon_cpmac.c" /*~RC3.02*/
++#include "cppi_cpmac.c"
++#include "cpmdio.c" /*~RC3.02*/
++
++static int MacAddressSave(HAL_DEVICE *HalDev, unsigned char *MacAddr)
++ {
++ int i;
++ int inst = HalDev->inst;
++
++ HalDev->MacAddr = MacAddr;
++
++ if(HalDev->debug)
++ {
++ dbgPrintf("MacAddrSave[%d]: ", inst);
++ for (i=0;i<6;i++)
++ dbgPrintf("%X", HalDev->MacAddr[i]);
++ dbgPrintf("\n");
++ osfuncSioFlush();
++ }
++ return(EC_NO_ERRORS);
++ }
++static int MacAddressSet(HAL_DEVICE *HalDev)
++ {
++ unsigned char *macadr = &HalDev->MacAddr[0];
++ int base = HalDev->dev_base;
++
++ scOpen(EC_CPMAC);
++ CPMAC_MACADDRLO_0(base) = macadr[5];
++ CPMAC_MACADDRMID(base) = macadr[4];
++ CPMAC_MACADDRHI(base) = (macadr[0])|(macadr[1]<<8)|(macadr[2]<<16)|(macadr[3]<<24);
++ if(HalDev->debug)
++ {
++ dbgPrintf("MacAddrSet: MacAddr(%d) %X %X %X\n", HalDev->inst, CPMAC_MACADDRLO_0(base),
++ CPMAC_MACADDRMID(base),
++ CPMAC_MACADDRHI(base));
++
++ dbgPrintf("Start MAC: %d\n",HalDev->dev_base);
++ osfuncSioFlush();
++ }
++ return(EC_NO_ERRORS);
++ }
++
++
++/*
++ Updates the MacHash registers
++*/
++static void MacHashSet(HAL_DEVICE *HalDev)
++ {
++ if(HalDev->State < enOpened)
++ return;
++
++ CPMAC_MACHASH1(HalDev->dev_base) = HalDev->MacHash1;
++ CPMAC_MACHASH2(HalDev->dev_base) = HalDev->MacHash2;
++ if (DBG(11))
++ dbgPrintf("CPMAC[%X]: MacHash1 0x%08X, MacHash2 0x%08X\n", HalDev->dev_base, CPMAC_MACHASH1(HalDev->dev_base), CPMAC_MACHASH2(HalDev->dev_base));
++ }
++
++/*
++ Reads the MacControl register and updates
++ the changable bits. (See MACCONTROL_MASK)
++*/
++static void RxMBP_EnableSet(HAL_DEVICE *HalDev)
++ {
++ bit32u RxMbpEnable;
++ if(HalDev->State < enOpened)
++ return;
++ RxMbpEnable = CPMAC_RX_MBP_ENABLE(HalDev->dev_base);
++ RxMbpEnable &= ~RX_MBP_ENABLE_MASK; /* Clear out updatable bits */
++ RxMbpEnable |= HalDev->RxMbpEnable;
++ CPMAC_RX_MBP_ENABLE(HalDev->dev_base) = RxMbpEnable;
++ }
++/*
++ Reads the MacControl register and updates
++ the changable bits. (See MACCONTROL_MASK)
++*/
++static void MacControlSet(HAL_DEVICE *HalDev)
++ {
++ bit32u MacControl;
++ if(HalDev->State < enOpened)
++ return;
++ MacControl = CPMAC_MACCONTROL(HalDev->dev_base);
++ MacControl &= ~MACCONTROL_MASK; /* Clear out updatable bits */
++ MacControl |= HalDev->MacControl;
++ if(!(MacControl & MII_EN)) /* If Enable is not set just update register */
++ CPMAC_MACCONTROL(HalDev->dev_base) = MacControl;
++ else
++ {
++ if(MacControl & CTRL_LOOPBACK) /* Loopback Set */
++ {
++ /* mii_en is set and loopback is needed,
++ clear mii_en, set loopback, then set mii_en
++ */
++ MacControl &= ~MII_EN; /* Clear MII_EN */
++ CPMAC_MACCONTROL(HalDev->dev_base) = MacControl;
++ CPMAC_MACCONTROL(HalDev->dev_base) |= MII_EN; /* Set MII_EN */
++ HalDev->Linked = 1; /* if in loopback the logically linked */
++ }
++ else /* If Loopback not set just update */
++ {
++ CPMAC_MACCONTROL(HalDev->dev_base) = MacControl;
++ }
++ }
++ if(DBG(0))
++ dbgPrintf("[halMacControlSet]MacControl:%08X\n", CPMAC_MACCONTROL(HalDev->dev_base));
++ }
++static int UnicastSet(HAL_DEVICE *HalDev)
++ {
++ CPMAC_RX_UNICAST_SET(HalDev->dev_base) = HalDev->RxUnicastSet;
++ CPMAC_RX_UNICAST_CLEAR(HalDev->dev_base) = HalDev->RxUnicastClear;
++ return(EC_NO_ERRORS);
++ }
++
++
++static bit32u HashGet(bit8u *Address)
++ {
++ bit32u hash;
++ bit8u tmpval;
++ int i;
++
++ hash = 0;
++ for( i=0; i<2; i++ )
++ {
++ tmpval = *Address++;
++ hash ^= (tmpval>>2)^(tmpval<<4);
++ tmpval = *Address++;
++ hash ^= (tmpval>>4)^(tmpval<<2);
++ tmpval = *Address++;
++ hash ^= (tmpval>>6)^(tmpval);
++ }
++
++ return( hash & 0x3F );
++ }
++
++static void HashAdd(HAL_DEVICE *HalDev, bit8u *MacAddress)
++{
++ bit32u HashValue;
++ bit32u HashBit;
++
++ HashValue = HashGet(MacAddress);
++
++ if(HashValue < 32)
++ {
++ HashBit = (1 << HashValue);
++ HalDev->MacHash1 |= HashBit;
++ }
++ else
++ {
++ HashBit = (1 << (HashValue-32));
++ HalDev->MacHash2 |= HashBit;
++ }
++}
++
++static void HashDel(HAL_DEVICE *HalDev, bit8u *MacAddress)
++{
++ bit32u HashValue;
++ bit32u HashBit;
++
++ HashValue = HashGet(MacAddress);
++
++ if(HashValue < 32)
++ {
++ HashBit = (1 << HashValue);
++ HalDev->MacHash1 &= ~HashBit;
++ }
++ else
++ {
++ HashBit = (1 << (HashValue-32));
++ HalDev->MacHash2 &= ~HashBit;
++ }
++}
++
++/* Replace with an array based on key, with a ptr to the code to do */
++/* e.g. [enRX_PASS_CRC] = {Set, MBP_UPDATE() } */
++static void DuplexUpdate(HAL_DEVICE *HalDev)
++{
++ int base = HalDev->dev_base;
++ PHY_DEVICE *PhyDev = HalDev->PhyDev;
++
++ if(HalDev->State < enOpened)
++ return;
++
++ /* No Phy Condition */
++ if(HalDev->MdioConnect & _CPMDIO_NOPHY) /*MJH+030805*/
++ {
++ /* No Phy condition, always linked */
++ HalDev->Linked = 1;
++ HalDev->EmacSpeed = 1;
++ HalDev->EmacDuplex = 1;
++ HalDev->PhyNum = 0xFFFFFFFF; /* No Phy Num */
++ CPMAC_MACCONTROL(base) |= FULLDUPLEX; /*MJH+030909*/
++ osfuncStateChange();
++ return;
++ }
++
++ if(HalDev->MacControl & CTRL_LOOPBACK) /* Loopback Set */
++ {
++ HalDev->Linked = 1;
++ return;
++ }
++
++ if (HalDev->MdioConnect & _CPMDIO_LOOPBK)
++ {
++ HalDev->Linked = cpMacMdioGetLoopback(HalDev->PhyDev);
++ }
++ else
++ {
++ HalDev->Linked = cpMacMdioGetLinked(HalDev->PhyDev);
++ }
++ if (HalDev->Linked)
++ {
++ /* Retreive Duplex and Speed and the Phy Number */
++ if(HalDev->MdioConnect & _CPMDIO_LOOPBK)
++ HalDev->EmacDuplex = 1;
++ else
++ HalDev->EmacDuplex = cpMacMdioGetDuplex(PhyDev);
++ HalDev->EmacSpeed = cpMacMdioGetSpeed(PhyDev);
++ HalDev->PhyNum = cpMacMdioGetPhyNum(PhyDev);
++
++ if(HalDev->EmacDuplex)
++ CPMAC_MACCONTROL(base) |= FULLDUPLEX;
++ else
++ CPMAC_MACCONTROL(base) &= ~FULLDUPLEX;
++ if(HalDev->debug)
++ dbgPrintf("%d: Phy= %d, Speed=%s, Duplex=%s\n",HalDev->inst,HalDev->PhyNum,(HalDev->EmacSpeed)?"100":"10",(HalDev->EmacDuplex)?"Full":"Half");
++ }
++ if(HalDev->debug)
++ dbgPrintf("DuplexUpdate[%d]: MACCONTROL 0x%08X, %s\n", HalDev->inst, CPMAC_MACCONTROL(base),(HalDev->Linked)?"Linked":"Not Linked");
++}
++static void MdioSetPhyMode(HAL_DEVICE *HalDev)
++ {
++ unsigned int PhyMode;
++ /* Verify proper device state */
++ if (HalDev->State < enOpened)
++ return;
++
++ PhyMode = NWAY_AUTO|NWAY_FD100|NWAY_HD100|NWAY_FD10|NWAY_HD10;
++ if(DBG(0))
++ {
++ dbgPrintf("halSetPhyMode1: MdioConnect:%08X ,", HalDev->MdioConnect);
++ dbgPrintf("PhyMode:%08X Auto:%d, FD10:%d, HD10:%d, FD100:%d, HD100:%d\n", PhyMode,
++ PhyMode&NWAY_AUTO, PhyMode&NWAY_FD10, PhyMode&NWAY_HD10, PhyMode&NWAY_FD100,
++ PhyMode&NWAY_HD100);
++ }
++
++
++ if ( HalDev->MdioConnect & _CPMDIO_NEG_OFF) /* ~RC3.01 */
++ PhyMode &= ~(NWAY_AUTO); /* Disable Auto Neg */
++ if (!(HalDev->MdioConnect & _CPMDIO_HD))
++ PhyMode &= ~(NWAY_HD100|NWAY_HD10); /* Cannot support HD */
++ if (!(HalDev->MdioConnect & _CPMDIO_FD))
++ PhyMode &= ~(NWAY_FD100|NWAY_FD10); /* Cannot support FD */
++ if (!(HalDev->MdioConnect & _CPMDIO_10))
++ PhyMode &= ~(NWAY_HD10|NWAY_FD10); /* Cannot support 10 Mbs */
++ if (!(HalDev->MdioConnect & _CPMDIO_100))
++ PhyMode &= ~(NWAY_HD100|NWAY_FD100); /* Cannot support 100 Mbs */
++
++ if(HalDev->MdioConnect & _CPMDIO_AUTOMDIX) PhyMode |= NWAY_AUTOMDIX; /* Set AutoMdix */
++
++ if (HalDev->CpmacFrequency <= 50000000)
++ PhyMode &= ~(NWAY_FD100|NWAY_HD100); /* Cannot support 100 MBS */
++ if(DBG(7))
++ dbgPrintf("halNeg: PhyMode[0x%08X] %d\n", HalDev->dev_base, PhyMode);
++
++ if(DBG(0))
++ {
++ dbgPrintf("halSetPhyMode2: MdioConnect:%08X ,", HalDev->MdioConnect);
++ dbgPrintf("PhyMode:%08X Auto:%d, FD10:%d, HD10:%d, FD100:%d, HD100:%d\n", PhyMode,
++ PhyMode&NWAY_AUTO, PhyMode&NWAY_FD10, PhyMode&NWAY_HD10, PhyMode&NWAY_FD100,
++ PhyMode&NWAY_HD100);
++ }
++
++
++ cpMacMdioSetPhyMode(HalDev->PhyDev,PhyMode);
++ DuplexUpdate(HalDev);
++ }
++static int StatsClear(HAL_DEVICE *HalDev)
++{
++ int i;
++ MEM_PTR pStats;
++
++ scOpen(EC_CPMAC);
++
++ pStats = pCPMAC_RXGOODFRAMES(HalDev->dev_base);
++ for (i=0;i<STATS_MAX;i++)
++ {
++ *(MEM_PTR)(pStats) = 0xFFFFFFFF;
++ pStats++;
++ }
++
++ return(EC_NO_ERRORS);
++}
++static void StatsDump(HAL_DEVICE *HalDev, void *Value)
++ {
++ MEM_PTR ptrStats;
++ MEM_PTR ptrValue;
++ int i;
++ ptrStats = pCPMAC_RXGOODFRAMES(HalDev->dev_base);
++ ptrValue = (bit32u*) Value;
++ for (i=0; i<STATS_MAX; i++)
++ {
++ *ptrValue = *ptrStats;
++ if(DBG(4))
++ {
++ dbgPrintf("halStatsDump: Stat[%d:0x%08X] %d 0x%08X %d\n", i, ptrStats, *ptrStats, ptrValue, *ptrValue);
++ osfuncSioFlush();
++ }
++ ptrStats++;
++ ptrValue++;
++ }
++ }
++static void ConfigApply(HAL_DEVICE *HalDev)
++ {
++ CPMAC_RX_MAXLEN(HalDev->dev_base) = HalDev->RxMaxLen;
++ CPMAC_RX_FILTERLOWTHRESH(HalDev->dev_base) = HalDev->RxFilterLowThresh;
++ CPMAC_RX0_FLOWTHRESH(HalDev->dev_base) = HalDev->Rx0FlowThresh;
++ UnicastSet(HalDev);
++ MacAddressSet(HalDev);
++ RxMBP_EnableSet(HalDev);
++ MacHashSet(HalDev);
++ MacControlSet(HalDev);
++ if(DBG(0))
++ dbgPrintf("ValuesUpdate[%d]: MBP_ENABLE 0x%08X\n", HalDev->inst, CPMAC_RX_MBP_ENABLE(HalDev->dev_base));
++ }
++static int halStatus(HAL_DEVICE *HalDev)
++{
++ int status;
++
++ if(HalDev->State < enOpened)
++ return (EC_CPMAC|EC_FUNC_STATUS|EC_VAL_INVALID_STATE); /*MJH+030805*/
++
++ /* No Phy Condition */
++ if(HalDev->MdioConnect & _CPMDIO_NOPHY) /*MJH+030805*/
++ {
++ /* No Phy condition, always linked */
++ status = HalDev->Linked;
++ status |= CPMAC_STATUS_LINK_DUPLEX;
++ status |= CPMAC_STATUS_LINK_SPEED;
++ return(status);
++ }
++
++
++ if (HalDev->HostErr) /* Adapter Check */
++ {
++ bit32u tmp;
++ status = CPMAC_STATUS_ADAPTER_CHECK;
++ if(HalDev->MacStatus & RX_HOST_ERR_CODE)
++ {
++ status |= CPMAC_STATUS_HOST_ERR_DIRECTION;
++ tmp = (HalDev->MacStatus & RX_HOST_ERR_CODE) >> 12; /* Code */
++ status |= (tmp << 9); /* Code */
++ tmp = (HalDev->MacStatus & RX_ERR_CH) >> 8; /* Channel */
++ status |= (tmp << 13);
++ }
++ else
++ if(HalDev->MacStatus & TX_HOST_ERR_CODE)
++ {
++ status |= CPMAC_STATUS_HOST_ERR_DIRECTION;
++ tmp = (HalDev->MacStatus & TX_HOST_ERR_CODE) >> 20; /* Code */
++ status |= (tmp << 9); /* Code */
++ tmp = (HalDev->MacStatus & TX_ERR_CH) >> 16; /* Channel */
++ status |= (tmp << 13);
++ }
++ }
++ else
++ {
++ status = HalDev->Linked;
++ if(status)
++ {
++ status = CPMAC_STATUS_LINK;
++ if(cpMacMdioGetDuplex(HalDev->PhyDev))
++ status |= CPMAC_STATUS_LINK_DUPLEX;
++ if(cpMacMdioGetSpeed(HalDev->PhyDev))
++ status |= CPMAC_STATUS_LINK_SPEED;
++ }
++ }
++ if(HalDev->debug)
++ dbgPrintf("[halStatus] Link Status is %d for 0x%X\n", status, HalDev->dev_base);
++ return(status);
++}
++static int InfoAccess(HAL_DEVICE *HalDev, int Key, int Action, void *ParmValue)
++ {
++ int rc = 0;
++ int Update=0;
++
++ switch (Key)
++ {
++ /********************************************************************/
++ /* */
++ /* GENERAL */
++ /* */
++ /********************************************************************/
++
++ case enVersion :
++ if(Action==enGET)
++ {
++ *(const char **)ParmValue = pszVersion_CPMAC;
++ }
++ break;
++ case enDebug :
++ if(Action==enSET)
++ {
++ HalDev->debug = *(unsigned int *)ParmValue;
++ }
++ break;
++
++ case enStatus :
++ if(Action==enGET)
++ {
++ int status;
++ status = halStatus(HalDev);
++ *(int *)ParmValue = status;
++ }
++ break;
++ /********************************************************************/
++ /* */
++ /* RX_MBP_ENABLE */
++ /* */
++ /********************************************************************/
++
++ case enRX_PASS_CRC :
++ if(Action==enSET)
++ {
++ UPDATE_RX_PASS_CRC(*(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++ case enRX_QOS_EN :
++ if(Action==enSET)
++ {
++ UPDATE_RX_QOS_EN(*(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++ case enRX_NO_CHAIN :
++ if(Action==enSET)
++ {
++ UPDATE_RX_NO_CHAIN(*(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++ case enRX_CMF_EN :
++ if(Action==enSET)
++ {
++ UPDATE_RX_CMF_EN(*(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++ case enRX_CSF_EN :
++ if(Action==enSET)
++ {
++ UPDATE_RX_CSF_EN(*(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++ case enRX_CEF_EN :
++ if(Action==enSET)
++ {
++ UPDATE_RX_CEF_EN(*(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++ case enRX_CAF_EN :
++ if(Action==enSET)
++ {
++ UPDATE_RX_CAF_EN(*(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++ case enRX_PROM_CH :
++ if(Action==enSET)
++ {
++ UPDATE_RX_PROM_CH(*(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++ case enRX_BROAD_EN :
++ if(Action==enSET)
++ {
++ UPDATE_RX_BROAD_EN(*(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++ case enRX_BROAD_CH :
++ if(Action==enSET)
++ {
++ UPDATE_RX_BROAD_CH(*(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++ case enRX_MULT_EN :
++ if(Action==enSET)
++ {
++ UPDATE_RX_MULT_EN(*(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++ case enRX_MULT_CH :
++ if(Action==enSET)
++ {
++ UPDATE_RX_MULT_CH(*(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++
++ /********************************************************************/
++ /* */
++ /* MAC_CONTROL */
++ /* */
++ /********************************************************************/
++
++ case enTX_PTYPE :
++ if(Action==enSET)
++ {
++ UPDATE_TX_PTYPE(*(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++ case enTX_PACE :
++ if(Action==enSET)
++ {
++ UPDATE_TX_PACE(*(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++ case enTX_FLOW_EN :
++ if(Action==enSET)
++ {
++ UPDATE_TX_FLOW_EN(*(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++ case enRX_FLOW_EN :
++ if(Action==enSET)
++ {
++ UPDATE_RX_FLOW_EN(*(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++
++ case enCTRL_LOOPBACK :
++ if(Action==enSET)
++ {
++ UPDATE_CTRL_LOOPBACK(*(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++ /********************************************************************/
++ /* */
++ /* RX_UNICAST_SET */
++ /* */
++ /********************************************************************/
++
++ case enRX_UNICAST_SET :
++ if(Action==enSET)
++ {
++ HalDev->RxUnicastSet |= (1 << *(unsigned int *)ParmValue);
++ HalDev->RxUnicastClear &= ~(1 << *(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++ case enRX_UNICAST_CLEAR :
++ if(Action==enSET)
++ {
++ HalDev->RxUnicastClear |= (1 << *(unsigned int *)ParmValue);
++ HalDev->RxUnicastSet &= ~(1 << *(unsigned int *)ParmValue);
++ Update=1;
++ }
++ break;
++
++ case enRX_MAXLEN :
++ if(Action==enSET)
++ {
++ HalDev->RxMaxLen = *(unsigned int *)ParmValue;
++ Update=1;
++ }
++ break;
++
++ case enRX_FILTERLOWTHRESH :
++ if(Action==enSET)
++ {
++ HalDev->RxFilterLowThresh = *(unsigned int *)ParmValue;
++ Update=1;
++ }
++ break;
++ case enRX0_FLOWTHRESH :
++ if(Action==enSET)
++ {
++ HalDev->Rx0FlowThresh = *(unsigned int *)ParmValue;
++ Update=1;
++ }
++ break;
++ /********************************************************************/
++ /* */
++ /* RX_MULTICAST */
++ /* */
++ /********************************************************************/
++
++ case enRX_MULTICAST :
++ break;
++ case enRX_MULTI_SINGLE :
++ if(DBG(11))
++ {
++ int tmpi;
++ bit8u *MacAddress;
++ MacAddress = (bit8u *) ParmValue;
++ dbgPrintf("CPMAC[%X]: MacAddress '", HalDev->dev_base);
++ for (tmpi=0; tmpi<6; tmpi++)
++ dbgPrintf("%02X:", MacAddress[tmpi]);
++ dbgPrintf("\n");
++ }
++ if(Action==enCLEAR)
++ {
++ HashDel(HalDev, ParmValue);
++ Update=1;
++ }
++ else
++ if(Action==enSET)
++ {
++ HashAdd(HalDev, ParmValue);
++ Update=1;
++ }
++ break;
++ case enRX_MULTI_ALL :
++ if(Action==enCLEAR)
++ {
++ HalDev->MacHash1 = 0;
++ HalDev->MacHash2 = 0;
++ Update=1;
++ }
++ else
++ if(Action==enSET)
++ {
++ HalDev->MacHash1 = 0xFFFFFFFF;
++ HalDev->MacHash2 = 0xFFFFFFFF;
++ Update=1;
++ }
++ break;
++
++ /********************************************************************/
++ /* */
++ /* MDIO */
++ /* */
++ /********************************************************************/
++
++ case enMdioConnect :
++ if(Action==enSET)
++ {
++ HalDev->MdioConnect = *(unsigned int *)ParmValue;
++ MdioSetPhyMode(HalDev);
++ }
++ if(Action==enGET)
++ {
++ *(unsigned int *)ParmValue = HalDev->MdioConnect;
++ }
++ break;
++
++
++ /********************************************************************/
++ /* */
++ /* STATISTICS */
++ /* */
++ /********************************************************************/
++ case enStatsClear :
++ StatsClear(HalDev);
++ break;
++ case enStatsDump :
++ if(Action==enGET)
++ {
++ StatsDump(HalDev, ParmValue);
++ }
++ break;
++
++/* Not implemented
++ case enStats1 :
++ if(Action==enGET)
++ {
++ StatsGet(HalDev, ParmValue, 1);
++ }
++ break;
++
++ case enStats2 :
++ if(Action==enGET)
++ {
++ StatsGet(HalDev, ParmValue, 2);
++ }
++ break;
++ case enStats3 :
++ if(Action==enGET)
++ {
++ StatsGet(HalDev, ParmValue, 3);
++ }
++ break;
++ case enStats4 :
++ if(Action==enGET)
++ {
++ StatsGet(HalDev, ParmValue, 4);
++ }
++ break;
++
++*/
++
++ default:
++ rc = EC_CPMAC|EC_FUNC_OPTIONS|EC_VAL_KEY_NOT_FOUND;
++ break;
++ }
++
++ /* Verify proper device state */
++ if (HalDev->State == enOpened)
++ switch (Update)
++ {
++ case 1 :
++ ConfigApply(HalDev);
++ break;
++ default:
++ break;
++ }
++
++ return (rc);
++ }
++static const char pszStats[] = "Stats;";
++
++static int halControl(HAL_DEVICE *HalDev, const char *pszKey, const char *pszAction, void *Value)
++ {
++ int i;
++ int rc=0;
++ int Action;
++ int ActionFound;
++ int KeyFound;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(1))
++ {
++ dbgPrintf("\nhalControl-HalDev:%08X,Action:%s,Key:%s\n", (bit32u)HalDev, pszAction, pszKey);
++ }
++#endif
++
++ /* 23Aug04 - BCIL needs to set Mac Address */
++ if(HalDev->OsFunc->Strcmpi(pszKey, pszMacAddr) == 0)
++ {
++ KeyFound=1;
++ if(HalDev->OsFunc->Strcmpi(pszAction, hcSet) == 0)
++ {
++ unsigned char *MacAddr;
++ MacAddr = (unsigned char *) Value;
++ MacAddressSave(HalDev, MacAddr);
++ MacAddressSet(HalDev);
++ return(0);
++ }
++ else
++ {
++ return(-1);
++ }
++ }
++
++ if(HalDev->OsFunc->Strcmpi(pszKey, hcLinked) == 0)
++ {
++ KeyFound=1;
++ if(HalDev->OsFunc->Strcmpi(pszAction, hcSet) == 0)
++ {
++ HalDev->Linked = *(int *)Value;
++ return(0);
++ }
++ else
++ {
++ return(-1);
++ }
++ }
++
++ if(HalDev->OsFunc->Strcmpi(pszKey, "TxIntDisable") == 0)
++ {
++ KeyFound=1;
++ if(HalDev->OsFunc->Strcmpi(pszAction, hcSet) == 0)
++ {
++ HalDev->TxIntDisable = *(int *)Value;
++ if(HalDev->TxIntDisable && (HalDev->State == enOpened))
++ {
++ /* if Opened and need TxIntDisabled, clear Ints for Channel 0 */
++ CPMAC_TX_INTMASK_CLEAR(HalDev->dev_base) = 1;
++ }
++ return(0);
++ }
++ else
++ {
++ return(-1);
++ }
++ }
++
++ if(HalDev->OsFunc->Strcmpi(pszKey, hcPhyAccess) == 0)
++ {
++ bit32u RegAddr;
++ bit32u PhyNum;
++ bit32u Data;
++ bit32u ValueIn;
++
++ ValueIn = *(bit32u*) Value;
++
++ KeyFound=1;
++ /* Cannot access MII if not opended */
++
++ if(HalDev->State < enOpened)
++ return(-1);
++
++ if(HalDev->OsFunc->Strcmpi(pszAction, hcGet) == 0)
++ {
++
++ PhyNum = (ValueIn & 0x1F); /* Phynum 0-32 */
++ RegAddr = (ValueIn >> 5) & 0xFF; /* RegAddr in upper 11 bits */
++
++ *(bit32u*)Value = _mdioUserAccessRead(HalDev->PhyDev, RegAddr, PhyNum);
++
++ return(0);
++ } /* end of hcGet */
++
++
++ if(HalDev->OsFunc->Strcmpi(pszAction, hcSet) == 0)
++ {
++ PhyNum = (ValueIn & 0x1F); /* Phynum 0-32 */
++ RegAddr = (ValueIn >> 5) & 0xFF; /* RegAddr in upper 11 bits of lower 16 */
++
++ Data = ValueIn >> 16; /* Data store in upper 16 bits */
++
++ _mdioUserAccessWrite(HalDev->PhyDev, RegAddr, PhyNum, Data);
++ return(0);
++ }
++ } /* End of hcPhyAccess */
++
++ if(HalDev->OsFunc->Strcmpi(pszKey, hcPhyNum) == 0)
++ {
++ KeyFound=1;
++ if(!HalDev->Linked)
++ return(-1); /* if not linked the no Phy Connected */
++ if(HalDev->OsFunc->Strcmpi(pszAction, hcGet) == 0)
++ {
++ *(int *)Value = HalDev->PhyNum;
++ return(0);
++ }
++ }
++
++ if(HalDev->OsFunc->Strcmpi(pszKey, hcCpmacSize) == 0)
++ {
++ KeyFound=1;
++ if(HalDev->OsFunc->Strcmpi(pszAction, hcGet) == 0)
++ {
++ *(bit32u *)Value = HalDev->CpmacSize;
++ return(0);
++ }
++ }
++
++ if(HalDev->OsFunc->Strcmpi(pszKey, hcCpmacBase) == 0)
++ {
++ KeyFound=1;
++ if(HalDev->OsFunc->Strcmpi(pszAction, hcGet) == 0)
++ {
++ *(int *)Value = HalDev->dev_base;
++ return(0);
++ }
++ }
++
++ if(HalDev->OsFunc->Strcmpi(pszKey, hcFullDuplex) == 0)
++ {
++ KeyFound=1;
++ if(HalDev->OsFunc->Strcmpi(pszAction, hcSet) == 0)
++ {
++ UPDATE_FULLDUPLEX(*(unsigned int *)Value);
++ if(HalDev->State == enOpened)
++ ConfigApply(HalDev);
++ return(0);
++ }
++ else
++ return(-1);
++ }
++
++ if(HalDev->OsFunc->Strcmpi(pszKey, pszDebug) == 0)
++ {
++ KeyFound=1;
++ if(HalDev->OsFunc->Strcmpi(pszAction, hcSet) == 0)
++ {
++ ActionFound=1;
++ HalDev->debug = *(int *)Value;
++ }
++ }
++
++ if(HalDev->OsFunc->Strcmpi(pszKey, hcMaxFrags) == 0)
++ {
++ KeyFound=1;
++ if(HalDev->OsFunc->Strcmpi(pszAction, hcSet) == 0)
++ {
++ ActionFound=1;
++
++ if ((*(int *)Value) > 0)
++ HalDev->MaxFrags = *(int *)Value;
++ else
++ rc = (EC_AAL5|EC_FUNC_CONTROL|EC_VAL_INVALID_VALUE);
++ }
++
++ if (HalDev->OsFunc->Strcmpi(pszAction, hcGet) == 0)
++ {
++ ActionFound=1;
++
++ *(int *)Value = HalDev->MaxFrags;
++ }
++ }
++
++ if(HalDev->OsFunc->Strstr(pszKey, pszStats) != 0)
++ {
++ KeyFound=1;
++ if(HalDev->OsFunc->Strcmpi(pszAction, hcGet) == 0)
++ {
++ int Level;
++ int Ch;
++ char *TmpKey = (char *)pszKey;
++ ActionFound=1;
++ TmpKey += HalDev->OsFunc->Strlen(pszStats);
++ Level = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++ TmpKey++;
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++ TmpKey++;
++ osfuncSioFlush();
++#ifdef __CPHAL_DEBUG
++ if (DBG(1))
++ {
++ dbgPrintf("\nhalControl-HalDev:%08X, Level:%d, Ch:%d\n", (bit32u)HalDev, Level, Ch);
++ }
++#endif
++ StatsGet(HalDev, (void **)Value, Level, Ch, 0);
++ osfuncSioFlush();
++ }
++ }
++
++
++ if(HalDev->OsFunc->Strcmpi(pszAction, hcSet) == 0)
++ Action = enSET;
++ else
++ if(HalDev->OsFunc->Strcmpi(pszAction, hcClear) == 0)
++ Action = enCLEAR;
++ else
++ if(HalDev->OsFunc->Strcmpi(pszAction, hcGet) == 0)
++ Action = enGET;
++ else
++ Action = enNULL;
++
++
++
++ for(i=enCommonStart+1;i<enCommonEnd;i++)
++ {
++ if(HalDev->OsFunc->Strcmpi(KeyCommon[i].strKey, pszKey)==0)
++ {
++ rc = InfoAccess(HalDev, KeyCommon[i].enKey, Action, Value);
++ }
++ }
++ for(i=enCpmacStart+1;i<enCpmacEnd;i++)
++ {
++ if(HalDev->OsFunc->Strcmpi(KeyCpmac[i].strKey, pszKey)==0)
++ {
++ rc = InfoAccess(HalDev, KeyCpmac[i].enKey, Action, Value);
++ }
++ }
++/*
++ if (KeyFound == 0)
++ rc = (EC_MODULE|EC_FUNC_CONTROL|EC_VAL_KEY_NOT_FOUND);
++
++ if (ActionFound == 0)
++ rc = (EC_MODULE|EC_FUNC_CONTROL|EC_VAL_ACTION_NOT_FOUND);
++*/
++
++ return(rc);
++ }
++static bit32u ConfigGet(HAL_DEVICE *HalDev)
++ {
++ OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++ char *DeviceInfo = HalDev->DeviceInfo;
++ int i = HalDev->inst;
++ bit32u Value;
++ int Error;
++
++ /* get the configuration parameters common to all modules */
++ Error = ConfigGetCommon(HalDev);
++ if (Error) return (EC_CPMAC|Error);
++
++ if (HalDev->debug)
++ {
++ dbgPrintf("ConfigGet: haldev:0x%08X inst:%d base:0x%08X reset:%d\n", (bit32u) &HalDev, HalDev->inst, HalDev->dev_base, HalDev->ResetBit);
++ osfuncSioFlush();
++ }
++
++ Error = OsFunc->DeviceFindParmUint(DeviceInfo, pszMdioConnect,&Value); /*MJH+030805*/
++ if(!Error) HalDev->MdioConnect = Value;
++
++ Error = OsFunc->DeviceFindParmUint(DeviceInfo, "PhyMask",&Value);
++ if(!Error) HalDev->PhyMask = Value;
++
++ Error = OsFunc->DeviceFindParmUint(DeviceInfo, "MLink",&Value);
++ if(!Error) HalDev->MLinkMask = Value;
++
++ Error = OsFunc->DeviceFindParmUint(DeviceInfo, hcMdixMask, &Value);
++ if(!Error)
++ HalDev->MdixMask = Value;
++ else
++ HalDev->MdixMask = 0;
++
++ Error = OsFunc->DeviceFindParmUint(DeviceInfo, hcSize, &Value); /*MJH+030425*/
++ if(!Error) HalDev->CpmacSize = Value;
++
++ for(i=enCommonStart+1;i<enCommonEnd;i++)
++ {
++ Error = OsFunc->DeviceFindParmUint(DeviceInfo, KeyCommon[i].strKey, (bit32u*)&Value);
++ if(!Error)
++ {
++ InfoAccess(HalDev, KeyCommon[i].enKey, enSET, (bit32u*)&Value);
++ }
++ }
++ for(i=enCpmacStart+1;i<enCpmacEnd;i++)
++ {
++ Error = OsFunc->DeviceFindParmUint(DeviceInfo, KeyCpmac[i].strKey, (bit32u*)&Value);
++ if(!Error)
++ {
++ InfoAccess(HalDev, KeyCpmac[i].enKey, enSET, (bit32u*)&Value);
++ }
++ }
++ return (EC_NO_ERRORS);
++ }
++
++
++static void ConfigInit(HAL_DEVICE *HalDev)
++ {
++ if(HalDev->inst == 0)
++ {
++ HalDev->dev_base = 0xA8610000;
++ HalDev->ResetBit = 17;
++ HalDev->interrupt = 19;
++ HalDev->MLinkMask = 0;
++ HalDev->PhyMask = 0xAAAAAAAA;
++ }
++ else
++ {
++ HalDev->dev_base = 0xA8612800;
++ HalDev->ResetBit = 21;
++ HalDev->interrupt = 33; /*~RC3.02*/
++ HalDev->MLinkMask = 0;
++ HalDev->PhyMask = 0x55555555;
++ }
++ HalDev->RxMaxLen = 1518;
++ HalDev->MaxFrags = 2;
++ HalDev->MdioConnect = _CPMDIO_HD|_CPMDIO_FD|_CPMDIO_10|_CPMDIO_100|_CPMDIO_AUTOMDIX;
++ HalDev->debug=0xFFFFFFFF;
++ HalDev->debug=0;
++ }
++/* Shuts down the EMAC device
++ *
++ *@param HalDev EMAC instance. This was returned by halOpen()
++ *@param mode Indicates actions to tak on close.
++ <br>
++ *PARTIAL - Disable EMAC
++ <br>
++ *FULL - Disable EMAC and call OS to free all allocated memory
++ *
++ *@retval
++ * 0 OK
++ <br>
++ * Non-Zero Not OK
++ *
++ */
++static int halInit( HAL_DEVICE *HalDev)
++ {
++ int rc;
++
++ /* Verify proper device state */
++ if (HalDev->State != enDevFound)
++ return(EC_CPMAC|EC_FUNC_HAL_INIT|EC_VAL_INVALID_STATE);
++
++ /* Configure HAL defaults */
++ ConfigInit(HalDev);
++
++ /* Retrieve HAL configuration parameters from data store */
++ rc = ConfigGet(HalDev);
++ if (rc) return (rc);
++
++ /* Updated 030403*/
++ rc = HalDev->OsFunc->Control(HalDev->OsDev, hcCpuFrequency, hcGet, &HalDev->CpuFrequency); /*MJH+030403*/
++ if(rc)
++ HalDev->CpuFrequency = 20000000; /*20 Mhz default */ /*MJH+030403*/
++
++ rc = HalDev->OsFunc->Control(HalDev->OsDev, hcCpmacFrequency, hcGet, &HalDev->CpmacFrequency); /*MJH+030331*/
++ if(rc)
++ HalDev->CpmacFrequency = HalDev->CpuFrequency/2; /*MJH~030404*/
++
++ rc = HalDev->OsFunc->Control(HalDev->OsDev, hcMdioBusFrequency, hcGet, &HalDev->MdioBusFrequency); /*MJH+030402*/
++ if(rc)
++ HalDev->MdioBusFrequency = HalDev->CpmacFrequency;
++
++ rc = HalDev->OsFunc->Control(HalDev->OsDev, hcMdioClockFrequency, hcGet, &HalDev->MdioClockFrequency); /*MJH+030402*/
++ if(rc)
++ HalDev->MdioClockFrequency = 2200000; /* 2.2 Mhz PITS #14 */
++
++
++ /* update device state */
++ HalDev->State = enInitialized;
++
++ /* initialize statistics */
++ StatsInit(HalDev); /* +RC3.02 */
++
++ /* -RC3.02
++ StatsTable3[0].StatPtr = &HalDev->ChData[0].RxBufSize;
++ StatsTable3[1].StatPtr = &HalDev->ChData[0].RxBufferOffset;
++ StatsTable3[2].StatPtr = &HalDev->ChData[0].RxNumBuffers;
++ StatsTable3[3].StatPtr = &HalDev->ChData[0].RxServiceMax;
++ StatsTable3[4].StatPtr = &HalDev->ChData[0].TxNumBuffers;
++ StatsTable3[5].StatPtr = &HalDev->ChData[0].TxNumQueues;
++ StatsTable3[6].StatPtr = &HalDev->ChData[0].TxServiceMax;
++ */
++
++ return(EC_NO_ERRORS);
++ }
++static int halProbe(HAL_DEVICE *HalDev)
++ {
++ int inst = HalDev->inst;
++ OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++ int error_code;
++
++ if (HalDev->State != enConnected)
++ return (EC_CPMAC|EC_FUNC_PROBE|EC_VAL_INVALID_STATE);
++
++ if(HalDev->debug) dbgPrintf("halProbe: %d ",inst);
++
++ error_code = OsFunc->DeviceFindInfo(inst,"cpmac",&HalDev->DeviceInfo);
++
++ if(error_code)
++ return (EC_CPMAC|EC_FUNC_PROBE|EC_VAL_DEVICE_NOT_FOUND );
++
++ /* Set device state to DevFound */
++ HalDev->State = enDevFound;
++ return(EC_NO_ERRORS);
++ }
++static void ChannelConfigInit(HAL_DEVICE *HalDev, CHANNEL_INFO *HalChn)
++ {
++ int Ch = HalChn->Channel;
++ int Direction = HalChn->Direction;
++ int nTxBuffers = 256;
++
++ if (Direction == DIRECTION_TX)
++ {
++ HalDev->ChData[Ch].TxNumBuffers = nTxBuffers;
++ HalDev->ChData[Ch].TxNumQueues = 1;
++ HalDev->ChData[Ch].TxServiceMax = nTxBuffers/3;
++ HalDev->TxIntThreshold[Ch] = HalDev->ChData[Ch].TxServiceMax;
++ HalDev->TxIntThresholdMaster[Ch] = HalDev->TxIntThreshold[Ch];
++ }
++
++ if (Direction == DIRECTION_RX)
++ {
++ HalDev->ChData[Ch].RxNumBuffers = nTxBuffers*2;
++ HalDev->ChData[Ch].RxBufferOffset = 0;
++ HalDev->ChData[Ch].RxBufSize = 1518;
++ HalDev->ChData[Ch].RxServiceMax = nTxBuffers/3; /*Not a typo*/
++ }
++ }
++static int ChannelConfigApply(HAL_DEVICE *HalDev, CHANNEL_INFO *HalChn)
++ {
++ int Ch = HalChn->Channel;
++ int Direction = HalChn->Direction;
++
++ if (DBG(11))
++ {
++ dbgPrintf("halChannelConfigApply[%d:%d] haldev:0x%08X inst:%d base:0x%08X reset:%d\n", Ch, Direction, (bit32u) &HalDev, HalDev->inst, HalDev->dev_base, HalDev->ResetBit);
++ osfuncSioFlush();
++ }
++
++ if (Direction == DIRECTION_TX)
++ {
++ if (HalDev->ChIsOpen[Ch][Direction] == TRUE)
++ {
++ return(EC_CPMAC|EC_FUNC_CHSETUP|EC_VAL_TX_CH_ALREADY_OPEN);
++ }
++
++ /* Initialize Queue Data */
++ HalDev->TxActQueueHead[Ch][0] = 0;
++ HalDev->TxActQueueCount[Ch][0] = 0;
++ HalDev->TxActive[Ch][0] = FALSE;
++
++ /* Need to use a macro that takes channel as input */
++ CPMAC_TX0_HDP(HalDev->dev_base)=0;
++
++ /* Initialize buffer memory for the channel */
++ InitTcb(HalDev, Ch);
++
++ if(!HalDev->TxIntDisable)
++ CPMAC_TX_INTMASK_SET(HalDev->dev_base) = (1<<Ch); /* GSG 11/22 */
++ }
++ else
++ {
++ if (HalDev->ChIsOpen[Ch][Direction] == TRUE)
++ {
++ return(EC_CPMAC|EC_FUNC_CHSETUP|EC_VAL_RX_CH_ALREADY_OPEN);
++ }
++
++ /* Initialize Queue Data */
++ HalDev->RxActQueueHead[Ch] = 0;
++ HalDev->RxActQueueCount[Ch] = 0;
++
++ HalDev->RxActive[Ch] = FALSE;
++
++ /* Need to use a macro that takes channel as input */
++ CPMAC_RX0_HDP(HalDev->dev_base)=0;
++
++ /* Initialize buffer memory for the channel */
++ InitRcb(HalDev, Ch);
++
++ CPMAC_RX_INTMASK_SET(HalDev->dev_base) = (1<<Ch); /* GSG 11/22 */
++ }
++
++ HalDev->ChIsOpen[Ch][Direction] = TRUE; /* channel is open */
++
++ return (EC_NO_ERRORS);
++ }
++
++/* GSG 11/22
++ * Retrieves channel parameters from configuration file. Any parameters
++ * which are not found are ignored, and the HAL default value will apply,
++ * unless a new value is given through the channel structure in the call
++ * to ChannelSetup.
++ */
++static int ChannelConfigGet(HAL_DEVICE *HalDev, CHANNEL_INFO *HalChn)
++ {
++ int Ch = HalChn->Channel;
++ int Direction = HalChn->Direction;
++ OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++ unsigned int rc, Value;
++ void *ChInfo;
++
++ rc=OsFunc->DeviceFindParmValue(HalDev->DeviceInfo, channel_names[Ch], &ChInfo);
++ /* Do not fail if Channel Info not available for RC2 */
++ if (rc) return(0);
++/* if (rc) return(EC_CPMAC|EC_FUNC_CHSETUP|EC_VAL_CH_INFO_NOT_FOUND);*/
++
++ /* i don't care if a value is not found because they are optional */
++ if(Direction == DIRECTION_TX)
++ {
++ rc=OsFunc->DeviceFindParmUint(ChInfo, "TxNumBuffers", &Value);
++ if (!rc) HalDev->ChData[Ch].TxNumBuffers = Value;
++
++ /*rc=OsFunc->DeviceFindParmUint(ChInfo, "TxNumQueues", &Value);*/ /*MJH-030329*/
++ /*if (!rc) HalDev->ChData[Ch].TxNumQueues = Value;*/ /*MJH-030329*/
++
++ rc=OsFunc->DeviceFindParmUint(ChInfo, "TxServiceMax", &Value);
++ if (!rc)
++ {
++ HalDev->ChData[Ch].TxServiceMax = Value;
++ HalDev->TxIntThreshold[Ch] = HalDev->ChData[Ch].TxServiceMax;
++ HalDev->TxIntThresholdMaster[Ch] = HalDev->TxIntThreshold[Ch];
++ }
++ }
++ if(Direction == DIRECTION_RX)
++ {
++ rc=OsFunc->DeviceFindParmUint(ChInfo, "RxNumBuffers", &Value);
++ if (!rc) HalDev->ChData[Ch].RxNumBuffers = Value;
++
++ rc=OsFunc->DeviceFindParmUint(ChInfo, "RxBufferOffset", &Value);
++ if (!rc) HalDev->ChData[Ch].RxBufferOffset = Value;
++
++ rc=OsFunc->DeviceFindParmUint(ChInfo, "RxBufSize", &Value);
++ if (!rc) HalDev->ChData[Ch].RxBufSize = Value;
++
++ rc=OsFunc->DeviceFindParmUint(ChInfo, "RxServiceMax", &Value);
++ if (!rc) HalDev->ChData[Ch].RxServiceMax = Value;
++ }
++ return (EC_NO_ERRORS);
++ }
++#define ChannelUpdate(Field) if(HalChn->Field != 0xFFFFFFFF) HalDev->ChData[Ch].Field = HalChn->Field
++
++static void ChannelConfigUpdate(HAL_DEVICE *HalDev, CHANNEL_INFO *HalChn)
++ {
++ int Ch = HalChn->Channel;
++ int Direction = HalChn->Direction;
++#ifdef __CPHAL_DEBUG
++ if (DBG(1))
++ {
++ dbgPrintf("\nChnUpd-HalDev:%08X,Chn:%d:%d\n", (bit32u)HalDev, Ch, Direction); osfuncSioFlush();
++ }
++#endif
++ if (Direction == DIRECTION_TX)
++ {
++ ChannelUpdate(TxNumBuffers);
++ /*ChannelUpdate(TxNumQueues);*/ /*MJH~030329*/
++ ChannelUpdate(TxServiceMax);
++ HalDev->TxIntThreshold[Ch] = HalDev->ChData[Ch].TxServiceMax;
++ HalDev->TxIntThresholdMaster[Ch] = HalDev->TxIntThreshold[Ch];
++ }
++ else
++ if (Direction == DIRECTION_RX)
++ {
++ ChannelUpdate(RxBufferOffset);
++ ChannelUpdate(RxBufSize);
++ ChannelUpdate(RxNumBuffers);
++ ChannelUpdate(RxServiceMax);
++#ifdef __CPHAL_DEBUG
++ if (DBG(1))
++ {
++ dbgPrintf("\nRxNumBuffers %d\n",HalChn->RxNumBuffers); osfuncSioFlush();
++ }
++#endif
++ }
++ }
++static int halChannelSetup(HAL_DEVICE *HalDev, CHANNEL_INFO *HalChn, OS_SETUP *OsSetup)
++ {
++ int Direction;
++ int Ch;
++ int rc;
++
++ /* Verify proper device state */
++ if (HalDev->State < enInitialized)
++ return (EC_CPMAC|EC_FUNC_CHSETUP|EC_VAL_INVALID_STATE);
++
++ /* We require the channel structure to be passed, even if it only contains
++ the channel number */
++ if (HalChn == NULL)
++ {
++ return(EC_CPMAC|EC_FUNC_CHSETUP|EC_VAL_NULL_CH_STRUCT);
++ }
++
++ Ch = HalChn->Channel;
++ Direction = HalChn->Direction;
++
++ /* This should check on Maximum Channels for RX or TX,
++ they might be different Mick 021124 */
++ if ((Ch < 0) || (Ch > (MAX_CHAN-1)))
++ {
++ return(EC_CPMAC|EC_FUNC_CHSETUP|EC_VAL_INVALID_CH);
++ }
++
++ /* if channel is already open, this call is invalid */
++ if (HalDev->ChIsOpen[Ch][Direction] == TRUE)
++ {
++ return(EC_CPMAC|EC_FUNC_CHSETUP|EC_VAL_CH_ALREADY_OPEN);
++ }
++
++ /* channel is closed, but might be setup. If so, reopen the hardware channel. */
++ if (HalDev->ChIsSetup[Ch][Direction] == FALSE)
++ {
++ /* Setup channel configuration */
++ HalDev->ChData[Ch].Channel = Ch;
++
++ /* Store OS_SETUP */
++ HalDev->ChData[Ch].OsSetup = OsSetup;
++
++ /* Framework :
++ Set Default Values
++ Update with options.conf
++ Apply driver updates
++ */
++ ChannelConfigInit(HalDev, HalChn);
++ ChannelConfigGet(HalDev, HalChn);
++ ChannelConfigUpdate(HalDev, HalChn);
++
++ /* cppi.c needs to use Rx/TxServiceMax */
++ HalDev->BuffersServicedMax = 169; /* TEMP */
++
++ HalDev->ChIsSetup[Ch][Direction] = TRUE;
++ }
++
++ rc = EC_NO_ERRORS;
++
++ /* If the hardware has been opened (is out of reset), then configure the channel
++ in the hardware. NOTE: ChannelConfigApply calls the CPSAR ChannelSetup()! */
++ if (HalDev->State == enOpened)
++ {
++ rc = ChannelConfigApply(HalDev, HalChn);
++ }
++
++ return (rc);
++ }
++
++
++static int miiInfoGet(HAL_DEVICE *HalDev, bit32u *miiBaseAddress, bit32u *miiResetBit)
++ {
++ int rc;
++ void *DeviceInfo;
++ OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++
++ /* Only one instance of cpmdio */
++ rc = OsFunc->DeviceFindInfo(0,"cpmdio",&DeviceInfo); /*~RC3.02*/
++
++ if(rc)
++ return (EC_DEV_CPMDIO|EC_FUNC_OPEN|EC_VAL_DEVICE_NOT_FOUND );
++
++ rc = OsFunc->DeviceFindParmUint(DeviceInfo, "base",miiBaseAddress);
++ if(rc)
++ rc=EC_DEV_CPMDIO|EC_FUNC_OPEN|EC_VAL_NO_BASE;
++
++ rc = OsFunc->DeviceFindParmUint(DeviceInfo, "reset_bit",miiResetBit);
++ if(rc)
++ rc=EC_DEV_CPMDIO|EC_FUNC_OPEN|EC_VAL_NO_BASE;
++
++
++ /* See if need to make mdio functional in GPIO */
++ gpioCheck(HalDev, DeviceInfo);
++
++ if(DBG(0))
++ dbgPrintf("miiBase: 0x%08X %u\n", *miiBaseAddress, *miiResetBit);
++ return(rc);
++ }
++static void ephyCheck(HAL_DEVICE *HalDev)
++ { /*+RC3.02*/
++ int rc;
++ void *DeviceInfo;
++ int mii_phy;
++ int reset_bit;
++ OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++
++ rc = OsFunc->DeviceFindInfo(0,"ephy",&DeviceInfo);
++ if(rc) return;
++
++ rc = OsFunc->DeviceFindParmUint(DeviceInfo, "mii_phy",&mii_phy);
++ if(rc) return;
++
++ rc = OsFunc->DeviceFindParmUint(DeviceInfo, "reset_bit",&reset_bit);
++ if(rc) return;
++
++ if (HalDev->PhyMask & (1 << mii_phy))
++ {
++ *(volatile bit32u *)(HalDev->ResetBase) |= (1 << reset_bit); /*+RC3.02*/
++ resetWait(HalDev);
++ }
++ } /*+RC3.02*/
++static void AutoNegotiate(HAL_DEVICE *HalDev)
++ {
++ int size;
++ bit32u ModID, RevMaj, RevMin;
++ PHY_DEVICE *PhyDev;
++ bit32u miiBaseAddress;
++ bit32u miiResetBit;
++
++ /* Verify proper device state */
++ if (HalDev->State < enOpened)
++ return;
++
++ miiInfoGet(HalDev, &miiBaseAddress, &miiResetBit);
++
++ cpMacMdioGetVer(miiBaseAddress, &ModID, &RevMaj, &RevMin);
++ if(HalDev->debug)
++ dbgPrintf("Mdio Module Id %d, Version %d.%d\n", ModID, RevMaj, RevMin);
++
++ size = cpMacMdioGetPhyDevSize();
++ PhyDev = (PHY_DEVICE *) HalDev->OsFunc->Malloc( size );
++
++ HalDev->PhyDev = PhyDev;
++
++ ephyCheck(HalDev);
++
++ cpMacMdioInit( PhyDev, miiBaseAddress, HalDev->inst, HalDev->PhyMask, HalDev->MLinkMask, HalDev->MdixMask, HalDev->ResetBase, miiResetBit, HalDev->MdioBusFrequency, HalDev->MdioClockFrequency, HalDev->debug, HalDev); /*MJH~030402*/
++ MdioSetPhyMode(HalDev);
++
++ return;
++ }
++static int halOpen(HAL_DEVICE *HalDev)
++ {
++ unsigned char *MacAddr;
++ int i;
++ int j;
++ int rc, Ticks;
++
++ if (HalDev->debug)
++ {
++ dbgPrintf("halOpen: haldev:0x%08X inst:%d base:0x%08X reset:%d\n", (bit32u) &HalDev, HalDev->inst, HalDev->dev_base, HalDev->ResetBit);
++ osfuncSioFlush();
++ }
++
++ /* Verify proper device state */
++ if (HalDev->State < enInitialized)
++ return (EC_CPMAC|EC_FUNC_OPEN|EC_VAL_INVALID_STATE);
++
++
++ /* take CPMAC out of reset - GSG 11/20*/
++ if ((VOLATILE32(HalDev->ResetBase) & (1 << HalDev->ResetBit)) != 0)
++ {
++ /* perform normal close duties */
++ CPMAC_MACCONTROL(HalDev->dev_base) &= ~MII_EN;
++ CPMAC_TX_CONTROL(HalDev->dev_base) &= ~TX_EN;
++ CPMAC_RX_CONTROL(HalDev->dev_base) &= ~RX_EN;
++
++ /* disable interrupt masks */
++ CPMAC_TX_INTMASK_CLEAR(HalDev->dev_base) = 0xFF;
++ CPMAC_RX_INTMASK_CLEAR(HalDev->dev_base) = 0xFF;
++ }
++
++ /* take CPMAC out of reset */
++ *(volatile bit32u *)(HalDev->ResetBase) &= ~(1 << HalDev->ResetBit);
++ resetWait(HalDev);
++ *(volatile bit32u *)(HalDev->ResetBase) |= (1 << HalDev->ResetBit);
++ resetWait(HalDev);
++
++ /* After Reset clear the Transmit and Receive DMA Head Descriptor Pointers */
++
++ CPMAC_TX0_HDP(HalDev->dev_base)=0;
++ CPMAC_TX1_HDP(HalDev->dev_base)=0;
++ CPMAC_TX2_HDP(HalDev->dev_base)=0;
++ CPMAC_TX3_HDP(HalDev->dev_base)=0;
++ CPMAC_TX4_HDP(HalDev->dev_base)=0;
++ CPMAC_TX5_HDP(HalDev->dev_base)=0;
++ CPMAC_TX6_HDP(HalDev->dev_base)=0;
++ CPMAC_TX7_HDP(HalDev->dev_base)=0;
++
++ /* Rx Init */
++
++ CPMAC_RX0_HDP(HalDev->dev_base) = 0;
++ CPMAC_RX1_HDP(HalDev->dev_base) = 0;
++ CPMAC_RX2_HDP(HalDev->dev_base) = 0;
++ CPMAC_RX3_HDP(HalDev->dev_base) = 0;
++ CPMAC_RX4_HDP(HalDev->dev_base) = 0;
++ CPMAC_RX5_HDP(HalDev->dev_base) = 0;
++ CPMAC_RX6_HDP(HalDev->dev_base) = 0;
++ CPMAC_RX7_HDP(HalDev->dev_base) = 0;
++
++ CPMAC_RX_BUFFER_OFFSET(HalDev->dev_base) = 0;
++
++ /* Init Tx and Rx DMA */
++
++ CPMAC_TX_CONTROL(HalDev->dev_base) |= TX_EN;
++ CPMAC_RX_CONTROL(HalDev->dev_base) |= RX_EN;
++
++ CPMAC_MAC_INTMASK_SET(HalDev->dev_base) |=2; /* Enable Adaptercheck Ints */
++ HalDev->OsFunc->Control(HalDev->OsDev, pszMacAddr, hcGet, &MacAddr); /* GSG 11/22 */
++ MacAddressSave(HalDev, MacAddr);
++
++ HalDev->HostErr = 0; /* Clear Adapter Check indicator */
++ HalDev->State = enOpened; /* Change device state */
++
++ /* Start MDIO Negotiation */
++ AutoNegotiate(HalDev);
++
++ /* Enable the Os Timer */
++ Ticks = HalDev->CpuFrequency / 100; /* 10 milli-secs */ /*MJH~030402*/
++ HalDev->OsFunc->Control(HalDev->OsDev, pszTick, hcSet, &Ticks); /* GSG 11/22 */
++ HalDev->OsFunc->IsrRegister(HalDev->OsDev, halIsr, HalDev->interrupt);
++
++ /* GSG +030523 Malloc space for the Rx fraglist */
++ HalDev->fraglist = HalDev->OsFunc->Malloc(HalDev->MaxFrags * sizeof(FRAGLIST));
++
++ /* Any pre-open configuration */
++
++ /* For any channels that have been pre-initialized, set them up now */
++ /* Note : This loop should not use MAX_CHN, it should only
++ loop through Channels Setup, memory should not be reserved
++ until Channel is Setup
++ */
++ for(i=0; i<MAX_CHAN; i++) /* i loops through Channels */
++ for(j=0; j<2; j++) /* j loops through DIRECTION values, 0 and 1 */
++ {
++ if(HalDev->ChIsSetup[i][j]==TRUE) /* If the Channel and Direction have been Setup */
++ if(HalDev->ChIsOpen[i][j]==FALSE) /* but not opened, then Apply Values now */
++ {
++ CHANNEL_INFO HalChn;
++ HalChn.Channel = i;
++ HalChn.Direction = j;
++ rc = ChannelConfigApply(HalDev, &HalChn);
++ if(rc != EC_NO_ERRORS)
++ return(rc);
++ }
++ } /* End of looping through Channel/Direction */
++
++ ConfigApply(HalDev); /* Apply Configuration Values to Device */
++ CPMAC_MACCONTROL(HalDev->dev_base) |= MII_EN; /* MAC_EN */
++ if(DBG(0))
++ dbgPrintf("[halOpen]MacControl:%08X\n", CPMAC_MACCONTROL(HalDev->dev_base));
++ return(EC_NO_ERRORS);
++ }
++
++#define INT_PENDING (MAC_IN_VECTOR_TX_INT_OR | MAC_IN_VECTOR_RX_INT_OR | MAC_IN_VECTOR_HOST_INT)
++static int halShutdown(HAL_DEVICE *HalDev)
++ {
++ int Ch, Queue; /*GSG+030514*/
++
++ /* Verify proper device state */
++ if (HalDev->State == enOpened)
++ halClose(HalDev, 3); /* GSG ~030429 */
++
++ /* Buffer/descriptor resources may still need to be freed if a Close
++ Mode 1 was performed prior to Shutdown - clean up here */ /*GSG+030514*/
++ for (Ch=0; Ch<MAX_CHAN; Ch++)
++ {
++ if (HalDev->RcbStart[Ch] != 0)
++ FreeRx(HalDev,Ch);
++
++ for(Queue=0; Queue<MAX_QUEUE; Queue++)
++ {
++ if (HalDev->TcbStart[Ch][Queue] != 0)
++ FreeTx(HalDev,Ch,Queue);
++ }
++ }
++
++ /* free the HalFunc */
++ HalDev->OsFunc->Free(HalDev->HalFuncPtr);
++
++ /* free the HAL device */
++ HalDev->OsFunc->Free(HalDev);
++
++ return(EC_NO_ERRORS);
++ }
++int halIsr(HAL_DEVICE *HalDev, int *MorePackets)
++{
++ bit32u IntVec;
++ int Serviced;
++ int PacketsServiced=0;
++ int Channel;
++ int TxMorePackets=0;
++ int RxMorePackets=0;
++
++ /* Verify proper device state - important because a call prior to Open would
++ result in a lockup */
++ if (HalDev->State != enOpened)
++ return(EC_CPMAC|EC_FUNC_DEVICE_INT|EC_VAL_INVALID_STATE);
++
++ IntVec = CPMAC_MAC_IN_VECTOR(HalDev->dev_base);
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("\nhalIsr: inst %d, IntVec 0x%X\n", HalDev->inst, IntVec); osfuncSioFlush();/* GSG 11/22 */
++ }
++#endif
++
++ HalDev->IntVec = IntVec;
++ if (IntVec & MAC_IN_VECTOR_TX_INT_OR)
++ {
++ int TxServiceMax=0; /* Compiler complains if not initialized */
++
++ Channel = (IntVec & 0x7);
++
++ if(HalDev->TxIntDisable)
++ {
++ CPMAC_TX_INTMASK_CLEAR(HalDev->dev_base) = (1<<Channel); /* Disable Interrupt for Channel */
++ TxServiceMax = HalDev->ChData[Channel].TxServiceMax;
++ HalDev->ChData[Channel].TxServiceMax = 10000; /* Need to service all packets in the Queue */
++ }
++
++ PacketsServiced |= TxInt(HalDev, Channel, 0, &TxMorePackets);
++
++ if(HalDev->TxIntDisable)
++ HalDev->ChData[Channel].TxServiceMax = TxServiceMax;
++ }
++
++ if (IntVec & MAC_IN_VECTOR_RX_INT_OR)
++ {
++ Channel = (IntVec >> 8) & 0x7;
++ Serviced = RxInt(HalDev, Channel, &RxMorePackets);
++ PacketsServiced |= (Serviced<<16);
++ }
++
++ if (IntVec & MAC_IN_VECTOR_HOST_INT)
++ {
++ /* Adaptercheck */
++ HalDev->HostErr = 1;
++ HalDev->MacStatus = CPMAC_MACSTATUS(HalDev->dev_base);
++ osfuncStateChange(); /*MJH+030328*/
++ if(DBG(0))
++ {
++ dbgPrintf("Adaptercheck: %08x for base:%X\n",HalDev->MacStatus, (bit32u)HalDev->dev_base);
++ osfuncSioFlush();
++ }
++ }
++ *MorePackets = (TxMorePackets | RxMorePackets);
++ return (PacketsServiced);
++}
++
++int halPacketProcessEnd(HAL_DEVICE *HalDev)
++{
++ int base = HalDev->dev_base;
++ CPMAC_MAC_EOI_VECTOR(base) = 0;
++ return(0);
++}
++
++
++
++static int PhyCheck(HAL_DEVICE *HalDev)
++ {
++ return(cpMacMdioTic(HalDev->PhyDev));
++ }
++static int halTick(HAL_DEVICE *HalDev)
++{
++ int TickChange;
++
++ if(HalDev->State < enOpened)
++ return (EC_CPMAC|EC_FUNC_TICK|EC_VAL_INVALID_STATE);
++
++ /* if NO Phy no need to check Link */
++ if(HalDev->MdioConnect & _CPMDIO_NOPHY)
++ return(EC_NO_ERRORS); /* No change in Phy State detected */
++
++ TickChange = PhyCheck(HalDev);
++ /* Phy State Change Detected */
++ if(TickChange == 1)
++ {
++ /* MDIO indicated a change */
++ DuplexUpdate(HalDev);
++ osfuncStateChange();
++ return(EC_NO_ERRORS);
++ }
++
++ /* if in AutoMdix mode, and Flip request received, inform OS */
++ if( (HalDev->MdioConnect & _CPMDIO_AUTOMDIX) &&
++ (TickChange & _MIIMDIO_MDIXFLIP))
++ {
++ bit32u Mdix;
++ Mdix = TickChange & 0x1; /* Mdix mode stored in bit 0 */
++ HalDev->OsFunc->Control(HalDev->OsDev, hcMdioMdixSwitch, hcSet, &Mdix);
++ return(EC_NO_ERRORS);
++ }
++
++ return(EC_NO_ERRORS);
++}
++
++int halCpmacInitModule(HAL_DEVICE **pHalDev, OS_DEVICE *OsDev, HAL_FUNCTIONS **pHalFunc,
++ OS_FUNCTIONS *OsFunc, int OsFuncSize, int *HalFuncSize, int Inst)
++ {
++ HAL_DEVICE *HalDev;
++ HAL_FUNCTIONS *HalFunc;
++
++ if (OsFuncSize < sizeof(OS_FUNCTIONS))
++ return (EC_CPMAC|EC_FUNC_HAL_INIT|EC_VAL_OS_VERSION_NOT_SUPPORTED);
++
++ HalDev = (HAL_DEVICE *) OsFunc->MallocDev(sizeof(HAL_DEVICE));
++ if (!HalDev)
++ return (EC_CPMAC|EC_FUNC_HAL_INIT|EC_VAL_MALLOC_DEV_FAILED);
++
++ /* clear the HalDev area */
++ OsFunc->Memset(HalDev, 0, sizeof(HAL_DEVICE));
++
++ /* Initialize the size of hal functions */
++ *HalFuncSize = sizeof (HAL_FUNCTIONS);
++
++ HalFunc = (HAL_FUNCTIONS *) OsFunc->Malloc(sizeof(HAL_FUNCTIONS));
++ if (!HalFunc)
++ return (EC_CPMAC|EC_FUNC_HAL_INIT|EC_VAL_MALLOC_FAILED);
++
++ /* clear the function pointers */
++ OsFunc->Memset(HalFunc, 0, sizeof(HAL_FUNCTIONS));
++
++ HalDev->OsDev = OsDev;
++ HalDev->OsOpen = OsDev;
++ HalDev->inst = Inst;
++ HalDev->OsFunc = OsFunc;
++ HalDev->HalFunc = HalFunc;
++ /* Remove the following from cppi, replace with HalFunc */
++ HalDev->HalFuncPtr = HalFunc; /* GSG 11/20 changed name to match cppi */
++
++ /****************************************************************/
++ /* POPULATE HALFUNC */
++ /****************************************************************/
++ HalFunc->ChannelSetup = halChannelSetup;
++ HalFunc->ChannelTeardown = halChannelTeardown; /* GSG 11/20 */
++ HalFunc->Close = halClose; /* GSG 11/20 */
++ HalFunc->Control = halControl; /* GSG 11/22 */
++ HalFunc->Init = halInit;
++ HalFunc->Open = halOpen;
++ HalFunc->PacketProcessEnd = halPacketProcessEnd;
++ HalFunc->Probe = halProbe;
++ HalFunc->RxReturn = halRxReturn;
++ HalFunc->Send = halSend;
++ HalFunc->Shutdown = halShutdown;
++ HalFunc->Tick = halTick;
++
++ /* HalFunc->Status = halStatus;*/ /* GSG 11/22 */
++ /* pass the HalDev and HalFunc back to the caller */
++
++ *pHalDev = HalDev;
++ *pHalFunc = HalFunc;
++
++ HalDev->State = enConnected; /* Initialize the hardware state */
++
++ if (HalDev->debug) HalDev->OsFunc->Printf("halCpmacInitModule: Leave\n");
++ return(0);
++ }
++
++int cpmacRandomRange(HAL_DEVICE *HalDev, int min, int max)
++{
++ int iTmp;
++ iTmp = cpmacRandom(HalDev);
++ iTmp %= ((max-min)+1);
++ iTmp += min;
++ return(iTmp);
++}
++
++int cpmacRandom(HAL_DEVICE *HalDev)
++{
++ int iTmp;
++ iTmp = CPMAC_BOFFTEST(HalDev->dev_base);
++ iTmp >>= 16; /* get rndnum field */
++ iTmp &= (0x3FF); /* field is 10 bits wide */
++ return(iTmp);
++}
+diff -urN linux.old/drivers/net/avalanche_cpmac/hcpmac.h linux.dev/drivers/net/avalanche_cpmac/hcpmac.h
+--- linux.old/drivers/net/avalanche_cpmac/hcpmac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/hcpmac.h 2005-07-12 02:48:42.175574000 +0200
+@@ -0,0 +1,383 @@
++/** @file***********************************************************************
++ * TNETDxxxx Software Support
++ * Copyright (c) 2002 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ * FILE:
++ *
++ * DESCRIPTION:
++ * This file contains definitions for the HAL EMAC API
++ *
++ * HISTORY:
++ * xxXxx01 Denis 1.00 Original Version created.
++ * 22Jan02 Denis/Mick 1.01 Modified for HAL EMAC API
++ * 24Jan02 Denis/Mick 1.02 Speed Improvements
++ * 28Jan02 Denis/Mick 1.16 Made function calls pointers
++ * 28Jan02 Mick 1.18 Split into separate modules
++ * @author Michael Hanrahan
++ * @version 1.02
++ * @date 24-Jan-2002
++ *****************************************************************************/
++#ifndef _INC_HCPMAC
++#define _INC_HCPMAC
++
++/** \namespace CPMAC_Version
++This documents version 01.07.04 of the CPMAC CPHAL.
++*/
++const char *pszVersion_CPMAC="CPMAC 01.07.08 "__DATE__" "__TIME__;
++
++/* CHECK THESE LOCATIONS */
++#define TEARDOWN_VAL 0xfffffffc
++#define CB_OFFSET_MASK 0xFFFF0000
++
++
++#define MAX_CHAN 8
++#define MAX_QUEUE 1
++
++typedef struct
++ {
++ bit32 HNext; /*< Hardware's pointer to next buffer descriptor */
++ bit32 BufPtr; /*< Pointer to the data buffer */
++ bit32 Off_BLen; /*< Contains buffer offset and buffer length */
++ bit32 mode; /*< SOP, EOP, Ownership, EOQ, Teardown, Q Starv, Length */
++ void *Next;
++ void *OsInfo;
++ void *Eop;
++#ifdef __CPHAL_DEBUG
++ bit32 DbgSop;
++ bit32 DbgData;
++ bit32 DbgFraglist;
++#endif
++ }HAL_TCB;
++
++typedef volatile struct hal_private
++ {
++ bit32 HNext; /*< Hardware's pointer to next buffer descriptor */
++ bit32 BufPtr; /*< Pointer to the data buffer */
++ bit32 Off_BLen; /*< Contains buffer offset and buffer length */
++ bit32 mode; /*< SOP, EOP, Ownership, EOQ, Teardown Complete bits */
++ void *DatPtr;
++ void *Next;
++ void *OsInfo;
++ void *Eop;
++ }HAL_RCB;
++
++#define MAX_NEEDS 512 /*MJH+030409*/
++/* HAL */
++
++typedef struct hal_device
++ {
++ OS_DEVICE *OsDev;
++ OS_FUNCTIONS *OsFunc;
++ /*OS_SETUP *OsSetup;*/ /* -GSG 030508 */
++ int inst;
++ bit32u rxbufseq;
++
++
++ bit32 dev_base;
++ bit32 offset;
++
++ bit32u ResetBase; /* GSG 10/20 */
++ int ResetBit;
++ void *OsOpen;
++ bit32u IntVec;
++ PHY_DEVICE *PhyDev;
++ bit32u EmacDuplex;
++ bit32u EmacSpeed;
++ bit32u PhyNum;
++ bit32u MLinkMask;
++ bit32u PhyMask;
++ bit32u MdixMask;
++
++ bit32u Linked;
++ DEVICE_STATE State;
++ unsigned char *MacAddr;
++ HAL_FUNCTIONS *HalFuncPtr; /* GSG 11/20 changed name to match cppi */
++ HAL_FUNCTIONS *HalFunc;
++/* unsigned int CpuFreq;*/ /*MJH-030402*/
++ unsigned int MdioConnect;
++ unsigned int HostErr;
++
++/************************************************************************/
++/* */
++/* R E G I S T E R S */
++/* */
++/************************************************************************/
++
++ bit32u RxMbpEnable;
++ bit32u RxUnicastSet;
++ bit32u RxUnicastClear;
++ bit32u RxMaxLen;
++ bit32u RxFilterLowThresh;
++ bit32u Rx0FlowThresh;
++ bit32u MacControl;
++ bit32u MacStatus;
++ bit32u MacHash1;
++ bit32u MacHash2;
++
++/************************************************************************/
++/* */
++/* O P T I O N S */
++/* */
++/************************************************************************/
++
++ char *DeviceInfo;
++ bit32u interrupt;
++
++
++ bit32u RxPassCrc;
++ bit32u RxCaf;
++ bit32u RxCef;
++ bit32u RxBcast;
++ bit32u RxBcastCh;
++ HAL_RCB *RcbPool[MAX_CHAN];
++ bit32 RxActQueueCount[MAX_CHAN];
++ HAL_RCB *RxActQueueHead[MAX_CHAN];
++ HAL_RCB *RxActQueueTail[MAX_CHAN];
++ bit32 RxActive[MAX_CHAN];
++ HAL_TCB *TcbPool[MAX_CHAN][MAX_QUEUE];
++ bit32 TxActQueueCount[MAX_CHAN][MAX_QUEUE];
++ HAL_TCB *TxActQueueHead[MAX_CHAN][MAX_QUEUE];
++ HAL_TCB *TxActQueueTail[MAX_CHAN][MAX_QUEUE];
++ bit32 TxActive[MAX_CHAN][MAX_QUEUE];
++ bit32 TxTeardownPending[MAX_CHAN];
++ bit32 RxTeardownPending[MAX_CHAN];
++ bit32 ChIsOpen[MAX_CHAN][2];
++ bit32 ChIsSetup[MAX_CHAN][2];
++ FRAGLIST *fraglist;
++ char *TcbStart[MAX_CHAN][MAX_QUEUE];
++ char *RcbStart[MAX_CHAN];
++ bit32 RcbSize[MAX_CHAN];
++/* STAT_INFO Stats; */
++ bit32 Inst;
++ bit32u BuffersServicedMax;
++ CHANNEL_INFO ChData[MAX_CHAN];
++ bit32u MdioClockFrequency; /*MJH+030402*/
++ bit32u MdioBusFrequency; /*MJH+030402*/
++ bit32u CpuFrequency; /*MJH+030402*/
++ bit32u CpmacFrequency; /*MJH+030403*/
++ bit32u CpmacSize; /*MJH+030425*/
++ int debug;
++ bit32u NeedsCount; /*MJH+030409*/
++ HAL_RECEIVEINFO *Needs[MAX_NEEDS]; /*MJH+030409*/
++ int MaxFrags;
++ int TxIntThreshold[MAX_CHAN]; /* MJH 040621 NSP Performance Update */
++ int TxIntThresholdMaster[MAX_CHAN]; /* MJH 040827 NSP Performance Update */
++ int TxIntDisable; /* MJH 040621 NSP Performance Update */
++ }HALDEVICE;
++
++#define STATS_MAX 36
++
++#define MACCONTROL_MASK (TX_PTYPE|TX_PACE|TX_FLOW_EN|RX_FLOW_EN|CTRL_LOOPBACK)
++#define RX_MBP_ENABLE_MASK \
++ (RX_PASS_CRC|RX_QOS_EN|RX_NO_CHAIN| \
++ RX_CMF_EN|RX_CSF_EN|RX_CEF_EN|RX_CAF_EN|RX_PROM_CH_MASK| \
++ RX_BROAD_EN|RX_BROAD_CH_MASK|RX_MULT_EN|RX_MULT_CH_MASK)
++
++
++#define MBP_UPDATE(Mask, On) \
++ if(On) HalDev->RxMbpEnable |= Mask; \
++ else HalDev->RxMbpEnable &= ~Mask
++
++#define CONTROL_UPDATE(Mask, On) \
++ if(On) HalDev->MacControl |= Mask; \
++ else HalDev->MacControl &= ~Mask
++
++
++#define UPDATE_TX_PTYPE(Value) CONTROL_UPDATE(TX_PTYPE,Value)
++#define UPDATE_TX_PACE(Value) CONTROL_UPDATE(TX_PACE,Value)
++#define UPDATE_MII_EN(Value) CONTROL_UPDATE(MII_EN,Value)
++#define UPDATE_TX_FLOW_EN(Value) CONTROL_UPDATE(TX_FLOW_EN,Value)
++#define UPDATE_RX_FLOW_EN(Value) CONTROL_UPDATE(RX_FLOW_EN,Value)
++#define UPDATE_CTRL_LOOPBACK(Value) CONTROL_UPDATE(CTRL_LOOPBACK,Value)
++#define UPDATE_FULLDUPLEX(Value) CONTROL_UPDATE(FULLDUPLEX,(Value))
++
++#define UPDATE_RX_PASS_CRC(Value) MBP_UPDATE(RX_PASS_CRC, Value)
++#define UPDATE_RX_QOS_EN(Value) MBP_UPDATE(RX_QOS_EN, Value)
++#define UPDATE_RX_NO_CHAIN(Value) MBP_UPDATE(RX_NO_CHAIN, Value)
++#define UPDATE_RX_CMF_EN(Value) MBP_UPDATE(RX_CMF_EN, Value)
++#define UPDATE_RX_CSF_EN(Value) MBP_UPDATE(RX_CSF_EN, Value)
++#define UPDATE_RX_CEF_EN(Value) MBP_UPDATE(RX_CEF_EN, Value)
++#define UPDATE_RX_CAF_EN(Value) MBP_UPDATE(RX_CAF_EN, Value)
++#define UPDATE_RX_BROAD_EN(Value) MBP_UPDATE(RX_BROAD_EN, Value)
++#define UPDATE_RX_MULT_EN(Value) MBP_UPDATE(RX_MULT_EN, Value)
++
++#define UPDATE_RX_PROM_CH(Value) \
++ HalDev->RxMbpEnable &= ~RX_PROM_CH_MASK; \
++ HalDev->RxMbpEnable |= RX_PROM_CH(Value)
++
++#define UPDATE_RX_BROAD_CH(Value) \
++ HalDev->RxMbpEnable &= ~RX_BROAD_CH_MASK; \
++ HalDev->RxMbpEnable |= RX_BROAD_CH(Value)
++
++#define UPDATE_RX_MULT_CH(Value) \
++ HalDev->RxMbpEnable &= ~RX_MULT_CH_MASK; \
++ HalDev->RxMbpEnable |= RX_MULT_CH(Value)
++
++
++
++typedef enum
++ {
++ /* CPMAC */
++ enCpmacStart=0,
++ enStats0,
++ enStats1,
++ enStats2,
++ enStats3,
++ enStats4,
++ enStatsDump,
++ enStatsClear,
++ enRX_PASS_CRC,
++ enRX_QOS_EN,
++ enRX_NO_CHAIN,
++ enRX_CMF_EN,
++ enRX_CSF_EN,
++ enRX_CEF_EN,
++ enRX_CAF_EN,
++ enRX_PROM_CH,
++ enRX_BROAD_EN,
++ enRX_BROAD_CH,
++ enRX_MULT_EN,
++ enRX_MULT_CH,
++
++ enTX_PTYPE,
++ enTX_PACE,
++ enMII_EN,
++ enTX_FLOW_EN,
++ enRX_FLOW_EN,
++ enCTRL_LOOPBACK,
++
++ enRX_MAXLEN,
++ enRX_FILTERLOWTHRESH,
++ enRX0_FLOWTHRESH,
++ enRX_UNICAST_SET,
++ enRX_UNICAST_CLEAR,
++ enMdioConnect,
++ enMAC_ADDR_GET,
++ enTick,
++ enRX_MULTICAST,
++ enRX_MULTI_ALL,
++ enRX_MULTI_SINGLE,
++ enVersion,
++ enCpmacEnd /* Last entry */
++ }INFO_KEY_CPMAC;
++
++static const char pszVersion[] = "Version";
++static const char pszStats0[] = "Stats0";
++static const char pszStats1[] = "Stats1";
++static const char pszStats2[] = "Stats2";
++static const char pszStats3[] = "Stats3";
++static const char pszStats4[] = "Stats4";
++static const char pszStatsDump[] = "StatsDump";
++static const char pszStatsClear[] = "StatsClear";
++
++/********************************************************************
++**
++** RX MBP ENABLE
++**
++********************************************************************/
++static const char pszRX_PASS_CRC[] = "RX_PASS_CRC";
++static const char pszRX_QOS_EN[] = "RX_QOS_EN";
++static const char pszRX_NO_CHAIN[] = "RX_NO_CHAIN";
++static const char pszRX_CMF_EN[] = "RX_CMF_EN";
++static const char pszRX_CSF_EN[] = "RX_CSF_EN";
++static const char pszRX_CEF_EN[] = "RX_CEF_EN";
++static const char pszRX_CAF_EN[] = "RX_CAF_EN";
++static const char pszRX_PROM_CH[] = "RX_PROM_CH";
++static const char pszRX_BROAD_EN[] = "RX_BROAD_EN";
++static const char pszRX_BROAD_CH[] = "RX_BROAD_CH";
++static const char pszRX_MULT_EN[] = "RX_MULT_EN";
++static const char pszRX_MULT_CH[] = "RX_MULT_CH";
++
++
++/********************************************************************
++**
++** MAC CONTROL
++**
++********************************************************************/
++static const char pszTX_PTYPE[] = "TX_PTYPE";
++static const char pszTX_PACE[] = "TX_PACE";
++static const char pszMII_EN[] = "MII_EN";
++static const char pszTX_FLOW_EN[] = "TX_FLOW_EN";
++static const char pszRX_FLOW_EN[] = "RX_FLOW_EN";
++static const char pszCTRL_LOOPBACK[] = "CTRL_LOOPBACK";
++
++static const char pszRX_MAXLEN[] = "RX_MAXLEN";
++static const char pszRX_FILTERLOWTHRESH[] = "RX_FILTERLOWTHRESH";
++static const char pszRX0_FLOWTHRESH[] = "RX0_FLOWTHRESH";
++static const char pszRX_UNICAST_SET[] = "RX_UNICAST_SET";
++static const char pszRX_UNICAST_CLEAR[] = "RX_UNICAST_CLEAR";
++static const char pszMdioConnect[] = "MdioConnect";
++static const char pszMacAddr[] = "MacAddr";
++static const char pszTick[] = "Tick";
++
++/********************************************************************
++**
++** MULTICAST
++**
++********************************************************************/
++
++static const char pszRX_MULTICAST[] = "RX_MULTICAST";
++static const char pszRX_MULTI_ALL[] = "RX_MULTI_ALL";
++static const char pszRX_MULTI_SINGLE[] = "RX_MULTI_SINGLE";
++
++/*
++static const char* pszGFHN = "GFHN";
++*/
++
++static const CONTROL_KEY KeyCpmac[] =
++ {
++ {"" , enCpmacStart},
++ {pszStats0 , enStats0},
++ {pszStats1 , enStats1},
++ {pszStats2 , enStats2},
++ {pszStats3 , enStats3},
++ {pszStats4 , enStats4},
++ {pszStatsClear , enStatsClear},
++ {pszStatsDump , enStatsDump},
++ {pszRX_PASS_CRC , enRX_PASS_CRC},
++ {pszRX_QOS_EN , enRX_QOS_EN},
++ {pszRX_NO_CHAIN , enRX_NO_CHAIN},
++ {pszRX_CMF_EN , enRX_CMF_EN},
++ {pszRX_CSF_EN , enRX_CSF_EN},
++ {pszRX_CEF_EN , enRX_CEF_EN},
++ {pszRX_CAF_EN , enRX_CAF_EN},
++ {pszRX_PROM_CH , enRX_PROM_CH},
++ {pszRX_BROAD_EN , enRX_BROAD_EN},
++ {pszRX_BROAD_CH , enRX_BROAD_CH},
++ {pszRX_MULT_EN , enRX_MULT_EN},
++ {pszRX_MULT_CH , enRX_MULT_CH},
++
++ {pszTX_PTYPE , enTX_PTYPE},
++ {pszTX_PACE , enTX_PACE},
++ {pszMII_EN , enMII_EN},
++ {pszTX_FLOW_EN , enTX_FLOW_EN},
++ {pszRX_FLOW_EN , enRX_FLOW_EN},
++ {pszCTRL_LOOPBACK , enCTRL_LOOPBACK},
++ {pszRX_MAXLEN , enRX_MAXLEN},
++ {pszRX_FILTERLOWTHRESH , enRX_FILTERLOWTHRESH},
++ {pszRX0_FLOWTHRESH , enRX0_FLOWTHRESH},
++ {pszRX_UNICAST_SET , enRX_UNICAST_SET},
++ {pszRX_UNICAST_CLEAR , enRX_UNICAST_CLEAR},
++ {pszMdioConnect , enMdioConnect},
++ {pszRX_MULTICAST , enRX_MULTICAST},
++ {pszRX_MULTI_ALL , enRX_MULTI_ALL},
++ {pszRX_MULTI_SINGLE , enRX_MULTI_SINGLE},
++ {pszTick , enTick},
++ {pszVersion , enVersion},
++ {"" , enCpmacEnd}
++ };
++
++const char hcCpuFrequency[] = "CpuFreq";
++const char hcCpmacFrequency[] = "CpmacFrequency";
++const char hcMdioBusFrequency[] = "MdioBusFrequency";
++const char hcMdioClockFrequency[] = "MdioClockFrequency";
++const char hcCpmacBase[] = "CpmacBase";
++const char hcPhyNum[] = "PhyNum";
++const char hcSize[] = "size";
++const char hcCpmacSize[] = "CpmacSize";
++const char hcPhyAccess[] = "PhyAccess";
++const char hcLinked[] = "Linked";
++const char hcFullDuplex[] = "FullDuplex";
++const char hcMdixMask[] = "MdixMask";
++const char hcMdioMdixSwitch[] = "MdixSet";
++#endif
+diff -urN linux.old/drivers/net/avalanche_cpmac/Makefile linux.dev/drivers/net/avalanche_cpmac/Makefile
+--- linux.old/drivers/net/avalanche_cpmac/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/Makefile 2005-07-12 02:48:42.175574000 +0200
+@@ -0,0 +1,26 @@
++# File: drivers/net/avalanche_cpmac/Makefile
++#
++# Makefile for the Linux network (CPMAC) device drivers.
++#
++
++O_TARGET := avalanche_cpmac.o
++
++
++list-multi := avalanche_cpmac.o
++obj-$(CONFIG_MIPS_AVALANCHE_CPMAC) := avalanche_cpmac.o
++
++avalanche_cpmac-objs += cpmac.o cpmacHalLx.o hcpmac.o \
++ psp_config_build.o psp_config_mgr.o \
++ psp_config_parse.o psp_config_util.o
++
++
++include $(TOPDIR)/Rules.make
++
++
++avalanche_cpmac.o: $(avalanche_cpmac-objs)
++ $(LD) -r -o $@ $(avalanche_cpmac-objs)
++
++
++
++clean:
++ rm -f core *.o *.a *.s
+diff -urN linux.old/drivers/net/avalanche_cpmac/mdio_reg.h linux.dev/drivers/net/avalanche_cpmac/mdio_reg.h
+--- linux.old/drivers/net/avalanche_cpmac/mdio_reg.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/mdio_reg.h 2005-07-12 02:48:42.176573000 +0200
+@@ -0,0 +1,121 @@
++/****************************************************************************
++** TNETD53xx Software Support
++** Copyright(c) 2002, Texas Instruments Incorporated. All Rights Reserved.
++**
++** FILE: mdio_reg.h Register definitions for the VBUS MII module
++**
++** DESCRIPTION:
++** This include file contains register definitions for the
++** VBUS MII module.
++**
++** HISTORY:
++** 27Mar02 Michael Hanrahan Original (modified from emacmdio.h)
++** 01Apr02 Michael Hanrahan Modified to include all regs. in spec
++** 03Apr02 Michael Hanrahan Updated to Version 0.6 of spec
++** 05Apr02 Michael Hanrahan Moved Phy Mode values into here
++** 30Apr02 Michael Hanrahan Updated to Version 0.8 of spec
++** 30Apr02 Michael Hanrahan Updated to recommended format
++** 10May02 Michael Hanrahan Updated to Version 0.9 of spec
++*****************************************************************************/
++#ifndef _INC_MDIO_REG
++#define _INC_MDIO_REG
++
++/***************************************************************************
++**
++** M D I O M E M O R Y M A P
++**
++***************************************************************************/
++
++
++#define pMDIO_VER(base) ((volatile bit32u *)(base+0x00))
++#define pMDIO_CONTROL(base) ((volatile bit32u *)(base+0x04))
++#define pMDIO_ALIVE(base) ((volatile bit32u *)(base+0x08))
++#define pMDIO_LINK(base) ((volatile bit32u *)(base+0x0C))
++#define pMDIO_LINKINTRAW(base) ((volatile bit32u *)(base+0x10))
++#define pMDIO_LINKINTMASKED(base) ((volatile bit32u *)(base+0x14))
++#define pMDIO_USERINTRAW(base) ((volatile bit32u *)(base+0x20))
++#define pMDIO_USERINTMASKED(base) ((volatile bit32u *)(base+0x24))
++#define pMDIO_USERINTMASKED_SET(base) ((volatile bit32u *)(base+0x28))
++#define pMDIO_USERINTMASKED_CLR(base) ((volatile bit32u *)(base+0x2C))
++#define pMDIO_USERACCESS(base, channel) ((volatile bit32u *)(base+(0x80+(channel*8))))
++#define pMDIO_USERPHYSEL(base, channel) ((volatile bit32u *)(base+(0x84+(channel*8))))
++
++
++/***************************************************************************
++**
++** M D I O R E G I S T E R A C C E S S M A C R O S
++**
++***************************************************************************/
++
++
++#define MDIO_ALIVE(base) (*(pMDIO_ALIVE(base)))
++#define MDIO_CONTROL(base) (*(pMDIO_CONTROL(base)))
++#define MDIO_CONTROL_IDLE (1 << 31)
++#define MDIO_CONTROL_ENABLE (1 << 30)
++#define MDIO_CONTROL_PREAMBLE (1 << 20)
++#define MDIO_CONTROL_FAULT (1 << 19)
++#define MDIO_CONTROL_FAULT_DETECT_ENABLE (1 << 18)
++#define MDIO_CONTROL_INT_TEST_ENABLE (1 << 17)
++#define MDIO_CONTROL_HIGHEST_USER_CHANNEL (0x1F << 8)
++#define MDIO_CONTROL_CLKDIV (0xFF)
++#define MDIO_LINK(base) (*(pMDIO_LINK(base)))
++#define MDIO_LINKINTRAW(base) (*(pMDIO_LINKINTRAW(base)))
++#define MDIO_LINKINTMASKED(base) (*(pMDIO_LINKINTMASKED(base)))
++#define MDIO_USERINTRAW(base) (*(pMDIO_USERINTRAW(base)))
++#define MDIO_USERINTMASKED(base) (*(pMDIO_USERINTMASKED(base)))
++#define MDIO_USERINTMASKED_CLR(base) (*(pMDIO_USERINTMASKED_CLR(base)))
++#define MDIO_USERINTMASKED_SET(base) (*(pMDIO_USERINTMASKED_SET(base)))
++#define MDIO_USERINTRAW(base) (*(pMDIO_USERINTRAW(base)))
++#define MDIO_USERACCESS(base, channel) (*(pMDIO_USERACCESS(base, channel)))
++#define MDIO_USERACCESS_GO (1 << 31)
++#define MDIO_USERACCESS_WRITE (1 << 30)
++#define MDIO_USERACCESS_READ (0 << 30)
++#define MDIO_USERACCESS_ACK (1 << 29)
++#define MDIO_USERACCESS_REGADR (0x1F << 21)
++#define MDIO_USERACCESS_PHYADR (0x1F << 16)
++#define MDIO_USERACCESS_DATA (0xFFFF)
++#define MDIO_USERPHYSEL(base, channel) (*(pMDIO_USERPHYSEL(base, channel)))
++#define MDIO_USERPHYSEL_LINKSEL (1 << 7)
++#define MDIO_USERPHYSEL_LINKINT_ENABLE (1 << 6)
++#define MDIO_USERPHYSEL_PHYADR_MON (0x1F)
++#define MDIO_VER(base) (*(pMDIO_VER(base)))
++#define MDIO_VER_MODID (0xFFFF << 16)
++#define MDIO_VER_REVMAJ (0xFF << 8)
++#define MDIO_VER_REVMIN (0xFF)
++
++
++
++
++/****************************************************************************/
++/* */
++/* P H Y R E G I S T E R D E F I N I T I O N S */
++/* */
++/****************************************************************************/
++
++
++#define PHY_CONTROL_REG 0
++ #define PHY_RESET (1<<15)
++ #define PHY_LOOP (1<<14)
++ #define PHY_100 (1<<13)
++ #define AUTO_NEGOTIATE_EN (1<<12)
++ #define PHY_PDOWN (1<<11)
++ #define PHY_ISOLATE (1<<10)
++ #define RENEGOTIATE (1<<9)
++ #define PHY_FD (1<<8)
++
++#define PHY_STATUS_REG 1
++ #define NWAY_COMPLETE (1<<5)
++ #define NWAY_CAPABLE (1<<3)
++ #define PHY_LINKED (1<<2)
++
++#define NWAY_ADVERTIZE_REG 4
++#define NWAY_REMADVERTISE_REG 5
++ #define NWAY_FD100 (1<<8)
++ #define NWAY_HD100 (1<<7)
++ #define NWAY_FD10 (1<<6)
++ #define NWAY_HD10 (1<<5)
++ #define NWAY_SEL (1<<0)
++ #define NWAY_AUTO (1<<0)
++
++
++#endif _INC_MDIO_REG
+diff -urN linux.old/drivers/net/avalanche_cpmac/psp_config_build.c linux.dev/drivers/net/avalanche_cpmac/psp_config_build.c
+--- linux.old/drivers/net/avalanche_cpmac/psp_config_build.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/psp_config_build.c 2005-07-12 02:48:42.176573000 +0200
+@@ -0,0 +1,335 @@
++/******************************************************************************
++ * FILE PURPOSE: PSP Config Manager - Configuration Build Source
++ ******************************************************************************
++ * FILE NAME: psp_config_build.c
++ *
++ * DESCRIPTION: Configuration Build API Implementation
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++#ifdef INCLUDE_FFS
++#include "ffs.h"
++#endif /* INCLUDE_FFS */
++
++#include "psp_config_mgr.h"
++#include "psp_config_build.h"
++#include "psp_config_util.h"
++
++#define MAX_DEVICE_NAME_LEN 16
++#define MAX_DEVICE_STR_LEN 512
++
++#ifndef NULL
++#define NULL (char *)0
++#endif
++
++#include <asm/ar7/sangam.h>
++#include <linux/slab.h>
++#include <linux/config.h>
++
++
++#define os_malloc(size) kmalloc(size, GFP_KERNEL)
++
++int psp_run_enumerator(void)
++{
++ return(0);
++}
++
++#if defined (CONFIG_AVALANCHE_CPMAC_AUTO)
++
++static int auto_detect_cpmac_phy(void)
++{
++
++#define SELECT_INT_PHY_MAC 0
++#define SELECT_EXT_PHY_MAC 1
++
++ volatile unsigned long *reset_cntl = AVALANCHE_RESET_CONTROL_BASE, *mdio_cntl = ((int)AVALANCHE_MDIO_BASE + 0x4);
++ unsigned int j= 0, detected_phy_map = 0, auto_select = SELECT_INT_PHY_MAC;
++
++ *reset_cntl |= (1 << AVALANCHE_MDIO_RESET_BIT) | (1 << AVALANCHE_LOW_CPMAC_RESET_BIT) | (1 << AVALANCHE_HIGH_CPMAC_RESET_BIT) | (1 << AVALANCHE_LOW_EPHY_RESET_BIT);
++ *mdio_cntl = (1 << 30) | ((CONFIG_AR7_SYS * 1000)/2200);
++
++ for(j=0;j < 300000; j++)
++ {
++ if(j%100000) continue;
++
++ detected_phy_map = *(mdio_cntl + 1);
++ if(detected_phy_map)
++ {
++ detected_phy_map &= ~AVALANCHE_LOW_CPMAC_PHY_MASK;
++
++ if(detected_phy_map && !(detected_phy_map & (detected_phy_map - 1)))
++ {
++ auto_select = SELECT_EXT_PHY_MAC;
++ break;
++ }
++ }
++ }
++
++ return(auto_select);
++
++}
++
++#endif
++
++
++#ifndef AVALANCHE_LOW_CPMAC_MDIX_MASK
++#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0
++#endif
++
++void psp_load_default_static_cfg(void)
++{
++ char s2[100], s3[100];
++ char s4[2000], s6[2000];
++ int threshold = 20;
++ char *tx_threshold_ptr = prom_getenv("threshold");
++
++ if(tx_threshold_ptr)
++ threshold = simple_strtol(tx_threshold_ptr, (char **)NULL, 10);
++
++ /* Static configuration if options.conf not present */
++ sprintf(s3,"cpmdio(id=mii, base=%u, reset_bit=%d)", AVALANCHE_MDIO_BASE, 22);
++ sprintf(s2, "reset( id=[ResetRegister], base=%u)", AVALANCHE_RESET_CONTROL_BASE);
++
++ sprintf(s4, "cpmac(id=[cpmac], unit=0, base=%u, size=0x800, reset_bit=%d, PhyMask=%u, MdixMask=%u, MLink=0, int_line=%d, memory_offset=0, RX_CAF=1, RX_PASSCRC=0, RX_CEF=1, RX_BCAST=0, RX_BCASTCH=0, Ch0=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128], Ch1=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128], Ch2=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128])", AVALANCHE_LOW_CPMAC_BASE, AVALANCHE_LOW_CPMAC_RESET_BIT, AVALANCHE_LOW_CPMAC_PHY_MASK, AVALANCHE_LOW_CPMAC_MDIX_MASK, AVALANCHE_LOW_CPMAC_INT,threshold,threshold,threshold);
++
++ sprintf(s6, "cpmac(id=[cpmac], unit=1, base=%u, size=0x800, reset_bit=%d, PhyMask=%u, MLink=0, int_line=%d, memory_offset=0, RX_CAF=1, RX_PASSCRC=0, RX_CEF=1, RX_BCAST=0, RX_BCASTCH=0, Ch0=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128], Ch1=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128], Ch2=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128])", AVALANCHE_HIGH_CPMAC_BASE, AVALANCHE_HIGH_CPMAC_RESET_BIT, AVALANCHE_HIGH_CPMAC_PHY_MASK, AVALANCHE_HIGH_CPMAC_INT,threshold,threshold,threshold);
++
++ psp_config_add("reset", s2, psp_config_strlen(s2), en_compile);
++
++
++#if defined (CONFIG_AVALANCHE_LOW_CPMAC)
++
++ psp_config_add("cpmdio", s3, psp_config_strlen(s3), en_compile);
++ psp_config_add("cpmac", s4, psp_config_strlen(s4), en_compile);
++
++#endif
++
++
++#if defined (CONFIG_AVALANCHE_HIGH_CPMAC)
++
++ psp_config_add("cpmdio", s3, psp_config_strlen(s3), en_compile);
++ psp_config_add("cpmac", s6, psp_config_strlen(s6), en_compile);
++
++#endif
++
++#if defined (CONFIG_AVALANCHE_CPMAC_AUTO)
++ {
++ char *phy_sel_ptr = prom_getenv("mac_phy_sel");
++ int phy_sel = SELECT_EXT_PHY_MAC;
++ char *mac_port = prom_getenv("MAC_PORT"); /* Internal: 0, External: 1 */
++
++ if(phy_sel_ptr && (0 == strcmp(phy_sel_ptr, "int")))
++ {
++ phy_sel = SELECT_INT_PHY_MAC;
++ }
++
++ //if(phy_sel == auto_detect_cpmac_phy())
++ if(0 == strcmp(mac_port, "1"))
++ {
++ printk("Using the MAC with external PHY\n");
++ psp_config_add("cpmdio", s3, psp_config_strlen(s3), en_compile);
++ psp_config_add("cpmac", s6, psp_config_strlen(s6), en_compile);
++ }
++ else
++ {
++ printk("Using the MAC with internal PHY\n");
++ psp_config_add("cpmdio", s3, psp_config_strlen(s3), en_compile);
++ psp_config_add("cpmac", s4, psp_config_strlen(s4), en_compile);
++ }
++ }
++
++#endif
++
++}
++
++char* psp_conf_read_file(char *p_file_name)
++{
++#ifdef INCLUDE_FFS
++
++ char *p_file_data = NULL;
++ unsigned int file_size;
++ FFS_FILE *p_file = NULL;
++
++ if(p_file_name == NULL)
++ {
++ return (NULL);
++ }
++
++ if(!(p_file = ffs_fopen(p_file_name, "r")))
++ {
++ return(NULL);
++ }
++
++ file_size = p_file->_AvailableBytes;
++
++ p_file_data = os_malloc(file_size + 1);
++
++ if(ffs_fread(p_file_data, file_size, 1, p_file) == 0)
++ {
++ kfree(p_file_data);
++ return(NULL);
++ }
++
++ ffs_fclose(p_file);
++
++ p_file_data[file_size] = '\0';
++
++ return(p_file_data);
++
++#else /* NO FFS */
++ return(NULL);
++#endif /* INCLUDE_FFS */
++}
++
++int psp_conf_get_line(char *p_in_data, char **next_line)
++{
++ char *p = p_in_data;
++
++ while(*p && *p++ != '\n')
++ {
++
++ }
++
++ *next_line = p;
++
++ return(p - 1 - p_in_data);
++}
++
++
++int psp_conf_is_data_line(char *line)
++{
++ int ret_val = 1;
++
++ if(*line == '\0' || *line == '\n' || *line == '#')
++ ret_val = 0;
++
++ return(ret_val);
++}
++
++int psp_conf_get_key_size(char *data)
++{
++ char *p = data;
++
++ while(*p && *p != '\n' && *p != '(' && *p != ' ')
++ p++;
++
++ return(p - data);
++}
++
++char* psp_conf_eat_white_spaces(char *p)
++{
++ while(*p && *p != '\n' && *p == ' ')
++ p++;
++
++ return (p);
++}
++
++int psp_build_from_opt_conf(void)
++{
++ char *data = NULL;
++ char *data_hold = NULL;
++ char *next_line = NULL;
++ int line_size = 0;
++
++ if((data = psp_conf_read_file("/etc/options.conf")) == NULL)
++ return(-1);
++
++ data_hold = data;
++
++ while((line_size=psp_conf_get_line(data, &next_line)) != -1)
++ {
++
++ char *name = NULL;
++ int name_size;
++
++ data = psp_conf_eat_white_spaces(data);
++
++ if(psp_conf_is_data_line(data))
++ {
++ data[line_size] = '\0';
++
++ name_size = psp_conf_get_key_size(data);
++
++ if(name_size > 0)
++ {
++ name = (char *) os_malloc(name_size + 1);
++ if(name == NULL) break;
++
++ psp_config_memcpy(name, data, name_size);
++ name[name_size] = '\0';
++
++ psp_config_add(name, data, line_size, en_opt_conf);
++
++ kfree(name);
++ }
++
++ data[line_size] = '\n';
++ }
++
++ data = next_line;
++ }
++
++ kfree(data_hold);
++ return (0);
++}
++
++
++int psp_write_conf_file(char *p_write_file, char * dev_cfg_string)
++{
++#ifdef INCLUDE_FFS
++ int bytes_written=0;
++ FFS_FILE *file_ptr=NULL;
++
++ /*
++ * NOTE: In current implementation of FFS in ADAM2 if the file exists beforehand, it
++ * can't be opened for write.
++ */
++ if(!(file_ptr=ffs_fopen(p_write_file, "w"))) {
++ return(-1);
++ }
++
++ /* Write into the file "output.con" the character string */
++ /* write a \n before a writing a line */
++ if(!(bytes_written = ffs_fwrite("\n", 1, sizeof(char), file_ptr))) {
++ return (-1);
++ }
++
++ if(!(bytes_written = ffs_fwrite(dev_cfg_string, psp_config_strlen(dev_cfg_string), sizeof(char), file_ptr))) {
++ return (-1);
++ }
++ ffs_fclose(file_ptr);
++ return (bytes_written+1);
++#else /* NO FFS */
++ return(-1);
++#endif /* INCLUDE_FFS */
++}
++
++void build_psp_config(void)
++{
++
++ /* initialize the repository. */
++ psp_config_init();
++
++#ifdef INCLUDE_FFS
++ ffs_init();
++#endif /* INCLUDE_FFS */
++
++ /* read the configuration from the options.conf to override default ones */
++ psp_build_from_opt_conf();
++
++ /* read the configuration which were not over ridden in options.conf */
++ psp_load_default_static_cfg();
++
++ /* let the vlynq be enumerated. Enumerator will add cfg info
++ of the discovered device instances to the repository.*/
++ psp_run_enumerator();
++
++ /* dump the repository*/
++ dump_device_cfg_pool();
++
++}
++
+diff -urN linux.old/drivers/net/avalanche_cpmac/psp_config_build.h linux.dev/drivers/net/avalanche_cpmac/psp_config_build.h
+--- linux.old/drivers/net/avalanche_cpmac/psp_config_build.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/psp_config_build.h 2005-07-12 02:48:42.176573000 +0200
+@@ -0,0 +1,138 @@
++/******************************************************************************
++ * FILE PURPOSE: PSP Config Manager - Configuration Build Header
++ ******************************************************************************
++ * FILE NAME: psp_config_build.h
++ *
++ * DESCRIPTION: Configuration Build API's.
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++#ifndef __PSP_CONF_BUILD_H__
++#define __PSP_CONF_BUILD_H__
++
++/*------------------------------------------------------------------------------
++ * Name: psp_conf_read_file
++ *
++ * Parameters:
++ * in: p_file_name - the name of the file to read from.
++ *
++ * Description:
++ * Reads the entire file in one shot. This function opens the
++ * file, determines the size of the data to be read, allocates
++ * the required memory, NULL terminates the data and closes the
++ * file.
++ *
++ * It is responsibily of the callee to free the memory after it is
++ * done with that data.
++ *
++ *
++ * Returns:
++ * A NULL pointer, if failed to read the data otherwise, a valid
++ * pointer referring to the data read from the file.
++ *
++ * Example:
++ *
++ * psp_conf_read_file("/etc/options.conf");
++ *---------------------------------------------------------------------------*/
++ char *psp_conf_read_file(char *p_file_name);
++
++ /*----------------------------------------------------------------------------
++ * Function : psp_conf_write_file
++ *
++ * Parameters:
++ * in: p_file_name - the file to which data is to be written.
++ * in: data - the NULL terminated data string.
++ *
++ * Description:
++ * Write the indicated data into the file. This function opens the file,
++ * appends the data to end of the file, closes the file.
++ *
++ * Returns:
++ *
++ * The number of bytes on success.
++ * 0 on failure.
++ *
++ * Example:
++ *
++ * psp_conf_write_file("/etc/outcon.conf", data);
++ *--------------------------------------------------------------------------*/
++ int psp_conf_write_file(char *p_file_name, char *data);
++
++ /*----------------------------------------------------------------------------
++ * Function: psp_conf_get_line
++ *
++ * Parameters:
++ * in: data - the data from which the line is to identified.
++ * out: next_line - the pointer to start of the next line.
++ *
++ * Description:
++ * Expects the data to be '\n' separated segments and data is NULL
++ * terminated. Parses the given data for '\n' or '\0'. Provides a pointer
++ * to the start of next line in the next_line.
++ *
++ * Returns:
++ * -1 on error.
++ * 0 or more to indicate the number of bytes in the line starting at
++ * data.
++ *--------------------------------------------------------------------------*/
++ int psp_get_conf_line(char *p_in_data, char **next_line);
++
++ /*----------------------------------------------------------------------------
++ * Function: psp_conf_is_data_line
++ *
++ * Parameters:
++ * in: line - the array of bytes.
++ *
++ * Description:
++ * Tests the first byte in the array for '\0' or '\n' or '#'. Lines
++ * starting with these characters are not considered data.
++ *
++ * Returns:
++ * 1 if the line has data.
++ * 0 otherwise.
++ *
++ *--------------------------------------------------------------------------*/
++ int psp_conf_is_data_line(char *line);
++
++ /*----------------------------------------------------------------------------
++ * Function: psp_conf_eat_white_spaces
++ *
++ * Parameters:
++ * in: line - the array of bytes.
++ *
++ * Description:
++ * Eats white spaces at the begining of the line while looking out for
++ * '\0' or '\n' or ' '.
++ *
++ * Returns:
++ * Pointer to the begining of the non white space character.
++ * NULL if '\0' or '\n' is found.
++ *
++ *--------------------------------------------------------------------------*/
++ char *psp_conf_eat_white_spaces(char *line);
++
++ /*---------------------------------------------------------------------------
++ * Function: psp_conf_get_key_size
++ *
++ * Parameters:
++ * in: line - the array of bytes.
++ *
++ * Description:
++ * Identifies the size of the 'key' in array formatted as
++ * key(id=[key1]....). This function also checks out for '\0' and '\n'.
++ *
++ * Returns:
++ * On success, The number of bytes that forms the key.
++ * 0 otherwise.
++ *
++ *-------------------------------------------------------------------------*/
++ int psp_conf_get_key_size(char *line);
++
++
++
++#endif /* __PSP_CONF_BUILD_H__ */
++
+diff -urN linux.old/drivers/net/avalanche_cpmac/psp_config_mgr.c linux.dev/drivers/net/avalanche_cpmac/psp_config_mgr.c
+--- linux.old/drivers/net/avalanche_cpmac/psp_config_mgr.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/psp_config_mgr.c 2005-07-12 02:48:42.177573000 +0200
+@@ -0,0 +1,464 @@
++/******************************************************************************
++ * FILE PURPOSE: PSP Config Manager Source
++ ******************************************************************************
++ * FILE NAME: psp_config_mgr.c
++ *
++ * DESCRIPTION:
++ *
++ * Manages configuration information. The repository is managed on the basis of
++ * <key, info> pair. It is possible to have multiple occurrence of the same key.
++ * Multiple occurences of the same keys are referred to as 'instances'.
++ * 'instances' are assigned in the order of configuration arrival. The first
++ * config for a 'key' added to the repository would be treated as instance 0 and
++ * next config to arrive for the same key would be treated as instance '1' and
++ * so on.
++ *
++ * Info is retrieved from the repository based on the 'key' and 'instance' value.
++ *
++ * No assumption is made about the format of the information that is put in the
++ * repository. The only requirement is that 'key' should be NULL terminated
++ * string.
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++//#include <stdio.h>
++//#include <stdlib.h>
++#include "psp_config_mgr.h"
++#include "psp_config_util.h"
++
++#include <linux/slab.h>
++
++/*-----------------------------------------------------------
++ Implemented elsewhere
++ -----------------------------------------------------------*/
++extern int sys_read_options_conf(void);
++extern int sys_write_options_conf(char *cfg_info);
++extern int sys_load_default_static_cfg(void);
++extern int sys_run_enumerator(void);
++
++#define os_malloc(size) kmalloc(size, GFP_KERNEL)
++
++/*---------------------------------------------------------
++ * Data structures.
++ *--------------------------------------------------------*/
++struct device_cfg_data;
++
++typedef struct device_instance_cfg_data
++{
++ struct device_instance_cfg_data *next;
++ char locale[100];
++ unsigned int data_size;
++ char *data;
++
++} DEV_INSTANCE_CFG_DATA_T;
++
++struct device_cfg_collection;
++
++typedef struct device_cfg_collection
++{
++ struct device_cfg_collection *next;
++ char *device_name;
++ CFG_TYPE_T cfg_type;
++ int count;
++ DEV_INSTANCE_CFG_DATA_T *dev_inst_list_begin;
++ DEV_INSTANCE_CFG_DATA_T *dev_inst_list_end;
++} DEVICE_CFG_T;
++
++
++typedef struct device_cfg_list
++{
++ DEVICE_CFG_T *device_cfg_begin;
++ int count;
++} DEVICE_CFG_LIST_T;
++
++/*-----------------------------------------------------------------------------
++ * Functions used locally with in the file.
++ *---------------------------------------------------------------------------*/
++static void p_init_device_cfg_list(void);
++static int p_add_instance_cfg_data(DEVICE_CFG_T *p_dev_cfg,
++ DEV_INSTANCE_CFG_DATA_T *p_dev_inst_data);
++static DEVICE_CFG_T* p_create_dev_cfg(char *device_name);
++static DEVICE_CFG_T* p_get_dev_cfg(char *device_name);
++static int p_set_device_cfg_type(DEVICE_CFG_T *p_dev_cfg,
++ CFG_TYPE_T cfg_type);
++
++/* PSP Config manager debug */
++#define PSP_CFG_MGR_DEBUG 0
++
++#define dbgPrint if (PSP_CFG_MGR_DEBUG) printk
++
++/*-----------------------------------------------------------------------------
++ * The repository.
++ *---------------------------------------------------------------------------*/
++static DEVICE_CFG_LIST_T g_device_cfg_list;
++
++/*---------------------------------------------
++ * Initialize the device collection pool.
++ *--------------------------------------------*/
++void p_init_device_cfg_list(void)
++{
++ g_device_cfg_list.count = 0;
++ g_device_cfg_list.device_cfg_begin = NULL;
++}
++
++/*----------------------------------------------------------------------
++ * Add the device cfg into the device linked list.
++ *---------------------------------------------------------------------*/
++int p_add_dev_cfg_to_list(DEVICE_CFG_LIST_T *p_dev_list,
++ DEVICE_CFG_T *p_dev_cfg)
++{
++ if(p_dev_list->count != 0)
++ p_dev_cfg->next = p_dev_list->device_cfg_begin;
++
++ p_dev_list->device_cfg_begin = p_dev_cfg;
++
++ p_dev_list->count++;
++
++ return (0);
++}
++
++/*------------------------------------------------------------------
++ * Add the cfg data into the cfg data linked list of the collection.
++ *------------------------------------------------------------------*/
++int p_add_instance_cfg_data(DEVICE_CFG_T *p_dev_cfg,
++ DEV_INSTANCE_CFG_DATA_T *p_dev_inst_data)
++{
++ if(p_dev_cfg->count == 0)
++ p_dev_cfg->dev_inst_list_begin = p_dev_inst_data;
++ else
++ p_dev_cfg->dev_inst_list_end->next = p_dev_inst_data;
++
++ p_dev_cfg->dev_inst_list_end = p_dev_inst_data;
++
++ p_dev_cfg->count++;
++
++ return (0);
++}
++
++/*-----------------------------------------------------------------------------
++ * Create the device cfg.
++ *---------------------------------------------------------------------------*/
++DEVICE_CFG_T *p_create_dev_cfg(char *device_name)
++{
++ DEVICE_CFG_T *p_dev_cfg = NULL;
++
++ if((p_dev_cfg = os_malloc(sizeof(DEVICE_CFG_T))) == NULL)
++ {
++ dbgPrint("Failed to allocate memory for DEVICE_CFG_T.\n");
++ }
++ else if((p_dev_cfg->device_name = os_malloc(psp_config_strlen(device_name) + 1))==NULL)
++ {
++ dbgPrint("Failed to allocate memory for device name.\n");
++ }
++ else
++ {
++ psp_config_strcpy(p_dev_cfg->device_name, device_name);
++ p_dev_cfg->cfg_type = en_raw;
++ p_dev_cfg->count = 0;
++ p_dev_cfg->dev_inst_list_begin = NULL;
++ p_dev_cfg->dev_inst_list_end = NULL;
++ p_dev_cfg->next = NULL;
++ }
++
++ return(p_dev_cfg);
++}
++
++/*------------------------------------------------------------------------------
++ * Get the device cfg collection.
++ *-----------------------------------------------------------------------------*/
++DEVICE_CFG_T *p_get_dev_cfg(char *device_name)
++{
++ int count = 0;
++ DEVICE_CFG_T *p_dev_cfg = g_device_cfg_list.device_cfg_begin;
++
++ for(count=0; count < g_device_cfg_list.count; count++)
++ {
++ if(psp_config_strcmp(device_name, p_dev_cfg->device_name) == 0)
++ {
++ break;
++ }
++
++ p_dev_cfg = p_dev_cfg->next;
++ }
++
++ return(p_dev_cfg);
++}
++
++/*-------------------------------------------------------------------------
++ * Gets the name for the static cfg type. Utility function. Debug purposes.
++ *-------------------------------------------------------------------------*/
++char *p_get_cfg_type_name_for_en(CFG_TYPE_T cfg_type)
++{
++ static char raw_str [] = "still raw";
++ static char compile_str [] = "configured at compile time";
++ static char optconf_str [] = "configured by options.conf";
++ static char vlynq_str [] = "configured by VLYNQ";
++ static char no_static_str[] = "no static configuration";
++
++ if(cfg_type == en_raw)
++ return (raw_str);
++ else if(cfg_type == en_compile)
++ return (compile_str);
++ else if(cfg_type == en_opt_conf)
++ return (optconf_str);
++ else if(cfg_type == en_vlynq)
++ return (vlynq_str);
++ else
++ return (no_static_str);
++
++}
++
++/*-----------------------------------------------------------------------------
++ * Sets the static cfg status of the device collection.
++ *
++ * If the collection is en_virgin then, the collection is assigned to cfg_type.
++ * If the cfg_type is en_vlynq then, the old cfg_type is retained.
++ * en_compile and en_opt_conf are mutually exclusive. One of these can be
++ * accomodated.
++ *
++ *---------------------------------------------------------------------------*/
++int p_set_device_cfg_type(DEVICE_CFG_T *p_dev_cfg,
++ CFG_TYPE_T cfg_type)
++{
++ int ret_val = 0;
++
++ if(p_dev_cfg->cfg_type == en_raw)
++ p_dev_cfg->cfg_type = cfg_type;
++ else if((cfg_type == en_vlynq) || (p_dev_cfg->cfg_type == cfg_type))
++ ;
++ else
++ {
++ dbgPrint("Device %s has been %s which overrides %s.\n",
++ p_dev_cfg->device_name,
++ p_get_cfg_type_name_for_en(p_dev_cfg->cfg_type),
++ p_get_cfg_type_name_for_en(cfg_type));
++ ret_val = -1;
++ }
++
++ return(ret_val);
++}
++
++/*------------------------------------------------------------------------
++ * Add the config str into the repository. The cfg type indicates
++ * whether the device has been configured statically, from options.conf or
++ * by vlynq enumeration.
++ *------------------------------------------------------------------------*/
++int psp_config_add(char *key, void *p_cfg_str, unsigned int cfg_len,
++ CFG_TYPE_T cfg_type)
++{
++ int ret_val = -1;
++ DEVICE_CFG_T *p_dev_cfg = NULL;
++ DEV_INSTANCE_CFG_DATA_T *p_dev_inst_data = NULL;
++
++ if(p_cfg_str == NULL || key == NULL)
++ {
++ dbgPrint("Null input pointer(s).\n");
++ }
++ /* check if there exist a dev_cfg for the given key, if not,
++ then create one and add it to the device list. */
++ else if(((p_dev_cfg = p_get_dev_cfg(key)) == NULL) &&
++ (((p_dev_cfg = p_create_dev_cfg(key)) == NULL) ||
++ p_add_dev_cfg_to_list(&g_device_cfg_list, p_dev_cfg) != 0))
++ {
++ dbgPrint("Failed to allocate mem or add dev cfg for %s.\n", key);
++ }
++ /* make sure that we can add this cfg type to the repository */
++ else if(p_set_device_cfg_type(p_dev_cfg, cfg_type) == -1)
++ {
++ dbgPrint("Ignoring \"%s\" for device \"%s\".\n",
++ p_get_cfg_type_name_for_en(cfg_type),
++ p_dev_cfg->device_name);
++ }
++ else if((p_dev_inst_data = os_malloc(sizeof(DEV_INSTANCE_CFG_DATA_T)))== NULL)
++ {
++ dbgPrint("Failed to allocate memory for DEV_INSTANCE_CFG_DATA_T.\n");
++ }
++ else if((p_dev_inst_data->data = os_malloc(cfg_len) + 1) == NULL)
++ {
++ dbgPrint("Failed to allocate memory for the config data.\n");
++ }
++ else
++ {
++ p_dev_inst_data->next = NULL;
++
++ if(cfg_type == en_opt_conf || cfg_type == en_compile)
++ psp_config_strcpy(p_dev_inst_data->locale, "dev on chip ");
++ else if(cfg_type == en_vlynq)
++ psp_config_strcpy(p_dev_inst_data->locale, "dev on vlynq");
++ else
++ psp_config_strcpy(p_dev_inst_data->locale, "dev locale ?");
++
++ psp_config_memcpy(p_dev_inst_data->data, p_cfg_str, cfg_len);
++ p_dev_inst_data->data_size = cfg_len;
++ *(p_dev_inst_data->data + cfg_len) = '\0';
++
++ ret_val = p_add_instance_cfg_data(p_dev_cfg, p_dev_inst_data);
++ }
++
++ return(ret_val);
++}
++
++/*-------------------------------------------------------------
++ * Get the total number of device instances in the repository
++ *------------------------------------------------------------*/
++int psp_config_get_num_keys(void)
++{
++ return(g_device_cfg_list.count);
++}
++
++
++/*--------------------------------------------------------------------
++ * Get the device configuration info from the repository.
++ *-------------------------------------------------------------------*/
++int psp_config_get(char *key, int instance, char **cfg_data_out)
++{
++ int ret_val = -1;
++ DEVICE_CFG_T *p_dev_cfg = NULL;
++ *cfg_data_out = NULL;
++
++ if(key == NULL && cfg_data_out == NULL)
++ {
++ dbgPrint("Key has a NULL value.\n");
++ }
++ else if((p_dev_cfg = p_get_dev_cfg(key)) == NULL)
++ {
++ dbgPrint("cfg information for %s could not be found.\n", key);
++ }
++ else if(p_dev_cfg->count)
++ {
++ DEV_INSTANCE_CFG_DATA_T *p_dev_inst_data =
++ p_dev_cfg->dev_inst_list_begin;
++ int index = 0;
++ for(index = 0;
++ index != instance && index < p_dev_cfg->count;
++ index++)
++ {
++ p_dev_inst_data = p_dev_inst_data->next;
++ }
++
++ if(p_dev_inst_data != NULL && p_dev_inst_data->data != NULL)
++ {
++ *cfg_data_out = p_dev_inst_data->data;
++ ret_val = p_dev_inst_data->data_size;
++ }
++ }
++
++ return (ret_val);
++}
++
++/*----------------------------------------------------------------
++ * Returns the number of instances found in the repository for the
++ * specified key.
++ *---------------------------------------------------------------*/
++int psp_config_get_num_instances(char *key)
++{
++ int ret_val = 0;
++ DEVICE_CFG_T *p_dev_cfg = NULL;
++
++ if(key == NULL)
++ {
++ dbgPrint("Key has a NULL value.\n");
++ }
++ else if((p_dev_cfg = p_get_dev_cfg(key)) == NULL)
++ {
++ dbgPrint("cfg information for %s could not be found.\n", key);
++ }
++ else
++ {
++ ret_val = p_dev_cfg->count;
++ }
++
++ return (ret_val);
++}
++
++/*------------------------------------------------------------------
++ * Dump the configuration repository.
++ * Caution: DO NOT USE THIS FOR ANY NON NBU specified config format.
++ *-----------------------------------------------------------------*/
++void psp_config_print(char *key)
++{
++ DEVICE_CFG_T *p_dev_cfg = NULL;
++
++ if(key == NULL)
++ {
++ dbgPrint("Key has a NULL value.\n");
++ }
++ else if((p_dev_cfg = p_get_dev_cfg(key)) == NULL)
++ {
++ dbgPrint("cfg information for %s could not be found.\n", key);
++ }
++ else if(p_dev_cfg && p_dev_cfg->count)
++ {
++ DEV_INSTANCE_CFG_DATA_T *p_dev_inst_data;
++
++ p_dev_inst_data = p_dev_cfg->dev_inst_list_begin;
++
++ do
++ {
++ dbgPrint("%s : %s\n", p_dev_inst_data->locale,
++ p_dev_inst_data->data);
++ p_dev_inst_data = p_dev_inst_data->next;
++
++ } while(p_dev_inst_data);
++ }
++ else
++ {
++ dbgPrint("Nothing was found for %s.\n", key);
++ }
++}
++
++void dump_device_cfg_pool(void)
++{
++ DEVICE_CFG_T *p_dev_cfg = g_device_cfg_list.device_cfg_begin;
++
++ if(p_dev_cfg != NULL && g_device_cfg_list.count)
++ {
++ int index=0;
++
++ for(index=0; index < g_device_cfg_list.count; index++)
++ {
++ psp_config_print(p_dev_cfg->device_name);
++ p_dev_cfg = p_dev_cfg->next;
++ }
++ }
++ else
++ {
++ dbgPrint("repository is empty.\n");
++ }
++}
++
++void psp_config_init(void)
++{
++ p_init_device_cfg_list();
++}
++
++void psp_config_cleanup()
++{
++ int dev_count = 0;
++ int inst_count = 0;
++ DEVICE_CFG_T *p = g_device_cfg_list.device_cfg_begin;
++ DEV_INSTANCE_CFG_DATA_T *q = NULL;
++
++ for(dev_count = 0; dev_count < g_device_cfg_list.count; dev_count++)
++ {
++ DEVICE_CFG_T *p_temp = NULL;
++ if(p) q = p->dev_inst_list_begin;
++
++ for(inst_count = 0; inst_count < p->count && q != NULL; inst_count++)
++ {
++ DEV_INSTANCE_CFG_DATA_T *q_temp = q;
++ q_temp = q->next;
++ kfree(q->data);
++ kfree(q);
++ q = q_temp;
++ }
++
++ p_temp = p->next;
++ kfree(p);
++ p = p_temp;
++ }
++}
+diff -urN linux.old/drivers/net/avalanche_cpmac/psp_config_mgr.h linux.dev/drivers/net/avalanche_cpmac/psp_config_mgr.h
+--- linux.old/drivers/net/avalanche_cpmac/psp_config_mgr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/psp_config_mgr.h 2005-07-12 02:48:42.177573000 +0200
+@@ -0,0 +1,110 @@
++/******************************************************************************
++ * FILE PURPOSE: PSP Config Manager Header
++ ******************************************************************************
++ * FILE NAME: psp_config_mgr.h
++ *
++ * DESCRIPTION: Storing and retrieving the configuration based on key
++ * A set of APIs to be used by one and sundry (including drivers and enumerator) to build
++ * and read cfg information of the devices for an avalanche SOC.
++ *
++ * This set of APIs isolates the configuration management from the world and provides simple
++ * access convinience.
++ *
++ * Device in this set refers to the peripherals that can be found on the SOC or on VLYNQ.
++ * The configuration is stored in the form of string and drivers can use these APIs to get
++ * a particular parameter value.
++ *
++ * The memory allocation for the pass back parameters is done by the caller.
++ *
++ * 0 is returned for SUCCESS or TRUE.
++ * -1 is returned for FAILURE or FALSE.
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++#ifndef __PSP_CONFIG_MGR_H__
++#define __PSP_CONFIG_MGR_H__
++
++typedef enum cfg_type
++{
++ en_raw = 0,
++ en_compile,
++ en_opt_conf,
++ en_vlynq
++} CFG_TYPE_T;
++
++/* Build psp configuration */
++void build_psp_config(void);
++
++/********************************************************
++ * Access Operations.
++ ********************************************************/
++
++/*-------------------------------------------------------------------------
++ initializes the configuration repository.
++ -------------------------------------------------------------------------*/
++void psp_config_init(void);
++
++/*--------------------------------------------------------------------------
++ Adds the configuration information into the repository. 'key' is required
++ to be NULL terminated string. 'cfg_ptr' points to the configuration data.
++ 'cfg_len' is the length of the data pointed to by 'cfg_ptr' in bytes.
++ 'cfg_type' indicates the type of config information.
++
++ psp_config_mgr copies the 'cfg_len' bytes of data pointed to by 'cfg_ptr'
++ into its internal repository.
++
++ Returns: 0 on success, -1 on failure.
++ -------------------------------------------------------------------------*/
++int psp_config_add(char *key, void *cfg_ptr,
++ unsigned int cfg_len, CFG_TYPE_T cfg_type);
++
++
++/* --------------------------------------------------------------------------
++ Passes back, in "*cfg_out_val" a pointer to the config data in the repository
++ for the specified 'key' and 'instance'. It returns the size of the config
++ info
++
++ psp_config_mgr passes back a pointer in '*cfg_out_val' which refers to
++ some location in its internal repository. It is strongly recommended that
++ if the user intends to modify the contents of the config info for reasons
++ whatsoever, then, user should allocate memory of size returned by this
++ routine and copy the contents from '*cfg_out_val'.
++
++ Any, modification carried out on the repository would lead to un-expected
++ results.
++
++ Returns: 0 or more for the size of config info, -1 on error.
++ --------------------------------------------------------------------------*/
++int psp_config_get(char *key, int instance, char **cfg_out_val);
++
++
++/*--------------------------------------------------------------------------
++ Get the number of keys that have been added in the repository so far.
++
++ Returns: 0 or more for the num of keys, -1 on error.
++ -------------------------------------------------------------------------*/
++int psp_config_get_num_keys(void);
++
++
++/*--------------------------------------------------------------------------
++ Get the number of instances that are present in the repository for the
++ given 'key'.
++
++ Returns: 0 or more for the num of instances, -1 on error.
++ -------------------------------------------------------------------------*/
++int psp_config_get_num_instances(char *key);
++
++
++/*--------------------------------------------------------------------------
++ Prints the config data for all instances associated with the specified
++ 'key'.
++ -------------------------------------------------------------------------*/
++void psp_config_print(char *key);
++
++void dump_device_cfg_pool(void);
++
++#endif /* __PSP_CONFIG_MGR_H__ */
+diff -urN linux.old/drivers/net/avalanche_cpmac/psp_config_parse.c linux.dev/drivers/net/avalanche_cpmac/psp_config_parse.c
+--- linux.old/drivers/net/avalanche_cpmac/psp_config_parse.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/psp_config_parse.c 2005-07-12 02:48:42.178573000 +0200
+@@ -0,0 +1,362 @@
++/******************************************************************************
++ * FILE PURPOSE: PSP Config Manager - Parse API Source
++ ******************************************************************************
++ * FILE NAME: psp_config_parse.c
++ *
++ * DESCRIPTION: These APIs should be used only for scanvenging parameters which
++ * are stored in the following format.
++ *
++ * str[] = "module(id=[module], k1=v1, k2=[k3=v3, k4=v4], k5=v5)"
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++//#include <stdio.h>
++#include <linux/stddef.h>
++
++/*--------------------------------------------------
++ * MACROS.
++ *-------------------------------------------------*/
++#define my_isdigit(c) (c >= '0' && c <= '9')
++#define my_isoct(c) (c >= '0' && c <= '7')
++#define my_xtod(c) ((c) <= '9' ? (c) - '0' : (c) - 'a' + 10)
++#define my_ifupper(c) (c >= 'A' && c <= 'F')
++#define XTOD(c) ((c) - 'A' + 10)
++#define my_ishex(c) ((c >= 'a' && c <='f') || (c >= 'A' && c<='F') || my_isdigit(c) )
++
++/*---------------------------------------------------
++ * Local Functions.
++ *--------------------------------------------------*/
++static int p_get_substr_from_str(char *p_in_str, char begin_delimiter,
++ char end_delimiter, int pair_flag,
++ char **p_out_str);
++static int p_get_u_int_from_str(char *p_in_str, char begin_delimiter,
++ char end_delimiter, unsigned long *out_val);
++
++/*---------------------------------------------------
++ * Return pointer to first instance of the char.
++ *--------------------------------------------------*/
++static char* psp_config_strchr(char *str, char chr)
++{
++ while(*str)
++ {
++ if(*str == chr)
++ break;
++ str++;
++ }
++
++ return((*str) ? str : NULL);
++}
++
++/*------------------------------------------------------------------------
++ * Convert the string upto delimiter to unsigned long.
++ *-----------------------------------------------------------------------*/
++unsigned long my_atoul(char *p, char end_delimiter, unsigned long *out_val)
++{
++ unsigned long n;
++ int c;
++
++ /* check the for null input */
++ if (!p)
++ return -1;
++
++ c = *p;
++
++ /* pass through the leading spaces */
++ if (!my_isdigit(c))
++ {
++ while ( c == ' ')
++ c = *++p;
++
++ }
++
++ if (c == '0')
++ {
++ if(*(p + 1) == 'x' || *(p+1) == 'X' )
++ {
++ /* string is in hex format */
++
++ p += 2;
++ c = *p;
++
++ if(my_ishex(c))
++ {
++ if(my_ifupper(c))
++ n = XTOD(c);
++ else
++ n = my_xtod(c);
++ }
++ else
++ return -1; /* invalid hex string format */
++
++ while ((c = *++p) && my_ishex(c))
++ {
++ n *= 16;
++ if(my_ifupper(c))
++ n += XTOD(c);
++ else
++ n += my_xtod(c);
++ }
++ }
++ else
++ {
++ /* string is in octal format */
++
++ if( my_isoct(c) )
++ n = c - '0';
++ else
++ return -1; /* invalid octal string format */
++
++ while ((c = *++p) && my_isoct(c))
++ {
++ n *= 8;
++ n += c - '0';
++ }
++ }
++
++ }
++ else
++ {
++ /* string is in decimal format */
++
++ if( my_isdigit(c) )
++ n = c - '0';
++ else
++ return -1; /* invalid decimal string format */
++
++ while ((c = *++p) && my_isdigit(c))
++ {
++ n *= 10;
++ n += c - '0';
++ }
++ }
++
++ /* move through the trailing spaces */
++ while(*p == ' ')
++ p++;
++
++ if(*p == end_delimiter)
++ {
++ *out_val = n;
++ return 0;
++ }
++
++ else
++ return -1; /* invalid string format */
++}
++
++/*---------------------------------------------------------------------------------
++ * Gets the substring de-limited by the 'begin_delimiter' and 'end_delimiter'.
++ * and returns the size of the substring.
++ *
++ * Parses the NULL terminated p_in_str for a character array delimited by
++ * begin_delimiter and end_delimiter, passes back the pointer to the character
++ * array in ' *p_out_str '. The passed pointer ' *p_out_str ' should point to
++ * the location next (byte) to the begin_delimiter. The function routine returns
++ * the number of characters excluding the begin_delimiter and end_delimiter,
++ * found in the array delimited by the said delimiters.
++ *
++ * If the pair_flag is set to 1, then, number of begin_delimiter and end_delimiter
++ * found in the parsing should match (equal) and this routine passes back the
++ * pointer to the character array, starting at a location next (byte) to the
++ * first begin_delimiter, inclusive of all intermediate matching delimiter
++ * characters found between outer delimiters. If the pair flag is set and if
++ * begin_delimiter and end_delimiter happens to be same, then error (-1) is
++ * returned.
++ *
++ * Return: 0 or more to indicate the size of the substring, -1 on error.
++ *-------------------------------------------------------------------------------*/
++int p_get_substr_from_str(char *p_in_str, char begin_delimiter,
++ char end_delimiter, int pair_flag,
++ char **p_out_str)
++{
++ int cnt,pos;
++
++ if(pair_flag && begin_delimiter == end_delimiter)
++ return -1;
++
++ if((p_in_str = psp_config_strchr(p_in_str, begin_delimiter)) == 0)
++ return -1; /* no start delimiter found */
++
++ p_in_str++;
++ *p_out_str = p_in_str;
++
++ for(pos = 0,cnt =1; cnt && p_in_str[pos] ; pos++)
++ {
++ if(p_in_str[pos] == end_delimiter)
++ {
++ if(pair_flag == 0)
++ return pos;
++
++ cnt--;
++ }
++ else if(p_in_str[pos] == begin_delimiter)
++ cnt++;
++ else
++ ; /* We do nothing */
++
++ }
++
++ if( cnt == 0)
++ return pos - 1;
++ else
++ return -1; /* no corresponding end delimiter found */
++}
++
++/*--------------------------------------------------------------------------
++ * Parses the NULL terminated p_in_str for unsigned long value delimited by
++ * begin_delimiter and end_delimiter, passes back the found in ' *out_val '.
++ * The function routine returns 0 on success and returns -1 on failure.
++ * The first instance of the de-limiter should be accounted for the parsing.
++ *
++ * The base for unsigned value would 10, octal and hex. The value passed back
++ * would be of the base 10. Spaces at the begining of the byte array are valid
++ * and should be ingnored in the calculation of the value. Space character in
++ * the middle of the byte array or any character other than the valid ones
++ * (based on base type) should return error. The octal value begins with '0',
++ * the hex value begins with "0x" or "0X", the base value can begin with
++ * '1' to '9'.
++ *
++ * Returns: 0 on success, -1 on failure.
++ *-------------------------------------------------------------------------*/
++int p_get_u_int_from_str(char *p_in_str, char begin_delimiter,
++ char end_delimiter, unsigned long *out_val)
++{
++ char *start;
++ unsigned long num;
++
++ num = p_get_substr_from_str(p_in_str, begin_delimiter, end_delimiter,
++ 0, &start);
++
++ if(num == (unsigned long)-1)
++ return -1;
++
++ return my_atoul(start,end_delimiter,out_val);
++}
++
++/*--------------------------------------------------------------------------
++ * Finds the first occurrence of the substring p_find_str in the string
++ * p_in_str.
++ *-------------------------------------------------------------------------*/
++char *my_strstr(char *p_in_str, const char *p_find_str)
++{
++ char *p = (char *)p_find_str;
++ char *ret = NULL;
++
++ while(*p_in_str)
++ {
++ if(!(*p))
++ return (ret);
++ else if(*p_in_str == *p)
++ {
++ if(!ret) ret = p_in_str;
++ p++;
++ p_in_str++;
++ }
++ else if(ret)
++ {
++ p = (char *)p_find_str;
++ p_in_str = ret + 1;
++ ret = NULL;
++ }
++ else
++ p_in_str++;
++ }
++
++ if(*p_in_str != *p) ret = NULL;
++
++ return (ret);
++
++}
++
++/*------------------------------------------------------------------------------
++ * Gets the value of the config param in the unsigned int format. The value is
++ * stored in the following format in the string.
++ * str[] = "module(id=[module], k1=v1, k2=[k3=v3, k4=v4], k5=v5)"
++ *-----------------------------------------------------------------------------*/
++int psp_config_get_param_uint(char *p_in_str, const char *param, unsigned int *out_val)
++{
++ int ret_val = -1;
++ char *p_strstr;
++
++ if(!p_in_str || !param || !out_val)
++ {
++ ;
++ }
++ else if((p_strstr = my_strstr(p_in_str, param)) == NULL)
++ {
++ ;
++ }
++ else if(p_get_u_int_from_str(p_strstr, '=', ',', (unsigned long *)out_val) == 0)
++ {
++ ret_val = 0;
++ }
++ else if(p_get_u_int_from_str(p_strstr, '=', ']', (unsigned long*)out_val) == 0)
++ {
++ ret_val = 0;
++ }
++ else if(p_get_u_int_from_str(p_strstr, '=', ')', (unsigned long*)out_val) == 0)
++ {
++ ret_val = 0;
++ }
++ else
++ {
++ /* we failed */
++ }
++
++ return (ret_val);
++}
++
++/*------------------------------------------------------------------------------
++ * Gets the value of the config param in the Non NULL terminated format. The value
++ * is stored in the following format in the string.
++ * str[] = "module(id=[module], k1=v1, k2=[k3=v3, k4=v4], k5=v5)"
++ *-----------------------------------------------------------------------------*/
++int psp_config_get_param_string(char *p_in_str, const char *param, char **out_val)
++{
++ int ret_val = -1;
++ char *p_strstr;
++
++ if(!p_in_str || !param || !(out_val))
++ ;
++ else if((p_strstr = my_strstr(p_in_str, param)) == NULL)
++ {
++ ;
++ }
++ else if((ret_val = p_get_substr_from_str(p_strstr, '[', ']', 1, out_val)) == -1)
++ {
++ ;
++ }
++ else
++ {
++ ; /* we got the value */
++ }
++
++ return (ret_val);
++}
++
++#ifdef PSP_CONFIG_MGR_DEBUG_TEST
++main()
++{
++ unsigned long num =999;
++ int ret = 0;
++ char *val1 = NULL;
++ char val[30];
++ char str1[] = "cpmac(id=[cpmac], k0=[a1=[a2=[test], a3=2], k1=100, k2=[k3=300, k4=200], k7=722)";
++
++ psp_config_get_param_uint(str1, "k7", &num);
++ printf("%u.\n", num);
++ ret = psp_config_get_param_string(str1, "a1", &val1);
++ if(ret >= 0) { printf("%d.\n", ret); strncpy(val, val1, ret); val[ret] = '\0';}
++
++ printf("val = \"%s\", and size = %d \n", val, ret);
++
++ if(val[ret]) ; else printf("jeee.\n");
++}
++#endif /* PSP_CONFIG_MGR_DEBUG_TEST */
++
++
++
+diff -urN linux.old/drivers/net/avalanche_cpmac/psp_config_parse.h linux.dev/drivers/net/avalanche_cpmac/psp_config_parse.h
+--- linux.old/drivers/net/avalanche_cpmac/psp_config_parse.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/psp_config_parse.h 2005-07-12 02:48:42.178573000 +0200
+@@ -0,0 +1,32 @@
++/******************************************************************************
++ * FILE PURPOSE: PSP Config Manager - Parse API Header
++ ******************************************************************************
++ * FILE NAME: psp_config_parse.h
++ *
++ * DESCRIPTION: Parsing for params from string available in the NBU format.
++ * These APIs should be used only for scanvenging parameters which
++ * are stored in the following format.
++ *
++ * str[] = "module(id=[module], k1=v1, k2=[k3=v3, k4=v4], k5=v5)"
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++#ifndef __PSP_CONFIG_PARSER_H__
++#define __PSP_CONFIG_PARSER_H__
++
++/*------------------------------------------------------------------
++ * These APIs should be used only for scanvenging parameters which
++ * are stored in the following format.
++ *
++ * str[] = "module(id=[module], k1=v1, k2=[k3=v3, k4=v4], k5=v5)"
++ *-----------------------------------------------------------------*/
++int psp_config_get_param_uint(char *p_in_str, const char *param,
++ unsigned int *out_val);
++int psp_config_get_param_string(char *p_in_str, const char *param,
++ char **out_val);
++
++#endif /* __PSP_CONFIG_PARSER_H__ */
+diff -urN linux.old/drivers/net/avalanche_cpmac/psp_config_util.c linux.dev/drivers/net/avalanche_cpmac/psp_config_util.c
+--- linux.old/drivers/net/avalanche_cpmac/psp_config_util.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/psp_config_util.c 2005-07-12 02:48:42.178573000 +0200
+@@ -0,0 +1,106 @@
++/******************************************************************************
++ * FILE PURPOSE: PSP Config Manager - Utilities API Source
++ ******************************************************************************
++ * FILE NAME: psp_config_util.c
++ *
++ * DESCRIPTION: These APIs provide the standard "C" string interfaces.
++ * Provided here to reduce dependencies on the standard libraries
++ * and for cases where psp_config would required to run before
++ * the whole system is loaded or outside the scope of the OS.
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++//#include <stdio.h>
++#include "psp_config_util.h"
++#include <linux/stddef.h>
++
++/*---------------------------------------------
++ * strlen.
++ *-------------------------------------------*/
++int psp_config_strlen(char *p)
++{
++ char *p_orig = p;
++ while(*p)
++ p++;
++ return(p - p_orig);
++}
++
++/*--------------------------------------------
++ * strcmp.
++ *-------------------------------------------*/
++int psp_config_strcmp(char *s1, char *s2)
++{
++ while(*s1 && *s2)
++ {
++ if(*s1 != *s2)
++ break;
++ s1++;
++ s2++;
++ }
++
++ return(*s1 - *s2);
++}
++
++/*--------------------------------------------
++ * strcpy.
++ *------------------------------------------*/
++char* psp_config_strcpy(char *dest, char *src)
++{
++ char *dest_orig = dest;
++
++ while(*src)
++ {
++ *dest++ = *src++;
++ }
++
++ *dest = '\0';
++
++ return(dest_orig);
++}
++
++/*----------------------------------------------
++ * psp_config_memcpy.
++ *--------------------------------------------*/
++void* psp_config_memcpy(void* dest, void* src, unsigned int n)
++{
++ void *dest_orig = dest;
++
++ while(n)
++ {
++ *(char *)dest++ = *(char *)src++;
++ n--;
++ }
++
++ return (dest_orig);
++}
++
++/*---------------------------------------------------
++ * Return pointer to first instance of the char.
++ *--------------------------------------------------*/
++char* psp_config_strchr(char *str, char chr)
++{
++ while(*str)
++ {
++ if(*str == chr)
++ break;
++ str++;
++ }
++
++ return((*str) ? str : NULL);
++}
++
++#ifdef PSP_CONFIG_MGR_DEBUG_TEST
++
++int main( )
++{
++ char s[] = "hello ";
++ printf("%d.\n", psp_config_strlen("hello\n"));
++ printf("%d.\n", psp_config_strcmp("hells", "hellq"));
++ printf("%s %s.\n", psp_config_strcpy(s + 6, "test1"), s);
++}
++
++#endif /* PSP_CONFIG_MGR_DEBUG_TEST */
+diff -urN linux.old/drivers/net/avalanche_cpmac/psp_config_util.h linux.dev/drivers/net/avalanche_cpmac/psp_config_util.h
+--- linux.old/drivers/net/avalanche_cpmac/psp_config_util.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/psp_config_util.h 2005-07-12 02:48:42.179573000 +0200
+@@ -0,0 +1,26 @@
++/******************************************************************************
++ * FILE PURPOSE: PSP Config Manager - Utilities API Header
++ ******************************************************************************
++ * FILE NAME: psp_config_util.h
++ *
++ * DESCRIPTION: These APIs provide the standard "C" string interfaces.
++ * Provided here to reduce dependencies on the standard libraries
++ * and for cases where psp_config would required to run before
++ * the whole system is loaded or outside the scope of the OS.
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++#ifndef __PSP_CONFIG_UTIL_H__
++#define __PSP_CONFIG_UTIL_H__
++
++extern int psp_config_strlen(char*);
++extern int psp_config_strcmp(char*, char*);
++extern char* psp_config_strcpy(char*, char*);
++extern void* psp_config_memcpy(void*, void*, unsigned int n);
++extern char* psp_config_strchr(char*, char);
++
++#endif /* __PSP_CONFIG_UTIL_H__ */
+diff -urN linux.old/drivers/net/avalanche_cpmac/readme.txt linux.dev/drivers/net/avalanche_cpmac/readme.txt
+--- linux.old/drivers/net/avalanche_cpmac/readme.txt 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/readme.txt 2005-07-12 02:48:42.179573000 +0200
+@@ -0,0 +1,545 @@
++23 August 2004 CPMAC 1.7.8 (NSP Performance Team Release)
++
++CC Labels: REL_20040823_HALdallas_cpmac_01.07.08
++
++New features: Key "MacAddr" can now be used to set the Mac Address after Open.
++
++ unsigned char MacAddr[6];
++
++ // Set Mac Address to "00.B0.D0.10.80.C1"
++ MacAddr[0] = 0x00;
++ MacAddr[1] = 0xB0;
++ MacAddr[2] = 0xD0;
++ MacAddr[3] = 0x10;
++ MacAddr[4] = 0x80;
++ MacAddr[5] = 0xC1;
++
++ HalFunc->Control(HalDev, "MacAddr", hcSet, &MacAddr);
++
++Bug fixes: in Send(), Threshold is not checked if Tx Ints are re-enabled.
++
++Modules affected: hcpmac.c, hcpmac.h, cppi_cpmac.c
++
++22 June 2004 CPMAC 1.7.6 (NSP Performance Team Release)
++
++CC Labels: REL_20040622_HALdallas_cpmac_01.07.06
++
++New features: Key "TxIntDisable" used to disable Tx Interrupts. If it is set, then Tx Interrupts will be processed on Send() controlled by Tx ServiceMax Setting.
++
++ int On = 1;
++ HalFunc->Control(HalDev, "TxIntDisable", "Set", &On);
++
++Bug fixes: NTR
++
++10 June 2004 CPMAC 1.7.5 (external release)
++
++CC Labels: REL_20040610_HALdallas_cpmac_01.07.05
++
++New features: NTR
++
++Bug fixes: Fixed an issue with calculation for the multicast hash.
++
++27 May 2004 CPSAR 1.7.4, CPMAC 1.7.4 (external release)
++
++CC Labels: REL_20040527_HALdallas_cpsar_01.07.04
++ REL_20040527_HALdallas_cpmac_01.07.04
++
++New features: NTR
++
++Bug fixes: A flaw was fixed in the critical sectioning of the CPPI file, affecting both
++ the MAC and the SAR releases. This flaw was detected on Titan PSP 4.7 BFT2.
++
++05 May 2004 CPSAR 1.7.3, CPMAC 1.7.3 (external release)
++
++CC Labels: REL_20040505_HALdallas_cpsar_01.07.03
++ REL_20040505_HALdallas_cpmac_01.07.03
++
++New features: NTR
++
++Bug fixes: 1) Firmware has been updated to fix a problem with Host OAM mode operation.
++ 2) Cache macros have been fixed.
++
++Notes: This release contains all performance enhancements currently available for CPHAL 1.x.
++
++19 April 2004 CPSAR 1.7.2, CPMAC 1.7.2 (external release)
++
++CC Labels: REL_20040419_HALdallas_cpsar_01.07.02
++ REL_20040419_HALdallas_cpmac_01.07.02
++
++New features: NTR
++
++Bug fixes: Fixes merge problem in 1.7.1.
++
++Notes: This is a branch release which contains only a subset of the performance improvements.
++ The remaining performance improvements are stiill being qualified at this time.
++
++1 April 2004 CPSAR 1.7.1, CPMAC 1.7.1 (external release)
++
++NOTICE: DO NOT USE 1.7.1. It has a known problem (see 1.7.2 notes)
++
++CC Labels: REL_20040401_HALdallas_cpsar_01.07.01
++ REL_20040401_HALdallas_cpmac_01.07.01
++
++New features: Performance improvement in CPPI layer, affecting both CPSAR and CPMAC.
++
++Bug fixes: NTR
++
++17 Februrary 2004 CPSAR 1.7.0 (external release)
++
++CC Labels: REL_20040217_HALdallas_cpsar_01.07.00
++
++New features: Added support for "TxFlush" feature. This allows the upper
++ layer to flush all or part of a given Tx queue for a given
++ channel. This is to be used during call setup for a voice
++ connection.
++
++30 January 2004 CPMAC 1.7.0 (external release)
++
++CC Labels: REL_20040130_HALdallas_cpmac_01.07.00
++
++Bug fixes: CPMDIO - When in manual negotiate mode and linked, dropping link would move into NWAY state rather than manual state.
++ CPMDIO - Extraneous debug message corrected
++New features: CPMDIO - Support for AutoMdix usage added.
++
++25 September 2003 CPSAR 1.6.6 (external release)
++
++CC Labels: REL_20030925_HALdallas_cpsar_01.06.06
++
++Bug fixes: PDSP firmware has been updated to fix the OAM padding problem. It previously
++ wrote pad bytes into a reserved field of the OAM cell. There is a small
++ change to the CPSAR configuration code which corresponds to the PDSP spec
++ change.
++
++New features: NTR
++
++09 September 2003 CPMAC 1.6.6 (external release)
++
++CC Labels: REL_20030909_HALdallas_cpmac_01.06.06
++
++Bug fixes: CPMAC : When _CPMDIO_NOPHY is set, Cpmac COntrol is set to Full Duplex
++ Bridge loopback test does not show a problem using 1.6.5 if packet rate is
++ below 50,000 pbs. Now testing with a 100% send from Ixia.
++
++New features: NTR
++
++05 August 2003 CPHAL 1.6.5 (external release)
++
++CC Labels: REL_20030805_HALdallas_cpmac_01.06.05
++
++Bug fixes: NTR
++
++New features: CPMAC : Added support for CPMAC modules that do not have a Phy connected.
++ The CPMAC is informed of this by the MdioConnect option
++ _CPMDIO_NOPHY. This is the only driver change needed to
++ receive and transmit packets through the Marvel switch.
++ Note In this mode Link status will reported linked at 100/FD to
++ PhyNum 0xFFFFFFFF.
++
++ ALL: Cleaned up some Vlynq support logic.
++
++16 July 2003 CPSAR 1.6.3 (external release), no CPMAC release
++
++CC Labels: REL_20030716_HALdallas_cpsar_01.06.03
++
++Bug fixes: 1) Changed default value of CPCS_UU from 0x5aa5 to 0. The old default value caused
++ problems with Cisco routers.
++
++New features: NTR
++
++Known issues not addressed in this release: NTR.
++
++01 July 2003 CPHAL 1.6.2 (external release)
++
++CC Labels: REL_20030701_HALdallas_cpmac_01.06.02
++ REL_20030701_HALdallas_cpsar_01.06.02
++
++Bug fixes: 1) A previous firmware upgrade caused firmware OAM loopback cells to only work on every other
++ command. This has been fixed in the new firmware version (0.47).
++ 2) Problem with PTI values changing on transparent mode packets has been resolved.
++ 3) Previously, successful firmware OAM loopback cells waited 5 seconds before notifying the
++ OS of success, rather that notifying immediately. This has been resolved in firmware.
++ 4) PITS #148 (MAC and SAR), #149 (MAC) have been fixed.
++
++New features: 1) AAL5 HAL now capable of receiving unknown VCI/VPI cells on a single transparent channel.
++ See updated HAL document (AAL5 appendix) for implementation details.
++ 2) AAL5 HAL now allows OS to modify the OAM loopback timeout window. Previously, failed
++ OAM loopback attempts timed out after a nominal 5 seconds (based on the SAR frequency
++ provided by the OS). Now, the default is 5 seconds, but the OS may change the
++ value via halControl() to any integer number of milliseconds. See updated HAL document
++ (AAL5 appendix) for implementation details.
++ 3) MAC (cpmdio): added loopback to Istate. Used for debug.
++
++Known issues not addressed in this release: NTR.
++
++09 June 2003 CPSAR 1.6.1 (external release), CPMAC 1.6.1 (internal release - no functional change)
++
++Note: This is the same set of fixes being applied to 1.6.0 that were applied to 1.5.3. The only difference
++ between 1.6.1 and 1.5.4 is that 1.6.1 has the TurboDSL fix.
++
++CC Labels: REL_20030609_HALdallas_cpmac_01.06.01
++ REL_20030609_HALdallas_cpsar_01.06.01
++
++Bug fixes: 1) Bug in OamLoopbackConfig fixed.
++ 2) New firmware version (.43) to fix Westell issue of dropped downstream packets in
++ presence of OAM traffic when operating at or near line rate.
++
++New features: NTR.
++
++09 June 2003 CPSAR 1.5.4 (external release), CPMAC 1.5.4 (internal release - no functional change)
++
++Note: This is a branch release from 1.5.3. This does not contain anything from 1.6.0. The CPMAC is
++only being labeled to keep the release flow consistent.
++
++CC Labels: REL_20030609_HALdallas_cpmac_01.05.04
++ REL_20030609_HALdallas_cpsar_01.05.04
++
++Bug fixes: 1) Bug in OamLoopbackConfig fixed.
++ 2) New firmware version (.43) to fix Westell issue of dropped downstream packets in
++ presence of OAM traffic when operating at or near line rate.
++
++New features: NTR.
++
++30 May 2003 CPSAR 1.6.0 (external release), CPMAC 1.6.0 (internal release - no functional change)
++
++CC Labels: REL_20030530_HALdallas_cpmac_01.06.00
++ REL_20030530_HALdallas_cpsar_01.06.00
++
++Bug fixes: 1) TurboDSL issue has been fixed with a software workaround in TxInt. This workaround
++ has been verified under Adam2 ONLY at this point. Testing remains to be done on
++ Linux and VxWorks.
++
++New features: NTR.
++
++Known issues not addressed in this release: NTR.
++
++30 May 2003 CPSAR 1.5.3 (external release), CPMAC 1.5.3 (internal release - no functional change)
++
++CC Labels: REL_20030530_HALdallas_cpmac_01.05.03
++ REL_20030530_HALdallas_cpsar_01.05.03
++
++Bug fixes: NTR.
++
++New features: 1) AAL5 Send() has been modified to accept an ATM Header either in the first
++ fragment by itself, or in the first fragment directly in front of payload data.
++ The API() does not change.
++ 2) Documentation updates throughout, reflected in latest version of CPHAL user's
++ guide.
++ 3) AAL5 MaxFrags default value is now 46. This is based upon the default AAL5
++ RxBufSize of 1518 (MaxFrags = (65568/1518) + 2). IF THE OS CHOOSES A SMALLER
++ RxBufSize, IT MUST INCREASE THE VALUE OF MaxFrags ACCORDINGLY. This is done
++ via halControl(), prior to Open().
++
++Known issues not addressed in this release:
++ 1) The Linux SAR driver is seeing an issue in which it cannot
++ reliably send traffic simultaneously on both the high and
++ low priority queues of a single AAL5 channel. (TurboDSL)
++
++23 May 2003 CPHAL 1.5.2 (external release)
++
++CC Labels: REL_20030523_HALdallas_cpmac_01.05.02
++ REL_20030523_HALdallas_cpsar_01.05.02
++
++Bug fixes: 1) PITS #138: CPMAC flooding issue resolved.
++ 2) PITS #142: OS may now set "MaxFrags" via Control(). This controls the
++ maximum number of fragments expected by the CPHAL. The default value is 2 for
++ CPMAC and 1028 for AAL5. If the OS chooses a RxBufSize that will cause more
++ fragments than the defaults, the OS must set "MaxFrags" to a correct value
++ ((maximum packet length / RxBufSize) + 2).
++ 3) PITS #143: Fixed.
++ 4) Firmware OAM bug fixed. (new firmware release in this version)
++
++New features: NTR.
++
++Known issues not addressed in this release:
++ 1) The Linux SAR driver is seeing an issue in which it cannot
++ reliably send traffic simultaneously on both the high and
++ low priority queues of a single AAL5 channel. (TurboDSL)
++
++14 May 2003 CPHAL 1.5.1 (external release)
++
++CC Labels: REL_20030514_HALdallas_cpmac_01.05.01
++ REL_20030514_HALdallas_cpsar_01.05.01
++
++Bug fixes: 1) PITS 132 - (CPMAC) Frames < 60 bytes and split into
++ multi-fragments.
++ 2) BCIL MR PSP00000353 - (CPMAC) PhyDev not free'd on halClose()
++ 3) PITS 113 - OsSetup bug in ChannelSetup fixed.
++ 4) Fixed AAL5 to check return values of InitTcb/InitRcb.
++ 5) Fixed Shutdown to properly free resources in the case of a Close
++ mode 1 followed by Shutdown. Previously, buffer and descriptor
++ resources were left unfreed in this case.
++
++New features: 1) AAL5 Send() modified to be capable of accepting ATM header as first four
++ bytes of first fragment. This allows the OS to "override" the
++ default ATM header which is constructed from preconfigured channel
++ parameters.
++ 2) AAL5 Receive() modified to be capable of passing the received ATM header (4 bytes, no HEC)
++ in the first fragment (by itself). It also passes up the OS an indication
++ of what the received packet type was. For Host OAM and transparent mode
++ packets, the ATM header is passed in this manner, and for other types of packets
++ (AAL5, NULL AAL) no ATM header is passed currently.
++
++Known issues not addressed in this release:
++ 1) The Linux SAR driver is seeing an issue in which it cannot
++ reliably send traffic simultaneously on both the high and
++ low priority queues of a single AAL5 channel.
++
++30 April 2003 CPHAL 1.5.0 (external release)
++
++CC Labels: REL_20030430_HALdallas_cpmac_01.05.00
++ REL_20030430_HALdallas_cpsar_01.05.00
++
++Bug fixes: 1) Fixed AAL5 bug that rendered the low priority queue
++ unusable.
++ 2) Fixed a bug in AAL5's Oam Rate calculations.
++ 3) Fixed use of "DeviceCPID" key in AAL5's halControl().
++ 4) Fixed RxReturn logic in HAL. The HAL now can handle
++ failing MallocRxBuffer calls when multiple fragments
++ are being used.
++
++New features: 1) AAL5 Stats now available on a per queue basis.
++ 2) AAL5 adds two new keys to halControl() for "Set" actions:
++ RxVc_OamCh and RxVp_OamCh.
++ 3) Shutdown() has been modified for both AAL5 and CPMAC to
++ call Close() if the module is still in the Open state.
++ 4) CPMAC adds the following access keys to halControl():
++ hcPhyAccess,hcPhyNum,hcCpmacBase,hcSize,and hcCpmacSize.
++ 5) CPHAL no longer requests an extra 15 bytes on data buffer
++ mallocs.
++
++Known issues not addressed in this release:
++ 1) The Linux SAR driver is seeing an issue in which it cannot
++ reliably send traffic simultaneously on both the high and
++ low priority queues of a single AAL5 channel.
++
++21 April 2003 CPHAL 1.4.1 (external release)
++
++CC Labels: REL_20030421_HALdallas_cpmac_01.04.01
++ REL_20030421_HALdallas_cpsar_01.04.01
++
++Bug fixes: 1) Fixed OAM logic in SAR portion of CPHAL.
++
++New features: 1) OAM loopback counters exposed through halControl.
++ 2) Host OAM Send() can now use a single channel to send
++ OAM cells on unlimited number of VP's/VC's.
++ 3) CPHAL now requests "SarFreq" through osControl.
++ 4) CPHAL now calculates all OAM function rates based on
++ "SarFreq"; function OamRateConfig removed for API.
++ 5) New OAM function OamLoopbackConfig, used for configuring
++ loopback functions in firmware OAM mode.
++
++Known issues not addressed in this release: Bug fix 1) in release 1.4
++ (see below) does not work properly for multiple fragments.
++
++10 April 2003 CPHAL 1.4 (external release)
++
++CC Labels: REL_20030410_HALdallas_cpmac_01.04.00
++ REL_20030410_HALdallas_cpsar_01.04.00
++
++This release is for SAR and MAC.
++
++ Bug fixes: 1) Implemented logic in HAL to re-request buffer mallocs
++ in the case of MallocRxBuffer failing. The HAL now maintains
++ a NeedsBuffer queue of all RCB's that are without buffers.
++ On interrupts, or on Send(), the HAL checks to see if any
++ RCB's are on the queue, and if so, calls MallocRxBuffer
++ to attempt to get a new buffer and return the RCB to
++ circulation.
++ 2) SAR now properly returns all error codes from halOpen and
++ halChannelSetup.
++
++ New features: NTR
++
++ Known issues not addressed in this release: NTR
++
++08 April 2003 CPHAL 1.3.1 (internal release - SAR only)
++
++ CC Labels: REL_20030408_HALdallas_cpsar_01.03.01
++
++ This is a SAR only release. The current CPMAC release is still 1.3.
++
++ Bug fixes: 1) PDSP State RAM / Scratchpad RAM is now completely cleared after reset.
++ This resolves a stability issue.
++
++ New features: 1) OamMode is now a parameter in halControl(). Both "Set" and "Get"
++ actions are available. The value may be "0" (Host OAM), or "1"
++ (Firmware OAM).
++
++ Known issues not addressed in this release:
++ 1) Appropriate action for HAL in the case of MallocRxBuffer failing. We
++ are investigating whether the HAL should implement a needs buffer
++ queue.
++
++04 April 2003 CPHAL 1.3 (external release)
++
++ CC Labels: REL_20030404_HALdallas_cpmac_01.03.00
++ REL_20030404_HALdallas_cpsar_01.03.00
++ REL_20030404_HALdallas_cpaal5_01.03.00
++ REL_20030404_HALdallas_cpaal2_01.03.00
++
++ This release requires no changes for the ethernet end driver. The changes necessary
++ for the sar driver (firmware file name changes) have already been implemented.
++
++ Bug fixes: 1) RxReturn now returns an error if MallocRxBuffer fails. On RxReturn error, the driver should
++ call RxReturn again at a later time (when the malloc may succeed) in order for the CPHAL
++ to maintain a full complement of Rx buffers. We recommend holding off making this driver
++ change until we verify that this condition occurs.
++
++ New features: 1) Removed benign compiler warnings.
++ 2) PITS 122: http://www.nbu.sc.ti.com/cgi-bin/pits/redisplay_archive?product=cphal_dev&report=122
++ 3) Cpsar label (above) now is applied to everything
++ beneath /cpsar.
++ 4) PITS 14: http://www.nbu.sc.ti.com/cgi-bin/pits/redisplay_archive?product=cphal_dev&report=14
++ Transferred to MR PSP 00000089.
++ 5) PITS 120: http://www.nbu.sc.ti.com/cgi-bin/pits/redisplay_archive?product=cphal_dev&report=120
++
++ Known issues not addressed in this release:
++ 1) PITS 102 (as relating to OamMode configuration):
++ http://www.nbu.sc.ti.com/cgi-bin/pits/redisplay_archive?product=cphal_dev&report=102
++ Future release will make OamMode configurable
++ through halControl(), not on per channel basis.
++
++20 March 2003 CPHAL 1.2.1 (internal release)
++
++ CC Labels: REL_20030320_HALdallas_cpmac_01.02.01
++ REL_20030320_HALdallas_cpsar_01.02.01
++ REL_20030320_HALdallas_cpaal5_01.02.01
++ REL_20030320_HALdallas_cpaal2_01.02.01
++
++ Bug fixes: 1. Fixed modification of buffer pointer following
++ MallocRxBuffer in cppi.c.
++ 2. Removed extra firmware files from /cpsar.
++
++ New features: NTR.
++
++ Known issues not addressed in this release: NTR.
++
++07 March 2003 CPHAL 1.2 (external release)
++
++ CPMAC/CPSAR feature complete release. SAR added
++ several features including full OAM support and various
++ other features and bug fixes to address PITS 99-106, and
++ 114. CPMAC cleaned up details raised by India PSP
++ team.
++
++29 January 2003 CPHAL RC 3.01a (external release)
++
++ Corrects non-static functions to be static in cppi.c.
++
++09 Janurary 2003 CPHAL RC 3.01 (external release)
++
++ PITS 88: Fixed MDIO re-connection problem (hcpmac.c)
++ PITS 90: Corrected Rx Buffer Pointer modification (cppi.c)
++
++ Corrected error in cpremap.c
++
++20 December 2002 CPHAL RC 3 (external release)
++
++ Statistics support via halControl(). See Appendix A of guide.
++ Fixed errors in ChannelTeardown/ChannelSetup CPHAL logic.
++ Added multicast support as requested.
++ Several new OS string functions added to OS_FUNCTIONS.
++ "DebugLevel" configuration parameter changed to "Debug".
++ "Stats0" changed to "StatsDump" for CPMAC.
++
++13 December 2002 CPHAL RC 2.03 (internal release)
++
++ Performance improvements.
++ More debug statements implemented (esp AAL5).
++ Updated makefile with "make debug" option.
++ Hbridge performance: [debug library] 15774 tps (53% line rate)
++ [non-debug library] 13700 tps (46%)
++
++10 December 2002 CPHAL Release Candidate 2.02 (internal release)
++
++ Much of the configuration code internal to CPMAC and AAL5 has been made common.
++ [os]Receive API had been modified to remove OsReceiveInfo. This information is now
++ available as third member of the FRAGLIST structure, on a per buffer basis.
++ Successfully tested multi-fragment support on CPMAC, using 32 byte buffers.
++ Code is now Emerald compliant - all buffer descriptors now aligned to cache-line
++ boundaries.
++
++2 December 2002 CPHAL Release Candidate 2.01
++
++ Updates to comments in hcpmac.c, cpmdio.c, hcpmac.h
++ Nested comment in hcpmac.c in RC2 can cause compile errors.
++
++25 November 2002 CPHAL Release Candidate 2
++
++Project Items not completed for RC2
++#6 Ship as Library - Once under CC. Moved to RC3
++#8 Under Clearcase - Moved to RC3
++#25 Emerald compliant - Moved to RC3
++#26 Statistics support - Moved to RC3 (some support in RC2)
++#36 Debug scheme implemented - Moved to RC3 (some support in RC2)
++
++8 November 2002 CPHAL Release Candidate 1
++
++Notes:
++
++Project Items not completed for RC1
++
++#8 Under Clearcase - Clearcase server failure this week. Moved to RC2
++#6 Ship as Library - Once under CC. Moved to RC2
++#13 Verify Datatypes. Moved to RC2
++#14 Review APIs. Moved to RC2
++
++APIs under review for RC2
++
++halIsr()
++hslRxReturn()
++halSend()
++osSendComplete()
++osReceive()
++
++
++CPMAC Build Instructions
++
++Compile the file 'hcpmac.c'.
++
++
++AAL5 Build Instructions
++
++The AAL5 build is composed of the source files aal5sar.c and cpsar.c.
++Refer to the provided makefile for an example of compiling these files
++into a library.
++
++Example CPHAL Code
++
++CPMAC:
++
++Example CPMAC code is provided in the file hbridge.c.
++This program is provided simply as an example of using the CPHAL API.
++It is not intended to be compiled and executed in your environment.
++
++AAL5:
++
++Example AAL5 code is provided in the file loopback.c. This program
++is provided simply as an example of using the CPHAL API. It is not
++intended to be compiled and executed in your environment.
++
++
++Performance Baseline
++
++
++Cpmac
++
++RC1: hbridge.bin, running with IXIA cpahl_1.cfg.
++ This sends 64-byte packets from each Ixia port, with mac destination the other Ixia port.
++ MIPS core 4Kc.
++
++RC2: hbridge.bin, running with IXIA cpahl_1.cfg.
++ This sends 64-byte packets from each Ixia port, with mac destination the other Ixia port.
++ MIPS core 4Ke.
++ CPHAL now includes Emerald support, but this has been disabled by using 'cache -wt' to emulate 4Kc.
++
++RC3: hbridge.bin, running with IXIA cpahl_1.cfg.
++ This sends 64-byte packets from each Ixia port, with mac destination the other Ixia port.
++ MIPS core 4Ke.
++ Running as Emerald processor.
++
++Release Total Receive Rate Throughput Setting
++
++RC1 11300 38%
++RC2 9524 32%
++RC3 15190 51%
+diff -urN linux.old/drivers/net/Config.in linux.dev/drivers/net/Config.in
+--- linux.old/drivers/net/Config.in 2005-07-12 03:20:45.726149872 +0200
++++ linux.dev/drivers/net/Config.in 2005-07-12 02:48:42.180573000 +0200
+@@ -25,6 +25,24 @@
+ comment 'Ethernet (10 or 100Mbit)'
+ bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET
+ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
++ if [ "$CONFIG_MIPS_TITAN" = "y" -o "$CONFIG_AR7" = "y" ]; then
++ tristate ' Texas Instruments Avalanche CPMAC support' CONFIG_MIPS_AVALANCHE_CPMAC
++ fi
++ if [ "$CONFIG_MIPS_AVALANCHE_CPMAC" != "n" ]; then
++ if [ "$CONFIG_AR7WRD" = "y" -o "$CONFIG_AR7VWI" = "y" -o "$CONFIG_AR7VW" = "y" ]; then
++ define_bool CONFIG_MIPS_CPMAC_INIT_BUF_MALLOC y
++ define_int CONFIG_MIPS_CPMAC_PORTS 1
++ if [ "$CONFIG_MIPS_AVALANCHE_MARVELL" = "y" ]; then
++ define_bool CONFIG_AVALANCHE_LOW_CPMAC n
++ define_bool CONFIG_AVALANCHE_HIGH_CPMAC y
++ else
++ define_bool CONFIG_AVALANCHE_CPMAC_AUTO y
++ define_bool CONFIG_AVALANCHE_LOW_CPMAC n
++ define_bool CONFIG_AVALANCHE_HIGH_CPMAC n
++ fi
++ fi
++ fi
++
+ if [ "$CONFIG_ARM" = "y" ]; then
+ dep_bool ' ARM EBSA110 AM79C961A support' CONFIG_ARM_AM79C961A $CONFIG_ARCH_EBSA110
+ tristate ' Cirrus Logic CS8900A support' CONFIG_ARM_CIRRUS
+diff -urN linux.old/drivers/net/Makefile linux.dev/drivers/net/Makefile
+--- linux.old/drivers/net/Makefile 2005-07-12 03:20:45.726149872 +0200
++++ linux.dev/drivers/net/Makefile 2005-07-12 02:48:42.181573000 +0200
+@@ -56,6 +56,16 @@
+ subdir-$(CONFIG_BONDING) += bonding
+
+ #
++# Texas Instruments AVALANCHE CPMAC driver
++#
++
++subdir-$(CONFIG_MIPS_AVALANCHE_CPMAC) += avalanche_cpmac
++#obj-$(CONFIG_MIPS_AVALANCHE_CPMAC) += avalanche_cpmac/avalanche_cpmac.o
++ifeq ($(CONFIG_MIPS_AVALANCHE_CPMAC),y)
++ obj-y += avalanche_cpmac/avalanche_cpmac.o
++endif
++
++#
+ # link order important here
+ #
+ obj-$(CONFIG_PLIP) += plip.o
+--- linux.old/drivers/net/avalanche_cpmac/cpmac.c 2005-08-25 10:56:33.702931008 +0200
++++ linux.dev/drivers/net/avalanche_cpmac/cpmac.c 2005-08-25 11:08:45.027451520 +0200
+@@ -2158,17 +2158,16 @@
+ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
+ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal;
+ struct sk_buff *p_skb = fragList[0].OsInfo;
+- p_skb->len = fragList[0].len;
+
+ /* invalidate the cache. */
+ dma_cache_inv((unsigned long)p_skb->data, fragList[0].len);
+ #ifdef CPMAC_TEST
+- xdump(p_skb->data, p_skb->len, "recv");
++ xdump(p_skb->data, fragList[0].len, "recv");
+ #endif
+ #ifdef CPMAC_8021Q_SUPPORT
+ /* 802.1q stuff, just does the basic checking here. */
+ if(!p_cpmac_priv->enable_802_1q &&
+- p_skb->len > TCI_END_OFFSET &&
++ fragList[0].len > TCI_END_OFFSET &&
+ IS_802_1Q_FRAME(p_skb->data + TPID_START_OFFSET))
+ {
+ goto cpmac_hal_recv_frame_mismatch;
diff --git a/target/linux/ar7-2.4/patches/004-atm_driver.patch b/target/linux/ar7-2.4/patches/004-atm_driver.patch
new file mode 100644
index 0000000000..f6a920853a
--- /dev/null
+++ b/target/linux/ar7-2.4/patches/004-atm_driver.patch
@@ -0,0 +1,27232 @@
+diff -urN linux.old/drivers/atm/Config.in linux.dev/drivers/atm/Config.in
+--- linux.old/drivers/atm/Config.in 2005-08-22 23:18:37.773532032 +0200
++++ linux.dev/drivers/atm/Config.in 2005-08-23 04:46:50.076846888 +0200
+@@ -99,4 +99,10 @@
+ bool 'Use S/UNI PHY driver' CONFIG_ATM_HE_USE_SUNI
+ fi
+ fi
++#
++# Texas Instruments SANGAM ADSL/ATM support
++#
++if [ "$CONFIG_AR7" = "y" ]; then
++ tristate 'Texas Instruments SANGAM ATM/ADSL support' CONFIG_MIPS_SANGAM_ATM
++fi
+ endmenu
+diff -urN linux.old/drivers/atm/Makefile linux.dev/drivers/atm/Makefile
+--- linux.old/drivers/atm/Makefile 2005-08-22 23:18:37.773532032 +0200
++++ linux.dev/drivers/atm/Makefile 2005-08-23 04:46:50.077846736 +0200
+@@ -14,6 +14,32 @@
+ obj-$(CONFIG_ATM_NICSTAR) += nicstar.o
+ obj-$(CONFIG_ATM_IDT77252) += idt77252.o
+
++ifeq ($(CONFIG_AR7),y)
++
++subdir-$(CONFIG_MIPS_SANGAM_ATM) += sangam_atm
++
++EXTRA_CFLAGS += -DEL -I$(TOPDIR)/drivers/atm/sangam_atm -DPOST_SILICON -DCOMMON_NSP -DCONFIG_LED_MODULE -DDEREGISTER_LED -DNO_ACT
++#EXTRA_CFLAGS += -DEL -I$(TOPDIR)/drivers/atm/sangam_atm -DPOST_SILICON -DCOMMON_NSP
++
++ifeq ($(ANNEX),B)
++EXTRA_CFLAGS += -DANNEX_B -DB
++else
++ifeq ($(ANNEX),C)
++EXTRA_CFLAGS += -DANNEX_C -DC
++else
++EXTRA_CFLAGS += -DANNEX_A -DP
++endif
++endif
++
++list-multi := tiatm.o
++tiatm-objs := sangam_atm/tn7atm.o sangam_atm/tn7dsl.o sangam_atm/tn7sar.o \
++ sangam_atm/dsl_hal_api.o sangam_atm/dsl_hal_support.o sangam_atm/cpsar.o \
++ sangam_atm/aal5sar.o
++
++obj-$(CONFIG_MIPS_SANGAM_ATM) += sangam_atm/tiatm.o
++
++endif
++
+ ifeq ($(CONFIG_ATM_NICSTAR_USE_SUNI),y)
+ obj-$(CONFIG_ATM_NICSTAR) += suni.o
+ endif
+diff -urN linux.old/drivers/atm/sangam_atm/aal5sar.c linux.dev/drivers/atm/sangam_atm/aal5sar.c
+--- linux.old/drivers/atm/sangam_atm/aal5sar.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/aal5sar.c 2005-08-23 04:46:50.080846280 +0200
+@@ -0,0 +1,2962 @@
++
++/**
++ *
++ * aal5sar.c
++ *
++ * TNETDxxxx Software Support\n
++ * Copyright (c) 2002 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ * version
++ * 28Feb02 Greg 1.00 Original Version created.\n
++ * 06Mar02 Greg 1.01 Documentation (Doxygen-style) enhanced
++ * 06May02 Greg 1.02 AAL2 added
++ * 06Jun02 Greg 1.03 Multiple API and bug fixes from emulation
++ * 12Jul02 Greg 1.04 API Update
++ */
++
++/**
++@defgroup CPHAL_Functions CPHAL Functions
++
++These are the CPHAL Functions.
++*/
++
++/**
++@page CPHAL_Implementation_Details
++
++@section cphal_intro Introduction
++
++The CPHAL API described above is generally applicable to all modules. Any
++implementation differences will be described in the following module-specific
++appendix sections.
++
++Included for your reference is a diagram showing the internal architecture
++of the CPHAL:
++
++@image html SangamSoftware.jpg "HAL Architecture"
++@image latex SangamSoftware.jpg "HAL Architecture" height=2.8in
++
++*/
++
++/**
++@defgroup AAL5_Functions Additional Functions for AAL5 Implementation
++
++These functions are used only by the AAL5 module.
++*/
++
++/*
++@defgroup CPMAC_Functions Additional Functions for CPMAC Implementation
++
++No additional functions currently defined.
++*/
++
++/**
++@page VDMA_Implementation_Details
++
++@section vdma_intro Introduction
++
++The VDMA-VT module facilitates efficient transfer of data (especially voice)
++between two devices, as shown in the figure below.
++
++@image html vdma.jpg "VDMA System Block Diagram"
++@image latex vdma.jpg "VDMA System Block Diagram" height=1in
++
++The VDMA-VT module supports two modes of operation: mirror mode and credit mode.
++Mirror mode is intended for systems in which the remote device does not have a
++VDMA-based module. Credit mode is intended for highest performance when VDMA-based
++modules exist on both ends of an interface.
++
++For more detailed information on the operation of the VDMA module, please
++reference the VDMA Module Guide.
++
++@section vdma_channels VDMA Channels
++
++The VDMA-VT module is a single channel, single transmit queue device. Therefore,
++when using the CHANNEL_INFO structure, the correct value for @c Ch is always 0.
++Correspondingly, the correct value for the @c Ch parameter in @c ChannelTeardown() is
++always 0. Further, when calling @c Send(), the driver should always supply the value
++of 0 for both the @c Ch and @c Queue parameters.
++
++For the VDMA-VT, configuring the channel requires the configuration of either 2 FIFO
++elements (in credit mode) or 4 FIFO elements (in mirror mode). For credit mode, the
++driver must configure just the local Tx and Rx FIFOs. For mirror mode, the driver must
++configure the Tx and Rx FIFOs for both the remote and local ends of the interface.
++
++This channel configuration is accomplished through multiple calls to @c ChannelSetup().
++Each call configures a single FIFO, according to the parameters in the CHANNEL_INFO
++structure. The members of VDMA-VT's CHANNEL_INFO structure are defined below.
++
++
++- int RemFifoAddr; Address of remote FIFO (mirror mode only). Set to 0 for credit mode.
++- int FifoAddr; Address of the local FIFO. If 0, the CPHAL will allocate the FIFO.
++- int FifoSize; Size of the FIFO.
++- int PollInt; Polling interval for the FIFO.
++- int Endianness; Endianness of the FIFO. If 1, big endian. If 0, little endian.
++- int RemAddr; Used only in credit mode. This is the base address of the remote
++ remote VDMA-based device (VDMA-VT or AAL2)
++- int RemDevID; Used only in credit mode. Identifies the type of remote VDMA-based device.
++ 0=VDMAVT, 1=AAL2 Ch0, 2=AAL2 Ch1, 3=AAL2 Ch2, 4= AAL2 Ch3.
++
++For the VDMA-VT module, the driver must make all calls to @c ChannelSetup() prior to calling
++@c Open(). This is because several of the channel specific parameters may not be changed
++while the VDMA-VT module is operational.
++
++@section vdma_params VDMA Parameters
++
++Defined here are the set of parameters for the VDMA-VT module. Default settings for
++each parameter should be represented in the device configuration file (options.conf).
++During @c Init(), the CPHAL will reference the device configuration file and load all
++default settings. The @c Control() interface gives the driver an opportunity to
++modify any default settings before the module becomes operational during the @c Open()
++call.
++
++@param NoTxIndication If 1, the CPHAL will not call @c SendComplete(). 0 is default.
++@param NoRxIndication If 1, the CPHAL will not call @c Receive(). 0 is default.
++@param RemoteCPU If 1, the CPHAL will not directly manipulate data in FIFO's, leaving
++ that task for a remote CPU. 0 is default.
++@param RxIntEn If 1, enables Rx interrupts. 0 is default.
++@param TxIntEn If 1, enables Tx interrupts. 0 is default.
++@param Mirror If 1, enables mirror mode. 0 selects credit mode (default).
++@param RxIntCtl Valid only in mirror mode. If 1, interrupts will occur when the Rx FIFO
++ RdIndex is updated. If 0, interrupts occur when the Rx FIFO WrIndex
++ is updated.
++@param TxIntCtl Valid only in mirror mode. If 1, interrupts will occur when the Rx FIFO
++ RdIndex is updated. If 0, interrupts occur when the Rx FIFO WrIndex
++ is updated.
++@param RBigEn Remote big endian mode. If 1, remote is big endian.
++@param LBigEn Local big endian mode. If 1, local is big endian.
++
++@section vdma_polling Using VDMA-VT without interrupts
++
++If your system configuration does not utilize VDMA interrupts, the ability to process the
++Tx and Rx FIFOs is supported. To process the Tx FIFO, call @c CheckTx(). If the CPHAL is
++able to process any complete data transmissions, it will call @c SendComplete() as usual.
++To process the Rx FIFO, call @c CheckRx(). If the CPHAL has received any data, it will
++call @c Receive() to pass the driver the data. Please reference @ref VDMA_Functions for more
++information on these interfaces.
++
++@section vdma_details VDMA Implementation Details
++
++The following functions are not defined for use with VDMA: @c Status(), @c Tick(), @c StatsGet(),
++and @c StatsClear().
++
++*/
++
++/**
++@page AAL5_Implementation_Details
++
++@section aal5_ver Version
++
++@copydoc AAL5_Version
++
++@section aal5_intro Introduction
++
++The AAL5 implementation will support 16 channels for transmit and 16 channels for
++receive. Each of the transmit channels may have up to two transmit queues
++associated with it. If two queues are used, Queue 0 is the high priority queue,
++and Queue 1 is the low priority queue.
++
++@section aal5_params AAL5 Configuration Parameters
++
++AAL5 requires two device entries to be available in the configuration repository, named
++@p "aal5" and @p "sar". The @p aal5 device entry must contain @p base (base address)
++and @p int_line (interrupt number). The @p sar device entry must have both @p base
++(base address) and @p reset_bit (reset bit).
++
++@par Device Level Configuration Parameters
++
++The following parameters are device-level parameters, which apply across all
++channels. The value for these parameters may be modified by changing the value in the
++configuration repository.
++
++- "UniNni":
++AAL5 network setting. 0 = UNI (default), 1 = NNI.
++
++@par Channel Configuration Parameters
++
++All AAL5 channel parameters may also be configured through the @c ChannelSetup() interface.
++Following is the list of @p CHANNEL_INFO members that may be modified by the driver when
++calling @c ChannelSetup(). The driver may provide a value of 0xFFFFFFFF for any channel
++parameter to select a default value for the parameter. The driver should at a minimum
++configure @p Vci and @p Vpi. The usage of all parameters beginning with TxVc_,
++TxVp_, RxVc_, RxVp_ is described in greater detail in the SAR Firmware Spec.
++These parameters are mainly associated with QoS and OAM functionality.
++
++- "RxNumBuffers":
++The number of Rx buffer descriptors to allocate for Ch.
++- "RxBufSize":
++Size (in bytes) for each Rx buffer.
++- "RxBufferOffset":
++Number of bytes to offset rx data from start of buffer (must be less than buffer size).
++- "RxServiceMax":
++Maximum number of packets to service at one time.
++- "TxNumBuffers":
++The number of Tx buffer descriptors to allocate for Ch.
++- "TxNumQueues":
++Number of Tx queues for this channel (1-2). Choosing 2 enables a low priority SAR queue.
++- "TxServiceMax":
++Maximum number of packets to service at one time.
++- "CpcsUU":
++The 2-byte CPCS UU and CPI information.
++- "Gfc":
++Generic Flow Control. Used in ATM header of Tx packets.
++- "Clp":
++Cell Loss Priority. Used in ATM header of Tx packets.
++- "Pti":
++Payload Type Indication. Used in ATM header of Tx packets.
++- "DaMask":
++Specifies whether credit issuance is paused when Tx data not available.
++- "Priority":
++Priority bin this channel will be scheduled within.
++- "PktType":
++0=AAL5,1=Null AAL,2=OAM,3=Transparent,4=AAL2.
++- "Vci":
++Virtual Channel Identifier.
++- "Vpi":
++Virtual Path Identifier.
++- "TxVc_AtmHeader":
++In firmware OAM mode, this
++is the ATM header to be appended to front of firmware generated VC OAM cells for
++this channel. Note: To generate host OAM cells, call @c Send() with
++the appropriate mode.
++- "TxVc_CellRate":
++Tx rate, set as clock ticks between transmissions (SCR for VBR, CBR for CBR).
++- "TxVc_QosType":
++0=CBR,1=VBR,2=UBR,3=UBRmcr.
++- "TxVc_Mbs":
++Min Burst Size in cells.
++- "TxVc_Pcr":
++Peak Cell Rate for VBR in clock ticks between transmissions.
++- "TxVc_OamTc":
++TC Path to transmit OAM cells for TX connections (0,1).
++- "TxVc_VpOffset":
++Offset to the OAM VP state table for TX connections. Channels with the same
++VPI must have the same VpOffset value. Channels with different VPIs
++must have unique VpOffset values.
++- "RxVc_OamCh":
++Channel to which to terminate received OAM cells to be forwarded to the Host
++for either Host OAM mode, or when RxVc_OamToHost is enabled during Firmware
++OAM mode.
++- "RxVc_OamToHost":
++Indicates whether to pass received unmatched OAM loopback cells to the host;
++0=do not pass, 1=pass.
++- "RxVc_AtmHeader":
++ATM Header placed on firmware gen'd OAM cells for this channel on a Rx
++connection (must be big endian with 0 PTI).
++- "RxVc_OamTc":
++TC Path to transmit OAM cells for RX connections (0,1).
++- "RxVc_VpOffset":
++Offset to the OAM VP state table for RX connections. Channels with the same
++VPI must have the same VpOffset value. Channels with different VPIs
++must have unique VpOffset values.
++- "TxVp_OamTc":
++TC Path to transmit OAM cells for TX VP connections (0,1).
++- "TxVp_AtmHeader":
++ATM Header placed on firmware gen'd VP OAM cells for this channel on a Tx VP
++connection (must be big endian with 0 VCI).
++- "RxVp_OamCh":
++Channel to which to terminate received OAM cells to be forwarded to the Host
++for either Host OAM mode, or when RxVc_OamToHost is enabled during Firmware
++OAM mode.
++- "RxVp_OamToHost":
++Indicates whether to pass received unmatched OAM loopback cells to the host;
++0=do not pass, 1=pass.
++- "RxVp_AtmHeader":
++In firmware OAM mode, this
++is the ATM header to be appended to front of firmware generated VP OAM cells for
++this channel. Note: To generate host OAM cells, call @c Send() with
++the appropriate mode.
++- "RxVp_OamTc":
++TC Path to transmit OAM cells for RX VP connections (0,1).
++- "RxVp_OamVcList":
++This 32-bit field is one-hot encoded to indicate all the VC channels that are
++associated with this VP channel. A value of 21 will indicate that VC
++channels 0, 2, and 4 are associated with this VP channel.
++- "FwdUnkVc":
++Indicates whether or not to forward unknown VCI/VPI cells to the host. This
++parameter only takes effect if the channel's PktType is Transparent(3).
++1=forwarding enabled, 0=forwarding disabled.
++
++@section aal5_details API Implementation Details
++
++ATTENTION: Documentation given here supplements the documentation given in the general
++CPHAL API section. The following details are crucial to correct usage of the
++AAL5 CPHAL.
++
++@par Receive()
++The least significant byte of @p Mode contains the channel number. Bit 31
++indicates whether or not the ATM header is present in the first fragment of
++the packet. If bit 31 is set, the 4 byte ATM header (minus HEC) will be provided
++in the first fragment, with the payload beginning in the second fragment. Currently,
++this is the default behavior for host OAM and transparent mode packets.
++Bits 17-16 indicate the packet type that is being received.
++Mode Parameter Breakdown: <BR>
++- 31 ATM Header In First Fragment (1=true, 0=false) <BR>
++- 30-18 Unused. <BR>
++- 17-16 Pkt Type. <BR>
++ - 0=AAL5 <BR>
++ - 1=PTI Based Null AAL <BR>
++ - 2=OAM <BR>
++ - 3=Transparent <BR>
++- 15-08 Unused. <BR>
++- 07-00 Channel Number.
++
++@par Send()
++The most significant 16 bits of the first fragment 'len' is used as the Offset
++to be added to the packet. @c Send() will reserve this many bytes at the
++beginning of the transmit buffer prior to the first byte of valid data.
++For the @p Mode parameter, Bit 31 must be set if the user has sent a packet with
++the ATM Header (minus HEC) embedded in the first 4 bytes of the first fragment data buffer.
++The OS has the option of using a 4 byte first fragment containing only ATM header,
++or concatenating the ATM Header in front of the data payload.
++If Bit 31 is set, the ATM Header in the buffer is preserved and sent with
++each cell of the packet. Otherwise, Send() will build the ATM header based on the
++values of the Pti, Gfc, Clp, Vpi, and Vci parameters for the given channel.
++Bits 17-16 are defined as the packet type. Bits 15-08 may be used to specify the
++transmit queue to send the packet on. Only values 0 (high priority) and 1 (low
++priority) are accepted. Bits 07-00 should be used to indicate the channel number
++for the @c Send() operation. Valid channel numbers are 0-15.
++Mode Parameter Breakdown: <BR>
++- 31 ATM Header In Packet (1=true, 0=false) <BR>
++- 30-18 Unused. <BR>
++- 17-16 Pkt Type. <BR>
++ - 0=AAL5 <BR>
++ - 1=PTI Based Null AAL <BR>
++ - 2=OAM <BR>
++ - 3=Transparent <BR>
++- 15-08 Transmit Queue. <BR>
++- 07-00 Channel Number.
++
++@par ChannelSetup()
++The AAL5 @c ChannelSetup() always configures both the Tx and Rx side of the channel
++connection in the same call.
++
++@par ChannelTeardown()
++Regardless of the channel teardown direction selected, the AAL5 CPHAL will always
++teardown both the Tx and Rx side of the channel connection.
++
++@par TeardownComplete()
++The value for the @p Direction parameter should be ignored for the AAL5 implementation,
++since both directions (Tx and Rx) are always torndown in response to a @c ChannelTeardown()
++command.
++
++@par Control() (HAL version)
++Defined keys and actions. Unless otherwise stated, the data type
++for Value is pointer to unsigned integer. The list is broken into
++three groups, one group which can be used anytime, one group that should
++be used before halOpen(), and one group which can only be used after
++halOpen() (but before halClose()). For channelized parameters, replace
++'Ch' with the integer number of a channel (ex. "Gfc.4" can be used to set
++Gfc for channel 4).
++
++MAY USE ANYTIME AFTER INIT (after halInit() is called):
++
++- "Gfc.Ch". The OS may "Set" this value. Changing this value causes
++the Gfc in each Tx ATM header for this channel to take on the new Gfc value.
++
++- "Clp.Ch". The OS may "Set" this value. Changing this value causes
++the Clp in each Tx ATM header for this channel to take on the new Clp value.
++
++- "Pti.Ch". The OS may "Set" this value. Changing this value causes
++the Pti in each Tx ATM header for this channel to take on the new Pti value.
++
++- "CpcsUU.Ch". The OS may "Set" this value. Changing this value causes
++the CpcsUU in each Tx ATM header for this channel to take on the new CpcsUU value.
++
++- "OamMode". Specifies if host or firmware is performing OAM functions; 0 = Host OAM,
++1 = Firmware OAM. When set, all SAR channels will be configured for
++the selection, including AAL2 channels.
++
++- "OamLbTimeout". Specifies the firmware OAM loopback timeout, in milliseconds.
++
++- "DeviceCPID". The OS may "Set" this value. This is the OAM connection
++point identifier. The OS should provide a pointer to an array of 4 32-bit
++integers. Each word must be configured in big endian format.
++
++- "FwdUnkVc.Ch". Indicates whether or not to forward unknown VCI/VPI cells to the host.
++This parameter only takes effect if the channel's PktType is Transparent(3).
++1=forwarding enabled, 0=forwarding disabled.
++
++MAY USE ONLY BEFORE HAL IS OPEN (before halOpen() call):
++- "StrictPriority". The OS may "Set" this value. Setting to 1 causes
++a different interrupt processing routine to be used, which gives strict
++priority to channels with lower numbers (channel 0 has highest priority).
++The default handler gives equal priority to all channels.
++
++- "MaxFrags". The OS may "Set" or "Get" this value. This defines the maximum
++number of fragments that can be received by the AAL5 Rx port. The default
++value for AAL5 is 46. This provides enough space to receive a maximum
++length AAL5 packet (65,568 bytes) with the default buffer size of 1518 bytes, and
++any amount of RxBufferOffset. If the buffer size is configured to be smaller,
++the OS *MUST* modify this parameter according to the following formula:
++((System Max AAL5 packet length)/(RxBufSize)) + 2. (The extra two fragments in
++the formula allow for RxBufferOffset and one fragment for the ATM Header, used
++when receiving host OAM or transparent mode packets)
++
++MAY USE ONLY AFTER HAL IS 'OPEN' (after halOpen() call):
++- "Stats;Level;Ch;Queue". The OS may "Get" Stats groups with this key, where
++'Level' is an integer from 0-4, Ch is an integer from 0-15, and Queue is
++an integer from 0-1. Note that Ch is not required for Level 4 stats, and Queue
++is not required for Level 0, 3, and 4. The statistics functionality and return
++value is described in the appendix entitled "Configuration and Control".
++
++- "TxVc_CellRate.Ch". The OS may "Set" this value. Can be used to modify
++CellRate for a channel on the fly.
++
++- "TxVc_Mbs.Ch". The OS may "Set" this value. Can be used to modify
++Mbs for a channel on the fly.
++
++- "TxVc_Pcr.Ch". The OS may "Set" this value. Can be used to modify
++Pcr for a channel on the fly.
++
++- "PdspEnable". The OS may "Set" this value. Value 0 disables the PDSP.
++Value 1 enables to PDSP.
++
++- "DeviceCPID". The OS may "Set" this value. The Value should be an array
++of 4 32-bit integers that comprise the CPID.
++
++- "RxVc_RDICount.Ch". The OS may "Get" or "Set" this value. Get returns
++the current RDI count for the VC channel. Set clears the counter, and the Value
++is ignored.
++
++- "RxVp_RDICount.Ch". The OS may "Get" or "Set" this value. Get returns
++the current RDI count for the VP channel. Set clears the counter, and the Value
++is ignored.
++
++- "RxVc_AISseg.Ch". The OS may "Get" this value. This is an indication of
++AIS segment error for the VC channel.
++
++- "RxVp_AISseg.Ch". The OS may "Get" this value. This is an indication of
++AIS segment error for the VP channel.
++
++- "RxVc_AISetoe.Ch". The OS may "Get" this value. This is an indication of
++AIS end-to-end error for the VC channel.
++
++- "RxVp_AISetoe.Ch". The OS may "Get" this value. This is an indication of
++AIS end-to-end error for the VP channel.
++
++- "RxVc_OamCh.Ch". The OS may "Set" this value. Channel to which to terminate
++received OAM cells to be forwarded to the Host for either Host OAM mode, or when
++RxVc_OamToHost is enabled during Firmware OAM mode.
++
++- "RxVp_OamCh.Ch". The OS may "Set" this value. Channel to which to terminate
++received OAM cells to be forwarded to the Host for either Host OAM mode, or when
++RxVp_OamToHost is enabled during Firmware OAM mode.
++
++- "F4_LB_Counter". The OS may "Get" this value. This is a count of the number
++ of near-end F4 loopbacks performed by the PDSP in firmware OAM mode.
++
++- "F5_LB_Counter". The OS may "Get" this value. This is a count of the number
++ of near-end F5 loopbacks performed by the PDSP in firmware OAM mode.
++
++- "TxVc_AtmHeader.Ch". The OS may "Set" this value. In firmware OAM mode, this
++is the ATM header to be appended to front of firmware generated VC OAM cells for
++this channel. In host OAM mode, this is used as the ATM header to be appended
++to front of host generated VC OAM cells for this channel. It must be configured
++as big endian with PTI=0. Note: To generate host OAM cells, call @c Send() with
++the appropriate mode.
++
++- "TxVp_AtmHeader.Ch". The OS may "Set" this value. In firmware OAM mode, this
++is the ATM header to be appended to front of firmware generated VP OAM cells for
++this channel. In host OAM mode, this is used as the ATM header to be appended
++to front of host generated VP OAM cells for this channel. It must be configured
++as big endian with VCI=0. Note: To generate host OAM cells, call @c Send() with
++the appropriate mode.
++
++- "PdspEnable". The OS may "Set" this value. Controls whether or not the PDSP is
++allowed to fetch new instructions. The PDSP is enabled by the CPHAL during Open(),
++and disabled during Close(). 0 = disabled, 1 = enabled.
++
++@par Control() (OS version)
++Defined keys and actions:
++
++- "Firmware". The CPHAL will perform a "Get" action for the key "Firmware". A pointer
++to a pointer is passed in @p Value. The OS must modify the referenced pointer to point
++to the firmware.
++
++- "FirmwareSize". The CPHAL will perform a "Get" action for the key "FirmwareSize".
++The OS must place the firmware size in the memory pointed at by @p Value.
++
++- "OamLbResult". When a channel that is in firmware OAM mode is commanded to perform
++a loopback function, the result of the loopback generates an interrupt that is handled
++by the OS like any other interrupt. The CPHAL, upon servicing the interrupt, will call
++osControl with this key, and an action of "Set". The @p Value parameter will be a
++pointer to the integer result. 1 = pass, 0 = fail.
++
++- "SarFreq". The CPHAL will perform a "Get" action for this key. The OS should place
++the SAR frequency (in Hz) in the memory pointed at by @p Value.
++
++@section aal5_stats AAL5 Specific Statistics
++
++Statistics level '0' contains all AAL5 specific statistics. The following values will
++be obtained when requesting stats level 0:
++
++- "Crc Errors". Number of CRC errors reported by SAR hardware. Incremented for received
++packets that contain CRC errors.
++
++- "Len Errors". Number of length errors reported by SAR hardware. Incremented for received
++packets that are in excess of 1366 cells.
++
++- "Abort Errors". Number of abort errors reported by SAR hardware.
++
++- "Starv Errors". Number of buffer starvation errors reported by SAR hardware. Incremented
++when a part or all of a buffer cannot be received due to lack of RX buffer resources. The SAR
++drops all cells associated with the packet for each buffer starvation error that occurs.
++
++*/
++
++/* register files */
++#include "cp_sar_reg.h"
++
++#define _CPHAL_AAL5
++#define _CPHAL
++#define _CPPI_TEST /** @todo remove for release */
++#define __CPHAL_CPPI_OFFSET /* support use of offset */
++
++/* OS Data Structure definitions */
++
++typedef void OS_PRIVATE;
++typedef void OS_DEVICE;
++typedef void OS_SENDINFO;
++typedef void OS_RECEIVEINFO;
++typedef void OS_SETUP;
++
++/* CPHAL Data Structure definitions */
++
++typedef struct hal_device HAL_DEVICE;
++typedef struct hal_private HAL_PRIVATE;
++typedef struct hal_private HAL_RECEIVEINFO;
++
++/* include CPHAL header files here */
++#include "cpcommon_cpaal5.h"
++#include "cpswhal_cpaal5.h"
++#include "aal5sar.h"
++#include "cpcommon_cpaal5.c"
++
++#define CR_SERVICE (170-1)
++#define UTOPIA_PAUSE_REG (*(volatile bit32u *)0xa4000000)
++
++/*
++these masks are for the mode parameter used in halSend/OsReceive
++(may move these elsewhere)
++*/
++#define CH_MASK 0xff
++#define PRI_MASK 0x10000
++
++/* Rcb/Tcb Constants */
++#define CB_SOF_BIT (1<<31)
++#define CB_EOF_BIT (1<<30)
++#define CB_SOF_AND_EOF_BIT (CB_SOF_BIT|CB_EOF_BIT)
++#define CB_OWNERSHIP_BIT (1<<29)
++#define CB_EOQ_BIT (1<<28)
++#define CB_SIZE_MASK 0x0000ffff
++#define CB_OFFSET_MASK 0xffff0000
++#define RCB_ERRORS_MASK 0x03fe0000
++#define RX_ERROR_MASK 0x000f0000
++#define CRC_ERROR_MASK 0x00010000
++#define LENGTH_ERROR_MASK 0x00020000
++#define ABORT_ERROR_MASK 0x00040000
++#define STARV_ERROR_MASK 0x00080000
++#define TEARDOWN_VAL 0xfffffffc
++
++/* interrupt vector masks */
++#define TXH_PEND 0x01000000
++#define TXL_PEND 0x02000000
++#define RX_PEND 0x04000000
++#define STS_PEND 0x08000000
++#define AAL2_PEND 0x10000000
++#define INT_PENDING (TXH_PEND | TXL_PEND | RX_PEND | STS_PEND | AAL2_PEND)
++#define STS_PEND_INVEC 0x0001F000
++#define RX_PEND_INVEC 0x00000F00
++#define TXL_PEND_INVEC 0x000000F0
++#define TXH_PEND_INVEC 0x0000000F
++#define AIS_SEG_MASK 0x1 /* +01.02.00 */
++#define AIS_SEG_SHIFT 0 /* +01.02.00 */
++#define AIS_ETOE_MASK 0x20000 /* +01.02.00 */
++#define AIS_ETOE_SHIFT 17 /* +01.02.00 */
++#define RDI_CNT_MASK 0xffff0000 /* +01.02.00 */
++#define RDI_CNT_SHIFT 16 /* +01.02.00 */
++
++/*
++ * This function takes a vpi/vci pair and computes the 4 byte atm header
++ * (minus the HEC).
++ *
++ * @param vpi Virtual Path Identifier.
++ * @param vci Virtual Channel Identifier.
++ *
++ * @return A properly formatted ATM header, without the HEC.
++ */
++static int atmheader(int gfc, int vpi, int vci, int pti, int clp)
++ {
++ int itmp;
++
++ itmp=0;
++
++ /* UNI Mode uses the GFC field */
++ itmp |= ((gfc & 0xF) << 28);
++ itmp |= ((vpi & 0xFF) << 20);
++
++ /* if NNI Mode, no gfc and larger VPI */
++ /*itmp |= ((vpi & 0xFFF) << 20);*/
++
++ itmp|=((vci & 0xFFFF) << 4);
++ itmp|=((pti & 0x7) << 1);
++ itmp|=(clp & 0x1);
++ return(itmp);
++ }
++
++#include "cppi_cpaal5.c"
++
++/*
++ * Re-entrancy Issues
++ * In order to ensure successful re-entrancy certain sections of the
++ * CPHAL code will be bracketed as Critical.
++ * The OS will provide the function Os.CriticalSection(BOOL), which
++ * will be passed a TRUE to enter the Critical Section and FALSE to exit.
++ */
++
++/*
++ * @ingroup CPHAL_Functions
++ * Clears the statistics information.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ *
++ * @return 0 OK, Non-zero not OK
++ */
++static int StatsClear(HAL_DEVICE *HalDev)
++ {
++ int i;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]StatsClear(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* clear stats */
++ for (i=0; i<NUM_AAL5_CHAN; i++)
++ {
++ HalDev->Stats.CrcErrors[i]=0;
++ HalDev->Stats.LenErrors[i]=0;
++ HalDev->Stats.DmaLenErrors[i]=0;
++ HalDev->Stats.AbortErrors[i]=0;
++ HalDev->Stats.StarvErrors[i]=0;
++ HalDev->Stats.TxMisQCnt[i][0]=0;
++ HalDev->Stats.TxMisQCnt[i][1]=0;
++ HalDev->Stats.RxMisQCnt[i]=0;
++ HalDev->Stats.RxEOQCnt[i]=0;
++ HalDev->Stats.TxEOQCnt[i][0]=0;
++ HalDev->Stats.TxEOQCnt[i][1]=0;
++ HalDev->Stats.RxPacketsServiced[i]=0;
++ HalDev->Stats.TxPacketsServiced[i][0]=0;
++ HalDev->Stats.TxPacketsServiced[i][1]=0;
++ HalDev->Stats.TxMaxServiced[i][0]=0;
++ HalDev->Stats.TxMaxServiced[i][1]=0;
++ }
++ HalDev->Stats.RxTotal=0;
++ HalDev->Stats.TxTotal=0;
++ HalDev->Stats.RxMaxServiced=0;
++ return (EC_NO_ERRORS);
++ }
++
++/*
++ * Returns statistics information.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ *
++ * @return 0
++ */
++/*
++static STAT_INFO* StatsGet(HAL_DEVICE *HalDev)
++ {
++ STAT_INFO* MyStats = &HalDev->Stats;
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]StatsGet(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++ dbgPrintf("HAL Stats:\n");
++ DispStat(HalDev, "Rx Total",MyStats->RxTotal);
++ DispStat(HalDev, "Tx Total",MyStats->TxTotal);
++ DispStat(HalDev, "Rx Peak",MyStats->RxMaxServiced);
++ DispStat(HalDev, "TxH Peak",MyStats->TxMaxServiced[0][0]);
++ DispStat(HalDev, "TxL Peak",MyStats->TxMaxServiced[0][1]);
++ DispChStat(HalDev, "CrcErr",&MyStats->CrcErrors[0],1);
++ DispChStat(HalDev, "LenErr",&MyStats->LenErrors[0],1);
++ DispChStat(HalDev, "DmaLenErr",&MyStats->DmaLenErrors[0],1);
++ DispChStat(HalDev, "AbortErr",&MyStats->AbortErrors[0],1);
++ DispChStat(HalDev, "StarvErr",&MyStats->StarvErrors[0],1);
++ DispChStat(HalDev, "TxH MisQ Cnt",&MyStats->TxMisQCnt[0][0],2);
++ DispChStat(HalDev, "TxL MisQ Cnt",&MyStats->TxMisQCnt[0][1],2);
++ DispChStat(HalDev, "Rx MisQ Cnt",&MyStats->RxMisQCnt[0],1);
++ DispChStat(HalDev, "Rx EOQ Cnt",&MyStats->RxEOQCnt[0],1);
++ DispChStat(HalDev, "TxH EOQ Cnt",&MyStats->TxEOQCnt[0][0],2);
++ DispChStat(HalDev, "TxL EOQ Cnt",&MyStats->TxEOQCnt[0][1],2);
++ DispChStat(HalDev, "Rx Pkts",&MyStats->RxPacketsServiced[0],1);
++ DispChStat(HalDev, "TxH Pkts",&MyStats->TxPacketsServiced[0][0],2);
++ DispChStat(HalDev, "TxL Pkts",&MyStats->TxPacketsServiced[0][1],2);
++
++ return (&HalDev->Stats);
++ }
++*/
++
++#ifdef __CPHAL_DEBUG
++void dbgChannelConfigDump(HAL_DEVICE *HalDev, int Ch)
++ {
++ CHANNEL_INFO *HalCh = &HalDev->ChData[Ch];
++ dbgPrintf(" [aal5 Inst %d, Ch %d] Config Dump:\n", HalDev->Inst, Ch);
++ dbgPrintf(" TxNumBuffers :%08d, TxNumQueues :%08d\n",
++ HalCh->TxNumBuffers, HalCh->TxNumQueues);
++ dbgPrintf(" RxNumBuffers :%08d, RxBufSize :%08d\n",
++ HalCh->RxNumBuffers, HalCh->RxBufSize);
++ dbgPrintf(" TxServiceMax :%08d, RxServiceMax:%08d\n",
++ HalCh->TxServiceMax, HalCh->RxServiceMax);
++ dbgPrintf(" RxBufferOffset:%08d, DaMask :%08d\n",
++ HalCh->RxBufferOffset, HalCh->DaMask);
++ dbgPrintf(" CpcsUU :%08d, Gfc :%08d\n",
++ HalCh->CpcsUU, HalCh->Gfc);
++ dbgPrintf(" Clp :%08d, Pti :%08d\n",
++ HalCh->Clp, HalCh->Pti);
++ dbgPrintf(" Priority :%08d, PktType :%08d\n",
++ HalCh->Priority, HalCh->PktType);
++ dbgPrintf(" Vci :%08d, Vpi :%08d\n",
++ HalCh->Vci, HalCh->Vpi);
++ dbgPrintf(" TxVc_CellRate :%08d, TxVc_QosType:%08d\n",
++ HalCh->TxVc_CellRate, HalCh->TxVc_QosType);
++ dbgPrintf(" TxVc_Mbs :%08d, TxVc_Pcr :%08d\n",
++ HalCh->TxVc_Mbs, HalCh->TxVc_Pcr);
++ dbgPrintf(" TxVc_AtmHeader:%08d\n",
++ HalCh->TxVc_AtmHeader);
++ osfuncSioFlush();
++ }
++#endif
++
++/*
++ * Retrieves channel parameters from configuration file. Any parameters
++ * which are not found are ignored, and the HAL default value will apply,
++ * unless a new value is given through the channel structure in the call
++ * to ChannelSetup.
++ */
++static int ChannelConfigGet(HAL_DEVICE *HalDev, CHANNEL_INFO *HalChn)
++ {
++ unsigned int Ret, Value, Ch = HalChn->Channel;
++ OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++ void *ChInfo;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]ChannelConfigGet(HalDev:%08x, HalChn:%08x)\n", (bit32u)HalDev,
++ (bit32u)HalChn);
++ osfuncSioFlush();
++ }
++#endif
++
++ Ret=OsFunc->DeviceFindParmValue(HalDev->DeviceInfo, channel_names[Ch], &ChInfo);
++ if (Ret) return (EC_AAL5|EC_FUNC_CHSETUP|EC_VAL_CH_INFO_NOT_FOUND);
++
++ /* i don't care if a value is not found because they are optional */
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "TxNumBuffers", &Value);
++ if (!Ret) HalDev->ChData[Ch].TxNumBuffers = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "TxNumQueues", &Value);
++ if (!Ret) HalDev->ChData[Ch].TxNumQueues = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "TxServiceMax", &Value);
++ if (!Ret) HalDev->ChData[Ch].TxServiceMax = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "RxNumBuffers", &Value);
++ if (!Ret) HalDev->ChData[Ch].RxNumBuffers = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "RxBufferOffset", &Value);
++ if (!Ret) HalDev->ChData[Ch].RxBufferOffset = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "RxBufSize", &Value);
++ if (!Ret) HalDev->ChData[Ch].RxBufSize = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "RxServiceMax", &Value);
++ if (!Ret) HalDev->ChData[Ch].RxServiceMax = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "CpcsUU", &Value);
++ if (!Ret) HalDev->ChData[Ch].CpcsUU = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "Gfc", &Value);
++ if (!Ret) HalDev->ChData[Ch].Gfc = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "Clp", &Value);
++ if (!Ret) HalDev->ChData[Ch].Clp = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "Pti", &Value);
++ if (!Ret) HalDev->ChData[Ch].Pti = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "DaMask", &Value);
++ if (!Ret) HalDev->ChData[Ch].DaMask = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "Priority", &Value);
++ if (!Ret) HalDev->ChData[Ch].Priority = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "PktType", &Value);
++ if (!Ret) HalDev->ChData[Ch].PktType = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "Vci", &Value);
++ if (!Ret) HalDev->ChData[Ch].Vci = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "Vpi", &Value);
++ if (!Ret) HalDev->ChData[Ch].Vpi = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "TxVc_CellRate", &Value);
++ if (!Ret) HalDev->ChData[Ch].TxVc_CellRate = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "TxVc_QosType", &Value);
++ if (!Ret) HalDev->ChData[Ch].TxVc_QosType = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "TxVc_Mbs", &Value);
++ if (!Ret) HalDev->ChData[Ch].TxVc_Mbs = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "TxVc_Pcr", &Value);
++ if (!Ret) HalDev->ChData[Ch].TxVc_Pcr = Value;
++
++ Ret=OsFunc->DeviceFindParmUint(ChInfo, "TxVc_AtmHeader", &Value);
++ if (!Ret) HalDev->ChData[Ch].TxVc_AtmHeader = Value;
++
++ return (EC_NO_ERRORS);
++ }
++
++/*
++ * Sets up channel parameters in the hardware, and initializes the CPPI
++ * TX and RX buffer descriptors and buffers.
++ */
++static int ChannelConfigApply(HAL_DEVICE *HalDev, CHANNEL_INFO *HalChn)
++ {
++ int j, Ch = HalChn->Channel;
++ volatile bit32u *pTmp;
++ int Ret; /* +GSG 030410 */
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]ChannelConfigApply(HalDev:%08x, HalChn:%08x)\n", (bit32u)HalDev,
++ (bit32u)HalChn);
++ osfuncSioFlush();
++ }
++#endif
++
++ if ((HalDev->ChIsOpen[Ch][DIRECTION_TX] == TRUE) || (HalDev->ChIsOpen[Ch][DIRECTION_RX] == TRUE))
++ {
++ return(EC_AAL5|EC_FUNC_CHSETUP|EC_VAL_CH_ALREADY_OPEN);
++ }
++
++ HalDev->InRxInt[Ch]=FALSE;
++
++ /* Initialize Queue Data */
++ HalDev->RxActQueueHead[Ch]=0;
++ HalDev->RxActQueueCount[Ch]=0;
++ HalDev->TxActQueueHead[Ch][0]=0;
++ HalDev->TxActQueueHead[Ch][1]=0;
++ HalDev->TxActQueueCount[Ch][0]=0;
++ HalDev->TxActQueueCount[Ch][1]=0;
++ HalDev->RxActive[Ch] = FALSE;
++ HalDev->TxActive[Ch][0] = FALSE;
++ HalDev->TxActive[Ch][1] = FALSE;
++
++ /* Clear Rx State RAM */
++ pTmp = pRX_DMA_STATE_WORD_0(HalDev->dev_base) + (Ch*64);
++ for (j=0; j<NUM_RX_STATE_WORDS; j++)
++ *pTmp++ = 0;
++
++ /* Check that Rx DMA State RAM was cleared */
++ pTmp -= NUM_RX_STATE_WORDS;
++ for (j=0; j<NUM_RX_STATE_WORDS; j++)
++ {
++ if (*pTmp++ != 0)
++ {
++ return(EC_AAL5|EC_FUNC_CHSETUP|EC_VAL_RX_STATE_RAM_NOT_CLEARED);
++ }
++ }
++
++ /* Clear Tx State RAM */
++ pTmp = pTX_DMA_STATE_WORD_0(HalDev->dev_base) + (Ch*64);
++ for (j=0; j<NUM_TX_STATE_WORDS; j++)
++ *pTmp++ = 0;
++
++ /* Check that Tx DMA State RAM was cleared */
++ pTmp -= NUM_TX_STATE_WORDS;
++ for (j=0; j<NUM_TX_STATE_WORDS; j++)
++ {
++ if (*pTmp++ != 0)
++ {
++ return(EC_AAL5|EC_FUNC_CHSETUP|EC_VAL_TX_STATE_RAM_NOT_CLEARED);
++ }
++ }
++
++ /* Initialize Tx State RAM (Nothing to do) */
++
++ /* Initialize Rx State RAM */
++ /* Configure the Rx buffer offset */
++ pTmp=(pRX_DMA_STATE_WORD_0(HalDev->dev_base) + (Ch*64));
++ *pTmp |= (HalDev->ChData[Ch].RxBufferOffset & 0xFF);
++
++ /* Initialize buffer memory for the channel */
++ Ret = InitTcb(HalDev, Ch);
++ if (Ret) return (Ret);
++
++ Ret = InitRcb(HalDev, Ch);
++ if (Ret) return (Ret);
++
++ /* setup interrupt mask/enable for the channel */
++ SAR_TX_MASK_SET(HalDev->dev_base) = (1<<Ch);
++
++ /* if using the low priority queue, set up mask for it */
++ if (HalDev->ChData[Ch].TxNumQueues == 2) /* +GSG 030421 */
++ SAR_TX_MASK_SET(HalDev->dev_base) = (1<<Ch)<<16; /* +GSG 030421 */
++
++ SAR_RX_MASK_SET(HalDev->dev_base) = (1<<Ch);
++
++ /* call SAR layer to complete the channel setup - hardware configuration of ch */
++ Ret = HalDev->SarFunc->ChannelSetup(HalDev->SarDev, &HalDev->ChData[Ch]); /* ~GSG 030410 */
++ if (Ret) /* +GSG 030410 */
++ return (Ret); /* +GSG 030410 */
++
++ /* channel officially open for business */
++ HalDev->ChIsOpen[Ch][DIRECTION_TX] = TRUE;
++ HalDev->ChIsOpen[Ch][DIRECTION_RX] = TRUE;
++
++ return (EC_NO_ERRORS);
++ }
++
++/*
++ * Sets up HAL default channel configuration parameter values.
++ */
++static void ChannelConfigInit(HAL_DEVICE *HalDev, CHANNEL_INFO *HalChn)
++ {
++ int Ch = HalChn->Channel;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]ChannelConfigInit(HalDev:%08x, HalChn:%08x)\n", (bit32u)HalDev,
++ (bit32u)HalChn);
++ osfuncSioFlush();
++ }
++#endif
++
++ HalDev->ChData[Ch].Channel = Ch;
++ HalDev->ChData[Ch].TxNumBuffers = cfg_tx_num_bufs[Ch];
++ HalDev->ChData[Ch].RxNumBuffers = cfg_rx_num_bufs[Ch];
++ HalDev->ChData[Ch].RxBufSize = cfg_rx_buf_size[Ch];
++ HalDev->ChData[Ch].RxBufferOffset = cfg_rx_buf_offset[Ch];
++ HalDev->ChData[Ch].TxNumQueues = cfg_tx_num_queues[Ch];
++ HalDev->ChData[Ch].CpcsUU = cfg_cpcs_uu[Ch];
++ HalDev->ChData[Ch].DaMask = cfg_da_mask[Ch];
++ HalDev->ChData[Ch].Priority = cfg_priority[Ch];
++ HalDev->ChData[Ch].PktType = cfg_pkt_type[Ch];
++ HalDev->ChData[Ch].Vci = cfg_vci[Ch];
++ HalDev->ChData[Ch].Vpi = cfg_vpi[Ch];
++ HalDev->ChData[Ch].TxVc_CellRate = cfg_cell_rate[Ch];
++ HalDev->ChData[Ch].TxVc_QosType = cfg_qos_type[Ch];
++ HalDev->ChData[Ch].TxVc_Mbs = cfg_mbs[Ch];
++ HalDev->ChData[Ch].TxVc_Pcr = cfg_pcr[Ch];
++ HalDev->ChData[Ch].Gfc = cfg_gfc[Ch];
++ HalDev->ChData[Ch].Clp = cfg_clp[Ch];
++ HalDev->ChData[Ch].Pti = cfg_pti[Ch];
++ HalDev->ChData[Ch].RxServiceMax = cfg_rx_max_service[Ch];
++ HalDev->ChData[Ch].TxServiceMax = cfg_tx_max_service[Ch];
++ }
++
++/*
++ * Update per channel data in the HalDev based channel structure.
++ * If a certain channel parameter has been passed with the HAL_DEFAULT
++ * value (0xFFFFFFFF), then do not copy it.
++ */
++static void ChannelConfigUpdate(HAL_DEVICE *HalDev, CHANNEL_INFO *HalChn)
++ {
++ int Ch = HalChn->Channel;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]ChannelConfigUpdate(HalDev:%08x, HalChn:%08x)\n", (bit32u)HalDev,
++ (bit32u)HalChn);
++ osfuncSioFlush();
++ }
++#endif
++
++ HalDev->ChData[Ch].Channel = Ch;
++
++ /* ChannelUpdate is a macro defined in cpcommon.h. It requires
++ the presence of the variables named 'Ch' and 'HalChn'.*/
++ ChannelUpdate(DaMask);
++ ChannelUpdate(Priority);
++ ChannelUpdate(PktType);
++ ChannelUpdate(Vci);
++ ChannelUpdate(Vpi);
++ ChannelUpdate(CpcsUU);
++ ChannelUpdate(Gfc);
++ ChannelUpdate(Clp);
++ ChannelUpdate(Pti);
++ /* AAL5 Stuff */
++ ChannelUpdate(TxNumBuffers);
++ ChannelUpdate(RxNumBuffers);
++ ChannelUpdate(RxBufSize);
++ ChannelUpdate(RxBufferOffset);
++ ChannelUpdate(TxNumQueues);
++ ChannelUpdate(TxServiceMax);
++ ChannelUpdate(RxServiceMax);
++ /* PDSP STATE RAM */
++ ChannelUpdate(TxVc_CellRate);
++ ChannelUpdate(TxVc_QosType);
++ ChannelUpdate(TxVc_Mbs);
++ ChannelUpdate(TxVc_Pcr);
++ /* OAM */
++ ChannelUpdate(TxVc_AtmHeader);
++ ChannelUpdate(TxVc_OamTc);
++ ChannelUpdate(TxVc_VpOffset);
++ ChannelUpdate(RxVc_OamCh);
++ ChannelUpdate(RxVc_OamToHost);
++ ChannelUpdate(RxVc_AtmHeader);
++ ChannelUpdate(RxVc_VpOffset);
++ ChannelUpdate(RxVc_OamTc);
++ ChannelUpdate(TxVp_AtmHeader);
++ ChannelUpdate(TxVp_OamTc);
++ ChannelUpdate(RxVp_AtmHeader);
++ ChannelUpdate(RxVp_OamCh);
++ ChannelUpdate(RxVp_OamTc);
++ ChannelUpdate(RxVp_OamToHost);
++ ChannelUpdate(RxVp_OamVcList);
++ ChannelUpdate(FwdUnkVc);
++ }
++
++/**
++ * @ingroup CPHAL_Functions
++ * This function opens the specified channel. The caller must populate
++ * the @p HalCh structure. CPHAL default values may be requested for any or all
++ * members of the @p HalCh structure by supplying a value of 0xFFFFFFFF for the
++ * given member. The @p OsSetup parameter is a pointer to an OS defined
++ * data structure. If the CPHAL later calls @c MallocRxBuffer(), this pointer
++ * is returned in that call.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ * @param HalCh Per channel information structure. Implementation specific.
++ * @param OsSetup Pointer to an OS-defined data structure.
++ *
++ * @return EC_NO_ERRORS (ok). <BR>
++ * Possible Error Codes:<BR>
++ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ * @ref EC_VAL_NULL_CH_STRUCT "EC_VAL_NULL_CH_STRUCT"<BR>
++ * @ref EC_VAL_INVALID_CH "EC_VAL_INVALID_CH"<BR>
++ * @ref EC_VAL_CH_ALREADY_OPEN "EC_VAL_CH_ALREADY_OPEN"<BR>
++ * @ref EC_VAL_RX_STATE_RAM_NOT_CLEARED "EC_VAL_RX_STATE_RAM_NOT_CLEARED"<BR>
++ * @ref EC_VAL_TX_STATE_RAM_NOT_CLEARED "EC_VAL_TX_STATE_RAM_NOT_CLEARED"<BR>
++ * @ref EC_VAL_TCB_MALLOC_FAILED "EC_VAL_TCB_MALLOC_FAILED"<BR>
++ * @ref EC_VAL_RCB_MALLOC_FAILED "EC_VAL_RCB_MALLOC_FAILED"<BR>
++ * @ref EC_VAL_RX_BUFFER_MALLOC_FAILED "EC_VAL_RX_BUFFER_MALLOC_FAILED"<BR>
++ * @ref EC_VAL_LUT_NOT_READY "EC_VAL_LUT_NOT_READY"<BR>
++ */
++static int halChannelSetup(HAL_DEVICE *HalDev, CHANNEL_INFO *HalCh, OS_SETUP *OsSetup)
++ {
++ int Ch, Ret;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]halChannelSetup(HalDev:%08x, HalCh:%08x, OsSetup:%08x)\n", (bit32u)HalDev,
++ (bit32u)HalCh, (bit32u)OsSetup);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* Verify proper device state */
++ if (HalDev->State < enInitialized)
++ return (EC_AAL5|EC_FUNC_CHSETUP|EC_VAL_INVALID_STATE);
++
++ /* We require the channel structure to be passed, even if it only contains
++ the channel number */
++ if (HalCh == NULL)
++ {
++ return(EC_AAL5|EC_FUNC_CHSETUP|EC_VAL_NULL_CH_STRUCT);
++ }
++
++ Ch = HalCh->Channel;
++
++ if ((Ch < 0) || (Ch > MAX_AAL5_CHAN))
++ {
++ return(EC_AAL5|EC_FUNC_CHSETUP|EC_VAL_INVALID_CH);
++ }
++
++ /* if channel is already open, this call is invalid */
++ if ((HalDev->ChIsOpen[Ch][DIRECTION_TX] == TRUE) || (HalDev->ChIsOpen[Ch][DIRECTION_RX] == TRUE))
++ {
++ return(EC_AAL5|EC_FUNC_CHSETUP|EC_VAL_CH_ALREADY_OPEN);
++ }
++
++ /* channel is closed, but might be setup. If so, reopen the hardware channel. */
++ if ((HalDev->ChIsSetup[Ch][DIRECTION_TX] == FALSE) && (HalDev->ChIsSetup[Ch][DIRECTION_RX] == FALSE))
++ {
++ /* Setup channel configuration */
++ /* Store OS_SETUP */
++ HalDev->ChData[Ch].OsSetup = OsSetup; /* ~GSG 030508 */
++
++ /* setup HAL default values for this channel first */
++ ChannelConfigInit(HalDev, HalCh);
++
++ /* retrieve options.conf channel parameters */
++ /* currently ignoring return value, making the choice that it's okay if
++ the user does not supply channel configuration in the data store */
++ ChannelConfigGet(HalDev, HalCh);
++
++ /* update HalDev with data given in HalCh */
++ ChannelConfigUpdate(HalDev, HalCh);
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(8))
++ {
++ dbgChannelConfigDump(HalDev, Ch);
++ }
++#endif
++
++ /* HalDev->ChIsSetup[Ch][0] = TRUE; */
++ HalDev->ChIsSetup[Ch][DIRECTION_TX] = TRUE;
++ HalDev->ChIsSetup[Ch][DIRECTION_RX] = TRUE;
++
++ /* I don't initialize RcbStart or TcbStart here because their values may be
++ reused across several Setup/Teardown calls */
++ }
++
++ /* If the hardware has been opened (is out of reset), then configure the channel
++ in the hardware. NOTE: ChannelConfigApply calls the CPSAR ChannelSetup()! */
++ if (HalDev->State == enOpened)
++ {
++ Ret = ChannelConfigApply(HalDev, HalCh);
++ if (Ret) return (Ret);
++ }
++
++ return (EC_NO_ERRORS);
++ }
++
++/*
++ * This function configures the rate at which the OAM timer scheduler
++ * channels will be scheduled. The value of OamRate is the number of
++ * clock ticks between cell transmissions (if OAM function is sourcing
++ * cells), or the number of clock ticks between events or absence of events
++ * (if OAM function is sinking cells). The value of i indicates
++ * which OAM function to apply the rate to. A list is given below.
++ *
++ * @par Oam Function Values
++ * - 0 : Loopback source
++ * - 1 : F4 CC source
++ * - 2 : F5 CC source
++ * - 3 : F4 CC sink
++ * - 4 : F5 CC sink
++ * - 5 : F4 TX AIS source
++ * - 6 : F5 TX AIS source
++ * - 7 : F4 RX RDI source
++ * - 8 : F5 RX RDI source
++ * - 9 : F4 AIS monitor
++ * - 10 : F5 AIS monitor
++ *
++ * The following is information on how to calculate the OAM rate. There
++ * is only one OAM timer that is shared among all channels. Therefore, if
++ * you wanted an OAM source function (ex. F4 CC source) to generate 1 cell/sec
++ * across 8 channels, you would need to configure the OAM timer to schedule 8
++ * cells/sec. In addition, the credits are shared between segment and end-to-end
++ * type OAM cells, so if you were sending both types of cells, you would
++ * need to configure the OAM timer for 16 cells/sec. However, the clock
++ * rate must be specified in clock ticks between events. Using an example
++ * clock rate of 125 MHz, the rate in clock ticks can be calculated by
++ * dividing 125 Mhz by 16 cells/sec. The results is 7812500 ticks. Thus,
++ * every 7812500 clock cycles, an OAM cell will be generated for the F4 CC
++ * Source function.
++ */
++static void OamRateConfig(HAL_DEVICE *HalDev)
++ {
++ int i;
++ bit32u OamRate, Freq = HalDev->SarFrequency;
++
++ /* Configure OAM Timer State Block */
++ for (i=0; i<NUM_OAM_RATES; i++)
++ {
++ switch(i)
++ {
++ case 0: OamRate = ((Freq/1000)*HalDev->OamLbTimeout);
++ break;
++ case 1:
++ case 2:
++ case 5:
++ case 6:
++ case 7:
++ case 8: OamRate = (Freq/38);
++ break;
++ case 3:
++ case 4: OamRate = ((Freq*3) + (Freq/2))/38;
++ break;
++ case 9:
++ case 10: OamRate = ((Freq*2) + (Freq/2))/38;
++ break;
++ default: OamRate = (Freq*5);
++ break;
++ }
++
++ *(pOAM_TIMER_STATE_WORD_0(HalDev->dev_base) + (i*64) + 1) = OamRate;
++ }
++ }
++
++/**
++ * @ingroup AAL5_Functions
++ * This function is used to enable OAM functions (other than loopback) for a
++ * particular channel. The channel (embedded within OamConfig - see below) must
++ * have been configured for firmware OAM (not host OAM) for these configurations
++ * to take effect. More than one function may be enabled at one time.
++ * If more than one function is enabled, they must all be of the same level, all
++ * F4(VP) or all F5(VC).
++ *
++ * The usage of the OamConfig parameter is described through the table below. To
++ * initiate firmware OAM, set one or more bits in OamConfig corresponding to the
++ * various OAM functions. To disable firmware OAM functions, set bit 30 along
++ * with any other combination of bits to shutdown various OAM functions at once.
++ *
++ * Acronyms:
++ * e2e - end to end, seg - segment, CC - continuity check,
++ * AIS - Alarm Indication Signal
++ *
++ * @par Bit: Function: Description
++ * - 31: Reserved:
++ * - 30: Setup/Teardown: 0 - enable, 1 - disable (Note 1)
++ * - 29: F4 CC Source seg: 0 - no action, 1 - configure
++ * - 28: F4 CC Source e2e: 0 - no action, 1 - configure
++ * - 27: F4 AIS Source seg: 0 - no action, 1 - configure
++ * - 26: F4 AIS Source e2e: 0 - no action, 1 - configure
++ * - 25: F5 CC Source seg: 0 - no action, 1 - configure
++ * - 24: F5 CC Source e2e: 0 - no action, 1 - configure
++ * - 23: F5 AIS Source seg: 0 - no action, 1 - configure
++ * - 22: F5 AIS Source e2e: 0 - no action, 1 - configure
++ * - 21: F4 CC Sink seg: 0 - no action, 1 - configure
++ * - 20: F4 CC Sink e2e: 0 - no action, 1 - configure
++ * - 19: F5 CC Sink seg: 0 - no action, 1 - configure
++ * - 18: F5 CC Sink e2e: 0 - no action, 1 - configure
++ * - 17:8: Reserved:
++ * - 7:0: Channel: AAL5/AAL2 VC/VP channel (Note 2)
++ *
++ *
++ * Note 1: This bit must be clear to enable the specified OAM function.
++ * Note 2: This must specify the VC channel for F5 functions, and the VP
++ * channel for F4 functions.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ * @param OamConfig A 32-bit integer field defined as follows:
++ */
++static void halOamFuncConfig(HAL_DEVICE *HalDev, unsigned int OamConfig)
++ {
++ /* GPR 0 */
++ SAR_PDSP_HOST_OAM_CONFIG_REG(HalDev->dev_base) = OamConfig;
++ }
++
++/**
++ * @ingroup AAL5_Functions
++ * This function is used to enable OAM loopback functions for a particular
++ * channel. The channel (embedded within OamConfig - see below) must have been
++ * configured for firmware OAM (not host OAM) for these configurations to take
++ * effect. Only one loopback function can be enabled at a time.
++ *
++ * The LLID is inserted into to the OAM cell's LLID field, and it specifies the
++ * LLID of the connection point in the network where the generated loopback cell
++ * should be turned around. The LLID is composed of 4 32-bit words, and this
++ * function expects the caller to pass an array of 4 words in the LLID field.
++ * The CorrelationTag is a 32-bit word that the PDSP uses to correlate loopback
++ * commands with loopback responses. It should simply be changed for each
++ * call, and there is no restriction on the value used for CorrelationTag.
++ *
++ * The usage of the OamConfig parameter is described through the table below. To
++ * initiate firmware OAM, set one of the bits corresponding to the
++ * various loopback OAM functions. Note that only one loopback source may be
++ * commanded at a time.
++ *
++ * Acronyms:
++ * e2e - end to end, seg - segment, LB - loopback
++ *
++ * @par Bit: Function: Description
++ * - 31:16: Reserved:
++ * - 15: F4 LB Source seg: 0 - no action, 1 - configure (Note 1)
++ * - 14: F4 LB Source seg: 0 - no action, 1 - configure (Note 1)
++ * - 13: F4 LB Source e2e: 0 - no action, 1 - configure (Note 1)
++ * - 12: F4 LB Source e2e: 0 - no action, 1 - configure (Note 1)
++ * - 11:8: Reserved:
++ * - 7:0: Channel: AAL5/AAL2 VC/VP channel (Note 2)
++ *
++ *
++ * Note 1: Only one LB function may be enabled at one time. Once enabled,
++ * the PDSP will time out after 5 seconds. The host must wait until it
++ * has received the result of the current LB request before initiating
++ * a new request. <BR>
++ * Note 2: This must specify the VC channel for F5 functions, and the VP
++ * channel for F4 functions.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ * @param OamConfig A 32-bit integer field defined as follows:
++ * @param LLID Loopback Location Identifier (passed as 4 word array).
++ * Must be configured in big endian format.
++ * @param CorrelationTag 32-bit tag correlates loopback commands with loopback
++ * responses. Must be configured in big endian format.
++ *
++ */
++static void halOamLoopbackConfig(HAL_DEVICE *HalDev, unsigned int OamConfig, unsigned int *LLID, unsigned int CorrelationTag)
++ {
++ volatile bit32u *tmp;
++
++ /* test to see if this is a loopback command */
++ if (OamConfig & 0xf000)
++ {
++ /* write the OAM correlation tag (GPR 1) */
++ SAR_PDSP_OAM_CORR_REG(HalDev->dev_base) = CorrelationTag;
++
++ /* write the LLID */
++ tmp = pOAM_CONFIG_BLOCK_WORD_0(HalDev->dev_base);
++
++ /* advance past the CPID */
++ tmp += 4;
++
++ *tmp++ = LLID[0];
++ *tmp++ = LLID[1];
++ *tmp++ = LLID[2];
++ *tmp = LLID[3];
++
++ /* GPR 0 */
++ SAR_PDSP_HOST_OAM_CONFIG_REG(HalDev->dev_base) = OamConfig;
++ }
++ }
++
++/*
++ * This function allows the host software to access any register directly.
++ * Primarily used for debug.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ * @param RegOffset Hexadecimal offset to desired register (from device base addr)
++ *
++ * @return Volatile pointer to desired register.
++ */
++static volatile bit32u* halRegAccess(HAL_DEVICE *HalDev, bit32u RegOffset)
++ {
++ /* compute the register address */
++ return ((volatile bit32u *)(HalDev->dev_base + RegOffset));
++ }
++
++#ifdef __CPHAL_DEBUG
++static void dbgConfigDump(HAL_DEVICE *HalDev)
++ {
++ dbgPrintf(" AAL5 Inst %d Config Dump:\n", HalDev->Inst);
++ dbgPrintf(" Base :%08x, offset:%08d\n",
++ HalDev->dev_base, HalDev->offset);
++ dbgPrintf(" Interrupt:%08d, debug :%08d\n",
++ HalDev->interrupt, HalDev->debug);
++ osfuncSioFlush();
++ }
++#endif
++
++/**
++ * @ingroup CPHAL_Functions
++ * Performs a variety of control functions on the CPHAL module. It is used to
++ * modify/read configuration parameters and to initiate internal functions.
++ * The @p Key indicates the function to perform or the parameter to access (note
++ * that these Keys are identical to those used in accessing the configuration data
++ * store). @p Action is applicable to parameters only, and indicates what the
++ * CPHAL should do with the parameter (i.e. "Set", "Get", etc..). The actions
++ * for each parameter are defined in the module specific documentation.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ * @param Key Key specifying the parameter to change or internal function to initiate. See module specific documentation for available keys.
++ * @param Action Specifies the action to take. See module specific documentation for available actions.
++ * @param Value Pointer to new value for given @p Key parameter ("Set"), or returned value of Key ("Get").
++ *
++ * @return EC_NO_ERRORS (ok).<BR>
++ * Possible Error Codes:<BR>
++ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ * @ref EC_VAL_KEY_NOT_FOUND "EC_VAL_KEY_NOT_FOUND"<BR>
++ * @ref EC_VAL_ACTION_NOT_FOUND "EC_VAL_ACTION_NOT_FOUND"<BR>
++ */
++static int halControl(HAL_DEVICE *HalDev, const char *Key, const char *Action, void *Value)
++ {
++ int Level, Ch, KeyFound=0, ActionFound=0, rc=EC_NO_ERRORS, Queue;
++ char *TmpKey = (char *)Key;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]halControl(HalDev:%08x, Key:%s, Action:%s, Value:%08x)\n", (bit32u)HalDev,
++ Key, Action, (bit32u)Value);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* Verify proper device state */
++ if (HalDev->State < enInitialized)
++ return (EC_AAL5|EC_FUNC_CONTROL|EC_VAL_INVALID_STATE);
++
++ if (HalDev->OsFunc->Strcmpi(Key, "Debug") == 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++ HalDev->debug = *(int *)Value;
++ /* also setup debug variable in CPSAR module */
++ rc = HalDev->SarFunc->Control(HalDev->SarDev, "Debug", "Set", Value);
++ }
++ }
++
++ if (HalDev->OsFunc->Strstr(Key, "FwdUnkVc.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("FwdUnkVc.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ HalDev->ChData[Ch].FwdUnkVc = *(int *)Value;
++
++ if ((HalDev->State == enOpened) && (HalDev->ChData[Ch].PktType == 3))
++ rc = HalDev->SarFunc->Control(HalDev->SarDev, Key, Action, Value);
++ }
++ }
++
++ /* +GSG 030407 */
++ if (HalDev->OsFunc->Strcmpi(Key, "OamMode") == 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++ rc = HalDev->SarFunc->Control(HalDev->SarDev, Key, Action, Value);
++ }
++
++ if (HalDev->OsFunc->Strcmpi(Action, "Get") == 0)
++ {
++ ActionFound=1;
++ rc = HalDev->SarFunc->Control(HalDev->SarDev, Key, Action, Value);
++ }
++ }
++
++ /* +GSG 030307 */
++ if (HalDev->OsFunc->Strcmpi(Key, "Version") == 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Get") == 0)
++ {
++ ActionFound=1;
++ *(const char **)Value = pszVersion_CPAAL5;
++ }
++ }
++
++ /* +GSG 030529 */
++ if (HalDev->OsFunc->Strcmpi(Key, "TurboDslErrors") == 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Get") == 0)
++ {
++ ActionFound=1;
++ *(int *)Value = HalDev->TurboDslErrors;
++ }
++ }
++
++ /* +GSG 030416 */
++ if (HalDev->OsFunc->Strcmpi(Key, "F4_LB_Counter") == 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Get") == 0)
++ {
++ ActionFound=1;
++ *(int *)Value = SAR_PDSP_OAM_F4_LB_COUNT_REG(HalDev->dev_base);
++ }
++ }
++
++ /* +GSG 030416 */
++ if (HalDev->OsFunc->Strcmpi(Key, "F5_LB_Counter") == 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Get") == 0)
++ {
++ ActionFound=1;
++ *(int *)Value = SAR_PDSP_OAM_F5_LB_COUNT_REG(HalDev->dev_base);
++ }
++ }
++
++ if (HalDev->OsFunc->Strstr(Key, "Stats;") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Get") == 0)
++ {
++ ActionFound=1;
++ TmpKey += HalDev->OsFunc->Strlen("Stats;");
++ Level = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++ TmpKey++;
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++ TmpKey++;
++ Queue = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++ TmpKey++;
++ StatsGet(HalDev, (void **)Value, Level, Ch, Queue);
++ }
++ }
++
++ /* +GSG 030306 */
++ /* Fixes PITS #100 */
++ if (HalDev->OsFunc->Strstr(Key, "Gfc.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("Gfc.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* first, store new value in our channel structure */
++ HalDev->ChData[Ch].Gfc = *(int *)Value;
++ }
++ }
++
++ /* +GSG 030306 */
++ /* Fixes PITS #100 */
++ if (HalDev->OsFunc->Strstr(Key, "Clp.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("Clp.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* first, store new value in our channel structure */
++ HalDev->ChData[Ch].Clp = *(int *)Value;
++ }
++ }
++
++ /* +GSG 030306 */
++ /* Fixes PITS #100 */
++ if (HalDev->OsFunc->Strstr(Key, "Pti.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("Pti.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* first, store new value in our channel structure */
++ HalDev->ChData[Ch].Pti = *(int *)Value;
++ }
++ }
++
++ /* +GSG 030306 */
++ /* Fixes PITS #100 */
++ if (HalDev->OsFunc->Strstr(Key, "CpcsUU.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("CpcsUU.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* first, store new value in our channel structure */
++ HalDev->ChData[Ch].CpcsUU = *(int *)Value;
++ }
++ }
++
++ /* +GSG 030306 */
++ /* Fixes PITS #100 */
++ if (HalDev->OsFunc->Strstr(Key, "TxVc_CellRate.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("TxVc_CellRate.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* first, store new value in our channel structure */
++ HalDev->ChData[Ch].TxVc_CellRate = *(int *)Value;
++
++ /* now, apply to PDSP state RAM */
++ if (HalDev->State == enOpened)
++ *(pPDSP_AAL5_TX_STATE_WORD_0(HalDev->dev_base)+(Ch*64))= HalDev->ChData[Ch].TxVc_CellRate;
++ }
++ }
++
++ /* +GSG 030306 */
++ /* Fixes PITS #100 */
++ if (HalDev->OsFunc->Strstr(Key, "TxVc_Mbs.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("TxVc_Mbs.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* first, store new value in our channel structure */
++ HalDev->ChData[Ch].TxVc_Mbs = *(int *)Value;
++
++ /* now, apply to PDSP state RAM */
++ if (HalDev->State == enOpened)
++ *(pPDSP_AAL5_TX_STATE_WORD_0(HalDev->dev_base)+(Ch*64)+2)= HalDev->ChData[Ch].TxVc_Mbs;
++ }
++ }
++
++ if (HalDev->OsFunc->Strstr(Key, "TxVc_AtmHeader.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("TxVc_AtmHeader.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* first, store new value in our channel structure */
++ HalDev->ChData[Ch].TxVc_AtmHeader = *(int *)Value;
++
++ /* now, apply to PDSP state RAM */
++ if (HalDev->State == enOpened)
++ *(pPDSP_AAL5_TX_STATE_WORD_0(HalDev->dev_base)+(Ch*64)+6)= HalDev->ChData[Ch].TxVc_AtmHeader;
++ }
++ }
++
++ if (HalDev->OsFunc->Strstr(Key, "TxVp_AtmHeader.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("TxVp_AtmHeader.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* first, store new value in our channel structure */
++ HalDev->ChData[Ch].TxVp_AtmHeader = *(int *)Value;
++
++ /* now, apply to PDSP state RAM */
++ if (HalDev->State == enOpened)
++ *(pPDSP_AAL5_TX_VP_STATE_WORD_0(HalDev->dev_base)+(Ch*64))= HalDev->ChData[Ch].TxVp_AtmHeader;
++ }
++ }
++
++ /* +GSG 030306 */
++ /* Fixes PITS #100 */
++ if (HalDev->OsFunc->Strstr(Key, "TxVc_Pcr.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("TxVc_Pcr.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* first, store new value in our channel structure */
++ HalDev->ChData[Ch].TxVc_Pcr = *(int *)Value;
++
++ /* now, apply to PDSP state RAM */
++ if (HalDev->State == enOpened)
++ *(pPDSP_AAL5_TX_STATE_WORD_0(HalDev->dev_base)+(Ch*64)+4)= HalDev->ChData[Ch].TxVc_Pcr;
++ }
++ }
++
++ /* +GSG 030428 */
++ if (HalDev->OsFunc->Strstr(Key, "RxVc_OamCh.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("RxVc_OamCh.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* first, store new value in our channel structure */
++ HalDev->ChData[Ch].RxVc_OamCh = (*(int *)Value) & 0xff;
++
++ /* now, apply to PDSP state RAM */
++ if (HalDev->State == enOpened)
++ *(pPDSP_AAL5_RX_STATE_WORD_0(HalDev->dev_base)+(Ch*64)) |= HalDev->ChData[Ch].RxVc_OamCh;
++ }
++ }
++
++ /* +GSG 030428 */
++ if (HalDev->OsFunc->Strstr(Key, "RxVp_OamCh.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("RxVp_OamCh.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* first, store new value in our channel structure */
++ HalDev->ChData[Ch].RxVp_OamCh = (*(int *)Value) & 0xff;
++
++ /* now, apply to PDSP state RAM */
++ if (HalDev->State == enOpened)
++ *(pPDSP_AAL5_RX_VP_STATE_WORD_0(HalDev->dev_base)+(Ch*64)+1) |= HalDev->ChData[Ch].RxVp_OamCh;
++ }
++ }
++
++ /* +GSG 030304 */
++ /* Fixes PITS #98 */
++ if (HalDev->OsFunc->Strstr(Key, "PdspEnable") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++
++ /* this variable is controlled by the CPSAR module */
++ if (HalDev->State == enOpened)
++ {
++ rc=HalDev->SarFunc->Control(HalDev->SarDev, "PdspEnable", "Set", Value);
++ }
++ }
++ }
++
++ if (HalDev->OsFunc->Strstr(Key, "OamLbTimeout") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++
++ HalDev->OamLbTimeout = *(int *)Value;
++ /* this variable is controlled by the CPSAR module */
++ if (HalDev->State == enOpened)
++ {
++ *(pOAM_TIMER_STATE_WORD_0(HalDev->dev_base) + 1) =
++ ((HalDev->SarFrequency/1000) * HalDev->OamLbTimeout);
++ }
++ }
++ }
++
++ /* +GSG 030306 (PITS #114) */
++ if (HalDev->OsFunc->Strstr(Key, "DeviceCPID") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ unsigned int* local = (unsigned int *)Value;
++ ActionFound=1;
++ /* first, store new value in our hal structure */
++ HalDev->DeviceCPID[0] = local[0];
++ HalDev->DeviceCPID[1] = local[1];
++ HalDev->DeviceCPID[2] = local[2];
++ HalDev->DeviceCPID[3] = local[3];
++
++ /* now, apply to PDSP state RAM */
++ if (HalDev->State == enOpened)
++ {
++ *(bit32u *)(pOAM_CONFIG_BLOCK_WORD_0(HalDev->dev_base) + 0) = HalDev->DeviceCPID[0];
++ *(bit32u *)(pOAM_CONFIG_BLOCK_WORD_0(HalDev->dev_base) + 1) = HalDev->DeviceCPID[1];
++ *(bit32u *)(pOAM_CONFIG_BLOCK_WORD_0(HalDev->dev_base) + 2) = HalDev->DeviceCPID[2];
++ *(bit32u *)(pOAM_CONFIG_BLOCK_WORD_0(HalDev->dev_base) + 3) = HalDev->DeviceCPID[3];
++ }
++ }
++ }
++
++ /* +GSG 030304 */
++ /* Fixes PITS #99 */
++ if (HalDev->OsFunc->Strstr(Key, "StrictPriority") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++
++ /* used in halOpen to decide which interrupt handler to use */
++ HalDev->StrictPriority = *(int *)Value;
++ }
++ }
++
++ if (HalDev->OsFunc->Strstr(Key, hcMaxFrags) != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++
++ if ((*(int *)Value) > 0)
++ HalDev->MaxFrags = *(int *)Value;
++ else
++ rc = (EC_AAL5|EC_FUNC_CONTROL|EC_VAL_INVALID_VALUE);
++ }
++
++ if (HalDev->OsFunc->Strcmpi(Action, "Get") == 0)
++ {
++ ActionFound=1;
++
++ *(int *)Value = HalDev->MaxFrags;
++ }
++ }
++
++ /* +GSG 030306 */
++ /* Fixes PITS #103 */
++ if (HalDev->OsFunc->Strstr(Key, "RxVc_RDICount.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Get") == 0)
++ {
++ ActionFound=1;
++
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("RxVc_RDICount.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* PDSP's Rx VC State word 3 contains the value */
++ if (HalDev->State == enOpened)
++ {
++ *(int *)Value = (((*(pPDSP_AAL5_RX_STATE_WORD_0(HalDev->dev_base)+(Ch*64))) & RDI_CNT_MASK)>>RDI_CNT_SHIFT);
++ }
++ }
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("RxVc_RDICount.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* All sets write 0, this action is a clear only */
++ if (HalDev->State == enOpened)
++ {
++ (*(pPDSP_AAL5_RX_STATE_WORD_0(HalDev->dev_base)+(Ch*64))) &=~ RDI_CNT_MASK;
++ }
++ }
++ }
++
++ /* +GSG 030306 */
++ /* Fixes PITS #103 */
++ if (HalDev->OsFunc->Strstr(Key, "RxVc_AISseg.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Get") == 0)
++ {
++ ActionFound=1;
++
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("RxVc_AISseg.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* PDSP's Rx VC State word 3 contains the value */
++ if (HalDev->State == enOpened)
++ {
++ *(int *)Value = (((*(pPDSP_AAL5_RX_STATE_WORD_0(HalDev->dev_base)+(Ch*64)+3)) & AIS_SEG_MASK)>>AIS_SEG_SHIFT);
++ }
++ }
++ }
++
++ /* +GSG 030306 */
++ /* Fixes PITS #103 */
++ if (HalDev->OsFunc->Strstr(Key, "RxVc_AISetoe.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Get") == 0)
++ {
++ ActionFound=1;
++
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("RxVc_AISetoe.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* PDSP's Rx VC State word 3 contains the value */
++ if (HalDev->State == enOpened)
++ {
++ *(int *)Value = (((*(pPDSP_AAL5_RX_STATE_WORD_0(HalDev->dev_base)+(Ch*64)+3)) & AIS_ETOE_MASK)>>AIS_ETOE_SHIFT);
++ }
++ }
++ }
++
++ /* +GSG 030306 */
++ /* Fixes PITS #103 */
++ if (HalDev->OsFunc->Strstr(Key, "RxVp_RDICount.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Get") == 0)
++ {
++ ActionFound=1;
++
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("RxVp_RDICount.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* PDSP's Rx VC State word 3 contains the value */
++ if (HalDev->State == enOpened)
++ {
++ *(int *)Value = (((*(pPDSP_AAL5_RX_VP_STATE_WORD_0(HalDev->dev_base)+(Ch*64)+1)) & RDI_CNT_MASK)>>RDI_CNT_SHIFT);
++ }
++ }
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("RxVp_RDICount.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* All sets write 0, this action is a clear only */
++ if (HalDev->State == enOpened)
++ {
++ (*(pPDSP_AAL5_RX_VP_STATE_WORD_0(HalDev->dev_base)+(Ch*64)+1)) &=~ RDI_CNT_MASK;
++ }
++ }
++ }
++
++ /* +GSG 030306 */
++ /* Fixes PITS #103 */
++ if (HalDev->OsFunc->Strstr(Key, "RxVp_AISseg.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Get") == 0)
++ {
++ ActionFound=1;
++
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("RxVp_AISseg.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* PDSP's Rx VC State word 3 contains the value */
++ if (HalDev->State == enOpened)
++ {
++ *(int *)Value = (((*(pPDSP_AAL5_RX_VP_STATE_WORD_0(HalDev->dev_base)+(Ch*64)+2)) & AIS_SEG_MASK)>>AIS_SEG_SHIFT);
++ }
++ }
++ }
++
++ /* +GSG 030306 */
++ /* Fixes PITS #103 */
++ if (HalDev->OsFunc->Strstr(Key, "RxVp_AISetoe.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Get") == 0)
++ {
++ ActionFound=1;
++
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("RxVp_AISetoe.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* PDSP's Rx VC State word 3 contains the value */
++ if (HalDev->State == enOpened)
++ {
++ *(int *)Value = (((*(pPDSP_AAL5_RX_VP_STATE_WORD_0(HalDev->dev_base)+(Ch*64)+2)) & AIS_ETOE_MASK)>>AIS_ETOE_SHIFT);
++ }
++ }
++ }
++
++ if (KeyFound == 0)
++ rc = (EC_AAL5|EC_FUNC_CONTROL|EC_VAL_KEY_NOT_FOUND);
++
++ if (ActionFound == 0)
++ rc = (EC_AAL5|EC_FUNC_CONTROL|EC_VAL_ACTION_NOT_FOUND);
++
++ return(rc);
++ }
++
++/*
++ * Sets up HAL default configuration parameter values.
++ */
++static void ConfigInit(HAL_DEVICE *HalDev)
++ {
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]ConfigInit(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* configure some defaults with tnetx7300 values */
++ HalDev->dev_base = 0xa3000000;
++ HalDev->offset = 0;
++ HalDev->interrupt = 15;
++ HalDev->debug = 0;
++ HalDev->MaxFrags = 46;
++ HalDev->OamLbTimeout = 5000;
++ }
++
++/*
++ * Retrieve HAL configuration parameter values.
++ */
++static bit32u ConfigGet(HAL_DEVICE *HalDev)
++ {
++ bit32u Ret;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]ConfigGet(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* get the configuration parameters common to all modules */
++ Ret = ConfigGetCommon(HalDev);
++ if (Ret) return (EC_AAL5|Ret);
++
++ /* get AAL5 specific configuration parameters here */
++ Ret = HalDev->OsFunc->Control(HalDev->OsDev, hcSarFrequency, pszGET, &HalDev->SarFrequency); /* GSG +030416*/
++ if (Ret) /* GSG +030416*/
++ HalDev->SarFrequency = 200000000; /* 200 Mhz default */ /* GSG +030416*/
++
++ return (EC_NO_ERRORS);
++ }
++
++/**
++ * @ingroup CPHAL_Functions
++ * This function initializes the CPHAL module. It gathers all
++ * necessary global configuration info from the configuration file, and
++ * performs initialization and configuration of the device. Note that
++ * the device operation is not started until the OS calls @c Open().
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ *
++ * @return EC_NO_ERRORS (ok). <BR>
++ * Possible Error Codes:<BR>
++ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ * @ref EC_VAL_BASE_ADDR_NOT_FOUND "EC_VAL_BASE_ADDR_NOT_FOUND"<BR>
++ * @ref EC_VAL_RESET_BIT_NOT_FOUND "EC_VAL_RESET_BIT_NOT_FOUND"<BR>
++ * @ref EC_VAL_INTERRUPT_NOT_FOUND "EC_VAL_INTERRUPT_NOT_FOUND"<BR>
++ * @ref EC_VAL_OFFSET_NOT_FOUND "EC_VAL_OFFSET_NOT_FOUND"<BR>
++ */
++static int halInit(HAL_DEVICE *HalDev)
++ {
++ int i;
++ bit32u error_code;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]halInit(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* Verify proper device state */
++ if (HalDev->State != enDevFound)
++ return(EC_AAL5|EC_FUNC_HAL_INIT|EC_VAL_INVALID_STATE);
++
++ /* Configure HAL defaults */
++ ConfigInit(HalDev);
++
++ /* Retrieve HAL configuration parameters from data store */
++ error_code = ConfigGet(HalDev);
++ if (error_code) return (error_code);
++
++ /* Other items (OAM related) that need to be passed in somehow */
++ HalDev->DeviceCPID[0] = 0xffffffff;
++ HalDev->DeviceCPID[1] = 0xffffffff;
++ HalDev->DeviceCPID[2] = 0xffffffff;
++ HalDev->DeviceCPID[3] = 0xffffffff;
++ HalDev->LBSourceLLID[0] = 0xffffffff;
++ HalDev->LBSourceLLID[1] = 0xffffffff;
++ HalDev->LBSourceLLID[2] = 0xffffffff;
++ HalDev->LBSourceLLID[3] = 0xffffffff;
++
++ /* Initialize SAR layer*/
++ error_code = HalDev->SarFunc->Init(HalDev->SarDev);
++ if (error_code) return (error_code);
++
++ /* Initialize various HalDev members. This is probably overkill, since these
++ are initialized in ChannelSetup() and HalDev is cleared in InitModule(). */
++ for (i=0; i<NUM_AAL5_CHAN; i++)
++ {
++ HalDev->InRxInt[i]=FALSE;
++ HalDev->ChIsOpen[i][DIRECTION_TX] = FALSE;
++ HalDev->ChIsOpen[i][DIRECTION_RX] = FALSE;
++ HalDev->TcbStart[i][0] = 0;
++ HalDev->TcbStart[i][1] = 0;
++ HalDev->RcbStart[i] = 0;
++ }
++
++ /* initialize SAR stats */
++ StatsClear(HalDev);
++
++ /* init Stat pointers */
++
++ /* even though these statistics may be for multiple channels/queues, i need
++ only configure the pointer to the beginning of the array, and I can index
++ from there if necessary */
++ StatsTable0[0].StatPtr = &HalDev->Stats.CrcErrors[0];
++ StatsTable0[1].StatPtr = &HalDev->Stats.LenErrors[0];
++ StatsTable0[2].StatPtr = &HalDev->Stats.AbortErrors[0];
++ StatsTable0[3].StatPtr = &HalDev->Stats.StarvErrors[0];
++
++ StatsTable1[0].StatPtr = &HalDev->Stats.DmaLenErrors[0];
++ StatsTable1[1].StatPtr = &HalDev->Stats.TxMisQCnt[0][0];
++ StatsTable1[2].StatPtr = &HalDev->Stats.RxMisQCnt[0];
++ StatsTable1[3].StatPtr = &HalDev->Stats.TxEOQCnt[0][0];
++ StatsTable1[4].StatPtr = &HalDev->Stats.RxEOQCnt[0];
++ StatsTable1[5].StatPtr = &HalDev->Stats.RxPacketsServiced[0];
++ StatsTable1[6].StatPtr = &HalDev->Stats.TxPacketsServiced[0][0];
++ StatsTable1[7].StatPtr = &HalDev->Stats.RxMaxServiced;
++ StatsTable1[8].StatPtr = &HalDev->Stats.TxMaxServiced[0][0];
++ StatsTable1[9].StatPtr = &HalDev->Stats.RxTotal;
++ StatsTable1[10].StatPtr = &HalDev->Stats.TxTotal;
++
++ StatsTable2[0].StatPtr = (bit32u *)&HalDev->RcbPool[0];
++ StatsTable2[1].StatPtr = &HalDev->RxActQueueCount[0];
++ StatsTable2[2].StatPtr = (bit32u *)&HalDev->RxActQueueHead[0];
++ StatsTable2[3].StatPtr = (bit32u *)&HalDev->RxActQueueTail[0];
++ StatsTable2[4].StatPtr = &HalDev->RxActive[0];
++ StatsTable2[5].StatPtr = (bit32u *)&HalDev->RcbStart[0];
++ StatsTable2[6].StatPtr = &HalDev->RxTeardownPending[0];
++ StatsTable2[7].StatPtr = (bit32u *)&HalDev->TcbPool[0][0];
++ StatsTable2[8].StatPtr = &HalDev->TxActQueueCount[0][0];
++ StatsTable2[9].StatPtr = (bit32u *)&HalDev->TxActQueueHead[0][0];
++ StatsTable2[10].StatPtr = (bit32u *)&HalDev->TxActQueueTail[0][0];
++ StatsTable2[11].StatPtr = &HalDev->TxActive[0][0];
++ StatsTable2[12].StatPtr = (bit32u *)&HalDev->TcbStart[0][0];
++ StatsTable2[13].StatPtr = &HalDev->TxTeardownPending[0];
++
++ StatsTable4[0].StatPtr = &HalDev->dev_base;
++ StatsTable4[1].StatPtr = &HalDev->offset;
++ StatsTable4[2].StatPtr = &HalDev->interrupt;
++ StatsTable4[3].StatPtr = &HalDev->debug;
++ StatsTable4[4].StatPtr = &HalDev->Inst;
++
++ StatsTable3[0].StatPtr = &HalDev->ChData[0].RxBufSize;
++ StatsTable3[1].StatPtr = &HalDev->ChData[0].RxBufferOffset;
++ StatsTable3[2].StatPtr = &HalDev->ChData[0].RxNumBuffers;
++ StatsTable3[3].StatPtr = &HalDev->ChData[0].RxServiceMax;
++ StatsTable3[4].StatPtr = &HalDev->ChData[0].TxNumBuffers;
++ StatsTable3[5].StatPtr = &HalDev->ChData[0].TxNumQueues;
++ StatsTable3[6].StatPtr = &HalDev->ChData[0].TxServiceMax;
++ StatsTable3[7].StatPtr = &HalDev->ChData[0].CpcsUU;
++ StatsTable3[8].StatPtr = &HalDev->ChData[0].Gfc;
++ StatsTable3[9].StatPtr = &HalDev->ChData[0].Clp;
++ StatsTable3[10].StatPtr = &HalDev->ChData[0].Pti;
++ StatsTable3[11].StatPtr = &HalDev->ChData[0].DaMask;
++ StatsTable3[12].StatPtr = &HalDev->ChData[0].Priority;
++ StatsTable3[13].StatPtr = &HalDev->ChData[0].PktType;
++ StatsTable3[14].StatPtr = &HalDev->ChData[0].Vci;
++ StatsTable3[15].StatPtr = &HalDev->ChData[0].Vpi;
++ StatsTable3[16].StatPtr = &HalDev->ChData[0].TxVc_CellRate;
++ StatsTable3[17].StatPtr = &HalDev->ChData[0].TxVc_QosType;
++ StatsTable3[18].StatPtr = &HalDev->ChData[0].TxVc_Mbs;
++ StatsTable3[19].StatPtr = &HalDev->ChData[0].TxVc_Pcr;
++
++ /* update device state */
++ HalDev->State = enInitialized;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(9))
++ dbgConfigDump(HalDev);
++#endif
++
++ return(EC_NO_ERRORS);
++ }
++
++/*
++ * Use this function to actually send after queuing multiple packets using
++ * Send(). This is a debug only function that should be removed - it was
++ * necessary to properly implement my loopback tests.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ * @param Queue Queue number to kick.
++ *
++ * @return 0 OK, Non-Zero Not OK
++ */
++static int halKick(HAL_DEVICE *HalDev, int Queue)
++ {
++ int Ch;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]halKick(HalDev:%08x. Queue:%d)\n", (bit32u)HalDev, Queue);
++ osfuncSioFlush();
++ }
++#endif
++
++ for (Ch = 0; Ch < 16; Ch ++)
++ {
++ if ((!HalDev->TxActive[Ch][Queue]) && (HalDev->TxActQueueHead[Ch][Queue] != 0))
++ {
++ *(pTX_DMA_STATE_WORD_0(HalDev->dev_base)+(Ch*64)+Queue)=
++ VirtToPhys(HalDev->TxActQueueHead[Ch][Queue]);
++ HalDev->TxActive[Ch][Queue]=TRUE;
++ }
++ }
++
++ return (EC_NO_ERRORS);
++ }
++
++/* +GSG 030305 For PITS #99
++ * Alternate interrupt handler that uses the INT_VECTOR in order to
++ * provide strict priority handling among channels, beginning with Ch 0.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ * @param MoreWork (Output) When set to 1, indicates that there is more work to do.
++ * Caller should ensure that the value pointed at is set to 0
++ * prior to the call.
++ * @return 0 OK, non-zero error.
++ */
++static int DeviceIntAlt(HAL_DEVICE *HalDev, int *MoreWork)
++ {
++ int tmp, Ch, WorkFlag;
++ bit32u rc;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]DeviceIntAlt(HalDev:%08x, MoreWork:%08x)\n", (bit32u)HalDev, (bit32u)MoreWork);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* Verify proper device state - important because a call prior to Open would
++ result in a lockup */
++ if (HalDev->State != enOpened)
++ return(EC_AAL5|EC_FUNC_DEVICE_INT_ALT|EC_VAL_INVALID_STATE);
++
++ if ((tmp=SAR_INTR_VECTOR(HalDev->dev_base))&INT_PENDING)
++ {
++ /*printf("\015 %d RxQ",HalDev->RxActQueueCount[0]);
++ HalDev->OsFunc->Control(HalDev->OsDev, enSIO_FLUSH, enNULL, 0); */
++
++ if (tmp&TXH_PEND)
++ {
++ /* decide which channel to service */
++ Ch = (SAR_INTR_VECTOR(HalDev->dev_base) & TXH_PEND_INVEC);
++
++ rc = TxInt(HalDev,Ch,0,&WorkFlag);
++ if (rc) return (rc);
++
++ if (WorkFlag == 1)
++ *MoreWork = 1;
++ }
++
++ if (tmp&TXL_PEND)
++ {
++ /* decide which channel to service */
++ Ch = ((SAR_INTR_VECTOR(HalDev->dev_base) & TXL_PEND_INVEC) >> 4);
++
++ rc = TxInt(HalDev,Ch,1,&WorkFlag);
++ if (rc) return (rc);
++
++ if (WorkFlag == 1)
++ *MoreWork = 1;
++ }
++
++ if (tmp&RX_PEND)
++ {
++ /* decide which channel to service */
++ Ch = ((SAR_INTR_VECTOR(HalDev->dev_base) & RX_PEND_INVEC) >> 8);
++
++ rc = RxInt(HalDev,Ch,&WorkFlag);
++ if (rc) return (rc);
++
++ if (WorkFlag == 1)
++ *MoreWork = 1;
++ }
++
++ if (tmp&STS_PEND)
++ {
++ /* GPR 2 code added for PITS 103 */
++ /* determine interrupt source */
++ Ch = ((SAR_INTR_VECTOR(HalDev->dev_base) & STS_PEND_INVEC) >> 12);
++
++ /* only if this is GPR 2 interrupt do we take action */
++ if (Ch == 26)
++ {
++ /* pass loopback result back to OS */
++ HalDev->OsFunc->Control(HalDev->OsDev, "OamLbResult", "Set",
++ (bit32u *)pSAR_PDSP_OAM_LB_RESULT_REG(HalDev->dev_base));
++ }
++
++ /* clear the interrupt */
++ SAR_STATUS_CLR_REG(HalDev->dev_base) |= 0x04000000;
++ }
++
++ if (tmp&AAL2_PEND)
++ {
++ /* no action defined */
++ }
++
++ SAR_INTR_VECTOR(HalDev->dev_base) = 0;
++ }
++
++ return (EC_NO_ERRORS);
++ }
++
++/*
++ * Called to service a module interrupt. This function determines
++ * what type of interrupt occurred and dispatches the correct handler.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ * @param MoreWork (Output) When set to 1, indicates that there is more work to do.
++ * Caller should ensure that the value pointed at is set to 0
++ * prior to the call.
++ * @return 0 OK, non-zero error.
++ */
++static int DeviceInt(HAL_DEVICE *HalDev, int *MoreWork)
++ {
++ /*static int NextRxCh=0;
++ static int NextTxCh[2]={0,0};*/
++
++ int tmp, Ch, FirstCh, WorkFlag;
++ int NextTxLCh, NextTxHCh, NextRxCh;
++ bit32u rc;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]DeviceInt(HalDev:%08x, MoreWork:%08x)\n", (bit32u)HalDev, (bit32u)MoreWork);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* Verify proper device state - important because a call prior to Open would
++ result in a lockup */
++ if (HalDev->State != enOpened)
++ return(EC_AAL5|EC_FUNC_DEVICE_INT|EC_VAL_INVALID_STATE);
++
++ NextTxHCh = HalDev->NextTxCh[0];
++ NextTxLCh = HalDev->NextTxCh[1];
++ NextRxCh = HalDev->NextRxCh;
++
++ /* service interrupts while there is more work to do */
++ /*while (((tmp=SAR_INTR_VECTOR(HalDev->dev_base))&INT_PENDING) && (TotalPkts < 500))*/
++ if ((tmp=SAR_INTR_VECTOR(HalDev->dev_base))&INT_PENDING)
++ {
++ /*printf("\015 %d RxQ",HalDev->RxActQueueCount[0]);
++ HalDev->OsFunc->Control(HalDev->OsDev, enSIO_FLUSH, enNULL, 0); */
++
++ if (tmp&TXH_PEND)
++ {
++ /* decide which channel to service */
++ FirstCh = NextTxHCh;
++ while (1)
++ {
++ Ch = NextTxHCh++;
++ if (NextTxHCh == 16)
++ NextTxHCh = 0;
++ if (SAR_TX_MASKED_STATUS(HalDev->dev_base) & (1<<Ch))
++ break;
++ if (FirstCh == NextTxHCh)
++ {
++ /* we checked every channel and still haven't found anything to do */
++ return (EC_AAL5|EC_FUNC_DEVICE_INT|EC_VAL_NO_TXH_WORK_TO_DO);
++ }
++ }
++
++ rc = TxInt(HalDev,Ch,0,&WorkFlag);
++ if (rc) return (rc);
++
++ if (WorkFlag == 1)
++ *MoreWork = 1;
++ }
++
++ if (tmp&TXL_PEND)
++ {
++ /* decide which channel to service */
++ FirstCh = NextTxLCh;
++ while (1)
++ {
++ Ch = NextTxLCh++;
++ if (NextTxLCh == 16)
++ NextTxLCh = 0;
++ if (SAR_TX_MASKED_STATUS(HalDev->dev_base) & (1<<(Ch+16)))
++ break;
++ if (FirstCh == NextTxLCh)
++ {
++ /* we checked every channel and still haven't found anything to do */
++ return (EC_AAL5|EC_FUNC_DEVICE_INT|EC_VAL_NO_TXL_WORK_TO_DO);
++ }
++ }
++
++ rc = TxInt(HalDev,Ch,1,&WorkFlag);
++ if (rc) return (rc);
++
++ if (WorkFlag == 1)
++ *MoreWork = 1;
++ }
++
++ if (tmp&RX_PEND)
++ {
++ FirstCh = NextRxCh;
++ while (1)
++ {
++ Ch = NextRxCh++;
++ if (NextRxCh == 16)
++ NextRxCh = 0;
++ if (SAR_RX_MASKED_STATUS(HalDev->dev_base) & (1 << Ch))
++ break; /* found a channel to service */
++ if (FirstCh == NextRxCh)
++ {
++ /* we checked every channel and still haven't found anything to do */
++ return (EC_AAL5|EC_FUNC_DEVICE_INT|EC_VAL_NO_RX_WORK_TO_DO);
++ }
++ }
++
++ rc = RxInt(HalDev,Ch, &WorkFlag);
++ if (rc) return (rc);
++
++ if (WorkFlag == 1)
++ *MoreWork = 1;
++ }
++
++ if (tmp&STS_PEND)
++ {
++ /* +GSG 030305 */
++ /* GPR 2 code added for PITS 103 */
++ /* determine interrupt source */
++ Ch = ((SAR_INTR_VECTOR(HalDev->dev_base) & STS_PEND_INVEC) >> 12);
++
++ /* only if this is GPR 2 interrupt do we take action */
++ if (Ch == 26)
++ {
++ /* pass loopback result back to OS */
++ HalDev->OsFunc->Control(HalDev->OsDev, "OamLbResult", "Set",
++ (bit32u *)pSAR_PDSP_OAM_LB_RESULT_REG(HalDev->dev_base));
++ }
++
++ /* clear the interrupt */
++ SAR_STATUS_CLR_REG(HalDev->dev_base) |= 0x04000000;
++ }
++
++ if (tmp&AAL2_PEND)
++ {
++ /* no action defined */
++ }
++
++ SAR_INTR_VECTOR(HalDev->dev_base) = 0;
++ }
++
++ HalDev->NextTxCh[0] = NextTxHCh;
++ HalDev->NextTxCh[1] = NextTxLCh;
++ HalDev->NextRxCh = NextRxCh;
++
++ /* This must be done by the upper layer */
++ /* SAR_EOI(HalDev->dev_base) = 0; */
++
++ return (EC_NO_ERRORS);
++ }
++
++/**
++ * @ingroup CPHAL_Functions
++ * This function starts the operation of the CPHAL device. It takes the device
++ * out of reset, and calls @c IsrRegister(). This function should be called after
++ * calling the @c Init() function.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ *
++ * @return EC_NO_ERRORS (ok).<BR>
++ * Possible Error Codes:<BR>
++ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ * @ref EC_VAL_KEY_NOT_FOUND "EC_VAL_KEY_NOT_FOUND"<BR>
++ * @ref EC_VAL_FIRMWARE_TOO_LARGE "EC_VAL_FIRMWARE_TOO_LARGE"<BR>
++ * @ref EC_VAL_PDSP_LOAD_FAIL "EC_VAL_PDSP_LOAD_FAIL"<BR>
++ * @ref EC_VAL_RX_STATE_RAM_NOT_CLEARED "EC_VAL_RX_STATE_RAM_NOT_CLEARED"<BR>
++ * @ref EC_VAL_TX_STATE_RAM_NOT_CLEARED "EC_VAL_TX_STATE_RAM_NOT_CLEARED"<BR>
++ * @ref EC_VAL_TCB_MALLOC_FAILED "EC_VAL_TCB_MALLOC_FAILED"<BR>
++ * @ref EC_VAL_RCB_MALLOC_FAILED "EC_VAL_RCB_MALLOC_FAILED"<BR>
++ * @ref EC_VAL_RX_BUFFER_MALLOC_FAILED "EC_VAL_RX_BUFFER_MALLOC_FAILED"<BR>
++ * @ref EC_VAL_LUT_NOT_READY "EC_VAL_LUT_NOT_READY"<BR>
++ */
++static int halOpen(HAL_DEVICE *HalDev)
++ {
++ int i,Ret;
++ bit32 SarBase = HalDev->dev_base;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]halOpen(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* Verify proper device state */
++ if (HalDev->State < enInitialized)
++ return (EC_AAL5|EC_FUNC_OPEN|EC_VAL_INVALID_STATE);
++
++ /* Open the SAR (this brings the whole device out of reset */
++ Ret = HalDev->SarFunc->Open(HalDev->SarDev); /* ~GSG 030410 */
++ if (Ret) /* +GSG 030410 */
++ return (Ret); /* +GSG 030410 */
++
++ /* Change device state */
++ HalDev->State = enOpened;
++
++
++#ifdef __CPHAL_DEBUG
++ /* print out the version information */
++ if (DBG(7))
++ {
++ dbgPrintf("[aal5 halOpen()]Module ID(AAL5-CPSAR):%d, Version:%2d.%02d\n",
++ (SAR_ID_REG(SarBase)&0xffff0000)>>16,
++ (SAR_ID_REG(SarBase)&0xff00)>>8,
++ SAR_ID_REG(SarBase)&0xff);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* GREG 11/1/02: The State RAM clearing code was previously in cpsar.c,
++ directly after device reset. I moved it here because I believe it is
++ AAL5 specific code. Also the MAX_CHAN was set to 19 in cpsar.c, which
++ would have caused this code to clear too much memory! */
++
++ /* NOTE: State RAM must be cleared prior to initializing the PDSP!! */
++
++ /* GSG 030416: Removed all of this. All PDSP State RAM is cleared
++ in CPSAR Open(). On Close(), all channels are torndown, thus all
++ AAL5 channel state RAM is cleared. */
++
++ /* Clear Rx State RAM */
++ /*for (i=0; i<NUM_AAL5_CHAN; i++)
++ for (j=0; j<NUM_RX_STATE_WORDS; j++)
++ *(pRX_DMA_STATE_WORD_0(SarBase) + (i*64) + j) = 0; */
++
++ /* Check that Rx DMA State RAM was cleared */
++ /*for (i=0; i<NUM_AAL5_CHAN; i++)
++ for (j=0; j<NUM_RX_STATE_WORDS; j++)
++ {
++ if (*(pRX_DMA_STATE_WORD_0(SarBase) + (i*64) + j) != 0)
++ {
++ return(EC_AAL5|EC_FUNC_HAL_INIT|EC_VAL_RX_STATE_RAM_NOT_CLEARED);
++ }
++ }*/
++
++ /* Clear Tx State RAM */
++ /*for (i=0; i<NUM_AAL5_CHAN; i++)
++ for (j=0; j<NUM_TX_STATE_WORDS; j++)
++ {
++ *(pTX_DMA_STATE_WORD_0(SarBase) + (i*64) + j) = 0;
++ }*/
++
++ /* Check that Tx DMA State RAM was cleared */
++ /*for (i=0; i<NUM_AAL5_CHAN; i++)
++ for (j=0; j<NUM_TX_STATE_WORDS; j++)
++ {
++ if (*(pTX_DMA_STATE_WORD_0(SarBase) + (i*64) + j) != 0)
++ {
++ return(EC_AAL5|EC_FUNC_HAL_INIT|EC_VAL_TX_STATE_RAM_NOT_CLEARED);
++ }
++ }*/
++
++ /* GSG +030523 Malloc space for the Rx fraglist */
++ HalDev->fraglist = HalDev->OsFunc->Malloc(HalDev->MaxFrags * sizeof(FRAGLIST));
++
++ /* For any channels that have been pre-initialized, set them up now */
++ for (i=0; i<NUM_AAL5_CHAN; i++)
++ {
++ if ((HalDev->ChIsSetup[i][0]==TRUE) && (HalDev->ChIsOpen[i][0]==FALSE))
++ {
++ CHANNEL_INFO HalChn;
++ HalChn.Channel = i;
++ Ret = ChannelConfigApply(HalDev, &HalChn);
++ if (Ret) return (Ret);
++ }
++ }
++
++ /* OAM code would be a candidate to go into ConfigApply */
++
++ /* Configure OAM Timer State Block */
++ OamRateConfig(HalDev); /* +GSG 030416 */
++
++ /* Setup OAM Configuration Block */
++ for (i=0; i<8; i++) /* ~GSG 030603 4->8 */
++ {
++ if (i < 4)
++ *(pOAM_CONFIG_BLOCK_WORD_0(SarBase) + i) = HalDev->DeviceCPID[i];
++ else
++ *(pOAM_CONFIG_BLOCK_WORD_0(SarBase) + i) = HalDev->LBSourceLLID[i-4];
++ }
++
++ /* Setup OAM Padding Block */
++ for (i=0; i<12; i++)
++ {
++ *(pOAM_PADDING_BLOCK_WORD_0(SarBase) + i) = ((i==11)?0x6a6a0000:0x6a6a6a6a);
++ }
++
++ /* Enable Tx CPPI DMA */
++ TX_CPPI_CTL_REG(HalDev->dev_base) = 1;
++
++ /* Enable Rx CPPI DMA */
++ RX_CPPI_CTL_REG(HalDev->dev_base) = 1;
++
++ /* +GSG 030306 */
++ /* Fix for PITS 103 */
++ /* Enable Host Interrupt for GPR 2 (OAM LB result register) */
++ SAR_HOST_INT_EN_SET_REG(HalDev->dev_base) |= 0x04000000;
++
++ /* +GSG 030304 to fix PITS 99 (if block is new)*/
++ if (HalDev->StrictPriority == 1)
++ {
++#ifdef __CPHAL_DEBUG
++ if (DBG(1))
++ {
++ dbgPrintf("[aal5->os]IsrRegister(OsDev:%08x, halIsr:%08x, Interrupt:%d)\n",
++ (bit32u)HalDev->OsDev, (bit32u)DeviceIntAlt, HalDev->interrupt);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* "register" the interrupt handler */
++ HalDev->OsFunc->IsrRegister(HalDev->OsDev, DeviceIntAlt, HalDev->interrupt);
++ }
++ else /* +GSG 030306 */
++ { /* +GSG 030306 */
++#ifdef __CPHAL_DEBUG
++ if (DBG(1))
++ {
++ dbgPrintf("[aal5->os]IsrRegister(OsDev:%08x, halIsr:%08x, Interrupt:%d)\n",
++ (bit32u)HalDev->OsDev, (bit32u)DeviceInt, HalDev->interrupt);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* "register" the interrupt handler */
++ HalDev->OsFunc->IsrRegister(HalDev->OsDev, DeviceInt, HalDev->interrupt);
++ } /* +GSG 030306 */
++
++ return(EC_NO_ERRORS);
++ }
++
++/**
++ * @ingroup CPHAL_Functions
++ * Called to retrigger the interrupt mechanism after packets have been
++ * processed. Call this function when the HalISR function indicates that
++ * there is no more work to do. Proper use of this function will guarantee
++ * that interrupts are never missed.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ *
++ * @return EC_NO_ERRORS (ok). <BR>
++ */
++static int halPacketProcessEnd(HAL_DEVICE *HalDev)
++ {
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]halPacketProcessEnd(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++ SAR_EOI(HalDev->dev_base) = 0;
++ return (EC_NO_ERRORS);
++ }
++
++/**
++ * @ingroup CPHAL_Functions
++ * This function probes for the instance of the CPHAL module. It will call
++ * the OS function @c DeviceFindInfo() to get the information required.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ *
++ * @return EC_NO_ERRORS (ok). <BR>
++ * Possible Error Codes:<BR>
++ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ * @ref EC_VAL_DEVICE_NOT_FOUND "EC_VAL_DEVICE_NOT_FOUND"<BR>
++ */
++static int halProbe(HAL_DEVICE *HalDev)
++ {
++ int Ret;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]halProbe(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* Verify hardware state is "enConnected */
++ if (HalDev->State != enConnected)
++ return (EC_AAL5|EC_FUNC_PROBE|EC_VAL_INVALID_STATE);
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(1))
++ {
++ dbgPrintf("[aal5->os]DeviceFindInfo(Inst:%d, DeviceName:%s, DeviceInfo:%08x)\n",
++ HalDev->Inst, "aal5", (bit32u)&HalDev->DeviceInfo);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* Attempt to find the device information */
++ Ret = HalDev->OsFunc->DeviceFindInfo(HalDev->Inst, "aal5", &HalDev->DeviceInfo);
++ if (Ret)
++ return(EC_AAL5|EC_FUNC_PROBE|EC_VAL_DEVICE_NOT_FOUND);
++
++ /* Call Probe for supporting CPSAR layer */
++ Ret = HalDev->SarFunc->Probe(HalDev->SarDev);
++ if (Ret)
++ return(Ret);
++
++ /* Set device state to DevFound */
++ HalDev->State = enDevFound;
++
++ return(EC_NO_ERRORS);
++ }
++
++/**
++ * @ingroup CPHAL_Functions
++ * This function shuts down the CPHAL module completely. The caller must call
++ * Close() to put the device in reset prior shutting down. This call will free
++ * the HalDev and the HAL function pointer structure, effectively ending
++ * communications between the driver and the CPHAL. Further use of the module
++ * must be initiated by a call to xxxInitModule(), which starts the entire process
++ * over again.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ *
++ * @return EC_NO_ERRORS (ok). <BR>
++ * Possible Error Codes:<BR>
++ * Any error code from halClose().<BR>
++ */
++static int halShutdown(HAL_DEVICE *HalDev)
++ {
++ int Ch, Queue; /*GSG+030514*/
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]halShutdown(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* Verify proper device state */
++ if (HalDev->State == enOpened)
++ halClose(HalDev, 3); /*GSG+030429*/
++
++ /* Buffer/descriptor resources may still need to be freed if a Close
++ Mode 1 was performed prior to Shutdown - clean up here */ /*GSG+030514*/
++ for (Ch=0; Ch<NUM_AAL5_CHAN; Ch++)
++ {
++ if (HalDev->RcbStart[Ch] != 0)
++ FreeRx(HalDev,Ch);
++
++ for(Queue=0; Queue<MAX_QUEUE; Queue++)
++ {
++ if (HalDev->TcbStart[Ch][Queue] != 0)
++ FreeTx(HalDev,Ch,Queue);
++ }
++ }
++
++ /* shutdown the CPSAR layer */
++ HalDev->SarFunc->Shutdown(HalDev->SarDev);
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(6))
++ {
++ dbgPrintf(" [aal5 halShutdown()]Free AAL5 function pointers\n");
++ osfuncSioFlush();
++ }
++ if (DBG(1)||DBG(3))
++ {
++ dbgPrintf("[aal5->os]Free(MemPtr:%08x)\n", (bit32u)HalDev->HalFuncPtr);
++ osfuncSioFlush();
++ }
++#endif
++ /* free the HalFunc */
++ HalDev->OsFunc->Free(HalDev->HalFuncPtr);
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(6))
++ {
++ dbgPrintf(" [aal5 halShutdown]Free HalDev\n");
++ osfuncSioFlush();
++ }
++ if (DBG(1)||DBG(3))
++ {
++ dbgPrintf("[aal5->os]Free(MemPtr:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++ /* free the HAL device */
++ HalDev->OsFunc->FreeDev(HalDev);
++
++ return(EC_NO_ERRORS);
++ }
++
++/**
++ * @ingroup CPHAL_Functions
++ * Used to perform regular checks on the device. This function should be
++ * called at a regular interval specified by the @c Tick parameter.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ *
++ * @return EC_NO_ERRORS (ok).<BR>
++ * Possible Error Codes:<BR>
++ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ */
++static int halTick(HAL_DEVICE *HalDev)
++ {
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[aal5]halTick(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++ if (HalDev->State != enOpened)
++ return(EC_AAL5|EC_FUNC_TICK|EC_VAL_INVALID_STATE);
++
++ return(EC_NO_ERRORS);
++ }
++
++/**
++ * @ingroup CPHAL_Functions
++ *
++ * This function will:
++ * -# allocate a HalDev that will be used by the OS for future communications with the device
++ * -# save OsDev for use when calling OS functions
++ * -# allocate and populate HalFunc with the addresses of CPHAL functions.
++ * -# check OsFuncSize to see if it meets the minimum requirement.
++ * -# return the size of the HAL_FUNCTIONS structure through the HalFuncSize pointer. The OS
++ * should check this value to ensure that the HAL meets its minimum requirement.
++ *
++ * Version checking between the OS and the CPHAL is done using the OsFuncSize and
++ * HalFuncSize. Future versions of the CPHAL may add new functions to either
++ * HAL_FUNCTIONS or OS_FUNCTIONS, but will never remove functionality. This enables
++ * both the HAL and OS to check the size of the function structure to ensure that
++ * the current OS and CPHAL are compatible.
++ *
++ * Note: This is the only function exported by a CPHAL module.
++ *
++ * Please refer to the section "@ref hal_init" for example code.
++ *
++ * @param HalDev Pointer to pointer to CPHAL module information. This will
++ * be used by the OS when communicating to this module via
++ * CPHAL. Allocated during the call.
++ * @param OsDev Pointer to OS device information. This will be saved by
++ * the CPHAL and returned to the OS when required.
++ * @param HalFunc Pointer to pointer to structure containing function pointers for all CPHAL
++ * interfaces. Allocated during the call.
++ * @param OsFunc Pointer to structure containing function pointers for all OS
++ * provided interfaces. Must be allocated by OS prior to call.
++ * @param OsFuncSize Size of OS_FUNCTIONS structure.
++ * @param HalFuncSize Pointer to the size of the HAL_FUNCTIONS structure.
++ * @param Inst The instance number of the module to initialize. (start at
++ * 0).
++ *
++ * @return EC_NO_ERRORS (ok). <BR>
++ * Possible Error Codes:<BR>
++ * @ref EC_VAL_OS_VERSION_NOT_SUPPORTED "EC_VAL_OS_VERSION_NOT_SUPPORTED"<BR>
++ * @ref EC_VAL_MALLOC_DEV_FAILED "EC_VAL_MALLOC_DEV_FAILED"<BR>
++ * @ref EC_VAL_MALLOC_FAILED "EC_VAL_MALLOC_FAILED"<BR>
++ */
++int xxxInitModule(HAL_DEVICE **HalDev,
++ OS_DEVICE *OsDev,
++ HAL_FUNCTIONS **HalFunc,
++ OS_FUNCTIONS *OsFunc,
++ int OsFuncSize,
++ int *HalFuncSize,
++ int Inst);
++
++int cpaal5InitModule(HAL_DEVICE **HalDev,
++ OS_DEVICE *OsDev,
++ HAL_FUNCTIONS **HalFunc,
++ OS_FUNCTIONS *OsFunc,
++ int OsFuncSize,
++ int *HalFuncSize,
++ int Inst)
++ {
++ int rc, SarFuncSize;
++ HAL_DEVICE *HalPtr;
++ HAL_FUNCTIONS *HalFuncPtr;
++
++ /* NEW CODE */
++ if (OsFuncSize < sizeof(OS_FUNCTIONS))
++ return (EC_AAL5|EC_FUNC_HAL_INIT|EC_VAL_OS_VERSION_NOT_SUPPORTED);
++
++ HalPtr = (HAL_DEVICE *) OsFunc->MallocDev(sizeof(HAL_DEVICE));
++ if (!HalPtr)
++ return (EC_AAL5|EC_FUNC_HAL_INIT|EC_VAL_MALLOC_DEV_FAILED);
++
++ HalFuncPtr = (HAL_FUNCTIONS *) OsFunc->Malloc(sizeof(HAL_FUNCTIONS));
++ if (!HalFuncPtr)
++ return (EC_AAL5|EC_FUNC_HAL_INIT|EC_VAL_MALLOC_FAILED);
++
++ /* Initialize the size of hal functions */
++ *HalFuncSize = sizeof (HAL_FUNCTIONS);
++
++ /* clear the device structure */
++ OsFunc->Memset(HalPtr, 0, sizeof(HAL_DEVICE));
++
++ /* clear the function pointers */
++ OsFunc->Memset(HalFuncPtr, 0, sizeof(HAL_FUNCTIONS));
++
++ /* initialize the HAL_DEVICE structure */
++ HalPtr->OsDev = OsDev;
++ /*HalPtr->OsOpen = OsDev;*/
++ HalPtr->Inst = Inst;
++ HalPtr->OsFunc = OsFunc;
++
++ /* Supply pointers for the CPHAL API functions */
++ HalFuncPtr->RxReturn = halRxReturn;
++ HalFuncPtr->Init = halInit;
++ HalFuncPtr->Close = halClose;
++ HalFuncPtr->Send = halSend;
++ HalFuncPtr->ChannelSetup = halChannelSetup;
++ HalFuncPtr->ChannelTeardown = halChannelTeardown;
++ HalFuncPtr->Open = halOpen;
++ HalFuncPtr->Kick = halKick;
++ HalFuncPtr->RegAccess = halRegAccess;
++ HalFuncPtr->Probe = halProbe;
++ HalFuncPtr->Control = halControl;
++ HalFuncPtr->Tick = halTick;
++ HalFuncPtr->Shutdown = halShutdown;
++ HalFuncPtr->OamFuncConfig = halOamFuncConfig; /* +GSG 030306 */
++ HalFuncPtr->OamLoopbackConfig = halOamLoopbackConfig; /* ~GSG 030416 */
++
++ /* Temporary */
++ /*HalFuncPtr->StatsGetOld = StatsGet;*/
++ HalFuncPtr->PacketProcessEnd = halPacketProcessEnd;
++
++ /* Now, AAL5 must connect to the CPSAR layer */
++
++ /* Attach to SAR HAL Functions */
++ /*
++ cpsarInitModule(NULL, NULL, 0, NULL, &SarFuncSize, Inst);
++
++ if (SarFuncSize!=sizeof(CPSAR_FUNCTIONS))
++ return(EC_AAL5|EC_FUNC_HAL_INIT|EC_VAL_CPSAR_VERSION_NOT_SUPPORTED);
++
++ HalPtr->SarFunc = (CPSAR_FUNCTIONS *) OsFunc->Malloc(SarFuncSize);
++ */
++
++ rc = cpsarInitModule(&HalPtr->SarDev, OsDev, &HalPtr->SarFunc, OsFunc, sizeof(OS_FUNCTIONS), &SarFuncSize, Inst);
++
++ /* pass back the error value from the CPSAR layer if necessary */
++ if (rc)
++ return(rc);
++
++ /*
++ if (!HalPtr->SarDev)
++ return(EC_AAL5|EC_FUNC_HAL_INIT|EC_VAL_NULL_CPSAR_DEV);
++ */
++
++ /* Initialize the hardware state */
++ HalPtr->State = enConnected;
++
++ /* keep a reference to HalFuncPtr so I can free it later */
++ HalPtr->HalFuncPtr = HalFuncPtr;
++
++ /* pass the HalPtr back to the caller */
++ *HalDev = HalPtr;
++ *HalFunc = HalFuncPtr;
++
++ return(EC_NO_ERRORS);
++ }
+diff -urN linux.old/drivers/atm/sangam_atm/aal5sar.h linux.dev/drivers/atm/sangam_atm/aal5sar.h
+--- linux.old/drivers/atm/sangam_atm/aal5sar.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/aal5sar.h 2005-08-23 04:46:50.080846280 +0200
+@@ -0,0 +1,198 @@
++/**@file************************************************************************
++ * TNETDxxxx Software Support
++ * Copyright (c) 2002 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ * FILE: aal5sar.h
++ *
++ * DESCRIPTION:
++ * This file contains data structure definitions for the AAL5 HAL SAR.
++ *
++ * HISTORY:
++ * 28Feb02 Greg 1.00 Original Version created.
++ * 06Mar02 Greg 1.01 Documented structures.
++ * 18Jul02 Greg 1.02 Major reorganization
++ *
++ *****************************************************************************/
++#ifndef _INC_AAL5SAR
++#define _INC_AAL5SAR
++
++/** \namespace AAL5_Version
++This documents version 01.06.06 of the AAL5 CPHAL.
++*/
++const char *pszVersion_CPAAL5="CPAAL5 01.06.06 "__DATE__" "__TIME__;
++
++#include "cpsar_cpaal5.h"
++
++#define NUM_AAL5_CHAN 16
++#define MAX_AAL5_CHAN 15
++#define MAX_QUEUE 2
++#define MAX_DIRECTION 2
++
++#define PKT_TYPE_AAL5 0 /* +GSG 030508 */
++#define PKT_TYPE_NULL 1 /* +GSG 030508 */
++#define PKT_TYPE_OAM 2 /* +GSG 030508 */
++#define PKT_TYPE_TRANS 3 /* +GSG 030508 */
++#define ATM_HEADER_SIZE 4 /* +GSG 030508 */
++
++/*
++ * HAL Default Parameter Values
++ */
++#define CFG_TX_NUM_BUFS {256,256,256,256,256,256,256,256, 256,256,256,256,256,256,256,256}
++#define CFG_RX_NUM_BUFS {256,256,256,256,256,256,256,256, 256,256,256,256,256,256,256,256}
++#define CFG_RX_BUF_SIZE {1518,1518,1518,1518,1518,1518,1518,1518, 1518,1518,1518,1518,1518,1518,1518,1518}
++#define CFG_RX_BUF_OFFSET {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}
++#define CFG_TX_NUM_QUEUES {1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1}
++#define CFG_CPCS_UU {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}
++#define CFG_DA_MASK {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}
++#define CFG_PRIORITY {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}
++#define CFG_PKT_TYPE {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}
++#define CFG_VCI {100,101,102,103,104,105,106,107, 108,109,110,111,112,113,114,115}
++#define CFG_VPI {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}
++#define CFG_CELL_RATE {0x30d4,0x30d4,0x30d4,0x30d4,0x30d4,0x30d4,0x30d4,0x30d4, 0x30d4,0x30d4,0x30d4,0x30d4,0x30d4,0x30d4,0x30d4,0x30d4}
++#define CFG_QOS_TYPE {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}
++#define CFG_MBS {8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8}
++#define CFG_PCR {1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1}
++#define CFG_GFC {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}
++#define CFG_CLP {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}
++#define CFG_PTI {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}
++#define CFG_RX_MAX_SERVICE {170,170,170,170,170,170,170,170, 170,170,170,170,170,170,170,170}
++#define CFG_TX_MAX_SERVICE {170,170,170,170,170,170,170,170, 170,170,170,170,170,170,170,170}
++
++static int cfg_tx_num_bufs[NUM_AAL5_CHAN] = CFG_TX_NUM_BUFS;
++static int cfg_rx_num_bufs[NUM_AAL5_CHAN] = CFG_RX_NUM_BUFS;
++static int cfg_rx_buf_size[NUM_AAL5_CHAN] = CFG_RX_BUF_SIZE;
++static int cfg_rx_buf_offset[NUM_AAL5_CHAN] = CFG_RX_BUF_OFFSET;
++static int cfg_tx_num_queues[NUM_AAL5_CHAN] = CFG_TX_NUM_QUEUES;
++static bit32u cfg_cpcs_uu[NUM_AAL5_CHAN] = CFG_CPCS_UU;
++static int cfg_da_mask[NUM_AAL5_CHAN] = CFG_DA_MASK;
++static int cfg_priority[NUM_AAL5_CHAN] = CFG_PRIORITY;
++static int cfg_pkt_type[NUM_AAL5_CHAN] = CFG_PKT_TYPE;
++static int cfg_vci[NUM_AAL5_CHAN] = CFG_VCI;
++static int cfg_vpi[NUM_AAL5_CHAN] = CFG_VPI;
++static bit32u cfg_cell_rate[NUM_AAL5_CHAN] = CFG_CELL_RATE;
++static int cfg_qos_type[NUM_AAL5_CHAN] = CFG_QOS_TYPE;
++static int cfg_mbs[NUM_AAL5_CHAN] = CFG_MBS;
++static int cfg_pcr[NUM_AAL5_CHAN] = CFG_PCR;
++static int cfg_gfc[NUM_AAL5_CHAN] = CFG_GFC;
++static int cfg_clp[NUM_AAL5_CHAN] = CFG_CLP;
++static int cfg_pti[NUM_AAL5_CHAN] = CFG_PTI;
++static int cfg_rx_max_service[NUM_AAL5_CHAN]= CFG_RX_MAX_SERVICE;
++static int cfg_tx_max_service[NUM_AAL5_CHAN]= CFG_TX_MAX_SERVICE;
++static char *channel_names[] = CHANNEL_NAMES;
++
++/*
++ * The HAL_FUNCTIONS struct defines the function pointers for all HAL functions
++ * accessible to upper layer software. It is populated by calling
++ * halInitModules().
++ *
++ * Note that this list is still under definition.
++ */
++
++/*
++ * This is the data structure for a transmit buffer descriptor. The first
++ * four 32-bit words of the BD represent the CPPI 3.0 defined buffer descriptor
++ * words. The other words are SAR/HAL implementation specific.
++ */
++typedef struct
++ {
++ bit32 HNext; /**< Hardware's pointer to next buffer descriptor */
++ bit32 BufPtr; /**< Pointer to the data buffer */
++ bit32 Off_BLen; /**< Contains buffer offset and buffer length */
++ bit32 mode; /**< SOP, EOP, Ownership, EOQ, Teardown Complete bits */
++ bit32 AtmHeader; /**< Atm Header to be used for each fragment */
++ bit32 Word5; /**< General control information for the packet */
++ bit32 Res6;
++ bit32 Res7;
++ void *Next;
++ void *OsInfo;
++#ifdef __CPHAL_DEBUG
++ bit32 DbgSop;
++ bit32 DbgData;
++ bit32 DbgFraglist;
++#endif
++ void *Eop;
++ }HAL_TCB;
++
++/*
++ * This is the data structure for a receive buffer descriptor. The first
++ * six 32-bit words of the BD represent the CPPI 3.0 defined buffer descriptor
++ * words. The other words are HAL implementation specific.
++ */
++typedef volatile struct hal_private
++ {
++ bit32 HNext; /**< Hardware's pointer to next buffer descriptor */
++ bit32 BufPtr; /**< Pointer to the data buffer */
++ bit32 Off_BLen; /**< Contains buffer offset and buffer length */
++ bit32 mode; /**< SOP, EOP, Ownership, EOQ, Teardown, Q Starv, Length */
++ bit32 AtmHeader;
++ bit32 UuCpi;
++ bit32 Res6;
++ bit32 Res7;
++ void *DatPtr;
++ void *Next;
++ void *OsInfo;
++ void *Eop;
++ bit32 FragCount;
++ bit32 Ch;
++ HAL_DEVICE *HalDev;
++ }HAL_RCB;
++
++
++#define MAX_NEEDS 512 /*MJH+030409*/
++/*
++ * This is the data structure for a generic HAL device. It contains all device
++ * specific data for a single instance of that device. This includes Rx/Tx
++ * buffer queues, device base address, reset bit, and other information.
++ */
++typedef struct hal_device
++ {
++ HAL_RCB *RcbPool[NUM_AAL5_CHAN];
++ bit32u rxbufseq;
++ bit32 RxActQueueCount[NUM_AAL5_CHAN];
++ HAL_RCB *RxActQueueHead[NUM_AAL5_CHAN];
++ HAL_RCB *RxActQueueTail[NUM_AAL5_CHAN];
++ bit32 RxActive[NUM_AAL5_CHAN];
++ bit32 dev_base;
++ HAL_TCB *TcbPool[NUM_AAL5_CHAN][MAX_QUEUE];
++ bit32 offset;
++ bit32 TxActQueueCount[NUM_AAL5_CHAN][MAX_QUEUE];
++ HAL_TCB *TxActQueueHead[NUM_AAL5_CHAN][MAX_QUEUE];
++ HAL_TCB *TxActQueueTail[NUM_AAL5_CHAN][MAX_QUEUE];
++ bit32 TxActive[NUM_AAL5_CHAN][MAX_QUEUE];
++ bit32 TxTeardownPending[NUM_AAL5_CHAN];
++ bit32 RxTeardownPending[NUM_AAL5_CHAN];
++ bit32 ChIsOpen[NUM_AAL5_CHAN][MAX_DIRECTION];
++ bit32 ChIsSetup[NUM_AAL5_CHAN][MAX_DIRECTION];
++ bit32 interrupt;
++ bit32 debug;
++ OS_DEVICE *OsDev;
++ OS_FUNCTIONS *OsFunc;
++ CPSAR_FUNCTIONS *SarFunc;
++ CPSAR_DEVICE *SarDev;
++ /*void *OsOpen;*/
++ /*FRAGLIST fraglist[MAX_FRAG];*/
++ FRAGLIST *fraglist;
++ char *TcbStart[NUM_AAL5_CHAN][MAX_QUEUE];
++ char *RcbStart[NUM_AAL5_CHAN];
++ /*bit32 RcbSize[NUM_AAL5_CHAN];*/
++ bit32 InRxInt[NUM_AAL5_CHAN];
++ STAT_INFO Stats;
++ bit32 Inst;
++ bit32u DeviceCPID[4];
++ bit32u LBSourceLLID[4];
++ CHANNEL_INFO ChData[NUM_AAL5_CHAN];
++ DEVICE_STATE State;
++ char *DeviceInfo;
++ HAL_FUNCTIONS *HalFuncPtr;
++ int NextRxCh;
++ int NextTxCh[2];
++ int StrictPriority; /* +GSG 030304 */
++ bit32u NeedsCount; /*MJH+030409*/
++ HAL_RECEIVEINFO *Needs[MAX_NEEDS]; /*MJH+030409*/
++ bit32u SarFrequency; /* +GSG 030416 */
++ int MaxFrags;
++ bit32u TurboDslErrors;
++ bit32u OamLbTimeout;
++ }HALDEVICE;
++
++#endif
+diff -urN linux.old/drivers/atm/sangam_atm/cpcommon_cpaal5.c linux.dev/drivers/atm/sangam_atm/cpcommon_cpaal5.c
+--- linux.old/drivers/atm/sangam_atm/cpcommon_cpaal5.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/cpcommon_cpaal5.c 2005-08-23 04:46:50.081846128 +0200
+@@ -0,0 +1,728 @@
++#ifndef _INC_CPCOMMON_C
++#define _INC_CPCOMMON_C
++
++#ifdef _CPHAL_CPMAC
++#include "cpremap_cpmac.c"
++#endif
++
++#ifdef _CPHAL_AAL5
++#include "cpremap_cpaal5.c"
++#endif
++
++#ifdef _CPHAL_CPSAR
++#include "cpremap_cpsar.c"
++#endif
++
++#ifdef _CPHAL_AAL2
++#include "cpremap_cpaal2.c"
++#endif
++
++/**
++@defgroup Common_Config_Params Common Configuration Parameters
++
++This section documents the configuration parameters that are valid across
++all CPHAL devices.
++@{
++*/
++/** This is the debug level. The field is bit defined, such that the user
++should set to 1 all the bits corresponding to desired debug outputs. The following
++are the meanings for each debug bit:
++- bit0 (LSB): CPHAL Function Trace
++- b1 : OS Function call trace
++- b2 : Critical section entry/exit
++- b3 : Memory allocation/destruction
++- b4 : Detailed information in Rx path
++- b5 : Detailed information in Tx path
++- b6 : Extended error information
++- b7 : General info
++*/
++static const char pszDebug[] = "debug";
++/** CPU Frequency. */
++/*static const char pszCpuFreq[] = "CpuFreq";*/ /*MJH-030403*/
++/** Base address for the module. */
++static const char pszBase[] = "base";
++/** Reset bit for the module. */
++static const char pszResetBit[] = "reset_bit";
++/** Reset base address for the module. */
++static const char pszResetBase[] = "ResetBase";
++/** Interrupt line for the module. */
++static const char pszIntLine[] = "int_line";
++/** VLYNQ offset for the module. Disregard if not using VLYNQ. */
++static const char pszOffset[] = "offset";
++/** The OS may "Get" this parameter, which is a pointer
++ to a character string that indicates the version of CPHAL. */
++static const char pszVer[] = "Version";
++/*@}*/
++
++/**
++@defgroup Common_Control_Params Common Keys for [os]Control()
++
++This section documents the keys used with the OS @c Control() interface that
++are required by CPHAL devices.
++
++@{
++*/
++/** Used to wait for an integer number of clock ticks, given as an integer
++ pointer in the @p Value parameter. No actions are defined. */
++static const char pszSleep[] = "Sleep";
++/** Requests the OS to flush it's IO buffers. No actions are defined. */
++static const char pszSioFlush[] = "SioFlush";
++/*@}*/
++
++static const char pszStateChange[] = "StateChange";
++static const char pszStatus[] = "Status";
++
++static const char pszGET[] = "Get";
++static const char pszSET[] = "Set";
++static const char pszCLEAR[] = "Clear";
++static const char pszNULL[] = "";
++static const char pszLocator[] = "Locator";
++static const char pszOff[] = "Off";
++static const char pszOn[] = "On";
++static const char hcMaxFrags[] = "MaxFrags";
++
++#ifdef _CPHAL_CPMAC
++
++/* New method for string constants */
++const char hcClear[] = "Clear";
++const char hcGet[] = "Get";
++const char hcSet[] = "Set";
++
++const char hcTick[] = "Tick";
++
++static const CONTROL_KEY KeyCommon[] =
++ {
++ {"" , enCommonStart},
++ {pszStatus , enStatus},
++ {pszOff , enOff},
++ {pszOn , enOn},
++ {pszDebug , enDebug},
++ {hcCpuFrequency , enCpuFreq}, /*MJH~030403*/
++ {"" , enCommonEnd}
++ };
++#endif
++
++/**
++@defgroup Common_Statistics Statistics
++
++A broad array of module statistics is available. Statistics values are accessed
++through the @c Control() interface of the CPHAL. There are 5 different levels
++of statistics, each of which correspond to a unique set of data. Furthermore,
++certain statistics data is indexed by using a channel number and Tx queue number.
++The following is a brief description of each statistics level, along with the
++indexes used for the level:
++
++- Level 0: Hardware Statistics (index with channel)
++- Level 1: CPHAL Software Statistics (channel, queue)
++- Level 2: CPHAL Flags (channel, queue)
++- Level 3: CPHAL Channel Configuration (channel)
++- Level 4: CPHAL General Configuration (no index)
++
++The caller requests statistics information by providing a Key string to the
++@c Control() API in the following format: "Stats;[Level #];[Ch #];[Queue #]".
++The only valid Action parameter for statistics usage is "Get".
++
++Code Examples:
++@code
++unsigned int *StatsData;
++
++# Get Level 0 stats for Channel 1
++HalFunc->Control(OsDev->HalDev, "Stats;0;1", "Get", &StatsData);
++
++# Get Level 2 stats for Channel 0, Queue 0
++HalFunc->Control(OsDev->HalDev, "Stats;2;0;0", "Get", &StatsData);
++
++# Get Level 4 stats
++HalFunc->Control(OsDev->HalDev, "Stats;4", "Get", &StatsData);
++@endcode
++
++The information returned in the Value parameter of @c Control() is an
++array of pointers to strings. The pointers are arranged in pairs.
++The first pointer is a pointer to a name string for a particular statistic.
++The next pointer is a pointer to a string containing the representation of
++the integer statistic value corresponding to the first pointer. This is followed
++by another pair of pointers, and so on, until a NULL pointer is encountered. The
++following is example code for processing the statistics data. Note that the OS
++is responsible for freeing the memory passed back through the Value parameter of
++@c Control().
++
++@code
++unsigned int *StatsData;
++
++# Get Level 0 stats for Channel 1
++HalFunc->Control(OsDev->HalDev, "Stats;0;1", "Get", &StatsData);
++
++# output Statistics data
++PrintStats(StatsData);
++
++# the upper layer is responsible for freeing stats info
++free(&StatsPtr);
++
++...
++
++void PrintStats(unsigned int *StatsPtr)
++ {
++ while(*StatsPtr)
++ {
++ printf("%20s:", (char *)*StatsPtr);
++ StatsPtr++;
++ printf("%11s\n", (char *)*StatsPtr);
++ StatsPtr++;
++ }
++ MySioFlush();
++ }
++@endcode
++
++Within each statistics level, there are several statistics defined. The statistics that
++are common to every CPPI module are listed below. In addition, each module may define
++extra statistics in each level, which will be documented within the module-specific
++documentation appendices.
++
++- Level 0 Statistics
++ - All level 0 statistics are module-specific.
++- Level 1 Statistics (CPHAL Software Statistics)
++ - DmaLenErrors: Incremented when the port DMA's more data than expected (per channel). (AAL5 Only)
++ - TxMisQCnt: Incremented when host queues a packet for transmission as the port finishes
++transmitting the previous last packet in the queue (per channel and queue).
++ - RxMisQCnt: Incremented when host queues adds buffers to a queue as the port finished the
++reception of the previous last packet in the queue (per channel).
++ - TxEOQCnt: Number of times the port has reached the end of the transmit queue (per channel and queue).
++ - RxEOQCnt: Number of times the port has reached the end of the receive queue (per channel).
++ - RxPacketsServiced: Number of received packets (per channel).
++ - TxPacketsServiced: Number of transmitted packets (per channel and queue).
++ - RxMaxServiced: Maximum number of packets that the CPHAL receive interrupt has serviced at a time (per channel).
++ - TxMaxServiced: Maximum number of packets that the CPHAL transmit interrupt has serviced at a time (per channel and queue).
++ - RxTotal: Total number of received packets, all channels.
++ - TxTotal: Total number of transmitted packets, all channels and queues.
++- Level 2 Statistics (CPHAL Flags)
++ - RcbPool: Pointer to receive descriptor pool (per channel).
++ - RxActQueueCount: Number of buffers currently available for receive (per channel).
++ - RxActQueueHead: Pointer to first buffer in receive queue (per channel).
++ - RxActQueueTail: Pointer to last buffer in receive queue (per channel).
++ - RxActive: 0 if inactive (no buffers available), or 1 if active (buffers available).
++ - RcbStart: Pointer to block of receive descriptors.
++ - RxTeardownPending: 1 if Rx teardown is pending but incomplete, 0 otherwise.
++ - TcbPool: Pointer to transmit descriptor pool (per channel and queue).
++ - TxActQueueCount: Number of buffers currently queued to be transmitted (per channel and queue).
++ - TxActQueueHead: Pointer to first buffer in transmit queue (per channel and queue).
++ - TxActQueueTail: Pointer to last buffer in transmit queue (per channel and queue).
++ - TxActive: 0 if inactive (no buffers to send), or 1 if active (buffers queued to send).
++ - TcbStart: Pointer to block of transmit descriptors.
++ - TxTeardownPending: 1 if Tx teardown is pending but incomplete, 0 otherwise.
++- Level 3 Statistics (CPHAL Channel Configuration)
++ - RxBufSize: Rx buffer size.
++ - RxBufferOffset: Rx buffer offset.
++ - RxNumBuffers: Number of Rx buffers.
++ - RxServiceMax: Maximum number of receive packets to service at a time.
++ - TxNumBuffers: Number of Tx buffer descriptors.
++ - TxNumQueues: Number of Tx queues to use.
++ - TxServiceMax: Maximum number of transmit packets to service at a time.
++- Level 4 Statistics (CPHAL General Configuration)
++ - Base Address: Base address of the module.
++ - Offset (VLYNQ): VLYNQ relative module offset.
++ - Interrupt Line: Interrupt number.
++ - Debug: Debug flag, 1 to enable debug.
++ - Inst: Instance number.
++*/
++
++/*
++ Data Type 0 = int display
++ Data Type 1 = hex display
++ Data Type 2 = channel structure, int display
++ Data Type 3 = queue index and int display
++ Data Type 4 = queue index and hex display
++*/
++#if (defined(_CPHAL_AAL5) || defined(_CPHAL_CPMAC)) /* +GSG 030307 */
++static STATS_TABLE StatsTable0[] =
++ {
++#ifdef _CPHAL_AAL5
++ /* Name , Data Ptr, Data Type */
++ {"Crc Errors", 0, 0},
++ {"Len Errors", 0, 0},
++ {"Abort Errors", 0, 0},
++ {"Starv Errors", 0, 0}
++#endif
++#ifdef _CPHAL_CPMAC
++ {"Rx Good Frames", 0, 0}
++#endif
++ };
++
++static STATS_TABLE StatsTable1[] =
++ {
++ /* Name , Data Ptr, Data Type */
++ {"DmaLenErrors", 0, 0},
++ {"TxMisQCnt", 0, 3},
++ {"RxMisQCnt", 0, 0},
++ {"TxEOQCnt", 0, 3},
++ {"RxEOQCnt", 0, 0},
++ {"RxPacketsServiced", 0, 0},
++ {"TxPacketsServiced", 0, 3},
++ {"RxMaxServiced", 0, 0},
++ {"TxMaxServiced", 0, 3},
++ {"RxTotal", 0, 0},
++ {"TxTotal", 0, 0},
++ };
++
++static STATS_TABLE StatsTable2[] =
++ {
++ /* Name , Data Ptr, Data Type */
++ {"RcbPool", 0, 1},
++ {"RxActQueueCount", 0, 0},
++ {"RxActQueueHead", 0, 1},
++ {"RxActQueueTail", 0, 1},
++ {"RxActive", 0, 0},
++ {"RcbStart", 0, 1},
++ {"RxTeardownPending", 0, 0},
++ {"TcbPool", 0, 4},
++ {"TxActQueueCount", 0, 3},
++ {"TxActQueueHead", 0, 4},
++ {"TxActQueueTail", 0, 4},
++ {"TxActive", 0, 3},
++ {"TcbStart", 0, 4},
++ {"TxTeardownPending", 0, 0}
++ };
++
++static STATS_TABLE StatsTable3[] =
++ {
++ /* Name , Data Ptr, Data Type */
++ {"RxBufSize", 0, 2},
++ {"RxBufferOffset", 0, 2},
++ {"RxNumBuffers", 0, 2},
++ {"RxServiceMax", 0, 2},
++ {"TxNumBuffers", 0, 2},
++ {"TxNumQueues", 0, 2},
++ {"TxServiceMax", 0, 2},
++#ifdef _CPHAL_AAL5
++ {"CpcsUU", 0, 2},
++ {"Gfc", 0, 2},
++ {"Clp", 0, 2},
++ {"Pti", 0, 2},
++ {"DaMask", 0, 2},
++ {"Priority", 0, 2},
++ {"PktType", 0, 2},
++ {"Vci", 0, 2},
++ {"Vpi", 0, 2},
++ {"CellRate", 0, 2},
++ {"QosType", 0, 2},
++ {"Mbs", 0, 2},
++ {"Pcr", 0, 2}
++#endif
++ };
++
++static STATS_TABLE StatsTable4[] =
++ {
++ {"Base Address", 0, 1},
++ {"Offset (VLYNQ)", 0, 0},
++ {"Interrupt Line", 0, 0},
++ {"Debug", 0, 0},
++ {"Instance", 0, 0},
++#ifdef _CPHAL_AAL5
++ {"UniNni", 0, 0}
++#endif
++ };
++
++static STATS_DB StatsDb[] =
++ {
++ {(sizeof(StatsTable0)/sizeof(STATS_TABLE)), StatsTable0},
++ {(sizeof(StatsTable1)/sizeof(STATS_TABLE)), StatsTable1},
++ {(sizeof(StatsTable2)/sizeof(STATS_TABLE)), StatsTable2},
++ {(sizeof(StatsTable3)/sizeof(STATS_TABLE)), StatsTable3},
++ {(sizeof(StatsTable4)/sizeof(STATS_TABLE)), StatsTable4}
++ };
++#endif /* +GSG 030307 */
++
++#ifdef _CPHAL_CPMAC /* +RC 3.02 */
++static void resetWait(HAL_DEVICE *HalDev)
++ { /*+RC3.02*/
++ const int TickReset=64;
++ osfuncSleep((int*)&TickReset);
++ } /*+RC3.02*/
++#endif /* +RC 3.02 */
++
++/* I only define the reset base function for the modules
++ that can perform a reset. The AAL5 and AAL2 modules
++ do not perform a reset, that is done by the shared module
++ CPSAR */
++#if defined(_CPHAL_CPSAR) || defined(_CPHAL_CPMAC) || defined(_CPHAL_VDMAVT)
++/*
++ * Determines the reset register address to be used for a particular device.
++ * It will search the current device entry for Locator information. If the
++ * device is a root device, there will be no Locator information, and the
++ * function will find and return the root reset register. If a Locator value
++ * is found, the function will search each VLYNQ device entry in the system
++ * looking for a matching Locator. Once it finds a VLYNQ device entry with
++ * a matching Locator, it will extract the "ResetBase" parameter from that
++ * VLYNQ device entry (thus every VLYNQ entry must have the ResetBase parameter).
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ * @param ResetBase Pointer to integer address of reset register.
++ *
++ * @return 0 OK, Non-zero not OK
++ */
++static int ResetBaseGet(HAL_DEVICE *HalDev, bit32u *ResetBase)
++ {
++ char *DeviceInfo = HalDev->DeviceInfo;
++ char *MyLocator, *NextLocator;
++ int Inst=1;
++ bit32u error_code;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpcommon]ResetBaseGet(HalDev:%08x, ResetBase:%08x)\n", (bit32u)HalDev, ResetBase);
++ osfuncSioFlush();
++ }
++#endif
++
++ error_code = HalDev->OsFunc->DeviceFindParmValue(DeviceInfo, "Locator", &MyLocator);
++ if (error_code)
++ {
++ /* if no Locator value, device is on the root, so get the "reset" device */
++ error_code = HalDev->OsFunc->DeviceFindInfo(0, "reset", &DeviceInfo);
++ if (error_code)
++ {
++ return(EC_VAL_DEVICE_NOT_FOUND);
++ }
++
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, "base", ResetBase);
++ if (error_code)
++ {
++ return(EC_VAL_BASE_ADDR_NOT_FOUND);
++ }
++
++ *ResetBase = ((bit32u)PhysToVirtNoCache(*ResetBase));
++
++ /* found base address for root device, so we're done */
++ return (EC_NO_ERRORS);
++ }
++ else
++ {
++ /* we have a Locator value, so the device is remote */
++
++ /* Find a vlynq device with a matching locator value */
++ while ((HalDev->OsFunc->DeviceFindInfo(Inst, "vlynq", &DeviceInfo)) == EC_NO_ERRORS)
++ {
++ error_code = HalDev->OsFunc->DeviceFindParmValue(DeviceInfo, "Locator", &NextLocator);
++ if (error_code)
++ {
++ /* no Locator value for this VLYNQ, so move on */
++ continue;
++ }
++ if (HalDev->OsFunc->Strcmpi(MyLocator, NextLocator)==0)
++ {
++ /* we have found a VLYNQ with a matching Locator, so extract the ResetBase */
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, "ResetBase", ResetBase);
++ if (error_code)
++ {
++ return(EC_VAL_BASE_ADDR_NOT_FOUND);
++ }
++ *ResetBase = ((bit32u)PhysToVirtNoCache(*ResetBase));
++
++ /* found base address for root device, so we're done */
++ return (EC_NO_ERRORS);
++ }
++ Inst++;
++ } /* while */
++ } /* else */
++
++ return (EC_NO_ERRORS);
++ }
++#endif
++
++#ifndef _CPHAL_AAL2 /* + RC 3.02 */
++static bit32u ConfigGetCommon(HAL_DEVICE *HalDev)
++ {
++ bit32u ParmValue;
++ bit32 error_code;
++ char *DeviceInfo = HalDev->DeviceInfo;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpcommon]ConfigGetCommon(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszBase, &ParmValue);
++ if (error_code)
++ {
++ return(EC_FUNC_HAL_INIT|EC_VAL_BASE_ADDR_NOT_FOUND);
++ }
++ HalDev->dev_base = ((bit32u)PhysToVirtNoCache(ParmValue));
++
++#ifndef _CPHAL_AAL5
++#ifndef _CPHAL_AAL2
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszResetBit, &ParmValue);
++ if(error_code)
++ {
++ return(EC_FUNC_HAL_INIT|EC_VAL_RESET_BIT_NOT_FOUND);
++ }
++ HalDev->ResetBit = ParmValue;
++
++ /* Get reset base address */
++ error_code = ResetBaseGet(HalDev, &ParmValue);
++ if (error_code)
++ return(EC_FUNC_HAL_INIT|EC_VAL_RESET_BASE_NOT_FOUND);
++ HalDev->ResetBase = ParmValue;
++#endif
++#endif
++
++#ifndef _CPHAL_CPSAR
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszIntLine,&ParmValue);
++ if (error_code)
++ {
++ return(EC_FUNC_HAL_INIT|EC_VAL_INTERRUPT_NOT_FOUND);
++ }
++ HalDev->interrupt = ParmValue;
++#endif
++
++ /* only look for the offset if there is a Locator field, which indicates that
++ the module is a VLYNQ module */
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszLocator,&ParmValue);
++ if (!error_code)
++ {
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszOffset,&ParmValue);
++ if (error_code)
++ {
++ return(EC_FUNC_HAL_INIT|EC_VAL_OFFSET_NOT_FOUND);
++ }
++ HalDev->offset = ParmValue;
++ }
++ else
++ HalDev->offset = 0;
++
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszDebug, &ParmValue);
++ if (!error_code) HalDev->debug = ParmValue;
++
++ return (EC_NO_ERRORS);
++ }
++#endif /* +RC 3.02 */
++
++#ifdef _CPHAL_CPMAC /* +RC 3.02 */
++static void StatsInit(HAL_DEVICE *HalDev) /* +() RC3.02 */
++ {
++ /* even though these statistics may be for multiple channels and
++ queues, i need only configure the pointer to the beginning
++ of the array, and I can index from there if necessary */
++
++#ifdef _CPHAL_AAL5
++ StatsTable0[0].StatPtr = &HalDev->Stats.CrcErrors[0];
++ StatsTable0[1].StatPtr = &HalDev->Stats.LenErrors[0];
++ StatsTable0[2].StatPtr = &HalDev->Stats.AbortErrors[0];
++ StatsTable0[3].StatPtr = &HalDev->Stats.StarvErrors[0];
++
++ StatsTable1[0].StatPtr = &HalDev->Stats.DmaLenErrors[0];
++ StatsTable1[1].StatPtr = &HalDev->Stats.TxMisQCnt[0][0];
++ StatsTable1[2].StatPtr = &HalDev->Stats.RxMisQCnt[0];
++ StatsTable1[3].StatPtr = &HalDev->Stats.TxEOQCnt[0][0];
++ StatsTable1[4].StatPtr = &HalDev->Stats.RxEOQCnt[0];
++ StatsTable1[5].StatPtr = &HalDev->Stats.RxPacketsServiced[0];
++ StatsTable1[6].StatPtr = &HalDev->Stats.TxPacketsServiced[0][0];
++ StatsTable1[7].StatPtr = &HalDev->Stats.RxMaxServiced;
++ StatsTable1[8].StatPtr = &HalDev->Stats.TxMaxServiced[0][0];
++ StatsTable1[9].StatPtr = &HalDev->Stats.RxTotal;
++ StatsTable1[10].StatPtr = &HalDev->Stats.TxTotal;
++#endif
++
++#if (defined(_CPHAL_AAL5) || defined(_CPHAL_CPMAC))
++ StatsTable2[0].StatPtr = (bit32u *)&HalDev->RcbPool[0];
++ StatsTable2[1].StatPtr = &HalDev->RxActQueueCount[0];
++ StatsTable2[2].StatPtr = (bit32u *)&HalDev->RxActQueueHead[0];
++ StatsTable2[3].StatPtr = (bit32u *)&HalDev->RxActQueueTail[0];
++ StatsTable2[4].StatPtr = &HalDev->RxActive[0];
++ StatsTable2[5].StatPtr = (bit32u *)&HalDev->RcbStart[0];
++ StatsTable2[6].StatPtr = &HalDev->RxTeardownPending[0];
++ StatsTable2[7].StatPtr = (bit32u *)&HalDev->TcbPool[0][0];
++ StatsTable2[8].StatPtr = &HalDev->TxActQueueCount[0][0];
++ StatsTable2[9].StatPtr = (bit32u *)&HalDev->TxActQueueHead[0][0];
++ StatsTable2[10].StatPtr = (bit32u *)&HalDev->TxActQueueTail[0][0];
++ StatsTable2[11].StatPtr = &HalDev->TxActive[0][0];
++ StatsTable2[12].StatPtr = (bit32u *)&HalDev->TcbStart[0][0];
++ StatsTable2[13].StatPtr = &HalDev->TxTeardownPending[0];
++
++ StatsTable3[0].StatPtr = &HalDev->ChData[0].RxBufSize;
++ StatsTable3[1].StatPtr = &HalDev->ChData[0].RxBufferOffset;
++ StatsTable3[2].StatPtr = &HalDev->ChData[0].RxNumBuffers;
++ StatsTable3[3].StatPtr = &HalDev->ChData[0].RxServiceMax;
++ StatsTable3[4].StatPtr = &HalDev->ChData[0].TxNumBuffers;
++ StatsTable3[5].StatPtr = &HalDev->ChData[0].TxNumQueues;
++ StatsTable3[6].StatPtr = &HalDev->ChData[0].TxServiceMax;
++#ifdef _CPHAL_AAL5
++ StatsTable3[7].StatPtr = &HalDev->ChData[0].CpcsUU;
++ StatsTable3[8].StatPtr = &HalDev->ChData[0].Gfc;
++ StatsTable3[9].StatPtr = &HalDev->ChData[0].Clp;
++ StatsTable3[10].StatPtr = &HalDev->ChData[0].Pti;
++ StatsTable3[11].StatPtr = &HalDev->ChData[0].DaMask;
++ StatsTable3[12].StatPtr = &HalDev->ChData[0].Priority;
++ StatsTable3[13].StatPtr = &HalDev->ChData[0].PktType;
++ StatsTable3[14].StatPtr = &HalDev->ChData[0].Vci;
++ StatsTable3[15].StatPtr = &HalDev->ChData[0].Vpi;
++ StatsTable3[16].StatPtr = &HalDev->ChData[0].TxVc_CellRate;
++ StatsTable3[17].StatPtr = &HalDev->ChData[0].TxVc_QosType;
++ StatsTable3[18].StatPtr = &HalDev->ChData[0].TxVc_Mbs;
++ StatsTable3[19].StatPtr = &HalDev->ChData[0].TxVc_Pcr;
++#endif
++#endif
++
++ StatsTable4[0].StatPtr = &HalDev->dev_base;
++ StatsTable4[1].StatPtr = &HalDev->offset;
++ StatsTable4[2].StatPtr = &HalDev->interrupt;
++ StatsTable4[3].StatPtr = &HalDev->debug;
++ StatsTable4[4].StatPtr = &HalDev->Inst;
++ }
++#endif /* +RC 3.02 */
++
++#ifndef _CPHAL_CPSAR /* +RC 3.02 */
++#ifndef _CPHAL_AAL2 /* +RC 3.02 */
++/*
++ * Returns statistics information.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ *
++ * @return 0
++ */
++static int StatsGet(HAL_DEVICE *HalDev, void **StatPtr, int Index, int Ch, int Queue)
++ {
++ int Size;
++ bit32u *AddrPtr;
++ char *DataPtr;
++ STATS_TABLE *StatsTable;
++ int i, NumberOfStats;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpcommon]StatsGet(HalDev:%08x, StatPtr:%08x)\n",
++ (bit32u)HalDev, (bit32u)StatPtr);
++ osfuncSioFlush();
++ }
++#endif
++
++ StatsTable = StatsDb[Index].StatTable;
++ NumberOfStats = StatsDb[Index].NumberOfStats;
++
++ Size = sizeof(bit32u)*((NumberOfStats*2)+1);
++ Size += (NumberOfStats*11);
++ *StatPtr = (bit32u *)HalDev->OsFunc->Malloc(Size);
++
++ AddrPtr = (bit32u *) *StatPtr;
++ DataPtr = (char *)AddrPtr;
++ DataPtr += sizeof(bit32u)*((NumberOfStats*2)+1);
++
++ for (i=0; i<NumberOfStats; i++)
++ {
++ *AddrPtr++ = (bit32u)StatsTable[i].StatName;
++ *AddrPtr++ = (bit32u)DataPtr;
++ if (&StatsTable[i].StatPtr[Ch] != 0)
++ {
++ switch(StatsTable[i].DataType)
++ {
++ case 0:
++ HalDev->OsFunc->Sprintf(DataPtr, "%d", (bit32u *)StatsTable[i].StatPtr[Ch]);
++ break;
++ case 1:
++ HalDev->OsFunc->Sprintf(DataPtr, "0x%x", (bit32u *)StatsTable[i].StatPtr[Ch]);
++ break;
++ case 2:
++ HalDev->OsFunc->Sprintf(DataPtr, "%d", *((bit32u *)StatsTable[i].StatPtr + (Ch * (sizeof(CHANNEL_INFO)/4))));
++ break;
++ case 3:
++ HalDev->OsFunc->Sprintf(DataPtr, "%d", *((bit32u *)StatsTable[i].StatPtr + (Ch*MAX_QUEUE)+Queue));
++ break;
++ case 4:
++ HalDev->OsFunc->Sprintf(DataPtr, "0x%x", *((bit32u *)StatsTable[i].StatPtr + (Ch*MAX_QUEUE)+Queue));
++ break;
++ default:
++ /* invalid data type, due to CPHAL programming error */
++ break;
++ }
++ }
++ else
++ {
++ /* invalid statistics pointer, probably was not initialized */
++ }
++ DataPtr += HalDev->OsFunc->Strlen(DataPtr) + 1;
++ }
++
++ *AddrPtr = (bit32u) 0;
++
++ return (EC_NO_ERRORS);
++ }
++#endif /* +RC 3.02 */
++#endif /* +RC 3.02 */
++
++#ifdef _CPHAL_CPMAC
++static void gpioFunctional(int base, int bit)
++ { /*+RC3.02*/
++ bit32u GpioEnr = base + 0xC;
++ /* To make functional, set to zero */
++ *(volatile bit32u *)(GpioEnr) &= ~(1 << bit); /*+RC3.02*/
++ } /*+RC3.02*/
++
++
++/*+RC3.02*/
++/* Common function, Checks to see if GPIO should be in functional mode */
++static void gpioCheck(HAL_DEVICE *HalDev, void *moduleDeviceInfo)
++ { /*+RC3.02*/
++ int rc;
++ void *DeviceInfo;
++ char *pszMuxBits;
++ char pszMuxBit[20];
++ char *pszTmp;
++ char szMuxBit[20];
++ char *ptr;
++ int base;
++ int reset_bit;
++ int bit;
++ OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++
++ rc = OsFunc->DeviceFindParmValue(moduleDeviceInfo, "gpio_mux",&pszTmp);
++ if(rc) return;
++ /* gpio entry found, get GPIO register info and make functional */
++
++ /* temp copy until FinParmValue fixed */
++ ptr = &szMuxBit[0];
++ while ((*ptr++ = *pszTmp++));
++
++ pszMuxBits = &szMuxBit[0];
++
++ rc = OsFunc->DeviceFindInfo(0,"gpio",&DeviceInfo);
++ if(rc) return;
++
++ rc = OsFunc->DeviceFindParmUint(DeviceInfo, "base",&base);
++ if(rc) return;
++
++ rc = OsFunc->DeviceFindParmUint(DeviceInfo, "reset_bit",&reset_bit);
++ if(rc) return;
++
++ /* If GPIO still in reset, then exit */
++ if((VOLATILE32(HalDev->ResetBase) & (1 << reset_bit)) == 0)
++ return;
++ /* format for gpio_mux is gpio_mux = <int>;<int>;<int>...*/
++ while (*pszMuxBits)
++ {
++ pszTmp = &pszMuxBit[0];
++ if(*pszMuxBits == ';') pszMuxBits++;
++ while ((*pszMuxBits != ';') && (*pszMuxBits != '\0'))
++ {
++ osfuncSioFlush();
++ /*If value not a number, skip */
++ if((*pszMuxBits < '0') || (*pszMuxBits > '9'))
++ pszMuxBits++;
++ else
++ *pszTmp++ = *pszMuxBits++;
++ }
++ *pszTmp = '\0';
++ bit = OsFunc->Strtoul(pszMuxBit, &pszTmp, 10);
++ gpioFunctional(base, bit);
++ resetWait(HalDev); /* not sure if this is needed */
++ }
++ } /*+RC3.02*/
++#endif /* CPMAC */
++
++#ifdef _CPHAL_AAL5
++const char hcSarFrequency[] = "SarFreq";
++#endif
++
++#endif /* _INC */
+diff -urN linux.old/drivers/atm/sangam_atm/cpcommon_cpaal5.h linux.dev/drivers/atm/sangam_atm/cpcommon_cpaal5.h
+--- linux.old/drivers/atm/sangam_atm/cpcommon_cpaal5.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/cpcommon_cpaal5.h 2005-08-23 04:46:50.082845976 +0200
+@@ -0,0 +1,79 @@
++#ifndef _INC_CPCOMMON_H
++#define _INC_CPCOMMON_H
++
++#define VOLATILE32(addr) (*(volatile bit32u *)(addr))
++#ifndef dbgPrintf
++#define dbgPrintf HalDev->OsFunc->Printf
++#endif
++
++#define ChannelUpdate(Field) if(HalChn->Field != 0xFFFFFFFF) HalDev->ChData[Ch].Field = HalChn->Field
++
++#define DBG(level) (HalDev->debug & (1<<(level)))
++/*
++#define DBG0() DBG(0)
++#define DBG1() DBG(1)
++#define DBG2() DBG(2)
++#define DBG3() DBG(3)
++#define DBG4() DBG(4)
++#define DBG5() DBG(5)
++#define DBG6() DBG(6)
++#define DBG7() DBG(7)
++*/
++
++/*
++ * List of defined actions for use with Control().
++ */
++typedef enum
++ {
++ enGET=0, /**< Get the value associated with a key */
++ enSET, /**< Set the value associates with a key */
++ enCLEAR, /**<Clear the value */
++ enNULL /**< No data action, used to initiate a service or send a message */
++ }ACTION;
++
++/*
++ * Enumerated hardware states.
++ */
++typedef enum
++ {
++ enConnected=1, enDevFound, enInitialized, enOpened
++ }DEVICE_STATE;
++
++typedef enum
++ {
++ enCommonStart=0,
++ /* General */
++ enOff, enOn, enDebug,
++ /* Module General */
++ enCpuFreq,
++ enStatus,
++ enCommonEnd
++ }COMMON_KEY;
++
++typedef struct
++ {
++ const char *strKey;
++ int enKey;
++ }CONTROL_KEY;
++
++typedef struct
++ {
++ char *StatName;
++ unsigned int *StatPtr;
++ int DataType; /* 0: int, 1: hex int, 2:channel data */
++ }STATS_TABLE;
++
++typedef struct
++ {
++ int NumberOfStats;
++ STATS_TABLE *StatTable;
++ }STATS_DB;
++
++#define osfuncSioFlush() HalDev->OsFunc->Control(HalDev->OsDev,"SioFlush",pszNULL,0)
++#define osfuncSleep(Ticks) HalDev->OsFunc->Control(HalDev->OsDev,pszSleep,pszNULL,Ticks)
++#define osfuncStateChange() HalDev->OsFunc->Control(HalDev->OsDev,pszStateChange,pszNULL,0)
++
++#define CHANNEL_NAMES {"Ch0","Ch1","Ch2","Ch3","Ch4","Ch5","Ch6","Ch7","Ch8","Ch9","Ch10","Ch11","Ch12","Ch13","Ch14","Ch15"}
++
++#endif
++
+diff -urN linux.old/drivers/atm/sangam_atm/cpcommon_cpsar.c linux.dev/drivers/atm/sangam_atm/cpcommon_cpsar.c
+--- linux.old/drivers/atm/sangam_atm/cpcommon_cpsar.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/cpcommon_cpsar.c 2005-08-23 04:46:50.082845976 +0200
+@@ -0,0 +1,728 @@
++#ifndef _INC_CPCOMMON_C
++#define _INC_CPCOMMON_C
++
++#ifdef _CPHAL_CPMAC
++#include "cpremap_cpmac.c"
++#endif
++
++#ifdef _CPHAL_AAL5
++#include "cpremap_cpaal5.c"
++#endif
++
++#ifdef _CPHAL_CPSAR
++#include "cpremap_cpsar.c"
++#endif
++
++#ifdef _CPHAL_AAL2
++#include "cpremap_cpaal2.c"
++#endif
++
++/**
++@defgroup Common_Config_Params Common Configuration Parameters
++
++This section documents the configuration parameters that are valid across
++all CPHAL devices.
++@{
++*/
++/** This is the debug level. The field is bit defined, such that the user
++should set to 1 all the bits corresponding to desired debug outputs. The following
++are the meanings for each debug bit:
++- bit0 (LSB): CPHAL Function Trace
++- b1 : OS Function call trace
++- b2 : Critical section entry/exit
++- b3 : Memory allocation/destruction
++- b4 : Detailed information in Rx path
++- b5 : Detailed information in Tx path
++- b6 : Extended error information
++- b7 : General info
++*/
++static const char pszDebug[] = "debug";
++/** CPU Frequency. */
++/*static const char pszCpuFreq[] = "CpuFreq";*/ /*MJH-030403*/
++/** Base address for the module. */
++static const char pszBase[] = "base";
++/** Reset bit for the module. */
++static const char pszResetBit[] = "reset_bit";
++/** Reset base address for the module. */
++static const char pszResetBase[] = "ResetBase";
++/** Interrupt line for the module. */
++static const char pszIntLine[] = "int_line";
++/** VLYNQ offset for the module. Disregard if not using VLYNQ. */
++static const char pszOffset[] = "offset";
++/** The OS may "Get" this parameter, which is a pointer
++ to a character string that indicates the version of CPHAL. */
++static const char pszVer[] = "Version";
++/*@}*/
++
++/**
++@defgroup Common_Control_Params Common Keys for [os]Control()
++
++This section documents the keys used with the OS @c Control() interface that
++are required by CPHAL devices.
++
++@{
++*/
++/** Used to wait for an integer number of clock ticks, given as an integer
++ pointer in the @p Value parameter. No actions are defined. */
++static const char pszSleep[] = "Sleep";
++/** Requests the OS to flush it's IO buffers. No actions are defined. */
++static const char pszSioFlush[] = "SioFlush";
++/*@}*/
++
++static const char pszStateChange[] = "StateChange";
++static const char pszStatus[] = "Status";
++
++static const char pszGET[] = "Get";
++static const char pszSET[] = "Set";
++static const char pszCLEAR[] = "Clear";
++static const char pszNULL[] = "";
++static const char pszLocator[] = "Locator";
++static const char pszOff[] = "Off";
++static const char pszOn[] = "On";
++static const char hcMaxFrags[] = "MaxFrags";
++
++#ifdef _CPHAL_CPMAC
++
++/* New method for string constants */
++const char hcClear[] = "Clear";
++const char hcGet[] = "Get";
++const char hcSet[] = "Set";
++
++const char hcTick[] = "Tick";
++
++static const CONTROL_KEY KeyCommon[] =
++ {
++ {"" , enCommonStart},
++ {pszStatus , enStatus},
++ {pszOff , enOff},
++ {pszOn , enOn},
++ {pszDebug , enDebug},
++ {hcCpuFrequency , enCpuFreq}, /*MJH~030403*/
++ {"" , enCommonEnd}
++ };
++#endif
++
++/**
++@defgroup Common_Statistics Statistics
++
++A broad array of module statistics is available. Statistics values are accessed
++through the @c Control() interface of the CPHAL. There are 5 different levels
++of statistics, each of which correspond to a unique set of data. Furthermore,
++certain statistics data is indexed by using a channel number and Tx queue number.
++The following is a brief description of each statistics level, along with the
++indexes used for the level:
++
++- Level 0: Hardware Statistics (index with channel)
++- Level 1: CPHAL Software Statistics (channel, queue)
++- Level 2: CPHAL Flags (channel, queue)
++- Level 3: CPHAL Channel Configuration (channel)
++- Level 4: CPHAL General Configuration (no index)
++
++The caller requests statistics information by providing a Key string to the
++@c Control() API in the following format: "Stats;[Level #];[Ch #];[Queue #]".
++The only valid Action parameter for statistics usage is "Get".
++
++Code Examples:
++@code
++unsigned int *StatsData;
++
++# Get Level 0 stats for Channel 1
++HalFunc->Control(OsDev->HalDev, "Stats;0;1", "Get", &StatsData);
++
++# Get Level 2 stats for Channel 0, Queue 0
++HalFunc->Control(OsDev->HalDev, "Stats;2;0;0", "Get", &StatsData);
++
++# Get Level 4 stats
++HalFunc->Control(OsDev->HalDev, "Stats;4", "Get", &StatsData);
++@endcode
++
++The information returned in the Value parameter of @c Control() is an
++array of pointers to strings. The pointers are arranged in pairs.
++The first pointer is a pointer to a name string for a particular statistic.
++The next pointer is a pointer to a string containing the representation of
++the integer statistic value corresponding to the first pointer. This is followed
++by another pair of pointers, and so on, until a NULL pointer is encountered. The
++following is example code for processing the statistics data. Note that the OS
++is responsible for freeing the memory passed back through the Value parameter of
++@c Control().
++
++@code
++unsigned int *StatsData;
++
++# Get Level 0 stats for Channel 1
++HalFunc->Control(OsDev->HalDev, "Stats;0;1", "Get", &StatsData);
++
++# output Statistics data
++PrintStats(StatsData);
++
++# the upper layer is responsible for freeing stats info
++free(&StatsPtr);
++
++...
++
++void PrintStats(unsigned int *StatsPtr)
++ {
++ while(*StatsPtr)
++ {
++ printf("%20s:", (char *)*StatsPtr);
++ StatsPtr++;
++ printf("%11s\n", (char *)*StatsPtr);
++ StatsPtr++;
++ }
++ MySioFlush();
++ }
++@endcode
++
++Within each statistics level, there are several statistics defined. The statistics that
++are common to every CPPI module are listed below. In addition, each module may define
++extra statistics in each level, which will be documented within the module-specific
++documentation appendices.
++
++- Level 0 Statistics
++ - All level 0 statistics are module-specific.
++- Level 1 Statistics (CPHAL Software Statistics)
++ - DmaLenErrors: Incremented when the port DMA's more data than expected (per channel). (AAL5 Only)
++ - TxMisQCnt: Incremented when host queues a packet for transmission as the port finishes
++transmitting the previous last packet in the queue (per channel and queue).
++ - RxMisQCnt: Incremented when host queues adds buffers to a queue as the port finished the
++reception of the previous last packet in the queue (per channel).
++ - TxEOQCnt: Number of times the port has reached the end of the transmit queue (per channel and queue).
++ - RxEOQCnt: Number of times the port has reached the end of the receive queue (per channel).
++ - RxPacketsServiced: Number of received packets (per channel).
++ - TxPacketsServiced: Number of transmitted packets (per channel and queue).
++ - RxMaxServiced: Maximum number of packets that the CPHAL receive interrupt has serviced at a time (per channel).
++ - TxMaxServiced: Maximum number of packets that the CPHAL transmit interrupt has serviced at a time (per channel and queue).
++ - RxTotal: Total number of received packets, all channels.
++ - TxTotal: Total number of transmitted packets, all channels and queues.
++- Level 2 Statistics (CPHAL Flags)
++ - RcbPool: Pointer to receive descriptor pool (per channel).
++ - RxActQueueCount: Number of buffers currently available for receive (per channel).
++ - RxActQueueHead: Pointer to first buffer in receive queue (per channel).
++ - RxActQueueTail: Pointer to last buffer in receive queue (per channel).
++ - RxActive: 0 if inactive (no buffers available), or 1 if active (buffers available).
++ - RcbStart: Pointer to block of receive descriptors.
++ - RxTeardownPending: 1 if Rx teardown is pending but incomplete, 0 otherwise.
++ - TcbPool: Pointer to transmit descriptor pool (per channel and queue).
++ - TxActQueueCount: Number of buffers currently queued to be transmitted (per channel and queue).
++ - TxActQueueHead: Pointer to first buffer in transmit queue (per channel and queue).
++ - TxActQueueTail: Pointer to last buffer in transmit queue (per channel and queue).
++ - TxActive: 0 if inactive (no buffers to send), or 1 if active (buffers queued to send).
++ - TcbStart: Pointer to block of transmit descriptors.
++ - TxTeardownPending: 1 if Tx teardown is pending but incomplete, 0 otherwise.
++- Level 3 Statistics (CPHAL Channel Configuration)
++ - RxBufSize: Rx buffer size.
++ - RxBufferOffset: Rx buffer offset.
++ - RxNumBuffers: Number of Rx buffers.
++ - RxServiceMax: Maximum number of receive packets to service at a time.
++ - TxNumBuffers: Number of Tx buffer descriptors.
++ - TxNumQueues: Number of Tx queues to use.
++ - TxServiceMax: Maximum number of transmit packets to service at a time.
++- Level 4 Statistics (CPHAL General Configuration)
++ - Base Address: Base address of the module.
++ - Offset (VLYNQ): VLYNQ relative module offset.
++ - Interrupt Line: Interrupt number.
++ - Debug: Debug flag, 1 to enable debug.
++ - Inst: Instance number.
++*/
++
++/*
++ Data Type 0 = int display
++ Data Type 1 = hex display
++ Data Type 2 = channel structure, int display
++ Data Type 3 = queue index and int display
++ Data Type 4 = queue index and hex display
++*/
++#if (defined(_CPHAL_AAL5) || defined(_CPHAL_CPMAC)) /* +GSG 030307 */
++static STATS_TABLE StatsTable0[] =
++ {
++#ifdef _CPHAL_AAL5
++ /* Name , Data Ptr, Data Type */
++ {"Crc Errors", 0, 0},
++ {"Len Errors", 0, 0},
++ {"Abort Errors", 0, 0},
++ {"Starv Errors", 0, 0}
++#endif
++#ifdef _CPHAL_CPMAC
++ {"Rx Good Frames", 0, 0}
++#endif
++ };
++
++static STATS_TABLE StatsTable1[] =
++ {
++ /* Name , Data Ptr, Data Type */
++ {"DmaLenErrors", 0, 0},
++ {"TxMisQCnt", 0, 3},
++ {"RxMisQCnt", 0, 0},
++ {"TxEOQCnt", 0, 3},
++ {"RxEOQCnt", 0, 0},
++ {"RxPacketsServiced", 0, 0},
++ {"TxPacketsServiced", 0, 3},
++ {"RxMaxServiced", 0, 0},
++ {"TxMaxServiced", 0, 3},
++ {"RxTotal", 0, 0},
++ {"TxTotal", 0, 0},
++ };
++
++static STATS_TABLE StatsTable2[] =
++ {
++ /* Name , Data Ptr, Data Type */
++ {"RcbPool", 0, 1},
++ {"RxActQueueCount", 0, 0},
++ {"RxActQueueHead", 0, 1},
++ {"RxActQueueTail", 0, 1},
++ {"RxActive", 0, 0},
++ {"RcbStart", 0, 1},
++ {"RxTeardownPending", 0, 0},
++ {"TcbPool", 0, 4},
++ {"TxActQueueCount", 0, 3},
++ {"TxActQueueHead", 0, 4},
++ {"TxActQueueTail", 0, 4},
++ {"TxActive", 0, 3},
++ {"TcbStart", 0, 4},
++ {"TxTeardownPending", 0, 0}
++ };
++
++static STATS_TABLE StatsTable3[] =
++ {
++ /* Name , Data Ptr, Data Type */
++ {"RxBufSize", 0, 2},
++ {"RxBufferOffset", 0, 2},
++ {"RxNumBuffers", 0, 2},
++ {"RxServiceMax", 0, 2},
++ {"TxNumBuffers", 0, 2},
++ {"TxNumQueues", 0, 2},
++ {"TxServiceMax", 0, 2},
++#ifdef _CPHAL_AAL5
++ {"CpcsUU", 0, 2},
++ {"Gfc", 0, 2},
++ {"Clp", 0, 2},
++ {"Pti", 0, 2},
++ {"DaMask", 0, 2},
++ {"Priority", 0, 2},
++ {"PktType", 0, 2},
++ {"Vci", 0, 2},
++ {"Vpi", 0, 2},
++ {"CellRate", 0, 2},
++ {"QosType", 0, 2},
++ {"Mbs", 0, 2},
++ {"Pcr", 0, 2}
++#endif
++ };
++
++static STATS_TABLE StatsTable4[] =
++ {
++ {"Base Address", 0, 1},
++ {"Offset (VLYNQ)", 0, 0},
++ {"Interrupt Line", 0, 0},
++ {"Debug", 0, 0},
++ {"Instance", 0, 0},
++#ifdef _CPHAL_AAL5
++ {"UniNni", 0, 0}
++#endif
++ };
++
++static STATS_DB StatsDb[] =
++ {
++ {(sizeof(StatsTable0)/sizeof(STATS_TABLE)), StatsTable0},
++ {(sizeof(StatsTable1)/sizeof(STATS_TABLE)), StatsTable1},
++ {(sizeof(StatsTable2)/sizeof(STATS_TABLE)), StatsTable2},
++ {(sizeof(StatsTable3)/sizeof(STATS_TABLE)), StatsTable3},
++ {(sizeof(StatsTable4)/sizeof(STATS_TABLE)), StatsTable4}
++ };
++#endif /* +GSG 030307 */
++
++#ifdef _CPHAL_CPMAC /* +RC 3.02 */
++static void resetWait(HAL_DEVICE *HalDev)
++ { /*+RC3.02*/
++ const int TickReset=64;
++ osfuncSleep((int*)&TickReset);
++ } /*+RC3.02*/
++#endif /* +RC 3.02 */
++
++/* I only define the reset base function for the modules
++ that can perform a reset. The AAL5 and AAL2 modules
++ do not perform a reset, that is done by the shared module
++ CPSAR */
++#if defined(_CPHAL_CPSAR) || defined(_CPHAL_CPMAC) || defined(_CPHAL_VDMAVT)
++/*
++ * Determines the reset register address to be used for a particular device.
++ * It will search the current device entry for Locator information. If the
++ * device is a root device, there will be no Locator information, and the
++ * function will find and return the root reset register. If a Locator value
++ * is found, the function will search each VLYNQ device entry in the system
++ * looking for a matching Locator. Once it finds a VLYNQ device entry with
++ * a matching Locator, it will extract the "ResetBase" parameter from that
++ * VLYNQ device entry (thus every VLYNQ entry must have the ResetBase parameter).
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ * @param ResetBase Pointer to integer address of reset register.
++ *
++ * @return 0 OK, Non-zero not OK
++ */
++static int ResetBaseGet(HAL_DEVICE *HalDev, bit32u *ResetBase)
++ {
++ char *DeviceInfo = HalDev->DeviceInfo;
++ char *MyLocator, *NextLocator;
++ int Inst=1;
++ bit32u error_code;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpcommon]ResetBaseGet(HalDev:%08x, ResetBase:%08x)\n", (bit32u)HalDev, ResetBase);
++ osfuncSioFlush();
++ }
++#endif
++
++ error_code = HalDev->OsFunc->DeviceFindParmValue(DeviceInfo, "Locator", &MyLocator);
++ if (error_code)
++ {
++ /* if no Locator value, device is on the root, so get the "reset" device */
++ error_code = HalDev->OsFunc->DeviceFindInfo(0, "reset", &DeviceInfo);
++ if (error_code)
++ {
++ return(EC_VAL_DEVICE_NOT_FOUND);
++ }
++
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, "base", ResetBase);
++ if (error_code)
++ {
++ return(EC_VAL_BASE_ADDR_NOT_FOUND);
++ }
++
++ *ResetBase = ((bit32u)PhysToVirtNoCache(*ResetBase));
++
++ /* found base address for root device, so we're done */
++ return (EC_NO_ERRORS);
++ }
++ else
++ {
++ /* we have a Locator value, so the device is remote */
++
++ /* Find a vlynq device with a matching locator value */
++ while ((HalDev->OsFunc->DeviceFindInfo(Inst, "vlynq", &DeviceInfo)) == EC_NO_ERRORS)
++ {
++ error_code = HalDev->OsFunc->DeviceFindParmValue(DeviceInfo, "Locator", &NextLocator);
++ if (error_code)
++ {
++ /* no Locator value for this VLYNQ, so move on */
++ continue;
++ }
++ if (HalDev->OsFunc->Strcmpi(MyLocator, NextLocator)==0)
++ {
++ /* we have found a VLYNQ with a matching Locator, so extract the ResetBase */
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, "ResetBase", ResetBase);
++ if (error_code)
++ {
++ return(EC_VAL_BASE_ADDR_NOT_FOUND);
++ }
++ *ResetBase = ((bit32u)PhysToVirtNoCache(*ResetBase));
++
++ /* found base address for root device, so we're done */
++ return (EC_NO_ERRORS);
++ }
++ Inst++;
++ } /* while */
++ } /* else */
++
++ return (EC_NO_ERRORS);
++ }
++#endif
++
++#ifndef _CPHAL_AAL2 /* + RC 3.02 */
++static bit32u ConfigGetCommon(HAL_DEVICE *HalDev)
++ {
++ bit32u ParmValue;
++ bit32 error_code;
++ char *DeviceInfo = HalDev->DeviceInfo;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpcommon]ConfigGetCommon(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszBase, &ParmValue);
++ if (error_code)
++ {
++ return(EC_FUNC_HAL_INIT|EC_VAL_BASE_ADDR_NOT_FOUND);
++ }
++ HalDev->dev_base = ((bit32u)PhysToVirtNoCache(ParmValue));
++
++#ifndef _CPHAL_AAL5
++#ifndef _CPHAL_AAL2
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszResetBit, &ParmValue);
++ if(error_code)
++ {
++ return(EC_FUNC_HAL_INIT|EC_VAL_RESET_BIT_NOT_FOUND);
++ }
++ HalDev->ResetBit = ParmValue;
++
++ /* Get reset base address */
++ error_code = ResetBaseGet(HalDev, &ParmValue);
++ if (error_code)
++ return(EC_FUNC_HAL_INIT|EC_VAL_RESET_BASE_NOT_FOUND);
++ HalDev->ResetBase = ParmValue;
++#endif
++#endif
++
++#ifndef _CPHAL_CPSAR
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszIntLine,&ParmValue);
++ if (error_code)
++ {
++ return(EC_FUNC_HAL_INIT|EC_VAL_INTERRUPT_NOT_FOUND);
++ }
++ HalDev->interrupt = ParmValue;
++#endif
++
++ /* only look for the offset if there is a Locator field, which indicates that
++ the module is a VLYNQ module */
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszLocator,&ParmValue);
++ if (!error_code)
++ {
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszOffset,&ParmValue);
++ if (error_code)
++ {
++ return(EC_FUNC_HAL_INIT|EC_VAL_OFFSET_NOT_FOUND);
++ }
++ HalDev->offset = ParmValue;
++ }
++ else
++ HalDev->offset = 0;
++
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszDebug, &ParmValue);
++ if (!error_code) HalDev->debug = ParmValue;
++
++ return (EC_NO_ERRORS);
++ }
++#endif /* +RC 3.02 */
++
++#ifdef _CPHAL_CPMAC /* +RC 3.02 */
++static void StatsInit(HAL_DEVICE *HalDev) /* +() RC3.02 */
++ {
++ /* even though these statistics may be for multiple channels and
++ queues, i need only configure the pointer to the beginning
++ of the array, and I can index from there if necessary */
++
++#ifdef _CPHAL_AAL5
++ StatsTable0[0].StatPtr = &HalDev->Stats.CrcErrors[0];
++ StatsTable0[1].StatPtr = &HalDev->Stats.LenErrors[0];
++ StatsTable0[2].StatPtr = &HalDev->Stats.AbortErrors[0];
++ StatsTable0[3].StatPtr = &HalDev->Stats.StarvErrors[0];
++
++ StatsTable1[0].StatPtr = &HalDev->Stats.DmaLenErrors[0];
++ StatsTable1[1].StatPtr = &HalDev->Stats.TxMisQCnt[0][0];
++ StatsTable1[2].StatPtr = &HalDev->Stats.RxMisQCnt[0];
++ StatsTable1[3].StatPtr = &HalDev->Stats.TxEOQCnt[0][0];
++ StatsTable1[4].StatPtr = &HalDev->Stats.RxEOQCnt[0];
++ StatsTable1[5].StatPtr = &HalDev->Stats.RxPacketsServiced[0];
++ StatsTable1[6].StatPtr = &HalDev->Stats.TxPacketsServiced[0][0];
++ StatsTable1[7].StatPtr = &HalDev->Stats.RxMaxServiced;
++ StatsTable1[8].StatPtr = &HalDev->Stats.TxMaxServiced[0][0];
++ StatsTable1[9].StatPtr = &HalDev->Stats.RxTotal;
++ StatsTable1[10].StatPtr = &HalDev->Stats.TxTotal;
++#endif
++
++#if (defined(_CPHAL_AAL5) || defined(_CPHAL_CPMAC))
++ StatsTable2[0].StatPtr = (bit32u *)&HalDev->RcbPool[0];
++ StatsTable2[1].StatPtr = &HalDev->RxActQueueCount[0];
++ StatsTable2[2].StatPtr = (bit32u *)&HalDev->RxActQueueHead[0];
++ StatsTable2[3].StatPtr = (bit32u *)&HalDev->RxActQueueTail[0];
++ StatsTable2[4].StatPtr = &HalDev->RxActive[0];
++ StatsTable2[5].StatPtr = (bit32u *)&HalDev->RcbStart[0];
++ StatsTable2[6].StatPtr = &HalDev->RxTeardownPending[0];
++ StatsTable2[7].StatPtr = (bit32u *)&HalDev->TcbPool[0][0];
++ StatsTable2[8].StatPtr = &HalDev->TxActQueueCount[0][0];
++ StatsTable2[9].StatPtr = (bit32u *)&HalDev->TxActQueueHead[0][0];
++ StatsTable2[10].StatPtr = (bit32u *)&HalDev->TxActQueueTail[0][0];
++ StatsTable2[11].StatPtr = &HalDev->TxActive[0][0];
++ StatsTable2[12].StatPtr = (bit32u *)&HalDev->TcbStart[0][0];
++ StatsTable2[13].StatPtr = &HalDev->TxTeardownPending[0];
++
++ StatsTable3[0].StatPtr = &HalDev->ChData[0].RxBufSize;
++ StatsTable3[1].StatPtr = &HalDev->ChData[0].RxBufferOffset;
++ StatsTable3[2].StatPtr = &HalDev->ChData[0].RxNumBuffers;
++ StatsTable3[3].StatPtr = &HalDev->ChData[0].RxServiceMax;
++ StatsTable3[4].StatPtr = &HalDev->ChData[0].TxNumBuffers;
++ StatsTable3[5].StatPtr = &HalDev->ChData[0].TxNumQueues;
++ StatsTable3[6].StatPtr = &HalDev->ChData[0].TxServiceMax;
++#ifdef _CPHAL_AAL5
++ StatsTable3[7].StatPtr = &HalDev->ChData[0].CpcsUU;
++ StatsTable3[8].StatPtr = &HalDev->ChData[0].Gfc;
++ StatsTable3[9].StatPtr = &HalDev->ChData[0].Clp;
++ StatsTable3[10].StatPtr = &HalDev->ChData[0].Pti;
++ StatsTable3[11].StatPtr = &HalDev->ChData[0].DaMask;
++ StatsTable3[12].StatPtr = &HalDev->ChData[0].Priority;
++ StatsTable3[13].StatPtr = &HalDev->ChData[0].PktType;
++ StatsTable3[14].StatPtr = &HalDev->ChData[0].Vci;
++ StatsTable3[15].StatPtr = &HalDev->ChData[0].Vpi;
++ StatsTable3[16].StatPtr = &HalDev->ChData[0].TxVc_CellRate;
++ StatsTable3[17].StatPtr = &HalDev->ChData[0].TxVc_QosType;
++ StatsTable3[18].StatPtr = &HalDev->ChData[0].TxVc_Mbs;
++ StatsTable3[19].StatPtr = &HalDev->ChData[0].TxVc_Pcr;
++#endif
++#endif
++
++ StatsTable4[0].StatPtr = &HalDev->dev_base;
++ StatsTable4[1].StatPtr = &HalDev->offset;
++ StatsTable4[2].StatPtr = &HalDev->interrupt;
++ StatsTable4[3].StatPtr = &HalDev->debug;
++ StatsTable4[4].StatPtr = &HalDev->Inst;
++ }
++#endif /* +RC 3.02 */
++
++#ifndef _CPHAL_CPSAR /* +RC 3.02 */
++#ifndef _CPHAL_AAL2 /* +RC 3.02 */
++/*
++ * Returns statistics information.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ *
++ * @return 0
++ */
++static int StatsGet(HAL_DEVICE *HalDev, void **StatPtr, int Index, int Ch, int Queue)
++ {
++ int Size;
++ bit32u *AddrPtr;
++ char *DataPtr;
++ STATS_TABLE *StatsTable;
++ int i, NumberOfStats;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpcommon]StatsGet(HalDev:%08x, StatPtr:%08x)\n",
++ (bit32u)HalDev, (bit32u)StatPtr);
++ osfuncSioFlush();
++ }
++#endif
++
++ StatsTable = StatsDb[Index].StatTable;
++ NumberOfStats = StatsDb[Index].NumberOfStats;
++
++ Size = sizeof(bit32u)*((NumberOfStats*2)+1);
++ Size += (NumberOfStats*11);
++ *StatPtr = (bit32u *)HalDev->OsFunc->Malloc(Size);
++
++ AddrPtr = (bit32u *) *StatPtr;
++ DataPtr = (char *)AddrPtr;
++ DataPtr += sizeof(bit32u)*((NumberOfStats*2)+1);
++
++ for (i=0; i<NumberOfStats; i++)
++ {
++ *AddrPtr++ = (bit32u)StatsTable[i].StatName;
++ *AddrPtr++ = (bit32u)DataPtr;
++ if (&StatsTable[i].StatPtr[Ch] != 0)
++ {
++ switch(StatsTable[i].DataType)
++ {
++ case 0:
++ HalDev->OsFunc->Sprintf(DataPtr, "%d", (bit32u *)StatsTable[i].StatPtr[Ch]);
++ break;
++ case 1:
++ HalDev->OsFunc->Sprintf(DataPtr, "0x%x", (bit32u *)StatsTable[i].StatPtr[Ch]);
++ break;
++ case 2:
++ HalDev->OsFunc->Sprintf(DataPtr, "%d", *((bit32u *)StatsTable[i].StatPtr + (Ch * (sizeof(CHANNEL_INFO)/4))));
++ break;
++ case 3:
++ HalDev->OsFunc->Sprintf(DataPtr, "%d", *((bit32u *)StatsTable[i].StatPtr + (Ch*MAX_QUEUE)+Queue));
++ break;
++ case 4:
++ HalDev->OsFunc->Sprintf(DataPtr, "0x%x", *((bit32u *)StatsTable[i].StatPtr + (Ch*MAX_QUEUE)+Queue));
++ break;
++ default:
++ /* invalid data type, due to CPHAL programming error */
++ break;
++ }
++ }
++ else
++ {
++ /* invalid statistics pointer, probably was not initialized */
++ }
++ DataPtr += HalDev->OsFunc->Strlen(DataPtr) + 1;
++ }
++
++ *AddrPtr = (bit32u) 0;
++
++ return (EC_NO_ERRORS);
++ }
++#endif /* +RC 3.02 */
++#endif /* +RC 3.02 */
++
++#ifdef _CPHAL_CPMAC
++static void gpioFunctional(int base, int bit)
++ { /*+RC3.02*/
++ bit32u GpioEnr = base + 0xC;
++ /* To make functional, set to zero */
++ *(volatile bit32u *)(GpioEnr) &= ~(1 << bit); /*+RC3.02*/
++ } /*+RC3.02*/
++
++
++/*+RC3.02*/
++/* Common function, Checks to see if GPIO should be in functional mode */
++static void gpioCheck(HAL_DEVICE *HalDev, void *moduleDeviceInfo)
++ { /*+RC3.02*/
++ int rc;
++ void *DeviceInfo;
++ char *pszMuxBits;
++ char pszMuxBit[20];
++ char *pszTmp;
++ char szMuxBit[20];
++ char *ptr;
++ int base;
++ int reset_bit;
++ int bit;
++ OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++
++ rc = OsFunc->DeviceFindParmValue(moduleDeviceInfo, "gpio_mux",&pszTmp);
++ if(rc) return;
++ /* gpio entry found, get GPIO register info and make functional */
++
++ /* temp copy until FinParmValue fixed */
++ ptr = &szMuxBit[0];
++ while ((*ptr++ = *pszTmp++));
++
++ pszMuxBits = &szMuxBit[0];
++
++ rc = OsFunc->DeviceFindInfo(0,"gpio",&DeviceInfo);
++ if(rc) return;
++
++ rc = OsFunc->DeviceFindParmUint(DeviceInfo, "base",&base);
++ if(rc) return;
++
++ rc = OsFunc->DeviceFindParmUint(DeviceInfo, "reset_bit",&reset_bit);
++ if(rc) return;
++
++ /* If GPIO still in reset, then exit */
++ if((VOLATILE32(HalDev->ResetBase) & (1 << reset_bit)) == 0)
++ return;
++ /* format for gpio_mux is gpio_mux = <int>;<int>;<int>...*/
++ while (*pszMuxBits)
++ {
++ pszTmp = &pszMuxBit[0];
++ if(*pszMuxBits == ';') pszMuxBits++;
++ while ((*pszMuxBits != ';') && (*pszMuxBits != '\0'))
++ {
++ osfuncSioFlush();
++ /*If value not a number, skip */
++ if((*pszMuxBits < '0') || (*pszMuxBits > '9'))
++ pszMuxBits++;
++ else
++ *pszTmp++ = *pszMuxBits++;
++ }
++ *pszTmp = '\0';
++ bit = OsFunc->Strtoul(pszMuxBit, &pszTmp, 10);
++ gpioFunctional(base, bit);
++ resetWait(HalDev); /* not sure if this is needed */
++ }
++ } /*+RC3.02*/
++#endif /* CPMAC */
++
++#ifdef _CPHAL_AAL5
++const char hcSarFrequency[] = "SarFreq";
++#endif
++
++#endif /* _INC */
+diff -urN linux.old/drivers/atm/sangam_atm/cpcommon_cpsar.h linux.dev/drivers/atm/sangam_atm/cpcommon_cpsar.h
+--- linux.old/drivers/atm/sangam_atm/cpcommon_cpsar.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/cpcommon_cpsar.h 2005-08-23 04:46:50.083845824 +0200
+@@ -0,0 +1,79 @@
++#ifndef _INC_CPCOMMON_H
++#define _INC_CPCOMMON_H
++
++#define VOLATILE32(addr) (*(volatile bit32u *)(addr))
++#ifndef dbgPrintf
++#define dbgPrintf HalDev->OsFunc->Printf
++#endif
++
++#define ChannelUpdate(Field) if(HalChn->Field != 0xFFFFFFFF) HalDev->ChData[Ch].Field = HalChn->Field
++
++#define DBG(level) (HalDev->debug & (1<<(level)))
++/*
++#define DBG0() DBG(0)
++#define DBG1() DBG(1)
++#define DBG2() DBG(2)
++#define DBG3() DBG(3)
++#define DBG4() DBG(4)
++#define DBG5() DBG(5)
++#define DBG6() DBG(6)
++#define DBG7() DBG(7)
++*/
++
++/*
++ * List of defined actions for use with Control().
++ */
++typedef enum
++ {
++ enGET=0, /**< Get the value associated with a key */
++ enSET, /**< Set the value associates with a key */
++ enCLEAR, /**<Clear the value */
++ enNULL /**< No data action, used to initiate a service or send a message */
++ }ACTION;
++
++/*
++ * Enumerated hardware states.
++ */
++typedef enum
++ {
++ enConnected=1, enDevFound, enInitialized, enOpened
++ }DEVICE_STATE;
++
++typedef enum
++ {
++ enCommonStart=0,
++ /* General */
++ enOff, enOn, enDebug,
++ /* Module General */
++ enCpuFreq,
++ enStatus,
++ enCommonEnd
++ }COMMON_KEY;
++
++typedef struct
++ {
++ const char *strKey;
++ int enKey;
++ }CONTROL_KEY;
++
++typedef struct
++ {
++ char *StatName;
++ unsigned int *StatPtr;
++ int DataType; /* 0: int, 1: hex int, 2:channel data */
++ }STATS_TABLE;
++
++typedef struct
++ {
++ int NumberOfStats;
++ STATS_TABLE *StatTable;
++ }STATS_DB;
++
++#define osfuncSioFlush() HalDev->OsFunc->Control(HalDev->OsDev,"SioFlush",pszNULL,0)
++#define osfuncSleep(Ticks) HalDev->OsFunc->Control(HalDev->OsDev,pszSleep,pszNULL,Ticks)
++#define osfuncStateChange() HalDev->OsFunc->Control(HalDev->OsDev,pszStateChange,pszNULL,0)
++
++#define CHANNEL_NAMES {"Ch0","Ch1","Ch2","Ch3","Ch4","Ch5","Ch6","Ch7","Ch8","Ch9","Ch10","Ch11","Ch12","Ch13","Ch14","Ch15"}
++
++#endif
++
+diff -urN linux.old/drivers/atm/sangam_atm/cppi_cpaal5.c linux.dev/drivers/atm/sangam_atm/cppi_cpaal5.c
+--- linux.old/drivers/atm/sangam_atm/cppi_cpaal5.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/cppi_cpaal5.c 2005-08-23 04:46:50.084845672 +0200
+@@ -0,0 +1,1483 @@
++/*************************************************************************
++ * TNETDxxxx Software Support
++ * Copyright (c) 2002,2003 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ * FILE: cppi.c
++ *
++ * DESCRIPTION:
++ * This file contains shared code for all CPPI modules.
++ *
++ * HISTORY:
++ * 7Aug02 Greg RC1.00 Original Version created.
++ * 27Sep02 Mick RC1.01 Merged for use by CPMAC/CPSAR
++ * 16Oct02 Mick RC1.02 Performance Tweaks (see cppihist.txt)
++ * 12Nov02 Mick RC1.02 Updated to use cpmac_reg.h
++ * 09Jan03 Mick RC3.01 Removed modification to RxBuffer ptr
++ * 28Mar03 Mick 1.03 RxReturn now returns error if Malloc Fails
++ * 10Apr03 Mick 1.03.02 Added Needs Buffer Support
++ * 11Jun03 Mick 1.06.02 halSend() errors corrected
++ *
++ * @author Greg Guyotte
++ * @version 1.00
++ * @date 7-Aug-2002
++ *****************************************************************************/
++/* each CPPI module must modify this file, the rest of the
++ code in cppi.c should be totally shared *//* Each CPPI module MUST properly define all constants shown below */
++
++/* CPPI registers */
++
++/* the following defines are not CPPI specific, but still used by cppi.c */
++
++static void FreeRx(HAL_DEVICE *HalDev, int Ch)
++ {
++ HAL_RCB *rcb_ptr; /*+GSG 030303*/
++ int rcbSize = (sizeof(HAL_RCB)+0xf)&~0xf; /*+GSG 030303*/
++ int Num = HalDev->ChData[Ch].RxNumBuffers, i; /*+GSG 030303*/
++
++ /* Free Rx data buffers attached to descriptors, if necessary */
++ if (HalDev->RcbStart[Ch] != 0) /*+GSG 030303*/
++ { /*+GSG 030303*/
++ for(i=0;i<Num;i++) /*+GSG 030303*/
++ { /*+GSG 030303*/
++ rcb_ptr = (HAL_RCB *)(HalDev->RcbStart[Ch] + (i*rcbSize)); /*+GSG 030303*/
++
++ /* free the data buffer */
++ if (rcb_ptr->DatPtr != 0)
++ {
++
++ HalDev->OsFunc->FreeRxBuffer((void *)rcb_ptr->OsInfo, (void *)rcb_ptr->DatPtr);
++ rcb_ptr->OsInfo=0; /*MJH+030522*/
++ rcb_ptr->DatPtr=0; /*MJH+030522*/
++ }
++ } /*+GSG 030303*/
++ } /*+GSG 030303*/
++
++ /* free up all desciptors at once */
++ HalDev->OsFunc->FreeDmaXfer(HalDev->RcbStart[Ch]);
++
++ /* mark buffers as freed */
++ HalDev->RcbStart[Ch] = 0;
++ }
++
++static void FreeTx(HAL_DEVICE *HalDev, int Ch, int Queue)
++ {
++
++/*+GSG 030303*/
++
++ /* free all descriptors at once */
++ HalDev->OsFunc->FreeDmaXfer(HalDev->TcbStart[Ch][Queue]);
++
++ HalDev->TcbStart[Ch][Queue] = 0;
++ }
++
++/* return of 0 means that this code executed, -1 means the interrupt was not
++ a teardown interrupt */
++static int RxTeardownInt(HAL_DEVICE *HalDev, int Ch)
++ {
++ bit32u base = HalDev->dev_base;
++
++ int i;
++ volatile bit32u *pTmp;
++
++ /* check to see if the interrupt is a teardown interrupt */
++ if (((*(pRX_CPPI_COMP_PTR( base )+( Ch *64))) & TEARDOWN_VAL) == TEARDOWN_VAL)
++ {
++ /* finish channel teardown */
++
++ /* Free channel resources on a FULL teardown */
++ if (HalDev->RxTeardownPending[Ch] & FULL_TEARDOWN)
++ {
++ FreeRx(HalDev, Ch);
++ }
++
++ /* bug fix - clear Rx channel pointers on teardown */
++ HalDev->RcbPool[Ch] = 0;
++ HalDev->RxActQueueHead[Ch] = 0;
++ HalDev->RxActQueueCount[Ch] = 0;
++ HalDev->RxActive[Ch] = FALSE;
++
++ /* write completion pointer */
++ (*(pRX_CPPI_COMP_PTR( base )+( Ch *64))) = TEARDOWN_VAL;
++
++ /* use direction bit as a teardown pending bit! May be able to
++ use only one teardown pending integer in HalDev */
++
++ HalDev->RxTeardownPending[Ch] &= ~RX_TEARDOWN;
++
++ HalDev->ChIsOpen[Ch][DIRECTION_RX] = 0;
++
++ /* call OS Teardown Complete (if TX is also done) */
++ if ((HalDev->TxTeardownPending[Ch] & TX_TEARDOWN) == 0)
++ {
++ /* mark channel as closed */
++ HalDev->ChIsOpen[Ch][DIRECTION_TX] = 0;
++
++ /* disable channel interrupt */
++ SAR_TX_MASK_CLR(HalDev->dev_base) = (1<<Ch);
++ SAR_TX_MASK_CLR(HalDev->dev_base) = (1<<(Ch+16)); /* +GSG 030307 */
++ SAR_RX_MASK_CLR(HalDev->dev_base) = (1<<Ch);
++
++ /* Clear PDSP Channel State RAM */
++ pTmp = (pPDSP_BLOCK_0(HalDev->dev_base)+(Ch*64));
++ for (i=0; i<NUM_PDSP_AAL5_STATE_WORDS; i++)
++ *pTmp++ = 0;
++
++ if ((HalDev->RxTeardownPending[Ch] & BLOCKING_TEARDOWN) == 0)
++ {
++
++ HalDev->OsFunc->TeardownComplete(HalDev->OsDev, Ch, DIRECTION_TX|DIRECTION_RX);
++ }
++ /* clear all teardown pending information for this channel */
++ HalDev->RxTeardownPending[Ch] = 0;
++ HalDev->TxTeardownPending[Ch] = 0;
++ }
++
++ return (EC_NO_ERRORS);
++ }
++ return (-1);
++ }
++
++/* return of 0 means that this code executed, -1 means the interrupt was not
++ a teardown interrupt */
++static int TxTeardownInt(HAL_DEVICE *HalDev, int Ch, int Queue)
++ {
++ bit32u base = HalDev->dev_base;
++ HAL_TCB *Last, *Curr, *First; /*+GSG 030303*/
++
++ int i;
++ volatile bit32u *pTmp;
++
++ if (((*(pTXH_CPPI_COMP_PTR( base )+( Ch *64)+( Queue ))) & TEARDOWN_VAL) == TEARDOWN_VAL)
++ {
++ /* return outstanding buffers to OS +RC3.02*/
++ Curr = HalDev->TxActQueueHead[Ch][Queue]; /*+GSG 030303*/
++ First = Curr; /*+GSG 030303*/
++ while (Curr) /*+GSG 030303*/
++ { /*+GSG 030303*/
++ /* Pop TCB(s) for packet from the stack */ /*+GSG 030303*/
++ Last = Curr->Eop; /*+GSG 030303*/
++ HalDev->TxActQueueHead[Ch][Queue] = Last->Next; /*+GSG 030303*/
++ /*+GSG 030303*/
++ /* return to OS */ /*+GSG 030303*/
++ HalDev->OsFunc->SendComplete(Curr->OsInfo); /*+GSG 030303*/
++ /*+GSG 030303*/
++ /* Push Tcb(s) back onto the stack */ /*+GSG 030303*/
++ Curr = Last->Next; /*+GSG 030303*/
++ Last->Next = HalDev->TcbPool[Ch][Queue]; /*+GSG 030303*/
++ HalDev->TcbPool[Ch][Queue] = First; /*+GSG 030303*/
++ /*+GSG 030303*/
++ /* set the first(SOP) pointer for the next packet */ /*+GSG 030303*/
++ First = Curr; /*+GSG 030303*/
++ } /*+GSG 030303*/
++
++ /* finish channel teardown */
++
++ /* save the OsInfo to pass to upper layer
++ THIS WAS CRASHING - because it's possible that I get the teardown
++ notification and the TcbHPool is null. In this case, the buffers
++ to free can be found in the TxHActiveQueue. If I need to get OsInfo
++ in the future, I can get it from one of those buffers.
++ OsInfo = HalDev->TcbHPool[Ch]->OsInfo; */
++
++ if (HalDev->TxTeardownPending[Ch] & FULL_TEARDOWN)
++ {
++ FreeTx(HalDev, Ch, Queue);
++ } /* if FULL teardown */
++
++ /* bug fix - clear Tx channel pointers on teardown */
++ HalDev->TcbPool[Ch][Queue] = 0;
++ HalDev->TxActQueueHead[Ch][Queue] = 0;
++ HalDev->TxActQueueCount[Ch][Queue] = 0;
++ HalDev->TxActive[Ch][Queue] = FALSE;
++
++ /* write completion pointer */
++ (*(pTXH_CPPI_COMP_PTR( base )+( Ch *64)+( Queue ))) = TEARDOWN_VAL;
++
++ /* no longer pending teardown */
++ HalDev->TxTeardownPending[Ch] &= ~TX_TEARDOWN;
++
++ HalDev->ChIsOpen[Ch][DIRECTION_TX] = 0;
++
++ /* call OS Teardown Complete (if Rx is also done) */
++ if ((HalDev->RxTeardownPending[Ch] & RX_TEARDOWN) == 0)
++ {
++ /* mark channel as closed */
++ HalDev->ChIsOpen[Ch][DIRECTION_RX] = 0;
++
++ /* disable channel interrupt */
++ SAR_TX_MASK_CLR(HalDev->dev_base) = (1<<Ch);
++ SAR_TX_MASK_CLR(HalDev->dev_base) = (1<<(Ch+16)); /* +GSG 030307 */
++ SAR_RX_MASK_CLR(HalDev->dev_base) = (1<<Ch);
++
++ /* Clear PDSP Channel State RAM */
++ pTmp = (pPDSP_BLOCK_0(HalDev->dev_base)+(Ch*64));
++ for (i=0; i<NUM_PDSP_AAL5_STATE_WORDS; i++)
++ *pTmp++ = 0;
++
++ if ((HalDev->TxTeardownPending[Ch] & BLOCKING_TEARDOWN) == 0)
++ {
++
++ HalDev->OsFunc->TeardownComplete(HalDev->OsDev, Ch, DIRECTION_TX|DIRECTION_RX);
++ }
++
++ /* clear all teardown pending information for this channel */
++ HalDev->RxTeardownPending[Ch] = 0;
++ HalDev->TxTeardownPending[Ch] = 0;
++ }
++
++ return (EC_NO_ERRORS);
++ }
++ return (-1);
++ }
++
++/* +GSG 030421 */
++static void AddToRxQueue(HAL_DEVICE *HalDev, HAL_RCB *FirstRcb, HAL_RCB *LastRcb, int FragCount, int Ch)
++ {
++ HAL_RCB *OldTailRcb;
++
++ if (HalDev->RxActQueueCount[Ch]==0)
++ {
++
++ HalDev->RxActQueueHead[Ch]=FirstRcb;
++ HalDev->RxActQueueTail[Ch]=LastRcb;
++ HalDev->RxActQueueCount[Ch]=FragCount;
++ if ((!HalDev->InRxInt[Ch])&&(!HalDev->RxActive[Ch]))
++ {
++ /* write Rx Queue Head Descriptor Pointer */
++ (*(pRX_DMA_STATE_WORD_1( HalDev->dev_base )+( Ch *64))) = VirtToPhys(FirstRcb) - HalDev->offset;
++ HalDev->RxActive[Ch]=TRUE;
++ }
++ }
++ else
++ {
++
++ OldTailRcb=HalDev->RxActQueueTail[Ch];
++ OldTailRcb->Next=(void *)FirstRcb;
++
++ /* Emerald fix 10/29 (Denis) */
++ *((bit32u *) VirtToVirtNoCache(&OldTailRcb->HNext))=VirtToPhys(FirstRcb) - HalDev->offset;
++
++ HalDev->RxActQueueTail[Ch]=LastRcb;
++ HalDev->RxActQueueCount[Ch]+=FragCount;
++ }
++ }
++
++/**
++ * @ingroup CPHAL_Functions
++ * This function is called to indicate to the CPHAL that the upper layer
++ * software has finished processing the receive data (given to it by
++ * osReceive()). The CPHAL will then return the appropriate receive buffers
++ * and buffer descriptors to the available pool.
++ *
++ * @param HalReceiveInfo Start of receive buffer descriptor chain returned to
++ * CPHAL.
++ * @param StripFlag Flag indicating whether the upper layer software has
++ * retained ownership of the receive data buffers.
++ *<BR>
++ * 'FALSE' means that the CPHAL can reuse the receive data buffers.
++ *<BR>
++ * 'TRUE' : indicates the data buffers were retained by the OS
++ *<BR>
++ * NOTE: If StripFlag is TRUE, it is the responsibility of the upper layer software to free the buffers when they are no longer needed.
++ *
++ * @return EC_NO_ERRORS (ok). <BR>
++ * Possible Error Codes:<BR>
++ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ * @ref EC_VAL_RCB_NEEDS_BUFFER "EC_VAL_RCB_NEEDS_BUFFER"<BR>
++ * @ref EC_VAL_RCB_DROPPED "EC_VAL_RCB_DROPPED"<BR>
++ */
++static int halRxReturn(HAL_RECEIVEINFO *HalReceiveInfo,
++ int StripFlag)
++ {
++ int Ch = HalReceiveInfo->Ch, i;
++ HAL_RCB *LastRcb, *TempRcb;
++ char *pBuf;
++ HAL_RCB *CurrHeadRcb = HalReceiveInfo, *LastGoodRcb=0; /* +GSG 030421 */
++ HAL_DEVICE *HalDev = HalReceiveInfo->HalDev;
++ int RcbSize = HalDev->ChData[Ch].RxBufSize;
++ int FragCount = HalReceiveInfo->FragCount;
++ int rc=0; /*MJH+030417*/
++ int GoodCount=0; /*GSG+030421*/
++
++ if (HalDev->State != enOpened)
++ return(EC_AAL5 |EC_FUNC_RXRETURN|EC_VAL_INVALID_STATE);
++
++ LastRcb=(HAL_RCB *)HalReceiveInfo->Eop;
++ LastRcb->HNext=0;
++ LastRcb->Next=0;
++
++ if (FragCount>1)
++ {
++ LastRcb->Off_BLen=RcbSize;
++ LastRcb->mode=CB_OWNERSHIP_BIT;
++ }
++
++ HalReceiveInfo->Off_BLen=RcbSize;
++ HalReceiveInfo->mode=CB_OWNERSHIP_BIT;
++
++ /* If OS has kept the buffers for this packet, attempt to alloc new buffers */
++ if (StripFlag)
++ {
++ TempRcb = HalReceiveInfo;
++ for (i=0; i<FragCount; i++)
++ {
++ if (TempRcb == 0)
++ {
++ dbgPrintf("Rx Return error while allocating new buffers\n");
++ dbgPrintf("Rcb = %08x, Rcb->Eop = %08x, FragCount = %d:%d\n",
++ (bit32u)HalReceiveInfo, (bit32u)HalReceiveInfo->Eop, FragCount,i);
++ osfuncSioFlush();
++
++ return(EC_CPPI|EC_FUNC_RXRETURN|EC_VAL_CORRUPT_RCB_CHAIN);
++ }
++
++ /* size = ((RcbSize+15) & ~15) + 15;*/ /*-3.01b*/
++ /*size = RcbSize + 15;*/ /* -GSG 030421 */
++ pBuf= (char *) HalDev->OsFunc->MallocRxBuffer(RcbSize,0,
++ 0xF,HalDev->ChData[Ch].OsSetup,
++ (void *)TempRcb,
++ (void *)&TempRcb->OsInfo,
++ (void *) HalDev->OsDev);
++ if (!pBuf)
++ {
++ /* malloc failed, add this RCB to Needs Buffer List */
++ TempRcb->FragCount = 1; /*MJH+030417*/
++ (HAL_RCB *)TempRcb->Eop = TempRcb; /* GSG +030430 */
++
++ if(HalDev->NeedsCount < MAX_NEEDS) /* +MJH 030410 */
++ { /* +MJH 030410 */
++ HalDev->Needs[HalDev->NeedsCount] = (HAL_RECEIVEINFO *) TempRcb; /* +MJH 030410 */
++ HalDev->NeedsCount++; /* +MJH 030410 */
++ rc = (EC_CPPI|EC_FUNC_RXRETURN|EC_VAL_RCB_NEEDS_BUFFER); /* ~MJH 030417 */
++ } /* +MJH 030410 */
++ else /* +MJH 030410 */
++ rc = (EC_CPPI|EC_FUNC_RXRETURN|EC_VAL_RCB_DROPPED); /* ~MJH 030417 */
++
++ /* requeue any previous RCB's that were ready to go before this one */
++ if (GoodCount > 0) /* +GSG 030421 */
++ { /* +GSG 030421 */
++ LastGoodRcb->HNext=0; /* +GSG 030430 */
++ LastGoodRcb->Next=0; /* +GSG 030430 */
++ osfuncDataCacheHitWriteback((void *)LastGoodRcb, 16); /* +GSG 030430 */
++
++ AddToRxQueue(HalDev, CurrHeadRcb, LastGoodRcb, GoodCount, Ch); /* +GSG 030421 */
++ GoodCount = 0; /* +GSG 030421 */
++ } /* +GSG 030421 */
++
++ CurrHeadRcb = TempRcb->Next; /* +GSG 030421 */
++ }
++ else /* +GSG 030421 */
++ { /* +GSG 030421 */
++ /* malloc succeeded, requeue the RCB to the hardware */
++ TempRcb->BufPtr=VirtToPhys(pBuf) - HalDev->offset;
++ TempRcb->DatPtr=pBuf;
++ /* Emerald fix 10/29 */
++ osfuncDataCacheHitWriteback((void *)TempRcb, 16);
++
++ /* i store the last good RCB in case the malloc fails for the
++ next fragment. This ensures that I can go ahead and return
++ a partial chain of RCB's to the hardware */
++ LastGoodRcb = TempRcb; /* +GSG 030421 */
++ GoodCount++; /* +GSG 030421 */
++ } /* +GSG 030421 */
++ TempRcb = TempRcb->Next;
++ } /* end of Frag loop */
++ /* if there any good RCB's to requeue, do so here */
++ if (GoodCount > 0) /* +GSG 030421 */
++ {
++ AddToRxQueue(HalDev, CurrHeadRcb, LastGoodRcb, GoodCount, Ch); /* +GSG 030421 */
++ }
++ return(rc); /* ~GSG 030421 */
++ }
++ else
++ {
++ /* Not Stripping */
++ /* Emerald */
++ /* Write Back SOP and last RCB */
++ osfuncDataCacheHitWriteback((void *)HalReceiveInfo, 16);
++
++ if (FragCount > 1)
++ {
++ osfuncDataCacheHitWriteback((void *)LastRcb, 16);
++ }
++ /* if not stripping buffers, always add to queue */
++ AddToRxQueue(HalDev, HalReceiveInfo, LastRcb, FragCount, Ch); /*MJH~030520*/
++ }
++
++ return(EC_NO_ERRORS);
++ }
++
++/* +MJH 030410
++ Trys to liberate an RCB until liberation fails.
++ Note: If liberation fails then RxReturn will re-add the RCB to the
++ Needs list.
++*/
++static void NeedsCheck(HAL_DEVICE *HalDev)
++{
++ HAL_RECEIVEINFO* HalRcb;
++ int rc;
++ HalDev->OsFunc->CriticalOn();
++ while(HalDev->NeedsCount)
++ {
++ HalDev->NeedsCount--;
++ HalRcb = HalDev->Needs[HalDev->NeedsCount];
++ rc = halRxReturn(HalRcb, 1);
++ /* short circuit if RxReturn starts to fail */
++ if (rc != 0)
++ break;
++ }
++ HalDev->OsFunc->CriticalOff();
++}
++
++/*
++ * This function allocates transmit buffer descriptors (internal CPHAL function).
++ * It creates a high priority transmit queue by default for a single Tx
++ * channel. If QoS is enabled for the given CPHAL device, this function
++ * will also allocate a low priority transmit queue.
++ *
++ * @param HalDev CPHAL module instance. (set by cphalInitModule())
++ * @param Ch Channel number.
++ *
++ * @return 0 OK, Non-Zero Not OK
++ */
++static int InitTcb(HAL_DEVICE *HalDev, int Ch)
++ {
++ int i, Num = HalDev->ChData[Ch].TxNumBuffers;
++ HAL_TCB *pTcb=0;
++ char *AllTcb;
++ int tcbSize, Queue;
++ int SizeMalloc;
++
++ tcbSize = (sizeof(HAL_TCB)+0xf)&~0xf;
++ SizeMalloc = (tcbSize*Num)+0xf;
++
++ for (Queue=0; Queue < HalDev->ChData[Ch].TxNumQueues; Queue++)
++ {
++ if (HalDev->TcbStart[Ch][Queue] == 0)
++ {
++
++ /* malloc all TCBs at once */
++ AllTcb = (char *)HalDev->OsFunc->MallocDmaXfer(SizeMalloc,0,0xffffffff);
++ if (!AllTcb)
++ {
++ return(EC_CPPI|EC_FUNC_HAL_INIT|EC_VAL_TCB_MALLOC_FAILED);
++ }
++
++ HalDev->OsFunc->Memset(AllTcb, 0, SizeMalloc);
++
++ /* keep this address for freeing later */
++ HalDev->TcbStart[Ch][Queue] = AllTcb;
++ }
++ else
++ {
++ /* if the memory has already been allocated, simply reuse it! */
++ AllTcb = HalDev->TcbStart[Ch][Queue];
++ }
++
++ /* align to cache line */
++ AllTcb = (char *)(((bit32u)AllTcb + 0xf) &~ 0xf); /*PITS #143 MJH~030522*/
++
++ /* default High priority transmit queue */
++ HalDev->TcbPool[Ch][Queue]=0;
++ for(i=0;i<Num;i++)
++ {
++ /*pTcb=(HAL_TCB *) OsFunc->MallocDmaXfer(sizeof(HAL_TCB),0,0xffffffff); */
++ pTcb= (HAL_TCB *)(AllTcb + (i*tcbSize));
++ pTcb->mode=0;
++ pTcb->BufPtr=0;
++ pTcb->Next=HalDev->TcbPool[Ch][Queue];
++ pTcb->Off_BLen=0;
++ HalDev->TcbPool[Ch][Queue]=pTcb;
++ }
++ /*HalDev->TcbEnd = pTcb;*/
++ }
++
++ return(EC_NO_ERRORS);
++ }
++
++/*
++ * This function allocates receive buffer descriptors (internal CPHAL function).
++ * After allocation, the function 'queues' (gives to the hardware) the newly
++ * created receive buffers to enable packet reception.
++ *
++ * @param HalDev CPHAL module instance. (set by cphalInitModule())
++ * @param Ch Channel number.
++ *
++ * @return 0 OK, Non-Zero Not OK
++ */
++static int InitRcb(HAL_DEVICE *HalDev, int Ch)
++ {
++ int i, Num = HalDev->ChData[Ch].RxNumBuffers;
++ int Size = HalDev->ChData[Ch].RxBufSize;
++ HAL_RCB *pRcb;
++ char *pBuf;
++ char *AllRcb;
++ int rcbSize;
++ int DoMalloc = 0;
++ int SizeMalloc;
++ int MallocSize;
++
++ rcbSize = (sizeof(HAL_RCB)+0xf)&~0xf;
++ SizeMalloc = (rcbSize*Num)+0xf;
++
++ if (HalDev->RcbStart[Ch] == 0)
++ {
++ DoMalloc = 1;
++
++ /* malloc all RCBs at once */
++ AllRcb= (char *)HalDev->OsFunc->MallocDmaXfer(SizeMalloc,0,0xffffffff);
++ if (!AllRcb)
++ {
++ return(EC_CPPI|EC_FUNC_HAL_INIT|EC_VAL_RCB_MALLOC_FAILED);
++ }
++
++ HalDev->OsFunc->Memset(AllRcb, 0, SizeMalloc);
++
++ /* keep this address for freeing later */
++ HalDev->RcbStart[Ch] = AllRcb;
++ }
++ else
++ {
++ /* if the memory has already been allocated, simply reuse it! */
++ AllRcb = HalDev->RcbStart[Ch];
++ }
++
++ /* align to cache line */
++ AllRcb = (char *)(((bit32u)AllRcb + 0xf)&~0xf); /*PITS #143 MJH~030522*/
++
++ HalDev->RcbPool[Ch]=0;
++ for(i=0;i<Num;i++)
++ {
++ pRcb = (HAL_RCB *)(AllRcb + (i*rcbSize));
++
++ if (DoMalloc == 1)
++ {
++
++ MallocSize = Size; /*~3.01 */
++ pBuf= (char *) HalDev->OsFunc->MallocRxBuffer(MallocSize,0,0xF,HalDev->ChData[Ch].OsSetup, (void *)pRcb, (void *)&pRcb->OsInfo, (void *) HalDev->OsDev);
++ if(!pBuf)
++ {
++ return(EC_CPPI|EC_FUNC_HAL_INIT|EC_VAL_RX_BUFFER_MALLOC_FAILED);
++ }
++ /* -RC3.01 pBuf = (char *)(((bit32u)pBuf+0xF) & ~0xF); */
++ pRcb->BufPtr=VirtToPhys(pBuf) - HalDev->offset;
++ pRcb->DatPtr=pBuf;
++ /*pRcb->BufSize=Size;*/
++ }
++ pRcb->mode=0;
++ pRcb->Ch=Ch;
++ pRcb->Next=(void *)HalDev->RcbPool[Ch];
++ pRcb->Off_BLen=0;
++ pRcb->HalDev = HalDev;
++ HalDev->RcbPool[Ch]=pRcb;
++ }
++
++ /* Give all of the Rx buffers to hardware */
++
++ while(HalDev->RcbPool[Ch])
++ {
++ pRcb=HalDev->RcbPool[Ch];
++ HalDev->RcbPool[Ch]=pRcb->Next;
++ pRcb->Eop=(void*)pRcb;
++ pRcb->FragCount=1;
++ halRxReturn((HAL_RECEIVEINFO *)pRcb, 0);
++ }
++
++ return(EC_NO_ERRORS);
++ }
++
++/**
++ * @ingroup CPHAL_Functions
++ * This function transmits the data in FragList using available transmit
++ * buffer descriptors. More information on the use of the Mode parameter
++ * is available in the module-specific appendices. Note: The OS should
++ * not call Send() for a channel that has been requested to be torndown.
++ *
++ * @param HalDev CPHAL module instance. (set by cphalInitModule())
++ * @param FragList Fragment List structure.
++ * @param FragCount Number of fragments in FragList.
++ * @param PacketSize Number of bytes to transmit.
++ * @param OsSendInfo OS Send Information structure. <BR>
++ * @param Mode 32-bit value with the following bit fields: <BR>
++ * 31-16: Mode (used for module specific data). <BR>
++ * 15-08: Queue (transmit queue to send on). <BR>
++ * 07-00: Channel (channel number to send on).
++ *
++ * @return EC_NO_ERRORS (ok). <BR>
++ * Possible Error Codes:<BR>
++ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ * @ref EC_VAL_NOT_LINKED "EC_VAL_NOT_LINKED"<BR>
++ * @ref EC_VAL_INVALID_CH "EC_VAL_INVALID_CH"<BR>
++ * @ref EC_VAL_OUT_OF_TCBS "EC_VAL_OUT_OF_TCBS"<BR>
++ * @ref EC_VAL_NO_TCBS "EC_VAL_NO_TCBS"<BR>
++ */
++static int halSend(HAL_DEVICE *HalDev,FRAGLIST *FragList,
++ int FragCount,int PacketSize, OS_SENDINFO *OsSendInfo,
++ bit32u Mode)
++ {
++ HAL_TCB *tcb_ptr, *head;
++ int i;
++ bit32u base = HalDev->dev_base;
++ int rc = EC_NO_ERRORS;
++ int Ch = Mode & 0xFF;
++ int Queue = (Mode>>8)&0xFF;
++
++ int WaitFlag = (Mode>>30)&1; /* This is for AAL5 testing only */ /* ~GSG 030508 */
++ int Offset = (FragList[0].len >> 16);
++ int PktType = (Mode>>16)&3; /* 0=AAL5, 1=Null AAL, 2=OAM, 3=Transparent */ /* +GSG 030508 */
++ int AtmHeaderInData = (Mode>>31)&1; /* +GSG 030508 */
++ int FragIndex = 0;
++
++ if (HalDev->State != enOpened)
++ return(EC_CPPI|EC_FUNC_SEND|EC_VAL_INVALID_STATE);
++
++ if (HalDev->ChIsOpen[Ch][DIRECTION_TX] == 0) /*MJH~030611*/ /*PITS 148*/
++ return(EC_AAL5 |EC_FUNC_SEND|EC_VAL_INVALID_CH); /*+GSG 030303*/
++
++ HalDev->OsFunc->CriticalOn();
++
++ tcb_ptr = head = HalDev->TcbPool[Ch][Queue];
++
++ if (tcb_ptr)
++ {
++
++ /* these two TCB words are only valid on SOP */
++ if (AtmHeaderInData == 1)
++ {
++ tcb_ptr->AtmHeader = 0; /* bug fix for transparent mode PTI problem */
++ /* Expect AtmHeader in the data */
++ tcb_ptr->AtmHeader |= *((bit8u *)FragList[FragIndex].data++) << 24;
++ tcb_ptr->AtmHeader |= *((bit8u *)FragList[FragIndex].data++) << 16;
++ tcb_ptr->AtmHeader |= *((bit8u *)FragList[FragIndex].data++) << 8;
++ tcb_ptr->AtmHeader |= *((bit8u *)FragList[FragIndex].data++);
++
++ /* decrement data buffer length accordingly */
++ FragList[FragIndex].len -= ATM_HEADER_SIZE;
++
++ /* if the first fragment was ATM Header only, go to next fragment for loop */
++ if (FragList[FragIndex].len == 0)
++ FragIndex++;
++
++ /* No CPCS_UU/CPI if not AAL5 */
++ tcb_ptr->Word5 = ((PktType & 0x3)<<16);
++ }
++ else
++ {
++ /* calculate AtmHeader from fields */
++ tcb_ptr->AtmHeader = atmheader(HalDev->ChData[Ch].Gfc, /* ~GSG 030306 */
++ HalDev->ChData[Ch].Vpi, HalDev->ChData[Ch].Vci,
++ HalDev->ChData[Ch].Pti, HalDev->ChData[Ch].Clp);
++
++ tcb_ptr->Word5 = HalDev->ChData[Ch].CpcsUU | ((HalDev->ChData[Ch].PktType &0x3)<<16);
++ }
++
++ for (i=FragIndex; i<FragCount; i++)
++
++ {
++ /* Setup Tx mode and size */
++ tcb_ptr->HNext = VirtToPhys((bit32 *)tcb_ptr->Next) - HalDev->offset;
++ tcb_ptr->Off_BLen = FragList[i].len;
++
++ if (i==0)
++ tcb_ptr->Off_BLen |= (Offset << 16);
++
++ tcb_ptr->mode = 0; /* MUST clear this for each frag !!! */
++ tcb_ptr->BufPtr = VirtToPhys((bit32 *)FragList[i].data) -
++ HalDev->offset;
++
++ /* first fragment */
++ if (i == 0)
++ {
++ tcb_ptr->mode |= CB_SOF_BIT;
++
++ }
++
++ tcb_ptr->mode |= (PacketSize | CB_OWNERSHIP_BIT);
++ tcb_ptr->OsInfo = OsSendInfo;
++
++ if (i == (FragCount - 1))
++ {
++ /* last fragment */
++ tcb_ptr->mode |= CB_EOF_BIT;
++
++ /* since this is the last fragment, set the TcbPool pointer before
++ nulling out the Next pointers */
++
++ HalDev->TcbPool[Ch][Queue] = tcb_ptr->Next;
++
++ tcb_ptr->Next = 0;
++ tcb_ptr->HNext = 0;
++
++ /* In the Tx Interrupt handler, we will need to know which TCB is EOP,
++ so we can save that information in the SOP */
++ head->Eop = tcb_ptr;
++
++ /* Emerald fix 10/29 */
++ osfuncDataCacheHitWriteback((void *)tcb_ptr, 16);
++
++ osfuncDataCacheHitWriteback((void *)((bit32u)tcb_ptr + 16), 16);
++
++ }
++ else
++ {
++ /* Emerald fix 10/29 */
++ osfuncDataCacheHitWriteback((void *)tcb_ptr, 16);
++
++ osfuncDataCacheHitWriteback((void *)((bit32u)tcb_ptr + 16), 16);
++
++ tcb_ptr = tcb_ptr->Next; /* what about the end of TCB list?? */
++
++ if (tcb_ptr == 0)
++ {
++ rc = EC_CPPI|EC_FUNC_SEND|EC_VAL_OUT_OF_TCBS;
++ goto ExitSend;
++ }
++ }
++ } /* for */
++
++ /* put it on the high priority queue */
++ if (HalDev->TxActQueueHead[Ch][Queue] == 0)
++ {
++ HalDev->TxActQueueHead[Ch][Queue]=head;
++ HalDev->TxActQueueTail[Ch][Queue]=tcb_ptr;
++/*+GSG 030303*//*+GSG 030303*/
++ if (!HalDev->TxActive[Ch][Queue])
++ {
++
++ if (!WaitFlag)
++ {
++
++ /* write CPPI TX HDP */
++ (*(pTX_DMA_STATE_WORD_0( base )+( Ch *64)+( Queue ))) = VirtToPhys(head) - HalDev->offset;
++ HalDev->TxActive[Ch][Queue]=TRUE;
++
++ }
++
++ }
++ }
++ else
++ {
++ HalDev->TxActQueueTail[Ch][Queue]->Next=head;
++ /* Emerald fix 10/29 */
++ *((bit32u *) VirtToVirtNoCache(&HalDev->TxActQueueTail[Ch][Queue]->HNext))=VirtToPhys(head) - HalDev->offset;
++ HalDev->TxActQueueTail[Ch][Queue]=tcb_ptr;
++/*+GSG 030303*//*+GSG 030303*/
++ }
++ rc = EC_NO_ERRORS;
++ goto ExitSend;
++ } /* if (tcb_ptr) */
++ else
++ {
++ rc = EC_CPPI|EC_FUNC_SEND|EC_VAL_NO_TCBS;
++ goto ExitSend;
++ }
++ExitSend:
++
++ HalDev->OsFunc->CriticalOff();
++ return(rc);
++ }
++
++/*
++ * This function processes receive interrupts. It traverses the receive
++ * buffer queue, extracting the data and passing it to the upper layer software via
++ * osReceive(). It handles all error conditions and fragments without valid data by
++ * immediately returning the RCB's to the RCB pool.
++ *
++ * @param HalDev CPHAL module instance. (set by cphalInitModule())
++ * @param Ch Channel Number.
++ * @param MoreWork Flag that indicates that there is more work to do when set to 1.
++ *
++ * @return 0 if OK, non-zero otherwise.
++ */
++static int RxInt(HAL_DEVICE *HalDev, int Ch, int *MoreWork)
++ {
++ HAL_RCB *CurrentRcb, *LastRcb=0, *SopRcb, *EofRcb, *EopRcb;
++ bit32u RxBufStatus,PacketsServiced, RxPktLen = 0, RxSopStatus,
++ FrmFrags, TotalFrags, CurrDmaLen, DmaLen, FrmLen;
++ int base = HalDev->dev_base, Ret;
++ OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++ int RxServiceMax = HalDev->ChData[Ch].RxServiceMax;
++ int FragIndex; /* +GSG 030508 */
++ int EarlyReturn = 0; /* +GSG 030521 */
++
++ bit32u PktType, ExpDmaSize, Cells;
++ int PassHeader=0;
++
++ int mode;
++
++ bit32u SopOffset;
++
++ if(HalDev->NeedsCount) /* +MJH 030410 */
++ NeedsCheck(HalDev); /* +MJH 030410 */
++
++ /* Handle case of teardown interrupt */
++ if (HalDev->RxTeardownPending[Ch] != 0)
++ {
++ Ret = RxTeardownInt(HalDev, Ch);
++ if (Ret == 0)
++ { /*+GSG 030303*/
++ *MoreWork = 0; /* bug fix 1/6 */ /*+GSG 030303*/
++ return (EC_NO_ERRORS);
++ } /*+GSG 030303*/
++ }
++
++ CurrentRcb=HalDev->RxActQueueHead[Ch];
++
++ osfuncDataCacheHitInvalidate((void*)CurrentRcb, 16);
++
++ RxBufStatus=CurrentRcb->mode;
++
++ /* I think I need to do this to ensure that i read UuCpi properly,
++ which is on the second cache line of the Rcb */
++ osfuncDataCacheHitInvalidate((void*)((bit32u)CurrentRcb+16), 16);
++
++ PacketsServiced=0;
++ HalDev->InRxInt[Ch]=TRUE;
++
++ while((CurrentRcb)&&((RxBufStatus&CB_OWNERSHIP_BIT)==0)&&
++ (PacketsServiced<RxServiceMax)) /* ~GSG 030307 */
++ {
++
++ PacketsServiced++; /* ~GSG 030307 */
++ SopRcb=CurrentRcb;
++ RxSopStatus=RxBufStatus;
++
++ RxPktLen = RxSopStatus&CB_SIZE_MASK;
++ /* Not sure what MAC needs to do for next block */
++
++ PktType=((SopRcb->UuCpi & 0x00030000) >> 16); /* GSG ~030508 */
++ /* Calculate the expected DMA length */
++ if (RxPktLen != 0)
++ {
++ Cells=RxPktLen/48;
++ if ((RxPktLen%48) > 40)
++ Cells++;
++ if (PktType == PKT_TYPE_AAL5) /* ~GSG 030508 */
++ Cells++;
++ ExpDmaSize=Cells*48;
++ }
++ else
++ {
++ ExpDmaSize=0;
++ }
++
++ SopOffset=(SopRcb->Off_BLen&CB_OFFSET_MASK)>>16;
++
++ CurrDmaLen=0;
++ FrmFrags=0;
++ TotalFrags=0;
++ FragIndex=0;
++ FrmLen=0;
++ EofRcb=0;
++
++/* +GSG 030508 */
++ if ((PktType == PKT_TYPE_OAM) || (PktType == PKT_TYPE_TRANS)) /* +GSG 030508 */
++ { /* +GSG 030508 */
++ /* first frag is ATM Header */ /* +GSG 030508 */
++ PassHeader = 1; /* +GSG 030508 */
++ HalDev->fraglist[FragIndex].data = (void *)&SopRcb->AtmHeader; /* +GSG 030508 */
++ HalDev->fraglist[FragIndex].len = 4; /* +GSG 030508 */
++ HalDev->fraglist[FragIndex].OsInfo = SopRcb->OsInfo; /* +GSG 030701 */
++ FragIndex++; /* +GSG 030508 */
++ } /* +GSG 030508 */
++/* +GSG 030508 */
++
++ do
++ {
++
++ DmaLen=CurrentRcb->Off_BLen&CB_SIZE_MASK;
++
++ CurrDmaLen+=DmaLen;
++ FrmLen+=DmaLen;
++ TotalFrags++;
++ if (!EofRcb)
++ {
++ HalDev->fraglist[FragIndex].data=((char *)CurrentRcb->DatPtr); /* ~GSG 030508 */
++
++ HalDev->fraglist[FragIndex].data+=((FrmFrags==0)?SopOffset:0); /* ~GSG 030508 */
++
++ HalDev->fraglist[FragIndex].len=DmaLen; /* ~GSG 030508 */
++
++ /* GSG 12/9 */
++ HalDev->fraglist[FragIndex].OsInfo = CurrentRcb->OsInfo; /* ~GSG 030508 */
++
++ /* Upper layer must do the data invalidate */
++
++ FrmFrags++;
++ FragIndex++; /* ~GSG 030508 */
++ if (FrmLen>=RxPktLen)
++ EofRcb=CurrentRcb;
++ }
++ LastRcb=CurrentRcb;
++ CurrentRcb=LastRcb->Next;
++ if (CurrentRcb)
++ {
++ osfuncDataCacheHitInvalidate((void*)CurrentRcb,16);
++ /* RxBufStatus=CurrentRcb->mode; */ /*DRB~030522*/
++ }
++ }while(((LastRcb->mode&CB_EOF_BIT)==0)&&(CurrentRcb));
++
++ /* New location for interrupt acknowledge */
++ /* Write the completion pointer */
++ (*(pRX_CPPI_COMP_PTR( base )+( Ch *64))) = VirtToPhys(LastRcb) - HalDev->offset;
++
++ EopRcb=LastRcb;
++ HalDev->RxActQueueHead[Ch]=CurrentRcb;
++ HalDev->RxActQueueCount[Ch]-=TotalFrags;
++
++ if (LastRcb->mode&CB_EOQ_BIT)
++ {
++ if (CurrentRcb)
++ {
++
++ HalDev->Stats.RxMisQCnt[Ch]++;
++
++ (*(pRX_DMA_STATE_WORD_1( base )+( Ch *64))) = LastRcb->HNext;
++ }
++ else
++ {
++
++ /* Rx EOQ */
++ HalDev->Stats.RxMisQCnt[Ch]++;
++
++ HalDev->RxActive[Ch]=FALSE;
++ }
++ }
++
++ EopRcb->Next=0;
++
++ /* setup SopRcb for the packet */
++ SopRcb->Eop=(void*)EopRcb;
++ SopRcb->FragCount=TotalFrags;
++
++ if ((ExpDmaSize!=CurrDmaLen)||(RxSopStatus&RX_ERROR_MASK))
++ {
++ /* check for Rx errors (only valid on SOP) */
++ if (RxSopStatus & RX_ERROR_MASK)
++ {
++ if (RxSopStatus & CRC_ERROR_MASK)
++ HalDev->Stats.CrcErrors[Ch]++;
++
++ if (RxSopStatus & LENGTH_ERROR_MASK)
++ HalDev->Stats.LenErrors[Ch]++;
++
++ if (RxSopStatus & ABORT_ERROR_MASK)
++ HalDev->Stats.AbortErrors[Ch]++;
++
++ if (RxSopStatus & STARV_ERROR_MASK)
++ HalDev->Stats.StarvErrors[Ch]++;
++ }
++ else
++ {
++ HalDev->Stats.DmaLenErrors[Ch]++; /* different type of length error */
++ }
++
++ EarlyReturn = 1;
++ }
++
++ /* do not pass up the packet if we're out of RCB's (or have an errored packet)*/
++ if ((CurrentRcb == 0) || (EarlyReturn == 1))
++ {
++ halRxReturn((HAL_RECEIVEINFO *)SopRcb,0);
++ }
++ else
++ {
++
++ if (EopRcb!=EofRcb)
++ {
++ HAL_RCB *FirstEmptyRcb;
++
++ FirstEmptyRcb = EofRcb->Next;
++ FirstEmptyRcb->Eop = (void*)EopRcb;
++ FirstEmptyRcb->FragCount = TotalFrags-FrmFrags;
++
++ halRxReturn((HAL_RECEIVEINFO *)FirstEmptyRcb,0);
++ SopRcb->Eop=(void*)EofRcb;
++ SopRcb->FragCount=FrmFrags;
++ EofRcb->Next=0; /* Optional */
++ }
++
++ mode = Ch | (PktType << 16) | (PassHeader << 31); /* ~GSG 030508 */
++
++ OsFunc->Receive(HalDev->OsDev,HalDev->fraglist,FragIndex,RxPktLen, /* ~GSG 030508 */
++ (HAL_RECEIVEINFO *)SopRcb,mode);
++ } /* else */
++
++ if (CurrentRcb) /*MJH+030522*/
++ {
++ RxBufStatus=CurrentRcb->mode;
++ }
++ } /* while */
++
++ if ((CurrentRcb)&&((RxBufStatus&CB_OWNERSHIP_BIT)==0)) /*~GSG 030307*/
++ {
++ *MoreWork = 1;
++ }
++ else
++ {
++ *MoreWork = 0;
++ }
++
++ if (PacketsServiced != 0)
++ {
++ /* REMOVED when removing InRxInt */
++ if ((!HalDev->RxActive[Ch]) && (HalDev->RxActQueueCount[Ch]))
++ {
++ (*(pRX_DMA_STATE_WORD_1( base )+( Ch *64))) = VirtToPhys(HalDev->RxActQueueHead[Ch]);
++ HalDev->RxActive[Ch]=TRUE;
++ }
++ }
++
++ HalDev->InRxInt[Ch]=FALSE;
++
++ /* update stats */
++ HalDev->Stats.RxPacketsServiced[Ch] += PacketsServiced;
++ HalDev->Stats.RxTotal += PacketsServiced;
++ if (HalDev->Stats.RxMaxServiced < PacketsServiced)
++ HalDev->Stats.RxMaxServiced = PacketsServiced;
++
++ return (EC_NO_ERRORS);
++ }
++
++/*
++ * This function processes transmit interrupts. It traverses the
++ * transmit buffer queue, detecting sent data buffers and notifying the upper
++ * layer software via osSendComplete(). (for SAR, i originally had this split
++ * into two functions, one for each queue, but joined them on 8/8/02)
++ *
++ * @param HalDev CPHAL module instance. (set by cphalInitModule())
++ * @param Queue Queue number to service (always 0 for MAC, Choose 1 for SAR to service low priority queue)
++ * @param MoreWork Flag that indicates that there is more work to do when set to 1.
++ *
++ * @return 0 if OK, non-zero otherwise.
++ */
++static int TxInt(HAL_DEVICE *HalDev, int Ch, int Queue, int *MoreWork)
++ {
++ HAL_TCB *CurrentTcb,*LastTcbProcessed,*FirstTcbProcessed;
++ int PacketsServiced;
++ bit32u TxFrameStatus;
++ int base = HalDev->dev_base, Ret;
++ int TxServiceMax = HalDev->ChData[Ch].TxServiceMax;
++ OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++
++ int OtherQueue = Queue^1;
++
++/*+GSG 030303*//*+GSG 030303*/
++
++ /* Handle case of teardown interrupt. This must be checked at
++ the top of the function rather than the bottom, because
++ the normal data processing can wipe out the completion
++ pointer which is used to determine teardown complete. */
++ if (HalDev->TxTeardownPending[Ch] != 0)
++ {
++ Ret = TxTeardownInt(HalDev, Ch, Queue);
++ if (Ret == 0)
++ { /*+GSG 030303*/
++ *MoreWork = 0; /* bug fix 1/6 */ /*+GSG 030303*/
++ return (EC_NO_ERRORS);
++ } /*+GSG 030303*/
++ }
++
++ CurrentTcb = HalDev->TxActQueueHead[Ch][Queue];
++ FirstTcbProcessed=CurrentTcb;
++
++ if (CurrentTcb==0)
++ {
++ /* I saw this error a couple of times when multi-channels were added */
++ dbgPrintf("[cppi TxInt()]TxH int with no TCB in queue!\n");
++ dbgPrintf(" Ch=%d, CurrentTcb = 0x%08x\n", Ch, (bit32u)CurrentTcb);
++ dbgPrintf(" HalDev = 0x%08x\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ return(EC_CPPI|EC_FUNC_TXINT|EC_VAL_NULL_TCB);
++ }
++
++ osfuncDataCacheHitInvalidate((void *)CurrentTcb, 16);
++ TxFrameStatus=CurrentTcb->mode;
++ PacketsServiced=0;
++
++ /* should the ownership bit check be inside of the loop?? could make it a
++ while-do loop and take this check away */
++ if ((TxFrameStatus&CB_OWNERSHIP_BIT)==0)
++ {
++ OsFunc->CriticalOn(); /* +GSG 030307 */
++ do
++ {
++ /* Pop TCB(s) for packet from the stack */
++ LastTcbProcessed=CurrentTcb->Eop;
++
++ /* new location for acknowledge */
++ /* Write the completion pointer */
++ (*(pTXH_CPPI_COMP_PTR( base )+( Ch *64)+( Queue ))) = VirtToPhys(LastTcbProcessed);
++
++ HalDev->TxActQueueHead[Ch][Queue] = LastTcbProcessed->Next;
++
++/*+GSG 030303*//*+GSG 030303*/
++
++ osfuncDataCacheHitInvalidate((void *)LastTcbProcessed, 16);
++
++ if (LastTcbProcessed->mode&CB_EOQ_BIT)
++ {
++ if (LastTcbProcessed->Next)
++ {
++ /* Misqueued packet */
++
++ HalDev->Stats.TxMisQCnt[Ch][Queue]++;
++
++ (*(pTX_DMA_STATE_WORD_0( base )+( Ch *64)+( Queue ))) = LastTcbProcessed->HNext;
++ }
++ else
++ {
++ /* Tx End of Queue */
++
++ HalDev->Stats.TxEOQCnt[Ch][Queue]++;
++
++ HalDev->TxActive[Ch][Queue]=FALSE;
++ }
++ }
++
++ OsFunc->SendComplete(CurrentTcb->OsInfo);
++
++ /* Push Tcb(s) back onto the stack */
++ CurrentTcb = LastTcbProcessed->Next;
++
++ LastTcbProcessed->Next=HalDev->TcbPool[Ch][Queue];
++
++ HalDev->TcbPool[Ch][Queue]=FirstTcbProcessed;
++
++ PacketsServiced++;
++
++ TxFrameStatus=CB_OWNERSHIP_BIT;
++ /* set the first(SOP) pointer for the next packet */
++ FirstTcbProcessed = CurrentTcb;
++ if (CurrentTcb)
++ {
++ osfuncDataCacheHitInvalidate((void *)CurrentTcb, 16);
++ TxFrameStatus=CurrentTcb->mode;
++ }
++
++ }while(((TxFrameStatus&CB_OWNERSHIP_BIT)==0)
++ &&(PacketsServiced<TxServiceMax));
++
++ /* this fixes the SAR TurboDSL hardware bug (multiple queue failure) */
++ if (HalDev->TxActive[Ch][OtherQueue])
++ if (HalDev->TxActQueueHead[Ch][OtherQueue])
++ if ((*(pTX_DMA_STATE_WORD_0( base )+( Ch *64)+( OtherQueue ))) == 0)
++ {
++ osfuncDataCacheHitInvalidate(HalDev->TxActQueueHead[Ch][OtherQueue],16);
++ if ((HalDev->TxActQueueHead[Ch][OtherQueue]->mode) & CB_OWNERSHIP_BIT)
++ {
++ HalDev->TurboDslErrors++;
++ (*(pTX_DMA_STATE_WORD_0( base )+( Ch *64)+( OtherQueue ))) =
++ VirtToPhys(HalDev->TxActQueueHead[Ch][OtherQueue]);
++ }
++ }
++
++ OsFunc->CriticalOff(); /* +GSG 030307 */
++ if (((TxFrameStatus&CB_OWNERSHIP_BIT)==0)
++ &&(PacketsServiced==TxServiceMax))
++ {
++ *MoreWork = 1;
++ }
++ else
++ {
++ *MoreWork = 0;
++ }
++ }
++
++ /* update stats */
++ HalDev->Stats.TxPacketsServiced[Ch][Queue] += PacketsServiced;
++ HalDev->Stats.TxTotal += PacketsServiced;
++ if (HalDev->Stats.TxMaxServiced[Ch][Queue] < PacketsServiced)
++ HalDev->Stats.TxMaxServiced[Ch][Queue] = PacketsServiced;
++
++ return(EC_NO_ERRORS);
++ }
++
++/**
++ * @ingroup CPHAL_Functions
++ * This function performs a teardown for the given channel. The value of the
++ * Mode parameter controls the operation of the function, as documented below.
++ *
++ * Note: If bit 3 of Mode is set, this call is blocking, and will not return
++ * until the teardown interrupt has occurred and been processed. While waiting
++ * for a blocking teardown to complete, ChannelTeardown() will signal the OS
++ * (via Control(.."Sleep"..)) to allow the OS to perform other tasks if
++ * necessary. If and only if bit 3 of Mode is clear, the CPHAL will call the
++ * OS TeardownComplete() function to indicate that the teardown has completed.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ * @param Ch Channel number.
++ * @param Mode Bit 0 (LSB): Perform Tx teardown (if set).<BR>
++ * Bit 1: Perform Rx teardown (if set). <BR>
++ * Bit 2: If set, perform full teardown (free buffers/descriptors).
++ * If clear, perform partial teardown (keep buffers). <BR>
++ * Bit 3 (MSB): If set, call is blocking.
++ * If clear, call is non-blocking.
++ *
++ * @return EC_NO_ERRORS (ok). <BR>
++ * Possible Error Codes:<BR>
++ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ * @ref EC_VAL_INVALID_CH "EC_VAL_INVALID_CH"<BR>
++ * @ref EC_VAL_TX_TEARDOWN_ALREADY_PEND "EC_VAL_TX_TEARDOWN_ALREADY_PEND"<BR>
++ * @ref EC_VAL_RX_TEARDOWN_ALREADY_PEND "EC_VAL_RX_TEARDOWN_ALREADY_PEND"<BR>
++ * @ref EC_VAL_TX_CH_ALREADY_TORNDOWN "EC_VAL_TX_CH_ALREADY_TORNDOWN"<BR>
++ * @ref EC_VAL_RX_CH_ALREADY_TORNDOWN "EC_VAL_RX_CH_ALREADY_TORNDOWN"<BR>
++ * @ref EC_VAL_TX_TEARDOWN_TIMEOUT "EC_VAL_TX_TEARDOWN_TIMEOUT"<BR>
++ * @ref EC_VAL_RX_TEARDOWN_TIMEOUT "EC_VAL_RX_TEARDOWN_TIMEOUT"<BR>
++ * @ref EC_VAL_LUT_NOT_READY "EC_VAL_LUT_NOT_READY"<BR>
++ */
++static int halChannelTeardown(HAL_DEVICE *HalDev, int Ch, bit32 Mode)
++ {
++ int DoTx, DoRx, Sleep=2048, timeout=0; /*MJH~030306*/
++ bit32u base = HalDev->dev_base;
++
++/* Set the module, used for error returns */
++
++ int Ret;
++
++ /* AAL5 only supports tearing down both sides at once (currently)*/
++ Mode = (Mode | TX_TEARDOWN | RX_TEARDOWN);
++
++ DoTx = (Mode & TX_TEARDOWN);
++ DoRx = (Mode & RX_TEARDOWN);
++
++ if (HalDev->State < enInitialized)
++ return(EC_AAL5 |EC_FUNC_CHTEARDOWN|EC_VAL_INVALID_STATE);
++
++ if ((Ch < 0) || (Ch > MAX_AAL5_CHAN ))
++ {
++ return(EC_AAL5 |EC_FUNC_CHTEARDOWN|EC_VAL_INVALID_CH);
++ }
++
++ /* set teardown pending bits before performing the teardown, because they
++ will be used in the int handler (this is done for AAL5) */
++ if (DoTx)
++ {
++ if (HalDev->TxTeardownPending[Ch] != 0)
++ return(EC_AAL5 |EC_FUNC_CHTEARDOWN|EC_VAL_TX_TEARDOWN_ALREADY_PEND);
++
++ /* If a full teardown, this also means that the user must
++ setup all channels again to use them */
++ if (Mode & FULL_TEARDOWN)
++ HalDev->ChIsSetup[Ch][DIRECTION_TX] = 0;
++
++ if (HalDev->State < enOpened)
++ {
++ /* if the hardware has never been opened, the channel has never actually
++ been setup in the hardware, so I just need to reset the software flag
++ and leave */
++ HalDev->ChIsSetup[Ch][DIRECTION_TX] = 0;
++ return (EC_NO_ERRORS);
++ }
++ else
++ {
++ if (HalDev->ChIsOpen[Ch][DIRECTION_TX] == 0)
++ {
++ return(EC_AAL5 |EC_FUNC_CHTEARDOWN|EC_VAL_TX_CH_ALREADY_TORNDOWN);
++ }
++
++ /* set teardown flag */
++ HalDev->TxTeardownPending[Ch] = Mode;
++ }
++ }
++
++ if (DoRx)
++ {
++ if (HalDev->RxTeardownPending[Ch] != 0)
++ return(EC_AAL5 |EC_FUNC_CHTEARDOWN|EC_VAL_RX_TEARDOWN_ALREADY_PEND);
++
++ if (Mode & FULL_TEARDOWN)
++ HalDev->ChIsSetup[Ch][DIRECTION_RX] = 0;
++
++ if (HalDev->State < enOpened)
++ {
++ HalDev->ChIsSetup[Ch][DIRECTION_RX] = 0;
++ return (EC_NO_ERRORS);
++ }
++ else
++ {
++ if (HalDev->ChIsOpen[Ch][DIRECTION_RX] == 0)
++ return(EC_AAL5 |EC_FUNC_CHTEARDOWN|EC_VAL_RX_CH_ALREADY_TORNDOWN);
++
++ HalDev->RxTeardownPending[Ch] = Mode;
++ }
++ }
++
++ /* Perform Tx Teardown Duties */
++ if ((DoTx) && (HalDev->State == enOpened))
++ {
++ /* Request TX channel teardown */
++ (TX_CPPI_TEARDOWN_REG( base )) = Ch;
++
++ /* wait until teardown has completed */
++ if (Mode & BLOCKING_TEARDOWN)
++ {
++ timeout = 0;
++ while (HalDev->ChIsOpen[Ch][DIRECTION_TX] == TRUE)
++ {
++ osfuncSleep(&Sleep);
++
++ timeout++;
++ if (timeout > 100000)
++ {
++ return(EC_AAL5 |EC_FUNC_CHTEARDOWN|EC_VAL_TX_TEARDOWN_TIMEOUT);
++ }
++ }
++ }
++ } /* if DoTx */
++
++ /* Perform Rx Teardown Duties */
++ if ((DoRx) && (HalDev->State == enOpened))
++ {
++
++ /* call main teardown routine for Rx */
++ Ret = HalDev->SarFunc->ChannelTeardown(HalDev->SarDev, Ch, Mode);
++ if (Ret) return (Ret);
++
++ if (Mode & BLOCKING_TEARDOWN)
++ {
++ timeout = 0;
++ while (HalDev->ChIsOpen[Ch][DIRECTION_RX] == TRUE)
++ {
++ osfuncSleep(&Sleep);
++
++ timeout++;
++ if (timeout > 100000)
++ {
++ return(EC_AAL5 |EC_FUNC_CHTEARDOWN|EC_VAL_RX_TEARDOWN_TIMEOUT);
++ }
++ }
++ }
++ } /* if DoRx */
++
++ return (EC_NO_ERRORS);
++ }
++
++/**
++ * @ingroup CPHAL_Functions
++ * This function closes the CPHAL module. The module will be reset.
++ * The Mode parameter should be used to determine the actions taken by
++ * Close().
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ * @param Mode Indicates actions to take on close. The following integer
++ * values are valid: <BR>
++ * 1: Does not free buffer resources, init parameters remain
++ * intact. User can then call Open() without calling Init()
++ * to attempt to reset the device and bring it back to the
++ * last known state.<BR>
++ * 2: Frees the buffer resources, but keeps init parameters. This
++ * option is a more aggressive means of attempting a device reset.
++ * 3: Frees the buffer resources, and clears all init parameters. <BR>
++ * At this point, the caller would have to call to completely
++ * reinitialize the device (Init()) before being able to call
++ * Open(). Use this mode if you are shutting down the module
++ * and do not plan to restart.
++ *
++ * @return EC_NO_ERRORS (ok).<BR>
++ * Possible Error Codes:<BR>
++ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ * Any error code from halChannelTeardown().<BR>
++ */
++static int halClose(HAL_DEVICE *HalDev, bit32 Mode)
++ {
++ int Ch, Inst, Ret;
++ OS_DEVICE *TmpOsDev;
++ OS_FUNCTIONS *TmpOsFunc;
++ HAL_FUNCTIONS *TmpHalFunc;
++ char *TmpDeviceInfo;
++
++ CPSAR_FUNCTIONS *TmpSarFunc;
++ CPSAR_DEVICE *TmpSarDev;
++
++ /* Verify proper device state */
++ if (HalDev->State != enOpened)
++ return (EC_AAL5 | EC_FUNC_CLOSE|EC_VAL_INVALID_STATE);
++
++ /* Teardown all open channels */
++ for (Ch = 0; Ch <= MAX_AAL5_CHAN ; Ch++)
++ {
++ if (HalDev->ChIsOpen[Ch][DIRECTION_TX] == TRUE)
++ {
++ if (Mode == 1)
++ {
++ Ret = halChannelTeardown(HalDev, Ch, TX_TEARDOWN | PARTIAL_TEARDOWN | BLOCKING_TEARDOWN);
++ if (Ret) return (Ret);
++ }
++ else
++ {
++ Ret = halChannelTeardown(HalDev, Ch, TX_TEARDOWN | FULL_TEARDOWN | BLOCKING_TEARDOWN);
++ if (Ret) return (Ret);
++ }
++ }
++
++ if (HalDev->ChIsOpen[Ch][DIRECTION_RX] == TRUE)
++ {
++ if (Mode == 1)
++ {
++ Ret = halChannelTeardown(HalDev, Ch, RX_TEARDOWN | PARTIAL_TEARDOWN | BLOCKING_TEARDOWN);
++ if (Ret) return (Ret);
++ }
++ else
++ {
++ Ret = halChannelTeardown(HalDev, Ch, RX_TEARDOWN | FULL_TEARDOWN | BLOCKING_TEARDOWN);
++ if (Ret) return (Ret);
++ }
++ }
++ }
++
++ /* free fraglist in HalDev */
++ HalDev->OsFunc->Free(HalDev->fraglist);
++ HalDev->fraglist = 0;
++
++ /* unregister the interrupt */
++ HalDev->OsFunc->IsrUnRegister(HalDev->OsDev, HalDev->interrupt);
++
++ /* Disable the Tx CPPI DMA */
++ TX_CPPI_CTL_REG(HalDev->dev_base) = 0;
++
++ /* Disable the Rx CPPI DMA */
++ RX_CPPI_CTL_REG(HalDev->dev_base) = 0;
++
++ /* Close the SAR hardware - puts the device in reset if this module is the
++ "last one out" */
++ HalDev->SarFunc->Close(HalDev->SarDev, Mode);
++
++ /* If mode is 3, than clear the HalDev and set next state to DevFound*/
++ if (Mode == 3)
++ {
++ /* I need to keep the HalDev parameters that were setup in InitModule */
++ TmpOsDev = HalDev->OsDev;
++ TmpOsFunc = HalDev->OsFunc;
++ TmpDeviceInfo = HalDev->DeviceInfo;
++
++ TmpSarFunc = HalDev->SarFunc;
++ TmpSarDev = HalDev->SarDev;
++
++ TmpHalFunc = HalDev->HalFuncPtr;
++ Inst = HalDev->Inst;
++
++ /* Clear HalDev */
++
++ HalDev->OsFunc->Memset(HalDev, 0, sizeof(HAL_DEVICE));
++
++ /* Restore key parameters */
++ HalDev->OsDev = TmpOsDev;
++ HalDev->OsFunc = TmpOsFunc;
++ HalDev->DeviceInfo = TmpDeviceInfo;
++
++ HalDev->SarFunc = TmpSarFunc;
++ HalDev->SarDev = TmpSarDev;
++
++ HalDev->HalFuncPtr = TmpHalFunc;
++ HalDev->Inst = Inst;
++
++ HalDev->State = enDevFound;
++ }
++ else
++ {
++ HalDev->State = enInitialized;
++ }
++
++ return(EC_NO_ERRORS);
++ }
+diff -urN linux.old/drivers/atm/sangam_atm/cpremap_cpaal5.c linux.dev/drivers/atm/sangam_atm/cpremap_cpaal5.c
+--- linux.old/drivers/atm/sangam_atm/cpremap_cpaal5.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/cpremap_cpaal5.c 2005-08-23 04:46:50.084845672 +0200
+@@ -0,0 +1,27 @@
++#ifndef _INC_CPREMAP_C
++#define _INC_CPREMAP_C
++
++#ifdef __ADAM2
++static inline void osfuncDataCacheHitInvalidate(void *ptr, int Size)
++ {
++ asm(" cache 17, (%0)" : : "r" (ptr));
++ }
++
++static inline void osfuncDataCacheHitWriteback(void *ptr, int Size)
++ {
++ asm(" cache 25, (%0)" : : "r" (ptr));
++ }
++
++#else
++ #define osfuncDataCacheHitInvalidate(MemPtr, Size) HalDev->OsFunc->DataCacheHitInvalidate(MemPtr, Size)
++ #define osfuncDataCacheHitWriteback(MemPtr, Size) HalDev->OsFunc->DataCacheHitWriteback(MemPtr, Size)
++#endif
++
++/*
++#define osfuncDataCacheHitInvalidate(ptr, Size) asm(" cache 17, (%0)" : : "r" (ptr))
++#define osfuncDataCacheHitWriteback(ptr, Size) asm(" cache 25, (%0)" : : "r" (ptr))
++*/
++
++
++
++#endif
+diff -urN linux.old/drivers/atm/sangam_atm/cpremap_cpsar.c linux.dev/drivers/atm/sangam_atm/cpremap_cpsar.c
+--- linux.old/drivers/atm/sangam_atm/cpremap_cpsar.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/cpremap_cpsar.c 2005-08-23 04:46:50.084845672 +0200
+@@ -0,0 +1,27 @@
++#ifndef _INC_CPREMAP_C
++#define _INC_CPREMAP_C
++
++#ifdef __ADAM2
++static inline void osfuncDataCacheHitInvalidate(void *ptr, int Size)
++ {
++ asm(" cache 17, (%0)" : : "r" (ptr));
++ }
++
++static inline void osfuncDataCacheHitWriteback(void *ptr, int Size)
++ {
++ asm(" cache 25, (%0)" : : "r" (ptr));
++ }
++
++#else
++ #define osfuncDataCacheHitInvalidate(MemPtr, Size) HalDev->OsFunc->DataCacheHitInvalidate(MemPtr, Size)
++ #define osfuncDataCacheHitWriteback(MemPtr, Size) HalDev->OsFunc->DataCacheHitWriteback(MemPtr, Size)
++#endif
++
++/*
++#define osfuncDataCacheHitInvalidate(ptr, Size) asm(" cache 17, (%0)" : : "r" (ptr))
++#define osfuncDataCacheHitWriteback(ptr, Size) asm(" cache 25, (%0)" : : "r" (ptr))
++*/
++
++
++
++#endif
+diff -urN linux.old/drivers/atm/sangam_atm/cpsar.c linux.dev/drivers/atm/sangam_atm/cpsar.c
+--- linux.old/drivers/atm/sangam_atm/cpsar.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/cpsar.c 2005-08-23 04:46:50.086845368 +0200
+@@ -0,0 +1,881 @@
++/**
++ * cpsar.c
++ *
++ * TNETDxxxx Software Support\n
++ * Copyright (c) 2002 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ * This file contains the HAL for the CPSAR module. In the software
++ * architecture, the CPSAR module is used exclusively by the AAL5 and AAL2
++ * CPHAL modules. AAL5 and AAL2 may utilize the same CPSAR instance
++ * simulataneously.
++ *
++ * version
++ * 5Sep02 Greg 1.00 Original Version created.
++ */
++
++/* register files */
++#include "cp_sar_reg.h"
++
++#define _CPHAL_CPSAR
++#define _CPHAL
++
++#define WAIT_THRESH 200000
++#define IRAM_SIZE 1536
++#define MAX_INST 2
++
++/* OS Data Structure definition */
++
++typedef void OS_PRIVATE;
++typedef void OS_DEVICE;
++typedef void OS_SENDINFO;
++typedef void OS_RECEIVEINFO;
++typedef void OS_SETUP;
++
++/* CPHAL Data Structure definitions */
++
++typedef struct cpsar_device CPSAR_DEVICE;
++typedef struct cpsar_device HAL_DEVICE;
++typedef void HAL_RECEIVEINFO;
++
++#define MAX_QUEUE 2
++#define MAX_CHAN 19
++
++#include "cpcommon_cpsar.h"
++#include "cpswhal_cpsar.h"
++#include "cpsar.h"
++#include "cpcommon_cpsar.c"
++
++static CPSAR_DEVICE *CpsarDev[MAX_INST]= {0,0};
++
++/*
++ * Returns statistics information.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ *
++ * @return 0
++ */
++static int StatsGet3(CPSAR_DEVICE *HalDev)
++ {
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpsar]StatsGet3(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++ /*
++ dbgPrintf("CPSAR General Stats:\n");
++ DispHexStat(HalDev, "Base Address",HalDev->dev_base);
++ DispStat(HalDev, "Offset (VLYNQ)",HalDev->offset);
++ DispStat(HalDev, "Debug Level",HalDev->debug);
++ DispStat(HalDev, "Instance",HalDev->Inst);
++ DispHexStat(HalDev, "Reset Address",HalDev->ResetBase);
++ DispStat(HalDev, "Reset Bit",HalDev->ResetBit);
++ */
++ return (EC_NO_ERRORS);
++ }
++
++/* +GSG 030407 */
++static void SetOamMode(HAL_DEVICE *HalDev)
++ {
++ int Ch;
++ volatile bit32u *pTmp;
++ int OamMode = (1<<8);
++
++ /* any configuration of OamMode affects all VC's, including AAL2 */
++ for (Ch = 0; Ch < MAX_CHAN; Ch++)
++ {
++ if (Ch < 16)
++ pTmp = (pPDSP_AAL5_RX_STATE_WORD_0(HalDev->dev_base) + (Ch*64));
++ else
++ pTmp = (pPDSP_AAL2_RX_STATE_WORD_0(HalDev->dev_base) + ((Ch-16)*64));
++
++ if (HalDev->OamMode == 0)
++ {
++ *pTmp &=~ OamMode;
++ }
++ else
++ {
++ *pTmp |= OamMode;
++ }
++ }
++ }
++
++static int halControl(CPSAR_DEVICE *HalDev, const char *Key, const char *Action, void *Value)
++ {
++ int KeyFound=0, ActionFound=0, rc=EC_NO_ERRORS, Ch; /* +RC3.02*/
++ char *TmpKey = (char *)Key;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpsar]halControl(HalDev:%08x, Key:%s, Action:%s, Value:%08x)\n", (bit32u)HalDev,
++ Key, Action, (bit32u)Value);
++ osfuncSioFlush();
++ }
++#endif
++
++ if (HalDev->OsFunc->Strcmpi(Key, "Debug") == 0)
++ {
++ KeyFound=1; /* +RC3.02*/
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1; /* +RC3.02*/
++ HalDev->debug = *(int *)Value;
++ }
++ }
++
++ /* +GSG 030407 */
++ if (HalDev->OsFunc->Strcmpi(Key, "OamMode") == 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++ HalDev->OamMode = *(int *)Value;
++
++ /* only do this if we're open */
++ if (HalDev->OpenCount > 0)
++ SetOamMode(HalDev);
++ }
++
++ if (HalDev->OsFunc->Strcmpi(Action, "Get") == 0)
++ {
++ ActionFound=1;
++ *(int *)Value = HalDev->OamMode;
++ }
++ }
++
++ if (HalDev->OsFunc->Strcmpi(Key, "Stats3") == 0)
++ {
++ if (HalDev->OsFunc->Strcmpi(Action, "Get") == 0)
++ StatsGet3(HalDev);
++ }
++
++ /* +RC3.02 (if statement) */
++ /* Fixes PITS #98 */
++ if (HalDev->OsFunc->Strstr(Key, "PdspEnable") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++
++ /* Configure PDSP enable bit based on Value*/
++ if (*(int *)Value & 1)
++ {
++ /* enable PDSP */
++ PDSP_CTRL_REG(HalDev->dev_base) |= 0x2;
++ }
++ else
++ {
++ /* disable PDSP */
++ PDSP_CTRL_REG(HalDev->dev_base) &=~ 0x2;
++ }
++ }
++ }
++
++ if (HalDev->OsFunc->Strstr(Key, "FwdUnkVc.") != 0)
++ {
++ KeyFound=1;
++ if (HalDev->OsFunc->Strcmpi(Action, "Set") == 0)
++ {
++ ActionFound=1;
++
++ /* extract channel number */
++ TmpKey += HalDev->OsFunc->Strlen("FwdUnkVc.");
++ Ch = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++
++ /* Configure forwarding of unknown VCI/VPI cells */
++ SAR_PDSP_FWD_UNK_VC_REG(HalDev->dev_base) = (((*(int*)Value)<<31) | Ch);
++ }
++ }
++
++ if (KeyFound == 0) /* +RC3.02 */
++ rc = (EC_CPSAR|EC_FUNC_CONTROL|EC_VAL_KEY_NOT_FOUND); /* +RC3.02 */
++
++ if (ActionFound == 0) /* +RC3.02 */
++ rc = (EC_CPSAR|EC_FUNC_CONTROL|EC_VAL_ACTION_NOT_FOUND); /* +RC3.02 */
++
++ return(rc); /* ~RC3.02 */
++ }
++
++/*
++ * This function opens the specified channel.
++ *
++ * @param HalDev CPHAL module instance. (set by cphalInitModule())
++ * @param Ch Channel number.
++ *
++ * @return 0 OK, Non-zero Not OK
++ */
++static int halChannelSetup(CPSAR_DEVICE *HalDev, CHANNEL_INFO *HalCh)
++ {
++ int i;
++ int Ch = HalCh->Channel;
++ int PdspChBlock = Ch;
++ int PdspBlockOffset = 0;
++ volatile bit32u *pTmp;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpsar]halChannelSetup(HalDev:%08x, HalCh:%08x)\n", (bit32u)HalDev,
++ (bit32u)HalCh);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* Figure out the correct offset from the start of the PDSP
++ Scratchpad RAM (starting at 0x8050 in the SAR) */
++ if (Ch > 15)
++ {
++ /* this is an AAL2 channel, which are channels 16-18 */
++ PdspChBlock = Ch - 16;
++ /* Get the offset to the AAL2 portion of the block (in words) */
++ PdspBlockOffset = NUM_PDSP_AAL5_STATE_WORDS + (PdspChBlock*64);
++ /* Clear PDSP State RAM */
++ /*pTmp = (pPDSP_BLOCK_0(HalDev->dev_base)+PdspBlockOffset);
++ for (i=0; i<NUM_PDSP_AAL2_STATE_WORDS; i++)
++ *pTmp++ = 0;*/
++ }
++ else
++ {
++ /* Get the offset to the AAL5 portion of the block (in words) */
++ PdspBlockOffset = (PdspChBlock*64);
++ /* Clear PDSP State RAM */
++ /*pTmp = (pPDSP_BLOCK_0(HalDev->dev_base)+PdspBlockOffset);
++ for (i=0; i<NUM_PDSP_AAL5_STATE_WORDS; i++)
++ *pTmp++ = 0;*/
++ }
++
++ /* Configure PDSP State RAM */
++
++ /* Setup TX PDSP State RAM */
++ pTmp = (pPDSP_BLOCK_0(HalDev->dev_base)+PdspBlockOffset);
++ *pTmp++ = HalCh->TxVc_CellRate; /* Set the cell rate in cells/sec */
++ *pTmp++ = HalCh->TxVc_QosType; /* Configure the QoS Type */
++ *pTmp++ = HalCh->TxVc_Mbs; /* Set minimum burst size */
++ *pTmp++ = 0; /* (skip a register) */
++ *pTmp++ = HalCh->TxVc_Pcr; /* set the peak cell rate */
++ *pTmp++ = 0; /* new addition 4.9.02 */
++ *pTmp++ = HalCh->TxVc_AtmHeader; /* give the ATM header */
++ *pTmp++ = (HalCh->TxVc_OamTc << 8)
++ |(HalCh->TxVc_VpOffset); /* Set the OAM TC Path and VP Offset */
++
++ /* Setup RX PDSP State RAM */
++ *pTmp++ = (HalCh->RxVc_OamCh)|
++ (HalDev->OamMode << 8) |
++ (HalCh->RxVc_OamToHost<<9); /* Set OAM Channel, Mode, and ToHost options */
++ *pTmp++ = HalCh->RxVc_AtmHeader; /* ATM hdr put on firmware generated OAM */
++ *pTmp++ = (HalCh->RxVc_VpOffset)| /* Set Rx OAM TC Path and VP Offset */
++ (HalCh->RxVc_OamTc<<8);
++
++ /* Setup TX VP PDSP State RAM */
++ pTmp = (pPDSP_BLOCK_0(HalDev->dev_base)+PdspBlockOffset+16); /*GSG~030703 12->16 */
++ *pTmp++ = HalCh->TxVp_AtmHeader;
++ *pTmp++ = (HalCh->TxVp_OamTc << 8);
++
++ /* Setup RX VP PDSP State RAM */
++ pTmp = (pPDSP_BLOCK_0(HalDev->dev_base)+PdspBlockOffset+20); /*GSG~030703 16->20 */
++ *pTmp++ = HalCh->RxVp_AtmHeader;
++ *pTmp++ = (HalCh->RxVp_OamCh)|
++ (HalCh->RxVp_OamTc<<8)|
++ (HalCh->RxVp_OamToHost<<9); /* Set OAM Channel, Mode, and ToHost options */
++ *pTmp++ = 0;
++ *pTmp++ = HalCh->RxVp_OamVcList;
++
++ /* Configure forwarding of unknown VCI/VPI cells */
++ if (HalCh->PktType == 3)
++ SAR_PDSP_FWD_UNK_VC_REG(HalDev->dev_base) = ((HalCh->FwdUnkVc<<31)|Ch);
++
++ /* Configure Tx Channel Mapping Register (turn channel "ON") */
++ TX_CH_MAPPING_REG(HalDev->dev_base) = 0x80000000 |
++ (HalCh->DaMask << 30)
++ | (HalCh->Priority << 24) | Ch;
++
++ /* Setup Rx Channel in the LUT */
++ i=0;
++ while (!(RX_LUT_CH_SETUP_REQ_REG(HalDev->dev_base) & 0x80000000))
++ {
++ if (i > WAIT_THRESH)
++ {
++ return(EC_CPSAR|EC_FUNC_CHSETUP|EC_VAL_LUT_NOT_READY);
++ }
++ else
++ i++;
++ }
++
++ /* RX LUT is ready */
++ RX_LUT_CH_SETUP_REQ_REG(HalDev->dev_base) = (HalCh->PktType << 24) | Ch;
++ RX_LUT_CH_SETUP_REQ_VC_REG(HalDev->dev_base) = ((HalCh->Vpi << 20) |
++ (HalCh->Vci << 4));
++
++ return (EC_NO_ERRORS);
++ }
++
++static int halChannelTeardown(CPSAR_DEVICE *HalDev, int Ch, bit32 Mode)
++ {
++ int waitcnt = 0;
++ int PdspBlockOffset = 0, i;
++ volatile bit32u *pTmp;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpsar]halChannelTeardown(HalDev:%08x, Ch:%d, Mode:%d\n",
++ (bit32u)HalDev, Ch, Mode);
++ osfuncSioFlush();
++ }
++#endif
++
++ if ((Ch < 0) || (Ch > MAX_CHAN))
++ return(EC_CPSAR|EC_FUNC_CHTEARDOWN|EC_VAL_INVALID_CH);
++
++ /* Request RX channel teardown through LUT */
++ while ((RX_LUT_CH_TEARDOWN_REQ_REG(HalDev->dev_base) & 0x80000000) == 0)
++ {
++ waitcnt++;
++ if (waitcnt == WAIT_THRESH)
++ {
++ return(EC_CPSAR|EC_FUNC_CHTEARDOWN|EC_VAL_LUT_NOT_READY);
++ }
++ }
++
++ RX_LUT_CH_TEARDOWN_REQ_REG(HalDev->dev_base) = (Ch & 0xffff);
++
++ /* for AAL2, clear channel PDSP RAM here. AAL5 does it when the teardown
++ has completed (which is asynchronous)*/
++ if (Ch > 15)
++ {
++ /* Get the offset to the AAL2 portion of the block (in words) */
++ PdspBlockOffset = NUM_PDSP_AAL5_STATE_WORDS + ((Ch-16)*64);
++ /* Clear PDSP State RAM */
++ pTmp = (pPDSP_BLOCK_0(HalDev->dev_base)+PdspBlockOffset);
++ for (i=0; i<NUM_PDSP_AAL2_STATE_WORDS; i++)
++ *pTmp++ = 0;
++ }
++
++ return (EC_NO_ERRORS);
++ }
++
++int InitPdsp(CPSAR_DEVICE *HalDev)
++ {
++ bit32u NumOfEntries,i,IRamAddress,iTmp;
++ int *SarPdspFirmware; /* ~GSG 030403 */
++ int FirmwareSize, rc; /* ~GSG 030403 */
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpsar]InitPdsp(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* Get firmware */
++ rc = HalDev->OsFunc->Control(HalDev->OsDev, "Firmware", "Get", &SarPdspFirmware); /* ~GSG 030403 */
++ if (rc) /* +GSG 030403 */
++ return (EC_CPSAR|EC_FUNC_OPEN|EC_VAL_KEY_NOT_FOUND); /* +GSG 030403 */
++
++ /* Get firmware size */
++ rc = HalDev->OsFunc->Control(HalDev->OsDev, "FirmwareSize", "Get", &FirmwareSize); /* ~GSG 030403 */
++ if (rc) /* +GSG 030403 */
++ return (EC_CPSAR|EC_FUNC_OPEN|EC_VAL_KEY_NOT_FOUND); /* +GSG 030403 */
++
++ IRamAddress = (bit32u) pPDSP_CTRL_REG(HalDev->dev_base);
++
++ NumOfEntries = (FirmwareSize)/4; /* ~GSG 030403 */
++ if (NumOfEntries > IRAM_SIZE)
++ {
++ /* Note: On Avalanche, they truncated the PDSP firmware and warned */
++ /* NumOfEntries = IRAM_SIZE; */
++ return(EC_CPSAR|EC_FUNC_INIT|EC_VAL_FIRMWARE_TOO_LARGE);
++ }
++ for(i=8;i<NumOfEntries;i++)
++ (*((bit32 *) (IRamAddress+(i*4))))=SarPdspFirmware[i]; /* ~GSG 030403 */
++
++ /* Check code */
++ for(i=8;i<NumOfEntries;i++)
++ {
++ iTmp=(*((bit32 *) (IRamAddress+(i*4))));
++ if (iTmp != SarPdspFirmware[i]) /* ~GSG 030403 */
++ {
++ return(EC_CPSAR|EC_FUNC_OPEN|EC_VAL_PDSP_LOAD_FAIL);
++ }
++ }
++
++ return(EC_NO_ERRORS);
++ }
++
++/*
++ * This function probes for the instance of the CPHAL module. It will call
++ * the OS function @c DeviceFindInfo() to get the information required.
++ *
++ * @param HalDev CPHAL module instance. (set by xxxInitModule())
++ *
++ * @return 0 OK, Otherwise error.
++ */
++static int halProbe(CPSAR_DEVICE *HalDev)
++ {
++ int Ret;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpsar]halProbe(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(1))
++ {
++ dbgPrintf("[os]DeviceFindInfo(Inst:%d, DeviceName:%s, DeviceInfo:%08x)\n",
++ HalDev->Inst, "sar", (bit32u)&HalDev->DeviceInfo);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* Attempt to find the device information */
++ Ret = HalDev->OsFunc->DeviceFindInfo(HalDev->Inst, "sar", &HalDev->DeviceInfo);
++ if (Ret)
++ return(EC_CPSAR|EC_FUNC_PROBE|EC_VAL_DEVICE_NOT_FOUND);
++
++ return(EC_NO_ERRORS);
++ }
++
++#ifdef __CPHAL_DEBUG
++static void dbgConfigDump(HAL_DEVICE *HalDev)
++ {
++ dbgPrintf(" [cpsar Inst %d] Config Dump:\n", HalDev->Inst);
++ dbgPrintf(" Base :%08x, offset :%08d\n",
++ HalDev->dev_base, HalDev->offset);
++ dbgPrintf(" ResetBit:%08d, ResetBase:%08x\n",
++ HalDev->ResetBit, HalDev->ResetBase);
++ dbgPrintf(" UniNni :%08d, debug :%08d\n",
++ HalDev->ResetBit, HalDev->debug);
++ osfuncSioFlush();
++ }
++#endif
++
++/*
++ * Sets up HAL default configuration parameter values.
++ */
++static void ConfigInit(CPSAR_DEVICE *HalDev)
++ {
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpsar]ConfigInit(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++ /* configure some defaults with tnetd7300 values */
++ HalDev->dev_base = 0xa3000000;
++ HalDev->offset = 0;
++ HalDev->UniNni = CFG_UNI_NNI;
++ HalDev->ResetBit = 9;
++ HalDev->debug = 0;
++ HalDev->ResetBase = 0xa8611600;
++ }
++
++/*
++ * Retrieve HAL configuration parameter values.
++ */
++static bit32u ConfigGet(HAL_DEVICE *HalDev)
++ {
++ bit32u ParmValue, error_code;
++ char *DeviceInfo = HalDev->DeviceInfo;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpsar]ConfigGet(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* get the configuration parameters common to all modules */
++ error_code = ConfigGetCommon(HalDev);
++ if (error_code) return (EC_CPSAR|error_code);
++
++ /* get SAR specific configuration parameters */
++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo,"UniNni",&ParmValue);
++ if (!error_code) HalDev->UniNni = ParmValue;
++
++ return (EC_NO_ERRORS);
++ }
++
++static int halInit(CPSAR_DEVICE *HalDev)
++ {
++ bit32u Ret;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpsar]halInit(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(7))
++ {
++ dbgPrintf("[cpsar halInit()]InitCount = %d\n", HalDev->InitCount);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* Only run the init code for the first calling module per instance */
++ if (HalDev->InitCount > 1)
++ {
++ return (EC_NO_ERRORS);
++ }
++
++ /* Configure HAL defaults */
++ ConfigInit(HalDev);
++
++ /* Retrieve HAL configuration parameters from data store */
++ Ret = ConfigGet(HalDev);
++ if (Ret) return (Ret);
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(9))
++ dbgConfigDump(HalDev);
++#endif
++
++ return(EC_NO_ERRORS);
++ }
++
++static int halOpen(CPSAR_DEVICE *HalDev)
++ {
++ int Ret, Ticks=64;
++ int i; /*+GSG 030407*/
++ volatile int *pTmp; /*+GSG 030407*/
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpsar]halOpen(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(7))
++ {
++ dbgPrintf("[cpsar halOpen()]OpenCount = %d\n", HalDev->OpenCount);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* Only run the open code for the first calling module per instance */
++ if (HalDev->OpenCount++ > 0)
++ {
++ return (EC_NO_ERRORS);
++ }
++
++ /* Take SAR out of reset */
++ if (((*(volatile bit32u *)(HalDev->ResetBase)) & (1<<HalDev->ResetBit)) != 0)
++ {
++ /** @todo Should I somehow call AAL5/AAL2 Close() here? All I've done
++ here is copy the Close code from each and paste it here. */
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(7))
++ {
++ dbgPrintf("[cpsar halOpen()]Module was already out of reset.\n");
++ dbgPrintf(" Closing module and resetting.\n");
++ osfuncSioFlush();
++ }
++#endif
++
++ /* Disable the Tx CPPI DMA */
++ TX_CPPI_CTL_REG(HalDev->dev_base) = 0;
++
++ /* Disable the Rx CPPI DMA */
++ RX_CPPI_CTL_REG(HalDev->dev_base) = 0;
++
++ /* Disable the PDSP */
++ PDSP_CTRL_REG(HalDev->dev_base) &=~ 0x00000002;
++
++ /* disable interrupt masks */
++ SAR_TX_MASK_CLR(HalDev->dev_base) = 0xffffffff;
++ SAR_RX_MASK_CLR(HalDev->dev_base) = 0xffffffff;
++
++#ifndef NO_RESET /* GSG+ 030428 */
++ /* clear reset bit */
++ (*(volatile bit32u *)(HalDev->ResetBase)) &=~ (1<<HalDev->ResetBit); /* ~GSG 030307 */
++ HalDev->OsFunc->Control(HalDev->OsDev, "Sleep", "", &Ticks);
++
++ /* set reset bit */
++ (*(volatile bit32u *)(HalDev->ResetBase)) |= (1<<HalDev->ResetBit); /* ~GSG 030307 */
++ HalDev->OsFunc->Control(HalDev->OsDev, "Sleep", "", &Ticks);
++#endif /* GSG+ 030428 */
++ }
++ else
++ {
++ (*(volatile bit32u *)(HalDev->ResetBase)) |= (1<<HalDev->ResetBit); /* ~GSG 030307 */
++ HalDev->OsFunc->Control(HalDev->OsDev, "Sleep", "", &Ticks);
++ }
++
++ /* Configure UNI/NNI */
++ RX_LUT_GLOBAL_CFG_REG(HalDev->dev_base) |= (HalDev->UniNni & 0x1);
++
++ /* Clear entire PDSP state RAM */ /*+GSG 030407*/
++ pTmp = (pTX_DMA_STATE_WORD_0(HalDev->dev_base)); /*+GSG 030407*/
++ for (i=0; i<PDSP_STATE_RAM_SIZE; i++) /*+GSG 030407*/
++ *pTmp++ = 0; /*+GSG 030407*/
++
++ /* Configure Oam Mode */ /*+GSG 030407*/
++ SetOamMode(HalDev); /*+GSG 030407*/
++
++ /* Initialize PDSP */
++ Ret=InitPdsp(HalDev);
++ if(Ret)
++ return(Ret);
++
++ /* Reset and Enable the PDSP */
++ PDSP_CTRL_REG(HalDev->dev_base) = 0x00080003;
++
++ return(EC_NO_ERRORS);
++ }
++
++static int halClose(CPSAR_DEVICE *HalDev, int Mode)
++ {
++ int Ticks = 64;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpsar]halClose(HalDev:%08x, Mode:%d)\n", (bit32u)HalDev, Mode);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* handle the error case if there is nothing open */
++ if (HalDev->OpenCount == 0)
++ {
++ return(EC_CPSAR|EC_FUNC_CLOSE|EC_VAL_MODULE_ALREADY_CLOSED);
++ }
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(7))
++ {
++ dbgPrintf("[cpsar halClose()]OpenCount = %d\n", HalDev->OpenCount);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* Only run the close code for the last calling module per instance */
++ if (HalDev->OpenCount-- > 1)
++ {
++ return (EC_NO_ERRORS);
++ }
++
++ /* Disable the PDSP */
++ PDSP_CTRL_REG(HalDev->dev_base) &=~ 0x00000002;
++
++#ifndef NO_RESET /* GSG +030428 */
++ /* put device back into reset */
++ (*(volatile bit32u *)(HalDev->ResetBase)) &=~ (1<<HalDev->ResetBit); /* ~GSG 030307 */
++ HalDev->OsFunc->Control(HalDev->OsDev, "Sleep", "", &Ticks);
++#endif /* GSG +030428 */
++
++ return(EC_NO_ERRORS);
++ }
++
++static int halShutdown(CPSAR_DEVICE *HalDev)
++ {
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpsar]halShutdown(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* handle the error case */
++ if (HalDev->InitCount == 0)
++ {
++ return(EC_CPSAR|EC_FUNC_CLOSE|EC_VAL_MODULE_ALREADY_SHUTDOWN);
++ }
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(7))
++ {
++ dbgPrintf("[cpsar halShutdown()]InitCount = %d\n", HalDev->InitCount);
++ osfuncSioFlush();
++ }
++#endif
++
++ /* Only run the shutdown code for the last calling module per instance */
++ if (HalDev->InitCount-- > 1)
++ {
++ return (EC_NO_ERRORS);
++ }
++
++ /* free the SAR functions */
++#ifdef __CPHAL_DEBUG
++ if (DBG(6))
++ {
++ dbgPrintf(" [cpsar halShutdown()]: Free CPSAR function pointers\n");
++ osfuncSioFlush();
++ }
++ if (DBG(1)||DBG(3))
++ {
++ dbgPrintf("[os]Free(MemPtr:%08x)\n", (bit32u)HalDev->HalFuncPtr);
++ osfuncSioFlush();
++ }
++#endif
++ /* free the HalFunc */
++ HalDev->OsFunc->Free(HalDev->HalFuncPtr);
++
++ /* we have a static global, so I should clear it's value as well */
++ CpsarDev[HalDev->Inst] = 0;
++
++#ifdef __CPHAL_DEBUG
++ if (DBG(6))
++ {
++ dbgPrintf(" [cpsar halShutdown()]Free HalDev\n");
++ osfuncSioFlush();
++ }
++ if (DBG(1)||DBG(3))
++ {
++ dbgPrintf("[os]Free(MemPtr:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++ /* free the CPSAR device */
++ HalDev->OsFunc->Free(HalDev);
++
++ return(EC_NO_ERRORS);
++ }
++
++static int halTick(CPSAR_DEVICE *HalDev)
++ {
++#ifdef __CPHAL_DEBUG
++ if (DBG(0))
++ {
++ dbgPrintf("[cpsar]halTick(HalDev:%08x)\n", (bit32u)HalDev);
++ osfuncSioFlush();
++ }
++#endif
++
++ return(EC_NO_ERRORS);
++ }
++
++/*
++ * The CPSAR version of InitModule() should be passed the OS_FUNCTIONS pointer,
++ * and will return the HalDev pointer.
++ *
++ * @param HalDev Pointer to CPSAR module information. This will
++ * be used by the OS when communicating to this module via
++ * CPSAR.
++ * @param OsDev Pointer to OS device information. This will be saved by
++ * the CPSAR and returned to the OS when required.
++ * @param HalFunc HAL_FUNCTIONS pointer.
++ * @param Size Pointer to the size of the HAL_FUNCTIONS structure. (If
++ * HalFunc is 0, the value will be set by CPSAR, otherwise
++ * ignored)
++ * @param Inst The instance number of the module to initialize. (start at
++ * 0).
++ *
++ * @return 0 OK, Nonzero - error.
++ */
++/*
++int cpsarInitModule(CPSAR_DEVICE **HalDev,
++ OS_DEVICE *OsDev,
++ CPSAR_FUNCTIONS *HalFunc,
++ OS_FUNCTIONS *OsFunc,
++ int *Size,
++ int Inst)
++*/
++int cpsarInitModule(CPSAR_DEVICE **HalDev,
++ OS_DEVICE *OsDev,
++ CPSAR_FUNCTIONS **HalFunc,
++ OS_FUNCTIONS *OsFunc,
++ int OsFuncSize,
++ int *HalFuncSize,
++ int Inst)
++ {
++ CPSAR_DEVICE *HalPtr;
++ CPSAR_FUNCTIONS *HalFuncPtr;
++
++ /*
++ if ( HalFunc == 0 )
++ {
++ *Size = sizeof(CPSAR_FUNCTIONS);
++ return(EC_NO_ERRORS);
++ }
++ */
++
++ if (CpsarDev[Inst] != 0)
++ {
++ /* this SAR module has been connected to before, so do not
++ allocate another CPSAR_DEVICE */
++ HalPtr = CpsarDev[Inst];
++
++ /* increase count of attached modules */
++ HalPtr->InitCount++;
++ }
++ else
++ {
++ /* allocate the CPSAR_DEVICE structure */
++ HalPtr = (CPSAR_DEVICE *) OsFunc->MallocDev(sizeof(CPSAR_DEVICE));
++ if(!HalPtr)
++ return(EC_CPSAR|EC_FUNC_HAL_INIT|EC_VAL_MALLOC_DEV_FAILED);
++
++ HalFuncPtr = (CPSAR_FUNCTIONS *) OsFunc->Malloc(sizeof(CPSAR_FUNCTIONS));
++ if (!HalFuncPtr)
++ return (EC_CPSAR|EC_FUNC_HAL_INIT|EC_VAL_MALLOC_FAILED);
++
++ /* Initialize the size of hal functions */
++ *HalFuncSize = sizeof (CPSAR_FUNCTIONS);
++
++ /* ensure the device structure is cleared */
++ OsFunc->Memset(HalPtr, 0, sizeof(CPSAR_DEVICE));
++
++ /* clear the function pointers */
++ OsFunc->Memset(HalFuncPtr, 0, sizeof(CPSAR_FUNCTIONS));
++
++ /* Supply pointers for the CPSAR API functions */
++ HalFuncPtr->ChannelSetup = halChannelSetup;
++ HalFuncPtr->ChannelTeardown = halChannelTeardown;
++ HalFuncPtr->Close = halClose;
++ HalFuncPtr->Control = halControl;
++ HalFuncPtr->Init = halInit;
++ HalFuncPtr->Open = halOpen;
++ HalFuncPtr->Probe = halProbe;
++ HalFuncPtr->Shutdown = halShutdown;
++ HalFuncPtr->Tick = halTick;
++
++ /* keep a reference to HalFuncPtr so I can free it later */
++ HalPtr->HalFuncPtr = HalFuncPtr;
++
++ /* store the CPSAR_DEVICE, so the CPSAR module will know whether
++ it is in use for the given instance */
++ CpsarDev[Inst] = HalPtr;
++
++ /* increase count of attached modules */
++ HalPtr->InitCount++;
++ }
++
++ /* @todo Does this need modification to deal with multiple callers/
++ drivers? If different callers will use different OsDev/OsFunc,
++ then the current code will not work.
++ */
++
++ /* initialize the CPSAR_DEVICE structure */
++ HalPtr->OsDev = OsDev;
++ /*HalPtr->OsOpen = OsDev;*/
++ HalPtr->Inst = Inst;
++ HalPtr->OsFunc = OsFunc;
++
++ /* pass the HalPtr back to the caller */
++ *HalDev = HalPtr;
++ *HalFunc = HalPtr->HalFuncPtr;
++
++ return (EC_NO_ERRORS);
++ }
+diff -urN linux.old/drivers/atm/sangam_atm/cpsar_cpaal5.h linux.dev/drivers/atm/sangam_atm/cpsar_cpaal5.h
+--- linux.old/drivers/atm/sangam_atm/cpsar_cpaal5.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/cpsar_cpaal5.h 2005-08-23 04:46:50.087845216 +0200
+@@ -0,0 +1,103 @@
++/*******************************************************************************
++ * TNETDxxxx Software Support
++ * Copyright (c) 2002 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ * FILE: cpsar.h
++ *
++ * DESCRIPTION:
++ * This file contains data structure definitions for the CPSAR HAL.
++ *
++ * HISTORY:
++ * 6Sep02 Greg 1.00 Original Version created.
++ *
++ *****************************************************************************/
++#ifndef _INC_CPSAR
++#define _INC_CPSAR
++
++#define NUM_RX_STATE_WORDS 7
++#define NUM_TX_STATE_WORDS 9
++#define MAX_CHAN 19
++
++
++#ifndef _CPHAL_CPSAR
++typedef void CPSAR_DEVICE;
++#endif
++
++/*
++ * HAL Default Parameter Values
++ */
++#define CFG_UNI_NNI 0
++
++/**
++ * @ingroup shared_data
++ *
++ * List of defined keys for use with Control().
++ */
++typedef enum
++ {
++ /* SAR */
++ enGET_FIRMWARE, /**< Used by the SAR to request a pointer to firmware */
++ enGET_FIRMWARE_SIZE, /**< Used by the SAR to request the size of the firmware */
++ enEND=9999 /* Last entry */
++ }INFO_KEY;
++
++/*
++ * The CPHAL_FUNCTIONS struct defines the CPHAL function pointers used by upper layer
++ * software. The upper layer software receives these pointers through the
++ * call to cphalInitModule().
++ */
++typedef struct
++ {
++ int (*ChannelSetup)(CPSAR_DEVICE *HalDev, CHANNEL_INFO *HalCh);
++ int (*ChannelTeardown)(CPSAR_DEVICE *HalDev, int Ch, int Mode);
++ int (*Close)(CPSAR_DEVICE *HalDev, int Mode);
++ int (*Control)(CPSAR_DEVICE *HalDev, const char *Key, const char *Action, void *Value);
++ int (*Init)(CPSAR_DEVICE *HalDev);
++ int (*ModeChange)(CPSAR_DEVICE *HalDev, char *DeviceParms);
++ int (*Open)(CPSAR_DEVICE *HalDev);
++ int (*Probe)(CPSAR_DEVICE *HalDev);
++ int (*Shutdown)(CPSAR_DEVICE *HalDev);
++ int (*Tick)(CPSAR_DEVICE *HalDev);
++ } CPSAR_FUNCTIONS;
++
++/*
++ * This is the data structure for a generic HAL device. It contains all device
++ * specific data for a single instance of that device. This includes Rx/Tx
++ * buffer queues, device base address, reset bit, and other information.
++ */
++typedef struct cpsar_device
++ {
++ bit32 dev_base;
++ bit32 offset;
++ bit32 TxTeardownPending[MAX_CHAN];
++ bit32 RxTeardownPending[MAX_CHAN];
++ bit32 ChIsOpen[MAX_CHAN];
++ bit32 ResetBit;
++ bit32 debug;
++ OS_DEVICE *OsDev;
++ OS_FUNCTIONS *OsFunc;
++ /*void *OsOpen;*/
++ bit32 UniNni;
++ bit32 Inst;
++ bit32u DeviceCPID[4];
++ bit32u LBSourceLLID[4];
++ bit32u OamRate[11];
++ CHANNEL_INFO ChData[MAX_CHAN];
++ int InitCount;
++ int OpenCount;
++ char *DeviceInfo;
++ bit32u ResetBase;
++ DEVICE_STATE State;
++ CPSAR_FUNCTIONS *HalFuncPtr;
++ int OamMode; /* +GSG 030407 */
++ }CPSARDEVICE;
++
++extern int cpsarInitModule(CPSAR_DEVICE **HalDev,
++ OS_DEVICE *OsDev,
++ CPSAR_FUNCTIONS **HalFunc,
++ OS_FUNCTIONS *OsFunc,
++ int OsFuncSize,
++ int *HalFuncSize,
++ int Inst);
++
++#endif
+diff -urN linux.old/drivers/atm/sangam_atm/cpsar.h linux.dev/drivers/atm/sangam_atm/cpsar.h
+--- linux.old/drivers/atm/sangam_atm/cpsar.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/cpsar.h 2005-08-23 04:46:50.087845216 +0200
+@@ -0,0 +1,103 @@
++/*******************************************************************************
++ * TNETDxxxx Software Support
++ * Copyright (c) 2002 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ * FILE: cpsar.h
++ *
++ * DESCRIPTION:
++ * This file contains data structure definitions for the CPSAR HAL.
++ *
++ * HISTORY:
++ * 6Sep02 Greg 1.00 Original Version created.
++ *
++ *****************************************************************************/
++#ifndef _INC_CPSAR
++#define _INC_CPSAR
++
++#define NUM_RX_STATE_WORDS 7
++#define NUM_TX_STATE_WORDS 9
++#define MAX_CHAN 19
++
++
++#ifndef _CPHAL_CPSAR
++typedef void CPSAR_DEVICE;
++#endif
++
++/*
++ * HAL Default Parameter Values
++ */
++#define CFG_UNI_NNI 0
++
++/**
++ * @ingroup shared_data
++ *
++ * List of defined keys for use with Control().
++ */
++typedef enum
++ {
++ /* SAR */
++ enGET_FIRMWARE, /**< Used by the SAR to request a pointer to firmware */
++ enGET_FIRMWARE_SIZE, /**< Used by the SAR to request the size of the firmware */
++ enEND=9999 /* Last entry */
++ }INFO_KEY;
++
++/*
++ * The CPHAL_FUNCTIONS struct defines the CPHAL function pointers used by upper layer
++ * software. The upper layer software receives these pointers through the
++ * call to cphalInitModule().
++ */
++typedef struct
++ {
++ int (*ChannelSetup)(CPSAR_DEVICE *HalDev, CHANNEL_INFO *HalCh);
++ int (*ChannelTeardown)(CPSAR_DEVICE *HalDev, int Ch, int Mode);
++ int (*Close)(CPSAR_DEVICE *HalDev, int Mode);
++ int (*Control)(CPSAR_DEVICE *HalDev, const char *Key, const char *Action, void *Value);
++ int (*Init)(CPSAR_DEVICE *HalDev);
++ int (*ModeChange)(CPSAR_DEVICE *HalDev, char *DeviceParms);
++ int (*Open)(CPSAR_DEVICE *HalDev);
++ int (*Probe)(CPSAR_DEVICE *HalDev);
++ int (*Shutdown)(CPSAR_DEVICE *HalDev);
++ int (*Tick)(CPSAR_DEVICE *HalDev);
++ } CPSAR_FUNCTIONS;
++
++/*
++ * This is the data structure for a generic HAL device. It contains all device
++ * specific data for a single instance of that device. This includes Rx/Tx
++ * buffer queues, device base address, reset bit, and other information.
++ */
++typedef struct cpsar_device
++ {
++ bit32 dev_base;
++ bit32 offset;
++ bit32 TxTeardownPending[MAX_CHAN];
++ bit32 RxTeardownPending[MAX_CHAN];
++ bit32 ChIsOpen[MAX_CHAN];
++ bit32 ResetBit;
++ bit32 debug;
++ OS_DEVICE *OsDev;
++ OS_FUNCTIONS *OsFunc;
++ /*void *OsOpen;*/
++ bit32 UniNni;
++ bit32 Inst;
++ bit32u DeviceCPID[4];
++ bit32u LBSourceLLID[4];
++ bit32u OamRate[11];
++ CHANNEL_INFO ChData[MAX_CHAN];
++ int InitCount;
++ int OpenCount;
++ char *DeviceInfo;
++ bit32u ResetBase;
++ DEVICE_STATE State;
++ CPSAR_FUNCTIONS *HalFuncPtr;
++ int OamMode; /* +GSG 030407 */
++ }CPSARDEVICE;
++
++extern int cpsarInitModule(CPSAR_DEVICE **HalDev,
++ OS_DEVICE *OsDev,
++ CPSAR_FUNCTIONS **HalFunc,
++ OS_FUNCTIONS *OsFunc,
++ int OsFuncSize,
++ int *HalFuncSize,
++ int Inst);
++
++#endif
+diff -urN linux.old/drivers/atm/sangam_atm/cp_sar_reg.h linux.dev/drivers/atm/sangam_atm/cp_sar_reg.h
+--- linux.old/drivers/atm/sangam_atm/cp_sar_reg.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/cp_sar_reg.h 2005-08-23 04:46:50.087845216 +0200
+@@ -0,0 +1,217 @@
++/***************************************************************************
++ TNETD73xx Software Support
++ Copyright(c) 2000, Texas Instruments Incorporated. All Rights Reserved.
++
++ FILE: cp_sar_reg.h Register definitions for the SAR module
++
++ DESCRIPTION:
++ This include file contains register definitions for the
++ SAR module.
++
++ HISTORY:
++ 15 Jan 02 G. Guyotte Original version written
++ 03 Oct 02 G. Guyotte C++ style comments removed
++****************************************************************************/
++#ifndef _INC_SAR_REG
++#define _INC_SAR_REG
++
++/* Global Registers */
++#define pSAR_ID_REG(base) ((volatile bit32u *)(base+0x0000))
++#define SAR_ID_REG(base) (*pSAR_ID_REG(base))
++#define pSAR_STATUS_SET_REG(base) ((volatile bit32u *)(base+0x0008))
++#define SAR_STATUS_SET_REG(base) (*pSAR_STATUS_SET_REG(base))
++#define pSAR_STATUS_CLR_REG(base) ((volatile bit32u *)(base+0x000C))
++#define SAR_STATUS_CLR_REG(base) (*pSAR_STATUS_CLR_REG(base))
++#define pSAR_HOST_INT_EN_SET_REG(base) ((volatile bit32u *)(base+0x0010))
++#define SAR_HOST_INT_EN_SET_REG(base) (*pSAR_HOST_INT_EN_SET_REG(base))
++#define pSAR_HOST_INT_EN_CLR_REG(base) ((volatile bit32u *)(base+0x0014))
++#define SAR_HOST_INT_EN_CLR_REG(base) (*pSAR_HOST_INT_EN_CLR_REG(base))
++#define pSAR_PDSP_INT_EN_SET_REG(base) ((volatile bit32u *)(base+0x0018))
++#define SAR_PDSP_INT_EN_SET_REG(base) (*pSAR_PDSP_INT_EN_SET_REG(base))
++#define pSAR_PDSP_INT_EN_CLR_REG(base) ((volatile bit32u *)(base+0x001C))
++#define SAR_PDSP_INT_EN_CLR_REG(base) (*pSAR_PDSP_INT_EN_CLR_REG(base))
++
++/* PDSP OAM General Purpose Registers */
++#define pSAR_PDSP_HOST_OAM_CONFIG_REG(base) ((volatile bit32u *)(base+0x0020))
++#define SAR_PDSP_HOST_OAM_CONFIG_REG(base) (*pSAR_PDSP_HOST_OAM_CONFIG_REG(base))
++#define pSAR_PDSP_OAM_CORR_REG(base) ((volatile bit32u *)(base+0x0024))
++#define SAR_PDSP_OAM_CORR_REG(base) (*pSAR_PDSP_OAM_CORR_REG(base))
++#define pSAR_PDSP_OAM_LB_RESULT_REG(base) ((volatile bit32u *)(base+0x0028))
++#define SAR_PDSP_OAM_LB_RESULT_REG(base) (*pSAR_PDSP_OAM_LB_RESULT_REG(base))
++#define pSAR_PDSP_OAM_F5_LB_COUNT_REG(base) ((volatile bit32u *)(base+0x002c)) /* +GSG 030416 */
++#define SAR_PDSP_OAM_F5_LB_COUNT_REG(base) (*pSAR_PDSP_OAM_F5_LB_COUNT_REG(base)) /* +GSG 030416 */
++#define pSAR_PDSP_OAM_F4_LB_COUNT_REG(base) ((volatile bit32u *)(base+0x0030)) /* +GSG 030416 */
++#define SAR_PDSP_OAM_F4_LB_COUNT_REG(base) (*pSAR_PDSP_OAM_F4_LB_COUNT_REG(base)) /* +GSG 030416 */
++#define pSAR_PDSP_FWD_UNK_VC_REG(base) ((volatile bit32u *)(base+0x0034)) /* +GSG 030701 */
++#define SAR_PDSP_FWD_UNK_VC_REG(base) (*pSAR_PDSP_FWD_UNK_VC_REG(base)) /* +GSG 030701 */
++
++
++/* Rx Lookup Table Registers */
++#define pRX_LUT_GLOBAL_CFG_REG(base) ((volatile bit32u *)(base+0x0080))
++#define RX_LUT_GLOBAL_CFG_REG(base) (*pRX_LUT_GLOBAL_CFG_REG(base))
++#define pRX_LUT_CH_SETUP_REQ_REG(base) ((volatile bit32u *)(base+0x0090))
++#define RX_LUT_CH_SETUP_REQ_REG(base) (*pRX_LUT_CH_SETUP_REQ_REG(base))
++#define pRX_LUT_CH_SETUP_REQ_VC_REG(base) ((volatile bit32u *)(base+0x0094))
++#define RX_LUT_CH_SETUP_REQ_VC_REG(base) (*pRX_LUT_CH_SETUP_REQ_VC_REG(base))
++#define pRX_LUT_CH_TEARDOWN_REQ_REG(base) ((volatile bit32u *)(base+0x009C))
++#define RX_LUT_CH_TEARDOWN_REQ_REG(base) (*pRX_LUT_CH_TEARDOWN_REQ_REG(base))
++
++/* Tx Scheduler Registers */
++#define pTX_CH_MAPPING_REG(base) ((volatile bit32u *)(base+0x0170))
++#define TX_CH_MAPPING_REG(base) (*pTX_CH_MAPPING_REG(base))
++
++/* Tx CPPI DMA Controller Registers */
++#define pTX_CPPI_CTL_REG(base) ((volatile bit32u *)(base+0x0700))
++#define TX_CPPI_CTL_REG(base) (*pTX_CPPI_CTL_REG(base))
++#define pTX_CPPI_TEARDOWN_REG(base) ((volatile bit32u *)(base+0x0704))
++#define TX_CPPI_TEARDOWN_REG(base) (*pTX_CPPI_TEARDOWN_REG(base))
++
++/* EOI Interrupt Additions */
++#define pSAR_EOI(base) ((volatile bit32u *)(base+0x0708))
++#define SAR_EOI(base) (*pSAR_EOI(base))
++#define pSAR_INTR_VECTOR(base) ((volatile bit32u *)(base+0x070c))
++#define SAR_INTR_VECTOR(base) (*pSAR_INTR_VECTOR(base))
++#define pSAR_TX_MASKED_STATUS(base) ((volatile bit32u *)(base+0x0710))
++#define SAR_TX_MASKED_STATUS(base) (*pSAR_TX_MASKED_STATUS(base))
++#define pSAR_TX_RAW_STATUS(base) ((volatile bit32u *)(base+0x0714))
++#define SAR_TX_RAW_STATUS(base) (*pSAR_TX_RAW_STATUS(base))
++#define pSAR_TX_MASK_SET(base) ((volatile bit32u *)(base+0x0718))
++#define SAR_TX_MASK_SET(base) (*pSAR_TX_MASK_SET(base))
++#define pSAR_TX_MASK_CLR(base) ((volatile bit32u *)(base+0x071c))
++#define SAR_TX_MASK_CLR(base) (*pSAR_TX_MASK_CLR(base))
++
++/* Rx CPPI DMA Controller Registers */
++#define pRX_CPPI_CTL_REG(base) ((volatile bit32u *)(base+0x0780))
++#define RX_CPPI_CTL_REG(base) (*pRX_CPPI_CTL_REG(base))
++#define pSAR_RX_MASKED_STATUS(base) ((volatile bit32u *)(base+0x0790))
++#define SAR_RX_MASKED_STATUS(base) (*pSAR_RX_MASKED_STATUS(base))
++#define pSAR_RX_RAW_STATUS(base) ((volatile bit32u *)(base+0x0794))
++#define SAR_RX_RAW_STATUS(base) (*pSAR_RX_RAW_STATUS(base))
++#define pSAR_RX_MASK_SET(base) ((volatile bit32u *)(base+0x0798))
++#define SAR_RX_MASK_SET(base) (*pSAR_RX_MASK_SET(base))
++#define pSAR_RX_MASK_CLR(base) ((volatile bit32u *)(base+0x079c))
++#define SAR_RX_MASK_CLR(base) (*pSAR_RX_MASK_CLR(base))
++
++/* PDSP Control/Status Registers */
++#define pPDSP_CTRL_REG(base) ((volatile bit32u *)(base+0x4000))
++#define PDSP_CTRL_REG(base) (*pPDSP_CTRL_REG(base))
++
++/* PDSP Instruction RAM */
++#define pPDSP_IRAM(base) ((volatile bit32u *)(base+0x4020))
++#define PDSP_IRAM(base) (*pPDSP_IRAM(base))
++
++/*
++ * Channel 0 State/Scratchpad RAM Block
++ *
++ * The following registers (Tx DMA State, Rx DMA State, CPPI Completion PTR,
++ * and PDSP Data) have been given the correct address for channel 0. To
++ * reach the registers for channel X, add (X * 0x100) to the pointer address.
++ *
++ */
++
++#define PDSP_STATE_RAM_SIZE 1024
++
++/* Tx DMA State RAM */
++#define pTX_DMA_STATE_WORD_0(base) ((volatile bit32u *)(base+0x8000))
++#define TX_DMA_STATE_WORD_0(base) (*pTX_DMA_STATE_WORD_0(base))
++#define pTX_DMA_STATE_WORD_1(base) ((volatile bit32u *)(base+0x8004))
++#define TX_DMA_STATE_WORD_1(base) (*pTX_DMA_STATE_WORD_1(base))
++#define pTX_DMA_STATE_WORD_2(base) ((volatile bit32u *)(base+0x8008))
++#define TX_DMA_STATE_WORD_2(base) (*pTX_DMA_STATE_WORD_2(base))
++#define pTX_DMA_STATE_WORD_3(base) ((volatile bit32u *)(base+0x800C))
++#define TX_DMA_STATE_WORD_3(base) (*pTX_DMA_STATE_WORD_3(base))
++#define pTX_DMA_STATE_WORD_4(base) ((volatile bit32u *)(base+0x8010))
++#define TX_DMA_STATE_WORD_4(base) (*pTX_DMA_STATE_WORD_4(base))
++#define pTX_DMA_STATE_WORD_5(base) ((volatile bit32u *)(base+0x8014))
++#define TX_DMA_STATE_WORD_5(base) (*pTX_DMA_STATE_WORD_5(base))
++#define pTX_DMA_STATE_WORD_6(base) ((volatile bit32u *)(base+0x8018))
++#define TX_DMA_STATE_WORD_6(base) (*pTX_DMA_STATE_WORD_6(base))
++#define pTX_DMA_STATE_WORD_7(base) ((volatile bit32u *)(base+0x801C))
++#define TX_DMA_STATE_WORD_7(base) (*pTX_DMA_STATE_WORD_7(base))
++#define pTX_DMA_STATE_WORD_8(base) ((volatile bit32u *)(base+0x8020))
++#define TX_DMA_STATE_WORD_8(base) (*pTX_DMA_STATE_WORD_8(base))
++
++/* Rx DMA State RAM */
++#define pRX_DMA_STATE_WORD_0(base) ((volatile bit32u *)(base+0x8024))
++#define RX_DMA_STATE_WORD_0(base) (*pRX_DMA_STATE_WORD_0(base))
++#define pRX_DMA_STATE_WORD_1(base) ((volatile bit32u *)(base+0x8028))
++#define RX_DMA_STATE_WORD_1(base) (*pRX_DMA_STATE_WORD_1(base))
++#define pRX_DMA_STATE_WORD_2(base) ((volatile bit32u *)(base+0x802C))
++#define RX_DMA_STATE_WORD_2(base) (*pRX_DMA_STATE_WORD_2(base))
++#define pRX_DMA_STATE_WORD_3(base) ((volatile bit32u *)(base+0x8030))
++#define RX_DMA_STATE_WORD_3(base) (*pRX_DMA_STATE_WORD_3(base))
++#define pRX_DMA_STATE_WORD_4(base) ((volatile bit32u *)(base+0x8034))
++#define RX_DMA_STATE_WORD_4(base) (*pRX_DMA_STATE_WORD_4(base))
++#define pRX_DMA_STATE_WORD_5(base) ((volatile bit32u *)(base+0x8038))
++#define RX_DMA_STATE_WORD_5(base) (*pRX_DMA_STATE_WORD_5(base))
++#define pRX_DMA_STATE_WORD_6(base) ((volatile bit32u *)(base+0x803C))
++#define RX_DMA_STATE_WORD_6(base) (*pRX_DMA_STATE_WORD_6(base))
++
++/* Tx CPPI Completion Pointers */
++#define pTXH_CPPI_COMP_PTR(base) ((volatile bit32u *)(base+0x8040))
++#define TXH_CPPI_COMP_PTR(base) (*pTXH_CPPI_COMP_PTR(base))
++#define pTXL_CPPI_COMP_PTR(base) ((volatile bit32u *)(base+0x8044))
++#define TXL_CPPI_COMP_PTR(base) (*pTXL_CPPI_COMP_PTR(base))
++
++/* Rx CPPI Completion Pointer */
++#define pRX_CPPI_COMP_PTR(base) ((volatile bit32u *)(base+0x8048))
++#define RX_CPPI_COMP_PTR(base) (*pRX_CPPI_COMP_PTR(base))
++
++/* Tx PDSP Defines */
++#define NUM_PDSP_AAL5_STATE_WORDS 24
++#define NUM_PDSP_AAL2_STATE_WORDS 20
++
++/* PDSP State RAM Block 0 */
++#define pPDSP_BLOCK_0(base) ((volatile bit32u *)(base+0x8050))
++#define PDSP_BLOCK_0(base) (*pPDSP_BLOCK_0(base))
++
++/* AAL5 Tx PDSP State RAM */
++#define pPDSP_AAL5_TX_STATE_WORD_0(base) ((volatile bit32u *)(base+0x8050))
++#define PDSP_AAL5_TX_STATE_WORD_0(base) (*pPDSP_AAL5_TX_STATE_WORD_0(base))
++
++/* AAL5 Rx PDSP State RAM */
++#define pPDSP_AAL5_RX_STATE_WORD_0(base) ((volatile bit32u *)(base+0x8070))
++#define PDSP_AAL5_RX_STATE_WORD_0(base) (*pPDSP_AAL5_RX_STATE_WORD_0(base))
++
++/* AAL5 Tx VP PDSP State RAM */
++#define pPDSP_AAL5_TX_VP_STATE_WORD_0(base) ((volatile bit32u *)(base+0x8090))
++#define PDSP_AAL5_TX_VP_STATE_WORD_0(base) (*pPDSP_AAL5_TX_VP_STATE_WORD_0(base))
++
++/* AAL5 Rx VP PDSP State RAM */
++#define pPDSP_AAL5_RX_VP_STATE_WORD_0(base) ((volatile bit32u *)(base+0x80A0))
++#define PDSP_AAL5_RX_VP_STATE_WORD_0(base) (*pPDSP_AAL5_RX_VP_STATE_WORD_0(base))
++
++/* AAL2 Tx PDSP State RAM */
++#define pPDSP_AAL2_TX_STATE_WORD_0(base) ((volatile bit32u *)(base+0x80B0))
++#define PDSP_AAL2_TX_STATE_WORD_0(base) (*pPDSP_AAL2_TX_STATE_WORD_0(base))
++
++/* AAL2 Rx PDSP State RAM */
++#define pPDSP_AAL2_RX_STATE_WORD_0(base) ((volatile bit32u *)(base+0x80D0))
++#define PDSP_AAL2_RX_STATE_WORD_0(base) (*pPDSP_AAL2_RX_STATE_WORD_0(base))
++
++/* AAL2 Tx VP PDSP State RAM */
++#define pPDSP_AAL2_TX_VP_STATE_WORD_0(base) ((volatile bit32u *)(base+0x80E0))
++#define PDSP_AAL2_TX_VP_STATE_WORD_0(base) (*pPDSP_AAL2_TX_VP_STATE_WORD_0(base))
++
++/* AAL2 Rx VP PDSP State RAM */
++#define pPDSP_AAL2_RX_VP_STATE_WORD_0(base) ((volatile bit32u *)(base+0x80F0))
++#define PDSP_AAL2_RX_VP_STATE_WORD_0(base) (*pPDSP_AAL2_RX_VP_STATE_WORD_0(base))
++
++/* PDSP OAM Configuration Block */
++#define pOAM_CONFIG_BLOCK_WORD_0(base) ((volatile bit32u *)(base+0x83C0))
++#define OAM_CONFIG_BLOCK_WORD_0(base) (*pOAM_CONFIG_BLOCK_WORD_0(base))
++
++/* PDSP OAM Padding Block */
++#define pOAM_PADDING_BLOCK_WORD_0(base) ((volatile bit32u *)(base+0x84C0))
++#define OAM_PADDING_BLOCK_WORD_0(base) (*pOAM_PADDING_BLOCK_WORD_0(base))
++
++#define NUM_OAM_RATES 11
++
++/* PDSP OAM Timer State RAM */
++#define pOAM_TIMER_STATE_WORD_0(base) ((volatile bit32u *)(base+0x85B0))
++#define OAM_TIMER_STATE_WORD_0(base) (*pOAM_TIMER_STATE_WORD_0(base))
++
++
++/* END OF FILE */
++
++#endif _INC_SAR_REG
+diff -urN linux.old/drivers/atm/sangam_atm/cpswhal_cpaal5.h linux.dev/drivers/atm/sangam_atm/cpswhal_cpaal5.h
+--- linux.old/drivers/atm/sangam_atm/cpswhal_cpaal5.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/cpswhal_cpaal5.h 2005-08-23 04:46:50.088845064 +0200
+@@ -0,0 +1,629 @@
++/************************************************************************
++ * TNETDxxxx Software Support
++ * Copyright (c) 2002 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ * FILE: cphal.h
++ *
++ * DESCRIPTION:
++ * User include file, contains data definitions shared between the CPHAL
++ * and the upper-layer software.
++ *
++ * HISTORY:
++ * Date Modifier Ver Notes
++ * 28Feb02 Greg 1.00 Original
++ * 06Mar02 Greg 1.01 Documentation enhanced
++ * 18Jul02 Greg 1.02 Many updates (OAM additions, general reorg)
++ * 22Nov02 Mick RC2 Additions from Denis' input on Control
++ *
++ * author Greg Guyotte
++ * version 1.02
++ * date 18-Jul-2002
++ *****************************************************************************/
++#ifndef _INC_CPHAL_H
++#define _INC_CPHAL_H
++
++#ifdef _CPHAL_CPMAC
++#include "ec_errors_cpmac.h"
++#endif
++
++#ifdef _CPHAL_AAL5
++#include "ec_errors_cpaal5.h"
++#endif
++
++#ifdef _CPHAL_CPSAR
++#include "ec_errors_cpsar.h"
++#endif
++
++#ifdef _CPHAL_AAL2
++#include "ec_errors_cpaal2.h"
++#endif
++
++#ifndef __ADAM2
++typedef char bit8;
++typedef short bit16;
++typedef int bit32;
++
++typedef unsigned char bit8u;
++typedef unsigned short bit16u;
++typedef unsigned int bit32u;
++
++/*
++typedef char INT8;
++typedef short INT16;
++typedef int INT32;
++typedef unsigned char UINT8;
++typedef unsigned short UINT16;
++typedef unsigned int UINT32;
++*/
++/*typedef unsigned int size_t;*/
++#endif
++
++#ifdef _CPHAL
++
++#ifndef TRUE
++#define TRUE (1==1)
++#endif
++
++#ifndef FALSE
++#define FALSE (1==2)
++#endif
++
++#ifndef NULL
++#define NULL 0
++#endif
++
++#endif
++
++#define VirtToPhys(a) (((int)a)&~0xe0000000)
++#define VirtToVirtNoCache(a) ((void*)((VirtToPhys(a))|0xa0000000))
++#define VirtToVirtCache(a) ((void*)((VirtToPhys(a))|0x80000000))
++#define PhysToVirtNoCache(a) ((void*)(((int)a)|0xa0000000))
++#define PhysToVirtCache(a) ((void*)(((int)a)|0x80000000))
++/*
++#define DataCacheHitInvalidate(a) {__asm__(" cache 17, (%0)" : : "r" (a));}
++#define DataCacheHitWriteback(a) {__asm__(" cache 25, (%0)" : : "r" (a));}
++*/
++
++#define PARTIAL 1 /**< Used in @c Close() and @c ChannelTeardown() */
++#define FULL 2 /**< Used in @c Close() and @c ChannelTeardown() */
++
++/* Channel Teardown Defines */
++#define RX_TEARDOWN 2
++#define TX_TEARDOWN 1
++#define BLOCKING_TEARDOWN 8
++#define FULL_TEARDOWN 4
++#define PARTIAL_TEARDOWN 0
++
++#define MAX_DIR 2
++#define DIRECTION_TX 0
++#define DIRECTION_RX 1
++#define TX_CH 0
++#define RX_CH 1
++#define HAL_ERROR_DEVICE_NOT_FOUND 1
++#define HAL_ERROR_FAILED_MALLOC 2
++#define HAL_ERROR_OSFUNC_SIZE 3
++#define HAL_DEFAULT 0xFFFFFFFF
++#define VALID(val) (val!=HAL_DEFAULT)
++
++/*
++ERROR REPORTING
++
++HAL Module Codes. Each HAL module reporting an error code
++should OR the error code with the respective Module error code
++from the list below.
++*/
++#define EC_AAL5 EC_HAL|EC_DEV_AAL5
++#define EC_AAL2 EC_HAL|EC_DEV_AAL2
++#define EC_CPSAR EC_HAL|EC_DEV_CPSAR
++#define EC_CPMAC EC_HAL|EC_DEV_CPMAC
++#define EC_VDMA EC_HAL|EC_DEV_VDMA
++#define EC_VLYNQ EC_HAL|EC_DEV_VLYNQ
++#define EC_CPPI EC_HAL|EC_DEV_CPPI
++
++/*
++HAL Function Codes. Each HAL module reporting an error code
++should OR the error code with one of the function codes from
++the list below.
++*/
++#define EC_FUNC_HAL_INIT EC_FUNC(1)
++#define EC_FUNC_CHSETUP EC_FUNC(2)
++#define EC_FUNC_CHTEARDOWN EC_FUNC(3)
++#define EC_FUNC_RXRETURN EC_FUNC(4)
++#define EC_FUNC_SEND EC_FUNC(5)
++#define EC_FUNC_RXINT EC_FUNC(6)
++#define EC_FUNC_TXINT EC_FUNC(7)
++#define EC_FUNC_AAL2_VDMA EC_FUNC(8)
++#define EC_FUNC_OPTIONS EC_FUNC(9)
++#define EC_FUNC_PROBE EC_FUNC(10)
++#define EC_FUNC_OPEN EC_FUNC(11)
++#define EC_FUNC_CONTROL EC_FUNC(12)
++#define EC_FUNC_DEVICE_INT EC_FUNC(13)
++#define EC_FUNC_STATUS EC_FUNC(14)
++#define EC_FUNC_TICK EC_FUNC(15)
++#define EC_FUNC_CLOSE EC_FUNC(16)
++#define EC_FUNC_SHUTDOWN EC_FUNC(17)
++#define EC_FUNC_DEVICE_INT_ALT EC_FUNC(18) /* +GSG 030306 */
++
++/*
++HAL Error Codes. The list below defines every type of error
++used in all HAL modules. DO NOT CHANGE THESE VALUES! Add new
++values in integer order to the bottom of the list.
++*/
++#define EC_VAL_PDSP_LOAD_FAIL EC_ERR(0x01)|EC_CRITICAL
++#define EC_VAL_FIRMWARE_TOO_LARGE EC_ERR(0x02)|EC_CRITICAL
++#define EC_VAL_DEVICE_NOT_FOUND EC_ERR(0x03)|EC_CRITICAL
++#define EC_VAL_BASE_ADDR_NOT_FOUND EC_ERR(0x04)|EC_CRITICAL
++#define EC_VAL_RESET_BIT_NOT_FOUND EC_ERR(0x05)|EC_CRITICAL
++#define EC_VAL_CH_INFO_NOT_FOUND EC_ERR(0x06)
++#define EC_VAL_RX_STATE_RAM_NOT_CLEARED EC_ERR(0x07)|EC_CRITICAL
++#define EC_VAL_TX_STATE_RAM_NOT_CLEARED EC_ERR(0x08)|EC_CRITICAL
++#define EC_VAL_MALLOC_DEV_FAILED EC_ERR(0x09)
++#define EC_VAL_OS_VERSION_NOT_SUPPORTED EC_ERR(0x0A)|EC_CRITICAL
++#define EC_VAL_CPSAR_VERSION_NOT_SUPPORTED EC_ERR(0x0B)|EC_CRITICAL
++#define EC_VAL_NULL_CPSAR_DEV EC_ERR(0x0C)|EC_CRITICAL
++
++#define EC_VAL_LUT_NOT_READY EC_ERR(0x0D)
++#define EC_VAL_INVALID_CH EC_ERR(0x0E)
++#define EC_VAL_NULL_CH_STRUCT EC_ERR(0x0F)
++#define EC_VAL_RX_TEARDOWN_ALREADY_PEND EC_ERR(0x10)
++#define EC_VAL_TX_TEARDOWN_ALREADY_PEND EC_ERR(0x11)
++#define EC_VAL_RX_CH_ALREADY_TORNDOWN EC_ERR(0x12)
++#define EC_VAL_TX_CH_ALREADY_TORNDOWN EC_ERR(0x13)
++#define EC_VAL_TX_TEARDOWN_TIMEOUT EC_ERR(0x14)
++#define EC_VAL_RX_TEARDOWN_TIMEOUT EC_ERR(0x15)
++#define EC_VAL_CH_ALREADY_TORNDOWN EC_ERR(0x16)
++#define EC_VAL_VC_SETUP_NOT_READY EC_ERR(0x17)
++#define EC_VAL_VC_TEARDOWN_NOT_READY EC_ERR(0x18)
++#define EC_VAL_INVALID_VC EC_ERR(0x19)
++#define EC_VAL_INVALID_LC EC_ERR(0x20)
++#define EC_VAL_INVALID_VDMA_CH EC_ERR(0x21)
++#define EC_VAL_INVALID_CID EC_ERR(0x22)
++#define EC_VAL_INVALID_UUI EC_ERR(0x23)
++#define EC_VAL_INVALID_UUI_DISCARD EC_ERR(0x24)
++#define EC_VAL_CH_ALREADY_OPEN EC_ERR(0x25)
++
++#define EC_VAL_RCB_MALLOC_FAILED EC_ERR(0x26)
++#define EC_VAL_RX_BUFFER_MALLOC_FAILED EC_ERR(0x27)
++#define EC_VAL_OUT_OF_TCBS EC_ERR(0x28)
++#define EC_VAL_NO_TCBS EC_ERR(0x29)
++#define EC_VAL_NULL_RCB EC_ERR(0x30)|EC_CRITICAL
++#define EC_VAL_SOP_ERROR EC_ERR(0x31)|EC_CRITICAL
++#define EC_VAL_EOP_ERROR EC_ERR(0x32)|EC_CRITICAL
++#define EC_VAL_NULL_TCB EC_ERR(0x33)|EC_CRITICAL
++#define EC_VAL_CORRUPT_RCB_CHAIN EC_ERR(0x34)|EC_CRITICAL
++#define EC_VAL_TCB_MALLOC_FAILED EC_ERR(0x35)
++
++#define EC_VAL_DISABLE_POLLING_FAILED EC_ERR(0x36)
++#define EC_VAL_KEY_NOT_FOUND EC_ERR(0x37)
++#define EC_VAL_MALLOC_FAILED EC_ERR(0x38)
++#define EC_VAL_RESET_BASE_NOT_FOUND EC_ERR(0x39)|EC_CRITICAL
++#define EC_VAL_INVALID_STATE EC_ERR(0x40)
++#define EC_VAL_NO_TXH_WORK_TO_DO EC_ERR(0x41)
++#define EC_VAL_NO_TXL_WORK_TO_DO EC_ERR(0x42)
++#define EC_VAL_NO_RX_WORK_TO_DO EC_ERR(0x43)
++#define EC_VAL_NOT_LINKED EC_ERR(0x44)
++#define EC_VAL_INTERRUPT_NOT_FOUND EC_ERR(0x45)
++#define EC_VAL_OFFSET_NOT_FOUND EC_ERR(0x46)
++#define EC_VAL_MODULE_ALREADY_CLOSED EC_ERR(0x47)
++#define EC_VAL_MODULE_ALREADY_SHUTDOWN EC_ERR(0x48)
++#define EC_VAL_ACTION_NOT_FOUND EC_ERR(0x49)
++#define EC_VAL_RX_CH_ALREADY_SETUP EC_ERR(0x50)
++#define EC_VAL_TX_CH_ALREADY_SETUP EC_ERR(0x51)
++#define EC_VAL_RX_CH_ALREADY_OPEN EC_ERR(0x52)
++#define EC_VAL_TX_CH_ALREADY_OPEN EC_ERR(0x53)
++#define EC_VAL_CH_ALREADY_SETUP EC_ERR(0x54)
++#define EC_VAL_RCB_NEEDS_BUFFER EC_ERR(0x55) /* +GSG 030410 */
++#define EC_VAL_RCB_DROPPED EC_ERR(0x56) /* +GSG 030410 */
++#define EC_VAL_INVALID_VALUE EC_ERR(0x57)
++
++/**
++@defgroup shared_data Shared Data Structures
++
++The data structures documented here are shared by all modules.
++*/
++
++/**
++ * @ingroup shared_data
++ * This is the fragment list structure. Each fragment list entry contains a
++ * length and a data buffer.
++ */
++typedef struct
++ {
++ bit32u len; /**< Length of the fragment in bytes (lower 16 bits are valid). For SOP, upper 16 bits is the buffer offset. */
++ void *data; /**< Pointer to fragment data. */
++ void *OsInfo; /**< Pointer to OS defined data. */
++ }FRAGLIST;
++
++#if defined (_CPHAL_CPMAC)
++#define CB_PASSCRC_BIT (1<<26)
++
++/* CPMAC CPHAL STATUS */
++#define CPMAC_STATUS_LINK (1 << 0)
++#define CPMAC_STATUS_LINK_DUPLEX (1 << 1) /* 0 - HD, 1 - FD */
++#define CPMAC_STATUS_LINK_SPEED (1 << 2) /* 0 - 10, 1 - 100 */
++
++/* ADAPTER CHECK Codes */
++
++#define CPMAC_STATUS_ADAPTER_CHECK (1 << 7)
++#define CPMAC_STATUS_HOST_ERR_DIRECTION (1 << 8)
++#define CPMAC_STATUS_HOST_ERR_CODE (0xF << 9)
++#define CPMAC_STATUS_HOST_ERR_CH (0x7 << 13)
++
++#define _CPMDIO_DISABLE (1 << 0)
++#define _CPMDIO_HD (1 << 1)
++#define _CPMDIO_FD (1 << 2)
++#define _CPMDIO_10 (1 << 3)
++#define _CPMDIO_100 (1 << 4)
++#define _CPMDIO_NEG_OFF (1 << 5)
++#define _CPMDIO_LOOPBK (1 << 16)
++#define _CPMDIO_NOPHY (1 << 20)
++#endif
++
++/**
++ * @ingroup shared_data
++ * Channel specific configuration information. This structure should be
++ * populated by upper-layer software prior to calling @c ChannelSetup(). Any
++ * configuration item that can be changed on a per channel basis should
++ * be represented here. Each module may define this structure with additional
++ * module-specific members.
++ */
++typedef struct
++ {
++ int Channel; /**< Channel number. */
++ int Direction; /**< DIRECTION_RX(1) or DIRECTION_TX(0). */
++ OS_SETUP *OsSetup; /**< OS defined information associated with this channel. */
++
++#if defined(_CPHAL_AAL5) || defined (_CPHAL_CPSAR) || defined (_CPHAL_CPMAC)
++ int RxBufSize; /**< Size (in bytes) for each Rx buffer.*/
++ int RxBufferOffset; /**< Number of bytes to offset rx data from start of buffer (must be less than buffer size). */
++ int RxNumBuffers; /**< The number of Rx buffer descriptors to allocate for Ch. */
++ int RxServiceMax; /**< Maximum number of packets to service at one time. */
++
++ int TxNumBuffers; /**< The number of Tx buffer descriptors to allocate for Ch. */
++ int TxNumQueues; /**< Number of Tx queues for this channel (1-2). Choosing 2 enables a low priority SAR queue. */
++ int TxServiceMax; /**< Maximum number of packets to service at one time. */
++#endif
++
++#if defined(_CPHAL_AAL5) || defined(_CPHAL_CPSAR)
++ int CpcsUU; /**< The 2-byte CPCS UU and CPI information. */
++ int Gfc; /**< Generic Flow Control. */
++ int Clp; /**< Cell Loss Priority. */
++ int Pti; /**< Payload Type Indication. */
++#endif
++
++#if defined(_CPHAL_AAL2) || defined(_CPHAL_AAL5) || defined(_CPHAL_CPSAR)
++ int DaMask; /**< Specifies whether credit issuance is paused when Tx data not available. */
++ int Priority; /**< Priority bin this channel will be scheduled within. */
++ int PktType; /**< 0=AAL5,1=Null AAL,2=OAM,3=Transparent,4=AAL2. */
++ int Vci; /**< Virtual Channel Identifier. */
++ int Vpi; /**< Virtual Path Identifier. */
++ int FwdUnkVc; /**< Enables forwarding of unknown VCI/VPI cells to host. 1=enable, 0=disable. */
++
++ /* Tx VC State */
++ int TxVc_CellRate; /**< Tx rate, set as clock ticks between transmissions (SCR for VBR, CBR for CBR). */
++ int TxVc_QosType; /**< 0=CBR,1=VBR,2=UBR,3=UBRmcr. */
++ int TxVc_Mbs; /**< Min Burst Size in cells.*/
++ int TxVc_Pcr; /**< Peak Cell Rate for VBR in clock ticks between transmissions. */
++
++ bit32 TxVc_AtmHeader; /**< ATM Header placed on firmware gen'd OAM cells for this Tx Ch (must be big endian with 0 PTI). */
++ int TxVc_OamTc; /**< TC Path to transmit OAM cells for TX connection (0,1). */
++ int TxVc_VpOffset; /**< Offset to the OAM VP state table. */
++ /* Rx VC State */
++ int RxVc_OamCh; /**< Ch to terminate rx'd OAM cells to be forwarded to the host. */
++ int RxVc_OamToHost; /**< 0=do not pass, 1=pass. */
++ bit32 RxVc_AtmHeader; /**< ATM Header placed on firmware gen'd OAM cells for this Rx conn (must be big endian with 0 PTI). */
++ int RxVc_OamTc; /**< TC Path to transmit OAM cells for RX connection (0,1). */
++ int RxVc_VpOffset; /**< Offset to the OAM VP state table. */
++ /* Tx VP State */
++ int TxVp_OamTc; /**< TC Path to transmit OAM cells for TX VP connection (0,1). */
++ bit32 TxVp_AtmHeader; /**< ATM Header placed on firmware gen'd VP OAM cells for this Tx VP conn (must be big endian with 0 VCI). */
++ /* Rx VP State */
++ int RxVp_OamCh; /**< Ch to terminate rx'd OAM cells to be forwarded to the host. */
++ int RxVp_OamToHost; /**< 0=do not pass, 1=pass. */
++ bit32 RxVp_AtmHeader; /**< ATM Header placed on firmware gen'd OAM cells for this Rx VP conn (must be big endian with 0 VCI). */
++ int RxVp_OamTc; /**< TC Path to transmit OAM cells for RX VP connection (0,1). */
++ int RxVp_OamVcList; /**< Indicates all VC channels associated with this VP channel (one-hot encoded). */
++#endif
++
++
++#ifdef _CPHAL_VDMAVT
++ bit32u RemFifoAddr; /* Mirror mode only. */
++ bit32u FifoAddr;
++ bit32 PollInt;
++ bit32 FifoSize;
++ int Ready;
++#endif
++
++ }CHANNEL_INFO;
++
++/*
++ * This structure contains each statistic value gathered by the CPHAL.
++ * Applications may access statistics data by using the @c StatsGet() routine.
++ */
++/* STATS */
++#if defined(_CPHAL_AAL2) || defined(_CPHAL_AAL5) || defined(_CPHAL_CPSAR)
++typedef struct
++ {
++ bit32u CrcErrors[16];
++ bit32u LenErrors[16];
++ bit32u DmaLenErrors[16];
++ bit32u AbortErrors[16];
++ bit32u StarvErrors[16];
++ bit32u TxMisQCnt[16][2];
++ bit32u RxMisQCnt[16];
++ bit32u RxEOQCnt[16];
++ bit32u TxEOQCnt[16][2];
++ bit32u RxPacketsServiced[16];
++ bit32u TxPacketsServiced[16][2];
++ bit32u RxMaxServiced;
++ bit32u TxMaxServiced[16][2];
++ bit32u RxTotal;
++ bit32u TxTotal;
++ } STAT_INFO;
++#endif
++
++/*
++ * VDMA Channel specific configuration information
++ */
++#ifdef _CPHAL_AAL2
++typedef struct
++ {
++ int Ch; /**< Channel Number */
++ int RemoteEndian; /**< Endianness of remote VDMA-VT device */
++ int CpsSwap; /**< When 0, octet 0 in CPS pkt located in LS byte of 16-bit word sent to rem VDMA device. When 1, in MS byte. */
++ }VdmaChInfo;
++#endif
++
++#ifndef _CPHAL
++ typedef void HAL_DEVICE;
++ typedef void HAL_PRIVATE;
++ typedef void HAL_RCB;
++ typedef void HAL_RECEIVEINFO;
++#endif
++
++/**
++ * @ingroup shared_data
++ * The HAL_FUNCTIONS struct defines the function pointers used by upper layer
++ * software. The upper layer software receives these pointers through the
++ * call to xxxInitModule().
++ */
++typedef struct
++ {
++ int (*ChannelSetup) (HAL_DEVICE *HalDev, CHANNEL_INFO *Channel, OS_SETUP *OsSetup);
++ int (*ChannelTeardown) (HAL_DEVICE *HalDev, int Channel, int Mode);
++ int (*Close) (HAL_DEVICE *HalDev, int Mode);
++ int (*Control) (HAL_DEVICE *HalDev, const char *Key, const char *Action, void *Value);
++ int (*Init) (HAL_DEVICE *HalDev);
++ int (*Open) (HAL_DEVICE *HalDev);
++ int (*PacketProcessEnd) (HAL_DEVICE *HalDev);
++ int (*Probe) (HAL_DEVICE *HalDev);
++ int (*RxReturn) (HAL_RECEIVEINFO *HalReceiveInfo, int StripFlag);
++ int (*Send) (HAL_DEVICE *HalDev, FRAGLIST *FragList, int FragCount, int PacketSize, OS_SENDINFO *OsSendInfo, bit32u Mode);
++ int (*Shutdown) (HAL_DEVICE *HalDev);
++ int (*Tick) (HAL_DEVICE *HalDev);
++
++#ifdef _CPHAL_AAL5
++ int (*Kick) (HAL_DEVICE *HalDev, int Queue);
++ void (*OamFuncConfig) (HAL_DEVICE *HalDev, unsigned int OamConfig);
++ void (*OamLoopbackConfig) (HAL_DEVICE *HalDev, unsigned int OamConfig, unsigned int *LLID, unsigned int CorrelationTag);
++ volatile bit32u* (*RegAccess)(HAL_DEVICE *HalDev, bit32u RegOffset);
++ STAT_INFO* (*StatsGetOld)(HAL_DEVICE *HalDev);
++#endif
++ } HAL_FUNCTIONS;
++
++/**
++ * @ingroup shared_data
++ * The OS_FUNCTIONS struct defines the function pointers for all upper layer
++ * functions accessible to the CPHAL. The upper layer software is responsible
++ * for providing the correct OS-specific implementations for the following
++ * functions. It is populated by calling InitModule() (done by the CPHAL in
++ * xxxInitModule().
++ */
++typedef struct
++ {
++ int (*Control)(OS_DEVICE *OsDev, const char *Key, const char *Action, void *Value);
++ void (*CriticalOn)(void);
++ void (*CriticalOff)(void);
++ void (*DataCacheHitInvalidate)(void *MemPtr, int Size);
++ void (*DataCacheHitWriteback)(void *MemPtr, int Size);
++ int (*DeviceFindInfo)(int Inst, const char *DeviceName, void *DeviceInfo);
++ int (*DeviceFindParmUint)(void *DeviceInfo, const char *Parm, bit32u *Value);
++ int (*DeviceFindParmValue)(void *DeviceInfo, const char *Parm, void *Value);
++ void (*Free)(void *MemPtr);
++ void (*FreeRxBuffer)(OS_RECEIVEINFO *OsReceiveInfo, void *MemPtr);
++ void (*FreeDev)(void *MemPtr);
++ void (*FreeDmaXfer)(void *MemPtr);
++ void (*IsrRegister)(OS_DEVICE *OsDev, int (*halISR)(HAL_DEVICE*, int*), int InterruptBit);
++ void (*IsrUnRegister)(OS_DEVICE *OsDev, int InterruptBit);
++ void* (*Malloc)(bit32u size);
++ void* (*MallocDev)(bit32u Size);
++ void* (*MallocDmaXfer)(bit32u size, void *MemBase, bit32u MemRange);
++ void* (*MallocRxBuffer)(bit32u size, void *MemBase, bit32u MemRange,
++ OS_SETUP *OsSetup, HAL_RECEIVEINFO *HalReceiveInfo,
++ OS_RECEIVEINFO **OsReceiveInfo, OS_DEVICE *OsDev);
++ void* (*Memset)(void *Dest, int C, bit32u N);
++ int (*Printf)(const char *Format, ...);
++ int (*Receive)(OS_DEVICE *OsDev,FRAGLIST *FragList,bit32u FragCount,
++ bit32u PacketSize,HAL_RECEIVEINFO *HalReceiveInfo, bit32u Mode);
++ int (*SendComplete)(OS_SENDINFO *OsSendInfo);
++ int (*Sprintf)(char *S, const char *Format, ...);
++ int (*Strcmpi)(const char *Str1, const char *Str2);
++ unsigned int (*Strlen)(const char *S);
++ char* (*Strstr)(const char *S1, const char *S2);
++ unsigned long (*Strtoul)(const char *Str, char **Endptr, int Base);
++ void (*TeardownComplete)(OS_DEVICE *OsDev, int Ch, int Direction);
++ } OS_FUNCTIONS;
++
++/************** MODULE SPECIFIC STUFF BELOW **************/
++
++#ifdef _CPHAL_CPMAC
++
++/*
++int halCpmacInitModule(HAL_DEVICE **HalDev, OS_DEVICE *OsDev, HAL_FUNCTIONS *HalFunc, int (*osBridgeInitModule)(OS_FUNCTIONS *), void* (*osMallocDev) (bit32u), int *Size, int inst);
++*/
++
++int halCpmacInitModule(HAL_DEVICE **HalDev,
++ OS_DEVICE *OsDev,
++ HAL_FUNCTIONS **HalFunc,
++ OS_FUNCTIONS *OsFunc,
++ int OsFuncSize,
++ int *HalFuncSize,
++ int Inst);
++#endif
++
++#ifdef _CPHAL_AAL5
++/*
++ * @ingroup shared_data
++ * The AAL5_FUNCTIONS struct defines the AAL5 function pointers used by upper layer
++ * software. The upper layer software receives these pointers through the
++ * call to cphalInitModule().
++ */
++/*
++typedef struct
++ {
++ int (*ChannelSetup)(HAL_DEVICE *HalDev, CHANNEL_INFO *HalCh, OS_SETUP *OsSetup);
++ int (*ChannelTeardown)(HAL_DEVICE *HalDev, int Ch, int Mode);
++ int (*Close)(HAL_DEVICE *HalDev, int Mode);
++ int (*Init)(HAL_DEVICE *HalDev);
++ int (*ModeChange)(HAL_DEVICE *HalDev, char *DeviceParms);
++ int (*Open)(HAL_DEVICE *HalDev);
++ int (*InfoGet)(HAL_DEVICE *HalDev, int Key, void *Value);
++ int (*Probe)(HAL_DEVICE *HalDev);
++ int (*RxReturn)(HAL_RECEIVEINFO *HalReceiveInfo, int StripFlag);
++ int (*Send)(HAL_DEVICE *HalDev,FRAGLIST *FragList,int FragCount,
++ int PacketSize,OS_SENDINFO *OsSendInfo,int Ch, int Queue,
++ bit32u Mode);
++ int (*StatsClear)(HAL_DEVICE *HalDev);
++ STAT_INFO* (*StatsGet)(HAL_DEVICE *HalDev);
++ int (*Status)(HAL_DEVICE *HalDev);
++ void (*Tick)(HAL_DEVICE *HalDev);
++ int (*Kick)(HAL_DEVICE *HalDev, int Queue);
++ volatile bit32u* (*RegAccess)(HAL_DEVICE *HalDev, bit32u RegOffset);
++ } AAL5_FUNCTIONS;
++*/
++
++int cpaal5InitModule(HAL_DEVICE **HalDev,
++ OS_DEVICE *OsDev,
++ HAL_FUNCTIONS **HalFunc,
++ OS_FUNCTIONS *OsFunc,
++ int OsFuncSize,
++ int *HalFuncSize,
++ int Inst);
++#endif
++
++#ifdef _CPHAL_AAL2
++/**
++ * @ingroup shared_data
++ * The AAL2_FUNCTIONS struct defines the AAL2 function pointers used by upper layer
++ * software. The upper layer software receives these pointers through the
++ * call to cphalInitModule().
++ */
++typedef struct
++ {
++ int (*ChannelSetup)(HAL_DEVICE *HalDev, CHANNEL_INFO *HalCh, OS_SETUP *OsSetup);
++ int (*ChannelTeardown)(HAL_DEVICE *HalDev, int Ch, int Mode);
++ int (*Close)(HAL_DEVICE *HalDev, int Mode);
++ int (*Init)(HAL_DEVICE *HalDev);
++ int (*ModeChange)(HAL_DEVICE *HalDev, char *DeviceParms);
++ int (*Open)(HAL_DEVICE *HalDev);
++ int (*OptionsGet)(HAL_DEVICE *HalDev, char *Key, bit32u *Value);
++ int (*Probe)(HAL_DEVICE *HalDev);
++
++ int (*StatsClear)(HAL_DEVICE *HalDev);
++ STAT_INFO* (*StatsGet)(HAL_DEVICE *HalDev);
++ int (*Status)(HAL_DEVICE *HalDev);
++ void (*Tick)(HAL_DEVICE *HalDev);
++ int (*Aal2UuiMappingSetup)(HAL_DEVICE *HalDev, int VC, int UUI,
++ int VdmaCh, int UUIDiscard);
++ int (*Aal2RxMappingSetup)(HAL_DEVICE *HalDev, int VC, int CID,
++ int LC);
++ int (*Aal2TxMappingSetup)(HAL_DEVICE *HalDev, int VC, int LC, int VdmaCh);
++ int (*Aal2VdmaChSetup)(HAL_DEVICE *HalDev, bit32u RemVdmaVtAddr,
++ VdmaChInfo *VdmaCh);
++ volatile bit32u* (*RegAccess)(HAL_DEVICE *HalDev, bit32u RegOffset);
++ int (*Aal2ModeChange)(HAL_DEVICE *HalDev, int Vc, int RxCrossMode,
++ int RxMultiMode, int TxMultiMode, int SchedMode,
++ int TcCh);
++ void (*Aal2VdmaEnable)(HAL_DEVICE *HalDev, int Ch);
++ int (*Aal2VdmaDisable)(HAL_DEVICE *HalDev, int Ch);
++ } AAL2_FUNCTIONS;
++
++int cpaal2InitModule(HAL_DEVICE **HalDev,
++ OS_DEVICE *OsDev,
++ AAL2_FUNCTIONS **HalFunc,
++ OS_FUNCTIONS *OsFunc,
++ int OsFuncSize,
++ int *HalFuncSize,
++ int Inst);
++#endif
++
++#ifdef _CPHAL_VDMAVT
++/**
++ * @ingroup shared_data
++ * The VDMA_FUNCTIONS struct defines the HAL function pointers used by upper layer
++ * software. The upper layer software receives these pointers through the
++ * call to InitModule().
++ *
++ * Note that this list is still under definition.
++ */
++typedef struct
++ {
++ bit32 (*Init)( HAL_DEVICE *VdmaVtDev);
++ /* bit32 (*SetupTxFifo)(HAL_DEVICE *VdmaVtDev, bit32u LclRem,
++ bit32u Addr, bit32u Size, bit32u PollInt);
++ bit32 (*SetupRxFifo)(HAL_DEVICE *VdmaVtDev, bit32u LclRem,
++ bit32u Addr, bit32u Size, bit32u PollInt); */
++ bit32 (*Tx)(HAL_DEVICE *VdmaVtDev);
++ bit32 (*Rx)(HAL_DEVICE *VdmaVtDev);
++ bit32 (*SetRemoteChannel)(HAL_DEVICE *VdmaVtDev, bit32u RemAddr,
++ bit32u RemDevID);
++ bit32 (*ClearRxInt)(HAL_DEVICE *VdmaVtDev);
++ bit32 (*ClearTxInt)(HAL_DEVICE *VdmaVtDev);
++ bit32 (*Open)(HAL_DEVICE *VdmaVtDev);
++ bit32 (*Close)(HAL_DEVICE *VdmaVtDev);
++ int (*Control) (HAL_DEVICE *HalDev, const char *Key, const char *Action, void *Value);
++ int (*ChannelSetup)(HAL_DEVICE *VdmaVtDev, CHANNEL_INFO *HalCh, OS_SETUP *OsSetup);
++ int (*ChannelTeardown)(HAL_DEVICE *VdmaVtDev, int Ch, int Mode);
++ int (*Send)(HAL_DEVICE *VdmaVtDev,FRAGLIST *FragList,int FragCount,
++ int PacketSize,OS_SENDINFO *OsSendInfo,bit32u Mode);
++ } VDMA_FUNCTIONS;
++
++int VdmaInitModule(HAL_DEVICE **VdmaVt,
++ OS_DEVICE *OsDev,
++ VDMA_FUNCTIONS **VdmaVtFunc,
++ OS_FUNCTIONS *OsFunc,
++ int OsFuncSize,
++ int *HalFuncSize,
++ int Inst);
++#endif
++
++/*
++extern int cphalInitModule(MODULE_TYPE ModuleType, HAL_DEVICE **HalDev, OS_DEVICE *OsDev, HAL_FUNCTIONS *HalFunc,
++ int (*osInitModule)(OS_FUNCTIONS *), void* (*osMallocDev)(bit32u),
++ int *Size, int Inst);
++*/
++
++
++#ifdef _CPHAL_AAL5
++extern const char hcSarFrequency[];
++#endif
++
++#ifdef _CPHAL_CPMAC
++/* following will be common, once 'utl' added */
++extern const char hcClear[];
++extern const char hcGet[];
++extern const char hcSet[];
++extern const char hcTick[];
++
++extern const char hcCpuFrequency[];
++extern const char hcCpmacFrequency[];
++extern const char hcMdioBusFrequency[];
++extern const char hcMdioClockFrequency[];
++extern const char hcCpmacBase[];
++extern const char hcPhyNum[];
++extern const char hcSize[];
++extern const char hcCpmacSize[];
++extern const char hcPhyAccess[];
++#endif
++
++#endif /* end of _INC_ */
+diff -urN linux.old/drivers/atm/sangam_atm/cpswhal_cpsar.h linux.dev/drivers/atm/sangam_atm/cpswhal_cpsar.h
+--- linux.old/drivers/atm/sangam_atm/cpswhal_cpsar.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/cpswhal_cpsar.h 2005-08-23 04:46:50.089844912 +0200
+@@ -0,0 +1,629 @@
++/************************************************************************
++ * TNETDxxxx Software Support
++ * Copyright (c) 2002 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ * FILE: cphal.h
++ *
++ * DESCRIPTION:
++ * User include file, contains data definitions shared between the CPHAL
++ * and the upper-layer software.
++ *
++ * HISTORY:
++ * Date Modifier Ver Notes
++ * 28Feb02 Greg 1.00 Original
++ * 06Mar02 Greg 1.01 Documentation enhanced
++ * 18Jul02 Greg 1.02 Many updates (OAM additions, general reorg)
++ * 22Nov02 Mick RC2 Additions from Denis' input on Control
++ *
++ * author Greg Guyotte
++ * version 1.02
++ * date 18-Jul-2002
++ *****************************************************************************/
++#ifndef _INC_CPHAL_H
++#define _INC_CPHAL_H
++
++#ifdef _CPHAL_CPMAC
++#include "ec_errors_cpmac.h"
++#endif
++
++#ifdef _CPHAL_AAL5
++#include "ec_errors_cpaal5.h"
++#endif
++
++#ifdef _CPHAL_CPSAR
++#include "ec_errors_cpsar.h"
++#endif
++
++#ifdef _CPHAL_AAL2
++#include "ec_errors_cpaal2.h"
++#endif
++
++#ifndef __ADAM2
++typedef char bit8;
++typedef short bit16;
++typedef int bit32;
++
++typedef unsigned char bit8u;
++typedef unsigned short bit16u;
++typedef unsigned int bit32u;
++
++/*
++typedef char INT8;
++typedef short INT16;
++typedef int INT32;
++typedef unsigned char UINT8;
++typedef unsigned short UINT16;
++typedef unsigned int UINT32;
++*/
++/*typedef unsigned int size_t;*/
++#endif
++
++#ifdef _CPHAL
++
++#ifndef TRUE
++#define TRUE (1==1)
++#endif
++
++#ifndef FALSE
++#define FALSE (1==2)
++#endif
++
++#ifndef NULL
++#define NULL 0
++#endif
++
++#endif
++
++#define VirtToPhys(a) (((int)a)&~0xe0000000)
++#define VirtToVirtNoCache(a) ((void*)((VirtToPhys(a))|0xa0000000))
++#define VirtToVirtCache(a) ((void*)((VirtToPhys(a))|0x80000000))
++#define PhysToVirtNoCache(a) ((void*)(((int)a)|0xa0000000))
++#define PhysToVirtCache(a) ((void*)(((int)a)|0x80000000))
++/*
++#define DataCacheHitInvalidate(a) {__asm__(" cache 17, (%0)" : : "r" (a));}
++#define DataCacheHitWriteback(a) {__asm__(" cache 25, (%0)" : : "r" (a));}
++*/
++
++#define PARTIAL 1 /**< Used in @c Close() and @c ChannelTeardown() */
++#define FULL 2 /**< Used in @c Close() and @c ChannelTeardown() */
++
++/* Channel Teardown Defines */
++#define RX_TEARDOWN 2
++#define TX_TEARDOWN 1
++#define BLOCKING_TEARDOWN 8
++#define FULL_TEARDOWN 4
++#define PARTIAL_TEARDOWN 0
++
++#define MAX_DIR 2
++#define DIRECTION_TX 0
++#define DIRECTION_RX 1
++#define TX_CH 0
++#define RX_CH 1
++#define HAL_ERROR_DEVICE_NOT_FOUND 1
++#define HAL_ERROR_FAILED_MALLOC 2
++#define HAL_ERROR_OSFUNC_SIZE 3
++#define HAL_DEFAULT 0xFFFFFFFF
++#define VALID(val) (val!=HAL_DEFAULT)
++
++/*
++ERROR REPORTING
++
++HAL Module Codes. Each HAL module reporting an error code
++should OR the error code with the respective Module error code
++from the list below.
++*/
++#define EC_AAL5 EC_HAL|EC_DEV_AAL5
++#define EC_AAL2 EC_HAL|EC_DEV_AAL2
++#define EC_CPSAR EC_HAL|EC_DEV_CPSAR
++#define EC_CPMAC EC_HAL|EC_DEV_CPMAC
++#define EC_VDMA EC_HAL|EC_DEV_VDMA
++#define EC_VLYNQ EC_HAL|EC_DEV_VLYNQ
++#define EC_CPPI EC_HAL|EC_DEV_CPPI
++
++/*
++HAL Function Codes. Each HAL module reporting an error code
++should OR the error code with one of the function codes from
++the list below.
++*/
++#define EC_FUNC_HAL_INIT EC_FUNC(1)
++#define EC_FUNC_CHSETUP EC_FUNC(2)
++#define EC_FUNC_CHTEARDOWN EC_FUNC(3)
++#define EC_FUNC_RXRETURN EC_FUNC(4)
++#define EC_FUNC_SEND EC_FUNC(5)
++#define EC_FUNC_RXINT EC_FUNC(6)
++#define EC_FUNC_TXINT EC_FUNC(7)
++#define EC_FUNC_AAL2_VDMA EC_FUNC(8)
++#define EC_FUNC_OPTIONS EC_FUNC(9)
++#define EC_FUNC_PROBE EC_FUNC(10)
++#define EC_FUNC_OPEN EC_FUNC(11)
++#define EC_FUNC_CONTROL EC_FUNC(12)
++#define EC_FUNC_DEVICE_INT EC_FUNC(13)
++#define EC_FUNC_STATUS EC_FUNC(14)
++#define EC_FUNC_TICK EC_FUNC(15)
++#define EC_FUNC_CLOSE EC_FUNC(16)
++#define EC_FUNC_SHUTDOWN EC_FUNC(17)
++#define EC_FUNC_DEVICE_INT_ALT EC_FUNC(18) /* +GSG 030306 */
++
++/*
++HAL Error Codes. The list below defines every type of error
++used in all HAL modules. DO NOT CHANGE THESE VALUES! Add new
++values in integer order to the bottom of the list.
++*/
++#define EC_VAL_PDSP_LOAD_FAIL EC_ERR(0x01)|EC_CRITICAL
++#define EC_VAL_FIRMWARE_TOO_LARGE EC_ERR(0x02)|EC_CRITICAL
++#define EC_VAL_DEVICE_NOT_FOUND EC_ERR(0x03)|EC_CRITICAL
++#define EC_VAL_BASE_ADDR_NOT_FOUND EC_ERR(0x04)|EC_CRITICAL
++#define EC_VAL_RESET_BIT_NOT_FOUND EC_ERR(0x05)|EC_CRITICAL
++#define EC_VAL_CH_INFO_NOT_FOUND EC_ERR(0x06)
++#define EC_VAL_RX_STATE_RAM_NOT_CLEARED EC_ERR(0x07)|EC_CRITICAL
++#define EC_VAL_TX_STATE_RAM_NOT_CLEARED EC_ERR(0x08)|EC_CRITICAL
++#define EC_VAL_MALLOC_DEV_FAILED EC_ERR(0x09)
++#define EC_VAL_OS_VERSION_NOT_SUPPORTED EC_ERR(0x0A)|EC_CRITICAL
++#define EC_VAL_CPSAR_VERSION_NOT_SUPPORTED EC_ERR(0x0B)|EC_CRITICAL
++#define EC_VAL_NULL_CPSAR_DEV EC_ERR(0x0C)|EC_CRITICAL
++
++#define EC_VAL_LUT_NOT_READY EC_ERR(0x0D)
++#define EC_VAL_INVALID_CH EC_ERR(0x0E)
++#define EC_VAL_NULL_CH_STRUCT EC_ERR(0x0F)
++#define EC_VAL_RX_TEARDOWN_ALREADY_PEND EC_ERR(0x10)
++#define EC_VAL_TX_TEARDOWN_ALREADY_PEND EC_ERR(0x11)
++#define EC_VAL_RX_CH_ALREADY_TORNDOWN EC_ERR(0x12)
++#define EC_VAL_TX_CH_ALREADY_TORNDOWN EC_ERR(0x13)
++#define EC_VAL_TX_TEARDOWN_TIMEOUT EC_ERR(0x14)
++#define EC_VAL_RX_TEARDOWN_TIMEOUT EC_ERR(0x15)
++#define EC_VAL_CH_ALREADY_TORNDOWN EC_ERR(0x16)
++#define EC_VAL_VC_SETUP_NOT_READY EC_ERR(0x17)
++#define EC_VAL_VC_TEARDOWN_NOT_READY EC_ERR(0x18)
++#define EC_VAL_INVALID_VC EC_ERR(0x19)
++#define EC_VAL_INVALID_LC EC_ERR(0x20)
++#define EC_VAL_INVALID_VDMA_CH EC_ERR(0x21)
++#define EC_VAL_INVALID_CID EC_ERR(0x22)
++#define EC_VAL_INVALID_UUI EC_ERR(0x23)
++#define EC_VAL_INVALID_UUI_DISCARD EC_ERR(0x24)
++#define EC_VAL_CH_ALREADY_OPEN EC_ERR(0x25)
++
++#define EC_VAL_RCB_MALLOC_FAILED EC_ERR(0x26)
++#define EC_VAL_RX_BUFFER_MALLOC_FAILED EC_ERR(0x27)
++#define EC_VAL_OUT_OF_TCBS EC_ERR(0x28)
++#define EC_VAL_NO_TCBS EC_ERR(0x29)
++#define EC_VAL_NULL_RCB EC_ERR(0x30)|EC_CRITICAL
++#define EC_VAL_SOP_ERROR EC_ERR(0x31)|EC_CRITICAL
++#define EC_VAL_EOP_ERROR EC_ERR(0x32)|EC_CRITICAL
++#define EC_VAL_NULL_TCB EC_ERR(0x33)|EC_CRITICAL
++#define EC_VAL_CORRUPT_RCB_CHAIN EC_ERR(0x34)|EC_CRITICAL
++#define EC_VAL_TCB_MALLOC_FAILED EC_ERR(0x35)
++
++#define EC_VAL_DISABLE_POLLING_FAILED EC_ERR(0x36)
++#define EC_VAL_KEY_NOT_FOUND EC_ERR(0x37)
++#define EC_VAL_MALLOC_FAILED EC_ERR(0x38)
++#define EC_VAL_RESET_BASE_NOT_FOUND EC_ERR(0x39)|EC_CRITICAL
++#define EC_VAL_INVALID_STATE EC_ERR(0x40)
++#define EC_VAL_NO_TXH_WORK_TO_DO EC_ERR(0x41)
++#define EC_VAL_NO_TXL_WORK_TO_DO EC_ERR(0x42)
++#define EC_VAL_NO_RX_WORK_TO_DO EC_ERR(0x43)
++#define EC_VAL_NOT_LINKED EC_ERR(0x44)
++#define EC_VAL_INTERRUPT_NOT_FOUND EC_ERR(0x45)
++#define EC_VAL_OFFSET_NOT_FOUND EC_ERR(0x46)
++#define EC_VAL_MODULE_ALREADY_CLOSED EC_ERR(0x47)
++#define EC_VAL_MODULE_ALREADY_SHUTDOWN EC_ERR(0x48)
++#define EC_VAL_ACTION_NOT_FOUND EC_ERR(0x49)
++#define EC_VAL_RX_CH_ALREADY_SETUP EC_ERR(0x50)
++#define EC_VAL_TX_CH_ALREADY_SETUP EC_ERR(0x51)
++#define EC_VAL_RX_CH_ALREADY_OPEN EC_ERR(0x52)
++#define EC_VAL_TX_CH_ALREADY_OPEN EC_ERR(0x53)
++#define EC_VAL_CH_ALREADY_SETUP EC_ERR(0x54)
++#define EC_VAL_RCB_NEEDS_BUFFER EC_ERR(0x55) /* +GSG 030410 */
++#define EC_VAL_RCB_DROPPED EC_ERR(0x56) /* +GSG 030410 */
++#define EC_VAL_INVALID_VALUE EC_ERR(0x57)
++
++/**
++@defgroup shared_data Shared Data Structures
++
++The data structures documented here are shared by all modules.
++*/
++
++/**
++ * @ingroup shared_data
++ * This is the fragment list structure. Each fragment list entry contains a
++ * length and a data buffer.
++ */
++typedef struct
++ {
++ bit32u len; /**< Length of the fragment in bytes (lower 16 bits are valid). For SOP, upper 16 bits is the buffer offset. */
++ void *data; /**< Pointer to fragment data. */
++ void *OsInfo; /**< Pointer to OS defined data. */
++ }FRAGLIST;
++
++#if defined (_CPHAL_CPMAC)
++#define CB_PASSCRC_BIT (1<<26)
++
++/* CPMAC CPHAL STATUS */
++#define CPMAC_STATUS_LINK (1 << 0)
++#define CPMAC_STATUS_LINK_DUPLEX (1 << 1) /* 0 - HD, 1 - FD */
++#define CPMAC_STATUS_LINK_SPEED (1 << 2) /* 0 - 10, 1 - 100 */
++
++/* ADAPTER CHECK Codes */
++
++#define CPMAC_STATUS_ADAPTER_CHECK (1 << 7)
++#define CPMAC_STATUS_HOST_ERR_DIRECTION (1 << 8)
++#define CPMAC_STATUS_HOST_ERR_CODE (0xF << 9)
++#define CPMAC_STATUS_HOST_ERR_CH (0x7 << 13)
++
++#define _CPMDIO_DISABLE (1 << 0)
++#define _CPMDIO_HD (1 << 1)
++#define _CPMDIO_FD (1 << 2)
++#define _CPMDIO_10 (1 << 3)
++#define _CPMDIO_100 (1 << 4)
++#define _CPMDIO_NEG_OFF (1 << 5)
++#define _CPMDIO_LOOPBK (1 << 16)
++#define _CPMDIO_NOPHY (1 << 20)
++#endif
++
++/**
++ * @ingroup shared_data
++ * Channel specific configuration information. This structure should be
++ * populated by upper-layer software prior to calling @c ChannelSetup(). Any
++ * configuration item that can be changed on a per channel basis should
++ * be represented here. Each module may define this structure with additional
++ * module-specific members.
++ */
++typedef struct
++ {
++ int Channel; /**< Channel number. */
++ int Direction; /**< DIRECTION_RX(1) or DIRECTION_TX(0). */
++ OS_SETUP *OsSetup; /**< OS defined information associated with this channel. */
++
++#if defined(_CPHAL_AAL5) || defined (_CPHAL_CPSAR) || defined (_CPHAL_CPMAC)
++ int RxBufSize; /**< Size (in bytes) for each Rx buffer.*/
++ int RxBufferOffset; /**< Number of bytes to offset rx data from start of buffer (must be less than buffer size). */
++ int RxNumBuffers; /**< The number of Rx buffer descriptors to allocate for Ch. */
++ int RxServiceMax; /**< Maximum number of packets to service at one time. */
++
++ int TxNumBuffers; /**< The number of Tx buffer descriptors to allocate for Ch. */
++ int TxNumQueues; /**< Number of Tx queues for this channel (1-2). Choosing 2 enables a low priority SAR queue. */
++ int TxServiceMax; /**< Maximum number of packets to service at one time. */
++#endif
++
++#if defined(_CPHAL_AAL5) || defined(_CPHAL_CPSAR)
++ int CpcsUU; /**< The 2-byte CPCS UU and CPI information. */
++ int Gfc; /**< Generic Flow Control. */
++ int Clp; /**< Cell Loss Priority. */
++ int Pti; /**< Payload Type Indication. */
++#endif
++
++#if defined(_CPHAL_AAL2) || defined(_CPHAL_AAL5) || defined(_CPHAL_CPSAR)
++ int DaMask; /**< Specifies whether credit issuance is paused when Tx data not available. */
++ int Priority; /**< Priority bin this channel will be scheduled within. */
++ int PktType; /**< 0=AAL5,1=Null AAL,2=OAM,3=Transparent,4=AAL2. */
++ int Vci; /**< Virtual Channel Identifier. */
++ int Vpi; /**< Virtual Path Identifier. */
++ int FwdUnkVc; /**< Enables forwarding of unknown VCI/VPI cells to host. 1=enable, 0=disable. */
++
++ /* Tx VC State */
++ int TxVc_CellRate; /**< Tx rate, set as clock ticks between transmissions (SCR for VBR, CBR for CBR). */
++ int TxVc_QosType; /**< 0=CBR,1=VBR,2=UBR,3=UBRmcr. */
++ int TxVc_Mbs; /**< Min Burst Size in cells.*/
++ int TxVc_Pcr; /**< Peak Cell Rate for VBR in clock ticks between transmissions. */
++
++ bit32 TxVc_AtmHeader; /**< ATM Header placed on firmware gen'd OAM cells for this Tx Ch (must be big endian with 0 PTI). */
++ int TxVc_OamTc; /**< TC Path to transmit OAM cells for TX connection (0,1). */
++ int TxVc_VpOffset; /**< Offset to the OAM VP state table. */
++ /* Rx VC State */
++ int RxVc_OamCh; /**< Ch to terminate rx'd OAM cells to be forwarded to the host. */
++ int RxVc_OamToHost; /**< 0=do not pass, 1=pass. */
++ bit32 RxVc_AtmHeader; /**< ATM Header placed on firmware gen'd OAM cells for this Rx conn (must be big endian with 0 PTI). */
++ int RxVc_OamTc; /**< TC Path to transmit OAM cells for RX connection (0,1). */
++ int RxVc_VpOffset; /**< Offset to the OAM VP state table. */
++ /* Tx VP State */
++ int TxVp_OamTc; /**< TC Path to transmit OAM cells for TX VP connection (0,1). */
++ bit32 TxVp_AtmHeader; /**< ATM Header placed on firmware gen'd VP OAM cells for this Tx VP conn (must be big endian with 0 VCI). */
++ /* Rx VP State */
++ int RxVp_OamCh; /**< Ch to terminate rx'd OAM cells to be forwarded to the host. */
++ int RxVp_OamToHost; /**< 0=do not pass, 1=pass. */
++ bit32 RxVp_AtmHeader; /**< ATM Header placed on firmware gen'd OAM cells for this Rx VP conn (must be big endian with 0 VCI). */
++ int RxVp_OamTc; /**< TC Path to transmit OAM cells for RX VP connection (0,1). */
++ int RxVp_OamVcList; /**< Indicates all VC channels associated with this VP channel (one-hot encoded). */
++#endif
++
++
++#ifdef _CPHAL_VDMAVT
++ bit32u RemFifoAddr; /* Mirror mode only. */
++ bit32u FifoAddr;
++ bit32 PollInt;
++ bit32 FifoSize;
++ int Ready;
++#endif
++
++ }CHANNEL_INFO;
++
++/*
++ * This structure contains each statistic value gathered by the CPHAL.
++ * Applications may access statistics data by using the @c StatsGet() routine.
++ */
++/* STATS */
++#if defined(_CPHAL_AAL2) || defined(_CPHAL_AAL5) || defined(_CPHAL_CPSAR)
++typedef struct
++ {
++ bit32u CrcErrors[16];
++ bit32u LenErrors[16];
++ bit32u DmaLenErrors[16];
++ bit32u AbortErrors[16];
++ bit32u StarvErrors[16];
++ bit32u TxMisQCnt[16][2];
++ bit32u RxMisQCnt[16];
++ bit32u RxEOQCnt[16];
++ bit32u TxEOQCnt[16][2];
++ bit32u RxPacketsServiced[16];
++ bit32u TxPacketsServiced[16][2];
++ bit32u RxMaxServiced;
++ bit32u TxMaxServiced[16][2];
++ bit32u RxTotal;
++ bit32u TxTotal;
++ } STAT_INFO;
++#endif
++
++/*
++ * VDMA Channel specific configuration information
++ */
++#ifdef _CPHAL_AAL2
++typedef struct
++ {
++ int Ch; /**< Channel Number */
++ int RemoteEndian; /**< Endianness of remote VDMA-VT device */
++ int CpsSwap; /**< When 0, octet 0 in CPS pkt located in LS byte of 16-bit word sent to rem VDMA device. When 1, in MS byte. */
++ }VdmaChInfo;
++#endif
++
++#ifndef _CPHAL
++ typedef void HAL_DEVICE;
++ typedef void HAL_PRIVATE;
++ typedef void HAL_RCB;
++ typedef void HAL_RECEIVEINFO;
++#endif
++
++/**
++ * @ingroup shared_data
++ * The HAL_FUNCTIONS struct defines the function pointers used by upper layer
++ * software. The upper layer software receives these pointers through the
++ * call to xxxInitModule().
++ */
++typedef struct
++ {
++ int (*ChannelSetup) (HAL_DEVICE *HalDev, CHANNEL_INFO *Channel, OS_SETUP *OsSetup);
++ int (*ChannelTeardown) (HAL_DEVICE *HalDev, int Channel, int Mode);
++ int (*Close) (HAL_DEVICE *HalDev, int Mode);
++ int (*Control) (HAL_DEVICE *HalDev, const char *Key, const char *Action, void *Value);
++ int (*Init) (HAL_DEVICE *HalDev);
++ int (*Open) (HAL_DEVICE *HalDev);
++ int (*PacketProcessEnd) (HAL_DEVICE *HalDev);
++ int (*Probe) (HAL_DEVICE *HalDev);
++ int (*RxReturn) (HAL_RECEIVEINFO *HalReceiveInfo, int StripFlag);
++ int (*Send) (HAL_DEVICE *HalDev, FRAGLIST *FragList, int FragCount, int PacketSize, OS_SENDINFO *OsSendInfo, bit32u Mode);
++ int (*Shutdown) (HAL_DEVICE *HalDev);
++ int (*Tick) (HAL_DEVICE *HalDev);
++
++#ifdef _CPHAL_AAL5
++ int (*Kick) (HAL_DEVICE *HalDev, int Queue);
++ void (*OamFuncConfig) (HAL_DEVICE *HalDev, unsigned int OamConfig);
++ void (*OamLoopbackConfig) (HAL_DEVICE *HalDev, unsigned int OamConfig, unsigned int *LLID, unsigned int CorrelationTag);
++ volatile bit32u* (*RegAccess)(HAL_DEVICE *HalDev, bit32u RegOffset);
++ STAT_INFO* (*StatsGetOld)(HAL_DEVICE *HalDev);
++#endif
++ } HAL_FUNCTIONS;
++
++/**
++ * @ingroup shared_data
++ * The OS_FUNCTIONS struct defines the function pointers for all upper layer
++ * functions accessible to the CPHAL. The upper layer software is responsible
++ * for providing the correct OS-specific implementations for the following
++ * functions. It is populated by calling InitModule() (done by the CPHAL in
++ * xxxInitModule().
++ */
++typedef struct
++ {
++ int (*Control)(OS_DEVICE *OsDev, const char *Key, const char *Action, void *Value);
++ void (*CriticalOn)(void);
++ void (*CriticalOff)(void);
++ void (*DataCacheHitInvalidate)(void *MemPtr, int Size);
++ void (*DataCacheHitWriteback)(void *MemPtr, int Size);
++ int (*DeviceFindInfo)(int Inst, const char *DeviceName, void *DeviceInfo);
++ int (*DeviceFindParmUint)(void *DeviceInfo, const char *Parm, bit32u *Value);
++ int (*DeviceFindParmValue)(void *DeviceInfo, const char *Parm, void *Value);
++ void (*Free)(void *MemPtr);
++ void (*FreeRxBuffer)(OS_RECEIVEINFO *OsReceiveInfo, void *MemPtr);
++ void (*FreeDev)(void *MemPtr);
++ void (*FreeDmaXfer)(void *MemPtr);
++ void (*IsrRegister)(OS_DEVICE *OsDev, int (*halISR)(HAL_DEVICE*, int*), int InterruptBit);
++ void (*IsrUnRegister)(OS_DEVICE *OsDev, int InterruptBit);
++ void* (*Malloc)(bit32u size);
++ void* (*MallocDev)(bit32u Size);
++ void* (*MallocDmaXfer)(bit32u size, void *MemBase, bit32u MemRange);
++ void* (*MallocRxBuffer)(bit32u size, void *MemBase, bit32u MemRange,
++ OS_SETUP *OsSetup, HAL_RECEIVEINFO *HalReceiveInfo,
++ OS_RECEIVEINFO **OsReceiveInfo, OS_DEVICE *OsDev);
++ void* (*Memset)(void *Dest, int C, bit32u N);
++ int (*Printf)(const char *Format, ...);
++ int (*Receive)(OS_DEVICE *OsDev,FRAGLIST *FragList,bit32u FragCount,
++ bit32u PacketSize,HAL_RECEIVEINFO *HalReceiveInfo, bit32u Mode);
++ int (*SendComplete)(OS_SENDINFO *OsSendInfo);
++ int (*Sprintf)(char *S, const char *Format, ...);
++ int (*Strcmpi)(const char *Str1, const char *Str2);
++ unsigned int (*Strlen)(const char *S);
++ char* (*Strstr)(const char *S1, const char *S2);
++ unsigned long (*Strtoul)(const char *Str, char **Endptr, int Base);
++ void (*TeardownComplete)(OS_DEVICE *OsDev, int Ch, int Direction);
++ } OS_FUNCTIONS;
++
++/************** MODULE SPECIFIC STUFF BELOW **************/
++
++#ifdef _CPHAL_CPMAC
++
++/*
++int halCpmacInitModule(HAL_DEVICE **HalDev, OS_DEVICE *OsDev, HAL_FUNCTIONS *HalFunc, int (*osBridgeInitModule)(OS_FUNCTIONS *), void* (*osMallocDev) (bit32u), int *Size, int inst);
++*/
++
++int halCpmacInitModule(HAL_DEVICE **HalDev,
++ OS_DEVICE *OsDev,
++ HAL_FUNCTIONS **HalFunc,
++ OS_FUNCTIONS *OsFunc,
++ int OsFuncSize,
++ int *HalFuncSize,
++ int Inst);
++#endif
++
++#ifdef _CPHAL_AAL5
++/*
++ * @ingroup shared_data
++ * The AAL5_FUNCTIONS struct defines the AAL5 function pointers used by upper layer
++ * software. The upper layer software receives these pointers through the
++ * call to cphalInitModule().
++ */
++/*
++typedef struct
++ {
++ int (*ChannelSetup)(HAL_DEVICE *HalDev, CHANNEL_INFO *HalCh, OS_SETUP *OsSetup);
++ int (*ChannelTeardown)(HAL_DEVICE *HalDev, int Ch, int Mode);
++ int (*Close)(HAL_DEVICE *HalDev, int Mode);
++ int (*Init)(HAL_DEVICE *HalDev);
++ int (*ModeChange)(HAL_DEVICE *HalDev, char *DeviceParms);
++ int (*Open)(HAL_DEVICE *HalDev);
++ int (*InfoGet)(HAL_DEVICE *HalDev, int Key, void *Value);
++ int (*Probe)(HAL_DEVICE *HalDev);
++ int (*RxReturn)(HAL_RECEIVEINFO *HalReceiveInfo, int StripFlag);
++ int (*Send)(HAL_DEVICE *HalDev,FRAGLIST *FragList,int FragCount,
++ int PacketSize,OS_SENDINFO *OsSendInfo,int Ch, int Queue,
++ bit32u Mode);
++ int (*StatsClear)(HAL_DEVICE *HalDev);
++ STAT_INFO* (*StatsGet)(HAL_DEVICE *HalDev);
++ int (*Status)(HAL_DEVICE *HalDev);
++ void (*Tick)(HAL_DEVICE *HalDev);
++ int (*Kick)(HAL_DEVICE *HalDev, int Queue);
++ volatile bit32u* (*RegAccess)(HAL_DEVICE *HalDev, bit32u RegOffset);
++ } AAL5_FUNCTIONS;
++*/
++
++int cpaal5InitModule(HAL_DEVICE **HalDev,
++ OS_DEVICE *OsDev,
++ HAL_FUNCTIONS **HalFunc,
++ OS_FUNCTIONS *OsFunc,
++ int OsFuncSize,
++ int *HalFuncSize,
++ int Inst);
++#endif
++
++#ifdef _CPHAL_AAL2
++/**
++ * @ingroup shared_data
++ * The AAL2_FUNCTIONS struct defines the AAL2 function pointers used by upper layer
++ * software. The upper layer software receives these pointers through the
++ * call to cphalInitModule().
++ */
++typedef struct
++ {
++ int (*ChannelSetup)(HAL_DEVICE *HalDev, CHANNEL_INFO *HalCh, OS_SETUP *OsSetup);
++ int (*ChannelTeardown)(HAL_DEVICE *HalDev, int Ch, int Mode);
++ int (*Close)(HAL_DEVICE *HalDev, int Mode);
++ int (*Init)(HAL_DEVICE *HalDev);
++ int (*ModeChange)(HAL_DEVICE *HalDev, char *DeviceParms);
++ int (*Open)(HAL_DEVICE *HalDev);
++ int (*OptionsGet)(HAL_DEVICE *HalDev, char *Key, bit32u *Value);
++ int (*Probe)(HAL_DEVICE *HalDev);
++
++ int (*StatsClear)(HAL_DEVICE *HalDev);
++ STAT_INFO* (*StatsGet)(HAL_DEVICE *HalDev);
++ int (*Status)(HAL_DEVICE *HalDev);
++ void (*Tick)(HAL_DEVICE *HalDev);
++ int (*Aal2UuiMappingSetup)(HAL_DEVICE *HalDev, int VC, int UUI,
++ int VdmaCh, int UUIDiscard);
++ int (*Aal2RxMappingSetup)(HAL_DEVICE *HalDev, int VC, int CID,
++ int LC);
++ int (*Aal2TxMappingSetup)(HAL_DEVICE *HalDev, int VC, int LC, int VdmaCh);
++ int (*Aal2VdmaChSetup)(HAL_DEVICE *HalDev, bit32u RemVdmaVtAddr,
++ VdmaChInfo *VdmaCh);
++ volatile bit32u* (*RegAccess)(HAL_DEVICE *HalDev, bit32u RegOffset);
++ int (*Aal2ModeChange)(HAL_DEVICE *HalDev, int Vc, int RxCrossMode,
++ int RxMultiMode, int TxMultiMode, int SchedMode,
++ int TcCh);
++ void (*Aal2VdmaEnable)(HAL_DEVICE *HalDev, int Ch);
++ int (*Aal2VdmaDisable)(HAL_DEVICE *HalDev, int Ch);
++ } AAL2_FUNCTIONS;
++
++int cpaal2InitModule(HAL_DEVICE **HalDev,
++ OS_DEVICE *OsDev,
++ AAL2_FUNCTIONS **HalFunc,
++ OS_FUNCTIONS *OsFunc,
++ int OsFuncSize,
++ int *HalFuncSize,
++ int Inst);
++#endif
++
++#ifdef _CPHAL_VDMAVT
++/**
++ * @ingroup shared_data
++ * The VDMA_FUNCTIONS struct defines the HAL function pointers used by upper layer
++ * software. The upper layer software receives these pointers through the
++ * call to InitModule().
++ *
++ * Note that this list is still under definition.
++ */
++typedef struct
++ {
++ bit32 (*Init)( HAL_DEVICE *VdmaVtDev);
++ /* bit32 (*SetupTxFifo)(HAL_DEVICE *VdmaVtDev, bit32u LclRem,
++ bit32u Addr, bit32u Size, bit32u PollInt);
++ bit32 (*SetupRxFifo)(HAL_DEVICE *VdmaVtDev, bit32u LclRem,
++ bit32u Addr, bit32u Size, bit32u PollInt); */
++ bit32 (*Tx)(HAL_DEVICE *VdmaVtDev);
++ bit32 (*Rx)(HAL_DEVICE *VdmaVtDev);
++ bit32 (*SetRemoteChannel)(HAL_DEVICE *VdmaVtDev, bit32u RemAddr,
++ bit32u RemDevID);
++ bit32 (*ClearRxInt)(HAL_DEVICE *VdmaVtDev);
++ bit32 (*ClearTxInt)(HAL_DEVICE *VdmaVtDev);
++ bit32 (*Open)(HAL_DEVICE *VdmaVtDev);
++ bit32 (*Close)(HAL_DEVICE *VdmaVtDev);
++ int (*Control) (HAL_DEVICE *HalDev, const char *Key, const char *Action, void *Value);
++ int (*ChannelSetup)(HAL_DEVICE *VdmaVtDev, CHANNEL_INFO *HalCh, OS_SETUP *OsSetup);
++ int (*ChannelTeardown)(HAL_DEVICE *VdmaVtDev, int Ch, int Mode);
++ int (*Send)(HAL_DEVICE *VdmaVtDev,FRAGLIST *FragList,int FragCount,
++ int PacketSize,OS_SENDINFO *OsSendInfo,bit32u Mode);
++ } VDMA_FUNCTIONS;
++
++int VdmaInitModule(HAL_DEVICE **VdmaVt,
++ OS_DEVICE *OsDev,
++ VDMA_FUNCTIONS **VdmaVtFunc,
++ OS_FUNCTIONS *OsFunc,
++ int OsFuncSize,
++ int *HalFuncSize,
++ int Inst);
++#endif
++
++/*
++extern int cphalInitModule(MODULE_TYPE ModuleType, HAL_DEVICE **HalDev, OS_DEVICE *OsDev, HAL_FUNCTIONS *HalFunc,
++ int (*osInitModule)(OS_FUNCTIONS *), void* (*osMallocDev)(bit32u),
++ int *Size, int Inst);
++*/
++
++
++#ifdef _CPHAL_AAL5
++extern const char hcSarFrequency[];
++#endif
++
++#ifdef _CPHAL_CPMAC
++/* following will be common, once 'utl' added */
++extern const char hcClear[];
++extern const char hcGet[];
++extern const char hcSet[];
++extern const char hcTick[];
++
++extern const char hcCpuFrequency[];
++extern const char hcCpmacFrequency[];
++extern const char hcMdioBusFrequency[];
++extern const char hcMdioClockFrequency[];
++extern const char hcCpmacBase[];
++extern const char hcPhyNum[];
++extern const char hcSize[];
++extern const char hcCpmacSize[];
++extern const char hcPhyAccess[];
++#endif
++
++#endif /* end of _INC_ */
+diff -urN linux.old/drivers/atm/sangam_atm/dev_host_interface.h linux.dev/drivers/atm/sangam_atm/dev_host_interface.h
+--- linux.old/drivers/atm/sangam_atm/dev_host_interface.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/dev_host_interface.h 2005-08-23 04:46:50.091844608 +0200
+@@ -0,0 +1,1162 @@
++#ifndef __DEV_HOST_INTERFACE_H__
++#define __DEV_HOST_INTERFACE_H__ 1
++
++/*******************************************************************************
++* FILE PURPOSE: Public header file for the Host-to-DSP interface
++********************************************************************************
++*
++* TEXAS INSTRUMENTS PROPRIETARTY INFORMATION
++*
++* (C) Copyright Texas Instruments Inc. 2002. All rights reserved.
++*
++* Property of Texas Instruments Incorporated
++*
++* Restricted Rights - Use, duplication, or disclosure is subject to
++* restrictions set forth in TI's program license agreement and
++* associated documentation
++*
++*
++* FILE NAME: dev_host_interface.h
++*
++* DESCRIPTION:
++* This header file defines the variables and parameters used between the
++* host processor and the DSP. This file is included in both the DSP
++* software and the host software.
++*
++* RULES FOR MODIFICATION AND USE OF THIS FILE:
++*
++* --The main pointer to the struct of pointers will always be at the same fixed
++* location (0x80000000).
++*
++* --Each pointer element in the struct of pointers (indicated by the main pointer)
++* will always point to a struct only.
++*
++* --Any new structures added to the host interface in subsequent versions must
++* each have a corresponding new pointer element added to the END of the struct
++* of pointers. Other than this, there will never be any moving or rearranging
++* of the pointer elements in the struct of pointers.
++*
++* --Any new elements added to existing structures will be added at the END of the
++* structure. Other than this, there will never be any moving or rearranging
++* of structure elements.
++*
++* --A new structure will never be added as a new element in an old structure.
++* New structures must be added separately with a new entry in the struct of
++* pointers, as noted above.
++*
++* --Also, the sizes of existing arrays within old structures will never be changed.
++*
++* --The modem code in the DSP will never reference the struct of pointers in order
++* to avoid aliasing issues in the DSP code. The modem code will only use the
++* specific structures directly.
++*
++* --The host processor never accesses the DSP side of the ATM-TC hardware directly.
++* The DSP interfaces directly to the ATM-TC hardware and relays information to
++* the host processor through the host interface.
++*
++* --The host processor can track the modem's transition through important states
++* by accessing the Modem State Bit Field in the host interface. Each bit in
++* the bit field represents an important state to track in the modem. As the
++* modem transitions through each important state, the corresponding bit will
++* change from a zero to a one. Each bit in the bit field will only be reset to
++* zero if the modem retrains. If new states need to be tracked and are added
++* in subsequent versions of the host interface, a corresponding bit will be
++* added at the END of the bit field to ensure backwards compatibility. The
++* Modem State Bit Field is reset if the modem retrains or falls out of Showtime.
++*
++* --An interrupt will be sent to the host processor when a change occurs in the
++* Modem State Bit Field. There is an interrupt masking register which can mask
++* specific interrupts corresponding to the bits of the Modem State Bit Field.
++* This allows the host to keep an interrupt from being generated for those
++* states that are masked.
++*
++* HISTORY:
++*
++* 11/20/02 J. Bergsagel Written from the previous host interface file
++* 11/27/02 J. Bergsagel Added comments for mailbox control struct and
++* fixed a couple items for overlay page stuff.
++* Also, added temporary elements for SWTC code.
++* 12/04/02 J. Bergsagel Added extra dummy byte to DEV_HOST_eocVarDef_t
++* for proper word alignment.
++* 12/12/02 J. Bergsagel Changed initial states in the modem state bit field
++* and added more instructions for adding more states.
++* 12/16/02 J. Bergsagel Changed name "hostVersion_p" to "hostIntfcVersion_p".
++* Removed dspAturState from DEV_HOST_modemStateBitField_t.
++* Reorganized several struct elements to clean up the
++* host interface.
++* 12/27/02 Sameer V Added missing channel 0 statistics for TC. Added
++* ocd error information.
++* 12/27/02 Sameer V Added overlayState to OlayDP_Parms to indicate whether
++* overlays are being executed in current state.
++* 01/06/03 J. Bergsagel Added maxAllowedMargin and minRequiredMargin to
++* DEV_HOST_msg_t.
++* Renamed TC chan 1 items to be chan 0 items to start out.
++* 01/17/03 Sameer V Moved delineationState to atmStats structure.
++* 01/21/03 Barnett Implemented Ax7 UNIT-MODULE modular software framework.
++* 01/22/03 J. Bergsagel Added warning comments for certain struct typedefs.
++* 01/23/03 C. Perez-N. Removed old AX5-only diags. command/response entries in the
++* HOST and DSP ennumerations, and added the AX7 new ones
++* Added pointer entries in the DEV_HOST_dspOamSharedInterface_t
++* structure pointing to the analog diags. input/output/options
++* structures.
++* 01/29/03 Sameer V Removed TC_IDLE in enum for delineation state. Hardware
++* only reports TC_HUNT, TC_PRESYNC and TC_SYNC.
++* 03/07/03 Sameer/Jonathan Put SWTC token around structs and elements only used by SWTC
++* 03/12/03 Mannering Add CO profile data structures
++* 03/18/03 J. Bergsagel Removed the obsolete DSP_CHECK_TC response message.
++* 03/24/03 J. Bergsagel Added DEV_HOST_hostInterruptMask_t for masking DSP interrupt sources
++* 03/28/03 C. Perez-N Changed the C-style comments and made them C++ sytle instead.
++* Replaced the occurrences of "SINT32 *" pointer declarations with
++* "PSINT32"
++* 03/28/03 Mannering Update CO profile data structures
++* 04/04/03 S. Yim Add host I/F hooks for switchable hybrid and RJ11
++* inner/outer pair selection
++* 04/11/03 J. Bergsagel Changed modem state bit field struct types to enums instead and used
++* a single integer variable for each "bitfield".
++* Changed bit field for host interrupt masks to an integer value also.
++* 04/14/03 J. Bergsagel Changed name of table pointer "meanSquareTblDstrm_p" to "marginTblDstrm_p".
++* 04/03/03 Umesh Iyer CMsg1 and RMsg1 use the same storage as CMSGPCB and RMSGPCB.
++* The string lengths for these have been adjusted to hold the longest
++* message in each case. The PCB messages from ADSL2 are longer.
++* 04/21/03 Sameeer V Added new host mailbox message for shutting down the DSLSS peripherals.
++* 04/23/03 J. Bergsagel Fixed comments for overlay mailbox messages and for losErrors.
++* 04/28/03 Mannering Added skip phase op flag to CO profile data structure
++* 05/05/03 Mannering Review Comments - Removed "#if CO_PROFILE" from around structure
++* definitions and define the number of profiles (DEV_HOST_LIST_ENTRIES)
++* 05/13/03 J. Bergsagel Added new elements to DEV_HOST_phyPerf_t for host control of hybrid.
++* 05/15/03 J. Bergsagel Added "farEndLosErrors" and "farEndRdiErrors" to DEV_HOST_modemStatsDef_t.
++* 05/16/03 Mannering Updated CO profile structure to support updated bit allocation and
++* interopability.
++* 05/20/03 Sameer V Added DSP message to inicate DYING GASP.
++* 05/22/03 J. Bergsagel Added a new struct typedef "DEV_HOST_hostInterruptSource_t".
++* Added "atucGhsRevisionNum" to "DEV_HOST_dspWrNegoParaDef_t".
++* Moved the following struct typedef's here to the public host interface:
++* DEV_HOST_dspBitSwapDef_t
++* DEV_HOST_atmDsBert_t
++* 05/28/03 A. Redfern Changed pointer type and location for margin reporting.
++* 05/28/03 Mannering Moved CO profile defines to dev_host_interface_pvt.h
++* 05/28/03 J. Bergsagel Moved subStateIndex and STM BERT controls into new struct "DEV_HOST_modemEnvPublic_t"
++* 05/29/03 J. Bergsagel Added elements to "DEV_HOST_modemEnvPublic_t" for host control of DSLSS LED's.
++* 06/10/03 Umesh Iyer Modified trainMode check to be compliant with the new host i/f mods.
++* 06/05/03 J. Bergsagel Added enum that will eventually replace the bitfield: DEV_HOST_diagAnlgOptionsVar_t.
++* Added new element "currentHybridNumUsed" in the DEV_HOST_phyPerf_t typedef
++* Added new host control flags for LPR signal detection on GPIO[0].
++* 06/06/03 A. Redfern Removed fine gain scale from the CO profile and added max downstream power cutback.
++* Changed "test1" in CO profile struct to "phyEcDelayAdjustment".
++* 06/26/03 J. Bergsagel Added genericStructure typedef and two pointer elements of this type in the big table.
++* 07/03/03 Jack Huang Renamed test2 to bSwapThresholdUpdate
++* 07/07/03 Mallesh Changed phySigTxPowerCutback_f flag to a variable phySigTxGainReductionAt0kft which indicates the
++* amount of gain reduction in linear scale.
++* 07/15/03 Sameer V Changed DEV_HOST_diagAnlgOptionsVar_t to be an enum instead of a bit field. Host code
++* does not support setting bit fields.
++* 07/22/03 Jack Huang Added bitswap control flag in host i/f for API calls
++* 08/06/03 Sameer V Added missingToneDs_p to the DEV_HOST_oamWrNegoParaDef_t to enable host to switch off
++* DS tones on specified bins
++* 08/21/03 Jack Huang Added pcbEnabled flag in the DEV_HOST_modemEnvPublic_t structure
++* Added g.hs buffer definitions to DEV_HOST_dspOamSharedInterface_t
++* Added DEV_HOST_consBufDef_t to the DEV_HOST_dspOamSharedInterface_t structure
++* 08/26/03 J. Bergsagel Fixed name of "missingToneDs_p" to be "missingToneDsAddr" instead (since it is
++* not really used as a pointer).
++* 09/11/03 Mallesh Added a flag "usPilotInT1413ModeInMedley" to determine the need to send Upstream Pilot
++* in medley in T1.413 mode.
++* 09/12/03 J. Bergsagel Changed "test3" to "phyBitaFastPathExcessFineGainBump" in CO profile struct.
++* Changed "test4" to "phyBitaSkipGapAdjustment" in CO profile struct.
++* 09/23/03 J. Bergsagel Changed "T1413vendorRevisionNumber" to "vendorRevisionNumber" in DEV_HOST_msg_t.
++* Added ADSL2 and ADSL2 diag. states to the modem state bit field.
++* 10/01/03 J. Bergsagel Changed define of "MULTI_MODE" to be 255 to indicate that all possible bits
++* in the 8-bit bit field are turned on for any current and future training modes.
++* 10/09/03 M. Turkboylari Added DSP_TRAINING_MSGS and adsl2DeltMsgs_p, which is a pointer to a pointer,
++* in order to pass the ADSL2 training and DELT messages to the host side. This is for ACT.
++* 10/20/03 Mallesh Added a GHS state enumerator for cleardown
++* 10/20/03 Xiaohui Li Add definition for READSL2_MODE and READSL2_DELT
++* 11/07/03 J. Bergsagel Removed all code for when SWTC==1, which therefore allows removal of include of
++* "env_def_defines.h". We shouldn't have any compile tokens used in this file.
++* (the SWTC token is always off in any Ax7 code).
++* 11/14/03 J. Bergsagel Also removed READSL2_ENABLE token (no more compile tokens to be used in this .h file).
++* 12/12/03 Sameer/Ram Added DEV_HOST_EOCAOC_INTERRUPT_MASK to enable host to disable response code for AOC/EOC
++* mailbox messages
++* 12/09/03 Jack Huang Changed G.hs txbuf size from 60 to 64 to fit the max segment size
++* 12/15/03 Mallesh Changed vendor ID type defenition from SINT16 to UINT16
++* 12/23/03 Sameer V Added ability to turn off constellation display reporting to host using oamFeature bit field.
++* 12/24/03 Sameer V Changed comment for Constellation Display Current Address to Host Write instead of DSP Write.
++* 12/26/03 Sameer/Ram Added DEV_HOST_GHSMSG_INTERRUPT_MASK to enable host to disable response code for GHS Messages
++* (C) Copyright Texas Instruments Inc. 2002. All rights reserved.
++*******************************************************************************/
++
++#include "dev_host_verdef.h"
++
++// ---------------------------------------------------------------------------------
++// Address of the pointer to the DEV_HOST_dspOamSharedInterface_s struct of pointers
++// This is where it all starts.
++// ---------------------------------------------------------------------------------
++#define DEV_HOST_DSP_OAM_POINTER_LOCATION 0x80000000
++
++// The define "MAX_NUM_UPBINS" is used in "DEV_HOST_diagAnlgInputVar_t" below.
++// This value can never be changed (for host intf. backwards compatibility)
++#define MAX_NUM_UPBINS 64
++
++// -----------------------------------------------
++// Begin common enumerations between DSP and host.
++// -----------------------------------------------
++
++// These Host-to-DSP commands are organized into two groups:
++// immediate state change commands and status affecting commands.
++// Do not add or remove commands except at the bottom since the DSP assumes this sequence.
++
++enum
++{
++ HOST_ACTREQ, // Send R-ACKREQ and monitor for C-ACKx
++ HOST_QUIET, // Sit quietly doing nothing for about 60 seconds, DEFAULT STATE; R_IDLE
++ HOST_XMITBITSWAP, // Perform upstream bitswap - FOR INTERNAL USE ONLY
++ HOST_RCVBITSWAP, // Perform downstream bitswap - FOR INTERNAL USE ONLY
++ HOST_RTDLPKT, // Send a remote download packet - FOR INTERNAL USE ONLY
++ HOST_CHANGELED, // Read the LED settings and change accordingly
++ HOST_IDLE, // Sit quiet
++ HOST_REVERBTEST, // Generate REVERB for manufacturing test
++ HOST_CAGCTEST, // Set coarse receive gain for manufacturing test
++ HOST_DGASP, // send Dying Gasp messages through EOC channel
++ HOST_GHSREQ, // G.hs - FOR INTERNAL USE ONLY
++ HOST_GHSMSG, // G.hs - FOR INTERNAL USE ONLY
++ HOST_GHS_SENDGALF, // G.hs - FOR INTERNAL USE ONLY
++ HOST_GHSEXIT, // G.hs - FOR INTERNAL USE ONLY
++ HOST_GHSMSG1, // G.hs - FOR INTERNAL USE ONLY
++ HOST_HYBRID, // Enable/Disable automatic hybrid switch
++ HOST_RJ11SELECT, // RJ11 inner/outer pair select
++ HOST_DIGITAL_MEM, // Digital Diags: run external memory tests
++ HOST_TXREVERB, // AFE Diags: TX path Reverb
++ HOST_TXMEDLEY, // AFE Diags: TX path Medley
++ HOST_RXNOISEPOWER, // AFE Diags: RX noise power
++ HOST_ECPOWER, // AFE Diags: RX eco power
++ HOST_ALL_ADIAG, // AFE Diags: all major analog diagnostic modes. Host is responsible to initiate each diagnostic sessions
++ HOST_USER_ADIAG, // AFE Diags: Host fills in analog diagnostic input data structure as specified and requests DSP to perform measurements as specified
++ HOST_QUIT_ADIAG, // AFE Diags: Host requests DSP to quit current diagnostic session. This is used for stopping the transmit REVERB/MEDLEY
++ HOST_NO_CMD, // All others - G.hs - FOR INTERNAL USE ONLY
++ HOST_DSLSS_SHUTDOWN, // Host initiated DSLSS shutdown message
++ HOST_SET_GENERIC, // Set generic CO profile
++ HOST_UNDO_GENERIC, // Set profile previous to Generic
++ HOST_GHS_CLEARDOWN // G.hs - FOR INTERNAL USE ONLY to start cleardown
++};
++
++// These DSP-to-Host responses are organized into two groups:
++// responses to commands and requests for OAM services.
++
++enum
++{
++ DSP_IDLE, // R_IDLE state entered
++ DSP_ACTMON, // R_ACTMON state entered
++ DSP_TRAIN, // R_TRAIN state entered
++ DSP_ACTIVE, // R_ACTIVE state entered
++ DSP_XMITBITSWAP, // Upstream bitswap complete - FOR INTERNAL USE ONLY
++ DSP_RCVBITSWAP, // Downstream bitswap complete - FOR INTERNAL USE ONLY
++ DSP_RTDL, // R_RTDL state entered - FOR INTERNAL USE ONLY
++ DSP_RRTDLPKT, // RTDL packet received - FOR INTERNAL USE ONLY
++ DSP_XRTDLPKT, // RTDL packet transmitted - FOR INTERNAL USE ONLY
++ DSP_ERROR, // Command rejected, wrong state for this command
++ DSP_REVERBTEST, // Manufacturing REVERB test mode entered
++ DSP_CAGCTEST, // Manufacturing receive gain test done
++ DSP_OVERLAY_START, // Notify host that page overlay has started - overlay number indicated by "tag"
++ DSP_OVERLAY_END, // Notify host that page overlay has ended - overlay number indicated by "tag"
++ DSP_CRATES1, // CRATES1 message is valid and should be copied to host memory now
++ DSP_SNR, // SNR calculations are ready and should be copied to host memory now
++ DSP_GHSMSG, // G.hs - FOR INTERNAL USE ONLY
++ DSP_RCVBITSWAP_TIMEOUT, // Acknowledge Message was not received within ~500 msec (26 Superframes).
++ DSP_ATM_TC_SYNC, // Indicates true TC sync on both the upstream and downstream. Phy layer ready for data xfer.
++ DSP_ATM_NO_TC_SYNC, // Indicates loss of sync on phy layer on either US or DS.
++ DSP_HYBRID, // DSP completed hybrid switch
++ DSP_RJ11SELECT, // DSP completed RJ11 inner/outer pair select
++ DSP_INVALID_CMD, // Manufacturing (Digital and AFE) diags: CMD received not recognized
++ DSP_TEST_PASSED, // Manufacturing diags: test passed
++ DSP_TEST_FAILED, // Manufacturing diags: test failed
++ DSP_TXREVERB, // Manufacturing AFE diags: Response to HOST_TXREVERB
++ DSP_TXMEDLEY, // Manufacturing AFE diags: Response to HOST_TXMEDLEY
++ DSP_RXNOISEPOWER, // Manufacturing AFE diags: Response to HOST_RXNOISEPOWER
++ DSP_ECPOWER, // Manufacturing AFE diags: Response to HOST_ECPOWER
++ DSP_ALL_ADIAG, // Manufacturing AFE diags: Response to HOST_ALL_ADIAG
++ DSP_USER_ADIAG, // Manufacturing AFE diags: Response to HOST_USER_ADIAG
++ DSP_QUIT_ADIAG, // Manufacturing AFE diags: Response to HOST_QUIT_ADIAG
++ DSP_DGASP, // DSP Message to indicate dying gasp
++ DSP_EOC, // DSP Message to indicate that DSP sent an EOC message to CO
++ DSP_TRAINING_MSGS // DSP Message to indicate that host has to copy the training message specified in the tag field.
++};
++
++// Define different ADSL training modes.
++//Defintions as per new host interface.
++#define NO_MODE 0
++#define GDMT_MODE 2
++#define GLITE_MODE 4
++#define ADSL2_MODE 8
++#define ADSL2_DELT (ADSL2_MODE+1)
++#define ADSL2PLUS_MODE 16
++#define ADSL2PLUS_DELT (ADSL2PLUS_MODE+1)
++#define READSL2_MODE 32
++#define READSL2_DELT (READSL2_MODE+1)
++#define T1413_MODE 128
++#define MULTI_MODE 255 // all possible bits are set in the bit field
++
++// Define the reason for dropping the connection
++
++enum
++{
++ REASON_LOS = 0x01,
++ REASON_DYING_GASP = 0x02,
++ REASON_USCRCERR = 0x04,
++ REASON_MARGIN_DROP = 0x08
++};
++
++
++// ----------------------------------------------------
++// Begin modem state bit field definitions - DSP write.
++// ----------------------------------------------------
++
++// BitField1 for initial states and G.hs states.
++// If more values need to be added, they will be added at the end (up to 32 total entries). However, if this causes
++// the state transitions to tick off out of normal bit order, then the C code will have to be re-written
++// that causes the proper values to be entered into the modem state bit fields.
++typedef enum
++{
++ ZERO_STATE1 = 0,
++ RTEST = 0x1,
++ RIDLE = 0x2,
++ RINIT = 0x4,
++ RRESET = 0x8,
++ GNSFLR = 0x10,
++ GTONE = 0x20,
++ GSILENT = 0x40,
++ GNEGO = 0x80,
++ GFAIL = 0x100,
++ GACKX = 0x200,
++ GQUIET2 = 0x400
++} DEV_HOST_stateBitField1_t; // this enum should only have 32 bit entries in it. Add another enum if you need more.
++
++// BitField2 for T1.413 states and for the rest of the modem states (so far)
++// If more values need to be added, they will be added at the end (up to 32 total entries). However, if this causes
++// the state transitions to tick off out of normal bit order, then the C code will have to be re-written
++// that causes the proper values to be entered into the modem state bit fields.
++typedef enum
++{
++ ZERO_STATE2 = 0,
++ TNSFLR = 0x1,
++ TACTREQ = 0x2,
++ TACTMON = 0x4,
++ TFAIL = 0x8,
++ TACKX = 0x10,
++ TQUIET2 = 0x20,
++ RQUIET2 = 0x40,
++ RREVERB1 = 0x80,
++ RQUIET3 = 0x100,
++ RECT = 0x200,
++ RREVERB2 = 0x400,
++ RSEGUE1 = 0x800,
++ RREVERB3 = 0x1000,
++ RSEGUE2 = 0x2000,
++ RRATES1 = 0x4000,
++ RMSGS1 = 0x8000,
++ RMEDLEY = 0x10000,
++ RREVERB4 = 0x20000,
++ RSEGUE3 = 0x40000,
++ RMSGSRA = 0x80000,
++ RRATESRA = 0x100000,
++ RREVERBRA = 0x200000,
++ RSEGUERA = 0x400000,
++ RMSGS2 = 0x800000,
++ RRATES2 = 0x1000000,
++ RREVERB5 = 0x2000000,
++ RSEGUE4 = 0x4000000,
++ RBNG = 0x8000000,
++ RREVERB6 = 0x10000000,
++ RSHOWTIME = 0x20000000
++} DEV_HOST_stateBitField2_t; // this enum should only have 32 bit entries in it. Add another enum if you need more.
++
++// BitField3 for ADSL2 states
++// If more values need to be added, they will be added at the end (up to 32 total entries). However, if this causes
++// the state transitions to tick off out of normal bit order, then the C code will have to be re-written
++// that causes the proper values to be entered into the modem state bit fields.
++typedef enum
++{
++ ZERO_STATE3 = 0,
++ G2QUIET1 = 0x1,
++ G2COMB1 = 0x2,
++ G2QUIET2 = 0x4,
++ G2COMB2 = 0x8,
++ G2ICOMB1 = 0x10,
++ G2LINEPROBE = 0x20,
++ G2QUIET3 = 0x40,
++ G2COMB3 = 0x80,
++ G2ICOMB2 = 0x100,
++ G2RMSGFMT = 0x200,
++ G2RMSGPCB = 0x400,
++ G2REVERB1 = 0x800,
++ G2QUIET4 = 0x1000,
++ G2REVERB2 = 0x2000,
++ G2QUIET5 = 0x4000,
++ G2REVERB3 = 0x8000,
++ G2ECT = 0x10000,
++ G2REVERB4 = 0x20000,
++ G2SEGUE1 = 0x40000,
++ G2REVERB5 = 0x80000,
++ G2SEGUE2 = 0x100000,
++ G2RMSG1 = 0x200000,
++ G2MEDLEY = 0x400000,
++ G2EXCHANGE = 0x800000,
++ G2RMSG2 = 0x1000000,
++ G2REVERB6 = 0x2000000,
++ G2SEGUE3 = 0x4000000,
++ G2RPARAMS = 0x8000000,
++ G2REVERB7 = 0x10000000,
++ G2SEGUE4 = 0x20000000
++} DEV_HOST_stateBitField3_t; // this enum should only have 32 bit entries in it. Add another enum if you need more.
++
++// BitField4 for ADSL2 diag. states
++// If more values need to be added, they will be added at the end (up to 32 total entries). However, if this causes
++// the state transitions to tick off out of normal bit order, then the C code will have to be re-written
++// that causes the proper values to be entered into the modem state bit fields.
++typedef enum
++{
++ ZERO_STATE4 = 0,
++ GDSEGUE1 = 0x1,
++ GDREVERB5 = 0x2,
++ GDSEGUE2 = 0x4,
++ GDEXCHANGE = 0x8,
++ GDSEGUELD = 0x10,
++ GDRMSGLD = 0x20,
++ GDQUIET1LD = 0x40,
++ GDQUIET2LD = 0x80,
++ GDRACK1 = 0x100,
++ GDRNACK1 = 0x200,
++ GDQUIETLAST = 0x400
++} DEV_HOST_stateBitField4_t; // this enum should only have 32 bit entries in it. Add another enum if you need more.
++
++// This struct collects all of the bitfield types listed above for the modem state bit field(s)
++typedef struct
++{
++ DEV_HOST_stateBitField1_t bitField1; // this is the first modem state bit field (mostly init. and G.hs)
++ DEV_HOST_stateBitField2_t bitField2; // this is the second modem state bit field (T1.413 and G.dmt)
++ DEV_HOST_stateBitField3_t bitField3; // this is the third modem state bit field (ADSL2)
++ DEV_HOST_stateBitField4_t bitField4; // this is the fourth modem state bit field (ADSL2 diag.)
++} DEV_HOST_modemStateBitField_t;
++
++
++// -----------------------------------------------
++// Begin NegoPara message definitions - DSP write.
++// -----------------------------------------------
++
++typedef struct
++{
++ UINT8 trainMode; // Train mode selected. See training modes defined above.
++ UINT8 bDummy1; // dummy byte for explicit 32-bit alignment
++ UINT16 lineLength; // Contains loop length estimate. Accuracy w/i 500 ft. LSbit = 1 for straight loop, = 0 for bridge tap
++ UINT32 atucVendorId; // Pass the vendor id of the CO to the host
++ UINT8 cMsgs1[8]; // CMsgs1 and CMSGPCB
++ UINT16 adsl2DSRate; //
++ UINT8 cRates2; //
++ UINT8 rRates2; //
++ UINT8 rRates1[4][11]; //
++ UINT8 cMsgs2[4]; //
++ UINT8 cRates1[4][30]; //
++ UINT8 rMsgs2[4]; //
++ UINT16 adsl2USRate; //
++ UINT8 atucGhsRevisionNum; // Pass the G.hs Revision number of the CO to the host
++ UINT8 reserved1; //
++ PUINT8 *adsl2DeltMsgs_p; // This pointer to a pointer passes the address of the globalvar.pString, which is also
++ // a pointer list of pointers. It will be used to pass all the new ADSL2 DELT messages to
++ // host side. This is for ACT.
++} DEV_HOST_dspWrNegoParaDef_t;
++
++
++// ----------------------------------------------------
++// Begin OAM NegoPara message definitions - Host write.
++// ----------------------------------------------------
++
++// OAM Feature bit fields.
++//
++// Bit 0 - Enable auto retrain of modem
++// Bit 1 - Detect and report TC sync to host
++// Bit 2-31 - Reserved
++
++#define DEV_HOST_AUTORETRAIN_ON 0x00000001
++#define DEV_HOST_TC_SYNC_DETECT_ON 0x00000002
++
++#define DEV_HOST_AUTORETRAIN_MASK 0x00000001
++#define DEV_HOST_TC_SYNC_DETECT_MASK 0x00000002
++#define DEV_HOST_EOCAOC_INTERRUPT_MASK 0x00000004
++#define DEV_HOST_CONS_DISP_DISABLE_MASK 0x00000008
++#define DEV_HOST_GHSMSG_INTERRUPT_MASK 0x00000010
++
++typedef struct
++{
++ UINT8 stdMode; // Desired train mode. See training modes defined above.
++ UINT8 ghsSequence; // Selected G.hs session as shown in Appendix 1
++ UINT8 usPilotFlag; // Value of 1 indicates transmit an upstream pilot on bin 16
++ UINT8 bDummy1; // dummy byte for 32-bit alignment
++ UINT8 rMsgs1[38]; // RMSG-1(6) and RMSG_PCB (38)
++ UINT8 bDummy2[2]; // dummy bytes for 32-bit alignment
++ UINT32 oamFeature; // 32 bit wide bit field to set OAM-specific features.
++ SINT8 marginThreshold; // Threshold for margin reporting
++ UINT8 hostFixAgc; // flag to force datapump to bypass AGC training and use the following values
++ UINT8 hostFixEqualizer; // forced analog equalizer value used during AGC training when hostfix_agc is on
++ UINT8 hostFixPga1; // forced pga1 value used during AGC training when hostFixAgc is on
++ UINT8 hostFixPga2; // forced pga2 value used during AGC training when hostFixAgc is on
++ UINT8 hostFixPga3; // forced pga3 value used during AGC training when hostFixAgc is on
++ UINT8 marginMonitorShwtme; // margin monitoring flag (during showtime)
++ UINT8 marginMonitorTrning; // margin monitoring flag (during training)
++ UINT8 disableLosAlarm; // flag to disable training based on los
++ UINT8 usCrcRetrain; // flag to disable retrain due to excessive USCRC
++ UINT8 t1413VendorId[2]; // Vendor ID used for T1.413 trainings
++ UINT8 gdmtVendorId[8]; // Vendor ID used for G.dmt trainings (ITU VendorID)
++ UINT8 missingTones[64]; // 64 element array to define missing tones for TX_MEDLEY and TX REVERB tests
++ UINT32 missingToneDsAddr; // Address given to DSP for tones to be switched off in DS direction
++ UINT8 dsToneTurnoff_f; // This flag controls the DS tone turn off logic
++ UINT8 reserved1; // Dummy bytes
++ UINT8 reserved2; // Dummy bytes
++ UINT8 reserved3; // Dummy bytes
++} DEV_HOST_oamWrNegoParaDef_t;
++
++
++// ----------------------------------------
++// Begin Rate-adaptive message definitions.
++// ----------------------------------------
++
++// The four values below can never be changed (for host intf. backwards compatibility)
++#define DEV_HOST_RMSGSRA_LENGTH 10
++#define DEV_HOST_RRATESRA_LENGTH 1
++#define DEV_HOST_CRATESRA_LENGTH 120
++#define DEV_HOST_CMSGSRA_LENGTH 6
++
++typedef struct
++{
++ UINT8 rRatesRaString[DEV_HOST_RRATESRA_LENGTH+3];
++ UINT8 rMsgsRaString[DEV_HOST_RMSGSRA_LENGTH+2];
++ UINT8 cMsgsRaString[DEV_HOST_CMSGSRA_LENGTH+2];
++} DEV_HOST_raMsgsDef_t;
++
++
++// ----------------------------------------------
++// Begin superframe cnts definitions - DSP write.
++// ----------------------------------------------
++
++#define DEV_HOST_FRAMES_PER_SUPER 68
++#define DEV_HOST_SUPERFRAMECNTDSTRM 0
++#define DEV_HOST_SUPERFRAMECNTUSTRM 4
++
++// Although only the least significant 8 bits should be used as an
++// unsigned char for computing the bitswap superframe number, a
++// full 32 bit counter is provided here in order to have an
++// accurate indicator of the length of time that the modem has
++// been connected. This counter will overflow after 2.35 years
++// of connect time.
++
++typedef struct
++{
++ UINT32 wSuperFrameCntDstrm;
++ UINT32 wSuperFrameCntUstrm;
++} DEV_HOST_dspWrSuperFrameCntDef_t;
++
++
++// --------------------------------
++// Begin ATUR/ATUC msg definitions.
++// --------------------------------
++
++// Grouping used by the DSP to simplify parameter passing.
++// All of these are written by the DSP.
++
++typedef struct
++{
++ UINT16 vendorId; // TI's vendor ID = 0x0004; Amati's vendor ID = 0x0006
++ UINT8 versionNum; // T1.413 issue number
++ UINT8 rateAdapt; // 0 = fix rate (Default); 1= adaptive rate
++ UINT8 trellis; // 0 = disable trellis(default); 1 = enable trellis
++ UINT8 echoCancelling; // 0 = disable echo cancelling; 1 = enable echo cancelling(default)
++ UINT8 maxBits; // value range: 0-15; default = 15
++ UINT8 maxPsd; //
++ UINT8 actualPsd; //
++ UINT8 maxIntlvDepth; // 0, 1, 2, or 3 for 64, 128, 256, or 512 max depth
++ UINT8 framingMode; // 0 for asynchronous, 1 for synchronous full overhead
++ // 2 for reduced overhead, 3 for merged reduced overhead DSP write.
++ UINT8 maxFrameMode; // maximum framing mode desired. Nor 0 or 3.
++ SINT16 targetMargin; //
++ SINT16 maxAllowedMargin; //
++ SINT16 minRequiredMargin; //
++ SINT16 maxTotBits; //
++ UINT8 grossGain; //
++ UINT8 ntr; // Enable/disable NTR support
++ SINT16 loopAttn; // Loop Attenuation
++ UINT8 vendorRevisionNumber; // Reported Vendor Revision Number
++ UINT8 reserved1; // for 32-bit alignment
++ UINT8 reserved2; // for 32-bit alignment
++ UINT8 reserved3; // for 32-bit alignment
++} DEV_HOST_msg_t;
++
++
++// --------------------------------------
++// Begin bits and gains table definitions
++// --------------------------------------
++
++typedef struct
++{
++ PUINT8 aturBng_p; // pointer to ATU-R bits and gains table
++ PUINT8 atucBng_p; // pointer to ATU-C bits and gains table
++ PUINT8 bitAllocTblDstrm_p; // pointer to Downstream Bit Allocation table
++ PUINT8 bitAllocTblUstrm_p; // pointer to Upstream Bit Allocation table
++ PSINT8 marginTblDstrm_p; // pointer to Downstream Margin table
++} DEV_HOST_dspWrSharedTables_t;
++
++
++// ----------------------------------------
++// Begin datapump code overlay definitions.
++// ----------------------------------------
++
++#define DEV_HOST_PAGE_NUM 4 // number of overlay pages
++
++// Never access a struct of this typedef directly. Always go through the DEV_HOST_olayDpDef_t struct
++typedef struct
++{
++ UINT32 overlayHostAddr; // source address in host memory
++ UINT32 overlayXferCount; // number of 32bit words to be transfered
++ UINT32 overlayDspAddr; // destination address in DSP's PMEM
++} DEV_HOST_olayDpPageDef_t;
++
++
++typedef struct
++{
++ UINT32 overlayStatus; // Status of current overlay to DSP PMEM
++ UINT32 overlayNumber; // DSP PMEM overlay page number
++ UINT32 overlayState; // Indicates whether current state is an overlay state
++ DEV_HOST_olayDpPageDef_t *olayDpPage_p[DEV_HOST_PAGE_NUM]; // Def's for the Pages
++} DEV_HOST_olayDpDef_t;
++
++
++// -------------------------
++// Begin ATM-TC definitions.
++// -------------------------
++
++// TC cell states.
++typedef enum
++{
++ TC_HUNT,
++ TC_PRESYNC,
++ TC_SYNC
++} DEV_HOST_cellDelinState_t;
++
++
++// --------------------------------------------
++// Begin datapump error/statistics definitions.
++// --------------------------------------------
++
++// Never access a struct of this typedef directly. Always go through the DEV_HOST_modemStatsDef_t struct.
++typedef struct
++{
++ UINT32 crcErrors; // Num of CRC errored ADSL frames
++ UINT32 fecErrors; // Num of FEC errored (corrected) ADSL frames
++ UINT32 ocdErrors; // Out of Cell Delineation
++ UINT32 ncdError; // No Cell Delineation
++ UINT32 lcdErrors; // Loss of Cell Delineation (within the same connection)
++ UINT32 hecErrors; // Num of HEC errored ADSL frames
++} DEV_HOST_errorStats_t;
++
++
++typedef struct
++{
++ DEV_HOST_errorStats_t *usErrorStatsIntlv_p; // us error stats - interleave path
++ DEV_HOST_errorStats_t *dsErrorStatsIntlv_p; // ds error stats - interleave path
++ DEV_HOST_errorStats_t *usErrorStatsFast_p; // us error stats - fast path
++ DEV_HOST_errorStats_t *dsErrorStatsFast_p; // ds error stats - fast path
++ UINT32 losErrors; // Num of ADSL frames where loss-of-signal
++ UINT32 sefErrors; // Num of severly errored ADSL frames - LOS > MAXBADSYNC ADSL frames
++ UINT32 farEndLosErrors; // Number of reported LOS defects by the CO.
++ UINT32 farEndRdiErrors; // Number of reported RDI defects by the CO.
++} DEV_HOST_modemStatsDef_t;
++
++// Never access a struct of this typedef directly. Always go through the DEV_HOST_atmStats_t struct.
++typedef struct
++{
++ UINT32 goodCount; // Upstream Good Cell Count
++ UINT32 idleCount; // Upstream Idle Cell Count
++} DEV_HOST_usAtmStats_t;
++
++// Never access a struct of this typedef directly. Always go through the DEV_HOST_atmStats_t struct.
++typedef struct
++{
++ UINT32 goodCount; // Downstream Good Cell Count
++ UINT32 idleCount; // Downstream Idle Cell Count
++ UINT32 badHecCount; // Downstream Bad Hec Cell Count
++ UINT32 ovflwDropCount; // Downstream Overflow Dropped Cell Count
++ DEV_HOST_cellDelinState_t delineationState; // Indicates current delineation state
++} DEV_HOST_dsAtmStats_t;
++
++
++typedef struct
++{
++ DEV_HOST_usAtmStats_t *us0_p; // US ATM stats for TC channel 0
++ DEV_HOST_dsAtmStats_t *ds0_p; // DS ATM stats for TC channel 0
++ DEV_HOST_usAtmStats_t *us1_p; // US ATM stats for TC channel 1
++ DEV_HOST_dsAtmStats_t *ds1_p; // DS ATM stats for TC channel 1
++} DEV_HOST_atmStats_t;
++
++
++// ----------------------
++// Begin EOC definitions.
++// ----------------------
++
++// The two values below can never change (for backwards compatibility of host intf.)
++#define DEV_HOST_EOCREG4LENGTH 32
++#define DEV_HOST_EOCREG5LENGTH 32
++
++typedef struct
++{
++ UINT8 eocReg4[DEV_HOST_EOCREG4LENGTH]; // Host/Dsp Write, vendor specific EOC Register 4
++ UINT8 eocReg5[DEV_HOST_EOCREG5LENGTH]; // Host/Dsp Write, vendor specific EOC Register 5
++ UINT8 vendorId[8]; // Host write
++ UINT8 revNumber[4]; // Host, ATU-R Revision Number
++ UINT8 serialNumber[32]; // Host write
++ UINT8 eocReg4Length; // Host Write, valid length for EOC register 4
++ UINT8 eocReg5Length; // Host Write, valid length for EOC register 5
++ UINT8 dummy[2]; // dummy bytes for 32-bit alignment
++ UINT32 eocModemStatusReg; // Dsp Write, status bits to host
++ UINT8 lineAtten; // Dsp Write, line attenuation in 0.5 db step
++ SINT8 dsMargin; // DSP Write, measured DS margin
++ UINT8 aturConfig[30]; // Dsp Write, also used by EOC for ATUR Configuration
++} DEV_HOST_eocVarDef_t;
++
++typedef struct
++{
++ UINT16 endEocThresh; // Host Write, end of Clear EOC stream threshold
++ UINT16 dummy; // dummy value to fill gap
++ UINT32 dropEocCount; // Dsp Write, counter of dropped Clear EOC bytes
++ UINT16 eocRxLength; // Host/DSP write, number of valid Rx Clear EOC bytes
++ UINT16 eocTxLength; // Host/DSP write, number of valid Tx Clear EOC bytes
++ UINT8 eocRxBuf[64]; // Dsp Write, Buffer for receiving Rx Clear EOC bytes
++ UINT8 eocTxBuf[64]; // Host Write, Buffer for writing Tx Clear EOC bytes
++} DEV_HOST_clearEocVarDef_t;
++
++
++// -----------------------------------
++// Begin CO profile Definitions.
++// -----------------------------------
++
++/* struct size must be a word size */
++typedef struct
++{
++
++ SINT16 devCodecRxdf4Coeff[12] ; // (BOTH) IIR Coefficients
++ SINT16 devCodecTxdf2aCoeff[64] ; // (BOTH) FIR filter coefficients
++ SINT16 devCodecTxdf2bCoeff[64] ; // (BOTH) FIR filter coefficients
++ SINT16 devCodecTxdf1Coeff[12] ; // (BOTH) IIR filter coefficients
++ UINT16 devCodecTxDf2aDen; // (BOTH) denominator for IIR filter
++ UINT16 devCodecTxDf2bDen; // (BOTH) denominator for IIR filter
++ SINT16 ctrlMsmSpecGain[32]; // (BOTH)
++
++ SINT16 phyBitaRateNegIntNoTrellis ; // (BOTH) value to set
++ SINT16 phyBitaRateNegIntTrellis ; // (BOTH) value to set
++ SINT16 phyBitaRateNegFastNoTrellis ; // (BOTH) value to set
++ SINT16 phyBitaRateNegFastTrellis ; // (BOTH) value to set
++ SINT16 phyBitaRsFlag ; // (BOTH)
++ SINT16 phyBitaFirstSubChannel ; // (BOTH)
++ SINT16 phyBitaMaxFineGainBump; // max fine gain bump
++ SINT16 phyBitaFineGainReduction; // fine gain reduction
++ SINT16 phyBitaMaxDownstreamPowerCutback; // max downstream power cutback
++
++ SINT16 phySigTxGainReductionAt0kft; // upstream power reduction at 0 kft.
++
++ SINT16 phyAgcPgaTarget ; // (BOTH) compare value
++
++ UINT16 imsg413TxRate ; // (BOTH) Tx rate
++ SINT16 imsg413RsBytesAdjust ; // (BOTH) subtract value
++ UINT16 imsg413PstringMask ; // (POTS) Or'ed into pString[RMSGS1_INDEX][1]
++ SINT16 imsg413UsPilot ; // (BOTH)??
++ UINT16 imsg413SkipPhaseOp ; // (POTS)
++
++ UINT16 ctrlMsmSensitivity1 ; // (BOTH) value to set
++ UINT16 ctrlMsmTxPsdShape_f; // (BOTH) upstream spectral shaping flag
++
++ UINT16 ovhdAocUsBswapReq_f ; // (BOTH)value to set
++ UINT16 ovhdAocScanMse_f ; // (BOTH)value to set
++
++ SINT16 phyRevFullFirstBin ; //
++ SINT16 phyRevFullLastBin ; //
++ SINT16 phyRevFirstBin ; //
++ SINT16 phyRevLastBin ; //
++ SINT16 phyMedFirstBin ; //
++ SINT16 phyMedLastBin ; //
++ SINT16 phyMedOptionalLastBin; // Medley last bin - optional
++
++ SINT16 phyEcDelayAdjustment; // Echo delay adjustment
++ SINT16 bSwapThresholdUpdate; // bSwapThresholdUpdate
++ SINT16 phyBitaFastPathExcessFineGainBump; // Used in phy_bita.c
++ SINT16 phyBitaSkipGapAdjustment; // Used in phy_bita.c
++ SINT16 usPilotInT1413ModeInMedley; // To send Upstream Pilot in medley in T1.413 mode.
++
++ UINT32 profileVendorId ; // vendor id
++
++} DEV_HOST_coData_t ;
++
++typedef struct
++{
++ DEV_HOST_coData_t * hostProfileBase_p; // base address of profile list
++} DEV_HOST_profileBase_t ;
++
++
++
++// -----------------------------------
++// Begin DSP/Host Mailbox Definitions.
++// -----------------------------------
++
++// The 3 values below can never be decreased, only increased.
++// If you increase one of the values, you must add more to the
++// initializers in "dev_host_interface.c".
++#define DEV_HOST_HOSTQUEUE_LENGTH 8
++#define DEV_HOST_DSPQUEUE_LENGTH 8
++#define DEV_HOST_TEXTQUEUE_LENGTH 8
++
++// Never access a struct of this typedef directly. Always go through the DEV_HOST_mailboxControl_t struct.
++typedef struct
++{
++ UINT8 cmd;
++ UINT8 tag;
++ UINT8 param1;
++ UINT8 param2;
++} DEV_HOST_dspHostMsg_t;
++
++// Never access a struct of this typedef directly. Always go through the DEV_HOST_mailboxControl_t struct.
++typedef struct
++{
++ UINT32 msgPart1;
++ UINT32 msgPart2;
++} DEV_HOST_textMsg_t;
++
++// The structure below has been ordered so that the Host need only write to
++// even byte locations to update the indices.
++
++// The Buffer pointers in the struct below each point to a different
++// struct array that has an array size of one of the matching Queue Length
++// values defined above (DEV_HOST_HOSTQUEUE_LENGTH, DEV_HOST_DSPQUEUE_LENGTH,
++// and DEV_HOST_TEXTQUEUE_LENGTH).
++
++typedef struct
++{
++ UINT8 hostInInx; // Host write, DSP must never write except for init
++ UINT8 bDummy0[3]; // dummy bytes for explicit 32-bit alignment
++ UINT8 hostOutInx; // DSP write, Host must never write
++ UINT8 bDummy1[3]; // dummy bytes for explicit 32-bit alignment
++ UINT8 dspOutInx; // Host write, DSP must never write except for init
++ UINT8 bDummy2[3]; // dummy bytes for explicit 32-bit alignment
++ UINT8 dspInInx; // DSP write, Host must never write
++ UINT8 bDummy3[3]; // dummy bytes for explicit 32-bit alignment
++ UINT8 textInInx; // DSP write, Host must never write
++ UINT8 bDummy4[3]; // dummy bytes for explicit 32-bit alignment
++ UINT8 textOutInx; // Host write, DSP must never write except for init
++ UINT8 bDummy5[3]; // dummy bytes for explicit 32-bit alignment
++ DEV_HOST_dspHostMsg_t *hostMsgBuf_p; // pointer to Host Mailbox Buffer (Host writes the buffer)
++ DEV_HOST_dspHostMsg_t *dspMsgBuf_p; // pointer to DSP Mailbox Buffer (DSP writes the buffer)
++ DEV_HOST_textMsg_t *textMsgBuf_p; // pointer to Text Mailbox Buffer (DSP writes the buffer)
++} DEV_HOST_mailboxControl_t;
++
++
++//-----------------------------------------
++// Physical layer performance parameter
++//-----------------------------------------
++typedef struct
++{
++ SINT32 hybridCost[5]; // Cost functions for hybrids (0: none, 1-4 hybrid options)
++ SINT32 usAvgGain; // upstream average gain in 20log10 (Q8)
++ SINT32 dsAvgGain; // downstream average gain in 20log10 (Q8)
++ UINT8 disableDspHybridSelect_f; // Allows host to disable the automatic hybrid selection by the DSP
++ UINT8 hostSelectHybridNum; // DSP will use this hybrid number only if DSP Select is disabled (values: 1-4)
++ UINT8 currentHybridNumUsed; // DSP indicates to the host the current hybrid number in use
++ UINT8 reserved1; // reserved for future use
++} DEV_HOST_phyPerf_t;
++
++
++/***********************************************************
++ * The 3 structures below are used only for analog
++ * diagnostic functions originally defined in diag.h
++ * Moved here by Carlos A. Perez under J. Bergsagel request
++ ***********************************************************/
++
++/****************************************************************************/
++/* Options for the Analog Diagnostic user input data structure */
++/* (MUST be word aligned) */
++/****************************************************************************/
++typedef enum
++{
++ ZERO_DIAG_OPT = 0, // dummy value for zero place-holder
++ NOISE_ONLY = 0x1, // diagnostic in noise only mode (on=1, off=0), disregard diagMode 0-4
++ EXTERNAL_CO = 0x2, // operates against external CO (external=1, internal=0)
++ DIAG_AGC = 0x4, // agc selects gains control (agc=1, manual=0)
++ CROSSTALK_TEQ = 0x8, // crosstalk selects teq (crosstalk=1, manual=0)
++ LEAKY_TEQ = 0x10, // use leaky teq (on=1, off=0)
++ AUX_AMPS = 0x20, // auxamps (on=1, off=0)
++ BW_SELECT = 0x40, // change rxhpf/txlpf fc (modify=1, default=0)
++ DIAG_HYB_SELECT = 0x80, // change hybrid (modify=1, default=0)
++ POWER_DOWN_CDC = 0x100, // power down codec (power down=1, no power down=0)
++ ISDN_OP_MODE = 0x200, // operation mode (pots=0, isdn=1)
++ BYPASS_RXAF2 = 0x400, // Bypass except RXAF2 (on=1, off = 0)
++ TX_TEST_CONT = 0x800, // Continuous tx test (on=1, off=0)
++ TX_SCALE_MTT = 0x1000 // Scale tx signal for Mtt test (on=1, off=0)
++} DEV_HOST_diagAnlgOptionsVar_t;
++
++/****************************************************************************/
++/* Analog Diagnostic user input data structure (MUST be word align) */
++/****************************************************************************/
++
++typedef struct
++{
++ DEV_HOST_diagAnlgOptionsVar_t diagOption; // Other diagnostic optional settings
++
++ UINT8 diagMode; // Performance diagnostic mode
++ UINT8 txMode; // transmit mode
++ UINT8 rxMode; // receive mode
++ UINT8 teqSp; // Select teq starting pt
++ UINT8 txDf1; // see dev_codec_filters.c and
++ UINT8 txDf2a; // dev_codec.h for filter coefficients
++ UINT8 txDf2b;
++ UINT8 rxDf4;
++
++ UINT16 codingGain256Log2; // 256*Log2(coding gain)
++ UINT16 noiseMargin256Log2; // 256*Log2(noise margin)
++
++ UINT16 rxPga1; // PGA1
++ UINT16 rxPga2; // PGA2
++ UINT16 rxPga3; // PGA3
++ UINT16 anlgEq; // AEQ settings (dB/MHz)
++
++ SINT8 pilotBin; // Select pilot subchannel
++ SINT8 txSwGain; // manual set for bridge tap loop
++ SINT8 tdw1Len; // TDW1 length - 0,2,4,8,16
++ SINT8 tdw2Len; // TDW2 length - 0,2,4,8,16
++
++ UINT8 teqEcMode; // TEQ/EC mode
++ UINT8 hybrid;
++ UINT8 txAttn; // Codec Tx attenuation
++ UINT8 txGain; // Codec Tx gain (Sangam only)
++
++ SINT16 txPda; //Codec Tx Digital gain/attn
++ UINT8 txTone[MAX_NUM_UPBINS]; // Turning tones on/off
++ // Still govern by lastbin
++ UINT16 rsvd; //for 32 bits alignment
++}DEV_HOST_diagAnlgInputVar_t;
++
++/****************************************************************************/
++/* Analog diagnostic output data structure */
++/****************************************************************************/
++typedef struct
++{
++ PSINT32 rxSnr_p[2]; // Pointer to estimated snr
++ PSINT32 rxSubChannelCapacity_p[2]; // Pointer to estimated subchan capacity
++ PSINT32 rxSignalPower_p[2]; // Pointer to estimated signal power
++ PSINT32 rxNoisePower_p[2]; // Pointer to estimated noise power
++ PSINT32 rxAvg_p; // Pointer to average of rcvd signal
++ SINT32 chanCapacity[2] ; // Channel total capacity
++ SINT32 dataRate[2]; // Modem data rate (SNR)
++ SINT32 avgNoiseFloor; // Average noise floor
++ SINT16 snrGap256Log2; // 256*Log2(snr gap)
++ SINT16 rxPga1; // PGA1
++ SINT16 rxPga2; // PGA2
++ SINT16 rxPga3; // PGA3
++ SINT16 anlgEq; // AEQ settings (dB/MHz)
++ SINT16 rsvd;
++}DEV_HOST_diagAnlgOutputVar_t;
++
++
++// Bit field structure that allows the host to mask off interrupt sources for possible DSP-to-Host interrupts.
++// Each bit represents a possible source of interrupts in the DSP code that might cause a DSP-to-Host
++// interrupt to occur.
++// This mask structure is not intended to show how interrupt sources in the DSP code correspond to the actual
++// DSP-to-Host interrupts. There could be multiple ways to cause an interrupt in the DSP code, but they all
++// eventually tie into one of the three possible DSP-to-Host interrupts.
++// The host should write a "1" to an individual bit when it wants to mask possible interrupts from that source.
++
++// enum that represents individual bits in maskBitField1
++typedef enum
++{
++ ZERO_MASK1 = 0, // dummy value for zero place-holder
++ DSP_MSG_BUF = 0x1, // mask interrupts due to DSP-to-Host message mailbox updates
++ STATE_BIT_FIELD = 0x2, // mask interrupts due to changes in the modem state bit fields
++ DSP_HEARTBEAT = 0x4 // mask interrupts for the DSP hearbeat
++} DEV_HOST_intMask1_t; // this enum should only have 32 values in it (maximum).
++
++// Add more "mask bit fields" at the end of this struct if you need more mask values
++typedef struct
++{
++ DEV_HOST_intMask1_t maskBitField1;
++} DEV_HOST_hostInterruptMask_t; // this struct should only have 32 bits in it.
++
++// Bit field structure that allows the host to determine the source(s) of DSP-to-Host interrupts in case
++// several of the interrupt sources get combined onto a single DSP-to-Host interrupt.
++// DSP will set each bit to a "1"as an interrupt occurs.
++// Host has the reponsibility to clear each bit to a "0" after it has determined the source(s) of interrupts.
++// Each source bit field in this struct will use the same enum typedef that matches the corresponding mask
++// bit field in "DEV_HOST_hostInterruptMask_t"
++typedef struct
++{
++ DEV_HOST_intMask1_t sourceBitField1;
++} DEV_HOST_hostInterruptSource_t;
++
++
++// --------------------------
++// Begin bitswap definitions.
++// --------------------------
++
++// bitSwapSCnt contains the superframe to perform bit swap
++// The entries must be ordered so that the first group only contains bit change commands
++// The other entries may contain power adjustment instructions and must be
++// written with something. NOP (0) is an available instruction.
++typedef struct
++{
++ PUINT8 fineGains_p; // pointer to bng string, needed to check fine gains for powerswap
++ UINT8 bitSwapNewIndices[6]; // Bin before bitSwapBin to process
++ UINT8 bitSwapCmd[6]; // Bitswap command for bitSwapBin
++ UINT8 bitSwapBin[6]; // bin to modify
++ UINT8 bitSwapSCnt; // Superframe count on which to perform bitswap
++ UINT8 bitSwapEnabled; // bitSwapEnabled
++} DEV_HOST_dspBitSwapDef_t;
++
++
++// ---------------------------
++// Begin ATM BERT definitions.
++// ---------------------------
++
++// Structure used for ATM Idle Cells based bit error rate computation.
++typedef struct
++{
++ UINT8 atmBertFlag; // Feature enable/disable flag (Host write)
++ UINT8 dummy1;
++ UINT8 dummy[2]; // Dummy bytes for 32-bit alignment
++ UINT32 bitCountLow; // Low part of 64-bit BERT bit count (DSP write)
++ UINT32 bitCountHigh; // High part of 64-bit BERT bit count (DSP write)
++ UINT32 bitErrorCountLow; // Low part of 64-bit BERT bit count (DSP write)
++ UINT32 bitErrorCountHigh;// High part of 64-bit BERT bit count (DSP write)
++} DEV_HOST_atmDsBert_t;
++
++
++// ------------------------------------
++// Misc. modem environment definitions.
++// ------------------------------------
++
++
++typedef struct
++{
++ SINT16 subStateIndex; // Index that signifies datapump substate. (DSP write)
++ UINT8 externalBert; // Turn on/off external BERT interface. 0 = OFF; 1 = ON. (Host write)
++ UINT8 usBertPattern; // BERT pattern for US TX data. 0 = 2^15-1; 1 = 2^23-1. (Host write)
++ UINT8 overrideDslLinkLed_f; // Overrides DSP operation of the DSL_LINK LED. (Host write)
++ // 0 = DSP is in control; 1 = Host is in control.
++ UINT8 dslLinkLedState_f; // DSL_LINK LED state when override flag has been set. (Host write)
++ // DSL_LINK LED will be updated with this value once per frame.
++ // LED is active-low: 0 = ON, 1 = OFF.
++ UINT8 overrideDslActLed_f; // Overrides DSP operation of the DSL_ACT LED. (Host write)
++ // 0 = DSP is in control; 1 = Host is in control.
++ UINT8 dslActLedState_f; // DSL_ACT LED state when override flag has been set. (Host write)
++ // DSL_ACT LED will be updated with this value once per frame.
++ // LED is active-low: 0 = ON, 1 = OFF.
++ UINT8 dGaspLprIndicator_f; // How LPR signal (GPIO[0]) is to be interpreted. (Host write)
++ // 0 = LPR is active-low; 1 = LPR is active-high.
++ UINT8 overrideDspLprGasp_f; // Overrides DSP detection of LPR signal to send out DGASP. (Host write)
++ // 0 = DSP detects LPR; 1 = Host detects LPR and sends "HOST_DGASP" to DSP.
++ UINT8 pcbEnabled; // DS power cut back
++ UINT8 maxAvgFineGainCtrl_f; // If maxAvgFineGainCtrl_f == 0, then the datapump controls the maximum average fine gain value.
++ // If maxAvgFineGainCtrl_f == 1, then the host controls the maximum average fine gain value.
++ UINT32 reasonForDrop; // This field will tell the host what might be the reason for a dropped connection.
++ SINT16 maxAverageFineGain; // When maxAvgFineGainCtrl_f == 1, the value in maxAverageFineGain is the maximum average fine gain level in 256log2 units.
++ UINT8 reserved1; // These are for 32-bit alignment.
++ UINT8 reserved2; // These are for 32-bit alignment.
++} DEV_HOST_modemEnvPublic_t;
++
++
++// -----------------------------
++// Generic structure definition.
++// -----------------------------
++
++typedef struct
++{
++ PSINT8 parameter1_p;
++ PSINT16 parameter2_p;
++ PSINT32 parameter3_p;
++ PUINT8 parameter4_p;
++ PUINT16 parameter5_p;
++ PUINT32 parameter6_p;
++} DEV_HOST_genericStructure_t;
++
++
++// ------------------------------
++// Begin G.hs buffer definitions.
++// ------------------------------
++
++typedef struct
++{
++ UINT8 txBuf[64]; // G.hs xmt buffer
++} DEV_HOST_ghsDspTxBufDef_t;
++
++
++typedef struct
++{
++ UINT8 rxBuf[80]; // G.hs rcv buffer
++} DEV_HOST_ghsDspRxBufDef_t;
++
++// -----------------------------------------
++// Begin Constellation Display definitions.
++// -----------------------------------------
++
++typedef struct
++{
++ UINT32 consDispStartAddr; // Host write
++ UINT32 consDispCurrentAddr; // Host write
++ UINT32 consDispBufLen; // Constellation Buffer Length
++ UINT32 consDispBin; // Host write, DS band only
++} DEV_HOST_consBufDef_t;
++
++typedef struct
++{
++ PSINT16 buffer1_p; //DSP write
++ PSINT16 buffer2_p; //DSP write
++} DEV_HOST_snrBuffer_t;
++
++// --------------------------------------------------------------------------------------
++// Typedef to be used for the DEV_HOST_dspOamSharedInterface_s struct of pointers
++// (this is used in dev_host_interface.c).
++// NOTE: This struct of pointers is NEVER to be referenced anywhere else in the DSP code.
++// IMPORTANT: Only pointers to other structs go into this struct !!
++// --------------------------------------------------------------------------------------
++typedef struct
++{
++ DEV_HOST_hostIntfcVersionDef_t *hostIntfcVersion_p;
++ DEV_HOST_dspVersionDef_t *datapumpVersion_p;
++ DEV_HOST_modemStateBitField_t *modemStateBitField_p;
++ DEV_HOST_dspWrNegoParaDef_t *dspWriteNegoParams_p;
++ DEV_HOST_oamWrNegoParaDef_t *oamWriteNegoParams_p;
++ DEV_HOST_raMsgsDef_t *raMsgs_p;
++ DEV_HOST_dspWrSuperFrameCntDef_t *dspWriteSuperFrameCnt_p;
++ DEV_HOST_msg_t *atucMsg_p;
++ DEV_HOST_msg_t *aturMsg_p;
++ DEV_HOST_dspWrSharedTables_t *dspWrSharedTables_p;
++ DEV_HOST_olayDpDef_t *olayDpParms_p;
++ DEV_HOST_eocVarDef_t *eocVar_p;
++ DEV_HOST_clearEocVarDef_t *clearEocVar_p;
++ DEV_HOST_modemStatsDef_t *modemStats_p;
++ DEV_HOST_atmStats_t *atmStats_p;
++ DEV_HOST_mailboxControl_t *dspHostMailboxControl_p;
++ DEV_HOST_phyPerf_t *phyPerf_p;
++ DEV_HOST_diagAnlgInputVar_t *analogInputVar_p;
++ DEV_HOST_diagAnlgOutputVar_t *analogOutputVar_p;
++ DEV_HOST_hostInterruptMask_t *hostInterruptMask_p;
++ DEV_HOST_profileBase_t *profileList_p;
++ DEV_HOST_hostInterruptSource_t *hostInterruptSource_p;
++ DEV_HOST_dspBitSwapDef_t *dspBitSwapDstrm_p;
++ DEV_HOST_dspBitSwapDef_t *dspBitSwapUstrm_p;
++ DEV_HOST_atmDsBert_t *atmDsBert_p;
++ DEV_HOST_modemEnvPublic_t *modemEnvPublic_p;
++ DEV_HOST_genericStructure_t *genericStructure1_p;
++ DEV_HOST_genericStructure_t *genericStructure2_p;
++ DEV_HOST_ghsDspTxBufDef_t *ghsDspTxBuf_p;
++ DEV_HOST_ghsDspRxBufDef_t *ghsDspRxBuf_p;
++ DEV_HOST_consBufDef_t *consDispVar_p;
++ DEV_HOST_snrBuffer_t *snrBuffer_p;
++} DEV_HOST_dspOamSharedInterface_t;
++
++
++// ---------------------------------------------------------------------------------
++// Typedef to be used for the pointer to the DEV_HOST_dspOamSharedInterface_s struct
++// of pointers (this is used in dev_host_interface.c).
++// ---------------------------------------------------------------------------------
++typedef DEV_HOST_dspOamSharedInterface_t *DEV_HOST_dspOamSharedInterfacePtr_t;
++
++#endif
+diff -urN linux.old/drivers/atm/sangam_atm/dev_host_verdef.h linux.dev/drivers/atm/sangam_atm/dev_host_verdef.h
+--- linux.old/drivers/atm/sangam_atm/dev_host_verdef.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/dev_host_verdef.h 2005-08-23 04:46:50.091844608 +0200
+@@ -0,0 +1,102 @@
++#ifndef __DEV_HOST_VERDEF_H__
++#define __DEV_HOST_VERDEF_H__ 1
++
++//********************************************************************
++//*
++//* DMT-BASE ADSL MODEM PROGRAM
++//* TEXAS INSTRUMENTS PROPRIETARTY INFORMATION
++//* AMATI CONFIDENTIAL PROPRIETARY
++//*
++//* (c) Copyright April 1999, Texas Instruments Incorporated.
++//* All Rights Reserved.
++//*
++//* Property of Texas Instruments Incorporated and Amati Communications Corp.
++//*
++//* Restricted Rights - Use, duplication, or disclosure is subject to
++//* restrictions set forth in TI's and Amati program license agreement and
++//* associated documentation
++//*
++//*********************************************************************
++//*
++//* FILENAME: dev_host_verdef.h
++//*
++//* ABSTRACT: This file defines the version structure
++//*
++//* TARGET: Non specific.
++//*
++//* TOOLSET: Non specific.
++//*
++//* ACTIVATION:
++//*
++//* HISTORY: DATE AUTHOR DESCRIPTION
++//* 04/29/99 FLW Created
++//* 01/17/00 Barnett Mod's in support of merging NIC
++//* hardware rev 6/7 T1.413 codebases.
++//* 01/21/00 Wagner derfmake mods
++//* 05/11/00 Barnett hardware_rev is a 2 char string.
++//* 07/24/00 Barnett Rework as part of host interface redesign.
++//* 11/29/00 Hunt added chipset_id2
++//* 03/30/01 Barnett Prefixed all public elements with DSPDP_.
++//* This insures uniqueness of names that might
++//* match host names by coincidence.
++//* 03/30/01 Barnett Added DSPDP_Host_VersionDef to facilitate
++//* representing a version id for the host i/f
++//* separate from the firmware version id as
++//* a courtesy to the host.
++//* 07/23/01 JEB Changed name from verdef_u.h to dpsys_verdef.h
++//* 04/12/02 Barnett Make timestamp unsigned 32-bit field.
++//* Generalizes for all kinds of hosts.
++//* 11/15/02 JEB Changed name from dpsys_verdef.h to dev_host_verdef.h
++//* Updated structs according to coding guidelines
++//* 12/16/02 JEB Renamed some struct elements for new usage in Ax7
++//* 01/21/03 MCB Implemented Ax7 UNIT-MODULE modular software framework.
++//* 03/19/03 JEB Added back in "bugFix" elements into each struct type.
++//* Rearranged elements.
++//*
++//********************************************************************
++
++#include "env_def_typedefs.h"
++
++#define DSPDP_FLAVOR_NEWCODES 0xFF // Other values are valid old-style flavors
++
++// ------------------------------
++// ------------------------------
++// Begin DSP version definitions.
++// ------------------------------
++// ------------------------------
++
++typedef struct
++{
++ UINT32 timestamp; // Number of seconds since 01/01/1970
++ UINT8 major; // Major "00".00.00.00 revision nomenclature
++ UINT8 minor; // Minor 00."00".00.00 revision nomenclature
++ UINT8 bugFix; // Bug Fix 00.00."00".00 revision nomenclature
++ UINT8 buildNum; // Build Number 00.00.00."00" revision nomenclature
++ UINT8 netService; // Network service identifier
++ UINT8 chipsetGen; // chipset generation
++ UINT8 chipsetId; // chipset identifier
++ UINT8 chipsetId2; // second byte for "RV" chipset et al.
++ UINT8 hardwareRev1; // hardware revision, 1st char
++ UINT8 hardwareRev2; // hardware revision, 2nd char
++ UINT8 featureCode; // feature code
++ UINT8 dummy1; // dummy byte for explicit 32-bit alignment
++} DEV_HOST_dspVersionDef_t;
++
++// -------------------------------
++// -------------------------------
++// Begin host version definitions.
++// -------------------------------
++// -------------------------------
++
++typedef struct
++{
++ UINT8 major; // Major "00".00.00.00 revision nomenclature
++ UINT8 minor; // Minor 00."00".00.00 revision nomenclature
++ UINT8 bugFix; // Bug Fix 00.00."00".00 revision nomenclature
++ UINT8 buildNum; // Build Number 00.00.00."00" revision nomenclature
++ UINT8 netService; // Network service identifier
++ UINT8 dummy[3]; // dummy bytes for explicit 32-bit alignment
++} DEV_HOST_hostIntfcVersionDef_t;
++
++
++#endif // __DEV_HOST_VERDEF_H__
+diff -urN linux.old/drivers/atm/sangam_atm/dsl_hal_api.c linux.dev/drivers/atm/sangam_atm/dsl_hal_api.c
+--- linux.old/drivers/atm/sangam_atm/dsl_hal_api.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/dsl_hal_api.c 2005-08-23 04:46:50.095844000 +0200
+@@ -0,0 +1,3339 @@
++/*******************************************************************************
++* FILE PURPOSE: DSL Driver API functions for Sangam
++*
++********************************************************************************
++* FILE NAME: dsl_hal_basicapi.c
++*
++* DESCRIPTION:
++* Contains basic DSL HAL APIs for Sangam
++*
++*
++* (C) Copyright 2001-02, Texas Instruments, Inc.
++* History
++* Date Version Notes
++* 06Feb03 0.00.00 RamP Original Version Created
++* 10Mar03 0.00.01 RamP Initial Revision for Modular Code Branch
++* 19Mar03 0.00.02 RamP Fixed DSL and DSP Version API Structures
++* 20Mar03 0.00.03 RamP Changed byteswap function names
++* 21Mar03 0.00.03 RamP/ZT Malloc for DSP f/w done in dslStartup
++* 25Mar03 0.00.04 RamP Removed statistics used only by SWTC
++* Created Checkpoint 3
++* 26Mar03 0.00.05 RamP Added Memory allocation for fwimage in
++* dslStartup function.
++* 07Apr03 0.00.06 RamP Implemented new error reporting scheme
++* Changed Commenting to C style only
++* 09Apr03 0.00.07 RamP Reorganized code to delete POST_SILICON
++* 10Apr03 0.00.08 RamP Removed ptidsl from loadFWImage function
++* moved size and fwimage initialization to
++* dslStartup function
++* 14Apr03 0.00.09 RamP Moved modemStateBitField processing to a
++* support function; deleted stateHistory
++* renamed the REG32 macro
++* 15Apr03 0.00.10 RamP Changed firmware allocate to shim_
++* osAllocateVMemory function
++* 15Apr03 0.00.11 RamP Changed host version number to 07.00.00.01
++* 16Apr03 0.00.12 RamP Modified return condition on dslShutdown
++* 16Apr03 0.00.13 RamP Changed host version number to 07.00.00.02
++* 21Apr03 0.01.00 RamP Cleaned up dslShutdown function
++* Added new function calls to allocate
++* (Alpha) /free overlay pages for different OS
++* Fixed typecasting for allocate/free fxns
++* Added Interrupt Acknowledge logic
++* 22Apr03 0.01.01 RamP Moved acknowledgeInterrupt into api
++* Added static global for intr source
++* 24Apr03 0.01.02 RamP Added processing for OVERLAY_END in
++* DSP message handlers, verified crc32
++* recovery for overlays
++* 28Apr03 0.01.03 RamP Removed global variable intrSource
++* Added parameter to handleInterrupt fxn
++* (Alpha Plus) to indicate interrupt source
++* Changed version number to 01.00.01.00
++* Fixed setTrainingMode function problem
++* 07May03 0.01.04 RamP Removed delineation state check in
++* message handling functions, added more
++* safety for setting lConnected in TC_SYNC
++* Changed version number to 01.00.01.01
++* 14May03 0.01.05 RamP Added 3 Switchable Hybrid APIs
++* Added additional statistics us/ds TxPower,
++* us margin,attenuation, us/ds bitallocation
++* moved versioning to dsl_hal_version.h
++* 14May03 0.01.06 RamP Fixed problem with CMsgs2 parsing
++* 20May03 0.01.07 RamP Added Inner/Outer pair API support. Added
++* dying gasp message.
++* 29May03 0.01.08 ZT/RamP Added memory optimizations for overlay pages
++* and coProfiles; added functions to free,
++* reload overlays and profiles
++* 04Jun03 0.01.09 RamP Added tick counters, fail states reporting
++* Made statistics fixes for higher data rates
++* Added Margin per tone to statistics
++* Added configuration checks for trellis/FEC
++* 06Jun03 0.01.10 RamP Added LED, STM Bert, dGasp LPR Config APIs
++* Modified interrupt acknowledge logic
++* Added current hybrid flag as statistic
++* 09Jun03 0.01.11 RamP Added function to send dying Gasp to Modem
++* fixed problem with reading OamNegoPara var
++* (Beta) fixed problem with reading current config
++* Added function to configure ATM Bert
++* fixed memory leak due to coProfiles
++* Added us/ds R/S FEC statistics
++* Added additional config capability for LED
++* fixed problem in free memory for CO profiles
++* 18Jul03 0.01.12 RamP Fixed problem with reading modemEnv structure
++* affects LED, DGaspLpr APIs
++* Sending Dying Gasp from shutdown function
++* 01Aug03 0.01.13 RamP Added preferred training mode to statistics
++* 13Aug03 0.01.14 MCB Set rev id for D3/R1.1 (ADSL2).
++* 21Aug03 0.01.15 RamP Added g.hs and aoc bitswap message gathering
++* Added new references to bits n gains table
++* Decoupled modem idle/retrain from pair select
++* Added line length and gross gain to statistics
++* 29Sep03 0.01.16 RamP Replaced advcfg function calls with support
++* module function switches
++* 01Oct03 0.01.17 RamP Added enum translation to set training mode
++* & to read statistics
++* 08Oct03 0.01.18 RamP Fixed problems with usTxPower statistic in
++* Annex B target, fixed problem with Trellis
++* 12Oct03 0.01.19 RamP Added API calls to gather ADSL2 Messages
++* 29Oct03 0.01.20 RamP Restored TC_SYNC detect logic
++* 30Oct03 0.01.21 RamP Removed Scaling factor for adsl2DSConRate
++* Setting Showtime state upon DSP_ACTIVE
++* 14Nov03 0.01.22 RamP Fixed scaling for usTxPower & dsTxPower
++* 14Nov03 0.01.23 RamP Added logic to gather CRates1/RRates1
++* by parsing DSP_CRATES1
++* 20Nov03 0.01.24 RamP Added generic & interface Read
++* and Write functions to read from
++* DSP - Host Interface
++* 24Nov03 0.01.25 RamP Modified interface Read/Write functions
++* to seperate element offsets from pointers
++* 19Dec03 0.01.26 RamP Modified pointer accessing problems with
++* block read functions
++* 26Dec03 0.01.27 RamP Made ghsIndex a local variable & added
++* check to avoid buffer overflow
++* 30Dec03 0.01.28 RamP Added generic mailbox command function
++*******************************************************************************/
++#include "dsl_hal_register.h"
++#include "dsl_hal_support.h"
++#include "dsl_hal_logtable.h"
++#include "dsl_hal_version.h"
++
++static unsigned int hybrid_selected;
++static unsigned int showtimeFlag = FALSE;
++
++#ifdef PRE_SILICON
++/*********************************************/
++/* Base Addresses */
++/*********************************************/
++#define DEV_MDMA_BASE 0x02000500
++
++/*********************************************/
++/* MC DMA Control Registers in DSL */
++/*********************************************/
++
++#define DEV_MDMA0_SRC_ADDR (DEV_MDMA_BASE + 0x00000000)
++#define DEV_MDMA0_DST_ADDR (DEV_MDMA_BASE + 0x00000004)
++#define DEV_MDMA0_CTL_ADDR (DEV_MDMA_BASE + 0x00000008)
++#define DEV_MDMA1_SRC_ADDR (DEV_MDMA_BASE + 0x00000040)
++#define DEV_MDMA1_DST_ADDR (DEV_MDMA_BASE + 0x00000044)
++#define DEV_MDMA1_CTL_ADDR (DEV_MDMA_BASE + 0x00000048)
++#define DEV_MDMA2_SRC_ADDR (DEV_MDMA_BASE + 0x00000080)
++#define DEV_MDMA2_DST_ADDR (DEV_MDMA_BASE + 0x00000084)
++#define DEV_MDMA2_CTL_ADDR (DEV_MDMA_BASE + 0x00000088)
++#define DEV_MDMA3_SRC_ADDR (DEV_MDMA_BASE + 0x000000C0)
++#define DEV_MDMA3_DST_ADDR (DEV_MDMA_BASE + 0x000000C4)
++#define DEV_MDMA3_CTL_ADDR (DEV_MDMA_BASE + 0x000000C8)
++
++#define DEV_MDMA0_SRC (*((volatile UINT32 *) DEV_MDMA0_SRC_ADDR))
++#define DEV_MDMA0_DST (*((volatile UINT32 *) DEV_MDMA0_DST_ADDR))
++#define DEV_MDMA0_CTL (*((volatile UINT32 *) DEV_MDMA0_CTL_ADDR))
++#define DEV_MDMA1_SRC (*((volatile UINT32 *) DEV_MDMA1_SRC_ADDR))
++#define DEV_MDMA1_DST (*((volatile UINT32 *) DEV_MDMA1_DST_ADDR))
++#define DEV_MDMA1_CTL (*((volatile UINT32 *) DEV_MDMA1_CTL_ADDR))
++#define DEV_MDMA2_SRC (*((volatile UINT32 *) DEV_MDMA2_SRC_ADDR))
++#define DEV_MDMA2_DST (*((volatile UINT32 *) DEV_MDMA2_DST_ADDR))
++#define DEV_MDMA2_CTL (*((volatile UINT32 *) DEV_MDMA2_CTL_ADDR))
++#define DEV_MDMA3_SRC (*((volatile UINT32 *) DEV_MDMA3_SRC_ADDR))
++#define DEV_MDMA3_DST (*((volatile UINT32 *) DEV_MDMA3_DST_ADDR))
++#define DEV_MDMA3_CTL (*((volatile UINT32 *) DEV_MDMA3_CTL_ADDR))
++
++/* MDMA control bits */
++
++#define DEV_MDMA_START 0x80000000
++#define DEV_MDMA_STOP 0x00000000
++#define DEV_MDMA_STATUS 0x40000000
++#define DEV_MDMA_DST_INC 0x00000000
++#define DEV_MDMA_DST_FIX 0x02000000
++#define DEV_MDMA_SRC_INC 0x00000000
++#define DEV_MDMA_SRC_FIX 0x00800000
++#define DEV_MDMA_BURST1 0x00000000
++#define DEV_MDMA_BURST2 0x00100000
++#define DEV_MDMA_BURST4 0x00200000
++
++#define DEV_MDMA_LEN_SHF 2
++#define DEV_MDMA_LEN_MASK 0x0000FFFF
++
++#define DMA0 0
++#define DMA1 1
++#define DMA2 2
++#define DMA3 3
++#endif
++#ifdef DMA
++SINT32 getDmaStatus(UINT32 mask)
++{
++ if(!(IFR & mask))
++ {
++ return DSLHAL_ERROR_NO_ERRORS;
++ }
++ else
++ {
++ ICR = mask ;
++ return 1 ;
++ }
++}
++
++void programMdma(UINT32 dma, UINT32 source, UINT32 destination, UINT32 length, UINT32 wait)
++{
++ volatile UINT32 statusMask ;
++
++ switch(dma)
++ {
++ case DMA0:
++ {
++ DEV_MDMA0_SRC = source ;
++ DEV_MDMA0_DST = destination ;
++ DEV_MDMA0_CTL = (DEV_MDMA_START | DEV_MDMA_DST_INC | DEV_MDMA_SRC_INC |
++ DEV_MDMA_BURST1 | (length << DEV_MDMA_LEN_SHF)) ;
++ statusMask = 0x00000010 ;
++ }
++ break ;
++ case DMA1:
++ {
++ DEV_MDMA1_SRC = source ;
++ DEV_MDMA1_DST = destination ;
++ DEV_MDMA1_CTL = (DEV_MDMA_START | DEV_MDMA_DST_INC | DEV_MDMA_SRC_INC |
++ DEV_MDMA_BURST1 | (length << DEV_MDMA_LEN_SHF)) ;
++ statusMask = 0x00000020 ;
++ }
++ break ;
++ case DMA2:
++ {
++ DEV_MDMA2_SRC = source ;
++ DEV_MDMA2_DST = destination ;
++ DEV_MDMA2_CTL = (DEV_MDMA_START | DEV_MDMA_DST_INC | DEV_MDMA_SRC_INC |
++ DEV_MDMA_BURST1 | (length << DEV_MDMA_LEN_SHF)) ;
++ statusMask = 0x00000040 ;
++ }
++ break ;
++ case DMA3:
++ {
++ DEV_MDMA3_SRC = source ;
++ DEV_MDMA3_DST = destination ;
++ DEV_MDMA3_CTL = (DEV_MDMA_START | DEV_MDMA_DST_INC | DEV_MDMA_SRC_INC |
++ DEV_MDMA_BURST1 | (length << DEV_MDMA_LEN_SHF)) ;
++ statusMask = 0x00000080 ;
++ }
++ break ;
++
++ }
++
++ if(wait)
++ {
++ while(!(getDmaStatus(statusMask))) ;
++ }
++
++}
++#endif
++
++
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_api_dslStartup
++*
++*******************************************************************************************
++* DESCRIPTION: Entry point to initialize and load ax5 daughter board
++*
++* INPUT: PITIDSLHW_T *ppIHw
++*
++* RETURN: 0 --succeeded
++* 1 --Failed
++*
++*****************************************************************************************/
++
++int dslhal_api_dslStartup(PITIDSLHW_T *ppIHw)
++{
++
++ ITIDSLHW_T *ptidsl;
++ int i;
++ int rc;
++ dprintf(4,"dslhal_api_dslStartup() NEW 1\n");
++
++ ptidsl=(ITIDSLHW_T *)shim_osAllocateMemory(sizeof(ITIDSLHW_T));
++ if(ptidsl==NULL)
++ {
++ dprintf(1, "unable to allocate memory for ptidsl\n");
++ return 1;
++ }
++ *ppIHw=ptidsl;
++ shim_osZeroMemory((char *) ptidsl, sizeof(ITIDSLHW_T));
++
++ /* Unreset the ADSL Subsystem */
++ rc=dslhal_support_unresetDslSubsystem();
++ if(rc)
++ {
++ dprintf(1, "unable to reset ADSL Subsystem \n");
++ shim_osFreeMemory((void *) ptidsl, sizeof(ITIDSLHW_T));
++ return DSLHAL_ERROR_UNRESET_ADSLSS;
++ }
++ ptidsl->fwimage = shim_osAllocateVMemory(DSP_FIRMWARE_MALLOC_SIZE);
++ if(!ptidsl->fwimage)
++ {
++ dprintf(1,"Failed to Allocate Memory for DSP firmware binary \n");
++ return DSLHAL_ERROR_FIRMWARE_MALLOC;
++ }
++ /* read firmware file from flash */
++ rc=shim_osLoadFWImage(ptidsl->fwimage);
++ if(rc<0)
++ {
++ dprintf(1, "unable to get fw image\n");
++ shim_osFreeVMemory((void *)ptidsl->fwimage,DSP_FIRMWARE_MALLOC_SIZE);
++ shim_osFreeMemory((void *) ptidsl, sizeof(ITIDSLHW_T));
++ return DSLHAL_ERROR_NO_FIRMWARE_IMAGE;
++ }
++ else
++ {
++ ptidsl->imagesize = rc;
++ }
++ /* Compute the CRC checksum on the image and validate the image */
++
++ /* Validate the image in the RAM */
++
++ /* load fw to DSP */
++
++ if(dslhal_support_hostDspCodeDownload(ptidsl))
++ {
++ dprintf(0,"dsp load error\n");
++ for(i=0; i<NUM_PAGES; i++)
++ {
++ if(ptidsl->olayDpPage[i].PmemStartWtAddr !=NULL)
++ {
++ shim_osFreeDmaMemory((void *) ptidsl->olayDpPage[i].PmemStartWtAddr,
++ ptidsl->olayDpPage[i].OverlayXferCount);
++ }
++ }
++ if(ptidsl->coProfiles.PmemStartWtAddr != NULL)
++ shim_osFreeDmaMemory((void *)ptidsl->coProfiles.PmemStartWtAddr, ptidsl->coProfiles.OverlayXferCount);
++ if(ptidsl->constDisplay.PmemStartWtAddr != NULL)
++ shim_osFreeDmaMemory((void *)ptidsl->constDisplay.PmemStartWtAddr, ptidsl->constDisplay.OverlayXferCount);
++ shim_osFreeVMemory((void *)ptidsl->fwimage,DSP_FIRMWARE_MALLOC_SIZE);
++ shim_osFreeMemory((void *) ptidsl, sizeof(ITIDSLHW_T));
++ return DSLHAL_ERROR_CODE_DOWNLOAD;
++ }
++
++ /* set flag to indicated overlay pages are loaded */
++ ptidsl->bOverlayPageLoaded = 1;
++ /* set auto retrain to 1 to disble the overlay page reload */
++ ptidsl->bAutoRetrain = 1;
++
++ /* unreset Raptor */
++ /* change this to new function */
++ /* This function should basically bring DSP out of reset bit 23 of PRCR */
++ /* Function is ready but bypassed for Pre-Silicon */
++
++ rc=dslhal_support_unresetDsp();
++ if (rc)
++ {
++ dprintf(0,"unable to bring DSP out of Reset\n");
++ for(i=0; i<NUM_PAGES; i++)
++ {
++ if(ptidsl->olayDpPage[i].PmemStartWtAddr !=NULL)
++ {
++ shim_osFreeDmaMemory((void *) ptidsl->olayDpPage[i].PmemStartWtAddr,
++ ptidsl->olayDpPage[i].OverlayXferCount);
++ }
++ }
++ if(ptidsl->coProfiles.PmemStartWtAddr != NULL)
++ shim_osFreeDmaMemory((void *)ptidsl->coProfiles.PmemStartWtAddr, ptidsl->coProfiles.OverlayXferCount);
++ if(ptidsl->constDisplay.PmemStartWtAddr != NULL)
++ shim_osFreeDmaMemory((void *)ptidsl->constDisplay.PmemStartWtAddr, ptidsl->constDisplay.OverlayXferCount);
++ shim_osFreeVMemory((void *)ptidsl->fwimage,DSP_FIRMWARE_MALLOC_SIZE);
++ shim_osFreeMemory((void *) ptidsl, sizeof(ITIDSLHW_T));
++ return DSLHAL_ERROR_UNRESET_DSP;
++ }
++ shim_osFreeVMemory((void *)ptidsl->fwimage,DSP_FIRMWARE_MALLOC_SIZE);
++ dprintf(4,"dslhal_api_dslStartup() done\n");
++
++ /* Add the code to initialize the host interface variables */
++ /* Add code to tickle the host interface */
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_dslShutdown
++ *
++ *******************************************************************************************
++ * DESCRIPTION: routine to shutdown ax5 modem and free the resource
++ *
++ * INPUT: tidsl_t *ptidsl
++ *
++ * RETURN: NULL
++ *
++ *
++ *****************************************************************************************/
++
++int dslhal_api_dslShutdown(tidsl_t *ptidsl)
++{
++ int rc= DSLHAL_ERROR_NO_ERRORS;
++ int i;
++
++ dprintf(5, "dslhal_api_dslShutdown\n");
++ rc = dslhal_support_writeHostMailbox(ptidsl, HOST_DSLSS_SHUTDOWN, 0, 0, 0);
++ if(rc)
++ {
++ dprintf(1, " unable to reset DSP \n");
++ rc = DSLHAL_ERROR_RESET_DSP;
++ }
++ /* DSP need 50 ms to send out the message*/
++
++ shim_osClockWait(60 * 1000);
++
++ rc = dslhal_support_writeHostMailbox(ptidsl, HOST_DGASP, 0, 0, 0);
++
++ /* free memory allocated*/
++
++ for(i=0; i<NUM_PAGES; i++)
++ {
++ if(ptidsl->olayDpPage[i].PmemStartWtAddr !=NULL)
++ {
++ shim_osFreeDmaMemory((void *) ptidsl->olayDpPage[i].PmemStartWtAddr,
++ ptidsl->olayDpPage[i].OverlayXferCount);
++ }
++ }
++ if(ptidsl->coProfiles.PmemStartWtAddr != NULL)
++ shim_osFreeDmaMemory((void *)ptidsl->coProfiles.PmemStartWtAddr, ptidsl->coProfiles.OverlayXferCount);
++ if(ptidsl->constDisplay.PmemStartWtAddr != NULL)
++ shim_osFreeDmaMemory((void *)ptidsl->constDisplay.PmemStartWtAddr, ptidsl->constDisplay.OverlayXferCount);
++ shim_osFreeMemory((void *)ptidsl, sizeof(tidsl_t));
++ rc = dslhal_support_resetDsp();
++ if(rc)
++ {
++ dprintf(1, " unable to reset ADSL subsystem \n");
++ rc = DSLHAL_ERROR_RESET_DSP;
++ }
++ rc = dslhal_support_resetDslSubsystem();
++ if(rc)
++ {
++ dprintf(1, " unable to reset ADSL subsystem \n");
++ rc = DSLHAL_ERROR_RESET_ADSLSS;
++ }
++return rc;
++}
++
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_api_getDslHalVersion
++*
++*******************************************************************************************
++* DESCRIPTION: This routine supply DSL Driver version.
++*
++* INPUT: tidsl_t * ptidsl
++* void *pVer, DSP Driver Version Pointer
++*
++* RETURN: 0 --succeeded
++* 1 --Failed
++* Note: See verdef_u.h for version structure definition.
++*****************************************************************************************/
++
++void dslhal_api_getDslHalVersion(void *pVer)
++{
++ dslVer *pVersion;
++ pVersion = (dslVer *)pVer;
++ pVersion->major = (unsigned char) DSLHAL_VERSION_MAJOR;
++ pVersion->minor = (unsigned char) DSLHAL_VERSION_MINOR;
++ pVersion->bugfix = (unsigned char) DSLHAL_VERSION_BUGFIX;
++ pVersion->buildNum = (unsigned char) DSLHAL_VERSION_BUILDNUM;
++ pVersion->timeStamp = (unsigned char) DSLHAL_VERSION_TIMESTAMP;
++}
++
++/********************************************************************************************
++ * FUNCTION NAME: dslhal_api_pollTrainingStatus()
++ *
++ *********************************************************************************************
++ * DESCRIPTION: code to decode modem status and to start modem training
++ * Input: tidsl_t *ptidsl
++ *
++ * Return: modem status
++ * -1 failed
++ *
++ ********************************************************************************************/
++
++int dslhal_api_pollTrainingStatus(tidsl_t *ptidsl)
++{
++ int cmd;
++ int tag;
++ int parm1,parm2;
++ int rc;
++ unsigned int failState;
++ static unsigned int pollGhsIndex=0;
++
++ /*char *tmp;*/
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++#if SWTC
++ DEV_HOST_tcHostCommDef_t TCHostCommDef;
++#endif
++
++ dprintf(5,"dslhal_api_pollTrainingStatus\n");
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterface_t *) ptidsl->pmainAddr;
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,
++ sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++#if SWTC
++ dspOamSharedInterface.tcHostComm_p =(DEV_HOST_tcHostCommDef_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.tcHostComm_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.tcHostComm_p,
++ &TCHostCommDef, sizeof(DEV_HOST_tcHostCommDef_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++#endif
++
++ rc = dslhal_support_processTrainingState(ptidsl);
++ if(rc)
++ {
++ dprintf(0,"Error Reading Modem Training State \n");
++ return DSLHAL_ERROR_MODEMSTATE;
++ }
++ rc = dslhal_support_processModemStateBitField(ptidsl);
++ if(rc)
++ {
++ dprintf(0,"Error Reading Modem Training State \n");
++ return DSLHAL_ERROR_MODEMSTATE;
++ }
++ /*
++ rc = dslhal_support_readDelineationState(ptidsl);
++ if(rc)
++ {
++ dprintf(0,"Error Reading Delineation State \n");
++ return DSLHAL_ERROR_MODEMSTATE;
++ }
++ */
++ while (dslhal_support_readDspMailbox(ptidsl,&cmd, &tag, &parm1, &parm2) == DSLHAL_ERROR_NO_ERRORS )
++ {
++ dprintf(4,"mailbox message: 0x%x\n", cmd);
++ /*
++ for(rc=0;rc<8;rc++)
++ {
++ dslhal_support_readTextMailbox(ptidsl,&msg1, &msg2);
++ }
++ */
++
++ if (cmd == DSP_IDLE)
++ {
++ dprintf(4,"DSP_IDLE\n");
++ ptidsl->lConnected=0;
++ hybrid_selected=888;
++ /* add code for reload overlay pages */
++ if(ptidsl->bAutoRetrain == 0)
++ {
++ while(ptidsl->bOverlayPageLoaded == 0)
++ {
++ shim_osClockWait(6400);
++ }
++ //dslhal_support_restoreTrainingInfo(ptidsl);
++ //ptidsl->bOverlayPageLoaded = 1;
++ }
++ /* command DSP to ACTREQ */
++ if(showtimeFlag == TRUE)
++ {
++ dslhal_api_resetTrainFailureLog(ptidsl);
++ dslhal_support_advancedIdleProcessing(ptidsl);
++ showtimeFlag = FALSE;
++ }
++ failState = (unsigned int)parm1;
++ if(failState!=0)
++ {
++ ptidsl->AppData.trainFailStates[ptidsl->AppData.trainFails]=failState;
++ ptidsl->AppData.trainFails++;
++ if(ptidsl->AppData.trainFails > 30)
++ ptidsl->AppData.trainFails=0;
++ }
++ for(pollGhsIndex=0;pollGhsIndex<10;pollGhsIndex++)
++ {
++ for(rc=0;rc<62;rc++)
++ ptidsl->AppData.dsl_ghsRxBuf[pollGhsIndex][rc]=0;
++ }
++ pollGhsIndex=0;
++ rc = dslhal_support_writeHostMailbox(ptidsl,HOST_ACTREQ, 0, 0, 0);
++ if (rc)
++ return DSLHAL_ERROR_MAILBOX_WRITE;
++ }
++
++ if(cmd == DSP_ATM_TC_SYNC)
++ {
++ dprintf(4,"\nTC_SYNC\n");
++ showtimeFlag = TRUE;
++ ptidsl->lConnected=1;
++ if(ptidsl->bAutoRetrain == 0 && ptidsl->bOverlayPageLoaded == 1)
++ {
++ dslhal_support_clearTrainingInfo(ptidsl);
++ ptidsl->bOverlayPageLoaded = 0;
++ }
++ }
++ if(cmd == DSP_ACTIVE)
++ {
++ dprintf(4,"DSP_ACTIVE");
++ ptidsl->lConnected=0;
++ ptidsl->AppData.bState = RSTATE_SHOWTIME;
++ dprintf(4,"US Connect Rate: %u \n",ptidsl->AppData.USConRate);
++ dprintf(4,"DS Connect Rate: %u \n",ptidsl->AppData.DSConRate);
++ }
++ if(cmd == DSP_ATM_NO_TC_SYNC)
++ {
++ dprintf(4,"\nTC_NOSYNC\n");
++ ptidsl->lConnected=0;
++ }
++ if(cmd == DSP_DGASP)
++ {
++ dprintf(0,"\n GASP!!! \n");
++ }
++ if(cmd == DSP_OVERLAY_END)
++ {
++ dprintf(4,"Overlay Page Done %d \n",tag);
++ rc = dslhal_support_checkOverlayPage(ptidsl,tag);
++ if(rc == DSLHAL_ERROR_OVERLAY_CORRUPTED)
++ {
++ dprintf(0,"Overlay Page: %d CORRUPTED \n",tag);
++ return (0-DSLHAL_ERROR_OVERLAY_CORRUPTED);
++ }
++ }
++ if(cmd == DSP_HYBRID)
++ {
++ dprintf(2,"Hybrid Metrics Available: %d\n",tag);
++ hybrid_selected = tag;
++ }
++ if(cmd == DSP_DGASP)
++ {
++ dprintf(0,"\n GASP!!! \n");
++ }
++ if(cmd == DSP_XMITBITSWAP)
++ {
++ dslhal_support_aocBitSwapProcessing(ptidsl,0);
++ }
++ if(cmd == DSP_RCVBITSWAP)
++ {
++ dslhal_support_aocBitSwapProcessing(ptidsl,1);
++ }
++ if(cmd == DSP_GHSMSG)
++ {
++ dprintf(3,"Ghs Message Received, bytes: %d \n",tag);
++ dprintf(3,"Addr: 0x%x\n",dspOamSharedInterface.ghsDspRxBuf_p);
++ if(pollGhsIndex > 9)
++ pollGhsIndex=0;
++ rc = dslhal_support_blockRead((void *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.ghsDspRxBuf_p), &ptidsl->AppData.dsl_ghsRxBuf[pollGhsIndex++][0], tag);
++ }
++ if(cmd == DSP_CRATES1)
++ {
++ dprintf(3,"DSP C-Rates1 Data Ready \n");
++ rc = dslhal_support_gatherRateMessages(ptidsl);
++ }
++ if(cmd == DSP_SNR)
++ {
++ dprintf(3,"DSP SNR Data Ready \n");
++ rc = dslhal_support_gatherSnrPerBin(ptidsl,tag);
++ }
++ if(cmd == DSP_EOC)
++ {
++ dprintf(3,"DSP_EOC message \n");
++ rc = dslhal_support_gatherEocMessages(ptidsl,tag,parm1,parm2);
++ }
++
++ if(cmd == DSP_TRAINING_MSGS)
++ {
++ dprintf(3,"DSP_TRAINING_MSGS \n");
++ rc = dslhal_support_gatherAdsl2Messages(ptidsl,tag,parm1,parm2);
++ }
++ }
++ dprintf(6,"dslhal_api_pollTrainingStatus done\n");
++ return(ptidsl->AppData.bState);
++
++} /* end of dslhal_api_pollTrainingStatus() */
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_handleTrainingInterrupt()
++*
++*********************************************************************************************
++* DESCRIPTION: Code to handle ax5 hardware interrupts
++*
++* Input: tidsl_t *ptidsl
++* int *pMsg, pointer to returned hardware messages. Each byte represent a messge
++* int *pTag, pointer to returned hardware message tags. Each byte represent a tag.
++* Return: 0 success
++* 1 failed
++*
++********************************************************************************************/
++int dslhal_api_handleTrainingInterrupt(tidsl_t *ptidsl, int intrSource)
++{
++ int cmd;
++ int tag;
++ int parm1,parm2;
++ unsigned int msg1;
++ unsigned int msg2;
++ int rc;
++ unsigned int failState;
++ static unsigned int interruptGhsIndex=0;
++ /*char *tmp;*/
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++#if SWTC
++ DEV_HOST_tcHostCommDef_t TCHostCommDef;
++#endif
++ dprintf(6,"dslhal_api_handleTrainingInterrupt\n");
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterface_t *) ptidsl->pmainAddr;
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,
++ sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++#if SWTC
++ dspOamSharedInterface.tcHostComm_p =(DEV_HOST_tcHostCommDef_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.tcHostComm_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.tcHostComm_p,
++ &TCHostCommDef, sizeof(DEV_HOST_tcHostCommDef_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++#endif
++
++ if(intrSource & MASK_BITFIELD_INTERRUPTS)
++ {
++ dspOamSharedInterface.modemStateBitField_p =(DEV_HOST_modemStateBitField_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.modemStateBitField_p);
++ rc = dslhal_support_processTrainingState(ptidsl);
++ if(rc)
++ {
++ dprintf(0,"Error Reading Modem Training State \n");
++ return DSLHAL_ERROR_MODEMSTATE;
++ }
++ rc = dslhal_support_processModemStateBitField(ptidsl);
++ if(rc)
++ {
++ dprintf(0,"Error Reading Modem Training State \n");
++ return DSLHAL_ERROR_MODEMSTATE;
++ }
++ }
++ if(intrSource & MASK_MAILBOX_INTERRUPTS)
++ {
++ /*
++ rc = dslhal_support_readDelineationState(ptidsl);
++ if(rc)
++ {
++ dprintf(0,"Error Reading Delineation State \n");
++ return DSLHAL_ERROR_MODEMSTATE;
++ }
++ */
++ while (dslhal_support_readDspMailbox(ptidsl,&cmd, &tag, &parm1, &parm2) == DSLHAL_ERROR_NO_ERRORS )
++ {
++ dprintf(4,"mailbox message: 0x%x\n", cmd);
++ /*
++ for(rc=0;rc<8;rc++)
++ {
++ dslhal_support_readTextMailbox(ptidsl,&msg1, &msg2);
++ }
++ */
++ if (cmd == DSP_IDLE)
++ {
++ dprintf(4,"DSP_IDLE\n");
++ ptidsl->lConnected=0;
++ hybrid_selected=888;
++ if(showtimeFlag == TRUE)
++ {
++ dslhal_api_resetTrainFailureLog(ptidsl);
++ dslhal_support_advancedIdleProcessing(ptidsl);
++ showtimeFlag = FALSE;
++ }
++ failState = (unsigned int)parm1;
++ if(failState!=0)
++ {
++ ptidsl->AppData.trainFailStates[ptidsl->AppData.trainFails]=failState;
++ ptidsl->AppData.trainFails++;
++ if(ptidsl->AppData.trainFails > 30)
++ ptidsl->AppData.trainFails=0;
++ }
++ for(interruptGhsIndex=0;interruptGhsIndex<10;interruptGhsIndex++)
++ {
++ for(rc=0;rc<62;rc++)
++ ptidsl->AppData.dsl_ghsRxBuf[interruptGhsIndex][rc]=0;
++ }
++ interruptGhsIndex=0;
++
++ /* add code for reload overlay pages */
++ if(ptidsl->bAutoRetrain == 0 && ptidsl->bOverlayPageLoaded == 0)
++ {
++ dslhal_support_restoreTrainingInfo(ptidsl);
++ ptidsl->bOverlayPageLoaded = 1;
++ }
++ /* command DSP to ACTREQ */
++ rc = dslhal_support_writeHostMailbox(ptidsl, HOST_ACTREQ, 0, 0, 0);
++ if (rc)
++ return DSLHAL_ERROR_MAILBOX_WRITE;
++ }
++ if(cmd == DSP_ATM_TC_SYNC)
++ {
++ dprintf(4,"\nTC_SYNC\n");
++ showtimeFlag = TRUE;
++ ptidsl->lConnected=1;
++ if(ptidsl->bAutoRetrain == 0 && ptidsl->bOverlayPageLoaded == 1)
++ {
++ dslhal_support_clearTrainingInfo(ptidsl);
++ ptidsl->bOverlayPageLoaded = 0;
++ }
++ }
++ if(cmd == DSP_ACTIVE)
++ {
++ ptidsl->lConnected=0;
++ ptidsl->AppData.bState = RSTATE_SHOWTIME;
++ dprintf(4,"DSP_ACTIVE");
++ dprintf(4,"US Connect Rate: %u \n",ptidsl->AppData.USConRate);
++ dprintf(4,"DS Connect Rate: %u \n",ptidsl->AppData.DSConRate);
++ }
++ if(cmd == DSP_ATM_NO_TC_SYNC)
++ {
++ dprintf(4,"\nTC_NOSYNC\n");
++ ptidsl->lConnected=0;
++ /* add code for reload overlay pages */
++ }
++ if(cmd == DSP_OVERLAY_END)
++ {
++ dprintf(4,"Overlay Page Done %d \n",tag);
++ rc = dslhal_support_checkOverlayPage(ptidsl,tag);
++ if(rc == DSLHAL_ERROR_OVERLAY_CORRUPTED)
++ {
++ dprintf(4,"Overlay Page: %d CORRUPTED \n",tag);
++ return(0-DSLHAL_ERROR_OVERLAY_CORRUPTED);
++ }
++ }
++ if(cmd == DSP_HYBRID)
++ {
++ dprintf(2,"Hybrid Metrics Available\n");
++ hybrid_selected = tag;
++ }
++ if(cmd == DSP_XMITBITSWAP)
++ {
++ rc = dslhal_support_aocBitSwapProcessing(ptidsl,0);
++ }
++ if(cmd == DSP_RCVBITSWAP)
++ {
++ rc = dslhal_support_aocBitSwapProcessing(ptidsl,1);
++ }
++ if(cmd == DSP_GHSMSG)
++ {
++ dprintf(3,"Ghs Message Received, bytes: %d \n",tag);
++ dprintf(3,"Addr: 0x%x\n",dspOamSharedInterface.ghsDspRxBuf_p);
++ if(interruptGhsIndex > 9)
++ interruptGhsIndex=0;
++ rc = dslhal_support_blockRead((void *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.ghsDspRxBuf_p), &ptidsl->AppData.dsl_ghsRxBuf[interruptGhsIndex++][0], tag);
++ }
++ if(cmd == DSP_CRATES1)
++ {
++ dprintf(3,"DSP C-Rates1 Data Ready \n");
++ rc = dslhal_support_gatherRateMessages(ptidsl);
++ }
++ if(cmd == DSP_SNR)
++ {
++ dprintf(3,"DSP SNR Data Ready \n");
++ rc = dslhal_support_gatherSnrPerBin(ptidsl,tag);
++ }
++ if(cmd == DSP_EOC)
++ {
++ dprintf(3,"DSP_EOC message \n");
++ rc = dslhal_support_gatherEocMessages(ptidsl,tag,parm1,parm2);
++ }
++ if(cmd == DSP_TRAINING_MSGS)
++ {
++ dprintf(3,"DSP_TRAINING_MSGS \n");
++ rc = dslhal_support_gatherAdsl2Messages(ptidsl,tag,parm1,parm2);
++ }
++ }
++
++ dslhal_support_readTextMailbox(ptidsl,&msg1, &msg2);
++ dprintf(5,"Text Message Part1: 0x%x \t Text Message Part2: 0x%x \n",msg1,msg2);
++ }
++ dprintf(6,"dslhal_api_handleTrainingInterrupt done\n");
++ return(ptidsl->AppData.bState);
++} /* end of dslhal_api_handleTrainingInterrupt() */
++
++
++
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_dslRetrain(tidsl_t *ptidsl)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction sends CMD_ACTREQ to the DSP to issue a retrain
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_dslRetrain(tidsl_t *ptidsl)
++{
++ int rc;
++
++ dprintf(5, "dslhal_cfg_dslRetrain \n");
++ rc = dslhal_support_writeHostMailbox(ptidsl, HOST_QUIET, 0, 0, 0);
++ if(rc)
++ {
++ dprintf(1,"dslhal_cfg_dslRetrain failed\n");
++ return DSLHAL_ERROR_CTRL_API_FAILURE;
++ }
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_sendQuiet(tidsl_t *ptidsl)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction sends the CMD_QUIET message to the DSP
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_sendQuiet(tidsl_t *ptidsl)
++{
++ int rc;
++
++ dprintf(5, "dslhal_api_sendQuiet\n");
++ rc = dslhal_support_writeHostMailbox(ptidsl, HOST_QUIET, 0, 0, 0);
++ if(rc)
++ {
++ dprintf(1,"dslhal_api_sendQuiet failed\n");
++ return DSLHAL_ERROR_CTRL_API_FAILURE;
++ }
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_sendIdle(tidsl_t *ptidsl)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction sends the CMD_IDLE message to the DSP
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_sendIdle(tidsl_t *ptidsl)
++{
++ int rc;
++
++ dprintf(5, "dslhal_api_sendIdle\n");
++ rc = dslhal_support_writeHostMailbox(ptidsl, HOST_IDLE, 0, 0, 0);
++ if(rc)
++ {
++ dprintf(1,"dslhal_api_sendIdle failed\n");
++ return DSLHAL_ERROR_CTRL_API_FAILURE;
++ }
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_sendDgasp(tidsl_t *ptidsl)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction sends the HOST_DGASP message to the DSP
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_sendDgasp(tidsl_t *ptidsl)
++{
++ int rc;
++
++ dprintf(5, "dslhal_api_sendDgasp\n");
++ rc = dslhal_support_writeHostMailbox(ptidsl, HOST_DGASP, 0, 0, 0);
++ if(rc)
++ {
++ dprintf(1,"dslhal_api_sendDgasp failed\n");
++ return DSLHAL_ERROR_CTRL_API_FAILURE;
++ }
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_api_setTrainingMode(tidsl_t *ptidsl,unsigned int trainmode)
++*
++*******************************************************************************************
++* DESCRIPTION: This fuction Sets the Desired Training Mode {None/Multimode/G.dmt/lite
++*
++* INPUT: PITIDSLHW_T *ptidsl
++* unsigned int trainmode :Should be between 0 and 4; 0:No Mode 1:Multimode
++* 2: T1.413, 3:G.dmt, 4: G.lite
++* RETURN: 0 SUCCESS
++* 1 FAILED
++*
++*****************************************************************************************/
++unsigned int dslhal_api_setTrainingMode(tidsl_t *ptidsl,unsigned int trainmode)
++{
++ DEV_HOST_oamWrNegoParaDef_t NegoPara;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ int rc;
++ dprintf(5," dslhal_api_setTrainingMode()\n");
++ if(trainmode>255)
++ {
++ dprintf(3,"Invalid Value for Desired Training Mode (must be <255)\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,
++ sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.oamWriteNegoParams_p = (DEV_HOST_oamWrNegoParaDef_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.oamWriteNegoParams_p);
++
++ rc = dslhal_support_blockRead((PVOID) dspOamSharedInterface.oamWriteNegoParams_p,&NegoPara, sizeof(DEV_HOST_oamWrNegoParaDef_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ /* Enum Translation to maintain backwards compatibility for train modes */
++ if(trainmode == DSLTRAIN_MULTI_MODE)
++ trainmode = MULTI_MODE;
++ if(trainmode == DSLTRAIN_T1413_MODE)
++ trainmode = T1413_MODE;
++ if(trainmode == DSLTRAIN_GDMT_MODE)
++ trainmode = GDMT_MODE;
++
++ NegoPara.stdMode = trainmode;
++ dprintf(5,"Train Mode: 0x%x\n",trainmode);
++ rc = dslhal_support_blockWrite(&NegoPara,(PVOID)dspOamSharedInterface.oamWriteNegoParams_p, sizeof(DEV_HOST_oamWrNegoParaDef_t));
++ if(rc)
++ return DSLHAL_ERROR_CONFIG_API_FAILURE;
++
++ dprintf(5," dslhal_api_setTrainingMode() Done\n");
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_api_getDspVersion
++*
++*******************************************************************************************
++* DESCRIPTION: This routine supply AX5 daugther card DSP version.
++*
++* INPUT: tidsl_t * ptidsl
++* void *pVer, DSP version struct is returned starting at this pointer
++*
++* RETURN: 0 --succeeded
++* 1 --Failed
++* Note: See verdef_u.h for version structure definition.
++*****************************************************************************************/
++int dslhal_api_getDspVersion(tidsl_t *ptidsl, void *pVer)
++{
++ /* DEV_HOST_dspVersionDef_t dspVersion; */
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ int rc;
++ dprintf(5, "dslhal_api_getDspVersion\n");
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++ if(!pVer)
++ return DSLHAL_ERROR_INVALID_PARAM;
++
++ *(unsigned int *) pVer = 0;
++
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.datapumpVersion_p = (DEV_HOST_dspVersionDef_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.datapumpVersion_p);
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.datapumpVersion_p,
++ pVer, sizeof(dspVer));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ pVer = (DEV_HOST_dspVersionDef_t *)(dslhal_support_byteSwap32((unsigned int)pVer));
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_gatherStatistics()
++*
++*********************************************************************************************
++* DESCRIPTION: Read statistical infromation from ax5 modem daugter card.
++* Input: tidsl_t *ptidsl
++*
++* Return: 0 success
++* 1 failed
++*
++********************************************************************************************/
++void dslhal_api_gatherStatistics(tidsl_t * ptidsl)
++{
++ int rc,optIdxU,optIdxD,i;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ DEV_HOST_dspWrNegoParaDef_t rateparms;
++ DEV_HOST_oamWrNegoParaDef_t configParms;
++ DEV_HOST_modemStatsDef_t StatisticsDef;
++ DEV_HOST_errorStats_t usIntlvError, usFastError, dsIntlvError, dsFastError;
++ DEV_HOST_atmStats_t atmStats;
++ DEV_HOST_usAtmStats_t usAtmStats0, usAtmStats1;
++ DEV_HOST_dsAtmStats_t dsAtmStats0,dsAtmStats1;
++ DEV_HOST_dspWrSuperFrameCntDef_t SuperFrameCnt;
++ DEV_HOST_msg_t atuc_msg, aturMsg;
++ DEV_HOST_eocVarDef_t eocVar;
++ DEV_HOST_dspWrSharedTables_t sharedTables;
++ DEV_HOST_phyPerf_t phyPerf;
++ unsigned char usBits[64],dsBits[256];
++ unsigned char dsPowerCutBack;
++ int usNumLoadedTones=0, dsNumLoadedTones=0;
++
++ dprintf(5, "dslhal_api_gatherStatistics\n");
++
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,
++ sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++ if(!ptidsl->bStatisticsInitialized && ptidsl->lConnected == LINE_CONNECTED)
++ {
++ dslhal_api_initStatistics(ptidsl);
++ ptidsl->bStatisticsInitialized = TRUE;
++ }
++
++ dspOamSharedInterface.dspWriteNegoParams_p = (DEV_HOST_dspWrNegoParaDef_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.dspWriteNegoParams_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.dspWriteNegoParams_p,
++ &rateparms, sizeof(DEV_HOST_dspWrNegoParaDef_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++ if(!rc)
++ {
++ /* trained mode */
++ ptidsl->AppData.dsl_modulation = (unsigned int)rateparms.trainMode;
++ if(rateparms.trainMode == T1413_MODE)
++ ptidsl->AppData.dsl_modulation = DSLTRAIN_T1413_MODE;
++ if(rateparms.trainMode == GDMT_MODE)
++ ptidsl->AppData.dsl_modulation = DSLTRAIN_GDMT_MODE;
++ /* rate */
++ /* shim_osMoveMemory((void *)ptidsl->AppData.bCRates1, (void *)rateparms.cRates1, 120); */
++ ptidsl->AppData.bCRates2 = rateparms.cRates2;
++ /* shim_osMoveMemory((void *)ptidsl->AppData.bRRates1, (void *)rateparms.rRates1, 44); */
++ ptidsl->AppData.bRRates2 = rateparms.rRates2;
++ shim_osMoveMemory((void *)ptidsl->AppData.bCMsgs1, (void *)rateparms.cMsgs1, 6);
++ shim_osMoveMemory((void *)ptidsl->AppData.bCMsgs2, (void *)rateparms.cMsgs2, 4);
++ shim_osMoveMemory((void *)ptidsl->AppData.bRMsgs2, (void *)rateparms.rMsgs2, 4);
++ ptidsl->AppData.atucVendorId = (unsigned int)rateparms.atucVendorId;
++ ptidsl->AppData.lineLength = (unsigned int)dslhal_support_byteSwap16((unsigned short)rateparms.lineLength);
++ ptidsl->AppData.atucRevisionNum = (unsigned int)rateparms.atucGhsRevisionNum;
++ ptidsl->AppData.usLineAttn = (ptidsl->AppData.bCMsgs2[3] >>2)&0x003f;
++ ptidsl->AppData.usMargin = (ptidsl->AppData.bCMsgs2[2])&0x001f;
++
++ if((rateparms.cRates2 & 0x0f) == 0x01)
++ optIdxU = 0;
++ else if((rateparms.cRates2 & 0x0f) == 0x02)
++ optIdxU = 1;
++ else if((rateparms.cRates2 & 0x0f) == 0x04)
++ optIdxU = 2;
++ else if((rateparms.cRates2 & 0x0f) == 0x08)
++ optIdxU = 3;
++ else
++ optIdxU = -1;
++
++ dprintf(5, "optIdxU=%d\n", optIdxU);
++
++ /* Obtain the US Rates using Opt# and CRates1 Table */
++ /* Rate(US) = [Bf(LS0) + Bi(LS0)]*32 */
++ if(ptidsl->AppData.dsl_modulation <= DSLTRAIN_GLITE_MODE)
++ ptidsl->AppData.USConRate = ((rateparms.cRates1[optIdxU][CRATES1_BF_LS0] + rateparms.cRates1[optIdxU][CRATES1_BI_LS0]) * 32);
++ else
++ ptidsl->AppData.USConRate = 32 * dslhal_support_byteSwap16((unsigned short)rateparms.adsl2USRate);
++
++ ptidsl->AppData.USPeakCellRate = ptidsl->AppData.USConRate;
++
++ if(((rateparms.cRates2 >> 4) & 0x0f) == 0x01)
++ optIdxD = 0;
++ else if(((rateparms.cRates2 >> 4) & 0x0f) == 0x02)
++ optIdxD = 1;
++ else if(((rateparms.cRates2 >> 4) & 0x0f) == 0x04)
++ optIdxD = 2;
++ else if(((rateparms.cRates2 >> 4) & 0x0f) == 0x08)
++ optIdxD = 3;
++ else
++ optIdxD = -1;
++ /* Obtain the DS Rates using Opt# and CRates1 Table */
++ /* Rate(DS) = [Bf(AS0) + Bi(AS0)]*32 */
++ if(ptidsl->AppData.dsl_modulation <= DSLTRAIN_GLITE_MODE)
++ ptidsl->AppData.DSConRate = (((rateparms.cRates1[optIdxD][CRATES1_BF_AS0]|((rateparms.cRates1[optIdxD][CRATES1_BF_DSRS]&0x80)<<1))+ (rateparms.cRates1[optIdxD][CRATES1_BI_AS0]|((rateparms.cRates1[optIdxD][CRATES1_BI_DSRS]&0x80)<<1)))* 32);
++ else
++ ptidsl->AppData.DSConRate = dslhal_support_byteSwap16((unsigned short)rateparms.adsl2DSRate);
++
++ dprintf(5, "ptidsl->AppData.wDSConRate=%d\n", ptidsl->AppData.DSConRate);
++ /* Determine which Path has Modem Trained with */
++ if((rateparms.cRates1[optIdxU][CRATES1_BF_LS0]) && (rateparms.cRates1[optIdxD][CRATES1_BF_AS0]))
++ ptidsl->AppData.TrainedPath = FAST_PATH;
++ else
++ ptidsl->AppData.TrainedPath = INTERLEAVED_PATH;
++
++ /* Set the mode in which the modem is trained */
++ ptidsl->AppData.TrainedMode = (unsigned int)rateparms.trainMode;
++ if(rateparms.trainMode == T1413_MODE)
++ ptidsl->AppData.TrainedMode = DSLTRAIN_T1413_MODE;
++ if(rateparms.trainMode == GDMT_MODE)
++ ptidsl->AppData.TrainedMode = DSLTRAIN_GDMT_MODE;
++
++ if(ptidsl->AppData.TrainedPath == FAST_PATH)
++ ptidsl->AppData.dsFastParityBytesPerSymbol = (rateparms.cRates1[optIdxU][CRATES1_BF_DSRS]&0x1f);
++ else
++ ptidsl->AppData.dsIntlvParityBytesPerSymbol = (rateparms.cRates1[optIdxU][CRATES1_BI_DSRS]&0x1f);
++ ptidsl->AppData.dsSymbolsPerCodeWord = (rateparms.cRates1[optIdxU][CRATES1_BFI_DSS]&0x1f);
++ ptidsl->AppData.dsInterleaverDepth = ((rateparms.cRates1[optIdxU][CRATES1_BFI_DSI])|((rateparms.cRates1[optIdxU][CRATES1_BFI_DSS]&0xc0)<<2));
++
++ if(ptidsl->AppData.TrainedPath == FAST_PATH)
++ ptidsl->AppData.usFastParityBytesPerSymbol = (rateparms.cRates1[optIdxU][CRATES1_BF_USRS]&0x1f);
++ else
++ ptidsl->AppData.usIntlvParityBytesPerSymbol = (rateparms.cRates1[optIdxU][CRATES1_BI_USRS]&0x1f);
++ ptidsl->AppData.usSymbolsPerCodeWord = (rateparms.cRates1[optIdxU][CRATES1_BFI_USS]&0x1f);
++ ptidsl->AppData.usInterleaverDepth = ((rateparms.cRates1[optIdxU][CRATES1_BFI_USI])|((rateparms.cRates1[optIdxU][CRATES1_BFI_USS]&0xc0)<<2));
++ }
++
++ dspOamSharedInterface.modemStats_p = (DEV_HOST_modemStatsDef_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.modemStats_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.modemStats_p,&StatisticsDef, sizeof(DEV_HOST_modemStatsDef_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++ /* Populate the Error Structure Variables */
++
++ /* US Interleave Path Error Statistics */
++
++ /* Change the endianness of the Pointer */
++ StatisticsDef.usErrorStatsIntlv_p = (DEV_HOST_errorStats_t *) dslhal_support_byteSwap32((unsigned int)StatisticsDef.usErrorStatsIntlv_p);
++
++ rc = dslhal_support_blockRead((PVOID)StatisticsDef.usErrorStatsIntlv_p,&usIntlvError, (sizeof(DEV_HOST_errorStats_t)));
++
++ if (rc)
++ return;
++
++ /* DS Interleave Path Error Statistics */
++
++ /* Change the endianness of the Pointer */
++ StatisticsDef.dsErrorStatsIntlv_p = (DEV_HOST_errorStats_t *) dslhal_support_byteSwap32((unsigned int)StatisticsDef.dsErrorStatsIntlv_p);
++
++ rc = dslhal_support_blockRead((PVOID)StatisticsDef.dsErrorStatsIntlv_p,&dsIntlvError, (sizeof(DEV_HOST_errorStats_t)));
++
++ if (rc)
++ return;
++
++ /* US Fast Path Error Statistics */
++
++ /* Change the endianness of the Pointer */
++ StatisticsDef.usErrorStatsFast_p = (DEV_HOST_errorStats_t *) dslhal_support_byteSwap32((unsigned int)StatisticsDef.usErrorStatsFast_p);
++
++ rc = dslhal_support_blockRead((PVOID)StatisticsDef.usErrorStatsFast_p,&usFastError, (sizeof(DEV_HOST_errorStats_t)));
++
++ if (rc)
++ return;
++
++ /* DS Fast Path Error Statistics */
++
++ /* Change the endianness of the Pointer */
++ StatisticsDef.dsErrorStatsFast_p = (DEV_HOST_errorStats_t *) dslhal_support_byteSwap32((unsigned int)StatisticsDef.dsErrorStatsFast_p);
++
++ rc = dslhal_support_blockRead((PVOID)StatisticsDef.dsErrorStatsFast_p,&dsFastError, (sizeof(DEV_HOST_errorStats_t)));
++
++ if (rc)
++ return;
++ if(!rc)
++ {
++ if(ptidsl->AppData.bState > 2)
++ {
++ /* Get CRC Errors Stats for both US and DS */
++ ptidsl->AppData.dsICRC_errors = dslhal_support_byteSwap32((unsigned int)dsIntlvError.crcErrors);
++ ptidsl->AppData.dsFCRC_errors = dslhal_support_byteSwap32((unsigned int)dsFastError.crcErrors);
++ ptidsl->AppData.usICRC_errors = dslhal_support_byteSwap32((unsigned int)usIntlvError.crcErrors);
++ ptidsl->AppData.usFCRC_errors = dslhal_support_byteSwap32((unsigned int)usFastError.crcErrors);
++ /* Get FEC Errors Stats for both US and DS */
++ ptidsl->AppData.dsIFEC_errors = dslhal_support_byteSwap32((unsigned int)dsIntlvError.fecErrors);
++ ptidsl->AppData.dsFFEC_errors = dslhal_support_byteSwap32((unsigned int)dsFastError.fecErrors);
++ ptidsl->AppData.usIFEC_errors = dslhal_support_byteSwap32((unsigned int)usIntlvError.fecErrors);
++ ptidsl->AppData.usFFEC_errors = dslhal_support_byteSwap32((unsigned int)usFastError.fecErrors);
++ /* Get NCD Errors Stats for both US and DS */
++ ptidsl->AppData.dsINCD_error = dslhal_support_byteSwap32((unsigned int)dsIntlvError.ncdError);
++ ptidsl->AppData.dsFNCD_error = dslhal_support_byteSwap32((unsigned int)dsFastError.ncdError);
++ ptidsl->AppData.usINCD_error = dslhal_support_byteSwap32((unsigned int)usIntlvError.ncdError);
++ ptidsl->AppData.usFNCD_error = dslhal_support_byteSwap32((unsigned int)usFastError.ncdError);
++ /* Get LCD Errors Stats for both US and DS */
++ ptidsl->AppData.dsILCD_errors = dslhal_support_byteSwap32((unsigned int)dsIntlvError.lcdErrors);
++ ptidsl->AppData.dsFLCD_errors = dslhal_support_byteSwap32((unsigned int)dsFastError.lcdErrors);
++ ptidsl->AppData.usILCD_errors = dslhal_support_byteSwap32((unsigned int)usIntlvError.lcdErrors);
++ ptidsl->AppData.usFLCD_errors = dslhal_support_byteSwap32((unsigned int)usFastError.lcdErrors);
++ /*Get HEC Errors Stats for both US and DS */
++ ptidsl->AppData.dsIHEC_errors = dslhal_support_byteSwap32((unsigned int)dsIntlvError.hecErrors);
++ ptidsl->AppData.dsFHEC_errors = dslhal_support_byteSwap32((unsigned int)dsFastError.hecErrors);
++ ptidsl->AppData.usIHEC_errors = dslhal_support_byteSwap32((unsigned int)usIntlvError.hecErrors);
++ ptidsl->AppData.usFHEC_errors = dslhal_support_byteSwap32((unsigned int)usFastError.hecErrors);
++
++ /* Get LOS and SEF error Stats */
++ ptidsl->AppData.LOS_errors = dslhal_support_byteSwap32(StatisticsDef.losErrors);
++ ptidsl->AppData.SEF_errors = dslhal_support_byteSwap32(StatisticsDef.sefErrors);
++ ptidsl->AppData.coLosErrors = dslhal_support_byteSwap32(StatisticsDef.farEndLosErrors);
++ ptidsl->AppData.coRdiErrors = dslhal_support_byteSwap32(StatisticsDef.farEndRdiErrors);
++
++ dspOamSharedInterface.atmStats_p = (DEV_HOST_atmStats_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.atmStats_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.atmStats_p,&atmStats, sizeof(DEV_HOST_atmStats_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++
++ /* Populate the US/DS ATM Stats Variables */
++
++ /* US ATM Statistics */
++
++ /* Change the endianness of the Pointer */
++ atmStats.us0_p = (DEV_HOST_usAtmStats_t *) dslhal_support_byteSwap32((unsigned int)atmStats.us0_p);
++
++ rc = dslhal_support_blockRead((PVOID)atmStats.us0_p,&usAtmStats0, (sizeof(DEV_HOST_usAtmStats_t)));
++
++ if (rc)
++ return;
++
++ atmStats.us1_p = (DEV_HOST_usAtmStats_t *) dslhal_support_byteSwap32((unsigned int)atmStats.us1_p);
++
++ rc = dslhal_support_blockRead((PVOID)atmStats.us1_p,&usAtmStats1, (sizeof(DEV_HOST_usAtmStats_t)));
++
++ if (rc)
++ return;
++
++ /* DS ATM Statistics */
++
++ /* Change the endianness of the Pointer */
++ atmStats.ds0_p = (DEV_HOST_dsAtmStats_t *) dslhal_support_byteSwap32((unsigned int)atmStats.ds0_p);
++
++ rc = dslhal_support_blockRead((PVOID)atmStats.ds0_p,&dsAtmStats0, (sizeof(DEV_HOST_dsAtmStats_t)));
++
++ if (rc)
++ return;
++ atmStats.ds1_p = (DEV_HOST_dsAtmStats_t *) dslhal_support_byteSwap32((unsigned int)atmStats.ds1_p);
++
++ rc = dslhal_support_blockRead((PVOID)atmStats.ds1_p,&dsAtmStats1, (sizeof(DEV_HOST_dsAtmStats_t)));
++
++ if (rc)
++ return;
++
++ /* Get ATM Stats for both US and DS for Channel 0*/
++ ptidsl->AppData.usAtm_count[0] = dslhal_support_byteSwap32(usAtmStats0.goodCount);
++ ptidsl->AppData.usIdle_count[0] = dslhal_support_byteSwap32(usAtmStats0.idleCount);
++#if SWTC
++ ptidsl->AppData.usPdu_count[0] = dslhal_support_byteSwap32(usAtmStats0.pduCount);
++#endif
++ ptidsl->AppData.dsGood_count[0] = dslhal_support_byteSwap32(dsAtmStats0.goodCount);
++ ptidsl->AppData.dsIdle_count[0] = dslhal_support_byteSwap32(dsAtmStats0.idleCount);
++#if SWTC
++ ptidsl->AppData.dsPdu_count[0] = dslhal_support_byteSwap32(dsAtmStats0.pduCount);
++#endif
++ ptidsl->AppData.dsBadHec_count[0] = dslhal_support_byteSwap32((dsAtmStats0.badHecCount));
++ ptidsl->AppData.dsOVFDrop_count[0] = dslhal_support_byteSwap32((dsAtmStats0.ovflwDropCount));
++ /* Get ATM Stats for both US and DS for Channel 1*/
++ ptidsl->AppData.usAtm_count[1] = dslhal_support_byteSwap32(usAtmStats1.goodCount);
++ ptidsl->AppData.usIdle_count[1] = dslhal_support_byteSwap32(usAtmStats1.idleCount);
++#if SWTC
++ ptidsl->AppData.usPdu_count[1] = dslhal_support_byteSwap32(usAtmStats1.pduCount);
++#endif
++ ptidsl->AppData.dsGood_count[1] = dslhal_support_byteSwap32(dsAtmStats1.goodCount);
++ ptidsl->AppData.dsIdle_count[1] = dslhal_support_byteSwap32(dsAtmStats1.idleCount);
++#if SWTC
++ ptidsl->AppData.dsPdu_count[1] = dslhal_support_byteSwap32(dsAtmStats1.pduCount);
++#endif
++ ptidsl->AppData.dsBadHec_count[1] = dslhal_support_byteSwap32((dsAtmStats1.badHecCount));
++ ptidsl->AppData.dsOVFDrop_count[1] = dslhal_support_byteSwap32((dsAtmStats1.ovflwDropCount));
++
++ /* Determine the US and DS Superframe Count */
++
++ dspOamSharedInterface.dspWriteSuperFrameCnt_p = (DEV_HOST_dspWrSuperFrameCntDef_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.dspWriteSuperFrameCnt_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.dspWriteSuperFrameCnt_p,&SuperFrameCnt, sizeof(DEV_HOST_dspWrSuperFrameCntDef_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++ ptidsl->AppData.usSuperFrmCnt = dslhal_support_byteSwap32(SuperFrameCnt.wSuperFrameCntUstrm);
++ ptidsl->AppData.dsSuperFrmCnt = dslhal_support_byteSwap32(SuperFrameCnt.wSuperFrameCntDstrm);
++
++ /* Determine Frame Mode and Max Frame Mode */
++
++ dspOamSharedInterface.atucMsg_p = (DEV_HOST_msg_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.atucMsg_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.atucMsg_p,&atuc_msg, sizeof(DEV_HOST_msg_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++
++ ptidsl->AppData.FrmMode = (unsigned int)atuc_msg.framingMode;
++ ptidsl->AppData.MaxFrmMode = (unsigned int)atuc_msg.maxFrameMode;
++
++ /* Determine Gross Gain */
++
++ dspOamSharedInterface.aturMsg_p = (DEV_HOST_msg_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.aturMsg_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.aturMsg_p,&aturMsg, sizeof(DEV_HOST_msg_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++ ptidsl->AppData.grossGain = (unsigned int)aturMsg.grossGain;
++
++ /* Determine DS Line Attenuation & Margin */
++ dspOamSharedInterface.eocVar_p = (DEV_HOST_eocVarDef_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.eocVar_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.eocVar_p,&eocVar, sizeof(DEV_HOST_eocVarDef_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++ ptidsl->AppData.dsLineAttn = (unsigned int)eocVar.lineAtten;
++ ptidsl->AppData.dsMargin = (unsigned int)eocVar.dsMargin;
++ }
++ }
++
++ /* Read in the Shared Tables structure */
++ dspOamSharedInterface.dspWrSharedTables_p = (DEV_HOST_dspWrSharedTables_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.dspWrSharedTables_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.dspWrSharedTables_p,&sharedTables, sizeof(DEV_HOST_dspWrSharedTables_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++
++ /* Read the ATU-R Bits and Gains Table */
++ sharedTables.aturBng_p = (unsigned char *)dslhal_support_byteSwap32((unsigned int)sharedTables.aturBng_p);
++ rc = dslhal_support_blockRead((PVOID)sharedTables.aturBng_p,ptidsl->AppData.rBng,255*2*sizeof(unsigned char));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++ /* Read the ATU-C Bits and Gains Table */
++ sharedTables.atucBng_p = (unsigned char *)dslhal_support_byteSwap32((unsigned int)sharedTables.atucBng_p);
++ if(ptidsl->netService == 2) /* for Annex_B */
++ {
++ rc = dslhal_support_blockRead((PVOID)sharedTables.atucBng_p,ptidsl->AppData.cBng,126*sizeof(unsigned char));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++ for(i=0;i<US_BNG_LENGTH*2;i++)
++ usBits[i]=0;
++ for(i=1;i<US_BNG_LENGTH*2;i++)
++ {
++ usBits[i]=((ptidsl->AppData.cBng[(i-1)*2])&0xf);
++ dprintf(5,"Bit #%d : 0x%x\n",i,usBits[i]);
++ }
++ for(i=1;i<US_BNG_LENGTH*2;i++)
++ {
++ if(usBits[i])
++ usNumLoadedTones++;
++ }
++ }
++ else
++ {
++ rc = dslhal_support_blockRead((PVOID)sharedTables.atucBng_p,ptidsl->AppData.cBng,62*sizeof(unsigned char));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++ for(i=0;i<US_BNG_LENGTH;i++)
++ usBits[i]=0;
++ for(i=1;i<US_BNG_LENGTH;i++)
++ {
++ usBits[i]=((ptidsl->AppData.cBng[(i-1)*2])&0xf);
++ dprintf(5,"Bit #%d : 0x%x\n",i,usBits[i]);
++ }
++ for(i=1;i<US_BNG_LENGTH;i++)
++ {
++ if(usBits[i])
++ usNumLoadedTones++;
++ }
++ }
++
++ /* Determine Number U/S of Loaded Tones */
++
++ /* U/S Power Computation */
++ dspOamSharedInterface.phyPerf_p = (DEV_HOST_phyPerf_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.phyPerf_p);
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.phyPerf_p,
++ &phyPerf, sizeof(DEV_HOST_phyPerf_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++ ptidsl->AppData.currentHybridNum = phyPerf.currentHybridNumUsed;
++ phyPerf.usAvgGain = dslhal_support_byteSwap32(phyPerf.usAvgGain);
++ ptidsl->AppData.usTxPower = LOG43125 + phyPerf.usAvgGain + (256*US_NOMINAL_POWER)+log10[usNumLoadedTones-1];
++ dprintf(7,"Avg Gain: 0x%x usNumLoadedTones: 0x%x log: 0x%x\n",phyPerf.usAvgGain, usNumLoadedTones, log10[usNumLoadedTones-1]);
++
++ /* Determine Number D/S of Loaded Tones */
++ dsBits[0]=0;
++ for(i=0;i<DS_BNG_LENGTH;i++)
++ {
++ dsBits[i]=0;
++ /* ptidsl->AppData.rBng[i-1]=dslhal_support_byteSwap32((unsigned int)ptidsl->AppData.rBng[i-1]);*/
++ }
++ for(i=1;i<DS_BNG_LENGTH;i++)
++ {
++ dsBits[i]=((ptidsl->AppData.rBng[(i-1)*2])&0xf);
++ dprintf(5,"Bit #%d : 0x%x\n",i,dsBits[i]);
++ }
++ for(i=1;i<DS_BNG_LENGTH;i++)
++ {
++ if(dsBits[i])
++ dsNumLoadedTones++;
++ }
++ /* D/S Power Computation */
++ dspOamSharedInterface.phyPerf_p = (DEV_HOST_phyPerf_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.phyPerf_p);
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.phyPerf_p,
++ &phyPerf, sizeof(DEV_HOST_phyPerf_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++ /* D/S Power Cutback */
++ dsPowerCutBack = (unsigned char)((((ptidsl->AppData.bCMsgs1[0]) >>6) &0x3)+(((ptidsl->AppData.bCMsgs1[1]) &0x1) <<2));
++ phyPerf.dsAvgGain = dslhal_support_byteSwap32(phyPerf.dsAvgGain);
++ ptidsl->AppData.dsTxPower = LOG43125 + phyPerf.dsAvgGain + (256*((2*(dsPowerCutBack-1))-52)) + log10[dsNumLoadedTones-1];
++ dprintf(7,"Avg Gain: %d dsNumLoadedTones: %d log: %d pcb: %d \n",phyPerf.dsAvgGain, dsNumLoadedTones, log10[dsNumLoadedTones-1], dsPowerCutBack);
++ /* ds bit allocation */
++ sharedTables.bitAllocTblDstrm_p = (unsigned char *)dslhal_support_byteSwap32((unsigned int)sharedTables.bitAllocTblDstrm_p);
++ rc = dslhal_support_blockRead((PVOID)sharedTables.bitAllocTblDstrm_p,ptidsl->AppData.BitAllocTblDstrm, 256*sizeof(unsigned char));
++ if(rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed \n");
++ return;
++ }
++
++ /* us bit allocation */
++ sharedTables.bitAllocTblUstrm_p = (unsigned char *)dslhal_support_byteSwap32((unsigned int)sharedTables.bitAllocTblUstrm_p);
++ rc = dslhal_support_blockRead((PVOID)sharedTables.bitAllocTblUstrm_p,ptidsl->AppData.BitAllocTblUstrm, 32*sizeof(unsigned char));
++ if(rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed \n");
++ return;
++ }
++ /* margin per tone */
++ sharedTables.marginTblDstrm_p = (signed char *)dslhal_support_byteSwap32((unsigned int)sharedTables.marginTblDstrm_p);
++ rc = dslhal_support_blockRead((PVOID)sharedTables.marginTblDstrm_p,ptidsl->AppData.marginTblDstrm, 256*sizeof(signed char));
++ if(rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed \n");
++ return;
++ }
++ /* Read Configured Options */
++ dspOamSharedInterface.oamWriteNegoParams_p = (DEV_HOST_oamWrNegoParaDef_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.oamWriteNegoParams_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.oamWriteNegoParams_p,
++ &configParms, sizeof(DEV_HOST_oamWrNegoParaDef_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++ else
++ {
++ /* r-Msg1 */
++ ptidsl->AppData.StdMode = (unsigned int)configParms.stdMode;
++ if(configParms.stdMode == T1413_MODE)
++ ptidsl->AppData.StdMode = DSLTRAIN_T1413_MODE;
++ if(configParms.stdMode == GDMT_MODE)
++ ptidsl->AppData.StdMode = DSLTRAIN_GDMT_MODE;
++ if(configParms.stdMode == MULTI_MODE)
++ ptidsl->AppData.StdMode = DSLTRAIN_MULTI_MODE;
++
++ shim_osMoveMemory((void *)ptidsl->AppData.bRMsgs1, (void *)configParms.rMsgs1, 6*sizeof(char));
++ if((ptidsl->AppData.bRMsgs1[2] & 0x02) == 0x02)
++ {
++ dprintf(7,"Trellis!\n");
++ ptidsl->configFlag |= CONFIG_FLAG_TRELLIS;
++ }
++ else
++ ptidsl->configFlag &= ~CONFIG_FLAG_TRELLIS;
++ if(ptidsl->AppData.bRMsgs1[2]&0x01)
++ ptidsl->configFlag |= CONFIG_FLAG_EC;
++ else
++ ptidsl->configFlag &= ~CONFIG_FLAG_EC;
++ }
++ return;
++}
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_initStatistics()
++*
++*********************************************************************************************
++* DESCRIPTION: init statistical information of ax5 modem daugter card.
++*
++* Input: tidsl_t *ptidsl
++*
++* Return: NULL
++*
++********************************************************************************************/
++void dslhal_api_initStatistics(tidsl_t * ptidsl)
++{
++ int rc;
++ /*TCHostCommDef TCHostCommParms; */
++ int optIdxU, optIdxD;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ DEV_HOST_dspWrNegoParaDef_t rateparms;
++ DEV_HOST_modemStatsDef_t StatisticsDef;
++ DEV_HOST_errorStats_t usIntlvError, usFastError, dsIntlvError, dsFastError;
++ DEV_HOST_atmStats_t atmStats;
++ DEV_HOST_usAtmStats_t usAtmStats0, usAtmStats1;
++ DEV_HOST_dsAtmStats_t dsAtmStats0,dsAtmStats1;
++ DEV_HOST_dspWrSuperFrameCntDef_t SuperFrameCnt;
++ DEV_HOST_msg_t atuc_msg, aturMsg;
++ DEV_HOST_eocVarDef_t eocVar;
++
++ dprintf(5, "dslhal_api_initStatistics\n");
++
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterface_t *) ptidsl->pmainAddr;
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++ dspOamSharedInterface.dspWriteNegoParams_p = (DEV_HOST_dspWrNegoParaDef_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.dspWriteNegoParams_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.dspWriteNegoParams_p,&rateparms, sizeof(DEV_HOST_dspWrNegoParaDef_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++ if(!rc)
++ {
++ /* shim_osMoveMemory((void *)ptidsl->AppData.bCRates1, (void *)rateparms.cRates1, SIZE_OF_CRATES1_TABLE); */
++ ptidsl->AppData.bCRates2 = rateparms.cRates2;
++ /* shim_osMoveMemory((void *)ptidsl->AppData.bRRates1, (void *)rateparms.rRates1, 44); */
++ ptidsl->AppData.bRRates2 = rateparms.rRates2;
++ shim_osMoveMemory((void *)ptidsl->AppData.bCMsgs1, (void *)rateparms.cMsgs1, 6);
++ shim_osMoveMemory((void *)ptidsl->AppData.bCMsgs2, (void *)rateparms.cMsgs2, 4);
++ shim_osMoveMemory((void *)ptidsl->AppData.bRMsgs2, (void *)rateparms.rMsgs2, 4);
++
++ ptidsl->AppData.atucVendorId = dslhal_support_byteSwap32((unsigned int)rateparms.atucVendorId);
++ ptidsl->AppData.lineLength = (unsigned int)dslhal_support_byteSwap16((unsigned short)rateparms.lineLength);
++ ptidsl->AppData.atucRevisionNum = rateparms.atucGhsRevisionNum;
++ ptidsl->AppData.usLineAttn = (ptidsl->AppData.bCMsgs2[3] >>2)&0x003f;
++ ptidsl->AppData.usMargin = (ptidsl->AppData.bCMsgs2[2])&0x001f;
++
++ /* Get the UpStream Connection Rate */
++ /* Based on the Bit Pattern Get the Opt# */
++ if((rateparms.cRates2 & 0x0f) == 0x01)
++ optIdxU = 0;
++ else if((rateparms.cRates2 & 0x0f) == 0x02)
++ optIdxU = 1;
++ else if((rateparms.cRates2 & 0x0f) == 0x04)
++ optIdxU = 2;
++ else if((rateparms.cRates2 & 0x0f) == 0x08)
++ optIdxU = 3;
++ else
++ optIdxU = -1;
++ dprintf(5, "optIdxU=%d\n", optIdxU);
++ /* Obtain the US Rates using Opt# and CRates1 Table */
++ /* Rate(US) = [Bf(LS0) + Bi(LS0)]*32 */
++ if(ptidsl->AppData.dsl_modulation <= DSLTRAIN_GLITE_MODE)
++ ptidsl->AppData.USConRate = ((rateparms.cRates1[optIdxU][CRATES1_BF_LS0] + rateparms.cRates1[optIdxU][CRATES1_BI_LS0]) * 32);
++ else
++ ptidsl->AppData.USConRate = dslhal_support_byteSwap16((unsigned short)rateparms.adsl2USRate);
++ ptidsl->AppData.USPeakCellRate = ptidsl->AppData.USConRate;
++
++ /* Get the DownStream Connection Rate */
++ /* Based on the Bit Pattern Get the Opt# */
++ if(((rateparms.cRates2 >> 4) & 0x0f) == 0x01)
++ optIdxD = 0;
++ else if(((rateparms.cRates2 >> 4) & 0x0f) == 0x02)
++ optIdxD = 1;
++ else if(((rateparms.cRates2 >> 4) & 0x0f) == 0x04)
++ optIdxD = 2;
++ else if(((rateparms.cRates2 >> 4) & 0x0f) == 0x08)
++ optIdxD = 3;
++ else
++ optIdxD = -1;
++ /* Obtain the DS Rates using Opt# and CRates1 Table */
++ /* Rate(DS) = [Bf(AS0) + Bi(AS0)]*32 */
++ if(ptidsl->AppData.dsl_modulation <= DSLTRAIN_GLITE_MODE)
++ ptidsl->AppData.DSConRate = (((rateparms.cRates1[optIdxD][CRATES1_BF_AS0]|((rateparms.cRates1[optIdxD][CRATES1_BF_DSRS]&0x80)<<1))+ (rateparms.cRates1[optIdxD][CRATES1_BI_AS0]|((rateparms.cRates1[optIdxD][CRATES1_BI_DSRS]&0x80)<<1)))* 32);
++ else
++ ptidsl->AppData.DSConRate = dslhal_support_byteSwap16((unsigned short)rateparms.adsl2DSRate);
++ dprintf(5, "ptidsl->AppData.wDSConRate=%d\n", ptidsl->AppData.DSConRate);
++ /* Determine which Path has Modem Trained with */
++ if((rateparms.cRates1[optIdxU][CRATES1_BF_LS0]) && (rateparms.cRates1[optIdxD][CRATES1_BF_AS0]))
++ ptidsl->AppData.TrainedPath = FAST_PATH;
++ else
++ ptidsl->AppData.TrainedPath = INTERLEAVED_PATH;
++
++ /* Set the mode in which the modem is trained */
++ ptidsl->AppData.TrainedMode = (unsigned int)rateparms.trainMode;
++ if(rateparms.trainMode == T1413_MODE)
++ ptidsl->AppData.TrainedMode = DSLTRAIN_T1413_MODE;
++ if(rateparms.trainMode == GDMT_MODE)
++ ptidsl->AppData.TrainedMode = DSLTRAIN_GDMT_MODE;
++
++ if(ptidsl->AppData.TrainedPath == FAST_PATH)
++ ptidsl->AppData.dsFastParityBytesPerSymbol = (rateparms.cRates1[optIdxU][CRATES1_BF_DSRS]&0x1f);
++ else
++ ptidsl->AppData.dsIntlvParityBytesPerSymbol = (rateparms.cRates1[optIdxU][CRATES1_BI_DSRS]&0x1f);
++ ptidsl->AppData.dsSymbolsPerCodeWord = (rateparms.cRates1[optIdxU][CRATES1_BFI_DSS]&0x1f);
++ ptidsl->AppData.dsInterleaverDepth = ((rateparms.cRates1[optIdxU][CRATES1_BFI_DSI])|((rateparms.cRates1[optIdxU][CRATES1_BFI_DSS]&0xc0)<<2));
++
++ if(ptidsl->AppData.TrainedPath == FAST_PATH)
++ ptidsl->AppData.usFastParityBytesPerSymbol = (rateparms.cRates1[optIdxU][CRATES1_BF_USRS]&0x1f);
++ else
++ ptidsl->AppData.usIntlvParityBytesPerSymbol = (rateparms.cRates1[optIdxU][CRATES1_BI_USRS]&0x1f);
++ ptidsl->AppData.usSymbolsPerCodeWord = (rateparms.cRates1[optIdxU][CRATES1_BFI_USS]&0x1f);
++ ptidsl->AppData.usInterleaverDepth = ((rateparms.cRates1[optIdxU][CRATES1_BFI_USI])|((rateparms.cRates1[optIdxU][CRATES1_BFI_USS]&0xc0)<<2));
++ }
++
++ /* get the Statistics itself */
++
++ dspOamSharedInterface.modemStats_p = (DEV_HOST_modemStatsDef_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.modemStats_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.modemStats_p,&StatisticsDef, sizeof(DEV_HOST_modemStatsDef_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++
++ /* Populate the Error Structure Variables */
++
++ /* US Interleave Path Error Statistics */
++
++ /* Change the endianness of the Pointer */
++ StatisticsDef.usErrorStatsIntlv_p = (DEV_HOST_errorStats_t *) dslhal_support_byteSwap32((unsigned int)StatisticsDef.usErrorStatsIntlv_p);
++
++ rc = dslhal_support_blockRead((PVOID)StatisticsDef.usErrorStatsIntlv_p,&usIntlvError, (sizeof(DEV_HOST_errorStats_t)));
++
++ if (rc)
++ return;
++
++ /* DS Interleave Path Error Statistics */
++
++ /* Change the endianness of the Pointer */
++ StatisticsDef.dsErrorStatsIntlv_p = (DEV_HOST_errorStats_t *) dslhal_support_byteSwap32((unsigned int)StatisticsDef.dsErrorStatsIntlv_p);
++
++ rc = dslhal_support_blockRead((PVOID)StatisticsDef.dsErrorStatsIntlv_p,&dsIntlvError, (sizeof(DEV_HOST_errorStats_t)));
++
++ if (rc)
++ return;
++
++ /* US Fast Path Error Statistics */
++
++ /* Change the endianness of the Pointer */
++ StatisticsDef.usErrorStatsFast_p = (DEV_HOST_errorStats_t *) dslhal_support_byteSwap32((unsigned int)StatisticsDef.usErrorStatsFast_p);
++
++ rc = dslhal_support_blockRead((PVOID)StatisticsDef.usErrorStatsFast_p,&usFastError, (sizeof(DEV_HOST_errorStats_t)));
++
++ if (rc)
++ return;
++
++
++ /* DS Fast Path Error Statistics */
++
++ /* Change the endianness of the Pointer */
++ StatisticsDef.dsErrorStatsFast_p = (DEV_HOST_errorStats_t *) dslhal_support_byteSwap32((unsigned int)StatisticsDef.dsErrorStatsFast_p);
++
++ rc = dslhal_support_blockRead((PVOID)StatisticsDef.dsErrorStatsFast_p,&dsFastError, (sizeof(DEV_HOST_errorStats_t)));
++
++ if (rc)
++ return;
++
++ if(ptidsl->AppData.bState > 2)
++ {
++ /* Get CRC Errors Stats for both US and DS */
++ ptidsl->AppData.dsICRC_errors = dslhal_support_byteSwap32((unsigned int)dsIntlvError.crcErrors);
++ ptidsl->AppData.dsFCRC_errors = dslhal_support_byteSwap32((unsigned int)dsFastError.crcErrors);
++ ptidsl->AppData.usICRC_errors = dslhal_support_byteSwap32((unsigned int)usIntlvError.crcErrors);
++ ptidsl->AppData.usFCRC_errors = dslhal_support_byteSwap32((unsigned int)usFastError.crcErrors);
++ /* Get FEC Errors Stats for both US and DS */
++ ptidsl->AppData.dsIFEC_errors = dslhal_support_byteSwap32((unsigned int)dsIntlvError.fecErrors);
++ ptidsl->AppData.dsFFEC_errors = dslhal_support_byteSwap32((unsigned int)dsFastError.fecErrors);
++ ptidsl->AppData.usIFEC_errors = dslhal_support_byteSwap32((unsigned int)usIntlvError.fecErrors);
++ ptidsl->AppData.usFFEC_errors = dslhal_support_byteSwap32((unsigned int)usFastError.fecErrors);
++ /* Get NCD Errors Stats for both US and DS */
++ ptidsl->AppData.dsINCD_error = dslhal_support_byteSwap32((unsigned int)dsIntlvError.ncdError);
++ ptidsl->AppData.dsFNCD_error = dslhal_support_byteSwap32((unsigned int)dsFastError.ncdError);
++ ptidsl->AppData.usINCD_error = dslhal_support_byteSwap32((unsigned int)usIntlvError.ncdError);
++ ptidsl->AppData.usFNCD_error = dslhal_support_byteSwap32((unsigned int)usFastError.ncdError);
++ /* Get LCD Errors Stats for both US and DS */
++ ptidsl->AppData.dsILCD_errors = dslhal_support_byteSwap32((unsigned int)dsIntlvError.lcdErrors);
++ ptidsl->AppData.dsFLCD_errors = dslhal_support_byteSwap32((unsigned int)dsFastError.lcdErrors);
++ ptidsl->AppData.usILCD_errors = dslhal_support_byteSwap32((unsigned int)usIntlvError.lcdErrors);
++ ptidsl->AppData.usFLCD_errors = dslhal_support_byteSwap32((unsigned int)usFastError.lcdErrors);
++ /*Get HEC Errors Stats for both US and DS */
++ ptidsl->AppData.dsIHEC_errors = dslhal_support_byteSwap32((unsigned int)dsIntlvError.hecErrors);
++ ptidsl->AppData.dsFHEC_errors = dslhal_support_byteSwap32((unsigned int)dsFastError.hecErrors);
++ ptidsl->AppData.usIHEC_errors = dslhal_support_byteSwap32((unsigned int)usIntlvError.hecErrors);
++ ptidsl->AppData.usFHEC_errors = dslhal_support_byteSwap32((unsigned int)usFastError.hecErrors);
++
++ /* Get LOS and SEF error Stats */
++ ptidsl->AppData.LOS_errors = dslhal_support_byteSwap32(StatisticsDef.losErrors);
++ ptidsl->AppData.SEF_errors = dslhal_support_byteSwap32(StatisticsDef.sefErrors);
++ ptidsl->AppData.coLosErrors = dslhal_support_byteSwap32(StatisticsDef.farEndLosErrors);
++ ptidsl->AppData.coRdiErrors = dslhal_support_byteSwap32(StatisticsDef.farEndRdiErrors);
++
++ dspOamSharedInterface.atmStats_p = (DEV_HOST_atmStats_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.atmStats_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.atmStats_p,&atmStats, sizeof(DEV_HOST_atmStats_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++
++ /* Populate the US/DS ATM Stats Variables */
++
++ /* US ATM Statistics */
++
++ /* Change the endianness of the Pointer */
++ atmStats.us0_p = (DEV_HOST_usAtmStats_t *) dslhal_support_byteSwap32((unsigned int)atmStats.us0_p);
++
++ rc = dslhal_support_blockRead((PVOID)atmStats.us0_p,&usAtmStats0, (sizeof(DEV_HOST_usAtmStats_t)));
++
++ if (rc)
++ return;
++
++ /* Change the endianness of the Pointer */
++ atmStats.us1_p = (DEV_HOST_usAtmStats_t *) dslhal_support_byteSwap32((unsigned int)atmStats.us1_p);
++
++ rc = dslhal_support_blockRead((PVOID)atmStats.us1_p,&usAtmStats1, (sizeof(DEV_HOST_usAtmStats_t)));
++
++ if (rc)
++ return;
++
++
++ /* DS ATM Statistics */
++
++ /* Change the endianness of the Pointer */
++ atmStats.ds0_p = (DEV_HOST_dsAtmStats_t *) dslhal_support_byteSwap32((unsigned int)atmStats.ds0_p);
++
++ rc = dslhal_support_blockRead((PVOID)atmStats.ds0_p,&dsAtmStats0, (sizeof(DEV_HOST_dsAtmStats_t)));
++
++ if (rc)
++ return;
++
++ /* Change the endianness of the Pointer */
++ atmStats.ds1_p = (DEV_HOST_dsAtmStats_t *) dslhal_support_byteSwap32((unsigned int)atmStats.ds1_p);
++
++ rc = dslhal_support_blockRead((PVOID)atmStats.ds1_p,&dsAtmStats1, (sizeof(DEV_HOST_dsAtmStats_t)));
++
++ if (rc)
++ return;
++ /* Get ATM Stats for both US and DS Channel 0*/
++ ptidsl->AppData.usAtm_count[0] = dslhal_support_byteSwap32(usAtmStats0.goodCount);
++ ptidsl->AppData.usIdle_count[0] = dslhal_support_byteSwap32(usAtmStats0.idleCount);
++#if SWTC
++ ptidsl->AppData.usPdu_count[0] = dslhal_support_byteSwap32(usAtmStats0.pduCount);
++#endif
++ ptidsl->AppData.dsGood_count[0] = dslhal_support_byteSwap32(dsAtmStats0.goodCount);
++ ptidsl->AppData.dsIdle_count[0] = dslhal_support_byteSwap32(dsAtmStats0.idleCount);
++#if SWTC
++ ptidsl->AppData.dsPdu_count[0] = dslhal_support_byteSwap32(dsAtmStats0.pduCount);
++#endif
++ ptidsl->AppData.dsBadHec_count[0] = dslhal_support_byteSwap32((dsAtmStats0.badHecCount));
++ ptidsl->AppData.dsOVFDrop_count[0] = dslhal_support_byteSwap32((dsAtmStats0.ovflwDropCount));
++
++ /* Get ATM Stats for both US and DS Channel 1*/
++ ptidsl->AppData.usAtm_count[1] = dslhal_support_byteSwap32(usAtmStats1.goodCount);
++ ptidsl->AppData.usIdle_count[1] = dslhal_support_byteSwap32(usAtmStats1.idleCount);
++#if SWTC
++ ptidsl->AppData.usPdu_count[1] = dslhal_support_byteSwap32(usAtmStats1.pduCount);
++#endif
++ ptidsl->AppData.dsGood_count[1] = dslhal_support_byteSwap32(dsAtmStats1.goodCount);
++ ptidsl->AppData.dsIdle_count[1] = dslhal_support_byteSwap32(dsAtmStats1.idleCount);
++#if SWTC
++ ptidsl->AppData.dsPdu_count[1] = dslhal_support_byteSwap32(dsAtmStats1.pduCount);
++#endif
++ ptidsl->AppData.dsBadHec_count[1] = dslhal_support_byteSwap32((dsAtmStats1.badHecCount));
++ ptidsl->AppData.dsOVFDrop_count[1] = dslhal_support_byteSwap32((dsAtmStats1.ovflwDropCount));
++
++
++ /* Determine the US and DS Superframe Count */
++
++ dspOamSharedInterface.dspWriteSuperFrameCnt_p = (DEV_HOST_dspWrSuperFrameCntDef_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.dspWriteSuperFrameCnt_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.dspWriteSuperFrameCnt_p,&SuperFrameCnt, sizeof(DEV_HOST_dspWrSuperFrameCntDef_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++
++ ptidsl->AppData.usSuperFrmCnt = dslhal_support_byteSwap32(SuperFrameCnt.wSuperFrameCntUstrm);
++ ptidsl->AppData.dsSuperFrmCnt = dslhal_support_byteSwap32(SuperFrameCnt.wSuperFrameCntDstrm);
++
++ /* Determine Frame Mode and Max Frame Mode */
++
++ dspOamSharedInterface.atucMsg_p = (DEV_HOST_msg_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.atucMsg_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.atucMsg_p,&atuc_msg, sizeof(DEV_HOST_msg_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++
++ ptidsl->AppData.FrmMode = (unsigned int)atuc_msg.framingMode;
++ ptidsl->AppData.MaxFrmMode = (unsigned int)atuc_msg.maxFrameMode;
++
++ /* Determine Gross Gain */
++
++ dspOamSharedInterface.aturMsg_p = (DEV_HOST_msg_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.aturMsg_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.aturMsg_p,&aturMsg, sizeof(DEV_HOST_msg_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++ ptidsl->AppData.grossGain = (unsigned int)aturMsg.grossGain;
++ /* Determine DS Line Attenuation & Margin */
++ dspOamSharedInterface.eocVar_p = (DEV_HOST_eocVarDef_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.eocVar_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.eocVar_p,&eocVar, sizeof(DEV_HOST_eocVarDef_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return;
++ }
++
++ ptidsl->AppData.dsLineAttn = (unsigned int)eocVar.lineAtten;
++ ptidsl->AppData.dsMargin = (unsigned int)eocVar.dsMargin;
++ }
++
++#if __HOST_FORINTERNALUSEONLY_R_H__
++ ptidsl->AppData.BER = dslhal_INTERNAL_computeAtmBitErrorRate(ptidsl);
++#endif
++ dprintf(5, "initstatistics done\n");
++ return;
++ }
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_disableLosAlarm(tidsl_t *ptidsl,unsigned int set)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction enables/disables all the LOS alarms
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ * unsigned int set; //if set is TRUE: LOS Alarms are disabled else enabled
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ * NOTES: Currently not supported in any version other than MR4 Patch release..
++ *****************************************************************************************/
++unsigned int dslhal_api_disableLosAlarm(tidsl_t *ptidsl,unsigned int set)
++{
++ DEV_HOST_oamWrNegoParaDef_t NegoPara;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ int rc;
++ dprintf(5," dslhal_api_setTrainingMode()\n");
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,
++ sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.oamWriteNegoParams_p = (DEV_HOST_oamWrNegoParaDef_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.oamWriteNegoParams_p);
++
++ rc = dslhal_support_blockRead((PVOID) dspOamSharedInterface.oamWriteNegoParams_p,&NegoPara, sizeof(DEV_HOST_oamWrNegoParaDef_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ if(set)
++ {
++ NegoPara.disableLosAlarm = TRUE;
++ /* NegoPara.marginMonitorTrning = TRUE;
++ NegoPara.marginMonitorShwtme = TRUE;*/
++ }
++ else
++ {
++ NegoPara.disableLosAlarm = FALSE;
++ /* NegoPara.marginMonitorTrning = FALSE;
++ NegoPara.marginMonitorShwtme = FALSE;*/
++ }
++
++ rc = dslhal_support_blockWrite(&NegoPara,(PVOID)dspOamSharedInterface.oamWriteNegoParams_p, sizeof(DEV_HOST_oamWrNegoParaDef_t));
++ if(rc)
++ return DSLHAL_ERROR_CONFIG_API_FAILURE;
++ dprintf(5," dslhal_api_disableLosAlarm() Done\n");
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_setMarginThreshold(tidsl_t *ptidsl,int threshold)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction does sets the Margin threshold
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ * int threshold
++ *
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_setMarginThreshold(tidsl_t *ptidsl, int threshold)
++{
++ DEV_HOST_oamWrNegoParaDef_t NegoPara;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ int rc;
++
++ dprintf(5," dslhal_ctrl_setThreshold()\n");
++
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.oamWriteNegoParams_p = (DEV_HOST_oamWrNegoParaDef_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.oamWriteNegoParams_p);
++
++
++ rc = dslhal_support_blockRead((PVOID) dspOamSharedInterface.oamWriteNegoParams_p,&NegoPara, sizeof(DEV_HOST_oamWrNegoParaDef_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ NegoPara.marginThreshold = threshold;
++
++ rc = dslhal_support_blockWrite(&NegoPara,dspOamSharedInterface.oamWriteNegoParams_p, sizeof(DEV_HOST_oamWrNegoParaDef_t));
++
++ if(rc)
++ return DSLHAL_ERROR_MARGIN_API_FAILURE;
++
++ dprintf(5," dslhal_api_setThreshold() Done\n");
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_setMonitorFlags(tidsl_t *ptidsl, unsigned int trainflag,unsigned int shwtflag)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction does sets the Margin monitoring flag
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ * unsigned int trainflag
++ * unsigned int shwtflag
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_setMarginMonitorFlags(tidsl_t *ptidsl,unsigned int trainflag,unsigned int shwtflag)
++{
++ DEV_HOST_oamWrNegoParaDef_t NegoPara;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ int rc;
++
++ dprintf(5," dslhal_ctrl_setMonitorFlags()\n");
++
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.oamWriteNegoParams_p = (DEV_HOST_oamWrNegoParaDef_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.oamWriteNegoParams_p);
++
++
++ rc = dslhal_support_blockRead((PVOID) dspOamSharedInterface.oamWriteNegoParams_p,&NegoPara, sizeof(DEV_HOST_oamWrNegoParaDef_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ if (trainflag)
++ {
++ NegoPara.marginMonitorTrning = TRUE;
++ }
++ else
++ {
++ NegoPara.marginMonitorTrning = FALSE;
++ }
++ if (shwtflag)
++ {
++ NegoPara.marginMonitorShwtme = TRUE;
++ }
++ else
++ {
++ NegoPara.marginMonitorShwtme = FALSE;
++ }
++
++ rc = dslhal_support_blockWrite(&NegoPara,dspOamSharedInterface.oamWriteNegoParams_p, sizeof(DEV_HOST_oamWrNegoParaDef_t));
++ if(rc)
++ return DSLHAL_ERROR_MARGIN_API_FAILURE;
++ dprintf(5," dslhal_api_setMonitorFlags() Done\n");
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_setEocSerialNumber(tidsl_t *ptidsl,char *SerialNum)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction Sets the eoc Serial Number
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ * char *SerialNum : Input eoc Serial Number
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_setEocSerialNumber(tidsl_t *ptidsl,char *SerialNumber)
++{
++ DEV_HOST_eocVarDef_t eocVar;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ int rc;
++ dprintf(5," dslhal_api_setEocSerialNumber()\n");
++
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.eocVar_p = (DEV_HOST_eocVarDef_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.eocVar_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.eocVar_p,
++ &eocVar, sizeof(DEV_HOST_eocVarDef_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ shim_osMoveMemory(eocVar.serialNumber,SerialNumber,32);
++
++ rc= dslhal_support_blockWrite(&eocVar,dspOamSharedInterface.eocVar_p,sizeof(DEV_HOST_eocVarDef_t));
++ if(rc)
++ return DSLHAL_ERROR_EOCREG_API_FAILURE;
++ dprintf(5," dslhal_api_setEocSerialNumber() Done\n");
++
++ return DSLHAL_ERROR_NO_ERRORS;
++
++}
++
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_setEocVendorId(tidsl_t *ptidsl,char *VendorID)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction Sets the eoc Vendor ID
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ * char *VendorID : Input eoc Vendor ID
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_setEocVendorId(tidsl_t *ptidsl,char *VendorID)
++{
++ DEV_HOST_oamWrNegoParaDef_t NegoPara;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ int rc;
++ dprintf(5," dslhal_api_setEocVendorId()\n");
++
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.oamWriteNegoParams_p = (DEV_HOST_oamWrNegoParaDef_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.oamWriteNegoParams_p);
++
++
++ rc = dslhal_support_blockRead((PVOID) dspOamSharedInterface.oamWriteNegoParams_p,&NegoPara, sizeof(DEV_HOST_oamWrNegoParaDef_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ shim_osMoveMemory(NegoPara.gdmtVendorId,VendorID,8);
++ rc= dslhal_support_blockWrite(&NegoPara,dspOamSharedInterface.oamWriteNegoParams_p, sizeof(DEV_HOST_oamWrNegoParaDef_t));
++ if(rc)
++ return DSLHAL_ERROR_EOCREG_API_FAILURE;
++
++ dprintf(5," dslhal_api_setEocVendorId() Done\n");
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_setEocRevisionNumber(tidsl_t *ptidsl,char *RevNum)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction Sets the eoc Revision Number
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ * char *RevNum : Input eoc Revision Number
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_setEocRevisionNumber(tidsl_t *ptidsl,char *RevNumber)
++{
++
++ DEV_HOST_eocVarDef_t eocVar;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ int rc;
++ /*add for UR2 test */
++ UINT8 selfTestResults[2];
++ memset(selfTestResults,0x00,sizeof(selfTestResults));
++ /* add for UR2 test */
++ dprintf(5," dslhal_api_setEocRevisionNumber()\n");
++
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.eocVar_p = (DEV_HOST_eocVarDef_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.eocVar_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.eocVar_p,
++ &eocVar, sizeof(DEV_HOST_eocVarDef_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ shim_osMoveMemory(eocVar.revNumber,RevNumber,4);
++ /* add for UR2 test */
++ shim_osMoveMemory(eocVar.dummy,selfTestResults,2);
++ /* add for UR2 test */
++ rc=dslhal_support_blockWrite(&eocVar,dspOamSharedInterface.eocVar_p,sizeof(DEV_HOST_eocVarDef_t));
++ if(rc)
++ return DSLHAL_ERROR_EOCREG_API_FAILURE;
++ dprintf(5," dslhal_api_setEocRevisionNumber Done\n");
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_setAturConfig(tidsl_t *ptidsl,char *ATURConfig)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction Sets the eoc ATUR Config Register
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ * char *ATURConfig : Input eoc ATUR Config Register
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_setAturConfig(tidsl_t *ptidsl,char *ATURConfig)
++{
++
++ DEV_HOST_eocVarDef_t eocVar;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ int rc;
++ dprintf(5," dslhal_api_setAturConfig()\n");
++
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.eocVar_p = (DEV_HOST_eocVarDef_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.eocVar_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.eocVar_p,
++ &eocVar, sizeof(DEV_HOST_eocVarDef_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ shim_osMoveMemory(eocVar.aturConfig,ATURConfig,30);
++ rc= dslhal_support_blockWrite(&eocVar,dspOamSharedInterface.eocVar_p,sizeof(DEV_HOST_eocVarDef_t));
++ if(rc)
++ return DSLHAL_ERROR_EOCREG_API_FAILURE;
++ dprintf(5," dslhal_api_setAturConfig() Done\n");
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_api_setRateAdaptFlag(tidsl_t *ptidsl,unsigned int flag)
++*
++*******************************************************************************************
++* DESCRIPTION: This fuction Sets the Rate Adapt Enable Flag
++*
++* INPUT: PITIDSLHW_T *ptidsl
++* unsigned int flag; //if flag = TRUE set rateadapt flag else reset it
++* RETURN: 0 SUCCESS
++* 1 FAILED
++*
++*****************************************************************************************/
++unsigned int dslhal_api_setRateAdaptFlag(tidsl_t *ptidsl,unsigned int flag)
++{
++ DEV_HOST_msg_t aturMsg;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ int rc;
++ dprintf(5," dslhal_api_setRateAdaptFlag()\n");
++
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.aturMsg_p = (DEV_HOST_msg_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.aturMsg_p);
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.aturMsg_p,
++ &aturMsg, sizeof(DEV_HOST_msg_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ if(flag)
++ aturMsg.rateAdapt = TRUE;
++ else
++ aturMsg.rateAdapt = FALSE;
++
++ rc= dslhal_support_blockWrite(&aturMsg,dspOamSharedInterface.aturMsg_p,sizeof(DEV_HOST_msg_t));
++ if(rc)
++ return DSLHAL_ERROR_CONFIG_API_FAILURE;
++ dprintf(5," dslhal_api_setRateAdaptFlag() Done\n");
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_api_setTrellisFlag(tidsl_t *ptidsl,unsigned int flag)
++*
++*******************************************************************************************
++* DESCRIPTION: This fuction Sets the Trellis Coding Enable Flag
++*
++* INPUT: PITIDSLHW_T *ptidsl
++* unsigned int flag; // if flag = TRUE, set trellis flag else reset
++* RETURN: 0 SUCCESS
++* 1 FAILED
++*
++*****************************************************************************************/
++unsigned int dslhal_api_setTrellisFlag(tidsl_t *ptidsl,unsigned int flag)
++{
++
++ DEV_HOST_msg_t aturMsg;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ DEV_HOST_oamWrNegoParaDef_t negoPara;
++ int rc;
++ dprintf(5," dslhal_api_setTrellisFlag()\n");
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.aturMsg_p = (DEV_HOST_msg_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.aturMsg_p);
++ rc += dslhal_support_blockRead((PVOID)dspOamSharedInterface.aturMsg_p,&aturMsg, sizeof(DEV_HOST_msg_t));
++ dspOamSharedInterface.oamWriteNegoParams_p = (DEV_HOST_oamWrNegoParaDef_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.oamWriteNegoParams_p);
++ rc += dslhal_support_blockRead((PVOID) dspOamSharedInterface.oamWriteNegoParams_p,&negoPara, sizeof(DEV_HOST_oamWrNegoParaDef_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ if(flag)
++ {
++ aturMsg.trellis = TRUE;
++ negoPara.rMsgs1[2] |= 0x02;
++ }
++ else
++ {
++ aturMsg.trellis = FALSE;
++ negoPara.rMsgs1[2] &= 0xFD;
++ }
++ rc=0;
++ rc+=dslhal_support_blockWrite(&aturMsg,dspOamSharedInterface.aturMsg_p,sizeof(DEV_HOST_msg_t));
++ rc+= dslhal_support_blockWrite(&negoPara,dspOamSharedInterface.oamWriteNegoParams_p, sizeof(DEV_HOST_oamWrNegoParaDef_t));
++ if(rc)
++ return DSLHAL_ERROR_CONFIG_API_FAILURE;
++
++ dprintf(5," dslhal_api_setTrellisFlag() Done\n");
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_api_setMaxBitsPerCarrier(tidsl_t *ptidsl,unsigned int maxbits)
++*
++*******************************************************************************************
++* DESCRIPTION: This fuction Sets the Maximum bits per carrier value
++*
++* INPUT: PITIDSLHW_T *ptidsl
++* unsigned int maxbits : should be a value between 0-15
++*
++* RETURN: 0 SUCCESS
++* 1 FAILED
++*
++*****************************************************************************************/
++unsigned int dslhal_api_setMaxBitsPerCarrier(tidsl_t *ptidsl,unsigned int maxbits)
++{
++
++ DEV_HOST_msg_t aturMsg;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ int rc;
++
++ dprintf(5," dslhal_api_setMaxBitsPerCarrier()\n");
++ if(maxbits>15)
++ {
++ dprintf(3,"Maximum Number of Bits per carrier cannot exceed 15!\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.aturMsg_p = (DEV_HOST_msg_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.aturMsg_p);
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.aturMsg_p,
++ &aturMsg, sizeof(DEV_HOST_msg_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ aturMsg.maxBits = maxbits;
++
++ rc=dslhal_support_blockWrite(&aturMsg,dspOamSharedInterface.aturMsg_p,sizeof(DEV_HOST_msg_t));
++ if(rc)
++ return DSLHAL_ERROR_CONFIG_API_FAILURE;
++ dprintf(5," dslhal_api_setMaxBitsPerCarrier() Done\n");
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_api_setMaxInterleaverDepth(tidsl_t *ptidsl,unsigned int maxdepth)
++*
++*******************************************************************************************
++* DESCRIPTION: This fuction Sets the Maximum Interleave Depth Supported
++*
++* INPUT: PITIDSLHW_T *ptidsl
++* unsigned int maxdepth : Should be between 0 and 3 depending on intlv buffer
++* size 64-512
++* RETURN: 0 SUCCESS
++* 1 FAILED
++*
++*****************************************************************************************/
++unsigned int dslhal_api_setMaxInterleaverDepth(tidsl_t *ptidsl,unsigned int maxdepth)
++{
++ DEV_HOST_msg_t aturMsg;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ int rc;
++ dprintf(5," dslhal_api_setMaxInterleaverDepth()\n");
++ if(maxdepth>3)
++ {
++ dprintf(3,"Invalid Value for maximum interleave depth (must be <3)\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.aturMsg_p = (DEV_HOST_msg_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.aturMsg_p);
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.aturMsg_p,
++ &aturMsg, sizeof(DEV_HOST_msg_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ aturMsg.maxIntlvDepth = maxdepth;
++
++ rc=dslhal_support_blockWrite(&aturMsg,dspOamSharedInterface.aturMsg_p,sizeof(DEV_HOST_msg_t));
++ if(rc)
++ return DSLHAL_ERROR_CONFIG_API_FAILURE;
++ dprintf(5," dslhal_api_setMaxInterleaverDepth() Done\n");
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_acknowledgeInterrupt()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_acknowledgeInterrupt(tidsl_t * ptidsl)
++{
++ unsigned int interruptSources=0;
++ /* Clear out the DSLSS Interrupt Registers to acknowledge Interrupt */
++ if(DSLHAL_REG32(dslhal_support_hostDspAddressTranslate(DSP_INTERRUPT_SOURCE_REGISTER))&MASK_MAILBOX_INTERRUPTS)
++ {
++ DSLHAL_REG32(dslhal_support_hostDspAddressTranslate(DSP_INTERRUPT_CLEAR_REGISTER))|=MASK_MAILBOX_INTERRUPTS;
++ dprintf(5,"Mailbox Interrupt \n");
++ }
++ if(DSLHAL_REG32(dslhal_support_hostDspAddressTranslate(DSP_INTERRUPT_SOURCE_REGISTER))&MASK_BITFIELD_INTERRUPTS)
++ {
++ DSLHAL_REG32(dslhal_support_hostDspAddressTranslate(DSP_INTERRUPT_CLEAR_REGISTER))|=MASK_BITFIELD_INTERRUPTS;
++ dprintf(5,"Bitfield Interrupt \n");
++ }
++ if(DSLHAL_REG32(dslhal_support_hostDspAddressTranslate(DSP_INTERRUPT_SOURCE_REGISTER))&MASK_HEARTBEAT_INTERRUPTS)
++ {
++ DSLHAL_REG32(dslhal_support_hostDspAddressTranslate(DSP_INTERRUPT_CLEAR_REGISTER))|=MASK_HEARTBEAT_INTERRUPTS;
++ dprintf(5,"HeartBeat Interrupt \n");
++ }
++ interruptSources = dslhal_support_parseInterruptSource(ptidsl);
++ if(interruptSources < 0)
++ return DSLHAL_ERROR_INTERRUPT_FAILURE;
++ else
++ return interruptSources;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_disableDspHybridSelect()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_disableDspHybridSelect(tidsl_t * ptidsl,unsigned int disable)
++{
++ int rc;
++ DEV_HOST_phyPerf_t phyPerf;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.phyPerf_p = (DEV_HOST_phyPerf_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.phyPerf_p);
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.phyPerf_p,
++ &phyPerf, sizeof(DEV_HOST_phyPerf_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ if(disable==1)
++ {
++ phyPerf.disableDspHybridSelect_f = TRUE;
++ // hybrid_selected = 888;
++ }
++ else
++ {
++ phyPerf.disableDspHybridSelect_f = FALSE;
++ // hybrid_selected = 888;
++ }
++ rc=dslhal_support_blockWrite(&phyPerf,dspOamSharedInterface.phyPerf_p,sizeof(DEV_HOST_phyPerf_t));
++ if(rc)
++ return DSLHAL_ERROR_HYBRID_API_FAILURE;
++ else
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_selectHybrid()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_selectHybrid(tidsl_t * ptidsl,unsigned int hybridNum)
++{
++ int rc;
++ DEV_HOST_phyPerf_t phyPerf;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ if(hybridNum<1||hybridNum>4)
++ {
++ dprintf(3,"Invalid Value for Hybrid Number \n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.phyPerf_p = (DEV_HOST_phyPerf_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.phyPerf_p);
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.phyPerf_p,
++ &phyPerf, sizeof(DEV_HOST_phyPerf_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ phyPerf.hostSelectHybridNum = hybridNum;
++ rc=dslhal_support_blockWrite(&phyPerf,dspOamSharedInterface.phyPerf_p,sizeof(DEV_HOST_phyPerf_t));
++ if(rc)
++ return DSLHAL_ERROR_HYBRID_API_FAILURE;
++ else
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_reportHybridMetrics()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_reportHybridMetrics(tidsl_t * ptidsl,int *metric)
++{
++ int rc,i;
++ DEV_HOST_phyPerf_t phyPerf;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ if(hybrid_selected>5)
++ {
++ dprintf(4,"Hybrid Metrics Not Yet Available \n");
++ }
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return (0-DSLHAL_ERROR_INVALID_PARAM);
++ }
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return (0-DSLHAL_ERROR_BLOCK_READ);
++ }
++
++ dspOamSharedInterface.phyPerf_p = (DEV_HOST_phyPerf_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.phyPerf_p);
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.phyPerf_p,
++ &phyPerf, sizeof(DEV_HOST_phyPerf_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return (0-DSLHAL_ERROR_BLOCK_READ);
++ }
++ rc = sizeof(phyPerf.hybridCost);
++ for(i=0;i<(rc/4);i++)
++ {
++ metric[i] = dslhal_support_byteSwap32(phyPerf.hybridCost[i]);
++ }
++ return hybrid_selected;
++}
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_selectInnerOuterPair(tidsl_t *ptidsl,unsigned int pairSelect)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction selects inner/outer pair on RJ11.
++ *
++ * INPUT: PITIDSLHW_T *ptidsl , unsigned int pairSelect
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_selectInnerOuterPair(tidsl_t *ptidsl,unsigned int pairSelect)
++{
++ int rc;
++
++ dprintf(5, "dslhal_api_sendQuiet\n");
++ rc = dslhal_support_writeHostMailbox(ptidsl, HOST_RJ11SELECT, (unsigned int)pairSelect, 0, 0);
++ if(rc)
++ {
++ dprintf(1,"dslhal_api_sendQuiet failed\n");
++ return DSLHAL_ERROR_CTRL_API_FAILURE;
++ }
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_resetTrainFailureLog(tidsl_t *ptidsl)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction resets the failed state log stored
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_resetTrainFailureLog(tidsl_t *ptidsl)
++{
++
++ int rc;
++ dprintf(5, "dslhal_api_resetTrainFailureLog \n");
++ for(rc=0;rc<ptidsl->AppData.trainFails;rc++)
++ {
++ ptidsl->AppData.trainFailStates[rc]=0;
++ }
++ ptidsl->AppData.trainFails = 0;
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_configureLed()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_configureLed(tidsl_t * ptidsl,unsigned int idLed, unsigned int onOff)
++{
++ int rc;
++ DEV_HOST_modemEnvPublic_t modemEnv;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ if(idLed>2 || onOff>2)
++ {
++ dprintf(3,"Invalid input parameter \n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.modemEnvPublic_p = (DEV_HOST_modemEnvPublic_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.modemEnvPublic_p);
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.modemEnvPublic_p,
++ &modemEnv, sizeof(DEV_HOST_modemEnvPublic_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ if(idLed==ID_DSL_LINK_LED)
++ {
++ modemEnv.overrideDslLinkLed_f = TRUE;
++ if(onOff!=2)
++ modemEnv.dslLinkLedState_f = onOff;
++ }
++ if(idLed==ID_DSL_ACT_LED)
++ {
++ modemEnv.overrideDslLinkLed_f = TRUE;
++ if(onOff!=2)
++ modemEnv.dslLinkLedState_f = onOff;
++ }
++ if(idLed==ID_RESTORE_DEFAULT_LED)
++ {
++ modemEnv.overrideDslLinkLed_f = FALSE;
++ modemEnv.overrideDslActLed_f = FALSE;
++ }
++ rc=dslhal_support_blockWrite(&modemEnv,dspOamSharedInterface.modemEnvPublic_p,sizeof(DEV_HOST_modemEnvPublic_t));
++ if(rc)
++ return DSLHAL_ERROR_MODEMENV_API_FAILURE;
++ else
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_configureExternBert()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_configureExternBert(tidsl_t * ptidsl,unsigned int configParm, unsigned int parmVal)
++{
++ int rc;
++ DEV_HOST_modemEnvPublic_t modemEnv;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ if(configParm>1 || parmVal>1)
++ {
++ dprintf(3,"Invalid input parameter \n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.modemEnvPublic_p = (DEV_HOST_modemEnvPublic_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.modemEnvPublic_p);
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.modemEnvPublic_p,
++ &modemEnv, sizeof(DEV_HOST_modemEnvPublic_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ if(configParm==0)
++ {
++ modemEnv.externalBert = parmVal;
++ }
++ if(configParm==1)
++ {
++ modemEnv.usBertPattern = parmVal;
++ }
++ rc=dslhal_support_blockWrite(&modemEnv,dspOamSharedInterface.modemEnvPublic_p,sizeof(DEV_HOST_modemEnvPublic_t));
++ if(rc)
++ return DSLHAL_ERROR_MODEMENV_API_FAILURE;
++ else
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_configureAtmBert()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_configureAtmBert(tidsl_t * ptidsl,unsigned int configParm, unsigned int parmVal)
++{
++ int rc;
++ DEV_HOST_atmDsBert_t atmDsBert;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ if(configParm>1 || parmVal>1)
++ {
++ dprintf(3,"Invalid input parameter \n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.atmDsBert_p = (DEV_HOST_atmDsBert_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.atmDsBert_p);
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.atmDsBert_p,
++ &atmDsBert, sizeof(DEV_HOST_atmDsBert_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ if(configParm==0)
++ {
++ atmDsBert.atmBertFlag = parmVal;
++ rc=dslhal_support_blockWrite(&atmDsBert,dspOamSharedInterface.atmDsBert_p,sizeof(DEV_HOST_atmDsBert_t));
++ if(rc)
++ return DSLHAL_ERROR_CONFIG_API_FAILURE;
++ }
++ if(configParm==1)
++ {
++ ptidsl->AppData.atmBertBitCountLow = atmDsBert.bitCountLow;
++ ptidsl->AppData.atmBertBitCountHigh = atmDsBert.bitCountHigh;
++ ptidsl->AppData.atmBertBitErrorCountLow = atmDsBert.bitErrorCountLow;
++ ptidsl->AppData.atmBertBitErrorCountHigh = atmDsBert.bitErrorCountHigh;
++ }
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_configureDgaspLpr()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Configures dying gasp LPR signal
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_configureDgaspLpr(tidsl_t * ptidsl,unsigned int configParm, unsigned int parmVal)
++{
++ int rc;
++ DEV_HOST_modemEnvPublic_t modemEnv;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ if(configParm>1 || parmVal>1)
++ {
++ dprintf(3,"Invalid input parameter \n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ if(!ptidsl)
++ {
++ dprintf(3, "Error: PTIDSL pointer invalid\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.modemEnvPublic_p = (DEV_HOST_modemEnvPublic_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.modemEnvPublic_p);
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.modemEnvPublic_p,
++ &modemEnv, sizeof(DEV_HOST_modemEnvPublic_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ if(configParm==0)
++ {
++ modemEnv.dGaspLprIndicator_f = parmVal;
++ }
++ if(configParm==1)
++ {
++ modemEnv.overrideDspLprGasp_f = parmVal;
++ }
++ rc=dslhal_support_blockWrite(&modemEnv,dspOamSharedInterface.modemEnvPublic_p,sizeof(DEV_HOST_modemEnvPublic_t));
++ if(rc)
++ return DSLHAL_ERROR_MODEMENV_API_FAILURE;
++ else
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_genericDspRead()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Reads from a Generic Location in the DSP Host Interface
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_genericDspRead(tidsl_t * ptidsl,unsigned int offset1, unsigned int offset2,
++ unsigned int offset3, unsigned char *localBuffer, unsigned int numBytes)
++{
++ int rc=0;
++ unsigned int hostIfLoc,structLoc,elementLoc;
++ hostIfLoc = (unsigned int)ptidsl->pmainAddr;
++ if(numBytes<=0 || !localBuffer || !ptidsl)
++ {
++ dprintf(3,"Invalid input parameter \n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++ rc += dslhal_support_blockRead((PVOID)(hostIfLoc+sizeof(int)*offset1), &structLoc,sizeof(int));
++ structLoc = dslhal_support_byteSwap32(structLoc);
++ rc += dslhal_support_blockRead((PVOID)(structLoc+sizeof(int)*offset2), &elementLoc,sizeof(int));
++ elementLoc = dslhal_support_byteSwap32(elementLoc);
++ dprintf(3,"Host IF Location: 0x%x Struct1 Location: 0x%x Element Location: 0x%x \n",hostIfLoc, structLoc, elementLoc);
++ rc += dslhal_support_blockRead((PVOID)(elementLoc+(offset3*4)), localBuffer,numBytes);
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_READ;
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_genericDspWrite()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Writes to a Generic Location in the DSP Host Interface
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_genericDspWrite(tidsl_t * ptidsl,unsigned int offset1, unsigned int offset2,
++ unsigned int offset3, unsigned char *localBuffer, unsigned int numBytes)
++{
++
++ int rc=0;
++ unsigned int hostIfLoc,structLoc,elementLoc;
++ hostIfLoc = (unsigned int)ptidsl->pmainAddr;
++ if(numBytes<=0 || !localBuffer || !ptidsl)
++ {
++ dprintf(3,"Invalid input parameter \n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++ rc += dslhal_support_blockRead((PVOID)(hostIfLoc+(offset1*4)), &structLoc,4);
++ structLoc = dslhal_support_byteSwap32(structLoc);
++ rc += dslhal_support_blockRead((PVOID)(structLoc+(offset2*4)), &elementLoc,4);
++ elementLoc = dslhal_support_byteSwap32(elementLoc);
++ dprintf(3,"Host IF Location: 0x%x Struct1 Location: 0x%x Element Location: 0x%x \n",hostIfLoc, structLoc, elementLoc);
++ rc += dslhal_support_blockWrite(localBuffer,(PVOID)(elementLoc+(offset3*4)),numBytes);
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_READ;
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_dspInterfaceRead()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Reads from a Generic Location in the DSP Host Interface
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_dspInterfaceRead(tidsl_t * ptidsl,unsigned int baseAddr, unsigned int numOffsets,
++ unsigned int *offsets, unsigned char *localBuffer, unsigned int numBytes)
++{
++ int rc=0, off=0;
++ unsigned int prevAddr,currAddr;
++ prevAddr = baseAddr;
++ if(numBytes<=0 || !localBuffer || !ptidsl || !offsets)
++ {
++ dprintf(3,"Invalid input parameter \n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++ for(off=0;off<numOffsets-1;off++)
++ {
++ rc += dslhal_support_blockRead((PVOID)(prevAddr+(4*offsets[off])), &currAddr,4);
++ currAddr = dslhal_support_byteSwap32(currAddr);
++ prevAddr = currAddr;
++ dprintf(5,"Curr Addr = 0x%x Current Level: %d \n",currAddr,off);
++ }
++ currAddr = currAddr + offsets[numOffsets-1]*4;
++ rc += dslhal_support_blockRead((PVOID)(currAddr),localBuffer,numBytes);
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_READ;
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_dspInterfaceWrite()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Writes to a Generic Location in the DSP Host Interface
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_dspInterfaceWrite(tidsl_t * ptidsl,unsigned int baseAddr, unsigned int numOffsets,
++ unsigned int *offsets,unsigned char *localBuffer, unsigned int numBytes)
++{
++
++ int rc=0, off=0;
++ unsigned int prevAddr,currAddr;
++ prevAddr = baseAddr;
++ if(numBytes<=0 || !localBuffer || !ptidsl || !offsets)
++ {
++ dprintf(3,"Invalid input parameter \n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++ for(off=0;off<numOffsets-1;off++)
++ {
++ rc += dslhal_support_blockRead((PVOID)(prevAddr+(4*offsets[off])), &currAddr,4);
++ currAddr = dslhal_support_byteSwap32(currAddr);
++ prevAddr = currAddr;
++ dprintf(5,"Curr Addr = 0x%x Current Level: %d \n",currAddr,off);
++ }
++ currAddr = currAddr + offsets[numOffsets-1]*4;
++ rc += dslhal_support_blockWrite(localBuffer,(PVOID)(currAddr),numBytes);
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_READ;
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_sendMailboxCommand(tidsl_t *ptidsl, unsigned int cmd)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction sends the passed mailbox command to the DSP
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ * unsigned int cmd
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++/* Function is commented out for now since, its not tested */
++ /*unsigned int dslhal_api_sendMailboxCommand(tidsl_t *ptidsl, unsigned int cmd)
++{
++ int rc;
++
++ dprintf(5, "dslhal_api_sendMailboxCommand\n");
++ rc = dslhal_support_writeHostMailbox(ptidsl, cmd, 0, 0, 0);
++ if(rc)
++ {
++ dprintf(1,"dslhal_api_sendMailboxCommand failed\n");
++ return DSLHAL_ERROR_CTRL_API_FAILURE;
++ }
++ return DSLHAL_ERROR_NO_ERRORS;
++} */
++
++
+diff -urN linux.old/drivers/atm/sangam_atm/dsl_hal_api.h linux.dev/drivers/atm/sangam_atm/dsl_hal_api.h
+--- linux.old/drivers/atm/sangam_atm/dsl_hal_api.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/dsl_hal_api.h 2005-08-23 04:46:50.097843696 +0200
+@@ -0,0 +1,1721 @@
++#ifndef __DSL_HAL_API_H__
++#define __DSL_HAL_API_H__ 1
++/*******************************************************************************
++* FILE PURPOSE: DSL HAL to Application Interface for Sangam
++*
++********************************************************************************
++* FILE NAME: dsl_application_interface.h
++*
++* DESCRIPTION:
++* DSL-Application Interface Structures
++*
++*
++* By: Ramakrishnan Parasuraman
++*
++* (C) Copyright 2003, Texas Instruments, Inc.
++* History
++* Data Version By Notes
++* 06Feb03 0.00 RamP Initial Version Written
++* 07Apr03 0.01 RamP Commented out typedefs
++* 09Apr03 0.02 RamP Added deviceContext and extended
++* dspVer to include bugfixes
++* 14Apr03 0.03 RamP Added stateTransition to structure
++* 16Apr03 0.04 RamP Removed typedefs; changed dspVer
++* 22Apr03 0.05 RamP Moved acknowledgeInterrupt from
++* (alpha) support module into this
++* 24Apr03 0.06 RamP Moved the RSTATE enum from register
++*
++* 28Apr03 0.07 RamP Added additional parameter to the
++* (alpha +) handleInterrupt function for intrSrc
++* 14May03 0.08 RamP Added hybrid switching APIs
++* (alpha ++) Added statistics fields in AppData
++* Added netService identifier
++* 20May03 0.09 RamP Added Inner/Outer pair API support.
++* Added dying gasp message.
++* 29May03 0.10 RamP Added coProfile structure
++* 04Jun03 0.11 RamP Added margin per tone statistics,
++* Added timing counters, added train
++* failure functions,added config flags
++* 06Jun03 0.12 RamP Added LED, STM Bert, dGasp LPR
++* config API functions
++* 09Jun03 0.13 RamP Added ATM Bert function, CO stats
++* Moved stateTransition to ITIDSLHW
++* (Beta) Moved configFlag to ITIDSLHW,
++* Cleaned up fifoInfo structure
++* Added US/DS R/S FEC parameters
++* 21Aug03 0.14 RamP Added g.hs message buffer, us/ds
++* bits n gains table, negoMsgs struct
++* (act) bitswap stucts/indices, trainstate,
++* Added functions for advanced config
++* Added gross gain and line length
++* 29Sep03 0.15 RamP Added tokens for advanced config
++* module api functions
++* 12Oct03 0.16 RamP Added adsl2Msgs structure with worst
++* case size for variable length msgs
++* Added API function prototypes
++* 21Oct03 0.17 RamP Added typedef for current modem
++* user settings
++* 28Oct03 0.18 RamP Added function to config blackout
++* bitmap in the RMSGPCB message
++* 20Nov03 0.19 RamP Added functions for generic and
++* host interface read - write
++* 24Nov03 0.20 RamP Added enum for detailed state track
++* Added element for state bit fields
++* Addded rState for encoded main state
++* Added blackout valid flag
++* 26Dec03 0.21 RamP Added defines for oamFeature masks
++* 30Dec03 0.22 RamP Increased sizes for cMsgPcb,RMsgPcb
++* to incorporate DELT mode messages
++* 30Dec03 0.23 RamP Added generic mailbox command fxn
++*******************************************************************************/
++
++#ifdef INTERNAL_BUILD
++#include <dsl_hal_api_pvt.h>
++#endif
++
++#define NUM_PAGES 4
++#define OAMFEATURE_AUTORETRAIN_MASK 0x00000001
++#define OAMFEATURE_TC_SYNC_DETECT_MASK 0x00000002
++#define OAMFEATURE_EOCAOC_INTERRUPT_MASK 0x00000004
++#define OAMFEATURE_CONS_DISP_DISABLE_MASK 0x00000008
++#define OAMFEATURE_GHSMSG_INTERRUPT_MASK 0x00000010
++
++typedef struct tagTIOIDINFO
++{
++ unsigned int bState; /* addr->bDSPATURState */
++ unsigned int USConRate; /* US Conection Rates */
++ unsigned int DSConRate; /* DS Connection Rates */
++ unsigned int USPayload; /* ennic_tx_pullup*/
++ unsigned int DSPayload; /* ennic_indicate_receive_packet*/
++ unsigned int FrmMode; /* addr->atur_msg.framing_mode*/
++ unsigned int MaxFrmMode;
++ unsigned int TrainedPath; /* Status of the Modem in which trained (Fast or Interleaved Path) */
++ unsigned int TrainedMode; /* Status of the mode in which the modem is trained (G.dmt, T1.413, etc) */
++
++ /* Superframe Count */
++ unsigned int usSuperFrmCnt; /* Num of US Superframes */
++ unsigned int dsSuperFrmCnt; /* Num of DS Superframes */
++
++ /* LOS & SEF Stats */
++ unsigned int LOS_errors; /* Num of ADSL frames where loss-of-sync */
++ unsigned int SEF_errors; /* Num of severly errored ADSL frames - LOS > MAXBADSYNC ADSL frames */
++ unsigned int coLosErrors; /* CO LOS Defects */
++ unsigned int coRdiErrors; /* CO RDI defects */
++ /* CRC Stats */
++ unsigned int usICRC_errors; /* Num of Upstream CRC errored ADSL frames on Interleaved Path */
++ unsigned int usFCRC_errors; /* Num of Upstream CRC errored ADSL frames on Fast Path */
++ unsigned int dsICRC_errors; /* Num of Downstream CRC errored ADSL frames on Interleaved Path */
++ unsigned int dsFCRC_errors; /* Num of Downstream CRC errored ADSL frames on Fast Path */
++
++ /* FEC Stats */
++ unsigned int usIFEC_errors; /* Num of Upstream FEC errored (corrected) ADSL frames on Interleaved Path */
++ unsigned int usFFEC_errors; /* Num of Upstream FEC errored (corrected) ADSL frames on Fast Path */
++ unsigned int dsIFEC_errors; /* Num of Downstream FEC errored (corrected) ADSL frames on Interleaved Path */
++ unsigned int dsFFEC_errors; /* Num of Downstream FEC errored (corrected) ADSL frames on Fast Path */
++
++ /* NCD Stats */
++ unsigned int usINCD_error; /* UpStream No Cell Delineation on Interleaved Path */
++ unsigned int usFNCD_error; /* UpStream No Cell Delineation on Fast Path */
++ unsigned int dsINCD_error; /* Downstream No Cell Delineation on Interleaved Path */
++ unsigned int dsFNCD_error; /* Downstream No Cell Delineation on Fast Path */
++
++ /* LCD Stats */
++ unsigned int usILCD_errors; /* UpStream Loss of Cell Delineation (within the same connection) on Interleaved Path */
++ unsigned int usFLCD_errors; /* UpStream Loss of Cell Delineation (within the same connection) on Fast Path */
++ unsigned int dsILCD_errors; /* Downstream Loss of Cell Delineation (within the same connection) on Interleaved Path */
++ unsigned int dsFLCD_errors; /* Downstream Loss of Cell Delineation (within the same connection) on Fast Path */
++
++ /* HEC Stats */
++ unsigned int usIHEC_errors; /* Num of Upstream HEC errored ADSL frames on Interleaved Path */
++ unsigned int usFHEC_errors; /* Num of Upstream HEC errored ADSL frames on Fast Path */
++ unsigned int dsIHEC_errors; /* Num of Downstream HEC errored ADSL frames on Interleaved Path */
++ unsigned int dsFHEC_errors; /* Num of Downstream HEC errored ADSL frames on Fast Path */
++
++ /* Upstream ATM Stats */
++ unsigned int usAtm_count[2]; /* Upstream Good Cell Count */
++ unsigned int usIdle_count[2]; /* Upstream Idle Cell Count */
++ unsigned int usPdu_count[2]; /* UpStream PDU Count */
++
++ /* Downstream ATM Stats */
++ unsigned int dsGood_count[2]; /* Downstream Good Cell Count */
++ unsigned int dsIdle_count[2]; /* Downstream Idle Cell Count */
++ unsigned int dsBadHec_count[2]; /* Downstream Bad Hec Cell Count */
++ unsigned int dsOVFDrop_count[2]; /* Downstream Overflow Dropped Cell Count */
++ unsigned int dsPdu_count[2]; /* Downstream PDU Count */
++ /* (only looks for end of pdu on good atm cells received, */
++ /* not on Bad_Hec or Overflow cell) */
++
++ unsigned int dsLineAttn; /* DS Line Attenuation */
++ unsigned int dsMargin; /* Measured DS MArgin */
++
++ unsigned int usLineAttn;
++ unsigned int usMargin;
++
++ unsigned char bCMsgs1[6];
++ unsigned char bRMsgs1[6];
++ unsigned char bCRates2;
++ unsigned char bRRates2;
++ unsigned char bRRates1[4][11];
++ unsigned char bCMsgs2[4];
++ unsigned char bCRates1[4][30];
++ unsigned char bRMsgs2[4];
++
++ unsigned int USPeakCellRate;
++
++ unsigned int dsl_status;
++ unsigned int dsl_modulation;
++ unsigned char dsl_ghsRxBuf[10][64];
++ unsigned char dsl_GHS_msg_type[2];
++
++ int TxVCs[12];
++ int RxVCs[12];
++
++ unsigned int vci_vpi_val;
++
++ unsigned char BitAllocTblDstrm[256];
++ unsigned char BitAllocTblUstrm[32];
++ signed char marginTblDstrm[256];
++ unsigned char rBng[512];
++ unsigned char cBng[126];
++ int usTxPower;
++ int dsTxPower;
++ short rxSnrPerBin0[256];
++ short rxSnrPerBin1[256];
++ short rxSnrPerBin2[256];
++
++ unsigned int StdMode;
++ unsigned int atucVendorId;
++ unsigned char currentHybridNum;
++ unsigned char atucRevisionNum;
++ unsigned int trainFails;
++ unsigned int trainFailStates[30];
++ unsigned int idleTick;
++ unsigned int initTick;
++ unsigned int showtimeTick;
++ unsigned char dsFastParityBytesPerSymbol;
++ unsigned char dsIntlvParityBytesPerSymbol;
++ unsigned char dsSymbolsPerCodeWord;
++ unsigned int dsInterleaverDepth;
++ unsigned char usFastParityBytesPerSymbol;
++ unsigned char usIntlvParityBytesPerSymbol;
++ unsigned char usSymbolsPerCodeWord;
++ unsigned int usInterleaverDepth;
++ unsigned int atmBertBitCountLow;
++ unsigned int atmBertBitCountHigh;
++ unsigned int atmBertBitErrorCountLow;
++ unsigned int atmBertBitErrorCountHigh;
++ unsigned int lineLength;
++ unsigned int grossGain;
++ int rxNoisePower0[256];
++ int rxNoisePower1[256];
++}TIOIDINFO,*PTIOIDINFO;
++
++typedef struct{
++ unsigned char bCMsgs1[6];
++ unsigned char bCRates2;
++ unsigned char bRRates2;
++ unsigned char bRRates1[4][11];
++ unsigned char bCMsgs2[4];
++ unsigned char bCRates1[4][30];
++ unsigned char bCRatesRA[4][30];
++ unsigned char bRMsgs2[4];
++ unsigned char bRRatesRA[4];
++ unsigned char bRMsgsRA[12];
++ unsigned char bCMsgsRA[6];
++}negoMsgs;
++
++typedef struct{
++ unsigned char cMsgFmt[2];
++ unsigned char rMsgFmt[2];
++ unsigned char cMsgPcb[12];
++ unsigned char rMsgPcb[70];
++ unsigned char dummy1[2];
++ unsigned char cMsg1[40];
++ unsigned char rMsg1[4];
++ unsigned char cMsg2[8];
++ unsigned char rMsg2[64];
++ unsigned char cParams[264];
++ unsigned char rParams[2088];
++ unsigned short cMsgPcbLen;
++ unsigned short rMsgPcbLen;
++ unsigned short cMsg1Len;
++ unsigned short rMsg1Len;
++ unsigned short cMsg2Len;
++ unsigned short rMsg2Len;
++ unsigned short cParamsLen;
++ unsigned short rParamsLen;
++}adsl2Msgs;
++
++typedef struct{
++ unsigned char rMsg1Ld[16];
++ unsigned char rMsg2Ld[260];
++ unsigned char rMsg3Ld[260];
++ unsigned char rMsg4Ld[260];
++ unsigned char rMsg5Ld[260];
++ unsigned char rMsg6Ld[260];
++ unsigned char rMsg7Ld[260];
++ unsigned char rMsg8Ld[260];
++ unsigned char rMsg9Ld[260];
++ unsigned char cMsg1Ld[16];
++ unsigned char cMsg2Ld[260];
++ unsigned char cMsg3Ld[132];
++ unsigned char cMsg4Ld[68];
++ unsigned char cMsg5Ld[68];
++ unsigned short rMsg1LdLen;
++ unsigned short rMsgxLdLen;
++ unsigned short cMsg1LdLen;
++ unsigned short cMsg2LdLen;
++ unsigned short cMsg3LdLen;
++ unsigned short cMsg4LdLen;
++ unsigned short cMsg5LdLen;
++ unsigned short dummy8;
++}adsl2DeltMsgs;
++
++typedef struct{
++ unsigned char trellisFlag;
++ unsigned char rateAdaptFlag;
++ unsigned char marginMonitorTraining;
++ unsigned char marginMonitorShowtime;
++ signed char marginThreshold;
++ unsigned char disableLosFlag;
++ unsigned char aturConfig[30];
++ unsigned char eocVendorId[8];
++ unsigned char eocSerialNumber[32];
++ unsigned char eocRevisionNumber[4];
++}currentPhySettings;
++
++
++typedef struct
++{
++ unsigned int PmemStartWtAddr; /* source address in host memory */
++ unsigned int OverlayXferCount; /* number of 32bit words to be transfered */
++ unsigned int BinAddr; /* destination address in dsp's pmem */
++ unsigned int overlayHostAddr;
++ unsigned int olayPageCrc32;
++ unsigned int SecOffset;
++} OlayDP_Def;
++
++typedef struct
++{
++ unsigned int timeStamp; /* TimeStp revision */
++ unsigned char major; /* Major revision */
++ unsigned char minor; /* Minor revision */
++ unsigned char bugFix; /* BugFix revision */
++ unsigned char buildNum; /* BuildNum revision */
++ unsigned char reserved; /* for future use */
++}dspVer;
++
++typedef struct{
++ unsigned char major;
++ unsigned char minor;
++ unsigned char bugfix;
++ unsigned char buildNum;
++ unsigned int timeStamp;
++}dslVer;
++
++typedef struct{
++ unsigned char bitSwapCommand[6];
++ unsigned char bitSwapBinNum[6];
++ unsigned char bitSwapSFrmCnt;
++}dslBitSwapDef;
++
++typedef struct{
++ unsigned int aturState;
++ unsigned int subStateIndex;
++ unsigned int timeStamp;
++}trainStateInfo;
++
++typedef struct{
++ unsigned char ctrlBits;
++ unsigned char infoBits;
++}eocMessageDef;
++
++enum
++{
++ RSTATE_TEST,
++ RSTATE_IDLE,
++ RSTATE_INIT,
++ RSTATE_HS,
++ RSTATE_RTDL,
++ RSTATE_SHOWTIME,
++};
++
++typedef enum
++{
++ ATU_RZERO1 = 100,
++ ATU_RTEST = 101,
++ ATU_RIDLE = 102,
++ ATU_RINIT = 103,
++ ATU_RRESET = 104,
++ GDMT_NSFLR = 105,
++ GDMT_TONE = 106,
++ GDMT_SILENT = 107,
++ GDMT_NEGO = 108,
++ GDMT_FAIL = 109,
++ GDMT_ACKX = 110,
++ GDMT_QUIET2 = 111,
++ ATU_RZERO2 = 200,
++ T1413_NSFLR = 201,
++ T1413_ACTREQ = 202,
++ T1413_ACTMON = 203,
++ T1413_FAIL = 204,
++ T1413_ACKX = 205,
++ T1413_QUIET2 = 206,
++ ATU_RQUIET2 = 207,
++ ATU_RREVERB1 = 208,
++ ATU_RQUIET3 = 209,
++ ATU_RECT = 210,
++ ATU_RREVERB2 = 211,
++ ATU_RSEGUE1 = 212,
++ ATU_RREVERB3 = 213,
++ ATU_RSEGUE2 = 214,
++ ATU_RRATES1 = 215,
++ ATU_RMSGS1 = 216,
++ ATU_RMEDLEY = 217,
++ ATU_RREVERB4 = 218,
++ ATU_RSEGUE3 = 219,
++ ATU_RMSGSRA = 220,
++ ATU_RRATESRA = 221,
++ ATU_RREVERBRA = 222,
++ ATU_RSEGUERA = 223,
++ ATU_RMSGS2 = 224,
++ ATU_RRATES2 = 225,
++ ATU_RREVERB5 = 226,
++ ATU_RSEGUE4 = 227,
++ ATU_RBNG = 228,
++ ATU_RREVERB6 = 229,
++ ATU_RSHOWTIME = 230,
++ ATU_RZERO3 = 300,
++ ADSL2_QUIET1 = 301,
++ ADSL2_COMB1 = 302,
++ ADSL2_QUIET2 = 303,
++ ADSL2_COMB2 = 304,
++ ADSL2_ICOMB1 = 305,
++ ADSL2_LINEPROBE = 306,
++ ADSL2_QUIET3 = 307,
++ ADSL2_COMB3 = 308,
++ ADSL2_ICOMB2 = 309,
++ ADSL2_RMSGFMT = 310,
++ ADSL2_RMSGPCB = 311,
++ ADSL2_REVERB1 = 312,
++ ADSL2_QUIET4 = 313,
++ ADSL2_REVERB2 = 314,
++ ADSL2_QUIET5 = 315,
++ ADSL2_REVERB3 = 316,
++ ADSL2_ECT = 317,
++ ADSL2_REVERB4 = 318,
++ ADSL2_SEGUE1 = 319,
++ ADSL2_REVERB5 = 320,
++ ADSL2_SEGUE2 = 321,
++ ADSL2_RMSG1 = 322,
++ ADSL2_MEDLEY = 323,
++ ADSL2_EXCHANGE = 324,
++ ADSL2_RMSG2 = 325,
++ ADSL2_REVERB6 = 326,
++ ADSL2_SEGUE3 = 327,
++ ADSL2_RPARAMS = 328,
++ ADSL2_REVERB7 = 329,
++ ADSL2_SEGUE4 = 330,
++ ATU_RZERO4 = 400,
++ DELT_SEGUE1 = 401,
++ DELT_REVERB5 = 402,
++ DELT_SEGUE2 = 403,
++ DELT_EXCHANGE = 404,
++ DELT_SEGUELD = 405,
++ DELT_RMSGLD = 406,
++ DELT_QUIET1LD = 407,
++ DELT_QUIET2LD = 408,
++ DELT_RACK1 = 409,
++ DELT_RNACK1 = 410,
++ DELT_QUIETLAST = 411
++} modemStates_t;
++
++enum
++{
++ DSLTRAIN_NO_MODE,
++ DSLTRAIN_MULTI_MODE,
++ DSLTRAIN_T1413_MODE,
++ DSLTRAIN_GDMT_MODE,
++ DSLTRAIN_GLITE_MODE
++};
++
++enum
++{
++ ID_RESTORE_DEFAULT_LED,
++ ID_DSL_LINK_LED,
++ ID_DSL_ACT_LED
++};
++
++typedef struct _ITIDSLHW
++{
++ /* struct _TIDSL_IHwVtbl * pVtbl; */
++ unsigned char* fwimage;
++ void* pmainAddr;
++ void* pOsContext;
++ unsigned int ReferenceCount;
++ unsigned int netService;
++
++ int InitFlag;
++
++ int imagesize;
++
++ unsigned int lConnected;
++ unsigned int bStatisticsInitialized;
++ unsigned int rState;
++ unsigned int bShutdown;
++ unsigned int blackOutValid_f;
++ unsigned char blackOutBits[64];
++ unsigned int bAutoRetrain;
++ volatile unsigned int bOverlayPageLoaded;
++ unsigned int stateTransition;
++ unsigned int configFlag;
++ unsigned int dsBitSwapInx;
++ unsigned int usBitSwapInx;
++ unsigned int trainStateInx;
++ unsigned int usEocMsgInx;
++ unsigned int dsEocMsgInx;
++ unsigned int reasonForDrop;
++ TIOIDINFO AppData;
++ dspVer dspVer;
++
++ OlayDP_Def olayDpPage[NUM_PAGES];
++ OlayDP_Def coProfiles;
++ OlayDP_Def constDisplay;
++ dslBitSwapDef dsBitSwap[30];
++ dslBitSwapDef usBitSwap[30];
++ trainStateInfo trainHistory[120];
++ eocMessageDef usEocMsgBuf[30];
++ eocMessageDef dsEocMsgBuf[30];
++ adsl2Msgs adsl2TrainingMessages;
++ adsl2DeltMsgs adsl2DiagnosticMessages;
++ unsigned int modemStateBitField[4];
++#ifdef INTERNAL_BUILD
++ internalParameters internalVars;
++#endif
++} ITIDSLHW_T, *PITIDSLHW_T, tidsl_t;
++
++
++/**********************************************************************************
++* API proto type defines
++**********************************************************************************/
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_api_dslStartup
++*
++*******************************************************************************************
++* DESCRIPTION: Entry point to initialize and load ax5 daughter board
++*
++* INPUT: PITIDSLHW_T *ppIHw
++*
++* RETURN: 0 --succeeded
++* 1 --Failed
++*
++* Notes: external function osAllocateMemory(), osZeroMemory(), osLoadFWImage() are required
++*****************************************************************************************/
++int dslhal_api_dslStartup
++(
++ PITIDSLHW_T *ppIHw
++);
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_gatherStatistics
++*
++*********************************************************************************************
++* DESCRIPTION: Read statistical infromation from ax5 modem daugter card.
++* Input: tidsl_t *ptidsl
++*
++* Return: 0 success
++* 1 failed
++*
++********************************************************************************************/
++
++void dslhal_api_gatherStatistics
++(
++ tidsl_t * ptidsl
++);
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_initStatistics
++*
++*********************************************************************************************
++* DESCRIPTION: init statistical infromation of ax5 modem daugter card.
++*
++* Input: tidsl_t *ptidsl
++*
++* Return: NULL
++*
++********************************************************************************************/
++
++void dslhal_api_initStatistics
++(
++ tidsl_t * ptidsl
++);
++
++
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_api_getDslDriverVersion
++*
++*******************************************************************************************
++* DESCRIPTION: This routine supply DSL Driver version.
++*
++* INPUT: tidsl_t * ptidsl
++* void *pVer, DSP Driver Version Pointer
++*
++* RETURN: 0 --succeeded
++* 1 --Failed
++* Note: See verdef_u.h for version structure definition.
++*****************************************************************************************/
++
++void dslhal_api_getDslHalVersion
++(
++ void *pVer
++);
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_api_dslShutdown
++*
++*******************************************************************************************
++* DESCRIPTION: routine to shutdown ax5 modem and free the resource
++*
++* INPUT: tidsl_t *ptidsl
++*
++* RETURN: NULL
++*
++* Notes: external function osFreeMemory() is required.
++*****************************************************************************************/
++
++int dslhal_api_dslShutdown
++(
++ tidsl_t *ptidsl
++);
++
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_api_getDspVersion
++*
++*******************************************************************************************
++* DESCRIPTION: This routine supply AX5 daugther card DSP version.
++*
++* INPUT: tidsl_t * ptidsl
++* void *pVer, DSP version struct is returned starting at this pointer
++*
++* RETURN: 0 --succeeded
++* 1 --Failed
++*
++*****************************************************************************************/
++
++int dslhal_api_getDspVersion
++(
++ tidsl_t *ptidsl,
++ void *pVer
++);
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_diags_digi_memTestA()
++*
++*********************************************************************************************
++* DESCRIPTION: This function does the digital tests on the DSP. It does the DSP ID test,
++* memory tests on the external and internal memories of DSP, Codec Interconnect
++* test and Interrupt Test.
++*
++* Input: Test selects the test to be performed based on the elements set of 9 element
++* array passed the the parameter.
++*
++* Return: Status of the Tests Failed
++*
++********************************************************************************************/
++
++unsigned int dslhal_diags_digi_memTestA
++(
++unsigned int* Test
++);
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_diags_digi_memTestB()
++*
++*********************************************************************************************
++* DESCRIPTION: This function does the digital tests on the DSP. It does the DSP ID test,
++* memory tests on the external and internal memories of DSP, Codec Interconnect
++* test and Interrupt Test.
++*
++* Input: Test selects the digital test to be performed.
++*
++* Return: Status of the Tests Failed
++*
++********************************************************************************************/
++
++unsigned int dslhal_diags_digi_memTestB
++(
++unsigned int Test,
++unsigned int *Status
++);
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_diags_anlg_tonesTestA()
++*
++*********************************************************************************************
++* DESCRIPTION: This function instructs the Transciever to transmit the Reverb with missing
++* tones and Medley's with missing tones. These signals are defined in ITU
++* G.992.1 ADSL Standards.
++*
++* Input: Test selects between the Reverb or Medley tests. 0 - Reverb, 1 - Medley
++* Array is a 64 element unsigned integer type array. The element of this array
++* describe which tones are to be generated by selecting the element of
++* the array to be non zero.
++* Return: NULL
++*
++********************************************************************************************/
++
++void dslhal_diags_anlg_tonesTestA
++(
++unsigned int Test,
++unsigned int* Array
++);
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_diags_anlg_tonesTestB()
++*
++*********************************************************************************************
++* DESCRIPTION: This function instructs the Transciever to transmit the Reverb with missing
++* tones and Medley's with missing tones. These signals are defined in ITU
++* G.992.1 ADSL Standards.
++*
++* Input: Test selects between the Reverb or Medley tests. 0 - Reverb, 1 - Medley
++* Array is a 64 element unsigned integer type array. The element of this array
++* describe which tones are to be generated by selecting the element of
++* the array to be non zero.
++* Return: NULL
++*
++********************************************************************************************/
++
++void dslhal_diags_anlg_tonesTestB
++(
++unsigned int Test,
++unsigned int Tones
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_diags_anlg_rxNoiseTest()
++*
++*********************************************************************************************
++* DESCRIPTION: This function instructs the Transciever to transmit the Reverb with missing
++* tones and Medley's with missing tones. These signals are defined in ITU
++* G.992.1 ADSL Standards.
++*
++* Input: Test selects between the Reverb or Medley tests. 0 - Reverb, 1 - Medley
++* Tones selects the .
++* Return: NULL
++*
++********************************************************************************************/
++
++void dslhal_diags_anlg_rxNoiseTest
++(int agcFlag,
++short pga1,
++short pga2,
++short pga3,
++short aeq
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_diags_anlg_ecNoiseTest()
++*
++*********************************************************************************************
++* DESCRIPTION: This function instructs the Transciever to transmit the Reverb with missing
++* tones and Medley's with missing tones. These signals are defined in ITU
++* G.992.1 ADSL Standards.
++*
++* Input: Test selects between the Reverb or Medley tests. 0 - Reverb, 1 - Medley
++* Tones selects the .
++* Return: NULL
++*
++********************************************************************************************/
++
++void dslhal_diags_anlg_ecNoiseTest
++(int agcFlag,
++short pga1,
++short pga2,
++short pga3,
++short aeq
++);
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_pollTrainingStatus()
++*
++*********************************************************************************************
++* DESCRIPTION: code to decode modem status and to start modem training
++*
++* Input: tidsl_t *ptidsl
++*
++* Return: 0-? status mode training
++* -1 failed
++*
++********************************************************************************************/
++int dslhal_api_pollTrainingStatus
++(
++ tidsl_t *ptidsl
++);
++
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_handleTrainingInterrupt()
++*
++*********************************************************************************************
++* DESCRIPTION: Code to handle ax5 hardware interrupts
++*
++* Input: tidsl_t *ptidsl
++* int *pMsg, pointer to returned hardware messages. Each byte represent a messge
++* int *pTag, pointer to returned hardware message tags. Each byte represent a tag.
++* Return: 0 success
++* 1 failed
++*
++********************************************************************************************/
++int dslhal_api_handleTrainingInterrupt
++(
++ tidsl_t *ptidsl,
++ int intrSource
++);
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_setEocSerialNumber(tidsl_t *ptidsl,char *SerialNumber)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction Sets the EOC Serial Number
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ * char *SerialNumber : Input EOC Serial Number
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_setEocSerialNumber
++(
++tidsl_t *ptidsl,
++char *SerialNumber
++);
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_setEocVendorId(tidsl_t *ptidsl,char *VendorID)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction Sets the EOC Serial Number
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ * char *VendorID : EOC Vendor ID
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_setEocVendorId
++(
++tidsl_t *ptidsl,
++char *VendorID
++);
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_setEocRevisionNumber(tidsl_t *ptidsl,char *RevNum)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction Sets the EOC Revision Number
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ * char *RevNum : Input EOC Revision Number
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_setEocRevisionNumber
++(
++tidsl_t *ptidsl,
++char *RevNumber
++);
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_setAturConfig(tidsl_t *ptidsl,char *ATURConfig)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction Sets the EOC ATUR Config Register
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ * char *RevNum : Input EOC ATUR Config Register
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_setAturConfig
++(
++tidsl_t *ptidsl,
++char *ATURConfig
++);
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_disableLosAlarm(tidsl_t *ptidsl, unsigned int set)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction disables all the LOS alarms
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ * unsigned int set // if set == TRUE : Disable LOS alarms, else enable
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ * NOTES: Currently not supported in any version other than MR4 Patch release..
++ *****************************************************************************************/
++unsigned int dslhal_api_disableLosAlarm
++(
++tidsl_t *ptidsl,
++unsigned int
++);
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_sendIdle(tidsl_t *ptidsl)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction sends the CMD_IDLE message to the DSP
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_sendIdle
++(
++tidsl_t *ptidsl
++);
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_sendQuiet(tidsl_t *ptidsl)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction sends the CMD_QUIET message to the DSP
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_sendQuiet
++(
++tidsl_t *ptidsl
++);
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_sendDgasp(tidsl_t *ptidsl)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction sends the HOST_DGASP message to the DSP
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_sendDgasp
++(
++tidsl_t *ptidsl
++);
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_setMarginThreshold(tidsl_t *ptidsl, int threshold)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction does sets the Margin threshold
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ * int threshold
++ *
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_setMarginThreshold
++(
++tidsl_t *ptidsl,
++int threshold
++);
++
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_setMarginMonitorFlags(tidsl_t *ptidsl, unsigned int trainflag,unsigned int shwtflag)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction does sets the Margin monitoring flag
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ * unsigned int trainflag
++ * unsigned int shwtflag
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_setMarginMonitorFlags
++(
++tidsl_t *ptidsl,
++unsigned int trainflag,
++unsigned int shwtflag
++);
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_api_setRateAdaptFlag(tidsl_t *ptidsl)
++*
++*******************************************************************************************
++* DESCRIPTION: This fuction Sets the Rate Adapt Enable Flag
++*
++* INPUT: PITIDSLHW_T *ptidsl
++* unsigned int flag //if flag = TRUE set flag else reset
++* RETURN: 0 SUCCESS
++* 1 FAILED
++*
++*****************************************************************************************/
++unsigned int dslhal_api_setRateAdaptFlag
++(
++tidsl_t *ptidsl,
++unsigned int flag
++);
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_api_setTrellisFlag(tidsl_t *ptidsl, unsigned int flag)
++*
++*******************************************************************************************
++* DESCRIPTION: This fuction Sets the Trellis Coding Enable Flag
++*
++* INPUT: PITIDSLHW_T *ptidsl
++* unsigned int flag //if flag = TRUE set flag else reset
++* RETURN: 0 SUCCESS
++* 1 FAILED
++*
++*****************************************************************************************/
++unsigned int dslhal_api_setTrellisFlag
++(
++tidsl_t *ptidsl,
++unsigned int flag
++);
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_api_setMaxBitsPerCarrier(tidsl_t *ptidsl,unsigned int maxbits)
++*
++*******************************************************************************************
++* DESCRIPTION: This fuction Sets the Maximum bits per carrier value
++*
++* INPUT: PITIDSLHW_T *ptidsl
++* unsigned int maxbits : should be a value between 0-15
++*
++* RETURN: 0 SUCCESS
++* 1 FAILED
++*
++*****************************************************************************************/
++unsigned int dslhal_api_setMaxBitsPerCarrier
++(
++tidsl_t *ptidsl,
++unsigned int maxbits
++);
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_api_setMaxInterleaverDepth(tidsl_t *ptidsl,unsigned int maxdepth)
++*
++*******************************************************************************************
++* DESCRIPTION: This fuction Sets the Maximum Interleave Depth Supported
++*
++* INPUT: PITIDSLHW_T *ptidsl
++* unsigned int maxdepth : Should be between 0 and 3 depending on intlv buffer
++* size 64-512
++* RETURN: 0 SUCCESS
++* 1 FAILED
++*
++*****************************************************************************************/
++unsigned int dslhal_api_setMaxInterleaverDepth
++(
++tidsl_t *ptidsl,
++unsigned int maxdepth
++);
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_api_setTrainingMode(tidsl_t *ptidsl,unsigned int trainmode)
++*
++*******************************************************************************************
++* DESCRIPTION: This fuction Sets the desired training mode(none/T1.413/G.dmt/G.lite)
++*
++* INPUT: PITIDSLHW_T *ptidsl
++* unsigned int trainmode :Should be between 0 and 4; 0:No Mode 1:Multimode
++* 2: T1.413, 3:G.dmt, 4: G.lite
++* RETURN: 0 SUCCESS
++* 1 FAILED
++*
++*****************************************************************************************/
++
++unsigned int dslhal_api_setTrainingMode
++(
++tidsl_t *ptidsl,
++unsigned int trainmode
++);
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_dslRetrain(tidsl_t *ptidsl)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction sends the CMD_QUIET message to the DSP
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_dslRetrain
++(
++tidsl_t *ptidsl
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_acknowledgeInterrupt()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_acknowledgeInterrupt
++(tidsl_t * ptidsl
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_disableDspHybridSelect()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_disableDspHybridSelect
++(tidsl_t * ptidsl,
++ unsigned int disable
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_disableDspHybridSelect()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_selectHybrid
++(tidsl_t * ptidsl,
++ unsigned int hybridNum
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_reportHybridMetrics()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_reportHybridMetrics
++(tidsl_t * ptidsl,
++ int *metric
++);
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_selectInnerOuterPair(tidsl_t *ptidsl, unsigned int pairSelect)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction sends the CMD_QUIET message to the DSP
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++
++unsigned int dslhal_api_selectInnerOuterPair
++(tidsl_t *ptidsl,
++unsigned int pairSelect
++);
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_resetTrainFailureLog(tidsl_t *ptidsl, unsigned int pairSelect)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction sends the CMD_QUIET message to the DSP
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++
++unsigned int dslhal_api_resetTrainFailureLog
++(tidsl_t *ptidsl
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_controlLed()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_configureLed
++(tidsl_t * ptidsl,
++unsigned int idLed,
++unsigned int onOff
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_configureExternBert()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_configureExternBert
++(tidsl_t * ptidsl,
++unsigned int configParm,
++unsigned int parmVal
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_configureAtmBert()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_configureAtmBert
++(tidsl_t * ptidsl,
++unsigned int configParm,
++unsigned int parmVal
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_configureDgaspLpr()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_configureDgaspLpr
++(tidsl_t * ptidsl,
++unsigned int configParm,
++unsigned int parmVal
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_advcfg_onOffPcb()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_advcfg_onOffPcb
++(tidsl_t * ptidsl,
++unsigned int onOff
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_advcfg_onOffBitSwap()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Turns on / off the power cutback feature;
++* Input
++* usDs; 0 = us and 1 = ds;
++* onOff; 0 = OFF and 1 = ON
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_advcfg_onOffBitSwap
++(tidsl_t * ptidsl,
++ unsigned int usDs,
++ unsigned int onOff
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_advcfg_configDsTones()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Turns on / off specific tones in the downstream direction;
++* Input
++* pointer to the array specifying the tones to be turned on/off
++*
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_advcfg_configDsTones
++(tidsl_t * ptidsl,
++ unsigned int *dsTones
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_advcfg_getAocBitSwapBuffer()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Fetches the Tx/Rx AOC bitswap Buffer;
++* Input
++* Transmit / Receive buffer to be fetched
++*
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_advcfg_getAocBitswapBuffer
++(tidsl_t * ptidsl,
++unsigned int usDs
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_advcfg_readTrainingMessages()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Reads all the training messages on demand;
++* Input
++* tidsl_t *ptidsl : Pointer to application structure
++* void *msgStruct : Pointer to Message Structure
++*
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_advcfg_readTrainingMessages
++(tidsl_t * ptidsl,
++void *msgPtr
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_advcfg_getTrainingState()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Reads all the training messages on demand;
++* Input
++* tidsl_t *ptidsl : Pointer to application structure
++* void *msgStruct : Pointer to training state structure
++*
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_advcfg_getTrainingState
++(tidsl_t * ptidsl,
++void *statePtr
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_advcfg_resetBitSwapMessageLog()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Clears the Aoc Bitswap Message Log
++* Input
++* tidsl_t *ptidsl : Pointer to application structure
++* unsigned int usDs ; Upstream=0, Downstream=1
++*
++* Return: 0 success
++* 1 failed
++*
++********************************************************************************************/
++unsigned int dslhal_advcfg_resetBitSwapMessageLog
++(tidsl_t * ptidsl,
++ unsigned int usDs
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_advcfg_setConstellationBinNumber()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Specifies the bin number for which constellation data should be fetched
++* Input
++* tidsl_t *ptidsl : Pointer to application structure
++* unsigned int binNum : constellation bin number whose data is required
++*
++* Return: 0 success
++* 1 failed
++*
++********************************************************************************************/
++unsigned int dslhal_advcfg_setConstellationBinNumber
++(tidsl_t * ptidsl,
++ unsigned int binNum
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_advcfg_resetTrainStateHistory()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Clears the Training State History Log
++* Input
++* tidsl_t *ptidsl : Pointer to application structure
++*
++*
++* Return: 0 success
++* 1 failed
++*
++********************************************************************************************/
++unsigned int dslhal_advcfg_resetTrainStateHistory
++(tidsl_t * ptidsl
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_advcfg_getSnrPerBin()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Get SNR data per bin
++* Input
++* tidsl_t *ptidsl : Pointer to application structure
++*
++*
++* Return: 0 success
++* 1 failed
++*
++********************************************************************************************/
++unsigned int dslhal_advcfg_getSnrPerBin
++(tidsl_t * ptidsl,
++ unsigned int snrBufferOpt
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_advcfg_logEocMessages()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Logs EOC messages sent by the Modem to the CO
++* Input
++* tidsl_t *ptidsl : Pointer to application structure
++* unsigned int eocLowerBytes : Lower [1-5] bits of EOC Message
++* unsigned int eocUpperBytes : Upper [6-13] bits of EOC Message
++*
++* Return: 0 success
++* 1 failed
++*
++********************************************************************************************/
++unsigned int dslhal_advcfg_logEocMessages
++(tidsl_t * ptidsl,
++ unsigned int usDs,
++ unsigned int eocLowerBytes,
++ unsigned int eocUpperBytes
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_advcfg_getReasonForDrop()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Reads the reason for dropping DSL connection;
++* Input
++* tidsl_t *ptidsl : Pointer to application structure
++
++*
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_advcfg_getReasonForDrop
++(tidsl_t * ptidsl
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_advcfg_ctrlMaxAvgFineGains()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Turns on / off the host control for Max Avg Fine Gains; 0 = OFF and 1 = ON
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_advcfg_ctrlMaxAvgFineGains
++(tidsl_t * ptidsl,
++unsigned int onOff
++);
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_advcfg_setMaxAvgFineGain()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Set the Maximum Average Fine Gain Value
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_advcfg_setMaxAvgFineGain
++(tidsl_t * ptidsl,
++ short fineGain
++);
++/********************************************************************************************
++* FUNCTION NAME: dslhal_advcfg_readPhySettings()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Reads the advanced Phy layer settings on demand;
++* Input
++* tidsl_t *ptidsl : Pointer to application structure
++* void *cfgStruct : Pointer to Phy Config Structure
++*
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_advcfg_readPhySettings
++(tidsl_t * ptidsl,
++void *cfgPtr
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_advcfg_setBlackOutBits()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the Blackout Bits in the RMSGPCB message
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_advcfg_setBlackOutBits
++(tidsl_t * ptidsl
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_genericDspRead()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Reads from a generic location in the host interface
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_genericDspRead
++(tidsl_t * ptidsl,
++ unsigned int offset1,
++ unsigned int offset2,
++ unsigned int offset3,
++ unsigned char* localBuffer,
++ unsigned int numBytes
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_genericDspWrite()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Writes to a generic location in the host interface
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_genericDspWrite
++(tidsl_t * ptidsl,
++ unsigned int offset1,
++ unsigned int offset2,
++ unsigned int offset3,
++ unsigned char* localBuffer,
++ unsigned int numBytes
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_dspInterfaceRead()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Reads from a generic location in the host interface
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_dspInterfaceRead
++(tidsl_t * ptidsl,
++ unsigned int baseAddr,
++ unsigned int numOffsets,
++ unsigned int *offsets,
++ unsigned char* localBuffer,
++ unsigned int numBytes
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_api_dspInterfaceWrite()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Writes to a generic location in the host interface
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_api_dspInterfaceWrite
++(tidsl_t * ptidsl,
++ unsigned int baseAddr,
++ unsigned int numOffsets,
++ unsigned int *offsets,
++ unsigned char* localBuffer,
++ unsigned int numBytes
++);
++
++/******************************************************************************************
++ * FUNCTION NAME: dslhal_api_sendMailboxCommand(tidsl_t *ptidsl, unsigned int cmd)
++ *
++ *******************************************************************************************
++ * DESCRIPTION: This fuction sends the passed mailbox command to the DSP
++ *
++ * INPUT: PITIDSLHW_T *ptidsl
++ * unsigned int cmd
++ *
++ * RETURN: 0 SUCCESS
++ * 1 FAILED
++ *
++ *****************************************************************************************/
++unsigned int dslhal_api_sendMailboxCommand
++(tidsl_t *ptidsl,
++unsigned int cmd
++);
++
++#ifdef INTERNAL_BUILD
++#include <dsl_hal_internal_api.h>
++#endif
++
++
++#endif /* pairs #ifndef __DSL_APPLICATION_INTERFACE_H__ */
+diff -urN linux.old/drivers/atm/sangam_atm/dsl_hal_logtable.h linux.dev/drivers/atm/sangam_atm/dsl_hal_logtable.h
+--- linux.old/drivers/atm/sangam_atm/dsl_hal_logtable.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/dsl_hal_logtable.h 2005-08-23 04:46:50.097843696 +0200
+@@ -0,0 +1,259 @@
++unsigned int log10[]=
++{
++ 0,
++ 771,
++ 1221,
++ 1541,
++ 1789,
++ 1992,
++ 2163,
++ 2312,
++ 2443,
++ 2560,
++ 2666,
++ 2763,
++ 2852,
++ 2934,
++ 3011,
++ 3083,
++ 3150,
++ 3213,
++ 3274,
++ 3331,
++ 3385,
++ 3437,
++ 3486,
++ 3533,
++ 3579,
++ 3622,
++ 3664,
++ 3705,
++ 3744,
++ 3781,
++ 3818,
++ 3853,
++ 3887,
++ 3921,
++ 3953,
++ 3984,
++ 4015,
++ 4044,
++ 4073,
++ 4101,
++ 4129,
++ 4156,
++ 4182,
++ 4207,
++ 4232,
++ 4257,
++ 4281,
++ 4304,
++ 4327,
++ 4349,
++ 4371,
++ 4393,
++ 4414,
++ 4435,
++ 4455,
++ 4475,
++ 4495,
++ 4514,
++ 4533,
++ 4552,
++ 4570,
++ 4589,
++ 4606,
++ 4624,
++ 4641,
++ 4658,
++ 4675,
++ 4691,
++ 4707,
++ 4723,
++ 4739,
++ 4755,
++ 4770,
++ 4785,
++ 4800,
++ 4815,
++ 4829,
++ 4844,
++ 4858,
++ 4872,
++ 4886,
++ 4899,
++ 4913,
++ 4926,
++ 4939,
++ 4952,
++ 4965,
++ 4978,
++ 4990,
++ 5003,
++ 5015,
++ 5027,
++ 5039,
++ 5051,
++ 5063,
++ 5075,
++ 5086,
++ 5098,
++ 5109,
++ 5120,
++ 5131,
++ 5142,
++ 5153,
++ 5164,
++ 5174,
++ 5185,
++ 5195,
++ 5206,
++ 5216,
++ 5226,
++ 5236,
++ 5246,
++ 5256,
++ 5266,
++ 5275,
++ 5285,
++ 5295,
++ 5304,
++ 5313,
++ 5323,
++ 5332,
++ 5341,
++ 5350,
++ 5359,
++ 5368,
++ 5377,
++ 5386,
++ 5394,
++ 5403,
++ 5412,
++ 5420,
++ 5429,
++ 5437,
++ 5445,
++ 5454,
++ 5462,
++ 5470,
++ 5478,
++ 5486,
++ 5494,
++ 5502,
++ 5510,
++ 5518,
++ 5525,
++ 5533,
++ 5541,
++ 5548,
++ 5556,
++ 5563,
++ 5571,
++ 5578,
++ 5586,
++ 5593,
++ 5600,
++ 5607,
++ 5614,
++ 5622,
++ 5629,
++ 5636,
++ 5643,
++ 5649,
++ 5656,
++ 5663,
++ 5670,
++ 5677,
++ 5683,
++ 5690,
++ 5697,
++ 5703,
++ 5710,
++ 5716,
++ 5723,
++ 5729,
++ 5736,
++ 5742,
++ 5749,
++ 5755,
++ 5761,
++ 5767,
++ 5773,
++ 5780,
++ 5786,
++ 5792,
++ 5798,
++ 5804,
++ 5810,
++ 5816,
++ 5822,
++ 5828,
++ 5834,
++ 5839,
++ 5845,
++ 5851,
++ 5857,
++ 5862,
++ 5868,
++ 5874,
++ 5879,
++ 5885,
++ 5891,
++ 5896,
++ 5902,
++ 5907,
++ 5913,
++ 5918,
++ 5924,
++ 5929,
++ 5934,
++ 5940,
++ 5945,
++ 5950,
++ 5955,
++ 5961,
++ 5966,
++ 5971,
++ 5976,
++ 5981,
++ 5986,
++ 5992,
++ 5997,
++ 6002,
++ 6007,
++ 6012,
++ 6017,
++ 6022,
++ 6027,
++ 6031,
++ 6036,
++ 6041,
++ 6046,
++ 6051,
++ 6056,
++ 6060,
++ 6065,
++ 6070,
++ 6075,
++ 6079,
++ 6084,
++ 6089,
++ 6093,
++ 6098,
++ 6103,
++ 6107,
++ 6112,
++ 6116,
++ 6121,
++ 6125,
++ 6130,
++ 6134,
++ 6139,
++ 6143,
++ 6148,
++ 6152,
++ 6156,
++ 6161,
++ 6165
++ };
+diff -urN linux.old/drivers/atm/sangam_atm/dsl_hal_register.h linux.dev/drivers/atm/sangam_atm/dsl_hal_register.h
+--- linux.old/drivers/atm/sangam_atm/dsl_hal_register.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/dsl_hal_register.h 2005-08-23 04:46:50.097843696 +0200
+@@ -0,0 +1,337 @@
++#ifndef ___DSL_REGISTER_DEFINES_H___
++#define ___DSL_REGISTER_DEFINES_H___ 1
++
++/*******************************************************************************
++* FILE PURPOSE: DSL HAL H/W Registers and Constant Declarations for Sangam
++*
++********************************************************************************
++* FILE NAME: dsl_hal_register.h
++*
++* DESCRIPTION:
++* Contains DSL HAL APIs for Adam2 OS functions
++*
++*
++* (C) Copyright 2001-02, Texas Instruments, Inc.
++* History
++* Date Version Notes
++* 06Feb03 0.00.00 RamP Created
++* 21Mar03 0.00.01 RamP Changed header files for Modular
++* build framework
++* 21Mar03 0.00.02 RamP Introduced malloc size for DSP f/w
++* 07Apr03 0.00.03 RamP Implemented new error reporting scheme
++* Changed Commenting to C style only
++* 12Apr03 0.00.04 RamP Added Interrupt Mask defines
++* 14Apr03 0.00.05 RamP Renamed macros for REG8, REG16 & REG32
++* 21Apr03 0.01.00 RamP Added Interrupt source/clear registers
++* Changed enum RSTATE_SHOWTIME to 5
++* 24Apr03 0.01.01 RamP Moved the RSTATE enum to api.h
++* Added olay recovery error condition
++* 14May03 0.01.02 RamP Added defines for power computation
++* Added error condition for hybrids
++* 04Jun03 0.01.03 RamP Added enum for config flags,
++* Cleaned up AR5 register defines
++* Added defines for higher data rate
++* 06Jun03 0.01.04 RamP Added error & interrupt defines
++* 09Jun03 0.01.05 RamP Modified enum for current config
++* Added additional C-Rates defines
++* 18Jul03 0.01.06 RamP Modified internal build flow
++* 21Aug03 0.01.07 RamP Added constellation buffer size
++* 08Oct03 0.01.08 RamP Added us/ds Bits n gains size
++* 12Oct03 0.01.08 RamP Added ADSL2 Message sizes, lengths
++* and offsets for various formats
++* 29Oct03 0.01.09 RamP Added ADSL2 Delt offsets & sizes
++* 24Nov03 0.01.10 RamP Added bit field number, scan vector
++* 26Dec03 0.01.11 RamP Removed the oamFeature masks to api.h
++*******************************************************************************/
++
++#include "env_def_typedefs.h"
++#ifdef INTERNAL_BUILD
++#include "dev_host_internalinterface.h"
++#endif
++#include "dev_host_interface.h"
++#include "dsl_hal_api.h"
++
++#define ADSLSS_BASE 0x01000000
++#define BBIF_BASE 0x02000000
++
++#define ADSLSSADR (BBIF_BASE+0x0000)
++#define ADSLSSADRMASK 0xff000000
++#define WAKEUP_DSP 0x00000001
++
++/* Ax7 Reset Control */
++
++#define RST_CNTRL_BASE 0x8611600
++#define RST_CNTRL_PRCR (RST_CNTRL_BASE + 0x00 )
++
++#define RST_CNTRL_PRCR_GPIO 0x00000040
++#define RST_CNTRL_PRCR_ADSLSS 0x00000080
++#define RST_CNTRL_PRCR_USB 0x00000100
++#define RST_CNTRL_PRCR_SAR 0x00000200
++#define RST_CNTRL_PRCR_DSP 0x00800000
++#define RST_CNTRL_PRCR_EMAC1 0x00200000 /* EMAC1 reset */
++
++#define RST_CNTRL_SWRCR (RST_CNTRL_BASE + 0x04 )
++#define RST_SWRCR_SWR0 0x00000001
++#define RST_SWRCR_SWR1 0x00000002
++
++#define RST_CNTRL_RSR (TNETD53XX_RST_CNTRL_BASE + 0x08 )
++#define RST_RSR_RSCAUSE 0x00000003 /* Software Reset Caused by writing to SWR1 bit */
++
++
++/* ******************************************************
++Interrupt sources on Ax7 interrupt controller.
++The reserved sources are noted.
++********************************************************* */
++
++#define INTR_CNTRL_SRC_SECOND 0
++#define INTR_CNTRL_SRC_EXTERNAL0 1
++#define INTR_CNTRL_SRC_EXTERNAL1 2
++/* reserved sources ... */
++#define INTR_CNTRL_SRC_TIMER0 5
++#define INTR_CNTRL_SRC_TIMER1 6
++#define INTR_CNTRL_SRC_UART0 7
++#define INTR_CNTRL_SRC_UART1 8
++#define INTR_CNTRL_SRC_DMA0 9
++#define INTR_CNTRL_SRC_DMA1 10
++/* reserved sources ... */
++#define INTR_CNTRL_SRC_SAR 15
++/* reserved sources ... */
++#define INTR_CNTRL_SRC_EMAC0 19
++/* reserved sources ... */
++#define INTR_CNTRL_SRC_VLYNQ0 21
++#define INTR_CNTRL_SRC_CODEC_WAKE 22
++/* reserved sources ... */
++#define INTR_CNTRL_SRC_USB 24
++#define INTR_CNTRL_SRC_VLYNQ1 25
++/* reserved sources ... */
++#define INTR_CNTRL_SRC_EMAC1 28
++#define INTR_CNTRL_SRC_I2C 29
++#define INTR_CNTRL_SRC_DMA2 30
++#define INTR_CNTRL_SRC_DMA3 31
++/* reserved sources ... */
++#define INTR_CNTRL_SRC_VDMA_RX 37
++#define INTR_CNTRL_SRC_VDMA_TX 38
++#define INTR_CNTRL_SRC_ADSLSS 39
++
++#ifndef K0BASE
++#define K0BASE 0x80000000
++#endif
++
++#ifndef K1BASE
++#define K1BASE 0xA0000000
++#endif
++
++#ifndef PHYS_ADDR
++#define PHYS_ADDR(X) ((X) & 0X1FFFFFFF)
++#endif
++
++#ifndef PHYS_TO_K0
++#define PHYS_TO_K0(X) (PHYS_ADDR(X)|K0BASE)
++#endif
++
++#ifndef PHYS_TO_K1
++#define PHYS_TO_K1(X) (PHYS_ADDR(X)|K1BASE)
++#endif
++
++#ifndef DSLHAL_REG8
++#define DSLHAL_REG8( addr ) (*(volatile unsigned short *) PHYS_TO_K1(addr))
++#endif
++
++#ifndef DSLHAL_REG16
++#define DSLHAL_REG16( addr ) (*(volatile unsigned short *)PHYS_TO_K1(addr))
++#endif
++
++#ifndef DSLHAL_REG32
++#define DSLHAL_REG32( addr ) (*(volatile unsigned int *)PHYS_TO_K1(addr))
++#endif
++
++#ifndef NULL
++#define NULL 0
++#endif
++
++#ifndef TRUE
++#define TRUE (1==1)
++#endif
++
++#ifndef FALSE
++#define FALSE (1==2)
++#endif
++
++/*******************************************************************************
++* Type Defines for Library
++********************************************************************************/
++typedef unsigned int size_t;
++
++#define TIDSL_HW_CREATED 0x00000001
++#define TIDSL_HW_OPENED 0x00000002
++#define TIDSL_HW_STARTED 0x00000004
++#define TIDSL_OS_INITIALIZED 0x00000008
++
++/* Data Pump CRATES Table Defines */
++#define SIZE_OF_CRATES1_TABLE 120
++#define CRATES1_BF_LS0 7
++#define CRATES1_BI_LS0 17
++#define CRATES1_BF_AS0 0
++#define CRATES1_BI_AS0 10
++#define CRATES1_BF_DSRS 20
++#define CRATES1_BI_DSRS 21
++#define CRATES1_BFI_DSS 22
++#define CRATES1_BFI_DSI 23
++#define CRATES1_BF_USRS 25
++#define CRATES1_BI_USRS 26
++#define CRATES1_BFI_USS 27
++#define CRATES1_BFI_USI 28
++
++#define FAST_PATH 0
++#define INTERLEAVED_PATH 1
++
++#define LINE_NOT_CONNECTED 0
++#define LINE_CONNECTED 1
++#define LINE_DISCONNECTED 2
++#define LINE_NOT_TO_CONNECT 3
++
++#define MAXSECTIONS 125
++
++/*****************************************************************************************
++ * Localstructure declarations
++ *
++ ****************************************************************************************/
++enum
++{
++ DSLHAL_ERROR_NO_ERRORS, /* 00 */
++ DSLHAL_ERROR_UNRESET_ADSLSS, /* 01 */
++ DSLHAL_ERROR_RESET_ADSLSS, /* 02 */
++ DSLHAL_ERROR_UNRESET_DSP, /* 03 */
++ DSLHAL_ERROR_RESET_DSP, /* 04 */
++ DSLHAL_ERROR_NO_FIRMWARE_IMAGE, /* 05 */
++ DSLHAL_ERROR_MALLOC, /* 06 */
++ DSLHAL_ERROR_FIRMWARE_MALLOC, /* 07 */
++ DSLHAL_ERROR_DIAG_MALLOC, /* 08 */
++ DSLHAL_ERROR_OVERLAY_MALLOC, /* 09 */
++ DSLHAL_ERROR_CODE_DOWNLOAD, /* 10 */
++ DSLHAL_ERROR_DIAGCODE_DOWNLOAD, /* 11 */
++ DSLHAL_ERROR_BLOCK_READ, /* 12 */
++ DSLHAL_ERROR_BLOCK_WRITE, /* 13 */
++ DSLHAL_ERROR_MAILBOX_READ, /* 14 */
++ DSLHAL_ERROR_MAILBOX_WRITE, /* 15 */
++ DSLHAL_ERROR_MAILBOX_NOMAIL, /* 16 */
++ DSLHAL_ERROR_MAILBOX_OVERFLOW, /* 17 */
++ DSLHAL_ERROR_INVALID_PARAM, /* 18 */
++ DSLHAL_ERROR_ADDRESS_TRANSLATE, /* 19 */
++ DSLHAL_ERROR_FIRMWARE_CRC, /* 20 */
++ DSLHAL_ERROR_FIRMWARE_OFFSET, /* 21 */
++ DSLHAL_ERROR_CONFIG_API_FAILURE, /* 22 */
++ DSLHAL_ERROR_EOCREG_API_FAILURE, /* 23 */
++ DSLHAL_ERROR_VERSION_API_FAILURE, /* 24 */
++ DSLHAL_ERROR_STATS_API_FAILURE, /* 25 */
++ DSLHAL_ERROR_MARGIN_API_FAILURE, /* 26 */
++ DSLHAL_ERROR_CTRL_API_FAILURE, /* 27 */
++ DSLHAL_ERROR_HYBRID_API_FAILURE, /* 28 */
++ DSLHAL_ERROR_MODEMENV_API_FAILURE, /* 29 */
++ DSLHAL_ERROR_INTERRUPT_FAILURE, /* 30 */
++ DSLHAL_ERROR_INTERNAL_API_FAILURE, /* 31 */
++ DSLHAL_ERROR_DIGIDIAG_FAILURE, /* 32 */
++ DSLHAL_ERROR_TONETEST_FAILURE, /* 33 */
++ DSLHAL_ERROR_NOISETEST_FAILURE, /* 34 */
++ DSLHAL_ERROR_MODEMSTATE, /* 35 */
++ DSLHAL_ERROR_OVERLAY_CORRUPTED /* 36 */
++};
++
++enum
++{
++ CONFIG_FLAG_NOFLAG, /* 00 */
++ CONFIG_FLAG_TRELLIS, /* 01 */
++ CONFIG_FLAG_EC, /* 02 */
++ CONFIG_FLAG_RS /* 03 */
++};
++
++#define USE_EMIF_REV 0
++#define USE_CVR_REV 1
++#define TNETD53XX_MAXLOOP 10000
++#define REVERB 0
++#define MEDLEY 1
++#define NONINTENSE 0
++#define slavespace0 0xa1000000
++
++#define MASK_MAILBOX_INTERRUPTS 0x00000001
++#define MASK_BITFIELD_INTERRUPTS 0x00000002
++#define MASK_HEARTBEAT_INTERRUPTS 0x00000004
++#define DSP_INTERRUPT_SOURCE_REGISTER 0x020007A0
++#define DSP_INTERRUPT_CLEAR_REGISTER 0x020007A4
++
++#define DIGITAL_DIAG_MEMSIZE 1048576
++#define CRC32_QUOTIENT 0x04c11db7
++#define DSP_FIRMWARE_MALLOC_SIZE 0x7ffff
++#define DSP_CONSTELLATION_BUFFER_SIZE 1024*4
++#define LOG43125 9303
++#define US_NOMINAL_POWER (-38)
++#define US_BNG_LENGTH 32
++#define DS_BNG_LENGTH 256
++#define NUMBER_OF_BITFIELDS 4
++#define BITFIELD_SCAN 0x80000000
++
++/* ADSL Message offsets from Host Interface Pointer */
++
++/* ADSL2 Messages Index and Length defines */
++
++#define CMSGFMT_INDEX 0
++#define CMSGPCB_INDEX 1
++#define RMSGFMT_INDEX 2
++#define RMSGPCB_INDEX 3
++#define RMSG1LD_INDEX 13
++#define RMSG2LD_INDEX 14
++#define RMSG3LD_INDEX 15
++#define RMSG4LD_INDEX 16
++#define RMSG5LD_INDEX 17
++#define RMSG6LD_INDEX 18
++#define RMSG7LD_INDEX 19
++#define RMSG8LD_INDEX 20
++#define RMSG9LD_INDEX 21
++#define CMSG1LD_INDEX 22
++#define CMSG2LD_INDEX 23
++#define CMSG3LD_INDEX 24
++#define CMSG4LD_INDEX 25
++#define CMSG5LD_INDEX 26
++#define CMSGPCB2_INDEX 28
++#define CMSGPCB2L_INDEX 29
++#define RMSGFMT2_INDEX 30
++#define RMSGPCB2L_INDEX 31
++#define CMSG1ADSL2_INDEX 32
++#define RMSG1ADSL2_INDEX 33
++#define CMSG2ADSL2_INDEX 34
++#define RMSG2ADSL2_INDEX 35
++#define CPARAMS_INDEX 36
++#define RPARAMS_INDEX 37
++
++/* ADSL2 Message Sizes */
++
++#define CMSGFMT_SIZE 2
++#define RMSGFMT_SIZE 2
++#define CMSGPCB_SIZE 2
++#define CMSGPCB2_SIZE 6 /* Annex A with Blackout */
++#define CMSGPCB2L_SIZE 10 /* Annex B with Blackout */
++#define RMSGPCB_SIZE 36
++#define RMSG1LD_SIZE 16
++#define RMSGxLD_SIZE 258
++#define CMSG1LD_SIZE 16
++#define CMSG2LD_SIZE 130
++#define CMSG3LD_SIZE 66
++#define CMSG4LD_SIZE 34
++#define CMSG5LD_SIZE 34
++#define CMSG1ADSL2_SIZE 24
++#define RMSG1ADSL2_SIZE 4
++#define CMSG2ADSL2_SIZE 4
++#define RMSG2ADSL2_SIZE 32
++#define CPARAMS_SIZE 136
++#define RPARAMS_SIZE 808
++
++/* ADSL2 Plus Message Sizes (if Different from ADSL2) */
++
++#define RMSGPCB_P_SIZE 68
++#define CMSG1ADSL2P_SIZE 40 /* With Blackout */
++#define CPARAMS_PA_SIZE 168
++#define RPARAMS_PA_SIZE 2088
++#define CPARAMS_PB_SIZE 296
++#define RPARAMS_PB_SIZE 2088
++
++#endif /* pairs #ifndef ___DSL_REGISTER_DEFINES_H___ */
+diff -urN linux.old/drivers/atm/sangam_atm/dsl_hal_support.c linux.dev/drivers/atm/sangam_atm/dsl_hal_support.c
+--- linux.old/drivers/atm/sangam_atm/dsl_hal_support.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/dsl_hal_support.c 2005-08-23 04:46:50.100843240 +0200
+@@ -0,0 +1,2788 @@
++/*******************************************************************************
++* FILE PURPOSE: DSL Driver API functions for Sangam
++*********************************************************************************
++* FILE NAME: dsl_hal_support.c
++*
++* DESCRIPTION:
++* Contains DSL HAL APIs for Modem Control
++*
++*
++* (C) Copyright 2001-02, Texas Instruments, Inc.
++* History
++* Date Version Notes
++* 06Feb03 0.00.00 RamP Created
++* 21Mar03 0.00.01 RamP Inserted byteswap functions
++* 07Apr03 0.00.02 RamP Implemented new error reporting scheme
++* Changed Commenting to C style only
++* 12Apr03 0.00.03 RamP Added function to set Interrupt Bit
++* Masks for bitfield & Mailboxes
++* 14Apr03 0.00.04 RamP Added function to process modem state
++* bit fields; renamed REG32 macros
++* Changed interrupt bit field settings
++* 15Apr03 0.00.05 RamP Fixed exit condition on dslShutdown
++* 21Apr03 0.01.00 RamP Fixed dslShutdown function & changed
++* loop counter for overlay byteswaps
++* (Alpha) Added cache writeback for overlays
++* Added function acknowledgeInterrupt
++* 22Apr03 0.01.01 RamP Moved acknowledgeInterrupt into api
++* 24Apr03 0.01.02 RamP Added function to compare crc32 with
++* pre-computed value as a recovery
++* scheme for corrupt overlay pages
++* 28Apr03 0.01.03 RamP Fixed a parameter in crc32 fxn call
++* 05May03 0.01.04 RamP Fixed Message structure access in
++* writeHostMailbox function
++* 14May03 0.01.05 RamP Lookup to netService of dsp version
++* (alpha ++) to determine pots/isdn service
++* 21May03 0.01.06 RamP Added support for CO profiles
++* 29May03 0.01.07 RamP Added critical section tabs for block
++* read/write operations
++* Added functions to reload overlay pages
++* and CO Profiles
++* 04Jun03 0.01.08 RamP Added state transition timing counters
++* 06Jun03 0.01.09 RamP Added Interrupt source parsing function
++* Interrupt masking for heartbeat added
++* 09Jun03 0.01.10 RamP Modified modem state bit field processing
++* for structure changes in ITIDSLHW
++* fixed problem in free memory for CO prof
++* 18Jul03 0.01.11 RamP Optimized free memory for CO profiles &
++* overlay pages in the supporting APIs
++* 28Jul03 0.02.00 RamP Modified the process bitfield functn
++* for LED & Application State report
++* 21Aug03 0.03.00 RamP Added logic to allocate & communicate
++* memory for constellation buffer display
++* 29Sep03 0.03.01 RamP Added API switch calls to advcfg module
++* to abstract them from the API module
++* 12Oct03 0.03.02 RamP Added API to gather ADSL2 Messages
++* 14Oct03 0.03.03 RamP Added function to read CMsgsRA
++* 23Oct03 0.03.04 RamP Changed train history index to circular
++* buffer upon rollover
++* 29Oct03 0.03.05 RamP Added Adsl2 Delt Message Parsing
++* 12Nov03 0.03.06 RamP Fixed endianness issues with
++* Constellation Display
++* 14Nov03 0.03.07 RamP Added function to gather CRates1/RRates1
++* before they get overwritten by CRatesRA
++* 19Nov03 0.03.08 JohnP Revised dslhal_support_aocBitSwapProcessing to
++* prevent duplicate ATU-R bitswaps going to ACT
++* 24Nov03 0.03.09 RamP Implemented detailed State Tracking through
++* Modem State bit fields for ADSL/2
++* 12Dec03 0.03.10 RamP Tokenized advanced configuration code
++* 12Dec03 0.03.11 RamP Added state reset upon IDLE
++* 19Dec03 0.03.12 RamP Added static adsl2 byteswap function for
++* handling pointer to pointer cases
++* Changed adsl2 messages to correct pointer to
++* pointer dereferencing problems in some OS
++* 26Dec03 0.03.13 RamP Setting Current Address for Constellation
++* buffer in addition to start address
++* Added additional check to overlay page malloc
++*******************************************************************************/
++#include "dsl_hal_register.h"
++#include "dsl_hal_support.h"
++
++static unsigned int dslhal_support_adsl2ByteSwap32(unsigned int in32Bits);
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_support_unresetDslSubsystem
++*
++*******************************************************************************************
++* DESCRIPTION: This function unreset Dsl Subsystem
++*
++* INPUT: None
++*
++* RETURN: 0 if Pass; 1 if Fail
++*
++*****************************************************************************************/
++int dslhal_support_unresetDslSubsystem(void)
++{
++ dprintf(4," dslhal_support_unresetDslSubsystem()\n");
++ /* Put ADSLSS in to reset */
++ DSLHAL_REG32(0xa8611a10) = 0x1;
++ shim_osClockWait(64);
++ dprintf(5,"Selected APLL Reg \n");
++
++ DSLHAL_REG32(0xa8610a90) = 0x4;
++ shim_osClockWait(64);
++ dprintf(5,"Enable Analog PLL \n");
++
++ DSLHAL_REG32(0xa8610a90) = 0x77fe;
++ shim_osClockWait(64);
++ dprintf(5,"Set PLL for DSP\n");
++
++ /* DSLHAL_REG32(0xa8611600) = 0x007f1bdf;*/
++ DSLHAL_REG32(0xa8611600) |= RST_CNTRL_PRCR_ADSLSS;
++ shim_osClockWait(64);
++ dprintf(5,"Brought ADSLSS out of Reset \n");
++
++ DSLHAL_REG32(0xa861090c) &= ~((1<<20)|(1<<21)|(1<<22)|(1<<23)|(1<<24)|(1<<25));
++ shim_osClockWait(64);
++ dprintf(5,"Configured GPIO 20-25 for McBSP \n");
++
++ /*DSLHAL_REG32(0xa8611600) |= RST_CNTRL_PRCR_ADSLSS;*/
++
++
++ /* DSLHAL_REG32(0xa8611a04) = 0x00000001;
++ shim_osClockWait(64); */
++
++ dprintf(4," dslhal_support_unresetDslSubsystem done\n");
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_support_resetDslSubsystem
++*
++*******************************************************************************************
++* DESCRIPTION: This function unreset Dsl Subsystem
++*
++* INPUT: None
++*
++* RETURN: 0 if Pass; 1 if Fail
++*
++*****************************************************************************************/
++int dslhal_support_resetDslSubsystem(void)
++{
++ dprintf(4, "dslhal_support_resetDslSubsystem \n");
++ /* Put ADSLSS into reset */
++ DSLHAL_REG32(0xa8611600) &= ~RST_CNTRL_PRCR_ADSLSS;
++ shim_osClockWait(64);
++ /* DSLHAL_REG32(0xa8611a04) = 0x00000000;
++ shim_osClockWait(64); */
++ dprintf(4, "dslhal_support_resetDslSubsystem Done \n");
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_support_unresetDsp()
++*
++*******************************************************************************************
++* DESCRIPTION: This fuction takes ax5 daugter board out of reset.
++*
++* INPUT: None
++*
++* RETURN: 0 --successful.
++* 1 --failed
++*
++*****************************************************************************************/
++int dslhal_support_unresetDsp(void)
++{
++#ifdef PRE_SILICON
++ /* unsigned char value; */
++ int rc;
++
++ rc=dslhal_support_hostDspAddressTranslate((unsigned int)DEV_MDMA0_SRC_ADDR);
++ if(rc==DSLHAL_ERROR_ADDRESS_TRANSLATE)
++ {
++ dprintf(1, "dslhal_support_hostDspAddressTranslate failed\n");
++ return DSLHAL_ERROR_ADDRESS_TRANSLATE;
++ }
++ dprintf(5,"MDMA SRC: %08x\n", rc);
++ DSLHAL_REG32(rc) = 0x80000001;
++ rc=dslhal_support_hostDspAddressTranslate((unsigned int)DEV_MDMA0_DST_ADDR);
++ if(rc==DSLHAL_ERROR_ADDRESS_TRANSLATE)
++ {
++ dprintf(1, "dslhal_support_hostDspAddressTranslate failed\n");
++ return DSLHAL_ERROR_ADDRESS_TRANSLATE;
++ }
++ dprintf(5,"MDMA DST: %08x\n", rc);
++ DSLHAL_REG32(rc) = 0x02090001;
++ rc=dslhal_support_hostDspAddressTranslate((unsigned int)DEV_MDMA0_CTL_ADDR);
++ if(rc== DSLHAL_ERROR_ADDRESS_TRANSLATE)
++ {
++ dprintf(1, "dslhal_support_hostDspAddressTranslate failed\n");
++ return DSLHAL_ERROR_ADDRESS_TRANSLATE;
++ }
++ dprintf(5,"MDMA CTL: %08x\n", rc);
++ DSLHAL_REG32(rc) = (DEV_MDMA_START | DEV_MDMA_DST_INC | DEV_MDMA_SRC_INC |
++ DEV_MDMA_BURST1 | (1 << DEV_MDMA_LEN_SHF));
++ /* statusMask = 0x00000010;*/
++#else
++ dprintf(4, "dslhal_support_unresetDsp()\n");
++
++ /* Bring the DSP core out of reset */
++ /* DSLHAL_REG32(0xa8611600) = 0x00ff1bdf; */
++ DSLHAL_REG32(0xa8611600) |= RST_CNTRL_PRCR_DSP;
++ shim_osClockWait(64);
++ dprintf(5,"Brought DSP out of Reset \n");
++ dprintf(6,"Current Contents of PRCR: 0x%x\n",(unsigned int)DSLHAL_REG32(0xa8611600));
++ /* DSLHAL_REG32(0xa8611a0c) = 0x00000007;
++ shim_osClockWait(64); */
++#endif
++
++ dprintf(4, "dslhal_support_unresetDsp() done\n");
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_support_resetDsp()
++*
++*******************************************************************************************
++* DESCRIPTION: This fuction takes ax5 daugter board into reset.
++*
++* INPUT: None
++*
++* RETURN: 0 --successful.
++* 1 --failed
++*
++*****************************************************************************************/
++int dslhal_support_resetDsp(void)
++{
++ dprintf(4, "dslhal_support_resetDsp \n");
++ /* Put ADSLSS into reset */
++ DSLHAL_REG32(0xa8611600) &= ~RST_CNTRL_PRCR_DSP;
++ shim_osClockWait(64);
++ dprintf(4, "dslhal_support_resetDsp Done \n");
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_hostDspAddressTranslate()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Maps ax5 daugter card dsp memory address to avalanche memory space
++*
++* Input: unsigned int addr, dsp memory address.
++*
++* Return: >=0, unsigned int, mapped Avalanche address(VBUS address).
++* -1, mapping failed
++*
++*
++********************************************************************************************/
++/* static unsigned int bbifmap0,bbifmap1; */
++
++unsigned int dslhal_support_hostDspAddressTranslate( unsigned int addr )
++{
++ unsigned int addrMap;
++ /* This function should just be used to move the memory window of the ADSLSS */
++ dprintf(5, "dslhal_support_hostDspAddressTranslate()\n");
++
++ /* select vbus to xbus memory */
++ /* addrMap = addr & 0xff000000; */
++ addrMap = addr & ADSLSSADRMASK;
++
++ DSLHAL_REG32(ADSLSSADR) = addrMap;
++
++ dprintf(6, "dslhal_support_hostDspAddressTranslate() done\n");
++#ifdef PRE_SILICON
++ return ((ADSLSS_BASE | (~ADSLSSADRMASK & addr))+ 0x00000100);
++ /* Added 0x100 for Pre-Silicon VLNQ offset.. to be removed for Silicon */
++#else
++ return ((ADSLSS_BASE | (~ADSLSSADRMASK & addr)));
++ /* Added 0x100 for Pre-Silicon VLNQ offset.. to be removed for Silicon */
++#endif
++
++}
++
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_support_blockWrite
++*
++*******************************************************************************************
++* DESCRIPTION: This rouin simulates DSP memory write as done in ax5 pci nic card
++*
++* INPUT: void *buffer, data need to written
++* void *adde, memory address to be written
++* size_t count, number of bytes to be written
++*
++* RETURN: 0 --succeeded
++* 1 --Failed
++*
++*****************************************************************************************/
++
++int dslhal_support_blockWrite(void *buffer, void *addr, size_t count)
++{
++ int rc, byteCnt=0;
++ unsigned char* ptr;
++ union
++ {
++ unsigned char *cptr;
++ short *sptr;
++ int *iptr;
++ } src;
++ union
++ {
++ int anint; /* DSP location */
++ unsigned char *cptr; /* to avoid casts */
++ } dst;
++ union
++ {
++ unsigned int anint;
++ unsigned char byte[4];
++ }data,dword,sword;
++
++ /* Enter Critical Section */
++ shim_osCriticalEnter();
++
++ dprintf(6, "dslhal_support_blockWrite\n");
++
++ dprintf(6,"addr=0x%X, length=0x%X, buffer=0x%X\n", (unsigned int) addr, (unsigned int) count, (unsigned int)buffer);
++
++ src.cptr = (unsigned char*) buffer; /* local buffer */
++ dst.cptr = addr; /* DSP memory location */
++
++ /*Maps address first*/
++ rc=dslhal_support_hostDspAddressTranslate((unsigned int)addr);
++ dprintf(5, "NewAddr: %08x\n", rc);
++ if(rc== DSLHAL_ERROR_ADDRESS_TRANSLATE)
++ {
++ dprintf(1, "dslhal_support_hostDspAddressTranslate failed\n");
++ return DSLHAL_ERROR_ADDRESS_TRANSLATE;
++ }
++
++ dst.cptr=(unsigned char *)rc;
++
++ /* check wether address is at 32bits boundary */
++
++ if ((dst.anint & 0x3) && count)
++ {
++ sword.anint = *(unsigned int*)((unsigned int)src.cptr & 0xfffffffc);
++ dword.anint = DSLHAL_REG32((unsigned int)dst.cptr & 0xfffffffc);
++ sword.anint = (unsigned int) dslhal_support_byteSwap32(sword.anint);
++ dword.anint = (unsigned int) dslhal_support_byteSwap32(dword.anint);
++ ptr = (unsigned char *)((unsigned int)dst.cptr & 0xfffffffc);
++
++ if((dst.anint & 3) ==3) /* last byte of a dword */
++ {
++ dword.byte[3] = sword.byte[3];
++ dst.anint++; /* bump the address by one */
++ byteCnt++;
++ count--;
++ }
++
++ if((dst.anint & 3) ==1) /* second byte */
++ {
++ if(count>3)
++ {
++ dword.byte[3] = sword.byte[3];
++ dst.anint++;
++ count--;
++ byteCnt++;
++ }
++ if(count>2)
++ {
++ dword.byte[2] = sword.byte[2];
++ dst.anint++;
++ count--;
++ byteCnt++;
++ }
++ if(count)
++ {
++ dword.byte[1] = sword.byte[1];
++ dst.anint++;
++ count--;
++ byteCnt++;
++ }
++ }
++
++ if((dst.anint & 3) && (count >1))
++ {
++ dword.byte[2] = sword.byte[2];
++ dword.byte[3] = sword.byte[3];
++ byteCnt+=2;
++ dst.anint += 2; /* bump the address by two */
++ count -= 2; /* decrement the byte count by two */
++ }
++
++ if((dst.anint & 3) && (count==1))
++ {
++ dword.byte[2] = sword.byte[2];
++ dst.anint++;
++ byteCnt++;
++ count--;
++ }
++ src.cptr = (char *)((unsigned int)src.cptr & 0xfffffffc); /* fix 032802 */
++ dword.anint = dslhal_support_byteSwap32(dword.anint);
++ DSLHAL_REG32((unsigned int)ptr) = dword.anint;
++ ptr = src.cptr;
++ for(rc=0;rc<count;rc++)
++ {
++ *ptr = *(ptr+byteCnt);
++ ptr++;
++ }
++ }
++
++ /* the dst pointer should now be on a 32-bit boundary */
++
++ while (count > 3)
++ {
++ DSLHAL_REG32((unsigned int)dst.cptr) = dslhal_support_byteSwap32(*src.iptr);
++ src.iptr++; /* bump the data pointer by four */
++ dst.anint += 4; /* bump the address by four */
++ count -= 4; /* decrement the byte count by four */
++ }
++
++ /* write remaining bytes */
++ if(count)
++ {
++ int i;
++
++ data.anint= DSLHAL_REG32((unsigned int)dst.cptr);
++ data.anint=dslhal_support_byteSwap32(data.anint);
++ for (i=0; i< count; i++)
++ {
++ data.byte[i]=*(src.cptr+i);
++ }
++ data.anint=dslhal_support_byteSwap32(data.anint);
++ DSLHAL_REG32((unsigned int)dst.cptr) = data.anint;
++ src.cptr +=count;
++ dst.anint +=count;
++ count=0;
++ }
++ dprintf(6, "dslhal_support_blockWrite done\n");
++ /* Exit Critical Section */
++ shim_osCriticalExit();
++ return DSLHAL_ERROR_NO_ERRORS;
++} /* end of dslhal_support_blockWrite() */
++
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_support_blockRead
++*
++*********************************************************************************************
++* DESCRIPTION: This rouin simulates DSP memory read as done in ax5 pci nic card
++*
++* INPUT: void *addr, memory address to be read
++* void *buffer, dat buffer to be filled with from memmory
++* size_t count, number of bytes to be written
++*
++* RETURN: 0 --succeeded
++* 1 --Failed
++*
++*****************************************************************************************/
++
++int dslhal_support_blockRead(void *addr, void *buffer, size_t count)
++{
++ int rc;
++ union
++ {
++ int anint; /* DSP location */
++ char *cptr; /* to avoid casts */
++ } src;
++ union
++ {
++ char byte[4];
++ int anint; /* DSP data */
++ } data;
++ union
++ {
++ char *cptr;
++ int *iptr;
++ } dst;
++
++ /* Enter Critical Section */
++ shim_osCriticalEnter();
++
++ dprintf(6,"dslhal_support_blockRead\n");
++
++
++ src.cptr = addr; /* DSP memory location */
++ dst.cptr = buffer; /* local buffer */
++
++ dprintf(6, "Read addr=0x%X, size=0x%X\n", (unsigned int)addr, count);
++
++
++ /*Maps address first*/
++ rc=dslhal_support_hostDspAddressTranslate((unsigned int)addr);
++ if(rc== DSLHAL_ERROR_ADDRESS_TRANSLATE)
++ {
++ dprintf(1, "dslhal_support_hostDspAddressTranslate failed\n");
++ return DSLHAL_ERROR_ADDRESS_TRANSLATE;
++ }
++
++ src.cptr=(unsigned char *)rc;
++
++ /**********************************************
++ * if the source is NOT on a 32-bit boundary *
++ * then we read the full word *
++ * and ignore the first part of it *
++ **********************************************/
++
++ if ((src.anint & 3) && count)
++ {
++ unsigned int anword;
++
++ anword = DSLHAL_REG32((unsigned int)src.cptr & 0xfffffffc);
++ data.anint = dslhal_support_byteSwap32(anword);
++
++ /************************************
++ * there is no need for case 0 *
++ * notice that there are no breaks *
++ * each falls through to the next *
++ ************************************/
++
++ switch (src.anint & 3)
++ {
++ case 1:
++ /* use only byte[1-3] */
++ *(dst.cptr++) = data.byte[1];
++ src.anint++;
++ count--;
++ case 2:
++ /* use byte[2-3] */
++ if (count)
++ {
++ *(dst.cptr++) = data.byte[2];
++ src.anint++;
++ count--;
++ }
++ case 3:
++ /* use byte[3] */
++ if (count)
++ {
++ *(dst.cptr++) = data.byte[3];
++ src.anint++;
++ count--;
++ }
++ }
++ }
++
++ /* the src pointer should now be on a 32-bit boundary */
++ while (count > 3)
++ {
++ unsigned int anword;
++
++ anword=DSLHAL_REG32((unsigned int)src.cptr);
++
++ *dst.iptr = dslhal_support_byteSwap32(anword);
++ src.anint += 4; /* bump the address by four */
++ dst.iptr++; /* bump the data pointer by four */
++ count -= 4; /* decrement the byte count by four */
++ }
++
++ /*******************************
++ * if there's any count left *
++ * then we read the next word *
++ * and ignore the end of it *
++ *******************************/
++ if (count)
++ {
++ unsigned int anword;
++
++ anword= DSLHAL_REG32((unsigned int)src.cptr);
++ data.anint = dslhal_support_byteSwap32(anword);
++
++ /************************************
++ * there is no need for case 0 *
++ * notice that there are no breaks *
++ * each falls through to the next *
++ ************************************/
++ switch (count)
++ {
++ case 1:
++ /* use byte[0] */
++ *(dst.cptr++) = data.byte[0];
++ src.anint++;
++ count--;
++ break;
++ case 2:
++ /* use byte[0-1] */
++ *(dst.cptr++) = data.byte[0];
++ *(dst.cptr++) = data.byte[1];
++ src.anint +=2;
++ count -= 2;
++ break;
++ case 3:
++ /* use only byte[0-2] */
++ *(dst.cptr++) = data.byte[0];
++ *(dst.cptr++) = data.byte[1];
++ *(dst.cptr++) = data.byte[2];
++ src.anint +=3;
++ count -= 3;
++ break;
++ }
++ }
++ /* Exit Critical Section */
++ shim_osCriticalExit();
++
++ return DSLHAL_ERROR_NO_ERRORS;
++
++} /* end of dslhal_support_blockRead() */
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_readDspMailbox
++*
++*********************************************************************************************
++* DESCRIPTION: Reads a message from the mailbox
++*
++* ARGUMENTS: int *pcmd Pointer to command read
++*
++* RETURNS: 0 if successful
++* 1 if no mail
++* NZ otherwise
++*
++*****************************************************************************************/
++
++int dslhal_support_readDspMailbox(tidsl_t *ptidsl, int *pcmd, int *ptag, int *pprm1, int *pprm2)
++{
++ int rc;
++ int cmd;
++ int tag;
++ int prm1;
++ int prm2;
++ unsigned char dspOutInx;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ DEV_HOST_mailboxControl_t mailboxControl;
++ DEV_HOST_dspHostMsg_t dspMailboxMsg[DEV_HOST_DSPQUEUE_LENGTH];
++
++ dprintf(6,"dslhal_support_readDspMailbox\n");
++
++ /* get the DSP main pointer */
++
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,
++ sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ /* Read in the command/response buffer */
++ dspOamSharedInterface.dspHostMailboxControl_p = (DEV_HOST_mailboxControl_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.dspHostMailboxControl_p);
++
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.dspHostMailboxControl_p,
++ &mailboxControl, sizeof(DEV_HOST_mailboxControl_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ /* Change the endianness of the Mailbox Pointer */
++ mailboxControl.dspMsgBuf_p = (DEV_HOST_dspHostMsg_t *) dslhal_support_byteSwap32((unsigned int)mailboxControl.dspMsgBuf_p);
++
++ rc = dslhal_support_blockRead((PVOID)mailboxControl.dspMsgBuf_p,
++ &dspMailboxMsg, (sizeof(DEV_HOST_dspHostMsg_t)*DEV_HOST_DSPQUEUE_LENGTH));
++
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_READ;
++ /* Extract the command/response message index */
++ mailboxControl.hostInInx &= 7;
++ mailboxControl.hostOutInx &= 7;
++ mailboxControl.dspOutInx &= 7;
++ mailboxControl.dspInInx &= 7;
++
++
++ /* check for messages in the mailbox */
++
++ if (mailboxControl.dspOutInx == mailboxControl.dspInInx)
++ {
++ return DSLHAL_ERROR_MAILBOX_NOMAIL;
++ /* no messages to read */
++ }
++
++ /* use bDRESPOutInx as index to DRESPMsgBuf */
++
++ cmd = dspMailboxMsg[mailboxControl.dspOutInx].cmd;
++ tag = dspMailboxMsg[mailboxControl.dspOutInx].tag;
++ prm1= dspMailboxMsg[mailboxControl.dspOutInx].param1;
++ prm2= dspMailboxMsg[mailboxControl.dspOutInx].param2;
++
++ mailboxControl.dspOutInx++; /* increment count */
++ mailboxControl.dspOutInx &= 7; /* only two bits */
++
++ dspOutInx = mailboxControl.dspOutInx;
++
++ /* Read in the command response buffer again to take care of changes */
++ mailboxControl.dspOutInx = dspOutInx;
++ rc = dslhal_support_blockWrite(&mailboxControl.dspOutInx,
++ &dspOamSharedInterface.dspHostMailboxControl_p->dspOutInx, sizeof(BYTE));
++
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_WRITE;
++
++ /* Is the input parameter address non-zero*/
++
++ if (pcmd)
++ {
++ *pcmd = cmd;
++ }
++ if (ptag)
++ {
++ *ptag = tag;
++ }
++ if (pprm1)
++ {
++ *pprm1 = prm1;
++ }
++ if (pprm2)
++ {
++ *pprm2 = prm2;
++ }
++
++ dprintf(6,"dslhal_support_readDspMailbox done\n");
++ dprintf(6,"cmd=%d, tag=%d\n", cmd, tag);
++ dprintf(6,"dslhal_support_readDspMailbox:cmd: 0x%x, tag=%d\n", cmd, tag);
++ return DSLHAL_ERROR_NO_ERRORS;
++
++} /* end of dslhal_support_readDspMailbox() */
++
++/*******************************************************************************************
++* FUNCTION NAME: dslhal_support_writeHostMailbox
++*
++********************************************************************************************
++* DESCRIPTION: Send a message to a mailbox
++*
++* ARGUMENTS: int cmd command to write
++* int tag tag (currently unused)
++* int p1 parameter 1 (currently unused)
++* int p2 parameter 2 (currently unused)
++*
++* RETURNS: 0 if successful
++* NZ otherwise
++*
++*******************************************************************************************/
++
++int dslhal_support_writeHostMailbox(tidsl_t *ptidsl, int cmd, int tag, int p1, int p2)
++{
++ int rc;
++ int index;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ DEV_HOST_mailboxControl_t mailboxControl;
++ DEV_HOST_dspHostMsg_t hostMailboxMsg[DEV_HOST_HOSTQUEUE_LENGTH];
++ unsigned char hostInInx;
++
++ dprintf(6,"dslhal_support_writeHostMailbox:cmd: 0x%x, tag=%d\n", cmd, tag);
++
++ dprintf(6,"cmd=%d, tag=%d\n", cmd, tag);
++
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,
++ sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ /* Read in the command/response buffer */
++ dspOamSharedInterface.dspHostMailboxControl_p = (DEV_HOST_mailboxControl_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.dspHostMailboxControl_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.dspHostMailboxControl_p,
++ &mailboxControl, sizeof(DEV_HOST_mailboxControl_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ /* Change the endianness of the Mailbox Control Pointer */
++ mailboxControl.hostMsgBuf_p = (DEV_HOST_dspHostMsg_t *) dslhal_support_byteSwap32((unsigned int)mailboxControl.hostMsgBuf_p);
++ rc = dslhal_support_blockRead((PVOID)mailboxControl.hostMsgBuf_p,
++ &hostMailboxMsg, (sizeof(DEV_HOST_dspHostMsg_t)*DEV_HOST_HOSTQUEUE_LENGTH));
++
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_READ;
++ /* Extract the command/response message index */
++ mailboxControl.hostInInx &= 7;
++ mailboxControl.hostOutInx &= 7;
++ mailboxControl.dspOutInx &= 7;
++ mailboxControl.dspInInx &= 7;
++
++ /* make sure there's room in the mailbox */
++
++ index = mailboxControl.hostInInx;
++ mailboxControl.hostInInx++;
++ mailboxControl.hostInInx &= 7;
++ hostInInx = mailboxControl.hostInInx;
++ if (mailboxControl.hostInInx == mailboxControl.hostOutInx)
++ {
++ /* mailbox is full */
++ return DSLHAL_ERROR_MAILBOX_OVERFLOW;
++ }
++
++ /* use bOCMDInInx as index to OCMDMsgBuf */
++ hostMailboxMsg[index].cmd = (BYTE) cmd;
++ hostMailboxMsg[index].tag = (BYTE) tag;
++ hostMailboxMsg[index].param1 = (BYTE) p1;
++ hostMailboxMsg[index].param2 = (BYTE) p2;
++ rc = dslhal_support_blockWrite(&hostMailboxMsg,
++ (PVOID)mailboxControl.hostMsgBuf_p,
++ sizeof(DEV_HOST_dspHostMsg_t)*DEV_HOST_HOSTQUEUE_LENGTH);
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockWrite failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ rc = dslhal_support_blockWrite(&mailboxControl,
++ &dspOamSharedInterface.dspHostMailboxControl_p,
++ sizeof(DEV_HOST_mailboxControl_t));
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_WRITE;
++ /* update the index */
++ mailboxControl.hostInInx = hostInInx;
++ rc = dslhal_support_blockWrite(&mailboxControl.hostInInx,
++ &dspOamSharedInterface.dspHostMailboxControl_p->hostInInx,
++ sizeof(BYTE));
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_WRITE;
++
++ dprintf(6,"dslhal_support_writeHostMailbox done\n");
++ return DSLHAL_ERROR_NO_ERRORS;
++
++}
++/* end of dslhal_support_writeHostMailbox() */
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_readTextMailbox
++*
++*********************************************************************************************
++* DESCRIPTION: Reads a message from the mailbox
++*
++* ARGUMENTS: int *pcmd Pointer to command read
++*
++* RETURNS: 0 if successful
++* 1 if no mail
++* NZ otherwise
++*
++*****************************************************************************************/
++
++int dslhal_support_readTextMailbox(tidsl_t *ptidsl, int *pmsg1, int *pmsg2)
++{
++ int rc;
++ unsigned int msg1;
++ unsigned int msg2;
++ unsigned char textOutInx;
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ DEV_HOST_mailboxControl_t mailboxControl;
++ DEV_HOST_textMsg_t textMailboxMsg[DEV_HOST_TEXTQUEUE_LENGTH];
++
++ dprintf(6,"dslhal_support_readTextMailbox\n");
++
++ /* get the DSP main pointer */
++
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterfacePtr_t) ptidsl->pmainAddr;
++
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,
++ sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ /* Read in the command/response buffer */
++ dspOamSharedInterface.dspHostMailboxControl_p = (DEV_HOST_mailboxControl_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.dspHostMailboxControl_p);
++
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.dspHostMailboxControl_p,
++ &mailboxControl, sizeof(DEV_HOST_mailboxControl_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ /* Change the endianness of the Mailbox Pointer */
++ mailboxControl.textMsgBuf_p = (DEV_HOST_textMsg_t *) dslhal_support_byteSwap32((unsigned int)mailboxControl.textMsgBuf_p);
++
++ rc = dslhal_support_blockRead((PVOID)mailboxControl.textMsgBuf_p,
++ &textMailboxMsg, (sizeof(DEV_HOST_textMsg_t)*DEV_HOST_DSPQUEUE_LENGTH));
++
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_READ;
++ /* Extract the command/response message index */
++
++ mailboxControl.textInInx &= 7;
++ mailboxControl.textOutInx &= 7;
++
++ /* check for messages in the mailbox */
++
++ if (mailboxControl.textOutInx == mailboxControl.textInInx)
++ {
++ return DSLHAL_ERROR_MAILBOX_NOMAIL;
++ /* no messages to read */
++ }
++
++ /* use bDRESPOutInx as index to DRESPMsgBuf */
++
++ msg1 = textMailboxMsg[mailboxControl.textOutInx].msgPart1;
++ msg2 = textMailboxMsg[mailboxControl.textOutInx].msgPart2;
++ msg1 = (unsigned int) dslhal_support_byteSwap32((unsigned int)msg1);
++ msg2 = (unsigned int) dslhal_support_byteSwap32((unsigned int)msg2);
++
++ mailboxControl.textOutInx++; /* increment count */
++ mailboxControl.textOutInx &= 7; /* only two bits */
++
++ textOutInx = mailboxControl.textOutInx;
++
++ /* Read in the command response buffer again to take care of changes */
++
++ mailboxControl.textOutInx = textOutInx;
++
++ rc = dslhal_support_blockWrite(&mailboxControl.textOutInx,
++ &dspOamSharedInterface.dspHostMailboxControl_p->textOutInx, sizeof(BYTE));
++
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_WRITE;
++
++ /* Is the input parameter address non-zero*/
++
++ if (pmsg1)
++ {
++ *pmsg1 = msg1;
++ }
++ if (pmsg2)
++ {
++ *pmsg2 = msg2;
++ }
++
++ dprintf(6,"dslhal_support_readTextMailbox done\n");
++ dprintf(6,"msgPart1=%d, msgPart2=%d\n", msg1, msg2);
++ dprintf(6,"dslhal_support_readTextMailbox:Message Part1: 0x%x, tag=0x%x\n", msg1, msg2);
++ return DSLHAL_ERROR_NO_ERRORS;
++
++} /* end of dslhal_support_readTextMailbox() */
++
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_hostDspCodeDownload()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* download DSP image from host memory to dsp memory
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++
++int dslhal_support_hostDspCodeDownload(tidsl_t * ptidsl)
++{
++
++ unsigned int index;
++ int rc = 0, i;
++ unsigned char *iptr; /* image pointer */
++ unsigned int numbytes,olayXfer,olayStore;
++ /* unsigned int holdSecPhyAddr=0,holdSecVirtAddr; */
++ unsigned int *olayStart;
++ size_t len; /* size of the file */
++ size_t expoffset; /* expected offset for next section header */
++ unsigned short checksum;
++ unsigned int crc32;
++ unsigned char * image;
++ char *tmp = (char *)DEV_HOST_DSP_OAM_POINTER_LOCATION;
++ DEV_HOST_dspVersionDef_t dspVersion;
++#if SWTC
++ DEV_HOST_tcHostCommDef_t TCHostCommDef;
++#endif
++ DEV_HOST_oamWrNegoParaDef_t OamWrNegoParaDef;
++ DEV_HOST_dspOamSharedInterface_t dspOamSharedInterface, *pdspOamSharedInterface;
++ DEV_HOST_olayDpDef_t olayDpParms;
++ DEV_HOST_profileBase_t profileList;
++#ifndef NO_ACT
++ DEV_HOST_consBufDef_t constDisp;
++#endif
++#if CO_PROFILES
++ DEV_HOST_coData_t coData;
++#endif
++ DEV_HOST_olayDpPageDef_t olayDpPageDef[NUM_PAGES];
++ union
++ {
++ char byte[4];
++ unsigned short hword[2];
++ unsigned int aword;
++ } data;
++
++ struct _header
++ {
++ char signature[6];
++ unsigned short sectcount;
++ unsigned int length;
++ } header;
++
++ struct _section
++ {
++ unsigned int addr;
++ unsigned int length;
++ unsigned int offset;
++ unsigned int page;
++ };/* section[MAXSECTIONS]; */
++
++ struct _section *sptr;
++ unsigned int secAddr, secLength, secOffset, secPage;
++
++
++ dprintf(5,"dslhal_support_hostDspCodeDownload\n");
++ image = ptidsl->fwimage;
++
++ if (!image)
++ {
++ dprintf(1,"no image file\n");
++ return DSLHAL_ERROR_NO_FIRMWARE_IMAGE;
++ }
++
++ iptr=image;
++
++ numbytes = sizeof(header);
++
++ shim_osMoveMemory((char *) &header, (char *)iptr, numbytes);
++ header.length = dslhal_support_byteSwap32(header.length);
++ header.sectcount = dslhal_support_byteSwap16(header.sectcount);
++#if 0
++ crc32 = dslhal_support_computeCrc32((unsigned char*)&crcTest[0],20);
++ dprintf(6,"CRC-32 for the crcTest: 0x%x",crc32);
++ dprintf(4,"header.length=%d, header.sectcount=0x%X\n", header.length, header.sectcount);
++#endif
++ /* point to the checksum */
++ /* compute the checksum on CRC32 here */
++ iptr = image + header.length-4;
++ numbytes = sizeof(data.aword);
++
++ dprintf(5,"tiload: check checksum\n");
++ shim_osMoveMemory((char *)&(data.byte), (char *)iptr, numbytes);
++
++ crc32 = dslhal_support_computeCrc32(image,ptidsl->imagesize);
++ dprintf(5,"CRC-32 for the Binary: 0x%x",crc32);
++ /* CRC currently not added to the DSP binary, so this code is commented out */
++ /*
++ data.aword = dslhal_support_byteSwap32(data.aword);
++ if (data.aword != crc32)
++ {
++ dprintf(1,"Checksum error\n");
++ }
++ */
++ /* Verify signature - Changed from "320C6x" to "TIDSL" for load 80 */
++
++ header.signature[5]='\0';
++ dprintf(5, "signature=%s\n", header.signature);
++
++ if (shim_osStringCmp(header.signature, "TIDSL"))
++ {
++ dprintf(1,"Signature not match\n");
++ return DSLHAL_ERROR_FIRMWARE_OFFSET;
++ }
++
++ dprintf(5,"tiload: check sect count\n");
++ /* check section count */
++
++ if (header.sectcount > MAXSECTIONS)
++ {
++ dprintf(1,"Section # %d exceeds max %d\n", header.sectcount, MAXSECTIONS);
++ return DSLHAL_ERROR_FIRMWARE_OFFSET;
++ }
++ else
++ {
++ dprintf(5,"found %d sections\n", header.sectcount);
++ }
++
++ /* Validation of Section offsets */
++
++ /* point to the first section */
++ len = header.length; /* file size in bytes */
++ expoffset = sizeof(struct _header) + header.sectcount * sizeof(struct _section);
++
++ dprintf(5,"tiload: check offset\n");
++ for (index=0; index<header.sectcount; index++) /* parse the sections one by one */
++ {
++ numbytes = sizeof(struct _header) + index * sizeof(struct _section); /* Compute Section Offset */
++ sptr = (struct _section *)(image + numbytes); /* Section Pointer to beginning of the section */
++
++ secAddr = dslhal_support_byteSwap32(sptr->addr);
++ secOffset = dslhal_support_byteSwap32(sptr->offset);
++ secLength = dslhal_support_byteSwap32(sptr->length);
++ secPage = dslhal_support_byteSwap32(sptr->page);
++
++ /* validate offset */
++ if ( secOffset== 0xffffffff)
++ {
++ /* special case: zero fill */
++ /* offset is valid, don't change expoffset */
++ }
++ else
++ {
++ if (secOffset > len-4)
++ {
++ dprintf(5,"Offset error\n");
++ return DSLHAL_ERROR_FIRMWARE_OFFSET;
++ }
++
++ /* determine expected offset of NEXT section */
++ expoffset = secLength + secOffset;
++
++ /* all addresses must be on word boundaries */
++ if (secAddr & 3)
++ {
++
++ }
++ }
++ }
++
++ /* check final offset - should just be a checksum left */
++/* IMPORTANT 11/24/02 --> Got this error... but bypassed for Pf of Concept*/
++ /*
++ if (expoffset != len-4)
++ {
++ dprintf(5,"Final offset error\n");
++ return DSLHAL_ERROR_FIRMWARE_OFFSET;
++ }
++ */
++
++ /* Actual Code loading to DSP Memory */
++
++ /* Initialize DSP Data Memory before code load*/
++ dprintf(5,"Zero Prefill DSP DMEM\n");
++ DSLHAL_REG32(ADSLSSADR)=0x80000000;
++ shim_osZeroMemory((char *)0xa1000000, 0x10000);
++ /* Load sections from the image */
++ for (index=0; index<header.sectcount; index++) /* Parse each section */
++ {
++ numbytes = sizeof(header) + index * sizeof(struct _section); /* Compute offset to next section */
++ sptr = (struct _section *)(image + numbytes); /* Point to next section */
++
++ secAddr = dslhal_support_byteSwap32(sptr->addr);
++ secOffset = dslhal_support_byteSwap32(sptr->offset);
++ secLength = dslhal_support_byteSwap32(sptr->length);
++ secPage = dslhal_support_byteSwap32(sptr->page);
++
++ data.aword = secAddr;
++ checksum += data.byte[0] + data.byte[1] + data.byte[2] + data.byte[3];
++
++ data.aword = secLength;
++ checksum += data.byte[0] + data.byte[1] + data.byte[2] + data.byte[3];
++
++ data.aword = secOffset;
++ checksum += data.byte[0] + data.byte[1] + data.byte[2] + data.byte[3];
++
++ data.aword = secPage;
++ checksum += data.byte[0] + data.byte[1] + data.byte[2] + data.byte[3];
++
++
++ /* validate offset */
++ if (secOffset == 0xffffffff)
++ {
++ /* special case: zero fill */
++ /* offset is valid, don't change expoffset */
++ }
++ else
++ {
++ /* real offset */
++ if(secOffset > len-4)
++ {
++ dprintf(5,"section[%u] offset too big (%X/%X)\n", index,
++ secOffset, len-4);
++
++ return DSLHAL_ERROR_FIRMWARE_OFFSET;
++ }
++
++ /* determine expected offset of NEXT section */
++ expoffset = secLength + secOffset;
++
++ }
++
++ }
++
++ /* check final offset - should just be a checksum left */
++ /*
++ if(expoffset != len-4)
++ {
++ dprintf(1,"sections don't span full file (%X/%X)\n",expoffset,len-2);
++ return DSLHAL_ERROR_FIRMWARE_OFFSET;
++ }
++ */
++ dprintf(5,"tiload: load binary\n");
++
++ for (index=0; index<header.sectcount; index++)
++ {
++ numbytes = sizeof(header) + index * sizeof(struct _section);
++ sptr = (struct _section *)(image + numbytes);
++
++ secAddr = dslhal_support_byteSwap32(sptr->addr);
++ secOffset = dslhal_support_byteSwap32(sptr->offset);
++ secLength = dslhal_support_byteSwap32(sptr->length);
++ secPage = dslhal_support_byteSwap32(sptr->page);
++ dprintf(5,"loading section %u\n", index);
++ dprintf(5,"section %u: addr: %X\n", index, secAddr);
++ dprintf(5,"section %u: length: %X\n", index, secLength);
++ dprintf(5,"section %u: offset: %X\n", index, secOffset);
++ dprintf(5,"section %u: page: %X\n", index, secPage);
++
++ /* point to the section's data */
++ if(secOffset != 0xffffffff)
++ {
++ /* Load this section of data */
++ iptr = image + secOffset;
++ dprintf(6, "iptr %8x\n", (unsigned int)iptr);
++ }
++
++ if(secPage)
++ {
++ dprintf(6,"OVERLAY PAGE #%d\n",secPage);
++ /* overlay page, don't write to dsp yet, save into host memory*/
++
++ dprintf(6,"Section Length: %d \n",secLength);
++ ptidsl->olayDpPage[secPage].PmemStartWtAddr = (unsigned int) shim_osAllocateDmaMemory(secLength);
++ if(ptidsl->olayDpPage[secPage].PmemStartWtAddr == NULL)
++ {
++ dprintf(1, "overlay page allocate error\n");
++ return DSLHAL_ERROR_OVERLAY_MALLOC;
++ }
++#ifdef PRE_SILICON
++ ptidsl->olayDpPage[secPage].overlayHostAddr = ((((ptidsl->olayDpPage[secPage].PmemStartWtAddr)-0x84000000)-0x10000000)+0x030b0000);
++#else
++ /* ptidsl->olayDpPage[secPage].overlayHostAddr = ((unsigned int)(ptidsl->olayDpPage[secPage].PmemStartWtAddr)&~0xe0000000); */
++ ptidsl->olayDpPage[secPage].overlayHostAddr = virtual2Physical((unsigned int)ptidsl->olayDpPage[secPage].PmemStartWtAddr);
++#endif
++ dprintf(6,"Allocated Addr: 0x%x \t Xlated Addr: 0x%x \n",ptidsl->olayDpPage[secPage].PmemStartWtAddr,ptidsl->olayDpPage[secPage].overlayHostAddr);
++
++ ptidsl->olayDpPage[secPage].overlayHostAddr = (unsigned int)dslhal_support_byteSwap32(ptidsl->olayDpPage[secPage].overlayHostAddr);
++ ptidsl->olayDpPage[secPage].OverlayXferCount = secLength;
++ ptidsl->olayDpPage[secPage].BinAddr = secAddr;
++ ptidsl->olayDpPage[secPage].SecOffset = secOffset;
++ shim_osMoveMemory((char *)ptidsl->olayDpPage[secPage].PmemStartWtAddr, (char *)iptr, secLength);
++ /* RamP Image ByteSwap test */
++ olayStart = (unsigned int *)ptidsl->olayDpPage[secPage].PmemStartWtAddr;
++
++ for(olayXfer=0;olayXfer< secLength/4;olayXfer++)
++ {
++ olayStore = *(unsigned int *)olayStart;
++ olayStore = (unsigned int)dslhal_support_byteSwap32(olayStore);
++ *(unsigned int*)olayStart = olayStore;
++ dprintf(5, "Addr:0x%x \t Content: 0x%x \n",olayStart,olayStore);
++ olayStart++;
++ olayStore=0;
++ }
++ /* RamP Image ByteSwap test */
++ /* compute the CRC of each overlay page and Store the Checksum in a local global variable */
++ /* This Value of CRC is to be compared with the header where all the CRC bytes are lumped together */
++ ptidsl->olayDpPage[secPage].olayPageCrc32 = dslhal_support_computeCrc32((char *)ptidsl->olayDpPage[secPage].PmemStartWtAddr, ptidsl->olayDpPage[secPage].OverlayXferCount);
++
++ shim_osWriteBackCache((void *)ptidsl->olayDpPage[secPage].PmemStartWtAddr, secLength);
++ }
++ else
++ {
++ rc = secAddr&0xff000000;
++ if(rc && rc!=0x80000000)
++ {
++ dprintf(4,"Not DSP PMEM/DMEM\n");
++ /* don't write to dsp, save into host memory*/
++ dprintf(4,"Section Addr: %x Section Length: %d \n",secAddr,secLength);
++ ptidsl->coProfiles.PmemStartWtAddr = (unsigned int) shim_osAllocateDmaMemory(secLength);
++ if(ptidsl->coProfiles.PmemStartWtAddr == NULL)
++ {
++ dprintf(1, "memory allocate error\n");
++ return DSLHAL_ERROR_OVERLAY_MALLOC;
++ }
++ ptidsl->coProfiles.overlayHostAddr = virtual2Physical((unsigned int)ptidsl->coProfiles.PmemStartWtAddr);
++ dprintf(4,"Allocated Addr: 0x%x \t Xlated Addr: 0x%x \n",ptidsl->coProfiles.PmemStartWtAddr, ptidsl->coProfiles.overlayHostAddr);
++ ptidsl->coProfiles.overlayHostAddr = (unsigned int)dslhal_support_byteSwap32(ptidsl->coProfiles.overlayHostAddr);
++ ptidsl->coProfiles.OverlayXferCount = secLength;
++ ptidsl->coProfiles.BinAddr = secAddr;
++ ptidsl->coProfiles.SecOffset = secOffset;
++
++ shim_osMoveMemory((char *)ptidsl->coProfiles.PmemStartWtAddr, (char *)iptr, secLength);
++ /* RamP Image ByteSwap test */
++ olayStart = (unsigned int *)ptidsl->coProfiles.PmemStartWtAddr;
++
++ for(olayXfer=0;olayXfer< secLength/4;olayXfer++)
++ {
++ olayStore = *(unsigned int *)olayStart;
++ olayStore = (unsigned int)dslhal_support_byteSwap32(olayStore);
++ *(unsigned int*)olayStart = olayStore;
++ dprintf(5, "Addr:0x%x \t Content: 0x%x \n",olayStart,olayStore);
++ olayStart++;
++ olayStore=0;
++ }
++ shim_osWriteBackCache((void *)ptidsl->coProfiles.PmemStartWtAddr, secLength);
++ }
++ else
++ {
++ /* IMPORTANT: write image to DSP memory */
++ rc=dslhal_support_blockWrite((void *)iptr, (void *)secAddr, secLength);
++ if(rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ shim_osClockWait(0x50000);
++ /*
++ rc=dslhal_support_blockRead((void*)secAddr, (void*)tmpBuffer, secLength);
++ if(rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ for(i=0;i<secLength;i++)
++ {
++ if(*iptr
++ }*/
++ }
++ }
++ } /* end of write dsp image */
++
++ /***********************************************************************************
++ * Start to fillup various values to our hardware structure for late use
++ ************************************************************************************/
++
++ /* get main pointer for data */
++
++ rc = dslhal_support_blockRead(tmp, &pdspOamSharedInterface, sizeof(unsigned int));
++ dprintf(5, "tmp=0x%X, addr=0x%X\n", (unsigned int)tmp, (unsigned int)pdspOamSharedInterface);
++ pdspOamSharedInterface= (DEV_HOST_dspOamSharedInterface_t *)dslhal_support_byteSwap32((unsigned int)pdspOamSharedInterface);
++ dprintf(5, "tmp=0x%X, addr=0x%X\n", (unsigned int)tmp, (unsigned int)pdspOamSharedInterface);
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ if(!pdspOamSharedInterface)
++ {
++ dprintf(1,"Couldn't read main pointer\n");
++ return DSLHAL_ERROR_INVALID_PARAM;
++ }
++
++ ptidsl->pmainAddr=pdspOamSharedInterface;
++
++ /* read the OamSharedInterfaceStructure */
++
++ dprintf(5,"ptidsl->hostIf.mainAddr=0x%X\n", (unsigned int)ptidsl->pmainAddr);
++
++ /* get the pointer to DSP-OAM Shared Interface */
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,
++ sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ /* Communicate the Allocated Memory Address to DSP to choose CO Profiles */
++
++ /* Change the Endianness of the profileList pointer */
++ dspOamSharedInterface.profileList_p = (DEV_HOST_profileBase_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.profileList_p);
++ /* Access the profileList Structure */
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.profileList_p,&profileList, sizeof(DEV_HOST_profileBase_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ dprintf(2,"Old Addr:%x New: %x \n",profileList.hostProfileBase_p,ptidsl->coProfiles.overlayHostAddr);
++ profileList.hostProfileBase_p = (DEV_HOST_coData_t *)ptidsl->coProfiles.overlayHostAddr;
++ rc = dslhal_support_blockWrite(&profileList,(PVOID)dspOamSharedInterface.profileList_p,sizeof(DEV_HOST_profileBase_t));
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_WRITE;
++
++ /* Communicate the Allocated Memory Address to DSP to do overlays */
++
++ /* Change the Endianness of the olayDpDef pointer */
++ dspOamSharedInterface.olayDpParms_p = (DEV_HOST_olayDpDef_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.olayDpParms_p);
++ /* Access the olayDpDef Structure */
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.olayDpParms_p,&olayDpParms, sizeof(DEV_HOST_olayDpDef_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++
++ for(i=1;i<NUM_PAGES;i++)
++ {
++ /* Change the endianness of the olayDpPageDef Pointer */
++ olayDpParms.olayDpPage_p[i] = (DEV_HOST_olayDpPageDef_t *) dslhal_support_byteSwap32((unsigned int)olayDpParms.olayDpPage_p[i]);
++ /* Access the olayDpPageDef Structure */
++ rc = dslhal_support_blockRead((PVOID)olayDpParms.olayDpPage_p[i],&olayDpPageDef[i],sizeof(DEV_HOST_olayDpPageDef_t));
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_READ;
++ olayDpPageDef[i].overlayHostAddr = ptidsl->olayDpPage[i].overlayHostAddr;
++ rc = dslhal_support_blockWrite(&olayDpPageDef[i],(PVOID)olayDpParms.olayDpPage_p[i],sizeof(DEV_HOST_olayDpPageDef_t));
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_WRITE;
++ }
++
++ /* Change the endianness of the Datapump Version Pointer */
++ dspOamSharedInterface.datapumpVersion_p = (DEV_HOST_dspVersionDef_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.datapumpVersion_p);
++
++ /* get DSPVersion itself */
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.datapumpVersion_p,&dspVersion, sizeof(DEV_HOST_dspVersionDef_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ /* table_dsp info */
++#if SWTC
++ dspOamSharedInterface.tcHostComm_p = (DEV_HOST_tcHostCommDef_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.tcHostComm_p);
++ rc = dslhal_support_blockRead(&pdspOamSharedInterface->tcHostComm_p,
++ &pTCHostCommDef, 4);
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ pTCHostCommDef=(DEV_HOST_tcHostCommDef_t *) dslhal_support_byteSwap32((unsigned int)pTCHostCommDef);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.tcHostComm_p,
++ &TCHostCommDef, sizeof(DEV_HOST_tcHostCommDef_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++#endif
++ /* Select the Multimode Training */
++ dspOamSharedInterface.oamWriteNegoParams_p = (DEV_HOST_oamWrNegoParaDef_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.oamWriteNegoParams_p);
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.oamWriteNegoParams_p, &OamWrNegoParaDef, sizeof(DEV_HOST_oamWrNegoParaDef_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++switch(dspVersion.netService)
++ {
++ case 1: OamWrNegoParaDef.stdMode = MULTI_MODE;
++ dprintf(5,"POTS Service \n");
++ ptidsl->netService = 1;
++ break;
++ case 2: OamWrNegoParaDef.stdMode = GDMT_MODE;
++ dprintf(5,"ISDN Service \n");
++ ptidsl->netService = 2;
++ break;
++ default: OamWrNegoParaDef.stdMode = T1413_MODE;
++ dprintf(5,"Default Service \n");
++ break;
++ }
++
++ ptidsl->AppData.StdMode = (unsigned int)OamWrNegoParaDef.stdMode;
++
++ OamWrNegoParaDef.oamFeature = dslhal_support_byteSwap32((OAMFEATURE_TC_SYNC_DETECT_MASK));
++ /* Set the flag to start retraining if the margin of the modem drops below
++ default margin during showtime */
++
++ OamWrNegoParaDef.marginMonitorShwtme = FALSE;
++ /* Set the flag to start retraining if the margin of the modem drops below default margin during training */
++
++ OamWrNegoParaDef.marginMonitorTrning = FALSE;
++ OamWrNegoParaDef.dsToneTurnoff_f = 0;
++ dslhal_support_blockWrite(&OamWrNegoParaDef,
++ (PVOID)dspOamSharedInterface.oamWriteNegoParams_p, sizeof(DEV_HOST_oamWrNegoParaDef_t));
++ rc=dslhal_support_setInterruptMask(ptidsl,0);
++ if(rc!=DSLHAL_ERROR_NO_ERRORS)
++ return rc;
++ /* Co Profile Test */
++#if CO_PROFILES
++ dspOamSharedInterface.profileList_p = (DEV_HOST_profileBase_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.profileList_p);
++ /* Access the profileList Structure */
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.profileList_p,&profileList, sizeof(DEV_HOST_profileBase_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ profileList.hostProfileBase_p = (DEV_HOST_coData_t *)dslhal_support_byteSwap32((unsigned int)profileList.hostProfileBase_p);
++ rc = dslhal_support_blockRead((PVOID)profileList.hostProfileBase_p,&coData, sizeof(DEV_HOST_coData_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ dprintf(2,"Current Profile Vendor Id: %x \n",coData.phyAgcPgaTarget);
++ coData.phyAgcPgaTarget = 0xcaba;
++ rc = dslhal_support_blockWrite(&coData,(PVOID)profileList.hostProfileBase_p,sizeof(DEV_HOST_coData_t));
++ if(rc)
++ return DSLHAL_ERROR_BLOCK_WRITE;
++#endif
++ /* End of CO Profile Test */
++
++#ifndef NO_ACT
++ /* Constellation Display Buffer Allocate */
++ ptidsl->constDisplay.PmemStartWtAddr = (unsigned int) shim_osAllocateDmaMemory(DSP_CONSTELLATION_BUFFER_SIZE);
++ if(ptidsl->constDisplay.PmemStartWtAddr == NULL)
++ {
++ dprintf(1, "memory allocate error\n");
++ return DSLHAL_ERROR_OVERLAY_MALLOC;
++ }
++ shim_osZeroMemory((void*)ptidsl->constDisplay.PmemStartWtAddr,DSP_CONSTELLATION_BUFFER_SIZE);
++ ptidsl->constDisplay.overlayHostAddr = virtual2Physical((unsigned int)ptidsl->constDisplay.PmemStartWtAddr);
++ dprintf(4,"Allocated Addr: 0x%x \t Xlated Addr: 0x%x \n",ptidsl->constDisplay.PmemStartWtAddr, ptidsl->constDisplay.overlayHostAddr);
++ ptidsl->constDisplay.OverlayXferCount = DSP_CONSTELLATION_BUFFER_SIZE;
++
++ /* Communicate the Allocated Buffer for DSP load Constellation Data */
++
++ /* Change the Endianness of the profileList pointer */
++ dspOamSharedInterface.consDispVar_p = (DEV_HOST_consBufDef_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.consDispVar_p);
++ /* Access the profileList Structure */
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.consDispVar_p,&constDisp, sizeof(DEV_HOST_consBufDef_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ dprintf(2,"Constellation Old Addr:%x New: %x \n",constDisp.consDispStartAddr,ptidsl->constDisplay.overlayHostAddr);
++ constDisp.consDispStartAddr = (unsigned int)dslhal_support_byteSwap32(ptidsl->constDisplay.overlayHostAddr);
++ constDisp.consDispCurrentAddr = constDisp.consDispStartAddr;
++ constDisp.consDispBufLen = (unsigned int)dslhal_support_byteSwap32(DSP_CONSTELLATION_BUFFER_SIZE);
++ rc = dslhal_support_blockWrite(&constDisp,(PVOID)dspOamSharedInterface.consDispVar_p,sizeof(DEV_HOST_consBufDef_t));
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_WRITE;
++#endif
++ dprintf(5,"dslhal_support_hostDspCodeDownload() completed.\n");
++ return DSLHAL_ERROR_NO_ERRORS;
++
++} /* end of dslhal_support_hostDspCodeDownload() */
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_readDelineationState()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* download DSP image from host memory to dsp memory
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++
++unsigned int dslhal_support_readDelineationState(tidsl_t * ptidsl)
++{
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ DEV_HOST_atmStats_t atmStats;
++ DEV_HOST_dsAtmStats_t dsAtmStats0;
++ unsigned int rc=0, delinState=0;
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterface_t *) ptidsl->pmainAddr;
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ dspOamSharedInterface.atmStats_p = (DEV_HOST_atmStats_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.atmStats_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.atmStats_p,&atmStats, sizeof(DEV_HOST_atmStats_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ atmStats.ds0_p = (DEV_HOST_dsAtmStats_t *) dslhal_support_byteSwap32((unsigned int)atmStats.ds0_p);
++
++ rc = dslhal_support_blockRead((PVOID)atmStats.ds0_p,&dsAtmStats0, (sizeof(DEV_HOST_dsAtmStats_t)));
++
++ if (rc)
++ return rc;
++ delinState = dslhal_support_byteSwap32(dsAtmStats0.delineationState);
++ if(delinState == TC_SYNC)
++ ptidsl->lConnected = 1;
++ else
++ ptidsl->lConnected = 0;
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_processModemStateBitField()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* download DSP image from host memory to dsp memory
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++
++unsigned int dslhal_support_processModemStateBitField(tidsl_t * ptidsl)
++{
++ int rc, offset[2]={2,0};
++ int modemStateBitFields[NUMBER_OF_BITFIELDS],changedField=0;
++ rc = dslhal_api_dspInterfaceRead(ptidsl,(unsigned int)ptidsl->pmainAddr,2,(unsigned int *)&offset,
++ (unsigned char *)&modemStateBitFields,NUMBER_OF_BITFIELDS*sizeof(int));
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_READ;
++ for(rc=0;rc<NUMBER_OF_BITFIELDS;rc++)
++ dprintf(4,"Bit Field %d: 0x%x \n",rc+1,dslhal_support_byteSwap32((unsigned int)modemStateBitFields[rc]));
++
++ for(rc=NUMBER_OF_BITFIELDS;rc>0;rc--)
++ {
++ if(ptidsl->modemStateBitField[rc-1]!=modemStateBitFields[rc-1])
++ {
++ changedField = rc;
++ break;
++ }
++ }
++ if(changedField)
++ {
++ for(rc=0;rc<32;rc++)
++ {
++ if(modemStateBitFields[changedField-1] & dslhal_support_byteSwap32((BITFIELD_SCAN >> rc)))
++ break;
++ }
++ dprintf(5,"Changed Field : %d Changed Bit : %d \n",changedField,(31-rc));
++ ptidsl->rState = ((changedField*100) + (31-rc));
++ dprintf(5,"Modem State : %d \n",ptidsl->rState);
++ shim_osMoveMemory((void *)ptidsl->modemStateBitField,(void *)modemStateBitFields, 4*NUMBER_OF_BITFIELDS);
++ }
++
++ switch(changedField)
++ {
++ case 1: if((ptidsl->rState >= ATU_RIDLE) && (ptidsl->AppData.bState < RSTATE_IDLE))
++ ptidsl->AppData.bState = RSTATE_IDLE;
++ if((ptidsl->rState >= GDMT_NSFLR) && (ptidsl->AppData.bState < RSTATE_INIT))
++ ptidsl->AppData.bState = RSTATE_INIT;
++ if((ptidsl->rState >= GDMT_ACKX) && (ptidsl->AppData.bState < RSTATE_HS))
++ ptidsl->AppData.bState = RSTATE_HS;
++ break;
++
++ case 2: if((ptidsl->rState >= T1413_NSFLR) && (ptidsl->AppData.bState < RSTATE_INIT))
++ ptidsl->AppData.bState = RSTATE_INIT;
++ if((ptidsl->rState >= T1413_ACKX) && (ptidsl->AppData.bState < RSTATE_HS))
++ ptidsl->AppData.bState = RSTATE_HS;
++ if((ptidsl->rState == ATU_RSHOWTIME) && (ptidsl->AppData.bState < RSTATE_SHOWTIME))
++ ptidsl->AppData.bState = RSTATE_SHOWTIME;
++ break;
++
++ case 3: if((ptidsl->rState >= ADSL2_COMB3) && (ptidsl->AppData.bState < RSTATE_INIT))
++ ptidsl->AppData.bState = RSTATE_INIT;
++ if((ptidsl->rState >= ADSL2_RPARAMS) && (ptidsl->AppData.bState < RSTATE_HS))
++ ptidsl->AppData.bState = RSTATE_HS;
++ break;
++
++ case 4: break;
++ default: break;
++ }
++
++ ptidsl->stateTransition = modemStateBitFields[1];
++ switch(ptidsl->AppData.bState)
++ {
++ case RSTATE_IDLE: ptidsl->AppData.idleTick=shim_osClockTick();
++ ptidsl->AppData.initTick=0;
++ ptidsl->AppData.showtimeTick=0;
++ break;
++ case RSTATE_HS: if(!ptidsl->AppData.initTick)
++ {
++ ptidsl->AppData.initTick=shim_osClockTick();
++ }
++ ptidsl->AppData.showtimeTick=0;
++ break;
++ case RSTATE_SHOWTIME: if(!ptidsl->AppData.showtimeTick)
++ ptidsl->AppData.showtimeTick=shim_osClockTick();
++ break;
++ default: break;
++ }
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_setInterruptMask()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++
++unsigned int dslhal_support_setInterruptMask(tidsl_t * ptidsl,unsigned int inputMask)
++{
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ DEV_HOST_hostInterruptMask_t interruptMask;
++ unsigned int rc=0;
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterface_t *) ptidsl->pmainAddr;
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ dspOamSharedInterface.hostInterruptMask_p =(DEV_HOST_hostInterruptMask_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.hostInterruptMask_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.hostInterruptMask_p,
++ &interruptMask, sizeof(DEV_HOST_hostInterruptMask_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ if(inputMask & MASK_MAILBOX_INTERRUPTS)
++ {
++ dprintf(7,"Mailbox Interrupts Masked \n");
++ dprintf(7,"interruptMask.maskBitField1 = %d \n",dslhal_support_byteSwap32(interruptMask.maskBitField1));
++ interruptMask.maskBitField1 |= dslhal_support_byteSwap32(MASK_MAILBOX_INTERRUPTS);
++ dprintf(7,"interruptMask.maskBitField1 = %d \n",dslhal_support_byteSwap32(interruptMask.maskBitField1));
++ }
++ if(inputMask & MASK_BITFIELD_INTERRUPTS)
++ {
++ dprintf(7,"Bit field Interrupts Masked \n");
++ dprintf(7,"interruptMask.maskBitField1 = %d \n",dslhal_support_byteSwap32(interruptMask.maskBitField1));
++ interruptMask.maskBitField1 |= dslhal_support_byteSwap32(MASK_BITFIELD_INTERRUPTS);
++ dprintf(7,"interruptMask.maskBitField1 = %d \n",dslhal_support_byteSwap32(interruptMask.maskBitField1));
++ }
++ if(inputMask & MASK_HEARTBEAT_INTERRUPTS)
++ {
++ dprintf(7,"Bit field Interrupts Masked \n");
++ dprintf(7,"interruptMask.maskBitField1 = %d \n",dslhal_support_byteSwap32(interruptMask.maskBitField1));
++ interruptMask.maskBitField1 |= dslhal_support_byteSwap32(MASK_HEARTBEAT_INTERRUPTS);
++ dprintf(7,"interruptMask.maskBitField1 = %d \n",dslhal_support_byteSwap32(interruptMask.maskBitField1));
++ }
++ dslhal_support_blockWrite(&interruptMask,
++ dspOamSharedInterface.hostInterruptMask_p, sizeof(DEV_HOST_hostInterruptMask_t));
++ dprintf(5,"dslhal_support_setInterruptMask() completed.\n");
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_parseInterruptSource()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Parses the Interrupt Source Bit Field
++*
++* Return: interrupt Code if successful
++* negative error code if failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++
++unsigned int dslhal_support_parseInterruptSource(tidsl_t * ptidsl)
++{
++ DEV_HOST_dspOamSharedInterface_t *pdspOamSharedInterface, dspOamSharedInterface;
++ DEV_HOST_hostInterruptSource_t interruptSource;
++ unsigned int rc=0,intrCode=0;
++ pdspOamSharedInterface = (DEV_HOST_dspOamSharedInterface_t *) ptidsl->pmainAddr;
++ rc = dslhal_support_blockRead(pdspOamSharedInterface, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return (0-DSLHAL_ERROR_BLOCK_READ);
++ }
++ dspOamSharedInterface.hostInterruptSource_p =(DEV_HOST_hostInterruptSource_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.hostInterruptSource_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.hostInterruptSource_p,
++ &interruptSource, sizeof(DEV_HOST_hostInterruptSource_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return (0-DSLHAL_ERROR_BLOCK_READ);
++ }
++ if(interruptSource.sourceBitField1 & dslhal_support_byteSwap32(MASK_MAILBOX_INTERRUPTS))
++ {
++ dprintf(7,"Mailbox Interrupts Acknowledge \n");
++ intrCode |= 0x00000011;
++ }
++ if(interruptSource.sourceBitField1 & dslhal_support_byteSwap32(MASK_BITFIELD_INTERRUPTS))
++ {
++ dprintf(7,"Bit field Interrupt Acknowledge \n");
++ intrCode |= 0x00001002;
++ }
++ if(interruptSource.sourceBitField1 & dslhal_support_byteSwap32(MASK_HEARTBEAT_INTERRUPTS))
++ {
++ dprintf(7,"HeartBeat Interrupt Acknowledge \n");
++ intrCode |= 0x00100004;
++ }
++
++ interruptSource.sourceBitField1 &=0x0;
++ rc=dslhal_support_blockWrite(&interruptSource,
++ dspOamSharedInterface.hostInterruptSource_p, sizeof(DEV_HOST_hostInterruptSource_t));
++ if(rc)
++ return (0-DSLHAL_ERROR_BLOCK_WRITE);
++ dprintf(5,"dslhal_support_parseInterruptSource() completed.\n");
++ return intrCode;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_byteSwap16()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* input 16 bit short, byte swap from little endian to big endian or vise versa
++*
++********************************************************************************************/
++
++unsigned short dslhal_support_byteSwap16(unsigned short in16Bits)
++{
++ unsigned short out16Bits;
++
++#ifdef EB
++ unsigned char *pchar;
++ unsigned char tmp;
++#endif
++
++ out16Bits = in16Bits;
++
++#ifdef EB
++ pchar = (unsigned char *)(&out16Bits);
++
++ tmp = *pchar;
++ *pchar = *(pchar + 1);
++ *(pchar + 1) = tmp;
++#endif
++
++ return out16Bits;
++
++} /* end of dslhal_support_byteSwap16() */
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_byteSwap32()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* input 32 bit int, byte swap from little endian to big endian or vise versa
++*
++********************************************************************************************/
++
++unsigned int dslhal_support_byteSwap32(unsigned int in32Bits)
++{
++ int out32Bits;
++
++#ifdef EB
++ unsigned char tmp;
++ unsigned char *pchar;
++#endif
++
++ out32Bits = in32Bits;
++
++#ifdef EB
++ pchar = (unsigned char *)(&out32Bits);
++
++ tmp = *pchar;
++ *pchar = *(pchar + 3);
++ *(pchar + 3) = tmp;
++
++ tmp = *(pchar + 1);
++ *(pchar + 1) = *(pchar + 2);
++ *(pchar + 2) = tmp;
++#endif
++
++ return out32Bits;
++
++} /* end of dslhal_support_byteSwap32() */
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_computeCrc32()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Computes the CRC-32 for the input data
++*
++* Return: 32 bit CRC of the input data
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_computeCrc32(unsigned char *data, int len)
++{
++ unsigned int result;
++ int i,j;
++ unsigned char octet;
++
++ if ((len < 4) || (data==NULL))
++ return(0xdeaddead);
++ result = *data++ << 24;
++ result |= *data++ << 16;
++ result |= *data++ << 8;
++ result |= *data++;
++ result = ~ result;
++
++ len -=4;
++
++ for (i=0; i<len; i++)
++ {
++ octet = *(data++);
++ for (j=0; j<8; j++)
++ {
++ if (result & 0x80000000)
++ {
++ result = (result << 1) ^ CRC32_QUOTIENT ^ (octet >> 7);
++ }
++ else
++ {
++ result = (result << 1) ^ (octet >> 7);
++ }
++ octet <<= 1;
++ }
++ }
++ return ~result; /* The complement of the remainder */
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_checkOverlayPage()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Computes the CRC-32 for the input data and compares it with reference
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_checkOverlayPage(tidsl_t *ptidsl, unsigned int tag)
++{
++ unsigned int computedCrc;
++ if((unsigned char *)ptidsl->olayDpPage[tag].PmemStartWtAddr == NULL)
++ {
++ dprintf(5,"Null Address for Page: %d\n",tag);
++ return DSLHAL_ERROR_OVERLAY_MALLOC;
++ }
++ computedCrc = dslhal_support_computeCrc32((unsigned char *)ptidsl->olayDpPage[tag].PmemStartWtAddr, ptidsl->olayDpPage[tag].OverlayXferCount);
++ dprintf(6,"\n Pre-Computed CRC32 = 0x%x \t Current CRC32 = 0x%x \n",ptidsl->olayDpPage[tag].olayPageCrc32,computedCrc);
++ if(computedCrc != ptidsl->olayDpPage[tag].olayPageCrc32)
++ return DSLHAL_ERROR_OVERLAY_CORRUPTED;
++ else
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_clearTrainingInfo()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Computes the CRC-32 for the input data and compares it with reference
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++
++int dslhal_support_clearTrainingInfo(tidsl_t *ptidsl)
++{
++ int i;
++
++ for(i=0; i<NUM_PAGES; i++)
++ {
++ if(ptidsl->olayDpPage[i].PmemStartWtAddr !=NULL)
++ {
++ shim_osFreeDmaMemory((void *) ptidsl->olayDpPage[i].PmemStartWtAddr,
++ ptidsl->olayDpPage[i].OverlayXferCount);
++ ptidsl->olayDpPage[i].PmemStartWtAddr =NULL;
++ }
++ }
++ if(ptidsl->coProfiles.PmemStartWtAddr != NULL)
++ {
++ shim_osFreeDmaMemory((void *)ptidsl->coProfiles.PmemStartWtAddr, ptidsl->coProfiles.OverlayXferCount);
++ ptidsl->coProfiles.PmemStartWtAddr = NULL;
++ }
++ return 0;
++}
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_reloadTrainingInfo()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Reload overlay pages from flash or memory
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++
++int dslhal_support_reloadTrainingInfo(tidsl_t * ptidsl)
++{
++
++ int rc = 0, i;
++ unsigned int olayXfer,olayStore;
++ unsigned int *olayStart;
++
++ unsigned int crc32;
++ DEV_HOST_dspOamSharedInterface_t dspOamSharedInterface;
++ DEV_HOST_olayDpDef_t olayDpParms;
++ DEV_HOST_olayDpPageDef_t olayDpPageDef[NUM_PAGES];
++ DEV_HOST_profileBase_t profileList;
++
++ unsigned int secLength, secOffset, secPage;
++
++ /* co profile */
++ secLength = ptidsl->coProfiles.OverlayXferCount;
++ secOffset = ptidsl->coProfiles.SecOffset;
++ ptidsl->coProfiles.PmemStartWtAddr = (unsigned int) shim_osAllocateDmaMemory(secLength);
++ if(ptidsl->coProfiles.PmemStartWtAddr == NULL)
++ {
++ dprintf(1, "memory allocate error\n");
++ return DSLHAL_ERROR_OVERLAY_MALLOC;
++ }
++ /* holdSecPhyAddr = virtual2Physical((unsigned int)holdSecVirtAddr); */
++ ptidsl->coProfiles.overlayHostAddr = virtual2Physical((unsigned int)ptidsl->coProfiles.PmemStartWtAddr);
++ dprintf(4,"Allocated Addr: 0x%x \t Xlated Addr: 0x%x \n",ptidsl->coProfiles.PmemStartWtAddr, ptidsl->coProfiles.overlayHostAddr);
++ ptidsl->coProfiles.overlayHostAddr = (unsigned int)dslhal_support_byteSwap32(ptidsl->coProfiles.overlayHostAddr);
++
++ rc = shim_read_overlay_page((void *)ptidsl->coProfiles.PmemStartWtAddr, secOffset, secLength);
++ if(rc != secLength)
++ {
++ dprintf(1, "shim_read_overlay_page failed\n");
++ return DSLHAL_ERROR_OVERLAY_MALLOC;
++ }
++
++ /*shim_osMoveMemory((char *)ptidsl->coProfiles.PmemStartWtAddr, (char *)iptr, secLength);*/
++ /* RamP Image ByteSwap test */
++ olayStart = (unsigned int *)ptidsl->coProfiles.PmemStartWtAddr;
++
++ for(olayXfer=0;olayXfer< secLength/4;olayXfer++)
++ {
++ olayStore = *(unsigned int *)olayStart;
++ olayStore = (unsigned int)dslhal_support_byteSwap32(olayStore);
++ *(unsigned int*)olayStart = olayStore;
++ dprintf(5, "Addr:0x%x \t Content: 0x%x \n",olayStart,olayStore);
++ olayStart++;
++ olayStore=0;
++ }
++ shim_osWriteBackCache((void *)ptidsl->coProfiles.PmemStartWtAddr, secLength);
++
++
++ for (secPage=1;secPage<NUM_PAGES; secPage++)
++ {
++
++ dprintf(6,"OVERLAY PAGE #%d\n",secPage);
++
++ secLength = ptidsl->olayDpPage[secPage].OverlayXferCount;
++
++ dprintf(4,"Section[%d] Length: %d \n",secPage, secLength);
++
++ secOffset = ptidsl->olayDpPage[secPage].SecOffset;
++ ptidsl->olayDpPage[secPage].PmemStartWtAddr = (unsigned int) shim_osAllocateDmaMemory(secLength);
++ if(ptidsl->olayDpPage[secPage].PmemStartWtAddr == NULL)
++ {
++ dprintf(1, "overlay page allocate error\n");
++ return DSLHAL_ERROR_OVERLAY_MALLOC;
++ }
++
++ rc = shim_read_overlay_page((void *)ptidsl->olayDpPage[secPage].PmemStartWtAddr,secOffset, secLength);
++ if(rc != secLength)
++ {
++ dprintf(1, "overlay page read error\n");
++ return DSLHAL_ERROR_OVERLAY_MALLOC;
++ }
++
++ /* ptidsl->olayDpPage[secPage].overlayHostAddr = ((unsigned int)(ptidsl->olayDpPage[secPage].PmemStartWtAddr)&~0xe0000000); */
++ ptidsl->olayDpPage[secPage].overlayHostAddr = virtual2Physical((unsigned int)ptidsl->olayDpPage[secPage].PmemStartWtAddr);
++ dprintf(6,"Allocated Addr: 0x%x \t Xlated Addr: 0x%x \n",ptidsl->olayDpPage[secPage].PmemStartWtAddr,ptidsl->olayDpPage[secPage].overlayHostAddr);
++
++ ptidsl->olayDpPage[secPage].overlayHostAddr = (unsigned int)dslhal_support_byteSwap32(ptidsl->olayDpPage[secPage].overlayHostAddr);
++ /*ptidsl->olayDpPage[secPage].OverlayXferCount = secLength;
++ ptidsl->olayDpPage[secPage].BinAddr = secAddr;
++ shim_osMoveMemory((char *)ptidsl->olayDpPage[secPage].PmemStartWtAddr, (char *)iptr, secLength);
++ */
++ olayStart = (unsigned int *)ptidsl->olayDpPage[secPage].PmemStartWtAddr;
++
++ for(olayXfer=0;olayXfer< secLength/4;olayXfer++)
++ {
++ olayStore = *(unsigned int *)olayStart;
++ olayStore = (unsigned int)dslhal_support_byteSwap32(olayStore);
++ *(unsigned int*)olayStart = olayStore;
++ dprintf(5, "Addr:0x%x \t Content: 0x%x \n",olayStart,olayStore);
++ olayStart++;
++ olayStore=0;
++ }
++ /* RamP Image ByteSwap test */
++ /* compute the CRC of each overlay page and Store the Checksum in a local global variable */
++ /* This Value of CRC is to be compared with the header where all the CRC bytes are lumped together */
++ crc32 = dslhal_support_computeCrc32((char *)ptidsl->olayDpPage[secPage].PmemStartWtAddr, ptidsl->olayDpPage[secPage].OverlayXferCount);
++ if(crc32 != ptidsl->olayDpPage[secPage].olayPageCrc32)
++ return DSLHAL_ERROR_OVERLAY_MALLOC;
++
++ shim_osWriteBackCache((void *)ptidsl->olayDpPage[secPage].PmemStartWtAddr, secLength);
++ }
++
++
++ dprintf(5,"ptidsl->hostIf.mainAddr=0x%X\n", (unsigned int)ptidsl->pmainAddr);
++
++ /* get the pointer to DSP-OAM Shared Interface */
++ rc = dslhal_support_blockRead(ptidsl->pmainAddr, &dspOamSharedInterface,
++ sizeof(DEV_HOST_dspOamSharedInterface_t));
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ /* Communicate the Allocated Memory Address to DSP to choose CO Profiles */
++
++ /* Change the Endianness of the profileList pointer */
++ dspOamSharedInterface.profileList_p = (DEV_HOST_profileBase_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.profileList_p);
++ /* Access the profileList Structure */
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.profileList_p,&profileList, sizeof(DEV_HOST_profileBase_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++ dprintf(2,"Old Addr:%x New: %x \n",profileList.hostProfileBase_p,ptidsl->coProfiles.overlayHostAddr);
++ profileList.hostProfileBase_p = (DEV_HOST_coData_t *)ptidsl->coProfiles.overlayHostAddr;
++ rc = dslhal_support_blockWrite(&profileList,(PVOID)dspOamSharedInterface.profileList_p,sizeof(DEV_HOST_profileBase_t));
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_WRITE;
++
++ /* Communicate the Allocated Memory Address to DSP to do overlays */
++
++ /* Change the Endianness of the olayDpDef pointer */
++ dspOamSharedInterface.olayDpParms_p = (DEV_HOST_olayDpDef_t *)dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.olayDpParms_p);
++ /* Access the olayDpDef Structure */
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.olayDpParms_p,&olayDpParms, sizeof(DEV_HOST_olayDpDef_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++
++ for(i=1;i<NUM_PAGES;i++)
++ {
++ /* Change the endianness of the olayDpPageDef Pointer */
++ olayDpParms.olayDpPage_p[i] = (DEV_HOST_olayDpPageDef_t *) dslhal_support_byteSwap32((unsigned int)olayDpParms.olayDpPage_p[i]);
++ /* Access the olayDpPageDef Structure */
++ rc = dslhal_support_blockRead((PVOID)olayDpParms.olayDpPage_p[i],&olayDpPageDef[i],sizeof(DEV_HOST_olayDpPageDef_t));
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_READ;
++ olayDpPageDef[i].overlayHostAddr = ptidsl->olayDpPage[i].overlayHostAddr;
++ rc = dslhal_support_blockWrite(&olayDpPageDef[i],(PVOID)olayDpParms.olayDpPage_p[i],sizeof(DEV_HOST_olayDpPageDef_t));
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_WRITE;
++ }
++
++ ptidsl->bOverlayPageLoaded = 1;
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++ /* end of dslhal_support_reloadTrainingInfo() */
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_restoreTrainingInfo()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Computes the CRC-32 for the input data and compares it with reference
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++
++
++int dslhal_support_restoreTrainingInfo(tidsl_t *ptidsl)
++{
++ int rc;
++
++ rc=1;
++ while(rc != 0)
++ {
++ dslhal_support_clearTrainingInfo(ptidsl);
++ //shim_osCriticalEnter();
++ rc = dslhal_support_reloadTrainingInfo(ptidsl);
++ //shim_osCriticalExit();
++ shim_osClockWait(6400);
++ }
++ return 0;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_advancedIdleProcessing()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Calls Advanced Idle State Processing Functions
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_advancedIdleProcessing(tidsl_t *ptidsl)
++{
++ int rc=0;
++ ptidsl->AppData.bState = RSTATE_IDLE;
++#ifndef NO_ACT
++ rc += dslhal_advcfg_resetBitSwapMessageLog(ptidsl,0);
++ rc += dslhal_advcfg_resetBitSwapMessageLog(ptidsl,1);
++ rc += dslhal_advcfg_resetTrainStateHistory(ptidsl);
++ rc += dslhal_advcfg_getReasonForDrop(ptidsl);
++#endif
++ if(rc)
++ return DSLHAL_ERROR_CONFIG_API_FAILURE;
++ else
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_aocBitSwapProcessing()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Calls Advanced Idle State Processing Functions
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_aocBitSwapProcessing(tidsl_t *ptidsl,unsigned int usDs)
++{
++ int rc=0;
++#ifndef NO_ACT
++ int i;
++ int differentCmd_f;
++ unsigned int dsSwapInx;
++
++ static UINT8 lastAturBitSwapCommands[6] = {0, 0, 0, 0, 0, 0};
++ static UINT8 lastAturBitSwapBinNum[6] = {0, 0, 0, 0, 0, 0};
++
++ if (usDs == 0)
++ {
++ dprintf(4," DSP_XMITBITSWAP\n");
++ rc += dslhal_advcfg_getAocBitswapBuffer(ptidsl,0);
++ ptidsl->usBitSwapInx++;
++ if (ptidsl->usBitSwapInx > 29)
++ ptidsl->usBitSwapInx=0;
++ }
++
++ if (usDs == 1)
++ {
++ dprintf(4," DSP_RCVBITSWAP\n");
++ rc += dslhal_advcfg_getAocBitswapBuffer(ptidsl,1);
++ differentCmd_f = FALSE;
++ dsSwapInx = ptidsl->dsBitSwapInx;
++ if (! rc)
++ {
++ for (i = 0; i < 6; i++)
++ {
++ if (lastAturBitSwapCommands[i] != ptidsl->dsBitSwap[dsSwapInx].bitSwapCommand[i])
++ {
++ differentCmd_f = TRUE;
++ break;
++ }
++ }
++ if (! differentCmd_f)
++ {
++ for (i = 0; i < 6; i++)
++ {
++ if (lastAturBitSwapBinNum[i] != ptidsl->dsBitSwap[dsSwapInx].bitSwapBinNum[i])
++ {
++ differentCmd_f = TRUE;
++ break;
++ }
++ }
++ }
++ //CPE data pump seems to occasionally send us the same bit swap twice in a row with different sframe counter.
++ //Since these are never counted twice by the debug output of AC5, we should not count them twice either.
++ //So, we ignore the sframe_counter in determining whether the most recent bitswap is a duplicate.
++ if (differentCmd_f)
++ {
++ shim_osMoveMemory((void *)lastAturBitSwapCommands, (void *)ptidsl->dsBitSwap[dsSwapInx].bitSwapCommand, 6);
++ shim_osMoveMemory((void *)lastAturBitSwapBinNum, (void *)ptidsl->dsBitSwap[dsSwapInx].bitSwapBinNum, 6);
++ ptidsl->dsBitSwapInx++;
++ if (ptidsl->dsBitSwapInx > 29)
++ ptidsl->dsBitSwapInx = 0;
++ }
++ }
++ }
++#endif
++ if(rc)
++ return DSLHAL_ERROR_CONFIG_API_FAILURE;
++ else
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_gatherEocMessages()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Calls Advanced EOC Buffering functions
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_gatherEocMessages(tidsl_t *ptidsl,int usDs, int msgPart1, int msgPart2)
++{
++ int rc=0;
++#ifndef NO_ACT
++ rc = dslhal_advcfg_logEocMessages(ptidsl,usDs, msgPart1, msgPart2);
++#endif
++ if(rc)
++ return DSLHAL_ERROR_CONFIG_API_FAILURE;
++ else
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_gatherSnrPerBin()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Calls Advanced Snr per bin buffering Functions
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_gatherSnrPerBin(tidsl_t *ptidsl,unsigned int snrParam)
++{
++ int rc=0;
++#ifndef NO_ACT
++ rc = dslhal_advcfg_getSnrPerBin(ptidsl,snrParam);
++#endif
++ if(rc)
++ return DSLHAL_ERROR_CONFIG_API_FAILURE;
++ else
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_processTrainingState()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Calls Advanced Training State Processing Functions
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_processTrainingState(tidsl_t *ptidsl)
++{
++ int rc=0;
++#ifndef NO_ACT
++
++ if(ptidsl->trainStateInx<120)
++ {
++ rc = dslhal_advcfg_getTrainingState(ptidsl,(void *)&ptidsl->trainHistory[ptidsl->trainStateInx++]);
++ if(ptidsl->trainHistory[(ptidsl->trainStateInx-1)].subStateIndex ==
++ ptidsl->trainHistory[(ptidsl->trainStateInx-2)].subStateIndex)
++ ptidsl->trainStateInx--;
++ }
++ else
++ ptidsl->trainStateInx = 0;
++#endif
++ if(rc)
++ return DSLHAL_ERROR_CONFIG_API_FAILURE;
++ else
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_gatherAdsl2Messages()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Gathers ADSL2 Training Messages
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_gatherAdsl2Messages(tidsl_t *ptidsl,int tag, int param1, int param2)
++{
++ int rc=0;
++ unsigned int adsl2MsgLoc;
++ switch(tag)
++ {
++ case CMSGFMT_INDEX:
++ dprintf(5,"C-Msg-FMT rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, CMSGFMT_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2TrainingMessages.cMsgFmt,CMSGFMT_SIZE);
++ break;
++ case RMSGFMT_INDEX:
++ case RMSGFMT2_INDEX:
++ dprintf(5,"R-Msg-FMT rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, RMSGFMT_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2TrainingMessages.rMsgFmt,RMSGFMT_SIZE);
++ break;
++ case CMSGPCB_INDEX:
++ dprintf(5,"C-Msg-PCB rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, CMSGPCB_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2TrainingMessages.cMsgPcb,CMSGPCB_SIZE);
++ ptidsl->adsl2TrainingMessages.cMsgPcbLen = CMSGPCB_SIZE;
++ break;
++ case CMSGPCB2_INDEX:
++ dprintf(5,"C-Msg-PCB2 rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, CMSGPCB2_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2TrainingMessages.cMsgPcb,CMSGPCB2_SIZE);
++ ptidsl->adsl2TrainingMessages.cMsgPcbLen = CMSGPCB2_SIZE;
++#ifndef NO_ACT
++ rc += dslhal_advcfg_setBlackOutBits(ptidsl);
++#endif
++ break;
++ case CMSGPCB2L_INDEX:
++ dprintf(5,"C-Msg-PCB2L rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, CMSGPCB2L_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2TrainingMessages.cMsgPcb,CMSGPCB2L_SIZE);
++ ptidsl->adsl2TrainingMessages.cMsgPcbLen = CMSGPCB2L_SIZE;
++ break;
++ case RMSGPCB_INDEX:
++ case RMSGPCB2L_INDEX:
++ dprintf(5,"R-Msg-PCB rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, RMSGPCB_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2TrainingMessages.rMsgPcb,RMSGPCB_SIZE);
++ ptidsl->adsl2TrainingMessages.rMsgPcbLen = RMSGPCB_SIZE;
++ break;
++
++ case CMSG1ADSL2_INDEX:
++ dprintf(5,"C-Msg1 rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, CMSG1ADSL2_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2TrainingMessages.cMsg1,CMSG1ADSL2_SIZE);
++ ptidsl->adsl2TrainingMessages.cMsg1Len = CMSG1ADSL2_SIZE;
++ break;
++ case CMSG2ADSL2_INDEX:
++ dprintf(5,"C-Msg2 rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, CMSG2ADSL2_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2TrainingMessages.cMsg2,CMSG2ADSL2_SIZE);
++ ptidsl->adsl2TrainingMessages.cMsg2Len = CMSG2ADSL2_SIZE;
++ break;
++ case RMSG1ADSL2_INDEX:
++ dprintf(5,"R-Msg1 rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, RMSG1ADSL2_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2TrainingMessages.rMsg1,RMSG1ADSL2_SIZE);
++ ptidsl->adsl2TrainingMessages.rMsg1Len = RMSG1ADSL2_SIZE;
++ break;
++ case RMSG2ADSL2_INDEX:
++ dprintf(5,"R-Msg2 rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, RMSG2ADSL2_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2TrainingMessages.rMsg2,RMSG2ADSL2_SIZE);
++ ptidsl->adsl2TrainingMessages.rMsg2Len = RMSG2ADSL2_SIZE;
++ break;
++ case CPARAMS_INDEX:
++ dprintf(5,"C-Params rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, CPARAMS_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2TrainingMessages.cParams,CPARAMS_SIZE);
++ ptidsl->adsl2TrainingMessages.cParamsLen = CPARAMS_SIZE;
++ break;
++ case RPARAMS_INDEX:
++ dprintf(5,"R-Params rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, RPARAMS_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2TrainingMessages.rParams,RPARAMS_SIZE);
++ ptidsl->adsl2TrainingMessages.rParamsLen = RPARAMS_SIZE;
++ break;
++ case RMSG1LD_INDEX:
++ dprintf(5,"R-Msg1 LD rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, RMSG1LD_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2DiagnosticMessages.rMsg1Ld,RMSG1LD_SIZE);
++ ptidsl->adsl2DiagnosticMessages.rMsg1LdLen = RMSG1LD_SIZE;
++ break;
++ case RMSG2LD_INDEX:
++ dprintf(5,"R-Msg2 LD rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, RMSG2LD_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2DiagnosticMessages.rMsg2Ld,RMSGxLD_SIZE);
++ ptidsl->adsl2DiagnosticMessages.rMsgxLdLen = RMSGxLD_SIZE;
++ break;
++ case RMSG3LD_INDEX:
++ dprintf(5,"R-Msg3 LD rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, RMSG3LD_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2DiagnosticMessages.rMsg3Ld,RMSGxLD_SIZE);
++ ptidsl->adsl2DiagnosticMessages.rMsgxLdLen = RMSGxLD_SIZE;
++ break;
++ case RMSG4LD_INDEX:
++ dprintf(5,"R-Msg4 LD rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, RMSG4LD_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2DiagnosticMessages.rMsg4Ld,RMSGxLD_SIZE);
++ ptidsl->adsl2DiagnosticMessages.rMsgxLdLen = RMSGxLD_SIZE;
++ break;
++ case RMSG5LD_INDEX:
++ dprintf(5,"R-Msg5 LD rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, RMSG5LD_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2DiagnosticMessages.rMsg5Ld,RMSGxLD_SIZE);
++ ptidsl->adsl2DiagnosticMessages.rMsgxLdLen = RMSGxLD_SIZE;
++ break;
++ case RMSG6LD_INDEX:
++ dprintf(5,"R-Msg6 LD rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, RMSG6LD_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2DiagnosticMessages.rMsg6Ld,RMSGxLD_SIZE);
++ ptidsl->adsl2DiagnosticMessages.rMsgxLdLen = RMSGxLD_SIZE;
++ break;
++ case RMSG7LD_INDEX:
++ dprintf(5,"R-Msg7 LD rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, RMSG7LD_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2DiagnosticMessages.rMsg7Ld,RMSGxLD_SIZE);
++ ptidsl->adsl2DiagnosticMessages.rMsgxLdLen = RMSGxLD_SIZE;
++ break;
++ case RMSG8LD_INDEX:
++ dprintf(5,"R-Msg8 LD rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, RMSG8LD_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2DiagnosticMessages.rMsg8Ld,RMSGxLD_SIZE);
++ ptidsl->adsl2DiagnosticMessages.rMsgxLdLen = RMSGxLD_SIZE;
++ break;
++ case RMSG9LD_INDEX:
++ dprintf(5,"R-Msg9 LD rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, RMSG9LD_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2DiagnosticMessages.rMsg9Ld,RMSGxLD_SIZE);
++ ptidsl->adsl2DiagnosticMessages.rMsgxLdLen = RMSGxLD_SIZE;
++ break;
++ case CMSG1LD_INDEX:
++ dprintf(5,"C-Msg1 LD rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, CMSG1LD_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2DiagnosticMessages.cMsg1Ld,CMSG1LD_SIZE);
++ ptidsl->adsl2DiagnosticMessages.cMsg1LdLen = CMSG1LD_SIZE;
++ break;
++ case CMSG2LD_INDEX:
++ dprintf(5,"C-Msg2 LD rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, CMSG2LD_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2DiagnosticMessages.cMsg2Ld,CMSG2LD_SIZE);
++ ptidsl->adsl2DiagnosticMessages.cMsg2LdLen = CMSG2LD_SIZE;
++ break;
++ case CMSG3LD_INDEX:
++ dprintf(5,"C-Msg3 LD rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, CMSG3LD_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2DiagnosticMessages.cMsg3Ld,CMSG3LD_SIZE);
++ ptidsl->adsl2DiagnosticMessages.cMsg3LdLen = CMSG3LD_SIZE;
++ break;
++ case CMSG4LD_INDEX:
++ dprintf(5,"C-Msg4 LD rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, CMSG4LD_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2DiagnosticMessages.cMsg4Ld,CMSG4LD_SIZE);
++ ptidsl->adsl2DiagnosticMessages.cMsg4LdLen = CMSG4LD_SIZE;
++ break;
++ case CMSG5LD_INDEX:
++ dprintf(5,"C-Msg5 LD rec'd\n");
++ adsl2MsgLoc = dslhal_support_getAdsl2MessageLocation
++ (ptidsl, CMSG5LD_INDEX);
++ rc += dslhal_support_blockRead((PVOID)adsl2MsgLoc,
++ ptidsl->adsl2DiagnosticMessages.cMsg5Ld,CMSG5LD_SIZE);
++ ptidsl->adsl2DiagnosticMessages.cMsg5LdLen = CMSG5LD_SIZE;
++ break;
++ default:
++ dprintf(5,"Unknown ADSL2 Message rec'd\n");
++ break;
++ }
++ if(rc)
++ return DSLHAL_ERROR_CONFIG_API_FAILURE;
++ else
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_getAdsl2MessageLocation()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Gets the address to the ADSL2 Message being looked up
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_getAdsl2MessageLocation(tidsl_t *ptidsl,int msgOffset)
++{
++ int rc=0;
++
++ DEV_HOST_dspOamSharedInterface_t *pSharedInterface, sharedInterface;
++ DEV_HOST_dspWrNegoParaDef_t dspNegoPara;
++ int adsl2MsgString, adsl2MsgAddr;
++
++ pSharedInterface = (DEV_HOST_dspOamSharedInterface_t *) ptidsl->pmainAddr;
++ rc += dslhal_support_blockRead(pSharedInterface, &sharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ sharedInterface.dspWriteNegoParams_p = (DEV_HOST_dspWrNegoParaDef_t *) dslhal_support_adsl2ByteSwap32((unsigned int)sharedInterface.dspWriteNegoParams_p);
++ rc += dslhal_support_blockRead((PVOID)sharedInterface.dspWriteNegoParams_p,&dspNegoPara, sizeof(DEV_HOST_dspWrNegoParaDef_t));
++
++ if (rc)
++ {
++ dprintf(1,"dslhal_support_blockRead failed\n");
++ return DSLHAL_ERROR_BLOCK_READ;
++ }
++
++ adsl2MsgString = dslhal_support_adsl2ByteSwap32((unsigned int)dspNegoPara.adsl2DeltMsgs_p);
++ dprintf(5,"ADSL2 Message String Address: 0x%x\n",adsl2MsgString);
++ rc += dslhal_support_blockRead((PVOID)(adsl2MsgString +
++ ((sizeof(unsigned char *)*msgOffset))),
++ &adsl2MsgAddr, sizeof(int));
++ adsl2MsgAddr = dslhal_support_adsl2ByteSwap32((unsigned int)adsl2MsgAddr);
++ dprintf(5," Message Address: 0x%x\n",adsl2MsgAddr);
++
++ if(rc)
++ return DSLHAL_ERROR_BLOCK_READ;
++ else
++ return adsl2MsgAddr;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_getCMsgsRa()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Calls Advanced Training Message functions
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_getCMsgsRa(tidsl_t *ptidsl,void *cMsg)
++{
++ int rc=0;
++ DEV_HOST_raMsgsDef_t raMsgParms;
++ DEV_HOST_dspOamSharedInterface_t dspOamSharedInterface;
++ rc += dslhal_support_blockRead(ptidsl->pmainAddr, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++
++ dspOamSharedInterface.raMsgs_p = (DEV_HOST_raMsgsDef_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.raMsgs_p);
++
++ rc += dslhal_support_blockRead((PVOID)dspOamSharedInterface.raMsgs_p,
++ &raMsgParms, sizeof(DEV_HOST_raMsgsDef_t));
++ shim_osMoveMemory((void *)cMsg,(void *)raMsgParms.cMsgsRaString,6);
++
++ if(rc)
++ return DSLHAL_ERROR_CONFIG_API_FAILURE;
++ else
++ return DSLHAL_ERROR_NO_ERRORS;
++}
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_gatherRateMessages()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Gathers Rate Training Messages
++* Input
++* tidsl_t *ptidsl : Pointer to application structure
++*
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_gatherRateMessages(tidsl_t * ptidsl)
++{
++ int rc;
++ DEV_HOST_dspWrNegoParaDef_t negoParms;
++ DEV_HOST_dspOamSharedInterface_t dspOamSharedInterface;
++
++ dprintf(1, "dslhal_support_gatherRateMessages\n");
++
++ rc += dslhal_support_blockRead(ptidsl->pmainAddr, &dspOamSharedInterface,sizeof(DEV_HOST_dspOamSharedInterface_t));
++ dspOamSharedInterface.dspWriteNegoParams_p = (DEV_HOST_dspWrNegoParaDef_t *) dslhal_support_byteSwap32((unsigned int)dspOamSharedInterface.dspWriteNegoParams_p);
++
++ rc = dslhal_support_blockRead((PVOID)dspOamSharedInterface.dspWriteNegoParams_p, &negoParms, sizeof(DEV_HOST_dspWrNegoParaDef_t));
++ if (rc)
++ return DSLHAL_ERROR_BLOCK_READ;
++ else
++ {
++ shim_osMoveMemory((void *)ptidsl->AppData.bCRates1, (void *)negoParms.cRates1, 120);
++ shim_osMoveMemory((void *)ptidsl->AppData.bRRates1, (void *)negoParms.rRates1, 44);
++ }
++return DSLHAL_ERROR_NO_ERRORS;
++}
++
++static unsigned int dslhal_support_adsl2ByteSwap32(unsigned int in32Bits)
++{
++ int out32Bits=0;
++
++#ifdef EB
++ out32Bits = (in32Bits << 24);
++ out32Bits |=((in32Bits & 0x0000ff00) << 8);
++ out32Bits |=((in32Bits & 0xff000000) >> 24);
++ out32Bits |=((in32Bits & 0x00ff0000) >> 8);
++#else
++ out32Bits = in32Bits;
++#endif
++
++ return out32Bits;
++
++} /* end of dslhal_support_byteSwap32() */
+diff -urN linux.old/drivers/atm/sangam_atm/dsl_hal_support.h linux.dev/drivers/atm/sangam_atm/dsl_hal_support.h
+--- linux.old/drivers/atm/sangam_atm/dsl_hal_support.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/dsl_hal_support.h 2005-08-23 04:46:50.101843088 +0200
+@@ -0,0 +1,718 @@
++#ifndef DSL_HAL_SUPPORT_H__
++#define DSL_HAL_SUPPORT_H__ 1
++
++/*******************************************************************************
++* FILE PURPOSE: DSL Driver API functions for Sangam
++*
++********************************************************************************
++* FILE NAME: dsl_hal_functiondefines.c
++*
++* DESCRIPTION:
++* Contains basic DSL HAL API declarations for Sangam
++*
++*
++* (C) Copyright 2001-02, Texas Instruments, Inc.
++* History
++* Date Version Notes
++* 06Feb03 0.00.00 RamP Created
++* 21Mar03 0.00.01 RamP Removed byteswap functions
++* 21Mar03 0.00.02 RamP Added extern osFreeVMemory declaration
++* 10Apr03 0.00.03 RamP Changed declaration for loadFWImage &
++* loadDebugFWImage to remove ptidsl param
++* 12Apr03 0.00.04 RamP Added function to set Interrupt Bit
++* Masks for bitfield & Mailboxes
++* 14Apr03 0.00.05 RamP Added modem state bit field processing
++* 15Apr03 0.00.06 RamP Added function osAllocateVMemory
++* 21Apr03 0.01.00 RamP Added function osAllocateDmaMemory
++* Added function osFreeDmaMemory
++* (Alpha) Added macro virtual2Physical,
++* 22Apr03 0.01.01 RamP Moved acknowledgeInterrupt to api.h
++* 24Apr03 0.01.02 RamP Added checkOvelayPage function
++* 29May03 0.01.03 RamP Added critical enter/exit function decl
++* 06Jun03 0.01.04 RamP Added Interrupt source parsing function
++* 06Oct03 0.01.05 RamP Added function abstraction switches
++* 12Oct03 0.01.06 RamP Added ADSL2 Message function prototypes
++* 14Nov03 0.03.07 RamP Added function to gather Rate Messages
++*******************************************************************************/
++
++#include "dsl_hal_api.h"
++
++#define virtual2Physical(a) (((int)a)&~0xe0000000)
++/* External Function Prototype Declarations */
++
++extern unsigned int shim_osGetCpuFrequency(void);
++extern void shim_osClockWait(int val);
++extern unsigned int shim_osClockTick(void);
++
++extern int shim_osStringCmp(const char *s1, const char *s2);
++
++extern void dprintf( int uDbgLevel, char * szFmt, ...);
++
++extern int shim_osLoadFWImage(unsigned char *firmwareImage);
++extern int shim_osLoadDebugFWImage(unsigned char *debugFirmwareImage);
++extern unsigned int shim_read_overlay_page(void *ptr, unsigned int secOffset, unsigned int secLength);
++extern void shim_osMoveMemory(char *dst, char *src, unsigned int numBytes);
++extern void shim_osZeroMemory(char *dst, unsigned int numBytes);
++
++extern void *shim_osAllocateMemory(unsigned int size);
++extern void *shim_osAllocateVMemory(unsigned int size);
++extern void *shim_osAllocateDmaMemory(unsigned int size);
++
++extern void shim_osFreeMemory(void *ptr, unsigned int size);
++extern void shim_osFreeVMemory(void *ptr, unsigned int size);
++extern void shim_osFreeDmaMemory(void *ptr, unsigned int size);
++
++extern void shim_osWriteBackCache(void *pMem, unsigned int size);
++extern void shim_osCriticalEnter(void);
++extern void shim_osCriticalExit(void);
++
++
++/*******************************************************************************************
++* FUNCTION NAME: dslhal_support_writeHostMailbox
++*
++********************************************************************************************
++* DESCRIPTION: Send a message to a mailbox
++*
++* ARGUMENTS: int cmd command to write
++* int tag tag (currently unused)
++* int p1 parameter 1 (currently unused)
++* int p2 parameter 2 (currently unused)
++*
++* RETURNS: 0 if successful
++* NZ otherwise
++*
++*******************************************************************************************/
++
++int dslhal_support_writeHostMailbox
++(tidsl_t *ptidsl,
++ int cmd,
++ int tag,
++ int p1,
++ int p2);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_readDspMailbox
++*
++*********************************************************************************************
++* DESCRIPTION: Reads a message from the mailbox
++*
++* ARGUMENTS: int *pcmd Pointer to command read
++*
++* RETURNS: 0 if successful
++* 1 if no mail
++* NZ otherwise
++*
++*****************************************************************************************/
++
++int dslhal_support_readDspMailbox
++(tidsl_t *ptidsl,
++ int *pcmd,
++ int *ptag,
++ int *pprm1,
++ int *pprm2);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_readTextMailbox
++*
++*********************************************************************************************
++* DESCRIPTION: Reads a message from the mailbox
++*
++* ARGUMENTS: int *pcmd Pointer to command read
++*
++* RETURNS: 0 if successful
++* 1 if no mail
++* NZ otherwise
++*
++*****************************************************************************************/
++
++int dslhal_support_readTextMailbox
++(tidsl_t *ptidsl,
++ int *pmsg1,
++ int *pmsg2);
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_support_blockRead
++*
++*********************************************************************************************
++* DESCRIPTION: This rouin simulates DSP memory read as done in ax5 pci nic card
++*
++* INPUT: void *addr, memory address to be read
++* void *buffer, dat buffer to be filled with from memmory
++* size_t count, number of bytes to be written
++*
++* RETURN: 0 --succeeded
++* 1 --Failed
++*
++*****************************************************************************************/
++
++int dslhal_support_blockRead
++(void *addr,
++ void *buffer,
++ size_t count);
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_support_blockWrite
++*
++*******************************************************************************************
++* DESCRIPTION: This rouin simulates DSP memory write as done in ax5 pci nic card
++*
++* INPUT: void *buffer, data need to written
++* void *adde, memory address to be written
++* size_t count, number of bytes to be written
++*
++* RETURN: 0 --succeeded
++* 1 --Failed
++*
++*****************************************************************************************/
++
++int dslhal_support_blockWrite
++(void *buffer,
++ void *addr,
++ size_t count);
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_support_hostDspAddressTranslate
++*
++*******************************************************************************************
++* DESCRIPTION: This function moves the address window to translate physical address
++*
++* INPUT: unsigned int addr : address that requires translation
++*
++* RETURN: Translated address or error condition
++*
++*
++*****************************************************************************************/
++
++unsigned int dslhal_support_hostDspAddressTranslate
++( unsigned int addr
++);
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_support_unresetDslSubsystem
++*
++*******************************************************************************************
++* DESCRIPTION: This function unreset Dsl Subsystem
++*
++* INPUT: None
++*
++* RETURN: 0 if Pass; 1 if Fail
++*
++*****************************************************************************************/
++int dslhal_support_unresetDslSubsystem
++(void
++);
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_support_unresetDsp()
++*
++*******************************************************************************************
++* DESCRIPTION: This fuction takes ax5 daugter board out of reset.
++*
++* INPUT: None
++*
++* RETURN: 0 --successful.
++* 1 --failed
++*
++*****************************************************************************************/
++int dslhal_support_unresetDsp
++(void
++);
++
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_support_resetDslSubsystem
++*
++*******************************************************************************************
++* DESCRIPTION: This function unreset Dsl Subsystem
++*
++* INPUT: None
++*
++* RETURN: 0 if Pass; 1 if Fail
++*
++*****************************************************************************************/
++int dslhal_support_resetDslSubsystem
++(void
++);
++
++/******************************************************************************************
++* FUNCTION NAME: dslhal_support_resetDsp()
++*
++*******************************************************************************************
++* DESCRIPTION: This fuction takes ax5 daugter board out of reset.
++*
++* INPUT: None
++*
++* RETURN: 0 --successful.
++* 1 --failed
++*
++*****************************************************************************************/
++int dslhal_support_resetDsp
++(void
++);
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_hostDspCodeDownload()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* download DSP image from host memory to dsp memory
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++
++int dslhal_support_hostDspCodeDownload
++(tidsl_t * ptidsl
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_diags_digi_assignMemTestSpace()
++*
++*********************************************************************************************
++* DESCRIPTION: Assigns Memory Space in SDRAM for External Memory Test
++* Input: tidsl_t *ptidsl
++*
++* Return: 0 success
++* 1 failed
++*
++********************************************************************************************/
++
++unsigned int dslhal_diags_digi_assignMemTestSpace
++(tidsl_t *ptidsl
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_diags_digi_readMemTestResult()
++*
++*********************************************************************************************
++* DESCRIPTION: Reads Results of External Memory Test
++* Input: tidsl_t *ptidsl
++*
++* Return: 0 success
++* 1 failed
++*
++********************************************************************************************/
++
++unsigned int dslhal_diags_digi_readMemTestResult
++(tidsl_t *ptidsl,
++unsigned int testResult
++);
++
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_diags_codeDownload()
++*
++*********************************************************************************************
++* DESCRIPTION: Brings DSLSS out of Reset, Downloads Diag Firmware,
++* brings DSP out of Reset
++* Input: tidsl_t *ptidsl
++*
++* Return: 0 success
++* 1 failed
++*
++********************************************************************************************/
++
++unsigned int dslhal_diags_codeDownload
++(tidsl_t *ptidsl,
++unsigned char* missingTones
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_diags_anlg_setPgaParams()
++*
++*********************************************************************************************
++* DESCRIPTION: This function instructs the Transciever to transmit the Reverb with missing
++* tones and Medley's with missing tones. These signals are defined in ITU
++* G.992.1 ADSL Standards.
++*
++* Input: Test selects between the Reverb or Medley tests. 0 - Reverb, 1 - Medley
++* Tones selects the .
++* Return: NULL
++*
++********************************************************************************************/
++
++unsigned int dslhal_diags_anlg_setPgaParams
++(tidsl_t *ptidsl,
++int agcFlag,
++short pga1,
++short pga2,
++short pga3,
++short aeq
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_diags_anlg_getRxNoisePower()
++*
++*********************************************************************************************
++* DESCRIPTION: This function instructs the Transciever to transmit the Reverb with missing
++* tones and Medley's with missing tones. These signals are defined in ITU
++* G.992.1 ADSL Standards.
++*
++* Input: Test selects between the Reverb or Medley tests. 0 - Reverb, 1 - Medley
++* Tones selects the .
++* Return: NULL
++*
++********************************************************************************************/
++
++unsigned int dslhal_diags_anlg_getRxNoisePower
++(tidsl_t *ptidsl
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_diags_anlg_setMissingTones()
++*
++*********************************************************************************************
++* DESCRIPTION: This function instructs the Transciever to transmit the Reverb with missing
++* tones and Medley's with missing tones. These signals are defined in ITU
++* G.992.1 ADSL Standards.
++*
++* Input: Test selects between the Reverb or Medley tests. 0 - Reverb, 1 - Medley
++* Tones selects the .
++* Return: NULL
++*
++********************************************************************************************/
++
++unsigned int dslhal_diags_anlg_setMissingTones
++(tidsl_t *ptidsl,
++unsigned char* missingTones
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_readDelineationState()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* download DSP image from host memory to dsp memory
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_readDelineationState
++(tidsl_t *ptidsl
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_processModemStateBitField()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* download DSP image from host memory to dsp memory
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_processModemStateBitField
++(tidsl_t *ptidsl
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_setInterruptMask()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++
++unsigned int dslhal_support_setInterruptMask
++(tidsl_t * ptidsl,
++unsigned int inputMask
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_computeCrc32()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Computes the CRC-32 for the input data
++*
++* Return: 32 bit CRC of the input data
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_computeCrc32
++(unsigned char *data,
++int len
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_checkOverlayPage()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Computes the CRC-32 for the input data and compares it with reference
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_checkOverlayPage
++(tidsl_t *ptidsl,
++unsigned int tag
++);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_restoreTrainingInfo()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Computes the CRC-32 for the input data and compares it with reference
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++
++int dslhal_support_restoreTrainingInfo(tidsl_t * ptidsl);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_reloadTrainingInfo()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Computes the CRC-32 for the input data and compares it with reference
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++
++int dslhal_support_reloadTrainingInfo(tidsl_t * ptidsl);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_clearTrainingInfo()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Computes the CRC-32 for the input data and compares it with reference
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++
++int dslhal_support_clearTrainingInfo(tidsl_t * ptidsl);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_parseInterruptSource()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Sets the host interrupt bit masks
++*
++* Return: 0 success
++* 1 failed
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++
++unsigned int dslhal_support_parseInterruptSource(tidsl_t * ptidsl);
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_advancedIdleProcessing()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Calls Advanced Idle State Processing Functions
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_advancedIdleProcessing(tidsl_t *ptidsl);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_aocBitSwapProcessing()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Calls Advanced Bitswap buffer Processing Functions
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_aocBitSwapProcessing(tidsl_t *ptidsl,unsigned int usDs);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_gatherEocMessages()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Calls Advanced EOC Buffering functions
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_gatherEocMessages(tidsl_t *ptidsl,int usDs, int msgPart1, int msgPart2);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_gatherSnrPerBin()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Calls Advanced Snr per bin buffering Functions
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_gatherSnrPerBin(tidsl_t *ptidsl,unsigned int snrParm);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_processTrainingState()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Calls Advanced Training State Processing Functions
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_processTrainingState(tidsl_t *ptidsl);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_gatherAdsl2Messages()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Calls Advanced EOC Buffering functions
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_gatherAdsl2Messages(tidsl_t *ptidsl,int msgTag, int param1, int param2);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_getAdsl2MsgLocation()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Gets the address to the ADSL2 Message being looked up
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_getAdsl2MessageLocation(tidsl_t *ptidsl,int msgOffset);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_getCMsgsRa()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Calls Advanced Training Message functions
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_getCMsgsRa(tidsl_t *ptidsl,void *cMsg);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_gatherRateMessages()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* Gathers Advanced Training Messages
++*
++* Return: Error Condition (if any)
++*
++*
++* NOTE:
++* DSP image is based on LITTLE endian
++*
++********************************************************************************************/
++unsigned int dslhal_support_gatherRateMessages(tidsl_t *ptidsl);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_byteSwap16()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* byteswap a short
++*
++* INPUT:
++* Return: NULL
++*
++********************************************************************************************/
++
++unsigned short dslhal_support_byteSwap16(unsigned short in16Bits);
++
++/********************************************************************************************
++* FUNCTION NAME: dslhal_support_byteSwap32()
++*
++*********************************************************************************************
++* DESCRIPTION:
++* byteswap a word
++*
++* INPUT:
++* Return: NULL
++*
++********************************************************************************************/
++
++unsigned int dslhal_support_byteSwap32(unsigned int in32Bits);
++
++#endif /* Pairs #ifndef DSL_HAL_FUNCTIONDEFINES_H__ */
+diff -urN linux.old/drivers/atm/sangam_atm/dsl_hal_version.h linux.dev/drivers/atm/sangam_atm/dsl_hal_version.h
+--- linux.old/drivers/atm/sangam_atm/dsl_hal_version.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/dsl_hal_version.h 2005-08-23 04:46:50.102842936 +0200
+@@ -0,0 +1,94 @@
++#ifndef __SYSSW_VERSION_H__
++#define __SYSSW_VERSION_H__ 1
++
++/*******************************************************************************
++* FILE PURPOSE: DSL Driver API functions for Sangam
++*
++********************************************************************************
++* FILE NAME: dsl_hal_basicapi.c
++*
++* DESCRIPTION:
++* Contains basic DSL HAL APIs for Sangam
++*
++* (C) Copyright 2003-04, Texas Instruments, Inc.
++* History
++* Date Version Notes
++* 14May03 0.00.00 RamP Original Version Created
++* 14May03 0.00.01 RamP Initial Rev numbers inserted
++* 14May03 0.00.02 RamP Bumped version numbers for Dsl Hal
++* & dhalapp for alpha plus
++* 19May03 0.00.03 MCB Bumped dslhal version number
++* because of dependant changes
++* wrt. linux-nsp atm drivers.
++* 22May03 0.00.04 RamP Bumped dslhal & dhalapp buildnum
++* for inner/outer pair & DGASP code
++* 06Jun03 0.00.05 RamP Bumped up buildnum for LED, STM,
++* interrupt processing, statistics
++* and other pre-beta features
++* 09Jun03 0.00.06 JEB Fixed error in DHALAPP bugfix/buildnum
++* 09Jun03 0.00.07 RamP Bumped up buildnum for incremental
++* changes to apis, statistics, memory
++* fixes, parameter configurations
++* 11Jun03 0.00.08 RamP Bumped up buildnum for Co profile
++* free memory fix
++* 12Jun03 0.00.09 JEB Bumped version numbers for AR7 1.00 Beta
++* 02Jul03 0.00.10 ZT Bumped HAL version for overlay page
++* 18Jul03 0.00.11 RamP Bumped HAL version for analog diags
++* 22Jul03 0.00.12 JEB Bumped DHALAPP buildnum for analog diags
++* 31Jul03 0.00.13 RamP Bumped HAL version for engr. drop
++* 04Aug03 0.00.14 JEB Bumped HAL version buildnum for CHECKPOINT65 changes
++* Bumped LINUX version buildnum for CHECKPOINT65 changes
++* 06Aug03 0.00.15 MCB Bumped all version numbers in prep for AR7 1.0 R2 release for POTS.
++* 13Aug03 0.00.16 MCB Set rev id's for D3/R1.1 (ADSL2).
++* 21Aug03 0.00.17 JEB Bumped up build numbers for merge of code additions from D1
++* 26Sep03 0.00.18 JEB Set rev id's for another D3/R1 (ADSL2).
++* 14Oct03 0.00.19 JEB Bumped Linux minor number and reset bugfix number for release.
++* Bumped build numbers on DSLHAL and DHALAPP for this checkpoint.
++* 14Oct03 0.00.20 JEB Bumped build numbers on DSLHAL and DHALAPP for CHECKPOINT15.
++* 21Oct03 0.00.21 JEB Bumped build number on DSLHAL for CHECKPOINT16.
++* 22Oct03 0.00.22 MCB Bumped all version numbers in support of D3R1 release.
++* 27Oct03 0.00.23 JEB Bumped build numbers on DSLHAL and DHALAPP for CHECKPOINT19.
++* Updated version for DSLAGENT to be 02.01.00.01 for ACT 2.1 R0.
++* 30Oct03 0.00.24 JEB Bumped bugfix number on LINUXATM Version for next release.
++* Bumped build numbers on DSLHAL and DHALAPP
++* 31Oct03 0.00.25 MCB Bumped all version numbers in support of D3R2 release.
++* 14Nov03 0.00.26 JEB Bumped build numbers on DSLHAL and DHALAPP
++* Changed version for DSLAGENT to be 02.00.01.01 for an ACT 2.0 R0
++* 20Nov03 0.00.27 JEB Bumped build number on DSLHAL.
++* Changed version for DSLAGENT to be 02.00.02.00 for the next ACT 2.0 R2
++* 21Nov03 0.00.28 MCB Bumped all version numbers in support of D3R2 release.
++* 21Nov03 0.00.29 JEB Bumped build numbers on DSLHAL and DHALAPP for D3-R0 drop on 11/21.
++* 16Dec03 0.00.30 JEB Bumped build numbers on DSLHAL and DHALAPP for CHECKPOINT31.
++* 21Dec03 0.00.31 MCB Bumped all version numbers in support of D3R2 release.
++* 05Jan04 0.00.32 JEB Bumped build numbers on DSLHAL and Linux ATM for CHECKPOINT 34.
++* 15Jan04 0.00.33 JEB Bumped build numbers on DSLHAL and Linux ATM for CHECKPOINT 36.
++* 26Jan04 0.00.34 JEB Changed Linux ATM version number to be 04.02.03.00.
++* 27Jan04 0.00.35 MCB Bumped all version numbers in support of D3R2 release.
++*******************************************************************************/
++
++/* Dsl Hal API Version Numbers */
++#define DSLHAL_VERSION_MAJOR 03
++#define DSLHAL_VERSION_MINOR 00
++#define DSLHAL_VERSION_BUGFIX 06
++#define DSLHAL_VERSION_BUILDNUM 00
++#define DSLHAL_VERSION_TIMESTAMP 00
++
++/* dhalapp Adam2 Application Version Numbers */
++#define DHALAPP_VERSION_MAJOR 03
++#define DHALAPP_VERSION_MINOR 00
++#define DHALAPP_VERSION_BUGFIX 05
++#define DHALAPP_VERSION_BUILDNUM 00
++
++/* Linux ATM Driver Version Numbers */
++#define LINUXATM_VERSION_MAJOR 04
++#define LINUXATM_VERSION_MINOR 02
++#define LINUXATM_VERSION_BUGFIX 04
++#define LINUXATM_VERSION_BUILDNUM 00
++
++/* DSL Agent Version Numbers */
++#define DSLAGENT_VERSION_MAJOR 02
++#define DSLAGENT_VERSION_MINOR 00
++#define DSLAGENT_VERSION_BUGFIX 02
++#define DSLAGENT_VERSION_BUILDNUM 00
++
++#endif /* pairs with #ifndef __SYSSW_VERSION_H__ */
+diff -urN linux.old/drivers/atm/sangam_atm/ec_errors_cpaal5.h linux.dev/drivers/atm/sangam_atm/ec_errors_cpaal5.h
+--- linux.old/drivers/atm/sangam_atm/ec_errors_cpaal5.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/ec_errors_cpaal5.h 2005-08-23 04:46:50.102842936 +0200
+@@ -0,0 +1,118 @@
++/***************************************************************************
++ Copyright(c) 2001, Texas Instruments Incorporated. All Rights Reserved.
++
++ FILE: ec_errors.h
++
++ DESCRIPTION:
++ This file contains definitions and function declarations for
++ error code support.
++
++ HISTORY:
++ 14Dec00 MJH Added masking to EC_CLASS etc macros
++ 17Sep02 GSG Added HAL support (new class&devices)
++ 03Oct02 GSG Removed C++ style comments
++***************************************************************************/
++#ifndef _INC_EC_ERRORS
++#define _INC_EC_ERRORS
++
++/*
++ 31 - CRITICAL
++ 30-28 - CLASS (ie. DIAG, KERNEL, FLASH, etc)
++ 27-24 - INSTANCE (ie. 1, 2, 3, etc )
++ 23-16 - DEVICE (ie. EMAC, IIC, etc)
++ 15-08 - FUNCTION (ie. RX, TX, INIT, etc)
++ 07-00 - ERROR CODE (ie. NO_BASE, FILE_NOT_FOUND, etc )
++*/
++
++/*---------------------------------------------------------------------------
++ Useful defines for accessing fields within error code
++---------------------------------------------------------------------------*/
++#define CRITICAL_SHIFT 31
++#define CLASS_SHIFT 28
++#define INST_SHIFT 24
++#define DEVICE_SHIFT 16
++#define FUNCTION_SHIFT 8
++#define ERROR_CODE_SHIFT 0
++
++#define CRITICAL_MASK 1
++#define CLASS_MASK 0x07
++#define DEVICE_MASK 0xFF
++#define INST_MASK 0x0F
++#define FUNCTION_MASK 0xFF
++#define ERROR_CODE_MASK 0xFF
++
++#define EC_CLASS(val) ((val&CLASS_MASK) << CLASS_SHIFT)
++#define EC_DEVICE(val) ((val&DEVICE_MASK) << DEVICE_SHIFT)
++#define EC_INST(val) ((val&INST_MASK) << INST_SHIFT)
++#define EC_FUNC(val) ((val&FUNCTION_MASK) << FUNCTION_SHIFT)
++#define EC_ERR(val) ((val&ERROR_CODE_MASK) << ERROR_CODE_SHIFT)
++
++/*---------------------------------------------------------------------------
++ Operation classes
++---------------------------------------------------------------------------*/
++#define EC_HAL EC_CLASS(0)
++#define EC_DIAG EC_CLASS(8)
++
++/*---------------------------------------------------------------------------
++ Device types
++---------------------------------------------------------------------------*/
++#define EC_DEV_EMAC EC_DEVICE(1)
++#define EC_DEV_IIC EC_DEVICE(2)
++#define EC_DEV_RESET EC_DEVICE(3)
++#define EC_DEV_ATMSAR EC_DEVICE(4)
++#define EC_DEV_MEM EC_DEVICE(5)
++#define EC_DEV_DES EC_DEVICE(6)
++#define EC_DEV_DMA EC_DEVICE(7)
++#define EC_DEV_DSP EC_DEVICE(8)
++#define EC_DEV_TMR EC_DEVICE(9)
++#define EC_DEV_WDT EC_DEVICE(10)
++#define EC_DEV_DCL EC_DEVICE(11)
++#define EC_DEV_BBIF EC_DEVICE(12)
++#define EC_DEV_PCI EC_DEVICE(13)
++#define EC_DEV_XBUS EC_DEVICE(14)
++#define EC_DEV_DSLIF EC_DEVICE(15)
++#define EC_DEV_USB EC_DEVICE(16)
++#define EC_DEV_CLKC EC_DEVICE(17)
++#define EC_DEV_RAPTOR EC_DEVICE(18)
++#define EC_DEV_DSPC EC_DEVICE(19)
++#define EC_DEV_INTC EC_DEVICE(20)
++#define EC_DEV_GPIO EC_DEVICE(21)
++#define EC_DEV_BIST EC_DEVICE(22)
++#define EC_DEV_HDLC EC_DEVICE(23)
++#define EC_DEV_UART EC_DEVICE(24)
++#define EC_DEV_VOIC EC_DEVICE(25)
++/* 9.17.02 (new HAL modules) */
++#define EC_DEV_CPSAR EC_DEVICE(0x1A)
++#define EC_DEV_AAL5 EC_DEVICE(0x1B)
++#define EC_DEV_AAL2 EC_DEVICE(0x1C)
++#define EC_DEV_CPMAC EC_DEVICE(0x1D)
++#define EC_DEV_VDMA EC_DEVICE(0x1E)
++#define EC_DEV_VLYNQ EC_DEVICE(0x1F)
++#define EC_DEV_CPPI EC_DEVICE(0x20)
++#define EC_DEV_CPMDIO EC_DEVICE(0x21)
++
++/*---------------------------------------------------------------------------
++ Function types
++---------------------------------------------------------------------------*/
++#define EC_FUNC_READ_CONF EC_FUNC(1)
++#define EC_FUNC_INIT EC_FUNC(2)
++
++/*---------------------------------------------------------------------------
++ Error codes
++---------------------------------------------------------------------------*/
++#define EC_CRITICAL (1<<CRITICAL_SHIFT)
++#define EC_NO_ERRORS 0
++#define EC_VAL_NO_BASE EC_ERR(1)
++#define EC_VAL_NO_RESET_BIT EC_ERR(2)
++#define EC_VAL_NO_RESET EC_ERR(3)
++#define EC_VAL_BAD_BASE EC_ERR(4)
++#define EC_VAL_MALLOCFAILED EC_ERR(5)
++#define EC_VAL_NO_RESETBASE EC_ERR(6)
++#define EC_DEVICE_NOT_FOUND EC_ERR(7)
++
++/*---------------------------------------------------------------------------
++ Function declarations
++---------------------------------------------------------------------------*/
++extern void ec_log_error( unsigned int );
++
++#endif /* _INC_EC_ERRORS */
+diff -urN linux.old/drivers/atm/sangam_atm/ec_errors_cpsar.h linux.dev/drivers/atm/sangam_atm/ec_errors_cpsar.h
+--- linux.old/drivers/atm/sangam_atm/ec_errors_cpsar.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/ec_errors_cpsar.h 2005-08-23 04:46:50.102842936 +0200
+@@ -0,0 +1,118 @@
++/***************************************************************************
++ Copyright(c) 2001, Texas Instruments Incorporated. All Rights Reserved.
++
++ FILE: ec_errors.h
++
++ DESCRIPTION:
++ This file contains definitions and function declarations for
++ error code support.
++
++ HISTORY:
++ 14Dec00 MJH Added masking to EC_CLASS etc macros
++ 17Sep02 GSG Added HAL support (new class&devices)
++ 03Oct02 GSG Removed C++ style comments
++***************************************************************************/
++#ifndef _INC_EC_ERRORS
++#define _INC_EC_ERRORS
++
++/*
++ 31 - CRITICAL
++ 30-28 - CLASS (ie. DIAG, KERNEL, FLASH, etc)
++ 27-24 - INSTANCE (ie. 1, 2, 3, etc )
++ 23-16 - DEVICE (ie. EMAC, IIC, etc)
++ 15-08 - FUNCTION (ie. RX, TX, INIT, etc)
++ 07-00 - ERROR CODE (ie. NO_BASE, FILE_NOT_FOUND, etc )
++*/
++
++/*---------------------------------------------------------------------------
++ Useful defines for accessing fields within error code
++---------------------------------------------------------------------------*/
++#define CRITICAL_SHIFT 31
++#define CLASS_SHIFT 28
++#define INST_SHIFT 24
++#define DEVICE_SHIFT 16
++#define FUNCTION_SHIFT 8
++#define ERROR_CODE_SHIFT 0
++
++#define CRITICAL_MASK 1
++#define CLASS_MASK 0x07
++#define DEVICE_MASK 0xFF
++#define INST_MASK 0x0F
++#define FUNCTION_MASK 0xFF
++#define ERROR_CODE_MASK 0xFF
++
++#define EC_CLASS(val) ((val&CLASS_MASK) << CLASS_SHIFT)
++#define EC_DEVICE(val) ((val&DEVICE_MASK) << DEVICE_SHIFT)
++#define EC_INST(val) ((val&INST_MASK) << INST_SHIFT)
++#define EC_FUNC(val) ((val&FUNCTION_MASK) << FUNCTION_SHIFT)
++#define EC_ERR(val) ((val&ERROR_CODE_MASK) << ERROR_CODE_SHIFT)
++
++/*---------------------------------------------------------------------------
++ Operation classes
++---------------------------------------------------------------------------*/
++#define EC_HAL EC_CLASS(0)
++#define EC_DIAG EC_CLASS(8)
++
++/*---------------------------------------------------------------------------
++ Device types
++---------------------------------------------------------------------------*/
++#define EC_DEV_EMAC EC_DEVICE(1)
++#define EC_DEV_IIC EC_DEVICE(2)
++#define EC_DEV_RESET EC_DEVICE(3)
++#define EC_DEV_ATMSAR EC_DEVICE(4)
++#define EC_DEV_MEM EC_DEVICE(5)
++#define EC_DEV_DES EC_DEVICE(6)
++#define EC_DEV_DMA EC_DEVICE(7)
++#define EC_DEV_DSP EC_DEVICE(8)
++#define EC_DEV_TMR EC_DEVICE(9)
++#define EC_DEV_WDT EC_DEVICE(10)
++#define EC_DEV_DCL EC_DEVICE(11)
++#define EC_DEV_BBIF EC_DEVICE(12)
++#define EC_DEV_PCI EC_DEVICE(13)
++#define EC_DEV_XBUS EC_DEVICE(14)
++#define EC_DEV_DSLIF EC_DEVICE(15)
++#define EC_DEV_USB EC_DEVICE(16)
++#define EC_DEV_CLKC EC_DEVICE(17)
++#define EC_DEV_RAPTOR EC_DEVICE(18)
++#define EC_DEV_DSPC EC_DEVICE(19)
++#define EC_DEV_INTC EC_DEVICE(20)
++#define EC_DEV_GPIO EC_DEVICE(21)
++#define EC_DEV_BIST EC_DEVICE(22)
++#define EC_DEV_HDLC EC_DEVICE(23)
++#define EC_DEV_UART EC_DEVICE(24)
++#define EC_DEV_VOIC EC_DEVICE(25)
++/* 9.17.02 (new HAL modules) */
++#define EC_DEV_CPSAR EC_DEVICE(0x1A)
++#define EC_DEV_AAL5 EC_DEVICE(0x1B)
++#define EC_DEV_AAL2 EC_DEVICE(0x1C)
++#define EC_DEV_CPMAC EC_DEVICE(0x1D)
++#define EC_DEV_VDMA EC_DEVICE(0x1E)
++#define EC_DEV_VLYNQ EC_DEVICE(0x1F)
++#define EC_DEV_CPPI EC_DEVICE(0x20)
++#define EC_DEV_CPMDIO EC_DEVICE(0x21)
++
++/*---------------------------------------------------------------------------
++ Function types
++---------------------------------------------------------------------------*/
++#define EC_FUNC_READ_CONF EC_FUNC(1)
++#define EC_FUNC_INIT EC_FUNC(2)
++
++/*---------------------------------------------------------------------------
++ Error codes
++---------------------------------------------------------------------------*/
++#define EC_CRITICAL (1<<CRITICAL_SHIFT)
++#define EC_NO_ERRORS 0
++#define EC_VAL_NO_BASE EC_ERR(1)
++#define EC_VAL_NO_RESET_BIT EC_ERR(2)
++#define EC_VAL_NO_RESET EC_ERR(3)
++#define EC_VAL_BAD_BASE EC_ERR(4)
++#define EC_VAL_MALLOCFAILED EC_ERR(5)
++#define EC_VAL_NO_RESETBASE EC_ERR(6)
++#define EC_DEVICE_NOT_FOUND EC_ERR(7)
++
++/*---------------------------------------------------------------------------
++ Function declarations
++---------------------------------------------------------------------------*/
++extern void ec_log_error( unsigned int );
++
++#endif /* _INC_EC_ERRORS */
+diff -urN linux.old/drivers/atm/sangam_atm/env_def_defines.h linux.dev/drivers/atm/sangam_atm/env_def_defines.h
+--- linux.old/drivers/atm/sangam_atm/env_def_defines.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/env_def_defines.h 2005-08-23 04:46:50.103842784 +0200
+@@ -0,0 +1,926 @@
++#ifndef __ENV_DEF_DEFINES_H__
++#define __ENV_DEF_DEFINES_H__ 1
++
++//********************************************************************
++//* DMT-BASE ADSL MODEM PROGRAM
++//* TEXAS INSTRUMENTS PROPRIETARTY INFORMATION
++//* AMATI CONFIDENTIAL PROPRIETARY
++//*
++//* (c) Copyright May 1999, Texas Instruments Incorporated.
++//* All Rights Reserved.
++//*
++//* Property of Texas Instruments Incorporated and Amati Communications Corp.
++//*
++//* Restricted Rights - Use, duplication, or disclosure is subject to
++//* restrictions set forth in TI's and Amati program license agreement and
++//* associated documentation
++//*
++//*********************************************************************
++//*
++//* FILENAME: dpsys_defines.h
++//*
++//* ABSTRACT: This file provides a mechanism for defining standard
++//* preprocessor flag sets for datapump.
++//*
++//* TARGET: Non specific.
++//*
++//* TOOLSET: Non specific.
++//*
++//* ACTIVATION:
++//*
++//* HISTORY: DATE AUTHOR DESCRIPTION
++//* 05/11/99 FLW Created
++//* 01/21/00 FLW derfmake changes
++//* 02/07/00 FLW/M.Seidl added _debug targets
++//* 02/23/00 FLW/M.Barnett merged in from G.lite branch
++//* 03/03/00 FLW/M.Barnett added TRELLIS token
++//* 05/11/00 Barnett Added ap036btp & ap037btp support.
++//* 02/07/00 M.Seidl added HW_TEQ, HW_DEC and DC_BIAS tokens
++//* 02/28/00 Derf/Seidl Mod's in support of suppressing compiler warnings for empty source files
++//* 02/28/00 M. Seidl added SWTC token
++//* 02/28/00 M. Seidl added ap0501tp and its _debug target
++//* 03/03/00 M. Seidl added MODPILOT token, ap0307tp_debug has SWDI and FDD enabled
++//* 03/08/00 Jack Huang Added HWRSDEC token
++//* 03/29/00 Derf/Seidl Mod's in support Soft-TC and derfmake
++//* 04/10/00 Jack Huang Added PCIMASTER token
++//* 04/11/00 Jack Huang Added STBFIX token
++//* 04/24/00 M. Seidl ap0500tp has OLAYDP turned on, ap0500tp_debug has OLAYDP turned off now
++//* 04/28/00 M.Seidl added KAPIL token for ap0501tp targets
++//* 06/02/00 P.Sexton Added OAM_EOC token
++//* 06/06/00 M. Seidl added au0501tp target
++//* 06/12/00 Michael Seidl activated h/w TEQ for KAPIL targets, disabled STBFIX for all targets
++//* 06/14/00 Derf added ap0308tp, alphabetized token lists
++//* 06/16/00 Jack Huang added au0501tp_debug target
++//* 06/22/00 M. Seidl Enabled code overlays through EMIF from external memory. Now there are 3
++//* different code overlay schemes that are differentiated by the following tokens:
++//* OLAYDP_PCI: uses PCI DMA in PCI Master Mode
++//* OLAYDP_HOST: Host downloads overlay code into DMEM upon request from DSP
++//* OLAYDP_EMIF: Host downloads overlay code into ext. mem at boot-time. DSP uses
++//* DMA channel 0 to load code into on-chip PMEM
++//* OLAYDP: turns overlays generally on or off
++//* 07/15/00 B.Srinivasan Cleaned up default tokens and tokens for au0501tp, au0501tp_debug,
++//* ap0501tp and ap0501tp_debug targets as well
++//* 07/19/00 B.Srinivasan Made changes w.r.t cleaning/fixing Rufus Interrupt related code
++//* (changed token TC_INTRPT_RUFUS to INTRPT_RUFUS
++//* 06/14/00 Derf added au0501cp
++//* 08/12/00 Yinong Ding Added DPLL_MODE token.
++//* 08/16/00 F. Mujica Moved DOUBLE_XMT_RATE, RX_HPF, and LEAKY_LMS tokens here.
++//* 09/05/00 M. Seidl Changed ap0501tp back to do overlay through PCI (OLAY_PCI = 1)
++//* 09/11/00 M. Seidl moved USB and OLAYDP_HOST definitions to be CHIPSET specific, not target specific
++//* 09/21/00 U.Dasgupta/ Added a token for separate transmit and receive buffers.
++//* F.Mujica (SEPARATE_TX_RX_BUFFERS).
++//* 10/02/00 U.Dasgupta/ Added DPLL and SEPARATE_TX_RX_BUFFER tokens for au0502 target.
++//* F.Mujica
++//* 10/02/00 M. Castellano Added new tokens for new Host/EMIF DSP code overlay.
++//* OLAYDP_2STEP: Host downloads overlay code into ext. mem upon DSP request. DSP
++//* DMA channel 0 to load code into on-chip PMEM. It is a somewhat hybrid version
++//* of OLAYDP_HOST and OLAYDP_EMIF. The test target is ap0502tp.
++//* 10/25/00 Balaji Added tokens for arv500tp target
++//* 10/31/00 U. Iyer Added TEQ_AVG token and set it one for Ax5
++//* 11/02/00 Barnett Added OAM_EOC=0 in defaults at bottom of file.
++//* 11/21/00 M. Seidl turned OLAYDP and AOC off for ap0307tp to make binary compatible w. whql'ed driver
++//* 11/28/00 Paul Hunt added FASTRETRAIN token for fast retrain specific code
++//* 11/28/00 Paul Hunt added PILOTDATA token to control channel estimation and transmission
++//* of data on the upstream pilot tone for ITU standard code loads
++//* 12/20/00 Jack Huang added EIGHTBITSRAM toekn for the targets that use 8-bit SRAM for
++//* interleaver/deinterleaver
++//* 01/11/01 U.Dasgupta Added mp targets and cleaned up GHS/PILOTDATA variables
++//* 01/23/01 U.Dasgupta Cleaned up code within GLITE tokens
++//* 01/23/00 Barnett Added in full EOC support for AP3/Ax5. Got rid of UTC. No longer needed.
++//* 02/08/01 Barnett Added DDC token.
++//* 03/09/01 Nirmal Warke Added in TOKEN definition for line diagnostics (LINE_DIAG): IMP DEPENDENCIES -
++//* TEQ_AVG must be off when LINE_DIAG is on (since they share a union buffer at the same time)
++//* 03/13/01 M. Seidl Recovered ap0500tp target. Added GHS token as PMEM saving option
++//* 03/14/01 Barnett Added ap0500mb target support. Look-and-feel is similar to ap0500tp.
++//* Added seperate-but-equal def's wrt. ISDN Annex B, Annex C, and PROP.
++//* 03/14/01 J. Bergsagel Added EXTERNBERT token.
++//* 03/15/01 Barnett/Balaji Merged AR5(H) -> 03.00.00 datapump.
++//* 03/16/01 Nirmal Warke Added in TOKEN definition for crosstalk performance mods (CROSSTALK): IMP DEPENDENCIES -
++//* TEQ_AVG must be off and LEAKY_LMS must be on when CROSSTALK is on
++//* 03/21/01 Barnett Added support for ar0500lp, ar0500mp, ar0500dp, arv500lp, arv500mp, and arv500dp.
++//* 03/26/01 M. Seidl enabled 64pt IFFT for ap0500mb (Raptor+AD11, FDM)
++//* 03/28/01 J. Bergsagel Removed EXTERNBERT token (now use host intf. var. instead)
++//* 04/03/01 J. Bergsagel Removed condition of DSPDP_CHIPSET_GEN==5 for default defines
++//* Removed LEAKY_LMS token (assumed always 1)
++//* Removed OLAYDP_HOST token (assumed always 0)
++//* Removed RX_HPF token (assumed always 1)
++//* Removed TRIBRID token (not used any more)
++//* Removed FDD token (assumed always 1)
++//* Removed HW_DEC token (assumed always 1)
++//* Removed HW_TEQ token (assumed always 1)
++//* Removed HWRSDEC token (assumed always 1)
++//* Removed ILEC_AD11_ALCATEL337 token (assumed always 0)
++//* Removed ILEC_AD11_HDSLNOISEFIX token (assumed always 0)
++//* Removed ILEC_AD11_MODULATEPILOT token (assumed always 0)
++//* Removed ILEC_AD11_NEWINTERPOLATE token (assumed always 0)
++//* Removed ILEC_AD11_USTXHPF token (assumed always 0)
++//* Removed SWDI token (assumed always 1)
++//* Removed TD_AGC token (assumed always 1)
++//* Removed DSPDP_LEGACY_TARGET token (assumed always 0)
++//* Removed AD11_20, AD11_20NL and AD11_20_NEWPREC token (always 1)
++//* Removed AI token (assumed always 1)
++//* Removed ATUC token (assumed always 0)
++//* Removed EU token (assumed always 0)
++//* Removed EVM2 token (assumed always 0)
++//* Removed INTRPT_RUFUS token (assumed always 0)
++//* Removed MODPILOT token (assumed always 0)
++//* Removed SL and SL_EVM tokens (assumed always 0)
++//* Removed STBIFX token (assumed always 0)
++//* Removed STD token (assumed always 1)
++//* Removed SWDI_LOOPBACK token (assumed always 0)
++//* Removed TID token (assumed always 0)
++//* Removed TII token (assumed always 1)
++//* Removed TIPCI token (assumed always 1)
++//* Removed UDI token (assumed always 1)
++//* Removed DC_BIAS token (assumed always 1)
++//* 04/05/01 Barnett Added DSPDP_ prefix to tokens that originate
++//* in the public interface.
++//* 05/07/01 Jack Huang Removed DOUBLE_XMT_RATE token.
++//* 05/16/01 Barnett Added back in EXTERNBERT token in support
++//* of saving PMEM.
++//* 06/05/01 Jack Huang Fixed the rules for ar0500mp_debug target
++//* 04/23/01 M. Halleck Merge Astro Wu's DDC enhancements
++//* 06/05/01 M. Capps Changed DSP_DEBUG to ENHANCED_SERIAL_DEBUG
++//* 07/03/01 M. Capps Replaced ESD token with !DDC, added DEV_DEBUG
++//* 06/26/01 J. Bergsagel Removed all the old ap03... stuff
++//* Removed OLAYDP_HOST token (again)
++//* Removed CROSSTALK token (assumed always 1)
++//* Removed TEQ_AVG token (assumed always 0)
++//* Removed DE token (assumed always 1)
++//* Removed PVAT token and au0501cp target
++//* Removed FASTRETRAIN token (assumed always 0)
++//* 07/05/01 J. Bergsagel Changed PCIMASTER token to TC_ATM_PCIMASTER
++//* 07/20/01 Umesh Iyer Added ATMBERT token. ATMBERT is conditional on SWTC definition. if SWTC is 0
++//* ATMBERT should be 0. Else it can be 0/1. Default 0.
++//* 07/23/01 J. Bergsagel Changed name from defines_u.h to dpsys_defines.h
++//* 07/24/01 Barnett Added support for build of $(TARGET)_diag mfgr'ing targets.
++//* 08/02/01 Michael Seidl renamed KAPIL token to !AD1X
++//* 08/02/01 Michael Seidl renamed GHS token to PMEMSAVE_GHS
++//* 08/03/01 S.Yim Added MFGR_DIAG token for afe diagnostic
++//* Added AFEDEV token for afe device driver
++//* Added DSPBIOSII token for dsp bios
++//* 09/21/01 Sameer Enable EXTERNBERT. Disable ATMBERT.
++//* 10/01/01 U.Dasgupta Turned off SMART_MARGIN for ap0500mb because of FECs/CRCs;
++//* 10/09/01 Barnett Added support for ar0500db.
++//* 10/12/01 Barnett Disable EXTERNBERT.
++//* 10/15/01 Barnett Turn off SMART_MARGIN.
++//* 11/07/01 Barnett Def'ed ISDN_DEBUG for all targets to avoid compiler warnings.
++//* Assumed defaul value is zero.
++//* 11/13/01 Barnett Reworked ar0500db_debug to build JTAG-bootable load.
++//* The equivalent production target should only be flash-bootable.
++//* 01/11/02 Yim Added TOKEN JTAG to build JTAG load ar0500db_diag.
++//* 01/23/02 U Iyer Added DEBUG_LOG token. Default value 0
++//* 01/31/02 Barnett Added support for ar0700mp target.
++//* 02/04/02 S.Yim Added TOKEN JTAG to build JTAG load ar0500mp_diag
++//* 02/11/02 U Iyer Added MARGIN_DELTA_RETRAIN token. Default value 1
++//* 05/15/02 Sameer V Enabled EXTERNBERT token for AR5 and AU5 platforms. EXTERNBERT is
++//* not supported on AR5H.
++//* 02/14/02 Barnett Don't ref the SWTC feature token if mfgr'ing diag target.
++//* 02/19/02 Yim Added support to build au0502db_diag target.
++//* 03/08/02 Nirmal Warke Added feature token HYBRID_SWITCH
++//* 03/15/02 U G Jani Turned ON Bitswap support for AU5I (au0502db) targets.
++//* 04/08/02 U G Jani Enabled NLNOISEADJSNR token for AU5I targets.
++//* 06/24/02 Seungmok Oh Added PERTONE_EQ token support for those targets:
++//* (ar0500mp_debug, au0502mp_debug, ar0500mp, au0502mp)
++//* 06/26/02 Mallesh Added DS_PWR_CUTBACK token. Default value 1.
++//* 06/27/02 Mallesh Changed default value of DS_PWR_CUTBACK token to 0.
++//* 06/29/02 U.Dasgupta Token cleanup: Removed ISDN_DEBUG token
++//* 04/29/02 Mannering Remove EIGHTBITSRAM, Combined DOUBLEBUFFER with
++//* BITSWAP, added FPGA token
++//* 05/03/02 Mannering cleanup token changed by the new routine names
++//* 05/06/02 Mannering Add tokens OUTBAND and INBAND for codec commands
++//* If both OUTBAND and INBAND are 0 codec register are
++//* memory mapped.
++//* 05/29/2002 S.Yim Removed AD1X, AFEDEV
++//* 08/31/2002 Paul Hunt Added PERTONE_EQ and HYBRID_SWITCH for ar0700mp
++//* 09/12/2002 Paul Hunt Added support for ar0700db target.
++//* 08/07/2002 U.Dasgupta Turned off MARGIN_DELTA_RETRAIN feature for ISDN platforms
++//* 11/14/2002 Paul Hunt Merged AX5 MR6 PC modifications into AR7 codebase, specifically
++//* turned off MARGIN_DELTA_RETRAIN feature for ar0700db target
++//* 08/26/2002 N. Warke Added DUAL_TEQ token. Active only for Ax7 target
++//* 09/26/2002 Mannering Add token CODEC_EMU for codec emulator board
++//* 10/15/2002 Iyer/Molla Added DMT_BIS token for DELT support
++//* 10/21/2002 A. Redfern Added PHY_EC_ENABLE and PHY_PATH_ENABLE tokens
++//* 10/23/2002 A. Redfern Removed LINE_DIAG token
++//* 10/28/2002 J. Bergsagel Cleaned up old targets and cleaned up the token list
++//* 10/30/2002 A. Redfern Added PHY_TDW_ENABLE
++//* 11/01/2002 A. Redfern Removed SMART_MARGIN token
++//* 11/01/2002 Mustafa Turned on SPECTRAL_SHAPING features for Lucent AnyMedia O.69 Interop.
++//* 11/15/2002 Yim/Mannering Added CODEC_EMU token for analog emulation board specifics
++//* 11/15/2002 Iyer/Molla Added DEBUG_DELT and MEM_STR token to support DELT debug
++//* 12/27/2002 Sameer V Added ATM_TC_HW token for Sangam.
++//* 01/06/2003 J. Bergsagel Added default values for NLNOISEADJSNR, ARTT and DS_PWR_CUTBACK
++//* 01/07/2003 S.Yim Modified ar0700db_diag target to turn on ISDN token
++//* 01/22/2003 J. Bergsagel Added back in defines for the debug targets.
++//* 01/21/2003 MCB Implemented Ax7 UNIT-MODULE modular software framework.
++//* 01/31/2003 J. Bergsagel Made debug targets to be for the FPGA platform; non-debug for Sangam.
++//* Turned off DUAL_TEQ, PHY_EC_ENABLE and PHY_PATH_ENABLE by default
++//* for the Sangam (non-debug) targets.
++//* Turned off OLAYDP token by default.
++//* Turned off SWTC and turned on ATM_TC_HW by default for Sangam targets.
++//* 01/29/2003 Sameer V Added ATMBERT_HW token for Sangam.
++//* 02/04/2003 D. Mannering Added CO_PROFILE token
++//* 02/19/2003 Sameer V Added back EXTERNBERT token for ar0700mp_dp and ar0700db_dp targets.
++//* Disabled EXTERNBERT for debug target since it is not supported on the
++//* FPGA platform.
++//* 02/21/2003 A. Redfern Turned off OAM_EOC, AOC and BITSWAP (until memory issues are resolved).
++//* Turned on DUAL_TEQ, PHY_PATH_ENABLE and PHY_EC_ENABLE.
++//* 02/21/2003 D. Mannering Added DEBUG_DUMP.
++//* 03/06/2003 J. Bergsagel Cleaned up tokens for each target and switched diag targets
++//* over to the Sangam platform (instead of the FPGA platform).
++//* 03/07/2003 J. Bergsagel Cleaned up TC and BERT tokens
++//* 03/11/2003 J. Bergsagel Turned on AOC and BITSWAP for Sangam POTS and ISDN targets.
++//* 03/20/2003 Mallesh Added SHALF token.
++//* 03/24/2003 F. Mujica Enable hybrid selection
++//* 03/26/2003 A. Redfern Removed PMEMSAVE_GHS (always = 1).
++//* 04/08/2003 F. Mujica Renamed HYBRID_SWITCH token to PHY_HYB_ENABLE
++//* 04/08/2003 J. Bergsagel Turned off PHY_HYB_ENABLE for _debug targets (FPGA board builds)
++//* 04/09/2003 J. Bergsagel Turned on OLAYDP only for ar0700mp and ar0700db.
++//* Turned on AOC, BITSWAP, and OAM_EOC for ar0700mp and ar0700db.
++//* 04/09/2003 J. Bergsagel Corrected name "PHY_HYB_SELECT" to "PHY_HYB_ENABLE"
++//* 04/15/2003 A. Redfern Turned on ECI_PULSECOM_INTEROP because phase optimization was enabled.
++//* 05/05/2003 D. Mannering Review Comments - turn on AOC, EXTERNBERT, SHALF, for ar0700mp; amd
++//* turn on AOC for ar0700db
++//* 05/11/2003 Prashant S Added DMT_BIS token for AR7 Soft DI work
++//* 05/13/2003 J. Bergsagel Turned on IMPROVED_STAT_SUPPORT_06_03_00 by default for necessary statistics
++//* 05/15/2003 J. Bergsagel Turned off CO_PROFILE for diag targets.
++//* 05/27/2003 U.Dasgupta Added NLNOISEADJSNR_EC token for ISDN - to take care of non-linear noise
++//* (from ISDN splitter) compensation.
++//* 06/02/2003 Z. Yang Added PHY_NDIAG_ENABLE token.
++//* 06/02/2003 Z. Yang Added COMB_LINEDIAG_ENABLE token.
++//* 06/05/2003 P. Hunt Turned on ATUC_CLEARDOWN_CHANGE token for all targets.
++//* 06/05/2003 Mallesh Turned on CENTILLIUM_VENDORID_AND_TXRATE_CHNG to enable logging the vendor ID
++//* for centillium and litespan
++//* 06/05/2003 U.Dasgupta Turned on SHALF token for ISDN.
++//* 06/06/2003 U.Dasgupta Turned on G.hs nonstandard field token for ar0700db target.
++//* 06/12/2003 J. Bergsagel Changed *_debug targets to be for JTAG=1 instead of FPGA targets
++//* IMPORTANT: For non-JTAG cases, "JTAG" should be undefined.
++//* Therefore, "JTAG" should not have a default case at the bottom (JTAG 0)
++//* 06/18/2003 A. Redfern Turned on spectral shaping token for all targets.
++//* 06/23/2003 J. Bergsagel Turned off GHS_NON_STD_FIELD token for ar0700db until bugs are fixed.
++//* 06/23/2003 U G Jani Undid the above change since the bug is fixed.
++//* 06/27/2003 Mallesh Removed all the interop tokens which are no longer required.
++//* 08/20/2003 J. Bergsagel Added default value for OVHD_PMDTEST_PARA and put default section
++//* tokens in alphabetical order.
++//* 10/09/2003 Hanyu Liu Defined token ADSL2_1BIT_TONE to support Rx one bit constellation.
++//* 10/12/2003 Hanyu Liu Defined token ADSL2_BSWP for bitswap.
++//* 10/20/2003 Xiaohui Li Added READSL2_ENABLE token.
++//* 12/01/2003 Seungmok Oh Added TXDF2B_PROFILING token, which is active only for POTS target.
++//* 12/09/2003 Jack Huang Turned on GHS_NON_STD_FIELD support for AR7 POTS targets
++//* 12/16/2003 Mustafa T. Added the necessary definitions for diag target.
++//*****************************************************************************************************
++//*
++//* The default flag settings are:
++//*
++//* -dATUC=1 -dSTD=0 -dISDN=0 -dTIPCI=0 -dTID=0 -dTII=0 -dAI=0
++//* -dEVM2=0 -dEU=0 -dSL=0 -dSL_EVM=1 -dGLITE=0
++//*
++//* and are set after all the per-suffix options have had a chance to
++//* set them. Each flag is only set if it has not previously been set, so
++//* per-suffix settings can override defaults, and command-line defines can
++//* override per-suffix settings.
++//*
++//*****************************************************************************
++
++
++//* ===========================================================================
++//* Suffix codes
++//* The command-line can include -dOBJSFX_xxx to get a flag set
++//* instead of explicitly setting each flag on each CC/ASM command-line.
++//* and the object suffix will control the settings of "feature" constants.
++//* ===========================================================================
++//
++//* ===========================================================================
++// Flag settings for new suffixes (in alphabetical order of suffix)
++// Each suffix has to specify only those flags which differ from the
++// default settings.
++//* ===========================================================================
++// NOTE: Try to keep feature flags in alphabetical order to ease maintenance.
++//* ===========================================================================
++//*
++
++#define CHIPSET_ID_UNKN '?'
++#define CHIPSET_ID_AH 'H'
++#define CHIPSET_ID_AP 'P'
++#define CHIPSET_ID_AR 'R'
++#define CHIPSET_ID_ARV 'R'
++#define CHIPSET_ID_AT 'T'
++#define CHIPSET_ID_AU 'U'
++
++#define CHIPSET_ID2_GENERIC '0'
++#define CHIPSET_ID2_ARV 'R'
++
++ #define DSPDP_IMAGE_ID_STANDARD(code) ( \
++ STANDARD_is_MULTIMODE(code) ? "M" : \
++ STANDARD_is_GDMT(code) ? "D" : \
++ STANDARD_is_GLITE(code) ? "L" : \
++ STANDARD_is_T1413(code) ? "T" : "_")
++
++ #define DSPDP_IMAGE_ID_SERVICE(code) ( \
++ SERVICE_is_POTS(code) ? "P" : \
++ SERVICE_is_ISDN_ANNEXB(code) ? "B" : \
++ SERVICE_is_ISDN_ANNEXC(code) ? "C" : \
++ SERVICE_is_ISDN_PROP(code) ? "I" : "")
++
++// Bit-codes for feature byte in new version.
++//
++// 0000 0000
++// |||| ||||
++// |||| |||+ -- POTS
++// |||| ||+---- ISDN_ANNEXB
++// |||| |+----- ISDN_ANNEXC
++// |||| +------ ISDN_PROP
++// |||+--------
++// ||+--------- GHS
++// |+---------- GLITE
++// +----------- T1413
++//
++//
++#define FEATURE_BIT_T1413 0x80
++#define FEATURE_BIT_GLITE 0x40
++#define FEATURE_BIT_GHS 0x20
++#define FEATURE_BIT_ISDN_PROP 0x08
++#define FEATURE_BIT_ISDN_ANNEXC 0x04
++#define FEATURE_BIT_ISDN_ANNEXB 0x02
++#define FEATURE_BIT_POTS 0x01
++
++#define STANDARD_BITS_MASK (FEATURE_BIT_T1413 | FEATURE_BIT_GLITE | FEATURE_BIT_GHS)
++#define STANDARD_BITS_T1413 FEATURE_BIT_T1413
++#define STANDARD_BITS_GHS FEATURE_BIT_GHS
++#define STANDARD_BITS_GLITE (FEATURE_BIT_GLITE | FEATURE_BIT_GHS)
++#define STANDARD_BITS_GDMT (STANDARD_BITS_T1413 | STANDARD_BITS_GHS)
++#define STANDARD_BITS_MULTIMODE (STANDARD_BITS_T1413 | STANDARD_BITS_GLITE | STANDARD_BITS_GDMT)
++
++#define SERVICE_BIT_ISDN_ANNEXB FEATURE_BIT_ISDN_ANNEXB
++#define SERVICE_BIT_ISDN_ANNEXC FEATURE_BIT_ISDN_ANNEXC
++#define SERVICE_BIT_ISDN_PROP FEATURE_BIT_ISDN_PROP
++#define SERVICE_BIT_POTS FEATURE_BIT_POTS
++
++//
++// Debug new-style suffixes
++//
++//
++
++#if defined(OBJSFX_ar0700db_debugobj)
++#ifndef OBJSFX_ar0700dbobj
++#define OBJSFX_ar0700dbobj 1
++#endif
++// Here, in alphabetic order, are the feature tokens that
++// distinguish this suffix from its non-_debug partner:
++// (All other tokens from the non-_debug partner that are non-conflicting will also be picked up)
++
++#ifndef JTAG
++#define JTAG 1
++#endif
++
++#elif defined(OBJSFX_ar0700mp_debugobj)
++#ifndef OBJSFX_ar0700mpobj
++#define OBJSFX_ar0700mpobj 1
++#endif
++// Here, in alphabetic order, are the feature tokens that
++// distinguish this suffix from its non-_debug partner:
++// (All other tokens from the non-_debug partner that are non-conflicting will also be picked up)
++
++#ifndef ADSL2_BSWP
++#define ADSL2_BSWP 1
++#endif
++#ifndef AOC
++#define AOC 1
++#endif
++#ifndef BITSWAP
++#define BITSWAP 1
++#endif
++#ifndef DEBUG_ADSL2
++#define DEBUG_ADSL2 0
++#endif
++#ifndef DEBUG_LOG
++#define DEBUG_LOG 0
++#endif
++#ifndef GHS_NON_STD_FIELD
++#define GHS_NON_STD_FIELD 1
++#endif
++#ifndef JTAG
++#define JTAG 1
++#endif
++#endif // end of the series of "#elif defined" for debug targets
++
++
++//
++// Standard new-style suffixes for operational and mfgr'ing diag.
++//
++
++#if defined(OBJSFX_ar0700dbobj)
++#define CHIPSET_AR07 1
++#define PLATFORM_AR0700 1
++#define DSPDP_CHIPSET_ID CHIPSET_ID_AR
++#define DSPDP_CHIPSET_ID2 CHIPSET_ID2_GENERIC
++#define DSPDP_CHIPSET_GEN 7
++#define DSPDP_HARDWARE_REV1 '0'
++#define DSPDP_HARDWARE_REV2 '0'
++#define DSPDP_FEATURE_CODE (STANDARD_BITS_GDMT|SERVICE_BIT_ISDN_ANNEXB)
++#ifndef AOC
++#define AOC 1
++#endif
++// ATM_TC_HW and SWTC are mutually exclusive
++#ifndef ATM_TC_HW
++#define ATM_TC_HW 1
++#endif
++#ifndef SWTC
++#define SWTC 0
++#endif
++#ifndef BITSWAP
++#define BITSWAP 1
++#endif
++#ifndef EXTERNBERT
++#define EXTERNBERT 0
++#endif
++#ifndef GHS_NON_STD_FIELD
++#define GHS_NON_STD_FIELD 1
++#endif
++#ifndef MARGIN_DELTA_RETRAIN
++#define MARGIN_DELTA_RETRAIN 0
++#endif
++#ifndef NLNOISEADJSNR_EC
++#define NLNOISEADJSNR_EC 1
++#endif
++#ifndef OLAYDP
++#define OLAYDP 1
++#endif
++#ifndef SHALF
++#define SHALF 1
++#endif
++
++
++#elif defined(OBJSFX_ar0700db_diagobj)
++#define CHIPSET_AR07 1
++#define PLATFORM_AR0700 1
++#define DSPDP_CHIPSET_ID CHIPSET_ID_AR
++#define DSPDP_CHIPSET_ID2 CHIPSET_ID2_GENERIC
++#define DSPDP_CHIPSET_GEN 7
++#define DSPDP_HARDWARE_REV1 '0'
++#define DSPDP_HARDWARE_REV2 '0'
++#define DSPDP_FEATURE_CODE (STANDARD_BITS_GDMT|SERVICE_BIT_ISDN_ANNEXB)
++#ifndef AOC
++#define AOC 0
++#endif
++// ATM_TC_HW and SWTC are mutually exclusive (or both must be off)
++#ifndef ATM_TC_HW
++#define ATM_TC_HW 0
++#endif
++#ifndef SWTC
++#define SWTC 0
++#endif
++#ifndef BITSWAP
++#define BITSWAP 0
++#endif
++#ifndef CO_PROFILE
++#define CO_PROFILE 0
++#endif
++#ifndef MARGIN_DELTA_RETRAIN
++#define MARGIN_DELTA_RETRAIN 0
++#endif
++#ifndef MFGR_DIAG
++#define MFGR_DIAG 1
++#endif
++#ifndef OAM_EOC
++#define OAM_EOC 0
++#endif
++#ifndef OLAYDP
++#define OLAYDP 0
++#endif
++#ifndef SNR_UPDATE
++#define SNR_UPDATE 0
++#endif
++
++#elif defined(OBJSFX_ar0700mpobj)
++#define CHIPSET_AR07 1
++#define PLATFORM_AR0700 1
++#define DSPDP_CHIPSET_ID CHIPSET_ID_AR
++#define DSPDP_CHIPSET_ID2 CHIPSET_ID2_GENERIC
++#define DSPDP_CHIPSET_GEN 7
++#define DSPDP_HARDWARE_REV1 '0'
++#define DSPDP_HARDWARE_REV2 '0'
++#define DSPDP_FEATURE_CODE (STANDARD_BITS_MULTIMODE|SERVICE_BIT_POTS)
++#ifndef AOC
++#define AOC 1
++#endif
++// ATM_TC_HW and SWTC are mutually exclusive
++#ifndef ADSL2_1BIT_TONE
++#define ADSL2_1BIT_TONE 0
++#endif
++#ifndef ADSL2_BSWP
++#define ADSL2_BSWP 1
++#endif
++#ifndef ATM_TC_HW
++#define ATM_TC_HW 1
++#endif
++#ifndef SWTC
++#define SWTC 0
++#endif
++#ifndef BITSWAP
++#define BITSWAP 1
++#endif
++#ifndef EXTERNBERT
++#define EXTERNBERT 0
++#endif
++#ifndef OLAYDP
++#define OLAYDP 1
++#endif
++#ifndef DMT_BIS
++#define DMT_BIS 1
++#endif
++#ifndef SHALF
++#define SHALF 1
++#endif
++#ifndef MEM_STR
++#define MEM_STR 0
++#endif
++#ifndef DS_LOOP_BACK
++#define DS_LOOP_BACK 0
++#endif
++#ifndef LOOP_BACK_DEBUG
++#define LOOP_BACK_DEBUG 0
++#endif
++#ifndef US_LOOP_BACK
++#define US_LOOP_BACK 0
++#endif
++#ifndef OVHD_PMDTEST_PARA
++#define OVHD_PMDTEST_PARA 0
++#endif
++#ifndef DS_RX_CODEWORD
++#define DS_RX_CODEWORD 1
++#endif
++#ifndef READSL2_ENABLE
++#define READSL2_ENABLE 1
++#endif
++#ifndef GHS_NON_STD_FIELD
++#define GHS_NON_STD_FIELD 1
++#endif
++
++#elif defined(OBJSFX_ar0700mp_diagobj)
++#define CHIPSET_AR07 1
++#define PLATFORM_AR0700 1
++#define DSPDP_CHIPSET_ID CHIPSET_ID_AR
++#define DSPDP_CHIPSET_ID2 CHIPSET_ID2_GENERIC
++#define DSPDP_CHIPSET_GEN 7
++#define DSPDP_HARDWARE_REV1 '0'
++#define DSPDP_HARDWARE_REV2 '0'
++#define DSPDP_FEATURE_CODE (STANDARD_BITS_MULTIMODE|SERVICE_BIT_POTS)
++#ifndef ADSL2_BSWP
++#define ADSL2_BSWP 0
++#endif
++#ifndef AOC
++#define AOC 0
++#endif
++// ATM_TC_HW and SWTC are mutually exclusive (or both must be off)
++#ifndef ATM_TC_HW
++#define ATM_TC_HW 0
++#endif
++#ifndef SWTC
++#define SWTC 0
++#endif
++#ifndef BITSWAP
++#define BITSWAP 0
++#endif
++#ifndef CO_PROFILE
++#define CO_PROFILE 0
++#endif
++#ifndef DMT_BIS
++#define DMT_BIS 0
++#endif
++#ifndef MARGIN_DELTA_RETRAIN
++#define MARGIN_DELTA_RETRAIN 0
++#endif
++#ifndef MFGR_DIAG
++#define MFGR_DIAG 1
++#endif
++#ifndef OAM_EOC
++#define OAM_EOC 0
++#endif
++#ifndef OLAYDP
++#define OLAYDP 0
++#endif
++#ifndef SNR_UPDATE
++#define SNR_UPDATE 0
++#endif
++#ifndef US_CRC_RETRAIN
++#define US_CRC_RETRAIN 0
++#endif
++#ifndef ADSL2_BSWP
++#define ADSL2_BSWP 0
++#endif
++#ifndef DMT_BIS
++#define DMT_BIS 0
++#endif
++#ifndef DS_RX_CODEWORD
++#define DS_RX_CODEWORD 0
++#endif
++
++#else
++#define DSPDP_CHIPSET_ID CHIPSET_ID_UNKN
++#define DSPDP_CHIPSET_ID2 CHIPSET_ID2_GENERIC
++#define DSPDP_CHIPSET_GEN 0
++#define DSPDP_HARDWARE_REV1 '0'
++#define DSPDP_HARDWARE_REV2 '0'
++#define DSPDP_FEATURE_CODE 0
++#endif
++
++// For use in checking the code in drivers -- indented to avoid .h->.ah
++ #define STANDARD_is_T1413(code) (!(((code) & STANDARD_BITS_MASK) ^ STANDARD_BITS_T1413))
++ #define STANDARD_is_GLITE(code) (!(((code) & STANDARD_BITS_MASK) ^ STANDARD_BITS_GLITE))
++ #define STANDARD_is_GHS(code) (((code) & STANDARD_BITS_MASK) & STANDARD_BITS_GHS)
++ #define STANDARD_is_GDMT(code) (!(((code) & STANDARD_BITS_MASK) ^ (STANDARD_BITS_T1413 | STANDARD_BITS_GHS)))
++ #define STANDARD_is_MULTIMODE(code) (!(((code) & STANDARD_BITS_MASK) ^ (STANDARD_BITS_T1413 | STANDARD_BITS_GLITE | STANDARD_BITS_GDMT)))
++ #define SERVICE_is_POTS(code) ((code) & SERVICE_BIT_POTS)
++ #define SERVICE_is_ISDN_ANNEXB(code) ((code) & SERVICE_BIT_ISDN_ANNEXB)
++ #define SERVICE_is_ISDN_ANNEXC(code) ((code) & SERVICE_BIT_ISDN_ANNEXC)
++ #define SERVICE_is_ISDN_PROP(code) ((code) & SERVICE_BIT_ISDN_PROP)
++
++#define STANDARD_T1413 (!((DSPDP_FEATURE_CODE & STANDARD_BITS_MASK) ^ STANDARD_BITS_T1413))
++#define STANDARD_GLITE (!((DSPDP_FEATURE_CODE & STANDARD_BITS_MASK) ^ STANDARD_BITS_GLITE))
++#define STANDARD_GHS ((DSPDP_FEATURE_CODE & STANDARD_BITS_MASK) & STANDARD_BITS_GHS)
++#define STANDARD_GDMT (!((DSPDP_FEATURE_CODE & STANDARD_BITS_MASK) ^ (STANDARD_BITS_T1413 | STANDARD_BITS_GHS)))
++#define STANDARD_MULTIMODE (!((DSPDP_FEATURE_CODE & STANDARD_BITS_MASK) ^ (STANDARD_BITS_T1413 | STANDARD_BITS_GLITE | STANDARD_BITS_GDMT)))
++
++#define SERVICE_POTS (DSPDP_FEATURE_CODE & SERVICE_BIT_POTS)
++#define SERVICE_ISDN_ANNEXB (DSPDP_FEATURE_CODE & SERVICE_BIT_ISDN_ANNEXB)
++#define SERVICE_ISDN_ANNEXC (DSPDP_FEATURE_CODE & SERVICE_BIT_ISDN_ANNEXC)
++#define SERVICE_ISDN_PROP (DSPDP_FEATURE_CODE & SERVICE_BIT_ISDN_PROP)
++#define SERVICE_ISDN (SERVICE_ISDN_ANNEXB | SERVICE_ISDN_ANNEXC | SERVICE_ISDN_PROP)
++
++
++//
++// Backwards compatibility with old tokens
++//
++
++#if (SERVICE_POTS)
++#ifndef ISDN
++#define ISDN 0
++#endif
++#endif
++
++#if (SERVICE_ISDN_ANNEXB | SERVICE_ISDN_PROP)
++#ifndef ISDN
++#define ISDN 1
++#endif
++#endif
++
++
++//
++//* ===========================================================================
++// More Default settings
++//* ===========================================================================
++//
++
++//
++// BEGIN Could automatically generate showdefs code
++//
++#ifndef AOC
++#define AOC 1
++#endif
++#ifndef ARTT
++#define ARTT 0
++#endif
++#ifndef ATMBERT
++#define ATMBERT 0
++#endif
++// ATM_TC_HW and SWTC are mutually exclusive
++#ifndef ATM_TC_HW
++#define ATM_TC_HW 1
++#endif
++#if ATM_TC_HW
++#ifndef ATMBERT_HW
++#define ATMBERT_HW 1
++#endif
++#ifndef SWTC
++#define SWTC 0
++#endif
++#else // else case for #if ATM_TC_HW
++#ifndef ATMBERT_HW
++#define ATMBERT_HW 0
++#endif
++#ifndef SWTC
++#define SWTC 1
++#endif
++#endif // end of #if ATM_TC_HW
++#ifndef ATM_TC_PATH1_ON
++#define ATM_TC_PATH1_ON 0
++#endif
++#ifndef BITSWAP
++#define BITSWAP 1
++#endif
++#ifndef COMB_LINEDIAG_ENABLE
++#define COMB_LINEDIAG_ENABLE 0
++#endif
++#ifndef CODEC_EMU
++#define CODEC_EMU 0
++#endif
++#ifndef CO_PROFILE
++#define CO_PROFILE 1
++#endif
++#ifndef DDC
++#define DDC 0
++#endif
++#ifndef DEBUG_ADSL2
++#define DEBUG_ADSL2 0
++#endif
++#ifndef DEBUG_DUMP
++#define DEBUG_DUMP 0
++#endif
++#ifndef DEBUG_LOG
++#define DEBUG_LOG 0
++#endif
++#ifndef DEV_DEBUG
++#define DEV_DEBUG 0
++#endif
++#ifndef DS_LOOP_BACK
++#define DS_LOOP_BACK 0
++#endif
++#ifndef DS_RX_CODEWORD
++#define DS_RX_CODEWORD 1
++#endif
++#ifndef LOOP_BACK_DEBUG
++#define LOOP_BACK_DEBUG 0
++#endif
++#ifndef US_LOOP_BACK
++#define US_LOOP_BACK 0
++#endif
++#ifndef DPLL_MODE
++#define DPLL_MODE 0
++#endif
++#ifndef DSPBIOSII
++#define DSPBIOSII 0
++#endif
++#ifndef DMT_BIS
++#define DMT_BIS 1
++#endif
++#ifndef ADSL2_1BIT_TONE
++#define ADSL2_1BIT_TONE 0
++#endif
++#ifndef ADSL2_BSWP
++#define ADSL2_BSWP 1
++#endif
++#ifndef MEM_STR
++#define MEM_STR 0
++#endif
++#ifndef DS_PWR_CUTBACK
++#define DS_PWR_CUTBACK 0
++#endif
++#ifndef DUAL_TEQ
++#define DUAL_TEQ 1
++#endif
++#ifndef EXTERNBERT
++#define EXTERNBERT 0
++#endif
++#ifndef FPGA
++#define FPGA 0
++#endif
++#ifndef INBAND
++#define INBAND 0
++#endif
++#ifndef ISDN
++#define ISDN 0
++#endif
++#ifndef ISDN_DEBUG
++#define ISDN_DEBUG 0
++#endif
++#ifndef LINE_DIAG
++#define LINE_DIAG 1
++#endif
++#ifndef LOOP_BACK_DEBUG
++#define LOOP_BACK_DEBUG 0
++#endif
++#ifndef MANUFACTURING_TESTS
++#define MANUFACTURING_TESTS 0
++#endif
++#ifndef MARGIN_DELTA_RETRAIN
++#define MARGIN_DELTA_RETRAIN 1
++#endif
++#ifndef MEM_STR
++#define MEM_STR 0
++#endif
++#ifndef MFGR_DIAG
++#define MFGR_DIAG 0
++#endif
++#ifndef NLNOISEADJSNR
++#define NLNOISEADJSNR 0
++#endif
++#ifndef NLNOISEADJSNR_EC
++#define NLNOISEADJSNR_EC 0
++#endif
++#ifndef NTR_MODE
++#define NTR_MODE 0
++#endif
++#ifndef OAM_EOC
++#define OAM_EOC 1
++#endif
++#ifndef OLAYDP
++#define OLAYDP 0
++#endif
++#ifndef OLAYDP_EMIF
++#define OLAYDP_EMIF 0
++#endif
++#ifndef OLAYDP_2STEP
++#define OLAYDP_2STEP 0
++#endif
++#ifndef OLAYDP_PCI
++#define OLAYDP_PCI 0
++#endif
++#ifndef OUTBAND
++#define OUTBAND 0
++#endif
++#ifndef OVHD_PMDTEST_PARA
++#define OVHD_PMDTEST_PARA 0
++#endif
++#ifndef PERTONE_EQ
++#define PERTONE_EQ 0
++#endif
++#ifndef PHY_EC_ENABLE
++#define PHY_EC_ENABLE 1
++#endif
++#ifndef PHY_HYB_ENABLE
++#define PHY_HYB_ENABLE 1
++#endif
++#ifndef PHY_NDIAG_ENABLE
++#define PHY_NDIAG_ENABLE 0
++#endif
++#ifndef PHY_PATH_ENABLE
++#define PHY_PATH_ENABLE 1
++#endif
++#ifndef PHY_TDW_ENABLE
++#define PHY_TDW_ENABLE 0
++#endif
++#ifndef TC_ATM_PCIMASTER
++#define TC_ATM_PCIMASTER 0
++#endif
++#ifndef SEPARATE_TX_RX_BUFFERS
++#define SEPARATE_TX_RX_BUFFERS 0
++#endif
++#ifndef SHALF
++#define SHALF 0
++#endif
++#ifndef SPECTRAL_SHAPING
++#define SPECTRAL_SHAPING 1
++#endif
++#ifndef SNR_UPDATE
++#define SNR_UPDATE 1
++#endif
++#ifndef TC_DEBUG
++#define TC_DEBUG 0
++#endif
++#ifndef TC_LOOPBACK
++#define TC_LOOPBACK 0
++#endif
++#ifndef TESTMODE
++#define TESTMODE 0
++#endif
++#ifndef TRELLIS
++#define TRELLIS 1
++#endif
++#ifndef TXDF2B_PROFILING
++#if (SERVICE_POTS & (!MFGR_DIAG) & (CO_PROFILE))
++#define TXDF2B_PROFILING 1
++#else
++#define TXDF2B_PROFILING 0
++#endif
++#endif
++#ifndef US_CRC_RETRAIN
++#define US_CRC_RETRAIN 1
++#endif
++#ifndef US_LOOP_BACK
++#define US_LOOP_BACK 0
++#endif
++#ifndef USB
++#define USB 0
++#endif
++#ifndef READSL2_ENABLE
++#define READSL2_ENABLE 1
++#endif
++
++// Interop tokens
++#ifndef GHS_NON_STD_FIELD
++#define GHS_NON_STD_FIELD 0
++#endif
++#ifndef LUCENT_ANYMEDIA_ENIATT_INTEROP
++#define LUCENT_ANYMEDIA_ENIATT_INTEROP 0
++#endif
++
++
++//
++// END Could automatically generate showdefs code
++//
++#if DSPDP_FEATURE_CODE
++#else
++// Unrecognized_suffix____check_spelling
++#endif
++//
++// LNK_CMD is set when running CPP to generate lnk_cpe.cmd file
++// -- the linker is not happy when it sees C code show up in the
++// result!
++//
++#ifndef LNK_CMD
++extern int compile_happy; // Keep the compiler from complaining about an empty file
++#endif
++
++#endif
++
+diff -urN linux.old/drivers/atm/sangam_atm/env_def_typedefs.h linux.dev/drivers/atm/sangam_atm/env_def_typedefs.h
+--- linux.old/drivers/atm/sangam_atm/env_def_typedefs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/env_def_typedefs.h 2005-08-23 04:46:50.104842632 +0200
+@@ -0,0 +1,228 @@
++#ifndef __ENV_DEF_TYPEDEFS_H__
++#define __ENV_DEF_TYPEDEFS_H__ 1
++
++/*******************************************************************************
++* FILE PURPOSE: Define data types for C and TMS320C6x C compilers
++********************************************************************************
++*
++* FILE NAME: dpsys_typedefs.h
++*
++* DESCRIPTION:
++* This file contains the main typedefs that we need.
++*
++* HISTORY:
++*
++* 03/11/97 Bob Lee Created
++* 03/13/97 Chishtie
++* 03/14/97 Bob Lee Format change to meet "Engineering Model
++* - System Architucture Specification"
++* Rev AP3. Jan. 29, 1997
++* 07/21/00 Barnett Moved many common typedefs from
++* host i/f header file to here.
++* 03/30/01 Barnett Mod's per driver team feedback.
++* Some tokens cannot be def'ed
++* if _WINDEF_ is def'ed.
++* 04/05/01 Barnett Added DSPDP_ prefix to tokens that originate
++* in the public interface.
++* 06/01/01 J. Bergsagel Modified to add standard typedefs
++* 07/25/01 J. Bergsagel Changed name from typedefs.h to dpsys_typedefs.h
++* 07/30/01 J. Bergsagel Moved typedefs that were conflicting with Windows
++* driver software to the "#ifndef _WINDEF_" section.
++* 08/09/01 S. Yim Moved FALSE/TRUE definitions from ctl_interface_u.h
++* (conflict with BIOS/std.h)
++* 09/03/01 S. Yim Do not include typedef char and float if _STD defined
++* (conflict with BIOS/std.h)
++* 01/21/03 MCB Implemented Ax7 UNIT-MODULE modular software framework.
++* 03/20/03 Mallesh Defined size of basic variables
++* 03/27/03 F. Mujica Added SINT40 and UINT40 definitions.
++*
++* (C) Copyright Texas Instruments Inc. 1997-2001. All rights reserved.
++*******************************************************************************/
++
++// Common type definitions
++
++// Basic constants needed everywhere
++#ifndef STD_
++#define FALSE 0
++#define TRUE 1
++#endif
++
++// Read-Write Data Types
++typedef signed char SINT8; // Signed 8-bit integer (7-bit magnitude)
++typedef unsigned char UINT8; // Unsigned 8-bit integer
++typedef signed short SINT16; // Signed 16-bit integer (15-bit magnitude)
++typedef unsigned short UINT16; // Unsigned 16-bit integer
++typedef signed int SINT32; // Signed 32-bit integer (31-bit magnitude)
++typedef unsigned int UINT32; // Unsigned 32-bit integer
++typedef long signed int SINT40; // Long signed 40-bit integer
++typedef long unsigned int UINT40; // Long unsigned 40-bit integer
++
++// All pointers are 32 bits long
++typedef SINT8 *PSINT8; // Pointer to SINT8
++typedef UINT8 *PUINT8; // Pointer to UINT8
++typedef SINT16 *PSINT16; // Pointer to SINT16
++typedef UINT16 *PUINT16; // Pointer to UINT16
++typedef SINT32 *PSINT32; // Pointer to SINT32
++typedef UINT32 *PUINT32; // Pointer to UINT32
++
++#define SIZEOF_SINT8 1
++#define SIZEOF_UINT8 1
++#define SIZEOF_SINT16 2
++#define SIZEOF_UINT16 2
++#define SIZEOF_SINT32 4
++#define SIZEOF_UINT32 4
++#define SIZEOF_SINT40 8
++#define SIZEOF_UINT40 8
++
++// Size of Read-Write Data Types - in bytes
++#define SIZEOF_char 1
++#define SIZEOF_Int8 1
++#define SIZEOF_UChar 1
++#define SIZEOF_UInt8 1
++#define SIZEOF_Float 4
++#define SIZEOF_Double 8
++#define SIZEOF_byte 1
++
++// Read-Only Data Types - should be only used for ROM code
++typedef const char CharRom; // 8 bit signed character
++typedef const signed char Int8Rom; // 8 bit signed integer
++typedef const unsigned char UCharRom; // 8 bit unsigned character
++typedef const unsigned char UInt8Rom; // 8 bit unsigned integer
++typedef const float FloatRom; // IEEE 32-bit
++typedef const double DoubleRom; // IEEE 64-bit
++
++#ifndef _WINDEF_
++
++// Read-Write Data Types
++typedef signed char Int8; // 8 bit signed integer
++typedef unsigned char UChar; // 8 bit unsigned character
++typedef unsigned char UInt8; // 8 bit unsigned integer
++#ifndef STD_
++typedef char Char; // 8 bit signed character
++typedef float Float; // IEEE 32-bit
++#endif
++typedef double Double; // IEEE 64-bit
++typedef signed char byte; // 8 bit signed integer
++
++
++// These typedefs collide with those in Win2k DDK inc\WINDEF.H
++
++// common type definition
++typedef unsigned char BYTE; // 8-bit
++typedef signed short SHORT; // 16-bit signed
++typedef unsigned short WORD; // 16-bit
++typedef unsigned int DWORD; // 32-bit, TI DSP has 40 bit longs
++
++// All pointers are 32 bits long
++typedef BYTE *PBYTE; // pointer to 8 bit data
++typedef unsigned char *PCHAR; // pointer to 8 bit data
++typedef SHORT *PSHORT; // pointer to 16 bit data
++typedef WORD *PWORD; // pointer to 16 bit data
++typedef DWORD *PDWORD; // pointer to 32 bit data
++
++#endif // #ifndef _WINDEF_
++
++
++#define SIZEOF_BYTE 1
++#define SIZEOF_SHORT 2
++#define SIZEOF_WORD 2
++#define SIZEOF_DWORD 4
++#define SIZEOF_PCHAR 4
++#define SIZEOF_PWORD 4
++#define SIZEOF_PDWORD 4
++
++// Size of Read-Only Data Types - in bytes
++#define SIZEOF_CharRom 1
++#define SIZEOF_Int8Rom 1
++#define SIZEOF_UCharRom 1
++#define SIZEOF_UInt8Rom 1
++#define SIZEOF_FloatRom 4
++#define SIZEOF_DoubleRom 8
++
++#define SIZEOF_complex_byte (2*SIZEOF_byte)
++#define SIZEOF_PTR_complex_byte 4
++typedef struct {
++ byte re;
++ byte im;
++} complex_byte, *PTR_complex_byte;
++
++#define SIZEOF_complex_short 4
++#define SIZEOF_PTR_complex_short 4
++typedef struct {
++ short re;
++ short im;
++} complex_short, *PTR_complex_short;
++
++#define SIZEOF_complex_int 8
++#define SIZEOF_PTR_complex_int 4
++typedef struct {
++ int re;
++ int im;
++} complex_int, *PTR_complex_int;
++
++typedef struct {
++ int high;
++ unsigned int low;
++} int64;
++
++typedef struct {
++ int64 real;
++ int64 imag;
++} complex_int64;
++
++#define SIZEOF_PVOID 4
++typedef void *PVOID; // pointer to void
++
++//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
++
++#if defined(_TMS320C6X) // TMS320C6xx type definitions
++
++// Read-Write Data Types
++typedef short Int16; // 16 bit signed integer
++typedef unsigned short UInt16; // 16 bit unsigned integer
++typedef int Int32; // 32 bit signed integer
++typedef unsigned int UInt32; // 32 bit unsigned signed integer
++typedef long Long40; // 40 bit signed integer
++typedef unsigned long ULong40; // 40 bit unsigned signed integer
++
++// Size of Read-Write Data Types - in bytes
++#define SIZEOF_Int16 2
++#define SIZEOF_UInt16 2
++#define SIZEOF_Int32 4
++#define SIZEOF_UInt32 4
++#define SIZEOF_Long40 5
++#define SIZEOF_ULong40 5
++
++// Read-Only Data Types - should be only used for ROM code
++typedef const short Int16Rom; // 16 bit signed integer
++typedef const unsigned short UInt16Rom; // 16 bit unsigned integer
++typedef const int Int32Rom; // 32 bit signed integer
++typedef const unsigned int UInt32Rom; // 32 bit unsigned signed integer
++typedef const long Long40Rom; // 40 bit signed integer
++typedef const unsigned long ULong40Rom; // 40 bit unsigned signed integer
++
++// Size of Read-Only Data Types - in bytes
++#define SIZEOF_Int16Rom 2
++#define SIZEOF_UInt16Rom 2
++#define SIZEOF_Int32Rom 4
++#define SIZEOF_UInt32Rom 4
++#define SIZEOF_Long40Rom 5
++#define SIZEOF_ULong40Rom 5
++
++#else // 32 bits PC Host type definitions
++
++// Read-Write Data Types
++typedef short Int16; // 16 bit signed integer
++typedef unsigned short UInt16; // 16 bit unsigned integer
++typedef int Int32; // 32 bit signed integer
++typedef unsigned int UInt32; // 32 bit unsigned integer
++
++// Read-Only Data Types - should be only used for ROM code
++typedef const short Int16Rom; // 16 bit signed integer
++typedef const unsigned short UInt16Rom; // 16 bit unsigned integer
++typedef const int Int32Rom; // 32 bit signed integer
++typedef const unsigned int UInt32Rom; // 32 bit unsigned integer
++
++#endif
++
++#endif
+diff -urN linux.old/drivers/atm/sangam_atm/Makefile linux.dev/drivers/atm/sangam_atm/Makefile
+--- linux.old/drivers/atm/sangam_atm/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/Makefile 2005-08-23 04:46:50.104842632 +0200
+@@ -0,0 +1,35 @@
++# File: drivers/net/avalanche_cpmac/Makefile
++#
++# Makefile for the Linux network (CPMAC) device drivers.
++#
++
++
++O_TARGET := tiatm.o
++obj-$(CONFIG_MIPS_SANGAM_ATM) += tiatm.o
++list-multi := tiatm.o
++
++tiatm-objs := tn7atm.o tn7dsl.o tn7sar.o dsl_hal_api.o dsl_hal_support.o cpsar.o aal5sar.o
++
++EXTRA_CFLAGS += -DEL -I$(TOPDIR)/drivers/atm/sangam_atm -DPOST_SILICON -DCOMMON_NSP -DCONFIG_LED_MODULE -DDEREGISTER_LED -DNO_ACT
++
++ifeq ($(ANNEX),B)
++EXTRA_CFLAGS += -DANNEX_B -DB
++else
++ifeq ($(ANNEX),C)
++EXTRA_CFLAGS += -DANNEX_C -DC
++else
++EXTRA_CFLAGS += -DANNEX_A -DP
++endif
++endif
++
++
++include $(TOPDIR)/Rules.make
++
++tiatm.o: $(tiatm-objs)
++ $(LD) -r -o $@ $(tiatm-objs)
++
++#avalanche_cpmac.o: $(avalanche_cpmac-objs)
++# $(LD) -r -o $@ $(avalanche_cpmac-objs)
++
++clean:
++ rm -f core *.o *.a *.s
+diff -urN linux.old/drivers/atm/sangam_atm/queue.h linux.dev/drivers/atm/sangam_atm/queue.h
+--- linux.old/drivers/atm/sangam_atm/queue.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/queue.h 2005-08-23 04:46:50.104842632 +0200
+@@ -0,0 +1,167 @@
++
++#if !defined( __QUEUE_H__ )
++#define __QUEUE_H__
++
++typedef spinlock_t OS_SPIN_LOCK;
++#define osFreeSpinLock(pLock) while(0)
++void osAcquireSpinLock(OS_SPIN_LOCK *pLock);
++void osReleaseSpinLock(OS_SPIN_LOCK *pLock);
++void osAllocateSpinLock(OS_SPIN_LOCK *pLock);
++
++//#define osAcquireSpinLock(pLock) spin_lock(pLock)
++//#define osReleaseSpinLock(pLock) spin_unlock(pLock)
++//#define osAllocateSpinLock(pLock) spin_lock_init(pLock)
++
++
++typedef struct _TI_LIST_ENTRY {
++ struct _TI_LIST_ENTRY *Flink;
++ struct _TI_LIST_ENTRY *Blink;
++} TI_LIST_ENTRY, *PTI_LIST_ENTRY, TQE, *PTQE;
++
++typedef struct _TIATM_LIST_ENTRY
++{
++ TI_LIST_ENTRY Link;
++} TIATM_LIST_ENTRY, *PTIATM_LIST_ENTRY;
++
++//-------------------------------------------------------------------------
++// QueueInitList -- Macro which will initialize a queue to NULL.
++//-------------------------------------------------------------------------
++#define QueueInitList(_L) (_L)->Link.Flink = (_L)->Link.Blink = (PTI_LIST_ENTRY)0;
++
++//-------------------------------------------------------------------------
++// QueueEmpty -- Macro which checks to see if a queue is empty.
++//-------------------------------------------------------------------------
++#define QueueEmpty(_L) (QueueGetHead((_L)) == (PTIATM_LIST_ENTRY)0)
++
++//-------------------------------------------------------------------------
++// QueueGetHead -- Macro which returns the head of the queue, but does not
++// remove the head from the queue.
++//-------------------------------------------------------------------------
++#define QueueGetHead(_L) ((PTIATM_LIST_ENTRY)((_L)->Link.Flink))
++
++#define QueueGetNext(Elem) ((PTIATM_LIST_ENTRY)((Elem)->Link.Flink))
++
++//-------------------------------------------------------------------------
++// QueuePushHead -- Macro which puts an element at the head of the queue.
++//-------------------------------------------------------------------------
++#define QueuePushHead(_L,_E) \
++ if (!((_E)->Link.Flink = (_L)->Link.Flink)) \
++ { \
++ (_L)->Link.Blink = (PTI_LIST_ENTRY)(_E); \
++ } \
++(_L)->Link.Flink = (PTI_LIST_ENTRY)(_E);
++
++//-------------------------------------------------------------------------
++// QueueRemoveHead -- Macro which removes the head of the head of queue.
++//-------------------------------------------------------------------------
++#define QueueRemoveHead(_L) \
++{ \
++ PTIATM_LIST_ENTRY ListElem; \
++ if (ListElem = (PTIATM_LIST_ENTRY)(_L)->Link.Flink) \
++ { \
++ if(!((_L)->Link.Flink = ListElem->Link.Flink)) \
++ (_L)->Link.Blink = (PTI_LIST_ENTRY) 0; \
++ } \
++}
++
++//-------------------------------------------------------------------------
++// QueuePutTail -- Macro which puts an element at the tail (end) of the queue.
++//-------------------------------------------------------------------------
++#define QueuePutTail(_L,_E) \
++{ \
++ if ((_L)->Link.Blink) \
++ { \
++ ((PTIATM_LIST_ENTRY)(_L)->Link.Blink)->Link.Flink = (PTI_LIST_ENTRY)(_E); \
++ (_L)->Link.Blink = (PTI_LIST_ENTRY)(_E); \
++ } \
++ else \
++ { \
++ (_L)->Link.Flink = \
++ (_L)->Link.Blink = (PTI_LIST_ENTRY)(_E); \
++ } \
++ (_E)->Link.Flink = (PTI_LIST_ENTRY)0; \
++}
++
++//-------------------------------------------------------------------------
++// QueuePutTailWithLock -- Macro which puts an element at the tail (end) of
++// the queue, using spin lock.
++//-------------------------------------------------------------------------
++#define QueuePutTailWithLock(_L,_E, pLock) \
++{ \
++ osAcquireSpinLock(pLock); \
++ if ((_L)->Link.Blink) \
++ { \
++ ((PTIATM_LIST_ENTRY)(_L)->Link.Blink)->Link.Flink = (PTI_LIST_ENTRY)(_E); \
++ (_L)->Link.Blink = (PTI_LIST_ENTRY)(_E); \
++ } \
++ else \
++ { \
++ (_L)->Link.Flink = \
++ (_L)->Link.Blink = (PTI_LIST_ENTRY)(_E); \
++ } \
++ (_E)->Link.Flink = (PTI_LIST_ENTRY)0; \
++ osReleaseSpinLock(pLock); \
++}
++
++//-------------------------------------------------------------------------
++// QueueGetTail -- Macro which returns the tail of the queue, but does not
++// remove the tail from the queue.
++//-------------------------------------------------------------------------
++#define QueueGetTail(_L) ((PTIATM_LIST_ENTRY)((_L)->Link.Blink))
++
++//-------------------------------------------------------------------------
++// QueuePopHead -- Macro which will pop the head off of a queue (list), and
++// return it (this differs only from queueremovehead only in
++// the 1st line)
++//-------------------------------------------------------------------------
++#define QueuePopHead(_L) \
++(PTIATM_LIST_ENTRY) (_L)->Link.Flink; QueueRemoveHead(_L);
++
++#define QueueRemoveTail(_L) \
++{ \
++ PTIATM_LIST_ENTRY ListElem; \
++ ListElem = (PTIATM_LIST_ENTRY)(_L)->Link.Flink; \
++ if(ListElem == (PTIATM_LIST_ENTRY)(_L)->Link.Blink) \
++ { \
++ (_L)->Link.Flink = (_L)->Link.Blink = (PTI_LIST_ENTRY) 0; \
++ } \
++ else \
++ { \
++ while(ListElem->Link.Flink != (PTI_LIST_ENTRY)(_L)->Link.Blink) \
++ { \
++ ListElem = (PTIATM_LIST_ENTRY)ListElem->Link.Flink; \
++ } \
++ (_L)->Link.Blink = (PTI_LIST_ENTRY) ListElem; \
++ ListElem->Link.Flink = (PTI_LIST_ENTRY)0; \
++ } \
++}
++
++#define QueueRemoveItem(_L, Elem) \
++{ \
++ PTIATM_LIST_ENTRY ListElem; \
++ ListElem = (PTIATM_LIST_ENTRY)(_L)->Link.Flink; \
++ if(ListElem == Elem) \
++ { \
++ QueueRemoveHead(_L); \
++ } \
++ else \
++ { \
++ while(ListElem) \
++ { \
++ if(Elem == (PTIATM_LIST_ENTRY)ListElem->Link.Flink) \
++ { \
++ ListElem->Link.Flink = ((PTIATM_LIST_ENTRY)Elem)->Link.Flink; \
++ if(Elem == (PTIATM_LIST_ENTRY)(_L)->Link.Blink) \
++ (_L)->Link.Blink = (PTI_LIST_ENTRY) 0; \
++ break; \
++ } \
++ ListElem = (PTIATM_LIST_ENTRY)ListElem->Link.Flink; \
++ }\
++ } \
++ ((PTIATM_LIST_ENTRY)Elem)->Link.Flink = (PTI_LIST_ENTRY) 0; \
++}
++
++#define QueuePopTail(_L) \
++((PTIATM_LIST_ENTRY)((_L)->Link.Blink)); QueueRemoveTail(_L);
++
++#endif
+diff -urN linux.old/drivers/atm/sangam_atm/release.txt linux.dev/drivers/atm/sangam_atm/release.txt
+--- linux.old/drivers/atm/sangam_atm/release.txt 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/release.txt 2005-08-23 04:46:50.104842632 +0200
+@@ -0,0 +1,118 @@
++This is release notes for AR7 Linux ATM driver.
++
++version 04.02.04.00
++-------------------
++
++1. Corrected the conditional logic from logical AND to logical OR in the case
++ of check for DSL line down condition. This is to fix PPPoA crashing
++ problem when DSL line is unplugged.
++
++version 04.02.03.00
++-------------------
++1. Changed overlay page to static allocation.
++2. Added flag to stop TX during channel closing.
++3. Changed DMA memory allocation back to "GFP_ATOMIC" flag.
++
++version 04.02.02.00
++-------------------
++1. Changed DMA memory allocation from "GFP_ATOMIC" to "GFP_KERNEL" flag.
++2. Added "DoMask" setting for VBR channel setup.
++
++version 04.02.01.01
++-------------------
++1. Modified priority check scheme per SPTC request.
++
++Version 04.02.01.00
++-------------------
++1. Add check to skb->priority to place packets to either normal or priority queue.
++2. Add spin lock to increment and decrement of queued buffer number.
++
++Version 04.02.00.00
++-------------------
++Features:
++1. Add MBS and CDVT QoS support for ATM driver.
++2. Add "stop/start queue" for ToS application.
++3. Add Showtime margin retrain based on EOC message.
++4. Add EOC vendor ID customalization logic for Annex B.
++5. Supports D3 datapump.
++
++Version 04.01.00.00
++-------------------
++Re-release of 04.00.07.00 for D1.1 datapump.
++
++Version 04.00.07.00
++-------------------
++Features:
++1. Add marging retrain capability by setting following Adam2 Env.
++ setenv enable_margin_retrain 1
++ setenv margin_threshold xx, xx is in half db, i.e., 10 means 5db.
++
++Bugfixs:
++1. New PDSP firmware that fix the F5 OAM cell loopback probelm in Cisco DSLAM.
++
++Version 04.00.06.00
++-------------------
++1. ATM interrupt pacing is defauted to 2 interrupts/s.
++2. Rx Service MAX changed ftom 16 to 8.
++
++Version 04.00.05.00
++-------------------
++Features:
++1. Add Adam2 env to disable the TurboDSL by entering "setenv TurboDSL 0".
++2. Add ability to set interrupt pacing for ATM driver.
++
++Bugfixs:
++1. Fixed the RFC2684 and CLIP problems for Cisco router.
++2. Fixed LED blinking problem when DSL cable is unplugged.
++3. Fixed problem that "selected mode" is not updated.
++
++Version 04.00.04.00
++-------------------
++Features:
++1. Added feature so OAM F5 ping will not require a corresponding PVC channel to
++ be setup.
++2. Added timeout value for F5 OAM ping. The new command are "exxxpyyycdzzzt" for
++ end-to-end and "sxxxpyyycdzzzt" for segment. "zzz" is timeout value in milli-second.
++3. Added proc entry "avsar_pvc_table" to record received VPIs and VCIs. The format is
++ vpi,vci
++ seperated by new line. To search for PVCs, an application can do the following.
++ i) Send a (or several) F5 OAM cell on a VPI/VPI pairs with command
++ echo exxxpyyycd2t > /proc/sys/dev/dslmod
++ ii) Wait >2ms or poll proc entry /proc/avalanche/avsar_oam_ping until the result
++ indicates a failure. (It will be failed all the time with 2ms timeout.)
++ iii) Repeat above two steps for new VPI/VCI pairs.
++ iv) Check proc entry /proc/avalanche/avsar_pvc_table any time for PVCs that responded.
++
++Version 04.00.03.00
++-------------------
++Bug Fixs:
++1. Fixed bug that caused crash when phone cable is unplugged.
++2. Fixed LED operation for "flexible LEDs".
++
++Features:
++1. Added the proc entry "avsar_oam_ping" to signal oam ping result.
++ 0 - failed; 1 - success; 2 - in progress.
++2. Added oam ping timeout env variable. The timeout can be specified by
++ adding Adam2 env "oam_lb_timeout". The value is in millisecond.
++
++Version 04.00.02.00
++-------------------
++1. The driver uses hardware queue for Turbo DSL.
++2. Added new modem statistics listed below:
++ US and DS TX powers, atuc Vendor ID and revision, training mode selected,
++ Hybrid Selected, and etc.
++
++Version 04.00.01.00
++-------------------
++
++1. This driver release contains all the features that exists in AR5 Linux ATM
++ 3.1 driver.
++
++2. F4 OAM generation is added.
++
++3. Software queuing is used for TURBO DSL.
++
++4. Porting guide "is created. Please look into that document for detailed
++ information.
++
++
+diff -urN linux.old/drivers/atm/sangam_atm/syssw_version.h linux.dev/drivers/atm/sangam_atm/syssw_version.h
+--- linux.old/drivers/atm/sangam_atm/syssw_version.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/syssw_version.h 2005-08-23 04:46:50.105842480 +0200
+@@ -0,0 +1,94 @@
++#ifndef __SYSSW_VERSION_H__
++#define __SYSSW_VERSION_H__ 1
++
++/*******************************************************************************
++* FILE PURPOSE: DSL Driver API functions for Sangam
++*
++********************************************************************************
++* FILE NAME: dsl_hal_basicapi.c
++*
++* DESCRIPTION:
++* Contains basic DSL HAL APIs for Sangam
++*
++* (C) Copyright 2003-04, Texas Instruments, Inc.
++* History
++* Date Version Notes
++* 14May03 0.00.00 RamP Original Version Created
++* 14May03 0.00.01 RamP Initial Rev numbers inserted
++* 14May03 0.00.02 RamP Bumped version numbers for Dsl Hal
++* & dhalapp for alpha plus
++* 19May03 0.00.03 MCB Bumped dslhal version number
++* because of dependant changes
++* wrt. linux-nsp atm drivers.
++* 22May03 0.00.04 RamP Bumped dslhal & dhalapp buildnum
++* for inner/outer pair & DGASP code
++* 06Jun03 0.00.05 RamP Bumped up buildnum for LED, STM,
++* interrupt processing, statistics
++* and other pre-beta features
++* 09Jun03 0.00.06 JEB Fixed error in DHALAPP bugfix/buildnum
++* 09Jun03 0.00.07 RamP Bumped up buildnum for incremental
++* changes to apis, statistics, memory
++* fixes, parameter configurations
++* 11Jun03 0.00.08 RamP Bumped up buildnum for Co profile
++* free memory fix
++* 12Jun03 0.00.09 JEB Bumped version numbers for AR7 1.00 Beta
++* 02Jul03 0.00.10 ZT Bumped HAL version for overlay page
++* 18Jul03 0.00.11 RamP Bumped HAL version for analog diags
++* 22Jul03 0.00.12 JEB Bumped DHALAPP buildnum for analog diags
++* 31Jul03 0.00.13 RamP Bumped HAL version for engr. drop
++* 04Aug03 0.00.14 JEB Bumped HAL version buildnum for CHECKPOINT65 changes
++* Bumped LINUX version buildnum for CHECKPOINT65 changes
++* 06Aug03 0.00.15 MCB Bumped all version numbers in prep for AR7 1.0 R2 release for POTS.
++* 13Aug03 0.00.16 MCB Set rev id's for D3/R1.1 (ADSL2).
++* 21Aug03 0.00.17 JEB Bumped up build numbers for merge of code additions from D1
++* 26Sep03 0.00.18 JEB Set rev id's for another D3/R1 (ADSL2).
++* 14Oct03 0.00.19 JEB Bumped Linux minor number and reset bugfix number for release.
++* Bumped build numbers on DSLHAL and DHALAPP for this checkpoint.
++* 14Oct03 0.00.20 JEB Bumped build numbers on DSLHAL and DHALAPP for CHECKPOINT15.
++* 21Oct03 0.00.21 JEB Bumped build number on DSLHAL for CHECKPOINT16.
++* 22Oct03 0.00.22 MCB Bumped all version numbers in support of D3R1 release.
++* 27Oct03 0.00.23 JEB Bumped build numbers on DSLHAL and DHALAPP for CHECKPOINT19.
++* Updated version for DSLAGENT to be 02.01.00.01 for ACT 2.1 R0.
++* 30Oct03 0.00.24 JEB Bumped bugfix number on LINUXATM Version for next release.
++* Bumped build numbers on DSLHAL and DHALAPP
++* 31Oct03 0.00.25 MCB Bumped all version numbers in support of D3R2 release.
++* 14Nov03 0.00.26 JEB Bumped build numbers on DSLHAL and DHALAPP
++* Changed version for DSLAGENT to be 02.00.01.01 for an ACT 2.0 R0
++* 20Nov03 0.00.27 JEB Bumped build number on DSLHAL.
++* Changed version for DSLAGENT to be 02.00.02.00 for the next ACT 2.0 R2
++* 21Nov03 0.00.28 MCB Bumped all version numbers in support of D3R2 release.
++* 21Nov03 0.00.29 JEB Bumped build numbers on DSLHAL and DHALAPP for D3-R0 drop on 11/21.
++* 16Dec03 0.00.30 JEB Bumped build numbers on DSLHAL and DHALAPP for CHECKPOINT31.
++* 21Dec03 0.00.31 MCB Bumped all version numbers in support of D3R2 release.
++* 05Jan04 0.00.32 JEB Bumped build numbers on DSLHAL and Linux ATM for CHECKPOINT 34.
++* 15Jan04 0.00.33 JEB Bumped build numbers on DSLHAL and Linux ATM for CHECKPOINT 36.
++* 26Jan04 0.00.34 JEB Changed Linux ATM version number to be 04.02.03.00.
++* 27Jan04 0.00.35 MCB Bumped all version numbers in support of D3R2 release.
++*******************************************************************************/
++
++/* Dsl Hal API Version Numbers */
++#define DSLHAL_VERSION_MAJOR 03
++#define DSLHAL_VERSION_MINOR 00
++#define DSLHAL_VERSION_BUGFIX 06
++#define DSLHAL_VERSION_BUILDNUM 00
++#define DSLHAL_VERSION_TIMESTAMP 00
++
++/* dhalapp Adam2 Application Version Numbers */
++#define DHALAPP_VERSION_MAJOR 03
++#define DHALAPP_VERSION_MINOR 00
++#define DHALAPP_VERSION_BUGFIX 05
++#define DHALAPP_VERSION_BUILDNUM 00
++
++/* Linux ATM Driver Version Numbers */
++#define LINUXATM_VERSION_MAJOR 04
++#define LINUXATM_VERSION_MINOR 02
++#define LINUXATM_VERSION_BUGFIX 04
++#define LINUXATM_VERSION_BUILDNUM 00
++
++/* DSL Agent Version Numbers */
++#define DSLAGENT_VERSION_MAJOR 02
++#define DSLAGENT_VERSION_MINOR 00
++#define DSLAGENT_VERSION_BUGFIX 02
++#define DSLAGENT_VERSION_BUILDNUM 00
++
++#endif /* pairs with #ifndef __SYSSW_VERSION_H__ */
+diff -urN linux.old/drivers/atm/sangam_atm/tn7api.h linux.dev/drivers/atm/sangam_atm/tn7api.h
+--- linux.old/drivers/atm/sangam_atm/tn7api.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/tn7api.h 2005-08-23 04:46:50.105842480 +0200
+@@ -0,0 +1,54 @@
++/*
++ * Tnetd73xx ATM driver.
++ * by Zhicheng Tang, ztang@ti.com
++ * 2000 (c) Texas Instruments Inc.
++ *
++ *
++*/
++
++#ifndef __SAPI_H
++#define __SAPI_H
++
++/* tn7atm.c */
++void xdump(unsigned char *buff, int len, int debugLev);
++int tn7atm_receive(void *os_dev, int ch, unsigned int packet_size, void *os_receive_info, void *data);
++void *tn7atm_allocate_rx_skb(void *os_dev, void **os_receive_info, unsigned int size);
++void tn7atm_free_rx_skb(void *skb);
++void tn7atm_sarhal_isr_register(void *os_dev, void *hal_isr, int interrupt_num);
++int tn7atm_send_complete(void *osSendInfo);
++int tn7atm_device_connect_status(void *priv, int state);
++int tn7atm_lut_find(short vpi, int vci);
++
++/* tn7dsl.h */
++void tn7dsl_exit(void);
++int tn7dsl_init(void *priv);
++int tn7dsl_proc_stats(char* buf, char **start, off_t offset, int count,int *eof, void *data);
++int tn7dsl_proc_modem(char* buf, char **start, off_t offset, int count,int *eof, void *data);
++int tn7dsl_handle_interrupt(void);
++void dprintf( int uDbgLevel, char * szFmt, ...);
++void tn7dsl_dslmod_sysctl_register(void);
++void tn7dsl_dslmod_sysctl_unregister(void);
++int tn7dsl_get_dslhal_version(char *pVer);
++int tn7dsl_get_dsp_version(char *pVer);
++
++int os_atoi(const char *pStr);
++int os_atoh(const char *pStr);
++unsigned long os_atoul(const char *pStr);
++
++/* tn7sar.c */
++int tn7sar_activate_vc(Tn7AtmPrivate *priv, short vpi, int vci, int pcr, int scr, int mbs, int cdvt, int chan, int qos);
++int tn7sar_init(struct atm_dev *dev, Tn7AtmPrivate *priv);
++int tn7sar_register_interrupt_handle(void *os_dev, void *hal_isr, int *interrupt_num);
++void tn7sar_exit(struct atm_dev *dev, Tn7AtmPrivate *priv);
++int tn7sar_deactivate_vc(Tn7AtmPrivate *priv, int chan);
++int tn7sar_handle_interrupt(struct atm_dev *dev, Tn7AtmPrivate *priv);
++int tn7sar_send_packet(Tn7AtmPrivate *priv, int chan, void *new_skb, void *data,unsigned int len, int priority);
++void tn7sar_get_sar_version(Tn7AtmPrivate *priv, char **pVer);
++int tn7sar_get_near_end_loopback_count(unsigned int *pF4count, unsigned int *pF5count);
++int tn7sar_oam_generation(void *privContext, int chan, int type, int vpi, int vci, int timeout);
++int tn7sar_get_stats(void *priv1);
++int tn7sar_proc_sar_stat(char* buf, char **start, off_t offset, int count,int *eof, void *data);
++void tn7sar_get_sar_firmware_version(unsigned int *pdsp_version_ms, unsigned int *pdsp_version_ls);
++int tn7sar_proc_oam_ping(char* buf, char **start, off_t offset, int count,int *eof, void *data);
++int tn7sar_proc_pvc_table(char* buf, char **start, off_t offset, int count,int *eof, void *data);
++#endif
+diff -urN linux.old/drivers/atm/sangam_atm/tn7atm.c linux.dev/drivers/atm/sangam_atm/tn7atm.c
+--- linux.old/drivers/atm/sangam_atm/tn7atm.c 2005-08-28 01:52:26.000000000 -0600
++++ linux.dev/drivers/atm/sangam_atm/tn7atm.c 2005-08-28 02:08:07.000000000 -0600
+@@ -0,0 +1,1233 @@
++/*
++ * tn7.c
++ * Linux atm module implementation.
++ * Zhicheng Tang 01/08/2003
++ * 2003 (c) Texas Instruments Inc.
++ *
++ *
++*/
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/atmdev.h>
++#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 "tn7atm.h"
++#include "tn7api.h"
++#include "syssw_version.h"
++
++#ifdef CONFIG_LED_MODULE
++#include <asm/ar7/ledapp.h>
++#endif
++#include <asm/ar7/avalanche_intc.h>
++
++#ifdef MODULE
++MODULE_DESCRIPTION ("Tnetd73xx ATM Device Driver");
++MODULE_AUTHOR ("Zhicheng Tang");
++#endif
++
++/* Version Information */
++//static char atm_version[] ="1.0.0.1";
++
++#define TRUE 1
++#define FALSE 0
++
++#define STOP_EMPTY_BUFF 2
++#define START_EMPTY_BUFF 3
++/* externs */
++
++/*end of externs */
++
++#define tn7atm_kfree_skb(x) dev_kfree_skb(x)
++
++/* prototypes */
++int tn7atm_open (struct atm_vcc *vcc, short vpi, int vci);
++
++void tn7atm_close (struct atm_vcc *vcc);
++
++static int tn7atm_ioctl (struct atm_dev *dev, unsigned int cmd, void *arg);
++
++int tn7atm_send (struct atm_vcc *vcc, struct sk_buff *skb);
++
++static int tn7atm_change_qos (struct atm_vcc *vcc, struct atm_qos *qos,int flags);
++
++static int tn7atm_detect(void);
++static int tn7atm_init(struct atm_dev* dev);
++//static int tn7atm_reset(void);
++static int tn7atm_irq_request(struct atm_dev* dev);
++static int tn7atm_proc_version(char* buf, char **start, off_t offset, int count,int *eof, void *data);
++static void tn7atm_exit(void);
++static int tn7atm_proc_channels(char* buf, char **start, off_t offset, int count,int *eof, void *data);
++static int tn7atm_proc_private(char* buf, char **start, off_t offset, int count,int *eof,void *data);
++//static void tn7atm_free_packet(void *vcc1, void *priv, void *skb1);
++static int tn7atm_queue_packet_to_sar(void *vcc1, void *skb1);
++
++#include "turbodsl.c"
++
++/* ATM device operations */
++
++struct atm_dev *mydev;
++
++static const struct atmdev_ops tn7atm_ops = {
++ open: tn7atm_open,
++ close: tn7atm_close,
++ ioctl: tn7atm_ioctl,
++ getsockopt: NULL,
++ setsockopt: NULL,
++ send: tn7atm_send,
++ sg_send: NULL,
++ phy_put: NULL,
++ phy_get: NULL,
++ change_qos: tn7atm_change_qos,
++};
++
++
++int __guDbgLevel = 1;
++
++
++void xdump(unsigned char *buff, int len, int debugLev)
++{
++#ifdef DEBUG_BUILD
++ int i, j;
++ if( __guDbgLevel < debugLev)
++ return;
++
++ j=0;
++ for(i=0;i<len;i++)
++ {
++ printk("%02x ", buff[i]);
++ j++;
++ if(j==8)
++ {
++ j=0;
++ printk("\n");
++ }
++ }
++ printk("\n");
++#endif
++}
++
++
++#if 0 /* by nbd */
++/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * 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;
++
++ // printk(tn7 "tn7atm_walk_vccs\n");
++ /* 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;
++}
++#endif
++
++
++/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * Function: int tn7atm_sar_irq(void)
++ *
++ * Description: tnetd73xx SAR interrupt.
++ *
++ *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
++static void
++tn7atm_sar_irq(int irq , void *voiddev , struct pt_regs *regs)
++{
++ struct atm_dev *atmdev;
++ Tn7AtmPrivate *priv;
++
++ dprintf(6, "tn7atm_sar_irq\n");
++ atmdev = (struct atm_dev *) voiddev;
++ priv = (Tn7AtmPrivate *)atmdev->dev_data;
++
++ tn7sar_handle_interrupt(atmdev, priv);
++
++ dprintf(6, "Leaving tn7atm_sar_irq\n");
++}
++
++/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * Function: int tn7atm_dsl_irq(void)
++ *
++ * Description: tnetd73xx DSL interrupt.
++ *
++ *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
++static void
++tn7atm_dsl_irq(int irq , void *voiddev , struct pt_regs *regs)
++{
++ struct atm_dev *atmdev;
++ Tn7AtmPrivate *priv;
++
++ dprintf(4, "tn7atm_dsl_irq\n");
++ atmdev = (struct atm_dev *) voiddev;
++ priv = (Tn7AtmPrivate *)atmdev->dev_data;
++
++ tn7dsl_handle_interrupt();
++
++ dprintf(4, "Leaving tn7atm_dsl_irq\n");
++}
++
++/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * Function: int tn7atm_Inittxcomp(struct tn7* tn7)
++ *
++ * Description: Initialize Interrupt handler
++ *
++ *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
++static int __init
++tn7atm_irq_request (struct atm_dev *dev)
++{
++ Tn7AtmPrivate *priv;
++ char *ptr;
++ int ipace=2;
++
++ dprintf(4, "tn7atm_irq_request()\n");
++ priv = (Tn7AtmPrivate *) dev->dev_data;
++
++ /* 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))
++ printk ("Could not register tn7atm_sar_irq\n");
++
++ /* interrupt pacing */
++ ptr= prom_getenv("sar_ipacemax");
++ if(ptr)
++ {
++ ipace=os_atoi(ptr);
++ }
++ avalanche_request_pacing(priv->sar_irq, ATM_SAR_INT_PACING_BLOCK_NUM, ipace);
++
++ /* 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))
++ printk ("Could not register tn7atm_dsl_irq\n");
++
++ return 0;
++}
++
++/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * Function: int tn7atm_lut_find(struct atm_vcc *vcc)
++ *
++ * Description: find an TX DMA channel
++ * that matches a vpi/vci pair
++ *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
++int
++tn7atm_lut_find(short vpi, int vci)
++{
++ int i;
++ Tn7AtmPrivate *priv;
++
++ priv = (Tn7AtmPrivate *)mydev->dev_data;
++
++ if(vci==0) // find first vpi channel
++ {
++ for(i=0; i< MAX_DMA_CHAN; i++)
++ {
++ if((priv->lut[i].vpi == vpi))
++ return i;
++ }
++ }
++
++ dprintf(4, "vpi=%d, vci=%d\n", vpi, vci);
++ for(i=0; i< MAX_DMA_CHAN; i++)
++ {
++ if((priv->lut[i].vpi == vpi) && (priv->lut[i].vci == vci))
++ return i;
++ }
++
++
++
++ return ATM_NO_DMA_CHAN;
++}
++
++/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * Function: int tn7atm_lut_clear(struct atm_vcc *vcc,int chan)
++ *
++ * Description: find an TX DMA channel
++ * that matches a vpi/vci pair
++ *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
++static int
++tn7atm_lut_clear(struct atm_vcc *vcc, int chan)
++{
++ Tn7AtmPrivate *priv;
++
++ priv = (Tn7AtmPrivate *)vcc->dev->dev_data;
++
++ memset(&priv->lut[chan], 0, sizeof(priv->lut[chan]));
++
++ return 0;
++}
++
++/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * Function: int tn7atm_walk_lut(void)
++ *
++ * Description: find an available TX DMA channel
++ * and initialize LUT
++ *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
++static int
++tn7atm_walk_lut(Tn7AtmPrivate *priv)
++{
++ int i;
++
++ for(i=0; i< MAX_DMA_CHAN; i++){
++ if(!priv->lut[i].inuse)
++ {
++ return i; /* return available dma channel number */
++ }
++ }
++ return ATM_NO_DMA_CHAN; /* no tx dma channels available */
++}
++
++static int
++tn7atm_set_lut(Tn7AtmPrivate *priv, struct atm_vcc *vcc, int chan)
++{
++
++ if(!priv->lut[chan].inuse)
++ {
++ priv->lut[chan].vpi = (int)vcc->vpi;
++ priv->lut[chan].vci = vcc->vci;
++ priv->lut[chan].chanid = chan;
++ priv->lut[chan].inuse = 1; /* claim the channel */
++ priv->lut[chan].vcc = (void *)vcc;
++ priv->lut[chan].bClosing = 0;
++ priv->lut[chan].ready = 0;
++ priv->lut[chan].tx_total_bufs = TX_BUFFER_NUM;
++ priv->lut[chan].tx_used_bufs[0] = 0;
++ priv->lut[chan].tx_used_bufs[1] = 0;
++ return 0;
++ }
++ return -1; /* no tx dma channels available */
++}
++
++#if 0
++static void tn7atm_free_packet(void *pVc, void *pDev, void *pPacket)
++ {
++ Tn7AtmPrivate *priv;
++ struct atm_vcc *vcc;
++ struct sk_buff *skb;
++
++ vcc = (struct atm_vcc *)pVc;
++ priv = (Tn7AtmPrivate *)pDev;
++ skb = (struct sk_buff *) pPacket;
++
++ if(vcc->pop)
++ vcc->pop(vcc, skb);
++ else
++ tn7atm_kfree_skb(skb);
++ }
++#endif
++
++static void str2eaddr(char *pMac, char *pStr)
++{
++ char tmp[3];
++ int i;
++
++ for(i=0;i<6;i++)
++ {
++ tmp[0]=pStr[i*3];
++ tmp[1]=pStr[i*3+1];
++ tmp[2]=0;
++ pMac[i]=os_atoh(tmp);
++ }
++}
++
++static int __init
++tn7atm_get_ESI(struct atm_dev *dev)
++{
++ int i;
++ char esi_addr[ESI_LEN]={0x00,0x00,0x11,0x22,0x33,0x44};
++ char *esiaddr_str = NULL;
++
++ esiaddr_str = prom_getenv("macc");
++
++ if (!esiaddr_str) {
++ //printk("macc address not set in adam2 environment space\n");
++ //printk("Using default macc address = 00:01:02:03:04:05\n");
++ esiaddr_str = "00:00:02:03:04:05";
++ }
++ str2eaddr(esi_addr, esiaddr_str);
++
++ for(i=0; i < ESI_LEN; i++)
++ dev->esi[i] = esi_addr[i];
++
++ return 0;
++}
++
++/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * Function: int tn7atm_open(struct atm_vcc *vcc, short vpi, int vci)
++ *
++ * Description: Device operation: open
++ *
++ *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
++//static int
++int tn7atm_open (struct atm_vcc *vcc, short vpi, int vci)
++{
++ Tn7AtmPrivate *priv;
++ int dmachan;
++ int rc;
++ int traffic_type;
++ int pcr = 0x20000;
++ int scr = 0x20000;
++ int mbs = 0x20000;
++ int cdvt = 10000;
++ int err;
++
++ dprintf(1, "tn7atm_open()\n");
++
++ priv = (Tn7AtmPrivate *)vcc->dev->dev_data;
++ if(priv==NULL)
++ {
++ printk("null priv\n");
++ return -1;
++ }
++
++ MOD_INC_USE_COUNT;
++
++#if 0 /* by nbd */
++ /* find a free VPI/VCI */
++ tn7atm_walk_vccs(vcc, &vpi, &vci);
++#else
++ if ((err = atm_find_ci(vcc, &vpi, &vci))) {
++ printk("atm_find_ci err = %d\n", err);
++ return err;
++ }
++
++#endif
++
++ vcc->vpi = vpi;
++ vcc->vci = vci;
++
++ if (vci == ATM_VCI_UNSPEC || vpi == ATM_VCI_UNSPEC)
++ {
++ MOD_DEC_USE_COUNT;
++ return -EBUSY;
++ }
++
++ /* check to see whether PVC is opened or not */
++ if((dmachan = tn7atm_lut_find(vcc->vpi, vcc->vci)) != ATM_NO_DMA_CHAN)
++ {
++ MOD_DEC_USE_COUNT;
++ printk("PVC already opened. dmachan = %d\n", dmachan);
++ return -EBUSY;
++ }
++ /*check for available channel */
++ if((dmachan = tn7atm_walk_lut(priv)) == ATM_NO_DMA_CHAN)
++ {
++ printk("No TX DMA channels available\n");
++ return -EBUSY;
++ }
++
++ set_bit(ATM_VF_ADDR, &vcc->flags); /* claim address */
++
++ vcc->itf = vcc->dev->number; /* interface number */
++
++ switch(vcc->qos.txtp.traffic_class)
++ {
++ case ATM_CBR: /* Constant Bit Rate */
++ traffic_type = 0;
++ pcr = vcc->qos.txtp.pcr;
++ scr = vcc->qos.txtp.pcr;
++ cdvt = vcc->qos.txtp.max_cdv;
++ printk("cdvt=%d\n", cdvt);
++ break;
++ case ATM_UBR: /* Unspecified Bit Rate */
++ traffic_type = 2;
++ break;
++
++ /* Disable ATM_VBR until pppd ppoatm plugin supports it.
++ * NOTE: Support ATM_VBR requires the addition of a scr
++ * field to the atm_trafprm structure which will cause
++ * a change in the SO_ATMQOS ioctl. Make sure that the
++ * revised header file becomes visible to the pppd
++ * pppoatm plugin source, or the SO_ATMQOS ioctl will fail.
++ */
++#if 0
++ case ATM_VBR: /* Variable Bit Rate */
++ traffic_type = 1;
++ pcr = vcc->qos.txtp.pcr;
++ scr = vcc->qos.txtp.scr;
++ if(vcc->qos.txtp.max_pcr >= 0)
++ mbs = vcc->qos.txtp.max_pcr;
++ cdvt = vcc->qos.txtp.max_cdv;
++ printk("cdvt=%d\n", cdvt);
++ printk("mbs=%d\n", mbs);
++ break;
++#endif
++ default:
++ traffic_type = 2;
++ }
++
++ dprintf(4, "vpi=%d, vci=%d, pcr=%d, dmachan=%d, qos=%d\n", vpi,vci,pcr,dmachan,traffic_type);
++ /* Activate SAR channel */
++ rc = tn7sar_activate_vc(priv, vpi, vci, pcr, scr, mbs, cdvt, dmachan, traffic_type);
++ if(rc < 0)
++ {
++
++ MOD_DEC_USE_COUNT;
++ return -EBUSY;
++ }
++
++ /* insure that the the vcc struct points to the correct entry
++ in the lookup table */
++
++ tn7atm_set_lut(priv,vcc, dmachan);
++ vcc->dev_data = (void *)&priv->lut[dmachan];
++ set_bit(ATM_VF_READY, &vcc->flags);
++
++ mdelay(100);
++ priv->lut[dmachan].ready = 1;
++ dprintf (1, "Leave tn7atm_open\n");
++ return 0;
++}
++
++
++//static void
++void tn7atm_close (struct atm_vcc *vcc)
++{
++ Tn7AtmPrivate *priv;
++ int dmachan;
++
++ priv = (Tn7AtmPrivate *)vcc->dev->dev_data;
++ dprintf(4, "closing %d.%d.%d.%d\n", vcc->itf, vcc->vpi, vcc->vci, vcc->qos.aal);
++
++ clear_bit(ATM_VF_READY, &vcc->flags); /* ATM_VF_READY: channel is ready to transfer data */
++
++ dmachan = tn7atm_lut_find(vcc->vpi, vcc->vci);
++ printk("closing channel: %d\n", dmachan);
++ if(dmachan == ATM_NO_DMA_CHAN)
++ {
++ printk("Closing channel not found.\n");
++ return;
++ }
++ priv->lut[dmachan].bClosing = 1;
++ priv->lut[dmachan].ready = 0;
++ if(tn7sar_deactivate_vc(priv,dmachan)) /* tear down channel */
++ {
++ printk("failed to close channel %d.\n", dmachan);
++ }
++
++ clear_bit(ATM_VF_READY, &vcc->flags); /* ATM_VF_READY: channel is ready to transfer data */
++ tn7atm_lut_clear(vcc, dmachan);
++
++ MOD_DEC_USE_COUNT;
++
++ dprintf (1, "Leave tn7atm_close\n");
++}
++
++#define ATM_TXSTOP 0x800c61f4
++static int
++tn7atm_ioctl (struct atm_dev *dev, unsigned int cmd, void *arg)
++{
++ Tn7AtmPrivate *priv;
++ priv = (Tn7AtmPrivate *) dev->dev_data;
++
++ //printk("tn7atm_ioctl\n");
++ //printk("arg = %x\n", *(int *)arg);
++ //printk("cmd =%x\n", cmd);
++ switch(cmd)
++ {
++
++ case ATM_TXSTOP: /*temp fix for SAR tear down problem */
++// printk("ioctl cmd = 0x%x (%u), arg = 0x%p (%lu)\n", cmd, cmd, arg, (unsigned long)arg);
++// printk("arg = %d\n", *(int*)arg);
++ priv->xmitStop = *(int *)arg;
++ //printk("Executing ATM_SETLOOP for tn7 \n");
++ //printk("Stop variable = :%d: \n",priv->xmitStop);
++ return 0;
++
++ //case SAR_DSL_RESET_SOFTBOOT:
++ // return tn7atm_dsl_clean_reboot();
++ case 0:
++ return 0;
++ }
++
++ return -ENOSYS;
++
++}
++
++static int
++tn7atm_change_qos (struct atm_vcc *vcc, struct atm_qos *qos,int flags)
++{
++ dprintf (1, "Enter tn7atm_change_qos\n");
++ dprintf (1, "Leave tn7atm_change_qos\n");
++ return 0;
++}
++
++
++int tn7atm_send (struct atm_vcc *vcc, struct sk_buff *skb)
++{
++
++ Tn7AtmPrivate *priv;
++ int bret;
++ int chan;
++
++ dprintf(4, "tn7atm_send()\n");
++
++ priv = (Tn7AtmPrivate*)vcc->dev->dev_data;
++
++ //if(skb->len < 64)
++ //xdump((unsigned char *)skb->data, skb->len, 1);
++ //else
++ //xdump((unsigned char *)skb->data, 64, 1);
++ /* check for dsl line connection */
++
++ /* add vcc field in skb for clip inATMARP fix */
++ ATM_SKB(skb)->vcc = vcc;
++ /* Ron change 2.3 -> 2.4 ??*/
++ //if(priv->lConnected != 1 || priv->xmitStop == 1)
++ if(priv->lConnected != 1 && priv->xmitStop == 1)
++ {
++ dprintf(4,"dsl line down\n");
++ if(vcc->pop)
++ vcc->pop(vcc, skb);
++ else
++ tn7atm_kfree_skb(skb);
++ return 1;
++ }
++
++ /* check whether PVC is closing */
++ chan = tn7atm_lut_find(vcc->vpi, vcc->vci);
++ /* set br2684 dev pointer */
++ priv->lut[chan].net_device = skb->dev;
++ if(chan == ATM_NO_DMA_CHAN || priv->lut[chan].bClosing == 1)
++ {
++ dprintf(4, "can find sar channel\n");
++ if(vcc->pop)
++ vcc->pop(vcc, skb);
++ else
++ tn7atm_kfree_skb(skb);
++ return 1;
++ }
++
++ bret=tn7atm_queue_packet_to_sar(vcc, skb);
++
++ return bret;
++}
++
++
++static int tn7atm_queue_packet_to_sar(void *vcc1, void *skb1)
++{
++ struct atm_vcc *vcc;
++ struct sk_buff *skb;
++ int priority = 1;
++ Tn7AtmPrivate *priv;
++ int dmachan;
++
++ vcc = (struct atm_vcc *)vcc1;
++ skb = (struct sk_buff *)skb1;
++
++ priv = (Tn7AtmPrivate*)vcc->dev->dev_data;
++
++ dprintf(4, "vcc->vci=%d\n", vcc->vci);
++ dmachan = tn7atm_lut_find(vcc->vpi, vcc->vci);
++ if(dmachan == ATM_NO_DMA_CHAN)
++ {
++ dprintf(4, "can find sar channel\n");
++ if(vcc->pop)
++ vcc->pop(vcc, skb);
++ else
++ tn7atm_kfree_skb(skb);
++ return 1;
++ }
++
++ // turbo dsl TCP ack check
++ if(priv->bTurboDsl)
++ priority = turbodsl_check_priority_type(skb->data);
++
++ //skb priority check
++ if(priority != 0)
++ {
++ if((skb->cb[47])>>1)
++ priority=1;
++ else
++ priority = 0;
++ }
++
++ /* add queue info here */
++ skb->cb[47] = (char)priority;
++ spin_lock_irqsave(&priv->netifqueueLock, priv->netifqueueLockFlag);
++ priv->lut[dmachan].tx_used_bufs[priority]++;
++ spin_unlock_irqrestore(&priv->netifqueueLock, priv->netifqueueLockFlag);
++
++ if(tn7sar_send_packet(priv,dmachan, skb, skb->data, skb->len, priority) != 0)
++ {
++ dprintf(1, "failed to send packet\n");
++ if(vcc->pop)
++ vcc->pop(vcc, skb);
++ else
++ tn7atm_kfree_skb(skb);
++
++ spin_lock_irqsave(&priv->netifqueueLock, priv->netifqueueLockFlag);
++ priv->lut[dmachan].tx_used_bufs[priority]--;
++ spin_unlock_irqrestore(&priv->netifqueueLock, priv->netifqueueLockFlag);
++ return 1;
++ }
++
++ /* check for whether tx queue is full or not */
++ //printk("bufs used = %d\n", priv->lut[dmachan].tx_used_bufs[1]);
++ spin_lock_irqsave(&priv->netifqueueLock, priv->netifqueueLockFlag);
++ if(priv->lut[dmachan].tx_used_bufs[1] >= (priv->lut[dmachan].tx_total_bufs - STOP_EMPTY_BUFF) ||
++ priv->lut[dmachan].tx_used_bufs[0] >= (priv->lut[dmachan].tx_total_bufs - STOP_EMPTY_BUFF))
++ {
++ //printk("net queue stoped\n");
++ netif_stop_queue(priv->lut[dmachan].net_device);
++ priv->lut[dmachan].netqueue_stop = 1;
++ }
++ spin_unlock_irqrestore(&priv->netifqueueLock, priv->netifqueueLockFlag);
++
++ return 0;
++}
++
++/* functions needed by SAR HAL */
++
++int tn7atm_send_complete(void *osSendInfo)
++{
++ Tn7AtmPrivate *priv;
++ //struct atm_dev *dev;
++ struct sk_buff *skb;
++ struct atm_vcc *vcc;
++ int chan;
++
++ dprintf(4, "tn7atm_send_complete()\n");
++
++
++ skb = (struct sk_buff *)osSendInfo;
++ //dev = (struct atm_dev *) (skb->dev);
++ priv = (Tn7AtmPrivate *)mydev->dev_data;
++ vcc =ATM_SKB(skb)->vcc;
++ if(vcc)
++ {
++ dprintf(4, "vcc->vci=%d\n",vcc->vci );
++ chan = tn7atm_lut_find(vcc->vpi, vcc->vci);
++ if(chan==ATM_NO_DMA_CHAN)
++ return 1;
++
++ /*decreament packet queued number */
++ spin_lock_irqsave(&priv->netifqueueLock, priv->netifqueueLockFlag);
++ priv->lut[chan].tx_used_bufs[(int)skb->cb[47]] --;
++ if(priv->lut[chan].tx_used_bufs[1] < priv->lut[chan].tx_total_bufs - START_EMPTY_BUFF &&
++ priv->lut[chan].tx_used_bufs[0] < priv->lut[chan].tx_total_bufs - START_EMPTY_BUFF)
++ {
++ if(priv->lut[chan].netqueue_stop)
++ {
++ //printk("net queue restarted\n");
++ netif_wake_queue(priv->lut[chan].net_device);
++ priv->lut[chan].netqueue_stop = 0;
++ }
++ }
++ spin_unlock_irqrestore(&priv->netifqueueLock, priv->netifqueueLockFlag);
++
++ if(vcc->pop)
++ {
++ dprintf(5, "free packet\n");
++ vcc->pop(vcc, skb);
++ }
++
++
++ }
++
++
++
++ /* Update Stats: There may be a better place to do this, but this is a start */
++ priv->stats.tx_packets++;
++#ifdef CONFIG_LED_MODULE
++// led_operation(MOD_ADSL, DEF_ADSL_ACTIVITY);
++#endif
++
++ /* track number of buffer used */
++
++ dprintf(4, "tn7atm_send_complete() done\n");
++
++ return 0;
++}
++
++void *tn7atm_allocate_rx_skb(void *os_dev, void **os_receive_info, unsigned int size)
++{
++ struct sk_buff *skb;
++ dprintf(4, "tn7atm_allocate_rx_skb size=%d\n", size);
++ size = ((size+3)&0xfffffffc);
++ skb = dev_alloc_skb(size);
++ if(skb==NULL)
++ {
++ //printk("rx allocate skb failed\n");
++ return NULL;
++ }
++ *os_receive_info = (void *)skb;
++ return (skb->data);
++}
++
++void tn7atm_free_rx_skb(void *skb)
++{
++ dprintf(4, "tn7atm_free_rx_skb\n");
++ tn7atm_kfree_skb((struct sk_buff *)skb);
++}
++
++
++int tn7atm_receive(void *os_dev, int ch, unsigned int packet_size, void *os_receive_info, void *data)
++{
++ Tn7AtmPrivate *priv;
++ struct atm_dev *dev;
++ struct sk_buff *skb;
++ struct atm_vcc *vcc;
++
++
++ dprintf(4, "tn7atm_receive()\n");
++ dev = (struct atm_dev *)os_dev;
++
++ priv = (Tn7AtmPrivate *)dev->dev_data;
++
++ if(priv->lConnected != 1 || priv->lut[ch].ready == 0)
++ {
++ //printk("channel not ready\n");
++ return 1;
++ }
++
++ vcc = (struct atm_vcc *)priv->lut[ch].vcc;
++ if(vcc == NULL)
++ {
++ printk("vcc=Null");
++ return 1;
++ }
++
++
++ /* assume no fragment packet for now */
++ skb = (struct sk_buff *)os_receive_info;
++
++ if(skb==NULL)
++ {
++ dprintf(1, "received empty skb.\n");
++ return 1;
++ }
++ /* see skbuff->cb definition in include/linux/skbuff.h */
++ ATM_SKB(skb)->vcc = vcc;
++
++ skb->len = packet_size;
++ dprintf(3, "skb:[0x%p]:0x%x pdu_len: 0x%04x\n",skb,skb->len,packet_size);
++ dprintf(3, "data location: 0x%x, 0x%x\n", (unsigned int)skb->data, (unsigned int)data);
++
++ /*skb_trim(skb,skb->len); */ /* skb size is incorrect for large packets > 1428 bytes ?? */
++ __skb_trim(skb,skb->len); /* change to correct > 1500 ping when firewall is on */
++
++ dprintf(3, "pushing the skb...\n");
++ skb->stamp = xtime;
++
++ xdump((unsigned char *)skb->data, skb->len, 5);
++
++ if(atm_charge(vcc, skb->truesize) == 0)
++ {
++ dprintf(1,"Receive buffers saturated for %d.%d.%d - PDU dropped\n", vcc->itf, vcc->vci, vcc->vpi);
++ return 1;
++ }
++
++ /*pass it up to kernel networking layer and update stats*/
++ vcc->push(vcc,skb);
++
++ /* Update receive packet stats */
++ priv->stats.rx_packets++;
++ atomic_inc(&vcc->stats->rx);
++
++#ifdef CONFIG_LED_MODULE
++// led_operation(MOD_ADSL, DEF_ADSL_ACTIVITY);
++#endif
++ dprintf(3, "(a) Receiving:vpi/vci[%d/%d] chan_id: %d skb len:0x%x skb truesize:0x%x\n",
++ vcc->vpi,vcc->vci,ch,skb->len, skb->truesize);
++
++ return 0;
++}
++
++static int
++tn7atm_proc_channels(char* buf, char **start, off_t offset, int count,int *eof, void *data)
++{
++ int len = 0;
++ int limit = count - 80;
++ int i;
++
++ struct atm_dev *dev;
++ Tn7AtmPrivate *priv;
++
++ dev = (struct atm_dev *)data;
++ priv = (Tn7AtmPrivate *)dev->dev_data;
++
++ if(len<=limit)
++ len += sprintf(buf+len,"Chan Inuse ChanID VPI VCI \n");
++ if(len<=limit)
++ len += sprintf(buf+len,"------------------------------------------------------------------\n");
++
++ for(i=0; i < MAX_DMA_CHAN; i++)
++ {
++ if(len<=limit)
++ {
++ len += sprintf(buf+len,
++ " %02d %05d %05d %05d %05d \n",
++ i,priv->lut[i].inuse,priv->lut[i].chanid,
++ priv->lut[i].vpi,priv->lut[i].vci);
++ }
++ }
++
++ return len;
++}
++
++static int
++tn7atm_proc_private(char* buf, char **start, off_t offset, int count,int *eof, void *data)
++{
++ int len = 0;
++ int limit = count - 80;
++ struct atm_dev *dev;
++ Tn7AtmPrivate *priv;
++
++ dev = (struct atm_dev *)data;
++ priv = (Tn7AtmPrivate *)dev->dev_data;
++
++ if(len<=limit)
++ len += sprintf(buf+len, "\nPrivate Data Structure(%s):\n",priv->name);
++ if(len<=limit)
++ len += sprintf(buf+len, "----------------------------------------\n");
++ if(len<=limit)
++ len += sprintf(buf+len, "priv: 0x%p\n",priv);
++ if(len<=limit)
++ len += sprintf(buf+len, "next: 0x%p",priv->next);
++ if(len<=limit)
++ len += sprintf(buf+len, "\tdev: 0x%p\n",priv->dev);
++
++ if(len<=limit)
++ len += sprintf(buf+len, "tx_irq: %02d",priv->sar_irq);
++ if(len<=limit)
++ len += sprintf(buf+len, "rx_irq: %02d",priv->dsl_irq);
++
++
++ return len;
++}
++
++void tn7atm_sarhal_isr_register(void *os_dev, void *hal_isr, int interrupt_num)
++{
++ struct atm_dev *dev;
++ Tn7AtmPrivate *priv;
++
++ dprintf(4, "tn7atm_sarhal_isr_register()\n");
++
++ dev = (struct atm_dev *)os_dev;
++ priv = (Tn7AtmPrivate *)dev->dev_data;
++ priv->halIsr = (void *)hal_isr;
++ priv->int_num = interrupt_num;
++}
++
++
++/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * Function: int tn7atm_exit(void)
++ *
++ * Description: Avalanche SAR exit function
++ *
++ *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
++
++static void
++tn7atm_exit (void)
++{
++
++ struct atm_dev *dev;
++
++ Tn7AtmPrivate *priv;
++
++ dprintf(4, "tn7atm_exit()\n");
++
++ dev=mydev;
++ priv = (Tn7AtmPrivate *)dev->dev_data;
++ priv->lConnected = 0;
++ tn7dsl_exit();
++
++ tn7sar_exit(dev, priv);
++
++ /* freeup irq's */
++ free_irq(priv->dsl_irq,priv->dev);
++ free_irq(priv->sar_irq,priv->dev);
++
++ kfree (dev->dev_data);
++
++ // atm_dev_deregister (dev);
++ shutdown_atm_dev(dev);
++
++ /* remove proc entries */
++ remove_proc_entry("tiatm/avsar_ver",NULL);
++ remove_proc_entry("tiatm/avsar_modem_stats",NULL);
++ remove_proc_entry("tiatm/avsar_modem_training",NULL);
++ remove_proc_entry("tiatm/avsar_channels",NULL);
++ remove_proc_entry("tiatm/avsar_private",NULL);
++ remove_proc_entry("tiatm/avsar_sarhal_stats",NULL);
++ remove_proc_entry("tiatm/avsar_oam_ping",NULL);
++ remove_proc_entry("tiatm/avsar_pvc_table",NULL);
++ remove_proc_entry("tiatm",NULL);
++ tn7dsl_dslmod_sysctl_unregister();
++
++ printk ("Module Removed\n");
++
++}
++
++
++
++/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * Function: int tn7atm_registration(struct tn7* tn7)
++ *
++ * Description: ATM driver registration
++ *
++ *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
++
++static int __init
++tn7atm_register (Tn7AtmPrivate * priv)
++{
++ /* allocate memory for the device */
++
++ dprintf(4,"device %s being registered\n", priv->name);
++
++ mydev = atm_dev_register (priv->proc_name, &tn7atm_ops, -1, NULL);
++
++ if (mydev == NULL)
++ {
++ printk ("atm_dev_register returning NULL\n");
++ return ATM_REG_FAILED;
++ }
++
++ printk ("registered device %s\n", priv->name);
++
++ mydev->dev_data = priv; /* setup device data in atm_dev struct */
++ priv->dev = mydev; /* setup atm_device in avalanche sar struct */
++
++ mydev->ci_range.vpi_bits = ATM_CI_MAX; /* atm supports 11 bits */
++ mydev->ci_range.vci_bits = 16; /* atm VCI max = 16 bits */
++
++
++ return ATM_REG_OK;
++}
++
++static int
++tn7atm_proc_version(char* buf, char **start, off_t offset, int count,int *eof, void *data)
++{
++ int len = 0;
++ char dslVer[8];
++ char dspVer[10];
++ char *pSarVer;
++ Tn7AtmPrivate *priv;
++ int i;
++ unsigned int pdspV1, pdspV2;
++
++ priv = mydev->dev_data;
++
++ len += sprintf(buf+len, "ATM Driver version:[%d.%02d.%02d.%02d]\n",LINUXATM_VERSION_MAJOR, LINUXATM_VERSION_MINOR,
++ LINUXATM_VERSION_BUGFIX, LINUXATM_VERSION_BUILDNUM);
++
++ tn7dsl_get_dslhal_version(dslVer);
++
++ len += sprintf(buf+len, "DSL HAL version: [%d.%02d.%02d.%02d]\n", dslVer[0], dslVer[1], dslVer[2],
++ dslVer[3]);
++ tn7dsl_get_dsp_version(dspVer);
++
++ len += sprintf(buf+len, "DSP Datapump version: [%d.%02d.%02d.%02d] ", dspVer[4], dspVer[5], dspVer[6],
++ dspVer[7]);
++ if(dspVer[8]==2) // annex B
++ len += sprintf(buf+len, "Annex B\n");
++ else if(dspVer[8]==3) //annex c
++ len += sprintf(buf+len, "Annex c\n");
++ else
++ len += sprintf(buf+len, "Annex A\n");
++
++ tn7sar_get_sar_version(priv, &pSarVer);
++
++ len += sprintf(buf+len, "SAR HAL version: [");
++ for(i=0;i<8;i++)
++ {
++ len += sprintf(buf+len, "%c", pSarVer[i+7]);
++ }
++ len += sprintf(buf+len, "]\n");
++
++ tn7sar_get_sar_firmware_version(&pdspV1, &pdspV2);
++ len += sprintf(buf+len, "PDSP Firmware version:[%01x.%02x]\n",
++ pdspV1,pdspV2);
++
++ return len;
++}
++
++/*
++static struct net_device_stats
++*tn7atm_get_stats(struct atm_dev *dev)
++{
++ Tn7AtmPrivate *priv;
++ //unsigned long flags;
++
++ //spin_lock_irqsave(&priv->stats_lock,flags);
++ priv= (Tn7AtmPrivate *)dev->dev_data;
++ //spin_unlock_irqrestore(&priv->stats_lock,flags);
++
++ return &priv->stats;
++
++}
++*/
++/* Device detection */
++
++static int __init
++tn7atm_detect (void)
++{
++ Tn7AtmPrivate *priv;
++ //static struct proc_dir_entry *proc_dir;
++
++ dprintf(4, "tn7atm_detect().\n");
++ /* Device allocated as a global static structure at top of code "mydev" */
++
++ /* Alloc priv struct */
++ priv=kmalloc(sizeof(Tn7AtmPrivate),GFP_KERNEL);
++ if(!priv)
++ {
++ printk("unable to kmalloc priv structure. Killing autoprobe.\n");
++ return -ENODEV;
++ }
++ memset(priv, 0, sizeof(Tn7AtmPrivate));
++#ifdef COMMON_NSP
++ priv->name = "TI Avalanche SAR";
++ priv->proc_name = "avsar";
++#else
++ priv->name = "TI tnetd73xx ATM Driver";
++ priv->proc_name = "tn7";
++#endif
++
++ if ((tn7atm_register (priv)) == ATM_REG_FAILED)
++ return -ENODEV;
++
++ tn7atm_init(mydev);
++
++ /* Set up proc entry for atm stats */
++ proc_mkdir("tiatm", NULL);
++ create_proc_read_entry("tiatm/avsar_modem_stats",0,NULL,tn7dsl_proc_stats,NULL);
++ create_proc_read_entry("tiatm/avsar_modem_training",0,NULL,tn7dsl_proc_modem,NULL);
++ create_proc_read_entry("tiatm/avsar_ver",0,NULL,tn7atm_proc_version,NULL);
++ create_proc_read_entry("tiatm/avsar_channels",0,NULL,tn7atm_proc_channels,mydev);
++ create_proc_read_entry("tiatm/avsar_private",0,NULL,tn7atm_proc_private,mydev);
++ create_proc_read_entry("tiatm/avsar_sarhal_stats",0,NULL,tn7sar_proc_sar_stat,mydev);
++ create_proc_read_entry("tiatm/avsar_oam_ping",0,NULL,tn7sar_proc_oam_ping,mydev);
++ create_proc_read_entry("tiatm/avsar_pvc_table",0,NULL,tn7sar_proc_pvc_table,mydev);
++
++ tn7dsl_dslmod_sysctl_register();
++
++ printk("Texas Instruments ATM driver: version:[%d.%02d.%02d.%02d]\n",LINUXATM_VERSION_MAJOR, LINUXATM_VERSION_MINOR,
++ LINUXATM_VERSION_BUGFIX, LINUXATM_VERSION_BUILDNUM);
++ return 0;
++}
++
++
++/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * Function: int tn7atm_probe(void)
++ *
++ * Description: Avalanche SAR driver probe (see net/atm/pvc.c)
++ * this is utilized when the SAR driver is built
++ * into the kernel and needs to be configured.
++ *
++ *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
++int __init tn7atm_probe(void)
++{
++ tn7atm_detect();
++ return -ENODEV;
++}
++
++
++/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * Function: int tn7atm_init(struct atm_dev *dev)
++ *
++ * Description: Device Initialization
++ *
++ *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
++static int __init
++tn7atm_init(struct atm_dev *dev)
++{
++ Tn7AtmPrivate *priv;
++ char *ptr;
++
++ dprintf(4, "tn7atm_init()\n");
++
++ priv = (Tn7AtmPrivate *)dev->dev_data;
++
++ if(tn7sar_init(dev, priv) != 0)
++ {
++ printk("Failed to init SAR.\n");
++ return -ENODEV;
++ }
++
++ if(tn7dsl_init(priv) < 0)
++ {
++ printk("Failed to init DSL.\n");
++ return -ENODEV;
++ }
++
++ if(tn7atm_get_ESI(dev) < 0) /* set ESI */
++ return -ENODEV;
++
++ if(tn7atm_irq_request(dev) < 0)
++ return -EBUSY;
++
++ priv->bTurboDsl = 1;
++ // read config for turbo dsl
++ ptr = prom_getenv("TurboDSL");
++ if(ptr)
++ {
++ priv->bTurboDsl = os_atoi(ptr);
++ }
++
++ return 0;
++}
++
++int tn7atm_device_connect_status(void *priv, int state)
++{
++ Tn7AtmPrivate *priv1;
++
++ dprintf(5, "tn7atm_device_connect_status()\n");
++ priv1 = (Tn7AtmPrivate *)priv;
++
++ priv1->lConnected = state;
++ dprintf(5, "priv1->lConnected=%d\n", priv1->lConnected);
++ return 0;
++}
++
++
++#ifdef MODULE
++module_init (tn7atm_detect);
++module_exit (tn7atm_exit);
++#endif /* MODULE */
+diff -urN linux.old/drivers/atm/sangam_atm/tn7atm.h linux.dev/drivers/atm/sangam_atm/tn7atm.h
+--- linux.old/drivers/atm/sangam_atm/tn7atm.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/tn7atm.h 2005-08-23 04:46:50.107842176 +0200
+@@ -0,0 +1,115 @@
++/*
++ * Tnetd73xx ATM driver.
++ * by Zhicheng Tang, ztang@ti.com
++ * 2000 (c) Texas Instruments Inc.
++ *
++ *
++*/
++
++#ifndef __TN7ATM_H
++#define __TN7ATM_H
++
++//#include "mips_support.h"
++#include <linux/list.h>
++
++#define ATM_REG_OK 1
++#define ATM_REG_FAILED 0
++
++#define TX_SERVICE_MAX 32
++#define RX_SERVICE_MAX 20
++#define TX_BUFFER_NUM 64
++#define RX_BUFFER_NUM 28
++#define TX_QUEUE_NUM 2
++#define RX_BUFFER_SIZE 1582
++
++#define TX_DMA_CHAN 16 /* number of tx dma channels available */
++#define MAX_DMA_CHAN 16
++#define ATM_NO_DMA_CHAN MAX_DMA_CHAN + 1 /* no tx dma channels available */
++#define ATM_SAR_INT 15
++#define ATM_SAR_INT_PACING_BLOCK_NUM 2
++#define ATM_DSL_INT 39
++
++#define CONFIG_ATM_TN7ATM_DEBUG 0 /* Debug level (0=no mtn7s 5=verbose) */
++
++#define TN7ATM_DEV(d) ((struct tn7atm*)((d)->dev_data))
++
++
++/* Avalanche SAR state information */
++
++typedef enum tn7atm_state
++{
++ TN7ATM_STATE_REGISTER /* device registered */
++}tn7atm_state;
++
++typedef struct _sar_stat
++{
++ unsigned int txErrors;
++ unsigned int rxErrors;
++ unsigned int rxPktCnt;
++ unsigned int txPktCnt;
++ unsigned int rxBytes;
++ unsigned int txBytes;
++}sar_stat_t;
++
++/* Host based look up table to xref Channel Id's, VPI/VCI, LC, CID, packet type */
++typedef struct _tn7atm_tx_lut
++{
++ int inuse; /* is DMA channel available (1=y) */
++ int chanid; /* DMA channel ID (0-0x1f) This corresponds to the Channel ID
++ that is used in the connection config reg (TN7ATM_CONN_CONFIG) */
++ int vpi; /* Virtual path identifier */
++ int vci; /* Virtual channel identifier */
++ void *vcc;
++ int bClosing;
++ int ready;
++ void *net_device;
++ int tx_total_bufs;
++ int tx_used_bufs[2];
++ int netqueue_stop;
++}tn7atm_lut_t;
++
++/* per device data */
++
++typedef struct _tn7atm_private
++{
++ struct _tn7atm_private *next; /* next device */
++ struct atm_dev *dev; /* ATM device */
++ struct net_device_stats stats; /* Used to report Tx/Rx frames from ifconfig */
++ tn7atm_lut_t lut[MAX_DMA_CHAN]; /* Tx DMA look up table (LUT) */
++ int dsl_irq; /* ATM SAR TransmitA interrupt number */
++ int sar_irq; /* ATM SAR ReceiveA interrupt number */
++ char* name; /* device name */
++ char* proc_name; /* board name under /proc/atm */
++ unsigned int available_cell_rate; /* cell rate */
++ unsigned int connection_cell_rate; /* cell rate */
++ int lConnected;
++
++ /* Tnetd73xx CPHAL */
++ void *pSarHalDev;
++ void *pSarHalFunc;
++ void *pSarOsFunc;
++ void *halIsr;
++ int int_num;
++
++ /* turbo dsl */
++ int bTurboDsl;
++
++ /* spin lock for netifqueue */
++ spinlock_t netifqueueLock;
++ int netifqueueLockFlag;
++ int xmitStop; /* temp fix for SAR problem */
++}tn7atm_private_t, Tn7AtmPrivate;
++
++
++
++/* ATM adaptation layer id */
++typedef enum tn7atm_aal {
++ TN7ATM_AAL0 = 0,
++ TN7ATM_AAL2 = 2,
++ TN7ATM_AAL5 = 5,
++} tn7atm_aal_t;
++
++
++
++
++#endif
+diff -urN linux.old/drivers/atm/sangam_atm/tn7dsl.c linux.dev/drivers/atm/sangam_atm/tn7dsl.c
+--- linux.old/drivers/atm/sangam_atm/tn7dsl.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/tn7dsl.c 2005-08-23 04:46:50.109841872 +0200
+@@ -0,0 +1,1780 @@
++/*
++ * $Id$
++ *
++ * Avalanche SAR driver
++ *
++ * Zhicheng Tang, ztang@ti.com
++ * 2000 (c) Texas Instruments Inc.
++ *
++ *
++*/
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/atmdev.h>
++#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 <linux/sysctl.h>
++#include <linux/timer.h>
++#include <linux/vmalloc.h>
++#include <linux/file.h>
++#include <asm/uaccess.h>
++
++#include "tn7atm.h"
++#include "tn7api.h"
++#include "dsl_hal_api.h"
++
++#ifdef CONFIG_LED_MODULE
++#include <asm/ar7/ledapp.h>
++#define MOD_ADSL 1
++#define DEF_ADSL_IDLE 1
++#define DEF_ADSL_TRAINING 2
++#define DEF_ADSL_SYNC 3
++#define DEF_ADSL_ACTIVITY 4
++
++#define LED_NUM_1 3
++#define LED_NUM_2 4
++
++led_reg_t ledreg[2];
++
++static int led_on;
++#endif
++
++extern int __guDbgLevel;
++extern sar_stat_t sarStat;
++static int dslInSync = 0;
++static int bMarginThConfig;
++static int bMarginRetrainEnable;
++static char EOCVendorID[8]= {0xb5, 0x00, 0x54, 0x53, 0x54, 0x43, 0x00, 0x00};
++
++#define TC_SYNC 1
++#define SYNC_TIME_DELAY 500000
++
++
++#define DEV_DSLMOD 1
++#define MAX_STR_SIZE 256
++#define DSL_MOD_SIZE 256
++
++#define TRUE 1
++#define FALSE 0
++
++
++enum
++{
++ NO_MODE,
++ MULTI_MODE,
++ T1413_MODE,
++ GDMT_MODE,
++ GLITE_MODE
++};
++
++
++
++/* a structure to store all information we need
++ for our thread */
++typedef struct kthread_struct
++{
++ /* private data */
++
++ /* Linux task structure of thread */
++ struct task_struct *thread;
++ /* Task queue need to launch thread */
++ struct tq_struct tq;
++ /* function to be started as thread */
++ void (*function) (struct kthread_struct *kthread);
++ /* semaphore needed on start and creation of thread. */
++ struct semaphore startstop_sem;
++
++ /* public data */
++
++ /* queue thread is waiting on. Gets initialized by
++ init_kthread, can be used by thread itself.
++ */
++ wait_queue_head_t queue;
++ /* flag to tell thread whether to die or not.
++ When the thread receives a signal, it must check
++ the value of terminate and call exit_kthread and terminate
++ if set.
++ */
++ int terminate;
++ /* additional data to pass to kernel thread */
++ void *arg;
++} kthread_t;
++
++#ifndef ADIAG
++#define DSP_FIRMWARE_PATH "/lib/modules/ar0700xx.bin"
++#else
++#define DSP_FIRMWARE_PATH "/var/tmp/ar0700xx_diag.bin"
++#endif
++
++/* externs */
++extern struct atm_dev *mydev;
++extern unsigned int oamFarLBCount[4];
++extern int dslhal_support_restoreTrainingInfo(PITIDSLHW_T pIhw);
++/* gloabal functions */
++
++/* end of global functions */
++
++/* module wide declars */
++static PITIDSLHW_T pIhw;
++static char mod_req[16]={'\t'};
++static volatile int bshutdown;
++static char info[MAX_STR_SIZE];
++static DECLARE_MUTEX_LOCKED(adsl_sem_overlay); /* Used for DSL Polling enable */
++kthread_t overlay_thread;
++/* end of module wide declars */
++
++/* Internal Functions */
++static void tn7dsl_chng_modulation(void* data);
++static void tn7dsl_set_modulation(void* data);
++static int tn7dsl_reload_overlay(void);
++static int dslmod_sysctl(ctl_table *ctl, int write, struct file * filp, void *buffer, size_t *lenp);
++static void tn7dsl_register_dslss_led(void);
++void tn7dsl_dslmod_sysctl_register(void);
++void tn7dsl_dslmod_sysctl_unregister(void);
++/* end of internal functions */
++
++
++
++
++
++/* prototypes */
++
++/* start new kthread (called by creator) */
++void start_kthread(void (*func)(kthread_t *), kthread_t *kthread);
++
++/* stop a running thread (called by "killer") */
++void stop_kthread(kthread_t *kthread);
++
++/* setup thread environment (called by new thread) */
++void init_kthread(kthread_t *kthread, char *name);
++
++/* cleanup thread environment (called by thread upon receiving termination signal) */
++void exit_kthread(kthread_t *kthread);
++
++
++
++/* private functions */
++static void kthread_launcher(void *data)
++{
++ kthread_t *kthread = data;
++ kernel_thread((int (*)(void *))kthread->function, (void *)kthread, 0);
++
++}
++
++/* public functions */
++
++/* create a new kernel thread. Called by the creator. */
++void start_kthread(void (*func)(kthread_t *), kthread_t *kthread)
++{
++ /* initialize the semaphore:
++ we start with the semaphore locked. The new kernel
++ thread will setup its stuff and unlock it. This
++ control flow (the one that creates the thread) blocks
++ in the down operation below until the thread has reached
++ the up() operation.
++ */
++ //init_MUTEX_LOCKED(&kthread->startstop_sem);
++
++ /* store the function to be executed in the data passed to
++ the launcher */
++ kthread->function=func;
++
++ /* create the new thread my running a task through keventd */
++
++ /* initialize the task queue structure */
++ kthread->tq.sync = 0;
++ INIT_LIST_HEAD(&kthread->tq.list);
++ kthread->tq.routine = kthread_launcher;
++ kthread->tq.data = kthread;
++
++ /* and schedule it for execution */
++ schedule_task(&kthread->tq);
++
++ /* wait till it has reached the setup_thread routine */
++ //down(&kthread->startstop_sem);
++
++}
++
++/* stop a kernel thread. Called by the removing instance */
++void stop_kthread(kthread_t *kthread)
++{
++ if (kthread->thread == NULL)
++ {
++ printk("stop_kthread: killing non existing thread!\n");
++ return;
++ }
++
++ /* this function needs to be protected with the big
++ kernel lock (lock_kernel()). The lock must be
++ grabbed before changing the terminate
++ flag and released after the down() call. */
++ lock_kernel();
++
++ /* initialize the semaphore. We lock it here, the
++ leave_thread call of the thread to be terminated
++ will unlock it. As soon as we see the semaphore
++ unlocked, we know that the thread has exited.
++ */
++ //init_MUTEX_LOCKED(&kthread->startstop_sem);
++
++ /* We need to do a memory barrier here to be sure that
++ the flags are visible on all CPUs.
++ */
++ mb();
++
++ /* set flag to request thread termination */
++ kthread->terminate = 1;
++
++ /* We need to do a memory barrier here to be sure that
++ the flags are visible on all CPUs.
++ */
++ mb();
++ kill_proc(kthread->thread->pid, SIGKILL, 1);
++
++ /* block till thread terminated */
++ //down(&kthread->startstop_sem);
++
++ /* release the big kernel lock */
++ unlock_kernel();
++
++ /* now we are sure the thread is in zombie state. We
++ notify keventd to clean the process up.
++ */
++ kill_proc(2, SIGCHLD, 1);
++
++}
++
++/* initialize new created thread. Called by the new thread. */
++void init_kthread(kthread_t *kthread, char *name)
++{
++ /* lock the kernel. A new kernel thread starts without
++ the big kernel lock, regardless of the lock state
++ of the creator (the lock level is *not* inheritated)
++ */
++ lock_kernel();
++
++ /* fill in thread structure */
++ kthread->thread = current;
++
++ /* set signal mask to what we want to respond */
++ siginitsetinv(&current->blocked, sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM));
++
++ /* initialise wait queue */
++ init_waitqueue_head(&kthread->queue);
++
++ /* initialise termination flag */
++ kthread->terminate = 0;
++
++ /* set name of this process (max 15 chars + 0 !) */
++ sprintf(current->comm, name);
++
++ /* let others run */
++ unlock_kernel();
++
++ /* tell the creator that we are ready and let him continue */
++ //up(&kthread->startstop_sem);
++
++}
++
++/* cleanup of thread. Called by the exiting thread. */
++void exit_kthread(kthread_t *kthread)
++{
++ /* we are terminating */
++
++ /* lock the kernel, the exit will unlock it */
++ lock_kernel();
++ kthread->thread = NULL;
++ mb();
++
++ /* notify the stop_kthread() routine that we are terminating. */
++ //up(&kthread->startstop_sem);
++ /* the kernel_thread that called clone() does a do_exit here. */
++
++ /* there is no race here between execution of the "killer" and real termination
++ of the thread (race window between up and do_exit), since both the
++ thread and the "killer" function are running with the kernel lock held.
++ The kernel lock will be freed after the thread exited, so the code
++ is really not executed anymore as soon as the unload functions gets
++ the kernel lock back.
++ The init process may not have made the cleanup of the process here,
++ but the cleanup can be done safely with the module unloaded.
++ */
++
++}
++
++
++
++int os_atoi(const char *pStr)
++{
++ int retVal = -1;
++
++ if(*pStr=='-')
++ retVal = -simple_strtoul(pStr+1, (char **)NULL, 10);
++ else
++ retVal = simple_strtoul(pStr, (char **)NULL, 10);
++ return retVal ;
++}
++
++
++int os_atoh(const char *pStr)
++{
++ int retVal = -1;
++
++ if(*pStr=='-')
++ retVal = -simple_strtoul(pStr+1, (char **)NULL, 16);
++ else
++ retVal = simple_strtoul(pStr, (char **)NULL, 16);
++ return retVal ;
++}
++
++unsigned long os_atoul(const char *pStr)
++{
++ unsigned long retVal = -1;
++
++ retVal = simple_strtoul(pStr, (char **)NULL, 10);
++ return retVal ;
++}
++
++void dprintf( int uDbgLevel, char * szFmt, ...)
++{
++#ifdef DEBUG_BUILD
++ static char buff[256];
++ va_list ap;
++
++ if( __guDbgLevel < uDbgLevel)
++ return;
++
++ va_start( ap, szFmt);
++ vsprintf((char *)buff, szFmt, ap);
++ va_end(ap);
++ printk("%s", buff);
++#endif
++}
++
++/*int strcmp(const char *s1, const char *s2)
++{
++
++ int i=0;
++
++ while(s1[i] !=0)
++ {
++ if(s2[i]==0)
++ return -1;
++ if(s1[i] != s2[i])
++ return 1;
++ i++;
++ }
++ if(s2[i] != 0)
++ return 1;
++ return 0;
++}
++*/
++
++int shim_osLoadFWImage(unsigned char *ptr)
++{
++ unsigned int bytesRead;
++ mm_segment_t oldfs;
++ static struct file *filp;
++ unsigned int imageLength=0x4ffff;
++
++
++ dprintf(4, "tn7dsl_read_dsp()\n");
++
++ dprintf(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_op->read==NULL)
++ return -1; /* File(system) doesn't allow reads */
++
++ /* Now read bytes from postion "StartPos" */
++ filp->f_pos = 0;
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ bytesRead = filp->f_op->read(filp,ptr,imageLength,&filp->f_pos);
++
++ dprintf(4,"file length = %d\n", bytesRead);
++
++ set_fs(oldfs);
++
++ /* Close the file */
++ fput(filp);
++
++ return bytesRead;
++}
++
++unsigned int shim_read_overlay_page(void *ptr, unsigned int secOffset, unsigned int secLength)
++{
++ unsigned int bytesRead;
++ mm_segment_t oldfs;
++ struct file *filp;
++
++ dprintf(4,"shim_read_overlay_page\n");
++ //dprintf(4,"sec offset=%d, sec length =%d\n", secOffset, secLength);
++
++ 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;
++}
++
++int shim_osLoadDebugFWImage(unsigned char *ptr)
++{
++ return 0;
++}
++int shim_osStringCmp(const char *s1, const char *s2)
++{
++ return strcmp(s1, s2);
++}
++
++void *shim_osAllocateMemory(unsigned int size)
++{
++ return ((void *)kmalloc(size, GFP_KERNEL));
++}
++
++void *shim_osAllocateDmaMemory(unsigned int size)
++{
++ /*
++ int order;
++
++ order=1;
++ size=size/4096;
++ while(size >= 1)
++ {
++ order++;
++ size=size/2;
++ }
++
++ return ( (void *)__get_free_pages(GFP_ATOMIC, order));
++ */
++ //return ((void *)kmalloc(size, GFP_ATOMIC));
++ //return ((void *)kmalloc(size, GFP_KERNEL));
++ void *ptr;
++
++ ptr = kmalloc(size, GFP_ATOMIC);
++ if(ptr==NULL)
++ {
++ printk("failed atomic\n");
++ ptr = kmalloc(size, GFP_KERNEL);
++ if(ptr==NULL)
++ {
++ printk("failed kernel\n");
++ ptr = kmalloc(size, GFP_KERNEL|GFP_DMA);
++ }
++ }
++ printk("size=%d\n", size);
++ return ptr;
++
++}
++
++
++void shim_osFreeMemory(void *ptr, unsigned int size)
++{
++
++ kfree(ptr);
++}
++
++void shim_osFreeDmaMemory(void *ptr, unsigned int size)
++{
++/*
++ int order;
++
++ order=1;
++ size=size/4096;
++ while(size >=1)
++ {
++ order++;
++ size=size/2;
++ }
++ free_pages(ptr, order);
++*/
++ kfree(ptr);
++}
++
++void *shim_osAllocateVMemory(unsigned int size)
++{
++
++ return ((void *)vmalloc(size));
++}
++
++void shim_osFreeVMemory(void *ptr, unsigned int size)
++{
++ vfree(ptr);
++}
++
++void shim_osMoveMemory(char *dst, char *src, unsigned int numBytes)
++{
++ memcpy(dst, src, numBytes);
++}
++
++void shim_osZeroMemory(char *dst, unsigned int numBytes)
++{
++ memset(dst, 0, numBytes);
++}
++
++void shim_osWriteBackCache(void *addr, unsigned int size)
++{
++ unsigned int i,Size=(((unsigned int)addr)&0xf)+size;
++
++ for (i=0;i<Size;i+=16,addr+=16)
++ {
++ __asm__(" .set mips3 ");
++ __asm__(" cache 25, (%0)" : : "r" (addr));
++ __asm__(" .set mips0 ");
++ }
++}
++
++void shim_osInvalidateCache(void *addr, unsigned int size)
++{
++ unsigned int i,Size=(((unsigned int)addr)&0xf)+size;
++
++ for (i=0;i<Size;i+=16,addr+=16)
++ {
++ __asm__(" .set mips3 ");
++ __asm__("cache 17, (%0)" : : "r" (addr));
++ __asm__(" .set mips0 ");
++ }
++}
++
++void shim_osClockWait(int val)
++{
++ unsigned int chkvalue;
++ chkvalue=val/64;
++
++ if(chkvalue > 1000)
++ {
++ mdelay(chkvalue/1000);
++ return;
++ }
++ else
++ udelay(val/64);
++} /* end of cwait() */
++
++unsigned int shim_osClockTick(int val)
++{
++ return jiffies;
++}
++
++int flags;
++spinlock_t shimLock;
++
++void shim_osCriticalEnter(void)
++{
++ spin_lock_irqsave(&shimLock, flags);
++
++}
++
++
++void shim_osCriticalExit(void)
++{
++ spin_unlock_irqrestore(&shimLock, flags);
++}
++
++
++int tn7dsl_proc_stats(char* buf, char **start, off_t offset, int count,
++ int *eof, void *data)
++{
++
++ int len = 0;
++ int limit = count - 80;
++ int F4count, F5count;
++
++
++ /* Read Ax5 Stats */
++ dslhal_api_gatherStatistics(pIhw);
++
++ if(len<=limit)
++ len += sprintf(buf+len, "\nAR7 DSL Modem Statistics:\n");
++ if(len<=limit)
++ len += sprintf(buf+len, "--------------------------------\n");
++ /* us and ds Connection Rates */
++ if(len<=limit)
++ len += sprintf(buf+len, "[DSL Modem Stats]\n");
++
++
++ if(len<=limit)
++ {
++ if(pIhw->lConnected != 1)
++ {
++ pIhw->AppData.USConRate = 0;
++ pIhw->AppData.DSConRate = 0;
++ }
++ len += sprintf(buf+len, "\tUS Connection Rate:\t%u\tDS Connection Rate:\t%u\n",
++ (unsigned int)pIhw->AppData.USConRate,
++ (unsigned int)pIhw->AppData.DSConRate );
++ }
++ if(len<=limit)
++ len += sprintf(buf+len, "\tDS Line Attenuation:\t%u\tDS Margin:\t\t%u\n",
++ (unsigned int)pIhw->AppData.dsLineAttn/2,
++ (unsigned int)pIhw->AppData.dsMargin/2 );
++ if(len<=limit)
++ len += sprintf(buf+len, "\tUS Line Attenuation:\t%u\tUS Margin:\t\t%u\n",
++ (unsigned int)pIhw->AppData.usLineAttn,
++ (unsigned int)pIhw->AppData.usMargin );
++ if(len<=limit)
++ len += sprintf(buf+len, "\tUS Payload :\t\t%u\tDS Payload:\t\t%u\n",
++ ((unsigned int)pIhw->AppData.usAtm_count[0] + (unsigned int)pIhw->AppData.usAtm_count[1])*48,
++ ((unsigned int)pIhw->AppData.dsGood_count[0] + (unsigned int)pIhw->AppData.dsGood_count[1])*48);
++ /* Superframe Count */
++ if(len<=limit)
++ len += sprintf(buf+len, "\tUS Superframe Cnt :\t%u\tDS Superframe Cnt:\t%u\n",
++ (unsigned int)pIhw->AppData.usSuperFrmCnt,
++ (unsigned int)pIhw->AppData.dsSuperFrmCnt );
++
++ /* US and DS power */
++ if(len<=limit)
++ len += sprintf(buf+len, "\tUS Transmit Power :\t%u\tDS Transmit Power:\t%u\n",
++ (unsigned int)pIhw->AppData.usTxPower/256,
++ (unsigned int)pIhw->AppData.dsTxPower/256 );
++ /* DSL Stats Errors*/
++ if(len<=limit)
++ len += sprintf(buf+len, "\tLOS errors:\t\t%u\tSEF errors:\t\t%u\n",
++ (unsigned int)pIhw->AppData.LOS_errors,
++ (unsigned int)pIhw->AppData.SEF_errors );
++ if(len<=limit)
++ len += sprintf(buf+len, "\tFrame mode:\t\t%u\tMax Frame mode:\t\t%u\n",
++ (unsigned int)pIhw->AppData.FrmMode,
++ (unsigned int)pIhw->AppData.MaxFrmMode );
++ if(len<=limit)
++ len += sprintf(buf+len, "\tTrained Path:\t\t%u\tUS Peak Cell Rate:\t%u\n",
++ (unsigned int)pIhw->AppData.TrainedPath,
++ (unsigned int)pIhw->AppData.USConRate*1000/8/53 );
++ if(len<=limit)
++ len += sprintf(buf+len, "\tTrained Mode:\t\t%u\tSelected Mode:\t\t%u\n",
++ (unsigned int)pIhw->AppData.TrainedMode, (unsigned int)pIhw->AppData.StdMode );
++
++ if(len<=limit)
++ len += sprintf(buf+len, "\tATUC Vendor ID:\t%u\tATUC Revision:\t\t%u\n",
++ (unsigned int)pIhw->AppData.atucVendorId, pIhw->AppData.atucRevisionNum);
++ if(len<=limit)
++ len += sprintf(buf+len, "\tHybrid Selected:\t%u\n",
++ (unsigned int)pIhw->AppData.currentHybridNum);
++
++ /* Upstream Interleaved Errors */
++ if(len<=limit)
++ len += sprintf(buf+len, "\n\t[Upstream (TX) Interleave path]\n");
++ if(len<=limit)
++ len += sprintf(buf+len, "\tCRC: \t%u\tFEC: \t%u\tNCD: \t%u\n",
++ (unsigned int)pIhw->AppData.usICRC_errors,
++ (unsigned int)pIhw->AppData.usIFEC_errors,
++ (unsigned int)pIhw->AppData.usINCD_error);
++ if(len<=limit)
++ len += sprintf(buf+len, "\tLCD: \t%u\tHEC: \t%u\n",
++ (unsigned int)pIhw->AppData.usILCD_errors,
++ (unsigned int)pIhw->AppData.usIHEC_errors);
++ /* Downstream Interleaved Errors */
++ if(len<=limit)
++ len += sprintf(buf+len, "\n\t[Downstream (RX) Interleave path]\n");
++ if(len<=limit)
++ len += sprintf(buf+len, "\tCRC: \t%u\tFEC: \t%u\tNCD: \t%u\n",
++ (unsigned int)pIhw->AppData.dsICRC_errors,
++ (unsigned int)pIhw->AppData.dsIFEC_errors,
++ (unsigned int)pIhw->AppData.dsINCD_error);
++ if(len<=limit)
++ len += sprintf(buf+len, "\tLCD: \t%u\tHEC: \t%u\n",
++ (unsigned int)pIhw->AppData.dsILCD_errors,
++ (unsigned int)pIhw->AppData.dsIHEC_errors);
++ /* Upstream Fast Errors */
++ if(len<=limit)
++ len += sprintf(buf+len, "\n\t[Upstream (TX) Fast path]\n");
++ if(len<=limit)
++ len += sprintf(buf+len, "\tCRC: \t%u\tFEC: \t%u\tNCD: \t%u\n",
++ (unsigned int)pIhw->AppData.usFCRC_errors,
++ (unsigned int)pIhw->AppData.usFFEC_errors,
++ (unsigned int)pIhw->AppData.usFNCD_error);
++ if(len<=limit)
++ len += sprintf(buf+len, "\tLCD: \t%u\tHEC: \t%u\n",
++ (unsigned int)pIhw->AppData.usFLCD_errors,
++ (unsigned int)pIhw->AppData.usFHEC_errors);
++ /* Downstream Fast Errors */
++ if(len<=limit)
++ len += sprintf(buf+len, "\n\t[Downstream (RX) Fast path]\n");
++ if(len<=limit)
++ len += sprintf(buf+len, "\tCRC: \t%u\tFEC: \t%u\tNCD: \t%u\n",
++ (unsigned int)pIhw->AppData.dsFCRC_errors,
++ (unsigned int)pIhw->AppData.dsFFEC_errors,
++ (unsigned int)pIhw->AppData.dsFNCD_error);
++ if(len<=limit)
++ len += sprintf(buf+len, "\tLCD: \t%u\tHEC: \t%u\n",
++ (unsigned int)pIhw->AppData.dsFLCD_errors,
++ (unsigned int)pIhw->AppData.dsFHEC_errors);
++ /* ATM stats upstream */
++ if(len<=limit)
++ len += sprintf(buf+len, "\n[ATM Stats]");
++ if(len<=limit)
++ len += sprintf(buf+len, "\n\t[Upstream/TX]\n");
++ if(len<=limit)
++ len += sprintf(buf+len, "\tGood Cell Cnt:\t%u\n\tIdle Cell Cnt:\t%u\n\n",
++ (unsigned int)pIhw->AppData.usAtm_count[0] + (unsigned int)pIhw->AppData.usAtm_count[1],
++ (unsigned int)pIhw->AppData.usIdle_count[0] + (unsigned int)pIhw->AppData.usIdle_count[1]);
++ /* ATM stats downstream */
++ if(len<=limit)
++ len += sprintf(buf+len, "\n\t[Downstream/RX)]\n");
++ if(len<=limit)
++ len += sprintf(buf+len, "\tGood Cell Cnt:\t%u\n\tIdle Cell Cnt:\t%u\n\tBad Hec Cell Cnt:\t%u\n",
++ (unsigned int)pIhw->AppData.dsGood_count[0] + (unsigned int)pIhw->AppData.dsGood_count[1],
++ (unsigned int)pIhw->AppData.dsIdle_count[0] + (unsigned int)pIhw->AppData.dsIdle_count[1],
++ (unsigned int)pIhw->AppData.dsBadHec_count[0] + (unsigned int)pIhw->AppData.dsBadHec_count[1]);
++ if(len<=limit)
++ len += sprintf(buf+len, "\tOverflow Dropped Cell Cnt:\t%u\n",
++ (unsigned int)pIhw->AppData.dsOVFDrop_count[0] + (unsigned int)pIhw->AppData.dsOVFDrop_count[1]);
++ tn7sar_get_stats(pIhw->pOsContext);
++ if(len<=limit)
++ len += sprintf(buf+len, "\n[SAR AAL5 Stats]\n");
++ if(len<=limit)
++ len += sprintf(buf+len, "\tTx PDU's:\t%u\n\tRx PDU's:\t%u\n",
++ sarStat.txPktCnt,
++ sarStat.rxPktCnt);
++ if(len<=limit)
++ len += sprintf(buf+len, "\tTx Total Bytes:\t%u\n\tRx Total Bytes:\t%u\n",
++ sarStat.txBytes,
++ sarStat.rxBytes);
++ if(len<=limit)
++ len += sprintf(buf+len, "\tTx Total Error Counts:\t%u\n\tRx Total Error Counts:\t%u\n\n",
++ sarStat.txErrors,
++ sarStat.rxErrors);
++
++ /* oam loopback info */
++ if(len<=limit)
++ len += sprintf(buf+len, "\n[OAM Stats]\n");
++
++ tn7sar_get_near_end_loopback_count(&F4count, &F5count);
++
++ if(len<=limit)
++ {
++ len += sprintf(buf+len, "\tNear End F5 Loop Back Count:\t%u\n\tNear End F4 Loop Back Count:\t%u\n\tFar End F5 Loop Back Count:\t%u\n\tFar End F4 Loop Back Count:\t%u\n",
++ F5count,
++ F4count,
++ oamFarLBCount[0] + oamFarLBCount[2],
++ oamFarLBCount[1] + oamFarLBCount[3]);
++ }
++ return len;
++}
++
++int
++tn7dsl_proc_modem(char* buf, char **start, off_t offset, int count,
++ int *eof, void *data)
++{
++
++ int len = 0;
++ int limit = count - 80;
++
++ char *state;
++ int tag;
++
++ tag= dslhal_api_pollTrainingStatus(pIhw);
++ tag = pIhw->AppData.bState;
++
++ switch(tag){
++ case 0: state = "ACTREQ"; break;
++ case 1: state = "QUIET1"; break;
++ case 2: state = "IDLE"; break;
++ case 3: state = "INIT"; break;
++ case 4: state = "RTDL"; break;
++ case 5: state = "SHOWTIME"; break;
++ default: state = "unknown"; break;
++ }
++
++ if(pIhw->lConnected == 1)
++ state = "SHOWTIME";
++ if(len<=limit)
++ len += sprintf(buf+len,"%s\n",state);
++
++ return len;
++}
++
++
++
++int tn7dsl_handle_interrupt(void)
++{
++ int intsrc;
++ unsigned char cMsgRa[6];
++ short margin;
++
++ dprintf(4, "tn7dsl_handle_dsl_interrupt()\n");
++ if(pIhw)
++ {
++ intsrc=dslhal_api_acknowledgeInterrupt(pIhw);
++ dslhal_api_handleTrainingInterrupt(pIhw, intsrc);
++
++ if(pIhw->lConnected == TC_SYNC)
++ {
++
++ if(dslInSync == 0)
++ {
++ printk("DSL in Sync\n");
++ tn7atm_device_connect_status(pIhw->pOsContext, 1);
++ dslhal_api_initStatistics(pIhw);
++ dslhal_api_gatherStatistics(pIhw);
++#ifdef CONFIG_LED_MODULE
++// led_operation(MOD_ADSL, DEF_ADSL_SYNC);
++ led_on = DEF_ADSL_SYNC;
++#endif
++ /* add auto margin retrain */
++ if(pIhw->AppData.TrainedMode < 5)
++ {
++ if(bMarginRetrainEnable && bMarginThConfig == 0)
++ {
++ dslhal_support_getCMsgsRa(pIhw, cMsgRa);
++ margin = *(unsigned short *)&cMsgRa[4];
++ margin = (margin >> 6) & 0x3f;
++ if(margin & 0x20) // highest bit is 1
++ {
++ margin = -(margin & 0x1f);
++ }
++
++ //printk("margin = %d, cmsg-ra = %02x %02x %02x %02x %02x %02x\n", margin, cMsgRa[0],cMsgRa[1],cMsgRa[2],cMsgRa[3],cMsgRa[4],cMsgRa[5]);
++ dslhal_api_setMarginThreshold(pIhw, margin*2); /* DSL margin is in 0.5db */
++ }
++ }
++
++ }
++ dslInSync = 1;
++ }
++ else
++ {
++ if(dslInSync == 1)
++ {
++ dslInSync = 0;
++ tn7atm_device_connect_status(pIhw->pOsContext, 0);
++ up(&adsl_sem_overlay);
++ printk("DSL out of syn\n");
++ }
++#ifdef CONFIG_LED_MODULE
++ if(pIhw->AppData.bState < RSTATE_INIT)
++ {
++ if(led_on != DEF_ADSL_IDLE)
++ {
++// led_operation(MOD_ADSL, DEF_ADSL_IDLE);
++ led_on = DEF_ADSL_IDLE;
++ }
++ }
++ else
++ {
++ if(led_on != DEF_ADSL_TRAINING)
++ {
++// led_operation(MOD_ADSL, DEF_ADSL_TRAINING);
++ led_on = DEF_ADSL_TRAINING;
++ }
++
++ }
++
++#endif
++
++ }
++ }
++ return 0;
++}
++
++
++int tn7dsl_get_dslhal_version(char *pVer)
++{
++ dslVer ver;
++
++ dslhal_api_getDslHalVersion(&ver);
++
++ memcpy(pVer,&ver,8);
++ return 0;
++}
++
++int tn7dsl_get_dsp_version(char *pVer)
++{
++ dspVer ver;
++ dslhal_api_getDspVersion(pIhw, &ver);
++ memcpy(pVer, &ver, 9);
++ return 0;
++}
++
++
++static int
++tn7dsl_get_modulation(void)
++{
++ char *ptr = NULL;
++
++ dprintf(4, "tn7dsl_get_modulation\n");
++ //printk("tn7dsl_get_modulation\n");
++ ptr = prom_getenv("modulation");
++
++ if (!ptr) {
++ //printk("modulation is not set in adam2 env\n");
++ //printk("Using multimode\n");
++ return 0;
++ }
++ printk("dsl modulation = %s\n", ptr);
++
++ tn7dsl_set_modulation(ptr);
++
++ return 0;
++}
++
++
++static int tn7dsl_set_dsl(void)
++{
++
++ char *ptr = NULL;
++ int value;
++ int i, offset[2]={4,11},oamFeature=0;
++ char tmp[4];
++ char dspVer[10];
++
++ // OAM Feature Configuration
++ dslhal_api_dspInterfaceRead(pIhw,(unsigned int)pIhw->pmainAddr, 2, (unsigned int *)&offset, (unsigned char *)&oamFeature, 4);
++ oamFeature |= dslhal_support_byteSwap32(0x0000000C);
++ dslhal_api_dspInterfaceWrite(pIhw,(unsigned int)pIhw->pmainAddr, 2, (unsigned int *)&offset, (unsigned char *)&oamFeature, 4);
++
++ // modulation
++ ptr = prom_getenv("modulation");
++ if (ptr)
++ {
++ printk("dsl modulation = %s\n", ptr);
++ tn7dsl_set_modulation(ptr);
++ }
++
++ // margin retrain
++ ptr = NULL;
++ ptr = prom_getenv("enable_margin_retrain");
++ if(ptr)
++ {
++ 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");
++ 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;
++ }
++ }
++ }
++ }
++
++ // rate adapt
++ ptr = NULL;
++ ptr = prom_getenv("enable_rate_adapt");
++ if(ptr)
++ {
++ dslhal_api_setRateAdaptFlag(pIhw, os_atoi(ptr));
++ }
++
++ // trellis
++ ptr = NULL;
++ ptr = prom_getenv("enable_trellis");
++ if(ptr)
++ {
++ dslhal_api_setTrellisFlag(pIhw, os_atoi(ptr));
++ }
++
++ // maximum bits per carrier
++ ptr = NULL;
++ ptr = prom_getenv("maximum_bits_per_carrier");
++ if(ptr)
++ {
++ dslhal_api_setMaxBitsPerCarrier(pIhw, os_atoi(ptr));
++ }
++
++ // maximum interleave depth
++ ptr = NULL;
++ ptr = prom_getenv("maximum_interleave_depth");
++ if(ptr)
++ {
++ dslhal_api_setMaxInterleaverDepth(pIhw, os_atoi(ptr));
++ }
++
++ // inner and outer pairs
++ ptr = NULL;
++ ptr = prom_getenv("pair_selection");
++ if(ptr)
++ {
++ dslhal_api_selectInnerOuterPair(pIhw, os_atoi(ptr));
++ }
++
++ ptr = NULL;
++ ptr = prom_getenv("dgas_polarity");
++ if(ptr)
++ {
++ dslhal_api_configureDgaspLpr(pIhw, 1, 1);
++ dslhal_api_configureDgaspLpr(pIhw, 0, os_atoi(ptr));
++ }
++
++ ptr = NULL;
++ ptr = prom_getenv("los_alarm");
++ if(ptr)
++ {
++ dslhal_api_disableLosAlarm(pIhw, os_atoi(ptr));
++ }
++
++ ptr = NULL;
++ ptr = prom_getenv("eoc_vendor_id");
++ if(ptr)
++ {
++ for(i=0;i<8;i++)
++ {
++ tmp[0]=ptr[i*2];
++ tmp[1]=ptr[i*2+1];
++ tmp[2]=0;
++ EOCVendorID[i] = os_atoh(tmp);
++ //printk("tmp=%s--", tmp);
++ //printk("ID[%d]=0x%02x ", i, (unsigned char)EOCVendorID[i]);
++ }
++ tn7dsl_get_dsp_version(dspVer);
++ //printk("Annex =%d\n", dspVer[8]);
++ if(dspVer[8]==2) // annex b
++ {
++ //printk("EOCVendorID=%02x %02x %02x %02x %02x %02x %02x %02x\n", EOCVendorID[0], EOCVendorID[1], EOCVendorID[2], EOCVendorID[3],
++ // EOCVendorID[4], EOCVendorID[5], EOCVendorID[6], EOCVendorID[7]);
++ dslhal_api_setEocVendorId(pIhw, EOCVendorID);
++ }
++
++ }
++
++ return 0;
++}
++
++
++
++
++
++/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * Function: static void tn7dsl_init(void)
++ *
++ * Description: This function initializes
++ * Ar7 DSL interface
++ *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
++
++int tn7dsl_init(void *priv)
++{
++
++ printk("Initializing DSL interface\n");
++
++
++ /* start dsl */
++ if(dslhal_api_dslStartup(&pIhw) !=0 )
++ {
++ printk("DSL start failed.\n");
++ return -1;
++ }
++
++ // set dsl into overlay page reload mode
++ pIhw->bAutoRetrain = 1;
++
++ // set default training properties
++ tn7dsl_set_dsl();
++
++ pIhw->pOsContext = priv;
++
++ //start_kthread(tn7dsl_reload_overlay, &overlay_thread);
++
++ /*register dslss LED with led module */
++#ifdef CONFIG_LED_MODULE
++ tn7dsl_register_dslss_led();
++#endif
++
++
++ return 0; /* What do we return here? */
++}
++
++/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * Function: int avsar_exit(void)
++ *
++ * Description: Avalanche SAR exit function
++ *
++ *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
++
++void tn7dsl_exit (void)
++{
++
++ bshutdown = 1;
++#ifdef CONFIG_LED_MODULE
++#ifdef DEREGISTER_LED
++ //down(&adsl_sem_overlay);
++ deregister_led_drv(LED_NUM_1);
++ deregister_led_drv(LED_NUM_2);
++#else
++// led_operation(MOD_ADSL,DEF_ADSL_IDLE);
++#endif
++#endif
++ stop_kthread(&overlay_thread);
++ dslhal_api_dslShutdown(pIhw);
++
++}
++
++
++static int tn7dsl_process_oam_string(int *type, int *pvpi, int *pvci, int *pdelay)
++{
++ int i=1;
++ int j=0;
++ int vci, vpi;
++ char tmp[16];
++ int chan;
++ int tt;
++
++ while(j<8)
++ {
++ tmp[j] = mod_req[i];
++ //printk("tmp[%d]=%c, %d\n", j, tmp[j], tmp[j]);
++ if(tmp[j] == 0x50 || tmp[j] == 0x70)
++ break;
++ j++;
++ i++;
++ }
++
++ tmp[j] = 0;
++ vpi = os_atoi(tmp);
++
++ i++;
++ j=0;
++ while(j<8)
++ {
++ tmp[j] = mod_req[i];
++ //printk("tmp[%d]=%c, %d\n", j, tmp[j], tmp[j]);
++ if(tmp[j] == 0x43 || tmp[j] == 0x63)
++ break;
++
++ j++;
++ i++;
++ }
++
++ vci = os_atoi(tmp);
++
++ if(vci==0) // f4 oam
++ *type = 1;
++ else
++ *type = 0;
++
++
++ tt=5000;
++ i++;
++ j=0;
++ tmp[j] = mod_req[i];
++ if(tmp[j]==0x44 || tmp[j]==0x64)
++ {
++ i++;
++ while(j<8)
++ {
++ tmp[j] = mod_req[i];
++
++ //printk("tmp[%d]=%c, %d\n", j, tmp[j], tmp[j]);
++ if(tmp[j] == 0x54 || tmp[j] == 0x74)
++ break;
++
++ j++;
++ i++;
++ }
++ tt = os_atoi(tmp);
++ }
++
++ chan = tn7atm_lut_find(vpi, vci);
++
++ *pvci=vci;
++ *pvpi=vpi;
++ *pdelay =tt;
++ dprintf(2, "oam chan=%d, type =%d\n", chan, *type);
++
++ return chan;
++}
++
++static void tn7dsl_dump_memory(void)
++{
++ unsigned int *pUi;
++ int i=1;
++ int j=0;
++ int addr, len;
++ char tmp[16];
++
++
++ while(j<8)
++ {
++ tmp[j] = mod_req[i];
++ j++;
++ i++;
++ }
++
++ tmp[j] = 0;
++
++ addr = os_atoh(tmp);
++
++ printk("start dump address =0x%x\n", addr);
++ pUi = (unsigned int *)addr;
++ i++;
++ j=0;
++ while(j<8)
++ {
++ tmp[j] = mod_req[i];
++ //printk("tmp[%d]=%c, %d\n", j, tmp[j], tmp[j]);
++ if(tmp[j] == 0x43 || tmp[j] == 0x63)
++ break;
++
++ j++;
++ i++;
++ }
++
++ len = os_atoi(tmp);
++ j=0;
++ for(i=0; i<len; i++)
++ {
++ if(j==0)
++ printk("0x%08x: ", (unsigned int)pUi);
++ printk("%08x ", *pUi);
++ pUi++;
++ j++;
++ if(j==4)
++ {
++ printk("\n");
++ j=0;
++ }
++ }
++
++}
++
++
++
++static int dslmod_sysctl(ctl_table *ctl, int write, struct file * filp,
++ void *buffer, size_t *lenp)
++{
++ char *ptr;
++ int ret, len = 0;
++ int chan;
++ int type;
++ int vpi,vci,timeout;
++
++ if (!*lenp || (filp->f_pos && !write)) {
++ *lenp = 0;
++ return 0;
++ }
++ /* DSL MODULATION is changed */
++ if(write)
++ {
++ ret = proc_dostring(ctl, write, filp, buffer, lenp);
++
++ switch (ctl->ctl_name)
++ {
++ case DEV_DSLMOD:
++ ptr = strpbrk(info, " \t");
++ strcpy(mod_req, info);
++
++ /* parse the string to determine the action */
++ if(mod_req[0] == 0x45 || mod_req[0] == 0x65 ) // 'e', or 'E' f5 end to end
++ {
++ chan = tn7dsl_process_oam_string(&type, &vpi, &vci, &timeout);
++ tn7sar_oam_generation(pIhw->pOsContext, chan, type, vpi, vci, timeout);
++ }
++ else if(mod_req[0] == 0x53 || mod_req[0] == 0x73 ) // 's', or 'S' f5 seg to seg
++ {
++ chan=tn7dsl_process_oam_string(&type, &vpi, &vci,&timeout);
++ type = type | (1<<1);
++ tn7sar_oam_generation(pIhw->pOsContext, chan, type, vpi, vci,timeout);
++ }
++ //debug only. Dump memory
++ else if(mod_req[0] == 0x44 || mod_req[0] == 0x64 ) // 'd' or 'D'
++ tn7dsl_dump_memory();
++ else
++ tn7dsl_chng_modulation(info);
++ break;
++ }
++ }
++ else
++ {
++ len += sprintf(info+len, mod_req);
++ ret = proc_dostring(ctl, write, filp, buffer, lenp);
++ }
++ return ret;
++}
++
++
++ctl_table dslmod_table[] = {
++ {DEV_DSLMOD, "dslmod", info, DSL_MOD_SIZE, 0644, NULL, &dslmod_sysctl},
++ {0}
++ };
++
++/* Make sure that /proc/sys/dev is there */
++ctl_table dslmod_root_table[] = {
++#ifdef CONFIG_PROC_FS
++ {CTL_DEV, "dev", NULL, 0, 0555, dslmod_table},
++#endif /* CONFIG_PROC_FS */
++ {0}
++ };
++
++static struct ctl_table_header *dslmod_sysctl_header;
++
++void tn7dsl_dslmod_sysctl_register(void)
++{
++ static int initialized;
++
++ if (initialized == 1)
++ return;
++
++ dslmod_sysctl_header = register_sysctl_table(dslmod_root_table, 1);
++ dslmod_root_table->child->de->owner = THIS_MODULE;
++
++ /* set the defaults */
++ info[0] = 0;
++
++ initialized = 1;
++}
++
++void tn7dsl_dslmod_sysctl_unregister(void)
++{
++ unregister_sysctl_table(dslmod_sysctl_header);
++}
++
++static void
++tn7dsl_set_modulation(void* data)
++{
++ dprintf(4,"tn7dsl_set_modulation\n");
++
++ if(!strcmp(data, "T1413"))
++ {
++ printk("retraining in T1413 mode\n");
++ dslhal_api_setTrainingMode(pIhw, T1413_MODE);
++ return;
++ }
++ if(!strcmp(data, "GDMT"))
++ {
++ dslhal_api_setTrainingMode(pIhw, GDMT_MODE);
++ return;
++ }
++ if(!strcmp(data, "GLITE"))
++ {
++ dslhal_api_setTrainingMode(pIhw, GLITE_MODE);
++ return;
++ }
++ if(!strcmp(data, "MMODE"))
++ {
++ dslhal_api_setTrainingMode(pIhw, MULTI_MODE);
++ return;
++ }
++ if(!strcmp(data, "NMODE"))
++ {
++ dslhal_api_setTrainingMode(pIhw, NO_MODE);
++ return;
++ }
++
++ return;
++}
++
++
++/* Codes added for compiling tiadiag.o for Analog Diagnostic tests */
++#ifdef ADIAG
++
++enum
++{
++ HOST_ACTREQ, // Send R-ACKREQ and monitor for C-ACKx
++ HOST_QUIET, // Sit quietly doing nothing for about 60 seconds, DEFAULT STATE; R_IDLE
++ HOST_XMITBITSWAP, // Perform upstream bitswap - FOR INTERNAL USE ONLY
++ HOST_RCVBITSWAP, // Perform downstream bitswap - FOR INTERNAL USE ONLY
++ HOST_RTDLPKT, // Send a remote download packet - FOR INTERNAL USE ONLY
++ HOST_CHANGELED, // Read the LED settings and change accordingly
++ HOST_IDLE, // Sit quiet
++ HOST_REVERBTEST, // Generate REVERB for manufacturing test
++ HOST_CAGCTEST, // Set coarse receive gain for manufacturing test
++ HOST_DGASP, // send Dying Gasp messages through EOC channel
++ HOST_GHSREQ, // G.hs - FOR INTERNAL USE ONLY
++ HOST_GHSMSG, // G.hs - FOR INTERNAL USE ONLY
++ HOST_GHS_SENDGALF, // G.hs - FOR INTERNAL USE ONLY
++ HOST_GHSEXIT, // G.hs - FOR INTERNAL USE ONLY
++ HOST_GHSMSG1, // G.hs - FOR INTERNAL USE ONLY
++ HOST_HYBRID, // Enable/Disable automatic hybrid switch
++ HOST_RJ11SELECT, // RJ11 inner/outer pair select
++ HOST_DIGITAL_MEM, // Digital Diags: run external memory tests
++ HOST_TXREVERB, // AFE Diags: TX path Reverb
++ HOST_TXMEDLEY, // AFE Diags: TX path Medley
++ HOST_RXNOISEPOWER, // AFE Diags: RX noise power
++ HOST_ECPOWER, // AFE Diags: RX eco power
++ HOST_ALL_ADIAG, // AFE Diags: all major analog diagnostic modes. Host is responsible to initiate each diagnostic sessions
++ HOST_USER_ADIAG, // AFE Diags: Host fills in analog diagnostic input data structure as specified and requests DSP to perform measurements as specified
++ HOST_QUIT_ADIAG, // AFE Diags: Host requests DSP to quit current diagnostic session. This is used for stopping the transmit REVERB/MEDLEY
++ HOST_NO_CMD, // All others - G.hs - FOR INTERNAL USE ONLY
++ HOST_DSLSS_SHUTDOWN, // Host initiated DSLSS shutdown message
++ HOST_SET_GENERIC, // Set generic CO profile
++ HOST_UNDO_GENERIC // Set profile previous to Generic
++};
++
++enum
++{
++ DSP_IDLE, // R_IDLE state entered
++ DSP_ACTMON, // R_ACTMON state entered
++ DSP_TRAIN, // R_TRAIN state entered
++ DSP_ACTIVE, // R_ACTIVE state entered
++ DSP_XMITBITSWAP, // Upstream bitswap complete - FOR INTERNAL USE ONLY
++ DSP_RCVBITSWAP, // Downstream bitswap complete - FOR INTERNAL USE ONLY
++ DSP_RTDL, // R_RTDL state entered - FOR INTERNAL USE ONLY
++ DSP_RRTDLPKT, // RTDL packet received - FOR INTERNAL USE ONLY
++ DSP_XRTDLPKT, // RTDL packet transmitted - FOR INTERNAL USE ONLY
++ DSP_ERROR, // Command rejected, wrong state for this command
++ DSP_REVERBTEST, // Manufacturing REVERB test mode entered
++ DSP_CAGCTEST, // Manufacturing receive gain test done
++ DSP_OVERLAY_START, // Notify host that page overlay has started - overlay number indicated by "tag"
++ DSP_OVERLAY_END, // Notify host that page overlay has ended - overlay number indicated by "tag"
++ DSP_CRATES1, // CRATES1 message is valid and should be copied to host memory now
++ DSP_SNR, // SNR calculations are ready and should be copied to host memory now
++ DSP_GHSMSG, // G.hs - FOR INTERNAL USE ONLY
++ DSP_RCVBITSWAP_TIMEOUT, // Acknowledge Message was not received within ~500 msec (26 Superframes).
++ DSP_ATM_TC_SYNC, // Indicates true TC sync on both the upstream and downstream. Phy layer ready for data xfer.
++ DSP_ATM_NO_TC_SYNC, // Indicates loss of sync on phy layer on either US or DS.
++ DSP_HYBRID, // DSP completed hybrid switch
++ DSP_RJ11SELECT, // DSP completed RJ11 inner/outer pair select
++ DSP_INVALID_CMD, // Manufacturing (Digital and AFE) diags: CMD received not recognized
++ DSP_TEST_PASSED, // Manufacturing diags: test passed
++ DSP_TEST_FAILED, // Manufacturing diags: test failed
++ DSP_TXREVERB, // Manufacturing AFE diags: Response to HOST_TXREVERB
++ DSP_TXMEDLEY, // Manufacturing AFE diags: Response to HOST_TXMEDLEY
++ DSP_RXNOISEPOWER, // Manufacturing AFE diags: Response to HOST_RXNOISEPOWER
++ DSP_ECPOWER, // Manufacturing AFE diags: Response to HOST_ECPOWER
++ DSP_ALL_ADIAG, // Manufacturing AFE diags: Response to HOST_ALL_ADIAG
++ DSP_USER_ADIAG, // Manufacturing AFE diags: Response to HOST_USER_ADIAG
++ DSP_QUIT_ADIAG, // Manufacturing AFE diags: Response to HOST_QUIT_ADIAG
++ DSP_DGASP // DSP Message to indicate dying gasp
++};
++
++static unsigned char analogNoTonesTestArray[64]=
++ {
++ 0,0,0,0,0,0,0,0, // Tones 01-08
++ 0,0,0,0,0,0,0,0, // Tones 09-16
++ 0,0,0,0,0,0,0,0, // Tones 17-24
++ 0,0,0,0,0,0,0,0, // Tones 25-32
++ 0,0,0,0,0,0,0,0, // Tones 33-40
++ 0,0,0,0,0,0,0,0, // Tones 41-48
++ 0,0,0,0,0,0,0,0, // Tones 49-56
++ 0,0,0,0,0,0,0,0 // Tones 57-64
++ };
++
++static unsigned char analogAllTonesTestArray[64]=
++ {
++ 1,1,1,1,1,1,1,1, // Tones 01-08
++ 1,1,1,1,1,1,1,1, // Tones 09-16
++ 1,1,1,1,1,1,1,1, // Tones 17-24
++ 1,1,1,1,1,1,1,1, // Tones 25-32
++ 1,1,1,1,1,1,1,1, // Tones 33-40
++ 1,1,1,1,1,1,1,1, // Tones 41-48
++ 1,1,1,1,1,1,1,1, // Tones 49-56
++ 1,1,1,1,1,1,1,1 // Tones 57-64
++ };
++
++static unsigned char analogEvenTonesTestArray[64]=
++ {
++ 0,1,0,1,0,1,0,1, // Tones 01-08
++ 0,1,0,1,0,1,0,1, // Tones 09-16
++ 0,1,0,1,0,1,0,1, // Tones 17-24
++ 0,1,0,1,0,1,0,1, // Tones 25-32
++ 0,1,0,1,0,1,0,1, // Tones 33-40
++ 0,1,0,1,0,1,0,1, // Tones 41-48
++ 0,1,0,1,0,1,0,1, // Tones 49-56
++ 0,1,0,1,0,1,0,1 // Tones 57-64
++ };
++
++static unsigned char analogOddTonesTestArray[64]=
++ {
++ 1,0,1,0,1,0,1,0, // Tones 01-08
++ 1,0,1,0,1,0,1,0, // Tones 09-16
++ 1,0,1,0,1,0,1,0, // Tones 17-24
++ 1,0,1,0,1,0,1,0, // Tones 25-32
++ 1,0,1,0,1,0,1,0, // Tones 33-40
++ 1,0,1,0,1,0,1,0, // Tones 41-48
++ 1,0,1,0,1,0,1,0, // Tones 49-56
++ 1,0,1,0,1,0,1,0 // Tones 57-64
++ };
++
++unsigned int shim_osGetCpuFrequency(void)
++{
++ return 150;
++}
++
++static void tn7dsl_adiag(int Test, unsigned char *missingTones)
++{
++ int rc,cmd, tag;
++
++ rc = dslhal_diags_anlg_setMissingTones(pIhw,missingTones);
++ if(rc)
++ {
++ printk(" failed to set Missing town\n");
++ return;
++ }
++
++/*********** Start the actual test **********************/
++
++ if(Test==0)
++ {
++ printk("TX REVERB Test\n");
++ rc = dslhal_support_writeHostMailbox(pIhw, HOST_TXREVERB, 0, 0, 0);
++ if (rc)
++ {
++ printk("HOST_TXREVERB failed\n");
++ return;
++ }
++
++ }
++ if(Test==1)
++ {
++ dprintf(0,"TX MEDLEY Test\n");
++ rc = dslhal_support_writeHostMailbox(pIhw, HOST_TXMEDLEY, 0, 0, 0);
++ if (rc)
++ return;
++ }
++ dprintf(4,"dslhal_diags_anlg_testA() done\n");
++ return;
++}
++
++
++static void tn7dsl_diagnostic_test(char *data)
++{
++ if(!strcmp(data, "ADIAGRALL"))
++ {
++ printk("TX Reverb All tone\n");
++ tn7dsl_adiag(0,analogAllTonesTestArray);
++ return;
++ }
++ if(!strcmp(data, "ADIAGRNONE"))
++ {
++ printk("TX Reverb No tone\n");
++ tn7dsl_adiag(0,analogNoTonesTestArray);
++ return;
++ }
++ if(!strcmp(data, "ADIAGREVEN"))
++ {
++ printk("TX Reverb Even tone\n");
++ tn7dsl_adiag(0,analogEvenTonesTestArray);
++ return;
++ }
++ if(!strcmp(data, "ADIAGRODD"))
++ {
++ printk("TX Reverb Odd tone\n");
++ tn7dsl_adiag(0,analogOddTonesTestArray);
++ return;
++ }
++ if(!strcmp(data, "ADIAGMALL"))
++ {
++ printk("TX Mdelay All tone\n");
++ tn7dsl_adiag(1,analogAllTonesTestArray);
++ return;
++ }
++ if(!strcmp(data, "ADIAGMNONE"))
++ {
++ printk("TX Mdelay No tone\n");
++ tn7dsl_adiag(1,analogNoTonesTestArray);
++ return;
++ }
++ if(!strcmp(data, "ADIAGMEVEN"))
++ {
++ printk("TX Mdelay Even tone\n");
++ tn7dsl_adiag(1,analogEvenTonesTestArray);
++ return;
++ }
++ if(!strcmp(data, "ADIAGMODD"))
++ {
++ printk("TX Mdelay Odd tone\n");
++ tn7dsl_adiag(1,analogOddTonesTestArray);
++ return;
++ }
++ if(!strcmp(data, "ADIAGQUIET"))
++ {
++ dslhal_api_sendIdle(pIhw);
++ return;
++ }
++ if(!strncmp(data, "ADIAGRN", 7))
++ {
++ char tones[64], tmp[4];
++ int nth, i;
++
++ tmp[0]=data[7];
++ tmp[1]=data[8];
++ tmp[2]=data[9];
++
++ nth = os_atoi(tmp);
++
++ for(i=0;i<64;i++)
++ {
++ if(((i+1)% nth)==0)
++ {
++ tones[i]=0;
++ }
++ else
++ {
++ tones[i]=1;
++ }
++ }
++ printk("TX Reverb with %dth tones missing.\n", nth);
++ tn7dsl_adiag(0,tones);
++ return;
++ }
++ if(!strncmp(data, "ADIAGMN", 7))
++ {
++ char tones[64], tmp[4];
++ int nth, i;
++
++ tmp[0]=data[7];
++ tmp[1]=data[8];
++ tmp[2]=data[9];
++ nth = os_atoi(tmp);
++
++ for(i=0;i<64;i++)
++ {
++ if(((i+1)% nth)==0)
++ {
++ tones[i]=0;
++ }
++ else
++ {
++ tones[i]=1;
++ }
++ }
++ printk("TX Mdelay with %dth tones missing.\n", nth);
++ tn7dsl_adiag(1,tones);
++ return;
++ }
++
++
++}
++
++#endif
++
++static void
++tn7dsl_chng_modulation(void* data)
++{
++ //printk("DSL Modem Retraining\n");
++
++ if(!strcmp(data, "T1413"))
++ {
++ printk("retraining in T1413 mode\n");
++ dslhal_api_setTrainingMode(pIhw, T1413_MODE);
++ dslhal_api_sendQuiet(pIhw);
++ return;
++ }
++ if(!strcmp(data, "GDMT"))
++ {
++ dslhal_api_setTrainingMode(pIhw, GDMT_MODE);
++ dslhal_api_sendQuiet(pIhw);
++ return;
++ }
++ if(!strcmp(data, "GLITE"))
++ {
++ dslhal_api_setTrainingMode(pIhw, GLITE_MODE);
++ dslhal_api_sendQuiet(pIhw);
++ return;
++ }
++ if(!strcmp(data, "MMODE"))
++ {
++ dslhal_api_setTrainingMode(pIhw, MULTI_MODE);
++ dslhal_api_sendQuiet(pIhw);
++ return;
++ }
++ if(!strcmp(data, "NMODE"))
++ {
++ dslhal_api_setTrainingMode(pIhw, NO_MODE);
++ dslhal_api_sendQuiet(pIhw);
++ return;
++ }
++
++#ifdef ADIAG
++ tn7dsl_diagnostic_test(data);
++#endif
++
++
++ return;
++}
++
++#ifdef CONFIG_LED_MODULE
++static void tn7dsl_led_on(unsigned long parm)
++{
++ dslhal_api_configureLed(pIhw,parm, 0);
++}
++
++
++static void tn7dsl_led_off(unsigned long parm)
++{
++ dslhal_api_configureLed(pIhw,parm, 1);
++}
++
++static void tn7dsl_led_init(unsigned long parm)
++{
++ dslhal_api_configureLed(pIhw,parm, 2);
++}
++#endif
++
++static void tn7dsl_register_dslss_led(void)
++{
++#ifdef CONFIG_LED_MODULE
++
++ // register led0 with led module
++ ledreg[0].param = 0;
++ ledreg[0].init = (void *)tn7dsl_led_init;
++ ledreg[0].onfunc = (void *)tn7dsl_led_on;
++ ledreg[0].offfunc = (void *)tn7dsl_led_off;
++ register_led_drv(LED_NUM_1, &ledreg[0]);
++
++ // register led1 output with led module
++ ledreg[1].param = 1;
++ ledreg[1].init = (void *)tn7dsl_led_init;
++ ledreg[1].onfunc = (void *)tn7dsl_led_on;
++ ledreg[1].offfunc = (void *)tn7dsl_led_off;
++ register_led_drv(LED_NUM_2, &ledreg[1]);
++#endif
++}
++
++static int tn7dsl_reload_overlay(void)
++{
++ int overlayFlag;
++ spinlock_t overlayLock;
++
++ init_kthread(&overlay_thread, "adsl");
++ down(&adsl_sem_overlay);
++ while(1)
++ {
++ mdelay(500);
++ if(pIhw->lConnected == 0)
++ {
++ spin_lock_irqsave(&overlayLock, overlayFlag);
++ dslhal_support_restoreTrainingInfo(pIhw);
++ spin_unlock_irqrestore(&overlayLock, overlayFlag);
++ }
++ down(&adsl_sem_overlay);
++ }
++ return 0;
++}
++
++
++
++
+diff -urN linux.old/drivers/atm/sangam_atm/tn7sar.c linux.dev/drivers/atm/sangam_atm/tn7sar.c
+--- linux.old/drivers/atm/sangam_atm/tn7sar.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/tn7sar.c 2005-08-23 04:46:50.110841720 +0200
+@@ -0,0 +1,1376 @@
++/******************************************************************************
++ * FILE PURPOSE: OS files for CPSAR
++ ******************************************************************************
++ * FILE NAME: tn7sar.c
++ *
++ * DESCRIPTION: This file contains source for required os files for CPSAR
++ *
++ * (C) Copyright 2002, Texas Instruments Inc
++ *
++ *
++ * Revision History:
++ * 0/11/02 Zhicheng Tang, created.
++ *
++ *******************************************************************************/
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/atmdev.h>
++#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>
++
++
++#define _CPHAL_AAL5
++#define _CPHAL_SAR
++#define _CPHAL_HAL
++typedef void OS_PRIVATE;
++typedef void OS_DEVICE;
++typedef void OS_SENDINFO;
++typedef void OS_RECEIVEINFO;
++typedef void OS_SETUP;
++
++#include "cpswhal_cpsar.h"
++#include "tn7atm.h"
++#include "tn7api.h"
++
++
++/* PDSP Firmware files */
++#include "tnetd7300_sar_firm.h"
++
++
++enum
++{
++ PACKET_TYPE_AAL5,
++ PACKET_TYPE_NULL,
++ PACKET_TYPE_OAM,
++ PACKET_TYPE_TRANS,
++ PACKET_TYPE_AAL2
++}PACKET_TYPE;
++
++enum
++{
++ OAM_PING_FAILED,
++ OAM_PING_SUCCESS,
++ OAM_PING_PENDING,
++ OAM_PING_NOT_STARTED
++}OAM_PING;
++
++/* PDSP OAM General Purpose Registers (@todo: These need to be used in the HAL!) */
++
++#define SAR_PDSP_HOST_OAM_CONFIG_REG_ADDR 0xa3000020
++#define SAR_PDSP_OAM_CORR_REG_ADDR 0xa3000024
++#define SAR_PDSP_OAM_LB_RESULT_REG_ADDR 0xa3000028
++#define SAR_PDSP_OAM_F5LB_COUNT_REG_ADDR 0xa300002c
++#define SAR_PDSP_OAM_F4LB_COUNT_REG_ADDR 0xa3000030
++
++#define SAR_FREQUNCY 50000000
++
++#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 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
++
++sar_stat_t sarStat;
++
++typedef struct _channel_parm
++{
++ unsigned int RxBufSize;
++ unsigned int RxNumBuffers;
++ unsigned int RxServiceMax;
++ unsigned int TxServiceMax;
++ unsigned int TxNumBuffers;
++ unsigned int CpcsUU;
++ unsigned int TxVc_CellRate;
++ unsigned int TxVc_AtmHeader;
++}channel_parm_t;
++
++typedef struct _aal5_parm
++{
++ unsigned int base;
++ unsigned int offset;
++ unsigned int int_line;
++ channel_parm_t chan[8];
++}aal5_parm_t;
++
++
++typedef struct _sar_parm
++{
++ unsigned int base;
++ unsigned int reset_bit;
++ unsigned int offset;
++ unsigned int UniNni;
++}sar_parm_t;
++
++typedef struct _pvc_table
++{
++ int bInUse;
++ int vpi;
++ int vci;
++}pvc_table;
++
++static aal5_parm_t aal5Parm;
++static sar_parm_t sarParm;
++static char *pAal5, *pSar, *pReset;
++static int oam_type;
++static unsigned int oamPingStatus;
++static int oamAtmHdr;
++static int oamLbTimeout;
++static char parm_data[1024];
++static char aal5Data[1024];
++static char sarData[1024];
++static char resetData[256];
++static pvc_table pvc_result[MAX_PVC_TABLE_ENTRY];
++
++/* external function */
++extern int __guDbgLevel;
++
++/* gloabal function */
++unsigned int oamFarLBCount[4];
++/* end of gloabal function */
++
++/* internal APIs */
++static int tn7sar_atm_header(int vpi, int vci);
++static void tn7sar_record_pvc(int atmheader);
++
++/*end of internal APIs */
++spinlock_t sar_lock;
++
++/* HAL OS support functions */
++
++
++unsigned long tn7sar_strtoul(const char *str, char **endptr, int base)
++{
++ unsigned long ret;
++
++ ret= simple_strtoul(str, endptr, base);
++ return ret;
++}
++
++static void *tn7sar_malloc(unsigned int size)
++{
++ return(kmalloc(size, GFP_KERNEL));
++}
++
++static unsigned long lockflags;
++static void tn7sar_critical_on(void)
++{
++ spin_lock_irqsave(&sar_lock,lockflags);
++}
++
++static void tn7sar_critical_off(void)
++{
++ spin_unlock_irqrestore(&sar_lock,lockflags);
++}
++
++static void tn7sar_data_invalidate(void *pmem, int size)
++{
++ unsigned int i,Size=(((unsigned int)pmem)&0xf)+size;
++
++ for (i=0;i<Size;i+=16,pmem+=16)
++ {
++ __asm__(" .set mips3 ");
++ __asm__("cache 17, (%0)" : : "r" (pmem));
++ __asm__(" .set mips0 ");
++ }
++
++}
++
++static void tn7sar_data_writeback(void *pmem, int size)
++{
++ unsigned int i,Size=(((unsigned int)pmem)&0xf)+size;
++
++ for (i=0;i<Size;i+=16,pmem+=16)
++ {
++ __asm__(" .set mips3 ");
++ __asm__(" cache 25, (%0)" : : "r" (pmem));
++ __asm__(" .set mips0 ");
++ }
++}
++
++
++static int
++tn7sar_find_device(int unit, const char *find_name, void *device_info)
++{
++ int ret_val = 0;
++ char **ptr;
++
++ ptr = (char **)device_info;
++ dprintf(3,"tn7sar_find_device\n");
++ if(strcmp(find_name, "aal5")==0)
++ {
++ //dprintf(4,"pAal5=%s\n", pAal5);
++ *ptr = pAal5;
++ }
++ else if(strcmp(find_name, "sar")==0)
++ {
++ dprintf(3, "pSar=%s\n", pSar);
++ *ptr = pSar;
++ }
++ else if(strcmp(find_name, "reset")==0)
++ {
++ dprintf(3, "pReset=%s\n", pReset);
++ *ptr = pReset;
++ }
++
++ device_info = NULL;
++
++ return(ret_val);
++}
++
++static int
++tn7sar_get_device_parm_uint(void *dev_info, const char *param, unsigned int *value)
++{
++ char *dev_str;
++ char *pMatch;
++ int i=0, j=0;
++ char val_str[64];
++ unsigned int val;
++ int base = 10;
++
++ dprintf(6, "tn7sar_get_device_parm_uint()\n");
++
++ dev_str = (char *)dev_info;
++ dprintf(3, "parm=%s\n", param);
++ pMatch = strstr(dev_str, param);
++ //dprintf(4, "pMatch=%s\n", pMatch);
++ if(pMatch)
++ {
++ //get "=" position
++ while(pMatch[i] != 0x3d)
++ {
++ i++;
++ }
++ i++;
++ // get rid of spaces
++ while(pMatch[i]==0x20)
++ {
++ i++;
++ }
++ //get rid of 0x
++ if(pMatch[i]==0x30)
++ {
++ if(pMatch[i+1] == 0x58 || pMatch[i+1] == 0x78)
++ {
++ i+=2;
++ base = 16;
++ }
++ }
++
++ // get next delineator
++ while(pMatch[i] != 0x2c && pMatch[i] != 0x0)
++ {
++ val_str[j]=pMatch[i];
++ j++;
++ i++;
++ }
++ val_str[j]=0;
++ //dprintf(4, "val_str=\n%s\n", val_str);
++ //xdump(val_str, strlen(val_str) + 1, 4);
++ val = simple_strtoul(val_str, (char **)NULL, base);
++ dprintf(4, "val =%d\n", val);
++ *value = val;
++ return 0;
++ }
++
++
++ dprintf(3, "match not found.\n");
++ if(strcmp(dev_str, "debug")==0)
++ {
++ dprintf(6,"debug..\n");
++ *value = 6;
++ return 0;
++ }
++ return (1);
++}
++
++static int tn7sar_get_device_parm_value(void *dev_info, const char *param, void *value)
++{
++ char *dev_str;
++ char *pMatch;
++ int i=0, j=0;
++ char *pVal;
++
++
++ dprintf(3, "tn7sar_get_device_parm_value().\n");
++
++ pVal = (char *) parm_data;
++ dev_str = (char *)dev_info;
++ dprintf(3, "dev_info: \n%s\n", dev_str);
++ dprintf(3, "param=%s\n", param);
++ if(strcmp(param, "Ch0")==0)
++ {
++ *(char **)value = CH0_PARM;
++ dprintf(3, "value =%s\n", *(char **)value);
++ return 0;
++ }
++
++ pMatch = strstr(dev_str, param);
++ if(pMatch)
++ {
++ //get "=" position
++ while(pMatch[i] != 0x3d)
++ {
++ i++;
++ }
++ i++;
++ // get rid of spaces
++ while(pMatch[i]==0x20)
++ {
++ i++;
++ }
++
++ if(pMatch[i] != 0x5b) //"["
++ {
++ // get next delineator
++ while(pMatch[i] != 0x2c && pMatch[i] != 0x0)
++ {
++ pVal[j] = pMatch[i];
++ j++;
++ i++;
++ }
++ pVal[j]=0;
++
++ *(char **)value = pVal;
++ return 0;
++ }
++ else
++ {
++ i++; //skip "["
++ while(pMatch[i] != 0x5d)
++ {
++ if(pMatch[i] == 0x3b) //";"
++ pVal[j] = 0x2c;
++ else
++ pVal[j] = pMatch[i];
++ j++;
++ i++;
++ }
++ pVal[j] = 0;
++ *(char **)value = pVal;
++ return 0;
++ }
++
++ }
++
++ return (1);
++}
++
++static void tn7sar_free(void *pmem)
++{
++ kfree(pmem);
++}
++
++static void
++tn7sar_free_buffer(OS_RECEIVEINFO *os_receive_info, void *pmem)
++{
++ tn7atm_free_rx_skb(os_receive_info);
++}
++
++static void tn7sar_free_dev(void *pmem)
++{
++ kfree(pmem);
++}
++
++static void tn7sar_free_dma_xfer(void *pmem)
++{
++ kfree(pmem);
++}
++
++
++static int
++tn7sar_control(void *dev_info, const char *key, const char *action, void *value)
++{
++ int ret_val = -1;
++
++ if (strcmp(key, "Firmware") == 0)
++ {
++ if (strcmp(action, "Get") == 0)
++ {
++ *(int **)value = &SarPdspFirmware[0];
++ }
++ ret_val=0;
++ }
++
++ if (strcmp(key, "FirmwareSize") == 0)
++ {
++ if (strcmp(action, "Get") == 0)
++ {
++ *(int *)value = sizeof(SarPdspFirmware);
++ }
++ ret_val=0;
++ }
++
++ if (strcmp(key, "OamLbResult") == 0)
++ {
++ dprintf(2, "get looback source call back\n");
++ if (strcmp(action, "Set") == 0)
++ {
++ dprintf(2, "oam result = %d\n", *(unsigned int *)value);
++ oamFarLBCount[oam_type] = oamFarLBCount[oam_type] + *(unsigned int *)value;
++ if(oamPingStatus == OAM_PING_PENDING)
++ {
++ oamPingStatus = *(unsigned int *)value;
++ if(oamPingStatus == OAM_PING_SUCCESS)
++ {
++ /* record pvc */
++ tn7sar_record_pvc(oamAtmHdr);
++ }
++ }
++
++ }
++ ret_val=0;
++ }
++
++ if (strcmp(key, "SarFreq") == 0)
++ {
++ if (strcmp(action, "Get") == 0)
++ {
++ *(int *)value = SAR_FREQUNCY;
++ }
++ ret_val=0;
++ }
++ return(ret_val);
++}
++
++
++static void
++tn7sar_sarhal_isr_register(OS_DEVICE *os_dev, int(*hal_isr)(HAL_DEVICE *, int *), int interrupt_num)
++{
++ tn7atm_sarhal_isr_register(os_dev, hal_isr, interrupt_num);
++}
++
++static void
++tn7sar_isr_unregister(OS_DEVICE *os_dev, int interrupt_num)
++{
++ /* TODO */
++}
++
++
++static void *
++tn7sar_malloc_rxbuffer(unsigned int size, void *mem_base, unsigned int mem_range, HAL_DEVICE *hal_dev,
++ HAL_RECEIVEINFO *hal_info, OS_RECEIVEINFO **os_receive_info, OS_DEVICE *os_dev)
++{
++ return tn7atm_allocate_rx_skb(os_dev, os_receive_info, size);
++}
++
++static void *
++tn7sar_malloc_dev(unsigned int size)
++{
++ return(kmalloc(size, GFP_KERNEL));
++}
++
++static void *
++tn7sar_malloc_dma_xfer(unsigned int size, void *mem_base, unsigned int mem_range)
++{
++ dprintf(4, "tn7sar_malloc_dma_xfer, size =%d\n", size);
++
++ return (kmalloc(size, GFP_DMA |GFP_KERNEL));
++
++}
++
++static void *
++tn7sar_memset(void *dst, int set_char, size_t count)
++{
++ return (memset(dst, set_char, count));
++}
++
++static int tn7sar_printf(const char *format, ...)
++{
++ /* TODO: add debug levels */
++ static char buff[256];
++ va_list ap;
++
++ va_start( ap, format);
++ vsprintf((char *)buff, format, ap);
++ va_end(ap);
++
++ printk("SAR HAL: %s\n", buff);
++ return(0);
++}
++
++static void tn7sar_record_pvc(int atmheader)
++{
++ int vci,vpi;
++ int i;
++
++ vci = 0xffff & (atmheader >> 4);
++ vpi = 0xff & (atmheader >> 20);
++ for(i=0;i<MAX_PVC_TABLE_ENTRY;i++)
++ {
++ if(pvc_result[i].bInUse)
++ {
++ if(pvc_result[i].vpi == vpi && pvc_result[i].vci == vci)
++ {
++ return;
++ }
++ }
++ }
++ for(i=0;i<MAX_PVC_TABLE_ENTRY;i++)
++ {
++ if(pvc_result[i].bInUse == 0)
++ {
++ pvc_result[i].bInUse = 1;
++ pvc_result[i].vpi = vpi;
++ pvc_result[i].vci = vci;
++ return;
++ }
++ }
++ return;
++}
++
++static void tn7sar_clear_pvc_table(void)
++{
++ int i;
++
++ for(i=0;i<MAX_PVC_TABLE_ENTRY; i++)
++ {
++ pvc_result[i].bInUse = 0;
++ pvc_result[i].vpi = 0;
++ pvc_result[i].vci = 0;
++ }
++}
++
++int tn7sar_process_unmatched_oam(FRAGLIST *frag_list, unsigned int frag_count, unsigned int packet_size, unsigned int mode)
++{
++
++ FRAGLIST *local_list;
++ int i;
++ unsigned int atmHdr;
++
++ local_list = frag_list;
++
++ for(i=0;i<(int)frag_count;i++)
++ {
++ tn7sar_data_invalidate(local_list->data, (int)local_list->len);
++ local_list ++;
++ }
++ local_list = frag_list;
++ if((mode>>31)) /*vci, vpi is attached */
++ {
++ atmHdr = *(unsigned int *)frag_list->data;
++ tn7sar_record_pvc(atmHdr);
++ if(atmHdr & 0x8) //oam cell
++ {
++ atmHdr &= 0xfffffff0;
++ if(atmHdr == oamAtmHdr)
++ {
++ if(oamPingStatus == OAM_PING_PENDING)
++ {
++ oamPingStatus = OAM_PING_SUCCESS;
++ oamFarLBCount[oam_type] = oamFarLBCount[oam_type] + 1;
++ }
++ return 0;
++ }
++ }
++ }
++
++ return 0;
++}
++
++
++static int
++tn7sar_receive(OS_DEVICE *os_dev,FRAGLIST *frag_list, unsigned int frag_count, unsigned int packet_size,
++ HAL_RECEIVEINFO *hal_receive_info, unsigned int mode)
++{
++ int ch;
++ struct atm_dev *dev;
++ Tn7AtmPrivate *priv;
++ HAL_FUNCTIONS *pHalFunc;
++ HAL_DEVICE *pHalDev;
++ int bRet;
++
++
++ dprintf(4, "tn7sar_receive\n");
++
++ dev = (struct atm_dev *)os_dev;
++ priv= (Tn7AtmPrivate *)dev->dev_data;
++ pHalFunc = (HAL_FUNCTIONS *)priv->pSarHalFunc;
++ pHalDev = (HAL_DEVICE *)priv->pSarHalDev;
++
++
++ /* Mode contains channel info */
++ ch = (mode & 0xFF);
++
++ if(ch == 15)
++ {
++ tn7sar_process_unmatched_oam(frag_list, frag_count, packet_size, mode);
++ pHalFunc->RxReturn(hal_receive_info, 0);
++ return 0;
++ }
++
++ if(frag_count > 1 || frag_list->len == 0)
++ {
++ printk("Packet fragment count > 1, not handdle.\n");
++ return 1;
++ }
++
++ tn7sar_data_invalidate(frag_list->data, (int)frag_list->len);
++ bRet=tn7atm_receive(os_dev, ch, packet_size, frag_list->OsInfo, frag_list->data);
++
++ if(bRet==0)
++ {
++ sarStat.rxPktCnt++;
++ sarStat.rxBytes += packet_size;
++ pHalFunc->RxReturn(hal_receive_info, 1);
++ }
++ else
++ {
++ pHalFunc->RxReturn(hal_receive_info, 0);
++ }
++
++ return bRet;
++}
++
++static int
++tn7sar_send_complete(OS_SENDINFO *osSendInfo)
++{
++ return (tn7atm_send_complete(osSendInfo));
++}
++
++void
++tn7sar_teardown_complete(OS_DEVICE *OsDev, int ch, int Dir)
++{
++ return;
++}
++
++
++/*
++unsigned int tn7sar_virt(unsigned int address)
++{
++ return phys_to_virt(address);
++}
++*/
++
++int tn7sar_init_module(OS_FUNCTIONS *os_funcs)
++{
++ dprintf(4, "tn7sar_init_module\n");
++ if( os_funcs == 0 )
++ {
++ return(-1);
++ }
++ os_funcs->Control = tn7sar_control;
++ os_funcs->CriticalOn = tn7sar_critical_on;
++ os_funcs->CriticalOff = tn7sar_critical_off;
++ os_funcs->DataCacheHitInvalidate = tn7sar_data_invalidate;
++ os_funcs->DataCacheHitWriteback = tn7sar_data_writeback;
++ os_funcs->DeviceFindInfo = tn7sar_find_device;
++ os_funcs->DeviceFindParmUint = tn7sar_get_device_parm_uint;
++ os_funcs->DeviceFindParmValue = tn7sar_get_device_parm_value;
++ os_funcs->Free = tn7sar_free;
++ os_funcs->FreeRxBuffer = tn7sar_free_buffer;
++ os_funcs->FreeDev = tn7sar_free_dev;
++ os_funcs->FreeDmaXfer = tn7sar_free_dma_xfer;
++ os_funcs->IsrRegister = tn7sar_sarhal_isr_register;
++ os_funcs->IsrUnRegister = tn7sar_isr_unregister;
++ os_funcs->Malloc = tn7sar_malloc;
++ os_funcs->MallocRxBuffer = tn7sar_malloc_rxbuffer;
++ os_funcs->MallocDev = tn7sar_malloc_dev;
++ os_funcs->MallocDmaXfer = tn7sar_malloc_dma_xfer;
++ os_funcs->Memset = tn7sar_memset;
++ os_funcs->Printf = tn7sar_printf;
++ os_funcs->Receive = tn7sar_receive;
++ os_funcs->SendComplete = tn7sar_send_complete;
++ os_funcs->Strcmpi = strcmp;
++ os_funcs->Sprintf = sprintf;
++ os_funcs->Strlen = strlen;
++ os_funcs->Strstr = strstr;
++ os_funcs->Strtoul = tn7sar_strtoul;
++ os_funcs->TeardownComplete = tn7sar_teardown_complete;
++
++ return(0);
++}
++
++
++static void tn7sar_init_dev_parm(void)
++{
++ int i;
++
++
++ /* aal5 */
++ //strcpy(aal5Parm.id, "aal5");
++ aal5Parm.base = 0x03000000;
++ aal5Parm.offset = 0;
++ aal5Parm.int_line=15;
++ aal5Parm.chan[0].RxBufSize=1600;
++ aal5Parm.chan[0].RxNumBuffers = 32;
++ aal5Parm.chan[0].RxServiceMax = 50;
++ aal5Parm.chan[0].TxServiceMax=50;
++ aal5Parm.chan[0].TxNumBuffers=32;
++ aal5Parm.chan[0].CpcsUU=0x5aa5;
++ aal5Parm.chan[0].TxVc_CellRate=0x3000;
++ aal5Parm.chan[0].TxVc_AtmHeader=0x00000640;
++ for(i=1;i<8;i++)
++ {
++ memcpy(&aal5Parm.chan[i], &aal5Parm.chan[0], sizeof(aal5Parm.chan[0]));
++ }
++
++
++ /* sar */
++ //strcpy(sarParm.id, "sar");
++ sarParm.base = 0x03000000;
++ sarParm.reset_bit = 9;
++ sarParm.offset = 0;
++ sarParm.UniNni = 0;
++
++ pAal5 = aal5Data;
++ pSar = sarData;
++ pReset = resetData;
++ strcpy(pAal5, AAL5_PARM);
++ strcpy(pSar, SAR_PARM);
++ strcpy(pReset, RESET_PARM);
++
++}
++
++
++int tn7sar_get_stats(void *priv1)
++{
++ HAL_FUNCTIONS *pHalFunc;
++ HAL_DEVICE *pHalDev;
++ Tn7AtmPrivate *priv;
++ int i, j;
++ unsigned int *pSarStat, *pStateBase;
++ char statString[64];
++ int len;
++
++ dprintf(2, "tn7sar_get_stats\n");
++
++ priv = (Tn7AtmPrivate *)priv1;
++ pHalFunc = (HAL_FUNCTIONS *)priv->pSarHalFunc;
++ pHalDev = (HAL_DEVICE *)priv->pSarHalDev;
++
++ //memset(&sarStat, 0, sizeof(sarStat));
++ sarStat.txErrors = 0;
++ sarStat.rxErrors = 0;
++ for(i=0;i<MAX_DMA_CHAN;i++)
++ {
++ if(priv->lut[i].inuse)
++ {
++ for(j=0;j<1;j++)
++ {
++ len=sprintf(statString, "Stats;0;%d", priv->lut[i].chanid);
++ statString[len]=0;
++ dprintf(2, "statString=%s\n",statString);
++ pHalFunc->Control(pHalDev, statString, "Get", &pSarStat);
++ pStateBase = pSarStat;
++ while(pSarStat)
++ {
++ if((char *)*pSarStat == NULL)
++ break;
++ dprintf(2, "%s\n", (char *) *pSarStat);
++ pSarStat++;
++ dprintf(2, "%s\n", (char *) *pSarStat);
++ sarStat.rxErrors += os_atoul((char *) *pSarStat);
++ pSarStat++;
++ }
++
++ kfree(pStateBase);
++ }
++ }
++ }
++ return 0;
++}
++
++int tn7sar_setup_oam_channel(Tn7AtmPrivate *priv)
++{
++
++ CHANNEL_INFO chInfo;
++ HAL_FUNCTIONS *pHalFunc;
++ HAL_DEVICE *pHalDev;
++ int chan=15;
++ dprintf(4, "tn7sar_setup_oam_channel\n");
++
++ pHalFunc = (HAL_FUNCTIONS *)priv->pSarHalFunc;
++ pHalDev = (HAL_DEVICE *)priv->pSarHalDev;
++
++ memset(&chInfo, 0xff, sizeof(chInfo));
++
++ /* channel specific */
++ chInfo.Channel = 15; /* hardcoded for last channel */
++ chInfo.Direction = 0;
++ chInfo.Vci = 30; /* just need below 32 */
++ chInfo.Vpi = 0;
++ chInfo.TxVc_QosType = 2;
++
++ /*default */
++ chInfo.PktType = PACKET_TYPE_TRANS;
++ chInfo.TxServiceMax = 2;
++ chInfo.RxServiceMax = 2;
++ chInfo.TxNumQueues = 1;
++ chInfo.TxNumBuffers = 4;
++ chInfo.RxNumBuffers = 4;
++ chInfo.RxBufSize = 256;
++ chInfo.RxVc_OamToHost = 0;
++ chInfo.RxVp_OamToHost = 0;
++ chInfo.FwdUnkVc = 1; //enable forwarding of unknown vc
++ chInfo.TxVc_AtmHeader = tn7sar_atm_header((int)chInfo.Vpi, chInfo.Vci);
++ chInfo.RxVc_AtmHeader = tn7sar_atm_header((int)chInfo.Vpi, chInfo.Vci);
++ chInfo.TxVp_AtmHeader = tn7sar_atm_header((int)chInfo.Vpi, 0);
++ chInfo.RxVp_AtmHeader = tn7sar_atm_header((int)chInfo.Vpi, 0);
++
++ dprintf(4, "TxVc_AtmHeader=0x%x\n", chInfo.TxVc_AtmHeader);
++
++ if(pHalFunc->ChannelSetup(pHalDev, &chInfo, NULL))
++ {
++ printk("failed to setup channel =%d.\n", chan);
++ return -1;
++ }
++
++ // claiming the channel
++ priv->lut[chan].vpi = 0;
++ priv->lut[chan].vci = 30;
++ priv->lut[chan].chanid = chan;
++ priv->lut[chan].inuse = 1;
++ return 0;
++}
++
++int tn7sar_init(struct atm_dev *dev, Tn7AtmPrivate *priv)
++{
++ int retCode;
++ int hal_funcs_size;
++
++ HAL_FUNCTIONS *pHalFunc;
++ HAL_DEVICE *pHalDev;
++ OS_FUNCTIONS *pOsFunc;
++ int oamMod;
++ char *pLbTimeout;
++ int lbTimeout;
++
++
++ dprintf(4, "tn7sar_init\n");
++
++ pOsFunc = (OS_FUNCTIONS *)kmalloc(sizeof(OS_FUNCTIONS), GFP_KERNEL);
++
++
++ priv->pSarOsFunc = ( void *)pOsFunc;
++
++ /* init boot parms */
++ tn7sar_init_dev_parm();
++
++ /* init sar os call back functions */
++ retCode = tn7sar_init_module(pOsFunc);
++ if (retCode != 0) /* error */
++ {
++ printk("Failed to init SAR OS Functions\n");
++ return (1);
++ }
++
++ /* Init sar hal */
++ retCode = cpaal5InitModule(&pHalDev, (OS_DEVICE*) dev, &pHalFunc,
++ pOsFunc, sizeof(OS_FUNCTIONS), &hal_funcs_size, 0);
++ if (retCode != 0) /* error */
++ {
++ printk("Failed to init SAR HAL\n");
++ return (1);
++ }
++
++ /* sanity check */
++ if (pHalDev == NULL || pHalFunc == NULL || hal_funcs_size != sizeof(HAL_FUNCTIONS) )
++ {
++ printk("Invalid SAR hal and/or functions.\n");
++ return (1);
++ }
++
++ /* remeber HAL pointers */
++ priv->pSarHalDev = (void *)pHalDev;
++ priv->pSarHalFunc = (void *)pHalFunc;
++
++ /* Probe for the Device to get hardware info from driver */
++ retCode = pHalFunc->Probe(pHalDev);
++ if (retCode !=0)
++ {
++ printk("SAR hal probing error.\n");
++ return (1);
++ }
++
++ /* init sar hal */
++ retCode = pHalFunc->Init(pHalDev);
++ if (retCode != 0) /* error */
++ {
++
++ printk("pHalFunc->Init failed. err code =%d\n", retCode);
++ return (1);
++ }
++
++ /* open hal module */
++ retCode = pHalFunc->Open(pHalDev);
++ if (retCode != 0) /* error */
++ {
++ printk("pHalFunc->open failed, err code: %d\n",retCode );
++ return (1);
++ }
++
++ /* init sar for firmware oam */
++ oamMod= 1;
++ pHalFunc->Control(pHalDev,"OamMode", "Set", &oamMod);
++
++ /* read in oam lb timeout value */
++ pLbTimeout = prom_getenv("oam_lb_timeout");
++ if(pLbTimeout)
++ {
++ lbTimeout =tn7sar_strtoul(pLbTimeout, NULL, 10);
++ oamLbTimeout = lbTimeout;
++ pHalFunc->Control(pHalDev,"OamLbTimeout", "Set", &lbTimeout);
++ }
++ else
++ {
++ oamLbTimeout = 5000;
++ }
++
++ oamFarLBCount[0]=0;
++ oamFarLBCount[1]=0;
++ oamFarLBCount[2]=0;
++ oamFarLBCount[3]=0;
++
++ memset(&sarStat, 0 , sizeof(sarStat));
++
++ /* setup channel 15 for oam operation */
++ tn7sar_setup_oam_channel(priv);
++ dprintf(4, "tn7sar_init done");
++ return 0;
++}
++
++static int
++tn7sar_atm_header(int vpi, int vci)
++{
++ union
++ {
++ unsigned char byte[4];
++ unsigned int dword;
++ }atm_h;
++ int itmp = 0;
++
++ //vci
++ itmp = vci &0xf;
++ atm_h.byte[0] = 0;
++ atm_h.byte[0] |= (itmp << 4);
++ atm_h.byte[1] = ((vci & 0xff0) >> 4);
++ atm_h.byte[2] = 0;
++ atm_h.byte[2] |= ((vci & 0xf000) >>12);;
++ atm_h.byte[2] |= ((vpi & 0xf) << 4);
++ atm_h.byte[3] = 0;
++ atm_h.byte[3] = ((vpi & 0xff0) >> 4);
++ return atm_h.dword;
++}
++
++int tn7sar_activate_vc(Tn7AtmPrivate *priv, short vpi, int vci, int pcr, int scr, int mbs, int cdvt, int chan, int qos)
++{
++ CHANNEL_INFO chInfo;
++ HAL_FUNCTIONS *pHalFunc;
++ HAL_DEVICE *pHalDev;
++
++ dprintf(4, "tn7sar_activate_vc\n");
++
++ pHalFunc = (HAL_FUNCTIONS *)priv->pSarHalFunc;
++ pHalDev = (HAL_DEVICE *)priv->pSarHalDev;
++
++ memset(&chInfo, 0xff, sizeof(chInfo));
++
++ /* channel specific */
++ chInfo.Channel = chan;
++ chInfo.Direction = 0;
++ chInfo.Vci = vci;
++ chInfo.Vpi = vpi;
++ chInfo.TxVc_QosType = qos;
++ chInfo.Priority = qos;
++
++ if(chInfo.TxVc_QosType == 1) /* if the connection is VBR than set the DaMask value to tell the schedular to accumalte the credit */
++ {
++ chInfo.DaMask = 1;
++ }
++ chInfo.TxVc_Mbs = mbs; /* use pcr as MBS */
++ pcr = SAR_FREQUNCY/pcr;
++ scr = SAR_FREQUNCY/scr;
++ chInfo.TxVc_CellRate = scr;
++ chInfo.TxVc_Pcr = pcr;
++
++ /*default */
++ chInfo.PktType = PACKET_TYPE_AAL5;
++ chInfo.TxServiceMax = TX_SERVICE_MAX;
++ chInfo.RxServiceMax = RX_SERVICE_MAX;
++ chInfo.TxNumQueues = TX_QUEUE_NUM;
++ chInfo.TxNumBuffers = TX_BUFFER_NUM;
++ chInfo.RxNumBuffers = RX_BUFFER_NUM;
++ chInfo.RxBufSize = RX_BUFFER_SIZE;
++ chInfo.RxVc_OamToHost = 0;
++ chInfo.RxVp_OamToHost = 0;
++ chInfo.TxVc_AtmHeader = tn7sar_atm_header((int)vpi, vci);
++ chInfo.RxVc_AtmHeader = tn7sar_atm_header((int)vpi, vci);
++ chInfo.TxVp_AtmHeader = tn7sar_atm_header((int)vpi, 0);
++ chInfo.RxVp_AtmHeader = tn7sar_atm_header((int)vpi, 0);
++ chInfo.CpcsUU = 0;
++
++ dprintf(4, "TxVc_AtmHeader=0x%x\n", chInfo.TxVc_AtmHeader);
++
++ if(pHalFunc->ChannelSetup(pHalDev, &chInfo, NULL))
++ {
++ printk("failed to setup channel =%d.\n", chan);
++ return -1;
++ }
++
++
++ return 0;
++}
++
++int tn7sar_send_packet(Tn7AtmPrivate *priv, int chan, void *new_skb, void *data,unsigned int len, int priority)
++{
++ FRAGLIST fragList;
++ unsigned int mode;
++ HAL_FUNCTIONS *pHalFunc;
++ HAL_DEVICE *pHalDev;
++
++ dprintf(4, "tn7sar_send_packet\n");
++ pHalFunc = (HAL_FUNCTIONS *)priv->pSarHalFunc;
++ pHalDev = (HAL_DEVICE *)priv->pSarHalDev;
++
++ fragList.len = len;
++ fragList.data = (void *)data;
++
++ xdump((char *)fragList.data , fragList.len, 6);
++
++ /*mode bit
++ 31-19 unused
++ 18 oam cell, 1 = true, 0=false
++ 17-16 oam type, 0=F4 seg, 1=F4 End, 2=F5 seg, 3=F5 end
++ 15-08 transimit queue, current, 0=priority queue, 1=normal queue
++ 07-00 channel number
++ */
++ mode = 0;
++ mode |= (0xff & chan);
++ mode |= ((0xff & priority) << 8);
++
++ dprintf(4, "mode = %d\n", mode);
++
++ tn7sar_data_writeback(fragList.data, len);
++ if(pHalFunc->Send(pHalDev, &fragList, 1, len, new_skb, mode) != 0)
++ {
++ dprintf(1, "SAR hal failed to send packet.\n");
++ return 1;
++ }
++ //tn7sar_get_stats(priv);
++ sarStat.txPktCnt++;
++ sarStat.txBytes +=len;
++ return 0;
++}
++
++
++
++int tn7sar_handle_interrupt(struct atm_dev *dev, Tn7AtmPrivate *priv)
++{
++ int more;
++ int rc;
++ HAL_FUNCTIONS *pHalFunc;
++ HAL_DEVICE *pHalDev;
++ int (*halIsr)(HAL_DEVICE *halDev, int *work);
++
++ pHalFunc = (HAL_FUNCTIONS *)priv->pSarHalFunc;
++ pHalDev = (HAL_DEVICE *)priv->pSarHalDev;
++ halIsr = priv->halIsr;
++
++ rc = halIsr(pHalDev, &more);
++
++ pHalFunc->PacketProcessEnd(pHalDev);
++
++ return rc;
++}
++
++
++int tn7sar_deactivate_vc(Tn7AtmPrivate *priv, int chan)
++{
++ unsigned int mode;
++ HAL_FUNCTIONS *pHalFunc;
++ HAL_DEVICE *pHalDev;
++
++ dprintf(4, "tn7sar_deactivate_vc\n");
++ pHalFunc = (HAL_FUNCTIONS *)priv->pSarHalFunc;
++ pHalDev = (HAL_DEVICE *)priv->pSarHalDev;
++
++ mode = 0xf; //tear down everything, wait for return;
++
++ pHalFunc->ChannelTeardown(pHalDev, chan, mode);
++ return 0;
++}
++
++void tn7sar_exit(struct atm_dev *dev, Tn7AtmPrivate *priv)
++{
++ HAL_FUNCTIONS *pHalFunc;
++ HAL_DEVICE *pHalDev;
++
++ dprintf(4, "tn7sar_exit()\n");
++
++ pHalFunc = (HAL_FUNCTIONS *)priv->pSarHalFunc;
++ pHalDev = (HAL_DEVICE *)priv->pSarHalDev;
++
++ tn7sar_deactivate_vc(priv, 15); // de-activate oam channel
++
++ pHalFunc->Close(pHalDev, 2);
++ pHalFunc->Shutdown(pHalDev);
++
++ kfree(priv->pSarOsFunc);
++
++}
++
++void tn7sar_get_sar_version(Tn7AtmPrivate *priv, char **pVer)
++{
++ HAL_FUNCTIONS *pHalFunc;
++ HAL_DEVICE *pHalDev;
++
++ dprintf(4, "tn7sar_get_sar_version()\n");
++
++ pHalFunc = (HAL_FUNCTIONS *)priv->pSarHalFunc;
++ pHalDev = (HAL_DEVICE *)priv->pSarHalDev;
++ pHalFunc->Control(pHalDev, "Version", "Get", pVer);
++}
++
++
++int tn7sar_get_near_end_loopback_count(unsigned int *pF4count, unsigned int *pF5count)
++{
++ unsigned int f4c, f5c;
++
++ f4c = *(volatile unsigned int *)SAR_PDSP_OAM_F4LB_COUNT_REG_ADDR;
++ f5c = *(volatile unsigned int *)SAR_PDSP_OAM_F5LB_COUNT_REG_ADDR;
++ *pF4count = f4c;
++ *pF5count = f5c;
++
++ return 0;
++}
++
++
++int tn7sar_unmatched_oam_generation(void *privContext, int vpi, int vci, int type)
++{
++
++ unsigned int regv = 0;
++ int chan=15;
++ static unsigned int tag;
++ HAL_FUNCTIONS *pHalFunc;
++ HAL_DEVICE *pHalDev;
++ Tn7AtmPrivate *priv;
++ unsigned int llid[4]={0xffffffff,0xffffffff,0xffffffff,0xffffffff};
++
++ dprintf(4, "tn7sar_unknow_oam_generation()\n");
++
++ priv = (Tn7AtmPrivate *)privContext;
++ pHalFunc = (HAL_FUNCTIONS *)priv->pSarHalFunc;
++ pHalDev = (HAL_DEVICE *)priv->pSarHalDev;
++
++ if(vci==0)
++ {
++ oamPingStatus = OAM_PING_FAILED;
++ return 0;
++ }
++ /* calculate atm header */
++ oamAtmHdr = tn7sar_atm_header(vpi,vci);
++
++ /* config the atm header */
++ pHalFunc->Control(pHalDev,"TxVc_AtmHeader.15", "Set", &oamAtmHdr);
++
++ /*record oam type */
++ oam_type = type;
++
++ regv = (0xff & chan);
++
++ switch(type)
++ {
++ case 0:
++ regv |= (1<<12); //f5 end
++ dprintf(2, "f5 loop back\n");
++ break;
++ case 1:
++ regv |= (1<<13); // f4 end
++ break;
++ case 2:
++ regv |= (1<<14); //f5 seg
++ break;
++ case 3:
++ regv |= (1<<15); //f4 seg
++ break;
++ default:
++ break;
++ }
++ oamPingStatus = OAM_PING_PENDING;
++ pHalFunc->OamLoopbackConfig(pHalDev, regv, llid, tag);
++ tag++;
++ return 0;
++
++}
++
++int tn7sar_oam_generation(void *privContext, int chan, int type, int vpi, int vci, int timeout)
++{
++ unsigned int regv = 0;
++ static unsigned int tag;
++ HAL_FUNCTIONS *pHalFunc;
++ HAL_DEVICE *pHalDev;
++ Tn7AtmPrivate *priv;
++ unsigned int llid[4]={0xffffffff,0xffffffff,0xffffffff,0xffffffff};
++
++ dprintf(2, "tn7sar_oam_generation()\n");
++
++ priv = (Tn7AtmPrivate *)privContext;
++ pHalFunc = (HAL_FUNCTIONS *)priv->pSarHalFunc;
++ pHalDev = (HAL_DEVICE *)priv->pSarHalDev;
++
++ if(timeout >= 5000)
++ {
++ if(timeout == 6000)
++ {
++ tn7sar_clear_pvc_table();
++ return 0;
++ }
++ timeout = oamLbTimeout;
++ }
++
++
++ pHalFunc->Control(pHalDev,"OamLbTimeout", "Set", &timeout);
++
++ if(chan == ATM_NO_DMA_CHAN)
++ {
++ tn7sar_unmatched_oam_generation(priv, vpi, vci, type);
++ return 0;
++ }
++
++ /* calculate atm header */
++ oamAtmHdr = tn7sar_atm_header(vpi,vci);
++
++ oam_type = type;
++
++ regv = (0xff & chan);
++ switch(type)
++ {
++ case 0:
++ regv |= (1<<12); //f5 end
++ dprintf(2, "f5 loop back\n");
++ break;
++ case 1:
++ regv |= (1<<13); // f4 end
++ break;
++ case 2:
++ regv |= (1<<14); //f5 seg
++ break;
++ case 3:
++ regv |= (1<<15); //f4 seg
++ break;
++ default:
++ break;
++ }
++ oamPingStatus = OAM_PING_PENDING;
++ pHalFunc->OamLoopbackConfig(pHalDev, regv, llid, tag);
++ tag++;
++
++ return 0;
++}
++
++int tn7sar_proc_oam_ping(char* buf, char **start, off_t offset, int count,int *eof, void *data)
++{
++ int len = 0;
++
++ len += sprintf(buf+len, "%d\n", oamPingStatus);
++
++ return len;
++}
++
++int tn7sar_proc_pvc_table(char* buf, char **start, off_t offset, int count,int *eof, void *data)
++{
++ int len = 0;
++ int i;
++
++ for(i=0;i<16;i++)
++ {
++ if(pvc_result[i].bInUse)
++ {
++ len += sprintf(buf+len, "%d,%d\n", pvc_result[i].vpi,pvc_result[i].vci);
++ }
++ else
++ {
++ len += sprintf(buf+len, "0,0\n");
++ }
++ }
++ return len;
++}
++
++
++
++int tn7sar_proc_sar_stat(char* buf, char **start, off_t offset, int count,int *eof, void *data)
++{
++ int len = 0;
++ int limit = count - 80;
++ struct atm_dev *dev;
++ Tn7AtmPrivate *priv;
++ int i, j, k;
++ int stat_len;
++ char statString[32];
++ unsigned int *pStateBase, *pSarStat;
++ HAL_FUNCTIONS *pHalFunc;
++ HAL_DEVICE *pHalDev;
++ int dBytes;
++
++ dev = (struct atm_dev *)data;
++ priv = (Tn7AtmPrivate *)dev->dev_data;
++
++ pHalFunc = (HAL_FUNCTIONS *)priv->pSarHalFunc;
++ pHalDev = (HAL_DEVICE *)priv->pSarHalDev;
++
++ len += sprintf(buf+len, "SAR HAL Statistics\n");
++ for(i=0;i<MAX_DMA_CHAN;i++)
++ {
++ if(priv->lut[i].inuse)
++ {
++ if(len<=limit)
++ len += sprintf(buf+len, "\nChannel %d:\n",priv->lut[i].chanid);
++ k=0;
++ for(j=0;j<4;j++)
++ {
++ stat_len =sprintf(statString, "Stats;%d;%d", j,priv->lut[i].chanid);
++ statString[stat_len]=0;
++ pHalFunc->Control(pHalDev, statString, "Get", &pSarStat);
++ pStateBase = pSarStat;
++ while(pSarStat)
++ {
++ if((char *)*pSarStat == NULL)
++ break;
++ if(len<=limit)
++ {
++ dBytes = sprintf(buf+len, "%s: ",(char *) *pSarStat);
++ len += dBytes;
++ k += dBytes;
++ }
++ pSarStat++;
++ if(len<=limit)
++ {
++ dBytes = sprintf(buf+len, "%s; ",(char *) *pSarStat);
++ len += dBytes;
++ k += dBytes;
++ }
++ pSarStat++;
++
++ if(k > 60)
++ {
++ k=0;
++ if(len<=limit)
++ len += sprintf(buf+len, "\n");
++ }
++ }
++
++ kfree(pStateBase);
++ }
++ }
++ }
++
++ return len;
++}
++
++void tn7sar_get_sar_firmware_version(unsigned int *pdsp_version_ms, unsigned int *pdsp_version_ls)
++{
++
++ *pdsp_version_ms = (SarPdspFirmware[9]>>20) & 0xF;
++ *pdsp_version_ls = (SarPdspFirmware[9]>>12) & 0xFF;
++ return;
++}
+diff -urN linux.old/drivers/atm/sangam_atm/tnetd7300_sar_firm.h linux.dev/drivers/atm/sangam_atm/tnetd7300_sar_firm.h
+--- linux.old/drivers/atm/sangam_atm/tnetd7300_sar_firm.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/tnetd7300_sar_firm.h 2005-08-23 04:46:50.111841568 +0200
+@@ -0,0 +1,988 @@
++//SarPdspFirmware Revision: 49
++
++static int SarPdspFirmware[] = {
++ 0xb0a8d1f1,
++ 0x000003d8,
++ 0x00000000,
++ 0x00000004,
++ 0x00000000,
++ 0x00000000,
++ 0x00000000,
++ 0x00000000,
++ 0x21000900,
++ 0x24049080,
++ 0x24000080,
++ 0x240000c0,
++ 0x10e0e0e1,
++ 0x10e0e0e2,
++ 0x10e0e0e3,
++ 0x10e0e0e4,
++ 0x10e0e0e5,
++ 0x10e0e0e6,
++ 0x10e0e0e7,
++ 0x10e0e0e8,
++ 0x10e0e0e9,
++ 0x10e0e0ea,
++ 0x10e0e0eb,
++ 0x10e0e0ec,
++ 0x10e0e0ed,
++ 0x10e0e0ee,
++ 0x10e0e0ef,
++ 0x10e0e0f0,
++ 0x10e0e0f1,
++ 0x10e0e0f2,
++ 0x10e0e0f3,
++ 0x10e0e0f4,
++ 0x10e0e0f5,
++ 0x10e0e0f6,
++ 0x10e0e0f7,
++ 0x10e0e0f8,
++ 0x10e0e0f9,
++ 0x10e0e0fa,
++ 0x10e0e0fb,
++ 0x10e0e0fc,
++ 0x10e0e0fd,
++ 0x10e0e0fe,
++ 0x10e0e0ff,
++ 0x81042680,
++ 0x810c2680,
++ 0x81042680,
++ 0x2483c080,
++ 0x81180b80,
++ 0x2484c080,
++ 0x811a0b80,
++ 0x2485c080,
++ 0x811c0b80,
++ 0x240100dd,
++ 0xa07d06fd,
++ 0x240400dd,
++ 0xa07d04fd,
++ 0x24c000dd,
++ 0x2400169d,
++ 0xa07d5cfd,
++ 0x511f9d03,
++ 0x01019d9d,
++ 0x7f0000fd,
++ 0xd11eff05,
++ 0x97c06890,
++ 0x1d00e5e5,
++ 0x2301229e,
++ 0x81bc2890,
++ 0x24000000,
++ 0xc917ff02,
++ 0x81000100,
++ 0x01010000,
++ 0xc918ff02,
++ 0x81000100,
++ 0x01010000,
++ 0xc919ff02,
++ 0x81000100,
++ 0xd110e70a,
++ 0xd11cff09,
++ 0x1d00e5e5,
++ 0xd100e704,
++ 0xd114ff06,
++ 0x2301179e,
++ 0x79000004,
++ 0xd70ffffd,
++ 0x91382486,
++ 0x2301059e,
++ 0xc903ff07,
++ 0xa06047e0,
++ 0xb10043e6,
++ 0xc910e602,
++ 0x81000106,
++ 0x24006025,
++ 0x2300d39e,
++ 0xd11dff09,
++ 0x1f00e5e5,
++ 0xc901e705,
++ 0xd111ff06,
++ 0x91382586,
++ 0x2301059e,
++ 0x79000003,
++ 0xd715fffc,
++ 0x2301179e,
++ 0xc910e706,
++ 0x110f2760,
++ 0x240000c6,
++ 0x24000086,
++ 0x13106006,
++ 0x7b00005a,
++ 0x11079f80,
++ 0x51008010,
++ 0xc912ff0f,
++ 0xd100ff04,
++ 0xd101ff05,
++ 0xa06046e0,
++ 0x79000004,
++ 0xa06044e0,
++ 0x79000002,
++ 0xa06045e0,
++ 0xb10043e6,
++ 0x61150602,
++ 0x2101c500,
++ 0xc910e602,
++ 0xa1001006,
++ 0x24000025,
++ 0x2300d39e,
++ 0xd11fff05,
++ 0x97c06a90,
++ 0x1f00e5e5,
++ 0x2301229e,
++ 0x81bc2a90,
++ 0xd11cff09,
++ 0x1d00e5e5,
++ 0xc900e705,
++ 0xd10fff06,
++ 0x91382486,
++ 0x2301059e,
++ 0x79000003,
++ 0xd714fffc,
++ 0x2301179e,
++ 0xc907ff07,
++ 0xa0604be0,
++ 0xb10043e6,
++ 0xc910e602,
++ 0x81000106,
++ 0x24006025,
++ 0x2300d39e,
++ 0xd111e70a,
++ 0xd11dff09,
++ 0x1f00e5e5,
++ 0xd101e704,
++ 0xd115ff06,
++ 0x2301179e,
++ 0x79000004,
++ 0xd711fffd,
++ 0x91382586,
++ 0x2301059e,
++ 0xc911e706,
++ 0x0b042760,
++ 0x240000c6,
++ 0x24000086,
++ 0x13106006,
++ 0x7b000024,
++ 0x11709f80,
++ 0x5100800e,
++ 0xc913ff0d,
++ 0xd104ff04,
++ 0xd105ff05,
++ 0xa0604ae0,
++ 0x79000004,
++ 0xa06048e0,
++ 0x79000002,
++ 0xa06049e0,
++ 0xb10043e6,
++ 0xc910e602,
++ 0xa1001106,
++ 0x24000025,
++ 0x2300d39e,
++ 0xc90bff02,
++ 0x7900000b,
++ 0xc90aff02,
++ 0x79000012,
++ 0xcf08ff89,
++ 0xb10002e0,
++ 0xcf18e087,
++ 0x790000b6,
++ 0x24000080,
++ 0x24fb00c0,
++ 0xa06003e0,
++ 0x7f000082,
++ 0xb10024e6,
++ 0xb10025e0,
++ 0xa06628e6,
++ 0xa06029e0,
++ 0x248000c6,
++ 0xa06624e6,
++ 0x671006f0,
++ 0x81082186,
++ 0x7f0000ee,
++ 0xb10027e6,
++ 0x61100604,
++ 0xa0662be6,
++ 0x810c2186,
++ 0x79000006,
++ 0xd70cffea,
++ 0xa0662be6,
++ 0x1f1be6e6,
++ 0x81382686,
++ 0x813c2680,
++ 0x248000c6,
++ 0xa06627e6,
++ 0x7f0000e3,
++ 0x110f0600,
++ 0x81100b00,
++ 0x01502545,
++ 0x90457888,
++ 0x5103091c,
++ 0x6901092a,
++ 0xc910e603,
++ 0xd108e90d,
++ 0x79000027,
++ 0x01582545,
++ 0x9045788a,
++ 0xd108e904,
++ 0x1f08e9e9,
++ 0x01552545,
++ 0x80451829,
++ 0x50eaeb20,
++ 0x0101ebeb,
++ 0x015c2545,
++ 0x8045388b,
++ 0x7900001c,
++ 0x015c2545,
++ 0x9045788b,
++ 0x6900eb05,
++ 0x1d08e9e9,
++ 0x01552545,
++ 0x80451829,
++ 0x79000004,
++ 0x0501ebeb,
++ 0x015c2545,
++ 0x8045388b,
++ 0x10ecece8,
++ 0x79000010,
++ 0x24000000,
++ 0x5110000e,
++ 0x690f6903,
++ 0x24000069,
++ 0x79000002,
++ 0x01016969,
++ 0x01010000,
++ 0x81100b69,
++ 0x01542545,
++ 0x90451809,
++ 0x6f0209f7,
++ 0xa1001069,
++ 0x81100b06,
++ 0x01572545,
++ 0x80451869,
++ 0xa06841e8,
++ 0xa1414006,
++ 0x209e0000,
++ 0x81100b06,
++ 0xd11fe603,
++ 0x9164388d,
++ 0x8108248d,
++ 0xd100e507,
++ 0x97406490,
++ 0x9108248d,
++ 0x813c2480,
++ 0x2302b4de,
++ 0x1d00e7e7,
++ 0x79000006,
++ 0x97406590,
++ 0x9108258d,
++ 0x813c2580,
++ 0x1d01e7e7,
++ 0x2302b9de,
++ 0x8164388d,
++ 0x209e0000,
++ 0x81040105,
++ 0x91002286,
++ 0x97086290,
++ 0x81042280,
++ 0xd100e504,
++ 0x2302b4de,
++ 0x1f00e7e7,
++ 0x209e0000,
++ 0x2302b9de,
++ 0x1f01e7e7,
++ 0x209e0000,
++ 0xd109ff00,
++ 0xa0702cf0,
++ 0x79000001,
++ 0xd109ff00,
++ 0xb1002de6,
++ 0xd11ee609,
++ 0xb1000de0,
++ 0xc91fe044,
++ 0x24c338c6,
++ 0x10000006,
++ 0x81382686,
++ 0x87406690,
++ 0x813c2680,
++ 0x7900003e,
++ 0x110f0600,
++ 0x81100b00,
++ 0x24000045,
++ 0x24000025,
++ 0x61100603,
++ 0x24006045,
++ 0x24006025,
++ 0x01704545,
++ 0x90451888,
++ 0x0b034600,
++ 0x11070000,
++ 0x69040004,
++ 0xc916ff2c,
++ 0x01019e9e,
++ 0x7900002f,
++ 0xc90cff04,
++ 0x6f0200fd,
++ 0xd308e8a1,
++ 0x7f0000fb,
++ 0x69020008,
++ 0xd308e89e,
++ 0xb1002fe6,
++ 0x91b82880,
++ 0xc91ce002,
++ 0x1f1ce6e6,
++ 0x10080806,
++ 0x79000015,
++ 0xb1002fe6,
++ 0x69030003,
++ 0x13c06666,
++ 0x79000011,
++ 0x91807809,
++ 0xc910ea09,
++ 0x81082689,
++ 0x01018a8a,
++ 0xc91ee60a,
++ 0x1d10eaea,
++ 0x240557c0,
++ 0x60c08a07,
++ 0x1f1de6e6,
++ 0x79000005,
++ 0x2400018a,
++ 0x1f10eaea,
++ 0x1f1fe6e6,
++ 0xd71ee6f8,
++ 0x51000002,
++ 0x11c76666,
++ 0x81382686,
++ 0x87406690,
++ 0x91082689,
++ 0x813c2680,
++ 0xb1002ee6,
++ 0xd103e609,
++ 0x81807809,
++ 0xc908e807,
++ 0x21039400,
++ 0x81002386,
++ 0x87086390,
++ 0x81042380,
++ 0xc908e802,
++ 0x21039400,
++ 0x209e0000,
++ 0xb10008ef,
++ 0x110f0f00,
++ 0x81100b00,
++ 0x24000025,
++ 0x61100f02,
++ 0x24005025,
++ 0x01952545,
++ 0x9045382e,
++ 0xc91def03,
++ 0x24000900,
++ 0x2301c09e,
++ 0xc91cef03,
++ 0x24001900,
++ 0x2301c09e,
++ 0xc91bef03,
++ 0x24000a00,
++ 0x2301c09e,
++ 0xc91aef03,
++ 0x24001a00,
++ 0x2301c09e,
++ 0x8045382e,
++ 0x01a82545,
++ 0x9045388e,
++ 0xc915ef03,
++ 0x24000000,
++ 0x2301c09e,
++ 0xc914ef03,
++ 0x24001000,
++ 0x2301c09e,
++ 0x8045388e,
++ 0x61100f02,
++ 0x24006025,
++ 0x016d2545,
++ 0x9045382e,
++ 0xc919ef03,
++ 0x24000900,
++ 0x2301c09e,
++ 0xc918ef03,
++ 0x24001900,
++ 0x2301c09e,
++ 0xc917ef03,
++ 0x24000a00,
++ 0x2301c09e,
++ 0xc916ef03,
++ 0x24001a00,
++ 0x2301c09e,
++ 0x8045382e,
++ 0x017c2545,
++ 0x9045388e,
++ 0xc913ef03,
++ 0x24000000,
++ 0x2301c09e,
++ 0xc912ef03,
++ 0x24001000,
++ 0x2301c09e,
++ 0x8045388e,
++ 0xd11eef19,
++ 0x11f02f00,
++ 0x51000017,
++ 0x24001520,
++ 0x81140b20,
++ 0x81b01a0f,
++ 0x1f02e7e7,
++ 0x24c000c0,
++ 0x24001580,
++ 0xa0605ce0,
++ 0xc90fef04,
++ 0x1d04e7e7,
++ 0x1d05e7e7,
++ 0x7900000c,
++ 0xc90eef04,
++ 0x1d04e7e7,
++ 0x1f05e7e7,
++ 0x79000008,
++ 0xc90def04,
++ 0x1f04e7e7,
++ 0x1d05e7e7,
++ 0x79000004,
++ 0xc90cef03,
++ 0x1f04e7e7,
++ 0x1f05e7e7,
++ 0x2100b900,
++ 0xd11eef03,
++ 0x1e00eeee,
++ 0x209e0000,
++ 0x1c00eeee,
++ 0x209e0000,
++ 0x110f0606,
++ 0x81140b06,
++ 0x13100606,
++ 0x91b01a83,
++ 0x24000025,
++ 0x61100304,
++ 0x24005025,
++ 0xc905e702,
++ 0x24006025,
++ 0x110f0300,
++ 0x81100b00,
++ 0x81120b00,
++ 0x51150611,
++ 0x61100302,
++ 0x24005025,
++ 0x1d01e5e5,
++ 0x51160639,
++ 0x511a0650,
++ 0x511c0657,
++ 0x5118065e,
++ 0x511e0685,
++ 0x61100302,
++ 0x24006025,
++ 0x1f01e5e5,
++ 0x51170634,
++ 0x511b064b,
++ 0x511d0652,
++ 0x51190658,
++ 0x511f067f,
++ 0xc903e708,
++ 0x1d03e7e7,
++ 0x24000060,
++ 0xa1000a60,
++ 0x244000c0,
++ 0x24001580,
++ 0xa0605ce0,
++ 0x21007d00,
++ 0xcf02e7fc,
++ 0x1d02e7e7,
++ 0x1f03e7e7,
++ 0xc904e703,
++ 0x1f08e3e3,
++ 0x79000002,
++ 0x1d08e3e3,
++ 0xc905e705,
++ 0x01682545,
++ 0x9045588d,
++ 0x2302879e,
++ 0x79000004,
++ 0x01902545,
++ 0x9045588d,
++ 0x2302819e,
++ 0x24001872,
++ 0x24000152,
++ 0xb10009e0,
++ 0x108080d3,
++ 0x10c0c092,
++ 0x2400102c,
++ 0x2302c8de,
++ 0x91021c97,
++ 0x91001cd8,
++ 0x91061c98,
++ 0x91041cd9,
++ 0x910a1c99,
++ 0x91081cda,
++ 0x910e1c9a,
++ 0x910c1cdb,
++ 0x91261d9b,
++ 0x91287d9c,
++ 0x23028dde,
++ 0x1f02e7e7,
++ 0x1d03e7e7,
++ 0x7d000070,
++ 0x01902545,
++ 0x9045798d,
++ 0x79000003,
++ 0x01682545,
++ 0x9045788d,
++ 0x0b09eee0,
++ 0x24001472,
++ 0xd108e303,
++ 0xc900e00b,
++ 0x79000002,
++ 0xc910e009,
++ 0xd101e503,
++ 0x2302819e,
++ 0x79000002,
++ 0x2302879e,
++ 0x91013d12,
++ 0x9504bd93,
++ 0x23028dde,
++ 0x7d00005d,
++ 0xd108ee03,
++ 0x1d10e7e7,
++ 0x7900009a,
++ 0x1d11e7e7,
++ 0x79000098,
++ 0x01902545,
++ 0x9045798d,
++ 0x79000003,
++ 0x01682545,
++ 0x9045788d,
++ 0x0b0aeee0,
++ 0x24001072,
++ 0x7f0000e8,
++ 0x01a02545,
++ 0x9045b98d,
++ 0x79000003,
++ 0x01742545,
++ 0x9045b88d,
++ 0x0b01efe0,
++ 0x24001172,
++ 0x7f0000e0,
++ 0x2302d1de,
++ 0x79000002,
++ 0x2302d6de,
++ 0x000c2545,
++ 0x9045198f,
++ 0xd100ef07,
++ 0x1d02efef,
++ 0xc901ef0c,
++ 0xc905ef0b,
++ 0x1d01efef,
++ 0x1d05efef,
++ 0x79000008,
++ 0xd102ef04,
++ 0x1f02efef,
++ 0x8045198f,
++ 0x79000078,
++ 0xd101ef04,
++ 0x1f01efef,
++ 0x1f05efef,
++ 0x8045198f,
++ 0x69180673,
++ 0x01ac2545,
++ 0x2302dbde,
++ 0xd100ef03,
++ 0x23036c9e,
++ 0x7900006e,
++ 0xc800e40b,
++ 0x110f0020,
++ 0x81100b20,
++ 0x100c0c45,
++ 0x61100002,
++ 0x01604545,
++ 0x9045188f,
++ 0xd101ef04,
++ 0x1f01efef,
++ 0x1f07efef,
++ 0x8045188f,
++ 0x01010000,
++ 0x6f1300f4,
++ 0x79000060,
++ 0x2302d1de,
++ 0x79000002,
++ 0x2302d6de,
++ 0x000c2545,
++ 0x9045198f,
++ 0xc903ef05,
++ 0x1d03efef,
++ 0x1f04efef,
++ 0x8045198f,
++ 0x79000056,
++ 0xc904ef55,
++ 0x1d04efef,
++ 0xc901ef04,
++ 0xc906ef03,
++ 0x1d01efef,
++ 0x1d06efef,
++ 0x8045198f,
++ 0x691e064e,
++ 0x01ac2545,
++ 0x2302dbde,
++ 0xc800e40c,
++ 0x110f0020,
++ 0x81100b20,
++ 0x100c0c45,
++ 0x61100002,
++ 0x01604545,
++ 0x9045188f,
++ 0xc901ef05,
++ 0xc908ef04,
++ 0x1d01efef,
++ 0x1d07efef,
++ 0x8045188f,
++ 0x01010000,
++ 0x6f1300f3,
++ 0x7900003d,
++ 0x10ededf0,
++ 0xc908e303,
++ 0x13401010,
++ 0x209e0000,
++ 0x13301010,
++ 0x209e0000,
++ 0x10ededf0,
++ 0xc908e303,
++ 0x130a1010,
++ 0x209e0000,
++ 0x13081010,
++ 0x209e0000,
++ 0x24000266,
++ 0x2400c800,
++ 0x24000020,
++ 0xd108ee17,
++ 0x01012020,
++ 0xc91cff09,
++ 0x6e0020fe,
++ 0xc910e702,
++ 0x20de0000,
++ 0x1f10e7e7,
++ 0x110f0600,
++ 0x11f02727,
++ 0x12002727,
++ 0x20de0000,
++ 0x1d10e7e7,
++ 0x2302b4de,
++ 0x511d0605,
++ 0x511c0602,
++ 0x7900001e,
++ 0x01a62545,
++ 0x79000002,
++ 0x01722545,
++ 0x90451880,
++ 0x01018080,
++ 0x80451880,
++ 0x79000017,
++ 0x01012020,
++ 0xc91dff09,
++ 0x6e0020fe,
++ 0xc911e702,
++ 0x20de0000,
++ 0x1f11e7e7,
++ 0x09040600,
++ 0x110f2727,
++ 0x12002727,
++ 0x20de0000,
++ 0x1d11e7e7,
++ 0x2302b9de,
++ 0x7f0000ea,
++ 0x81b82786,
++ 0x240000d1,
++ 0x87c06790,
++ 0x81bc2780,
++ 0x20de0000,
++ 0x81b82986,
++ 0x87c06990,
++ 0x81bc2980,
++ 0x20de0000,
++ 0x91b43a88,
++ 0x2301029e,
++ 0x51150608,
++ 0xc908e305,
++ 0x51120303,
++ 0x01010303,
++ 0x79000002,
++ 0x24000003,
++ 0x01012323,
++ 0x81b01a83,
++ 0x21007d00,
++ 0x902cfc88,
++ 0x10c8c893,
++ 0x108888d4,
++ 0x10c9c994,
++ 0x108989d5,
++ 0x10caca95,
++ 0x108a8ad6,
++ 0x10cbcb96,
++ 0x108b8bd7,
++ 0xd108e303,
++ 0x2400a80c,
++ 0x20de0000,
++ 0x2400aa0c,
++ 0x20de0000,
++ 0xd108e303,
++ 0x24007c0c,
++ 0x20de0000,
++ 0x24007e0c,
++ 0x20de0000,
++ 0x24000000,
++ 0x90453904,
++ 0xd108e303,
++ 0x24007c0c,
++ 0x20de0000,
++ 0x24007e0c,
++ 0x20de0000,
++ 0xb1002fe6,
++ 0x91b82880,
++ 0xc91ce002,
++ 0x209e0000,
++ 0xb1002ee6,
++ 0x69187279,
++ 0xd110f230,
++ 0xc903e769,
++ 0xc90be604,
++ 0xc904e767,
++ 0xd105e766,
++ 0x7900000c,
++ 0xc90ae604,
++ 0xd104e763,
++ 0xd105e762,
++ 0x79000008,
++ 0xc907e604,
++ 0xc904e75f,
++ 0xc905e75e,
++ 0x79000004,
++ 0xc906e65c,
++ 0xd104e75b,
++ 0xc905e75a,
++ 0x91003c80,
++ 0x6897c058,
++ 0x68d88057,
++ 0x91043c80,
++ 0x6898c055,
++ 0x68d98054,
++ 0x91083c80,
++ 0x6899c052,
++ 0x68da8051,
++ 0x910c3c80,
++ 0x689ac04f,
++ 0x68db804e,
++ 0xb10009e0,
++ 0x6892c04c,
++ 0x68d3804b,
++ 0x24000160,
++ 0xa1000a60,
++ 0x244000c0,
++ 0x24001580,
++ 0xa0605ce0,
++ 0x1d03e7e7,
++ 0x109393c8,
++ 0x10d4d488,
++ 0x109494c9,
++ 0x10d5d589,
++ 0x109595ca,
++ 0x10d6d68a,
++ 0x109696cb,
++ 0x10d7d78b,
++ 0x8110fc88,
++ 0x209e0000,
++ 0x91003c80,
++ 0x6893c00c,
++ 0x68d4800b,
++ 0x91043c80,
++ 0x6894c009,
++ 0x68d58008,
++ 0x91083c80,
++ 0x6895c006,
++ 0x68d68005,
++ 0x910c3c80,
++ 0x6896c003,
++ 0x68d78002,
++ 0x79000010,
++ 0x24ffff80,
++ 0x24ffffc0,
++ 0x68809306,
++ 0x68e0f405,
++ 0x68e0f504,
++ 0x68e0f603,
++ 0x6880d702,
++ 0x79000008,
++ 0x24000080,
++ 0x240000c0,
++ 0x68809323,
++ 0x68e0f422,
++ 0x68e0f521,
++ 0x68e0f620,
++ 0x6880d71f,
++ 0x1d10f2f2,
++ 0x2400002c,
++ 0x2302c8de,
++ 0x24000f80,
++ 0x240000c0,
++ 0x0101c0c0,
++ 0xd100e504,
++ 0xc91cff06,
++ 0x6e80c0fd,
++ 0x21016d00,
++ 0xc91dff03,
++ 0x6e80c0fa,
++ 0x21016d00,
++ 0xd104e606,
++ 0xc909e608,
++ 0xb1000ce0,
++ 0x0101e0e0,
++ 0xa0600ce0,
++ 0x79000004,
++ 0xb1000be0,
++ 0x0101e0e0,
++ 0xa0600be0,
++ 0xb1002fe6,
++ 0xd100e504,
++ 0x2302b4de,
++ 0x24000022,
++ 0x209e0000,
++ 0x2302b9de,
++ 0x24000042,
++ 0x209e0000,
++ 0xd104e609,
++ 0x01782545,
++ 0x9045180e,
++ 0x110f0e00,
++ 0x81100b00,
++ 0x2400a445,
++ 0x51002502,
++ 0x01504545,
++ 0x90451888,
++ 0xc909e87d,
++ 0xb1002fe6,
++ 0x1f1fe6e6,
++ 0x10080806,
++ 0x21015f00,
++ 0x6914721b,
++ 0x01782545,
++ 0x2303bade,
++ 0x900c188f,
++ 0x1d02efef,
++ 0xc901ef05,
++ 0xc905ef04,
++ 0x1d01efef,
++ 0x1d05efef,
++ 0x800c188f,
++ 0xc909e66e,
++ 0x2303d0de,
++ 0xc800e40c,
++ 0x110f0020,
++ 0x81100b20,
++ 0x100c0c45,
++ 0x61100002,
++ 0x01604545,
++ 0x9045188f,
++ 0xc901ef05,
++ 0xc907ef04,
++ 0x1d01efef,
++ 0x1d07efef,
++ 0x8045188f,
++ 0x01010000,
++ 0x6f1300f3,
++ 0x7900005e,
++ 0x6910725d,
++ 0x01782545,
++ 0x2303bade,
++ 0x900c188f,
++ 0x1f03efef,
++ 0xd101ef03,
++ 0x1f01efef,
++ 0x1f06efef,
++ 0x800c188f,
++ 0xc909e654,
++ 0x2303d0de,
++ 0xc800e40b,
++ 0x110f0020,
++ 0x81100b20,
++ 0x100c0c45,
++ 0x61100002,
++ 0x01604545,
++ 0x9045188f,
++ 0xd101ef04,
++ 0x1f01efef,
++ 0x1f08efef,
++ 0x8045188f,
++ 0x01010000,
++ 0x6f1300f4,
++ 0x79000045,
++ 0x01782545,
++ 0x9045788e,
++ 0x1d02efef,
++ 0x1d12efef,
++ 0xc905ef04,
++ 0x1d05efef,
++ 0x1d01efef,
++ 0x7900000c,
++ 0xc915ef04,
++ 0x1d15efef,
++ 0x1d11efef,
++ 0x79000008,
++ 0xc907ef04,
++ 0x1d07efef,
++ 0x1d01efef,
++ 0x79000004,
++ 0xc917ef03,
++ 0x1d17efef,
++ 0x1d11efef,
++ 0x017c2545,
++ 0x8045388f,
++ 0x110f0e00,
++ 0x81100b00,
++ 0x2400a845,
++ 0x51002502,
++ 0x01504545,
++ 0x9045388f,
++ 0x1d02efef,
++ 0x1d12efef,
++ 0xc905ef04,
++ 0x1d05efef,
++ 0x1d01efef,
++ 0x79000004,
++ 0xc915ef03,
++ 0x1d15efef,
++ 0x1d11efef,
++ 0x8045388f,
++ 0x7900001f,
++ 0xc909e60d,
++ 0x9045180e,
++ 0x110f0e00,
++ 0x81100b00,
++ 0xc90ae603,
++ 0x2400a80c,
++ 0x79000003,
++ 0xc90be617,
++ 0x2400aa0c,
++ 0x51002503,
++ 0x01500c0c,
++ 0x24005025,
++ 0x20de0000,
++ 0xc904e611,
++ 0xc906e603,
++ 0x24007c0c,
++ 0x79000003,
++ 0xc907e60d,
++ 0x24007e0c,
++ 0x51002502,
++ 0x01600c0c,
++ 0x20de0000,
++ 0x01ac2545,
++ 0x24000000,
++ 0x90453804,
++ 0xd10be603,
++ 0x24007c0c,
++ 0x20de0000,
++ 0x24007e0c,
++ 0x20de0000,
++ 0x209e0000};
+diff -urN linux.old/drivers/atm/sangam_atm/turbodsl.c linux.dev/drivers/atm/sangam_atm/turbodsl.c
+--- linux.old/drivers/atm/sangam_atm/turbodsl.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/atm/sangam_atm/turbodsl.c 2005-08-23 04:46:50.111841568 +0200
+@@ -0,0 +1,223 @@
++
++
++/*
++ *
++ * Turbo DSL Implementaion
++ *
++ * Zhicheng Tang ztang@ti.com
++ *
++ * 2002 (c) Texas Instruments Inc.
++ *
++*/
++
++/* defines and variables */
++#define RFC2684_BRIDGED_HDR_SIZE 10
++unsigned char LLC_BRIDGED_HEADER_2684[RFC2684_BRIDGED_HDR_SIZE] =
++ {0xAA, 0xAA, 0x03, 0x00, 0x80, 0xC2, 0x00, 0x07, 0x00, 0x00};
++
++#define RFC2684_ROUTED_HDR_SIZE 6
++unsigned char LLC_ROUTED_HEADER_2684[6] ={0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00};
++
++unsigned long PPP_LLC_HEADER = 0xCF03FEFE;
++
++/* struct definition */
++enum
++{
++ AAL5_ENCAP_PPP_LLC,
++ AAL5_ENCAP_PPP_VCMUX,
++ AAL5_ENCAP_RFC2684_LLC_BRIDGED,
++ AAL5_ENCAP_RFC2684_LLC_ROUTED
++};
++
++/* Etherent header */
++typedef struct _turbodsl_ether_header
++{
++ unsigned char dst_mac_addr[6];
++ unsigned char src_mac_addr[6];
++ unsigned short ether_type;
++} turbodsl_ether_header_t;
++
++
++/* Ip header define */
++typedef struct _turbodsl_ip_header
++{
++
++ unsigned short vit;
++ unsigned short total_length;
++ unsigned short ip_id;
++ unsigned char flag; /* bit 0 = 0, bit1 = don't fragment, bit2=more frag */
++ unsigned char fragment_offset; /* offset include remaining 5 bits above, which make it 13 bits */
++ unsigned char time_to_live;
++ unsigned char protocol;
++ unsigned short checksum;
++ unsigned int src_ip;
++ unsigned int dst_ip;
++} turbodsl_ip_header_t;
++
++/* Arp packet define */
++typedef struct _turbodsl_arp_header
++{
++ unsigned short hardware_type;
++ unsigned short protocol_type;
++ unsigned char h_len;
++ unsigned char p_len;
++ unsigned short operation ;
++ unsigned char snd_hw_address[6];
++ unsigned char snd_pt_address[4];
++ unsigned char dst_hw_address[6];
++ unsigned char dst_pt_address[4];
++} turbodsl_arp_header_t;
++
++#define FIN_FLAG 1
++#define SYN_FLAG 1<<1
++#define RST_FLAG 1<<2
++#define PSH_FLAG 1<<3
++#define ACK_FLAG 1<<4
++#define URG_FLAG 1<<5
++
++typedef struct _turbodsl_tcp_header
++{
++ unsigned short src_port;
++ unsigned short dst_port;
++ unsigned int seq_num;
++ unsigned int ack_num;
++ unsigned char offset; /* only bits 4-7 are for offset */
++ unsigned char flags; /* bits: 0-FIN, 1-SYN, 2-RST, 3-PSH, 4-ACK, 5-URG */
++ unsigned short windows;
++ unsigned short checksum;
++ unsigned short urgent_ptr;
++} turbodsl_tcp_header_t;
++
++
++
++/***************************************************************************
++ * Function: turbodsl_memory_compare
++ * Descripation: Memory compare
++ ****************************************************************************/
++int turbodsl_memory_compare(unsigned char *pIn, unsigned char *pOut, unsigned int len)
++ {
++ int i;
++
++ for(i=0;i<(int)len; i++)
++ {
++ if(pIn[i] != pOut[i])
++ return 0;
++ }
++ return 1;
++ }
++
++/***************************************************************************
++ * Function: turbodsl_check_aal5_encap_type
++ * Descripation: Determine AAL5 Encapsulation type
++ * Input:
++ * unsigned char *pData, AAL5 Packet buffer pointer
++ ****************************************************************************/
++int turbodsl_check_aal5_encap_type(unsigned char *pData)
++ {
++
++ if(turbodsl_memory_compare(pData, LLC_BRIDGED_HEADER_2684, 6))
++ return AAL5_ENCAP_RFC2684_LLC_BRIDGED;
++ if(turbodsl_memory_compare(pData, LLC_ROUTED_HEADER_2684, 6))
++ return AAL5_ENCAP_RFC2684_LLC_ROUTED;
++ if(turbodsl_memory_compare(pData, (unsigned char *)&PPP_LLC_HEADER, sizeof(PPP_LLC_HEADER)))
++ return AAL5_ENCAP_PPP_LLC;
++
++ return AAL5_ENCAP_PPP_VCMUX;
++ }
++
++/***************************************************************************
++ * Function: turbodsl_check_priority_type
++ * Descripation: Determine AAL5 Encapsulation type
++ * Input:
++ * unsigned char *pData, AAL5 Packet buffer pointer.
++ * short vpi, VPI.
++ * int vci, VCI
++ ****************************************************************************/
++int turbodsl_check_priority_type(unsigned char *pData)
++ {
++ int encap;
++ unsigned char *pP;
++ unsigned short etherType;
++ turbodsl_ip_header_t *pIp;
++ turbodsl_tcp_header_t *pTcp;
++ unsigned short ip_length;
++
++ dprintf(2, "turbodsl_check_priority_type ==>\n");
++
++ encap = turbodsl_check_aal5_encap_type(pData);
++ pP = pData;
++
++ switch(encap)
++ {
++ case AAL5_ENCAP_RFC2684_LLC_BRIDGED:
++ pP += RFC2684_BRIDGED_HDR_SIZE; //skip off aal5 encap
++ pP += 12; //skip of mac address
++ etherType = *(unsigned short *)pP;
++ if(etherType != 0x6488 && etherType != 0x0008)
++ {
++ //Not an IP packet
++ return 1;
++ }
++
++ pP +=2; //skip ether type
++ if(etherType == 0x6488)
++ {
++ pP += 6;
++ }
++ break;
++ case AAL5_ENCAP_RFC2684_LLC_ROUTED:
++ pP += RFC2684_ROUTED_HDR_SIZE; //skip of encap
++ pP += 2; //skip ether type
++ break;
++ case AAL5_ENCAP_PPP_LLC:
++ pP += sizeof(PPP_LLC_HEADER);
++ if(*pP == 0xff && *(pP+1) == 0x03) //ppp hdlc header
++ pP += 2;
++ break;
++ case AAL5_ENCAP_PPP_VCMUX:
++ if(*pP == 0xff && *(pP+1) == 0x03) //ppp hdlc header
++ pP += 2;
++ break;
++ default:
++ return 1;
++ }
++
++ pIp = (turbodsl_ip_header_t *)pP;
++ if(pIp->vit != 0x0045)
++ {
++ //Not a IP packet
++ return 1;
++ }
++
++ if(pIp->protocol != 0x06)
++ {
++ //not tcp packet
++ return 1;
++ }
++
++ pTcp = (turbodsl_tcp_header_t *)(pP + sizeof(turbodsl_ip_header_t));
++
++ ip_length = (pIp->total_length>>8) + (pIp->total_length<<8);
++
++ if((pTcp->flags & ACK_FLAG) && ip_length <=40)
++ return 0;
++
++ return 1;
++ }
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
+diff -urN linux.old/include/linux/atmdev.h linux.dev/include/linux/atmdev.h
+--- linux.old/include/linux/atmdev.h 2005-08-22 23:18:37.812526104 +0200
++++ linux.dev/include/linux/atmdev.h 2005-08-23 06:33:33.425389944 +0200
+@@ -30,6 +30,9 @@
+ #define ATM_DS3_PCR (8000*12)
+ /* DS3: 12 cells in a 125 usec time slot */
+
++#define ATM_PDU_OVHD 0 /* number of bytes to charge against buffer
++ quota per PDU */
++
+ #define ATM_SD(s) ((s)->sk->protinfo.af_atm)
+
+
+@@ -94,7 +97,8 @@
+ /* set backend handler */
+ #define ATM_NEWBACKENDIF _IOW('a',ATMIOC_SPECIAL+3,atm_backend_t)
+ /* use backend to make new if */
+-
++#define ATM_STOPTX _IOW('a',ATMIOC_SPECIAL+4,struct atmif_sioc)
++ /* Stop Tx on Sangam DSL */
+ /*
+ * These are backend handkers that can be set via the ATM_SETBACKEND call
+ * above. In the future we may support dynamic loading of these - for now,
+@@ -199,7 +203,9 @@
+ "SESSION", "HASSAP", "BOUND", "CLOSE"
+
+
+-#ifdef __KERNEL__
++#ifndef __KERNEL__
++#undef __AAL_STAT_ITEMS
++#else
+
+ #include <linux/sched.h> /* wait_queue_head_t */
+ #include <linux/time.h> /* struct timeval */
+@@ -291,6 +297,7 @@
+ int (*send)(struct atm_vcc *vcc,struct sk_buff *skb);
+ void *dev_data; /* per-device data */
+ void *proto_data; /* per-protocol data */
++ struct timeval timestamp; /* AAL timestamps */
+ struct k_atm_aal_stats *stats; /* pointer to AAL stats group */
+ wait_queue_head_t sleep; /* if socket is busy */
+ struct sock *sk; /* socket backpointer */
+@@ -333,13 +340,14 @@
+ struct k_atm_dev_stats stats; /* statistics */
+ char signal; /* signal status (ATM_PHY_SIG_*) */
+ int link_rate; /* link rate (default: OC3) */
+- atomic_t refcnt; /* reference count */
+- spinlock_t lock; /* protect internal members */
++ atomic_t refcnt; /* reference count */
++ spinlock_t lock; /* protect internal members */
+ #ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *proc_entry; /* proc entry */
+ char *proc_name; /* proc entry name */
+ #endif
+- struct list_head dev_list; /* linkage */
++ struct list_head dev_list; /* linkage */
++
+ };
+
+
diff --git a/target/linux/ar7-2.4/patches/005-wdt_driver.patch b/target/linux/ar7-2.4/patches/005-wdt_driver.patch
new file mode 100644
index 0000000000..9b01a353da
--- /dev/null
+++ b/target/linux/ar7-2.4/patches/005-wdt_driver.patch
@@ -0,0 +1,392 @@
+diff -ruN linux-2.4.30-patch006/drivers/char/ar7_wdt.c linux-2.4.30-patch007/drivers/char/ar7_wdt.c
+--- linux-2.4.30-patch006/drivers/char/ar7_wdt.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30-patch007/drivers/char/ar7_wdt.c 2005-10-27 09:39:40.000000000 +0200
+@@ -0,0 +1,335 @@
++/* linux/drivers/char/ar7_wdt.c
++
++ TI AR7 watch dog timer support
++
++ Copyright (c) 2005 Enrik Berkhan <Enrik.Berkhan@akk.org>
++
++ Som code taken from:
++ National Semiconductor SCx200 Watchdog support
++ Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.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.
++
++ The author(s) of this software shall not be held liable for damages
++ of any nature resulting due to the use of this software. This
++ software is provided AS-IS with no warranties. */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/miscdevice.h>
++#include <linux/watchdog.h>
++#include <linux/notifier.h>
++#include <linux/reboot.h>
++#include <linux/ioport.h>
++
++#include <asm/uaccess.h>
++
++#include <asm/ar7/avalanche_misc.h>
++#include <asm/ar7/sangam.h>
++
++#define NAME "ar7_wdt"
++#define LONGNAME "TI AR7 Watchdog Timer"
++
++MODULE_AUTHOR("Enrik Berkhan <Enrik.Berkhan@akk.org>");
++MODULE_DESCRIPTION(LONGNAME);
++MODULE_LICENSE("GPL");
++
++#ifndef CONFIG_WATCHDOG_NOWAYOUT
++#define CONFIG_WATCHDOG_NOWAYOUT 0
++#endif
++
++static int margin = 60;
++MODULE_PARM(margin, "i");
++MODULE_PARM_DESC(margin, "Watchdog margin in seconds (1 - ~68)");
++
++static int nowayout = CONFIG_WATCHDOG_NOWAYOUT;
++MODULE_PARM(nowayout, "i");
++MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
++
++typedef struct {
++ uint32_t kick_lock;
++ uint32_t kick;
++ uint32_t change_lock;
++ uint32_t change ;
++ uint32_t disable_lock;
++ uint32_t disable;
++ uint32_t prescale_lock;
++ uint32_t prescale;
++} ar7_wdt_t;
++
++volatile ar7_wdt_t *ar7_wdt = (ar7_wdt_t *)AVALANCHE_WATCHDOG_TIMER_BASE;
++
++static struct semaphore open_semaphore;
++static unsigned expect_close;
++
++/* XXX correct? assumed to be sysfreq/2. get this dynamically ... */
++#define vbus_freq 62500000
++
++/* XXX currently fixed, allows max margin ~68.72 secs */
++#define prescale_value 0xFFFF
++
++static void ar7_wdt_kick(uint32_t value)
++{
++ ar7_wdt->kick_lock = 0x5555;
++ if ((ar7_wdt->kick_lock & 3) == 1) {
++ ar7_wdt->kick_lock = 0xAAAA;
++ if ((ar7_wdt->kick_lock & 3) == 3) {
++ ar7_wdt->kick = value;
++ return;
++ }
++ }
++ printk(KERN_ERR NAME "failed to unlock WDT kick reg\n");
++}
++
++static void ar7_wdt_prescale(uint32_t value)
++{
++ ar7_wdt->prescale_lock = 0x5A5A;
++ if ((ar7_wdt->prescale_lock & 3) == 1) {
++ ar7_wdt->prescale_lock = 0xA5A5;
++ if ((ar7_wdt->prescale_lock & 3) == 3) {
++ ar7_wdt->prescale = value;
++ return;
++ }
++ }
++ printk(KERN_ERR NAME "failed to unlock WDT prescale reg\n");
++}
++
++static void ar7_wdt_change(uint32_t value)
++{
++ ar7_wdt->change_lock = 0x6666;
++ if ((ar7_wdt->change_lock & 3) == 1) {
++ ar7_wdt->change_lock = 0xBBBB;
++ if ((ar7_wdt->change_lock & 3) == 3) {
++ ar7_wdt->change = value;
++ return;
++ }
++ }
++ printk(KERN_ERR NAME "failed to unlock WDT change reg\n");
++}
++
++static void ar7_wdt_disable(uint32_t value)
++{
++ ar7_wdt->disable_lock = 0x7777;
++ if ((ar7_wdt->disable_lock & 3) == 1) {
++ ar7_wdt->disable_lock = 0xCCCC;
++ if ((ar7_wdt->disable_lock & 3) == 2) {
++ ar7_wdt->disable_lock = 0xDDDD;
++ if ((ar7_wdt->disable_lock & 3) == 3) {
++ ar7_wdt->disable = value;
++ return;
++ }
++ }
++ }
++ printk(KERN_ERR NAME "failed to unlock WDT disable reg\n");
++ return;
++}
++
++static void ar7_wdt_update_margin(int new_margin)
++{
++ uint32_t change;
++
++ change = new_margin * (vbus_freq / prescale_value);
++ if (change < 1) change = 1;
++ if (change > 0xFFFF) change = 0xFFFF;
++ ar7_wdt_change(change);
++ margin = change * prescale_value / vbus_freq;
++ printk(KERN_INFO NAME
++ ": timer margin %d seconds (prescale %d, change %d, freq %d)\n",
++ margin, prescale_value, change, vbus_freq);
++}
++
++static void ar7_wdt_enable_wdt(void)
++{
++ printk(KERN_DEBUG NAME ": enabling watchdog timer\n");
++ ar7_wdt_disable(1);
++ ar7_wdt_kick(1);
++}
++
++static void ar7_wdt_disable_wdt(void)
++{
++ printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
++ ar7_wdt_disable(0);
++}
++
++static int ar7_wdt_open(struct inode *inode, struct file *file)
++{
++ /* only allow one at a time */
++ if (down_trylock(&open_semaphore))
++ return -EBUSY;
++ ar7_wdt_enable_wdt();
++ expect_close = 0;
++
++ return 0;
++}
++
++static int ar7_wdt_release(struct inode *inode, struct file *file)
++{
++ if (!expect_close) {
++ printk(KERN_WARNING NAME ": watchdog device closed unexpectedly, will not disable the watchdog timer\n");
++ } else if (!nowayout) {
++ ar7_wdt_disable_wdt();
++ }
++ up(&open_semaphore);
++
++ return 0;
++}
++
++static int ar7_wdt_notify_sys(struct notifier_block *this,
++ unsigned long code, void *unused)
++{
++ if (code == SYS_HALT || code == SYS_POWER_OFF)
++ if (!nowayout)
++ ar7_wdt_disable_wdt();
++
++ return NOTIFY_DONE;
++}
++
++static struct notifier_block ar7_wdt_notifier =
++{
++ .notifier_call = ar7_wdt_notify_sys
++};
++
++static ssize_t ar7_wdt_write(struct file *file, const char *data,
++ size_t len, loff_t *ppos)
++{
++ if (ppos != &file->f_pos)
++ return -ESPIPE;
++
++ /* check for a magic close character */
++ if (len)
++ {
++ size_t i;
++
++ ar7_wdt_kick(1);
++
++ expect_close = 0;
++ for (i = 0; i < len; ++i) {
++ char c;
++ if (get_user(c, data+i))
++ return -EFAULT;
++ if (c == 'V')
++ expect_close = 1;
++ }
++
++ }
++ return len;
++}
++
++static int ar7_wdt_ioctl(struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ static struct watchdog_info ident = {
++ .identity = LONGNAME,
++ .firmware_version = 1,
++ .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING),
++ };
++ int new_margin;
++
++ switch (cmd) {
++ default:
++ return -ENOTTY;
++ case WDIOC_GETSUPPORT:
++ if(copy_to_user((struct watchdog_info *)arg, &ident,
++ sizeof(ident)))
++ return -EFAULT;
++ return 0;
++ case WDIOC_GETSTATUS:
++ case WDIOC_GETBOOTSTATUS:
++ if (put_user(0, (int *)arg))
++ return -EFAULT;
++ return 0;
++ case WDIOC_KEEPALIVE:
++ ar7_wdt_kick(1);
++ return 0;
++ case WDIOC_SETTIMEOUT:
++ if (get_user(new_margin, (int *)arg))
++ return -EFAULT;
++ if (new_margin < 1)
++ return -EINVAL;
++
++ ar7_wdt_update_margin(new_margin);
++ ar7_wdt_kick(1);
++
++ case WDIOC_GETTIMEOUT:
++ if (put_user(margin, (int *)arg))
++ return -EFAULT;
++ return 0;
++ }
++}
++
++static struct file_operations ar7_wdt_fops = {
++ .owner = THIS_MODULE,
++ .write = ar7_wdt_write,
++ .ioctl = ar7_wdt_ioctl,
++ .open = ar7_wdt_open,
++ .release = ar7_wdt_release,
++};
++
++static struct miscdevice ar7_wdt_miscdev = {
++ .minor = WATCHDOG_MINOR,
++ .name = "watchdog",
++ .fops = &ar7_wdt_fops,
++};
++
++static __initdata char *last_initiator[] = {
++ [HARDWARE_RESET] = "hardware reset",
++ [SOFTWARE_RESET0] = "SW0 software reset",
++ [SOFTWARE_RESET1] = "SW1 software reset",
++ [WATCHDOG_RESET] = "watchdog"
++};
++
++static int __init ar7_wdt_init(void)
++{
++ int r;
++
++ if (!request_mem_region(AVALANCHE_WATCHDOG_TIMER_BASE,
++ sizeof(ar7_wdt_t), LONGNAME)) {
++ printk(KERN_WARNING NAME ": watchdog I/O region busy\n");
++ return -EBUSY;
++ }
++
++ printk(KERN_INFO NAME ": last system reset initiated by %s\n",
++ last_initiator[avalanche_get_sys_last_reset_status()]);
++
++
++ ar7_wdt_disable_wdt();
++ ar7_wdt_prescale(prescale_value);
++ ar7_wdt_update_margin(margin);
++
++ sema_init(&open_semaphore, 1);
++
++ r = misc_register(&ar7_wdt_miscdev);
++ if (r) {
++ printk(KERN_ERR NAME ": unable to register misc device\n");
++ release_mem_region(AVALANCHE_WATCHDOG_TIMER_BASE,
++ sizeof(ar7_wdt_t));
++ return r;
++ }
++
++ r = register_reboot_notifier(&ar7_wdt_notifier);
++ if (r) {
++ printk(KERN_ERR NAME ": unable to register reboot notifier\n");
++ misc_deregister(&ar7_wdt_miscdev);
++ release_mem_region(AVALANCHE_WATCHDOG_TIMER_BASE,
++ sizeof(ar7_wdt_t));
++ return r;
++ }
++
++ return 0;
++}
++
++static void __exit ar7_wdt_cleanup(void)
++{
++ unregister_reboot_notifier(&ar7_wdt_notifier);
++ misc_deregister(&ar7_wdt_miscdev);
++ release_mem_region(AVALANCHE_WATCHDOG_TIMER_BASE, sizeof(ar7_wdt_t));
++}
++
++module_init(ar7_wdt_init);
++module_exit(ar7_wdt_cleanup);
+diff -ruN linux-2.4.30-patch006/drivers/char/Config.in linux-2.4.30-patch007/drivers/char/Config.in
+--- linux-2.4.30-patch006/drivers/char/Config.in 2005-10-27 11:25:29.000000000 +0200
++++ linux-2.4.30-patch007/drivers/char/Config.in 2005-10-27 11:17:32.000000000 +0200
+@@ -251,6 +251,9 @@
+ bool 'Watchdog Timer Support' CONFIG_WATCHDOG
+ if [ "$CONFIG_WATCHDOG" != "n" ]; then
+ bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT
++ if [ "$CONFIG_AR7" = "y" ] ; then
++ tristate ' TI AR7 Watchdog Timer' CONFIG_AR7_WDT
++ else
+ tristate ' Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT
+ tristate ' Advantech SBC Watchdog Timer' CONFIG_ADVANTECH_WDT
+ tristate ' ALi M7101 PMU on ALi 1535D+ Watchdog Timer' CONFIG_ALIM1535_WDT
+@@ -271,7 +274,6 @@
+ tristate ' SBC-60XX Watchdog Timer' CONFIG_60XX_WDT
+ dep_tristate ' SC1200 Watchdog Timer (EXPERIMENTAL)' CONFIG_SC1200_WDT $CONFIG_EXPERIMENTAL
+ tristate ' NatSemi SCx200 Watchdog' CONFIG_SCx200_WDT
+- tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG
+ tristate ' W83877F (EMACS) Watchdog Timer' CONFIG_W83877F_WDT
+ tristate ' WDT Watchdog timer' CONFIG_WDT
+ tristate ' WDT PCI Watchdog timer' CONFIG_WDTPCI
+@@ -282,6 +284,8 @@
+ fi
+ fi
+ tristate ' ZF MachZ Watchdog' CONFIG_MACHZ_WDT
++ fi
++ tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG
+ if [ "$CONFIG_SGI_IP22" = "y" ]; then
+ dep_tristate ' Indy/I2 Hardware Watchdog' CONFIG_INDYDOG $CONFIG_SGI_IP22
+ fi
+diff -ruN linux-2.4.30-patch006/drivers/char/Makefile linux-2.4.30-patch007/drivers/char/Makefile
+--- linux-2.4.30-patch006/drivers/char/Makefile 2005-10-27 11:19:38.000000000 +0200
++++ linux-2.4.30-patch007/drivers/char/Makefile 2005-10-27 09:39:40.000000000 +0200
+@@ -342,6 +342,7 @@
+ obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
+ obj-$(CONFIG_INDYDOG) += indydog.o
+ obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
++obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
+
+ subdir-$(CONFIG_MWAVE) += mwave
+ ifeq ($(CONFIG_MWAVE),y)
+diff -ruN linux-2.4.30-patch006/include/asm-mips/ar7/sangam.h linux-2.4.30-patch007/include/asm-mips/ar7/sangam.h
+--- linux-2.4.30-patch006/include/asm-mips/ar7/sangam.h 2005-10-27 11:25:51.000000000 +0200
++++ linux-2.4.30-patch007/include/asm-mips/ar7/sangam.h 2005-10-27 11:13:37.000000000 +0200
+@@ -152,7 +152,7 @@
+ #define AVALANCHE_EMIF_SDRAM_CFG (AVALANCHE_EMIF_CONTROL_BASE + 0x8)
+ #define AVALANCHE_RST_CTRL_PRCR (KSEG1ADDR(0x08611600))
+ #define AVALANCHE_RST_CTRL_SWRCR (KSEG1ADDR(0x08611604))
+-#define AVALANCHE_RST_CTRL_RSR (KSEG1ADDR(0x08611600))
++#define AVALANCHE_RST_CTRL_RSR (KSEG1ADDR(0x08611608))
+
+ #define AVALANCHE_POWER_CTRL_PDCR (KSEG1ADDR(0x08610A00))
+ #define AVALANCHE_WAKEUP_CTRL_WKCR (KSEG1ADDR(0x08610A0C))
diff --git a/target/linux/ar7-2.4/patches/006-sched_use_tsc.patch b/target/linux/ar7-2.4/patches/006-sched_use_tsc.patch
new file mode 100644
index 0000000000..5b64310738
--- /dev/null
+++ b/target/linux/ar7-2.4/patches/006-sched_use_tsc.patch
@@ -0,0 +1,84 @@
+diff -urN linux.old/arch/mips/kernel/time.c linux.dev/arch/mips/kernel/time.c
+--- linux.old/arch/mips/kernel/time.c 2005-11-14 11:06:38.661262000 +0100
++++ linux.dev/arch/mips/kernel/time.c 2005-11-15 20:02:50.059676750 +0100
+@@ -151,6 +151,27 @@
+ unsigned int (*mips_hpt_read)(void);
+ void (*mips_hpt_init)(unsigned int);
+
++extern __u32 get_htscl(void)
++{
++ return timerhi;
++}
++
++static __u64 tscll_last = 0;
++
++extern __u64 get_tscll(void)
++{
++ __u64 h = (__u64) timerhi;
++ __u32 c = read_c0_count();
++
++ h <<= 32;
++ h += c;
++
++ while (h < tscll_last)
++ h += (((__u64) 1) << 32);
++
++ tscll_last = h;
++ return h;
++}
+
+ /*
+ * timeofday services, for syscalls.
+@@ -761,3 +782,5 @@
+ EXPORT_SYMBOL(to_tm);
+ EXPORT_SYMBOL(rtc_set_time);
+ EXPORT_SYMBOL(rtc_get_time);
++EXPORT_SYMBOL(get_htscl);
++EXPORT_SYMBOL(get_tscll);
+diff -urN linux.old/include/asm-mips/timex.h linux.dev/include/asm-mips/timex.h
+--- linux.old/include/asm-mips/timex.h 2005-11-14 11:06:38.685263500 +0100
++++ linux.dev/include/asm-mips/timex.h 2005-11-14 11:02:21.069163500 +0100
+@@ -31,6 +31,19 @@
+ return read_c0_count();
+ }
+
++extern __u32 get_htscl(void);
++extern __u64 get_tscll(void);
++
++#define rdtsc(low, high) \
++ high = get_htscl(); \
++ low = read_c0_count();
++
++#define rdtscl(low) \
++ low = read_c0_count();
++
++#define rdtscll(val) \
++ val = get_tscll();
++
+ #define vxtime_lock() do {} while (0)
+ #define vxtime_unlock() do {} while (0)
+
+diff -urN linux.old/include/net/pkt_sched.h linux.dev/include/net/pkt_sched.h
+--- linux.old/include/net/pkt_sched.h 2005-11-14 11:06:38.709265000 +0100
++++ linux.dev/include/net/pkt_sched.h 2005-11-14 11:02:21.069163500 +0100
+@@ -5,7 +5,11 @@
+ #define PSCHED_JIFFIES 2
+ #define PSCHED_CPU 3
+
++#ifdef __mips__
++#define PSCHED_CLOCK_SOURCE PSCHED_CPU
++#else
+ #define PSCHED_CLOCK_SOURCE PSCHED_JIFFIES
++#endif
+
+ #include <linux/config.h>
+ #include <linux/types.h>
+@@ -271,7 +275,7 @@
+ #define PSCHED_US2JIFFIE(delay) (((delay)+psched_clock_per_hz-1)/psched_clock_per_hz)
+ #define PSCHED_JIFFIE2US(delay) ((delay)*psched_clock_per_hz)
+
+-#ifdef CONFIG_X86_TSC
++#if defined(CONFIG_X86_TSC) || defined(__mips__)
+
+ #define PSCHED_GET_TIME(stamp) \
+ ({ u64 __cur; \
diff --git a/target/linux/aruba-2.6/Makefile b/target/linux/aruba-2.6/Makefile
new file mode 100644
index 0000000000..7ffd11c668
--- /dev/null
+++ b/target/linux/aruba-2.6/Makefile
@@ -0,0 +1,22 @@
+#
+# 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
+
+LINUX_VERSION:=2.6.17
+LINUX_RELEASE:=1
+LINUX_KERNEL_MD5SUM:=37ddefe96625502161f075b9d907f21e
+
+include ./config
+include $(INCLUDE_DIR)/kernel.mk
+include $(INCLUDE_DIR)/kernel-build.mk
+
+$(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked
+ [ -d ../generic-$(KERNEL)/patches ] && $(PATCH) $(LINUX_DIR) ../generic-$(KERNEL)/patches $(MAKE_TRACE)
+ [ -d ./patches ] && $(PATCH) $(LINUX_DIR) ./patches $(MAKE_TRACE)
+ @$(CP) config $(LINUX_DIR)/.config
+ touch $@
+
diff --git a/target/linux/aruba-2.6/config b/target/linux/aruba-2.6/config
new file mode 100644
index 0000000000..82c42d467e
--- /dev/null
+++ b/target/linux/aruba-2.6/config
@@ -0,0 +1,1539 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Fri Aug 25 11:20:17 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+CONFIG_MACH_ARUBA=y
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IPSEC_NAT_TRAVERSAL is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_BRIDGE_NETFILTER is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NETFILTER_XTABLES=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+CONFIG_IP_NF_CT_ACCT=y
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=y
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_IPP2P=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TIME=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
+CONFIG_IP_NF_MATCH_LAYER7=m
+# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_IMQ=m
+# CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_TARGET_ROUTE=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_SAME is not set
+# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=y
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_IP_NF_SET=m
+CONFIG_IP_NF_SET_MAX=256
+CONFIG_IP_NF_SET_HASHSIZE=1024
+CONFIG_IP_NF_SET_IPMAP=m
+CONFIG_IP_NF_SET_MACIPMAP=m
+CONFIG_IP_NF_SET_PORTMAP=m
+CONFIG_IP_NF_SET_IPHASH=m
+CONFIG_IP_NF_SET_NETHASH=m
+CONFIG_IP_NF_SET_IPTREE=m
+CONFIG_IP_NF_MATCH_SET=m
+CONFIG_IP_NF_TARGET_SET=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_ESFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+# CONFIG_NET_SCH_NETEM is not set
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+# CONFIG_NET_ACT_SIMP is not set
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIVHCI is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x1fc00000
+CONFIG_MTD_PHYSMAP_LEN=0x400000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_IFB is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_IMQ=m
+# CONFIG_IMQ_BEHAVIOR_AA is not set
+# CONFIG_IMQ_BEHAVIOR_AB is not set
+CONFIG_IMQ_BEHAVIOR_BA=y
+# CONFIG_IMQ_BEHAVIOR_BB is not set
+CONFIG_IMQ_NUM_DEVS=2
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_AR2313=y
+CONFIG_IDT_RC32434_ETH=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+CONFIG_NATSEMI=y
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+# CONFIG_BCM43XX is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=m
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+# CONFIG_VIDEO_V4L1 is not set
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA2 is not set
+
+#
+# Encoders and Decoders
+#
+
+#
+# V4L USB devices
+#
+
+#
+# Radio Adapters
+#
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# PCI devices
+#
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+
+#
+# ALSA MIPS devices
+#
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=m
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
diff --git a/target/linux/aruba-2.6/patches/000-aruba.patch b/target/linux/aruba-2.6/patches/000-aruba.patch
new file mode 100644
index 0000000000..1db6831f4c
--- /dev/null
+++ b/target/linux/aruba-2.6/patches/000-aruba.patch
@@ -0,0 +1,10521 @@
+diff -Nur linux-2.6.17/arch/mips/aruba/Makefile linux-2.6.17-owrt/arch/mips/aruba/Makefile
+--- linux-2.6.17/arch/mips/aruba/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/aruba/Makefile 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,49 @@
++###############################################################################
++#
++# BRIEF MODULE DESCRIPTION
++# Makefile for IDT EB434 BSP
++#
++# Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++#
++# 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.
++#
++#
++###############################################################################
++# May 2004 rkt, neb
++#
++# Initial Release
++#
++#
++#
++###############################################################################
++
++
++# .S.s:
++# $(CPP) $(CFLAGS) $< -o $*.s
++# .S.o:
++# $(CC) $(CFLAGS) -c $< -o $*.o
++
++obj-y := prom.o setup.o irq.o time.o flash_lock.o
++obj-$(CONFIG_SERIAL_8250) += serial.o
++
++subdir-y += nvram
++obj-y += nvram/built-in.o
++
+diff -Nur linux-2.6.17/arch/mips/aruba/nvram/Makefile linux-2.6.17-owrt/arch/mips/aruba/nvram/Makefile
+--- linux-2.6.17/arch/mips/aruba/nvram/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/aruba/nvram/Makefile 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,46 @@
++###############################################################################
++#
++# BRIEF MODULE DESCRIPTION
++# Makefile for IDT EB434 nvram access routines
++#
++# Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++#
++# 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.
++#
++#
++###############################################################################
++# May 2004 rkt, neb
++#
++# Initial Release
++#
++#
++#
++###############################################################################
++
++obj-y := nvram434.o
++obj-m := $(O_TARGET)
++
++
++
++
++
++
++
+diff -Nur linux-2.6.17/arch/mips/aruba/nvram/nvram434.c linux-2.6.17-owrt/arch/mips/aruba/nvram/nvram434.c
+--- linux-2.6.17/arch/mips/aruba/nvram/nvram434.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/aruba/nvram/nvram434.c 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,392 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * nvram interface routines.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#include <linux/ctype.h>
++#include <linux/string.h>
++
++//#include <asm/ds1553rtc.h>
++#include "nvram434.h"
++#define NVRAM_BASE 0xbfff8000
++
++extern void setenv (char *e, char *v, int rewrite);
++extern void unsetenv (char *e);
++extern void mapenv (int (*func)(char *, char *));
++extern char *getenv (char *s);
++extern void purgeenv(void);
++
++static void nvram_initenv(void);
++
++static unsigned char
++nvram_getbyte(int offs)
++{
++ return(*((unsigned char*)(NVRAM_BASE + offs)));
++}
++
++static void
++nvram_setbyte(int offs, unsigned char val)
++{
++ unsigned char* nvramDataPointer = (unsigned char*)(NVRAM_BASE + offs);
++
++ *nvramDataPointer = val;
++}
++
++/*
++ * BigEndian!
++ */
++static unsigned short
++nvram_getshort(int offs)
++{
++ return((nvram_getbyte(offs) << 8) | nvram_getbyte(offs + 1));
++}
++
++static void
++nvram_setshort(int offs, unsigned short val)
++{
++ nvram_setbyte(offs, (unsigned char)((val >> 8) & 0xff));
++ nvram_setbyte(offs + 1, (unsigned char)(val & 0xff));
++}
++#if 0
++static unsigned int
++nvram_getint(int offs)
++{
++ unsigned int val;
++ val = nvram_getbyte(offs) << 24;
++ val |= nvram_getbyte(offs + 1) << 16;
++ val |= nvram_getbyte(offs + 2) << 8;
++ val |= nvram_getbyte(offs + 3);
++ return(val);
++}
++
++static void
++nvram_setint(int offs, unsigned int val)
++{
++ nvram_setbyte(offs, val >> 24);
++ nvram_setbyte(offs + 1, val >> 16);
++ nvram_setbyte(offs + 2, val >> 8);
++ nvram_setbyte(offs + 3, val);
++}
++#endif
++/*
++ * calculate NVRAM checksum
++ */
++static unsigned short
++nvram_calcsum(void)
++{
++ unsigned short sum = NV_MAGIC;
++ int i;
++
++ for (i = ENV_BASE; i < ENV_TOP; i += 2)
++ sum += nvram_getshort(i);
++ return(sum);
++}
++
++/*
++ * update the nvram checksum
++ */
++static void
++nvram_updatesum (void)
++{
++ nvram_setshort(NVOFF_CSUM, nvram_calcsum());
++}
++
++/*
++ * test validity of nvram by checksumming it
++ */
++static int
++nvram_isvalid(void)
++{
++ static int is_valid;
++
++ if (is_valid)
++ return(1);
++
++ if (nvram_getshort(NVOFF_MAGIC) != NV_MAGIC) {
++ printk("nvram_isvalid FAILED\n");
++ //nvram_initenv();
++ }
++ is_valid = 1;
++ return(1);
++}
++
++/* return nvram address of environment string */
++static int
++nvram_matchenv(char *s)
++{
++ int envsize, envp, n, i, varsize;
++ char *var;
++
++ envsize = nvram_getshort(NVOFF_ENVSIZE);
++
++ if (envsize > ENV_AVAIL)
++ return(0); /* sanity */
++
++ envp = ENV_BASE;
++
++ if ((n = strlen (s)) > 255)
++ return(0);
++
++ while (envsize > 0) {
++ varsize = nvram_getbyte(envp);
++ if (varsize == 0 || (envp + varsize) > ENV_TOP)
++ return(0); /* sanity */
++ for (i = envp + 1, var = s; i <= envp + n; i++, var++) {
++ char c1 = nvram_getbyte(i);
++ char c2 = *var;
++ if (islower(c1))
++ c1 = toupper(c1);
++ if (islower(c2))
++ c2 = toupper(c2);
++ if (c1 != c2)
++ break;
++ }
++ if (i > envp + n) { /* match so far */
++ if (n == varsize - 1) /* match on boolean */
++ return(envp);
++ if (nvram_getbyte(i) == '=') /* exact match on variable */
++ return(envp);
++ }
++ envsize -= varsize;
++ envp += varsize;
++ }
++ return(0);
++}
++
++static void nvram_initenv(void)
++{
++ nvram_setshort(NVOFF_MAGIC, NV_MAGIC);
++ nvram_setshort(NVOFF_ENVSIZE, 0);
++
++ nvram_updatesum();
++}
++
++static void
++nvram_delenv(char *s)
++{
++ int nenvp, envp, envsize, nbytes;
++
++ envp = nvram_matchenv(s);
++ if (envp == 0)
++ return;
++
++ nenvp = envp + nvram_getbyte(envp);
++ envsize = nvram_getshort(NVOFF_ENVSIZE);
++ nbytes = envsize - (nenvp - ENV_BASE);
++ nvram_setshort(NVOFF_ENVSIZE, envsize - (nenvp - envp));
++ while (nbytes--) {
++ nvram_setbyte(envp, nvram_getbyte(nenvp));
++ envp++;
++ nenvp++;
++ }
++ nvram_updatesum();
++}
++
++static int
++nvram_setenv(char *s, char *v)
++{
++ int ns, nv, total;
++ int envp;
++
++ if (!nvram_isvalid())
++ return(-1);
++
++ nvram_delenv(s);
++ ns = strlen(s);
++ if (ns == 0)
++ return (-1);
++ if (v && *v) {
++ nv = strlen(v);
++ total = ns + nv + 2;
++ }
++ else {
++ nv = 0;
++ total = ns + 1;
++ }
++ if (total > 255 || total > ENV_AVAIL - nvram_getshort(NVOFF_ENVSIZE))
++ return(-1);
++
++ envp = ENV_BASE + nvram_getshort(NVOFF_ENVSIZE);
++
++ nvram_setbyte(envp, (unsigned char) total);
++ envp++;
++
++ while (ns--) {
++ nvram_setbyte(envp, *s);
++ envp++;
++ s++;
++ }
++
++ if (nv) {
++ nvram_setbyte(envp, '=');
++ envp++;
++ while (nv--) {
++ nvram_setbyte(envp, *v);
++ envp++;
++ v++;
++ }
++ }
++ nvram_setshort(NVOFF_ENVSIZE, envp-ENV_BASE);
++ nvram_updatesum();
++ return 0;
++}
++
++static char *
++nvram_getenv(char *s)
++{
++ static char buf[256]; /* FIXME: this cannot be static */
++ int envp, ns, nbytes, i;
++
++ if (!nvram_isvalid())
++ return "INVALID NVRAM"; //((char *)0);
++
++ envp = nvram_matchenv(s);
++ if (envp == 0)
++ return "NOT FOUND"; //((char *)0);
++ ns = strlen(s);
++ if (nvram_getbyte(envp) == ns + 1) /* boolean */
++ buf[0] = '\0';
++ else {
++ nbytes = nvram_getbyte(envp) - (ns + 2);
++ envp += ns + 2;
++ for (i = 0; i < nbytes; i++)
++ buf[i] = nvram_getbyte(envp++);
++ buf[i] = '\0';
++ }
++ return(buf);
++}
++
++static void
++nvram_unsetenv(char *s)
++{
++ if (!nvram_isvalid())
++ return;
++
++ nvram_delenv(s);
++}
++
++/*
++ * apply func to each string in environment
++ */
++static void
++nvram_mapenv(int (*func)(char *, char *))
++{
++ int envsize, envp, n, i, seeneql;
++ char name[256], value[256];
++ char c, *s;
++
++ if (!nvram_isvalid())
++ return;
++
++ envsize = nvram_getshort(NVOFF_ENVSIZE);
++ envp = ENV_BASE;
++
++ while (envsize > 0) {
++ value[0] = '\0';
++ seeneql = 0;
++ s = name;
++ n = nvram_getbyte(envp);
++ for (i = envp + 1; i < envp + n; i++) {
++ c = nvram_getbyte(i);
++ if ((c == '=') && !seeneql) {
++ *s = '\0';
++ s = value;
++ seeneql = 1;
++ continue;
++ }
++ *s++ = c;
++ }
++ *s = '\0';
++ (*func)(name, value);
++ envsize -= n;
++ envp += n;
++ }
++}
++#if 0
++static unsigned int
++digit(char c)
++{
++ if ('0' <= c && c <= '9')
++ return (c - '0');
++ if ('A' <= c && c <= 'Z')
++ return (10 + c - 'A');
++ if ('a' <= c && c <= 'z')
++ return (10 + c - 'a');
++ return (~0);
++}
++#endif
++/*
++ * Wrappers to allow 'special' environment variables to get processed
++ */
++void
++setenv(char *e, char *v, int rewrite)
++{
++ if (nvram_getenv(e) && !rewrite)
++ return;
++
++ nvram_setenv(e, v);
++}
++
++char *
++getenv(char *e)
++{
++ return(nvram_getenv(e));
++}
++
++void
++unsetenv(char *e)
++{
++ nvram_unsetenv(e);
++}
++
++void
++purgeenv()
++{
++ int i;
++ unsigned char* nvramDataPointer = (unsigned char*)(NVRAM_BASE);
++
++ for (i = ENV_BASE; i < ENV_TOP; i++)
++ *nvramDataPointer++ = 0;
++ nvram_setshort(NVOFF_MAGIC, NV_MAGIC);
++ nvram_setshort(NVOFF_ENVSIZE, 0);
++ nvram_setshort(NVOFF_CSUM, NV_MAGIC);
++}
++
++void
++mapenv(int (*func)(char *, char *))
++{
++ nvram_mapenv(func);
++}
+diff -Nur linux-2.6.17/arch/mips/aruba/nvram/nvram434.h linux-2.6.17-owrt/arch/mips/aruba/nvram/nvram434.h
+--- linux-2.6.17/arch/mips/aruba/nvram/nvram434.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/aruba/nvram/nvram434.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,66 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * nvram definitions.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++
++#ifndef _NVRAM_
++#define _NVRAM_
++#define NVOFFSET 0 /* use all of NVRAM */
++
++/* Offsets to reserved locations */
++ /* size description */
++#define NVOFF_MAGIC (NVOFFSET + 0) /* 2 magic value */
++#define NVOFF_CSUM (NVOFFSET + 2) /* 2 NVRAM environment checksum */
++#define NVOFF_ENVSIZE (NVOFFSET + 4) /* 2 size of 'environment' */
++#define NVOFF_TEST (NVOFFSET + 5) /* 1 cold start test byte */
++#define NVOFF_ETHADDR (NVOFFSET + 6) /* 6 decoded ethernet address */
++#define NVOFF_UNUSED (NVOFFSET + 12) /* 0 current end of table */
++
++#define NV_MAGIC 0xdeaf /* nvram magic number */
++#define NV_RESERVED 6 /* number of reserved bytes */
++
++#undef NVOFF_ETHADDR
++#define NVOFF_ETHADDR (NVOFFSET + NV_RESERVED - 6)
++
++/* number of bytes available for environment */
++#define ENV_BASE (NVOFFSET + NV_RESERVED)
++#define ENV_TOP 0x2000
++#define ENV_AVAIL (ENV_TOP - ENV_BASE)
++
++#endif /* _NVRAM_ */
++
++
+diff -Nur linux-2.6.17/arch/mips/aruba/prom.c linux-2.6.17-owrt/arch/mips/aruba/prom.c
+--- linux-2.6.17/arch/mips/aruba/prom.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/aruba/prom.c 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,111 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * prom interface routines
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/console.h>
++#include <asm/bootinfo.h>
++#include <linux/bootmem.h>
++#include <linux/ioport.h>
++#include <linux/serial.h>
++#include <linux/serialP.h>
++#include <asm/serial.h>
++#include <linux/ioport.h>
++
++unsigned int idt_cpu_freq;
++EXPORT_SYMBOL(idt_cpu_freq);
++
++unsigned int arch_has_pci=0;
++
++/* Kernel Boot parameters */
++static unsigned char bootparm[] = "console=ttyS0,9600 root=/dev/mtdblock1 rootfstype=jffs2";
++
++extern unsigned long mips_machgroup;
++extern unsigned long mips_machtype;
++
++extern void setup_serial_port(void);
++extern char * getenv(char *e);
++
++/* IDT 79EB434 memory map -- we really should be auto sizing it */
++#define RAM_SIZE 32*1024*1024
++
++char *__init prom_getcmdline(void)
++{
++ return &(arcs_cmdline[0]);
++}
++
++void __init prom_init(void)
++{
++ char *boardname;
++ sprintf(arcs_cmdline, "%s", bootparm);
++
++ /* set our arch type */
++ mips_machgroup = MACH_GROUP_ARUBA;
++ mips_machtype = MACH_ARUBA_UNKNOWN;
++
++ boardname=getenv("boardname");
++
++ if (!strcmp(boardname,"Muscat")) {
++ mips_machtype = MACH_ARUBA_AP70;
++ idt_cpu_freq = 133000000;
++ arch_has_pci=1;
++ } else if (!strcmp(boardname,"Mataro")) {
++ mips_machtype = MACH_ARUBA_AP65;
++ idt_cpu_freq = 110000000;
++ } else if (!strcmp(boardname,"Merlot")) {
++ mips_machtype = MACH_ARUBA_AP60;
++ idt_cpu_freq = 90000000;
++ }
++
++ /* turn on the console */
++ setup_serial_port();
++
++ /*
++ * give all RAM to boot allocator,
++ * except where the kernel was loaded
++ */
++ add_memory_region(0,RAM_SIZE,BOOT_MEM_RAM);
++}
++
++void prom_free_prom_memory(void)
++{
++ printk("stubbed prom_free_prom_memory()\n");
++}
+diff -Nur linux-2.6.17/arch/mips/aruba/serial.c linux-2.6.17-owrt/arch/mips/aruba/serial.c
+--- linux-2.6.17/arch/mips/aruba/serial.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/aruba/serial.c 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,94 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Serial port initialisation.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/pci.h>
++#include <linux/interrupt.h>
++#include <linux/tty.h>
++#include <linux/serial.h>
++#include <linux/serial_core.h>
++
++#include <asm/time.h>
++#include <asm/cpu.h>
++#include <asm/bootinfo.h>
++#include <asm/irq.h>
++#include <asm/serial.h>
++
++#include <asm/idt-boards/rc32434/rc32434.h>
++
++extern int __init early_serial_setup(struct uart_port *port);
++
++#define BASE_BAUD (1843200 / 16)
++
++extern unsigned int idt_cpu_freq;
++
++extern int __init setup_serial_port(void)
++{
++ static struct uart_port serial_req[2];
++
++ memset(serial_req, 0, sizeof(serial_req));
++ serial_req[0].type = PORT_16550A;
++ serial_req[0].line = 0;
++ serial_req[0].flags = STD_COM_FLAGS;
++ serial_req[0].iotype = SERIAL_IO_MEM;
++ serial_req[0].regshift = 2;
++
++ switch (mips_machtype) {
++ case MACH_ARUBA_AP70:
++ serial_req[0].irq = 104;
++ serial_req[0].mapbase = KSEG1ADDR(0x18058003);
++ serial_req[0].membase = (char *) KSEG1ADDR(0x18058003);
++ serial_req[0].uartclk = idt_cpu_freq;
++ break;
++ case MACH_ARUBA_AP65:
++ case MACH_ARUBA_AP60:
++ default:
++ serial_req[0].irq = 12;
++ serial_req[0].mapbase = KSEG1ADDR(0xbc000003);
++ serial_req[0].membase = (char *) KSEG1ADDR(0xbc000003);
++ serial_req[0].uartclk = idt_cpu_freq / 2;
++ break;
++ }
++
++ early_serial_setup(&serial_req[0]);
++
++ return(0);
++}
+diff -Nur linux-2.6.17/arch/mips/aruba/setup.c linux-2.6.17-owrt/arch/mips/aruba/setup.c
+--- linux-2.6.17/arch/mips/aruba/setup.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/aruba/setup.c 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,134 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * setup routines for IDT EB434 boards
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/irq.h>
++#include <asm/bootinfo.h>
++#include <asm/io.h>
++#include <linux/ioport.h>
++#include <asm/mipsregs.h>
++#include <asm/pgtable.h>
++#include <asm/reboot.h>
++#include <asm/addrspace.h> /* for KSEG1ADDR() */
++#include <asm/idt-boards/rc32434/rc32434.h>
++#include <linux/pm.h>
++
++extern char *__init prom_getcmdline(void);
++
++extern void (*board_time_init) (void);
++extern void (*board_timer_setup) (struct irqaction * irq);
++extern void aruba_time_init(void);
++extern void aruba_timer_setup(struct irqaction *irq);
++extern void aruba_reset(void);
++
++#define epldMask ((volatile unsigned char *)0xB900000d)
++
++static void aruba_machine_restart(char *command)
++{
++ switch (mips_machtype) {
++ case MACH_ARUBA_AP70:
++ *(volatile u32 *)KSEG1ADDR(0x18008000) = 0x80000001;
++ break;
++ case MACH_ARUBA_AP65:
++ case MACH_ARUBA_AP60:
++ default:
++ /* Reset*/
++ *((volatile u32 *)KSEG1ADDR(0x1c003020)) = 0x00080350; // reset everything in sight
++ udelay(100);
++ *((volatile u32 *)KSEG1ADDR(0x1c003020)) = 0; // reset everything in sight
++ udelay(100);
++ *((volatile u32 *)KSEG1ADDR(0x1c003020)) = 0x3; // cold reset the cpu & system
++ break;
++ }
++}
++
++static void aruba_machine_halt(void)
++{
++ for (;;) continue;
++}
++
++extern char * getenv(char *e);
++extern void unlock_ap60_70_flash(void);
++
++void __init plat_setup(void)
++{
++ board_time_init = aruba_time_init;
++
++ board_timer_setup = aruba_timer_setup;
++
++ _machine_restart = aruba_machine_restart;
++ _machine_halt = aruba_machine_halt;
++ pm_power_off = aruba_machine_halt;
++
++ set_io_port_base(KSEG1);
++
++ /* Enable PCI interrupts in EPLD Mask register */
++ *epldMask = 0x0;
++ *(epldMask + 1) = 0x0;
++
++ write_c0_wired(0);
++ unlock_ap60_70_flash();
++
++ printk("BOARD - %s\n",getenv("boardname"));
++
++ return 0;
++}
++
++int page_is_ram(unsigned long pagenr)
++{
++ return 1;
++}
++
++const char *get_system_type(void)
++{
++ switch (mips_machtype) {
++ case MACH_ARUBA_AP70:
++ return "Aruba AP70";
++ case MACH_ARUBA_AP65:
++ return "Aruba AP65";
++ case MACH_ARUBA_AP60:
++ return "Aruba AP60/AP61";
++ default:
++ return "Aruba UNKNOWN";
++ }
++}
++
++EXPORT_SYMBOL(get_system_type);
+diff -Nur linux-2.6.17/arch/mips/aruba/time.c linux-2.6.17-owrt/arch/mips/aruba/time.c
+--- linux-2.6.17/arch/mips/aruba/time.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/aruba/time.c 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,110 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * timer routines for IDT EB434 boards
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/kernel_stat.h>
++#include <linux/sched.h>
++#include <linux/spinlock.h>
++#include <linux/mc146818rtc.h>
++#include <linux/irq.h>
++#include <linux/timex.h>
++
++#include <linux/param.h>
++#include <asm/mipsregs.h>
++#include <asm/ptrace.h>
++#include <asm/time.h>
++#include <asm/hardirq.h>
++
++#include <asm/mipsregs.h>
++#include <asm/ptrace.h>
++#include <asm/debug.h>
++#include <asm/time.h>
++
++#include <asm/idt-boards/rc32434/rc32434.h>
++
++static unsigned long r4k_offset; /* Amount to incr compare reg each time */
++static unsigned long r4k_cur; /* What counter should be at next timer irq */
++
++extern unsigned int idt_cpu_freq;
++
++static unsigned long __init cal_r4koff(void)
++{
++ mips_hpt_frequency = idt_cpu_freq * IDT_CLOCK_MULT / 2;
++ return (mips_hpt_frequency / HZ);
++}
++
++void __init aruba_time_init(void)
++{
++ unsigned int est_freq, flags;
++ local_irq_save(flags);
++
++ printk("calculating r4koff... ");
++ r4k_offset = cal_r4koff();
++ printk("%08lx(%d)\n", r4k_offset, (int)r4k_offset);
++
++ est_freq = 2 * r4k_offset * HZ;
++ est_freq += 5000; /* round */
++ est_freq -= est_freq % 10000;
++ printk("CPU frequency %d.%02d MHz\n", est_freq / 1000000,
++ (est_freq % 1000000) * 100 / 1000000);
++ local_irq_restore(flags);
++
++}
++
++void __init aruba_timer_setup(struct irqaction *irq)
++{
++ /* we are using the cpu counter for timer interrupts */
++ setup_irq(MIPS_CPU_TIMER_IRQ, irq);
++
++ /* to generate the first timer interrupt */
++ r4k_cur = (read_c0_count() + r4k_offset);
++ write_c0_compare(r4k_cur);
++
++}
++
++asmlinkage void aruba_timer_interrupt(struct pt_regs *regs)
++{
++ int irq = MIPS_CPU_TIMER_IRQ;
++
++ irq_enter();
++ kstat_this_cpu.irqs[irq]++;
++
++ timer_interrupt(irq, NULL, regs);
++ irq_exit();
++}
+diff -Nur linux-2.6.17/arch/mips/Kconfig linux-2.6.17-owrt/arch/mips/Kconfig
+--- linux-2.6.17/arch/mips/Kconfig 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/arch/mips/Kconfig 2006-06-18 12:44:28.000000000 +0200
+@@ -227,6 +227,17 @@
+ either a NEC Vr5432 or QED RM5231. Say Y here if you wish to build
+ a kernel for this platform.
+
++config MACH_ARUBA
++ bool "Support for the ARUBA product line"
++ select DMA_NONCOHERENT
++ select CPU_HAS_PREFETCH
++ select HW_HAS_PCI
++ select SWAP_IO_SPACE
++ select SYS_SUPPORTS_32BIT_KERNEL
++ select SYS_HAS_CPU_MIPS32_R1
++ select SYS_SUPPORTS_BIG_ENDIAN
++
++
+ config MACH_JAZZ
+ bool "Jazz family of machines"
+ select ARC
+diff -Nur linux-2.6.17/arch/mips/Makefile linux-2.6.17-owrt/arch/mips/Makefile
+--- linux-2.6.17/arch/mips/Makefile 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/arch/mips/Makefile 2006-06-18 12:44:28.000000000 +0200
+@@ -145,6 +145,14 @@
+ #
+
+ #
++# Aruba
++#
++
++core-$(CONFIG_MACH_ARUBA) += arch/mips/aruba/
++cflags-$(CONFIG_MACH_ARUBA) += -Iinclude/asm-mips/aruba
++load-$(CONFIG_MACH_ARUBA) += 0x80100000
++
++#
+ # Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
+ #
+ core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/
+diff -Nur linux-2.6.17/arch/mips/mm/tlbex.c linux-2.6.17-owrt/arch/mips/mm/tlbex.c
+--- linux-2.6.17/arch/mips/mm/tlbex.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/arch/mips/mm/tlbex.c 2006-06-18 12:48:27.000000000 +0200
+@@ -876,7 +876,6 @@
+ case CPU_R10000:
+ case CPU_R12000:
+ case CPU_R14000:
+- case CPU_4KC:
+ case CPU_SB1:
+ case CPU_SB1A:
+ case CPU_4KSC:
+@@ -904,6 +903,7 @@
+ tlbw(p);
+ break;
+
++ case CPU_4KC:
+ case CPU_4KEC:
+ case CPU_24K:
+ case CPU_34K:
+diff -Nur linux-2.6.17/drivers/net/Kconfig linux-2.6.17-owrt/drivers/net/Kconfig
+--- linux-2.6.17/drivers/net/Kconfig 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/drivers/net/Kconfig 2006-06-18 12:44:28.000000000 +0200
+@@ -187,6 +187,13 @@
+
+ source "drivers/net/arm/Kconfig"
+
++config IDT_RC32434_ETH
++ tristate "IDT RC32434 Local Ethernet support"
++ depends on NET_ETHERNET
++ help
++ IDT RC32434 has one local ethernet port. Say Y here to enable it.
++ To compile this driver as a module, choose M here.
++
+ config MACE
+ tristate "MACE (Power Mac ethernet) support"
+ depends on NET_ETHERNET && PPC_PMAC && PPC32
+diff -Nur linux-2.6.17/drivers/net/Makefile linux-2.6.17-owrt/drivers/net/Makefile
+--- linux-2.6.17/drivers/net/Makefile 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/drivers/net/Makefile 2006-06-18 12:44:28.000000000 +0200
+@@ -38,6 +38,7 @@
+
+ obj-$(CONFIG_OAKNET) += oaknet.o 8390.o
+
++obj-$(CONFIG_IDT_RC32434_ETH) += rc32434_eth.o
+ obj-$(CONFIG_DGRS) += dgrs.o
+ obj-$(CONFIG_VORTEX) += 3c59x.o
+ obj-$(CONFIG_TYPHOON) += typhoon.o
+diff -Nur linux-2.6.17/drivers/net/natsemi.c linux-2.6.17-owrt/drivers/net/natsemi.c
+--- linux-2.6.17/drivers/net/natsemi.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/drivers/net/natsemi.c 2006-06-18 12:44:28.000000000 +0200
+@@ -771,6 +771,49 @@
+ static int netdev_get_eeprom(struct net_device *dev, u8 *buf);
+ static struct ethtool_ops ethtool_ops;
+
++#ifdef CONFIG_MACH_ARUBA
++
++#include <linux/ctype.h>
++
++#ifndef ERR
++#define ERR(fmt, args...) printk("%s: " fmt, __func__, ##args)
++#endif
++
++static int parse_mac_addr(struct net_device *dev, char* macstr)
++{
++ int i, j;
++ unsigned char result, value;
++
++ for (i=0; i<6; i++) {
++ result = 0;
++ if (i != 5 && *(macstr+2) != ':') {
++ ERR("invalid mac address format: %d %c\n",
++ i, *(macstr+2));
++ return -EINVAL;
++ }
++ for (j=0; j<2; j++) {
++ if (isxdigit(*macstr) && (value = isdigit(*macstr) ? *macstr-'0' :
++ toupper(*macstr)-'A'+10) < 16) {
++ result = result*16 + value;
++ macstr++;
++ }
++ else {
++ ERR("invalid mac address "
++ "character: %c\n", *macstr);
++ return -EINVAL;
++ }
++ }
++
++ macstr++;
++ dev->dev_addr[i] = result;
++ }
++
++ dev->dev_addr[5]++;
++ return 0;
++}
++
++#endif
++
+ static inline void __iomem *ns_ioaddr(struct net_device *dev)
+ {
+ return (void __iomem *) dev->base_addr;
+@@ -871,6 +914,7 @@
+ goto err_ioremap;
+ }
+
++#ifndef CONFIG_MACH_ARUBA
+ /* Work around the dropped serial bit. */
+ prev_eedata = eeprom_read(ioaddr, 6);
+ for (i = 0; i < 3; i++) {
+@@ -879,6 +923,19 @@
+ dev->dev_addr[i*2+1] = eedata >> 7;
+ prev_eedata = eedata;
+ }
++#else
++ {
++ char mac[32];
++ unsigned char def_mac[6] = {00, 0x0b, 0x86, 0xba, 0xdb, 0xad};
++ extern char *getenv(char *e);
++ memset(mac, 0, 32);
++ memcpy(mac, getenv("ethaddr"), 17);
++ if (parse_mac_addr(dev, mac)){
++ printk("%s: MAC address not found\n", __func__);
++ memcpy(dev->dev_addr, def_mac, 6);
++ }
++ }
++#endif
+
+ dev->base_addr = (unsigned long __force) ioaddr;
+ dev->irq = irq;
+diff -Nur linux-2.6.17/drivers/net/rc32434_eth.c linux-2.6.17-owrt/drivers/net/rc32434_eth.c
+--- linux-2.6.17/drivers/net/rc32434_eth.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/drivers/net/rc32434_eth.c 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,1273 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Driver for the IDT RC32434 on-chip ethernet controller.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Based on the driver developed by B. Maruthanayakam, H. Kou and others.
++ *
++ * Aug 2004 Sadik
++ *
++ * Added NAPI
++ *
++ **************************************************************************
++ */
++
++#include <linux/config.h>
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/moduleparam.h>
++#include <linux/sched.h>
++#include <linux/ctype.h>
++#include <linux/types.h>
++#include <linux/fcntl.h>
++#include <linux/interrupt.h>
++#include <linux/ptrace.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/proc_fs.h>
++#include <linux/in.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++#include <linux/errno.h>
++#include <asm/bootinfo.h>
++#include <asm/system.h>
++#include <asm/bitops.h>
++#include <asm/pgtable.h>
++#include <asm/segment.h>
++#include <asm/io.h>
++#include <asm/dma.h>
++
++#include "rc32434_eth.h"
++
++#define DRIVER_VERSION "(mar2904)"
++
++#define DRIVER_NAME "rc32434 Ethernet driver. " DRIVER_VERSION
++
++
++#define STATION_ADDRESS_HIGH(dev) (((dev)->dev_addr[0] << 8) | \
++ ((dev)->dev_addr[1]))
++#define STATION_ADDRESS_LOW(dev) (((dev)->dev_addr[2] << 24) | \
++ ((dev)->dev_addr[3] << 16) | \
++ ((dev)->dev_addr[4] << 8) | \
++ ((dev)->dev_addr[5]))
++
++#define MII_CLOCK 1250000 /* no more than 2.5MHz */
++static char mac0[18] = "08:00:06:05:40:01";
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,52)
++module_param_string(mac0, mac0, 18, 0);
++#else
++MODULE_PARM(mac0, "c18");
++#endif
++MODULE_PARM_DESC(mac0, "MAC address for RC32434 ethernet0");
++
++static struct rc32434_if_t {
++ char *name;
++ struct net_device *dev;
++ char* mac_str;
++ int weight;
++ u32 iobase;
++ u32 rxdmabase;
++ u32 txdmabase;
++ int rx_dma_irq;
++ int tx_dma_irq;
++ int rx_ovr_irq;
++ int tx_und_irq;
++} rc32434_iflist[] =
++{
++ {
++ "rc32434_eth0", NULL, mac0,
++ 64,
++ ETH0_PhysicalAddress,
++ ETH0_RX_DMA_ADDR,
++ ETH0_TX_DMA_ADDR,
++ ETH0_DMA_RX_IRQ,
++ ETH0_DMA_TX_IRQ,
++ ETH0_RX_OVR_IRQ,
++ ETH0_TX_UND_IRQ
++ }
++};
++
++
++static int parse_mac_addr(struct net_device *dev, char* macstr)
++{
++ int i, j;
++ unsigned char result, value;
++
++ for (i=0; i<6; i++) {
++ result = 0;
++ if (i != 5 && *(macstr+2) != ':') {
++ ERR("invalid mac address format: %d %c\n",
++ i, *(macstr+2));
++ return -EINVAL;
++ }
++ for (j=0; j<2; j++) {
++ if (isxdigit(*macstr) && (value = isdigit(*macstr) ? *macstr-'0' :
++ toupper(*macstr)-'A'+10) < 16) {
++ result = result*16 + value;
++ macstr++;
++ }
++ else {
++ ERR("invalid mac address "
++ "character: %c\n", *macstr);
++ return -EINVAL;
++ }
++ }
++
++ macstr++;
++ dev->dev_addr[i] = result;
++ }
++
++ return 0;
++}
++
++
++
++static inline void rc32434_abort_tx(struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ rc32434_abort_dma(dev, lp->tx_dma_regs);
++
++}
++
++static inline void rc32434_abort_rx(struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ rc32434_abort_dma(dev, lp->rx_dma_regs);
++
++}
++
++static inline void rc32434_start_tx(struct rc32434_local *lp, volatile DMAD_t td)
++{
++ rc32434_start_dma(lp->tx_dma_regs, CPHYSADDR(td));
++}
++
++static inline void rc32434_start_rx(struct rc32434_local *lp, volatile DMAD_t rd)
++{
++ rc32434_start_dma(lp->rx_dma_regs, CPHYSADDR(rd));
++}
++
++static inline void rc32434_chain_tx(struct rc32434_local *lp, volatile DMAD_t td)
++{
++ rc32434_chain_dma(lp->tx_dma_regs, CPHYSADDR(td));
++}
++
++static inline void rc32434_chain_rx(struct rc32434_local *lp, volatile DMAD_t rd)
++{
++ rc32434_chain_dma(lp->rx_dma_regs, CPHYSADDR(rd));
++}
++
++#ifdef RC32434_PROC_DEBUG
++static int rc32434_read_proc(char *buf, char **start, off_t fpos,
++ int length, int *eof, void *data)
++{
++ struct net_device *dev = (struct net_device *)data;
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ int len = 0;
++
++ /* print out header */
++ len += sprintf(buf + len, "\n\tRC32434 Ethernet Debug\n\n");
++ len += sprintf (buf + len,
++ "DMA halt count = %10d, DMA run count = %10d\n",
++ lp->dma_halt_cnt, lp->dma_run_cnt);
++
++ if (fpos >= len) {
++ *start = buf;
++ *eof = 1;
++ return 0;
++ }
++ *start = buf + fpos;
++
++ if ((len -= fpos) > length)
++ return length;
++ *eof = 1;
++
++ return len;
++
++}
++#endif
++
++
++/*
++ * Restart the RC32434 ethernet controller.
++ */
++static int rc32434_restart(struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++
++ /*
++ * Disable interrupts
++ */
++ disable_irq(lp->rx_irq);
++ disable_irq(lp->tx_irq);
++#ifdef RC32434_REVISION
++ disable_irq(lp->ovr_irq);
++#endif
++ disable_irq(lp->und_irq);
++
++ /* Mask F E bit in Tx DMA */
++ rc32434_writel(rc32434_readl(&lp->tx_dma_regs->dmasm) | DMASM_f_m | DMASM_e_m, &lp->tx_dma_regs->dmasm);
++ /* Mask D H E bit in Rx DMA */
++ rc32434_writel(rc32434_readl(&lp->rx_dma_regs->dmasm) | DMASM_d_m | DMASM_h_m | DMASM_e_m, &lp->rx_dma_regs->dmasm);
++
++ rc32434_init(dev);
++ rc32434_multicast_list(dev);
++
++ enable_irq(lp->und_irq);
++#ifdef RC32434_REVISION
++ enable_irq(lp->ovr_irq);
++#endif
++ enable_irq(lp->tx_irq);
++ enable_irq(lp->rx_irq);
++
++ return 0;
++}
++
++int rc32434_init_module(void)
++{
++#ifdef CONFIG_MACH_ARUBA
++ if (mips_machtype != MACH_ARUBA_AP70)
++ return 1;
++#endif
++
++ printk(KERN_INFO DRIVER_NAME " \n");
++ return rc32434_probe(0);
++}
++
++static int rc32434_probe(int port_num)
++{
++ struct rc32434_if_t *bif = &rc32434_iflist[port_num];
++ struct rc32434_local *lp = NULL;
++ struct net_device *dev = NULL;
++ int i, retval,err;
++
++ dev = alloc_etherdev(sizeof(struct rc32434_local));
++ if(!dev) {
++ ERR("rc32434_eth: alloc_etherdev failed\n");
++ return -1;
++ }
++
++ SET_MODULE_OWNER(dev);
++ bif->dev = dev;
++
++#ifdef CONFIG_MACH_ARUBA
++ {
++ extern char * getenv(char *e);
++ memcpy(bif->mac_str, getenv("ethaddr"), 17);
++ }
++#endif
++
++ printk("mac: %s\n", bif->mac_str);
++ if ((retval = parse_mac_addr(dev, bif->mac_str))) {
++ ERR("MAC address parse failed\n");
++ free_netdev(dev);
++ return -1;
++ }
++
++
++ /* Initialize the device structure. */
++ if (dev->priv == NULL) {
++ lp = (struct rc32434_local *)kmalloc(sizeof(*lp), GFP_KERNEL);
++ memset(lp, 0, sizeof(struct rc32434_local));
++ }
++ else {
++ lp = (struct rc32434_local *)dev->priv;
++ }
++
++ lp->rx_irq = bif->rx_dma_irq;
++ lp->tx_irq = bif->tx_dma_irq;
++ lp->ovr_irq = bif->rx_ovr_irq;
++ lp->und_irq = bif->tx_und_irq;
++
++ lp->eth_regs = ioremap_nocache(bif->iobase, sizeof(*lp->eth_regs));
++
++ if (!lp->eth_regs) {
++ ERR("Can't remap eth registers\n");
++ retval = -ENXIO;
++ goto probe_err_out;
++ }
++
++ lp->rx_dma_regs = ioremap_nocache(bif->rxdmabase, sizeof(struct DMA_Chan_s));
++
++ if (!lp->rx_dma_regs) {
++ ERR("Can't remap Rx DMA registers\n");
++ retval = -ENXIO;
++ goto probe_err_out;
++ }
++ lp->tx_dma_regs = ioremap_nocache(bif->txdmabase,sizeof(struct DMA_Chan_s));
++
++ if (!lp->tx_dma_regs) {
++ ERR("Can't remap Tx DMA registers\n");
++ retval = -ENXIO;
++ goto probe_err_out;
++ }
++
++#ifdef RC32434_PROC_DEBUG
++ lp->ps = create_proc_read_entry (bif->name, 0, proc_net,
++ rc32434_read_proc, dev);
++#endif
++
++ lp->td_ring = (DMAD_t)kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL);
++ if (!lp->td_ring) {
++ ERR("Can't allocate descriptors\n");
++ retval = -ENOMEM;
++ goto probe_err_out;
++ }
++
++ dma_cache_inv((unsigned long)(lp->td_ring), TD_RING_SIZE + RD_RING_SIZE);
++
++ /* now convert TD_RING pointer to KSEG1 */
++ lp->td_ring = (DMAD_t )KSEG1ADDR(lp->td_ring);
++ lp->rd_ring = &lp->td_ring[RC32434_NUM_TDS];
++
++
++ spin_lock_init(&lp->lock);
++
++ dev->base_addr = bif->iobase;
++ /* just use the rx dma irq */
++ dev->irq = bif->rx_dma_irq;
++
++ dev->priv = lp;
++
++ dev->open = rc32434_open;
++ dev->stop = rc32434_close;
++ dev->hard_start_xmit = rc32434_send_packet;
++ dev->get_stats = rc32434_get_stats;
++ dev->set_multicast_list = &rc32434_multicast_list;
++ dev->tx_timeout = rc32434_tx_timeout;
++ dev->watchdog_timeo = RC32434_TX_TIMEOUT;
++
++#ifdef CONFIG_IDT_USE_NAPI
++ dev->poll = rc32434_poll;
++ dev->weight = bif->weight;
++ printk("Using NAPI with weight %d\n",dev->weight);
++#else
++ lp->rx_tasklet = kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
++ tasklet_init(lp->rx_tasklet, rc32434_rx_tasklet, (unsigned long)dev);
++#endif
++ lp->tx_tasklet = kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
++ tasklet_init(lp->tx_tasklet, rc32434_tx_tasklet, (unsigned long)dev);
++
++ if ((err = register_netdev(dev))) {
++ printk(KERN_ERR "rc32434 ethernet. Cannot register net device %d\n", err);
++ free_netdev(dev);
++ retval = -EINVAL;
++ goto probe_err_out;
++ }
++
++ INFO("Rx IRQ %d, Tx IRQ %d, ", bif->rx_dma_irq, bif->tx_dma_irq);
++ for (i = 0; i < 6; i++) {
++ printk("%2.2x", dev->dev_addr[i]);
++ if (i<5)
++ printk(":");
++ }
++ printk("\n");
++
++ return 0;
++
++ probe_err_out:
++ rc32434_cleanup_module();
++ ERR(" failed. Returns %d\n", retval);
++ return retval;
++
++}
++
++
++static void rc32434_cleanup_module(void)
++{
++ int i;
++
++ for (i = 0; rc32434_iflist[i].iobase; i++) {
++ struct rc32434_if_t * bif = &rc32434_iflist[i];
++ if (bif->dev != NULL) {
++ struct rc32434_local *lp = (struct rc32434_local *)bif->dev->priv;
++ if (lp != NULL) {
++ if (lp->eth_regs)
++ iounmap((void*)lp->eth_regs);
++ if (lp->rx_dma_regs)
++ iounmap((void*)lp->rx_dma_regs);
++ if (lp->tx_dma_regs)
++ iounmap((void*)lp->tx_dma_regs);
++ if (lp->td_ring)
++ kfree((void*)KSEG0ADDR(lp->td_ring));
++
++#ifdef RC32434_PROC_DEBUG
++ if (lp->ps) {
++ remove_proc_entry(bif->name, proc_net);
++ }
++#endif
++ kfree(lp);
++ }
++
++ unregister_netdev(bif->dev);
++ free_netdev(bif->dev);
++ kfree(bif->dev);
++ }
++ }
++}
++
++
++
++static int rc32434_open(struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++
++ /* Initialize */
++ if (rc32434_init(dev)) {
++ ERR("Error: cannot open the Ethernet device\n");
++ return -EAGAIN;
++ }
++
++ /* Install the interrupt handler that handles the Done Finished Ovr and Und Events */
++ if (request_irq(lp->rx_irq, &rc32434_rx_dma_interrupt,
++ SA_SHIRQ | SA_INTERRUPT,
++ "rc32434 ethernet Rx", dev)) {
++ ERR(": unable to get Rx DMA IRQ %d\n",
++ lp->rx_irq);
++ return -EAGAIN;
++ }
++ if (request_irq(lp->tx_irq, &rc32434_tx_dma_interrupt,
++ SA_SHIRQ | SA_INTERRUPT,
++ "rc32434 ethernet Tx", dev)) {
++ ERR(": unable to get Tx DMA IRQ %d\n",
++ lp->tx_irq);
++ free_irq(lp->rx_irq, dev);
++ return -EAGAIN;
++ }
++
++#ifdef RC32434_REVISION
++ /* Install handler for overrun error. */
++ if (request_irq(lp->ovr_irq, &rc32434_ovr_interrupt,
++ SA_SHIRQ | SA_INTERRUPT,
++ "Ethernet Overflow", dev)) {
++ ERR(": unable to get OVR IRQ %d\n",
++ lp->ovr_irq);
++ free_irq(lp->rx_irq, dev);
++ free_irq(lp->tx_irq, dev);
++ return -EAGAIN;
++ }
++#endif
++
++ /* Install handler for underflow error. */
++ if (request_irq(lp->und_irq, &rc32434_und_interrupt,
++ SA_SHIRQ | SA_INTERRUPT,
++ "Ethernet Underflow", dev)) {
++ ERR(": unable to get UND IRQ %d\n",
++ lp->und_irq);
++ free_irq(lp->rx_irq, dev);
++ free_irq(lp->tx_irq, dev);
++#ifdef RC32434_REVISION
++ free_irq(lp->ovr_irq, dev);
++#endif
++ return -EAGAIN;
++ }
++
++
++ return 0;
++}
++
++
++
++
++static int rc32434_close(struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ u32 tmp;
++
++ /* Disable interrupts */
++ disable_irq(lp->rx_irq);
++ disable_irq(lp->tx_irq);
++#ifdef RC32434_REVISION
++ disable_irq(lp->ovr_irq);
++#endif
++ disable_irq(lp->und_irq);
++
++ tmp = rc32434_readl(&lp->tx_dma_regs->dmasm);
++ tmp = tmp | DMASM_f_m | DMASM_e_m;
++ rc32434_writel(tmp, &lp->tx_dma_regs->dmasm);
++
++ tmp = rc32434_readl(&lp->rx_dma_regs->dmasm);
++ tmp = tmp | DMASM_d_m | DMASM_h_m | DMASM_e_m;
++ rc32434_writel(tmp, &lp->rx_dma_regs->dmasm);
++
++ free_irq(lp->rx_irq, dev);
++ free_irq(lp->tx_irq, dev);
++#ifdef RC32434_REVISION
++ free_irq(lp->ovr_irq, dev);
++#endif
++ free_irq(lp->und_irq, dev);
++ return 0;
++}
++
++
++/* transmit packet */
++static int rc32434_send_packet(struct sk_buff *skb, struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ unsigned long flags;
++ u32 length;
++ DMAD_t td;
++
++
++ spin_lock_irqsave(&lp->lock, flags);
++
++ td = &lp->td_ring[lp->tx_chain_tail];
++
++ /* stop queue when full, drop pkts if queue already full */
++ if(lp->tx_count >= (RC32434_NUM_TDS - 2)) {
++ lp->tx_full = 1;
++
++ if(lp->tx_count == (RC32434_NUM_TDS - 2)) {
++ netif_stop_queue(dev);
++ }
++ else {
++ lp->stats.tx_dropped++;
++ dev_kfree_skb_any(skb);
++ spin_unlock_irqrestore(&lp->lock, flags);
++ return 1;
++ }
++ }
++
++ lp->tx_count ++;
++
++ lp->tx_skb[lp->tx_chain_tail] = skb;
++
++ length = skb->len;
++
++ /* Setup the transmit descriptor. */
++ td->ca = CPHYSADDR(skb->data);
++
++ if(rc32434_readl(&(lp->tx_dma_regs->dmandptr)) == 0) {
++ if( lp->tx_chain_status == empty ) {
++ td->control = DMA_COUNT(length) |DMAD_cof_m |DMAD_iof_m; /* Update tail */
++ lp->tx_chain_tail = (lp->tx_chain_tail + 1) & RC32434_TDS_MASK; /* Move tail */
++ rc32434_writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]), &(lp->tx_dma_regs->dmandptr)); /* Write to NDPTR */
++ lp->tx_chain_head = lp->tx_chain_tail; /* Move head to tail */
++ }
++ else {
++ td->control = DMA_COUNT(length) |DMAD_cof_m|DMAD_iof_m; /* Update tail */
++ lp->td_ring[(lp->tx_chain_tail-1)& RC32434_TDS_MASK].control &= ~(DMAD_cof_m); /* Link to prev */
++ lp->td_ring[(lp->tx_chain_tail-1)& RC32434_TDS_MASK].link = CPHYSADDR(td); /* Link to prev */
++ lp->tx_chain_tail = (lp->tx_chain_tail + 1) & RC32434_TDS_MASK; /* Move tail */
++ rc32434_writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]), &(lp->tx_dma_regs->dmandptr)); /* Write to NDPTR */
++ lp->tx_chain_head = lp->tx_chain_tail; /* Move head to tail */
++ lp->tx_chain_status = empty;
++ }
++ }
++ else {
++ if( lp->tx_chain_status == empty ) {
++ td->control = DMA_COUNT(length) |DMAD_cof_m |DMAD_iof_m; /* Update tail */
++ lp->tx_chain_tail = (lp->tx_chain_tail + 1) & RC32434_TDS_MASK; /* Move tail */
++ lp->tx_chain_status = filled;
++ }
++ else {
++ td->control = DMA_COUNT(length) |DMAD_cof_m |DMAD_iof_m; /* Update tail */
++ lp->td_ring[(lp->tx_chain_tail-1)& RC32434_TDS_MASK].control &= ~(DMAD_cof_m); /* Link to prev */
++ lp->td_ring[(lp->tx_chain_tail-1)& RC32434_TDS_MASK].link = CPHYSADDR(td); /* Link to prev */
++ lp->tx_chain_tail = (lp->tx_chain_tail + 1) & RC32434_TDS_MASK; /* Move tail */
++ }
++ }
++
++ dev->trans_start = jiffies;
++
++ spin_unlock_irqrestore(&lp->lock, flags);
++
++ return 0;
++}
++
++
++/* Ethernet MII-PHY Handler */
++static void rc32434_mii_handler(unsigned long data)
++{
++ struct net_device *dev = (struct net_device *)data;
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ unsigned long flags;
++ unsigned long duplex_status;
++ int port_addr = (lp->rx_irq == 0x2c? 1:0) << 8;
++
++ spin_lock_irqsave(&lp->lock, flags);
++
++ /* Two ports are using the same MII, the difference is the PHY address */
++ rc32434_writel(0, &rc32434_eth0_regs->miimcfg);
++ rc32434_writel(0, &rc32434_eth0_regs->miimcmd);
++ rc32434_writel(port_addr |0x05, &rc32434_eth0_regs->miimaddr);
++ rc32434_writel(MIIMCMD_scn_m, &rc32434_eth0_regs->miimcmd);
++ while(rc32434_readl(&rc32434_eth0_regs->miimind) & MIIMIND_nv_m);
++
++ ERR("irq:%x port_addr:%x RDD:%x\n",
++ lp->rx_irq, port_addr, rc32434_readl(&rc32434_eth0_regs->miimrdd));
++ duplex_status = (rc32434_readl(&rc32434_eth0_regs->miimrdd) & 0x140)? ETHMAC2_fd_m: 0;
++ if(duplex_status != lp->duplex_mode) {
++ ERR("The MII-PHY is Auto-negotiated to %s-Duplex mode for Eth-%x\n", duplex_status? "Full":"Half", lp->rx_irq == 0x2c? 1:0);
++ lp->duplex_mode = duplex_status;
++ rc32434_restart(dev);
++ }
++
++ lp->mii_phy_timer.expires = jiffies + 10 * HZ;
++ add_timer(&lp->mii_phy_timer);
++
++ spin_unlock_irqrestore(&lp->lock, flags);
++
++}
++
++#ifdef RC32434_REVISION
++/* Ethernet Rx Overflow interrupt */
++static irqreturn_t
++rc32434_ovr_interrupt(int irq, void *dev_id, struct pt_regs * regs)
++{
++ struct net_device *dev = (struct net_device *)dev_id;
++ struct rc32434_local *lp;
++ unsigned int ovr;
++ irqreturn_t retval = IRQ_NONE;
++
++ ASSERT(dev != NULL);
++
++ lp = (struct rc32434_local *)dev->priv;
++ spin_lock(&lp->lock);
++ ovr = rc32434_readl(&lp->eth_regs->ethintfc);
++
++ if(ovr & ETHINTFC_ovr_m) {
++ netif_stop_queue(dev);
++
++ /* clear OVR bit */
++ rc32434_writel((ovr & ~ETHINTFC_ovr_m), &lp->eth_regs->ethintfc);
++
++ /* Restart interface */
++ rc32434_restart(dev);
++ retval = IRQ_HANDLED;
++ }
++ spin_unlock(&lp->lock);
++
++ return retval;
++}
++
++#endif
++
++
++/* Ethernet Tx Underflow interrupt */
++static irqreturn_t
++rc32434_und_interrupt(int irq, void *dev_id, struct pt_regs * regs)
++{
++ struct net_device *dev = (struct net_device *)dev_id;
++ struct rc32434_local *lp;
++ unsigned int und;
++ irqreturn_t retval = IRQ_NONE;
++
++ ASSERT(dev != NULL);
++
++ lp = (struct rc32434_local *)dev->priv;
++
++ spin_lock(&lp->lock);
++
++ und = rc32434_readl(&lp->eth_regs->ethintfc);
++
++ if(und & ETHINTFC_und_m) {
++ netif_stop_queue(dev);
++
++ rc32434_writel((und & ~ETHINTFC_und_m), &lp->eth_regs->ethintfc);
++
++ /* Restart interface */
++ rc32434_restart(dev);
++ retval = IRQ_HANDLED;
++ }
++
++ spin_unlock(&lp->lock);
++
++ return retval;
++}
++
++
++/* Ethernet Rx DMA interrupt */
++static irqreturn_t
++rc32434_rx_dma_interrupt(int irq, void *dev_id, struct pt_regs * regs)
++{
++ struct net_device *dev = (struct net_device *)dev_id;
++ struct rc32434_local* lp;
++ volatile u32 dmas,dmasm;
++ irqreturn_t retval;
++
++ ASSERT(dev != NULL);
++
++ lp = (struct rc32434_local *)dev->priv;
++
++ spin_lock(&lp->lock);
++ dmas = rc32434_readl(&lp->rx_dma_regs->dmas);
++ if(dmas & (DMAS_d_m|DMAS_h_m|DMAS_e_m)) {
++ /* Mask D H E bit in Rx DMA */
++ dmasm = rc32434_readl(&lp->rx_dma_regs->dmasm);
++ rc32434_writel(dmasm | (DMASM_d_m | DMASM_h_m | DMASM_e_m), &lp->rx_dma_regs->dmasm);
++#ifdef CONFIG_IDT_USE_NAPI
++ if(netif_rx_schedule_prep(dev))
++ __netif_rx_schedule(dev);
++#else
++ tasklet_hi_schedule(lp->rx_tasklet);
++#endif
++
++ if (dmas & DMAS_e_m)
++ ERR(": DMA error\n");
++
++ retval = IRQ_HANDLED;
++ }
++ else
++ retval = IRQ_NONE;
++
++ spin_unlock(&lp->lock);
++ return retval;
++}
++
++#ifdef CONFIG_IDT_USE_NAPI
++static int rc32434_poll(struct net_device *rx_data_dev, int *budget)
++#else
++static void rc32434_rx_tasklet(unsigned long rx_data_dev)
++#endif
++{
++ struct net_device *dev = (struct net_device *)rx_data_dev;
++ struct rc32434_local* lp = netdev_priv(dev);
++ volatile DMAD_t rd = &lp->rd_ring[lp->rx_next_done];
++ struct sk_buff *skb, *skb_new;
++ u8* pkt_buf;
++ u32 devcs, count, pkt_len, pktuncrc_len;
++ volatile u32 dmas;
++#ifdef CONFIG_IDT_USE_NAPI
++ u32 received = 0;
++ int rx_work_limit = min(*budget,dev->quota);
++#else
++ unsigned long flags;
++ spin_lock_irqsave(&lp->lock, flags);
++#endif
++
++ while ( (count = RC32434_RBSIZE - (u32)DMA_COUNT(rd->control)) != 0) {
++#ifdef CONFIG_IDT_USE_NAPI
++ if(--rx_work_limit <0)
++ {
++ break;
++ }
++#endif
++ /* init the var. used for the later operations within the while loop */
++ skb_new = NULL;
++ devcs = rd->devcs;
++ pkt_len = RCVPKT_LENGTH(devcs);
++ skb = lp->rx_skb[lp->rx_next_done];
++
++ if (count < 64) {
++ lp->stats.rx_errors++;
++ lp->stats.rx_dropped++;
++ }
++ else if ((devcs & ( ETHRX_ld_m)) != ETHRX_ld_m) {
++ /* check that this is a whole packet */
++ /* WARNING: DMA_FD bit incorrectly set in Rc32434 (errata ref #077) */
++ lp->stats.rx_errors++;
++ lp->stats.rx_dropped++;
++ }
++ else if ( (devcs & ETHRX_rok_m) ) {
++
++ {
++ /* must be the (first and) last descriptor then */
++ pkt_buf = (u8*)lp->rx_skb[lp->rx_next_done]->data;
++
++ pktuncrc_len = pkt_len - 4;
++ /* invalidate the cache */
++ dma_cache_inv((unsigned long)pkt_buf, pktuncrc_len);
++
++ /* Malloc up new buffer. */
++ skb_new = dev_alloc_skb(RC32434_RBSIZE + 2);
++
++ if (skb_new != NULL){
++ /* Make room */
++ skb_put(skb, pktuncrc_len);
++
++ skb->protocol = eth_type_trans(skb, dev);
++
++ /* pass the packet to upper layers */
++#ifdef CONFIG_IDT_USE_NAPI
++ netif_receive_skb(skb);
++#else
++ netif_rx(skb);
++#endif
++
++ dev->last_rx = jiffies;
++ lp->stats.rx_packets++;
++ lp->stats.rx_bytes += pktuncrc_len;
++
++ if (IS_RCV_MP(devcs))
++ lp->stats.multicast++;
++
++ /* 16 bit align */
++ skb_reserve(skb_new, 2);
++
++ skb_new->dev = dev;
++ lp->rx_skb[lp->rx_next_done] = skb_new;
++ }
++ else {
++ ERR("no memory, dropping rx packet.\n");
++ lp->stats.rx_errors++;
++ lp->stats.rx_dropped++;
++ }
++ }
++
++ }
++ else {
++ /* This should only happen if we enable accepting broken packets */
++ lp->stats.rx_errors++;
++ lp->stats.rx_dropped++;
++
++ /* add statistics counters */
++ if (IS_RCV_CRC_ERR(devcs)) {
++ DBG(2, "RX CRC error\n");
++ lp->stats.rx_crc_errors++;
++ }
++ else if (IS_RCV_LOR_ERR(devcs)) {
++ DBG(2, "RX LOR error\n");
++ lp->stats.rx_length_errors++;
++ }
++ else if (IS_RCV_LE_ERR(devcs)) {
++ DBG(2, "RX LE error\n");
++ lp->stats.rx_length_errors++;
++ }
++ else if (IS_RCV_OVR_ERR(devcs)) {
++ lp->stats.rx_over_errors++;
++ }
++ else if (IS_RCV_CV_ERR(devcs)) {
++ /* code violation */
++ DBG(2, "RX CV error\n");
++ lp->stats.rx_frame_errors++;
++ }
++ else if (IS_RCV_CES_ERR(devcs)) {
++ DBG(2, "RX Preamble error\n");
++ }
++ }
++
++ rd->devcs = 0;
++
++ /* restore descriptor's curr_addr */
++ if(skb_new)
++ rd->ca = CPHYSADDR(skb_new->data);
++ else
++ rd->ca = CPHYSADDR(skb->data);
++
++ rd->control = DMA_COUNT(RC32434_RBSIZE) |DMAD_cod_m |DMAD_iod_m;
++ lp->rd_ring[(lp->rx_next_done-1)& RC32434_RDS_MASK].control &= ~(DMAD_cod_m);
++
++ lp->rx_next_done = (lp->rx_next_done + 1) & RC32434_RDS_MASK;
++ rd = &lp->rd_ring[lp->rx_next_done];
++ rc32434_writel( ~DMAS_d_m, &lp->rx_dma_regs->dmas);
++ }
++#ifdef CONFIG_IDT_USE_NAPI
++ dev->quota -= received;
++ *budget =- received;
++ if(rx_work_limit < 0)
++ goto not_done;
++#endif
++
++ dmas = rc32434_readl(&lp->rx_dma_regs->dmas);
++
++ if(dmas & DMAS_h_m) {
++ rc32434_writel( ~(DMAS_h_m | DMAS_e_m), &lp->rx_dma_regs->dmas);
++#ifdef RC32434_PROC_DEBUG
++ lp->dma_halt_cnt++;
++#endif
++ rd->devcs = 0;
++ skb = lp->rx_skb[lp->rx_next_done];
++ rd->ca = CPHYSADDR(skb->data);
++ rc32434_chain_rx(lp,rd);
++ }
++
++#ifdef CONFIG_IDT_USE_NAPI
++ netif_rx_complete(dev);
++#endif
++ /* Enable D H E bit in Rx DMA */
++ rc32434_writel(rc32434_readl(&lp->rx_dma_regs->dmasm) & ~(DMASM_d_m | DMASM_h_m |DMASM_e_m), &lp->rx_dma_regs->dmasm);
++#ifdef CONFIG_IDT_USE_NAPI
++ return 0;
++ not_done:
++ return 1;
++#else
++ spin_unlock_irqrestore(&lp->lock, flags);
++ return;
++#endif
++
++
++}
++
++
++
++/* Ethernet Tx DMA interrupt */
++static irqreturn_t
++rc32434_tx_dma_interrupt(int irq, void *dev_id, struct pt_regs * regs)
++{
++ struct net_device *dev = (struct net_device *)dev_id;
++ struct rc32434_local *lp;
++ volatile u32 dmas,dmasm;
++ irqreturn_t retval;
++
++ ASSERT(dev != NULL);
++
++ lp = (struct rc32434_local *)dev->priv;
++
++ spin_lock(&lp->lock);
++
++ dmas = rc32434_readl(&lp->tx_dma_regs->dmas);
++
++ if (dmas & (DMAS_f_m | DMAS_e_m)) {
++ dmasm = rc32434_readl(&lp->tx_dma_regs->dmasm);
++ /* Mask F E bit in Tx DMA */
++ rc32434_writel(dmasm | (DMASM_f_m | DMASM_e_m), &lp->tx_dma_regs->dmasm);
++
++ tasklet_hi_schedule(lp->tx_tasklet);
++
++ if(lp->tx_chain_status == filled && (rc32434_readl(&(lp->tx_dma_regs->dmandptr)) == 0)) {
++ rc32434_writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]), &(lp->tx_dma_regs->dmandptr));
++ lp->tx_chain_status = empty;
++ lp->tx_chain_head = lp->tx_chain_tail;
++ dev->trans_start = jiffies;
++ }
++
++ if (dmas & DMAS_e_m)
++ ERR(": DMA error\n");
++
++ retval = IRQ_HANDLED;
++ }
++ else
++ retval = IRQ_NONE;
++
++ spin_unlock(&lp->lock);
++
++ return retval;
++}
++
++
++static void rc32434_tx_tasklet(unsigned long tx_data_dev)
++{
++ struct net_device *dev = (struct net_device *)tx_data_dev;
++ struct rc32434_local* lp = (struct rc32434_local *)dev->priv;
++ volatile DMAD_t td = &lp->td_ring[lp->tx_next_done];
++ u32 devcs;
++ unsigned long flags;
++ volatile u32 dmas;
++
++ spin_lock_irqsave(&lp->lock, flags);
++
++ /* process all desc that are done */
++ while(IS_DMA_FINISHED(td->control)) {
++ if(lp->tx_full == 1) {
++ netif_wake_queue(dev);
++ lp->tx_full = 0;
++ }
++
++ devcs = lp->td_ring[lp->tx_next_done].devcs;
++ if ((devcs & (ETHTX_fd_m | ETHTX_ld_m)) != (ETHTX_fd_m | ETHTX_ld_m)) {
++ lp->stats.tx_errors++;
++ lp->stats.tx_dropped++;
++
++ /* should never happen */
++ DBG(1, __FUNCTION__ ": split tx ignored\n");
++ }
++ else if (IS_TX_TOK(devcs)) {
++ lp->stats.tx_packets++;
++ }
++ else {
++ lp->stats.tx_errors++;
++ lp->stats.tx_dropped++;
++
++ /* underflow */
++ if (IS_TX_UND_ERR(devcs))
++ lp->stats.tx_fifo_errors++;
++
++ /* oversized frame */
++ if (IS_TX_OF_ERR(devcs))
++ lp->stats.tx_aborted_errors++;
++
++ /* excessive deferrals */
++ if (IS_TX_ED_ERR(devcs))
++ lp->stats.tx_carrier_errors++;
++
++ /* collisions: medium busy */
++ if (IS_TX_EC_ERR(devcs))
++ lp->stats.collisions++;
++
++ /* late collision */
++ if (IS_TX_LC_ERR(devcs))
++ lp->stats.tx_window_errors++;
++
++ }
++
++ /* We must always free the original skb */
++ if (lp->tx_skb[lp->tx_next_done] != NULL) {
++ dev_kfree_skb_any(lp->tx_skb[lp->tx_next_done]);
++ lp->tx_skb[lp->tx_next_done] = NULL;
++ }
++
++ lp->td_ring[lp->tx_next_done].control = DMAD_iof_m;
++ lp->td_ring[lp->tx_next_done].devcs = ETHTX_fd_m | ETHTX_ld_m;
++ lp->td_ring[lp->tx_next_done].link = 0;
++ lp->td_ring[lp->tx_next_done].ca = 0;
++ lp->tx_count --;
++
++ /* go on to next transmission */
++ lp->tx_next_done = (lp->tx_next_done + 1) & RC32434_TDS_MASK;
++ td = &lp->td_ring[lp->tx_next_done];
++
++ }
++
++ dmas = rc32434_readl(&lp->tx_dma_regs->dmas);
++ rc32434_writel( ~dmas, &lp->tx_dma_regs->dmas);
++
++ /* Enable F E bit in Tx DMA */
++ rc32434_writel(rc32434_readl(&lp->tx_dma_regs->dmasm) & ~(DMASM_f_m | DMASM_e_m), &lp->tx_dma_regs->dmasm);
++ spin_unlock_irqrestore(&lp->lock, flags);
++
++}
++
++
++static struct net_device_stats * rc32434_get_stats(struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ return &lp->stats;
++}
++
++
++/*
++ * Set or clear the multicast filter for this adaptor.
++ */
++static void rc32434_multicast_list(struct net_device *dev)
++{
++ /* listen to broadcasts always and to treat */
++ /* IFF bits independantly */
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ unsigned long flags;
++ u32 recognise = ETHARC_ab_m; /* always accept broadcasts */
++
++ if (dev->flags & IFF_PROMISC) /* set promiscuous mode */
++ recognise |= ETHARC_pro_m;
++
++ if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 15))
++ recognise |= ETHARC_am_m; /* all multicast & bcast */
++ else if (dev->mc_count > 0) {
++ DBG(2, __FUNCTION__ ": mc_count %d\n", dev->mc_count);
++ recognise |= ETHARC_am_m; /* for the time being */
++ }
++
++ spin_lock_irqsave(&lp->lock, flags);
++ rc32434_writel(recognise, &lp->eth_regs->etharc);
++ spin_unlock_irqrestore(&lp->lock, flags);
++}
++
++
++static void rc32434_tx_timeout(struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ unsigned long flags;
++
++ spin_lock_irqsave(&lp->lock, flags);
++ rc32434_restart(dev);
++ spin_unlock_irqrestore(&lp->lock, flags);
++
++}
++
++
++/*
++ * Initialize the RC32434 ethernet controller.
++ */
++static int rc32434_init(struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ int i, j;
++
++ /* Disable DMA */
++ rc32434_abort_tx(dev);
++ rc32434_abort_rx(dev);
++
++ /* reset ethernet logic */
++ rc32434_writel(0, &lp->eth_regs->ethintfc);
++ while((rc32434_readl(&lp->eth_regs->ethintfc) & ETHINTFC_rip_m))
++ dev->trans_start = jiffies;
++
++ /* Enable Ethernet Interface */
++ rc32434_writel(ETHINTFC_en_m, &lp->eth_regs->ethintfc);
++
++#ifndef CONFIG_IDT_USE_NAPI
++ tasklet_disable(lp->rx_tasklet);
++#endif
++ tasklet_disable(lp->tx_tasklet);
++
++ /* Initialize the transmit Descriptors */
++ for (i = 0; i < RC32434_NUM_TDS; i++) {
++ lp->td_ring[i].control = DMAD_iof_m;
++ lp->td_ring[i].devcs = ETHTX_fd_m | ETHTX_ld_m;
++ lp->td_ring[i].ca = 0;
++ lp->td_ring[i].link = 0;
++ if (lp->tx_skb[i] != NULL) {
++ dev_kfree_skb_any(lp->tx_skb[i]);
++ lp->tx_skb[i] = NULL;
++ }
++ }
++ lp->tx_next_done = lp->tx_chain_head = lp->tx_chain_tail = lp->tx_full = lp->tx_count = 0;
++ lp-> tx_chain_status = empty;
++
++ /*
++ * Initialize the receive descriptors so that they
++ * become a circular linked list, ie. let the last
++ * descriptor point to the first again.
++ */
++ for (i=0; i<RC32434_NUM_RDS; i++) {
++ struct sk_buff *skb = lp->rx_skb[i];
++
++ if (lp->rx_skb[i] == NULL) {
++ skb = dev_alloc_skb(RC32434_RBSIZE + 2);
++ if (skb == NULL) {
++ ERR("No memory in the system\n");
++ for (j = 0; j < RC32434_NUM_RDS; j ++)
++ if (lp->rx_skb[j] != NULL)
++ dev_kfree_skb_any(lp->rx_skb[j]);
++
++ return 1;
++ }
++ else {
++ skb->dev = dev;
++ skb_reserve(skb, 2);
++ lp->rx_skb[i] = skb;
++ lp->rd_ring[i].ca = CPHYSADDR(skb->data);
++
++ }
++ }
++ lp->rd_ring[i].control = DMAD_iod_m | DMA_COUNT(RC32434_RBSIZE);
++ lp->rd_ring[i].devcs = 0;
++ lp->rd_ring[i].ca = CPHYSADDR(skb->data);
++ lp->rd_ring[i].link = CPHYSADDR(&lp->rd_ring[i+1]);
++
++ }
++ /* loop back */
++ lp->rd_ring[RC32434_NUM_RDS-1].link = CPHYSADDR(&lp->rd_ring[0]);
++ lp->rx_next_done = 0;
++
++ lp->rd_ring[RC32434_NUM_RDS-1].control |= DMAD_cod_m;
++ lp->rx_chain_head = 0;
++ lp->rx_chain_tail = 0;
++ lp->rx_chain_status = empty;
++
++ rc32434_writel(0, &lp->rx_dma_regs->dmas);
++ /* Start Rx DMA */
++ rc32434_start_rx(lp, &lp->rd_ring[0]);
++
++ /* Enable F E bit in Tx DMA */
++ rc32434_writel(rc32434_readl(&lp->tx_dma_regs->dmasm) & ~(DMASM_f_m | DMASM_e_m), &lp->tx_dma_regs->dmasm);
++ /* Enable D H E bit in Rx DMA */
++ rc32434_writel(rc32434_readl(&lp->rx_dma_regs->dmasm) & ~(DMASM_d_m | DMASM_h_m | DMASM_e_m), &lp->rx_dma_regs->dmasm);
++
++ /* Accept only packets destined for this Ethernet device address */
++ rc32434_writel(ETHARC_ab_m, &lp->eth_regs->etharc);
++
++ /* Set all Ether station address registers to their initial values */
++ rc32434_writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal0);
++ rc32434_writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah0);
++
++ rc32434_writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal1);
++ rc32434_writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah1);
++
++ rc32434_writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal2);
++ rc32434_writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah2);
++
++ rc32434_writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal3);
++ rc32434_writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah3);
++
++
++ /* Frame Length Checking, Pad Enable, CRC Enable, Full Duplex set */
++ rc32434_writel(ETHMAC2_pe_m | ETHMAC2_cen_m | ETHMAC2_fd_m, &lp->eth_regs->ethmac2);
++ //ETHMAC2_flc_m ETHMAC2_fd_m lp->duplex_mode
++
++ /* Back to back inter-packet-gap */
++ rc32434_writel(0x15, &lp->eth_regs->ethipgt);
++ /* Non - Back to back inter-packet-gap */
++ rc32434_writel(0x12, &lp->eth_regs->ethipgr);
++
++ /* Management Clock Prescaler Divisor */
++ /* Clock independent setting */
++ rc32434_writel(((idt_cpu_freq)/MII_CLOCK+1) & ~1,
++ &lp->eth_regs->ethmcp);
++
++ /* don't transmit until fifo contains 48b */
++ rc32434_writel(48, &lp->eth_regs->ethfifott);
++
++ rc32434_writel(ETHMAC1_re_m, &lp->eth_regs->ethmac1);
++
++#ifndef CONFIG_IDT_USE_NAPI
++ tasklet_enable(lp->rx_tasklet);
++#endif
++ tasklet_enable(lp->tx_tasklet);
++
++ netif_start_queue(dev);
++
++
++ return 0;
++
++}
++
++
++#ifndef MODULE
++
++static int __init rc32434_setup(char *options)
++{
++ /* no options yet */
++ return 1;
++}
++
++static int __init rc32434_setup_ethaddr0(char *options)
++{
++ memcpy(mac0, options, 17);
++ mac0[17]= '\0';
++ return 1;
++}
++
++__setup("rc32434eth=", rc32434_setup);
++__setup("ethaddr0=", rc32434_setup_ethaddr0);
++
++
++#endif /* MODULE */
++
++module_init(rc32434_init_module);
++module_exit(rc32434_cleanup_module);
++
++
++
++
++
++
++
++
++
++
++
++
++
++
+diff -Nur linux-2.6.17/drivers/net/rc32434_eth.h linux-2.6.17-owrt/drivers/net/rc32434_eth.h
+--- linux-2.6.17/drivers/net/rc32434_eth.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/drivers/net/rc32434_eth.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,187 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Definitions for IDT RC32434 on-chip ethernet controller.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Initial Release
++ *
++ * Aug 2004
++ *
++ * Added NAPI
++ *
++ **************************************************************************
++ */
++
++
++#include <asm/idt-boards/rc32434/rc32434.h>
++#include <asm/idt-boards/rc32434/rc32434_dma_v.h>
++#include <asm/idt-boards/rc32434/rc32434_eth_v.h>
++
++#define RC32434_DEBUG 2
++//#define RC32434_PROC_DEBUG
++#undef RC32434_DEBUG
++
++#ifdef RC32434_DEBUG
++
++/* use 0 for production, 1 for verification, >2 for debug */
++static int rc32434_debug = RC32434_DEBUG;
++#define ASSERT(expr) \
++ if(!(expr)) { \
++ printk( "Assertion failed! %s,%s,%s,line=%d\n", \
++ #expr,__FILE__,__FUNCTION__,__LINE__); }
++#define DBG(lvl, format, arg...) if (rc32434_debug > lvl) printk(KERN_INFO "%s: " format, dev->name , ## arg)
++#else
++#define ASSERT(expr) do {} while (0)
++#define DBG(lvl, format, arg...) do {} while (0)
++#endif
++
++#define INFO(format, arg...) printk(KERN_INFO "%s: " format, dev->name , ## arg)
++#define ERR(format, arg...) printk(KERN_ERR "%s: " format, dev->name , ## arg)
++#define WARN(format, arg...) printk(KERN_WARNING "%s: " format, dev->name , ## arg)
++
++#define ETH0_DMA_RX_IRQ GROUP1_IRQ_BASE + 0
++#define ETH0_DMA_TX_IRQ GROUP1_IRQ_BASE + 1
++#define ETH0_RX_OVR_IRQ GROUP3_IRQ_BASE + 9
++#define ETH0_TX_UND_IRQ GROUP3_IRQ_BASE + 10
++
++#define ETH0_RX_DMA_ADDR (DMA0_PhysicalAddress + 0*DMA_CHAN_OFFSET)
++#define ETH0_TX_DMA_ADDR (DMA0_PhysicalAddress + 1*DMA_CHAN_OFFSET)
++
++/* the following must be powers of two */
++#ifdef CONFIG_IDT_USE_NAPI
++#define RC32434_NUM_RDS 64 /* number of receive descriptors */
++#define RC32434_NUM_TDS 64 /* number of transmit descriptors */
++#else
++#define RC32434_NUM_RDS 128 /* number of receive descriptors */
++#define RC32434_NUM_TDS 128 /* number of transmit descriptors */
++#endif
++
++#define RC32434_RBSIZE 1536 /* size of one resource buffer = Ether MTU */
++#define RC32434_RDS_MASK (RC32434_NUM_RDS-1)
++#define RC32434_TDS_MASK (RC32434_NUM_TDS-1)
++#define RD_RING_SIZE (RC32434_NUM_RDS * sizeof(struct DMAD_s))
++#define TD_RING_SIZE (RC32434_NUM_TDS * sizeof(struct DMAD_s))
++
++#define RC32434_TX_TIMEOUT HZ * 100
++
++#define rc32434_eth0_regs ((ETH_t)(ETH0_VirtualAddress))
++#define rc32434_eth1_regs ((ETH_t)(ETH1_VirtualAddress))
++
++enum status { filled, empty};
++#define IS_DMA_FINISHED(X) (((X) & (DMAD_f_m)) != 0)
++#define IS_DMA_DONE(X) (((X) & (DMAD_d_m)) != 0)
++
++
++/* Information that need to be kept for each board. */
++struct rc32434_local {
++ ETH_t eth_regs;
++ DMA_Chan_t rx_dma_regs;
++ DMA_Chan_t tx_dma_regs;
++ volatile DMAD_t td_ring; /* transmit descriptor ring */
++ volatile DMAD_t rd_ring; /* receive descriptor ring */
++
++ struct sk_buff* tx_skb[RC32434_NUM_TDS]; /* skbuffs for pkt to trans */
++ struct sk_buff* rx_skb[RC32434_NUM_RDS]; /* skbuffs for pkt to trans */
++
++#ifndef CONFIG_IDT_USE_NAPI
++ struct tasklet_struct * rx_tasklet;
++#endif
++ struct tasklet_struct * tx_tasklet;
++
++ int rx_next_done;
++ int rx_chain_head;
++ int rx_chain_tail;
++ enum status rx_chain_status;
++
++ int tx_next_done;
++ int tx_chain_head;
++ int tx_chain_tail;
++ enum status tx_chain_status;
++ int tx_count;
++ int tx_full;
++
++ struct timer_list mii_phy_timer;
++ unsigned long duplex_mode;
++
++ int rx_irq;
++ int tx_irq;
++ int ovr_irq;
++ int und_irq;
++
++ struct net_device_stats stats;
++ spinlock_t lock;
++
++ /* debug /proc entry */
++ struct proc_dir_entry *ps;
++ int dma_halt_cnt; int dma_run_cnt;
++};
++
++extern unsigned int idt_cpu_freq;
++
++/* Index to functions, as function prototypes. */
++static int rc32434_open(struct net_device *dev);
++static int rc32434_send_packet(struct sk_buff *skb, struct net_device *dev);
++static void rc32434_mii_handler(unsigned long data);
++static irqreturn_t rc32434_und_interrupt(int irq, void *dev_id, struct pt_regs * regs);
++static irqreturn_t rc32434_rx_dma_interrupt(int irq, void *dev_id, struct pt_regs * regs);
++static irqreturn_t rc32434_tx_dma_interrupt(int irq, void *dev_id, struct pt_regs * regs);
++#ifdef RC32434_REVISION
++static irqreturn_t rc32434_ovr_interrupt(int irq, void *dev_id, struct pt_regs * regs);
++#endif
++static int rc32434_close(struct net_device *dev);
++static struct net_device_stats *rc32434_get_stats(struct net_device *dev);
++static void rc32434_multicast_list(struct net_device *dev);
++static int rc32434_init(struct net_device *dev);
++static void rc32434_tx_timeout(struct net_device *dev);
++
++static void rc32434_tx_tasklet(unsigned long tx_data_dev);
++#ifdef CONFIG_IDT_USE_NAPI
++static int rc32434_poll(struct net_device *rx_data_dev, int *budget);
++#else
++static void rc32434_rx_tasklet(unsigned long rx_data_dev);
++#endif
++static void rc32434_cleanup_module(void);
++static int rc32434_probe(int port_num);
++int rc32434_init_module(void);
++
++
++static inline void rc32434_abort_dma(struct net_device *dev, DMA_Chan_t ch)
++{
++ if (rc32434_readl(&ch->dmac) & DMAC_run_m) {
++ rc32434_writel(0x10, &ch->dmac);
++
++ while (!(rc32434_readl(&ch->dmas) & DMAS_h_m))
++ dev->trans_start = jiffies;
++
++ rc32434_writel(0, &ch->dmas);
++ }
++
++ rc32434_writel(0, &ch->dmadptr);
++ rc32434_writel(0, &ch->dmandptr);
++}
+diff -Nur linux-2.6.17/include/asm-mips/bootinfo.h linux-2.6.17-owrt/include/asm-mips/bootinfo.h
+--- linux-2.6.17/include/asm-mips/bootinfo.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/asm-mips/bootinfo.h 2006-06-18 12:44:28.000000000 +0200
+@@ -218,6 +218,17 @@
+ #define MACH_GROUP_TITAN 22 /* PMC-Sierra Titan */
+ #define MACH_TITAN_YOSEMITE 1 /* PMC-Sierra Yosemite */
+
++
++/*
++ * Valid machtype for group ARUBA
++ */
++#define MACH_GROUP_ARUBA 23
++#define MACH_ARUBA_UNKNOWN 0
++#define MACH_ARUBA_AP60 1
++#define MACH_ARUBA_AP65 2
++#define MACH_ARUBA_AP70 3
++#define MACH_ARUBA_AP40 4
++
+ #define CL_SIZE COMMAND_LINE_SIZE
+
+ const char *get_system_type(void);
+diff -Nur linux-2.6.17/include/asm-mips/cpu.h linux-2.6.17-owrt/include/asm-mips/cpu.h
+--- linux-2.6.17/include/asm-mips/cpu.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/asm-mips/cpu.h 2006-06-18 12:45:56.000000000 +0200
+@@ -54,6 +54,9 @@
+ #define PRID_IMP_R14000 0x0f00
+ #define PRID_IMP_R8000 0x1000
+ #define PRID_IMP_PR4450 0x1200
++#define PRID_IMP_RC32334 0x1800
++#define PRID_IMP_RC32355 0x1900
++#define PRID_IMP_RC32365 0x1900
+ #define PRID_IMP_R4600 0x2000
+ #define PRID_IMP_R4700 0x2100
+ #define PRID_IMP_TX39 0x2200
+@@ -200,7 +203,8 @@
+ #define CPU_SB1A 62
+ #define CPU_74K 63
+ #define CPU_R14000 64
+-#define CPU_LAST 64
++#define CPU_RC32300 65
++#define CPU_LAST 65
+
+ /*
+ * ISA Level encodings
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32300.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32300.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32300.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32300.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,142 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * RC32300 helper routines
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_RC32300_H__
++#define __IDT_RC32300_H__
++
++#include <linux/delay.h>
++#include <asm/io.h>
++
++
++/* cpu pipeline flush */
++static inline void rc32300_sync(void)
++{
++ __asm__ volatile ("sync");
++}
++
++static inline void rc32300_sync_udelay(int us)
++{
++ __asm__ volatile ("sync");
++ udelay(us);
++}
++
++static inline void rc32300_sync_delay(int ms)
++{
++ __asm__ volatile ("sync");
++ mdelay(ms);
++}
++
++/*
++ * Macros to access internal RC32300 registers. No byte
++ * swapping should be done when accessing the internal
++ * registers.
++ */
++
++static inline u8 rc32300_readb(unsigned long pa)
++{
++ return *((volatile u8 *)KSEG1ADDR(pa));
++}
++static inline u16 rc32300_readw(unsigned long pa)
++{
++ return *((volatile u16 *)KSEG1ADDR(pa));
++}
++static inline u32 rc32300_readl(unsigned long pa)
++{
++ return *((volatile u32 *)KSEG1ADDR(pa));
++}
++static inline void rc32300_writeb(u8 val, unsigned long pa)
++{
++ *((volatile u8 *)KSEG1ADDR(pa)) = val;
++}
++static inline void rc32300_writew(u16 val, unsigned long pa)
++{
++ *((volatile u16 *)KSEG1ADDR(pa)) = val;
++}
++static inline void rc32300_writel(u32 val, unsigned long pa)
++{
++ *((volatile u32 *)KSEG1ADDR(pa)) = val;
++}
++
++
++#define local_readb __raw_readb
++#define local_readw __raw_readw
++#define local_readl __raw_readl
++
++#define local_writeb __raw_writeb
++#define local_writew __raw_writew
++#define local_writel __raw_writel
++
++
++/*
++ * C access to CLZ and CLO instructions
++ * (count leading zeroes/ones).
++ */
++static inline int rc32300_clz(unsigned long val)
++{
++ int ret;
++ __asm__ volatile (
++ ".set\tnoreorder\n\t"
++ ".set\tnoat\n\t"
++ ".set\tmips32\n\t"
++ "clz\t%0,%1\n\t"
++ ".set\tmips0\n\t"
++ ".set\tat\n\t"
++ ".set\treorder"
++ : "=r" (ret)
++ : "r" (val));
++
++ return ret;
++}
++static inline int rc32300_clo(unsigned long val)
++{
++ int ret;
++ __asm__ volatile (
++ ".set\tnoreorder\n\t"
++ ".set\tnoat\n\t"
++ ".set\tmips32\n\t"
++ "clo\t%0,%1\n\t"
++ ".set\tmips0\n\t"
++ ".set\tat\n\t"
++ ".set\treorder"
++ : "=r" (ret)
++ : "r" (val));
++
++ return ret;
++}
++
++#endif // __IDT_RC32300_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32334.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32334.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32334.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32334.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,207 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Definitions for IDT RC32334 CPU.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++
++#ifndef __IDT_RC32334_H__
++#define __IDT_RC32334_H__
++
++#include <linux/delay.h>
++#include <asm/io.h>
++
++/* Base address of internal registers */
++#define RC32334_REG_BASE 0x18000000
++
++/* CPU and IP Bus Control */
++#define CPU_PORT_WIDTH 0xffffe200 // virtual!
++#define CPU_BTA 0xffffe204 // virtual!
++#define CPU_BUSERR_ADDR 0xffffe208 // virtual!
++#define CPU_IP_BTA (RC32334_REG_BASE + 0x0000)
++#define CPU_IP_ADDR_LATCH (RC32334_REG_BASE + 0x0004)
++#define CPU_IP_ARBITRATION (RC32334_REG_BASE + 0x0008)
++#define CPU_IP_BUSERR_CNTL (RC32334_REG_BASE + 0x0010)
++#define CPU_IP_BUSERR_ADDR (RC32334_REG_BASE + 0x0014)
++#define CPU_IP_SYSID (RC32334_REG_BASE + 0x0018)
++
++/* Memory Controller */
++#define MEM_BASE_BANK0 (RC32334_REG_BASE + 0x0080)
++#define MEM_MASK_BANK0 (RC32334_REG_BASE + 0x0084)
++#define MEM_CNTL_BANK0 (RC32334_REG_BASE + 0x0200)
++#define MEM_BASE_BANK1 (RC32334_REG_BASE + 0x0088)
++#define MEM_MASK_BANK1 (RC32334_REG_BASE + 0x008c)
++#define MEM_CNTL_BANK1 (RC32334_REG_BASE + 0x0204)
++#define MEM_CNTL_BANK2 (RC32334_REG_BASE + 0x0208)
++#define MEM_CNTL_BANK3 (RC32334_REG_BASE + 0x020c)
++#define MEM_CNTL_BANK4 (RC32334_REG_BASE + 0x0210)
++#define MEM_CNTL_BANK5 (RC32334_REG_BASE + 0x0214)
++
++/* PCI Controller */
++#define PCI_INTR_PEND (RC32334_REG_BASE + 0x05b0)
++#define PCI_INTR_MASK (RC32334_REG_BASE + 0x05b4)
++#define PCI_INTR_CLEAR (RC32334_REG_BASE + 0x05b8)
++#define CPU2PCI_INTR_PEND (RC32334_REG_BASE + 0x05c0)
++#define CPU2PCI_INTR_MASK (RC32334_REG_BASE + 0x05c4)
++#define CPU2PCI_INTR_CLEAR (RC32334_REG_BASE + 0x05c8)
++#define PCI2CPU_INTR_PEND (RC32334_REG_BASE + 0x05d0)
++#define PCI2CPU_INTR_MASK (RC32334_REG_BASE + 0x05d4)
++#define PCI2CPU_INTR_CLEAR (RC32334_REG_BASE + 0x05d8)
++#define PCI_MEM1_BASE (RC32334_REG_BASE + 0x20b0)
++#define PCI_MEM2_BASE (RC32334_REG_BASE + 0x20b8)
++#define PCI_MEM3_BASE (RC32334_REG_BASE + 0x20c0)
++#define PCI_IO1_BASE (RC32334_REG_BASE + 0x20c8)
++#define PCI_ARBITRATION (RC32334_REG_BASE + 0x20e0)
++#define PCI_CPU_MEM1_BASE (RC32334_REG_BASE + 0x20e8)
++#define PCI_CPU_IO_BASE (RC32334_REG_BASE + 0x2100)
++#define PCI_CFG_CNTL (RC32334_REG_BASE + 0x2cf8)
++#define PCI_CFG_DATA (RC32334_REG_BASE + 0x2cfc)
++
++/* Timers */
++#define TIMER0_CNTL (RC32334_REG_BASE + 0x0700)
++#define TIMER0_COUNT (RC32334_REG_BASE + 0x0704)
++#define TIMER0_COMPARE (RC32334_REG_BASE + 0x0708)
++#define TIMER_REG_OFFSET 0x10
++
++/* Programmable I/O */
++#define PIO_DATA0 (RC32334_REG_BASE + 0x0600)
++#define PIO_DATA1 (RC32334_REG_BASE + 0x0610)
++
++/*
++ * DMA
++ *
++ * NOTE: DMA_IO is a trick for non linear RC32300_IO_DMA stuff
++ *
++ * DMA0: 18001400
++ * DMA1: 18001440
++ * DMA2: 18001900
++ * DMA3: 18001940
++ * NB: dma number must be immediate value or variable.
++ * It MUST NOT be a function since it would get called twice!
++ */
++#define DMA_IO(n) (((n)>1?0x500:0)+((n)&1?0x40:0))
++
++#define RC32300_IO_DMA(n) (RC32334_REG_BASE + 0x1400 + DMA_IO(n))
++#define RC32300_DMA_CONFREG(n) RC32300_IO_DMA(n)
++#define RC32300_DMA_BASEREG(n) (RC32300_IO_DMA(n)+0x4)
++
++#define RC32300_DMA_CURRREG(n) (RC32300_IO_DMA(n)+0x8)
++#define RC32300_DMA_STATREG(n) (RC32300_IO_DMA(n)+0x10)
++#define RC32300_DMA_SRCREG(n) (RC32300_IO_DMA(n)+0x14)
++#define RC32300_DMA_DSTREG(n) (RC32300_IO_DMA(n)+0x18)
++#define RC32300_DMA_NEXTREG(n) (RC32300_IO_DMA(n)+0x1c)
++
++#define RC32300_DMA_IRQ(n) (GROUP7_IRQ_BASE+5*(n))
++
++/* Expansion Interrupt Controller */
++#define IC_GROUP0_PEND (RC32334_REG_BASE + 0x0500)
++#define IC_GROUP0_MASK (RC32334_REG_BASE + 0x0504)
++#define IC_GROUP0_CLEAR (RC32334_REG_BASE + 0x0508)
++#define IC_GROUP_OFFSET 0x10
++
++#define NUM_INTR_GROUPS 15
++/*
++ * The IRQ mapping is as follows:
++ *
++ * IRQ Mapped To
++ * --- -------------------
++ * 0 SW0 (IP0) SW0 intr
++ * 1 SW1 (IP1) SW1 intr
++ * 2 Int0 (IP2) board-specific
++ * 3 Int1 (IP3) board-specific
++ * 4 Int2 (IP4) board-specific
++ * - Int3 (IP5) not used, mapped to IRQ's 8 and up
++ * 6 Int4 (IP6) board-specific
++ * 7 Int5 (IP7) CP0 Timer
++ *
++ * IRQ's 8 and up are all mapped to Int3 (IP5), which
++ * internally on the RC32334 is routed to the Expansion
++ * Interrupt Controller.
++ */
++#define MIPS_CPU_TIMER_IRQ 7
++
++#define GROUP1_IRQ_BASE 8 // bus error
++#define GROUP2_IRQ_BASE (GROUP1_IRQ_BASE + 1) // PIO active low
++#define GROUP3_IRQ_BASE (GROUP2_IRQ_BASE + 12) // PIO active high
++#define GROUP4_IRQ_BASE (GROUP3_IRQ_BASE + 8) // Timer Rollovers
++#define GROUP5_IRQ_BASE (GROUP4_IRQ_BASE + 8) // UART0
++#define GROUP6_IRQ_BASE (GROUP5_IRQ_BASE + 3) // UART1
++#define GROUP7_IRQ_BASE (GROUP6_IRQ_BASE + 3) // DMA Ch0
++#define GROUP8_IRQ_BASE (GROUP7_IRQ_BASE + 5) // DMA Ch1
++#define GROUP9_IRQ_BASE (GROUP8_IRQ_BASE + 5) // DMA Ch2
++#define GROUP10_IRQ_BASE (GROUP9_IRQ_BASE + 5) // DMA Ch3
++#define GROUP11_IRQ_BASE (GROUP10_IRQ_BASE + 5) // PCI Ctlr errors
++#define GROUP12_IRQ_BASE (GROUP11_IRQ_BASE + 4) // PCI Satellite Mode
++#define GROUP13_IRQ_BASE (GROUP12_IRQ_BASE + 16) // PCI to CPU Mailbox
++#define GROUP14_IRQ_BASE (GROUP13_IRQ_BASE + 4) // SPI
++
++#define RC32334_NR_IRQS (GROUP14_IRQ_BASE + 1)
++
++/* 16550 UARTs */
++#ifdef __MIPSEB__
++#define RC32300_UART0_BASE (RC32334_REG_BASE + 0x0803)
++#define RC32300_UART1_BASE (RC32334_REG_BASE + 0x0823)
++#else
++#define RC32300_UART0_BASE (RC32334_REG_BASE + 0x0800)
++#define RC32300_UART1_BASE (RC32334_REG_BASE + 0x0820)
++#endif
++
++#define RC32300_UART0_IRQ GROUP5_IRQ_BASE
++#define RC32300_UART1_IRQ GROUP6_IRQ_BASE
++
++#define IDT_CLOCK_MULT 2
++
++/* NVRAM */
++#define NVRAM_BASE 0x12000000
++#define NVRAM_ENVSIZE_OFF 4
++#define NVRAM_ENVSTART_OFF 0x40
++
++/* LCD 4-digit display */
++#define LCD_CLEAR 0x14000400
++#define LCD_DIGIT0 0x1400000f
++#define LCD_DIGIT1 0x14000008
++#define LCD_DIGIT2 0x14000007
++#define LCD_DIGIT3 0x14000003
++
++/* Interrupts routed on 79S334A board (see rc32334.h) */
++#define RC32334_SCC8530_IRQ 2
++#define RC32334_PCI_INTA_IRQ 3
++#define RC32334_PCI_INTB_IRQ 4
++#define RC32334_PCI_INTC_IRQ 6
++#define RC32334_PCI_INTD_IRQ 7
++
++#define RAM_SIZE (32*1024*1024)
++
++#endif // __IDT_RC32334_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32355_dma.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32355_dma.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32355_dma.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32355_dma.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,206 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * DMA controller defines on IDT RC32355
++ *
++ * Copyright 2004 IDT Inc.
++ * Author: Integrated Device Technology Inc. rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ * May 2004 rkt
++ * Initial Release
++ *
++ **************************************************************************
++ */
++
++#ifndef BANYAN_DMA_H
++#define BANYAN_DMA_H
++#include <asm/idt-boards/rc32300/rc32300.h>
++
++/*
++ * An image of one RC32355 dma channel registers
++ */
++typedef struct {
++ u32 dmac;
++ u32 dmas;
++ u32 dmasm;
++ u32 dmadptr;
++ u32 dmandptr;
++} rc32355_dma_ch_t;
++
++/*
++ * An image of all RC32355 dma channel registers
++ */
++typedef struct {
++ rc32355_dma_ch_t ch[16];
++} rc32355_dma_regs_t;
++
++
++#define rc32355_dma_regs ((rc32355_dma_regs_t*)KSEG1ADDR(RC32355_DMA_BASE))
++
++
++/* DMAC register layout */
++
++#define DMAC_RUN 0x1 /* Halts processing when cleared */
++#define DMAC_DM 0x2 /* Done Mask, ignore DMA events */
++#define DMAC_MODE_MASK 0xC /* DMA operating mode */
++
++#define DMAC_MODE_AUTO 0x0 /* DMA Auto Request Mode */
++#define DMAC_MODE_BURST 0x4 /* DMA Burst Request Mode */
++#define DMAC_MODE_TFER 0x8 /* DMA Transfer Request Mode */
++
++/* DMAS and DMASM register layout */
++
++#define DMAS_F 0x01 /* Finished */
++#define DMAS_D 0x02 /* Done */
++#define DMAS_C 0x04 /* Chain */
++#define DMAS_E 0x08 /* Error */
++#define DMAS_H 0x10 /* Halt */
++
++/* Polling count for DMAS_H bit in DMAS register after halting DMA */
++#define DMA_HALT_TIMEOUT 500
++
++
++static inline int rc32355_halt_dma(rc32355_dma_ch_t* ch)
++{
++ int timeout=1;
++
++ if (local_readl(&ch->dmac) & DMAC_RUN) {
++ local_writel(0, &ch->dmac);
++ for (timeout = DMA_HALT_TIMEOUT; timeout > 0; timeout--) {
++ if (local_readl(&ch->dmas) & DMAS_H) {
++ local_writel(0, &ch->dmas);
++ break;
++ }
++ }
++ }
++
++ return timeout ? 0 : 1;
++}
++
++static inline void rc32355_start_dma(rc32355_dma_ch_t* ch, u32 dma_addr)
++{
++ local_writel(0, &ch->dmandptr);
++ local_writel(dma_addr, &ch->dmadptr);
++}
++
++static inline void rc32355_chain_dma(rc32355_dma_ch_t* ch, u32 dma_addr)
++{
++ local_writel(dma_addr, &ch->dmandptr);
++}
++
++
++/* The following can be used to describe DMA channels 0 to 15, and the */
++/* sub device's needed to select them in the DMADESC_DS_MASK field */
++
++#define DMA_CHAN_ATM01 0 /* ATM interface 0,1 chan */
++
++#define DMA_CHAN_ATM0IN 0 /* ATM interface 0 input */
++#define DMA_DEV_ATM0IN 0 /* ATM interface 0 input */
++
++#define DMA_CHAN_ATM1IN 0 /* ATM interface 1 input */
++#define DMA_DEV_ATM1IN 1 /* ATM interface 1 input */
++
++#define DMA_CHAN_ATM0OUT 0 /* ATM interface 0 output */
++#define DMA_DEV_ATM0OUT 2 /* ATM interface 0 output */
++
++#define DMA_CHAN_ATM1OUT 0 /* ATM interface 1 output */
++#define DMA_DEV_ATM1OUT 3 /* ATM interface 1 output */
++
++/* for entry in {0,1,2,3,4,5,6,7} - note 5,6,7 share with those below */
++#define DMA_CHAN_ATMVCC(entry) ((entry)+1) /* ATM VC cache entry */
++#define DMA_DEV_ATMVCC(entry) 0
++
++#define DMA_CHAN_MEMTOMEM 6 /* Memory to memory DMA */
++#define DMA_DEV_MEMTOMEM 1 /* Memory to memory DMA */
++
++#define DMA_CHAN_ATMFMB0 7 /* ATM Frame Mode Buffer 0 */
++#define DMA_DEV_ATMFMB0 1 /* ATM Frame Mode Buffer 0 */
++
++#define DMA_CHAN_ATMFMB1 8 /* ATM Frame Mode Buffer 1 */
++#define DMA_DEV_ATMFMB1 1 /* ATM Frame Mode Buffer 1 */
++
++#define DMA_CHAN_ETHERIN 9 /* Ethernet input */
++#define DMA_DEV_ETHERIN 0 /* Ethernet input */
++
++#define DMA_CHAN_ETHEROUT 10 /* Ethernet output */
++#define DMA_DEV_ETHEROUT 0 /* Ethernet output */
++
++#define DMA_CHAN_TDMIN 11 /* TDM Bus input */
++#define DMA_DEV_TDMIN 0 /* TDM Bus input */
++
++#define DMA_CHAN_TDMOUT 12 /* TDM Bus output */
++#define DMA_DEV_TDMOUT 0 /* TDM Bus output */
++
++#define DMA_CHAN_USBIN 13 /* USB input */
++#define DMA_DEV_USBIN 0 /* USB input */
++
++#define DMA_CHAN_USBOUT 14 /* USB output */
++#define DMA_DEV_USBOUT 0 /* USB output */
++
++#define DMA_CHAN_EXTERN 15 /* External DMA */
++#define DMA_DEV_EXTERN 0 /* External DMA */
++
++/*
++ * An RC32355 dma descriptor in system memory
++ */
++typedef struct {
++ u32 cmdstat; /* control and status */
++ u32 curr_addr; /* current address of data */
++ u32 devcs; /* peripheral-specific control and status */
++ u32 link; /* link to next descriptor */
++} rc32355_dma_desc_t;
++
++/* Values for the descriptor cmdstat word */
++
++#define DMADESC_F 0x80000000u /* Finished bit */
++#define DMADESC_D 0x40000000u /* Done bit */
++#define DMADESC_T 0x20000000u /* Terminated bit */
++#define DMADESC_IOD 0x10000000u /* Interrupt On Done */
++#define DMADESC_IOF 0x08000000u /* Interrupt On Finished */
++#define DMADESC_COD 0x04000000u /* Chain On Done */
++#define DMADESC_COF 0x02000000u /* Chain On Finished */
++
++#define DMADESC_DEVCMD_MASK 0x01C00000u /* Device Command mask */
++#define DMADESC_DEVCMD_SHIFT 22 /* Device Command shift */
++
++#define DMADESC_DS_MASK 0x00300000u /* Device Select mask */
++#define DMADESC_DS_SHIFT 20 /* Device Select shift */
++
++#define DMADESC_COUNT_MASK 0x0003FFFFu /* Byte Count mask */
++#define DMADESC_COUNT_SHIFT 0 /* Byte Count shift */
++
++#define IS_DMA_FINISHED(X) ( ( (X) & DMADESC_F ) >> 31) /* F Bit */
++#define IS_DMA_DONE(X) ( ( (X) & DMADESC_D ) >> 30) /* D Bit */
++#define IS_DMA_TERMINATED(X) ( ( (X) & DMADESC_T ) >> 29) /* T Bit */
++#define IS_DMA_USED(X) (((X) & (DMADESC_F | DMADESC_D | DMADESC_T)) != 0)
++
++#define DMA_DEVCMD(devcmd) \
++ (((devcmd) << DMADESC_DEVCMD_SHIFT) & DMADESC_DS_MASK)
++#define DMA_DS(ds) \
++ (((ds) << DMADESC_DS_SHIFT) & DMADESC_DS_MASK)
++#define DMA_COUNT(count) \
++ ((count) & DMADESC_COUNT_MASK)
++
++#endif /* RC32355_DMA_H */
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32355_eth.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32355_eth.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32355_eth.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32355_eth.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,442 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Ethernet registers on IDT RC32355
++ *
++ * Copyright 2004 IDT Inc.
++ * Author: Integrated Device Technology Inc. rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ * May 2004 rkt
++ * Initial Release
++ *
++ **************************************************************************
++ */
++
++
++#ifndef RC32355_ETHER_H
++#define RC32355_ETHER_H
++
++#include <asm/idt-boards/rc32300/rc32355_dma.h>
++
++/*
++ * A partial image of the RC32355 ethernet registers
++ */
++typedef struct {
++ u32 ethintfc;
++ u32 ethfifott;
++ u32 etharc;
++ u32 ethhash0;
++ u32 ethhash1;
++ u32 ethfifost;
++ u32 ethfifos;
++ u32 ethodeops;
++ u32 ethis;
++ u32 ethos;
++ u32 ethmcp;
++ u32 _u1;
++ u32 ethid;
++ u32 _u2;
++ u32 _u3;
++ u32 _u4;
++ u32 ethod;
++ u32 _u5;
++ u32 _u6;
++ u32 _u7;
++ u32 ethodeop;
++ u32 _u8[43];
++ u32 ethsal0;
++ u32 ethsah0;
++ u32 ethsal1;
++ u32 ethsah1;
++ u32 ethsal2;
++ u32 ethsah2;
++ u32 ethsal3;
++ u32 ethsah3;
++ u32 ethrbc;
++ u32 ethrpc;
++ u32 ethrupc;
++ u32 ethrfc;
++ u32 ethtbc;
++ u32 ethgpf;
++ u32 _u9[50];
++ u32 ethmac1;
++ u32 ethmac2;
++ u32 ethipgt;
++ u32 ethipgr;
++ u32 ethclrt;
++ u32 ethmaxf;
++ u32 _u10;
++ u32 ethmtest;
++ u32 miimcfg;
++ u32 miimcmd;
++ u32 miimaddr;
++ u32 miimwtd;
++ u32 miimrdd;
++ u32 miimind;
++ u32 _u11;
++ u32 _u12;
++ u32 ethcfsa0;
++ u32 ethcfsa1;
++ u32 ethcfsa2;
++} rc32355_eth_regs_t;
++
++#define rc32355_eth_regs ((rc32355_eth_regs_t*)KSEG1ADDR(RC32355_ETH_BASE))
++
++#define ETH_INTFC (RC32355_ETH_BASE + 0x000) /* INTerFace Control */
++#define ETH_FIFOTT (RC32355_ETH_BASE + 0x004) /* FIFO Transmit Threshold */
++#define ETH_ARC (RC32355_ETH_BASE + 0x008) /* Address Recognition Ctrl */
++#define ETH_HASH0 (RC32355_ETH_BASE + 0x00C) /* 32 multicast Hash bits */
++#define ETH_HASH1 (RC32355_ETH_BASE + 0x010) /* another 32 Hash bits */
++#define ETH_FIFOST (RC32355_ETH_BASE + 0x014) /* FIFO Status Threshold */
++#define ETH_FIFOS (RC32355_ETH_BASE + 0x018) /* FIFO Status Register */
++#define ETH_ODEOPS (RC32355_ETH_BASE + 0x01C) /* Out Data End-Of-Pkt Size */
++#define ETH_IS (RC32355_ETH_BASE + 0x020) /* Input Status */
++#define ETH_OS (RC32355_ETH_BASE + 0x024) /* Output Status */
++#define ETH_MCP (RC32355_ETH_BASE + 0x028) /* Managemt Clock Prescaler */
++#define ETH_ID (RC32355_ETH_BASE + 0x030) /* Input Data register */
++#define ETH_OD (RC32355_ETH_BASE + 0x040) /* Output Data register */
++#define ETH_ODEOP (RC32355_ETH_BASE + 0x050) /* OD End-Of-Packet Size */
++
++/* for n in { 0, 1, 2, 3 } */
++#define ETH_SAL(n) (RC32355_ETH_BASE + 0x100 + (n * 8)) /* Stn Address 2-5 */
++#define ETH_SAH(n) (RC32355_ETH_BASE + 0x104 + (n * 8)) /* Stn Address 0-1 */
++
++#define ETH_RBC (RC32355_ETH_BASE + 0x120) /* Receive Byte Count */
++#define ETH_RPC (RC32355_ETH_BASE + 0x124) /* Receive Packet Count */
++#define ETH_RUPC (RC32355_ETH_BASE + 0x128) /* Rx Undersized Pkt count */
++#define ETH_RFC (RC32355_ETH_BASE + 0x12C) /* Receive Fragment Count */
++#define ETH_TBC (RC32355_ETH_BASE + 0x130) /* Transmit Byte Count */
++#define ETH_GPF (RC32355_ETH_BASE + 0x134) /* Generate Pause Frame */
++#define ETH_MAC1 (RC32355_ETH_BASE + 0x200) /* Medium Access Control 1 */
++#define ETH_MAC2 (RC32355_ETH_BASE + 0x204) /* Medium Access Control 2 */
++#define ETH_IPGT (RC32355_ETH_BASE + 0x208) /* Back-to-back InterPkt Gap */
++#define ETH_IPGR (RC32355_ETH_BASE + 0x20C) /* Non " InterPkt Gap */
++#define ETH_CLRT (RC32355_ETH_BASE + 0x210) /* Collis'n Window and Retry */
++#define ETH_MAXF (RC32355_ETH_BASE + 0x214) /* Maximum Frame Length */
++#define ETH_MTEST (RC32355_ETH_BASE + 0x21C) /* MAC Test */
++
++#define ETHMIIM_CFG (RC32355_ETH_BASE + 0x220) /* MII Mgmt Configuration */
++#define ETHMIIM_CMD (RC32355_ETH_BASE + 0x224) /* MII Mgmt Command */
++#define ETHMIIM_ADDR (RC32355_ETH_BASE + 0x228) /* MII Mgmt Address */
++#define ETHMIIM_WTD (RC32355_ETH_BASE + 0x22C) /* MII Mgmt Write Data */
++#define ETHMIIM_RDD (RC32355_ETH_BASE + 0x230) /* MII Mgmt Read Data */
++#define ETHMIIM_IND (RC32355_ETH_BASE + 0x234) /* MII Mgmt Indicators */
++
++/* for n in { 0, 1, 2 } */
++#define ETH_CFSA(n) (RC32355_ETH_BASE + 0x240 + ((n) * 4)) /* Station Addr */
++
++
++/*
++ * Register Interpretations follow
++ */
++
++/******************************************************************************
++ * ETHINTFC register
++ *****************************************************************************/
++
++#define ETHERINTFC_EN (1<<0)
++#define ETHERINTFC_ITS (1<<1)
++#define ETHERINTFC_RES (1<<2)
++#define ETHERINTFC_RIP (1<<2)
++#define ETHERINTFC_JAM (1<<3)
++
++/******************************************************************************
++ * ETHFIFOTT register
++ *****************************************************************************/
++
++#define ETHERFIFOTT_TTH(v) (((v)&0x3f)<<0)
++
++/******************************************************************************
++ * ETHARC register
++ *****************************************************************************/
++
++#define ETHERARC_PRO (1<<0)
++#define ETHERARC_AM (1<<1)
++#define ETHERARC_AFM (1<<2)
++#define ETHERARC_AB (1<<3)
++
++/******************************************************************************
++ * ETHHASH registers
++ *****************************************************************************/
++
++#define ETHERHASH0(v) (((v)&0xffff)<<0)
++#define ETHERHASH1(v) (((v)&0xffff)<<0)
++
++/******************************************************************************
++ * ETHSA registers
++ *****************************************************************************/
++
++#define ETHERSAL0(v) (((v)&0xffff)<<0)
++#define ETHERSAL1(v) (((v)&0xffff)<<0)
++#define ETHERSAL2(v) (((v)&0xffff)<<0)
++#define ETHERSAL3(v) (((v)&0xffff)<<0)
++#define ETHERSAH0(v) (((v)&0xff)<<0)
++#define ETHERSAH1(v) (((v)&0xff)<<0)
++#define ETHERSAH2(v) (((v)&0xff)<<0)
++#define ETHERSAH3(v) (((v)&0xff)<<0)
++
++/******************************************************************************
++ * ETHFIFOST register
++ *****************************************************************************/
++
++#define ETHERFIFOST_IRTH(v) (((v)&0x3f)<<0)
++#define ETHERFIFOST_ORTH(v) (((v)&0x3f)<<16)
++
++/******************************************************************************
++ * ETHFIFOS register
++ *****************************************************************************/
++
++#define ETHERFIFOS_IR (1<<0)
++#define ETHERFIFOS_OR (1<<1)
++#define ETHERFIFOS_OVR (1<<2)
++#define ETHERFIFOS_UND (1<<3)
++
++/******************************************************************************
++ * DATA registers
++ *****************************************************************************/
++
++#define ETHERID(v) (((v)&0xffff)<<0)
++#define ETHEROD(v) (((v)&0xffff)<<0)
++
++/******************************************************************************
++ * ETHODEOPS register
++ *****************************************************************************/
++
++#define ETHERODEOPS_SIZE(v) (((v)&0x3)<<0)
++
++/******************************************************************************
++ * ETHODEOP register
++ *****************************************************************************/
++
++#define ETHERODEOP(v) (((v)&0xffff)<<0)
++
++/******************************************************************************
++ * ETHIS register
++ *****************************************************************************/
++
++#define ETHERIS_EOP (1<<0)
++#define ETHERIS_ROK (1<<2)
++#define ETHERIS_FM (1<<3)
++#define ETHERIS_MP (1<<4)
++#define ETHERIS_BP (1<<5)
++#define ETHERIS_VLT (1<<6)
++#define ETHERIS_CF (1<<7)
++#define ETHERIS_OVR (1<<8)
++#define ETHERIS_CRC (1<<9)
++#define ETHERIS_CV (1<<10)
++#define ETHERIS_DB (1<<11)
++#define ETHERIS_LE (1<<12)
++#define ETHERIS_LOR (1<<13)
++#define ETHERIS_SIZE(v) (((v)&0x3)<<14)
++#define ETHERIS_LENGTH(v) (((v)&0xff)<<16)
++
++/******************************************************************************
++ * ETHOS register
++ *****************************************************************************/
++
++#define ETHEROS_T (1<<0)
++#define ETHEROS_TOK (1<<6)
++#define ETHEROS_MP (1<<7)
++#define ETHEROS_BP (1<<8)
++#define ETHEROS_UND (1<<9)
++#define ETHEROS_OF (1<<10)
++#define ETHEROS_ED (1<<11)
++#define ETHEROS_EC (1<<12)
++#define ETHEROS_LC (1<<13)
++#define ETHEROS_TD (1<<14)
++#define ETHEROS_CRC (1<<15)
++#define ETHEROS_LE (1<<16)
++#define ETHEROS_CC(v) (((v)&0xf)<<17)
++#define ETHEROS_PFD (1<<21)
++
++/******************************************************************************
++ * Statistics registers
++ *****************************************************************************/
++
++#define ETHERRBC(v) (((v)&0xffff)<<0)
++#define ETHERRPC(v) (((v)&0xffff)<<0)
++#define ETHERRUPC(v) (((v)&0xffff)<<0)
++#define ETHERRFC(v) (((v)&0xffff)<<0)
++#define ETHERTBC(v) (((v)&0xffff)<<0)
++
++/******************************************************************************
++ * ETHGPF register
++ *****************************************************************************/
++
++#define ETHERGPF_PTV(v) (((v)&0xff)<<0)
++
++/******************************************************************************
++ * MAC registers
++ *****************************************************************************/
++//ETHMAC1
++#define ETHERMAC1_RE (1<<0)
++#define ETHERMAC1_PAF (1<<1)
++#define ETHERMAC1_RFC (1<<2)
++#define ETHERMAC1_TFC (1<<3)
++#define ETHERMAC1_LB (1<<4)
++#define ETHERMAC1_MR (1<<15)
++
++//ETHMAC2
++#define ETHERMAC2_FD (1<<0)
++#define ETHERMAC2_FLC (1<<1)
++#define ETHERMAC2_HFE (1<<2)
++#define ETHERMAC2_DC (1<<3)
++#define ETHERMAC2_CEN (1<<4)
++#define ETHERMAC2_PE (1<<5)
++#define ETHERMAC2_VPE (1<<6)
++#define ETHERMAC2_APE (1<<7)
++#define ETHERMAC2_PPE (1<<8)
++#define ETHERMAC2_LPE (1<<9)
++#define ETHERMAC2_NB (1<<12)
++#define ETHERMAC2_BP (1<<13)
++#define ETHERMAC2_ED (1<<14)
++
++//ETHIPGT
++#define ETHERIPGT(v) (((v)&0x3f)<<0)
++
++//ETHIPGR
++#define ETHERIPGR_IPGR1(v) (((v)&0x3f)<<0)
++#define ETHERIPGR_IPGR2(v) (((v)&0x3f)<<8)
++
++//ETHCLRT
++#define ETHERCLRT_MAXRET(v) (((v)&0x3f)<<0)
++#define ETHERCLRT_COLWIN(v) (((v)&0x3f)<<8)
++
++//ETHMAXF
++#define ETHERMAXF(v) (((v)&0x3f)<<0)
++
++//ETHMTEST
++#define ETHERMTEST_TB (1<<2)
++
++//ETHMCP
++#define ETHERMCP_DIV(v) (((v)&0xff)<<0)
++
++//MIIMCFG
++#define ETHERMIIMCFG_CS(v) (((v)&0x3)<<2)
++#define ETHERMIIMCFG_R (1<<15)
++
++//MIIMCMD
++#define ETHERMIIMCMD_RD (1<<0)
++#define ETHERMIIMCMD_SCN (1<<1)
++
++//MIIMADDR
++#define ETHERMIIMADDR_REGADDR(v) (((v)&0x1f)<<0)
++#define ETHERMIIMADDR_PHYADDR(v) (((v)&0x1f)<<8)
++
++//MIIMWTD
++#define ETHERMIIMWTD(v) (((v)&0xff)<<0)
++
++//MIIMRDD
++#define ETHERMIIMRDD(v) (((v)&0xff)<<0)
++
++//MIIMIND
++#define ETHERMIIMIND_BSY (1<<0)
++#define ETHERMIIMIND_SCN (1<<1)
++#define ETHERMIIMIND_NV (1<<2)
++
++//DMA DEVCS IN
++#define ETHERDMA_IN_LENGTH(v) (((v)&0xffff)<<16)
++#define ETHERDMA_IN_CES (1<<14)
++#define ETHERDMA_IN_LOR (1<<13)
++#define ETHERDMA_IN_LE (1<<12)
++#define ETHERDMA_IN_DB (1<<11)
++#define ETHERDMA_IN_CV (1<<10)
++#define ETHERDMA_IN_CRC (1<<9)
++#define ETHERDMA_IN_OVR (1<<8)
++#define ETHERDMA_IN_CF (1<<7)
++#define ETHERDMA_IN_VLT (1<<6)
++#define ETHERDMA_IN_BP (1<<5)
++#define ETHERDMA_IN_MP (1<<4)
++#define ETHERDMA_IN_FM (1<<3)
++#define ETHERDMA_IN_ROK (1<<2)
++#define ETHERDMA_IN_LD (1<<1)
++#define ETHERDMA_IN_FD (1<<0)
++
++//DMA DEVCS OUT
++#define ETHERDMA_OUT_CC(v) (((v)&0xf)<<17)
++#define ETHERDMA_OUT_CNT 0x001e0000
++#define ETHERDMA_OUT_SHFT 17
++#define ETHERDMA_OUT_LE (1<<16)
++
++#define ETHERDMA_OUT_CRC (1<<15)
++#define ETHERDMA_OUT_TD (1<<14)
++#define ETHERDMA_OUT_LC (1<<13)
++#define ETHERDMA_OUT_EC (1<<12)
++#define ETHERDMA_OUT_ED (1<<11)
++#define ETHERDMA_OUT_OF (1<<10)
++#define ETHERDMA_OUT_UND (1<<9)
++#define ETHERDMA_OUT_BP (1<<8)
++#define ETHERDMA_OUT_MP (1<<7)
++#define ETHERDMA_OUT_TOK (1<<6)
++#define ETHERDMA_OUT_HEN (1<<5)
++#define ETHERDMA_OUT_CEN (1<<4)
++#define ETHERDMA_OUT_PEN (1<<3)
++#define ETHERDMA_OUT_OEN (1<<2)
++#define ETHERDMA_OUT_LD (1<<1)
++#define ETHERDMA_OUT_FD (1<<0)
++
++#define RCV_ERRS \
++ (ETHERDMA_IN_OVR | ETHERDMA_IN_CRC | ETHERDMA_IN_CV | ETHERDMA_IN_LE)
++#define TX_ERRS \
++ (ETHERDMA_OUT_LC | ETHERDMA_OUT_EC | ETHERDMA_OUT_ED | \
++ ETHERDMA_OUT_OF | ETHERDMA_OUT_UND)
++
++#define IS_RCV_ROK(X) (((X) & (1<<2)) >> 2) /* Receive Okay */
++#define IS_RCV_FM(X) (((X) & (1<<3)) >> 3) /* Is Filter Match */
++#define IS_RCV_MP(X) (((X) & (1<<4)) >> 4) /* Is it MP */
++#define IS_RCV_BP(X) (((X) & (1<<5)) >> 5) /* Is it BP */
++#define IS_RCV_VLT(X) (((X) & (1<<6)) >> 6) /* VLAN Tag Detect */
++#define IS_RCV_CF(X) (((X) & (1<<7)) >> 7) /* Control Frame */
++#define IS_RCV_OVR_ERR(X) (((X) & (1<<8)) >> 8) /* Receive Overflow */
++#define IS_RCV_CRC_ERR(X) (((X) & (1<<9)) >> 9) /* CRC Error */
++#define IS_RCV_CV_ERR(X) (((X) & (1<<10))>>10) /* Code Violation */
++#define IS_RCV_DB_ERR(X) (((X) & (1<<11))>>11) /* Dribble Bits */
++#define IS_RCV_LE_ERR(X) (((X) & (1<<12))>>12) /* Length error */
++#define IS_RCV_LOR_ERR(X) (((X) & (1<<13))>>13) /* Length Out of
++ Range */
++#define IS_RCV_CES_ERR(X) (((X) & (1<<14))>>14) /* Preamble error */
++#define RCVPKT_LENGTH(X) (((X) & 0xFFFF0000)>>16) /* Length of the
++ received packet */
++
++#define IS_TX_TOK(X) (((X) & (1<<6) ) >> 6 ) /* Transmit Okay */
++#define IS_TX_MP(X) (((X) & (1<<7) ) >> 7 ) /* Multicast */
++
++#define IS_TX_BP(X) (((X) & (1<<8) ) >> 8 ) /* Broadcast */
++#define IS_TX_UND_ERR(X) (((X) & (1<<9) ) >> 9 ) /* Transmit FIFO
++ Underflow */
++#define IS_TX_OF_ERR(X) (((X) & (1<<10)) >>10 ) /* Oversized frame */
++#define IS_TX_ED_ERR(X) (((X) & (1<<11)) >>11 ) /* Excessive
++ deferral */
++#define IS_TX_EC_ERR(X) (((X) & (1<<12)) >>12 ) /* Excessive
++ collisions */
++#define IS_TX_LC_ERR(X) (((X) & (1<<13)) >>13 ) /* Late Collision */
++#define IS_TX_TD_ERR(X) (((X) & (1<<14)) >>14 ) /* Transmit deferred*/
++#define IS_TX_CRC_ERR(X) (((X) & (1<<15)) >>15 ) /* CRC Error */
++#define IS_TX_LE_ERR(X) (((X) & (1<<16)) >>16 ) /* Length Error */
++
++#define TX_COLLISION_COUNT(X) (((X) & 0x001E0000u)>>17) /* Collision Count */
++
++#endif /* RC32355_ETHER_H */
++
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32355.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32355.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32355.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32355.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,177 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Definitions for IDT RC32355 CPU.
++ *
++ * Copyright 2004 IDT Inc.
++ * Author: Integrated Device Technology Inc. rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ * May 2004 rkt
++ * Initial Release
++ *
++ **************************************************************************
++ */
++
++
++#ifndef _RC32355_H_
++#define _RC32355_H_
++
++#include <linux/delay.h>
++#include <asm/io.h>
++
++/* Base address of internal registers */
++#define RC32355_REG_BASE 0x18000000
++
++/* System ID Registers */
++#define CPU_SYSID (RC32355_REG_BASE + 0x00018)
++#define CPU_BTADDR (RC32355_REG_BASE + 0x0001c)
++#define CPU_REV (RC32355_REG_BASE + 0x0002c)
++
++/* Reset Controller */
++#define RESET_CNTL (RC32355_REG_BASE + 0x08000)
++
++/* Device Controller */
++#define DEV0_BASE (RC32355_REG_BASE + 0x10000)
++#define DEV0_MASK (RC32355_REG_BASE + 0x10004)
++#define DEV0_CNTL (RC32355_REG_BASE + 0x10008)
++#define DEV0_TIMING (RC32355_REG_BASE + 0x1000c)
++#define DEV_REG_OFFSET 0x10
++
++/* SDRAM Controller */
++#define SDRAM0_BASE (RC32355_REG_BASE + 0x18000)
++#define SDRAM0_MASK (RC32355_REG_BASE + 0x18004)
++#define SDRAM1_BASE (RC32355_REG_BASE + 0x18008)
++#define SDRAM1_MASK (RC32355_REG_BASE + 0x1800c)
++#define SDRAM_CNTL (RC32355_REG_BASE + 0x18010)
++
++/* Bus Arbiter */
++#define BUS_ARB_CNTL0 (RC32355_REG_BASE + 0x20000)
++#define BUS_ARB_CNTL1 (RC32355_REG_BASE + 0x20004)
++
++/* Counters/Timers */
++#define TIMER0_COUNT (RC32355_REG_BASE + 0x28000)
++#define TIMER0_COMPARE (RC32355_REG_BASE + 0x28004)
++#define TIMER0_CNTL (RC32355_REG_BASE + 0x28008)
++#define TIMER_REG_OFFSET 0x0C
++
++/* System Integrity */
++
++/* Interrupt Controller */
++#define IC_GROUP0_PEND (RC32355_REG_BASE + 0x30000)
++#define IC_GROUP0_MASK (RC32355_REG_BASE + 0x30004)
++#define IC_GROUP_OFFSET 0x08
++
++#define NUM_INTR_GROUPS 5
++/*
++ * The IRQ mapping is as follows:
++ *
++ * IRQ Mapped To
++ * --- -------------------
++ * 0 SW0 (IP0) SW0 intr
++ * 1 SW1 (IP1) SW1 intr
++ * - Int0 (IP2) mapped to GROUP0_IRQ_BASE
++ * - Int1 (IP3) mapped to GROUP1_IRQ_BASE
++ * - Int2 (IP4) mapped to GROUP2_IRQ_BASE
++ * - Int3 (IP5) mapped to GROUP3_IRQ_BASE
++ * - Int4 (IP6) mapped to GROUP4_IRQ_BASE
++ * 7 Int5 (IP7) CP0 Timer
++ *
++ * IRQ's 8 and up are all mapped to Int0-4 (IP2-IP6), which
++ * internally on the RC32355 is routed to the Expansion
++ * Interrupt Controller.
++ */
++#define MIPS_CPU_TIMER_IRQ 7
++
++#define GROUP0_IRQ_BASE 8 // Counter/Timers, UCW
++#define GROUP1_IRQ_BASE (GROUP0_IRQ_BASE + 32) // DMA
++#define GROUP2_IRQ_BASE (GROUP1_IRQ_BASE + 32) // ATM
++#define GROUP3_IRQ_BASE (GROUP2_IRQ_BASE + 32) // TDM, Eth, USB, UARTs, I2C
++#define GROUP4_IRQ_BASE (GROUP3_IRQ_BASE + 32) // GPIO
++
++#define RC32355_NR_IRQS (GROUP4_IRQ_BASE + 32)
++
++/* DMA - see rc32355_dma.h for full list of registers */
++
++#define RC32355_DMA_BASE (RC32355_REG_BASE + 0x38000)
++#define DMA_CHAN_OFFSET 0x14
++
++/* GPIO Controller */
++
++/* TDM Bus */
++
++/* 16550 UARTs */
++#ifdef __MIPSEB__
++#define RC32300_UART0_BASE (RC32355_REG_BASE + 0x50003)
++#define RC32300_UART1_BASE (RC32355_REG_BASE + 0x50023)
++#else
++#define RC32300_UART0_BASE (RC32355_REG_BASE + 0x50000)
++#define RC32300_UART1_BASE (RC32355_REG_BASE + 0x50020)
++#endif
++
++#define RC32300_UART0_IRQ (GROUP3_IRQ_BASE + 14)
++#define RC32300_UART1_IRQ (GROUP3_IRQ_BASE + 17)
++
++/* ATM */
++
++/* Ethernet - see rc32355_eth.h for full list of registers */
++
++#define RC32355_ETH_BASE (RC32355_REG_BASE + 0x60000)
++
++
++#define IDT_CLOCK_MULT 2
++
++/* Memory map of 79EB355 board */
++
++/* DRAM */
++#define RAM_BASE 0x00000000
++#define RAM_SIZE (32*1024*1024)
++
++/* SRAM (device 1) */
++#define SRAM_BASE 0x02000000
++#define SRAM_SIZE 0x00100000
++
++/* FLASH (device 2) */
++#define FLASH_BASE 0x0C000000
++#define FLASH_SIZE 0x00C00000
++
++/* ATM PHY (device 4) */
++#define ATM_PHY_BASE 0x14000000
++
++/* TDM switch (device 3) */
++#define TDM_BASE 0x1A000000
++
++/* LCD panel (device 3) */
++#define LCD_BASE 0x1A002000
++
++/* RTC (DS1511W) (device 3) */
++#define RTC_BASE 0x1A004000
++
++/* NVRAM (256 bytes internal to the DS1511 RTC) */
++#define NVRAM_ADDR RTC_BASE + 0x10
++#define NVRAM_DATA RTC_BASE + 0x13
++#define NVRAM_ENVSIZE_OFF 4
++#define NVRAM_ENVSTART_OFF 32
++
++#endif /* _RC32355_H_ */
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365_dma.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365_dma.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365_dma.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365_dma.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,226 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * RC32365/336 DMA hardware abstraction.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_RC32365_DMA_H__
++#define __IDT_RC32365_DMA_H__
++
++enum
++{
++ DMA0_PhysicalAddress = 0x18038000,
++ DMA_PhysicalAddress = DMA0_PhysicalAddress, // Default
++
++ DMA0_VirtualAddress = 0xb8038000,
++ DMA_VirtualAddress = DMA0_VirtualAddress, // Default
++} ;
++
++/*
++ * DMA descriptor (in physical memory).
++ */
++
++typedef struct DMAD_s
++{
++ u32 control ; // Control. use DMAD_*
++ u32 ca ; // Current Address.
++ u32 devcs ; // Device control and status.
++ u32 link ; // Next descriptor in chain.
++} volatile *DMAD_t ;
++
++enum
++{
++ DMAD_size = sizeof (struct DMAD_s),
++ DMAD_count_b = 0, // in DMAD_t -> control
++ DMAD_count_m = 0x0003ffff, // in DMAD_t -> control
++ DMAD_ds_b = 20, // in DMAD_t -> control
++ DMAD_ds_m = 0x00300000, // in DMAD_t -> control
++ DMAD_ds_extToMem0_v = 0,
++ DMAD_ds_memToExt0_v = 1,
++ DMAD_ds_extToMem1_v = 0,
++ DMAD_ds_memToExt1_v = 1,
++ DMAD_ds_ethRcv0_v = 0,
++ DMAD_ds_ethXmt0_v = 0,
++ DMAD_ds_ethRcv1_v = 0,
++ DMAD_ds_ethXmt2_v = 0,
++ DMAD_ds_memToFifo_v = 0,
++ DMAD_ds_fifoToMem_v = 0,
++ DMAD_ds_rng_de_v = 1,//randomNumberGenerator on LC/DE
++ DMAD_ds_pciToMem_v = 0,
++ DMAD_ds_memToPci_v = 0,
++ DMAD_ds_securityInput_v = 0,
++ DMAD_ds_securityOutput_v = 0,
++ DMAD_ds_rng_se_v = 0,//randomNumberGenerator on SE
++
++ DMAD_devcmd_b = 22, // in DMAD_t -> control
++ DMAD_devcmd_m = 0x01c00000, // in DMAD_t -> control
++ DMAD_devcmd_byte_v = 0, //memory-to-memory
++ DMAD_devcmd_halfword_v = 1, //memory-to-memory
++ DMAD_devcmd_word_v = 2, //memory-to-memory
++ DMAD_devcmd_2words_v = 3, //memory-to-memory
++ DMAD_devcmd_4words_v = 4, //memory-to-memory
++ DMAD_devcmd_6words_v = 5, //memory-to-memory
++ DMAD_devcmd_8words_v = 6, //memory-to-memory
++ DMAD_devcmd_16words_v = 7, //memory-to-memory
++ DMAD_cof_b = 25, // chain on finished
++ DMAD_cof_m = 0x02000000, //
++ DMAD_cod_b = 26, // chain on done
++ DMAD_cod_m = 0x04000000, //
++ DMAD_iof_b = 27, // interrupt on finished
++ DMAD_iof_m = 0x08000000, //
++ DMAD_iod_b = 28, // interrupt on done
++ DMAD_iod_m = 0x10000000, //
++ DMAD_t_b = 29, // terminated
++ DMAD_t_m = 0x20000000, //
++ DMAD_d_b = 30, // done
++ DMAD_d_m = 0x40000000, //
++ DMAD_f_b = 31, // finished
++ DMAD_f_m = 0x80000000, //
++} ;
++
++/*
++ * DMA register (within Internal Register Map).
++ */
++
++struct DMA_Chan_s
++{
++ u32 dmac ; // Control.
++ u32 dmas ; // Status.
++ u32 dmasm ; // Mask.
++ u32 dmadptr ; // Descriptor pointer.
++ u32 dmandptr ; // Next descriptor pointer.
++};
++
++typedef struct DMA_Chan_s volatile *DMA_Chan_t ;
++
++//DMA_Channels use DMACH_count instead
++
++enum
++{
++ DMAC_run_b = 0, //
++ DMAC_run_m = 0x00000001, //
++ DMAC_dm_b = 1, // done mask
++ DMAC_dm_m = 0x00000002, //
++ DMAC_mode_b = 2, //
++ DMAC_mode_m = 0x0000000c, //
++ DMAC_mode_auto_v = 0,
++ DMAC_mode_burst_v = 1,
++ DMAC_mode_transfer_v = 2, //usually used
++ DMAC_mode_reserved_v = 3,
++ DMAC_a_b = 4, //
++ DMAC_a_m = 0x00000010, //
++
++ DMAS_f_b = 0, // finished (sticky)
++ DMAS_f_m = 0x00000001, //
++ DMAS_d_b = 1, // done (sticky)
++ DMAS_d_m = 0x00000002, //
++ DMAS_c_b = 2, // chain (sticky)
++ DMAS_c_m = 0x00000004, //
++ DMAS_e_b = 3, // error (sticky)
++ DMAS_e_m = 0x00000008, //
++ DMAS_h_b = 4, // halt (sticky)
++ DMAS_h_m = 0x00000010, //
++
++ DMASM_f_b = 0, // finished (1=mask)
++ DMASM_f_m = 0x00000001, //
++ DMASM_d_b = 1, // done (1=mask)
++ DMASM_d_m = 0x00000002, //
++ DMASM_c_b = 2, // chain (1=mask)
++ DMASM_c_m = 0x00000004, //
++ DMASM_e_b = 3, // error (1=mask)
++ DMASM_e_m = 0x00000008, //
++ DMASM_h_b = 4, // halt (1=mask)
++ DMASM_h_m = 0x00000010, //
++} ;
++
++/*
++ * DMA channel definitions
++ */
++
++enum
++{
++ DMACH_ethRcv0 = 0,
++ DMACH_ethXmt0 = 1,
++ DMACH_ethRcv1 = 2,
++ DMACH_ethXmt2 = 3,
++ DMACH_pciToMem = 4,
++ DMACH_memToPci = 5,
++ DMACH_securityInput = 6,
++ DMACH_securityOutput = 7,
++ DMACH_rng = 8,
++
++ DMACH_count //must be last
++};
++
++
++typedef struct DMAC_s
++{
++ struct DMA_Chan_s ch [DMACH_count] ; //use ch[DMACH_]
++} volatile *DMA_t ;
++
++
++/*
++ * External DMA parameters
++*/
++
++enum
++{
++ DMADEVCMD_ts_b = 0, // ts field in devcmd
++ DMADEVCMD_ts_m = 0x00000007, // ts field in devcmd
++ DMADEVCMD_ts_byte_v = 0,
++ DMADEVCMD_ts_halfword_v = 1,
++ DMADEVCMD_ts_word_v = 2,
++ DMADEVCMD_ts_2word_v = 3,
++ DMADEVCMD_ts_4word_v = 4,
++ DMADEVCMD_ts_6word_v = 5,
++ DMADEVCMD_ts_8word_v = 6,
++ DMADEVCMD_ts_16word_v = 7
++};
++
++
++#if 1 // aws - Compatibility.
++# define EXTDMA_ts_b DMADEVCMD_ts_b
++# define EXTDMA_ts_m DMADEVCMD_ts_m
++# define EXTDMA_ts_byte_v DMADEVCMD_ts_byte_v
++# define EXTDMA_ts_halfword_v DMADEVCMD_ts_halfword_v
++# define EXTDMA_ts_word_v DMADEVCMD_ts_word_v
++# define EXTDMA_ts_2word_v DMADEVCMD_ts_2word_v
++# define EXTDMA_ts_4word_v DMADEVCMD_ts_4word_v
++# define EXTDMA_ts_6word_v DMADEVCMD_ts_6word_v
++# define EXTDMA_ts_8word_v DMADEVCMD_ts_8word_v
++# define EXTDMA_ts_16word_v DMADEVCMD_ts_16word_v
++#endif // aws - Compatibility.
++
++#endif // __IDT_RC32365_DMA_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365_dma_v.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365_dma_v.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365_dma_v.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365_dma_v.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,86 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * RC32365/336 DMA interface routines.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_RC32365_DMA_V_H__
++#define __IDT_RC32365_DMA_V_H__
++
++
++#include <asm/idt-boards/rc32300/rc32300.h>
++#include <asm/idt-boards/rc32300/rc32365_dma.h>
++#include <asm/idt-boards/rc32300/rc32365.h>
++
++#define DMA_CHAN_OFFSET 0x14
++#define IS_DMA_USED(X) (((X) & (DMAD_f_m | DMAD_d_m | DMAD_t_m)) != 0)
++#define IS_DMA_FINISHED(X) (((X) & (DMAD_f_m)) != 0)
++#define IS_DMA_DONE(X) (((X) & (DMAD_d_m)) != 0)
++
++#define DMA_COUNT(count) \
++ ((count) & DMAD_count_m)
++
++#define DMA_HALT_TIMEOUT 500
++
++static inline int rc32365_halt_dma(DMA_Chan_t ch)
++{
++ int timeout=1;
++ if (local_readl(&ch->dmac) & DMAC_run_m) {
++ local_writel(0, &ch->dmac);
++
++ for (timeout = DMA_HALT_TIMEOUT; timeout > 0; timeout--) {
++ if (local_readl(&ch->dmas) & DMAS_h_m) {
++ local_writel(0, &ch->dmas);
++ break;
++ }
++ }
++
++ }
++
++ return timeout ? 0 : 1;
++}
++
++
++static inline void rc32365_start_dma(DMA_Chan_t ch, u32 dma_addr)
++{
++ local_writel(0, &ch->dmandptr);
++ local_writel(dma_addr, &ch->dmadptr);
++}
++
++static inline void rc32365_chain_dma(DMA_Chan_t ch, u32 dma_addr)
++{
++ local_writel(dma_addr, &ch->dmandptr);
++}
++#endif //__IDT_RC32365_DMA_V_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365_eth.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365_eth.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365_eth.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365_eth.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,344 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * RC32365/336 Ethernet hardware abstraction.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_RC32365_ETH_H__
++#define __IDT_RC32365_ETH_H__
++
++enum
++{
++ ETH0_PhysicalAddress = 0x18058000,
++ ETH_PhysicalAddress = ETH0_PhysicalAddress, // Default
++ ETH0_VirtualAddress = 0xb8058000,
++
++ ETH_VirtualAddress = ETH0_VirtualAddress, // Default
++
++ ETH1_PhysicalAddress = 0x18060000,
++ ETH1_VirtualAddress = 0xb8060000, // Default
++} ;
++
++typedef struct
++{
++ u32 ethintfc ;
++ u32 ethfifott ;
++ u32 etharc ;
++ u32 ethhash0 ;
++ u32 ethhash1 ;
++ u32 ethu0 [4] ; // Reserved.
++ u32 ethpfs ;
++ u32 ethmcp ;
++ u32 eth_u1 [10] ; // Reserved.
++ u32 ethspare ;
++ u32 eth_u2 [42] ; // Reserved.
++ u32 ethsal0 ;
++ u32 ethsah0 ;
++ u32 ethsal1 ;
++ u32 ethsah1 ;
++ u32 ethsal2 ;
++ u32 ethsah2 ;
++ u32 ethsal3 ;
++ u32 ethsah3 ;
++ u32 ethrbc ;
++ u32 ethrpc ;
++ u32 ethrupc ;
++ u32 ethrfc ;
++ u32 ethtbc ;
++ u32 ethgpf ;
++ u32 eth_u9 [50] ; // Reserved.
++ u32 ethmac1 ;
++ u32 ethmac2 ;
++ u32 ethipgt ;
++ u32 ethipgr ;
++ u32 ethclrt ;
++ u32 ethmaxf ;
++ u32 eth_u10 ; // Reserved.
++ u32 ethmtest ;
++ u32 miimcfg ;
++ u32 miimcmd ;
++ u32 miimaddr ;
++ u32 miimwtd ;
++ u32 miimrdd ;
++ u32 miimind ;
++ u32 eth_u11 ; // Reserved.
++ u32 eth_u12 ; // Reserved.
++ u32 ethcfsa0 ;
++ u32 ethcfsa1 ;
++ u32 ethcfsa2 ;
++} volatile *ETH_t;
++
++enum
++{
++ ETHINTFC_en_b = 0,
++ ETHINTFC_en_m = 0x00000001,
++ ETHINTFC_its_b = 1,
++ ETHINTFC_its_m = 0x00000002,
++ ETHINTFC_rip_b = 2,
++ ETHINTFC_rip_m = 0x00000004,
++ ETHINTFC_jam_b = 3,
++ ETHINTFC_jam_m = 0x00000008,
++ ETHINTFC_ovr_b = 4,
++ ETHINTFC_ovr_m = 0x00000010,
++ ETHINTFC_und_b = 5,
++ ETHINTFC_und_m = 0x00000020,
++
++ ETHFIFOTT_tth_b = 0,
++ ETHFIFOTT_tth_m = 0x0000007f,
++
++ ETHARC_pro_b = 0,
++ ETHARC_pro_m = 0x00000001,
++ ETHARC_am_b = 1,
++ ETHARC_am_m = 0x00000002,
++ ETHARC_afm_b = 2,
++ ETHARC_afm_m = 0x00000004,
++ ETHARC_ab_b = 3,
++ ETHARC_ab_m = 0x00000008,
++
++ ETHSAL_byte5_b = 0,
++ ETHSAL_byte5_m = 0x000000ff,
++ ETHSAL_byte4_b = 8,
++ ETHSAL_byte4_m = 0x0000ff00,
++ ETHSAL_byte3_b = 16,
++ ETHSAL_byte3_m = 0x00ff0000,
++ ETHSAL_byte2_b = 24,
++ ETHSAL_byte2_m = 0xff000000,
++
++ ETHSAH_byte1_b = 0,
++ ETHSAH_byte1_m = 0x000000ff,
++ ETHSAH_byte0_b = 8,
++ ETHSAH_byte0_m = 0x0000ff00,
++
++ ETHGPF_ptv_b = 0,
++ ETHGPF_ptv_m = 0x0000ffff,
++
++ ETHPFS_pfd_b = 0,
++ ETHPFS_pfd_m = 0x00000001,
++
++ ETHCFSA0_cfsa4_b = 0,
++ ETHCFSA0_cfsa4_m = 0x000000ff,
++ ETHCFSA0_cfsa5_b = 8,
++ ETHCFSA0_cfsa5_m = 0x0000ff00,
++
++ ETHCFSA1_cfsa2_b = 0,
++ ETHCFSA1_cfsa2_m = 0x000000ff,
++ ETHCFSA1_cfsa3_b = 8,
++ ETHCFSA1_cfsa3_m = 0x0000ff00,
++
++ ETHCFSA2_cfsa0_b = 0,
++ ETHCFSA2_cfsa0_m = 0x000000ff,
++ ETHCFSA2_cfsa1_b = 8,
++ ETHCFSA2_cfsa1_m = 0x0000ff00,
++
++ ETHMAC1_re_b = 0,
++ ETHMAC1_re_m = 0x00000001,
++ ETHMAC1_paf_b = 1,
++ ETHMAC1_paf_m = 0x00000002,
++ ETHMAC1_rfc_b = 2,
++ ETHMAC1_rfc_m = 0x00000004,
++ ETHMAC1_tfc_b = 3,
++ ETHMAC1_tfc_m = 0x00000008,
++ ETHMAC1_lb_b = 4,
++ ETHMAC1_lb_m = 0x00000010,
++ ETHMAC1_mr_b = 31,
++ ETHMAC1_mr_m = 0x80000000,
++
++ ETHMAC2_fd_b = 0,
++ ETHMAC2_fd_m = 0x00000001,
++ ETHMAC2_flc_b = 1,
++ ETHMAC2_flc_m = 0x00000002,
++ ETHMAC2_hfe_b = 2,
++ ETHMAC2_hfe_m = 0x00000004,
++ ETHMAC2_dc_b = 3,
++ ETHMAC2_dc_m = 0x00000008,
++ ETHMAC2_cen_b = 4,
++ ETHMAC2_cen_m = 0x00000010,
++ ETHMAC2_pe_b = 5,
++ ETHMAC2_pe_m = 0x00000020,
++ ETHMAC2_vpe_b = 6,
++ ETHMAC2_vpe_m = 0x00000040,
++ ETHMAC2_ape_b = 7,
++ ETHMAC2_ape_m = 0x00000080,
++ ETHMAC2_ppe_b = 8,
++ ETHMAC2_ppe_m = 0x00000100,
++ ETHMAC2_lpe_b = 9,
++ ETHMAC2_lpe_m = 0x00000200,
++ ETHMAC2_nb_b = 12,
++ ETHMAC2_nb_m = 0x00001000,
++ ETHMAC2_bp_b = 13,
++ ETHMAC2_bp_m = 0x00002000,
++ ETHMAC2_ed_b = 14,
++ ETHMAC2_ed_m = 0x00004000,
++
++ ETHIPGT_ipgt_b = 0,
++ ETHIPGT_ipgt_m = 0x0000007f,
++
++ ETHIPGR_ipgr2_b = 0,
++ ETHIPGR_ipgr2_m = 0x0000007f,
++ ETHIPGR_ipgr1_b = 8,
++ ETHIPGR_ipgr1_m = 0x00007f00,
++
++ ETHCLRT_maxret_b = 0,
++ ETHCLRT_maxret_m = 0x0000000f,
++ ETHCLRT_colwin_b = 8,
++ ETHCLRT_colwin_m = 0x00003f00,
++
++ ETHMAXF_maxf_b = 0,
++ ETHMAXF_maxf_m = 0x0000ffff,
++
++ ETHMTEST_tb_b = 2,
++ ETHMTEST_tb_m = 0x00000004,
++
++ ETHMCP_div_b = 0,
++ ETHMCP_div_m = 0x000000ff,
++
++ MIIMCFG_rsv_b = 0,
++ MIIMCFG_rsv_m = 0x0000000c,
++
++ MIIMCMD_rd_b = 0,
++ MIIMCMD_rd_m = 0x00000001,
++ MIIMCMD_scn_b = 1,
++ MIIMCMD_scn_m = 0x00000002,
++
++ MIIMADDR_regaddr_b = 0,
++ MIIMADDR_regaddr_m = 0x0000001f,
++ MIIMADDR_phyaddr_b = 8,
++ MIIMADDR_phyaddr_m = 0x00001f00,
++
++ MIIMWTD_wdata_b = 0,
++ MIIMWTD_wdata_m = 0x0000ffff,
++
++ MIIMRDD_rdata_b = 0,
++ MIIMRDD_rdata_m = 0x0000ffff,
++
++ MIIMIND_bsy_b = 0,
++ MIIMIND_bsy_m = 0x00000001,
++ MIIMIND_scn_b = 1,
++ MIIMIND_scn_m = 0x00000002,
++ MIIMIND_nv_b = 2,
++ MIIMIND_nv_m = 0x00000004,
++
++} ;
++
++/*
++ * Values for the DEVCS field of the Ethernet DMA Rx and Tx descriptors.
++ */
++enum
++{
++ ETHRX_fd_b = 0,
++ ETHRX_fd_m = 0x00000001,
++ ETHRX_ld_b = 1,
++ ETHRX_ld_m = 0x00000002,
++ ETHRX_rok_b = 2,
++ ETHRX_rok_m = 0x00000004,
++ ETHRX_fm_b = 3,
++ ETHRX_fm_m = 0x00000008,
++ ETHRX_mp_b = 4,
++ ETHRX_mp_m = 0x00000010,
++ ETHRX_bp_b = 5,
++ ETHRX_bp_m = 0x00000020,
++ ETHRX_vlt_b = 6,
++ ETHRX_vlt_m = 0x00000040,
++ ETHRX_cf_b = 7,
++ ETHRX_cf_m = 0x00000080,
++ ETHRX_ovr_b = 8,
++ ETHRX_ovr_m = 0x00000100,
++ ETHRX_crc_b = 9,
++ ETHRX_crc_m = 0x00000200,
++ ETHRX_cv_b = 10,
++ ETHRX_cv_m = 0x00000400,
++ ETHRX_db_b = 11,
++ ETHRX_db_m = 0x00000800,
++ ETHRX_le_b = 12,
++ ETHRX_le_m = 0x00001000,
++ ETHRX_lor_b = 13,
++ ETHRX_lor_m = 0x00002000,
++ ETHRX_ces_b = 14,
++ ETHRX_ces_m = 0x00004000,
++ ETHRX_length_b = 16,
++ ETHRX_length_m = 0xffff0000,
++
++ ETHTX_fd_b = 0,
++ ETHTX_fd_m = 0x00000001,
++ ETHTX_ld_b = 1,
++ ETHTX_ld_m = 0x00000002,
++ ETHTX_oen_b = 2,
++ ETHTX_oen_m = 0x00000004,
++ ETHTX_pen_b = 3,
++ ETHTX_pen_m = 0x00000008,
++ ETHTX_cen_b = 4,
++ ETHTX_cen_m = 0x00000010,
++ ETHTX_hen_b = 5,
++ ETHTX_hen_m = 0x00000020,
++ ETHTX_tok_b = 6,
++ ETHTX_tok_m = 0x00000040,
++ ETHTX_mp_b = 7,
++ ETHTX_mp_m = 0x00000080,
++ ETHTX_bp_b = 8,
++ ETHTX_bp_m = 0x00000100,
++ ETHTX_und_b = 9,
++ ETHTX_und_m = 0x00000200,
++ ETHTX_of_b = 10,
++ ETHTX_of_m = 0x00000400,
++ ETHTX_ed_b = 11,
++ ETHTX_ed_m = 0x00000800,
++ ETHTX_ec_b = 12,
++ ETHTX_ec_m = 0x00001000,
++ ETHTX_lc_b = 13,
++ ETHTX_lc_m = 0x00002000,
++ ETHTX_td_b = 14,
++ ETHTX_td_m = 0x00004000,
++ ETHTX_crc_b = 15,
++ ETHTX_crc_m = 0x00008000,
++ ETHTX_le_b = 16,
++ ETHTX_le_m = 0x00010000,
++ ETHTX_cc_b = 17,
++ ETHTX_cc_m = 0x001E0000,
++} ;
++
++enum
++{
++ ETH0_IPABMC_PhysicalAddress = 0x18040010,
++ ETH0_IPABMC_VirtualAddress = 0xb8040000,
++ ETH1_IPABMC_PhysicalAddress = 0x18040018,
++ ETH1_IPABMC_VirtualAddress = 0xb8040018,
++} ;
++
++typedef struct
++{
++ u32 ipabmcrx ;
++ u32 ipabmctx ;
++}volatile *IPABM_ETH_t;
++#endif //__IDT_RC32365_ETH_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365_eth_v.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365_eth_v.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365_eth_v.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365_eth_v.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,72 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * RC32365/336 Ethernet status checking.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_RC32365_ETH_V_H__
++#define __IDT_RC32365_ETH_V_H__
++#include <asm/idt-boards/rc32300/rc32365_eth.h>
++
++#define IS_TX_TOK(X) (((X) & (1<<ETHTX_tok_b)) >> ETHTX_tok_b ) /* Transmit Okay */
++#define IS_TX_MP(X) (((X) & (1<<ETHTX_mp_b)) >> ETHTX_mp_b ) /* Multicast */
++#define IS_TX_BP(X) (((X) & (1<<ETHTX_bp_b)) >> ETHTX_bp_b ) /* Broadcast */
++#define IS_TX_UND_ERR(X) (((X) & (1<<ETHTX_und_b)) >> ETHTX_und_b ) /* Transmit FIFO Underflow */
++#define IS_TX_OF_ERR(X) (((X) & (1<<ETHTX_of_b)) >> ETHTX_of_b ) /* Oversized frame */
++#define IS_TX_ED_ERR(X) (((X) & (1<<ETHTX_ed_b)) >> ETHTX_ed_b ) /* Excessive deferral */
++#define IS_TX_EC_ERR(X) (((X) & (1<<ETHTX_ec_b)) >> ETHTX_ec_b) /* Excessive collisions */
++#define IS_TX_LC_ERR(X) (((X) & (1<<ETHTX_lc_b)) >> ETHTX_lc_b ) /* Late Collision */
++#define IS_TX_TD_ERR(X) (((X) & (1<<ETHTX_td_b)) >> ETHTX_td_b ) /* Transmit deferred*/
++#define IS_TX_CRC_ERR(X) (((X) & (1<<ETHTX_crc_b)) >> ETHTX_crc_b ) /* CRC Error */
++#define IS_TX_LE_ERR(X) (((X) & (1<<ETHTX_le_b)) >> ETHTX_le_b ) /* Length Error */
++
++#define TX_COLLISION_COUNT(X) (((X) & ETHTX_cc_m)>>ETHTX_cc_b) /* Collision Count */
++
++#define IS_RCV_ROK(X) (((X) & (1<<ETHRX_rok_b)) >> ETHRX_rok_b) /* Receive Okay */
++#define IS_RCV_FM(X) (((X) & (1<<ETHRX_fm_b)) >> ETHRX_fm_b) /* Is Filter Match */
++#define IS_RCV_MP(X) (((X) & (1<<ETHRX_mp_b)) >> ETHRX_mp_b) /* Is it MP */
++#define IS_RCV_BP(X) (((X) & (1<<ETHRX_bp_b)) >> ETHRX_bp_b) /* Is it BP */
++#define IS_RCV_VLT(X) (((X) & (1<<ETHRX_vlt_b)) >> ETHRX_vlt_b) /* VLAN Tag Detect */
++#define IS_RCV_CF(X) (((X) & (1<<ETHRX_cf_b)) >> ETHRX_cf_b) /* Control Frame */
++#define IS_RCV_OVR_ERR(X) (((X) & (1<<ETHRX_ovr_b)) >> ETHRX_ovr_b) /* Receive Overflow */
++#define IS_RCV_CRC_ERR(X) (((X) & (1<<ETHRX_crc_b)) >> ETHRX_crc_b) /* CRC Error */
++#define IS_RCV_CV_ERR(X) (((X) & (1<<ETHRX_cv_b)) >> ETHRX_cv_b) /* Code Violation */
++#define IS_RCV_DB_ERR(X) (((X) & (1<<ETHRX_db_b)) >> ETHRX_db_b) /* Dribble Bits */
++#define IS_RCV_LE_ERR(X) (((X) & (1<<ETHRX_le_b)) >> ETHRX_le_b) /* Length error */
++#define IS_RCV_LOR_ERR(X) (((X) & (1<<ETHRX_lor_b)) >> ETHRX_lor_b) /* Length Out of Range */
++#define IS_RCV_CES_ERR(X) (((X) & (1<<ETHRX_ces_b)) >> ETHRX_ces_b) /* Preamble error */
++#define RCVPKT_LENGTH(X) (((X) & ETHRX_length_m) >> ETHRX_length_b) /* Length of the received packet */
++
++#endif //__IDT_RC32365_ETH_V_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365_gpio.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365_gpio.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365_gpio.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365_gpio.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,181 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * RC32365/336 GPIO hardware abstraction.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_RC32365_GPIO_H__
++#define __IDT_RC32365_GPIO_H__
++
++enum
++{
++ GPIO0_PhysicalAddress = 0x18048000,
++ GPIO_PhysicalAddress = GPIO0_PhysicalAddress, // Default
++
++ GPIO0_VirtualAddress = 0xb8048000,
++ GPIO_VirtualAddress = GPIO0_VirtualAddress, // Default
++} ;
++
++typedef struct
++{
++ u32 gpiofunc; /* GPIO Function Register
++ * gpiofunc[x]==0 bit = gpio
++ * func[x]==1 bit = altfunc
++ */
++ u32 gpiocfg; /* GPIO Configuration Register
++ * gpiocfg[x]==0 bit = input
++ * gpiocfg[x]==1 bit = output
++ */
++ u32 gpiod; /* GPIO Data Register
++ * gpiod[x] read/write gpio pinX status
++ */
++ u32 gpioilevel; /* GPIO Interrupt Status Register
++ * interrupt level (see gpioistat)
++ */
++ u32 gpioistat; /* Gpio Interrupt Status Register
++ * istat[x] = (gpiod[x] == level[x])
++ * cleared in ISR (STICKY bits)
++ */
++ u32 gpionmien; /* GPIO Non-maskable Interrupt Enable Register */
++} volatile * GPIO_t ;
++
++typedef enum
++{
++ GPIO_gpio_v = 0, // gpiofunc use pin as GPIO.
++ GPIO_alt_v = 1, // gpiofunc use pin as alt.
++ GPIO_input_v = 0, // gpiocfg use pin as input.
++ GPIO_output_v = 1, // gpiocfg use pin as output.
++ GPIO_pin0_b = 0,
++ GPIO_pin0_m = 0x00000001,
++ GPIO_pin1_b = 1,
++ GPIO_pin1_m = 0x00000002,
++ GPIO_pin2_b = 2,
++ GPIO_pin2_m = 0x00000004,
++ GPIO_pin3_b = 3,
++ GPIO_pin3_m = 0x00000008,
++ GPIO_pin4_b = 4,
++ GPIO_pin4_m = 0x00000010,
++ GPIO_pin5_b = 5,
++ GPIO_pin5_m = 0x00000020,
++ GPIO_pin6_b = 6,
++ GPIO_pin6_m = 0x00000040,
++ GPIO_pin7_b = 7,
++ GPIO_pin7_m = 0x00000080,
++ GPIO_pin8_b = 8,
++ GPIO_pin8_m = 0x00000100,
++ GPIO_pin9_b = 9,
++ GPIO_pin9_m = 0x00000200,
++ GPIO_pin10_b = 10,
++ GPIO_pin10_m = 0x00000400,
++ GPIO_pin11_b = 11,
++ GPIO_pin11_m = 0x00000800,
++ GPIO_pin12_b = 12,
++ GPIO_pin12_m = 0x00001000,
++ GPIO_pin13_b = 13,
++ GPIO_pin13_m = 0x00002000,
++ GPIO_pin14_b = 14,
++ GPIO_pin14_m = 0x00004000,
++ GPIO_pin15_b = 15,
++ GPIO_pin15_m = 0x00008000,
++
++// Alternate function pins. Corrsponding gpiofunc bit set to GPIO_alt_v.
++
++ GPIO_u0sout_b = GPIO_pin0_b, // UART 0 serial out.
++ GPIO_u0sout_m = GPIO_pin0_m,
++ GPIO_u0sout_cfg_v = GPIO_output_v,
++
++ GPIO_u0sinp_b = GPIO_pin1_b, // UART 0 serial in.
++ GPIO_u0sinp_m = GPIO_pin1_m,
++ GPIO_u0sinp_cfg_v = GPIO_input_v,
++
++ GPIO_maddr22_b = GPIO_pin2_b, // M&P bus bit 22.
++ GPIO_maddr22_m = GPIO_pin2_m,
++ GPIO_maddr22_cfg_v = GPIO_output_v,
++
++ GPIO_maddr23_b = GPIO_pin3_b, // M&P bus bit 23.
++ GPIO_maddr23_m = GPIO_pin3_m,
++ GPIO_maddr23_cfg_v = GPIO_output_v,
++
++ GPIO_maddr24_b = GPIO_pin4_b, // M&P bus bit 24.
++ GPIO_maddr24_m = GPIO_pin4_m,
++ GPIO_maddr24_cfg_v = GPIO_output_v,
++
++ GPIO_maddr25_b = GPIO_pin5_b, // M&P bus bit 25.
++ GPIO_maddr25_m = GPIO_pin5_m,
++ GPIO_maddr25_cfg_v = GPIO_output_v,
++
++ GPIO_rngclk_b = GPIO_pin6_b, // reserved.
++ GPIO_rngclk_m = GPIO_pin6_m,
++ GPIO_rngclk_cfg_v = GPIO_input_v,
++
++ GPIO_sdckenp_b = GPIO_pin7_b, // reserved.
++ GPIO_sdckenp_m = GPIO_pin7_m,
++ GPIO_sdckenp_cfg_v = GPIO_output_v,
++
++ GPIO_cen1_b = GPIO_pin8_b, // reserved.
++ GPIO_cen1_m = GPIO_pin8_m,
++ GPIO_cen1_cfg_v = GPIO_output_v,
++
++ GPIO_cen2_b = GPIO_pin9_b, // reserved.
++ GPIO_cen2_m = GPIO_pin9_m,
++ GPIO_cen2_cfg_v = GPIO_output_v,
++
++ GPIO_regn_b = GPIO_pin10_b, // reserved.
++ GPIO_regn_m = GPIO_pin10_m,
++ GPIO_regn_cfg_v = GPIO_output_v,
++
++ GPIO_iordn_b = GPIO_pin11_b, // reserved.
++ GPIO_iordn_m = GPIO_pin11_m,
++ GPIO_iordn_cfg_v = GPIO_output_v,
++
++ GPIO_iowrn_b = GPIO_pin12_b, // reserved.
++ GPIO_iowrn_m = GPIO_pin12_m,
++ GPIO_iowrn_cfg_v = GPIO_output_v,
++
++ GPIO_pcireqn2_b = GPIO_pin13_b, // PCI messaging int.
++ GPIO_pcireqn2_m = GPIO_pin13_m,
++ GPIO_pcireqn2_cfg_v = GPIO_input_v,
++
++ GPIO_pcigntn2_b = GPIO_pin14_b, // PCI messaging int.
++ GPIO_pcigntn2_m = GPIO_pin14_m,
++ GPIO_pcigntn2_cfg_v = GPIO_output_v,
++
++ GPIO_pcimuintn_b = GPIO_pin15_b, // PCI messaging int.
++ GPIO_pcimuintn_m = GPIO_pin15_m,
++ GPIO_pcimuintn_cfg_v= GPIO_output_v,
++
++} GPIO_DEFS_t;
++
++#endif //__IDT_RC32365_GPIO_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365_gpio_v.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365_gpio_v.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365_gpio_v.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365_gpio_v.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,91 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Routines to set/clear/toggle GPIO on RC32365
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++#ifndef __IDT_RC32365_GPIO_V_H__
++#define __IDT_RC32365_GPIO_V_H__
++
++
++#ifdef _LANGUAGE_ASSEMBLY
++#define SET_GPIO(pin) \
++ lui t5,0xb804 ; \
++ ori t5,t5,0x8000 ; \
++ lw t4,8(t5) ; \
++ ori t4,t4,pin ; \
++ sw t4,8(t5) ;
++
++#define CLEAR_GPIO(pin) \
++ lui t5,0xb804 ; \
++ ori t5,t5,0x8000 ; \
++ lw t4,8(t5) ; \
++ lui t6,0xFFFF; \
++ ori t6,t6,0xFFFF; \
++ xori t6,t6,pin ; \
++ and t4,t6 ; \
++ sw t4,8(t5) ;
++
++#define TOGGLE_GPIO(pin) \
++ lui t5,0xb804 ; \
++ ori t5,t5,0x8000 ; \
++ lw t4,8(t5) ; \
++ xori t4,t4,pin ; \
++ sw t4,8(t5) ;
++
++#else // !_LANGUAGE_ASSEMBLY
++#include <asm/rc32300/types.h>
++#include <asm/rc32300/rc32365_gpio.h>
++#include <asm/rc32300/rc32365.h>
++
++static inline void set_gpio(unsigned long pin)
++{
++ idt_gpio->gpiod |= pin;
++}
++
++static inline void clear_gpio(unsigned long pin)
++{
++ idt_gpio->gpiod &= ~pin;
++}
++static inline void toggle_gpio(unsigned long pin)
++{
++ idt_gpio->gpiod ^= pin;
++}
++#define SET_GPIO(pin) set_gpio(pin)
++#define CLEAR_GPIO(pin) clear_gpio(pin)
++#define TOGGLE_GPIO(pin) toggle_gpio(pin)
++#endif // _LANGUAGE_ASSEMBLY
++
++#endif //__IDT_RC32365_GPIO_V_H__
++
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,160 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Definitions for IDT RC32365 CPU.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_RC32365_H__
++#define __IDT_RC32365_H__
++
++extern unsigned int cedar_za;
++
++/* Base address of internal registers */
++#define RC32365_REG_BASE 0x18000000
++
++/* System ID Registers */
++#define CPU_SYSID (RC32365_REG_BASE + 0x00018)
++#define CPU_DEVTYPE (RC32365_REG_BASE + 0x0001c)
++
++/* Reset Controller */
++#define RESET_CNTL (RC32365_REG_BASE + 0x08000)
++#define BOOT_VECTOR (RC32365_REG_BASE + 0x08004)
++
++/* Device Controller */
++#define DEV0_BASE (RC32365_REG_BASE + 0x10000)
++#define DEV0_MASK (RC32365_REG_BASE + 0x10004)
++#define DEV0_CNTL (RC32365_REG_BASE + 0x10008)
++#define DEV0_TIMING (RC32365_REG_BASE + 0x1000c)
++#define DEV_REG_OFFSET 0x10
++
++/* SDRAM Controller */
++#define SDRAM0_BASE (RC32365_REG_BASE + 0x18000)
++#define SDRAM0_MASK (RC32365_REG_BASE + 0x18004)
++#define SDRAM1_BASE (RC32365_REG_BASE + 0x18008)
++#define SDRAM1_MASK (RC32365_REG_BASE + 0x1800c)
++#define SDRAM_CNTL (RC32365_REG_BASE + 0x18010)
++
++/* Counters/Timers */
++#define TIMER0_COUNT (RC32365_REG_BASE + 0x20000)
++#define TIMER0_COMPARE (RC32365_REG_BASE + 0x20004)
++#define TIMER0_CNTL (RC32365_REG_BASE + 0x20008)
++#define TIMER0_SELECT (RC32365_REG_BASE + 0x2000c)
++#define TIMER_REG_OFFSET 0x10
++
++/* System Integrity */
++
++/* Interrupt Controller */
++#define IC_GROUP0_PEND (RC32365_REG_BASE + 0x30000)
++#define IC_GROUP0_TEST (RC32365_REG_BASE + 0x30004)
++#define IC_GROUP0_MASK (RC32365_REG_BASE + 0x30008)
++#define IC_GROUP_OFFSET 0x0c
++
++#define NUM_INTR_GROUPS 5
++/*
++ * The IRQ mapping is as follows:
++ *
++ * IRQ Mapped To
++ * --- -------------------
++ * 0 SW0 (IP0) SW0 intr
++ * 1 SW1 (IP1) SW1 intr
++ * - Int0 (IP2) mapped to GROUP0_IRQ_BASE
++ * - Int1 (IP3) mapped to GROUP1_IRQ_BASE
++ * - Int2 (IP4) mapped to GROUP2_IRQ_BASE
++ * - Int3 (IP5) mapped to GROUP3_IRQ_BASE
++ * - Int4 (IP6) mapped to GROUP4_IRQ_BASE
++ * 7 Int5 (IP7) CP0 Timer
++ *
++ * IRQ's 8 and up are all mapped to Int0-4 (IP2-IP6), which
++ * internally on the RC32365 is routed to the Expansion
++ * Interrupt Controller.
++ */
++#define MIPS_CPU_TIMER_IRQ 7
++
++#define GROUP0_IRQ_BASE 8 // Counter/Timers, UCW
++#define GROUP1_IRQ_BASE (GROUP0_IRQ_BASE + 32) // DMA
++#define GROUP2_IRQ_BASE (GROUP1_IRQ_BASE + 32) // RNG, SEC
++#define GROUP3_IRQ_BASE (GROUP2_IRQ_BASE + 32) // Eth, PCI, UARTs
++#define GROUP4_IRQ_BASE (GROUP3_IRQ_BASE + 32) // GPIO
++
++#define RC32365_NR_IRQS (GROUP4_IRQ_BASE + 32)
++
++/* DMA - see rc32365_dma.h for full list of registers */
++
++#define RC32365_DMA_BASE (RC32365_REG_BASE + 0x38000)
++#define DMA_CHAN_OFFSET 0x14
++
++/* GPIO Controller */
++#define idt_gpio ((volatile GPIO_t) GPIO0_VirtualAddress)
++
++/* 16550 UARTs */
++#ifdef __MIPSEB__
++#define RC32300_UART0_BASE (RC32365_REG_BASE + 0x50003)
++#else
++#define RC32300_UART0_BASE (RC32365_REG_BASE + 0x50000)
++#endif
++#define RC32300_UART0_IRQ (GROUP3_IRQ_BASE + 0)
++
++/* Ethernet - see rc32365_eth.h for full list of registers */
++
++#define RC32365_ETH_BASE (RC32365_REG_BASE + 0x58000)
++
++#define IDT_CLOCK_MULT 2
++
++/* FLASH (device 1) */
++#define FLASH_BASE 0x08000000
++#define FLASH_SIZE 0x00800000
++
++/* LCD 4-digit display (device 2) */
++#define LCD_DIGIT0 0x0C000003
++#define LCD_DIGIT1 0x0C000002
++#define LCD_DIGIT2 0x0C000001
++#define LCD_DIGIT3 0x0C000000
++
++/* RTC (DS1553) (device 2) */
++#define RTC_BASE 0x0c800000
++/* NVRAM */
++#define NVRAM_BASE RTC_BASE
++#define NVRAM_ENVSIZE_OFF 4
++#define NVRAM_ENVSTART_OFF 32
++
++/* Interrupts routed on 79EB365 board */
++#define RC32365_PCI_INTA_IRQ (GROUP4_IRQ_BASE + 8)
++#define RC32365_PCI_INTB_IRQ (GROUP4_IRQ_BASE + 9)
++#define RC32365_PCI_INTC_IRQ (GROUP4_IRQ_BASE + 10)
++#define RC32365_PCI_INTD_IRQ (GROUP4_IRQ_BASE + 11)
++
++#define RAM_SIZE (32 * 1024 * 1024)
++
++#endif //__IDT_RC32365_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365_pci.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365_pci.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365_pci.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365_pci.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,515 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Datatype declaration for IDT 79EB365/336 PCI
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_RC32365_PCI_H__
++#define __IDT_RC32365_PCI_H__
++
++enum
++{
++ PCI0_PhysicalAddress = 0x18068000,
++ PCI_PhysicalAddress = PCI0_PhysicalAddress,
++
++ PCI0_VirtualAddress = 0xb8068000,
++ PCI_VirtualAddress = PCI0_VirtualAddress,
++} ;
++
++enum
++{
++ PCI_LbaCount = 4, // Local base addresses.
++} ;
++
++typedef struct
++{
++ u32 a ; // Address.
++ u32 c ; // Control.
++ u32 m ; // mapping.
++} PCI_Map_s ;
++
++typedef struct
++{
++ u32 pcic ;
++ u32 pcis ;
++ u32 pcism ;
++ u32 pcicfga ;
++ u32 pcicfgd ;
++ PCI_Map_s pcilba [PCI_LbaCount] ;
++ u32 pcidac ;
++ u32 pcidas ;
++ u32 pcidasm ;
++ u32 pcidad ;
++ u32 pcidma8c ;
++ u32 pcidma9c ;
++ u32 pcitc ;
++} volatile *PCI_t ;
++
++// PCI messaging unit.
++enum
++{
++ PCIM_Count = 2,
++} ;
++typedef struct
++{
++ u32 pciim [PCIM_Count] ;
++ u32 pciom [PCIM_Count] ;
++ u32 pciid ;
++ u32 pciiic ;
++ u32 pciiim ;
++ u32 pciiod ;
++ u32 pciioic ;
++ u32 pciioim ;
++} volatile *PCIM_t ;
++
++/*******************************************************************************
++ *
++ * PCI Control Register
++ *
++ ******************************************************************************/
++enum
++{
++ PCIC_en_b = 0,
++ PCIC_en_m = 0x00000001,
++ PCIC_tnr_b = 1,
++ PCIC_tnr_m = 0x00000002,
++ PCIC_sce_b = 2,
++ PCIC_sce_m = 0x00000004,
++ PCIC_ien_b = 3,
++ PCIC_ien_m = 0x00000008,
++ PCIC_aaa_b = 4,
++ PCIC_aaa_m = 0x00000010,
++ PCIC_eap_b = 5,
++ PCIC_eap_m = 0x00000020,
++ PCIC_pcim_b = 6,
++ PCIC_pcim_m = 0x000001c0,
++ PCIC_pcim_disabled_v = 0,
++ PCIC_pcim_tnr_v = 1, // Satellite - target not ready
++ PCIC_pcim_suspend_v = 2, // Satellite - suspended CPU.
++ PCIC_pcim_extern_v = 3, // Host - external arbiter.
++ PCIC_pcim_fixed_v = 4, // Host - fixed priority arb.
++ PCIC_pcim_roundrobin_v = 5, // Host - round robin priority.
++ PCIC_pcim_reserved6_v = 6,
++ PCIC_pcim_reserved7_v = 7,
++ PCIC_igm_b = 9,
++ PCIC_igm_m = 0x00000200,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Status Register
++ *
++ ******************************************************************************/
++enum {
++ PCIS_eed_b = 0,
++ PCIS_eed_m = 0x00000001,
++ PCIS_wr_b = 1,
++ PCIS_wr_m = 0x00000002,
++ PCIS_nmi_b = 2,
++ PCIS_nmi_m = 0x00000004,
++ PCIS_ii_b = 3,
++ PCIS_ii_m = 0x00000008,
++ PCIS_cwe_b = 4,
++ PCIS_cwe_m = 0x00000010,
++ PCIS_cre_b = 5,
++ PCIS_cre_m = 0x00000020,
++ PCIS_mdpe_b = 6,
++ PCIS_mdpe_m = 0x00000040,
++ PCIS_sta_b = 7,
++ PCIS_sta_m = 0x00000080,
++ PCIS_rta_b = 8,
++ PCIS_rta_m = 0x00000100,
++ PCIS_rma_b = 9,
++ PCIS_rma_m = 0x00000200,
++ PCIS_sse_b = 10,
++ PCIS_sse_m = 0x00000400,
++ PCIS_ose_b = 11,
++ PCIS_ose_m = 0x00000800,
++ PCIS_pe_b = 12,
++ PCIS_pe_m = 0x00001000,
++ PCIS_tae_b = 13,
++ PCIS_tae_m = 0x00002000,
++ PCIS_rle_b = 14,
++ PCIS_rle_m = 0x00004000,
++ PCIS_bme_b = 15,
++ PCIS_bme_m = 0x00008000,
++ PCIS_prd_b = 16,
++ PCIS_prd_m = 0x00010000,
++ PCIS_rip_b = 17,
++ PCIS_rip_m = 0x00020000,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Status Mask Register
++ *
++ ******************************************************************************/
++enum {
++ PCISM_eed_b = 0,
++ PCISM_eed_m = 0x00000001,
++ PCISM_wr_b = 1,
++ PCISM_wr_m = 0x00000002,
++ PCISM_nmi_b = 2,
++ PCISM_nmi_m = 0x00000004,
++ PCISM_ii_b = 3,
++ PCISM_ii_m = 0x00000008,
++ PCISM_cwe_b = 4,
++ PCISM_cwe_m = 0x00000010,
++ PCISM_cre_b = 5,
++ PCISM_cre_m = 0x00000020,
++ PCISM_mdpe_b = 6,
++ PCISM_mdpe_m = 0x00000040,
++ PCISM_sta_b = 7,
++ PCISM_sta_m = 0x00000080,
++ PCISM_rta_b = 8,
++ PCISM_rta_m = 0x00000100,
++ PCISM_rma_b = 9,
++ PCISM_rma_m = 0x00000200,
++ PCISM_sse_b = 10,
++ PCISM_sse_m = 0x00000400,
++ PCISM_ose_b = 11,
++ PCISM_ose_m = 0x00000800,
++ PCISM_pe_b = 12,
++ PCISM_pe_m = 0x00001000,
++ PCISM_tae_b = 13,
++ PCISM_tae_m = 0x00002000,
++ PCISM_rle_b = 14,
++ PCISM_rle_m = 0x00004000,
++ PCISM_bme_b = 15,
++ PCISM_bme_m = 0x00008000,
++ PCISM_prd_b = 16,
++ PCISM_prd_m = 0x00010000,
++ PCISM_rip_b = 17,
++ PCISM_rip_m = 0x00020000,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Configuration Address Register
++ *
++ ******************************************************************************/
++enum {
++ PCICFGA_reg_b = 2,
++ PCICFGA_reg_m = 0x000000fc,
++ PCICFGA_reg_id_v = 0x00>>2, //use PCFGID_
++ PCICFGA_reg_04_v = 0x04>>2, //use PCFG04_
++ PCICFGA_reg_08_v = 0x08>>2, //use PCFG08_
++ PCICFGA_reg_0C_v = 0x0C>>2, //use PCFG0C_
++ PCICFGA_reg_pba0_v = 0x10>>2, //use PCIPBA_
++ PCICFGA_reg_pba1_v = 0x14>>2, //use PCIPBA_
++ PCICFGA_reg_pba2_v = 0x18>>2, //use PCIPBA_
++ PCICFGA_reg_pba3_v = 0x1c>>2, //use PCIPBA_
++ PCICFGA_reg_subsystem_v = 0x2c>>2, //use PCFGSS_
++ PCICFGA_reg_3C_v = 0x3C>>2, //use PCFG3C_
++ PCICFGA_reg_pba0c_v = 0x44>>2, //use PCIPBAC_
++ PCICFGA_reg_pba0m_v = 0x48>>2,
++ PCICFGA_reg_pba1c_v = 0x4c>>2, //use PCIPBAC_
++ PCICFGA_reg_pba1m_v = 0x50>>2,
++ PCICFGA_reg_pba2c_v = 0x54>>2, //use PCIPBAC_
++ PCICFGA_reg_pba2m_v = 0x58>>2,
++ PCICFGA_reg_pba3c_v = 0x5c>>2, //use PCIPBAC_
++ PCICFGA_reg_pba3m_v = 0x60>>2,
++ PCICFGA_reg_pmgt_v = 0x64>>2,
++ PCICFGA_func_b = 8,
++ PCICFGA_func_m = 0x00000700,
++ PCICFGA_dev_b = 11,
++ PCICFGA_dev_m = 0x0000f800,
++ PCICFGA_dev_internal_v = 0,
++ PCICFGA_bus_b = 16,
++ PCICFGA_bus_m = 0x00ff0000,
++ PCICFGA_bus_type0_v = 0, //local bus
++ PCICFGA_en_b = 31, // read only
++ PCICFGA_en_m = 0x80000000,
++} ;
++
++enum {
++ PCFGID_vendor_b = 0,
++ PCFGID_vendor_m = 0x0000ffff,
++ PCFGID_vendor_IDT_v = 0x111d,
++ PCFGID_device_b = 16,
++ PCFGID_device_m = 0xffff0000,
++ PCFGID_device_Acaciade_v = 0x0207,
++
++ PCFG04_command_ioena_b = 1,
++ PCFG04_command_ioena_m = 0x00000001,
++ PCFG04_command_memena_b = 2,
++ PCFG04_command_memena_m = 0x00000002,
++ PCFG04_command_bmena_b = 3,
++ PCFG04_command_bmena_m = 0x00000004,
++ PCFG04_command_mwinv_b = 5,
++ PCFG04_command_mwinv_m = 0x00000010,
++ PCFG04_command_parena_b = 7,
++ PCFG04_command_parena_m = 0x00000040,
++ PCFG04_command_serrena_b = 9,
++ PCFG04_command_serrena_m = 0x00000100,
++ PCFG04_command_fastbbena_b = 10,
++ PCFG04_command_fastbbena_m = 0x00000200,
++ PCFG04_status_b = 16,
++ PCFG04_status_m = 0xffff0000,
++ PCFG04_status_66MHz_b = 21, // 66 MHz enable
++ PCFG04_status_66MHz_m = 0x00200000,
++ PCFG04_status_fbb_b = 23,
++ PCFG04_status_fbb_m = 0x00800000,
++ PCFG04_status_mdpe_b = 24,
++ PCFG04_status_mdpe_m = 0x01000000,
++ PCFG04_status_dst_b = 25,
++ PCFG04_status_dst_m = 0x06000000,
++ PCFG04_status_sta_b = 27,
++ PCFG04_status_sta_m = 0x08000000,
++ PCFG04_status_rta_b = 28,
++ PCFG04_status_rta_m = 0x10000000,
++ PCFG04_status_rma_b = 29,
++ PCFG04_status_rma_m = 0x20000000,
++ PCFG04_status_sse_b = 30,
++ PCFG04_status_sse_m = 0x40000000,
++ PCFG04_status_pe_b = 31,
++ PCFG04_status_pe_m = 0x40000000,
++
++ PCFG08_revId_b = 0,
++ PCFG08_revId_m = 0x000000ff,
++ PCFG08_classCode_b = 0,
++ PCFG08_classCode_m = 0xffffff00,
++ PCFG08_classCode_bridge_v = 06,
++ PCFG08_classCode_proc_v = 0x0b3000, // processor-MIPS
++ PCFG0C_cacheline_b = 0,
++ PCFG0C_cacheline_m = 0x000000ff,
++ PCFG0C_masterLatency_b = 8,
++ PCFG0C_masterLatency_m = 0x0000ff00,
++ PCFG0C_headerType_b = 16,
++ PCFG0C_headerType_m = 0x00ff0000,
++ PCFG0C_bist_b = 24,
++ PCFG0C_bist_m = 0xff000000,
++
++ PCIPBA_msi_b = 0,
++ PCIPBA_msi_m = 0x00000001,
++ PCIPBA_p_b = 3,
++ PCIPBA_p_m = 0x00000004,
++ PCIPBA_baddr_b = 8,
++ PCIPBA_baddr_m = 0xffffff00,
++
++ PCFGSS_vendorId_b = 0,
++ PCFGSS_vendorId_m = 0x0000ffff,
++ PCFGSS_id_b = 16,
++ PCFGSS_id_m = 0xffff0000,
++
++ PCFG3C_interruptLine_b = 0,
++ PCFG3C_interruptLine_m = 0x000000ff,
++ PCFG3C_interruptPin_b = 8,
++ PCFG3C_interruptPin_m = 0x0000ff00,
++ PCFG3C_minGrant_b = 16,
++ PCFG3C_minGrant_m = 0x00ff0000,
++ PCFG3C_maxLat_b = 24,
++ PCFG3C_maxLat_m = 0xff000000,
++
++ PCIPBAC_msi_b = 0,
++ PCIPBAC_msi_m = 0x00000001,
++ PCIPBAC_p_b = 1,
++ PCIPBAC_p_m = 0x00000002,
++ PCIPBAC_size_b = 2,
++ PCIPBAC_size_m = 0x0000007c,
++ PCIPBAC_sb_b = 7,
++ PCIPBAC_sb_m = 0x00000080,
++ PCIPBAC_pp_b = 8,
++ PCIPBAC_pp_m = 0x00000100,
++ PCIPBAC_mr_b = 9,
++ PCIPBAC_mr_m = 0x00000600,
++ PCIPBAC_mr_read_v =0, //no prefetching
++ PCIPBAC_mr_readLine_v =1,
++ PCIPBAC_mr_readMult_v =2,
++ PCIPBAC_mrl_b = 11,
++ PCIPBAC_mrl_m = 0x00000800,
++ PCIPBAC_mrm_b = 12,
++ PCIPBAC_mrm_m = 0x00001000,
++ PCIPBAC_trp_b = 13,
++ PCIPBAC_trp_m = 0x00002000,
++
++ PCFG40_trdyTimeout_b = 0,
++ PCFG40_trdyTimeout_m = 0x000000ff,
++ PCFG40_retryLim_b = 8,
++ PCFG40_retryLim_m = 0x0000ff00,
++};
++
++/*******************************************************************************
++ *
++ * PCI Local Base Address [0|1|2|3] Register
++ *
++ ******************************************************************************/
++enum {
++ PCILBA_baddr_b = 0, // In PCI_t -> pcilba [] .a
++ PCILBA_baddr_m = 0xffffff00,
++} ;
++/*******************************************************************************
++ *
++ * PCI Local Base Address Control Register
++ *
++ ******************************************************************************/
++enum {
++ PCILBAC_msi_b = 0, // In pPci->pcilba[i].c
++ PCILBAC_msi_m = 0x00000001,
++ PCILBAC_msi_mem_v = 0,
++ PCILBAC_msi_io_v = 1,
++ PCILBAC_size_b = 2, // In pPci->pcilba[i].c
++ PCILBAC_size_m = 0x0000007c,
++ PCILBAC_sb_b = 7, // In pPci->pcilba[i].c
++ PCILBAC_sb_m = 0x00000080,
++ PCILBAC_rt_b = 8, // In pPci->pcilba[i].c
++ PCILBAC_rt_m = 0x00000100,
++ PCILBAC_rt_noprefetch_v = 0, // mem read
++ PCILBAC_rt_prefetch_v = 1, // mem readline
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Local Base Address [0|1|2|3] Mapping Register
++ *
++ ******************************************************************************/
++enum {
++ PCILBAM_maddr_b = 8,
++ PCILBAM_maddr_m = 0xffffff00,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Decoupled Access Control Register
++ *
++ ******************************************************************************/
++enum {
++ PCIDAC_den_b = 0,
++ PCIDAC_den_m = 0x00000001,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Decoupled Access Status Register
++ *
++ ******************************************************************************/
++enum {
++ PCIDAS_d_b = 0,
++ PCIDAS_d_m = 0x00000001,
++ PCIDAS_b_b = 1,
++ PCIDAS_b_m = 0x00000002,
++ PCIDAS_e_b = 2,
++ PCIDAS_e_m = 0x00000004,
++ PCIDAS_ofe_b = 3,
++ PCIDAS_ofe_m = 0x00000008,
++ PCIDAS_off_b = 4,
++ PCIDAS_off_m = 0x00000010,
++ PCIDAS_ife_b = 5,
++ PCIDAS_ife_m = 0x00000020,
++ PCIDAS_iff_b = 6,
++ PCIDAS_iff_m = 0x00000040,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI DMA Channel 8 Configuration Register
++ *
++ ******************************************************************************/
++enum
++{
++ PCIDMA8C_mbs_b = 0, // Maximum Burst Size.
++ PCIDMA8C_mbs_m = 0x00000fff, // { pcidma8c }
++ PCIDMA8C_our_b = 12, // Optimize Unaligned Burst Reads.
++ PCIDMA8C_our_m = 0x00001000, // { pcidma8c }
++} ;
++
++/*******************************************************************************
++ *
++ * PCI DMA Channel 9 Configuration Register
++ *
++ ******************************************************************************/
++enum
++{
++ PCIDMA9C_mbs_b = 0, // Maximum Burst Size.
++ PCIDMA9C_mbs_m = 0x00000fff, // { pcidma9c }
++} ;
++
++/*******************************************************************************
++ *
++ * PCI to Memory(DMA Channel 8) AND Memory to PCI DMA(DMA Channel 9)Descriptors
++ *
++ ******************************************************************************/
++enum {
++ PCIDMAD_pt_b = 22, // in DEVCMD field (descriptor)
++ PCIDMAD_pt_m = 0x00c00000, // preferred transaction field
++ // These are for reads (DMA channel 8)
++ PCIDMAD_devcmd_mr_v = 0, //memory read
++ PCIDMAD_devcmd_mrl_v = 1, //memory read line
++ PCIDMAD_devcmd_mrm_v = 2, //memory read multiple
++ PCIDMAD_devcmd_ior_v = 3, //I/O read
++ // These are for writes (DMA channel 9)
++ PCIDMAD_devcmd_mw_v = 0, //memory write
++ PCIDMAD_devcmd_mwi_v = 1, //memory write invalidate
++ PCIDMAD_devcmd_iow_v = 3, //I/O write
++
++ // Swap byte field applies to both DMA channel 8 and 9
++ PCIDMAD_sb_b = 24, // in DEVCMD field (descriptor)
++ PCIDMAD_sb_m = 0x01000000, // swap byte field
++} ;
++
++
++/*******************************************************************************
++ *
++ * PCI Target Control Register
++ *
++ ******************************************************************************/
++enum
++{
++ PCITC_rtimer_b = 0, // In PCITC_t -> pcitc
++ PCITC_rtimer_m = 0x000000ff,
++ PCITC_dtimer_b = 8, // In PCITC_t -> pcitc
++ PCITC_dtimer_m = 0x0000ff00,
++ PCITC_rdr_b = 18, // In PCITC_t -> pcitc
++ PCITC_rdr_m = 0x00040000,
++ PCITC_ddt_b = 19, // In PCITC_t -> pcitc
++ PCITC_ddt_m = 0x00080000,
++} ;
++/*******************************************************************************
++ *
++ * PCI messaging unit [applies to both inbound and outbound registers ]
++ *
++ ******************************************************************************/
++enum
++{
++ PCIM_m0_b = 0, // In PCIM_t -> {pci{iic,iim,ioic,ioim}}
++ PCIM_m0_m = 0x00000001, // inbound or outbound message 0
++ PCIM_m1_b = 1, // In PCIM_t -> {pci{iic,iim,ioic,ioim}}
++ PCIM_m1_m = 0x00000002, // inbound or outbound message 1
++ PCIM_db_b = 2, // In PCIM_t -> {pci{iic,iim,ioic,ioim}}
++ PCIM_db_m = 0x00000004, // inbound or outbound doorbell
++};
++
++
++#endif // __IDT_RC32365_PCI_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365_pci_v.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365_pci_v.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32300/rc32365_pci_v.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32300/rc32365_pci_v.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,217 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * PCI header values for IDT 79EB365/336
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_RC32365_PCI_V_H__
++#define __IDT_RC32365_PCI_V_H__
++
++
++#define PCI_MSG_VirtualAddress 0xB806C010
++#define rc32365_pci ((volatile PCI_t) PCI0_VirtualAddress)
++#define rc32365_pci_msg ((volatile PCIM_t) PCI_MSG_VirtualAddress)
++
++#define PCIM_SHFT 0x6
++#define PCIM_BIT_LEN 0x7
++#define PCIM_H_EA 0x3
++#define PCIM_H_IA_FIX 0x4
++#define PCIM_H_IA_RR 0x5
++
++#define PCI_ADDR_START 0x50000000
++
++#define CPUTOPCI_MEM_WIN 0x02000000
++#define CPUTOPCI_IO_WIN 0x00100000
++#define PCILBA_SIZE_SHFT 2
++#define PCILBA_SIZE_MASK 0x1F
++#define SIZE_256MB 0x1C
++#define SIZE_128MB 0x1B
++#define SIZE_64MB 0x1A
++#define SIZE_32MB 0x19
++#define SIZE_16MB 0x18
++#define SIZE_4MB 0x16
++#define SIZE_2MB 0x15
++#define SIZE_1MB 0x14
++#define CEDAR_CONFIG0_ADDR 0x80000000
++#define CEDAR_CONFIG1_ADDR 0x80000004
++#define CEDAR_CONFIG2_ADDR 0x80000008
++#define CEDAR_CONFIG3_ADDR 0x8000000C
++#define CEDAR_CONFIG4_ADDR 0x80000010
++#define CEDAR_CONFIG5_ADDR 0x80000014
++#define CEDAR_CONFIG6_ADDR 0x80000018
++#define CEDAR_CONFIG7_ADDR 0x8000001C
++#define CEDAR_CONFIG8_ADDR 0x80000020
++#define CEDAR_CONFIG9_ADDR 0x80000024
++#define CEDAR_CONFIG10_ADDR 0x80000028
++#define CEDAR_CONFIG11_ADDR 0x8000002C
++#define CEDAR_CONFIG12_ADDR 0x80000030
++#define CEDAR_CONFIG13_ADDR 0x80000034
++#define CEDAR_CONFIG14_ADDR 0x80000038
++#define CEDAR_CONFIG15_ADDR 0x8000003C
++#define CEDAR_CONFIG16_ADDR 0x80000040
++#define CEDAR_CONFIG17_ADDR 0x80000044
++#define CEDAR_CONFIG18_ADDR 0x80000048
++#define CEDAR_CONFIG19_ADDR 0x8000004C
++#define CEDAR_CONFIG20_ADDR 0x80000050
++#define CEDAR_CONFIG21_ADDR 0x80000054
++#define CEDAR_CONFIG22_ADDR 0x80000058
++#define CEDAR_CONFIG23_ADDR 0x8000005C
++#define CEDAR_CONFIG24_ADDR 0x80000060
++#define CEDAR_CONFIG25_ADDR 0x80000064
++#define CEDAR_CMD (PCFG04_command_ioena_m | \
++ PCFG04_command_memena_m | \
++ PCFG04_command_bmena_m | \
++ PCFG04_command_mwinv_m | \
++ PCFG04_command_parena_m | \
++ PCFG04_command_serrena_m )
++
++#define CEDAR_STAT (PCFG04_status_mdpe_m | \
++ PCFG04_status_sta_m | \
++ PCFG04_status_rta_m | \
++ PCFG04_status_rma_m | \
++ PCFG04_status_sse_m | \
++ PCFG04_status_pe_m)
++
++#define CEDAR_CNFG1 ((CEDAR_STAT << 16) | \
++ CEDAR_CMD)
++
++#define CEDAR_REVID 0
++#define CEDAR_CLASS_CODE 0
++#define CEDAR_CNFG2 ((CEDAR_CLASS_CODE << 8) | \
++ CEDAR_REVID)
++
++#define CEDAR_CACHE_LINE_SIZE 4
++#define CEDAR_MASTER_LAT 0x3c
++#define CEDAR_HEADER_TYPE 0
++#define CEDAR_BIST 0
++
++#define CEDAR_CNFG3 ((CEDAR_BIST << 24) | \
++ (CEDAR_HEADER_TYPE << 16) | \
++ (CEDAR_MASTER_LAT << 8) | \
++ CEDAR_CACHE_LINE_SIZE)
++
++#define CEDAR_BAR0 0x00000008 /* 128 MB Memory */
++#define CEDAR_BAR1 0x18800001 /* 1 MB IO */
++#define CEDAR_BAR2 0x18000001 /* 2 MB IO window for Cedar
++ internal Registers */
++#define CEDAR_BAR3 0x48000008 /* Spare 128 MB Memory */
++
++#define CEDAR_CNFG4 CEDAR_BAR0
++#define CEDAR_CNFG5 CEDAR_BAR1
++#define CEDAR_CNFG6 CEDAR_BAR2
++#define CEDAR_CNFG7 CEDAR_BAR3
++
++#define CEDAR_SUBSYS_VENDOR_ID 0
++#define CEDAR_SUBSYSTEM_ID 0
++#define CEDAR_CNFG8 0
++#define CEDAR_CNFG9 0
++#define CEDAR_CNFG10 0
++#define CEDAR_CNFG11 ((CEDAR_SUBSYS_VENDOR_ID << 16) | \
++ CEDAR_SUBSYSTEM_ID)
++#define CEDAR_INT_LINE 1
++#define CEDAR_INT_PIN 1
++#define CEDAR_MIN_GNT 8
++#define CEDAR_MAX_LAT 0x38
++#define CEDAR_CNFG12 0
++#define CEDAR_CNFG13 0
++#define CEDAR_CNFG14 0
++#define CEDAR_CNFG15 ((CEDAR_MAX_LAT << 24) | \
++ (CEDAR_MIN_GNT << 16) | \
++ (CEDAR_INT_PIN << 8) | \
++ CEDAR_INT_LINE)
++#define CEDAR_RETRY_LIMIT 0x80
++#define CEDAR_TRDY_LIMIT 0x80
++#define CEDAR_CNFG16 ((CEDAR_RETRY_LIMIT << 8) | \
++ CEDAR_TRDY_LIMIT)
++#define PCI_PBAxC_R 0x0
++#define PCI_PBAxC_RL 0x1
++#define PCI_PBAxC_RM 0x2
++#define SIZE_SHFT 2
++#ifdef __MIPSEB__
++#define CEDAR_PBA0C (((1 & 0x3) << PCIPBAC_mr_b) | \
++ PCIPBAC_pp_m | \
++ PCIPBAC_sb_m | \
++ (SIZE_128MB << SIZE_SHFT) | \
++ PCIPBAC_p_m)
++#else
++
++#define CEDAR_PBA0C (((1 & 0x3) << PCIPBAC_mr_b) | \
++ PCIPBAC_pp_m | \
++ (SIZE_128MB << SIZE_SHFT) | \
++ PCIPBAC_p_m)
++#endif
++#define CEDAR_CNFG17 CEDAR_PBA0C
++#define CEDAR_PBA0M 0x0
++#define CEDAR_CNFG18 CEDAR_PBA0M
++
++#ifdef __MIPSEB__
++#define CEDAR_PBA1C ((SIZE_1MB << SIZE_SHFT) | \
++ PCIPBAC_sb_m | \
++ PCIPBAC_msi_m)
++#else
++#define CEDAR_PBA1C ((SIZE_1MB << SIZE_SHFT) | \
++ PCIPBAC_msi_m)
++#endif
++#define CEDAR_CNFG19 CEDAR_PBA1C
++#define CEDAR_PBA1M 0x0
++#define CEDAR_CNFG20 CEDAR_PBA1M
++
++#ifdef __MIPSEB__
++#define CEDAR_PBA2C ((SIZE_2MB << SIZE_SHFT) | \
++ PCIPBAC_sb_m | \
++ PCIPBAC_msi_m)
++#else
++#define CEDAR_PBA2C ((SIZE_2MB << SIZE_SHFT) | \
++ PCIPBAC_msi_m)
++#endif
++
++#define CEDAR_CNFG21 CEDAR_PBA2C
++#define CEDAR_PBA2M 0x18000000
++#define CEDAR_CNFG22 CEDAR_PBA2M
++
++#ifdef __MIPSEB__
++#define CEDAR_PBA3C PCIPBAC_sb_m
++#else
++#define CEDAR_PBA3C 0
++#endif
++
++#define CEDAR_CNFG23 CEDAR_PBA3C
++#define CEDAR_PBA3M 0
++#define CEDAR_CNFG24 CEDAR_PBA3M
++
++#define PCITC_DTIMER_VAL 8
++#define PCITC_RTIMER_VAL 0x10
++
++#endif //__IDT_RC32365_PCI_V_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_dma.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_dma.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_dma.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_dma.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,205 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * DMA register definition
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_DMA_H__
++#define __IDT_DMA_H__
++
++enum
++{
++ DMA0_PhysicalAddress = 0x18040000,
++ DMA_PhysicalAddress = DMA0_PhysicalAddress, // Default
++
++ DMA0_VirtualAddress = 0xb8040000,
++ DMA_VirtualAddress = DMA0_VirtualAddress, // Default
++} ;
++
++/*
++ * DMA descriptor (in physical memory).
++ */
++
++typedef struct DMAD_s
++{
++ u32 control ; // Control. use DMAD_*
++ u32 ca ; // Current Address.
++ u32 devcs ; // Device control and status.
++ u32 link ; // Next descriptor in chain.
++} volatile *DMAD_t ;
++
++enum
++{
++ DMAD_size = sizeof (struct DMAD_s),
++ DMAD_count_b = 0, // in DMAD_t -> control
++ DMAD_count_m = 0x0003ffff, // in DMAD_t -> control
++ DMAD_ds_b = 20, // in DMAD_t -> control
++ DMAD_ds_m = 0x00300000, // in DMAD_t -> control
++ DMAD_ds_ethRcv0_v = 0,
++ DMAD_ds_ethXmt0_v = 0,
++ DMAD_ds_memToFifo_v = 0,
++ DMAD_ds_fifoToMem_v = 0,
++ DMAD_ds_pciToMem_v = 0,
++ DMAD_ds_memToPci_v = 0,
++
++ DMAD_devcmd_b = 22, // in DMAD_t -> control
++ DMAD_devcmd_m = 0x01c00000, // in DMAD_t -> control
++ DMAD_devcmd_byte_v = 0, //memory-to-memory
++ DMAD_devcmd_halfword_v = 1, //memory-to-memory
++ DMAD_devcmd_word_v = 2, //memory-to-memory
++ DMAD_devcmd_2words_v = 3, //memory-to-memory
++ DMAD_devcmd_4words_v = 4, //memory-to-memory
++ DMAD_devcmd_6words_v = 5, //memory-to-memory
++ DMAD_devcmd_8words_v = 6, //memory-to-memory
++ DMAD_devcmd_16words_v = 7, //memory-to-memory
++ DMAD_cof_b = 25, // chain on finished
++ DMAD_cof_m = 0x02000000, //
++ DMAD_cod_b = 26, // chain on done
++ DMAD_cod_m = 0x04000000, //
++ DMAD_iof_b = 27, // interrupt on finished
++ DMAD_iof_m = 0x08000000, //
++ DMAD_iod_b = 28, // interrupt on done
++ DMAD_iod_m = 0x10000000, //
++ DMAD_t_b = 29, // terminated
++ DMAD_t_m = 0x20000000, //
++ DMAD_d_b = 30, // done
++ DMAD_d_m = 0x40000000, //
++ DMAD_f_b = 31, // finished
++ DMAD_f_m = 0x80000000, //
++} ;
++
++/*
++ * DMA register (within Internal Register Map).
++ */
++
++struct DMA_Chan_s
++{
++ u32 dmac ; // Control.
++ u32 dmas ; // Status.
++ u32 dmasm ; // Mask.
++ u32 dmadptr ; // Descriptor pointer.
++ u32 dmandptr ; // Next descriptor pointer.
++};
++
++typedef struct DMA_Chan_s volatile *DMA_Chan_t ;
++
++//DMA_Channels use DMACH_count instead
++
++enum
++{
++ DMAC_run_b = 0, //
++ DMAC_run_m = 0x00000001, //
++ DMAC_dm_b = 1, // done mask
++ DMAC_dm_m = 0x00000002, //
++ DMAC_mode_b = 2, //
++ DMAC_mode_m = 0x0000000c, //
++ DMAC_mode_auto_v = 0,
++ DMAC_mode_burst_v = 1,
++ DMAC_mode_transfer_v = 2, //usually used
++ DMAC_mode_reserved_v = 3,
++ DMAC_a_b = 4, //
++ DMAC_a_m = 0x00000010, //
++
++ DMAS_f_b = 0, // finished (sticky)
++ DMAS_f_m = 0x00000001, //
++ DMAS_d_b = 1, // done (sticky)
++ DMAS_d_m = 0x00000002, //
++ DMAS_c_b = 2, // chain (sticky)
++ DMAS_c_m = 0x00000004, //
++ DMAS_e_b = 3, // error (sticky)
++ DMAS_e_m = 0x00000008, //
++ DMAS_h_b = 4, // halt (sticky)
++ DMAS_h_m = 0x00000010, //
++
++ DMASM_f_b = 0, // finished (1=mask)
++ DMASM_f_m = 0x00000001, //
++ DMASM_d_b = 1, // done (1=mask)
++ DMASM_d_m = 0x00000002, //
++ DMASM_c_b = 2, // chain (1=mask)
++ DMASM_c_m = 0x00000004, //
++ DMASM_e_b = 3, // error (1=mask)
++ DMASM_e_m = 0x00000008, //
++ DMASM_h_b = 4, // halt (1=mask)
++ DMASM_h_m = 0x00000010, //
++} ;
++
++/*
++ * DMA channel definitions
++ */
++
++enum
++{
++ DMACH_ethRcv0 = 0,
++ DMACH_ethXmt0 = 1,
++ DMACH_memToFifo = 2,
++ DMACH_fifoToMem = 3,
++ DMACH_pciToMem = 4,
++ DMACH_memToPci = 5,
++
++ DMACH_count //must be last
++};
++
++
++typedef struct DMAC_s
++{
++ struct DMA_Chan_s ch [DMACH_count] ; //use ch[DMACH_]
++} volatile *DMA_t ;
++
++
++/*
++ * External DMA parameters
++*/
++
++enum
++{
++ DMADEVCMD_ts_b = 0, // ts field in devcmd
++ DMADEVCMD_ts_m = 0x00000007, // ts field in devcmd
++ DMADEVCMD_ts_byte_v = 0,
++ DMADEVCMD_ts_halfword_v = 1,
++ DMADEVCMD_ts_word_v = 2,
++ DMADEVCMD_ts_2word_v = 3,
++ DMADEVCMD_ts_4word_v = 4,
++ DMADEVCMD_ts_6word_v = 5,
++ DMADEVCMD_ts_8word_v = 6,
++ DMADEVCMD_ts_16word_v = 7
++};
++
++
++#endif // __IDT_DMA_H__
++
++
++
++
++
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_dma_v.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_dma_v.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_dma_v.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_dma_v.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,89 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Definitions for DMA controller.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_DMA_V_H__
++#define __IDT_DMA_V_H__
++
++#include <asm/idt-boards/rc32434/rc32434_dma.h>
++#include <asm/idt-boards/rc32434/rc32434.h>
++
++#define DMA_CHAN_OFFSET 0x14
++#define IS_DMA_USED(X) (((X) & (DMAD_f_m | DMAD_d_m | DMAD_t_m)) != 0)
++#define DMA_COUNT(count) \
++ ((count) & DMAD_count_m)
++
++#define DMA_HALT_TIMEOUT 500
++
++
++static inline int rc32434_halt_dma(DMA_Chan_t ch)
++{
++ int timeout=1;
++ if (rc32434_readl(&ch->dmac) & DMAC_run_m) {
++ rc32434_writel(0, &ch->dmac);
++
++ for (timeout = DMA_HALT_TIMEOUT; timeout > 0; timeout--) {
++ if (rc32434_readl(&ch->dmas) & DMAS_h_m) {
++ rc32434_writel(0, &ch->dmas);
++ break;
++ }
++ }
++
++ }
++
++ return timeout ? 0 : 1;
++}
++
++static inline void rc32434_start_dma(DMA_Chan_t ch, u32 dma_addr)
++{
++ rc32434_writel(0, &ch->dmandptr);
++ rc32434_writel(dma_addr, &ch->dmadptr);
++}
++
++static inline void rc32434_chain_dma(DMA_Chan_t ch, u32 dma_addr)
++{
++ rc32434_writel(dma_addr, &ch->dmandptr);
++}
++
++#endif // __IDT_DMA_V_H__
++
++
++
++
++
++
++
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_eth.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_eth.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_eth.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_eth.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,333 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Ethernet register definition
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_ETH_H__
++#define __IDT_ETH_H__
++
++
++enum
++{
++ ETH0_PhysicalAddress = 0x18060000,
++ ETH_PhysicalAddress = ETH0_PhysicalAddress, // Default
++
++ ETH0_VirtualAddress = 0xb8060000,
++ ETH_VirtualAddress = ETH0_VirtualAddress, // Default
++} ;
++
++typedef struct
++{
++ u32 ethintfc ;
++ u32 ethfifott ;
++ u32 etharc ;
++ u32 ethhash0 ;
++ u32 ethhash1 ;
++ u32 ethu0 [4] ; // Reserved.
++ u32 ethpfs ;
++ u32 ethmcp ;
++ u32 eth_u1 [10] ; // Reserved.
++ u32 ethspare ;
++ u32 eth_u2 [42] ; // Reserved.
++ u32 ethsal0 ;
++ u32 ethsah0 ;
++ u32 ethsal1 ;
++ u32 ethsah1 ;
++ u32 ethsal2 ;
++ u32 ethsah2 ;
++ u32 ethsal3 ;
++ u32 ethsah3 ;
++ u32 ethrbc ;
++ u32 ethrpc ;
++ u32 ethrupc ;
++ u32 ethrfc ;
++ u32 ethtbc ;
++ u32 ethgpf ;
++ u32 eth_u9 [50] ; // Reserved.
++ u32 ethmac1 ;
++ u32 ethmac2 ;
++ u32 ethipgt ;
++ u32 ethipgr ;
++ u32 ethclrt ;
++ u32 ethmaxf ;
++ u32 eth_u10 ; // Reserved.
++ u32 ethmtest ;
++ u32 miimcfg ;
++ u32 miimcmd ;
++ u32 miimaddr ;
++ u32 miimwtd ;
++ u32 miimrdd ;
++ u32 miimind ;
++ u32 eth_u11 ; // Reserved.
++ u32 eth_u12 ; // Reserved.
++ u32 ethcfsa0 ;
++ u32 ethcfsa1 ;
++ u32 ethcfsa2 ;
++} volatile *ETH_t;
++
++enum
++{
++ ETHINTFC_en_b = 0,
++ ETHINTFC_en_m = 0x00000001,
++ ETHINTFC_its_b = 1,
++ ETHINTFC_its_m = 0x00000002,
++ ETHINTFC_rip_b = 2,
++ ETHINTFC_rip_m = 0x00000004,
++ ETHINTFC_jam_b = 3,
++ ETHINTFC_jam_m = 0x00000008,
++ ETHINTFC_ovr_b = 4,
++ ETHINTFC_ovr_m = 0x00000010,
++ ETHINTFC_und_b = 5,
++ ETHINTFC_und_m = 0x00000020,
++
++ ETHFIFOTT_tth_b = 0,
++ ETHFIFOTT_tth_m = 0x0000007f,
++
++ ETHARC_pro_b = 0,
++ ETHARC_pro_m = 0x00000001,
++ ETHARC_am_b = 1,
++ ETHARC_am_m = 0x00000002,
++ ETHARC_afm_b = 2,
++ ETHARC_afm_m = 0x00000004,
++ ETHARC_ab_b = 3,
++ ETHARC_ab_m = 0x00000008,
++
++ ETHSAL_byte5_b = 0,
++ ETHSAL_byte5_m = 0x000000ff,
++ ETHSAL_byte4_b = 8,
++ ETHSAL_byte4_m = 0x0000ff00,
++ ETHSAL_byte3_b = 16,
++ ETHSAL_byte3_m = 0x00ff0000,
++ ETHSAL_byte2_b = 24,
++ ETHSAL_byte2_m = 0xff000000,
++
++ ETHSAH_byte1_b = 0,
++ ETHSAH_byte1_m = 0x000000ff,
++ ETHSAH_byte0_b = 8,
++ ETHSAH_byte0_m = 0x0000ff00,
++
++ ETHGPF_ptv_b = 0,
++ ETHGPF_ptv_m = 0x0000ffff,
++
++ ETHPFS_pfd_b = 0,
++ ETHPFS_pfd_m = 0x00000001,
++
++ ETHCFSA0_cfsa4_b = 0,
++ ETHCFSA0_cfsa4_m = 0x000000ff,
++ ETHCFSA0_cfsa5_b = 8,
++ ETHCFSA0_cfsa5_m = 0x0000ff00,
++
++ ETHCFSA1_cfsa2_b = 0,
++ ETHCFSA1_cfsa2_m = 0x000000ff,
++ ETHCFSA1_cfsa3_b = 8,
++ ETHCFSA1_cfsa3_m = 0x0000ff00,
++
++ ETHCFSA2_cfsa0_b = 0,
++ ETHCFSA2_cfsa0_m = 0x000000ff,
++ ETHCFSA2_cfsa1_b = 8,
++ ETHCFSA2_cfsa1_m = 0x0000ff00,
++
++ ETHMAC1_re_b = 0,
++ ETHMAC1_re_m = 0x00000001,
++ ETHMAC1_paf_b = 1,
++ ETHMAC1_paf_m = 0x00000002,
++ ETHMAC1_rfc_b = 2,
++ ETHMAC1_rfc_m = 0x00000004,
++ ETHMAC1_tfc_b = 3,
++ ETHMAC1_tfc_m = 0x00000008,
++ ETHMAC1_lb_b = 4,
++ ETHMAC1_lb_m = 0x00000010,
++ ETHMAC1_mr_b = 31,
++ ETHMAC1_mr_m = 0x80000000,
++
++ ETHMAC2_fd_b = 0,
++ ETHMAC2_fd_m = 0x00000001,
++ ETHMAC2_flc_b = 1,
++ ETHMAC2_flc_m = 0x00000002,
++ ETHMAC2_hfe_b = 2,
++ ETHMAC2_hfe_m = 0x00000004,
++ ETHMAC2_dc_b = 3,
++ ETHMAC2_dc_m = 0x00000008,
++ ETHMAC2_cen_b = 4,
++ ETHMAC2_cen_m = 0x00000010,
++ ETHMAC2_pe_b = 5,
++ ETHMAC2_pe_m = 0x00000020,
++ ETHMAC2_vpe_b = 6,
++ ETHMAC2_vpe_m = 0x00000040,
++ ETHMAC2_ape_b = 7,
++ ETHMAC2_ape_m = 0x00000080,
++ ETHMAC2_ppe_b = 8,
++ ETHMAC2_ppe_m = 0x00000100,
++ ETHMAC2_lpe_b = 9,
++ ETHMAC2_lpe_m = 0x00000200,
++ ETHMAC2_nb_b = 12,
++ ETHMAC2_nb_m = 0x00001000,
++ ETHMAC2_bp_b = 13,
++ ETHMAC2_bp_m = 0x00002000,
++ ETHMAC2_ed_b = 14,
++ ETHMAC2_ed_m = 0x00004000,
++
++ ETHIPGT_ipgt_b = 0,
++ ETHIPGT_ipgt_m = 0x0000007f,
++
++ ETHIPGR_ipgr2_b = 0,
++ ETHIPGR_ipgr2_m = 0x0000007f,
++ ETHIPGR_ipgr1_b = 8,
++ ETHIPGR_ipgr1_m = 0x00007f00,
++
++ ETHCLRT_maxret_b = 0,
++ ETHCLRT_maxret_m = 0x0000000f,
++ ETHCLRT_colwin_b = 8,
++ ETHCLRT_colwin_m = 0x00003f00,
++
++ ETHMAXF_maxf_b = 0,
++ ETHMAXF_maxf_m = 0x0000ffff,
++
++ ETHMTEST_tb_b = 2,
++ ETHMTEST_tb_m = 0x00000004,
++
++ ETHMCP_div_b = 0,
++ ETHMCP_div_m = 0x000000ff,
++
++ MIIMCFG_rsv_b = 0,
++ MIIMCFG_rsv_m = 0x0000000c,
++
++ MIIMCMD_rd_b = 0,
++ MIIMCMD_rd_m = 0x00000001,
++ MIIMCMD_scn_b = 1,
++ MIIMCMD_scn_m = 0x00000002,
++
++ MIIMADDR_regaddr_b = 0,
++ MIIMADDR_regaddr_m = 0x0000001f,
++ MIIMADDR_phyaddr_b = 8,
++ MIIMADDR_phyaddr_m = 0x00001f00,
++
++ MIIMWTD_wdata_b = 0,
++ MIIMWTD_wdata_m = 0x0000ffff,
++
++ MIIMRDD_rdata_b = 0,
++ MIIMRDD_rdata_m = 0x0000ffff,
++
++ MIIMIND_bsy_b = 0,
++ MIIMIND_bsy_m = 0x00000001,
++ MIIMIND_scn_b = 1,
++ MIIMIND_scn_m = 0x00000002,
++ MIIMIND_nv_b = 2,
++ MIIMIND_nv_m = 0x00000004,
++
++} ;
++
++/*
++ * Values for the DEVCS field of the Ethernet DMA Rx and Tx descriptors.
++ */
++enum
++{
++ ETHRX_fd_b = 0,
++ ETHRX_fd_m = 0x00000001,
++ ETHRX_ld_b = 1,
++ ETHRX_ld_m = 0x00000002,
++ ETHRX_rok_b = 2,
++ ETHRX_rok_m = 0x00000004,
++ ETHRX_fm_b = 3,
++ ETHRX_fm_m = 0x00000008,
++ ETHRX_mp_b = 4,
++ ETHRX_mp_m = 0x00000010,
++ ETHRX_bp_b = 5,
++ ETHRX_bp_m = 0x00000020,
++ ETHRX_vlt_b = 6,
++ ETHRX_vlt_m = 0x00000040,
++ ETHRX_cf_b = 7,
++ ETHRX_cf_m = 0x00000080,
++ ETHRX_ovr_b = 8,
++ ETHRX_ovr_m = 0x00000100,
++ ETHRX_crc_b = 9,
++ ETHRX_crc_m = 0x00000200,
++ ETHRX_cv_b = 10,
++ ETHRX_cv_m = 0x00000400,
++ ETHRX_db_b = 11,
++ ETHRX_db_m = 0x00000800,
++ ETHRX_le_b = 12,
++ ETHRX_le_m = 0x00001000,
++ ETHRX_lor_b = 13,
++ ETHRX_lor_m = 0x00002000,
++ ETHRX_ces_b = 14,
++ ETHRX_ces_m = 0x00004000,
++ ETHRX_length_b = 16,
++ ETHRX_length_m = 0xffff0000,
++
++ ETHTX_fd_b = 0,
++ ETHTX_fd_m = 0x00000001,
++ ETHTX_ld_b = 1,
++ ETHTX_ld_m = 0x00000002,
++ ETHTX_oen_b = 2,
++ ETHTX_oen_m = 0x00000004,
++ ETHTX_pen_b = 3,
++ ETHTX_pen_m = 0x00000008,
++ ETHTX_cen_b = 4,
++ ETHTX_cen_m = 0x00000010,
++ ETHTX_hen_b = 5,
++ ETHTX_hen_m = 0x00000020,
++ ETHTX_tok_b = 6,
++ ETHTX_tok_m = 0x00000040,
++ ETHTX_mp_b = 7,
++ ETHTX_mp_m = 0x00000080,
++ ETHTX_bp_b = 8,
++ ETHTX_bp_m = 0x00000100,
++ ETHTX_und_b = 9,
++ ETHTX_und_m = 0x00000200,
++ ETHTX_of_b = 10,
++ ETHTX_of_m = 0x00000400,
++ ETHTX_ed_b = 11,
++ ETHTX_ed_m = 0x00000800,
++ ETHTX_ec_b = 12,
++ ETHTX_ec_m = 0x00001000,
++ ETHTX_lc_b = 13,
++ ETHTX_lc_m = 0x00002000,
++ ETHTX_td_b = 14,
++ ETHTX_td_m = 0x00004000,
++ ETHTX_crc_b = 15,
++ ETHTX_crc_m = 0x00008000,
++ ETHTX_le_b = 16,
++ ETHTX_le_m = 0x00010000,
++ ETHTX_cc_b = 17,
++ ETHTX_cc_m = 0x001E0000,
++} ;
++
++#endif // __IDT_ETH_H__
++
++
++
++
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_eth_v.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_eth_v.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_eth_v.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_eth_v.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,77 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Ethernet register definition
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_ETH_V_H__
++#define __IDT_ETH_V_H__
++
++#include <asm/idt-boards/rc32434/rc32434_eth.h>
++
++#define IS_TX_TOK(X) (((X) & (1<<ETHTX_tok_b)) >> ETHTX_tok_b ) /* Transmit Okay */
++#define IS_TX_MP(X) (((X) & (1<<ETHTX_mp_b)) >> ETHTX_mp_b ) /* Multicast */
++#define IS_TX_BP(X) (((X) & (1<<ETHTX_bp_b)) >> ETHTX_bp_b ) /* Broadcast */
++#define IS_TX_UND_ERR(X) (((X) & (1<<ETHTX_und_b)) >> ETHTX_und_b ) /* Transmit FIFO Underflow */
++#define IS_TX_OF_ERR(X) (((X) & (1<<ETHTX_of_b)) >> ETHTX_of_b ) /* Oversized frame */
++#define IS_TX_ED_ERR(X) (((X) & (1<<ETHTX_ed_b)) >> ETHTX_ed_b ) /* Excessive deferral */
++#define IS_TX_EC_ERR(X) (((X) & (1<<ETHTX_ec_b)) >> ETHTX_ec_b) /* Excessive collisions */
++#define IS_TX_LC_ERR(X) (((X) & (1<<ETHTX_lc_b)) >> ETHTX_lc_b ) /* Late Collision */
++#define IS_TX_TD_ERR(X) (((X) & (1<<ETHTX_td_b)) >> ETHTX_td_b ) /* Transmit deferred*/
++#define IS_TX_CRC_ERR(X) (((X) & (1<<ETHTX_crc_b)) >> ETHTX_crc_b ) /* CRC Error */
++#define IS_TX_LE_ERR(X) (((X) & (1<<ETHTX_le_b)) >> ETHTX_le_b ) /* Length Error */
++
++#define TX_COLLISION_COUNT(X) (((X) & ETHTX_cc_m)>>ETHTX_cc_b) /* Collision Count */
++
++#define IS_RCV_ROK(X) (((X) & (1<<ETHRX_rok_b)) >> ETHRX_rok_b) /* Receive Okay */
++#define IS_RCV_FM(X) (((X) & (1<<ETHRX_fm_b)) >> ETHRX_fm_b) /* Is Filter Match */
++#define IS_RCV_MP(X) (((X) & (1<<ETHRX_mp_b)) >> ETHRX_mp_b) /* Is it MP */
++#define IS_RCV_BP(X) (((X) & (1<<ETHRX_bp_b)) >> ETHRX_bp_b) /* Is it BP */
++#define IS_RCV_VLT(X) (((X) & (1<<ETHRX_vlt_b)) >> ETHRX_vlt_b) /* VLAN Tag Detect */
++#define IS_RCV_CF(X) (((X) & (1<<ETHRX_cf_b)) >> ETHRX_cf_b) /* Control Frame */
++#define IS_RCV_OVR_ERR(X) (((X) & (1<<ETHRX_ovr_b)) >> ETHRX_ovr_b) /* Receive Overflow */
++#define IS_RCV_CRC_ERR(X) (((X) & (1<<ETHRX_crc_b)) >> ETHRX_crc_b) /* CRC Error */
++#define IS_RCV_CV_ERR(X) (((X) & (1<<ETHRX_cv_b)) >> ETHRX_cv_b) /* Code Violation */
++#define IS_RCV_DB_ERR(X) (((X) & (1<<ETHRX_db_b)) >> ETHRX_db_b) /* Dribble Bits */
++#define IS_RCV_LE_ERR(X) (((X) & (1<<ETHRX_le_b)) >> ETHRX_le_b) /* Length error */
++#define IS_RCV_LOR_ERR(X) (((X) & (1<<ETHRX_lor_b)) >> ETHRX_lor_b) /* Length Out of Range */
++#define IS_RCV_CES_ERR(X) (((X) & (1<<ETHRX_ces_b)) >> ETHRX_ces_b) /* Preamble error */
++#define RCVPKT_LENGTH(X) (((X) & ETHRX_length_m) >> ETHRX_length_b) /* Length of the received packet */
++#endif // __IDT_ETH_V_H__
++
++
++
++
++
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_gpio.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_gpio.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_gpio.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_gpio.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,167 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * GPIO register definition
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_GPIO_H__
++#define __IDT_GPIO_H__
++
++enum
++{
++ GPIO0_PhysicalAddress = 0x18050000,
++ GPIO_PhysicalAddress = GPIO0_PhysicalAddress, // Default
++
++ GPIO0_VirtualAddress = 0xb8050000,
++ GPIO_VirtualAddress = GPIO0_VirtualAddress, // Default
++} ;
++
++typedef struct
++{
++ u32 gpiofunc; /* GPIO Function Register
++ * gpiofunc[x]==0 bit = gpio
++ * func[x]==1 bit = altfunc
++ */
++ u32 gpiocfg; /* GPIO Configuration Register
++ * gpiocfg[x]==0 bit = input
++ * gpiocfg[x]==1 bit = output
++ */
++ u32 gpiod; /* GPIO Data Register
++ * gpiod[x] read/write gpio pinX status
++ */
++ u32 gpioilevel; /* GPIO Interrupt Status Register
++ * interrupt level (see gpioistat)
++ */
++ u32 gpioistat; /* Gpio Interrupt Status Register
++ * istat[x] = (gpiod[x] == level[x])
++ * cleared in ISR (STICKY bits)
++ */
++ u32 gpionmien; /* GPIO Non-maskable Interrupt Enable Register */
++} volatile * GPIO_t ;
++
++typedef enum
++{
++ GPIO_gpio_v = 0, // gpiofunc use pin as GPIO.
++ GPIO_alt_v = 1, // gpiofunc use pin as alt.
++ GPIO_input_v = 0, // gpiocfg use pin as input.
++ GPIO_output_v = 1, // gpiocfg use pin as output.
++ GPIO_pin0_b = 0,
++ GPIO_pin0_m = 0x00000001,
++ GPIO_pin1_b = 1,
++ GPIO_pin1_m = 0x00000002,
++ GPIO_pin2_b = 2,
++ GPIO_pin2_m = 0x00000004,
++ GPIO_pin3_b = 3,
++ GPIO_pin3_m = 0x00000008,
++ GPIO_pin4_b = 4,
++ GPIO_pin4_m = 0x00000010,
++ GPIO_pin5_b = 5,
++ GPIO_pin5_m = 0x00000020,
++ GPIO_pin6_b = 6,
++ GPIO_pin6_m = 0x00000040,
++ GPIO_pin7_b = 7,
++ GPIO_pin7_m = 0x00000080,
++ GPIO_pin8_b = 8,
++ GPIO_pin8_m = 0x00000100,
++ GPIO_pin9_b = 9,
++ GPIO_pin9_m = 0x00000200,
++ GPIO_pin10_b = 10,
++ GPIO_pin10_m = 0x00000400,
++ GPIO_pin11_b = 11,
++ GPIO_pin11_m = 0x00000800,
++ GPIO_pin12_b = 12,
++ GPIO_pin12_m = 0x00001000,
++ GPIO_pin13_b = 13,
++ GPIO_pin13_m = 0x00002000,
++
++// Alternate function pins. Corrsponding gpiofunc bit set to GPIO_alt_v.
++
++ GPIO_u0sout_b = GPIO_pin0_b, // UART 0 serial out.
++ GPIO_u0sout_m = GPIO_pin0_m,
++ GPIO_u0sout_cfg_v = GPIO_output_v,
++ GPIO_u0sinp_b = GPIO_pin1_b, // UART 0 serial in.
++ GPIO_u0sinp_m = GPIO_pin1_m,
++ GPIO_u0sinp_cfg_v = GPIO_input_v,
++ GPIO_u0rtsn_b = GPIO_pin2_b, // UART 0 req. to send.
++ GPIO_u0rtsn_m = GPIO_pin2_m,
++ GPIO_u0rtsn_cfg_v = GPIO_output_v,
++ GPIO_u0ctsn_b = GPIO_pin3_b, // UART 0 clear to send.
++ GPIO_u0ctsn_m = GPIO_pin3_m,
++ GPIO_u0ctsn_cfg_v = GPIO_input_v,
++
++ GPIO_maddr22_b = GPIO_pin4_b, // M&P bus bit 22.
++ GPIO_maddr22_m = GPIO_pin4_m,
++ GPIO_maddr22_cfg_v = GPIO_output_v,
++
++ GPIO_maddr23_b = GPIO_pin5_b, // M&P bus bit 23.
++ GPIO_maddr23_m = GPIO_pin5_m,
++ GPIO_maddr23_cfg_v = GPIO_output_v,
++
++ GPIO_maddr24_b = GPIO_pin6_b, // M&P bus bit 24.
++ GPIO_maddr24_m = GPIO_pin6_m,
++ GPIO_maddr24_cfg_v = GPIO_output_v,
++
++ GPIO_maddr25_b = GPIO_pin7_b, // M&P bus bit 25.
++ GPIO_maddr25_m = GPIO_pin7_m,
++ GPIO_maddr25_cfg_v = GPIO_output_v,
++
++ GPIO_cpudmadebug_b = GPIO_pin8_b, // CPU or DMA debug pin
++ GPIO_cpudmadebug_m = GPIO_pin8_m,
++ GPIO_cpudmadebug_cfg_v = GPIO_output_v,
++
++ GPIO_pcireq4_b = GPIO_pin9_b, // PCI Request 4
++ GPIO_pcireq4_m = GPIO_pin9_m,
++ GPIO_pcireq4_cfg_v = GPIO_input_v,
++
++ GPIO_pcigrant4_b = GPIO_pin10_b, // PCI Grant 4
++ GPIO_pcigrant4_m = GPIO_pin10_m,
++ GPIO_pcigrant4_cfg_v = GPIO_output_v,
++
++ GPIO_pcireq5_b = GPIO_pin11_b, // PCI Request 5
++ GPIO_pcireq5_m = GPIO_pin11_m,
++ GPIO_pcireq5_cfg_v = GPIO_input_v,
++
++ GPIO_pcigrant5_b = GPIO_pin12_b, // PCI Grant 5
++ GPIO_pcigrant5_m = GPIO_pin12_m,
++ GPIO_pcigrant5_cfg_v = GPIO_output_v,
++
++ GPIO_pcimuintn_b = GPIO_pin13_b, // PCI messaging int.
++ GPIO_pcimuintn_m = GPIO_pin13_m,
++ GPIO_pcimuintn_cfg_v = GPIO_output_v,
++
++} GPIO_DEFS_t;
++
++#endif // __IDT_GPIO_H__
++
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,199 @@
++ /**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Definitions for IDT RC32434 CPU
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef _RC32434_H_
++#define _RC32434_H_
++
++#include <linux/config.h>
++#include <linux/delay.h>
++#include <asm/io.h>
++#include <asm/idt-boards/rc32434/rc32434_timer.h>
++
++#define RC32434_REG_BASE 0x18000000
++
++
++#define interrupt ((volatile INT_t ) INT0_VirtualAddress)
++#define idt_timer ((volatile TIM_t) TIM0_VirtualAddress)
++#define idt_gpio ((volatile GPIO_t) GPIO0_VirtualAddress)
++
++#define IDT_CLOCK_MULT 2
++#define MIPS_CPU_TIMER_IRQ 7
++/* Interrupt Controller */
++#define IC_GROUP0_PEND (RC32434_REG_BASE + 0x38000)
++#define IC_GROUP0_MASK (RC32434_REG_BASE + 0x38008)
++#define IC_GROUP_OFFSET 0x0C
++#define RTC_BASE 0xBA001FF0
++
++#define NUM_INTR_GROUPS 5
++/* 16550 UARTs */
++
++#define GROUP0_IRQ_BASE 8 /* GRP2 IRQ numbers start here */
++#define GROUP1_IRQ_BASE (GROUP0_IRQ_BASE + 32) /* GRP3 IRQ numbers start here */
++#define GROUP2_IRQ_BASE (GROUP1_IRQ_BASE + 32) /* GRP4 IRQ numbers start here */
++#define GROUP3_IRQ_BASE (GROUP2_IRQ_BASE + 32) /* GRP5 IRQ numbers start here */
++#define GROUP4_IRQ_BASE (GROUP3_IRQ_BASE + 32)
++
++#ifdef __MIPSEB__
++
++#define RC32434_UART0_BASE (RC32434_REG_BASE + 0x58003)
++#define EB434_UART1_BASE (0x19800003)
++
++#else
++
++#define RC32434_UART0_BASE (RC32434_REG_BASE + 0x58000)
++#define EB434_UART1_BASE (0x19800000)
++
++#endif
++
++#define RC32434_UART0_IRQ GROUP3_IRQ_BASE + 0
++#define EB434_UART1_IRQ GROUP4_IRQ_BASE + 11
++
++#define RC32434_NR_IRQS (GROUP4_IRQ_BASE + 32)
++
++/* cpu pipeline flush */
++static inline void rc32434_sync(void)
++{
++ __asm__ volatile ("sync");
++}
++
++static inline void rc32434_sync_udelay(int us)
++{
++ __asm__ volatile ("sync");
++ udelay(us);
++}
++
++static inline void rc32434_sync_delay(int ms)
++{
++ __asm__ volatile ("sync");
++ mdelay(ms);
++}
++
++
++
++/*
++ * Macros to access internal RC32434 registers. No byte
++ * swapping should be done when accessing the internal
++ * registers.
++ */
++
++#define rc32434_readb __raw_readb
++#define rc32434_readw __raw_readw
++#define rc32434_readl __raw_readl
++
++#define rc32434_writeb __raw_writeb
++#define rc32434_writew __raw_writew
++#define rc32434_writel __raw_writel
++
++#if 0
++static inline u8 rc32434_readb(unsigned long pa)
++{
++ return *((volatile u8 *)KSEG1ADDR(pa));
++}
++static inline u16 rc32434_readw(unsigned long pa)
++{
++ return *((volatile u16 *)KSEG1ADDR(pa));
++}
++static inline u32 rc32434_readl(unsigned long pa)
++{
++ return *((volatile u32 *)KSEG1ADDR(pa));
++}
++static inline void rc32434_writeb(u8 val, unsigned long pa)
++{
++ *((volatile u8 *)KSEG1ADDR(pa)) = val;
++}
++static inline void rc32434_writew(u16 val, unsigned long pa)
++{
++ *((volatile u16 *)KSEG1ADDR(pa)) = val;
++}
++static inline void rc32434_writel(u32 val, unsigned long pa)
++{
++ *((volatile u32 *)KSEG1ADDR(pa)) = val;
++}
++
++#endif
++
++
++/*
++ * C access to CLZ and CLO instructions
++ * (count leading zeroes/ones).
++ */
++static inline int rc32434_clz(unsigned long val)
++{
++ int ret;
++ __asm__ volatile (
++ ".set\tnoreorder\n\t"
++ ".set\tnoat\n\t"
++ ".set\tmips32\n\t"
++ "clz\t%0,%1\n\t"
++ ".set\tmips0\n\t"
++ ".set\tat\n\t"
++ ".set\treorder"
++ : "=r" (ret)
++ : "r" (val));
++
++ return ret;
++}
++static inline int rc32434_clo(unsigned long val)
++{
++ int ret;
++ __asm__ volatile (
++ ".set\tnoreorder\n\t"
++ ".set\tnoat\n\t"
++ ".set\tmips32\n\t"
++ "clo\t%0,%1\n\t"
++ ".set\tmips0\n\t"
++ ".set\tat\n\t"
++ ".set\treorder"
++ : "=r" (ret)
++ : "r" (val));
++
++ return ret;
++}
++#endif /* _RC32434_H_ */
++
++
++
++
++
++
++
++
++
++
++
++
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_integ.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_integ.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_integ.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_integ.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,90 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * System Integrity register definition
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_INTEG_H__
++#define __IDT_INTEG_H__
++
++enum
++{
++ INTEG0_PhysicalAddress = 0x18030000,
++ INTEG_PhysicalAddress = INTEG0_PhysicalAddress, // Default
++
++ INTEG0_VirtualAddress = 0xB8030000,
++ INTEG_VirtualAddress = INTEG0_VirtualAddress, // Default
++} ;
++
++// if you are looking for CEA, try rst.h
++typedef struct
++{
++ u32 filler [0xc] ; // 0x30 bytes unused.
++ u32 errcs ; // sticky use ERRCS_
++ u32 wtcount ; // Watchdog timer count reg.
++ u32 wtcompare ; // Watchdog timer timeout value.
++ u32 wtc ; // Watchdog timer control. use WTC_
++} volatile *INTEG_t ;
++
++enum
++{
++ ERRCS_wto_b = 0, // In INTEG_t -> errcs
++ ERRCS_wto_m = 0x00000001,
++ ERRCS_wne_b = 1, // In INTEG_t -> errcs
++ ERRCS_wne_m = 0x00000002,
++ ERRCS_ucw_b = 2, // In INTEG_t -> errcs
++ ERRCS_ucw_m = 0x00000004,
++ ERRCS_ucr_b = 3, // In INTEG_t -> errcs
++ ERRCS_ucr_m = 0x00000008,
++ ERRCS_upw_b = 4, // In INTEG_t -> errcs
++ ERRCS_upw_m = 0x00000010,
++ ERRCS_upr_b = 5, // In INTEG_t -> errcs
++ ERRCS_upr_m = 0x00000020,
++ ERRCS_udw_b = 6, // In INTEG_t -> errcs
++ ERRCS_udw_m = 0x00000040,
++ ERRCS_udr_b = 7, // In INTEG_t -> errcs
++ ERRCS_udr_m = 0x00000080,
++ ERRCS_sae_b = 8, // In INTEG_t -> errcs
++ ERRCS_sae_m = 0x00000100,
++ ERRCS_wre_b = 9, // In INTEG_t -> errcs
++ ERRCS_wre_m = 0x00000200,
++
++ WTC_en_b = 0, // In INTEG_t -> wtc
++ WTC_en_m = 0x00000001,
++ WTC_to_b = 1, // In INTEG_t -> wtc
++ WTC_to_m = 0x00000002,
++} ;
++
++#endif // __IDT_INTEG_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_int.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_int.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_int.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_int.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,174 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Interrupt Controller register definition.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_INT_H__
++#define __IDT_INT_H__
++
++enum
++{
++ INT0_PhysicalAddress = 0x18038000,
++ INT_PhysicalAddress = INT0_PhysicalAddress, // Default
++
++ INT0_VirtualAddress = 0xB8038000,
++ INT_VirtualAddress = INT0_VirtualAddress, // Default
++} ;
++
++struct INT_s
++{
++ u32 ipend ; //Pending interrupts. use INT?_
++ u32 itest ; //Test bits. use INT?_
++ u32 imask ; //Interrupt disabled when set. use INT?_
++} ;
++
++enum
++{
++ IPEND2 = 0, // HW 2 interrupt to core. use INT2_
++ IPEND3 = 1, // HW 3 interrupt to core. use INT3_
++ IPEND4 = 2, // HW 4 interrupt to core. use INT4_
++ IPEND5 = 3, // HW 5 interrupt to core. use INT5_
++ IPEND6 = 4, // HW 6 interrupt to core. use INT6_
++
++ IPEND_count, // must be last (used in loops)
++ IPEND_min = IPEND2 // min IPEND (used in loops)
++};
++
++typedef struct INTC_s
++{
++ struct INT_s i [IPEND_count] ;// use i[IPEND?] = INT?_
++ u32 nmips ; // use NMIPS_
++} volatile *INT_t ;
++
++enum
++{
++ INT2_timer0_b = 0,
++ INT2_timer0_m = 0x00000001,
++ INT2_timer1_b = 1,
++ INT2_timer1_m = 0x00000002,
++ INT2_timer2_b = 2,
++ INT2_timer2_m = 0x00000004,
++ INT2_refresh_b = 3,
++ INT2_refresh_m = 0x00000008,
++ INT2_watchdogTimeout_b = 4,
++ INT2_watchdogTimeout_m = 0x00000010,
++ INT2_undecodedCpuWrite_b = 5,
++ INT2_undecodedCpuWrite_m = 0x00000020,
++ INT2_undecodedCpuRead_b = 6,
++ INT2_undecodedCpuRead_m = 0x00000040,
++ INT2_undecodedPciWrite_b = 7,
++ INT2_undecodedPciWrite_m = 0x00000080,
++ INT2_undecodedPciRead_b = 8,
++ INT2_undecodedPciRead_m = 0x00000100,
++ INT2_undecodedDmaWrite_b = 9,
++ INT2_undecodedDmaWrite_m = 0x00000200,
++ INT2_undecodedDmaRead_b = 10,
++ INT2_undecodedDmaRead_m = 0x00000400,
++ INT2_ipBusSlaveAckError_b = 11,
++ INT2_ipBusSlaveAckError_m = 0x00000800,
++
++ INT3_dmaChannel0_b = 0,
++ INT3_dmaChannel0_m = 0x00000001,
++ INT3_dmaChannel1_b = 1,
++ INT3_dmaChannel1_m = 0x00000002,
++ INT3_dmaChannel2_b = 2,
++ INT3_dmaChannel2_m = 0x00000004,
++ INT3_dmaChannel3_b = 3,
++ INT3_dmaChannel3_m = 0x00000008,
++ INT3_dmaChannel4_b = 4,
++ INT3_dmaChannel4_m = 0x00000010,
++ INT3_dmaChannel5_b = 5,
++ INT3_dmaChannel5_m = 0x00000020,
++
++ INT5_uartGeneral0_b = 0,
++ INT5_uartGeneral0_m = 0x00000001,
++ INT5_uartTxrdy0_b = 1,
++ INT5_uartTxrdy0_m = 0x00000002,
++ INT5_uartRxrdy0_b = 2,
++ INT5_uartRxrdy0_m = 0x00000004,
++ INT5_pci_b = 3,
++ INT5_pci_m = 0x00000008,
++ INT5_pciDecoupled_b = 4,
++ INT5_pciDecoupled_m = 0x00000010,
++ INT5_spi_b = 5,
++ INT5_spi_m = 0x00000020,
++ INT5_deviceDecoupled_b = 6,
++ INT5_deviceDecoupled_m = 0x00000040,
++ INT5_eth0Ovr_b = 9,
++ INT5_eth0Ovr_m = 0x00000200,
++ INT5_eth0Und_b = 10,
++ INT5_eth0Und_m = 0x00000400,
++ INT5_eth0Pfd_b = 11,
++ INT5_eth0Pfd_m = 0x00000800,
++ INT5_nvram_b = 12,
++ INT5_nvram_m = 0x00001000,
++
++ INT6_gpio0_b = 0,
++ INT6_gpio0_m = 0x00000001,
++ INT6_gpio1_b = 1,
++ INT6_gpio1_m = 0x00000002,
++ INT6_gpio2_b = 2,
++ INT6_gpio2_m = 0x00000004,
++ INT6_gpio3_b = 3,
++ INT6_gpio3_m = 0x00000008,
++ INT6_gpio4_b = 4,
++ INT6_gpio4_m = 0x00000010,
++ INT6_gpio5_b = 5,
++ INT6_gpio5_m = 0x00000020,
++ INT6_gpio6_b = 6,
++ INT6_gpio6_m = 0x00000040,
++ INT6_gpio7_b = 7,
++ INT6_gpio7_m = 0x00000080,
++ INT6_gpio8_b = 8,
++ INT6_gpio8_m = 0x00000100,
++ INT6_gpio9_b = 9,
++ INT6_gpio9_m = 0x00000200,
++ INT6_gpio10_b = 10,
++ INT6_gpio10_m = 0x00000400,
++ INT6_gpio11_b = 11,
++ INT6_gpio11_m = 0x00000800,
++ INT6_gpio12_b = 12,
++ INT6_gpio12_m = 0x00001000,
++ INT6_gpio13_b = 13,
++ INT6_gpio13_m = 0x00002000,
++
++ NMIPS_gpio_b = 0,
++ NMIPS_gpio_m = 0x00000001,
++} ;
++
++#endif // __IDT_INT_H__
++
++
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_iparb.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_iparb.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_iparb.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_iparb.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,111 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * IP Arbiter register definitions
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt,neb
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_IPARB_H__
++#define __IDT_IPARB_H__
++
++enum
++{
++ IPARB0_PhysicalAddress = 0x18048000,
++ IPARB_PhysicalAddress = IPARB0_PhysicalAddress, // Default
++
++ IPARB0_VirtualAddress = 0xB8048000,
++ IPARB_VirtualAddress = IPARB0_VirtualAddress, // Default
++} ;
++
++enum
++{
++ IPABMXC_ethernet0Receive = 0,
++ IPABMXC_ethernet0Transmit = 1,
++ IPABMXC_memoryToHoldFifo = 2,
++ IPABMXC_holdFifoToMemory = 3,
++ IPABMXC_pciToMemory = 4,
++ IPABMXC_memoryToPci = 5,
++ IPABMXC_pciTarget = 6,
++ IPABMXC_pciTargetStart = 7,
++ IPABMXC_cpuToIpBus = 8,
++
++ IPABMXC_Count, // Must be last in list !
++ IPABMXC_Min = IPABMXC_ethernet0Receive,
++
++ IPAPXC_PriorityCount = 4, // 3-highest, 0-lowest.
++} ;
++
++typedef struct
++{
++ u32 ipapc [IPAPXC_PriorityCount] ; // ipapc[IPAPXC_] = IPAPC_
++ u32 ipabmc [IPABMXC_Count] ; // ipabmc[IPABMXC_] = IPABMC_
++ u32 ipac ; // use IPAC_
++ u32 ipaitcc; // use IPAITCC_
++ u32 ipaspare ;
++} volatile * IPARB_t ;
++
++enum
++{
++ IPAC_dp_b = 0,
++ IPAC_dp_m = 0x00000001,
++ IPAC_dep_b = 1,
++ IPAC_dep_m = 0x00000002,
++ IPAC_drm_b = 2,
++ IPAC_drm_m = 0x00000004,
++ IPAC_dwm_b = 3,
++ IPAC_dwm_m = 0x00000008,
++ IPAC_msk_b = 4,
++ IPAC_msk_m = 0x00000010,
++
++ IPAPC_ptc_b = 0,
++ IPAPC_ptc_m = 0x00003fff,
++ IPAPC_mf_b = 14,
++ IPAPC_mf_m = 0x00004000,
++ IPAPC_cptc_b = 16,
++ IPAPC_cptc_m = 0x3fff0000,
++
++ IPAITCC_itcc = 0,
++ IPAITCC_itcc, = 0x000001ff,
++
++ IPABMC_mtc_b = 0,
++ IPABMC_mtc_m = 0x00000fff,
++ IPABMC_p_b = 12,
++ IPABMC_p_m = 0x00003000,
++ IPABMC_msk_b = 14,
++ IPABMC_msk_m = 0x00004000,
++ IPABMC_cmtc_b = 16,
++ IPABMC_cmtc_m = 0x0fff0000,
++};
++
++#endif // __IDT_IPARB_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_pci.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_pci.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_pci.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_pci.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,695 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * PCI register definitio
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_PCI_H__
++#define __IDT_PCI_H__
++
++enum
++{
++ PCI0_PhysicalAddress = 0x18080000,
++ PCI_PhysicalAddress = PCI0_PhysicalAddress,
++
++ PCI0_VirtualAddress = 0xB8080000,
++ PCI_VirtualAddress = PCI0_VirtualAddress,
++} ;
++
++enum
++{
++ PCI_LbaCount = 4, // Local base addresses.
++} ;
++
++typedef struct
++{
++ u32 a ; // Address.
++ u32 c ; // Control.
++ u32 m ; // mapping.
++} PCI_Map_s ;
++
++typedef struct
++{
++ u32 pcic ;
++ u32 pcis ;
++ u32 pcism ;
++ u32 pcicfga ;
++ u32 pcicfgd ;
++ PCI_Map_s pcilba [PCI_LbaCount] ;
++ u32 pcidac ;
++ u32 pcidas ;
++ u32 pcidasm ;
++ u32 pcidad ;
++ u32 pcidma8c ;
++ u32 pcidma9c ;
++ u32 pcitc ;
++} volatile *PCI_t ;
++
++// PCI messaging unit.
++enum
++{
++ PCIM_Count = 2,
++} ;
++typedef struct
++{
++ u32 pciim [PCIM_Count] ;
++ u32 pciom [PCIM_Count] ;
++ u32 pciid ;
++ u32 pciiic ;
++ u32 pciiim ;
++ u32 pciiod ;
++ u32 pciioic ;
++ u32 pciioim ;
++} volatile *PCIM_t ;
++
++/*******************************************************************************
++ *
++ * PCI Control Register
++ *
++ ******************************************************************************/
++enum
++{
++ PCIC_en_b = 0,
++ PCIC_en_m = 0x00000001,
++ PCIC_tnr_b = 1,
++ PCIC_tnr_m = 0x00000002,
++ PCIC_sce_b = 2,
++ PCIC_sce_m = 0x00000004,
++ PCIC_ien_b = 3,
++ PCIC_ien_m = 0x00000008,
++ PCIC_aaa_b = 4,
++ PCIC_aaa_m = 0x00000010,
++ PCIC_eap_b = 5,
++ PCIC_eap_m = 0x00000020,
++ PCIC_pcim_b = 6,
++ PCIC_pcim_m = 0x000001c0,
++ PCIC_pcim_disabled_v = 0,
++ PCIC_pcim_tnr_v = 1, // Satellite - target not ready
++ PCIC_pcim_suspend_v = 2, // Satellite - suspended CPU.
++ PCIC_pcim_extern_v = 3, // Host - external arbiter.
++ PCIC_pcim_fixed_v = 4, // Host - fixed priority arb.
++ PCIC_pcim_roundrobin_v = 5, // Host - round robin priority.
++ PCIC_pcim_reserved6_v = 6,
++ PCIC_pcim_reserved7_v = 7,
++ PCIC_igm_b = 9,
++ PCIC_igm_m = 0x00000200,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Status Register
++ *
++ ******************************************************************************/
++enum {
++ PCIS_eed_b = 0,
++ PCIS_eed_m = 0x00000001,
++ PCIS_wr_b = 1,
++ PCIS_wr_m = 0x00000002,
++ PCIS_nmi_b = 2,
++ PCIS_nmi_m = 0x00000004,
++ PCIS_ii_b = 3,
++ PCIS_ii_m = 0x00000008,
++ PCIS_cwe_b = 4,
++ PCIS_cwe_m = 0x00000010,
++ PCIS_cre_b = 5,
++ PCIS_cre_m = 0x00000020,
++ PCIS_mdpe_b = 6,
++ PCIS_mdpe_m = 0x00000040,
++ PCIS_sta_b = 7,
++ PCIS_sta_m = 0x00000080,
++ PCIS_rta_b = 8,
++ PCIS_rta_m = 0x00000100,
++ PCIS_rma_b = 9,
++ PCIS_rma_m = 0x00000200,
++ PCIS_sse_b = 10,
++ PCIS_sse_m = 0x00000400,
++ PCIS_ose_b = 11,
++ PCIS_ose_m = 0x00000800,
++ PCIS_pe_b = 12,
++ PCIS_pe_m = 0x00001000,
++ PCIS_tae_b = 13,
++ PCIS_tae_m = 0x00002000,
++ PCIS_rle_b = 14,
++ PCIS_rle_m = 0x00004000,
++ PCIS_bme_b = 15,
++ PCIS_bme_m = 0x00008000,
++ PCIS_prd_b = 16,
++ PCIS_prd_m = 0x00010000,
++ PCIS_rip_b = 17,
++ PCIS_rip_m = 0x00020000,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Status Mask Register
++ *
++ ******************************************************************************/
++enum {
++ PCISM_eed_b = 0,
++ PCISM_eed_m = 0x00000001,
++ PCISM_wr_b = 1,
++ PCISM_wr_m = 0x00000002,
++ PCISM_nmi_b = 2,
++ PCISM_nmi_m = 0x00000004,
++ PCISM_ii_b = 3,
++ PCISM_ii_m = 0x00000008,
++ PCISM_cwe_b = 4,
++ PCISM_cwe_m = 0x00000010,
++ PCISM_cre_b = 5,
++ PCISM_cre_m = 0x00000020,
++ PCISM_mdpe_b = 6,
++ PCISM_mdpe_m = 0x00000040,
++ PCISM_sta_b = 7,
++ PCISM_sta_m = 0x00000080,
++ PCISM_rta_b = 8,
++ PCISM_rta_m = 0x00000100,
++ PCISM_rma_b = 9,
++ PCISM_rma_m = 0x00000200,
++ PCISM_sse_b = 10,
++ PCISM_sse_m = 0x00000400,
++ PCISM_ose_b = 11,
++ PCISM_ose_m = 0x00000800,
++ PCISM_pe_b = 12,
++ PCISM_pe_m = 0x00001000,
++ PCISM_tae_b = 13,
++ PCISM_tae_m = 0x00002000,
++ PCISM_rle_b = 14,
++ PCISM_rle_m = 0x00004000,
++ PCISM_bme_b = 15,
++ PCISM_bme_m = 0x00008000,
++ PCISM_prd_b = 16,
++ PCISM_prd_m = 0x00010000,
++ PCISM_rip_b = 17,
++ PCISM_rip_m = 0x00020000,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Configuration Address Register
++ *
++ ******************************************************************************/
++enum {
++ PCICFGA_reg_b = 2,
++ PCICFGA_reg_m = 0x000000fc,
++ PCICFGA_reg_id_v = 0x00>>2, //use PCFGID_
++ PCICFGA_reg_04_v = 0x04>>2, //use PCFG04_
++ PCICFGA_reg_08_v = 0x08>>2, //use PCFG08_
++ PCICFGA_reg_0C_v = 0x0C>>2, //use PCFG0C_
++ PCICFGA_reg_pba0_v = 0x10>>2, //use PCIPBA_
++ PCICFGA_reg_pba1_v = 0x14>>2, //use PCIPBA_
++ PCICFGA_reg_pba2_v = 0x18>>2, //use PCIPBA_
++ PCICFGA_reg_pba3_v = 0x1c>>2, //use PCIPBA_
++ PCICFGA_reg_subsystem_v = 0x2c>>2, //use PCFGSS_
++ PCICFGA_reg_3C_v = 0x3C>>2, //use PCFG3C_
++ PCICFGA_reg_pba0c_v = 0x44>>2, //use PCIPBAC_
++ PCICFGA_reg_pba0m_v = 0x48>>2,
++ PCICFGA_reg_pba1c_v = 0x4c>>2, //use PCIPBAC_
++ PCICFGA_reg_pba1m_v = 0x50>>2,
++ PCICFGA_reg_pba2c_v = 0x54>>2, //use PCIPBAC_
++ PCICFGA_reg_pba2m_v = 0x58>>2,
++ PCICFGA_reg_pba3c_v = 0x5c>>2, //use PCIPBAC_
++ PCICFGA_reg_pba3m_v = 0x60>>2,
++ PCICFGA_reg_pmgt_v = 0x64>>2,
++ PCICFGA_func_b = 8,
++ PCICFGA_func_m = 0x00000700,
++ PCICFGA_dev_b = 11,
++ PCICFGA_dev_m = 0x0000f800,
++ PCICFGA_dev_internal_v = 0,
++ PCICFGA_bus_b = 16,
++ PCICFGA_bus_m = 0x00ff0000,
++ PCICFGA_bus_type0_v = 0, //local bus
++ PCICFGA_en_b = 31, // read only
++ PCICFGA_en_m = 0x80000000,
++} ;
++
++enum {
++ PCFGID_vendor_b = 0,
++ PCFGID_vendor_m = 0x0000ffff,
++ PCFGID_vendor_IDT_v = 0x111d,
++ PCFGID_device_b = 16,
++ PCFGID_device_m = 0xffff0000,
++ PCFGID_device_Korinade_v = 0x0214,
++
++ PCFG04_command_ioena_b = 1,
++ PCFG04_command_ioena_m = 0x00000001,
++ PCFG04_command_memena_b = 2,
++ PCFG04_command_memena_m = 0x00000002,
++ PCFG04_command_bmena_b = 3,
++ PCFG04_command_bmena_m = 0x00000004,
++ PCFG04_command_mwinv_b = 5,
++ PCFG04_command_mwinv_m = 0x00000010,
++ PCFG04_command_parena_b = 7,
++ PCFG04_command_parena_m = 0x00000040,
++ PCFG04_command_serrena_b = 9,
++ PCFG04_command_serrena_m = 0x00000100,
++ PCFG04_command_fastbbena_b = 10,
++ PCFG04_command_fastbbena_m = 0x00000200,
++ PCFG04_status_b = 16,
++ PCFG04_status_m = 0xffff0000,
++ PCFG04_status_66MHz_b = 21, // 66 MHz enable
++ PCFG04_status_66MHz_m = 0x00200000,
++ PCFG04_status_fbb_b = 23,
++ PCFG04_status_fbb_m = 0x00800000,
++ PCFG04_status_mdpe_b = 24,
++ PCFG04_status_mdpe_m = 0x01000000,
++ PCFG04_status_dst_b = 25,
++ PCFG04_status_dst_m = 0x06000000,
++ PCFG04_status_sta_b = 27,
++ PCFG04_status_sta_m = 0x08000000,
++ PCFG04_status_rta_b = 28,
++ PCFG04_status_rta_m = 0x10000000,
++ PCFG04_status_rma_b = 29,
++ PCFG04_status_rma_m = 0x20000000,
++ PCFG04_status_sse_b = 30,
++ PCFG04_status_sse_m = 0x40000000,
++ PCFG04_status_pe_b = 31,
++ PCFG04_status_pe_m = 0x40000000,
++
++ PCFG08_revId_b = 0,
++ PCFG08_revId_m = 0x000000ff,
++ PCFG08_classCode_b = 0,
++ PCFG08_classCode_m = 0xffffff00,
++ PCFG08_classCode_bridge_v = 06,
++ PCFG08_classCode_proc_v = 0x0b3000, // processor-MIPS
++ PCFG0C_cacheline_b = 0,
++ PCFG0C_cacheline_m = 0x000000ff,
++ PCFG0C_masterLatency_b = 8,
++ PCFG0C_masterLatency_m = 0x0000ff00,
++ PCFG0C_headerType_b = 16,
++ PCFG0C_headerType_m = 0x00ff0000,
++ PCFG0C_bist_b = 24,
++ PCFG0C_bist_m = 0xff000000,
++
++ PCIPBA_msi_b = 0,
++ PCIPBA_msi_m = 0x00000001,
++ PCIPBA_p_b = 3,
++ PCIPBA_p_m = 0x00000004,
++ PCIPBA_baddr_b = 8,
++ PCIPBA_baddr_m = 0xffffff00,
++
++ PCFGSS_vendorId_b = 0,
++ PCFGSS_vendorId_m = 0x0000ffff,
++ PCFGSS_id_b = 16,
++ PCFGSS_id_m = 0xffff0000,
++
++ PCFG3C_interruptLine_b = 0,
++ PCFG3C_interruptLine_m = 0x000000ff,
++ PCFG3C_interruptPin_b = 8,
++ PCFG3C_interruptPin_m = 0x0000ff00,
++ PCFG3C_minGrant_b = 16,
++ PCFG3C_minGrant_m = 0x00ff0000,
++ PCFG3C_maxLat_b = 24,
++ PCFG3C_maxLat_m = 0xff000000,
++
++ PCIPBAC_msi_b = 0,
++ PCIPBAC_msi_m = 0x00000001,
++ PCIPBAC_p_b = 1,
++ PCIPBAC_p_m = 0x00000002,
++ PCIPBAC_size_b = 2,
++ PCIPBAC_size_m = 0x0000007c,
++ PCIPBAC_sb_b = 7,
++ PCIPBAC_sb_m = 0x00000080,
++ PCIPBAC_pp_b = 8,
++ PCIPBAC_pp_m = 0x00000100,
++ PCIPBAC_mr_b = 9,
++ PCIPBAC_mr_m = 0x00000600,
++ PCIPBAC_mr_read_v =0, //no prefetching
++ PCIPBAC_mr_readLine_v =1,
++ PCIPBAC_mr_readMult_v =2,
++ PCIPBAC_mrl_b = 11,
++ PCIPBAC_mrl_m = 0x00000800,
++ PCIPBAC_mrm_b = 12,
++ PCIPBAC_mrm_m = 0x00001000,
++ PCIPBAC_trp_b = 13,
++ PCIPBAC_trp_m = 0x00002000,
++
++ PCFG40_trdyTimeout_b = 0,
++ PCFG40_trdyTimeout_m = 0x000000ff,
++ PCFG40_retryLim_b = 8,
++ PCFG40_retryLim_m = 0x0000ff00,
++};
++
++/*******************************************************************************
++ *
++ * PCI Local Base Address [0|1|2|3] Register
++ *
++ ******************************************************************************/
++enum {
++ PCILBA_baddr_b = 0, // In PCI_t -> pcilba [] .a
++ PCILBA_baddr_m = 0xffffff00,
++} ;
++/*******************************************************************************
++ *
++ * PCI Local Base Address Control Register
++ *
++ ******************************************************************************/
++enum {
++ PCILBAC_msi_b = 0, // In pPci->pcilba[i].c
++ PCILBAC_msi_m = 0x00000001,
++ PCILBAC_msi_mem_v = 0,
++ PCILBAC_msi_io_v = 1,
++ PCILBAC_size_b = 2, // In pPci->pcilba[i].c
++ PCILBAC_size_m = 0x0000007c,
++ PCILBAC_sb_b = 7, // In pPci->pcilba[i].c
++ PCILBAC_sb_m = 0x00000080,
++ PCILBAC_rt_b = 8, // In pPci->pcilba[i].c
++ PCILBAC_rt_m = 0x00000100,
++ PCILBAC_rt_noprefetch_v = 0, // mem read
++ PCILBAC_rt_prefetch_v = 1, // mem readline
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Local Base Address [0|1|2|3] Mapping Register
++ *
++ ******************************************************************************/
++enum {
++ PCILBAM_maddr_b = 8,
++ PCILBAM_maddr_m = 0xffffff00,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Decoupled Access Control Register
++ *
++ ******************************************************************************/
++enum {
++ PCIDAC_den_b = 0,
++ PCIDAC_den_m = 0x00000001,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Decoupled Access Status Register
++ *
++ ******************************************************************************/
++enum {
++ PCIDAS_d_b = 0,
++ PCIDAS_d_m = 0x00000001,
++ PCIDAS_b_b = 1,
++ PCIDAS_b_m = 0x00000002,
++ PCIDAS_e_b = 2,
++ PCIDAS_e_m = 0x00000004,
++ PCIDAS_ofe_b = 3,
++ PCIDAS_ofe_m = 0x00000008,
++ PCIDAS_off_b = 4,
++ PCIDAS_off_m = 0x00000010,
++ PCIDAS_ife_b = 5,
++ PCIDAS_ife_m = 0x00000020,
++ PCIDAS_iff_b = 6,
++ PCIDAS_iff_m = 0x00000040,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI DMA Channel 8 Configuration Register
++ *
++ ******************************************************************************/
++enum
++{
++ PCIDMA8C_mbs_b = 0, // Maximum Burst Size.
++ PCIDMA8C_mbs_m = 0x00000fff, // { pcidma8c }
++ PCIDMA8C_our_b = 12, // Optimize Unaligned Burst Reads.
++ PCIDMA8C_our_m = 0x00001000, // { pcidma8c }
++} ;
++
++/*******************************************************************************
++ *
++ * PCI DMA Channel 9 Configuration Register
++ *
++ ******************************************************************************/
++enum
++{
++ PCIDMA9C_mbs_b = 0, // Maximum Burst Size.
++ PCIDMA9C_mbs_m = 0x00000fff, // { pcidma9c }
++} ;
++
++/*******************************************************************************
++ *
++ * PCI to Memory(DMA Channel 8) AND Memory to PCI DMA(DMA Channel 9)Descriptors
++ *
++ ******************************************************************************/
++enum {
++ PCIDMAD_pt_b = 22, // in DEVCMD field (descriptor)
++ PCIDMAD_pt_m = 0x00c00000, // preferred transaction field
++ // These are for reads (DMA channel 8)
++ PCIDMAD_devcmd_mr_v = 0, //memory read
++ PCIDMAD_devcmd_mrl_v = 1, //memory read line
++ PCIDMAD_devcmd_mrm_v = 2, //memory read multiple
++ PCIDMAD_devcmd_ior_v = 3, //I/O read
++ // These are for writes (DMA channel 9)
++ PCIDMAD_devcmd_mw_v = 0, //memory write
++ PCIDMAD_devcmd_mwi_v = 1, //memory write invalidate
++ PCIDMAD_devcmd_iow_v = 3, //I/O write
++
++ // Swap byte field applies to both DMA channel 8 and 9
++ PCIDMAD_sb_b = 24, // in DEVCMD field (descriptor)
++ PCIDMAD_sb_m = 0x01000000, // swap byte field
++} ;
++
++
++/*******************************************************************************
++ *
++ * PCI Target Control Register
++ *
++ ******************************************************************************/
++enum
++{
++ PCITC_rtimer_b = 0, // In PCITC_t -> pcitc
++ PCITC_rtimer_m = 0x000000ff,
++ PCITC_dtimer_b = 8, // In PCITC_t -> pcitc
++ PCITC_dtimer_m = 0x0000ff00,
++ PCITC_rdr_b = 18, // In PCITC_t -> pcitc
++ PCITC_rdr_m = 0x00040000,
++ PCITC_ddt_b = 19, // In PCITC_t -> pcitc
++ PCITC_ddt_m = 0x00080000,
++} ;
++/*******************************************************************************
++ *
++ * PCI messaging unit [applies to both inbound and outbound registers ]
++ *
++ ******************************************************************************/
++enum
++{
++ PCIM_m0_b = 0, // In PCIM_t -> {pci{iic,iim,ioic,ioim}}
++ PCIM_m0_m = 0x00000001, // inbound or outbound message 0
++ PCIM_m1_b = 1, // In PCIM_t -> {pci{iic,iim,ioic,ioim}}
++ PCIM_m1_m = 0x00000002, // inbound or outbound message 1
++ PCIM_db_b = 2, // In PCIM_t -> {pci{iic,iim,ioic,ioim}}
++ PCIM_db_m = 0x00000004, // inbound or outbound doorbell
++};
++
++
++
++
++
++
++#define PCI_MSG_VirtualAddress 0xB8088010
++#define rc32434_pci ((volatile PCI_t) PCI0_VirtualAddress)
++#define rc32434_pci_msg ((volatile PCIM_t) PCI_MSG_VirtualAddress)
++
++#define PCIM_SHFT 0x6
++#define PCIM_BIT_LEN 0x7
++#define PCIM_H_EA 0x3
++#define PCIM_H_IA_FIX 0x4
++#define PCIM_H_IA_RR 0x5
++#if 0
++#define PCI_ADDR_START 0x13000000
++#endif
++
++#define PCI_ADDR_START 0x50000000
++
++#define CPUTOPCI_MEM_WIN 0x02000000
++#define CPUTOPCI_IO_WIN 0x00100000
++#define PCILBA_SIZE_SHFT 2
++#define PCILBA_SIZE_MASK 0x1F
++#define SIZE_256MB 0x1C
++#define SIZE_128MB 0x1B
++#define SIZE_64MB 0x1A
++#define SIZE_32MB 0x19
++#define SIZE_16MB 0x18
++#define SIZE_4MB 0x16
++#define SIZE_2MB 0x15
++#define SIZE_1MB 0x14
++#define KORINA_CONFIG0_ADDR 0x80000000
++#define KORINA_CONFIG1_ADDR 0x80000004
++#define KORINA_CONFIG2_ADDR 0x80000008
++#define KORINA_CONFIG3_ADDR 0x8000000C
++#define KORINA_CONFIG4_ADDR 0x80000010
++#define KORINA_CONFIG5_ADDR 0x80000014
++#define KORINA_CONFIG6_ADDR 0x80000018
++#define KORINA_CONFIG7_ADDR 0x8000001C
++#define KORINA_CONFIG8_ADDR 0x80000020
++#define KORINA_CONFIG9_ADDR 0x80000024
++#define KORINA_CONFIG10_ADDR 0x80000028
++#define KORINA_CONFIG11_ADDR 0x8000002C
++#define KORINA_CONFIG12_ADDR 0x80000030
++#define KORINA_CONFIG13_ADDR 0x80000034
++#define KORINA_CONFIG14_ADDR 0x80000038
++#define KORINA_CONFIG15_ADDR 0x8000003C
++#define KORINA_CONFIG16_ADDR 0x80000040
++#define KORINA_CONFIG17_ADDR 0x80000044
++#define KORINA_CONFIG18_ADDR 0x80000048
++#define KORINA_CONFIG19_ADDR 0x8000004C
++#define KORINA_CONFIG20_ADDR 0x80000050
++#define KORINA_CONFIG21_ADDR 0x80000054
++#define KORINA_CONFIG22_ADDR 0x80000058
++#define KORINA_CONFIG23_ADDR 0x8000005C
++#define KORINA_CONFIG24_ADDR 0x80000060
++#define KORINA_CONFIG25_ADDR 0x80000064
++#define KORINA_CMD (PCFG04_command_ioena_m | \
++ PCFG04_command_memena_m | \
++ PCFG04_command_bmena_m | \
++ PCFG04_command_mwinv_m | \
++ PCFG04_command_parena_m | \
++ PCFG04_command_serrena_m )
++
++#define KORINA_STAT (PCFG04_status_mdpe_m | \
++ PCFG04_status_sta_m | \
++ PCFG04_status_rta_m | \
++ PCFG04_status_rma_m | \
++ PCFG04_status_sse_m | \
++ PCFG04_status_pe_m)
++
++#define KORINA_CNFG1 ((KORINA_STAT<<16)|KORINA_CMD)
++
++#define KORINA_REVID 0
++#define KORINA_CLASS_CODE 0
++#define KORINA_CNFG2 ((KORINA_CLASS_CODE<<8) | \
++ KORINA_REVID)
++
++#define KORINA_CACHE_LINE_SIZE 4
++#define KORINA_MASTER_LAT 0x3c
++#define KORINA_HEADER_TYPE 0
++#define KORINA_BIST 0
++
++#define KORINA_CNFG3 ((KORINA_BIST << 24) | \
++ (KORINA_HEADER_TYPE<<16) | \
++ (KORINA_MASTER_LAT<<8) | \
++ KORINA_CACHE_LINE_SIZE )
++
++#define KORINA_BAR0 0x00000008 /* 128 MB Memory */
++#define KORINA_BAR1 0x18800001 /* 1 MB IO */
++#define KORINA_BAR2 0x18000001 /* 2 MB IO window for Korina
++ internal Registers */
++#define KORINA_BAR3 0x48000008 /* Spare 128 MB Memory */
++
++#define KORINA_CNFG4 KORINA_BAR0
++#define KORINA_CNFG5 KORINA_BAR1
++#define KORINA_CNFG6 KORINA_BAR2
++#define KORINA_CNFG7 KORINA_BAR3
++
++#define KORINA_SUBSYS_VENDOR_ID 0x011d
++#define KORINA_SUBSYSTEM_ID 0x0214
++#define KORINA_CNFG8 0
++#define KORINA_CNFG9 0
++#define KORINA_CNFG10 0
++#define KORINA_CNFG11 ((KORINA_SUBSYS_VENDOR_ID<<16) | \
++ KORINA_SUBSYSTEM_ID)
++#define KORINA_INT_LINE 1
++#define KORINA_INT_PIN 1
++#define KORINA_MIN_GNT 8
++#define KORINA_MAX_LAT 0x38
++#define KORINA_CNFG12 0
++#define KORINA_CNFG13 0
++#define KORINA_CNFG14 0
++#define KORINA_CNFG15 ((KORINA_MAX_LAT<<24) | \
++ (KORINA_MIN_GNT<<16) | \
++ (KORINA_INT_PIN<<8) | \
++ KORINA_INT_LINE)
++#define KORINA_RETRY_LIMIT 0x80
++#define KORINA_TRDY_LIMIT 0x80
++#define KORINA_CNFG16 ((KORINA_RETRY_LIMIT<<8) | \
++ KORINA_TRDY_LIMIT)
++#define PCI_PBAxC_R 0x0
++#define PCI_PBAxC_RL 0x1
++#define PCI_PBAxC_RM 0x2
++#define SIZE_SHFT 2
++
++#if defined(__MIPSEB__)
++#define KORINA_PBA0C ( PCIPBAC_mrl_m | PCIPBAC_sb_m | \
++ ((PCI_PBAxC_RM &0x3) << PCIPBAC_mr_b) | \
++ PCIPBAC_pp_m | \
++ (SIZE_128MB<<SIZE_SHFT) | \
++ PCIPBAC_p_m)
++#else
++#define KORINA_PBA0C ( PCIPBAC_mrl_m | \
++ ((PCI_PBAxC_RM &0x3) << PCIPBAC_mr_b) | \
++ PCIPBAC_pp_m | \
++ (SIZE_128MB<<SIZE_SHFT) | \
++ PCIPBAC_p_m)
++#endif
++#define KORINA_CNFG17 KORINA_PBA0C
++#define KORINA_PBA0M 0x0
++#define KORINA_CNFG18 KORINA_PBA0M
++
++#if defined(__MIPSEB__)
++#define KORINA_PBA1C ((SIZE_1MB<<SIZE_SHFT) | PCIPBAC_sb_m | \
++ PCIPBAC_msi_m)
++#else
++#define KORINA_PBA1C ((SIZE_1MB<<SIZE_SHFT) | \
++ PCIPBAC_msi_m)
++#endif
++#define KORINA_CNFG19 KORINA_PBA1C
++#define KORINA_PBA1M 0x0
++#define KORINA_CNFG20 KORINA_PBA1M
++
++#if defined(__MIPSEB__)
++#define KORINA_PBA2C ((SIZE_2MB<<SIZE_SHFT) | PCIPBAC_sb_m | \
++ PCIPBAC_msi_m)
++#else
++#define KORINA_PBA2C ((SIZE_2MB<<SIZE_SHFT) | \
++ PCIPBAC_msi_m)
++#endif
++#define KORINA_CNFG21 KORINA_PBA2C
++#define KORINA_PBA2M 0x18000000
++#define KORINA_CNFG22 KORINA_PBA2M
++#define KORINA_PBA3C 0
++#define KORINA_CNFG23 KORINA_PBA3C
++#define KORINA_PBA3M 0
++#define KORINA_CNFG24 KORINA_PBA3M
++
++
++
++#define PCITC_DTIMER_VAL 8
++#define PCITC_RTIMER_VAL 0x10
++
++
++
++
++#endif // __IDT_PCI_H__
++
++
++
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_rst.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_rst.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_rst.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_rst.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,119 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Reset register definitions.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_RST_H__
++#define __IDT_RST_H__
++
++enum
++{
++ RST0_PhysicalAddress = 0x18000000,
++ RST_PhysicalAddress = RST0_PhysicalAddress, // Default
++
++ RST0_VirtualAddress = 0xb8000000,
++ RST_VirtualAddress = RST0_VirtualAddress, // Default
++} ;
++
++typedef struct RST_s
++{
++ u32 filler [0x0006] ;
++ u32 sysid ;
++ u32 filler2 [0x2000-8] ; // Pad out to offset 0x8000
++ u32 reset ;
++ u32 bcv ;
++ u32 cea ;
++} volatile * RST_t ;
++
++enum
++{
++ SYSID_rev_b = 0,
++ SYSID_rev_m = 0x000000ff,
++ SYSID_imp_b = 8,
++ SYSID_imp_m = 0x000fff00,
++ SYSID_vendor_b = 8,
++ SYSID_vendor_m = 0xfff00000,
++
++ BCV_pll_b = 0,
++ BCV_pll_m = 0x0000000f,
++ BCV_pll_PLLBypass_v = 0x0, // PCLK=1*CLK.
++ BCV_pll_Mul3_v = 0x1, // PCLK=3*CLK.
++ BCV_pll_Mul4_v = 0x2, // PCLK=4*CLK.
++ BCV_pll_SlowMul5_v = 0x3, // PCLK=5*CLK.
++ BCV_pll_Mul5_v = 0x4, // PCLK=5*CLK.
++ BCV_pll_SlowMul6_v = 0x5, // PCLK=6*CLK.
++ BCV_pll_Mul6_v = 0x6, // PCLK=6*CLK.
++ BCV_pll_Mul8_v = 0x7, // PCLK=8*CLK.
++ BCV_pll_Mul10_v = 0x8, // PCLK=10*CLK.
++ BCV_pll_Res9_v = 0x9,
++ BCV_pll_Res10_v = 0xa,
++ BCV_pll_Res11_v = 0xb,
++ BCV_pll_Res12_v = 0xc,
++ BCV_pll_Res13_v = 0xd,
++ BCV_pll_Res14_v = 0xe,
++ BCV_pll_Res15_v = 0xf,
++ BCV_clkDiv_b = 4,
++ BCV_clkDiv_m = 0x00000030,
++ BCV_clkDiv_Div1_v = 0x0,
++ BCV_clkDiv_Div2_v = 0x1,
++ BCV_clkDiv_Div4_v = 0x2,
++ BCV_clkDiv_Res3_v = 0x3,
++ BCV_bigEndian_b = 6,
++ BCV_bigEndian_m = 0x00000040,
++ BCV_resetFast_b = 7,
++ BCV_resetFast_m = 0x00000080,
++ BCV_pciMode_b = 8,
++ BCV_pciMode_m = 0x00000700,
++ BCV_pciMode_disabled_v = 0, // PCI is disabled.
++ BCV_pciMode_tnr_v = 1, // satellite Target Not Ready.
++ BCV_pciMode_suspended_v = 2, // satellite with suspended CPU.
++ BCV_pciMode_external_v = 3, // host, external arbiter.
++ BCV_pciMode_fixed_v = 4, // host, fixed priority arbiter.
++ BCV_pciMode_roundRobin_v= 5, // host, round robin arbiter.
++ BCV_pciMode_res6_v = 6,
++ BCV_pciMode_res7_v = 7,
++ BCV_watchDisable_b = 11,
++ BCV_watchDisable_m = 0x00000800,
++ BCV_res12_b = 12,
++ BCV_res12_m = 0x00001000,
++ BCV_res13_b = 13,
++ BCV_res13_m = 0x00002000,
++ BCV_res14_b = 14,
++ BCV_res14_m = 0x00004000,
++ BCV_res15_b = 15,
++ BCV_res15_m = 0x00008000,
++} ;
++#endif // __IDT_RST_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_spi.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_spi.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_spi.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_spi.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,120 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Serial Peripheral Interface register definitions.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_SPI_H__
++#define __IDT_SPI_H__
++
++enum
++{
++ SPI0_PhysicalAddress = 0x18070000,
++ SPI_PhysicalAddress = SPI0_PhysicalAddress,
++
++ SPI0_VirtualAddress = 0xB8070000,
++ SPI_VirtualAddress = SPI0_VirtualAddress,
++} ;
++
++typedef struct
++{
++ u32 spcp ; // prescalar. 0=off, * spiClk = sysClk/(2*(spcp+1)*SPR)
++ u32 spc ; // spi control reg use SPC_
++ u32 sps ; // spi status reg use SPS_
++ u32 spd ; // spi data reg use SPD_
++ u32 siofunc ; // serial IO function use SIOFUNC_
++ u32 siocfg ; // serial IO config use SIOCFG_
++ u32 siod; // serial IO data use SIOD_
++} volatile *SPI_t ;
++
++enum
++{
++ SPCP_div_b = 0,
++ SPCP_div_m = 0x000000ff,
++ SPC_spr_b = 0,
++ SPC_spr_m = 0x00000003,
++ SPC_spr_div2_v = 0,
++ SPC_spr_div4_v = 1,
++ SPC_spr_div16_v = 2,
++ SPC_spr_div32_v = 3,
++ SPC_cpha_b = 2,
++ SPC_cpha_m = 0x00000004,
++ SPC_cpol_b = 3,
++ SPC_cpol_m = 0x00000008,
++ SPC_mstr_b = 4,
++ SPC_mstr_m = 0x00000010,
++ SPC_spe_b = 6,
++ SPC_spe_m = 0x00000040,
++ SPC_spie_b = 7,
++ SPC_spie_m = 0x00000080,
++
++ SPS_modf_b = 4,
++ SPS_modf_m = 0x00000010,
++ SPS_wcol_b = 6,
++ SPS_wcol_m = 0x00000040,
++ SPS_spif_b = 7,
++ SPS_spif_m = 0x00000070,
++
++ SPD_data_b = 0,
++ SPD_data_m = 0x000000ff,
++
++ SIOFUNC_sdo_b = 0,
++ SIOFUNC_sdo_m = 0x00000001,
++ SIOFUNC_sdi_b = 1,
++ SIOFUNC_sdi_m = 0x00000002,
++ SIOFUNC_sck_b = 2,
++ SIOFUNC_sck_m = 0x00000004,
++ SIOFUNC_pci_b = 3,
++ SIOFUNC_pci_m = 0x00000008,
++
++ SIOCFG_sdo_b = 0,
++ SIOCFG_sdo_m = 0x00000001,
++ SIOCFG_sdi_b = 1,
++ SIOCFG_sdi_m = 0x00000002,
++ SIOCFG_sck_b = 2,
++ SIOCFG_sck_m = 0x00000004,
++ SIOCFG_pci_b = 3,
++ SIOCFG_pci_m = 0x00000008,
++
++ SIOD_sdo_b = 0,
++ SIOD_sdo_m = 0x00000001,
++ SIOD_sdi_b = 1,
++ SIOD_sdi_m = 0x00000002,
++ SIOD_sck_b = 2,
++ SIOD_sck_m = 0x00000004,
++ SIOD_pci_b = 3,
++ SIOD_pci_m = 0x00000008,
++} ;
++#endif // __IDT_SPI_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_timer.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_timer.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_timer.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_timer.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,91 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Definitions for timer registers
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt,neb.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_TIM_H__
++#define __IDT_TIM_H__
++
++enum
++{
++ TIM0_PhysicalAddress = 0x18028000,
++ TIM_PhysicalAddress = TIM0_PhysicalAddress, // Default
++
++ TIM0_VirtualAddress = 0xb8028000,
++ TIM_VirtualAddress = TIM0_VirtualAddress, // Default
++} ;
++
++enum
++{
++ TIM_Count = 3,
++} ;
++
++struct TIM_CNTR_s
++{
++ u32 count ;
++ u32 compare ;
++ u32 ctc ; //use CTC_
++} ;
++
++typedef struct TIM_s
++{
++ struct TIM_CNTR_s tim [TIM_Count] ;
++ u32 rcount ; //use RCOUNT_
++ u32 rcompare ; //use RCOMPARE_
++ u32 rtc ; //use RTC_
++} volatile * TIM_t ;
++
++enum
++{
++ CTC_en_b = 0,
++ CTC_en_m = 0x00000001,
++ CTC_to_b = 1,
++ CTC_to_m = 0x00000002,
++
++ RCOUNT_count_b = 0,
++ RCOUNT_count_m = 0x0000ffff,
++ RCOMPARE_compare_b = 0,
++ RCOMPARE_compare_m = 0x0000ffff,
++ RTC_ce_b = 0,
++ RTC_ce_m = 0x00000001,
++ RTC_to_b = 1,
++ RTC_to_m = 0x00000002,
++ RTC_rqe_b = 2,
++ RTC_rqe_m = 0x00000004,
++
++} ;
++#endif // __IDT_TIM_H__
++
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_uart.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_uart.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32434/rc32434_uart.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32434/rc32434_uart.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,189 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * UART register definitions
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_UART_H__
++#define __IDT_UART_H__
++
++enum
++{
++ UART0_PhysicalAddress = 0x1c000000,
++ UART_PhysicalAddress = UART0_PhysicalAddress, // Default
++
++ UART0_VirtualAddress = 0xbc000000,
++ UART_VirtualAddress = UART0_VirtualAddress, // Default
++} ;
++
++/*
++ * Register definitions are in bytes so we can handle endian problems.
++ */
++
++typedef struct UART_s
++{
++ union
++ {
++ u32 const uartrb ; // 0x00 - DLAB=0, read.
++ u32 uartth ; // 0x00 - DLAB=0, write.
++ u32 uartdll ; // 0x00 - DLAB=1, read/write.
++ } ;
++
++ union
++ {
++ u32 uartie ; // 0x04 - DLAB=0, read/write.
++ u32 uartdlh ; // 0x04 - DLAB=1, read/write.
++ } ;
++ union
++ {
++ u32 const uartii ; // 0x08 - DLAB=0, read.
++ u32 uartfc ; // 0x08 - DLAB=0, write.
++ } ;
++
++ u32 uartlc ; // 0x0c
++ u32 uartmc ; // 0x10
++ u32 uartls ; // 0x14
++ u32 uartms ; // 0x18
++ u32 uarts ; // 0x1c
++} volatile *UART_t ;
++
++// Reset registers.
++typedef u32 volatile *UARTRR_t ;
++
++enum
++{
++ UARTIE_rda_b = 0,
++ UARTIE_rda_m = 0x00000001,
++ UARTIE_the_b = 1,
++ UARTIE_the_m = 0x00000002,
++ UARTIE_rls_b = 2,
++ UARTIE_rls_m = 0x00000004,
++ UARTIE_ems_b = 3,
++ UARTIE_ems_m = 0x00000008,
++
++ UARTII_pi_b = 0,
++ UARTII_pi_m = 0x00000001,
++ UARTII_iid_b = 1,
++ UARTII_iid_m = 0x0000000e,
++ UARTII_iid_ms_v = 0, // Modem stat-CTS,DSR,RI or DCD.
++ UARTII_iid_thre_v = 1, // Trans. Holding Reg. empty.
++ UARTII_iid_rda_v = 2, // Receive data available
++ UARTII_iid_rls_v = 3, // Overrun, parity, etc, error.
++ UARTII_iid_res4_v = 4, // reserved.
++ UARTII_iid_res5_v = 5, // reserved.
++ UARTII_iid_cto_v = 6, // Character timeout.
++ UARTII_iid_res7_v = 7, // reserved.
++
++ UARTFC_en_b = 0,
++ UARTFC_en_m = 0x00000001,
++ UARTFC_rr_b = 1,
++ UARTFC_rr_m = 0x00000002,
++ UARTFC_tr_b = 2,
++ UARTFC_tr_m = 0x00000004,
++ UARTFC_dms_b = 3,
++ UARTFC_dms_m = 0x00000008,
++ UARTFC_rt_b = 6,
++ UARTFC_rt_m = 0x000000c0,
++ UARTFC_rt_1Byte_v = 0,
++ UARTFC_rt_4Byte_v = 1,
++ UARTFC_rt_8Byte_v = 2,
++ UARTFC_rt_14Byte_v = 3,
++
++ UARTLC_wls_b = 0,
++ UARTLC_wls_m = 0x00000003,
++ UARTLC_wls_5Bits_v = 0,
++ UARTLC_wls_6Bits_v = 1,
++ UARTLC_wls_7Bits_v = 2,
++ UARTLC_wls_8Bits_v = 3,
++ UARTLC_stb_b = 2,
++ UARTLC_stb_m = 0x00000004,
++ UARTLC_pen_b = 3,
++ UARTLC_pen_m = 0x00000008,
++ UARTLC_eps_b = 4,
++ UARTLC_eps_m = 0x00000010,
++ UARTLC_sp_b = 5,
++ UARTLC_sp_m = 0x00000020,
++ UARTLC_sb_b = 6,
++ UARTLC_sb_m = 0x00000040,
++ UARTLC_dlab_b = 7,
++ UARTLC_dlab_m = 0x00000080,
++
++ UARTMC_dtr_b = 0,
++ UARTMC_dtr_m = 0x00000001,
++ UARTMC_rts_b = 1,
++ UARTMC_rts_m = 0x00000002,
++ UARTMC_o1_b = 2,
++ UARTMC_o1_m = 0x00000004,
++ UARTMC_o2_b = 3,
++ UARTMC_o2_m = 0x00000008,
++ UARTMC_lp_b = 4,
++ UARTMC_lp_m = 0x00000010,
++
++ UARTLS_dr_b = 0,
++ UARTLS_dr_m = 0x00000001,
++ UARTLS_oe_b = 1,
++ UARTLS_oe_m = 0x00000002,
++ UARTLS_pe_b = 2,
++ UARTLS_pe_m = 0x00000004,
++ UARTLS_fe_b = 3,
++ UARTLS_fe_m = 0x00000008,
++ UARTLS_bi_b = 4,
++ UARTLS_bi_m = 0x00000010,
++ UARTLS_thr_b = 5,
++ UARTLS_thr_m = 0x00000020,
++ UARTLS_te_b = 6,
++ UARTLS_te_m = 0x00000040,
++ UARTLS_rfe_b = 7,
++ UARTLS_rfe_m = 0x00000080,
++
++ UARTMS_dcts_b = 0,
++ UARTMS_dcts_m = 0x00000001,
++ UARTMS_ddsr_b = 1,
++ UARTMS_ddsr_m = 0x00000002,
++ UARTMS_teri_b = 2,
++ UARTMS_teri_m = 0x00000004,
++ UARTMS_ddcd_b = 3,
++ UARTMS_ddcd_m = 0x00000008,
++ UARTMS_cts_b = 4,
++ UARTMS_cts_m = 0x00000010,
++ UARTMS_dsr_b = 5,
++ UARTMS_dsr_m = 0x00000020,
++ UARTMS_ri_b = 6,
++ UARTMS_ri_m = 0x00000040,
++ UARTMS_dcd_b = 7,
++ UARTMS_dcd_m = 0x00000080,
++} ;
++
++#endif // __IDT_UART_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438_dma.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438_dma.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438_dma.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438_dma.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,231 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Register definitions for IDT RC32438 DMA.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++#ifndef __IDT_RC32438_DMA_H__
++#define __IDT_RC32438_DMA_H__
++enum
++{
++ DMA0_PhysicalAddress = 0x18040000,
++ DMA_PhysicalAddress = DMA0_PhysicalAddress, // Default
++
++ DMA0_VirtualAddress = 0xb8040000,
++ DMA_VirtualAddress = DMA0_VirtualAddress, // Default
++} ;
++
++/*
++ * DMA descriptor (in physical memory).
++ */
++
++typedef struct DMAD_s
++{
++ u32 control ; // Control. use DMAD_*
++ u32 ca ; // Current Address.
++ u32 devcs ; // Device control and status.
++ u32 link ; // Next descriptor in chain.
++} volatile *DMAD_t ;
++
++enum
++{
++ DMAD_size = sizeof (struct DMAD_s),
++ DMAD_count_b = 0, // in DMAD_t -> control
++ DMAD_count_m = 0x0003ffff, // in DMAD_t -> control
++ DMAD_ds_b = 20, // in DMAD_t -> control
++ DMAD_ds_m = 0x00300000, // in DMAD_t -> control
++ DMAD_ds_extToMem0_v = 0,
++ DMAD_ds_memToExt0_v = 1,
++ DMAD_ds_extToMem1_v = 0,
++ DMAD_ds_memToExt1_v = 1,
++ DMAD_ds_ethRcv0_v = 0,
++ DMAD_ds_ethXmt0_v = 0,
++ DMAD_ds_ethRcv1_v = 0,
++ DMAD_ds_ethXmt2_v = 0,
++ DMAD_ds_memToFifo_v = 0,
++ DMAD_ds_fifoToMem_v = 0,
++ DMAD_ds_rng_de_v = 1,//randomNumberGenerator on LC/DE
++ DMAD_ds_pciToMem_v = 0,
++ DMAD_ds_memToPci_v = 0,
++ DMAD_ds_securityInput_v = 0,
++ DMAD_ds_securityOutput_v = 0,
++ DMAD_ds_rng_se_v = 0,//randomNumberGenerator on SE
++
++ DMAD_devcmd_b = 22, // in DMAD_t -> control
++ DMAD_devcmd_m = 0x01c00000, // in DMAD_t -> control
++ DMAD_devcmd_byte_v = 0, //memory-to-memory
++ DMAD_devcmd_halfword_v = 1, //memory-to-memory
++ DMAD_devcmd_word_v = 2, //memory-to-memory
++ DMAD_devcmd_2words_v = 3, //memory-to-memory
++ DMAD_devcmd_4words_v = 4, //memory-to-memory
++ DMAD_devcmd_6words_v = 5, //memory-to-memory
++ DMAD_devcmd_8words_v = 6, //memory-to-memory
++ DMAD_devcmd_16words_v = 7, //memory-to-memory
++ DMAD_cof_b = 25, // chain on finished
++ DMAD_cof_m = 0x02000000, //
++ DMAD_cod_b = 26, // chain on done
++ DMAD_cod_m = 0x04000000, //
++ DMAD_iof_b = 27, // interrupt on finished
++ DMAD_iof_m = 0x08000000, //
++ DMAD_iod_b = 28, // interrupt on done
++ DMAD_iod_m = 0x10000000, //
++ DMAD_t_b = 29, // terminated
++ DMAD_t_m = 0x20000000, //
++ DMAD_d_b = 30, // done
++ DMAD_d_m = 0x40000000, //
++ DMAD_f_b = 31, // finished
++ DMAD_f_m = 0x80000000, //
++} ;
++
++/*
++ * DMA register (within Internal Register Map).
++ */
++
++struct DMA_Chan_s
++{
++ u32 dmac ; // Control.
++ u32 dmas ; // Status.
++ u32 dmasm ; // Mask.
++ u32 dmadptr ; // Descriptor pointer.
++ u32 dmandptr ; // Next descriptor pointer.
++};
++
++typedef struct DMA_Chan_s volatile *DMA_Chan_t ;
++
++//DMA_Channels use DMACH_count instead
++
++enum
++{
++ DMAC_run_b = 0, //
++ DMAC_run_m = 0x00000001, //
++ DMAC_dm_b = 1, // done mask
++ DMAC_dm_m = 0x00000002, //
++ DMAC_mode_b = 2, //
++ DMAC_mode_m = 0x0000000c, //
++ DMAC_mode_auto_v = 0,
++ DMAC_mode_burst_v = 1,
++ DMAC_mode_transfer_v = 2, //usually used
++ DMAC_mode_reserved_v = 3,
++ DMAC_a_b = 4, //
++ DMAC_a_m = 0x00000010, //
++
++ DMAS_f_b = 0, // finished (sticky)
++ DMAS_f_m = 0x00000001, //
++ DMAS_d_b = 1, // done (sticky)
++ DMAS_d_m = 0x00000002, //
++ DMAS_c_b = 2, // chain (sticky)
++ DMAS_c_m = 0x00000004, //
++ DMAS_e_b = 3, // error (sticky)
++ DMAS_e_m = 0x00000008, //
++ DMAS_h_b = 4, // halt (sticky)
++ DMAS_h_m = 0x00000010, //
++
++ DMASM_f_b = 0, // finished (1=mask)
++ DMASM_f_m = 0x00000001, //
++ DMASM_d_b = 1, // done (1=mask)
++ DMASM_d_m = 0x00000002, //
++ DMASM_c_b = 2, // chain (1=mask)
++ DMASM_c_m = 0x00000004, //
++ DMASM_e_b = 3, // error (1=mask)
++ DMASM_e_m = 0x00000008, //
++ DMASM_h_b = 4, // halt (1=mask)
++ DMASM_h_m = 0x00000010, //
++} ;
++
++/*
++ * DMA channel definitions
++ */
++
++enum
++{
++ DMACH_extToMem0 = 0,
++ DMACH_memToExt0 = 0,
++ DMACH_extToMem1 = 1,
++ DMACH_memToExt1 = 1,
++ DMACH_ethRcv0 = 2,
++ DMACH_ethXmt0 = 3,
++ DMACH_ethRcv1 = 4,
++ DMACH_ethXmt2 = 5,
++ DMACH_memToFifo = 6,
++ DMACH_fifoToMem = 7,
++ DMACH_rng_de = 7,//randomNumberGenerator on LC/DE
++ DMACH_pciToMem = 8,
++ DMACH_memToPci = 9,
++ DMACH_securityInput = 10,
++ DMACH_securityOutput = 11,
++ DMACH_rng_se = 12, //randomNumberGenerator on SE
++
++ DMACH_count //must be last
++};
++
++
++typedef struct DMAC_s
++{
++ struct DMA_Chan_s ch [DMACH_count] ; //use ch[DMACH_]
++} volatile *DMA_t ;
++
++
++/*
++ * External DMA parameters
++*/
++
++enum
++{
++ DMADEVCMD_ts_b = 0, // ts field in devcmd
++ DMADEVCMD_ts_m = 0x00000007, // ts field in devcmd
++ DMADEVCMD_ts_byte_v = 0,
++ DMADEVCMD_ts_halfword_v = 1,
++ DMADEVCMD_ts_word_v = 2,
++ DMADEVCMD_ts_2word_v = 3,
++ DMADEVCMD_ts_4word_v = 4,
++ DMADEVCMD_ts_6word_v = 5,
++ DMADEVCMD_ts_8word_v = 6,
++ DMADEVCMD_ts_16word_v = 7
++};
++
++
++#if 1 // aws - Compatibility.
++# define EXTDMA_ts_b DMADEVCMD_ts_b
++# define EXTDMA_ts_m DMADEVCMD_ts_m
++# define EXTDMA_ts_byte_v DMADEVCMD_ts_byte_v
++# define EXTDMA_ts_halfword_v DMADEVCMD_ts_halfword_v
++# define EXTDMA_ts_word_v DMADEVCMD_ts_word_v
++# define EXTDMA_ts_2word_v DMADEVCMD_ts_2word_v
++# define EXTDMA_ts_4word_v DMADEVCMD_ts_4word_v
++# define EXTDMA_ts_6word_v DMADEVCMD_ts_6word_v
++# define EXTDMA_ts_8word_v DMADEVCMD_ts_8word_v
++# define EXTDMA_ts_16word_v DMADEVCMD_ts_16word_v
++#endif // aws - Compatibility.
++
++#endif //__IDT_RC32438_DMA_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438_dma_v.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438_dma_v.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438_dma_v.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438_dma_v.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,82 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * DMA operations for IDT RC32438.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_RC32438_DMA_V_H__
++#define __IDT_RC32438_DMA_V_H__
++#include <asm/idt-boards/rc32438/rc32438_dma.h>
++
++#define DMA_CHAN_OFFSET 0x14
++#define IS_DMA_USED(X) (((X) & (DMAD_f_m | DMAD_d_m | DMAD_t_m)) != 0)
++#define DMA_COUNT(count) \
++ ((count) & DMAD_count_m)
++
++#define DMA_HALT_TIMEOUT 500
++
++
++static inline int rc32438_halt_dma(DMA_Chan_t ch)
++{
++ int timeout=1;
++ if (rc32438_readl(&ch->dmac) & DMAC_run_m) {
++ rc32438_writel(0, &ch->dmac);
++
++ for (timeout = DMA_HALT_TIMEOUT; timeout > 0; timeout--) {
++ if (rc32438_readl(&ch->dmas) & DMAS_h_m) {
++ rc32438_writel(0, &ch->dmas);
++ break;
++ }
++ }
++
++ }
++
++ return timeout ? 0 : 1;
++}
++
++
++
++
++static inline void rc32438_start_dma(DMA_Chan_t ch, u32 dma_addr)
++{
++ rc32438_writel(0, &ch->dmandptr);
++ rc32438_writel(dma_addr, &ch->dmadptr);
++}
++
++static inline void rc32438_chain_dma(DMA_Chan_t ch, u32 dma_addr)
++{
++ rc32438_writel(dma_addr, &ch->dmandptr);
++}
++#endif //__IDT_RC32438_DMA_V_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438_eth.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438_eth.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438_eth.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438_eth.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,328 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Definitions for IDT EB438 ethernet
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_RC32438_ETH_H__
++#define __IDT_RC32438_ETH_H__
++enum
++{
++ ETH0_PhysicalAddress = 0x18058000,
++ ETH_PhysicalAddress = ETH0_PhysicalAddress, // Default
++
++ ETH0_VirtualAddress = 0xb8058000,
++ ETH_VirtualAddress = ETH0_VirtualAddress, // Default
++ ETH1_PhysicalAddress = 0x18060000,
++ ETH1_VirtualAddress = 0xb8060000, // Default
++} ;
++
++typedef struct
++{
++ u32 ethintfc ;
++ u32 ethfifott ;
++ u32 etharc ;
++ u32 ethhash0 ;
++ u32 ethhash1 ;
++ u32 ethu0 [4] ; // Reserved.
++ u32 ethpfs ;
++ u32 ethmcp ;
++ u32 eth_u1 [10] ; // Reserved.
++ u32 ethspare ;
++ u32 eth_u2 [42] ; // Reserved.
++ u32 ethsal0 ;
++ u32 ethsah0 ;
++ u32 ethsal1 ;
++ u32 ethsah1 ;
++ u32 ethsal2 ;
++ u32 ethsah2 ;
++ u32 ethsal3 ;
++ u32 ethsah3 ;
++ u32 ethrbc ;
++ u32 ethrpc ;
++ u32 ethrupc ;
++ u32 ethrfc ;
++ u32 ethtbc ;
++ u32 ethgpf ;
++ u32 eth_u9 [50] ; // Reserved.
++ u32 ethmac1 ;
++ u32 ethmac2 ;
++ u32 ethipgt ;
++ u32 ethipgr ;
++ u32 ethclrt ;
++ u32 ethmaxf ;
++ u32 eth_u10 ; // Reserved.
++ u32 ethmtest ;
++ u32 miimcfg ;
++ u32 miimcmd ;
++ u32 miimaddr ;
++ u32 miimwtd ;
++ u32 miimrdd ;
++ u32 miimind ;
++ u32 eth_u11 ; // Reserved.
++ u32 eth_u12 ; // Reserved.
++ u32 ethcfsa0 ;
++ u32 ethcfsa1 ;
++ u32 ethcfsa2 ;
++} volatile *ETH_t;
++
++enum
++{
++ ETHINTFC_en_b = 0,
++ ETHINTFC_en_m = 0x00000001,
++ ETHINTFC_its_b = 1,
++ ETHINTFC_its_m = 0x00000002,
++ ETHINTFC_rip_b = 2,
++ ETHINTFC_rip_m = 0x00000004,
++ ETHINTFC_jam_b = 3,
++ ETHINTFC_jam_m = 0x00000008,
++ ETHINTFC_ovr_b = 4,
++ ETHINTFC_ovr_m = 0x00000010,
++ ETHINTFC_und_b = 5,
++ ETHINTFC_und_m = 0x00000020,
++
++ ETHFIFOTT_tth_b = 0,
++ ETHFIFOTT_tth_m = 0x0000007f,
++
++ ETHARC_pro_b = 0,
++ ETHARC_pro_m = 0x00000001,
++ ETHARC_am_b = 1,
++ ETHARC_am_m = 0x00000002,
++ ETHARC_afm_b = 2,
++ ETHARC_afm_m = 0x00000004,
++ ETHARC_ab_b = 3,
++ ETHARC_ab_m = 0x00000008,
++
++ ETHSAL_byte5_b = 0,
++ ETHSAL_byte5_m = 0x000000ff,
++ ETHSAL_byte4_b = 8,
++ ETHSAL_byte4_m = 0x0000ff00,
++ ETHSAL_byte3_b = 16,
++ ETHSAL_byte3_m = 0x00ff0000,
++ ETHSAL_byte2_b = 24,
++ ETHSAL_byte2_m = 0xff000000,
++
++ ETHSAH_byte1_b = 0,
++ ETHSAH_byte1_m = 0x000000ff,
++ ETHSAH_byte0_b = 8,
++ ETHSAH_byte0_m = 0x0000ff00,
++
++ ETHGPF_ptv_b = 0,
++ ETHGPF_ptv_m = 0x0000ffff,
++
++ ETHPFS_pfd_b = 0,
++ ETHPFS_pfd_m = 0x00000001,
++
++ ETHCFSA0_cfsa4_b = 0,
++ ETHCFSA0_cfsa4_m = 0x000000ff,
++ ETHCFSA0_cfsa5_b = 8,
++ ETHCFSA0_cfsa5_m = 0x0000ff00,
++
++ ETHCFSA1_cfsa2_b = 0,
++ ETHCFSA1_cfsa2_m = 0x000000ff,
++ ETHCFSA1_cfsa3_b = 8,
++ ETHCFSA1_cfsa3_m = 0x0000ff00,
++
++ ETHCFSA2_cfsa0_b = 0,
++ ETHCFSA2_cfsa0_m = 0x000000ff,
++ ETHCFSA2_cfsa1_b = 8,
++ ETHCFSA2_cfsa1_m = 0x0000ff00,
++
++ ETHMAC1_re_b = 0,
++ ETHMAC1_re_m = 0x00000001,
++ ETHMAC1_paf_b = 1,
++ ETHMAC1_paf_m = 0x00000002,
++ ETHMAC1_rfc_b = 2,
++ ETHMAC1_rfc_m = 0x00000004,
++ ETHMAC1_tfc_b = 3,
++ ETHMAC1_tfc_m = 0x00000008,
++ ETHMAC1_lb_b = 4,
++ ETHMAC1_lb_m = 0x00000010,
++ ETHMAC1_mr_b = 31,
++ ETHMAC1_mr_m = 0x80000000,
++
++ ETHMAC2_fd_b = 0,
++ ETHMAC2_fd_m = 0x00000001,
++ ETHMAC2_flc_b = 1,
++ ETHMAC2_flc_m = 0x00000002,
++ ETHMAC2_hfe_b = 2,
++ ETHMAC2_hfe_m = 0x00000004,
++ ETHMAC2_dc_b = 3,
++ ETHMAC2_dc_m = 0x00000008,
++ ETHMAC2_cen_b = 4,
++ ETHMAC2_cen_m = 0x00000010,
++ ETHMAC2_pe_b = 5,
++ ETHMAC2_pe_m = 0x00000020,
++ ETHMAC2_vpe_b = 6,
++ ETHMAC2_vpe_m = 0x00000040,
++ ETHMAC2_ape_b = 7,
++ ETHMAC2_ape_m = 0x00000080,
++ ETHMAC2_ppe_b = 8,
++ ETHMAC2_ppe_m = 0x00000100,
++ ETHMAC2_lpe_b = 9,
++ ETHMAC2_lpe_m = 0x00000200,
++ ETHMAC2_nb_b = 12,
++ ETHMAC2_nb_m = 0x00001000,
++ ETHMAC2_bp_b = 13,
++ ETHMAC2_bp_m = 0x00002000,
++ ETHMAC2_ed_b = 14,
++ ETHMAC2_ed_m = 0x00004000,
++
++ ETHIPGT_ipgt_b = 0,
++ ETHIPGT_ipgt_m = 0x0000007f,
++
++ ETHIPGR_ipgr2_b = 0,
++ ETHIPGR_ipgr2_m = 0x0000007f,
++ ETHIPGR_ipgr1_b = 8,
++ ETHIPGR_ipgr1_m = 0x00007f00,
++
++ ETHCLRT_maxret_b = 0,
++ ETHCLRT_maxret_m = 0x0000000f,
++ ETHCLRT_colwin_b = 8,
++ ETHCLRT_colwin_m = 0x00003f00,
++
++ ETHMAXF_maxf_b = 0,
++ ETHMAXF_maxf_m = 0x0000ffff,
++
++ ETHMTEST_tb_b = 2,
++ ETHMTEST_tb_m = 0x00000004,
++
++ ETHMCP_div_b = 0,
++ ETHMCP_div_m = 0x000000ff,
++
++ MIIMCFG_rsv_b = 0,
++ MIIMCFG_rsv_m = 0x0000000c,
++
++ MIIMCMD_rd_b = 0,
++ MIIMCMD_rd_m = 0x00000001,
++ MIIMCMD_scn_b = 1,
++ MIIMCMD_scn_m = 0x00000002,
++
++ MIIMADDR_regaddr_b = 0,
++ MIIMADDR_regaddr_m = 0x0000001f,
++ MIIMADDR_phyaddr_b = 8,
++ MIIMADDR_phyaddr_m = 0x00001f00,
++
++ MIIMWTD_wdata_b = 0,
++ MIIMWTD_wdata_m = 0x0000ffff,
++
++ MIIMRDD_rdata_b = 0,
++ MIIMRDD_rdata_m = 0x0000ffff,
++
++ MIIMIND_bsy_b = 0,
++ MIIMIND_bsy_m = 0x00000001,
++ MIIMIND_scn_b = 1,
++ MIIMIND_scn_m = 0x00000002,
++ MIIMIND_nv_b = 2,
++ MIIMIND_nv_m = 0x00000004,
++
++} ;
++
++/*
++ * Values for the DEVCS field of the Ethernet DMA Rx and Tx descriptors.
++ */
++enum
++{
++ ETHRX_fd_b = 0,
++ ETHRX_fd_m = 0x00000001,
++ ETHRX_ld_b = 1,
++ ETHRX_ld_m = 0x00000002,
++ ETHRX_rok_b = 2,
++ ETHRX_rok_m = 0x00000004,
++ ETHRX_fm_b = 3,
++ ETHRX_fm_m = 0x00000008,
++ ETHRX_mp_b = 4,
++ ETHRX_mp_m = 0x00000010,
++ ETHRX_bp_b = 5,
++ ETHRX_bp_m = 0x00000020,
++ ETHRX_vlt_b = 6,
++ ETHRX_vlt_m = 0x00000040,
++ ETHRX_cf_b = 7,
++ ETHRX_cf_m = 0x00000080,
++ ETHRX_ovr_b = 8,
++ ETHRX_ovr_m = 0x00000100,
++ ETHRX_crc_b = 9,
++ ETHRX_crc_m = 0x00000200,
++ ETHRX_cv_b = 10,
++ ETHRX_cv_m = 0x00000400,
++ ETHRX_db_b = 11,
++ ETHRX_db_m = 0x00000800,
++ ETHRX_le_b = 12,
++ ETHRX_le_m = 0x00001000,
++ ETHRX_lor_b = 13,
++ ETHRX_lor_m = 0x00002000,
++ ETHRX_ces_b = 14,
++ ETHRX_ces_m = 0x00004000,
++ ETHRX_length_b = 16,
++ ETHRX_length_m = 0xffff0000,
++
++ ETHTX_fd_b = 0,
++ ETHTX_fd_m = 0x00000001,
++ ETHTX_ld_b = 1,
++ ETHTX_ld_m = 0x00000002,
++ ETHTX_oen_b = 2,
++ ETHTX_oen_m = 0x00000004,
++ ETHTX_pen_b = 3,
++ ETHTX_pen_m = 0x00000008,
++ ETHTX_cen_b = 4,
++ ETHTX_cen_m = 0x00000010,
++ ETHTX_hen_b = 5,
++ ETHTX_hen_m = 0x00000020,
++ ETHTX_tok_b = 6,
++ ETHTX_tok_m = 0x00000040,
++ ETHTX_mp_b = 7,
++ ETHTX_mp_m = 0x00000080,
++ ETHTX_bp_b = 8,
++ ETHTX_bp_m = 0x00000100,
++ ETHTX_und_b = 9,
++ ETHTX_und_m = 0x00000200,
++ ETHTX_of_b = 10,
++ ETHTX_of_m = 0x00000400,
++ ETHTX_ed_b = 11,
++ ETHTX_ed_m = 0x00000800,
++ ETHTX_ec_b = 12,
++ ETHTX_ec_m = 0x00001000,
++ ETHTX_lc_b = 13,
++ ETHTX_lc_m = 0x00002000,
++ ETHTX_td_b = 14,
++ ETHTX_td_m = 0x00004000,
++ ETHTX_crc_b = 15,
++ ETHTX_crc_m = 0x00008000,
++ ETHTX_le_b = 16,
++ ETHTX_le_m = 0x00010000,
++ ETHTX_cc_b = 17,
++ ETHTX_cc_m = 0x001E0000,
++} ;
++#endif //__IDT_RC32438_ETH_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438_eth_v.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438_eth_v.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438_eth_v.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438_eth_v.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,72 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * macros for IDT EB438 ethernet
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_RC32438_ETH_V_H__
++#define __IDT_RC32438_ETH_V_H__
++#include <asm/idt-boards/rc32438/rc32438_eth.h>
++
++#define IS_TX_TOK(X) (((X) & (1<<ETHTX_tok_b)) >> ETHTX_tok_b ) /* Transmit Okay */
++#define IS_TX_MP(X) (((X) & (1<<ETHTX_mp_b)) >> ETHTX_mp_b ) /* Multicast */
++#define IS_TX_BP(X) (((X) & (1<<ETHTX_bp_b)) >> ETHTX_bp_b ) /* Broadcast */
++#define IS_TX_UND_ERR(X) (((X) & (1<<ETHTX_und_b)) >> ETHTX_und_b ) /* Transmit FIFO Underflow */
++#define IS_TX_OF_ERR(X) (((X) & (1<<ETHTX_of_b)) >> ETHTX_of_b ) /* Oversized frame */
++#define IS_TX_ED_ERR(X) (((X) & (1<<ETHTX_ed_b)) >> ETHTX_ed_b ) /* Excessive deferral */
++#define IS_TX_EC_ERR(X) (((X) & (1<<ETHTX_ec_b)) >> ETHTX_ec_b) /* Excessive collisions */
++#define IS_TX_LC_ERR(X) (((X) & (1<<ETHTX_lc_b)) >> ETHTX_lc_b ) /* Late Collision */
++#define IS_TX_TD_ERR(X) (((X) & (1<<ETHTX_td_b)) >> ETHTX_td_b ) /* Transmit deferred*/
++#define IS_TX_CRC_ERR(X) (((X) & (1<<ETHTX_crc_b)) >> ETHTX_crc_b ) /* CRC Error */
++#define IS_TX_LE_ERR(X) (((X) & (1<<ETHTX_le_b)) >> ETHTX_le_b ) /* Length Error */
++
++#define TX_COLLISION_COUNT(X) (((X) & ETHTX_cc_m)>>ETHTX_cc_b) /* Collision Count */
++
++#define IS_RCV_ROK(X) (((X) & (1<<ETHRX_rok_b)) >> ETHRX_rok_b) /* Receive Okay */
++#define IS_RCV_FM(X) (((X) & (1<<ETHRX_fm_b)) >> ETHRX_fm_b) /* Is Filter Match */
++#define IS_RCV_MP(X) (((X) & (1<<ETHRX_mp_b)) >> ETHRX_mp_b) /* Is it MP */
++#define IS_RCV_BP(X) (((X) & (1<<ETHRX_bp_b)) >> ETHRX_bp_b) /* Is it BP */
++#define IS_RCV_VLT(X) (((X) & (1<<ETHRX_vlt_b)) >> ETHRX_vlt_b) /* VLAN Tag Detect */
++#define IS_RCV_CF(X) (((X) & (1<<ETHRX_cf_b)) >> ETHRX_cf_b) /* Control Frame */
++#define IS_RCV_OVR_ERR(X) (((X) & (1<<ETHRX_ovr_b)) >> ETHRX_ovr_b) /* Receive Overflow */
++#define IS_RCV_CRC_ERR(X) (((X) & (1<<ETHRX_crc_b)) >> ETHRX_crc_b) /* CRC Error */
++#define IS_RCV_CV_ERR(X) (((X) & (1<<ETHRX_cv_b)) >> ETHRX_cv_b) /* Code Violation */
++#define IS_RCV_DB_ERR(X) (((X) & (1<<ETHRX_db_b)) >> ETHRX_db_b) /* Dribble Bits */
++#define IS_RCV_LE_ERR(X) (((X) & (1<<ETHRX_le_b)) >> ETHRX_le_b) /* Length error */
++#define IS_RCV_LOR_ERR(X) (((X) & (1<<ETHRX_lor_b)) >> ETHRX_lor_b) /* Length Out of Range */
++#define IS_RCV_CES_ERR(X) (((X) & (1<<ETHRX_ces_b)) >> ETHRX_ces_b) /* Preamble error */
++#define RCVPKT_LENGTH(X) (((X) & ETHRX_length_m) >> ETHRX_length_b) /* Length of the received packet */
++
++#endif //__IDT_RC32438_ETH_V_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438_gpio.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438_gpio.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438_gpio.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438_gpio.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,257 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Definitions for IDT RC32438 GPIO.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++#ifndef __IDT_RC32438_GPIO_H__
++#define __IDT_RC32438_GPIO_H__
++enum
++{
++ GPIO0_PhysicalAddress = 0x18048000,
++ GPIO_PhysicalAddress = GPIO0_PhysicalAddress, // Default
++
++ GPIO0_VirtualAddress = 0xb8048000,
++ GPIO_VirtualAddress = GPIO0_VirtualAddress, // Default
++} ;
++
++typedef struct
++{
++ u32 gpiofunc; /* GPIO Function Register
++ * gpiofunc[x]==0 bit = gpio
++ * func[x]==1 bit = altfunc
++ */
++ u32 gpiocfg; /* GPIO Configuration Register
++ * gpiocfg[x]==0 bit = input
++ * gpiocfg[x]==1 bit = output
++ */
++ u32 gpiod; /* GPIO Data Register
++ * gpiod[x] read/write gpio pinX status
++ */
++ u32 gpioilevel; /* GPIO Interrupt Status Register
++ * interrupt level (see gpioistat)
++ */
++ u32 gpioistat; /* Gpio Interrupt Status Register
++ * istat[x] = (gpiod[x] == level[x])
++ * cleared in ISR (STICKY bits)
++ */
++ u32 gpionmien; /* GPIO Non-maskable Interrupt Enable Register */
++} volatile * GPIO_t ;
++
++typedef enum
++{
++ GPIO_gpio_v = 0, // gpiofunc use pin as GPIO.
++ GPIO_alt_v = 1, // gpiofunc use pin as alt.
++ GPIO_input_v = 0, // gpiocfg use pin as input.
++ GPIO_output_v = 1, // gpiocfg use pin as output.
++ GPIO_pin0_b = 0,
++ GPIO_pin0_m = 0x00000001,
++ GPIO_pin1_b = 1,
++ GPIO_pin1_m = 0x00000002,
++ GPIO_pin2_b = 2,
++ GPIO_pin2_m = 0x00000004,
++ GPIO_pin3_b = 3,
++ GPIO_pin3_m = 0x00000008,
++ GPIO_pin4_b = 4,
++ GPIO_pin4_m = 0x00000010,
++ GPIO_pin5_b = 5,
++ GPIO_pin5_m = 0x00000020,
++ GPIO_pin6_b = 6,
++ GPIO_pin6_m = 0x00000040,
++ GPIO_pin7_b = 7,
++ GPIO_pin7_m = 0x00000080,
++ GPIO_pin8_b = 8,
++ GPIO_pin8_m = 0x00000100,
++ GPIO_pin9_b = 9,
++ GPIO_pin9_m = 0x00000200,
++ GPIO_pin10_b = 10,
++ GPIO_pin10_m = 0x00000400,
++ GPIO_pin11_b = 11,
++ GPIO_pin11_m = 0x00000800,
++ GPIO_pin12_b = 12,
++ GPIO_pin12_m = 0x00001000,
++ GPIO_pin13_b = 13,
++ GPIO_pin13_m = 0x00002000,
++ GPIO_pin14_b = 14,
++ GPIO_pin14_m = 0x00004000,
++ GPIO_pin15_b = 15,
++ GPIO_pin15_m = 0x00008000,
++ GPIO_pin16_b = 16,
++ GPIO_pin16_m = 0x00010000,
++ GPIO_pin17_b = 17,
++ GPIO_pin17_m = 0x00020000,
++ GPIO_pin18_b = 18,
++ GPIO_pin18_m = 0x00040000,
++ GPIO_pin19_b = 19,
++ GPIO_pin19_m = 0x00080000,
++ GPIO_pin20_b = 20,
++ GPIO_pin20_m = 0x00100000,
++ GPIO_pin21_b = 21,
++ GPIO_pin21_m = 0x00200000,
++ GPIO_pin22_b = 22,
++ GPIO_pin22_m = 0x00400000,
++ GPIO_pin23_b = 23,
++ GPIO_pin23_m = 0x00800000,
++ GPIO_pin24_b = 24,
++ GPIO_pin24_m = 0x01000000,
++ GPIO_pin25_b = 25,
++ GPIO_pin25_m = 0x02000000,
++ GPIO_pin26_b = 26,
++ GPIO_pin26_m = 0x04000000,
++ GPIO_pin27_b = 27,
++ GPIO_pin27_m = 0x08000000,
++ GPIO_pin28_b = 28,
++ GPIO_pin28_m = 0x10000000,
++ GPIO_pin29_b = 29,
++ GPIO_pin29_m = 0x20000000,
++ GPIO_pin30_b = 30,
++ GPIO_pin30_m = 0x40000000,
++ GPIO_pin31_b = 31,
++ GPIO_pin31_m = 0x80000000,
++
++// Alternate function pins. Corrsponding gpiofunc bit set to GPIO_alt_v.
++
++ GPIO_u0sout_b = GPIO_pin0_b, // UART 0 serial out.
++ GPIO_u0sout_m = GPIO_pin0_m,
++ GPIO_u0sout_cfg_v = GPIO_output_v,
++ GPIO_u0sinp_b = GPIO_pin1_b, // UART 0 serial in.
++ GPIO_u0sinp_m = GPIO_pin1_m,
++ GPIO_u0sinp_cfg_v = GPIO_input_v,
++ GPIO_u0rin_b = GPIO_pin2_b, // UART 0 ring indic.
++ GPIO_u0rin_m = GPIO_pin2_m,
++ GPIO_u0rin_cfg_v = GPIO_input_v,
++ GPIO_u0dcdn_b = GPIO_pin3_b, // UART 0 data carr.det.
++ GPIO_u0dcdn_m = GPIO_pin3_m,
++ GPIO_u0dcdn_cfg_v = GPIO_input_v,
++ GPIO_u0dtrn_b = GPIO_pin4_b, // UART 0 data term rdy.
++ GPIO_u0dtrn_m = GPIO_pin4_m,
++ GPIO_u0dtrn_cfg_v = GPIO_output_v,
++ GPIO_u0dsrn_b = GPIO_pin5_b, // UART 0 data set rdy.
++ GPIO_u0dsrn_m = GPIO_pin5_m,
++ GPIO_u0dsrn_cfg_v = GPIO_input_v,
++ GPIO_u0rtsn_b = GPIO_pin6_b, // UART 0 req. to send.
++ GPIO_u0rtsn_m = GPIO_pin6_m,
++ GPIO_u0rtsn_cfg_v = GPIO_output_v,
++ GPIO_u0ctsn_b = GPIO_pin7_b, // UART 0 clear to send.
++ GPIO_u0ctsn_m = GPIO_pin7_m,
++ GPIO_u0ctsn_cfg_v = GPIO_input_v,
++
++ GPIO_u1sout_b = GPIO_pin8_b, // UART 1 serial out.
++ GPIO_u1sout_m = GPIO_pin8_m,
++ GPIO_u1sout_cfg_v = GPIO_output_v,
++ GPIO_u1sinp_b = GPIO_pin9_b, // UART 1 serial in.
++ GPIO_u1sinp_m = GPIO_pin9_m,
++ GPIO_u1sinp_cfg_v = GPIO_input_v,
++ GPIO_u1dtrn_b = GPIO_pin10_b, // UART 1 data term rdy.
++ GPIO_u1dtrn_m = GPIO_pin10_m,
++ GPIO_u1dtrn_cfg_v = GPIO_output_v,
++ GPIO_u1dsrn_b = GPIO_pin11_b, // UART 1 data set rdy.
++ GPIO_u1dsrn_m = GPIO_pin11_m,
++ GPIO_u1dsrn_cfg_v = GPIO_input_v,
++ GPIO_u1rtsn_b = GPIO_pin12_b, // UART 1 req. to send.
++ GPIO_u1rtsn_m = GPIO_pin12_m,
++ GPIO_u1rtsn_cfg_v = GPIO_output_v,
++ GPIO_u1ctsn_b = GPIO_pin13_b, // UART 1 clear to send.
++ GPIO_u1ctsn_m = GPIO_pin13_m,
++ GPIO_u1ctsn_cfg_v = GPIO_input_v,
++
++ GPIO_dmareqn0_b = GPIO_pin14_b, // Ext. DMA 0 request
++ GPIO_dmareqn0_m = GPIO_pin14_m,
++ GPIO_dmareqn0_cfg_v = GPIO_input_v,
++
++ GPIO_dmareqn1_b = GPIO_pin15_b, // Ext. DMA 1 request
++ GPIO_dmareqn1_m = GPIO_pin15_m,
++ GPIO_dmareqn1_cfg_v = GPIO_input_v,
++
++ GPIO_dmadonen0_b = GPIO_pin16_b, // Ext. DMA 0 done
++ GPIO_dmadonen0_m = GPIO_pin16_m,
++ GPIO_dmadonen0_cfg_v = GPIO_input_v,
++
++ GPIO_dmadonen1_b = GPIO_pin17_b, // Ext. DMA 1 done
++ GPIO_dmadonen1_m = GPIO_pin17_m,
++ GPIO_dmadonen1_cfg_v = GPIO_input_v,
++
++ GPIO_dmafinn0_b = GPIO_pin18_b, // Ext. DMA 0 finished
++ GPIO_dmafinn0_m = GPIO_pin18_m,
++ GPIO_dmafinn0_cfg_v = GPIO_output_v,
++
++ GPIO_dmafinn1_b = GPIO_pin19_b, // Ext. DMA 1 finished
++ GPIO_dmafinn1_m = GPIO_pin19_m,
++ GPIO_dmafinn1_cfg_v = GPIO_output_v,
++
++ GPIO_maddr22_b = GPIO_pin20_b, // M&P bus bit 22.
++ GPIO_maddr22_m = GPIO_pin20_m,
++ GPIO_maddr22_cfg_v = GPIO_output_v,
++
++ GPIO_maddr23_b = GPIO_pin21_b, // M&P bus bit 23.
++ GPIO_maddr23_m = GPIO_pin21_m,
++ GPIO_maddr23_cfg_v = GPIO_output_v,
++
++ GPIO_maddr24_b = GPIO_pin22_b, // M&P bus bit 24.
++ GPIO_maddr24_m = GPIO_pin22_m,
++ GPIO_maddr24_cfg_v = GPIO_output_v,
++
++ GPIO_maddr25_b = GPIO_pin23_b, // M&P bus bit 25.
++ GPIO_maddr25_m = GPIO_pin23_m,
++ GPIO_maddr25_cfg_v = GPIO_output_v,
++
++ GPIO_afspare6_b = GPIO_pin24_b, // reserved.
++ GPIO_afspare6_m = GPIO_pin24_m,
++ GPIO_afspare6_cfg_v = GPIO_input_v,
++ GPIO_afspare5_b = GPIO_pin25_b, // reserved.
++ GPIO_afspare5_m = GPIO_pin25_m,
++ GPIO_afspare5_cfg_v = GPIO_input_v,
++ GPIO_afspare4_b = GPIO_pin26_b, // reserved.
++ GPIO_afspare4_m = GPIO_pin26_m,
++ GPIO_afspare4_cfg_v = GPIO_input_v,
++ GPIO_afspare3_b = GPIO_pin27_b, // reserved.
++ GPIO_afspare3_m = GPIO_pin27_m,
++ GPIO_afspare3_cfg_v = GPIO_input_v,
++ GPIO_afspare2_b = GPIO_pin28_b, // reserved.
++ GPIO_afspare2_m = GPIO_pin28_m,
++ GPIO_afspare2_cfg_v = GPIO_input_v,
++ GPIO_afspare1_b = GPIO_pin29_b, // reserved.
++ GPIO_afspare1_m = GPIO_pin29_m,
++ GPIO_afspare1_cfg_v = GPIO_input_v,
++
++ GPIO_pcimuintn_b = GPIO_pin30_b, // PCI messaging int.
++ GPIO_pcimuintn_m = GPIO_pin30_m,
++ GPIO_pcimuintn_cfg_v = GPIO_output_v,
++
++ GPIO_rngclk_b = GPIO_pin31_b, // RNG external clock
++ GPIO_rngclk_m = GPIO_pin31_m,
++ GPIO_rncclk_cfg_v = GPIO_input_v,
++} GPIO_DEFS_t;
++
++#endif //__IDT_RC32438_GPIO_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,152 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Definitions for IDT RC32438 CPU.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_RC32438_H__
++#define __IDT_RC32438_H__
++#include <linux/config.h>
++#include <linux/delay.h>
++#include <asm/io.h>
++#include <asm/idt-boards/rc32438/rc32438_timer.h>
++
++#define RC32438_REG_BASE 0x18000000
++
++#define interrupt ((volatile INT_t ) INT0_VirtualAddress)
++#define idttimer ((volatile TIM_t) TIM0_VirtualAddress)
++#define idt_gpio ((volatile GPIO_t) GPIO0_VirtualAddress)
++
++#define IDT_CLOCK_MULT 2
++#define MIPS_CPU_TIMER_IRQ 7
++/* Interrupt Controller */
++#define IC_GROUP0_PEND (RC32438_REG_BASE + 0x38000)
++#define IC_GROUP0_MASK (RC32438_REG_BASE + 0x38008)
++#define IC_GROUP_OFFSET 0x0C
++#define RTC_BASE 0xAC0801FF0
++
++#define NUM_INTR_GROUPS 5
++/* 16550 UARTs */
++
++#define GROUP0_IRQ_BASE 8 /* GRP2 IRQ numbers start here */
++#define GROUP1_IRQ_BASE (GROUP0_IRQ_BASE + 32) /* GRP3 IRQ numbers start here */
++#define GROUP2_IRQ_BASE (GROUP1_IRQ_BASE + 32) /* GRP4 IRQ numbers start here */
++#define GROUP3_IRQ_BASE (GROUP2_IRQ_BASE + 32) /* GRP5 IRQ numbers start here */
++#define GROUP4_IRQ_BASE (GROUP3_IRQ_BASE + 32)
++
++#ifdef __MIPSEB__
++#define RC32438_UART0_BASE (RC32438_REG_BASE + 0x50003)
++#define RC32438_UART1_BASE (RC32438_REG_BASE + 0x50023)
++#else
++#define RC32438_UART0_BASE (RC32438_REG_BASE + 0x50000)
++#define RC32438_UART1_BASE (RC32438_REG_BASE + 0x50020)
++#endif
++
++#define RC32438_UART0_IRQ GROUP3_IRQ_BASE + 0
++#define RC32438_UART1_IRQ GROUP3_IRQ_BASE + 3
++
++#define RC32438_NR_IRQS (GROUP4_IRQ_BASE + 32)
++
++
++
++/* cpu pipeline flush */
++static inline void rc32438_sync(void)
++{
++ __asm__ volatile ("sync");
++}
++
++static inline void rc32438_sync_udelay(int us)
++{
++ __asm__ volatile ("sync");
++ udelay(us);
++}
++
++static inline void rc32438_sync_delay(int ms)
++{
++ __asm__ volatile ("sync");
++ mdelay(ms);
++}
++
++/*
++ * Macros to access internal RC32438 registers. No byte
++ * swapping should be done when accessing the internal
++ * registers.
++ */
++
++#define rc32438_readb __raw_readb
++#define rc32438_readw __raw_readw
++#define rc32438_readl __raw_readl
++
++#define rc32438_writeb __raw_writeb
++#define rc32438_writew __raw_writew
++#define rc32438_writel __raw_writel
++
++/*
++ * C access to CLZ and CLO instructions
++ * (count leading zeroes/ones).
++ */
++static inline int rc32438_clz(unsigned long val)
++{
++ int ret;
++ __asm__ volatile (
++ ".set\tnoreorder\n\t"
++ ".set\tnoat\n\t"
++ ".set\tmips32\n\t"
++ "clz\t%0,%1\n\t"
++ ".set\tmips0\n\t"
++ ".set\tat\n\t"
++ ".set\treorder"
++ : "=r" (ret)
++ : "r" (val));
++
++ return ret;
++}
++static inline int rc32438_clo(unsigned long val)
++{
++ int ret;
++ __asm__ volatile (
++ ".set\tnoreorder\n\t"
++ ".set\tnoat\n\t"
++ ".set\tmips32\n\t"
++ "clo\t%0,%1\n\t"
++ ".set\tmips0\n\t"
++ ".set\tat\n\t"
++ ".set\treorder"
++ : "=r" (ret)
++ : "r" (val));
++
++ return ret;
++}
++#endif //__IDT_RC32438_H__
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438_pci.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438_pci.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438_pci.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438_pci.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,510 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Definitions for IDT RC32438 PCI.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++enum
++{
++ PCI0_PhysicalAddress = 0x18080000,
++ PCI_PhysicalAddress = PCI0_PhysicalAddress,
++
++ PCI0_VirtualAddress = 0xb8080000,
++ PCI_VirtualAddress = PCI0_VirtualAddress,
++} ;
++
++enum
++{
++ PCI_LbaCount = 4, // Local base addresses.
++} ;
++
++typedef struct
++{
++ u32 a ; // Address.
++ u32 c ; // Control.
++ u32 m ; // mapping.
++} PCI_Map_s ;
++
++typedef struct
++{
++ u32 pcic ;
++ u32 pcis ;
++ u32 pcism ;
++ u32 pcicfga ;
++ u32 pcicfgd ;
++ PCI_Map_s pcilba [PCI_LbaCount] ;
++ u32 pcidac ;
++ u32 pcidas ;
++ u32 pcidasm ;
++ u32 pcidad ;
++ u32 pcidma8c ;
++ u32 pcidma9c ;
++ u32 pcitc ;
++} volatile *PCI_t ;
++
++// PCI messaging unit.
++enum
++{
++ PCIM_Count = 2,
++} ;
++typedef struct
++{
++ u32 pciim [PCIM_Count] ;
++ u32 pciom [PCIM_Count] ;
++ u32 pciid ;
++ u32 pciiic ;
++ u32 pciiim ;
++ u32 pciiod ;
++ u32 pciioic ;
++ u32 pciioim ;
++} volatile *PCIM_t ;
++
++/*******************************************************************************
++ *
++ * PCI Control Register
++ *
++ ******************************************************************************/
++enum
++{
++ PCIC_en_b = 0,
++ PCIC_en_m = 0x00000001,
++ PCIC_tnr_b = 1,
++ PCIC_tnr_m = 0x00000002,
++ PCIC_sce_b = 2,
++ PCIC_sce_m = 0x00000004,
++ PCIC_ien_b = 3,
++ PCIC_ien_m = 0x00000008,
++ PCIC_aaa_b = 4,
++ PCIC_aaa_m = 0x00000010,
++ PCIC_eap_b = 5,
++ PCIC_eap_m = 0x00000020,
++ PCIC_pcim_b = 6,
++ PCIC_pcim_m = 0x000001c0,
++ PCIC_pcim_disabled_v = 0,
++ PCIC_pcim_tnr_v = 1, // Satellite - target not ready
++ PCIC_pcim_suspend_v = 2, // Satellite - suspended CPU.
++ PCIC_pcim_extern_v = 3, // Host - external arbiter.
++ PCIC_pcim_fixed_v = 4, // Host - fixed priority arb.
++ PCIC_pcim_roundrobin_v = 5, // Host - round robin priority.
++ PCIC_pcim_reserved6_v = 6,
++ PCIC_pcim_reserved7_v = 7,
++ PCIC_igm_b = 9,
++ PCIC_igm_m = 0x00000200,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Status Register
++ *
++ ******************************************************************************/
++enum {
++ PCIS_eed_b = 0,
++ PCIS_eed_m = 0x00000001,
++ PCIS_wr_b = 1,
++ PCIS_wr_m = 0x00000002,
++ PCIS_nmi_b = 2,
++ PCIS_nmi_m = 0x00000004,
++ PCIS_ii_b = 3,
++ PCIS_ii_m = 0x00000008,
++ PCIS_cwe_b = 4,
++ PCIS_cwe_m = 0x00000010,
++ PCIS_cre_b = 5,
++ PCIS_cre_m = 0x00000020,
++ PCIS_mdpe_b = 6,
++ PCIS_mdpe_m = 0x00000040,
++ PCIS_sta_b = 7,
++ PCIS_sta_m = 0x00000080,
++ PCIS_rta_b = 8,
++ PCIS_rta_m = 0x00000100,
++ PCIS_rma_b = 9,
++ PCIS_rma_m = 0x00000200,
++ PCIS_sse_b = 10,
++ PCIS_sse_m = 0x00000400,
++ PCIS_ose_b = 11,
++ PCIS_ose_m = 0x00000800,
++ PCIS_pe_b = 12,
++ PCIS_pe_m = 0x00001000,
++ PCIS_tae_b = 13,
++ PCIS_tae_m = 0x00002000,
++ PCIS_rle_b = 14,
++ PCIS_rle_m = 0x00004000,
++ PCIS_bme_b = 15,
++ PCIS_bme_m = 0x00008000,
++ PCIS_prd_b = 16,
++ PCIS_prd_m = 0x00010000,
++ PCIS_rip_b = 17,
++ PCIS_rip_m = 0x00020000,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Status Mask Register
++ *
++ ******************************************************************************/
++enum {
++ PCISM_eed_b = 0,
++ PCISM_eed_m = 0x00000001,
++ PCISM_wr_b = 1,
++ PCISM_wr_m = 0x00000002,
++ PCISM_nmi_b = 2,
++ PCISM_nmi_m = 0x00000004,
++ PCISM_ii_b = 3,
++ PCISM_ii_m = 0x00000008,
++ PCISM_cwe_b = 4,
++ PCISM_cwe_m = 0x00000010,
++ PCISM_cre_b = 5,
++ PCISM_cre_m = 0x00000020,
++ PCISM_mdpe_b = 6,
++ PCISM_mdpe_m = 0x00000040,
++ PCISM_sta_b = 7,
++ PCISM_sta_m = 0x00000080,
++ PCISM_rta_b = 8,
++ PCISM_rta_m = 0x00000100,
++ PCISM_rma_b = 9,
++ PCISM_rma_m = 0x00000200,
++ PCISM_sse_b = 10,
++ PCISM_sse_m = 0x00000400,
++ PCISM_ose_b = 11,
++ PCISM_ose_m = 0x00000800,
++ PCISM_pe_b = 12,
++ PCISM_pe_m = 0x00001000,
++ PCISM_tae_b = 13,
++ PCISM_tae_m = 0x00002000,
++ PCISM_rle_b = 14,
++ PCISM_rle_m = 0x00004000,
++ PCISM_bme_b = 15,
++ PCISM_bme_m = 0x00008000,
++ PCISM_prd_b = 16,
++ PCISM_prd_m = 0x00010000,
++ PCISM_rip_b = 17,
++ PCISM_rip_m = 0x00020000,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Configuration Address Register
++ *
++ ******************************************************************************/
++enum {
++ PCICFGA_reg_b = 2,
++ PCICFGA_reg_m = 0x000000fc,
++ PCICFGA_reg_id_v = 0x00>>2, //use PCFGID_
++ PCICFGA_reg_04_v = 0x04>>2, //use PCFG04_
++ PCICFGA_reg_08_v = 0x08>>2, //use PCFG08_
++ PCICFGA_reg_0C_v = 0x0C>>2, //use PCFG0C_
++ PCICFGA_reg_pba0_v = 0x10>>2, //use PCIPBA_
++ PCICFGA_reg_pba1_v = 0x14>>2, //use PCIPBA_
++ PCICFGA_reg_pba2_v = 0x18>>2, //use PCIPBA_
++ PCICFGA_reg_pba3_v = 0x1c>>2, //use PCIPBA_
++ PCICFGA_reg_subsystem_v = 0x2c>>2, //use PCFGSS_
++ PCICFGA_reg_3C_v = 0x3C>>2, //use PCFG3C_
++ PCICFGA_reg_pba0c_v = 0x44>>2, //use PCIPBAC_
++ PCICFGA_reg_pba0m_v = 0x48>>2,
++ PCICFGA_reg_pba1c_v = 0x4c>>2, //use PCIPBAC_
++ PCICFGA_reg_pba1m_v = 0x50>>2,
++ PCICFGA_reg_pba2c_v = 0x54>>2, //use PCIPBAC_
++ PCICFGA_reg_pba2m_v = 0x58>>2,
++ PCICFGA_reg_pba3c_v = 0x5c>>2, //use PCIPBAC_
++ PCICFGA_reg_pba3m_v = 0x60>>2,
++ PCICFGA_reg_pmgt_v = 0x64>>2,
++ PCICFGA_func_b = 8,
++ PCICFGA_func_m = 0x00000700,
++ PCICFGA_dev_b = 11,
++ PCICFGA_dev_m = 0x0000f800,
++ PCICFGA_dev_internal_v = 0,
++ PCICFGA_bus_b = 16,
++ PCICFGA_bus_m = 0x00ff0000,
++ PCICFGA_bus_type0_v = 0, //local bus
++ PCICFGA_en_b = 31, // read only
++ PCICFGA_en_m = 0x80000000,
++} ;
++
++enum {
++ PCFGID_vendor_b = 0,
++ PCFGID_vendor_m = 0x0000ffff,
++ PCFGID_vendor_IDT_v = 0x111d,
++ PCFGID_device_b = 16,
++ PCFGID_device_m = 0xffff0000,
++ PCFGID_device_Acaciade_v = 0x0207,
++
++ PCFG04_command_ioena_b = 1,
++ PCFG04_command_ioena_m = 0x00000001,
++ PCFG04_command_memena_b = 2,
++ PCFG04_command_memena_m = 0x00000002,
++ PCFG04_command_bmena_b = 3,
++ PCFG04_command_bmena_m = 0x00000004,
++ PCFG04_command_mwinv_b = 5,
++ PCFG04_command_mwinv_m = 0x00000010,
++ PCFG04_command_parena_b = 7,
++ PCFG04_command_parena_m = 0x00000040,
++ PCFG04_command_serrena_b = 9,
++ PCFG04_command_serrena_m = 0x00000100,
++ PCFG04_command_fastbbena_b = 10,
++ PCFG04_command_fastbbena_m = 0x00000200,
++ PCFG04_status_b = 16,
++ PCFG04_status_m = 0xffff0000,
++ PCFG04_status_66MHz_b = 21, // 66 MHz enable
++ PCFG04_status_66MHz_m = 0x00200000,
++ PCFG04_status_fbb_b = 23,
++ PCFG04_status_fbb_m = 0x00800000,
++ PCFG04_status_mdpe_b = 24,
++ PCFG04_status_mdpe_m = 0x01000000,
++ PCFG04_status_dst_b = 25,
++ PCFG04_status_dst_m = 0x06000000,
++ PCFG04_status_sta_b = 27,
++ PCFG04_status_sta_m = 0x08000000,
++ PCFG04_status_rta_b = 28,
++ PCFG04_status_rta_m = 0x10000000,
++ PCFG04_status_rma_b = 29,
++ PCFG04_status_rma_m = 0x20000000,
++ PCFG04_status_sse_b = 30,
++ PCFG04_status_sse_m = 0x40000000,
++ PCFG04_status_pe_b = 31,
++ PCFG04_status_pe_m = 0x40000000,
++
++ PCFG08_revId_b = 0,
++ PCFG08_revId_m = 0x000000ff,
++ PCFG08_classCode_b = 0,
++ PCFG08_classCode_m = 0xffffff00,
++ PCFG08_classCode_bridge_v = 06,
++ PCFG08_classCode_proc_v = 0x0b3000, // processor-MIPS
++ PCFG0C_cacheline_b = 0,
++ PCFG0C_cacheline_m = 0x000000ff,
++ PCFG0C_masterLatency_b = 8,
++ PCFG0C_masterLatency_m = 0x0000ff00,
++ PCFG0C_headerType_b = 16,
++ PCFG0C_headerType_m = 0x00ff0000,
++ PCFG0C_bist_b = 24,
++ PCFG0C_bist_m = 0xff000000,
++
++ PCIPBA_msi_b = 0,
++ PCIPBA_msi_m = 0x00000001,
++ PCIPBA_p_b = 3,
++ PCIPBA_p_m = 0x00000004,
++ PCIPBA_baddr_b = 8,
++ PCIPBA_baddr_m = 0xffffff00,
++
++ PCFGSS_vendorId_b = 0,
++ PCFGSS_vendorId_m = 0x0000ffff,
++ PCFGSS_id_b = 16,
++ PCFGSS_id_m = 0xffff0000,
++
++ PCFG3C_interruptLine_b = 0,
++ PCFG3C_interruptLine_m = 0x000000ff,
++ PCFG3C_interruptPin_b = 8,
++ PCFG3C_interruptPin_m = 0x0000ff00,
++ PCFG3C_minGrant_b = 16,
++ PCFG3C_minGrant_m = 0x00ff0000,
++ PCFG3C_maxLat_b = 24,
++ PCFG3C_maxLat_m = 0xff000000,
++
++ PCIPBAC_msi_b = 0,
++ PCIPBAC_msi_m = 0x00000001,
++ PCIPBAC_p_b = 1,
++ PCIPBAC_p_m = 0x00000002,
++ PCIPBAC_size_b = 2,
++ PCIPBAC_size_m = 0x0000007c,
++ PCIPBAC_sb_b = 7,
++ PCIPBAC_sb_m = 0x00000080,
++ PCIPBAC_pp_b = 8,
++ PCIPBAC_pp_m = 0x00000100,
++ PCIPBAC_mr_b = 9,
++ PCIPBAC_mr_m = 0x00000600,
++ PCIPBAC_mr_read_v =0, //no prefetching
++ PCIPBAC_mr_readLine_v =1,
++ PCIPBAC_mr_readMult_v =2,
++ PCIPBAC_mrl_b = 11,
++ PCIPBAC_mrl_m = 0x00000800,
++ PCIPBAC_mrm_b = 12,
++ PCIPBAC_mrm_m = 0x00001000,
++ PCIPBAC_trp_b = 13,
++ PCIPBAC_trp_m = 0x00002000,
++
++ PCFG40_trdyTimeout_b = 0,
++ PCFG40_trdyTimeout_m = 0x000000ff,
++ PCFG40_retryLim_b = 8,
++ PCFG40_retryLim_m = 0x0000ff00,
++};
++
++/*******************************************************************************
++ *
++ * PCI Local Base Address [0|1|2|3] Register
++ *
++ ******************************************************************************/
++enum {
++ PCILBA_baddr_b = 0, // In PCI_t -> pcilba [] .a
++ PCILBA_baddr_m = 0xffffff00,
++} ;
++/*******************************************************************************
++ *
++ * PCI Local Base Address Control Register
++ *
++ ******************************************************************************/
++enum {
++ PCILBAC_msi_b = 0, // In pPci->pcilba[i].c
++ PCILBAC_msi_m = 0x00000001,
++ PCILBAC_msi_mem_v = 0,
++ PCILBAC_msi_io_v = 1,
++ PCILBAC_size_b = 2, // In pPci->pcilba[i].c
++ PCILBAC_size_m = 0x0000007c,
++ PCILBAC_sb_b = 7, // In pPci->pcilba[i].c
++ PCILBAC_sb_m = 0x00000080,
++ PCILBAC_rt_b = 8, // In pPci->pcilba[i].c
++ PCILBAC_rt_m = 0x00000100,
++ PCILBAC_rt_noprefetch_v = 0, // mem read
++ PCILBAC_rt_prefetch_v = 1, // mem readline
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Local Base Address [0|1|2|3] Mapping Register
++ *
++ ******************************************************************************/
++enum {
++ PCILBAM_maddr_b = 8,
++ PCILBAM_maddr_m = 0xffffff00,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Decoupled Access Control Register
++ *
++ ******************************************************************************/
++enum {
++ PCIDAC_den_b = 0,
++ PCIDAC_den_m = 0x00000001,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Decoupled Access Status Register
++ *
++ ******************************************************************************/
++enum {
++ PCIDAS_d_b = 0,
++ PCIDAS_d_m = 0x00000001,
++ PCIDAS_b_b = 1,
++ PCIDAS_b_m = 0x00000002,
++ PCIDAS_e_b = 2,
++ PCIDAS_e_m = 0x00000004,
++ PCIDAS_ofe_b = 3,
++ PCIDAS_ofe_m = 0x00000008,
++ PCIDAS_off_b = 4,
++ PCIDAS_off_m = 0x00000010,
++ PCIDAS_ife_b = 5,
++ PCIDAS_ife_m = 0x00000020,
++ PCIDAS_iff_b = 6,
++ PCIDAS_iff_m = 0x00000040,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI DMA Channel 8 Configuration Register
++ *
++ ******************************************************************************/
++enum
++{
++ PCIDMA8C_mbs_b = 0, // Maximum Burst Size.
++ PCIDMA8C_mbs_m = 0x00000fff, // { pcidma8c }
++ PCIDMA8C_our_b = 12, // Optimize Unaligned Burst Reads.
++ PCIDMA8C_our_m = 0x00001000, // { pcidma8c }
++} ;
++
++/*******************************************************************************
++ *
++ * PCI DMA Channel 9 Configuration Register
++ *
++ ******************************************************************************/
++enum
++{
++ PCIDMA9C_mbs_b = 0, // Maximum Burst Size.
++ PCIDMA9C_mbs_m = 0x00000fff, // { pcidma9c }
++} ;
++
++/*******************************************************************************
++ *
++ * PCI to Memory(DMA Channel 8) AND Memory to PCI DMA(DMA Channel 9)Descriptors
++ *
++ ******************************************************************************/
++enum {
++ PCIDMAD_pt_b = 22, // in DEVCMD field (descriptor)
++ PCIDMAD_pt_m = 0x00c00000, // preferred transaction field
++ // These are for reads (DMA channel 8)
++ PCIDMAD_devcmd_mr_v = 0, //memory read
++ PCIDMAD_devcmd_mrl_v = 1, //memory read line
++ PCIDMAD_devcmd_mrm_v = 2, //memory read multiple
++ PCIDMAD_devcmd_ior_v = 3, //I/O read
++ // These are for writes (DMA channel 9)
++ PCIDMAD_devcmd_mw_v = 0, //memory write
++ PCIDMAD_devcmd_mwi_v = 1, //memory write invalidate
++ PCIDMAD_devcmd_iow_v = 3, //I/O write
++
++ // Swap byte field applies to both DMA channel 8 and 9
++ PCIDMAD_sb_b = 24, // in DEVCMD field (descriptor)
++ PCIDMAD_sb_m = 0x01000000, // swap byte field
++} ;
++
++
++/*******************************************************************************
++ *
++ * PCI Target Control Register
++ *
++ ******************************************************************************/
++enum
++{
++ PCITC_rtimer_b = 0, // In PCITC_t -> pcitc
++ PCITC_rtimer_m = 0x000000ff,
++ PCITC_dtimer_b = 8, // In PCITC_t -> pcitc
++ PCITC_dtimer_m = 0x0000ff00,
++ PCITC_rdr_b = 18, // In PCITC_t -> pcitc
++ PCITC_rdr_m = 0x00040000,
++ PCITC_ddt_b = 19, // In PCITC_t -> pcitc
++ PCITC_ddt_m = 0x00080000,
++} ;
++/*******************************************************************************
++ *
++ * PCI messaging unit [applies to both inbound and outbound registers ]
++ *
++ ******************************************************************************/
++enum
++{
++ PCIM_m0_b = 0, // In PCIM_t -> {pci{iic,iim,ioic,ioim}}
++ PCIM_m0_m = 0x00000001, // inbound or outbound message 0
++ PCIM_m1_b = 1, // In PCIM_t -> {pci{iic,iim,ioic,ioim}}
++ PCIM_m1_m = 0x00000002, // inbound or outbound message 1
++ PCIM_db_b = 2, // In PCIM_t -> {pci{iic,iim,ioic,ioim}}
++ PCIM_db_m = 0x00000004, // inbound or outbound doorbell
++};
++
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438_pci_v.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438_pci_v.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438_pci_v.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438_pci_v.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,190 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Definitions for IDT RC32438 PCI setup.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#define PCI_MSG_VirtualAddress 0xB8088010
++#define rc32438_pci ((volatile PCI_t) PCI0_VirtualAddress)
++#define rc32438_pci_msg ((volatile PCIM_t) PCI_MSG_VirtualAddress)
++
++#define PCIM_SHFT 0x6
++#define PCIM_BIT_LEN 0x7
++#define PCIM_H_EA 0x3
++#define PCIM_H_IA_FIX 0x4
++#define PCIM_H_IA_RR 0x5
++
++#define PCI_ADDR_START 0x50000000
++
++#define CPUTOPCI_MEM_WIN 0x02000000
++#define CPUTOPCI_IO_WIN 0x00100000
++#define PCILBA_SIZE_SHFT 2
++#define PCILBA_SIZE_MASK 0x1F
++#define SIZE_256MB 0x1C
++#define SIZE_128MB 0x1B
++#define SIZE_64MB 0x1A
++#define SIZE_32MB 0x19
++#define SIZE_16MB 0x18
++#define SIZE_4MB 0x16
++#define SIZE_2MB 0x15
++#define SIZE_1MB 0x14
++#define ACACIA_CONFIG0_ADDR 0x80000000
++#define ACACIA_CONFIG1_ADDR 0x80000004
++#define ACACIA_CONFIG2_ADDR 0x80000008
++#define ACACIA_CONFIG3_ADDR 0x8000000C
++#define ACACIA_CONFIG4_ADDR 0x80000010
++#define ACACIA_CONFIG5_ADDR 0x80000014
++#define ACACIA_CONFIG6_ADDR 0x80000018
++#define ACACIA_CONFIG7_ADDR 0x8000001C
++#define ACACIA_CONFIG8_ADDR 0x80000020
++#define ACACIA_CONFIG9_ADDR 0x80000024
++#define ACACIA_CONFIG10_ADDR 0x80000028
++#define ACACIA_CONFIG11_ADDR 0x8000002C
++#define ACACIA_CONFIG12_ADDR 0x80000030
++#define ACACIA_CONFIG13_ADDR 0x80000034
++#define ACACIA_CONFIG14_ADDR 0x80000038
++#define ACACIA_CONFIG15_ADDR 0x8000003C
++#define ACACIA_CONFIG16_ADDR 0x80000040
++#define ACACIA_CONFIG17_ADDR 0x80000044
++#define ACACIA_CONFIG18_ADDR 0x80000048
++#define ACACIA_CONFIG19_ADDR 0x8000004C
++#define ACACIA_CONFIG20_ADDR 0x80000050
++#define ACACIA_CONFIG21_ADDR 0x80000054
++#define ACACIA_CONFIG22_ADDR 0x80000058
++#define ACACIA_CONFIG23_ADDR 0x8000005C
++#define ACACIA_CONFIG24_ADDR 0x80000060
++#define ACACIA_CONFIG25_ADDR 0x80000064
++#define ACACIA_CMD (PCFG04_command_ioena_m | \
++ PCFG04_command_memena_m | \
++ PCFG04_command_bmena_m | \
++ PCFG04_command_mwinv_m | \
++ PCFG04_command_parena_m | \
++ PCFG04_command_serrena_m )
++
++#define ACACIA_STAT (PCFG04_status_mdpe_m | \
++ PCFG04_status_sta_m | \
++ PCFG04_status_rta_m | \
++ PCFG04_status_rma_m | \
++ PCFG04_status_sse_m | \
++ PCFG04_status_pe_m)
++
++#define ACACIA_CNFG1 ((ACACIA_STAT<<16)|ACACIA_CMD)
++
++#define ACACIA_REVID 0
++#define ACACIA_CLASS_CODE 0
++#define ACACIA_CNFG2 ((ACACIA_CLASS_CODE<<8) | \
++ ACACIA_REVID)
++
++#define ACACIA_CACHE_LINE_SIZE 4
++#define ACACIA_MASTER_LAT 0x3c
++#define ACACIA_HEADER_TYPE 0
++#define ACACIA_BIST 0
++
++#define ACACIA_CNFG3 ((ACACIA_BIST << 24) | \
++ (ACACIA_HEADER_TYPE<<16) | \
++ (ACACIA_MASTER_LAT<<8) | \
++ ACACIA_CACHE_LINE_SIZE )
++
++#define ACACIA_BAR0 0x00000008 /* 128 MB Memory */
++#define ACACIA_BAR1 0x18800001 /* 1 MB IO */
++#define ACACIA_BAR2 0x18000001 /* 2 MB IO window for Acacia
++ internal Registers */
++#define ACACIA_BAR3 0x48000008 /* Spare 128 MB Memory */
++
++#define ACACIA_CNFG4 ACACIA_BAR0
++#define ACACIA_CNFG5 ACACIA_BAR1
++#define ACACIA_CNFG6 ACACIA_BAR2
++#define ACACIA_CNFG7 ACACIA_BAR3
++
++#define ACACIA_SUBSYS_VENDOR_ID 0
++#define ACACIA_SUBSYSTEM_ID 0
++#define ACACIA_CNFG8 0
++#define ACACIA_CNFG9 0
++#define ACACIA_CNFG10 0
++#define ACACIA_CNFG11 ((ACACIA_SUBSYS_VENDOR_ID<<16) | \
++ ACACIA_SUBSYSTEM_ID)
++#define ACACIA_INT_LINE 1
++#define ACACIA_INT_PIN 1
++#define ACACIA_MIN_GNT 8
++#define ACACIA_MAX_LAT 0x38
++#define ACACIA_CNFG12 0
++#define ACACIA_CNFG13 0
++#define ACACIA_CNFG14 0
++#define ACACIA_CNFG15 ((ACACIA_MAX_LAT<<24) | \
++ (ACACIA_MIN_GNT<<16) | \
++ (ACACIA_INT_PIN<<8) | \
++ ACACIA_INT_LINE)
++#define ACACIA_RETRY_LIMIT 0x80
++#define ACACIA_TRDY_LIMIT 0x80
++#define ACACIA_CNFG16 ((ACACIA_RETRY_LIMIT<<8) | \
++ ACACIA_TRDY_LIMIT)
++#define PCI_PBAxC_R 0x0
++#define PCI_PBAxC_RL 0x1
++#define PCI_PBAxC_RM 0x2
++#define SIZE_SHFT 2
++
++#define ACACIA_PBA0C ( PCIPBAC_mrl_m | PCIPBAC_sb_m | \
++ ((PCI_PBAxC_RM &0x3) << PCIPBAC_mr_b) | \
++ PCIPBAC_pp_m | \
++ (SIZE_128MB<<SIZE_SHFT) | \
++ PCIPBAC_p_m)
++
++#define ACACIA_CNFG17 ACACIA_PBA0C
++#define ACACIA_PBA0M 0x0
++#define ACACIA_CNFG18 ACACIA_PBA0M
++
++#define ACACIA_PBA1C ((SIZE_1MB<<SIZE_SHFT) | PCIPBAC_sb_m | \
++ PCIPBAC_msi_m)
++
++#define ACACIA_CNFG19 ACACIA_PBA1C
++#define ACACIA_PBA1M 0x0
++#define ACACIA_CNFG20 ACACIA_PBA1M
++
++#define ACACIA_PBA2C ((SIZE_2MB<<SIZE_SHFT) | PCIPBAC_sb_m | \
++ PCIPBAC_msi_m)
++
++#define ACACIA_CNFG21 ACACIA_PBA2C
++#define ACACIA_PBA2M 0x18000000
++#define ACACIA_CNFG22 ACACIA_PBA2M
++#define ACACIA_PBA3C 0
++#define ACACIA_CNFG23 ACACIA_PBA3C
++#define ACACIA_PBA3M 0
++#define ACACIA_CNFG24 ACACIA_PBA3M
++
++
++
++#define PCITC_DTIMER_VAL 8
++#define PCITC_RTIMER_VAL 0x10
++
+diff -Nur linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438_timer.h linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438_timer.h
+--- linux-2.6.17/include/asm-mips/idt-boards/rc32438/rc32438_timer.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/asm-mips/idt-boards/rc32438/rc32438_timer.h 2006-06-18 12:44:28.000000000 +0200
+@@ -0,0 +1,91 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Timer register definition IDT RC32438 CPU.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 P. Sadik.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_RC32438_TIM_H__
++#define __IDT_RC32438_TIM_H__
++
++enum
++{
++ TIM0_PhysicalAddress = 0x18028000,
++ TIM_PhysicalAddress = TIM0_PhysicalAddress, // Default
++
++ TIM0_VirtualAddress = 0xb8028000,
++ TIM_VirtualAddress = TIM0_VirtualAddress, // Default
++} ;
++
++enum
++{
++ TIM_Count = 3,
++} ;
++
++struct TIM_CNTR_s
++{
++ u32 count ;
++ u32 compare ;
++ u32 ctc ; //use CTC_
++} ;
++
++typedef struct TIM_s
++{
++ struct TIM_CNTR_s tim [TIM_Count] ;
++ u32 rcount ; //use RCOUNT_
++ u32 rcompare ; //use RCOMPARE_
++ u32 rtc ; //use RTC_
++} volatile * TIM_t ;
++
++enum
++{
++ CTC_en_b = 0,
++ CTC_en_m = 0x00000001,
++ CTC_to_b = 1,
++ CTC_to_m = 0x00000002,
++
++ RCOUNT_count_b = 0,
++ RCOUNT_count_m = 0x0000ffff,
++ RCOMPARE_compare_b = 0,
++ RCOMPARE_compare_m = 0x0000ffff,
++ RTC_ce_b = 0,
++ RTC_ce_m = 0x00000001,
++ RTC_to_b = 1,
++ RTC_to_m = 0x00000002,
++ RTC_rqe_b = 2,
++ RTC_rqe_m = 0x00000004,
++
++} ;
++#endif //__IDT_RC32438_TIM_H__
++
+diff -Nur linux-2.6.17/include/asm-mips/mach-generic/irq.h linux-2.6.17-owrt/include/asm-mips/mach-generic/irq.h
+--- linux-2.6.17/include/asm-mips/mach-generic/irq.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/asm-mips/mach-generic/irq.h 2006-06-18 12:44:28.000000000 +0200
+@@ -8,6 +8,6 @@
+ #ifndef __ASM_MACH_GENERIC_IRQ_H
+ #define __ASM_MACH_GENERIC_IRQ_H
+
+-#define NR_IRQS 128
++#define NR_IRQS 256
+
+ #endif /* __ASM_MACH_GENERIC_IRQ_H */
+diff -Nur linux-2.6.17/include/linux/kernel.h linux-2.6.17-owrt/include/linux/kernel.h
+--- linux-2.6.17/include/linux/kernel.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/linux/kernel.h 2006-06-18 12:44:28.000000000 +0200
+@@ -329,6 +329,7 @@
+ };
+
+ /* Force a compilation error if condition is true */
++extern void BUILD_BUG(void);
+ #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+
+ /* Trap pasters of __FUNCTION__ at compile-time */
diff --git a/target/linux/aruba-2.6/patches/001-flash.patch b/target/linux/aruba-2.6/patches/001-flash.patch
new file mode 100644
index 0000000000..f0b951370d
--- /dev/null
+++ b/target/linux/aruba-2.6/patches/001-flash.patch
@@ -0,0 +1,159 @@
+diff -Nur linux-2.6.15/arch/mips/aruba/flash_lock.c linux-2.6.15-openwrt/arch/mips/aruba/flash_lock.c
+--- linux-2.6.15/arch/mips/aruba/flash_lock.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-openwrt/arch/mips/aruba/flash_lock.c 2006-01-10 00:32:32.000000000 +0100
+@@ -0,0 +1,27 @@
++#include <linux/module.h>
++#include <linux/types.h>
++#include <asm/bootinfo.h>
++
++#define AP70_PROT_ADDR 0xb8010008
++#define AP70_PROT_DATA 0x8
++#define AP60_PROT_ADDR 0xB8400000
++#define AP60_PROT_DATA 0x04000000
++
++void unlock_ap60_70_flash(void)
++{
++ volatile __u32 val;
++ switch (mips_machtype) {
++ case MACH_ARUBA_AP70:
++ val = *(volatile __u32 *)AP70_PROT_ADDR;
++ val &= ~(AP70_PROT_DATA);
++ *(volatile __u32 *)AP70_PROT_ADDR = val;
++ break;
++ case MACH_ARUBA_AP65:
++ case MACH_ARUBA_AP60:
++ default:
++ val = *(volatile __u32 *)AP60_PROT_ADDR;
++ val &= ~(AP60_PROT_DATA);
++ *(volatile __u32 *)AP60_PROT_ADDR = val;
++ break;
++ }
++}
+diff -Nur linux-2.6.15/drivers/mtd/chips/cfi_probe.c linux-2.6.15-openwrt/drivers/mtd/chips/cfi_probe.c
+--- linux-2.6.15/drivers/mtd/chips/cfi_probe.c 2006-01-03 04:21:10.000000000 +0100
++++ linux-2.6.15-openwrt/drivers/mtd/chips/cfi_probe.c 2006-01-10 00:32:32.000000000 +0100
+@@ -26,6 +26,74 @@
+ static void print_cfi_ident(struct cfi_ident *);
+ #endif
+
++#if 1
++
++#define AMD_AUTOSEL_OFF1 0xAAA
++#define AMD_AUTOSEL_OFF2 0x555
++#define AMD_MANUF_ID 0x1
++#define AMD_DEVICE_ID1 0xF6 /* T */
++#define AMD_DEVICE_ID2 0xF9 /* B */
++/* Foll. are definitions for Macronix Flash Part */
++#define MCX_MANUF_ID 0xC2
++#define MCX_DEVICE_ID1 0xA7
++#define MCX_DEVICE_ID2 0xA8
++/* Foll. common to both AMD and Macronix */
++#define FACTORY_LOCKED 0x99
++#define USER_LOCKED 0x19
++
++/* NOTE: AP-70/6x use BYTE mode flash access. Therefore the
++ * lowest Addr. pin in the flash is not A0 but A-1 (A minus 1).
++ * CPU's A0 is tied to Flash's A-1, A1 to A0 and so on. This
++ * gives 4MB of byte-addressable mem. In byte mode, all addr
++ * need to be multiplied by 2 (i.e compared to word mode).
++ * NOTE: AMD_AUTOSEL_OFF1 and OFF2 are already mult. by 2
++ * Just blindly use the addr offsets suggested in the manual
++ * for byte mode and you'll be OK. Offs. in Table 6 need to
++ * be mult by 2 (for getting autosel params)
++ */
++void
++flash_detect(struct map_info *map, __u32 base, struct cfi_private *cfi)
++{
++ map_word val[3];
++ int osf = cfi->interleave * cfi->device_type; // =2 for AP70/6x
++ char *manuf, *part, *lock ;
++
++ if (osf != 1) return ;
++
++ cfi_send_gen_cmd(0xAA, AMD_AUTOSEL_OFF1, base, map, cfi, cfi->device_type, NULL);
++ cfi_send_gen_cmd(0x55, AMD_AUTOSEL_OFF2, base, map, cfi, cfi->device_type, NULL);
++ cfi_send_gen_cmd(0x90, AMD_AUTOSEL_OFF1, base, map, cfi, cfi->device_type, NULL);
++ val[0] = map_read(map, base) ; // manuf ID
++ val[1] = map_read(map, base+2) ; // device ID
++ val[2] = map_read(map, base+6) ; // lock indicator
++#if 0
++printk("v1=0x%x v2=0x%x v3=0x%x\n", val[0], val[1], val[2]) ;
++#endif
++ if (val[0].x[0] == AMD_MANUF_ID) {
++ manuf = "AMD Flash" ;
++ if (val[1].x[0] == AMD_DEVICE_ID1)
++ part = "AM29LV320D (Top)" ;
++ else if (val[1].x[0] == AMD_DEVICE_ID2)
++ part = "AM29LV320D (Bot)" ;
++ else part = "Unknown" ;
++ } else if (val[0].x[0] == MCX_MANUF_ID) {
++ manuf = "Macronix Flash" ;
++ if (val[1].x[0] == MCX_DEVICE_ID1)
++ part = "MX29LV320A (Top)" ;
++ else if (val[1].x[0] == MCX_DEVICE_ID2)
++ part = "MX29LV320A (Bot)" ;
++ else part = "Unknown" ;
++ } else
++ return ;
++ if (val[2].x[0] == FACTORY_LOCKED)
++ lock = "Factory Locked" ;
++ else if (val[2].x[0] == USER_LOCKED)
++ lock = "User Locked" ;
++ else lock = "Unknown locking" ;
++ printk("%s %s (%s)\n", manuf, part, lock) ;
++}
++#endif
++
+ static int cfi_probe_chip(struct map_info *map, __u32 base,
+ unsigned long *chip_map, struct cfi_private *cfi);
+ static int cfi_chip_setup(struct map_info *map, struct cfi_private *cfi);
+@@ -118,6 +186,10 @@
+ }
+
+ xip_disable();
++#if 1
++ //cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
++ flash_detect(map, base, cfi) ;
++#endif
+ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+ cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
+ cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
+diff -Nur linux-2.6.15/drivers/mtd/maps/physmap.c linux-2.6.15-openwrt/drivers/mtd/maps/physmap.c
+--- linux-2.6.15/drivers/mtd/maps/physmap.c 2006-01-03 04:21:10.000000000 +0100
++++ linux-2.6.15-openwrt/drivers/mtd/maps/physmap.c 2006-01-10 00:32:32.000000000 +0100
+@@ -34,15 +34,31 @@
+ static struct mtd_partition *mtd_parts;
+ static int mtd_parts_nb;
+
+-static int num_physmap_partitions;
+-static struct mtd_partition *physmap_partitions;
++static int num_physmap_partitions = 3;
++static struct mtd_partition physmap_partitions[] = {
++ {
++ name: "zImage",
++ size: 0x3f0000-0x80000,
++ offset: 0x80000,
++ },
++ {
++ name: "JFFS2",
++ size: 0x3f0000-0x120000,
++ offset: 0x120000,
++ },
++ {
++ name: "NVRAM",
++ size: 0x2000,
++ offset: 0x3f8000,
++ }
++};
+
+ static const char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL};
+
+ void physmap_set_partitions(struct mtd_partition *parts, int num_parts)
+ {
+- physmap_partitions=parts;
+- num_physmap_partitions=num_parts;
++// physmap_partitions=parts;
++// num_physmap_partitions=num_parts;
+ }
+ #endif /* CONFIG_MTD_PARTITIONS */
+
diff --git a/target/linux/aruba-2.6/patches/002-irq.patch b/target/linux/aruba-2.6/patches/002-irq.patch
new file mode 100644
index 0000000000..f6b9425d8d
--- /dev/null
+++ b/target/linux/aruba-2.6/patches/002-irq.patch
@@ -0,0 +1,286 @@
+diff -Nur linux-2.6.17/arch/mips/aruba/irq.c linux-2.6.17-openwrt/arch/mips/aruba/irq.c
+--- linux-2.6.17/arch/mips/aruba/irq.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-openwrt/arch/mips/aruba/irq.c 2006-10-12 14:32:40.026285000 -0700
+@@ -0,0 +1,282 @@
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/kernel_stat.h>
++#include <linux/module.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/timex.h>
++#include <linux/slab.h>
++#include <linux/random.h>
++#include <linux/delay.h>
++
++#include <asm/bitops.h>
++#include <asm/bootinfo.h>
++#include <asm/io.h>
++#include <asm/mipsregs.h>
++#include <asm/system.h>
++#include <asm/idt-boards/rc32434/rc32434.h>
++#include <asm/idt-boards/rc32434/rc32434_gpio.h>
++
++#include <asm/irq.h>
++
++extern void aruba_timer_interrupt(struct pt_regs *regs);
++
++typedef struct {
++ u32 mask;
++ volatile u32 *base_addr;
++} intr_group_t;
++
++static const intr_group_t intr_group_merlot[NUM_INTR_GROUPS] = {
++ {0x00000000, (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 0)},
++};
++
++#define READ_PEND_MERLOT(base) (*((volatile unsigned long *)(0xbc003010)))
++#define READ_MASK_MERLOT(base) (*((volatile unsigned long *)(0xbc003014)))
++#define WRITE_MASK_MERLOT(base, val) ((*((volatile unsigned long *)(0xbc003014))) = (val), READ_MASK_MERLOT())
++
++static const intr_group_t intr_group_muscat[NUM_INTR_GROUPS] = {
++ {0x0000efff, (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 0 * IC_GROUP_OFFSET)},
++ {0x00001fff, (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 1 * IC_GROUP_OFFSET)},
++ {0x00000007, (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 2 * IC_GROUP_OFFSET)},
++ {0x0003ffff, (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 3 * IC_GROUP_OFFSET)},
++ {0xffffffff, (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 4 * IC_GROUP_OFFSET)}
++};
++
++#define READ_PEND_MUSCAT(base) (*(base))
++#define READ_MASK_MUSCAT(base) (*(base + 2))
++#define WRITE_MASK_MUSCAT(base, val) (*(base + 2) = (val))
++
++static inline int group_to_ip(unsigned int group)
++{
++ switch (mips_machtype) {
++ case MACH_ARUBA_AP70:
++ return group + 2;
++ case MACH_ARUBA_AP65:
++ case MACH_ARUBA_AP60:
++ default:
++ return 6;
++ }
++}
++
++static inline void enable_local_irq(unsigned int irq)
++{
++ clear_c0_cause(0x100 << irq);
++ set_c0_status(0x100 << irq);
++ irq_enable_hazard();
++}
++
++static inline void disable_local_irq(unsigned int irq)
++{
++ clear_c0_status(0x100 << irq);
++ clear_c0_cause(0x100 << irq);
++ irq_disable_hazard();
++}
++
++static inline void aruba_irq_enable(unsigned int irq)
++{
++ unsigned long flags;
++ unsigned int group, intr_bit;
++ volatile unsigned int *addr;
++
++ local_irq_save(flags);
++
++ if (irq < GROUP0_IRQ_BASE) {
++ enable_local_irq(irq);
++ } else {
++ int ip = irq - GROUP0_IRQ_BASE;
++ switch (mips_machtype) {
++ case MACH_ARUBA_AP70:
++ // irqs are in groups of 32
++ // ip is set to the remainder
++ group = ip >> 5;
++ ip &= 0x1f;
++
++ // bit -> 0 = unmask
++ intr_bit = 1 << ip;
++ addr = intr_group_muscat[group].base_addr;
++ WRITE_MASK_MUSCAT(addr, READ_MASK_MUSCAT(addr) & ~intr_bit);
++ break;
++
++ case MACH_ARUBA_AP65:
++ case MACH_ARUBA_AP60:
++ group = 0;
++
++ // bit -> 1 = unmasked
++ intr_bit = 1 << ip;
++ addr = intr_group_merlot[group].base_addr;
++ WRITE_MASK_MERLOT(addr, READ_MASK_MERLOT(addr) | intr_bit);
++ break;
++ }
++ enable_local_irq(group_to_ip(group));
++ }
++
++ back_to_back_c0_hazard();
++ local_irq_restore(flags);
++}
++
++static void aruba_irq_disable(unsigned int irq)
++{
++ unsigned long flags;
++ unsigned int group, intr_bit, mask;
++ volatile unsigned int *addr;
++
++ local_irq_save(flags);
++
++ if (irq < GROUP0_IRQ_BASE) {
++ disable_local_irq(irq);
++ } else {
++ int ip = irq - GROUP0_IRQ_BASE;
++ switch (mips_machtype) {
++ case MACH_ARUBA_AP70:
++ idt_gpio->gpioistat &= ~(1 << ip);
++
++ // irqs are in groups of 32
++ // ip is set to the remainder
++ group = ip >> 5;
++ ip &= 0x1f;
++
++ // bit -> 1 = mask
++ intr_bit = 1 << ip;
++ addr = intr_group_muscat[group].base_addr;
++
++ mask = READ_MASK_MUSCAT(addr);
++ mask |= intr_bit;
++ WRITE_MASK_MUSCAT(addr, mask);
++
++ if (mask == intr_group_muscat[group].mask) {
++ disable_local_irq(group_to_ip(group));
++ }
++ break;
++
++ case MACH_ARUBA_AP65:
++ case MACH_ARUBA_AP60:
++ group = 0;
++
++ // bit -> 0 = masked
++ intr_bit = 1 << ip;
++ addr = intr_group_merlot[group].base_addr;
++
++ mask = READ_MASK_MERLOT(addr);
++ mask &= ~intr_bit;
++ WRITE_MASK_MERLOT(addr, mask);
++
++ if (mask == intr_group_merlot[group].mask) {
++ disable_local_irq(group_to_ip(group));
++ }
++ break;
++ }
++ }
++
++ back_to_back_c0_hazard();
++ local_irq_restore(flags);
++}
++
++static unsigned int aruba_irq_startup(unsigned int irq)
++{
++ aruba_irq_enable(irq);
++ return 0;
++}
++
++#define aruba_irq_shutdown aruba_irq_disable
++
++static void aruba_irq_ack(unsigned int irq)
++{
++ aruba_irq_disable(irq);
++}
++
++static void aruba_irq_end(unsigned int irq)
++{
++ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
++ aruba_irq_enable(irq);
++}
++
++static struct hw_interrupt_type aruba_irq_type = {
++ .typename = "ARUBA",
++ .startup = aruba_irq_startup,
++ .shutdown = aruba_irq_shutdown,
++ .enable = aruba_irq_enable,
++ .disable = aruba_irq_disable,
++ .ack = aruba_irq_ack,
++ .end = aruba_irq_end,
++};
++
++void __init arch_init_irq(void)
++{
++ int i;
++ printk("Initializing IRQ's: %d out of %d\n", RC32434_NR_IRQS, NR_IRQS);
++ memset(irq_desc, 0, sizeof(irq_desc));
++
++ for (i = 0; i < RC32434_NR_IRQS; i++) {
++ irq_desc[i].status = IRQ_DISABLED;
++ irq_desc[i].action = NULL;
++ irq_desc[i].depth = 1;
++ irq_desc[i].handler = &aruba_irq_type;
++ spin_lock_init(&irq_desc[i].lock);
++ }
++}
++
++/* Main Interrupt dispatcher */
++
++void plat_irq_dispatch(struct pt_regs *regs)
++{
++ unsigned int pend, group, ip;
++ volatile unsigned int *addr;
++ unsigned long cp0_cause = read_c0_cause() & read_c0_status() & CAUSEF_IP;
++
++ if (cp0_cause & CAUSEF_IP7)
++ return aruba_timer_interrupt(regs);
++
++ if(cp0_cause == 0) {
++ printk("INTERRUPT(S) FIRED WHILE MASKED\n");
++#ifdef ARUBA_DEBUG
++ // debuging use -- figure out which interrupt(s) fired
++ cp0_cause = read_c0_cause() & CAUSEF_IP;
++ while (cp0_cause) {
++ unsigned long intr_bit;
++ unsigned int irq_nr;
++ intr_bit = (31 - rc32434_clz(cp0_cause));
++ irq_nr = intr_bit - GROUP0_IRQ_BASE;
++ printk(" ---> MASKED IRQ %d\n",irq_nr);
++ cp0_cause &= ~(1 << intr_bit);
++ }
++#endif
++ return;
++ }
++
++ switch (mips_machtype) {
++ case MACH_ARUBA_AP70:
++ if ((ip = (cp0_cause & 0x7c00))) {
++ group = 21 - rc32434_clz(ip);
++
++ addr = intr_group_muscat[group].base_addr;
++
++ pend = READ_PEND_MUSCAT(addr);
++ pend &= ~READ_MASK_MUSCAT(addr); // only unmasked interrupts
++ pend = 39 - rc32434_clz(pend);
++ do_IRQ(pend + (group << 5), regs);
++ }
++ break;
++ case MACH_ARUBA_AP65:
++ case MACH_ARUBA_AP60:
++ default:
++ if (cp0_cause & 0x4000) { // 1 << (8 +6) == irq 6
++ // Misc Interrupt
++ group = 0;
++
++ addr = intr_group_merlot[group].base_addr;
++
++ pend = READ_PEND_MERLOT(addr);
++ pend &= READ_MASK_MERLOT(addr); // only unmasked interrupts
++ pend = 31 - rc32434_clz(pend);
++ do_IRQ(pend + GROUP0_IRQ_BASE, regs);
++ }
++ if ((ip = (cp0_cause & 0x3c00))) { // irq 2-5
++ pend = 31 - rc32434_clz(ip);
++ do_IRQ(pend - GROUP0_IRQ_BASE, regs);
++ }
++ break;
++ }
++}
diff --git a/target/linux/aruba-2.6/patches/003-pci.patch b/target/linux/aruba-2.6/patches/003-pci.patch
new file mode 100644
index 0000000000..0cad12a087
--- /dev/null
+++ b/target/linux/aruba-2.6/patches/003-pci.patch
@@ -0,0 +1,618 @@
+diff -Nur linux-2.6.15/arch/mips/pci/fixup-aruba.c linux-2.6.15-openwrt/arch/mips/pci/fixup-aruba.c
+--- linux-2.6.15/arch/mips/pci/fixup-aruba.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-openwrt/arch/mips/pci/fixup-aruba.c 2006-01-10 00:34:41.000000000 +0100
+@@ -0,0 +1,115 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * PCI fixups for IDT EB434 board
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <asm/idt-boards/rc32434/rc32434.h>
++#include <asm/idt-boards/rc32434/rc32434_pci.h>
++
++int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++
++ if (dev->bus->number != 0) {
++ return 0;
++ }
++
++ slot = PCI_SLOT(dev->devfn);
++ dev->irq = 0;
++
++ if (slot > 0 && slot <= 15) {
++#if 1
++ if(slot == 10) {
++ if(pin == 1) dev->irq = GROUP4_IRQ_BASE + 9; // intA
++ } else if(slot == 11) {
++ if(pin == 1) dev->irq = GROUP4_IRQ_BASE + 10; // intA
++ if(pin == 2) dev->irq = GROUP4_IRQ_BASE + 10; // intA
++ if(pin == 3) dev->irq = GROUP4_IRQ_BASE + 10; // intA
++ } else if(slot == 12) {
++ if(pin == 1) dev->irq = GROUP4_IRQ_BASE + 11; // intA
++ if(pin == 2) dev->irq = GROUP4_IRQ_BASE + 12; // intB
++ } else if (slot == 13) {
++ if(pin == 1) dev->irq = GROUP4_IRQ_BASE + 12; // intA
++ if(pin == 2) dev->irq = GROUP4_IRQ_BASE + 11; // intB
++ } else {
++ dev->irq = GROUP4_IRQ_BASE + 11;
++ }
++#else
++ switch (pin) {
++ case 1: /* INTA*/
++ dev->irq = GROUP4_IRQ_BASE + 11;
++ break;
++ case 2: /* INTB */
++ dev->irq = GROUP4_IRQ_BASE + 11;
++ break;
++ case 3: /* INTC */
++ dev->irq = GROUP4_IRQ_BASE + 11;
++ break;
++ case 4: /* INTD */
++ dev->irq = GROUP4_IRQ_BASE + 11;
++ break;
++ default:
++ dev->irq = 0xff;
++ break;
++ }
++#endif
++#ifdef DEBUG
++ printk("irq fixup: slot %d, pin %d, irq %d\n",
++ slot, pin, dev->irq);
++#endif
++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE,dev->irq);
++ }
++ return (dev->irq);
++}
++
++struct pci_fixup pcibios_fixups[] = {
++ {0}
++};
++
++
++
++
++
++
++
++
++
++
++
+diff -Nur linux-2.6.15/arch/mips/pci/Makefile linux-2.6.15-openwrt/arch/mips/pci/Makefile
+--- linux-2.6.15/arch/mips/pci/Makefile 2006-01-03 04:21:10.000000000 +0100
++++ linux-2.6.15-openwrt/arch/mips/pci/Makefile 2006-01-10 00:32:32.000000000 +0100
+@@ -56,3 +56,4 @@
+ obj-$(CONFIG_TOSHIBA_RBTX4938) += fixup-tx4938.o ops-tx4938.o
+ obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o
+ obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o
++obj-$(CONFIG_MACH_ARUBA) += fixup-aruba.o ops-aruba.o pci-aruba.o
+diff -Nur linux-2.6.15/arch/mips/pci/ops-aruba.c linux-2.6.15-openwrt/arch/mips/pci/ops-aruba.c
+--- linux-2.6.15/arch/mips/pci/ops-aruba.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-openwrt/arch/mips/pci/ops-aruba.c 2006-01-10 00:32:32.000000000 +0100
+@@ -0,0 +1,204 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * pci_ops for IDT EB434 board
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++
++#include <asm/cpu.h>
++#include <asm/io.h>
++
++#include <asm/idt-boards/rc32434/rc32434.h>
++#include <asm/idt-boards/rc32434/rc32434_pci.h>
++
++#define PCI_ACCESS_READ 0
++#define PCI_ACCESS_WRITE 1
++
++
++#define PCI_CFG_SET(slot,func,off) \
++ (rc32434_pci->pcicfga = (0x80000000 | ((slot)<<11) | \
++ ((func)<<8) | (off)))
++
++static int config_access(unsigned char access_type, struct pci_bus *bus,
++ unsigned int devfn, unsigned char where,
++ u32 * data)
++{
++ /*
++ * config cycles are on 4 byte boundary only
++ */
++ unsigned int slot = PCI_SLOT(devfn);
++ u8 func = PCI_FUNC(devfn);
++
++ if (slot < 2 || slot > 15) {
++ *data = 0xFFFFFFFF;
++ return -1;
++ }
++ /* Setup address */
++ PCI_CFG_SET(slot, func, where);
++ rc32434_sync();
++
++ if (access_type == PCI_ACCESS_WRITE) {
++ rc32434_sync();
++ rc32434_pci->pcicfgd = *data;
++ } else {
++ rc32434_sync();
++ *data = rc32434_pci->pcicfgd;
++ }
++
++ rc32434_sync();
++
++ return 0;
++}
++
++
++/*
++ * We can't address 8 and 16 bit words directly. Instead we have to
++ * read/write a 32bit word and mask/modify the data we actually want.
++ */
++static int read_config_byte(struct pci_bus *bus, unsigned int devfn,
++ int where, u8 * val)
++{
++ u32 data;
++ int ret;
++
++ ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
++ *val = (data >> ((where & 3) << 3)) & 0xff;
++ return ret;
++}
++
++static int read_config_word(struct pci_bus *bus, unsigned int devfn,
++ int where, u16 * val)
++{
++ u32 data;
++ int ret;
++
++ ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
++ *val = (data >> ((where & 3) << 3)) & 0xffff;
++ return ret;
++}
++
++static int read_config_dword(struct pci_bus *bus, unsigned int devfn,
++ int where, u32 * val)
++{
++ int ret;
++
++ ret = config_access(PCI_ACCESS_READ, bus, devfn, where, val);
++ return ret;
++}
++
++static int
++write_config_byte(struct pci_bus *bus, unsigned int devfn, int where,
++ u8 val)
++{
++ u32 data = 0;
++
++ if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
++ return -1;
++
++ data = (data & ~(0xff << ((where & 3) << 3))) |
++ (val << ((where & 3) << 3));
++
++ if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
++ return -1;
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++
++static int
++write_config_word(struct pci_bus *bus, unsigned int devfn, int where,
++ u16 val)
++{
++ u32 data = 0;
++
++ if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
++ return -1;
++
++ data = (data & ~(0xffff << ((where & 3) << 3))) |
++ (val << ((where & 3) << 3));
++
++ if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
++ return -1;
++
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++
++static int
++write_config_dword(struct pci_bus *bus, unsigned int devfn, int where,
++ u32 val)
++{
++ if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val))
++ return -1;
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int pci_config_read(struct pci_bus *bus, unsigned int devfn,
++ int where, int size, u32 * val)
++{
++ switch (size) {
++ case 1:
++ return read_config_byte(bus, devfn, where, (u8 *) val);
++ case 2:
++ return read_config_word(bus, devfn, where, (u16 *) val);
++ default:
++ return read_config_dword(bus, devfn, where, val);
++ }
++}
++
++static int pci_config_write(struct pci_bus *bus, unsigned int devfn,
++ int where, int size, u32 val)
++{
++ switch (size) {
++ case 1:
++ return write_config_byte(bus, devfn, where, (u8) val);
++ case 2:
++ return write_config_word(bus, devfn, where, (u16) val);
++ default:
++ return write_config_dword(bus, devfn, where, val);
++ }
++}
++
++struct pci_ops rc32434_pci_ops = {
++ .read = pci_config_read,
++ .write = pci_config_write,
++};
+diff -Nur linux-2.6.15/arch/mips/pci/pci-aruba.c linux-2.6.15-openwrt/arch/mips/pci/pci-aruba.c
+--- linux-2.6.15/arch/mips/pci/pci-aruba.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-openwrt/arch/mips/pci/pci-aruba.c 2006-01-10 00:32:32.000000000 +0100
+@@ -0,0 +1,235 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * PCI initialization for IDT EB434 board
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <asm/idt-boards/rc32434/rc32434.h>
++#include <asm/idt-boards/rc32434/rc32434_pci.h>
++
++#define PCI_ACCESS_READ 0
++#define PCI_ACCESS_WRITE 1
++
++#undef DEBUG
++#ifdef DEBUG
++#define DBG(x...) printk(x)
++#else
++#define DBG(x...)
++#endif
++/* define an unsigned array for the PCI registers */
++unsigned int korinaCnfgRegs[25] = {
++ KORINA_CNFG1, KORINA_CNFG2, KORINA_CNFG3, KORINA_CNFG4,
++ KORINA_CNFG5, KORINA_CNFG6, KORINA_CNFG7, KORINA_CNFG8,
++ KORINA_CNFG9, KORINA_CNFG10, KORINA_CNFG11, KORINA_CNFG12,
++ KORINA_CNFG13, KORINA_CNFG14, KORINA_CNFG15, KORINA_CNFG16,
++ KORINA_CNFG17, KORINA_CNFG18, KORINA_CNFG19, KORINA_CNFG20,
++ KORINA_CNFG21, KORINA_CNFG22, KORINA_CNFG23, KORINA_CNFG24
++};
++
++static struct resource rc32434_res_pci_mem2;
++
++static struct resource rc32434_res_pci_mem1 = {
++ .name = "PCI MEM1",
++ .start = 0x50000000,
++ .end = 0x5FFFFFFF,
++ .flags = IORESOURCE_MEM,
++ .child = &rc32434_res_pci_mem2,
++};
++static struct resource rc32434_res_pci_mem2 = {
++ .name = "PCI MEM2",
++ .start = 0x60000000,
++ .end = 0x6FFFFFFF,
++ .flags = IORESOURCE_MEM,
++ .parent = &rc32434_res_pci_mem1,
++};
++static struct resource rc32434_res_pci_io1 = {
++ .name = "PCI I/O1",
++ .start = 0x18800000,
++ .end = 0x188FFFFF,
++ .flags = IORESOURCE_IO,
++};
++
++extern struct pci_ops rc32434_pci_ops;
++
++struct pci_controller rc32434_controller = {
++ .pci_ops = &rc32434_pci_ops,
++ .mem_resource = &rc32434_res_pci_mem1,
++ .io_resource = &rc32434_res_pci_io1,
++ .mem_offset = 0x00000000UL,
++ .io_offset = 0x00000000UL,
++};
++
++extern unsigned int arch_has_pci;
++
++static int __init rc32434_pcibridge_init(void)
++{
++
++ unsigned int pciConfigAddr = 0;/*used for writing pci config values */
++ int loopCount=0 ;/*used for the loop */
++
++ unsigned int pcicValue, pcicData=0;
++ unsigned int dummyRead, pciCntlVal = 0;
++
++ if (!arch_has_pci) return 0;
++
++ printk("PCI: Initializing PCI\n");
++
++ /* Disable the IP bus error for PCI scaning */
++ pciCntlVal=rc32434_pci->pcic;
++ pciCntlVal &= 0xFFFFFF7;
++ rc32434_pci->pcic = pciCntlVal;
++
++ ioport_resource.start = rc32434_res_pci_io1.start;
++ ioport_resource.end = rc32434_res_pci_io1.end;
++/*
++ iomem_resource.start = rc32434_res_pci_mem1.start;
++ iomem_resource.end = rc32434_res_pci_mem1.end;
++*/
++
++ pcicValue = rc32434_pci->pcic;
++ pcicValue = (pcicValue >> PCIM_SHFT) & PCIM_BIT_LEN;
++ if (!((pcicValue == PCIM_H_EA) ||
++ (pcicValue == PCIM_H_IA_FIX) ||
++ (pcicValue == PCIM_H_IA_RR))) {
++ /* Not in Host Mode, return ERROR */
++ return -1;
++ }
++
++ /* Enables the Idle Grant mode, Arbiter Parking */
++ pcicData |=(PCIC_igm_m|PCIC_eap_m|PCIC_en_m);
++ rc32434_pci->pcic = pcicData; /* Enable the PCI bus Interface */
++ /* Zero out the PCI status & PCI Status Mask */
++ for(;;) {
++ pcicData = rc32434_pci->pcis;
++ if (!(pcicData & PCIS_rip_m))
++ break;
++ }
++
++ rc32434_pci->pcis = 0;
++ rc32434_pci->pcism = 0xFFFFFFFF;
++ /* Zero out the PCI decoupled registers */
++ rc32434_pci->pcidac=0; /* disable PCI decoupled accesses at initialization */
++ rc32434_pci->pcidas=0; /* clear the status */
++ rc32434_pci->pcidasm=0x0000007F; /* Mask all the interrupts */
++ /* Mask PCI Messaging Interrupts */
++ rc32434_pci_msg->pciiic = 0;
++ rc32434_pci_msg->pciiim = 0xFFFFFFFF;
++ rc32434_pci_msg->pciioic = 0;
++ rc32434_pci_msg->pciioim = 0;
++
++ /* Setup PCILB0 as Memory Window */
++ rc32434_pci->pcilba[0].a = (unsigned int) (PCI_ADDR_START);
++
++ /* setup the PCI map address as same as the local address */
++
++ rc32434_pci->pcilba[0].m = (unsigned int) (PCI_ADDR_START);
++
++ /* Setup PCILBA1 as MEM */
++#ifdef __MIPSEB__
++ rc32434_pci->pcilba[0].c = ( ((SIZE_16MB & 0x1f) << PCILBAC_size_b) | PCILBAC_sb_m);
++#else
++ rc32434_pci->pcilba[0].c = ( ((SIZE_16MB & 0x1f) << PCILBAC_size_b));
++#endif
++ dummyRead = rc32434_pci->pcilba[0].c; /* flush the CPU write Buffers */
++
++ rc32434_pci->pcilba[1].a = 0x60000000;
++
++ rc32434_pci->pcilba[1].m = 0x60000000;
++ /* setup PCILBA2 as IO Window*/
++#ifdef __MIPSEB__
++ rc32434_pci->pcilba[1].c = ( ((SIZE_256MB & 0x1f) << PCILBAC_size_b) | PCILBAC_sb_m);
++#else
++ rc32434_pci->pcilba[1].c = ((SIZE_256MB & 0x1f) << PCILBAC_size_b);
++#endif
++ dummyRead = rc32434_pci->pcilba[1].c; /* flush the CPU write Buffers */
++ rc32434_pci->pcilba[2].a = 0x18C00000;
++
++ rc32434_pci->pcilba[2].m = 0x18FFFFFF;
++ /* setup PCILBA2 as IO Window*/
++#ifdef __MIPSEB__
++ rc32434_pci->pcilba[2].c = ( ((SIZE_4MB & 0x1f) << PCILBAC_size_b) | PCILBAC_sb_m);
++#else
++ rc32434_pci->pcilba[2].c = ((SIZE_4MB & 0x1f) << PCILBAC_size_b);
++#endif
++
++ dummyRead = rc32434_pci->pcilba[2].c; /* flush the CPU write Buffers */
++
++
++ rc32434_pci->pcilba[3].a = 0x18800000;
++
++ rc32434_pci->pcilba[3].m = 0x18800000;
++ /* Setup PCILBA3 as IO Window */
++
++#ifdef __MIPSEB__
++ rc32434_pci->pcilba[3].c = ( (((SIZE_1MB & 0x1ff) << PCILBAC_size_b) | PCILBAC_msi_m) | PCILBAC_sb_m);
++#else
++ rc32434_pci->pcilba[3].c = (((SIZE_1MB & 0x1ff) << PCILBAC_size_b) | PCILBAC_msi_m);
++#endif
++ dummyRead = rc32434_pci->pcilba[2].c; /* flush the CPU write Buffers */
++
++ pciConfigAddr = (unsigned int)(0x80000004);
++ for(loopCount = 0; loopCount < 24; loopCount++){
++ rc32434_pci->pcicfga = pciConfigAddr;
++ dummyRead = rc32434_pci->pcicfga;
++ rc32434_pci->pcicfgd = korinaCnfgRegs[loopCount];
++ dummyRead=rc32434_pci->pcicfgd;
++ pciConfigAddr += 4;
++ }
++ rc32434_pci->pcitc=(unsigned int)((PCITC_RTIMER_VAL&0xff) << PCITC_rtimer_b) |
++ ((PCITC_DTIMER_VAL&0xff)<<PCITC_dtimer_b);
++
++ pciCntlVal = rc32434_pci->pcic;
++ pciCntlVal &= ~(PCIC_tnr_m);
++ rc32434_pci->pcic = pciCntlVal;
++ pciCntlVal = rc32434_pci->pcic;
++
++ register_pci_controller(&rc32434_controller);
++
++ rc32434_sync();
++ return 0;
++}
++
++arch_initcall(rc32434_pcibridge_init);
++
++/* Do platform specific device initialization at pci_enable_device() time */
++int pcibios_plat_dev_init(struct pci_dev *dev)
++{
++ return 0;
++}
+diff -Nur linux-2.6.15/drivers/pci/access.c linux-2.6.15-openwrt/drivers/pci/access.c
+--- linux-2.6.15/drivers/pci/access.c 2006-01-03 04:21:10.000000000 +0100
++++ linux-2.6.15-openwrt/drivers/pci/access.c 2006-01-10 00:43:10.000000000 +0100
+@@ -21,6 +21,7 @@
+ #define PCI_word_BAD (pos & 1)
+ #define PCI_dword_BAD (pos & 3)
+
++#ifdef __MIPSEB__
+ #define PCI_OP_READ(size,type,len) \
+ int pci_bus_read_config_##size \
+ (struct pci_bus *bus, unsigned int devfn, int pos, type *value) \
+@@ -31,11 +32,32 @@
+ if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
+ spin_lock_irqsave(&pci_lock, flags); \
+ res = bus->ops->read(bus, devfn, pos, len, &data); \
++ if (len == 1) \
++ *value = (type)((data >> 24) & 0xff); \
++ else if (len == 2) \
++ *value = (type)((data >> 16) & 0xffff); \
++ else \
+ *value = (type)data; \
+ spin_unlock_irqrestore(&pci_lock, flags); \
+ return res; \
+ }
++#else
+
++#define PCI_OP_READ(size,type,len) \
++int pci_bus_read_config_##size \
++ (struct pci_bus *bus, unsigned int devfn, int pos, type *value) \
++{ \
++ int res; \
++ unsigned long flags; \
++ u32 data = 0; \
++ if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
++ spin_lock_irqsave(&pci_lock, flags); \
++ res = bus->ops->read(bus, devfn, pos, len, &data); \
++ *value = (type)data; \
++ spin_unlock_irqrestore(&pci_lock, flags); \
++ return res; \
++}
++#endif
+ #define PCI_OP_WRITE(size,type,len) \
+ int pci_bus_write_config_##size \
+ (struct pci_bus *bus, unsigned int devfn, int pos, type value) \
diff --git a/target/linux/aruba-2.6/patches/004-wdt.patch b/target/linux/aruba-2.6/patches/004-wdt.patch
new file mode 100644
index 0000000000..15fbffa043
--- /dev/null
+++ b/target/linux/aruba-2.6/patches/004-wdt.patch
@@ -0,0 +1,126 @@
+diff -Nur linux-2.6.15.1/drivers/char/watchdog/wdt_merlot.c linux-2.6.15.1-openwrt/drivers/char/watchdog/wdt_merlot.c
+--- linux-2.6.15.1/drivers/char/watchdog/wdt_merlot.c 2006-01-26 21:14:02.204626250 -0800
++++ linux-2.6.15.1-openwrt/drivers/char/watchdog/wdt_merlot.c 2006-02-02 20:31:43.000000000 -0800
+@@ -0,0 +1,110 @@
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/miscdevice.h>
++#include <linux/watchdog.h>
++#include <linux/fs.h>
++
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/system.h>
++#include <asm/bootinfo.h>
++
++extern unsigned long mips_machtype;
++
++static unsigned long wdt_is_open;
++static struct timer_list wdt_timer;
++
++static void wdt_merlot_refresh(void)
++{
++ volatile __u32 *wdt;
++ switch (mips_machtype) {
++ case MACH_ARUBA_AP70:
++ wdt = (__u32 *) 0xb8030034;
++ *wdt = 0x10000000;
++ break;
++ default:
++ wdt = (__u32 *) 0xbc00300c;
++ *wdt = 0x40000000;
++ break;
++ }
++}
++
++static void wdt_merlot_timer_fn(unsigned long data)
++{
++ wdt_merlot_refresh();
++ if (!test_bit(1, &wdt_is_open))
++ mod_timer(&wdt_timer, jiffies + HZ);
++}
++
++static int wdt_merlot_setup_timer(void)
++{
++
++ init_timer(&wdt_timer);
++ wdt_timer.function = wdt_merlot_timer_fn;
++ wdt_timer.data = 0;
++ wdt_timer.expires = jiffies + HZ;
++ add_timer(&wdt_timer);
++ return 0;
++}
++
++static int wdt_open(struct inode *inode, struct file *file)
++{
++ if (test_and_set_bit(0, &wdt_is_open))
++ return -EBUSY;
++ set_bit(1, &wdt_is_open);
++ return nonseekable_open(inode, file);
++}
++
++static ssize_t wdt_write(struct file *file, const char __user * buf, size_t count, loff_t * ppos)
++{
++ if (count) /* something was written */
++ wdt_merlot_refresh();
++ return count;
++}
++
++static int wdt_release(struct inode *inode, struct file *file)
++{
++ clear_bit(0, &wdt_is_open);
++ return 0;
++}
++
++static struct file_operations wdt_fops = {
++ .owner = THIS_MODULE,
++ .llseek = no_llseek,
++ .write = wdt_write,
++ .open = wdt_open,
++ .release = wdt_release,
++};
++
++static struct miscdevice wdt_miscdev = {
++ .minor = WATCHDOG_MINOR,
++ .name = "watchdog",
++ .fops = &wdt_fops,
++};
++
++static void __exit wdt_exit(void)
++{
++ misc_deregister(&wdt_miscdev);
++}
++
++static int __init wdt_init(void)
++{
++ int ret;
++ ret = misc_register(&wdt_miscdev);
++ if (ret) {
++ printk(KERN_ERR
++ "wdt: cannot register miscdev on minor=%d (err=%d)\n",
++ WATCHDOG_MINOR, ret);
++ misc_deregister(&wdt_miscdev);
++ goto out;
++ }
++ printk("wdt: registered with refresh\n");
++ wdt_merlot_refresh();
++ wdt_merlot_setup_timer();
++ out:
++ return ret;
++}
++
++module_init(wdt_init);
++module_exit(wdt_exit);
+diff -Nur linux-2.6.15.3/drivers/char/watchdog/Makefile linux-2.6.15.3-openwrt/drivers/char/watchdog/Makefile
+--- linux-2.6.15.3/drivers/char/watchdog/Makefile 2006-02-22 10:04:18.596278000 -0800
++++ linux-2.6.15.3-openwrt/drivers/char/watchdog/Makefile 2006-02-22 10:06:21.400960000 -0800
+@@ -71,5 +71,8 @@
+
+ # SPARC64 Architecture
+
++# Aruba Architecture
++obj-$(CONFIG_MACH_ARUBA) += wdt_merlot.o
++
+ # Architecture Independant
+ obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
diff --git a/target/linux/aruba-2.6/patches/010-ar2313_enet.patch b/target/linux/aruba-2.6/patches/010-ar2313_enet.patch
new file mode 100644
index 0000000000..d71d96f452
--- /dev/null
+++ b/target/linux/aruba-2.6/patches/010-ar2313_enet.patch
@@ -0,0 +1,2175 @@
+diff -Nur linux-2.6.17/drivers/net/ar2313/ar2313.c linux-2.6.17-owrt/drivers/net/ar2313/ar2313.c
+--- linux-2.6.17/drivers/net/ar2313/ar2313.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/drivers/net/ar2313/ar2313.c 2006-06-19 12:57:27.000000000 +0200
+@@ -0,0 +1,1649 @@
++/*
++ * ar2313.c: Linux driver for the Atheros AR2313 Ethernet device.
++ *
++ * Copyright 2004 by Sameer Dekate, <sdekate@arubanetworks.com>.
++ * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
++ *
++ * Thanks to Atheros for providing hardware and documentation
++ * enabling me to write this driver.
++ *
++ * 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.
++ *
++ * Additional credits:
++ * This code is taken from John Taylor's Sibyte driver and then
++ * modified for the AR2313.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/ioport.h>
++#include <linux/pci.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/mm.h>
++#include <linux/highmem.h>
++#include <linux/sockios.h>
++#include <linux/pkt_sched.h>
++#include <linux/compile.h>
++#include <linux/mii.h>
++#include <linux/ethtool.h>
++#include <linux/ctype.h>
++
++#include <net/sock.h>
++#include <net/ip.h>
++
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/byteorder.h>
++#include <asm/uaccess.h>
++#include <asm/bootinfo.h>
++
++extern char *getenv(char *e);
++
++
++#undef INDEX_DEBUG
++#define DEBUG 0
++#define DEBUG_TX 0
++#define DEBUG_RX 0
++#define DEBUG_INT 0
++#define DEBUG_MC 0
++#define DEBUG_ERR 1
++
++#ifndef __exit
++#define __exit
++#endif
++
++#ifndef min
++#define min(a,b) (((a)<(b))?(a):(b))
++#endif
++
++#ifndef SMP_CACHE_BYTES
++#define SMP_CACHE_BYTES L1_CACHE_BYTES
++#endif
++
++#ifndef SET_MODULE_OWNER
++#define SET_MODULE_OWNER(dev) {do{} while(0);}
++#define AR2313_MOD_INC_USE_COUNT MOD_INC_USE_COUNT
++#define AR2313_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT
++#else
++#define AR2313_MOD_INC_USE_COUNT {do{} while(0);}
++#define AR2313_MOD_DEC_USE_COUNT {do{} while(0);}
++#endif
++
++#define PHYSADDR(a) ((_ACAST32_ (a)) & 0x1fffffff)
++
++static char ethaddr[18] = "00:00:00:00:00:00";
++static char ifname[5] = "bond";
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,52)
++module_param_string(ethaddr, ethaddr, 18, 0);
++module_param_string(ifname, ifname, 5, 0);
++#else
++MODULE_PARM(ethaddr, "c18");
++MODULE_PARM(ifname, "c5");
++#endif
++
++#define AR2313_MBOX_SET_BIT 0x8
++
++#define BOARD_IDX_STATIC 0
++#define BOARD_IDX_OVERFLOW -1
++
++/* margot includes */
++#include <asm/idt-boards/rc32434/rc32434.h>
++
++#include "ar2313_msg.h"
++#include "platform.h"
++#include "dma.h"
++#include "ar2313.h"
++
++/*
++ * New interrupt handler strategy:
++ *
++ * An old interrupt handler worked using the traditional method of
++ * replacing an skbuff with a new one when a packet arrives. However
++ * the rx rings do not need to contain a static number of buffer
++ * descriptors, thus it makes sense to move the memory allocation out
++ * of the main interrupt handler and do it in a bottom half handler
++ * and only allocate new buffers when the number of buffers in the
++ * ring is below a certain threshold. In order to avoid starving the
++ * NIC under heavy load it is however necessary to force allocation
++ * when hitting a minimum threshold. The strategy for alloction is as
++ * follows:
++ *
++ * RX_LOW_BUF_THRES - allocate buffers in the bottom half
++ * RX_PANIC_LOW_THRES - we are very low on buffers, allocate
++ * the buffers in the interrupt handler
++ * RX_RING_THRES - maximum number of buffers in the rx ring
++ *
++ * One advantagous side effect of this allocation approach is that the
++ * entire rx processing can be done without holding any spin lock
++ * since the rx rings and registers are totally independent of the tx
++ * ring and its registers. This of course includes the kmalloc's of
++ * new skb's. Thus start_xmit can run in parallel with rx processing
++ * and the memory allocation on SMP systems.
++ *
++ * Note that running the skb reallocation in a bottom half opens up
++ * another can of races which needs to be handled properly. In
++ * particular it can happen that the interrupt handler tries to run
++ * the reallocation while the bottom half is either running on another
++ * CPU or was interrupted on the same CPU. To get around this the
++ * driver uses bitops to prevent the reallocation routines from being
++ * reentered.
++ *
++ * TX handling can also be done without holding any spin lock, wheee
++ * this is fun! since tx_csm is only written to by the interrupt
++ * handler.
++ */
++
++/*
++ * Threshold values for RX buffer allocation - the low water marks for
++ * when to start refilling the rings are set to 75% of the ring
++ * sizes. It seems to make sense to refill the rings entirely from the
++ * intrrupt handler once it gets below the panic threshold, that way
++ * we don't risk that the refilling is moved to another CPU when the
++ * one running the interrupt handler just got the slab code hot in its
++ * cache.
++ */
++#define RX_RING_SIZE AR2313_DESCR_ENTRIES
++#define RX_PANIC_THRES (RX_RING_SIZE/4)
++#define RX_LOW_THRES ((3*RX_RING_SIZE)/4)
++#define CRC_LEN 4
++#define RX_OFFSET 2
++
++#define AR2313_BUFSIZE (AR2313_MTU + ETH_HLEN + CRC_LEN + RX_OFFSET)
++
++#ifdef MODULE
++MODULE_AUTHOR("Sameer Dekate<sdekate@arubanetworks.com>");
++MODULE_DESCRIPTION("AR2313 Ethernet driver");
++#endif
++
++#if DEBUG
++static char version[] __initdata =
++ "ar2313.c: v0.02 2006/06/19 sdekate@arubanetworks.com\n";
++#endif /* DEBUG */
++
++#define virt_to_phys(x) ((u32)(x) & 0x1fffffff)
++
++// prototypes
++static short armiiread(short phy, short reg);
++static void armiiwrite(short phy, short reg, short data);
++#ifdef TX_TIMEOUT
++static void ar2313_tx_timeout(struct net_device *dev);
++#endif
++static void ar2313_halt(struct net_device *dev);
++static void rx_tasklet_func(unsigned long data);
++static void ar2313_multicast_list(struct net_device *dev);
++
++static struct net_device *root_dev;
++static int probed __initdata = 0;
++static unsigned long ar_eth_base;
++static unsigned long ar_dma_base;
++static unsigned long ar_int_base;
++static unsigned long ar_int_mac_mask;
++static unsigned long ar_int_phy_mask;
++
++#ifndef ERR
++#define ERR(fmt, args...) printk("%s: " fmt, __func__, ##args)
++#endif
++
++static int parse_mac_addr(struct net_device *dev, char* macstr){
++ int i, j;
++ unsigned char result, value;
++
++ for (i=0; i<6; i++) {
++ result = 0;
++ if (i != 5 && *(macstr+2) != ':') {
++ ERR("invalid mac address format: %d %c\n",
++ i, *(macstr+2));
++ return -EINVAL;
++ }
++ for (j=0; j<2; j++) {
++ if (isxdigit(*macstr) && (value = isdigit(*macstr) ? *macstr-'0' :
++ toupper(*macstr)-'A'+10) < 16)
++ {
++ result = result*16 + value;
++ macstr++;
++ }
++ else {
++ ERR("invalid mac address "
++ "character: %c\n", *macstr);
++ return -EINVAL;
++ }
++ }
++
++ macstr++;
++ dev->dev_addr[i] = result;
++ }
++
++ return 0;
++}
++
++
++int __init ar2313_probe(void)
++{
++ struct net_device *dev;
++ struct ar2313_private *sp;
++ int version_disp;
++ char name[64] ;
++
++ if (probed)
++ return -ENODEV;
++ probed++;
++
++ version_disp = 0;
++ sprintf(name, "%s%%d", ifname) ;
++ dev = alloc_etherdev(sizeof(struct ar2313_private));
++
++ if (dev == NULL) {
++ printk(KERN_ERR "ar2313: Unable to allocate net_device structure!\n");
++ return -ENOMEM;
++ }
++
++ SET_MODULE_OWNER(dev);
++
++ sp = dev->priv;
++
++ sp->link = 0;
++ switch (mips_machtype) {
++ case MACH_ARUBA_AP60:
++ ar_eth_base = 0xb8100000;
++ ar_dma_base = ar_eth_base + 0x1000;
++ ar_int_base = 0x1C003020;
++ ar_int_mac_mask = RESET_ENET0|RESET_ENET1;
++ ar_int_phy_mask = RESET_EPHY0|RESET_EPHY1;
++ sp->mac = 1;
++ sp->phy = 1;
++ dev->irq = 4;
++ break;
++
++ case MACH_ARUBA_AP40:
++ ar_eth_base = 0xb0500000;
++ ar_dma_base = ar_eth_base + 0x1000;
++ ar_int_base = 0x11000004;
++ ar_int_mac_mask = 0x800;
++ ar_int_phy_mask = 0x400;
++ sp->mac = 0;
++ sp->phy = 1;
++ dev->irq = 4;
++ break;
++
++ case MACH_ARUBA_AP65:
++ ar_eth_base = 0xb8100000;
++ ar_dma_base = ar_eth_base + 0x1000;
++ ar_int_base = 0x1C003020;
++ ar_int_mac_mask = RESET_ENET0|RESET_ENET1;
++ ar_int_phy_mask = RESET_EPHY0|RESET_EPHY1;
++ sp->mac = 0;
++#if 0
++ // commented out, for now
++
++ if (mips_machtype == MACH_ARUBA_SAMSUNG) {
++ sp->phy = 0x1f;
++ } else {
++ sp->phy = 1;
++ }
++#else
++ sp->phy = 1;
++#endif
++ dev->irq = 3;
++ break;
++
++ default:
++ printk("%s: unsupported mips_machtype=0x%lx\n",
++ __FUNCTION__, mips_machtype) ;
++ return -ENODEV;
++ }
++
++ spin_lock_init(&sp->lock);
++
++ /* initialize func pointers */
++ dev->open = &ar2313_open;
++ dev->stop = &ar2313_close;
++ dev->hard_start_xmit = &ar2313_start_xmit;
++
++ dev->get_stats = &ar2313_get_stats;
++ dev->set_multicast_list = &ar2313_multicast_list;
++#ifdef TX_TIMEOUT
++ dev->tx_timeout = ar2313_tx_timeout;
++ dev->watchdog_timeo = AR2313_TX_TIMEOUT;
++#endif
++ dev->do_ioctl = &ar2313_ioctl;
++
++ // SAMEER: do we need this?
++ dev->features |= NETIF_F_SG | NETIF_F_HIGHDMA;
++
++ tasklet_init(&sp->rx_tasklet, rx_tasklet_func, (unsigned long) dev);
++ tasklet_disable(&sp->rx_tasklet);
++
++ /* display version info if adapter is found */
++ if (!version_disp) {
++ /* set display flag to TRUE so that */
++ /* we only display this string ONCE */
++ version_disp = 1;
++#if DEBUG
++ printk(version);
++#endif /* DEBUG */
++ }
++
++ request_region(PHYSADDR(ETHERNET_BASE), ETHERNET_SIZE*ETHERNET_MACS,
++ "AR2313ENET");
++
++ sp->eth_regs = ioremap_nocache(PHYSADDR(ETHERNET_BASE + ETHERNET_SIZE*sp->mac),
++ sizeof(*sp->eth_regs));
++ if (!sp->eth_regs) {
++ printk("Can't remap eth registers\n");
++ return(-ENXIO);
++ }
++
++ sp->dma_regs = ioremap_nocache(PHYSADDR(DMA_BASE + DMA_SIZE*sp->mac),
++ sizeof(*sp->dma_regs));
++ dev->base_addr = (unsigned int) sp->dma_regs;
++ if (!sp->dma_regs) {
++ printk("Can't remap DMA registers\n");
++ return(-ENXIO);
++ }
++
++ sp->int_regs = ioremap_nocache(PHYSADDR(INTERRUPT_BASE),
++ sizeof(*sp->int_regs));
++ if (!sp->int_regs) {
++ printk("Can't remap INTERRUPT registers\n");
++ return(-ENXIO);
++ }
++
++ strncpy(sp->name, "Atheros AR2313", sizeof (sp->name) - 1);
++ sp->name [sizeof (sp->name) - 1] = '\0';
++
++ {
++ char mac[32];
++ extern char *getenv(char *e);
++ unsigned char def_mac[6] = {0, 0x0b, 0x86, 0xba, 0xdb, 0xad};
++ memset(mac, 0, 32);
++ memcpy(mac, getenv("ethaddr"), 17);
++ if (parse_mac_addr(dev, mac)){
++ printk("%s: MAC address not found, using default\n", __func__);
++ memcpy(dev->dev_addr, def_mac, 6);
++ }
++ }
++
++ sp->board_idx = BOARD_IDX_STATIC;
++
++ if (ar2313_init(dev)) {
++ /*
++ * ar2313_init() calls ar2313_init_cleanup() on error.
++ */
++ kfree(dev);
++ return -ENODEV;
++ }
++
++ if (register_netdev(dev)){
++ printk("%s: register_netdev failed\n", __func__);
++ return -1;
++ }
++
++ printk("%s: %s: %02x:%02x:%02x:%02x:%02x:%02x, irq %d\n",
++ dev->name, sp->name,
++ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
++ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5],
++ dev->irq);
++
++ /* start link poll timer */
++ ar2313_setup_timer(dev);
++
++ /*
++ * Register the device
++ */
++ root_dev = dev;
++
++ return 0;
++}
++
++#if 0
++static void ar2313_dump_regs(struct net_device *dev)
++{
++ unsigned int *ptr, i;
++ struct ar2313_private *sp = (struct ar2313_private *)dev->priv;
++
++ ptr = (unsigned int *)sp->eth_regs;
++ for(i=0; i< (sizeof(ETHERNET_STRUCT)/ sizeof(unsigned int)); i++, ptr++) {
++ printk("ENET: %08x = %08x\n", (int)ptr, *ptr);
++ }
++
++ ptr = (unsigned int *)sp->dma_regs;
++ for(i=0; i< (sizeof(DMA)/ sizeof(unsigned int)); i++, ptr++) {
++ printk("DMA: %08x = %08x\n", (int)ptr, *ptr);
++ }
++
++ ptr = (unsigned int *)sp->int_regs;
++ for(i=0; i< (sizeof(INTERRUPT)/ sizeof(unsigned int)); i++, ptr++){
++ printk("INT: %08x = %08x\n", (int)ptr, *ptr);
++ }
++
++ for (i = 0; i < AR2313_DESCR_ENTRIES; i++) {
++ ar2313_descr_t *td = &sp->tx_ring[i];
++ printk("Tx desc %2d: %08x %08x %08x %08x\n", i,
++ td->status, td->devcs, td->addr, td->descr);
++ }
++}
++#endif
++
++#ifdef TX_TIMEOUT
++static void
++ar2313_tx_timeout(struct net_device *dev)
++{
++ struct ar2313_private *sp = (struct ar2313_private *)dev->priv;
++ unsigned long flags;
++
++#if DEBUG_TX
++ printk("Tx timeout\n");
++#endif
++ spin_lock_irqsave(&sp->lock, flags);
++ ar2313_restart(dev);
++ spin_unlock_irqrestore(&sp->lock, flags);
++}
++#endif
++
++#if DEBUG_MC
++static void
++printMcList(struct net_device *dev)
++{
++ struct dev_mc_list *list = dev->mc_list;
++ int num=0, i;
++ while(list){
++ printk("%d MC ADDR ", num);
++ for(i=0;i<list->dmi_addrlen;i++) {
++ printk(":%02x", list->dmi_addr[i]);
++ }
++ list = list->next;
++ printk("\n");
++ }
++}
++#endif
++
++/*
++ * Set or clear the multicast filter for this adaptor.
++ * THIS IS ABSOLUTE CRAP, disabled
++ */
++static void
++ar2313_multicast_list(struct net_device *dev)
++{
++ /*
++ * Always listen to broadcasts and
++ * treat IFF bits independently
++ */
++ struct ar2313_private *sp = (struct ar2313_private *)dev->priv;
++ unsigned int recognise;
++
++ recognise = sp->eth_regs->mac_control;
++
++ if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */
++ recognise |= MAC_CONTROL_PR;
++ } else {
++ recognise &= ~MAC_CONTROL_PR;
++ }
++
++ if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 15)) {
++#if DEBUG_MC
++ printMcList(dev);
++ printk("%s: all MULTICAST mc_count %d\n", __FUNCTION__, dev->mc_count);
++#endif
++ recognise |= MAC_CONTROL_PM;/* all multicast */
++ } else if (dev->mc_count > 0) {
++#if DEBUG_MC
++ printMcList(dev);
++ printk("%s: mc_count %d\n", __FUNCTION__, dev->mc_count);
++#endif
++ recognise |= MAC_CONTROL_PM; /* for the time being */
++ }
++#if DEBUG_MC
++ printk("%s: setting %08x to %08x\n", __FUNCTION__, (int)sp->eth_regs, recognise);
++#endif
++
++ sp->eth_regs->mac_control = recognise;
++}
++
++static void rx_tasklet_cleanup(struct net_device *dev)
++{
++ struct ar2313_private *sp = dev->priv;
++
++ /*
++ * Tasklet may be scheduled. Need to get it removed from the list
++ * since we're about to free the struct.
++ */
++
++ sp->unloading = 1;
++ tasklet_enable(&sp->rx_tasklet);
++ tasklet_kill(&sp->rx_tasklet);
++}
++
++static void __exit ar2313_module_cleanup(void)
++{
++ rx_tasklet_cleanup(root_dev);
++ ar2313_init_cleanup(root_dev);
++ unregister_netdev(root_dev);
++ kfree(root_dev);
++ release_region(PHYSADDR(ETHERNET_BASE), ETHERNET_SIZE*ETHERNET_MACS);
++}
++
++
++/*
++ * Restart the AR2313 ethernet controller.
++ */
++static int ar2313_restart(struct net_device *dev)
++{
++ /* disable interrupts */
++ disable_irq(dev->irq);
++
++ /* stop mac */
++ ar2313_halt(dev);
++
++ /* initialize */
++ ar2313_init(dev);
++
++ /* enable interrupts */
++ enable_irq(dev->irq);
++
++ return 0;
++}
++
++extern unsigned long mips_machtype;
++
++int __init ar2313_module_init(void)
++{
++ int status=-1;
++ switch (mips_machtype){
++ case MACH_ARUBA_AP60:
++ case MACH_ARUBA_AP65:
++ case MACH_ARUBA_AP40:
++ root_dev = NULL;
++ status = ar2313_probe();
++ break;
++ }
++ return status;
++}
++
++
++module_init(ar2313_module_init);
++module_exit(ar2313_module_cleanup);
++
++
++static void ar2313_free_descriptors(struct net_device *dev)
++{
++ struct ar2313_private *sp = dev->priv;
++ if (sp->rx_ring != NULL) {
++ kfree((void*)KSEG0ADDR(sp->rx_ring));
++ sp->rx_ring = NULL;
++ sp->tx_ring = NULL;
++ }
++}
++
++
++static int ar2313_allocate_descriptors(struct net_device *dev)
++{
++ struct ar2313_private *sp = dev->priv;
++ int size;
++ int j;
++ ar2313_descr_t *space;
++
++ if(sp->rx_ring != NULL){
++ printk("%s: already done.\n", __FUNCTION__);
++ return 0;
++ }
++
++ size = (sizeof(ar2313_descr_t) * (AR2313_DESCR_ENTRIES * AR2313_QUEUES));
++ space = kmalloc(size, GFP_KERNEL);
++ if (space == NULL)
++ return 1;
++
++ /* invalidate caches */
++ dma_cache_inv((unsigned int)space, size);
++
++ /* now convert pointer to KSEG1 */
++ space = (ar2313_descr_t *)KSEG1ADDR(space);
++
++ memset((void *)space, 0, size);
++
++ sp->rx_ring = space;
++ space += AR2313_DESCR_ENTRIES;
++
++ sp->tx_ring = space;
++ space += AR2313_DESCR_ENTRIES;
++
++ /* Initialize the transmit Descriptors */
++ for (j = 0; j < AR2313_DESCR_ENTRIES; j++) {
++ ar2313_descr_t *td = &sp->tx_ring[j];
++ td->status = 0;
++ td->devcs = DMA_TX1_CHAINED;
++ td->addr = 0;
++ td->descr = K1_TO_PHYS(&sp->tx_ring[(j+1) & (AR2313_DESCR_ENTRIES-1)]);
++ }
++
++ return 0;
++}
++
++
++/*
++ * Generic cleanup handling data allocated during init. Used when the
++ * module is unloaded or if an error occurs during initialization
++ */
++static void ar2313_init_cleanup(struct net_device *dev)
++{
++ struct ar2313_private *sp = dev->priv;
++ struct sk_buff *skb;
++ int j;
++
++ ar2313_free_descriptors(dev);
++
++ if (sp->eth_regs) iounmap((void*)sp->eth_regs);
++ if (sp->dma_regs) iounmap((void*)sp->dma_regs);
++
++ if (sp->rx_skb) {
++ for (j = 0; j < AR2313_DESCR_ENTRIES; j++) {
++ skb = sp->rx_skb[j];
++ if (skb) {
++ sp->rx_skb[j] = NULL;
++ dev_kfree_skb(skb);
++ }
++ }
++ kfree(sp->rx_skb);
++ sp->rx_skb = NULL;
++ }
++
++ if (sp->tx_skb) {
++ for (j = 0; j < AR2313_DESCR_ENTRIES; j++) {
++ skb = sp->tx_skb[j];
++ if (skb) {
++ sp->tx_skb[j] = NULL;
++ dev_kfree_skb(skb);
++ }
++ }
++ kfree(sp->tx_skb);
++ sp->tx_skb = NULL;
++ }
++}
++
++static int ar2313_setup_timer(struct net_device *dev)
++{
++ struct ar2313_private *sp = dev->priv;
++
++ init_timer(&sp->link_timer);
++
++ sp->link_timer.function = ar2313_link_timer_fn;
++ sp->link_timer.data = (int) dev;
++ sp->link_timer.expires = jiffies + HZ;
++
++ add_timer(&sp->link_timer);
++ return 0;
++
++}
++
++static void ar2313_link_timer_fn(unsigned long data)
++{
++ struct net_device *dev = (struct net_device *) data;
++ struct ar2313_private *sp = dev->priv;
++
++ // see if the link status changed
++ // This was needed to make sure we set the PHY to the
++ // autonegotiated value of half or full duplex.
++ ar2313_check_link(dev);
++
++ // Loop faster when we don't have link.
++ // This was needed to speed up the AP bootstrap time.
++ if(sp->link == 0) {
++ mod_timer(&sp->link_timer, jiffies + HZ/2);
++ } else {
++ mod_timer(&sp->link_timer, jiffies + LINK_TIMER);
++ }
++}
++
++static void ar2313_check_link(struct net_device *dev)
++{
++ struct ar2313_private *sp = dev->priv;
++ u16 phyData;
++
++ phyData = armiiread(sp->phy, MII_BMSR);
++ if (sp->phyData != phyData) {
++ if (phyData & BMSR_LSTATUS) {
++ /* link is present, ready link partner ability to deterine duplexity */
++ int duplex = 0;
++ u16 reg;
++
++ sp->link = 1;
++ reg = armiiread(sp->phy, MII_BMCR);
++ if (reg & BMCR_ANENABLE) {
++ /* auto neg enabled */
++ reg = armiiread(sp->phy, MII_LPA);
++ duplex = (reg & (LPA_100FULL|LPA_10FULL))? 1:0;
++ } else {
++ /* no auto neg, just read duplex config */
++ duplex = (reg & BMCR_FULLDPLX)? 1:0;
++ }
++
++ printk(KERN_INFO "%s: Configuring MAC for %s duplex\n", dev->name,
++ (duplex)? "full":"half");
++
++ if (duplex) {
++ /* full duplex */
++ sp->eth_regs->mac_control = ((sp->eth_regs->mac_control | MAC_CONTROL_F) &
++ ~MAC_CONTROL_DRO);
++ } else {
++ /* half duplex */
++ sp->eth_regs->mac_control = ((sp->eth_regs->mac_control | MAC_CONTROL_DRO) &
++ ~MAC_CONTROL_F);
++ }
++ } else {
++ /* no link */
++ sp->link = 0;
++ }
++ sp->phyData = phyData;
++ }
++}
++
++static int
++ar2313_reset_reg(struct net_device *dev)
++{
++ struct ar2313_private *sp = (struct ar2313_private *)dev->priv;
++ unsigned int ethsal, ethsah;
++ unsigned int flags;
++
++ *sp->int_regs |= ar_int_mac_mask;
++ mdelay(10);
++ *sp->int_regs &= ~ar_int_mac_mask;
++ mdelay(10);
++ *sp->int_regs |= ar_int_phy_mask;
++ mdelay(10);
++ *sp->int_regs &= ~ar_int_phy_mask;
++ mdelay(10);
++
++ sp->dma_regs->bus_mode = (DMA_BUS_MODE_SWR);
++ mdelay(10);
++ sp->dma_regs->bus_mode = ((32 << DMA_BUS_MODE_PBL_SHIFT) | DMA_BUS_MODE_BLE);
++
++ /* enable interrupts */
++ sp->dma_regs->intr_ena = (DMA_STATUS_AIS |
++ DMA_STATUS_NIS |
++ DMA_STATUS_RI |
++ DMA_STATUS_TI |
++ DMA_STATUS_FBE);
++ sp->dma_regs->xmt_base = K1_TO_PHYS(sp->tx_ring);
++ sp->dma_regs->rcv_base = K1_TO_PHYS(sp->rx_ring);
++ sp->dma_regs->control = (DMA_CONTROL_SR | DMA_CONTROL_ST | DMA_CONTROL_SF);
++
++ sp->eth_regs->flow_control = (FLOW_CONTROL_FCE);
++ sp->eth_regs->vlan_tag = (0x8100);
++
++ /* Enable Ethernet Interface */
++ flags = (MAC_CONTROL_TE | /* transmit enable */
++ MAC_CONTROL_PM | /* pass mcast */
++ MAC_CONTROL_F | /* full duplex */
++ MAC_CONTROL_HBD); /* heart beat disabled */
++
++ if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */
++ flags |= MAC_CONTROL_PR;
++ }
++ sp->eth_regs->mac_control = flags;
++
++ /* Set all Ethernet station address registers to their initial values */
++ ethsah = ((((u_int)(dev->dev_addr[5]) << 8) & (u_int)0x0000FF00) |
++ (((u_int)(dev->dev_addr[4]) << 0) & (u_int)0x000000FF));
++
++ ethsal = ((((u_int)(dev->dev_addr[3]) << 24) & (u_int)0xFF000000) |
++ (((u_int)(dev->dev_addr[2]) << 16) & (u_int)0x00FF0000) |
++ (((u_int)(dev->dev_addr[1]) << 8) & (u_int)0x0000FF00) |
++ (((u_int)(dev->dev_addr[0]) << 0) & (u_int)0x000000FF) );
++
++ sp->eth_regs->mac_addr[0] = ethsah;
++ sp->eth_regs->mac_addr[1] = ethsal;
++
++ mdelay(10);
++
++ return(0);
++}
++
++
++static int ar2313_init(struct net_device *dev)
++{
++ struct ar2313_private *sp = dev->priv;
++ int ecode=0;
++
++ /*
++ * Allocate descriptors
++ */
++ if (ar2313_allocate_descriptors(dev)) {
++ printk("%s: %s: ar2313_allocate_descriptors failed\n",
++ dev->name, __FUNCTION__);
++ ecode = -EAGAIN;
++ goto init_error;
++ }
++
++ /*
++ * Get the memory for the skb rings.
++ */
++ if(sp->rx_skb == NULL) {
++ sp->rx_skb = kmalloc(sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES, GFP_KERNEL);
++ if (!(sp->rx_skb)) {
++ printk("%s: %s: rx_skb kmalloc failed\n",
++ dev->name, __FUNCTION__);
++ ecode = -EAGAIN;
++ goto init_error;
++ }
++ }
++ memset(sp->rx_skb, 0, sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES);
++
++ if(sp->tx_skb == NULL) {
++ sp->tx_skb = kmalloc(sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES, GFP_KERNEL);
++ if (!(sp->tx_skb)) {
++ printk("%s: %s: tx_skb kmalloc failed\n",
++ dev->name, __FUNCTION__);
++ ecode = -EAGAIN;
++ goto init_error;
++ }
++ }
++ memset(sp->tx_skb, 0, sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES);
++
++ /*
++ * Set tx_csm before we start receiving interrupts, otherwise
++ * the interrupt handler might think it is supposed to process
++ * tx ints before we are up and running, which may cause a null
++ * pointer access in the int handler.
++ */
++ sp->rx_skbprd = 0;
++ sp->cur_rx = 0;
++ sp->tx_prd = 0;
++ sp->tx_csm = 0;
++
++ /*
++ * Zero the stats before starting the interface
++ */
++ memset(&sp->stats, 0, sizeof(sp->stats));
++
++ /*
++ * We load the ring here as there seem to be no way to tell the
++ * firmware to wipe the ring without re-initializing it.
++ */
++ ar2313_load_rx_ring(dev, RX_RING_SIZE);
++
++ /*
++ * Init hardware
++ */
++ ar2313_reset_reg(dev);
++
++ /*
++ * Get the IRQ
++ */
++ ecode = request_irq(dev->irq, &ar2313_interrupt, SA_SHIRQ | SA_INTERRUPT, dev->name, dev);
++ if (ecode) {
++ printk(KERN_WARNING "%s: %s: Requested IRQ %d is busy\n",
++ dev->name, __FUNCTION__, dev->irq);
++ goto init_error;
++ }
++
++#if 0
++ // commented out, for now
++
++ if(mips_machtype == MACH_ARUBA_SAMSUNG) {
++ int i;
++ /* configure Marvell 88E6060 */
++ /* reset chip */
++ armiiwrite(0x1f, 0xa, 0xa130);
++ do {
++ udelay(1000);
++ i = armiiread(sp->phy, 0xa);
++ } while (i & 0x8000);
++
++ /* configure MAC address */
++ armiiwrite(sp->phy, 0x1, dev->dev_addr[0] << 8 | dev->dev_addr[1]);
++ armiiwrite(sp->phy, 0x2, dev->dev_addr[2] << 8 | dev->dev_addr[3]);
++ armiiwrite(sp->phy, 0x3, dev->dev_addr[4] << 8 | dev->dev_addr[5]);
++
++ /* set ports to forwarding */
++ armiiwrite(0x18, 0x4, 0x3);
++ armiiwrite(0x1c, 0x4, 0x3);
++ armiiwrite(0x1d, 0x4, 0x3);
++ }
++#endif
++
++ tasklet_enable(&sp->rx_tasklet);
++
++ return 0;
++
++ init_error:
++ ar2313_init_cleanup(dev);
++ return ecode;
++}
++
++/*
++ * Load the rx ring.
++ *
++ * Loading rings is safe without holding the spin lock since this is
++ * done only before the device is enabled, thus no interrupts are
++ * generated and by the interrupt handler/tasklet handler.
++ */
++static void ar2313_load_rx_ring(struct net_device *dev, int nr_bufs)
++{
++
++ struct ar2313_private *sp = ((struct net_device *)dev)->priv;
++ short i, idx;
++
++ idx = sp->rx_skbprd;
++
++ for (i = 0; i < nr_bufs; i++) {
++ struct sk_buff *skb;
++ ar2313_descr_t *rd;
++
++ if (sp->rx_skb[idx]) {
++#if DEBUG_RX
++ printk(KERN_INFO "ar2313 rx refill full\n");
++#endif /* DEBUG */
++ break;
++ }
++
++ // partha: create additional room for the second GRE fragment
++ skb = alloc_skb(AR2313_BUFSIZE+128, GFP_ATOMIC);
++ if (!skb) {
++ printk("\n\n\n\n %s: No memory in system\n\n\n\n", __FUNCTION__);
++ break;
++ }
++ // partha: create additional room in the front for tx pkt capture
++ skb_reserve(skb, 32);
++
++ /*
++ * Make sure IP header starts on a fresh cache line.
++ */
++ skb->dev = dev;
++ skb_reserve(skb, RX_OFFSET);
++ sp->rx_skb[idx] = skb;
++
++ rd = (ar2313_descr_t *) &sp->rx_ring[idx];
++
++ /* initialize dma descriptor */
++ rd->devcs = ((AR2313_BUFSIZE << DMA_RX1_BSIZE_SHIFT) |
++ DMA_RX1_CHAINED);
++ rd->addr = virt_to_phys(skb->data);
++ rd->descr = virt_to_phys(&sp->rx_ring[(idx+1) & (AR2313_DESCR_ENTRIES-1)]);
++ rd->status = DMA_RX_OWN;
++
++ idx = DSC_NEXT(idx);
++ }
++
++ if (!i) {
++#if DEBUG_ERR
++ printk(KERN_INFO "Out of memory when allocating standard receive buffers\n");
++#endif /* DEBUG */
++ } else {
++ sp->rx_skbprd = idx;
++ }
++
++ return;
++}
++
++#define AR2313_MAX_PKTS_PER_CALL 64
++
++static int ar2313_rx_int(struct net_device *dev)
++{
++ struct ar2313_private *sp = dev->priv;
++ struct sk_buff *skb, *skb_new;
++ ar2313_descr_t *rxdesc;
++ unsigned int status;
++ u32 idx;
++ int pkts = 0;
++ int rval;
++
++ idx = sp->cur_rx;
++
++ /* process at most the entire ring and then wait for another interrupt */
++ while(1) {
++
++ rxdesc = &sp->rx_ring[idx];
++ status = rxdesc->status;
++ if (status & DMA_RX_OWN) {
++ /* SiByte owns descriptor or descr not yet filled in */
++ rval = 0;
++ break;
++ }
++
++ if (++pkts > AR2313_MAX_PKTS_PER_CALL) {
++ rval = 1;
++ break;
++ }
++
++#if DEBUG_RX
++ printk("index %d\n", idx);
++ printk("RX status %08x\n", rxdesc->status);
++ printk("RX devcs %08x\n", rxdesc->devcs );
++ printk("RX addr %08x\n", rxdesc->addr );
++ printk("RX descr %08x\n", rxdesc->descr );
++#endif
++
++ if ((status & (DMA_RX_ERROR|DMA_RX_ERR_LENGTH)) &&
++ (!(status & DMA_RX_LONG))){
++#if DEBUG_RX
++ printk("%s: rx ERROR %08x\n", __FUNCTION__, status);
++#endif
++ sp->stats.rx_errors++;
++ sp->stats.rx_dropped++;
++
++ /* add statistics counters */
++ if (status & DMA_RX_ERR_CRC) sp->stats.rx_crc_errors++;
++ if (status & DMA_RX_ERR_COL) sp->stats.rx_over_errors++;
++ if (status & DMA_RX_ERR_LENGTH)
++ sp->stats.rx_length_errors++;
++ if (status & DMA_RX_ERR_RUNT) sp->stats.rx_over_errors++;
++ if (status & DMA_RX_ERR_DESC) sp->stats.rx_over_errors++;
++
++ } else {
++ /* alloc new buffer. */
++ skb_new = dev_alloc_skb(AR2313_BUFSIZE + RX_OFFSET + 128);
++ if (skb_new != NULL) {
++
++ skb = sp->rx_skb[idx];
++ /* set skb */
++ skb_put(skb, ((status >> DMA_RX_LEN_SHIFT) & 0x3fff) - CRC_LEN);
++
++#ifdef CONFIG_MERLOT
++ if ((dev->am_pkt_handler == NULL) ||
++ (dev->am_pkt_handler(skb, dev) == 0)) {
++#endif
++ sp->stats.rx_bytes += skb->len;
++ skb->protocol = eth_type_trans(skb, dev);
++ /* pass the packet to upper layers */
++
++#ifdef CONFIG_MERLOT
++ if (dev->asap_netif_rx)
++ dev->asap_netif_rx(skb);
++ else
++#endif
++ netif_rx(skb);
++#ifdef CONFIG_MERLOT
++ }
++#endif
++ skb_new->dev = dev;
++ /* 16 bit align */
++ skb_reserve(skb_new, RX_OFFSET+32);
++ /* reset descriptor's curr_addr */
++ rxdesc->addr = virt_to_phys(skb_new->data);
++
++ sp->stats.rx_packets++;
++ sp->rx_skb[idx] = skb_new;
++
++ } else {
++ sp->stats.rx_dropped++;
++ }
++ }
++
++ rxdesc->devcs = ((AR2313_BUFSIZE << DMA_RX1_BSIZE_SHIFT) |
++ DMA_RX1_CHAINED);
++ rxdesc->status = DMA_RX_OWN;
++
++ idx = DSC_NEXT(idx);
++ }
++
++ sp->cur_rx = idx;
++
++ return rval;
++}
++
++
++static void ar2313_tx_int(struct net_device *dev)
++{
++ struct ar2313_private *sp = dev->priv;
++ u32 idx;
++ struct sk_buff *skb;
++ ar2313_descr_t *txdesc;
++ unsigned int status=0;
++
++ idx = sp->tx_csm;
++
++ while (idx != sp->tx_prd) {
++
++ txdesc = &sp->tx_ring[idx];
++
++#if DEBUG_TX
++ printk("%s: TXINT: csm=%d idx=%d prd=%d status=%x devcs=%x addr=%08x descr=%x\n",
++ dev->name, sp->tx_csm, idx, sp->tx_prd,
++ txdesc->status, txdesc->devcs, txdesc->addr, txdesc->descr);
++#endif /* DEBUG */
++
++ if ((status = txdesc->status) & DMA_TX_OWN) {
++ /* ar2313 dma still owns descr */
++ break;
++ }
++ /* done with this descriptor */
++ txdesc->status = 0;
++
++ if (status & DMA_TX_ERROR){
++ sp->stats.tx_errors++;
++ sp->stats.tx_dropped++;
++ if(status & DMA_TX_ERR_UNDER)
++ sp->stats.tx_fifo_errors++;
++ if(status & DMA_TX_ERR_HB)
++ sp->stats.tx_heartbeat_errors++;
++ if(status & (DMA_TX_ERR_LOSS |
++ DMA_TX_ERR_LINK))
++ sp->stats.tx_carrier_errors++;
++ if (status & (DMA_TX_ERR_LATE|
++ DMA_TX_ERR_COL |
++ DMA_TX_ERR_JABBER |
++ DMA_TX_ERR_DEFER))
++ sp->stats.tx_aborted_errors++;
++ } else {
++ /* transmit OK */
++ sp->stats.tx_packets++;
++ }
++
++ skb = sp->tx_skb[idx];
++ sp->tx_skb[idx] = NULL;
++ idx = DSC_NEXT(idx);
++ sp->stats.tx_bytes += skb->len;
++ dev_kfree_skb_irq(skb);
++ }
++
++ sp->tx_csm = idx;
++
++ return;
++}
++
++
++static void
++rx_tasklet_func(unsigned long data)
++{
++ struct net_device *dev = (struct net_device *) data;
++ struct ar2313_private *sp = dev->priv;
++
++ if (sp->unloading) {
++ return;
++ }
++
++ if (ar2313_rx_int(dev)) {
++ tasklet_hi_schedule(&sp->rx_tasklet);
++ }
++ else {
++ unsigned long flags;
++ spin_lock_irqsave(&sp->lock, flags);
++ sp->dma_regs->intr_ena |= DMA_STATUS_RI;
++ spin_unlock_irqrestore(&sp->lock, flags);
++ }
++}
++
++static void
++rx_schedule(struct net_device *dev)
++{
++ struct ar2313_private *sp = dev->priv;
++
++ sp->dma_regs->intr_ena &= ~DMA_STATUS_RI;
++
++ tasklet_hi_schedule(&sp->rx_tasklet);
++}
++
++static irqreturn_t ar2313_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
++{
++ struct net_device *dev = (struct net_device *)dev_id;
++ struct ar2313_private *sp = dev->priv;
++ unsigned int status, enabled;
++
++ /* clear interrupt */
++ /*
++ * Don't clear RI bit if currently disabled.
++ */
++ status = sp->dma_regs->status;
++ enabled = sp->dma_regs->intr_ena;
++ sp->dma_regs->status = status & enabled;
++
++ if (status & DMA_STATUS_NIS) {
++ /* normal status */
++ /*
++ * Don't schedule rx processing if interrupt
++ * is already disabled.
++ */
++ if (status & enabled & DMA_STATUS_RI) {
++ /* receive interrupt */
++ rx_schedule(dev);
++ }
++ if (status & DMA_STATUS_TI) {
++ /* transmit interrupt */
++ ar2313_tx_int(dev);
++ }
++ }
++
++ if (status & DMA_STATUS_AIS) {
++#if DEBUG_INT
++ printk("%s: AIS set %08x & %x\n", __FUNCTION__,
++ status, (DMA_STATUS_FBE | DMA_STATUS_TPS));
++#endif
++ /* abnormal status */
++ if (status & (DMA_STATUS_FBE | DMA_STATUS_TPS)) {
++ ar2313_restart(dev);
++ }
++ }
++ return IRQ_HANDLED;
++}
++
++
++static int ar2313_open(struct net_device *dev)
++{
++ struct ar2313_private *sp;
++
++ sp = dev->priv;
++
++ dev->mtu = 1500;
++ netif_start_queue(dev);
++
++ sp->eth_regs->mac_control |= MAC_CONTROL_RE;
++
++ AR2313_MOD_INC_USE_COUNT;
++
++ return 0;
++}
++
++static void ar2313_halt(struct net_device *dev)
++{
++ struct ar2313_private *sp = dev->priv;
++ int j;
++
++ tasklet_disable(&sp->rx_tasklet);
++
++ /* kill the MAC */
++ sp->eth_regs->mac_control &= ~(MAC_CONTROL_RE | /* disable Receives */
++ MAC_CONTROL_TE); /* disable Transmits */
++ /* stop dma */
++ sp->dma_regs->control = 0;
++ sp->dma_regs->bus_mode = DMA_BUS_MODE_SWR;
++
++ /* place phy and MAC in reset */
++ *sp->int_regs |= (ar_int_mac_mask | ar_int_phy_mask);
++
++ /* free buffers on tx ring */
++ for (j = 0; j < AR2313_DESCR_ENTRIES; j++) {
++ struct sk_buff *skb;
++ ar2313_descr_t *txdesc;
++
++ txdesc = &sp->tx_ring[j];
++ txdesc->descr = 0;
++
++ skb = sp->tx_skb[j];
++ if (skb) {
++ dev_kfree_skb(skb);
++ sp->tx_skb[j] = NULL;
++ }
++ }
++}
++
++/*
++ * close should do nothing. Here's why. It's called when
++ * 'ifconfig bond0 down' is run. If it calls free_irq then
++ * the irq is gone forever ! When bond0 is made 'up' again,
++ * the ar2313_open () does not call request_irq (). Worse,
++ * the call to ar2313_halt() generates a WDOG reset due to
++ * the write to 'sp->int_regs' and the box reboots.
++ * Commenting this out is good since it allows the
++ * system to resume when bond0 is made up again.
++ */
++static int ar2313_close(struct net_device *dev)
++{
++#if 0
++ /*
++ * Disable interrupts
++ */
++ disable_irq(dev->irq);
++
++ /*
++ * Without (or before) releasing irq and stopping hardware, this
++ * is an absolute non-sense, by the way. It will be reset instantly
++ * by the first irq.
++ */
++ netif_stop_queue(dev);
++
++ /* stop the MAC and DMA engines */
++ ar2313_halt(dev);
++
++ /* release the interrupt */
++ free_irq(dev->irq, dev);
++
++#endif
++ AR2313_MOD_DEC_USE_COUNT;
++ return 0;
++}
++
++static int ar2313_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ struct ar2313_private *sp = dev->priv;
++ ar2313_descr_t *td;
++ u32 idx;
++
++ idx = sp->tx_prd;
++ td = &sp->tx_ring[idx];
++
++ if (td->status & DMA_TX_OWN) {
++#if DEBUG_TX
++ printk("%s: No space left to Tx\n", __FUNCTION__);
++#endif
++ /* free skbuf and lie to the caller that we sent it out */
++ sp->stats.tx_dropped++;
++ dev_kfree_skb(skb);
++
++ /* restart transmitter in case locked */
++ sp->dma_regs->xmt_poll = 0;
++ return 0;
++ }
++
++ /* Setup the transmit descriptor. */
++ td->devcs = ((skb->len << DMA_TX1_BSIZE_SHIFT) |
++ (DMA_TX1_LS|DMA_TX1_IC|DMA_TX1_CHAINED));
++ td->addr = virt_to_phys(skb->data);
++ td->status = DMA_TX_OWN;
++
++ /* kick transmitter last */
++ sp->dma_regs->xmt_poll = 0;
++
++#if DEBUG_TX
++ printk("index %d\n", idx);
++ printk("TX status %08x\n", td->status);
++ printk("TX devcs %08x\n", td->devcs );
++ printk("TX addr %08x\n", td->addr );
++ printk("TX descr %08x\n", td->descr );
++#endif
++
++ sp->tx_skb[idx] = skb;
++ idx = DSC_NEXT(idx);
++ sp->tx_prd = idx;
++
++ //dev->trans_start = jiffies;
++
++ return 0;
++}
++
++static int netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
++{
++ struct ar2313_private *np = dev->priv;
++ u32 tmp;
++
++ ecmd->supported =
++ (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
++ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
++ SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
++
++ ecmd->port = PORT_TP;
++ /* only supports internal transceiver */
++ ecmd->transceiver = XCVR_INTERNAL;
++ /* not sure what this is for */
++ ecmd->phy_address = 1;
++
++ ecmd->advertising = ADVERTISED_MII;
++ tmp = armiiread(np->phy, MII_ADVERTISE);
++ if (tmp & ADVERTISE_10HALF)
++ ecmd->advertising |= ADVERTISED_10baseT_Half;
++ if (tmp & ADVERTISE_10FULL)
++ ecmd->advertising |= ADVERTISED_10baseT_Full;
++ if (tmp & ADVERTISE_100HALF)
++ ecmd->advertising |= ADVERTISED_100baseT_Half;
++ if (tmp & ADVERTISE_100FULL)
++ ecmd->advertising |= ADVERTISED_100baseT_Full;
++
++ tmp = armiiread(np->phy, MII_BMCR);
++ if (tmp & BMCR_ANENABLE) {
++ ecmd->advertising |= ADVERTISED_Autoneg;
++ ecmd->autoneg = AUTONEG_ENABLE;
++ } else {
++ ecmd->autoneg = AUTONEG_DISABLE;
++ }
++
++ if (ecmd->autoneg == AUTONEG_ENABLE) {
++ tmp = armiiread(np->phy, MII_LPA);
++ if (tmp & (LPA_100FULL|LPA_10FULL)) {
++ ecmd->duplex = DUPLEX_FULL;
++ } else {
++ ecmd->duplex = DUPLEX_HALF;
++ }
++ if (tmp & (LPA_100FULL|LPA_100HALF)) {
++ ecmd->speed = SPEED_100;
++ } else {
++ ecmd->speed = SPEED_10;
++ }
++ } else {
++ if (tmp & BMCR_FULLDPLX) {
++ ecmd->duplex = DUPLEX_FULL;
++ } else {
++ ecmd->duplex = DUPLEX_HALF;
++ }
++ if (tmp & BMCR_SPEED100) {
++ ecmd->speed = SPEED_100;
++ } else {
++ ecmd->speed = SPEED_10;
++ }
++ }
++
++ /* ignore maxtxpkt, maxrxpkt for now */
++
++ return 0;
++}
++
++static int netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
++{
++ struct ar2313_private *np = dev->priv;
++ u32 tmp;
++
++ if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100)
++ return -EINVAL;
++ if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
++ return -EINVAL;
++ if (ecmd->port != PORT_TP)
++ return -EINVAL;
++ if (ecmd->transceiver != XCVR_INTERNAL)
++ return -EINVAL;
++ if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
++ return -EINVAL;
++ /* ignore phy_address, maxtxpkt, maxrxpkt for now */
++
++ /* WHEW! now lets bang some bits */
++
++ tmp = armiiread(np->phy, MII_BMCR);
++ if (ecmd->autoneg == AUTONEG_ENABLE) {
++ /* turn on autonegotiation */
++ tmp |= BMCR_ANENABLE;
++ printk("%s: Enabling auto-neg\n", dev->name);
++ } else {
++ /* turn off auto negotiation, set speed and duplexity */
++ tmp &= ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX);
++ if (ecmd->speed == SPEED_100)
++ tmp |= BMCR_SPEED100;
++ if (ecmd->duplex == DUPLEX_FULL)
++ tmp |= BMCR_FULLDPLX;
++ printk("%s: Hard coding %d/%s\n", dev->name,
++ (ecmd->speed == SPEED_100)? 100:10,
++ (ecmd->duplex == DUPLEX_FULL)? "full":"half");
++ }
++ armiiwrite(np->phy, MII_BMCR, tmp);
++ np->phyData = 0;
++ return 0;
++}
++
++static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
++{
++ struct ar2313_private *np = dev->priv;
++ u32 cmd;
++
++ if (get_user(cmd, (u32 *)useraddr))
++ return -EFAULT;
++
++ switch (cmd) {
++ /* get settings */
++ case ETHTOOL_GSET: {
++ struct ethtool_cmd ecmd = { ETHTOOL_GSET };
++ spin_lock_irq(&np->lock);
++ netdev_get_ecmd(dev, &ecmd);
++ spin_unlock_irq(&np->lock);
++ if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
++ return -EFAULT;
++ return 0;
++ }
++ /* set settings */
++ case ETHTOOL_SSET: {
++ struct ethtool_cmd ecmd;
++ int r;
++ if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
++ return -EFAULT;
++ spin_lock_irq(&np->lock);
++ r = netdev_set_ecmd(dev, &ecmd);
++ spin_unlock_irq(&np->lock);
++ return r;
++ }
++ /* restart autonegotiation */
++ case ETHTOOL_NWAY_RST: {
++ int tmp;
++ int r = -EINVAL;
++ /* if autoneg is off, it's an error */
++ tmp = armiiread(np->phy, MII_BMCR);
++ if (tmp & BMCR_ANENABLE) {
++ tmp |= (BMCR_ANRESTART);
++ armiiwrite(np->phy, MII_BMCR, tmp);
++ r = 0;
++ }
++ return r;
++ }
++ /* get link status */
++ case ETHTOOL_GLINK: {
++ struct ethtool_value edata = {ETHTOOL_GLINK};
++ edata.data = (armiiread(np->phy, MII_BMSR)&BMSR_LSTATUS) ? 1:0;
++ if (copy_to_user(useraddr, &edata, sizeof(edata)))
++ return -EFAULT;
++ return 0;
++ }
++ }
++
++ return -EOPNOTSUPP;
++}
++
++static int ar2313_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
++{
++ struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data;
++
++ switch (cmd) {
++ case SIOCDEVPRIVATE: {
++ struct ar2313_cmd scmd;
++
++ if (copy_from_user(&scmd, ifr->ifr_data, sizeof(scmd)))
++ return -EFAULT;
++
++#if DEBUG
++ printk("%s: ioctl devprivate c=%d a=%x l=%d m=%d d=%x,%x\n",
++ dev->name, scmd.cmd,
++ scmd.address, scmd.length,
++ scmd.mailbox, scmd.data[0], scmd.data[1]);
++#endif /* DEBUG */
++
++ switch (scmd.cmd) {
++ case AR2313_READ_DATA:
++ if(scmd.length==4){
++ scmd.data[0] = *((u32*)scmd.address);
++ } else if(scmd.length==2) {
++ scmd.data[0] = *((u16*)scmd.address);
++ } else if (scmd.length==1) {
++ scmd.data[0] = *((u8*)scmd.address);
++ } else {
++ return -EOPNOTSUPP;
++ }
++ if(copy_to_user(ifr->ifr_data, &scmd, sizeof(scmd)))
++ return -EFAULT;
++ break;
++
++ case AR2313_WRITE_DATA:
++ if(scmd.length==4){
++ *((u32*)scmd.address) = scmd.data[0];
++ } else if(scmd.length==2) {
++ *((u16*)scmd.address) = scmd.data[0];
++ } else if (scmd.length==1) {
++ *((u8*)scmd.address) = scmd.data[0];
++ } else {
++ return -EOPNOTSUPP;
++ }
++ break;
++
++ case AR2313_GET_VERSION:
++ // SAMEER: sprintf((char*) &scmd, "%s", ARUBA_VERSION);
++ if(copy_to_user(ifr->ifr_data, &scmd, sizeof(scmd)))
++ return -EFAULT;
++ break;
++
++ default:
++ return -EOPNOTSUPP;
++ }
++ return 0;
++ }
++
++ case SIOCETHTOOL:
++ return netdev_ethtool_ioctl(dev, (void *) ifr->ifr_data);
++
++ case SIOCGMIIPHY: /* Get address of MII PHY in use. */
++ data->phy_id = 1;
++ /* Fall Through */
++
++ case SIOCGMIIREG: /* Read MII PHY register. */
++ case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */
++ data->val_out = armiiread(data->phy_id & 0x1f,
++ data->reg_num & 0x1f);
++ return 0;
++ case SIOCSMIIREG: /* Write MII PHY register. */
++ case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */
++ if (!capable(CAP_NET_ADMIN))
++ return -EPERM;
++ armiiwrite(data->phy_id & 0x1f,
++ data->reg_num & 0x1f, data->val_in);
++ return 0;
++
++ case SIOCSIFHWADDR:
++ if (copy_from_user(dev->dev_addr, ifr->ifr_data, sizeof(dev->dev_addr)))
++ return -EFAULT;
++ return 0;
++
++ case SIOCGIFHWADDR:
++ if (copy_to_user(ifr->ifr_data, dev->dev_addr, sizeof(dev->dev_addr)))
++ return -EFAULT;
++ return 0;
++
++ default:
++ break;
++ }
++
++ return -EOPNOTSUPP;
++}
++
++static struct net_device_stats *ar2313_get_stats(struct net_device *dev)
++{
++ struct ar2313_private *sp = dev->priv;
++ return &sp->stats;
++}
++
++static short
++armiiread(short phy, short reg)
++{
++ volatile ETHERNET_STRUCT * ethernet;
++
++ ethernet = (volatile ETHERNET_STRUCT *)ETHERNET_BASE; /* always MAC 0 */
++ ethernet->mii_addr = ((reg << MII_ADDR_REG_SHIFT) |
++ (phy << MII_ADDR_PHY_SHIFT));
++ while (ethernet->mii_addr & MII_ADDR_BUSY);
++ return (ethernet->mii_data >> MII_DATA_SHIFT);
++}
++
++static void
++armiiwrite(short phy, short reg, short data)
++{
++ volatile ETHERNET_STRUCT * ethernet;
++
++ ethernet = (volatile ETHERNET_STRUCT *)ETHERNET_BASE; /* always MAC 0 */
++ while (ethernet->mii_addr & MII_ADDR_BUSY);
++ ethernet->mii_data = data << MII_DATA_SHIFT;
++ ethernet->mii_addr = ((reg << MII_ADDR_REG_SHIFT) |
++ (phy << MII_ADDR_PHY_SHIFT) |
++ MII_ADDR_WRITE);
++}
++
+diff -Nur linux-2.6.17/drivers/net/ar2313/ar2313.h linux-2.6.17-owrt/drivers/net/ar2313/ar2313.h
+--- linux-2.6.17/drivers/net/ar2313/ar2313.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/drivers/net/ar2313/ar2313.h 2006-06-19 12:05:29.000000000 +0200
+@@ -0,0 +1,190 @@
++#ifndef _AR2313_H_
++#define _AR2313_H_
++
++#include <linux/config.h>
++#include <asm/bootinfo.h>
++#include "platform.h"
++
++extern unsigned long mips_machtype;
++
++#undef ETHERNET_BASE
++#define ETHERNET_BASE ar_eth_base
++#define ETHERNET_SIZE 0x00100000
++#define ETHERNET_MACS 2
++
++#undef DMA_BASE
++#define DMA_BASE ar_dma_base
++#define DMA_SIZE 0x00100000
++
++
++/*
++ * probe link timer - 5 secs
++ */
++#define LINK_TIMER (5*HZ)
++
++/*
++ * Interrupt register base address
++ */
++#define INTERRUPT_BASE PHYS_TO_K1(ar_int_base)
++
++/*
++ * Reset Register
++ */
++#define AR531X_RESET (AR531X_RESETTMR + 0x0020)
++#define RESET_SYSTEM 0x00000001 /* cold reset full system */
++#define RESET_PROC 0x00000002 /* cold reset MIPS core */
++#define RESET_WLAN0 0x00000004 /* cold reset WLAN MAC and BB */
++#define RESET_EPHY0 0x00000008 /* cold reset ENET0 phy */
++#define RESET_EPHY1 0x00000010 /* cold reset ENET1 phy */
++#define RESET_ENET0 0x00000020 /* cold reset ENET0 mac */
++#define RESET_ENET1 0x00000040 /* cold reset ENET1 mac */
++
++#define IS_DMA_TX_INT(X) (((X) & (DMA_STATUS_TI)) != 0)
++#define IS_DMA_RX_INT(X) (((X) & (DMA_STATUS_RI)) != 0)
++#define IS_DRIVER_OWNED(X) (((X) & (DMA_TX_OWN)) == 0)
++
++#ifndef K1_TO_PHYS
++// hack
++#define K1_TO_PHYS(x) (((unsigned int)(x)) & 0x1FFFFFFF) /* kseg1 to physical */
++#endif
++
++#ifndef PHYS_TO_K1
++// hack
++#define PHYS_TO_K1(x) (((unsigned int)(x)) | 0xA0000000) /* physical to kseg1 */
++#endif
++
++#define AR2313_TX_TIMEOUT (HZ/4)
++
++/*
++ * Rings
++ */
++#define DSC_RING_ENTRIES_SIZE (AR2313_DESCR_ENTRIES * sizeof(struct desc))
++#define DSC_NEXT(idx) ((idx + 1) & (AR2313_DESCR_ENTRIES - 1))
++
++static inline int tx_space (u32 csm, u32 prd)
++{
++ return (csm - prd - 1) & (AR2313_DESCR_ENTRIES - 1);
++}
++
++#if MAX_SKB_FRAGS
++#define TX_RESERVED (MAX_SKB_FRAGS+1) /* +1 for message header */
++#define tx_ring_full(csm, prd) (tx_space(csm, prd) <= TX_RESERVED)
++#else
++#define tx_ring_full 0
++#endif
++
++#define AR2313_MBGET 2
++#define AR2313_MBSET 3
++#define AR2313_PCI_RECONFIG 4
++#define AR2313_PCI_DUMP 5
++#define AR2313_TEST_PANIC 6
++#define AR2313_TEST_NULLPTR 7
++#define AR2313_READ_DATA 8
++#define AR2313_WRITE_DATA 9
++#define AR2313_GET_VERSION 10
++#define AR2313_TEST_HANG 11
++#define AR2313_SYNC 12
++
++
++struct ar2313_cmd {
++ u32 cmd;
++ u32 address; /* virtual address of image */
++ u32 length; /* size of image to download */
++ u32 mailbox; /* mailbox to get/set */
++ u32 data[2]; /* contents of mailbox to read/write */
++};
++
++
++/*
++ * Struct private for the Sibyte.
++ *
++ * Elements are grouped so variables used by the tx handling goes
++ * together, and will go into the same cache lines etc. in order to
++ * avoid cache line contention between the rx and tx handling on SMP.
++ *
++ * Frequently accessed variables are put at the beginning of the
++ * struct to help the compiler generate better/shorter code.
++ */
++struct ar2313_private
++{
++ int version;
++ u32 mb[2];
++
++ volatile ETHERNET_STRUCT *eth_regs;
++ volatile DMA *dma_regs;
++ volatile u32 *int_regs;
++
++ spinlock_t lock; /* Serialise access to device */
++
++ /*
++ * RX and TX descriptors, must be adjacent
++ */
++ ar2313_descr_t *rx_ring;
++ ar2313_descr_t *tx_ring;
++
++
++ struct sk_buff **rx_skb;
++ struct sk_buff **tx_skb;
++
++ /*
++ * RX elements
++ */
++ u32 rx_skbprd;
++ u32 cur_rx;
++
++ /*
++ * TX elements
++ */
++ u32 tx_prd;
++ u32 tx_csm;
++
++ /*
++ * Misc elements
++ */
++ int board_idx;
++ char name[48];
++ struct net_device_stats stats;
++ struct {
++ u32 address;
++ u32 length;
++ char *mapping;
++ } desc;
++
++
++ struct timer_list link_timer;
++ unsigned short phy; /* merlot phy = 1, samsung phy = 0x1f */
++ unsigned short mac;
++ unsigned short link; /* 0 - link down, 1 - link up */
++ u16 phyData;
++
++ struct tasklet_struct rx_tasklet;
++ int unloading;
++};
++
++
++/*
++ * Prototypes
++ */
++static int ar2313_init(struct net_device *dev);
++#ifdef TX_TIMEOUT
++static void ar2313_tx_timeout(struct net_device *dev);
++#endif
++#if 0
++static void ar2313_multicast_list(struct net_device *dev);
++#endif
++static int ar2313_restart(struct net_device *dev);
++#if DEBUG
++static void ar2313_dump_regs(struct net_device *dev);
++#endif
++static void ar2313_load_rx_ring(struct net_device *dev, int bufs);
++static irqreturn_t ar2313_interrupt(int irq, void *dev_id, struct pt_regs *regs);
++static int ar2313_open(struct net_device *dev);
++static int ar2313_start_xmit(struct sk_buff *skb, struct net_device *dev);
++static int ar2313_close(struct net_device *dev);
++static int ar2313_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
++static void ar2313_init_cleanup(struct net_device *dev);
++static int ar2313_setup_timer(struct net_device *dev);
++static void ar2313_link_timer_fn(unsigned long data);
++static void ar2313_check_link(struct net_device *dev);
++static struct net_device_stats *ar2313_get_stats(struct net_device *dev);
++#endif /* _AR2313_H_ */
+diff -Nur linux-2.6.17/drivers/net/ar2313/ar2313_msg.h linux-2.6.17-owrt/drivers/net/ar2313/ar2313_msg.h
+--- linux-2.6.17/drivers/net/ar2313/ar2313_msg.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/drivers/net/ar2313/ar2313_msg.h 2006-06-19 12:05:29.000000000 +0200
+@@ -0,0 +1,17 @@
++#ifndef _AR2313_MSG_H_
++#define _AR2313_MSG_H_
++
++#define AR2313_MTU 1692
++#define AR2313_PRIOS 1
++#define AR2313_QUEUES (2*AR2313_PRIOS)
++
++#define AR2313_DESCR_ENTRIES 64
++
++typedef struct {
++ volatile unsigned int status; // OWN, Device control and status.
++ volatile unsigned int devcs; // pkt Control bits + Length
++ volatile unsigned int addr; // Current Address.
++ volatile unsigned int descr; // Next descriptor in chain.
++} ar2313_descr_t;
++
++#endif /* _AR2313_MSG_H_ */
+diff -Nur linux-2.6.17/drivers/net/ar2313/dma.h linux-2.6.17-owrt/drivers/net/ar2313/dma.h
+--- linux-2.6.17/drivers/net/ar2313/dma.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/drivers/net/ar2313/dma.h 2006-06-19 12:05:29.000000000 +0200
+@@ -0,0 +1,135 @@
++#ifndef __ARUBA_DMA_H__
++#define __ARUBA_DMA_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * DMA register definition.
++ *
++ * File : $Id: dma.h,v 1.3 2002/06/06 18:34:03 astichte Exp $
++ *
++ * Author : ryan.holmQVist@idt.com
++ * Date : 20011005
++ * Update :
++ * $Log: dma.h,v $
++ * Revision 1.3 2002/06/06 18:34:03 astichte
++ * Added XXX_PhysicalAddress and XXX_VirtualAddress
++ *
++ * Revision 1.2 2002/06/05 18:30:46 astichte
++ * Removed IDTField
++ *
++ * Revision 1.1 2002/05/29 17:33:21 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ *
++ ******************************************************************************/
++
++#define AR_BIT(x) (1 << (x))
++#define DMA_RX_ERR_CRC AR_BIT(1)
++#define DMA_RX_ERR_DRIB AR_BIT(2)
++#define DMA_RX_ERR_MII AR_BIT(3)
++#define DMA_RX_EV2 AR_BIT(5)
++#define DMA_RX_ERR_COL AR_BIT(6)
++#define DMA_RX_LONG AR_BIT(7)
++#define DMA_RX_LS AR_BIT(8) /* last descriptor */
++#define DMA_RX_FS AR_BIT(9) /* first descriptor */
++#define DMA_RX_MF AR_BIT(10) /* multicast frame */
++#define DMA_RX_ERR_RUNT AR_BIT(11) /* runt frame */
++#define DMA_RX_ERR_LENGTH AR_BIT(12) /* length error */
++#define DMA_RX_ERR_DESC AR_BIT(14) /* descriptor error */
++#define DMA_RX_ERROR AR_BIT(15) /* error summary */
++#define DMA_RX_LEN_MASK 0x3fff0000
++#define DMA_RX_LEN_SHIFT 16
++#define DMA_RX_FILT AR_BIT(30)
++#define DMA_RX_OWN AR_BIT(31) /* desc owned by DMA controller */
++
++#define DMA_RX1_BSIZE_MASK 0x000007ff
++#define DMA_RX1_BSIZE_SHIFT 0
++#define DMA_RX1_CHAINED AR_BIT(24)
++#define DMA_RX1_RER AR_BIT(25)
++
++#define DMA_TX_ERR_UNDER AR_BIT(1) /* underflow error */
++#define DMA_TX_ERR_DEFER AR_BIT(2) /* excessive deferral */
++#define DMA_TX_COL_MASK 0x78
++#define DMA_TX_COL_SHIFT 3
++#define DMA_TX_ERR_HB AR_BIT(7) /* hearbeat failure */
++#define DMA_TX_ERR_COL AR_BIT(8) /* excessive collisions */
++#define DMA_TX_ERR_LATE AR_BIT(9) /* late collision */
++#define DMA_TX_ERR_LINK AR_BIT(10) /* no carrier */
++#define DMA_TX_ERR_LOSS AR_BIT(11) /* loss of carrier */
++#define DMA_TX_ERR_JABBER AR_BIT(14) /* transmit jabber timeout */
++#define DMA_TX_ERROR AR_BIT(15) /* frame aborted */
++#define DMA_TX_OWN AR_BIT(31) /* descr owned by DMA controller */
++
++#define DMA_TX1_BSIZE_MASK 0x000007ff
++#define DMA_TX1_BSIZE_SHIFT 0
++#define DMA_TX1_CHAINED AR_BIT(24) /* chained descriptors */
++#define DMA_TX1_TER AR_BIT(25) /* transmit end of ring */
++#define DMA_TX1_FS AR_BIT(29) /* first segment */
++#define DMA_TX1_LS AR_BIT(30) /* last segment */
++#define DMA_TX1_IC AR_BIT(31) /* interrupt on completion */
++
++#define RCVPKT_LENGTH(X) (X >> 16) /* Received pkt Length */
++
++#define MAC_CONTROL_RE AR_BIT(2) /* receive enable */
++#define MAC_CONTROL_TE AR_BIT(3) /* transmit enable */
++#define MAC_CONTROL_DC AR_BIT(5) /* Deferral check*/
++#define MAC_CONTROL_ASTP AR_BIT(8) /* Auto pad strip */
++#define MAC_CONTROL_DRTY AR_BIT(10) /* Disable retry */
++#define MAC_CONTROL_DBF AR_BIT(11) /* Disable bcast frames */
++#define MAC_CONTROL_LCC AR_BIT(12) /* late collision ctrl */
++#define MAC_CONTROL_HP AR_BIT(13) /* Hash Perfect filtering */
++#define MAC_CONTROL_HASH AR_BIT(14) /* Unicast hash filtering */
++#define MAC_CONTROL_HO AR_BIT(15) /* Hash only filtering */
++#define MAC_CONTROL_PB AR_BIT(16) /* Pass Bad frames */
++#define MAC_CONTROL_IF AR_BIT(17) /* Inverse filtering */
++#define MAC_CONTROL_PR AR_BIT(18) /* promiscuous mode (valid frames only) */
++#define MAC_CONTROL_PM AR_BIT(19) /* pass multicast */
++#define MAC_CONTROL_F AR_BIT(20) /* full-duplex */
++#define MAC_CONTROL_DRO AR_BIT(23) /* Disable Receive Own */
++#define MAC_CONTROL_HBD AR_BIT(28) /* heart-beat disabled (MUST BE SET) */
++#define MAC_CONTROL_BLE AR_BIT(30) /* big endian mode */
++#define MAC_CONTROL_RA AR_BIT(31) /* receive all (valid and invalid frames) */
++
++#define MII_ADDR_BUSY AR_BIT(0)
++#define MII_ADDR_WRITE AR_BIT(1)
++#define MII_ADDR_REG_SHIFT 6
++#define MII_ADDR_PHY_SHIFT 11
++#define MII_DATA_SHIFT 0
++
++#define FLOW_CONTROL_FCE AR_BIT(1)
++
++#define DMA_BUS_MODE_SWR AR_BIT(0) /* software reset */
++#define DMA_BUS_MODE_BLE AR_BIT(7) /* big endian mode */
++#define DMA_BUS_MODE_PBL_SHIFT 8 /* programmable burst length 32 */
++#define DMA_BUS_MODE_DBO AR_BIT(20) /* big-endian descriptors */
++
++#define DMA_STATUS_TI AR_BIT(0) /* transmit interrupt */
++#define DMA_STATUS_TPS AR_BIT(1) /* transmit process stopped */
++#define DMA_STATUS_TU AR_BIT(2) /* transmit buffer unavailable */
++#define DMA_STATUS_TJT AR_BIT(3) /* transmit buffer timeout */
++#define DMA_STATUS_UNF AR_BIT(5) /* transmit underflow */
++#define DMA_STATUS_RI AR_BIT(6) /* receive interrupt */
++#define DMA_STATUS_RU AR_BIT(7) /* receive buffer unavailable */
++#define DMA_STATUS_RPS AR_BIT(8) /* receive process stopped */
++#define DMA_STATUS_ETI AR_BIT(10) /* early transmit interrupt */
++#define DMA_STATUS_FBE AR_BIT(13) /* fatal bus interrupt */
++#define DMA_STATUS_ERI AR_BIT(14) /* early receive interrupt */
++#define DMA_STATUS_AIS AR_BIT(15) /* abnormal interrupt summary */
++#define DMA_STATUS_NIS AR_BIT(16) /* normal interrupt summary */
++#define DMA_STATUS_RS_SHIFT 17 /* receive process state */
++#define DMA_STATUS_TS_SHIFT 20 /* transmit process state */
++#define DMA_STATUS_EB_SHIFT 23 /* error bits */
++
++#define DMA_CONTROL_SR AR_BIT(1) /* start receive */
++#define DMA_CONTROL_ST AR_BIT(13) /* start transmit */
++#define DMA_CONTROL_SF AR_BIT(21) /* store and forward */
++
++#endif // __ARUBA_DMA_H__
++
++
++
++
++
+diff -Nur linux-2.6.17/drivers/net/ar2313/Makefile linux-2.6.17-owrt/drivers/net/ar2313/Makefile
+--- linux-2.6.17/drivers/net/ar2313/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/drivers/net/ar2313/Makefile 2006-06-19 12:25:58.000000000 +0200
+@@ -0,0 +1,5 @@
++#
++# Makefile for the AR2313 ethernet driver
++#
++
++obj-$(CONFIG_AR2313) += ar2313.o
+diff -Nur linux-2.6.17/drivers/net/ar2313/platform.h linux-2.6.17-owrt/drivers/net/ar2313/platform.h
+--- linux-2.6.17/drivers/net/ar2313/platform.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/drivers/net/ar2313/platform.h 2006-06-19 12:05:29.000000000 +0200
+@@ -0,0 +1,128 @@
++/********************************************************************************
++ Title: $Source: platform.h,v $
++
++ Author: Dan Steinberg
++ Copyright Integrated Device Technology 2001
++
++ Purpose: AR2313 Register/Bit Definitions
++
++ Update:
++ $Log: platform.h,v $
++
++ Notes: See Merlot architecture spec for complete details. Note, all
++ addresses are virtual addresses in kseg1 (Uncached, Unmapped).
++
++********************************************************************************/
++
++#ifndef PLATFORM_H
++#define PLATFORM_H
++
++#define BIT(x) (1 << (x))
++
++#define RESET_BASE 0xBC003020
++#define RESET_VALUE 0x00000001
++
++/********************************************************************
++ * Device controller
++ ********************************************************************/
++typedef struct {
++ volatile unsigned int flash0;
++} DEVICE;
++
++#define device (*((volatile DEVICE *) DEV_CTL_BASE))
++
++// DDRC register
++#define DEV_WP (1<<26)
++
++/********************************************************************
++ * DDR controller
++ ********************************************************************/
++typedef struct {
++ volatile unsigned int ddrc0;
++ volatile unsigned int ddrc1;
++ volatile unsigned int ddrrefresh;
++} DDR;
++
++#define ddr (*((volatile DDR *) DDR_BASE))
++
++// DDRC register
++#define DDRC_CS(i) ((i&0x3)<<0)
++#define DDRC_WE (1<<2)
++
++/********************************************************************
++ * Ethernet interfaces
++ ********************************************************************/
++#define ETHERNET_BASE 0xB8200000
++
++//
++// New Combo structure for Both Eth0 AND eth1
++//
++typedef struct {
++ volatile unsigned int mac_control; /* 0x00 */
++ volatile unsigned int mac_addr[2]; /* 0x04 - 0x08*/
++ volatile unsigned int mcast_table[2]; /* 0x0c - 0x10 */
++ volatile unsigned int mii_addr; /* 0x14 */
++ volatile unsigned int mii_data; /* 0x18 */
++ volatile unsigned int flow_control; /* 0x1c */
++ volatile unsigned int vlan_tag; /* 0x20 */
++ volatile unsigned int pad[7]; /* 0x24 - 0x3c */
++ volatile unsigned int ucast_table[8]; /* 0x40-0x5c */
++
++} ETHERNET_STRUCT;
++
++/********************************************************************
++ * Interrupt controller
++ ********************************************************************/
++
++typedef struct {
++ volatile unsigned int wdog_control; /* 0x08 */
++ volatile unsigned int wdog_timer; /* 0x0c */
++ volatile unsigned int misc_status; /* 0x10 */
++ volatile unsigned int misc_mask; /* 0x14 */
++ volatile unsigned int global_status; /* 0x18 */
++ volatile unsigned int reserved; /* 0x1c */
++ volatile unsigned int reset_control; /* 0x20 */
++} INTERRUPT;
++
++#define interrupt (*((volatile INTERRUPT *) INTERRUPT_BASE))
++
++#define INTERRUPT_MISC_TIMER BIT(0)
++#define INTERRUPT_MISC_AHBPROC BIT(1)
++#define INTERRUPT_MISC_AHBDMA BIT(2)
++#define INTERRUPT_MISC_GPIO BIT(3)
++#define INTERRUPT_MISC_UART BIT(4)
++#define INTERRUPT_MISC_UARTDMA BIT(5)
++#define INTERRUPT_MISC_WATCHDOG BIT(6)
++#define INTERRUPT_MISC_LOCAL BIT(7)
++
++#define INTERRUPT_GLOBAL_ETH BIT(2)
++#define INTERRUPT_GLOBAL_WLAN BIT(3)
++#define INTERRUPT_GLOBAL_MISC BIT(4)
++#define INTERRUPT_GLOBAL_ITIMER BIT(5)
++
++/********************************************************************
++ * DMA controller
++ ********************************************************************/
++#define DMA_BASE 0xB8201000
++
++typedef struct {
++ volatile unsigned int bus_mode; /* 0x00 (CSR0) */
++ volatile unsigned int xmt_poll; /* 0x04 (CSR1) */
++ volatile unsigned int rcv_poll; /* 0x08 (CSR2) */
++ volatile unsigned int rcv_base; /* 0x0c (CSR3) */
++ volatile unsigned int xmt_base; /* 0x10 (CSR4) */
++ volatile unsigned int status; /* 0x14 (CSR5) */
++ volatile unsigned int control; /* 0x18 (CSR6) */
++ volatile unsigned int intr_ena; /* 0x1c (CSR7) */
++ volatile unsigned int rcv_missed; /* 0x20 (CSR8) */
++ volatile unsigned int reserved[11]; /* 0x24-0x4c (CSR9-19) */
++ volatile unsigned int cur_tx_buf_addr; /* 0x50 (CSR20) */
++ volatile unsigned int cur_rx_buf_addr; /* 0x50 (CSR21) */
++} DMA;
++
++#define dma (*((volatile DMA *) DMA_BASE))
++
++// macro to convert from virtual to physical address
++#define phys_addr(x) (x & 0x1fffffff)
++
++#endif /* PLATFORM_H */
+diff -Nur linux-2.6.17/drivers/net/Kconfig linux-2.6.17-owrt/drivers/net/Kconfig
+--- linux-2.6.17/drivers/net/Kconfig 2006-06-19 12:05:01.000000000 +0200
++++ linux-2.6.17-owrt/drivers/net/Kconfig 2006-06-19 12:26:35.000000000 +0200
+@@ -310,6 +310,12 @@
+
+ source "drivers/net/arm/Kconfig"
+
++config AR2313
++ tristate "AR2313 Ethernet support"
++ depends on NET_ETHERNET && MACH_ARUBA
++ help
++ Support for the AR2313 Ethernet part on Aruba AP60/61
++
+ config IDT_RC32434_ETH
+ tristate "IDT RC32434 Local Ethernet support"
+ depends on NET_ETHERNET
+diff -Nur linux-2.6.17/drivers/net/Makefile linux-2.6.17-owrt/drivers/net/Makefile
+--- linux-2.6.17/drivers/net/Makefile 2006-06-19 12:05:01.000000000 +0200
++++ linux-2.6.17-owrt/drivers/net/Makefile 2006-06-19 12:27:02.000000000 +0200
+@@ -12,6 +12,7 @@
+ obj-$(CONFIG_CHELSIO_T1) += chelsio/
+ obj-$(CONFIG_BONDING) += bonding/
+ obj-$(CONFIG_GIANFAR) += gianfar_driver.o
++obj-$(CONFIG_AR2313) += ar2313/
+
+ gianfar_driver-objs := gianfar.o \
+ gianfar_ethtool.o \
diff --git a/target/linux/aruba-2.6/patches/011-ap6x_serial_fix.patch b/target/linux/aruba-2.6/patches/011-ap6x_serial_fix.patch
new file mode 100644
index 0000000000..528d0e90fb
--- /dev/null
+++ b/target/linux/aruba-2.6/patches/011-ap6x_serial_fix.patch
@@ -0,0 +1,31 @@
+diff -urN linux.old/drivers/serial/8250.c linux.net/drivers/serial/8250.c
+--- linux.old/drivers/serial/8250.c 2006-01-15 07:16:02.000000000 +0100
++++ linux.net/drivers/serial/8250.c 2006-01-30 06:12:30.509342250 +0100
+@@ -1510,7 +1510,7 @@
+ {
+ struct uart_8250_port *up = (struct uart_8250_port *)port;
+ unsigned long flags;
+- unsigned char lsr, iir;
++// unsigned char lsr, iir;
+ int retval;
+
+ up->capabilities = uart_config[up->port.type].flags;
+@@ -1615,6 +1615,8 @@
+
+ serial8250_set_mctrl(&up->port, up->port.mctrl);
+
++// For some reason this test causes problems on the AP6x serial console
++#if 0
+ /*
+ * Do a quick test to see if we receive an
+ * interrupt when we enable the TX irq.
+@@ -1633,7 +1635,8 @@
+ } else {
+ up->bugs &= ~UART_BUG_TXEN;
+ }
+-
++#endif
++
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ /*
diff --git a/target/linux/aruba-2.6/patches/012-ehci_softirq.patch b/target/linux/aruba-2.6/patches/012-ehci_softirq.patch
new file mode 100644
index 0000000000..ae7f9f26c8
--- /dev/null
+++ b/target/linux/aruba-2.6/patches/012-ehci_softirq.patch
@@ -0,0 +1,70 @@
+diff -Nurb linux-2.6.16.1/drivers/usb/host/ehci.h linux-patched/drivers/usb/host/ehci.h
+--- linux-2.6.16.1/drivers/usb/host/ehci.h 2006-03-27 22:49:02.000000000 -0800
++++ linux-patched/drivers/usb/host/ehci.h 2006-04-07 12:07:30.000000000 -0700
+@@ -82,6 +82,7 @@
+ struct dma_pool *sitd_pool; /* sitd per split iso urb */
+
+ struct timer_list watchdog;
++ struct timer_list softirq;
+ struct notifier_block reboot_notifier;
+ unsigned long actions;
+ unsigned stamp;
+diff -Nurb linux-2.6.16.1/drivers/usb/host/ehci-hcd.c linux-patched/drivers/usb/host/ehci-hcd.c
+--- linux-2.6.16.1/drivers/usb/host/ehci-hcd.c 2006-03-27 22:49:02.000000000 -0800
++++ linux-patched/drivers/usb/host/ehci-hcd.c 2006-04-07 13:20:13.000000000 -0700
+@@ -116,6 +116,7 @@
+ #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */
+ #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */
+ #define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */
++#define EHCI_SOFTIRQ (HZ/400)
+
+ /* Initial IRQ latency: faster than hw default */
+ static int log2_irq_thresh = 0; // 0 to 6
+@@ -263,6 +264,16 @@
+ #include "ehci-sched.c"
+
+ /*-------------------------------------------------------------------------*/
++static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs);
++
++static void ehci_softirq (unsigned long param)
++{
++ struct ehci_hcd *ehci = (struct ehci_hcd *) param;
++
++ if (ehci_irq(ehci_to_hcd(ehci),0) != IRQ_NONE)
++ set_bit(HCD_FLAG_SAW_IRQ, &(ehci_to_hcd(ehci))->flags);
++ mod_timer (&ehci->softirq, jiffies + EHCI_SOFTIRQ);
++}
+
+ static void ehci_watchdog (unsigned long param)
+ {
+@@ -280,6 +291,10 @@
+ COUNT (ehci->stats.lost_iaa);
+ writel (STS_IAA, &ehci->regs->status);
+ ehci->reclaim_ready = 1;
++ if (!timer_pending(&ehci->softirq)) {
++ ehci_info(ehci, "switching to softirq\n");
++ mod_timer (&ehci->softirq, jiffies + EHCI_SOFTIRQ);
++ }
+ }
+ }
+
+@@ -371,6 +388,7 @@
+
+ /* no more interrupts ... */
+ del_timer_sync (&ehci->watchdog);
++ del_timer_sync (&ehci->softirq);
+
+ spin_lock_irq(&ehci->lock);
+ if (HC_IS_RUNNING (hcd->state))
+@@ -418,6 +436,10 @@
+ ehci->watchdog.function = ehci_watchdog;
+ ehci->watchdog.data = (unsigned long) ehci;
+
++ init_timer(&ehci->softirq);
++ ehci->softirq.function = ehci_softirq;
++ ehci->softirq.data = (unsigned long) ehci;
++
+ /*
+ * hw default: 1K periodic list heads, one per frame.
+ * periodic_size can shrink by USBCMD update if hcc_params allows.
+
diff --git a/target/linux/au1000-2.6/Makefile b/target/linux/au1000-2.6/Makefile
new file mode 100644
index 0000000000..5d2711cb30
--- /dev/null
+++ b/target/linux/au1000-2.6/Makefile
@@ -0,0 +1,27 @@
+#
+# 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
+
+LINUX_VERSION:=2.6.17
+LINUX_RELEASE:=1
+LINUX_KERNEL_MD5SUM:=37ddefe96625502161f075b9d907f21e
+
+include ./config
+include $(INCLUDE_DIR)/kernel.mk
+include $(INCLUDE_DIR)/kernel-build.mk
+
+$(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked
+ [ -d ../generic-$(KERNEL)/patches ] && $(PATCH) $(LINUX_DIR) ../generic-$(KERNEL)/patches
+ [ -d ./patches ] && $(PATCH) $(LINUX_DIR) ./patches
+ @$(CP) config $(LINUX_DIR)/.config
+ touch $@
+
+$(LINUX_BUILD_DIR)/zImage.flash.srec: $(LINUX_DIR)/vmlinux
+ $(CP) $(LINUX_DIR)/arch/mips/boot/compressed/images/zImage.flash.srec $(LINUX_DIR)/zImage.flash.srec
+ $(CP) $(LINUX_DIR)/arch/mips/boot/compressed/images/zImage.srec $(LINUX_DIR)/zImage.srec
+
+compile: $(LINUX_BUILD_DIR)/zImage.flash.srec
diff --git a/target/linux/au1000-2.6/config b/target/linux/au1000-2.6/config
new file mode 100644
index 0000000000..e94f884cb2
--- /dev/null
+++ b/target/linux/au1000-2.6/config
@@ -0,0 +1,1595 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Mon Jul 31 19:15:16 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+CONFIG_MIPS_MTX1=y
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_SOC_AU1500=y
+CONFIG_SOC_AU1X00=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
+CONFIG_64BIT_PHYS_ADDR=y
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_TRAD_SIGNALS=y
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=m
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_MULTIPATH_CACHED=y
+CONFIG_IP_ROUTE_MULTIPATH_RR=m
+CONFIG_IP_ROUTE_MULTIPATH_RANDOM=m
+CONFIG_IP_ROUTE_MULTIPATH_WRANDOM=m
+CONFIG_IP_ROUTE_MULTIPATH_DRR=m
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IPSEC_NAT_TRAVERSAL=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NETFILTER_XTABLES=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=y
+CONFIG_IP_NF_IRC=y
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_IPP2P=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TIME=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
+CONFIG_IP_NF_MATCH_LAYER7=m
+# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+# CONFIG_IP_NF_TARGET_IMQ is not set
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_TARGET_ROUTE=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_SAME is not set
+# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+CONFIG_IP_NF_NAT_IRC=y
+CONFIG_IP_NF_NAT_FTP=y
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+CONFIG_IP_NF_RAW=m
+# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_IP_NF_SET=m
+CONFIG_IP_NF_SET_MAX=256
+CONFIG_IP_NF_SET_HASHSIZE=1024
+CONFIG_IP_NF_SET_IPMAP=m
+CONFIG_IP_NF_SET_MACIPMAP=m
+CONFIG_IP_NF_SET_PORTMAP=m
+CONFIG_IP_NF_SET_IPHASH=m
+CONFIG_IP_NF_SET_NETHASH=m
+CONFIG_IP_NF_SET_IPTREE=m
+CONFIG_IP_NF_MATCH_SET=m
+CONFIG_IP_NF_TARGET_SET=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+# CONFIG_IP6_NF_MATCH_RT is not set
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+CONFIG_IP6_NF_MATCH_OWNER=m
+# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_IMQ=m
+# CONFIG_IP6_NF_TARGET_LOG is not set
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_ROUTE=m
+CONFIG_IP6_NF_MANGLE=m
+# CONFIG_IP6_NF_TARGET_HL is not set
+# CONFIG_IP6_NF_RAW is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+CONFIG_LLC2=m
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_ESFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ALCHEMY is not set
+CONFIG_MTD_MTX1=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_IFB is not set
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_IMQ=m
+# CONFIG_IMQ_BEHAVIOR_AA is not set
+# CONFIG_IMQ_BEHAVIOR_AB is not set
+CONFIG_IMQ_BEHAVIOR_BA=y
+# CONFIG_IMQ_BEHAVIOR_BB is not set
+CONFIG_IMQ_NUM_DEVS=2
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_MIPS_AU1X00_ENET=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+CONFIG_STRIP=m
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+CONFIG_IPW2100_DEBUG=y
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW_QOS=y
+CONFIG_IPW2200_DEBUG=y
+CONFIG_HERMES=m
+# CONFIG_PLX_HERMES is not set
+# CONFIG_TMD_HERMES is not set
+# CONFIG_NORTEL_HERMES is not set
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_BCM43XX=m
+CONFIG_BCM43XX_DEBUG=y
+CONFIG_BCM43XX_DMA=y
+CONFIG_BCM43XX_PIO=y
+CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
+# CONFIG_BCM43XX_DMA_MODE is not set
+# CONFIG_BCM43XX_PIO_MODE is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+CONFIG_SHAPER=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+CONFIG_SERIAL_8250_AU1X00=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_MTX1_WATCHDOG=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=m
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_ZD1201=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+# CONFIG_USB_SERIAL_ANYDATA is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+CONFIG_DEVFS_DEBUG=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+# CONFIG_ROOT_NFS is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+# CONFIG_CIFS_STATS2 is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=m
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="init=/etc/preinit"
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
diff --git a/target/linux/au1000-2.6/patches/001-redefinitions_fixes.patch b/target/linux/au1000-2.6/patches/001-redefinitions_fixes.patch
new file mode 100644
index 0000000000..f2c524a030
--- /dev/null
+++ b/target/linux/au1000-2.6/patches/001-redefinitions_fixes.patch
@@ -0,0 +1,26 @@
+--- linux-2.6.16.2/drivers/usb/host/ohci-pci.c 2006-04-07 18:56:47.000000000 +0200
++++ linux-2.6.16.2.new/drivers/usb/host/ohci-pci.c 2006-04-11 14:20:33.000000000 +0200
+@@ -215,7 +215,7 @@
+ #endif
+ };
+
+-
++/*
+ static int __init ohci_hcd_pci_init (void)
+ {
+ printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name);
+@@ -227,11 +227,12 @@
+ return pci_register_driver (&ohci_pci_driver);
+ }
+ module_init (ohci_hcd_pci_init);
+-
++*/
+ /*-------------------------------------------------------------------------*/
+-
++/*
+ static void __exit ohci_hcd_pci_cleanup (void)
+ {
+ pci_unregister_driver (&ohci_pci_driver);
+ }
+ module_exit (ohci_hcd_pci_cleanup);
++*/
diff --git a/target/linux/au1000-2.6/patches/002-mtx1_flash_map.patch b/target/linux/au1000-2.6/patches/002-mtx1_flash_map.patch
new file mode 100644
index 0000000000..9a6b05b146
--- /dev/null
+++ b/target/linux/au1000-2.6/patches/002-mtx1_flash_map.patch
@@ -0,0 +1,16 @@
+diff -urN linux-2.6.16.7/drivers/mtd/maps/alchemy-flash.c linux-2.6.16.7.new/drivers/mtd/maps/alchemy-flash.c
+--- linux-2.6.16.7/drivers/mtd/maps/alchemy-flash.c 2006-04-17 23:53:25.000000000 +0200
++++ linux-2.6.16.7.new/drivers/mtd/maps/alchemy-flash.c 2006-04-20 19:16:26.000000000 +0200
+@@ -105,6 +105,12 @@
+ #define USE_LOCAL_ACCESSORS /* why? */
+ #endif
+
++#ifdef CONFIG_MIPS_MTX1
++#define BOARD_MAP_NAME "MTX-1 Flash"
++#define BOARD_FLASH_SIZE 0x04000000 /* 64MB */
++#define BOARD_FLASH_WIDTH 4 /* 32-bits */
++#endif
++
+ static struct map_info alchemy_map = {
+ .name = BOARD_MAP_NAME,
+ };
diff --git a/target/linux/au1000-2.6/patches/003-zImage.patch b/target/linux/au1000-2.6/patches/003-zImage.patch
new file mode 100644
index 0000000000..1d4c6ad5d1
--- /dev/null
+++ b/target/linux/au1000-2.6/patches/003-zImage.patch
@@ -0,0 +1,1364 @@
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/au1xxx/head.S linux-2.6.16.7.new/arch/mips/boot/compressed/au1xxx/head.S
+--- linux-2.6.16.7/arch/mips/boot/compressed/au1xxx/head.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/au1xxx/head.S 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,119 @@
++/*
++ * arch/mips/kernel/head.S
++ *
++ * 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) 1994, 1995 Waldorf Electronics
++ * Written by Ralf Baechle and Andreas Busse
++ * Copyright (C) 1995 - 1999 Ralf Baechle
++ * Copyright (C) 1996 Paul M. Antoine
++ * Modified for DECStation and hence R3000 support by Paul M. Antoine
++ * Further modifications by David S. Miller and Harald Koerfgen
++ * Copyright (C) 1999 Silicon Graphics, Inc.
++ *
++ * Head.S contains the MIPS exception handler and startup code.
++ *
++ **************************************************************************
++ * 9 Nov, 2000.
++ * Added Cache Error exception handler and SBDDP EJTAG debug exception.
++ *
++ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
++ **************************************************************************
++ */
++#include <linux/config.h>
++#include <linux/threads.h>
++
++#include <asm/asm.h>
++#include <asm/cacheops.h>
++#include <asm/mipsregs.h>
++#include <asm/cachectl.h>
++#include <asm/regdef.h>
++
++#define IndexInvalidate_I 0x00
++#define IndexWriteBack_D 0x01
++
++ .set noreorder
++ .cprestore
++ LEAF(start)
++start:
++ bal locate
++ nop
++locate:
++ subu s8, ra, 8 /* Where we were loaded */
++ la sp, (.stack + 8192)
++
++ move s0, a0 /* Save boot rom start args */
++ move s1, a1
++ move s2, a2
++ move s3, a3
++
++ la a0, start /* Where we were linked to run */
++
++ move a1, s8
++ la a2, _edata
++ subu t1, a2, a0
++ srl t1, t1, 2
++
++ /* copy text section */
++ li t0, 0
++1: lw v0, 0(a1)
++ nop
++ sw v0, 0(a0)
++ xor t0, t0, v0
++ addu a0, 4
++ bne a2, a0, 1b
++ addu a1, 4
++
++ /* Clear BSS */
++ la a0, _edata
++ la a2, _end
++2: sw zero, 0(a0)
++ bne a2, a0, 2b
++ addu a0, 4
++
++ /* push the D-Cache and invalidate I-Cache */
++ li k0, 0x80000000 # start address
++ li k1, 0x80004000 # end address (16KB I-Cache)
++ subu k1, 128
++
++1:
++ .set mips3
++ cache IndexWriteBack_D, 0(k0)
++ cache IndexWriteBack_D, 32(k0)
++ cache IndexWriteBack_D, 64(k0)
++ cache IndexWriteBack_D, 96(k0)
++ cache IndexInvalidate_I, 0(k0)
++ cache IndexInvalidate_I, 32(k0)
++ cache IndexInvalidate_I, 64(k0)
++ cache IndexInvalidate_I, 96(k0)
++ .set mips0
++
++ bne k0, k1, 1b
++ addu k0, k0, 128
++ /* done */
++
++ move a0, s8 /* load address */
++ move a1, t1 /* length in words */
++ move a2, t0 /* checksum */
++ move a3, sp
++
++ la ra, 1f
++ la k0, decompress_kernel
++ jr k0
++ nop
++1:
++
++ move a0, s0
++ move a1, s1
++ move a2, s2
++ move a3, s3
++ li k0, KERNEL_ENTRY
++ jr k0
++ nop
++3:
++ b 3b
++ END(start)
++ .comm .stack,4096*2,4
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/au1xxx/Makefile linux-2.6.16.7.new/arch/mips/boot/compressed/au1xxx/Makefile
+--- linux-2.6.16.7/arch/mips/boot/compressed/au1xxx/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/au1xxx/Makefile 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,110 @@
++# arch/mips/boot/compressed/au1xxx/Makefile
++#
++# Makefile for AMD Alchemy Semiconductor Au1x based boards.
++# All of the boot loader code was derived from the ppc
++# boot code.
++#
++# Copyright 2001,2002 MontaVista Software Inc.
++#
++# Author: Mark A. Greer
++# mgreer@mvista.com
++#
++# Copyright 2004 Embedded Alley Solutions, Inc
++# Ported and modified for mips 2.6 support by
++# Pete Popov <ppopov@embeddedalley.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.
++
++boot := arch/mips/boot
++compressed := $(boot)/compressed
++utils := $(compressed)/utils
++lib := $(compressed)/lib
++images := $(compressed)/images
++common := $(compressed)/common
++
++#########################################################################
++# START BOARD SPECIFIC VARIABLES
++
++# These two variables control where the zImage is stored
++# in flash and loaded in memory. It only controls how the srec
++# file is generated, the code is the same.
++RAM_RUN_ADDR = 0x81000000
++
++ifdef CONFIG_MIPS_XXS1500
++FLASH_LOAD_ADDR = 0xBF000000
++else
++FLASH_LOAD_ADDR = 0xBFD00000
++endif
++
++# These two variables specify the free ram region
++# that can be used for temporary malloc area
++AVAIL_RAM_START=0x80500000
++AVAIL_RAM_END=0x80900000
++
++# This one must match the LOADADDR in arch/mips/Makefile!
++LOADADDR=0x80100000
++
++# WARNING WARNING WARNING
++# Note that with a LOADADDR of 0x80100000 and AVAIL_RAM_START of
++# 0x80500000, the max decompressed kernel size can be 4MB. Else we
++# start overwriting ourselve. You can change these vars as needed;
++# it would be much better if we just figured everything out on the fly.
++
++# END BOARD SPECIFIC VARIABLES
++#########################################################################
++
++OBJECTS := $(obj)/head.o $(common)/misc-common.o $(common)/misc-simple.o \
++ $(common)/au1k_uart.o
++LIBS := $(lib)/lib.a
++
++ENTRY := $(utils)/entry
++OFFSET := $(utils)/offset
++SIZE := $(utils)/size
++
++LD_ARGS := -T $(compressed)/ld.script -Ttext $(RAM_RUN_ADDR) -Bstatic
++
++ifdef CONFIG_CPU_LITTLE_ENDIAN
++OBJCOPY_ARGS = -O elf32-tradlittlemips
++else
++OBJCOPY_ARGS = -O elf32-tradbigmips
++endif
++
++$(obj)/head.o: $(obj)/head.S $(TOPDIR)/vmlinux
++ $(CC) -I $(TOPDIR)/include $(AFLAGS) \
++ -DKERNEL_ENTRY=$(shell sh $(ENTRY) $(NM) $(TOPDIR)/vmlinux ) \
++ -c -o $*.o $<
++
++$(common)/misc-simple.o:
++ $(CC) -I $(TOPDIR)/include $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 -DZIMAGE_OFFSET=0 \
++ -DAVAIL_RAM_START=$(AVAIL_RAM_START) \
++ -DAVAIL_RAM_END=$(AVAIL_RAM_END) \
++ -DLOADADDR=$(LOADADDR) \
++ -DZIMAGE_SIZE=0 -c -o $@ $*.c
++
++$(obj)/zvmlinux: $(OBJECTS) $(LIBS) $(srctree)/$(compressed)/ld.script $(images)/vmlinux.gz $(common)/dummy.o
++ $(OBJCOPY) \
++ --add-section=.image=$(images)/vmlinux.gz \
++ --set-section-flags=.image=contents,alloc,load,readonly,data \
++ $(common)/dummy.o $(common)/image.o
++ $(LD) $(LD_ARGS) -o $@ $(OBJECTS) $(common)/image.o $(LIBS)
++ $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R __kcrctab -R __ksymtab_strings \
++ -R .comment -R .stab -R .stabstr -R .initrd -R .sysmap
++
++# Here we manipulate the image in order to get it the necessary
++# srecord file we need.
++zImage: $(obj)/zvmlinux
++ mv $(obj)/zvmlinux $(images)/zImage
++ $(OBJCOPY) -O srec $(images)/zImage $(images)/zImage.srec
++ $(OBJCOPY) -O binary $(images)/zImage $(images)/zImage.bin
++
++zImage.flash: zImage
++ ( \
++ flash=${FLASH_LOAD_ADDR} ; \
++ ram=${RAM_RUN_ADDR} ; \
++ adjust=$$[ $$flash - $$ram ] ; \
++ $(OBJCOPY) -O srec --adjust-vma `printf '0x%08x' $$adjust` \
++ $(images)/zImage $(images)/zImage.flash.srec ; \
++ )
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/common/au1k_uart.c linux-2.6.16.7.new/arch/mips/boot/compressed/common/au1k_uart.c
+--- linux-2.6.16.7/arch/mips/boot/compressed/common/au1k_uart.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/common/au1k_uart.c 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,103 @@
++/*
++ * BRIEF MODULE DESCRIPTION
++ * Simple Au1000 uart routines.
++ *
++ * Copyright 2001 MontaVista Software Inc.
++ * Author: MontaVista Software, Inc.
++ * ppopov@mvista.com or source@mvista.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/config.h>
++#include <asm/io.h>
++#include <asm/mach-au1x00/au1000.h>
++#include "ns16550.h"
++
++typedef unsigned char uint8;
++typedef unsigned int uint32;
++
++#define UART16550_BAUD_2400 2400
++#define UART16550_BAUD_4800 4800
++#define UART16550_BAUD_9600 9600
++#define UART16550_BAUD_19200 19200
++#define UART16550_BAUD_38400 38400
++#define UART16550_BAUD_57600 57600
++#define UART16550_BAUD_115200 115200
++
++#define UART16550_PARITY_NONE 0
++#define UART16550_PARITY_ODD 0x08
++#define UART16550_PARITY_EVEN 0x18
++#define UART16550_PARITY_MARK 0x28
++#define UART16550_PARITY_SPACE 0x38
++
++#define UART16550_DATA_5BIT 0x0
++#define UART16550_DATA_6BIT 0x1
++#define UART16550_DATA_7BIT 0x2
++#define UART16550_DATA_8BIT 0x3
++
++#define UART16550_STOP_1BIT 0x0
++#define UART16550_STOP_2BIT 0x4
++
++/* It would be nice if we had a better way to do this.
++ * It could be a variable defined in one of the board specific files.
++ */
++#undef UART_BASE
++#ifdef CONFIG_COGENT_CSB250
++#define UART_BASE UART3_ADDR
++#else
++#define UART_BASE UART0_ADDR
++#endif
++
++/* memory-mapped read/write of the port */
++#define UART16550_READ(y) (au_readl(UART_BASE + y) & 0xff)
++#define UART16550_WRITE(y,z) (au_writel(z&0xff, UART_BASE + y))
++
++/*
++ * We use uart 0, which is already initialized by
++ * yamon.
++ */
++volatile struct NS16550 *
++serial_init(int chan)
++{
++ volatile struct NS16550 *com_port;
++ com_port = (struct NS16550 *) UART_BASE;
++ return (com_port);
++}
++
++void
++serial_putc(volatile struct NS16550 *com_port, unsigned char c)
++{
++ while ((UART16550_READ(UART_LSR)&0x40) == 0);
++ UART16550_WRITE(UART_TX, c);
++}
++
++unsigned char
++serial_getc(volatile struct NS16550 *com_port)
++{
++ while((UART16550_READ(UART_LSR) & 0x1) == 0);
++ return UART16550_READ(UART_RX);
++}
++
++int
++serial_tstc(volatile struct NS16550 *com_port)
++{
++ return((UART16550_READ(UART_LSR) & LSR_DR) != 0);
++}
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/common/dummy.c linux-2.6.16.7.new/arch/mips/boot/compressed/common/dummy.c
+--- linux-2.6.16.7/arch/mips/boot/compressed/common/dummy.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/common/dummy.c 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,4 @@
++int main(void)
++{
++ return 0;
++}
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/common/Makefile linux-2.6.16.7.new/arch/mips/boot/compressed/common/Makefile
+--- linux-2.6.16.7/arch/mips/boot/compressed/common/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/common/Makefile 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,14 @@
++#
++# arch/mips/boot/compressed/common/Makefile
++#
++# 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.
++#
++# Tom Rini January 2001
++#
++# Pete Popov, 2004
++#
++
++lib-y := misc-common.o no_initrd.o dummy.o
++lib-$(CONFIG_SOC_AU1X00) += au1k_uart.o
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/common/misc-common.c linux-2.6.16.7.new/arch/mips/boot/compressed/common/misc-common.c
+--- linux-2.6.16.7/arch/mips/boot/compressed/common/misc-common.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/common/misc-common.c 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,434 @@
++/*
++ * arch/mips/boot/compressed/common/misc-common.c
++ *
++ * Misc. bootloader code (almost) all platforms can use
++ *
++ * Author: Johnnie Peters <jpeters@mvista.com>
++ * Editor: Tom Rini <trini@mvista.com>
++ *
++ * Derived from arch/ppc/boot/prep/misc.c
++ *
++ * Ported by Pete Popov <ppopov@mvista.com> to
++ * support mips board(s). I also got rid of the vga console
++ * code.
++ *
++ * Copyright 2000-2001 MontaVista Software Inc.
++ *
++ * Ported to MIPS 2.6 by Pete Popov, <ppopov@embeddedalley.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <stdarg.h> /* for va_ bits */
++#include <linux/config.h>
++#include <linux/string.h>
++#include <linux/zlib.h>
++
++extern char *avail_ram;
++extern char *end_avail;
++extern char _end[];
++
++void puts(const char *);
++void putc(const char c);
++void puthex(unsigned long val);
++void _bcopy(char *src, char *dst, int len);
++void gunzip(void *, int, unsigned char *, int *);
++static int _cvt(unsigned long val, char *buf, long radix, char *digits);
++
++void _vprintk(void(*)(const char), const char *, va_list ap);
++
++struct NS16550 *com_port;
++
++int serial_tstc(volatile struct NS16550 *);
++unsigned char serial_getc(volatile struct NS16550 *);
++void serial_putc(volatile struct NS16550 *, unsigned char);
++
++void pause(void)
++{
++ puts("pause\n");
++}
++
++void exit(void)
++{
++ puts("exit\n");
++ while(1);
++}
++
++int tstc(void)
++{
++ return (serial_tstc(com_port));
++}
++
++int getc(void)
++{
++ while (1) {
++ if (serial_tstc(com_port))
++ return (serial_getc(com_port));
++ }
++}
++
++void
++putc(const char c)
++{
++ serial_putc(com_port, c);
++ if ( c == '\n' )
++ serial_putc(com_port, '\r');
++}
++
++void puts(const char *s)
++{
++ char c;
++ while ( ( c = *s++ ) != '\0' ) {
++ serial_putc(com_port, c);
++ if ( c == '\n' ) serial_putc(com_port, '\r');
++ }
++}
++
++void error(char *x)
++{
++ puts("\n\n");
++ puts(x);
++ puts("\n\n -- System halted");
++
++ while(1); /* Halt */
++}
++
++static void *zalloc(unsigned size)
++{
++ void *p = avail_ram;
++
++ size = (size + 7) & -8;
++ avail_ram += size;
++ if (avail_ram > end_avail) {
++ puts("oops... out of memory\n");
++ pause();
++ }
++ return p;
++}
++
++
++#define HEAD_CRC 2
++#define EXTRA_FIELD 4
++#define ORIG_NAME 8
++#define COMMENT 0x10
++#define RESERVED 0xe0
++
++#define DEFLATED 8
++
++void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
++{
++ z_stream s;
++ int r, i, flags;
++
++ /* skip header */
++ i = 10;
++ flags = src[3];
++ if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
++ puts("bad gzipped data\n");
++ exit();
++ }
++ if ((flags & EXTRA_FIELD) != 0)
++ i = 12 + src[10] + (src[11] << 8);
++ if ((flags & ORIG_NAME) != 0)
++ while (src[i++] != 0)
++ ;
++ if ((flags & COMMENT) != 0)
++ while (src[i++] != 0)
++ ;
++ if ((flags & HEAD_CRC) != 0)
++ i += 2;
++ if (i >= *lenp) {
++ puts("gunzip: ran out of data in header\n");
++ exit();
++ }
++
++ /* Initialize ourself. */
++ s.workspace = zalloc(zlib_inflate_workspacesize());
++ r = zlib_inflateInit2(&s, -MAX_WBITS);
++ if (r != Z_OK) {
++ puts("zlib_inflateInit2 returned "); puthex(r); puts("\n");
++ exit();
++ }
++ s.next_in = src + i;
++ s.avail_in = *lenp - i;
++ s.next_out = dst;
++ s.avail_out = dstlen;
++ r = zlib_inflate(&s, Z_FINISH);
++ if (r != Z_OK && r != Z_STREAM_END) {
++ puts("inflate returned "); puthex(r); puts("\n");
++ exit();
++ }
++ *lenp = s.next_out - (unsigned char *) dst;
++ zlib_inflateEnd(&s);
++}
++
++void
++puthex(unsigned long val)
++{
++
++ unsigned char buf[10];
++ int i;
++ for (i = 7; i >= 0; i--)
++ {
++ buf[i] = "0123456789ABCDEF"[val & 0x0F];
++ val >>= 4;
++ }
++ buf[8] = '\0';
++ puts(buf);
++}
++
++#define FALSE 0
++#define TRUE 1
++
++void
++_printk(char const *fmt, ...)
++{
++ va_list ap;
++
++ va_start(ap, fmt);
++ _vprintk(putc, fmt, ap);
++ va_end(ap);
++ return;
++}
++
++#define is_digit(c) ((c >= '0') && (c <= '9'))
++
++void
++_vprintk(void(*putc)(const char), const char *fmt0, va_list ap)
++{
++ char c, sign, *cp = 0;
++ int left_prec, right_prec, zero_fill, length = 0, pad, pad_on_right;
++ char buf[32];
++ long val;
++ while ((c = *fmt0++))
++ {
++ if (c == '%')
++ {
++ c = *fmt0++;
++ left_prec = right_prec = pad_on_right = 0;
++ if (c == '-')
++ {
++ c = *fmt0++;
++ pad_on_right++;
++ }
++ if (c == '0')
++ {
++ zero_fill = TRUE;
++ c = *fmt0++;
++ } else
++ {
++ zero_fill = FALSE;
++ }
++ while (is_digit(c))
++ {
++ left_prec = (left_prec * 10) + (c - '0');
++ c = *fmt0++;
++ }
++ if (c == '.')
++ {
++ c = *fmt0++;
++ zero_fill++;
++ while (is_digit(c))
++ {
++ right_prec = (right_prec * 10) + (c - '0');
++ c = *fmt0++;
++ }
++ } else
++ {
++ right_prec = left_prec;
++ }
++ sign = '\0';
++ switch (c)
++ {
++ case 'd':
++ case 'x':
++ case 'X':
++ val = va_arg(ap, long);
++ switch (c)
++ {
++ case 'd':
++ if (val < 0)
++ {
++ sign = '-';
++ val = -val;
++ }
++ length = _cvt(val, buf, 10, "0123456789");
++ break;
++ case 'x':
++ length = _cvt(val, buf, 16, "0123456789abcdef");
++ break;
++ case 'X':
++ length = _cvt(val, buf, 16, "0123456789ABCDEF");
++ break;
++ }
++ cp = buf;
++ break;
++ case 's':
++ cp = va_arg(ap, char *);
++ length = strlen(cp);
++ break;
++ case 'c':
++ c = va_arg(ap, long /*char*/);
++ (*putc)(c);
++ continue;
++ default:
++ (*putc)('?');
++ }
++ pad = left_prec - length;
++ if (sign != '\0')
++ {
++ pad--;
++ }
++ if (zero_fill)
++ {
++ c = '0';
++ if (sign != '\0')
++ {
++ (*putc)(sign);
++ sign = '\0';
++ }
++ } else
++ {
++ c = ' ';
++ }
++ if (!pad_on_right)
++ {
++ while (pad-- > 0)
++ {
++ (*putc)(c);
++ }
++ }
++ if (sign != '\0')
++ {
++ (*putc)(sign);
++ }
++ while (length-- > 0)
++ {
++ (*putc)(c = *cp++);
++ if (c == '\n')
++ {
++ (*putc)('\r');
++ }
++ }
++ if (pad_on_right)
++ {
++ while (pad-- > 0)
++ {
++ (*putc)(c);
++ }
++ }
++ } else
++ {
++ (*putc)(c);
++ if (c == '\n')
++ {
++ (*putc)('\r');
++ }
++ }
++ }
++}
++
++int
++_cvt(unsigned long val, char *buf, long radix, char *digits)
++{
++ char temp[80];
++ char *cp = temp;
++ int length = 0;
++ if (val == 0)
++ { /* Special case */
++ *cp++ = '0';
++ } else
++ while (val)
++ {
++ *cp++ = digits[val % radix];
++ val /= radix;
++ }
++ while (cp != temp)
++ {
++ *buf++ = *--cp;
++ length++;
++ }
++ *buf = '\0';
++ return (length);
++}
++
++void
++_dump_buf_with_offset(unsigned char *p, int s, unsigned char *base)
++{
++ int i, c;
++ if ((unsigned int)s > (unsigned int)p)
++ {
++ s = (unsigned int)s - (unsigned int)p;
++ }
++ while (s > 0)
++ {
++ if (base)
++ {
++ _printk("%06X: ", (int)p - (int)base);
++ } else
++ {
++ _printk("%06X: ", p);
++ }
++ for (i = 0; i < 16; i++)
++ {
++ if (i < s)
++ {
++ _printk("%02X", p[i] & 0xFF);
++ } else
++ {
++ _printk(" ");
++ }
++ if ((i % 2) == 1) _printk(" ");
++ if ((i % 8) == 7) _printk(" ");
++ }
++ _printk(" |");
++ for (i = 0; i < 16; i++)
++ {
++ if (i < s)
++ {
++ c = p[i] & 0xFF;
++ if ((c < 0x20) || (c >= 0x7F)) c = '.';
++ } else
++ {
++ c = ' ';
++ }
++ _printk("%c", c);
++ }
++ _printk("|\n");
++ s -= 16;
++ p += 16;
++ }
++}
++
++void
++_dump_buf(unsigned char *p, int s)
++{
++ _printk("\n");
++ _dump_buf_with_offset(p, s, 0);
++}
++
++/*
++ * Local variables:
++ * c-indent-level: 8
++ * c-basic-offset: 8
++ * tab-width: 8
++ * End:
++ */
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/common/misc-simple.c linux-2.6.16.7.new/arch/mips/boot/compressed/common/misc-simple.c
+--- linux-2.6.16.7/arch/mips/boot/compressed/common/misc-simple.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/common/misc-simple.c 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,122 @@
++/*
++ * arch/mips/zboot/common/misc-simple.c
++ *
++ * Misc. bootloader code for many machines. This assumes you have are using
++ * a 6xx/7xx/74xx CPU in your machine. This assumes the chunk of memory
++ * below 8MB is free. Finally, it assumes you have a NS16550-style uart for
++ * your serial console. If a machine meets these requirements, it can quite
++ * likely use this code during boot.
++ *
++ * Author: Matt Porter <mporter@mvista.com>
++ * Derived from arch/ppc/boot/prep/misc.c
++ *
++ * Copyright 2001 MontaVista Software 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.
++ */
++
++#include <linux/types.h>
++#include <linux/elf.h>
++#include <linux/config.h>
++
++#include <asm/page.h>
++
++#include "linux/zlib.h"
++
++extern struct NS16550 *com_port;
++
++char *avail_ram;
++char *end_avail;
++extern char _end[];
++char *zimage_start;
++
++#ifdef CONFIG_CMDLINE
++#define CMDLINE CONFIG_CMDLINE
++#else
++#define CMDLINE ""
++#endif
++char cmd_preset[] = CMDLINE;
++char cmd_buf[256];
++char *cmd_line = cmd_buf;
++
++/* The linker tells us where the image is.
++*/
++extern unsigned char __image_begin, __image_end;
++extern unsigned char __ramdisk_begin, __ramdisk_end;
++unsigned long initrd_size;
++
++extern void puts(const char *);
++extern void putc(const char c);
++extern void puthex(unsigned long val);
++extern void *memcpy(void * __dest, __const void * __src,
++ __kernel_size_t __n);
++extern void gunzip(void *, int, unsigned char *, int *);
++extern void udelay(long delay);
++extern int tstc(void);
++extern int getc(void);
++extern volatile struct NS16550 *serial_init(int chan);
++
++void
++decompress_kernel(unsigned long load_addr, int num_words,
++ unsigned long cksum, unsigned long *sp)
++{
++ extern unsigned long start;
++ int zimage_size;
++
++ com_port = (struct NS16550 *)serial_init(0);
++
++ initrd_size = (unsigned long)(&__ramdisk_end) -
++ (unsigned long)(&__ramdisk_begin);
++
++ /*
++ * Reveal where we were loaded at and where we
++ * were relocated to.
++ */
++ puts("loaded at: "); puthex(load_addr);
++ puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n");
++ if ( (unsigned long)load_addr != (unsigned long)&start )
++ {
++ puts("relocated to: "); puthex((unsigned long)&start);
++ puts(" ");
++ puthex((unsigned long)((unsigned long)&start + (4*num_words)));
++ puts("\n");
++ }
++
++ /*
++ * We link ourself to an arbitrary low address. When we run, we
++ * relocate outself to that address. __image_being points to
++ * the part of the image where the zImage is. -- Tom
++ */
++ zimage_start = (char *)(unsigned long)(&__image_begin);
++ zimage_size = (unsigned long)(&__image_end) -
++ (unsigned long)(&__image_begin);
++
++ /*
++ * The zImage and initrd will be between start and _end, so they've
++ * already been moved once. We're good to go now. -- Tom
++ */
++ puts("zimage at: "); puthex((unsigned long)zimage_start);
++ puts(" "); puthex((unsigned long)(zimage_size+zimage_start));
++ puts("\n");
++
++ if ( initrd_size ) {
++ puts("initrd at: ");
++ puthex((unsigned long)(&__ramdisk_begin));
++ puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n");
++ }
++
++ /* assume the chunk below 8M is free */
++ avail_ram = (char *)AVAIL_RAM_START;
++ end_avail = (char *)AVAIL_RAM_END;
++
++ /* Display standard Linux/MIPS boot prompt for kernel args */
++ puts("Uncompressing Linux at load address ");
++ puthex(LOADADDR);
++ puts("\n");
++ /* I don't like this hard coded gunzip size (fixme) */
++ gunzip((void *)LOADADDR, 0x400000, zimage_start, &zimage_size);
++ puts("Now booting the kernel\n");
++}
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/common/no_initrd.c linux-2.6.16.7.new/arch/mips/boot/compressed/common/no_initrd.c
+--- linux-2.6.16.7/arch/mips/boot/compressed/common/no_initrd.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/common/no_initrd.c 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,2 @@
++char initrd_data[1];
++int initrd_len = 0;
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/images/Makefile linux-2.6.16.7.new/arch/mips/boot/compressed/images/Makefile
+--- linux-2.6.16.7/arch/mips/boot/compressed/images/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/images/Makefile 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,17 @@
++
++#
++# This dir holds all of the images for MIPS machines.
++# Tom Rini January 2001
++# Pete Popov 2004
++
++extra-y := vmlinux.bin vmlinux.gz
++
++OBJCOPYFLAGS_vmlinux.bin := -O binary
++$(obj)/vmlinux.bin: vmlinux FORCE
++ $(call if_changed,objcopy)
++
++$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
++ $(call if_changed,gzip)
++
++# Files generated that shall be removed upon make clean
++clean-files := vmlinux* zImage*
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/include/nonstdio.h linux-2.6.16.7.new/arch/mips/boot/compressed/include/nonstdio.h
+--- linux-2.6.16.7/arch/mips/boot/compressed/include/nonstdio.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/include/nonstdio.h 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,18 @@
++/*
++ * Copyright (C) Paul Mackerras 1997.
++ *
++ * 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.
++ */
++typedef int FILE;
++extern FILE *stdin, *stdout;
++#define NULL ((void *)0)
++#define EOF (-1)
++#define fopen(n, m) NULL
++#define fflush(f) 0
++#define fclose(f) 0
++extern char *fgets();
++
++#define perror(s) printf("%s: no files!\n", (s))
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/include/ns16550.h linux-2.6.16.7.new/arch/mips/boot/compressed/include/ns16550.h
+--- linux-2.6.16.7/arch/mips/boot/compressed/include/ns16550.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/include/ns16550.h 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,46 @@
++/*
++ * NS16550 Serial Port
++ */
++
++/*
++ * Figure out which file will have the definitons of COMx
++ */
++
++/* Some machines have their uart registers 16 bytes apart. Most don't.
++ * TODO: Make this work like drivers/char/serial does - Tom */
++#if !defined(UART_REG_PAD)
++#define UART_REG_PAD(x)
++#endif
++
++struct NS16550
++ {
++ unsigned char rbr; /* 0 */
++ UART_REG_PAD(rbr)
++ unsigned char ier; /* 1 */
++ UART_REG_PAD(ier)
++ unsigned char fcr; /* 2 */
++ UART_REG_PAD(fcr)
++ unsigned char lcr; /* 3 */
++ UART_REG_PAD(lcr)
++ unsigned char mcr; /* 4 */
++ UART_REG_PAD(mcr)
++ unsigned char lsr; /* 5 */
++ UART_REG_PAD(lsr)
++ unsigned char msr; /* 6 */
++ UART_REG_PAD(msr)
++ unsigned char scr; /* 7 */
++ };
++
++#define thr rbr
++#define iir fcr
++#define dll rbr
++#define dlm ier
++
++#define LSR_DR 0x01 /* Data ready */
++#define LSR_OE 0x02 /* Overrun */
++#define LSR_PE 0x04 /* Parity error */
++#define LSR_FE 0x08 /* Framing error */
++#define LSR_BI 0x10 /* Break */
++#define LSR_THRE 0x20 /* Xmit holding register empty */
++#define LSR_TEMT 0x40 /* Xmitter empty */
++#define LSR_ERR 0x80 /* Error */
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/include/pb1000_serial.h linux-2.6.16.7.new/arch/mips/boot/compressed/include/pb1000_serial.h
+--- linux-2.6.16.7/arch/mips/boot/compressed/include/pb1000_serial.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/include/pb1000_serial.h 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,20 @@
++/*
++ * arch/ppc/boot/include/sandpoint_serial.h
++ *
++ * Location of the COM ports on Motorola SPS Sandpoint machines
++ *
++ * Author: Mark A. Greer
++ * mgreer@mvista.com
++ *
++ * Copyright 2001 MontaVista Software 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.
++ */
++
++#define COM1 0xfe0003f8
++#define COM2 0xfe0002f8
++#define COM3 0x00000000 /* No COM3 */
++#define COM4 0x00000000 /* No COM4 */
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/ld.script linux-2.6.16.7.new/arch/mips/boot/compressed/ld.script
+--- linux-2.6.16.7/arch/mips/boot/compressed/ld.script 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/ld.script 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,151 @@
++OUTPUT_ARCH(mips)
++ENTRY(start)
++SECTIONS
++{
++ /* Read-only sections, merged into text segment: */
++ /* . = 0x81000000; */
++ .init : { *(.init) } =0
++ .text :
++ {
++ _ftext = . ;
++ *(.text)
++ *(.rodata) *(.rodata.*)
++ *(.rodata1)
++ /* .gnu.warning sections are handled specially by elf32.em. */
++ *(.gnu.warning)
++ } =0
++ .kstrtab : { *(.kstrtab) }
++
++ . = ALIGN(16); /* Exception table */
++ __start___ex_table = .;
++ __ex_table : { *(__ex_table) }
++ __stop___ex_table = .;
++
++ __start___dbe_table = .; /* Exception table for data bus errors */
++ __dbe_table : { *(__dbe_table) }
++ __stop___dbe_table = .;
++
++ __start___ksymtab = .; /* Kernel symbol table */
++ __ksymtab : { *(__ksymtab) }
++ __stop___ksymtab = .;
++
++ _etext = .;
++
++ . = ALIGN(8192);
++ .data.init_task : { *(.data.init_task) }
++
++ /* Startup code */
++ . = ALIGN(4096);
++ __init_begin = .;
++ .text.init : { *(.text.init) }
++ .data.init : { *(.data.init) }
++ . = ALIGN(16);
++ __setup_start = .;
++ .setup.init : { *(.setup.init) }
++ __setup_end = .;
++ __initcall_start = .;
++ .initcall.init : { *(.initcall.init) }
++ __initcall_end = .;
++ . = ALIGN(4096); /* Align double page for init_task_union */
++ __init_end = .;
++
++ . = ALIGN(4096);
++ .data.page_aligned : { *(.data.idt) }
++
++ . = ALIGN(32);
++ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
++
++ .fini : { *(.fini) } =0
++ .reginfo : { *(.reginfo) }
++ /* Adjust the address for the data segment. We want to adjust up to
++ the same address within the page on the next page up. It would
++ be more correct to do this:
++ . = .;
++ The current expression does not correctly handle the case of a
++ text segment ending precisely at the end of a page; it causes the
++ data segment to skip a page. The above expression does not have
++ this problem, but it will currently (2/95) cause BFD to allocate
++ a single segment, combining both text and data, for this case.
++ This will prevent the text segment from being shared among
++ multiple executions of the program; I think that is more
++ important than losing a page of the virtual address space (note
++ that no actual memory is lost; the page which is skipped can not
++ be referenced). */
++ . = .;
++ .data :
++ {
++ _fdata = . ;
++ *(.data)
++
++ /* Put the compressed image here, so bss is on the end. */
++ __image_begin = .;
++ *(.image)
++ __image_end = .;
++ /* Align the initial ramdisk image (INITRD) on page boundaries. */
++ . = ALIGN(4096);
++ __ramdisk_begin = .;
++ *(.initrd)
++ __ramdisk_end = .;
++ . = ALIGN(4096);
++
++ CONSTRUCTORS
++ }
++ .data1 : { *(.data1) }
++ _gp = . + 0x8000;
++ .lit8 : { *(.lit8) }
++ .lit4 : { *(.lit4) }
++ .ctors : { *(.ctors) }
++ .dtors : { *(.dtors) }
++ .got : { *(.got.plt) *(.got) }
++ .dynamic : { *(.dynamic) }
++ /* We want the small data sections together, so single-instruction offsets
++ can access them all, and initialized data all before uninitialized, so
++ we can shorten the on-disk segment size. */
++ .sdata : { *(.sdata) }
++ . = ALIGN(4);
++ _edata = .;
++ PROVIDE (edata = .);
++
++ __bss_start = .;
++ _fbss = .;
++ .sbss : { *(.sbss) *(.scommon) }
++ .bss :
++ {
++ *(.dynbss)
++ *(.bss)
++ *(COMMON)
++ . = ALIGN(4);
++ _end = . ;
++ PROVIDE (end = .);
++ }
++
++ /* Sections to be discarded */
++ /DISCARD/ :
++ {
++ *(.text.exit)
++ *(.data.exit)
++ *(.exitcall.exit)
++ }
++
++ /* This is the MIPS specific mdebug section. */
++ .mdebug : { *(.mdebug) }
++ /* These are needed for ELF backends which have not yet been
++ converted to the new style linker. */
++ .stab 0 : { *(.stab) }
++ .stabstr 0 : { *(.stabstr) }
++ /* DWARF debug sections.
++ Symbols in the .debug DWARF section are relative to the beginning of the
++ section so we begin .debug at 0. It's not clear yet what needs to happen
++ for the others. */
++ .debug 0 : { *(.debug) }
++ .debug_srcinfo 0 : { *(.debug_srcinfo) }
++ .debug_aranges 0 : { *(.debug_aranges) }
++ .debug_pubnames 0 : { *(.debug_pubnames) }
++ .debug_sfnames 0 : { *(.debug_sfnames) }
++ .line 0 : { *(.line) }
++ /* These must appear regardless of . */
++ .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
++ .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
++ .comment : { *(.comment) }
++ .note : { *(.note) }
++}
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/lib/Makefile linux-2.6.16.7.new/arch/mips/boot/compressed/lib/Makefile
+--- linux-2.6.16.7/arch/mips/boot/compressed/lib/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/lib/Makefile 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,11 @@
++
++#
++# Makefile for some libs needed by zImage.
++#
++
++lib-y := $(addprefix ../../../../../lib/zlib_inflate/, \
++ infblock.o infcodes.o inffast.o inflate.o inftrees.o infutil.o) \
++ $(addprefix ../../../../../lib/, ctype.o string.o) \
++ $(addprefix ../../../../../arch/mips/lib/, memcpy.o) \
++
++
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/Makefile linux-2.6.16.7.new/arch/mips/boot/compressed/Makefile
+--- linux-2.6.16.7/arch/mips/boot/compressed/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/Makefile 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,32 @@
++
++#
++# arch/mips/boot/compressed/Makefile
++#
++# 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) 1994 by Linus Torvalds
++# Adapted for PowerPC by Gary Thomas
++# modified by Cort (cort@cs.nmt.edu)
++#
++# Ported to MIPS by Pete Popov, ppopov@embeddedalley.com
++#
++
++boot := arch/mips/boot
++compressed := arch/mips/boot/compressed
++
++CFLAGS += -fno-builtin -D__BOOTER__ -I$(compressed)/include
++
++BOOT_TARGETS = zImage zImage.flash
++
++bootdir-$(CONFIG_SOC_AU1X00) := au1xxx
++subdir-y := common lib images
++
++.PHONY: $(BOOT_TARGETS) $(bootdir-y)
++
++$(BOOT_TARGETS): $(bootdir-y)
++
++$(bootdir-y): $(addprefix $(obj)/,$(subdir-y)) \
++ $(addprefix $(obj)/,$(hostprogs-y))
++ $(Q)$(MAKE) $(build)=$(obj)/$@ $(MAKECMDGOALS)
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/utils/entry linux-2.6.16.7.new/arch/mips/boot/compressed/utils/entry
+--- linux-2.6.16.7/arch/mips/boot/compressed/utils/entry 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/utils/entry 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,12 @@
++#!/bin/sh
++
++# grab the kernel_entry address from the vmlinux elf image
++entry=`$1 $2 | grep kernel_entry`
++
++fs=`echo $entry | grep ffffffff` # check toolchain output
++
++if [ -n "$fs" ]; then
++ echo "0x"`$1 $2 | grep kernel_entry | cut -c9- | awk '{print $1}'`
++else
++ echo "0x"`$1 $2 | grep kernel_entry | cut -c1- | awk '{print $1}'`
++fi
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/utils/offset linux-2.6.16.7.new/arch/mips/boot/compressed/utils/offset
+--- linux-2.6.16.7/arch/mips/boot/compressed/utils/offset 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/utils/offset 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,3 @@
++#!/bin/sh
++
++echo "0x"`$1 -h $2 | grep $3 | grep -v zvmlinux| awk '{print $6}'`
+diff -urN linux-2.6.16.7/arch/mips/boot/compressed/utils/size linux-2.6.16.7.new/arch/mips/boot/compressed/utils/size
+--- linux-2.6.16.7/arch/mips/boot/compressed/utils/size 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/boot/compressed/utils/size 2006-05-04 23:08:18.000000000 +0200
+@@ -0,0 +1,4 @@
++#!/bin/sh
++
++OFFSET=`$1 -h $2 | grep $3 | grep -v zvmlinux | awk '{print $3}'`
++echo "0x"$OFFSET
+diff -urN linux-2.6.16.7/arch/mips/boot/Makefile linux-2.6.16.7.new/arch/mips/boot/Makefile
+--- linux-2.6.16.7/arch/mips/boot/Makefile 2006-04-17 23:53:25.000000000 +0200
++++ linux-2.6.16.7.new/arch/mips/boot/Makefile 2006-05-04 23:08:18.000000000 +0200
+@@ -16,6 +16,7 @@
+ E2EFLAGS =
+ endif
+
++
+ #
+ # Drop some uninteresting sections in the kernel.
+ # This is only relevant for ELF kernels but doesn't hurt a.out
+@@ -25,7 +26,10 @@
+
+ VMLINUX = vmlinux
+
+-all: vmlinux.ecoff vmlinux.srec addinitrd
++ZBOOT_TARGETS = zImage zImage.flash
++bootdir-y := compressed
++
++all: vmlinux.ecoff vmlinux.srec addinitrd zImage
+
+ vmlinux.ecoff: $(obj)/elf2ecoff $(VMLINUX)
+ $(obj)/elf2ecoff $(VMLINUX) vmlinux.ecoff $(E2EFLAGS)
+@@ -51,3 +55,11 @@
+ vmlinux.bin \
+ vmlinux.ecoff \
+ vmlinux.srec
++
++.PHONY: $(ZBOOT_TARGETS) $(bootdir-y)
++
++$(ZBOOT_TARGETS): $(bootdir-y)
++
++$(bootdir-y): $(addprefix $(obj)/,$(subdir-y)) \
++ $(addprefix $(obj)/,$(hostprogs-y))
++ $(Q)$(MAKE) $(build)=$(obj)/$@ $(MAKECMDGOALS)
+diff -urN linux-2.6.16.7/arch/mips/Makefile linux-2.6.16.7.new/arch/mips/Makefile
+--- linux-2.6.16.7/arch/mips/Makefile 2006-04-17 23:53:25.000000000 +0200
++++ linux-2.6.16.7.new/arch/mips/Makefile 2006-05-04 23:09:44.000000000 +0200
+@@ -831,6 +831,10 @@
+ all: vmlinux.ecoff
+ endif
+
++ifdef CONFIG_MIPS_MTX1
++all: vmlinux.srec zImage zImage.flash
++endif
++
+ vmlinux.bin: $(vmlinux-32)
+ +@$(call makeboot,$@)
+
+@@ -840,6 +844,12 @@
+ vmlinux.srec: $(vmlinux-32)
+ +@$(call makeboot,$@)
+
++zImage: vmlinux
++ +@$(call makeboot,$@)
++
++zImage.flash: vmlinux
++ +@$(call makeboot,$@)
++
+ CLEAN_FILES += vmlinux.ecoff \
+ vmlinux.srec \
+ vmlinux.rm200.tmp \
+@@ -848,6 +858,7 @@
+ archclean:
+ @$(MAKE) $(clean)=arch/mips/boot
+ @$(MAKE) $(clean)=arch/mips/lasat
++ @$(MAKE) $(clean)=arch/mips/boot/compressed
+
+ CLEAN_FILES += vmlinux.32 \
+ vmlinux.64 \
diff --git a/target/linux/au1000-2.6/patches/004-mtx1_watchdog.patch b/target/linux/au1000-2.6/patches/004-mtx1_watchdog.patch
new file mode 100644
index 0000000000..c7e329b295
--- /dev/null
+++ b/target/linux/au1000-2.6/patches/004-mtx1_watchdog.patch
@@ -0,0 +1,279 @@
+diff -urN linux-2.6.16.7/drivers/char/watchdog/Kconfig linux-2.6.16.7.new/drivers/char/watchdog/Kconfig
+--- linux-2.6.16.7/drivers/char/watchdog/Kconfig 2006-04-17 23:53:25.000000000 +0200
++++ linux-2.6.16.7.new/drivers/char/watchdog/Kconfig 2006-04-22 23:23:53.000000000 +0200
+@@ -460,6 +460,14 @@
+ timer expired and no process has written to /dev/watchdog during
+ that time.
+
++config MTX1_WATCHDOG
++ tristate "MTX-1 Hardware Watchdog"
++ depends on WATCHDOG && MIPS_MTX1
++ help
++ Hardware driver for the AccessCube MTX-1 watchdog. This is a
++ watchdog timer that will reboot the machine after a 100 seconds
++ timer expired.
++
+ # S390 Architecture
+
+ config ZVM_WATCHDOG
+diff -urN linux-2.6.16.7/drivers/char/watchdog/Makefile linux-2.6.16.7.new/drivers/char/watchdog/Makefile
+--- linux-2.6.16.7/drivers/char/watchdog/Makefile 2006-04-17 23:53:25.000000000 +0200
++++ linux-2.6.16.7.new/drivers/char/watchdog/Makefile 2006-04-22 23:21:18.000000000 +0200
+@@ -65,6 +65,7 @@
+
+ # MIPS Architecture
+ obj-$(CONFIG_INDYDOG) += indydog.o
++obj-$(CONFIG_MTX1_WATCHDOG) += mtx-1_watchdog.o
+
+ # S390 Architecture
+
+diff -urN linux-2.6.16.7/drivers/char/watchdog/mtx-1_watchdog.c linux-2.6.16.7.new/drivers/char/watchdog/mtx-1_watchdog.c
+--- linux-2.6.16.7/drivers/char/watchdog/mtx-1_watchdog.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/drivers/char/watchdog/mtx-1_watchdog.c 2006-04-22 23:20:53.000000000 +0200
+@@ -0,0 +1,246 @@
++/*
++ * Driver for the MTX-1 Watchdog.
++ *
++ * (c) Copyright 2005 4G Systems <info@4g-systems.biz>, All Rights Reserved.
++ * http://www.4g-systems.biz
++ *
++ * 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.
++ *
++ * Neither Michael Stickel nor 4G Systems admit liability nor provide
++ * warranty for any of this software. This material is provided
++ * "AS-IS" and at no charge.
++ *
++ * (c) Copyright 2005 4G Systems <info@4g-systems.biz>
++ *
++ * Release 0.01.
++ *
++ * Author: Michael Stickel michael.stickel@4g-systems.biz
++ *
++ *
++ * The Watchdog is configured to reset the MTX-1
++ * if it is not triggered for 100 seconds.
++ * It should not be triggered more often than 1.6 seconds.
++ *
++ * A timer triggers the watchdog every 5 seconds, until
++ * it is opened for the first time. After the first open
++ * it MUST be triggered every 2..95 seconds.
++ */
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/miscdevice.h>
++#include <linux/watchdog.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <asm/uaccess.h>
++#include <linux/fs.h>
++
++#include <asm/mach-au1x00/au1000.h>
++
++#ifndef FALSE
++# define FALSE (0)
++#endif
++
++#ifndef TRUE
++# define TRUE (!FALSE)
++#endif
++
++
++//---------[ Hardware Functions ]-----------------
++
++static void mtx1_trigger_wd (void)
++{
++ /*
++ * toggle GPIO2_15
++ */
++
++ u32 tmp = au_readl(GPIO2_DIR);
++ tmp = (tmp & ~(1<<15)) | ((~tmp) & (1<<15));
++ au_writel (tmp, GPIO2_DIR);
++}
++
++static void mtx1_enable_wd (void)
++{
++ au_writel (au_readl(GPIO2_DIR) | (u32)(1<<15), GPIO2_DIR);
++}
++
++static void mtx1_disable_wd (void)
++{
++ au_writel (au_readl(GPIO2_DIR) & ~((u32)(1<<15)), GPIO2_DIR);
++}
++
++
++//---------[ Timer Functions ]-----------------
++
++static struct timer_list wd_trigger_timer;
++static char timer_is_running = FALSE;
++
++static void wd_timer_callback (unsigned long data)
++{
++ if (timer_is_running)
++ mod_timer (&wd_trigger_timer, jiffies + 5 * HZ);
++ mtx1_trigger_wd();
++}
++
++static void start_wd_timer (void)
++{
++ if (!timer_is_running) {
++ struct timer_list *t = &wd_trigger_timer;
++
++ init_timer (t);
++ t->function = wd_timer_callback;
++ t->data = (unsigned long)0L;
++ t->expires = jiffies + 5 * HZ; // 5 seconds.
++ add_timer (t);
++ timer_is_running = TRUE;
++ }
++}
++
++
++
++static void stop_wd_timer (void)
++{
++ if (timer_is_running) {
++ del_timer(&wd_trigger_timer);
++ timer_is_running = FALSE;
++ }
++}
++
++
++//---------[ File Functions ]-----------------
++
++static char restart_after_close;
++
++static int mtx1wd_open (struct inode *inode, struct file *file)
++{
++ if (MINOR(inode->i_rdev) != WATCHDOG_MINOR) return -ENODEV;
++ //MOD_INC_USE_COUNT;
++
++ // stop the timer, if it is running. It will not be
++ // started again, until the module is loaded again.
++ stop_wd_timer();
++
++ // sleep for 2 seconds, to ensure, that the wd is
++ // not triggered more often than every 2 seconds.
++ schedule_timeout (2 * HZ);
++
++ return 0;
++}
++
++
++static int mtx1wd_release (struct inode *inode, struct file *file) {
++ if (MINOR(inode->i_rdev)==WATCHDOG_MINOR) {
++ }
++ if (restart_after_close)
++ start_wd_timer();
++ //MOD_DEC_USE_COUNT;
++ return 0;
++}
++
++
++static ssize_t mtx1wd_write (struct file *file, const char *buf, size_t count, loff_t *ppos) {
++
++ mtx1_trigger_wd ();
++
++ if (count > 0) {
++ char buffer[10];
++ int n = (count>9)?9:count;
++
++ if (copy_from_user (&buffer, buf, n))
++ return -EFAULT;
++ buffer[n]=0;
++
++ if (count >= 4 && strncmp("auto", buffer, 4)==0)
++ restart_after_close = 1;
++
++ else if (count >= 6 && strncmp("manual", buffer, 6)==0)
++ restart_after_close = 0;
++
++ return n;
++ }
++
++ return 0;
++}
++
++static ssize_t mtx1wd_read (struct file *file, char *buf, size_t count, loff_t *ppos)
++{
++ char * state = restart_after_close ? "auto\n" : "manual\n";
++ int n = strlen(state)+1;
++
++ if (file->f_pos >= n)
++ return 0;
++
++ if (count < n)
++ return -EINVAL;
++
++ if(copy_to_user(buf, state, n))
++ return -EFAULT;
++
++ file->f_pos += n;
++
++ return n;
++}
++
++static struct file_operations mtx1wd_fops = {
++ .owner = THIS_MODULE,
++ .read = mtx1wd_read,
++ .write = mtx1wd_write,
++ .open = mtx1wd_open,
++ .release = mtx1wd_release
++};
++
++
++static struct miscdevice mtx1wd_miscdev = {
++ WATCHDOG_MINOR,
++ "watchdog",
++ &mtx1wd_fops
++};
++
++
++
++//---------[ Module Functions ]-----------------
++
++
++static int __init init_mtx1_watchdog(void)
++{
++ printk("MTX-1 watchdog driver\n");
++
++ misc_register(&mtx1wd_miscdev);
++
++ restart_after_close = 0;
++
++ mtx1_enable_wd ();
++
++ //-- trigger it for the first time.
++ //-- We do not exactly know how long it has not been triggered.
++ mtx1_trigger_wd ();
++
++ // start a timer, that calls mtx1_trigger_wd every 5 seconds.
++ start_wd_timer();
++
++ return 0;
++}
++
++static void __exit exit_mtx1_watchdog(void) {
++
++ // stop the timer, if it is running.
++ stop_wd_timer();
++
++ misc_deregister(&mtx1wd_miscdev);
++
++ mtx1_disable_wd();
++}
++
++module_init(init_mtx1_watchdog);
++module_exit(exit_mtx1_watchdog);
++
++MODULE_AUTHOR("Michael Stickel");
++MODULE_DESCRIPTION("Driver for the MTX-1 watchdog");
++MODULE_LICENSE("GPL");
diff --git a/target/linux/au1000-2.6/patches/005-au1000_eth_link_beat.patch b/target/linux/au1000-2.6/patches/005-au1000_eth_link_beat.patch
new file mode 100644
index 0000000000..946bd84540
--- /dev/null
+++ b/target/linux/au1000-2.6/patches/005-au1000_eth_link_beat.patch
@@ -0,0 +1,24 @@
+diff -urN linux-2.6.16.7/drivers/net/au1000_eth.c linux-2.6.16.7.new/drivers/net/au1000_eth.c
+--- linux-2.6.16.7/drivers/net/au1000_eth.c 2006-04-17 23:53:25.000000000 +0200
++++ linux-2.6.16.7.new/drivers/net/au1000_eth.c 2006-04-23 01:42:48.000000000 +0200
+@@ -12,6 +12,9 @@
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
++ * Bjoern Riemer 2004
++ * riemer@fokus.fraunhofer.de or riemer@riemer-nt.de
++ * // fixed the link beat detection with ioctls (SIOCGMIIPHY)
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+@@ -1672,6 +1675,10 @@
+ aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed);
+ control = MAC_DISABLE_RX_OWN | MAC_RX_ENABLE | MAC_TX_ENABLE;
+ #ifndef CONFIG_CPU_LITTLE_ENDIAN
++ /*riemer: fix for startup without cable */
++ if (!link)
++ dev->flags &= ~IFF_RUNNING;
++
+ control |= MAC_BIG_ENDIAN;
+ #endif
+ if (link && (dev->if_port == IF_PORT_100BASEFX)) {
diff --git a/target/linux/au1000-2.6/patches/006-mtx1_system_button.patch b/target/linux/au1000-2.6/patches/006-mtx1_system_button.patch
new file mode 100644
index 0000000000..511df2c8da
--- /dev/null
+++ b/target/linux/au1000-2.6/patches/006-mtx1_system_button.patch
@@ -0,0 +1,241 @@
+diff -urN linux-2.6.16.7/arch/mips/au1000/mtx-1/irqmap.c linux-2.6.16.7.new/arch/mips/au1000/mtx-1/irqmap.c
+--- linux-2.6.16.7/arch/mips/au1000/mtx-1/irqmap.c 2006-04-17 23:53:25.000000000 +0200
++++ linux-2.6.16.7.new/arch/mips/au1000/mtx-1/irqmap.c 2006-04-23 11:54:31.000000000 +0200
+@@ -64,6 +64,7 @@
+ { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
++ { AU1500_GPIO_207, INTC_INT_RISE_AND_FALL_EDGE, 0 },
+ };
+
+ int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+diff -urN linux-2.6.16.7/arch/mips/au1000/mtx-1/Makefile linux-2.6.16.7.new/arch/mips/au1000/mtx-1/Makefile
+--- linux-2.6.16.7/arch/mips/au1000/mtx-1/Makefile 2006-04-17 23:53:25.000000000 +0200
++++ linux-2.6.16.7.new/arch/mips/au1000/mtx-1/Makefile 2006-04-23 14:01:36.000000000 +0200
+@@ -8,3 +8,4 @@
+ #
+
+ lib-y := init.o board_setup.o irqmap.o
++obj-y := mtx-1_sysbtn.o
+diff -urN linux-2.6.16.7/arch/mips/au1000/mtx-1/mtx-1_sysbtn.c linux-2.6.16.7.new/arch/mips/au1000/mtx-1/mtx-1_sysbtn.c
+--- linux-2.6.16.7/arch/mips/au1000/mtx-1/mtx-1_sysbtn.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7.new/arch/mips/au1000/mtx-1/mtx-1_sysbtn.c 2006-04-23 14:01:17.000000000 +0200
+@@ -0,0 +1,218 @@
++/*
++ * Driver for the MTX-1 System Button.
++ *
++ * (c) Copyright 2005 4G Systems <info@4g-systems.biz>, All Rights Reserved.
++ * http://www.4g-systems.biz
++ *
++ * 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.
++ *
++ * Neither Michael Stickel nor 4G Systeme GmbH admit liability nor provide
++ * warranty for any of this software. This material is provided
++ * "AS-IS" and at no charge.
++ *
++ * (c) Copyright 2005 4G Systems <info@4g-systems.biz>
++ *
++ * Release 0.01.
++ *
++ * Author: Michael Stickel michael.stickel@4g-systems.biz
++ *
++ *
++ * After the module is loaded there is a device /dev/misc/btn
++ * that can be read. It returns one char '1' if the button
++ * has been pressed an '0' if it has been released.
++ */
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/poll.h>
++#include <linux/sched.h>
++#include <linux/miscdevice.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++
++#include <asm/uaccess.h>
++
++#include <asm/mach-au1x00/au1000.h>
++
++
++#ifndef FALSE
++# define FALSE (0)
++#endif
++
++#ifndef TRUE
++# define TRUE (!FALSE)
++#endif
++
++
++//---------[ declarations ]-----------------
++
++
++static DECLARE_WAIT_QUEUE_HEAD(mtx1btn_wait_queue);
++static char state_changed;
++static char last_value;
++static char is_inuse;
++
++
++//---------[ Hardware Functions ]-----------------
++
++// The MTX-1 Button is attached to GPIO207.
++#define MTX1_GPIO2_SYSBTN (7)
++#define MTX1_SYSBTN_IRQ (AU1500_GPIO_207)
++
++
++static char mtx1_getbtn (int btnno)
++{
++ if (btnno==0) {
++ return (au_readl(GPIO2_PINSTATE) & (1<<MTX1_GPIO2_SYSBTN)) ? 0 : 1;
++ }
++ return 0;
++}
++
++static void mtx1_initbuttons (void)
++{
++ au_writel (au_readl(GPIO2_DIR) & ~(1<<MTX1_GPIO2_SYSBTN), GPIO2_DIR);
++}
++
++
++//---------[ Interrupt handling ]-----------------
++
++
++static void mtx1_btn_interrupt (int irq, void *private, struct pt_regs *regs)
++{
++ char value = mtx1_getbtn(0);
++ if (last_value != value)
++ {
++ last_value = value;
++ state_changed = 1;
++ wake_up (&mtx1btn_wait_queue);
++ }
++// kill_fasync(&async_queue, SIGIO, POLL_OUT);
++}
++
++
++static int mtx1_btn_startirq (void)
++{
++ if (!request_irq (MTX1_SYSBTN_IRQ, mtx1_btn_interrupt, 0 /* | SA_INTERRUPT */, "mtx1btn", (void *)&state_changed)) {
++ return 0;
++ }
++ return -1;
++}
++
++static int mtx1_btn_stopirq (void)
++{
++ free_irq(MTX1_SYSBTN_IRQ, (void *)&state_changed);
++ return 0;
++}
++
++
++
++//---------[ File Functions ]-----------------
++
++
++static int mtx1sysbtn_minor = -1;
++
++
++static int mtx1sysbtn_open (struct inode *inode, struct file *file)
++{
++ if (MINOR(inode->i_rdev)!=mtx1sysbtn_minor) return -ENODEV;
++ if (is_inuse) return -EBUSY;
++ is_inuse=1;
++ last_value = mtx1_getbtn(0);
++ state_changed = 0;
++ return 0;
++}
++
++
++static int mtx1sysbtn_release (struct inode *inode, struct file *file) {
++ if (MINOR(inode->i_rdev)==mtx1sysbtn_minor) {
++ is_inuse=0;
++ }
++ return 0;
++}
++
++
++static ssize_t mtx1sysbtn_read (struct file *file, char *buf, size_t count, loff_t *ppos)
++{
++ if (count < 1)
++ return -EINVAL;
++ if (!state_changed)
++ interruptible_sleep_on (&mtx1btn_wait_queue);
++ state_changed = 0;
++ char c = last_value ? '1' : '0'; /* mtx1_getbtn(0) */
++ if(copy_to_user(buf, &c, 1))
++ return -EFAULT;
++ return 1;
++}
++
++
++static unsigned int mtx1sysbtn_poll (struct file *file, poll_table * wait)
++{
++ unsigned int mask = 0;
++
++ poll_wait (file, &mtx1btn_wait_queue, wait);
++
++ if (state_changed) // state changed since last time.
++ mask |= POLLIN | POLLRDNORM;
++
++ return mask;
++}
++
++
++static struct file_operations mtx1sysbtn_fops = {
++ .owner = THIS_MODULE,
++ .read = mtx1sysbtn_read,
++ .poll = mtx1sysbtn_poll,
++ .open = mtx1sysbtn_open,
++ .release = mtx1sysbtn_release
++};
++
++
++static struct miscdevice mtx1sysbtn_miscdev = {
++ MISC_DYNAMIC_MINOR /* SYSBTN_MINOR */ ,
++ "btn",
++ &mtx1sysbtn_fops
++};
++
++
++
++//---------[ Module Functions ]-----------------
++
++
++void __exit exit_mtx1_sysbtn (void)
++{
++ is_inuse = 1;
++ mtx1_btn_stopirq ();
++ misc_deregister(&mtx1sysbtn_miscdev);
++}
++
++
++static int __init init_mtx1_sysbtn (void)
++{
++ printk("MTX-1 System Button driver\n");
++ is_inuse = 1;
++ mtx1_initbuttons ();
++ if (misc_register (&mtx1sysbtn_miscdev) >= 0) {
++ mtx1sysbtn_minor = mtx1sysbtn_miscdev.minor;
++ if (mtx1_btn_startirq () == 0) {
++ is_inuse=0;
++ return 0;
++ }
++ misc_deregister(&mtx1sysbtn_miscdev);
++ }
++ return 1;
++}
++
++module_init(init_mtx1_sysbtn);
++module_exit(exit_mtx1_sysbtn);
++
++MODULE_AUTHOR("Michael Stickel");
++MODULE_DESCRIPTION("Driver for the MTX-1 system button");
++MODULE_LICENSE("GPL");
diff --git a/target/linux/au1000-2.6/patches/007-mtx1_sio2.patch b/target/linux/au1000-2.6/patches/007-mtx1_sio2.patch
new file mode 100644
index 0000000000..34d1005347
--- /dev/null
+++ b/target/linux/au1000-2.6/patches/007-mtx1_sio2.patch
@@ -0,0 +1,13 @@
+--- linux-2.6.16.7/arch/mips/au1000/mtx-1/board_setup.c 2006-04-17 23:53:25.000000000 +0200
++++ linux-2.6.16.7.new/arch/mips/au1000/mtx-1/board_setup.c 2006-04-23 14:35:42.000000000 +0200
+@@ -71,9 +71,7 @@
+ #endif
+
+ // initialize sys_pinfunc:
+- // disable second ethernet port (SYS_PF_NI2)
+- // set U3/GPIO23 to GPIO23 (SYS_PF_U3)
+- au_writel( SYS_PF_NI2 | SYS_PF_U3, SYS_PINFUNC );
++ au_writel( SYS_PF_NI2, SYS_PINFUNC );
+
+ // initialize GPIO
+ au_writel( 0xFFFFFFFF, SYS_TRIOUTCLR );
diff --git a/target/linux/au1000-2.6/patches/008-isdel_cardbus.patch b/target/linux/au1000-2.6/patches/008-isdel_cardbus.patch
new file mode 100644
index 0000000000..9e54ac1c59
--- /dev/null
+++ b/target/linux/au1000-2.6/patches/008-isdel_cardbus.patch
@@ -0,0 +1,63 @@
+diff -urN linux-2.6.16.7/arch/mips/au1000/mtx-1/board_setup.c linux-2.6.16.7.new/arch/mips/au1000/mtx-1/board_setup.c
+--- linux-2.6.16.7/arch/mips/au1000/mtx-1/board_setup.c 2006-04-23 14:39:21.000000000 +0200
++++ linux-2.6.16.7.new/arch/mips/au1000/mtx-1/board_setup.c 2006-04-23 14:39:03.000000000 +0200
+@@ -44,6 +44,9 @@
+ #include <asm/pgtable.h>
+ #include <asm/mach-au1x00/au1000.h>
+
++extern int (*board_pci_idsel)(unsigned int devsel, int assert);
++int mtx1_pci_idsel(unsigned int devsel, int assert);
++
+ void board_reset (void)
+ {
+ /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
+@@ -77,11 +80,37 @@
+ au_writel( 0xFFFFFFFF, SYS_TRIOUTCLR );
+ au_writel( 0x00000001, SYS_OUTPUTCLR ); // set M66EN (PCI 66MHz) to OFF
+ au_writel( 0x00000008, SYS_OUTPUTSET ); // set PCI CLKRUN# to OFF
++ au_writel( 0x00000002, SYS_OUTPUTSET ); // set EXT_IO3 ON
+ au_writel( 0x00000020, SYS_OUTPUTCLR ); // set eth PHY TX_ER to OFF
+
+ // enable LED and set it to green
+ au_writel( au_readl(GPIO2_DIR) | 0x1800, GPIO2_DIR );
+ au_writel( 0x18000800, GPIO2_OUTPUT );
+
++ board_pci_idsel = mtx1_pci_idsel;
++
+ printk("4G Systems MTX-1 Board\n");
+ }
++
++int
++mtx1_pci_idsel(unsigned int devsel, int assert)
++{
++#define MTX_IDSEL_ONLY_0_AND_3 0
++#if MTX_IDSEL_ONLY_0_AND_3
++ if (devsel != 0 && devsel != 3) {
++ printk("*** not 0 or 3\n");
++ return 0;
++ }
++#endif
++
++ if (assert && devsel != 0) {
++ // supress signal to cardbus
++ au_writel( 0x00000002, SYS_OUTPUTCLR ); // set EXT_IO3 OFF
++ }
++ else {
++ au_writel( 0x00000002, SYS_OUTPUTSET ); // set EXT_IO3 ON
++ }
++ au_sync_udelay(1);
++ return 1;
++}
++
+diff -urN linux-2.6.16.7/arch/mips/au1000/mtx-1/irqmap.c linux-2.6.16.7.new/arch/mips/au1000/mtx-1/irqmap.c
+--- linux-2.6.16.7/arch/mips/au1000/mtx-1/irqmap.c 2006-04-23 14:40:54.000000000 +0200
++++ linux-2.6.16.7.new/arch/mips/au1000/mtx-1/irqmap.c 2006-04-23 14:40:12.000000000 +0200
+@@ -48,7 +48,7 @@
+ #include <asm/mach-au1x00/au1000.h>
+
+ char irq_tab_alchemy[][5] __initdata = {
+- [0] = { -1, INTA, INTB, INTX, INTX}, /* IDSEL 00 - AdapterA-Slot0 (top) */
++ [0] = { -1, INTA, INTA, INTX, INTX}, /* IDSEL 00 - AdapterA-Slot0 (top) */
+ [1] = { -1, INTB, INTA, INTX, INTX}, /* IDSEL 01 - AdapterA-Slot1 (bottom) */
+ [2] = { -1, INTC, INTD, INTX, INTX}, /* IDSEL 02 - AdapterB-Slot0 (top) */
+ [3] = { -1, INTD, INTC, INTX, INTX}, /* IDSEL 03 - AdapterB-Slot1 (bottom) */
diff --git a/target/linux/brcm-2.4/Makefile b/target/linux/brcm-2.4/Makefile
new file mode 100644
index 0000000000..33cb47cf50
--- /dev/null
+++ b/target/linux/brcm-2.4/Makefile
@@ -0,0 +1,22 @@
+#
+# 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
+
+LINUX_VERSION:=2.4.32
+LINUX_RELEASE:=1
+LINUX_KERNEL_MD5SUM:=38f4d0830e95a20f4bfed17622d5557c
+
+include ./config
+include $(INCLUDE_DIR)/kernel.mk
+include $(INCLUDE_DIR)/kernel-build.mk
+
+$(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked
+ [ -d ../generic-$(KERNEL)/patches ] && $(PATCH) $(LINUX_DIR) ../generic-$(KERNEL)/patches
+ [ -d ./patches ] && $(PATCH) $(LINUX_DIR) ./patches
+ @$(CP) config $(LINUX_DIR)/.config
+ touch $@
+
diff --git a/target/linux/brcm-2.4/config b/target/linux/brcm-2.4/config
new file mode 100644
index 0000000000..7b0020722b
--- /dev/null
+++ b/target/linux/brcm-2.4/config
@@ -0,0 +1,1385 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+CONFIG_MIPS=y
+CONFIG_MIPS32=y
+# CONFIG_MIPS64 is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
+
+#
+# Machine selection
+#
+# CONFIG_ACER_PICA_61 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_FICMMP is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_HYDROGEN3 is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_COGENT_CSB250 is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_CASIO_E55 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MAGNUM_4000 is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_BIG_SUR is not set
+# CONFIG_PMC_STRETCH is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_NEC_EAGLE is not set
+# CONFIG_OLIVETTI_M700 is not set
+# CONFIG_NINO is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+CONFIG_MIPS_BRCM=y
+CONFIG_BCM947XX=y
+CONFIG_BCM4710=y
+CONFIG_BCM4310=y
+CONFIG_BCM4704=y
+CONFIG_BCM5365=y
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TANBAC_TB0226 is not set
+# CONFIG_TANBAC_TB0229 is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=squashfs,jffs2 init=/etc/preinit noinitrd console=ttyS0,115200"
+CONFIG_PCI=y
+CONFIG_NONCOHERENT_IO=y
+CONFIG_NEW_TIME_C=y
+CONFIG_NEW_IRQ=y
+# CONFIG_MIPS_AU1000 is not set
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_VTAG_ICACHE is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_LLDSCD is not set
+# CONFIG_CPU_HAS_WB is not set
+CONFIG_CPU_HAS_SYNC=y
+
+#
+# General setup
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_BUILD_ELF64 is not set
+CONFIG_NET=y
+CONFIG_PCI=y
+# CONFIG_PCI_NEW is not set
+CONFIG_PCI_AUTO=y
+# CONFIG_PCI_NAMES is not set
+# CONFIG_ISA is not set
+# CONFIG_TC is not set
+# CONFIG_MCA is not set
+# CONFIG_SBUS is not set
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+CONFIG_CARDBUS=y
+# CONFIG_TCIC is not set
+# CONFIG_I82092 is not set
+# CONFIG_I82365 is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_HOTPLUG_PCI_COMPAQ is not set
+# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set
+# CONFIG_HOTPLUG_PCI_PCIE is not set
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_ELF_AOUT is not set
+# CONFIG_MIPS32_COMPAT is not set
+# CONFIG_MIPS32_O32 is not set
+# CONFIG_MIPS32_N32 is not set
+# CONFIG_BINFMT_ELF32 is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_OOM_KILLER is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_CFI_B1 is not set
+CONFIG_MTD_CFI_B2=y
+# CONFIG_MTD_CFI_B4 is not set
+# CONFIG_MTD_CFI_B8 is not set
+CONFIG_MTD_CFI_I1=y
+# CONFIG_MTD_CFI_I2 is not set
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_SSTSTD=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_AMDSTD is not set
+# CONFIG_MTD_SHARP is not set
+# CONFIG_MTD_JEDEC is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_BCM947XX=y
+# CONFIG_MTD_PB1000 is not set
+# CONFIG_MTD_PB1500 is not set
+# CONFIG_MTD_PB1100 is not set
+# CONFIG_MTD_BOSPORUS is not set
+# CONFIG_MTD_XXS1500 is not set
+# CONFIG_MTD_MTX1 is not set
+# CONFIG_MTD_DB1X00 is not set
+# CONFIG_MTD_PB1550 is not set
+# CONFIG_MTD_HYDROGEN3 is not set
+# CONFIG_MTD_MIRAGE is not set
+# CONFIG_MTD_CSTM_MIPS_IXX is not set
+# CONFIG_MTD_OCELOT is not set
+# CONFIG_MTD_LASAT is not set
+# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PCMCIA is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_SFLASH=y
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+# CONFIG_PARPORT_PC is not set
+CONFIG_PARPORT_SPLINK=m
+# CONFIG_PARPORT_AMIGA is not set
+# CONFIG_PARPORT_MFC3 is not set
+# CONFIG_PARPORT_ATARI is not set
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_SUNBPP is not set
+# CONFIG_PARPORT_IP22 is not set
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_STATS is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_FILTER=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_NAT=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_TOS=y
+# CONFIG_IP_ROUTE_VERBOSE is not set
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_FTP=y
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_IRC=y
+CONFIG_IP_NF_CT_ACCT=m
+CONFIG_IP_NF_MATCH_CONNBYTES=m
+CONFIG_IP_NF_CT_PROTO_GRE=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_MMS=m
+CONFIG_IP_NF_RTSP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_QUOTA=m
+CONFIG_IP_NF_SET=m
+CONFIG_IP_NF_SET_MAX=256
+CONFIG_IP_NF_SET_HASHSIZE=1024
+CONFIG_IP_NF_MATCH_SET=m
+CONFIG_IP_NF_TARGET_SET=m
+CONFIG_IP_NF_SET_IPMAP=m
+CONFIG_IP_NF_SET_PORTMAP=m
+CONFIG_IP_NF_SET_MACIPMAP=m
+CONFIG_IP_NF_SET_IPHASH=m
+CONFIG_IP_NF_SET_NETHASH=m
+CONFIG_IP_NF_SET_IPTREE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=y
+CONFIG_IP_NF_MATCH_MULTIPORT=y
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TIME=m
+CONFIG_IP_NF_MATCH_CONDITION=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_IPP2P=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=y
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_UNCLEAN=m
+CONFIG_IP_NF_MATCH_STRING=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_LAYER7=m
+# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
+CONFIG_IP_NF_MATCH_LAYER7_MAXDATALEN=2048
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_MIRROR=m
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_PROTO_GRE=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_MMS=m
+CONFIG_IP_NF_NAT_RTSP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=y
+CONFIG_IP_NF_NAT_FTP=y
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=y
+CONFIG_IP_NF_TARGET_IMQ=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=y
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_CONDITION=m
+CONFIG_IP6_NF_MATCH_MAC=m
+# CONFIG_IP6_NF_MATCH_RT is not set
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
+# CONFIG_IP6_NF_MATCH_AHESP is not set
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_TARGET_IMQ=m
+# CONFIG_KHTTPD is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+CONFIG_VLAN_8021Q=y
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+CONFIG_BRIDGE=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_CSZ=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+# CONFIG_NET_SCH_NETEM is not set
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_POLICE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_IPSEC_NAT_TRAVERSAL=y
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+# CONFIG_PHONE_IXJ is not set
+# CONFIG_PHONE_IXJ_PCMCIA is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=m
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=m
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_IDEDISK_STROKE=y
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_DELKIN is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+CONFIG_BLK_DEV_OFFBOARD=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_PCI_WIP is not set
+# CONFIG_BLK_DEV_ADMA100 is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_WDC_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_AMD74XX_OVERRIDE is not set
+# CONFIG_BLK_DEV_ATIIXP is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_HPT34X_AUTODMA is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=m
+CONFIG_PDC202XX_BURST=y
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SIS5513 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_IDEDMA_AUTO=y
+CONFIG_IDEDMA_IVB=y
+# CONFIG_DMA_NONPCI is not set
+CONFIG_BLK_DEV_PDC202XX=y
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_BLK_DEV_ATARAID_MEDLEY is not set
+# CONFIG_BLK_DEV_ATARAID_SII is not set
+
+#
+# SCSI support
+#
+CONFIG_SCSI=m
+CONFIG_BLK_DEV_SD=m
+CONFIG_SD_EXTRA_DEVS=5
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_SCSI_DEBUG_QUEUES is not set
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_MEGARAID2 is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_SATA_AHCI is not set
+# CONFIG_SCSI_SATA_SVW is not set
+# CONFIG_SCSI_ATA_PIIX is not set
+# CONFIG_SCSI_SATA_NV is not set
+# CONFIG_SCSI_SATA_QSTOR is not set
+# CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_SX4 is not set
+# CONFIG_SCSI_SATA_SIL is not set
+# CONFIG_SCSI_SATA_SIS is not set
+# CONFIG_SCSI_SATA_ULI is not set
+# CONFIG_SCSI_SATA_VIA is not set
+# CONFIG_SCSI_SATA_VITESSE is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_DMA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_NCR53C8XX is not set
+# CONFIG_SCSI_SYM53C8XX is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_SCSI_PCMCIA is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_BOOT is not set
+# CONFIG_FUSION_ISENSE is not set
+# CONFIG_FUSION_CTL is not set
+# CONFIG_FUSION_LAN is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_IMQ=m
+CONFIG_TUN=m
+CONFIG_NET_RANDOM=y
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_SUNLANCE is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_APRICOT is not set
+CONFIG_B44=y
+# CONFIG_CS89x0 is not set
+# CONFIG_TULIP is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_DGRS is not set
+# CONFIG_DM9102 is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_EEPRO100_PIO is not set
+# CONFIG_E100 is not set
+# CONFIG_LNE390 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_SUNDANCE_MMIO is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_RHINE_MMIO is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_LAN_SAA9730 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE_MPPC=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_STRIP is not set
+# CONFIG_WAVELAN is not set
+# CONFIG_ARLAN is not set
+# CONFIG_AIRONET4500 is not set
+# CONFIG_AIRONET4500_NONCS is not set
+# CONFIG_AIRONET4500_PROC is not set
+# CONFIG_AIRO is not set
+# CONFIG_HERMES is not set
+# CONFIG_PLX_HERMES is not set
+# CONFIG_TMD_HERMES is not set
+# CONFIG_PCI_HERMES is not set
+# CONFIG_PCMCIA_HERMES is not set
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_ATMEL is not set
+# CONFIG_PRISM54 is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+CONFIG_SHAPER=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Amateur Radio support
+#
+CONFIG_HAMRADIO=y
+CONFIG_AX25=m
+# CONFIG_AX25_DAMA_SLAVE is not set
+# CONFIG_NETROM is not set
+# CONFIG_ROSE is not set
+
+#
+# AX.25 network device drivers
+#
+CONFIG_MKISS=m
+# CONFIG_6PACK is not set
+# CONFIG_BPQETHER is not set
+# CONFIG_SCC_DELAY is not set
+# CONFIG_SCC_TRXECHO is not set
+# CONFIG_BAYCOM_SER_FDX is not set
+# CONFIG_BAYCOM_SER_HDX is not set
+# CONFIG_BAYCOM_PAR is not set
+# CONFIG_BAYCOM_EPP is not set
+# CONFIG_SOUNDMODEM is not set
+# CONFIG_YAM is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_UINPUT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=128
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+CONFIG_PPDEV=m
+# CONFIG_TIPAR is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_IPMI_PANIC_EVENT is not set
+# CONFIG_IPMI_DEVICE_INTERFACE is not set
+# CONFIG_IPMI_KCS is not set
+# CONFIG_IPMI_WATCHDOG is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+# CONFIG_ALIM1535_WDT is not set
+# CONFIG_ALIM7101_WDT is not set
+# CONFIG_SC520_WDT is not set
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+# CONFIG_WAFER_WDT is not set
+# CONFIG_I810_TCO is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_SC1200_WDT is not set
+# CONFIG_SCx200_WDT is not set
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_W83877F_WDT is not set
+# CONFIG_WDT is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_MACHZ_WDT is not set
+# CONFIG_SCx200 is not set
+# CONFIG_SCx200_GPIO is not set
+# CONFIG_AMD_PM768 is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+CONFIG_PCMCIA_SERIAL_CS=m
+# CONFIG_SYNCLINK_CS is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+CONFIG_EXT3_FS=m
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FAT_FS=m
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=m
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_BBC_ARMLIB is not set
+# CONFIG_JFFS2_BBC_LZO is not set
+CONFIG_JFFS2_BBC_LZARI=y
+# CONFIG_JFFS2_BBC_LZHD is not set
+# CONFIG_JFFS2_BBC_LZSS is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_MINIX_FS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=m
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_SUNRPC=m
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_POSIX=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SMB_NLS is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+CONFIG_VIDEO_PROC_FS=y
+# CONFIG_I2C_PARPORT is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_BWQCAM is not set
+# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN_BUZ is not set
+# CONFIG_VIDEO_ZORAN_DC10 is not set
+# CONFIG_VIDEO_ZORAN_LML33 is not set
+# CONFIG_VIDEO_ZR36120 is not set
+# CONFIG_VIDEO_MEYE is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_MIROPCM20 is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+# CONFIG_SOUND_ALI5455 is not set
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_MIDI_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_FORTE is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_MIDI_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+# CONFIG_SOUND_WM97XX is not set
+
+#
+# USB support
+#
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_UHCI is not set
+CONFIG_USB_UHCI_ALT=m
+CONFIG_USB_OHCI=m
+CONFIG_USB_AUDIO=m
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_MIDI is not set
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+# CONFIG_USB_STORAGE_ISD200 is not set
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_HP8200e=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+# CONFIG_USB_HID is not set
+# CONFIG_USB_HIDINPUT is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_OV511 is not set
+CONFIG_USB_PWC=m
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_W9968CF is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_CDCETHER is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_USS720 is not set
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_SERIAL_DEBUG is not set
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_BELKIN=m
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_BRLVGER is not set
+# CONFIG_USB_LCD is not set
+
+#
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+CONFIG_BLUEZ=m
+CONFIG_BLUEZ_L2CAP=m
+CONFIG_BLUEZ_SCO=m
+CONFIG_BLUEZ_RFCOMM=m
+CONFIG_BLUEZ_RFCOMM_TTY=y
+CONFIG_BLUEZ_BNEP=m
+CONFIG_BLUEZ_BNEP_MC_FILTER=y
+CONFIG_BLUEZ_BNEP_PROTO_FILTER=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BLUEZ_HCIUSB=m
+CONFIG_BLUEZ_HCIUSB_SCO=y
+CONFIG_BLUEZ_HCIUART=m
+CONFIG_BLUEZ_HCIUART_H4=y
+CONFIG_BLUEZ_HCIUART_BCSP=y
+CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y
+# CONFIG_BLUEZ_HCIBFUSB is not set
+# CONFIG_BLUEZ_HCIDTL1 is not set
+# CONFIG_BLUEZ_HCIBT3C is not set
+# CONFIG_BLUEZ_HCIBLUECARD is not set
+# CONFIG_BLUEZ_HCIBTUART is not set
+# CONFIG_BLUEZ_HCIVHCI is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+# CONFIG_RUNTIME_DEBUG is not set
+# CONFIG_REMOTE_DEBUG is not set
+# CONFIG_GDB_CONSOLE is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_MIPS_UNCACHED is not set
+CONFIG_LOG_BUF_SHIFT=0
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+# CONFIG_FW_LOADER is not set
diff --git a/target/linux/brcm-2.4/patches/001-bcm47xx.patch b/target/linux/brcm-2.4/patches/001-bcm47xx.patch
new file mode 100644
index 0000000000..726eba8061
--- /dev/null
+++ b/target/linux/brcm-2.4/patches/001-bcm47xx.patch
@@ -0,0 +1,16794 @@
+diff -urN linux.old/arch/mips/bcm947xx/bcmsrom.c linux.dev/arch/mips/bcm947xx/bcmsrom.c
+--- linux.old/arch/mips/bcm947xx/bcmsrom.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/bcmsrom.c 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,1212 @@
++/*
++ * Misc useful routines to access NIC SROM/OTP .
++ *
++ * 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.
++ * $Id: bcmsrom.c,v 1.1.1.14 2006/04/15 01:28:25 michael Exp $
++ */
++
++#include <typedefs.h>
++#include <bcmdefs.h>
++#include <osl.h>
++#include <bcmutils.h>
++#include <bcmsrom.h>
++#include <bcmdevs.h>
++#include <bcmendian.h>
++#include <sbpcmcia.h>
++#include <pcicfg.h>
++#include <sbutils.h>
++#include <bcmnvram.h>
++
++/* debug/trace */
++#if defined(WLTEST)
++#define BS_ERROR(args) printf args
++#else
++#define BS_ERROR(args)
++#endif /* BCMDBG_ERR || WLTEST */
++
++#define VARS_MAX 4096 /* should be reduced */
++
++#define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */
++#define WRITE_WORD_DELAY 20 /* 20 ms between each word write */
++
++static int initvars_srom_pci(void *sbh, void *curmap, char **vars, uint *count);
++static int initvars_cis_pcmcia(void *sbh, osl_t *osh, char **vars, uint *count);
++static int initvars_flash_sb(void *sbh, char **vars, uint *count);
++static int srom_parsecis(osl_t *osh, uint8 **pcis, uint ciscnt, char **vars, uint *count);
++static int sprom_cmd_pcmcia(osl_t *osh, uint8 cmd);
++static int sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data);
++static int sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data);
++static int sprom_read_pci(osl_t *osh, uint16 *sprom, uint wordoff, uint16 *buf, uint nwords,
++ bool check_crc);
++
++static int initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count);
++static int initvars_flash(osl_t *osh, char **vp, uint len, char *devpath);
++
++/*
++ * Initialize local vars from the right source for this platform.
++ * Return 0 on success, nonzero on error.
++ */
++int
++srom_var_init(void *sbh, uint bustype, void *curmap, osl_t *osh, char **vars, uint *count)
++{
++ ASSERT(bustype == BUSTYPE(bustype));
++ if (vars == NULL || count == NULL)
++ return (0);
++
++ switch (BUSTYPE(bustype)) {
++ case SB_BUS:
++ case JTAG_BUS:
++ return initvars_flash_sb(sbh, vars, count);
++
++ case PCI_BUS:
++ ASSERT(curmap); /* can not be NULL */
++ return initvars_srom_pci(sbh, curmap, vars, count);
++
++ case PCMCIA_BUS:
++ return initvars_cis_pcmcia(sbh, osh, vars, count);
++
++
++ default:
++ ASSERT(0);
++ }
++ return (-1);
++}
++
++/* support only 16-bit word read from srom */
++int
++srom_read(uint bustype, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf)
++{
++ void *srom;
++ uint i, off, nw;
++
++ ASSERT(bustype == BUSTYPE(bustype));
++
++ /* check input - 16-bit access only */
++ if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > (SPROM_SIZE * 2))
++ return 1;
++
++ off = byteoff / 2;
++ nw = nbytes / 2;
++
++ if (BUSTYPE(bustype) == PCI_BUS) {
++ if (!curmap)
++ return 1;
++ srom = (uchar*)curmap + PCI_BAR0_SPROM_OFFSET;
++ if (sprom_read_pci(osh, srom, off, buf, nw, FALSE))
++ return 1;
++ } else if (BUSTYPE(bustype) == PCMCIA_BUS) {
++ for (i = 0; i < nw; i++) {
++ if (sprom_read_pcmcia(osh, (uint16)(off + i), (uint16*)(buf + i)))
++ return 1;
++ }
++ } else {
++ return 1;
++ }
++
++ return 0;
++}
++
++/* support only 16-bit word write into srom */
++int
++srom_write(uint bustype, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf)
++{
++ uint16 *srom;
++ uint i, nw, crc_range;
++ uint16 image[SPROM_SIZE];
++ uint8 crc;
++ volatile uint32 val32;
++
++ ASSERT(bustype == BUSTYPE(bustype));
++
++ /* check input - 16-bit access only */
++ if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > (SPROM_SIZE * 2))
++ return 1;
++
++ /* Are we writing the whole thing at once? */
++ if ((byteoff == 0) &&
++ ((nbytes == SPROM_SIZE) ||
++ (nbytes == (SPROM_CRC_RANGE * 2)) ||
++ (nbytes == (SROM4_WORDS * 2)))) {
++ crc_range = nbytes;
++ bcopy((void*)buf, (void*)image, nbytes);
++ nw = nbytes / 2;
++ } else {
++ if ((BUSTYPE(bustype) == PCMCIA_BUS) || (BUSTYPE(bustype) == SDIO_BUS))
++ crc_range = SPROM_SIZE;
++ else
++ crc_range = SPROM_CRC_RANGE * 2; /* Tentative */
++
++ nw = crc_range / 2;
++ /* read first 64 words from srom */
++ if (srom_read(bustype, curmap, osh, 0, nw * 2, image))
++ return 1;
++ if (image[SROM4_SIGN] == SROM4_SIGNATURE) {
++ crc_range = SROM4_WORDS;
++ nw = crc_range / 2;
++ if (srom_read(bustype, curmap, osh, 0, nw * 2, image))
++ return 1;
++ }
++ /* make changes */
++ bcopy((void*)buf, (void*)&image[byteoff / 2], nbytes);
++ }
++
++ /* calculate crc */
++ htol16_buf(image, crc_range);
++ crc = ~hndcrc8((uint8 *)image, crc_range - 1, CRC8_INIT_VALUE);
++ ltoh16_buf(image, crc_range);
++ image[(crc_range / 2) - 1] = (crc << 8) | (image[(crc_range / 2) - 1] & 0xff);
++
++ if (BUSTYPE(bustype) == PCI_BUS) {
++ srom = (uint16*)((uchar*)curmap + PCI_BAR0_SPROM_OFFSET);
++ /* enable writes to the SPROM */
++ val32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32));
++ val32 |= SPROM_WRITEEN;
++ OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32);
++ bcm_mdelay(WRITE_ENABLE_DELAY);
++ /* write srom */
++ for (i = 0; i < nw; i++) {
++ W_REG(osh, &srom[i], image[i]);
++ bcm_mdelay(WRITE_WORD_DELAY);
++ }
++ /* disable writes to the SPROM */
++ OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 &
++ ~SPROM_WRITEEN);
++ } else if (BUSTYPE(bustype) == PCMCIA_BUS) {
++ /* enable writes to the SPROM */
++ if (sprom_cmd_pcmcia(osh, SROM_WEN))
++ return 1;
++ bcm_mdelay(WRITE_ENABLE_DELAY);
++ /* write srom */
++ for (i = 0; i < nw; i++) {
++ sprom_write_pcmcia(osh, (uint16)(i), image[i]);
++ bcm_mdelay(WRITE_WORD_DELAY);
++ }
++ /* disable writes to the SPROM */
++ if (sprom_cmd_pcmcia(osh, SROM_WDS))
++ return 1;
++ } else {
++ return 1;
++ }
++
++ bcm_mdelay(WRITE_ENABLE_DELAY);
++ return 0;
++}
++
++
++static int
++srom_parsecis(osl_t *osh, uint8 **pcis, uint ciscnt, char **vars, uint *count)
++{
++ char eabuf[32];
++ char *vp, *base;
++ uint8 *cis, tup, tlen, sromrev = 1;
++ int i, j;
++ uint varsize;
++ bool ag_init = FALSE;
++ uint32 w32;
++
++ ASSERT(vars);
++ ASSERT(count);
++
++ base = vp = MALLOC(osh, VARS_MAX);
++ ASSERT(vp);
++ if (!vp)
++ return -2;
++
++ while (ciscnt--) {
++ cis = *pcis++;
++ i = 0;
++ do {
++ tup = cis[i++];
++ tlen = cis[i++];
++ if ((i + tlen) >= CIS_SIZE)
++ break;
++
++ switch (tup) {
++ case CISTPL_MANFID:
++ vp += sprintf(vp, "manfid=%d", (cis[i + 1] << 8) + cis[i]);
++ vp++;
++ vp += sprintf(vp, "prodid=%d", (cis[i + 3] << 8) + cis[i + 2]);
++ vp++;
++ break;
++
++ case CISTPL_FUNCE:
++ switch (cis[i]) {
++ case LAN_NID:
++ ASSERT(cis[i + 1] == 6);
++ bcm_ether_ntoa((struct ether_addr *)&cis[i + 2], eabuf);
++ vp += sprintf(vp, "il0macaddr=%s", eabuf);
++ vp++;
++ break;
++ case 1: /* SDIO Extended Data */
++ vp += sprintf(vp, "sdmaxblk=%d",
++ (cis[i + 13] << 8) | cis[i + 12]);
++ vp++;
++ break;
++ }
++ break;
++
++ case CISTPL_CFTABLE:
++ vp += sprintf(vp, "regwindowsz=%d", (cis[i + 7] << 8) | cis[i + 6]);
++ vp++;
++ break;
++
++ case CISTPL_BRCM_HNBU:
++ switch (cis[i]) {
++ case HNBU_SROMREV:
++ sromrev = cis[i + 1];
++ break;
++
++ case HNBU_CHIPID:
++ vp += sprintf(vp, "vendid=%d", (cis[i + 2] << 8) +
++ cis[i + 1]);
++ vp++;
++ vp += sprintf(vp, "devid=%d", (cis[i + 4] << 8) +
++ cis[i + 3]);
++ vp++;
++ if (tlen == 7) {
++ vp += sprintf(vp, "chiprev=%d",
++ (cis[i + 6] << 8) + cis[i + 5]);
++ vp++;
++ }
++ break;
++
++ case HNBU_BOARDREV:
++ vp += sprintf(vp, "boardrev=%d", cis[i + 1]);
++ vp++;
++ break;
++
++ case HNBU_AA:
++ vp += sprintf(vp, "aa2g=%d", cis[i + 1]);
++ vp++;
++ break;
++
++ case HNBU_AG:
++ vp += sprintf(vp, "ag0=%d", cis[i + 1]);
++ vp++;
++ ag_init = TRUE;
++ break;
++
++ case HNBU_CC:
++ ASSERT(sromrev == 1);
++ vp += sprintf(vp, "cc=%d", cis[i + 1]);
++ vp++;
++ break;
++
++ case HNBU_PAPARMS:
++ if (tlen == 2) {
++ ASSERT(sromrev == 1);
++ vp += sprintf(vp, "pa0maxpwr=%d", cis[i + 1]);
++ vp++;
++ } else if (tlen >= 9) {
++ if (tlen == 10) {
++ ASSERT(sromrev == 2);
++ vp += sprintf(vp, "opo=%d", cis[i + 9]);
++ vp++;
++ } else
++ ASSERT(tlen == 9);
++
++ for (j = 0; j < 3; j++) {
++ vp += sprintf(vp, "pa0b%d=%d", j,
++ (cis[i + (j * 2) + 2] << 8) +
++ cis[i + (j * 2) + 1]);
++ vp++;
++ }
++ vp += sprintf(vp, "pa0itssit=%d", cis[i + 7]);
++ vp++;
++ vp += sprintf(vp, "pa0maxpwr=%d", cis[i + 8]);
++ vp++;
++ } else
++ ASSERT(tlen >= 9);
++ break;
++
++ case HNBU_OEM:
++ ASSERT(sromrev == 1);
++ vp += sprintf(vp, "oem=%02x%02x%02x%02x%02x%02x%02x%02x",
++ cis[i + 1], cis[i + 2],
++ cis[i + 3], cis[i + 4],
++ cis[i + 5], cis[i + 6],
++ cis[i + 7], cis[i + 8]);
++ vp++;
++ break;
++
++ case HNBU_BOARDFLAGS:
++ w32 = (cis[i + 2] << 8) + cis[i + 1];
++ if (tlen == 5)
++ w32 |= (cis[i + 4] << 24) + (cis[i + 3] << 16);
++ vp += sprintf(vp, "boardflags=0x%x", w32);
++ vp++;
++ break;
++
++ case HNBU_LEDS:
++ if (cis[i + 1] != 0xff) {
++ vp += sprintf(vp, "ledbh0=%d", cis[i + 1]);
++ vp++;
++ }
++ if (cis[i + 2] != 0xff) {
++ vp += sprintf(vp, "ledbh1=%d", cis[i + 2]);
++ vp++;
++ }
++ if (cis[i + 3] != 0xff) {
++ vp += sprintf(vp, "ledbh2=%d", cis[i + 3]);
++ vp++;
++ }
++ if (cis[i + 4] != 0xff) {
++ vp += sprintf(vp, "ledbh3=%d", cis[i + 4]);
++ vp++;
++ }
++ break;
++
++ case HNBU_CCODE:
++ {
++ char str[3];
++ ASSERT(sromrev > 1);
++ str[0] = cis[i + 1];
++ str[1] = cis[i + 2];
++ str[2] = 0;
++ vp += sprintf(vp, "ccode=%s", str);
++ vp++;
++ vp += sprintf(vp, "cctl=0x%x", cis[i + 3]);
++ vp++;
++ break;
++ }
++
++ case HNBU_CCKPO:
++ ASSERT(sromrev > 2);
++ vp += sprintf(vp, "cckpo=0x%x",
++ (cis[i + 2] << 8) | cis[i + 1]);
++ vp++;
++ break;
++
++ case HNBU_OFDMPO:
++ ASSERT(sromrev > 2);
++ vp += sprintf(vp, "ofdmpo=0x%x",
++ (cis[i + 4] << 24) |
++ (cis[i + 3] << 16) |
++ (cis[i + 2] << 8) |
++ cis[i + 1]);
++ vp++;
++ break;
++ }
++ break;
++
++ }
++ i += tlen;
++ } while (tup != 0xff);
++ }
++
++ /* Set the srom version */
++ vp += sprintf(vp, "sromrev=%d", sromrev);
++ vp++;
++
++ /* if there is no antenna gain field, set default */
++ if (ag_init == FALSE) {
++ ASSERT(sromrev == 1);
++ vp += sprintf(vp, "ag0=%d", 0xff);
++ vp++;
++ }
++
++ /* final nullbyte terminator */
++ *vp++ = '\0';
++ varsize = (uint)(vp - base);
++
++ ASSERT((vp - base) < VARS_MAX);
++
++ if (varsize == VARS_MAX) {
++ *vars = base;
++ } else {
++ vp = MALLOC(osh, varsize);
++ ASSERT(vp);
++ if (vp)
++ bcopy(base, vp, varsize);
++ MFREE(osh, base, VARS_MAX);
++ *vars = vp;
++ if (!vp) {
++ *count = 0;
++ return -2;
++ }
++ }
++ *count = varsize;
++
++ return (0);
++}
++
++
++/* set PCMCIA sprom command register */
++static int
++sprom_cmd_pcmcia(osl_t *osh, uint8 cmd)
++{
++ uint8 status = 0;
++ uint wait_cnt = 1000;
++
++ /* write sprom command register */
++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_CS, &cmd, 1);
++
++ /* wait status */
++ while (wait_cnt--) {
++ OSL_PCMCIA_READ_ATTR(osh, SROM_CS, &status, 1);
++ if (status & SROM_DONE)
++ return 0;
++ }
++
++ return 1;
++}
++
++/* read a word from the PCMCIA srom */
++static int
++sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data)
++{
++ uint8 addr_l, addr_h, data_l, data_h;
++
++ addr_l = (uint8)((addr * 2) & 0xff);
++ addr_h = (uint8)(((addr * 2) >> 8) & 0xff);
++
++ /* set address */
++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1);
++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1);
++
++ /* do read */
++ if (sprom_cmd_pcmcia(osh, SROM_READ))
++ return 1;
++
++ /* read data */
++ data_h = data_l = 0;
++ OSL_PCMCIA_READ_ATTR(osh, SROM_DATAH, &data_h, 1);
++ OSL_PCMCIA_READ_ATTR(osh, SROM_DATAL, &data_l, 1);
++
++ *data = (data_h << 8) | data_l;
++ return 0;
++}
++
++/* write a word to the PCMCIA srom */
++static int
++sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data)
++{
++ uint8 addr_l, addr_h, data_l, data_h;
++
++ addr_l = (uint8)((addr * 2) & 0xff);
++ addr_h = (uint8)(((addr * 2) >> 8) & 0xff);
++ data_l = (uint8)(data & 0xff);
++ data_h = (uint8)((data >> 8) & 0xff);
++
++ /* set address */
++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1);
++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1);
++
++ /* write data */
++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAH, &data_h, 1);
++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAL, &data_l, 1);
++
++ /* do write */
++ return sprom_cmd_pcmcia(osh, SROM_WRITE);
++}
++
++/*
++ * Read in and validate sprom.
++ * Return 0 on success, nonzero on error.
++ */
++static int
++sprom_read_pci(osl_t *osh, uint16 *sprom, uint wordoff, uint16 *buf, uint nwords, bool check_crc)
++{
++ int err = 0;
++ uint i;
++
++ /* read the sprom */
++ for (i = 0; i < nwords; i++)
++ buf[i] = R_REG(osh, &sprom[wordoff + i]);
++
++ if (check_crc) {
++ /* fixup the endianness so crc8 will pass */
++ htol16_buf(buf, nwords * 2);
++ if (hndcrc8((uint8*)buf, nwords * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE)
++ err = 1;
++ /* now correct the endianness of the byte array */
++ ltoh16_buf(buf, nwords * 2);
++ }
++
++ return err;
++}
++
++/*
++* Create variable table from memory.
++* Return 0 on success, nonzero on error.
++*/
++static int
++initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count)
++{
++ int c = (int)(end - start);
++
++ /* do it only when there is more than just the null string */
++ if (c > 1) {
++ char *vp = MALLOC(osh, c);
++ ASSERT(vp);
++ if (!vp)
++ return BCME_NOMEM;
++ bcopy(start, vp, c);
++ *vars = vp;
++ *count = c;
++ }
++ else {
++ *vars = NULL;
++ *count = 0;
++ }
++
++ return 0;
++}
++
++/*
++ * Find variables with <devpath> from flash. 'base' points to the beginning
++ * of the table upon enter and to the end of the table upon exit when success.
++ * Return 0 on success, nonzero on error.
++ */
++static int
++initvars_flash(osl_t *osh, char **base, uint len, char *devpath)
++{
++ char *vp = *base;
++ char *flash;
++ int err;
++ char *s;
++ uint l, dl, copy_len;
++
++ /* allocate memory and read in flash */
++ if (!(flash = MALLOC(osh, NVRAM_SPACE)))
++ return BCME_NOMEM;
++ if ((err = nvram_getall(flash, NVRAM_SPACE)))
++ goto exit;
++
++ /* grab vars with the <devpath> prefix in name */
++ dl = strlen(devpath);
++ for (s = flash; s && *s; s += l + 1) {
++ l = strlen(s);
++
++ /* skip non-matching variable */
++ if (strncmp(s, devpath, dl))
++ continue;
++
++ /* is there enough room to copy? */
++ copy_len = l - dl + 1;
++ if (len < copy_len) {
++ err = BCME_BUFTOOSHORT;
++ goto exit;
++ }
++
++ /* no prefix, just the name=value */
++ strcpy(vp, &s[dl]);
++ vp += copy_len;
++ len -= copy_len;
++ }
++
++ /* add null string as terminator */
++ if (len < 1) {
++ err = BCME_BUFTOOSHORT;
++ goto exit;
++ }
++ *vp++ = '\0';
++
++ *base = vp;
++
++exit: MFREE(osh, flash, NVRAM_SPACE);
++ return err;
++}
++
++/*
++ * Initialize nonvolatile variable table from flash.
++ * Return 0 on success, nonzero on error.
++ */
++static int
++initvars_flash_sb(void *sbh, char **vars, uint *count)
++{
++ osl_t *osh = sb_osh(sbh);
++ char devpath[SB_DEVPATH_BUFSZ];
++ char *vp, *base;
++ int err;
++
++ ASSERT(vars);
++ ASSERT(count);
++
++ if ((err = sb_devpath(sbh, devpath, sizeof(devpath))))
++ return err;
++
++ base = vp = MALLOC(osh, VARS_MAX);
++ ASSERT(vp);
++ if (!vp)
++ return BCME_NOMEM;
++
++ if ((err = initvars_flash(osh, &vp, VARS_MAX, devpath)))
++ goto err;
++
++ err = initvars_table(osh, base, vp, vars, count);
++
++err: MFREE(osh, base, VARS_MAX);
++ return err;
++}
++
++#ifdef WLTEST
++char mfgsromvars[256];
++char *defaultsromvars = "il0macaddr=00:11:22:33:44:51\0"
++ "et0macaddr=00:11:22:33:44:52\0"
++ "et1macaddr=00:11:22:33:44:53\0"
++ "boardtype=0xffff\0"
++ "boardrev=0x10\0"
++ "boardflags=8\0"
++ "sromrev=2\0"
++ "aa2g=3";
++#define MFGSROM_DEFVARSLEN 147 /* default srom len */
++#endif /* WL_TEST */
++
++/*
++ * Initialize nonvolatile variable table from sprom.
++ * Return 0 on success, nonzero on error.
++ */
++static int
++initvars_srom_pci(void *sbh, void *curmap, char **vars, uint *count)
++{
++ uint16 w, *b;
++ uint8 sromrev = 0;
++ struct ether_addr ea;
++ char eabuf[32];
++ uint32 w32;
++ int woff, i;
++ char *vp, *base;
++ osl_t *osh = sb_osh(sbh);
++ bool flash = FALSE;
++ char name[SB_DEVPATH_BUFSZ+16], *value;
++ char devpath[SB_DEVPATH_BUFSZ];
++ int err;
++
++ /*
++ * Apply CRC over SROM content regardless SROM is present or not,
++ * and use variable <devpath>sromrev's existance in flash to decide
++ * if we should return an error when CRC fails or read SROM variables
++ * from flash.
++ */
++ b = MALLOC(osh, SROM_MAX);
++ ASSERT(b);
++ if (!b)
++ return -2;
++
++ err = sprom_read_pci(osh, (void*)((int8*)curmap + PCI_BAR0_SPROM_OFFSET), 0, b,
++ 64, TRUE);
++ if (err == 0) {
++ /* srom is good and is rev < 4 */
++ /* top word of sprom contains version and crc8 */
++ sromrev = b[63] & 0xff;
++ /* bcm4401 sroms misprogrammed */
++ if (sromrev == 0x10)
++ sromrev = 1;
++ } else if (b[SROM4_SIGN] == SROM4_SIGNATURE) {
++ /* If sromrev >= 4, read more */
++ err = sprom_read_pci(osh, (void*)((int8*)curmap + PCI_BAR0_SPROM_OFFSET), 0, b,
++ SROM4_WORDS, TRUE);
++ sromrev = b[SROM4_WORDS - 1] & 0xff;
++ }
++
++ if (err) {
++#ifdef WLTEST
++ BS_ERROR(("SROM Crc Error, so see if we could use a default\n"));
++ w32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32));
++ if (w32 & SPROM_OTPIN_USE) {
++ BS_ERROR(("srom crc failed with OTP, use default vars....\n"));
++ vp = base = mfgsromvars;
++ if (sb_chip(sbh) == BCM4311_CHIP_ID) {
++ BS_ERROR(("setting the devid to be 4311\n"));
++ vp += sprintf(vp, "devid=0x4311");
++ vp++;
++ }
++ bcopy(defaultsromvars, vp, MFGSROM_DEFVARSLEN);
++ vp += MFGSROM_DEFVARSLEN;
++ goto varsdone;
++ } else {
++ BS_ERROR(("srom crc failed with SPROM....\n"));
++#endif /* WLTEST */
++ if ((err = sb_devpath(sbh, devpath, sizeof(devpath))))
++ return err;
++ sprintf(name, "%ssromrev", devpath);
++ if (!(value = getvar(NULL, name)))
++ return (-1);
++ sromrev = (uint8)bcm_strtoul(value, NULL, 0);
++ flash = TRUE;
++#ifdef WLTEST
++ }
++#endif /* WLTEST */
++ }
++
++ /* srom version check */
++ if (sromrev > 4)
++ return (-2);
++
++ ASSERT(vars);
++ ASSERT(count);
++
++ base = vp = MALLOC(osh, VARS_MAX);
++ ASSERT(vp);
++ if (!vp)
++ return -2;
++
++ /* read variables from flash */
++ if (flash) {
++ if ((err = initvars_flash(osh, &vp, VARS_MAX, devpath)))
++ goto err;
++ goto varsdone;
++ }
++
++ vp += sprintf(vp, "sromrev=%d", sromrev);
++ vp++;
++
++ if (sromrev >= 4) {
++ uint path, pathbase;
++ const uint pathbases[MAX_PATH] = {SROM4_PATH0, SROM4_PATH1,
++ SROM4_PATH2, SROM4_PATH3};
++
++ vp += sprintf(vp, "boardrev=%d", b[SROM4_BREV]);
++ vp++;
++
++ vp += sprintf(vp, "boardflags=%d", (b[SROM4_BFL1] << 16) | b[SROM4_BFL0]);
++ vp++;
++
++ vp += sprintf(vp, "boardflags2=%d", (b[SROM4_BFL3] << 16) | b[SROM4_BFL2]);
++ vp++;
++
++ /* The macaddr */
++ ea.octet[0] = (b[SROM4_MACHI] >> 8) & 0xff;
++ ea.octet[1] = b[SROM4_MACHI] & 0xff;
++ ea.octet[2] = (b[SROM4_MACMID] >> 8) & 0xff;
++ ea.octet[3] = b[SROM4_MACMID] & 0xff;
++ ea.octet[4] = (b[SROM4_MACLO] >> 8) & 0xff;
++ ea.octet[5] = b[SROM4_MACLO] & 0xff;
++ bcm_ether_ntoa(&ea, eabuf);
++ vp += sprintf(vp, "macaddr=%s", eabuf);
++ vp++;
++
++ w = b[SROM4_CCODE];
++ if (w == 0)
++ vp += sprintf(vp, "ccode=");
++ else
++ vp += sprintf(vp, "ccode=%c%c", (w >> 8), (w & 0xff));
++ vp++;
++ vp += sprintf(vp, "regrev=%d", b[SROM4_REGREV]);
++ vp++;
++
++ w = b[SROM4_LEDBH10];
++ if ((w != 0) && (w != 0xffff)) {
++ /* ledbh0 */
++ vp += sprintf(vp, "ledbh0=%d", (w & 0xff));
++ vp++;
++
++ /* ledbh1 */
++ vp += sprintf(vp, "ledbh1=%d", (w >> 8) & 0xff);
++ vp++;
++ }
++ w = b[SROM4_LEDBH32];
++ if ((w != 0) && (w != 0xffff)) {
++ /* ledbh2 */
++ vp += sprintf(vp, "ledbh2=%d", w & 0xff);
++ vp++;
++
++ /* ledbh3 */
++ vp += sprintf(vp, "ledbh3=%d", (w >> 8) & 0xff);
++ vp++;
++ }
++ /* LED Powersave duty cycle (oncount >> 24) (offcount >> 8) */
++ w = b[SROM4_LEDDC];
++ w32 = ((uint32)((unsigned char)(w >> 8) & 0xff) << 24) | /* oncount */
++ ((uint32)((unsigned char)(w & 0xff)) << 8); /* offcount */
++ vp += sprintf(vp, "leddc=%d", w32);
++ vp++;
++
++ w = b[SROM4_AA];
++ vp += sprintf(vp, "aa2g=%d", w & SROM4_AA2G_MASK);
++ vp++;
++ vp += sprintf(vp, "aa5g=%d", w >> SROM4_AA5G_SHIFT);
++ vp++;
++
++ w = b[SROM4_AG10];
++ vp += sprintf(vp, "ag0=%d", w & 0xff);
++ vp++;
++ vp += sprintf(vp, "ag1=%d", (w >> 8) & 0xff);
++ vp++;
++ w = b[SROM4_AG32];
++ vp += sprintf(vp, "ag2=%d", w & 0xff);
++ vp++;
++ vp += sprintf(vp, "ag3=%d", (w >> 8) & 0xff);
++ vp++;
++
++ /* Fixed power indices when power control is disabled */
++ for (i = 0; i < 2; i++) {
++ w = b[SROM4_TXPID2G + i];
++ vp += sprintf(vp, "txpid2ga%d=%d", 2 * i, w & 0xff);
++ vp++;
++ vp += sprintf(vp, "txpid2ga%d=%d", (2 * i) + 1, (w >> 8) & 0xff);
++ vp++;
++ w = b[SROM4_TXPID5G + i];
++ vp += sprintf(vp, "txpid5ga%d=%d", 2 * i, w & 0xff);
++ vp++;
++ vp += sprintf(vp, "txpid5ga%d=%d", (2 * i) + 1, (w >> 8) & 0xff);
++ vp++;
++ w = b[SROM4_TXPID5GL + i];
++ vp += sprintf(vp, "txpid5gla%d=%d", 2 * i, w & 0xff);
++ vp++;
++ vp += sprintf(vp, "txpid5gla%d=%d", (2 * i) + 1, (w >> 8) & 0xff);
++ vp++;
++ w = b[SROM4_TXPID5GH + i];
++ vp += sprintf(vp, "txpid5gha%d=%d", 2 * i, w & 0xff);
++ vp++;
++ vp += sprintf(vp, "txpid5gha%d=%d", (2 * i) + 1, (w >> 8) & 0xff);
++ vp++;
++ }
++
++ /* Per path variables */
++ for (path = 0; path < MAX_PATH; path++) {
++ pathbase = pathbases[path];
++ w = b[pathbase + SROM4_2G_ITT_MAXP];
++ vp += sprintf(vp, "itt2ga%d=%d", path, w >> B2G_ITT_SHIFT);
++ vp++;
++ vp += sprintf(vp, "maxp2ga%d=%d", path, w & B2G_MAXP_MASK);
++ vp++;
++
++ for (i = 0; i < 4; i++) {
++ vp += sprintf(vp, "pa2gw%da%d=%d", i, path,
++ b[pathbase + SROM4_2G_PA + i]);
++ vp++;
++ }
++
++ w = b[pathbase + SROM4_5G_ITT_MAXP];
++ vp += sprintf(vp, "itt5ga%d=%d", path, w >> B5G_ITT_SHIFT);
++ vp++;
++ vp += sprintf(vp, "maxp5ga%d=%d", path, w & B5G_MAXP_MASK);
++ vp++;
++
++ w = b[pathbase + SROM4_5GLH_MAXP];
++ vp += sprintf(vp, "maxp5lga%d=%d", path, w >> B5GL_MAXP_SHIFT);
++ vp++;
++ vp += sprintf(vp, "maxp5gha%d=%d", path, w & B5GH_MAXP_MASK);
++ vp++;
++
++ for (i = 0; i < 4; i++) {
++ vp += sprintf(vp, "pa5gw%da%d=%d", i, path,
++ b[pathbase + SROM4_5G_PA + i]);
++ vp++;
++ vp += sprintf(vp, "pa5glw%da%d=%d", i, path,
++ b[pathbase + SROM4_5GL_PA + i]);
++ vp++;
++ vp += sprintf(vp, "pa5hgw%da%d=%d", i, path,
++ b[pathbase + SROM4_5GH_PA + i]);
++ vp++;
++ }
++ }
++
++ vp += sprintf(vp, "cck2gpo=%d", b[SROM4_2G_CCKPO]);
++ vp++;
++
++ w32 = ((uint32)b[SROM4_2G_OFDMPO + 1] << 16) | b[SROM4_2G_OFDMPO];
++ vp += sprintf(vp, "ofdm2gpo=%d", w32);
++ vp++;
++
++ w32 = ((uint32)b[SROM4_5G_OFDMPO + 1] << 16) | b[SROM4_5G_OFDMPO];
++ vp += sprintf(vp, "ofdm5gpo=%d", w32);
++ vp++;
++
++ w32 = ((uint32)b[SROM4_5GL_OFDMPO + 1] << 16) | b[SROM4_5GL_OFDMPO];
++ vp += sprintf(vp, "ofdm5glpo=%d", w32);
++ vp++;
++
++ w32 = ((uint32)b[SROM4_5GH_OFDMPO + 1] << 16) | b[SROM4_5GH_OFDMPO];
++ vp += sprintf(vp, "ofdm5ghpo=%d", w32);
++ vp++;
++
++ for (i = 0; i < 8; i++) {
++ vp += sprintf(vp, "mcs2gpo%d=%d", i, b[SROM4_2G_MCSPO]);
++ vp++;
++ vp += sprintf(vp, "mcs5gpo%d=%d", i, b[SROM4_5G_MCSPO]);
++ vp++;
++ vp += sprintf(vp, "mcs5glpo%d=%d", i, b[SROM4_5GL_MCSPO]);
++ vp++;
++ vp += sprintf(vp, "mcs5ghpo%d=%d", i, b[SROM4_5GH_MCSPO]);
++ vp++;
++ }
++
++ vp += sprintf(vp, "ccdpo%d=%d", i, b[SROM4_CCDPO]);
++ vp++;
++ vp += sprintf(vp, "stbcpo%d=%d", i, b[SROM4_STBCPO]);
++ vp++;
++ vp += sprintf(vp, "bw40po%d=%d", i, b[SROM4_BW40PO]);
++ vp++;
++ vp += sprintf(vp, "bwduppo%d=%d", i, b[SROM4_BWDUPPO]);
++ vp++;
++
++ goto done;
++ }
++ if (sromrev >= 3) {
++ /* New section takes over the 3th hardware function space */
++
++ /* Words 22+23 are 11a (mid) ofdm power offsets */
++ w32 = ((uint32)b[23] << 16) | b[22];
++ vp += sprintf(vp, "ofdmapo=%d", w32);
++ vp++;
++
++ /* Words 24+25 are 11a (low) ofdm power offsets */
++ w32 = ((uint32)b[25] << 16) | b[24];
++ vp += sprintf(vp, "ofdmalpo=%d", w32);
++ vp++;
++
++ /* Words 26+27 are 11a (high) ofdm power offsets */
++ w32 = ((uint32)b[27] << 16) | b[26];
++ vp += sprintf(vp, "ofdmahpo=%d", w32);
++ vp++;
++
++ /* LED Powersave duty cycle (oncount >> 24) (offcount >> 8) */
++ w32 = ((uint32)((unsigned char)(b[21] >> 8) & 0xff) << 24) | /* oncount */
++ ((uint32)((unsigned char)(b[21] & 0xff)) << 8); /* offcount */
++ vp += sprintf(vp, "leddc=%d", w32);
++
++ vp++;
++ }
++
++ if (sromrev >= 2) {
++ /* New section takes over the 4th hardware function space */
++
++ /* Word 29 is max power 11a high/low */
++ w = b[29];
++ vp += sprintf(vp, "pa1himaxpwr=%d", w & 0xff);
++ vp++;
++ vp += sprintf(vp, "pa1lomaxpwr=%d", (w >> 8) & 0xff);
++ vp++;
++
++ /* Words 30-32 set the 11alow pa settings,
++ * 33-35 are the 11ahigh ones.
++ */
++ for (i = 0; i < 3; i++) {
++ vp += sprintf(vp, "pa1lob%d=%d", i, b[30 + i]);
++ vp++;
++ vp += sprintf(vp, "pa1hib%d=%d", i, b[33 + i]);
++ vp++;
++ }
++ w = b[59];
++ if (w == 0)
++ vp += sprintf(vp, "ccode=");
++ else
++ vp += sprintf(vp, "ccode=%c%c", (w >> 8), (w & 0xff));
++ vp++;
++
++ }
++
++ /* parameter section of sprom starts at byte offset 72 */
++ woff = 72/2;
++
++ /* first 6 bytes are il0macaddr */
++ ea.octet[0] = (b[woff] >> 8) & 0xff;
++ ea.octet[1] = b[woff] & 0xff;
++ ea.octet[2] = (b[woff+1] >> 8) & 0xff;
++ ea.octet[3] = b[woff+1] & 0xff;
++ ea.octet[4] = (b[woff+2] >> 8) & 0xff;
++ ea.octet[5] = b[woff+2] & 0xff;
++ woff += 3;
++ bcm_ether_ntoa(&ea, eabuf);
++ vp += sprintf(vp, "il0macaddr=%s", eabuf);
++ vp++;
++
++ /* next 6 bytes are et0macaddr */
++ ea.octet[0] = (b[woff] >> 8) & 0xff;
++ ea.octet[1] = b[woff] & 0xff;
++ ea.octet[2] = (b[woff+1] >> 8) & 0xff;
++ ea.octet[3] = b[woff+1] & 0xff;
++ ea.octet[4] = (b[woff+2] >> 8) & 0xff;
++ ea.octet[5] = b[woff+2] & 0xff;
++ woff += 3;
++ bcm_ether_ntoa(&ea, eabuf);
++ vp += sprintf(vp, "et0macaddr=%s", eabuf);
++ vp++;
++
++ /* next 6 bytes are et1macaddr */
++ ea.octet[0] = (b[woff] >> 8) & 0xff;
++ ea.octet[1] = b[woff] & 0xff;
++ ea.octet[2] = (b[woff+1] >> 8) & 0xff;
++ ea.octet[3] = b[woff+1] & 0xff;
++ ea.octet[4] = (b[woff+2] >> 8) & 0xff;
++ ea.octet[5] = b[woff+2] & 0xff;
++ woff += 3;
++ bcm_ether_ntoa(&ea, eabuf);
++ vp += sprintf(vp, "et1macaddr=%s", eabuf);
++ vp++;
++
++ /*
++ * Enet phy settings one or two singles or a dual
++ * Bits 4-0 : MII address for enet0 (0x1f for not there)
++ * Bits 9-5 : MII address for enet1 (0x1f for not there)
++ * Bit 14 : Mdio for enet0
++ * Bit 15 : Mdio for enet1
++ */
++ w = b[woff];
++ vp += sprintf(vp, "et0phyaddr=%d", (w & 0x1f));
++ vp++;
++ vp += sprintf(vp, "et1phyaddr=%d", ((w >> 5) & 0x1f));
++ vp++;
++ vp += sprintf(vp, "et0mdcport=%d", ((w >> 14) & 0x1));
++ vp++;
++ vp += sprintf(vp, "et1mdcport=%d", ((w >> 15) & 0x1));
++ vp++;
++
++ /* Word 46 has board rev, antennas 0/1 & Country code/control */
++ w = b[46];
++ vp += sprintf(vp, "boardrev=%d", w & 0xff);
++ vp++;
++
++ if (sromrev > 1)
++ vp += sprintf(vp, "cctl=%d", (w >> 8) & 0xf);
++ else
++ vp += sprintf(vp, "cc=%d", (w >> 8) & 0xf);
++ vp++;
++
++ vp += sprintf(vp, "aa2g=%d", (w >> 12) & 0x3);
++ vp++;
++
++ vp += sprintf(vp, "aa5g=%d", (w >> 14) & 0x3);
++ vp++;
++
++ /* Words 47-49 set the (wl) pa settings */
++ woff = 47;
++
++ for (i = 0; i < 3; i++) {
++ vp += sprintf(vp, "pa0b%d=%d", i, b[woff+i]);
++ vp++;
++ vp += sprintf(vp, "pa1b%d=%d", i, b[woff+i+6]);
++ vp++;
++ }
++
++ /*
++ * Words 50-51 set the customer-configured wl led behavior.
++ * 8 bits/gpio pin. High bit: activehi=0, activelo=1;
++ * LED behavior values defined in wlioctl.h .
++ */
++ w = b[50];
++ if ((w != 0) && (w != 0xffff)) {
++ /* ledbh0 */
++ vp += sprintf(vp, "ledbh0=%d", (w & 0xff));
++ vp++;
++
++ /* ledbh1 */
++ vp += sprintf(vp, "ledbh1=%d", (w >> 8) & 0xff);
++ vp++;
++ }
++ w = b[51];
++ if ((w != 0) && (w != 0xffff)) {
++ /* ledbh2 */
++ vp += sprintf(vp, "ledbh2=%d", w & 0xff);
++ vp++;
++
++ /* ledbh */
++ vp += sprintf(vp, "ledbh3=%d", (w >> 8) & 0xff);
++ vp++;
++ }
++
++ /* Word 52 is max power 0/1 */
++ w = b[52];
++ vp += sprintf(vp, "pa0maxpwr=%d", w & 0xff);
++ vp++;
++ vp += sprintf(vp, "pa1maxpwr=%d", (w >> 8) & 0xff);
++ vp++;
++
++ /* Word 56 is idle tssi target 0/1 */
++ w = b[56];
++ vp += sprintf(vp, "pa0itssit=%d", w & 0xff);
++ vp++;
++ vp += sprintf(vp, "pa1itssit=%d", (w >> 8) & 0xff);
++ vp++;
++
++ /* Word 57 is boardflags, if not programmed make it zero */
++ w32 = (uint32)b[57];
++ if (w32 == 0xffff) w32 = 0;
++ if (sromrev > 1) {
++ /* Word 28 is the high bits of boardflags */
++ w32 |= (uint32)b[28] << 16;
++ }
++ vp += sprintf(vp, "boardflags=%d", w32);
++ vp++;
++
++ /* Word 58 is antenna gain 0/1 */
++ w = b[58];
++ vp += sprintf(vp, "ag0=%d", w & 0xff);
++ vp++;
++
++ vp += sprintf(vp, "ag1=%d", (w >> 8) & 0xff);
++ vp++;
++
++ if (sromrev == 1) {
++ /* set the oem string */
++ vp += sprintf(vp, "oem=%02x%02x%02x%02x%02x%02x%02x%02x",
++ ((b[59] >> 8) & 0xff), (b[59] & 0xff),
++ ((b[60] >> 8) & 0xff), (b[60] & 0xff),
++ ((b[61] >> 8) & 0xff), (b[61] & 0xff),
++ ((b[62] >> 8) & 0xff), (b[62] & 0xff));
++ vp++;
++ } else if (sromrev == 2) {
++ /* Word 60 OFDM tx power offset from CCK level */
++ /* OFDM Power Offset - opo */
++ vp += sprintf(vp, "opo=%d", b[60] & 0xff);
++ vp++;
++ } else {
++ /* Word 60: cck power offsets */
++ vp += sprintf(vp, "cckpo=%d", b[60]);
++ vp++;
++
++ /* Words 61+62: 11g ofdm power offsets */
++ w32 = ((uint32)b[62] << 16) | b[61];
++ vp += sprintf(vp, "ofdmgpo=%d", w32);
++ vp++;
++ }
++
++ /* final nullbyte terminator */
++done: *vp++ = '\0';
++
++ ASSERT((vp - base) <= VARS_MAX);
++
++varsdone:
++ err = initvars_table(osh, base, vp, vars, count);
++
++err:
++#ifdef WLTEST
++ if (base != mfgsromvars)
++#endif
++ MFREE(osh, base, VARS_MAX);
++ MFREE(osh, b, SROM_MAX);
++ return err;
++}
++
++/*
++ * Read the cis and call parsecis to initialize the vars.
++ * Return 0 on success, nonzero on error.
++ */
++static int
++initvars_cis_pcmcia(void *sbh, osl_t *osh, char **vars, uint *count)
++{
++ uint8 *cis = NULL;
++ int rc;
++ uint data_sz;
++
++ data_sz = (sb_pcmciarev(sbh) == 1) ? (SPROM_SIZE * 2) : CIS_SIZE;
++
++ if ((cis = MALLOC(osh, data_sz)) == NULL)
++ return (-2);
++
++ if (sb_pcmciarev(sbh) == 1) {
++ if (srom_read(PCMCIA_BUS, (void *)NULL, osh, 0, data_sz, (uint16 *)cis)) {
++ MFREE(osh, cis, data_sz);
++ return (-1);
++ }
++ /* fix up endianess for 16-bit data vs 8-bit parsing */
++ ltoh16_buf((uint16 *)cis, data_sz);
++ } else
++ OSL_PCMCIA_READ_ATTR(osh, 0, cis, data_sz);
++
++ rc = srom_parsecis(osh, &cis, 1, vars, count);
++
++ MFREE(osh, cis, data_sz);
++
++ return (rc);
++}
++
+diff -urN linux.old/arch/mips/bcm947xx/bcmutils.c linux.dev/arch/mips/bcm947xx/bcmutils.c
+--- linux.old/arch/mips/bcm947xx/bcmutils.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/bcmutils.c 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,247 @@
++/*
++ * Misc useful OS-independent routines.
++ *
++ * 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.
++ * $Id: bcmutils.c,v 1.1.1.12 2006/02/27 03:43:16 honor Exp $
++ */
++
++#include <typedefs.h>
++#include <bcmdefs.h>
++#include <stdarg.h>
++#include <bcmutils.h>
++#include <osl.h>
++#include <sbutils.h>
++#include <bcmnvram.h>
++#include <bcmendian.h>
++#include <bcmdevs.h>
++
++unsigned char bcm_ctype[] = {
++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */
++ _BCM_C, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C,
++ _BCM_C, /* 8-15 */
++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */
++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */
++ _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */
++ _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */
++ _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */
++ _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */
++ _BCM_P, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X,
++ _BCM_U|_BCM_X, _BCM_U, /* 64-71 */
++ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */
++ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */
++ _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */
++ _BCM_P, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X,
++ _BCM_L|_BCM_X, _BCM_L, /* 96-103 */
++ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */
++ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */
++ _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-143 */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144-159 */
++ _BCM_S|_BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 160-175 */
++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 176-191 */
++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U,
++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 192-207 */
++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, _BCM_U, _BCM_U,
++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L, /* 208-223 */
++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L,
++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 224-239 */
++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, _BCM_L, _BCM_L,
++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */
++};
++
++
++ulong
++bcm_strtoul(char *cp, char **endp, uint base)
++{
++ ulong result, value;
++ bool minus;
++
++ minus = FALSE;
++
++ while (bcm_isspace(*cp))
++ cp++;
++
++ if (cp[0] == '+')
++ cp++;
++ else if (cp[0] == '-') {
++ minus = TRUE;
++ cp++;
++ }
++
++ if (base == 0) {
++ if (cp[0] == '0') {
++ if ((cp[1] == 'x') || (cp[1] == 'X')) {
++ base = 16;
++ cp = &cp[2];
++ } else {
++ base = 8;
++ cp = &cp[1];
++ }
++ } else
++ base = 10;
++ } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) {
++ cp = &cp[2];
++ }
++
++ result = 0;
++
++ while (bcm_isxdigit(*cp) &&
++ (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) {
++ result = result*base + value;
++ cp++;
++ }
++
++ if (minus)
++ result = (ulong)(result * -1);
++
++ if (endp)
++ *endp = (char *)cp;
++
++ return (result);
++}
++
++uchar
++bcm_toupper(uchar c)
++{
++ if (bcm_islower(c))
++ c -= 'a'-'A';
++ return (c);
++}
++
++char*
++bcm_ether_ntoa(struct ether_addr *ea, char *buf)
++{
++ sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
++ ea->octet[0]&0xff, ea->octet[1]&0xff, ea->octet[2]&0xff,
++ ea->octet[3]&0xff, ea->octet[4]&0xff, ea->octet[5]&0xff);
++ return (buf);
++}
++
++
++/*
++ * Search the name=value vars for a specific one and return its value.
++ * Returns NULL if not found.
++ */
++char*
++getvar(char *vars, char *name)
++{
++ char *s;
++ int len;
++
++ len = strlen(name);
++
++ /* first look in vars[] */
++ for (s = vars; s && *s;) {
++ /* CSTYLED */
++ if ((memcmp(s, name, len) == 0) && (s[len] == '='))
++ return (&s[len+1]);
++
++ while (*s++)
++ ;
++ }
++
++ /* then query nvram */
++ return (nvram_get(name));
++}
++
++/*
++ * Search the vars for a specific one and return its value as
++ * an integer. Returns 0 if not found.
++ */
++int
++getintvar(char *vars, char *name)
++{
++ char *val;
++
++ if ((val = getvar(vars, name)) == NULL)
++ return (0);
++
++ return (bcm_strtoul(val, NULL, 0));
++}
++
++
++/*******************************************************************************
++ * 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 uint8 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
++};
++
++#define CRC_INNER_LOOP(n, c, x) \
++ (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff]
++
++uint8
++hndcrc8(
++ uint8 *pdata, /* pointer to array of data to process */
++ uint nbytes, /* number of input data bytes to process */
++ uint8 crc /* either CRC8_INIT_VALUE or previous return value */
++)
++{
++ /* hard code the crc loop instead of using CRC_INNER_LOOP macro
++ * to avoid the undefined and unnecessary (uint8 >> 8) operation.
++ */
++ while (nbytes-- > 0)
++ crc = crc8_table[(crc ^ *pdata++) & 0xff];
++
++ return crc;
++}
++
++
+diff -urN linux.old/arch/mips/bcm947xx/cfe_env.c linux.dev/arch/mips/bcm947xx/cfe_env.c
+--- linux.old/arch/mips/bcm947xx/cfe_env.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/cfe_env.c 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,234 @@
++/*
++ * NVRAM variable manipulation (Linux kernel half)
++ *
++ * Copyright 2001-2003, 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.
++ *
++ * $Id$
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++
++#include <typedefs.h>
++#include <osl.h>
++#include <bcmendian.h>
++#include <bcmutils.h>
++
++#define NVRAM_SIZE (0x1ff0)
++static char _nvdata[NVRAM_SIZE] __initdata;
++static char _valuestr[256] __initdata;
++
++/*
++ * TLV types. These codes are used in the "type-length-value"
++ * encoding of the items stored in the NVRAM device (flash or EEPROM)
++ *
++ * The layout of the flash/nvram is as follows:
++ *
++ * <type> <length> <data ...> <type> <length> <data ...> <type_end>
++ *
++ * The type code of "ENV_TLV_TYPE_END" marks the end of the list.
++ * The "length" field marks the length of the data section, not
++ * including the type and length fields.
++ *
++ * Environment variables are stored as follows:
++ *
++ * <type_env> <length> <flags> <name> = <value>
++ *
++ * If bit 0 (low bit) is set, the length is an 8-bit value.
++ * If bit 0 (low bit) is clear, the length is a 16-bit value
++ *
++ * Bit 7 set indicates "user" TLVs. In this case, bit 0 still
++ * indicates the size of the length field.
++ *
++ * Flags are from the constants below:
++ *
++ */
++#define ENV_LENGTH_16BITS 0x00 /* for low bit */
++#define ENV_LENGTH_8BITS 0x01
++
++#define ENV_TYPE_USER 0x80
++
++#define ENV_CODE_SYS(n,l) (((n)<<1)|(l))
++#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER)
++
++/*
++ * The actual TLV types we support
++ */
++
++#define ENV_TLV_TYPE_END 0x00
++#define ENV_TLV_TYPE_ENV ENV_CODE_SYS(0,ENV_LENGTH_8BITS)
++
++/*
++ * Environment variable flags
++ */
++
++#define ENV_FLG_NORMAL 0x00 /* normal read/write */
++#define ENV_FLG_BUILTIN 0x01 /* builtin - not stored in flash */
++#define ENV_FLG_READONLY 0x02 /* read-only - cannot be changed */
++
++#define ENV_FLG_MASK 0xFF /* mask of attributes we keep */
++#define ENV_FLG_ADMIN 0x100 /* lets us internally override permissions */
++
++
++/* *********************************************************************
++ * _nvram_read(buffer,offset,length)
++ *
++ * Read data from the NVRAM device
++ *
++ * Input parameters:
++ * buffer - destination buffer
++ * offset - offset of data to read
++ * length - number of bytes to read
++ *
++ * Return value:
++ * number of bytes read, or <0 if error occured
++ ********************************************************************* */
++static int
++_nvram_read(unsigned char *nv_buf, unsigned char *buffer, int offset, int length)
++{
++ int i;
++ if (offset > NVRAM_SIZE)
++ return -1;
++
++ for ( i = 0; i < length; i++) {
++ buffer[i] = ((volatile unsigned char*)nv_buf)[offset + i];
++ }
++ return length;
++}
++
++
++static char*
++_strnchr(const char *dest,int c,size_t cnt)
++{
++ while (*dest && (cnt > 0)) {
++ if (*dest == c) return (char *) dest;
++ dest++;
++ cnt--;
++ }
++ return NULL;
++}
++
++
++
++/*
++ * Core support API: Externally visible.
++ */
++
++/*
++ * Get the value of an NVRAM variable
++ * @param name name of variable to get
++ * @return value of variable or NULL if undefined
++ */
++
++char*
++cfe_env_get(unsigned char *nv_buf, char* name)
++{
++ int size;
++ unsigned char *buffer;
++ unsigned char *ptr;
++ unsigned char *envval;
++ unsigned int reclen;
++ unsigned int rectype;
++ int offset;
++ int flg;
++
++ size = NVRAM_SIZE;
++ buffer = &_nvdata[0];
++
++ ptr = buffer;
++ offset = 0;
++
++ /* Read the record type and length */
++ if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
++ goto error;
++ }
++
++ while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) {
++
++ /* Adjust pointer for TLV type */
++ rectype = *(ptr);
++ offset++;
++ size--;
++
++ /*
++ * Read the length. It can be either 1 or 2 bytes
++ * depending on the code
++ */
++ if (rectype & ENV_LENGTH_8BITS) {
++ /* Read the record type and length - 8 bits */
++ if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
++ goto error;
++ }
++ reclen = *(ptr);
++ size--;
++ offset++;
++ }
++ else {
++ /* Read the record type and length - 16 bits, MSB first */
++ if (_nvram_read(nv_buf, ptr,offset,2) != 2) {
++ goto error;
++ }
++ reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1);
++ size -= 2;
++ offset += 2;
++ }
++
++ if (reclen > size)
++ break; /* should not happen, bad NVRAM */
++
++ switch (rectype) {
++ case ENV_TLV_TYPE_ENV:
++ /* Read the TLV data */
++ if (_nvram_read(nv_buf, ptr,offset,reclen) != reclen)
++ goto error;
++ flg = *ptr++;
++ envval = (unsigned char *) _strnchr(ptr,'=',(reclen-1));
++ if (envval) {
++ *envval++ = '\0';
++ memcpy(_valuestr,envval,(reclen-1)-(envval-ptr));
++ _valuestr[(reclen-1)-(envval-ptr)] = '\0';
++#if 0
++ printk(KERN_INFO "NVRAM:%s=%s\n", ptr, _valuestr);
++#endif
++ if(!strcmp(ptr, name)){
++ return _valuestr;
++ }
++ if((strlen(ptr) > 1) && !strcmp(&ptr[1], name))
++ return _valuestr;
++ }
++ break;
++
++ default:
++ /* Unknown TLV type, skip it. */
++ break;
++ }
++
++ /*
++ * Advance to next TLV
++ */
++
++ size -= (int)reclen;
++ offset += reclen;
++
++ /* Read the next record type */
++ ptr = buffer;
++ if (_nvram_read(nv_buf, ptr,offset,1) != 1)
++ goto error;
++ }
++
++error:
++ return NULL;
++
++}
++
+diff -urN linux.old/arch/mips/bcm947xx/compressed/Makefile linux.dev/arch/mips/bcm947xx/compressed/Makefile
+--- linux.old/arch/mips/bcm947xx/compressed/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/compressed/Makefile 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,33 @@
++#
++# Makefile for Broadcom BCM947XX boards
++#
++# Copyright 2001-2003, 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.
++#
++# $Id: Makefile,v 1.2 2005/04/02 12:12:57 wbx Exp $
++#
++
++OBJCOPY_ARGS = -O binary -R .reginfo -R .note -R .comment -R .mdebug -S
++SYSTEM ?= $(TOPDIR)/vmlinux
++
++all: vmlinuz
++
++# Don't build dependencies, this may die if $(CC) isn't gcc
++dep:
++
++# Create a gzipped version named vmlinuz for compatibility
++vmlinuz: piggy
++ gzip -c9 $< > $@
++
++piggy: $(SYSTEM)
++ $(OBJCOPY) $(OBJCOPY_ARGS) $< $@
++
++mrproper: clean
++
++clean:
++ rm -f vmlinuz piggy
+diff -urN linux.old/arch/mips/bcm947xx/export.c linux.dev/arch/mips/bcm947xx/export.c
+--- linux.old/arch/mips/bcm947xx/export.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/export.c 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,65 @@
++#include <linux/module.h>
++
++#define _export(n) \
++ void n(void); \
++ EXPORT_SYMBOL(n);
++
++_export(bcm947xx_sbh)
++
++_export(sb_attach)
++_export(sb_kattach)
++_export(sb_boardtype)
++_export(sb_boardvendor)
++_export(sb_btcgpiowar)
++_export(sb_bus)
++_export(sb_chip)
++_export(sb_chiprev)
++_export(sb_chipcrev)
++_export(sb_chippkg)
++_export(sb_clkctl_clk)
++_export(sb_clkctl_fast_pwrup_delay)
++_export(sb_clkctl_init)
++_export(sb_clkctl_xtal)
++_export(sb_core_disable)
++_export(sb_core_reset)
++_export(sb_core_tofixup)
++_export(sb_coreflags)
++_export(sb_coreflagshi)
++_export(sb_coreidx)
++_export(sb_corerev)
++_export(sb_coreunit)
++_export(sb_detach)
++_export(sb_deviceremoved)
++_export(sb_gpiosetcore)
++_export(sb_gpiocontrol)
++_export(sb_gpioled)
++_export(sb_gpioin)
++_export(sb_gpioout)
++_export(sb_gpioouten)
++_export(sb_gpiotimerval)
++_export(sb_iscoreup)
++_export(sb_pci_setup)
++_export(sb_pcirev)
++_export(sb_pcmcia_init)
++_export(sb_pcmciarev)
++_export(sb_register_intr_callback)
++_export(sb_setcore)
++_export(sb_war16165)
++_export(sb_osh)
++
++_export(getvar)
++_export(getintvar)
++_export(bcm_strtoul)
++_export(bcm_ctype)
++_export(bcm_toupper)
++_export(bcm_ether_ntoa)
++
++_export(nvram_get)
++_export(nvram_getall)
++_export(nvram_set)
++_export(nvram_unset)
++_export(nvram_commit)
++
++_export(srom_read)
++_export(srom_write)
++
+diff -urN linux.old/arch/mips/bcm947xx/generic/int-handler.S linux.dev/arch/mips/bcm947xx/generic/int-handler.S
+--- linux.old/arch/mips/bcm947xx/generic/int-handler.S 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/generic/int-handler.S 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,51 @@
++/*
++ * Generic interrupt handler for Broadcom MIPS boards
++ *
++ * 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.
++ *
++ * $Id: int-handler.S,v 1.1 2005/03/16 13:50:00 wbx Exp $
++ */
++
++#include <linux/config.h>
++
++#include <asm/asm.h>
++#include <asm/mipsregs.h>
++#include <asm/regdef.h>
++#include <asm/stackframe.h>
++
++/*
++ * MIPS IRQ Source
++ * -------- ------
++ * 0 Software (ignored)
++ * 1 Software (ignored)
++ * 2 Combined hardware interrupt (hw0)
++ * 3 Hardware
++ * 4 Hardware
++ * 5 Hardware
++ * 6 Hardware
++ * 7 R4k timer
++ */
++
++ .text
++ .set noreorder
++ .set noat
++ .align 5
++ NESTED(brcmIRQ, PT_SIZE, sp)
++ SAVE_ALL
++ CLI
++ .set at
++ .set noreorder
++
++ jal brcm_irq_dispatch
++ move a0, sp
++
++ j ret_from_irq
++ nop
++
++ END(brcmIRQ)
+diff -urN linux.old/arch/mips/bcm947xx/generic/irq.c linux.dev/arch/mips/bcm947xx/generic/irq.c
+--- linux.old/arch/mips/bcm947xx/generic/irq.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/generic/irq.c 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,130 @@
++/*
++ * Generic interrupt control functions for Broadcom MIPS boards
++ *
++ * 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.
++ *
++ * $Id: irq.c,v 1.1 2005/03/16 13:50:00 wbx Exp $
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++
++#include <asm/irq.h>
++#include <asm/mipsregs.h>
++#include <asm/gdb-stub.h>
++
++#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
++
++extern asmlinkage void brcmIRQ(void);
++extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs);
++
++void
++brcm_irq_dispatch(struct pt_regs *regs)
++{
++ u32 cause;
++
++ cause = read_c0_cause() &
++ read_c0_status() &
++ CAUSEF_IP;
++
++#ifdef CONFIG_KERNPROF
++ change_c0_status(cause | 1, 1);
++#else
++ clear_c0_status(cause);
++#endif
++
++ if (cause & CAUSEF_IP7)
++ do_IRQ(7, regs);
++ if (cause & CAUSEF_IP2)
++ do_IRQ(2, regs);
++ if (cause & CAUSEF_IP3)
++ do_IRQ(3, regs);
++ if (cause & CAUSEF_IP4)
++ do_IRQ(4, regs);
++ if (cause & CAUSEF_IP5)
++ do_IRQ(5, regs);
++ if (cause & CAUSEF_IP6)
++ do_IRQ(6, regs);
++}
++
++static void
++enable_brcm_irq(unsigned int irq)
++{
++ if (irq < 8)
++ set_c0_status(1 << (irq + 8));
++ else
++ set_c0_status(IE_IRQ0);
++}
++
++static void
++disable_brcm_irq(unsigned int irq)
++{
++ if (irq < 8)
++ clear_c0_status(1 << (irq + 8));
++ else
++ clear_c0_status(IE_IRQ0);
++}
++
++static void
++ack_brcm_irq(unsigned int irq)
++{
++ /* Already done in brcm_irq_dispatch */
++}
++
++static unsigned int
++startup_brcm_irq(unsigned int irq)
++{
++ enable_brcm_irq(irq);
++
++ return 0; /* never anything pending */
++}
++
++static void
++end_brcm_irq(unsigned int irq)
++{
++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
++ enable_brcm_irq(irq);
++}
++
++static struct hw_interrupt_type brcm_irq_type = {
++ typename: "MIPS",
++ startup: startup_brcm_irq,
++ shutdown: disable_brcm_irq,
++ enable: enable_brcm_irq,
++ disable: disable_brcm_irq,
++ ack: ack_brcm_irq,
++ end: end_brcm_irq,
++ NULL
++};
++
++void __init
++init_IRQ(void)
++{
++ int i;
++
++ for (i = 0; i < NR_IRQS; i++) {
++ irq_desc[i].status = IRQ_DISABLED;
++ irq_desc[i].action = 0;
++ irq_desc[i].depth = 1;
++ irq_desc[i].handler = &brcm_irq_type;
++ }
++
++ set_except_vector(0, brcmIRQ);
++ change_c0_status(ST0_IM, ALLINTS);
++
++#ifdef CONFIG_REMOTE_DEBUG
++ printk("Breaking into debugger...\n");
++ set_debug_traps();
++ breakpoint();
++#endif
++}
+diff -urN linux.old/arch/mips/bcm947xx/generic/Makefile linux.dev/arch/mips/bcm947xx/generic/Makefile
+--- linux.old/arch/mips/bcm947xx/generic/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/generic/Makefile 2006-10-02 21:26:29.000000000 +0200
+@@ -0,0 +1,16 @@
++#
++# Makefile for the BCM947xx specific kernel interface routines
++# under Linux.
++#
++EXTRA_CFLAGS += -fno-delayed-branch
++
++.S.s:
++ $(CPP) $(AFLAGS) $< -o $*.s
++.S.o:
++ $(CC) $(AFLAGS) -c $< -o $*.o
++
++O_TARGET := brcm.o
++
++obj-y := int-handler.o irq.o
++
++include $(TOPDIR)/Rules.make
+diff -urN linux.old/arch/mips/bcm947xx/gpio.c linux.dev/arch/mips/bcm947xx/gpio.c
+--- linux.old/arch/mips/bcm947xx/gpio.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/gpio.c 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,159 @@
++/*
++ * GPIO char driver
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/miscdevice.h>
++#include <asm/uaccess.h>
++
++#include <typedefs.h>
++#include <osl.h>
++#include <bcmutils.h>
++#include <sbutils.h>
++#include <bcmdevs.h>
++
++static sb_t *gpio_sbh;
++static int gpio_major;
++static devfs_handle_t gpio_dir;
++static struct {
++ char *name;
++ devfs_handle_t handle;
++} gpio_file[] = {
++ { "in", NULL },
++ { "out", NULL },
++ { "outen", NULL },
++ { "control", NULL }
++};
++
++static int
++gpio_open(struct inode *inode, struct file * file)
++{
++ if (MINOR(inode->i_rdev) > ARRAYSIZE(gpio_file))
++ return -ENODEV;
++
++ MOD_INC_USE_COUNT;
++ return 0;
++}
++
++static int
++gpio_release(struct inode *inode, struct file * file)
++{
++ MOD_DEC_USE_COUNT;
++ return 0;
++}
++
++static ssize_t
++gpio_read(struct file *file, char *buf, size_t count, loff_t *ppos)
++{
++ u32 val;
++
++ switch (MINOR(file->f_dentry->d_inode->i_rdev)) {
++ case 0:
++ val = sb_gpioin(gpio_sbh);
++ break;
++ case 1:
++ val = sb_gpioout(gpio_sbh, 0, 0, GPIO_DRV_PRIORITY);
++ break;
++ case 2:
++ val = sb_gpioouten(gpio_sbh, 0, 0, GPIO_DRV_PRIORITY);
++ break;
++ case 3:
++ val = sb_gpiocontrol(gpio_sbh, 0, 0, GPIO_DRV_PRIORITY);
++ break;
++ default:
++ return -ENODEV;
++ }
++
++ if (put_user(val, (u32 *) buf))
++ return -EFAULT;
++
++ return sizeof(val);
++}
++
++static ssize_t
++gpio_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
++{
++ u32 val;
++
++ if (get_user(val, (u32 *) buf))
++ return -EFAULT;
++
++ switch (MINOR(file->f_dentry->d_inode->i_rdev)) {
++ case 0:
++ return -EACCES;
++ case 1:
++ sb_gpioout(gpio_sbh, ~0, val, GPIO_DRV_PRIORITY);
++ break;
++ case 2:
++ sb_gpioouten(gpio_sbh, ~0, val, GPIO_DRV_PRIORITY);
++ break;
++ case 3:
++ sb_gpiocontrol(gpio_sbh, ~0, val, GPIO_DRV_PRIORITY);
++ break;
++ default:
++ return -ENODEV;
++ }
++
++ return sizeof(val);
++}
++
++static struct file_operations gpio_fops = {
++ owner: THIS_MODULE,
++ open: gpio_open,
++ release: gpio_release,
++ read: gpio_read,
++ write: gpio_write,
++};
++
++static int __init
++gpio_init(void)
++{
++ int i;
++
++ if (!(gpio_sbh = sb_kattach()))
++ return -ENODEV;
++
++ sb_gpiosetcore(gpio_sbh);
++
++ if ((gpio_major = devfs_register_chrdev(0, "gpio", &gpio_fops)) < 0)
++ return gpio_major;
++
++ gpio_dir = devfs_mk_dir(NULL, "gpio", NULL);
++
++ for (i = 0; i < ARRAYSIZE(gpio_file); i++) {
++ gpio_file[i].handle = devfs_register(gpio_dir,
++ gpio_file[i].name,
++ DEVFS_FL_DEFAULT, gpio_major, i,
++ S_IFCHR | S_IRUGO | S_IWUGO,
++ &gpio_fops, NULL);
++ }
++
++ return 0;
++}
++
++static void __exit
++gpio_exit(void)
++{
++ int i;
++
++ for (i = 0; i < ARRAYSIZE(gpio_file); i++)
++ devfs_unregister(gpio_file[i].handle);
++ devfs_unregister(gpio_dir);
++ devfs_unregister_chrdev(gpio_major, "gpio");
++ sb_detach(gpio_sbh);
++}
++
++module_init(gpio_init);
++module_exit(gpio_exit);
+diff -urN linux.old/arch/mips/bcm947xx/hndchipc.c linux.dev/arch/mips/bcm947xx/hndchipc.c
+--- linux.old/arch/mips/bcm947xx/hndchipc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/hndchipc.c 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,158 @@
++/*
++ * BCM47XX support code for some chipcommon (old extif) facilities (uart)
++ *
++ * 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.
++ *
++ * $Id: hndchipc.c,v 1.1.1.1 2006/02/27 03:43:16 honor Exp $
++ */
++
++#include <typedefs.h>
++#include <bcmdefs.h>
++#include <osl.h>
++#include <bcmutils.h>
++#include <sbutils.h>
++#include <bcmdevs.h>
++#include <bcmnvram.h>
++#include <sbconfig.h>
++#include <sbextif.h>
++#include <sbchipc.h>
++#include <hndcpu.h>
++
++/*
++ * Returns TRUE if an external UART exists at the given base
++ * register.
++ */
++static bool
++BCMINITFN(serial_exists)(osl_t *osh, uint8 *regs)
++{
++ uint8 save_mcr, status1;
++
++ save_mcr = R_REG(osh, &regs[UART_MCR]);
++ W_REG(osh, &regs[UART_MCR], UART_MCR_LOOP | 0x0a);
++ status1 = R_REG(osh, &regs[UART_MSR]) & 0xf0;
++ W_REG(osh, &regs[UART_MCR], save_mcr);
++
++ return (status1 == 0x90);
++}
++
++/*
++ * Initializes UART access. The callback function will be called once
++ * per found UART.
++ */
++void
++BCMINITFN(sb_serial_init)(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base,
++ uint reg_shift))
++{
++ osl_t *osh;
++ void *regs;
++ ulong base;
++ uint irq;
++ int i, n;
++
++ osh = sb_osh(sbh);
++
++ if ((regs = sb_setcore(sbh, SB_EXTIF, 0))) {
++ extifregs_t *eir = (extifregs_t *) regs;
++ sbconfig_t *sb;
++
++ /* Determine external UART register base */
++ sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF);
++ base = EXTIF_CFGIF_BASE(sb_base(R_REG(osh, &sb->sbadmatch1)));
++
++ /* Determine IRQ */
++ irq = sb_irq(sbh);
++
++ /* Disable GPIO interrupt initially */
++ W_REG(osh, &eir->gpiointpolarity, 0);
++ W_REG(osh, &eir->gpiointmask, 0);
++
++ /* Search for external UARTs */
++ n = 2;
++ for (i = 0; i < 2; i++) {
++ regs = (void *) REG_MAP(base + (i * 8), 8);
++ if (serial_exists(osh, regs)) {
++ /* Set GPIO 1 to be the external UART IRQ */
++ W_REG(osh, &eir->gpiointmask, 2);
++ /* XXXDetermine external UART clock */
++ if (add)
++ add(regs, irq, 13500000, 0);
++ }
++ }
++
++ /* Add internal UART if enabled */
++ if (R_REG(osh, &eir->corecontrol) & CC_UE)
++ if (add)
++ add((void *) &eir->uartdata, irq, sb_clock(sbh), 2);
++ } else if ((regs = sb_setcore(sbh, SB_CC, 0))) {
++ chipcregs_t *cc = (chipcregs_t *) regs;
++ uint32 rev, cap, pll, baud_base, div;
++
++ /* Determine core revision and capabilities */
++ rev = sb_corerev(sbh);
++ cap = R_REG(osh, &cc->capabilities);
++ pll = cap & CAP_PLL_MASK;
++
++ /* Determine IRQ */
++ irq = sb_irq(sbh);
++
++ if (pll == PLL_TYPE1) {
++ /* PLL clock */
++ baud_base = sb_clock_rate(pll,
++ R_REG(osh, &cc->clockcontrol_n),
++ R_REG(osh, &cc->clockcontrol_m2));
++ div = 1;
++ } else {
++ /* Fixed ALP clock */
++ if (rev >= 11 && rev != 15) {
++ baud_base = 20000000;
++ div = 1;
++ /* Set the override bit so we don't divide it */
++ W_REG(osh, &cc->corecontrol, CC_UARTCLKO);
++ }
++ /* Internal backplane clock */
++ else if (rev >= 3) {
++ baud_base = sb_clock(sbh);
++ div = 2; /* Minimum divisor */
++ W_REG(osh, &cc->clkdiv,
++ ((R_REG(osh, &cc->clkdiv) & ~CLKD_UART) | div));
++ }
++ /* Fixed internal backplane clock */
++ else {
++ baud_base = 88000000;
++ div = 48;
++ }
++
++ /* Clock source depends on strapping if UartClkOverride is unset */
++ if ((rev > 0) &&
++ ((R_REG(osh, &cc->corecontrol) & CC_UARTCLKO) == 0)) {
++ if ((cap & CAP_UCLKSEL) == CAP_UINTCLK) {
++ /* Internal divided backplane clock */
++ baud_base /= div;
++ } else {
++ /* Assume external clock of 1.8432 MHz */
++ baud_base = 1843200;
++ }
++ }
++ }
++
++ /* Add internal UARTs */
++ n = cap & CAP_UARTS_MASK;
++ for (i = 0; i < n; i++) {
++ /* Register offset changed after revision 0 */
++ if (rev)
++ regs = (void *)((ulong) &cc->uart0data + (i * 256));
++ else
++ regs = (void *)((ulong) &cc->uart0data + (i * 8));
++
++ if (add)
++ add(regs, irq, baud_base, 0);
++ }
++ }
++}
++
+diff -urN linux.old/arch/mips/bcm947xx/include/bcm4710.h linux.dev/arch/mips/bcm947xx/include/bcm4710.h
+--- linux.old/arch/mips/bcm947xx/include/bcm4710.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/bcm4710.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,91 @@
++/*
++ * BCM4710 address space map and definitions
++ * Think twice before adding to this file, this is not the kitchen sink
++ * These definitions are not guaranteed for all 47xx chips, only the 4710
++ *
++ * 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.
++ *
++ * $Id: bcm4710.h,v 1.3 2004/09/27 07:23:30 tallest Exp $
++ */
++
++#ifndef _bcm4710_h_
++#define _bcm4710_h_
++
++/* Address map */
++#define BCM4710_SDRAM 0x00000000 /* Physical SDRAM */
++#define BCM4710_PCI_MEM 0x08000000 /* Host Mode PCI memory access space (64 MB) */
++#define BCM4710_PCI_CFG 0x0c000000 /* Host Mode PCI configuration space (64 MB) */
++#define BCM4710_PCI_DMA 0x40000000 /* Client Mode PCI memory access space (1 GB) */
++#define BCM4710_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */
++#define BCM4710_ENUM 0x18000000 /* Beginning of core enumeration space */
++
++/* Core register space */
++#define BCM4710_REG_SDRAM 0x18000000 /* SDRAM core registers */
++#define BCM4710_REG_ILINE20 0x18001000 /* InsideLine20 core registers */
++#define BCM4710_REG_EMAC0 0x18002000 /* Ethernet MAC 0 core registers */
++#define BCM4710_REG_CODEC 0x18003000 /* Codec core registers */
++#define BCM4710_REG_USB 0x18004000 /* USB core registers */
++#define BCM4710_REG_PCI 0x18005000 /* PCI core registers */
++#define BCM4710_REG_MIPS 0x18006000 /* MIPS core registers */
++#define BCM4710_REG_EXTIF 0x18007000 /* External Interface core registers */
++#define BCM4710_REG_EMAC1 0x18008000 /* Ethernet MAC 1 core registers */
++
++#define BCM4710_EXTIF 0x1f000000 /* External Interface base address */
++#define BCM4710_PCMCIA_MEM 0x1f000000 /* External Interface PCMCIA memory access */
++#define BCM4710_PCMCIA_IO 0x1f100000 /* PCMCIA I/O access */
++#define BCM4710_PCMCIA_CONF 0x1f200000 /* PCMCIA configuration */
++#define BCM4710_PROG 0x1f800000 /* Programable interface */
++#define BCM4710_FLASH 0x1fc00000 /* Flash */
++
++#define BCM4710_EJTAG 0xff200000 /* MIPS EJTAG space (2M) */
++
++#define BCM4710_UART (BCM4710_REG_EXTIF + 0x00000300)
++
++#define BCM4710_EUART (BCM4710_EXTIF + 0x00800000)
++#define BCM4710_LED (BCM4710_EXTIF + 0x00900000)
++
++#define SBFLAG_PCI 0
++#define SBFLAG_ENET0 1
++#define SBFLAG_ILINE20 2
++#define SBFLAG_CODEC 3
++#define SBFLAG_USB 4
++#define SBFLAG_EXTIF 5
++#define SBFLAG_ENET1 6
++
++#ifdef CONFIG_HWSIM
++#define BCM4710_TRACE(trval) do { *((int *)0xa0000f18) = (trval); } while (0)
++#else
++#define BCM4710_TRACE(trval)
++#endif
++
++
++/* BCM94702 CPCI -ExtIF used for LocalBus devs */
++
++#define BCM94702_CPCI_RESET_ADDR BCM4710_EXTIF
++#define BCM94702_CPCI_BOARDID_ADDR (BCM4710_EXTIF | 0x4000)
++#define BCM94702_CPCI_DOC_ADDR (BCM4710_EXTIF | 0x6000)
++#define BCM94702_DOC_ADDR BCM94702_CPCI_DOC_ADDR
++#define BCM94702_CPCI_LED_ADDR (BCM4710_EXTIF | 0xc000)
++#define BCM94702_CPCI_NVRAM_ADDR (BCM4710_EXTIF | 0xe000)
++#define BCM94702_CPCI_NVRAM_SIZE 0x1ff0 /* 8K NVRAM : DS1743/STM48txx*/
++#define BCM94702_CPCI_TOD_REG_BASE (BCM94702_CPCI_NVRAM_ADDR | 0x1ff0)
++
++#define LED_REG(x) \
++ (*(volatile unsigned char *) (KSEG1ADDR(BCM94702_CPCI_LED_ADDR) + (x)))
++
++/*
++ * Reset function implemented in PLD. Read or write should trigger hard reset
++ */
++#define SYS_HARD_RESET() \
++ { for (;;) \
++ *( (volatile unsigned char *)\
++ KSEG1ADDR(BCM94702_CPCI_RESET_ADDR) ) = 0x80; \
++ }
++
++#endif /* _bcm4710_h_ */
+diff -urN linux.old/arch/mips/bcm947xx/include/bcmdefs.h linux.dev/arch/mips/bcm947xx/include/bcmdefs.h
+--- linux.old/arch/mips/bcm947xx/include/bcmdefs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/bcmdefs.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,106 @@
++/*
++ * Misc system wide definitions
++ *
++ * 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.
++ * $Id: bcmdefs.h,v 1.1.1.3 2006/04/08 06:13:39 honor Exp $
++ */
++
++#ifndef _bcmdefs_h_
++#define _bcmdefs_h_
++
++/*
++ * One doesn't need to include this file explicitly, gets included automatically if
++ * typedefs.h is included.
++ */
++
++/* Reclaiming text and data :
++ * The following macros specify special linker sections that can be reclaimed
++ * after a system is considered 'up'.
++ */
++#if defined(__GNUC__) && defined(BCMRECLAIM)
++extern bool bcmreclaimed;
++#define BCMINITDATA(_data) __attribute__ ((__section__ (".dataini." #_data))) _data
++#define BCMINITFN(_fn) __attribute__ ((__section__ (".textini." #_fn))) _fn
++#else /* #if defined(__GNUC__) && defined(BCMRECLAIM) */
++#define BCMINITDATA(_data) _data
++#define BCMINITFN(_fn) _fn
++#define bcmreclaimed 0
++#endif /* #if defined(__GNUC__) && defined(BCMRECLAIM) */
++
++/* Reclaim uninit functions if BCMNODOWN is defined */
++/* and if they are not already removed by -gc-sections */
++#ifdef BCMNODOWN
++#define BCMUNINITFN(_fn) BCMINITFN(_fn)
++#else
++#define BCMUNINITFN(_fn) _fn
++#endif
++
++#ifdef BCMRECLAIM
++#define CONST
++#else
++#define CONST const
++#endif /* BCMRECLAIM */
++
++/* Compatibility with old-style BCMRECLAIM */
++#define BCMINIT(_id) _id
++
++
++/* Put some library data/code into ROM to reduce RAM requirements */
++#if defined(__GNUC__) && defined(BCMROMOFFLOAD)
++#define BCMROMDATA(_data) __attribute__ ((__section__ (".datarom." #_data))) _data
++#define BCMROMFN(_fn) __attribute__ ((__section__ (".textrom." #_fn))) _fn
++#else
++#define BCMROMDATA(_data) _data
++#define BCMROMFN(_fn) _fn
++#endif
++
++/* Bus types */
++#define SB_BUS 0 /* Silicon Backplane */
++#define PCI_BUS 1 /* PCI target */
++#define PCMCIA_BUS 2 /* PCMCIA target */
++#define SDIO_BUS 3 /* SDIO target */
++#define JTAG_BUS 4 /* JTAG */
++#define NO_BUS 0xFF /* Bus that does not support R/W REG */
++
++/* Allows optimization for single-bus support */
++#ifdef BCMBUSTYPE
++#define BUSTYPE(bus) (BCMBUSTYPE)
++#else
++#define BUSTYPE(bus) (bus)
++#endif
++
++/* Defines for DMA Address Width - Shared between OSL and HNDDMA */
++#define DMADDR_MASK_32 0x0 /* Address mask for 32-bits */
++#define DMADDR_MASK_30 0xc0000000 /* Address mask for 30-bits */
++#define DMADDR_MASK_0 0xffffffff /* Address mask for 0-bits (hi-part) */
++
++#define DMADDRWIDTH_30 30 /* 30-bit addressing capability */
++#define DMADDRWIDTH_32 32 /* 32-bit addressing capability */
++#define DMADDRWIDTH_63 63 /* 64-bit addressing capability */
++#define DMADDRWIDTH_64 64 /* 64-bit addressing capability */
++
++/* packet headroom necessary to accomodate the largest header in the system, (i.e TXOFF).
++ * By doing, we avoid the need to allocate an extra buffer for the header when bridging to WL.
++ * There is a compile time check in wlc.c which ensure that this value is at least as big
++ * as TXOFF. This value is used in dma_rxfill (hnddma.c).
++ */
++#define BCMEXTRAHDROOM 160
++
++/* Headroom required for dongle-to-host communication. Packets allocated
++ * locally in the dongle (e.g. for CDC ioctls or RNDIS messages) should
++ * leave this much room in front for low-level message headers which may
++ * be needed to get across the dongle bus to the host. (These messages
++ * don't go over the network, so room for the full WL header above would
++ * be a waste.)
++ */
++#define BCMDONGLEHDRSZ 8
++
++
++
++#endif /* _bcmdefs_h_ */
+diff -urN linux.old/arch/mips/bcm947xx/include/bcmdevs1.h linux.dev/arch/mips/bcm947xx/include/bcmdevs1.h
+--- linux.old/arch/mips/bcm947xx/include/bcmdevs1.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/bcmdevs1.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,391 @@
++/*
++ * Broadcom device-specific manifest constants.
++ *
++ * Copyright 2005, 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.
++ * $Id$
++ */
++
++#ifndef _BCMDEVS_H
++#define _BCMDEVS_H
++
++
++/* Known PCI vendor Id's */
++#define VENDOR_EPIGRAM 0xfeda
++#define VENDOR_BROADCOM 0x14e4
++#define VENDOR_3COM 0x10b7
++#define VENDOR_NETGEAR 0x1385
++#define VENDOR_DIAMOND 0x1092
++#define VENDOR_DELL 0x1028
++#define VENDOR_HP 0x0e11
++#define VENDOR_APPLE 0x106b
++
++/* PCI Device Id's */
++#define BCM4210_DEVICE_ID 0x1072 /* never used */
++#define BCM4211_DEVICE_ID 0x4211
++#define BCM4230_DEVICE_ID 0x1086 /* never used */
++#define BCM4231_DEVICE_ID 0x4231
++
++#define BCM4410_DEVICE_ID 0x4410 /* bcm44xx family pci iline */
++#define BCM4430_DEVICE_ID 0x4430 /* bcm44xx family cardbus iline */
++#define BCM4412_DEVICE_ID 0x4412 /* bcm44xx family pci enet */
++#define BCM4432_DEVICE_ID 0x4432 /* bcm44xx family cardbus enet */
++
++#define BCM3352_DEVICE_ID 0x3352 /* bcm3352 device id */
++#define BCM3360_DEVICE_ID 0x3360 /* bcm3360 device id */
++
++#define EPI41210_DEVICE_ID 0xa0fa /* bcm4210 */
++#define EPI41230_DEVICE_ID 0xa10e /* bcm4230 */
++
++#define BCM47XX_ILINE_ID 0x4711 /* 47xx iline20 */
++#define BCM47XX_V90_ID 0x4712 /* 47xx v90 codec */
++#define BCM47XX_ENET_ID 0x4713 /* 47xx enet */
++#define BCM47XX_EXT_ID 0x4714 /* 47xx external i/f */
++#define BCM47XX_USB_ID 0x4715 /* 47xx usb */
++#define BCM47XX_USBH_ID 0x4716 /* 47xx usb host */
++#define BCM47XX_USBD_ID 0x4717 /* 47xx usb device */
++#define BCM47XX_IPSEC_ID 0x4718 /* 47xx ipsec */
++#define BCM47XX_ROBO_ID 0x4719 /* 47xx/53xx roboswitch core */
++#define BCM47XX_USB20H_ID 0x471a /* 47xx usb 2.0 host */
++#define BCM47XX_USB20D_ID 0x471b /* 47xx usb 2.0 device */
++
++#define BCM4710_DEVICE_ID 0x4710 /* 4710 primary function 0 */
++
++#define BCM4610_DEVICE_ID 0x4610 /* 4610 primary function 0 */
++#define BCM4610_ILINE_ID 0x4611 /* 4610 iline100 */
++#define BCM4610_V90_ID 0x4612 /* 4610 v90 codec */
++#define BCM4610_ENET_ID 0x4613 /* 4610 enet */
++#define BCM4610_EXT_ID 0x4614 /* 4610 external i/f */
++#define BCM4610_USB_ID 0x4615 /* 4610 usb */
++
++#define BCM4402_DEVICE_ID 0x4402 /* 4402 primary function 0 */
++#define BCM4402_ENET_ID 0x4402 /* 4402 enet */
++#define BCM4402_V90_ID 0x4403 /* 4402 v90 codec */
++#define BCM4401_ENET_ID 0x170c /* 4401b0 production enet cards */
++
++#define BCM4301_DEVICE_ID 0x4301 /* 4301 primary function 0 */
++#define BCM4301_D11B_ID 0x4301 /* 4301 802.11b */
++
++#define BCM4307_DEVICE_ID 0x4307 /* 4307 primary function 0 */
++#define BCM4307_V90_ID 0x4305 /* 4307 v90 codec */
++#define BCM4307_ENET_ID 0x4306 /* 4307 enet */
++#define BCM4307_D11B_ID 0x4307 /* 4307 802.11b */
++
++#define BCM4306_DEVICE_ID 0x4306 /* 4306 chipcommon chipid */
++#define BCM4306_D11G_ID 0x4320 /* 4306 802.11g */
++#define BCM4306_D11G_ID2 0x4325
++#define BCM4306_D11A_ID 0x4321 /* 4306 802.11a */
++#define BCM4306_UART_ID 0x4322 /* 4306 uart */
++#define BCM4306_V90_ID 0x4323 /* 4306 v90 codec */
++#define BCM4306_D11DUAL_ID 0x4324 /* 4306 dual A+B */
++
++#define BCM4309_PKG_ID 1 /* 4309 package id */
++
++#define BCM4303_D11B_ID 0x4303 /* 4303 802.11b */
++#define BCM4303_PKG_ID 2 /* 4303 package id */
++
++#define BCM4310_DEVICE_ID 0x4310 /* 4310 chipcommon chipid */
++#define BCM4310_D11B_ID 0x4311 /* 4310 802.11b */
++#define BCM4310_UART_ID 0x4312 /* 4310 uart */
++#define BCM4310_ENET_ID 0x4313 /* 4310 enet */
++#define BCM4310_USB_ID 0x4315 /* 4310 usb */
++
++#define BCMGPRS_UART_ID 0x4333 /* Uart id used by 4306/gprs card */
++#define BCMGPRS2_UART_ID 0x4344 /* Uart id used by 4306/gprs card */
++
++
++#define BCM4704_DEVICE_ID 0x4704 /* 4704 chipcommon chipid */
++#define BCM4704_ENET_ID 0x4706 /* 4704 enet (Use 47XX_ENET_ID instead!) */
++
++#define BCM4317_DEVICE_ID 0x4317 /* 4317 chip common chipid */
++
++#define BCM4318_DEVICE_ID 0x4318 /* 4318 chip common chipid */
++#define BCM4318_D11G_ID 0x4318 /* 4318 801.11b/g id */
++#define BCM4318_D11DUAL_ID 0x4319 /* 4318 801.11a/b/g id */
++#define BCM4318_JTAGM_ID 0x4331 /* 4318 jtagm device id */
++
++#define FPGA_JTAGM_ID 0x4330 /* ??? */
++
++/* Address map */
++#define BCM4710_SDRAM 0x00000000 /* Physical SDRAM */
++#define BCM4710_PCI_MEM 0x08000000 /* Host Mode PCI memory access space (64 MB) */
++#define BCM4710_PCI_CFG 0x0c000000 /* Host Mode PCI configuration space (64 MB) */
++#define BCM4710_PCI_DMA 0x40000000 /* Client Mode PCI memory access space (1 GB) */
++#define BCM4710_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */
++#define BCM4710_ENUM 0x18000000 /* Beginning of core enumeration space */
++
++/* Core register space */
++#define BCM4710_REG_SDRAM 0x18000000 /* SDRAM core registers */
++#define BCM4710_REG_ILINE20 0x18001000 /* InsideLine20 core registers */
++#define BCM4710_REG_EMAC0 0x18002000 /* Ethernet MAC 0 core registers */
++#define BCM4710_REG_CODEC 0x18003000 /* Codec core registers */
++#define BCM4710_REG_USB 0x18004000 /* USB core registers */
++#define BCM4710_REG_PCI 0x18005000 /* PCI core registers */
++#define BCM4710_REG_MIPS 0x18006000 /* MIPS core registers */
++#define BCM4710_REG_EXTIF 0x18007000 /* External Interface core registers */
++#define BCM4710_REG_EMAC1 0x18008000 /* Ethernet MAC 1 core registers */
++
++#define BCM4710_EXTIF 0x1f000000 /* External Interface base address */
++#define BCM4710_PCMCIA_MEM 0x1f000000 /* External Interface PCMCIA memory access */
++#define BCM4710_PCMCIA_IO 0x1f100000 /* PCMCIA I/O access */
++#define BCM4710_PCMCIA_CONF 0x1f200000 /* PCMCIA configuration */
++#define BCM4710_PROG 0x1f800000 /* Programable interface */
++#define BCM4710_FLASH 0x1fc00000 /* Flash */
++
++#define BCM4710_EJTAG 0xff200000 /* MIPS EJTAG space (2M) */
++
++#define BCM4710_UART (BCM4710_REG_EXTIF + 0x00000300)
++
++#define BCM4710_EUART (BCM4710_EXTIF + 0x00800000)
++#define BCM4710_LED (BCM4710_EXTIF + 0x00900000)
++
++#define BCM4712_DEVICE_ID 0x4712 /* 4712 chipcommon chipid */
++#define BCM4712_MIPS_ID 0x4720 /* 4712 base devid */
++#define BCM4712LARGE_PKG_ID 0 /* 340pin 4712 package id */
++#define BCM4712SMALL_PKG_ID 1 /* 200pin 4712 package id */
++#define BCM4712MID_PKG_ID 2 /* 225pin 4712 package id */
++
++#define SDIOH_FPGA_ID 0x4380 /* sdio host fpga */
++
++#define BCM5365_DEVICE_ID 0x5365 /* 5365 chipcommon chipid */
++#define BCM5350_DEVICE_ID 0x5350 /* bcm5350 chipcommon chipid */
++#define BCM5352_DEVICE_ID 0x5352 /* bcm5352 chipcommon chipid */
++
++#define BCM4320_DEVICE_ID 0x4320 /* bcm4320 chipcommon chipid */
++
++/* PCMCIA vendor Id's */
++
++#define VENDOR_BROADCOM_PCMCIA 0x02d0
++
++/* SDIO vendor Id's */
++#define VENDOR_BROADCOM_SDIO 0x00BF
++
++
++/* boardflags */
++#define BFL_BTCOEXIST 0x0001 /* This board implements Bluetooth coexistance */
++#define BFL_PACTRL 0x0002 /* This board has gpio 9 controlling the PA */
++#define BFL_AIRLINEMODE 0x0004 /* This board implements gpio13 radio disable indication */
++#define BFL_ENETROBO 0x0010 /* This board has robo switch or core */
++#define BFL_CCKHIPWR 0x0040 /* Can do high-power CCK transmission */
++#define BFL_ENETADM 0x0080 /* This board has ADMtek switch */
++#define BFL_ENETVLAN 0x0100 /* This board has vlan capability */
++#define BFL_AFTERBURNER 0x0200 /* This board supports Afterburner mode */
++#define BFL_NOPCI 0x0400 /* This board leaves PCI floating */
++#define BFL_FEM 0x0800 /* This board supports the Front End Module */
++#define BFL_EXTLNA 0x1000 /* This board has an external LNA */
++#define BFL_HGPA 0x2000 /* This board has a high gain PA */
++#define BFL_BTCMOD 0x4000 /* This board' BTCOEXIST is in the alternate gpios */
++#define BFL_ALTIQ 0x8000 /* Alternate I/Q settings */
++
++/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */
++#define BOARD_GPIO_HWRAD_B 0x010 /* bit 4 is HWRAD input on 4301 */
++#define BOARD_GPIO_BTCMOD_IN 0x010 /* bit 4 is the alternate BT Coexistance Input */
++#define BOARD_GPIO_BTCMOD_OUT 0x020 /* bit 5 is the alternate BT Coexistance Out */
++#define BOARD_GPIO_BTC_IN 0x080 /* bit 7 is BT Coexistance Input */
++#define BOARD_GPIO_BTC_OUT 0x100 /* bit 8 is BT Coexistance Out */
++#define BOARD_GPIO_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */
++#define PCI_CFG_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */
++#define PCI_CFG_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */
++#define PCI_CFG_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */
++#define PCI_CFG_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */
++
++/* Bus types */
++#define SB_BUS 0 /* Silicon Backplane */
++#define PCI_BUS 1 /* PCI target */
++#define PCMCIA_BUS 2 /* PCMCIA target */
++#define SDIO_BUS 3 /* SDIO target */
++#define JTAG_BUS 4 /* JTAG */
++
++/* Allows optimization for single-bus support */
++#ifdef BCMBUSTYPE
++#define BUSTYPE(bus) (BCMBUSTYPE)
++#else
++#define BUSTYPE(bus) (bus)
++#endif
++
++/* power control defines */
++#define PLL_DELAY 150 /* us pll on delay */
++#define FREF_DELAY 200 /* us fref change delay */
++#define MIN_SLOW_CLK 32 /* us Slow clock period */
++#define XTAL_ON_DELAY 1000 /* us crystal power-on delay */
++
++/* Reference Board Types */
++
++#define BU4710_BOARD 0x0400
++#define VSIM4710_BOARD 0x0401
++#define QT4710_BOARD 0x0402
++
++#define BU4610_BOARD 0x0403
++#define VSIM4610_BOARD 0x0404
++
++#define BU4307_BOARD 0x0405
++#define BCM94301CB_BOARD 0x0406
++#define BCM94301PC_BOARD 0x0406 /* Pcmcia 5v card */
++#define BCM94301MP_BOARD 0x0407
++#define BCM94307MP_BOARD 0x0408
++#define BCMAP4307_BOARD 0x0409
++
++#define BU4309_BOARD 0x040a
++#define BCM94309CB_BOARD 0x040b
++#define BCM94309MP_BOARD 0x040c
++#define BCM4309AP_BOARD 0x040d
++
++#define BCM94302MP_BOARD 0x040e
++
++#define VSIM4310_BOARD 0x040f
++#define BU4711_BOARD 0x0410
++#define BCM94310U_BOARD 0x0411
++#define BCM94310AP_BOARD 0x0412
++#define BCM94310MP_BOARD 0x0414
++
++#define BU4306_BOARD 0x0416
++#define BCM94306CB_BOARD 0x0417
++#define BCM94306MP_BOARD 0x0418
++
++#define BCM94710D_BOARD 0x041a
++#define BCM94710R1_BOARD 0x041b
++#define BCM94710R4_BOARD 0x041c
++#define BCM94710AP_BOARD 0x041d
++
++
++#define BU2050_BOARD 0x041f
++
++
++#define BCM94309G_BOARD 0x0421
++
++#define BCM94301PC3_BOARD 0x0422 /* Pcmcia 3.3v card */
++
++#define BU4704_BOARD 0x0423
++#define BU4702_BOARD 0x0424
++
++#define BCM94306PC_BOARD 0x0425 /* pcmcia 3.3v 4306 card */
++
++#define BU4317_BOARD 0x0426
++
++
++#define BCM94702MN_BOARD 0x0428
++
++/* BCM4702 1U CompactPCI Board */
++#define BCM94702CPCI_BOARD 0x0429
++
++/* BCM4702 with BCM95380 VLAN Router */
++#define BCM95380RR_BOARD 0x042a
++
++/* cb4306 with SiGe PA */
++#define BCM94306CBSG_BOARD 0x042b
++
++/* mp4301 with 2050 radio */
++#define BCM94301MPL_BOARD 0x042c
++
++/* cb4306 with SiGe PA */
++#define PCSG94306_BOARD 0x042d
++
++/* bu4704 with sdram */
++#define BU4704SD_BOARD 0x042e
++
++/* Dual 11a/11g Router */
++#define BCM94704AGR_BOARD 0x042f
++
++/* 11a-only minipci */
++#define BCM94308MP_BOARD 0x0430
++
++
++
++/* BCM94317 boards */
++#define BCM94317CB_BOARD 0x0440
++#define BCM94317MP_BOARD 0x0441
++#define BCM94317PCMCIA_BOARD 0x0442
++#define BCM94317SDIO_BOARD 0x0443
++
++#define BU4712_BOARD 0x0444
++#define BU4712SD_BOARD 0x045d
++#define BU4712L_BOARD 0x045f
++
++/* BCM4712 boards */
++#define BCM94712AP_BOARD 0x0445
++#define BCM94712P_BOARD 0x0446
++
++/* BCM4318 boards */
++#define BU4318_BOARD 0x0447
++#define CB4318_BOARD 0x0448
++#define MPG4318_BOARD 0x0449
++#define MP4318_BOARD 0x044a
++#define SD4318_BOARD 0x044b
++
++/* BCM63XX boards */
++#define BCM96338_BOARD 0x6338
++#define BCM96345_BOARD 0x6345
++#define BCM96348_BOARD 0x6348
++
++/* Another mp4306 with SiGe */
++#define BCM94306P_BOARD 0x044c
++
++/* CF-like 4317 modules */
++#define BCM94317CF_BOARD 0x044d
++
++/* mp4303 */
++#define BCM94303MP_BOARD 0x044e
++
++/* mpsgh4306 */
++#define BCM94306MPSGH_BOARD 0x044f
++
++/* BRCM 4306 w/ Front End Modules */
++#define BCM94306MPM 0x0450
++#define BCM94306MPL 0x0453
++
++/* 4712agr */
++#define BCM94712AGR_BOARD 0x0451
++
++/* The real CF 4317 board */
++#define CFI4317_BOARD 0x0452
++
++/* pcmcia 4303 */
++#define PC4303_BOARD 0x0454
++
++/* 5350K */
++#define BCM95350K_BOARD 0x0455
++
++/* 5350R */
++#define BCM95350R_BOARD 0x0456
++
++/* 4306mplna */
++#define BCM94306MPLNA_BOARD 0x0457
++
++/* 4320 boards */
++#define BU4320_BOARD 0x0458
++#define BU4320S_BOARD 0x0459
++#define BCM94320PH_BOARD 0x045a
++
++/* 4306mph */
++#define BCM94306MPH_BOARD 0x045b
++
++/* 4306pciv */
++#define BCM94306PCIV_BOARD 0x045c
++
++#define BU4712SD_BOARD 0x045d
++
++#define BCM94320PFLSH_BOARD 0x045e
++
++#define BU4712L_BOARD 0x045f
++#define BCM94712LGR_BOARD 0x0460
++#define BCM94320R_BOARD 0x0461
++
++#define BU5352_BOARD 0x0462
++
++#define BCM94318MPGH_BOARD 0x0463
++
++
++#define BCM95352GR_BOARD 0x0467
++
++/* bcm95351agr */
++#define BCM95351AGR_BOARD 0x0470
++
++/* # of GPIO pins */
++#define GPIO_NUMPINS 16
++
++#endif /* _BCMDEVS_H */
+diff -urN linux.old/arch/mips/bcm947xx/include/bcmdevs.h linux.dev/arch/mips/bcm947xx/include/bcmdevs.h
+--- linux.old/arch/mips/bcm947xx/include/bcmdevs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/bcmdevs.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,369 @@
++/*
++ * Broadcom device-specific manifest constants.
++ *
++ * 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.
++ * $Id: bcmdevs.h,v 1.1.1.17 2006/04/15 01:29:08 michael Exp $
++ */
++
++#ifndef _BCMDEVS_H
++#define _BCMDEVS_H
++
++#include "bcm4710.h"
++
++/* Known PCI vendor Id's */
++#define VENDOR_EPIGRAM 0xfeda
++#define VENDOR_BROADCOM 0x14e4
++#define VENDOR_3COM 0x10b7
++#define VENDOR_NETGEAR 0x1385
++#define VENDOR_DIAMOND 0x1092
++#define VENDOR_DELL 0x1028
++#define VENDOR_HP 0x0e11
++#define VENDOR_APPLE 0x106b
++
++/* PCI Device Id's */
++#define BCM4210_DEVICE_ID 0x1072 /* never used */
++#define BCM4211_DEVICE_ID 0x4211
++#define BCM4230_DEVICE_ID 0x1086 /* never used */
++#define BCM4231_DEVICE_ID 0x4231
++
++#define BCM4410_DEVICE_ID 0x4410 /* bcm44xx family pci iline */
++#define BCM4430_DEVICE_ID 0x4430 /* bcm44xx family cardbus iline */
++#define BCM4412_DEVICE_ID 0x4412 /* bcm44xx family pci enet */
++#define BCM4432_DEVICE_ID 0x4432 /* bcm44xx family cardbus enet */
++
++#define BCM3352_DEVICE_ID 0x3352 /* bcm3352 device id */
++#define BCM3360_DEVICE_ID 0x3360 /* bcm3360 device id */
++
++#define EPI41210_DEVICE_ID 0xa0fa /* bcm4210 */
++#define EPI41230_DEVICE_ID 0xa10e /* bcm4230 */
++
++#define BCM47XX_ILINE_ID 0x4711 /* 47xx iline20 */
++#define BCM47XX_V90_ID 0x4712 /* 47xx v90 codec */
++#define BCM47XX_ENET_ID 0x4713 /* 47xx enet */
++#define BCM47XX_EXT_ID 0x4714 /* 47xx external i/f */
++#define BCM47XX_USB_ID 0x4715 /* 47xx usb */
++#define BCM47XX_USBH_ID 0x4716 /* 47xx usb host */
++#define BCM47XX_USBD_ID 0x4717 /* 47xx usb device */
++#define BCM47XX_IPSEC_ID 0x4718 /* 47xx ipsec */
++#define BCM47XX_ROBO_ID 0x4719 /* 47xx/53xx roboswitch core */
++#define BCM47XX_USB20H_ID 0x471a /* 47xx usb 2.0 host */
++#define BCM47XX_USB20D_ID 0x471b /* 47xx usb 2.0 device */
++#define BCM47XX_ATA100_ID 0x471d /* 47xx parallel ATA */
++#define BCM47XX_SATAXOR_ID 0x471e /* 47xx serial ATA & XOR DMA */
++#define BCM47XX_GIGETH_ID 0x471f /* 47xx GbE (5700) */
++
++#define BCM47XX_SMBUS_EMU_ID 0x47fe /* 47xx emulated SMBus device */
++#define BCM47XX_XOR_EMU_ID 0x47ff /* 47xx emulated XOR engine */
++
++#define BCM4710_CHIP_ID 0x4710 /* 4710 chipid returned by sb_chip() */
++#define BCM4710_DEVICE_ID 0x4710 /* 4710 primary function 0 */
++
++#define BCM4402_CHIP_ID 0x4402 /* 4402 chipid */
++#define BCM4402_ENET_ID 0x4402 /* 4402 enet */
++#define BCM4402_V90_ID 0x4403 /* 4402 v90 codec */
++#define BCM4401_ENET_ID 0x170c /* 4401b0 production enet cards */
++
++#define BCM4306_CHIP_ID 0x4306 /* 4306 chipcommon chipid */
++#define BCM4306_D11G_ID 0x4320 /* 4306 802.11g */
++#define BCM4306_D11G_ID2 0x4325
++#define BCM4306_D11A_ID 0x4321 /* 4306 802.11a */
++#define BCM4306_UART_ID 0x4322 /* 4306 uart */
++#define BCM4306_V90_ID 0x4323 /* 4306 v90 codec */
++#define BCM4306_D11DUAL_ID 0x4324 /* 4306 dual A+B */
++
++#define BCM4309_PKG_ID 1 /* 4309 package id */
++
++#define BCM4311_CHIP_ID 0x4311 /* 4311 PCIe 802.11a/b/g */
++#define BCM4311_D11G_ID 0x4311 /* 4311 802.11b/g id */
++#define BCM4311_D11DUAL_ID 0x4312 /* 4311 802.11a/b/g id */
++#define BCM4311_D11A_ID 0x4313 /* 4311 802.11a id */
++
++#define BCM4303_D11B_ID 0x4303 /* 4303 802.11b */
++#define BCM4303_PKG_ID 2 /* 4303 package id */
++
++#define BCMGPRS_UART_ID 0x4333 /* Uart id used by 4306/gprs card */
++#define BCMGPRS2_UART_ID 0x4344 /* Uart id used by 4306/gprs card */
++
++#define BCM4704_CHIP_ID 0x4704 /* 4704 chipcommon chipid */
++#define BCM4704_ENET_ID 0x4706 /* 4704 enet (Use 47XX_ENET_ID instead!) */
++
++#define BCM4318_CHIP_ID 0x4318 /* 4318 chip common chipid */
++#define BCM4318_D11G_ID 0x4318 /* 4318 802.11b/g id */
++#define BCM4318_D11DUAL_ID 0x4319 /* 4318 802.11a/b/g id */
++#define BCM4318_D11A_ID 0x431a /* 4318 802.11a id */
++
++#define BCM4321_CHIP_ID 0x4321 /* 4321 chip common chipid */
++#define BCM4321_D11N_ID 0x4328 /* 4321 802.11n dualband id */
++#define BCM4321_D11N2G_ID 0x4329 /* 4321 802.11n 2.4Hgz band id */
++#define BCM4321_D11N5G_ID 0x432a /* 4321 802.11n 5Ghz band id */
++
++#define BCM4331_CHIP_ID 0x4331 /* 4331 chip common chipid */
++#define BCM4331_D11N2G_ID 0x4330 /* 4331 802.11n 2.4Ghz band id */
++#define BCM4331_D11N_ID 0x4331 /* 4331 802.11n dualband id */
++#define BCM4331_D11N5G_ID 0x4332 /* 4331 802.11n 5Ghz band id */
++
++#define HDLSIM5350_PKG_ID 1 /* HDL simulator package id for a 5350 */
++#define HDLSIM_PKG_ID 14 /* HDL simulator package id */
++#define HWSIM_PKG_ID 15 /* Hardware simulator package id */
++
++#define BCM4712_CHIP_ID 0x4712 /* 4712 chipcommon chipid */
++#define BCM4712_MIPS_ID 0x4720 /* 4712 base devid */
++#define BCM4712LARGE_PKG_ID 0 /* 340pin 4712 package id */
++#define BCM4712SMALL_PKG_ID 1 /* 200pin 4712 package id */
++#define BCM4712MID_PKG_ID 2 /* 225pin 4712 package id */
++
++#define BCM5365_CHIP_ID 0x5365 /* 5365 chipcommon chipid */
++#define BCM5350_CHIP_ID 0x5350 /* bcm5350 chipcommon chipid */
++#define BCM5352_CHIP_ID 0x5352 /* bcm5352 chipcommon chipid */
++
++#define BCM4320_CHIP_ID 0x4320 /* bcm4320 chipcommon chipid */
++
++#define BCM4328_CHIP_ID 0x4328 /* bcm4328 chipcommon chipid */
++
++#define FPGA_JTAGM_ID 0x43f0 /* FPGA jtagm device id */
++#define BCM43XX_JTAGM_ID 0x43f1 /* 43xx jtagm device id */
++#define BCM43XXOLD_JTAGM_ID 0x4331 /* 43xx old jtagm device id */
++
++#define SDIOH_FPGA_ID 0x43f2 /* sdio host fpga */
++#define SDIOD_FPGA_ID 0x43f4 /* sdio device fpga */
++
++#define MIMO_FPGA_ID 0x43f8 /* FPGA mimo minimacphy device id */
++
++#define BCM4785_CHIP_ID 0x4785 /* 4785 chipcommon chipid */
++
++/* PCMCIA vendor Id's */
++
++#define VENDOR_BROADCOM_PCMCIA 0x02d0
++
++/* SDIO vendor Id's */
++#define VENDOR_BROADCOM_SDIO 0x00BF
++
++
++/* boardflags */
++#define BFL_BTCOEXIST 0x0001 /* This board implements Bluetooth coexistance */
++#define BFL_PACTRL 0x0002 /* This board has gpio 9 controlling the PA */
++#define BFL_AIRLINEMODE 0x0004 /* This board implements gpio13 radio disable indication */
++#define BFL_ENETROBO 0x0010 /* This board has robo switch or core */
++#define BFL_CCKHIPWR 0x0040 /* Can do high-power CCK transmission */
++#define BFL_ENETADM 0x0080 /* This board has ADMtek switch */
++#define BFL_ENETVLAN 0x0100 /* This board has vlan capability */
++#define BFL_AFTERBURNER 0x0200 /* This board supports Afterburner mode */
++#define BFL_NOPCI 0x0400 /* This board leaves PCI floating */
++#define BFL_FEM 0x0800 /* This board supports the Front End Module */
++#define BFL_EXTLNA 0x1000 /* This board has an external LNA */
++#define BFL_HGPA 0x2000 /* This board has a high gain PA */
++#define BFL_BTCMOD 0x4000 /* This board' BTCOEXIST is in the alternate gpios */
++#define BFL_ALTIQ 0x8000 /* Alternate I/Q settings */
++
++/* boardflags2 */
++#define BFL2_RXBB_INT_REG_DIS 0x00000001 /* This board has an external rxbb regulator */
++#define BFL2_SSWITCH_AVAIL 0x00000002 /* This board has a superswitch for > 2 antennas */
++#define BFL2_TXPWRCTRL_EN 0x00000004 /* This board permits TX Power Control to be enabled */
++
++/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */
++#define BOARD_GPIO_BTCMOD_IN 0x010 /* bit 4 is the alternate BT Coexistance Input */
++#define BOARD_GPIO_BTCMOD_OUT 0x020 /* bit 5 is the alternate BT Coexistance Out */
++#define BOARD_GPIO_BTC_IN 0x080 /* bit 7 is BT Coexistance Input */
++#define BOARD_GPIO_BTC_OUT 0x100 /* bit 8 is BT Coexistance Out */
++#define BOARD_GPIO_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */
++#define PCI_CFG_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */
++#define PCI_CFG_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */
++#define PCI_CFG_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */
++#define PCI_CFG_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */
++
++/* power control defines */
++#define PLL_DELAY 150 /* us pll on delay */
++#define FREF_DELAY 200 /* us fref change delay */
++#define MIN_SLOW_CLK 32 /* us Slow clock period */
++#define XTAL_ON_DELAY 1000 /* us crystal power-on delay */
++
++/* Reference Board Types */
++
++#define BU4710_BOARD 0x0400
++#define VSIM4710_BOARD 0x0401
++#define QT4710_BOARD 0x0402
++
++#define BU4309_BOARD 0x040a
++#define BCM94309CB_BOARD 0x040b
++#define BCM94309MP_BOARD 0x040c
++#define BCM4309AP_BOARD 0x040d
++
++#define BCM94302MP_BOARD 0x040e
++
++#define BU4306_BOARD 0x0416
++#define BCM94306CB_BOARD 0x0417
++#define BCM94306MP_BOARD 0x0418
++
++#define BCM94710D_BOARD 0x041a
++#define BCM94710R1_BOARD 0x041b
++#define BCM94710R4_BOARD 0x041c
++#define BCM94710AP_BOARD 0x041d
++
++#define BU2050_BOARD 0x041f
++
++
++#define BCM94309G_BOARD 0x0421
++
++#define BU4704_BOARD 0x0423
++#define BU4702_BOARD 0x0424
++
++#define BCM94306PC_BOARD 0x0425 /* pcmcia 3.3v 4306 card */
++
++
++#define BCM94702MN_BOARD 0x0428
++
++/* BCM4702 1U CompactPCI Board */
++#define BCM94702CPCI_BOARD 0x0429
++
++/* BCM4702 with BCM95380 VLAN Router */
++#define BCM95380RR_BOARD 0x042a
++
++/* cb4306 with SiGe PA */
++#define BCM94306CBSG_BOARD 0x042b
++
++/* cb4306 with SiGe PA */
++#define PCSG94306_BOARD 0x042d
++
++/* bu4704 with sdram */
++#define BU4704SD_BOARD 0x042e
++
++/* Dual 11a/11g Router */
++#define BCM94704AGR_BOARD 0x042f
++
++/* 11a-only minipci */
++#define BCM94308MP_BOARD 0x0430
++
++
++
++#define BU4712_BOARD 0x0444
++#define BU4712SD_BOARD 0x045d
++#define BU4712L_BOARD 0x045f
++
++/* BCM4712 boards */
++#define BCM94712AP_BOARD 0x0445
++#define BCM94712P_BOARD 0x0446
++
++/* BCM4318 boards */
++#define BU4318_BOARD 0x0447
++#define CB4318_BOARD 0x0448
++#define MPG4318_BOARD 0x0449
++#define MP4318_BOARD 0x044a
++#define SD4318_BOARD 0x044b
++
++/* BCM63XX boards */
++#define BCM96338_BOARD 0x6338
++#define BCM96348_BOARD 0x6348
++
++/* Another mp4306 with SiGe */
++#define BCM94306P_BOARD 0x044c
++
++/* mp4303 */
++#define BCM94303MP_BOARD 0x044e
++
++/* mpsgh4306 */
++#define BCM94306MPSGH_BOARD 0x044f
++
++/* BRCM 4306 w/ Front End Modules */
++#define BCM94306MPM 0x0450
++#define BCM94306MPL 0x0453
++
++/* 4712agr */
++#define BCM94712AGR_BOARD 0x0451
++
++/* pcmcia 4303 */
++#define PC4303_BOARD 0x0454
++
++/* 5350K */
++#define BCM95350K_BOARD 0x0455
++
++/* 5350R */
++#define BCM95350R_BOARD 0x0456
++
++/* 4306mplna */
++#define BCM94306MPLNA_BOARD 0x0457
++
++/* 4320 boards */
++#define BU4320_BOARD 0x0458
++#define BU4320S_BOARD 0x0459
++#define BCM94320PH_BOARD 0x045a
++
++/* 4306mph */
++#define BCM94306MPH_BOARD 0x045b
++
++/* 4306pciv */
++#define BCM94306PCIV_BOARD 0x045c
++
++#define BU4712SD_BOARD 0x045d
++
++#define BCM94320PFLSH_BOARD 0x045e
++
++#define BU4712L_BOARD 0x045f
++#define BCM94712LGR_BOARD 0x0460
++#define BCM94320R_BOARD 0x0461
++
++#define BU5352_BOARD 0x0462
++
++#define BCM94318MPGH_BOARD 0x0463
++
++#define BU4311_BOARD 0x0464
++#define BCM94311MC_BOARD 0x0465
++#define BCM94311MCAG_BOARD 0x0466
++
++#define BCM95352GR_BOARD 0x0467
++
++/* bcm95351agr */
++#define BCM95351AGR_BOARD 0x0470
++
++/* bcm94704mpcb */
++#define BCM94704MPCB_BOARD 0x0472
++
++/* 4785 boards */
++#define BU4785_BOARD 0x0478
++
++/* 4321 boards */
++#define BU4321_BOARD 0x046b
++#define BU4321E_BOARD 0x047c
++#define MP4321_BOARD 0x046c
++#define CB2_4321_BOARD 0x046d
++#define MC4321_BOARD 0x046e
++
++/* # of GPIO pins */
++#define GPIO_NUMPINS 16
++
++/* radio ID codes */
++#define NORADIO_ID 0xe4f5
++#define NORADIO_IDCODE 0x4e4f5246
++
++#define BCM2050_ID 0x2050
++#define BCM2050_IDCODE 0x02050000
++#define BCM2050A0_IDCODE 0x1205017f
++#define BCM2050A1_IDCODE 0x2205017f
++#define BCM2050R8_IDCODE 0x8205017f
++
++#define BCM2055_ID 0x2055
++#define BCM2055_IDCODE 0x02055000
++#define BCM2055A0_IDCODE 0x1205517f
++
++#define BCM2060_ID 0x2060
++#define BCM2060_IDCODE 0x02060000
++#define BCM2060WW_IDCODE 0x1206017f
++
++#define BCM2062_ID 0x2062
++#define BCM2062_IDCODE 0x02062000
++#define BCM2062A0_IDCODE 0x0206217f
++
++/* parts of an idcode: */
++#define IDCODE_MFG_MASK 0x00000fff
++#define IDCODE_MFG_SHIFT 0
++#define IDCODE_ID_MASK 0x0ffff000
++#define IDCODE_ID_SHIFT 12
++#define IDCODE_REV_MASK 0xf0000000
++#define IDCODE_REV_SHIFT 28
++
++#endif /* _BCMDEVS_H */
+diff -urN linux.old/arch/mips/bcm947xx/include/bcmendian.h linux.dev/arch/mips/bcm947xx/include/bcmendian.h
+--- linux.old/arch/mips/bcm947xx/include/bcmendian.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/bcmendian.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,198 @@
++/*
++ * local version of endian.h - byte order defines
++ *
++ * 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.
++ *
++ * $Id: bcmendian.h,v 1.1.1.10 2006/02/27 03:43:16 honor Exp $
++*/
++
++#ifndef _BCMENDIAN_H_
++#define _BCMENDIAN_H_
++
++#include <typedefs.h>
++
++/* Byte swap a 16 bit value */
++#define BCMSWAP16(val) \
++ ((uint16)(\
++ (((uint16)(val) & (uint16)0x00ffU) << 8) | \
++ (((uint16)(val) & (uint16)0xff00U) >> 8)))
++
++/* Byte swap a 32 bit value */
++#define BCMSWAP32(val) \
++ ((uint32)(\
++ (((uint32)(val) & (uint32)0x000000ffUL) << 24) | \
++ (((uint32)(val) & (uint32)0x0000ff00UL) << 8) | \
++ (((uint32)(val) & (uint32)0x00ff0000UL) >> 8) | \
++ (((uint32)(val) & (uint32)0xff000000UL) >> 24)))
++
++/* 2 Byte swap a 32 bit value */
++#define BCMSWAP32BY16(val) \
++ ((uint32)(\
++ (((uint32)(val) & (uint32)0x0000ffffUL) << 16) | \
++ (((uint32)(val) & (uint32)0xffff0000UL) >> 16)))
++
++
++static INLINE uint16
++bcmswap16(uint16 val)
++{
++ return BCMSWAP16(val);
++}
++
++static INLINE uint32
++bcmswap32(uint32 val)
++{
++ return BCMSWAP32(val);
++}
++
++static INLINE uint32
++bcmswap32by16(uint32 val)
++{
++ return BCMSWAP32BY16(val);
++}
++
++/* buf - start of buffer of shorts to swap */
++/* len - byte length of buffer */
++static INLINE void
++bcmswap16_buf(uint16 *buf, uint len)
++{
++ len = len/2;
++
++ while (len--) {
++ *buf = bcmswap16(*buf);
++ buf++;
++ }
++}
++
++#ifndef hton16
++#ifndef IL_BIGENDIAN
++#define HTON16(i) BCMSWAP16(i)
++#define hton16(i) bcmswap16(i)
++#define hton32(i) bcmswap32(i)
++#define ntoh16(i) bcmswap16(i)
++#define ntoh32(i) bcmswap32(i)
++#define ltoh16(i) (i)
++#define ltoh32(i) (i)
++#define htol16(i) (i)
++#define htol32(i) (i)
++#else
++#define HTON16(i) (i)
++#define hton16(i) (i)
++#define hton32(i) (i)
++#define ntoh16(i) (i)
++#define ntoh32(i) (i)
++#define ltoh16(i) bcmswap16(i)
++#define ltoh32(i) bcmswap32(i)
++#define htol16(i) bcmswap16(i)
++#define htol32(i) bcmswap32(i)
++#endif /* IL_BIGENDIAN */
++#endif /* hton16 */
++
++#ifndef IL_BIGENDIAN
++#define ltoh16_buf(buf, i)
++#define htol16_buf(buf, i)
++#else
++#define ltoh16_buf(buf, i) bcmswap16_buf((uint16*)buf, i)
++#define htol16_buf(buf, i) bcmswap16_buf((uint16*)buf, i)
++#endif /* IL_BIGENDIAN */
++
++/*
++* store 16-bit value to unaligned little endian byte array.
++*/
++static INLINE void
++htol16_ua_store(uint16 val, uint8 *bytes)
++{
++ bytes[0] = val&0xff;
++ bytes[1] = val>>8;
++}
++
++/*
++* store 32-bit value to unaligned little endian byte array.
++*/
++static INLINE void
++htol32_ua_store(uint32 val, uint8 *bytes)
++{
++ bytes[0] = val&0xff;
++ bytes[1] = (val>>8)&0xff;
++ bytes[2] = (val>>16)&0xff;
++ bytes[3] = val>>24;
++}
++
++/*
++* store 16-bit value to unaligned network(big) endian byte array.
++*/
++static INLINE void
++hton16_ua_store(uint16 val, uint8 *bytes)
++{
++ bytes[1] = val&0xff;
++ bytes[0] = val>>8;
++}
++
++/*
++* store 32-bit value to unaligned network(big) endian byte array.
++*/
++static INLINE void
++hton32_ua_store(uint32 val, uint8 *bytes)
++{
++ bytes[3] = val&0xff;
++ bytes[2] = (val>>8)&0xff;
++ bytes[1] = (val>>16)&0xff;
++ bytes[0] = val>>24;
++}
++
++/*
++* load 16-bit value from unaligned little endian byte array.
++*/
++static INLINE uint16
++ltoh16_ua(void *bytes)
++{
++ return (((uint8*)bytes)[1]<<8)+((uint8 *)bytes)[0];
++}
++
++/*
++* load 32-bit value from unaligned little endian byte array.
++*/
++static INLINE uint32
++ltoh32_ua(void *bytes)
++{
++ return (((uint8*)bytes)[3]<<24)+(((uint8*)bytes)[2]<<16)+
++ (((uint8*)bytes)[1]<<8)+((uint8*)bytes)[0];
++}
++
++/*
++* load 16-bit value from unaligned big(network) endian byte array.
++*/
++static INLINE uint16
++ntoh16_ua(void *bytes)
++{
++ return (((uint8*)bytes)[0]<<8)+((uint8*)bytes)[1];
++}
++
++/*
++* load 32-bit value from unaligned big(network) endian byte array.
++*/
++static INLINE uint32
++ntoh32_ua(void *bytes)
++{
++ return (((uint8*)bytes)[0]<<24)+(((uint8*)bytes)[1]<<16)+
++ (((uint8*)bytes)[2]<<8)+((uint8*)bytes)[3];
++}
++
++#define ltoh_ua(ptr) (\
++ sizeof(*(ptr)) == sizeof(uint8) ? *(uint8 *)ptr : \
++ sizeof(*(ptr)) == sizeof(uint16) ? (((uint8 *)ptr)[1]<<8)+((uint8 *)ptr)[0] : \
++ (((uint8 *)ptr)[3]<<24)+(((uint8 *)ptr)[2]<<16)+(((uint8 *)ptr)[1]<<8)+((uint8 *)ptr)[0] \
++)
++
++#define ntoh_ua(ptr) (\
++ sizeof(*(ptr)) == sizeof(uint8) ? *(uint8 *)ptr : \
++ sizeof(*(ptr)) == sizeof(uint16) ? (((uint8 *)ptr)[0]<<8)+((uint8 *)ptr)[1] : \
++ (((uint8 *)ptr)[0]<<24)+(((uint8 *)ptr)[1]<<16)+(((uint8 *)ptr)[2]<<8)+((uint8 *)ptr)[3] \
++)
++
++#endif /* _BCMENDIAN_H_ */
+diff -urN linux.old/arch/mips/bcm947xx/include/bcmnvram.h linux.dev/arch/mips/bcm947xx/include/bcmnvram.h
+--- linux.old/arch/mips/bcm947xx/include/bcmnvram.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/bcmnvram.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,159 @@
++/*
++ * NVRAM variable manipulation
++ *
++ * 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.
++ *
++ * $Id: bcmnvram.h,v 1.17 2006/03/02 12:33:44 honor Exp $
++ */
++
++#ifndef _bcmnvram_h_
++#define _bcmnvram_h_
++
++#ifndef _LANGUAGE_ASSEMBLY
++
++#include <typedefs.h>
++#include <bcmdefs.h>
++
++struct nvram_header {
++ uint32 magic;
++ uint32 len;
++ uint32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
++ uint32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
++ uint32 config_ncdl; /* ncdl values for memc */
++};
++
++struct nvram_tuple {
++ char *name;
++ char *value;
++ struct nvram_tuple *next;
++};
++
++/*
++ * Initialize NVRAM access. May be unnecessary or undefined on certain
++ * platforms.
++ */
++extern int nvram_init(void *sbh);
++
++/*
++ * Disable NVRAM access. May be unnecessary or undefined on certain
++ * platforms.
++ */
++extern void nvram_exit(void *sbh);
++
++/*
++ * Get the value of an NVRAM variable. The pointer returned may be
++ * invalid after a set.
++ * @param name name of variable to get
++ * @return value of variable or NULL if undefined
++ */
++extern char * nvram_get(const char *name);
++
++/*
++ * Read the reset GPIO value from the nvram and set the GPIO
++ * as input
++ */
++extern int BCMINITFN(nvram_resetgpio_init)(void *sbh);
++extern int BCMINITFN(nvram_gpio_init)(const char *name, void *sbh);
++extern int BCMINITFN(nvram_gpio_set)(const char *name, void *sbh, int type);
++
++/*
++ * Get the value of an NVRAM variable.
++ * @param name name of variable to get
++ * @return value of variable or NUL if undefined
++ */
++#define nvram_safe_get(name) (nvram_get(name) ? : "")
++
++#define nvram_safe_unset(name) ({ \
++ if(nvram_get(name)) \
++ nvram_unset(name); \
++})
++
++#define nvram_safe_set(name, value) ({ \
++ if(!nvram_get(name) || strcmp(nvram_get(name), value)) \
++ nvram_set(name, value); \
++})
++
++/*
++ * Match an NVRAM variable.
++ * @param name name of variable to match
++ * @param match value to compare against value of variable
++ * @return TRUE if variable is defined and its value is string equal
++ * to match or FALSE otherwise
++ */
++static INLINE int
++nvram_match(char *name, char *match) {
++ const char *value = nvram_get(name);
++ return (value && !strcmp(value, match));
++}
++
++/*
++ * Inversely match an NVRAM variable.
++ * @param name name of variable to match
++ * @param match value to compare against value of variable
++ * @return TRUE if variable is defined and its value is not string
++ * equal to invmatch or FALSE otherwise
++ */
++static INLINE int
++nvram_invmatch(char *name, char *invmatch) {
++ const char *value = nvram_get(name);
++ return (value && strcmp(value, invmatch));
++}
++
++/*
++ * Set the value of an NVRAM variable. The name and value strings are
++ * copied into private storage. Pointers to previously set values
++ * may become invalid. The new value may be immediately
++ * retrieved but will not be permanently stored until a commit.
++ * @param name name of variable to set
++ * @param value value of variable
++ * @return 0 on success and errno on failure
++ */
++extern int nvram_set(const char *name, const char *value);
++
++/*
++ * Unset an NVRAM variable. Pointers to previously set values
++ * remain valid until a set.
++ * @param name name of variable to unset
++ * @return 0 on success and errno on failure
++ * NOTE: use nvram_commit to commit this change to flash.
++ */
++extern int nvram_unset(const char *name);
++
++/*
++ * Commit NVRAM variables to permanent storage. All pointers to values
++ * may be invalid after a commit.
++ * NVRAM values are undefined after a commit.
++ * @return 0 on success and errno on failure
++ */
++extern int nvram_commit(void);
++
++/*
++ * Get all NVRAM variables (format name=value\0 ... \0\0).
++ * @param buf buffer to store variables
++ * @param count size of buffer in bytes
++ * @return 0 on success and errno on failure
++ */
++extern int nvram_getall(char *buf, int count);
++
++extern int file2nvram(char *filename, char *varname);
++extern int nvram2file(char *varname, char *filename);
++
++#endif /* _LANGUAGE_ASSEMBLY */
++
++#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */
++#define NVRAM_CLEAR_MAGIC 0x0
++#define NVRAM_INVALID_MAGIC 0xFFFFFFFF
++#define NVRAM_VERSION 1
++#define NVRAM_HEADER_SIZE 20
++#define NVRAM_SPACE 0x8000
++
++#define NVRAM_MAX_VALUE_LEN 255
++#define NVRAM_MAX_PARAM_LEN 64
++
++#endif /* _bcmnvram_h_ */
+diff -urN linux.old/arch/mips/bcm947xx/include/bcmsrom.h linux.dev/arch/mips/bcm947xx/include/bcmsrom.h
+--- linux.old/arch/mips/bcm947xx/include/bcmsrom.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/bcmsrom.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,108 @@
++/*
++ * Misc useful routines to access NIC local SROM/OTP .
++ *
++ * 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.
++ *
++ * $Id: bcmsrom.h,v 1.1.1.13 2006/04/15 01:29:08 michael Exp $
++ */
++
++#ifndef _bcmsrom_h_
++#define _bcmsrom_h_
++
++/* Maximum srom: 4 Kilobits == 512 bytes */
++#define SROM_MAX 512
++
++/* SROM Rev 4: Reallocate the software part of the srom to accomodate
++ * MIMO features. It assumes up to two PCIE functions and 440 bytes
++ * of useable srom i.e. the useable storage in chips with OTP that
++ * implements hardware redundancy.
++ */
++
++#define SROM4_WORDS 220
++
++#define SROM4_SIGN 32
++#define SROM4_SIGNATURE 0x5372
++
++#define SROM4_BREV 33
++
++#define SROM4_BFL0 34
++#define SROM4_BFL1 35
++#define SROM4_BFL2 36
++#define SROM4_BFL3 37
++
++#define SROM4_MACHI 38
++#define SROM4_MACMID 39
++#define SROM4_MACLO 40
++
++#define SROM4_CCODE 41
++#define SROM4_REGREV 42
++
++#define SROM4_LEDBH10 43
++#define SROM4_LEDBH32 44
++
++#define SROM4_LEDDC 45
++
++#define SROM4_AA 46
++#define SROM4_AA2G_MASK 0x00ff
++#define SROM4_AA2G_SHIFT 0
++#define SROM4_AA5G_MASK 0xff00
++#define SROM4_AA5G_SHIFT 8
++
++#define SROM4_AG10 47
++#define SROM4_AG32 48
++
++#define SROM4_TXPID2G 49
++#define SROM4_TXPID5G 51
++#define SROM4_TXPID5GL 53
++#define SROM4_TXPID5GH 55
++
++/* Per-path fields */
++#define MAX_PATH 4
++#define SROM4_PATH0 64
++#define SROM4_PATH1 87
++#define SROM4_PATH2 110
++#define SROM4_PATH3 133
++
++#define SROM4_2G_ITT_MAXP 0
++#define SROM4_2G_PA 1
++#define SROM4_5G_ITT_MAXP 5
++#define SROM4_5GLH_MAXP 6
++#define SROM4_5G_PA 7
++#define SROM4_5GL_PA 11
++#define SROM4_5GH_PA 15
++
++/* Fields in the ITT_MAXP and 5GLH_MAXP words */
++#define B2G_MAXP_MASK 0xff
++#define B2G_ITT_SHIFT 8
++#define B5G_MAXP_MASK 0xff
++#define B5G_ITT_SHIFT 8
++#define B5GH_MAXP_MASK 0xff
++#define B5GL_MAXP_SHIFT 8
++
++/* All the miriad power offsets */
++#define SROM4_2G_CCKPO 156
++#define SROM4_2G_OFDMPO 157
++#define SROM4_5G_OFDMPO 159
++#define SROM4_5GL_OFDMPO 161
++#define SROM4_5GH_OFDMPO 163
++#define SROM4_2G_MCSPO 165
++#define SROM4_5G_MCSPO 173
++#define SROM4_5GL_MCSPO 181
++#define SROM4_5GH_MCSPO 189
++#define SROM4_CCDPO 197
++#define SROM4_STBCPO 198
++#define SROM4_BW40PO 199
++#define SROM4_BWDUPPO 200
++
++extern int srom_var_init(void *sbh, uint bus, void *curmap, osl_t *osh, char **vars, uint *count);
++
++extern int srom_read(uint bus, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf);
++extern int srom_write(uint bus, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf);
++
++#endif /* _bcmsrom_h_ */
+diff -urN linux.old/arch/mips/bcm947xx/include/bcmutils.h linux.dev/arch/mips/bcm947xx/include/bcmutils.h
+--- linux.old/arch/mips/bcm947xx/include/bcmutils.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/bcmutils.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,433 @@
++/*
++ * Misc useful os-independent macros and functions.
++ *
++ * 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.
++ * $Id: bcmutils.h,v 1.1.1.16 2006/04/08 06:13:39 honor Exp $
++ */
++
++#ifndef _bcmutils_h_
++#define _bcmutils_h_
++
++/* ** driver-only section ** */
++#ifdef BCMDRIVER
++
++#define _BCM_U 0x01 /* upper */
++#define _BCM_L 0x02 /* lower */
++#define _BCM_D 0x04 /* digit */
++#define _BCM_C 0x08 /* cntrl */
++#define _BCM_P 0x10 /* punct */
++#define _BCM_S 0x20 /* white space (space/lf/tab) */
++#define _BCM_X 0x40 /* hex digit */
++#define _BCM_SP 0x80 /* hard space (0x20) */
++
++#define GPIO_PIN_NOTDEFINED 0x20 /* Pin not defined */
++
++extern unsigned char bcm_ctype[];
++#define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)])
++
++#define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0)
++#define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0)
++#define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0)
++#define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0)
++#define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0)
++#define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0)
++#define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0)
++#define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0)
++#define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0)
++#define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0)
++#define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0)
++
++/*
++ * Spin at most 'us' microseconds while 'exp' is true.
++ * Caller should explicitly test 'exp' when this completes
++ * and take appropriate error action if 'exp' is still true.
++ */
++#define SPINWAIT(exp, us) { \
++ uint countdown = (us) + 9; \
++ while ((exp) && (countdown >= 10)) {\
++ OSL_DELAY(10); \
++ countdown -= 10; \
++ } \
++}
++
++struct ether_addr {
++ uint8 octet[6];
++} __attribute__((packed));
++
++/* string */
++extern uchar bcm_toupper(uchar c);
++extern ulong bcm_strtoul(char *cp, char **endp, uint base);
++extern char *bcmstrstr(char *haystack, char *needle);
++extern char *bcmstrcat(char *dest, const char *src);
++extern ulong wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen);
++/* ethernet address */
++extern char *bcm_ether_ntoa(struct ether_addr *ea, char *buf);
++/* variable access */
++extern char *getvar(char *vars, char *name);
++extern int getintvar(char *vars, char *name);
++extern uint getgpiopin(char *vars, char *pin_name, uint def_pin);
++#ifdef BCMPERFSTATS
++extern void bcm_perf_enable(void);
++extern void bcmstats(char *fmt);
++extern void bcmlog(char *fmt, uint a1, uint a2);
++extern void bcmdumplog(char *buf, int size);
++extern int bcmdumplogent(char *buf, uint idx);
++#else
++#define bcm_perf_enable()
++#define bcmstats(fmt)
++#define bcmlog(fmt, a1, a2)
++#define bcmdumplog(buf, size) *buf = '\0'
++#define bcmdumplogent(buf, idx) -1
++#endif /* BCMPERFSTATS */
++extern char *bcm_nvram_vars(uint *length);
++extern int bcm_nvram_cache(void *sbh);
++
++/* Support for sharing code across in-driver iovar implementations.
++ * The intent is that a driver use this structure to map iovar names
++ * to its (private) iovar identifiers, and the lookup function to
++ * find the entry. Macros are provided to map ids and get/set actions
++ * into a single number space for a switch statement.
++ */
++
++/* iovar structure */
++typedef struct bcm_iovar {
++ const char *name; /* name for lookup and display */
++ uint16 varid; /* id for switch */
++ uint16 flags; /* driver-specific flag bits */
++ uint16 type; /* base type of argument */
++ uint16 minlen; /* min length for buffer vars */
++} bcm_iovar_t;
++
++/* varid definitions are per-driver, may use these get/set bits */
++
++/* IOVar action bits for id mapping */
++#define IOV_GET 0 /* Get an iovar */
++#define IOV_SET 1 /* Set an iovar */
++
++/* Varid to actionid mapping */
++#define IOV_GVAL(id) ((id)*2)
++#define IOV_SVAL(id) (((id)*2)+IOV_SET)
++#define IOV_ISSET(actionid) ((actionid & IOV_SET) == IOV_SET)
++
++/* flags are per-driver based on driver attributes */
++
++/* Base type definitions */
++#define IOVT_VOID 0 /* no value (implictly set only) */
++#define IOVT_BOOL 1 /* any value ok (zero/nonzero) */
++#define IOVT_INT8 2 /* integer values are range-checked */
++#define IOVT_UINT8 3 /* unsigned int 8 bits */
++#define IOVT_INT16 4 /* int 16 bits */
++#define IOVT_UINT16 5 /* unsigned int 16 bits */
++#define IOVT_INT32 6 /* int 32 bits */
++#define IOVT_UINT32 7 /* unsigned int 32 bits */
++#define IOVT_BUFFER 8 /* buffer is size-checked as per minlen */
++
++extern const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name);
++extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg, int len, bool set);
++
++#endif /* #ifdef BCMDRIVER */
++
++/* ** driver/apps-shared section ** */
++
++#define BCME_STRLEN 64 /* Max string length for BCM errors */
++#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST))
++
++
++/*
++ * error codes could be added but the defined ones shouldn't be changed/deleted
++ * these error codes are exposed to the user code
++ * when ever a new error code is added to this list
++ * please update errorstring table with the related error string and
++ * update osl files with os specific errorcode map
++*/
++
++#define BCME_OK 0 /* Success */
++#define BCME_ERROR -1 /* Error generic */
++#define BCME_BADARG -2 /* Bad Argument */
++#define BCME_BADOPTION -3 /* Bad option */
++#define BCME_NOTUP -4 /* Not up */
++#define BCME_NOTDOWN -5 /* Not down */
++#define BCME_NOTAP -6 /* Not AP */
++#define BCME_NOTSTA -7 /* Not STA */
++#define BCME_BADKEYIDX -8 /* BAD Key Index */
++#define BCME_RADIOOFF -9 /* Radio Off */
++#define BCME_NOTBANDLOCKED -10 /* Not band locked */
++#define BCME_NOCLK -11 /* No Clock */
++#define BCME_BADRATESET -12 /* BAD Rate valueset */
++#define BCME_BADBAND -13 /* BAD Band */
++#define BCME_BUFTOOSHORT -14 /* Buffer too short */
++#define BCME_BUFTOOLONG -15 /* Buffer too long */
++#define BCME_BUSY -16 /* Busy */
++#define BCME_NOTASSOCIATED -17 /* Not Associated */
++#define BCME_BADSSIDLEN -18 /* Bad SSID len */
++#define BCME_OUTOFRANGECHAN -19 /* Out of Range Channel */
++#define BCME_BADCHAN -20 /* Bad Channel */
++#define BCME_BADADDR -21 /* Bad Address */
++#define BCME_NORESOURCE -22 /* Not Enough Resources */
++#define BCME_UNSUPPORTED -23 /* Unsupported */
++#define BCME_BADLEN -24 /* Bad length */
++#define BCME_NOTREADY -25 /* Not Ready */
++#define BCME_EPERM -26 /* Not Permitted */
++#define BCME_NOMEM -27 /* No Memory */
++#define BCME_ASSOCIATED -28 /* Associated */
++#define BCME_RANGE -29 /* Not In Range */
++#define BCME_NOTFOUND -30 /* Not Found */
++#define BCME_WME_NOT_ENABLED -31 /* WME Not Enabled */
++#define BCME_TSPEC_NOTFOUND -32 /* TSPEC Not Found */
++#define BCME_ACM_NOTSUPPORTED -33 /* ACM Not Supported */
++#define BCME_NOT_WME_ASSOCIATION -34 /* Not WME Association */
++#define BCME_SDIO_ERROR -35 /* SDIO Bus Error */
++#define BCME_DONGLE_DOWN -36 /* Dongle Not Accessible */
++#define BCME_LAST BCME_DONGLE_DOWN
++
++/* These are collection of BCME Error strings */
++#define BCMERRSTRINGTABLE { \
++ "OK", \
++ "Undefined error", \
++ "Bad Argument", \
++ "Bad Option", \
++ "Not up", \
++ "Not down", \
++ "Not AP", \
++ "Not STA", \
++ "Bad Key Index", \
++ "Radio Off", \
++ "Not band locked", \
++ "No clock", \
++ "Bad Rate valueset", \
++ "Bad Band", \
++ "Buffer too short", \
++ "Buffer too long", \
++ "Busy", \
++ "Not Associated", \
++ "Bad SSID len", \
++ "Out of Range Channel", \
++ "Bad Channel", \
++ "Bad Address", \
++ "Not Enough Resources", \
++ "Unsupported", \
++ "Bad length", \
++ "Not Ready", \
++ "Not Permitted", \
++ "No Memory", \
++ "Associated", \
++ "Not In Range", \
++ "Not Found", \
++ "WME Not Enabled", \
++ "TSPEC Not Found", \
++ "ACM Not Supported", \
++ "Not WME Association", \
++ "SDIO Bus Error", \
++ "Dongle Not Accessible" \
++}
++
++#ifndef ABS
++#define ABS(a) (((a) < 0)?-(a):(a))
++#endif /* ABS */
++
++#ifndef MIN
++#define MIN(a, b) (((a) < (b))?(a):(b))
++#endif /* MIN */
++
++#ifndef MAX
++#define MAX(a, b) (((a) > (b))?(a):(b))
++#endif /* MAX */
++
++#define CEIL(x, y) (((x) + ((y)-1)) / (y))
++#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
++#define ISALIGNED(a, x) (((a) & ((x)-1)) == 0)
++#define ISPOWEROF2(x) ((((x)-1)&(x)) == 0)
++#define VALID_MASK(mask) !((mask) & ((mask) + 1))
++#define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member)
++#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
++
++/* bit map related macros */
++#ifndef setbit
++#ifndef NBBY /* the BSD family defines NBBY */
++#define NBBY 8 /* 8 bits per byte */
++#endif /* #ifndef NBBY */
++#define setbit(a, i) (((uint8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY))
++#define clrbit(a, i) (((uint8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
++#define isset(a, i) (((uint8 *)a)[(i)/NBBY] & (1<<((i)%NBBY)))
++#define isclr(a, i) ((((uint8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
++#endif /* setbit */
++
++#define NBITS(type) (sizeof(type) * 8)
++#define NBITVAL(nbits) (1 << (nbits))
++#define MAXBITVAL(nbits) ((1 << (nbits)) - 1)
++#define NBITMASK(nbits) MAXBITVAL(nbits)
++#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8)
++
++/* basic mux operation - can be optimized on several architectures */
++#define MUX(pred, true, false) ((pred) ? (true) : (false))
++
++/* modulo inc/dec - assumes x E [0, bound - 1] */
++#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1)
++#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1)
++
++/* modulo inc/dec, bound = 2^k */
++#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1))
++#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1))
++
++/* modulo add/sub - assumes x, y E [0, bound - 1] */
++#define MODADD(x, y, bound) \
++ MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y))
++#define MODSUB(x, y, bound) \
++ MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y))
++
++/* module add/sub, bound = 2^k */
++#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1))
++#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1))
++
++/* crc defines */
++#define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */
++#define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */
++#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */
++#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */
++#define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */
++#define CRC32_GOOD_VALUE 0xdebb20e3 /* Good final CRC32 checksum value */
++
++/* bcm_format_flags() bit description structure */
++typedef struct bcm_bit_desc {
++ uint32 bit;
++ char* name;
++} bcm_bit_desc_t;
++
++/* tag_ID/length/value_buffer tuple */
++typedef struct bcm_tlv {
++ uint8 id;
++ uint8 len;
++ uint8 data[1];
++} bcm_tlv_t;
++
++/* Check that bcm_tlv_t fits into the given buflen */
++#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (int)(buflen) >= (int)(2 + (elt)->len))
++
++/* buffer length for ethernet address from bcm_ether_ntoa() */
++#define ETHER_ADDR_STR_LEN 18 /* 18-bytes of Ethernet address buffer length */
++
++/* unaligned load and store macros */
++#ifdef IL_BIGENDIAN
++static INLINE uint32
++load32_ua(uint8 *a)
++{
++ return ((a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]);
++}
++
++static INLINE void
++store32_ua(uint8 *a, uint32 v)
++{
++ a[0] = (v >> 24) & 0xff;
++ a[1] = (v >> 16) & 0xff;
++ a[2] = (v >> 8) & 0xff;
++ a[3] = v & 0xff;
++}
++
++static INLINE uint16
++load16_ua(uint8 *a)
++{
++ return ((a[0] << 8) | a[1]);
++}
++
++static INLINE void
++store16_ua(uint8 *a, uint16 v)
++{
++ a[0] = (v >> 8) & 0xff;
++ a[1] = v & 0xff;
++}
++
++#else
++
++static INLINE uint32
++load32_ua(uint8 *a)
++{
++ return ((a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0]);
++}
++
++static INLINE void
++store32_ua(uint8 *a, uint32 v)
++{
++ a[3] = (v >> 24) & 0xff;
++ a[2] = (v >> 16) & 0xff;
++ a[1] = (v >> 8) & 0xff;
++ a[0] = v & 0xff;
++}
++
++static INLINE uint16
++load16_ua(uint8 *a)
++{
++ return ((a[1] << 8) | a[0]);
++}
++
++static INLINE void
++store16_ua(uint8 *a, uint16 v)
++{
++ a[1] = (v >> 8) & 0xff;
++ a[0] = v & 0xff;
++}
++
++#endif /* IL_BIGENDIAN */
++
++/* externs */
++/* crc */
++extern uint8 hndcrc8(uint8 *p, uint nbytes, uint8 crc);
++extern uint16 hndcrc16(uint8 *p, uint nbytes, uint16 crc);
++extern uint32 hndcrc32(uint8 *p, uint nbytes, uint32 crc);
++/* format/print */
++extern void printfbig(char *buf);
++
++/* IE parsing */
++extern bcm_tlv_t *bcm_next_tlv(bcm_tlv_t *elt, int *buflen);
++extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key);
++extern bcm_tlv_t *bcm_parse_ordered_tlvs(void *buf, int buflen, uint key);
++
++/* bcmerror */
++extern const char *bcmerrorstr(int bcmerror);
++
++/* multi-bool data type: set of bools, mbool is true if any is set */
++typedef uint32 mbool;
++#define mboolset(mb, bit) (mb |= bit) /* set one bool */
++#define mboolclr(mb, bit) (mb &= ~bit) /* clear one bool */
++#define mboolisset(mb, bit) ((mb & bit) != 0) /* TRUE if one bool is set */
++#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val)))
++
++/* power conversion */
++extern uint16 bcm_qdbm_to_mw(uint8 qdbm);
++extern uint8 bcm_mw_to_qdbm(uint16 mw);
++
++/* generic datastruct to help dump routines */
++struct fielddesc {
++ char *nameandfmt;
++ uint32 offset;
++ uint32 len;
++};
++
++/* Buffer structure for collecting string-formatted data
++* using bcm_bprintf() API.
++* Use bcm_binit() to initialize before use
++*/
++struct bcmstrbuf
++{
++ char *buf; /* pointer to current position in origbuf */
++ uint size; /* current (residual) size in bytes */
++ char *origbuf; /* unmodified pointer to orignal buffer */
++ uint origsize; /* unmodified orignal buffer size in bytes */
++};
++
++extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size);
++extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...);
++
++typedef uint32 (*readreg_rtn)(void *arg0, void *arg1, uint32 offset);
++extern uint bcmdumpfields(readreg_rtn func_ptr, void *arg0, void *arg1, struct fielddesc *str,
++ char *buf, uint32 bufsize);
++
++extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len);
++extern uint bcm_bitcount(uint8 *bitmap, uint bytelength);
++
++#endif /* _bcmutils_h_ */
+diff -urN linux.old/arch/mips/bcm947xx/include/hndcpu.h linux.dev/arch/mips/bcm947xx/include/hndcpu.h
+--- linux.old/arch/mips/bcm947xx/include/hndcpu.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/hndcpu.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,28 @@
++/*
++ * HND SiliconBackplane MIPS/ARM cores software interface.
++ *
++ * 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.
++ *
++ * $Id: hndcpu.h,v 1.1.1.1 2006/02/27 03:43:16 honor Exp $
++ */
++
++#ifndef _hndcpu_h_
++#define _hndcpu_h_
++
++#if defined(mips)
++#include <hndmips.h>
++#elif defined(__ARM_ARCH_4T__)
++#include <hndarm.h>
++#endif
++
++extern uint sb_irq(sb_t *sbh);
++extern uint32 sb_cpu_clock(sb_t *sbh);
++extern void sb_cpu_wait(void);
++
++#endif /* _hndcpu_h_ */
+diff -urN linux.old/arch/mips/bcm947xx/include/hndmips.h linux.dev/arch/mips/bcm947xx/include/hndmips.h
+--- linux.old/arch/mips/bcm947xx/include/hndmips.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/hndmips.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,45 @@
++/*
++ * HND SiliconBackplane MIPS core software interface.
++ *
++ * 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.
++ *
++ * $Id: hndmips.h,v 1.1.1.8 2006/02/27 03:43:16 honor Exp $
++ */
++
++#ifndef _hndmips_h_
++#define _hndmips_h_
++
++extern void sb_mips_init(sb_t *sbh, uint shirq_map_base);
++extern bool sb_mips_setclock(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 pciclock);
++extern void enable_pfc(uint32 mode);
++extern uint32 sb_memc_get_ncdl(sb_t *sbh);
++
++#if defined(BCMPERFSTATS)
++/* enable counting - exclusive version. Only one set of counters allowed at a time */
++extern void hndmips_perf_instrcount_enable(void);
++extern void hndmips_perf_icachecount_enable(void);
++extern void hndmips_perf_dcachecount_enable(void);
++/* start and stop counting */
++#define hndmips_perf_start01() \
++ MTC0(C0_PERFORMANCE, 4, MFC0(C0_PERFORMANCE, 4) | 0x80008000)
++#define hndmips_perf_stop01() \
++ MTC0(C0_PERFORMANCE, 4, MFC0(C0_PERFORMANCE, 4) & ~0x80008000)
++/* retrieve coutners - counters *decrement* */
++#define hndmips_perf_read0() -(long)(MFC0(C0_PERFORMANCE, 0))
++#define hndmips_perf_read1() -(long)(MFC0(C0_PERFORMANCE, 1))
++#define hndmips_perf_read2() -(long)(MFC0(C0_PERFORMANCE, 2))
++/* enable counting - modular version. Each counters can be enabled separately. */
++extern void hndmips_perf_icache_hit_enable(void);
++extern void hndmips_perf_icache_miss_enable(void);
++extern uint32 hndmips_perf_read_instrcount(void);
++extern uint32 hndmips_perf_read_cache_miss(void);
++extern uint32 hndmips_perf_read_cache_hit(void);
++#endif /* defined(BCMINTERNAL) || defined (BCMPERFSTATS) */
++
++#endif /* _hndmips_h_ */
+diff -urN linux.old/arch/mips/bcm947xx/include/hndpci.h linux.dev/arch/mips/bcm947xx/include/hndpci.h
+--- linux.old/arch/mips/bcm947xx/include/hndpci.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/hndpci.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,30 @@
++/*
++ * HND SiliconBackplane PCI core software interface.
++ *
++ * $Id: hndpci.h,v 1.1.1.1 2006/02/27 03:43:16 honor Exp $
++ * 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 _hndpci_h_
++#define _hndpci_h_
++
++extern int sbpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf,
++ int len);
++extern int extpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf,
++ int len);
++extern int sbpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf,
++ int len);
++extern int extpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf,
++ int len);
++extern void sbpci_ban(uint16 core);
++extern int sbpci_init(sb_t *sbh);
++extern int sbpci_init_pci(sb_t *sbh);
++extern void sbpci_check(sb_t *sbh);
++
++#endif /* _hndpci_h_ */
+diff -urN linux.old/arch/mips/bcm947xx/include/linuxver.h linux.dev/arch/mips/bcm947xx/include/linuxver.h
+--- linux.old/arch/mips/bcm947xx/include/linuxver.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/linuxver.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,417 @@
++/*
++ * Linux-specific abstractions to gain some independence from linux kernel versions.
++ * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences.
++ *
++ * 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.
++ *
++ * $Id: linuxver.h,v 1.1.1.10 2006/02/27 03:43:16 honor Exp $
++ */
++
++#ifndef _linuxver_h_
++#define _linuxver_h_
++
++#include <linux/config.h>
++#include <linux/version.h>
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0))
++/* __NO_VERSION__ must be defined for all linkables except one in 2.2 */
++#ifdef __UNDEF_NO_VERSION__
++#undef __NO_VERSION__
++#else
++#define __NO_VERSION__
++#endif
++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0) */
++
++#if defined(MODULE) && defined(MODVERSIONS)
++#include <linux/modversions.h>
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
++#include <linux/moduleparam.h>
++#endif
++
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
++#define module_param(_name_, _type_, _perm_) MODULE_PARM(_name_, "i")
++#define module_param_string(_name_, _string_, _size_, _perm_) \
++ MODULE_PARM(_string_, "c" __MODULE_STRING(_size_))
++#endif
++
++/* linux/malloc.h is deprecated, use linux/slab.h instead. */
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 9))
++#include <linux/malloc.h>
++#else
++#include <linux/slab.h>
++#endif
++
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/string.h>
++#include <linux/pci.h>
++#include <linux/interrupt.h>
++#include <linux/netdevice.h>
++#include <asm/io.h>
++
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41))
++#include <linux/workqueue.h>
++#else
++#include <linux/tqueue.h>
++#ifndef work_struct
++#define work_struct tq_struct
++#endif
++#ifndef INIT_WORK
++#define INIT_WORK(_work, _func, _data) INIT_TQUEUE((_work), (_func), (_data))
++#endif
++#ifndef schedule_work
++#define schedule_work(_work) schedule_task((_work))
++#endif
++#ifndef flush_scheduled_work
++#define flush_scheduled_work() flush_scheduled_tasks()
++#endif
++#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41) */
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
++/* Some distributions have their own 2.6.x compatibility layers */
++#ifndef IRQ_NONE
++typedef void irqreturn_t;
++#define IRQ_NONE
++#define IRQ_HANDLED
++#define IRQ_RETVAL(x)
++#endif
++#else
++typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs);
++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */
++
++#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
++
++#include <pcmcia/version.h>
++#include <pcmcia/cs_types.h>
++#include <pcmcia/cs.h>
++#include <pcmcia/cistpl.h>
++#include <pcmcia/cisreg.h>
++#include <pcmcia/ds.h>
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 69))
++/* In 2.5 (as of 2.5.69 at least) there is a cs_error exported which
++ * does this, but it's not in 2.4 so we do our own for now.
++ */
++static inline void
++cs_error(client_handle_t handle, int func, int ret)
++{
++ error_info_t err = { func, ret };
++ CardServices(ReportError, handle, &err);
++}
++#endif
++
++#endif /* CONFIG_PCMCIA */
++
++#ifndef __exit
++#define __exit
++#endif
++#ifndef __devexit
++#define __devexit
++#endif
++#ifndef __devinit
++#define __devinit __init
++#endif
++#ifndef __devinitdata
++#define __devinitdata
++#endif
++#ifndef __devexit_p
++#define __devexit_p(x) x
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0))
++
++#define pci_get_drvdata(dev) (dev)->sysdata
++#define pci_set_drvdata(dev, value) (dev)->sysdata = (value)
++
++/*
++ * New-style (2.4.x) PCI/hot-pluggable PCI/CardBus registration
++ */
++
++struct pci_device_id {
++ unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */
++ unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
++ unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */
++ unsigned long driver_data; /* Data private to the driver */
++};
++
++struct pci_driver {
++ struct list_head node;
++ char *name;
++ const struct pci_device_id *id_table; /* NULL if wants all devices */
++ int (*probe)(struct pci_dev *dev,
++ const struct pci_device_id *id); /* New device inserted */
++ void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug
++ * capable driver)
++ */
++ void (*suspend)(struct pci_dev *dev); /* Device suspended */
++ void (*resume)(struct pci_dev *dev); /* Device woken up */
++};
++
++#define MODULE_DEVICE_TABLE(type, name)
++#define PCI_ANY_ID (~0)
++
++/* compatpci.c */
++#define pci_module_init pci_register_driver
++extern int pci_register_driver(struct pci_driver *drv);
++extern void pci_unregister_driver(struct pci_driver *drv);
++
++#endif /* PCI registration */
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18))
++#ifdef MODULE
++#define module_init(x) int init_module(void) { return x(); }
++#define module_exit(x) void cleanup_module(void) { x(); }
++#else
++#define module_init(x) __initcall(x);
++#define module_exit(x) __exitcall(x);
++#endif
++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) */
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 48))
++#define list_for_each(pos, head) \
++ for (pos = (head)->next; pos != (head); pos = pos->next)
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 13))
++#define pci_resource_start(dev, bar) ((dev)->base_address[(bar)])
++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 44))
++#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start)
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 23))
++#define pci_enable_device(dev) do { } while (0)
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 14))
++#define net_device device
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 42))
++
++/*
++ * DMA mapping
++ *
++ * See linux/Documentation/DMA-mapping.txt
++ */
++
++#ifndef PCI_DMA_TODEVICE
++#define PCI_DMA_TODEVICE 1
++#define PCI_DMA_FROMDEVICE 2
++#endif
++
++typedef u32 dma_addr_t;
++
++/* Pure 2^n version of get_order */
++static inline int get_order(unsigned long size)
++{
++ int order;
++
++ size = (size-1) >> (PAGE_SHIFT-1);
++ order = -1;
++ do {
++ size >>= 1;
++ order++;
++ } while (size);
++ return order;
++}
++
++static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
++ dma_addr_t *dma_handle)
++{
++ void *ret;
++ int gfp = GFP_ATOMIC | GFP_DMA;
++
++ ret = (void *)__get_free_pages(gfp, get_order(size));
++
++ if (ret != NULL) {
++ memset(ret, 0, size);
++ *dma_handle = virt_to_bus(ret);
++ }
++ return ret;
++}
++static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size,
++ void *vaddr, dma_addr_t dma_handle)
++{
++ free_pages((unsigned long)vaddr, get_order(size));
++}
++#ifdef ILSIM
++extern uint pci_map_single(void *dev, void *va, uint size, int direction);
++extern void pci_unmap_single(void *dev, uint pa, uint size, int direction);
++#else
++#define pci_map_single(cookie, address, size, dir) virt_to_bus(address)
++#define pci_unmap_single(cookie, address, size, dir)
++#endif
++
++#endif /* DMA mapping */
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 43))
++
++#define dev_kfree_skb_any(a) dev_kfree_skb(a)
++#define netif_down(dev) do { (dev)->start = 0; } while (0)
++
++/* pcmcia-cs provides its own netdevice compatibility layer */
++#ifndef _COMPAT_NETDEVICE_H
++
++/*
++ * SoftNet
++ *
++ * For pre-softnet kernels we need to tell the upper layer not to
++ * re-enter start_xmit() while we are in there. However softnet
++ * guarantees not to enter while we are in there so there is no need
++ * to do the netif_stop_queue() dance unless the transmit queue really
++ * gets stuck. This should also improve performance according to tests
++ * done by Aman Singla.
++ */
++
++#define dev_kfree_skb_irq(a) dev_kfree_skb(a)
++#define netif_wake_queue(dev) \
++ do { clear_bit(0, &(dev)->tbusy); mark_bh(NET_BH); } while (0)
++#define netif_stop_queue(dev) set_bit(0, &(dev)->tbusy)
++
++static inline void netif_start_queue(struct net_device *dev)
++{
++ dev->tbusy = 0;
++ dev->interrupt = 0;
++ dev->start = 1;
++}
++
++#define netif_queue_stopped(dev) (dev)->tbusy
++#define netif_running(dev) (dev)->start
++
++#endif /* _COMPAT_NETDEVICE_H */
++
++#define netif_device_attach(dev) netif_start_queue(dev)
++#define netif_device_detach(dev) netif_stop_queue(dev)
++
++/* 2.4.x renamed bottom halves to tasklets */
++#define tasklet_struct tq_struct
++static inline void tasklet_schedule(struct tasklet_struct *tasklet)
++{
++ queue_task(tasklet, &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++}
++
++static inline void tasklet_init(struct tasklet_struct *tasklet,
++ void (*func)(unsigned long),
++ unsigned long data)
++{
++ tasklet->next = NULL;
++ tasklet->sync = 0;
++ tasklet->routine = (void (*)(void *))func;
++ tasklet->data = (void *)data;
++}
++#define tasklet_kill(tasklet) { do{} while (0); }
++
++/* 2.4.x introduced del_timer_sync() */
++#define del_timer_sync(timer) del_timer(timer)
++
++#else
++
++#define netif_down(dev)
++
++#endif /* SoftNet */
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3))
++
++/*
++ * Emit code to initialise a tq_struct's routine and data pointers
++ */
++#define PREPARE_TQUEUE(_tq, _routine, _data) \
++ do { \
++ (_tq)->routine = _routine; \
++ (_tq)->data = _data; \
++ } while (0)
++
++/*
++ * Emit code to initialise all of a tq_struct
++ */
++#define INIT_TQUEUE(_tq, _routine, _data) \
++ do { \
++ INIT_LIST_HEAD(&(_tq)->list); \
++ (_tq)->sync = 0; \
++ PREPARE_TQUEUE((_tq), (_routine), (_data)); \
++ } while (0)
++
++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3) */
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 6))
++
++/* Power management related routines */
++
++static inline int
++pci_save_state(struct pci_dev *dev, u32 *buffer)
++{
++ int i;
++ if (buffer) {
++ for (i = 0; i < 16; i++)
++ pci_read_config_dword(dev, i * 4, &buffer[i]);
++ }
++ return 0;
++}
++
++static inline int
++pci_restore_state(struct pci_dev *dev, u32 *buffer)
++{
++ int i;
++
++ if (buffer) {
++ for (i = 0; i < 16; i++)
++ pci_write_config_dword(dev, i * 4, buffer[i]);
++ }
++ /*
++ * otherwise, write the context information we know from bootup.
++ * This works around a problem where warm-booting from Windows
++ * combined with a D3(hot)->D0 transition causes PCI config
++ * header data to be forgotten.
++ */
++ else {
++ for (i = 0; i < 6; i ++)
++ pci_write_config_dword(dev,
++ PCI_BASE_ADDRESS_0 + (i * 4),
++ pci_resource_start(dev, i));
++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
++ }
++ return 0;
++}
++
++#endif /* PCI power management */
++
++/* Old cp0 access macros deprecated in 2.4.19 */
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 19))
++#define read_c0_count() read_32bit_cp0_register(CP0_COUNT)
++#endif
++
++/* Module refcount handled internally in 2.6.x */
++#ifndef SET_MODULE_OWNER
++#define SET_MODULE_OWNER(dev) do {} while (0)
++#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT
++#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT
++#else
++#define OLD_MOD_INC_USE_COUNT do {} while (0)
++#define OLD_MOD_DEC_USE_COUNT do {} while (0)
++#endif
++
++#ifndef SET_NETDEV_DEV
++#define SET_NETDEV_DEV(net, pdev) do {} while (0)
++#endif
++
++#ifndef HAVE_FREE_NETDEV
++#define free_netdev(dev) kfree(dev)
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
++/* struct packet_type redefined in 2.6.x */
++#define af_packet_priv data
++#endif
++
++#endif /* _linuxver_h_ */
+diff -urN linux.old/arch/mips/bcm947xx/include/mipsinc.h linux.dev/arch/mips/bcm947xx/include/mipsinc.h
+--- linux.old/arch/mips/bcm947xx/include/mipsinc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/mipsinc.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,541 @@
++/*
++ * HND Run Time Environment for standalone MIPS programs.
++ *
++ * 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.
++ *
++ * $Id: mipsinc.h,v 1.1.1.5 2006/02/27 03:43:16 honor Exp $
++ */
++
++#ifndef _MISPINC_H
++#define _MISPINC_H
++
++
++/* MIPS defines */
++
++#ifdef _LANGUAGE_ASSEMBLY
++
++/*
++ * 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 */
++
++
++/* CP0 Registers */
++
++#define C0_INX $0
++#define C0_RAND $1
++#define C0_TLBLO0 $2
++#define C0_TLBLO C0_TLBLO0
++#define C0_TLBLO1 $3
++#define C0_CTEXT $4
++#define C0_PGMASK $5
++#define C0_WIRED $6
++#define C0_BADVADDR $8
++#define C0_COUNT $9
++#define C0_TLBHI $10
++#define C0_COMPARE $11
++#define C0_SR $12
++#define C0_STATUS C0_SR
++#define C0_CAUSE $13
++#define C0_EPC $14
++#define C0_PRID $15
++#define C0_CONFIG $16
++#define C0_LLADDR $17
++#define C0_WATCHLO $18
++#define C0_WATCHHI $19
++#define C0_XCTEXT $20
++#define C0_DIAGNOSTIC $22
++#define C0_BROADCOM C0_DIAGNOSTIC
++#define C0_PERFORMANCE $25
++#define C0_ECC $26
++#define C0_CACHEERR $27
++#define C0_TAGLO $28
++#define C0_TAGHI $29
++#define C0_ERREPC $30
++#define C0_DESAVE $31
++
++/*
++ * LEAF - declare leaf routine
++ */
++#define LEAF(symbol) \
++ .globl symbol; \
++ .align 2; \
++ .type symbol, @function; \
++ .ent symbol, 0; \
++symbol: .frame sp, 0, ra
++
++/*
++ * END - mark end of function
++ */
++#define END(function) \
++ .end function; \
++ .size function, . - function
++
++#define _ULCAST_
++
++#define MFC0_SEL(dst, src, sel) \
++ .word\t(0x40000000 | ((dst) << 16) | ((src) << 11) | (sel))
++
++
++#define MTC0_SEL(dst, src, sel) \
++ .word\t(0x40800000 | ((dst) << 16) | ((src) << 11) | (sel))
++
++#else
++
++/*
++ * The following macros are especially useful for __asm__
++ * inline assembler.
++ */
++#ifndef __STR
++#define __STR(x) #x
++#endif
++#ifndef STR
++#define STR(x) __STR(x)
++#endif
++
++#define _ULCAST_ (unsigned long)
++
++
++/* CP0 Registers */
++
++#define C0_INX 0 /* CP0: TLB Index */
++#define C0_RAND 1 /* CP0: TLB Random */
++#define C0_TLBLO0 2 /* CP0: TLB EntryLo0 */
++#define C0_TLBLO C0_TLBLO0 /* CP0: TLB EntryLo0 */
++#define C0_TLBLO1 3 /* CP0: TLB EntryLo1 */
++#define C0_CTEXT 4 /* CP0: Context */
++#define C0_PGMASK 5 /* CP0: TLB PageMask */
++#define C0_WIRED 6 /* CP0: TLB Wired */
++#define C0_BADVADDR 8 /* CP0: Bad Virtual Address */
++#define C0_COUNT 9 /* CP0: Count */
++#define C0_TLBHI 10 /* CP0: TLB EntryHi */
++#define C0_COMPARE 11 /* CP0: Compare */
++#define C0_SR 12 /* CP0: Processor Status */
++#define C0_STATUS C0_SR /* CP0: Processor Status */
++#define C0_CAUSE 13 /* CP0: Exception Cause */
++#define C0_EPC 14 /* CP0: Exception PC */
++#define C0_PRID 15 /* CP0: Processor Revision Indentifier */
++#define C0_CONFIG 16 /* CP0: Config */
++#define C0_LLADDR 17 /* CP0: LLAddr */
++#define C0_WATCHLO 18 /* CP0: WatchpointLo */
++#define C0_WATCHHI 19 /* CP0: WatchpointHi */
++#define C0_XCTEXT 20 /* CP0: XContext */
++#define C0_DIAGNOSTIC 22 /* CP0: Diagnostic */
++#define C0_BROADCOM C0_DIAGNOSTIC /* CP0: Broadcom Register */
++#define C0_PERFORMANCE 25 /* CP0: Performance Counter/Control Registers */
++#define C0_ECC 26 /* CP0: ECC */
++#define C0_CACHEERR 27 /* CP0: CacheErr */
++#define C0_TAGLO 28 /* CP0: TagLo */
++#define C0_TAGHI 29 /* CP0: TagHi */
++#define C0_ERREPC 30 /* CP0: ErrorEPC */
++#define C0_DESAVE 31 /* CP0: DebugSave */
++
++#endif /* _LANGUAGE_ASSEMBLY */
++
++/*
++ * Memory segments (32bit kernel mode addresses)
++ */
++#undef KUSEG
++#undef KSEG0
++#undef KSEG1
++#undef KSEG2
++#undef KSEG3
++#define KUSEG 0x00000000
++#define KSEG0 0x80000000
++#define KSEG1 0xa0000000
++#define KSEG2 0xc0000000
++#define KSEG3 0xe0000000
++#define PHYSADDR_MASK 0x1fffffff
++
++/*
++ * Map an address to a certain kernel segment
++ */
++#undef PHYSADDR
++#undef KSEG0ADDR
++#undef KSEG1ADDR
++#undef KSEG2ADDR
++#undef KSEG3ADDR
++
++#define PHYSADDR(a) (_ULCAST_(a) & PHYSADDR_MASK)
++#define KSEG0ADDR(a) ((_ULCAST_(a) & PHYSADDR_MASK) | KSEG0)
++#define KSEG1ADDR(a) ((_ULCAST_(a) & PHYSADDR_MASK) | KSEG1)
++#define KSEG2ADDR(a) ((_ULCAST_(a) & PHYSADDR_MASK) | KSEG2)
++#define KSEG3ADDR(a) ((_ULCAST_(a) & PHYSADDR_MASK) | KSEG3)
++
++
++#ifndef Index_Invalidate_I
++/*
++ * Cache Operations
++ */
++#define Index_Invalidate_I 0x00
++#define Index_Writeback_Inv_D 0x01
++#define Index_Invalidate_SI 0x02
++#define Index_Writeback_Inv_SD 0x03
++#define Index_Load_Tag_I 0x04
++#define Index_Load_Tag_D 0x05
++#define Index_Load_Tag_SI 0x06
++#define Index_Load_Tag_SD 0x07
++#define Index_Store_Tag_I 0x08
++#define Index_Store_Tag_D 0x09
++#define Index_Store_Tag_SI 0x0A
++#define Index_Store_Tag_SD 0x0B
++#define Create_Dirty_Excl_D 0x0d
++#define Create_Dirty_Excl_SD 0x0f
++#define Hit_Invalidate_I 0x10
++#define Hit_Invalidate_D 0x11
++#define Hit_Invalidate_SI 0x12
++#define Hit_Invalidate_SD 0x13
++#define Fill_I 0x14
++#define Hit_Writeback_Inv_D 0x15
++ /* 0x16 is unused */
++#define Hit_Writeback_Inv_SD 0x17
++#define R5K_Page_Invalidate_S 0x17
++#define Hit_Writeback_I 0x18
++#define Hit_Writeback_D 0x19
++ /* 0x1a is unused */
++#define Hit_Writeback_SD 0x1b
++ /* 0x1c is unused */
++ /* 0x1e is unused */
++#define Hit_Set_Virtual_SI 0x1e
++#define Hit_Set_Virtual_SD 0x1f
++#endif /* !Index_Invalidate_I */
++
++
++/*
++ * R4x00 interrupt enable / cause bits
++ */
++#define IE_SW0 (_ULCAST_(1) << 8)
++#define IE_SW1 (_ULCAST_(1) << 9)
++#define IE_IRQ0 (_ULCAST_(1) << 10)
++#define IE_IRQ1 (_ULCAST_(1) << 11)
++#define IE_IRQ2 (_ULCAST_(1) << 12)
++#define IE_IRQ3 (_ULCAST_(1) << 13)
++#define IE_IRQ4 (_ULCAST_(1) << 14)
++#define IE_IRQ5 (_ULCAST_(1) << 15)
++
++#ifndef ST0_UM
++/*
++ * Bitfields in the mips32 cp0 status register
++ */
++#define ST0_IE 0x00000001
++#define ST0_EXL 0x00000002
++#define ST0_ERL 0x00000004
++#define ST0_UM 0x00000010
++#define ST0_SWINT0 0x00000100
++#define ST0_SWINT1 0x00000200
++#define ST0_HWINT0 0x00000400
++#define ST0_HWINT1 0x00000800
++#define ST0_HWINT2 0x00001000
++#define ST0_HWINT3 0x00002000
++#define ST0_HWINT4 0x00004000
++#define ST0_HWINT5 0x00008000
++#define ST0_IM 0x0000ff00
++#define ST0_NMI 0x00080000
++#define ST0_SR 0x00100000
++#define ST0_TS 0x00200000
++#define ST0_BEV 0x00400000
++#define ST0_RE 0x02000000
++#define ST0_RP 0x08000000
++#define ST0_CU 0xf0000000
++#define ST0_CU0 0x10000000
++#define ST0_CU1 0x20000000
++#define ST0_CU2 0x40000000
++#define ST0_CU3 0x80000000
++#endif /* !ST0_UM */
++
++
++/*
++ * Bitfields in the mips32 cp0 cause register
++ */
++#define C_EXC 0x0000007c
++#define C_EXC_SHIFT 2
++#define C_INT 0x0000ff00
++#define C_INT_SHIFT 8
++#define C_SW0 (_ULCAST_(1) << 8)
++#define C_SW1 (_ULCAST_(1) << 9)
++#define C_IRQ0 (_ULCAST_(1) << 10)
++#define C_IRQ1 (_ULCAST_(1) << 11)
++#define C_IRQ2 (_ULCAST_(1) << 12)
++#define C_IRQ3 (_ULCAST_(1) << 13)
++#define C_IRQ4 (_ULCAST_(1) << 14)
++#define C_IRQ5 (_ULCAST_(1) << 15)
++#define C_WP 0x00400000
++#define C_IV 0x00800000
++#define C_CE 0x30000000
++#define C_CE_SHIFT 28
++#define C_BD 0x80000000
++
++/* Values in C_EXC */
++#define EXC_INT 0
++#define EXC_TLBM 1
++#define EXC_TLBL 2
++#define EXC_TLBS 3
++#define EXC_AEL 4
++#define EXC_AES 5
++#define EXC_IBE 6
++#define EXC_DBE 7
++#define EXC_SYS 8
++#define EXC_BPT 9
++#define EXC_RI 10
++#define EXC_CU 11
++#define EXC_OV 12
++#define EXC_TR 13
++#define EXC_WATCH 23
++#define EXC_MCHK 24
++
++
++/*
++ * Bits in the cp0 config register.
++ */
++#define CONF_CM_CACHABLE_NO_WA 0
++#define CONF_CM_CACHABLE_WA 1
++#define CONF_CM_UNCACHED 2
++#define CONF_CM_CACHABLE_NONCOHERENT 3
++#define CONF_CM_CACHABLE_CE 4
++#define CONF_CM_CACHABLE_COW 5
++#define CONF_CM_CACHABLE_CUW 6
++#define CONF_CM_CACHABLE_ACCELERATED 7
++#define CONF_CM_CMASK 7
++#define CONF_CU (_ULCAST_(1) << 3)
++#define CONF_DB (_ULCAST_(1) << 4)
++#define CONF_IB (_ULCAST_(1) << 5)
++#define CONF_SE (_ULCAST_(1) << 12)
++#ifndef CONF_BE /* duplicate in mipsregs.h */
++#define CONF_BE (_ULCAST_(1) << 15)
++#endif
++#define CONF_SC (_ULCAST_(1) << 17)
++#define CONF_AC (_ULCAST_(1) << 23)
++#define CONF_HALT (_ULCAST_(1) << 25)
++#ifndef CONF_M /* duplicate in mipsregs.h */
++#define CONF_M (_ULCAST_(1) << 31)
++#endif
++
++
++/*
++ * Bits in the cp0 config register select 1.
++ */
++#define CONF1_FP 0x00000001 /* FPU present */
++#define CONF1_EP 0x00000002 /* EJTAG present */
++#define CONF1_CA 0x00000004 /* mips16 implemented */
++#define CONF1_WR 0x00000008 /* Watch registers present */
++#define CONF1_PC 0x00000010 /* Performance counters present */
++#define CONF1_DA_SHIFT 7 /* D$ associativity */
++#define CONF1_DA_MASK 0x00000380
++#define CONF1_DA_BASE 1
++#define CONF1_DL_SHIFT 10 /* D$ line size */
++#define CONF1_DL_MASK 0x00001c00
++#define CONF1_DL_BASE 2
++#define CONF1_DS_SHIFT 13 /* D$ sets/way */
++#define CONF1_DS_MASK 0x0000e000
++#define CONF1_DS_BASE 64
++#define CONF1_IA_SHIFT 16 /* I$ associativity */
++#define CONF1_IA_MASK 0x00070000
++#define CONF1_IA_BASE 1
++#define CONF1_IL_SHIFT 19 /* I$ line size */
++#define CONF1_IL_MASK 0x00380000
++#define CONF1_IL_BASE 2
++#define CONF1_IS_SHIFT 22 /* Instruction cache sets/way */
++#define CONF1_IS_MASK 0x01c00000
++#define CONF1_IS_BASE 64
++#define CONF1_MS_MASK 0x7e000000 /* Number of tlb entries */
++#define CONF1_MS_SHIFT 25
++
++/* PRID register */
++#define PRID_COPT_MASK 0xff000000
++#define PRID_COMP_MASK 0x00ff0000
++#define PRID_IMP_MASK 0x0000ff00
++#define PRID_REV_MASK 0x000000ff
++
++#define PRID_COMP_LEGACY 0x000000
++#define PRID_COMP_MIPS 0x010000
++#define PRID_COMP_BROADCOM 0x020000
++#define PRID_COMP_ALCHEMY 0x030000
++#define PRID_COMP_SIBYTE 0x040000
++#define PRID_IMP_BCM4710 0x4000
++#define PRID_IMP_BCM3302 0x9000
++#define PRID_IMP_BCM3303 0x9100
++
++#define PRID_IMP_UNKNOWN 0xff00
++
++#define BCM330X(id) \
++ (((id & (PRID_COMP_MASK | PRID_IMP_MASK)) == \
++ (PRID_COMP_BROADCOM | PRID_IMP_BCM3302)) || \
++ ((id & (PRID_COMP_MASK | PRID_IMP_MASK)) == \
++ (PRID_COMP_BROADCOM | PRID_IMP_BCM3303)))
++
++/* Bits in C0_BROADCOM */
++#define BRCM_PFC_AVAIL 0x20000000 /* PFC is available */
++#define BRCM_DC_ENABLE 0x40000000 /* Enable Data $ */
++#define BRCM_IC_ENABLE 0x80000000 /* Enable Instruction $ */
++#define BRCM_PFC_ENABLE 0x00400000 /* Obsolete? Enable PFC (at least on 4310) */
++#define BRCM_CLF_ENABLE 0x00100000 /* Enable cache line first feature */
++
++/* PreFetch Cache aka Read Ahead Cache */
++
++#define PFC_CR0 0xff400000 /* control reg 0 */
++#define PFC_CR1 0xff400004 /* control reg 1 */
++
++/* PFC operations */
++#define PFC_I 0x00000001 /* Enable PFC use for instructions */
++#define PFC_D 0x00000002 /* Enable PFC use for data */
++#define PFC_PFI 0x00000004 /* Enable seq. prefetch for instructions */
++#define PFC_PFD 0x00000008 /* Enable seq. prefetch for data */
++#define PFC_CINV 0x00000010 /* Enable selective (i/d) cacheop flushing */
++#define PFC_NCH 0x00000020 /* Disable flushing based on cacheops */
++#define PFC_DPF 0x00000040 /* Enable directional prefetching */
++#define PFC_FLUSH 0x00000100 /* Flush the PFC */
++#define PFC_BRR 0x40000000 /* Bus error indication */
++#define PFC_PWR 0x80000000 /* Disable power saving (clock gating) */
++
++/* Handy defaults */
++#define PFC_DISABLED 0
++#define PFC_AUTO 0xffffffff /* auto select the default mode */
++#define PFC_INST (PFC_I | PFC_PFI | PFC_CINV)
++#define PFC_INST_NOPF (PFC_I | PFC_CINV)
++#define PFC_DATA (PFC_D | PFC_PFD | PFC_CINV)
++#define PFC_DATA_NOPF (PFC_D | PFC_CINV)
++#define PFC_I_AND_D (PFC_INST | PFC_DATA)
++#define PFC_I_AND_D_NOPF (PFC_INST_NOPF | PFC_DATA_NOPF)
++
++#ifndef _LANGUAGE_ASSEMBLY
++
++/*
++ * Macros to access the system control coprocessor
++ */
++
++#define MFC0(source, sel) \
++({ \
++ int __res; \
++ __asm__ __volatile__(" \
++ .set\tnoreorder; \
++ .set\tnoat; \
++ .word\t"STR(0x40010000 | ((source) << 11) | (sel))"; \
++ move\t%0, $1; \
++ .set\tat; \
++ .set\treorder" \
++ :"=r" (__res) \
++ : \
++ :"$1"); \
++ __res; \
++})
++
++#define MTC0(source, sel, value) \
++do { \
++ __asm__ __volatile__(" \
++ .set\tnoreorder; \
++ .set\tnoat; \
++ move\t$1, %z0; \
++ .word\t"STR(0x40810000 | ((source) << 11) | (sel))"; \
++ .set\tat; \
++ .set\treorder" \
++ : \
++ :"jr" (value) \
++ :"$1"); \
++} while (0)
++
++#define get_c0_count() \
++({ \
++ int __res; \
++ __asm__ __volatile__(" \
++ .set\tnoreorder; \
++ .set\tnoat; \
++ mfc0\t%0, $9; \
++ .set\tat; \
++ .set\treorder" \
++ :"=r" (__res)); \
++ __res; \
++})
++
++static INLINE void icache_probe(uint32 config1, uint *size, uint *lsize)
++{
++ uint lsz, sets, ways;
++
++ /* Instruction Cache Size = Associativity * Line Size * Sets Per Way */
++ if ((lsz = ((config1 & CONF1_IL_MASK) >> CONF1_IL_SHIFT)))
++ lsz = CONF1_IL_BASE << lsz;
++ sets = CONF1_IS_BASE << ((config1 & CONF1_IS_MASK) >> CONF1_IS_SHIFT);
++ ways = CONF1_IA_BASE + ((config1 & CONF1_IA_MASK) >> CONF1_IA_SHIFT);
++ *size = lsz * sets * ways;
++ *lsize = lsz;
++}
++
++static INLINE void dcache_probe(uint32 config1, uint *size, uint *lsize)
++{
++ uint lsz, sets, ways;
++
++ /* Data Cache Size = Associativity * Line Size * Sets Per Way */
++ if ((lsz = ((config1 & CONF1_DL_MASK) >> CONF1_DL_SHIFT)))
++ lsz = CONF1_DL_BASE << lsz;
++ sets = CONF1_DS_BASE << ((config1 & CONF1_DS_MASK) >> CONF1_DS_SHIFT);
++ ways = CONF1_DA_BASE + ((config1 & CONF1_DA_MASK) >> CONF1_DA_SHIFT);
++ *size = lsz * sets * ways;
++ *lsize = lsz;
++}
++
++#define cache_op(base, op) \
++ __asm__ __volatile__(" \
++ .set noreorder; \
++ .set mips3; \
++ cache %1, (%0); \
++ .set mips0; \
++ .set reorder" \
++ : \
++ : "r" (base), \
++ "i" (op));
++
++#define cache_unroll4(base, delta, op) \
++ __asm__ __volatile__(" \
++ .set noreorder; \
++ .set mips3; \
++ cache %1, 0(%0); \
++ cache %1, delta(%0); \
++ cache %1, (2 * delta)(%0); \
++ cache %1, (3 * delta)(%0); \
++ .set mips0; \
++ .set reorder" \
++ : \
++ : "r" (base), \
++ "i" (op));
++
++#endif /* !_LANGUAGE_ASSEMBLY */
++
++#endif /* _MISPINC_H */
+diff -urN linux.old/arch/mips/bcm947xx/include/osl.h linux.dev/arch/mips/bcm947xx/include/osl.h
+--- linux.old/arch/mips/bcm947xx/include/osl.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/osl.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,179 @@
++#ifndef __osl_h
++#define __osl_h
++
++#include <linux/delay.h>
++#include <typedefs.h>
++#include <linuxver.h>
++#include <bcmutils.h>
++#include <pcicfg.h>
++
++#define ASSERT(n)
++
++/* Pkttag flag should be part of public information */
++struct osl_pubinfo {
++ bool pkttag;
++ uint pktalloced; /* Number of allocated packet buffers */
++};
++
++struct osl_info {
++ struct osl_pubinfo pub;
++ uint magic;
++ void *pdev;
++ uint malloced;
++ uint failed;
++ void *dbgmem_list;
++};
++
++typedef struct osl_info osl_t;
++
++#define PCI_CFG_RETRY 10
++
++/* map/unmap direction */
++#define DMA_TX 1 /* TX direction for DMA */
++#define DMA_RX 2 /* RX direction for DMA */
++
++#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v))
++#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v))
++#define SET_REG(osh, r, mask, val) W_REG((osh), (r), ((R_REG((osh), r) & ~(mask)) | (val)))
++
++/* bcopy, bcmp, and bzero */
++#define bcopy(src, dst, len) memcpy((dst), (src), (len))
++#define bcmp(b1, b2, len) memcmp((b1), (b2), (len))
++#define bzero(b, len) memset((b), '\0', (len))
++
++/* uncached virtual address */
++#ifdef mips
++#define OSL_UNCACHED(va) KSEG1ADDR((va))
++#include <asm/addrspace.h>
++#else
++#define OSL_UNCACHED(va) (va)
++#endif /* mips */
++
++
++#ifndef IL_BIGENDIAN
++#define R_REG(osh, r) (\
++ sizeof(*(r)) == sizeof(uint8) ? readb((volatile uint8*)(r)) : \
++ sizeof(*(r)) == sizeof(uint16) ? readw((volatile uint16*)(r)) : \
++ readl((volatile uint32*)(r)) \
++)
++#define W_REG(osh, r, v) do { \
++ switch (sizeof(*(r))) { \
++ case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)(r)); break; \
++ case sizeof(uint16): writew((uint16)(v), (volatile uint16*)(r)); break; \
++ case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \
++ } \
++} while (0)
++#else /* IL_BIGENDIAN */
++#define R_REG(osh, r) ({ \
++ __typeof(*(r)) __osl_v; \
++ switch (sizeof(*(r))) { \
++ case sizeof(uint8): __osl_v = readb((volatile uint8*)((uint32)r^3)); break; \
++ case sizeof(uint16): __osl_v = readw((volatile uint16*)((uint32)r^2)); break; \
++ case sizeof(uint32): __osl_v = readl((volatile uint32*)(r)); break; \
++ } \
++ __osl_v; \
++})
++#define W_REG(osh, r, v) do { \
++ switch (sizeof(*(r))) { \
++ case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)((uint32)r^3)); break; \
++ case sizeof(uint16): writew((uint16)(v), (volatile uint16*)((uint32)r^2)); break; \
++ case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \
++ } \
++} while (0)
++#endif /* IL_BIGENDIAN */
++
++/* dereference an address that may cause a bus exception */
++#define BUSPROBE(val, addr) get_dbe((val), (addr))
++#include <asm/paccess.h>
++
++/* map/unmap physical to virtual I/O */
++#define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), (unsigned long)(size))
++#define REG_UNMAP(va) iounmap((void *)(va))
++
++/* shared (dma-able) memory access macros */
++#define R_SM(r) *(r)
++#define W_SM(r, v) (*(r) = (v))
++#define BZERO_SM(r, len) memset((r), '\0', (len))
++
++#define MALLOC(osh, size) kmalloc((size), GFP_ATOMIC)
++#define MFREE(osh, addr, size) kfree((addr))
++#define MALLOCED(osh) (0)
++
++#define osl_delay OSL_DELAY
++static inline void OSL_DELAY(uint usec)
++{
++ uint d;
++
++ while (usec > 0) {
++ d = MIN(usec, 1000);
++ udelay(d);
++ usec -= d;
++ }
++}
++
++static inline void
++bcm_mdelay(uint ms)
++{
++ uint i;
++
++ for (i = 0; i < ms; i++) {
++ OSL_DELAY(1000);
++ }
++}
++
++
++#define OSL_PCMCIA_READ_ATTR(osh, offset, buf, size)
++#define OSL_PCMCIA_WRITE_ATTR(osh, offset, buf, size)
++
++#define OSL_PCI_READ_CONFIG(osh, offset, size) \
++ osl_pci_read_config((osh), (offset), (size))
++
++static inline uint32
++osl_pci_read_config(osl_t *osh, uint offset, uint size)
++{
++ uint val;
++ uint retry = PCI_CFG_RETRY;
++
++ do {
++ pci_read_config_dword(osh->pdev, offset, &val);
++ if (val != 0xffffffff)
++ break;
++ } while (retry--);
++
++ return (val);
++}
++
++#define OSL_PCI_WRITE_CONFIG(osh, offset, size, val) \
++ osl_pci_write_config((osh), (offset), (size), (val))
++static inline void
++osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val)
++{
++ uint retry = PCI_CFG_RETRY;
++
++ do {
++ pci_write_config_dword(osh->pdev, offset, val);
++ if (offset != PCI_BAR0_WIN)
++ break;
++ if (osl_pci_read_config(osh, offset, size) == val)
++ break;
++ } while (retry--);
++}
++
++
++/* return bus # for the pci device pointed by osh->pdev */
++#define OSL_PCI_BUS(osh) osl_pci_bus(osh)
++static inline uint
++osl_pci_bus(osl_t *osh)
++{
++ return ((struct pci_dev *)osh->pdev)->bus->number;
++}
++
++/* return slot # for the pci device pointed by osh->pdev */
++#define OSL_PCI_SLOT(osh) osl_pci_slot(osh)
++static inline uint
++osl_pci_slot(osl_t *osh)
++{
++ return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn);
++}
++
++#endif
+diff -urN linux.old/arch/mips/bcm947xx/include/pcicfg.h linux.dev/arch/mips/bcm947xx/include/pcicfg.h
+--- linux.old/arch/mips/bcm947xx/include/pcicfg.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/pcicfg.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,495 @@
++/*
++ * pcicfg.h: PCI configuration constants and structures.
++ *
++ * 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.
++ *
++ * $Id: pcicfg.h,v 1.1.1.11 2006/04/08 06:13:40 honor Exp $
++ */
++
++#ifndef _h_pcicfg_
++#define _h_pcicfg_
++
++/* The following inside ifndef's so we don't collide with NTDDK.H */
++#ifndef PCI_MAX_BUS
++#define PCI_MAX_BUS 0x100
++#endif
++#ifndef PCI_MAX_DEVICES
++#define PCI_MAX_DEVICES 0x20
++#endif
++#ifndef PCI_MAX_FUNCTION
++#define PCI_MAX_FUNCTION 0x8
++#endif
++
++#ifndef PCI_INVALID_VENDORID
++#define PCI_INVALID_VENDORID 0xffff
++#endif
++#ifndef PCI_INVALID_DEVICEID
++#define PCI_INVALID_DEVICEID 0xffff
++#endif
++
++
++/* Convert between bus-slot-function-register and config addresses */
++
++#define PCICFG_BUS_SHIFT 16 /* Bus shift */
++#define PCICFG_SLOT_SHIFT 11 /* Slot shift */
++#define PCICFG_FUN_SHIFT 8 /* Function shift */
++#define PCICFG_OFF_SHIFT 0 /* Register shift */
++
++#define PCICFG_BUS_MASK 0xff /* Bus mask */
++#define PCICFG_SLOT_MASK 0x1f /* Slot mask */
++#define PCICFG_FUN_MASK 7 /* Function mask */
++#define PCICFG_OFF_MASK 0xff /* Bus mask */
++
++#define PCI_CONFIG_ADDR(b, s, f, o) \
++ ((((b) & PCICFG_BUS_MASK) << PCICFG_BUS_SHIFT) \
++ | (((s) & PCICFG_SLOT_MASK) << PCICFG_SLOT_SHIFT) \
++ | (((f) & PCICFG_FUN_MASK) << PCICFG_FUN_SHIFT) \
++ | (((o) & PCICFG_OFF_MASK) << PCICFG_OFF_SHIFT))
++
++#define PCI_CONFIG_BUS(a) (((a) >> PCICFG_BUS_SHIFT) & PCICFG_BUS_MASK)
++#define PCI_CONFIG_SLOT(a) (((a) >> PCICFG_SLOT_SHIFT) & PCICFG_SLOT_MASK)
++#define PCI_CONFIG_FUN(a) (((a) >> PCICFG_FUN_SHIFT) & PCICFG_FUN_MASK)
++#define PCI_CONFIG_OFF(a) (((a) >> PCICFG_OFF_SHIFT) & PCICFG_OFF_MASK)
++
++/* PCIE Config space accessing MACROS */
++
++#define PCIECFG_BUS_SHIFT 24 /* Bus shift */
++#define PCIECFG_SLOT_SHIFT 19 /* Slot/Device shift */
++#define PCIECFG_FUN_SHIFT 16 /* Function shift */
++#define PCIECFG_OFF_SHIFT 0 /* Register shift */
++
++#define PCIECFG_BUS_MASK 0xff /* Bus mask */
++#define PCIECFG_SLOT_MASK 0x1f /* Slot/Device mask */
++#define PCIECFG_FUN_MASK 7 /* Function mask */
++#define PCIECFG_OFF_MASK 0x3ff /* Register mask */
++
++#define PCIE_CONFIG_ADDR(b, s, f, o) \
++ ((((b) & PCIECFG_BUS_MASK) << PCIECFG_BUS_SHIFT) \
++ | (((s) & PCIECFG_SLOT_MASK) << PCIECFG_SLOT_SHIFT) \
++ | (((f) & PCIECFG_FUN_MASK) << PCIECFG_FUN_SHIFT) \
++ | (((o) & PCIECFG_OFF_MASK) << PCIECFG_OFF_SHIFT))
++
++#define PCIE_CONFIG_BUS(a) (((a) >> PCIECFG_BUS_SHIFT) & PCIECFG_BUS_MASK)
++#define PCIE_CONFIG_SLOT(a) (((a) >> PCIECFG_SLOT_SHIFT) & PCIECFG_SLOT_MASK)
++#define PCIE_CONFIG_FUN(a) (((a) >> PCIECFG_FUN_SHIFT) & PCIECFG_FUN_MASK)
++#define PCIE_CONFIG_OFF(a) (((a) >> PCIECFG_OFF_SHIFT) & PCIECFG_OFF_MASK)
++
++/* The actual config space */
++
++#define PCI_BAR_MAX 6
++
++#define PCI_ROM_BAR 8
++
++#define PCR_RSVDA_MAX 2
++
++/* Bits in PCI bars' flags */
++
++#define PCIBAR_FLAGS 0xf
++#define PCIBAR_IO 0x1
++#define PCIBAR_MEM1M 0x2
++#define PCIBAR_MEM64 0x4
++#define PCIBAR_PREFETCH 0x8
++#define PCIBAR_MEM32_MASK 0xFFFFFF80
++
++/* pci config status reg has a bit to indicate that capability ptr is present */
++
++#define PCI_CAPPTR_PRESENT 0x0010
++
++typedef struct _pci_config_regs {
++ unsigned short vendor;
++ unsigned short device;
++ unsigned short command;
++ unsigned short status;
++ unsigned char rev_id;
++ unsigned char prog_if;
++ unsigned char sub_class;
++ unsigned char base_class;
++ unsigned char cache_line_size;
++ unsigned char latency_timer;
++ unsigned char header_type;
++ unsigned char bist;
++ unsigned long base[PCI_BAR_MAX];
++ unsigned long cardbus_cis;
++ unsigned short subsys_vendor;
++ unsigned short subsys_id;
++ unsigned long baserom;
++ unsigned long rsvd_a[PCR_RSVDA_MAX];
++ unsigned char int_line;
++ unsigned char int_pin;
++ unsigned char min_gnt;
++ unsigned char max_lat;
++ unsigned char dev_dep[192];
++} pci_config_regs;
++
++#define SZPCR (sizeof (pci_config_regs))
++#define MINSZPCR 64 /* offsetof (dev_dep[0] */
++
++/* A structure for the config registers is nice, but in most
++ * systems the config space is not memory mapped, so we need
++ * filed offsetts. :-(
++ */
++#define PCI_CFG_VID 0
++#define PCI_CFG_DID 2
++#define PCI_CFG_CMD 4
++#define PCI_CFG_STAT 6
++#define PCI_CFG_REV 8
++#define PCI_CFG_PROGIF 9
++#define PCI_CFG_SUBCL 0xa
++#define PCI_CFG_BASECL 0xb
++#define PCI_CFG_CLSZ 0xc
++#define PCI_CFG_LATTIM 0xd
++#define PCI_CFG_HDR 0xe
++#define PCI_CFG_BIST 0xf
++#define PCI_CFG_BAR0 0x10
++#define PCI_CFG_BAR1 0x14
++#define PCI_CFG_BAR2 0x18
++#define PCI_CFG_BAR3 0x1c
++#define PCI_CFG_BAR4 0x20
++#define PCI_CFG_BAR5 0x24
++#define PCI_CFG_CIS 0x28
++#define PCI_CFG_SVID 0x2c
++#define PCI_CFG_SSID 0x2e
++#define PCI_CFG_ROMBAR 0x30
++#define PCI_CFG_CAPPTR 0x34
++#define PCI_CFG_INT 0x3c
++#define PCI_CFG_PIN 0x3d
++#define PCI_CFG_MINGNT 0x3e
++#define PCI_CFG_MAXLAT 0x3f
++
++#ifdef __NetBSD__
++#undef PCI_CLASS_DISPLAY
++#undef PCI_CLASS_MEMORY
++#undef PCI_CLASS_BRIDGE
++#undef PCI_CLASS_INPUT
++#undef PCI_CLASS_DOCK
++#endif /* __NetBSD__ */
++
++/* Classes and subclasses */
++
++typedef enum {
++ PCI_CLASS_OLD = 0,
++ PCI_CLASS_DASDI,
++ PCI_CLASS_NET,
++ PCI_CLASS_DISPLAY,
++ PCI_CLASS_MMEDIA,
++ PCI_CLASS_MEMORY,
++ PCI_CLASS_BRIDGE,
++ PCI_CLASS_COMM,
++ PCI_CLASS_BASE,
++ PCI_CLASS_INPUT,
++ PCI_CLASS_DOCK,
++ PCI_CLASS_CPU,
++ PCI_CLASS_SERIAL,
++ PCI_CLASS_INTELLIGENT = 0xe,
++ PCI_CLASS_SATELLITE,
++ PCI_CLASS_CRYPT,
++ PCI_CLASS_DSP,
++ PCI_CLASS_XOR = 0xfe
++} pci_classes;
++
++typedef enum {
++ PCI_DASDI_SCSI,
++ PCI_DASDI_IDE,
++ PCI_DASDI_FLOPPY,
++ PCI_DASDI_IPI,
++ PCI_DASDI_RAID,
++ PCI_DASDI_OTHER = 0x80
++} pci_dasdi_subclasses;
++
++typedef enum {
++ PCI_NET_ETHER,
++ PCI_NET_TOKEN,
++ PCI_NET_FDDI,
++ PCI_NET_ATM,
++ PCI_NET_OTHER = 0x80
++} pci_net_subclasses;
++
++typedef enum {
++ PCI_DISPLAY_VGA,
++ PCI_DISPLAY_XGA,
++ PCI_DISPLAY_3D,
++ PCI_DISPLAY_OTHER = 0x80
++} pci_display_subclasses;
++
++typedef enum {
++ PCI_MMEDIA_VIDEO,
++ PCI_MMEDIA_AUDIO,
++ PCI_MMEDIA_PHONE,
++ PCI_MEDIA_OTHER = 0x80
++} pci_mmedia_subclasses;
++
++typedef enum {
++ PCI_MEMORY_RAM,
++ PCI_MEMORY_FLASH,
++ PCI_MEMORY_OTHER = 0x80
++} pci_memory_subclasses;
++
++typedef enum {
++ PCI_BRIDGE_HOST,
++ PCI_BRIDGE_ISA,
++ PCI_BRIDGE_EISA,
++ PCI_BRIDGE_MC,
++ PCI_BRIDGE_PCI,
++ PCI_BRIDGE_PCMCIA,
++ PCI_BRIDGE_NUBUS,
++ PCI_BRIDGE_CARDBUS,
++ PCI_BRIDGE_RACEWAY,
++ PCI_BRIDGE_OTHER = 0x80
++} pci_bridge_subclasses;
++
++typedef enum {
++ PCI_COMM_UART,
++ PCI_COMM_PARALLEL,
++ PCI_COMM_MULTIUART,
++ PCI_COMM_MODEM,
++ PCI_COMM_OTHER = 0x80
++} pci_comm_subclasses;
++
++typedef enum {
++ PCI_BASE_PIC,
++ PCI_BASE_DMA,
++ PCI_BASE_TIMER,
++ PCI_BASE_RTC,
++ PCI_BASE_PCI_HOTPLUG,
++ PCI_BASE_OTHER = 0x80
++} pci_base_subclasses;
++
++typedef enum {
++ PCI_INPUT_KBD,
++ PCI_INPUT_PEN,
++ PCI_INPUT_MOUSE,
++ PCI_INPUT_SCANNER,
++ PCI_INPUT_GAMEPORT,
++ PCI_INPUT_OTHER = 0x80
++} pci_input_subclasses;
++
++typedef enum {
++ PCI_DOCK_GENERIC,
++ PCI_DOCK_OTHER = 0x80
++} pci_dock_subclasses;
++
++typedef enum {
++ PCI_CPU_386,
++ PCI_CPU_486,
++ PCI_CPU_PENTIUM,
++ PCI_CPU_ALPHA = 0x10,
++ PCI_CPU_POWERPC = 0x20,
++ PCI_CPU_MIPS = 0x30,
++ PCI_CPU_COPROC = 0x40,
++ PCI_CPU_OTHER = 0x80
++} pci_cpu_subclasses;
++
++typedef enum {
++ PCI_SERIAL_IEEE1394,
++ PCI_SERIAL_ACCESS,
++ PCI_SERIAL_SSA,
++ PCI_SERIAL_USB,
++ PCI_SERIAL_FIBER,
++ PCI_SERIAL_SMBUS,
++ PCI_SERIAL_OTHER = 0x80
++} pci_serial_subclasses;
++
++typedef enum {
++ PCI_INTELLIGENT_I2O
++} pci_intelligent_subclasses;
++
++typedef enum {
++ PCI_SATELLITE_TV,
++ PCI_SATELLITE_AUDIO,
++ PCI_SATELLITE_VOICE,
++ PCI_SATELLITE_DATA,
++ PCI_SATELLITE_OTHER = 0x80
++} pci_satellite_subclasses;
++
++typedef enum {
++ PCI_CRYPT_NETWORK,
++ PCI_CRYPT_ENTERTAINMENT,
++ PCI_CRYPT_OTHER = 0x80
++} pci_crypt_subclasses;
++
++typedef enum {
++ PCI_DSP_DPIO,
++ PCI_DSP_OTHER = 0x80
++} pci_dsp_subclasses;
++
++typedef enum {
++ PCI_XOR_QDMA,
++ PCI_XOR_OTHER = 0x80
++} pci_xor_subclasses;
++
++/* Header types */
++typedef enum {
++ PCI_HEADER_NORMAL,
++ PCI_HEADER_BRIDGE,
++ PCI_HEADER_CARDBUS
++} pci_header_types;
++
++
++/* Overlay for a PCI-to-PCI bridge */
++
++#define PPB_RSVDA_MAX 2
++#define PPB_RSVDD_MAX 8
++
++typedef struct _ppb_config_regs {
++ unsigned short vendor;
++ unsigned short device;
++ unsigned short command;
++ unsigned short status;
++ unsigned char rev_id;
++ unsigned char prog_if;
++ unsigned char sub_class;
++ unsigned char base_class;
++ unsigned char cache_line_size;
++ unsigned char latency_timer;
++ unsigned char header_type;
++ unsigned char bist;
++ unsigned long rsvd_a[PPB_RSVDA_MAX];
++ unsigned char prim_bus;
++ unsigned char sec_bus;
++ unsigned char sub_bus;
++ unsigned char sec_lat;
++ unsigned char io_base;
++ unsigned char io_lim;
++ unsigned short sec_status;
++ unsigned short mem_base;
++ unsigned short mem_lim;
++ unsigned short pf_mem_base;
++ unsigned short pf_mem_lim;
++ unsigned long pf_mem_base_hi;
++ unsigned long pf_mem_lim_hi;
++ unsigned short io_base_hi;
++ unsigned short io_lim_hi;
++ unsigned short subsys_vendor;
++ unsigned short subsys_id;
++ unsigned long rsvd_b;
++ unsigned char rsvd_c;
++ unsigned char int_pin;
++ unsigned short bridge_ctrl;
++ unsigned char chip_ctrl;
++ unsigned char diag_ctrl;
++ unsigned short arb_ctrl;
++ unsigned long rsvd_d[PPB_RSVDD_MAX];
++ unsigned char dev_dep[192];
++} ppb_config_regs;
++
++
++/* PCI CAPABILITY DEFINES */
++#define PCI_CAP_POWERMGMTCAP_ID 0x01
++#define PCI_CAP_MSICAP_ID 0x05
++#define PCI_CAP_PCIECAP_ID 0x10
++
++/* Data structure to define the Message Signalled Interrupt facility
++ * Valid for PCI and PCIE configurations
++ */
++typedef struct _pciconfig_cap_msi {
++ unsigned char capID;
++ unsigned char nextptr;
++ unsigned short msgctrl;
++ unsigned int msgaddr;
++} pciconfig_cap_msi;
++
++/* Data structure to define the Power managment facility
++ * Valid for PCI and PCIE configurations
++ */
++typedef struct _pciconfig_cap_pwrmgmt {
++ unsigned char capID;
++ unsigned char nextptr;
++ unsigned short pme_cap;
++ unsigned short pme_sts_ctrl;
++ unsigned char pme_bridge_ext;
++ unsigned char data;
++} pciconfig_cap_pwrmgmt;
++
++/* Data structure to define the PCIE capability */
++typedef struct _pciconfig_cap_pcie {
++ unsigned char capID;
++ unsigned char nextptr;
++ unsigned short pcie_cap;
++ unsigned int dev_cap;
++ unsigned short dev_ctrl;
++ unsigned short dev_status;
++ unsigned int link_cap;
++ unsigned short link_ctrl;
++ unsigned short link_status;
++} pciconfig_cap_pcie;
++
++/* PCIE Enhanced CAPABILITY DEFINES */
++#define PCIE_EXTCFG_OFFSET 0x100
++#define PCIE_ADVERRREP_CAPID 0x0001
++#define PCIE_VC_CAPID 0x0002
++#define PCIE_DEVSNUM_CAPID 0x0003
++#define PCIE_PWRBUDGET_CAPID 0x0004
++
++/* Header to define the PCIE specific capabilities in the extended config space */
++typedef struct _pcie_enhanced_caphdr {
++ unsigned short capID;
++ unsigned short cap_ver : 4;
++ unsigned short next_ptr : 12;
++} pcie_enhanced_caphdr;
++
++
++/* Everything below is BRCM HND proprietary */
++
++
++/* Brcm PCI configuration registers */
++#define cap_list rsvd_a[0]
++#define bar0_window dev_dep[0x80 - 0x40]
++#define bar1_window dev_dep[0x84 - 0x40]
++#define sprom_control dev_dep[0x88 - 0x40]
++
++#define PCI_BAR0_WIN 0x80 /* backplane addres space accessed by BAR0 */
++#define PCI_BAR1_WIN 0x84 /* backplane addres space accessed by BAR1 */
++#define PCI_SPROM_CONTROL 0x88 /* sprom property control */
++#define PCI_BAR1_CONTROL 0x8c /* BAR1 region burst control */
++#define PCI_INT_STATUS 0x90 /* PCI and other cores interrupts */
++#define PCI_INT_MASK 0x94 /* mask of PCI and other cores interrupts */
++#define PCI_TO_SB_MB 0x98 /* signal backplane interrupts */
++#define PCI_BACKPLANE_ADDR 0xA0 /* address an arbitrary location on the system backplane */
++#define PCI_BACKPLANE_DATA 0xA4 /* data at the location specified by above address */
++#define PCI_GPIO_IN 0xb0 /* pci config space gpio input (>=rev3) */
++#define PCI_GPIO_OUT 0xb4 /* pci config space gpio output (>=rev3) */
++#define PCI_GPIO_OUTEN 0xb8 /* pci config space gpio output enable (>=rev3) */
++
++#define PCI_BAR0_SHADOW_OFFSET (2 * 1024) /* bar0 + 2K accesses sprom shadow (in pci core) */
++#define PCI_BAR0_SPROM_OFFSET (4 * 1024) /* bar0 + 4K accesses external sprom */
++#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) /* bar0 + 6K accesses pci core registers */
++#define PCI_BAR0_PCISBR_OFFSET (4 * 1024) /* pci core SB registers are at the end of the
++ * 8KB window, so their address is the "regular"
++ * address plus 4K
++ */
++#define PCI_BAR0_WINSZ 8192 /* bar0 window size */
++
++/* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */
++#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024) /* bar0 + 8K accesses pci/pcie core registers */
++#define PCI_16KB0_CCREGS_OFFSET (12 * 1024) /* bar0 + 12K accesses chipc core registers */
++#define PCI_16KBB0_WINSZ (16 * 1024) /* bar0 window size */
++
++/* PCI_INT_STATUS */
++#define PCI_SBIM_STATUS_SERR 0x4 /* backplane SBErr interrupt status */
++
++/* PCI_INT_MASK */
++#define PCI_SBIM_SHIFT 8 /* backplane core interrupt mask bits offset */
++#define PCI_SBIM_MASK 0xff00 /* backplane core interrupt mask */
++#define PCI_SBIM_MASK_SERR 0x4 /* backplane SBErr interrupt mask */
++
++/* PCI_SPROM_CONTROL */
++#define SPROM_SZ_MSK 0x02 /* SPROM Size Mask */
++#define SPROM_LOCKED 0x08 /* SPROM Locked */
++#define SPROM_BLANK 0x04 /* indicating a blank SPROM */
++#define SPROM_WRITEEN 0x10 /* SPROM write enable */
++#define SPROM_BOOTROM_WE 0x20 /* external bootrom write enable */
++#define SPROM_OTPIN_USE 0x80 /* device OTP In use */
++
++#define SPROM_SIZE 256 /* sprom size in 16-bit */
++#define SPROM_CRC_RANGE 64 /* crc cover range in 16-bit */
++
++/* PCI_CFG_CMD_STAT */
++#define PCI_CFG_CMD_STAT_TA 0x08000000 /* target abort status */
++
++#endif /* _h_pcicfg_ */
+diff -urN linux.old/arch/mips/bcm947xx/include/sbchipc.h linux.dev/arch/mips/bcm947xx/include/sbchipc.h
+--- linux.old/arch/mips/bcm947xx/include/sbchipc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/sbchipc.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,516 @@
++/*
++ * SiliconBackplane Chipcommon core hardware definitions.
++ *
++ * The chipcommon core provides chip identification, SB control,
++ * jtag, 0/1/2 uarts, clock frequency control, a watchdog interrupt timer,
++ * gpio interface, extbus, and support for serial and parallel flashes.
++ *
++ * $Id: sbchipc.h,v 1.1.1.14 2006/04/15 01:29:08 michael Exp $
++ * 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 _SBCHIPC_H
++#define _SBCHIPC_H
++
++
++#ifndef _LANGUAGE_ASSEMBLY
++
++/* cpp contortions to concatenate w/arg prescan */
++#ifndef PAD
++#define _PADLINE(line) pad ## line
++#define _XSTR(line) _PADLINE(line)
++#define PAD _XSTR(__LINE__)
++#endif /* PAD */
++
++typedef volatile struct {
++ uint32 chipid; /* 0x0 */
++ uint32 capabilities;
++ uint32 corecontrol; /* corerev >= 1 */
++ uint32 bist;
++
++ /* OTP */
++ uint32 otpstatus; /* 0x10, corerev >= 10 */
++ uint32 otpcontrol;
++ uint32 otpprog;
++ uint32 PAD;
++
++ /* Interrupt control */
++ uint32 intstatus; /* 0x20 */
++ uint32 intmask;
++ uint32 chipcontrol; /* 0x28, rev >= 11 */
++ uint32 chipstatus; /* 0x2c, rev >= 11 */
++
++ /* Jtag Master */
++ uint32 jtagcmd; /* 0x30, rev >= 10 */
++ uint32 jtagir;
++ uint32 jtagdr;
++ uint32 jtagctrl;
++
++ /* serial flash interface registers */
++ uint32 flashcontrol; /* 0x40 */
++ uint32 flashaddress;
++ uint32 flashdata;
++ uint32 PAD[1];
++
++ /* Silicon backplane configuration broadcast control */
++ uint32 broadcastaddress; /* 0x50 */
++ uint32 broadcastdata;
++ uint32 PAD[2];
++
++ /* gpio - cleared only by power-on-reset */
++ uint32 gpioin; /* 0x60 */
++ uint32 gpioout;
++ uint32 gpioouten;
++ uint32 gpiocontrol;
++ uint32 gpiointpolarity;
++ uint32 gpiointmask;
++ uint32 PAD[2];
++
++ /* Watchdog timer */
++ uint32 watchdog; /* 0x80 */
++ uint32 PAD[1];
++
++ /* GPIO based LED powersave registers corerev >= 16 */
++ uint32 gpiotimerval; /* 0x88 */
++ uint32 gpiotimeroutmask;
++
++ /* clock control */
++ uint32 clockcontrol_n; /* 0x90 */
++ uint32 clockcontrol_sb; /* aka m0 */
++ uint32 clockcontrol_pci; /* aka m1 */
++ uint32 clockcontrol_m2; /* mii/uart/mipsref */
++ uint32 clockcontrol_m3; /* cpu */
++ uint32 clkdiv; /* corerev >= 3 */
++ uint32 PAD[2];
++
++ /* pll delay registers (corerev >= 4) */
++ uint32 pll_on_delay; /* 0xb0 */
++ uint32 fref_sel_delay;
++ uint32 slow_clk_ctl; /* 5 < corerev < 10 */
++ uint32 PAD[1];
++
++ /* Instaclock registers (corerev >= 10) */
++ uint32 system_clk_ctl; /* 0xc0 */
++ uint32 clkstatestretch;
++ uint32 PAD[14];
++
++ /* ExtBus control registers (corerev >= 3) */
++ uint32 pcmcia_config; /* 0x100 */
++ uint32 pcmcia_memwait;
++ uint32 pcmcia_attrwait;
++ uint32 pcmcia_iowait;
++ uint32 ide_config;
++ uint32 ide_memwait;
++ uint32 ide_attrwait;
++ uint32 ide_iowait;
++ uint32 prog_config;
++ uint32 prog_waitcount;
++ uint32 flash_config;
++ uint32 flash_waitcount;
++ uint32 PAD[44];
++
++ /* Clock control and hardware workarounds */
++ uint32 clk_ctl_st;
++ uint32 hw_war;
++ uint32 PAD[70];
++
++ /* uarts */
++ uint8 uart0data; /* 0x300 */
++ uint8 uart0imr;
++ uint8 uart0fcr;
++ uint8 uart0lcr;
++ uint8 uart0mcr;
++ uint8 uart0lsr;
++ uint8 uart0msr;
++ uint8 uart0scratch;
++ uint8 PAD[248]; /* corerev >= 1 */
++
++ uint8 uart1data; /* 0x400 */
++ uint8 uart1imr;
++ uint8 uart1fcr;
++ uint8 uart1lcr;
++ uint8 uart1mcr;
++ uint8 uart1lsr;
++ uint8 uart1msr;
++ uint8 uart1scratch;
++} chipcregs_t;
++
++#endif /* _LANGUAGE_ASSEMBLY */
++
++#define CC_CHIPID 0
++#define CC_CAPABILITIES 4
++#define CC_JTAGCMD 0x30
++#define CC_JTAGIR 0x34
++#define CC_JTAGDR 0x38
++#define CC_JTAGCTRL 0x3c
++#define CC_WATCHDOG 0x80
++#define CC_CLKC_N 0x90
++#define CC_CLKC_M0 0x94
++#define CC_CLKC_M1 0x98
++#define CC_CLKC_M2 0x9c
++#define CC_CLKC_M3 0xa0
++#define CC_CLKDIV 0xa4
++#define CC_SYS_CLK_CTL 0xc0
++#define CC_OTP 0x800
++
++/* chipid */
++#define CID_ID_MASK 0x0000ffff /* Chip Id mask */
++#define CID_REV_MASK 0x000f0000 /* Chip Revision mask */
++#define CID_REV_SHIFT 16 /* Chip Revision shift */
++#define CID_PKG_MASK 0x00f00000 /* Package Option mask */
++#define CID_PKG_SHIFT 20 /* Package Option shift */
++#define CID_CC_MASK 0x0f000000 /* CoreCount (corerev >= 4) */
++#define CID_CC_SHIFT 24
++
++/* capabilities */
++#define CAP_UARTS_MASK 0x00000003 /* Number of uarts */
++#define CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */
++#define CAP_UCLKSEL 0x00000018 /* UARTs clock select */
++#define CAP_UINTCLK 0x00000008 /* UARTs are driven by internal divided clock */
++#define CAP_UARTGPIO 0x00000020 /* UARTs own Gpio's 15:12 */
++#define CAP_EXTBUS_MASK 0x000000c0 /* External bus mask */
++#define CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */
++#define CAP_EXTBUS_FULL 0x00000040 /* ExtBus: PCMCIA, IDE & Prog */
++#define CAP_EXTBUS_PROG 0x00000080 /* ExtBus: ProgIf only */
++#define CAP_FLASH_MASK 0x00000700 /* Type of flash */
++#define CAP_PLL_MASK 0x00038000 /* Type of PLL */
++#define CAP_PWR_CTL 0x00040000 /* Power control */
++#define CAP_OTPSIZE 0x00380000 /* OTP Size (0 = none) */
++#define CAP_OTPSIZE_SHIFT 19 /* OTP Size shift */
++#define CAP_OTPSIZE_BASE 5 /* OTP Size base */
++#define CAP_JTAGP 0x00400000 /* JTAG Master Present */
++#define CAP_ROM 0x00800000 /* Internal boot rom active */
++#define CAP_BKPLN64 0x08000000 /* 64-bit backplane */
++
++/* PLL type */
++#define PLL_NONE 0x00000000
++#define PLL_TYPE1 0x00010000 /* 48Mhz base, 3 dividers */
++#define PLL_TYPE2 0x00020000 /* 48Mhz, 4 dividers */
++#define PLL_TYPE3 0x00030000 /* 25Mhz, 2 dividers */
++#define PLL_TYPE4 0x00008000 /* 48Mhz, 4 dividers */
++#define PLL_TYPE5 0x00018000 /* 25Mhz, 4 dividers */
++#define PLL_TYPE6 0x00028000 /* 100/200 or 120/240 only */
++#define PLL_TYPE7 0x00038000 /* 25Mhz, 4 dividers */
++
++/* corecontrol */
++#define CC_UARTCLKO 0x00000001 /* Drive UART with internal clock */
++#define CC_SE 0x00000002 /* sync clk out enable (corerev >= 3) */
++
++/* chipcontrol */
++#define CHIPCTRL_4321A0_DEFAULT 0x3a4
++#define CHIPCTRL_4321A1_DEFAULT 0x0a4
++
++/* Fields in the otpstatus register */
++#define OTPS_PROGFAIL 0x80000000
++#define OTPS_PROTECT 0x00000007
++#define OTPS_HW_PROTECT 0x00000001
++#define OTPS_SW_PROTECT 0x00000002
++#define OTPS_CID_PROTECT 0x00000004
++
++/* Fields in the otpcontrol register */
++#define OTPC_RECWAIT 0xff000000
++#define OTPC_PROGWAIT 0x00ffff00
++#define OTPC_PRW_SHIFT 8
++#define OTPC_MAXFAIL 0x00000038
++#define OTPC_VSEL 0x00000006
++#define OTPC_SELVL 0x00000001
++
++/* Fields in otpprog */
++#define OTPP_COL_MASK 0x000000ff
++#define OTPP_ROW_MASK 0x0000ff00
++#define OTPP_ROW_SHIFT 8
++#define OTPP_READERR 0x10000000
++#define OTPP_VALUE 0x20000000
++#define OTPP_VALUE_SHIFT 29
++#define OTPP_READ 0x40000000
++#define OTPP_START 0x80000000
++#define OTPP_BUSY 0x80000000
++
++/* jtagcmd */
++#define JCMD_START 0x80000000
++#define JCMD_BUSY 0x80000000
++#define JCMD_PAUSE 0x40000000
++#define JCMD0_ACC_MASK 0x0000f000
++#define JCMD0_ACC_IRDR 0x00000000
++#define JCMD0_ACC_DR 0x00001000
++#define JCMD0_ACC_IR 0x00002000
++#define JCMD0_ACC_RESET 0x00003000
++#define JCMD0_ACC_IRPDR 0x00004000
++#define JCMD0_ACC_PDR 0x00005000
++#define JCMD0_IRW_MASK 0x00000f00
++#define JCMD_ACC_MASK 0x000f0000 /* Changes for corerev 11 */
++#define JCMD_ACC_IRDR 0x00000000
++#define JCMD_ACC_DR 0x00010000
++#define JCMD_ACC_IR 0x00020000
++#define JCMD_ACC_RESET 0x00030000
++#define JCMD_ACC_IRPDR 0x00040000
++#define JCMD_ACC_PDR 0x00050000
++#define JCMD_IRW_MASK 0x00001f00
++#define JCMD_IRW_SHIFT 8
++#define JCMD_DRW_MASK 0x0000003f
++
++/* jtagctrl */
++#define JCTRL_FORCE_CLK 4 /* Force clock */
++#define JCTRL_EXT_EN 2 /* Enable external targets */
++#define JCTRL_EN 1 /* Enable Jtag master */
++
++/* Fields in clkdiv */
++#define CLKD_SFLASH 0x0f000000
++#define CLKD_SFLASH_SHIFT 24
++#define CLKD_OTP 0x000f0000
++#define CLKD_OTP_SHIFT 16
++#define CLKD_JTAG 0x00000f00
++#define CLKD_JTAG_SHIFT 8
++#define CLKD_UART 0x000000ff
++
++/* intstatus/intmask */
++#define CI_GPIO 0x00000001 /* gpio intr */
++#define CI_EI 0x00000002 /* ro: ext intr pin (corerev >= 3) */
++#define CI_WDRESET 0x80000000 /* watchdog reset occurred */
++
++/* slow_clk_ctl */
++#define SCC_SS_MASK 0x00000007 /* slow clock source mask */
++#define SCC_SS_LPO 0x00000000 /* source of slow clock is LPO */
++#define SCC_SS_XTAL 0x00000001 /* source of slow clock is crystal */
++#define SCC_SS_PCI 0x00000002 /* source of slow clock is PCI */
++#define SCC_LF 0x00000200 /* LPOFreqSel, 1: 160Khz, 0: 32KHz */
++#define SCC_LP 0x00000400 /* LPOPowerDown, 1: LPO is disabled,
++ * 0: LPO is enabled
++ */
++#define SCC_FS 0x00000800 /* ForceSlowClk, 1: sb/cores running on slow clock,
++ * 0: power logic control
++ */
++#define SCC_IP 0x00001000 /* IgnorePllOffReq, 1/0: power logic ignores/honors
++ * PLL clock disable requests from core
++ */
++#define SCC_XC 0x00002000 /* XtalControlEn, 1/0: power logic does/doesn't
++ * disable crystal when appropriate
++ */
++#define SCC_XP 0x00004000 /* XtalPU (RO), 1/0: crystal running/disabled */
++#define SCC_CD_MASK 0xffff0000 /* ClockDivider (SlowClk = 1/(4+divisor)) */
++#define SCC_CD_SHIFT 16
++
++/* system_clk_ctl */
++#define SYCC_IE 0x00000001 /* ILPen: Enable Idle Low Power */
++#define SYCC_AE 0x00000002 /* ALPen: Enable Active Low Power */
++#define SYCC_FP 0x00000004 /* ForcePLLOn */
++#define SYCC_AR 0x00000008 /* Force ALP (or HT if ALPen is not set */
++#define SYCC_HR 0x00000010 /* Force HT */
++#define SYCC_CD_MASK 0xffff0000 /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */
++#define SYCC_CD_SHIFT 16
++
++/* gpiotimerval */
++#define GPIO_ONTIME_SHIFT 16
++
++/* clockcontrol_n */
++#define CN_N1_MASK 0x3f /* n1 control */
++#define CN_N2_MASK 0x3f00 /* n2 control */
++#define CN_N2_SHIFT 8
++#define CN_PLLC_MASK 0xf0000 /* pll control */
++#define CN_PLLC_SHIFT 16
++
++/* clockcontrol_sb/pci/uart */
++#define CC_M1_MASK 0x3f /* m1 control */
++#define CC_M2_MASK 0x3f00 /* m2 control */
++#define CC_M2_SHIFT 8
++#define CC_M3_MASK 0x3f0000 /* m3 control */
++#define CC_M3_SHIFT 16
++#define CC_MC_MASK 0x1f000000 /* mux control */
++#define CC_MC_SHIFT 24
++
++/* N3M Clock control magic field values */
++#define CC_F6_2 0x02 /* A factor of 2 in */
++#define CC_F6_3 0x03 /* 6-bit fields like */
++#define CC_F6_4 0x05 /* N1, M1 or M3 */
++#define CC_F6_5 0x09
++#define CC_F6_6 0x11
++#define CC_F6_7 0x21
++
++#define CC_F5_BIAS 5 /* 5-bit fields get this added */
++
++#define CC_MC_BYPASS 0x08
++#define CC_MC_M1 0x04
++#define CC_MC_M1M2 0x02
++#define CC_MC_M1M2M3 0x01
++#define CC_MC_M1M3 0x11
++
++/* Type 2 Clock control magic field values */
++#define CC_T2_BIAS 2 /* n1, n2, m1 & m3 bias */
++#define CC_T2M2_BIAS 3 /* m2 bias */
++
++#define CC_T2MC_M1BYP 1
++#define CC_T2MC_M2BYP 2
++#define CC_T2MC_M3BYP 4
++
++/* Type 6 Clock control magic field values */
++#define CC_T6_MMASK 1 /* bits of interest in m */
++#define CC_T6_M0 120000000 /* sb clock for m = 0 */
++#define CC_T6_M1 100000000 /* sb clock for m = 1 */
++#define SB2MIPS_T6(sb) (2 * (sb))
++
++/* Common clock base */
++#define CC_CLOCK_BASE1 24000000 /* Half the clock freq */
++#define CC_CLOCK_BASE2 12500000 /* Alternate crystal on some PLL's */
++
++/* Clock control values for 200Mhz in 5350 */
++#define CLKC_5350_N 0x0311
++#define CLKC_5350_M 0x04020009
++
++/* Flash types in the chipcommon capabilities register */
++#define FLASH_NONE 0x000 /* No flash */
++#define SFLASH_ST 0x100 /* ST serial flash */
++#define SFLASH_AT 0x200 /* Atmel serial flash */
++#define PFLASH 0x700 /* Parallel flash */
++
++/* Bits in the ExtBus config registers */
++#define CC_CFG_EN 0x0001 /* Enable */
++#define CC_CFG_EM_MASK 0x000e /* Extif Mode */
++#define CC_CFG_EM_ASYNC 0x0000 /* Async/Parallel flash */
++#define CC_CFG_EM_SYNC 0x0002 /* Synchronous */
++#define CC_CFG_EM_PCMCIA 0x0004 /* PCMCIA */
++#define CC_CFG_EM_IDE 0x0006 /* IDE */
++#define CC_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */
++#define CC_CFG_CD_MASK 0x0060 /* Sync: Clock divisor */
++#define CC_CFG_CE 0x0080 /* Sync: Clock enable */
++#define CC_CFG_SB 0x0100 /* Sync: Size/Bytestrobe */
++
++/* ExtBus address space */
++#define CC_EB_BASE 0x1a000000 /* Chipc ExtBus base address */
++#define CC_EB_PCMCIA_MEM 0x1a000000 /* PCMCIA 0 memory base address */
++#define CC_EB_PCMCIA_IO 0x1a200000 /* PCMCIA 0 I/O base address */
++#define CC_EB_PCMCIA_CFG 0x1a400000 /* PCMCIA 0 config base address */
++#define CC_EB_IDE 0x1a800000 /* IDE memory base */
++#define CC_EB_PCMCIA1_MEM 0x1a800000 /* PCMCIA 1 memory base address */
++#define CC_EB_PCMCIA1_IO 0x1aa00000 /* PCMCIA 1 I/O base address */
++#define CC_EB_PCMCIA1_CFG 0x1ac00000 /* PCMCIA 1 config base address */
++#define CC_EB_PROGIF 0x1b000000 /* ProgIF Async/Sync base address */
++
++
++/* Start/busy bit in flashcontrol */
++#define SFLASH_OPCODE 0x000000ff
++#define SFLASH_ACTION 0x00000700
++#define SFLASH_START 0x80000000
++#define SFLASH_BUSY SFLASH_START
++
++/* flashcontrol action codes */
++#define SFLASH_ACT_OPONLY 0x0000 /* Issue opcode only */
++#define SFLASH_ACT_OP1D 0x0100 /* opcode + 1 data byte */
++#define SFLASH_ACT_OP3A 0x0200 /* opcode + 3 address bytes */
++#define SFLASH_ACT_OP3A1D 0x0300 /* opcode + 3 addres & 1 data bytes */
++#define SFLASH_ACT_OP3A4D 0x0400 /* opcode + 3 addres & 4 data bytes */
++#define SFLASH_ACT_OP3A4X4D 0x0500 /* opcode + 3 addres, 4 don't care & 4 data bytes */
++#define SFLASH_ACT_OP3A1X4D 0x0700 /* opcode + 3 addres, 1 don't care & 4 data bytes */
++
++/* flashcontrol action+opcodes for ST flashes */
++#define SFLASH_ST_WREN 0x0006 /* Write Enable */
++#define SFLASH_ST_WRDIS 0x0004 /* Write Disable */
++#define SFLASH_ST_RDSR 0x0105 /* Read Status Register */
++#define SFLASH_ST_WRSR 0x0101 /* Write Status Register */
++#define SFLASH_ST_READ 0x0303 /* Read Data Bytes */
++#define SFLASH_ST_PP 0x0302 /* Page Program */
++#define SFLASH_ST_SE 0x02d8 /* Sector Erase */
++#define SFLASH_ST_BE 0x00c7 /* Bulk Erase */
++#define SFLASH_ST_DP 0x00b9 /* Deep Power-down */
++#define SFLASH_ST_RES 0x03ab /* Read Electronic Signature */
++
++/* Status register bits for ST flashes */
++#define SFLASH_ST_WIP 0x01 /* Write In Progress */
++#define SFLASH_ST_WEL 0x02 /* Write Enable Latch */
++#define SFLASH_ST_BP_MASK 0x1c /* Block Protect */
++#define SFLASH_ST_BP_SHIFT 2
++#define SFLASH_ST_SRWD 0x80 /* Status Register Write Disable */
++
++/* flashcontrol action+opcodes for Atmel flashes */
++#define SFLASH_AT_READ 0x07e8
++#define SFLASH_AT_PAGE_READ 0x07d2
++#define SFLASH_AT_BUF1_READ
++#define SFLASH_AT_BUF2_READ
++#define SFLASH_AT_STATUS 0x01d7
++#define SFLASH_AT_BUF1_WRITE 0x0384
++#define SFLASH_AT_BUF2_WRITE 0x0387
++#define SFLASH_AT_BUF1_ERASE_PROGRAM 0x0283
++#define SFLASH_AT_BUF2_ERASE_PROGRAM 0x0286
++#define SFLASH_AT_BUF1_PROGRAM 0x0288
++#define SFLASH_AT_BUF2_PROGRAM 0x0289
++#define SFLASH_AT_PAGE_ERASE 0x0281
++#define SFLASH_AT_BLOCK_ERASE 0x0250
++#define SFLASH_AT_BUF1_WRITE_ERASE_PROGRAM 0x0382
++#define SFLASH_AT_BUF2_WRITE_ERASE_PROGRAM 0x0385
++#define SFLASH_AT_BUF1_LOAD 0x0253
++#define SFLASH_AT_BUF2_LOAD 0x0255
++#define SFLASH_AT_BUF1_COMPARE 0x0260
++#define SFLASH_AT_BUF2_COMPARE 0x0261
++#define SFLASH_AT_BUF1_REPROGRAM 0x0258
++#define SFLASH_AT_BUF2_REPROGRAM 0x0259
++
++/* Status register bits for Atmel flashes */
++#define SFLASH_AT_READY 0x80
++#define SFLASH_AT_MISMATCH 0x40
++#define SFLASH_AT_ID_MASK 0x38
++#define SFLASH_AT_ID_SHIFT 3
++
++/* OTP regions */
++#define OTP_HW_REGION OTPS_HW_PROTECT
++#define OTP_SW_REGION OTPS_SW_PROTECT
++#define OTP_CID_REGION OTPS_CID_PROTECT
++
++/* OTP regions (Byte offsets from otp size) */
++#define OTP_SWLIM_OFF (-8)
++#define OTP_CIDBASE_OFF 0
++#define OTP_CIDLIM_OFF 8
++
++/* Predefined OTP words (Word offset from otp size) */
++#define OTP_BOUNDARY_OFF (-4)
++#define OTP_HWSIGN_OFF (-3)
++#define OTP_SWSIGN_OFF (-2)
++#define OTP_CIDSIGN_OFF (-1)
++
++#define OTP_CID_OFF 0
++#define OTP_PKG_OFF 1
++#define OTP_FID_OFF 2
++#define OTP_RSV_OFF 3
++#define OTP_LIM_OFF 4
++
++#define OTP_SIGNATURE 0x578a
++#define OTP_MAGIC 0x4e56
++
++/*
++ * These are the UART port assignments, expressed as offsets from the base
++ * register. These assignments should hold for any serial port based on
++ * a 8250, 16450, or 16550(A).
++ */
++
++#define UART_RX 0 /* In: Receive buffer (DLAB=0) */
++#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */
++#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */
++#define UART_IER 1 /* In/Out: Interrupt Enable Register (DLAB=0) */
++#define UART_DLM 1 /* Out: Divisor Latch High (DLAB=1) */
++#define UART_IIR 2 /* In: Interrupt Identity Register */
++#define UART_FCR 2 /* Out: FIFO Control Register */
++#define UART_LCR 3 /* Out: Line Control Register */
++#define UART_MCR 4 /* Out: Modem Control Register */
++#define UART_LSR 5 /* In: Line Status Register */
++#define UART_MSR 6 /* In: Modem Status Register */
++#define UART_SCR 7 /* I/O: Scratch Register */
++#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
++#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */
++#define UART_MCR_OUT2 0x08 /* MCR GPIO out 2 */
++#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
++#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
++#define UART_LSR_RXRDY 0x01 /* Receiver ready */
++#define UART_FCR_FIFO_ENABLE 1 /* FIFO control register bit controlling FIFO enable/disable */
++
++/* Interrupt Enable Register (IER) bits */
++#define UART_IER_EDSSI 8 /* enable modem status interrupt */
++#define UART_IER_ELSI 4 /* enable receiver line status interrupt */
++#define UART_IER_ETBEI 2 /* enable transmitter holding register empty interrupt */
++#define UART_IER_ERBFI 1 /* enable data available interrupt */
++
++#endif /* _SBCHIPC_H */
+diff -urN linux.old/arch/mips/bcm947xx/include/sbconfig.h linux.dev/arch/mips/bcm947xx/include/sbconfig.h
+--- linux.old/arch/mips/bcm947xx/include/sbconfig.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/sbconfig.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,369 @@
++/*
++ * Broadcom SiliconBackplane hardware register definitions.
++ *
++ * 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.
++ *
++ * $Id: sbconfig.h,v 1.1.1.11 2006/02/27 03:43:16 honor Exp $
++ */
++
++#ifndef _SBCONFIG_H
++#define _SBCONFIG_H
++
++/* cpp contortions to concatenate w/arg prescan */
++#ifndef PAD
++#define _PADLINE(line) pad ## line
++#define _XSTR(line) _PADLINE(line)
++#define PAD _XSTR(__LINE__)
++#endif
++
++/*
++ * SiliconBackplane Address Map.
++ * All regions may not exist on all chips.
++ */
++#define SB_SDRAM_BASE 0x00000000 /* Physical SDRAM */
++#define SB_PCI_MEM 0x08000000 /* Host Mode sb2pcitranslation0 (64 MB) */
++#define SB_PCI_MEM_SZ (64 * 1024 * 1024)
++#define SB_PCI_CFG 0x0c000000 /* Host Mode sb2pcitranslation1 (64 MB) */
++#define SB_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */
++#define SB_ENUM_BASE 0x18000000 /* Enumeration space base */
++#define SB_ENUM_LIM 0x18010000 /* Enumeration space limit */
++
++#define SB_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */
++#define SB_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */
++
++#define SB_EXTIF_BASE 0x1f000000 /* External Interface region base address */
++#define SB_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */
++#define SB_FLASH1_SZ 0x00400000 /* MIPS Size of Flash Region 1 */
++
++#define SB_ROM 0x20000000 /* ARM ROM */
++#define SB_SRAM2 0x80000000 /* ARM SRAM Region 2 */
++#define SB_ARM_FLASH1 0xffff0000 /* ARM Flash Region 1 */
++#define SB_ARM_FLASH1_SZ 0x00010000 /* ARM Size of Flash Region 1 */
++
++#define SB_PCI_DMA 0x40000000 /* Client Mode sb2pcitranslation2 (1 GB) */
++#define SB_PCI_DMA_SZ 0x40000000 /* Client Mode sb2pcitranslation2 size in bytes */
++#define SB_PCIE_DMA_L32 0x00000000 /* PCIE Client Mode sb2pcitranslation2
++ * (2 ZettaBytes), low 32 bits
++ */
++#define SB_PCIE_DMA_H32 0x80000000 /* PCIE Client Mode sb2pcitranslation2
++ * (2 ZettaBytes), high 32 bits
++ */
++#define SB_EUART (SB_EXTIF_BASE + 0x00800000)
++#define SB_LED (SB_EXTIF_BASE + 0x00900000)
++
++
++/* enumeration space related defs */
++#define SB_CORE_SIZE 0x1000 /* each core gets 4Kbytes for registers */
++#define SB_MAXCORES ((SB_ENUM_LIM - SB_ENUM_BASE)/SB_CORE_SIZE)
++#define SB_MAXFUNCS 4 /* max. # functions per core */
++#define SBCONFIGOFF 0xf00 /* core sbconfig regs are top 256bytes of regs */
++#define SBCONFIGSIZE 256 /* sizeof (sbconfig_t) */
++
++/* mips address */
++#define SB_EJTAG 0xff200000 /* MIPS EJTAG space (2M) */
++
++/*
++ * Sonics Configuration Space Registers.
++ */
++#define SBIPSFLAG 0x08
++#define SBTPSFLAG 0x18
++#define SBTMERRLOGA 0x48 /* sonics >= 2.3 */
++#define SBTMERRLOG 0x50 /* sonics >= 2.3 */
++#define SBADMATCH3 0x60
++#define SBADMATCH2 0x68
++#define SBADMATCH1 0x70
++#define SBIMSTATE 0x90
++#define SBINTVEC 0x94
++#define SBTMSTATELOW 0x98
++#define SBTMSTATEHIGH 0x9c
++#define SBBWA0 0xa0
++#define SBIMCONFIGLOW 0xa8
++#define SBIMCONFIGHIGH 0xac
++#define SBADMATCH0 0xb0
++#define SBTMCONFIGLOW 0xb8
++#define SBTMCONFIGHIGH 0xbc
++#define SBBCONFIG 0xc0
++#define SBBSTATE 0xc8
++#define SBACTCNFG 0xd8
++#define SBFLAGST 0xe8
++#define SBIDLOW 0xf8
++#define SBIDHIGH 0xfc
++
++/* All the previous registers are above SBCONFIGOFF, but with Sonics 2.3, we have
++ * a few registers *below* that line. I think it would be very confusing to try
++ * and change the value of SBCONFIGOFF, so I'm definig them as absolute offsets here,
++ */
++
++#define SBIMERRLOGA 0xea8
++#define SBIMERRLOG 0xeb0
++#define SBTMPORTCONNID0 0xed8
++#define SBTMPORTLOCK0 0xef8
++
++#ifndef _LANGUAGE_ASSEMBLY
++
++typedef volatile struct _sbconfig {
++ uint32 PAD[2];
++ uint32 sbipsflag; /* initiator port ocp slave flag */
++ uint32 PAD[3];
++ uint32 sbtpsflag; /* target port ocp slave flag */
++ uint32 PAD[11];
++ uint32 sbtmerrloga; /* (sonics >= 2.3) */
++ uint32 PAD;
++ uint32 sbtmerrlog; /* (sonics >= 2.3) */
++ uint32 PAD[3];
++ uint32 sbadmatch3; /* address match3 */
++ uint32 PAD;
++ uint32 sbadmatch2; /* address match2 */
++ uint32 PAD;
++ uint32 sbadmatch1; /* address match1 */
++ uint32 PAD[7];
++ uint32 sbimstate; /* initiator agent state */
++ uint32 sbintvec; /* interrupt mask */
++ uint32 sbtmstatelow; /* target state */
++ uint32 sbtmstatehigh; /* target state */
++ uint32 sbbwa0; /* bandwidth allocation table0 */
++ uint32 PAD;
++ uint32 sbimconfiglow; /* initiator configuration */
++ uint32 sbimconfighigh; /* initiator configuration */
++ uint32 sbadmatch0; /* address match0 */
++ uint32 PAD;
++ uint32 sbtmconfiglow; /* target configuration */
++ uint32 sbtmconfighigh; /* target configuration */
++ uint32 sbbconfig; /* broadcast configuration */
++ uint32 PAD;
++ uint32 sbbstate; /* broadcast state */
++ uint32 PAD[3];
++ uint32 sbactcnfg; /* activate configuration */
++ uint32 PAD[3];
++ uint32 sbflagst; /* current sbflags */
++ uint32 PAD[3];
++ uint32 sbidlow; /* identification */
++ uint32 sbidhigh; /* identification */
++} sbconfig_t;
++
++#endif /* _LANGUAGE_ASSEMBLY */
++
++/* sbipsflag */
++#define SBIPS_INT1_MASK 0x3f /* which sbflags get routed to mips interrupt 1 */
++#define SBIPS_INT1_SHIFT 0
++#define SBIPS_INT2_MASK 0x3f00 /* which sbflags get routed to mips interrupt 2 */
++#define SBIPS_INT2_SHIFT 8
++#define SBIPS_INT3_MASK 0x3f0000 /* which sbflags get routed to mips interrupt 3 */
++#define SBIPS_INT3_SHIFT 16
++#define SBIPS_INT4_MASK 0x3f000000 /* which sbflags get routed to mips interrupt 4 */
++#define SBIPS_INT4_SHIFT 24
++
++/* sbtpsflag */
++#define SBTPS_NUM0_MASK 0x3f /* interrupt sbFlag # generated by this core */
++#define SBTPS_F0EN0 0x40 /* interrupt is always sent on the backplane */
++
++/* sbtmerrlog */
++#define SBTMEL_CM 0x00000007 /* command */
++#define SBTMEL_CI 0x0000ff00 /* connection id */
++#define SBTMEL_EC 0x0f000000 /* error code */
++#define SBTMEL_ME 0x80000000 /* multiple error */
++
++/* sbimstate */
++#define SBIM_PC 0xf /* pipecount */
++#define SBIM_AP_MASK 0x30 /* arbitration policy */
++#define SBIM_AP_BOTH 0x00 /* use both timeslaces and token */
++#define SBIM_AP_TS 0x10 /* use timesliaces only */
++#define SBIM_AP_TK 0x20 /* use token only */
++#define SBIM_AP_RSV 0x30 /* reserved */
++#define SBIM_IBE 0x20000 /* inbanderror */
++#define SBIM_TO 0x40000 /* timeout */
++#define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */
++#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */
++
++/* sbtmstatelow */
++#define SBTML_RESET 0x1 /* reset */
++#define SBTML_REJ_MASK 0x6 /* reject */
++#define SBTML_REJ_SHIFT 1
++#define SBTML_CLK 0x10000 /* clock enable */
++#define SBTML_FGC 0x20000 /* force gated clocks on */
++#define SBTML_FL_MASK 0x3ffc0000 /* core-specific flags */
++#define SBTML_PE 0x40000000 /* pme enable */
++#define SBTML_BE 0x80000000 /* bist enable */
++
++/* sbtmstatehigh */
++#define SBTMH_SERR 0x1 /* serror */
++#define SBTMH_INT 0x2 /* interrupt */
++#define SBTMH_BUSY 0x4 /* busy */
++#define SBTMH_TO 0x00000020 /* timeout (sonics >= 2.3) */
++#define SBTMH_FL_MASK 0x1fff0000 /* core-specific flags */
++#define SBTMH_DMA64 0x10000000 /* supports DMA with 64-bit addresses */
++#define SBTMH_GCR 0x20000000 /* gated clock request */
++#define SBTMH_BISTF 0x40000000 /* bist failed */
++#define SBTMH_BISTD 0x80000000 /* bist done */
++
++
++/* sbbwa0 */
++#define SBBWA_TAB0_MASK 0xffff /* lookup table 0 */
++#define SBBWA_TAB1_MASK 0xffff /* lookup table 1 */
++#define SBBWA_TAB1_SHIFT 16
++
++/* sbimconfiglow */
++#define SBIMCL_STO_MASK 0x7 /* service timeout */
++#define SBIMCL_RTO_MASK 0x70 /* request timeout */
++#define SBIMCL_RTO_SHIFT 4
++#define SBIMCL_CID_MASK 0xff0000 /* connection id */
++#define SBIMCL_CID_SHIFT 16
++
++/* sbimconfighigh */
++#define SBIMCH_IEM_MASK 0xc /* inband error mode */
++#define SBIMCH_TEM_MASK 0x30 /* timeout error mode */
++#define SBIMCH_TEM_SHIFT 4
++#define SBIMCH_BEM_MASK 0xc0 /* bus error mode */
++#define SBIMCH_BEM_SHIFT 6
++
++/* sbadmatch0 */
++#define SBAM_TYPE_MASK 0x3 /* address type */
++#define SBAM_AD64 0x4 /* reserved */
++#define SBAM_ADINT0_MASK 0xf8 /* type0 size */
++#define SBAM_ADINT0_SHIFT 3
++#define SBAM_ADINT1_MASK 0x1f8 /* type1 size */
++#define SBAM_ADINT1_SHIFT 3
++#define SBAM_ADINT2_MASK 0x1f8 /* type2 size */
++#define SBAM_ADINT2_SHIFT 3
++#define SBAM_ADEN 0x400 /* enable */
++#define SBAM_ADNEG 0x800 /* negative decode */
++#define SBAM_BASE0_MASK 0xffffff00 /* type0 base address */
++#define SBAM_BASE0_SHIFT 8
++#define SBAM_BASE1_MASK 0xfffff000 /* type1 base address for the core */
++#define SBAM_BASE1_SHIFT 12
++#define SBAM_BASE2_MASK 0xffff0000 /* type2 base address for the core */
++#define SBAM_BASE2_SHIFT 16
++
++/* sbtmconfiglow */
++#define SBTMCL_CD_MASK 0xff /* clock divide */
++#define SBTMCL_CO_MASK 0xf800 /* clock offset */
++#define SBTMCL_CO_SHIFT 11
++#define SBTMCL_IF_MASK 0xfc0000 /* interrupt flags */
++#define SBTMCL_IF_SHIFT 18
++#define SBTMCL_IM_MASK 0x3000000 /* interrupt mode */
++#define SBTMCL_IM_SHIFT 24
++
++/* sbtmconfighigh */
++#define SBTMCH_BM_MASK 0x3 /* busy mode */
++#define SBTMCH_RM_MASK 0x3 /* retry mode */
++#define SBTMCH_RM_SHIFT 2
++#define SBTMCH_SM_MASK 0x30 /* stop mode */
++#define SBTMCH_SM_SHIFT 4
++#define SBTMCH_EM_MASK 0x300 /* sb error mode */
++#define SBTMCH_EM_SHIFT 8
++#define SBTMCH_IM_MASK 0xc00 /* int mode */
++#define SBTMCH_IM_SHIFT 10
++
++/* sbbconfig */
++#define SBBC_LAT_MASK 0x3 /* sb latency */
++#define SBBC_MAX0_MASK 0xf0000 /* maxccntr0 */
++#define SBBC_MAX0_SHIFT 16
++#define SBBC_MAX1_MASK 0xf00000 /* maxccntr1 */
++#define SBBC_MAX1_SHIFT 20
++
++/* sbbstate */
++#define SBBS_SRD 0x1 /* st reg disable */
++#define SBBS_HRD 0x2 /* hold reg disable */
++
++/* sbidlow */
++#define SBIDL_CS_MASK 0x3 /* config space */
++#define SBIDL_AR_MASK 0x38 /* # address ranges supported */
++#define SBIDL_AR_SHIFT 3
++#define SBIDL_SYNCH 0x40 /* sync */
++#define SBIDL_INIT 0x80 /* initiator */
++#define SBIDL_MINLAT_MASK 0xf00 /* minimum backplane latency */
++#define SBIDL_MINLAT_SHIFT 8
++#define SBIDL_MAXLAT 0xf000 /* maximum backplane latency */
++#define SBIDL_MAXLAT_SHIFT 12
++#define SBIDL_FIRST 0x10000 /* this initiator is first */
++#define SBIDL_CW_MASK 0xc0000 /* cycle counter width */
++#define SBIDL_CW_SHIFT 18
++#define SBIDL_TP_MASK 0xf00000 /* target ports */
++#define SBIDL_TP_SHIFT 20
++#define SBIDL_IP_MASK 0xf000000 /* initiator ports */
++#define SBIDL_IP_SHIFT 24
++#define SBIDL_RV_MASK 0xf0000000 /* sonics backplane revision code */
++#define SBIDL_RV_SHIFT 28
++#define SBIDL_RV_2_2 0x00000000 /* version 2.2 or earlier */
++#define SBIDL_RV_2_3 0x10000000 /* version 2.3 */
++
++/* sbidhigh */
++#define SBIDH_RC_MASK 0x000f /* revision code */
++#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */
++#define SBIDH_RCE_SHIFT 8
++#define SBCOREREV(sbidh) \
++ ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK))
++#define SBIDH_CC_MASK 0x8ff0 /* core code */
++#define SBIDH_CC_SHIFT 4
++#define SBIDH_VC_MASK 0xffff0000 /* vendor code */
++#define SBIDH_VC_SHIFT 16
++
++#define SB_COMMIT 0xfd8 /* update buffered registers value */
++
++/* vendor codes */
++#define SB_VEND_BCM 0x4243 /* Broadcom's SB vendor code */
++
++/* core codes */
++#define SB_NODEV 0x700 /* Invalid coreid */
++#define SB_CC 0x800 /* chipcommon core */
++#define SB_ILINE20 0x801 /* iline20 core */
++#define SB_SDRAM 0x803 /* sdram core */
++#define SB_PCI 0x804 /* pci core */
++#define SB_MIPS 0x805 /* mips core */
++#define SB_ENET 0x806 /* enet mac core */
++#define SB_CODEC 0x807 /* v90 codec core */
++#define SB_USB 0x808 /* usb 1.1 host/device core */
++#define SB_ADSL 0x809 /* ADSL core */
++#define SB_ILINE100 0x80a /* iline100 core */
++#define SB_IPSEC 0x80b /* ipsec core */
++#define SB_PCMCIA 0x80d /* pcmcia core */
++#define SB_SDIOD SB_PCMCIA /* pcmcia core has sdio device */
++#define SB_SOCRAM 0x80e /* internal memory core */
++#define SB_MEMC 0x80f /* memc sdram core */
++#define SB_EXTIF 0x811 /* external interface core */
++#define SB_D11 0x812 /* 802.11 MAC core */
++#define SB_MIPS33 0x816 /* mips3302 core */
++#define SB_USB11H 0x817 /* usb 1.1 host core */
++#define SB_USB11D 0x818 /* usb 1.1 device core */
++#define SB_USB20H 0x819 /* usb 2.0 host core */
++#define SB_USB20D 0x81a /* usb 2.0 device core */
++#define SB_SDIOH 0x81b /* sdio host core */
++#define SB_ROBO 0x81c /* roboswitch core */
++#define SB_ATA100 0x81d /* parallel ATA core */
++#define SB_SATAXOR 0x81e /* serial ATA & XOR DMA core */
++#define SB_GIGETH 0x81f /* gigabit ethernet core */
++#define SB_PCIE 0x820 /* pci express core */
++#define SB_MIMO 0x821 /* MIMO phy core */
++#define SB_SRAMC 0x822 /* SRAM controller core */
++#define SB_MINIMAC 0x823 /* MINI MAC/phy core */
++#define SB_ARM11 0x824 /* ARM 1176 core */
++#define SB_ARM7 0x825 /* ARM 7tdmi core */
++
++#define SB_CC_IDX 0 /* chipc, when present, is always core 0 */
++
++/* Not really related to Silicon Backplane, but a couple of software
++ * conventions for the use the flash space:
++ */
++
++/* Minumum amount of flash we support */
++#define FLASH_MIN 0x00020000 /* Minimum flash size */
++
++/* A boot/binary may have an embedded block that describes its size */
++#define BISZ_OFFSET 0x3e0 /* At this offset into the binary */
++#define BISZ_MAGIC 0x4249535a /* Marked with this value: 'BISZ' */
++#define BISZ_MAGIC_IDX 0 /* Word 0: magic */
++#define BISZ_TXTST_IDX 1 /* 1: text start */
++#define BISZ_TXTEND_IDX 2 /* 2: text start */
++#define BISZ_DATAST_IDX 3 /* 3: text start */
++#define BISZ_DATAEND_IDX 4 /* 4: text start */
++#define BISZ_BSSST_IDX 5 /* 5: text start */
++#define BISZ_BSSEND_IDX 6 /* 6: text start */
++#define BISZ_SIZE 7 /* descriptor size in 32-bit intergers */
++
++#endif /* _SBCONFIG_H */
+diff -urN linux.old/arch/mips/bcm947xx/include/sbextif.h linux.dev/arch/mips/bcm947xx/include/sbextif.h
+--- linux.old/arch/mips/bcm947xx/include/sbextif.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/sbextif.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,243 @@
++/*
++ * Hardware-specific External Interface I/O core definitions
++ * for the BCM47xx family of SiliconBackplane-based chips.
++ *
++ * The External Interface core supports a total of three external chip selects
++ * supporting external interfaces. One of the external chip selects is
++ * used for Flash, one is used for PCMCIA, and the other may be
++ * programmed to support either a synchronous interface or an
++ * asynchronous interface. The asynchronous interface can be used to
++ * support external devices such as UARTs and the BCM2019 Bluetooth
++ * baseband processor.
++ * The external interface core also contains 2 on-chip 16550 UARTs, clock
++ * frequency control, a watchdog interrupt timer, and a GPIO interface.
++ *
++ * 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.
++ *
++ * $Id: sbextif.h,v 1.1.1.8 2006/02/27 03:43:16 honor Exp $
++ */
++
++#ifndef _SBEXTIF_H
++#define _SBEXTIF_H
++
++/* external interface address space */
++#define EXTIF_PCMCIA_MEMBASE(x) (x)
++#define EXTIF_PCMCIA_IOBASE(x) ((x) + 0x100000)
++#define EXTIF_PCMCIA_CFGBASE(x) ((x) + 0x200000)
++#define EXTIF_CFGIF_BASE(x) ((x) + 0x800000)
++#define EXTIF_FLASH_BASE(x) ((x) + 0xc00000)
++
++/* cpp contortions to concatenate w/arg prescan */
++#ifndef PAD
++#define _PADLINE(line) pad ## line
++#define _XSTR(line) _PADLINE(line)
++#define PAD _XSTR(__LINE__)
++#endif /* PAD */
++
++/*
++ * The multiple instances of output and output enable registers
++ * are present to allow driver software for multiple cores to control
++ * gpio outputs without needing to share a single register pair.
++ */
++struct gpiouser {
++ uint32 out;
++ uint32 outen;
++};
++#define NGPIOUSER 5
++
++typedef volatile struct {
++ uint32 corecontrol;
++ uint32 extstatus;
++ uint32 PAD[2];
++
++ /* pcmcia control registers */
++ uint32 pcmcia_config;
++ uint32 pcmcia_memwait;
++ uint32 pcmcia_attrwait;
++ uint32 pcmcia_iowait;
++
++ /* programmable interface control registers */
++ uint32 prog_config;
++ uint32 prog_waitcount;
++
++ /* flash control registers */
++ uint32 flash_config;
++ uint32 flash_waitcount;
++ uint32 PAD[4];
++
++ uint32 watchdog;
++
++ /* clock control */
++ uint32 clockcontrol_n;
++ uint32 clockcontrol_sb;
++ uint32 clockcontrol_pci;
++ uint32 clockcontrol_mii;
++ uint32 PAD[3];
++
++ /* gpio */
++ uint32 gpioin;
++ struct gpiouser gpio[NGPIOUSER];
++ uint32 PAD;
++ uint32 ejtagouten;
++ uint32 gpiointpolarity;
++ uint32 gpiointmask;
++ uint32 PAD[153];
++
++ uint8 uartdata;
++ uint8 PAD[3];
++ uint8 uartimer;
++ uint8 PAD[3];
++ uint8 uartfcr;
++ uint8 PAD[3];
++ uint8 uartlcr;
++ uint8 PAD[3];
++ uint8 uartmcr;
++ uint8 PAD[3];
++ uint8 uartlsr;
++ uint8 PAD[3];
++ uint8 uartmsr;
++ uint8 PAD[3];
++ uint8 uartscratch;
++ uint8 PAD[3];
++} extifregs_t;
++
++/* corecontrol */
++#define CC_UE (1 << 0) /* uart enable */
++
++/* extstatus */
++#define ES_EM (1 << 0) /* endian mode (ro) */
++#define ES_EI (1 << 1) /* external interrupt pin (ro) */
++#define ES_GI (1 << 2) /* gpio interrupt pin (ro) */
++
++/* gpio bit mask */
++#define GPIO_BIT0 (1 << 0)
++#define GPIO_BIT1 (1 << 1)
++#define GPIO_BIT2 (1 << 2)
++#define GPIO_BIT3 (1 << 3)
++#define GPIO_BIT4 (1 << 4)
++#define GPIO_BIT5 (1 << 5)
++#define GPIO_BIT6 (1 << 6)
++#define GPIO_BIT7 (1 << 7)
++
++
++/* pcmcia/prog/flash_config */
++#define CF_EN (1 << 0) /* enable */
++#define CF_EM_MASK 0xe /* mode */
++#define CF_EM_SHIFT 1
++#define CF_EM_FLASH 0x0 /* flash/asynchronous mode */
++#define CF_EM_SYNC 0x2 /* synchronous mode */
++#define CF_EM_PCMCIA 0x4 /* pcmcia mode */
++#define CF_DS (1 << 4) /* destsize: 0=8bit, 1=16bit */
++#define CF_BS (1 << 5) /* byteswap */
++#define CF_CD_MASK 0xc0 /* clock divider */
++#define CF_CD_SHIFT 6
++#define CF_CD_DIV2 0x0 /* backplane/2 */
++#define CF_CD_DIV3 0x40 /* backplane/3 */
++#define CF_CD_DIV4 0x80 /* backplane/4 */
++#define CF_CE (1 << 8) /* clock enable */
++#define CF_SB (1 << 9) /* size/bytestrobe (synch only) */
++
++/* pcmcia_memwait */
++#define PM_W0_MASK 0x3f /* waitcount0 */
++#define PM_W1_MASK 0x1f00 /* waitcount1 */
++#define PM_W1_SHIFT 8
++#define PM_W2_MASK 0x1f0000 /* waitcount2 */
++#define PM_W2_SHIFT 16
++#define PM_W3_MASK 0x1f000000 /* waitcount3 */
++#define PM_W3_SHIFT 24
++
++/* pcmcia_attrwait */
++#define PA_W0_MASK 0x3f /* waitcount0 */
++#define PA_W1_MASK 0x1f00 /* waitcount1 */
++#define PA_W1_SHIFT 8
++#define PA_W2_MASK 0x1f0000 /* waitcount2 */
++#define PA_W2_SHIFT 16
++#define PA_W3_MASK 0x1f000000 /* waitcount3 */
++#define PA_W3_SHIFT 24
++
++/* pcmcia_iowait */
++#define PI_W0_MASK 0x3f /* waitcount0 */
++#define PI_W1_MASK 0x1f00 /* waitcount1 */
++#define PI_W1_SHIFT 8
++#define PI_W2_MASK 0x1f0000 /* waitcount2 */
++#define PI_W2_SHIFT 16
++#define PI_W3_MASK 0x1f000000 /* waitcount3 */
++#define PI_W3_SHIFT 24
++
++/* prog_waitcount */
++#define PW_W0_MASK 0x0000001f /* waitcount0 */
++#define PW_W1_MASK 0x00001f00 /* waitcount1 */
++#define PW_W1_SHIFT 8
++#define PW_W2_MASK 0x001f0000 /* waitcount2 */
++#define PW_W2_SHIFT 16
++#define PW_W3_MASK 0x1f000000 /* waitcount3 */
++#define PW_W3_SHIFT 24
++
++#define PW_W0 0x0000000c
++#define PW_W1 0x00000a00
++#define PW_W2 0x00020000
++#define PW_W3 0x01000000
++
++/* flash_waitcount */
++#define FW_W0_MASK 0x1f /* waitcount0 */
++#define FW_W1_MASK 0x1f00 /* waitcount1 */
++#define FW_W1_SHIFT 8
++#define FW_W2_MASK 0x1f0000 /* waitcount2 */
++#define FW_W2_SHIFT 16
++#define FW_W3_MASK 0x1f000000 /* waitcount3 */
++#define FW_W3_SHIFT 24
++
++/* watchdog */
++#define WATCHDOG_CLOCK 48000000 /* Hz */
++
++/* clockcontrol_n */
++#define CN_N1_MASK 0x3f /* n1 control */
++#define CN_N2_MASK 0x3f00 /* n2 control */
++#define CN_N2_SHIFT 8
++
++/* clockcontrol_sb/pci/mii */
++#define CC_M1_MASK 0x3f /* m1 control */
++#define CC_M2_MASK 0x3f00 /* m2 control */
++#define CC_M2_SHIFT 8
++#define CC_M3_MASK 0x3f0000 /* m3 control */
++#define CC_M3_SHIFT 16
++#define CC_MC_MASK 0x1f000000 /* mux control */
++#define CC_MC_SHIFT 24
++
++/* Clock control default values */
++#define CC_DEF_N 0x0009 /* Default values for bcm4710 */
++#define CC_DEF_100 0x04020011
++#define CC_DEF_33 0x11030011
++#define CC_DEF_25 0x11050011
++
++/* Clock control values for 125Mhz */
++#define CC_125_N 0x0802
++#define CC_125_M 0x04020009
++#define CC_125_M25 0x11090009
++#define CC_125_M33 0x11090005
++
++/* Clock control magic field values */
++#define CC_F6_2 0x02 /* A factor of 2 in */
++#define CC_F6_3 0x03 /* 6-bit fields like */
++#define CC_F6_4 0x05 /* N1, M1 or M3 */
++#define CC_F6_5 0x09
++#define CC_F6_6 0x11
++#define CC_F6_7 0x21
++
++#define CC_F5_BIAS 5 /* 5-bit fields get this added */
++
++#define CC_MC_BYPASS 0x08
++#define CC_MC_M1 0x04
++#define CC_MC_M1M2 0x02
++#define CC_MC_M1M2M3 0x01
++#define CC_MC_M1M3 0x11
++
++#define CC_CLOCK_BASE 24000000 /* Half the clock freq. in the 4710 */
++
++#endif /* _SBEXTIF_H */
+diff -urN linux.old/arch/mips/bcm947xx/include/sbhndmips.h linux.dev/arch/mips/bcm947xx/include/sbhndmips.h
+--- linux.old/arch/mips/bcm947xx/include/sbhndmips.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/sbhndmips.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,47 @@
++/*
++ * Broadcom SiliconBackplane MIPS definitions
++ *
++ * SB MIPS cores are custom MIPS32 processors with SiliconBackplane
++ * OCP interfaces. The CP0 processor ID is 0x00024000, where bits
++ * 23:16 mean Broadcom and bits 15:8 mean a MIPS core with an OCP
++ * interface. The core revision is stored in the SB ID register in SB
++ * configuration space.
++ *
++ * 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.
++ *
++ * $Id: sbhndmips.h,v 1.1.1.1 2006/02/27 03:43:16 honor Exp $
++ */
++
++#ifndef _sbhndmips_h_
++#define _sbhndmips_h_
++
++#include <mipsinc.h>
++
++#ifndef _LANGUAGE_ASSEMBLY
++
++/* cpp contortions to concatenate w/arg prescan */
++#ifndef PAD
++#define _PADLINE(line) pad ## line
++#define _XSTR(line) _PADLINE(line)
++#define PAD _XSTR(__LINE__)
++#endif /* PAD */
++
++typedef volatile struct {
++ uint32 corecontrol;
++ uint32 PAD[2];
++ uint32 biststatus;
++ uint32 PAD[4];
++ uint32 intstatus;
++ uint32 intmask;
++ uint32 timer;
++} mipsregs_t;
++
++#endif /* _LANGUAGE_ASSEMBLY */
++
++#endif /* _sbhndmips_h_ */
+diff -urN linux.old/arch/mips/bcm947xx/include/sbmemc.h linux.dev/arch/mips/bcm947xx/include/sbmemc.h
+--- linux.old/arch/mips/bcm947xx/include/sbmemc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/sbmemc.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,147 @@
++/*
++ * BCM47XX Sonics SiliconBackplane DDR/SDRAM controller core hardware definitions.
++ *
++ * 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.
++ *
++ * $Id: sbmemc.h,v 1.6 2006/03/02 12:33:44 honor Exp $
++ */
++
++#ifndef _SBMEMC_H
++#define _SBMEMC_H
++
++#ifdef _LANGUAGE_ASSEMBLY
++
++#define MEMC_CONTROL 0x00
++#define MEMC_CONFIG 0x04
++#define MEMC_REFRESH 0x08
++#define MEMC_BISTSTAT 0x0c
++#define MEMC_MODEBUF 0x10
++#define MEMC_BKCLS 0x14
++#define MEMC_PRIORINV 0x18
++#define MEMC_DRAMTIM 0x1c
++#define MEMC_INTSTAT 0x20
++#define MEMC_INTMASK 0x24
++#define MEMC_INTINFO 0x28
++#define MEMC_NCDLCTL 0x30
++#define MEMC_RDNCDLCOR 0x34
++#define MEMC_WRNCDLCOR 0x38
++#define MEMC_MISCDLYCTL 0x3c
++#define MEMC_DQSGATENCDL 0x40
++#define MEMC_SPARE 0x44
++#define MEMC_TPADDR 0x48
++#define MEMC_TPDATA 0x4c
++#define MEMC_BARRIER 0x50
++#define MEMC_CORE 0x54
++
++#else /* !_LANGUAGE_ASSEMBLY */
++
++/* Sonics side: MEMC core registers */
++typedef volatile struct sbmemcregs {
++ uint32 control;
++ uint32 config;
++ uint32 refresh;
++ uint32 biststat;
++ uint32 modebuf;
++ uint32 bkcls;
++ uint32 priorinv;
++ uint32 dramtim;
++ uint32 intstat;
++ uint32 intmask;
++ uint32 intinfo;
++ uint32 reserved1;
++ uint32 ncdlctl;
++ uint32 rdncdlcor;
++ uint32 wrncdlcor;
++ uint32 miscdlyctl;
++ uint32 dqsgatencdl;
++ uint32 spare;
++ uint32 tpaddr;
++ uint32 tpdata;
++ uint32 barrier;
++ uint32 core;
++} sbmemcregs_t;
++
++#endif /* _LANGUAGE_ASSEMBLY */
++
++/* MEMC Core Init values (OCP ID 0x80f) */
++
++/* For sdr: */
++#define MEMC_SD_CONFIG_INIT 0x00048000
++#define MEMC_SD_DRAMTIM2_INIT 0x000754d8
++#define MEMC_SD_DRAMTIM3_INIT 0x000754da
++#define MEMC_SD_RDNCDLCOR_INIT 0x00000000
++#define MEMC_SD_WRNCDLCOR_INIT 0x49351200
++#define MEMC_SD1_WRNCDLCOR_INIT 0x14500200 /* For corerev 1 (4712) */
++#define MEMC_SD_MISCDLYCTL_INIT 0x00061c1b
++#define MEMC_SD1_MISCDLYCTL_INIT 0x00021416 /* For corerev 1 (4712) */
++#define MEMC_SD_CONTROL_INIT0 0x00000002
++#define MEMC_SD_CONTROL_INIT1 0x00000008
++#define MEMC_SD_CONTROL_INIT2 0x00000004
++#define MEMC_SD_CONTROL_INIT3 0x00000010
++#define MEMC_SD_CONTROL_INIT4 0x00000001
++#define MEMC_SD_MODEBUF_INIT 0x00000000
++#define MEMC_SD_REFRESH_INIT 0x0000840f
++
++
++/* This is for SDRM8X8X4 */
++#define MEMC_SDR_INIT 0x0008
++#define MEMC_SDR_MODE 0x32
++#define MEMC_SDR_NCDL 0x00020032
++#define MEMC_SDR1_NCDL 0x0002020f /* For corerev 1 (4712) */
++
++/* For ddr: */
++#define MEMC_CONFIG_INIT 0x00048000
++#define MEMC_DRAMTIM2_INIT 0x000754d8
++#define MEMC_DRAMTIM25_INIT 0x000754d9
++#define MEMC_RDNCDLCOR_INIT 0x00000000
++#define MEMC_RDNCDLCOR_SIMINIT 0xf6f6f6f6 /* For hdl sim */
++#define MEMC_WRNCDLCOR_INIT 0x49351200
++#define MEMC_1_WRNCDLCOR_INIT 0x14500200
++#define MEMC_DQSGATENCDL_INIT 0x00030000
++#define MEMC_MISCDLYCTL_INIT 0x21061c1b
++#define MEMC_1_MISCDLYCTL_INIT 0x21021400
++#define MEMC_NCDLCTL_INIT 0x00002001
++#define MEMC_CONTROL_INIT0 0x00000002
++#define MEMC_CONTROL_INIT1 0x00000008
++#define MEMC_MODEBUF_INIT0 0x00004000
++#define MEMC_CONTROL_INIT2 0x00000010
++#define MEMC_MODEBUF_INIT1 0x00000100
++#define MEMC_CONTROL_INIT3 0x00000010
++#define MEMC_CONTROL_INIT4 0x00000008
++#define MEMC_REFRESH_INIT 0x0000840f
++#define MEMC_CONTROL_INIT5 0x00000004
++#define MEMC_MODEBUF_INIT2 0x00000000
++#define MEMC_CONTROL_INIT6 0x00000010
++#define MEMC_CONTROL_INIT7 0x00000001
++
++
++/* This is for DDRM16X16X2 */
++#define MEMC_DDR_INIT 0x0009
++#define MEMC_DDR_MODE 0x62
++#define MEMC_DDR_NCDL 0x0005050a
++#define MEMC_DDR1_NCDL 0x00000a0a /* For corerev 1 (4712) */
++
++/* mask for sdr/ddr calibration registers */
++#define MEMC_RDNCDLCOR_RD_MASK 0x000000ff
++#define MEMC_WRNCDLCOR_WR_MASK 0x000000ff
++#define MEMC_DQSGATENCDL_G_MASK 0x000000ff
++
++/* masks for miscdlyctl registers */
++#define MEMC_MISC_SM_MASK 0x30000000
++#define MEMC_MISC_SM_SHIFT 28
++#define MEMC_MISC_SD_MASK 0x0f000000
++#define MEMC_MISC_SD_SHIFT 24
++
++/* hw threshhold for calculating wr/rd for sdr memc */
++#define MEMC_CD_THRESHOLD 128
++
++/* Low bit of init register says if memc is ddr or sdr */
++#define MEMC_CONFIG_DDR 0x00000001
++
++#endif /* _SBMEMC_H */
+diff -urN linux.old/arch/mips/bcm947xx/include/sbpcie.h linux.dev/arch/mips/bcm947xx/include/sbpcie.h
+--- linux.old/arch/mips/bcm947xx/include/sbpcie.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/sbpcie.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,200 @@
++/*
++ * BCM43XX SiliconBackplane PCIE core hardware definitions.
++ *
++ * 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.
++ *
++ * $Id: sbpcie.h,v 1.1.1.2 2006/02/27 03:43:16 honor Exp $
++ */
++
++#ifndef _SBPCIE_H
++#define _SBPCIE_H
++
++/* cpp contortions to concatenate w/arg prescan */
++#ifndef PAD
++#define _PADLINE(line) pad ## line
++#define _XSTR(line) _PADLINE(line)
++#define PAD _XSTR(__LINE__)
++#endif
++
++/* PCIE Enumeration space offsets */
++#define PCIE_CORE_CONFIG_OFFSET 0x0
++#define PCIE_FUNC0_CONFIG_OFFSET 0x400
++#define PCIE_FUNC1_CONFIG_OFFSET 0x500
++#define PCIE_FUNC2_CONFIG_OFFSET 0x600
++#define PCIE_FUNC3_CONFIG_OFFSET 0x700
++#define PCIE_SPROM_SHADOW_OFFSET 0x800
++#define PCIE_SBCONFIG_OFFSET 0xE00
++
++/* PCIE Bar0 Address Mapping. Each function maps 16KB config space */
++#define PCIE_DEV_BAR0_SIZE 0x4000
++#define PCIE_BAR0_WINMAPCORE_OFFSET 0x0
++#define PCIE_BAR0_EXTSPROM_OFFSET 0x1000
++#define PCIE_BAR0_PCIECORE_OFFSET 0x2000
++#define PCIE_BAR0_CCCOREREG_OFFSET 0x3000
++
++/* SB side: PCIE core and host control registers */
++typedef struct sbpcieregs {
++ uint32 PAD[3];
++ uint32 biststatus; /* bist Status: 0x00C */
++ uint32 PAD[6];
++ uint32 sbtopcimailbox; /* sb to pcie mailbox: 0x028 */
++ uint32 PAD[54];
++ uint32 sbtopcie0; /* sb to pcie translation 0: 0x100 */
++ uint32 sbtopcie1; /* sb to pcie translation 1: 0x104 */
++ uint32 sbtopcie2; /* sb to pcie translation 2: 0x108 */
++ uint32 PAD[4];
++
++ /* pcie core supports in direct access to config space */
++ uint32 configaddr; /* pcie config space access: Address field: 0x120 */
++ uint32 configdata; /* pcie config space access: Data field: 0x124 */
++
++ /* mdio access to serdes */
++ uint32 mdiocontrol; /* controls the mdio access: 0x128 */
++ uint32 mdiodata; /* Data to the mdio access: 0x12c */
++
++ /* pcie protocol phy/dllp/tlp register access mechanism */
++ uint32 pcieaddr; /* address of the internal registeru: 0x130 */
++ uint32 pciedata; /* Data to/from the internal regsiter: 0x134 */
++
++ uint32 PAD[434];
++ uint16 sprom[36]; /* SPROM shadow Area */
++} sbpcieregs_t;
++
++/* SB to PCIE translation masks */
++#define SBTOPCIE0_MASK 0xfc000000
++#define SBTOPCIE1_MASK 0xfc000000
++#define SBTOPCIE2_MASK 0xc0000000
++
++/* Access type bits (0:1) */
++#define SBTOPCIE_MEM 0
++#define SBTOPCIE_IO 1
++#define SBTOPCIE_CFG0 2
++#define SBTOPCIE_CFG1 3
++
++/* Prefetch enable bit 2 */
++#define SBTOPCIE_PF 4
++
++/* Write Burst enable for memory write bit 3 */
++#define SBTOPCIE_WR_BURST 8
++
++/* config access */
++#define CONFIGADDR_FUNC_MASK 0x7000
++#define CONFIGADDR_FUNC_SHF 12
++#define CONFIGADDR_REG_MASK 0x0FFF
++#define CONFIGADDR_REG_SHF 0
++
++/* PCIE protocol regs Indirect Address */
++#define PCIEADDR_PROT_MASK 0x300
++#define PCIEADDR_PROT_SHF 8
++#define PCIEADDR_PL_TLP 0
++#define PCIEADDR_PL_DLLP 1
++#define PCIEADDR_PL_PLP 2
++
++/* PCIE protocol PHY diagnostic registers */
++#define PCIE_PLP_MODEREG 0x200 /* Mode */
++#define PCIE_PLP_STATUSREG 0x204 /* Status */
++#define PCIE_PLP_LTSSMCTRLREG 0x208 /* LTSSM control */
++#define PCIE_PLP_LTLINKNUMREG 0x20c /* Link Training Link number */
++#define PCIE_PLP_LTLANENUMREG 0x210 /* Link Training Lane number */
++#define PCIE_PLP_LTNFTSREG 0x214 /* Link Training N_FTS */
++#define PCIE_PLP_ATTNREG 0x218 /* Attention */
++#define PCIE_PLP_ATTNMASKREG 0x21C /* Attention Mask */
++#define PCIE_PLP_RXERRCTR 0x220 /* Rx Error */
++#define PCIE_PLP_RXFRMERRCTR 0x224 /* Rx Framing Error */
++#define PCIE_PLP_RXERRTHRESHREG 0x228 /* Rx Error threshold */
++#define PCIE_PLP_TESTCTRLREG 0x22C /* Test Control reg */
++#define PCIE_PLP_SERDESCTRLOVRDREG 0x230 /* SERDES Control Override */
++#define PCIE_PLP_TIMINGOVRDREG 0x234 /* Timing param override */
++#define PCIE_PLP_RXTXSMDIAGREG 0x238 /* RXTX State Machine Diag */
++#define PCIE_PLP_LTSSMDIAGREG 0x23C /* LTSSM State Machine Diag */
++
++/* PCIE protocol DLLP diagnostic registers */
++#define PCIE_DLLP_LCREG 0x100 /* Link Control */
++#define PCIE_DLLP_LSREG 0x104 /* Link Status */
++#define PCIE_DLLP_LAREG 0x108 /* Link Attention */
++#define PCIE_DLLP_LAMASKREG 0x10C /* Link Attention Mask */
++#define PCIE_DLLP_NEXTTXSEQNUMREG 0x110 /* Next Tx Seq Num */
++#define PCIE_DLLP_ACKEDTXSEQNUMREG 0x114 /* Acked Tx Seq Num */
++#define PCIE_DLLP_PURGEDTXSEQNUMREG 0x118 /* Purged Tx Seq Num */
++#define PCIE_DLLP_RXSEQNUMREG 0x11C /* Rx Sequence Number */
++#define PCIE_DLLP_LRREG 0x120 /* Link Replay */
++#define PCIE_DLLP_LACKTOREG 0x124 /* Link Ack Timeout */
++#define PCIE_DLLP_PMTHRESHREG 0x128 /* Power Management Threshold */
++#define PCIE_DLLP_RTRYWPREG 0x12C /* Retry buffer write ptr */
++#define PCIE_DLLP_RTRYRPREG 0x130 /* Retry buffer Read ptr */
++#define PCIE_DLLP_RTRYPPREG 0x134 /* Retry buffer Purged ptr */
++#define PCIE_DLLP_RTRRWREG 0x138 /* Retry buffer Read/Write */
++#define PCIE_DLLP_ECTHRESHREG 0x13C /* Error Count Threshold */
++#define PCIE_DLLP_TLPERRCTRREG 0x140 /* TLP Error Counter */
++#define PCIE_DLLP_ERRCTRREG 0x144 /* Error Counter */
++#define PCIE_DLLP_NAKRXCTRREG 0x148 /* NAK Received Counter */
++#define PCIE_DLLP_TESTREG 0x14C /* Test */
++#define PCIE_DLLP_PKTBIST 0x150 /* Packet BIST */
++
++/* PCIE protocol TLP diagnostic registers */
++#define PCIE_TLP_CONFIGREG 0x000 /* Configuration */
++#define PCIE_TLP_WORKAROUNDSREG 0x004 /* TLP Workarounds */
++#define PCIE_TLP_WRDMAUPPER 0x010 /* Write DMA Upper Address */
++#define PCIE_TLP_WRDMALOWER 0x014 /* Write DMA Lower Address */
++#define PCIE_TLP_WRDMAREQ_LBEREG 0x018 /* Write DMA Len/ByteEn Req */
++#define PCIE_TLP_RDDMAUPPER 0x01C /* Read DMA Upper Address */
++#define PCIE_TLP_RDDMALOWER 0x020 /* Read DMA Lower Address */
++#define PCIE_TLP_RDDMALENREG 0x024 /* Read DMA Len Req */
++#define PCIE_TLP_MSIDMAUPPER 0x028 /* MSI DMA Upper Address */
++#define PCIE_TLP_MSIDMALOWER 0x02C /* MSI DMA Lower Address */
++#define PCIE_TLP_MSIDMALENREG 0x030 /* MSI DMA Len Req */
++#define PCIE_TLP_SLVREQLENREG 0x034 /* Slave Request Len */
++#define PCIE_TLP_FCINPUTSREQ 0x038 /* Flow Control Inputs */
++#define PCIE_TLP_TXSMGRSREQ 0x03C /* Tx StateMachine and Gated Req */
++#define PCIE_TLP_ADRACKCNTARBLEN 0x040 /* Address Ack XferCnt and ARB Len */
++#define PCIE_TLP_DMACPLHDR0 0x044 /* DMA Completion Hdr 0 */
++#define PCIE_TLP_DMACPLHDR1 0x048 /* DMA Completion Hdr 1 */
++#define PCIE_TLP_DMACPLHDR2 0x04C /* DMA Completion Hdr 2 */
++#define PCIE_TLP_DMACPLMISC0 0x050 /* DMA Completion Misc0 */
++#define PCIE_TLP_DMACPLMISC1 0x054 /* DMA Completion Misc1 */
++#define PCIE_TLP_DMACPLMISC2 0x058 /* DMA Completion Misc2 */
++#define PCIE_TLP_SPTCTRLLEN 0x05C /* Split Controller Req len */
++#define PCIE_TLP_SPTCTRLMSIC0 0x060 /* Split Controller Misc 0 */
++#define PCIE_TLP_SPTCTRLMSIC1 0x064 /* Split Controller Misc 1 */
++#define PCIE_TLP_BUSDEVFUNC 0x068 /* Bus/Device/Func */
++#define PCIE_TLP_RESETCTR 0x06C /* Reset Counter */
++#define PCIE_TLP_RTRYBUF 0x070 /* Retry Buffer value */
++#define PCIE_TLP_TGTDEBUG1 0x074 /* Target Debug Reg1 */
++#define PCIE_TLP_TGTDEBUG2 0x078 /* Target Debug Reg2 */
++#define PCIE_TLP_TGTDEBUG3 0x07C /* Target Debug Reg3 */
++#define PCIE_TLP_TGTDEBUG4 0x080 /* Target Debug Reg4 */
++
++/* MDIO control */
++#define MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */
++#define MDIOCTL_DIVISOR_VAL 0x2
++#define MDIOCTL_PREAM_EN 0x80 /* Enable preamble sequnce */
++#define MDIOCTL_ACCESS_DONE 0x100 /* Tranaction complete */
++
++/* MDIO Data */
++#define MDIODATA_MASK 0x0000ffff /* data 2 bytes */
++#define MDIODATA_TA 0x00020000 /* Turnaround */
++#define MDIODATA_REGADDR_SHF 18 /* Regaddr shift */
++#define MDIODATA_REGADDR_MASK 0x003c0000 /* Regaddr Mask */
++#define MDIODATA_DEVADDR_SHF 22 /* Physmedia devaddr shift */
++#define MDIODATA_DEVADDR_MASK 0x0fc00000 /* Physmedia devaddr Mask */
++#define MDIODATA_WRITE 0x10000000 /* write Transaction */
++#define MDIODATA_READ 0x20000000 /* Read Transaction */
++#define MDIODATA_START 0x40000000 /* start of Transaction */
++
++/* MDIO devices (SERDES modules) */
++#define MDIODATA_DEV_PLL 0x1d /* SERDES PLL Dev */
++#define MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */
++#define MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */
++
++/* SERDES registers */
++#define SERDES_RX_TIMER1 2 /* Rx Timer1 */
++#define SERDES_RX_CDR 6 /* CDR */
++#define SERDES_RX_CDRBW 7 /* CDR BW */
++
++#endif /* _SBPCIE_H */
+diff -urN linux.old/arch/mips/bcm947xx/include/sbpci.h linux.dev/arch/mips/bcm947xx/include/sbpci.h
+--- linux.old/arch/mips/bcm947xx/include/sbpci.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/sbpci.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,114 @@
++/*
++ * HND SiliconBackplane PCI core hardware definitions.
++ *
++ * 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.
++ *
++ * $Id: sbpci.h,v 1.1.1.11 2006/02/27 03:43:16 honor Exp $
++ */
++
++#ifndef _sbpci_h_
++#define _sbpci_h_
++
++#ifndef _LANGUAGE_ASSEMBLY
++
++/* cpp contortions to concatenate w/arg prescan */
++#ifndef PAD
++#define _PADLINE(line) pad ## line
++#define _XSTR(line) _PADLINE(line)
++#define PAD _XSTR(__LINE__)
++#endif
++
++/* Sonics side: PCI core and host control registers */
++typedef struct sbpciregs {
++ uint32 control; /* PCI control */
++ uint32 PAD[3];
++ uint32 arbcontrol; /* PCI arbiter control */
++ uint32 PAD[3];
++ uint32 intstatus; /* Interrupt status */
++ uint32 intmask; /* Interrupt mask */
++ uint32 sbtopcimailbox; /* Sonics to PCI mailbox */
++ uint32 PAD[9];
++ uint32 bcastaddr; /* Sonics broadcast address */
++ uint32 bcastdata; /* Sonics broadcast data */
++ uint32 PAD[2];
++ uint32 gpioin; /* ro: gpio input (>=rev2) */
++ uint32 gpioout; /* rw: gpio output (>=rev2) */
++ uint32 gpioouten; /* rw: gpio output enable (>= rev2) */
++ uint32 gpiocontrol; /* rw: gpio control (>= rev2) */
++ uint32 PAD[36];
++ uint32 sbtopci0; /* Sonics to PCI translation 0 */
++ uint32 sbtopci1; /* Sonics to PCI translation 1 */
++ uint32 sbtopci2; /* Sonics to PCI translation 2 */
++ uint32 PAD[189];
++ uint32 pcicfg[4][64]; /* 0x400 - 0x7FF, PCI Cfg Space (>=rev8) */
++ uint16 sprom[36]; /* SPROM shadow Area */
++ uint32 PAD[46];
++} sbpciregs_t;
++
++#endif /* _LANGUAGE_ASSEMBLY */
++
++/* PCI control */
++#define PCI_RST_OE 0x01 /* When set, drives PCI_RESET out to pin */
++#define PCI_RST 0x02 /* Value driven out to pin */
++#define PCI_CLK_OE 0x04 /* When set, drives clock as gated by PCI_CLK out to pin */
++#define PCI_CLK 0x08 /* Gate for clock driven out to pin */
++
++/* PCI arbiter control */
++#define PCI_INT_ARB 0x01 /* When set, use an internal arbiter */
++#define PCI_EXT_ARB 0x02 /* When set, use an external arbiter */
++/* ParkID - for PCI corerev >= 8 */
++#define PCI_PARKID_MASK 0x1c /* Selects which agent is parked on an idle bus */
++#define PCI_PARKID_SHIFT 2
++#define PCI_PARKID_EXT0 0 /* External master 0 */
++#define PCI_PARKID_EXT1 1 /* External master 1 */
++#define PCI_PARKID_EXT2 2 /* External master 2 */
++#define PCI_PARKID_INT 3 /* Internal master */
++#define PCI_PARKID_LAST 4 /* Last active master */
++
++/* Interrupt status/mask */
++#define PCI_INTA 0x01 /* PCI INTA# is asserted */
++#define PCI_INTB 0x02 /* PCI INTB# is asserted */
++#define PCI_SERR 0x04 /* PCI SERR# has been asserted (write one to clear) */
++#define PCI_PERR 0x08 /* PCI PERR# has been asserted (write one to clear) */
++#define PCI_PME 0x10 /* PCI PME# is asserted */
++
++/* (General) PCI/SB mailbox interrupts, two bits per pci function */
++#define MAILBOX_F0_0 0x100 /* function 0, int 0 */
++#define MAILBOX_F0_1 0x200 /* function 0, int 1 */
++#define MAILBOX_F1_0 0x400 /* function 1, int 0 */
++#define MAILBOX_F1_1 0x800 /* function 1, int 1 */
++#define MAILBOX_F2_0 0x1000 /* function 2, int 0 */
++#define MAILBOX_F2_1 0x2000 /* function 2, int 1 */
++#define MAILBOX_F3_0 0x4000 /* function 3, int 0 */
++#define MAILBOX_F3_1 0x8000 /* function 3, int 1 */
++
++/* Sonics broadcast address */
++#define BCAST_ADDR_MASK 0xff /* Broadcast register address */
++
++/* Sonics to PCI translation types */
++#define SBTOPCI0_MASK 0xfc000000
++#define SBTOPCI1_MASK 0xfc000000
++#define SBTOPCI2_MASK 0xc0000000
++#define SBTOPCI_MEM 0
++#define SBTOPCI_IO 1
++#define SBTOPCI_CFG0 2
++#define SBTOPCI_CFG1 3
++#define SBTOPCI_PREF 0x4 /* prefetch enable */
++#define SBTOPCI_BURST 0x8 /* burst enable */
++#define SBTOPCI_RC_MASK 0x30 /* read command (>= rev11) */
++#define SBTOPCI_RC_READ 0x00 /* memory read */
++#define SBTOPCI_RC_READLINE 0x10 /* memory read line */
++#define SBTOPCI_RC_READMULTI 0x20 /* memory read multiple */
++
++/* PCI core index in SROM shadow area */
++#define SRSH_PI_OFFSET 0 /* first word */
++#define SRSH_PI_MASK 0xf000 /* bit 15:12 */
++#define SRSH_PI_SHIFT 12 /* bit 15:12 */
++
++#endif /* _sbpci_h_ */
+diff -urN linux.old/arch/mips/bcm947xx/include/sbpcmcia.h linux.dev/arch/mips/bcm947xx/include/sbpcmcia.h
+--- linux.old/arch/mips/bcm947xx/include/sbpcmcia.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/sbpcmcia.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,147 @@
++/*
++ * BCM43XX Sonics SiliconBackplane PCMCIA core hardware definitions.
++ *
++ * 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.
++ *
++ * $Id: sbpcmcia.h,v 1.1.1.9 2006/02/27 03:43:16 honor Exp $
++ */
++
++#ifndef _SBPCMCIA_H
++#define _SBPCMCIA_H
++
++
++/* All the addresses that are offsets in attribute space are divided
++ * by two to account for the fact that odd bytes are invalid in
++ * attribute space and our read/write routines make the space appear
++ * as if they didn't exist. Still we want to show the original numbers
++ * as documented in the hnd_pcmcia core manual.
++ */
++
++/* PCMCIA Function Configuration Registers */
++#define PCMCIA_FCR (0x700 / 2)
++
++#define FCR0_OFF 0
++#define FCR1_OFF (0x40 / 2)
++#define FCR2_OFF (0x80 / 2)
++#define FCR3_OFF (0xc0 / 2)
++
++#define PCMCIA_FCR0 (0x700 / 2)
++#define PCMCIA_FCR1 (0x740 / 2)
++#define PCMCIA_FCR2 (0x780 / 2)
++#define PCMCIA_FCR3 (0x7c0 / 2)
++
++/* Standard PCMCIA FCR registers */
++
++#define PCMCIA_COR 0
++
++#define COR_RST 0x80
++#define COR_LEV 0x40
++#define COR_IRQEN 0x04
++#define COR_BLREN 0x01
++#define COR_FUNEN 0x01
++
++
++#define PCICIA_FCSR (2 / 2)
++#define PCICIA_PRR (4 / 2)
++#define PCICIA_SCR (6 / 2)
++#define PCICIA_ESR (8 / 2)
++
++
++#define PCM_MEMOFF 0x0000
++#define F0_MEMOFF 0x1000
++#define F1_MEMOFF 0x2000
++#define F2_MEMOFF 0x3000
++#define F3_MEMOFF 0x4000
++
++/* Memory base in the function fcr's */
++#define MEM_ADDR0 (0x728 / 2)
++#define MEM_ADDR1 (0x72a / 2)
++#define MEM_ADDR2 (0x72c / 2)
++
++/* PCMCIA base plus Srom access in fcr0: */
++#define PCMCIA_ADDR0 (0x072e / 2)
++#define PCMCIA_ADDR1 (0x0730 / 2)
++#define PCMCIA_ADDR2 (0x0732 / 2)
++
++#define MEM_SEG (0x0734 / 2)
++#define SROM_CS (0x0736 / 2)
++#define SROM_DATAL (0x0738 / 2)
++#define SROM_DATAH (0x073a / 2)
++#define SROM_ADDRL (0x073c / 2)
++#define SROM_ADDRH (0x073e / 2)
++
++/* Values for srom_cs: */
++#define SROM_IDLE 0
++#define SROM_WRITE 1
++#define SROM_READ 2
++#define SROM_WEN 4
++#define SROM_WDS 7
++#define SROM_DONE 8
++
++/* CIS stuff */
++
++/* The CIS stops where the FCRs start */
++#define CIS_SIZE PCMCIA_FCR
++
++/* Standard tuples we know about */
++
++#define CISTPL_MANFID 0x20 /* Manufacturer and device id */
++#define CISTPL_FUNCE 0x22 /* Function extensions */
++#define CISTPL_CFTABLE 0x1b /* Config table entry */
++
++/* Function extensions for LANs */
++
++#define LAN_TECH 1 /* Technology type */
++#define LAN_SPEED 2 /* Raw bit rate */
++#define LAN_MEDIA 3 /* Transmission media */
++#define LAN_NID 4 /* Node identification (aka MAC addr) */
++#define LAN_CONN 5 /* Connector standard */
++
++
++/* CFTable */
++#define CFTABLE_REGWIN_2K 0x08 /* 2k reg windows size */
++#define CFTABLE_REGWIN_4K 0x10 /* 4k reg windows size */
++#define CFTABLE_REGWIN_8K 0x20 /* 8k reg windows size */
++
++/* Vendor unique tuples are 0x80-0x8f. Within Broadcom we'll
++ * take one for HNBU, and use "extensions" (a la FUNCE) within it.
++ */
++
++#define CISTPL_BRCM_HNBU 0x80
++
++/* Subtypes of BRCM_HNBU: */
++
++#define HNBU_SROMREV 0x00 /* A byte with sromrev, 1 if not present */
++#define HNBU_CHIPID 0x01 /* Two 16bit values: PCI vendor & device id */
++#define HNBU_BOARDREV 0x02 /* One byte board revision */
++#define HNBU_PAPARMS 0x03 /* PA parameters: 8 (sromrev == 1)
++ * or 9 (sromrev > 1) bytes
++ */
++#define HNBU_OEM 0x04 /* Eight bytes OEM data (sromrev == 1) */
++#define HNBU_CC 0x05 /* Default country code (sromrev == 1) */
++#define HNBU_AA 0x06 /* Antennas available */
++#define HNBU_AG 0x07 /* Antenna gain */
++#define HNBU_BOARDFLAGS 0x08 /* board flags (2 or 4 bytes) */
++#define HNBU_LEDS 0x09 /* LED set */
++#define HNBU_CCODE 0x0a /* Country code (2 bytes ascii + 1 byte cctl)
++ * in rev 2
++ */
++#define HNBU_CCKPO 0x0b /* 2 byte cck power offsets in rev 3 */
++#define HNBU_OFDMPO 0x0c /* 4 byte 11g ofdm power offsets in rev 3 */
++#define HNBU_GPIOTIMER 0x0d /* 2 bytes with on/off values in rev 3 */
++
++
++/* sbtmstatelow */
++#define SBTML_INT_ACK 0x40000 /* ack the sb interrupt */
++#define SBTML_INT_EN 0x20000 /* enable sb interrupt */
++
++/* sbtmstatehigh */
++#define SBTMH_INT_STATUS 0x40000 /* sb interrupt status */
++
++#endif /* _SBPCMCIA_H */
+diff -urN linux.old/arch/mips/bcm947xx/include/sbsdram.h linux.dev/arch/mips/bcm947xx/include/sbsdram.h
+--- linux.old/arch/mips/bcm947xx/include/sbsdram.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/sbsdram.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,85 @@
++/*
++ * BCM47XX Sonics SiliconBackplane SDRAM controller core hardware definitions.
++ *
++ * 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.
++ *
++ * $Id: sbsdram.h,v 1.1.1.9 2006/03/02 13:03:52 honor Exp $
++ */
++
++#ifndef _SBSDRAM_H
++#define _SBSDRAM_H
++
++#ifndef _LANGUAGE_ASSEMBLY
++
++/* Sonics side: SDRAM core registers */
++typedef volatile struct sbsdramregs {
++ uint32 initcontrol; /* Generates external SDRAM initialization sequence */
++ uint32 config; /* Initializes external SDRAM mode register */
++ uint32 refresh; /* Controls external SDRAM refresh rate */
++ uint32 pad1;
++ uint32 pad2;
++} sbsdramregs_t;
++
++/* SDRAM simulation */
++#ifdef RAMSZ
++#define SDRAMSZ RAMSZ
++#else
++#define SDRAMSZ (4 * 1024 * 1024)
++#endif
++
++extern uchar sdrambuf[SDRAMSZ];
++
++#endif /* _LANGUAGE_ASSEMBLY */
++
++/* SDRAM initialization control (initcontrol) register bits */
++#define SDRAM_CBR 0x0001 /* Writing 1 generates refresh cycle and toggles bit */
++#define SDRAM_PRE 0x0002 /* Writing 1 generates precharge cycle and toggles bit */
++#define SDRAM_MRS 0x0004 /* Writing 1 generates mode register select cycle and toggles bit */
++#define SDRAM_EN 0x0008 /* When set, enables access to SDRAM */
++#define SDRAM_16Mb 0x0000 /* Use 16 Megabit SDRAM */
++#define SDRAM_64Mb 0x0010 /* Use 64 Megabit SDRAM */
++#define SDRAM_128Mb 0x0020 /* Use 128 Megabit SDRAM */
++#define SDRAM_RSVMb 0x0030 /* Use special SDRAM */
++#define SDRAM_RST 0x0080 /* Writing 1 causes soft reset of controller */
++#define SDRAM_SELFREF 0x0100 /* Writing 1 enables self refresh mode */
++#define SDRAM_PWRDOWN 0x0200 /* Writing 1 causes controller to power down */
++#define SDRAM_32BIT 0x0400 /* When set, indicates 32 bit SDRAM interface */
++#define SDRAM_9BITCOL 0x0800 /* When set, indicates 9 bit column */
++
++/* SDRAM configuration (config) register bits */
++#define SDRAM_BURSTFULL 0x0000 /* Use full page bursts */
++#define SDRAM_BURST8 0x0001 /* Use burst of 8 */
++#define SDRAM_BURST4 0x0002 /* Use burst of 4 */
++#define SDRAM_BURST2 0x0003 /* Use burst of 2 */
++#define SDRAM_CAS3 0x0000 /* Use CAS latency of 3 */
++#define SDRAM_CAS2 0x0004 /* Use CAS latency of 2 */
++
++/* 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 SDRAM_INIT MEM4MX16X2
++#define SDRAM_CONFIG SDRAM_BURSTFULL
++#define SDRAM_REFRESH SDRAM_REF(0x40)
++
++#define MEM1MX16 0x009 /* 2 MB */
++#define MEM1MX16X2 0x409 /* 4 MB */
++#define MEM2MX8X2 0x809 /* 4 MB */
++#define MEM2MX8X4 0xc09 /* 8 MB */
++#define MEM2MX32 0x439 /* 8 MB */
++#define MEM4MX16 0x019 /* 8 MB */
++#define MEM4MX16X2 0x419 /* 16 MB */
++#define MEM8MX8X2 0x819 /* 16 MB */
++#define MEM8MX16 0x829 /* 16 MB */
++#define MEM4MX32 0x429 /* 16 MB */
++#define MEM8MX8X4 0xc19 /* 32 MB */
++#define MEM8MX16X2 0xc29 /* 32 MB */
++
++#endif /* _SBSDRAM_H */
+diff -urN linux.old/arch/mips/bcm947xx/include/sbsocram.h linux.dev/arch/mips/bcm947xx/include/sbsocram.h
+--- linux.old/arch/mips/bcm947xx/include/sbsocram.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/sbsocram.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,64 @@
++/*
++ * BCM47XX Sonics SiliconBackplane embedded ram core
++ *
++ * 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.
++ *
++ * $Id: sbsocram.h,v 1.1.1.3 2006/02/27 03:43:16 honor Exp $
++ */
++
++#ifndef _SBSOCRAM_H
++#define _SBSOCRAM_H
++
++#define SR_COREINFO 0x00
++#define SR_BWALLOC 0x04
++#define SR_BISTSTAT 0x0c
++#define SR_BANKINDEX 0x10
++#define SR_BANKSTBYCTL 0x14
++
++
++#ifndef _LANGUAGE_ASSEMBLY
++
++/* Memcsocram core registers */
++typedef volatile struct sbsocramregs {
++ uint32 coreinfo;
++ uint32 bwalloc;
++ uint32 PAD;
++ uint32 biststat;
++ uint32 bankidx;
++ uint32 standbyctrl;
++} sbsocramregs_t;
++
++#endif
++
++/* Coreinfo register */
++#define SRCI_PT_MASK 0x30000
++#define SRCI_PT_SHIFT 16
++
++/* In corerev 0, the memory size is 2 to the power of the
++ * base plus 16 plus to the contents of the memsize field plus 1.
++ */
++#define SRCI_MS0_MASK 0xf
++#define SR_MS0_BASE 16
++
++/*
++ * In corerev 1 the bank size is 2 ^ the bank size field plus 14,
++ * the memory size is number of banks times bank size.
++ * The same applies to rom size.
++ */
++#define SRCI_ROMNB_MASK 0xf000
++#define SRCI_ROMNB_SHIFT 12
++#define SRCI_ROMBSZ_MASK 0xf00
++#define SRCI_ROMBSZ_SHIFT 8
++#define SRCI_SRNB_MASK 0xf0
++#define SRCI_SRNB_SHIFT 4
++#define SRCI_SRBSZ_MASK 0xf
++#define SRCI_SRBSZ_SHIFT 0
++
++#define SR_BSZ_BASE 14
++#endif /* _SBSOCRAM_H */
+diff -urN linux.old/arch/mips/bcm947xx/include/sbutils.h linux.dev/arch/mips/bcm947xx/include/sbutils.h
+--- linux.old/arch/mips/bcm947xx/include/sbutils.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/sbutils.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,150 @@
++/*
++ * Misc utility routines for accessing chip-specific features
++ * of Broadcom HNBU SiliconBackplane-based chips.
++ *
++ * 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.
++ *
++ * $Id: sbutils.h,v 1.4 2006/04/08 07:12:42 honor Exp $
++ */
++
++#ifndef _sbutils_h_
++#define _sbutils_h_
++
++/*
++ * Datastructure to export all chip specific common variables
++ * public (read-only) portion of sbutils handle returned by
++ * sb_attach()/sb_kattach()
++*/
++
++struct sb_pub {
++
++ uint bustype; /* SB_BUS, PCI_BUS */
++ uint buscoretype; /* SB_PCI, SB_PCMCIA, SB_PCIE */
++ uint buscorerev; /* buscore rev */
++ uint buscoreidx; /* buscore index */
++ int ccrev; /* chip common core rev */
++ uint boardtype; /* board type */
++ uint boardvendor; /* board vendor */
++ uint chip; /* chip number */
++ uint chiprev; /* chip revision */
++ uint chippkg; /* chip package option */
++ uint sonicsrev; /* sonics backplane rev */
++};
++
++typedef const struct sb_pub sb_t;
++
++/*
++ * Many of the routines below take an 'sbh' handle as their first arg.
++ * Allocate this by calling sb_attach(). Free it by calling sb_detach().
++ * At any one time, the sbh is logically focused on one particular sb core
++ * (the "current core").
++ * Use sb_setcore() or sb_setcoreidx() to change the association to another core.
++ */
++
++#define SB_OSH NULL /* Use for sb_kattach when no osh is available */
++/* exported externs */
++extern sb_t *sb_attach(uint pcidev, osl_t *osh, void *regs, uint bustype,
++ void *sdh, char **vars, uint *varsz);
++extern sb_t *sb_kattach(void);
++extern void sb_detach(sb_t *sbh);
++extern uint sb_chip(sb_t *sbh);
++extern uint sb_chiprev(sb_t *sbh);
++extern uint sb_chipcrev(sb_t *sbh);
++extern uint sb_chippkg(sb_t *sbh);
++extern uint sb_pcirev(sb_t *sbh);
++extern bool sb_war16165(sb_t *sbh);
++extern uint sb_pcmciarev(sb_t *sbh);
++extern uint sb_boardvendor(sb_t *sbh);
++extern uint sb_boardtype(sb_t *sbh);
++extern uint sb_bus(sb_t *sbh);
++extern uint sb_buscoretype(sb_t *sbh);
++extern uint sb_buscorerev(sb_t *sbh);
++extern uint sb_corelist(sb_t *sbh, uint coreid[]);
++extern uint sb_coreid(sb_t *sbh);
++extern uint sb_coreidx(sb_t *sbh);
++extern uint sb_coreunit(sb_t *sbh);
++extern uint sb_corevendor(sb_t *sbh);
++extern uint sb_corerev(sb_t *sbh);
++extern void *sb_osh(sb_t *sbh);
++extern void sb_setosh(sb_t *sbh, osl_t *osh);
++extern void *sb_coreregs(sb_t *sbh);
++extern uint32 sb_coreflags(sb_t *sbh, uint32 mask, uint32 val);
++extern uint32 sb_coreflagshi(sb_t *sbh, uint32 mask, uint32 val);
++extern bool sb_iscoreup(sb_t *sbh);
++extern void *sb_setcoreidx(sb_t *sbh, uint coreidx);
++extern void *sb_setcore(sb_t *sbh, uint coreid, uint coreunit);
++extern int sb_corebist(sb_t *sbh);
++extern void sb_commit(sb_t *sbh);
++extern uint32 sb_base(uint32 admatch);
++extern uint32 sb_size(uint32 admatch);
++extern void sb_core_reset(sb_t *sbh, uint32 bits, uint32 resetbits);
++extern void sb_core_tofixup(sb_t *sbh);
++extern void sb_core_disable(sb_t *sbh, uint32 bits);
++extern uint32 sb_clock_rate(uint32 pll_type, uint32 n, uint32 m);
++extern uint32 sb_clock(sb_t *sbh);
++extern void sb_pci_setup(sb_t *sbh, uint coremask);
++extern void sb_pcmcia_init(sb_t *sbh);
++extern void sb_watchdog(sb_t *sbh, uint ticks);
++extern void *sb_gpiosetcore(sb_t *sbh);
++extern uint32 sb_gpiocontrol(sb_t *sbh, uint32 mask, uint32 val, uint8 priority);
++extern uint32 sb_gpioouten(sb_t *sbh, uint32 mask, uint32 val, uint8 priority);
++extern uint32 sb_gpioout(sb_t *sbh, uint32 mask, uint32 val, uint8 priority);
++extern uint32 sb_gpioin(sb_t *sbh);
++extern uint32 sb_gpiointpolarity(sb_t *sbh, uint32 mask, uint32 val, uint8 priority);
++extern uint32 sb_gpiointmask(sb_t *sbh, uint32 mask, uint32 val, uint8 priority);
++extern uint32 sb_gpioled(sb_t *sbh, uint32 mask, uint32 val);
++extern uint32 sb_gpioreserve(sb_t *sbh, uint32 gpio_num, uint8 priority);
++extern uint32 sb_gpiorelease(sb_t *sbh, uint32 gpio_num, uint8 priority);
++
++extern void sb_clkctl_init(sb_t *sbh);
++extern uint16 sb_clkctl_fast_pwrup_delay(sb_t *sbh);
++extern bool sb_clkctl_clk(sb_t *sbh, uint mode);
++extern int sb_clkctl_xtal(sb_t *sbh, uint what, bool on);
++extern void sb_register_intr_callback(sb_t *sbh, void *intrsoff_fn, void *intrsrestore_fn,
++ void *intrsenabled_fn, void *intr_arg);
++extern uint32 sb_set_initiator_to(sb_t *sbh, uint32 to);
++extern int sb_corepciid(sb_t *sbh, uint func, uint16 *pcivendor, uint16 *pcidevice,
++ uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif,
++ uint8 *pciheader);
++extern uint sb_pcie_readreg(void *sbh, void* arg1, uint offset);
++extern uint sb_pcie_writereg(sb_t *sbh, void *arg1, uint offset, uint val);
++extern uint32 sb_gpiotimerval(sb_t *sbh, uint32 mask, uint32 val);
++extern bool sb_backplane64(sb_t *sbh);
++extern void sb_btcgpiowar(sb_t *sbh);
++
++
++
++
++extern bool sb_deviceremoved(sb_t *sbh);
++extern uint32 sb_socram_size(sb_t *sbh);
++
++/*
++* Build device path. Path size must be >= SB_DEVPATH_BUFSZ.
++* The returned path is NULL terminated and has trailing '/'.
++* Return 0 on success, nonzero otherwise.
++*/
++extern int sb_devpath(sb_t *sbh, char *path, int size);
++
++/* clkctl xtal what flags */
++#define XTAL 0x1 /* primary crystal oscillator (2050) */
++#define PLL 0x2 /* main chip pll */
++
++/* clkctl clk mode */
++#define CLK_FAST 0 /* force fast (pll) clock */
++#define CLK_DYNAMIC 2 /* enable dynamic clock control */
++
++
++/* GPIO usage priorities */
++#define GPIO_DRV_PRIORITY 0 /* Driver */
++#define GPIO_APP_PRIORITY 1 /* Application */
++
++/* device path */
++#define SB_DEVPATH_BUFSZ 16 /* min buffer size in bytes */
++
++#endif /* _sbutils_h_ */
+diff -urN linux.old/arch/mips/bcm947xx/include/sflash.h linux.dev/arch/mips/bcm947xx/include/sflash.h
+--- linux.old/arch/mips/bcm947xx/include/sflash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/sflash.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,36 @@
++/*
++ * Broadcom SiliconBackplane chipcommon serial flash interface
++ *
++ * 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.
++ *
++ * $Id: sflash.h,v 1.1.1.8 2006/02/27 03:43:16 honor Exp $
++ */
++
++#ifndef _sflash_h_
++#define _sflash_h_
++
++#include <typedefs.h>
++#include <sbchipc.h>
++
++struct sflash {
++ uint blocksize; /* Block size */
++ uint numblocks; /* Number of blocks */
++ uint32 type; /* Type */
++ uint size; /* Total size in bytes */
++};
++
++/* Utility functions */
++extern int sflash_poll(chipcregs_t *cc, uint offset);
++extern int sflash_read(chipcregs_t *cc, uint offset, uint len, uchar *buf);
++extern int sflash_write(chipcregs_t *cc, uint offset, uint len, const uchar *buf);
++extern int sflash_erase(chipcregs_t *cc, uint offset);
++extern int sflash_commit(chipcregs_t *cc, uint offset, uint len, const uchar *buf);
++extern struct sflash * sflash_init(chipcregs_t *cc);
++
++#endif /* _sflash_h_ */
+diff -urN linux.old/arch/mips/bcm947xx/include/trxhdr.h linux.dev/arch/mips/bcm947xx/include/trxhdr.h
+--- linux.old/arch/mips/bcm947xx/include/trxhdr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/trxhdr.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,33 @@
++/*
++ * TRX image file header format.
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#include <typedefs.h>
++
++#define TRX_MAGIC 0x30524448 /* "HDR0" */
++#define TRX_VERSION 1
++#define TRX_MAX_LEN 0x3A0000
++#define TRX_NO_HEADER 1 /* Do not write TRX header */
++#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */
++#define TRX_MAX_OFFSET 3
++
++struct trx_header {
++ uint32 magic; /* "HDR0" */
++ uint32 len; /* Length of file including header */
++ uint32 crc32; /* 32-bit CRC from flag_version to end of file */
++ uint32 flag_version; /* 0:15 flags, 16:31 version */
++ uint32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */
++};
++
++/* Compatibility */
++typedef struct trx_header TRXHDR, *PTRXHDR;
+diff -urN linux.old/arch/mips/bcm947xx/include/typedefs.h linux.dev/arch/mips/bcm947xx/include/typedefs.h
+--- linux.old/arch/mips/bcm947xx/include/typedefs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/include/typedefs.h 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,361 @@
++/*
++ * 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.
++ * $Id: typedefs.h,v 1.1.1.12 2006/04/08 06:13:40 honor Exp $
++ */
++
++#ifndef _TYPEDEFS_H_
++#define _TYPEDEFS_H_
++
++
++/* Define 'SITE_TYPEDEFS' in the compile to include a site specific
++ * typedef file "site_typedefs.h".
++ *
++ * If 'SITE_TYPEDEFS' is not defined, then the "Inferred Typedefs"
++ * section of this file makes inferences about the compile environment
++ * based on defined symbols and possibly compiler pragmas.
++ *
++ * Following these two sections is the "Default Typedefs"
++ * section. This section is only prcessed if 'USE_TYPEDEF_DEFAULTS' is
++ * defined. This section has a default set of typedefs and a few
++ * proprocessor symbols (TRUE, FALSE, NULL, ...).
++ */
++
++#ifdef SITE_TYPEDEFS
++
++/*
++ * Site Specific Typedefs
++ *
++ */
++
++#include "site_typedefs.h"
++
++#else
++
++/*
++ * Inferred Typedefs
++ *
++ */
++
++/* Infer the compile environment based on preprocessor symbols and pramas.
++ * Override type definitions as needed, and include configuration dependent
++ * header files to define types.
++ */
++
++#ifdef __cplusplus
++
++#define TYPEDEF_BOOL
++#ifndef FALSE
++#define FALSE false
++#endif
++#ifndef TRUE
++#define TRUE true
++#endif
++
++#else /* ! __cplusplus */
++
++#if defined(_WIN32)
++
++#define TYPEDEF_BOOL
++typedef unsigned char bool; /* consistent w/BOOL */
++
++#endif /* _WIN32 */
++
++#endif /* ! __cplusplus */
++
++/* use the Windows ULONG_PTR type when compiling for 64 bit */
++#if defined(_WIN64)
++#include <basetsd.h>
++#define TYPEDEF_UINTPTR
++typedef ULONG_PTR uintptr;
++#endif
++
++
++#if defined(_MINOSL_)
++#define _NEED_SIZE_T_
++#endif
++
++#if defined(_NEED_SIZE_T_)
++typedef long unsigned int size_t;
++#endif
++
++#ifdef __DJGPP__
++typedef long unsigned int size_t;
++#endif /* __DJGPP__ */
++
++#ifdef _MSC_VER /* Microsoft C */
++#define TYPEDEF_INT64
++#define TYPEDEF_UINT64
++typedef signed __int64 int64;
++typedef unsigned __int64 uint64;
++#endif
++
++#if defined(MACOSX)
++#define TYPEDEF_BOOL
++#endif
++
++#if defined(__NetBSD__)
++#define TYPEDEF_ULONG
++#endif
++
++
++#if defined(linux)
++#define TYPEDEF_UINT
++#define TYPEDEF_USHORT
++#define TYPEDEF_ULONG
++#endif
++
++#if !defined(linux) && !defined(_WIN32) && !defined(_CFE_) && \
++ !defined(_HNDRTE_) && !defined(_MINOSL_) && !defined(__DJGPP__)
++#define TYPEDEF_UINT
++#define TYPEDEF_USHORT
++#endif
++
++
++/* Do not support the (u)int64 types with strict ansi for GNU C */
++#if defined(__GNUC__) && defined(__STRICT_ANSI__)
++#define TYPEDEF_INT64
++#define TYPEDEF_UINT64
++#endif
++
++/* ICL accepts unsigned 64 bit type only, and complains in ANSI mode
++ * for singned or unsigned
++ */
++#if defined(__ICL)
++
++#define TYPEDEF_INT64
++
++#if defined(__STDC__)
++#define TYPEDEF_UINT64
++#endif
++
++#endif /* __ICL */
++
++#if !defined(_WIN32) && !defined(_CFE_) && !defined(_MINOSL_) && \
++ !defined(__DJGPP__)
++
++/* pick up ushort & uint from standard types.h */
++#if defined(linux) && defined(__KERNEL__)
++
++#include <linux/types.h> /* sys/types.h and linux/types.h are oil and water */
++
++#else
++
++#include <sys/types.h>
++
++#endif
++
++#endif /* !_WIN32 && !PMON && !_CFE_ && !_HNDRTE_ && !_MINOSL_ && !__DJGPP__ */
++
++#if defined(MACOSX)
++
++#ifdef __BIG_ENDIAN__
++#define IL_BIGENDIAN
++#else
++#ifdef IL_BIGENDIAN
++#error "IL_BIGENDIAN was defined for a little-endian compile"
++#endif
++#endif /* __BIG_ENDIAN__ */
++
++#if !defined(__cplusplus)
++
++#if defined(__i386__)
++typedef unsigned char bool;
++#else
++typedef unsigned int bool;
++#endif
++#define TYPE_BOOL 1
++enum {
++ false = 0,
++ true = 1
++};
++
++#if defined(KERNEL)
++#include <IOKit/IOTypes.h>
++#endif /* KERNEL */
++
++#endif /* __cplusplus */
++
++#endif /* MACOSX */
++
++
++/* use the default typedefs in the next section of this file */
++#define USE_TYPEDEF_DEFAULTS
++
++#endif /* SITE_TYPEDEFS */
++
++
++/*
++ * Default Typedefs
++ *
++ */
++
++#ifdef USE_TYPEDEF_DEFAULTS
++#undef USE_TYPEDEF_DEFAULTS
++
++#ifndef TYPEDEF_BOOL
++typedef /* @abstract@ */ unsigned char bool;
++#endif
++
++/* define uchar, ushort, uint, ulong */
++
++#ifndef TYPEDEF_UCHAR
++typedef unsigned char uchar;
++#endif
++
++#ifndef TYPEDEF_USHORT
++typedef unsigned short ushort;
++#endif
++
++#ifndef TYPEDEF_UINT
++typedef unsigned int uint;
++#endif
++
++#ifndef TYPEDEF_ULONG
++typedef unsigned long ulong;
++#endif
++
++/* define [u]int8/16/32/64, uintptr */
++
++#ifndef TYPEDEF_UINT8
++typedef unsigned char uint8;
++#endif
++
++#ifndef TYPEDEF_UINT16
++typedef unsigned short uint16;
++#endif
++
++#ifndef TYPEDEF_UINT32
++typedef unsigned int uint32;
++#endif
++
++#ifndef TYPEDEF_UINT64
++typedef unsigned long long uint64;
++#endif
++
++#ifndef TYPEDEF_UINTPTR
++typedef unsigned int uintptr;
++#endif
++
++#ifndef TYPEDEF_INT8
++typedef signed char int8;
++#endif
++
++#ifndef TYPEDEF_INT16
++typedef signed short int16;
++#endif
++
++#ifndef TYPEDEF_INT32
++typedef signed int int32;
++#endif
++
++#ifndef TYPEDEF_INT64
++typedef signed long long int64;
++#endif
++
++/* define float32/64, float_t */
++
++#ifndef TYPEDEF_FLOAT32
++typedef float float32;
++#endif
++
++#ifndef TYPEDEF_FLOAT64
++typedef double float64;
++#endif
++
++/*
++ * abstracted floating point type allows for compile time selection of
++ * single or double precision arithmetic. Compiling with -DFLOAT32
++ * selects single precision; the default is double precision.
++ */
++
++#ifndef TYPEDEF_FLOAT_T
++
++#if defined(FLOAT32)
++typedef float32 float_t;
++#else /* default to double precision floating point */
++typedef float64 float_t;
++#endif
++
++#endif /* TYPEDEF_FLOAT_T */
++
++/* define macro values */
++
++#ifndef FALSE
++#define FALSE 0
++#endif
++
++#ifndef TRUE
++#define TRUE 1 /* TRUE */
++#endif
++
++#ifndef NULL
++#define NULL 0
++#endif
++
++#ifndef OFF
++#define OFF 0
++#endif
++
++#ifndef ON
++#define ON 1 /* ON = 1 */
++#endif
++
++#define AUTO (-1) /* Auto = -1 */
++
++/* define PTRSZ, INLINE */
++
++#ifndef PTRSZ
++#define PTRSZ sizeof(char*)
++#endif
++
++#ifndef INLINE
++
++#ifdef _MSC_VER
++
++#define INLINE __inline
++
++#elif __GNUC__
++
++#define INLINE __inline__
++
++#else
++
++#define INLINE
++
++#endif /* _MSC_VER */
++
++#endif /* INLINE */
++
++#undef TYPEDEF_BOOL
++#undef TYPEDEF_UCHAR
++#undef TYPEDEF_USHORT
++#undef TYPEDEF_UINT
++#undef TYPEDEF_ULONG
++#undef TYPEDEF_UINT8
++#undef TYPEDEF_UINT16
++#undef TYPEDEF_UINT32
++#undef TYPEDEF_UINT64
++#undef TYPEDEF_UINTPTR
++#undef TYPEDEF_INT8
++#undef TYPEDEF_INT16
++#undef TYPEDEF_INT32
++#undef TYPEDEF_INT64
++#undef TYPEDEF_FLOAT32
++#undef TYPEDEF_FLOAT64
++#undef TYPEDEF_FLOAT_T
++
++#endif /* USE_TYPEDEF_DEFAULTS */
++
++/*
++ * Including the bcmdefs.h here, to make sure everyone including typedefs.h
++ * gets this automatically
++*/
++#include "bcmdefs.h"
++
++#endif /* _TYPEDEFS_H_ */
+diff -urN linux.old/arch/mips/bcm947xx/Makefile linux.dev/arch/mips/bcm947xx/Makefile
+--- linux.old/arch/mips/bcm947xx/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/Makefile 2006-10-02 21:26:08.000000000 +0200
+@@ -0,0 +1,17 @@
++#
++# Makefile for the BCM947xx specific kernel interface routines
++# under Linux.
++#
++
++EXTRA_CFLAGS+=-I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER -fno-delayed-branch
++
++O_TARGET := bcm947xx.o
++
++export-objs := export.o
++obj-y := prom.o setup.o time.o sbmips.o gpio.o
++obj-y += nvram.o nvram_linux.o sflash.o cfe_env.o
++obj-y += sbutils.o bcmutils.o bcmsrom.o hndchipc.o
++obj-$(CONFIG_PCI) += sbpci.o pcibios.o
++obj-y += export.o
++
++include $(TOPDIR)/Rules.make
+diff -urN linux.old/arch/mips/bcm947xx/nvram.c linux.dev/arch/mips/bcm947xx/nvram.c
+--- linux.old/arch/mips/bcm947xx/nvram.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/nvram.c 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,315 @@
++/*
++ * NVRAM variable manipulation (common)
++ *
++ * 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.
++ *
++ */
++
++#include <typedefs.h>
++#include <osl.h>
++#include <bcmendian.h>
++#include <bcmnvram.h>
++#include <bcmutils.h>
++#include <sbsdram.h>
++
++extern struct nvram_tuple * BCMINIT(_nvram_realloc)(struct nvram_tuple *t, const char *name, const char *value);
++extern void BCMINIT(_nvram_free)(struct nvram_tuple *t);
++extern int BCMINIT(_nvram_read)(void *buf);
++
++char * BCMINIT(_nvram_get)(const char *name);
++int BCMINIT(_nvram_set)(const char *name, const char *value);
++int BCMINIT(_nvram_unset)(const char *name);
++int BCMINIT(_nvram_getall)(char *buf, int count);
++int BCMINIT(_nvram_commit)(struct nvram_header *header);
++int BCMINIT(_nvram_init)(void);
++void BCMINIT(_nvram_exit)(void);
++
++static struct nvram_tuple * BCMINITDATA(nvram_hash)[257];
++static struct nvram_tuple * nvram_dead;
++
++/* Free all tuples. Should be locked. */
++static void
++BCMINITFN(nvram_free)(void)
++{
++ uint i;
++ struct nvram_tuple *t, *next;
++
++ /* Free hash table */
++ for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) {
++ for (t = BCMINIT(nvram_hash)[i]; t; t = next) {
++ next = t->next;
++ BCMINIT(_nvram_free)(t);
++ }
++ BCMINIT(nvram_hash)[i] = NULL;
++ }
++
++ /* Free dead table */
++ for (t = nvram_dead; t; t = next) {
++ next = t->next;
++ BCMINIT(_nvram_free)(t);
++ }
++ nvram_dead = NULL;
++
++ /* Indicate to per-port code that all tuples have been freed */
++ BCMINIT(_nvram_free)(NULL);
++}
++
++/* String hash */
++static INLINE uint
++hash(const char *s)
++{
++ uint hash = 0;
++
++ while (*s)
++ hash = 31 * hash + *s++;
++
++ return hash;
++}
++
++/* (Re)initialize the hash table. Should be locked. */
++static int
++BCMINITFN(nvram_rehash)(struct nvram_header *header)
++{
++ char buf[] = "0xXXXXXXXX", *name, *value, *end, *eq;
++
++ /* (Re)initialize hash table */
++ BCMINIT(nvram_free)();
++
++ /* Parse and set "name=value\0 ... \0\0" */
++ name = (char *) &header[1];
++ end = (char *) header + NVRAM_SPACE - 2;
++ end[0] = end[1] = '\0';
++ for (; *name; name = value + strlen(value) + 1) {
++ if (!(eq = strchr(name, '=')))
++ break;
++ *eq = '\0';
++ value = eq + 1;
++ BCMINIT(_nvram_set)(name, value);
++ *eq = '=';
++ }
++
++ /* Set special SDRAM parameters */
++ if (!BCMINIT(_nvram_get)("sdram_init")) {
++ sprintf(buf, "0x%04X", (uint16)(header->crc_ver_init >> 16));
++ BCMINIT(_nvram_set)("sdram_init", buf);
++ }
++ if (!BCMINIT(_nvram_get)("sdram_config")) {
++ sprintf(buf, "0x%04X", (uint16)(header->config_refresh & 0xffff));
++ BCMINIT(_nvram_set)("sdram_config", buf);
++ }
++ if (!BCMINIT(_nvram_get)("sdram_refresh")) {
++ sprintf(buf, "0x%04X", (uint16)((header->config_refresh >> 16) & 0xffff));
++ BCMINIT(_nvram_set)("sdram_refresh", buf);
++ }
++ if (!BCMINIT(_nvram_get)("sdram_ncdl")) {
++ sprintf(buf, "0x%08X", header->config_ncdl);
++ BCMINIT(_nvram_set)("sdram_ncdl", buf);
++ }
++
++ return 0;
++}
++
++/* Get the value of an NVRAM variable. Should be locked. */
++char *
++BCMINITFN(_nvram_get)(const char *name)
++{
++ uint i;
++ struct nvram_tuple *t;
++ char *value;
++
++ if (!name)
++ return NULL;
++
++ /* Hash the name */
++ i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash));
++
++ /* Find the associated tuple in the hash table */
++ for (t = BCMINIT(nvram_hash)[i]; t && strcmp(t->name, name); t = t->next);
++
++ value = t ? t->value : NULL;
++
++ return value;
++}
++
++/* Get the value of an NVRAM variable. Should be locked. */
++int
++BCMINITFN(_nvram_set)(const char *name, const char *value)
++{
++ uint i;
++ struct nvram_tuple *t, *u, **prev;
++
++ /* Hash the name */
++ i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash));
++
++ /* Find the associated tuple in the hash table */
++ for (prev = &BCMINIT(nvram_hash)[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev);
++
++ /* (Re)allocate tuple */
++ if (!(u = BCMINIT(_nvram_realloc)(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 = nvram_dead;
++ nvram_dead = t;
++ }
++
++ /* Add new tuple to the hash table */
++ u->next = BCMINIT(nvram_hash)[i];
++ BCMINIT(nvram_hash)[i] = u;
++
++ return 0;
++}
++
++/* Unset the value of an NVRAM variable. Should be locked. */
++int
++BCMINITFN(_nvram_unset)(const char *name)
++{
++ uint i;
++ struct nvram_tuple *t, **prev;
++
++ if (!name)
++ return 0;
++
++ /* Hash the name */
++ i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash));
++
++ /* Find the associated tuple in the hash table */
++ for (prev = &BCMINIT(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 = nvram_dead;
++ nvram_dead = t;
++ }
++
++ return 0;
++}
++
++/* Get all NVRAM variables. Should be locked. */
++int
++BCMINITFN(_nvram_getall)(char *buf, int count)
++{
++ uint i;
++ struct nvram_tuple *t;
++ int len = 0;
++
++ bzero(buf, count);
++
++ /* Write name=value\0 ... \0\0 */
++ for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) {
++ for (t = BCMINIT(nvram_hash)[i]; t; t = t->next) {
++ if ((count - len) > (strlen(t->name) + 1 + strlen(t->value) + 1))
++ len += sprintf(buf + len, "%s=%s", t->name, t->value) + 1;
++ else
++ break;
++ }
++ }
++
++ return 0;
++}
++
++/* Regenerate NVRAM. Should be locked. */
++int
++BCMINITFN(_nvram_commit)(struct nvram_header *header)
++{
++ char *init, *config, *refresh, *ncdl;
++ char *ptr, *end;
++ int i;
++ struct nvram_tuple *t;
++ struct nvram_header tmp;
++ uint8 crc;
++
++ /* Regenerate header */
++ header->magic = NVRAM_MAGIC;
++ header->crc_ver_init = (NVRAM_VERSION << 8);
++ if (!(init = BCMINIT(_nvram_get)("sdram_init")) ||
++ !(config = BCMINIT(_nvram_get)("sdram_config")) ||
++ !(refresh = BCMINIT(_nvram_get)("sdram_refresh")) ||
++ !(ncdl = BCMINIT(_nvram_get)("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 |= (bcm_strtoul(init, NULL, 0) & 0xffff) << 16;
++ header->config_refresh = bcm_strtoul(config, NULL, 0) & 0xffff;
++ header->config_refresh |= (bcm_strtoul(refresh, NULL, 0) & 0xffff) << 16;
++ header->config_ncdl = bcm_strtoul(ncdl, NULL, 0);
++ }
++
++ /* Clear data area */
++ ptr = (char *) header + sizeof(struct nvram_header);
++ bzero(ptr, NVRAM_SPACE - sizeof(struct nvram_header));
++
++ /* Leave space for a double NUL at the end */
++ end = (char *) header + NVRAM_SPACE - 2;
++
++ /* Write out all tuples */
++ for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) {
++ for (t = BCMINIT(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 NUL */
++ ptr += 2;
++
++ /* Set new length */
++ header->len = ROUNDUP(ptr - (char *) header, 4);
++
++ /* Little-endian CRC8 over the last 11 bytes of the header */
++ tmp.crc_ver_init = htol32(header->crc_ver_init);
++ tmp.config_refresh = htol32(header->config_refresh);
++ tmp.config_ncdl = htol32(header->config_ncdl);
++ crc = hndcrc8((char *) &tmp + 9, sizeof(struct nvram_header) - 9, CRC8_INIT_VALUE);
++
++ /* Continue CRC8 over data bytes */
++ crc = hndcrc8((char *) &header[1], header->len - sizeof(struct nvram_header), crc);
++
++ /* Set new CRC8 */
++ header->crc_ver_init |= crc;
++
++ /* Reinitialize hash table */
++ return BCMINIT(nvram_rehash)(header);
++}
++
++/* Initialize hash table. Should be locked. */
++int
++BCMINITFN(_nvram_init)(void)
++{
++ struct nvram_header *header;
++ int ret;
++
++ if (!(header = (struct nvram_header *) kmalloc(NVRAM_SPACE, GFP_ATOMIC))) {
++ return -12; /* -ENOMEM */
++ }
++
++ if ((ret = BCMINIT(_nvram_read)(header)) == 0 &&
++ header->magic == NVRAM_MAGIC)
++ BCMINIT(nvram_rehash)(header);
++
++ kfree(header);
++ return ret;
++}
++
++/* Free hash table. Should be locked. */
++void
++BCMINITFN(_nvram_exit)(void)
++{
++ BCMINIT(nvram_free)();
++}
+diff -urN linux.old/arch/mips/bcm947xx/nvram_linux.c linux.dev/arch/mips/bcm947xx/nvram_linux.c
+--- linux.old/arch/mips/bcm947xx/nvram_linux.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/nvram_linux.c 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,723 @@
++/*
++ * NVRAM variable manipulation (Linux kernel half)
++ *
++ * 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.
++ *
++ * $Id: nvram_linux.c,v 1.19 2006/04/08 07:12:42 honor Exp $
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/bootmem.h>
++#include <linux/wrapper.h>
++#include <linux/fs.h>
++#include <linux/miscdevice.h>
++#include <linux/mtd/mtd.h>
++#include <asm/addrspace.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++
++#include <typedefs.h>
++#include <osl.h>
++#include <bcmendian.h>
++#include <bcmnvram.h>
++#include <bcmutils.h>
++#include <sbconfig.h>
++#include <sbchipc.h>
++#include <sbutils.h>
++#include <hndmips.h>
++#include <sflash.h>
++
++/* In BSS to minimize text size and page aligned so it can be mmap()-ed */
++static char nvram_buf[NVRAM_SPACE] __attribute__((aligned(PAGE_SIZE)));
++
++#ifdef MODULE
++
++#define early_nvram_get(name) nvram_get(name)
++
++#else /* !MODULE */
++
++/* Global SB handle */
++extern void *bcm947xx_sbh;
++extern spinlock_t bcm947xx_sbh_lock;
++
++static int cfe_env;
++extern char *cfe_env_get(char *nv_buf, const char *name);
++
++/* Convenience */
++#define sbh bcm947xx_sbh
++#define sbh_lock bcm947xx_sbh_lock
++#define KB * 1024
++#define MB * 1024 * 1024
++
++/* Probe for NVRAM header */
++static void __init
++early_nvram_init(void)
++{
++ struct nvram_header *header;
++ chipcregs_t *cc;
++ struct sflash *info = NULL;
++ int i;
++ uint32 base, off, lim;
++ u32 *src, *dst;
++
++ if ((cc = sb_setcore(sbh, SB_CC, 0)) != NULL) {
++ base = KSEG1ADDR(SB_FLASH2);
++ switch (readl(&cc->capabilities) & CAP_FLASH_MASK) {
++ case PFLASH:
++ lim = SB_FLASH2_SZ;
++ break;
++
++ case SFLASH_ST:
++ case SFLASH_AT:
++ if ((info = sflash_init(cc)) == NULL)
++ return;
++ lim = info->size;
++ break;
++
++ case FLASH_NONE:
++ default:
++ return;
++ }
++ } else {
++ /* extif assumed, Stop at 4 MB */
++ base = KSEG1ADDR(SB_FLASH1);
++ lim = SB_FLASH1_SZ;
++ }
++
++ /* XXX: hack for supporting the CFE environment stuff on WGT634U */
++ src = (u32 *) KSEG1ADDR(base + 8 * 1024 * 1024 - 0x2000);
++ dst = (u32 *) nvram_buf;
++ if ((lim == 0x02000000) && ((*src & 0xff00ff) == 0x000001)) {
++ printk("early_nvram_init: WGT634U NVRAM found.\n");
++
++ for (i = 0; i < 0x1ff0; i++) {
++ if (*src == 0xFFFFFFFF)
++ break;
++ *dst++ = *src++;
++ }
++ cfe_env = 1;
++ return;
++ }
++
++ off = FLASH_MIN;
++ while (off <= lim) {
++ /* Windowed flash access */
++ header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE);
++ if (header->magic == NVRAM_MAGIC)
++ goto found;
++ off <<= 1;
++ }
++
++ /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
++ header = (struct nvram_header *) KSEG1ADDR(base + 4 KB);
++ if (header->magic == NVRAM_MAGIC)
++ goto found;
++
++ header = (struct nvram_header *) KSEG1ADDR(base + 1 KB);
++ if (header->magic == NVRAM_MAGIC)
++ goto found;
++
++ printk("early_nvram_init: NVRAM not found\n");
++ return;
++
++found:
++ src = (u32 *) header;
++ dst = (u32 *) nvram_buf;
++ for (i = 0; i < sizeof(struct nvram_header); i += 4)
++ *dst++ = *src++;
++ for (; i < header->len && i < NVRAM_SPACE; i += 4)
++ *dst++ = ltoh32(*src++);
++}
++
++/* Early (before mm or mtd) read-only access to NVRAM */
++static char * __init
++early_nvram_get(const char *name)
++{
++ char *var, *value, *end, *eq;
++
++ if (!name)
++ return NULL;
++
++ /* Too early? */
++ if (sbh == NULL)
++ return NULL;
++
++ if (!nvram_buf[0])
++ early_nvram_init();
++
++ if (cfe_env)
++ return cfe_env_get(nvram_buf, name);
++
++ /* Look for name=value and return value */
++ var = &nvram_buf[sizeof(struct nvram_header)];
++ end = nvram_buf + sizeof(nvram_buf) - 2;
++ end[0] = end[1] = '\0';
++ for (; *var; var = value + strlen(value) + 1) {
++ if (!(eq = strchr(var, '=')))
++ break;
++ value = eq + 1;
++ if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0)
++ return value;
++ }
++
++ return NULL;
++}
++
++static int __init
++early_nvram_getall(char *buf, int count)
++{
++ char *var, *end;
++ int len = 0;
++
++ /* Too early? */
++ if (sbh == NULL)
++ return -1;
++
++ if (!nvram_buf[0])
++ early_nvram_init();
++
++ bzero(buf, count);
++
++ /* Write name=value\0 ... \0\0 */
++ var = &nvram_buf[sizeof(struct nvram_header)];
++ end = nvram_buf + sizeof(nvram_buf) - 2;
++ end[0] = end[1] = '\0';
++ for (; *var; var += strlen(var) + 1) {
++ if ((count - len) <= (strlen(var) + 1))
++ break;
++ len += sprintf(buf + len, "%s", var) + 1;
++ }
++
++ return 0;
++}
++#endif /* !MODULE */
++
++extern char * _nvram_get(const char *name);
++extern int _nvram_set(const char *name, const char *value);
++extern int _nvram_unset(const char *name);
++extern int _nvram_getall(char *buf, int count);
++extern int _nvram_commit(struct nvram_header *header);
++extern int _nvram_init(void *sbh);
++extern void _nvram_exit(void);
++
++/* Globals */
++static spinlock_t nvram_lock = SPIN_LOCK_UNLOCKED;
++static struct semaphore nvram_sem;
++static unsigned long nvram_offset = 0;
++static int nvram_major = -1;
++static devfs_handle_t nvram_handle = NULL;
++static struct mtd_info *nvram_mtd = NULL;
++
++int
++_nvram_read(char *buf)
++{
++ struct nvram_header *header = (struct nvram_header *) buf;
++ size_t len;
++
++ if (!nvram_mtd ||
++ MTD_READ(nvram_mtd, nvram_mtd->size - NVRAM_SPACE, NVRAM_SPACE, &len, buf) ||
++ len != NVRAM_SPACE ||
++ header->magic != NVRAM_MAGIC) {
++ /* Maybe we can recover some data from early initialization */
++ memcpy(buf, nvram_buf, NVRAM_SPACE);
++ }
++
++ return 0;
++}
++
++struct nvram_tuple *
++_nvram_realloc(struct nvram_tuple *t, const char *name, const char *value)
++{
++ if ((nvram_offset + strlen(value) + 1) > NVRAM_SPACE)
++ return NULL;
++
++ if (!t) {
++ if (!(t = kmalloc(sizeof(struct nvram_tuple) + strlen(name) + 1, GFP_ATOMIC)))
++ 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)) {
++ t->value = &nvram_buf[nvram_offset];
++ strcpy(t->value, value);
++ nvram_offset += strlen(value) + 1;
++ }
++
++ return t;
++}
++
++void
++_nvram_free(struct nvram_tuple *t)
++{
++ if (!t)
++ nvram_offset = 0;
++ else
++ kfree(t);
++}
++
++int
++nvram_set(const char *name, const char *value)
++{
++ unsigned long flags;
++ int ret;
++ struct nvram_header *header;
++
++ spin_lock_irqsave(&nvram_lock, flags);
++ if ((ret = _nvram_set(name, value))) {
++ /* Consolidate space and try again */
++ if ((header = kmalloc(NVRAM_SPACE, GFP_ATOMIC))) {
++ if (_nvram_commit(header) == 0)
++ ret = _nvram_set(name, value);
++ kfree(header);
++ }
++ }
++ spin_unlock_irqrestore(&nvram_lock, flags);
++
++ return ret;
++}
++
++char *
++real_nvram_get(const char *name)
++{
++ unsigned long flags;
++ char *value;
++
++ spin_lock_irqsave(&nvram_lock, flags);
++ value = _nvram_get(name);
++ spin_unlock_irqrestore(&nvram_lock, flags);
++
++ return value;
++}
++
++char *
++nvram_get(const char *name)
++{
++ if (nvram_major >= 0)
++ return real_nvram_get(name);
++ else
++ return early_nvram_get(name);
++}
++
++int
++nvram_unset(const char *name)
++{
++ unsigned long flags;
++ int ret;
++
++ spin_lock_irqsave(&nvram_lock, flags);
++ ret = _nvram_unset(name);
++ spin_unlock_irqrestore(&nvram_lock, flags);
++
++ return ret;
++}
++
++static void
++erase_callback(struct erase_info *done)
++{
++ wait_queue_head_t *wait_q = (wait_queue_head_t *) done->priv;
++ wake_up(wait_q);
++}
++
++int
++nvram_commit(void)
++{
++ char *buf;
++ size_t erasesize, len, magic_len;
++ unsigned int i;
++ int ret;
++ struct nvram_header *header;
++ unsigned long flags;
++ u_int32_t offset;
++ DECLARE_WAITQUEUE(wait, current);
++ wait_queue_head_t wait_q;
++ struct erase_info erase;
++ u_int32_t magic_offset = 0; /* Offset for writing MAGIC # */
++
++ if (!nvram_mtd) {
++ printk("nvram_commit: NVRAM not found\n");
++ return -ENODEV;
++ }
++
++ if (in_interrupt()) {
++ printk("nvram_commit: not committing in interrupt\n");
++ return -EINVAL;
++ }
++
++ /* Backup sector blocks to be erased */
++ erasesize = ROUNDUP(NVRAM_SPACE, nvram_mtd->erasesize);
++ if (!(buf = kmalloc(erasesize, GFP_KERNEL))) {
++ printk("nvram_commit: out of memory\n");
++ return -ENOMEM;
++ }
++
++ down(&nvram_sem);
++
++ if ((i = erasesize - NVRAM_SPACE) > 0) {
++ offset = nvram_mtd->size - erasesize;
++ len = 0;
++ ret = MTD_READ(nvram_mtd, offset, i, &len, buf);
++ if (ret || len != i) {
++ printk("nvram_commit: read error ret = %d, len = %d/%d\n", ret, len, i);
++ ret = -EIO;
++ goto done;
++ }
++ header = (struct nvram_header *)(buf + i);
++ magic_offset = i + ((void *)&header->magic - (void *)header);
++ } else {
++ offset = nvram_mtd->size - NVRAM_SPACE;
++ magic_offset = ((void *)&header->magic - (void *)header);
++ header = (struct nvram_header *)buf;
++ }
++
++ /* clear the existing magic # to mark the NVRAM as unusable
++ we can pull MAGIC bits low without erase */
++ header->magic = NVRAM_CLEAR_MAGIC; /* All zeros magic */
++
++ /* Unlock sector blocks (for Intel 28F320C3B flash) , 20060309 */
++ if(nvram_mtd->unlock)
++ nvram_mtd->unlock(nvram_mtd, offset, nvram_mtd->erasesize);
++
++ ret = MTD_WRITE(nvram_mtd, offset + magic_offset, sizeof(header->magic),
++ &magic_len, (char *)&header->magic);
++ if (ret || magic_len != sizeof(header->magic)) {
++ printk("nvram_commit: clear MAGIC error\n");
++ ret = -EIO;
++ goto done;
++ }
++
++ header->magic = NVRAM_MAGIC; /* reset MAGIC before we regenerate the NVRAM,
++ otherwise we'll have an incorrect CRC */
++ /* Regenerate NVRAM */
++ spin_lock_irqsave(&nvram_lock, flags);
++ ret = _nvram_commit(header);
++ spin_unlock_irqrestore(&nvram_lock, flags);
++ if (ret)
++ goto done;
++
++ /* Erase sector blocks */
++ init_waitqueue_head(&wait_q);
++ for (; offset < nvram_mtd->size - NVRAM_SPACE + header->len; offset += nvram_mtd->erasesize) {
++ erase.mtd = nvram_mtd;
++ erase.addr = offset;
++ erase.len = nvram_mtd->erasesize;
++ erase.callback = erase_callback;
++ erase.priv = (u_long) &wait_q;
++
++ set_current_state(TASK_INTERRUPTIBLE);
++ add_wait_queue(&wait_q, &wait);
++
++ /* Unlock sector blocks */
++ if (nvram_mtd->unlock)
++ nvram_mtd->unlock(nvram_mtd, offset, nvram_mtd->erasesize);
++
++ if ((ret = MTD_ERASE(nvram_mtd, &erase))) {
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&wait_q, &wait);
++ printk("nvram_commit: erase error\n");
++ goto done;
++ }
++
++ /* Wait for erase to finish */
++ schedule();
++ remove_wait_queue(&wait_q, &wait);
++ }
++
++ /* Write partition up to end of data area */
++ header->magic = NVRAM_INVALID_MAGIC; /* All ones magic */
++ offset = nvram_mtd->size - erasesize;
++ i = erasesize - NVRAM_SPACE + header->len;
++ ret = MTD_WRITE(nvram_mtd, offset, i, &len, buf);
++ if (ret || len != i) {
++ printk("nvram_commit: write error\n");
++ ret = -EIO;
++ goto done;
++ }
++
++ /* Now mark the NVRAM in flash as "valid" by setting the correct
++ MAGIC # */
++ header->magic = NVRAM_MAGIC;
++ ret = MTD_WRITE(nvram_mtd, offset + magic_offset, sizeof(header->magic),
++ &magic_len, (char *)&header->magic);
++ if (ret || magic_len != sizeof(header->magic)) {
++ printk("nvram_commit: write MAGIC error\n");
++ ret = -EIO;
++ goto done;
++ }
++
++ /*
++ * Reading a few bytes back here will put the device
++ * back to the correct mode on certain flashes */
++ offset = nvram_mtd->size - erasesize;
++ ret = MTD_READ(nvram_mtd, offset, 4, &len, buf);
++
++ done:
++ up(&nvram_sem);
++ kfree(buf);
++
++ return ret;
++}
++
++int
++nvram_getall(char *buf, int count)
++{
++ unsigned long flags;
++ int ret;
++
++ spin_lock_irqsave(&nvram_lock, flags);
++ if (nvram_major >= 0)
++ ret = _nvram_getall(buf, count);
++ else
++ ret = early_nvram_getall(buf, count);
++ spin_unlock_irqrestore(&nvram_lock, flags);
++
++ return ret;
++}
++
++
++
++
++
++
++
++/* User mode interface below */
++
++static ssize_t
++dev_nvram_read(struct file *file, char *buf, size_t count, loff_t *ppos)
++{
++ char tmp[100], *name = tmp, *value;
++ ssize_t ret;
++ unsigned long off;
++
++ if (count > sizeof(tmp)) {
++ if (!(name = kmalloc(count, GFP_KERNEL)))
++ return -ENOMEM;
++ }
++
++ if (copy_from_user(name, buf, count)) {
++ ret = -EFAULT;
++ goto done;
++ }
++
++ if (*name == '\0') {
++ /* Get all variables */
++ ret = nvram_getall(name, count);
++ if (ret == 0) {
++ if (copy_to_user(buf, name, count)) {
++ ret = -EFAULT;
++ goto done;
++ }
++ ret = count;
++ }
++ } else {
++ if (!(value = nvram_get(name))) {
++ ret = 0;
++ goto done;
++ }
++
++ /* Provide the offset into mmap() space */
++ off = (unsigned long) value - (unsigned long) nvram_buf;
++
++ if (put_user(off, (unsigned long *) buf)) {
++ ret = -EFAULT;
++ goto done;
++ }
++
++ ret = sizeof(unsigned long);
++ }
++
++ flush_cache_all();
++
++done:
++ if (name != tmp)
++ kfree(name);
++
++ return ret;
++}
++
++static ssize_t
++dev_nvram_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
++{
++ char tmp[100], *name = tmp, *value;
++ ssize_t ret;
++
++ if (count > sizeof(tmp)) {
++ if (!(name = kmalloc(count, GFP_KERNEL)))
++ return -ENOMEM;
++ }
++
++ if (copy_from_user(name, buf, count)) {
++ ret = -EFAULT;
++ goto done;
++ }
++
++ value = name;
++ name = strsep(&value, "=");
++ if (value)
++ ret = nvram_set(name, value) ? : count;
++ else
++ ret = nvram_unset(name) ? : count;
++
++ done:
++ if (name != tmp)
++ kfree(name);
++
++ return ret;
++}
++
++static int
++dev_nvram_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
++{
++ if (cmd != NVRAM_MAGIC)
++ return -EINVAL;
++
++ return nvram_commit();
++}
++
++static int
++dev_nvram_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ unsigned long offset = virt_to_phys(nvram_buf);
++
++ if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start,
++ vma->vm_page_prot))
++ return -EAGAIN;
++
++ return 0;
++}
++
++static int
++dev_nvram_open(struct inode *inode, struct file * file)
++{
++ MOD_INC_USE_COUNT;
++ return 0;
++}
++
++static int
++dev_nvram_release(struct inode *inode, struct file * file)
++{
++ MOD_DEC_USE_COUNT;
++ return 0;
++}
++
++static struct file_operations dev_nvram_fops = {
++ owner: THIS_MODULE,
++ open: dev_nvram_open,
++ release: dev_nvram_release,
++ read: dev_nvram_read,
++ write: dev_nvram_write,
++ ioctl: dev_nvram_ioctl,
++ mmap: dev_nvram_mmap,
++};
++
++static void
++dev_nvram_exit(void)
++{
++ int order = 0;
++ struct page *page, *end;
++
++ if (nvram_handle)
++ devfs_unregister(nvram_handle);
++
++ if (nvram_major >= 0)
++ devfs_unregister_chrdev(nvram_major, "nvram");
++
++ if (nvram_mtd)
++ put_mtd_device(nvram_mtd);
++
++ while ((PAGE_SIZE << order) < NVRAM_SPACE)
++ order++;
++ end = virt_to_page(nvram_buf + (PAGE_SIZE << order) - 1);
++ for (page = virt_to_page(nvram_buf); page <= end; page++)
++ mem_map_unreserve(page);
++
++ _nvram_exit();
++}
++
++static int __init
++dev_nvram_init(void)
++{
++ int order = 0, ret = 0;
++ struct page *page, *end;
++ unsigned int i;
++
++ /* Allocate and reserve memory to mmap() */
++ while ((PAGE_SIZE << order) < NVRAM_SPACE)
++ order++;
++ end = virt_to_page(nvram_buf + (PAGE_SIZE << order) - 1);
++ for (page = virt_to_page(nvram_buf); page <= end; page++)
++ mem_map_reserve(page);
++
++#ifdef CONFIG_MTD
++ /* Find associated MTD device */
++ for (i = 0; i < MAX_MTD_DEVICES; i++) {
++ nvram_mtd = get_mtd_device(NULL, i);
++ if (nvram_mtd) {
++ if (!strcmp(nvram_mtd->name, "nvram") &&
++ nvram_mtd->size >= NVRAM_SPACE)
++ break;
++ put_mtd_device(nvram_mtd);
++ }
++ }
++ if (i >= MAX_MTD_DEVICES)
++ nvram_mtd = NULL;
++#endif
++
++ /* Initialize hash table lock */
++ spin_lock_init(&nvram_lock);
++
++ /* Initialize commit semaphore */
++ init_MUTEX(&nvram_sem);
++
++ /* Register char device */
++ if ((nvram_major = devfs_register_chrdev(0, "nvram", &dev_nvram_fops)) < 0) {
++ ret = nvram_major;
++ goto err;
++ }
++
++ /* Initialize hash table */
++ _nvram_init(sbh);
++
++ /* Create /dev/nvram handle */
++ nvram_handle = devfs_register(NULL, "nvram", DEVFS_FL_NONE, nvram_major, 0,
++ S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, &dev_nvram_fops, NULL);
++
++ /* Set the SDRAM NCDL value into NVRAM if not already done */
++ if (getintvar(NULL, "sdram_ncdl") == 0) {
++ unsigned int ncdl;
++ char buf[] = "0x00000000";
++
++ if ((ncdl = sb_memc_get_ncdl(sbh))) {
++ sprintf(buf, "0x%08x", ncdl);
++ nvram_set("sdram_ncdl", buf);
++ nvram_commit();
++ }
++ }
++
++ return 0;
++
++ err:
++ dev_nvram_exit();
++ return ret;
++}
++
++module_init(dev_nvram_init);
++module_exit(dev_nvram_exit);
+diff -urN linux.old/arch/mips/bcm947xx/pcibios.c linux.dev/arch/mips/bcm947xx/pcibios.c
+--- linux.old/arch/mips/bcm947xx/pcibios.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/pcibios.c 2006-10-02 21:22:56.000000000 +0200
+@@ -0,0 +1,380 @@
++/*
++ * Low-Level PCI and SB support for BCM47xx (Linux support code)
++ *
++ * 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.
++ *
++ * $Id: pcibios.c,v 1.1.1.9 2006/02/27 03:42:55 honor Exp $
++ */
++
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/paccess.h>
++
++#include <typedefs.h>
++#include <osl.h>
++#include <bcmutils.h>
++#include <sbconfig.h>
++#include <sbutils.h>
++#include <hndpci.h>
++#include <pcicfg.h>
++#include <bcmdevs.h>
++#include <bcmnvram.h>
++
++/* Global SB handle */
++extern sb_t *bcm947xx_sbh;
++extern spinlock_t bcm947xx_sbh_lock;
++
++/* Convenience */
++#define sbh bcm947xx_sbh
++#define sbh_lock bcm947xx_sbh_lock
++
++static int
++sbpci_read_config_byte(struct pci_dev *dev, int where, u8 *value)
++{
++ unsigned long flags;
++ int ret;
++
++ spin_lock_irqsave(&sbh_lock, flags);
++ ret = sbpci_read_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn),
++ PCI_FUNC(dev->devfn), where, value, sizeof(*value));
++ spin_unlock_irqrestore(&sbh_lock, flags);
++ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
++}
++
++static int
++sbpci_read_config_word(struct pci_dev *dev, int where, u16 *value)
++{
++ unsigned long flags;
++ int ret;
++
++ spin_lock_irqsave(&sbh_lock, flags);
++ ret = sbpci_read_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn),
++ PCI_FUNC(dev->devfn), where, value, sizeof(*value));
++ spin_unlock_irqrestore(&sbh_lock, flags);
++ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
++}
++
++static int
++sbpci_read_config_dword(struct pci_dev *dev, int where, u32 *value)
++{
++ unsigned long flags;
++ int ret;
++
++ spin_lock_irqsave(&sbh_lock, flags);
++ ret = sbpci_read_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn),
++ PCI_FUNC(dev->devfn), where, value, sizeof(*value));
++ spin_unlock_irqrestore(&sbh_lock, flags);
++ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
++}
++
++static int
++sbpci_write_config_byte(struct pci_dev *dev, int where, u8 value)
++{
++ unsigned long flags;
++ int ret;
++
++ spin_lock_irqsave(&sbh_lock, flags);
++ ret = sbpci_write_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn),
++ PCI_FUNC(dev->devfn), where, &value, sizeof(value));
++ spin_unlock_irqrestore(&sbh_lock, flags);
++ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
++}
++
++static int
++sbpci_write_config_word(struct pci_dev *dev, int where, u16 value)
++{
++ unsigned long flags;
++ int ret;
++
++ spin_lock_irqsave(&sbh_lock, flags);
++ ret = sbpci_write_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn),
++ PCI_FUNC(dev->devfn), where, &value, sizeof(value));
++ spin_unlock_irqrestore(&sbh_lock, flags);
++ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
++}
++
++static int
++sbpci_write_config_dword(struct pci_dev *dev, int where, u32 value)
++{
++ unsigned long flags;
++ int ret;
++
++ spin_lock_irqsave(&sbh_lock, flags);
++ ret = sbpci_write_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn),
++ PCI_FUNC(dev->devfn), where, &value, sizeof(value));
++ spin_unlock_irqrestore(&sbh_lock, flags);
++ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops pcibios_ops = {
++ sbpci_read_config_byte,
++ sbpci_read_config_word,
++ sbpci_read_config_dword,
++ sbpci_write_config_byte,
++ sbpci_write_config_word,
++ sbpci_write_config_dword
++};
++
++
++void __init
++pcibios_init(void)
++{
++ ulong flags;
++
++ if (!(sbh = sb_kattach()))
++ panic("sb_kattach failed");
++ spin_lock_init(&sbh_lock);
++
++ spin_lock_irqsave(&sbh_lock, flags);
++ sbpci_init(sbh);
++ spin_unlock_irqrestore(&sbh_lock, flags);
++
++ set_io_port_base((unsigned long) ioremap_nocache(SB_PCI_MEM, 0x04000000));
++
++ /* Scan the SB bus */
++ pci_scan_bus(0, &pcibios_ops, NULL);
++
++}
++
++char * __init
++pcibios_setup(char *str)
++{
++ if (!strncmp(str, "ban=", 4)) {
++ sbpci_ban(simple_strtoul(str + 4, NULL, 0));
++ return NULL;
++ }
++
++ return (str);
++}
++
++static u32 pci_iobase = 0x100;
++static u32 pci_membase = SB_PCI_DMA;
++
++void __init
++pcibios_fixup_bus(struct pci_bus *b)
++{
++ struct list_head *ln;
++ struct pci_dev *d;
++ struct resource *res;
++ int pos, size;
++ u32 *base;
++ u8 irq;
++
++ printk("PCI: Fixing up bus %d\n", b->number);
++
++ /* Fix up SB */
++ if (b->number == 0) {
++ for (ln = b->devices.next; ln != &b->devices; ln = ln->next) {
++ d = pci_dev_b(ln);
++ /* Fix up interrupt lines */
++ pci_read_config_byte(d, PCI_INTERRUPT_LINE, &irq);
++ d->irq = irq + 2;
++ pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);
++ }
++ }
++
++ /* Fix up external PCI */
++ else {
++ for (ln = b->devices.next; ln != &b->devices; ln = ln->next) {
++ d = pci_dev_b(ln);
++ /* Fix up resource bases */
++ for (pos = 0; pos < 6; pos++) {
++ res = &d->resource[pos];
++ base = (res->flags & IORESOURCE_IO) ? &pci_iobase : &pci_membase;
++ if (res->end) {
++ size = res->end - res->start + 1;
++ if (*base & (size - 1))
++ *base = (*base + size) & ~(size - 1);
++ res->start = *base;
++ res->end = res->start + size - 1;
++ *base += size;
++ pci_write_config_dword(d,
++ PCI_BASE_ADDRESS_0 + (pos << 2), res->start);
++ }
++ /* Fix up PCI bridge BAR0 only */
++ if (b->number == 1 && PCI_SLOT(d->devfn) == 0)
++ break;
++ }
++ /* Fix up interrupt lines */
++ if (pci_find_device(VENDOR_BROADCOM, SB_PCI, NULL))
++ d->irq = (pci_find_device(VENDOR_BROADCOM, SB_PCI, NULL))->irq;
++ pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);
++ }
++ }
++}
++
++unsigned int
++pcibios_assign_all_busses(void)
++{
++ return 1;
++}
++
++void
++pcibios_align_resource(void *data, struct resource *res,
++ unsigned long size, unsigned long align)
++{
++}
++
++int
++pcibios_enable_resources(struct pci_dev *dev)
++{
++ u16 cmd, old_cmd;
++ int idx;
++ struct resource *r;
++
++ /* External PCI only */
++ if (dev->bus->number == 0)
++ return 0;
++
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ old_cmd = cmd;
++ for (idx = 0; idx < 6; idx++) {
++ r = &dev->resource[idx];
++ if (r->flags & IORESOURCE_IO)
++ cmd |= PCI_COMMAND_IO;
++ if (r->flags & IORESOURCE_MEM)
++ cmd |= PCI_COMMAND_MEMORY;
++ }
++ if (dev->resource[PCI_ROM_RESOURCE].start)
++ cmd |= PCI_COMMAND_MEMORY;
++ if (cmd != old_cmd) {
++ printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++ }
++ return 0;
++}
++
++int
++pcibios_enable_device(struct pci_dev *dev, int mask)
++{
++ ulong flags;
++ uint coreidx;
++ void *regs;
++
++ /* External PCI device enable */
++ if (dev->bus->number != 0)
++ return pcibios_enable_resources(dev);
++
++ /* These cores come out of reset enabled */
++ if (dev->device == SB_MIPS ||
++ dev->device == SB_MIPS33 ||
++ dev->device == SB_EXTIF ||
++ dev->device == SB_CC)
++ return 0;
++
++ spin_lock_irqsave(&sbh_lock, flags);
++ coreidx = sb_coreidx(sbh);
++ regs = sb_setcoreidx(sbh, PCI_SLOT(dev->devfn));
++ if (!regs)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ /*
++ * The USB core requires a special bit to be set during core
++ * reset to enable host (OHCI) mode. Resetting the SB core in
++ * pcibios_enable_device() is a hack for compatibility with
++ * vanilla usb-ohci so that it does not have to know about
++ * SB. A driver that wants to use the USB core in device mode
++ * should know about SB and should reset the bit back to 0
++ * after calling pcibios_enable_device().
++ */
++ if (sb_coreid(sbh) == SB_USB) {
++ sb_core_disable(sbh, sb_coreflags(sbh, 0, 0));
++ sb_core_reset(sbh, 1 << 29, 0);
++ }
++ /*
++ * USB 2.0 special considerations:
++ *
++ * 1. Since the core supports both OHCI and EHCI functions, it must
++ * only be reset once.
++ *
++ * 2. In addition to the standard SB reset sequence, the Host Control
++ * Register must be programmed to bring the USB core and various
++ * phy components out of reset.
++ */
++ else if (sb_coreid(sbh) == SB_USB20H) {
++ if (!sb_iscoreup(sbh)) {
++ sb_core_reset(sbh, 0, 0);
++ writel(0x7FF, (ulong)regs + 0x200);
++ udelay(1);
++ }
++ } else
++ sb_core_reset(sbh, 0, 0);
++
++ sb_setcoreidx(sbh, coreidx);
++ spin_unlock_irqrestore(&sbh_lock, flags);
++
++ return 0;
++}
++
++void
++pcibios_update_resource(struct pci_dev *dev, struct resource *root,
++ struct resource *res, int resource)
++{
++ unsigned long where, size;
++ u32 reg;
++
++ /* External PCI only */
++ if (dev->bus->number == 0)
++ return;
++
++ where = PCI_BASE_ADDRESS_0 + (resource * 4);
++ size = res->end - res->start;
++ pci_read_config_dword(dev, where, &reg);
++ reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
++ pci_write_config_dword(dev, where, reg);
++}
++
++static void __init
++quirk_sbpci_bridge(struct pci_dev *dev)
++{
++ if (dev->bus->number != 1 || PCI_SLOT(dev->devfn) != 0)
++ return;
++
++ printk("PCI: Fixing up bridge\n");
++
++ /* Enable PCI bridge bus mastering and memory space */
++ pci_set_master(dev);
++ pcibios_enable_resources(dev);
++
++ /* Enable PCI bridge BAR1 prefetch and burst */
++ pci_write_config_dword(dev, PCI_BAR1_CONTROL, 3);
++}
++
++struct pci_fixup pcibios_fixups[] = {
++ { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, quirk_sbpci_bridge },
++ { 0 }
++};
++
++/*
++ * If we set up a device for bus mastering, we need to check the latency
++ * timer as certain crappy BIOSes forget to set it properly.
++ */
++unsigned int pcibios_max_latency = 255;
++
++void pcibios_set_master(struct pci_dev *dev)
++{
++ u8 lat;
++ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
++ if (lat < 16)
++ lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
++ else if (lat > pcibios_max_latency)
++ lat = pcibios_max_latency;
++ else
++ return;
++ printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat);
++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
++}
++
+diff -urN linux.old/arch/mips/bcm947xx/prom.c linux.dev/arch/mips/bcm947xx/prom.c
+--- linux.old/arch/mips/bcm947xx/prom.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/prom.c 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,41 @@
++/*
++ * Early initialization code for BCM94710 boards
++ *
++ * 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.
++ *
++ * $Id: prom.c,v 1.1 2005/03/16 13:49:59 wbx Exp $
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <asm/bootinfo.h>
++
++void __init
++prom_init(int argc, const char **argv)
++{
++ unsigned long mem;
++
++ mips_machgroup = MACH_GROUP_BRCM;
++ mips_machtype = MACH_BCM947XX;
++
++ /* Figure out memory size by finding aliases */
++ for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
++ if (*(unsigned long *)((unsigned long)(prom_init) + mem) ==
++ *(unsigned long *)(prom_init))
++ break;
++ }
++ add_memory_region(0, mem, BOOT_MEM_RAM);
++}
++
++void __init
++prom_free_prom_memory(void)
++{
++}
+diff -urN linux.old/arch/mips/bcm947xx/sbmips.c linux.dev/arch/mips/bcm947xx/sbmips.c
+--- linux.old/arch/mips/bcm947xx/sbmips.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/sbmips.c 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,1132 @@
++/*
++ * BCM47XX Sonics SiliconBackplane MIPS core routines
++ *
++ * 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.
++ *
++ * $Id: hndmips.c,v 1.1.1.1 2006/02/27 03:43:16 honor Exp $
++ */
++
++#include <typedefs.h>
++#include <bcmdefs.h>
++#include <osl.h>
++#include <bcmutils.h>
++#include <sbutils.h>
++#include <bcmdevs.h>
++#include <bcmnvram.h>
++#include <sbconfig.h>
++#include <sbextif.h>
++#include <sbchipc.h>
++#include <sbmemc.h>
++#include <mipsinc.h>
++#include <sbhndmips.h>
++#include <hndcpu.h>
++
++/* sbipsflag register format, indexed by irq. */
++static const uint32 sbips_int_mask[] = {
++ 0, /* placeholder */
++ SBIPS_INT1_MASK,
++ SBIPS_INT2_MASK,
++ SBIPS_INT3_MASK,
++ SBIPS_INT4_MASK
++};
++
++static const uint32 sbips_int_shift[] = {
++ 0, /* placeholder */
++ SBIPS_INT1_SHIFT,
++ SBIPS_INT2_SHIFT,
++ SBIPS_INT3_SHIFT,
++ SBIPS_INT4_SHIFT
++};
++
++/*
++ * Map SB cores sharing the MIPS hardware IRQ0 to virtual dedicated OS IRQs.
++ * Per-port BSP code is required to provide necessary translations between
++ * the shared MIPS IRQ and the virtual OS IRQs based on SB core flag.
++ *
++ * See sb_irq() for the mapping.
++ */
++static uint shirq_map_base = 0;
++
++/* Returns the SB interrupt flag of the current core. */
++static uint32
++sb_getflag(sb_t *sbh)
++{
++ osl_t *osh;
++ void *regs;
++ sbconfig_t *sb;
++
++ osh = sb_osh(sbh);
++ regs = sb_coreregs(sbh);
++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
++
++ return (R_REG(osh, &sb->sbtpsflag) & SBTPS_NUM0_MASK);
++}
++
++/*
++ * Returns the MIPS IRQ assignment of the current core. If unassigned,
++ * 0 is returned.
++ */
++uint
++sb_irq(sb_t *sbh)
++{
++ osl_t *osh;
++ uint idx;
++ void *regs;
++ sbconfig_t *sb;
++ uint32 flag, sbipsflag;
++ uint irq = 0;
++
++ osh = sb_osh(sbh);
++ flag = sb_getflag(sbh);
++
++ idx = sb_coreidx(sbh);
++
++ if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
++ (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
++
++ /* sbipsflag specifies which core is routed to interrupts 1 to 4 */
++ sbipsflag = R_REG(osh, &sb->sbipsflag);
++ for (irq = 1; irq <= 4; irq++) {
++ if (((sbipsflag & sbips_int_mask[irq]) >> sbips_int_shift[irq]) == flag)
++ break;
++ }
++ if (irq == 5)
++ irq = 0;
++ }
++
++ sb_setcoreidx(sbh, idx);
++
++ return irq;
++}
++
++/* Clears the specified MIPS IRQ. */
++static void
++BCMINITFN(sb_clearirq)(sb_t *sbh, uint irq)
++{
++ osl_t *osh;
++ void *regs;
++ sbconfig_t *sb;
++
++ osh = sb_osh(sbh);
++
++ if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
++ !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
++ ASSERT(regs);
++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
++
++ if (irq == 0)
++ W_REG(osh, &sb->sbintvec, 0);
++ else
++ OR_REG(osh, &sb->sbipsflag, sbips_int_mask[irq]);
++}
++
++/*
++ * Assigns the specified MIPS IRQ to the specified core. Shared MIPS
++ * IRQ 0 may be assigned more than once.
++ *
++ * The old assignment to the specified core is removed first.
++ */
++static void
++BCMINITFN(sb_setirq)(sb_t *sbh, uint irq, uint coreid, uint coreunit)
++{
++ osl_t *osh;
++ void *regs;
++ sbconfig_t *sb;
++ uint32 flag;
++ uint oldirq;
++
++ osh = sb_osh(sbh);
++
++ regs = sb_setcore(sbh, coreid, coreunit);
++ ASSERT(regs);
++ flag = sb_getflag(sbh);
++ oldirq = sb_irq(sbh);
++ if (oldirq)
++ sb_clearirq(sbh, oldirq);
++
++ if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
++ !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
++ ASSERT(regs);
++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
++
++ if (!oldirq)
++ AND_REG(osh, &sb->sbintvec, ~(1 << flag));
++
++ if (irq == 0)
++ OR_REG(osh, &sb->sbintvec, 1 << flag);
++ else {
++ flag <<= sbips_int_shift[irq];
++ ASSERT(!(flag & ~sbips_int_mask[irq]));
++ flag |= R_REG(osh, &sb->sbipsflag) & ~sbips_int_mask[irq];
++ W_REG(osh, &sb->sbipsflag, flag);
++ }
++}
++
++/*
++ * Initializes clocks and interrupts. SB and NVRAM access must be
++ * initialized prior to calling.
++ *
++ * 'shirqmap' enables virtual dedicated OS IRQ mapping if non-zero.
++ */
++void
++BCMINITFN(sb_mips_init)(sb_t *sbh, uint shirqmap)
++{
++ osl_t *osh;
++ ulong hz, ns, tmp;
++ extifregs_t *eir;
++ chipcregs_t *cc;
++ char *value;
++ uint irq;
++
++ osh = sb_osh(sbh);
++
++ /* Figure out current SB clock speed */
++ if ((hz = sb_clock(sbh)) == 0)
++ hz = 100000000;
++ ns = 1000000000 / hz;
++
++ /* Setup external interface timing */
++ if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) {
++ /* Initialize extif so we can get to the LEDs and external UART */
++ W_REG(osh, &eir->prog_config, CF_EN);
++
++ /* Set timing for the flash */
++ tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
++ tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */
++ tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
++ W_REG(osh, &eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
++
++ /* Set programmable interface timing for external uart */
++ tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
++ tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */
++ tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */
++ tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
++ W_REG(osh, &eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
++ } else if ((cc = sb_setcore(sbh, SB_CC, 0))) {
++ /* Set timing for the flash */
++ tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
++ tmp |= CEIL(10, ns) << FW_W1_SHIFT; /* W1 = 10nS */
++ tmp |= CEIL(120, ns); /* W0 = 120nS */
++ if ((sb_corerev(sbh) < 9) ||
++ (BCMINIT(sb_chip)(sbh) == 0x5365))
++ W_REG(osh, &cc->flash_waitcount, tmp);
++
++ if ((sb_corerev(sbh) < 9) ||
++ ((sb_chip(sbh) == BCM5350_CHIP_ID) && sb_chiprev(sbh) == 0) ||
++ (BCMINIT(sb_chip)(sbh) == 0x5365)) {
++ W_REG(osh, &cc->pcmcia_memwait, tmp);
++ }
++
++ /* Save shared IRQ mapping base */
++ shirq_map_base = shirqmap;
++ }
++
++ /* Chip specific initialization */
++ switch (sb_chip(sbh)) {
++ case BCM4710_CHIP_ID:
++ /* Clear interrupt map */
++ for (irq = 0; irq <= 4; irq++)
++ sb_clearirq(sbh, irq);
++ sb_setirq(sbh, 0, SB_CODEC, 0);
++ sb_setirq(sbh, 0, SB_EXTIF, 0);
++ sb_setirq(sbh, 2, SB_ENET, 1);
++ sb_setirq(sbh, 3, SB_ILINE20, 0);
++ sb_setirq(sbh, 4, SB_PCI, 0);
++ ASSERT(eir);
++ value = nvram_get("et0phyaddr");
++ if (value && !strcmp(value, "31")) {
++ /* Enable internal UART */
++ W_REG(osh, &eir->corecontrol, CC_UE);
++ /* Give USB its own interrupt */
++ sb_setirq(sbh, 1, SB_USB, 0);
++ } else {
++ /* Disable internal UART */
++ W_REG(osh, &eir->corecontrol, 0);
++ /* Give Ethernet its own interrupt */
++ sb_setirq(sbh, 1, SB_ENET, 0);
++ sb_setirq(sbh, 0, SB_USB, 0);
++ }
++ break;
++ case BCM5350_CHIP_ID:
++ /* Clear interrupt map */
++ for (irq = 0; irq <= 4; irq++)
++ sb_clearirq(sbh, irq);
++ sb_setirq(sbh, 0, SB_CC, 0);
++ sb_setirq(sbh, 0, SB_MIPS33, 0);
++ sb_setirq(sbh, 1, SB_D11, 0);
++ sb_setirq(sbh, 2, SB_ENET, 0);
++ sb_setirq(sbh, 3, SB_PCI, 0);
++ sb_setirq(sbh, 4, SB_USB, 0);
++ break;
++ case BCM4785_CHIP_ID:
++ /* Reassign PCI to irq 4 */
++ sb_setirq(sbh, 4, SB_PCI, 0);
++ break;
++ }
++}
++
++uint32
++BCMINITFN(sb_cpu_clock)(sb_t *sbh)
++{
++ extifregs_t *eir;
++ chipcregs_t *cc;
++ uint32 n, m;
++ uint idx;
++ uint32 pll_type, rate = 0;
++
++ /* get index of the current core */
++ idx = sb_coreidx(sbh);
++ pll_type = PLL_TYPE1;
++
++ /* switch to extif or chipc core */
++ if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
++ n = R_REG(osh, &eir->clockcontrol_n);
++ m = R_REG(osh, &eir->clockcontrol_sb);
++ } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
++ pll_type = R_REG(osh, &cc->capabilities) & CAP_PLL_MASK;
++ n = R_REG(osh, &cc->clockcontrol_n);
++ if ((pll_type == PLL_TYPE2) ||
++ (pll_type == PLL_TYPE4) ||
++ (pll_type == PLL_TYPE6) ||
++ (pll_type == PLL_TYPE7))
++ m = R_REG(osh, &cc->clockcontrol_m3);
++ else if (pll_type == PLL_TYPE5) {
++ rate = 200000000;
++ goto out;
++ }
++ else if (pll_type == PLL_TYPE3) {
++ if (sb_chip(sbh) == BCM5365_CHIP_ID) {
++ rate = 200000000;
++ goto out;
++ }
++ /* 5350 uses m2 to control mips */
++ else
++ m = R_REG(osh, &cc->clockcontrol_m2);
++ } else
++ m = R_REG(osh, &cc->clockcontrol_sb);
++ } else
++ goto out;
++
++
++ /* calculate rate */
++ if (BCMINIT(sb_chip)(sbh) == 0x5365)
++ rate = 100000000;
++ else
++ rate = sb_clock_rate(pll_type, n, m);
++
++ if (pll_type == PLL_TYPE6)
++ rate = SB2MIPS_T6(rate);
++
++out:
++ /* switch back to previous core */
++ sb_setcoreidx(sbh, idx);
++
++ return rate;
++}
++
++#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
++
++static void
++BCMINITFN(handler)(void)
++{
++ __asm__(
++ ".set\tmips32\n\t"
++ "ssnop\n\t"
++ "ssnop\n\t"
++ /* Disable interrupts */
++ /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */
++ "mfc0 $15, $12\n\t"
++ /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */
++ "li $14, -31746\n\t"
++ "and $15, $15, $14\n\t"
++ "mtc0 $15, $12\n\t"
++ "eret\n\t"
++ "nop\n\t"
++ "nop\n\t"
++ ".set\tmips0");
++}
++
++/* The following MUST come right after handler() */
++static void
++BCMINITFN(afterhandler)(void)
++{
++}
++
++/*
++ * Set the MIPS, backplane and PCI clocks as closely as possible.
++ *
++ * MIPS clocks synchronization function has been moved from PLL in chipcommon
++ * core rev. 15 to a DLL inside the MIPS core in 4785.
++ */
++bool
++BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 pciclock)
++{
++ extifregs_t *eir = NULL;
++ chipcregs_t *cc = NULL;
++ mipsregs_t *mipsr = NULL;
++ volatile uint32 *clockcontrol_n, *clockcontrol_sb, *clockcontrol_pci, *clockcontrol_m2;
++ uint32 orig_n, orig_sb, orig_pci, orig_m2, orig_mips, orig_ratio_parm, orig_ratio_cfg;
++ uint32 pll_type, sync_mode;
++ uint ic_size, ic_lsize;
++ uint idx, i;
++
++ /* PLL configuration: type 1 */
++ typedef struct {
++ uint32 mipsclock;
++ uint16 n;
++ uint32 sb;
++ uint32 pci33;
++ uint32 pci25;
++ } n3m_table_t;
++ static n3m_table_t BCMINITDATA(type1_table)[] = {
++ /* 96.000 32.000 24.000 */
++ { 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011 },
++ /* 100.000 33.333 25.000 */
++ { 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011 },
++ /* 104.000 31.200 24.960 */
++ { 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009 },
++ /* 108.000 32.400 24.923 */
++ { 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802 },
++ /* 112.000 32.000 24.889 */
++ { 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403 },
++ /* 115.200 32.000 24.000 */
++ { 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011 },
++ /* 120.000 30.000 24.000 */
++ { 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011 },
++ /* 124.800 31.200 24.960 */
++ { 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009 },
++ /* 128.000 32.000 24.000 */
++ { 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305 },
++ /* 132.000 33.000 24.750 */
++ { 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305 },
++ /* 136.000 32.640 24.727 */
++ { 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603 },
++ /* 140.000 30.000 24.706 */
++ { 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02 },
++ /* 144.000 30.857 24.686 */
++ { 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021 },
++ /* 150.857 33.000 24.000 */
++ { 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605 },
++ /* 152.000 32.571 24.000 */
++ { 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02 },
++ /* 156.000 31.200 24.960 */
++ { 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009 },
++ /* 160.000 32.000 24.000 */
++ { 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309 },
++ /* 163.200 32.640 24.727 */
++ { 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603 },
++ /* 168.000 32.000 24.889 */
++ { 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403 },
++ /* 176.000 33.000 24.000 */
++ { 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602 },
++ };
++
++ /* PLL configuration: type 3 */
++ typedef struct {
++ uint32 mipsclock;
++ uint16 n;
++ uint32 m2; /* that is the clockcontrol_m2 */
++ } type3_table_t;
++ static type3_table_t type3_table[] = {
++ /* for 5350, mips clock is always double sb clock */
++ { 150000000, 0x311, 0x4020005 },
++ { 200000000, 0x311, 0x4020003 },
++ };
++
++ /* PLL configuration: type 2, 4, 7 */
++ typedef struct {
++ uint32 mipsclock;
++ uint32 sbclock;
++ uint16 n;
++ uint32 sb;
++ uint32 pci33;
++ uint32 m2;
++ uint32 m3;
++ uint32 ratio_cfg;
++ uint32 ratio_parm;
++ uint32 d11_r1;
++ uint32 d11_r2;
++ } n4m_table_t;
++ static n4m_table_t BCMINITDATA(type2_table)[] = {
++ { 120000000, 60000000, 0x0303, 0x01000200, 0x01000600, 0x01000200, 0x05000200, 11,
++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
++ { 150000000, 75000000, 0x0303, 0x01000100, 0x01000600, 0x01000100, 0x05000100, 11,
++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
++ { 180000000, 80000000, 0x0403, 0x01010000, 0x01020300, 0x01020600, 0x05000100, 8,
++ 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
++ { 180000000, 90000000, 0x0403, 0x01000100, 0x01020300, 0x01000100, 0x05000100, 11,
++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
++ { 200000000, 100000000, 0x0303, 0x02010000, 0x02040001, 0x02010000, 0x06000001, 11,
++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
++ { 211200000, 105600000, 0x0902, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11,
++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
++ { 220800000, 110400000, 0x1500, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11,
++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
++ { 230400000, 115200000, 0x0604, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11,
++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
++ { 234000000, 104000000, 0x0b01, 0x01010000, 0x01010700, 0x01020600, 0x05000100, 8,
++ 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
++ { 240000000, 120000000, 0x0803, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11,
++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
++ { 252000000, 126000000, 0x0504, 0x01000100, 0x01020500, 0x01000100, 0x05000100, 11,
++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
++ { 264000000, 132000000, 0x0903, 0x01000200, 0x01020700, 0x01000200, 0x05000200, 11,
++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
++ { 270000000, 120000000, 0x0703, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8,
++ 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
++ { 276000000, 122666666, 0x1500, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8,
++ 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
++ { 280000000, 140000000, 0x0503, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11,
++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
++ { 288000000, 128000000, 0x0604, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8,
++ 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
++ { 288000000, 144000000, 0x0404, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11,
++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
++ { 300000000, 133333333, 0x0803, 0x01010000, 0x01020600, 0x01010100, 0x05000100, 8,
++ 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 },
++ { 300000000, 150000000, 0x0803, 0x01000100, 0x01020600, 0x01010100, 0x05000100, 11,
++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 },
++ { 330000000, 132000000, 0x0903, 0x01000200, 0x00020200, 0x01010100, 0x05000100, 0,
++ 0, 10 /* ratio 4/10 */, 0x02520129 },
++ { 330000000, 146666666, 0x0903, 0x01010000, 0x00020200, 0x01010100, 0x05000100, 0,
++ 0, 9 /* ratio 4/9 */, 0x012a00a9 },
++ { 330000000, 165000000, 0x0903, 0x01000100, 0x00020200, 0x01010100, 0x05000100, 0,
++ 0, 8 /* ratio 4/8 */, 0x00aa0055 },
++ { 360000000, 120000000, 0x0a03, 0x01000300, 0x00010201, 0x01010200, 0x05000100, 0,
++ 0, 12 /* ratio 4/12 */, 0x04920492 },
++ { 360000000, 144000000, 0x0a03, 0x01000200, 0x00010201, 0x01010200, 0x05000100, 0,
++ 0, 10 /* ratio 4/10 */, 0x02520129 },
++ { 360000000, 160000000, 0x0a03, 0x01010000, 0x00010201, 0x01010200, 0x05000100, 0,
++ 0, 9 /* ratio 4/9 */, 0x012a00a9 },
++ { 360000000, 180000000, 0x0a03, 0x01000100, 0x00010201, 0x01010200, 0x05000100, 0,
++ 0, 8 /* ratio 4/8 */, 0x00aa0055 },
++ { 390000000, 130000000, 0x0b03, 0x01010100, 0x00020101, 0x01020100, 0x05000100, 0,
++ 0, 12 /* ratio 4/12 */, 0x04920492 },
++ { 390000000, 156000000, 0x0b03, 0x01000200, 0x00020101, 0x01020100, 0x05000100, 0,
++ 0, 10 /* ratio 4/10 */, 0x02520129 },
++ { 390000000, 173000000, 0x0b03, 0x01010000, 0x00020101, 0x01020100, 0x05000100, 0,
++ 0, 9 /* ratio 4/9 */, 0x012a00a9 },
++ { 390000000, 195000000, 0x0b03, 0x01000100, 0x00020101, 0x01020100, 0x05000100, 0,
++ 0, 8 /* ratio 4/8 */, 0x00aa0055 },
++ };
++ static n4m_table_t BCMINITDATA(type4_table)[] = {
++ { 120000000, 60000000, 0x0009, 0x11020009, 0x01030203, 0x11020009, 0x04000009, 11,
++ 0x0aaa0555 },
++ { 150000000, 75000000, 0x0009, 0x11050002, 0x01030203, 0x11050002, 0x04000005, 11,
++ 0x0aaa0555 },
++ { 192000000, 96000000, 0x0702, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11,
++ 0x0aaa0555 },
++ { 198000000, 99000000, 0x0603, 0x11020005, 0x11030011, 0x11020005, 0x04000005, 11,
++ 0x0aaa0555 },
++ { 200000000, 100000000, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11,
++ 0x0aaa0555 },
++ { 204000000, 102000000, 0x0c02, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11,
++ 0x0aaa0555 },
++ { 208000000, 104000000, 0x0802, 0x11030002, 0x11090005, 0x11030002, 0x04000003, 11,
++ 0x0aaa0555 },
++ { 210000000, 105000000, 0x0209, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11,
++ 0x0aaa0555 },
++ { 216000000, 108000000, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11,
++ 0x0aaa0555 },
++ { 224000000, 112000000, 0x0205, 0x11030002, 0x02002103, 0x11030002, 0x04000003, 11,
++ 0x0aaa0555 },
++ { 228000000, 101333333, 0x0e02, 0x11030003, 0x11210005, 0x01030305, 0x04000005, 8,
++ 0x012a00a9 },
++ { 228000000, 114000000, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11,
++ 0x0aaa0555 },
++ { 240000000, 102857143, 0x0109, 0x04000021, 0x01050203, 0x11030021, 0x04000003, 13,
++ 0x254a14a9 },
++ { 240000000, 120000000, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003, 11,
++ 0x0aaa0555 },
++ { 252000000, 100800000, 0x0203, 0x04000009, 0x11050005, 0x02000209, 0x04000002, 9,
++ 0x02520129 },
++ { 252000000, 126000000, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11,
++ 0x0aaa0555 },
++ { 264000000, 132000000, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11,
++ 0x0aaa0555 },
++ { 272000000, 116571428, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003, 13,
++ 0x254a14a9 },
++ { 280000000, 120000000, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13,
++ 0x254a14a9 },
++ { 288000000, 123428571, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13,
++ 0x254a14a9 },
++ { 300000000, 120000000, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002, 9,
++ 0x02520129 },
++ { 300000000, 150000000, 0x0009, 0x04000005, 0x01030203, 0x04000005, 0x04000002, 11,
++ 0x0aaa0555 }
++ };
++ static n4m_table_t BCMINITDATA(type7_table)[] = {
++ { 183333333, 91666666, 0x0605, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11,
++ 0x0aaa0555 },
++ { 187500000, 93750000, 0x0a03, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11,
++ 0x0aaa0555 },
++ { 196875000, 98437500, 0x1003, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11,
++ 0x0aaa0555 },
++ { 200000000, 100000000, 0x0311, 0x04000011, 0x11030011, 0x04000009, 0x04000003, 11,
++ 0x0aaa0555 },
++ { 200000000, 100000000, 0x0311, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11,
++ 0x0aaa0555 },
++ { 206250000, 103125000, 0x1103, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11,
++ 0x0aaa0555 },
++ { 212500000, 106250000, 0x0c05, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11,
++ 0x0aaa0555 },
++ { 215625000, 107812500, 0x1203, 0x11090009, 0x11050005, 0x11020005, 0x04000005, 11,
++ 0x0aaa0555 },
++ { 216666666, 108333333, 0x0805, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11,
++ 0x0aaa0555 },
++ { 225000000, 112500000, 0x0d03, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11,
++ 0x0aaa0555 },
++ { 233333333, 116666666, 0x0905, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11,
++ 0x0aaa0555 },
++ { 237500000, 118750000, 0x0e05, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11,
++ 0x0aaa0555 },
++ { 240000000, 120000000, 0x0b11, 0x11020009, 0x11210009, 0x11020009, 0x04000009, 11,
++ 0x0aaa0555 },
++ { 250000000, 125000000, 0x0f03, 0x11020003, 0x11210003, 0x11020003, 0x04000003, 11,
++ 0x0aaa0555 }
++ };
++
++ ulong start, end, dst;
++ bool ret = FALSE;
++
++ volatile uint32 *dll_ctrl = (volatile uint32 *)0xff400008;
++ volatile uint32 *dll_r1 = (volatile uint32 *)0xff400010;
++ volatile uint32 *dll_r2 = (volatile uint32 *)0xff400018;
++
++ /* get index of the current core */
++ idx = sb_coreidx(sbh);
++ clockcontrol_m2 = NULL;
++
++ /* switch to extif or chipc core */
++ if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
++ pll_type = PLL_TYPE1;
++ clockcontrol_n = &eir->clockcontrol_n;
++ clockcontrol_sb = &eir->clockcontrol_sb;
++ clockcontrol_pci = &eir->clockcontrol_pci;
++ clockcontrol_m2 = &cc->clockcontrol_m2;
++ } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
++ pll_type = R_REG(osh, &cc->capabilities) & CAP_PLL_MASK;
++ if (pll_type == PLL_TYPE6) {
++ clockcontrol_n = NULL;
++ clockcontrol_sb = NULL;
++ clockcontrol_pci = NULL;
++ } else {
++ clockcontrol_n = &cc->clockcontrol_n;
++ clockcontrol_sb = &cc->clockcontrol_sb;
++ clockcontrol_pci = &cc->clockcontrol_pci;
++ clockcontrol_m2 = &cc->clockcontrol_m2;
++ }
++ } else
++ goto done;
++
++ if (pll_type == PLL_TYPE6) {
++ /* Silence compilers */
++ orig_n = orig_sb = orig_pci = 0;
++ } else {
++ /* Store the current clock register values */
++ orig_n = R_REG(osh, clockcontrol_n);
++ orig_sb = R_REG(osh, clockcontrol_sb);
++ orig_pci = R_REG(osh, clockcontrol_pci);
++ }
++
++ if (pll_type == PLL_TYPE1) {
++ /* Keep the current PCI clock if not specified */
++ if (pciclock == 0) {
++ pciclock = sb_clock_rate(pll_type, R_REG(osh, clockcontrol_n),
++ R_REG(osh, clockcontrol_pci));
++ pciclock = (pciclock <= 25000000) ? 25000000 : 33000000;
++ }
++
++ /* Search for the closest MIPS clock less than or equal to a preferred value */
++ for (i = 0; i < ARRAYSIZE(type1_table); i++) {
++ ASSERT(type1_table[i].mipsclock ==
++ sb_clock_rate(pll_type, type1_table[i].n,
++ type1_table[i].sb));
++ if (type1_table[i].mipsclock > mipsclock)
++ break;
++ }
++ if (i == 0) {
++ ret = FALSE;
++ goto done;
++ } else {
++ ret = TRUE;
++ i--;
++ }
++ ASSERT(type1_table[i].mipsclock <= mipsclock);
++
++ /* No PLL change */
++ if ((orig_n == type1_table[i].n) &&
++ (orig_sb == type1_table[i].sb) &&
++ (orig_pci == type1_table[i].pci33))
++ goto done;
++
++ /* Set the PLL controls */
++ W_REG(osh, clockcontrol_n, type1_table[i].n);
++ W_REG(osh, clockcontrol_sb, type1_table[i].sb);
++ if (pciclock == 25000000)
++ W_REG(osh, clockcontrol_pci, type1_table[i].pci25);
++ else
++ W_REG(osh, clockcontrol_pci, type1_table[i].pci33);
++
++ /* Reset */
++ sb_watchdog(sbh, 1);
++ while (1);
++ } else if (pll_type == PLL_TYPE3) {
++ /* 5350 */
++ if (sb_chip(sbh) != BCM5365_CHIP_ID) {
++ /*
++ * Search for the closest MIPS clock less than or equal to
++ * a preferred value.
++ */
++ for (i = 0; i < ARRAYSIZE(type3_table); i++) {
++ if (type3_table[i].mipsclock > mipsclock)
++ break;
++ }
++ if (i == 0) {
++ ret = FALSE;
++ goto done;
++ } else {
++ ret = TRUE;
++ i--;
++ }
++ ASSERT(type3_table[i].mipsclock <= mipsclock);
++
++ /* No PLL change */
++ orig_m2 = R_REG(osh, &cc->clockcontrol_m2);
++ if ((orig_n == type3_table[i].n) &&
++ (orig_m2 == type3_table[i].m2)) {
++ goto done;
++ }
++
++ /* Set the PLL controls */
++ W_REG(osh, clockcontrol_n, type3_table[i].n);
++ W_REG(osh, clockcontrol_m2, type3_table[i].m2);
++
++ /* Reset */
++ sb_watchdog(sbh, 1);
++ while (1);
++ }
++ } else if ((pll_type == PLL_TYPE2) ||
++ (pll_type == PLL_TYPE4) ||
++ (pll_type == PLL_TYPE6) ||
++ (pll_type == PLL_TYPE7)) {
++ n4m_table_t *table = NULL, *te;
++ uint tabsz = 0;
++
++ ASSERT(cc);
++
++ orig_mips = R_REG(osh, &cc->clockcontrol_m3);
++
++ switch (pll_type) {
++ case PLL_TYPE6: {
++ uint32 new_mips = 0;
++
++ ret = TRUE;
++ if (mipsclock <= SB2MIPS_T6(CC_T6_M1))
++ new_mips = CC_T6_MMASK;
++
++ if (orig_mips == new_mips)
++ goto done;
++
++ W_REG(osh, &cc->clockcontrol_m3, new_mips);
++ goto end_fill;
++ }
++ case PLL_TYPE2:
++ table = type2_table;
++ tabsz = ARRAYSIZE(type2_table);
++ break;
++ case PLL_TYPE4:
++ table = type4_table;
++ tabsz = ARRAYSIZE(type4_table);
++ break;
++ case PLL_TYPE7:
++ table = type7_table;
++ tabsz = ARRAYSIZE(type7_table);
++ break;
++ default:
++ ASSERT("No table for plltype" == NULL);
++ break;
++ }
++
++ /* Store the current clock register values */
++ orig_m2 = R_REG(osh, &cc->clockcontrol_m2);
++ orig_ratio_parm = 0;
++ orig_ratio_cfg = 0;
++
++ /* Look up current ratio */
++ for (i = 0; i < tabsz; i++) {
++ if ((orig_n == table[i].n) &&
++ (orig_sb == table[i].sb) &&
++ (orig_pci == table[i].pci33) &&
++ (orig_m2 == table[i].m2) &&
++ (orig_mips == table[i].m3)) {
++ orig_ratio_parm = table[i].ratio_parm;
++ orig_ratio_cfg = table[i].ratio_cfg;
++ break;
++ }
++ }
++
++ /* Search for the closest MIPS clock greater or equal to a preferred value */
++ for (i = 0; i < tabsz; i++) {
++ ASSERT(table[i].mipsclock ==
++ sb_clock_rate(pll_type, table[i].n, table[i].m3));
++ if ((mipsclock <= table[i].mipsclock) &&
++ ((sbclock == 0) || (sbclock <= table[i].sbclock)))
++ break;
++ }
++ if (i == tabsz) {
++ ret = FALSE;
++ goto done;
++ } else {
++ te = &table[i];
++ ret = TRUE;
++ }
++
++ /* No PLL change */
++ if ((orig_n == te->n) &&
++ (orig_sb == te->sb) &&
++ (orig_pci == te->pci33) &&
++ (orig_m2 == te->m2) &&
++ (orig_mips == te->m3))
++ goto done;
++
++ /* Set the PLL controls */
++ W_REG(osh, clockcontrol_n, te->n);
++ W_REG(osh, clockcontrol_sb, te->sb);
++ W_REG(osh, clockcontrol_pci, te->pci33);
++ W_REG(osh, &cc->clockcontrol_m2, te->m2);
++ W_REG(osh, &cc->clockcontrol_m3, te->m3);
++
++ /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */
++ if ((pll_type == PLL_TYPE7) && (te->sb != te->m2) &&
++ (sb_clock_rate(pll_type, te->n, te->m2) == 120000000))
++ W_REG(osh, &cc->chipcontrol,
++ R_REG(osh, &cc->chipcontrol) | 0x100);
++
++ /* No ratio change */
++ if (sb_chip(sbh) != BCM4785_CHIP_ID) {
++ if (orig_ratio_parm == te->ratio_parm)
++ goto end_fill;
++ }
++
++ /* Preload the code into the cache */
++ icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize);
++ if (sb_chip(sbh) == BCM4785_CHIP_ID) {
++ start = ((ulong) &&start_fill_4785) & ~(ic_lsize - 1);
++ end = ((ulong) &&end_fill_4785 + (ic_lsize - 1)) & ~(ic_lsize - 1);
++ }
++ else {
++ start = ((ulong) &&start_fill) & ~(ic_lsize - 1);
++ end = ((ulong) &&end_fill + (ic_lsize - 1)) & ~(ic_lsize - 1);
++ }
++ while (start < end) {
++ cache_op(start, Fill_I);
++ start += ic_lsize;
++ }
++
++ /* Copy the handler */
++ start = (ulong) &handler;
++ end = (ulong) &afterhandler;
++ dst = KSEG1ADDR(0x180);
++ for (i = 0; i < (end - start); i += 4)
++ *((ulong *)(dst + i)) = *((ulong *)(start + i));
++
++ /* Preload the handler into the cache one line at a time */
++ for (i = 0; i < (end - start); i += ic_lsize)
++ cache_op(dst + i, Fill_I);
++
++ /* Clear BEV bit */
++ MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~ST0_BEV);
++
++ /* Enable interrupts */
++ MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) | (ALLINTS | ST0_IE));
++
++ /* 4785 clock freq change procedures */
++ if (sb_chip(sbh) == BCM4785_CHIP_ID) {
++ start_fill_4785:
++ /* Switch to async */
++ MTC0(C0_BROADCOM, 4, (1 << 22));
++
++ /* Set clock ratio in MIPS */
++ *dll_r1 = (*dll_r1 & 0xfffffff0) | (te->d11_r1 - 1);
++ *dll_r2 = te->d11_r2;
++
++ /* Enable new settings in MIPS */
++ *dll_r1 = *dll_r1 | 0xc0000000;
++
++ /* Set active cfg */
++ MTC0(C0_BROADCOM, 2, MFC0(C0_BROADCOM, 2) | (1 << 3) | 1);
++
++ /* Fake soft reset (clock cfg registers not reset) */
++ MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | (1 << 2));
++
++ /* Clear active cfg */
++ MTC0(C0_BROADCOM, 2, MFC0(C0_BROADCOM, 2) & ~(1 << 3));
++
++ /* set watchdog timer */
++ W_REG(osh, &cc->watchdog, 20);
++ (void) R_REG(osh, &cc->chipid);
++
++ /* wait for timer interrupt */
++ __asm__ __volatile__(
++ ".set\tmips3\n\t"
++ "sync\n\t"
++ "wait\n\t"
++ ".set\tmips0");
++ end_fill_4785:
++ while (1);
++ }
++ /* Generic clock freq change procedures */
++ else {
++ /* Enable MIPS timer interrupt */
++ if (!(mipsr = sb_setcore(sbh, SB_MIPS, 0)) &&
++ !(mipsr = sb_setcore(sbh, SB_MIPS33, 0)))
++ ASSERT(mipsr);
++ W_REG(osh, &mipsr->intmask, 1);
++
++ start_fill:
++ /* step 1, set clock ratios */
++ MTC0(C0_BROADCOM, 3, te->ratio_parm);
++ MTC0(C0_BROADCOM, 1, te->ratio_cfg);
++
++ /* step 2: program timer intr */
++ W_REG(osh, &mipsr->timer, 100);
++ (void) R_REG(osh, &mipsr->timer);
++
++ /* step 3, switch to async */
++ sync_mode = MFC0(C0_BROADCOM, 4);
++ MTC0(C0_BROADCOM, 4, 1 << 22);
++
++ /* step 4, set cfg active */
++ MTC0(C0_BROADCOM, 2, (1 << 3) | 1);
++
++ /* steps 5 & 6 */
++ __asm__ __volatile__(
++ ".set\tmips3\n\t"
++ "wait\n\t"
++ ".set\tmips0");
++
++ /* step 7, clear cfg active */
++ MTC0(C0_BROADCOM, 2, 0);
++
++ /* Additional Step: set back to orig sync mode */
++ MTC0(C0_BROADCOM, 4, sync_mode);
++
++ /* step 8, fake soft reset */
++ MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | (1 << 2));
++
++ end_fill:
++ /* set watchdog timer */
++ W_REG(osh, &cc->watchdog, 20);
++ (void) R_REG(osh, &cc->chipid);
++
++ /* wait for timer interrupt */
++ __asm__ __volatile__(
++ ".set\tmips3\n\t"
++ "sync\n\t"
++ "wait\n\t"
++ ".set\tmips0");
++ while (1);
++ }
++ }
++
++done:
++ /* Enable 4785 DLL */
++ if (sb_chip(sbh) == BCM4785_CHIP_ID) {
++ uint32 tmp;
++
++ /* set mask to 1e, enable DLL (bit 0) */
++ *dll_ctrl |= 0x0041e021;
++
++ /* enable aggressive hardware mode */
++ *dll_ctrl |= 0x00000080;
++
++ /* wait for lock flag to clear */
++ while ((*dll_ctrl & 0x2) == 0);
++
++ /* clear sticky flags (clear on write 1) */
++ tmp = *dll_ctrl;
++ *dll_ctrl = tmp;
++
++ /* set mask to 5b'10001 */
++ *dll_ctrl = (*dll_ctrl & 0xfffc1fff) | 0x00022000;
++
++ /* enable sync mode */
++ MTC0(C0_BROADCOM, 4, MFC0(C0_BROADCOM, 4) & 0xfe3fffff);
++ (void)MFC0(C0_BROADCOM, 4);
++ }
++
++ /* switch back to previous core */
++ sb_setcoreidx(sbh, idx);
++
++ return ret;
++}
++
++void
++BCMINITFN(enable_pfc)(uint32 mode)
++{
++ ulong start, end;
++ uint ic_size, ic_lsize;
++
++ /* If auto then choose the correct mode for this
++ * platform, currently we only ever select one mode
++ */
++ if (mode == PFC_AUTO)
++ mode = PFC_INST;
++
++ icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize);
++
++ /* enable prefetch cache if available */
++ if (MFC0(C0_BROADCOM, 0) & BRCM_PFC_AVAIL) {
++ start = ((ulong) &&setpfc_start) & ~(ic_lsize - 1);
++ end = ((ulong) &&setpfc_end + (ic_lsize - 1)) & ~(ic_lsize - 1);
++
++ /* Preload setpfc code into the cache one line at a time */
++ while (start < end) {
++ cache_op(start, Fill_I);
++ start += ic_lsize;
++ }
++
++ /* Now set the pfc */
++ setpfc_start:
++ /* write range */
++ *(volatile uint32 *)PFC_CR1 = 0xffff0000;
++
++ /* enable */
++ *(volatile uint32 *)PFC_CR0 = mode;
++ setpfc_end:
++ /* Compiler foder */
++ ic_size = 0;
++ }
++}
++
++/* returns the ncdl value to be programmed into sdram_ncdl for calibration */
++uint32
++BCMINITFN(sb_memc_get_ncdl)(sb_t *sbh)
++{
++ osl_t *osh;
++ sbmemcregs_t *memc;
++ uint32 ret = 0;
++ uint32 config, rd, wr, misc, dqsg, cd, sm, sd;
++ uint idx, rev;
++
++ osh = sb_osh(sbh);
++
++ idx = sb_coreidx(sbh);
++
++ memc = (sbmemcregs_t *)sb_setcore(sbh, SB_MEMC, 0);
++ if (memc == 0)
++ goto out;
++
++ rev = sb_corerev(sbh);
++
++ config = R_REG(osh, &memc->config);
++ wr = R_REG(osh, &memc->wrncdlcor);
++ rd = R_REG(osh, &memc->rdncdlcor);
++ misc = R_REG(osh, &memc->miscdlyctl);
++ dqsg = R_REG(osh, &memc->dqsgatencdl);
++
++ rd &= MEMC_RDNCDLCOR_RD_MASK;
++ wr &= MEMC_WRNCDLCOR_WR_MASK;
++ dqsg &= MEMC_DQSGATENCDL_G_MASK;
++
++ if (config & MEMC_CONFIG_DDR) {
++ ret = (wr << 16) | (rd << 8) | dqsg;
++ } else {
++ if (rev > 0)
++ cd = rd;
++ else
++ cd = (rd == MEMC_CD_THRESHOLD) ? rd : (wr + MEMC_CD_THRESHOLD);
++ sm = (misc & MEMC_MISC_SM_MASK) >> MEMC_MISC_SM_SHIFT;
++ sd = (misc & MEMC_MISC_SD_MASK) >> MEMC_MISC_SD_SHIFT;
++ ret = (sm << 16) | (sd << 8) | cd;
++ }
++
++out:
++ /* switch back to previous core */
++ sb_setcoreidx(sbh, idx);
++
++ return ret;
++}
++
++#if defined(BCMPERFSTATS)
++/*
++ * CP0 Register 25 supports 4 semi-independent 32bit performance counters.
++ * $25 select 0, 1, 2, and 3 are the counters. The counters *decrement* (who thought this one up?)
++ * $25 select 4 and 5 each contain 2-16bit control fields, one for each of the 4 counters
++ * $25 select 6 is the global perf control register.
++ */
++/* enable and start instruction counting */
++
++void
++hndmips_perf_instrcount_enable()
++{
++ MTC0(C0_PERFORMANCE, 6, 0x80000200); /* global enable perf counters */
++ MTC0(C0_PERFORMANCE, 4,
++ 0x8044 | MFC0(C0_PERFORMANCE, 4)); /* enable instruction counting for counter 0 */
++ MTC0(C0_PERFORMANCE, 0, 0); /* zero counter zero */
++}
++
++/* enable and start I$ hit and I$ miss counting */
++void
++hndmips_perf_icachecount_enable(void)
++{
++ MTC0(C0_PERFORMANCE, 6, 0x80000218); /* enable I$ counting */
++ MTC0(C0_PERFORMANCE, 4, 0x80148018); /* count I$ hits in cntr 0 and misses in cntr 1 */
++ MTC0(C0_PERFORMANCE, 0, 0); /* zero counter 0 - # I$ hits */
++ MTC0(C0_PERFORMANCE, 1, 0); /* zero counter 1 - # I$ misses */
++}
++
++/* enable and start D$ hit and I$ miss counting */
++void
++hndmips_perf_dcachecount_enable(void)
++{
++ MTC0(C0_PERFORMANCE, 6, 0x80000211); /* enable D$ counting */
++ MTC0(C0_PERFORMANCE, 4, 0x80248028); /* count D$ hits in cntr 0 and misses in cntr 1 */
++ MTC0(C0_PERFORMANCE, 0, 0); /* zero counter 0 - # D$ hits */
++ MTC0(C0_PERFORMANCE, 1, 0); /* zero counter 1 - # D$ misses */
++}
++
++void
++hndmips_perf_icache_miss_enable()
++{
++ MTC0(C0_PERFORMANCE, 4,
++ 0x80140000 | MFC0(C0_PERFORMANCE, 4)); /* enable cache misses counting for counter 1 */
++ MTC0(C0_PERFORMANCE, 1, 0); /* zero counter one */
++}
++
++
++void
++hndmips_perf_icache_hit_enable()
++{
++ MTC0(C0_PERFORMANCE, 5, 0x8018 | MFC0(C0_PERFORMANCE, 5));
++ /* enable cache hits counting for counter 2 */
++ MTC0(C0_PERFORMANCE, 2, 0); /* zero counter 2 */
++}
++
++uint32
++hndmips_perf_read_instrcount()
++{
++ return -(long)(MFC0(C0_PERFORMANCE, 0));
++}
++
++uint32
++hndmips_perf_read_cache_miss()
++{
++ return -(long)(MFC0(C0_PERFORMANCE, 1));
++}
++
++uint32
++hndmips_perf_read_cache_hit()
++{
++ return -(long)(MFC0(C0_PERFORMANCE, 2));
++}
++
++#endif /* BCMINTERNAL | BCMPERFSTATS */
+diff -urN linux.old/arch/mips/bcm947xx/sbpci.c linux.dev/arch/mips/bcm947xx/sbpci.c
+--- linux.old/arch/mips/bcm947xx/sbpci.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/sbpci.c 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,768 @@
++/*
++ * Low-Level PCI and SB support for BCM47xx
++ *
++ * 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.
++ *
++ * $Id: hndpci.c,v 1.1.1.3 2006/04/08 06:13:39 honor Exp $
++ */
++
++#include <typedefs.h>
++#include <osl.h>
++#include <pcicfg.h>
++#include <bcmdevs.h>
++#include <sbconfig.h>
++#include <bcmutils.h>
++#include <sbutils.h>
++#include <sbpci.h>
++#include <bcmendian.h>
++#include <bcmnvram.h>
++#include <hndcpu.h>
++#include <hndmips.h>
++#include <hndpci.h>
++
++/* debug/trace */
++#ifdef BCMDBG_PCI
++#define PCI_MSG(args) printf args
++#else
++#define PCI_MSG(args)
++#endif /* BCMDBG_PCI */
++
++/* Can free sbpci_init() memory after boot */
++#ifndef linux
++#define __init
++#endif /* linux */
++
++/* Emulated configuration space */
++typedef struct {
++ int n;
++ uint size0;
++ uint size1;
++ uint size2;
++ uint size3;
++} sb_bar_cfg_t;
++static pci_config_regs sb_config_regs[SB_MAXCORES];
++static sb_bar_cfg_t sb_bar_cfg[SB_MAXCORES];
++
++/* Links to emulated and real PCI configuration spaces */
++#define MAXFUNCS 2
++typedef struct {
++ pci_config_regs *emu; /* emulated PCI config */
++ pci_config_regs *pci; /* real PCI config */
++ sb_bar_cfg_t *bar; /* region sizes */
++} sb_pci_cfg_t;
++static sb_pci_cfg_t sb_pci_cfg[SB_MAXCORES][MAXFUNCS];
++
++/* Special emulated config space for non-existing device */
++static pci_config_regs sb_pci_null = { 0xffff, 0xffff };
++
++/* Banned cores */
++static uint16 pci_ban[SB_MAXCORES] = { 0 };
++static uint pci_banned = 0;
++
++/* CardBus mode */
++static bool cardbus = FALSE;
++
++/* Disable PCI host core */
++static bool pci_disabled = FALSE;
++
++/* Host bridge slot #, default to 0 */
++static uint8 pci_hbslot = 0;
++
++/* Internal macros */
++#define PCI_SLOTAD_MAP 16 /* SLOT<n> mapps to AD<n+16> */
++#define PCI_HBSBCFG_REV 8 /* MIN. core rev. required to
++ * access host bridge PCI cfg space
++ * from SB
++ */
++
++/*
++ * Functions for accessing external PCI configuration space
++ */
++
++/* Assume one-hot slot wiring */
++#define PCI_SLOT_MAX 16 /* Max. PCI Slots */
++
++static uint32
++config_cmd(sb_t *sbh, uint bus, uint dev, uint func, uint off)
++{
++ uint coreidx;
++ sbpciregs_t *regs;
++ uint32 addr = 0;
++ osl_t *osh;
++
++ /* CardBusMode supports only one device */
++ if (cardbus && dev > 1)
++ return 0;
++
++ osh = sb_osh(sbh);
++
++ coreidx = sb_coreidx(sbh);
++ regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0);
++
++ /* Type 0 transaction */
++ if (bus == 1) {
++ /* Skip unwired slots */
++ if (dev < PCI_SLOT_MAX) {
++ uint32 win;
++
++ /* Slide the PCI window to the appropriate slot */
++ win = (SBTOPCI_CFG0 | ((1 << (dev + PCI_SLOTAD_MAP)) & SBTOPCI1_MASK));
++ W_REG(osh, &regs->sbtopci1, win);
++ addr = SB_PCI_CFG |
++ ((1 << (dev + PCI_SLOTAD_MAP)) & ~SBTOPCI1_MASK) |
++ (func << PCICFG_FUN_SHIFT) |
++ (off & ~3);
++ }
++ } else {
++ /* Type 1 transaction */
++ W_REG(osh, &regs->sbtopci1, SBTOPCI_CFG1);
++ addr = SB_PCI_CFG |
++ (bus << PCICFG_BUS_SHIFT) |
++ (dev << PCICFG_SLOT_SHIFT) |
++ (func << PCICFG_FUN_SHIFT) |
++ (off & ~3);
++ }
++
++ sb_setcoreidx(sbh, coreidx);
++
++ return addr;
++}
++
++/*
++ * Read host bridge PCI config registers from Silicon Backplane (>=rev8).
++ *
++ * It returns TRUE to indicate that access to the host bridge's pci config
++ * from SB is ok, and values in 'addr' and 'val' are valid.
++ *
++ * It can only read registers at multiple of 4-bytes. Callers must pick up
++ * needed bytes from 'val' based on 'off' value. Value in 'addr' reflects
++ * the register address where value in 'val' is read.
++ */
++static bool
++sb_pcihb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off,
++ uint32 **addr, uint32 *val)
++{
++ sbpciregs_t *regs;
++ osl_t *osh;
++ uint coreidx;
++ bool ret = FALSE;
++
++ /* sanity check */
++ ASSERT(bus == 1);
++ ASSERT(dev == pci_hbslot);
++ ASSERT(func == 0);
++
++ osh = sb_osh(sbh);
++
++ /* read pci config when core rev >= 8 */
++ coreidx = sb_coreidx(sbh);
++ regs = (sbpciregs_t *)sb_setcore(sbh, SB_PCI, 0);
++ if (regs && sb_corerev(sbh) >= PCI_HBSBCFG_REV) {
++ *addr = (uint32 *)&regs->pcicfg[func][off >> 2];
++ *val = R_REG(osh, *addr);
++ ret = TRUE;
++ }
++ sb_setcoreidx(sbh, coreidx);
++
++ return ret;
++}
++
++int
++extpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
++{
++ uint32 addr = 0, *reg = NULL, val;
++ int ret = 0;
++
++ /*
++ * Set value to -1 when:
++ * flag 'pci_disabled' is true;
++ * value of 'addr' is zero;
++ * REG_MAP() fails;
++ * BUSPROBE() fails;
++ */
++ if (pci_disabled)
++ val = 0xffffffff;
++ else if (bus == 1 && dev == pci_hbslot && func == 0 &&
++ sb_pcihb_read_config(sbh, bus, dev, func, off, &reg, &val))
++ ;
++ else if (((addr = config_cmd(sbh, bus, dev, func, off)) == 0) ||
++ ((reg = (uint32 *)REG_MAP(addr, len)) == 0) ||
++ (BUSPROBE(val, reg) != 0))
++ val = 0xffffffff;
++
++ PCI_MSG(("%s: 0x%x <= 0x%p(0x%x), len %d, off 0x%x, buf 0x%p\n",
++ __FUNCTION__, val, reg, addr, len, off, buf));
++
++ val >>= 8 * (off & 3);
++ if (len == 4)
++ *((uint32 *) buf) = val;
++ else if (len == 2)
++ *((uint16 *) buf) = (uint16) val;
++ else if (len == 1)
++ *((uint8 *) buf) = (uint8) val;
++ else
++ ret = -1;
++
++ if (reg && addr)
++ REG_UNMAP(reg);
++
++ return ret;
++}
++
++int
++extpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
++{
++ osl_t *osh;
++ uint32 addr = 0, *reg = NULL, val;
++ int ret = 0;
++
++ osh = sb_osh(sbh);
++
++ /*
++ * Ignore write attempt when:
++ * flag 'pci_disabled' is true;
++ * value of 'addr' is zero;
++ * REG_MAP() fails;
++ * BUSPROBE() fails;
++ */
++ if (pci_disabled)
++ return 0;
++ else if (bus == 1 && dev == pci_hbslot && func == 0 &&
++ sb_pcihb_read_config(sbh, bus, dev, func, off, &reg, &val))
++ ;
++ else if (((addr = config_cmd(sbh, bus, dev, func, off)) == 0) ||
++ ((reg = (uint32 *) REG_MAP(addr, len)) == 0) ||
++ (BUSPROBE(val, reg) != 0))
++ goto done;
++
++ if (len == 4)
++ val = *((uint32 *) buf);
++ else if (len == 2) {
++ val &= ~(0xffff << (8 * (off & 3)));
++ val |= *((uint16 *) buf) << (8 * (off & 3));
++ } else if (len == 1) {
++ val &= ~(0xff << (8 * (off & 3)));
++ val |= *((uint8 *) buf) << (8 * (off & 3));
++ } else {
++ ret = -1;
++ goto done;
++ }
++
++ PCI_MSG(("%s: 0x%x => 0x%p\n", __FUNCTION__, val, reg));
++
++ W_REG(osh, reg, val);
++
++done:
++ if (reg && addr)
++ REG_UNMAP(reg);
++
++ return ret;
++}
++
++/*
++ * Must access emulated PCI configuration at these locations even when
++ * the real PCI config space exists and is accessible.
++ *
++ * PCI_CFG_VID (0x00)
++ * PCI_CFG_DID (0x02)
++ * PCI_CFG_PROGIF (0x09)
++ * PCI_CFG_SUBCL (0x0a)
++ * PCI_CFG_BASECL (0x0b)
++ * PCI_CFG_HDR (0x0e)
++ * PCI_CFG_INT (0x3c)
++ * PCI_CFG_PIN (0x3d)
++ */
++#define FORCE_EMUCFG(off, len) \
++ ((off == PCI_CFG_VID) || (off == PCI_CFG_DID) || \
++ (off == PCI_CFG_PROGIF) || \
++ (off == PCI_CFG_SUBCL) || (off == PCI_CFG_BASECL) || \
++ (off == PCI_CFG_HDR) || \
++ (off == PCI_CFG_INT) || (off == PCI_CFG_PIN))
++
++/* Sync the emulation registers and the real PCI config registers. */
++static void
++sb_pcid_read_config(sb_t *sbh, uint coreidx, sb_pci_cfg_t *cfg,
++ uint off, uint len)
++{
++ osl_t *osh;
++ uint oldidx;
++
++ ASSERT(cfg);
++ ASSERT(cfg->emu);
++ ASSERT(cfg->pci);
++
++ /* decide if real PCI config register access is necessary */
++ if (FORCE_EMUCFG(off, len))
++ return;
++
++ osh = sb_osh(sbh);
++
++ /* access to the real pci config space only when the core is up */
++ oldidx = sb_coreidx(sbh);
++ sb_setcoreidx(sbh, coreidx);
++ if (sb_iscoreup(sbh)) {
++ if (len == 4)
++ *(uint32 *)((ulong)cfg->emu + off) =
++ htol32(R_REG(osh, (uint32 *)((ulong)cfg->pci + off)));
++ else if (len == 2)
++ *(uint16 *)((ulong)cfg->emu + off) =
++ htol16(R_REG(osh, (uint16 *)((ulong)cfg->pci + off)));
++ else if (len == 1)
++ *(uint8 *)((ulong)cfg->emu + off) =
++ R_REG(osh, (uint8 *)((ulong)cfg->pci + off));
++ }
++ sb_setcoreidx(sbh, oldidx);
++}
++
++static void
++sb_pcid_write_config(sb_t *sbh, uint coreidx, sb_pci_cfg_t *cfg,
++ uint off, uint len)
++{
++ osl_t *osh;
++ uint oldidx;
++
++ ASSERT(cfg);
++ ASSERT(cfg->emu);
++ ASSERT(cfg->pci);
++
++ osh = sb_osh(sbh);
++
++ /* decide if real PCI config register access is necessary */
++ if (FORCE_EMUCFG(off, len))
++ return;
++
++ /* access to the real pci config space only when the core is up */
++ oldidx = sb_coreidx(sbh);
++ sb_setcoreidx(sbh, coreidx);
++ if (sb_iscoreup(sbh)) {
++ if (len == 4)
++ W_REG(osh, (uint32 *)((ulong)cfg->pci + off),
++ ltoh32(*(uint32 *)((ulong)cfg->emu + off)));
++ else if (len == 2)
++ W_REG(osh, (uint16 *)((ulong)cfg->pci + off),
++ ltoh16(*(uint16 *)((ulong)cfg->emu + off)));
++ else if (len == 1)
++ W_REG(osh, (uint8 *)((ulong)cfg->pci + off),
++ *(uint8 *)((ulong)cfg->emu + off));
++ }
++ sb_setcoreidx(sbh, oldidx);
++}
++
++/*
++ * Functions for accessing translated SB configuration space
++ */
++static int
++sb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
++{
++ pci_config_regs *cfg;
++
++ if (dev >= SB_MAXCORES || func >= MAXFUNCS || (off + len) > sizeof(pci_config_regs))
++ return -1;
++ cfg = sb_pci_cfg[dev][func].emu;
++
++ ASSERT(ISALIGNED(off, len));
++ ASSERT(ISALIGNED((uintptr)buf, len));
++
++ /* use special config space if the device does not exist */
++ if (!cfg)
++ cfg = &sb_pci_null;
++ /* sync emulation with real PCI config if necessary */
++ else if (sb_pci_cfg[dev][func].pci)
++ sb_pcid_read_config(sbh, dev, &sb_pci_cfg[dev][func], off, len);
++
++ if (len == 4)
++ *((uint32 *) buf) = ltoh32(*((uint32 *)((ulong) cfg + off)));
++ else if (len == 2)
++ *((uint16 *) buf) = ltoh16(*((uint16 *)((ulong) cfg + off)));
++ else if (len == 1)
++ *((uint8 *) buf) = *((uint8 *)((ulong) cfg + off));
++ else
++ return -1;
++
++ return 0;
++}
++
++static int
++sb_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
++{
++ uint coreidx;
++ void *regs;
++ pci_config_regs *cfg;
++ osl_t *osh;
++ sb_bar_cfg_t *bar;
++
++ if (dev >= SB_MAXCORES || func >= MAXFUNCS || (off + len) > sizeof(pci_config_regs))
++ return -1;
++ cfg = sb_pci_cfg[dev][func].emu;
++ if (!cfg)
++ return -1;
++
++ ASSERT(ISALIGNED(off, len));
++ ASSERT(ISALIGNED((uintptr)buf, len));
++
++ osh = sb_osh(sbh);
++
++ /* Emulate BAR sizing */
++ if (off >= OFFSETOF(pci_config_regs, base[0]) &&
++ off <= OFFSETOF(pci_config_regs, base[3]) &&
++ len == 4 && *((uint32 *) buf) == ~0) {
++ coreidx = sb_coreidx(sbh);
++ if ((regs = sb_setcoreidx(sbh, dev))) {
++ bar = sb_pci_cfg[dev][func].bar;
++ /* Highest numbered address match register */
++ if (off == OFFSETOF(pci_config_regs, base[0]))
++ cfg->base[0] = ~(bar->size0 - 1);
++ else if (off == OFFSETOF(pci_config_regs, base[1]) && bar->n >= 1)
++ cfg->base[1] = ~(bar->size1 - 1);
++ else if (off == OFFSETOF(pci_config_regs, base[2]) && bar->n >= 2)
++ cfg->base[2] = ~(bar->size2 - 1);
++ else if (off == OFFSETOF(pci_config_regs, base[3]) && bar->n >= 3)
++ cfg->base[3] = ~(bar->size3 - 1);
++ }
++ sb_setcoreidx(sbh, coreidx);
++ }
++ else if (len == 4)
++ *((uint32 *)((ulong) cfg + off)) = htol32(*((uint32 *) buf));
++ else if (len == 2)
++ *((uint16 *)((ulong) cfg + off)) = htol16(*((uint16 *) buf));
++ else if (len == 1)
++ *((uint8 *)((ulong) cfg + off)) = *((uint8 *) buf);
++ else
++ return -1;
++
++ /* sync emulation with real PCI config if necessary */
++ if (sb_pci_cfg[dev][func].pci)
++ sb_pcid_write_config(sbh, dev, &sb_pci_cfg[dev][func], off, len);
++
++ return 0;
++}
++
++int
++sbpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
++{
++ if (bus == 0)
++ return sb_read_config(sbh, bus, dev, func, off, buf, len);
++ else
++ return extpci_read_config(sbh, bus, dev, func, off, buf, len);
++}
++
++int
++sbpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
++{
++ if (bus == 0)
++ return sb_write_config(sbh, bus, dev, func, off, buf, len);
++ else
++ return extpci_write_config(sbh, bus, dev, func, off, buf, len);
++}
++
++void
++sbpci_ban(uint16 core)
++{
++ if (pci_banned < ARRAYSIZE(pci_ban))
++ pci_ban[pci_banned++] = core;
++}
++
++/*
++ * Initiliaze PCI core. Return 0 after a successful initialization.
++ * Otherwise return -1 to indicate there is no PCI core and return 1
++ * to indicate PCI core is disabled.
++ */
++int __init
++sbpci_init_pci(sb_t *sbh)
++{
++ uint chip, chiprev, chippkg, host;
++ uint32 boardflags;
++ sbpciregs_t *pci;
++ sbconfig_t *sb;
++ uint32 val;
++ int ret = 0;
++ char *hbslot;
++ osl_t *osh;
++
++ chip = sb_chip(sbh);
++ chiprev = sb_chiprev(sbh);
++ chippkg = sb_chippkg(sbh);
++
++ osh = sb_osh(sbh);
++
++ if (!(pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0))) {
++ printk("PCI: no core\n");
++ pci_disabled = TRUE;
++ return -1;
++ }
++
++ if ((chip == 0x4310) && (chiprev == 0))
++ pci_disabled = TRUE;
++
++ sb = (sbconfig_t *)((ulong) pci + SBCONFIGOFF);
++
++ boardflags = (uint32) getintvar(NULL, "boardflags");
++
++ /*
++ * The 200-pin BCM4712 package does not bond out PCI. Even when
++ * PCI is bonded out, some boards may leave the pins
++ * floating.
++ */
++ if (((chip == BCM4712_CHIP_ID) &&
++ ((chippkg == BCM4712SMALL_PKG_ID) ||
++ (chippkg == BCM4712MID_PKG_ID))) ||
++ (boardflags & BFL_NOPCI))
++ pci_disabled = TRUE;
++
++ /* Enable the core */
++ sb_core_reset(sbh, 0, 0);
++
++ /*
++ * If the PCI core should not be touched (disabled, not bonded
++ * out, or pins floating), do not even attempt to access core
++ * registers. Otherwise, try to determine if it is in host
++ * mode.
++ */
++ if (pci_disabled)
++ host = 0;
++ else
++ host = !BUSPROBE(val, &pci->control);
++
++ if (!host) {
++ ret = 1;
++
++ /* Disable PCI interrupts in client mode */
++ W_REG(osh, &sb->sbintvec, 0);
++
++ /* Disable the PCI bridge in client mode */
++ sbpci_ban(SB_PCI);
++ sb_core_disable(sbh, 0);
++
++ printk("PCI: Disabled\n");
++ } else {
++ printk("PCI: Initializing host\n");
++
++ /* Disable PCI SBReqeustTimeout for BCM4785 */
++ if (chip == BCM4785_CHIP_ID) {
++ AND_REG(osh, &sb->sbimconfiglow, ~0x00000070);
++ sb_commit(sbh);
++ }
++
++ /* Reset the external PCI bus and enable the clock */
++ W_REG(osh, &pci->control, 0x5); /* enable the tristate drivers */
++ W_REG(osh, &pci->control, 0xd); /* enable the PCI clock */
++ OSL_DELAY(150); /* delay > 100 us */
++ W_REG(osh, &pci->control, 0xf); /* deassert PCI reset */
++ /* Use internal arbiter and park REQ/GRNT at external master 0 */
++ W_REG(osh, &pci->arbcontrol, PCI_INT_ARB);
++ OSL_DELAY(1); /* delay 1 us */
++ if (sb_corerev(sbh) >= 8) {
++ val = getintvar(NULL, "parkid");
++ ASSERT(val <= PCI_PARKID_LAST);
++ OR_REG(osh, &pci->arbcontrol, val << PCI_PARKID_SHIFT);
++ OSL_DELAY(1);
++ }
++
++ /* Enable CardBusMode */
++ cardbus = getintvar(NULL, "cardbus") == 1;
++ if (cardbus) {
++ printk("PCI: Enabling CardBus\n");
++ /* GPIO 1 resets the CardBus device on bcm94710ap */
++ sb_gpioout(sbh, 1, 1, GPIO_DRV_PRIORITY);
++ sb_gpioouten(sbh, 1, 1, GPIO_DRV_PRIORITY);
++ W_REG(osh, &pci->sprom[0], R_REG(osh, &pci->sprom[0]) | 0x400);
++ }
++
++ /* 64 MB I/O access window */
++ W_REG(osh, &pci->sbtopci0, SBTOPCI_IO);
++ /* 64 MB configuration access window */
++ W_REG(osh, &pci->sbtopci1, SBTOPCI_CFG0);
++ /* 1 GB memory access window */
++ W_REG(osh, &pci->sbtopci2, SBTOPCI_MEM | SB_PCI_DMA);
++
++ /* Host bridge slot # nvram overwrite */
++ if ((hbslot = nvram_get("pcihbslot"))) {
++ pci_hbslot = bcm_strtoul(hbslot, NULL, 0);
++ ASSERT(pci_hbslot < PCI_MAX_DEVICES);
++ }
++
++ /* Enable PCI bridge BAR0 prefetch and burst */
++ val = 6;
++ sbpci_write_config(sbh, 1, pci_hbslot, 0, PCI_CFG_CMD, &val, sizeof(val));
++
++ /* Enable PCI interrupts */
++ W_REG(osh, &pci->intmask, PCI_INTA);
++ }
++
++ return ret;
++}
++
++/*
++ * Get the PCI region address and size information.
++ */
++static void __init
++sbpci_init_regions(sb_t *sbh, uint func, pci_config_regs *cfg, sb_bar_cfg_t *bar)
++{
++ osl_t *osh;
++ uint16 coreid;
++ void *regs;
++ sbconfig_t *sb;
++ uint32 base;
++
++ osh = sb_osh(sbh);
++ coreid = sb_coreid(sbh);
++ regs = sb_coreregs(sbh);
++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
++
++ switch (coreid) {
++ case SB_USB20H:
++ base = htol32(sb_base(R_REG(osh, &sb->sbadmatch0)));
++
++ cfg->base[0] = func == 0 ? base : base + 0x800; /* OHCI/EHCI */
++ cfg->base[1] = 0;
++ cfg->base[2] = 0;
++ cfg->base[3] = 0;
++ cfg->base[4] = 0;
++ cfg->base[5] = 0;
++ bar->n = 1;
++ bar->size0 = func == 0 ? 0x200 : 0x100; /* OHCI/EHCI */
++ bar->size1 = 0;
++ bar->size2 = 0;
++ bar->size3 = 0;
++ break;
++ default:
++ cfg->base[0] = htol32(sb_base(R_REG(osh, &sb->sbadmatch0)));
++ cfg->base[1] = htol32(sb_base(R_REG(osh, &sb->sbadmatch1)));
++ cfg->base[2] = htol32(sb_base(R_REG(osh, &sb->sbadmatch2)));
++ cfg->base[3] = htol32(sb_base(R_REG(osh, &sb->sbadmatch3)));
++ cfg->base[4] = 0;
++ cfg->base[5] = 0;
++ bar->n = (R_REG(osh, &sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT;
++ bar->size0 = sb_size(R_REG(osh, &sb->sbadmatch0));
++ bar->size1 = sb_size(R_REG(osh, &sb->sbadmatch1));
++ bar->size2 = sb_size(R_REG(osh, &sb->sbadmatch2));
++ bar->size3 = sb_size(R_REG(osh, &sb->sbadmatch3));
++ break;
++ }
++}
++
++/*
++ * Construct PCI config spaces for SB cores so that they
++ * can be accessed as if they were PCI devices.
++ */
++static void __init
++sbpci_init_cores(sb_t *sbh)
++{
++ uint chiprev, coreidx, i;
++ sbconfig_t *sb;
++ pci_config_regs *cfg, *pci;
++ sb_bar_cfg_t *bar;
++ void *regs;
++ osl_t *osh;
++ uint16 vendor, device;
++ uint16 coreid;
++ uint8 class, subclass, progif;
++ uint dev;
++ uint8 header;
++ uint func;
++
++ chiprev = sb_chiprev(sbh);
++ coreidx = sb_coreidx(sbh);
++
++ osh = sb_osh(sbh);
++
++ /* Scan the SB bus */
++ bzero(sb_config_regs, sizeof(sb_config_regs));
++ bzero(sb_bar_cfg, sizeof(sb_bar_cfg));
++ bzero(sb_pci_cfg, sizeof(sb_pci_cfg));
++ memset(&sb_pci_null, -1, sizeof(sb_pci_null));
++ cfg = sb_config_regs;
++ bar = sb_bar_cfg;
++ for (dev = 0; dev < SB_MAXCORES; dev ++) {
++ /* Check if the core exists */
++ if (!(regs = sb_setcoreidx(sbh, dev)))
++ continue;
++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
++
++ /* Check if this core is banned */
++ coreid = sb_coreid(sbh);
++ for (i = 0; i < pci_banned; i++)
++ if (coreid == pci_ban[i])
++ break;
++ if (i < pci_banned)
++ continue;
++
++ for (func = 0; func < MAXFUNCS; ++func) {
++ /* Make sure we won't go beyond the limit */
++ if (cfg >= &sb_config_regs[SB_MAXCORES]) {
++ printk("PCI: too many emulated devices\n");
++ goto done;
++ }
++
++ /* Convert core id to pci id */
++ if (sb_corepciid(sbh, func, &vendor, &device, &class, &subclass,
++ &progif, &header))
++ continue;
++
++ /*
++ * Differentiate real PCI config from emulated.
++ * non zero 'pci' indicate there is a real PCI config space
++ * for this device.
++ */
++ switch (device) {
++ case BCM47XX_GIGETH_ID:
++ pci = (pci_config_regs *)((uint32)regs + 0x800);
++ break;
++ case BCM47XX_SATAXOR_ID:
++ pci = (pci_config_regs *)((uint32)regs + 0x400);
++ break;
++ case BCM47XX_ATA100_ID:
++ pci = (pci_config_regs *)((uint32)regs + 0x800);
++ break;
++ default:
++ pci = NULL;
++ break;
++ }
++ /* Supported translations */
++ cfg->vendor = htol16(vendor);
++ cfg->device = htol16(device);
++ cfg->rev_id = chiprev;
++ cfg->prog_if = progif;
++ cfg->sub_class = subclass;
++ cfg->base_class = class;
++ cfg->header_type = header;
++ sbpci_init_regions(sbh, func, cfg, bar);
++ /* Save core interrupt flag */
++ cfg->int_pin = R_REG(osh, &sb->sbtpsflag) & SBTPS_NUM0_MASK;
++ /* Save core interrupt assignment */
++ cfg->int_line = sb_irq(sbh);
++ /* Indicate there is no SROM */
++ *((uint32 *) &cfg->sprom_control) = 0xffffffff;
++
++ /* Point to the PCI config spaces */
++ sb_pci_cfg[dev][func].emu = cfg;
++ sb_pci_cfg[dev][func].pci = pci;
++ sb_pci_cfg[dev][func].bar = bar;
++ cfg ++;
++ bar ++;
++ }
++ }
++
++done:
++ sb_setcoreidx(sbh, coreidx);
++}
++
++/*
++ * Initialize PCI core and construct PCI config spaces for SB cores.
++ * Must propagate sbpci_init_pci() return value to the caller to let
++ * them know the PCI core initialization status.
++ */
++int __init
++sbpci_init(sb_t *sbh)
++{
++ int status = sbpci_init_pci(sbh);
++ sbpci_init_cores(sbh);
++ return status;
++}
++
+diff -urN linux.old/arch/mips/bcm947xx/sbutils.c linux.dev/arch/mips/bcm947xx/sbutils.c
+--- linux.old/arch/mips/bcm947xx/sbutils.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/sbutils.c 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,3081 @@
++/*
++ * Misc utility routines for accessing chip-specific features
++ * of the SiliconBackplane-based Broadcom chips.
++ *
++ * 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.
++ * $Id: sbutils.c,v 1.10 2006/04/08 07:12:42 honor Exp $
++ */
++
++#include <typedefs.h>
++#include <bcmdefs.h>
++#include <osl.h>
++#include <bcmutils.h>
++#include <sbutils.h>
++#include <bcmdevs.h>
++#include <sbconfig.h>
++#include <sbchipc.h>
++#include <sbpci.h>
++#include <sbpcie.h>
++#include <pcicfg.h>
++#include <sbpcmcia.h>
++#include <sbextif.h>
++#include <sbsocram.h>
++#include <bcmsrom.h>
++#ifdef __mips__
++#include <mipsinc.h>
++#endif /* __mips__ */
++
++/* debug/trace */
++#define SB_ERROR(args)
++
++typedef uint32 (*sb_intrsoff_t)(void *intr_arg);
++typedef void (*sb_intrsrestore_t)(void *intr_arg, uint32 arg);
++typedef bool (*sb_intrsenabled_t)(void *intr_arg);
++
++/* misc sb info needed by some of the routines */
++typedef struct sb_info {
++
++ struct sb_pub sb; /* back plane public state (must be first field) */
++
++ void *osh; /* osl os handle */
++ void *sdh; /* bcmsdh handle */
++
++ void *curmap; /* current regs va */
++ void *regs[SB_MAXCORES]; /* other regs va */
++
++ uint curidx; /* current core index */
++ uint dev_coreid; /* the core provides driver functions */
++
++ bool memseg; /* flag to toggle MEM_SEG register */
++
++ uint gpioidx; /* gpio control core index */
++ uint gpioid; /* gpio control coretype */
++
++ uint numcores; /* # discovered cores */
++ uint coreid[SB_MAXCORES]; /* id of each core */
++
++ void *intr_arg; /* interrupt callback function arg */
++ sb_intrsoff_t intrsoff_fn; /* turns chip interrupts off */
++ sb_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */
++ sb_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */
++
++} sb_info_t;
++
++/* local prototypes */
++static sb_info_t * sb_doattach(sb_info_t *si, uint devid, osl_t *osh, void *regs,
++ uint bustype, void *sdh, char **vars, uint *varsz);
++static void sb_scan(sb_info_t *si);
++static uint sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val);
++static uint _sb_coreidx(sb_info_t *si);
++static uint sb_findcoreidx(sb_info_t *si, uint coreid, uint coreunit);
++static uint sb_pcidev2chip(uint pcidev);
++static uint sb_chip2numcores(uint chip);
++static bool sb_ispcie(sb_info_t *si);
++static bool sb_find_pci_capability(sb_info_t *si, uint8 req_cap_id, uchar *buf, uint32 *buflen);
++static int sb_pci_fixcfg(sb_info_t *si);
++
++/* routines to access mdio slave device registers */
++static int sb_pcie_mdiowrite(sb_info_t *si, uint physmedia, uint readdr, uint val);
++static void sb_war30841(sb_info_t *si);
++
++/* delay needed between the mdio control/ mdiodata register data access */
++#define PR28829_DELAY() OSL_DELAY(10)
++
++/* size that can take bitfielddump */
++#define BITFIELD_DUMP_SIZE 32
++
++/* global variable to indicate reservation/release of gpio's */
++static uint32 sb_gpioreservation = 0;
++
++#define SB_INFO(sbh) (sb_info_t*)sbh
++#define SET_SBREG(si, r, mask, val) \
++ W_SBREG((si), (r), ((R_SBREG((si), (r)) & ~(mask)) | (val)))
++#define GOODCOREADDR(x) (((x) >= SB_ENUM_BASE) && ((x) <= SB_ENUM_LIM) && \
++ ISALIGNED((x), SB_CORE_SIZE))
++#define GOODREGS(regs) ((regs) && ISALIGNED((uintptr)(regs), SB_CORE_SIZE))
++#define REGS2SB(va) (sbconfig_t*) ((int8*)(va) + SBCONFIGOFF)
++#define GOODIDX(idx) (((uint)idx) < SB_MAXCORES)
++#define BADIDX (SB_MAXCORES+1)
++#define NOREV -1 /* Invalid rev */
++
++#define PCI(si) ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (si->sb.buscoretype == SB_PCI))
++#define PCIE(si) ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (si->sb.buscoretype == SB_PCIE))
++
++/* sonicsrev */
++#define SONICS_2_2 (SBIDL_RV_2_2 >> SBIDL_RV_SHIFT)
++#define SONICS_2_3 (SBIDL_RV_2_3 >> SBIDL_RV_SHIFT)
++
++#define R_SBREG(si, sbr) sb_read_sbreg((si), (sbr))
++#define W_SBREG(si, sbr, v) sb_write_sbreg((si), (sbr), (v))
++#define AND_SBREG(si, sbr, v) W_SBREG((si), (sbr), (R_SBREG((si), (sbr)) & (v)))
++#define OR_SBREG(si, sbr, v) W_SBREG((si), (sbr), (R_SBREG((si), (sbr)) | (v)))
++
++/*
++ * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/
++ * after core switching to avoid invalid register accesss inside ISR.
++ */
++#define INTR_OFF(si, intr_val) \
++ if ((si)->intrsoff_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
++ intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); }
++#define INTR_RESTORE(si, intr_val) \
++ if ((si)->intrsrestore_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
++ (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); }
++
++/* dynamic clock control defines */
++#define LPOMINFREQ 25000 /* low power oscillator min */
++#define LPOMAXFREQ 43000 /* low power oscillator max */
++#define XTALMINFREQ 19800000 /* 20 MHz - 1% */
++#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */
++#define PCIMINFREQ 25000000 /* 25 MHz */
++#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */
++
++#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */
++#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */
++
++/* different register spaces to access thr'u pcie indirect access */
++#define PCIE_CONFIGREGS 1 /* Access to config space */
++#define PCIE_PCIEREGS 2 /* Access to pcie registers */
++
++/* GPIO Based LED powersave defines */
++#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */
++#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */
++
++#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME)
++
++static uint32
++sb_read_sbreg(sb_info_t *si, volatile uint32 *sbr)
++{
++ uint8 tmp;
++ uint32 val, intr_val = 0;
++
++
++ /*
++ * compact flash only has 11 bits address, while we needs 12 bits address.
++ * MEM_SEG will be OR'd with other 11 bits address in hardware,
++ * so we program MEM_SEG with 12th bit when necessary(access sb regsiters).
++ * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special
++ */
++ if (si->memseg) {
++ INTR_OFF(si, intr_val);
++ tmp = 1;
++ OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1);
++ sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */
++ }
++
++ val = R_REG(si->osh, sbr);
++
++ if (si->memseg) {
++ tmp = 0;
++ OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1);
++ INTR_RESTORE(si, intr_val);
++ }
++
++ return (val);
++}
++
++static void
++sb_write_sbreg(sb_info_t *si, volatile uint32 *sbr, uint32 v)
++{
++ uint8 tmp;
++ volatile uint32 dummy;
++ uint32 intr_val = 0;
++
++
++ /*
++ * compact flash only has 11 bits address, while we needs 12 bits address.
++ * MEM_SEG will be OR'd with other 11 bits address in hardware,
++ * so we program MEM_SEG with 12th bit when necessary(access sb regsiters).
++ * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special
++ */
++ if (si->memseg) {
++ INTR_OFF(si, intr_val);
++ tmp = 1;
++ OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1);
++ sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */
++ }
++
++ if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) {
++#ifdef IL_BIGENDIAN
++ dummy = R_REG(si->osh, sbr);
++ W_REG(si->osh, ((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff));
++ dummy = R_REG(si->osh, sbr);
++ W_REG(si->osh, (volatile uint16 *)sbr, (uint16)(v & 0xffff));
++#else
++ dummy = R_REG(si->osh, sbr);
++ W_REG(si->osh, (volatile uint16 *)sbr, (uint16)(v & 0xffff));
++ dummy = R_REG(si->osh, sbr);
++ W_REG(si->osh, ((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff));
++#endif /* IL_BIGENDIAN */
++ } else
++ W_REG(si->osh, sbr, v);
++
++ if (si->memseg) {
++ tmp = 0;
++ OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1);
++ INTR_RESTORE(si, intr_val);
++ }
++}
++
++/*
++ * Allocate a sb handle.
++ * devid - pci device id (used to determine chip#)
++ * osh - opaque OS handle
++ * regs - virtual address of initial core registers
++ * bustype - pci/pcmcia/sb/sdio/etc
++ * vars - pointer to a pointer area for "environment" variables
++ * varsz - pointer to int to return the size of the vars
++ */
++sb_t *
++BCMINITFN(sb_attach)(uint devid, osl_t *osh, void *regs,
++ uint bustype, void *sdh, char **vars, uint *varsz)
++{
++ sb_info_t *si;
++
++ /* alloc sb_info_t */
++ if ((si = MALLOC(osh, sizeof (sb_info_t))) == NULL) {
++ SB_ERROR(("sb_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
++ return (NULL);
++ }
++
++ if (sb_doattach(si, devid, osh, regs, bustype, sdh, vars, (uint*)varsz) == NULL) {
++ MFREE(osh, si, sizeof(sb_info_t));
++ return (NULL);
++ }
++
++ return (sb_t *)si;
++}
++
++/* Using sb_kattach depends on SB_BUS support, either implicit */
++/* no limiting BCMBUSTYPE value) or explicit (value is SB_BUS). */
++#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SB_BUS)
++
++/* global kernel resource */
++static sb_info_t ksi;
++static bool ksi_attached = FALSE;
++
++/* generic kernel variant of sb_attach() */
++sb_t *
++BCMINITFN(sb_kattach)(void)
++{
++ osl_t *osh = NULL;
++ uint32 *regs;
++
++ if (!ksi_attached) {
++ uint32 cid;
++
++ regs = (uint32 *)REG_MAP(SB_ENUM_BASE, SB_CORE_SIZE);
++ cid = R_REG(osh, (uint32 *)regs);
++ if (((cid & CID_ID_MASK) == BCM4712_CHIP_ID) &&
++ ((cid & CID_PKG_MASK) != BCM4712LARGE_PKG_ID) &&
++ ((cid & CID_REV_MASK) <= (3 << CID_REV_SHIFT))) {
++ uint32 *scc, val;
++
++ scc = (uint32 *)((uchar*)regs + OFFSETOF(chipcregs_t, slow_clk_ctl));
++ val = R_REG(osh, scc);
++ SB_ERROR((" initial scc = 0x%x\n", val));
++ val |= SCC_SS_XTAL;
++ W_REG(osh, scc, val);
++ }
++
++ if (sb_doattach(&ksi, BCM4710_DEVICE_ID, osh, (void*)regs,
++ SB_BUS, NULL, NULL, NULL) == NULL) {
++ return NULL;
++ }
++ else
++ ksi_attached = TRUE;
++ }
++
++ return (sb_t *)&ksi;
++}
++#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SB_BUS) */
++
++static sb_info_t *
++BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs,
++ uint bustype, void *sdh, char **vars, uint *varsz)
++{
++ uint origidx;
++ chipcregs_t *cc;
++ sbconfig_t *sb;
++ uint32 w;
++
++ ASSERT(GOODREGS(regs));
++
++ bzero((uchar*)si, sizeof(sb_info_t));
++
++ si->sb.buscoreidx = si->gpioidx = BADIDX;
++
++ si->curmap = regs;
++ si->sdh = sdh;
++ si->osh = osh;
++
++ /* check to see if we are a sb core mimic'ing a pci core */
++ if (bustype == PCI_BUS) {
++ if (OSL_PCI_READ_CONFIG(si->osh, PCI_SPROM_CONTROL, sizeof(uint32)) == 0xffffffff) {
++ SB_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SB "
++ "devid:0x%x\n", __FUNCTION__, devid));
++ bustype = SB_BUS;
++ }
++ }
++
++ si->sb.bustype = bustype;
++ if (si->sb.bustype != BUSTYPE(si->sb.bustype)) {
++ SB_ERROR(("sb_doattach: bus type %d does not match configured bus type %d\n",
++ si->sb.bustype, BUSTYPE(si->sb.bustype)));
++ return NULL;
++ }
++
++ /* need to set memseg flag for CF card first before any sb registers access */
++ if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS)
++ si->memseg = TRUE;
++
++ /* kludge to enable the clock on the 4306 which lacks a slowclock */
++ if (BUSTYPE(si->sb.bustype) == PCI_BUS)
++ sb_clkctl_xtal(&si->sb, XTAL|PLL, ON);
++
++ if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
++ w = OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32));
++ if (!GOODCOREADDR(w))
++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32), SB_ENUM_BASE);
++ }
++
++ /* initialize current core index value */
++ si->curidx = _sb_coreidx(si);
++
++ if (si->curidx == BADIDX) {
++ SB_ERROR(("sb_doattach: bad core index\n"));
++ return NULL;
++ }
++
++ /* get sonics backplane revision */
++ sb = REGS2SB(si->curmap);
++ si->sb.sonicsrev = (R_SBREG(si, &sb->sbidlow) & SBIDL_RV_MASK) >> SBIDL_RV_SHIFT;
++
++ /* keep and reuse the initial register mapping */
++ origidx = si->curidx;
++ if (BUSTYPE(si->sb.bustype) == SB_BUS)
++ si->regs[origidx] = regs;
++
++ /* is core-0 a chipcommon core? */
++ si->numcores = 1;
++ cc = (chipcregs_t*) sb_setcoreidx(&si->sb, 0);
++ if (sb_coreid(&si->sb) != SB_CC)
++ cc = NULL;
++
++ /* determine chip id and rev */
++ if (cc) {
++ /* chip common core found! */
++ si->sb.chip = R_REG(si->osh, &cc->chipid) & CID_ID_MASK;
++ si->sb.chiprev = (R_REG(si->osh, &cc->chipid) & CID_REV_MASK) >> CID_REV_SHIFT;
++ si->sb.chippkg = (R_REG(si->osh, &cc->chipid) & CID_PKG_MASK) >> CID_PKG_SHIFT;
++ } else {
++ /* no chip common core -- must convert device id to chip id */
++ if ((si->sb.chip = sb_pcidev2chip(devid)) == 0) {
++ SB_ERROR(("sb_doattach: unrecognized device id 0x%04x\n", devid));
++ sb_setcoreidx(&si->sb, origidx);
++ return NULL;
++ }
++ }
++
++ /* get chipcommon rev */
++ si->sb.ccrev = cc ? (int)sb_corerev(&si->sb) : NOREV;
++
++ /* determine numcores */
++ if (cc && ((si->sb.ccrev == 4) || (si->sb.ccrev >= 6)))
++ si->numcores = (R_REG(si->osh, &cc->chipid) & CID_CC_MASK) >> CID_CC_SHIFT;
++ else
++ si->numcores = sb_chip2numcores(si->sb.chip);
++
++ /* return to original core */
++ sb_setcoreidx(&si->sb, origidx);
++
++ /* sanity checks */
++ ASSERT(si->sb.chip);
++
++ /* scan for cores */
++ sb_scan(si);
++
++ /* fixup necessary chip/core configurations */
++ if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
++ if (sb_pci_fixcfg(si)) {
++ SB_ERROR(("sb_doattach: sb_pci_fixcfg failed\n"));
++ return NULL;
++ }
++ }
++
++ /* srom_var_init() depends on sb_scan() info */
++ if (srom_var_init(si, si->sb.bustype, si->curmap, si->osh, vars, varsz)) {
++ SB_ERROR(("sb_doattach: srom_var_init failed: bad srom\n"));
++ return (NULL);
++ }
++
++ if (cc == NULL) {
++ /*
++ * The chip revision number is hardwired into all
++ * of the pci function config rev fields and is
++ * independent from the individual core revision numbers.
++ * For example, the "A0" silicon of each chip is chip rev 0.
++ * For PCMCIA we get it from the CIS instead.
++ */
++ if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) {
++ ASSERT(vars);
++ si->sb.chiprev = getintvar(*vars, "chiprev");
++ } else if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
++ w = OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_REV, sizeof(uint32));
++ si->sb.chiprev = w & 0xff;
++ } else
++ si->sb.chiprev = 0;
++ }
++
++ if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) {
++ w = getintvar(*vars, "regwindowsz");
++ si->memseg = (w <= CFTABLE_REGWIN_2K) ? TRUE : FALSE;
++ }
++
++ /* gpio control core is required */
++ if (!GOODIDX(si->gpioidx)) {
++ SB_ERROR(("sb_doattach: gpio control core not found\n"));
++ return NULL;
++ }
++
++ /* get boardtype and boardrev */
++ switch (BUSTYPE(si->sb.bustype)) {
++ case PCI_BUS:
++ /* do a pci config read to get subsystem id and subvendor id */
++ w = OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_SVID, sizeof(uint32));
++ si->sb.boardvendor = w & 0xffff;
++ si->sb.boardtype = (w >> 16) & 0xffff;
++ break;
++
++ case PCMCIA_BUS:
++ case SDIO_BUS:
++ si->sb.boardvendor = getintvar(*vars, "manfid");
++ si->sb.boardtype = getintvar(*vars, "prodid");
++ break;
++
++ case SB_BUS:
++ case JTAG_BUS:
++ si->sb.boardvendor = VENDOR_BROADCOM;
++ if ((si->sb.boardtype = getintvar(NULL, "boardtype")) == 0)
++ si->sb.boardtype = 0xffff;
++ break;
++ }
++
++ if (si->sb.boardtype == 0) {
++ SB_ERROR(("sb_doattach: unknown board type\n"));
++ ASSERT(si->sb.boardtype);
++ }
++
++ /* setup the GPIO based LED powersave register */
++ if (si->sb.ccrev >= 16) {
++ if ((vars == NULL) || ((w = getintvar(*vars, "leddc")) == 0))
++ w = DEFAULT_GPIOTIMERVAL;
++ sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
++ }
++ if ((si->sb.chip == BCM4311_CHIP_ID) && (si->sb.chiprev <= 1)) {
++ /* set proper clk setup delays before forcing HT */
++ sb_clkctl_init((void *)si);
++ sb_corereg((void*)si, SB_CC_IDX, OFFSETOF(chipcregs_t, system_clk_ctl),
++ SYCC_HR, SYCC_HR);
++ }
++
++
++ return (si);
++}
++
++uint
++sb_coreid(sb_t *sbh)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++
++ si = SB_INFO(sbh);
++ sb = REGS2SB(si->curmap);
++
++ return ((R_SBREG(si, &sb->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT);
++}
++
++uint
++sb_coreidx(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return (si->curidx);
++}
++
++/* return current index of core */
++static uint
++_sb_coreidx(sb_info_t *si)
++{
++ sbconfig_t *sb;
++ uint32 sbaddr = 0;
++
++ ASSERT(si);
++
++ switch (BUSTYPE(si->sb.bustype)) {
++ case SB_BUS:
++ sb = REGS2SB(si->curmap);
++ sbaddr = sb_base(R_SBREG(si, &sb->sbadmatch0));
++ break;
++
++ case PCI_BUS:
++ sbaddr = OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32));
++ break;
++
++ case PCMCIA_BUS: {
++ uint8 tmp = 0;
++
++ OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR0, &tmp, 1);
++ sbaddr = (uint)tmp << 12;
++ OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR1, &tmp, 1);
++ sbaddr |= (uint)tmp << 16;
++ OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR2, &tmp, 1);
++ sbaddr |= (uint)tmp << 24;
++ break;
++ }
++
++#ifdef BCMJTAG
++ case JTAG_BUS:
++ sbaddr = (uint32)si->curmap;
++ break;
++#endif /* BCMJTAG */
++
++ default:
++ ASSERT(0);
++ }
++
++ if (!GOODCOREADDR(sbaddr))
++ return BADIDX;
++
++ return ((sbaddr - SB_ENUM_BASE) / SB_CORE_SIZE);
++}
++
++uint
++sb_corevendor(sb_t *sbh)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++
++ si = SB_INFO(sbh);
++ sb = REGS2SB(si->curmap);
++
++ return ((R_SBREG(si, &sb->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT);
++}
++
++uint
++sb_corerev(sb_t *sbh)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++ uint sbidh;
++
++ si = SB_INFO(sbh);
++ sb = REGS2SB(si->curmap);
++ sbidh = R_SBREG(si, &sb->sbidhigh);
++
++ return (SBCOREREV(sbidh));
++}
++
++void *
++sb_osh(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return si->osh;
++}
++
++void
++sb_setosh(sb_t *sbh, osl_t *osh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ if (si->osh != NULL) {
++ SB_ERROR(("osh is already set....\n"));
++ ASSERT(!si->osh);
++ }
++ si->osh = osh;
++}
++
++/* set/clear sbtmstatelow core-specific flags */
++uint32
++sb_coreflags(sb_t *sbh, uint32 mask, uint32 val)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++ uint32 w;
++
++ si = SB_INFO(sbh);
++ sb = REGS2SB(si->curmap);
++
++ ASSERT((val & ~mask) == 0);
++
++ /* mask and set */
++ if (mask || val) {
++ w = (R_SBREG(si, &sb->sbtmstatelow) & ~mask) | val;
++ W_SBREG(si, &sb->sbtmstatelow, w);
++ }
++
++ /* return the new value */
++ return (R_SBREG(si, &sb->sbtmstatelow));
++}
++
++/* set/clear sbtmstatehigh core-specific flags */
++uint32
++sb_coreflagshi(sb_t *sbh, uint32 mask, uint32 val)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++ uint32 w;
++
++ si = SB_INFO(sbh);
++ sb = REGS2SB(si->curmap);
++
++ ASSERT((val & ~mask) == 0);
++ ASSERT((mask & ~SBTMH_FL_MASK) == 0);
++
++ /* mask and set */
++ if (mask || val) {
++ w = (R_SBREG(si, &sb->sbtmstatehigh) & ~mask) | val;
++ W_SBREG(si, &sb->sbtmstatehigh, w);
++ }
++
++ /* return the new value */
++ return (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_FL_MASK);
++}
++
++/* Run bist on current core. Caller needs to take care of core-specific bist hazards */
++int
++sb_corebist(sb_t *sbh)
++{
++ uint32 sblo;
++ sb_info_t *si;
++ sbconfig_t *sb;
++ int result = 0;
++
++ si = SB_INFO(sbh);
++ sb = REGS2SB(si->curmap);
++
++ sblo = R_SBREG(si, &sb->sbtmstatelow);
++ W_SBREG(si, &sb->sbtmstatelow, (sblo | SBTML_FGC | SBTML_BE));
++
++ SPINWAIT(((R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BISTD) == 0), 100000);
++
++ if (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BISTF)
++ result = BCME_ERROR;
++
++ W_SBREG(si, &sb->sbtmstatelow, sblo);
++
++ return result;
++}
++
++bool
++sb_iscoreup(sb_t *sbh)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++
++ si = SB_INFO(sbh);
++ sb = REGS2SB(si->curmap);
++
++ return ((R_SBREG(si, &sb->sbtmstatelow) &
++ (SBTML_RESET | SBTML_REJ_MASK | SBTML_CLK)) == SBTML_CLK);
++}
++
++/*
++ * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation,
++ * switch back to the original core, and return the new value.
++ *
++ * When using the silicon backplane, no fidleing with interrupts or core switches are needed.
++ *
++ * Also, when using pci/pcie, we can optimize away the core switching for pci registers
++ * and (on newer pci cores) chipcommon registers.
++ */
++static uint
++sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val)
++{
++ uint origidx = 0;
++ uint32 *r = NULL;
++ uint w;
++ uint intr_val = 0;
++ bool fast = FALSE;
++
++ ASSERT(GOODIDX(coreidx));
++ ASSERT(regoff < SB_CORE_SIZE);
++ ASSERT((val & ~mask) == 0);
++
++#ifdef notyet
++ if (si->sb.bustype == SB_BUS) {
++ /* If internal bus, we can always get at everything */
++ fast = TRUE;
++ r = (uint32 *)((uchar *)si->regs[coreidx] + regoff);
++ } else if (si->sb.bustype == PCI_BUS) {
++ /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */
++
++ if ((si->coreid[coreidx] == SB_CC) &&
++ ((si->sb.buscoretype == SB_PCIE) ||
++ (si->sb.buscorerev >= 13))) {
++ /* Chipc registers are mapped at 12KB */
++
++ fast = TRUE;
++ r = (uint32 *)((char *)si->curmap + PCI_16KB0_CCREGS_OFFSET + regoff);
++ } else if (si->sb.buscoreidx == coreidx) {
++ /* pci registers are at either in the last 2KB of an 8KB window
++ * or, in pcie and pci rev 13 at 8KB
++ */
++ fast = TRUE;
++ if ((si->sb.buscoretype == SB_PCIE) ||
++ (si->sb.buscorerev >= 13))
++ r = (uint32 *)((char *)si->curmap +
++ PCI_16KB0_PCIREGS_OFFSET + regoff);
++ else
++ r = (uint32 *)((char *)si->curmap +
++ ((regoff >= SBCONFIGOFF) ?
++ PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) +
++ regoff);
++ }
++ }
++#endif /* notyet */
++
++ if (!fast) {
++ INTR_OFF(si, intr_val);
++
++ /* save current core index */
++ origidx = sb_coreidx(&si->sb);
++
++ /* switch core */
++ r = (uint32*) ((uchar*) sb_setcoreidx(&si->sb, coreidx) + regoff);
++ }
++ ASSERT(r);
++
++ /* mask and set */
++ if (mask || val) {
++ if (regoff >= SBCONFIGOFF) {
++ w = (R_SBREG(si, r) & ~mask) | val;
++ W_SBREG(si, r, w);
++ } else {
++ w = (R_REG(si->osh, r) & ~mask) | val;
++ W_REG(si->osh, r, w);
++ }
++ }
++
++ /* readback */
++ if (regoff >= SBCONFIGOFF)
++ w = R_SBREG(si, r);
++ else
++ w = R_REG(si->osh, r);
++
++ if (!fast) {
++ /* restore core index */
++ if (origidx != coreidx)
++ sb_setcoreidx(&si->sb, origidx);
++
++ INTR_RESTORE(si, intr_val);
++ }
++
++ return (w);
++}
++
++#define DWORD_ALIGN(x) (x & ~(0x03))
++#define BYTE_POS(x) (x & 0x3)
++#define WORD_POS(x) (x & 0x1)
++
++#define BYTE_SHIFT(x) (8 * BYTE_POS(x))
++#define WORD_SHIFT(x) (16 * WORD_POS(x))
++
++#define BYTE_VAL(a, x) ((a >> BYTE_SHIFT(x)) & 0xFF)
++#define WORD_VAL(a, x) ((a >> WORD_SHIFT(x)) & 0xFFFF)
++
++#define read_pci_cfg_byte(a) \
++ (BYTE_VAL(OSL_PCI_READ_CONFIG(si->osh, DWORD_ALIGN(a), 4), a) & 0xff)
++
++#define read_pci_cfg_write(a) \
++ (WORD_VAL(OSL_PCI_READ_CONFIG(si->osh, DWORD_ALIGN(a), 4), a) & 0xffff)
++
++
++/* return TRUE if requested capability exists in the PCI config space */
++static bool
++sb_find_pci_capability(sb_info_t *si, uint8 req_cap_id, uchar *buf, uint32 *buflen)
++{
++ uint8 cap_id;
++ uint8 cap_ptr;
++ uint32 bufsize;
++ uint8 byte_val;
++
++ if (BUSTYPE(si->sb.bustype) != PCI_BUS)
++ return FALSE;
++
++ /* check for Header type 0 */
++ byte_val = read_pci_cfg_byte(PCI_CFG_HDR);
++ if ((byte_val & 0x7f) != PCI_HEADER_NORMAL)
++ return FALSE;
++
++ /* check if the capability pointer field exists */
++ byte_val = read_pci_cfg_byte(PCI_CFG_STAT);
++ if (!(byte_val & PCI_CAPPTR_PRESENT))
++ return FALSE;
++
++ cap_ptr = read_pci_cfg_byte(PCI_CFG_CAPPTR);
++ /* check if the capability pointer is 0x00 */
++ if (cap_ptr == 0x00)
++ return FALSE;
++
++
++ /* loop thr'u the capability list and see if the pcie capabilty exists */
++
++ cap_id = read_pci_cfg_byte(cap_ptr);
++
++ while (cap_id != req_cap_id) {
++ cap_ptr = read_pci_cfg_byte((cap_ptr+1));
++ if (cap_ptr == 0x00) break;
++ cap_id = read_pci_cfg_byte(cap_ptr);
++ }
++ if (cap_id != req_cap_id) {
++ return FALSE;
++ }
++ /* found the caller requested capability */
++ if ((buf != NULL) && (buflen != NULL)) {
++ bufsize = *buflen;
++ if (!bufsize) goto end;
++ *buflen = 0;
++ /* copy the cpability data excluding cap ID and next ptr */
++ cap_ptr += 2;
++ if ((bufsize + cap_ptr) > SZPCR)
++ bufsize = SZPCR - cap_ptr;
++ *buflen = bufsize;
++ while (bufsize--) {
++ *buf = read_pci_cfg_byte(cap_ptr);
++ cap_ptr++;
++ buf++;
++ }
++ }
++end:
++ return TRUE;
++}
++
++/* return TRUE if PCIE capability exists the pci config space */
++static inline bool
++sb_ispcie(sb_info_t *si)
++{
++ return (sb_find_pci_capability(si, PCI_CAP_PCIECAP_ID, NULL, NULL));
++}
++
++/* scan the sb enumerated space to identify all cores */
++static void
++BCMINITFN(sb_scan)(sb_info_t *si)
++{
++ uint origidx;
++ uint i;
++ bool pci;
++ bool pcie;
++ uint pciidx;
++ uint pcieidx;
++ uint pcirev;
++ uint pcierev;
++
++
++ /* numcores should already be set */
++ ASSERT((si->numcores > 0) && (si->numcores <= SB_MAXCORES));
++
++ /* save current core index */
++ origidx = sb_coreidx(&si->sb);
++
++ si->sb.buscorerev = NOREV;
++ si->sb.buscoreidx = BADIDX;
++
++ si->gpioidx = BADIDX;
++
++ pci = pcie = FALSE;
++ pcirev = pcierev = NOREV;
++ pciidx = pcieidx = BADIDX;
++
++ for (i = 0; i < si->numcores; i++) {
++ sb_setcoreidx(&si->sb, i);
++ si->coreid[i] = sb_coreid(&si->sb);
++
++ if (si->coreid[i] == SB_PCI) {
++ pciidx = i;
++ pcirev = sb_corerev(&si->sb);
++ pci = TRUE;
++ } else if (si->coreid[i] == SB_PCIE) {
++ pcieidx = i;
++ pcierev = sb_corerev(&si->sb);
++ pcie = TRUE;
++ } else if (si->coreid[i] == SB_PCMCIA) {
++ si->sb.buscorerev = sb_corerev(&si->sb);
++ si->sb.buscoretype = si->coreid[i];
++ si->sb.buscoreidx = i;
++ }
++ }
++ if (pci && pcie) {
++ if (sb_ispcie(si))
++ pci = FALSE;
++ else
++ pcie = FALSE;
++ }
++ if (pci) {
++ si->sb.buscoretype = SB_PCI;
++ si->sb.buscorerev = pcirev;
++ si->sb.buscoreidx = pciidx;
++ } else if (pcie) {
++ si->sb.buscoretype = SB_PCIE;
++ si->sb.buscorerev = pcierev;
++ si->sb.buscoreidx = pcieidx;
++ }
++
++ /*
++ * Find the gpio "controlling core" type and index.
++ * Precedence:
++ * - if there's a chip common core - use that
++ * - else if there's a pci core (rev >= 2) - use that
++ * - else there had better be an extif core (4710 only)
++ */
++ if (GOODIDX(sb_findcoreidx(si, SB_CC, 0))) {
++ si->gpioidx = sb_findcoreidx(si, SB_CC, 0);
++ si->gpioid = SB_CC;
++ } else if (PCI(si) && (si->sb.buscorerev >= 2)) {
++ si->gpioidx = si->sb.buscoreidx;
++ si->gpioid = SB_PCI;
++ } else if (sb_findcoreidx(si, SB_EXTIF, 0)) {
++ si->gpioidx = sb_findcoreidx(si, SB_EXTIF, 0);
++ si->gpioid = SB_EXTIF;
++ } else
++ ASSERT(si->gpioidx != BADIDX);
++
++ /* return to original core index */
++ sb_setcoreidx(&si->sb, origidx);
++}
++
++/* may be called with core in reset */
++void
++sb_detach(sb_t *sbh)
++{
++ sb_info_t *si;
++ uint idx;
++
++ si = SB_INFO(sbh);
++
++ if (si == NULL)
++ return;
++
++ if (BUSTYPE(si->sb.bustype) == SB_BUS)
++ for (idx = 0; idx < SB_MAXCORES; idx++)
++ if (si->regs[idx]) {
++ REG_UNMAP(si->regs[idx]);
++ si->regs[idx] = NULL;
++ }
++#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SB_BUS)
++ if (si != &ksi)
++#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SB_BUS) */
++ MFREE(si->osh, si, sizeof(sb_info_t));
++
++}
++
++/* use pci dev id to determine chip id for chips not having a chipcommon core */
++static uint
++BCMINITFN(sb_pcidev2chip)(uint pcidev)
++{
++ if ((pcidev >= BCM4710_DEVICE_ID) && (pcidev <= BCM47XX_USB_ID))
++ return (BCM4710_CHIP_ID);
++ if ((pcidev >= BCM4402_ENET_ID) && (pcidev <= BCM4402_V90_ID))
++ return (BCM4402_CHIP_ID);
++ if (pcidev == BCM4401_ENET_ID)
++ return (BCM4402_CHIP_ID);
++
++ return (0);
++}
++
++/* convert chip number to number of i/o cores */
++static uint
++BCMINITFN(sb_chip2numcores)(uint chip)
++{
++ if (chip == BCM4710_CHIP_ID)
++ return (9);
++ if (chip == BCM4402_CHIP_ID)
++ return (3);
++ if (chip == BCM4306_CHIP_ID) /* < 4306c0 */
++ return (6);
++ if (chip == BCM4704_CHIP_ID)
++ return (9);
++ if (chip == BCM5365_CHIP_ID)
++ return (7);
++
++ SB_ERROR(("sb_chip2numcores: unsupported chip 0x%x\n", chip));
++ ASSERT(0);
++ return (1);
++}
++
++/* return index of coreid or BADIDX if not found */
++static uint
++sb_findcoreidx(sb_info_t *si, uint coreid, uint coreunit)
++{
++ uint found;
++ uint i;
++
++ found = 0;
++
++ for (i = 0; i < si->numcores; i++)
++ if (si->coreid[i] == coreid) {
++ if (found == coreunit)
++ return (i);
++ found++;
++ }
++
++ return (BADIDX);
++}
++
++/*
++ * this function changes logical "focus" to the indiciated core,
++ * must be called with interrupt off.
++ * Moreover, callers should keep interrupts off during switching out of and back to d11 core
++ */
++void*
++sb_setcoreidx(sb_t *sbh, uint coreidx)
++{
++ sb_info_t *si;
++ uint32 sbaddr;
++ uint8 tmp;
++
++ si = SB_INFO(sbh);
++
++ if (coreidx >= si->numcores)
++ return (NULL);
++
++ /*
++ * If the user has provided an interrupt mask enabled function,
++ * then assert interrupts are disabled before switching the core.
++ */
++ ASSERT((si->intrsenabled_fn == NULL) || !(*(si)->intrsenabled_fn)((si)->intr_arg));
++
++ sbaddr = SB_ENUM_BASE + (coreidx * SB_CORE_SIZE);
++
++ switch (BUSTYPE(si->sb.bustype)) {
++ case SB_BUS:
++ /* map new one */
++ if (!si->regs[coreidx]) {
++ si->regs[coreidx] = (void*)REG_MAP(sbaddr, SB_CORE_SIZE);
++ ASSERT(GOODREGS(si->regs[coreidx]));
++ }
++ si->curmap = si->regs[coreidx];
++ break;
++
++ case PCI_BUS:
++ /* point bar0 window */
++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, 4, sbaddr);
++ break;
++
++ case PCMCIA_BUS:
++ tmp = (sbaddr >> 12) & 0x0f;
++ OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_ADDR0, &tmp, 1);
++ tmp = (sbaddr >> 16) & 0xff;
++ OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_ADDR1, &tmp, 1);
++ tmp = (sbaddr >> 24) & 0xff;
++ OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_ADDR2, &tmp, 1);
++ break;
++#ifdef BCMJTAG
++ case JTAG_BUS:
++ /* map new one */
++ if (!si->regs[coreidx]) {
++ si->regs[coreidx] = (void *)sbaddr;
++ ASSERT(GOODREGS(si->regs[coreidx]));
++ }
++ si->curmap = si->regs[coreidx];
++ break;
++#endif /* BCMJTAG */
++ }
++
++ si->curidx = coreidx;
++
++ return (si->curmap);
++}
++
++/*
++ * this function changes logical "focus" to the indiciated core,
++ * must be called with interrupt off.
++ * Moreover, callers should keep interrupts off during switching out of and back to d11 core
++ */
++void*
++sb_setcore(sb_t *sbh, uint coreid, uint coreunit)
++{
++ sb_info_t *si;
++ uint idx;
++
++ si = SB_INFO(sbh);
++ idx = sb_findcoreidx(si, coreid, coreunit);
++ if (!GOODIDX(idx))
++ return (NULL);
++
++ return (sb_setcoreidx(sbh, idx));
++}
++
++/* return chip number */
++uint
++sb_chip(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return (si->sb.chip);
++}
++
++/* return chip revision number */
++uint
++sb_chiprev(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return (si->sb.chiprev);
++}
++
++/* return chip common revision number */
++uint
++sb_chipcrev(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return (si->sb.ccrev);
++}
++
++/* return chip package option */
++uint
++sb_chippkg(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return (si->sb.chippkg);
++}
++
++/* return PCI core rev. */
++uint
++sb_pcirev(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return (si->sb.buscorerev);
++}
++
++bool
++BCMINITFN(sb_war16165)(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++
++ return (PCI(si) && (si->sb.buscorerev <= 10));
++}
++
++static void
++BCMINITFN(sb_war30841)(sb_info_t *si)
++{
++ sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128);
++ sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100);
++ sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466);
++}
++
++/* return PCMCIA core rev. */
++uint
++BCMINITFN(sb_pcmciarev)(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return (si->sb.buscorerev);
++}
++
++/* return board vendor id */
++uint
++sb_boardvendor(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return (si->sb.boardvendor);
++}
++
++/* return boardtype */
++uint
++sb_boardtype(sb_t *sbh)
++{
++ sb_info_t *si;
++ char *var;
++
++ si = SB_INFO(sbh);
++
++ if (BUSTYPE(si->sb.bustype) == SB_BUS && si->sb.boardtype == 0xffff) {
++ /* boardtype format is a hex string */
++ si->sb.boardtype = getintvar(NULL, "boardtype");
++
++ /* backward compatibility for older boardtype string format */
++ if ((si->sb.boardtype == 0) && (var = getvar(NULL, "boardtype"))) {
++ if (!strcmp(var, "bcm94710dev"))
++ si->sb.boardtype = BCM94710D_BOARD;
++ else if (!strcmp(var, "bcm94710ap"))
++ si->sb.boardtype = BCM94710AP_BOARD;
++ else if (!strcmp(var, "bu4710"))
++ si->sb.boardtype = BU4710_BOARD;
++ else if (!strcmp(var, "bcm94702mn"))
++ si->sb.boardtype = BCM94702MN_BOARD;
++ else if (!strcmp(var, "bcm94710r1"))
++ si->sb.boardtype = BCM94710R1_BOARD;
++ else if (!strcmp(var, "bcm94710r4"))
++ si->sb.boardtype = BCM94710R4_BOARD;
++ else if (!strcmp(var, "bcm94702cpci"))
++ si->sb.boardtype = BCM94702CPCI_BOARD;
++ else if (!strcmp(var, "bcm95380_rr"))
++ si->sb.boardtype = BCM95380RR_BOARD;
++ }
++ }
++
++ return (si->sb.boardtype);
++}
++
++/* return bus type of sbh device */
++uint
++sb_bus(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return (si->sb.bustype);
++}
++
++/* return bus core type */
++uint
++sb_buscoretype(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++
++ return (si->sb.buscoretype);
++}
++
++/* return bus core revision */
++uint
++sb_buscorerev(sb_t *sbh)
++{
++ sb_info_t *si;
++ si = SB_INFO(sbh);
++
++ return (si->sb.buscorerev);
++}
++
++/* return list of found cores */
++uint
++sb_corelist(sb_t *sbh, uint coreid[])
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++
++ bcopy((uchar*)si->coreid, (uchar*)coreid, (si->numcores * sizeof(uint)));
++ return (si->numcores);
++}
++
++/* return current register mapping */
++void *
++sb_coreregs(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ ASSERT(GOODREGS(si->curmap));
++
++ return (si->curmap);
++}
++
++
++/* do buffered registers update */
++void
++sb_commit(sb_t *sbh)
++{
++ sb_info_t *si;
++ uint origidx;
++ uint intr_val = 0;
++
++ si = SB_INFO(sbh);
++
++ origidx = si->curidx;
++ ASSERT(GOODIDX(origidx));
++
++ INTR_OFF(si, intr_val);
++
++ /* switch over to chipcommon core if there is one, else use pci */
++ if (si->sb.ccrev != NOREV) {
++ chipcregs_t *ccregs = (chipcregs_t *)sb_setcore(sbh, SB_CC, 0);
++
++ /* do the buffer registers update */
++ W_REG(si->osh, &ccregs->broadcastaddress, SB_COMMIT);
++ W_REG(si->osh, &ccregs->broadcastdata, 0x0);
++ } else if (PCI(si)) {
++ sbpciregs_t *pciregs = (sbpciregs_t *)sb_setcore(sbh, SB_PCI, 0);
++
++ /* do the buffer registers update */
++ W_REG(si->osh, &pciregs->bcastaddr, SB_COMMIT);
++ W_REG(si->osh, &pciregs->bcastdata, 0x0);
++ } else
++ ASSERT(0);
++
++ /* restore core index */
++ sb_setcoreidx(sbh, origidx);
++ INTR_RESTORE(si, intr_val);
++}
++
++/* reset and re-enable a core
++ * inputs:
++ * bits - core specific bits that are set during and after reset sequence
++ * resetbits - core specific bits that are set only during reset sequence
++ */
++void
++sb_core_reset(sb_t *sbh, uint32 bits, uint32 resetbits)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++ volatile uint32 dummy;
++
++ si = SB_INFO(sbh);
++ ASSERT(GOODREGS(si->curmap));
++ sb = REGS2SB(si->curmap);
++
++ /*
++ * Must do the disable sequence first to work for arbitrary current core state.
++ */
++ sb_core_disable(sbh, (bits | resetbits));
++
++ /*
++ * Now do the initialization sequence.
++ */
++
++ /* set reset while enabling the clock and forcing them on throughout the core */
++ W_SBREG(si, &sb->sbtmstatelow, (SBTML_FGC | SBTML_CLK | SBTML_RESET | bits | resetbits));
++ dummy = R_SBREG(si, &sb->sbtmstatelow);
++ OSL_DELAY(1);
++
++ if (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_SERR) {
++ W_SBREG(si, &sb->sbtmstatehigh, 0);
++ }
++ if ((dummy = R_SBREG(si, &sb->sbimstate)) & (SBIM_IBE | SBIM_TO)) {
++ AND_SBREG(si, &sb->sbimstate, ~(SBIM_IBE | SBIM_TO));
++ }
++
++ /* clear reset and allow it to propagate throughout the core */
++ W_SBREG(si, &sb->sbtmstatelow, (SBTML_FGC | SBTML_CLK | bits));
++ dummy = R_SBREG(si, &sb->sbtmstatelow);
++ OSL_DELAY(1);
++
++ /* leave clock enabled */
++ W_SBREG(si, &sb->sbtmstatelow, (SBTML_CLK | bits));
++ dummy = R_SBREG(si, &sb->sbtmstatelow);
++ OSL_DELAY(1);
++}
++
++void
++sb_core_tofixup(sb_t *sbh)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++
++ si = SB_INFO(sbh);
++
++ if ((BUSTYPE(si->sb.bustype) != PCI_BUS) || PCIE(si) ||
++ (PCI(si) && (si->sb.buscorerev >= 5)))
++ return;
++
++ ASSERT(GOODREGS(si->curmap));
++ sb = REGS2SB(si->curmap);
++
++ if (BUSTYPE(si->sb.bustype) == SB_BUS) {
++ SET_SBREG(si, &sb->sbimconfiglow,
++ SBIMCL_RTO_MASK | SBIMCL_STO_MASK,
++ (0x5 << SBIMCL_RTO_SHIFT) | 0x3);
++ } else {
++ if (sb_coreid(sbh) == SB_PCI) {
++ SET_SBREG(si, &sb->sbimconfiglow,
++ SBIMCL_RTO_MASK | SBIMCL_STO_MASK,
++ (0x3 << SBIMCL_RTO_SHIFT) | 0x2);
++ } else {
++ SET_SBREG(si, &sb->sbimconfiglow, (SBIMCL_RTO_MASK | SBIMCL_STO_MASK), 0);
++ }
++ }
++
++ sb_commit(sbh);
++}
++
++/*
++ * Set the initiator timeout for the "master core".
++ * The master core is defined to be the core in control
++ * of the chip and so it issues accesses to non-memory
++ * locations (Because of dma *any* core can access memeory).
++ *
++ * The routine uses the bus to decide who is the master:
++ * SB_BUS => mips
++ * JTAG_BUS => chipc
++ * PCI_BUS => pci or pcie
++ * PCMCIA_BUS => pcmcia
++ * SDIO_BUS => pcmcia
++ *
++ * This routine exists so callers can disable initiator
++ * timeouts so accesses to very slow devices like otp
++ * won't cause an abort. The routine allows arbitrary
++ * settings of the service and request timeouts, though.
++ *
++ * Returns the timeout state before changing it or -1
++ * on error.
++ */
++
++#define TO_MASK (SBIMCL_RTO_MASK | SBIMCL_STO_MASK)
++
++uint32
++sb_set_initiator_to(sb_t *sbh, uint32 to)
++{
++ sb_info_t *si;
++ uint origidx, idx;
++ uint intr_val = 0;
++ uint32 tmp, ret = 0xffffffff;
++ sbconfig_t *sb;
++
++ si = SB_INFO(sbh);
++
++ if ((to & ~TO_MASK) != 0)
++ return ret;
++
++ /* Figure out the master core */
++ idx = BADIDX;
++ switch (BUSTYPE(si->sb.bustype)) {
++ case PCI_BUS:
++ idx = si->sb.buscoreidx;
++ break;
++ case JTAG_BUS:
++ idx = SB_CC_IDX;
++ break;
++ case PCMCIA_BUS:
++ case SDIO_BUS:
++ idx = sb_findcoreidx(si, SB_PCMCIA, 0);
++ break;
++ case SB_BUS:
++ if ((idx = sb_findcoreidx(si, SB_MIPS33, 0)) == BADIDX)
++ idx = sb_findcoreidx(si, SB_MIPS, 0);
++ break;
++ default:
++ ASSERT(0);
++ }
++ if (idx == BADIDX)
++ return ret;
++
++ INTR_OFF(si, intr_val);
++ origidx = sb_coreidx(sbh);
++
++ sb = REGS2SB(sb_setcoreidx(sbh, idx));
++
++ tmp = R_SBREG(si, &sb->sbimconfiglow);
++ ret = tmp & TO_MASK;
++ W_SBREG(si, &sb->sbimconfiglow, (tmp & ~TO_MASK) | to);
++
++ sb_commit(sbh);
++ sb_setcoreidx(sbh, origidx);
++ INTR_RESTORE(si, intr_val);
++ return ret;
++}
++
++void
++sb_core_disable(sb_t *sbh, uint32 bits)
++{
++ sb_info_t *si;
++ volatile uint32 dummy;
++ uint32 rej;
++ sbconfig_t *sb;
++
++ si = SB_INFO(sbh);
++
++ ASSERT(GOODREGS(si->curmap));
++ sb = REGS2SB(si->curmap);
++
++ /* if core is already in reset, just return */
++ if (R_SBREG(si, &sb->sbtmstatelow) & SBTML_RESET)
++ return;
++
++ /* reject value changed between sonics 2.2 and 2.3 */
++ if (si->sb.sonicsrev == SONICS_2_2)
++ rej = (1 << SBTML_REJ_SHIFT);
++ else
++ rej = (2 << SBTML_REJ_SHIFT);
++
++ /* if clocks are not enabled, put into reset and return */
++ if ((R_SBREG(si, &sb->sbtmstatelow) & SBTML_CLK) == 0)
++ goto disable;
++
++ /* set target reject and spin until busy is clear (preserve core-specific bits) */
++ OR_SBREG(si, &sb->sbtmstatelow, rej);
++ dummy = R_SBREG(si, &sb->sbtmstatelow);
++ OSL_DELAY(1);
++ SPINWAIT((R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BUSY), 100000);
++ if (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BUSY)
++ SB_ERROR(("%s: target state still busy\n", __FUNCTION__));
++
++ if (R_SBREG(si, &sb->sbidlow) & SBIDL_INIT) {
++ OR_SBREG(si, &sb->sbimstate, SBIM_RJ);
++ dummy = R_SBREG(si, &sb->sbimstate);
++ OSL_DELAY(1);
++ SPINWAIT((R_SBREG(si, &sb->sbimstate) & SBIM_BY), 100000);
++ }
++
++ /* set reset and reject while enabling the clocks */
++ W_SBREG(si, &sb->sbtmstatelow, (bits | SBTML_FGC | SBTML_CLK | rej | SBTML_RESET));
++ dummy = R_SBREG(si, &sb->sbtmstatelow);
++ OSL_DELAY(10);
++
++ /* don't forget to clear the initiator reject bit */
++ if (R_SBREG(si, &sb->sbidlow) & SBIDL_INIT)
++ AND_SBREG(si, &sb->sbimstate, ~SBIM_RJ);
++
++disable:
++ /* leave reset and reject asserted */
++ W_SBREG(si, &sb->sbtmstatelow, (bits | rej | SBTML_RESET));
++ OSL_DELAY(1);
++}
++
++/* set chip watchdog reset timer to fire in 'ticks' backplane cycles */
++void
++sb_watchdog(sb_t *sbh, uint ticks)
++{
++ sb_info_t *si = SB_INFO(sbh);
++
++ /* make sure we come up in fast clock mode */
++ sb_clkctl_clk(sbh, CLK_FAST);
++
++ /* instant NMI */
++ switch (si->gpioid) {
++ case SB_CC:
++#ifdef __mips__
++ if (sb_chip(sbh) == BCM4785_CHIP_ID && ticks <= 1)
++ MTC0(C0_BROADCOM, 4, (1 << 22));
++#endif /* __mips__ */
++ sb_corereg(si, 0, OFFSETOF(chipcregs_t, watchdog), ~0, ticks);
++#ifdef __mips__
++ if (sb_chip(sbh) == BCM4785_CHIP_ID && ticks <= 1) {
++ __asm__ __volatile__ (
++ ".set\tmips3\n\t"
++ "sync\n\t"
++ "wait\n\t"
++ ".set\tmips0"
++ );
++ while (1);
++ }
++#endif /* __mips__ */
++ break;
++ case SB_EXTIF:
++ sb_corereg(si, si->gpioidx, OFFSETOF(extifregs_t, watchdog), ~0, ticks);
++ break;
++ }
++}
++
++/* initialize the pcmcia core */
++void
++sb_pcmcia_init(sb_t *sbh)
++{
++ sb_info_t *si;
++ uint8 cor = 0;
++
++ si = SB_INFO(sbh);
++
++ /* enable d11 mac interrupts */
++ OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1);
++ cor |= COR_IRQEN | COR_FUNEN;
++ OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1);
++
++}
++
++
++/*
++ * Configure the pci core for pci client (NIC) action
++ * coremask is the bitvec of cores by index to be enabled.
++ */
++void
++BCMINITFN(sb_pci_setup)(sb_t *sbh, uint coremask)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++ sbpciregs_t *pciregs;
++ uint32 sbflag;
++ uint32 w;
++ uint idx;
++ int reg_val;
++
++ si = SB_INFO(sbh);
++
++ /* if not pci bus, we're done */
++ if (BUSTYPE(si->sb.bustype) != PCI_BUS)
++ return;
++
++ ASSERT(PCI(si) || PCIE(si));
++ ASSERT(si->sb.buscoreidx != BADIDX);
++
++ /* get current core index */
++ idx = si->curidx;
++
++ /* we interrupt on this backplane flag number */
++ ASSERT(GOODREGS(si->curmap));
++ sb = REGS2SB(si->curmap);
++ sbflag = R_SBREG(si, &sb->sbtpsflag) & SBTPS_NUM0_MASK;
++
++ /* switch over to pci core */
++ pciregs = (sbpciregs_t*) sb_setcoreidx(sbh, si->sb.buscoreidx);
++ sb = REGS2SB(pciregs);
++
++ /*
++ * Enable sb->pci interrupts. Assume
++ * PCI rev 2.3 support was added in pci core rev 6 and things changed..
++ */
++ if (PCIE(si) || (PCI(si) && ((si->sb.buscorerev) >= 6))) {
++ /* pci config write to set this core bit in PCIIntMask */
++ w = OSL_PCI_READ_CONFIG(si->osh, PCI_INT_MASK, sizeof(uint32));
++ w |= (coremask << PCI_SBIM_SHIFT);
++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_INT_MASK, sizeof(uint32), w);
++ } else {
++ /* set sbintvec bit for our flag number */
++ OR_SBREG(si, &sb->sbintvec, (1 << sbflag));
++ }
++
++ if (PCI(si)) {
++ OR_REG(si->osh, &pciregs->sbtopci2, (SBTOPCI_PREF|SBTOPCI_BURST));
++ if (si->sb.buscorerev >= 11)
++ OR_REG(si->osh, &pciregs->sbtopci2, SBTOPCI_RC_READMULTI);
++ if (si->sb.buscorerev < 5) {
++ SET_SBREG(si, &sb->sbimconfiglow, SBIMCL_RTO_MASK | SBIMCL_STO_MASK,
++ (0x3 << SBIMCL_RTO_SHIFT) | 0x2);
++ sb_commit(sbh);
++ }
++ }
++
++#ifdef PCIE_SUPPOER
++ /* PCIE workarounds */
++ if (PCIE(si)) {
++ if ((si->sb.buscorerev == 0) || (si->sb.buscorerev == 1)) {
++ reg_val = sb_pcie_readreg((void *)sbh, (void *)PCIE_PCIEREGS,
++ PCIE_TLP_WORKAROUNDSREG);
++ reg_val |= 0x8;
++ sb_pcie_writereg((void *)sbh, (void *)PCIE_PCIEREGS,
++ PCIE_TLP_WORKAROUNDSREG, reg_val);
++ }
++
++ if (si->sb.buscorerev == 1) {
++ reg_val = sb_pcie_readreg((void *)sbh, (void *)PCIE_PCIEREGS,
++ PCIE_DLLP_LCREG);
++ reg_val |= (0x40);
++ sb_pcie_writereg(sbh, (void *)PCIE_PCIEREGS, PCIE_DLLP_LCREG, reg_val);
++ }
++
++ if (si->sb.buscorerev == 0)
++ sb_war30841(si);
++ }
++#endif
++
++ /* switch back to previous core */
++ sb_setcoreidx(sbh, idx);
++}
++
++uint32
++sb_base(uint32 admatch)
++{
++ uint32 base;
++ uint type;
++
++ type = admatch & SBAM_TYPE_MASK;
++ ASSERT(type < 3);
++
++ base = 0;
++
++ if (type == 0) {
++ base = admatch & SBAM_BASE0_MASK;
++ } else if (type == 1) {
++ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
++ base = admatch & SBAM_BASE1_MASK;
++ } else if (type == 2) {
++ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
++ base = admatch & SBAM_BASE2_MASK;
++ }
++
++ return (base);
++}
++
++uint32
++sb_size(uint32 admatch)
++{
++ uint32 size;
++ uint type;
++
++ type = admatch & SBAM_TYPE_MASK;
++ ASSERT(type < 3);
++
++ size = 0;
++
++ if (type == 0) {
++ size = 1 << (((admatch & SBAM_ADINT0_MASK) >> SBAM_ADINT0_SHIFT) + 1);
++ } else if (type == 1) {
++ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
++ size = 1 << (((admatch & SBAM_ADINT1_MASK) >> SBAM_ADINT1_SHIFT) + 1);
++ } else if (type == 2) {
++ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
++ size = 1 << (((admatch & SBAM_ADINT2_MASK) >> SBAM_ADINT2_SHIFT) + 1);
++ }
++
++ return (size);
++}
++
++/* return the core-type instantiation # of the current core */
++uint
++sb_coreunit(sb_t *sbh)
++{
++ sb_info_t *si;
++ uint idx;
++ uint coreid;
++ uint coreunit;
++ uint i;
++
++ si = SB_INFO(sbh);
++ coreunit = 0;
++
++ idx = si->curidx;
++
++ ASSERT(GOODREGS(si->curmap));
++ coreid = sb_coreid(sbh);
++
++ /* count the cores of our type */
++ for (i = 0; i < idx; i++)
++ if (si->coreid[i] == coreid)
++ coreunit++;
++
++ return (coreunit);
++}
++
++static INLINE uint32
++factor6(uint32 x)
++{
++ switch (x) {
++ case CC_F6_2: return 2;
++ case CC_F6_3: return 3;
++ case CC_F6_4: return 4;
++ case CC_F6_5: return 5;
++ case CC_F6_6: return 6;
++ case CC_F6_7: return 7;
++ default: return 0;
++ }
++}
++
++/* calculate the speed the SB would run at given a set of clockcontrol values */
++uint32
++sb_clock_rate(uint32 pll_type, uint32 n, uint32 m)
++{
++ uint32 n1, n2, clock, m1, m2, m3, mc;
++
++ n1 = n & CN_N1_MASK;
++ n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
++
++ if (pll_type == PLL_TYPE6) {
++ if (m & CC_T6_MMASK)
++ return CC_T6_M1;
++ else
++ return CC_T6_M0;
++ } else if ((pll_type == PLL_TYPE1) ||
++ (pll_type == PLL_TYPE3) ||
++ (pll_type == PLL_TYPE4) ||
++ (pll_type == PLL_TYPE7)) {
++ n1 = factor6(n1);
++ n2 += CC_F5_BIAS;
++ } else if (pll_type == PLL_TYPE2) {
++ n1 += CC_T2_BIAS;
++ n2 += CC_T2_BIAS;
++ ASSERT((n1 >= 2) && (n1 <= 7));
++ ASSERT((n2 >= 5) && (n2 <= 23));
++ } else if (pll_type == PLL_TYPE5) {
++ return (100000000);
++ } else
++ ASSERT(0);
++ /* PLL types 3 and 7 use BASE2 (25Mhz) */
++ if ((pll_type == PLL_TYPE3) ||
++ (pll_type == PLL_TYPE7)) {
++ clock = CC_CLOCK_BASE2 * n1 * n2;
++ } else
++ clock = CC_CLOCK_BASE1 * n1 * n2;
++
++ if (clock == 0)
++ return 0;
++
++ m1 = m & CC_M1_MASK;
++ m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
++ m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
++ mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
++
++ if ((pll_type == PLL_TYPE1) ||
++ (pll_type == PLL_TYPE3) ||
++ (pll_type == PLL_TYPE4) ||
++ (pll_type == PLL_TYPE7)) {
++ m1 = factor6(m1);
++ if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
++ m2 += CC_F5_BIAS;
++ else
++ m2 = factor6(m2);
++ m3 = factor6(m3);
++
++ switch (mc) {
++ case CC_MC_BYPASS: return (clock);
++ case CC_MC_M1: return (clock / m1);
++ case CC_MC_M1M2: return (clock / (m1 * m2));
++ case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3));
++ case CC_MC_M1M3: return (clock / (m1 * m3));
++ default: return (0);
++ }
++ } else {
++ ASSERT(pll_type == PLL_TYPE2);
++
++ m1 += CC_T2_BIAS;
++ m2 += CC_T2M2_BIAS;
++ m3 += CC_T2_BIAS;
++ ASSERT((m1 >= 2) && (m1 <= 7));
++ ASSERT((m2 >= 3) && (m2 <= 10));
++ ASSERT((m3 >= 2) && (m3 <= 7));
++
++ if ((mc & CC_T2MC_M1BYP) == 0)
++ clock /= m1;
++ if ((mc & CC_T2MC_M2BYP) == 0)
++ clock /= m2;
++ if ((mc & CC_T2MC_M3BYP) == 0)
++ clock /= m3;
++
++ return (clock);
++ }
++}
++
++/* returns the current speed the SB is running at */
++uint32
++sb_clock(sb_t *sbh)
++{
++ sb_info_t *si;
++ extifregs_t *eir;
++ chipcregs_t *cc;
++ uint32 n, m;
++ uint idx;
++ uint32 pll_type, rate;
++ uint intr_val = 0;
++
++ si = SB_INFO(sbh);
++ idx = si->curidx;
++ pll_type = PLL_TYPE1;
++
++ INTR_OFF(si, intr_val);
++
++ /* switch to extif or chipc core */
++ if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
++ n = R_REG(si->osh, &eir->clockcontrol_n);
++ m = R_REG(si->osh, &eir->clockcontrol_sb);
++ } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
++ pll_type = R_REG(si->osh, &cc->capabilities) & CAP_PLL_MASK;
++ if (pll_type == PLL_NONE) {
++ INTR_RESTORE(si, intr_val);
++ return 80000000;
++ }
++ n = R_REG(si->osh, &cc->clockcontrol_n);
++ if (pll_type == PLL_TYPE6)
++ m = R_REG(si->osh, &cc->clockcontrol_m3);
++ else if ((pll_type == PLL_TYPE3) && !(BCMINIT(sb_chip)(sbh) == 0x5365))
++ m = R_REG(si->osh, &cc->clockcontrol_m2);
++ else
++ m = R_REG(si->osh, &cc->clockcontrol_sb);
++ } else {
++ INTR_RESTORE(si, intr_val);
++ return 0;
++ }
++
++ /* calculate rate */
++ if (BCMINIT(sb_chip)(sbh) == 0x5365)
++ rate = 100000000;
++ else {
++ rate = sb_clock_rate(pll_type, n, m);
++
++ if (pll_type == PLL_TYPE3)
++ rate = rate / 2;
++ }
++
++ /* switch back to previous core */
++ sb_setcoreidx(sbh, idx);
++
++ INTR_RESTORE(si, intr_val);
++
++ return rate;
++}
++
++/* change logical "focus" to the gpio core for optimized access */
++void*
++sb_gpiosetcore(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++
++ return (sb_setcoreidx(sbh, si->gpioidx));
++}
++
++/* mask&set gpiocontrol bits */
++uint32
++sb_gpiocontrol(sb_t *sbh, uint32 mask, uint32 val, uint8 priority)
++{
++ sb_info_t *si;
++ uint regoff;
++
++ si = SB_INFO(sbh);
++ regoff = 0;
++
++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */
++
++ /* gpios could be shared on router platforms */
++ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
++ mask = priority ? (sb_gpioreservation & mask) :
++ ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
++ val &= mask;
++ }
++
++ switch (si->gpioid) {
++ case SB_CC:
++ regoff = OFFSETOF(chipcregs_t, gpiocontrol);
++ break;
++
++ case SB_PCI:
++ regoff = OFFSETOF(sbpciregs_t, gpiocontrol);
++ break;
++
++ case SB_EXTIF:
++ return (0);
++ }
++
++ return (sb_corereg(si, si->gpioidx, regoff, mask, val));
++}
++
++/* mask&set gpio output enable bits */
++uint32
++sb_gpioouten(sb_t *sbh, uint32 mask, uint32 val, uint8 priority)
++{
++ sb_info_t *si;
++ uint regoff;
++
++ si = SB_INFO(sbh);
++ regoff = 0;
++
++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */
++
++ /* gpios could be shared on router platforms */
++ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
++ mask = priority ? (sb_gpioreservation & mask) :
++ ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
++ val &= mask;
++ }
++
++ switch (si->gpioid) {
++ case SB_CC:
++ regoff = OFFSETOF(chipcregs_t, gpioouten);
++ break;
++
++ case SB_PCI:
++ regoff = OFFSETOF(sbpciregs_t, gpioouten);
++ break;
++
++ case SB_EXTIF:
++ regoff = OFFSETOF(extifregs_t, gpio[0].outen);
++ break;
++ }
++
++ return (sb_corereg(si, si->gpioidx, regoff, mask, val));
++}
++
++/* mask&set gpio output bits */
++uint32
++sb_gpioout(sb_t *sbh, uint32 mask, uint32 val, uint8 priority)
++{
++ sb_info_t *si;
++ uint regoff;
++
++ si = SB_INFO(sbh);
++ regoff = 0;
++
++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */
++
++ /* gpios could be shared on router platforms */
++ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
++ mask = priority ? (sb_gpioreservation & mask) :
++ ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
++ val &= mask;
++ }
++
++ switch (si->gpioid) {
++ case SB_CC:
++ regoff = OFFSETOF(chipcregs_t, gpioout);
++ break;
++
++ case SB_PCI:
++ regoff = OFFSETOF(sbpciregs_t, gpioout);
++ break;
++
++ case SB_EXTIF:
++ regoff = OFFSETOF(extifregs_t, gpio[0].out);
++ break;
++ }
++
++ return (sb_corereg(si, si->gpioidx, regoff, mask, val));
++}
++
++/* reserve one gpio */
++uint32
++sb_gpioreserve(sb_t *sbh, uint32 gpio_bitmask, uint8 priority)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++
++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */
++
++ /* only cores on SB_BUS share GPIO's and only applcation users need to
++ * reserve/release GPIO
++ */
++ if ((BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) {
++ ASSERT((BUSTYPE(si->sb.bustype) == SB_BUS) && (priority));
++ return -1;
++ }
++ /* make sure only one bit is set */
++ if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
++ ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
++ return -1;
++ }
++
++ /* already reserved */
++ if (sb_gpioreservation & gpio_bitmask)
++ return -1;
++ /* set reservation */
++ sb_gpioreservation |= gpio_bitmask;
++
++ return sb_gpioreservation;
++}
++
++/* release one gpio */
++/*
++ * releasing the gpio doesn't change the current value on the GPIO last write value
++ * persists till some one overwrites it
++*/
++
++uint32
++sb_gpiorelease(sb_t *sbh, uint32 gpio_bitmask, uint8 priority)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++
++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */
++
++ /* only cores on SB_BUS share GPIO's and only applcation users need to
++ * reserve/release GPIO
++ */
++ if ((BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) {
++ ASSERT((BUSTYPE(si->sb.bustype) == SB_BUS) && (priority));
++ return -1;
++ }
++ /* make sure only one bit is set */
++ if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
++ ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
++ return -1;
++ }
++
++ /* already released */
++ if (!(sb_gpioreservation & gpio_bitmask))
++ return -1;
++
++ /* clear reservation */
++ sb_gpioreservation &= ~gpio_bitmask;
++
++ return sb_gpioreservation;
++}
++
++/* return the current gpioin register value */
++uint32
++sb_gpioin(sb_t *sbh)
++{
++ sb_info_t *si;
++ uint regoff;
++
++ si = SB_INFO(sbh);
++ regoff = 0;
++
++ switch (si->gpioid) {
++ case SB_CC:
++ regoff = OFFSETOF(chipcregs_t, gpioin);
++ break;
++
++ case SB_PCI:
++ regoff = OFFSETOF(sbpciregs_t, gpioin);
++ break;
++
++ case SB_EXTIF:
++ regoff = OFFSETOF(extifregs_t, gpioin);
++ break;
++ }
++
++ return (sb_corereg(si, si->gpioidx, regoff, 0, 0));
++}
++
++/* mask&set gpio interrupt polarity bits */
++uint32
++sb_gpiointpolarity(sb_t *sbh, uint32 mask, uint32 val, uint8 priority)
++{
++ sb_info_t *si;
++ uint regoff;
++
++ si = SB_INFO(sbh);
++ regoff = 0;
++
++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */
++
++ /* gpios could be shared on router platforms */
++ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
++ mask = priority ? (sb_gpioreservation & mask) :
++ ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
++ val &= mask;
++ }
++
++ switch (si->gpioid) {
++ case SB_CC:
++ regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
++ break;
++
++ case SB_PCI:
++ /* pci gpio implementation does not support interrupt polarity */
++ ASSERT(0);
++ break;
++
++ case SB_EXTIF:
++ regoff = OFFSETOF(extifregs_t, gpiointpolarity);
++ break;
++ }
++
++ return (sb_corereg(si, si->gpioidx, regoff, mask, val));
++}
++
++/* mask&set gpio interrupt mask bits */
++uint32
++sb_gpiointmask(sb_t *sbh, uint32 mask, uint32 val, uint8 priority)
++{
++ sb_info_t *si;
++ uint regoff;
++
++ si = SB_INFO(sbh);
++ regoff = 0;
++
++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */
++
++ /* gpios could be shared on router platforms */
++ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
++ mask = priority ? (sb_gpioreservation & mask) :
++ ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
++ val &= mask;
++ }
++
++ switch (si->gpioid) {
++ case SB_CC:
++ regoff = OFFSETOF(chipcregs_t, gpiointmask);
++ break;
++
++ case SB_PCI:
++ /* pci gpio implementation does not support interrupt mask */
++ ASSERT(0);
++ break;
++
++ case SB_EXTIF:
++ regoff = OFFSETOF(extifregs_t, gpiointmask);
++ break;
++ }
++
++ return (sb_corereg(si, si->gpioidx, regoff, mask, val));
++}
++
++/* assign the gpio to an led */
++uint32
++sb_gpioled(sb_t *sbh, uint32 mask, uint32 val)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ if (si->sb.ccrev < 16)
++ return -1;
++
++ /* gpio led powersave reg */
++ return (sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val));
++}
++
++/* mask & set gpio timer val */
++uint32
++sb_gpiotimerval(sb_t *sbh, uint32 mask, uint32 gpiotimerval)
++{
++ sb_info_t *si;
++ si = SB_INFO(sbh);
++
++ if (si->sb.ccrev < 16)
++ return -1;
++
++ return (sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval));
++}
++
++
++/* return the slow clock source - LPO, XTAL, or PCI */
++static uint
++sb_slowclk_src(sb_info_t *si)
++{
++ chipcregs_t *cc;
++
++
++ ASSERT(sb_coreid(&si->sb) == SB_CC);
++
++ if (si->sb.ccrev < 6) {
++ if ((BUSTYPE(si->sb.bustype) == PCI_BUS) &&
++ (OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, sizeof(uint32)) &
++ PCI_CFG_GPIO_SCS))
++ return (SCC_SS_PCI);
++ else
++ return (SCC_SS_XTAL);
++ } else if (si->sb.ccrev < 10) {
++ cc = (chipcregs_t*) sb_setcoreidx(&si->sb, si->curidx);
++ return (R_REG(si->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
++ } else /* Insta-clock */
++ return (SCC_SS_XTAL);
++}
++
++/* return the ILP (slowclock) min or max frequency */
++static uint
++sb_slowclk_freq(sb_info_t *si, bool max)
++{
++ chipcregs_t *cc;
++ uint32 slowclk;
++ uint div;
++
++
++ ASSERT(sb_coreid(&si->sb) == SB_CC);
++
++ cc = (chipcregs_t*) sb_setcoreidx(&si->sb, si->curidx);
++
++ /* shouldn't be here unless we've established the chip has dynamic clk control */
++ ASSERT(R_REG(si->osh, &cc->capabilities) & CAP_PWR_CTL);
++
++ slowclk = sb_slowclk_src(si);
++ if (si->sb.ccrev < 6) {
++ if (slowclk == SCC_SS_PCI)
++ return (max? (PCIMAXFREQ/64) : (PCIMINFREQ/64));
++ else
++ return (max? (XTALMAXFREQ/32) : (XTALMINFREQ/32));
++ } else if (si->sb.ccrev < 10) {
++ div = 4 * (((R_REG(si->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
++ if (slowclk == SCC_SS_LPO)
++ return (max? LPOMAXFREQ : LPOMINFREQ);
++ else if (slowclk == SCC_SS_XTAL)
++ return (max? (XTALMAXFREQ/div) : (XTALMINFREQ/div));
++ else if (slowclk == SCC_SS_PCI)
++ return (max? (PCIMAXFREQ/div) : (PCIMINFREQ/div));
++ else
++ ASSERT(0);
++ } else {
++ /* Chipc rev 10 is InstaClock */
++ div = R_REG(si->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
++ div = 4 * (div + 1);
++ return (max ? XTALMAXFREQ : (XTALMINFREQ/div));
++ }
++ return (0);
++}
++
++static void
++BCMINITFN(sb_clkctl_setdelay)(sb_info_t *si, void *chipcregs)
++{
++ chipcregs_t * cc;
++ uint slowmaxfreq, pll_delay, slowclk;
++ uint pll_on_delay, fref_sel_delay;
++
++ pll_delay = PLL_DELAY;
++
++ /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
++ * since the xtal will also be powered down by dynamic clk control logic.
++ */
++
++ slowclk = sb_slowclk_src(si);
++ if (slowclk != SCC_SS_XTAL)
++ pll_delay += XTAL_ON_DELAY;
++
++ /* Starting with 4318 it is ILP that is used for the delays */
++ slowmaxfreq = sb_slowclk_freq(si, (si->sb.ccrev >= 10) ? FALSE : TRUE);
++
++ pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
++ fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
++
++ cc = (chipcregs_t *)chipcregs;
++ W_REG(si->osh, &cc->pll_on_delay, pll_on_delay);
++ W_REG(si->osh, &cc->fref_sel_delay, fref_sel_delay);
++}
++
++/* initialize power control delay registers */
++void
++BCMINITFN(sb_clkctl_init)(sb_t *sbh)
++{
++ sb_info_t *si;
++ uint origidx;
++ chipcregs_t *cc;
++
++ si = SB_INFO(sbh);
++
++ origidx = si->curidx;
++
++ if ((cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0)) == NULL)
++ return;
++
++ if ((si->sb.chip == BCM4321_CHIP_ID) && (si->sb.chiprev < 2))
++ W_REG(si->osh, &cc->chipcontrol,
++ (si->sb.chiprev == 0) ? CHIPCTRL_4321A0_DEFAULT : CHIPCTRL_4321A1_DEFAULT);
++
++ if (!(R_REG(si->osh, &cc->capabilities) & CAP_PWR_CTL))
++ goto done;
++
++ /* set all Instaclk chip ILP to 1 MHz */
++ else if (si->sb.ccrev >= 10)
++ SET_REG(si->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
++ (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
++
++ sb_clkctl_setdelay(si, (void *)cc);
++
++done:
++ sb_setcoreidx(sbh, origidx);
++}
++
++/* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */
++uint16
++sb_clkctl_fast_pwrup_delay(sb_t *sbh)
++{
++ sb_info_t *si;
++ uint origidx;
++ chipcregs_t *cc;
++ uint slowminfreq;
++ uint16 fpdelay;
++ uint intr_val = 0;
++
++ si = SB_INFO(sbh);
++ fpdelay = 0;
++ origidx = si->curidx;
++
++ INTR_OFF(si, intr_val);
++
++ if ((cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0)) == NULL)
++ goto done;
++
++ if (!(R_REG(si->osh, &cc->capabilities) & CAP_PWR_CTL))
++ goto done;
++
++ slowminfreq = sb_slowclk_freq(si, FALSE);
++ fpdelay = (((R_REG(si->osh, &cc->pll_on_delay) + 2) * 1000000) +
++ (slowminfreq - 1)) / slowminfreq;
++
++done:
++ sb_setcoreidx(sbh, origidx);
++ INTR_RESTORE(si, intr_val);
++ return (fpdelay);
++}
++
++/* turn primary xtal and/or pll off/on */
++int
++sb_clkctl_xtal(sb_t *sbh, uint what, bool on)
++{
++ sb_info_t *si;
++ uint32 in, out, outen;
++
++ si = SB_INFO(sbh);
++
++ switch (BUSTYPE(si->sb.bustype)) {
++
++
++ case PCMCIA_BUS:
++ return (0);
++
++
++ case PCI_BUS:
++
++ /* pcie core doesn't have any mapping to control the xtal pu */
++ if (PCIE(si))
++ return -1;
++
++ in = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_IN, sizeof(uint32));
++ out = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, sizeof(uint32));
++ outen = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUTEN, sizeof(uint32));
++
++ /*
++ * Avoid glitching the clock if GPRS is already using it.
++ * We can't actually read the state of the PLLPD so we infer it
++ * by the value of XTAL_PU which *is* readable via gpioin.
++ */
++ if (on && (in & PCI_CFG_GPIO_XTAL))
++ return (0);
++
++ if (what & XTAL)
++ outen |= PCI_CFG_GPIO_XTAL;
++ if (what & PLL)
++ outen |= PCI_CFG_GPIO_PLL;
++
++ if (on) {
++ /* turn primary xtal on */
++ if (what & XTAL) {
++ out |= PCI_CFG_GPIO_XTAL;
++ if (what & PLL)
++ out |= PCI_CFG_GPIO_PLL;
++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT,
++ sizeof(uint32), out);
++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUTEN,
++ sizeof(uint32), outen);
++ OSL_DELAY(XTAL_ON_DELAY);
++ }
++
++ /* turn pll on */
++ if (what & PLL) {
++ out &= ~PCI_CFG_GPIO_PLL;
++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT,
++ sizeof(uint32), out);
++ OSL_DELAY(2000);
++ }
++ } else {
++ if (what & XTAL)
++ out &= ~PCI_CFG_GPIO_XTAL;
++ if (what & PLL)
++ out |= PCI_CFG_GPIO_PLL;
++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT, sizeof(uint32), out);
++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUTEN, sizeof(uint32),
++ outen);
++ }
++
++ default:
++ return (-1);
++ }
++
++ return (0);
++}
++
++/* set dynamic clk control mode (forceslow, forcefast, dynamic) */
++/* returns true if we are forcing fast clock */
++bool
++sb_clkctl_clk(sb_t *sbh, uint mode)
++{
++ sb_info_t *si;
++ uint origidx;
++ chipcregs_t *cc;
++ uint32 scc;
++ uint intr_val = 0;
++
++ si = SB_INFO(sbh);
++
++ /* chipcommon cores prior to rev6 don't support dynamic clock control */
++ if (si->sb.ccrev < 6)
++ return (FALSE);
++
++
++ /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */
++ ASSERT(si->sb.ccrev != 10);
++
++ INTR_OFF(si, intr_val);
++
++ origidx = si->curidx;
++
++ if (sb_setcore(sbh, SB_MIPS33, 0) && (sb_corerev(&si->sb) <= 7) &&
++ (BUSTYPE(si->sb.bustype) == SB_BUS) && (si->sb.ccrev >= 10))
++ goto done;
++
++ /* PR32414WAR "Force HT clock on" all the time, no dynamic clk ctl */
++ if ((si->sb.chip == BCM4311_CHIP_ID) && (si->sb.chiprev <= 1))
++ goto done;
++
++ cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0);
++ ASSERT(cc != NULL);
++
++ if (!(R_REG(si->osh, &cc->capabilities) & CAP_PWR_CTL))
++ goto done;
++
++ switch (mode) {
++ case CLK_FAST: /* force fast (pll) clock */
++ if (si->sb.ccrev < 10) {
++ /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
++ sb_clkctl_xtal(&si->sb, XTAL, ON);
++
++ SET_REG(si->osh, &cc->slow_clk_ctl, (SCC_XC | SCC_FS | SCC_IP), SCC_IP);
++ } else
++ OR_REG(si->osh, &cc->system_clk_ctl, SYCC_HR);
++ /* wait for the PLL */
++ OSL_DELAY(PLL_DELAY);
++ break;
++
++ case CLK_DYNAMIC: /* enable dynamic clock control */
++
++ if (si->sb.ccrev < 10) {
++ scc = R_REG(si->osh, &cc->slow_clk_ctl);
++ scc &= ~(SCC_FS | SCC_IP | SCC_XC);
++ if ((scc & SCC_SS_MASK) != SCC_SS_XTAL)
++ scc |= SCC_XC;
++ W_REG(si->osh, &cc->slow_clk_ctl, scc);
++
++ /* for dynamic control, we have to release our xtal_pu "force on" */
++ if (scc & SCC_XC)
++ sb_clkctl_xtal(&si->sb, XTAL, OFF);
++ } else {
++ /* Instaclock */
++ AND_REG(si->osh, &cc->system_clk_ctl, ~SYCC_HR);
++ }
++ break;
++
++ default:
++ ASSERT(0);
++ }
++
++done:
++ sb_setcoreidx(sbh, origidx);
++ INTR_RESTORE(si, intr_val);
++ return (mode == CLK_FAST);
++}
++
++/* register driver interrupt disabling and restoring callback functions */
++void
++sb_register_intr_callback(sb_t *sbh, void *intrsoff_fn, void *intrsrestore_fn,
++ void *intrsenabled_fn, void *intr_arg)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ si->intr_arg = intr_arg;
++ si->intrsoff_fn = (sb_intrsoff_t)intrsoff_fn;
++ si->intrsrestore_fn = (sb_intrsrestore_t)intrsrestore_fn;
++ si->intrsenabled_fn = (sb_intrsenabled_t)intrsenabled_fn;
++ /* save current core id. when this function called, the current core
++ * must be the core which provides driver functions(il, et, wl, etc.)
++ */
++ si->dev_coreid = si->coreid[si->curidx];
++}
++
++
++int
++sb_corepciid(sb_t *sbh, uint func, uint16 *pcivendor, uint16 *pcidevice,
++ uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif,
++ uint8 *pciheader)
++{
++ uint16 vendor = 0xffff, device = 0xffff;
++ uint core, unit;
++ uint chip, chippkg;
++ uint nfunc;
++ char varname[SB_DEVPATH_BUFSZ + 8];
++ uint8 class, subclass, progif;
++ char devpath[SB_DEVPATH_BUFSZ];
++ uint8 header;
++
++ core = sb_coreid(sbh);
++ unit = sb_coreunit(sbh);
++
++ chip = sb_chip(sbh);
++ chippkg = sb_chippkg(sbh);
++
++ progif = 0;
++ header = PCI_HEADER_NORMAL;
++
++ /* Verify whether the function exists for the core */
++ nfunc = (core == SB_USB20H) ? 2 : 1;
++ if (func >= nfunc)
++ return BCME_ERROR;
++
++ /* Known vendor translations */
++ switch (sb_corevendor(sbh)) {
++ case SB_VEND_BCM:
++ vendor = VENDOR_BROADCOM;
++ break;
++ default:
++ return BCME_ERROR;
++ }
++
++ /* Determine class based on known core codes */
++ switch (core) {
++ case SB_ILINE20:
++ class = PCI_CLASS_NET;
++ subclass = PCI_NET_ETHER;
++ device = BCM47XX_ILINE_ID;
++ break;
++ case SB_ENET:
++ class = PCI_CLASS_NET;
++ subclass = PCI_NET_ETHER;
++ device = BCM47XX_ENET_ID;
++ break;
++ case SB_GIGETH:
++ class = PCI_CLASS_NET;
++ subclass = PCI_NET_ETHER;
++ device = BCM47XX_GIGETH_ID;
++ break;
++ case SB_SDRAM:
++ case SB_MEMC:
++ class = PCI_CLASS_MEMORY;
++ subclass = PCI_MEMORY_RAM;
++ device = (uint16)core;
++ break;
++ case SB_PCI:
++ case SB_PCIE:
++ class = PCI_CLASS_BRIDGE;
++ subclass = PCI_BRIDGE_PCI;
++ device = (uint16)core;
++ header = PCI_HEADER_BRIDGE;
++ break;
++ case SB_MIPS:
++ case SB_MIPS33:
++ class = PCI_CLASS_CPU;
++ subclass = PCI_CPU_MIPS;
++ device = (uint16)core;
++ break;
++ case SB_CODEC:
++ class = PCI_CLASS_COMM;
++ subclass = PCI_COMM_MODEM;
++ device = BCM47XX_V90_ID;
++ break;
++ case SB_USB:
++ class = PCI_CLASS_SERIAL;
++ subclass = PCI_SERIAL_USB;
++ progif = 0x10; /* OHCI */
++ device = BCM47XX_USB_ID;
++ break;
++ case SB_USB11H:
++ class = PCI_CLASS_SERIAL;
++ subclass = PCI_SERIAL_USB;
++ progif = 0x10; /* OHCI */
++ device = BCM47XX_USBH_ID;
++ break;
++ case SB_USB20H:
++ class = PCI_CLASS_SERIAL;
++ subclass = PCI_SERIAL_USB;
++ progif = func == 0 ? 0x10 : 0x20; /* OHCI/EHCI */
++ device = BCM47XX_USB20H_ID;
++ header = 0x80; /* multifunction */
++ break;
++ case SB_USB11D:
++ class = PCI_CLASS_SERIAL;
++ subclass = PCI_SERIAL_USB;
++ device = BCM47XX_USBD_ID;
++ break;
++ case SB_USB20D:
++ class = PCI_CLASS_SERIAL;
++ subclass = PCI_SERIAL_USB;
++ device = BCM47XX_USB20D_ID;
++ break;
++ case SB_IPSEC:
++ class = PCI_CLASS_CRYPT;
++ subclass = PCI_CRYPT_NETWORK;
++ device = BCM47XX_IPSEC_ID;
++ break;
++ case SB_ROBO:
++ class = PCI_CLASS_NET;
++ subclass = PCI_NET_OTHER;
++ device = BCM47XX_ROBO_ID;
++ break;
++ case SB_EXTIF:
++ case SB_CC:
++ class = PCI_CLASS_MEMORY;
++ subclass = PCI_MEMORY_FLASH;
++ device = (uint16)core;
++ break;
++ case SB_D11:
++ class = PCI_CLASS_NET;
++ subclass = PCI_NET_OTHER;
++ /* Let nvram variable override core ID */
++ sb_devpath(sbh, devpath, sizeof(devpath));
++ sprintf(varname, "%sdevid", devpath);
++ if ((device = (uint16)getintvar(NULL, varname)))
++ break;
++ /*
++ * no longer support wl%did, but keep the code
++ * here for backward compatibility.
++ */
++ sprintf(varname, "wl%did", unit);
++ if ((device = (uint16)getintvar(NULL, varname)))
++ break;
++ /* Chip specific conversion */
++ if (chip == BCM4712_CHIP_ID) {
++ if (chippkg == BCM4712SMALL_PKG_ID)
++ device = BCM4306_D11G_ID;
++ else
++ device = BCM4306_D11DUAL_ID;
++ break;
++ }
++ /* ignore it */
++ device = 0xffff;
++ break;
++ case SB_SATAXOR:
++ class = PCI_CLASS_XOR;
++ subclass = PCI_XOR_QDMA;
++ device = BCM47XX_SATAXOR_ID;
++ break;
++ case SB_ATA100:
++ class = PCI_CLASS_DASDI;
++ subclass = PCI_DASDI_IDE;
++ device = BCM47XX_ATA100_ID;
++ break;
++
++ default:
++ class = subclass = progif = 0xff;
++ device = (uint16)core;
++ break;
++ }
++
++ *pcivendor = vendor;
++ *pcidevice = device;
++ *pciclass = class;
++ *pcisubclass = subclass;
++ *pciprogif = progif;
++ *pciheader = header;
++
++ return 0;
++}
++
++
++
++/* use the mdio interface to write to mdio slaves */
++static int
++sb_pcie_mdiowrite(sb_info_t *si, uint physmedia, uint regaddr, uint val)
++{
++ uint mdiodata;
++ uint i = 0;
++ sbpcieregs_t *pcieregs;
++
++ pcieregs = (sbpcieregs_t*) sb_setcoreidx(&si->sb, si->sb.buscoreidx);
++ ASSERT(pcieregs);
++
++ /* enable mdio access to SERDES */
++ W_REG(si->osh, (&pcieregs->mdiocontrol), MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
++
++ mdiodata = MDIODATA_START | MDIODATA_WRITE |
++ (physmedia << MDIODATA_DEVADDR_SHF) |
++ (regaddr << MDIODATA_REGADDR_SHF) | MDIODATA_TA | val;
++
++ W_REG(si->osh, (&pcieregs->mdiodata), mdiodata);
++
++ PR28829_DELAY();
++
++ /* retry till the transaction is complete */
++ while (i < 10) {
++ if (R_REG(si->osh, &(pcieregs->mdiocontrol)) & MDIOCTL_ACCESS_DONE) {
++ /* Disable mdio access to SERDES */
++ W_REG(si->osh, (&pcieregs->mdiocontrol), 0);
++ return 0;
++ }
++ OSL_DELAY(1000);
++ i++;
++ }
++
++ SB_ERROR(("sb_pcie_mdiowrite: timed out\n"));
++ /* Disable mdio access to SERDES */
++ W_REG(si->osh, (&pcieregs->mdiocontrol), 0);
++ ASSERT(0);
++ return 1;
++
++}
++
++/* indirect way to read pcie config regs */
++uint
++sb_pcie_readreg(void *sb, void* arg1, uint offset)
++{
++ sb_info_t *si;
++ sb_t *sbh;
++ uint retval = 0xFFFFFFFF;
++ sbpcieregs_t *pcieregs;
++ uint addrtype;
++
++ sbh = (sb_t *)sb;
++ si = SB_INFO(sbh);
++ ASSERT(PCIE(si));
++
++ pcieregs = (sbpcieregs_t *)sb_setcore(sbh, SB_PCIE, 0);
++ ASSERT(pcieregs);
++
++ addrtype = (uint)((uintptr)arg1);
++ switch (addrtype) {
++ case PCIE_CONFIGREGS:
++ W_REG(si->osh, (&pcieregs->configaddr), offset);
++ retval = R_REG(si->osh, &(pcieregs->configdata));
++ break;
++ case PCIE_PCIEREGS:
++ W_REG(si->osh, &(pcieregs->pcieaddr), offset);
++ retval = R_REG(si->osh, &(pcieregs->pciedata));
++ break;
++ default:
++ ASSERT(0);
++ break;
++ }
++ return retval;
++}
++
++/* indirect way to write pcie config/mdio/pciecore regs */
++uint
++sb_pcie_writereg(sb_t *sbh, void *arg1, uint offset, uint val)
++{
++ sb_info_t *si;
++ sbpcieregs_t *pcieregs;
++ uint addrtype;
++
++ si = SB_INFO(sbh);
++ ASSERT(PCIE(si));
++
++ pcieregs = (sbpcieregs_t *)sb_setcore(sbh, SB_PCIE, 0);
++ ASSERT(pcieregs);
++
++ addrtype = (uint)((uintptr)arg1);
++
++ switch (addrtype) {
++ case PCIE_CONFIGREGS:
++ W_REG(si->osh, (&pcieregs->configaddr), offset);
++ W_REG(si->osh, (&pcieregs->configdata), val);
++ break;
++ case PCIE_PCIEREGS:
++ W_REG(si->osh, (&pcieregs->pcieaddr), offset);
++ W_REG(si->osh, (&pcieregs->pciedata), val);
++ break;
++ default:
++ ASSERT(0);
++ break;
++ }
++ return 0;
++}
++
++/* Build device path. Support SB, PCI, and JTAG for now. */
++int
++sb_devpath(sb_t *sbh, char *path, int size)
++{
++ ASSERT(path);
++ ASSERT(size >= SB_DEVPATH_BUFSZ);
++
++ switch (BUSTYPE((SB_INFO(sbh))->sb.bustype)) {
++ case SB_BUS:
++ case JTAG_BUS:
++ sprintf(path, "sb/%u/", sb_coreidx(sbh));
++ break;
++ case PCI_BUS:
++ ASSERT((SB_INFO(sbh))->osh);
++ sprintf(path, "pci/%u/%u/", OSL_PCI_BUS((SB_INFO(sbh))->osh),
++ OSL_PCI_SLOT((SB_INFO(sbh))->osh));
++ break;
++ case PCMCIA_BUS:
++ SB_ERROR(("sb_devpath: OSL_PCMCIA_BUS() not implemented, bus 1 assumed\n"));
++ SB_ERROR(("sb_devpath: OSL_PCMCIA_SLOT() not implemented, slot 1 assumed\n"));
++ sprintf(path, "pc/%u/%u/", 1, 1);
++ break;
++ case SDIO_BUS:
++ SB_ERROR(("sb_devpath: device 0 assumed\n"));
++ sprintf(path, "sd/%u/", sb_coreidx(sbh));
++ break;
++ default:
++ ASSERT(0);
++ break;
++ }
++
++ return 0;
++}
++
++/*
++ * Fixup SROMless PCI device's configuration.
++ * The current core may be changed upon return.
++ */
++static int
++sb_pci_fixcfg(sb_info_t *si)
++{
++ uint origidx, pciidx;
++ sbpciregs_t *pciregs;
++ sbpcieregs_t *pcieregs;
++ uint16 val16, *reg16;
++ char name[SB_DEVPATH_BUFSZ+16], *value;
++ char devpath[SB_DEVPATH_BUFSZ];
++
++ ASSERT(BUSTYPE(si->sb.bustype) == PCI_BUS);
++
++ /* Fixup PI in SROM shadow area to enable the correct PCI core access */
++ /* save the current index */
++ origidx = sb_coreidx(&si->sb);
++
++ /* check 'pi' is correct and fix it if not */
++ if (si->sb.buscoretype == SB_PCIE) {
++ pcieregs = (sbpcieregs_t *)sb_setcore(&si->sb, SB_PCIE, 0);
++ ASSERT(pcieregs);
++ reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
++ } else if (si->sb.buscoretype == SB_PCI) {
++ pciregs = (sbpciregs_t *)sb_setcore(&si->sb, SB_PCI, 0);
++ ASSERT(pciregs);
++ reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
++ } else {
++ ASSERT(0);
++ return -1;
++ }
++ pciidx = sb_coreidx(&si->sb);
++ val16 = R_REG(si->osh, reg16);
++ if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (uint16)pciidx) {
++ val16 = (uint16)(pciidx << SRSH_PI_SHIFT) | (val16 & ~SRSH_PI_MASK);
++ W_REG(si->osh, reg16, val16);
++ }
++
++ /* restore the original index */
++ sb_setcoreidx(&si->sb, origidx);
++
++ /*
++ * Fixup bar0window in PCI config space to make the core indicated
++ * by the nvram variable the current core.
++ * !Do it last, it may change the current core!
++ */
++ if (sb_devpath(&si->sb, devpath, sizeof(devpath)))
++ return -1;
++ sprintf(name, "%sb0w", devpath);
++ if ((value = getvar(NULL, name))) {
++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32),
++ bcm_strtoul(value, NULL, 16));
++ /* update curidx since the current core is changed */
++ si->curidx = _sb_coreidx(si);
++ if (si->curidx == BADIDX) {
++ SB_ERROR(("sb_pci_fixcfg: bad core index\n"));
++ return -1;
++ }
++ }
++
++ return 0;
++}
++
++static uint
++sb_chipc_capability(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++
++ /* Make sure that there is ChipCommon core present */
++ if (si->coreid[SB_CC_IDX] == SB_CC)
++ return (sb_corereg(si, SB_CC_IDX, OFFSETOF(chipcregs_t, capabilities),
++ 0, 0));
++ return 0;
++}
++
++/* Return ADDR64 capability of the backplane */
++bool
++sb_backplane64(sb_t *sbh)
++{
++ return ((sb_chipc_capability(sbh) & CAP_BKPLN64) != 0);
++}
++
++void
++sb_btcgpiowar(sb_t *sbh)
++{
++ sb_info_t *si;
++ uint origidx;
++ uint intr_val = 0;
++ chipcregs_t *cc;
++ si = SB_INFO(sbh);
++
++ /* Make sure that there is ChipCommon core present &&
++ * UART_TX is strapped to 1
++ */
++ if (!(sb_chipc_capability(sbh) & CAP_UARTGPIO))
++ return;
++
++ /* sb_corereg cannot be used as we have to guarantee 8-bit read/writes */
++ INTR_OFF(si, intr_val);
++
++ origidx = sb_coreidx(sbh);
++
++ cc = (chipcregs_t *)sb_setcore(sbh, SB_CC, 0);
++ if (cc == NULL)
++ goto end;
++
++ W_REG(si->osh, &cc->uart0mcr, R_REG(si->osh, &cc->uart0mcr) | 0x04);
++
++end:
++ /* restore the original index */
++ sb_setcoreidx(sbh, origidx);
++
++ INTR_RESTORE(si, intr_val);
++}
++
++/* check if the device is removed */
++bool
++sb_deviceremoved(sb_t *sbh)
++{
++ uint32 w;
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++
++ switch (BUSTYPE(si->sb.bustype)) {
++ case PCI_BUS:
++ ASSERT(si->osh);
++ w = OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_VID, sizeof(uint32));
++ if ((w & 0xFFFF) != VENDOR_BROADCOM)
++ return TRUE;
++ else
++ return FALSE;
++ default:
++ return FALSE;
++ }
++ return FALSE;
++}
++
++/* Return the RAM size of the SOCRAM core */
++uint32
++sb_socram_size(sb_t *sbh)
++{
++ sb_info_t *si;
++ uint origidx;
++ uint intr_val = 0;
++
++ sbsocramregs_t *regs;
++ bool wasup;
++ uint corerev;
++ uint32 coreinfo;
++ uint memsize = 0;
++
++ si = SB_INFO(sbh);
++ ASSERT(si);
++
++ /* Block ints and save current core */
++ INTR_OFF(si, intr_val);
++ origidx = sb_coreidx(sbh);
++
++ /* Switch to SOCRAM core */
++ if (!(regs = sb_setcore(sbh, SB_SOCRAM, 0)))
++ goto done;
++
++ /* Get info for determining size */
++ if (!(wasup = sb_iscoreup(sbh)))
++ sb_core_reset(sbh, 0, 0);
++ corerev = sb_corerev(sbh);
++ coreinfo = R_REG(si->osh, &regs->coreinfo);
++
++ /* Calculate size from coreinfo based on rev */
++ switch (corerev) {
++ case 0:
++ memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
++ break;
++ default: /* rev >= 1 */
++ memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
++ memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
++ break;
++ }
++
++ /* Return to previous state and core */
++ if (!wasup)
++ sb_core_disable(sbh, 0);
++ sb_setcoreidx(sbh, origidx);
++
++done:
++ INTR_RESTORE(si, intr_val);
++ return memsize;
++}
++
++
+diff -urN linux.old/arch/mips/bcm947xx/setup.c linux.dev/arch/mips/bcm947xx/setup.c
+--- linux.old/arch/mips/bcm947xx/setup.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/setup.c 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,241 @@
++/*
++ * Generic setup routines for Broadcom MIPS boards
++ *
++ * 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.
++ *
++ * THIS SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ * Copyright 2005, 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.
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/serialP.h>
++#include <linux/ide.h>
++#include <asm/bootinfo.h>
++#include <asm/cpu.h>
++#include <asm/time.h>
++#include <asm/reboot.h>
++
++#include <typedefs.h>
++#include <osl.h>
++#include <sbutils.h>
++#include <bcmutils.h>
++#include <bcmnvram.h>
++#include <sbhndmips.h>
++#include <hndmips.h>
++#include <trxhdr.h>
++
++/* Virtual IRQ base, after last hw IRQ */
++#define SBMIPS_VIRTIRQ_BASE 6
++
++/* # IRQs, hw and sw IRQs */
++#define SBMIPS_NUMIRQS 8
++
++/* Global SB handle */
++sb_t *bcm947xx_sbh = NULL;
++spinlock_t bcm947xx_sbh_lock = SPIN_LOCK_UNLOCKED;
++
++/* Convenience */
++#define sbh bcm947xx_sbh
++#define sbh_lock bcm947xx_sbh_lock
++
++extern void bcm947xx_time_init(void);
++extern void bcm947xx_timer_setup(struct irqaction *irq);
++
++#ifdef CONFIG_REMOTE_DEBUG
++extern void set_debug_traps(void);
++extern void rs_kgdb_hook(struct serial_state *);
++extern void breakpoint(void);
++#endif
++
++#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
++extern struct ide_ops std_ide_ops;
++#endif
++
++/* Kernel command line */
++char arcs_cmdline[CL_SIZE] __initdata = CONFIG_CMDLINE;
++extern void sb_serial_init(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base, uint reg_shift));
++
++void
++bcm947xx_machine_restart(char *command)
++{
++ printk("Please stand by while rebooting the system...\n");
++
++ /* Set the watchdog timer to reset immediately */
++ __cli();
++ sb_watchdog(sbh, 1);
++ while (1);
++}
++
++void
++bcm947xx_machine_halt(void)
++{
++ printk("System halted\n");
++
++ /* Disable interrupts and watchdog and spin forever */
++ __cli();
++ sb_watchdog(sbh, 0);
++ while (1);
++}
++
++#ifdef CONFIG_SERIAL
++
++static int ser_line = 0;
++
++typedef struct {
++ void *regs;
++ uint irq;
++ uint baud_base;
++ uint reg_shift;
++} serial_port;
++
++static serial_port ports[4];
++static int num_ports = 0;
++
++static void
++serial_add(void *regs, uint irq, uint baud_base, uint reg_shift)
++{
++ ports[num_ports].regs = regs;
++ ports[num_ports].irq = irq;
++ ports[num_ports].baud_base = baud_base;
++ ports[num_ports].reg_shift = reg_shift;
++ num_ports++;
++}
++
++static void
++do_serial_add(serial_port *port)
++{
++ void *regs;
++ uint irq;
++ uint baud_base;
++ uint reg_shift;
++ struct serial_struct s;
++
++ regs = port->regs;
++ irq = port->irq;
++ baud_base = port->baud_base;
++ reg_shift = port->reg_shift;
++
++ memset(&s, 0, sizeof(s));
++
++ s.line = ser_line++;
++ s.iomem_base = regs;
++ s.irq = irq + 2;
++ s.baud_base = baud_base / 16;
++ s.flags = ASYNC_BOOT_AUTOCONF;
++ s.io_type = SERIAL_IO_MEM;
++ s.iomem_reg_shift = reg_shift;
++
++ if (early_serial_setup(&s) != 0) {
++ printk(KERN_ERR "Serial setup failed!\n");
++ }
++}
++
++#endif /* CONFIG_SERIAL */
++
++void __init
++brcm_setup(void)
++{
++ char *s;
++ int i;
++ char *value;
++
++ /* Get global SB handle */
++ sbh = sb_kattach();
++
++ /* Initialize clocks and interrupts */
++ sb_mips_init(sbh, SBMIPS_VIRTIRQ_BASE);
++
++ if (BCM330X(current_cpu_data.processor_id) &&
++ (read_c0_diag() & BRCM_PFC_AVAIL)) {
++ /*
++ * Now that the sbh is inited set the proper PFC value
++ */
++ printk("Setting the PFC to its default value\n");
++ enable_pfc(PFC_AUTO);
++ }
++
++
++#ifdef CONFIG_SERIAL
++ sb_serial_init(sbh, serial_add);
++
++ /* reverse serial ports if nvram variable starts with console=ttyS1 */
++ /* Initialize UARTs */
++ s = nvram_get("kernel_args");
++ if (!s) s = "";
++ if (!strncmp(s, "console=ttyS1", 13)) {
++ for (i = num_ports; i; i--)
++ do_serial_add(&ports[i - 1]);
++ } else {
++ for (i = 0; i < num_ports; i++)
++ do_serial_add(&ports[i]);
++ }
++#endif
++
++#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
++ ide_ops = &std_ide_ops;
++#endif
++
++ /* Override default command line arguments */
++ value = nvram_get("kernel_cmdline");
++ if (value && strlen(value) && strncmp(value, "empty", 5))
++ strncpy(arcs_cmdline, value, sizeof(arcs_cmdline));
++
++
++ /* Generic setup */
++ _machine_restart = bcm947xx_machine_restart;
++ _machine_halt = bcm947xx_machine_halt;
++ _machine_power_off = bcm947xx_machine_halt;
++
++ board_time_init = bcm947xx_time_init;
++ board_timer_setup = bcm947xx_timer_setup;
++}
++
++const char *
++get_system_type(void)
++{
++ static char s[32];
++
++ if (bcm947xx_sbh) {
++ sprintf(s, "Broadcom BCM%X chip rev %d", sb_chip(bcm947xx_sbh),
++ sb_chiprev(bcm947xx_sbh));
++ return s;
++ }
++ else
++ return "Broadcom BCM947XX";
++}
++
++void __init
++bus_error_init(void)
++{
++}
++
+diff -urN linux.old/arch/mips/bcm947xx/sflash.c linux.dev/arch/mips/bcm947xx/sflash.c
+--- linux.old/arch/mips/bcm947xx/sflash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/sflash.c 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,422 @@
++/*
++ * Broadcom SiliconBackplane chipcommon serial flash interface
++ *
++ * 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.
++ *
++ * $Id: sflash.c,v 1.1.1.13 2006/02/27 03:43:16 honor Exp $
++ */
++
++#include <osl.h>
++#include <typedefs.h>
++#include <sbconfig.h>
++#include <sbchipc.h>
++#include <mipsinc.h>
++#include <bcmutils.h>
++#include <bcmdevs.h>
++#include <sflash.h>
++
++/* Private global state */
++static struct sflash sflash;
++
++/* Issue a serial flash command */
++static INLINE void
++sflash_cmd(chipcregs_t *cc, uint opcode)
++{
++ W_REG(NULL, &cc->flashcontrol, SFLASH_START | opcode);
++ while (R_REG(NULL, &cc->flashcontrol) & SFLASH_BUSY);
++}
++
++/* Initialize serial flash access */
++struct sflash *
++sflash_init(chipcregs_t *cc)
++{
++ uint32 id, id2;
++
++ bzero(&sflash, sizeof(sflash));
++
++ sflash.type = R_REG(NULL, &cc->capabilities) & CAP_FLASH_MASK;
++
++ switch (sflash.type) {
++ case SFLASH_ST:
++ /* Probe for ST chips */
++ sflash_cmd(cc, SFLASH_ST_DP);
++ sflash_cmd(cc, SFLASH_ST_RES);
++ id = R_REG(NULL, &cc->flashdata);
++ switch (id) {
++ case 0x11:
++ /* ST M25P20 2 Mbit Serial Flash */
++ sflash.blocksize = 64 * 1024;
++ sflash.numblocks = 4;
++ break;
++ case 0x12:
++ /* ST M25P40 4 Mbit Serial Flash */
++ sflash.blocksize = 64 * 1024;
++ sflash.numblocks = 8;
++ break;
++ case 0x13:
++ /* ST M25P80 8 Mbit Serial Flash */
++ sflash.blocksize = 64 * 1024;
++ sflash.numblocks = 16;
++ break;
++ case 0x14:
++ /* ST M25P16 16 Mbit Serial Flash */
++ sflash.blocksize = 64 * 1024;
++ sflash.numblocks = 32;
++ break;
++ case 0x15:
++ /* ST M25P32 32 Mbit Serial Flash */
++ sflash.blocksize = 64 * 1024;
++ sflash.numblocks = 64;
++ break;
++ case 0x16:
++ /* ST M25P64 64 Mbit Serial Flash */
++ sflash.blocksize = 64 * 1024;
++ sflash.numblocks = 128;
++ break;
++ case 0xbf:
++ W_REG(NULL, &cc->flashaddress, 1);
++ sflash_cmd(cc, SFLASH_ST_RES);
++ id2 = R_REG(NULL, &cc->flashdata);
++ if (id2 == 0x44) {
++ /* SST M25VF80 4 Mbit Serial Flash */
++ sflash.blocksize = 64 * 1024;
++ sflash.numblocks = 8;
++ }
++ break;
++ }
++ break;
++
++ case SFLASH_AT:
++ /* Probe for Atmel chips */
++ sflash_cmd(cc, SFLASH_AT_STATUS);
++ id = R_REG(NULL, &cc->flashdata) & 0x3c;
++ switch (id) {
++ case 0xc:
++ /* Atmel AT45DB011 1Mbit Serial Flash */
++ sflash.blocksize = 256;
++ sflash.numblocks = 512;
++ break;
++ case 0x14:
++ /* Atmel AT45DB021 2Mbit Serial Flash */
++ sflash.blocksize = 256;
++ sflash.numblocks = 1024;
++ break;
++ case 0x1c:
++ /* Atmel AT45DB041 4Mbit Serial Flash */
++ sflash.blocksize = 256;
++ sflash.numblocks = 2048;
++ break;
++ case 0x24:
++ /* Atmel AT45DB081 8Mbit Serial Flash */
++ sflash.blocksize = 256;
++ sflash.numblocks = 4096;
++ break;
++ case 0x2c:
++ /* Atmel AT45DB161 16Mbit Serial Flash */
++ sflash.blocksize = 512;
++ sflash.numblocks = 4096;
++ break;
++ case 0x34:
++ /* Atmel AT45DB321 32Mbit Serial Flash */
++ sflash.blocksize = 512;
++ sflash.numblocks = 8192;
++ break;
++ case 0x3c:
++ /* Atmel AT45DB642 64Mbit Serial Flash */
++ sflash.blocksize = 1024;
++ sflash.numblocks = 8192;
++ break;
++ }
++ break;
++ }
++
++ sflash.size = sflash.blocksize * sflash.numblocks;
++ return sflash.size ? &sflash : NULL;
++}
++
++/* Read len bytes starting at offset into buf. Returns number of bytes read. */
++int
++sflash_read(chipcregs_t *cc, uint offset, uint len, uchar *buf)
++{
++ int cnt;
++ uint32 *from, *to;
++
++ if (!len)
++ return 0;
++
++ if ((offset + len) > sflash.size)
++ return -22;
++
++ if ((len >= 4) && (offset & 3))
++ cnt = 4 - (offset & 3);
++ else if ((len >= 4) && ((uint32)buf & 3))
++ cnt = 4 - ((uint32)buf & 3);
++ else
++ cnt = len;
++
++ from = (uint32 *)KSEG1ADDR(SB_FLASH2 + offset);
++ to = (uint32 *)buf;
++
++ if (cnt < 4) {
++ bcopy(from, to, cnt);
++ return cnt;
++ }
++
++ while (cnt >= 4) {
++ *to++ = *from++;
++ cnt -= 4;
++ }
++
++ return (len - cnt);
++}
++
++/* Poll for command completion. Returns zero when complete. */
++int
++sflash_poll(chipcregs_t *cc, uint offset)
++{
++ if (offset >= sflash.size)
++ return -22;
++
++ switch (sflash.type) {
++ case SFLASH_ST:
++ /* Check for ST Write In Progress bit */
++ sflash_cmd(cc, SFLASH_ST_RDSR);
++ return R_REG(NULL, &cc->flashdata) & SFLASH_ST_WIP;
++ case SFLASH_AT:
++ /* Check for Atmel Ready bit */
++ sflash_cmd(cc, SFLASH_AT_STATUS);
++ return !(R_REG(NULL, &cc->flashdata) & SFLASH_AT_READY);
++ }
++
++ return 0;
++}
++
++/* Write len bytes starting at offset into buf. Returns number of bytes
++ * written. Caller should poll for completion.
++ */
++int
++sflash_write(chipcregs_t *cc, uint offset, uint len, const uchar *buf)
++{
++ struct sflash *sfl;
++ int ret = 0;
++ bool is4712b0;
++ uint32 page, byte, mask;
++
++ if (!len)
++ return 0;
++
++ if ((offset + len) > sflash.size)
++ return -22;
++
++ sfl = &sflash;
++ switch (sfl->type) {
++ case SFLASH_ST:
++ mask = R_REG(NULL, &cc->chipid);
++ is4712b0 = (((mask & CID_ID_MASK) == BCM4712_CHIP_ID) &&
++ ((mask & CID_REV_MASK) == (3 << CID_REV_SHIFT)));
++ /* Enable writes */
++ sflash_cmd(cc, SFLASH_ST_WREN);
++ if (is4712b0) {
++ mask = 1 << 14;
++ W_REG(NULL, &cc->flashaddress, offset);
++ W_REG(NULL, &cc->flashdata, *buf++);
++ /* Set chip select */
++ OR_REG(NULL, &cc->gpioout, mask);
++ /* Issue a page program with the first byte */
++ sflash_cmd(cc, SFLASH_ST_PP);
++ ret = 1;
++ offset++;
++ len--;
++ while (len > 0) {
++ if ((offset & 255) == 0) {
++ /* Page boundary, drop cs and return */
++ AND_REG(NULL, &cc->gpioout, ~mask);
++ if (!sflash_poll(cc, offset)) {
++ /* Flash rejected command */
++ return -11;
++ }
++ return ret;
++ } else {
++ /* Write single byte */
++ sflash_cmd(cc, *buf++);
++ }
++ ret++;
++ offset++;
++ len--;
++ }
++ /* All done, drop cs if needed */
++ if ((offset & 255) != 1) {
++ /* Drop cs */
++ AND_REG(NULL, &cc->gpioout, ~mask);
++ if (!sflash_poll(cc, offset)) {
++ /* Flash rejected command */
++ return -12;
++ }
++ }
++ } else {
++ ret = 1;
++ W_REG(NULL, &cc->flashaddress, offset);
++ W_REG(NULL, &cc->flashdata, *buf);
++ /* Page program */
++ sflash_cmd(cc, SFLASH_ST_PP);
++ }
++ break;
++ case SFLASH_AT:
++ mask = sfl->blocksize - 1;
++ page = (offset & ~mask) << 1;
++ byte = offset & mask;
++ /* Read main memory page into buffer 1 */
++ if (byte || (len < sfl->blocksize)) {
++ W_REG(NULL, &cc->flashaddress, page);
++ sflash_cmd(cc, SFLASH_AT_BUF1_LOAD);
++ /* 250 us for AT45DB321B */
++ SPINWAIT(sflash_poll(cc, offset), 1000);
++ ASSERT(!sflash_poll(cc, offset));
++ }
++ /* Write into buffer 1 */
++ for (ret = 0; (ret < (int)len) && (byte < sfl->blocksize); ret++) {
++ W_REG(NULL, &cc->flashaddress, byte++);
++ W_REG(NULL, &cc->flashdata, *buf++);
++ sflash_cmd(cc, SFLASH_AT_BUF1_WRITE);
++ }
++ /* Write buffer 1 into main memory page */
++ W_REG(NULL, &cc->flashaddress, page);
++ sflash_cmd(cc, SFLASH_AT_BUF1_PROGRAM);
++ break;
++ }
++
++ return ret;
++}
++
++/* Erase a region. Returns number of bytes scheduled for erasure.
++ * Caller should poll for completion.
++ */
++int
++sflash_erase(chipcregs_t *cc, uint offset)
++{
++ struct sflash *sfl;
++
++ if (offset >= sflash.size)
++ return -22;
++
++ sfl = &sflash;
++ switch (sfl->type) {
++ case SFLASH_ST:
++ sflash_cmd(cc, SFLASH_ST_WREN);
++ W_REG(NULL, &cc->flashaddress, offset);
++ sflash_cmd(cc, SFLASH_ST_SE);
++ return sfl->blocksize;
++ case SFLASH_AT:
++ W_REG(NULL, &cc->flashaddress, offset << 1);
++ sflash_cmd(cc, SFLASH_AT_PAGE_ERASE);
++ return sfl->blocksize;
++ }
++
++ return 0;
++}
++
++/*
++ * writes the appropriate range of flash, a NULL buf simply erases
++ * the region of flash
++ */
++int
++sflash_commit(chipcregs_t *cc, uint offset, uint len, const uchar *buf)
++{
++ struct sflash *sfl;
++ uchar *block = NULL, *cur_ptr, *blk_ptr;
++ uint blocksize = 0, mask, cur_offset, cur_length, cur_retlen, remainder;
++ uint blk_offset, blk_len, copied;
++ int bytes, ret = 0;
++
++ /* Check address range */
++ if (len <= 0)
++ return 0;
++
++ sfl = &sflash;
++ if ((offset + len) > sfl->size)
++ return -1;
++
++ blocksize = sfl->blocksize;
++ mask = blocksize - 1;
++
++ /* Allocate a block of mem */
++ if (!(block = MALLOC(NULL, blocksize)))
++ return -1;
++
++ while (len) {
++ /* Align offset */
++ cur_offset = offset & ~mask;
++ cur_length = blocksize;
++ cur_ptr = block;
++
++ remainder = blocksize - (offset & mask);
++ if (len < remainder)
++ cur_retlen = len;
++ else
++ cur_retlen = remainder;
++
++ /* buf == NULL means erase only */
++ if (buf) {
++ /* Copy existing data into holding block if necessary */
++ if ((offset & mask) || (len < blocksize)) {
++ blk_offset = cur_offset;
++ blk_len = cur_length;
++ blk_ptr = cur_ptr;
++
++ /* Copy entire block */
++ while (blk_len) {
++ copied = sflash_read(cc, blk_offset, blk_len, blk_ptr);
++ blk_offset += copied;
++ blk_len -= copied;
++ blk_ptr += copied;
++ }
++ }
++
++ /* Copy input data into holding block */
++ memcpy(cur_ptr + (offset & mask), buf, cur_retlen);
++ }
++
++ /* Erase block */
++ if ((ret = sflash_erase(cc, (uint) cur_offset)) < 0)
++ goto done;
++ while (sflash_poll(cc, (uint) cur_offset));
++
++ /* buf == NULL means erase only */
++ if (!buf) {
++ offset += cur_retlen;
++ len -= cur_retlen;
++ continue;
++ }
++
++ /* Write holding block */
++ while (cur_length > 0) {
++ if ((bytes = sflash_write(cc,
++ (uint) cur_offset,
++ (uint) cur_length,
++ (uchar *) cur_ptr)) < 0) {
++ ret = bytes;
++ goto done;
++ }
++ while (sflash_poll(cc, (uint) cur_offset));
++ cur_offset += bytes;
++ cur_length -= bytes;
++ cur_ptr += bytes;
++ }
++
++ offset += cur_retlen;
++ len -= cur_retlen;
++ buf += cur_retlen;
++ }
++
++ ret = len;
++done:
++ if (block)
++ MFREE(NULL, block, blocksize);
++ return ret;
++}
+diff -urN linux.old/arch/mips/bcm947xx/time.c linux.dev/arch/mips/bcm947xx/time.c
+--- linux.old/arch/mips/bcm947xx/time.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/time.c 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,104 @@
++/*
++ * 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.
++ *
++ * $Id: time.c,v 1.1.1.10 2006/02/27 03:42:55 honor Exp $
++ */
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/serial_reg.h>
++#include <linux/interrupt.h>
++#include <asm/addrspace.h>
++#include <asm/io.h>
++#include <asm/time.h>
++
++#include <typedefs.h>
++#include <osl.h>
++#include <bcmnvram.h>
++#include <sbconfig.h>
++#include <sbextif.h>
++#include <sbutils.h>
++#include <hndmips.h>
++#include <mipsinc.h>
++#include <hndcpu.h>
++
++/* Global SB handle */
++extern void *bcm947xx_sbh;
++extern spinlock_t bcm947xx_sbh_lock;
++
++/* Convenience */
++#define sbh bcm947xx_sbh
++#define sbh_lock bcm947xx_sbh_lock
++
++extern int panic_timeout;
++static int watchdog = 0;
++static u8 *mcr = NULL;
++
++void __init
++bcm947xx_time_init(void)
++{
++ unsigned int hz;
++ extifregs_t *eir;
++
++ /*
++ * Use deterministic values for initial counter interrupt
++ * so that calibrate delay avoids encountering a counter wrap.
++ */
++ write_c0_count(0);
++ write_c0_compare(0xffff);
++
++ if (!(hz = sb_cpu_clock(sbh)))
++ hz = 100000000;
++
++ printk("CPU: BCM%04x rev %d at %d MHz\n", sb_chip(sbh), sb_chiprev(sbh),
++ (hz + 500000) / 1000000);
++
++ /* Set MIPS counter frequency for fixed_rate_gettimeoffset() */
++ mips_hpt_frequency = hz / 2;
++
++ /* Set watchdog interval in ms */
++ watchdog = simple_strtoul(nvram_safe_get("watchdog"), NULL, 0);
++
++ /* Please set the watchdog to 3 sec if it is less than 3 but not equal to 0 */
++ if (watchdog > 0) {
++ if (watchdog < 3000)
++ watchdog = 3000;
++ }
++
++ /* Set panic timeout in seconds */
++ panic_timeout = watchdog / 1000;
++}
++
++static void
++bcm947xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++ /* Generic MIPS timer code */
++ timer_interrupt(irq, dev_id, regs);
++
++ /* Set the watchdog timer to reset after the specified number of ms */
++ if (watchdog > 0)
++ sb_watchdog(sbh, WATCHDOG_CLOCK / 1000 * watchdog);
++}
++
++static struct irqaction bcm947xx_timer_irqaction = {
++ bcm947xx_timer_interrupt,
++ SA_INTERRUPT,
++ 0,
++ "timer",
++ NULL,
++ NULL
++};
++
++void __init
++bcm947xx_timer_setup(struct irqaction *irq)
++{
++ /* Enable the timer interrupt */
++ setup_irq(7, &bcm947xx_timer_irqaction);
++}
+diff -urN linux.old/arch/mips/config-shared.in linux.dev/arch/mips/config-shared.in
+--- linux.old/arch/mips/config-shared.in 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/arch/mips/config-shared.in 2006-10-02 21:19:59.000000000 +0200
+@@ -208,6 +208,14 @@
+ fi
+ define_bool CONFIG_MIPS_RTC y
+ fi
++dep_bool 'Support for Broadcom MIPS-based boards' CONFIG_MIPS_BRCM $CONFIG_EXPERIMENTAL
++dep_bool 'Support for Broadcom BCM947XX' CONFIG_BCM947XX $CONFIG_MIPS_BRCM
++if [ "$CONFIG_BCM947XX" = "y" ] ; then
++ bool ' Support for Broadcom BCM4710' CONFIG_BCM4710
++ bool ' Support for Broadcom BCM4310' CONFIG_BCM4310
++ bool ' Support for Broadcom BCM4704' CONFIG_BCM4704
++ bool ' Support for Broadcom BCM5365' CONFIG_BCM5365
++fi
+ bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI
+ bool 'Support for TANBAC TB0226 (Mbase)' CONFIG_TANBAC_TB0226
+ bool 'Support for TANBAC TB0229 (VR4131DIMM)' CONFIG_TANBAC_TB0229
+@@ -229,6 +237,11 @@
+ define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
+
+ #
++# Provide an option for a default kernel command line
++#
++string 'Default kernel command string' CONFIG_CMDLINE ""
++
++#
+ # Select some configuration options automatically based on user selections.
+ #
+ if [ "$CONFIG_ACER_PICA_61" = "y" ]; then
+@@ -554,6 +567,12 @@
+ define_bool CONFIG_SWAP_IO_SPACE_L y
+ define_bool CONFIG_BOOT_ELF32 y
+ fi
++if [ "$CONFIG_BCM947XX" = "y" ] ; then
++ define_bool CONFIG_PCI y
++ define_bool CONFIG_NONCOHERENT_IO y
++ define_bool CONFIG_NEW_TIME_C y
++ define_bool CONFIG_NEW_IRQ y
++fi
+ if [ "$CONFIG_SNI_RM200_PCI" = "y" ]; then
+ define_bool CONFIG_ARC32 y
+ define_bool CONFIG_ARC_MEMORY y
+@@ -1042,7 +1061,11 @@
+
+ bool 'Are you using a crosscompiler' CONFIG_CROSSCOMPILE
+ bool 'Enable run-time debugging' CONFIG_RUNTIME_DEBUG
+-bool 'Remote GDB kernel debugging' CONFIG_KGDB
++if [ "$CONFIG_BCM947XX" = "y" ] ; then
++ bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG
++else
++ bool 'Remote GDB kernel debugging' CONFIG_KGDB
++fi
+ dep_bool ' Console output to GDB' CONFIG_GDB_CONSOLE $CONFIG_KGDB
+ if [ "$CONFIG_KGDB" = "y" ]; then
+ define_bool CONFIG_DEBUG_INFO y
+diff -urN linux.old/arch/mips/kernel/cpu-probe.c linux.dev/arch/mips/kernel/cpu-probe.c
+--- linux.old/arch/mips/kernel/cpu-probe.c 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/arch/mips/kernel/cpu-probe.c 2006-10-02 21:19:59.000000000 +0200
+@@ -162,7 +162,7 @@
+
+ static inline void cpu_probe_legacy(struct cpuinfo_mips *c)
+ {
+- switch (c->processor_id & 0xff00) {
++ switch (c->processor_id & PRID_IMP_MASK) {
+ case PRID_IMP_R2000:
+ c->cputype = CPU_R2000;
+ c->isa_level = MIPS_CPU_ISA_I;
+@@ -172,7 +172,7 @@
+ c->tlbsize = 64;
+ break;
+ case PRID_IMP_R3000:
+- if ((c->processor_id & 0xff) == PRID_REV_R3000A)
++ if ((c->processor_id & PRID_REV_MASK) == PRID_REV_R3000A)
+ if (cpu_has_confreg())
+ c->cputype = CPU_R3081E;
+ else
+@@ -187,12 +187,12 @@
+ break;
+ case PRID_IMP_R4000:
+ if (read_c0_config() & CONF_SC) {
+- if ((c->processor_id & 0xff) >= PRID_REV_R4400)
++ if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_R4400)
+ c->cputype = CPU_R4400PC;
+ else
+ c->cputype = CPU_R4000PC;
+ } else {
+- if ((c->processor_id & 0xff) >= PRID_REV_R4400)
++ if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_R4400)
+ c->cputype = CPU_R4400SC;
+ else
+ c->cputype = CPU_R4000SC;
+@@ -438,7 +438,7 @@
+ static inline void cpu_probe_mips(struct cpuinfo_mips *c)
+ {
+ decode_config1(c);
+- switch (c->processor_id & 0xff00) {
++ switch (c->processor_id & PRID_IMP_MASK) {
+ case PRID_IMP_4KC:
+ c->cputype = CPU_4KC;
+ c->isa_level = MIPS_CPU_ISA_M32;
+@@ -479,10 +479,10 @@
+ {
+ decode_config1(c);
+ c->options |= MIPS_CPU_PREFETCH;
+- switch (c->processor_id & 0xff00) {
++ switch (c->processor_id & PRID_IMP_MASK) {
+ case PRID_IMP_AU1_REV1:
+ case PRID_IMP_AU1_REV2:
+- switch ((c->processor_id >> 24) & 0xff) {
++ switch ((c->processor_id >> 24) & PRID_REV_MASK) {
+ case 0:
+ c->cputype = CPU_AU1000;
+ break;
+@@ -510,10 +510,34 @@
+ }
+ }
+
++static inline void cpu_probe_broadcom(struct cpuinfo_mips *c)
++{
++ decode_config1(c);
++ c->options |= MIPS_CPU_PREFETCH;
++ switch (c->processor_id & PRID_IMP_MASK) {
++ case PRID_IMP_BCM4710:
++ c->cputype = CPU_BCM4710;
++ c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
++ MIPS_CPU_4KTLB | MIPS_CPU_COUNTER;
++ c->scache.flags = MIPS_CACHE_NOT_PRESENT;
++ break;
++ case PRID_IMP_4KC:
++ case PRID_IMP_BCM3302:
++ c->cputype = CPU_BCM3302;
++ c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
++ MIPS_CPU_4KTLB | MIPS_CPU_COUNTER;
++ c->scache.flags = MIPS_CACHE_NOT_PRESENT;
++ break;
++ default:
++ c->cputype = CPU_UNKNOWN;
++ break;
++ }
++}
++
+ static inline void cpu_probe_sibyte(struct cpuinfo_mips *c)
+ {
+ decode_config1(c);
+- switch (c->processor_id & 0xff00) {
++ switch (c->processor_id & PRID_IMP_MASK) {
+ case PRID_IMP_SB1:
+ c->cputype = CPU_SB1;
+ c->isa_level = MIPS_CPU_ISA_M64;
+@@ -535,7 +559,7 @@
+ static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c)
+ {
+ decode_config1(c);
+- switch (c->processor_id & 0xff00) {
++ switch (c->processor_id & PRID_IMP_MASK) {
+ case PRID_IMP_SR71000:
+ c->cputype = CPU_SR71000;
+ c->isa_level = MIPS_CPU_ISA_M64;
+@@ -560,7 +584,7 @@
+ c->cputype = CPU_UNKNOWN;
+
+ c->processor_id = read_c0_prid();
+- switch (c->processor_id & 0xff0000) {
++ switch (c->processor_id & PRID_COMP_MASK) {
+
+ case PRID_COMP_LEGACY:
+ cpu_probe_legacy(c);
+@@ -571,6 +595,9 @@
+ case PRID_COMP_ALCHEMY:
+ cpu_probe_alchemy(c);
+ break;
++ case PRID_COMP_BROADCOM:
++ cpu_probe_broadcom(c);
++ break;
+ case PRID_COMP_SIBYTE:
+ cpu_probe_sibyte(c);
+ break;
+diff -urN linux.old/arch/mips/kernel/head.S linux.dev/arch/mips/kernel/head.S
+--- linux.old/arch/mips/kernel/head.S 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/arch/mips/kernel/head.S 2006-10-02 21:19:59.000000000 +0200
+@@ -28,12 +28,20 @@
+ #include <asm/mipsregs.h>
+ #include <asm/stackframe.h>
+
++#ifdef CONFIG_BCM4710
++#undef eret
++#define eret nop; nop; eret
++#endif
++
+ .text
++ j kernel_entry
++ nop
++
+ /*
+ * Reserved space for exception handlers.
+ * Necessary for machines which link their kernels at KSEG0.
+ */
+- .fill 0x400
++ .fill 0x3f4
+
+ /* The following two symbols are used for kernel profiling. */
+ EXPORT(stext)
+diff -urN linux.old/arch/mips/kernel/proc.c linux.dev/arch/mips/kernel/proc.c
+--- linux.old/arch/mips/kernel/proc.c 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/arch/mips/kernel/proc.c 2006-10-02 21:19:59.000000000 +0200
+@@ -78,9 +78,10 @@
+ [CPU_AU1550] "Au1550",
+ [CPU_24K] "MIPS 24K",
+ [CPU_AU1200] "Au1200",
++ [CPU_BCM4710] "BCM4710",
++ [CPU_BCM3302] "BCM3302",
+ };
+
+-
+ static int show_cpuinfo(struct seq_file *m, void *v)
+ {
+ unsigned int version = current_cpu_data.processor_id;
+diff -urN linux.old/arch/mips/kernel/setup.c linux.dev/arch/mips/kernel/setup.c
+--- linux.old/arch/mips/kernel/setup.c 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/arch/mips/kernel/setup.c 2006-10-02 21:19:59.000000000 +0200
+@@ -493,6 +493,7 @@
+ void swarm_setup(void);
+ void hp_setup(void);
+ void au1x00_setup(void);
++ void brcm_setup(void);
+ void frame_info_init(void);
+
+ frame_info_init();
+@@ -691,6 +692,11 @@
+ pmc_yosemite_setup();
+ break;
+ #endif
++#if defined(CONFIG_BCM4710) || defined(CONFIG_BCM4310)
++ case MACH_GROUP_BRCM:
++ brcm_setup();
++ break;
++#endif
+ default:
+ panic("Unsupported architecture");
+ }
+diff -urN linux.old/arch/mips/kernel/traps.c linux.dev/arch/mips/kernel/traps.c
+--- linux.old/arch/mips/kernel/traps.c 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/arch/mips/kernel/traps.c 2006-10-02 21:19:59.000000000 +0200
+@@ -920,6 +920,7 @@
+ void __init trap_init(void)
+ {
+ extern char except_vec1_generic;
++ extern char except_vec2_generic;
+ extern char except_vec3_generic, except_vec3_r4000;
+ extern char except_vec_ejtag_debug;
+ extern char except_vec4;
+@@ -927,6 +928,7 @@
+
+ /* Copy the generic exception handler code to it's final destination. */
+ memcpy((void *)(KSEG0 + 0x80), &except_vec1_generic, 0x80);
++ memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80);
+
+ /*
+ * Setup default vectors
+@@ -985,6 +987,12 @@
+ set_except_vector(13, handle_tr);
+ set_except_vector(22, handle_mdmx);
+
++ if (current_cpu_data.cputype == CPU_SB1) {
++ /* Enable timer interrupt and scd mapped interrupt */
++ clear_c0_status(0xf000);
++ set_c0_status(0xc00);
++ }
++
+ if (cpu_has_fpu && !cpu_has_nofpuex)
+ set_except_vector(15, handle_fpe);
+
+diff -urN linux.old/arch/mips/Makefile linux.dev/arch/mips/Makefile
+--- linux.old/arch/mips/Makefile 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/arch/mips/Makefile 2006-10-02 21:19:59.000000000 +0200
+@@ -726,6 +726,19 @@
+ endif
+
+ #
++# Broadcom BCM947XX variants
++#
++ifdef CONFIG_BCM947XX
++LIBS += arch/mips/bcm947xx/generic/brcm.o arch/mips/bcm947xx/bcm947xx.o
++SUBDIRS += arch/mips/bcm947xx/generic arch/mips/bcm947xx
++LOADADDR := 0x80001000
++
++zImage: vmlinux
++ $(MAKE) -C arch/$(ARCH)/bcm947xx/compressed
++export LOADADDR
++endif
++
++#
+ # Choosing incompatible machines durings configuration will result in
+ # error messages during linking. Select a default linkscript if
+ # none has been choosen above.
+@@ -778,6 +791,7 @@
+ $(MAKE) -C arch/$(ARCH)/tools clean
+ $(MAKE) -C arch/mips/baget clean
+ $(MAKE) -C arch/mips/lasat clean
++ $(MAKE) -C arch/mips/bcm947xx/compressed clean
+
+ archmrproper:
+ @$(MAKEBOOT) mrproper
+diff -urN linux.old/arch/mips/mm/c-r4k.c linux.dev/arch/mips/mm/c-r4k.c
+--- linux.old/arch/mips/mm/c-r4k.c 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/arch/mips/mm/c-r4k.c 2006-10-02 21:19:59.000000000 +0200
+@@ -1166,3 +1166,47 @@
+ build_clear_page();
+ build_copy_page();
+ }
++
++#ifdef CONFIG_BCM4704
++static void __init mips32_icache_fill(unsigned long addr, uint nbytes)
++{
++ unsigned long ic_lsize = current_cpu_data.icache.linesz;
++ int i;
++ for (i = 0; i < nbytes; i += ic_lsize)
++ fill_icache_line((addr + i));
++}
++
++/*
++ * This must be run from the cache on 4704A0
++ * so there are no mips core BIU ops in progress
++ * when the PFC is enabled.
++ */
++#define PFC_CR0 0xff400000 /* control reg 0 */
++#define PFC_CR1 0xff400004 /* control reg 1 */
++static void __init enable_pfc(u32 mode)
++{
++ /* write range */
++ *(volatile u32 *)PFC_CR1 = 0xffff0000;
++
++ /* enable */
++ *(volatile u32 *)PFC_CR0 = mode;
++}
++#endif
++
++
++void check_enable_mips_pfc(int val)
++{
++
++#ifdef CONFIG_BCM4704
++ struct cpuinfo_mips *c = &current_cpu_data;
++
++ /* enable prefetch cache */
++ if (((c->processor_id & (PRID_COMP_MASK | PRID_IMP_MASK)) == PRID_IMP_BCM3302)
++ && (read_c0_diag() & (1 << 29))) {
++ mips32_icache_fill((unsigned long) &enable_pfc, 64);
++ enable_pfc(val);
++ }
++#endif
++}
++
++
+diff -urN linux.old/arch/mips/pci/Makefile linux.dev/arch/mips/pci/Makefile
+--- linux.old/arch/mips/pci/Makefile 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/arch/mips/pci/Makefile 2006-10-02 21:19:59.000000000 +0200
+@@ -13,7 +13,9 @@
+ obj-$(CONFIG_MIPS_MSC) += ops-msc.o
+ obj-$(CONFIG_MIPS_NILE4) += ops-nile4.o
+ obj-$(CONFIG_SNI_RM200_PCI) += ops-sni.o
++ifndef CONFIG_BCM947XX
+ obj-y += pci.o
++endif
+ obj-$(CONFIG_PCI_AUTO) += pci_auto.o
+
+ include $(TOPDIR)/Rules.make
+diff -urN linux.old/drivers/char/serial.c linux.dev/drivers/char/serial.c
+--- linux.old/drivers/char/serial.c 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/drivers/char/serial.c 2006-10-02 21:19:59.000000000 +0200
+@@ -444,6 +444,10 @@
+ return inb(info->port+1);
+ #endif
+ case SERIAL_IO_MEM:
++#ifdef CONFIG_BCM4310
++ readb((unsigned long) info->iomem_base +
++ (UART_SCR<<info->iomem_reg_shift));
++#endif
+ return readb((unsigned long) info->iomem_base +
+ (offset<<info->iomem_reg_shift));
+ default:
+@@ -464,6 +468,9 @@
+ case SERIAL_IO_MEM:
+ writeb(value, (unsigned long) info->iomem_base +
+ (offset<<info->iomem_reg_shift));
++#ifdef CONFIG_BCM4704
++ *((volatile unsigned int *) KSEG1ADDR(0x18000000));
++#endif
+ break;
+ default:
+ outb(value, info->port+offset);
+@@ -1728,7 +1735,7 @@
+ /* Special case since 134 is really 134.5 */
+ quot = (2*baud_base / 269);
+ else if (baud)
+- quot = baud_base / baud;
++ quot = (baud_base + (baud / 2)) / baud;
+ }
+ /* If the quotient is zero refuse the change */
+ if (!quot && old_termios) {
+@@ -1745,12 +1752,12 @@
+ /* Special case since 134 is really 134.5 */
+ quot = (2*baud_base / 269);
+ else if (baud)
+- quot = baud_base / baud;
++ quot = (baud_base + (baud / 2)) / baud;
+ }
+ }
+ /* As a last resort, if the quotient is zero, default to 9600 bps */
+ if (!quot)
+- quot = baud_base / 9600;
++ quot = (baud_base + 4800) / 9600;
+ /*
+ * Work around a bug in the Oxford Semiconductor 952 rev B
+ * chip which causes it to seriously miscalculate baud rates
+@@ -5994,6 +6001,13 @@
+ * Divisor, bytesize and parity
+ */
+ state = rs_table + co->index;
++ /*
++ * Safe guard: state structure must have been initialized
++ */
++ if (state->iomem_base == NULL) {
++ printk("!unable to setup serial console!\n");
++ return -1;
++ }
+ if (doflow)
+ state->flags |= ASYNC_CONS_FLOW;
+ info = &async_sercons;
+@@ -6007,7 +6021,7 @@
+ info->io_type = state->io_type;
+ info->iomem_base = state->iomem_base;
+ info->iomem_reg_shift = state->iomem_reg_shift;
+- quot = state->baud_base / baud;
++ quot = (state->baud_base + (baud / 2)) / baud;
+ cval = cflag & (CSIZE | CSTOPB);
+ #if defined(__powerpc__) || defined(__alpha__)
+ cval >>= 8;
+diff -urN linux.old/drivers/net/Makefile linux.dev/drivers/net/Makefile
+--- linux.old/drivers/net/Makefile 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/drivers/net/Makefile 2006-10-02 21:19:59.000000000 +0200
+@@ -3,6 +3,8 @@
+ # Makefile for the Linux network (ethercard) device drivers.
+ #
+
++EXTRA_CFLAGS := -I$(TOPDIR)/arch/mips/bcm947xx/include
++
+ obj-y :=
+ obj-m :=
+ obj-n :=
+diff -urN linux.old/drivers/parport/Config.in linux.dev/drivers/parport/Config.in
+--- linux.old/drivers/parport/Config.in 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/drivers/parport/Config.in 2006-10-02 21:19:59.000000000 +0200
+@@ -11,6 +11,7 @@
+ tristate 'Parallel port support' CONFIG_PARPORT
+ if [ "$CONFIG_PARPORT" != "n" ]; then
+ dep_tristate ' PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
++ dep_tristate ' Asus WL500g parallel port' CONFIG_PARPORT_SPLINK $CONFIG_PARPORT
+ if [ "$CONFIG_PARPORT_PC" != "n" -a "$CONFIG_SERIAL" != "n" ]; then
+ if [ "$CONFIG_SERIAL" = "m" ]; then
+ define_tristate CONFIG_PARPORT_PC_CML1 m
+diff -urN linux.old/drivers/parport/Makefile linux.dev/drivers/parport/Makefile
+--- linux.old/drivers/parport/Makefile 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/drivers/parport/Makefile 2006-10-02 21:19:59.000000000 +0200
+@@ -22,6 +22,7 @@
+
+ obj-$(CONFIG_PARPORT) += parport.o
+ obj-$(CONFIG_PARPORT_PC) += parport_pc.o
++obj-$(CONFIG_PARPORT_SPLINK) += parport_splink.o
+ obj-$(CONFIG_PARPORT_PC_PCMCIA) += parport_cs.o
+ obj-$(CONFIG_PARPORT_AMIGA) += parport_amiga.o
+ obj-$(CONFIG_PARPORT_MFC3) += parport_mfc3.o
+diff -urN linux.old/drivers/parport/parport_splink.c linux.dev/drivers/parport/parport_splink.c
+--- linux.old/drivers/parport/parport_splink.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/parport/parport_splink.c 2006-10-02 21:19:59.000000000 +0200
+@@ -0,0 +1,345 @@
++/* Low-level parallel port routines for the ASUS WL-500g built-in port
++ *
++ * Author: Nuno Grilo <nuno.grilo@netcabo.pt>
++ * Based on parport_pc source
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/parport.h>
++#include <linux/parport_pc.h>
++
++#define SPLINK_ADDRESS 0xBF800010
++
++#undef DEBUG
++
++#ifdef DEBUG
++#define DPRINTK printk
++#else
++#define DPRINTK(stuff...)
++#endif
++
++
++/* __parport_splink_frob_control differs from parport_splink_frob_control in that
++ * it doesn't do any extra masking. */
++static __inline__ unsigned char __parport_splink_frob_control (struct parport *p,
++ unsigned char mask,
++ unsigned char val)
++{
++ struct parport_pc_private *priv = p->physport->private_data;
++ unsigned char *io = (unsigned char *) p->base;
++ unsigned char ctr = priv->ctr;
++#ifdef DEBUG_PARPORT
++ printk (KERN_DEBUG
++ "__parport_splink_frob_control(%02x,%02x): %02x -> %02x\n",
++ mask, val, ctr, ((ctr & ~mask) ^ val) & priv->ctr_writable);
++#endif
++ ctr = (ctr & ~mask) ^ val;
++ ctr &= priv->ctr_writable; /* only write writable bits. */
++ *(io+2) = ctr;
++ priv->ctr = ctr; /* Update soft copy */
++ return ctr;
++}
++
++
++
++static void parport_splink_data_forward (struct parport *p)
++{
++ DPRINTK(KERN_DEBUG "parport_splink: parport_data_forward called\n");
++ __parport_splink_frob_control (p, 0x20, 0);
++}
++
++static void parport_splink_data_reverse (struct parport *p)
++{
++ DPRINTK(KERN_DEBUG "parport_splink: parport_data_forward called\n");
++ __parport_splink_frob_control (p, 0x20, 0x20);
++}
++
++/*
++static void parport_splink_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++ DPRINTK(KERN_DEBUG "parport_splink: IRQ handler called\n");
++ parport_generic_irq(irq, (struct parport *) dev_id, regs);
++}
++*/
++
++static void parport_splink_enable_irq(struct parport *p)
++{
++ DPRINTK(KERN_DEBUG "parport_splink: parport_splink_enable_irq called\n");
++ __parport_splink_frob_control (p, 0x10, 0x10);
++}
++
++static void parport_splink_disable_irq(struct parport *p)
++{
++ DPRINTK(KERN_DEBUG "parport_splink: parport_splink_disable_irq called\n");
++ __parport_splink_frob_control (p, 0x10, 0);
++}
++
++static void parport_splink_init_state(struct pardevice *dev, struct parport_state *s)
++{
++ DPRINTK(KERN_DEBUG "parport_splink: parport_splink_init_state called\n");
++ s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0);
++ if (dev->irq_func &&
++ dev->port->irq != PARPORT_IRQ_NONE)
++ /* Set ackIntEn */
++ s->u.pc.ctr |= 0x10;
++}
++
++static void parport_splink_save_state(struct parport *p, struct parport_state *s)
++{
++ const struct parport_pc_private *priv = p->physport->private_data;
++ DPRINTK(KERN_DEBUG "parport_splink: parport_splink_save_state called\n");
++ s->u.pc.ctr = priv->ctr;
++}
++
++static void parport_splink_restore_state(struct parport *p, struct parport_state *s)
++{
++ struct parport_pc_private *priv = p->physport->private_data;
++ unsigned char *io = (unsigned char *) p->base;
++ unsigned char ctr = s->u.pc.ctr;
++
++ DPRINTK(KERN_DEBUG "parport_splink: parport_splink_restore_state called\n");
++ *(io+2) = ctr;
++ priv->ctr = ctr;
++}
++
++static void parport_splink_setup_interrupt(void) {
++ return;
++}
++
++static void parport_splink_write_data(struct parport *p, unsigned char d) {
++ DPRINTK(KERN_DEBUG "parport_splink: write data called\n");
++ unsigned char *io = (unsigned char *) p->base;
++ *io = d;
++}
++
++static unsigned char parport_splink_read_data(struct parport *p) {
++ DPRINTK(KERN_DEBUG "parport_splink: read data called\n");
++ unsigned char *io = (unsigned char *) p->base;
++ return *io;
++}
++
++static void parport_splink_write_control(struct parport *p, unsigned char d)
++{
++ const unsigned char wm = (PARPORT_CONTROL_STROBE |
++ PARPORT_CONTROL_AUTOFD |
++ PARPORT_CONTROL_INIT |
++ PARPORT_CONTROL_SELECT);
++
++ DPRINTK(KERN_DEBUG "parport_splink: write control called\n");
++ /* Take this out when drivers have adapted to the newer interface. */
++ if (d & 0x20) {
++ printk (KERN_DEBUG "%s (%s): use data_reverse for this!\n",
++ p->name, p->cad->name);
++ parport_splink_data_reverse (p);
++ }
++
++ __parport_splink_frob_control (p, wm, d & wm);
++}
++
++static unsigned char parport_splink_read_control(struct parport *p)
++{
++ const unsigned char wm = (PARPORT_CONTROL_STROBE |
++ PARPORT_CONTROL_AUTOFD |
++ PARPORT_CONTROL_INIT |
++ PARPORT_CONTROL_SELECT);
++ DPRINTK(KERN_DEBUG "parport_splink: read control called\n");
++ const struct parport_pc_private *priv = p->physport->private_data;
++ return priv->ctr & wm; /* Use soft copy */
++}
++
++static unsigned char parport_splink_frob_control (struct parport *p, unsigned char mask,
++ unsigned char val)
++{
++ const unsigned char wm = (PARPORT_CONTROL_STROBE |
++ PARPORT_CONTROL_AUTOFD |
++ PARPORT_CONTROL_INIT |
++ PARPORT_CONTROL_SELECT);
++
++ DPRINTK(KERN_DEBUG "parport_splink: frob control called\n");
++ /* Take this out when drivers have adapted to the newer interface. */
++ if (mask & 0x20) {
++ printk (KERN_DEBUG "%s (%s): use data_%s for this!\n",
++ p->name, p->cad->name,
++ (val & 0x20) ? "reverse" : "forward");
++ if (val & 0x20)
++ parport_splink_data_reverse (p);
++ else
++ parport_splink_data_forward (p);
++ }
++
++ /* Restrict mask and val to control lines. */
++ mask &= wm;
++ val &= wm;
++
++ return __parport_splink_frob_control (p, mask, val);
++}
++
++static unsigned char parport_splink_read_status(struct parport *p)
++{
++ DPRINTK(KERN_DEBUG "parport_splink: read status called\n");
++ unsigned char *io = (unsigned char *) p->base;
++ return *(io+1);
++}
++
++static void parport_splink_inc_use_count(void)
++{
++#ifdef MODULE
++ MOD_INC_USE_COUNT;
++#endif
++}
++
++static void parport_splink_dec_use_count(void)
++{
++#ifdef MODULE
++ MOD_DEC_USE_COUNT;
++#endif
++}
++
++static struct parport_operations parport_splink_ops =
++{
++ parport_splink_write_data,
++ parport_splink_read_data,
++
++ parport_splink_write_control,
++ parport_splink_read_control,
++ parport_splink_frob_control,
++
++ parport_splink_read_status,
++
++ parport_splink_enable_irq,
++ parport_splink_disable_irq,
++
++ parport_splink_data_forward,
++ parport_splink_data_reverse,
++
++ parport_splink_init_state,
++ parport_splink_save_state,
++ parport_splink_restore_state,
++
++ parport_splink_inc_use_count,
++ parport_splink_dec_use_count,
++
++ parport_ieee1284_epp_write_data,
++ parport_ieee1284_epp_read_data,
++ parport_ieee1284_epp_write_addr,
++ parport_ieee1284_epp_read_addr,
++
++ parport_ieee1284_ecp_write_data,
++ parport_ieee1284_ecp_read_data,
++ parport_ieee1284_ecp_write_addr,
++
++ parport_ieee1284_write_compat,
++ parport_ieee1284_read_nibble,
++ parport_ieee1284_read_byte,
++};
++
++/* --- Initialisation code -------------------------------- */
++
++static struct parport *parport_splink_probe_port (unsigned long int base)
++{
++ struct parport_pc_private *priv;
++ struct parport_operations *ops;
++ struct parport *p;
++
++ if (check_mem_region(base, 3)) {
++ printk (KERN_DEBUG "parport (0x%lx): iomem region not available\n", base);
++ return NULL;
++ }
++ priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL);
++ if (!priv) {
++ printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base);
++ return NULL;
++ }
++ ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
++ if (!ops) {
++ printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n",
++ base);
++ kfree (priv);
++ return NULL;
++ }
++ memcpy (ops, &parport_splink_ops, sizeof (struct parport_operations));
++ priv->ctr = 0xc;
++ priv->ctr_writable = 0xff;
++
++ if (!(p = parport_register_port(base, PARPORT_IRQ_NONE,
++ PARPORT_DMA_NONE, ops))) {
++ printk (KERN_DEBUG "parport (0x%lx): registration failed!\n",
++ base);
++ kfree (priv);
++ kfree (ops);
++ return NULL;
++ }
++
++ p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT;
++ p->size = (p->modes & PARPORT_MODE_EPP)?8:3;
++ p->private_data = priv;
++
++ parport_proc_register(p);
++ request_mem_region (p->base, 3, p->name);
++
++ /* Done probing. Now put the port into a sensible start-up state. */
++ parport_splink_write_data(p, 0);
++ parport_splink_data_forward (p);
++
++ /* Now that we've told the sharing engine about the port, and
++ found out its characteristics, let the high-level drivers
++ know about it. */
++ parport_announce_port (p);
++
++ DPRINTK(KERN_DEBUG "parport (0x%lx): init ok!\n",
++ base);
++ return p;
++}
++
++static void parport_splink_unregister_port(struct parport *p) {
++ struct parport_pc_private *priv = p->private_data;
++ struct parport_operations *ops = p->ops;
++
++ if (p->irq != PARPORT_IRQ_NONE)
++ free_irq(p->irq, p);
++ release_mem_region(p->base, 3);
++ parport_proc_unregister(p);
++ kfree (priv);
++ parport_unregister_port(p);
++ kfree (ops);
++}
++
++
++int parport_splink_init(void)
++{
++ int ret;
++
++ DPRINTK(KERN_DEBUG "parport_splink init called\n");
++ parport_splink_setup_interrupt();
++ ret = !parport_splink_probe_port(SPLINK_ADDRESS);
++
++ return ret;
++}
++
++void parport_splink_cleanup(void) {
++ struct parport *p = parport_enumerate(), *tmp;
++ DPRINTK(KERN_DEBUG "parport_splink cleanup called\n");
++ if (p->size) {
++ if (p->modes & PARPORT_MODE_PCSPP) {
++ while(p) {
++ tmp = p->next;
++ parport_splink_unregister_port(p);
++ p = tmp;
++ }
++ }
++ }
++}
++
++MODULE_AUTHOR("Nuno Grilo <nuno.grilo@netcabo.pt>");
++MODULE_DESCRIPTION("Parport Driver for ASUS WL-500g router builtin Port");
++MODULE_SUPPORTED_DEVICE("ASUS WL-500g builtin Parallel Port");
++MODULE_LICENSE("GPL");
++
++module_init(parport_splink_init)
++module_exit(parport_splink_cleanup)
++
+diff -urN linux.old/include/asm-mips/bootinfo.h linux.dev/include/asm-mips/bootinfo.h
+--- linux.old/include/asm-mips/bootinfo.h 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/include/asm-mips/bootinfo.h 2006-10-02 21:19:59.000000000 +0200
+@@ -37,6 +37,7 @@
+ #define MACH_GROUP_HP_LJ 20 /* Hewlett Packard LaserJet */
+ #define MACH_GROUP_LASAT 21
+ #define MACH_GROUP_TITAN 22 /* PMC-Sierra Titan */
++#define MACH_GROUP_BRCM 23 /* Broadcom */
+
+ /*
+ * Valid machtype values for group unknown (low order halfword of mips_machtype)
+@@ -197,6 +198,15 @@
+ #define MACH_TANBAC_TB0229 7 /* TANBAC TB0229 (VR4131DIMM) */
+
+ /*
++ * Valid machtypes for group Broadcom
++ */
++#define MACH_BCM93725 0
++#define MACH_BCM93725_VJ 1
++#define MACH_BCM93730 2
++#define MACH_BCM947XX 3
++#define MACH_BCM933XX 4
++
++/*
+ * Valid machtype for group TITAN
+ */
+ #define MACH_TITAN_YOSEMITE 1 /* PMC-Sierra Yosemite */
+diff -urN linux.old/include/asm-mips/cpu.h linux.dev/include/asm-mips/cpu.h
+--- linux.old/include/asm-mips/cpu.h 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/include/asm-mips/cpu.h 2006-10-02 21:19:59.000000000 +0200
+@@ -22,6 +22,11 @@
+ spec.
+ */
+
++#define PRID_COPT_MASK 0xff000000
++#define PRID_COMP_MASK 0x00ff0000
++#define PRID_IMP_MASK 0x0000ff00
++#define PRID_REV_MASK 0x000000ff
++
+ #define PRID_COMP_LEGACY 0x000000
+ #define PRID_COMP_MIPS 0x010000
+ #define PRID_COMP_BROADCOM 0x020000
+@@ -58,6 +63,7 @@
+ #define PRID_IMP_RM7000 0x2700
+ #define PRID_IMP_NEVADA 0x2800 /* RM5260 ??? */
+ #define PRID_IMP_RM9000 0x3400
++#define PRID_IMP_BCM4710 0x4000
+ #define PRID_IMP_R5432 0x5400
+ #define PRID_IMP_R5500 0x5500
+ #define PRID_IMP_4KC 0x8000
+@@ -66,10 +72,16 @@
+ #define PRID_IMP_4KEC 0x8400
+ #define PRID_IMP_4KSC 0x8600
+ #define PRID_IMP_25KF 0x8800
++#define PRID_IMP_BCM3302 0x9000
++#define PRID_IMP_BCM3303 0x9100
+ #define PRID_IMP_24K 0x9300
+
+ #define PRID_IMP_UNKNOWN 0xff00
+
++#define BCM330X(id) \
++ (((id & (PRID_COMP_MASK | PRID_IMP_MASK)) == (PRID_COMP_BROADCOM | PRID_IMP_BCM3302)) \
++ || ((id & (PRID_COMP_MASK | PRID_IMP_MASK)) == (PRID_COMP_BROADCOM | PRID_IMP_BCM3303)))
++
+ /*
+ * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
+ */
+@@ -174,7 +186,9 @@
+ #define CPU_AU1550 57
+ #define CPU_24K 58
+ #define CPU_AU1200 59
+-#define CPU_LAST 59
++#define CPU_BCM4710 60
++#define CPU_BCM3302 61
++#define CPU_LAST 61
+
+ /*
+ * ISA Level encodings
+diff -urN linux.old/include/asm-mips/r4kcache.h linux.dev/include/asm-mips/r4kcache.h
+--- linux.old/include/asm-mips/r4kcache.h 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/include/asm-mips/r4kcache.h 2006-10-02 21:19:59.000000000 +0200
+@@ -658,4 +658,17 @@
+ cache128_unroll32(addr|ws,Index_Writeback_Inv_SD);
+ }
+
++extern inline void fill_icache_line(unsigned long addr)
++{
++ __asm__ __volatile__(
++ ".set noreorder\n\t"
++ ".set mips3\n\t"
++ "cache %1, (%0)\n\t"
++ ".set mips0\n\t"
++ ".set reorder"
++ :
++ : "r" (addr),
++ "i" (Fill));
++}
++
+ #endif /* __ASM_R4KCACHE_H */
+diff -urN linux.old/include/asm-mips/serial.h linux.dev/include/asm-mips/serial.h
+--- linux.old/include/asm-mips/serial.h 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/include/asm-mips/serial.h 2006-10-02 21:19:59.000000000 +0200
+@@ -223,6 +223,13 @@
+ #define TXX927_SERIAL_PORT_DEFNS
+ #endif
+
++#ifdef CONFIG_BCM947XX
++/* reserve 4 ports to be configured at runtime */
++#define BCM947XX_SERIAL_PORT_DEFNS { 0, }, { 0, }, { 0, }, { 0, },
++#else
++#define BCM947XX_SERIAL_PORT_DEFNS
++#endif
++
+ #ifdef CONFIG_HAVE_STD_PC_SERIAL_PORT
+ #define STD_SERIAL_PORT_DEFNS \
+ /* UART CLK PORT IRQ FLAGS */ \
+@@ -470,6 +477,7 @@
+ #define SERIAL_PORT_DFNS \
+ ATLAS_SERIAL_PORT_DEFNS \
+ AU1000_SERIAL_PORT_DEFNS \
++ BCM947XX_SERIAL_PORT_DEFNS \
+ COBALT_SERIAL_PORT_DEFNS \
+ DDB5477_SERIAL_PORT_DEFNS \
+ EV96100_SERIAL_PORT_DEFNS \
+diff -urN linux.old/init/do_mounts.c linux.dev/init/do_mounts.c
+--- linux.old/init/do_mounts.c 2006-10-02 21:23:10.000000000 +0200
++++ linux.dev/init/do_mounts.c 2006-10-02 21:19:59.000000000 +0200
+@@ -254,7 +254,13 @@
+ { "ftlb", 0x2c08 },
+ { "ftlc", 0x2c10 },
+ { "ftld", 0x2c18 },
++#if defined(CONFIG_MTD_BLOCK) || defined(CONFIG_MTD_BLOCK_RO)
+ { "mtdblock", 0x1f00 },
++ { "mtdblock0",0x1f00 },
++ { "mtdblock1",0x1f01 },
++ { "mtdblock2",0x1f02 },
++ { "mtdblock3",0x1f03 },
++#endif
+ { "nb", 0x2b00 },
+ { NULL, 0 }
+ };
diff --git a/target/linux/brcm-2.4/patches/002-wl_fix.patch b/target/linux/brcm-2.4/patches/002-wl_fix.patch
new file mode 100644
index 0000000000..95044b6d60
--- /dev/null
+++ b/target/linux/brcm-2.4/patches/002-wl_fix.patch
@@ -0,0 +1,348 @@
+diff -urN linux.old/include/linux/netdevice.h linux.dev/include/linux/netdevice.h
+--- linux.old/include/linux/netdevice.h 2006-03-19 06:32:22.000000000 +0100
++++ linux.dev/include/linux/netdevice.h 2006-03-19 06:33:21.000000000 +0100
+@@ -296,10 +296,7 @@
+ /* List of functions to handle Wireless Extensions (instead of ioctl).
+ * See <net/iw_handler.h> for details. Jean II */
+ const struct iw_handler_def * wireless_handlers;
+- /* Instance data managed by the core of Wireless Extensions. */
+- struct iw_public_data * wireless_data;
+
+- struct ethtool_ops *ethtool_ops;
+
+ /*
+ * This marks the end of the "visible" part of the structure. All
+@@ -354,8 +351,8 @@
+
+ struct Qdisc *qdisc;
+ struct Qdisc *qdisc_sleeping;
++ struct Qdisc *qdisc_list;
+ struct Qdisc *qdisc_ingress;
+- struct list_head qdisc_list;
+ unsigned long tx_queue_len; /* Max frames per queue allowed */
+
+ /* hard_start_xmit synchronizer */
+@@ -455,6 +452,10 @@
+ /* this will get initialized at each interface type init routine */
+ struct divert_blk *divert;
+ #endif /* CONFIG_NET_DIVERT */
++ struct ethtool_ops *ethtool_ops;
++
++ /* Instance data managed by the core of Wireless Extensions. */
++ struct iw_public_data * wireless_data;
+ };
+
+ /* 2.6 compatibility */
+diff -urN linux.old/include/linux/skbuff.h linux.dev/include/linux/skbuff.h
+--- linux.old/include/linux/skbuff.h 2006-03-19 06:32:22.000000000 +0100
++++ linux.dev/include/linux/skbuff.h 2006-03-19 06:29:41.000000000 +0100
+@@ -138,10 +138,6 @@
+ struct sock *sk; /* Socket we are owned by */
+ struct timeval stamp; /* Time we arrived */
+ struct net_device *dev; /* Device we arrived on/are leaving by */
+- struct net_device *real_dev; /* For support of point to point protocols
+- (e.g. 802.3ad) over bonding, we must save the
+- physical device that got the packet before
+- replacing skb->dev with the virtual device. */
+
+ /* Transport layer header */
+ union
+@@ -225,6 +221,10 @@
+ #if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+ struct nf_info *nf_info;
+ #endif
++ struct net_device *real_dev; /* For support of point to point protocols
++ (e.g. 802.3ad) over bonding, we must save the
++ physical device that got the packet before
++ replacing skb->dev with the virtual device. */
+ };
+
+ #ifdef __KERNEL__
+diff -urN linux.old/include/net/pkt_sched.h linux.dev/include/net/pkt_sched.h
+--- linux.old/include/net/pkt_sched.h 2006-03-19 06:32:22.000000000 +0100
++++ linux.dev/include/net/pkt_sched.h 2006-03-19 06:29:41.000000000 +0100
+@@ -63,8 +63,11 @@
+ int (*enqueue)(struct sk_buff *, struct Qdisc *);
+ struct sk_buff * (*dequeue)(struct Qdisc *);
+ int (*requeue)(struct sk_buff *, struct Qdisc *);
+- unsigned int (*drop)(struct Qdisc *);
+-
++#ifdef CONFIG_BCM4710
++ int (*drop)(struct Qdisc *);
++#else
++ unsigned int (*drop)(struct Qdisc *);
++#endif
+ int (*init)(struct Qdisc *, struct rtattr *arg);
+ void (*reset)(struct Qdisc *);
+ void (*destroy)(struct Qdisc *);
+@@ -84,12 +87,19 @@
+ #define TCQ_F_THROTTLED 2
+ #define TCQ_F_INGRESS 4
+ struct Qdisc_ops *ops;
++#ifdef CONFIG_BCM4710
++ struct Qdisc *next;
++#endif
+ u32 handle;
+- u32 parent;
++#ifndef CONFIG_BCM4710
++ u32 parent;
++#endif
+ atomic_t refcnt;
+ struct sk_buff_head q;
+ struct net_device *dev;
+- struct list_head list;
++#ifndef CONFIG_BCM4710
++ struct list_head list;
++#endif
+
+ struct tc_stats stats;
+ int (*reshape_fail)(struct sk_buff *skb, struct Qdisc *q);
+diff -urN linux.old/net/core/Makefile linux.dev/net/core/Makefile
+--- linux.old/net/core/Makefile 2006-03-19 06:32:22.000000000 +0100
++++ linux.dev/net/core/Makefile 2006-03-19 06:29:41.000000000 +0100
+@@ -9,7 +9,11 @@
+
+ O_TARGET := core.o
+
++ifeq ($(CONFIG_BCM4710),y)
++export-objs := netfilter.o profile.o neighbour.o
++else
+ export-objs := netfilter.o profile.o ethtool.o neighbour.o
++endif
+
+ obj-y := sock.o skbuff.o iovec.o datagram.o scm.o
+
+@@ -21,8 +25,13 @@
+
+ obj-$(CONFIG_FILTER) += filter.o
+
++ifeq ($(CONFIG_BCM4710),y)
++obj-$(CONFIG_NET) += dev.o dev_mcast.o dst.o neighbour.o \
++ rtnetlink.o utils.o
++else
+ obj-$(CONFIG_NET) += dev.o ethtool.o dev_mcast.o dst.o neighbour.o \
+ rtnetlink.o utils.o
++endif
+
+ obj-$(CONFIG_NETFILTER) += netfilter.o
+ obj-$(CONFIG_NET_DIVERT) += dv.o
+diff -urN linux.old/net/core/dev.c linux.dev/net/core/dev.c
+--- linux.old/net/core/dev.c 2006-03-19 06:32:22.000000000 +0100
++++ linux.dev/net/core/dev.c 2006-03-19 06:29:41.000000000 +0100
+@@ -2232,6 +2232,7 @@
+ cmd == SIOCGMIIPHY ||
+ cmd == SIOCGMIIREG ||
+ cmd == SIOCSMIIREG ||
++ cmd == SIOCETHTOOL ||
+ cmd == SIOCWANDEV) {
+ if (dev->do_ioctl) {
+ if (!netif_device_present(dev))
+@@ -2324,6 +2325,7 @@
+ }
+ return ret;
+
++#ifndef CONFIG_BCM4710
+ case SIOCETHTOOL:
+ dev_load(ifr.ifr_name);
+ rtnl_lock();
+@@ -2337,6 +2339,7 @@
+ ret = -EFAULT;
+ }
+ return ret;
++#endif
+
+ /*
+ * These ioctl calls:
+@@ -2412,6 +2415,7 @@
+
+ default:
+ if (cmd == SIOCWANDEV ||
++ (cmd == SIOCETHTOOL) ||
+ (cmd >= SIOCDEVPRIVATE &&
+ cmd <= SIOCDEVPRIVATE + 15)) {
+ dev_load(ifr.ifr_name);
+diff -urN linux.old/net/sched/sch_api.c linux.dev/net/sched/sch_api.c
+--- linux.old/net/sched/sch_api.c 2006-03-19 06:32:22.000000000 +0100
++++ linux.dev/net/sched/sch_api.c 2006-03-19 06:29:41.000000000 +0100
+@@ -194,11 +194,12 @@
+ {
+ struct Qdisc *q;
+
+- list_for_each_entry(q, &dev->qdisc_list, list) {
++ for (q = dev->qdisc_list; q; q = q->next) {
+ if (q->handle == handle)
+ return q;
+ }
+ return NULL;
++
+ }
+
+ struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid)
+@@ -371,8 +372,6 @@
+ unsigned long cl = cops->get(parent, classid);
+ if (cl) {
+ err = cops->graft(parent, cl, new, old);
+- if (new)
+- new->parent = classid;
+ cops->put(parent, cl);
+ }
+ }
+@@ -427,7 +426,6 @@
+
+ memset(sch, 0, size);
+
+- INIT_LIST_HEAD(&sch->list);
+ skb_queue_head_init(&sch->q);
+
+ if (handle == TC_H_INGRESS)
+@@ -453,7 +451,8 @@
+
+ if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
+ write_lock(&qdisc_tree_lock);
+- list_add_tail(&sch->list, &dev->qdisc_list);
++ sch->next = dev->qdisc_list;
++ dev->qdisc_list = sch;
+ write_unlock(&qdisc_tree_lock);
+ #ifdef CONFIG_NET_ESTIMATOR
+ if (tca[TCA_RATE-1])
+@@ -808,19 +807,16 @@
+ if (idx > s_idx)
+ s_q_idx = 0;
+ read_lock(&qdisc_tree_lock);
+- q_idx = 0;
+- list_for_each_entry(q, &dev->qdisc_list, list) {
+- if (q_idx < s_q_idx) {
+- q_idx++;
+- continue;
+- }
+- if (tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid,
+- cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) {
+- read_unlock(&qdisc_tree_lock);
+- goto done;
+- }
+- q_idx++;
+- }
++ for (q = dev->qdisc_list, q_idx = 0; q;
++ q = q->next, q_idx++) {
++ if (q_idx < s_q_idx)
++ continue;
++ if (tc_fill_qdisc(skb, q, 0, NETLINK_CB(cb->skb).pid,
++ cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) {
++ read_unlock(&qdisc_tree_lock);
++ goto done;
++ }
++ }
+ read_unlock(&qdisc_tree_lock);
+ }
+
+@@ -1033,27 +1029,24 @@
+ t = 0;
+
+ read_lock(&qdisc_tree_lock);
+- list_for_each_entry(q, &dev->qdisc_list, list) {
+- if (t < s_t || !q->ops->cl_ops ||
+- (tcm->tcm_parent &&
+- TC_H_MAJ(tcm->tcm_parent) != q->handle)) {
+- t++;
+- continue;
+- }
+- if (t > s_t)
+- memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0]));
+- arg.w.fn = qdisc_class_dump;
+- arg.skb = skb;
+- arg.cb = cb;
+- arg.w.stop = 0;
+- arg.w.skip = cb->args[1];
+- arg.w.count = 0;
+- q->ops->cl_ops->walk(q, &arg.w);
+- cb->args[1] = arg.w.count;
+- if (arg.w.stop)
+- break;
+- t++;
+- }
++ for (q=dev->qdisc_list, t=0; q; q = q->next, t++) {
++ if (t < s_t) continue;
++ if (!q->ops->cl_ops) continue;
++ if (tcm->tcm_parent && TC_H_MAJ(tcm->tcm_parent) != q->handle)
++ continue;
++ if (t > s_t)
++ memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0]));
++ arg.w.fn = qdisc_class_dump;
++ arg.skb = skb;
++ arg.cb = cb;
++ arg.w.stop = 0;
++ arg.w.skip = cb->args[1];
++ arg.w.count = 0;
++ q->ops->cl_ops->walk(q, &arg.w);
++ cb->args[1] = arg.w.count;
++ if (arg.w.stop)
++ break;
++ }
+ read_unlock(&qdisc_tree_lock);
+
+ cb->args[0] = t;
+diff -urN linux.old/net/sched/sch_generic.c linux.dev/net/sched/sch_generic.c
+--- linux.old/net/sched/sch_generic.c 2006-03-19 06:32:22.000000000 +0100
++++ linux.dev/net/sched/sch_generic.c 2006-03-19 06:29:41.000000000 +0100
+@@ -399,7 +399,6 @@
+ return NULL;
+ memset(sch, 0, size);
+
+- INIT_LIST_HEAD(&sch->list);
+ skb_queue_head_init(&sch->q);
+ sch->ops = ops;
+ sch->enqueue = ops->enqueue;
+@@ -429,11 +428,22 @@
+ void qdisc_destroy(struct Qdisc *qdisc)
+ {
+ struct Qdisc_ops *ops = qdisc->ops;
++ struct net_device *dev;
+
+ if (qdisc->flags&TCQ_F_BUILTIN ||
+ !atomic_dec_and_test(&qdisc->refcnt))
+ return;
+- list_del(&qdisc->list);
++
++ dev = qdisc->dev;
++ if (dev) {
++ struct Qdisc *q, **qp;
++ for (qp = &qdisc->dev->qdisc_list; (q=*qp) != NULL; qp = &q->next) {
++ if (q == qdisc) {
++ *qp = q->next;
++ break;
++ }
++ }
++ }
+ #ifdef CONFIG_NET_ESTIMATOR
+ qdisc_kill_estimator(&qdisc->stats);
+ #endif
+@@ -462,9 +472,9 @@
+ return;
+ }
+ write_lock(&qdisc_tree_lock);
+- list_add_tail(&qdisc->list, &dev->qdisc_list);
++ qdisc->next = dev->qdisc_list;
++ dev->qdisc_list = qdisc;
+ write_unlock(&qdisc_tree_lock);
+-
+ } else {
+ qdisc = &noqueue_qdisc;
+ }
+@@ -508,7 +518,7 @@
+ dev->qdisc = &noop_qdisc;
+ spin_unlock_bh(&dev->queue_lock);
+ dev->qdisc_sleeping = &noop_qdisc;
+- INIT_LIST_HEAD(&dev->qdisc_list);
++ dev->qdisc_list = NULL;
+ write_unlock(&qdisc_tree_lock);
+
+ dev_watchdog_init(dev);
+@@ -530,7 +540,7 @@
+ qdisc_destroy(qdisc);
+ }
+ #endif
+- BUG_TRAP(list_empty(&dev->qdisc_list));
++ BUG_TRAP(dev->qdisc_list == NULL);
+ BUG_TRAP(!timer_pending(&dev->watchdog_timer));
+ spin_unlock_bh(&dev->queue_lock);
+ write_unlock(&qdisc_tree_lock);
diff --git a/target/linux/brcm-2.4/patches/003-bcm47xx_cache_fixes.patch b/target/linux/brcm-2.4/patches/003-bcm47xx_cache_fixes.patch
new file mode 100644
index 0000000000..e971e7fdfd
--- /dev/null
+++ b/target/linux/brcm-2.4/patches/003-bcm47xx_cache_fixes.patch
@@ -0,0 +1,498 @@
+diff -urN linux.old/arch/mips/kernel/entry.S linux.dev/arch/mips/kernel/entry.S
+--- linux.old/arch/mips/kernel/entry.S 2005-07-05 16:46:49.000000000 +0200
++++ linux.dev/arch/mips/kernel/entry.S 2005-07-06 11:23:55.000000000 +0200
+@@ -100,6 +100,10 @@
+ * and R4400 SC and MC versions.
+ */
+ NESTED(except_vec3_generic, 0, sp)
++#ifdef CONFIG_BCM4710
++ nop
++ nop
++#endif
+ #if R5432_CP0_INTERRUPT_WAR
+ mfc0 k0, CP0_INDEX
+ #endif
+diff -urN linux.old/arch/mips/mm/c-r4k.c linux.dev/arch/mips/mm/c-r4k.c
+--- linux.old/arch/mips/mm/c-r4k.c 2005-07-05 16:46:49.000000000 +0200
++++ linux.dev/arch/mips/mm/c-r4k.c 2005-07-06 11:23:55.000000000 +0200
+@@ -14,6 +14,12 @@
+ #include <linux/mm.h>
+ #include <linux/bitops.h>
+
++#ifdef CONFIG_BCM4710
++#include "../bcm947xx/include/typedefs.h"
++#include "../bcm947xx/include/sbconfig.h"
++#include <asm/paccess.h>
++#endif
++
+ #include <asm/bcache.h>
+ #include <asm/bootinfo.h>
+ #include <asm/cacheops.h>
+@@ -40,6 +46,8 @@
+ .bc_inv = (void *)no_sc_noop
+ };
+
++int bcm4710 = 0;
++EXPORT_SYMBOL(bcm4710);
+ struct bcache_ops *bcops = &no_sc_ops;
+
+ #define cpu_is_r4600_v1_x() ((read_c0_prid() & 0xfffffff0) == 0x2010)
+@@ -64,8 +72,10 @@
+ static inline void r4k_blast_dcache_page_setup(void)
+ {
+ unsigned long dc_lsize = current_cpu_data.dcache.linesz;
+-
+- if (dc_lsize == 16)
++
++ if (bcm4710)
++ r4k_blast_dcache_page = blast_dcache_page;
++ else if (dc_lsize == 16)
+ r4k_blast_dcache_page = blast_dcache16_page;
+ else if (dc_lsize == 32)
+ r4k_blast_dcache_page = r4k_blast_dcache_page_dc32;
+@@ -77,7 +87,9 @@
+ {
+ unsigned long dc_lsize = current_cpu_data.dcache.linesz;
+
+- if (dc_lsize == 16)
++ if (bcm4710)
++ r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
++ else if (dc_lsize == 16)
+ r4k_blast_dcache_page_indexed = blast_dcache16_page_indexed;
+ else if (dc_lsize == 32)
+ r4k_blast_dcache_page_indexed = blast_dcache32_page_indexed;
+@@ -89,7 +101,9 @@
+ {
+ unsigned long dc_lsize = current_cpu_data.dcache.linesz;
+
+- if (dc_lsize == 16)
++ if (bcm4710)
++ r4k_blast_dcache = blast_dcache;
++ else if (dc_lsize == 16)
+ r4k_blast_dcache = blast_dcache16;
+ else if (dc_lsize == 32)
+ r4k_blast_dcache = blast_dcache32;
+@@ -266,6 +280,7 @@
+ r4k_blast_dcache();
+ r4k_blast_icache();
+
++ if (!bcm4710)
+ switch (current_cpu_data.cputype) {
+ case CPU_R4000SC:
+ case CPU_R4000MC:
+@@ -304,10 +319,10 @@
+ * Kludge alert. For obscure reasons R4000SC and R4400SC go nuts if we
+ * only flush the primary caches but R10000 and R12000 behave sane ...
+ */
+- if (current_cpu_data.cputype == CPU_R4000SC ||
++ if (!bcm4710 && (current_cpu_data.cputype == CPU_R4000SC ||
+ current_cpu_data.cputype == CPU_R4000MC ||
+ current_cpu_data.cputype == CPU_R4400SC ||
+- current_cpu_data.cputype == CPU_R4400MC)
++ current_cpu_data.cputype == CPU_R4400MC))
+ r4k_blast_scache();
+ }
+
+@@ -383,12 +398,15 @@
+ unsigned long ic_lsize = current_cpu_data.icache.linesz;
+ unsigned long addr, aend;
+
++ addr = start & ~(dc_lsize - 1);
++ aend = (end - 1) & ~(dc_lsize - 1);
++
+ if (!cpu_has_ic_fills_f_dc) {
+ if (end - start > dcache_size)
+ r4k_blast_dcache();
+ else {
+- addr = start & ~(dc_lsize - 1);
+- aend = (end - 1) & ~(dc_lsize - 1);
++ BCM4710_PROTECTED_FILL_TLB(addr);
++ BCM4710_PROTECTED_FILL_TLB(aend);
+
+ while (1) {
+ /* Hit_Writeback_Inv_D */
+@@ -403,8 +421,6 @@
+ if (end - start > icache_size)
+ r4k_blast_icache();
+ else {
+- addr = start & ~(ic_lsize - 1);
+- aend = (end - 1) & ~(ic_lsize - 1);
+ while (1) {
+ /* Hit_Invalidate_I */
+ protected_flush_icache_line(addr);
+@@ -413,6 +429,9 @@
+ addr += ic_lsize;
+ }
+ }
++
++ if (bcm4710)
++ flush_cache_all();
+ }
+
+ /*
+@@ -443,7 +462,8 @@
+ if (cpu_has_subset_pcaches) {
+ unsigned long addr = (unsigned long) page_address(page);
+
+- r4k_blast_scache_page(addr);
++ if (!bcm4710)
++ r4k_blast_scache_page(addr);
+ ClearPageDcacheDirty(page);
+
+ return;
+@@ -451,6 +471,7 @@
+
+ if (!cpu_has_ic_fills_f_dc) {
+ unsigned long addr = (unsigned long) page_address(page);
++
+ r4k_blast_dcache_page(addr);
+ ClearPageDcacheDirty(page);
+ }
+@@ -477,7 +498,7 @@
+ /* Catch bad driver code */
+ BUG_ON(size == 0);
+
+- if (cpu_has_subset_pcaches) {
++ if (!bcm4710 && cpu_has_subset_pcaches) {
+ unsigned long sc_lsize = current_cpu_data.scache.linesz;
+
+ if (size >= scache_size) {
+@@ -509,6 +530,8 @@
+ R4600_HIT_CACHEOP_WAR_IMPL;
+ a = addr & ~(dc_lsize - 1);
+ end = (addr + size - 1) & ~(dc_lsize - 1);
++ BCM4710_FILL_TLB(a);
++ BCM4710_FILL_TLB(end);
+ while (1) {
+ flush_dcache_line(a); /* Hit_Writeback_Inv_D */
+ if (a == end)
+@@ -527,7 +550,7 @@
+ /* Catch bad driver code */
+ BUG_ON(size == 0);
+
+- if (cpu_has_subset_pcaches) {
++ if (!bcm4710 && (cpu_has_subset_pcaches)) {
+ unsigned long sc_lsize = current_cpu_data.scache.linesz;
+
+ if (size >= scache_size) {
+@@ -554,6 +577,8 @@
+ R4600_HIT_CACHEOP_WAR_IMPL;
+ a = addr & ~(dc_lsize - 1);
+ end = (addr + size - 1) & ~(dc_lsize - 1);
++ BCM4710_FILL_TLB(a);
++ BCM4710_FILL_TLB(end);
+ while (1) {
+ flush_dcache_line(a); /* Hit_Writeback_Inv_D */
+ if (a == end)
+@@ -577,6 +602,8 @@
+ unsigned long dc_lsize = current_cpu_data.dcache.linesz;
+
+ R4600_HIT_CACHEOP_WAR_IMPL;
++ BCM4710_PROTECTED_FILL_TLB(addr);
++ BCM4710_PROTECTED_FILL_TLB(addr + 4);
+ protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
+ protected_flush_icache_line(addr & ~(ic_lsize - 1));
+ if (MIPS4K_ICACHE_REFILL_WAR) {
+@@ -986,10 +1013,12 @@
+ case CPU_R4000MC:
+ case CPU_R4400SC:
+ case CPU_R4400MC:
+- probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache));
+- sc_present = probe_scache_kseg1(config);
+- if (sc_present)
+- c->options |= MIPS_CPU_CACHE_CDEX_S;
++ if (!bcm4710) {
++ probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache));
++ sc_present = probe_scache_kseg1(config);
++ if (sc_present)
++ c->options |= MIPS_CPU_CACHE_CDEX_S;
++ }
+ break;
+
+ case CPU_R10000:
+@@ -1041,6 +1070,19 @@
+ static inline void coherency_setup(void)
+ {
+ change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
++
++#if defined(CONFIG_BCM4310) || defined(CONFIG_BCM4704) || defined(CONFIG_BCM5365)
++ if (BCM330X(current_cpu_data.processor_id)) {
++ uint32 cm;
++
++ cm = read_c0_diag();
++ /* Enable icache */
++ cm |= (1 << 31);
++ /* Enable dcache */
++ cm |= (1 << 30);
++ write_c0_diag(cm);
++ }
++#endif
+
+ /*
+ * c0_status.cu=0 specifies that updates by the sc instruction use
+@@ -1073,6 +1115,12 @@
+ memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80);
+ memcpy((void *)(KSEG1 + 0x100), &except_vec2_generic, 0x80);
+
++ if (current_cpu_data.cputype == CPU_BCM4710 && (current_cpu_data.processor_id & PRID_REV_MASK) == 0) {
++ printk("Enabling BCM4710A0 cache workarounds.\n");
++ bcm4710 = 1;
++ } else
++ bcm4710 = 0;
++
+ probe_pcache();
+ setup_scache();
+
+diff -urN linux.old/arch/mips/mm/tlbex-mips32.S linux.dev/arch/mips/mm/tlbex-mips32.S
+--- linux.old/arch/mips/mm/tlbex-mips32.S 2005-07-05 16:46:49.000000000 +0200
++++ linux.dev/arch/mips/mm/tlbex-mips32.S 2005-07-06 11:23:56.000000000 +0200
+@@ -90,6 +90,9 @@
+ .set noat
+ LEAF(except_vec0_r4000)
+ .set mips3
++#ifdef CONFIG_BCM4704
++ nop
++#endif
+ #ifdef CONFIG_SMP
+ mfc0 k1, CP0_CONTEXT
+ la k0, pgd_current
+diff -urN linux.old/include/asm-mips/r4kcache.h linux.dev/include/asm-mips/r4kcache.h
+--- linux.old/include/asm-mips/r4kcache.h 2005-07-05 16:46:49.000000000 +0200
++++ linux.dev/include/asm-mips/r4kcache.h 2005-07-06 12:52:57.000000000 +0200
+@@ -15,6 +15,18 @@
+ #include <asm/asm.h>
+ #include <asm/cacheops.h>
+
++#ifdef CONFIG_BCM4710
++#define BCM4710_DUMMY_RREG() (((sbconfig_t *)(KSEG1ADDR(SB_ENUM_BASE + SBCONFIGOFF)))->sbimstate)
++
++#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr))
++#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); })
++#else
++#define BCM4710_DUMMY_RREG()
++
++#define BCM4710_FILL_TLB(addr)
++#define BCM4710_PROTECTED_FILL_TLB(addr)
++#endif
++
+ #define cache_op(op,addr) \
+ __asm__ __volatile__( \
+ " .set noreorder \n" \
+@@ -27,12 +39,25 @@
+
+ static inline void flush_icache_line_indexed(unsigned long addr)
+ {
+- cache_op(Index_Invalidate_I, addr);
++ unsigned int way;
++ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
++
++ for (way = 0; way < current_cpu_data.dcache.ways; way++) {
++ cache_op(Index_Invalidate_I, addr);
++ addr += ws_inc;
++ }
+ }
+
+ static inline void flush_dcache_line_indexed(unsigned long addr)
+ {
+- cache_op(Index_Writeback_Inv_D, addr);
++ unsigned int way;
++ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
++
++ for (way = 0; way < current_cpu_data.dcache.ways; way++) {
++ BCM4710_DUMMY_RREG();
++ cache_op(Index_Writeback_Inv_D, addr);
++ addr += ws_inc;
++ }
+ }
+
+ static inline void flush_scache_line_indexed(unsigned long addr)
+@@ -47,6 +72,7 @@
+
+ static inline void flush_dcache_line(unsigned long addr)
+ {
++ BCM4710_DUMMY_RREG();
+ cache_op(Hit_Writeback_Inv_D, addr);
+ }
+
+@@ -91,6 +117,7 @@
+ */
+ static inline void protected_writeback_dcache_line(unsigned long addr)
+ {
++ BCM4710_DUMMY_RREG();
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ ".set mips3\n"
+@@ -138,6 +165,62 @@
+ : "r" (base), \
+ "i" (op));
+
++#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 blast_dcache(void)
++{
++ unsigned long start = KSEG0;
++ unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways;
++ unsigned long end = (start + dcache_size);
++
++ while(start < end) {
++ BCM4710_DUMMY_RREG();
++ cache_unroll(start,Index_Writeback_Inv_D);
++ start += current_cpu_data.dcache.linesz;
++ }
++}
++
++static inline void blast_dcache_page(unsigned long page)
++{
++ unsigned long start = page;
++ unsigned long end = start + PAGE_SIZE;
++
++ BCM4710_FILL_TLB(start);
++ do {
++ BCM4710_DUMMY_RREG();
++ cache_unroll(start,Hit_Writeback_Inv_D);
++ start += current_cpu_data.dcache.linesz;
++ } while (start < end);
++}
++
++static inline void blast_dcache_page_indexed(unsigned long page)
++{
++ unsigned long start = page;
++ unsigned long end = start + PAGE_SIZE;
++ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
++ unsigned long ws_end = current_cpu_data.dcache.ways <<
++ current_cpu_data.dcache.waybit;
++ unsigned long ws, addr;
++
++ for (ws = 0; ws < ws_end; ws += ws_inc) {
++ start = page + ws;
++ for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
++ BCM4710_DUMMY_RREG();
++ cache_unroll(addr,Index_Writeback_Inv_D);
++ }
++ }
++}
++
+ static inline void blast_dcache16(void)
+ {
+ unsigned long start = KSEG0;
+@@ -148,8 +231,9 @@
+ unsigned long ws, addr;
+
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+- for (addr = start; addr < end; addr += 0x200)
++ for (addr = start; addr < end; addr += 0x200) {
+ cache16_unroll32(addr|ws,Index_Writeback_Inv_D);
++ }
+ }
+
+ static inline void blast_dcache16_page(unsigned long page)
+@@ -173,8 +257,9 @@
+ unsigned long ws, addr;
+
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+- for (addr = start; addr < end; addr += 0x200)
++ for (addr = start; addr < end; addr += 0x200) {
+ cache16_unroll32(addr|ws,Index_Writeback_Inv_D);
++ }
+ }
+
+ static inline void blast_icache16(void)
+@@ -196,6 +281,7 @@
+ unsigned long start = page;
+ unsigned long end = start + PAGE_SIZE;
+
++ BCM4710_FILL_TLB(start);
+ do {
+ cache16_unroll32(start,Hit_Invalidate_I);
+ start += 0x200;
+@@ -281,6 +367,7 @@
+ : "r" (base), \
+ "i" (op));
+
++
+ static inline void blast_dcache32(void)
+ {
+ unsigned long start = KSEG0;
+@@ -291,8 +378,9 @@
+ unsigned long ws, addr;
+
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+- for (addr = start; addr < end; addr += 0x400)
++ for (addr = start; addr < end; addr += 0x400) {
+ cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
++ }
+ }
+
+ static inline void blast_dcache32_page(unsigned long page)
+@@ -316,8 +404,9 @@
+ unsigned long ws, addr;
+
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+- for (addr = start; addr < end; addr += 0x400)
++ for (addr = start; addr < end; addr += 0x400) {
+ cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
++ }
+ }
+
+ static inline void blast_icache32(void)
+@@ -339,6 +428,7 @@
+ unsigned long start = page;
+ unsigned long end = start + PAGE_SIZE;
+
++ BCM4710_FILL_TLB(start);
+ do {
+ cache32_unroll32(start,Hit_Invalidate_I);
+ start += 0x400;
+@@ -443,6 +533,7 @@
+ unsigned long start = page;
+ unsigned long end = start + PAGE_SIZE;
+
++ BCM4710_FILL_TLB(start);
+ do {
+ cache64_unroll32(start,Hit_Invalidate_I);
+ start += 0x800;
+diff -urN linux.old/include/asm-mips/stackframe.h linux.dev/include/asm-mips/stackframe.h
+--- linux.old/include/asm-mips/stackframe.h 2005-07-05 16:46:49.000000000 +0200
++++ linux.dev/include/asm-mips/stackframe.h 2005-07-06 11:23:56.000000000 +0200
+@@ -209,6 +209,20 @@
+
+ #endif
+
++#if defined(CONFIG_BCM4710) || defined(CONFIG_BCM4704)
++
++#undef RESTORE_SP_AND_RET
++#define RESTORE_SP_AND_RET \
++ lw sp, PT_R29(sp); \
++ .set mips3; \
++ nop; \
++ nop; \
++ eret; \
++ .set mips0
++
++#endif
++
++
+ #define RESTORE_SP \
+ lw sp, PT_R29(sp); \
+
+diff -urN linux.old/mm/memory.c linux.dev/mm/memory.c
+--- linux.old/mm/memory.c 2005-04-04 03:42:20.000000000 +0200
++++ linux.dev/mm/memory.c 2005-07-06 11:23:56.000000000 +0200
+@@ -925,6 +925,7 @@
+ flush_page_to_ram(new_page);
+ flush_cache_page(vma, address);
+ establish_pte(vma, address, page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot))));
++ flush_icache_page(vma, new_page);
+ }
+
+ /*
diff --git a/target/linux/brcm-2.4/patches/004-flash.patch b/target/linux/brcm-2.4/patches/004-flash.patch
new file mode 100644
index 0000000000..de2d5b170f
--- /dev/null
+++ b/target/linux/brcm-2.4/patches/004-flash.patch
@@ -0,0 +1,916 @@
+diff -urN linux.old/drivers/mtd/devices/Config.in linux.dev/drivers/mtd/devices/Config.in
+--- linux.old/drivers/mtd/devices/Config.in 2006-06-22 17:35:39.000000000 +0200
++++ linux.dev/drivers/mtd/devices/Config.in 2006-06-21 21:41:24.000000000 +0200
+@@ -5,6 +5,7 @@
+ mainmenu_option next_comment
+
+ comment 'Self-contained MTD device drivers'
++bool ' Broadcom Chipcommon Serial Flash support' CONFIG_MTD_SFLASH
+ dep_tristate ' Ramix PMC551 PCI Mezzanine RAM card support' CONFIG_MTD_PMC551 $CONFIG_MTD $CONFIG_PCI
+ if [ "$CONFIG_MTD_PMC551" = "y" -o "$CONFIG_MTD_PMC551" = "m" ]; then
+ bool ' PMC551 256M DRAM Bugfix' CONFIG_MTD_PMC551_BUGFIX
+diff -urN linux.old/drivers/mtd/devices/Makefile linux.dev/drivers/mtd/devices/Makefile
+--- linux.old/drivers/mtd/devices/Makefile 2006-06-22 17:35:39.000000000 +0200
++++ linux.dev/drivers/mtd/devices/Makefile 2006-06-21 21:41:24.000000000 +0200
+@@ -3,6 +3,8 @@
+ #
+ # $Id: Makefile,v 1.4 2001/06/26 21:10:05 spse Exp $
+
++EXTRA_CFLAGS := -I$(TOPDIR)/arch/mips/bcm947xx/include
++
+ O_TARGET := devlink.o
+
+ # *** BIG UGLY NOTE ***
+@@ -12,6 +14,7 @@
+ # here where previously there was none. We now have to ensure that
+ # doc200[01].o are linked before docprobe.o
+
++obj-$(CONFIG_MTD_SFLASH) += sflash.o
+ obj-$(CONFIG_MTD_DOC1000) += doc1000.o
+ obj-$(CONFIG_MTD_DOC2000) += doc2000.o
+ obj-$(CONFIG_MTD_DOC2001) += doc2001.o
+diff -urN linux.old/drivers/mtd/devices/sflash.c linux.dev/drivers/mtd/devices/sflash.c
+--- linux.old/drivers/mtd/devices/sflash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/mtd/devices/sflash.c 2006-06-21 21:41:24.000000000 +0200
+@@ -0,0 +1,298 @@
++/*
++ * Broadcom SiliconBackplane chipcommon serial flash interface
++ *
++ * Copyright 2001-2003, 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.
++ *
++ * $Id: sflash.c,v 1.1.1.3 2003/11/10 17:43:38 hyin Exp $
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/ioport.h>
++#include <linux/mtd/compatmac.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/errno.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <asm/io.h>
++
++#ifdef CONFIG_MTD_PARTITIONS
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/minix_fs.h>
++#include <linux/ext2_fs.h>
++#include <linux/romfs_fs.h>
++#include <linux/cramfs_fs.h>
++#include <linux/jffs2.h>
++#endif
++
++#include <typedefs.h>
++#include <bcmdevs.h>
++#include <bcmutils.h>
++#include <osl.h>
++#include <bcmutils.h>
++#include <bcmnvram.h>
++#include <sbconfig.h>
++#include <sbchipc.h>
++#include <sflash.h>
++#include <trxhdr.h>
++
++#ifdef CONFIG_MTD_PARTITIONS
++extern struct mtd_partition * init_mtd_partitions(struct mtd_info *mtd, size_t size);
++#endif
++
++struct sflash_mtd {
++ chipcregs_t *cc;
++ struct semaphore lock;
++ struct mtd_info mtd;
++ struct mtd_erase_region_info regions[1];
++};
++
++/* Private global state */
++static struct sflash_mtd sflash;
++
++static int
++sflash_mtd_poll(struct sflash_mtd *sflash, unsigned int offset, int timeout)
++{
++ int now = jiffies;
++ int ret = 0;
++
++ for (;;) {
++ if (!sflash_poll(sflash->cc, offset)) {
++ ret = 0;
++ break;
++ }
++ if (time_after(jiffies, now + timeout)) {
++ printk(KERN_ERR "sflash: timeout\n");
++ ret = -ETIMEDOUT;
++ break;
++ }
++ if (current->need_resched) {
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout(timeout / 10);
++ } else
++ udelay(1);
++ }
++
++ return ret;
++}
++
++static int
++sflash_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
++{
++ struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv;
++ int bytes, ret = 0;
++
++ /* Check address range */
++ if (!len)
++ return 0;
++ if ((from + len) > mtd->size)
++ return -EINVAL;
++
++ down(&sflash->lock);
++
++ *retlen = 0;
++ while (len) {
++ if ((bytes = sflash_read(sflash->cc, (uint) from, len, buf)) < 0) {
++ ret = bytes;
++ break;
++ }
++ from += (loff_t) bytes;
++ len -= bytes;
++ buf += bytes;
++ *retlen += bytes;
++ }
++
++ up(&sflash->lock);
++
++ return ret;
++}
++
++static int
++sflash_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
++{
++ struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv;
++ int bytes, ret = 0;
++
++ /* Check address range */
++ if (!len)
++ return 0;
++ if ((to + len) > mtd->size)
++ return -EINVAL;
++
++ down(&sflash->lock);
++
++ *retlen = 0;
++ while (len) {
++ if ((bytes = sflash_write(sflash->cc, (uint) to, len, buf)) < 0) {
++ ret = bytes;
++ break;
++ }
++ if ((ret = sflash_mtd_poll(sflash, (unsigned int) to, HZ / 10)))
++ break;
++ to += (loff_t) bytes;
++ len -= bytes;
++ buf += bytes;
++ *retlen += bytes;
++ }
++
++ up(&sflash->lock);
++
++ return ret;
++}
++
++static int
++sflash_mtd_erase(struct mtd_info *mtd, struct erase_info *erase)
++{
++ struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv;
++ int i, j, ret = 0;
++ unsigned int addr, len;
++
++ /* Check address range */
++ if (!erase->len)
++ return 0;
++ if ((erase->addr + erase->len) > mtd->size)
++ return -EINVAL;
++
++ addr = erase->addr;
++ len = erase->len;
++
++ down(&sflash->lock);
++
++ /* Ensure that requested region is aligned */
++ for (i = 0; i < mtd->numeraseregions; i++) {
++ for (j = 0; j < mtd->eraseregions[i].numblocks; j++) {
++ if (addr == mtd->eraseregions[i].offset + mtd->eraseregions[i].erasesize * j &&
++ len >= mtd->eraseregions[i].erasesize) {
++ if ((ret = sflash_erase(sflash->cc, addr)) < 0)
++ break;
++ if ((ret = sflash_mtd_poll(sflash, addr, 10 * HZ)))
++ break;
++ addr += mtd->eraseregions[i].erasesize;
++ len -= mtd->eraseregions[i].erasesize;
++ }
++ }
++ if (ret)
++ break;
++ }
++
++ up(&sflash->lock);
++
++ /* Set erase status */
++ if (ret)
++ erase->state = MTD_ERASE_FAILED;
++ else
++ erase->state = MTD_ERASE_DONE;
++
++ /* Call erase callback */
++ if (erase->callback)
++ erase->callback(erase);
++
++ return ret;
++}
++
++#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
++#define sflash_mtd_init init_module
++#define sflash_mtd_exit cleanup_module
++#endif
++
++mod_init_t
++sflash_mtd_init(void)
++{
++ struct pci_dev *pdev;
++ int ret = 0;
++ struct sflash *info;
++ uint bank, i;
++#ifdef CONFIG_MTD_PARTITIONS
++ struct mtd_partition *parts;
++#endif
++
++ if (!(pdev = pci_find_device(VENDOR_BROADCOM, SB_CC, NULL))) {
++ printk(KERN_ERR "sflash: chipcommon not found\n");
++ return -ENODEV;
++ }
++
++ memset(&sflash, 0, sizeof(struct sflash_mtd));
++ init_MUTEX(&sflash.lock);
++
++ /* Map registers and flash base */
++ if (!(sflash.cc = ioremap_nocache(pci_resource_start(pdev, 0),
++ pci_resource_len(pdev, 0)))) {
++ printk(KERN_ERR "sflash: error mapping registers\n");
++ ret = -EIO;
++ goto fail;
++ }
++
++ /* Initialize serial flash access */
++ info = sflash_init(sflash.cc);
++
++ if (!info) {
++ printk(KERN_ERR "sflash: found no supported devices\n");
++ ret = -ENODEV;
++ goto fail;
++ }
++
++ /* Setup banks */
++ sflash.regions[0].offset = 0;
++ sflash.regions[0].erasesize = info->blocksize;
++ sflash.regions[0].numblocks = info->numblocks;
++ if (sflash.regions[0].erasesize > sflash.mtd.erasesize)
++ sflash.mtd.erasesize = sflash.regions[0].erasesize;
++ if (sflash.regions[0].erasesize * sflash.regions[0].numblocks) {
++ sflash.mtd.size += sflash.regions[0].erasesize * sflash.regions[0].numblocks;
++ }
++ sflash.mtd.numeraseregions = 1;
++ ASSERT(sflash.mtd.size == info->size);
++
++ /* Register with MTD */
++ sflash.mtd.name = "sflash";
++ sflash.mtd.type = MTD_NORFLASH;
++ sflash.mtd.flags = MTD_CAP_NORFLASH;
++ sflash.mtd.eraseregions = sflash.regions;
++ sflash.mtd.module = THIS_MODULE;
++ sflash.mtd.erase = sflash_mtd_erase;
++ sflash.mtd.read = sflash_mtd_read;
++ sflash.mtd.write = sflash_mtd_write;
++ sflash.mtd.priv = &sflash;
++
++#ifdef CONFIG_MTD_PARTITIONS
++ parts = init_mtd_partitions(&sflash.mtd, sflash.mtd.size);
++ for (i = 0; parts[i].name; i++);
++ ret = add_mtd_partitions(&sflash.mtd, parts, i);
++#else
++ ret = add_mtd_device(&sflash.mtd);
++#endif
++ if (ret) {
++ printk(KERN_ERR "sflash: add_mtd failed\n");
++ goto fail;
++ }
++
++ return 0;
++
++ fail:
++ if (sflash.cc)
++ iounmap((void *) sflash.cc);
++ return ret;
++}
++
++mod_exit_t
++sflash_mtd_exit(void)
++{
++#ifdef CONFIG_MTD_PARTITIONS
++ del_mtd_partitions(&sflash.mtd);
++#else
++ del_mtd_device(&sflash.mtd);
++#endif
++ iounmap((void *) sflash.cc);
++}
++
++module_init(sflash_mtd_init);
++module_exit(sflash_mtd_exit);
+diff -urN linux.old/drivers/mtd/maps/bcm947xx-flash.c linux.dev/drivers/mtd/maps/bcm947xx-flash.c
+--- linux.old/drivers/mtd/maps/bcm947xx-flash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/mtd/maps/bcm947xx-flash.c 2006-06-23 18:08:46.000000000 +0200
+@@ -0,0 +1,548 @@
++/*
++ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
++ * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
++ * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
++ *
++ * original functions for finding root filesystem from Mike Baker
++ *
++ * 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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ * 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.
++ *
++ * Flash mapping for BCM947XX boards
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/wait.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#ifdef CONFIG_MTD_PARTITIONS
++#include <linux/mtd/partitions.h>
++#endif
++#include <linux/config.h>
++#include <linux/squashfs_fs.h>
++#include <linux/jffs2.h>
++#include <linux/crc32.h>
++#include <asm/io.h>
++
++#include <typedefs.h>
++#include <osl.h>
++#include <bcmnvram.h>
++#include <bcmutils.h>
++#include <sbconfig.h>
++#include <sbchipc.h>
++#include <sbutils.h>
++#include <trxhdr.h>
++
++/* Global SB handle */
++extern void *bcm947xx_sbh;
++extern spinlock_t bcm947xx_sbh_lock;
++
++/* Convenience */
++#define sbh bcm947xx_sbh
++#define sbh_lock bcm947xx_sbh_lock
++
++#define WINDOW_ADDR 0x1fc00000
++#define WINDOW_SIZE 0x400000
++#define BUSWIDTH 2
++
++static struct mtd_info *bcm947xx_mtd;
++
++__u8 bcm947xx_map_read8(struct map_info *map, unsigned long ofs)
++{
++ if (map->map_priv_2 == 1)
++ return __raw_readb(map->map_priv_1 + ofs);
++
++ u16 val = __raw_readw(map->map_priv_1 + (ofs & ~1));
++ if (ofs & 1)
++ return ((val >> 8) & 0xff);
++ else
++ return (val & 0xff);
++}
++
++__u16 bcm947xx_map_read16(struct map_info *map, unsigned long ofs)
++{
++ return __raw_readw(map->map_priv_1 + ofs);
++}
++
++__u32 bcm947xx_map_read32(struct map_info *map, unsigned long ofs)
++{
++ return __raw_readl(map->map_priv_1 + ofs);
++}
++
++void bcm947xx_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
++{
++ if (len==1) {
++ memcpy_fromio(to, map->map_priv_1 + from, len);
++ } else {
++ int i;
++ u16 *dest = (u16 *) to;
++ u16 *src = (u16 *) (map->map_priv_1 + from);
++ for (i = 0; i < (len / 2); i++) {
++ dest[i] = src[i];
++ }
++ if (len & 1)
++ *((u8 *)dest+len-1) = src[i] & 0xff;
++ }
++}
++
++void bcm947xx_map_write8(struct map_info *map, __u8 d, unsigned long adr)
++{
++ __raw_writeb(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void bcm947xx_map_write16(struct map_info *map, __u16 d, unsigned long adr)
++{
++ __raw_writew(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void bcm947xx_map_write32(struct map_info *map, __u32 d, unsigned long adr)
++{
++ __raw_writel(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void bcm947xx_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
++{
++ memcpy_toio(map->map_priv_1 + to, from, len);
++}
++
++struct map_info bcm947xx_map = {
++ name: "Physically mapped flash",
++ size: WINDOW_SIZE,
++ buswidth: BUSWIDTH,
++ read8: bcm947xx_map_read8,
++ read16: bcm947xx_map_read16,
++ read32: bcm947xx_map_read32,
++ copy_from: bcm947xx_map_copy_from,
++ write8: bcm947xx_map_write8,
++ write16: bcm947xx_map_write16,
++ write32: bcm947xx_map_write32,
++ copy_to: bcm947xx_map_copy_to
++};
++
++#ifdef CONFIG_MTD_PARTITIONS
++
++static struct mtd_partition bcm947xx_parts[] = {
++ { name: "cfe", offset: 0, size: 0, mask_flags: MTD_WRITEABLE, },
++ { name: "linux", offset: 0, size: 0, },
++ { name: "rootfs", offset: 0, size: 0, },
++ { name: "nvram", offset: 0, size: 0, },
++ { name: "OpenWrt", offset: 0, size: 0, },
++ { name: NULL, },
++};
++
++static int __init
++find_cfe_size(struct mtd_info *mtd, size_t size)
++{
++ struct trx_header *trx;
++ unsigned char buf[512];
++ int off;
++ size_t len;
++ int blocksize;
++
++ trx = (struct trx_header *) buf;
++
++ blocksize = mtd->erasesize;
++ if (blocksize < 0x10000)
++ blocksize = 0x10000;
++
++ for (off = (128*1024); off < size; off += blocksize) {
++ memset(buf, 0xe5, sizeof(buf));
++
++ /*
++ * Read into buffer
++ */
++ if (MTD_READ(mtd, off, sizeof(buf), &len, buf) ||
++ len != sizeof(buf))
++ continue;
++
++ /* found a TRX header */
++ if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
++ goto found;
++ }
++ }
++
++ printk(KERN_NOTICE
++ "%s: Couldn't find bootloader size\n",
++ mtd->name);
++ return -1;
++
++ found:
++ printk(KERN_NOTICE "bootloader size: %d\n", off);
++ return off;
++
++}
++
++/*
++ * Copied from mtdblock.c
++ *
++ * Cache stuff...
++ *
++ * Since typical flash erasable sectors are much larger than what Linux's
++ * buffer cache can handle, we must implement read-modify-write on flash
++ * sectors for each block write requests. To avoid over-erasing flash sectors
++ * and to speed things up, we locally cache a whole flash sector while it is
++ * being written to until a different sector is required.
++ */
++
++static void erase_callback(struct erase_info *done)
++{
++ wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
++ wake_up(wait_q);
++}
++
++static int erase_write (struct mtd_info *mtd, unsigned long pos,
++ int len, const char *buf)
++{
++ struct erase_info erase;
++ DECLARE_WAITQUEUE(wait, current);
++ wait_queue_head_t wait_q;
++ size_t retlen;
++ int ret;
++
++ /*
++ * First, let's erase the flash block.
++ */
++
++ init_waitqueue_head(&wait_q);
++ erase.mtd = mtd;
++ erase.callback = erase_callback;
++ erase.addr = pos;
++ erase.len = len;
++ erase.priv = (u_long)&wait_q;
++
++ set_current_state(TASK_INTERRUPTIBLE);
++ add_wait_queue(&wait_q, &wait);
++
++ ret = MTD_ERASE(mtd, &erase);
++ if (ret) {
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&wait_q, &wait);
++ printk (KERN_WARNING "erase of region [0x%lx, 0x%x] "
++ "on \"%s\" failed\n",
++ pos, len, mtd->name);
++ return ret;
++ }
++
++ schedule(); /* Wait for erase to finish. */
++ remove_wait_queue(&wait_q, &wait);
++
++ /*
++ * Next, writhe data to flash.
++ */
++
++ ret = MTD_WRITE (mtd, pos, len, &retlen, buf);
++ if (ret)
++ return ret;
++ if (retlen != len)
++ return -EIO;
++ return 0;
++}
++
++
++
++
++static int __init
++find_root(struct mtd_info *mtd, size_t size, struct mtd_partition *part)
++{
++ struct trx_header trx, *trx2;
++ unsigned char buf[512], *block;
++ int off, blocksize;
++ u32 i, crc = ~0;
++ size_t len;
++ struct squashfs_super_block *sb = (struct squashfs_super_block *) buf;
++
++ blocksize = mtd->erasesize;
++ if (blocksize < 0x10000)
++ blocksize = 0x10000;
++
++ for (off = (128*1024); off < size; off += blocksize) {
++ memset(&trx, 0xe5, sizeof(trx));
++
++ /*
++ * Read into buffer
++ */
++ if (MTD_READ(mtd, off, sizeof(trx), &len, (char *) &trx) ||
++ len != sizeof(trx))
++ continue;
++
++ /* found a TRX header */
++ if (le32_to_cpu(trx.magic) == TRX_MAGIC) {
++ part->offset = le32_to_cpu(trx.offsets[2]) ? :
++ le32_to_cpu(trx.offsets[1]);
++ part->size = le32_to_cpu(trx.len);
++
++ part->size -= part->offset;
++ part->offset += off;
++
++ goto found;
++ }
++ }
++
++ printk(KERN_NOTICE
++ "%s: Couldn't find root filesystem\n",
++ mtd->name);
++ return -1;
++
++ found:
++ if (part->size == 0)
++ return 0;
++
++ if (MTD_READ(mtd, part->offset, sizeof(buf), &len, buf) || len != sizeof(buf))
++ return 0;
++
++ if (*((__u32 *) buf) == SQUASHFS_MAGIC) {
++ printk(KERN_INFO "%s: Filesystem type: squashfs, size=0x%x\n", mtd->name, (u32) sb->bytes_used);
++
++ /* Update the squashfs partition size based on the superblock info */
++ part->size = sb->bytes_used;
++ len = part->offset + part->size;
++ len += (mtd->erasesize - 1);
++ len &= ~(mtd->erasesize - 1);
++ part->size = len - part->offset;
++ } else if (*((__u16 *) buf) == JFFS2_MAGIC_BITMASK) {
++ printk(KERN_INFO "%s: Filesystem type: jffs2\n", mtd->name);
++
++ /* Move the squashfs outside of the trx */
++ part->size = 0;
++ } else {
++ printk(KERN_INFO "%s: Filesystem type: unknown\n", mtd->name);
++ return 0;
++ }
++
++ if (trx.len != part->offset + part->size - off) {
++ /* Update the trx offsets and length */
++ trx.len = part->offset + part->size - off;
++
++ /* Update the trx crc32 */
++ for (i = (u32) &(((struct trx_header *)NULL)->flag_version); i <= trx.len; i += sizeof(buf)) {
++ if (MTD_READ(mtd, off + i, sizeof(buf), &len, buf) || len != sizeof(buf))
++ return 0;
++ crc = crc32_le(crc, buf, min(sizeof(buf), trx.len - i));
++ }
++ trx.crc32 = crc;
++
++ /* read first eraseblock from the trx */
++ trx2 = block = kmalloc(mtd->erasesize, GFP_KERNEL);
++ if (MTD_READ(mtd, off, mtd->erasesize, &len, block) || len != mtd->erasesize) {
++ printk("Error accessing the first trx eraseblock\n");
++ return 0;
++ }
++
++ printk("Updating TRX offsets and length:\n");
++ printk("old trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx2->offsets[0], trx2->offsets[1], trx2->offsets[2], trx2->len, trx2->crc32);
++ printk("new trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx.offsets[0], trx.offsets[1], trx.offsets[2], trx.len, trx.crc32);
++
++ /* Write updated trx header to the flash */
++ memcpy(block, &trx, sizeof(trx));
++ if (mtd->unlock)
++ mtd->unlock(mtd, off, mtd->erasesize);
++ erase_write(mtd, off, mtd->erasesize, block);
++ if (mtd->sync)
++ mtd->sync(mtd);
++ kfree(block);
++ printk("Done\n");
++ }
++
++ return part->size;
++}
++
++struct mtd_partition * __init
++init_mtd_partitions(struct mtd_info *mtd, size_t size)
++{
++ int cfe_size;
++
++ if ((cfe_size = find_cfe_size(mtd,size)) < 0)
++ return NULL;
++
++ /* boot loader */
++ bcm947xx_parts[0].offset = 0;
++ bcm947xx_parts[0].size = cfe_size;
++
++ /* nvram */
++ if (cfe_size != 384 * 1024) {
++ bcm947xx_parts[3].offset = size - ROUNDUP(NVRAM_SPACE, mtd->erasesize);
++ bcm947xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
++ } else {
++ /* nvram (old 128kb config partition on netgear wgt634u) */
++ bcm947xx_parts[3].offset = bcm947xx_parts[0].size;
++ bcm947xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
++ }
++
++ /* linux (kernel and rootfs) */
++ if (cfe_size != 384 * 1024) {
++ bcm947xx_parts[1].offset = bcm947xx_parts[0].size;
++ bcm947xx_parts[1].size = bcm947xx_parts[3].offset -
++ bcm947xx_parts[1].offset;
++ } else {
++ /* do not count the elf loader, which is on one block */
++ bcm947xx_parts[1].offset = bcm947xx_parts[0].size +
++ bcm947xx_parts[3].size + mtd->erasesize;
++ bcm947xx_parts[1].size = size -
++ bcm947xx_parts[0].size -
++ (2*bcm947xx_parts[3].size) -
++ mtd->erasesize;
++ }
++
++ /* find and size rootfs */
++ if (find_root(mtd,size,&bcm947xx_parts[2])==0) {
++ /* entirely jffs2 */
++ bcm947xx_parts[4].name = NULL;
++ bcm947xx_parts[2].size = size - bcm947xx_parts[2].offset -
++ bcm947xx_parts[3].size;
++ } else {
++ /* legacy setup */
++ /* calculate leftover flash, and assign it to the jffs2 partition */
++ if (cfe_size != 384 * 1024) {
++ bcm947xx_parts[4].offset = bcm947xx_parts[2].offset +
++ bcm947xx_parts[2].size;
++ if ((bcm947xx_parts[4].offset % mtd->erasesize) > 0) {
++ bcm947xx_parts[4].offset += mtd->erasesize -
++ (bcm947xx_parts[4].offset % mtd->erasesize);
++ }
++ bcm947xx_parts[4].size = bcm947xx_parts[3].offset -
++ bcm947xx_parts[4].offset;
++ } else {
++ bcm947xx_parts[4].offset = bcm947xx_parts[2].offset +
++ bcm947xx_parts[2].size;
++ if ((bcm947xx_parts[4].offset % mtd->erasesize) > 0) {
++ bcm947xx_parts[4].offset += mtd->erasesize -
++ (bcm947xx_parts[4].offset % mtd->erasesize);
++ }
++ bcm947xx_parts[4].size = size - bcm947xx_parts[3].size -
++ bcm947xx_parts[4].offset;
++ }
++ }
++
++ return bcm947xx_parts;
++}
++
++#endif
++
++
++mod_init_t init_bcm947xx_map(void)
++{
++ ulong flags;
++ uint coreidx;
++ chipcregs_t *cc;
++ uint32 fltype;
++ uint window_addr = 0, window_size = 0;
++ size_t size;
++ int ret = 0;
++#ifdef CONFIG_MTD_PARTITIONS
++ struct mtd_partition *parts;
++ int i;
++#endif
++
++ spin_lock_irqsave(&sbh_lock, flags);
++ coreidx = sb_coreidx(sbh);
++
++ /* Check strapping option if chipcommon exists */
++ if ((cc = sb_setcore(sbh, SB_CC, 0))) {
++ fltype = readl(&cc->capabilities) & CAP_FLASH_MASK;
++ if (fltype == PFLASH) {
++ bcm947xx_map.map_priv_2 = 1;
++ window_addr = 0x1c000000;
++ bcm947xx_map.size = window_size = 32 * 1024 * 1024;
++ if ((readl(&cc->flash_config) & CC_CFG_DS) == 0)
++ bcm947xx_map.buswidth = 1;
++ }
++ } else {
++ fltype = PFLASH;
++ bcm947xx_map.map_priv_2 = 0;
++ window_addr = WINDOW_ADDR;
++ window_size = WINDOW_SIZE;
++ }
++
++ sb_setcoreidx(sbh, coreidx);
++ spin_unlock_irqrestore(&sbh_lock, flags);
++
++ if (fltype != PFLASH) {
++ printk(KERN_ERR "pflash: found no supported devices\n");
++ ret = -ENODEV;
++ goto fail;
++ }
++
++ bcm947xx_map.map_priv_1 = (unsigned long) ioremap(window_addr, window_size);
++
++ if (!bcm947xx_map.map_priv_1) {
++ printk(KERN_ERR "Failed to ioremap\n");
++ return -EIO;
++ }
++
++ if (!(bcm947xx_mtd = do_map_probe("cfi_probe", &bcm947xx_map))) {
++ printk(KERN_ERR "pflash: cfi_probe failed\n");
++ iounmap((void *)bcm947xx_map.map_priv_1);
++ return -ENXIO;
++ }
++
++ bcm947xx_mtd->module = THIS_MODULE;
++
++ size = bcm947xx_mtd->size;
++
++ printk(KERN_NOTICE "Flash device: 0x%x at 0x%x\n", size, window_addr);
++
++#ifdef CONFIG_MTD_PARTITIONS
++ parts = init_mtd_partitions(bcm947xx_mtd, size);
++ for (i = 0; parts[i].name; i++);
++ ret = add_mtd_partitions(bcm947xx_mtd, parts, i);
++ if (ret) {
++ printk(KERN_ERR "Flash: add_mtd_partitions failed\n");
++ goto fail;
++ }
++#endif
++
++ return 0;
++
++ fail:
++ if (bcm947xx_mtd)
++ map_destroy(bcm947xx_mtd);
++ if (bcm947xx_map.map_priv_1)
++ iounmap((void *) bcm947xx_map.map_priv_1);
++ bcm947xx_map.map_priv_1 = 0;
++ return ret;
++}
++
++mod_exit_t cleanup_bcm947xx_map(void)
++{
++#ifdef CONFIG_MTD_PARTITIONS
++ del_mtd_partitions(bcm947xx_mtd);
++#endif
++ map_destroy(bcm947xx_mtd);
++ iounmap((void *) bcm947xx_map.map_priv_1);
++ bcm947xx_map.map_priv_1 = 0;
++}
++
++module_init(init_bcm947xx_map);
++module_exit(cleanup_bcm947xx_map);
+diff -urN linux.old/drivers/mtd/maps/Config.in linux.dev/drivers/mtd/maps/Config.in
+--- linux.old/drivers/mtd/maps/Config.in 2006-06-22 17:35:39.000000000 +0200
++++ linux.dev/drivers/mtd/maps/Config.in 2006-06-21 21:41:24.000000000 +0200
+@@ -48,6 +48,7 @@
+ fi
+
+ if [ "$CONFIG_MIPS" = "y" ]; then
++ dep_tristate ' CFI Flash device mapped on Broadcom BCM947XX boards' CONFIG_MTD_BCM947XX $CONFIG_MTD_CFI
+ dep_tristate ' Pb1000 MTD support' CONFIG_MTD_PB1000 $CONFIG_MIPS_PB1000
+ dep_tristate ' Pb1500 MTD support' CONFIG_MTD_PB1500 $CONFIG_MIPS_PB1500
+ dep_tristate ' Pb1100 MTD support' CONFIG_MTD_PB1100 $CONFIG_MIPS_PB1100
+diff -urN linux.old/drivers/mtd/maps/Makefile linux.dev/drivers/mtd/maps/Makefile
+--- linux.old/drivers/mtd/maps/Makefile 2006-06-22 17:35:39.000000000 +0200
++++ linux.dev/drivers/mtd/maps/Makefile 2006-06-21 21:41:24.000000000 +0200
+@@ -3,6 +3,8 @@
+ #
+ # $Id: Makefile,v 1.37 2003/01/24 14:26:38 dwmw2 Exp $
+
++EXTRA_CFLAGS := -I$(TOPDIR)/arch/mips/bcm947xx/include
++
+ BELOW25 := $(shell echo $(PATCHLEVEL) | sed s/[1234]/y/)
+
+ ifeq ($(BELOW25),y)
+@@ -10,6 +12,7 @@
+ endif
+
+ # Chip mappings
++obj-$(CONFIG_MTD_BCM947XX) += bcm947xx-flash.o
+ obj-$(CONFIG_MTD_CDB89712) += cdb89712.o
+ obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o
+ obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o
diff --git a/target/linux/brcm-2.4/patches/005-bluetooth_sco_buffer_align.patch b/target/linux/brcm-2.4/patches/005-bluetooth_sco_buffer_align.patch
new file mode 100644
index 0000000000..77ade1c8b2
--- /dev/null
+++ b/target/linux/brcm-2.4/patches/005-bluetooth_sco_buffer_align.patch
@@ -0,0 +1,12 @@
+--- linux-2.4.30/drivers/bluetooth/hci_usb.c 2004-08-08 01:26:04.000000000 +0200
++++ linux-2.4.30/drivers/bluetooth/hci_usb.c 2005-07-25 20:12:11.000000000 +0200
+@@ -259,6 +259,9 @@
+ void *buf;
+
+ mtu = husb->isoc_in_ep->wMaxPacketSize;
++#ifdef CONFIG_BCM4710
++ mtu = (mtu + 1) & ~1; /* brcm: isoc buffers must be aligned on word boundary */
++#endif
+ size = mtu * HCI_MAX_ISOC_FRAMES;
+
+ buf = kmalloc(size, GFP_ATOMIC);
diff --git a/target/linux/brcm-2.4/patches/006-ide_workaround.patch b/target/linux/brcm-2.4/patches/006-ide_workaround.patch
new file mode 100644
index 0000000000..9f8d2ee29d
--- /dev/null
+++ b/target/linux/brcm-2.4/patches/006-ide_workaround.patch
@@ -0,0 +1,18 @@
+diff -urN linux.old/arch/mips/lib/ide-std.c linux.dev/arch/mips/lib/ide-std.c
+--- linux.old/arch/mips/lib/ide-std.c 2003-08-25 13:44:40.000000000 +0200
++++ linux.dev/arch/mips/lib/ide-std.c 2005-08-12 23:55:23.886963936 +0200
+@@ -31,12 +31,14 @@
+ static ide_ioreg_t std_ide_default_io_base(int index)
+ {
+ switch (index) {
++#if 0
+ case 0: return 0x1f0;
+ case 1: return 0x170;
+ case 2: return 0x1e8;
+ case 3: return 0x168;
+ case 4: return 0x1e0;
+ case 5: return 0x160;
++#endif
+ default:
+ return 0;
+ }
diff --git a/target/linux/brcm-2.4/patches/007-sched_use_tsc.patch b/target/linux/brcm-2.4/patches/007-sched_use_tsc.patch
new file mode 100644
index 0000000000..5b64310738
--- /dev/null
+++ b/target/linux/brcm-2.4/patches/007-sched_use_tsc.patch
@@ -0,0 +1,84 @@
+diff -urN linux.old/arch/mips/kernel/time.c linux.dev/arch/mips/kernel/time.c
+--- linux.old/arch/mips/kernel/time.c 2005-11-14 11:06:38.661262000 +0100
++++ linux.dev/arch/mips/kernel/time.c 2005-11-15 20:02:50.059676750 +0100
+@@ -151,6 +151,27 @@
+ unsigned int (*mips_hpt_read)(void);
+ void (*mips_hpt_init)(unsigned int);
+
++extern __u32 get_htscl(void)
++{
++ return timerhi;
++}
++
++static __u64 tscll_last = 0;
++
++extern __u64 get_tscll(void)
++{
++ __u64 h = (__u64) timerhi;
++ __u32 c = read_c0_count();
++
++ h <<= 32;
++ h += c;
++
++ while (h < tscll_last)
++ h += (((__u64) 1) << 32);
++
++ tscll_last = h;
++ return h;
++}
+
+ /*
+ * timeofday services, for syscalls.
+@@ -761,3 +782,5 @@
+ EXPORT_SYMBOL(to_tm);
+ EXPORT_SYMBOL(rtc_set_time);
+ EXPORT_SYMBOL(rtc_get_time);
++EXPORT_SYMBOL(get_htscl);
++EXPORT_SYMBOL(get_tscll);
+diff -urN linux.old/include/asm-mips/timex.h linux.dev/include/asm-mips/timex.h
+--- linux.old/include/asm-mips/timex.h 2005-11-14 11:06:38.685263500 +0100
++++ linux.dev/include/asm-mips/timex.h 2005-11-14 11:02:21.069163500 +0100
+@@ -31,6 +31,19 @@
+ return read_c0_count();
+ }
+
++extern __u32 get_htscl(void);
++extern __u64 get_tscll(void);
++
++#define rdtsc(low, high) \
++ high = get_htscl(); \
++ low = read_c0_count();
++
++#define rdtscl(low) \
++ low = read_c0_count();
++
++#define rdtscll(val) \
++ val = get_tscll();
++
+ #define vxtime_lock() do {} while (0)
+ #define vxtime_unlock() do {} while (0)
+
+diff -urN linux.old/include/net/pkt_sched.h linux.dev/include/net/pkt_sched.h
+--- linux.old/include/net/pkt_sched.h 2005-11-14 11:06:38.709265000 +0100
++++ linux.dev/include/net/pkt_sched.h 2005-11-14 11:02:21.069163500 +0100
+@@ -5,7 +5,11 @@
+ #define PSCHED_JIFFIES 2
+ #define PSCHED_CPU 3
+
++#ifdef __mips__
++#define PSCHED_CLOCK_SOURCE PSCHED_CPU
++#else
+ #define PSCHED_CLOCK_SOURCE PSCHED_JIFFIES
++#endif
+
+ #include <linux/config.h>
+ #include <linux/types.h>
+@@ -271,7 +275,7 @@
+ #define PSCHED_US2JIFFIE(delay) (((delay)+psched_clock_per_hz-1)/psched_clock_per_hz)
+ #define PSCHED_JIFFIE2US(delay) ((delay)*psched_clock_per_hz)
+
+-#ifdef CONFIG_X86_TSC
++#if defined(CONFIG_X86_TSC) || defined(__mips__)
+
+ #define PSCHED_GET_TIME(stamp) \
+ ({ u64 __cur; \
diff --git a/target/linux/brcm-2.4/patches/008-b44_bcm47xx_support.patch b/target/linux/brcm-2.4/patches/008-b44_bcm47xx_support.patch
new file mode 100644
index 0000000000..35c80acd25
--- /dev/null
+++ b/target/linux/brcm-2.4/patches/008-b44_bcm47xx_support.patch
@@ -0,0 +1,585 @@
+diff -urN linux.old/drivers/net/b44.c linux.dev/drivers/net/b44.c
+--- linux.old/drivers/net/b44.c 2006-02-12 13:49:59.000000000 +0100
++++ linux.dev/drivers/net/b44.c 2006-03-06 22:37:14.000000000 +0100
+@@ -1,7 +1,9 @@
+ /* b44.c: Broadcom 4400 device driver.
+ *
+ * Copyright (C) 2002 David S. Miller (davem@redhat.com)
+- * Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
++ * Copyright (C) 2004 Pekka Pietikainen (pp@ee.oulu.fi)
++ * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
++ * Copyright (C) 2006 Felix Fietkau (nbd@openwrt.org)
+ *
+ * Distribute under GPL.
+ */
+@@ -25,6 +27,41 @@
+
+ #include "b44.h"
+
++#include <typedefs.h>
++#include <bcmdevs.h>
++#include <bcmutils.h>
++#include <osl.h>
++#include <bcmutils.h>
++#include <bcmnvram.h>
++#include <sbconfig.h>
++#include <sbchipc.h>
++#include <sflash.h>
++
++#ifdef CONFIG_BCM947XX
++#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0)
++
++static inline void e_aton(char *str, char *dest)
++{
++ int i = 0;
++ u16 *d = (u16 *) dest;
++
++ if (str == NULL) {
++ memset(dest, 0, 6);
++ return;
++ }
++
++ for (;;) {
++ dest[i++] = (char) simple_strtoul(str, NULL, 16);
++ str += 2;
++ if (!*str++ || i == 6)
++ break;
++ }
++}
++
++static int instance = 0;
++#endif
++
++
+ #define DRV_MODULE_NAME "b44"
+ #define PFX DRV_MODULE_NAME ": "
+ #define DRV_MODULE_VERSION "0.93"
+@@ -75,7 +112,7 @@
+ DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+
+ MODULE_AUTHOR("David S. Miller (davem@redhat.com)");
+-MODULE_DESCRIPTION("Broadcom 4400 10/100 PCI ethernet driver");
++MODULE_DESCRIPTION("Broadcom 4400/47xx 10/100 PCI ethernet driver");
+ MODULE_LICENSE("GPL");
+ MODULE_PARM(b44_debug, "i");
+ MODULE_PARM_DESC(b44_debug, "B44 bitmapped debugging message enable value");
+@@ -89,6 +126,8 @@
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B1,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4713,
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+ { } /* terminate list with empty entry */
+ };
+
+@@ -113,11 +152,13 @@
+ udelay(10);
+ }
+ if (i == timeout) {
++#ifdef DEBUG
+ printk(KERN_ERR PFX "%s: BUG! Timeout waiting for bit %08x of register "
+ "%lx to %s.\n",
+ bp->dev->name,
+ bit, reg,
+ (clear ? "clear" : "set"));
++#endif
+ return -ENODEV;
+ }
+ return 0;
+@@ -236,6 +277,8 @@
+ udelay(1);
+ }
+
++static int b44_4713_instance;
++
+ static int ssb_core_unit(struct b44 *bp)
+ {
+ #if 0
+@@ -258,6 +301,9 @@
+ break;
+ };
+ #endif
++ if (bp->pdev->device == PCI_DEVICE_ID_BCM4713)
++ return b44_4713_instance++;
++ else
+ return 0;
+ }
+
+@@ -267,6 +313,28 @@
+ == SBTMSLOW_CLOCK);
+ }
+
++static inline void __b44_cam_read(struct b44 *bp, unsigned char *data, int index)
++{
++ u32 val;
++
++ bw32(B44_CAM_CTRL, (CAM_CTRL_READ |
++ (index << CAM_CTRL_INDEX_SHIFT)));
++
++ b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
++
++ val = br32(B44_CAM_DATA_LO);
++
++ data[2] = (val >> 24) & 0xFF;
++ data[3] = (val >> 16) & 0xFF;
++ data[4] = (val >> 8) & 0xFF;
++ data[5] = (val >> 0) & 0xFF;
++
++ val = br32(B44_CAM_DATA_HI);
++
++ data[0] = (val >> 8) & 0xFF;
++ data[1] = (val >> 0) & 0xFF;
++}
++
+ static void __b44_cam_write(struct b44 *bp, unsigned char *data, int index)
+ {
+ u32 val;
+@@ -287,7 +355,7 @@
+
+ static inline void __b44_disable_ints(struct b44 *bp)
+ {
+- bw32(B44_IMASK, 0);
++ bw32(B44_IMASK, ISTAT_TO); /* leave the timeout interrupt active */
+ }
+
+ static void b44_disable_ints(struct b44 *bp)
+@@ -303,14 +371,14 @@
+ bw32(B44_IMASK, bp->imask);
+ }
+
+-static int b44_readphy(struct b44 *bp, int reg, u32 *val)
++static int __b44_readphy(struct b44 *bp, int phy_addr, int reg, u32 *val)
+ {
+ int err;
+
+ bw32(B44_EMAC_ISTAT, EMAC_INT_MII);
+ bw32(B44_MDIO_DATA, (MDIO_DATA_SB_START |
+ (MDIO_OP_READ << MDIO_DATA_OP_SHIFT) |
+- (bp->phy_addr << MDIO_DATA_PMD_SHIFT) |
++ (phy_addr << MDIO_DATA_PMD_SHIFT) |
+ (reg << MDIO_DATA_RA_SHIFT) |
+ (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT)));
+ err = b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
+@@ -319,23 +387,42 @@
+ return err;
+ }
+
+-static int b44_writephy(struct b44 *bp, int reg, u32 val)
++static int b44_readphy(struct b44 *bp, int reg, u32 *val)
++{
++ if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
++ return 0;
++
++ return __b44_readphy(bp, bp->phy_addr, reg, val);
++}
++
++static int __b44_writephy(struct b44 *bp, int phy_addr, int reg, u32 val)
+ {
+ bw32(B44_EMAC_ISTAT, EMAC_INT_MII);
+ bw32(B44_MDIO_DATA, (MDIO_DATA_SB_START |
+ (MDIO_OP_WRITE << MDIO_DATA_OP_SHIFT) |
+- (bp->phy_addr << MDIO_DATA_PMD_SHIFT) |
++ (phy_addr << MDIO_DATA_PMD_SHIFT) |
+ (reg << MDIO_DATA_RA_SHIFT) |
+ (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT) |
+ (val & MDIO_DATA_DATA)));
+ return b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
+ }
+
++static int b44_writephy(struct b44 *bp, int reg, u32 val)
++{
++ if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
++ return 0;
++
++ return __b44_writephy(bp, bp->phy_addr, reg, val);
++}
++
+ static int b44_phy_reset(struct b44 *bp)
+ {
+ u32 val;
+ int err;
+
++ if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
++ return 0;
++
+ err = b44_writephy(bp, MII_BMCR, BMCR_RESET);
+ if (err)
+ return err;
+@@ -406,6 +493,23 @@
+ u32 val;
+ int err;
+
++
++ /*
++ * workaround for bad hardware design in Linksys WAP54G v1.0
++ * see https://dev.openwrt.org/ticket/146
++ * check and reset bit "isolate"
++ */
++ if ((bp->pdev->device == PCI_DEVICE_ID_BCM4713) &&
++ (atoi(nvram_get("boardnum")) == 2) &&
++ (__b44_readphy(bp, 0, MII_BMCR, &val) == 0) &&
++ (val & BMCR_ISOLATE) &&
++ (__b44_writephy(bp, 0, MII_BMCR, val & ~BMCR_ISOLATE) != 0)) {
++ printk(KERN_WARNING PFX "PHY: cannot reset MII transceiver isolate bit.\n");
++ }
++
++ if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
++ return 0;
++
+ if ((err = b44_readphy(bp, B44_MII_ALEDCTRL, &val)) != 0)
+ goto out;
+ if ((err = b44_writephy(bp, B44_MII_ALEDCTRL,
+@@ -498,6 +602,19 @@
+ {
+ u32 bmsr, aux;
+
++ if (bp->phy_addr == B44_PHY_ADDR_NO_PHY) {
++ bp->flags |= B44_FLAG_100_BASE_T;
++ bp->flags |= B44_FLAG_FULL_DUPLEX;
++ if (!netif_carrier_ok(bp->dev)) {
++ u32 val = br32(B44_TX_CTRL);
++ val |= TX_CTRL_DUPLEX;
++ bw32(B44_TX_CTRL, val);
++ netif_carrier_on(bp->dev);
++ b44_link_report(bp);
++ }
++ return;
++ }
++
+ if (!b44_readphy(bp, MII_BMSR, &bmsr) &&
+ !b44_readphy(bp, B44_MII_AUXCTRL, &aux) &&
+ (bmsr != 0xffff)) {
+@@ -765,6 +882,25 @@
+ return received;
+ }
+
++
++static inline void __b44_reset(struct b44 *bp)
++{
++ spin_lock_irq(&bp->lock);
++ b44_halt(bp);
++ b44_init_rings(bp);
++ b44_init_hw(bp);
++ spin_unlock_irq(&bp->lock);
++
++ b44_enable_ints(bp);
++ netif_wake_queue(bp->dev);
++}
++
++static inline void __b44_set_timeout(struct b44 *bp, int timeout)
++{
++ /* Set timeout for Rx to two seconds after the last Tx */
++ bw32(B44_GPTIMER, timeout ? 2 * 125000000 : 0);
++}
++
+ static int b44_poll(struct net_device *netdev, int *budget)
+ {
+ struct b44 *bp = netdev->priv;
+@@ -772,13 +908,13 @@
+
+ spin_lock_irq(&bp->lock);
+
+- if (bp->istat & (ISTAT_TX | ISTAT_TO)) {
++ if (bp->istat & ISTAT_TX) {
+ /* spin_lock(&bp->tx_lock); */
+ b44_tx(bp);
+ /* spin_unlock(&bp->tx_lock); */
+ }
+ spin_unlock_irq(&bp->lock);
+-
++
+ done = 1;
+ if (bp->istat & ISTAT_RX) {
+ int orig_budget = *budget;
+@@ -796,24 +932,18 @@
+ done = 0;
+ }
+
+- if (bp->istat & ISTAT_ERRORS) {
+- spin_lock_irq(&bp->lock);
+- b44_halt(bp);
+- b44_init_rings(bp);
+- b44_init_hw(bp);
+- netif_wake_queue(bp->dev);
+- spin_unlock_irq(&bp->lock);
+- done = 1;
+- }
+-
+ if (done) {
+ netif_rx_complete(netdev);
+ b44_enable_ints(bp);
+ }
+
++ if ((bp->core_unit == 1) && (bp->istat & (ISTAT_TX | ISTAT_RX)))
++ __b44_set_timeout(bp, (bp->istat & ISTAT_TX) ? 1 : 0);
++
+ return (done ? 0 : 1);
+ }
+
++
+ static irqreturn_t b44_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+ {
+ struct net_device *dev = dev_id;
+@@ -832,6 +962,18 @@
+ */
+ istat &= imask;
+ if (istat) {
++ /* Workaround for the WL-500g WAN port hang */
++ if (istat & (ISTAT_TO | ISTAT_ERRORS)) {
++ /*
++ * no rx before the watchdog timeout
++ * reset the interface
++ */
++ __b44_reset(bp);
++ }
++
++ if ((bp->core_unit == 1) && (bp->istat & (ISTAT_TX | ISTAT_RX)))
++ __b44_set_timeout(bp, (bp->istat & ISTAT_TX) ? 1 : 0);
++
+ handled = 1;
+ if (netif_rx_schedule_prep(dev)) {
+ /* NOTE: These writes are posted by the readback of
+@@ -848,6 +990,7 @@
+ bw32(B44_ISTAT, istat);
+ br32(B44_ISTAT);
+ }
++
+ spin_unlock_irqrestore(&bp->lock, flags);
+ return IRQ_RETVAL(handled);
+ }
+@@ -859,16 +1002,7 @@
+ printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
+ dev->name);
+
+- spin_lock_irq(&bp->lock);
+-
+- b44_halt(bp);
+- b44_init_rings(bp);
+- b44_init_hw(bp);
+-
+- spin_unlock_irq(&bp->lock);
+-
+- b44_enable_ints(bp);
+-
++ __b44_reset(bp);
+ netif_wake_queue(dev);
+ }
+
+@@ -1092,6 +1226,8 @@
+ /* bp->lock is held. */
+ static void b44_chip_reset(struct b44 *bp)
+ {
++ unsigned int sb_clock;
++
+ if (ssb_is_core_up(bp)) {
+ bw32(B44_RCV_LAZY, 0);
+ bw32(B44_ENET_CTRL, ENET_CTRL_DISABLE);
+@@ -1105,9 +1241,10 @@
+ bw32(B44_DMARX_CTRL, 0);
+ bp->rx_prod = bp->rx_cons = 0;
+ } else {
+- ssb_pci_setup(bp, (bp->core_unit == 0 ?
+- SBINTVEC_ENET0 :
+- SBINTVEC_ENET1));
++ /*if (bp->pdev->device != PCI_DEVICE_ID_BCM4713)*/
++ ssb_pci_setup(bp, (bp->core_unit == 0 ?
++ SBINTVEC_ENET0 :
++ SBINTVEC_ENET1));
+ }
+
+ ssb_core_reset(bp);
+@@ -1115,6 +1252,11 @@
+ b44_clear_stats(bp);
+
+ /* Make PHY accessible. */
++ if (bp->pdev->device == PCI_DEVICE_ID_BCM4713)
++ sb_clock = 100000000; /* 100 MHz */
++ else
++ sb_clock = 62500000; /* 62.5 MHz */
++
+ bw32(B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
+ (0x0d & MDIO_CTRL_MAXF_MASK)));
+ br32(B44_MDIO_CTRL);
+@@ -1215,6 +1357,8 @@
+ struct b44 *bp = dev->priv;
+ int err;
+
++ netif_carrier_off(dev);
++
+ err = b44_alloc_consistent(bp);
+ if (err)
+ return err;
+@@ -1235,9 +1379,10 @@
+ bp->timer.expires = jiffies + HZ;
+ bp->timer.data = (unsigned long) bp;
+ bp->timer.function = b44_timer;
+- add_timer(&bp->timer);
++ b44_timer((unsigned long) bp);
+
+ b44_enable_ints(bp);
++ netif_start_queue(dev);
+
+ return 0;
+
+@@ -1628,7 +1773,7 @@
+ u32 mii_regval;
+
+ spin_lock_irq(&bp->lock);
+- err = b44_readphy(bp, data->reg_num & 0x1f, &mii_regval);
++ err = __b44_readphy(bp, data->phy_id & 0x1f, data->reg_num & 0x1f, &mii_regval);
+ spin_unlock_irq(&bp->lock);
+
+ data->val_out = mii_regval;
+@@ -1641,7 +1786,7 @@
+ return -EPERM;
+
+ spin_lock_irq(&bp->lock);
+- err = b44_writephy(bp, data->reg_num & 0x1f, data->val_in);
++ err = __b44_writephy(bp, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
+ spin_unlock_irq(&bp->lock);
+
+ return err;
+@@ -1668,21 +1813,52 @@
+ static int __devinit b44_get_invariants(struct b44 *bp)
+ {
+ u8 eeprom[128];
++ u8 buf[32];
+ int err;
++ unsigned long flags;
+
+- err = b44_read_eeprom(bp, &eeprom[0]);
+- if (err)
+- goto out;
+-
+- bp->dev->dev_addr[0] = eeprom[79];
+- bp->dev->dev_addr[1] = eeprom[78];
+- bp->dev->dev_addr[2] = eeprom[81];
+- bp->dev->dev_addr[3] = eeprom[80];
+- bp->dev->dev_addr[4] = eeprom[83];
+- bp->dev->dev_addr[5] = eeprom[82];
+-
+- bp->phy_addr = eeprom[90] & 0x1f;
+- bp->mdc_port = (eeprom[90] >> 14) & 0x1;
++ if (bp->pdev->device == PCI_DEVICE_ID_BCM4713) {
++#ifdef CONFIG_BCM947XX
++ sprintf(buf, "et%dmacaddr", instance - 1);
++ e_aton(nvram_get(buf), bp->dev->dev_addr);
++
++ sprintf(buf, "et%dphyaddr", instance - 1);
++ bp->phy_addr = B44_PHY_ADDR_NO_PHY;
++#else
++ /*
++ * BCM47xx boards don't have a EEPROM. The MAC is stored in
++ * a NVRAM area somewhere in the flash memory. As we don't
++ * know the location and/or the format of the NVRAM area
++ * here, we simply rely on the bootloader to write the
++ * MAC into the CAM.
++ */
++ spin_lock_irqsave(&bp->lock, flags);
++ __b44_cam_read(bp, bp->dev->dev_addr, 0);
++ spin_unlock_irqrestore(&bp->lock, flags);
++
++ /*
++ * BCM47xx boards don't have a PHY. Usually there is a switch
++ * chip with multiple PHYs connected to the PHY port.
++ */
++ bp->phy_addr = B44_PHY_ADDR_NO_PHY;
++#endif
++ bp->dma_offset = 0;
++ } else {
++ err = b44_read_eeprom(bp, &eeprom[0]);
++ if (err)
++ return err;
++
++ bp->dev->dev_addr[0] = eeprom[79];
++ bp->dev->dev_addr[1] = eeprom[78];
++ bp->dev->dev_addr[2] = eeprom[81];
++ bp->dev->dev_addr[3] = eeprom[80];
++ bp->dev->dev_addr[4] = eeprom[83];
++ bp->dev->dev_addr[5] = eeprom[82];
++
++ bp->phy_addr = eeprom[90] & 0x1f;
++ bp->dma_offset = SB_PCI_DMA;
++ bp->mdc_port = (eeprom[90] >> 14) & 0x1;
++ }
+
+ /* With this, plus the rx_header prepended to the data by the
+ * hardware, we'll land the ethernet header on a 2-byte boundary.
+@@ -1692,13 +1868,12 @@
+ bp->imask = IMASK_DEF;
+
+ bp->core_unit = ssb_core_unit(bp);
+- bp->dma_offset = ssb_get_addr(bp, SBID_PCI_DMA, 0);
+
+ /* XXX - really required?
+ bp->flags |= B44_FLAG_BUGGY_TXPTR;
+ */
+-out:
+- return err;
++
++ return 0;
+ }
+
+ static int __devinit b44_init_one(struct pci_dev *pdev,
+@@ -1710,6 +1885,10 @@
+ struct b44 *bp;
+ int err, i;
+
++#ifdef CONFIG_BCM947XX
++ instance++;
++#endif
++
+ if (b44_version_printed++ == 0)
+ printk(KERN_INFO "%s", version);
+
+@@ -1819,11 +1998,17 @@
+
+ pci_save_state(bp->pdev, bp->pci_cfg_state);
+
+- printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name);
++ printk(KERN_INFO "%s: Broadcom %s 10/100BaseT Ethernet ", dev->name,
++ (pdev->device == PCI_DEVICE_ID_BCM4713) ? "47xx" : "4400");
+ for (i = 0; i < 6; i++)
+ printk("%2.2x%c", dev->dev_addr[i],
+ i == 5 ? '\n' : ':');
+
++ /* Initialize phy */
++ spin_lock_irq(&bp->lock);
++ b44_chip_reset(bp);
++ spin_unlock_irq(&bp->lock);
++
+ return 0;
+
+ err_out_iounmap:
+diff -urN linux.old/drivers/net/b44.h linux.dev/drivers/net/b44.h
+--- linux.old/drivers/net/b44.h 2006-02-12 13:49:59.000000000 +0100
++++ linux.dev/drivers/net/b44.h 2006-01-24 20:52:08.000000000 +0100
+@@ -229,8 +229,6 @@
+ #define SBIPSFLAG_IMASK4 0x3f000000 /* Which sbflags --> mips interrupt 4 */
+ #define SBIPSFLAG_ISHIFT4 24
+ #define B44_SBTPSFLAG 0x0F18UL /* SB Target Port OCP Slave Flag */
+-#define SBTPS_NUM0_MASK 0x0000003f
+-#define SBTPS_F0EN0 0x00000040
+ #define B44_SBADMATCH3 0x0F60UL /* SB Address Match 3 */
+ #define B44_SBADMATCH2 0x0F68UL /* SB Address Match 2 */
+ #define B44_SBADMATCH1 0x0F70UL /* SB Address Match 1 */
+@@ -461,6 +459,8 @@
+ };
+
+ #define B44_MCAST_TABLE_SIZE 32
++#define B44_PHY_ADDR_NO_PHY 30
++#define B44_MDC_RATIO 5000000
+
+ /* SW copy of device statistics, kept up to date by periodic timer
+ * which probes HW values. Must have same relative layout as HW
+diff -urN linux.old/include/linux/pci_ids.h linux.dev/include/linux/pci_ids.h
+--- linux.old/include/linux/pci_ids.h 2006-02-12 13:49:59.000000000 +0100
++++ linux.dev/include/linux/pci_ids.h 2006-01-24 20:52:08.000000000 +0100
+@@ -1735,6 +1735,7 @@
+ #define PCI_DEVICE_ID_TIGON3_5901_2 0x170e
+ #define PCI_DEVICE_ID_BCM4401 0x4401
+ #define PCI_DEVICE_ID_BCM4401B0 0x4402
++#define PCI_DEVICE_ID_BCM4713 0x4713
+
+ #define PCI_VENDOR_ID_ENE 0x1524
+ #define PCI_DEVICE_ID_ENE_1211 0x1211
diff --git a/target/linux/brcm-2.4/patches/009-wrt54g3g_pcmcia.patch b/target/linux/brcm-2.4/patches/009-wrt54g3g_pcmcia.patch
new file mode 100644
index 0000000000..0759eeb40e
--- /dev/null
+++ b/target/linux/brcm-2.4/patches/009-wrt54g3g_pcmcia.patch
@@ -0,0 +1,119 @@
+diff -urN linux.old/arch/mips/bcm947xx/pcibios.c linux.dev/arch/mips/bcm947xx/pcibios.c
+--- linux.old/arch/mips/bcm947xx/pcibios.c 2006-04-07 21:20:59.000000000 +0200
++++ linux.dev/arch/mips/bcm947xx/pcibios.c 2006-04-08 03:17:59.000000000 +0200
+@@ -157,6 +157,7 @@
+
+ static u32 pci_iobase = 0x100;
+ static u32 pci_membase = SB_PCI_DMA;
++static u32 pcmcia_membase = 0x40004000;
+
+ void __init
+ pcibios_fixup_bus(struct pci_bus *b)
+@@ -188,7 +189,7 @@
+ /* Fix up resource bases */
+ for (pos = 0; pos < 6; pos++) {
+ res = &d->resource[pos];
+- base = (res->flags & IORESOURCE_IO) ? &pci_iobase : &pci_membase;
++ base = (res->flags & IORESOURCE_IO) ? &pci_iobase : ((b->number == 2) ? &pcmcia_membase : &pci_membase);
+ if (res->end) {
+ size = res->end - res->start + 1;
+ if (*base & (size - 1))
+@@ -308,7 +309,12 @@
+ where = PCI_BASE_ADDRESS_0 + (resource * 4);
+ size = res->end - res->start;
+ pci_read_config_dword(dev, where, &reg);
+- reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
++
++ if (dev->bus->number == 1)
++ reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
++ else
++ reg = res->start;
++
+ pci_write_config_dword(dev, where, reg);
+ }
+
+diff -urN linux.old/drivers/pcmcia/yenta.c linux.dev/drivers/pcmcia/yenta.c
+--- linux.old/drivers/pcmcia/yenta.c 2004-11-17 12:54:21.000000000 +0100
++++ linux.dev/drivers/pcmcia/yenta.c 2006-04-11 17:47:45.000000000 +0200
+@@ -543,6 +543,9 @@
+ * Probe for usable interrupts using the force
+ * register to generate bogus card status events.
+ */
++
++#ifndef CONFIG_BCM947XX
++ /* WRT54G3G does not like this */
+ cb_writel(socket, CB_SOCKET_EVENT, -1);
+ cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
+ exca_writeb(socket, I365_CSCINT, 0);
+@@ -557,7 +560,8 @@
+ }
+ cb_writel(socket, CB_SOCKET_MASK, 0);
+ exca_writeb(socket, I365_CSCINT, 0);
+-
++#endif
++
+ mask = probe_irq_mask(val) & 0xffff;
+
+ bridge_ctrl &= ~CB_BRIDGE_INTR;
+@@ -578,6 +582,12 @@
+ socket->cap.cb_dev = socket->dev;
+ socket->cap.bus = NULL;
+
++#ifdef CONFIG_BCM947XX
++ /* irq mask probing is broken for the WRT54G3G */
++ if (socket->cap.irq_mask == 0)
++ socket->cap.irq_mask = 0x6f8;
++#endif
++
+ printk(KERN_INFO "Yenta ISA IRQ mask 0x%04x, PCI irq %d\n",
+ socket->cap.irq_mask, socket->cb_irq);
+ }
+@@ -609,6 +619,15 @@
+ printk(KERN_INFO "Socket status: %08x\n",
+ cb_readl(socket, CB_SOCKET_STATE));
+
++ /* Generate an interrupt on card insert/remove */
++ config_writew(socket, CB_SOCKET_MASK, CB_CSTSMASK | CB_CDMASK);
++
++ /* Set up Multifunction Routing Status Register */
++ config_writew(socket, 0x8C, 0x1000 /* MFUNC3 to GPIO3 */ | 0x2 /* MFUNC0 to INTA */);
++
++ /* Switch interrupts to parallelized */
++ config_writeb(socket, 0x92, 0x64);
++
+ /* Register it with the pcmcia layer.. */
+ cardbus_register(socket);
+
+@@ -731,7 +750,7 @@
+ {
+ struct pci_bus *bus;
+ struct resource *root, *res;
+- u32 start, end;
++ u32 start = 0, end = 0;
+ u32 align, size, min, max;
+ unsigned offset;
+ unsigned mask;
+@@ -750,6 +769,15 @@
+ res->end = 0;
+ root = pci_find_parent_resource(socket->dev, res);
+
++#ifdef CONFIG_BCM947XX
++ /* default mem resources are completely fscked up on the wrt54g3g */
++ /* bypass the entire resource allocation stuff below and just set it statically */
++ if (type & IORESOURCE_MEM) {
++ res->start = 0x40004000;
++ res->end = res->start + 0x3fff;
++ }
++
++#else
+ if (!root)
+ return;
+
+@@ -794,6 +822,7 @@
+ res->start = res->end = 0;
+ return;
+ }
++#endif
+
+ config_writel(socket, offset, res->start);
+ config_writel(socket, offset+4, res->end);
diff --git a/target/linux/brcm-2.4/patches/010-bcm47xx-cam_absent.patch b/target/linux/brcm-2.4/patches/010-bcm47xx-cam_absent.patch
new file mode 100644
index 0000000000..1deffc54a3
--- /dev/null
+++ b/target/linux/brcm-2.4/patches/010-bcm47xx-cam_absent.patch
@@ -0,0 +1,42 @@
+--- linux-2.4.32.orig/drivers/net/b44.h 2006-09-19 19:56:03.000000000 +0200
++++ linux-2.4.32/drivers/net/b44.h 2006-09-19 19:58:01.000000000 +0200
+@@ -122,6 +122,7 @@
+ #define RXCONFIG_FLOW 0x00000020 /* Flow Control Enable */
+ #define RXCONFIG_FLOW_ACCEPT 0x00000040 /* Accept Unicast Flow Control Frame */
+ #define RXCONFIG_RFILT 0x00000080 /* Reject Filter */
++#define RXCONFIG_CAM_ABSENT 0x00000100 /* CAM Absent */
+ #define B44_RXMAXLEN 0x0404UL /* EMAC RX Max Packet Length */
+ #define B44_TXMAXLEN 0x0408UL /* EMAC TX Max Packet Length */
+ #define B44_MDIO_CTRL 0x0410UL /* EMAC MDIO Control */
+--- linux-2.4.32.orig/drivers/net/b44.c 2006-09-19 19:56:03.000000000 +0200
++++ linux-2.4.32/drivers/net/b44.c 2006-09-19 20:08:22.000000000 +0200
+@@ -1301,6 +1301,7 @@
+ {
+ struct b44 *bp = dev->priv;
+ struct sockaddr *addr = p;
++ u32 val;
+
+ if (netif_running(dev))
+ return -EBUSY;
+@@ -1308,7 +1309,11 @@
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ spin_lock_irq(&bp->lock);
+- __b44_set_mac_addr(bp);
++
++ val = br32(B44_RXCONFIG);
++ if (!(val & RXCONFIG_CAM_ABSENT))
++ __b44_set_mac_addr(bp);
++
+ spin_unlock_irq(&bp->lock);
+
+ return 0;
+@@ -1488,7 +1493,7 @@
+
+ val = br32(B44_RXCONFIG);
+ val &= ~(RXCONFIG_PROMISC | RXCONFIG_ALLMULTI);
+- if (dev->flags & IFF_PROMISC) {
++ if ((dev->flags & IFF_PROMISC) || (val & RXCONFIG_CAM_ABSENT)) {
+ val |= RXCONFIG_PROMISC;
+ bw32(B44_RXCONFIG, val);
+ } else {
diff --git a/target/linux/brcm-2.6/Makefile b/target/linux/brcm-2.6/Makefile
new file mode 100644
index 0000000000..0437338e8e
--- /dev/null
+++ b/target/linux/brcm-2.6/Makefile
@@ -0,0 +1,23 @@
+#
+# 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
+
+LINUX_VERSION:=2.6.17
+LINUX_RELEASE:=1
+LINUX_KERNEL_MD5SUM:=37ddefe96625502161f075b9d907f21e
+
+include ./config
+include $(INCLUDE_DIR)/kernel.mk
+include $(INCLUDE_DIR)/kernel-build.mk
+
+
+$(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked
+ [ -d ../generic-$(KERNEL)/patches ] && $(PATCH) $(LINUX_DIR) ../generic-$(KERNEL)/patches $(MAKE_TRACE)
+ [ -d ./patches ] && $(PATCH) $(LINUX_DIR) ./patches $(MAKE_TRACE)
+ @$(CP) config $(LINUX_DIR)/.config
+ touch $@
+
diff --git a/target/linux/brcm-2.6/config b/target/linux/brcm-2.6/config
new file mode 100644
index 0000000000..29842b0a05
--- /dev/null
+++ b/target/linux/brcm-2.6/config
@@ -0,0 +1,1740 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Tue Aug 22 11:48:58 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+CONFIG_BCM947XX=y
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+# CONFIG_PCMCIA_LOAD_CIS is not set
+# CONFIG_PCMCIA_IOCTL is not set
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=m
+# CONFIG_YENTA_O2 is not set
+# CONFIG_YENTA_RICOH is not set
+# CONFIG_YENTA_TI is not set
+# CONFIG_YENTA_TOSHIBA is not set
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+CONFIG_PCCARD_NONSTATIC=m
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+CONFIG_IPSEC_NAT_TRAVERSAL=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=y
+CONFIG_TCP_CONG_SCALABLE=m
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+CONFIG_IPV6_ROUTER_PREF=y
+# CONFIG_IPV6_ROUTE_INFO is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_BRIDGE_NETFILTER is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NETFILTER_XTABLES=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=y
+CONFIG_IP_NF_IRC=y
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_IPP2P=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TIME=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
+CONFIG_IP_NF_MATCH_LAYER7=m
+# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_IMQ=m
+# CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_TARGET_ROUTE=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_SAME is not set
+# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+CONFIG_IP_NF_NAT_IRC=y
+CONFIG_IP_NF_NAT_FTP=y
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+CONFIG_IP_NF_RAW=m
+# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_IP_NF_SET=m
+CONFIG_IP_NF_SET_MAX=256
+CONFIG_IP_NF_SET_HASHSIZE=1024
+CONFIG_IP_NF_SET_IPMAP=m
+CONFIG_IP_NF_SET_MACIPMAP=m
+CONFIG_IP_NF_SET_PORTMAP=m
+CONFIG_IP_NF_SET_IPHASH=m
+CONFIG_IP_NF_SET_NETHASH=m
+CONFIG_IP_NF_SET_IPTREE=m
+CONFIG_IP_NF_MATCH_SET=m
+CONFIG_IP_NF_TARGET_SET=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+# CONFIG_IP6_NF_MATCH_RT is not set
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+CONFIG_IP6_NF_MATCH_OWNER=m
+# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_IMQ=m
+# CONFIG_IP6_NF_TARGET_LOG is not set
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_ROUTE=m
+CONFIG_IP6_NF_MANGLE=m
+# CONFIG_IP6_NF_TARGET_HL is not set
+# CONFIG_IP6_NF_RAW is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+CONFIG_ATM_CLIP_NO_ICMP=y
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+CONFIG_ATM_BR2684_IPFILTER=y
+CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_ESFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+# CONFIG_NET_SCH_NETEM is not set
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+CONFIG_AX25=m
+# CONFIG_AX25_DAMA_SLAVE is not set
+# CONFIG_NETROM is not set
+# CONFIG_ROSE is not set
+
+#
+# AX.25 network device drivers
+#
+CONFIG_MKISS=m
+# CONFIG_6PACK is not set
+# CONFIG_BPQETHER is not set
+# CONFIG_BAYCOM_SER_FDX is not set
+# CONFIG_BAYCOM_SER_HDX is not set
+# CONFIG_YAM is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIDTL1 is not set
+# CONFIG_BT_HCIBT3C is not set
+# CONFIG_BT_HCIBLUECARD is not set
+# CONFIG_BT_HCIBTUART is not set
+# CONFIG_BT_HCIVHCI is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_IEEE80211_SOFTMAC is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_BCM47XX=y
+# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_IMQ=m
+# CONFIG_IMQ_BEHAVIOR_AA is not set
+# CONFIG_IMQ_BEHAVIOR_AB is not set
+CONFIG_IMQ_BEHAVIOR_BA=y
+# CONFIG_IMQ_BEHAVIOR_BB is not set
+CONFIG_IMQ_NUM_DEVS=2
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+CONFIG_B44=y
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+CONFIG_ATM_DUMMY=m
+CONFIG_ATM_TCP=m
+# CONFIG_ATM_LANAI is not set
+# CONFIG_ATM_ENI is not set
+# CONFIG_ATM_FIRESTREAM is not set
+# CONFIG_ATM_ZATM is not set
+# CONFIG_ATM_NICSTAR is not set
+# CONFIG_ATM_IDT77252 is not set
+# CONFIG_ATM_AMBASSADOR is not set
+# CONFIG_ATM_HORIZON is not set
+# CONFIG_ATM_IA is not set
+# CONFIG_ATM_FORE200E_MAYBE is not set
+# CONFIG_ATM_HE is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=m
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+# CONFIG_VIDEO_V4L1 is not set
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA2 is not set
+
+#
+# Encoders and Decoders
+#
+
+#
+# V4L USB devices
+#
+
+#
+# Radio Adapters
+#
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# PCI devices
+#
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+
+#
+# ALSA MIPS devices
+#
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+CONFIG_USB_SERIAL_BELKIN=m
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+CONFIG_USB_SERIAL_VISOR=m
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+# CONFIG_USB_CXACRU is not set
+CONFIG_USB_UEAGLEATM=m
+# CONFIG_USB_XUSBATM is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=m
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=m
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=squashfs,jffs2 init=/etc/preinit noinitrd console=ttyS0,115200"
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
diff --git a/target/linux/brcm-2.6/patches/001-bcm947xx.patch b/target/linux/brcm-2.6/patches/001-bcm947xx.patch
new file mode 100644
index 0000000000..be3ac9429c
--- /dev/null
+++ b/target/linux/brcm-2.6/patches/001-bcm947xx.patch
@@ -0,0 +1,11862 @@
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/broadcom/bcmsrom.c linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/bcmsrom.c
+--- linux-2.6.17/arch/mips/bcm947xx/broadcom/bcmsrom.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/bcmsrom.c 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,481 @@
++/*
++ * Misc useful routines to access NIC SROM/OTP .
++ *
++ * Copyright 2005, 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.
++ * $Id$
++ */
++
++#include <typedefs.h>
++#include <osl.h>
++#include <bcmutils.h>
++#include <bcmsrom.h>
++#include <bcmdevs.h>
++#include <bcmendian.h>
++#include <pcicfg.h>
++#include <sbutils.h>
++
++#include <proto/ethernet.h> /* for sprom content groking */
++
++#define VARS_MAX 4096 /* should be reduced */
++
++#define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */
++#define WRITE_WORD_DELAY 20 /* 20 ms between each word write */
++
++static int initvars_srom_pci(void *sbh, void *curmap, char **vars, int *count);
++static int sprom_read_pci(uint16 *sprom, uint wordoff, uint16 *buf, uint nwords, bool check_crc);
++
++static int initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count);
++
++/*
++ * Initialize local vars from the right source for this platform.
++ * Return 0 on success, nonzero on error.
++ */
++int
++srom_var_init(void *sbh, uint bustype, void *curmap, osl_t *osh, char **vars, int *count)
++{
++ ASSERT(bustype == BUSTYPE(bustype));
++ if (vars == NULL || count == NULL)
++ return (0);
++
++ switch (BUSTYPE(bustype)) {
++
++ case PCI_BUS:
++ ASSERT(curmap); /* can not be NULL */
++ return initvars_srom_pci(sbh, curmap, vars, count);
++
++ default:
++ return 0;
++ }
++ return (-1);
++}
++
++/* support only 16-bit word read from srom */
++int
++srom_read(uint bustype, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf)
++{
++ void *srom;
++ uint off, nw;
++
++ ASSERT(bustype == BUSTYPE(bustype));
++
++ /* check input - 16-bit access only */
++ if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > (SPROM_SIZE * 2))
++ return 1;
++
++ off = byteoff / 2;
++ nw = nbytes / 2;
++
++ if (BUSTYPE(bustype) == PCI_BUS) {
++ if (!curmap)
++ return 1;
++ srom = (uchar*)curmap + PCI_BAR0_SPROM_OFFSET;
++ if (sprom_read_pci(srom, off, buf, nw, FALSE))
++ return 1;
++ } else {
++ return 1;
++ }
++
++ return 0;
++}
++
++/* support only 16-bit word write into srom */
++int
++srom_write(uint bustype, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf)
++{
++ uint16 *srom;
++ uint i, off, nw, crc_range;
++ uint16 image[SPROM_SIZE], *p;
++ uint8 crc;
++ volatile uint32 val32;
++
++ ASSERT(bustype == BUSTYPE(bustype));
++
++ /* check input - 16-bit access only */
++ if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > (SPROM_SIZE * 2))
++ return 1;
++
++ crc_range = (((BUSTYPE(bustype) == SDIO_BUS)) ? SPROM_SIZE : SPROM_CRC_RANGE) * 2;
++
++ /* if changes made inside crc cover range */
++ if (byteoff < crc_range) {
++ nw = (((byteoff + nbytes) > crc_range) ? byteoff + nbytes : crc_range) / 2;
++ /* read data including entire first 64 words from srom */
++ if (srom_read(bustype, curmap, osh, 0, nw * 2, image))
++ return 1;
++ /* make changes */
++ bcopy((void*)buf, (void*)&image[byteoff / 2], nbytes);
++ /* calculate crc */
++ htol16_buf(image, crc_range);
++ crc = ~hndcrc8((uint8 *)image, crc_range - 1, CRC8_INIT_VALUE);
++ ltoh16_buf(image, crc_range);
++ image[(crc_range / 2) - 1] = (crc << 8) | (image[(crc_range / 2) - 1] & 0xff);
++ p = image;
++ off = 0;
++ } else {
++ p = buf;
++ off = byteoff / 2;
++ nw = nbytes / 2;
++ }
++
++ if (BUSTYPE(bustype) == PCI_BUS) {
++ srom = (uint16*)((uchar*)curmap + PCI_BAR0_SPROM_OFFSET);
++ /* enable writes to the SPROM */
++ val32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32));
++ val32 |= SPROM_WRITEEN;
++ OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32);
++ bcm_mdelay(WRITE_ENABLE_DELAY);
++ /* write srom */
++ for (i = 0; i < nw; i++) {
++ W_REG(&srom[off + i], p[i]);
++ bcm_mdelay(WRITE_WORD_DELAY);
++ }
++ /* disable writes to the SPROM */
++ OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 & ~SPROM_WRITEEN);
++ } else {
++ return 1;
++ }
++
++ bcm_mdelay(WRITE_ENABLE_DELAY);
++ return 0;
++}
++
++
++/*
++ * Read in and validate sprom.
++ * Return 0 on success, nonzero on error.
++ */
++static int
++sprom_read_pci(uint16 *sprom, uint wordoff, uint16 *buf, uint nwords, bool check_crc)
++{
++ int err = 0;
++ uint i;
++
++ /* read the sprom */
++ for (i = 0; i < nwords; i++)
++ buf[i] = R_REG(&sprom[wordoff + i]);
++
++ if (check_crc) {
++ /* fixup the endianness so crc8 will pass */
++ htol16_buf(buf, nwords * 2);
++ if (hndcrc8((uint8*)buf, nwords * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE)
++ err = 1;
++ /* now correct the endianness of the byte array */
++ ltoh16_buf(buf, nwords * 2);
++ }
++
++ return err;
++}
++
++/*
++* Create variable table from memory.
++* Return 0 on success, nonzero on error.
++*/
++static int
++initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count)
++{
++ int c = (int)(end - start);
++
++ /* do it only when there is more than just the null string */
++ if (c > 1) {
++ char *vp = MALLOC(osh, c);
++ ASSERT(vp);
++ if (!vp)
++ return BCME_NOMEM;
++ bcopy(start, vp, c);
++ *vars = vp;
++ *count = c;
++ }
++ else {
++ *vars = NULL;
++ *count = 0;
++ }
++
++ return 0;
++}
++
++/*
++ * Initialize nonvolatile variable table from sprom.
++ * Return 0 on success, nonzero on error.
++ */
++static int
++initvars_srom_pci(void *sbh, void *curmap, char **vars, int *count)
++{
++ uint16 w, b[64];
++ uint8 sromrev;
++ struct ether_addr ea;
++ char eabuf[32];
++ uint32 w32;
++ int woff, i;
++ char *vp, *base;
++ osl_t *osh = sb_osh(sbh);
++ int err;
++
++ /*
++ * Apply CRC over SROM content regardless SROM is present or not,
++ * and use variable <devpath>sromrev's existance in flash to decide
++ * if we should return an error when CRC fails or read SROM variables
++ * from flash.
++ */
++ sprom_read_pci((void*)((int8*)curmap + PCI_BAR0_SPROM_OFFSET), 0, b, sizeof(b)/sizeof(b[0]), TRUE);
++
++ /* top word of sprom contains version and crc8 */
++ sromrev = b[63] & 0xff;
++ /* bcm4401 sroms misprogrammed */
++ if (sromrev == 0x10)
++ sromrev = 1;
++
++ /* srom version check */
++ if (sromrev > 3)
++ return (-2);
++
++ ASSERT(vars);
++ ASSERT(count);
++
++ base = vp = MALLOC(osh, VARS_MAX);
++ ASSERT(vp);
++ if (!vp)
++ return -2;
++
++ vp += sprintf(vp, "sromrev=%d", sromrev);
++ vp++;
++
++ if (sromrev >= 3) {
++ /* New section takes over the 3th hardware function space */
++
++ /* Words 22+23 are 11a (mid) ofdm power offsets */
++ w32 = ((uint32)b[23] << 16) | b[22];
++ vp += sprintf(vp, "ofdmapo=%d", w32);
++ vp++;
++
++ /* Words 24+25 are 11a (low) ofdm power offsets */
++ w32 = ((uint32)b[25] << 16) | b[24];
++ vp += sprintf(vp, "ofdmalpo=%d", w32);
++ vp++;
++
++ /* Words 26+27 are 11a (high) ofdm power offsets */
++ w32 = ((uint32)b[27] << 16) | b[26];
++ vp += sprintf(vp, "ofdmahpo=%d", w32);
++ vp++;
++
++ /*GPIO LED Powersave duty cycle (oncount >> 24) (offcount >> 8)*/
++ w32 = ((uint32)b[43] << 24) | ((uint32)b[42] << 8);
++ vp += sprintf(vp, "gpiotimerval=%d", w32);
++
++ /*GPIO LED Powersave duty cycle (oncount >> 24) (offcount >> 8)*/
++ w32 = ((uint32)((unsigned char)(b[21] >> 8) & 0xFF) << 24) | /* oncount*/
++ ((uint32)((unsigned char)(b[21] & 0xFF)) << 8); /* offcount */
++ vp += sprintf(vp, "gpiotimerval=%d", w32);
++
++ vp++;
++ }
++
++ if (sromrev >= 2) {
++ /* New section takes over the 4th hardware function space */
++
++ /* Word 29 is max power 11a high/low */
++ w = b[29];
++ vp += sprintf(vp, "pa1himaxpwr=%d", w & 0xff);
++ vp++;
++ vp += sprintf(vp, "pa1lomaxpwr=%d", (w >> 8) & 0xff);
++ vp++;
++
++ /* Words 30-32 set the 11alow pa settings,
++ * 33-35 are the 11ahigh ones.
++ */
++ for (i = 0; i < 3; i++) {
++ vp += sprintf(vp, "pa1lob%d=%d", i, b[30 + i]);
++ vp++;
++ vp += sprintf(vp, "pa1hib%d=%d", i, b[33 + i]);
++ vp++;
++ }
++ w = b[59];
++ if (w == 0)
++ vp += sprintf(vp, "ccode=");
++ else
++ vp += sprintf(vp, "ccode=%c%c", (w >> 8), (w & 0xff));
++ vp++;
++
++ }
++
++ /* parameter section of sprom starts at byte offset 72 */
++ woff = 72/2;
++
++ /* first 6 bytes are il0macaddr */
++ ea.octet[0] = (b[woff] >> 8) & 0xff;
++ ea.octet[1] = b[woff] & 0xff;
++ ea.octet[2] = (b[woff+1] >> 8) & 0xff;
++ ea.octet[3] = b[woff+1] & 0xff;
++ ea.octet[4] = (b[woff+2] >> 8) & 0xff;
++ ea.octet[5] = b[woff+2] & 0xff;
++ woff += ETHER_ADDR_LEN/2 ;
++ bcm_ether_ntoa((uchar*)&ea, eabuf);
++ vp += sprintf(vp, "il0macaddr=%s", eabuf);
++ vp++;
++
++ /* next 6 bytes are et0macaddr */
++ ea.octet[0] = (b[woff] >> 8) & 0xff;
++ ea.octet[1] = b[woff] & 0xff;
++ ea.octet[2] = (b[woff+1] >> 8) & 0xff;
++ ea.octet[3] = b[woff+1] & 0xff;
++ ea.octet[4] = (b[woff+2] >> 8) & 0xff;
++ ea.octet[5] = b[woff+2] & 0xff;
++ woff += ETHER_ADDR_LEN/2 ;
++ bcm_ether_ntoa((uchar*)&ea, eabuf);
++ vp += sprintf(vp, "et0macaddr=%s", eabuf);
++ vp++;
++
++ /* next 6 bytes are et1macaddr */
++ ea.octet[0] = (b[woff] >> 8) & 0xff;
++ ea.octet[1] = b[woff] & 0xff;
++ ea.octet[2] = (b[woff+1] >> 8) & 0xff;
++ ea.octet[3] = b[woff+1] & 0xff;
++ ea.octet[4] = (b[woff+2] >> 8) & 0xff;
++ ea.octet[5] = b[woff+2] & 0xff;
++ woff += ETHER_ADDR_LEN/2 ;
++ bcm_ether_ntoa((uchar*)&ea, eabuf);
++ vp += sprintf(vp, "et1macaddr=%s", eabuf);
++ vp++;
++
++ /*
++ * Enet phy settings one or two singles or a dual
++ * Bits 4-0 : MII address for enet0 (0x1f for not there)
++ * Bits 9-5 : MII address for enet1 (0x1f for not there)
++ * Bit 14 : Mdio for enet0
++ * Bit 15 : Mdio for enet1
++ */
++ w = b[woff];
++ vp += sprintf(vp, "et0phyaddr=%d", (w & 0x1f));
++ vp++;
++ vp += sprintf(vp, "et1phyaddr=%d", ((w >> 5) & 0x1f));
++ vp++;
++ vp += sprintf(vp, "et0mdcport=%d", ((w >> 14) & 0x1));
++ vp++;
++ vp += sprintf(vp, "et1mdcport=%d", ((w >> 15) & 0x1));
++ vp++;
++
++ /* Word 46 has board rev, antennas 0/1 & Country code/control */
++ w = b[46];
++ vp += sprintf(vp, "boardrev=%d", w & 0xff);
++ vp++;
++
++ if (sromrev > 1)
++ vp += sprintf(vp, "cctl=%d", (w >> 8) & 0xf);
++ else
++ vp += sprintf(vp, "cc=%d", (w >> 8) & 0xf);
++ vp++;
++
++ vp += sprintf(vp, "aa0=%d", (w >> 12) & 0x3);
++ vp++;
++
++ vp += sprintf(vp, "aa1=%d", (w >> 14) & 0x3);
++ vp++;
++
++ /* Words 47-49 set the (wl) pa settings */
++ woff = 47;
++
++ for (i = 0; i < 3; i++) {
++ vp += sprintf(vp, "pa0b%d=%d", i, b[woff+i]);
++ vp++;
++ vp += sprintf(vp, "pa1b%d=%d", i, b[woff+i+6]);
++ vp++;
++ }
++
++ /*
++ * Words 50-51 set the customer-configured wl led behavior.
++ * 8 bits/gpio pin. High bit: activehi=0, activelo=1;
++ * LED behavior values defined in wlioctl.h .
++ */
++ w = b[50];
++ if ((w != 0) && (w != 0xffff)) {
++ /* gpio0 */
++ vp += sprintf(vp, "wl0gpio0=%d", (w & 0xff));
++ vp++;
++
++ /* gpio1 */
++ vp += sprintf(vp, "wl0gpio1=%d", (w >> 8) & 0xff);
++ vp++;
++ }
++ w = b[51];
++ if ((w != 0) && (w != 0xffff)) {
++ /* gpio2 */
++ vp += sprintf(vp, "wl0gpio2=%d", w & 0xff);
++ vp++;
++
++ /* gpio3 */
++ vp += sprintf(vp, "wl0gpio3=%d", (w >> 8) & 0xff);
++ vp++;
++ }
++
++ /* Word 52 is max power 0/1 */
++ w = b[52];
++ vp += sprintf(vp, "pa0maxpwr=%d", w & 0xff);
++ vp++;
++ vp += sprintf(vp, "pa1maxpwr=%d", (w >> 8) & 0xff);
++ vp++;
++
++ /* Word 56 is idle tssi target 0/1 */
++ w = b[56];
++ vp += sprintf(vp, "pa0itssit=%d", w & 0xff);
++ vp++;
++ vp += sprintf(vp, "pa1itssit=%d", (w >> 8) & 0xff);
++ vp++;
++
++ /* Word 57 is boardflags, if not programmed make it zero */
++ w32 = (uint32)b[57];
++ if (w32 == 0xffff) w32 = 0;
++ if (sromrev > 1) {
++ /* Word 28 is the high bits of boardflags */
++ w32 |= (uint32)b[28] << 16;
++ }
++ vp += sprintf(vp, "boardflags=%d", w32);
++ vp++;
++
++ /* Word 58 is antenna gain 0/1 */
++ w = b[58];
++ vp += sprintf(vp, "ag0=%d", w & 0xff);
++ vp++;
++
++ vp += sprintf(vp, "ag1=%d", (w >> 8) & 0xff);
++ vp++;
++
++ if (sromrev == 1) {
++ /* set the oem string */
++ vp += sprintf(vp, "oem=%02x%02x%02x%02x%02x%02x%02x%02x",
++ ((b[59] >> 8) & 0xff), (b[59] & 0xff),
++ ((b[60] >> 8) & 0xff), (b[60] & 0xff),
++ ((b[61] >> 8) & 0xff), (b[61] & 0xff),
++ ((b[62] >> 8) & 0xff), (b[62] & 0xff));
++ vp++;
++ } else if (sromrev == 2) {
++ /* Word 60 OFDM tx power offset from CCK level */
++ /* OFDM Power Offset - opo */
++ vp += sprintf(vp, "opo=%d", b[60] & 0xff);
++ vp++;
++ } else {
++ /* Word 60: cck power offsets */
++ vp += sprintf(vp, "cckpo=%d", b[60]);
++ vp++;
++
++ /* Words 61+62: 11g ofdm power offsets */
++ w32 = ((uint32)b[62] << 16) | b[61];
++ vp += sprintf(vp, "ofdmgpo=%d", w32);
++ vp++;
++ }
++
++ /* final nullbyte terminator */
++ *vp++ = '\0';
++
++ ASSERT((vp - base) <= VARS_MAX);
++
++ err = initvars_table(osh, base, vp, vars, count);
++
++ MFREE(osh, base, VARS_MAX);
++ return err;
++}
++
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/broadcom/bcmutils.c linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/bcmutils.c
+--- linux-2.6.17/arch/mips/bcm947xx/broadcom/bcmutils.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/bcmutils.c 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,356 @@
++/*
++ * Misc useful OS-independent routines.
++ *
++ * Copyright 2005, 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.
++ * $Id$
++ */
++
++#include <typedefs.h>
++#include <osl.h>
++#include <sbutils.h>
++#include <bcmnvram.h>
++#include <bcmutils.h>
++#include <bcmendian.h>
++#include <bcmdevs.h>
++
++unsigned char bcm_ctype[] = {
++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */
++ _BCM_C,_BCM_C|_BCM_S,_BCM_C|_BCM_S,_BCM_C|_BCM_S,_BCM_C|_BCM_S,_BCM_C|_BCM_S,_BCM_C,_BCM_C, /* 8-15 */
++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */
++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */
++ _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */
++ _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */
++ _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */
++ _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */
++ _BCM_P,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U, /* 64-71 */
++ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */
++ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */
++ _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */
++ _BCM_P,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L, /* 96-103 */
++ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */
++ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */
++ _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */
++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
++ _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 160-175 */
++ _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 176-191 */
++ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 192-207 */
++ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_L, /* 208-223 */
++ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 224-239 */
++ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L /* 240-255 */
++};
++
++uchar
++bcm_toupper(uchar c)
++{
++ if (bcm_islower(c))
++ c -= 'a'-'A';
++ return (c);
++}
++
++ulong
++bcm_strtoul(char *cp, char **endp, uint base)
++{
++ ulong result, value;
++ bool minus;
++
++ minus = FALSE;
++
++ while (bcm_isspace(*cp))
++ cp++;
++
++ if (cp[0] == '+')
++ cp++;
++ else if (cp[0] == '-') {
++ minus = TRUE;
++ cp++;
++ }
++
++ if (base == 0) {
++ if (cp[0] == '0') {
++ if ((cp[1] == 'x') || (cp[1] == 'X')) {
++ base = 16;
++ cp = &cp[2];
++ } else {
++ base = 8;
++ cp = &cp[1];
++ }
++ } else
++ base = 10;
++ } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) {
++ cp = &cp[2];
++ }
++
++ result = 0;
++
++ while (bcm_isxdigit(*cp) &&
++ (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) {
++ result = result*base + value;
++ cp++;
++ }
++
++ if (minus)
++ result = (ulong)(result * -1);
++
++ if (endp)
++ *endp = (char *)cp;
++
++ return (result);
++}
++
++uint
++bcm_atoi(char *s)
++{
++ uint n;
++
++ n = 0;
++
++ while (bcm_isdigit(*s))
++ n = (n * 10) + *s++ - '0';
++ return (n);
++}
++
++/* return pointer to location of substring 'needle' in 'haystack' */
++char*
++bcmstrstr(char *haystack, char *needle)
++{
++ int len, nlen;
++ int i;
++
++ if ((haystack == NULL) || (needle == NULL))
++ return (haystack);
++
++ nlen = strlen(needle);
++ len = strlen(haystack) - nlen + 1;
++
++ for (i = 0; i < len; i++)
++ if (bcmp(needle, &haystack[i], nlen) == 0)
++ return (&haystack[i]);
++ return (NULL);
++}
++
++char*
++bcmstrcat(char *dest, const char *src)
++{
++ strcpy(&dest[strlen(dest)], src);
++ return (dest);
++}
++
++
++char*
++bcm_ether_ntoa(char *ea, char *buf)
++{
++ sprintf(buf,"%02x:%02x:%02x:%02x:%02x:%02x",
++ (uchar)ea[0]&0xff, (uchar)ea[1]&0xff, (uchar)ea[2]&0xff,
++ (uchar)ea[3]&0xff, (uchar)ea[4]&0xff, (uchar)ea[5]&0xff);
++ return (buf);
++}
++
++/* parse a xx:xx:xx:xx:xx:xx format ethernet address */
++int
++bcm_ether_atoe(char *p, char *ea)
++{
++ int i = 0;
++
++ for (;;) {
++ ea[i++] = (char) bcm_strtoul(p, &p, 16);
++ if (!*p++ || i == 6)
++ break;
++ }
++
++ return (i == 6);
++}
++
++void
++bcm_mdelay(uint ms)
++{
++ uint i;
++
++ for (i = 0; i < ms; i++) {
++ OSL_DELAY(1000);
++ }
++}
++
++/*
++ * Search the name=value vars for a specific one and return its value.
++ * Returns NULL if not found.
++ */
++char*
++getvar(char *vars, char *name)
++{
++ char *s;
++ int len;
++
++ len = strlen(name);
++
++ /* first look in vars[] */
++ for (s = vars; s && *s; ) {
++ if ((bcmp(s, name, len) == 0) && (s[len] == '='))
++ return (&s[len+1]);
++
++ while (*s++)
++ ;
++ }
++
++ /* then query nvram */
++ return (BCMINIT(nvram_get)(name));
++}
++
++/*
++ * Search the vars for a specific one and return its value as
++ * an integer. Returns 0 if not found.
++ */
++int
++getintvar(char *vars, char *name)
++{
++ char *val;
++
++ if ((val = getvar(vars, name)) == NULL)
++ return (0);
++
++ return (bcm_strtoul(val, NULL, 0));
++}
++
++
++/* Search for token in comma separated token-string */
++static int
++findmatch(char *string, char *name)
++{
++ uint len;
++ char *c;
++
++ len = strlen(name);
++ while ((c = strchr(string, ',')) != NULL) {
++ if (len == (uint)(c - string) && !strncmp(string, name, len))
++ return 1;
++ string = c + 1;
++ }
++
++ return (!strcmp(string, name));
++}
++
++/* Return gpio pin number assigned to the named pin */
++/*
++* Variable should be in format:
++*
++* gpio<N>=pin_name,pin_name
++*
++* This format allows multiple features to share the gpio with mutual
++* understanding.
++*
++* 'def_pin' is returned if a specific gpio is not defined for the requested functionality
++* and if def_pin is not used by others.
++*/
++uint
++getgpiopin(char *vars, char *pin_name, uint def_pin)
++{
++ char name[] = "gpioXXXX";
++ char *val;
++ uint pin;
++
++ /* Go thru all possibilities till a match in pin name */
++ for (pin = 0; pin < GPIO_NUMPINS; pin ++) {
++ sprintf(name, "gpio%d", pin);
++ val = getvar(vars, name);
++ if (val && findmatch(val, pin_name))
++ return pin;
++ }
++
++ if (def_pin != GPIO_PIN_NOTDEFINED) {
++ /* make sure the default pin is not used by someone else */
++ sprintf(name, "gpio%d", def_pin);
++ if (getvar(vars, name)) {
++ def_pin = GPIO_PIN_NOTDEFINED;
++ }
++ }
++
++ return def_pin;
++}
++
++
++/*******************************************************************************
++ * 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 uint8 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
++};
++
++#define CRC_INNER_LOOP(n, c, x) \
++ (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff]
++
++uint8
++hndcrc8(
++ uint8 *pdata, /* pointer to array of data to process */
++ uint nbytes, /* number of input data bytes to process */
++ uint8 crc /* either CRC8_INIT_VALUE or previous return value */
++)
++{
++ /* hard code the crc loop instead of using CRC_INNER_LOOP macro
++ * to avoid the undefined and unnecessary (uint8 >> 8) operation. */
++ while (nbytes-- > 0)
++ crc = crc8_table[(crc ^ *pdata++) & 0xff];
++
++ return crc;
++}
++
++#ifdef notdef
++#define CLEN 1499
++#define CBUFSIZ (CLEN+4)
++#define CNBUFS 5
++
++#endif
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/broadcom/cfe_env.c linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/cfe_env.c
+--- linux-2.6.17/arch/mips/bcm947xx/broadcom/cfe_env.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/cfe_env.c 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,234 @@
++/*
++ * NVRAM variable manipulation (Linux kernel half)
++ *
++ * Copyright 2001-2003, 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.
++ *
++ * $Id$
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++
++#include <typedefs.h>
++#include <osl.h>
++#include <bcmendian.h>
++#include <bcmutils.h>
++
++#define NVRAM_SIZE (0x1ff0)
++static char _nvdata[NVRAM_SIZE] __initdata;
++static char _valuestr[256] __initdata;
++
++/*
++ * TLV types. These codes are used in the "type-length-value"
++ * encoding of the items stored in the NVRAM device (flash or EEPROM)
++ *
++ * The layout of the flash/nvram is as follows:
++ *
++ * <type> <length> <data ...> <type> <length> <data ...> <type_end>
++ *
++ * The type code of "ENV_TLV_TYPE_END" marks the end of the list.
++ * The "length" field marks the length of the data section, not
++ * including the type and length fields.
++ *
++ * Environment variables are stored as follows:
++ *
++ * <type_env> <length> <flags> <name> = <value>
++ *
++ * If bit 0 (low bit) is set, the length is an 8-bit value.
++ * If bit 0 (low bit) is clear, the length is a 16-bit value
++ *
++ * Bit 7 set indicates "user" TLVs. In this case, bit 0 still
++ * indicates the size of the length field.
++ *
++ * Flags are from the constants below:
++ *
++ */
++#define ENV_LENGTH_16BITS 0x00 /* for low bit */
++#define ENV_LENGTH_8BITS 0x01
++
++#define ENV_TYPE_USER 0x80
++
++#define ENV_CODE_SYS(n,l) (((n)<<1)|(l))
++#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER)
++
++/*
++ * The actual TLV types we support
++ */
++
++#define ENV_TLV_TYPE_END 0x00
++#define ENV_TLV_TYPE_ENV ENV_CODE_SYS(0,ENV_LENGTH_8BITS)
++
++/*
++ * Environment variable flags
++ */
++
++#define ENV_FLG_NORMAL 0x00 /* normal read/write */
++#define ENV_FLG_BUILTIN 0x01 /* builtin - not stored in flash */
++#define ENV_FLG_READONLY 0x02 /* read-only - cannot be changed */
++
++#define ENV_FLG_MASK 0xFF /* mask of attributes we keep */
++#define ENV_FLG_ADMIN 0x100 /* lets us internally override permissions */
++
++
++/* *********************************************************************
++ * _nvram_read(buffer,offset,length)
++ *
++ * Read data from the NVRAM device
++ *
++ * Input parameters:
++ * buffer - destination buffer
++ * offset - offset of data to read
++ * length - number of bytes to read
++ *
++ * Return value:
++ * number of bytes read, or <0 if error occured
++ ********************************************************************* */
++static int
++_nvram_read(unsigned char *nv_buf, unsigned char *buffer, int offset, int length)
++{
++ int i;
++ if (offset > NVRAM_SIZE)
++ return -1;
++
++ for ( i = 0; i < length; i++) {
++ buffer[i] = ((volatile unsigned char*)nv_buf)[offset + i];
++ }
++ return length;
++}
++
++
++static char*
++_strnchr(const char *dest,int c,size_t cnt)
++{
++ while (*dest && (cnt > 0)) {
++ if (*dest == c) return (char *) dest;
++ dest++;
++ cnt--;
++ }
++ return NULL;
++}
++
++
++
++/*
++ * Core support API: Externally visible.
++ */
++
++/*
++ * Get the value of an NVRAM variable
++ * @param name name of variable to get
++ * @return value of variable or NULL if undefined
++ */
++
++char*
++cfe_env_get(unsigned char *nv_buf, char* name)
++{
++ int size;
++ unsigned char *buffer;
++ unsigned char *ptr;
++ unsigned char *envval;
++ unsigned int reclen;
++ unsigned int rectype;
++ int offset;
++ int flg;
++
++ size = NVRAM_SIZE;
++ buffer = &_nvdata[0];
++
++ ptr = buffer;
++ offset = 0;
++
++ /* Read the record type and length */
++ if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
++ goto error;
++ }
++
++ while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) {
++
++ /* Adjust pointer for TLV type */
++ rectype = *(ptr);
++ offset++;
++ size--;
++
++ /*
++ * Read the length. It can be either 1 or 2 bytes
++ * depending on the code
++ */
++ if (rectype & ENV_LENGTH_8BITS) {
++ /* Read the record type and length - 8 bits */
++ if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
++ goto error;
++ }
++ reclen = *(ptr);
++ size--;
++ offset++;
++ }
++ else {
++ /* Read the record type and length - 16 bits, MSB first */
++ if (_nvram_read(nv_buf, ptr,offset,2) != 2) {
++ goto error;
++ }
++ reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1);
++ size -= 2;
++ offset += 2;
++ }
++
++ if (reclen > size)
++ break; /* should not happen, bad NVRAM */
++
++ switch (rectype) {
++ case ENV_TLV_TYPE_ENV:
++ /* Read the TLV data */
++ if (_nvram_read(nv_buf, ptr,offset,reclen) != reclen)
++ goto error;
++ flg = *ptr++;
++ envval = (unsigned char *) _strnchr(ptr,'=',(reclen-1));
++ if (envval) {
++ *envval++ = '\0';
++ memcpy(_valuestr,envval,(reclen-1)-(envval-ptr));
++ _valuestr[(reclen-1)-(envval-ptr)] = '\0';
++#if 0
++ printk(KERN_INFO "NVRAM:%s=%s\n", ptr, _valuestr);
++#endif
++ if(!strcmp(ptr, name)){
++ return _valuestr;
++ }
++ if((strlen(ptr) > 1) && !strcmp(&ptr[1], name))
++ return _valuestr;
++ }
++ break;
++
++ default:
++ /* Unknown TLV type, skip it. */
++ break;
++ }
++
++ /*
++ * Advance to next TLV
++ */
++
++ size -= (int)reclen;
++ offset += reclen;
++
++ /* Read the next record type */
++ ptr = buffer;
++ if (_nvram_read(nv_buf, ptr,offset,1) != 1)
++ goto error;
++ }
++
++error:
++ return NULL;
++
++}
++
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/broadcom/linux_osl.c linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/linux_osl.c
+--- linux-2.6.17/arch/mips/bcm947xx/broadcom/linux_osl.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/linux_osl.c 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,102 @@
++/*
++ * Linux OS Independent Layer
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#define LINUX_OSL
++
++#include <typedefs.h>
++#include <bcmendian.h>
++#include <linux/module.h>
++#include <linuxver.h>
++#include <osl.h>
++#include <bcmutils.h>
++#include <linux/delay.h>
++#ifdef mips
++#include <asm/paccess.h>
++#endif
++#include <pcicfg.h>
++
++#define PCI_CFG_RETRY 10
++
++#define OS_HANDLE_MAGIC 0x1234abcd
++#define BCM_MEM_FILENAME_LEN 24
++
++typedef struct bcm_mem_link {
++ struct bcm_mem_link *prev;
++ struct bcm_mem_link *next;
++ uint size;
++ int line;
++ char file[BCM_MEM_FILENAME_LEN];
++} bcm_mem_link_t;
++
++struct os_handle {
++ uint magic;
++ void *pdev;
++ uint malloced;
++ uint failed;
++ bcm_mem_link_t *dbgmem_list;
++};
++
++uint32
++osl_pci_read_config(osl_t *osh, uint offset, uint size)
++{
++ uint val;
++ uint retry=PCI_CFG_RETRY;
++
++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
++
++ /* only 4byte access supported */
++ ASSERT(size == 4);
++
++ do {
++ pci_read_config_dword(osh->pdev, offset, &val);
++ if (val != 0xffffffff)
++ break;
++ } while (retry--);
++
++
++ return (val);
++}
++
++void
++osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val)
++{
++ uint retry=PCI_CFG_RETRY;
++
++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
++
++ /* only 4byte access supported */
++ ASSERT(size == 4);
++
++ do {
++ pci_write_config_dword(osh->pdev, offset, val);
++ if (offset!=PCI_BAR0_WIN)
++ break;
++ if (osl_pci_read_config(osh,offset,size) == val)
++ break;
++ } while (retry--);
++
++}
++
++void
++osl_delay(uint usec)
++{
++ uint d;
++
++ while (usec > 0) {
++ d = MIN(usec, 1000);
++ udelay(d);
++ usec -= d;
++ }
++}
++
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/broadcom/Makefile linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/Makefile
+--- linux-2.6.17/arch/mips/bcm947xx/broadcom/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/Makefile 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,6 @@
++#
++# Makefile for the BCM47xx specific kernel interface routines
++# under Linux.
++#
++
++obj-y := sbutils.o linux_osl.o bcmsrom.o bcmutils.o sbmips.o sbpci.o sflash.o nvram.o cfe_env.o
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/broadcom/nvram.c linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/nvram.c
+--- linux-2.6.17/arch/mips/bcm947xx/broadcom/nvram.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/nvram.c 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,192 @@
++/*
++ * NVRAM variable manipulation (Linux kernel half)
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <asm/bootinfo.h>
++#include <asm/addrspace.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++
++#include <typedefs.h>
++#include <bcmendian.h>
++#include <bcmnvram.h>
++#include <bcmutils.h>
++#include <sbconfig.h>
++#include <sbchipc.h>
++#include <sbutils.h>
++#include <sbmips.h>
++#include <sflash.h>
++
++/* In BSS to minimize text size and page aligned so it can be mmap()-ed */
++static char nvram_buf[NVRAM_SPACE] __attribute__((aligned(PAGE_SIZE)));
++
++/* Global SB handle */
++extern void *sbh;
++extern spinlock_t bcm947xx_sbh_lock;
++static int cfe_env;
++
++extern char *cfe_env_get(char *nv_buf, const char *name);
++
++
++/* Convenience */
++#define sbh_lock bcm947xx_sbh_lock
++#define KB * 1024
++#define MB * 1024 * 1024
++
++/* Probe for NVRAM header */
++static void __init
++early_nvram_init(void)
++{
++ struct nvram_header *header;
++ chipcregs_t *cc;
++ struct sflash *info = NULL;
++ int i;
++ uint32 base, off, lim;
++ u32 *src, *dst;
++
++ cfe_env = 0;
++ if ((cc = sb_setcore(sbh, SB_CC, 0)) != NULL) {
++ base = KSEG1ADDR(SB_FLASH2);
++ switch (readl(&cc->capabilities) & CAP_FLASH_MASK) {
++ case PFLASH:
++ lim = SB_FLASH2_SZ;
++ break;
++
++ case SFLASH_ST:
++ case SFLASH_AT:
++ if ((info = sflash_init(cc)) == NULL)
++ return;
++ lim = info->size;
++ break;
++
++ case FLASH_NONE:
++ default:
++ return;
++ }
++ } else {
++ /* extif assumed, Stop at 4 MB */
++ base = KSEG1ADDR(SB_FLASH1);
++ lim = SB_FLASH1_SZ;
++ }
++
++ /* XXX: hack for supporting the CFE environment stuff on WGT634U */
++ src = (u32 *) KSEG1ADDR(base + 8 * 1024 * 1024 - 0x2000);
++ dst = (u32 *) nvram_buf;
++ if ((lim == 0x02000000) && ((*src & 0xff00ff) == 0x000001)) {
++ printk("early_nvram_init: WGT634U NVRAM found.\n");
++
++ for (i = 0; i < 0x1ff0; i++) {
++ if (*src == 0xFFFFFFFF)
++ break;
++ *dst++ = *src++;
++ }
++ cfe_env = 1;
++ return;
++ }
++
++ off = FLASH_MIN;
++ while (off <= lim) {
++ /* Windowed flash access */
++ header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE);
++ if (header->magic == NVRAM_MAGIC)
++ goto found;
++ off <<= 1;
++ }
++
++ /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
++ header = (struct nvram_header *) KSEG1ADDR(base + 4 KB);
++ if (header->magic == NVRAM_MAGIC)
++ goto found;
++
++ header = (struct nvram_header *) KSEG1ADDR(base + 1 KB);
++ if (header->magic == NVRAM_MAGIC)
++ goto found;
++
++ return;
++
++found:
++ src = (u32 *) header;
++ dst = (u32 *) nvram_buf;
++ for (i = 0; i < sizeof(struct nvram_header); i += 4)
++ *dst++ = *src++;
++ for (; i < header->len && i < NVRAM_SPACE; i += 4)
++ *dst++ = ltoh32(*src++);
++}
++
++/* Early (before mm or mtd) read-only access to NVRAM */
++char * __init early_nvram_get(const char *name)
++{
++ char *var, *value, *end, *eq;
++
++ if (!name)
++ return NULL;
++
++ /* Too early? */
++ if (sbh == NULL)
++ return NULL;
++
++ if (!nvram_buf[0])
++ early_nvram_init();
++
++ if (cfe_env)
++ return cfe_env_get(nvram_buf, name);
++
++ /* Look for name=value and return value */
++ var = &nvram_buf[sizeof(struct nvram_header)];
++ end = nvram_buf + sizeof(nvram_buf) - 2;
++ end[0] = end[1] = '\0';
++ for (; *var; var = value + strlen(value) + 1) {
++ if (!(eq = strchr(var, '=')))
++ break;
++ value = eq + 1;
++ if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0)
++ return value;
++ }
++
++ return NULL;
++}
++
++char *nvram_get(const char *name)
++{
++ char *var, *value, *end, *eq;
++
++ if (!name)
++ return NULL;
++
++ if (!nvram_buf[0])
++ return NULL;
++
++ /* Look for name=value and return value */
++ var = &nvram_buf[sizeof(struct nvram_header)];
++ end = nvram_buf + sizeof(nvram_buf) - 2;
++ end[0] = end[1] = '\0';
++ for (; *var; var = value + strlen(value) + 1) {
++ if (!(eq = strchr(var, '=')))
++ break;
++ value = eq + 1;
++ if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0)
++ return value;
++ }
++
++ return NULL;
++}
++
++EXPORT_SYMBOL(nvram_get);
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/broadcom/sbmips.c linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/sbmips.c
+--- linux-2.6.17/arch/mips/bcm947xx/broadcom/sbmips.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/sbmips.c 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,1055 @@
++/*
++ * BCM47XX Sonics SiliconBackplane MIPS core routines
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#include <typedefs.h>
++#include <osl.h>
++#include <sbutils.h>
++#include <bcmdevs.h>
++#include <bcmnvram.h>
++#include <bcmutils.h>
++#include <hndmips.h>
++#include <sbconfig.h>
++#include <sbextif.h>
++#include <sbchipc.h>
++#include <sbmemc.h>
++#include <mipsinc.h>
++#include <sbutils.h>
++
++/*
++ * Returns TRUE if an external UART exists at the given base
++ * register.
++ */
++static bool
++BCMINITFN(serial_exists)(uint8 *regs)
++{
++ uint8 save_mcr, status1;
++
++ save_mcr = R_REG(&regs[UART_MCR]);
++ W_REG(&regs[UART_MCR], UART_MCR_LOOP | 0x0a);
++ status1 = R_REG(&regs[UART_MSR]) & 0xf0;
++ W_REG(&regs[UART_MCR], save_mcr);
++
++ return (status1 == 0x90);
++}
++
++/*
++ * Initializes UART access. The callback function will be called once
++ * per found UART.
++ */
++void
++BCMINITFN(sb_serial_init)(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base, uint reg_shift))
++{
++ void *regs;
++ ulong base;
++ uint irq;
++ int i, n;
++
++ if ((regs = sb_setcore(sbh, SB_EXTIF, 0))) {
++ extifregs_t *eir = (extifregs_t *) regs;
++ sbconfig_t *sb;
++
++ /* Determine external UART register base */
++ sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF);
++ base = EXTIF_CFGIF_BASE(sb_base(R_REG(&sb->sbadmatch1)));
++
++ /* Determine IRQ */
++ irq = sb_irq(sbh);
++
++ /* Disable GPIO interrupt initially */
++ W_REG(&eir->gpiointpolarity, 0);
++ W_REG(&eir->gpiointmask, 0);
++
++ /* Search for external UARTs */
++ n = 2;
++ for (i = 0; i < 2; i++) {
++ regs = (void *) REG_MAP(base + (i * 8), 8);
++ if (BCMINIT(serial_exists)(regs)) {
++ /* Set GPIO 1 to be the external UART IRQ */
++ W_REG(&eir->gpiointmask, 2);
++ if (add)
++ add(regs, irq, 13500000, 0);
++ }
++ }
++
++ /* Add internal UART if enabled */
++ if (R_REG(&eir->corecontrol) & CC_UE)
++ if (add)
++ add((void *) &eir->uartdata, irq, sb_clock(sbh), 2);
++ } else if ((regs = sb_setcore(sbh, SB_CC, 0))) {
++ chipcregs_t *cc = (chipcregs_t *) regs;
++ uint32 rev, cap, pll, baud_base, div;
++
++ /* Determine core revision and capabilities */
++ rev = sb_corerev(sbh);
++ cap = R_REG(&cc->capabilities);
++ pll = cap & CAP_PLL_MASK;
++
++ /* Determine IRQ */
++ irq = sb_irq(sbh);
++
++ if (pll == PLL_TYPE1) {
++ /* PLL clock */
++ baud_base = sb_clock_rate(pll,
++ R_REG(&cc->clockcontrol_n),
++ R_REG(&cc->clockcontrol_m2));
++ div = 1;
++ } else {
++ if (rev >= 11) {
++ /* Fixed ALP clock */
++ baud_base = 20000000;
++ div = 1;
++ /* Set the override bit so we don't divide it */
++ W_REG(&cc->corecontrol, CC_UARTCLKO);
++ } else if (rev >= 3) {
++ /* Internal backplane clock */
++ baud_base = sb_clock(sbh);
++ div = 2; /* Minimum divisor */
++ W_REG(&cc->clkdiv,
++ ((R_REG(&cc->clkdiv) & ~CLKD_UART) | div));
++ } else {
++ /* Fixed internal backplane clock */
++ baud_base = 88000000;
++ div = 48;
++ }
++
++ /* Clock source depends on strapping if UartClkOverride is unset */
++ if ((rev > 0) &&
++ ((R_REG(&cc->corecontrol) & CC_UARTCLKO) == 0)) {
++ if ((cap & CAP_UCLKSEL) == CAP_UINTCLK) {
++ /* Internal divided backplane clock */
++ baud_base /= div;
++ } else {
++ /* Assume external clock of 1.8432 MHz */
++ baud_base = 1843200;
++ }
++ }
++ }
++
++ /* Add internal UARTs */
++ n = cap & CAP_UARTS_MASK;
++ for (i = 0; i < n; i++) {
++ /* Register offset changed after revision 0 */
++ if (rev)
++ regs = (void *)((ulong) &cc->uart0data + (i * 256));
++ else
++ regs = (void *)((ulong) &cc->uart0data + (i * 8));
++
++ if (add)
++ add(regs, irq, baud_base, 0);
++ }
++ }
++}
++
++/*
++ * Initialize jtag master and return handle for
++ * jtag_rwreg. Returns NULL on failure.
++ */
++void *
++sb_jtagm_init(sb_t *sbh, uint clkd, bool exttap)
++{
++ void *regs;
++
++ if ((regs = sb_setcore(sbh, SB_CC, 0)) != NULL) {
++ chipcregs_t *cc = (chipcregs_t *) regs;
++ uint32 tmp;
++
++ /*
++ * Determine jtagm availability from
++ * core revision and capabilities.
++ */
++ tmp = sb_corerev(sbh);
++ /*
++ * Corerev 10 has jtagm, but the only chip
++ * with it does not have a mips, and
++ * the layout of the jtagcmd register is
++ * different. We'll only accept >= 11.
++ */
++ if (tmp < 11)
++ return (NULL);
++
++ tmp = R_REG(&cc->capabilities);
++ if ((tmp & CAP_JTAGP) == 0)
++ return (NULL);
++
++ /* Set clock divider if requested */
++ if (clkd != 0) {
++ tmp = R_REG(&cc->clkdiv);
++ tmp = (tmp & ~CLKD_JTAG) |
++ ((clkd << CLKD_JTAG_SHIFT) & CLKD_JTAG);
++ W_REG(&cc->clkdiv, tmp);
++ }
++
++ /* Enable jtagm */
++ tmp = JCTRL_EN | (exttap ? JCTRL_EXT_EN : 0);
++ W_REG(&cc->jtagctrl, tmp);
++ }
++
++ return (regs);
++}
++
++void
++sb_jtagm_disable(void *h)
++{
++ chipcregs_t *cc = (chipcregs_t *)h;
++
++ W_REG(&cc->jtagctrl, R_REG(&cc->jtagctrl) & ~JCTRL_EN);
++}
++
++/*
++ * Read/write a jtag register. Assumes a target with
++ * 8 bit IR and 32 bit DR.
++ */
++#define IRWIDTH 8
++#define DRWIDTH 32
++uint32
++jtag_rwreg(void *h, uint32 ir, uint32 dr)
++{
++ chipcregs_t *cc = (chipcregs_t *) h;
++ uint32 tmp;
++
++ W_REG(&cc->jtagir, ir);
++ W_REG(&cc->jtagdr, dr);
++ tmp = JCMD_START | JCMD_ACC_IRDR |
++ ((IRWIDTH - 1) << JCMD_IRW_SHIFT) |
++ (DRWIDTH - 1);
++ W_REG(&cc->jtagcmd, tmp);
++ while (((tmp = R_REG(&cc->jtagcmd)) & JCMD_BUSY) == JCMD_BUSY) {
++ /* OSL_DELAY(1); */
++ }
++
++ tmp = R_REG(&cc->jtagdr);
++ return (tmp);
++}
++
++/* Returns the SB interrupt flag of the current core. */
++uint32
++sb_flag(sb_t *sbh)
++{
++ void *regs;
++ sbconfig_t *sb;
++
++ regs = sb_coreregs(sbh);
++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
++
++ return (R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK);
++}
++
++static const uint32 sbips_int_mask[] = {
++ 0,
++ SBIPS_INT1_MASK,
++ SBIPS_INT2_MASK,
++ SBIPS_INT3_MASK,
++ SBIPS_INT4_MASK
++};
++
++static const uint32 sbips_int_shift[] = {
++ 0,
++ 0,
++ SBIPS_INT2_SHIFT,
++ SBIPS_INT3_SHIFT,
++ SBIPS_INT4_SHIFT
++};
++
++/*
++ * Returns the MIPS IRQ assignment of the current core. If unassigned,
++ * 0 is returned.
++ */
++uint
++sb_irq(sb_t *sbh)
++{
++ uint idx;
++ void *regs;
++ sbconfig_t *sb;
++ uint32 flag, sbipsflag;
++ uint irq = 0;
++
++ flag = sb_flag(sbh);
++
++ idx = sb_coreidx(sbh);
++
++ if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
++ (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
++
++ /* sbipsflag specifies which core is routed to interrupts 1 to 4 */
++ sbipsflag = R_REG(&sb->sbipsflag);
++ for (irq = 1; irq <= 4; irq++) {
++ if (((sbipsflag & sbips_int_mask[irq]) >> sbips_int_shift[irq]) == flag)
++ break;
++ }
++ if (irq == 5)
++ irq = 0;
++ }
++
++ sb_setcoreidx(sbh, idx);
++
++ return irq;
++}
++
++/* Clears the specified MIPS IRQ. */
++static void
++BCMINITFN(sb_clearirq)(sb_t *sbh, uint irq)
++{
++ void *regs;
++ sbconfig_t *sb;
++
++ if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
++ !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
++ ASSERT(regs);
++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
++
++ if (irq == 0)
++ W_REG(&sb->sbintvec, 0);
++ else
++ OR_REG(&sb->sbipsflag, sbips_int_mask[irq]);
++}
++
++/*
++ * Assigns the specified MIPS IRQ to the specified core. Shared MIPS
++ * IRQ 0 may be assigned more than once.
++ */
++static void
++BCMINITFN(sb_setirq)(sb_t *sbh, uint irq, uint coreid, uint coreunit)
++{
++ void *regs;
++ sbconfig_t *sb;
++ uint32 flag;
++
++ regs = sb_setcore(sbh, coreid, coreunit);
++ ASSERT(regs);
++ flag = sb_flag(sbh);
++
++ if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
++ !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
++ ASSERT(regs);
++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
++
++ if (irq == 0)
++ OR_REG(&sb->sbintvec, 1 << flag);
++ else {
++ flag <<= sbips_int_shift[irq];
++ ASSERT(!(flag & ~sbips_int_mask[irq]));
++ flag |= R_REG(&sb->sbipsflag) & ~sbips_int_mask[irq];
++ W_REG(&sb->sbipsflag, flag);
++ }
++}
++
++/*
++ * Initializes clocks and interrupts. SB and NVRAM access must be
++ * initialized prior to calling.
++ */
++void
++BCMINITFN(sb_mips_init)(sb_t *sbh)
++{
++ ulong hz, ns, tmp;
++ extifregs_t *eir;
++ chipcregs_t *cc;
++ char *value;
++ uint irq;
++
++ /* Figure out current SB clock speed */
++ if ((hz = sb_clock(sbh)) == 0)
++ hz = 100000000;
++ ns = 1000000000 / hz;
++
++ /* Setup external interface timing */
++ if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) {
++ /* Initialize extif so we can get to the LEDs and external UART */
++ W_REG(&eir->prog_config, CF_EN);
++
++ /* Set timing for the flash */
++ tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
++ tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */
++ tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
++ W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
++
++ /* Set programmable interface timing for external uart */
++ tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
++ tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */
++ tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */
++ tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
++ W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
++ } else if ((cc = sb_setcore(sbh, SB_CC, 0))) {
++ /* set register for external IO to control LED. */
++ W_REG(&cc->prog_config, 0x11);
++ tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
++ tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */
++ tmp = tmp | CEIL(240, ns); /* W0 = 120nS */
++ W_REG(&cc->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
++
++ /* Set timing for the flash */
++ tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
++ tmp |= CEIL(10, ns) << FW_W1_SHIFT; /* W1 = 10nS */
++ tmp |= CEIL(120, ns); /* W0 = 120nS */
++
++ // Added by Chen-I for 5365
++ if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID)
++ {
++ W_REG(&cc->flash_waitcount, tmp);
++ W_REG(&cc->pcmcia_memwait, tmp);
++ }
++ else
++ {
++ if (sb_corerev(sbh) < 9)
++ W_REG(&cc->flash_waitcount, tmp);
++
++ if ((sb_corerev(sbh) < 9) ||
++ ((BCMINIT(sb_chip)(sbh) == BCM5350_DEVICE_ID) && BCMINIT(sb_chiprev)(sbh) == 0)) {
++ W_REG(&cc->pcmcia_memwait, tmp);
++ }
++ }
++ // Added by Chen-I & Yen for enabling 5350 EXTIF
++ if (BCMINIT(sb_chip)(sbh) == BCM5350_DEVICE_ID)
++ {
++ /* Set programmable interface timing for external uart */
++ tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
++ tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */
++ tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */
++ tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
++ W_REG(&cc->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
++ }
++ }
++
++ /* Chip specific initialization */
++ switch (BCMINIT(sb_chip)(sbh)) {
++ case BCM4710_DEVICE_ID:
++ /* Clear interrupt map */
++ for (irq = 0; irq <= 4; irq++)
++ BCMINIT(sb_clearirq)(sbh, irq);
++ BCMINIT(sb_setirq)(sbh, 0, SB_CODEC, 0);
++ BCMINIT(sb_setirq)(sbh, 0, SB_EXTIF, 0);
++ BCMINIT(sb_setirq)(sbh, 2, SB_ENET, 1);
++ BCMINIT(sb_setirq)(sbh, 3, SB_ILINE20, 0);
++ BCMINIT(sb_setirq)(sbh, 4, SB_PCI, 0);
++ ASSERT(eir);
++ value = BCMINIT(early_nvram_get)("et0phyaddr");
++ if (value && !strcmp(value, "31")) {
++ /* Enable internal UART */
++ W_REG(&eir->corecontrol, CC_UE);
++ /* Give USB its own interrupt */
++ BCMINIT(sb_setirq)(sbh, 1, SB_USB, 0);
++ } else {
++ /* Disable internal UART */
++ W_REG(&eir->corecontrol, 0);
++ /* Give Ethernet its own interrupt */
++ BCMINIT(sb_setirq)(sbh, 1, SB_ENET, 0);
++ BCMINIT(sb_setirq)(sbh, 0, SB_USB, 0);
++ }
++ break;
++ case BCM5350_DEVICE_ID:
++ /* Clear interrupt map */
++ for (irq = 0; irq <= 4; irq++)
++ BCMINIT(sb_clearirq)(sbh, irq);
++ BCMINIT(sb_setirq)(sbh, 0, SB_CC, 0);
++ BCMINIT(sb_setirq)(sbh, 1, SB_D11, 0);
++ BCMINIT(sb_setirq)(sbh, 2, SB_ENET, 0);
++ BCMINIT(sb_setirq)(sbh, 3, SB_PCI, 0);
++ BCMINIT(sb_setirq)(sbh, 4, SB_USB, 0);
++ break;
++ }
++}
++
++uint32
++BCMINITFN(sb_mips_clock)(sb_t *sbh)
++{
++ extifregs_t *eir;
++ chipcregs_t *cc;
++ uint32 n, m;
++ uint idx;
++ uint32 pll_type, rate = 0;
++
++ /* get index of the current core */
++ idx = sb_coreidx(sbh);
++ pll_type = PLL_TYPE1;
++
++ /* switch to extif or chipc core */
++ if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
++ n = R_REG(&eir->clockcontrol_n);
++ m = R_REG(&eir->clockcontrol_sb);
++ } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
++ pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK;
++ n = R_REG(&cc->clockcontrol_n);
++ if ((pll_type == PLL_TYPE2) ||
++ (pll_type == PLL_TYPE4) ||
++ (pll_type == PLL_TYPE6) ||
++ (pll_type == PLL_TYPE7))
++ m = R_REG(&cc->clockcontrol_mips);
++ else if (pll_type == PLL_TYPE5) {
++ rate = 200000000;
++ goto out;
++ }
++ else if (pll_type == PLL_TYPE3) {
++ if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID) { /* 5365 is also type3 */
++ rate = 200000000;
++ goto out;
++ } else
++ m = R_REG(&cc->clockcontrol_m2); /* 5350 uses m2 to control mips */
++ } else
++ m = R_REG(&cc->clockcontrol_sb);
++ } else
++ goto out;
++
++ // Added by Chen-I for 5365
++ if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID)
++ rate = 100000000;
++ else
++ /* calculate rate */
++ rate = sb_clock_rate(pll_type, n, m);
++
++ if (pll_type == PLL_TYPE6)
++ rate = SB2MIPS_T6(rate);
++
++out:
++ /* switch back to previous core */
++ sb_setcoreidx(sbh, idx);
++
++ return rate;
++}
++
++#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
++
++static void
++BCMINITFN(handler)(void)
++{
++ /* Step 11 */
++ __asm__ (
++ ".set\tmips32\n\t"
++ "ssnop\n\t"
++ "ssnop\n\t"
++ /* Disable interrupts */
++ /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */
++ "mfc0 $15, $12\n\t"
++ /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */
++ "li $14, -31746\n\t"
++ "and $15, $15, $14\n\t"
++ "mtc0 $15, $12\n\t"
++ "eret\n\t"
++ "nop\n\t"
++ "nop\n\t"
++ ".set\tmips0"
++ );
++}
++
++/* The following MUST come right after handler() */
++static void
++BCMINITFN(afterhandler)(void)
++{
++}
++
++/*
++ * Set the MIPS, backplane and PCI clocks as closely as possible.
++ */
++bool
++BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 pciclock)
++{
++ extifregs_t *eir = NULL;
++ chipcregs_t *cc = NULL;
++ mipsregs_t *mipsr = NULL;
++ volatile uint32 *clockcontrol_n, *clockcontrol_sb, *clockcontrol_pci, *clockcontrol_m2;
++ uint32 orig_n, orig_sb, orig_pci, orig_m2, orig_mips, orig_ratio_parm, orig_ratio_cfg;
++ uint32 pll_type, sync_mode;
++ uint ic_size, ic_lsize;
++ uint idx, i;
++ typedef struct {
++ uint32 mipsclock;
++ uint16 n;
++ uint32 sb;
++ uint32 pci33;
++ uint32 pci25;
++ } n3m_table_t;
++ static n3m_table_t BCMINITDATA(type1_table)[] = {
++ { 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011 }, /* 96.000 32.000 24.000 */
++ { 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011 }, /* 100.000 33.333 25.000 */
++ { 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009 }, /* 104.000 31.200 24.960 */
++ { 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802 }, /* 108.000 32.400 24.923 */
++ { 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403 }, /* 112.000 32.000 24.889 */
++ { 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011 }, /* 115.200 32.000 24.000 */
++ { 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011 }, /* 120.000 30.000 24.000 */
++ { 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009 }, /* 124.800 31.200 24.960 */
++ { 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305 }, /* 128.000 32.000 24.000 */
++ { 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305 }, /* 132.000 33.000 24.750 */
++ { 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603 }, /* 136.000 32.640 24.727 */
++ { 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02 }, /* 140.000 30.000 24.706 */
++ { 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021 }, /* 144.000 30.857 24.686 */
++ { 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605 }, /* 150.857 33.000 24.000 */
++ { 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02 }, /* 152.000 32.571 24.000 */
++ { 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009 }, /* 156.000 31.200 24.960 */
++ { 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309 }, /* 160.000 32.000 24.000 */
++ { 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603 }, /* 163.200 32.640 24.727 */
++ { 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403 }, /* 168.000 32.000 24.889 */
++ { 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602 }, /* 176.000 33.000 24.000 */
++ };
++ typedef struct {
++ uint32 mipsclock;
++ uint16 n;
++ uint32 m2; /* that is the clockcontrol_m2 */
++ } type3_table_t;
++ static type3_table_t type3_table[] = { /* for 5350, mips clock is always double sb clock */
++ { 150000000, 0x311, 0x4020005 },
++ { 200000000, 0x311, 0x4020003 },
++ };
++ typedef struct {
++ uint32 mipsclock;
++ uint32 sbclock;
++ uint16 n;
++ uint32 sb;
++ uint32 pci33;
++ uint32 m2;
++ uint32 m3;
++ uint32 ratio_cfg;
++ uint32 ratio_parm;
++ } n4m_table_t;
++
++ static n4m_table_t BCMINITDATA(type2_table)[] = {
++ { 180000000, 80000000, 0x0403, 0x01010000, 0x01020300, 0x01020600, 0x05000100, 8, 0x012a00a9 },
++ { 180000000, 90000000, 0x0403, 0x01000100, 0x01020300, 0x01000100, 0x05000100, 11, 0x0aaa0555 },
++ { 200000000, 100000000, 0x0303, 0x02010000, 0x02040001, 0x02010000, 0x06000001, 11, 0x0aaa0555 },
++ { 211200000, 105600000, 0x0902, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
++ { 220800000, 110400000, 0x1500, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
++ { 230400000, 115200000, 0x0604, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
++ { 234000000, 104000000, 0x0b01, 0x01010000, 0x01010700, 0x01020600, 0x05000100, 8, 0x012a00a9 },
++ { 240000000, 120000000, 0x0803, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
++ { 252000000, 126000000, 0x0504, 0x01000100, 0x01020500, 0x01000100, 0x05000100, 11, 0x0aaa0555 },
++ { 264000000, 132000000, 0x0903, 0x01000200, 0x01020700, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
++ { 270000000, 120000000, 0x0703, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
++ { 276000000, 122666666, 0x1500, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
++ { 280000000, 140000000, 0x0503, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555 },
++ { 288000000, 128000000, 0x0604, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
++ { 288000000, 144000000, 0x0404, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555 },
++ { 300000000, 133333333, 0x0803, 0x01010000, 0x01020600, 0x01020600, 0x05000100, 8, 0x012a00a9 },
++ { 300000000, 150000000, 0x0803, 0x01000100, 0x01020600, 0x01000100, 0x05000100, 11, 0x0aaa0555 }
++ };
++
++ static n4m_table_t BCMINITDATA(type4_table)[] = {
++ { 192000000, 96000000, 0x0702, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
++ { 198000000, 99000000, 0x0603, 0x11020005, 0x11030011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
++ { 200000000, 100000000, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, 0x0aaa0555 },
++ { 204000000, 102000000, 0x0c02, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
++ { 208000000, 104000000, 0x0802, 0x11030002, 0x11090005, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
++ { 210000000, 105000000, 0x0209, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
++ { 216000000, 108000000, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
++ { 224000000, 112000000, 0x0205, 0x11030002, 0x02002103, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
++ { 228000000, 101333333, 0x0e02, 0x11030003, 0x11210005, 0x01030305, 0x04000005, 8, 0x012a00a9 },
++ { 228000000, 114000000, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
++ { 240000000, 102857143, 0x0109, 0x04000021, 0x01050203, 0x11030021, 0x04000003, 13, 0x254a14a9 },
++ { 240000000, 120000000, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
++ { 252000000, 100800000, 0x0203, 0x04000009, 0x11050005, 0x02000209, 0x04000002, 9, 0x02520129 },
++ { 252000000, 126000000, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, 0x0aaa0555 },
++ { 264000000, 132000000, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, 0x0aaa0555 },
++ { 272000000, 116571428, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003, 13, 0x254a14a9 },
++ { 280000000, 120000000, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, 0x254a14a9 },
++ { 288000000, 123428571, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, 0x254a14a9 },
++ { 300000000, 120000000, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002, 9, 0x02520129 },
++ { 300000000, 150000000, 0x0009, 0x04000005, 0x01030203, 0x04000005, 0x04000002, 11, 0x0aaa0555 }
++ };
++
++ static n4m_table_t BCMINITDATA(type7_table)[] = {
++ { 183333333, 91666666, 0x0605, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
++ { 187500000, 93750000, 0x0a03, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
++ { 196875000, 98437500, 0x1003, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
++ { 200000000, 100000000, 0x0311, 0x04000011, 0x11030011, 0x04000009, 0x04000003, 11, 0x0aaa0555 },
++ { 200000000, 100000000, 0x0311, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, 0x0aaa0555 },
++ { 206250000, 103125000, 0x1103, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
++ { 212500000, 106250000, 0x0c05, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
++ { 215625000, 107812500, 0x1203, 0x11090009, 0x11050005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
++ { 216666666, 108333333, 0x0805, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
++ { 225000000, 112500000, 0x0d03, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
++ { 233333333, 116666666, 0x0905, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
++ { 237500000, 118750000, 0x0e05, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
++ { 240000000, 120000000, 0x0b11, 0x11020009, 0x11210009, 0x11020009, 0x04000009, 11, 0x0aaa0555 },
++ { 250000000, 125000000, 0x0f03, 0x11020003, 0x11210003, 0x11020003, 0x04000003, 11, 0x0aaa0555 }
++ };
++
++ ulong start, end, dst;
++ bool ret = FALSE;
++
++ /* get index of the current core */
++ idx = sb_coreidx(sbh);
++ clockcontrol_m2 = NULL;
++
++ /* switch to extif or chipc core */
++ if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
++ pll_type = PLL_TYPE1;
++ clockcontrol_n = &eir->clockcontrol_n;
++ clockcontrol_sb = &eir->clockcontrol_sb;
++ clockcontrol_pci = &eir->clockcontrol_pci;
++ clockcontrol_m2 = &cc->clockcontrol_m2;
++ } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
++ pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK;
++ if (pll_type == PLL_TYPE6) {
++ clockcontrol_n = NULL;
++ clockcontrol_sb = NULL;
++ clockcontrol_pci = NULL;
++ } else {
++ clockcontrol_n = &cc->clockcontrol_n;
++ clockcontrol_sb = &cc->clockcontrol_sb;
++ clockcontrol_pci = &cc->clockcontrol_pci;
++ clockcontrol_m2 = &cc->clockcontrol_m2;
++ }
++ } else
++ goto done;
++
++ if (pll_type == PLL_TYPE6) {
++ /* Silence compilers */
++ orig_n = orig_sb = orig_pci = 0;
++ } else {
++ /* Store the current clock register values */
++ orig_n = R_REG(clockcontrol_n);
++ orig_sb = R_REG(clockcontrol_sb);
++ orig_pci = R_REG(clockcontrol_pci);
++ }
++
++ if (pll_type == PLL_TYPE1) {
++ /* Keep the current PCI clock if not specified */
++ if (pciclock == 0) {
++ pciclock = sb_clock_rate(pll_type, R_REG(clockcontrol_n), R_REG(clockcontrol_pci));
++ pciclock = (pciclock <= 25000000) ? 25000000 : 33000000;
++ }
++
++ /* Search for the closest MIPS clock less than or equal to a preferred value */
++ for (i = 0; i < ARRAYSIZE(BCMINIT(type1_table)); i++) {
++ ASSERT(BCMINIT(type1_table)[i].mipsclock ==
++ sb_clock_rate(pll_type, BCMINIT(type1_table)[i].n, BCMINIT(type1_table)[i].sb));
++ if (BCMINIT(type1_table)[i].mipsclock > mipsclock)
++ break;
++ }
++ if (i == 0) {
++ ret = FALSE;
++ goto done;
++ } else {
++ ret = TRUE;
++ i--;
++ }
++ ASSERT(BCMINIT(type1_table)[i].mipsclock <= mipsclock);
++
++ /* No PLL change */
++ if ((orig_n == BCMINIT(type1_table)[i].n) &&
++ (orig_sb == BCMINIT(type1_table)[i].sb) &&
++ (orig_pci == BCMINIT(type1_table)[i].pci33))
++ goto done;
++
++ /* Set the PLL controls */
++ W_REG(clockcontrol_n, BCMINIT(type1_table)[i].n);
++ W_REG(clockcontrol_sb, BCMINIT(type1_table)[i].sb);
++ if (pciclock == 25000000)
++ W_REG(clockcontrol_pci, BCMINIT(type1_table)[i].pci25);
++ else
++ W_REG(clockcontrol_pci, BCMINIT(type1_table)[i].pci33);
++
++ /* Reset */
++ sb_watchdog(sbh, 1);
++
++ while (1);
++ } else if ((pll_type == PLL_TYPE3) &&
++ (BCMINIT(sb_chip)(sbh) != BCM5365_DEVICE_ID)) {
++ /* 5350 */
++ /* Search for the closest MIPS clock less than or equal to a preferred value */
++
++ for (i = 0; i < ARRAYSIZE(type3_table); i++) {
++ if (type3_table[i].mipsclock > mipsclock)
++ break;
++ }
++ if (i == 0) {
++ ret = FALSE;
++ goto done;
++ } else {
++ ret = TRUE;
++ i--;
++ }
++ ASSERT(type3_table[i].mipsclock <= mipsclock);
++
++ /* No PLL change */
++ orig_m2 = R_REG(&cc->clockcontrol_m2);
++ if ((orig_n == type3_table[i].n) &&
++ (orig_m2 == type3_table[i].m2)) {
++ goto done;
++ }
++
++ /* Set the PLL controls */
++ W_REG(clockcontrol_n, type3_table[i].n);
++ W_REG(clockcontrol_m2, type3_table[i].m2);
++
++ /* Reset */
++ sb_watchdog(sbh, 1);
++ while (1);
++ } else if ((pll_type == PLL_TYPE2) ||
++ (pll_type == PLL_TYPE4) ||
++ (pll_type == PLL_TYPE6) ||
++ (pll_type == PLL_TYPE7)) {
++ n4m_table_t *table = NULL, *te;
++ uint tabsz = 0;
++
++ ASSERT(cc);
++
++ orig_mips = R_REG(&cc->clockcontrol_mips);
++
++ if (pll_type == PLL_TYPE6) {
++ uint32 new_mips = 0;
++
++ ret = TRUE;
++ if (mipsclock <= SB2MIPS_T6(CC_T6_M1))
++ new_mips = CC_T6_MMASK;
++
++ if (orig_mips == new_mips)
++ goto done;
++
++ W_REG(&cc->clockcontrol_mips, new_mips);
++ goto end_fill;
++ }
++
++ if (pll_type == PLL_TYPE2) {
++ table = BCMINIT(type2_table);
++ tabsz = ARRAYSIZE(BCMINIT(type2_table));
++ } else if (pll_type == PLL_TYPE4) {
++ table = BCMINIT(type4_table);
++ tabsz = ARRAYSIZE(BCMINIT(type4_table));
++ } else if (pll_type == PLL_TYPE7) {
++ table = BCMINIT(type7_table);
++ tabsz = ARRAYSIZE(BCMINIT(type7_table));
++ } else
++ ASSERT("No table for plltype" == NULL);
++
++ /* Store the current clock register values */
++ orig_m2 = R_REG(&cc->clockcontrol_m2);
++ orig_ratio_parm = 0;
++ orig_ratio_cfg = 0;
++
++ /* Look up current ratio */
++ for (i = 0; i < tabsz; i++) {
++ if ((orig_n == table[i].n) &&
++ (orig_sb == table[i].sb) &&
++ (orig_pci == table[i].pci33) &&
++ (orig_m2 == table[i].m2) &&
++ (orig_mips == table[i].m3)) {
++ orig_ratio_parm = table[i].ratio_parm;
++ orig_ratio_cfg = table[i].ratio_cfg;
++ break;
++ }
++ }
++
++ /* Search for the closest MIPS clock greater or equal to a preferred value */
++ for (i = 0; i < tabsz; i++) {
++ ASSERT(table[i].mipsclock ==
++ sb_clock_rate(pll_type, table[i].n, table[i].m3));
++ if ((mipsclock <= table[i].mipsclock) &&
++ ((sbclock == 0) || (sbclock <= table[i].sbclock)))
++ break;
++ }
++ if (i == tabsz) {
++ ret = FALSE;
++ goto done;
++ } else {
++ te = &table[i];
++ ret = TRUE;
++ }
++
++ /* No PLL change */
++ if ((orig_n == te->n) &&
++ (orig_sb == te->sb) &&
++ (orig_pci == te->pci33) &&
++ (orig_m2 == te->m2) &&
++ (orig_mips == te->m3))
++ goto done;
++
++ /* Set the PLL controls */
++ W_REG(clockcontrol_n, te->n);
++ W_REG(clockcontrol_sb, te->sb);
++ W_REG(clockcontrol_pci, te->pci33);
++ W_REG(&cc->clockcontrol_m2, te->m2);
++ W_REG(&cc->clockcontrol_mips, te->m3);
++
++ /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */
++ if ((pll_type == PLL_TYPE7) &&
++ (te->sb != te->m2) &&
++ (sb_clock_rate(pll_type, te->n, te->m2) == 120000000))
++ W_REG(&cc->chipcontrol, R_REG(&cc->chipcontrol) | 0x100);
++
++ /* No ratio change */
++ if (orig_ratio_parm == te->ratio_parm)
++ goto end_fill;
++
++ icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize);
++
++ /* Preload the code into the cache */
++ start = ((ulong) &&start_fill) & ~(ic_lsize - 1);
++ end = ((ulong) &&end_fill + (ic_lsize - 1)) & ~(ic_lsize - 1);
++ while (start < end) {
++ cache_op(start, Fill_I);
++ start += ic_lsize;
++ }
++
++ /* Copy the handler */
++ start = (ulong) &BCMINIT(handler);
++ end = (ulong) &BCMINIT(afterhandler);
++ dst = KSEG1ADDR(0x180);
++ for (i = 0; i < (end - start); i += 4)
++ *((ulong *)(dst + i)) = *((ulong *)(start + i));
++
++ /* Preload handler into the cache one line at a time */
++ for (i = 0; i < (end - start); i += 4)
++ cache_op(dst + i, Fill_I);
++
++ /* Clear BEV bit */
++ MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~ST0_BEV);
++
++ /* Enable interrupts */
++ MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) | (ALLINTS | ST0_IE));
++
++ /* Enable MIPS timer interrupt */
++ if (!(mipsr = sb_setcore(sbh, SB_MIPS, 0)) &&
++ !(mipsr = sb_setcore(sbh, SB_MIPS33, 0)))
++ ASSERT(mipsr);
++ W_REG(&mipsr->intmask, 1);
++
++ start_fill:
++ /* step 1, set clock ratios */
++ MTC0(C0_BROADCOM, 3, te->ratio_parm);
++ MTC0(C0_BROADCOM, 1, te->ratio_cfg);
++
++ /* step 2: program timer intr */
++ W_REG(&mipsr->timer, 100);
++ (void) R_REG(&mipsr->timer);
++
++ /* step 3, switch to async */
++ sync_mode = MFC0(C0_BROADCOM, 4);
++ MTC0(C0_BROADCOM, 4, 1 << 22);
++
++ /* step 4, set cfg active */
++ MTC0(C0_BROADCOM, 2, 0x9);
++
++
++ /* steps 5 & 6 */
++ __asm__ __volatile__ (
++ ".set\tmips3\n\t"
++ "wait\n\t"
++ ".set\tmips0"
++ );
++
++ /* step 7, clear cfg_active */
++ MTC0(C0_BROADCOM, 2, 0);
++
++ /* Additional Step: set back to orig sync mode */
++ MTC0(C0_BROADCOM, 4, sync_mode);
++
++ /* step 8, fake soft reset */
++ MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | 4);
++
++ end_fill:
++ /* step 9 set watchdog timer */
++ sb_watchdog(sbh, 20);
++ (void) R_REG(&cc->chipid);
++
++ /* step 11 */
++ __asm__ __volatile__ (
++ ".set\tmips3\n\t"
++ "sync\n\t"
++ "wait\n\t"
++ ".set\tmips0"
++ );
++ while (1);
++ }
++
++done:
++ /* switch back to previous core */
++ sb_setcoreidx(sbh, idx);
++
++ return ret;
++}
++
++/*
++ * This also must be run from the cache on 47xx
++ * so there are no mips core BIU ops in progress
++ * when the PFC is enabled.
++ */
++
++static void
++BCMINITFN(_enable_pfc)(uint32 mode)
++{
++ /* write range */
++ *(volatile uint32 *)PFC_CR1 = 0xffff0000;
++
++ /* enable */
++ *(volatile uint32 *)PFC_CR0 = mode;
++}
++
++void
++BCMINITFN(enable_pfc)(uint32 mode)
++{
++ ulong start, end;
++ int i;
++
++ /* If auto then choose the correct mode for this
++ platform, currently we only ever select one mode */
++ if (mode == PFC_AUTO)
++ mode = PFC_INST;
++
++ /* enable prefetch cache if available */
++ if (MFC0(C0_BROADCOM, 0) & BRCM_PFC_AVAIL) {
++ start = (ulong) &BCMINIT(_enable_pfc);
++ end = (ulong) &BCMINIT(enable_pfc);
++
++ /* Preload handler into the cache one line at a time */
++ for (i = 0; i < (end - start); i += 4)
++ cache_op(start + i, Fill_I);
++
++ BCMINIT(_enable_pfc)(mode);
++ }
++}
++
++/* returns the ncdl value to be programmed into sdram_ncdl for calibration */
++uint32
++BCMINITFN(sb_memc_get_ncdl)(sb_t *sbh)
++{
++ sbmemcregs_t *memc;
++ uint32 ret = 0;
++ uint32 config, rd, wr, misc, dqsg, cd, sm, sd;
++ uint idx, rev;
++
++ idx = sb_coreidx(sbh);
++
++ memc = (sbmemcregs_t *)sb_setcore(sbh, SB_MEMC, 0);
++ if (memc == 0)
++ goto out;
++
++ rev = sb_corerev(sbh);
++
++ config = R_REG(&memc->config);
++ wr = R_REG(&memc->wrncdlcor);
++ rd = R_REG(&memc->rdncdlcor);
++ misc = R_REG(&memc->miscdlyctl);
++ dqsg = R_REG(&memc->dqsgatencdl);
++
++ rd &= MEMC_RDNCDLCOR_RD_MASK;
++ wr &= MEMC_WRNCDLCOR_WR_MASK;
++ dqsg &= MEMC_DQSGATENCDL_G_MASK;
++
++ if (config & MEMC_CONFIG_DDR) {
++ ret = (wr << 16) | (rd << 8) | dqsg;
++ } else {
++ if (rev > 0)
++ cd = rd;
++ else
++ cd = (rd == MEMC_CD_THRESHOLD) ? rd : (wr + MEMC_CD_THRESHOLD);
++ sm = (misc & MEMC_MISC_SM_MASK) >> MEMC_MISC_SM_SHIFT;
++ sd = (misc & MEMC_MISC_SD_MASK) >> MEMC_MISC_SD_SHIFT;
++ ret = (sm << 16) | (sd << 8) | cd;
++ }
++
++out:
++ /* switch back to previous core */
++ sb_setcoreidx(sbh, idx);
++
++ return ret;
++}
++
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/broadcom/sbpci.c linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/sbpci.c
+--- linux-2.6.17/arch/mips/bcm947xx/broadcom/sbpci.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/sbpci.c 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,534 @@
++/*
++ * Low-Level PCI and SB support for BCM47xx
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#include <typedefs.h>
++#include <pcicfg.h>
++#include <bcmdevs.h>
++#include <sbconfig.h>
++#include <osl.h>
++#include <sbutils.h>
++#include <sbpci.h>
++#include <bcmendian.h>
++#include <bcmutils.h>
++#include <bcmnvram.h>
++#include <hndmips.h>
++
++/* Can free sbpci_init() memory after boot */
++#ifndef linux
++#define __init
++#endif
++
++/* Emulated configuration space */
++static pci_config_regs sb_config_regs[SB_MAXCORES];
++
++/* Banned cores */
++static uint16 pci_ban[32] = { 0 };
++static uint pci_banned = 0;
++
++/* CardBus mode */
++static bool cardbus = FALSE;
++
++/* Disable PCI host core */
++static bool pci_disabled = FALSE;
++
++/*
++ * Functions for accessing external PCI configuration space
++ */
++
++/* Assume one-hot slot wiring */
++#define PCI_SLOT_MAX 16
++
++static uint32
++config_cmd(sb_t *sbh, uint bus, uint dev, uint func, uint off)
++{
++ uint coreidx;
++ sbpciregs_t *regs;
++ uint32 addr = 0;
++
++ /* CardBusMode supports only one device */
++ if (cardbus && dev > 1)
++ return 0;
++
++ coreidx = sb_coreidx(sbh);
++ regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0);
++
++ /* Type 0 transaction */
++ if (bus == 1) {
++ /* Skip unwired slots */
++ if (dev < PCI_SLOT_MAX) {
++ /* Slide the PCI window to the appropriate slot */
++ W_REG(&regs->sbtopci1, SBTOPCI_CFG0 | ((1 << (dev + 16)) & SBTOPCI1_MASK));
++ addr = SB_PCI_CFG | ((1 << (dev + 16)) & ~SBTOPCI1_MASK) |
++ (func << 8) | (off & ~3);
++ }
++ }
++
++ /* Type 1 transaction */
++ else {
++ W_REG(&regs->sbtopci1, SBTOPCI_CFG1);
++ addr = SB_PCI_CFG | (bus << 16) | (dev << 11) | (func << 8) | (off & ~3);
++ }
++
++ sb_setcoreidx(sbh, coreidx);
++
++ return addr;
++}
++
++static int
++extpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
++{
++ uint32 addr, *reg = NULL, val;
++ int ret = 0;
++
++ if (pci_disabled ||
++ !(addr = config_cmd(sbh, bus, dev, func, off)) ||
++ !(reg = (uint32 *) REG_MAP(addr, len)) ||
++ BUSPROBE(val, reg))
++ val = 0xffffffff;
++
++ val >>= 8 * (off & 3);
++ if (len == 4)
++ *((uint32 *) buf) = val;
++ else if (len == 2)
++ *((uint16 *) buf) = (uint16) val;
++ else if (len == 1)
++ *((uint8 *) buf) = (uint8) val;
++ else
++ ret = -1;
++
++ if (reg)
++ REG_UNMAP(reg);
++
++ return ret;
++}
++
++static int
++extpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
++{
++ uint32 addr, *reg = NULL, val;
++ int ret = 0;
++
++ if (pci_disabled ||
++ !(addr = config_cmd(sbh, bus, dev, func, off)) ||
++ !(reg = (uint32 *) REG_MAP(addr, len)) ||
++ BUSPROBE(val, reg))
++ goto done;
++
++ if (len == 4)
++ val = *((uint32 *) buf);
++ else if (len == 2) {
++ val &= ~(0xffff << (8 * (off & 3)));
++ val |= *((uint16 *) buf) << (8 * (off & 3));
++ } else if (len == 1) {
++ val &= ~(0xff << (8 * (off & 3)));
++ val |= *((uint8 *) buf) << (8 * (off & 3));
++ } else
++ ret = -1;
++
++ W_REG(reg, val);
++
++ done:
++ if (reg)
++ REG_UNMAP(reg);
++
++ return ret;
++}
++
++/*
++ * Functions for accessing translated SB configuration space
++ */
++
++static int
++sb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
++{
++ pci_config_regs *cfg;
++
++ if (dev >= SB_MAXCORES || (off + len) > sizeof(pci_config_regs))
++ return -1;
++ cfg = &sb_config_regs[dev];
++
++ ASSERT(ISALIGNED(off, len));
++ ASSERT(ISALIGNED((uintptr)buf, len));
++
++ if (len == 4)
++ *((uint32 *) buf) = ltoh32(*((uint32 *)((ulong) cfg + off)));
++ else if (len == 2)
++ *((uint16 *) buf) = ltoh16(*((uint16 *)((ulong) cfg + off)));
++ else if (len == 1)
++ *((uint8 *) buf) = *((uint8 *)((ulong) cfg + off));
++ else
++ return -1;
++
++ return 0;
++}
++
++static int
++sb_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
++{
++ uint coreidx, n;
++ void *regs;
++ sbconfig_t *sb;
++ pci_config_regs *cfg;
++
++ if (dev >= SB_MAXCORES || (off + len) > sizeof(pci_config_regs))
++ return -1;
++ cfg = &sb_config_regs[dev];
++
++ ASSERT(ISALIGNED(off, len));
++ ASSERT(ISALIGNED((uintptr)buf, len));
++
++ /* Emulate BAR sizing */
++ if (off >= OFFSETOF(pci_config_regs, base[0]) && off <= OFFSETOF(pci_config_regs, base[3]) &&
++ len == 4 && *((uint32 *) buf) == ~0) {
++ coreidx = sb_coreidx(sbh);
++ if ((regs = sb_setcoreidx(sbh, dev))) {
++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
++ /* Highest numbered address match register */
++ n = (R_REG(&sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT;
++ if (off == OFFSETOF(pci_config_regs, base[0]))
++ cfg->base[0] = ~(sb_size(R_REG(&sb->sbadmatch0)) - 1);
++#if 0
++ else if (off == OFFSETOF(pci_config_regs, base[1]) && n >= 1)
++ cfg->base[1] = ~(sb_size(R_REG(&sb->sbadmatch1)) - 1);
++ else if (off == OFFSETOF(pci_config_regs, base[2]) && n >= 2)
++ cfg->base[2] = ~(sb_size(R_REG(&sb->sbadmatch2)) - 1);
++ else if (off == OFFSETOF(pci_config_regs, base[3]) && n >= 3)
++ cfg->base[3] = ~(sb_size(R_REG(&sb->sbadmatch3)) - 1);
++#endif
++ }
++ sb_setcoreidx(sbh, coreidx);
++ return 0;
++ }
++
++ if (len == 4)
++ *((uint32 *)((ulong) cfg + off)) = htol32(*((uint32 *) buf));
++ else if (len == 2)
++ *((uint16 *)((ulong) cfg + off)) = htol16(*((uint16 *) buf));
++ else if (len == 1)
++ *((uint8 *)((ulong) cfg + off)) = *((uint8 *) buf);
++ else
++ return -1;
++
++ return 0;
++}
++
++int
++sbpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
++{
++ if (bus == 0)
++ return sb_read_config(sbh, bus, dev, func, off, buf, len);
++ else
++ return extpci_read_config(sbh, bus, dev, func, off, buf, len);
++}
++
++int
++sbpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
++{
++ if (bus == 0)
++ return sb_write_config(sbh, bus, dev, func, off, buf, len);
++ else
++ return extpci_write_config(sbh, bus, dev, func, off, buf, len);
++}
++
++void
++sbpci_ban(uint16 core)
++{
++ if (pci_banned < ARRAYSIZE(pci_ban))
++ pci_ban[pci_banned++] = core;
++}
++
++static int
++sbpci_init_pci(sb_t *sbh)
++{
++ uint chip, chiprev, chippkg, host;
++ uint32 boardflags;
++ sbpciregs_t *pci;
++ sbconfig_t *sb;
++ uint32 val;
++
++ chip = sb_chip(sbh);
++ chiprev = sb_chiprev(sbh);
++ chippkg = sb_chippkg(sbh);
++
++ if (!(pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0))) {
++ printf("PCI: no core\n");
++ pci_disabled = TRUE;
++ return -1;
++ }
++ sb_core_reset(sbh, 0);
++
++ boardflags = (uint32) getintvar(NULL, "boardflags");
++
++ if ((chip == BCM4310_DEVICE_ID) && (chiprev == 0))
++ pci_disabled = TRUE;
++
++ /*
++ * The 200-pin BCM4712 package does not bond out PCI. Even when
++ * PCI is bonded out, some boards may leave the pins
++ * floating.
++ */
++ if (((chip == BCM4712_DEVICE_ID) &&
++ ((chippkg == BCM4712SMALL_PKG_ID) ||
++ (chippkg == BCM4712MID_PKG_ID))) ||
++ (chip == BCM5350_DEVICE_ID) ||
++ (boardflags & BFL_NOPCI))
++ pci_disabled = TRUE;
++
++ /*
++ * If the PCI core should not be touched (disabled, not bonded
++ * out, or pins floating), do not even attempt to access core
++ * registers. Otherwise, try to determine if it is in host
++ * mode.
++ */
++ if (pci_disabled)
++ host = 0;
++ else
++ host = !BUSPROBE(val, &pci->control);
++
++ if (!host) {
++ /* Disable PCI interrupts in client mode */
++ sb = (sbconfig_t *)((ulong) pci + SBCONFIGOFF);
++ W_REG(&sb->sbintvec, 0);
++
++ /* Disable the PCI bridge in client mode */
++ sbpci_ban(SB_PCI);
++ printf("PCI: Disabled\n");
++ } else {
++ /* Reset the external PCI bus and enable the clock */
++ W_REG(&pci->control, 0x5); /* enable the tristate drivers */
++ W_REG(&pci->control, 0xd); /* enable the PCI clock */
++ OSL_DELAY(150); /* delay > 100 us */
++ W_REG(&pci->control, 0xf); /* deassert PCI reset */
++ W_REG(&pci->arbcontrol, PCI_INT_ARB); /* use internal arbiter */
++ OSL_DELAY(1); /* delay 1 us */
++
++ /* Enable CardBusMode */
++ cardbus = nvram_match("cardbus", "1");
++ if (cardbus) {
++ printf("PCI: Enabling CardBus\n");
++ /* GPIO 1 resets the CardBus device on bcm94710ap */
++ sb_gpioout(sbh, 1, 1, GPIO_DRV_PRIORITY);
++ sb_gpioouten(sbh, 1, 1, GPIO_DRV_PRIORITY);
++ W_REG(&pci->sprom[0], R_REG(&pci->sprom[0]) | 0x400);
++ }
++
++ /* 64 MB I/O access window */
++ W_REG(&pci->sbtopci0, SBTOPCI_IO);
++ /* 64 MB configuration access window */
++ W_REG(&pci->sbtopci1, SBTOPCI_CFG0);
++ /* 1 GB memory access window */
++ W_REG(&pci->sbtopci2, SBTOPCI_MEM | SB_PCI_DMA);
++
++ /* Enable PCI bridge BAR0 prefetch and burst */
++ val = 6;
++ sbpci_write_config(sbh, 1, 0, 0, PCI_CFG_CMD, &val, sizeof(val));
++
++ /* Enable PCI interrupts */
++ W_REG(&pci->intmask, PCI_INTA);
++ }
++
++ return 0;
++}
++
++static int
++sbpci_init_cores(sb_t *sbh)
++{
++ uint chip, chiprev, chippkg, coreidx, i;
++ sbconfig_t *sb;
++ pci_config_regs *cfg;
++ void *regs;
++ char varname[8];
++ uint wlidx = 0;
++ uint16 vendor, core;
++ uint8 class, subclass, progif;
++ uint32 val;
++ uint32 sbips_int_mask[] = { 0, SBIPS_INT1_MASK, SBIPS_INT2_MASK, SBIPS_INT3_MASK, SBIPS_INT4_MASK };
++ uint32 sbips_int_shift[] = { 0, 0, SBIPS_INT2_SHIFT, SBIPS_INT3_SHIFT, SBIPS_INT4_SHIFT };
++
++ chip = sb_chip(sbh);
++ chiprev = sb_chiprev(sbh);
++ chippkg = sb_chippkg(sbh);
++ coreidx = sb_coreidx(sbh);
++
++ /* Scan the SB bus */
++ bzero(sb_config_regs, sizeof(sb_config_regs));
++ for (cfg = sb_config_regs; cfg < &sb_config_regs[SB_MAXCORES]; cfg++) {
++ cfg->vendor = 0xffff;
++ if (!(regs = sb_setcoreidx(sbh, cfg - sb_config_regs)))
++ continue;
++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
++
++ /* Read ID register and parse vendor and core */
++ val = R_REG(&sb->sbidhigh);
++ vendor = (val & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT;
++ core = (val & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
++ progif = 0;
++
++ /* Check if this core is banned */
++ for (i = 0; i < pci_banned; i++)
++ if (core == pci_ban[i])
++ break;
++ if (i < pci_banned)
++ continue;
++
++ /* Known vendor translations */
++ switch (vendor) {
++ case SB_VEND_BCM:
++ vendor = VENDOR_BROADCOM;
++ break;
++ }
++
++ /* Determine class based on known core codes */
++ switch (core) {
++ case SB_ILINE20:
++ class = PCI_CLASS_NET;
++ subclass = PCI_NET_ETHER;
++ core = BCM47XX_ILINE_ID;
++ break;
++ case SB_ILINE100:
++ class = PCI_CLASS_NET;
++ subclass = PCI_NET_ETHER;
++ core = BCM4610_ILINE_ID;
++ break;
++ case SB_ENET:
++ class = PCI_CLASS_NET;
++ subclass = PCI_NET_ETHER;
++ core = BCM47XX_ENET_ID;
++ break;
++ case SB_SDRAM:
++ case SB_MEMC:
++ class = PCI_CLASS_MEMORY;
++ subclass = PCI_MEMORY_RAM;
++ break;
++ case SB_PCI:
++#if 0
++ class = PCI_CLASS_BRIDGE;
++ subclass = PCI_BRIDGE_PCI;
++ break;
++#endif
++ case SB_MIPS:
++ case SB_MIPS33:
++ class = PCI_CLASS_CPU;
++ subclass = PCI_CPU_MIPS;
++ break;
++ case SB_CODEC:
++ class = PCI_CLASS_COMM;
++ subclass = PCI_COMM_MODEM;
++ core = BCM47XX_V90_ID;
++ break;
++ case SB_USB:
++ class = PCI_CLASS_SERIAL;
++ subclass = PCI_SERIAL_USB;
++ progif = 0x10; /* OHCI */
++ core = BCM47XX_USB_ID;
++ break;
++ case SB_USB11H:
++ class = PCI_CLASS_SERIAL;
++ subclass = PCI_SERIAL_USB;
++ progif = 0x10; /* OHCI */
++ core = BCM47XX_USBH_ID;
++ break;
++ case SB_USB11D:
++ class = PCI_CLASS_SERIAL;
++ subclass = PCI_SERIAL_USB;
++ core = BCM47XX_USBD_ID;
++ break;
++ case SB_IPSEC:
++ class = PCI_CLASS_CRYPT;
++ subclass = PCI_CRYPT_NETWORK;
++ core = BCM47XX_IPSEC_ID;
++ break;
++ case SB_ROBO:
++ class = PCI_CLASS_NET;
++ subclass = PCI_NET_OTHER;
++ core = BCM47XX_ROBO_ID;
++ break;
++ case SB_EXTIF:
++ case SB_CC:
++ class = PCI_CLASS_MEMORY;
++ subclass = PCI_MEMORY_FLASH;
++ break;
++ case SB_D11:
++ class = PCI_CLASS_NET;
++ subclass = PCI_NET_OTHER;
++ /* Let an nvram variable override this */
++ sprintf(varname, "wl%did", wlidx);
++ wlidx++;
++ if ((core = getintvar(NULL, varname)) == 0) {
++ if (chip == BCM4712_DEVICE_ID) {
++ if (chippkg == BCM4712SMALL_PKG_ID)
++ core = BCM4306_D11G_ID;
++ else
++ core = BCM4306_D11DUAL_ID;
++ } else {
++ /* 4310 */
++ core = BCM4310_D11B_ID;
++ }
++ }
++ break;
++
++ default:
++ class = subclass = progif = 0xff;
++ break;
++ }
++
++ /* Supported translations */
++ cfg->vendor = htol16(vendor);
++ cfg->device = htol16(core);
++ cfg->rev_id = chiprev;
++ cfg->prog_if = progif;
++ cfg->sub_class = subclass;
++ cfg->base_class = class;
++ cfg->base[0] = htol32(sb_base(R_REG(&sb->sbadmatch0)));
++ cfg->base[1] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch1)));
++ cfg->base[2] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch2)));
++ cfg->base[3] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch3)));
++ cfg->base[4] = 0;
++ cfg->base[5] = 0;
++ if (class == PCI_CLASS_BRIDGE && subclass == PCI_BRIDGE_PCI)
++ cfg->header_type = PCI_HEADER_BRIDGE;
++ else
++ cfg->header_type = PCI_HEADER_NORMAL;
++ /* Save core interrupt flag */
++ cfg->int_pin = R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK;
++ /* Default to MIPS shared interrupt 0 */
++ cfg->int_line = 0;
++ /* MIPS sbipsflag maps core interrupt flags to interrupts 1 through 4 */
++ if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
++ (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
++ val = R_REG(&sb->sbipsflag);
++ for (cfg->int_line = 1; cfg->int_line <= 4; cfg->int_line++) {
++ if (((val & sbips_int_mask[cfg->int_line]) >> sbips_int_shift[cfg->int_line]) == cfg->int_pin)
++ break;
++ }
++ if (cfg->int_line > 4)
++ cfg->int_line = 0;
++ }
++ /* Emulated core */
++ *((uint32 *) &cfg->sprom_control) = 0xffffffff;
++ }
++
++ sb_setcoreidx(sbh, coreidx);
++ return 0;
++}
++
++int __init
++sbpci_init(sb_t *sbh)
++{
++ sbpci_init_pci(sbh);
++ sbpci_init_cores(sbh);
++ return 0;
++}
++
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/broadcom/sbutils.c linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/sbutils.c
+--- linux-2.6.17/arch/mips/bcm947xx/broadcom/sbutils.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/sbutils.c 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,2370 @@
++/*
++ * Misc utility routines for accessing chip-specific features
++ * of the SiliconBackplane-based Broadcom chips.
++ *
++ * Copyright 2005, 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.
++ * $Id$
++ */
++
++#include <typedefs.h>
++#include <osl.h>
++#include <sbutils.h>
++#include <bcmutils.h>
++#include <bcmdevs.h>
++#include <sbconfig.h>
++#include <sbchipc.h>
++#include <sbpci.h>
++#include <pcicfg.h>
++#include <sbextif.h>
++#include <bcmsrom.h>
++
++/* debug/trace */
++#define SB_ERROR(args)
++
++
++typedef uint32 (*sb_intrsoff_t)(void *intr_arg);
++typedef void (*sb_intrsrestore_t)(void *intr_arg, uint32 arg);
++typedef bool (*sb_intrsenabled_t)(void *intr_arg);
++
++/* misc sb info needed by some of the routines */
++typedef struct sb_info {
++
++ struct sb_pub sb; /* back plane public state(must be first field of sb_info */
++
++ void *osh; /* osl os handle */
++ void *sdh; /* bcmsdh handle */
++
++ void *curmap; /* current regs va */
++ void *regs[SB_MAXCORES]; /* other regs va */
++
++ uint curidx; /* current core index */
++ uint dev_coreid; /* the core provides driver functions */
++
++ uint gpioidx; /* gpio control core index */
++ uint gpioid; /* gpio control coretype */
++
++ uint numcores; /* # discovered cores */
++ uint coreid[SB_MAXCORES]; /* id of each core */
++
++ void *intr_arg; /* interrupt callback function arg */
++ sb_intrsoff_t intrsoff_fn; /* function turns chip interrupts off */
++ sb_intrsrestore_t intrsrestore_fn; /* function restore chip interrupts */
++ sb_intrsenabled_t intrsenabled_fn; /* function to check if chip interrupts are enabled */
++
++} sb_info_t;
++
++/* local prototypes */
++static sb_info_t * BCMINIT(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs,
++ uint bustype, void *sdh, char **vars, int *varsz);
++static void BCMINIT(sb_scan)(sb_info_t *si);
++static uint sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val);
++static uint _sb_coreidx(sb_info_t *si);
++static uint sb_findcoreidx(sb_info_t *si, uint coreid, uint coreunit);
++static uint BCMINIT(sb_pcidev2chip)(uint pcidev);
++static uint BCMINIT(sb_chip2numcores)(uint chip);
++static int sb_pci_fixcfg(sb_info_t *si);
++
++/* delay needed between the mdio control/ mdiodata register data access */
++#define PR28829_DELAY() OSL_DELAY(10)
++
++
++/* global variable to indicate reservation/release of gpio's*/
++static uint32 sb_gpioreservation = 0;
++
++#define SB_INFO(sbh) (sb_info_t*)sbh
++#define SET_SBREG(sbh, r, mask, val) W_SBREG((sbh), (r), ((R_SBREG((sbh), (r)) & ~(mask)) | (val)))
++#define GOODCOREADDR(x) (((x) >= SB_ENUM_BASE) && ((x) <= SB_ENUM_LIM) && ISALIGNED((x), SB_CORE_SIZE))
++#define GOODREGS(regs) ((regs) && ISALIGNED((uintptr)(regs), SB_CORE_SIZE))
++#define REGS2SB(va) (sbconfig_t*) ((int8*)(va) + SBCONFIGOFF)
++#define GOODIDX(idx) (((uint)idx) < SB_MAXCORES)
++#define BADIDX (SB_MAXCORES+1)
++#define NOREV -1
++
++#define PCI(si) ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (si->sb.buscoretype == SB_PCI))
++
++/* sonicsrev */
++#define SONICS_2_2 (SBIDL_RV_2_2 >> SBIDL_RV_SHIFT)
++#define SONICS_2_3 (SBIDL_RV_2_3 >> SBIDL_RV_SHIFT)
++
++#define R_SBREG(sbh, sbr) sb_read_sbreg((sbh), (sbr))
++#define W_SBREG(sbh, sbr, v) sb_write_sbreg((sbh), (sbr), (v))
++#define AND_SBREG(sbh, sbr, v) W_SBREG((sbh), (sbr), (R_SBREG((sbh), (sbr)) & (v)))
++#define OR_SBREG(sbh, sbr, v) W_SBREG((sbh), (sbr), (R_SBREG((sbh), (sbr)) | (v)))
++
++/*
++ * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/
++ * after core switching to avoid invalid register accesss inside ISR.
++ */
++#define INTR_OFF(si, intr_val) \
++ if ((si)->intrsoff_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
++ intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); }
++#define INTR_RESTORE(si, intr_val) \
++ if ((si)->intrsrestore_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
++ (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); }
++
++/* dynamic clock control defines */
++#define LPOMINFREQ 25000 /* low power oscillator min */
++#define LPOMAXFREQ 43000 /* low power oscillator max */
++#define XTALMINFREQ 19800000 /* 20 MHz - 1% */
++#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */
++#define PCIMINFREQ 25000000 /* 25 MHz */
++#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */
++
++#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */
++#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */
++
++#define MIN_DUMPBUFLEN 32 /* debug */
++
++/* GPIO Based LED powersave defines */
++#define DEFAULT_GPIO_ONTIME 10
++#define DEFAULT_GPIO_OFFTIME 90
++
++#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME)
++
++static uint32
++sb_read_sbreg(sb_info_t *si, volatile uint32 *sbr)
++{
++ uint32 val = R_REG(sbr);
++
++ return (val);
++}
++
++static void
++sb_write_sbreg(sb_info_t *si, volatile uint32 *sbr, uint32 v)
++{
++ W_REG(sbr, v);
++}
++
++/* Using sb_kattach depends on SB_BUS support, either implicit */
++/* no limiting BCMBUSTYPE value) or explicit (value is SB_BUS). */
++#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SB_BUS)
++
++/* global kernel resource */
++static sb_info_t ksi;
++
++/* generic kernel variant of sb_attach() */
++sb_t *
++BCMINITFN(sb_kattach)()
++{
++ uint32 *regs;
++
++ if (ksi.curmap == NULL) {
++ uint32 cid;
++
++ regs = (uint32 *)REG_MAP(SB_ENUM_BASE, SB_CORE_SIZE);
++ cid = R_REG((uint32 *)regs);
++ if (((cid & CID_ID_MASK) == BCM4712_DEVICE_ID) &&
++ ((cid & CID_PKG_MASK) != BCM4712LARGE_PKG_ID) &&
++ ((cid & CID_REV_MASK) <= (3 << CID_REV_SHIFT))) {
++ uint32 *scc, val;
++
++ scc = (uint32 *)((uchar*)regs + OFFSETOF(chipcregs_t, slow_clk_ctl));
++ val = R_REG(scc);
++ SB_ERROR((" initial scc = 0x%x\n", val));
++ val |= SCC_SS_XTAL;
++ W_REG(scc, val);
++ }
++
++ if (BCMINIT(sb_doattach)(&ksi, BCM4710_DEVICE_ID, NULL, (void*)regs,
++ SB_BUS, NULL, NULL, NULL) == NULL) {
++ return NULL;
++ }
++ }
++
++ return (sb_t *)&ksi;
++}
++#endif
++
++static sb_info_t *
++BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs,
++ uint bustype, void *sdh, char **vars, int *varsz)
++{
++ uint origidx;
++ chipcregs_t *cc;
++ sbconfig_t *sb;
++ uint32 w;
++
++ ASSERT(GOODREGS(regs));
++
++ bzero((uchar*)si, sizeof (sb_info_t));
++
++ si->sb.buscoreidx = si->gpioidx = BADIDX;
++
++ si->osh = osh;
++ si->curmap = regs;
++ si->sdh = sdh;
++
++ /* check to see if we are a sb core mimic'ing a pci core */
++ if (bustype == PCI_BUS) {
++ if (OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof (uint32)) == 0xffffffff)
++ bustype = SB_BUS;
++ else
++ bustype = PCI_BUS;
++ }
++
++ si->sb.bustype = bustype;
++ if (si->sb.bustype != BUSTYPE(si->sb.bustype)) {
++ SB_ERROR(("sb_doattach: bus type %d does not match configured bus type %d\n",
++ si->sb.bustype, BUSTYPE(si->sb.bustype)));
++ return NULL;
++ }
++
++ /* kludge to enable the clock on the 4306 which lacks a slowclock */
++ if (BUSTYPE(si->sb.bustype) == PCI_BUS)
++ sb_clkctl_xtal(&si->sb, XTAL|PLL, ON);
++
++ if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
++ w = OSL_PCI_READ_CONFIG(osh, PCI_BAR0_WIN, sizeof (uint32));
++ if (!GOODCOREADDR(w))
++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, sizeof (uint32), SB_ENUM_BASE);
++ }
++
++ /* initialize current core index value */
++ si->curidx = _sb_coreidx(si);
++
++ if (si->curidx == BADIDX) {
++ SB_ERROR(("sb_doattach: bad core index\n"));
++ return NULL;
++ }
++
++ /* get sonics backplane revision */
++ sb = REGS2SB(si->curmap);
++ si->sb.sonicsrev = (R_SBREG(si, &(sb)->sbidlow) & SBIDL_RV_MASK) >> SBIDL_RV_SHIFT;
++
++ /* keep and reuse the initial register mapping */
++ origidx = si->curidx;
++ if (BUSTYPE(si->sb.bustype) == SB_BUS)
++ si->regs[origidx] = regs;
++
++ /* is core-0 a chipcommon core? */
++ si->numcores = 1;
++ cc = (chipcregs_t*) sb_setcoreidx(&si->sb, 0);
++ if (sb_coreid(&si->sb) != SB_CC)
++ cc = NULL;
++
++ /* determine chip id and rev */
++ if (cc) {
++ /* chip common core found! */
++ si->sb.chip = R_REG(&cc->chipid) & CID_ID_MASK;
++ si->sb.chiprev = (R_REG(&cc->chipid) & CID_REV_MASK) >> CID_REV_SHIFT;
++ si->sb.chippkg = (R_REG(&cc->chipid) & CID_PKG_MASK) >> CID_PKG_SHIFT;
++ } else {
++ /* no chip common core -- must convert device id to chip id */
++ if ((si->sb.chip = BCMINIT(sb_pcidev2chip)(devid)) == 0) {
++ SB_ERROR(("sb_doattach: unrecognized device id 0x%04x\n", devid));
++ sb_setcoreidx(&si->sb, origidx);
++ return NULL;
++ }
++ }
++
++ /* get chipcommon rev */
++ si->sb.ccrev = cc ? (int)sb_corerev(&si->sb) : NOREV;
++
++ /* determine numcores */
++ if (cc && ((si->sb.ccrev == 4) || (si->sb.ccrev >= 6)))
++ si->numcores = (R_REG(&cc->chipid) & CID_CC_MASK) >> CID_CC_SHIFT;
++ else
++ si->numcores = BCMINIT(sb_chip2numcores)(si->sb.chip);
++
++ /* return to original core */
++ sb_setcoreidx(&si->sb, origidx);
++
++ /* sanity checks */
++ ASSERT(si->sb.chip);
++
++ /* scan for cores */
++ BCMINIT(sb_scan)(si);
++
++ /* fixup necessary chip/core configurations */
++ if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
++ if (sb_pci_fixcfg(si)) {
++ SB_ERROR(("sb_doattach: sb_pci_fixcfg failed\n"));
++ return NULL;
++ }
++ }
++
++ /* srom_var_init() depends on sb_scan() info */
++ if (srom_var_init(si, si->sb.bustype, si->curmap, osh, vars, varsz)) {
++ SB_ERROR(("sb_doattach: srom_var_init failed: bad srom\n"));
++ return (NULL);
++ }
++
++ if (cc == NULL) {
++ /*
++ * The chip revision number is hardwired into all
++ * of the pci function config rev fields and is
++ * independent from the individual core revision numbers.
++ * For example, the "A0" silicon of each chip is chip rev 0.
++ */
++ if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
++ w = OSL_PCI_READ_CONFIG(osh, PCI_CFG_REV, sizeof (uint32));
++ si->sb.chiprev = w & 0xff;
++ } else
++ si->sb.chiprev = 0;
++ }
++
++ /* gpio control core is required */
++ if (!GOODIDX(si->gpioidx)) {
++ SB_ERROR(("sb_doattach: gpio control core not found\n"));
++ return NULL;
++ }
++
++ /* get boardtype and boardrev */
++ switch (BUSTYPE(si->sb.bustype)) {
++ case PCI_BUS:
++ /* do a pci config read to get subsystem id and subvendor id */
++ w = OSL_PCI_READ_CONFIG(osh, PCI_CFG_SVID, sizeof (uint32));
++ si->sb.boardvendor = w & 0xffff;
++ si->sb.boardtype = (w >> 16) & 0xffff;
++ break;
++
++ case SB_BUS:
++ case JTAG_BUS:
++ si->sb.boardvendor = VENDOR_BROADCOM;
++ if ((si->sb.boardtype = getintvar(NULL, "boardtype")) == 0)
++ si->sb.boardtype = 0xffff;
++ break;
++ }
++
++ if (si->sb.boardtype == 0) {
++ SB_ERROR(("sb_doattach: unknown board type\n"));
++ ASSERT(si->sb.boardtype);
++ }
++
++ /* setup the GPIO based LED powersave register */
++ if (si->sb.ccrev >= 16) {
++ w = getintvar(*vars, "gpiotimerval");
++ if (!w)
++ w = DEFAULT_GPIOTIMERVAL;
++ sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
++ }
++
++
++ return (si);
++}
++
++uint
++sb_coreid(sb_t *sbh)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++
++ si = SB_INFO(sbh);
++ sb = REGS2SB(si->curmap);
++
++ return ((R_SBREG(si, &(sb)->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT);
++}
++
++uint
++sb_coreidx(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return (si->curidx);
++}
++
++/* return current index of core */
++static uint
++_sb_coreidx(sb_info_t *si)
++{
++ sbconfig_t *sb;
++ uint32 sbaddr = 0;
++
++ ASSERT(si);
++
++ switch (BUSTYPE(si->sb.bustype)) {
++ case SB_BUS:
++ sb = REGS2SB(si->curmap);
++ sbaddr = sb_base(R_SBREG(si, &sb->sbadmatch0));
++ break;
++
++ case PCI_BUS:
++ sbaddr = OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof (uint32));
++ break;
++
++#ifdef BCMJTAG
++ case JTAG_BUS:
++ sbaddr = (uint32)si->curmap;
++ break;
++#endif /* BCMJTAG */
++
++ default:
++ ASSERT(0);
++ }
++
++ if (!GOODCOREADDR(sbaddr))
++ return BADIDX;
++
++ return ((sbaddr - SB_ENUM_BASE) / SB_CORE_SIZE);
++}
++
++uint
++sb_corevendor(sb_t *sbh)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++
++ si = SB_INFO(sbh);
++ sb = REGS2SB(si->curmap);
++
++ return ((R_SBREG(si, &(sb)->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT);
++}
++
++uint
++sb_corerev(sb_t *sbh)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++ uint sbidh;
++
++ si = SB_INFO(sbh);
++ sb = REGS2SB(si->curmap);
++ sbidh = R_SBREG(si, &(sb)->sbidhigh);
++
++ return (SBCOREREV(sbidh));
++}
++
++void *
++sb_osh(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return si->osh;
++}
++
++#define SBTML_ALLOW (SBTML_PE | SBTML_FGC | SBTML_FL_MASK)
++
++/* set/clear sbtmstatelow core-specific flags */
++uint32
++sb_coreflags(sb_t *sbh, uint32 mask, uint32 val)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++ uint32 w;
++
++ si = SB_INFO(sbh);
++ sb = REGS2SB(si->curmap);
++
++ ASSERT((val & ~mask) == 0);
++ ASSERT((mask & ~SBTML_ALLOW) == 0);
++
++ /* mask and set */
++ if (mask || val) {
++ w = (R_SBREG(si, &sb->sbtmstatelow) & ~mask) | val;
++ W_SBREG(si, &sb->sbtmstatelow, w);
++ }
++
++ /* return the new value */
++ return (R_SBREG(si, &sb->sbtmstatelow) & SBTML_ALLOW);
++}
++
++/* set/clear sbtmstatehigh core-specific flags */
++uint32
++sb_coreflagshi(sb_t *sbh, uint32 mask, uint32 val)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++ uint32 w;
++
++ si = SB_INFO(sbh);
++ sb = REGS2SB(si->curmap);
++
++ ASSERT((val & ~mask) == 0);
++ ASSERT((mask & ~SBTMH_FL_MASK) == 0);
++
++ /* mask and set */
++ if (mask || val) {
++ w = (R_SBREG(si, &sb->sbtmstatehigh) & ~mask) | val;
++ W_SBREG(si, &sb->sbtmstatehigh, w);
++ }
++
++ /* return the new value */
++ return (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_FL_MASK);
++}
++
++/* caller needs to take care of core-specific bist hazards */
++int
++sb_corebist(sb_t *sbh, uint coreid, uint coreunit)
++{
++ uint32 sblo;
++ uint coreidx;
++ sb_info_t *si;
++ int result = 0;
++
++ si = SB_INFO(sbh);
++
++ coreidx = sb_findcoreidx(si, coreid, coreunit);
++ if (!GOODIDX(coreidx))
++ result = BCME_ERROR;
++ else {
++ sblo = sb_corereg(si, coreidx, SBCONFIGOFF + OFFSETOF(sbconfig_t, sbtmstatelow), 0, 0);
++ sb_corereg(si, coreidx, SBCONFIGOFF + OFFSETOF(sbconfig_t, sbtmstatelow), ~0, (sblo | SBTML_FGC | SBTML_BE));
++
++ SPINWAIT(((sb_corereg(si, coreidx, SBCONFIGOFF + OFFSETOF(sbconfig_t, sbtmstatehigh), 0, 0) & SBTMH_BISTD) == 0), 100000);
++
++ if (sb_corereg(si, coreidx, SBCONFIGOFF + OFFSETOF(sbconfig_t, sbtmstatehigh), 0, 0) & SBTMH_BISTF)
++ result = BCME_ERROR;
++
++ sb_corereg(si, coreidx, SBCONFIGOFF + OFFSETOF(sbconfig_t, sbtmstatelow), ~0, sblo);
++ }
++
++ return result;
++}
++
++bool
++sb_iscoreup(sb_t *sbh)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++
++ si = SB_INFO(sbh);
++ sb = REGS2SB(si->curmap);
++
++ return ((R_SBREG(si, &(sb)->sbtmstatelow) & (SBTML_RESET | SBTML_REJ_MASK | SBTML_CLK)) == SBTML_CLK);
++}
++
++/*
++ * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation,
++ * switch back to the original core, and return the new value.
++ */
++static uint
++sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val)
++{
++ uint origidx;
++ uint32 *r;
++ uint w;
++ uint intr_val = 0;
++
++ ASSERT(GOODIDX(coreidx));
++ ASSERT(regoff < SB_CORE_SIZE);
++ ASSERT((val & ~mask) == 0);
++
++ INTR_OFF(si, intr_val);
++
++ /* save current core index */
++ origidx = sb_coreidx(&si->sb);
++
++ /* switch core */
++ r = (uint32*) ((uchar*) sb_setcoreidx(&si->sb, coreidx) + regoff);
++
++ /* mask and set */
++ if (mask || val) {
++ if (regoff >= SBCONFIGOFF) {
++ w = (R_SBREG(si, r) & ~mask) | val;
++ W_SBREG(si, r, w);
++ } else {
++ w = (R_REG(r) & ~mask) | val;
++ W_REG(r, w);
++ }
++ }
++
++ /* readback */
++ if (regoff >= SBCONFIGOFF)
++ w = R_SBREG(si, r);
++ else
++ w = R_REG(r);
++
++ /* restore core index */
++ if (origidx != coreidx)
++ sb_setcoreidx(&si->sb, origidx);
++
++ INTR_RESTORE(si, intr_val);
++ return (w);
++}
++
++#define DWORD_ALIGN(x) (x & ~(0x03))
++#define BYTE_POS(x) (x & 0x3)
++#define WORD_POS(x) (x & 0x1)
++
++#define BYTE_SHIFT(x) (8 * BYTE_POS(x))
++#define WORD_SHIFT(x) (16 * WORD_POS(x))
++
++#define BYTE_VAL(a, x) ((a >> BYTE_SHIFT(x)) & 0xFF)
++#define WORD_VAL(a, x) ((a >> WORD_SHIFT(x)) & 0xFFFF)
++
++#define read_pci_cfg_byte(a) \
++ (BYTE_VAL(OSL_PCI_READ_CONFIG(si->osh, DWORD_ALIGN(a), 4), a) & 0xff)
++
++#define read_pci_cfg_write(a) \
++ (WORD_VAL(OSL_PCI_READ_CONFIG(si->osh, DWORD_ALIGN(a), 4), a) & 0xffff)
++
++
++/* scan the sb enumerated space to identify all cores */
++static void
++BCMINITFN(sb_scan)(sb_info_t *si)
++{
++ uint origidx;
++ uint i;
++ bool pci;
++ uint pciidx;
++ uint pcirev;
++
++
++
++ /* numcores should already be set */
++ ASSERT((si->numcores > 0) && (si->numcores <= SB_MAXCORES));
++
++ /* save current core index */
++ origidx = sb_coreidx(&si->sb);
++
++ si->sb.buscorerev = NOREV;
++ si->sb.buscoreidx = BADIDX;
++
++ si->gpioidx = BADIDX;
++
++ pci = FALSE;
++ pcirev = NOREV;
++ pciidx = BADIDX;
++
++ for (i = 0; i < si->numcores; i++) {
++ sb_setcoreidx(&si->sb, i);
++ si->coreid[i] = sb_coreid(&si->sb);
++
++ if (si->coreid[i] == SB_PCI) {
++ pciidx = i;
++ pcirev = sb_corerev(&si->sb);
++ pci = TRUE;
++ }
++ }
++ if (pci) {
++ si->sb.buscoretype = SB_PCI;
++ si->sb.buscorerev = pcirev;
++ si->sb.buscoreidx = pciidx;
++ }
++
++ /*
++ * Find the gpio "controlling core" type and index.
++ * Precedence:
++ * - if there's a chip common core - use that
++ * - else if there's a pci core (rev >= 2) - use that
++ * - else there had better be an extif core (4710 only)
++ */
++ if (GOODIDX(sb_findcoreidx(si, SB_CC, 0))) {
++ si->gpioidx = sb_findcoreidx(si, SB_CC, 0);
++ si->gpioid = SB_CC;
++ } else if (PCI(si) && (si->sb.buscorerev >= 2)) {
++ si->gpioidx = si->sb.buscoreidx;
++ si->gpioid = SB_PCI;
++ } else if (sb_findcoreidx(si, SB_EXTIF, 0)) {
++ si->gpioidx = sb_findcoreidx(si, SB_EXTIF, 0);
++ si->gpioid = SB_EXTIF;
++ } else
++ ASSERT(si->gpioidx != BADIDX);
++
++ /* return to original core index */
++ sb_setcoreidx(&si->sb, origidx);
++}
++
++/* may be called with core in reset */
++void
++sb_detach(sb_t *sbh)
++{
++ sb_info_t *si;
++ uint idx;
++
++ si = SB_INFO(sbh);
++
++ if (si == NULL)
++ return;
++
++ if (BUSTYPE(si->sb.bustype) == SB_BUS)
++ for (idx = 0; idx < SB_MAXCORES; idx++)
++ if (si->regs[idx]) {
++ REG_UNMAP(si->regs[idx]);
++ si->regs[idx] = NULL;
++ }
++
++ if (si != &ksi)
++ MFREE(si->osh, si, sizeof (sb_info_t));
++}
++
++/* use pci dev id to determine chip id for chips not having a chipcommon core */
++static uint
++BCMINITFN(sb_pcidev2chip)(uint pcidev)
++{
++ if ((pcidev >= BCM4710_DEVICE_ID) && (pcidev <= BCM47XX_USB_ID))
++ return (BCM4710_DEVICE_ID);
++ if ((pcidev >= BCM4402_DEVICE_ID) && (pcidev <= BCM4402_V90_ID))
++ return (BCM4402_DEVICE_ID);
++ if (pcidev == BCM4401_ENET_ID)
++ return (BCM4402_DEVICE_ID);
++ if ((pcidev >= BCM4307_V90_ID) && (pcidev <= BCM4307_D11B_ID))
++ return (BCM4307_DEVICE_ID);
++ if (pcidev == BCM4301_DEVICE_ID)
++ return (BCM4301_DEVICE_ID);
++
++ return (0);
++}
++
++/* convert chip number to number of i/o cores */
++static uint
++BCMINITFN(sb_chip2numcores)(uint chip)
++{
++ if (chip == BCM4710_DEVICE_ID)
++ return (9);
++ if (chip == BCM4402_DEVICE_ID)
++ return (3);
++ if ((chip == BCM4301_DEVICE_ID) || (chip == BCM4307_DEVICE_ID))
++ return (5);
++ if (chip == BCM4306_DEVICE_ID) /* < 4306c0 */
++ return (6);
++ if (chip == BCM4704_DEVICE_ID)
++ return (9);
++ if (chip == BCM5365_DEVICE_ID)
++ return (7);
++
++ SB_ERROR(("sb_chip2numcores: unsupported chip 0x%x\n", chip));
++ ASSERT(0);
++ return (1);
++}
++
++/* return index of coreid or BADIDX if not found */
++static uint
++sb_findcoreidx( sb_info_t *si, uint coreid, uint coreunit)
++{
++ uint found;
++ uint i;
++
++ found = 0;
++
++ for (i = 0; i < si->numcores; i++)
++ if (si->coreid[i] == coreid) {
++ if (found == coreunit)
++ return (i);
++ found++;
++ }
++
++ return (BADIDX);
++}
++
++/*
++ * this function changes logical "focus" to the indiciated core,
++ * must be called with interrupt off.
++ * Moreover, callers should keep interrupts off during switching out of and back to d11 core
++ */
++void*
++sb_setcoreidx(sb_t *sbh, uint coreidx)
++{
++ sb_info_t *si;
++ uint32 sbaddr;
++
++ si = SB_INFO(sbh);
++
++ if (coreidx >= si->numcores)
++ return (NULL);
++
++ /*
++ * If the user has provided an interrupt mask enabled function,
++ * then assert interrupts are disabled before switching the core.
++ */
++ ASSERT((si->intrsenabled_fn == NULL) || !(*(si)->intrsenabled_fn)((si)->intr_arg));
++
++ sbaddr = SB_ENUM_BASE + (coreidx * SB_CORE_SIZE);
++
++ switch (BUSTYPE(si->sb.bustype)) {
++ case SB_BUS:
++ /* map new one */
++ if (!si->regs[coreidx]) {
++ si->regs[coreidx] = (void*)REG_MAP(sbaddr, SB_CORE_SIZE);
++ ASSERT(GOODREGS(si->regs[coreidx]));
++ }
++ si->curmap = si->regs[coreidx];
++ break;
++
++ case PCI_BUS:
++ /* point bar0 window */
++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, 4, sbaddr);
++ break;
++
++#ifdef BCMJTAG
++ case JTAG_BUS:
++ /* map new one */
++ if (!si->regs[coreidx]) {
++ si->regs[coreidx] = (void *)sbaddr;
++ ASSERT(GOODREGS(si->regs[coreidx]));
++ }
++ si->curmap = si->regs[coreidx];
++ break;
++#endif /* BCMJTAG */
++ }
++
++ si->curidx = coreidx;
++
++ return (si->curmap);
++}
++
++/*
++ * this function changes logical "focus" to the indiciated core,
++ * must be called with interrupt off.
++ * Moreover, callers should keep interrupts off during switching out of and back to d11 core
++ */
++void*
++sb_setcore(sb_t *sbh, uint coreid, uint coreunit)
++{
++ sb_info_t *si;
++ uint idx;
++
++ si = SB_INFO(sbh);
++ idx = sb_findcoreidx(si, coreid, coreunit);
++ if (!GOODIDX(idx))
++ return (NULL);
++
++ return (sb_setcoreidx(sbh, idx));
++}
++
++/* return chip number */
++uint
++BCMINITFN(sb_chip)(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return (si->sb.chip);
++}
++
++/* return chip revision number */
++uint
++BCMINITFN(sb_chiprev)(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return (si->sb.chiprev);
++}
++
++/* return chip common revision number */
++uint
++BCMINITFN(sb_chipcrev)(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return (si->sb.ccrev);
++}
++
++/* return chip package option */
++uint
++BCMINITFN(sb_chippkg)(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return (si->sb.chippkg);
++}
++
++/* return PCI core rev. */
++uint
++BCMINITFN(sb_pcirev)(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return (si->sb.buscorerev);
++}
++
++bool
++BCMINITFN(sb_war16165)(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++
++ return (PCI(si) && (si->sb.buscorerev <= 10));
++}
++
++/* return board vendor id */
++uint
++BCMINITFN(sb_boardvendor)(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return (si->sb.boardvendor);
++}
++
++/* return boardtype */
++uint
++BCMINITFN(sb_boardtype)(sb_t *sbh)
++{
++ sb_info_t *si;
++ char *var;
++
++ si = SB_INFO(sbh);
++
++ if (BUSTYPE(si->sb.bustype) == SB_BUS && si->sb.boardtype == 0xffff) {
++ /* boardtype format is a hex string */
++ si->sb.boardtype = getintvar(NULL, "boardtype");
++
++ /* backward compatibility for older boardtype string format */
++ if ((si->sb.boardtype == 0) && (var = getvar(NULL, "boardtype"))) {
++ if (!strcmp(var, "bcm94710dev"))
++ si->sb.boardtype = BCM94710D_BOARD;
++ else if (!strcmp(var, "bcm94710ap"))
++ si->sb.boardtype = BCM94710AP_BOARD;
++ else if (!strcmp(var, "bu4710"))
++ si->sb.boardtype = BU4710_BOARD;
++ else if (!strcmp(var, "bcm94702mn"))
++ si->sb.boardtype = BCM94702MN_BOARD;
++ else if (!strcmp(var, "bcm94710r1"))
++ si->sb.boardtype = BCM94710R1_BOARD;
++ else if (!strcmp(var, "bcm94710r4"))
++ si->sb.boardtype = BCM94710R4_BOARD;
++ else if (!strcmp(var, "bcm94702cpci"))
++ si->sb.boardtype = BCM94702CPCI_BOARD;
++ else if (!strcmp(var, "bcm95380_rr"))
++ si->sb.boardtype = BCM95380RR_BOARD;
++ }
++ }
++
++ return (si->sb.boardtype);
++}
++
++/* return bus type of sbh device */
++uint
++sb_bus(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ return (si->sb.bustype);
++}
++
++/* return bus core type */
++uint
++sb_buscoretype(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++
++ return (si->sb.buscoretype);
++}
++
++/* return bus core revision */
++uint
++sb_buscorerev(sb_t *sbh)
++{
++ sb_info_t *si;
++ si = SB_INFO(sbh);
++
++ return (si->sb.buscorerev);
++}
++
++/* return list of found cores */
++uint
++sb_corelist(sb_t *sbh, uint coreid[])
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++
++ bcopy((uchar*)si->coreid, (uchar*)coreid, (si->numcores * sizeof (uint)));
++ return (si->numcores);
++}
++
++/* return current register mapping */
++void *
++sb_coreregs(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ ASSERT(GOODREGS(si->curmap));
++
++ return (si->curmap);
++}
++
++
++/* do buffered registers update */
++void
++sb_commit(sb_t *sbh)
++{
++ sb_info_t *si;
++ uint origidx;
++ uint intr_val = 0;
++
++ si = SB_INFO(sbh);
++
++ origidx = si->curidx;
++ ASSERT(GOODIDX(origidx));
++
++ INTR_OFF(si, intr_val);
++
++ /* switch over to chipcommon core if there is one, else use pci */
++ if (si->sb.ccrev != NOREV) {
++ chipcregs_t *ccregs = (chipcregs_t *)sb_setcore(sbh, SB_CC, 0);
++
++ /* do the buffer registers update */
++ W_REG(&ccregs->broadcastaddress, SB_COMMIT);
++ W_REG(&ccregs->broadcastdata, 0x0);
++ } else if (PCI(si)) {
++ sbpciregs_t *pciregs = (sbpciregs_t *)sb_setcore(sbh, SB_PCI, 0);
++
++ /* do the buffer registers update */
++ W_REG(&pciregs->bcastaddr, SB_COMMIT);
++ W_REG(&pciregs->bcastdata, 0x0);
++ } else
++ ASSERT(0);
++
++ /* restore core index */
++ sb_setcoreidx(sbh, origidx);
++ INTR_RESTORE(si, intr_val);
++}
++
++/* reset and re-enable a core */
++void
++sb_core_reset(sb_t *sbh, uint32 bits)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++ volatile uint32 dummy;
++
++ si = SB_INFO(sbh);
++ ASSERT(GOODREGS(si->curmap));
++ sb = REGS2SB(si->curmap);
++
++ /*
++ * Must do the disable sequence first to work for arbitrary current core state.
++ */
++ sb_core_disable(sbh, bits);
++
++ /*
++ * Now do the initialization sequence.
++ */
++
++ /* set reset while enabling the clock and forcing them on throughout the core */
++ W_SBREG(si, &sb->sbtmstatelow, (SBTML_FGC | SBTML_CLK | SBTML_RESET | bits));
++ dummy = R_SBREG(si, &sb->sbtmstatelow);
++ OSL_DELAY(1);
++
++ if (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_SERR) {
++ W_SBREG(si, &sb->sbtmstatehigh, 0);
++ }
++ if ((dummy = R_SBREG(si, &sb->sbimstate)) & (SBIM_IBE | SBIM_TO)) {
++ AND_SBREG(si, &sb->sbimstate, ~(SBIM_IBE | SBIM_TO));
++ }
++
++ /* clear reset and allow it to propagate throughout the core */
++ W_SBREG(si, &sb->sbtmstatelow, (SBTML_FGC | SBTML_CLK | bits));
++ dummy = R_SBREG(si, &sb->sbtmstatelow);
++ OSL_DELAY(1);
++
++ /* leave clock enabled */
++ W_SBREG(si, &sb->sbtmstatelow, (SBTML_CLK | bits));
++ dummy = R_SBREG(si, &sb->sbtmstatelow);
++ OSL_DELAY(1);
++}
++
++void
++sb_core_tofixup(sb_t *sbh)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++
++ si = SB_INFO(sbh);
++
++ if ( (BUSTYPE(si->sb.bustype) != PCI_BUS) || (PCI(si) && (si->sb.buscorerev >= 5)) )
++ return;
++
++ ASSERT(GOODREGS(si->curmap));
++ sb = REGS2SB(si->curmap);
++
++ if (BUSTYPE(si->sb.bustype) == SB_BUS) {
++ SET_SBREG(si, &sb->sbimconfiglow,
++ SBIMCL_RTO_MASK | SBIMCL_STO_MASK,
++ (0x5 << SBIMCL_RTO_SHIFT) | 0x3);
++ } else {
++ if (sb_coreid(sbh) == SB_PCI) {
++ SET_SBREG(si, &sb->sbimconfiglow,
++ SBIMCL_RTO_MASK | SBIMCL_STO_MASK,
++ (0x3 << SBIMCL_RTO_SHIFT) | 0x2);
++ } else {
++ SET_SBREG(si, &sb->sbimconfiglow, (SBIMCL_RTO_MASK | SBIMCL_STO_MASK), 0);
++ }
++ }
++
++ sb_commit(sbh);
++}
++
++/*
++ * Set the initiator timeout for the "master core".
++ * The master core is defined to be the core in control
++ * of the chip and so it issues accesses to non-memory
++ * locations (Because of dma *any* core can access memeory).
++ *
++ * The routine uses the bus to decide who is the master:
++ * SB_BUS => mips
++ * JTAG_BUS => chipc
++ * PCI_BUS => pci
++ *
++ * This routine exists so callers can disable initiator
++ * timeouts so accesses to very slow devices like otp
++ * won't cause an abort. The routine allows arbitrary
++ * settings of the service and request timeouts, though.
++ *
++ * Returns the timeout state before changing it or -1
++ * on error.
++ */
++
++#define TO_MASK (SBIMCL_RTO_MASK | SBIMCL_STO_MASK)
++
++uint32
++sb_set_initiator_to(sb_t *sbh, uint32 to)
++{
++ sb_info_t *si;
++ uint origidx, idx;
++ uint intr_val = 0;
++ uint32 tmp, ret = 0xffffffff;
++ sbconfig_t *sb;
++
++ si = SB_INFO(sbh);
++
++ if ((to & ~TO_MASK) != 0)
++ return ret;
++
++ /* Figure out the master core */
++ idx = BADIDX;
++ switch (BUSTYPE(si->sb.bustype)) {
++ case PCI_BUS:
++ idx = si->sb.buscoreidx;
++ break;
++ case JTAG_BUS:
++ idx = SB_CC_IDX;
++ break;
++ case SB_BUS:
++ if ((idx = sb_findcoreidx(si, SB_MIPS33, 0)) == BADIDX)
++ idx = sb_findcoreidx(si, SB_MIPS, 0);
++ break;
++ default:
++ ASSERT(0);
++ }
++ if (idx == BADIDX)
++ return ret;
++
++ INTR_OFF(si, intr_val);
++ origidx = sb_coreidx(sbh);
++
++ sb = REGS2SB(sb_setcoreidx(sbh, idx));
++
++ tmp = R_SBREG(si, &sb->sbimconfiglow);
++ ret = tmp & TO_MASK;
++ W_SBREG(si, &sb->sbimconfiglow, (tmp & ~TO_MASK) | to);
++
++ sb_commit(sbh);
++ sb_setcoreidx(sbh, origidx);
++ INTR_RESTORE(si, intr_val);
++ return ret;
++}
++
++void
++sb_core_disable(sb_t *sbh, uint32 bits)
++{
++ sb_info_t *si;
++ volatile uint32 dummy;
++ uint32 rej;
++ sbconfig_t *sb;
++
++ si = SB_INFO(sbh);
++
++ ASSERT(GOODREGS(si->curmap));
++ sb = REGS2SB(si->curmap);
++
++ /* if core is already in reset, just return */
++ if (R_SBREG(si, &sb->sbtmstatelow) & SBTML_RESET)
++ return;
++
++ /* reject value changed between sonics 2.2 and 2.3 */
++ if (si->sb.sonicsrev == SONICS_2_2)
++ rej = (1 << SBTML_REJ_SHIFT);
++ else
++ rej = (2 << SBTML_REJ_SHIFT);
++
++ /* if clocks are not enabled, put into reset and return */
++ if ((R_SBREG(si, &sb->sbtmstatelow) & SBTML_CLK) == 0)
++ goto disable;
++
++ /* set target reject and spin until busy is clear (preserve core-specific bits) */
++ OR_SBREG(si, &sb->sbtmstatelow, rej);
++ dummy = R_SBREG(si, &sb->sbtmstatelow);
++ OSL_DELAY(1);
++ SPINWAIT((R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BUSY), 100000);
++
++ if (R_SBREG(si, &sb->sbidlow) & SBIDL_INIT) {
++ OR_SBREG(si, &sb->sbimstate, SBIM_RJ);
++ dummy = R_SBREG(si, &sb->sbimstate);
++ OSL_DELAY(1);
++ SPINWAIT((R_SBREG(si, &sb->sbimstate) & SBIM_BY), 100000);
++ }
++
++ /* set reset and reject while enabling the clocks */
++ W_SBREG(si, &sb->sbtmstatelow, (bits | SBTML_FGC | SBTML_CLK | rej | SBTML_RESET));
++ dummy = R_SBREG(si, &sb->sbtmstatelow);
++ OSL_DELAY(10);
++
++ /* don't forget to clear the initiator reject bit */
++ if (R_SBREG(si, &sb->sbidlow) & SBIDL_INIT)
++ AND_SBREG(si, &sb->sbimstate, ~SBIM_RJ);
++
++disable:
++ /* leave reset and reject asserted */
++ W_SBREG(si, &sb->sbtmstatelow, (bits | rej | SBTML_RESET));
++ OSL_DELAY(1);
++}
++
++/* set chip watchdog reset timer to fire in 'ticks' backplane cycles */
++void
++sb_watchdog(sb_t *sbh, uint ticks)
++{
++ sb_info_t *si = SB_INFO(sbh);
++
++ /* instant NMI */
++ switch (si->gpioid) {
++ case SB_CC:
++ sb_corereg(si, 0, OFFSETOF(chipcregs_t, watchdog), ~0, ticks);
++ break;
++ case SB_EXTIF:
++ sb_corereg(si, si->gpioidx, OFFSETOF(extifregs_t, watchdog), ~0, ticks);
++ break;
++ }
++}
++
++
++/*
++ * Configure the pci core for pci client (NIC) action
++ * coremask is the bitvec of cores by index to be enabled.
++ */
++void
++sb_pci_setup(sb_t *sbh, uint coremask)
++{
++ sb_info_t *si;
++ sbconfig_t *sb;
++ sbpciregs_t *pciregs;
++ uint32 sbflag;
++ uint32 w;
++ uint idx;
++
++ si = SB_INFO(sbh);
++
++ /* if not pci bus, we're done */
++ if (BUSTYPE(si->sb.bustype) != PCI_BUS)
++ return;
++
++ ASSERT(PCI(si));
++ ASSERT(si->sb.buscoreidx != BADIDX);
++
++ /* get current core index */
++ idx = si->curidx;
++
++ /* we interrupt on this backplane flag number */
++ ASSERT(GOODREGS(si->curmap));
++ sb = REGS2SB(si->curmap);
++ sbflag = R_SBREG(si, &sb->sbtpsflag) & SBTPS_NUM0_MASK;
++
++ /* switch over to pci core */
++ pciregs = (sbpciregs_t*) sb_setcoreidx(sbh, si->sb.buscoreidx);
++ sb = REGS2SB(pciregs);
++
++ /*
++ * Enable sb->pci interrupts. Assume
++ * PCI rev 2.3 support was added in pci core rev 6 and things changed..
++ */
++ if ((PCI(si) && ((si->sb.buscorerev) >= 6))) {
++ /* pci config write to set this core bit in PCIIntMask */
++ w = OSL_PCI_READ_CONFIG(si->osh, PCI_INT_MASK, sizeof(uint32));
++ w |= (coremask << PCI_SBIM_SHIFT);
++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_INT_MASK, sizeof(uint32), w);
++ } else {
++ /* set sbintvec bit for our flag number */
++ OR_SBREG(si, &sb->sbintvec, (1 << sbflag));
++ }
++
++ if (PCI(si)) {
++ OR_REG(&pciregs->sbtopci2, (SBTOPCI_PREF|SBTOPCI_BURST));
++ if (si->sb.buscorerev >= 11)
++ OR_REG(&pciregs->sbtopci2, SBTOPCI_RC_READMULTI);
++ if (si->sb.buscorerev < 5) {
++ SET_SBREG(si, &sb->sbimconfiglow, SBIMCL_RTO_MASK | SBIMCL_STO_MASK,
++ (0x3 << SBIMCL_RTO_SHIFT) | 0x2);
++ sb_commit(sbh);
++ }
++ }
++
++ /* switch back to previous core */
++ sb_setcoreidx(sbh, idx);
++}
++
++uint32
++sb_base(uint32 admatch)
++{
++ uint32 base;
++ uint type;
++
++ type = admatch & SBAM_TYPE_MASK;
++ ASSERT(type < 3);
++
++ base = 0;
++
++ if (type == 0) {
++ base = admatch & SBAM_BASE0_MASK;
++ } else if (type == 1) {
++ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
++ base = admatch & SBAM_BASE1_MASK;
++ } else if (type == 2) {
++ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
++ base = admatch & SBAM_BASE2_MASK;
++ }
++
++ return (base);
++}
++
++uint32
++sb_size(uint32 admatch)
++{
++ uint32 size;
++ uint type;
++
++ type = admatch & SBAM_TYPE_MASK;
++ ASSERT(type < 3);
++
++ size = 0;
++
++ if (type == 0) {
++ size = 1 << (((admatch & SBAM_ADINT0_MASK) >> SBAM_ADINT0_SHIFT) + 1);
++ } else if (type == 1) {
++ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
++ size = 1 << (((admatch & SBAM_ADINT1_MASK) >> SBAM_ADINT1_SHIFT) + 1);
++ } else if (type == 2) {
++ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
++ size = 1 << (((admatch & SBAM_ADINT2_MASK) >> SBAM_ADINT2_SHIFT) + 1);
++ }
++
++ return (size);
++}
++
++/* return the core-type instantiation # of the current core */
++uint
++sb_coreunit(sb_t *sbh)
++{
++ sb_info_t *si;
++ uint idx;
++ uint coreid;
++ uint coreunit;
++ uint i;
++
++ si = SB_INFO(sbh);
++ coreunit = 0;
++
++ idx = si->curidx;
++
++ ASSERT(GOODREGS(si->curmap));
++ coreid = sb_coreid(sbh);
++
++ /* count the cores of our type */
++ for (i = 0; i < idx; i++)
++ if (si->coreid[i] == coreid)
++ coreunit++;
++
++ return (coreunit);
++}
++
++static INLINE uint32
++factor6(uint32 x)
++{
++ switch (x) {
++ case CC_F6_2: return 2;
++ case CC_F6_3: return 3;
++ case CC_F6_4: return 4;
++ case CC_F6_5: return 5;
++ case CC_F6_6: return 6;
++ case CC_F6_7: return 7;
++ default: return 0;
++ }
++}
++
++/* calculate the speed the SB would run at given a set of clockcontrol values */
++uint32
++sb_clock_rate(uint32 pll_type, uint32 n, uint32 m)
++{
++ uint32 n1, n2, clock, m1, m2, m3, mc;
++
++ n1 = n & CN_N1_MASK;
++ n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
++
++ if (pll_type == PLL_TYPE6) {
++ if (m & CC_T6_MMASK)
++ return CC_T6_M1;
++ else
++ return CC_T6_M0;
++ } else if ((pll_type == PLL_TYPE1) ||
++ (pll_type == PLL_TYPE3) ||
++ (pll_type == PLL_TYPE4) ||
++ (pll_type == PLL_TYPE7)) {
++ n1 = factor6(n1);
++ n2 += CC_F5_BIAS;
++ } else if (pll_type == PLL_TYPE2) {
++ n1 += CC_T2_BIAS;
++ n2 += CC_T2_BIAS;
++ ASSERT((n1 >= 2) && (n1 <= 7));
++ ASSERT((n2 >= 5) && (n2 <= 23));
++ } else if (pll_type == PLL_TYPE5) {
++ return (100000000);
++ } else
++ ASSERT(0);
++ /* PLL types 3 and 7 use BASE2 (25Mhz) */
++ if ((pll_type == PLL_TYPE3) ||
++ (pll_type == PLL_TYPE7)) {
++ clock = CC_CLOCK_BASE2 * n1 * n2;
++ }
++ else
++ clock = CC_CLOCK_BASE1 * n1 * n2;
++
++ if (clock == 0)
++ return 0;
++
++ m1 = m & CC_M1_MASK;
++ m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
++ m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
++ mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
++
++ if ((pll_type == PLL_TYPE1) ||
++ (pll_type == PLL_TYPE3) ||
++ (pll_type == PLL_TYPE4) ||
++ (pll_type == PLL_TYPE7)) {
++ m1 = factor6(m1);
++ if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
++ m2 += CC_F5_BIAS;
++ else
++ m2 = factor6(m2);
++ m3 = factor6(m3);
++
++ switch (mc) {
++ case CC_MC_BYPASS: return (clock);
++ case CC_MC_M1: return (clock / m1);
++ case CC_MC_M1M2: return (clock / (m1 * m2));
++ case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3));
++ case CC_MC_M1M3: return (clock / (m1 * m3));
++ default: return (0);
++ }
++ } else {
++ ASSERT(pll_type == PLL_TYPE2);
++
++ m1 += CC_T2_BIAS;
++ m2 += CC_T2M2_BIAS;
++ m3 += CC_T2_BIAS;
++ ASSERT((m1 >= 2) && (m1 <= 7));
++ ASSERT((m2 >= 3) && (m2 <= 10));
++ ASSERT((m3 >= 2) && (m3 <= 7));
++
++ if ((mc & CC_T2MC_M1BYP) == 0)
++ clock /= m1;
++ if ((mc & CC_T2MC_M2BYP) == 0)
++ clock /= m2;
++ if ((mc & CC_T2MC_M3BYP) == 0)
++ clock /= m3;
++
++ return(clock);
++ }
++}
++
++/* returns the current speed the SB is running at */
++uint32
++sb_clock(sb_t *sbh)
++{
++ sb_info_t *si;
++ extifregs_t *eir;
++ chipcregs_t *cc;
++ uint32 n, m;
++ uint idx;
++ uint32 pll_type, rate;
++ uint intr_val = 0;
++
++ si = SB_INFO(sbh);
++ idx = si->curidx;
++ pll_type = PLL_TYPE1;
++
++ INTR_OFF(si, intr_val);
++
++ /* switch to extif or chipc core */
++ if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
++ n = R_REG(&eir->clockcontrol_n);
++ m = R_REG(&eir->clockcontrol_sb);
++ } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
++ pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK;
++ n = R_REG(&cc->clockcontrol_n);
++ if (pll_type == PLL_TYPE6)
++ m = R_REG(&cc->clockcontrol_mips);
++ else if (pll_type == PLL_TYPE3)
++ {
++ // Added by Chen-I for 5365
++ if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID)
++ m = R_REG(&cc->clockcontrol_sb);
++ else
++ m = R_REG(&cc->clockcontrol_m2);
++ }
++ else
++ m = R_REG(&cc->clockcontrol_sb);
++ } else {
++ INTR_RESTORE(si, intr_val);
++ return 0;
++ }
++
++ // Added by Chen-I for 5365
++ if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID)
++ {
++ rate = 100000000;
++ }
++ else
++ {
++ /* calculate rate */
++ rate = sb_clock_rate(pll_type, n, m);
++ if (pll_type == PLL_TYPE3)
++ rate = rate / 2;
++ }
++
++ /* switch back to previous core */
++ sb_setcoreidx(sbh, idx);
++
++ INTR_RESTORE(si, intr_val);
++
++ return rate;
++}
++
++/* change logical "focus" to the gpio core for optimized access */
++void*
++sb_gpiosetcore(sb_t *sbh)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++
++ return (sb_setcoreidx(sbh, si->gpioidx));
++}
++
++/* mask&set gpiocontrol bits */
++uint32
++sb_gpiocontrol(sb_t *sbh, uint32 mask, uint32 val, uint8 priority)
++{
++ sb_info_t *si;
++ uint regoff;
++
++ si = SB_INFO(sbh);
++ regoff = 0;
++
++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */
++
++ /* gpios could be shared on router platforms */
++ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
++ mask = priority ? (sb_gpioreservation & mask) :
++ ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
++ val &= mask;
++ }
++
++ switch (si->gpioid) {
++ case SB_CC:
++ regoff = OFFSETOF(chipcregs_t, gpiocontrol);
++ break;
++
++ case SB_PCI:
++ regoff = OFFSETOF(sbpciregs_t, gpiocontrol);
++ break;
++
++ case SB_EXTIF:
++ return (0);
++ }
++
++ return (sb_corereg(si, si->gpioidx, regoff, mask, val));
++}
++
++/* mask&set gpio output enable bits */
++uint32
++sb_gpioouten(sb_t *sbh, uint32 mask, uint32 val, uint8 priority)
++{
++ sb_info_t *si;
++ uint regoff;
++
++ si = SB_INFO(sbh);
++ regoff = 0;
++
++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */
++
++ /* gpios could be shared on router platforms */
++ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
++ mask = priority ? (sb_gpioreservation & mask) :
++ ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
++ val &= mask;
++ }
++
++ switch (si->gpioid) {
++ case SB_CC:
++ regoff = OFFSETOF(chipcregs_t, gpioouten);
++ break;
++
++ case SB_PCI:
++ regoff = OFFSETOF(sbpciregs_t, gpioouten);
++ break;
++
++ case SB_EXTIF:
++ regoff = OFFSETOF(extifregs_t, gpio[0].outen);
++ break;
++ }
++
++ return (sb_corereg(si, si->gpioidx, regoff, mask, val));
++}
++
++/* mask&set gpio output bits */
++uint32
++sb_gpioout(sb_t *sbh, uint32 mask, uint32 val, uint8 priority)
++{
++ sb_info_t *si;
++ uint regoff;
++
++ si = SB_INFO(sbh);
++ regoff = 0;
++
++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */
++
++ /* gpios could be shared on router platforms */
++ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
++ mask = priority ? (sb_gpioreservation & mask) :
++ ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
++ val &= mask;
++ }
++
++ switch (si->gpioid) {
++ case SB_CC:
++ regoff = OFFSETOF(chipcregs_t, gpioout);
++ break;
++
++ case SB_PCI:
++ regoff = OFFSETOF(sbpciregs_t, gpioout);
++ break;
++
++ case SB_EXTIF:
++ regoff = OFFSETOF(extifregs_t, gpio[0].out);
++ break;
++ }
++
++ return (sb_corereg(si, si->gpioidx, regoff, mask, val));
++}
++
++/* reserve one gpio */
++uint32
++sb_gpioreserve(sb_t *sbh, uint32 gpio_bitmask, uint8 priority)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++
++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */
++
++ /* only cores on SB_BUS share GPIO's and only applcation users need to reserve/release GPIO */
++ if ( (BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) {
++ ASSERT((BUSTYPE(si->sb.bustype) == SB_BUS) && (priority));
++ return -1;
++ }
++ /* make sure only one bit is set */
++ if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
++ ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
++ return -1;
++ }
++
++ /* already reserved */
++ if (sb_gpioreservation & gpio_bitmask)
++ return -1;
++ /* set reservation */
++ sb_gpioreservation |= gpio_bitmask;
++
++ return sb_gpioreservation;
++}
++
++/* release one gpio */
++/*
++ * releasing the gpio doesn't change the current value on the GPIO last write value
++ * persists till some one overwrites it
++*/
++
++uint32
++sb_gpiorelease(sb_t *sbh, uint32 gpio_bitmask, uint8 priority)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++
++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */
++
++ /* only cores on SB_BUS share GPIO's and only applcation users need to reserve/release GPIO */
++ if ( (BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) {
++ ASSERT((BUSTYPE(si->sb.bustype) == SB_BUS) && (priority));
++ return -1;
++ }
++ /* make sure only one bit is set */
++ if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
++ ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
++ return -1;
++ }
++
++ /* already released */
++ if (!(sb_gpioreservation & gpio_bitmask))
++ return -1;
++
++ /* clear reservation */
++ sb_gpioreservation &= ~gpio_bitmask;
++
++ return sb_gpioreservation;
++}
++
++/* return the current gpioin register value */
++uint32
++sb_gpioin(sb_t *sbh)
++{
++ sb_info_t *si;
++ uint regoff;
++
++ si = SB_INFO(sbh);
++ regoff = 0;
++
++ switch (si->gpioid) {
++ case SB_CC:
++ regoff = OFFSETOF(chipcregs_t, gpioin);
++ break;
++
++ case SB_PCI:
++ regoff = OFFSETOF(sbpciregs_t, gpioin);
++ break;
++
++ case SB_EXTIF:
++ regoff = OFFSETOF(extifregs_t, gpioin);
++ break;
++ }
++
++ return (sb_corereg(si, si->gpioidx, regoff, 0, 0));
++}
++
++/* mask&set gpio interrupt polarity bits */
++uint32
++sb_gpiointpolarity(sb_t *sbh, uint32 mask, uint32 val, uint8 priority)
++{
++ sb_info_t *si;
++ uint regoff;
++
++ si = SB_INFO(sbh);
++ regoff = 0;
++
++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */
++
++ /* gpios could be shared on router platforms */
++ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
++ mask = priority ? (sb_gpioreservation & mask) :
++ ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
++ val &= mask;
++ }
++
++ switch (si->gpioid) {
++ case SB_CC:
++ regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
++ break;
++
++ case SB_PCI:
++ /* pci gpio implementation does not support interrupt polarity */
++ ASSERT(0);
++ break;
++
++ case SB_EXTIF:
++ regoff = OFFSETOF(extifregs_t, gpiointpolarity);
++ break;
++ }
++
++ return (sb_corereg(si, si->gpioidx, regoff, mask, val));
++}
++
++/* mask&set gpio interrupt mask bits */
++uint32
++sb_gpiointmask(sb_t *sbh, uint32 mask, uint32 val, uint8 priority)
++{
++ sb_info_t *si;
++ uint regoff;
++
++ si = SB_INFO(sbh);
++ regoff = 0;
++
++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */
++
++ /* gpios could be shared on router platforms */
++ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
++ mask = priority ? (sb_gpioreservation & mask) :
++ ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
++ val &= mask;
++ }
++
++ switch (si->gpioid) {
++ case SB_CC:
++ regoff = OFFSETOF(chipcregs_t, gpiointmask);
++ break;
++
++ case SB_PCI:
++ /* pci gpio implementation does not support interrupt mask */
++ ASSERT(0);
++ break;
++
++ case SB_EXTIF:
++ regoff = OFFSETOF(extifregs_t, gpiointmask);
++ break;
++ }
++
++ return (sb_corereg(si, si->gpioidx, regoff, mask, val));
++}
++
++/* assign the gpio to an led */
++uint32
++sb_gpioled(sb_t *sbh, uint32 mask, uint32 val)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ if (si->sb.ccrev < 16)
++ return -1;
++
++ /* gpio led powersave reg */
++ return(sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val));
++}
++
++/* mask&set gpio timer val */
++uint32
++sb_gpiotimerval(sb_t *sbh, uint32 mask, uint32 gpiotimerval)
++{
++ sb_info_t *si;
++ si = SB_INFO(sbh);
++
++ if (si->sb.ccrev < 16)
++ return -1;
++
++ return(sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval));
++}
++
++
++/* return the slow clock source - LPO, XTAL, or PCI */
++static uint
++sb_slowclk_src(sb_info_t *si)
++{
++ chipcregs_t *cc;
++
++
++ ASSERT(sb_coreid(&si->sb) == SB_CC);
++
++ if (si->sb.ccrev < 6) {
++ if ((BUSTYPE(si->sb.bustype) == PCI_BUS)
++ && (OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, sizeof (uint32)) & PCI_CFG_GPIO_SCS))
++ return (SCC_SS_PCI);
++ else
++ return (SCC_SS_XTAL);
++ } else if (si->sb.ccrev < 10) {
++ cc = (chipcregs_t*) sb_setcoreidx(&si->sb, si->curidx);
++ return (R_REG(&cc->slow_clk_ctl) & SCC_SS_MASK);
++ } else /* Insta-clock */
++ return (SCC_SS_XTAL);
++}
++
++/* return the ILP (slowclock) min or max frequency */
++static uint
++sb_slowclk_freq(sb_info_t *si, bool max)
++{
++ chipcregs_t *cc;
++ uint32 slowclk;
++ uint div;
++
++
++ ASSERT(sb_coreid(&si->sb) == SB_CC);
++
++ cc = (chipcregs_t*) sb_setcoreidx(&si->sb, si->curidx);
++
++ /* shouldn't be here unless we've established the chip has dynamic clk control */
++ ASSERT(R_REG(&cc->capabilities) & CAP_PWR_CTL);
++
++ slowclk = sb_slowclk_src(si);
++ if (si->sb.ccrev < 6) {
++ if (slowclk == SCC_SS_PCI)
++ return (max? (PCIMAXFREQ/64) : (PCIMINFREQ/64));
++ else
++ return (max? (XTALMAXFREQ/32) : (XTALMINFREQ/32));
++ } else if (si->sb.ccrev < 10) {
++ div = 4 * (((R_REG(&cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
++ if (slowclk == SCC_SS_LPO)
++ return (max? LPOMAXFREQ : LPOMINFREQ);
++ else if (slowclk == SCC_SS_XTAL)
++ return (max? (XTALMAXFREQ/div) : (XTALMINFREQ/div));
++ else if (slowclk == SCC_SS_PCI)
++ return (max? (PCIMAXFREQ/div) : (PCIMINFREQ/div));
++ else
++ ASSERT(0);
++ } else {
++ /* Chipc rev 10 is InstaClock */
++ div = R_REG(&cc->system_clk_ctl) >> SYCC_CD_SHIFT;
++ div = 4 * (div + 1);
++ return (max ? XTALMAXFREQ : (XTALMINFREQ/div));
++ }
++ return (0);
++}
++
++static void
++sb_clkctl_setdelay(sb_info_t *si, void *chipcregs)
++{
++ chipcregs_t * cc;
++ uint slowmaxfreq, pll_delay, slowclk;
++ uint pll_on_delay, fref_sel_delay;
++
++ pll_delay = PLL_DELAY;
++
++ /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
++ * since the xtal will also be powered down by dynamic clk control logic.
++ */
++ slowclk = sb_slowclk_src(si);
++ if (slowclk != SCC_SS_XTAL)
++ pll_delay += XTAL_ON_DELAY;
++
++ /* Starting with 4318 it is ILP that is used for the delays */
++ slowmaxfreq = sb_slowclk_freq(si, (si->sb.ccrev >= 10) ? FALSE : TRUE);
++
++ pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
++ fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
++
++ cc = (chipcregs_t *)chipcregs;
++ W_REG(&cc->pll_on_delay, pll_on_delay);
++ W_REG(&cc->fref_sel_delay, fref_sel_delay);
++}
++
++int
++sb_pwrctl_slowclk(void *sbh, bool set, uint *div)
++{
++ sb_info_t *si;
++ uint origidx;
++ chipcregs_t *cc;
++ uint intr_val = 0;
++ uint err = 0;
++
++ si = SB_INFO(sbh);
++
++ /* chipcommon cores prior to rev6 don't support slowclkcontrol */
++ if (si->sb.ccrev < 6)
++ return 1;
++
++ /* chipcommon cores rev10 are a whole new ball game */
++ if (si->sb.ccrev >= 10)
++ return 1;
++
++ if (set && ((*div % 4) || (*div < 4)))
++ return 2;
++
++ INTR_OFF(si, intr_val);
++ origidx = si->curidx;
++ cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0);
++ ASSERT(cc != NULL);
++
++ if (!(R_REG(&cc->capabilities) & CAP_PWR_CTL)) {
++ err = 3;
++ goto done;
++ }
++
++ if (set) {
++ SET_REG(&cc->slow_clk_ctl, SCC_CD_MASK, ((*div / 4 - 1) << SCC_CD_SHIFT));
++ sb_clkctl_setdelay(sbh, (void *)cc);
++ } else
++ *div = 4 * (((R_REG(&cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
++
++done:
++ sb_setcoreidx(sbh, origidx);
++ INTR_RESTORE(si, intr_val);
++ return err;
++}
++
++/* initialize power control delay registers */
++void sb_clkctl_init(sb_t *sbh)
++{
++ sb_info_t *si;
++ uint origidx;
++ chipcregs_t *cc;
++
++ si = SB_INFO(sbh);
++
++ origidx = si->curidx;
++
++ if ((cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0)) == NULL)
++ return;
++
++ if (!(R_REG(&cc->capabilities) & CAP_PWR_CTL))
++ goto done;
++
++ /* set all Instaclk chip ILP to 1 MHz */
++ if (si->sb.ccrev >= 10)
++ SET_REG(&cc->system_clk_ctl, SYCC_CD_MASK, (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
++
++ sb_clkctl_setdelay(si, (void *)cc);
++
++done:
++ sb_setcoreidx(sbh, origidx);
++}
++void sb_pwrctl_init(sb_t *sbh)
++{
++sb_clkctl_init(sbh);
++}
++/* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */
++uint16
++sb_clkctl_fast_pwrup_delay(sb_t *sbh)
++{
++ sb_info_t *si;
++ uint origidx;
++ chipcregs_t *cc;
++ uint slowminfreq;
++ uint16 fpdelay;
++ uint intr_val = 0;
++
++ si = SB_INFO(sbh);
++ fpdelay = 0;
++ origidx = si->curidx;
++
++ INTR_OFF(si, intr_val);
++
++ if ((cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0)) == NULL)
++ goto done;
++
++ if (!(R_REG(&cc->capabilities) & CAP_PWR_CTL))
++ goto done;
++
++ slowminfreq = sb_slowclk_freq(si, FALSE);
++ fpdelay = (((R_REG(&cc->pll_on_delay) + 2) * 1000000) + (slowminfreq - 1)) / slowminfreq;
++
++done:
++ sb_setcoreidx(sbh, origidx);
++ INTR_RESTORE(si, intr_val);
++ return (fpdelay);
++}
++uint16 sb_pwrctl_fast_pwrup_delay(sb_t *sbh)
++{
++return sb_clkctl_fast_pwrup_delay(sbh);
++}
++/* turn primary xtal and/or pll off/on */
++int
++sb_clkctl_xtal(sb_t *sbh, uint what, bool on)
++{
++ sb_info_t *si;
++ uint32 in, out, outen;
++
++ si = SB_INFO(sbh);
++
++ switch (BUSTYPE(si->sb.bustype)) {
++ case PCI_BUS:
++
++ in = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_IN, sizeof (uint32));
++ out = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, sizeof (uint32));
++ outen = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUTEN, sizeof (uint32));
++
++ /*
++ * Avoid glitching the clock if GPRS is already using it.
++ * We can't actually read the state of the PLLPD so we infer it
++ * by the value of XTAL_PU which *is* readable via gpioin.
++ */
++ if (on && (in & PCI_CFG_GPIO_XTAL))
++ return (0);
++
++ if (what & XTAL)
++ outen |= PCI_CFG_GPIO_XTAL;
++ if (what & PLL)
++ outen |= PCI_CFG_GPIO_PLL;
++
++ if (on) {
++ /* turn primary xtal on */
++ if (what & XTAL) {
++ out |= PCI_CFG_GPIO_XTAL;
++ if (what & PLL)
++ out |= PCI_CFG_GPIO_PLL;
++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT, sizeof (uint32), out);
++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUTEN, sizeof (uint32), outen);
++ OSL_DELAY(XTAL_ON_DELAY);
++ }
++
++ /* turn pll on */
++ if (what & PLL) {
++ out &= ~PCI_CFG_GPIO_PLL;
++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT, sizeof (uint32), out);
++ OSL_DELAY(2000);
++ }
++ } else {
++ if (what & XTAL)
++ out &= ~PCI_CFG_GPIO_XTAL;
++ if (what & PLL)
++ out |= PCI_CFG_GPIO_PLL;
++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT, sizeof (uint32), out);
++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUTEN, sizeof (uint32), outen);
++ }
++
++ default:
++ return (-1);
++ }
++
++ return (0);
++}
++
++int sb_pwrctl_xtal(sb_t *sbh, uint what, bool on)
++{
++return sb_clkctl_xtal(sbh,what,on);
++}
++
++/* set dynamic clk control mode (forceslow, forcefast, dynamic) */
++/* returns true if ignore pll off is set and false if it is not */
++bool
++sb_clkctl_clk(sb_t *sbh, uint mode)
++{
++ sb_info_t *si;
++ uint origidx;
++ chipcregs_t *cc;
++ uint32 scc;
++ bool forcefastclk=FALSE;
++ uint intr_val = 0;
++
++ si = SB_INFO(sbh);
++
++ /* chipcommon cores prior to rev6 don't support dynamic clock control */
++ if (si->sb.ccrev < 6)
++ return (FALSE);
++
++ /* chipcommon cores rev10 are a whole new ball game */
++ if (si->sb.ccrev >= 10)
++ return (FALSE);
++
++ INTR_OFF(si, intr_val);
++
++ origidx = si->curidx;
++
++ cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0);
++ ASSERT(cc != NULL);
++
++ if (!(R_REG(&cc->capabilities) & CAP_PWR_CTL))
++ goto done;
++
++ switch (mode) {
++ case CLK_FAST: /* force fast (pll) clock */
++ /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
++ sb_clkctl_xtal(&si->sb, XTAL, ON);
++
++ SET_REG(&cc->slow_clk_ctl, (SCC_XC | SCC_FS | SCC_IP), SCC_IP);
++ break;
++
++ case CLK_DYNAMIC: /* enable dynamic clock control */
++ scc = R_REG(&cc->slow_clk_ctl);
++ scc &= ~(SCC_FS | SCC_IP | SCC_XC);
++ if ((scc & SCC_SS_MASK) != SCC_SS_XTAL)
++ scc |= SCC_XC;
++ W_REG(&cc->slow_clk_ctl, scc);
++
++ /* for dynamic control, we have to release our xtal_pu "force on" */
++ if (scc & SCC_XC)
++ sb_clkctl_xtal(&si->sb, XTAL, OFF);
++ break;
++
++ default:
++ ASSERT(0);
++ }
++
++ /* Is the h/w forcing the use of the fast clk */
++ forcefastclk = (bool)((R_REG(&cc->slow_clk_ctl) & SCC_IP) == SCC_IP);
++
++done:
++ sb_setcoreidx(sbh, origidx);
++ INTR_RESTORE(si, intr_val);
++ return (forcefastclk);
++}
++
++bool sb_pwrctl_clk(sb_t *sbh, uint mode)
++{
++return sb_clkctl_clk(sbh, mode);
++}
++/* register driver interrupt disabling and restoring callback functions */
++void
++sb_register_intr_callback(sb_t *sbh, void *intrsoff_fn, void *intrsrestore_fn, void *intrsenabled_fn, void *intr_arg)
++{
++ sb_info_t *si;
++
++ si = SB_INFO(sbh);
++ si->intr_arg = intr_arg;
++ si->intrsoff_fn = (sb_intrsoff_t)intrsoff_fn;
++ si->intrsrestore_fn = (sb_intrsrestore_t)intrsrestore_fn;
++ si->intrsenabled_fn = (sb_intrsenabled_t)intrsenabled_fn;
++ /* save current core id. when this function called, the current core
++ * must be the core which provides driver functions(il, et, wl, etc.)
++ */
++ si->dev_coreid = si->coreid[si->curidx];
++}
++
++
++void
++sb_corepciid(sb_t *sbh, uint16 *pcivendor, uint16 *pcidevice,
++ uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif)
++{
++ uint vendor, core, unit;
++ uint chip, chippkg;
++ char varname[8];
++ uint8 class, subclass, progif;
++
++ vendor = sb_corevendor(sbh);
++ core = sb_coreid(sbh);
++ unit = sb_coreunit(sbh);
++
++ chip = BCMINIT(sb_chip)(sbh);
++ chippkg = BCMINIT(sb_chippkg)(sbh);
++
++ progif = 0;
++
++ /* Known vendor translations */
++ switch (vendor) {
++ case SB_VEND_BCM:
++ vendor = VENDOR_BROADCOM;
++ break;
++ }
++
++ /* Determine class based on known core codes */
++ switch (core) {
++ case SB_ILINE20:
++ class = PCI_CLASS_NET;
++ subclass = PCI_NET_ETHER;
++ core = BCM47XX_ILINE_ID;
++ break;
++ case SB_ENET:
++ class = PCI_CLASS_NET;
++ subclass = PCI_NET_ETHER;
++ core = BCM47XX_ENET_ID;
++ break;
++ case SB_SDRAM:
++ case SB_MEMC:
++ class = PCI_CLASS_MEMORY;
++ subclass = PCI_MEMORY_RAM;
++ break;
++ case SB_PCI:
++ class = PCI_CLASS_BRIDGE;
++ subclass = PCI_BRIDGE_PCI;
++ break;
++ case SB_MIPS:
++ case SB_MIPS33:
++ class = PCI_CLASS_CPU;
++ subclass = PCI_CPU_MIPS;
++ break;
++ case SB_CODEC:
++ class = PCI_CLASS_COMM;
++ subclass = PCI_COMM_MODEM;
++ core = BCM47XX_V90_ID;
++ break;
++ case SB_USB:
++ class = PCI_CLASS_SERIAL;
++ subclass = PCI_SERIAL_USB;
++ progif = 0x10; /* OHCI */
++ core = BCM47XX_USB_ID;
++ break;
++ case SB_USB11H:
++ class = PCI_CLASS_SERIAL;
++ subclass = PCI_SERIAL_USB;
++ progif = 0x10; /* OHCI */
++ core = BCM47XX_USBH_ID;
++ break;
++ case SB_USB11D:
++ class = PCI_CLASS_SERIAL;
++ subclass = PCI_SERIAL_USB;
++ core = BCM47XX_USBD_ID;
++ break;
++ case SB_IPSEC:
++ class = PCI_CLASS_CRYPT;
++ subclass = PCI_CRYPT_NETWORK;
++ core = BCM47XX_IPSEC_ID;
++ break;
++ case SB_ROBO:
++ class = PCI_CLASS_NET;
++ subclass = PCI_NET_OTHER;
++ core = BCM47XX_ROBO_ID;
++ break;
++ case SB_EXTIF:
++ case SB_CC:
++ class = PCI_CLASS_MEMORY;
++ subclass = PCI_MEMORY_FLASH;
++ break;
++ case SB_D11:
++ class = PCI_CLASS_NET;
++ subclass = PCI_NET_OTHER;
++ /* Let an nvram variable override this */
++ sprintf(varname, "wl%did", unit);
++ if ((core = getintvar(NULL, varname)) == 0) {
++ if (chip == BCM4712_DEVICE_ID) {
++ if (chippkg == BCM4712SMALL_PKG_ID)
++ core = BCM4306_D11G_ID;
++ else
++ core = BCM4306_D11DUAL_ID;
++ }
++ }
++ break;
++
++ default:
++ class = subclass = progif = 0xff;
++ break;
++ }
++
++ *pcivendor = (uint16)vendor;
++ *pcidevice = (uint16)core;
++ *pciclass = class;
++ *pcisubclass = subclass;
++ *pciprogif = progif;
++}
++
++/* Fix chip's configuration. The current core may be changed upon return */
++static int
++sb_pci_fixcfg(sb_info_t *si)
++{
++ uint origidx, pciidx;
++ sbpciregs_t *pciregs;
++ uint16 val16, *reg16;
++
++ ASSERT(BUSTYPE(si->sb.bustype) == PCI_BUS);
++
++ /* Fix PCI(e) SROM shadow area */
++ /* save the current index */
++ origidx = sb_coreidx(&si->sb);
++
++ if (si->sb.buscoretype == SB_PCI) {
++ pciregs = (sbpciregs_t *)sb_setcore(&si->sb, SB_PCI, 0);
++ ASSERT(pciregs);
++ reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
++ }
++ else {
++ ASSERT(0);
++ return -1;
++ }
++ pciidx = sb_coreidx(&si->sb);
++ val16 = R_REG(reg16);
++ if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (uint16)pciidx) {
++ val16 = (uint16)(pciidx << SRSH_PI_SHIFT) | (val16 & ~SRSH_PI_MASK);
++ W_REG(reg16, val16);
++ }
++
++ /* restore the original index */
++ sb_setcoreidx(&si->sb, origidx);
++
++ return 0;
++}
++
++EXPORT_SYMBOL(sb_boardtype);
++EXPORT_SYMBOL(sb_boardvendor);
++EXPORT_SYMBOL(sb_gpiocontrol);
++EXPORT_SYMBOL(sb_gpioin);
++EXPORT_SYMBOL(sb_gpiointmask);
++EXPORT_SYMBOL(sb_gpiointpolarity);
++EXPORT_SYMBOL(sb_gpioled);
++EXPORT_SYMBOL(sb_gpioout);
++EXPORT_SYMBOL(sb_gpioouten);
++EXPORT_SYMBOL(sb_gpiorelease);
++EXPORT_SYMBOL(sb_gpioreserve);
++EXPORT_SYMBOL(sb_gpiosetcore);
++EXPORT_SYMBOL(sb_gpiotimerval);
++EXPORT_SYMBOL(sb_watchdog);
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/broadcom/sflash.c linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/sflash.c
+--- linux-2.6.17/arch/mips/bcm947xx/broadcom/sflash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/broadcom/sflash.c 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,418 @@
++/*
++ * Broadcom SiliconBackplane chipcommon serial flash interface
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#include <osl.h>
++#include <typedefs.h>
++#include <sbconfig.h>
++#include <sbchipc.h>
++#include <mipsinc.h>
++#include <bcmutils.h>
++#include <bcmdevs.h>
++#include <sflash.h>
++
++/* Private global state */
++static struct sflash sflash;
++
++/* Issue a serial flash command */
++static INLINE void
++sflash_cmd(chipcregs_t *cc, uint opcode)
++{
++ W_REG(&cc->flashcontrol, SFLASH_START | opcode);
++ while (R_REG(&cc->flashcontrol) & SFLASH_BUSY);
++}
++
++/* Initialize serial flash access */
++struct sflash *
++sflash_init(chipcregs_t *cc)
++{
++ uint32 id, id2;
++
++ bzero(&sflash, sizeof(sflash));
++
++ sflash.type = R_REG(&cc->capabilities) & CAP_FLASH_MASK;
++
++ switch (sflash.type) {
++ case SFLASH_ST:
++ /* Probe for ST chips */
++ sflash_cmd(cc, SFLASH_ST_DP);
++ sflash_cmd(cc, SFLASH_ST_RES);
++ id = R_REG(&cc->flashdata);
++ switch (id) {
++ case 0x11:
++ /* ST M25P20 2 Mbit Serial Flash */
++ sflash.blocksize = 64 * 1024;
++ sflash.numblocks = 4;
++ break;
++ case 0x12:
++ /* ST M25P40 4 Mbit Serial Flash */
++ sflash.blocksize = 64 * 1024;
++ sflash.numblocks = 8;
++ break;
++ case 0x13:
++ /* ST M25P80 8 Mbit Serial Flash */
++ sflash.blocksize = 64 * 1024;
++ sflash.numblocks = 16;
++ break;
++ case 0x14:
++ /* ST M25P16 16 Mbit Serial Flash */
++ sflash.blocksize = 64 * 1024;
++ sflash.numblocks = 32;
++ break;
++ case 0x15:
++ /* ST M25P32 32 Mbit Serial Flash */
++ sflash.blocksize = 64 * 1024;
++ sflash.numblocks = 64;
++ break;
++ case 0xbf:
++ W_REG(&cc->flashaddress, 1);
++ sflash_cmd(cc, SFLASH_ST_RES);
++ id2 = R_REG(&cc->flashdata);
++ if (id2 == 0x44) {
++ /* SST M25VF80 4 Mbit Serial Flash */
++ sflash.blocksize = 64 * 1024;
++ sflash.numblocks = 8;
++ }
++ break;
++ }
++ break;
++
++ case SFLASH_AT:
++ /* Probe for Atmel chips */
++ sflash_cmd(cc, SFLASH_AT_STATUS);
++ id = R_REG(&cc->flashdata) & 0x3c;
++ switch (id) {
++ case 0xc:
++ /* Atmel AT45DB011 1Mbit Serial Flash */
++ sflash.blocksize = 256;
++ sflash.numblocks = 512;
++ break;
++ case 0x14:
++ /* Atmel AT45DB021 2Mbit Serial Flash */
++ sflash.blocksize = 256;
++ sflash.numblocks = 1024;
++ break;
++ case 0x1c:
++ /* Atmel AT45DB041 4Mbit Serial Flash */
++ sflash.blocksize = 256;
++ sflash.numblocks = 2048;
++ break;
++ case 0x24:
++ /* Atmel AT45DB081 8Mbit Serial Flash */
++ sflash.blocksize = 256;
++ sflash.numblocks = 4096;
++ break;
++ case 0x2c:
++ /* Atmel AT45DB161 16Mbit Serial Flash */
++ sflash.blocksize = 512;
++ sflash.numblocks = 4096;
++ break;
++ case 0x34:
++ /* Atmel AT45DB321 32Mbit Serial Flash */
++ sflash.blocksize = 512;
++ sflash.numblocks = 8192;
++ break;
++ case 0x3c:
++ /* Atmel AT45DB642 64Mbit Serial Flash */
++ sflash.blocksize = 1024;
++ sflash.numblocks = 8192;
++ break;
++ }
++ break;
++ }
++
++ sflash.size = sflash.blocksize * sflash.numblocks;
++ return sflash.size ? &sflash : NULL;
++}
++
++/* Read len bytes starting at offset into buf. Returns number of bytes read. */
++int
++sflash_read(chipcregs_t *cc, uint offset, uint len, uchar *buf)
++{
++ int cnt;
++ uint32 *from, *to;
++
++ if (!len)
++ return 0;
++
++ if ((offset + len) > sflash.size)
++ return -22;
++
++ if ((len >= 4) && (offset & 3))
++ cnt = 4 - (offset & 3);
++ else if ((len >= 4) && ((uint32)buf & 3))
++ cnt = 4 - ((uint32)buf & 3);
++ else
++ cnt = len;
++
++ from = (uint32 *)KSEG1ADDR(SB_FLASH2 + offset);
++ to = (uint32 *)buf;
++
++ if (cnt < 4) {
++ bcopy(from, to, cnt);
++ return cnt;
++ }
++
++ while (cnt >= 4) {
++ *to++ = *from++;
++ cnt -= 4;
++ }
++
++ return (len - cnt);
++}
++
++/* Poll for command completion. Returns zero when complete. */
++int
++sflash_poll(chipcregs_t *cc, uint offset)
++{
++ if (offset >= sflash.size)
++ return -22;
++
++ switch (sflash.type) {
++ case SFLASH_ST:
++ /* Check for ST Write In Progress bit */
++ sflash_cmd(cc, SFLASH_ST_RDSR);
++ return R_REG(&cc->flashdata) & SFLASH_ST_WIP;
++ case SFLASH_AT:
++ /* Check for Atmel Ready bit */
++ sflash_cmd(cc, SFLASH_AT_STATUS);
++ return !(R_REG(&cc->flashdata) & SFLASH_AT_READY);
++ }
++
++ return 0;
++}
++
++/* Write len bytes starting at offset into buf. Returns number of bytes
++ * written. Caller should poll for completion.
++ */
++int
++sflash_write(chipcregs_t *cc, uint offset, uint len, const uchar *buf)
++{
++ struct sflash *sfl;
++ int ret = 0;
++ bool is4712b0;
++ uint32 page, byte, mask;
++
++ if (!len)
++ return 0;
++
++ if ((offset + len) > sflash.size)
++ return -22;
++
++ sfl = &sflash;
++ switch (sfl->type) {
++ case SFLASH_ST:
++ mask = R_REG(&cc->chipid);
++ is4712b0 = (((mask & CID_ID_MASK) == BCM4712_DEVICE_ID) &&
++ ((mask & CID_REV_MASK) == (3 << CID_REV_SHIFT)));
++ /* Enable writes */
++ sflash_cmd(cc, SFLASH_ST_WREN);
++ if (is4712b0) {
++ mask = 1 << 14;
++ W_REG(&cc->flashaddress, offset);
++ W_REG(&cc->flashdata, *buf++);
++ /* Set chip select */
++ OR_REG(&cc->gpioout, mask);
++ /* Issue a page program with the first byte */
++ sflash_cmd(cc, SFLASH_ST_PP);
++ ret = 1;
++ offset++;
++ len--;
++ while (len > 0) {
++ if ((offset & 255) == 0) {
++ /* Page boundary, drop cs and return */
++ AND_REG(&cc->gpioout, ~mask);
++ if (!sflash_poll(cc, offset)) {
++ /* Flash rejected command */
++ return -11;
++ }
++ return ret;
++ } else {
++ /* Write single byte */
++ sflash_cmd(cc, *buf++);
++ }
++ ret++;
++ offset++;
++ len--;
++ }
++ /* All done, drop cs if needed */
++ if ((offset & 255) != 1) {
++ /* Drop cs */
++ AND_REG(&cc->gpioout, ~mask);
++ if (!sflash_poll(cc, offset)) {
++ /* Flash rejected command */
++ return -12;
++ }
++ }
++ } else {
++ ret = 1;
++ W_REG(&cc->flashaddress, offset);
++ W_REG(&cc->flashdata, *buf);
++ /* Page program */
++ sflash_cmd(cc, SFLASH_ST_PP);
++ }
++ break;
++ case SFLASH_AT:
++ mask = sfl->blocksize - 1;
++ page = (offset & ~mask) << 1;
++ byte = offset & mask;
++ /* Read main memory page into buffer 1 */
++ if (byte || len < sfl->blocksize) {
++ W_REG(&cc->flashaddress, page);
++ sflash_cmd(cc, SFLASH_AT_BUF1_LOAD);
++ /* 250 us for AT45DB321B */
++ SPINWAIT(sflash_poll(cc, offset), 1000);
++ ASSERT(!sflash_poll(cc, offset));
++ }
++ /* Write into buffer 1 */
++ for (ret = 0; ret < len && byte < sfl->blocksize; ret++) {
++ W_REG(&cc->flashaddress, byte++);
++ W_REG(&cc->flashdata, *buf++);
++ sflash_cmd(cc, SFLASH_AT_BUF1_WRITE);
++ }
++ /* Write buffer 1 into main memory page */
++ W_REG(&cc->flashaddress, page);
++ sflash_cmd(cc, SFLASH_AT_BUF1_PROGRAM);
++ break;
++ }
++
++ return ret;
++}
++
++/* Erase a region. Returns number of bytes scheduled for erasure.
++ * Caller should poll for completion.
++ */
++int
++sflash_erase(chipcregs_t *cc, uint offset)
++{
++ struct sflash *sfl;
++
++ if (offset >= sflash.size)
++ return -22;
++
++ sfl = &sflash;
++ switch (sfl->type) {
++ case SFLASH_ST:
++ sflash_cmd(cc, SFLASH_ST_WREN);
++ W_REG(&cc->flashaddress, offset);
++ sflash_cmd(cc, SFLASH_ST_SE);
++ return sfl->blocksize;
++ case SFLASH_AT:
++ W_REG(&cc->flashaddress, offset << 1);
++ sflash_cmd(cc, SFLASH_AT_PAGE_ERASE);
++ return sfl->blocksize;
++ }
++
++ return 0;
++}
++
++/*
++ * writes the appropriate range of flash, a NULL buf simply erases
++ * the region of flash
++ */
++int
++sflash_commit(chipcregs_t *cc, uint offset, uint len, const uchar *buf)
++{
++ struct sflash *sfl;
++ uchar *block = NULL, *cur_ptr, *blk_ptr;
++ uint blocksize = 0, mask, cur_offset, cur_length, cur_retlen, remainder;
++ uint blk_offset, blk_len, copied;
++ int bytes, ret = 0;
++
++ /* Check address range */
++ if (len <= 0)
++ return 0;
++
++ sfl = &sflash;
++ if ((offset + len) > sfl->size)
++ return -1;
++
++ blocksize = sfl->blocksize;
++ mask = blocksize - 1;
++
++ /* Allocate a block of mem */
++ if (!(block = MALLOC(NULL, blocksize)))
++ return -1;
++
++ while (len) {
++ /* Align offset */
++ cur_offset = offset & ~mask;
++ cur_length = blocksize;
++ cur_ptr = block;
++
++ remainder = blocksize - (offset & mask);
++ if (len < remainder)
++ cur_retlen = len;
++ else
++ cur_retlen = remainder;
++
++ /* buf == NULL means erase only */
++ if (buf) {
++ /* Copy existing data into holding block if necessary */
++ if ((offset & mask) || (len < blocksize)) {
++ blk_offset = cur_offset;
++ blk_len = cur_length;
++ blk_ptr = cur_ptr;
++
++ /* Copy entire block */
++ while(blk_len) {
++ copied = sflash_read(cc, blk_offset, blk_len, blk_ptr);
++ blk_offset += copied;
++ blk_len -= copied;
++ blk_ptr += copied;
++ }
++ }
++
++ /* Copy input data into holding block */
++ memcpy(cur_ptr + (offset & mask), buf, cur_retlen);
++ }
++
++ /* Erase block */
++ if ((ret = sflash_erase(cc, (uint) cur_offset)) < 0)
++ goto done;
++ while (sflash_poll(cc, (uint) cur_offset));
++
++ /* buf == NULL means erase only */
++ if (!buf) {
++ offset += cur_retlen;
++ len -= cur_retlen;
++ continue;
++ }
++
++ /* Write holding block */
++ while (cur_length > 0) {
++ if ((bytes = sflash_write(cc,
++ (uint) cur_offset,
++ (uint) cur_length,
++ (uchar *) cur_ptr)) < 0) {
++ ret = bytes;
++ goto done;
++ }
++ while (sflash_poll(cc, (uint) cur_offset));
++ cur_offset += bytes;
++ cur_length -= bytes;
++ cur_ptr += bytes;
++ }
++
++ offset += cur_retlen;
++ len -= cur_retlen;
++ buf += cur_retlen;
++ }
++
++ ret = len;
++done:
++ if (block)
++ MFREE(NULL, block, blocksize);
++ return ret;
++}
++
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/bcmdevs.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/bcmdevs.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/bcmdevs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/bcmdevs.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,391 @@
++/*
++ * Broadcom device-specific manifest constants.
++ *
++ * Copyright 2005, 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.
++ * $Id$
++ */
++
++#ifndef _BCMDEVS_H
++#define _BCMDEVS_H
++
++
++/* Known PCI vendor Id's */
++#define VENDOR_EPIGRAM 0xfeda
++#define VENDOR_BROADCOM 0x14e4
++#define VENDOR_3COM 0x10b7
++#define VENDOR_NETGEAR 0x1385
++#define VENDOR_DIAMOND 0x1092
++#define VENDOR_DELL 0x1028
++#define VENDOR_HP 0x0e11
++#define VENDOR_APPLE 0x106b
++
++/* PCI Device Id's */
++#define BCM4210_DEVICE_ID 0x1072 /* never used */
++#define BCM4211_DEVICE_ID 0x4211
++#define BCM4230_DEVICE_ID 0x1086 /* never used */
++#define BCM4231_DEVICE_ID 0x4231
++
++#define BCM4410_DEVICE_ID 0x4410 /* bcm44xx family pci iline */
++#define BCM4430_DEVICE_ID 0x4430 /* bcm44xx family cardbus iline */
++#define BCM4412_DEVICE_ID 0x4412 /* bcm44xx family pci enet */
++#define BCM4432_DEVICE_ID 0x4432 /* bcm44xx family cardbus enet */
++
++#define BCM3352_DEVICE_ID 0x3352 /* bcm3352 device id */
++#define BCM3360_DEVICE_ID 0x3360 /* bcm3360 device id */
++
++#define EPI41210_DEVICE_ID 0xa0fa /* bcm4210 */
++#define EPI41230_DEVICE_ID 0xa10e /* bcm4230 */
++
++#define BCM47XX_ILINE_ID 0x4711 /* 47xx iline20 */
++#define BCM47XX_V90_ID 0x4712 /* 47xx v90 codec */
++#define BCM47XX_ENET_ID 0x4713 /* 47xx enet */
++#define BCM47XX_EXT_ID 0x4714 /* 47xx external i/f */
++#define BCM47XX_USB_ID 0x4715 /* 47xx usb */
++#define BCM47XX_USBH_ID 0x4716 /* 47xx usb host */
++#define BCM47XX_USBD_ID 0x4717 /* 47xx usb device */
++#define BCM47XX_IPSEC_ID 0x4718 /* 47xx ipsec */
++#define BCM47XX_ROBO_ID 0x4719 /* 47xx/53xx roboswitch core */
++#define BCM47XX_USB20H_ID 0x471a /* 47xx usb 2.0 host */
++#define BCM47XX_USB20D_ID 0x471b /* 47xx usb 2.0 device */
++
++#define BCM4710_DEVICE_ID 0x4710 /* 4710 primary function 0 */
++
++#define BCM4610_DEVICE_ID 0x4610 /* 4610 primary function 0 */
++#define BCM4610_ILINE_ID 0x4611 /* 4610 iline100 */
++#define BCM4610_V90_ID 0x4612 /* 4610 v90 codec */
++#define BCM4610_ENET_ID 0x4613 /* 4610 enet */
++#define BCM4610_EXT_ID 0x4614 /* 4610 external i/f */
++#define BCM4610_USB_ID 0x4615 /* 4610 usb */
++
++#define BCM4402_DEVICE_ID 0x4402 /* 4402 primary function 0 */
++#define BCM4402_ENET_ID 0x4402 /* 4402 enet */
++#define BCM4402_V90_ID 0x4403 /* 4402 v90 codec */
++#define BCM4401_ENET_ID 0x170c /* 4401b0 production enet cards */
++
++#define BCM4301_DEVICE_ID 0x4301 /* 4301 primary function 0 */
++#define BCM4301_D11B_ID 0x4301 /* 4301 802.11b */
++
++#define BCM4307_DEVICE_ID 0x4307 /* 4307 primary function 0 */
++#define BCM4307_V90_ID 0x4305 /* 4307 v90 codec */
++#define BCM4307_ENET_ID 0x4306 /* 4307 enet */
++#define BCM4307_D11B_ID 0x4307 /* 4307 802.11b */
++
++#define BCM4306_DEVICE_ID 0x4306 /* 4306 chipcommon chipid */
++#define BCM4306_D11G_ID 0x4320 /* 4306 802.11g */
++#define BCM4306_D11G_ID2 0x4325
++#define BCM4306_D11A_ID 0x4321 /* 4306 802.11a */
++#define BCM4306_UART_ID 0x4322 /* 4306 uart */
++#define BCM4306_V90_ID 0x4323 /* 4306 v90 codec */
++#define BCM4306_D11DUAL_ID 0x4324 /* 4306 dual A+B */
++
++#define BCM4309_PKG_ID 1 /* 4309 package id */
++
++#define BCM4303_D11B_ID 0x4303 /* 4303 802.11b */
++#define BCM4303_PKG_ID 2 /* 4303 package id */
++
++#define BCM4310_DEVICE_ID 0x4310 /* 4310 chipcommon chipid */
++#define BCM4310_D11B_ID 0x4311 /* 4310 802.11b */
++#define BCM4310_UART_ID 0x4312 /* 4310 uart */
++#define BCM4310_ENET_ID 0x4313 /* 4310 enet */
++#define BCM4310_USB_ID 0x4315 /* 4310 usb */
++
++#define BCMGPRS_UART_ID 0x4333 /* Uart id used by 4306/gprs card */
++#define BCMGPRS2_UART_ID 0x4344 /* Uart id used by 4306/gprs card */
++
++
++#define BCM4704_DEVICE_ID 0x4704 /* 4704 chipcommon chipid */
++#define BCM4704_ENET_ID 0x4706 /* 4704 enet (Use 47XX_ENET_ID instead!) */
++
++#define BCM4317_DEVICE_ID 0x4317 /* 4317 chip common chipid */
++
++#define BCM4318_DEVICE_ID 0x4318 /* 4318 chip common chipid */
++#define BCM4318_D11G_ID 0x4318 /* 4318 801.11b/g id */
++#define BCM4318_D11DUAL_ID 0x4319 /* 4318 801.11a/b/g id */
++#define BCM4318_JTAGM_ID 0x4331 /* 4318 jtagm device id */
++
++#define FPGA_JTAGM_ID 0x4330 /* ??? */
++
++/* Address map */
++#define BCM4710_SDRAM 0x00000000 /* Physical SDRAM */
++#define BCM4710_PCI_MEM 0x08000000 /* Host Mode PCI memory access space (64 MB) */
++#define BCM4710_PCI_CFG 0x0c000000 /* Host Mode PCI configuration space (64 MB) */
++#define BCM4710_PCI_DMA 0x40000000 /* Client Mode PCI memory access space (1 GB) */
++#define BCM4710_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */
++#define BCM4710_ENUM 0x18000000 /* Beginning of core enumeration space */
++
++/* Core register space */
++#define BCM4710_REG_SDRAM 0x18000000 /* SDRAM core registers */
++#define BCM4710_REG_ILINE20 0x18001000 /* InsideLine20 core registers */
++#define BCM4710_REG_EMAC0 0x18002000 /* Ethernet MAC 0 core registers */
++#define BCM4710_REG_CODEC 0x18003000 /* Codec core registers */
++#define BCM4710_REG_USB 0x18004000 /* USB core registers */
++#define BCM4710_REG_PCI 0x18005000 /* PCI core registers */
++#define BCM4710_REG_MIPS 0x18006000 /* MIPS core registers */
++#define BCM4710_REG_EXTIF 0x18007000 /* External Interface core registers */
++#define BCM4710_REG_EMAC1 0x18008000 /* Ethernet MAC 1 core registers */
++
++#define BCM4710_EXTIF 0x1f000000 /* External Interface base address */
++#define BCM4710_PCMCIA_MEM 0x1f000000 /* External Interface PCMCIA memory access */
++#define BCM4710_PCMCIA_IO 0x1f100000 /* PCMCIA I/O access */
++#define BCM4710_PCMCIA_CONF 0x1f200000 /* PCMCIA configuration */
++#define BCM4710_PROG 0x1f800000 /* Programable interface */
++#define BCM4710_FLASH 0x1fc00000 /* Flash */
++
++#define BCM4710_EJTAG 0xff200000 /* MIPS EJTAG space (2M) */
++
++#define BCM4710_UART (BCM4710_REG_EXTIF + 0x00000300)
++
++#define BCM4710_EUART (BCM4710_EXTIF + 0x00800000)
++#define BCM4710_LED (BCM4710_EXTIF + 0x00900000)
++
++#define BCM4712_DEVICE_ID 0x4712 /* 4712 chipcommon chipid */
++#define BCM4712_MIPS_ID 0x4720 /* 4712 base devid */
++#define BCM4712LARGE_PKG_ID 0 /* 340pin 4712 package id */
++#define BCM4712SMALL_PKG_ID 1 /* 200pin 4712 package id */
++#define BCM4712MID_PKG_ID 2 /* 225pin 4712 package id */
++
++#define SDIOH_FPGA_ID 0x4380 /* sdio host fpga */
++
++#define BCM5365_DEVICE_ID 0x5365 /* 5365 chipcommon chipid */
++#define BCM5350_DEVICE_ID 0x5350 /* bcm5350 chipcommon chipid */
++#define BCM5352_DEVICE_ID 0x5352 /* bcm5352 chipcommon chipid */
++
++#define BCM4320_DEVICE_ID 0x4320 /* bcm4320 chipcommon chipid */
++
++/* PCMCIA vendor Id's */
++
++#define VENDOR_BROADCOM_PCMCIA 0x02d0
++
++/* SDIO vendor Id's */
++#define VENDOR_BROADCOM_SDIO 0x00BF
++
++
++/* boardflags */
++#define BFL_BTCOEXIST 0x0001 /* This board implements Bluetooth coexistance */
++#define BFL_PACTRL 0x0002 /* This board has gpio 9 controlling the PA */
++#define BFL_AIRLINEMODE 0x0004 /* This board implements gpio13 radio disable indication */
++#define BFL_ENETROBO 0x0010 /* This board has robo switch or core */
++#define BFL_CCKHIPWR 0x0040 /* Can do high-power CCK transmission */
++#define BFL_ENETADM 0x0080 /* This board has ADMtek switch */
++#define BFL_ENETVLAN 0x0100 /* This board has vlan capability */
++#define BFL_AFTERBURNER 0x0200 /* This board supports Afterburner mode */
++#define BFL_NOPCI 0x0400 /* This board leaves PCI floating */
++#define BFL_FEM 0x0800 /* This board supports the Front End Module */
++#define BFL_EXTLNA 0x1000 /* This board has an external LNA */
++#define BFL_HGPA 0x2000 /* This board has a high gain PA */
++#define BFL_BTCMOD 0x4000 /* This board' BTCOEXIST is in the alternate gpios */
++#define BFL_ALTIQ 0x8000 /* Alternate I/Q settings */
++
++/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */
++#define BOARD_GPIO_HWRAD_B 0x010 /* bit 4 is HWRAD input on 4301 */
++#define BOARD_GPIO_BTCMOD_IN 0x010 /* bit 4 is the alternate BT Coexistance Input */
++#define BOARD_GPIO_BTCMOD_OUT 0x020 /* bit 5 is the alternate BT Coexistance Out */
++#define BOARD_GPIO_BTC_IN 0x080 /* bit 7 is BT Coexistance Input */
++#define BOARD_GPIO_BTC_OUT 0x100 /* bit 8 is BT Coexistance Out */
++#define BOARD_GPIO_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */
++#define PCI_CFG_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */
++#define PCI_CFG_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */
++#define PCI_CFG_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */
++#define PCI_CFG_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */
++
++/* Bus types */
++#define SB_BUS 0 /* Silicon Backplane */
++#define PCI_BUS 1 /* PCI target */
++#define PCMCIA_BUS 2 /* PCMCIA target */
++#define SDIO_BUS 3 /* SDIO target */
++#define JTAG_BUS 4 /* JTAG */
++
++/* Allows optimization for single-bus support */
++#ifdef BCMBUSTYPE
++#define BUSTYPE(bus) (BCMBUSTYPE)
++#else
++#define BUSTYPE(bus) (bus)
++#endif
++
++/* power control defines */
++#define PLL_DELAY 150 /* us pll on delay */
++#define FREF_DELAY 200 /* us fref change delay */
++#define MIN_SLOW_CLK 32 /* us Slow clock period */
++#define XTAL_ON_DELAY 1000 /* us crystal power-on delay */
++
++/* Reference Board Types */
++
++#define BU4710_BOARD 0x0400
++#define VSIM4710_BOARD 0x0401
++#define QT4710_BOARD 0x0402
++
++#define BU4610_BOARD 0x0403
++#define VSIM4610_BOARD 0x0404
++
++#define BU4307_BOARD 0x0405
++#define BCM94301CB_BOARD 0x0406
++#define BCM94301PC_BOARD 0x0406 /* Pcmcia 5v card */
++#define BCM94301MP_BOARD 0x0407
++#define BCM94307MP_BOARD 0x0408
++#define BCMAP4307_BOARD 0x0409
++
++#define BU4309_BOARD 0x040a
++#define BCM94309CB_BOARD 0x040b
++#define BCM94309MP_BOARD 0x040c
++#define BCM4309AP_BOARD 0x040d
++
++#define BCM94302MP_BOARD 0x040e
++
++#define VSIM4310_BOARD 0x040f
++#define BU4711_BOARD 0x0410
++#define BCM94310U_BOARD 0x0411
++#define BCM94310AP_BOARD 0x0412
++#define BCM94310MP_BOARD 0x0414
++
++#define BU4306_BOARD 0x0416
++#define BCM94306CB_BOARD 0x0417
++#define BCM94306MP_BOARD 0x0418
++
++#define BCM94710D_BOARD 0x041a
++#define BCM94710R1_BOARD 0x041b
++#define BCM94710R4_BOARD 0x041c
++#define BCM94710AP_BOARD 0x041d
++
++
++#define BU2050_BOARD 0x041f
++
++
++#define BCM94309G_BOARD 0x0421
++
++#define BCM94301PC3_BOARD 0x0422 /* Pcmcia 3.3v card */
++
++#define BU4704_BOARD 0x0423
++#define BU4702_BOARD 0x0424
++
++#define BCM94306PC_BOARD 0x0425 /* pcmcia 3.3v 4306 card */
++
++#define BU4317_BOARD 0x0426
++
++
++#define BCM94702MN_BOARD 0x0428
++
++/* BCM4702 1U CompactPCI Board */
++#define BCM94702CPCI_BOARD 0x0429
++
++/* BCM4702 with BCM95380 VLAN Router */
++#define BCM95380RR_BOARD 0x042a
++
++/* cb4306 with SiGe PA */
++#define BCM94306CBSG_BOARD 0x042b
++
++/* mp4301 with 2050 radio */
++#define BCM94301MPL_BOARD 0x042c
++
++/* cb4306 with SiGe PA */
++#define PCSG94306_BOARD 0x042d
++
++/* bu4704 with sdram */
++#define BU4704SD_BOARD 0x042e
++
++/* Dual 11a/11g Router */
++#define BCM94704AGR_BOARD 0x042f
++
++/* 11a-only minipci */
++#define BCM94308MP_BOARD 0x0430
++
++
++
++/* BCM94317 boards */
++#define BCM94317CB_BOARD 0x0440
++#define BCM94317MP_BOARD 0x0441
++#define BCM94317PCMCIA_BOARD 0x0442
++#define BCM94317SDIO_BOARD 0x0443
++
++#define BU4712_BOARD 0x0444
++#define BU4712SD_BOARD 0x045d
++#define BU4712L_BOARD 0x045f
++
++/* BCM4712 boards */
++#define BCM94712AP_BOARD 0x0445
++#define BCM94712P_BOARD 0x0446
++
++/* BCM4318 boards */
++#define BU4318_BOARD 0x0447
++#define CB4318_BOARD 0x0448
++#define MPG4318_BOARD 0x0449
++#define MP4318_BOARD 0x044a
++#define SD4318_BOARD 0x044b
++
++/* BCM63XX boards */
++#define BCM96338_BOARD 0x6338
++#define BCM96345_BOARD 0x6345
++#define BCM96348_BOARD 0x6348
++
++/* Another mp4306 with SiGe */
++#define BCM94306P_BOARD 0x044c
++
++/* CF-like 4317 modules */
++#define BCM94317CF_BOARD 0x044d
++
++/* mp4303 */
++#define BCM94303MP_BOARD 0x044e
++
++/* mpsgh4306 */
++#define BCM94306MPSGH_BOARD 0x044f
++
++/* BRCM 4306 w/ Front End Modules */
++#define BCM94306MPM 0x0450
++#define BCM94306MPL 0x0453
++
++/* 4712agr */
++#define BCM94712AGR_BOARD 0x0451
++
++/* The real CF 4317 board */
++#define CFI4317_BOARD 0x0452
++
++/* pcmcia 4303 */
++#define PC4303_BOARD 0x0454
++
++/* 5350K */
++#define BCM95350K_BOARD 0x0455
++
++/* 5350R */
++#define BCM95350R_BOARD 0x0456
++
++/* 4306mplna */
++#define BCM94306MPLNA_BOARD 0x0457
++
++/* 4320 boards */
++#define BU4320_BOARD 0x0458
++#define BU4320S_BOARD 0x0459
++#define BCM94320PH_BOARD 0x045a
++
++/* 4306mph */
++#define BCM94306MPH_BOARD 0x045b
++
++/* 4306pciv */
++#define BCM94306PCIV_BOARD 0x045c
++
++#define BU4712SD_BOARD 0x045d
++
++#define BCM94320PFLSH_BOARD 0x045e
++
++#define BU4712L_BOARD 0x045f
++#define BCM94712LGR_BOARD 0x0460
++#define BCM94320R_BOARD 0x0461
++
++#define BU5352_BOARD 0x0462
++
++#define BCM94318MPGH_BOARD 0x0463
++
++
++#define BCM95352GR_BOARD 0x0467
++
++/* bcm95351agr */
++#define BCM95351AGR_BOARD 0x0470
++
++/* # of GPIO pins */
++#define GPIO_NUMPINS 16
++
++#endif /* _BCMDEVS_H */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/bcmendian.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/bcmendian.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/bcmendian.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/bcmendian.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,152 @@
++/*
++ * local version of endian.h - byte order defines
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++*/
++
++#ifndef _BCMENDIAN_H_
++#define _BCMENDIAN_H_
++
++#include <typedefs.h>
++
++/* Byte swap a 16 bit value */
++#define BCMSWAP16(val) \
++ ((uint16)( \
++ (((uint16)(val) & (uint16)0x00ffU) << 8) | \
++ (((uint16)(val) & (uint16)0xff00U) >> 8) ))
++
++/* Byte swap a 32 bit value */
++#define BCMSWAP32(val) \
++ ((uint32)( \
++ (((uint32)(val) & (uint32)0x000000ffUL) << 24) | \
++ (((uint32)(val) & (uint32)0x0000ff00UL) << 8) | \
++ (((uint32)(val) & (uint32)0x00ff0000UL) >> 8) | \
++ (((uint32)(val) & (uint32)0xff000000UL) >> 24) ))
++
++/* 2 Byte swap a 32 bit value */
++#define BCMSWAP32BY16(val) \
++ ((uint32)( \
++ (((uint32)(val) & (uint32)0x0000ffffUL) << 16) | \
++ (((uint32)(val) & (uint32)0xffff0000UL) >> 16) ))
++
++
++static INLINE uint16
++bcmswap16(uint16 val)
++{
++ return BCMSWAP16(val);
++}
++
++static INLINE uint32
++bcmswap32(uint32 val)
++{
++ return BCMSWAP32(val);
++}
++
++static INLINE uint32
++bcmswap32by16(uint32 val)
++{
++ return BCMSWAP32BY16(val);
++}
++
++/* buf - start of buffer of shorts to swap */
++/* len - byte length of buffer */
++static INLINE void
++bcmswap16_buf(uint16 *buf, uint len)
++{
++ len = len/2;
++
++ while(len--){
++ *buf = bcmswap16(*buf);
++ buf++;
++ }
++}
++
++#ifndef hton16
++#ifndef IL_BIGENDIAN
++#define HTON16(i) BCMSWAP16(i)
++#define hton16(i) bcmswap16(i)
++#define hton32(i) bcmswap32(i)
++#define ntoh16(i) bcmswap16(i)
++#define ntoh32(i) bcmswap32(i)
++#define ltoh16(i) (i)
++#define ltoh32(i) (i)
++#define htol16(i) (i)
++#define htol32(i) (i)
++#else
++#define HTON16(i) (i)
++#define hton16(i) (i)
++#define hton32(i) (i)
++#define ntoh16(i) (i)
++#define ntoh32(i) (i)
++#define ltoh16(i) bcmswap16(i)
++#define ltoh32(i) bcmswap32(i)
++#define htol16(i) bcmswap16(i)
++#define htol32(i) bcmswap32(i)
++#endif
++#endif
++
++#ifndef IL_BIGENDIAN
++#define ltoh16_buf(buf, i)
++#define htol16_buf(buf, i)
++#else
++#define ltoh16_buf(buf, i) bcmswap16_buf((uint16*)buf, i)
++#define htol16_buf(buf, i) bcmswap16_buf((uint16*)buf, i)
++#endif
++
++/*
++* load 16-bit value from unaligned little endian byte array.
++*/
++static INLINE uint16
++ltoh16_ua(uint8 *bytes)
++{
++ return (bytes[1]<<8)+bytes[0];
++}
++
++/*
++* load 32-bit value from unaligned little endian byte array.
++*/
++static INLINE uint32
++ltoh32_ua(uint8 *bytes)
++{
++ return (bytes[3]<<24)+(bytes[2]<<16)+(bytes[1]<<8)+bytes[0];
++}
++
++/*
++* load 16-bit value from unaligned big(network) endian byte array.
++*/
++static INLINE uint16
++ntoh16_ua(uint8 *bytes)
++{
++ return (bytes[0]<<8)+bytes[1];
++}
++
++/*
++* load 32-bit value from unaligned big(network) endian byte array.
++*/
++static INLINE uint32
++ntoh32_ua(uint8 *bytes)
++{
++ return (bytes[0]<<24)+(bytes[1]<<16)+(bytes[2]<<8)+bytes[3];
++}
++
++#define ltoh_ua(ptr) ( \
++ sizeof(*(ptr)) == sizeof(uint8) ? *(uint8 *)ptr : \
++ sizeof(*(ptr)) == sizeof(uint16) ? (((uint8 *)ptr)[1]<<8)+((uint8 *)ptr)[0] : \
++ (((uint8 *)ptr)[3]<<24)+(((uint8 *)ptr)[2]<<16)+(((uint8 *)ptr)[1]<<8)+((uint8 *)ptr)[0] \
++)
++
++#define ntoh_ua(ptr) ( \
++ sizeof(*(ptr)) == sizeof(uint8) ? *(uint8 *)ptr : \
++ sizeof(*(ptr)) == sizeof(uint16) ? (((uint8 *)ptr)[0]<<8)+((uint8 *)ptr)[1] : \
++ (((uint8 *)ptr)[0]<<24)+(((uint8 *)ptr)[1]<<16)+(((uint8 *)ptr)[2]<<8)+((uint8 *)ptr)[3] \
++)
++
++#endif /* _BCMENDIAN_H_ */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/bcmnvram.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/bcmnvram.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/bcmnvram.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/bcmnvram.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,95 @@
++/*
++ * NVRAM variable manipulation
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#ifndef _bcmnvram_h_
++#define _bcmnvram_h_
++
++#ifndef _LANGUAGE_ASSEMBLY
++
++#include <typedefs.h>
++
++struct nvram_header {
++ uint32 magic;
++ uint32 len;
++ uint32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
++ uint32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
++ uint32 config_ncdl; /* ncdl values for memc */
++};
++
++struct nvram_tuple {
++ char *name;
++ char *value;
++ struct nvram_tuple *next;
++};
++
++/*
++ * Get the value of an NVRAM variable. The pointer returned may be
++ * invalid after a set.
++ * @param name name of variable to get
++ * @return value of variable or NULL if undefined
++ */
++extern char * __init early_nvram_get(const char *name);
++
++/*
++ * Get the value of an NVRAM variable. The pointer returned may be
++ * invalid after a set.
++ * @param name name of variable to get
++ * @return value of variable or NULL if undefined
++ */
++extern char *nvram_get(const char *name);
++
++/*
++ * Get the value of an NVRAM variable.
++ * @param name name of variable to get
++ * @return value of variable or NUL if undefined
++ */
++#define nvram_safe_get(name) (BCMINIT(early_nvram_get)(name) ? : "")
++
++/*
++ * Match an NVRAM variable.
++ * @param name name of variable to match
++ * @param match value to compare against value of variable
++ * @return TRUE if variable is defined and its value is string equal
++ * to match or FALSE otherwise
++ */
++static inline int
++nvram_match(char *name, char *match) {
++ const char *value = BCMINIT(early_nvram_get)(name);
++ return (value && !strcmp(value, match));
++}
++
++/*
++ * Inversely match an NVRAM variable.
++ * @param name name of variable to match
++ * @param match value to compare against value of variable
++ * @return TRUE if variable is defined and its value is not string
++ * equal to invmatch or FALSE otherwise
++ */
++static inline int
++nvram_invmatch(char *name, char *invmatch) {
++ const char *value = BCMINIT(early_nvram_get)(name);
++ return (value && strcmp(value, invmatch));
++}
++
++#endif /* _LANGUAGE_ASSEMBLY */
++
++#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */
++#define NVRAM_VERSION 1
++#define NVRAM_HEADER_SIZE 20
++#define NVRAM_SPACE 0x8000
++
++#define NVRAM_MAX_VALUE_LEN 255
++#define NVRAM_MAX_PARAM_LEN 64
++
++#endif /* _bcmnvram_h_ */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/bcmsrom.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/bcmsrom.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/bcmsrom.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/bcmsrom.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,23 @@
++/*
++ * Misc useful routines to access NIC local SROM/OTP .
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#ifndef _bcmsrom_h_
++#define _bcmsrom_h_
++
++extern int srom_var_init(void *sbh, uint bus, void *curmap, osl_t *osh, char **vars, int *count);
++
++extern int srom_read(uint bus, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf);
++extern int srom_write(uint bus, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf);
++
++#endif /* _bcmsrom_h_ */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/bcmutils.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/bcmutils.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/bcmutils.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/bcmutils.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,308 @@
++/*
++ * Misc useful os-independent macros and functions.
++ *
++ * Copyright 2005, 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.
++ * $Id$
++ */
++
++#ifndef _bcmutils_h_
++#define _bcmutils_h_
++
++/*** driver-only section ***/
++#include <osl.h>
++
++#define _BCM_U 0x01 /* upper */
++#define _BCM_L 0x02 /* lower */
++#define _BCM_D 0x04 /* digit */
++#define _BCM_C 0x08 /* cntrl */
++#define _BCM_P 0x10 /* punct */
++#define _BCM_S 0x20 /* white space (space/lf/tab) */
++#define _BCM_X 0x40 /* hex digit */
++#define _BCM_SP 0x80 /* hard space (0x20) */
++
++#define GPIO_PIN_NOTDEFINED 0x20
++
++extern unsigned char bcm_ctype[];
++#define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)])
++
++#define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0)
++#define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0)
++#define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0)
++#define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0)
++#define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0)
++#define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0)
++#define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0)
++#define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0)
++#define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0)
++#define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0)
++#define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0)
++
++/*
++ * Spin at most 'us' microseconds while 'exp' is true.
++ * Caller should explicitly test 'exp' when this completes
++ * and take appropriate error action if 'exp' is still true.
++ */
++#define SPINWAIT(exp, us) { \
++ uint countdown = (us) + 9; \
++ while ((exp) && (countdown >= 10)) {\
++ OSL_DELAY(10); \
++ countdown -= 10; \
++ } \
++}
++
++/* generic osl packet queue */
++struct pktq {
++ void *head; /* first packet to dequeue */
++ void *tail; /* last packet to dequeue */
++ uint len; /* number of queued packets */
++ uint maxlen; /* maximum number of queued packets */
++ bool priority; /* enqueue by packet priority */
++ uint8 prio_map[MAXPRIO+1]; /* user priority to packet enqueue policy map */
++};
++#define DEFAULT_QLEN 128
++
++#define pktq_len(q) ((q)->len)
++#define pktq_avail(q) ((q)->maxlen - (q)->len)
++#define pktq_head(q) ((q)->head)
++#define pktq_full(q) ((q)->len >= (q)->maxlen)
++#define _pktq_pri(q, pri) ((q)->prio_map[pri])
++#define pktq_tailpri(q) ((q)->tail ? _pktq_pri(q, PKTPRIO((q)->tail)) : _pktq_pri(q, 0))
++
++/* externs */
++/* packet */
++extern uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf);
++extern uint pkttotlen(osl_t *osh, void *);
++extern void pktq_init(struct pktq *q, uint maxlen, const uint8 prio_map[]);
++extern void pktenq(struct pktq *q, void *p, bool lifo);
++extern void *pktdeq(struct pktq *q);
++extern void *pktdeqtail(struct pktq *q);
++/* string */
++extern uint bcm_atoi(char *s);
++extern uchar bcm_toupper(uchar c);
++extern ulong bcm_strtoul(char *cp, char **endp, uint base);
++extern char *bcmstrstr(char *haystack, char *needle);
++extern char *bcmstrcat(char *dest, const char *src);
++extern ulong wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen);
++/* ethernet address */
++extern char *bcm_ether_ntoa(char *ea, char *buf);
++extern int bcm_ether_atoe(char *p, char *ea);
++/* delay */
++extern void bcm_mdelay(uint ms);
++/* variable access */
++extern char *getvar(char *vars, char *name);
++extern int getintvar(char *vars, char *name);
++extern uint getgpiopin(char *vars, char *pin_name, uint def_pin);
++#define bcmlog(fmt, a1, a2)
++#define bcmdumplog(buf, size) *buf = '\0'
++#define bcmdumplogent(buf, idx) -1
++
++/*** driver/apps-shared section ***/
++
++#define BCME_STRLEN 64
++#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST))
++
++
++/*
++ * error codes could be added but the defined ones shouldn't be changed/deleted
++ * these error codes are exposed to the user code
++ * when ever a new error code is added to this list
++ * please update errorstring table with the related error string and
++ * update osl files with os specific errorcode map
++*/
++
++#define BCME_ERROR -1 /* Error generic */
++#define BCME_BADARG -2 /* Bad Argument */
++#define BCME_BADOPTION -3 /* Bad option */
++#define BCME_NOTUP -4 /* Not up */
++#define BCME_NOTDOWN -5 /* Not down */
++#define BCME_NOTAP -6 /* Not AP */
++#define BCME_NOTSTA -7 /* Not STA */
++#define BCME_BADKEYIDX -8 /* BAD Key Index */
++#define BCME_RADIOOFF -9 /* Radio Off */
++#define BCME_NOTBANDLOCKED -10 /* Not bandlocked */
++#define BCME_NOCLK -11 /* No Clock*/
++#define BCME_BADRATESET -12 /* BAD RateSet*/
++#define BCME_BADBAND -13 /* BAD Band */
++#define BCME_BUFTOOSHORT -14 /* Buffer too short */
++#define BCME_BUFTOOLONG -15 /* Buffer too Long */
++#define BCME_BUSY -16 /* Busy*/
++#define BCME_NOTASSOCIATED -17 /* Not associated*/
++#define BCME_BADSSIDLEN -18 /* BAD SSID Len */
++#define BCME_OUTOFRANGECHAN -19 /* Out of Range Channel*/
++#define BCME_BADCHAN -20 /* BAD Channel */
++#define BCME_BADADDR -21 /* BAD Address*/
++#define BCME_NORESOURCE -22 /* No resources*/
++#define BCME_UNSUPPORTED -23 /* Unsupported*/
++#define BCME_BADLEN -24 /* Bad Length*/
++#define BCME_NOTREADY -25 /* Not ready Yet*/
++#define BCME_EPERM -26 /* Not Permitted */
++#define BCME_NOMEM -27 /* No Memory */
++#define BCME_ASSOCIATED -28 /* Associated */
++#define BCME_RANGE -29 /* Range Error*/
++#define BCME_NOTFOUND -30 /* Not found */
++#define BCME_LAST BCME_NOTFOUND
++
++#ifndef ABS
++#define ABS(a) (((a)<0)?-(a):(a))
++#endif
++
++#ifndef MIN
++#define MIN(a, b) (((a)<(b))?(a):(b))
++#endif
++
++#ifndef MAX
++#define MAX(a, b) (((a)>(b))?(a):(b))
++#endif
++
++#define CEIL(x, y) (((x) + ((y)-1)) / (y))
++#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
++#define ISALIGNED(a, x) (((a) & ((x)-1)) == 0)
++#define ISPOWEROF2(x) ((((x)-1)&(x))==0)
++#define VALID_MASK(mask) !((mask) & ((mask) + 1))
++#define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member)
++#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
++
++/* bit map related macros */
++#ifndef setbit
++#define NBBY 8 /* 8 bits per byte */
++#define setbit(a,i) (((uint8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY))
++#define clrbit(a,i) (((uint8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
++#define isset(a,i) (((uint8 *)a)[(i)/NBBY] & (1<<((i)%NBBY)))
++#define isclr(a,i) ((((uint8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
++#endif
++
++#define NBITS(type) (sizeof(type) * 8)
++#define NBITVAL(bits) (1 << (bits))
++#define MAXBITVAL(bits) ((1 << (bits)) - 1)
++
++/* crc defines */
++#define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */
++#define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */
++#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */
++#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */
++#define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */
++#define CRC32_GOOD_VALUE 0xdebb20e3 /* Good final CRC32 checksum value */
++
++/* bcm_format_flags() bit description structure */
++typedef struct bcm_bit_desc {
++ uint32 bit;
++ char* name;
++} bcm_bit_desc_t;
++
++/* tag_ID/length/value_buffer tuple */
++typedef struct bcm_tlv {
++ uint8 id;
++ uint8 len;
++ uint8 data[1];
++} bcm_tlv_t;
++
++/* Check that bcm_tlv_t fits into the given buflen */
++#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (int)(buflen) >= (int)(2 + (elt)->len))
++
++/* buffer length for ethernet address from bcm_ether_ntoa() */
++#define ETHER_ADDR_STR_LEN 18
++
++/* unaligned load and store macros */
++#ifdef IL_BIGENDIAN
++static INLINE uint32
++load32_ua(uint8 *a)
++{
++ return ((a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]);
++}
++
++static INLINE void
++store32_ua(uint8 *a, uint32 v)
++{
++ a[0] = (v >> 24) & 0xff;
++ a[1] = (v >> 16) & 0xff;
++ a[2] = (v >> 8) & 0xff;
++ a[3] = v & 0xff;
++}
++
++static INLINE uint16
++load16_ua(uint8 *a)
++{
++ return ((a[0] << 8) | a[1]);
++}
++
++static INLINE void
++store16_ua(uint8 *a, uint16 v)
++{
++ a[0] = (v >> 8) & 0xff;
++ a[1] = v & 0xff;
++}
++
++#else
++
++static INLINE uint32
++load32_ua(uint8 *a)
++{
++ return ((a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0]);
++}
++
++static INLINE void
++store32_ua(uint8 *a, uint32 v)
++{
++ a[3] = (v >> 24) & 0xff;
++ a[2] = (v >> 16) & 0xff;
++ a[1] = (v >> 8) & 0xff;
++ a[0] = v & 0xff;
++}
++
++static INLINE uint16
++load16_ua(uint8 *a)
++{
++ return ((a[1] << 8) | a[0]);
++}
++
++static INLINE void
++store16_ua(uint8 *a, uint16 v)
++{
++ a[1] = (v >> 8) & 0xff;
++ a[0] = v & 0xff;
++}
++
++#endif
++
++/* externs */
++/* crc */
++extern uint8 hndcrc8(uint8 *p, uint nbytes, uint8 crc);
++/* format/print */
++/* IE parsing */
++extern bcm_tlv_t *bcm_next_tlv(bcm_tlv_t *elt, int *buflen);
++extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key);
++extern bcm_tlv_t *bcm_parse_ordered_tlvs(void *buf, int buflen, uint key);
++
++/* bcmerror*/
++extern const char *bcmerrorstr(int bcmerror);
++
++/* multi-bool data type: set of bools, mbool is true if any is set */
++typedef uint32 mbool;
++#define mboolset(mb, bit) (mb |= bit) /* set one bool */
++#define mboolclr(mb, bit) (mb &= ~bit) /* clear one bool */
++#define mboolisset(mb, bit) ((mb & bit) != 0) /* TRUE if one bool is set */
++#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val)))
++
++/* power conversion */
++extern uint16 bcm_qdbm_to_mw(uint8 qdbm);
++extern uint8 bcm_mw_to_qdbm(uint16 mw);
++
++/* generic datastruct to help dump routines */
++struct fielddesc {
++ char *nameandfmt;
++ uint32 offset;
++ uint32 len;
++};
++
++typedef uint32 (*readreg_rtn)(void *arg0, void *arg1, uint32 offset);
++extern uint bcmdumpfields(readreg_rtn func_ptr, void *arg0, void *arg1, struct fielddesc *str, char *buf, uint32 bufsize);
++
++extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len);
++
++#endif /* _bcmutils_h_ */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/bitfuncs.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/bitfuncs.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/bitfuncs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/bitfuncs.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,85 @@
++/*
++ * bit manipulation utility functions
++ *
++ * Copyright 2005, 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.
++ * $Id$
++ */
++
++#ifndef _BITFUNCS_H
++#define _BITFUNCS_H
++
++#include <typedefs.h>
++
++/* local prototypes */
++static INLINE uint32 find_msbit(uint32 x);
++
++
++/*
++ * find_msbit: returns index of most significant set bit in x, with index
++ * range defined as 0-31. NOTE: returns zero if input is zero.
++ */
++
++#if defined(USE_PENTIUM_BSR) && defined(__GNUC__)
++
++/*
++ * Implementation for Pentium processors and gcc. Note that this
++ * instruction is actually very slow on some processors (e.g., family 5,
++ * model 2, stepping 12, "Pentium 75 - 200"), so we use the generic
++ * implementation instead.
++ */
++static INLINE uint32 find_msbit(uint32 x)
++{
++ uint msbit;
++ __asm__("bsrl %1,%0"
++ :"=r" (msbit)
++ :"r" (x));
++ return msbit;
++}
++
++#else
++
++/*
++ * Generic Implementation
++ */
++
++#define DB_POW_MASK16 0xffff0000
++#define DB_POW_MASK8 0x0000ff00
++#define DB_POW_MASK4 0x000000f0
++#define DB_POW_MASK2 0x0000000c
++#define DB_POW_MASK1 0x00000002
++
++static INLINE uint32 find_msbit(uint32 x)
++{
++ uint32 temp_x = x;
++ uint msbit = 0;
++ if (temp_x & DB_POW_MASK16) {
++ temp_x >>= 16;
++ msbit = 16;
++ }
++ if (temp_x & DB_POW_MASK8) {
++ temp_x >>= 8;
++ msbit += 8;
++ }
++ if (temp_x & DB_POW_MASK4) {
++ temp_x >>= 4;
++ msbit += 4;
++ }
++ if (temp_x & DB_POW_MASK2) {
++ temp_x >>= 2;
++ msbit += 2;
++ }
++ if (temp_x & DB_POW_MASK1) {
++ msbit += 1;
++ }
++ return(msbit);
++}
++
++#endif
++
++#endif /* _BITFUNCS_H */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/flash.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/flash.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/flash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/flash.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,188 @@
++/*
++ * flash.h: Common definitions for flash access.
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++/* Types of flashes we know about */
++typedef enum _flash_type {OLD, BSC, SCS, AMD, SST, SFLASH} flash_type_t;
++
++/* Commands to write/erase the flases */
++typedef struct _flash_cmds{
++ flash_type_t type;
++ bool need_unlock;
++ uint16 pre_erase;
++ uint16 erase_block;
++ uint16 erase_chip;
++ uint16 write_word;
++ uint16 write_buf;
++ uint16 clear_csr;
++ uint16 read_csr;
++ uint16 read_id;
++ uint16 confirm;
++ uint16 read_array;
++} flash_cmds_t;
++
++#define UNLOCK_CMD_WORDS 2
++
++typedef struct _unlock_cmd {
++ uint addr[UNLOCK_CMD_WORDS];
++ uint16 cmd[UNLOCK_CMD_WORDS];
++} unlock_cmd_t;
++
++/* Flash descriptors */
++typedef struct _flash_desc {
++ uint16 mfgid; /* Manufacturer Id */
++ uint16 devid; /* Device Id */
++ uint size; /* Total size in bytes */
++ uint width; /* Device width in bytes */
++ flash_type_t type; /* Device type old, S, J */
++ uint bsize; /* Block size */
++ uint nb; /* Number of blocks */
++ uint ff; /* First full block */
++ uint lf; /* Last full block */
++ uint nsub; /* Number of subblocks */
++ uint *subblocks; /* Offsets for subblocks */
++ char *desc; /* Description */
++} flash_desc_t;
++
++
++#ifdef DECLARE_FLASHES
++flash_cmds_t sflash_cmd_t =
++ { SFLASH, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
++
++flash_cmds_t flash_cmds[] = {
++/* type needu preera eraseb erasech write wbuf clcsr rdcsr rdid confrm read */
++ { BSC, 0, 0x00, 0x20, 0x00, 0x40, 0x00, 0x50, 0x70, 0x90, 0xd0, 0xff },
++ { SCS, 0, 0x00, 0x20, 0x00, 0x40, 0xe8, 0x50, 0x70, 0x90, 0xd0, 0xff },
++ { AMD, 1, 0x80, 0x30, 0x10, 0xa0, 0x00, 0x00, 0x00, 0x90, 0x00, 0xf0 },
++ { SST, 1, 0x80, 0x50, 0x10, 0xa0, 0x00, 0x00, 0x00, 0x90, 0x00, 0xf0 },
++ { 0 }
++};
++
++unlock_cmd_t unlock_cmd_amd = {
++#ifdef MIPSEB
++/* addr: */ { 0x0aa8, 0x0556},
++#else
++/* addr: */ { 0x0aaa, 0x0554},
++#endif
++/* data: */ { 0xaa, 0x55}
++};
++
++unlock_cmd_t unlock_cmd_sst = {
++#ifdef MIPSEB
++/* addr: */ { 0xaaa8, 0x5556},
++#else
++/* addr: */ { 0xaaaa, 0x5554},
++#endif
++/* data: */ { 0xaa, 0x55}
++};
++
++#define AMD_CMD 0xaaa
++#define SST_CMD 0xaaaa
++
++/* intel unlock block cmds */
++#define INTEL_UNLOCK1 0x60
++#define INTEL_UNLOCK2 0xD0
++
++/* Just eight blocks of 8KB byte each */
++
++uint blk8x8k[] = { 0x00000000,
++ 0x00002000,
++ 0x00004000,
++ 0x00006000,
++ 0x00008000,
++ 0x0000a000,
++ 0x0000c000,
++ 0x0000e000,
++ 0x00010000
++};
++
++/* Funky AMD arrangement for 29xx800's */
++uint amd800[] = { 0x00000000, /* 16KB */
++ 0x00004000, /* 32KB */
++ 0x0000c000, /* 8KB */
++ 0x0000e000, /* 8KB */
++ 0x00010000, /* 8KB */
++ 0x00012000, /* 8KB */
++ 0x00014000, /* 32KB */
++ 0x0001c000, /* 16KB */
++ 0x00020000
++};
++
++/* AMD arrangement for 29xx160's */
++uint amd4112[] = { 0x00000000, /* 32KB */
++ 0x00008000, /* 8KB */
++ 0x0000a000, /* 8KB */
++ 0x0000c000, /* 16KB */
++ 0x00010000
++};
++uint amd2114[] = { 0x00000000, /* 16KB */
++ 0x00004000, /* 8KB */
++ 0x00006000, /* 8KB */
++ 0x00008000, /* 32KB */
++ 0x00010000
++};
++
++
++flash_desc_t sflash_desc =
++ { 0, 0, 0, 0, SFLASH, 0, 0, 0, 0, 0, NULL, "SFLASH" };
++
++flash_desc_t flashes[] = {
++ { 0x00b0, 0x00d0, 0x0200000, 2, SCS, 0x10000, 32, 0, 31, 0, NULL, "Intel 28F160S3/5 1Mx16" },
++ { 0x00b0, 0x00d4, 0x0400000, 2, SCS, 0x10000, 64, 0, 63, 0, NULL, "Intel 28F320S3/5 2Mx16" },
++ { 0x0089, 0x8890, 0x0200000, 2, BSC, 0x10000, 32, 0, 30, 8, blk8x8k, "Intel 28F160B3 1Mx16 TopB" },
++ { 0x0089, 0x8891, 0x0200000, 2, BSC, 0x10000, 32, 1, 31, 8, blk8x8k, "Intel 28F160B3 1Mx16 BotB" },
++ { 0x0089, 0x8896, 0x0400000, 2, BSC, 0x10000, 64, 0, 62, 8, blk8x8k, "Intel 28F320B3 2Mx16 TopB" },
++ { 0x0089, 0x8897, 0x0400000, 2, BSC, 0x10000, 64, 1, 63, 8, blk8x8k, "Intel 28F320B3 2Mx16 BotB" },
++ { 0x0089, 0x8898, 0x0800000, 2, BSC, 0x10000, 128, 0, 126, 8, blk8x8k, "Intel 28F640B3 4Mx16 TopB" },
++ { 0x0089, 0x8899, 0x0800000, 2, BSC, 0x10000, 128, 1, 127, 8, blk8x8k, "Intel 28F640B3 4Mx16 BotB" },
++ { 0x0089, 0x88C2, 0x0200000, 2, BSC, 0x10000, 32, 0, 30, 8, blk8x8k, "Intel 28F160C3 1Mx16 TopB" },
++ { 0x0089, 0x88C3, 0x0200000, 2, BSC, 0x10000, 32, 1, 31, 8, blk8x8k, "Intel 28F160C3 1Mx16 BotB" },
++ { 0x0089, 0x88C4, 0x0400000, 2, BSC, 0x10000, 64, 0, 62, 8, blk8x8k, "Intel 28F320C3 2Mx16 TopB" },
++ { 0x0089, 0x88C5, 0x0400000, 2, BSC, 0x10000, 64, 1, 63, 8, blk8x8k, "Intel 28F320C3 2Mx16 BotB" },
++ { 0x0089, 0x88CC, 0x0800000, 2, BSC, 0x10000, 128, 0, 126, 8, blk8x8k, "Intel 28F640C3 4Mx16 TopB" },
++ { 0x0089, 0x88CD, 0x0800000, 2, BSC, 0x10000, 128, 1, 127, 8, blk8x8k, "Intel 28F640C3 4Mx16 BotB" },
++ { 0x0089, 0x0014, 0x0400000, 2, SCS, 0x20000, 32, 0, 31, 0, NULL, "Intel 28F320J5 2Mx16" },
++ { 0x0089, 0x0015, 0x0800000, 2, SCS, 0x20000, 64, 0, 63, 0, NULL, "Intel 28F640J5 4Mx16" },
++ { 0x0089, 0x0016, 0x0400000, 2, SCS, 0x20000, 32, 0, 31, 0, NULL, "Intel 28F320J3 2Mx16" },
++ { 0x0089, 0x0017, 0x0800000, 2, SCS, 0x20000, 64, 0, 63, 0, NULL, "Intel 28F640J3 4Mx16" },
++ { 0x0089, 0x0018, 0x1000000, 2, SCS, 0x20000, 128, 0, 127, 0, NULL, "Intel 28F128J3 8Mx16" },
++ { 0x00b0, 0x00e3, 0x0400000, 2, BSC, 0x10000, 64, 1, 63, 8, blk8x8k, "Sharp 28F320BJE 2Mx16 BotB" },
++ { 0x0001, 0x224a, 0x0100000, 2, AMD, 0x10000, 16, 0, 13, 8, amd800, "AMD 29DL800BT 512Kx16 TopB" },
++ { 0x0001, 0x22cb, 0x0100000, 2, AMD, 0x10000, 16, 2, 15, 8, amd800, "AMD 29DL800BB 512Kx16 BotB" },
++ { 0x0001, 0x22c4, 0x0200000, 2, AMD, 0x10000, 32, 0, 30, 4, amd2114, "AMD 29lv160DT 1Mx16 TopB" },
++ { 0x0001, 0x2249, 0x0200000, 2, AMD, 0x10000, 32, 1, 31, 4, amd4112, "AMD 29lv160DB 1Mx16 BotB" },
++ { 0x0001, 0x22f6, 0x0400000, 2, AMD, 0x10000, 64, 0, 62, 8, blk8x8k, "AMD 29lv320DT 2Mx16 TopB" },
++ { 0x0001, 0x22f9, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 8, blk8x8k, "AMD 29lv320DB 2Mx16 BotB" },
++ { 0x0001, 0x227e, 0x0400000, 2, AMD, 0x10000, 64, 0, 62, 8, blk8x8k, "AMD 29lv320MT 2Mx16 TopB" },
++ { 0x0001, 0x2200, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 8, blk8x8k, "AMD 29lv320MB 2Mx16 BotB" },
++ { 0x0020, 0x22CA, 0x0400000, 2, AMD, 0x10000, 64, 0, 62, 4, amd4112, "ST 29w320DT 2Mx16 TopB" },
++ { 0x0020, 0x22CB, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 4, amd2114, "ST 29w320DB 2Mx16 BotB" },
++ { 0x00C2, 0x00A7, 0x0400000, 2, AMD, 0x10000, 64, 0, 62, 4, amd4112, "MX29LV320T 2Mx16 TopB" },
++ { 0x00C2, 0x00A8, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 4, amd2114, "MX29LV320B 2Mx16 BotB" },
++ { 0x0004, 0x22F6, 0x0400000, 2, AMD, 0x10000, 64, 0, 62, 4, amd4112, "MBM29LV320TE 2Mx16 TopB" },
++ { 0x0004, 0x22F9, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 4, amd2114, "MBM29LV320BE 2Mx16 BotB" },
++ { 0x0098, 0x009A, 0x0400000, 2, AMD, 0x10000, 64, 0, 62, 4, amd4112, "TC58FVT321 2Mx16 TopB" },
++ { 0x0098, 0x009C, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 4, amd2114, "TC58FVB321 2Mx16 BotB" },
++ { 0x00C2, 0x22A7, 0x0400000, 2, AMD, 0x10000, 64, 0, 62, 4, amd4112, "MX29LV320T 2Mx16 TopB" },
++ { 0x00C2, 0x22A8, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 4, amd2114, "MX29LV320B 2Mx16 BotB" },
++ { 0x00BF, 0x2783, 0x0400000, 2, SST, 0x10000, 64, 0, 63, 0, NULL, "SST39VF320 2Mx16" },
++ { 0, 0, 0, 0, OLD, 0, 0, 0, 0, 0, NULL, NULL },
++};
++
++#else
++
++extern flash_cmds_t flash_cmds[];
++extern unlock_cmd_t unlock_cmd;
++extern flash_desc_t flashes[];
++
++#endif
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/flashutl.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/flashutl.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/flashutl.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/flashutl.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,27 @@
++/*
++ * BCM47XX FLASH driver interface
++ *
++ * Copyright 2005, 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.
++ * $Id$
++ */
++
++#ifndef _flashutl_h_
++#define _flashutl_h_
++
++
++#ifndef _LANGUAGE_ASSEMBLY
++
++int sysFlashInit(char *flash_str);
++int sysFlashRead(uint off, uchar *dst, uint bytes);
++int sysFlashWrite(uint off, uchar *src, uint bytes);
++void nvWrite(unsigned short *data, unsigned int len);
++
++#endif /* _LANGUAGE_ASSEMBLY */
++
++#endif /* _flashutl_h_ */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/hndmips.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/hndmips.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/hndmips.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/hndmips.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,16 @@
++/*
++ * Alternate include file for HND sbmips.h since CFE also ships with
++ * a sbmips.h.
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#include "sbmips.h"
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/linux_osl.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/linux_osl.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/linux_osl.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/linux_osl.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,331 @@
++/*
++ * Linux OS Independent Layer
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#ifndef _linux_osl_h_
++#define _linux_osl_h_
++
++#include <typedefs.h>
++
++/* use current 2.4.x calling conventions */
++#include <linuxver.h>
++
++/* assert and panic */
++#ifdef __GNUC__
++#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
++#if GCC_VERSION > 30100
++#define ASSERT(exp) do {} while (0)
++#else
++/* ASSERT could causes segmentation fault on GCC3.1, use empty instead*/
++#define ASSERT(exp)
++#endif
++#endif
++
++/* microsecond delay */
++#define OSL_DELAY(usec) osl_delay(usec)
++extern void osl_delay(uint usec);
++
++/* PCI configuration space access macros */
++#define OSL_PCI_READ_CONFIG(osh, offset, size) \
++ osl_pci_read_config((osh), (offset), (size))
++#define OSL_PCI_WRITE_CONFIG(osh, offset, size, val) \
++ osl_pci_write_config((osh), (offset), (size), (val))
++extern uint32 osl_pci_read_config(osl_t *osh, uint size, uint offset);
++extern void osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val);
++
++/* PCI device bus # and slot # */
++#define OSL_PCI_BUS(osh) osl_pci_bus(osh)
++#define OSL_PCI_SLOT(osh) osl_pci_slot(osh)
++extern uint osl_pci_bus(osl_t *osh);
++extern uint osl_pci_slot(osl_t *osh);
++
++/* OSL initialization */
++extern osl_t *osl_attach(void *pdev);
++extern void osl_detach(osl_t *osh);
++
++/* host/bus architecture-specific byte swap */
++#define BUS_SWAP32(v) (v)
++
++/* general purpose memory allocation */
++
++#define MALLOC(osh, size) kmalloc(size, GFP_ATOMIC)
++#define MFREE(osh, addr, size) kfree(addr);
++
++#define MALLOC_FAILED(osh) osl_malloc_failed((osh))
++
++extern void *osl_malloc(osl_t *osh, uint size);
++extern void osl_mfree(osl_t *osh, void *addr, uint size);
++extern uint osl_malloced(osl_t *osh);
++extern uint osl_malloc_failed(osl_t *osh);
++
++/* allocate/free shared (dma-able) consistent memory */
++#define DMA_CONSISTENT_ALIGN PAGE_SIZE
++#define DMA_ALLOC_CONSISTENT(osh, size, pap) \
++ osl_dma_alloc_consistent((osh), (size), (pap))
++#define DMA_FREE_CONSISTENT(osh, va, size, pa) \
++ osl_dma_free_consistent((osh), (void*)(va), (size), (pa))
++extern void *osl_dma_alloc_consistent(osl_t *osh, uint size, ulong *pap);
++extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa);
++
++/* map/unmap direction */
++#define DMA_TX 1
++#define DMA_RX 2
++
++/* register access macros */
++#if defined(BCMJTAG)
++#include <bcmjtag.h>
++#define R_REG(r) bcmjtag_read(NULL, (uint32)(r), sizeof (*(r)))
++#define W_REG(r, v) bcmjtag_write(NULL, (uint32)(r), (uint32)(v), sizeof (*(r)))
++#endif
++
++/*
++ * BINOSL selects the slightly slower function-call-based binary compatible osl.
++ * Macros expand to calls to functions defined in linux_osl.c .
++ */
++#ifndef BINOSL
++
++/* string library, kernel mode */
++#define printf(fmt, args...) printk(fmt, ## args)
++#include <linux/kernel.h>
++#include <linux/string.h>
++
++/* register access macros */
++#if !defined(BCMJTAG)
++#ifndef IL_BIGENDIAN
++#define R_REG(r) ( \
++ sizeof(*(r)) == sizeof(uint8) ? readb((volatile uint8*)(r)) : \
++ sizeof(*(r)) == sizeof(uint16) ? readw((volatile uint16*)(r)) : \
++ readl((volatile uint32*)(r)) \
++)
++#define W_REG(r, v) do { \
++ switch (sizeof(*(r))) { \
++ case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)(r)); break; \
++ case sizeof(uint16): writew((uint16)(v), (volatile uint16*)(r)); break; \
++ case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \
++ } \
++} while (0)
++#else /* IL_BIGENDIAN */
++#define R_REG(r) ({ \
++ __typeof(*(r)) __osl_v; \
++ switch (sizeof(*(r))) { \
++ case sizeof(uint8): __osl_v = readb((volatile uint8*)((uint32)r^3)); break; \
++ case sizeof(uint16): __osl_v = readw((volatile uint16*)((uint32)r^2)); break; \
++ case sizeof(uint32): __osl_v = readl((volatile uint32*)(r)); break; \
++ } \
++ __osl_v; \
++})
++#define W_REG(r, v) do { \
++ switch (sizeof(*(r))) { \
++ case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)((uint32)r^3)); break; \
++ case sizeof(uint16): writew((uint16)(v), (volatile uint16*)((uint32)r^2)); break; \
++ case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \
++ } \
++} while (0)
++#endif
++#endif
++
++#define AND_REG(r, v) W_REG((r), R_REG(r) & (v))
++#define OR_REG(r, v) W_REG((r), R_REG(r) | (v))
++
++/* bcopy, bcmp, and bzero */
++#define bcopy(src, dst, len) memcpy((dst), (src), (len))
++#define bcmp(b1, b2, len) memcmp((b1), (b2), (len))
++#define bzero(b, len) memset((b), '\0', (len))
++
++/* uncached virtual address */
++#ifdef mips
++#define OSL_UNCACHED(va) KSEG1ADDR((va))
++#include <asm/addrspace.h>
++#else
++#define OSL_UNCACHED(va) (va)
++#endif
++
++/* get processor cycle count */
++#if defined(mips)
++#define OSL_GETCYCLES(x) ((x) = read_c0_count() * 2)
++#elif defined(__i386__)
++#define OSL_GETCYCLES(x) rdtscl((x))
++#else
++#define OSL_GETCYCLES(x) ((x) = 0)
++#endif
++
++/* dereference an address that may cause a bus exception */
++#ifdef mips
++#if defined(MODULE) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,17))
++#define BUSPROBE(val, addr) panic("get_dbe() will not fixup a bus exception when compiled into a module")
++#else
++#define BUSPROBE(val, addr) get_dbe((val), (addr))
++#include <asm/paccess.h>
++#endif
++#else
++#define BUSPROBE(val, addr) ({ (val) = R_REG((addr)); 0; })
++#endif
++
++/* map/unmap physical to virtual I/O */
++#define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), (unsigned long)(size))
++#define REG_UNMAP(va) iounmap((void *)(va))
++
++/* shared (dma-able) memory access macros */
++#define R_SM(r) *(r)
++#define W_SM(r, v) (*(r) = (v))
++#define BZERO_SM(r, len) memset((r), '\0', (len))
++
++/* packet primitives */
++#define PKTGET(osh, len, send) osl_pktget((osh), (len), (send))
++#define PKTFREE(osh, skb, send) osl_pktfree((skb))
++#define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data)
++#define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len)
++#define PKTHEADROOM(osh, skb) (PKTDATA(osh,skb)-(((struct sk_buff*)(skb))->head))
++#define PKTTAILROOM(osh, skb) ((((struct sk_buff*)(skb))->end)-(((struct sk_buff*)(skb))->tail))
++#define PKTNEXT(osh, skb) (((struct sk_buff*)(skb))->next)
++#define PKTSETNEXT(skb, x) (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x))
++#define PKTSETLEN(osh, skb, len) __skb_trim((struct sk_buff*)(skb), (len))
++#define PKTPUSH(osh, skb, bytes) skb_push((struct sk_buff*)(skb), (bytes))
++#define PKTPULL(osh, skb, bytes) skb_pull((struct sk_buff*)(skb), (bytes))
++#define PKTDUP(osh, skb) skb_clone((struct sk_buff*)(skb), GFP_ATOMIC)
++#define PKTCOOKIE(skb) ((void*)((struct sk_buff*)(skb))->csum)
++#define PKTSETCOOKIE(skb, x) (((struct sk_buff*)(skb))->csum = (uint)(x))
++#define PKTLINK(skb) (((struct sk_buff*)(skb))->prev)
++#define PKTSETLINK(skb, x) (((struct sk_buff*)(skb))->prev = (struct sk_buff*)(x))
++#define PKTPRIO(skb) (((struct sk_buff*)(skb))->priority)
++#define PKTSETPRIO(skb, x) (((struct sk_buff*)(skb))->priority = (x))
++extern void *osl_pktget(osl_t *osh, uint len, bool send);
++extern void osl_pktfree(void *skb);
++
++#else /* BINOSL */
++
++/* string library */
++#ifndef LINUX_OSL
++#undef printf
++#define printf(fmt, args...) osl_printf((fmt), ## args)
++#undef sprintf
++#define sprintf(buf, fmt, args...) osl_sprintf((buf), (fmt), ## args)
++#undef strcmp
++#define strcmp(s1, s2) osl_strcmp((s1), (s2))
++#undef strncmp
++#define strncmp(s1, s2, n) osl_strncmp((s1), (s2), (n))
++#undef strlen
++#define strlen(s) osl_strlen((s))
++#undef strcpy
++#define strcpy(d, s) osl_strcpy((d), (s))
++#undef strncpy
++#define strncpy(d, s, n) osl_strncpy((d), (s), (n))
++#endif
++extern int osl_printf(const char *format, ...);
++extern int osl_sprintf(char *buf, const char *format, ...);
++extern int osl_strcmp(const char *s1, const char *s2);
++extern int osl_strncmp(const char *s1, const char *s2, uint n);
++extern int osl_strlen(const char *s);
++extern char* osl_strcpy(char *d, const char *s);
++extern char* osl_strncpy(char *d, const char *s, uint n);
++
++/* register access macros */
++#if !defined(BCMJTAG)
++#define R_REG(r) ( \
++ sizeof(*(r)) == sizeof(uint8) ? osl_readb((volatile uint8*)(r)) : \
++ sizeof(*(r)) == sizeof(uint16) ? osl_readw((volatile uint16*)(r)) : \
++ osl_readl((volatile uint32*)(r)) \
++)
++#define W_REG(r, v) do { \
++ switch (sizeof(*(r))) { \
++ case sizeof(uint8): osl_writeb((uint8)(v), (volatile uint8*)(r)); break; \
++ case sizeof(uint16): osl_writew((uint16)(v), (volatile uint16*)(r)); break; \
++ case sizeof(uint32): osl_writel((uint32)(v), (volatile uint32*)(r)); break; \
++ } \
++} while (0)
++#endif
++
++#define AND_REG(r, v) W_REG((r), R_REG(r) & (v))
++#define OR_REG(r, v) W_REG((r), R_REG(r) | (v))
++extern uint8 osl_readb(volatile uint8 *r);
++extern uint16 osl_readw(volatile uint16 *r);
++extern uint32 osl_readl(volatile uint32 *r);
++extern void osl_writeb(uint8 v, volatile uint8 *r);
++extern void osl_writew(uint16 v, volatile uint16 *r);
++extern void osl_writel(uint32 v, volatile uint32 *r);
++
++/* bcopy, bcmp, and bzero */
++extern void bcopy(const void *src, void *dst, int len);
++extern int bcmp(const void *b1, const void *b2, int len);
++extern void bzero(void *b, int len);
++
++/* uncached virtual address */
++#define OSL_UNCACHED(va) osl_uncached((va))
++extern void *osl_uncached(void *va);
++
++/* get processor cycle count */
++#define OSL_GETCYCLES(x) ((x) = osl_getcycles())
++extern uint osl_getcycles(void);
++
++/* dereference an address that may target abort */
++#define BUSPROBE(val, addr) osl_busprobe(&(val), (addr))
++extern int osl_busprobe(uint32 *val, uint32 addr);
++
++/* map/unmap physical to virtual */
++#define REG_MAP(pa, size) osl_reg_map((pa), (size))
++#define REG_UNMAP(va) osl_reg_unmap((va))
++extern void *osl_reg_map(uint32 pa, uint size);
++extern void osl_reg_unmap(void *va);
++
++/* shared (dma-able) memory access macros */
++#define R_SM(r) *(r)
++#define W_SM(r, v) (*(r) = (v))
++#define BZERO_SM(r, len) bzero((r), (len))
++
++/* packet primitives */
++#define PKTGET(osh, len, send) osl_pktget((osh), (len), (send))
++#define PKTFREE(osh, skb, send) osl_pktfree((skb))
++#define PKTDATA(osh, skb) osl_pktdata((osh), (skb))
++#define PKTLEN(osh, skb) osl_pktlen((osh), (skb))
++#define PKTHEADROOM(osh, skb) osl_pktheadroom((osh), (skb))
++#define PKTTAILROOM(osh, skb) osl_pkttailroom((osh), (skb))
++#define PKTNEXT(osh, skb) osl_pktnext((osh), (skb))
++#define PKTSETNEXT(skb, x) osl_pktsetnext((skb), (x))
++#define PKTSETLEN(osh, skb, len) osl_pktsetlen((osh), (skb), (len))
++#define PKTPUSH(osh, skb, bytes) osl_pktpush((osh), (skb), (bytes))
++#define PKTPULL(osh, skb, bytes) osl_pktpull((osh), (skb), (bytes))
++#define PKTDUP(osh, skb) osl_pktdup((osh), (skb))
++#define PKTCOOKIE(skb) osl_pktcookie((skb))
++#define PKTSETCOOKIE(skb, x) osl_pktsetcookie((skb), (x))
++#define PKTLINK(skb) osl_pktlink((skb))
++#define PKTSETLINK(skb, x) osl_pktsetlink((skb), (x))
++#define PKTPRIO(skb) osl_pktprio((skb))
++#define PKTSETPRIO(skb, x) osl_pktsetprio((skb), (x))
++extern void *osl_pktget(osl_t *osh, uint len, bool send);
++extern void osl_pktfree(void *skb);
++extern uchar *osl_pktdata(osl_t *osh, void *skb);
++extern uint osl_pktlen(osl_t *osh, void *skb);
++extern uint osl_pktheadroom(osl_t *osh, void *skb);
++extern uint osl_pkttailroom(osl_t *osh, void *skb);
++extern void *osl_pktnext(osl_t *osh, void *skb);
++extern void osl_pktsetnext(void *skb, void *x);
++extern void osl_pktsetlen(osl_t *osh, void *skb, uint len);
++extern uchar *osl_pktpush(osl_t *osh, void *skb, int bytes);
++extern uchar *osl_pktpull(osl_t *osh, void *skb, int bytes);
++extern void *osl_pktdup(osl_t *osh, void *skb);
++extern void *osl_pktcookie(void *skb);
++extern void osl_pktsetcookie(void *skb, void *x);
++extern void *osl_pktlink(void *skb);
++extern void osl_pktsetlink(void *skb, void *x);
++extern uint osl_pktprio(void *skb);
++extern void osl_pktsetprio(void *skb, uint x);
++
++#endif /* BINOSL */
++
++#define OSL_ERROR(bcmerror) osl_error(bcmerror)
++extern int osl_error(int bcmerror);
++
++/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */
++#define PKTBUFSZ 2048
++
++#endif /* _linux_osl_h_ */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/linuxver.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/linuxver.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/linuxver.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/linuxver.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,389 @@
++/*
++ * Linux-specific abstractions to gain some independence from linux kernel versions.
++ * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences.
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#ifndef _linuxver_h_
++#define _linuxver_h_
++
++#include <linux/config.h>
++#include <linux/version.h>
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
++/* __NO_VERSION__ must be defined for all linkables except one in 2.2 */
++#ifdef __UNDEF_NO_VERSION__
++#undef __NO_VERSION__
++#else
++#define __NO_VERSION__
++#endif
++#endif
++
++#if defined(MODULE) && defined(MODVERSIONS)
++#include <linux/modversions.h>
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
++#include <linux/moduleparam.h>
++#endif
++
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
++#define module_param(_name_, _type_, _perm_) MODULE_PARM(_name_, "i")
++#define module_param_string(_name_, _string_, _size_, _perm_) MODULE_PARM(_string_, "c" __MODULE_STRING(_size_))
++#endif
++
++/* linux/malloc.h is deprecated, use linux/slab.h instead. */
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,9))
++#include <linux/malloc.h>
++#else
++#include <linux/slab.h>
++#endif
++
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/string.h>
++#include <linux/pci.h>
++#include <linux/interrupt.h>
++#include <linux/netdevice.h>
++#include <asm/io.h>
++
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41))
++#include <linux/workqueue.h>
++#else
++#include <linux/tqueue.h>
++#ifndef work_struct
++#define work_struct tq_struct
++#endif
++#ifndef INIT_WORK
++#define INIT_WORK(_work, _func, _data) INIT_TQUEUE((_work), (_func), (_data))
++#endif
++#ifndef schedule_work
++#define schedule_work(_work) schedule_task((_work))
++#endif
++#ifndef flush_scheduled_work
++#define flush_scheduled_work() flush_scheduled_tasks()
++#endif
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
++/* Some distributions have their own 2.6.x compatibility layers */
++#ifndef IRQ_NONE
++typedef void irqreturn_t;
++#define IRQ_NONE
++#define IRQ_HANDLED
++#define IRQ_RETVAL(x)
++#endif
++#else
++typedef irqreturn_t (*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs);
++#endif
++
++#ifndef __exit
++#define __exit
++#endif
++#ifndef __devexit
++#define __devexit
++#endif
++#ifndef __devinit
++#define __devinit __init
++#endif
++#ifndef __devinitdata
++#define __devinitdata
++#endif
++#ifndef __devexit_p
++#define __devexit_p(x) x
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
++
++#define pci_get_drvdata(dev) (dev)->sysdata
++#define pci_set_drvdata(dev, value) (dev)->sysdata=(value)
++
++/*
++ * New-style (2.4.x) PCI/hot-pluggable PCI/CardBus registration
++ */
++
++struct pci_device_id {
++ unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */
++ unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
++ unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */
++ unsigned long driver_data; /* Data private to the driver */
++};
++
++struct pci_driver {
++ struct list_head node;
++ char *name;
++ const struct pci_device_id *id_table; /* NULL if wants all devices */
++ int (*probe)(struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */
++ void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */
++ void (*suspend)(struct pci_dev *dev); /* Device suspended */
++ void (*resume)(struct pci_dev *dev); /* Device woken up */
++};
++
++#define MODULE_DEVICE_TABLE(type, name)
++#define PCI_ANY_ID (~0)
++
++/* compatpci.c */
++#define pci_module_init pci_register_driver
++extern int pci_register_driver(struct pci_driver *drv);
++extern void pci_unregister_driver(struct pci_driver *drv);
++
++#endif /* PCI registration */
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18))
++#ifdef MODULE
++#define module_init(x) int init_module(void) { return x(); }
++#define module_exit(x) void cleanup_module(void) { x(); }
++#else
++#define module_init(x) __initcall(x);
++#define module_exit(x) __exitcall(x);
++#endif
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,48))
++#define list_for_each(pos, head) \
++ for (pos = (head)->next; pos != (head); pos = pos->next)
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13))
++#define pci_resource_start(dev, bar) ((dev)->base_address[(bar)])
++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,44))
++#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start)
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,23))
++#define pci_enable_device(dev) do { } while (0)
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,14))
++#define net_device device
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,42))
++
++/*
++ * DMA mapping
++ *
++ * See linux/Documentation/DMA-mapping.txt
++ */
++
++#ifndef PCI_DMA_TODEVICE
++#define PCI_DMA_TODEVICE 1
++#define PCI_DMA_FROMDEVICE 2
++#endif
++
++typedef u32 dma_addr_t;
++
++/* Pure 2^n version of get_order */
++static inline int get_order(unsigned long size)
++{
++ int order;
++
++ size = (size-1) >> (PAGE_SHIFT-1);
++ order = -1;
++ do {
++ size >>= 1;
++ order++;
++ } while (size);
++ return order;
++}
++
++static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
++ dma_addr_t *dma_handle)
++{
++ void *ret;
++ int gfp = GFP_ATOMIC | GFP_DMA;
++
++ ret = (void *)__get_free_pages(gfp, get_order(size));
++
++ if (ret != NULL) {
++ memset(ret, 0, size);
++ *dma_handle = virt_to_bus(ret);
++ }
++ return ret;
++}
++static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size,
++ void *vaddr, dma_addr_t dma_handle)
++{
++ free_pages((unsigned long)vaddr, get_order(size));
++}
++#ifdef ILSIM
++extern uint pci_map_single(void *dev, void *va, uint size, int direction);
++extern void pci_unmap_single(void *dev, uint pa, uint size, int direction);
++#else
++#define pci_map_single(cookie, address, size, dir) virt_to_bus(address)
++#define pci_unmap_single(cookie, address, size, dir)
++#endif
++
++#endif /* DMA mapping */
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43))
++
++#define dev_kfree_skb_any(a) dev_kfree_skb(a)
++#define netif_down(dev) do { (dev)->start = 0; } while(0)
++
++/* pcmcia-cs provides its own netdevice compatibility layer */
++#ifndef _COMPAT_NETDEVICE_H
++
++/*
++ * SoftNet
++ *
++ * For pre-softnet kernels we need to tell the upper layer not to
++ * re-enter start_xmit() while we are in there. However softnet
++ * guarantees not to enter while we are in there so there is no need
++ * to do the netif_stop_queue() dance unless the transmit queue really
++ * gets stuck. This should also improve performance according to tests
++ * done by Aman Singla.
++ */
++
++#define dev_kfree_skb_irq(a) dev_kfree_skb(a)
++#define netif_wake_queue(dev) do { clear_bit(0, &(dev)->tbusy); mark_bh(NET_BH); } while(0)
++#define netif_stop_queue(dev) set_bit(0, &(dev)->tbusy)
++
++static inline void netif_start_queue(struct net_device *dev)
++{
++ dev->tbusy = 0;
++ dev->interrupt = 0;
++ dev->start = 1;
++}
++
++#define netif_queue_stopped(dev) (dev)->tbusy
++#define netif_running(dev) (dev)->start
++
++#endif /* _COMPAT_NETDEVICE_H */
++
++#define netif_device_attach(dev) netif_start_queue(dev)
++#define netif_device_detach(dev) netif_stop_queue(dev)
++
++/* 2.4.x renamed bottom halves to tasklets */
++#define tasklet_struct tq_struct
++static inline void tasklet_schedule(struct tasklet_struct *tasklet)
++{
++ queue_task(tasklet, &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++}
++
++static inline void tasklet_init(struct tasklet_struct *tasklet,
++ void (*func)(unsigned long),
++ unsigned long data)
++{
++ tasklet->next = NULL;
++ tasklet->sync = 0;
++ tasklet->routine = (void (*)(void *))func;
++ tasklet->data = (void *)data;
++}
++#define tasklet_kill(tasklet) {do{} while(0);}
++
++/* 2.4.x introduced del_timer_sync() */
++#define del_timer_sync(timer) del_timer(timer)
++
++#else
++
++#define netif_down(dev)
++
++#endif /* SoftNet */
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3))
++
++/*
++ * Emit code to initialise a tq_struct's routine and data pointers
++ */
++#define PREPARE_TQUEUE(_tq, _routine, _data) \
++ do { \
++ (_tq)->routine = _routine; \
++ (_tq)->data = _data; \
++ } while (0)
++
++/*
++ * Emit code to initialise all of a tq_struct
++ */
++#define INIT_TQUEUE(_tq, _routine, _data) \
++ do { \
++ INIT_LIST_HEAD(&(_tq)->list); \
++ (_tq)->sync = 0; \
++ PREPARE_TQUEUE((_tq), (_routine), (_data)); \
++ } while (0)
++
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6))
++
++/* Power management related routines */
++
++static inline int
++pci_save_state(struct pci_dev *dev, u32 *buffer)
++{
++ int i;
++ if (buffer) {
++ for (i = 0; i < 16; i++)
++ pci_read_config_dword(dev, i * 4,&buffer[i]);
++ }
++ return 0;
++}
++
++static inline int
++pci_restore_state(struct pci_dev *dev, u32 *buffer)
++{
++ int i;
++
++ if (buffer) {
++ for (i = 0; i < 16; i++)
++ pci_write_config_dword(dev,i * 4, buffer[i]);
++ }
++ /*
++ * otherwise, write the context information we know from bootup.
++ * This works around a problem where warm-booting from Windows
++ * combined with a D3(hot)->D0 transition causes PCI config
++ * header data to be forgotten.
++ */
++ else {
++ for (i = 0; i < 6; i ++)
++ pci_write_config_dword(dev,
++ PCI_BASE_ADDRESS_0 + (i * 4),
++ pci_resource_start(dev, i));
++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
++ }
++ return 0;
++}
++
++#endif /* PCI power management */
++
++/* Old cp0 access macros deprecated in 2.4.19 */
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19))
++#define read_c0_count() read_32bit_cp0_register(CP0_COUNT)
++#endif
++
++/* Module refcount handled internally in 2.6.x */
++#ifndef SET_MODULE_OWNER
++#define SET_MODULE_OWNER(dev) do {} while (0)
++#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT
++#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT
++#else
++#define OLD_MOD_INC_USE_COUNT do {} while (0)
++#define OLD_MOD_DEC_USE_COUNT do {} while (0)
++#endif
++
++#ifndef SET_NETDEV_DEV
++#define SET_NETDEV_DEV(net, pdev) do {} while (0)
++#endif
++
++#ifndef HAVE_FREE_NETDEV
++#define free_netdev(dev) kfree(dev)
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
++/* struct packet_type redefined in 2.6.x */
++#define af_packet_priv data
++#endif
++
++#endif /* _linuxver_h_ */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/mipsinc.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/mipsinc.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/mipsinc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/mipsinc.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,552 @@
++/*
++ * HND Run Time Environment for standalone MIPS programs.
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#ifndef _MISPINC_H
++#define _MISPINC_H
++
++
++/* MIPS defines */
++
++#ifdef _LANGUAGE_ASSEMBLY
++
++/*
++ * 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 */
++
++
++/*
++ * CP0 Registers
++ */
++
++#define C0_INX $0
++#define C0_RAND $1
++#define C0_TLBLO0 $2
++#define C0_TLBLO C0_TLBLO0
++#define C0_TLBLO1 $3
++#define C0_CTEXT $4
++#define C0_PGMASK $5
++#define C0_WIRED $6
++#define C0_BADVADDR $8
++#define C0_COUNT $9
++#define C0_TLBHI $10
++#define C0_COMPARE $11
++#define C0_SR $12
++#define C0_STATUS C0_SR
++#define C0_CAUSE $13
++#define C0_EPC $14
++#define C0_PRID $15
++#define C0_CONFIG $16
++#define C0_LLADDR $17
++#define C0_WATCHLO $18
++#define C0_WATCHHI $19
++#define C0_XCTEXT $20
++#define C0_DIAGNOSTIC $22
++#define C0_BROADCOM C0_DIAGNOSTIC
++#define C0_PERFORMANCE $25
++#define C0_ECC $26
++#define C0_CACHEERR $27
++#define C0_TAGLO $28
++#define C0_TAGHI $29
++#define C0_ERREPC $30
++#define C0_DESAVE $31
++
++/*
++ * LEAF - declare leaf routine
++ */
++#define LEAF(symbol) \
++ .globl symbol; \
++ .align 2; \
++ .type symbol,@function; \
++ .ent symbol,0; \
++symbol: .frame sp,0,ra
++
++/*
++ * END - mark end of function
++ */
++#define END(function) \
++ .end function; \
++ .size function,.-function
++
++#define _ULCAST_
++
++#else
++
++/*
++ * The following macros are especially useful for __asm__
++ * inline assembler.
++ */
++#ifndef __STR
++#define __STR(x) #x
++#endif
++#ifndef STR
++#define STR(x) __STR(x)
++#endif
++
++#define _ULCAST_ (unsigned long)
++
++
++/*
++ * CP0 Registers
++ */
++
++#define C0_INX 0 /* CP0: TLB Index */
++#define C0_RAND 1 /* CP0: TLB Random */
++#define C0_TLBLO0 2 /* CP0: TLB EntryLo0 */
++#define C0_TLBLO C0_TLBLO0 /* CP0: TLB EntryLo0 */
++#define C0_TLBLO1 3 /* CP0: TLB EntryLo1 */
++#define C0_CTEXT 4 /* CP0: Context */
++#define C0_PGMASK 5 /* CP0: TLB PageMask */
++#define C0_WIRED 6 /* CP0: TLB Wired */
++#define C0_BADVADDR 8 /* CP0: Bad Virtual Address */
++#define C0_COUNT 9 /* CP0: Count */
++#define C0_TLBHI 10 /* CP0: TLB EntryHi */
++#define C0_COMPARE 11 /* CP0: Compare */
++#define C0_SR 12 /* CP0: Processor Status */
++#define C0_STATUS C0_SR /* CP0: Processor Status */
++#define C0_CAUSE 13 /* CP0: Exception Cause */
++#define C0_EPC 14 /* CP0: Exception PC */
++#define C0_PRID 15 /* CP0: Processor Revision Indentifier */
++#define C0_CONFIG 16 /* CP0: Config */
++#define C0_LLADDR 17 /* CP0: LLAddr */
++#define C0_WATCHLO 18 /* CP0: WatchpointLo */
++#define C0_WATCHHI 19 /* CP0: WatchpointHi */
++#define C0_XCTEXT 20 /* CP0: XContext */
++#define C0_DIAGNOSTIC 22 /* CP0: Diagnostic */
++#define C0_BROADCOM C0_DIAGNOSTIC /* CP0: Broadcom Register */
++#define C0_PERFORMANCE 25 /* CP0: Performance Counter/Control Registers */
++#define C0_ECC 26 /* CP0: ECC */
++#define C0_CACHEERR 27 /* CP0: CacheErr */
++#define C0_TAGLO 28 /* CP0: TagLo */
++#define C0_TAGHI 29 /* CP0: TagHi */
++#define C0_ERREPC 30 /* CP0: ErrorEPC */
++#define C0_DESAVE 31 /* CP0: DebugSave */
++
++#endif /* _LANGUAGE_ASSEMBLY */
++
++/*
++ * Memory segments (32bit kernel mode addresses)
++ */
++#undef KUSEG
++#undef KSEG0
++#undef KSEG1
++#undef KSEG2
++#undef KSEG3
++#define KUSEG 0x00000000
++#define KSEG0 0x80000000
++#define KSEG1 0xa0000000
++#define KSEG2 0xc0000000
++#define KSEG3 0xe0000000
++#define PHYSADDR_MASK 0x1fffffff
++
++/*
++ * Map an address to a certain kernel segment
++ */
++#undef PHYSADDR
++#undef KSEG0ADDR
++#undef KSEG1ADDR
++#undef KSEG2ADDR
++#undef KSEG3ADDR
++
++#define PHYSADDR(a) (_ULCAST_(a) & PHYSADDR_MASK)
++#define KSEG0ADDR(a) ((_ULCAST_(a) & PHYSADDR_MASK) | KSEG0)
++#define KSEG1ADDR(a) ((_ULCAST_(a) & PHYSADDR_MASK) | KSEG1)
++#define KSEG2ADDR(a) ((_ULCAST_(a) & PHYSADDR_MASK) | KSEG2)
++#define KSEG3ADDR(a) ((_ULCAST_(a) & PHYSADDR_MASK) | KSEG3)
++
++
++#ifndef Index_Invalidate_I
++/*
++ * Cache Operations
++ */
++#define Index_Invalidate_I 0x00
++#define Index_Writeback_Inv_D 0x01
++#define Index_Invalidate_SI 0x02
++#define Index_Writeback_Inv_SD 0x03
++#define Index_Load_Tag_I 0x04
++#define Index_Load_Tag_D 0x05
++#define Index_Load_Tag_SI 0x06
++#define Index_Load_Tag_SD 0x07
++#define Index_Store_Tag_I 0x08
++#define Index_Store_Tag_D 0x09
++#define Index_Store_Tag_SI 0x0A
++#define Index_Store_Tag_SD 0x0B
++#define Create_Dirty_Excl_D 0x0d
++#define Create_Dirty_Excl_SD 0x0f
++#define Hit_Invalidate_I 0x10
++#define Hit_Invalidate_D 0x11
++#define Hit_Invalidate_SI 0x12
++#define Hit_Invalidate_SD 0x13
++#define Fill_I 0x14
++#define Hit_Writeback_Inv_D 0x15
++ /* 0x16 is unused */
++#define Hit_Writeback_Inv_SD 0x17
++#define R5K_Page_Invalidate_S 0x17
++#define Hit_Writeback_I 0x18
++#define Hit_Writeback_D 0x19
++ /* 0x1a is unused */
++#define Hit_Writeback_SD 0x1b
++ /* 0x1c is unused */
++ /* 0x1e is unused */
++#define Hit_Set_Virtual_SI 0x1e
++#define Hit_Set_Virtual_SD 0x1f
++#endif
++
++
++/*
++ * R4x00 interrupt enable / cause bits
++ */
++#define IE_SW0 (_ULCAST_(1) << 8)
++#define IE_SW1 (_ULCAST_(1) << 9)
++#define IE_IRQ0 (_ULCAST_(1) << 10)
++#define IE_IRQ1 (_ULCAST_(1) << 11)
++#define IE_IRQ2 (_ULCAST_(1) << 12)
++#define IE_IRQ3 (_ULCAST_(1) << 13)
++#define IE_IRQ4 (_ULCAST_(1) << 14)
++#define IE_IRQ5 (_ULCAST_(1) << 15)
++
++#ifndef ST0_UM
++/*
++ * Bitfields in the mips32 cp0 status register
++ */
++#define ST0_IE 0x00000001
++#define ST0_EXL 0x00000002
++#define ST0_ERL 0x00000004
++#define ST0_UM 0x00000010
++#define ST0_SWINT0 0x00000100
++#define ST0_SWINT1 0x00000200
++#define ST0_HWINT0 0x00000400
++#define ST0_HWINT1 0x00000800
++#define ST0_HWINT2 0x00001000
++#define ST0_HWINT3 0x00002000
++#define ST0_HWINT4 0x00004000
++#define ST0_HWINT5 0x00008000
++#define ST0_IM 0x0000ff00
++#define ST0_NMI 0x00080000
++#define ST0_SR 0x00100000
++#define ST0_TS 0x00200000
++#define ST0_BEV 0x00400000
++#define ST0_RE 0x02000000
++#define ST0_RP 0x08000000
++#define ST0_CU 0xf0000000
++#define ST0_CU0 0x10000000
++#define ST0_CU1 0x20000000
++#define ST0_CU2 0x40000000
++#define ST0_CU3 0x80000000
++#endif
++
++
++/*
++ * Bitfields in the mips32 cp0 cause register
++ */
++#define C_EXC 0x0000007c
++#define C_EXC_SHIFT 2
++#define C_INT 0x0000ff00
++#define C_INT_SHIFT 8
++#define C_SW0 (_ULCAST_(1) << 8)
++#define C_SW1 (_ULCAST_(1) << 9)
++#define C_IRQ0 (_ULCAST_(1) << 10)
++#define C_IRQ1 (_ULCAST_(1) << 11)
++#define C_IRQ2 (_ULCAST_(1) << 12)
++#define C_IRQ3 (_ULCAST_(1) << 13)
++#define C_IRQ4 (_ULCAST_(1) << 14)
++#define C_IRQ5 (_ULCAST_(1) << 15)
++#define C_WP 0x00400000
++#define C_IV 0x00800000
++#define C_CE 0x30000000
++#define C_CE_SHIFT 28
++#define C_BD 0x80000000
++
++/* Values in C_EXC */
++#define EXC_INT 0
++#define EXC_TLBM 1
++#define EXC_TLBL 2
++#define EXC_TLBS 3
++#define EXC_AEL 4
++#define EXC_AES 5
++#define EXC_IBE 6
++#define EXC_DBE 7
++#define EXC_SYS 8
++#define EXC_BPT 9
++#define EXC_RI 10
++#define EXC_CU 11
++#define EXC_OV 12
++#define EXC_TR 13
++#define EXC_WATCH 23
++#define EXC_MCHK 24
++
++
++/*
++ * Bits in the cp0 config register.
++ */
++#define CONF_CM_CACHABLE_NO_WA 0
++#define CONF_CM_CACHABLE_WA 1
++#define CONF_CM_UNCACHED 2
++#define CONF_CM_CACHABLE_NONCOHERENT 3
++#define CONF_CM_CACHABLE_CE 4
++#define CONF_CM_CACHABLE_COW 5
++#define CONF_CM_CACHABLE_CUW 6
++#define CONF_CM_CACHABLE_ACCELERATED 7
++#define CONF_CM_CMASK 7
++#define CONF_CU (_ULCAST_(1) << 3)
++#define CONF_DB (_ULCAST_(1) << 4)
++#define CONF_IB (_ULCAST_(1) << 5)
++#define CONF_SE (_ULCAST_(1) << 12)
++#define CONF_SC (_ULCAST_(1) << 17)
++#define CONF_AC (_ULCAST_(1) << 23)
++#define CONF_HALT (_ULCAST_(1) << 25)
++
++
++/*
++ * Bits in the cp0 config register select 1.
++ */
++#define CONF1_FP 0x00000001 /* FPU present */
++#define CONF1_EP 0x00000002 /* EJTAG present */
++#define CONF1_CA 0x00000004 /* mips16 implemented */
++#define CONF1_WR 0x00000008 /* Watch registers present */
++#define CONF1_PC 0x00000010 /* Performance counters present */
++#define CONF1_DA_SHIFT 7 /* D$ associativity */
++#define CONF1_DA_MASK 0x00000380
++#define CONF1_DA_BASE 1
++#define CONF1_DL_SHIFT 10 /* D$ line size */
++#define CONF1_DL_MASK 0x00001c00
++#define CONF1_DL_BASE 2
++#define CONF1_DS_SHIFT 13 /* D$ sets/way */
++#define CONF1_DS_MASK 0x0000e000
++#define CONF1_DS_BASE 64
++#define CONF1_IA_SHIFT 16 /* I$ associativity */
++#define CONF1_IA_MASK 0x00070000
++#define CONF1_IA_BASE 1
++#define CONF1_IL_SHIFT 19 /* I$ line size */
++#define CONF1_IL_MASK 0x00380000
++#define CONF1_IL_BASE 2
++#define CONF1_IS_SHIFT 22 /* Instruction cache sets/way */
++#define CONF1_IS_MASK 0x01c00000
++#define CONF1_IS_BASE 64
++#define CONF1_MS_MASK 0x7e000000 /* Number of tlb entries */
++#define CONF1_MS_SHIFT 25
++
++/* PRID register */
++#define PRID_COPT_MASK 0xff000000
++#define PRID_COMP_MASK 0x00ff0000
++#define PRID_IMP_MASK 0x0000ff00
++#define PRID_REV_MASK 0x000000ff
++
++#define PRID_COMP_LEGACY 0x000000
++#define PRID_COMP_MIPS 0x010000
++#define PRID_COMP_BROADCOM 0x020000
++#define PRID_COMP_ALCHEMY 0x030000
++#define PRID_COMP_SIBYTE 0x040000
++#define PRID_IMP_BCM4710 0x4000
++#define PRID_IMP_BCM3302 0x9000
++#define PRID_IMP_BCM3303 0x9100
++
++#define PRID_IMP_UNKNOWN 0xff00
++
++#define BCM330X(id) \
++ (((id & (PRID_COMP_MASK | PRID_IMP_MASK)) == (PRID_COMP_BROADCOM | PRID_IMP_BCM3302)) \
++ || ((id & (PRID_COMP_MASK | PRID_IMP_MASK)) == (PRID_COMP_BROADCOM | PRID_IMP_BCM3303)))
++
++/* Bits in C0_BROADCOM */
++#define BRCM_PFC_AVAIL 0x20000000 /* PFC is available */
++#define BRCM_DC_ENABLE 0x40000000 /* Enable Data $ */
++#define BRCM_IC_ENABLE 0x80000000 /* Enable Instruction $ */
++#define BRCM_PFC_ENABLE 0x00400000 /* Obsolete? Enable PFC (at least on 4310) */
++
++/* PreFetch Cache aka Read Ahead Cache */
++
++#define PFC_CR0 0xff400000 /* control reg 0 */
++#define PFC_CR1 0xff400004 /* control reg 1 */
++
++/* PFC operations */
++#define PFC_I 0x00000001 /* Enable PFC use for instructions */
++#define PFC_D 0x00000002 /* Enable PFC use for data */
++#define PFC_PFI 0x00000004 /* Enable seq. prefetch for instructions */
++#define PFC_PFD 0x00000008 /* Enable seq. prefetch for data */
++#define PFC_CINV 0x00000010 /* Enable selective (i/d) cacheop flushing */
++#define PFC_NCH 0x00000020 /* Disable flushing based on cacheops */
++#define PFC_DPF 0x00000040 /* Enable directional prefetching */
++#define PFC_FLUSH 0x00000100 /* Flush the PFC */
++#define PFC_BRR 0x40000000 /* Bus error indication */
++#define PFC_PWR 0x80000000 /* Disable power saving (clock gating) */
++
++/* Handy defaults */
++#define PFC_DISABLED 0
++#define PFC_AUTO 0xffffffff /* auto select the default mode */
++#define PFC_INST (PFC_I | PFC_PFI | PFC_CINV)
++#define PFC_INST_NOPF (PFC_I | PFC_CINV)
++#define PFC_DATA (PFC_D | PFC_PFD | PFC_CINV)
++#define PFC_DATA_NOPF (PFC_D | PFC_CINV)
++#define PFC_I_AND_D (PFC_INST | PFC_DATA)
++#define PFC_I_AND_D_NOPF (PFC_INST_NOPF | PFC_DATA_NOPF)
++
++
++/*
++ * These are the UART port assignments, expressed as offsets from the base
++ * register. These assignments should hold for any serial port based on
++ * a 8250, 16450, or 16550(A).
++ */
++
++#define UART_RX 0 /* In: Receive buffer (DLAB=0) */
++#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */
++#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */
++#define UART_DLM 1 /* Out: Divisor Latch High (DLAB=1) */
++#define UART_LCR 3 /* Out: Line Control Register */
++#define UART_MCR 4 /* Out: Modem Control Register */
++#define UART_LSR 5 /* In: Line Status Register */
++#define UART_MSR 6 /* In: Modem Status Register */
++#define UART_SCR 7 /* I/O: Scratch Register */
++#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
++#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */
++#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
++#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
++#define UART_LSR_RXRDY 0x01 /* Receiver ready */
++
++
++#ifndef _LANGUAGE_ASSEMBLY
++
++/*
++ * Macros to access the system control coprocessor
++ */
++
++#define MFC0(source, sel) \
++({ \
++ int __res; \
++ __asm__ __volatile__( \
++ ".set\tnoreorder\n\t" \
++ ".set\tnoat\n\t" \
++ ".word\t"STR(0x40010000 | ((source)<<11) | (sel))"\n\t" \
++ "move\t%0,$1\n\t" \
++ ".set\tat\n\t" \
++ ".set\treorder" \
++ :"=r" (__res) \
++ : \
++ :"$1"); \
++ __res; \
++})
++
++#define MTC0(source, sel, value) \
++do { \
++ __asm__ __volatile__( \
++ ".set\tnoreorder\n\t" \
++ ".set\tnoat\n\t" \
++ "move\t$1,%z0\n\t" \
++ ".word\t"STR(0x40810000 | ((source)<<11) | (sel))"\n\t" \
++ ".set\tat\n\t" \
++ ".set\treorder" \
++ : \
++ :"jr" (value) \
++ :"$1"); \
++} while (0)
++
++#define get_c0_count() \
++({ \
++ int __res; \
++ __asm__ __volatile__( \
++ ".set\tnoreorder\n\t" \
++ ".set\tnoat\n\t" \
++ "mfc0\t%0,$9\n\t" \
++ ".set\tat\n\t" \
++ ".set\treorder" \
++ :"=r" (__res)); \
++ __res; \
++})
++
++static INLINE void icache_probe(uint32 config1, uint *size, uint *lsize)
++{
++ uint lsz, sets, ways;
++
++ /* Instruction Cache Size = Associativity * Line Size * Sets Per Way */
++ if ((lsz = ((config1 & CONF1_IL_MASK) >> CONF1_IL_SHIFT)))
++ lsz = CONF1_IL_BASE << lsz;
++ sets = CONF1_IS_BASE << ((config1 & CONF1_IS_MASK) >> CONF1_IS_SHIFT);
++ ways = CONF1_IA_BASE + ((config1 & CONF1_IA_MASK) >> CONF1_IA_SHIFT);
++ *size = lsz * sets * ways;
++ *lsize = lsz;
++}
++
++static INLINE void dcache_probe(uint32 config1, uint *size, uint *lsize)
++{
++ uint lsz, sets, ways;
++
++ /* Data Cache Size = Associativity * Line Size * Sets Per Way */
++ if ((lsz = ((config1 & CONF1_DL_MASK) >> CONF1_DL_SHIFT)))
++ lsz = CONF1_DL_BASE << lsz;
++ sets = CONF1_DS_BASE << ((config1 & CONF1_DS_MASK) >> CONF1_DS_SHIFT);
++ ways = CONF1_DA_BASE + ((config1 & CONF1_DA_MASK) >> CONF1_DA_SHIFT);
++ *size = lsz * sets * ways;
++ *lsize = lsz;
++}
++
++#define cache_op(base, op) \
++ __asm__ __volatile__(" \
++ .set noreorder; \
++ .set mips3; \
++ cache %1, (%0); \
++ .set mips0; \
++ .set reorder" \
++ : \
++ : "r" (base), \
++ "i" (op));
++
++#define cache_unroll4(base, delta, op) \
++ __asm__ __volatile__(" \
++ .set noreorder; \
++ .set mips3; \
++ cache %1,0(%0); \
++ cache %1,delta(%0); \
++ cache %1,(2 * delta)(%0); \
++ cache %1,(3 * delta)(%0); \
++ .set mips0; \
++ .set reorder" \
++ : \
++ : "r" (base), \
++ "i" (op));
++
++#endif /* !_LANGUAGE_ASSEMBLY */
++
++#endif /* _MISPINC_H */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/osl.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/osl.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/osl.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/osl.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,42 @@
++/*
++ * OS Abstraction Layer
++ *
++ * Copyright 2005, 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.
++ * $Id$
++ */
++
++#ifndef _osl_h_
++#define _osl_h_
++
++/* osl handle type forward declaration */
++typedef struct os_handle osl_t;
++
++#if defined(linux)
++#include <linux_osl.h>
++#elif defined(NDIS)
++#include <ndis_osl.h>
++#elif defined(_CFE_)
++#include <cfe_osl.h>
++#elif defined(_HNDRTE_)
++#include <hndrte_osl.h>
++#elif defined(_MINOSL_)
++#include <min_osl.h>
++#elif PMON
++#include <pmon_osl.h>
++#elif defined(MACOSX)
++#include <macosx_osl.h>
++#else
++#error "Unsupported OSL requested"
++#endif
++
++/* handy */
++#define SET_REG(r, mask, val) W_REG((r), ((R_REG(r) & ~(mask)) | (val)))
++#define MAXPRIO 7 /* 0-7 */
++
++#endif /* _osl_h_ */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/pcicfg.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/pcicfg.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/pcicfg.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/pcicfg.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,398 @@
++/*
++ * pcicfg.h: PCI configuration constants and structures.
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#ifndef _h_pci_
++#define _h_pci_
++
++/* The following inside ifndef's so we don't collide with NTDDK.H */
++#ifndef PCI_MAX_BUS
++#define PCI_MAX_BUS 0x100
++#endif
++#ifndef PCI_MAX_DEVICES
++#define PCI_MAX_DEVICES 0x20
++#endif
++#ifndef PCI_MAX_FUNCTION
++#define PCI_MAX_FUNCTION 0x8
++#endif
++
++#ifndef PCI_INVALID_VENDORID
++#define PCI_INVALID_VENDORID 0xffff
++#endif
++#ifndef PCI_INVALID_DEVICEID
++#define PCI_INVALID_DEVICEID 0xffff
++#endif
++
++
++/* Convert between bus-slot-function-register and config addresses */
++
++#define PCICFG_BUS_SHIFT 16 /* Bus shift */
++#define PCICFG_SLOT_SHIFT 11 /* Slot shift */
++#define PCICFG_FUN_SHIFT 8 /* Function shift */
++#define PCICFG_OFF_SHIFT 0 /* Register shift */
++
++#define PCICFG_BUS_MASK 0xff /* Bus mask */
++#define PCICFG_SLOT_MASK 0x1f /* Slot mask */
++#define PCICFG_FUN_MASK 7 /* Function mask */
++#define PCICFG_OFF_MASK 0xff /* Bus mask */
++
++#define PCI_CONFIG_ADDR(b, s, f, o) \
++ ((((b) & PCICFG_BUS_MASK) << PCICFG_BUS_SHIFT) \
++ | (((s) & PCICFG_SLOT_MASK) << PCICFG_SLOT_SHIFT) \
++ | (((f) & PCICFG_FUN_MASK) << PCICFG_FUN_SHIFT) \
++ | (((o) & PCICFG_OFF_MASK) << PCICFG_OFF_SHIFT))
++
++#define PCI_CONFIG_BUS(a) (((a) >> PCICFG_BUS_SHIFT) & PCICFG_BUS_MASK)
++#define PCI_CONFIG_SLOT(a) (((a) >> PCICFG_SLOT_SHIFT) & PCICFG_SLOT_MASK)
++#define PCI_CONFIG_FUN(a) (((a) >> PCICFG_FUN_SHIFT) & PCICFG_FUN_MASK)
++#define PCI_CONFIG_OFF(a) (((a) >> PCICFG_OFF_SHIFT) & PCICFG_OFF_MASK)
++
++/* The actual config space */
++
++#define PCI_BAR_MAX 6
++
++#define PCI_ROM_BAR 8
++
++#define PCR_RSVDA_MAX 2
++
++/* pci config status reg has a bit to indicate that capability ptr is present*/
++
++#define PCI_CAPPTR_PRESENT 0x0010
++
++typedef struct _pci_config_regs {
++ unsigned short vendor;
++ unsigned short device;
++ unsigned short command;
++ unsigned short status;
++ unsigned char rev_id;
++ unsigned char prog_if;
++ unsigned char sub_class;
++ unsigned char base_class;
++ unsigned char cache_line_size;
++ unsigned char latency_timer;
++ unsigned char header_type;
++ unsigned char bist;
++ unsigned long base[PCI_BAR_MAX];
++ unsigned long cardbus_cis;
++ unsigned short subsys_vendor;
++ unsigned short subsys_id;
++ unsigned long baserom;
++ unsigned long rsvd_a[PCR_RSVDA_MAX];
++ unsigned char int_line;
++ unsigned char int_pin;
++ unsigned char min_gnt;
++ unsigned char max_lat;
++ unsigned char dev_dep[192];
++} pci_config_regs;
++
++#define SZPCR (sizeof (pci_config_regs))
++#define MINSZPCR 64 /* offsetof (dev_dep[0] */
++
++/* A structure for the config registers is nice, but in most
++ * systems the config space is not memory mapped, so we need
++ * filed offsetts. :-(
++ */
++#define PCI_CFG_VID 0
++#define PCI_CFG_DID 2
++#define PCI_CFG_CMD 4
++#define PCI_CFG_STAT 6
++#define PCI_CFG_REV 8
++#define PCI_CFG_PROGIF 9
++#define PCI_CFG_SUBCL 0xa
++#define PCI_CFG_BASECL 0xb
++#define PCI_CFG_CLSZ 0xc
++#define PCI_CFG_LATTIM 0xd
++#define PCI_CFG_HDR 0xe
++#define PCI_CFG_BIST 0xf
++#define PCI_CFG_BAR0 0x10
++#define PCI_CFG_BAR1 0x14
++#define PCI_CFG_BAR2 0x18
++#define PCI_CFG_BAR3 0x1c
++#define PCI_CFG_BAR4 0x20
++#define PCI_CFG_BAR5 0x24
++#define PCI_CFG_CIS 0x28
++#define PCI_CFG_SVID 0x2c
++#define PCI_CFG_SSID 0x2e
++#define PCI_CFG_ROMBAR 0x30
++#define PCI_CFG_CAPPTR 0x34
++#define PCI_CFG_INT 0x3c
++#define PCI_CFG_PIN 0x3d
++#define PCI_CFG_MINGNT 0x3e
++#define PCI_CFG_MAXLAT 0x3f
++
++/* Classes and subclasses */
++
++typedef enum {
++ PCI_CLASS_OLD = 0,
++ PCI_CLASS_DASDI,
++ PCI_CLASS_NET,
++ PCI_CLASS_DISPLAY,
++ PCI_CLASS_MMEDIA,
++ PCI_CLASS_MEMORY,
++ PCI_CLASS_BRIDGE,
++ PCI_CLASS_COMM,
++ PCI_CLASS_BASE,
++ PCI_CLASS_INPUT,
++ PCI_CLASS_DOCK,
++ PCI_CLASS_CPU,
++ PCI_CLASS_SERIAL,
++ PCI_CLASS_INTELLIGENT = 0xe,
++ PCI_CLASS_SATELLITE,
++ PCI_CLASS_CRYPT,
++ PCI_CLASS_DSP,
++ PCI_CLASS_MAX
++} pci_classes;
++
++typedef enum {
++ PCI_DASDI_SCSI,
++ PCI_DASDI_IDE,
++ PCI_DASDI_FLOPPY,
++ PCI_DASDI_IPI,
++ PCI_DASDI_RAID,
++ PCI_DASDI_OTHER = 0x80
++} pci_dasdi_subclasses;
++
++typedef enum {
++ PCI_NET_ETHER,
++ PCI_NET_TOKEN,
++ PCI_NET_FDDI,
++ PCI_NET_ATM,
++ PCI_NET_OTHER = 0x80
++} pci_net_subclasses;
++
++typedef enum {
++ PCI_DISPLAY_VGA,
++ PCI_DISPLAY_XGA,
++ PCI_DISPLAY_3D,
++ PCI_DISPLAY_OTHER = 0x80
++} pci_display_subclasses;
++
++typedef enum {
++ PCI_MMEDIA_VIDEO,
++ PCI_MMEDIA_AUDIO,
++ PCI_MMEDIA_PHONE,
++ PCI_MEDIA_OTHER = 0x80
++} pci_mmedia_subclasses;
++
++typedef enum {
++ PCI_MEMORY_RAM,
++ PCI_MEMORY_FLASH,
++ PCI_MEMORY_OTHER = 0x80
++} pci_memory_subclasses;
++
++typedef enum {
++ PCI_BRIDGE_HOST,
++ PCI_BRIDGE_ISA,
++ PCI_BRIDGE_EISA,
++ PCI_BRIDGE_MC,
++ PCI_BRIDGE_PCI,
++ PCI_BRIDGE_PCMCIA,
++ PCI_BRIDGE_NUBUS,
++ PCI_BRIDGE_CARDBUS,
++ PCI_BRIDGE_RACEWAY,
++ PCI_BRIDGE_OTHER = 0x80
++} pci_bridge_subclasses;
++
++typedef enum {
++ PCI_COMM_UART,
++ PCI_COMM_PARALLEL,
++ PCI_COMM_MULTIUART,
++ PCI_COMM_MODEM,
++ PCI_COMM_OTHER = 0x80
++} pci_comm_subclasses;
++
++typedef enum {
++ PCI_BASE_PIC,
++ PCI_BASE_DMA,
++ PCI_BASE_TIMER,
++ PCI_BASE_RTC,
++ PCI_BASE_PCI_HOTPLUG,
++ PCI_BASE_OTHER = 0x80
++} pci_base_subclasses;
++
++typedef enum {
++ PCI_INPUT_KBD,
++ PCI_INPUT_PEN,
++ PCI_INPUT_MOUSE,
++ PCI_INPUT_SCANNER,
++ PCI_INPUT_GAMEPORT,
++ PCI_INPUT_OTHER = 0x80
++} pci_input_subclasses;
++
++typedef enum {
++ PCI_DOCK_GENERIC,
++ PCI_DOCK_OTHER = 0x80
++} pci_dock_subclasses;
++
++typedef enum {
++ PCI_CPU_386,
++ PCI_CPU_486,
++ PCI_CPU_PENTIUM,
++ PCI_CPU_ALPHA = 0x10,
++ PCI_CPU_POWERPC = 0x20,
++ PCI_CPU_MIPS = 0x30,
++ PCI_CPU_COPROC = 0x40,
++ PCI_CPU_OTHER = 0x80
++} pci_cpu_subclasses;
++
++typedef enum {
++ PCI_SERIAL_IEEE1394,
++ PCI_SERIAL_ACCESS,
++ PCI_SERIAL_SSA,
++ PCI_SERIAL_USB,
++ PCI_SERIAL_FIBER,
++ PCI_SERIAL_SMBUS,
++ PCI_SERIAL_OTHER = 0x80
++} pci_serial_subclasses;
++
++typedef enum {
++ PCI_INTELLIGENT_I2O,
++} pci_intelligent_subclasses;
++
++typedef enum {
++ PCI_SATELLITE_TV,
++ PCI_SATELLITE_AUDIO,
++ PCI_SATELLITE_VOICE,
++ PCI_SATELLITE_DATA,
++ PCI_SATELLITE_OTHER = 0x80
++} pci_satellite_subclasses;
++
++typedef enum {
++ PCI_CRYPT_NETWORK,
++ PCI_CRYPT_ENTERTAINMENT,
++ PCI_CRYPT_OTHER = 0x80
++} pci_crypt_subclasses;
++
++typedef enum {
++ PCI_DSP_DPIO,
++ PCI_DSP_OTHER = 0x80
++} pci_dsp_subclasses;
++
++/* Header types */
++typedef enum {
++ PCI_HEADER_NORMAL,
++ PCI_HEADER_BRIDGE,
++ PCI_HEADER_CARDBUS
++} pci_header_types;
++
++
++/* Overlay for a PCI-to-PCI bridge */
++
++#define PPB_RSVDA_MAX 2
++#define PPB_RSVDD_MAX 8
++
++typedef struct _ppb_config_regs {
++ unsigned short vendor;
++ unsigned short device;
++ unsigned short command;
++ unsigned short status;
++ unsigned char rev_id;
++ unsigned char prog_if;
++ unsigned char sub_class;
++ unsigned char base_class;
++ unsigned char cache_line_size;
++ unsigned char latency_timer;
++ unsigned char header_type;
++ unsigned char bist;
++ unsigned long rsvd_a[PPB_RSVDA_MAX];
++ unsigned char prim_bus;
++ unsigned char sec_bus;
++ unsigned char sub_bus;
++ unsigned char sec_lat;
++ unsigned char io_base;
++ unsigned char io_lim;
++ unsigned short sec_status;
++ unsigned short mem_base;
++ unsigned short mem_lim;
++ unsigned short pf_mem_base;
++ unsigned short pf_mem_lim;
++ unsigned long pf_mem_base_hi;
++ unsigned long pf_mem_lim_hi;
++ unsigned short io_base_hi;
++ unsigned short io_lim_hi;
++ unsigned short subsys_vendor;
++ unsigned short subsys_id;
++ unsigned long rsvd_b;
++ unsigned char rsvd_c;
++ unsigned char int_pin;
++ unsigned short bridge_ctrl;
++ unsigned char chip_ctrl;
++ unsigned char diag_ctrl;
++ unsigned short arb_ctrl;
++ unsigned long rsvd_d[PPB_RSVDD_MAX];
++ unsigned char dev_dep[192];
++} ppb_config_regs;
++
++
++/* PCI CAPABILITY DEFINES */
++#define PCI_CAP_POWERMGMTCAP_ID 0x01
++#define PCI_CAP_MSICAP_ID 0x05
++
++/* Data structure to define the Message Signalled Interrupt facility
++ * Valid for PCI and PCIE configurations */
++typedef struct _pciconfig_cap_msi {
++ unsigned char capID;
++ unsigned char nextptr;
++ unsigned short msgctrl;
++ unsigned int msgaddr;
++} pciconfig_cap_msi;
++
++/* Data structure to define the Power managment facility
++ * Valid for PCI and PCIE configurations */
++typedef struct _pciconfig_cap_pwrmgmt {
++ unsigned char capID;
++ unsigned char nextptr;
++ unsigned short pme_cap;
++ unsigned short pme_sts_ctrl;
++ unsigned char pme_bridge_ext;
++ unsigned char data;
++} pciconfig_cap_pwrmgmt;
++
++/* Everything below is BRCM HND proprietary */
++
++#define PCI_BAR0_WIN 0x80 /* backplane addres space accessed by BAR0 */
++#define PCI_BAR1_WIN 0x84 /* backplane addres space accessed by BAR1 */
++#define PCI_SPROM_CONTROL 0x88 /* sprom property control */
++#define PCI_BAR1_CONTROL 0x8c /* BAR1 region burst control */
++#define PCI_INT_STATUS 0x90 /* PCI and other cores interrupts */
++#define PCI_INT_MASK 0x94 /* mask of PCI and other cores interrupts */
++#define PCI_TO_SB_MB 0x98 /* signal backplane interrupts */
++#define PCI_BACKPLANE_ADDR 0xA0 /* address an arbitrary location on the system backplane */
++#define PCI_BACKPLANE_DATA 0xA4 /* data at the location specified by above address register */
++#define PCI_GPIO_IN 0xb0 /* pci config space gpio input (>=rev3) */
++#define PCI_GPIO_OUT 0xb4 /* pci config space gpio output (>=rev3) */
++#define PCI_GPIO_OUTEN 0xb8 /* pci config space gpio output enable (>=rev3) */
++
++#define PCI_BAR0_SPROM_OFFSET (4 * 1024) /* bar0 + 4K accesses external sprom */
++#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) /* bar0 + 6K accesses pci core registers */
++
++/* PCI_INT_STATUS */
++#define PCI_SBIM_STATUS_SERR 0x4 /* backplane SBErr interrupt status */
++
++/* PCI_INT_MASK */
++#define PCI_SBIM_SHIFT 8 /* backplane core interrupt mask bits offset */
++#define PCI_SBIM_MASK 0xff00 /* backplane core interrupt mask */
++#define PCI_SBIM_MASK_SERR 0x4 /* backplane SBErr interrupt mask */
++
++/* PCI_SPROM_CONTROL */
++#define SPROM_BLANK 0x04 /* indicating a blank sprom */
++#define SPROM_WRITEEN 0x10 /* sprom write enable */
++#define SPROM_BOOTROM_WE 0x20 /* external bootrom write enable */
++
++#define SPROM_SIZE 256 /* sprom size in 16-bit */
++#define SPROM_CRC_RANGE 64 /* crc cover range in 16-bit */
++
++/* PCI_CFG_CMD_STAT */
++#define PCI_CFG_CMD_STAT_TA 0x08000000 /* target abort status */
++
++#endif
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/proto/ethernet.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/proto/ethernet.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/proto/ethernet.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/proto/ethernet.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,145 @@
++/*******************************************************************************
++ * $Id$
++ * Copyright 2001-2003, 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.
++ * From FreeBSD 2.2.7: Fundamental constants relating to ethernet.
++ ******************************************************************************/
++
++#ifndef _NET_ETHERNET_H_ /* use native BSD ethernet.h when available */
++#define _NET_ETHERNET_H_
++
++#ifndef _TYPEDEFS_H_
++#include "typedefs.h"
++#endif
++
++#if defined(__GNUC__)
++#define PACKED __attribute__((packed))
++#else
++#define PACKED
++#endif
++
++/*
++ * The number of bytes in an ethernet (MAC) address.
++ */
++#define ETHER_ADDR_LEN 6
++
++/*
++ * The number of bytes in the type field.
++ */
++#define ETHER_TYPE_LEN 2
++
++/*
++ * The number of bytes in the trailing CRC field.
++ */
++#define ETHER_CRC_LEN 4
++
++/*
++ * The length of the combined header.
++ */
++#define ETHER_HDR_LEN (ETHER_ADDR_LEN*2+ETHER_TYPE_LEN)
++
++/*
++ * The minimum packet length.
++ */
++#define ETHER_MIN_LEN 64
++
++/*
++ * The minimum packet user data length.
++ */
++#define ETHER_MIN_DATA 46
++
++/*
++ * The maximum packet length.
++ */
++#define ETHER_MAX_LEN 1518
++
++/*
++ * The maximum packet user data length.
++ */
++#define ETHER_MAX_DATA 1500
++
++/*
++ * Used to uniquely identify a 802.1q VLAN-tagged header.
++ */
++#define VLAN_TAG 0x8100
++
++/*
++ * Located after dest & src address in ether header.
++ */
++#define VLAN_FIELDS_OFFSET (ETHER_ADDR_LEN * 2)
++
++/*
++ * 4 bytes of vlan field info.
++ */
++#define VLAN_FIELDS_SIZE 4
++
++/* location of pri bits in 16-bit vlan fields */
++#define VLAN_PRI_SHIFT 13
++
++/* 3 bits of priority */
++#define VLAN_PRI_MASK 7
++
++/* 802.1X ethertype */
++#define ETHER_TYPE_802_1X 0x888e
++
++/*
++ * A macro to validate a length with
++ */
++#define ETHER_IS_VALID_LEN(foo) \
++ ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN)
++
++
++#ifndef __INCif_etherh /* Quick and ugly hack for VxWorks */
++/*
++ * Structure of a 10Mb/s Ethernet header.
++ */
++struct ether_header {
++ uint8 ether_dhost[ETHER_ADDR_LEN];
++ uint8 ether_shost[ETHER_ADDR_LEN];
++ uint16 ether_type;
++} PACKED ;
++
++/*
++ * Structure of a 48-bit Ethernet address.
++ */
++struct ether_addr {
++ uint8 octet[ETHER_ADDR_LEN];
++} PACKED ;
++#endif
++
++/*
++ * Takes a pointer, returns true if a 48-bit multicast address
++ * (including broadcast, since it is all ones)
++ */
++#define ETHER_ISMULTI(ea) (((uint8 *)(ea))[0] & 1)
++
++/*
++ * Takes a pointer, returns true if a 48-bit broadcast (all ones)
++ */
++#define ETHER_ISBCAST(ea) ((((uint8 *)(ea))[0] & \
++ ((uint8 *)(ea))[1] & \
++ ((uint8 *)(ea))[2] & \
++ ((uint8 *)(ea))[3] & \
++ ((uint8 *)(ea))[4] & \
++ ((uint8 *)(ea))[5]) == 0xff)
++
++static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}};
++
++/*
++ * Takes a pointer, returns true if a 48-bit null address (all zeros)
++ */
++#define ETHER_ISNULLADDR(ea) ((((uint8 *)(ea))[0] | \
++ ((uint8 *)(ea))[1] | \
++ ((uint8 *)(ea))[2] | \
++ ((uint8 *)(ea))[3] | \
++ ((uint8 *)(ea))[4] | \
++ ((uint8 *)(ea))[5]) == 0)
++
++#undef PACKED
++
++#endif /* _NET_ETHERNET_H_ */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/s5.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/s5.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/s5.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/s5.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,103 @@
++#ifndef _S5_H_
++#define _S5_H_
++/*
++ * Copyright 2003, Broadcom Corporation
++ * All Rights Reserved.
++ *
++ * Broadcom Sentry5 (S5) BCM5365, 53xx, BCM58xx SOC Internal Core
++ * and MIPS3301 (R4K) System Address Space
++ *
++ * 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, located in the file
++ * LICENSE.
++ *
++ * $Id: s5.h,v 1.3 2003/06/10 18:54:51 jfd Exp $
++ *
++ */
++
++/* BCM5365 Address map */
++#define KSEG1ADDR(x) ( (x) | 0xa0000000)
++#define BCM5365_SDRAM 0x00000000 /* 0-128MB Physical SDRAM */
++#define BCM5365_PCI_MEM 0x08000000 /* Host Mode PCI mem space (64MB) */
++#define BCM5365_PCI_CFG 0x0c000000 /* Host Mode PCI cfg space (64MB) */
++#define BCM5365_PCI_DMA 0x40000000 /* Client Mode PCI mem space (1GB)*/
++#define BCM5365_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */
++#define BCM5365_ENUM 0x18000000 /* Beginning of core enum space */
++
++/* BCM5365 Core register space */
++#define BCM5365_REG_CHIPC 0x18000000 /* Chipcommon registers */
++#define BCM5365_REG_EMAC0 0x18001000 /* Ethernet MAC0 core registers */
++#define BCM5365_REG_IPSEC 0x18002000 /* BCM582x CryptoCore registers */
++#define BCM5365_REG_USB 0x18003000 /* USB core registers */
++#define BCM5365_REG_PCI 0x18004000 /* PCI core registers */
++#define BCM5365_REG_MIPS33 0x18005000 /* MIPS core registers */
++#define BCM5365_REG_MEMC 0x18006000 /* MEMC core registers */
++#define BCM5365_REG_UARTS (BCM5365_REG_CHIPC + 0x300) /* UART regs */
++#define BCM5365_EJTAG 0xff200000 /* MIPS EJTAG space (2M) */
++
++/* COM Ports 1/2 */
++#define BCM5365_UART (BCM5365_REG_UARTS)
++#define BCM5365_UART_COM2 (BCM5365_REG_UARTS + 0x00000100)
++
++/* Registers common to MIPS33 Core used in 5365 */
++#define MIPS33_FLASH_REGION 0x1fc00000 /* Boot FLASH Region */
++#define MIPS33_EXTIF_REGION 0x1a000000 /* Chipcommon EXTIF region*/
++#define BCM5365_EXTIF 0x1b000000 /* MISC_CS */
++#define MIPS33_FLASH_REGION_AUX 0x1c000000 /* FLASH Region 2*/
++
++/* Internal Core Sonics Backplane Devices */
++#define INTERNAL_UART_COM1 BCM5365_UART
++#define INTERNAL_UART_COM2 BCM5365_UART_COM2
++#define SB_REG_CHIPC BCM5365_REG_CHIPC
++#define SB_REG_ENET0 BCM5365_REG_EMAC0
++#define SB_REG_IPSEC BCM5365_REG_IPSEC
++#define SB_REG_USB BCM5365_REG_USB
++#define SB_REG_PCI BCM5365_REG_PCI
++#define SB_REG_MIPS BCM5365_REG_MIPS33
++#define SB_REG_MEMC BCM5365_REG_MEMC
++#define SB_REG_MEMC_OFF 0x6000
++#define SB_EXTIF_SPACE MIPS33_EXTIF_REGION
++#define SB_FLASH_SPACE MIPS33_FLASH_REGION
++
++/*
++ * XXX
++ * 5365-specific backplane interrupt flag numbers. This should be done
++ * dynamically instead.
++ */
++#define SBFLAG_PCI 0
++#define SBFLAG_ENET0 1
++#define SBFLAG_ILINE20 2
++#define SBFLAG_CODEC 3
++#define SBFLAG_USB 4
++#define SBFLAG_EXTIF 5
++#define SBFLAG_ENET1 6
++
++/* BCM95365 Local Bus devices */
++#define BCM95365K_RESET_ADDR BCM5365_EXTIF
++#define BCM95365K_BOARDID_ADDR (BCM5365_EXTIF | 0x4000)
++#define BCM95365K_DOC_ADDR (BCM5365_EXTIF | 0x6000)
++#define BCM95365K_LED_ADDR (BCM5365_EXTIF | 0xc000)
++#define BCM95365K_TOD_REG_BASE (BCM95365K_NVRAM_ADDR | 0x1ff0)
++#define BCM95365K_NVRAM_ADDR (BCM5365_EXTIF | 0xe000)
++#define BCM95365K_NVRAM_SIZE 0x1ff0 /* 8K NVRAM : DS1743/STM48txx*/
++
++/* Write to DLR2416 VFD Display character RAM */
++#define LED_REG(x) \
++ (*(volatile unsigned char *) (KSEG1ADDR(BCM95365K_LED_ADDR) + (x)))
++
++#ifdef CONFIG_VSIM
++#define BCM5365_TRACE(trval) do { *((int *)0xa0002ff8) = (trval); \
++ } while (0)
++#else
++#define BCM5365_TRACE(trval) do { *((unsigned char *)\
++ KSEG1ADDR(BCM5365K_LED_ADDR)) = (trval); \
++ *((int *)0xa0002ff8) = (trval); } while (0)
++#endif
++
++/* BCM9536R Local Bus devices */
++#define BCM95365R_DOC_ADDR BCM5365_EXTIF
++
++
++
++#endif /*!_S5_H_ */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/sbchipc.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/sbchipc.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/sbchipc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/sbchipc.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,440 @@
++/*
++ * SiliconBackplane Chipcommon core hardware definitions.
++ *
++ * The chipcommon core provides chip identification, SB control,
++ * jtag, 0/1/2 uarts, clock frequency control, a watchdog interrupt timer,
++ * gpio interface, extbus, and support for serial and parallel flashes.
++ *
++ * $Id$
++ * Copyright 2005, 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 _SBCHIPC_H
++#define _SBCHIPC_H
++
++
++#ifndef _LANGUAGE_ASSEMBLY
++
++/* cpp contortions to concatenate w/arg prescan */
++#ifndef PAD
++#define _PADLINE(line) pad ## line
++#define _XSTR(line) _PADLINE(line)
++#define PAD _XSTR(__LINE__)
++#endif /* PAD */
++
++typedef volatile struct {
++ uint32 chipid; /* 0x0 */
++ uint32 capabilities;
++ uint32 corecontrol; /* corerev >= 1 */
++ uint32 bist;
++
++ /* OTP */
++ uint32 otpstatus; /* 0x10, corerev >= 10 */
++ uint32 otpcontrol;
++ uint32 otpprog;
++ uint32 PAD;
++
++ /* Interrupt control */
++ uint32 intstatus; /* 0x20 */
++ uint32 intmask;
++ uint32 chipcontrol; /* 0x28, rev >= 11 */
++ uint32 chipstatus; /* 0x2c, rev >= 11 */
++
++ /* Jtag Master */
++ uint32 jtagcmd; /* 0x30, rev >= 10 */
++ uint32 jtagir;
++ uint32 jtagdr;
++ uint32 jtagctrl;
++
++ /* serial flash interface registers */
++ uint32 flashcontrol; /* 0x40 */
++ uint32 flashaddress;
++ uint32 flashdata;
++ uint32 PAD[1];
++
++ /* Silicon backplane configuration broadcast control */
++ uint32 broadcastaddress; /* 0x50 */
++ uint32 broadcastdata;
++ uint32 PAD[2];
++
++ /* gpio - cleared only by power-on-reset */
++ uint32 gpioin; /* 0x60 */
++ uint32 gpioout;
++ uint32 gpioouten;
++ uint32 gpiocontrol;
++ uint32 gpiointpolarity;
++ uint32 gpiointmask;
++ uint32 PAD[2];
++
++ /* Watchdog timer */
++ uint32 watchdog; /* 0x80 */
++ uint32 PAD[1];
++
++ /*GPIO based LED powersave registers corerev >= 16*/
++ uint32 gpiotimerval; /*0x88 */
++ uint32 gpiotimeroutmask;
++
++ /* clock control */
++ uint32 clockcontrol_n; /* 0x90 */
++ uint32 clockcontrol_sb; /* aka m0 */
++ uint32 clockcontrol_pci; /* aka m1 */
++ uint32 clockcontrol_m2; /* mii/uart/mipsref */
++ uint32 clockcontrol_mips; /* aka m3 */
++ uint32 clkdiv; /* corerev >= 3 */
++ uint32 PAD[2];
++
++ /* pll delay registers (corerev >= 4) */
++ uint32 pll_on_delay; /* 0xb0 */
++ uint32 fref_sel_delay;
++ uint32 slow_clk_ctl; /* 5 < corerev < 10 */
++ uint32 PAD[1];
++
++ /* Instaclock registers (corerev >= 10) */
++ uint32 system_clk_ctl; /* 0xc0 */
++ uint32 clkstatestretch;
++ uint32 PAD[14];
++
++ /* ExtBus control registers (corerev >= 3) */
++ uint32 pcmcia_config; /* 0x100 */
++ uint32 pcmcia_memwait;
++ uint32 pcmcia_attrwait;
++ uint32 pcmcia_iowait;
++ uint32 ide_config;
++ uint32 ide_memwait;
++ uint32 ide_attrwait;
++ uint32 ide_iowait;
++ uint32 prog_config;
++ uint32 prog_waitcount;
++ uint32 flash_config;
++ uint32 flash_waitcount;
++ uint32 PAD[116];
++
++ /* uarts */
++ uint8 uart0data; /* 0x300 */
++ uint8 uart0imr;
++ uint8 uart0fcr;
++ uint8 uart0lcr;
++ uint8 uart0mcr;
++ uint8 uart0lsr;
++ uint8 uart0msr;
++ uint8 uart0scratch;
++ uint8 PAD[248]; /* corerev >= 1 */
++
++ uint8 uart1data; /* 0x400 */
++ uint8 uart1imr;
++ uint8 uart1fcr;
++ uint8 uart1lcr;
++ uint8 uart1mcr;
++ uint8 uart1lsr;
++ uint8 uart1msr;
++ uint8 uart1scratch;
++} chipcregs_t;
++
++#endif /* _LANGUAGE_ASSEMBLY */
++
++#define CC_CHIPID 0
++#define CC_CAPABILITIES 4
++#define CC_JTAGCMD 0x30
++#define CC_JTAGIR 0x34
++#define CC_JTAGDR 0x38
++#define CC_JTAGCTRL 0x3c
++#define CC_WATCHDOG 0x80
++#define CC_CLKC_N 0x90
++#define CC_CLKC_M0 0x94
++#define CC_CLKC_M1 0x98
++#define CC_CLKC_M2 0x9c
++#define CC_CLKC_M3 0xa0
++#define CC_CLKDIV 0xa4
++#define CC_SYS_CLK_CTL 0xc0
++#define CC_OTP 0x800
++
++/* chipid */
++#define CID_ID_MASK 0x0000ffff /* Chip Id mask */
++#define CID_REV_MASK 0x000f0000 /* Chip Revision mask */
++#define CID_REV_SHIFT 16 /* Chip Revision shift */
++#define CID_PKG_MASK 0x00f00000 /* Package Option mask */
++#define CID_PKG_SHIFT 20 /* Package Option shift */
++#define CID_CC_MASK 0x0f000000 /* CoreCount (corerev >= 4) */
++#define CID_CC_SHIFT 24
++
++/* capabilities */
++#define CAP_UARTS_MASK 0x00000003 /* Number of uarts */
++#define CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */
++#define CAP_UCLKSEL 0x00000018 /* UARTs clock select */
++#define CAP_UINTCLK 0x00000008 /* UARTs are driven by internal divided clock */
++#define CAP_UARTGPIO 0x00000020 /* UARTs own Gpio's 15:12 */
++#define CAP_EXTBUS 0x00000040 /* External bus present */
++#define CAP_FLASH_MASK 0x00000700 /* Type of flash */
++#define CAP_PLL_MASK 0x00038000 /* Type of PLL */
++#define CAP_PWR_CTL 0x00040000 /* Power control */
++#define CAP_OTPSIZE 0x00380000 /* OTP Size (0 = none) */
++#define CAP_OTPSIZE_SHIFT 19 /* OTP Size shift */
++#define CAP_OTPSIZE_BASE 5 /* OTP Size base */
++#define CAP_JTAGP 0x00400000 /* JTAG Master Present */
++#define CAP_ROM 0x00800000 /* Internal boot rom active */
++
++/* PLL type */
++#define PLL_NONE 0x00000000
++#define PLL_TYPE1 0x00010000 /* 48Mhz base, 3 dividers */
++#define PLL_TYPE2 0x00020000 /* 48Mhz, 4 dividers */
++#define PLL_TYPE3 0x00030000 /* 25Mhz, 2 dividers */
++#define PLL_TYPE4 0x00008000 /* 48Mhz, 4 dividers */
++#define PLL_TYPE5 0x00018000 /* 25Mhz, 4 dividers */
++#define PLL_TYPE6 0x00028000 /* 100/200 or 120/240 only */
++#define PLL_TYPE7 0x00038000 /* 25Mhz, 4 dividers */
++
++/* corecontrol */
++#define CC_UARTCLKO 0x00000001 /* Drive UART with internal clock */
++#define CC_SE 0x00000002 /* sync clk out enable (corerev >= 3) */
++
++/* Fields in the otpstatus register */
++#define OTPS_PROGFAIL 0x80000000
++#define OTPS_PROTECT 0x00000007
++#define OTPS_HW_PROTECT 0x00000001
++#define OTPS_SW_PROTECT 0x00000002
++#define OTPS_CID_PROTECT 0x00000004
++
++/* Fields in the otpcontrol register */
++#define OTPC_RECWAIT 0xff000000
++#define OTPC_PROGWAIT 0x00ffff00
++#define OTPC_PRW_SHIFT 8
++#define OTPC_MAXFAIL 0x00000038
++#define OTPC_VSEL 0x00000006
++#define OTPC_SELVL 0x00000001
++
++/* Fields in otpprog */
++#define OTPP_COL_MASK 0x000000ff
++#define OTPP_ROW_MASK 0x0000ff00
++#define OTPP_ROW_SHIFT 8
++#define OTPP_READERR 0x10000000
++#define OTPP_VALUE 0x20000000
++#define OTPP_VALUE_SHIFT 29
++#define OTPP_READ 0x40000000
++#define OTPP_START 0x80000000
++#define OTPP_BUSY 0x80000000
++
++/* jtagcmd */
++#define JCMD_START 0x80000000
++#define JCMD_BUSY 0x80000000
++#define JCMD_PAUSE 0x40000000
++#define JCMD0_ACC_MASK 0x0000f000
++#define JCMD0_ACC_IRDR 0x00000000
++#define JCMD0_ACC_DR 0x00001000
++#define JCMD0_ACC_IR 0x00002000
++#define JCMD0_ACC_RESET 0x00003000
++#define JCMD0_ACC_IRPDR 0x00004000
++#define JCMD0_ACC_PDR 0x00005000
++#define JCMD0_IRW_MASK 0x00000f00
++#define JCMD_ACC_MASK 0x000f0000 /* Changes for corerev 11 */
++#define JCMD_ACC_IRDR 0x00000000
++#define JCMD_ACC_DR 0x00010000
++#define JCMD_ACC_IR 0x00020000
++#define JCMD_ACC_RESET 0x00030000
++#define JCMD_ACC_IRPDR 0x00040000
++#define JCMD_ACC_PDR 0x00050000
++#define JCMD_IRW_MASK 0x00001f00
++#define JCMD_IRW_SHIFT 8
++#define JCMD_DRW_MASK 0x0000003f
++
++/* jtagctrl */
++#define JCTRL_FORCE_CLK 4 /* Force clock */
++#define JCTRL_EXT_EN 2 /* Enable external targets */
++#define JCTRL_EN 1 /* Enable Jtag master */
++
++/* Fields in clkdiv */
++#define CLKD_SFLASH 0x0f000000
++#define CLKD_SFLASH_SHIFT 24
++#define CLKD_OTP 0x000f0000
++#define CLKD_OTP_SHIFT 16
++#define CLKD_JTAG 0x00000f00
++#define CLKD_JTAG_SHIFT 8
++#define CLKD_UART 0x000000ff
++
++/* intstatus/intmask */
++#define CI_GPIO 0x00000001 /* gpio intr */
++#define CI_EI 0x00000002 /* ro: ext intr pin (corerev >= 3) */
++#define CI_WDRESET 0x80000000 /* watchdog reset occurred */
++
++/* slow_clk_ctl */
++#define SCC_SS_MASK 0x00000007 /* slow clock source mask */
++#define SCC_SS_LPO 0x00000000 /* source of slow clock is LPO */
++#define SCC_SS_XTAL 0x00000001 /* source of slow clock is crystal */
++#define SCC_SS_PCI 0x00000002 /* source of slow clock is PCI */
++#define SCC_LF 0x00000200 /* LPOFreqSel, 1: 160Khz, 0: 32KHz */
++#define SCC_LP 0x00000400 /* LPOPowerDown, 1: LPO is disabled, 0: LPO is enabled */
++#define SCC_FS 0x00000800 /* ForceSlowClk, 1: sb/cores running on slow clock, 0: power logic control */
++#define SCC_IP 0x00001000 /* IgnorePllOffReq, 1/0: power logic ignores/honors PLL clock disable requests from core */
++#define SCC_XC 0x00002000 /* XtalControlEn, 1/0: power logic does/doesn't disable crystal when appropriate */
++#define SCC_XP 0x00004000 /* XtalPU (RO), 1/0: crystal running/disabled */
++#define SCC_CD_MASK 0xffff0000 /* ClockDivider (SlowClk = 1/(4+divisor)) */
++#define SCC_CD_SHIFT 16
++
++/* system_clk_ctl */
++#define SYCC_IE 0x00000001 /* ILPen: Enable Idle Low Power */
++#define SYCC_AE 0x00000002 /* ALPen: Enable Active Low Power */
++#define SYCC_FP 0x00000004 /* ForcePLLOn */
++#define SYCC_AR 0x00000008 /* Force ALP (or HT if ALPen is not set */
++#define SYCC_HR 0x00000010 /* Force HT */
++#define SYCC_CD_MASK 0xffff0000 /* ClkDiv (ILP = 1/(4+divisor)) */
++#define SYCC_CD_SHIFT 16
++
++/* gpiotimerval*/
++#define GPIO_ONTIME_SHIFT 16
++
++/* clockcontrol_n */
++#define CN_N1_MASK 0x3f /* n1 control */
++#define CN_N2_MASK 0x3f00 /* n2 control */
++#define CN_N2_SHIFT 8
++#define CN_PLLC_MASK 0xf0000 /* pll control */
++#define CN_PLLC_SHIFT 16
++
++/* clockcontrol_sb/pci/uart */
++#define CC_M1_MASK 0x3f /* m1 control */
++#define CC_M2_MASK 0x3f00 /* m2 control */
++#define CC_M2_SHIFT 8
++#define CC_M3_MASK 0x3f0000 /* m3 control */
++#define CC_M3_SHIFT 16
++#define CC_MC_MASK 0x1f000000 /* mux control */
++#define CC_MC_SHIFT 24
++
++/* N3M Clock control magic field values */
++#define CC_F6_2 0x02 /* A factor of 2 in */
++#define CC_F6_3 0x03 /* 6-bit fields like */
++#define CC_F6_4 0x05 /* N1, M1 or M3 */
++#define CC_F6_5 0x09
++#define CC_F6_6 0x11
++#define CC_F6_7 0x21
++
++#define CC_F5_BIAS 5 /* 5-bit fields get this added */
++
++#define CC_MC_BYPASS 0x08
++#define CC_MC_M1 0x04
++#define CC_MC_M1M2 0x02
++#define CC_MC_M1M2M3 0x01
++#define CC_MC_M1M3 0x11
++
++/* Type 2 Clock control magic field values */
++#define CC_T2_BIAS 2 /* n1, n2, m1 & m3 bias */
++#define CC_T2M2_BIAS 3 /* m2 bias */
++
++#define CC_T2MC_M1BYP 1
++#define CC_T2MC_M2BYP 2
++#define CC_T2MC_M3BYP 4
++
++/* Type 6 Clock control magic field values */
++#define CC_T6_MMASK 1 /* bits of interest in m */
++#define CC_T6_M0 120000000 /* sb clock for m = 0 */
++#define CC_T6_M1 100000000 /* sb clock for m = 1 */
++#define SB2MIPS_T6(sb) (2 * (sb))
++
++/* Common clock base */
++#define CC_CLOCK_BASE1 24000000 /* Half the clock freq */
++#define CC_CLOCK_BASE2 12500000 /* Alternate crystal on some PLL's */
++
++/* Clock control values for 200Mhz in 5350 */
++#define CLKC_5350_N 0x0311
++#define CLKC_5350_M 0x04020009
++
++/* Flash types in the chipcommon capabilities register */
++#define FLASH_NONE 0x000 /* No flash */
++#define SFLASH_ST 0x100 /* ST serial flash */
++#define SFLASH_AT 0x200 /* Atmel serial flash */
++#define PFLASH 0x700 /* Parallel flash */
++
++/* Bits in the config registers */
++#define CC_CFG_EN 0x0001 /* Enable */
++#define CC_CFG_EM_MASK 0x000e /* Extif Mode */
++#define CC_CFG_EM_ASYNC 0x0002 /* Async/Parallel flash */
++#define CC_CFG_EM_SYNC 0x0004 /* Synchronous */
++#define CC_CFG_EM_PCMCIA 0x0008 /* PCMCIA */
++#define CC_CFG_EM_IDE 0x000a /* IDE */
++#define CC_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */
++#define CC_CFG_CD_MASK 0x0060 /* Sync: Clock divisor */
++#define CC_CFG_CE 0x0080 /* Sync: Clock enable */
++#define CC_CFG_SB 0x0100 /* Sync: Size/Bytestrobe */
++
++/* Start/busy bit in flashcontrol */
++#define SFLASH_START 0x80000000
++#define SFLASH_BUSY SFLASH_START
++
++/* flashcontrol opcodes for ST flashes */
++#define SFLASH_ST_WREN 0x0006 /* Write Enable */
++#define SFLASH_ST_WRDIS 0x0004 /* Write Disable */
++#define SFLASH_ST_RDSR 0x0105 /* Read Status Register */
++#define SFLASH_ST_WRSR 0x0101 /* Write Status Register */
++#define SFLASH_ST_READ 0x0303 /* Read Data Bytes */
++#define SFLASH_ST_PP 0x0302 /* Page Program */
++#define SFLASH_ST_SE 0x02d8 /* Sector Erase */
++#define SFLASH_ST_BE 0x00c7 /* Bulk Erase */
++#define SFLASH_ST_DP 0x00b9 /* Deep Power-down */
++#define SFLASH_ST_RES 0x03ab /* Read Electronic Signature */
++
++/* Status register bits for ST flashes */
++#define SFLASH_ST_WIP 0x01 /* Write In Progress */
++#define SFLASH_ST_WEL 0x02 /* Write Enable Latch */
++#define SFLASH_ST_BP_MASK 0x1c /* Block Protect */
++#define SFLASH_ST_BP_SHIFT 2
++#define SFLASH_ST_SRWD 0x80 /* Status Register Write Disable */
++
++/* flashcontrol opcodes for Atmel flashes */
++#define SFLASH_AT_READ 0x07e8
++#define SFLASH_AT_PAGE_READ 0x07d2
++#define SFLASH_AT_BUF1_READ
++#define SFLASH_AT_BUF2_READ
++#define SFLASH_AT_STATUS 0x01d7
++#define SFLASH_AT_BUF1_WRITE 0x0384
++#define SFLASH_AT_BUF2_WRITE 0x0387
++#define SFLASH_AT_BUF1_ERASE_PROGRAM 0x0283
++#define SFLASH_AT_BUF2_ERASE_PROGRAM 0x0286
++#define SFLASH_AT_BUF1_PROGRAM 0x0288
++#define SFLASH_AT_BUF2_PROGRAM 0x0289
++#define SFLASH_AT_PAGE_ERASE 0x0281
++#define SFLASH_AT_BLOCK_ERASE 0x0250
++#define SFLASH_AT_BUF1_WRITE_ERASE_PROGRAM 0x0382
++#define SFLASH_AT_BUF2_WRITE_ERASE_PROGRAM 0x0385
++#define SFLASH_AT_BUF1_LOAD 0x0253
++#define SFLASH_AT_BUF2_LOAD 0x0255
++#define SFLASH_AT_BUF1_COMPARE 0x0260
++#define SFLASH_AT_BUF2_COMPARE 0x0261
++#define SFLASH_AT_BUF1_REPROGRAM 0x0258
++#define SFLASH_AT_BUF2_REPROGRAM 0x0259
++
++/* Status register bits for Atmel flashes */
++#define SFLASH_AT_READY 0x80
++#define SFLASH_AT_MISMATCH 0x40
++#define SFLASH_AT_ID_MASK 0x38
++#define SFLASH_AT_ID_SHIFT 3
++
++/* OTP regions */
++#define OTP_HW_REGION OTPS_HW_PROTECT
++#define OTP_SW_REGION OTPS_SW_PROTECT
++#define OTP_CID_REGION OTPS_CID_PROTECT
++
++/* OTP regions (Byte offsets from otp size) */
++#define OTP_SWLIM_OFF (-8)
++#define OTP_CIDBASE_OFF 0
++#define OTP_CIDLIM_OFF 8
++
++/* Predefined OTP words (Word offset from otp size) */
++#define OTP_BOUNDARY_OFF (-4)
++#define OTP_HWSIGN_OFF (-3)
++#define OTP_SWSIGN_OFF (-2)
++#define OTP_CIDSIGN_OFF (-1)
++
++#define OTP_CID_OFF 0
++#define OTP_PKG_OFF 1
++#define OTP_FID_OFF 2
++#define OTP_RSV_OFF 3
++#define OTP_LIM_OFF 4
++
++#define OTP_SIGNATURE 0x578a
++#define OTP_MAGIC 0x4e56
++
++#endif /* _SBCHIPC_H */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/sbconfig.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/sbconfig.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/sbconfig.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/sbconfig.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,342 @@
++/*
++ * Broadcom SiliconBackplane hardware register definitions.
++ *
++ * Copyright 2005, 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.
++ * $Id$
++ */
++
++#ifndef _SBCONFIG_H
++#define _SBCONFIG_H
++
++/* cpp contortions to concatenate w/arg prescan */
++#ifndef PAD
++#define _PADLINE(line) pad ## line
++#define _XSTR(line) _PADLINE(line)
++#define PAD _XSTR(__LINE__)
++#endif
++
++/*
++ * SiliconBackplane Address Map.
++ * All regions may not exist on all chips.
++ */
++#define SB_SDRAM_BASE 0x00000000 /* Physical SDRAM */
++#define SB_PCI_MEM 0x08000000 /* Host Mode sb2pcitranslation0 (64 MB) */
++#define SB_PCI_CFG 0x0c000000 /* Host Mode sb2pcitranslation1 (64 MB) */
++#define SB_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */
++#define SB_ENUM_BASE 0x18000000 /* Enumeration space base */
++#define SB_ENUM_LIM 0x18010000 /* Enumeration space limit */
++
++#define SB_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */
++#define SB_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */
++
++#define SB_EXTIF_BASE 0x1f000000 /* External Interface region base address */
++#define SB_FLASH1 0x1fc00000 /* Flash Region 1 */
++#define SB_FLASH1_SZ 0x00400000 /* Size of Flash Region 1 */
++
++#define SB_PCI_DMA 0x40000000 /* Client Mode sb2pcitranslation2 (1 GB) */
++#define SB_PCI_DMA_SZ 0x40000000 /* Client Mode sb2pcitranslation2 size in bytes */
++#define SB_PCIE_DMA_L32 0x00000000 /* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), low 32 bits */
++#define SB_PCIE_DMA_H32 0x80000000 /* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */
++#define SB_EUART (SB_EXTIF_BASE + 0x00800000)
++#define SB_LED (SB_EXTIF_BASE + 0x00900000)
++
++
++/* enumeration space related defs */
++#define SB_CORE_SIZE 0x1000 /* each core gets 4Kbytes for registers */
++#define SB_MAXCORES ((SB_ENUM_LIM - SB_ENUM_BASE)/SB_CORE_SIZE)
++#define SBCONFIGOFF 0xf00 /* core sbconfig regs are top 256bytes of regs */
++#define SBCONFIGSIZE 256 /* sizeof (sbconfig_t) */
++
++/* mips address */
++#define SB_EJTAG 0xff200000 /* MIPS EJTAG space (2M) */
++
++/*
++ * Sonics Configuration Space Registers.
++ */
++#define SBIPSFLAG 0x08
++#define SBTPSFLAG 0x18
++#define SBTMERRLOGA 0x48 /* sonics >= 2.3 */
++#define SBTMERRLOG 0x50 /* sonics >= 2.3 */
++#define SBADMATCH3 0x60
++#define SBADMATCH2 0x68
++#define SBADMATCH1 0x70
++#define SBIMSTATE 0x90
++#define SBINTVEC 0x94
++#define SBTMSTATELOW 0x98
++#define SBTMSTATEHIGH 0x9c
++#define SBBWA0 0xa0
++#define SBIMCONFIGLOW 0xa8
++#define SBIMCONFIGHIGH 0xac
++#define SBADMATCH0 0xb0
++#define SBTMCONFIGLOW 0xb8
++#define SBTMCONFIGHIGH 0xbc
++#define SBBCONFIG 0xc0
++#define SBBSTATE 0xc8
++#define SBACTCNFG 0xd8
++#define SBFLAGST 0xe8
++#define SBIDLOW 0xf8
++#define SBIDHIGH 0xfc
++
++#ifndef _LANGUAGE_ASSEMBLY
++
++typedef volatile struct _sbconfig {
++ uint32 PAD[2];
++ uint32 sbipsflag; /* initiator port ocp slave flag */
++ uint32 PAD[3];
++ uint32 sbtpsflag; /* target port ocp slave flag */
++ uint32 PAD[11];
++ uint32 sbtmerrloga; /* (sonics >= 2.3) */
++ uint32 PAD;
++ uint32 sbtmerrlog; /* (sonics >= 2.3) */
++ uint32 PAD[3];
++ uint32 sbadmatch3; /* address match3 */
++ uint32 PAD;
++ uint32 sbadmatch2; /* address match2 */
++ uint32 PAD;
++ uint32 sbadmatch1; /* address match1 */
++ uint32 PAD[7];
++ uint32 sbimstate; /* initiator agent state */
++ uint32 sbintvec; /* interrupt mask */
++ uint32 sbtmstatelow; /* target state */
++ uint32 sbtmstatehigh; /* target state */
++ uint32 sbbwa0; /* bandwidth allocation table0 */
++ uint32 PAD;
++ uint32 sbimconfiglow; /* initiator configuration */
++ uint32 sbimconfighigh; /* initiator configuration */
++ uint32 sbadmatch0; /* address match0 */
++ uint32 PAD;
++ uint32 sbtmconfiglow; /* target configuration */
++ uint32 sbtmconfighigh; /* target configuration */
++ uint32 sbbconfig; /* broadcast configuration */
++ uint32 PAD;
++ uint32 sbbstate; /* broadcast state */
++ uint32 PAD[3];
++ uint32 sbactcnfg; /* activate configuration */
++ uint32 PAD[3];
++ uint32 sbflagst; /* current sbflags */
++ uint32 PAD[3];
++ uint32 sbidlow; /* identification */
++ uint32 sbidhigh; /* identification */
++} sbconfig_t;
++
++#endif /* _LANGUAGE_ASSEMBLY */
++
++/* sbipsflag */
++#define SBIPS_INT1_MASK 0x3f /* which sbflags get routed to mips interrupt 1 */
++#define SBIPS_INT1_SHIFT 0
++#define SBIPS_INT2_MASK 0x3f00 /* which sbflags get routed to mips interrupt 2 */
++#define SBIPS_INT2_SHIFT 8
++#define SBIPS_INT3_MASK 0x3f0000 /* which sbflags get routed to mips interrupt 3 */
++#define SBIPS_INT3_SHIFT 16
++#define SBIPS_INT4_MASK 0x3f000000 /* which sbflags get routed to mips interrupt 4 */
++#define SBIPS_INT4_SHIFT 24
++
++/* sbtpsflag */
++#define SBTPS_NUM0_MASK 0x3f /* interrupt sbFlag # generated by this core */
++#define SBTPS_F0EN0 0x40 /* interrupt is always sent on the backplane */
++
++/* sbtmerrlog */
++#define SBTMEL_CM 0x00000007 /* command */
++#define SBTMEL_CI 0x0000ff00 /* connection id */
++#define SBTMEL_EC 0x0f000000 /* error code */
++#define SBTMEL_ME 0x80000000 /* multiple error */
++
++/* sbimstate */
++#define SBIM_PC 0xf /* pipecount */
++#define SBIM_AP_MASK 0x30 /* arbitration policy */
++#define SBIM_AP_BOTH 0x00 /* use both timeslaces and token */
++#define SBIM_AP_TS 0x10 /* use timesliaces only */
++#define SBIM_AP_TK 0x20 /* use token only */
++#define SBIM_AP_RSV 0x30 /* reserved */
++#define SBIM_IBE 0x20000 /* inbanderror */
++#define SBIM_TO 0x40000 /* timeout */
++#define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */
++#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */
++
++/* sbtmstatelow */
++#define SBTML_RESET 0x1 /* reset */
++#define SBTML_REJ_MASK 0x6 /* reject */
++#define SBTML_REJ_SHIFT 1
++#define SBTML_CLK 0x10000 /* clock enable */
++#define SBTML_FGC 0x20000 /* force gated clocks on */
++#define SBTML_FL_MASK 0x3ffc0000 /* core-specific flags */
++#define SBTML_PE 0x40000000 /* pme enable */
++#define SBTML_BE 0x80000000 /* bist enable */
++
++/* sbtmstatehigh */
++#define SBTMH_SERR 0x1 /* serror */
++#define SBTMH_INT 0x2 /* interrupt */
++#define SBTMH_BUSY 0x4 /* busy */
++#define SBTMH_TO 0x00000020 /* timeout (sonics >= 2.3) */
++#define SBTMH_FL_MASK 0x1fff0000 /* core-specific flags */
++#define SBTMH_DMA64 0x10000000 /* supports DMA with 64-bit addresses */
++#define SBTMH_GCR 0x20000000 /* gated clock request */
++#define SBTMH_BISTF 0x40000000 /* bist failed */
++#define SBTMH_BISTD 0x80000000 /* bist done */
++
++
++/* sbbwa0 */
++#define SBBWA_TAB0_MASK 0xffff /* lookup table 0 */
++#define SBBWA_TAB1_MASK 0xffff /* lookup table 1 */
++#define SBBWA_TAB1_SHIFT 16
++
++/* sbimconfiglow */
++#define SBIMCL_STO_MASK 0x7 /* service timeout */
++#define SBIMCL_RTO_MASK 0x70 /* request timeout */
++#define SBIMCL_RTO_SHIFT 4
++#define SBIMCL_CID_MASK 0xff0000 /* connection id */
++#define SBIMCL_CID_SHIFT 16
++
++/* sbimconfighigh */
++#define SBIMCH_IEM_MASK 0xc /* inband error mode */
++#define SBIMCH_TEM_MASK 0x30 /* timeout error mode */
++#define SBIMCH_TEM_SHIFT 4
++#define SBIMCH_BEM_MASK 0xc0 /* bus error mode */
++#define SBIMCH_BEM_SHIFT 6
++
++/* sbadmatch0 */
++#define SBAM_TYPE_MASK 0x3 /* address type */
++#define SBAM_AD64 0x4 /* reserved */
++#define SBAM_ADINT0_MASK 0xf8 /* type0 size */
++#define SBAM_ADINT0_SHIFT 3
++#define SBAM_ADINT1_MASK 0x1f8 /* type1 size */
++#define SBAM_ADINT1_SHIFT 3
++#define SBAM_ADINT2_MASK 0x1f8 /* type2 size */
++#define SBAM_ADINT2_SHIFT 3
++#define SBAM_ADEN 0x400 /* enable */
++#define SBAM_ADNEG 0x800 /* negative decode */
++#define SBAM_BASE0_MASK 0xffffff00 /* type0 base address */
++#define SBAM_BASE0_SHIFT 8
++#define SBAM_BASE1_MASK 0xfffff000 /* type1 base address for the core */
++#define SBAM_BASE1_SHIFT 12
++#define SBAM_BASE2_MASK 0xffff0000 /* type2 base address for the core */
++#define SBAM_BASE2_SHIFT 16
++
++/* sbtmconfiglow */
++#define SBTMCL_CD_MASK 0xff /* clock divide */
++#define SBTMCL_CO_MASK 0xf800 /* clock offset */
++#define SBTMCL_CO_SHIFT 11
++#define SBTMCL_IF_MASK 0xfc0000 /* interrupt flags */
++#define SBTMCL_IF_SHIFT 18
++#define SBTMCL_IM_MASK 0x3000000 /* interrupt mode */
++#define SBTMCL_IM_SHIFT 24
++
++/* sbtmconfighigh */
++#define SBTMCH_BM_MASK 0x3 /* busy mode */
++#define SBTMCH_RM_MASK 0x3 /* retry mode */
++#define SBTMCH_RM_SHIFT 2
++#define SBTMCH_SM_MASK 0x30 /* stop mode */
++#define SBTMCH_SM_SHIFT 4
++#define SBTMCH_EM_MASK 0x300 /* sb error mode */
++#define SBTMCH_EM_SHIFT 8
++#define SBTMCH_IM_MASK 0xc00 /* int mode */
++#define SBTMCH_IM_SHIFT 10
++
++/* sbbconfig */
++#define SBBC_LAT_MASK 0x3 /* sb latency */
++#define SBBC_MAX0_MASK 0xf0000 /* maxccntr0 */
++#define SBBC_MAX0_SHIFT 16
++#define SBBC_MAX1_MASK 0xf00000 /* maxccntr1 */
++#define SBBC_MAX1_SHIFT 20
++
++/* sbbstate */
++#define SBBS_SRD 0x1 /* st reg disable */
++#define SBBS_HRD 0x2 /* hold reg disable */
++
++/* sbidlow */
++#define SBIDL_CS_MASK 0x3 /* config space */
++#define SBIDL_AR_MASK 0x38 /* # address ranges supported */
++#define SBIDL_AR_SHIFT 3
++#define SBIDL_SYNCH 0x40 /* sync */
++#define SBIDL_INIT 0x80 /* initiator */
++#define SBIDL_MINLAT_MASK 0xf00 /* minimum backplane latency */
++#define SBIDL_MINLAT_SHIFT 8
++#define SBIDL_MAXLAT 0xf000 /* maximum backplane latency */
++#define SBIDL_MAXLAT_SHIFT 12
++#define SBIDL_FIRST 0x10000 /* this initiator is first */
++#define SBIDL_CW_MASK 0xc0000 /* cycle counter width */
++#define SBIDL_CW_SHIFT 18
++#define SBIDL_TP_MASK 0xf00000 /* target ports */
++#define SBIDL_TP_SHIFT 20
++#define SBIDL_IP_MASK 0xf000000 /* initiator ports */
++#define SBIDL_IP_SHIFT 24
++#define SBIDL_RV_MASK 0xf0000000 /* sonics backplane revision code */
++#define SBIDL_RV_SHIFT 28
++#define SBIDL_RV_2_2 0x00000000 /* version 2.2 or earlier */
++#define SBIDL_RV_2_3 0x10000000 /* version 2.3 */
++
++/* sbidhigh */
++#define SBIDH_RC_MASK 0x000f /* revision code */
++#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */
++#define SBIDH_RCE_SHIFT 8
++#define SBCOREREV(sbidh) \
++ ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK))
++#define SBIDH_CC_MASK 0x8ff0 /* core code */
++#define SBIDH_CC_SHIFT 4
++#define SBIDH_VC_MASK 0xffff0000 /* vendor code */
++#define SBIDH_VC_SHIFT 16
++
++#define SB_COMMIT 0xfd8 /* update buffered registers value */
++
++/* vendor codes */
++#define SB_VEND_BCM 0x4243 /* Broadcom's SB vendor code */
++
++/* core codes */
++#define SB_CC 0x800 /* chipcommon core */
++#define SB_ILINE20 0x801 /* iline20 core */
++#define SB_SDRAM 0x803 /* sdram core */
++#define SB_PCI 0x804 /* pci core */
++#define SB_MIPS 0x805 /* mips core */
++#define SB_ENET 0x806 /* enet mac core */
++#define SB_CODEC 0x807 /* v90 codec core */
++#define SB_USB 0x808 /* usb 1.1 host/device core */
++#define SB_ADSL 0x809 /* ADSL core */
++#define SB_ILINE100 0x80a /* iline100 core */
++#define SB_IPSEC 0x80b /* ipsec core */
++#define SB_PCMCIA 0x80d /* pcmcia core */
++#define SB_SOCRAM 0x80e /* internal memory core */
++#define SB_MEMC 0x80f /* memc sdram core */
++#define SB_EXTIF 0x811 /* external interface core */
++#define SB_D11 0x812 /* 802.11 MAC core */
++#define SB_MIPS33 0x816 /* mips3302 core */
++#define SB_USB11H 0x817 /* usb 1.1 host core */
++#define SB_USB11D 0x818 /* usb 1.1 device core */
++#define SB_USB20H 0x819 /* usb 2.0 host core */
++#define SB_USB20D 0x81a /* usb 2.0 device core */
++#define SB_SDIOH 0x81b /* sdio host core */
++#define SB_ROBO 0x81c /* roboswitch core */
++#define SB_ATA100 0x81d /* parallel ATA core */
++#define SB_SATAXOR 0x81e /* serial ATA & XOR DMA core */
++#define SB_GIGETH 0x81f /* gigabit ethernet core */
++#define SB_PCIE 0x820 /* pci express core */
++#define SB_SRAMC 0x822 /* SRAM controller core */
++#define SB_MINIMAC 0x823 /* MINI MAC/phy core */
++
++#define SB_CC_IDX 0 /* chipc, when present, is always core 0 */
++
++/* Not really related to Silicon Backplane, but a couple of software
++ * conventions for the use the flash space:
++ */
++
++/* Minumum amount of flash we support */
++#define FLASH_MIN 0x00020000 /* Minimum flash size */
++
++/* A boot/binary may have an embedded block that describes its size */
++#define BISZ_OFFSET 0x3e0 /* At this offset into the binary */
++#define BISZ_MAGIC 0x4249535a /* Marked with this value: 'BISZ' */
++#define BISZ_MAGIC_IDX 0 /* Word 0: magic */
++#define BISZ_TXTST_IDX 1 /* 1: text start */
++#define BISZ_TXTEND_IDX 2 /* 2: text start */
++#define BISZ_DATAST_IDX 3 /* 3: text start */
++#define BISZ_DATAEND_IDX 4 /* 4: text start */
++#define BISZ_BSSST_IDX 5 /* 5: text start */
++#define BISZ_BSSEND_IDX 6 /* 6: text start */
++#define BISZ_SIZE 7 /* descriptor size in 32-bit intergers */
++
++#endif /* _SBCONFIG_H */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/sbextif.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/sbextif.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/sbextif.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/sbextif.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,242 @@
++/*
++ * Hardware-specific External Interface I/O core definitions
++ * for the BCM47xx family of SiliconBackplane-based chips.
++ *
++ * The External Interface core supports a total of three external chip selects
++ * supporting external interfaces. One of the external chip selects is
++ * used for Flash, one is used for PCMCIA, and the other may be
++ * programmed to support either a synchronous interface or an
++ * asynchronous interface. The asynchronous interface can be used to
++ * support external devices such as UARTs and the BCM2019 Bluetooth
++ * baseband processor.
++ * The external interface core also contains 2 on-chip 16550 UARTs, clock
++ * frequency control, a watchdog interrupt timer, and a GPIO interface.
++ *
++ * Copyright 2005, 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.
++ * $Id$
++ */
++
++#ifndef _SBEXTIF_H
++#define _SBEXTIF_H
++
++/* external interface address space */
++#define EXTIF_PCMCIA_MEMBASE(x) (x)
++#define EXTIF_PCMCIA_IOBASE(x) ((x) + 0x100000)
++#define EXTIF_PCMCIA_CFGBASE(x) ((x) + 0x200000)
++#define EXTIF_CFGIF_BASE(x) ((x) + 0x800000)
++#define EXTIF_FLASH_BASE(x) ((x) + 0xc00000)
++
++/* cpp contortions to concatenate w/arg prescan */
++#ifndef PAD
++#define _PADLINE(line) pad ## line
++#define _XSTR(line) _PADLINE(line)
++#define PAD _XSTR(__LINE__)
++#endif /* PAD */
++
++/*
++ * The multiple instances of output and output enable registers
++ * are present to allow driver software for multiple cores to control
++ * gpio outputs without needing to share a single register pair.
++ */
++struct gpiouser {
++ uint32 out;
++ uint32 outen;
++};
++#define NGPIOUSER 5
++
++typedef volatile struct {
++ uint32 corecontrol;
++ uint32 extstatus;
++ uint32 PAD[2];
++
++ /* pcmcia control registers */
++ uint32 pcmcia_config;
++ uint32 pcmcia_memwait;
++ uint32 pcmcia_attrwait;
++ uint32 pcmcia_iowait;
++
++ /* programmable interface control registers */
++ uint32 prog_config;
++ uint32 prog_waitcount;
++
++ /* flash control registers */
++ uint32 flash_config;
++ uint32 flash_waitcount;
++ uint32 PAD[4];
++
++ uint32 watchdog;
++
++ /* clock control */
++ uint32 clockcontrol_n;
++ uint32 clockcontrol_sb;
++ uint32 clockcontrol_pci;
++ uint32 clockcontrol_mii;
++ uint32 PAD[3];
++
++ /* gpio */
++ uint32 gpioin;
++ struct gpiouser gpio[NGPIOUSER];
++ uint32 PAD;
++ uint32 ejtagouten;
++ uint32 gpiointpolarity;
++ uint32 gpiointmask;
++ uint32 PAD[153];
++
++ uint8 uartdata;
++ uint8 PAD[3];
++ uint8 uartimer;
++ uint8 PAD[3];
++ uint8 uartfcr;
++ uint8 PAD[3];
++ uint8 uartlcr;
++ uint8 PAD[3];
++ uint8 uartmcr;
++ uint8 PAD[3];
++ uint8 uartlsr;
++ uint8 PAD[3];
++ uint8 uartmsr;
++ uint8 PAD[3];
++ uint8 uartscratch;
++ uint8 PAD[3];
++} extifregs_t;
++
++/* corecontrol */
++#define CC_UE (1 << 0) /* uart enable */
++
++/* extstatus */
++#define ES_EM (1 << 0) /* endian mode (ro) */
++#define ES_EI (1 << 1) /* external interrupt pin (ro) */
++#define ES_GI (1 << 2) /* gpio interrupt pin (ro) */
++
++/* gpio bit mask */
++#define GPIO_BIT0 (1 << 0)
++#define GPIO_BIT1 (1 << 1)
++#define GPIO_BIT2 (1 << 2)
++#define GPIO_BIT3 (1 << 3)
++#define GPIO_BIT4 (1 << 4)
++#define GPIO_BIT5 (1 << 5)
++#define GPIO_BIT6 (1 << 6)
++#define GPIO_BIT7 (1 << 7)
++
++
++/* pcmcia/prog/flash_config */
++#define CF_EN (1 << 0) /* enable */
++#define CF_EM_MASK 0xe /* mode */
++#define CF_EM_SHIFT 1
++#define CF_EM_FLASH 0x0 /* flash/asynchronous mode */
++#define CF_EM_SYNC 0x2 /* synchronous mode */
++#define CF_EM_PCMCIA 0x4 /* pcmcia mode */
++#define CF_DS (1 << 4) /* destsize: 0=8bit, 1=16bit */
++#define CF_BS (1 << 5) /* byteswap */
++#define CF_CD_MASK 0xc0 /* clock divider */
++#define CF_CD_SHIFT 6
++#define CF_CD_DIV2 0x0 /* backplane/2 */
++#define CF_CD_DIV3 0x40 /* backplane/3 */
++#define CF_CD_DIV4 0x80 /* backplane/4 */
++#define CF_CE (1 << 8) /* clock enable */
++#define CF_SB (1 << 9) /* size/bytestrobe (synch only) */
++
++/* pcmcia_memwait */
++#define PM_W0_MASK 0x3f /* waitcount0 */
++#define PM_W1_MASK 0x1f00 /* waitcount1 */
++#define PM_W1_SHIFT 8
++#define PM_W2_MASK 0x1f0000 /* waitcount2 */
++#define PM_W2_SHIFT 16
++#define PM_W3_MASK 0x1f000000 /* waitcount3 */
++#define PM_W3_SHIFT 24
++
++/* pcmcia_attrwait */
++#define PA_W0_MASK 0x3f /* waitcount0 */
++#define PA_W1_MASK 0x1f00 /* waitcount1 */
++#define PA_W1_SHIFT 8
++#define PA_W2_MASK 0x1f0000 /* waitcount2 */
++#define PA_W2_SHIFT 16
++#define PA_W3_MASK 0x1f000000 /* waitcount3 */
++#define PA_W3_SHIFT 24
++
++/* pcmcia_iowait */
++#define PI_W0_MASK 0x3f /* waitcount0 */
++#define PI_W1_MASK 0x1f00 /* waitcount1 */
++#define PI_W1_SHIFT 8
++#define PI_W2_MASK 0x1f0000 /* waitcount2 */
++#define PI_W2_SHIFT 16
++#define PI_W3_MASK 0x1f000000 /* waitcount3 */
++#define PI_W3_SHIFT 24
++
++/* prog_waitcount */
++#define PW_W0_MASK 0x0000001f /* waitcount0 */
++#define PW_W1_MASK 0x00001f00 /* waitcount1 */
++#define PW_W1_SHIFT 8
++#define PW_W2_MASK 0x001f0000 /* waitcount2 */
++#define PW_W2_SHIFT 16
++#define PW_W3_MASK 0x1f000000 /* waitcount3 */
++#define PW_W3_SHIFT 24
++
++#define PW_W0 0x0000000c
++#define PW_W1 0x00000a00
++#define PW_W2 0x00020000
++#define PW_W3 0x01000000
++
++/* flash_waitcount */
++#define FW_W0_MASK 0x1f /* waitcount0 */
++#define FW_W1_MASK 0x1f00 /* waitcount1 */
++#define FW_W1_SHIFT 8
++#define FW_W2_MASK 0x1f0000 /* waitcount2 */
++#define FW_W2_SHIFT 16
++#define FW_W3_MASK 0x1f000000 /* waitcount3 */
++#define FW_W3_SHIFT 24
++
++/* watchdog */
++#define WATCHDOG_CLOCK 48000000 /* Hz */
++
++/* clockcontrol_n */
++#define CN_N1_MASK 0x3f /* n1 control */
++#define CN_N2_MASK 0x3f00 /* n2 control */
++#define CN_N2_SHIFT 8
++
++/* clockcontrol_sb/pci/mii */
++#define CC_M1_MASK 0x3f /* m1 control */
++#define CC_M2_MASK 0x3f00 /* m2 control */
++#define CC_M2_SHIFT 8
++#define CC_M3_MASK 0x3f0000 /* m3 control */
++#define CC_M3_SHIFT 16
++#define CC_MC_MASK 0x1f000000 /* mux control */
++#define CC_MC_SHIFT 24
++
++/* Clock control default values */
++#define CC_DEF_N 0x0009 /* Default values for bcm4710 */
++#define CC_DEF_100 0x04020011
++#define CC_DEF_33 0x11030011
++#define CC_DEF_25 0x11050011
++
++/* Clock control values for 125Mhz */
++#define CC_125_N 0x0802
++#define CC_125_M 0x04020009
++#define CC_125_M25 0x11090009
++#define CC_125_M33 0x11090005
++
++/* Clock control magic field values */
++#define CC_F6_2 0x02 /* A factor of 2 in */
++#define CC_F6_3 0x03 /* 6-bit fields like */
++#define CC_F6_4 0x05 /* N1, M1 or M3 */
++#define CC_F6_5 0x09
++#define CC_F6_6 0x11
++#define CC_F6_7 0x21
++
++#define CC_F5_BIAS 5 /* 5-bit fields get this added */
++
++#define CC_MC_BYPASS 0x08
++#define CC_MC_M1 0x04
++#define CC_MC_M1M2 0x02
++#define CC_MC_M1M2M3 0x01
++#define CC_MC_M1M3 0x11
++
++#define CC_CLOCK_BASE 24000000 /* Half the clock freq. in the 4710 */
++
++#endif /* _SBEXTIF_H */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/sbmemc.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/sbmemc.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/sbmemc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/sbmemc.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,148 @@
++/*
++ * BCM47XX Sonics SiliconBackplane DDR/SDRAM controller core hardware definitions.
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#ifndef _SBMEMC_H
++#define _SBMEMC_H
++
++#ifdef _LANGUAGE_ASSEMBLY
++
++#define MEMC_CONTROL 0x00
++#define MEMC_CONFIG 0x04
++#define MEMC_REFRESH 0x08
++#define MEMC_BISTSTAT 0x0c
++#define MEMC_MODEBUF 0x10
++#define MEMC_BKCLS 0x14
++#define MEMC_PRIORINV 0x18
++#define MEMC_DRAMTIM 0x1c
++#define MEMC_INTSTAT 0x20
++#define MEMC_INTMASK 0x24
++#define MEMC_INTINFO 0x28
++#define MEMC_NCDLCTL 0x30
++#define MEMC_RDNCDLCOR 0x34
++#define MEMC_WRNCDLCOR 0x38
++#define MEMC_MISCDLYCTL 0x3c
++#define MEMC_DQSGATENCDL 0x40
++#define MEMC_SPARE 0x44
++#define MEMC_TPADDR 0x48
++#define MEMC_TPDATA 0x4c
++#define MEMC_BARRIER 0x50
++#define MEMC_CORE 0x54
++
++
++#else
++
++/* Sonics side: MEMC core registers */
++typedef volatile struct sbmemcregs {
++ uint32 control;
++ uint32 config;
++ uint32 refresh;
++ uint32 biststat;
++ uint32 modebuf;
++ uint32 bkcls;
++ uint32 priorinv;
++ uint32 dramtim;
++ uint32 intstat;
++ uint32 intmask;
++ uint32 intinfo;
++ uint32 reserved1;
++ uint32 ncdlctl;
++ uint32 rdncdlcor;
++ uint32 wrncdlcor;
++ uint32 miscdlyctl;
++ uint32 dqsgatencdl;
++ uint32 spare;
++ uint32 tpaddr;
++ uint32 tpdata;
++ uint32 barrier;
++ uint32 core;
++} sbmemcregs_t;
++
++#endif
++
++/* MEMC Core Init values (OCP ID 0x80f) */
++
++/* For sdr: */
++#define MEMC_SD_CONFIG_INIT 0x00048000
++#define MEMC_SD_DRAMTIM2_INIT 0x000754d8
++#define MEMC_SD_DRAMTIM3_INIT 0x000754da
++#define MEMC_SD_RDNCDLCOR_INIT 0x00000000
++#define MEMC_SD_WRNCDLCOR_INIT 0x49351200
++#define MEMC_SD1_WRNCDLCOR_INIT 0x14500200 /* For corerev 1 (4712) */
++#define MEMC_SD_MISCDLYCTL_INIT 0x00061c1b
++#define MEMC_SD1_MISCDLYCTL_INIT 0x00021416 /* For corerev 1 (4712) */
++#define MEMC_SD_CONTROL_INIT0 0x00000002
++#define MEMC_SD_CONTROL_INIT1 0x00000008
++#define MEMC_SD_CONTROL_INIT2 0x00000004
++#define MEMC_SD_CONTROL_INIT3 0x00000010
++#define MEMC_SD_CONTROL_INIT4 0x00000001
++#define MEMC_SD_MODEBUF_INIT 0x00000000
++#define MEMC_SD_REFRESH_INIT 0x0000840f
++
++
++/* This is for SDRM8X8X4 */
++#define MEMC_SDR_INIT 0x0008
++#define MEMC_SDR_MODE 0x32
++#define MEMC_SDR_NCDL 0x00020032
++#define MEMC_SDR1_NCDL 0x0002020f /* For corerev 1 (4712) */
++
++/* For ddr: */
++#define MEMC_CONFIG_INIT 0x00048000
++#define MEMC_DRAMTIM2_INIT 0x000754d8
++#define MEMC_DRAMTIM25_INIT 0x000754d9
++#define MEMC_RDNCDLCOR_INIT 0x00000000
++#define MEMC_RDNCDLCOR_SIMINIT 0xf6f6f6f6 /* For hdl sim */
++#define MEMC_WRNCDLCOR_INIT 0x49351200
++#define MEMC_1_WRNCDLCOR_INIT 0x14500200
++#define MEMC_DQSGATENCDL_INIT 0x00030000
++#define MEMC_MISCDLYCTL_INIT 0x21061c1b
++#define MEMC_1_MISCDLYCTL_INIT 0x21021400
++#define MEMC_NCDLCTL_INIT 0x00002001
++#define MEMC_CONTROL_INIT0 0x00000002
++#define MEMC_CONTROL_INIT1 0x00000008
++#define MEMC_MODEBUF_INIT0 0x00004000
++#define MEMC_CONTROL_INIT2 0x00000010
++#define MEMC_MODEBUF_INIT1 0x00000100
++#define MEMC_CONTROL_INIT3 0x00000010
++#define MEMC_CONTROL_INIT4 0x00000008
++#define MEMC_REFRESH_INIT 0x0000840f
++#define MEMC_CONTROL_INIT5 0x00000004
++#define MEMC_MODEBUF_INIT2 0x00000000
++#define MEMC_CONTROL_INIT6 0x00000010
++#define MEMC_CONTROL_INIT7 0x00000001
++
++
++/* This is for DDRM16X16X2 */
++#define MEMC_DDR_INIT 0x0009
++#define MEMC_DDR_MODE 0x62
++#define MEMC_DDR_NCDL 0x0005050a
++#define MEMC_DDR1_NCDL 0x00000a0a /* For corerev 1 (4712) */
++
++/* mask for sdr/ddr calibration registers */
++#define MEMC_RDNCDLCOR_RD_MASK 0x000000ff
++#define MEMC_WRNCDLCOR_WR_MASK 0x000000ff
++#define MEMC_DQSGATENCDL_G_MASK 0x000000ff
++
++/* masks for miscdlyctl registers */
++#define MEMC_MISC_SM_MASK 0x30000000
++#define MEMC_MISC_SM_SHIFT 28
++#define MEMC_MISC_SD_MASK 0x0f000000
++#define MEMC_MISC_SD_SHIFT 24
++
++/* hw threshhold for calculating wr/rd for sdr memc */
++#define MEMC_CD_THRESHOLD 128
++
++/* Low bit of init register says if memc is ddr or sdr */
++#define MEMC_CONFIG_DDR 0x00000001
++
++#endif /* _SBMEMC_H */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/sbmips.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/sbmips.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/sbmips.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/sbmips.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,62 @@
++/*
++ * Broadcom SiliconBackplane MIPS definitions
++ *
++ * SB MIPS cores are custom MIPS32 processors with SiliconBackplane
++ * OCP interfaces. The CP0 processor ID is 0x00024000, where bits
++ * 23:16 mean Broadcom and bits 15:8 mean a MIPS core with an OCP
++ * interface. The core revision is stored in the SB ID register in SB
++ * configuration space.
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#ifndef _SBMIPS_H
++#define _SBMIPS_H
++
++#include <mipsinc.h>
++
++#ifndef _LANGUAGE_ASSEMBLY
++
++/* cpp contortions to concatenate w/arg prescan */
++#ifndef PAD
++#define _PADLINE(line) pad ## line
++#define _XSTR(line) _PADLINE(line)
++#define PAD _XSTR(__LINE__)
++#endif /* PAD */
++
++typedef volatile struct {
++ uint32 corecontrol;
++ uint32 PAD[2];
++ uint32 biststatus;
++ uint32 PAD[4];
++ uint32 intstatus;
++ uint32 intmask;
++ uint32 timer;
++} mipsregs_t;
++
++extern uint32 sb_flag(sb_t *sbh);
++extern uint sb_irq(sb_t *sbh);
++
++extern void BCMINIT(sb_serial_init)(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base, uint reg_shift));
++
++extern void *sb_jtagm_init(sb_t *sbh, uint clkd, bool exttap);
++extern void sb_jtagm_disable(void *h);
++extern uint32 jtag_rwreg(void *h, uint32 ir, uint32 dr);
++extern void BCMINIT(sb_mips_init)(sb_t *sbh);
++extern uint32 BCMINIT(sb_mips_clock)(sb_t *sbh);
++extern bool BCMINIT(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 pciclock);
++extern void BCMINIT(enable_pfc)(uint32 mode);
++extern uint32 BCMINIT(sb_memc_get_ncdl)(sb_t *sbh);
++
++
++#endif /* _LANGUAGE_ASSEMBLY */
++
++#endif /* _SBMIPS_H */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/sbpci.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/sbpci.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/sbpci.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/sbpci.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,122 @@
++/*
++ * BCM47XX Sonics SiliconBackplane PCI core hardware definitions.
++ *
++ * $Id$
++ * Copyright 2005, 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 _SBPCI_H
++#define _SBPCI_H
++
++/* cpp contortions to concatenate w/arg prescan */
++#ifndef PAD
++#define _PADLINE(line) pad ## line
++#define _XSTR(line) _PADLINE(line)
++#define PAD _XSTR(__LINE__)
++#endif
++
++/* Sonics side: PCI core and host control registers */
++typedef struct sbpciregs {
++ uint32 control; /* PCI control */
++ uint32 PAD[3];
++ uint32 arbcontrol; /* PCI arbiter control */
++ uint32 PAD[3];
++ uint32 intstatus; /* Interrupt status */
++ uint32 intmask; /* Interrupt mask */
++ uint32 sbtopcimailbox; /* Sonics to PCI mailbox */
++ uint32 PAD[9];
++ uint32 bcastaddr; /* Sonics broadcast address */
++ uint32 bcastdata; /* Sonics broadcast data */
++ uint32 PAD[2];
++ uint32 gpioin; /* ro: gpio input (>=rev2) */
++ uint32 gpioout; /* rw: gpio output (>=rev2) */
++ uint32 gpioouten; /* rw: gpio output enable (>= rev2) */
++ uint32 gpiocontrol; /* rw: gpio control (>= rev2) */
++ uint32 PAD[36];
++ uint32 sbtopci0; /* Sonics to PCI translation 0 */
++ uint32 sbtopci1; /* Sonics to PCI translation 1 */
++ uint32 sbtopci2; /* Sonics to PCI translation 2 */
++ uint32 PAD[445];
++ uint16 sprom[36]; /* SPROM shadow Area */
++ uint32 PAD[46];
++} sbpciregs_t;
++
++/* PCI control */
++#define PCI_RST_OE 0x01 /* When set, drives PCI_RESET out to pin */
++#define PCI_RST 0x02 /* Value driven out to pin */
++#define PCI_CLK_OE 0x04 /* When set, drives clock as gated by PCI_CLK out to pin */
++#define PCI_CLK 0x08 /* Gate for clock driven out to pin */
++
++/* PCI arbiter control */
++#define PCI_INT_ARB 0x01 /* When set, use an internal arbiter */
++#define PCI_EXT_ARB 0x02 /* When set, use an external arbiter */
++#define PCI_PARKID_MASK 0x06 /* Selects which agent is parked on an idle bus */
++#define PCI_PARKID_SHIFT 1
++#define PCI_PARKID_LAST 0 /* Last requestor */
++#define PCI_PARKID_4710 1 /* 4710 */
++#define PCI_PARKID_EXTREQ0 2 /* External requestor 0 */
++#define PCI_PARKID_EXTREQ1 3 /* External requestor 1 */
++
++/* Interrupt status/mask */
++#define PCI_INTA 0x01 /* PCI INTA# is asserted */
++#define PCI_INTB 0x02 /* PCI INTB# is asserted */
++#define PCI_SERR 0x04 /* PCI SERR# has been asserted (write one to clear) */
++#define PCI_PERR 0x08 /* PCI PERR# has been asserted (write one to clear) */
++#define PCI_PME 0x10 /* PCI PME# is asserted */
++
++/* (General) PCI/SB mailbox interrupts, two bits per pci function */
++#define MAILBOX_F0_0 0x100 /* function 0, int 0 */
++#define MAILBOX_F0_1 0x200 /* function 0, int 1 */
++#define MAILBOX_F1_0 0x400 /* function 1, int 0 */
++#define MAILBOX_F1_1 0x800 /* function 1, int 1 */
++#define MAILBOX_F2_0 0x1000 /* function 2, int 0 */
++#define MAILBOX_F2_1 0x2000 /* function 2, int 1 */
++#define MAILBOX_F3_0 0x4000 /* function 3, int 0 */
++#define MAILBOX_F3_1 0x8000 /* function 3, int 1 */
++
++/* Sonics broadcast address */
++#define BCAST_ADDR_MASK 0xff /* Broadcast register address */
++
++/* Sonics to PCI translation types */
++#define SBTOPCI0_MASK 0xfc000000
++#define SBTOPCI1_MASK 0xfc000000
++#define SBTOPCI2_MASK 0xc0000000
++#define SBTOPCI_MEM 0
++#define SBTOPCI_IO 1
++#define SBTOPCI_CFG0 2
++#define SBTOPCI_CFG1 3
++#define SBTOPCI_PREF 0x4 /* prefetch enable */
++#define SBTOPCI_BURST 0x8 /* burst enable */
++#define SBTOPCI_RC_MASK 0x30 /* read command (>= rev11) */
++#define SBTOPCI_RC_READ 0x00 /* memory read */
++#define SBTOPCI_RC_READLINE 0x10 /* memory read line */
++#define SBTOPCI_RC_READMULTI 0x20 /* memory read multiple */
++
++/* PCI core index in SROM shadow area */
++#define SRSH_PI_OFFSET 0 /* first word */
++#define SRSH_PI_MASK 0xf000 /* bit 15:12 */
++#define SRSH_PI_SHIFT 12 /* bit 15:12 */
++
++/* PCI side: Reserved PCI configuration registers (see pcicfg.h) */
++#define cap_list rsvd_a[0]
++#define bar0_window dev_dep[0x80 - 0x40]
++#define bar1_window dev_dep[0x84 - 0x40]
++#define sprom_control dev_dep[0x88 - 0x40]
++
++#ifndef _LANGUAGE_ASSEMBLY
++
++extern int sbpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len);
++extern int sbpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len);
++extern void sbpci_ban(uint16 core);
++extern int sbpci_init(sb_t *sbh);
++extern void sbpci_check(sb_t *sbh);
++
++#endif /* !_LANGUAGE_ASSEMBLY */
++
++#endif /* _SBPCI_H */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/sbsdram.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/sbsdram.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/sbsdram.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/sbsdram.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,75 @@
++/*
++ * BCM47XX Sonics SiliconBackplane SDRAM controller core hardware definitions.
++ *
++ * Copyright 2005, 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.
++ * $Id$
++ */
++
++#ifndef _SBSDRAM_H
++#define _SBSDRAM_H
++
++#ifndef _LANGUAGE_ASSEMBLY
++
++/* Sonics side: SDRAM core registers */
++typedef volatile struct sbsdramregs {
++ uint32 initcontrol; /* Generates external SDRAM initialization sequence */
++ uint32 config; /* Initializes external SDRAM mode register */
++ uint32 refresh; /* Controls external SDRAM refresh rate */
++ uint32 pad1;
++ uint32 pad2;
++} sbsdramregs_t;
++
++#endif
++
++/* SDRAM initialization control (initcontrol) register bits */
++#define SDRAM_CBR 0x0001 /* Writing 1 generates refresh cycle and toggles bit */
++#define SDRAM_PRE 0x0002 /* Writing 1 generates precharge cycle and toggles bit */
++#define SDRAM_MRS 0x0004 /* Writing 1 generates mode register select cycle and toggles bit */
++#define SDRAM_EN 0x0008 /* When set, enables access to SDRAM */
++#define SDRAM_16Mb 0x0000 /* Use 16 Megabit SDRAM */
++#define SDRAM_64Mb 0x0010 /* Use 64 Megabit SDRAM */
++#define SDRAM_128Mb 0x0020 /* Use 128 Megabit SDRAM */
++#define SDRAM_RSVMb 0x0030 /* Use special SDRAM */
++#define SDRAM_RST 0x0080 /* Writing 1 causes soft reset of controller */
++#define SDRAM_SELFREF 0x0100 /* Writing 1 enables self refresh mode */
++#define SDRAM_PWRDOWN 0x0200 /* Writing 1 causes controller to power down */
++#define SDRAM_32BIT 0x0400 /* When set, indicates 32 bit SDRAM interface */
++#define SDRAM_9BITCOL 0x0800 /* When set, indicates 9 bit column */
++
++/* SDRAM configuration (config) register bits */
++#define SDRAM_BURSTFULL 0x0000 /* Use full page bursts */
++#define SDRAM_BURST8 0x0001 /* Use burst of 8 */
++#define SDRAM_BURST4 0x0002 /* Use burst of 4 */
++#define SDRAM_BURST2 0x0003 /* Use burst of 2 */
++#define SDRAM_CAS3 0x0000 /* Use CAS latency of 3 */
++#define SDRAM_CAS2 0x0004 /* Use CAS latency of 2 */
++
++/* 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 SDRAM_INIT MEM4MX16X2
++#define SDRAM_CONFIG SDRAM_BURSTFULL
++#define SDRAM_REFRESH SDRAM_REF(0x40)
++
++#define MEM1MX16 0x009 /* 2 MB */
++#define MEM1MX16X2 0x409 /* 4 MB */
++#define MEM2MX8X2 0x809 /* 4 MB */
++#define MEM2MX8X4 0xc09 /* 8 MB */
++#define MEM2MX32 0x439 /* 8 MB */
++#define MEM4MX16 0x019 /* 8 MB */
++#define MEM4MX16X2 0x419 /* 16 MB */
++#define MEM8MX8X2 0x819 /* 16 MB */
++#define MEM8MX16 0x829 /* 16 MB */
++#define MEM4MX32 0x429 /* 16 MB */
++#define MEM8MX8X4 0xc19 /* 32 MB */
++#define MEM8MX16X2 0xc29 /* 32 MB */
++
++#endif /* _SBSDRAM_H */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/sbutils.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/sbutils.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/sbutils.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/sbutils.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,136 @@
++/*
++ * Misc utility routines for accessing chip-specific features
++ * of Broadcom HNBU SiliconBackplane-based chips.
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#ifndef _sbutils_h_
++#define _sbutils_h_
++
++/*
++ * Datastructure to export all chip specific common variables
++ * public (read-only) portion of sbutils handle returned by
++ * sb_attach()/sb_kattach()
++*/
++
++struct sb_pub {
++
++ uint bustype; /* SB_BUS, PCI_BUS */
++ uint buscoretype; /* SB_PCI, SB_PCMCIA, SB_PCIE*/
++ uint buscorerev; /* buscore rev */
++ uint buscoreidx; /* buscore index */
++ int ccrev; /* chip common core rev */
++ uint boardtype; /* board type */
++ uint boardvendor; /* board vendor */
++ uint chip; /* chip number */
++ uint chiprev; /* chip revision */
++ uint chippkg; /* chip package option */
++ uint sonicsrev; /* sonics backplane rev */
++};
++
++typedef const struct sb_pub sb_t;
++
++/*
++ * Many of the routines below take an 'sbh' handle as their first arg.
++ * Allocate this by calling sb_attach(). Free it by calling sb_detach().
++ * At any one time, the sbh is logically focused on one particular sb core
++ * (the "current core").
++ * Use sb_setcore() or sb_setcoreidx() to change the association to another core.
++ */
++
++/* exported externs */
++extern sb_t * BCMINIT(sb_attach)(uint pcidev, osl_t *osh, void *regs, uint bustype, void *sdh, char **vars, int *varsz);
++extern sb_t * BCMINIT(sb_kattach)(void);
++extern void sb_detach(sb_t *sbh);
++extern uint BCMINIT(sb_chip)(sb_t *sbh);
++extern uint BCMINIT(sb_chiprev)(sb_t *sbh);
++extern uint BCMINIT(sb_chipcrev)(sb_t *sbh);
++extern uint BCMINIT(sb_chippkg)(sb_t *sbh);
++extern uint BCMINIT(sb_pcirev)(sb_t *sbh);
++extern bool BCMINIT(sb_war16165)(sb_t *sbh);
++extern uint BCMINIT(sb_boardvendor)(sb_t *sbh);
++extern uint BCMINIT(sb_boardtype)(sb_t *sbh);
++extern uint sb_bus(sb_t *sbh);
++extern uint sb_buscoretype(sb_t *sbh);
++extern uint sb_buscorerev(sb_t *sbh);
++extern uint sb_corelist(sb_t *sbh, uint coreid[]);
++extern uint sb_coreid(sb_t *sbh);
++extern uint sb_coreidx(sb_t *sbh);
++extern uint sb_coreunit(sb_t *sbh);
++extern uint sb_corevendor(sb_t *sbh);
++extern uint sb_corerev(sb_t *sbh);
++extern void *sb_osh(sb_t *sbh);
++extern void *sb_coreregs(sb_t *sbh);
++extern uint32 sb_coreflags(sb_t *sbh, uint32 mask, uint32 val);
++extern uint32 sb_coreflagshi(sb_t *sbh, uint32 mask, uint32 val);
++extern bool sb_iscoreup(sb_t *sbh);
++extern void *sb_setcoreidx(sb_t *sbh, uint coreidx);
++extern void *sb_setcore(sb_t *sbh, uint coreid, uint coreunit);
++extern int sb_corebist(sb_t *sbh, uint coreid, uint coreunit);
++extern void sb_commit(sb_t *sbh);
++extern uint32 sb_base(uint32 admatch);
++extern uint32 sb_size(uint32 admatch);
++extern void sb_core_reset(sb_t *sbh, uint32 bits);
++extern void sb_core_tofixup(sb_t *sbh);
++extern void sb_core_disable(sb_t *sbh, uint32 bits);
++extern uint32 sb_clock_rate(uint32 pll_type, uint32 n, uint32 m);
++extern uint32 sb_clock(sb_t *sbh);
++extern void sb_pci_setup(sb_t *sbh, uint coremask);
++extern void sb_watchdog(sb_t *sbh, uint ticks);
++extern void *sb_gpiosetcore(sb_t *sbh);
++extern uint32 sb_gpiocontrol(sb_t *sbh, uint32 mask, uint32 val, uint8 priority);
++extern uint32 sb_gpioouten(sb_t *sbh, uint32 mask, uint32 val, uint8 priority);
++extern uint32 sb_gpioout(sb_t *sbh, uint32 mask, uint32 val, uint8 priority);
++extern uint32 sb_gpioin(sb_t *sbh);
++extern uint32 sb_gpiointpolarity(sb_t *sbh, uint32 mask, uint32 val, uint8 priority);
++extern uint32 sb_gpiointmask(sb_t *sbh, uint32 mask, uint32 val, uint8 priority);
++extern uint32 sb_gpioled(sb_t *sbh, uint32 mask, uint32 val);
++extern uint32 sb_gpioreserve(sb_t *sbh, uint32 gpio_num, uint8 priority);
++extern uint32 sb_gpiorelease(sb_t *sbh, uint32 gpio_num, uint8 priority);
++
++extern void sb_clkctl_init(sb_t *sbh);
++extern uint16 sb_clkctl_fast_pwrup_delay(sb_t *sbh);
++extern bool sb_clkctl_clk(sb_t *sbh, uint mode);
++extern int sb_clkctl_xtal(sb_t *sbh, uint what, bool on);
++extern void sb_register_intr_callback(sb_t *sbh, void *intrsoff_fn,
++ void *intrsrestore_fn, void *intrsenabled_fn, void *intr_arg);
++extern uint32 sb_set_initiator_to(sb_t *sbh, uint32 to);
++extern void sb_corepciid(sb_t *sbh, uint16 *pcivendor, uint16 *pcidevice,
++ uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif);
++extern uint32 sb_gpiotimerval(sb_t *sbh, uint32 mask, uint32 val);
++
++
++
++/*
++* Build device path. Path size must be >= SB_DEVPATH_BUFSZ.
++* The returned path is NULL terminated and has trailing '/'.
++* Return 0 on success, nonzero otherwise.
++*/
++extern int sb_devpath(sb_t *sbh, char *path, int size);
++
++/* clkctl xtal what flags */
++#define XTAL 0x1 /* primary crystal oscillator (2050) */
++#define PLL 0x2 /* main chip pll */
++
++/* clkctl clk mode */
++#define CLK_FAST 0 /* force fast (pll) clock */
++#define CLK_DYNAMIC 2 /* enable dynamic clock control */
++
++
++/* GPIO usage priorities */
++#define GPIO_DRV_PRIORITY 0
++#define GPIO_APP_PRIORITY 1
++
++/* device path */
++#define SB_DEVPATH_BUFSZ 16 /* min buffer size in bytes */
++
++#endif /* _sbutils_h_ */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/sflash.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/sflash.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/sflash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/sflash.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,36 @@
++/*
++ * Broadcom SiliconBackplane chipcommon serial flash interface
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#ifndef _sflash_h_
++#define _sflash_h_
++
++#include <typedefs.h>
++#include <sbchipc.h>
++
++struct sflash {
++ uint blocksize; /* Block size */
++ uint numblocks; /* Number of blocks */
++ uint32 type; /* Type */
++ uint size; /* Total size in bytes */
++};
++
++/* Utility functions */
++extern int sflash_poll(chipcregs_t *cc, uint offset);
++extern int sflash_read(chipcregs_t *cc, uint offset, uint len, uchar *buf);
++extern int sflash_write(chipcregs_t *cc, uint offset, uint len, const uchar *buf);
++extern int sflash_erase(chipcregs_t *cc, uint offset);
++extern int sflash_commit(chipcregs_t *cc, uint offset, uint len, const uchar *buf);
++extern struct sflash * sflash_init(chipcregs_t *cc);
++
++#endif /* _sflash_h_ */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/trxhdr.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/trxhdr.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/trxhdr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/trxhdr.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,33 @@
++/*
++ * TRX image file header format.
++ *
++ * Copyright 2005, 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.
++ *
++ * $Id$
++ */
++
++#include <typedefs.h>
++
++#define TRX_MAGIC 0x30524448 /* "HDR0" */
++#define TRX_VERSION 1
++#define TRX_MAX_LEN 0x3A0000
++#define TRX_NO_HEADER 1 /* Do not write TRX header */
++#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */
++#define TRX_MAX_OFFSET 3
++
++struct trx_header {
++ uint32 magic; /* "HDR0" */
++ uint32 len; /* Length of file including header */
++ uint32 crc32; /* 32-bit CRC from flag_version to end of file */
++ uint32 flag_version; /* 0:15 flags, 16:31 version */
++ uint32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */
++};
++
++/* Compatibility */
++typedef struct trx_header TRXHDR, *PTRXHDR;
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/include/typedefs.h linux-2.6.17-owrt/arch/mips/bcm947xx/include/typedefs.h
+--- linux-2.6.17/arch/mips/bcm947xx/include/typedefs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/include/typedefs.h 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,326 @@
++/*
++ * Copyright 2005, 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.
++ * $Id$
++ */
++
++#ifndef _TYPEDEFS_H_
++#define _TYPEDEFS_H_
++
++
++/* Define 'SITE_TYPEDEFS' in the compile to include a site specific
++ * typedef file "site_typedefs.h".
++ *
++ * If 'SITE_TYPEDEFS' is not defined, then the "Inferred Typedefs"
++ * section of this file makes inferences about the compile environment
++ * based on defined symbols and possibly compiler pragmas.
++ *
++ * Following these two sections is the "Default Typedefs"
++ * section. This section is only prcessed if 'USE_TYPEDEF_DEFAULTS' is
++ * defined. This section has a default set of typedefs and a few
++ * proprocessor symbols (TRUE, FALSE, NULL, ...).
++ */
++
++#ifdef SITE_TYPEDEFS
++
++/*******************************************************************************
++ * Site Specific Typedefs
++ *******************************************************************************/
++
++#include "site_typedefs.h"
++
++#else
++
++/*******************************************************************************
++ * Inferred Typedefs
++ *******************************************************************************/
++
++/* Infer the compile environment based on preprocessor symbols and pramas.
++ * Override type definitions as needed, and include configuration dependent
++ * header files to define types.
++ */
++
++#ifdef __cplusplus
++
++#define TYPEDEF_BOOL
++#ifndef FALSE
++#define FALSE false
++#endif
++#ifndef TRUE
++#define TRUE true
++#endif
++
++#else /* ! __cplusplus */
++
++#if defined(_WIN32)
++
++#define TYPEDEF_BOOL
++typedef unsigned char bool; /* consistent w/BOOL */
++
++#endif /* _WIN32 */
++
++#endif /* ! __cplusplus */
++
++/* use the Windows ULONG_PTR type when compiling for 64 bit */
++#if defined(_WIN64)
++#include <basetsd.h>
++#define TYPEDEF_UINTPTR
++typedef ULONG_PTR uintptr;
++#endif
++
++#ifdef _HNDRTE_
++typedef long unsigned int size_t;
++#endif
++
++#ifdef _MSC_VER /* Microsoft C */
++#define TYPEDEF_INT64
++#define TYPEDEF_UINT64
++typedef signed __int64 int64;
++typedef unsigned __int64 uint64;
++#endif
++
++#if defined(MACOSX) && defined(KERNEL)
++#define TYPEDEF_BOOL
++#endif
++
++
++#if defined(linux)
++#define TYPEDEF_UINT
++#define TYPEDEF_USHORT
++#define TYPEDEF_ULONG
++#endif
++
++#if !defined(linux) && !defined(_WIN32) && !defined(PMON) && !defined(_CFE_) && !defined(_HNDRTE_) && !defined(_MINOSL_)
++#define TYPEDEF_UINT
++#define TYPEDEF_USHORT
++#endif
++
++
++/* Do not support the (u)int64 types with strict ansi for GNU C */
++#if defined(__GNUC__) && defined(__STRICT_ANSI__)
++#define TYPEDEF_INT64
++#define TYPEDEF_UINT64
++#endif
++
++/* ICL accepts unsigned 64 bit type only, and complains in ANSI mode
++ * for singned or unsigned */
++#if defined(__ICL)
++
++#define TYPEDEF_INT64
++
++#if defined(__STDC__)
++#define TYPEDEF_UINT64
++#endif
++
++#endif /* __ICL */
++
++
++#if !defined(_WIN32) && !defined(PMON) && !defined(_CFE_) && !defined(_HNDRTE_) && !defined(_MINOSL_)
++
++/* pick up ushort & uint from standard types.h */
++#if defined(linux) && defined(__KERNEL__)
++
++#include <linux/types.h> /* sys/types.h and linux/types.h are oil and water */
++
++#else
++
++#include <sys/types.h>
++
++#endif
++
++#endif /* !_WIN32 && !PMON && !_CFE_ && !_HNDRTE_ && !_MINOSL_ */
++
++#if defined(MACOSX) && defined(KERNEL)
++#include <IOKit/IOTypes.h>
++#endif
++
++
++/* use the default typedefs in the next section of this file */
++#define USE_TYPEDEF_DEFAULTS
++
++#endif /* SITE_TYPEDEFS */
++
++
++/*******************************************************************************
++ * Default Typedefs
++ *******************************************************************************/
++
++#ifdef USE_TYPEDEF_DEFAULTS
++#undef USE_TYPEDEF_DEFAULTS
++
++#ifndef TYPEDEF_BOOL
++typedef /*@abstract@*/ unsigned char bool;
++#endif
++
++/*----------------------- define uchar, ushort, uint, ulong ------------------*/
++
++#ifndef TYPEDEF_UCHAR
++typedef unsigned char uchar;
++#endif
++
++#ifndef TYPEDEF_USHORT
++typedef unsigned short ushort;
++#endif
++
++#ifndef TYPEDEF_UINT
++typedef unsigned int uint;
++#endif
++
++#ifndef TYPEDEF_ULONG
++typedef unsigned long ulong;
++#endif
++
++/*----------------------- define [u]int8/16/32/64, uintptr --------------------*/
++
++#ifndef TYPEDEF_UINT8
++typedef unsigned char uint8;
++#endif
++
++#ifndef TYPEDEF_UINT16
++typedef unsigned short uint16;
++#endif
++
++#ifndef TYPEDEF_UINT32
++typedef unsigned int uint32;
++#endif
++
++#ifndef TYPEDEF_UINT64
++typedef unsigned long long uint64;
++#endif
++
++#ifndef TYPEDEF_UINTPTR
++typedef unsigned int uintptr;
++#endif
++
++#ifndef TYPEDEF_INT8
++typedef signed char int8;
++#endif
++
++#ifndef TYPEDEF_INT16
++typedef signed short int16;
++#endif
++
++#ifndef TYPEDEF_INT32
++typedef signed int int32;
++#endif
++
++#ifndef TYPEDEF_INT64
++typedef signed long long int64;
++#endif
++
++/*----------------------- define float32/64, float_t -----------------------*/
++
++#ifndef TYPEDEF_FLOAT32
++typedef float float32;
++#endif
++
++#ifndef TYPEDEF_FLOAT64
++typedef double float64;
++#endif
++
++/*
++ * abstracted floating point type allows for compile time selection of
++ * single or double precision arithmetic. Compiling with -DFLOAT32
++ * selects single precision; the default is double precision.
++ */
++
++#ifndef TYPEDEF_FLOAT_T
++
++#if defined(FLOAT32)
++typedef float32 float_t;
++#else /* default to double precision floating point */
++typedef float64 float_t;
++#endif
++
++#endif /* TYPEDEF_FLOAT_T */
++
++/*----------------------- define macro values -----------------------------*/
++
++#ifndef FALSE
++#define FALSE 0
++#endif
++
++#ifndef TRUE
++#define TRUE 1
++#endif
++
++#ifndef NULL
++#define NULL 0
++#endif
++
++#ifndef OFF
++#define OFF 0
++#endif
++
++#ifndef ON
++#define ON 1
++#endif
++
++#define AUTO (-1)
++
++/* Reclaiming text and data :
++ The following macros specify special linker sections that can be reclaimed
++ after a system is considered 'up'.
++ */
++#if defined(__GNUC__) && defined(BCMRECLAIM)
++extern bool bcmreclaimed;
++#define BCMINITDATA(_data) __attribute__ ((__section__ (".dataini." #_data))) _data##_ini
++#define BCMINITFN(_fn) __attribute__ ((__section__ (".textini." #_fn))) _fn##_ini
++#define BCMINIT(_id) _id##_ini
++#else
++#define BCMINITDATA(_data) _data
++#define BCMINITFN(_fn) _fn
++#define BCMINIT(_id) _id
++#define bcmreclaimed 0
++#endif
++
++/*----------------------- define PTRSZ, INLINE ----------------------------*/
++
++#ifndef PTRSZ
++#define PTRSZ sizeof (char*)
++#endif
++
++#ifndef INLINE
++
++#ifdef _MSC_VER
++
++#define INLINE __inline
++
++#elif __GNUC__
++
++#define INLINE __inline__
++
++#else
++
++#define INLINE
++
++#endif /* _MSC_VER */
++
++#endif /* INLINE */
++
++#undef TYPEDEF_BOOL
++#undef TYPEDEF_UCHAR
++#undef TYPEDEF_USHORT
++#undef TYPEDEF_UINT
++#undef TYPEDEF_ULONG
++#undef TYPEDEF_UINT8
++#undef TYPEDEF_UINT16
++#undef TYPEDEF_UINT32
++#undef TYPEDEF_UINT64
++#undef TYPEDEF_UINTPTR
++#undef TYPEDEF_INT8
++#undef TYPEDEF_INT16
++#undef TYPEDEF_INT32
++#undef TYPEDEF_INT64
++#undef TYPEDEF_FLOAT32
++#undef TYPEDEF_FLOAT64
++#undef TYPEDEF_FLOAT_T
++
++#endif /* USE_TYPEDEF_DEFAULTS */
++
++#endif /* _TYPEDEFS_H_ */
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/irq.c linux-2.6.17-owrt/arch/mips/bcm947xx/irq.c
+--- linux-2.6.17/arch/mips/bcm947xx/irq.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/irq.c 2006-06-18 15:32:25.000000000 +0200
+@@ -0,0 +1,64 @@
++/*
++ * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/config.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/module.h>
++#include <linux/smp.h>
++#include <linux/types.h>
++
++#include <asm/cpu.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/irq_cpu.h>
++
++void plat_irq_dispatch(struct pt_regs *regs)
++{
++ u32 cause;
++
++ cause = read_c0_cause() & read_c0_status() & CAUSEF_IP;
++
++ clear_c0_status(cause);
++
++ if (cause & CAUSEF_IP7)
++ do_IRQ(7, regs);
++ if (cause & CAUSEF_IP2)
++ do_IRQ(2, regs);
++ if (cause & CAUSEF_IP3)
++ do_IRQ(3, regs);
++ if (cause & CAUSEF_IP4)
++ do_IRQ(4, regs);
++ if (cause & CAUSEF_IP5)
++ do_IRQ(5, regs);
++ if (cause & CAUSEF_IP6)
++ do_IRQ(6, regs);
++}
++
++void __init arch_init_irq(void)
++{
++ mips_cpu_irq_init(0);
++}
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/Makefile linux-2.6.17-owrt/arch/mips/bcm947xx/Makefile
+--- linux-2.6.17/arch/mips/bcm947xx/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/Makefile 2006-06-18 15:33:03.000000000 +0200
+@@ -0,0 +1,6 @@
++#
++# Makefile for the BCM47xx specific kernel interface routines
++# under Linux.
++#
++
++obj-y := irq.o prom.o setup.o time.o pci.o
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/pci.c linux-2.6.17-owrt/arch/mips/bcm947xx/pci.c
+--- linux-2.6.17/arch/mips/bcm947xx/pci.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/pci.c 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,215 @@
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/types.h>
++
++#include <asm/cpu.h>
++#include <asm/io.h>
++
++#include <typedefs.h>
++#include <osl.h>
++#include <sbutils.h>
++#include <sbmips.h>
++#include <sbconfig.h>
++#include <sbpci.h>
++#include <bcmdevs.h>
++#include <pcicfg.h>
++
++extern sb_t *sbh;
++extern spinlock_t sbh_lock;
++
++
++static int
++sb_pci_read_config(struct pci_bus *bus, unsigned int devfn,
++ int reg, int size, u32 *val)
++{
++ int ret;
++ unsigned long flags;
++
++ spin_lock_irqsave(&sbh_lock, flags);
++ ret = sbpci_read_config(sbh, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), reg, val, size);
++ spin_unlock_irqrestore(&sbh_lock, flags);
++
++ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
++}
++
++static int
++sb_pci_write_config(struct pci_bus *bus, unsigned int devfn,
++ int reg, int size, u32 val)
++{
++ int ret;
++ unsigned long flags;
++
++ spin_lock_irqsave(&sbh_lock, flags);
++ ret = sbpci_write_config(sbh, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), reg, &val, size);
++ spin_unlock_irqrestore(&sbh_lock, flags);
++
++ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
++}
++
++
++static struct pci_ops sb_pci_ops = {
++ .read = sb_pci_read_config,
++ .write = sb_pci_write_config,
++};
++
++static struct resource sb_pci_mem_resource = {
++ .name = "SB PCI Memory resources",
++ .start = SB_ENUM_BASE,
++ .end = SB_ENUM_LIM - 1,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct resource sb_pci_io_resource = {
++ .name = "SB PCI I/O resources",
++ .start = 0x000,
++ .end = 0x0FF,
++ .flags = IORESOURCE_IO,
++};
++
++static struct pci_controller bcm47xx_sb_pci_controller = {
++ .pci_ops = &sb_pci_ops,
++ .mem_resource = &sb_pci_mem_resource,
++ .io_resource = &sb_pci_io_resource,
++};
++
++static struct resource ext_pci_mem_resource = {
++ .name = "Ext PCI Memory resources",
++ .start = 0x40000000,
++ .end = 0x7fffffff,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct resource ext_pci_io_resource = {
++ .name = "Ext PCI I/O resources",
++ .start = 0x100,
++ .end = 0x1FF,
++ .flags = IORESOURCE_IO,
++};
++
++static struct pci_controller bcm47xx_ext_pci_controller = {
++ .pci_ops = &sb_pci_ops,
++ .io_resource = &ext_pci_io_resource,
++ .mem_resource = &ext_pci_mem_resource,
++ .mem_offset = 0x24000000,
++};
++
++void bcm47xx_pci_init(void)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&sbh_lock, flags);
++ sbpci_init(sbh);
++ spin_unlock_irqrestore(&sbh_lock, flags);
++
++ set_io_port_base((unsigned long) ioremap_nocache(SB_PCI_MEM, 0x04000000));
++
++ register_pci_controller(&bcm47xx_sb_pci_controller);
++ register_pci_controller(&bcm47xx_ext_pci_controller);
++}
++
++int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ u8 irq;
++
++ if (dev->bus->number == 1)
++ return 2;
++
++ pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
++ return irq + 2;
++}
++
++u32 pci_iobase = 0x100;
++u32 pci_membase = SB_PCI_DMA;
++
++static void bcm47xx_fixup_device(struct pci_dev *d)
++{
++ struct resource *res;
++ int pos, size;
++ u32 *base;
++
++ if (d->bus->number == 0)
++ return;
++
++ printk("PCI: Fixing up device %s\n", pci_name(d));
++
++ /* Fix up resource bases */
++ for (pos = 0; pos < 6; pos++) {
++ res = &d->resource[pos];
++ base = ((res->flags & IORESOURCE_IO) ? &pci_iobase : &pci_membase);
++ if (res->end) {
++ size = res->end - res->start + 1;
++ if (*base & (size - 1))
++ *base = (*base + size) & ~(size - 1);
++ res->start = *base;
++ res->end = res->start + size - 1;
++ *base += size;
++ pci_write_config_dword(d, PCI_BASE_ADDRESS_0 + (pos << 2), res->start);
++ }
++ /* Fix up PCI bridge BAR0 only */
++ if (d->bus->number == 1 && PCI_SLOT(d->devfn) == 0)
++ break;
++ }
++ /* Fix up interrupt lines */
++ if (pci_find_device(VENDOR_BROADCOM, SB_PCI, NULL))
++ d->irq = (pci_find_device(VENDOR_BROADCOM, SB_PCI, NULL))->irq;
++ pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);
++}
++
++
++static void bcm47xx_fixup_bridge(struct pci_dev *dev)
++{
++ if (dev->bus->number != 1 || PCI_SLOT(dev->devfn) != 0)
++ return;
++
++ printk("PCI: fixing up bridge\n");
++
++ /* Enable PCI bridge bus mastering and memory space */
++ pci_set_master(dev);
++ pcibios_enable_device(dev, ~0);
++
++ /* Enable PCI bridge BAR1 prefetch and burst */
++ pci_write_config_dword(dev, PCI_BAR1_CONTROL, 3);
++}
++
++/* Do platform specific device initialization at pci_enable_device() time */
++int pcibios_plat_dev_init(struct pci_dev *dev)
++{
++ uint coreidx;
++ unsigned long flags;
++
++ bcm47xx_fixup_device(dev);
++
++ /* These cores come out of reset enabled */
++ if ((dev->bus->number != 0) ||
++ (dev->device == SB_MIPS) ||
++ (dev->device == SB_MIPS33) ||
++ (dev->device == SB_EXTIF) ||
++ (dev->device == SB_CC))
++ return 0;
++
++ /* Do a core reset */
++ spin_lock_irqsave(&sbh_lock, flags);
++ coreidx = sb_coreidx(sbh);
++ if (sb_setcoreidx(sbh, PCI_SLOT(dev->devfn)) && (sb_coreid(sbh) == SB_USB)) {
++ /*
++ * The USB core requires a special bit to be set during core
++ * reset to enable host (OHCI) mode. Resetting the SB core in
++ * pcibios_enable_device() is a hack for compatibility with
++ * vanilla usb-ohci so that it does not have to know about
++ * SB. A driver that wants to use the USB core in device mode
++ * should know about SB and should reset the bit back to 0
++ * after calling pcibios_enable_device().
++ */
++ sb_core_disable(sbh, sb_coreflags(sbh, 0, 0));
++ sb_core_reset(sbh, 1 << 29);
++ } else {
++ sb_core_reset(sbh, 0);
++ }
++ sb_setcoreidx(sbh, coreidx);
++ spin_unlock_irqrestore(&sbh_lock, flags);
++
++ return 0;
++}
++
++DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, bcm47xx_fixup_bridge);
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/prom.c linux-2.6.17-owrt/arch/mips/bcm947xx/prom.c
+--- linux-2.6.17/arch/mips/bcm947xx/prom.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/prom.c 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,59 @@
++/*
++ * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/init.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/bootmem.h>
++
++#include <asm/addrspace.h>
++#include <asm/bootinfo.h>
++#include <asm/pmon.h>
++
++const char *get_system_type(void)
++{
++ return "Broadcom BCM47xx";
++}
++
++void __init prom_init(void)
++{
++ unsigned long mem;
++
++ mips_machgroup = MACH_GROUP_BRCM;
++ mips_machtype = MACH_BCM47XX;
++
++ /* Figure out memory size by finding aliases */
++ for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
++ if (*(unsigned long *)((unsigned long)(prom_init) + mem) ==
++ *(unsigned long *)(prom_init))
++ break;
++ }
++
++ add_memory_region(0, mem, BOOT_MEM_RAM);
++}
++
++unsigned long __init prom_free_prom_memory(void)
++{
++ return 0;
++}
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/setup.c linux-2.6.17-owrt/arch/mips/bcm947xx/setup.c
+--- linux-2.6.17/arch/mips/bcm947xx/setup.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/setup.c 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,158 @@
++/*
++ * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
++ * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
++ * 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.
++ *
++ * THIS SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/init.h>
++#include <linux/types.h>
++#include <linux/tty.h>
++#include <linux/serial.h>
++#include <linux/serial_core.h>
++#include <linux/serial_reg.h>
++#include <asm/bootinfo.h>
++#include <asm/time.h>
++#include <asm/reboot.h>
++#include <linux/pm.h>
++
++#include <typedefs.h>
++#include <osl.h>
++#include <sbutils.h>
++#include <sbmips.h>
++#include <sbpci.h>
++#include <sbconfig.h>
++#include <bcmdevs.h>
++#include <bcmutils.h>
++#include <bcmnvram.h>
++
++extern void bcm47xx_pci_init(void);
++extern void bcm47xx_time_init(void);
++extern void bcm47xx_timer_setup(struct irqaction *irq);
++void *sbh;
++spinlock_t sbh_lock = SPIN_LOCK_UNLOCKED;
++int boardflags;
++
++static int ser_line = 0;
++
++typedef struct {
++ void *regs;
++ uint irq;
++ uint baud_base;
++ uint reg_shift;
++} serial_port;
++
++static serial_port ports[4];
++static int num_ports = 0;
++
++static void
++serial_add(void *regs, uint irq, uint baud_base, uint reg_shift)
++{
++ ports[num_ports].regs = regs;
++ ports[num_ports].irq = irq;
++ ports[num_ports].baud_base = baud_base;
++ ports[num_ports].reg_shift = reg_shift;
++ num_ports++;
++}
++
++static void
++do_serial_add(serial_port *port)
++{
++ void *regs;
++ uint irq;
++ uint baud_base;
++ uint reg_shift;
++ struct uart_port s;
++
++ regs = port->regs;
++ irq = port->irq;
++ baud_base = port->baud_base;
++ reg_shift = port->reg_shift;
++
++ memset(&s, 0, sizeof(s));
++
++ s.line = ser_line++;
++ s.membase = regs;
++ s.irq = irq + 2;
++ s.uartclk = baud_base;
++ s.flags = ASYNC_BOOT_AUTOCONF;
++ s.iotype = SERIAL_IO_MEM;
++ s.regshift = reg_shift;
++
++ if (early_serial_setup(&s) != 0) {
++ printk(KERN_ERR "Serial setup failed!\n");
++ }
++}
++
++static void bcm47xx_machine_restart(char *command)
++{
++ printk("Please stand by while rebooting the system...\n");
++
++ /* Set the watchdog timer to reset immediately */
++ local_irq_disable();
++ sb_watchdog(sbh, 1);
++ while (1);
++}
++
++static void bcm47xx_machine_halt(void)
++{
++ /* Disable interrupts and watchdog and spin forever */
++ local_irq_disable();
++ sb_watchdog(sbh, 0);
++ while (1);
++}
++
++void __init plat_setup(void)
++{
++ char *s;
++ int i;
++
++ sbh = (void *) sb_kattach();
++ sb_mips_init(sbh);
++
++ bcm47xx_pci_init();
++
++ sb_serial_init(sbh, serial_add);
++ boardflags = getintvar(NULL, "boardflags");
++
++ /* reverse serial ports if the nvram variable kernel_args starts with console=ttyS1 */
++ s = early_nvram_get("kernel_args");
++ if (!s) s = "";
++ if (!strncmp(s, "console=ttyS1", 13)) {
++ for (i = num_ports; i; i--)
++ do_serial_add(&ports[i - 1]);
++ } else {
++ for (i = 0; i < num_ports; i++)
++ do_serial_add(&ports[i]);
++ }
++
++ _machine_restart = bcm47xx_machine_restart;
++ _machine_halt = bcm47xx_machine_halt;
++ pm_power_off = bcm47xx_machine_halt;
++
++ board_time_init = bcm47xx_time_init;
++ board_timer_setup = bcm47xx_timer_setup;
++}
++
++EXPORT_SYMBOL(sbh);
++EXPORT_SYMBOL(sbh_lock);
++EXPORT_SYMBOL(boardflags);
+diff -Nur linux-2.6.17/arch/mips/bcm947xx/time.c linux-2.6.17-owrt/arch/mips/bcm947xx/time.c
+--- linux-2.6.17/arch/mips/bcm947xx/time.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/mips/bcm947xx/time.c 2006-06-18 15:29:23.000000000 +0200
+@@ -0,0 +1,59 @@
++/*
++ * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/config.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/serial_reg.h>
++#include <linux/interrupt.h>
++#include <asm/addrspace.h>
++#include <asm/io.h>
++#include <asm/time.h>
++
++void __init
++bcm47xx_time_init(void)
++{
++ unsigned int hz;
++
++ /*
++ * Use deterministic values for initial counter interrupt
++ * so that calibrate delay avoids encountering a counter wrap.
++ */
++ write_c0_count(0);
++ write_c0_compare(0xffff);
++
++ hz = 200 * 1000 * 1000;
++
++ /* Set MIPS counter frequency for fixed_rate_gettimeoffset() */
++ mips_hpt_frequency = hz / 2;
++
++}
++
++void __init
++bcm47xx_timer_setup(struct irqaction *irq)
++{
++ /* Enable the timer interrupt */
++ setup_irq(7, irq);
++}
+diff -Nur linux-2.6.17/arch/mips/Kconfig linux-2.6.17-owrt/arch/mips/Kconfig
+--- linux-2.6.17/arch/mips/Kconfig 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/arch/mips/Kconfig 2006-06-18 15:29:23.000000000 +0200
+@@ -245,6 +245,17 @@
+ Members include the Acer PICA, MIPS Magnum 4000, MIPS Millenium and
+ Olivetti M700-10 workstations.
+
++config BCM947XX
++ bool "Support for BCM947xx based boards"
++ select DMA_NONCOHERENT
++ select HW_HAS_PCI
++ select IRQ_CPU
++ select SYS_HAS_CPU_MIPS32_R1
++ select SYS_SUPPORTS_32BIT_KERNEL
++ select SYS_SUPPORTS_LITTLE_ENDIAN
++ help
++ Support for BCM947xx based boards
++
+ config LASAT
+ bool "LASAT Networks platforms"
+ select DMA_NONCOHERENT
+diff -Nur linux-2.6.17/arch/mips/kernel/cpu-probe.c linux-2.6.17-owrt/arch/mips/kernel/cpu-probe.c
+--- linux-2.6.17/arch/mips/kernel/cpu-probe.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/arch/mips/kernel/cpu-probe.c 2006-06-18 15:29:23.000000000 +0200
+@@ -691,6 +691,28 @@
+ }
+
+
++static inline void cpu_probe_broadcom(struct cpuinfo_mips *c)
++{
++ decode_config1(c);
++ switch (c->processor_id & 0xff00) {
++ case PRID_IMP_BCM3302:
++ c->cputype = CPU_BCM3302;
++ c->isa_level = MIPS_CPU_ISA_M32R1;
++ c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
++ MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER;
++ break;
++ case PRID_IMP_BCM4710:
++ c->cputype = CPU_BCM4710;
++ c->isa_level = MIPS_CPU_ISA_M32R1;
++ c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
++ MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER;
++ break;
++ default:
++ c->cputype = CPU_UNKNOWN;
++ break;
++ }
++}
++
+ __init void cpu_probe(void)
+ {
+ struct cpuinfo_mips *c = &current_cpu_data;
+@@ -713,6 +735,9 @@
+ case PRID_COMP_SIBYTE:
+ cpu_probe_sibyte(c);
+ break;
++ case PRID_COMP_BROADCOM:
++ cpu_probe_broadcom(c);
++ break;
+ case PRID_COMP_SANDCRAFT:
+ cpu_probe_sandcraft(c);
+ break;
+diff -Nur linux-2.6.17/arch/mips/kernel/head.S linux-2.6.17-owrt/arch/mips/kernel/head.S
+--- linux-2.6.17/arch/mips/kernel/head.S 2006-06-18 12:54:51.000000000 +0200
++++ linux-2.6.17-owrt/arch/mips/kernel/head.S 2006-06-18 15:29:23.000000000 +0200
+@@ -133,6 +133,11 @@
+ j kernel_entry
+ nop
+
++#ifdef CONFIG_BCM4710
++#undef eret
++#define eret nop; nop; eret
++#endif
++
+ /*
+ * Reserved space for exception handlers.
+ * Necessary for machines which link their kernels at KSEG0.
+diff -Nur linux-2.6.17/arch/mips/kernel/proc.c linux-2.6.17-owrt/arch/mips/kernel/proc.c
+--- linux-2.6.17/arch/mips/kernel/proc.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/arch/mips/kernel/proc.c 2006-06-18 15:29:23.000000000 +0200
+@@ -84,6 +84,8 @@
+ [CPU_VR4181] = "NEC VR4181",
+ [CPU_VR4181A] = "NEC VR4181A",
+ [CPU_SR71000] = "Sandcraft SR71000",
++ [CPU_BCM3302] = "Broadcom BCM3302",
++ [CPU_BCM4710] = "Broadcom BCM4710",
+ [CPU_PR4450] = "Philips PR4450",
+ };
+
+diff -Nur linux-2.6.17/arch/mips/Makefile linux-2.6.17-owrt/arch/mips/Makefile
+--- linux-2.6.17/arch/mips/Makefile 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/arch/mips/Makefile 2006-06-18 15:29:23.000000000 +0200
+@@ -565,6 +565,13 @@
+ load-$(CONFIG_SIBYTE_BIGSUR) := 0xffffffff80100000
+
+ #
++# Broadcom BCM47XX boards
++#
++core-$(CONFIG_BCM947XX) += arch/mips/bcm947xx/ arch/mips/bcm947xx/broadcom/
++cflags-$(CONFIG_BCM947XX) += -Iarch/mips/bcm947xx/include
++load-$(CONFIG_BCM947XX) := 0xffffffff80001000
++
++#
+ # SNI RM200 PCI
+ #
+ core-$(CONFIG_SNI_RM200_PCI) += arch/mips/sni/
+diff -Nur linux-2.6.17/arch/mips/mm/tlbex.c linux-2.6.17-owrt/arch/mips/mm/tlbex.c
+--- linux-2.6.17/arch/mips/mm/tlbex.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/arch/mips/mm/tlbex.c 2006-06-18 15:29:23.000000000 +0200
+@@ -882,6 +882,8 @@
+ case CPU_4KSC:
+ case CPU_20KC:
+ case CPU_25KF:
++ case CPU_BCM3302:
++ case CPU_BCM4710:
+ tlbw(p);
+ break;
+
+diff -Nur linux-2.6.17/include/asm-mips/bootinfo.h linux-2.6.17-owrt/include/asm-mips/bootinfo.h
+--- linux-2.6.17/include/asm-mips/bootinfo.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/asm-mips/bootinfo.h 2006-06-18 15:29:23.000000000 +0200
+@@ -218,6 +218,12 @@
+ #define MACH_GROUP_TITAN 22 /* PMC-Sierra Titan */
+ #define MACH_TITAN_YOSEMITE 1 /* PMC-Sierra Yosemite */
+
++/*
++ * Valid machtype for group Broadcom
++ */
++#define MACH_GROUP_BRCM 23 /* Broadcom */
++#define MACH_BCM47XX 1 /* Broadcom BCM47xx */
++
+ #define CL_SIZE COMMAND_LINE_SIZE
+
+ const char *get_system_type(void);
+diff -Nur linux-2.6.17/include/asm-mips/cpu.h linux-2.6.17-owrt/include/asm-mips/cpu.h
+--- linux-2.6.17/include/asm-mips/cpu.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/asm-mips/cpu.h 2006-06-18 15:30:53.000000000 +0200
+@@ -104,6 +104,13 @@
+ #define PRID_IMP_SR71000 0x0400
+
+ /*
++ * These are the PRID's for when 23:16 == PRID_COMP_BROADCOM
++ */
++
++#define PRID_IMP_BCM4710 0x4000
++#define PRID_IMP_BCM3302 0x9000
++
++/*
+ * Definitions for 7:0 on legacy processors
+ */
+
+@@ -200,7 +207,9 @@
+ #define CPU_SB1A 62
+ #define CPU_74K 63
+ #define CPU_R14000 64
+-#define CPU_LAST 64
++#define CPU_BCM3302 65
++#define CPU_BCM4710 66
++#define CPU_LAST 66
+
+ /*
+ * ISA Level encodings
+diff -Nur linux-2.6.17/include/linux/pci_ids.h linux-2.6.17-owrt/include/linux/pci_ids.h
+--- linux-2.6.17/include/linux/pci_ids.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/linux/pci_ids.h 2006-06-18 15:29:23.000000000 +0200
+@@ -1906,6 +1906,7 @@
+ #define PCI_DEVICE_ID_TIGON3_5901_2 0x170e
+ #define PCI_DEVICE_ID_BCM4401 0x4401
+ #define PCI_DEVICE_ID_BCM4401B0 0x4402
++#define PCI_DEVICE_ID_BCM4713 0x4713
+
+ #define PCI_VENDOR_ID_TOPIC 0x151f
+ #define PCI_DEVICE_ID_TOPIC_TP560 0x0000
diff --git a/target/linux/brcm-2.6/patches/002-flash-map.patch b/target/linux/brcm-2.6/patches/002-flash-map.patch
new file mode 100644
index 0000000000..9d568930d2
--- /dev/null
+++ b/target/linux/brcm-2.6/patches/002-flash-map.patch
@@ -0,0 +1,483 @@
+diff -urN linux.old/drivers/mtd/maps/bcm47xx-flash.c linux.dev/drivers/mtd/maps/bcm47xx-flash.c
+--- linux.old/drivers/mtd/maps/bcm47xx-flash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/mtd/maps/bcm47xx-flash.c 2006-06-23 19:54:06.000000000 +0200
+@@ -0,0 +1,452 @@
++/*
++ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
++ * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
++ * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
++ *
++ * original functions for finding root filesystem from Mike Baker
++ *
++ * 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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ * Copyright 2001-2003, 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.
++ *
++ * Flash mapping for BCM947XX boards
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/wait.h>
++#include <linux/config.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#ifdef CONFIG_MTD_PARTITIONS
++#include <linux/mtd/partitions.h>
++#endif
++#include <linux/squashfs_fs.h>
++#include <linux/jffs2.h>
++#include <linux/crc32.h>
++#include <asm/io.h>
++
++#include <trxhdr.h>
++
++#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
++#define NVRAM_SPACE 0x8000
++#define WINDOW_ADDR 0x1c000000
++#define WINDOW_SIZE 0x800000
++#define BUSWIDTH 2
++
++static struct mtd_info *bcm947xx_mtd;
++
++static void bcm947xx_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
++{
++#define MIPS_MEMCPY_ALIGN 4
++ map_word ret;
++ ssize_t transfer;
++ ssize_t done = 0;
++ if ((len >= MIPS_MEMCPY_ALIGN) && (!(from & (MIPS_MEMCPY_ALIGN - 1))) && (!(((unsigned int)to & (MIPS_MEMCPY_ALIGN - 1))))) {
++ done = len & ~(MIPS_MEMCPY_ALIGN - 1);
++ memcpy_fromio(to, map->virt + from, done);
++ }
++ while (done < len) {
++ ret = map->read(map, from + done);
++ transfer = len - done;
++ if (transfer > map->bankwidth)
++ transfer = map->bankwidth;
++ memcpy((void *)((unsigned long)to + done), &ret.x[0], transfer);
++ done += transfer;
++ }
++}
++
++static struct map_info bcm947xx_map = {
++ name: "Physically mapped flash",
++ size: WINDOW_SIZE,
++ bankwidth: BUSWIDTH,
++ phys: WINDOW_ADDR,
++};
++
++#ifdef CONFIG_MTD_PARTITIONS
++
++static struct mtd_partition bcm947xx_parts[] = {
++ { name: "cfe", offset: 0, size: 0, mask_flags: MTD_WRITEABLE, },
++ { name: "linux", offset: 0, size: 0, },
++ { name: "rootfs", offset: 0, size: 0, },
++ { name: "nvram", offset: 0, size: 0, },
++ { name: "OpenWrt", offset: 0, size: 0, },
++ { name: NULL, },
++};
++
++static int __init
++find_cfe_size(struct mtd_info *mtd, size_t size)
++{
++ struct trx_header *trx;
++ unsigned char buf[512];
++ int off;
++ size_t len;
++ int blocksize;
++
++ trx = (struct trx_header *) buf;
++
++ blocksize = mtd->erasesize;
++ if (blocksize < 0x10000)
++ blocksize = 0x10000;
++
++ for (off = (128*1024); off < size; off += blocksize) {
++ memset(buf, 0xe5, sizeof(buf));
++
++ /*
++ * Read into buffer
++ */
++ if (MTD_READ(mtd, off, sizeof(buf), &len, buf) ||
++ len != sizeof(buf))
++ continue;
++
++ /* found a TRX header */
++ if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
++ goto found;
++ }
++ }
++
++ printk(KERN_NOTICE
++ "%s: Couldn't find bootloader size\n",
++ mtd->name);
++ return -1;
++
++ found:
++ printk(KERN_NOTICE "bootloader size: %d\n", off);
++ return off;
++
++}
++
++/*
++ * Copied from mtdblock.c
++ *
++ * Cache stuff...
++ *
++ * Since typical flash erasable sectors are much larger than what Linux's
++ * buffer cache can handle, we must implement read-modify-write on flash
++ * sectors for each block write requests. To avoid over-erasing flash sectors
++ * and to speed things up, we locally cache a whole flash sector while it is
++ * being written to until a different sector is required.
++ */
++
++static void erase_callback(struct erase_info *done)
++{
++ wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
++ wake_up(wait_q);
++}
++
++static int erase_write (struct mtd_info *mtd, unsigned long pos,
++ int len, const char *buf)
++{
++ struct erase_info erase;
++ DECLARE_WAITQUEUE(wait, current);
++ wait_queue_head_t wait_q;
++ size_t retlen;
++ int ret;
++
++ /*
++ * First, let's erase the flash block.
++ */
++
++ init_waitqueue_head(&wait_q);
++ erase.mtd = mtd;
++ erase.callback = erase_callback;
++ erase.addr = pos;
++ erase.len = len;
++ erase.priv = (u_long)&wait_q;
++
++ set_current_state(TASK_INTERRUPTIBLE);
++ add_wait_queue(&wait_q, &wait);
++
++ ret = MTD_ERASE(mtd, &erase);
++ if (ret) {
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&wait_q, &wait);
++ printk (KERN_WARNING "erase of region [0x%lx, 0x%x] "
++ "on \"%s\" failed\n",
++ pos, len, mtd->name);
++ return ret;
++ }
++
++ schedule(); /* Wait for erase to finish. */
++ remove_wait_queue(&wait_q, &wait);
++
++ /*
++ * Next, writhe data to flash.
++ */
++
++ ret = MTD_WRITE (mtd, pos, len, &retlen, buf);
++ if (ret)
++ return ret;
++ if (retlen != len)
++ return -EIO;
++ return 0;
++}
++
++
++
++
++static int __init
++find_root(struct mtd_info *mtd, size_t size, struct mtd_partition *part)
++{
++ struct trx_header trx, *trx2;
++ unsigned char buf[512], *block;
++ int off, blocksize;
++ u32 i, crc = ~0;
++ size_t len;
++ struct squashfs_super_block *sb = (struct squashfs_super_block *) buf;
++
++ blocksize = mtd->erasesize;
++ if (blocksize < 0x10000)
++ blocksize = 0x10000;
++
++ for (off = (128*1024); off < size; off += blocksize) {
++ memset(&trx, 0xe5, sizeof(trx));
++
++ /*
++ * Read into buffer
++ */
++ if (MTD_READ(mtd, off, sizeof(trx), &len, (char *) &trx) ||
++ len != sizeof(trx))
++ continue;
++
++ /* found a TRX header */
++ if (le32_to_cpu(trx.magic) == TRX_MAGIC) {
++ part->offset = le32_to_cpu(trx.offsets[2]) ? :
++ le32_to_cpu(trx.offsets[1]);
++ part->size = le32_to_cpu(trx.len);
++
++ part->size -= part->offset;
++ part->offset += off;
++
++ goto found;
++ }
++ }
++
++ printk(KERN_NOTICE
++ "%s: Couldn't find root filesystem\n",
++ mtd->name);
++ return -1;
++
++ found:
++ if (part->size == 0)
++ return 0;
++
++ if (MTD_READ(mtd, part->offset, sizeof(buf), &len, buf) || len != sizeof(buf))
++ return 0;
++
++ if (*((__u32 *) buf) == SQUASHFS_MAGIC) {
++ printk(KERN_INFO "%s: Filesystem type: squashfs, size=0x%x\n", mtd->name, (u32) sb->bytes_used);
++
++ /* Update the squashfs partition size based on the superblock info */
++ part->size = sb->bytes_used;
++ len = part->offset + part->size;
++ len += (mtd->erasesize - 1);
++ len &= ~(mtd->erasesize - 1);
++ part->size = len - part->offset;
++ } else if (*((__u16 *) buf) == JFFS2_MAGIC_BITMASK) {
++ printk(KERN_INFO "%s: Filesystem type: jffs2\n", mtd->name);
++
++ /* Move the squashfs outside of the trx */
++ part->size = 0;
++ } else {
++ printk(KERN_INFO "%s: Filesystem type: unknown\n", mtd->name);
++ return 0;
++ }
++
++ if (trx.len != part->offset + part->size - off) {
++ /* Update the trx offsets and length */
++ trx.len = part->offset + part->size - off;
++
++ /* Update the trx crc32 */
++ for (i = (u32) &(((struct trx_header *)NULL)->flag_version); i <= trx.len; i += sizeof(buf)) {
++ if (MTD_READ(mtd, off + i, sizeof(buf), &len, buf) || len != sizeof(buf))
++ return 0;
++ crc = crc32_le(crc, buf, min(sizeof(buf), trx.len - i));
++ }
++ trx.crc32 = crc;
++
++ /* read first eraseblock from the trx */
++ block = kmalloc(mtd->erasesize, GFP_KERNEL);
++ trx2 = (struct trx_header *) block;
++ if (MTD_READ(mtd, off, mtd->erasesize, &len, block) || len != mtd->erasesize) {
++ printk("Error accessing the first trx eraseblock\n");
++ return 0;
++ }
++
++ printk("Updating TRX offsets and length:\n");
++ printk("old trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx2->offsets[0], trx2->offsets[1], trx2->offsets[2], trx2->len, trx2->crc32);
++ printk("new trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx.offsets[0], trx.offsets[1], trx.offsets[2], trx.len, trx.crc32);
++
++ /* Write updated trx header to the flash */
++ memcpy(block, &trx, sizeof(trx));
++ if (mtd->unlock)
++ mtd->unlock(mtd, off, mtd->erasesize);
++ erase_write(mtd, off, mtd->erasesize, block);
++ if (mtd->sync)
++ mtd->sync(mtd);
++ kfree(block);
++ printk("Done\n");
++ }
++
++ return part->size;
++}
++
++struct mtd_partition * __init
++init_mtd_partitions(struct mtd_info *mtd, size_t size)
++{
++ int cfe_size;
++
++ if ((cfe_size = find_cfe_size(mtd,size)) < 0)
++ return NULL;
++
++ /* boot loader */
++ bcm947xx_parts[0].offset = 0;
++ bcm947xx_parts[0].size = cfe_size;
++
++ /* nvram */
++ if (cfe_size != 384 * 1024) {
++ bcm947xx_parts[3].offset = size - ROUNDUP(NVRAM_SPACE, mtd->erasesize);
++ bcm947xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
++ } else {
++ /* nvram (old 128kb config partition on netgear wgt634u) */
++ bcm947xx_parts[3].offset = bcm947xx_parts[0].size;
++ bcm947xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
++ }
++
++ /* linux (kernel and rootfs) */
++ if (cfe_size != 384 * 1024) {
++ bcm947xx_parts[1].offset = bcm947xx_parts[0].size;
++ bcm947xx_parts[1].size = bcm947xx_parts[3].offset -
++ bcm947xx_parts[1].offset;
++ } else {
++ /* do not count the elf loader, which is on one block */
++ bcm947xx_parts[1].offset = bcm947xx_parts[0].size +
++ bcm947xx_parts[3].size + mtd->erasesize;
++ bcm947xx_parts[1].size = size -
++ bcm947xx_parts[0].size -
++ (2*bcm947xx_parts[3].size) -
++ mtd->erasesize;
++ }
++
++ /* find and size rootfs */
++ if (find_root(mtd,size,&bcm947xx_parts[2])==0) {
++ /* entirely jffs2 */
++ bcm947xx_parts[4].name = NULL;
++ bcm947xx_parts[2].size = size - bcm947xx_parts[2].offset -
++ bcm947xx_parts[3].size;
++ } else {
++ /* legacy setup */
++ /* calculate leftover flash, and assign it to the jffs2 partition */
++ if (cfe_size != 384 * 1024) {
++ bcm947xx_parts[4].offset = bcm947xx_parts[2].offset +
++ bcm947xx_parts[2].size;
++ if ((bcm947xx_parts[4].offset % mtd->erasesize) > 0) {
++ bcm947xx_parts[4].offset += mtd->erasesize -
++ (bcm947xx_parts[4].offset % mtd->erasesize);
++ }
++ bcm947xx_parts[4].size = bcm947xx_parts[3].offset -
++ bcm947xx_parts[4].offset;
++ } else {
++ bcm947xx_parts[4].offset = bcm947xx_parts[2].offset +
++ bcm947xx_parts[2].size;
++ if ((bcm947xx_parts[4].offset % mtd->erasesize) > 0) {
++ bcm947xx_parts[4].offset += mtd->erasesize -
++ (bcm947xx_parts[4].offset % mtd->erasesize);
++ }
++ bcm947xx_parts[4].size = size - bcm947xx_parts[3].size -
++ bcm947xx_parts[4].offset;
++ }
++ }
++
++ return bcm947xx_parts;
++}
++#endif
++
++int __init init_bcm947xx_map(void)
++{
++ size_t size;
++ int ret = 0;
++#ifdef CONFIG_MTD_PARTITIONS
++ struct mtd_partition *parts;
++ int i;
++#endif
++
++ bcm947xx_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
++
++ if (!bcm947xx_map.virt) {
++ printk("Failed to ioremap\n");
++ return -EIO;
++ }
++ simple_map_init(&bcm947xx_map);
++
++ bcm947xx_map.copy_from = bcm947xx_map_copy_from;
++
++ if (!(bcm947xx_mtd = do_map_probe("cfi_probe", &bcm947xx_map))) {
++ printk("Failed to do_map_probe\n");
++ iounmap((void *)bcm947xx_map.virt);
++ return -ENXIO;
++ }
++
++ bcm947xx_mtd->owner = THIS_MODULE;
++
++ size = bcm947xx_mtd->size;
++
++ printk(KERN_NOTICE "Flash device: 0x%x at 0x%x\n", size, WINDOW_ADDR);
++
++#ifdef CONFIG_MTD_PARTITIONS
++ parts = init_mtd_partitions(bcm947xx_mtd, size);
++ for (i = 0; parts[i].name; i++);
++ ret = add_mtd_partitions(bcm947xx_mtd, parts, i);
++ if (ret) {
++ printk(KERN_ERR "Flash: add_mtd_partitions failed\n");
++ goto fail;
++ }
++#endif
++ return 0;
++
++ fail:
++ if (bcm947xx_mtd)
++ map_destroy(bcm947xx_mtd);
++ if (bcm947xx_map.virt)
++ iounmap((void *)bcm947xx_map.virt);
++ bcm947xx_map.virt = 0;
++ return ret;
++}
++
++void __exit cleanup_bcm947xx_map(void)
++{
++#ifdef CONFIG_MTD_PARTITIONS
++ del_mtd_partitions(bcm947xx_mtd);
++#endif
++ map_destroy(bcm947xx_mtd);
++ iounmap((void *)bcm947xx_map.virt);
++}
++
++module_init(init_bcm947xx_map);
++module_exit(cleanup_bcm947xx_map);
+diff -urN linux.old/drivers/mtd/maps/Kconfig linux.dev/drivers/mtd/maps/Kconfig
+--- linux.old/drivers/mtd/maps/Kconfig 2006-06-23 19:13:51.000000000 +0200
++++ linux.dev/drivers/mtd/maps/Kconfig 2006-06-23 18:47:58.000000000 +0200
+@@ -299,6 +299,12 @@
+ Mapping for the Flaga digital module. If you don't have one, ignore
+ this setting.
+
++config MTD_BCM47XX
++ tristate "BCM47xx flash device"
++ depends on MIPS && MTD_CFI && BCM947XX
++ help
++ Support for the flash chips on the BCM947xx board.
++
+ config MTD_BEECH
+ tristate "CFI Flash device mapped on IBM 405LP Beech"
+ depends on MTD_CFI && BEECH
+diff -urN linux.old/drivers/mtd/maps/Makefile linux.dev/drivers/mtd/maps/Makefile
+--- linux.old/drivers/mtd/maps/Makefile 2006-06-23 19:13:51.000000000 +0200
++++ linux.dev/drivers/mtd/maps/Makefile 2006-06-23 18:47:58.000000000 +0200
+@@ -30,6 +30,7 @@
+ obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
+ obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
+ obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o
++obj-$(CONFIG_MTD_BCM47XX) += bcm47xx-flash.o
+ obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o
+ obj-$(CONFIG_MTD_IPAQ) += ipaq-flash.o
+ obj-$(CONFIG_MTD_SBC_GXX) += sbc_gxx.o
diff --git a/target/linux/brcm-2.6/patches/003-bcm4710_cache_fixes.patch b/target/linux/brcm-2.6/patches/003-bcm4710_cache_fixes.patch
new file mode 100644
index 0000000000..c8a08eb926
--- /dev/null
+++ b/target/linux/brcm-2.6/patches/003-bcm4710_cache_fixes.patch
@@ -0,0 +1,354 @@
+diff -Nur linux-2.6.17/arch/mips/kernel/genex.S linux-2.6.17-owrt/arch/mips/kernel/genex.S
+--- linux-2.6.17/arch/mips/kernel/genex.S 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/arch/mips/kernel/genex.S 2006-06-18 15:36:58.000000000 +0200
+@@ -73,6 +73,10 @@
+ .set push
+ .set mips3
+ .set noat
++#ifdef CONFIG_BCM4710
++ nop
++ nop
++#endif
+ mfc0 k1, CP0_CAUSE
+ li k0, 31<<2
+ andi k1, k1, 0x7c
+diff -Nur linux-2.6.17/arch/mips/mm/c-r4k.c linux-2.6.17-owrt/arch/mips/mm/c-r4k.c
+--- linux-2.6.17/arch/mips/mm/c-r4k.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/arch/mips/mm/c-r4k.c 2006-06-18 15:36:58.000000000 +0200
+@@ -14,6 +14,12 @@
+ #include <linux/mm.h>
+ #include <linux/bitops.h>
+
++#ifdef CONFIG_BCM4710
++#include "../bcm947xx/include/typedefs.h"
++#include "../bcm947xx/include/sbconfig.h"
++#include <asm/paccess.h>
++#endif
++
+ #include <asm/bcache.h>
+ #include <asm/bootinfo.h>
+ #include <asm/cache.h>
+@@ -30,6 +36,9 @@
+ #include <asm/cacheflush.h> /* for run_uncached() */
+
+
++/* For enabling BCM4710 cache workarounds */
++int bcm4710 = 0;
++
+ /*
+ * Special Variant of smp_call_function for use by cache functions:
+ *
+@@ -94,7 +103,9 @@
+ {
+ unsigned long dc_lsize = cpu_dcache_line_size();
+
+- if (dc_lsize == 16)
++ if (bcm4710)
++ r4k_blast_dcache_page = blast_dcache_page;
++ else if (dc_lsize == 16)
+ r4k_blast_dcache_page = blast_dcache16_page;
+ else if (dc_lsize == 32)
+ r4k_blast_dcache_page = r4k_blast_dcache_page_dc32;
+@@ -106,7 +117,9 @@
+ {
+ unsigned long dc_lsize = cpu_dcache_line_size();
+
+- if (dc_lsize == 16)
++ if (bcm4710)
++ r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
++ else if (dc_lsize == 16)
+ r4k_blast_dcache_page_indexed = blast_dcache16_page_indexed;
+ else if (dc_lsize == 32)
+ r4k_blast_dcache_page_indexed = blast_dcache32_page_indexed;
+@@ -118,7 +131,9 @@
+ {
+ unsigned long dc_lsize = cpu_dcache_line_size();
+
+- if (dc_lsize == 16)
++ if (bcm4710)
++ r4k_blast_dcache = blast_dcache;
++ else if (dc_lsize == 16)
+ r4k_blast_dcache = blast_dcache16;
+ else if (dc_lsize == 32)
+ r4k_blast_dcache = blast_dcache32;
+@@ -683,6 +698,8 @@
+ unsigned long addr = (unsigned long) arg;
+
+ R4600_HIT_CACHEOP_WAR_IMPL;
++ BCM4710_PROTECTED_FILL_TLB(addr);
++ BCM4710_PROTECTED_FILL_TLB(addr + 4);
+ protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
+ if (!cpu_icache_snoops_remote_store && scache_size)
+ protected_writeback_scache_line(addr & ~(sc_lsize - 1));
+@@ -1189,6 +1206,16 @@
+ static inline void coherency_setup(void)
+ {
+ change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
++#if defined(CONFIG_BCM4310) || defined(CONFIG_BCM4704) || defined(CONFIG_BCM5365)
++ if (BCM330X(current_cpu_data.processor_id)) {
++ __u32 cm = read_c0_diag();
++ /* Enable icache */
++ cm |= (1 << 31);
++ /* Enable dcache */
++ cm |= (1 << 30);
++ write_c0_diag(cm);
++ }
++#endif
+
+ /*
+ * c0_status.cu=0 specifies that updates by the sc instruction use
+@@ -1227,6 +1254,15 @@
+
+ /* Default cache error handler for R4000 and R5000 family */
+ set_uncached_handler (0x100, &except_vec2_generic, 0x80);
++
++ /* Check if special workarounds are required */
++#ifdef CONFIG_BCM4710
++ if (current_cpu_data.cputype == CPU_BCM4710 && (current_cpu_data.processor_id & 0xff) == 0) {
++ printk("Enabling BCM4710A0 cache workarounds.\n");
++ bcm4710 = 1;
++ } else
++#endif
++ bcm4710 = 0;
+
+ probe_pcache();
+ setup_scache();
+diff -Nur linux-2.6.17/arch/mips/mm/tlbex.c linux-2.6.17-owrt/arch/mips/mm/tlbex.c
+--- linux-2.6.17/arch/mips/mm/tlbex.c 2006-06-18 15:34:19.000000000 +0200
++++ linux-2.6.17-owrt/arch/mips/mm/tlbex.c 2006-06-18 15:36:58.000000000 +0200
+@@ -38,6 +38,10 @@
+
+ /* #define DEBUG_TLB */
+
++#ifdef CONFIG_BCM4710
++extern int bcm4710;
++#endif
++
+ static __init int __attribute__((unused)) r45k_bvahwbug(void)
+ {
+ /* XXX: We should probe for the presence of this bug, but we don't. */
+@@ -1184,6 +1188,12 @@
+ memset(relocs, 0, sizeof(relocs));
+ memset(final_handler, 0, sizeof(final_handler));
+
++#ifdef CONFIG_BCM4710
++ if (bcm4710) {
++ i_nop(&p);
++ }
++#endif
++
+ /*
+ * create the plain linear handler
+ */
+diff -Nur linux-2.6.17/include/asm-mips/r4kcache.h linux-2.6.17-owrt/include/asm-mips/r4kcache.h
+--- linux-2.6.17/include/asm-mips/r4kcache.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/asm-mips/r4kcache.h 2006-06-18 15:56:57.000000000 +0200
+@@ -17,6 +17,18 @@
+ #include <asm/cpu-features.h>
+ #include <asm/mipsmtregs.h>
+
++#ifdef CONFIG_BCM4710
++#define BCM4710_DUMMY_RREG() (((sbconfig_t *)(KSEG1ADDR(SB_ENUM_BASE + SBCONFIGOFF)))->sbimstate)
++
++#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr))
++#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); })
++#else
++#define BCM4710_DUMMY_RREG()
++
++#define BCM4710_FILL_TLB(addr)
++#define BCM4710_PROTECTED_FILL_TLB(addr)
++#endif
++
+ /*
+ * This macro return a properly sign-extended address suitable as base address
+ * for indexed cache operations. Two issues here:
+@@ -150,6 +162,7 @@
+ static inline void flush_dcache_line_indexed(unsigned long addr)
+ {
+ __dflush_prologue
++ BCM4710_DUMMY_RREG();
+ cache_op(Index_Writeback_Inv_D, addr);
+ __dflush_epilogue
+ }
+@@ -169,6 +182,7 @@
+ static inline void flush_dcache_line(unsigned long addr)
+ {
+ __dflush_prologue
++ BCM4710_DUMMY_RREG();
+ cache_op(Hit_Writeback_Inv_D, addr);
+ __dflush_epilogue
+ }
+@@ -176,6 +190,7 @@
+ static inline void invalidate_dcache_line(unsigned long addr)
+ {
+ __dflush_prologue
++ BCM4710_DUMMY_RREG();
+ cache_op(Hit_Invalidate_D, addr);
+ __dflush_epilogue
+ }
+@@ -208,6 +223,7 @@
+ */
+ static inline void protected_flush_icache_line(unsigned long addr)
+ {
++ BCM4710_DUMMY_RREG();
+ protected_cache_op(Hit_Invalidate_I, addr);
+ }
+
+@@ -219,6 +235,7 @@
+ */
+ static inline void protected_writeback_dcache_line(unsigned long addr)
+ {
++ BCM4710_DUMMY_RREG();
+ protected_cache_op(Hit_Writeback_Inv_D, addr);
+ }
+
+@@ -339,8 +356,52 @@
+ : "r" (base), \
+ "i" (op));
+
++static inline void blast_dcache(void)
++{
++ unsigned long start = KSEG0;
++ unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways;
++ unsigned long end = (start + dcache_size);
++
++ do {
++ BCM4710_DUMMY_RREG();
++ cache_op(Index_Writeback_Inv_D, start);
++ start += current_cpu_data.dcache.linesz;
++ } while(start < end);
++}
++
++static inline void blast_dcache_page(unsigned long page)
++{
++ unsigned long start = page;
++ unsigned long end = start + PAGE_SIZE;
++
++ BCM4710_FILL_TLB(start);
++ do {
++ BCM4710_DUMMY_RREG();
++ cache_op(Hit_Writeback_Inv_D, start);
++ start += current_cpu_data.dcache.linesz;
++ } while(start < end);
++}
++
++static inline void blast_dcache_page_indexed(unsigned long page)
++{
++ unsigned long start = page;
++ unsigned long end = start + PAGE_SIZE;
++ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
++ unsigned long ws_end = current_cpu_data.dcache.ways <<
++ current_cpu_data.dcache.waybit;
++ unsigned long ws, addr;
++ for (ws = 0; ws < ws_end; ws += ws_inc) {
++ start = page + ws;
++ for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
++ BCM4710_DUMMY_RREG();
++ cache_op(Index_Writeback_Inv_D, addr);
++ }
++ }
++}
++
++
+ /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
+-#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \
++#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, war) \
+ static inline void blast_##pfx##cache##lsize(void) \
+ { \
+ unsigned long start = INDEX_BASE; \
+@@ -352,6 +413,7 @@
+ \
+ __##pfx##flush_prologue \
+ \
++ war \
+ for (ws = 0; ws < ws_end; ws += ws_inc) \
+ for (addr = start; addr < end; addr += lsize * 32) \
+ cache##lsize##_unroll32(addr|ws,indexop); \
+@@ -366,6 +428,7 @@
+ \
+ __##pfx##flush_prologue \
+ \
++ war \
+ do { \
+ cache##lsize##_unroll32(start,hitop); \
+ start += lsize * 32; \
+@@ -384,6 +447,8 @@
+ current_cpu_data.desc.waybit; \
+ unsigned long ws, addr; \
+ \
++ war \
++ \
+ __##pfx##flush_prologue \
+ \
+ for (ws = 0; ws < ws_end; ws += ws_inc) \
+@@ -393,24 +458,25 @@
+ __##pfx##flush_epilogue \
+ }
+
+-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
+-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
+-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
+-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
+-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
+-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
+-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
+-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
+-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
++__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
++__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, BCM4710_FILL_TLB(start);)
++__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
++__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
++__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, BCM4710_FILL_TLB(start);)
++__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
++__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, BCM4710_FILL_TLB(start);)
++__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
++__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
+
+ /* build blast_xxx_range, protected_blast_xxx_range */
+-#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
++#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, war) \
+ static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
+ unsigned long end) \
+ { \
+ unsigned long lsize = cpu_##desc##_line_size(); \
+ unsigned long addr = start & ~(lsize - 1); \
+ unsigned long aend = (end - 1) & ~(lsize - 1); \
++ war \
+ \
+ __##pfx##flush_prologue \
+ \
+@@ -424,13 +490,13 @@
+ __##pfx##flush_epilogue \
+ }
+
+-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
+-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
+-__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
+-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
+-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
++__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);)
++__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, )
++__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, )
++__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);)
++__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , )
+ /* blast_inv_dcache_range */
+-__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )
+-__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, )
++__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , )
++__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , )
+
+ #endif /* _ASM_R4KCACHE_H */
+diff -Nur linux-2.6.17/include/asm-mips/stackframe.h linux-2.6.17-owrt/include/asm-mips/stackframe.h
+--- linux-2.6.17/include/asm-mips/stackframe.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/asm-mips/stackframe.h 2006-06-18 15:36:58.000000000 +0200
+@@ -361,6 +361,10 @@
+ .macro RESTORE_SP_AND_RET
+ LONG_L sp, PT_R29(sp)
+ .set mips3
++#ifdef CONFIG_BCM4710
++ nop
++ nop
++#endif
+ eret
+ .set mips0
+ .endm
diff --git a/target/linux/brcm-2.6/patches/004-b44_bcm47xx_support.patch b/target/linux/brcm-2.6/patches/004-b44_bcm47xx_support.patch
new file mode 100644
index 0000000000..15e4297a81
--- /dev/null
+++ b/target/linux/brcm-2.6/patches/004-b44_bcm47xx_support.patch
@@ -0,0 +1,699 @@
+diff -Nur linux-2.6.17/drivers/net/b44.c linux-2.6.17-owrt/drivers/net/b44.c
+--- linux-2.6.17/drivers/net/b44.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/drivers/net/b44.c 2006-06-18 16:24:14.000000000 +0200
+@@ -1,7 +1,9 @@
+-/* b44.c: Broadcom 4400 device driver.
++/* b44.c: Broadcom 4400/47xx device driver.
+ *
+ * Copyright (C) 2002 David S. Miller (davem@redhat.com)
+- * Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
++ * Copyright (C) 2004 Pekka Pietikainen (pp@ee.oulu.fi)
++ * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
++ * Copyright (C) 2006 Felix Fietkau (nbd@openwrt.org)
+ * Copyright (C) 2006 Broadcom Corporation.
+ *
+ * Distribute under GPL.
+@@ -32,6 +34,28 @@
+ #define DRV_MODULE_VERSION "1.00"
+ #define DRV_MODULE_RELDATE "Apr 7, 2006"
+
++#ifdef CONFIG_BCM947XX
++extern char *nvram_get(char *name);
++static inline void e_aton(char *str, char *dest)
++{
++ int i = 0;
++
++ if (str == NULL) {
++ memset(dest, 0, 6);
++ return;
++ }
++
++ for (;;) {
++ dest[i++] = (char) simple_strtoul(str, NULL, 16);
++ str += 2;
++ if (!*str++ || i == 6)
++ break;
++ }
++}
++
++static int b44_4713_instance;
++#endif
++
+ #define B44_DEF_MSG_ENABLE \
+ (NETIF_MSG_DRV | \
+ NETIF_MSG_PROBE | \
+@@ -78,8 +102,8 @@
+ static char version[] __devinitdata =
+ DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+
+-MODULE_AUTHOR("Florian Schirmer, Pekka Pietikainen, David S. Miller");
+-MODULE_DESCRIPTION("Broadcom 4400 10/100 PCI ethernet driver");
++MODULE_AUTHOR("Felix Fietkau, Florian Schirmer, Pekka Pietikainen, David S. Miller");
++MODULE_DESCRIPTION("Broadcom 4400/47xx 10/100 PCI ethernet driver");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(DRV_MODULE_VERSION);
+
+@@ -94,6 +118,10 @@
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B1,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++#ifdef CONFIG_BCM947XX
++ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4713,
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++#endif
+ { } /* terminate list with empty entry */
+ };
+
+@@ -132,17 +160,6 @@
+ dma_desc_sync_size, dir);
+ }
+
+-static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
+-{
+- return readl(bp->regs + reg);
+-}
+-
+-static inline void bw32(const struct b44 *bp,
+- unsigned long reg, unsigned long val)
+-{
+- writel(val, bp->regs + reg);
+-}
+-
+ static int b44_wait_bit(struct b44 *bp, unsigned long reg,
+ u32 bit, unsigned long timeout, const int clear)
+ {
+@@ -269,6 +286,10 @@
+ break;
+ };
+ #endif
++#ifdef CONFIG_BCM947XX
++ if (bp->pdev->device == PCI_DEVICE_ID_BCM4713)
++ return b44_4713_instance++;
++#endif
+ return 0;
+ }
+
+@@ -278,6 +299,30 @@
+ == SBTMSLOW_CLOCK);
+ }
+
++#ifdef CONFIG_BCM947XX
++static inline void __b44_cam_read(struct b44 *bp, unsigned char *data, int index)
++{
++ u32 val;
++
++ bw32(bp, B44_CAM_CTRL, (CAM_CTRL_READ |
++ (index << CAM_CTRL_INDEX_SHIFT)));
++
++ b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
++
++ val = br32(bp, B44_CAM_DATA_LO);
++
++ data[2] = (val >> 24) & 0xFF;
++ data[3] = (val >> 16) & 0xFF;
++ data[4] = (val >> 8) & 0xFF;
++ data[5] = (val >> 0) & 0xFF;
++
++ val = br32(bp, B44_CAM_DATA_HI);
++
++ data[0] = (val >> 8) & 0xFF;
++ data[1] = (val >> 0) & 0xFF;
++}
++#endif
++
+ static void __b44_cam_write(struct b44 *bp, unsigned char *data, int index)
+ {
+ u32 val;
+@@ -314,14 +359,14 @@
+ bw32(bp, B44_IMASK, bp->imask);
+ }
+
+-static int b44_readphy(struct b44 *bp, int reg, u32 *val)
++static int __b44_readphy(struct b44 *bp, int phy_addr, int reg, u32 *val)
+ {
+ int err;
+
+ bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
+ bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START |
+ (MDIO_OP_READ << MDIO_DATA_OP_SHIFT) |
+- (bp->phy_addr << MDIO_DATA_PMD_SHIFT) |
++ (phy_addr << MDIO_DATA_PMD_SHIFT) |
+ (reg << MDIO_DATA_RA_SHIFT) |
+ (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT)));
+ err = b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
+@@ -330,18 +375,34 @@
+ return err;
+ }
+
+-static int b44_writephy(struct b44 *bp, int reg, u32 val)
++static int __b44_writephy(struct b44 *bp, int phy_addr, int reg, u32 val)
+ {
+ bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
+ bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START |
+ (MDIO_OP_WRITE << MDIO_DATA_OP_SHIFT) |
+- (bp->phy_addr << MDIO_DATA_PMD_SHIFT) |
++ (phy_addr << MDIO_DATA_PMD_SHIFT) |
+ (reg << MDIO_DATA_RA_SHIFT) |
+ (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT) |
+ (val & MDIO_DATA_DATA)));
+ return b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
+ }
+
++static inline int b44_readphy(struct b44 *bp, int reg, u32 *val)
++{
++ if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
++ return 0;
++
++ return __b44_readphy(bp, bp->phy_addr, reg, val);
++}
++
++static inline int b44_writephy(struct b44 *bp, int reg, u32 val)
++{
++ if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
++ return 0;
++
++ return __b44_writephy(bp, bp->phy_addr, reg, val);
++}
++
+ /* miilib interface */
+ /* FIXME FIXME: phy_id is ignored, bp->phy_addr use is unconditional
+ * due to code existing before miilib use was added to this driver.
+@@ -370,6 +431,8 @@
+ u32 val;
+ int err;
+
++ if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
++ return 0;
+ err = b44_writephy(bp, MII_BMCR, BMCR_RESET);
+ if (err)
+ return err;
+@@ -433,6 +496,22 @@
+ u32 val;
+ int err;
+
++#ifdef CONFIG_BCM947XX
++ /*
++ * workaround for bad hardware design in Linksys WAP54G v1.0
++ * see https://dev.openwrt.org/ticket/146
++ * check and reset bit "isolate"
++ */
++ if ((bp->pdev->device == PCI_DEVICE_ID_BCM4713) &&
++ (atoi(nvram_get("boardnum")) == 2) &&
++ (__b44_readphy(bp, 0, MII_BMCR, &val) == 0) &&
++ (val & BMCR_ISOLATE) &&
++ (__b44_writephy(bp, 0, MII_BMCR, val & ~BMCR_ISOLATE) != 0)) {
++ printk(KERN_WARNING PFX "PHY: cannot reset MII transceiver isolate bit.\n");
++ }
++#endif
++ if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
++ return 0;
+ if ((err = b44_readphy(bp, B44_MII_ALEDCTRL, &val)) != 0)
+ goto out;
+ if ((err = b44_writephy(bp, B44_MII_ALEDCTRL,
+@@ -528,6 +607,19 @@
+ {
+ u32 bmsr, aux;
+
++ if (bp->phy_addr == B44_PHY_ADDR_NO_PHY) {
++ bp->flags |= B44_FLAG_100_BASE_T;
++ bp->flags |= B44_FLAG_FULL_DUPLEX;
++ if (!netif_carrier_ok(bp->dev)) {
++ u32 val = br32(bp, B44_TX_CTRL);
++ val |= TX_CTRL_DUPLEX;
++ bw32(bp, B44_TX_CTRL, val);
++ netif_carrier_on(bp->dev);
++ b44_link_report(bp);
++ }
++ return;
++ }
++
+ if (!b44_readphy(bp, MII_BMSR, &bmsr) &&
+ !b44_readphy(bp, B44_MII_AUXCTRL, &aux) &&
+ (bmsr != 0xffff)) {
+@@ -1282,9 +1374,10 @@
+ bw32(bp, B44_DMARX_CTRL, 0);
+ bp->rx_prod = bp->rx_cons = 0;
+ } else {
+- ssb_pci_setup(bp, (bp->core_unit == 0 ?
+- SBINTVEC_ENET0 :
+- SBINTVEC_ENET1));
++ if (bp->pdev->device != PCI_DEVICE_ID_BCM4713)
++ ssb_pci_setup(bp, (bp->core_unit == 0 ?
++ SBINTVEC_ENET0 :
++ SBINTVEC_ENET1));
+ }
+
+ ssb_core_reset(bp);
+@@ -1292,8 +1385,14 @@
+ b44_clear_stats(bp);
+
+ /* Make PHY accessible. */
+- bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
++ if (bp->pdev->device == PCI_DEVICE_ID_BCM4713)
++ bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
++ (((100000000 + (B44_MDC_RATIO / 2)) / B44_MDC_RATIO)
++ & MDIO_CTRL_MAXF_MASK)));
++ else
++ bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
+ (0x0d & MDIO_CTRL_MAXF_MASK)));
++
+ br32(bp, B44_MDIO_CTRL);
+
+ if (!(br32(bp, B44_DEVCTRL) & DEVCTRL_IPP)) {
+@@ -1837,18 +1936,297 @@
+ .get_perm_addr = ethtool_op_get_perm_addr,
+ };
+
++static int b44_ethtool_ioctl (struct net_device *dev, void __user *useraddr)
++{
++ struct b44 *bp = dev->priv;
++ struct pci_dev *pci_dev = bp->pdev;
++ u32 ethcmd;
++
++ if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
++ return -EFAULT;
++
++ switch (ethcmd) {
++ case ETHTOOL_GDRVINFO: {
++ struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
++ strcpy (info.driver, DRV_MODULE_NAME);
++ strcpy (info.version, DRV_MODULE_VERSION);
++ memset(&info.fw_version, 0, sizeof(info.fw_version));
++ strcpy (info.bus_info, pci_name(pci_dev));
++ info.eedump_len = 0;
++ info.regdump_len = 0;
++ if (copy_to_user (useraddr, &info, sizeof (info)))
++ return -EFAULT;
++ return 0;
++ }
++
++ case ETHTOOL_GSET: {
++ struct ethtool_cmd cmd = { ETHTOOL_GSET };
++
++ if (!(bp->flags & B44_FLAG_INIT_COMPLETE))
++ return -EAGAIN;
++ cmd.supported = (SUPPORTED_Autoneg);
++ cmd.supported |= (SUPPORTED_100baseT_Half |
++ SUPPORTED_100baseT_Full |
++ SUPPORTED_10baseT_Half |
++ SUPPORTED_10baseT_Full |
++ SUPPORTED_MII);
++
++ cmd.advertising = 0;
++ if (bp->flags & B44_FLAG_ADV_10HALF)
++ cmd.advertising |= ADVERTISE_10HALF;
++ if (bp->flags & B44_FLAG_ADV_10FULL)
++ cmd.advertising |= ADVERTISE_10FULL;
++ if (bp->flags & B44_FLAG_ADV_100HALF)
++ cmd.advertising |= ADVERTISE_100HALF;
++ if (bp->flags & B44_FLAG_ADV_100FULL)
++ cmd.advertising |= ADVERTISE_100FULL;
++ cmd.advertising |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
++ cmd.speed = (bp->flags & B44_FLAG_100_BASE_T) ?
++ SPEED_100 : SPEED_10;
++ cmd.duplex = (bp->flags & B44_FLAG_FULL_DUPLEX) ?
++ DUPLEX_FULL : DUPLEX_HALF;
++ cmd.port = 0;
++ cmd.phy_address = bp->phy_addr;
++ cmd.transceiver = (bp->flags & B44_FLAG_INTERNAL_PHY) ?
++ XCVR_INTERNAL : XCVR_EXTERNAL;
++ cmd.autoneg = (bp->flags & B44_FLAG_FORCE_LINK) ?
++ AUTONEG_DISABLE : AUTONEG_ENABLE;
++ cmd.maxtxpkt = 0;
++ cmd.maxrxpkt = 0;
++ if (copy_to_user(useraddr, &cmd, sizeof(cmd)))
++ return -EFAULT;
++ return 0;
++ }
++ case ETHTOOL_SSET: {
++ struct ethtool_cmd cmd;
++
++ if (!(bp->flags & B44_FLAG_INIT_COMPLETE))
++ return -EAGAIN;
++
++ if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
++ return -EFAULT;
++
++ /* We do not support gigabit. */
++ if (cmd.autoneg == AUTONEG_ENABLE) {
++ if (cmd.advertising &
++ (ADVERTISED_1000baseT_Half |
++ ADVERTISED_1000baseT_Full))
++ return -EINVAL;
++ } else if ((cmd.speed != SPEED_100 &&
++ cmd.speed != SPEED_10) ||
++ (cmd.duplex != DUPLEX_HALF &&
++ cmd.duplex != DUPLEX_FULL)) {
++ return -EINVAL;
++ }
++
++ spin_lock_irq(&bp->lock);
++
++ if (cmd.autoneg == AUTONEG_ENABLE) {
++ bp->flags &= ~B44_FLAG_FORCE_LINK;
++ bp->flags &= ~(B44_FLAG_ADV_10HALF |
++ B44_FLAG_ADV_10FULL |
++ B44_FLAG_ADV_100HALF |
++ B44_FLAG_ADV_100FULL);
++ if (cmd.advertising & ADVERTISE_10HALF)
++ bp->flags |= B44_FLAG_ADV_10HALF;
++ if (cmd.advertising & ADVERTISE_10FULL)
++ bp->flags |= B44_FLAG_ADV_10FULL;
++ if (cmd.advertising & ADVERTISE_100HALF)
++ bp->flags |= B44_FLAG_ADV_100HALF;
++ if (cmd.advertising & ADVERTISE_100FULL)
++ bp->flags |= B44_FLAG_ADV_100FULL;
++ } else {
++ bp->flags |= B44_FLAG_FORCE_LINK;
++ if (cmd.speed == SPEED_100)
++ bp->flags |= B44_FLAG_100_BASE_T;
++ if (cmd.duplex == DUPLEX_FULL)
++ bp->flags |= B44_FLAG_FULL_DUPLEX;
++ }
++
++ b44_setup_phy(bp);
++
++ spin_unlock_irq(&bp->lock);
++
++ return 0;
++ }
++
++ case ETHTOOL_GMSGLVL: {
++ struct ethtool_value edata = { ETHTOOL_GMSGLVL };
++ edata.data = bp->msg_enable;
++ if (copy_to_user(useraddr, &edata, sizeof(edata)))
++ return -EFAULT;
++ return 0;
++ }
++ case ETHTOOL_SMSGLVL: {
++ struct ethtool_value edata;
++ if (copy_from_user(&edata, useraddr, sizeof(edata)))
++ return -EFAULT;
++ bp->msg_enable = edata.data;
++ return 0;
++ }
++ case ETHTOOL_NWAY_RST: {
++ u32 bmcr;
++ int r;
++
++ spin_lock_irq(&bp->lock);
++ b44_readphy(bp, MII_BMCR, &bmcr);
++ b44_readphy(bp, MII_BMCR, &bmcr);
++ r = -EINVAL;
++ if (bmcr & BMCR_ANENABLE) {
++ b44_writephy(bp, MII_BMCR,
++ bmcr | BMCR_ANRESTART);
++ r = 0;
++ }
++ spin_unlock_irq(&bp->lock);
++
++ return r;
++ }
++ case ETHTOOL_GLINK: {
++ struct ethtool_value edata = { ETHTOOL_GLINK };
++ edata.data = netif_carrier_ok(bp->dev) ? 1 : 0;
++ if (copy_to_user(useraddr, &edata, sizeof(edata)))
++ return -EFAULT;
++ return 0;
++ }
++ case ETHTOOL_GRINGPARAM: {
++ struct ethtool_ringparam ering = { ETHTOOL_GRINGPARAM };
++
++ ering.rx_max_pending = B44_RX_RING_SIZE - 1;
++ ering.rx_pending = bp->rx_pending;
++
++ /* XXX ethtool lacks a tx_max_pending, oops... */
++
++ if (copy_to_user(useraddr, &ering, sizeof(ering)))
++ return -EFAULT;
++ return 0;
++ }
++ case ETHTOOL_SRINGPARAM: {
++ struct ethtool_ringparam ering;
++
++ if (copy_from_user(&ering, useraddr, sizeof(ering)))
++ return -EFAULT;
++
++ if ((ering.rx_pending > B44_RX_RING_SIZE - 1) ||
++ (ering.rx_mini_pending != 0) ||
++ (ering.rx_jumbo_pending != 0) ||
++ (ering.tx_pending > B44_TX_RING_SIZE - 1))
++ return -EINVAL;
++
++ spin_lock_irq(&bp->lock);
++
++ bp->rx_pending = ering.rx_pending;
++ bp->tx_pending = ering.tx_pending;
++
++ b44_halt(bp);
++ b44_init_rings(bp);
++ b44_init_hw(bp);
++ netif_wake_queue(bp->dev);
++ spin_unlock_irq(&bp->lock);
++
++ b44_enable_ints(bp);
++
++ return 0;
++ }
++ case ETHTOOL_GPAUSEPARAM: {
++ struct ethtool_pauseparam epause = { ETHTOOL_GPAUSEPARAM };
++
++ epause.autoneg =
++ (bp->flags & B44_FLAG_PAUSE_AUTO) != 0;
++ epause.rx_pause =
++ (bp->flags & B44_FLAG_RX_PAUSE) != 0;
++ epause.tx_pause =
++ (bp->flags & B44_FLAG_TX_PAUSE) != 0;
++ if (copy_to_user(useraddr, &epause, sizeof(epause)))
++ return -EFAULT;
++ return 0;
++ }
++ case ETHTOOL_SPAUSEPARAM: {
++ struct ethtool_pauseparam epause;
++
++ if (copy_from_user(&epause, useraddr, sizeof(epause)))
++ return -EFAULT;
++
++ spin_lock_irq(&bp->lock);
++ if (epause.autoneg)
++ bp->flags |= B44_FLAG_PAUSE_AUTO;
++ else
++ bp->flags &= ~B44_FLAG_PAUSE_AUTO;
++ if (epause.rx_pause)
++ bp->flags |= B44_FLAG_RX_PAUSE;
++ else
++ bp->flags &= ~B44_FLAG_RX_PAUSE;
++ if (epause.tx_pause)
++ bp->flags |= B44_FLAG_TX_PAUSE;
++ else
++ bp->flags &= ~B44_FLAG_TX_PAUSE;
++ if (bp->flags & B44_FLAG_PAUSE_AUTO) {
++ b44_halt(bp);
++ b44_init_rings(bp);
++ b44_init_hw(bp);
++ } else {
++ __b44_set_flow_ctrl(bp, bp->flags);
++ }
++ spin_unlock_irq(&bp->lock);
++
++ b44_enable_ints(bp);
++
++ return 0;
++ }
++ };
++
++ return -EOPNOTSUPP;
++}
++
+ static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
+ struct mii_ioctl_data *data = if_mii(ifr);
+ struct b44 *bp = netdev_priv(dev);
+ int err = -EINVAL;
+
+- if (!netif_running(dev))
++ if (bp->pdev->device != PCI_DEVICE_ID_BCM4713) {
++ if (!netif_running(dev))
++ goto out;
++
++ spin_lock_irq(&bp->lock);
++ err = generic_mii_ioctl(&bp->mii_if, data, cmd, NULL);
++ spin_unlock_irq(&bp->lock);
+ goto out;
++ }
+
+- spin_lock_irq(&bp->lock);
+- err = generic_mii_ioctl(&bp->mii_if, data, cmd, NULL);
+- spin_unlock_irq(&bp->lock);
++ switch (cmd) {
++ case SIOCETHTOOL:
++ return b44_ethtool_ioctl(dev, (void __user*) ifr->ifr_data);
++
++ case SIOCGMIIPHY:
++ data->phy_id = bp->phy_addr;
++
++ /* fallthru */
++ case SIOCGMIIREG: {
++ u32 mii_regval;
++ spin_lock_irq(&bp->lock);
++ err = __b44_readphy(bp, data->phy_id & 0x1f, data->reg_num & 0x1f, &mii_regval);
++ spin_unlock_irq(&bp->lock);
++
++ data->val_out = mii_regval;
++
++ return err;
++ }
++
++ case SIOCSMIIREG:
++ if (!capable(CAP_NET_ADMIN))
++ return -EPERM;
++
++ spin_lock_irq(&bp->lock);
++ err = __b44_writephy(bp, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
++ spin_unlock_irq(&bp->lock);
++
++ return err;
++
++ default:
++ break;
++ };
++ return -EOPNOTSUPP;
++
+ out:
+ return err;
+ }
+@@ -1868,27 +2246,60 @@
+ static int __devinit b44_get_invariants(struct b44 *bp)
+ {
+ u8 eeprom[128];
+- int err;
++ u8 buf[32];
++ int err = 0;
++ unsigned long flags;
++
++#ifdef CONFIG_BCM947XX
++ if (bp->pdev->device == PCI_DEVICE_ID_BCM4713) {
++ /*
++ * BCM47xx boards don't have a EEPROM. The MAC is stored in
++ * a NVRAM area somewhere in the flash memory.
++ */
++ sprintf(buf, "et%dmacaddr", b44_4713_instance);
++ if (nvram_get(buf)) {
++ e_aton(nvram_get(buf), bp->dev->dev_addr);
++ } else {
++ /*
++ * Getting the MAC out of NVRAM failed. To make it work
++ * here, we simply rely on the bootloader to write the
++ * MAC into the CAM.
++ */
++ spin_lock_irqsave(&bp->lock, flags);
++ __b44_cam_read(bp, bp->dev->dev_addr, 0);
++ spin_unlock_irqrestore(&bp->lock, flags);
++ }
+
+- err = b44_read_eeprom(bp, &eeprom[0]);
+- if (err)
+- goto out;
++ /*
++ * BCM47xx boards don't have a PHY. Usually there is a switch
++ * chip with multiple PHYs connected to the PHY port.
++ */
++ bp->phy_addr = B44_PHY_ADDR_NO_PHY;
++ bp->dma_offset = 0;
++ } else
++#endif
++ {
++ err = b44_read_eeprom(bp, &eeprom[0]);
++ if (err)
++ goto out;
+
+- bp->dev->dev_addr[0] = eeprom[79];
+- bp->dev->dev_addr[1] = eeprom[78];
+- bp->dev->dev_addr[2] = eeprom[81];
+- bp->dev->dev_addr[3] = eeprom[80];
+- bp->dev->dev_addr[4] = eeprom[83];
+- bp->dev->dev_addr[5] = eeprom[82];
++ bp->dev->dev_addr[0] = eeprom[79];
++ bp->dev->dev_addr[1] = eeprom[78];
++ bp->dev->dev_addr[2] = eeprom[81];
++ bp->dev->dev_addr[3] = eeprom[80];
++ bp->dev->dev_addr[4] = eeprom[83];
++ bp->dev->dev_addr[5] = eeprom[82];
+
+- if (!is_valid_ether_addr(&bp->dev->dev_addr[0])){
+- printk(KERN_ERR PFX "Invalid MAC address found in EEPROM\n");
+- return -EINVAL;
+- }
++ if (!is_valid_ether_addr(&bp->dev->dev_addr[0])){
++ printk(KERN_ERR PFX "Invalid MAC address found in EEPROM\n");
++ return -EINVAL;
++ }
+
+- memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len);
++ memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len);
+
+- bp->phy_addr = eeprom[90] & 0x1f;
++ bp->phy_addr = eeprom[90] & 0x1f;
++ bp->dma_offset = SB_PCI_DMA;
++ }
+
+ /* With this, plus the rx_header prepended to the data by the
+ * hardware, we'll land the ethernet header on a 2-byte boundary.
+@@ -1898,7 +2309,6 @@
+ bp->imask = IMASK_DEF;
+
+ bp->core_unit = ssb_core_unit(bp);
+- bp->dma_offset = SB_PCI_DMA;
+
+ /* XXX - really required?
+ bp->flags |= B44_FLAG_BUGGY_TXPTR;
+@@ -2048,11 +2458,17 @@
+ */
+ b44_chip_reset(bp);
+
+- printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name);
++ printk(KERN_INFO "%s: Broadcom %s 10/100BaseT Ethernet ", dev->name,
++ (pdev->device == PCI_DEVICE_ID_BCM4713) ? "47xx" : "4400");
+ for (i = 0; i < 6; i++)
+ printk("%2.2x%c", dev->dev_addr[i],
+ i == 5 ? '\n' : ':');
+
++ /* Initialize phy */
++ spin_lock_irq(&bp->lock);
++ b44_chip_reset(bp);
++ spin_unlock_irq(&bp->lock);
++
+ return 0;
+
+ err_out_iounmap:
+diff -Nur linux-2.6.17/drivers/net/b44.h linux-2.6.17-owrt/drivers/net/b44.h
+--- linux-2.6.17/drivers/net/b44.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/drivers/net/b44.h 2006-06-18 16:01:10.000000000 +0200
+@@ -292,6 +292,10 @@
+ #define SSB_PCI_MASK1 0xfc000000
+ #define SSB_PCI_MASK2 0xc0000000
+
++#define br32(bp, REG) readl((void *)bp->regs + (REG))
++#define bw32(bp, REG,VAL) writel((VAL), (void *)bp->regs + (REG))
++#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0)
++
+ /* 4400 PHY registers */
+ #define B44_MII_AUXCTRL 24 /* Auxiliary Control */
+ #define MII_AUXCTRL_DUPLEX 0x0001 /* Full Duplex */
+@@ -345,6 +349,8 @@
+ };
+
+ #define B44_MCAST_TABLE_SIZE 32
++#define B44_PHY_ADDR_NO_PHY 30
++#define B44_MDC_RATIO 5000000
+
+ #define B44_STAT_REG_DECLARE \
+ _B44(tx_good_octets) \
+@@ -420,6 +426,7 @@
+
+ u32 dma_offset;
+ u32 flags;
++#define B44_FLAG_INIT_COMPLETE 0x00000001
+ #define B44_FLAG_BUGGY_TXPTR 0x00000002
+ #define B44_FLAG_REORDER_BUG 0x00000004
+ #define B44_FLAG_PAUSE_AUTO 0x00008000
diff --git a/target/linux/brcm-2.6/patches/010-bcm47xx-cam_absent.patch b/target/linux/brcm-2.6/patches/010-bcm47xx-cam_absent.patch
new file mode 100644
index 0000000000..51206296bc
--- /dev/null
+++ b/target/linux/brcm-2.6/patches/010-bcm47xx-cam_absent.patch
@@ -0,0 +1,42 @@
+--- linux-2.6.17.orig/drivers/net/b44.h 2006-09-19 19:56:03.000000000 +0200
++++ linux-2.6.17/drivers/net/b44.h 2006-09-19 19:58:01.000000000 +0200
+@@ -122,6 +122,7 @@
+ #define RXCONFIG_FLOW 0x00000020 /* Flow Control Enable */
+ #define RXCONFIG_FLOW_ACCEPT 0x00000040 /* Accept Unicast Flow Control Frame */
+ #define RXCONFIG_RFILT 0x00000080 /* Reject Filter */
++#define RXCONFIG_CAM_ABSENT 0x00000100 /* CAM Absent */
+ #define B44_RXMAXLEN 0x0404UL /* EMAC RX Max Packet Length */
+ #define B44_TXMAXLEN 0x0408UL /* EMAC TX Max Packet Length */
+ #define B44_MDIO_CTRL 0x0410UL /* EMAC MDIO Control */
+--- linux-2.6.17.orig/drivers/net/b44.c 2006-09-19 19:56:03.000000000 +0200
++++ linux-2.6.17/drivers/net/b44.c 2006-09-19 20:08:22.000000000 +0200
+@@ -1435,6 +1435,7 @@
+ {
+ struct b44 *bp = netdev_priv(dev);
+ struct sockaddr *addr = p;
++ u32 val;
+
+ if (netif_running(dev))
+ return -EBUSY;
+@@ -1445,7 +1446,11 @@
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ spin_lock_irq(&bp->lock);
+- __b44_set_mac_addr(bp);
++
++ val = br32(bp, B44_RXCONFIG);
++ if (!(val & RXCONFIG_CAM_ABSENT))
++ __b44_set_mac_addr(bp);
++
+ spin_unlock_irq(&bp->lock);
+
+ return 0;
+@@ -1641,7 +1646,7 @@
+
+ val = br32(bp, B44_RXCONFIG);
+ val &= ~(RXCONFIG_PROMISC | RXCONFIG_ALLMULTI);
+- if (dev->flags & IFF_PROMISC) {
++ if ((dev->flags & IFF_PROMISC) || (val & RXCONFIG_CAM_ABSENT)) {
+ val |= RXCONFIG_PROMISC;
+ bw32(bp, B44_RXCONFIG, val);
+ } else {
diff --git a/target/linux/brcm63xx-2.6/Makefile b/target/linux/brcm63xx-2.6/Makefile
new file mode 100644
index 0000000000..0437338e8e
--- /dev/null
+++ b/target/linux/brcm63xx-2.6/Makefile
@@ -0,0 +1,23 @@
+#
+# 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
+
+LINUX_VERSION:=2.6.17
+LINUX_RELEASE:=1
+LINUX_KERNEL_MD5SUM:=37ddefe96625502161f075b9d907f21e
+
+include ./config
+include $(INCLUDE_DIR)/kernel.mk
+include $(INCLUDE_DIR)/kernel-build.mk
+
+
+$(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked
+ [ -d ../generic-$(KERNEL)/patches ] && $(PATCH) $(LINUX_DIR) ../generic-$(KERNEL)/patches $(MAKE_TRACE)
+ [ -d ./patches ] && $(PATCH) $(LINUX_DIR) ./patches $(MAKE_TRACE)
+ @$(CP) config $(LINUX_DIR)/.config
+ touch $@
+
diff --git a/target/linux/brcm63xx-2.6/config b/target/linux/brcm63xx-2.6/config
new file mode 100644
index 0000000000..ac286dfb90
--- /dev/null
+++ b/target/linux/brcm63xx-2.6/config
@@ -0,0 +1,1629 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Thu Sep 21 15:05:29 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+CONFIG_MIPS_BRCM=y
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_BCM96338 is not set
+# CONFIG_BCM96345 is not set
+CONFIG_BCM96348=y
+# CONFIG_BCM_BOARD is not set
+CONFIG_BCM_SERIAL=y
+# CONFIG_BCM_ENET is not set
+# CONFIG_BCM_USB is not set
+# CONFIG_BCM_WLAN is not set
+CONFIG_BCM_PCI=y
+# CONFIG_BCM_ATMAPI is not set
+# CONFIG_BCM_ATMTEST is not set
+# CONFIG_BCM_ADSL is not set
+# CONFIG_BCM_ENDPOINT is not set
+CONFIG_BCM_PROCFS=y
+# CONFIG_BCM_VDSL is not set
+# CONFIG_BCM_SECURITY is not set
+# CONFIG_BCM_HPNA is not set
+CONFIG_BCM_BOARD_IMPL=1
+CONFIG_BCM_SERIAL_IMPL=1
+CONFIG_BCM_ENET_IMPL=1
+CONFIG_BCM_USB_IMPL=1
+CONFIG_BCM_WLAN_IMPL=1
+CONFIG_BCM_ATMAPI_IMPL=1
+CONFIG_BCM_ATMTEST_IMPL=1
+CONFIG_BCM_BLAA_IMPL=1
+CONFIG_BCM_ADSL_IMPL=1
+CONFIG_BCM_ENDPOINT_IMPL=1
+CONFIG_BCM_PROCFS_IMPL=1
+CONFIG_BCM_VDSL_IMPL=1
+CONFIG_BCM_SECURITY_IMPL=1
+CONFIG_BCM_HPNA_IMPL=0
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DEBUG=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+# CONFIG_IP_ROUTE_FWMARK is not set
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_MULTIPATH_CACHED=y
+CONFIG_IP_ROUTE_MULTIPATH_RR=m
+CONFIG_IP_ROUTE_MULTIPATH_RANDOM=m
+CONFIG_IP_ROUTE_MULTIPATH_WRANDOM=m
+CONFIG_IP_ROUTE_MULTIPATH_DRR=m
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IPSEC_NAT_TRAVERSAL=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+CONFIG_IP_NF_CT_ACCT=y
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=y
+CONFIG_IP_NF_IRC=y
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=y
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_IPP2P=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TIME=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
+CONFIG_IP_NF_MATCH_LAYER7=m
+# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_IMQ=m
+# CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_TARGET_ROUTE=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_SAME is not set
+# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+CONFIG_IP_NF_NAT_IRC=y
+CONFIG_IP_NF_NAT_FTP=y
+CONFIG_IP_NF_NAT_TFTP=y
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_IP_NF_SET=m
+CONFIG_IP_NF_SET_MAX=256
+CONFIG_IP_NF_SET_HASHSIZE=1024
+CONFIG_IP_NF_SET_IPMAP=m
+CONFIG_IP_NF_SET_MACIPMAP=m
+CONFIG_IP_NF_SET_PORTMAP=m
+CONFIG_IP_NF_SET_IPHASH=m
+CONFIG_IP_NF_SET_NETHASH=m
+CONFIG_IP_NF_SET_IPTREE=m
+CONFIG_IP_NF_MATCH_SET=m
+CONFIG_IP_NF_TARGET_SET=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+# CONFIG_IP6_NF_MATCH_RT is not set
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+CONFIG_IP6_NF_MATCH_OWNER=m
+# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_IMQ=m
+# CONFIG_IP6_NF_TARGET_LOG is not set
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_ROUTE=m
+CONFIG_IP6_NF_MANGLE=m
+# CONFIG_IP6_NF_TARGET_HL is not set
+# CONFIG_IP6_NF_RAW is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+CONFIG_ATM_CLIP_NO_ICMP=y
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+CONFIG_ATM_BR2684_IPFILTER=y
+CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_ESFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+# CONFIG_NET_ACT_IPT is not set
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+# CONFIG_IEEE80211_CRYPT_TKIP is not set
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+CONFIG_MTD_DEBUG=y
+CONFIG_MTD_DEBUG_VERBOSE=3
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+CONFIG_MTD_OBSOLETE_CHIPS=y
+# CONFIG_MTD_SHARP is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xBFC00000
+CONFIG_MTD_PHYSMAP_LEN=0x400000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_BCM963XX is not set
+# CONFIG_MTD_CSTM_MIPS_IXX is not set
+# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_IMQ=m
+# CONFIG_IMQ_BEHAVIOR_AA is not set
+# CONFIG_IMQ_BEHAVIOR_AB is not set
+CONFIG_IMQ_BEHAVIOR_BA=y
+# CONFIG_IMQ_BEHAVIOR_BB is not set
+CONFIG_IMQ_NUM_DEVS=2
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+CONFIG_IPW2100_DEBUG=y
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW_QOS=y
+CONFIG_IPW2200_DEBUG=y
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_BCM43XX=m
+CONFIG_BCM43XX_DEBUG=y
+CONFIG_BCM43XX_DMA=y
+CONFIG_BCM43XX_PIO=y
+CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
+# CONFIG_BCM43XX_DMA_MODE is not set
+# CONFIG_BCM43XX_PIO_MODE is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+CONFIG_ATM_DUMMY=m
+CONFIG_ATM_TCP=m
+# CONFIG_ATM_LANAI is not set
+# CONFIG_ATM_ENI is not set
+# CONFIG_ATM_FIRESTREAM is not set
+# CONFIG_ATM_ZATM is not set
+# CONFIG_ATM_NICSTAR is not set
+# CONFIG_ATM_IDT77252 is not set
+# CONFIG_ATM_AMBASSADOR is not set
+# CONFIG_ATM_HORIZON is not set
+# CONFIG_ATM_IA is not set
+# CONFIG_ATM_FORE200E_MAYBE is not set
+# CONFIG_ATM_HE is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+CONFIG_SHAPER=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=m
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=m
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=m
+CONFIG_SERIO_I8042=m
+CONFIG_SERIO_SERPORT=m
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=m
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+CONFIG_USB_SERIAL_BELKIN=m
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+CONFIG_USB_SERIAL_VISOR=m
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+# CONFIG_USB_CXACRU is not set
+CONFIG_USB_UEAGLEATM=m
+# CONFIG_USB_XUSBATM is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+CONFIG_DEVFS_DEBUG=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_EMBEDDED=y
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_SQUASHFS_VMALLOC=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=m
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_KGDB is not set
+# CONFIG_RUNTIME_DEBUG is not set
+# CONFIG_MIPS_UNCACHED is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
diff --git a/target/linux/brcm63xx-2.6/patches/001-bcm963xx.patch b/target/linux/brcm63xx-2.6/patches/001-bcm963xx.patch
new file mode 100644
index 0000000000..c079c5a4bf
--- /dev/null
+++ b/target/linux/brcm63xx-2.6/patches/001-bcm963xx.patch
@@ -0,0 +1,9656 @@
+diff -urN linux.old/arch/mips/bcm963xx/bcm63xx_led.c linux.dev/arch/mips/bcm963xx/bcm63xx_led.c
+--- linux.old/arch/mips/bcm963xx/bcm63xx_led.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/bcm63xx_led.c 2006-08-25 00:39:38.000000000 +0200
+@@ -0,0 +1,582 @@
++/*
++<:copyright-gpl
++ Copyright 2002 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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.
++:>
++*/
++/***************************************************************************
++ * File Name : bcm63xx_led.c
++ *
++ * Description:
++ *
++ * This file contains bcm963xx board led control API functions.
++ *
++ * To use it, do the following
++ *
++ * 1). define in the board.c the following led mappping (this is for 6345GW board):
++ * const LED_MAP_PAIR cLedMapping45GW[] =
++ * { // led name Initial state physical pin (ledMask)
++ * {kLedUsb, kLedStateOff, GPIO_LED_PIN_7},
++ * {kLedAdsl, kLedStateOff, GPIO_LED_PIN_8},
++ * {kLedPPP, kLedStateOff, GPIO_LED_PIN_9}, // PPP and WanData share PIN_9
++ * {kLedWanData, kLedStateOff, GPIO_LED_PIN_9},
++ * {kLedWireless, kLedStateOff, GPIO_LED_PIN_10},
++ * {kLedEnd, kLedStateOff, 0 } // NOTE: kLedEnd has to be at the end.
++ *
++ * 2). };To initialize led API and initial state of the leds, call the following function with the mapping
++ * pointer from the above struct
++ *
++ * boardLedInit((PLED_MAP_PAIR) &cLedMapping45R);
++ *
++ * 3). Sample call for kernel mode:
++ *
++ * kerSysLedCtrl(kLedAdsl, kLedStateBlinkOnce); // kLedxxx defines in board.h
++ *
++ * 4). Sample call for user mode
++ *
++ * sysLedCtrl(kLedAdsl, kLedStateBlinkOnce); // kLedxxx defines in board_api.h
++ *
++ *
++ * Created on : 10/28/2002 seanl
++ *
++ ***************************************************************************/
++
++/* Includes. */
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/capability.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/module.h>
++#include <linux/netdevice.h>
++#include <asm/uaccess.h>
++
++#include <bcm_map_part.h>
++#include <board.h>
++
++#define k100ms (HZ / 10) // ~100 ms
++#define kFastBlinkCount 0 // ~100ms
++#define kSlowBlinkCount 5 // ~600ms
++
++#define MAX_VIRT_LEDS 12
++
++// uncomment // for debug led
++//#define DEBUG_LED
++
++// global variables:
++struct timer_list gLedTimer;
++int gTimerOn = FALSE;
++int gLedCount = 0;
++
++typedef struct ledinfo
++{
++ unsigned short ledMask; // mask for led: ie. giop 10 = 0x0400
++ unsigned short ledActiveLow; // GPIO bit reset to turn on LED
++ unsigned short ledMaskFail; // mask for led: ie. giop 10 = 0x0400
++ unsigned short ledActiveLowFail;// GPIO bit reset to turn on LED
++ BOARD_LED_STATE ledState; // current led state
++ BOARD_LED_STATE savedLedState; // used in blink once for restore to the orignal ledState
++ int blinkCountDown; // if == 0, do blink (toggle). Is assgined value and dec by 1 at each timer.
++} LED_INFO, *PLED_INFO;
++
++static PLED_INFO gLed = NULL;
++static PLED_INFO gpVirtLeds[MAX_VIRT_LEDS];
++static HANDLE_LED_FUNC gLedHwFunc[MAX_VIRT_LEDS];
++static HANDLE_LED_FUNC gLedHwFailFunc[MAX_VIRT_LEDS];
++
++#if 0 /* BROKEN */
++#if defined(CONFIG_BCM96348) || defined(CONFIG_BCM96338)
++static int gLedOffInBridgeMode = 1;
++#elif defined(CONFIG_BCM96345)
++static int gLedOffInBridgeMode = 0;
++#endif
++#endif
++
++void ledTimerExpire(void);
++int initLedInfo( PLED_MAP_PAIR pCurMap, PLED_INFO pCurLed );
++
++//**************************************************************************************
++// LED operations
++//**************************************************************************************
++
++// turn led on and set the ledState
++void ledOn(PLED_INFO pLed)
++{
++ if( pLed->ledMask )
++ {
++ GPIO->GPIODir |= pLed->ledMask; // turn on the direction bit in case was turned off by some one
++ if( pLed->ledActiveLow )
++ GPIO->GPIOio &= ~pLed->ledMask; // turn on the led
++ else
++ GPIO->GPIOio |= pLed->ledMask; // turn on the led
++ pLed->ledState = pLed->savedLedState = kLedStateOn;
++ }
++}
++
++
++// turn led off and set the ledState
++void ledOff(PLED_INFO pLed)
++{
++ if( pLed->ledMask )
++ {
++ GPIO->GPIODir |= pLed->ledMask; // turn on the direction bit in case was turned off by some one
++ if( pLed->ledActiveLow )
++ GPIO->GPIOio |= pLed->ledMask; // turn off the led
++ else
++ GPIO->GPIOio &= ~pLed->ledMask; // turn off the led
++ pLed->ledState = pLed->savedLedState = kLedStateOff;
++ }
++}
++
++// turn led on and set the ledState
++void ledOnFail(PLED_INFO pLed)
++{
++ if( pLed->ledMaskFail )
++ {
++ GPIO->GPIODir |= pLed->ledMaskFail; // turn on the direction bit in case was turned off by some one
++ if( pLed->ledActiveLowFail )
++ GPIO->GPIOio &= ~pLed->ledMaskFail;// turn on the led
++ else
++ GPIO->GPIOio |= pLed->ledMaskFail; // turn on the led
++ pLed->ledState = pLed->savedLedState = kLedStateFail;
++ }
++}
++
++
++// turn led off and set the ledState
++void ledOffFail(PLED_INFO pLed)
++{
++ if( pLed->ledMaskFail )
++ {
++ GPIO->GPIODir |= pLed->ledMaskFail; // turn on the direction bit in case was turned off by some one
++ if( pLed->ledActiveLowFail )
++ GPIO->GPIOio |= pLed->ledMaskFail; // turn off the led
++ else
++ GPIO->GPIOio &= ~pLed->ledMaskFail;// turn off the led
++ pLed->ledState = pLed->savedLedState = kLedStateOff;
++ }
++}
++
++
++// toggle the led and return the current ledState
++BOARD_LED_STATE ledToggle(PLED_INFO pLed)
++{
++ GPIO->GPIODir |= pLed->ledMask; // turn on the direction bit in case was turned off by some one
++ if (GPIO->GPIOio & pLed->ledMask)
++ {
++ GPIO->GPIOio &= ~(pLed->ledMask);
++ return( (pLed->ledActiveLow) ? kLedStateOn : kLedStateOff );
++ }
++ else
++ {
++ GPIO->GPIOio |= pLed->ledMask;
++ return( (pLed->ledActiveLow) ? kLedStateOff : kLedStateOn );
++ }
++}
++
++
++// led timer. Will return if timer is already on
++void ledTimerStart(void)
++{
++ if (gTimerOn)
++ return;
++
++#if defined(DEBUG_LED)
++ printk("led: add_timer\n");
++#endif
++
++ init_timer(&gLedTimer);
++ gLedTimer.function = (void*)ledTimerExpire;
++ gLedTimer.expires = jiffies + k100ms; // timer expires in ~100ms
++ add_timer (&gLedTimer);
++ gTimerOn = TRUE;
++}
++
++
++// led timer expire kicks in about ~100ms and perform the led operation according to the ledState and
++// restart the timer according to ledState
++void ledTimerExpire(void)
++{
++ int i;
++ PLED_INFO pCurLed;
++
++ gTimerOn = FALSE;
++
++ for (i = 0, pCurLed = gLed; i < gLedCount; i++, pCurLed++)
++ {
++#if defined(DEBUG_LED)
++ printk("led[%d]: Mask=0x%04x, State = %d, blcd=%d\n", i, pCurLed->ledMask, pCurLed->ledState, pCurLed->blinkCountDown);
++#endif
++ switch (pCurLed->ledState)
++ {
++ case kLedStateOn:
++ case kLedStateOff:
++ case kLedStateFail:
++ pCurLed->blinkCountDown = 0; // reset the blink count down
++ break;
++
++ case kLedStateBlinkOnce:
++ ledToggle(pCurLed);
++ pCurLed->blinkCountDown = 0; // reset to 0
++ pCurLed->ledState = pCurLed->savedLedState;
++ if (pCurLed->ledState == kLedStateSlowBlinkContinues ||
++ pCurLed->ledState == kLedStateFastBlinkContinues)
++ ledTimerStart(); // start timer if in blinkContinues stats
++ break;
++
++ case kLedStateSlowBlinkContinues:
++ if (pCurLed->blinkCountDown-- == 0)
++ {
++ pCurLed->blinkCountDown = kSlowBlinkCount;
++ ledToggle(pCurLed);
++ }
++ ledTimerStart();
++ break;
++
++ case kLedStateFastBlinkContinues:
++ if (pCurLed->blinkCountDown-- == 0)
++ {
++ pCurLed->blinkCountDown = kFastBlinkCount;
++ ledToggle(pCurLed);
++ }
++ ledTimerStart();
++ break;
++
++ default:
++ printk("Invalid state = %d\n", pCurLed->ledState);
++ }
++ }
++}
++
++// initialize the gLedCount and allocate and fill gLed struct
++void __init boardLedInit(PLED_MAP_PAIR cLedMapping)
++{
++ PLED_MAP_PAIR p1, p2;
++ PLED_INFO pCurLed;
++ int needTimer = FALSE;
++ int alreadyUsed = 0;
++
++#if defined(CONFIG_BCM96348) || defined(CONFIG_BCM96338)
++ /* Set blink rate for BCM6348/BCM6338 hardware LEDs. */
++ GPIO->LEDCtrl &= ~LED_INTERVAL_SET_MASK;
++ GPIO->LEDCtrl |= LED_INTERVAL_SET_80MS;
++#endif
++
++ memset( gpVirtLeds, 0x00, sizeof(gpVirtLeds) );
++ memset( gLedHwFunc, 0x00, sizeof(gLedHwFunc) );
++ memset( gLedHwFailFunc, 0x00, sizeof(gLedHwFailFunc) );
++
++ gLedCount = 0;
++
++ // Check for multiple LED names and multiple LED GPIO pins that share the
++ // same physical board LED.
++ for( p1 = cLedMapping; p1->ledName != kLedEnd; p1++ )
++ {
++ alreadyUsed = 0;
++ for( p2 = cLedMapping; p2 != p1; p2++ )
++ {
++ if( (p1->ledMask && p1->ledMask == p2->ledMask) ||
++ (p1->ledMaskFail && p1->ledMaskFail == p2->ledMaskFail) )
++ {
++ alreadyUsed = 1;
++ break;
++ }
++ }
++
++ if( alreadyUsed == 0 )
++ gLedCount++;
++ }
++
++ gLed = (PLED_INFO) kmalloc((gLedCount * sizeof(LED_INFO)), GFP_KERNEL);
++ if( gLed == NULL )
++ {
++ printk( "LED memory allocation error.\n" );
++ return;
++ }
++
++ memset( gLed, 0x00, gLedCount * sizeof(LED_INFO) );
++
++ // initial the gLed with unique ledMask and initial state. If more than 1 ledNames share the physical led
++ // (ledMask) the first defined led's ledInitState will be used.
++ pCurLed = gLed;
++ for( p1 = cLedMapping; p1->ledName != kLedEnd; p1++ )
++ {
++ if( (int) p1->ledName > MAX_VIRT_LEDS )
++ continue;
++
++ alreadyUsed = 0;
++ for( p2 = cLedMapping; p2 != p1; p2++ )
++ {
++ if( (p1->ledMask && p1->ledMask == p2->ledMask) ||
++ (p1->ledMaskFail && p1->ledMaskFail == p2->ledMaskFail) )
++ {
++ alreadyUsed = 1;
++ break;
++ }
++ }
++
++ if( alreadyUsed == 0 )
++ {
++ // Initialize the board LED for the first time.
++ needTimer = initLedInfo( p1, pCurLed );
++ gpVirtLeds[(int) p1->ledName] = pCurLed;
++ pCurLed++;
++ }
++ else
++ {
++ PLED_INFO pLed;
++ for( pLed = gLed; pLed != pCurLed; pLed++ )
++ {
++ // Find the LED_INFO structure that has already been initialized.
++ if((pLed->ledMask && pLed->ledMask == p1->ledMask) ||
++ (pLed->ledMaskFail && pLed->ledMaskFail==p1->ledMaskFail))
++ {
++ // The board LED has already been initialized but possibly
++ // not completely initialized.
++ if( p1->ledMask )
++ {
++ pLed->ledMask = p1->ledMask;
++ pLed->ledActiveLow = p1->ledActiveLow;
++ }
++ if( p1->ledMaskFail )
++ {
++ pLed->ledMaskFail = p1->ledMaskFail;
++ pLed->ledActiveLowFail = p1->ledActiveLowFail;
++ }
++ gpVirtLeds[(int) p1->ledName] = pLed;
++ break;
++ }
++ }
++ }
++ }
++
++ if (needTimer)
++ ledTimerStart();
++
++#if defined(DEBUG_LED)
++ int i;
++ for (i=0; i < gLedCount; i++)
++ printk("initLed: led[%d]: mask=0x%04x, state=%d\n", i,(gLed+i)->ledMask, (gLed+i)->ledState);
++#endif
++
++}
++
++// Initialize a structure that contains information about a physical board LED
++// control. The board LED may contain more than one GPIO pin to control a
++// normal condition (green) or a failure condition (red).
++int initLedInfo( PLED_MAP_PAIR pCurMap, PLED_INFO pCurLed )
++{
++ int needTimer = FALSE;
++ pCurLed->ledState = pCurLed->savedLedState = pCurMap->ledInitState;
++ pCurLed->ledMask = pCurMap->ledMask;
++ pCurLed->ledActiveLow = pCurMap->ledActiveLow;
++ pCurLed->ledMaskFail = pCurMap->ledMaskFail;
++ pCurLed->ledActiveLowFail = pCurMap->ledActiveLowFail;
++
++ switch (pCurLed->ledState)
++ {
++ case kLedStateOn:
++ pCurLed->blinkCountDown = 0; // reset the blink count down
++ ledOn(pCurLed);
++ break;
++ case kLedStateOff:
++ pCurLed->blinkCountDown = 0; // reset the blink count down
++ ledOff(pCurLed);
++ break;
++ case kLedStateFail:
++ pCurLed->blinkCountDown = 0; // reset the blink count down
++ ledOnFail(pCurLed);
++ break;
++ case kLedStateBlinkOnce:
++ pCurLed->blinkCountDown = 1;
++ needTimer = TRUE;
++ break;
++ case kLedStateSlowBlinkContinues:
++ pCurLed->blinkCountDown = kSlowBlinkCount;
++ needTimer = TRUE;
++ break;
++ case kLedStateFastBlinkContinues:
++ pCurLed->blinkCountDown = kFastBlinkCount;
++ needTimer = TRUE;
++ break;
++ default:
++ printk("Invalid state = %d\n", pCurLed->ledState);
++ }
++
++ return( needTimer );
++}
++
++#if 0 /* BROKEN */
++// Determines if there is at least one interface in bridge mode. Bridge mode
++// is determined by the cfm convention of naming bridge interfaces nas17
++// through nas24.
++static int isBridgedProtocol(void)
++{
++ extern int dev_get(const char *name);
++ const int firstBridgeId = 17;
++ const int lastBridgeId = 24;
++ int i;
++ int ret = FALSE;
++ char name[16];
++
++ for( i = firstBridgeId; i <= lastBridgeId; i++ )
++ {
++ sprintf( name, "nas%d", i );
++
++ if( dev_get(name) )
++ {
++ ret = TRUE;
++ break;
++ }
++ }
++
++ return(ret);
++}
++#endif
++
++// led ctrl. Maps the ledName to the corresponding ledInfoPtr and perform the led operation
++void boardLedCtrl(BOARD_LED_NAME ledName, BOARD_LED_STATE ledState)
++{
++ PLED_INFO ledInfoPtr;
++
++ // do the mapping from virtual to physical led
++ if( (int) ledName < MAX_VIRT_LEDS )
++ ledInfoPtr = gpVirtLeds[(int) ledName];
++ else
++ ledInfoPtr = NULL;
++
++ if (ledInfoPtr == NULL)
++ return;
++
++ if( ledState != kLedStateFail && gLedHwFunc[(int) ledName] )
++ {
++ (*gLedHwFunc[(int) ledName]) (ledName, ledState);
++ ledOffFail(ledInfoPtr);
++ return;
++ }
++ else
++ if( ledState == kLedStateFail && gLedHwFailFunc[(int) ledName] )
++ {
++ (*gLedHwFailFunc[(int) ledName]) (ledName, ledState);
++ ledOff(ledInfoPtr);
++ return;
++ }
++
++#if 0 /* BROKEN */
++ // Do not blink the WAN Data LED if at least one interface is in bridge mode.
++ if(gLedOffInBridgeMode == 1 && (ledName == kLedWanData || ledName == kLedPPP))
++ {
++ static int BridgedProtocol = -1;
++
++ if( BridgedProtocol == -1 )
++ BridgedProtocol = isBridgedProtocol();
++
++ if( BridgedProtocol == TRUE )
++ return;
++ }
++#endif
++
++ // If the state is kLedStateFail and there is not a failure LED defined
++ // in the board parameters, change the state to kLedStateFastBlinkContinues.
++ if( ledState == kLedStateFail && ledInfoPtr->ledMaskFail == 0 )
++ ledState = kLedStateFastBlinkContinues;
++
++ switch (ledState)
++ {
++ case kLedStateOn:
++ // First, turn off the complimentary (failure) LED GPIO.
++ if( ledInfoPtr->ledMaskFail )
++ ledOffFail(ledInfoPtr);
++ else
++ if( gLedHwFailFunc[(int) ledName] )
++ (*gLedHwFailFunc[(int) ledName]) (ledName, kLedStateOff);
++
++ // Next, turn on the specified LED GPIO.
++ ledOn(ledInfoPtr);
++ break;
++
++ case kLedStateOff:
++ // First, turn off the complimentary (failure) LED GPIO.
++ if( ledInfoPtr->ledMaskFail )
++ ledOffFail(ledInfoPtr);
++ else
++ if( gLedHwFailFunc[(int) ledName] )
++ (*gLedHwFailFunc[(int) ledName]) (ledName, kLedStateOff);
++
++ // Next, turn off the specified LED GPIO.
++ ledOff(ledInfoPtr);
++ break;
++
++ case kLedStateFail:
++ // First, turn off the complimentary (normal) LED GPIO.
++ if( ledInfoPtr->ledMask )
++ ledOff(ledInfoPtr);
++ else
++ if( gLedHwFunc[(int) ledName] )
++ (*gLedHwFunc[(int) ledName]) (ledName, kLedStateOff);
++
++ // Next, turn on (red) the specified LED GPIO.
++ ledOnFail(ledInfoPtr);
++ break;
++
++ case kLedStateBlinkOnce:
++ // skip blinkOnce if it is already in Slow/Fast blink continues state
++ if (ledInfoPtr->savedLedState == kLedStateSlowBlinkContinues ||
++ ledInfoPtr->savedLedState == kLedStateFastBlinkContinues)
++ ;
++ else
++ {
++ if (ledInfoPtr->blinkCountDown == 0) // skip the call if it is 1
++ {
++ ledToggle(ledInfoPtr);
++ ledInfoPtr->blinkCountDown = 1; // it will be reset to 0 when timer expires
++ ledInfoPtr->ledState = kLedStateBlinkOnce;
++ ledTimerStart();
++ }
++ }
++ break;
++
++ case kLedStateSlowBlinkContinues:
++ ledInfoPtr->blinkCountDown = kSlowBlinkCount;
++ ledInfoPtr->ledState = kLedStateSlowBlinkContinues;
++ ledInfoPtr->savedLedState = kLedStateSlowBlinkContinues;
++ ledTimerStart();
++ break;
++
++ case kLedStateFastBlinkContinues:
++ ledInfoPtr->blinkCountDown = kFastBlinkCount;
++ ledInfoPtr->ledState = kLedStateFastBlinkContinues;
++ ledInfoPtr->savedLedState = kLedStateFastBlinkContinues;
++ ledTimerStart();
++ break;
++
++ default:
++ printk("Invalid led state\n");
++ }
++}
++
++// This function is called for an LED that is controlled by hardware.
++void kerSysLedRegisterHwHandler( BOARD_LED_NAME ledName,
++ HANDLE_LED_FUNC ledHwFunc, int ledFailType )
++{
++ if( (int) ledName < MAX_VIRT_LEDS )
++ {
++ if( ledFailType == 1 )
++ gLedHwFailFunc[(int) ledName] = ledHwFunc;
++ else
++ gLedHwFunc[(int) ledName] = ledHwFunc;
++ }
++}
++
+diff -urN linux.old/arch/mips/bcm963xx/board.c linux.dev/arch/mips/bcm963xx/board.c
+--- linux.old/arch/mips/bcm963xx/board.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/board.c 2006-08-27 21:02:04.000000000 +0200
+@@ -0,0 +1,559 @@
++/*
++<:copyright-gpl
++ Copyright 2002 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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.
++:>
++*/
++
++/* Includes. */
++#include <linux/version.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/interrupt.h>
++#include <linux/capability.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/module.h>
++#include <linux/pagemap.h>
++#include <asm/uaccess.h>
++#include <linux/wait.h>
++#include <linux/poll.h>
++#include <linux/sched.h>
++#include <linux/list.h>
++#include <linux/if.h>
++#include <linux/spinlock.h>
++
++#include <bcm_map_part.h>
++#include <board.h>
++#include <bcmTag.h>
++#include "boardparms.h"
++#include "bcm_intr.h"
++#include "board.h"
++#include "bcm_map_part.h"
++
++static DEFINE_SPINLOCK(board_lock);
++
++/* Typedefs. */
++#if defined (NON_CONSECUTIVE_MAC)
++// used to be the last octet. Now changed to the first 5 bits of the the forth octet
++// to reduced the duplicated MAC addresses.
++#define CHANGED_OCTET 3
++#define SHIFT_BITS 3
++#else
++#define CHANGED_OCTET 1
++#define SHIFT_BITS 0
++#endif
++
++typedef struct
++{
++ unsigned long ulId;
++ char chInUse;
++ char chReserved[3];
++} MAC_ADDR_INFO, *PMAC_ADDR_INFO;
++
++typedef struct
++{
++ unsigned long ulSdramSize;
++ unsigned long ulPsiSize;
++ unsigned long ulNumMacAddrs;
++ unsigned long ucaBaseMacAddr[NVRAM_MAC_ADDRESS_LEN];
++ MAC_ADDR_INFO MacAddrs[1];
++} NVRAM_INFO, *PNVRAM_INFO;
++
++typedef struct
++{
++ unsigned long eventmask;
++} BOARD_IOC, *PBOARD_IOC;
++
++
++/*Dyinggasp callback*/
++typedef void (*cb_dgasp_t)(void *arg);
++typedef struct _CB_DGASP__LIST
++{
++ struct list_head list;
++ char name[IFNAMSIZ];
++ cb_dgasp_t cb_dgasp_fn;
++ void *context;
++}CB_DGASP_LIST , *PCB_DGASP_LIST;
++
++
++static LED_MAP_PAIR LedMapping[] =
++{ // led name Initial state physical pin (ledMask)
++ {kLedEnd, kLedStateOff, 0, 0, 0, 0},
++ {kLedEnd, kLedStateOff, 0, 0, 0, 0},
++ {kLedEnd, kLedStateOff, 0, 0, 0, 0},
++ {kLedEnd, kLedStateOff, 0, 0, 0, 0},
++ {kLedEnd, kLedStateOff, 0, 0, 0, 0},
++ {kLedEnd, kLedStateOff, 0, 0, 0, 0},
++ {kLedEnd, kLedStateOff, 0, 0, 0, 0},
++ {kLedEnd, kLedStateOff, 0, 0, 0, 0},
++ {kLedEnd, kLedStateOff, 0, 0, 0, 0} // NOTE: kLedEnd has to be at the end.
++};
++
++/* Externs. */
++extern struct file fastcall *fget_light(unsigned int fd, int *fput_needed);
++extern unsigned int nr_free_pages (void);
++extern const char *get_system_type(void);
++extern void kerSysFlashInit(void);
++extern unsigned long get_nvram_start_addr(void);
++extern unsigned long get_scratch_pad_start_addr(void);
++extern unsigned long getMemorySize(void);
++extern void __init boardLedInit(PLED_MAP_PAIR);
++extern void boardLedCtrl(BOARD_LED_NAME, BOARD_LED_STATE);
++extern void kerSysLedRegisterHandler( BOARD_LED_NAME ledName,
++ HANDLE_LED_FUNC ledHwFunc, int ledFailType );
++
++/* Prototypes. */
++void __init InitNvramInfo( void );
++
++/* DyingGasp function prototype */
++static void __init kerSysDyingGaspMapIntr(void);
++static irqreturn_t kerSysDyingGaspIsr(int irq, void * dev_id, struct pt_regs * regs);
++static void __init kerSysInitDyingGaspHandler( void );
++static void __exit kerSysDeinitDyingGaspHandler( void );
++/* -DyingGasp function prototype - */
++
++static PNVRAM_INFO g_pNvramInfo = NULL;
++static int g_ledInitialized = 0;
++static CB_DGASP_LIST *g_cb_dgasp_list_head = NULL;
++
++static int g_wakeup_monitor = 0;
++static struct file *g_monitor_file = NULL;
++static struct task_struct *g_monitor_task = NULL;
++static unsigned int (*g_orig_fop_poll)
++ (struct file *, struct poll_table_struct *) = NULL;
++
++void kerSysMipsSoftReset(void)
++{
++ if (PERF->RevID == 0x634800A1) {
++ typedef void (*FNPTR) (void);
++ FNPTR bootaddr = (FNPTR) FLASH_BASE;
++ int i;
++
++ /* Disable interrupts. */
++ //cli();
++ spin_lock_irq(&board_lock);
++
++ /* Reset all blocks. */
++ PERF->BlockSoftReset &= ~BSR_ALL_BLOCKS;
++ for( i = 0; i < 1000000; i++ )
++ ;
++ PERF->BlockSoftReset |= BSR_ALL_BLOCKS;
++ /* Jump to the power on address. */
++ (*bootaddr) ();
++ }
++ else
++ PERF->pll_control |= SOFT_RESET; // soft reset mips
++}
++
++
++int kerSysGetMacAddress( unsigned char *pucaMacAddr, unsigned long ulId )
++{
++ int nRet = 0;
++ PMAC_ADDR_INFO pMai = NULL;
++ PMAC_ADDR_INFO pMaiFreeNoId = NULL;
++ PMAC_ADDR_INFO pMaiFreeId = NULL;
++ unsigned long i = 0, ulIdxNoId = 0, ulIdxId = 0, shiftedIdx = 0;
++
++ /* CMO -- Fix le problème avec les adresses mac que l'on n'arrive pas
++ * * à relire plusieurs fois */
++ /* inv_xde */
++#if 0
++ if (boot_loader_type == BOOT_CFE)
++ memcpy( pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,
++ NVRAM_MAC_ADDRESS_LEN );
++ else {
++#endif
++ pucaMacAddr[0] = 0x00;
++ pucaMacAddr[1] = 0x07;
++ pucaMacAddr[2] = 0x3A;
++ pucaMacAddr[3] = 0xFF;
++ pucaMacAddr[4] = 0xFF;
++ pucaMacAddr[5] = 0xFF;
++#if 0
++ }
++#endif
++
++ return nRet;
++} /* kerSysGetMacAddr */
++
++int kerSysReleaseMacAddress( unsigned char *pucaMacAddr )
++{
++ int nRet = -EINVAL;
++ unsigned long ulIdx = 0;
++ int idx = (pucaMacAddr[NVRAM_MAC_ADDRESS_LEN - CHANGED_OCTET] -
++ g_pNvramInfo->ucaBaseMacAddr[NVRAM_MAC_ADDRESS_LEN - CHANGED_OCTET]);
++
++ // if overflow 255 (negitive), add 256 to have the correct index
++ if (idx < 0)
++ idx += 256;
++ ulIdx = (unsigned long) (idx >> SHIFT_BITS);
++
++ if( ulIdx < g_pNvramInfo->ulNumMacAddrs )
++ {
++ PMAC_ADDR_INFO pMai = &g_pNvramInfo->MacAddrs[ulIdx];
++ if( pMai->chInUse == 1 )
++ {
++ pMai->chInUse = 0;
++ nRet = 0;
++ }
++ }
++
++ return( nRet );
++} /* kerSysReleaseMacAddr */
++
++int kerSysGetSdramSize( void )
++{
++ if (boot_loader_type == BOOT_CFE) {
++ return( (int) g_pNvramInfo->ulSdramSize );
++ }
++ else {
++ printk("kerSysGetSdramSize : 0x%08X\n", (int)getMemorySize() + 0x00040000);
++ return((int)getMemorySize() + 0x00040000);
++ }
++} /* kerSysGetSdramSize */
++
++
++void kerSysLedCtrl(BOARD_LED_NAME ledName, BOARD_LED_STATE ledState)
++{
++ if (g_ledInitialized)
++ boardLedCtrl(ledName, ledState);
++}
++
++unsigned int kerSysMonitorPollHook( struct file *f, struct poll_table_struct *t)
++{
++ int mask = (*g_orig_fop_poll) (f, t);
++
++ if( g_wakeup_monitor == 1 && g_monitor_file == f )
++ {
++ /* If g_wakeup_monitor is non-0, the user mode application needs to
++ * return from a blocking select function. Return POLLPRI which will
++ * cause the select to return with the exception descriptor set.
++ */
++ mask |= POLLPRI;
++ g_wakeup_monitor = 0;
++ }
++
++ return( mask );
++}
++
++/* Put the user mode application that monitors link state on a run queue. */
++void kerSysWakeupMonitorTask( void )
++{
++ g_wakeup_monitor = 1;
++ if( g_monitor_task )
++ wake_up_process( g_monitor_task );
++}
++
++//<<JUNHON, 2004/09/15, get reset button status , tim hou , 05/04/12
++int kerSysGetResetHold(void)
++{
++ unsigned short gpio;
++
++ if( BpGetPressAndHoldResetGpio( &gpio ) == BP_SUCCESS )
++ {
++ unsigned long gpio_mask = GPIO_NUM_TO_MASK(gpio);
++ volatile unsigned long *gpio_reg = &GPIO->GPIOio;
++
++ if( (gpio & ~BP_ACTIVE_MASK) >= 32 )
++ {
++ gpio_mask = GPIO_NUM_TO_MASK_HIGH(gpio);
++ gpio_reg = &GPIO->GPIOio_high;
++ }
++ //printk("gpio=%04x,gpio_mask=%04x,gpio_reg=%04x\n",gpio,gpio_mask,*gpio_reg);
++ if(*gpio_reg & gpio_mask) //press down
++ return RESET_BUTTON_UP;
++ }
++ return RESET_BUTTON_PRESSDOWN;
++}
++//<<JUNHON, 2004/09/15
++
++/***************************************************************************
++ * Dying gasp ISR and functions.
++ ***************************************************************************/
++#define KERSYS_DBG printk
++
++#if defined(CONFIG_BCM96345)
++#define CYCLE_PER_US 70
++#elif defined(CONFIG_BCM96348) || defined(CONFIG_BCM96338)
++/* The BCM6348 cycles per microsecond is really variable since the BCM6348
++ * MIPS speed can vary depending on the PLL settings. However, an appoximate
++ * value of 120 will still work OK for the test being done.
++ */
++#define CYCLE_PER_US 120
++#endif
++#define DG_GLITCH_TO (100*CYCLE_PER_US)
++
++static void __init kerSysDyingGaspMapIntr()
++{
++ unsigned long ulIntr;
++
++#if defined(CONFIG_BCM96348) || defined(_BCM96348_) || defined(CONFIG_BCM96338) || defined(_BCM96338_)
++ if( BpGetAdslDyingGaspExtIntr( &ulIntr ) == BP_SUCCESS ) {
++ BcmHalMapInterrupt((FN_HANDLER)kerSysDyingGaspIsr, 0, INTERRUPT_ID_DG);
++ BcmHalInterruptEnable( INTERRUPT_ID_DG );
++ }
++#elif defined(CONFIG_BCM96345) || defined(_BCM96345_)
++ if( BpGetAdslDyingGaspExtIntr( &ulIntr ) == BP_SUCCESS ) {
++ ulIntr += INTERRUPT_ID_EXTERNAL_0;
++ BcmHalMapInterrupt((FN_HANDLER)kerSysDyingGaspIsr, 0, ulIntr);
++ BcmHalInterruptEnable( ulIntr );
++ }
++#endif
++
++}
++
++void kerSysSetWdTimer(ulong timeUs)
++{
++ TIMER->WatchDogDefCount = timeUs * (FPERIPH/1000000);
++ TIMER->WatchDogCtl = 0xFF00;
++ TIMER->WatchDogCtl = 0x00FF;
++}
++
++ulong kerSysGetCycleCount(void)
++{
++ ulong cnt;
++#ifdef _WIN32_WCE
++ cnt = 0;
++#else
++ __asm volatile("mfc0 %0, $9":"=d"(cnt));
++#endif
++ return(cnt);
++}
++
++static Bool kerSysDyingGaspCheckPowerLoss(void)
++{
++ ulong clk0;
++ ulong ulIntr;
++
++ ulIntr = 0;
++ clk0 = kerSysGetCycleCount();
++
++ UART->Data = 'D';
++ UART->Data = '%';
++ UART->Data = 'G';
++
++#if defined(CONFIG_BCM96345)
++ BpGetAdslDyingGaspExtIntr( &ulIntr );
++
++ do {
++ ulong clk1;
++
++ clk1 = kerSysGetCycleCount(); /* time cleared */
++ /* wait a little to get new reading */
++ while ((kerSysGetCycleCount()-clk1) < CYCLE_PER_US*2)
++ ;
++ } while ((0 == (PERF->ExtIrqCfg & (1 << (ulIntr + EI_STATUS_SHFT)))) && ((kerSysGetCycleCount() - clk0) < DG_GLITCH_TO));
++
++ if (PERF->ExtIrqCfg & (1 << (ulIntr + EI_STATUS_SHFT))) { /* power glitch */
++ BcmHalInterruptEnable( ulIntr + INTERRUPT_ID_EXTERNAL_0);
++ KERSYS_DBG(" - Power glitch detected. Duration: %ld us\n", (kerSysGetCycleCount() - clk0)/CYCLE_PER_US);
++ return 0;
++ }
++#elif (defined(CONFIG_BCM96348) || defined(CONFIG_BCM96338)) && !defined(VXWORKS)
++ do {
++ ulong clk1;
++
++ clk1 = kerSysGetCycleCount(); /* time cleared */
++ /* wait a little to get new reading */
++ while ((kerSysGetCycleCount()-clk1) < CYCLE_PER_US*2)
++ ;
++ } while ((PERF->IrqStatus & (1 << (INTERRUPT_ID_DG - INTERNAL_ISR_TABLE_OFFSET))) && ((kerSysGetCycleCount() - clk0) < DG_GLITCH_TO));
++
++ if (!(PERF->IrqStatus & (1 << (INTERRUPT_ID_DG - INTERNAL_ISR_TABLE_OFFSET)))) {
++ BcmHalInterruptEnable( INTERRUPT_ID_DG );
++ KERSYS_DBG(" - Power glitch detected. Duration: %ld us\n", (kerSysGetCycleCount() - clk0)/CYCLE_PER_US);
++ return 0;
++ }
++#endif
++ return 1;
++}
++
++static void kerSysDyingGaspShutdown( void )
++{
++ kerSysSetWdTimer(1000000);
++#if defined(CONFIG_BCM96345)
++ PERF->blkEnables &= ~(EMAC_CLK_EN | USB_CLK_EN | CPU_CLK_EN);
++#elif defined(CONFIG_BCM96348)
++ PERF->blkEnables &= ~(EMAC_CLK_EN | USBS_CLK_EN | USBH_CLK_EN | SAR_CLK_EN);
++#endif
++}
++
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
++static irqreturn_t kerSysDyingGaspIsr(int irq, void * dev_id, struct pt_regs * regs)
++#else
++static unsigned int kerSysDyingGaspIsr(void)
++#endif
++{
++ struct list_head *pos;
++ CB_DGASP_LIST *tmp, *dsl = NULL;
++
++ if (kerSysDyingGaspCheckPowerLoss()) {
++
++ /* first to turn off everything other than dsl */
++ list_for_each(pos, &g_cb_dgasp_list_head->list) {
++ tmp = list_entry(pos, CB_DGASP_LIST, list);
++ if(strncmp(tmp->name, "dsl", 3)) {
++ (tmp->cb_dgasp_fn)(tmp->context);
++ }else {
++ dsl = tmp;
++ }
++ }
++
++ /* now send dgasp */
++ if(dsl)
++ (dsl->cb_dgasp_fn)(dsl->context);
++
++ /* reset and shutdown system */
++ kerSysDyingGaspShutdown();
++ }
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
++return( IRQ_HANDLED );
++#else
++ return( 1 );
++#endif
++}
++
++static void __init kerSysInitDyingGaspHandler( void )
++{
++ CB_DGASP_LIST *new_node;
++
++ if( g_cb_dgasp_list_head != NULL) {
++ printk("Error: kerSysInitDyingGaspHandler: list head is not null\n");
++ return;
++ }
++ new_node= (CB_DGASP_LIST *)kmalloc(sizeof(CB_DGASP_LIST), GFP_KERNEL);
++ memset(new_node, 0x00, sizeof(CB_DGASP_LIST));
++ INIT_LIST_HEAD(&new_node->list);
++ g_cb_dgasp_list_head = new_node;
++
++} /* kerSysInitDyingGaspHandler */
++
++static void __exit kerSysDeinitDyingGaspHandler( void )
++{
++ struct list_head *pos;
++ CB_DGASP_LIST *tmp;
++
++ if(g_cb_dgasp_list_head == NULL)
++ return;
++
++ list_for_each(pos, &g_cb_dgasp_list_head->list) {
++ tmp = list_entry(pos, CB_DGASP_LIST, list);
++ list_del(pos);
++ kfree(tmp);
++ }
++
++ kfree(g_cb_dgasp_list_head);
++ g_cb_dgasp_list_head = NULL;
++
++} /* kerSysDeinitDyingGaspHandler */
++
++void kerSysRegisterDyingGaspHandler(char *devname, void *cbfn, void *context)
++{
++ CB_DGASP_LIST *new_node;
++
++ if( g_cb_dgasp_list_head == NULL) {
++ printk("Error: kerSysRegisterDyingGaspHandler: list head is null\n");
++ return;
++ }
++
++ if( devname == NULL || cbfn == NULL ) {
++ printk("Error: kerSysRegisterDyingGaspHandler: register info not enough (%s,%x,%x)\n", devname, (unsigned int)cbfn, (unsigned int)context);
++ return;
++ }
++
++ new_node= (CB_DGASP_LIST *)kmalloc(sizeof(CB_DGASP_LIST), GFP_KERNEL);
++ memset(new_node, 0x00, sizeof(CB_DGASP_LIST));
++ INIT_LIST_HEAD(&new_node->list);
++ strncpy(new_node->name, devname, IFNAMSIZ);
++ new_node->cb_dgasp_fn = (cb_dgasp_t)cbfn;
++ new_node->context = context;
++ list_add(&new_node->list, &g_cb_dgasp_list_head->list);
++
++ printk("dgasp: kerSysRegisterDyingGaspHandler: %s registered \n", devname);
++
++} /* kerSysRegisterDyingGaspHandler */
++
++void kerSysDeregisterDyingGaspHandler(char *devname)
++{
++ struct list_head *pos;
++ CB_DGASP_LIST *tmp;
++
++ if(g_cb_dgasp_list_head == NULL) {
++ printk("Error: kerSysDeregisterDyingGaspHandler: list head is null\n");
++ return;
++ }
++
++ if(devname == NULL) {
++ printk("Error: kerSysDeregisterDyingGaspHandler: devname is null\n");
++ return;
++ }
++
++ printk("kerSysDeregisterDyingGaspHandler: %s is deregistering\n", devname);
++
++ list_for_each(pos, &g_cb_dgasp_list_head->list) {
++ tmp = list_entry(pos, CB_DGASP_LIST, list);
++ if(!strcmp(tmp->name, devname)) {
++ list_del(pos);
++ kfree(tmp);
++ printk("kerSysDeregisterDyingGaspHandler: %s is deregistered\n", devname);
++ return;
++ }
++ }
++ printk("kerSysDeregisterDyingGaspHandler: %s not (de)registered\n", devname);
++
++} /* kerSysDeregisterDyingGaspHandler */
++
++//EXPORT_SYMBOL(kerSysNvRamGet);
++EXPORT_SYMBOL(kerSysGetMacAddress);
++EXPORT_SYMBOL(kerSysReleaseMacAddress);
++EXPORT_SYMBOL(kerSysGetSdramSize);
++EXPORT_SYMBOL(kerSysLedCtrl);
++EXPORT_SYMBOL(kerSysGetResetHold);
++EXPORT_SYMBOL(kerSysLedRegisterHwHandler);
++EXPORT_SYMBOL(BpGetBoardIds);
++EXPORT_SYMBOL(BpGetSdramSize);
++EXPORT_SYMBOL(BpGetPsiSize);
++EXPORT_SYMBOL(BpGetEthernetMacInfo);
++EXPORT_SYMBOL(BpGetRj11InnerOuterPairGpios);
++EXPORT_SYMBOL(BpGetPressAndHoldResetGpio);
++EXPORT_SYMBOL(BpGetVoipResetGpio);
++EXPORT_SYMBOL(BpGetVoipIntrGpio);
++EXPORT_SYMBOL(BpGetPcmciaResetGpio);
++EXPORT_SYMBOL(BpGetRtsCtsUartGpios);
++EXPORT_SYMBOL(BpGetAdslLedGpio);
++EXPORT_SYMBOL(BpGetAdslFailLedGpio);
++EXPORT_SYMBOL(BpGetWirelessLedGpio);
++EXPORT_SYMBOL(BpGetUsbLedGpio);
++EXPORT_SYMBOL(BpGetHpnaLedGpio);
++EXPORT_SYMBOL(BpGetWanDataLedGpio);
++EXPORT_SYMBOL(BpGetPppLedGpio);
++EXPORT_SYMBOL(BpGetPppFailLedGpio);
++EXPORT_SYMBOL(BpGetVoipLedGpio);
++EXPORT_SYMBOL(BpGetWirelessExtIntr);
++EXPORT_SYMBOL(BpGetAdslDyingGaspExtIntr);
++EXPORT_SYMBOL(BpGetVoipExtIntr);
++EXPORT_SYMBOL(BpGetHpnaExtIntr);
++EXPORT_SYMBOL(BpGetHpnaChipSelect);
++EXPORT_SYMBOL(BpGetVoipChipSelect);
++EXPORT_SYMBOL(BpGetWirelessSesBtnGpio);
++EXPORT_SYMBOL(BpGetWirelessSesExtIntr);
++EXPORT_SYMBOL(BpGetWirelessSesLedGpio);
++EXPORT_SYMBOL(kerSysRegisterDyingGaspHandler);
++EXPORT_SYMBOL(kerSysDeregisterDyingGaspHandler);
++EXPORT_SYMBOL(kerSysGetCycleCount);
++EXPORT_SYMBOL(kerSysSetWdTimer);
++EXPORT_SYMBOL(kerSysWakeupMonitorTask);
++
+diff -urN linux.old/arch/mips/bcm963xx/boardparms.c linux.dev/arch/mips/bcm963xx/boardparms.c
+--- linux.old/arch/mips/bcm963xx/boardparms.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/boardparms.c 2006-08-25 00:39:38.000000000 +0200
+@@ -0,0 +1,2391 @@
++/*
++<:copyright-gpl
++
++ Copyright 2003 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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.
++
++:>
++*/
++/**************************************************************************
++ * File Name : boardparms.c
++ *
++ * Description: This file contains the implementation for the BCM63xx board
++ * parameter access functions.
++ *
++ * Updates : 07/14/2003 Created.
++ ***************************************************************************/
++
++/* Includes. */
++#include "boardparms.h"
++
++/* Defines. */
++
++/* Default psi size in K bytes */
++#define BP_PSI_DEFAULT_SIZE 24
++
++/* Typedefs */
++typedef struct boardparameters
++{
++ char szBoardId[BP_BOARD_ID_LEN]; /* board id string */
++ ETHERNET_MAC_INFO EnetMacInfos[BP_MAX_ENET_MACS];
++ VOIP_DSP_INFO VoIPDspInfo[BP_MAX_VOIP_DSP];
++ unsigned short usSdramSize; /* SDRAM size and type */
++ unsigned short usPsiSize; /* persistent storage in K bytes */
++ unsigned short usGpioRj11InnerPair; /* GPIO pin or not defined */
++ unsigned short usGpioRj11OuterPair; /* GPIO pin or not defined */
++ unsigned short usGpioPressAndHoldReset; /* GPIO pin or not defined */
++ unsigned short usGpioPcmciaReset; /* GPIO pin or not defined */
++ unsigned short usGpioUartRts; /* GPIO pin or not defined */
++ unsigned short usGpioUartCts; /* GPIO pin or not defined */
++ unsigned short usGpioLedAdsl; /* GPIO pin or not defined */
++ unsigned short usGpioLedAdslFail; /* GPIO pin or not defined */
++ unsigned short usGpioLedWireless; /* GPIO pin or not defined */
++ unsigned short usGpioLedUsb; /* GPIO pin or not defined */
++ unsigned short usGpioLedHpna; /* GPIO pin or not defined */
++ unsigned short usGpioLedWanData; /* GPIO pin or not defined */
++ unsigned short usGpioLedPpp; /* GPIO pin or not defined */
++ unsigned short usGpioLedPppFail; /* GPIO pin or not defined */
++ unsigned short usGpioLedBlPowerOn; /* GPIO pin or not defined */
++ unsigned short usGpioLedBlAlarm; /* GPIO pin or not defined */
++ unsigned short usGpioLedBlResetCfg; /* GPIO pin or not defined */
++ unsigned short usGpioLedBlStop; /* GPIO pin or not defined */
++ unsigned short usExtIntrWireless; /* ext intr or not defined */
++ unsigned short usExtIntrAdslDyingGasp; /* ext intr or not defined */
++ unsigned short usExtIntrHpna; /* ext intr or not defined */
++ unsigned short usCsHpna; /* chip select not defined */
++ unsigned short usAntInUseWireless; /* antenna in use or not defined */
++ unsigned short usGpioSesBtnWireless; /* GPIO pin or not defined */
++ unsigned short usExtIntrSesBtnWireless; /* ext intr or not defined */
++ unsigned short usGpioLedSesWireless; /* GPIO pin or not defined */
++} BOARD_PARAMETERS, *PBOARD_PARAMETERS;
++
++/* Variables */
++#if defined(_BCM96338_) || defined(CONFIG_BCM96338)
++static BOARD_PARAMETERS g_bcm96338sv =
++{
++ "96338SV", /* szBoardId */
++ {{BP_ENET_INTERNAL_PHY, /* ucPhyType */
++ 0x01, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x01, /* numSwitchPorts */
++ BP_ENET_CONFIG_MDIO, /* usConfigType */
++ BP_NOT_DEFINED}, /* usReverseMii */
++ {BP_ENET_NO_PHY}}, /* ucPhyType */
++ {{BP_VOIP_NO_DSP}, /* ucDspType */
++ {BP_VOIP_NO_DSP}}, /* ucDspType */
++ BP_MEMORY_16MB_1_CHIP, /* usSdramSize */
++ BP_PSI_DEFAULT_SIZE, /* usPsiSize */
++ BP_NOT_DEFINED, /* usGpioRj11InnerPair */
++ BP_NOT_DEFINED, /* usGpioRj11OuterPair */
++ BP_NOT_DEFINED, /* usGpioPressAndHoldReset */
++ BP_NOT_DEFINED, /* usGpioPcmciaReset */
++ BP_NOT_DEFINED, /* usGpioUartRts */
++ BP_NOT_DEFINED, /* usGpioUartCts */
++ BP_NOT_DEFINED, /* usGpioLedAdsl */
++ BP_NOT_DEFINED, /* usGpioLedAdslFail */
++ BP_NOT_DEFINED, /* usGpioLedWireless */
++ BP_NOT_DEFINED, /* usGpioLedUsb */
++ BP_NOT_DEFINED, /* usGpioLedHpna */
++ BP_NOT_DEFINED, /* usGpioLedWanData */
++ BP_NOT_DEFINED, /* usGpioLedPpp */
++ BP_NOT_DEFINED, /* usGpioLedPppFail */
++ BP_NOT_DEFINED, /* usGpioLedBlPowerOn */
++ BP_NOT_DEFINED, /* usGpioLedBlAlarm */
++ BP_NOT_DEFINED, /* usGpioLedBlResetCfg */
++ BP_NOT_DEFINED, /* usGpioLedBlStop */
++ BP_NOT_DEFINED, /* usExtIntrWireless */
++ BP_HW_DEFINED, /* usExtIntrAdslDyingGasp */
++ BP_NOT_DEFINED, /* usExtIntrHpna */
++ BP_NOT_DEFINED, /* usCsHpna */
++ BP_NOT_DEFINED, /* usAntInUseWireless */
++ BP_NOT_DEFINED, /* usGpioSesBtnWireless */
++ BP_NOT_DEFINED, /* usExtIntrSesBtnWireless */
++ BP_NOT_DEFINED /* usGpioLedSesWireless */
++};
++static BOARD_PARAMETERS g_bcm96338l2m8m =
++{
++ "96338L-2M-8M", /* szBoardId */
++ {{BP_ENET_INTERNAL_PHY, /* ucPhyType */
++ 0x01, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x01, /* numSwitchPorts */
++ BP_ENET_CONFIG_MDIO, /* usConfigType */
++ BP_NOT_DEFINED}, /* usReverseMii */
++ {BP_ENET_NO_PHY}}, /* ucPhyType */
++ {{BP_VOIP_NO_DSP}, /* ucDspType */
++ {BP_VOIP_NO_DSP}}, /* ucDspType */
++ BP_MEMORY_8MB_1_CHIP, /* usSdramSize */
++ BP_PSI_DEFAULT_SIZE, /* usPsiSize */
++ BP_NOT_DEFINED, /* usGpioRj11InnerPair */
++ BP_NOT_DEFINED, /* usGpioRj11OuterPair */
++ BP_NOT_DEFINED, /* usGpioPressAndHoldReset */
++ BP_NOT_DEFINED, /* usGpioPcmciaReset */
++ BP_NOT_DEFINED, /* usGpioUartRts */
++ BP_NOT_DEFINED, /* usGpioUartCts */
++ BP_NOT_DEFINED, /* usGpioLedAdsl */
++ BP_GPIO_2_AL, /* usGpioLedAdslFail */
++ BP_NOT_DEFINED, /* usGpioLedWireless */
++ BP_NOT_DEFINED, /* usGpioLedUsb */
++ BP_NOT_DEFINED, /* usGpioLedHpna */
++ BP_GPIO_3_AL, /* usGpioLedWanData */
++ BP_GPIO_3_AL, /* usGpioLedPpp */
++ BP_GPIO_4_AL, /* usGpioLedPppFail */
++ BP_GPIO_0_AL, /* usGpioLedBlPowerOn */
++ BP_NOT_DEFINED, /* usGpioLedBlAlarm */
++ BP_GPIO_3_AL, /* usGpioLedBlResetCfg */
++ BP_GPIO_1_AL, /* usGpioLedBlStop */
++ BP_NOT_DEFINED, /* usExtIntrWireless */
++ BP_HW_DEFINED, /* usExtIntrAdslDyingGasp */
++ BP_NOT_DEFINED, /* usExtIntrHpna */
++ BP_NOT_DEFINED, /* usCsHpna */
++ BP_NOT_DEFINED, /* usAntInUseWireless */
++ BP_NOT_DEFINED, /* usGpioSesBtnWireless */
++ BP_NOT_DEFINED, /* usExtIntrSesBtnWireless */
++ BP_NOT_DEFINED /* usGpioLedSesWireless */
++};
++static PBOARD_PARAMETERS g_BoardParms[] =
++ {&g_bcm96338sv, &g_bcm96338l2m8m, 0};
++#endif
++
++#if defined(_BCM96345_) || defined(CONFIG_BCM96345)
++static BOARD_PARAMETERS g_bcm96345r =
++{
++ "96345R", /* szBoardId */
++ {{BP_ENET_INTERNAL_PHY, /* ucPhyType */
++ 0x01, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x01, /* numSwitchPorts */
++ BP_ENET_CONFIG_MDIO, /* usConfigType */
++ BP_NOT_DEFINED}, /* usReverseMii */
++ {BP_ENET_NO_PHY}}, /* ucPhyType */
++ {{BP_VOIP_NO_DSP}, /* ucDspType */
++ {BP_VOIP_NO_DSP}}, /* ucDspType */
++ BP_MEMORY_8MB_1_CHIP, /* usSdramSize */
++ BP_PSI_DEFAULT_SIZE, /* usPsiSize */
++ BP_GPIO_11_AH, /* usGpioRj11InnerPair */
++ BP_GPIO_12_AH, /* usGpioRj11OuterPair */
++ BP_GPIO_13_AH, /* usGpioPressAndHoldReset */
++ BP_NOT_DEFINED, /* usGpioPcmciaReset */
++ BP_NOT_DEFINED, /* usGpioUartRts */
++ BP_NOT_DEFINED, /* usGpioUartCts */
++ BP_GPIO_8_AH, /* usGpioLedAdsl */
++ BP_NOT_DEFINED, /* usGpioLedAdslFail */
++ BP_NOT_DEFINED, /* usGpioLedWireless */
++ BP_NOT_DEFINED, /* usGpioLedUsb */
++ BP_NOT_DEFINED, /* usGpioLedHpna */
++ BP_GPIO_8_AH, /* usGpioLedWanData */
++ BP_GPIO_9_AH, /* usGpioLedPpp */
++ BP_NOT_DEFINED, /* usGpioLedPppFail */
++ BP_NOT_DEFINED, /* usGpioLedBlPowerOn */
++ BP_GPIO_10_AH, /* usGpioLedBlAlarm */
++ BP_GPIO_9_AH, /* usGpioLedBlResetCfg */
++ BP_GPIO_8_AH, /* usGpioLedBlStop */
++ BP_NOT_DEFINED, /* usExtIntrWireless */
++ BP_EXT_INTR_0, /* usExtIntrAdslDyingGasp */
++ BP_NOT_DEFINED, /* usExtIntrHpna */
++ BP_NOT_DEFINED, /* usCsHpna */
++ BP_NOT_DEFINED, /* usAntInUseWireless */
++ BP_NOT_DEFINED, /* usGpioSesBtnWireless */
++ BP_NOT_DEFINED, /* usExtIntrSesBtnWireless */
++ BP_NOT_DEFINED /* usGpioLedSesWireless */
++};
++
++static BOARD_PARAMETERS g_bcm96345gw2 =
++{
++ /* A hardware jumper determines whether GPIO 13 is used for Press and Hold
++ * Reset or RTS.
++ */
++ "96345GW2", /* szBoardId */
++ {{BP_ENET_EXTERNAL_SWITCH, /* ucPhyType */
++ 0x00, /* ucPhyAddress */
++ BP_GPIO_0_AH, /* usGpioPhySpiSck */
++ BP_GPIO_4_AH, /* usGpioPhySpiSs */
++ BP_GPIO_12_AH, /* usGpioPhySpiMosi */
++ BP_GPIO_11_AH, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x04, /* numSwitchPorts */
++ BP_ENET_CONFIG_GPIO, /* usConfigType */
++ BP_ENET_REVERSE_MII}, /* usReverseMii */
++ {BP_ENET_NO_PHY}}, /* ucPhyType */
++ {{BP_VOIP_DSP, /* ucDspType */
++ 0x00, /* ucDspAddress */
++ BP_EXT_INTR_1, /* usExtIntrVoip */
++ BP_GPIO_6_AH, /* usGpioVoipReset */
++ BP_GPIO_15_AH, /* usGpioVoipIntr */
++ BP_NOT_DEFINED, /* usGpioLedVoip */
++ BP_CS_2}, /* usCsVoip */
++ {BP_VOIP_NO_DSP}}, /* ucDspType */
++ BP_MEMORY_16MB_1_CHIP, /* usSdramSize */
++ BP_PSI_DEFAULT_SIZE, /* usPsiSize */
++ BP_NOT_DEFINED, /* usGpioRj11InnerPair */
++ BP_NOT_DEFINED, /* usGpioRj11OuterPair */
++ BP_GPIO_13_AH, /* usGpioPressAndHoldReset */
++ BP_GPIO_2_AH, /* usGpioPcmciaReset */
++ BP_GPIO_13_AH, /* usGpioUartRts */
++ BP_GPIO_9_AH, /* usGpioUartCts */
++ BP_GPIO_8_AH, /* usGpioLedAdsl */
++ BP_NOT_DEFINED, /* usGpioLedAdslFail */
++ BP_NOT_DEFINED, /* usGpioLedWireless */
++ BP_GPIO_7_AH, /* usGpioLedUsb */
++ BP_NOT_DEFINED, /* usGpioLedHpna */
++ BP_GPIO_8_AH, /* usGpioLedWanData */
++ BP_NOT_DEFINED, /* usGpioLedPpp */
++ BP_NOT_DEFINED, /* usGpioLedPppFail */
++ BP_NOT_DEFINED, /* usGpioLedBlPowerOn */
++ BP_GPIO_10_AH, /* usGpioLedBlAlarm */
++ BP_GPIO_7_AH, /* usGpioLedBlResetCfg */
++ BP_GPIO_8_AH, /* usGpioLedBlStop */
++ BP_EXT_INTR_2, /* usExtIntrWireless */
++ BP_EXT_INTR_0, /* usExtIntrAdslDyingGasp */
++ BP_NOT_DEFINED, /* usExtIntrHpna */
++ BP_NOT_DEFINED, /* usCsHpna */
++ BP_WLAN_ANT_MAIN, /* usAntInUseWireless */
++ BP_NOT_DEFINED, /* usGpioSesBtnWireless */
++ BP_NOT_DEFINED, /* usExtIntrSesBtnWireless */
++ BP_NOT_DEFINED /* usGpioLedSesWireless */
++};
++
++static BOARD_PARAMETERS g_bcm96345gw =
++{
++ "96345GW", /* szBoardId */
++ {{BP_ENET_EXTERNAL_SWITCH, /* ucPhyType */
++ 0x00, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x04, /* numSwitchPorts */
++ BP_ENET_CONFIG_MDIO, /* usConfigType */
++ BP_ENET_NO_REVERSE_MII}, /* usReverseMii */
++ {BP_ENET_NO_PHY}}, /* ucPhyType */
++ {{BP_VOIP_DSP, /* ucDspType */
++ 0x00, /* ucDspAddress */
++ BP_EXT_INTR_1, /* usExtIntrVoip */
++ BP_GPIO_6_AH, /* usGpioVoipReset */
++ BP_GPIO_15_AH, /* usGpioVoipIntr */
++ BP_NOT_DEFINED, /* usGpioLedVoip */
++ BP_CS_2}, /* usCsVoip */
++ {BP_VOIP_NO_DSP}}, /* ucDspType */
++ BP_MEMORY_16MB_1_CHIP, /* usSdramSize */
++ BP_PSI_DEFAULT_SIZE, /* usPsiSize */
++ BP_GPIO_11_AH, /* usGpioRj11InnerPair */
++ BP_GPIO_1_AH, /* usGpioRj11OuterPair */
++ BP_GPIO_13_AH, /* usGpioPressAndHoldReset */
++ BP_GPIO_2_AH, /* usGpioPcmciaReset */
++ BP_NOT_DEFINED, /* usGpioUartRts */
++ BP_NOT_DEFINED, /* usGpioUartCts */
++ BP_GPIO_8_AH, /* usGpioLedAdsl */
++ BP_NOT_DEFINED, /* usGpioLedAdslFail */
++ BP_GPIO_10_AH, /* usGpioLedWireless */
++ BP_GPIO_7_AH, /* usGpioLedUsb */
++ BP_NOT_DEFINED, /* usGpioLedHpna */
++ BP_GPIO_8_AH, /* usGpioLedWanData */
++ BP_NOT_DEFINED, /* usGpioLedPpp */
++ BP_NOT_DEFINED, /* usGpioLedPppFail */
++ BP_NOT_DEFINED, /* usGpioLedBlPowerOn */
++ BP_GPIO_9_AH, /* usGpioLedBlAlarm */
++ BP_GPIO_10_AH, /* usGpioLedBlResetCfg */
++ BP_GPIO_8_AH, /* usGpioLedBlStop */
++ BP_EXT_INTR_2, /* usExtIntrWireless */
++ BP_EXT_INTR_0, /* usExtIntrAdslDyingGasp */
++ BP_EXT_INTR_3, /* usExtIntrHpna */
++ BP_CS_1, /* usCsHpna */
++ BP_WLAN_ANT_MAIN, /* usAntInUseWireless */
++ BP_NOT_DEFINED, /* usGpioSesBtnWireless */
++ BP_NOT_DEFINED, /* usExtIntrSesBtnWireless */
++ BP_NOT_DEFINED /* usGpioLedSesWireless */
++};
++
++static BOARD_PARAMETERS g_bcm96335r =
++{
++ "96335R", /* szBoardId */
++ {{BP_ENET_INTERNAL_PHY, /* ucPhyType */
++ 0x01, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x01, /* numSwitchPorts */
++ BP_ENET_CONFIG_MDIO, /* usConfigType */
++ BP_NOT_DEFINED}, /* usReverseMii */
++ {BP_ENET_NO_PHY}}, /* ucPhyType */
++ {{BP_VOIP_NO_DSP}, /* ucDspType */
++ {BP_VOIP_NO_DSP}}, /* ucDspType */
++ BP_MEMORY_8MB_1_CHIP, /* usSdramSize */
++ BP_PSI_DEFAULT_SIZE, /* usPsiSize */
++ BP_NOT_DEFINED, /* usGpioRj11InnerPair */
++ BP_NOT_DEFINED, /* usGpioRj11OuterPair */
++ BP_GPIO_14_AH, /* usGpioPressAndHoldReset */
++ BP_NOT_DEFINED, /* usGpioPcmciaReset */
++ BP_NOT_DEFINED, /* usGpioUartRts */
++ BP_NOT_DEFINED, /* usGpioUartCts */
++ BP_GPIO_9_AH, /* usGpioLedAdsl */
++ BP_NOT_DEFINED, /* usGpioLedAdslFail */
++ BP_NOT_DEFINED, /* usGpioLedWireless */
++ BP_NOT_DEFINED, /* usGpioLedUsb */
++ BP_NOT_DEFINED, /* usGpioLedHpna */
++ BP_GPIO_9_AH, /* usGpioLedWanData */
++ BP_GPIO_8_AH, /* usGpioLedPpp */
++ BP_NOT_DEFINED, /* usGpioLedPppFail */
++ BP_NOT_DEFINED, /* usGpioLedBlPowerOn */
++ BP_GPIO_10_AH, /* usGpioLedBlAlarm */
++ BP_GPIO_8_AH, /* usGpioLedBlResetCfg */
++ BP_GPIO_9_AH, /* usGpioLedBlStop */
++ BP_NOT_DEFINED, /* usExtIntrWireless */
++ BP_NOT_DEFINED, /* usExtIntrAdslDyingGasp */
++ BP_NOT_DEFINED, /* usExtIntrHpna */
++ BP_NOT_DEFINED, /* usCsHpna */
++ BP_NOT_DEFINED, /* usAntInUseWireless */
++ BP_NOT_DEFINED, /* usGpioSesBtnWireless */
++ BP_NOT_DEFINED, /* usExtIntrSesBtnWireless */
++ BP_NOT_DEFINED /* usGpioLedSesWireless */
++};
++
++static BOARD_PARAMETERS g_bcm96345r0 =
++{
++ "96345R0", /* szBoardId */
++ {{BP_ENET_INTERNAL_PHY, /* ucPhyType */
++ 0x01, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x01, /* numSwitchPorts */
++ BP_ENET_CONFIG_MDIO, /* usConfigType */
++ BP_NOT_DEFINED}, /* usReverseMii */
++ {BP_ENET_NO_PHY}}, /* ucPhyType */
++ {{BP_VOIP_NO_DSP}, /* ucDspType */
++ {BP_VOIP_NO_DSP}}, /* ucDspType */
++ BP_MEMORY_8MB_1_CHIP, /* usSdramSize */
++ BP_PSI_DEFAULT_SIZE, /* usPsiSize */
++ BP_NOT_DEFINED, /* usGpioRj11InnerPair */
++ BP_NOT_DEFINED, /* usGpioRj11OuterPair */
++ BP_NOT_DEFINED, /* usGpioPressAndHoldReset */
++ BP_NOT_DEFINED, /* usGpioPcmciaReset */
++ BP_NOT_DEFINED, /* usGpioUartRts */
++ BP_NOT_DEFINED, /* usGpioUartCts */
++ BP_GPIO_8_AH, /* usGpioLedAdsl */
++ BP_NOT_DEFINED, /* usGpioLedAdslFail */
++ BP_NOT_DEFINED, /* usGpioLedWireless */
++ BP_NOT_DEFINED, /* usGpioLedUsb */
++ BP_NOT_DEFINED, /* usGpioLedHpna */
++ BP_GPIO_9_AH, /* usGpioLedWanData */
++ BP_GPIO_9_AH, /* usGpioLedPpp */
++ BP_NOT_DEFINED, /* usGpioLedPppFail */
++ BP_NOT_DEFINED, /* usGpioLedBlPowerOn */
++ BP_GPIO_9_AH, /* usGpioLedBlAlarm */
++ BP_GPIO_8_AH, /* usGpioLedBlResetCfg */
++ BP_GPIO_8_AH, /* usGpioLedBlStop */
++ BP_NOT_DEFINED, /* usExtIntrWireless */
++ BP_NOT_DEFINED, /* usExtIntrAdslDyingGasp */
++ BP_NOT_DEFINED, /* usExtIntrHpna */
++ BP_NOT_DEFINED, /* usCsHpna */
++ BP_NOT_DEFINED, /* usAntInUseWireless */
++ BP_NOT_DEFINED, /* usGpioSesBtnWireless */
++ BP_NOT_DEFINED, /* usExtIntrSesBtnWireless */
++ BP_NOT_DEFINED /* usGpioLedSesWireless */
++};
++
++static BOARD_PARAMETERS g_bcm96345rs =
++{
++ "96345RS", /* szBoardId */
++ {{BP_ENET_EXTERNAL_SWITCH, /* ucPhyType */
++ 0x00, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x01, /* numSwitchPorts */
++ BP_ENET_CONFIG_MDIO, /* usConfigType */
++ BP_ENET_NO_REVERSE_MII}, /* usReverseMii */
++ {BP_ENET_NO_PHY}}, /* ucPhyType */
++ {{BP_VOIP_NO_DSP}, /* ucDspType */
++ {BP_VOIP_NO_DSP}}, /* ucDspType */
++ BP_MEMORY_8MB_1_CHIP, /* usSdramSize */
++ BP_PSI_DEFAULT_SIZE, /* usPsiSize */
++ BP_GPIO_11_AH, /* usGpioRj11InnerPair */
++ BP_GPIO_12_AH, /* usGpioRj11OuterPair */
++ BP_GPIO_13_AH, /* usGpioPressAndHoldReset */
++ BP_NOT_DEFINED, /* usGpioPcmciaReset */
++ BP_NOT_DEFINED, /* usGpioUartRts */
++ BP_NOT_DEFINED, /* usGpioUartCts */
++ BP_GPIO_8_AH, /* usGpioLedAdsl */
++ BP_NOT_DEFINED, /* usGpioLedAdslFail */
++ BP_NOT_DEFINED, /* usGpioLedWireless */
++ BP_NOT_DEFINED, /* usGpioLedUsb */
++ BP_NOT_DEFINED, /* usGpioLedHpna */
++ BP_GPIO_8_AH, /* usGpioLedWanData */
++ BP_GPIO_9_AH, /* usGpioLedPpp */
++ BP_NOT_DEFINED, /* usGpioLedPppFail */
++ BP_NOT_DEFINED, /* usGpioLedBlPowerOn */
++ BP_GPIO_10_AH, /* usGpioLedBlAlarm */
++ BP_GPIO_9_AH, /* usGpioLedBlResetCfg */
++ BP_GPIO_8_AH, /* usGpioLedBlStop */
++ BP_NOT_DEFINED, /* usExtIntrWireless */
++ BP_EXT_INTR_0, /* usExtIntrAdslDyingGasp */
++ BP_NOT_DEFINED, /* usExtIntrHpna */
++ BP_NOT_DEFINED, /* usCsHpna */
++ BP_NOT_DEFINED, /* usAntInUseWireless */
++ BP_NOT_DEFINED, /* usGpioSesBtnWireless */
++ BP_NOT_DEFINED, /* usExtIntrSesBtnWireless */
++ BP_NOT_DEFINED /* usGpioLedSesWireless */
++};
++
++static PBOARD_PARAMETERS g_BoardParms[] =
++ {&g_bcm96345r, &g_bcm96345gw2, &g_bcm96345gw, &g_bcm96335r, &g_bcm96345r0,
++ &g_bcm96345rs, 0};
++#endif
++
++#if defined(_BCM96348_) || defined(CONFIG_BCM96348)
++
++static BOARD_PARAMETERS g_bcm96348r =
++{
++ "96348R", /* szBoardId */
++ {{BP_ENET_INTERNAL_PHY, /* ucPhyType */
++ 0x01, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x01, /* numSwitchPorts */
++ BP_ENET_CONFIG_MDIO, /* usConfigType */
++ BP_NOT_DEFINED}, /* usReverseMii */
++ {BP_ENET_NO_PHY}}, /* ucPhyType */
++ {{BP_VOIP_NO_DSP}, /* ucDspType */
++ {BP_VOIP_NO_DSP}}, /* ucDspType */
++ BP_MEMORY_8MB_1_CHIP, /* usSdramSize */
++ BP_PSI_DEFAULT_SIZE, /* usPsiSize */
++ BP_NOT_DEFINED, /* usGpioRj11InnerPair */
++ BP_NOT_DEFINED, /* usGpioRj11OuterPair */
++ BP_GPIO_7_AH, /* usGpioPressAndHoldReset */
++ BP_NOT_DEFINED, /* usGpioPcmciaReset */
++ BP_NOT_DEFINED, /* usGpioUartRts */
++ BP_NOT_DEFINED, /* usGpioUartCts */
++ BP_NOT_DEFINED, /* usGpioLedAdsl */
++ BP_GPIO_2_AL, /* usGpioLedAdslFail */
++ BP_NOT_DEFINED, /* usGpioLedWireless */
++ BP_NOT_DEFINED, /* usGpioLedUsb */
++ BP_NOT_DEFINED, /* usGpioLedHpna */
++ BP_GPIO_3_AL, /* usGpioLedWanData */
++ BP_GPIO_3_AL, /* usGpioLedPpp */
++ BP_GPIO_4_AL, /* usGpioLedPppFail */
++ BP_GPIO_0_AL, /* usGpioLedBlPowerOn */
++ BP_NOT_DEFINED, /* usGpioLedBlAlarm */
++ BP_GPIO_3_AL, /* usGpioLedBlResetCfg */
++ BP_GPIO_1_AL, /* usGpioLedBlStop */
++ BP_NOT_DEFINED, /* usExtIntrWireless */
++ BP_HW_DEFINED, /* usExtIntrAdslDyingGasp */
++ BP_NOT_DEFINED, /* usExtIntrHpna */
++ BP_NOT_DEFINED, /* usCsHpna */
++ BP_NOT_DEFINED, /* usAntInUseWireless */
++ BP_NOT_DEFINED, /* usGpioSesBtnWireless */
++ BP_NOT_DEFINED, /* usExtIntrSesBtnWireless */
++ BP_NOT_DEFINED /* usGpioLedSesWireless */
++};
++
++static BOARD_PARAMETERS g_bcm96348lv =
++{
++ "96348LV", /* szBoardId */
++ {{BP_ENET_INTERNAL_PHY, /* ucPhyType */
++ 0x01, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x01, /* numSwitchPorts */
++ BP_ENET_CONFIG_MDIO, /* usConfigType */
++ BP_NOT_DEFINED}, /* usReverseMii */
++ {BP_ENET_EXTERNAL_PHY, /* ucPhyType */
++ 0x02, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_GPIO_5_AL, /* usGpioPhyReset */
++ 0x01, /* numSwitchPorts */
++ BP_ENET_CONFIG_MDIO, /* usConfigType */
++ BP_NOT_DEFINED}}, /* usReverseMii */
++ {{BP_VOIP_NO_DSP}, /* ucDspType */
++ {BP_VOIP_NO_DSP}}, /* ucDspType */
++ BP_MEMORY_16MB_2_CHIP, /* usSdramSize */
++ BP_PSI_DEFAULT_SIZE, /* usPsiSize */
++ BP_NOT_DEFINED, /* usGpioRj11InnerPair */
++ BP_NOT_DEFINED, /* usGpioRj11OuterPair */
++ BP_GPIO_7_AH, /* usGpioPressAndHoldReset */
++ BP_NOT_DEFINED, /* usGpioPcmciaReset */
++ BP_NOT_DEFINED, /* usGpioUartRts */
++ BP_NOT_DEFINED, /* usGpioUartCts */
++ BP_NOT_DEFINED, /* usGpioLedAdsl */
++ BP_GPIO_2_AL, /* usGpioLedAdslFail */
++ BP_NOT_DEFINED, /* usGpioLedWireless */
++ BP_NOT_DEFINED, /* usGpioLedUsb */
++ BP_NOT_DEFINED, /* usGpioLedHpna */
++ BP_GPIO_3_AL, /* usGpioLedWanData */
++ BP_GPIO_3_AL, /* usGpioLedPpp */
++ BP_GPIO_4_AL, /* usGpioLedPppFail */
++ BP_GPIO_0_AL, /* usGpioLedBlPowerOn */
++ BP_NOT_DEFINED, /* usGpioLedBlAlarm */
++ BP_GPIO_3_AL, /* usGpioLedBlResetCfg */
++ BP_GPIO_1_AL, /* usGpioLedBlStop */
++ BP_NOT_DEFINED, /* usExtIntrWireless */
++ BP_NOT_DEFINED, /* usExtIntrAdslDyingGasp */
++ BP_NOT_DEFINED, /* usExtIntrHpna */
++ BP_NOT_DEFINED, /* usCsHpna */
++ BP_NOT_DEFINED, /* usAntInUseWireless */
++ BP_NOT_DEFINED, /* usGpioSesBtnWireless */
++ BP_NOT_DEFINED, /* usExtIntrSesBtnWireless */
++ BP_NOT_DEFINED /* usGpioLedSesWireless */
++};
++
++static BOARD_PARAMETERS g_bcm96348gw =
++{
++ "96348GW", /* szBoardId */
++ {{BP_ENET_INTERNAL_PHY, /* ucPhyType */
++ 0x01, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x01, /* numSwitchPorts */
++ BP_ENET_CONFIG_MDIO, /* usConfigType */
++ BP_NOT_DEFINED}, /* usReverseMii */
++ {BP_ENET_EXTERNAL_SWITCH, /* ucPhyType */
++ 0x00, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x03, /* numSwitchPorts */
++ BP_ENET_CONFIG_SPI_SSB_0, /* usConfigType */
++ BP_ENET_REVERSE_MII}}, /* usReverseMii */
++ {{BP_VOIP_DSP, /* ucDspType */
++ 0x00, /* ucDspAddress */
++ BP_EXT_INTR_2, /* usExtIntrVoip */
++ BP_GPIO_6_AH, /* usGpioVoipReset */
++ BP_GPIO_34_AH, /* usGpioVoipIntr */
++ BP_NOT_DEFINED, /* usGpioLedVoip */
++ BP_CS_2}, /* usCsVoip */
++ {BP_VOIP_NO_DSP}}, /* ucDspType */
++ BP_MEMORY_16MB_2_CHIP, /* usSdramSize */
++ BP_PSI_DEFAULT_SIZE, /* usPsiSize */
++ BP_NOT_DEFINED, /* usGpioRj11InnerPair */
++ BP_NOT_DEFINED, /* usGpioRj11OuterPair */
++ BP_GPIO_33_AL, /* usGpioPressAndHoldReset */
++ BP_NOT_DEFINED, /* usGpioPcmciaReset */
++ BP_NOT_DEFINED, /* usGpioUartRts */
++ BP_NOT_DEFINED, /* usGpioUartCts */
++ BP_NOT_DEFINED, /* usGpioLedAdsl */
++ BP_GPIO_2_AL, /* usGpioLedAdslFail */
++ BP_NOT_DEFINED, /* usGpioLedWireless */
++ BP_NOT_DEFINED, /* usGpioLedUsb */
++ BP_NOT_DEFINED, /* usGpioLedHpna */
++ BP_GPIO_3_AL, /* usGpioLedWanData */
++ BP_GPIO_3_AL, /* usGpioLedPpp */
++ BP_GPIO_4_AL, /* usGpioLedPppFail */
++ BP_GPIO_0_AL, /* usGpioLedBlPowerOn */
++ BP_NOT_DEFINED, /* usGpioLedBlAlarm */
++ BP_GPIO_3_AL, /* usGpioLedBlResetCfg */
++ BP_GPIO_1_AL, /* usGpioLedBlStop */
++ BP_NOT_DEFINED, /* usExtIntrWireless */
++ BP_HW_DEFINED, /* usExtIntrAdslDyingGasp */
++ BP_NOT_DEFINED, /* usExtIntrHpna */
++ BP_NOT_DEFINED, /* usCsHpna */
++ BP_WLAN_ANT_MAIN, /* usAntInUseWireless */
++ BP_NOT_DEFINED, /* BP_GPIO_35_AH, */ /* usGpioSesBtnWireless */
++ BP_NOT_DEFINED, /* BP_EXT_INTR_3, */ /* usExtIntrSesBtnWireless */
++ BP_NOT_DEFINED /* BP_GPIO_0_AL */ /* usGpioLedSesWireless */
++};
++
++
++static BOARD_PARAMETERS g_bcm96348gw_10 =
++{
++ "96348GW-10", /* szBoardId */
++ {{BP_ENET_INTERNAL_PHY, /* ucPhyType */
++ 0x01, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x01, /* numSwitchPorts */
++ BP_ENET_CONFIG_MDIO, /* usConfigType */
++ BP_NOT_DEFINED}, /* usReverseMii */
++ {BP_ENET_EXTERNAL_SWITCH, /* ucPhyType */
++ 0x00, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x03, /* numSwitchPorts */
++ BP_ENET_CONFIG_SPI_SSB_1, /* usConfigType */
++ BP_ENET_REVERSE_MII}}, /* usReverseMii */
++ {{BP_VOIP_DSP, /* ucDspType */
++ 0x00, /* ucDspAddress */
++ BP_EXT_INTR_2, /* usExtIntrVoip */
++ BP_GPIO_6_AH, /* usGpioVoipReset */
++ BP_GPIO_34_AH, /* usGpioVoipIntr */
++ BP_NOT_DEFINED, /* usGpioLedVoip */
++ BP_CS_2}, /* usCsVoip */
++ {BP_VOIP_NO_DSP}}, /* ucDspType */
++ BP_MEMORY_16MB_2_CHIP, /* usSdramSize */
++ BP_PSI_DEFAULT_SIZE, /* usPsiSize */
++ BP_NOT_DEFINED, /* usGpioRj11InnerPair */
++ BP_NOT_DEFINED, /* usGpioRj11OuterPair */
++ BP_GPIO_33_AL, /* usGpioPressAndHoldReset */
++ BP_NOT_DEFINED, /* usGpioPcmciaReset */
++ BP_NOT_DEFINED, /* usGpioUartRts */
++ BP_NOT_DEFINED, /* usGpioUartCts */
++ BP_NOT_DEFINED, /* usGpioLedAdsl */
++ BP_GPIO_2_AL, /* usGpioLedAdslFail */
++ BP_NOT_DEFINED, /* usGpioLedWireless */
++ BP_NOT_DEFINED, /* usGpioLedUsb */
++ BP_NOT_DEFINED, /* usGpioLedHpna */
++ BP_GPIO_3_AL, /* usGpioLedWanData */
++ BP_GPIO_3_AL, /* usGpioLedPpp */
++ BP_GPIO_4_AL, /* usGpioLedPppFail */
++ BP_GPIO_0_AL, /* usGpioLedBlPowerOn */
++ BP_NOT_DEFINED, /* usGpioLedBlAlarm */
++ BP_GPIO_3_AL, /* usGpioLedBlResetCfg */
++ BP_GPIO_1_AL, /* usGpioLedBlStop */
++ BP_NOT_DEFINED, /* usExtIntrWireless */
++ BP_HW_DEFINED, /* usExtIntrAdslDyingGasp */
++ BP_NOT_DEFINED, /* usExtIntrHpna */
++ BP_NOT_DEFINED, /* usCsHpna */
++ BP_WLAN_ANT_MAIN, /* usAntInUseWireless */
++ BP_NOT_DEFINED, /* usGpioSesBtnWireless */
++ BP_NOT_DEFINED, /* usExtIntrSesBtnWireless */
++ BP_NOT_DEFINED /* usGpioLedSesWireless */
++};
++
++static BOARD_PARAMETERS g_bcm96348gw_11 =
++{
++ "96348GW-11", /* szBoardId */
++ {{BP_ENET_NO_PHY}, /* ucPhyType */
++ {BP_ENET_EXTERNAL_SWITCH, /* ucPhyType */
++ 0x00, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x04, /* numSwitchPorts */
++ BP_ENET_CONFIG_SPI_SSB_1, /* usConfigType */
++ BP_ENET_REVERSE_MII}}, /* usReverseMii */
++ {{BP_VOIP_NO_DSP}, /* ucDspType */
++ {BP_VOIP_NO_DSP}}, /* ucDspType */
++ BP_MEMORY_16MB_2_CHIP, /* usSdramSize */
++ BP_PSI_DEFAULT_SIZE, /* usPsiSize */
++ BP_NOT_DEFINED, /* usGpioRj11InnerPair */
++ BP_NOT_DEFINED, /* usGpioRj11OuterPair */
++ BP_GPIO_33_AL, /* usGpioPressAndHoldReset */
++ BP_NOT_DEFINED, /* usGpioPcmciaReset */
++ BP_NOT_DEFINED, /* usGpioUartRts */
++ BP_NOT_DEFINED, /* usGpioUartCts */
++ BP_NOT_DEFINED, /* usGpioLedAdsl */
++ BP_GPIO_2_AL, /* usGpioLedAdslFail */
++ BP_NOT_DEFINED, /* usGpioLedWireless */
++ BP_NOT_DEFINED, /* usGpioLedUsb */
++ BP_NOT_DEFINED, /* usGpioLedHpna */
++ BP_GPIO_3_AL, /* usGpioLedWanData */
++ BP_GPIO_3_AL, /* usGpioLedPpp */
++ BP_GPIO_4_AL, /* usGpioLedPppFail */
++ BP_GPIO_0_AL, /* usGpioLedBlPowerOn */
++ BP_NOT_DEFINED, /* usGpioLedBlAlarm */
++ BP_GPIO_3_AL, /* usGpioLedBlResetCfg */
++ BP_GPIO_1_AL, /* usGpioLedBlStop */
++ BP_NOT_DEFINED, /* usExtIntrWireless */
++ BP_HW_DEFINED, /* usExtIntrAdslDyingGasp */
++ BP_NOT_DEFINED, /* usExtIntrHpna */
++ BP_NOT_DEFINED, /* usCsHpna */
++ BP_NOT_DEFINED, /* usAntInUseWireless */
++ BP_NOT_DEFINED, /* usGpioSesBtnWireless */
++ BP_NOT_DEFINED, /* usExtIntrSesBtnWireless */
++ BP_NOT_DEFINED /* usGpioLedSesWireless */
++};
++
++static BOARD_PARAMETERS g_bcm96348sv =
++{
++ "96348SV", /* szBoardId */
++ {{BP_ENET_INTERNAL_PHY, /* ucPhyType */
++ 0x01, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x01, /* numSwitchPorts */
++ BP_ENET_CONFIG_MDIO, /* usConfigType */
++ BP_NOT_DEFINED}, /* usReverseMii */
++ {BP_ENET_EXTERNAL_PHY, /* ucPhyType */
++ 0x1f, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x01, /* numSwitchPorts */
++ BP_ENET_CONFIG_MDIO, /* usConfigType */
++ BP_NOT_DEFINED}}, /* usReverseMii */
++ {{BP_VOIP_NO_DSP}, /* ucDspType */
++ {BP_VOIP_NO_DSP}}, /* ucDspType */
++ BP_MEMORY_32MB_2_CHIP, /* usSdramSize */
++ BP_PSI_DEFAULT_SIZE, /* usPsiSize */
++ BP_NOT_DEFINED, /* usGpioRj11InnerPair */
++ BP_NOT_DEFINED, /* usGpioRj11OuterPair */
++ BP_NOT_DEFINED, /* usGpioPressAndHoldReset */
++ BP_NOT_DEFINED, /* usGpioPcmciaReset */
++ BP_NOT_DEFINED, /* usGpioUartRts */
++ BP_NOT_DEFINED, /* usGpioUartCts */
++ BP_NOT_DEFINED, /* usGpioLedAdsl */
++ BP_NOT_DEFINED, /* usGpioLedAdslFail */
++ BP_NOT_DEFINED, /* usGpioLedWireless */
++ BP_NOT_DEFINED, /* usGpioLedUsb */
++ BP_NOT_DEFINED, /* usGpioLedHpna */
++ BP_NOT_DEFINED, /* usGpioLedWanData */
++ BP_NOT_DEFINED, /* usGpioLedPpp */
++ BP_NOT_DEFINED, /* usGpioLedPppFail */
++ BP_NOT_DEFINED, /* usGpioLedBlPowerOn */
++ BP_NOT_DEFINED, /* usGpioLedBlAlarm */
++ BP_NOT_DEFINED, /* usGpioLedBlResetCfg */
++ BP_NOT_DEFINED, /* usGpioLedBlStop */
++ BP_NOT_DEFINED, /* usExtIntrWireless */
++ BP_HW_DEFINED, /* usExtIntrAdslDyingGasp */
++ BP_NOT_DEFINED, /* usExtIntrHpna */
++ BP_NOT_DEFINED, /* usCsHpna */
++ BP_NOT_DEFINED, /* usAntInUseWireless */
++ BP_NOT_DEFINED, /* usGpioSesBtnWireless */
++ BP_NOT_DEFINED, /* usExtIntrSesBtnWireless */
++ BP_NOT_DEFINED /* usGpioLedSesWireless */
++};
++
++
++static BOARD_PARAMETERS g_bcm96348gw_dualDsp =
++{
++ "96348GW-DualDSP", /* szBoardId */
++ {{BP_ENET_INTERNAL_PHY, /* ucPhyType */
++ 0x01, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x01, /* numSwitchPorts */
++ BP_ENET_CONFIG_MDIO, /* usConfigType */
++ BP_NOT_DEFINED}, /* usReverseMii */
++ {BP_ENET_EXTERNAL_SWITCH, /* ucPhyType */
++ 0x00, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x03, /* numSwitchPorts */
++ BP_ENET_CONFIG_SPI_SSB_1, /* usConfigType */
++ BP_ENET_REVERSE_MII}}, /* usReverseMii */
++ {{BP_VOIP_DSP, /* ucDspType */
++ 0x00, /* ucDspAddress */
++ BP_EXT_INTR_2, /* usExtIntrVoip */
++ BP_UNEQUIPPED, /* usGpioVoipReset */
++ BP_GPIO_34_AH, /* usGpioVoipIntr */
++ BP_NOT_DEFINED, /* usGpioLedVoip */
++ BP_CS_2}, /* usCsVoip */
++ {BP_VOIP_DSP, /* ucDspType */
++ 0x01, /* ucDspAddress */
++ BP_EXT_INTR_3, /* usExtIntrVoip */
++ BP_UNEQUIPPED , /* usGpioVoipReset */
++ BP_GPIO_35_AH, /* usGpioVoipIntr */
++ BP_NOT_DEFINED, /* usGpioLedVoip */
++ BP_CS_3}}, /* usCsVoip */
++ BP_MEMORY_16MB_2_CHIP, /* usSdramSize */
++ BP_PSI_DEFAULT_SIZE, /* usPsiSize */
++ BP_NOT_DEFINED, /* usGpioRj11InnerPair */
++ BP_NOT_DEFINED, /* usGpioRj11OuterPair */
++ BP_GPIO_33_AL, /* usGpioPressAndHoldReset */
++ BP_NOT_DEFINED, /* usGpioPcmciaReset */
++ BP_NOT_DEFINED, /* usGpioUartRts */
++ BP_NOT_DEFINED, /* usGpioUartCts */
++ BP_NOT_DEFINED, /* usGpioLedAdsl */
++ BP_GPIO_2_AL, /* usGpioLedAdslFail */
++ BP_NOT_DEFINED, /* usGpioLedWireless */
++ BP_NOT_DEFINED, /* usGpioLedUsb */
++ BP_NOT_DEFINED, /* usGpioLedHpna */
++ BP_GPIO_3_AL, /* usGpioLedWanData */
++ BP_GPIO_3_AL, /* usGpioLedPpp */
++ BP_GPIO_4_AL, /* usGpioLedPppFail */
++ BP_GPIO_0_AL, /* usGpioLedBlPowerOn */
++ BP_NOT_DEFINED, /* usGpioLedBlAlarm */
++ BP_GPIO_3_AL, /* usGpioLedBlResetCfg */
++ BP_GPIO_1_AL, /* usGpioLedBlStop */
++ BP_NOT_DEFINED, /* usExtIntrWireless */
++ BP_HW_DEFINED, /* usExtIntrAdslDyingGasp */
++ BP_NOT_DEFINED, /* usExtIntrHpna */
++ BP_NOT_DEFINED, /* usCsHpna */
++ BP_WLAN_ANT_MAIN, /* usAntInUseWireless */
++ BP_NOT_DEFINED, /* usGpioSesBtnWireless */
++ BP_NOT_DEFINED, /* usExtIntrSesBtnWireless */
++ BP_NOT_DEFINED /* usGpioLedSesWireless */
++};
++
++
++static BOARD_PARAMETERS g_bcmCustom_01 =
++{
++ "BCMCUST_01", /* szBoardId */
++ {{BP_ENET_INTERNAL_PHY, /* ucPhyType */
++ 0x01, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x01, /* numSwitchPorts */
++ BP_ENET_CONFIG_MDIO, /* usConfigType */
++ BP_NOT_DEFINED}, /* usReverseMii */
++ {BP_ENET_NO_PHY, /* ucPhyType */
++ 0x00, /* ucPhyAddress */
++ BP_NOT_DEFINED, /* usGpioPhySpiSck */
++ BP_NOT_DEFINED, /* usGpioPhySpiSs */
++ BP_NOT_DEFINED, /* usGpioPhySpiMosi */
++ BP_NOT_DEFINED, /* usGpioPhySpiMiso */
++ BP_NOT_DEFINED, /* usGpioPhyReset */
++ 0x01, /* numSwitchPorts */
++ BP_ENET_CONFIG_SPI_SSB_1, /* usConfigType */
++ BP_ENET_REVERSE_MII}}, /* usReverseMii */
++ {{BP_VOIP_DSP, /* ucDspType */
++ 0x00, /* ucDspAddress */
++ BP_EXT_INTR_2, /* usExtIntrVoip */
++ BP_GPIO_36_AH, /* usGpioVoipReset */
++ BP_GPIO_34_AL, /* usGpioVoipIntr */
++ BP_NOT_DEFINED, /* usGpioLedVoip */
++ BP_CS_2}, /* usCsVoip */
++ {BP_VOIP_NO_DSP}}, /* ucDspType */
++ BP_MEMORY_16MB_2_CHIP, /* usSdramSize */
++ BP_PSI_DEFAULT_SIZE, /* usPsiSize */
++ BP_NOT_DEFINED, /* usGpioRj11InnerPair */
++ BP_NOT_DEFINED, /* usGpioRj11OuterPair */
++ BP_GPIO_33_AL, /* usGpioPressAndHoldReset */
++ BP_NOT_DEFINED, /* usGpioPcmciaReset */
++ BP_NOT_DEFINED, /* usGpioUartRts */
++ BP_NOT_DEFINED, /* usGpioUartCts */
++ BP_NOT_DEFINED, /* usGpioLedAdsl */
++ BP_GPIO_2_AL, /* usGpioLedAdslFail */
++ BP_NOT_DEFINED, /* usGpioLedWireless */
++ BP_NOT_DEFINED, /* usGpioLedUsb */
++ BP_NOT_DEFINED, /* usGpioLedHpna */
++ BP_GPIO_3_AL, /* usGpioLedWanData */
++ BP_GPIO_3_AL, /* usGpioLedPpp */
++ BP_GPIO_4_AL, /* usGpioLedPppFail */
++ BP_GPIO_0_AL, /* usGpioLedBlPowerOn */
++ BP_NOT_DEFINED, /* usGpioLedBlAlarm */
++ BP_GPIO_3_AL, /* usGpioLedBlResetCfg */
++ BP_GPIO_1_AL, /* usGpioLedBlStop */
++ BP_NOT_DEFINED, /* usExtIntrWireless */
++ BP_NOT_DEFINED, /* usExtIntrAdslDyingGasp */
++ BP_NOT_DEFINED, /* usExtIntrHpna */
++ BP_NOT_DEFINED, /* usCsHpna */
++ BP_NOT_DEFINED, /* usAntInUseWireless */
++ BP_NOT_DEFINED, /* usGpioSesBtnWireless */
++ BP_NOT_DEFINED, /* usExtIntrSesBtnWireless */
++ BP_NOT_DEFINED /* usGpioLedSesWireless */
++};
++
++static PBOARD_PARAMETERS g_BoardParms[] =
++ {&g_bcm96348r, &g_bcm96348lv, &g_bcm96348gw, &g_bcm96348gw_10,
++ &g_bcm96348gw_11, &g_bcm96348sv, &g_bcm96348gw_dualDsp,
++ &g_bcmCustom_01, 0};
++#endif
++
++static PBOARD_PARAMETERS g_pCurrentBp = 0;
++
++/**************************************************************************
++ * Name : bpstrcmp
++ *
++ * Description: String compare for this file so it does not depend on an OS.
++ * (Linux kernel and CFE share this source file.)
++ *
++ * Parameters : [IN] dest - destination string
++ * [IN] src - source string
++ *
++ * Returns : -1 - dest < src, 1 - dest > src, 0 dest == src
++ ***************************************************************************/
++static int bpstrcmp(const char *dest,const char *src);
++static int bpstrcmp(const char *dest,const char *src)
++{
++ while (*src && *dest)
++ {
++ if (*dest < *src) return -1;
++ if (*dest > *src) return 1;
++ dest++;
++ src++;
++ }
++
++ if (*dest && !*src) return 1;
++ if (!*dest && *src) return -1;
++ return 0;
++} /* bpstrcmp */
++
++/**************************************************************************
++ * Name : BpGetVoipDspConfig
++ *
++ * Description: Gets the DSP configuration from the board parameter
++ * structure for a given DSP index.
++ *
++ * Parameters : [IN] dspNum - DSP index (number)
++ *
++ * Returns : Pointer to DSP configuration block if found/valid, NULL
++ * otherwise.
++ ***************************************************************************/
++VOIP_DSP_INFO *BpGetVoipDspConfig( unsigned char dspNum );
++VOIP_DSP_INFO *BpGetVoipDspConfig( unsigned char dspNum )
++{
++ VOIP_DSP_INFO *pDspConfig = 0;
++ int i;
++
++ if( g_pCurrentBp )
++ {
++ for( i = 0 ; i < BP_MAX_VOIP_DSP ; i++ )
++ {
++ if( g_pCurrentBp->VoIPDspInfo[i].ucDspType != BP_VOIP_NO_DSP &&
++ g_pCurrentBp->VoIPDspInfo[i].ucDspAddress == dspNum )
++ {
++ pDspConfig = &g_pCurrentBp->VoIPDspInfo[i];
++ break;
++ }
++ }
++ }
++
++ return pDspConfig;
++}
++
++
++/**************************************************************************
++ * Name : BpSetBoardId
++ *
++ * Description: This function find the BOARD_PARAMETERS structure for the
++ * specified board id string and assigns it to a global, static
++ * variable.
++ *
++ * Parameters : [IN] pszBoardId - Board id string that is saved into NVRAM.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_FOUND - Error, board id input string does not
++ * have a board parameters configuration record.
++ ***************************************************************************/
++int BpSetBoardId( char *pszBoardId )
++{
++ int nRet = BP_BOARD_ID_NOT_FOUND;
++ PBOARD_PARAMETERS *ppBp;
++
++ for( ppBp = g_BoardParms; *ppBp; ppBp++ )
++ {
++ if( !bpstrcmp((*ppBp)->szBoardId, pszBoardId) )
++ {
++ g_pCurrentBp = *ppBp;
++ nRet = BP_SUCCESS;
++ break;
++ }
++ }
++
++ return( nRet );
++} /* BpSetBoardId */
++
++/**************************************************************************
++ * Name : BpGetBoardIds
++ *
++ * Description: This function returns all of the supported board id strings.
++ *
++ * Parameters : [OUT] pszBoardIds - Address of a buffer that the board id
++ * strings are returned in. Each id starts at BP_BOARD_ID_LEN
++ * boundary.
++ * [IN] nBoardIdsSize - Number of BP_BOARD_ID_LEN elements that
++ * were allocated in pszBoardIds.
++ *
++ * Returns : Number of board id strings returned.
++ ***************************************************************************/
++int BpGetBoardIds( char *pszBoardIds, int nBoardIdsSize )
++{
++ PBOARD_PARAMETERS *ppBp;
++ int i;
++ char *src;
++ char *dest;
++
++ for( i = 0, ppBp = g_BoardParms; *ppBp && nBoardIdsSize;
++ i++, ppBp++, nBoardIdsSize--, pszBoardIds += BP_BOARD_ID_LEN )
++ {
++ dest = pszBoardIds;
++ src = (*ppBp)->szBoardId;
++ while( *src )
++ *dest++ = *src++;
++ *dest = '\0';
++ }
++
++ return( i );
++} /* BpGetBoardIds */
++
++/**************************************************************************
++ * Name : BpGetEthernetMacInfo
++ *
++ * Description: This function returns all of the supported board id strings.
++ *
++ * Parameters : [OUT] pEnetInfos - Address of an array of ETHERNET_MAC_INFO
++ * buffers.
++ * [IN] nNumEnetInfos - Number of ETHERNET_MAC_INFO elements that
++ * are pointed to by pEnetInfos.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ ***************************************************************************/
++int BpGetEthernetMacInfo( PETHERNET_MAC_INFO pEnetInfos, int nNumEnetInfos )
++{
++ int i, nRet;
++
++ if( g_pCurrentBp )
++ {
++ for( i = 0; i < nNumEnetInfos; i++, pEnetInfos++ )
++ {
++ if( i < BP_MAX_ENET_MACS )
++ {
++ unsigned char *src = (unsigned char *)
++ &g_pCurrentBp->EnetMacInfos[i];
++ unsigned char *dest = (unsigned char *) pEnetInfos;
++ int len = sizeof(ETHERNET_MAC_INFO);
++ while( len-- )
++ *dest++ = *src++;
++ }
++ else
++ pEnetInfos->ucPhyType = BP_ENET_NO_PHY;
++ }
++
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ for( i = 0; i < nNumEnetInfos; i++, pEnetInfos++ )
++ pEnetInfos->ucPhyType = BP_ENET_NO_PHY;
++
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetEthernetMacInfo */
++
++/**************************************************************************
++ * Name : BpGetSdramSize
++ *
++ * Description: This function returns a constant that describees the board's
++ * SDRAM type and size.
++ *
++ * Parameters : [OUT] pulSdramSize - Address of short word that the SDRAM size
++ * is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ ***************************************************************************/
++int BpGetSdramSize( unsigned long *pulSdramSize )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pulSdramSize = g_pCurrentBp->usSdramSize;
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ *pulSdramSize = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetSdramSize */
++
++/**************************************************************************
++ * Name : BpGetPsiSize
++ *
++ * Description: This function returns the persistent storage size in K bytes.
++ *
++ * Parameters : [OUT] pulPsiSize - Address of short word that the persistent
++ * storage size is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ ***************************************************************************/
++int BpGetPsiSize( unsigned long *pulPsiSize )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pulPsiSize = g_pCurrentBp->usPsiSize;
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ *pulPsiSize = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetPsiSize */
++
++/**************************************************************************
++ * Name : BpGetRj11InnerOuterPairGpios
++ *
++ * Description: This function returns the GPIO pin assignments for changing
++ * between the RJ11 inner pair and RJ11 outer pair.
++ *
++ * Parameters : [OUT] pusInner - Address of short word that the RJ11 inner pair
++ * GPIO pin is returned in.
++ * [OUT] pusOuter - Address of short word that the RJ11 outer pair
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, values are returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetRj11InnerOuterPairGpios( unsigned short *pusInner,
++ unsigned short *pusOuter )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusInner = g_pCurrentBp->usGpioRj11InnerPair;
++ *pusOuter = g_pCurrentBp->usGpioRj11OuterPair;
++
++ if( g_pCurrentBp->usGpioRj11InnerPair != BP_NOT_DEFINED &&
++ g_pCurrentBp->usGpioRj11OuterPair != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusInner = *pusOuter = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetRj11InnerOuterPairGpios */
++
++/**************************************************************************
++ * Name : BpGetPressAndHoldResetGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the press
++ * and hold reset button.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the press and hold
++ * reset button GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetPressAndHoldResetGpio( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usGpioPressAndHoldReset;
++
++ if( g_pCurrentBp->usGpioPressAndHoldReset != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetPressAndHoldResetGpio */
++
++/**************************************************************************
++ * Name : BpGetVoipResetGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the VOIP
++ * Reset operation.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the VOIP reset
++ * GPIO pin is returned in.
++ * [IN] dspNum - Address of the DSP to query.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetVoipResetGpio( unsigned char dspNum, unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ VOIP_DSP_INFO *pDspInfo = BpGetVoipDspConfig( dspNum );
++
++ if( pDspInfo )
++ {
++ *pusValue = pDspInfo->usGpioVoipReset;
++
++ if( *pusValue != BP_NOT_DEFINED ||
++ *pusValue == BP_UNEQUIPPED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_FOUND;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetVoipResetGpio */
++
++/**************************************************************************
++ * Name : BpGetVoipIntrGpio
++ *
++ * Description: This function returns the GPIO pin assignment for VoIP interrupt.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the VOIP interrupt
++ * GPIO pin is returned in.
++ * [IN] dspNum - Address of the DSP to query.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetVoipIntrGpio( unsigned char dspNum, unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ VOIP_DSP_INFO *pDspInfo = BpGetVoipDspConfig( dspNum );
++
++ if( pDspInfo )
++ {
++ *pusValue = pDspInfo->usGpioVoipIntr;
++
++ if( *pusValue != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_FOUND;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetVoipIntrGpio */
++
++/**************************************************************************
++ * Name : BpGetPcmciaResetGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the PCMCIA
++ * Reset operation.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the PCMCIA reset
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetPcmciaResetGpio( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usGpioPcmciaReset;
++
++ if( g_pCurrentBp->usGpioPcmciaReset != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetPcmciaResetGpio */
++
++/**************************************************************************
++ * Name : BpGetUartRtsCtsGpios
++ *
++ * Description: This function returns the GPIO pin assignments for RTS and CTS
++ * UART signals.
++ *
++ * Parameters : [OUT] pusRts - Address of short word that the UART RTS GPIO
++ * pin is returned in.
++ * [OUT] pusCts - Address of short word that the UART CTS GPIO
++ * pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, values are returned.
++ * BP_BOARD_ID_NOT_SET - Error, board id input string does not
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetRtsCtsUartGpios( unsigned short *pusRts, unsigned short *pusCts )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusRts = g_pCurrentBp->usGpioUartRts;
++ *pusCts = g_pCurrentBp->usGpioUartCts;
++
++ if( g_pCurrentBp->usGpioUartRts != BP_NOT_DEFINED &&
++ g_pCurrentBp->usGpioUartCts != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusRts = *pusCts = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetUartRtsCtsGpios */
++
++/**************************************************************************
++ * Name : BpGetAdslLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the ADSL
++ * LED.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the ADSL LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetAdslLedGpio( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usGpioLedAdsl;
++
++ if( g_pCurrentBp->usGpioLedAdsl != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetAdslLedGpio */
++
++/**************************************************************************
++ * Name : BpGetAdslFailLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the ADSL
++ * LED that is used when there is a DSL connection failure.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the ADSL LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetAdslFailLedGpio( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usGpioLedAdslFail;
++
++ if( g_pCurrentBp->usGpioLedAdslFail != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetAdslFailLedGpio */
++
++/**************************************************************************
++ * Name : BpGetWirelessLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the Wireless
++ * LED.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the Wireless LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetWirelessLedGpio( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usGpioLedWireless;
++
++ if( g_pCurrentBp->usGpioLedWireless != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetWirelessLedGpio */
++
++/**************************************************************************
++ * Name : BpGetWirelessAntInUse
++ *
++ * Description: This function returns the antennas in use for wireless
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the Wireless Antenna
++ * is in use.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetWirelessAntInUse( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usAntInUseWireless;
++
++ if( g_pCurrentBp->usAntInUseWireless != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetWirelessAntInUse */
++
++/**************************************************************************
++ * Name : BpGetWirelessSesBtnGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the Wireless
++ * Ses Button.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the Wireless LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetWirelessSesBtnGpio( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usGpioSesBtnWireless;
++
++ if( g_pCurrentBp->usGpioSesBtnWireless != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetWirelessSesBtnGpio */
++
++/**************************************************************************
++ * Name : BpGetWirelessSesExtIntr
++ *
++ * Description: This function returns the external interrupt number for the
++ * Wireless Ses Button.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the Wireless Ses
++ * external interrup is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetWirelessSesExtIntr( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usExtIntrSesBtnWireless;
++
++ if( g_pCurrentBp->usExtIntrSesBtnWireless != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++
++} /* BpGetWirelessSesExtIntr */
++
++/**************************************************************************
++ * Name : BpGetWirelessSesLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the Wireless
++ * Ses Led.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the Wireless Ses
++ * Led GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetWirelessSesLedGpio( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usGpioLedSesWireless;
++
++ if( g_pCurrentBp->usGpioLedSesWireless != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++
++} /* BpGetWirelessSesLedGpio */
++
++/**************************************************************************
++ * Name : BpGetUsbLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the USB
++ * LED.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the USB LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetUsbLedGpio( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usGpioLedUsb;
++
++ if( g_pCurrentBp->usGpioLedUsb != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetUsbLedGpio */
++
++/**************************************************************************
++ * Name : BpGetHpnaLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the HPNA
++ * LED.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the HPNA LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetHpnaLedGpio( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usGpioLedHpna;
++
++ if( g_pCurrentBp->usGpioLedHpna != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetHpnaLedGpio */
++
++/**************************************************************************
++ * Name : BpGetWanDataLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the WAN Data
++ * LED.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the WAN Data LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetWanDataLedGpio( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usGpioLedWanData;
++
++ if( g_pCurrentBp->usGpioLedWanData != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetWanDataLedGpio */
++
++/**************************************************************************
++ * Name : BpGetPppLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the PPP
++ * LED.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the PPP LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetPppLedGpio( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usGpioLedPpp;
++
++ if( g_pCurrentBp->usGpioLedPpp != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetPppLedGpio */
++
++/**************************************************************************
++ * Name : BpGetPppFailLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the PPP
++ * LED that is used when there is a PPP connection failure.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the PPP LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetPppFailLedGpio( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usGpioLedPppFail;
++
++ if( g_pCurrentBp->usGpioLedPppFail != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetPppFailLedGpio */
++
++/**************************************************************************
++ * Name : BpGetBootloaderPowerOnLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the power
++ * on LED that is set by the bootloader.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the alarm LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetBootloaderPowerOnLedGpio( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usGpioLedBlPowerOn;
++
++ if( g_pCurrentBp->usGpioLedBlPowerOn != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetBootloaderPowerOn */
++
++/**************************************************************************
++ * Name : BpGetBootloaderAlarmLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the alarm
++ * LED that is set by the bootloader.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the alarm LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetBootloaderAlarmLedGpio( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usGpioLedBlAlarm;
++
++ if( g_pCurrentBp->usGpioLedBlAlarm != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetBootloaderAlarmLedGpio */
++
++/**************************************************************************
++ * Name : BpGetBootloaderResetCfgLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the reset
++ * configuration LED that is set by the bootloader.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the reset
++ * configuration LED GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetBootloaderResetCfgLedGpio( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usGpioLedBlResetCfg;
++
++ if( g_pCurrentBp->usGpioLedBlResetCfg != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetBootloaderResetCfgLedGpio */
++
++/**************************************************************************
++ * Name : BpGetBootloaderStopLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the break
++ * into bootloader LED that is set by the bootloader.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the break into
++ * bootloader LED GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetBootloaderStopLedGpio( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pusValue = g_pCurrentBp->usGpioLedBlStop;
++
++ if( g_pCurrentBp->usGpioLedBlStop != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetBootloaderStopLedGpio */
++
++/**************************************************************************
++ * Name : BpGetVoipLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the VOIP
++ * LED.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the VOIP LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ *
++ * Note : The VoIP structure would allow for having one LED per DSP
++ * however, the board initialization function assumes only one
++ * LED per functionality (ie one LED for VoIP). Therefore in
++ * order to keep this tidy and simple we do not make usage of the
++ * one-LED-per-DSP function. Instead, we assume that the LED for
++ * VoIP is unique and associated with DSP 0 (always present on
++ * any VoIP platform). If changing this to a LED-per-DSP function
++ * then one need to update the board initialization driver in
++ * bcmdrivers\opensource\char\board\bcm963xx\impl1
++ ***************************************************************************/
++int BpGetVoipLedGpio( unsigned short *pusValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ VOIP_DSP_INFO *pDspInfo = BpGetVoipDspConfig( 0 );
++
++ if( pDspInfo )
++ {
++ *pusValue = pDspInfo->usGpioLedVoip;
++
++ if( *pusValue != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_FOUND;
++ }
++ }
++ else
++ {
++ *pusValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetVoipLedGpio */
++
++/**************************************************************************
++ * Name : BpGetWirelessExtIntr
++ *
++ * Description: This function returns the Wireless external interrupt number.
++ *
++ * Parameters : [OUT] pulValue - Address of short word that the wireless
++ * external interrupt number is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetWirelessExtIntr( unsigned long *pulValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pulValue = g_pCurrentBp->usExtIntrWireless;
++
++ if( g_pCurrentBp->usExtIntrWireless != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pulValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetWirelessExtIntr */
++
++/**************************************************************************
++ * Name : BpGetAdslDyingGaspExtIntr
++ *
++ * Description: This function returns the ADSL Dying Gasp external interrupt
++ * number.
++ *
++ * Parameters : [OUT] pulValue - Address of short word that the ADSL Dying Gasp
++ * external interrupt number is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetAdslDyingGaspExtIntr( unsigned long *pulValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pulValue = g_pCurrentBp->usExtIntrAdslDyingGasp;
++
++ if( g_pCurrentBp->usExtIntrAdslDyingGasp != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pulValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetAdslDyingGaspExtIntr */
++
++/**************************************************************************
++ * Name : BpGetVoipExtIntr
++ *
++ * Description: This function returns the VOIP external interrupt number.
++ *
++ * Parameters : [OUT] pulValue - Address of short word that the VOIP
++ * external interrupt number is returned in.
++ * [IN] dspNum - Address of the DSP to query.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetVoipExtIntr( unsigned char dspNum, unsigned long *pulValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ VOIP_DSP_INFO *pDspInfo = BpGetVoipDspConfig( dspNum );
++
++ if( pDspInfo )
++ {
++ *pulValue = pDspInfo->usExtIntrVoip;
++
++ if( *pulValue != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pulValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_FOUND;
++ }
++ }
++ else
++ {
++ *pulValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetVoipExtIntr */
++
++/**************************************************************************
++ * Name : BpGetHpnaExtIntr
++ *
++ * Description: This function returns the HPNA external interrupt number.
++ *
++ * Parameters : [OUT] pulValue - Address of short word that the HPNA
++ * external interrupt number is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetHpnaExtIntr( unsigned long *pulValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pulValue = g_pCurrentBp->usExtIntrHpna;
++
++ if( g_pCurrentBp->usExtIntrHpna != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pulValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetHpnaExtIntr */
++
++/**************************************************************************
++ * Name : BpGetHpnaChipSelect
++ *
++ * Description: This function returns the HPNA chip select number.
++ *
++ * Parameters : [OUT] pulValue - Address of short word that the HPNA
++ * chip select number is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetHpnaChipSelect( unsigned long *pulValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ *pulValue = g_pCurrentBp->usCsHpna;
++
++ if( g_pCurrentBp->usCsHpna != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pulValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetHpnaChipSelect */
++
++/**************************************************************************
++ * Name : BpGetVoipChipSelect
++ *
++ * Description: This function returns the VOIP chip select number.
++ *
++ * Parameters : [OUT] pulValue - Address of short word that the VOIP
++ * chip select number is returned in.
++ * [IN] dspNum - Address of the DSP to query.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetVoipChipSelect( unsigned char dspNum, unsigned long *pulValue )
++{
++ int nRet;
++
++ if( g_pCurrentBp )
++ {
++ VOIP_DSP_INFO *pDspInfo = BpGetVoipDspConfig( dspNum );
++
++ if( pDspInfo )
++ {
++ *pulValue = pDspInfo->usCsVoip;
++
++ if( *pulValue != BP_NOT_DEFINED )
++ {
++ nRet = BP_SUCCESS;
++ }
++ else
++ {
++ nRet = BP_VALUE_NOT_DEFINED;
++ }
++ }
++ else
++ {
++ *pulValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_FOUND;
++ }
++ }
++ else
++ {
++ *pulValue = BP_NOT_DEFINED;
++ nRet = BP_BOARD_ID_NOT_SET;
++ }
++
++ return( nRet );
++} /* BpGetVoipChipSelect */
++
+diff -urN linux.old/arch/mips/bcm963xx/boardparms.h linux.dev/arch/mips/bcm963xx/boardparms.h
+--- linux.old/arch/mips/bcm963xx/boardparms.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/boardparms.h 2006-08-25 00:39:38.000000000 +0200
+@@ -0,0 +1,758 @@
++/*
++<:copyright-gpl
++
++ Copyright 2003 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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.
++
++:>
++*/
++/**************************************************************************
++ * File Name : boardparms.h
++ *
++ * Description: This file contains definitions and function prototypes for
++ * the BCM63xx board parameter access functions.
++ *
++ * Updates : 07/14/2003 Created.
++ ***************************************************************************/
++
++#if !defined(_BOARDPARMS_H)
++#define _BOARDPARMS_H
++
++/* Return codes. */
++#define BP_SUCCESS 0
++#define BP_BOARD_ID_NOT_FOUND 1
++#define BP_VALUE_NOT_DEFINED 2
++#define BP_BOARD_ID_NOT_SET 3
++
++/* Values for BpGetSdramSize. */
++#define BP_MEMORY_8MB_1_CHIP 0
++#define BP_MEMORY_16MB_1_CHIP 1
++#define BP_MEMORY_32MB_1_CHIP 2
++#define BP_MEMORY_64MB_2_CHIP 3
++#define BP_MEMORY_32MB_2_CHIP 4
++#define BP_MEMORY_16MB_2_CHIP 5
++
++/* Values for EthernetMacInfo PhyType. */
++#define BP_ENET_NO_PHY 0
++#define BP_ENET_INTERNAL_PHY 1
++#define BP_ENET_EXTERNAL_PHY 2
++#define BP_ENET_EXTERNAL_SWITCH 3
++
++/* Values for EthernetMacInfo Configuration type. */
++#define BP_ENET_CONFIG_MDIO 0 /* Internal PHY, External PHY, Switch+(no GPIO, no SPI, no MDIO Pseudo phy */
++#define BP_ENET_CONFIG_GPIO 1 /* Bcm96345GW board + Bcm5325M/E */
++#define BP_ENET_CONFIG_MDIO_PSEUDO_PHY 2 /* Bcm96348GW board + Bcm5325E */
++#define BP_ENET_CONFIG_SPI_SSB_0 3 /* Bcm96348GW board + Bcm5325M/E */
++#define BP_ENET_CONFIG_SPI_SSB_1 4 /* Bcm96348GW board + Bcm5325M/E */
++#define BP_ENET_CONFIG_SPI_SSB_2 5 /* Bcm96348GW board + Bcm5325M/E */
++#define BP_ENET_CONFIG_SPI_SSB_3 6 /* Bcm96348GW board + Bcm5325M/E */
++
++/* Values for EthernetMacInfo Reverse MII. */
++#define BP_ENET_NO_REVERSE_MII 0
++#define BP_ENET_REVERSE_MII 1
++
++/* Values for VoIPDSPInfo DSPType. */
++#define BP_VOIP_NO_DSP 0
++#define BP_VOIP_DSP 1
++
++
++/* Values for GPIO pin assignments (AH = Active High, AL = Active Low). */
++#define BP_ACTIVE_MASK 0x8000
++#define BP_ACTIVE_HIGH 0x0000
++#define BP_ACTIVE_LOW 0x8000
++#define BP_GPIO_0_AH (0 | BP_ACTIVE_HIGH)
++#define BP_GPIO_0_AL (0 | BP_ACTIVE_LOW)
++#define BP_GPIO_1_AH (1 | BP_ACTIVE_HIGH)
++#define BP_GPIO_1_AL (1 | BP_ACTIVE_LOW)
++#define BP_GPIO_2_AH (2 | BP_ACTIVE_HIGH)
++#define BP_GPIO_2_AL (2 | BP_ACTIVE_LOW)
++#define BP_GPIO_3_AH (3 | BP_ACTIVE_HIGH)
++#define BP_GPIO_3_AL (3 | BP_ACTIVE_LOW)
++#define BP_GPIO_4_AH (4 | BP_ACTIVE_HIGH)
++#define BP_GPIO_4_AL (4 | BP_ACTIVE_LOW)
++#define BP_GPIO_5_AH (5 | BP_ACTIVE_HIGH)
++#define BP_GPIO_5_AL (5 | BP_ACTIVE_LOW)
++#define BP_GPIO_6_AH (6 | BP_ACTIVE_HIGH)
++#define BP_GPIO_6_AL (6 | BP_ACTIVE_LOW)
++#define BP_GPIO_7_AH (7 | BP_ACTIVE_HIGH)
++#define BP_GPIO_7_AL (7 | BP_ACTIVE_LOW)
++#define BP_GPIO_8_AH (8 | BP_ACTIVE_HIGH)
++#define BP_GPIO_8_AL (8 | BP_ACTIVE_LOW)
++#define BP_GPIO_9_AH (9 | BP_ACTIVE_HIGH)
++#define BP_GPIO_9_AL (9 | BP_ACTIVE_LOW)
++#define BP_GPIO_10_AH (10 | BP_ACTIVE_HIGH)
++#define BP_GPIO_10_AL (10 | BP_ACTIVE_LOW)
++#define BP_GPIO_11_AH (11 | BP_ACTIVE_HIGH)
++#define BP_GPIO_11_AL (11 | BP_ACTIVE_LOW)
++#define BP_GPIO_12_AH (12 | BP_ACTIVE_HIGH)
++#define BP_GPIO_12_AL (12 | BP_ACTIVE_LOW)
++#define BP_GPIO_13_AH (13 | BP_ACTIVE_HIGH)
++#define BP_GPIO_13_AL (13 | BP_ACTIVE_LOW)
++#define BP_GPIO_14_AH (14 | BP_ACTIVE_HIGH)
++#define BP_GPIO_14_AL (14 | BP_ACTIVE_LOW)
++#define BP_GPIO_15_AH (15 | BP_ACTIVE_HIGH)
++#define BP_GPIO_15_AL (15 | BP_ACTIVE_LOW)
++#define BP_GPIO_16_AH (16 | BP_ACTIVE_HIGH)
++#define BP_GPIO_16_AL (16 | BP_ACTIVE_LOW)
++#define BP_GPIO_17_AH (17 | BP_ACTIVE_HIGH)
++#define BP_GPIO_17_AL (17 | BP_ACTIVE_LOW)
++#define BP_GPIO_18_AH (18 | BP_ACTIVE_HIGH)
++#define BP_GPIO_18_AL (18 | BP_ACTIVE_LOW)
++#define BP_GPIO_19_AH (19 | BP_ACTIVE_HIGH)
++#define BP_GPIO_19_AL (19 | BP_ACTIVE_LOW)
++#define BP_GPIO_20_AH (20 | BP_ACTIVE_HIGH)
++#define BP_GPIO_20_AL (20 | BP_ACTIVE_LOW)
++#define BP_GPIO_21_AH (21 | BP_ACTIVE_HIGH)
++#define BP_GPIO_21_AL (21 | BP_ACTIVE_LOW)
++#define BP_GPIO_22_AH (22 | BP_ACTIVE_HIGH)
++#define BP_GPIO_22_AL (22 | BP_ACTIVE_LOW)
++#define BP_GPIO_23_AH (23 | BP_ACTIVE_HIGH)
++#define BP_GPIO_23_AL (23 | BP_ACTIVE_LOW)
++#define BP_GPIO_24_AH (24 | BP_ACTIVE_HIGH)
++#define BP_GPIO_24_AL (24 | BP_ACTIVE_LOW)
++#define BP_GPIO_25_AH (25 | BP_ACTIVE_HIGH)
++#define BP_GPIO_25_AL (25 | BP_ACTIVE_LOW)
++#define BP_GPIO_26_AH (26 | BP_ACTIVE_HIGH)
++#define BP_GPIO_26_AL (26 | BP_ACTIVE_LOW)
++#define BP_GPIO_27_AH (27 | BP_ACTIVE_HIGH)
++#define BP_GPIO_27_AL (27 | BP_ACTIVE_LOW)
++#define BP_GPIO_28_AH (28 | BP_ACTIVE_HIGH)
++#define BP_GPIO_28_AL (28 | BP_ACTIVE_LOW)
++#define BP_GPIO_29_AH (29 | BP_ACTIVE_HIGH)
++#define BP_GPIO_29_AL (29 | BP_ACTIVE_LOW)
++#define BP_GPIO_30_AH (30 | BP_ACTIVE_HIGH)
++#define BP_GPIO_30_AL (30 | BP_ACTIVE_LOW)
++#define BP_GPIO_31_AH (31 | BP_ACTIVE_HIGH)
++#define BP_GPIO_31_AL (31 | BP_ACTIVE_LOW)
++#define BP_GPIO_32_AH (32 | BP_ACTIVE_HIGH)
++#define BP_GPIO_32_AL (32 | BP_ACTIVE_LOW)
++#define BP_GPIO_33_AH (33 | BP_ACTIVE_HIGH)
++#define BP_GPIO_33_AL (33 | BP_ACTIVE_LOW)
++#define BP_GPIO_34_AH (34 | BP_ACTIVE_HIGH)
++#define BP_GPIO_34_AL (34 | BP_ACTIVE_LOW)
++#define BP_GPIO_35_AH (35 | BP_ACTIVE_HIGH)
++#define BP_GPIO_35_AL (35 | BP_ACTIVE_LOW)
++#define BP_GPIO_36_AH (36 | BP_ACTIVE_HIGH)
++#define BP_GPIO_36_AL (36 | BP_ACTIVE_LOW)
++
++/* Values for external interrupt assignments. */
++#define BP_EXT_INTR_0 0
++#define BP_EXT_INTR_1 1
++#define BP_EXT_INTR_2 2
++#define BP_EXT_INTR_3 3
++
++/* Values for chip select assignments. */
++#define BP_CS_0 0
++#define BP_CS_1 1
++#define BP_CS_2 2
++#define BP_CS_3 3
++
++/* Value for GPIO and external interrupt fields that are not used. */
++#define BP_NOT_DEFINED 0xffff
++#define BP_HW_DEFINED 0xfff0
++#define BP_UNEQUIPPED 0xfff1
++
++/* Maximum size of the board id string. */
++#define BP_BOARD_ID_LEN 16
++
++/* Maximum number of Ethernet MACs. */
++#define BP_MAX_ENET_MACS 2
++
++/* Maximum number of VoIP DSPs. */
++#define BP_MAX_VOIP_DSP 2
++
++/* Wireless Antenna Settings. */
++#define BP_WLAN_ANT_MAIN 0
++#define BP_WLAN_ANT_AUX 1
++#define BP_WLAN_ANT_BOTH 3
++
++#if !defined(__ASSEMBLER__)
++
++/* Information about an Ethernet MAC. If ucPhyType is BP_ENET_NO_PHY,
++ * then the other fields are not valid.
++ */
++typedef struct EthernetMacInfo
++{
++ unsigned char ucPhyType; /* BP_ENET_xxx */
++ unsigned char ucPhyAddress; /* 0 to 31 */
++ unsigned short usGpioPhySpiSck; /* GPIO pin or not defined */
++ unsigned short usGpioPhySpiSs; /* GPIO pin or not defined */
++ unsigned short usGpioPhySpiMosi; /* GPIO pin or not defined */
++ unsigned short usGpioPhySpiMiso; /* GPIO pin or not defined */
++ unsigned short usGpioPhyReset; /* GPIO pin or not defined (96348LV) */
++ unsigned short numSwitchPorts; /* Number of PHY ports */
++ unsigned short usConfigType; /* Configuration type */
++ unsigned short usReverseMii; /* Reverse MII */
++} ETHERNET_MAC_INFO, *PETHERNET_MAC_INFO;
++
++
++/* Information about VoIP DSPs. If ucDspType is BP_VOIP_NO_DSP,
++ * then the other fields are not valid.
++ */
++typedef struct VoIPDspInfo
++{
++ unsigned char ucDspType;
++ unsigned char ucDspAddress;
++ unsigned short usExtIntrVoip;
++ unsigned short usGpioVoipReset;
++ unsigned short usGpioVoipIntr;
++ unsigned short usGpioLedVoip;
++ unsigned short usCsVoip;
++
++} VOIP_DSP_INFO;
++
++
++/**************************************************************************
++ * Name : BpSetBoardId
++ *
++ * Description: This function find the BOARD_PARAMETERS structure for the
++ * specified board id string and assigns it to a global, static
++ * variable.
++ *
++ * Parameters : [IN] pszBoardId - Board id string that is saved into NVRAM.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_FOUND - Error, board id input string does not
++ * have a board parameters configuration record.
++ ***************************************************************************/
++int BpSetBoardId( char *pszBoardId );
++
++/**************************************************************************
++ * Name : BpGetBoardIds
++ *
++ * Description: This function returns all of the supported board id strings.
++ *
++ * Parameters : [OUT] pszBoardIds - Address of a buffer that the board id
++ * strings are returned in. Each id starts at BP_BOARD_ID_LEN
++ * boundary.
++ * [IN] nBoardIdsSize - Number of BP_BOARD_ID_LEN elements that
++ * were allocated in pszBoardIds.
++ *
++ * Returns : Number of board id strings returned.
++ ***************************************************************************/
++int BpGetBoardIds( char *pszBoardIds, int nBoardIdsSize );
++
++/**************************************************************************
++ * Name : BpGetEthernetMacInfo
++ *
++ * Description: This function returns all of the supported board id strings.
++ *
++ * Parameters : [OUT] pEnetInfos - Address of an array of ETHERNET_MAC_INFO
++ * buffers.
++ * [IN] nNumEnetInfos - Number of ETHERNET_MAC_INFO elements that
++ * are pointed to by pEnetInfos.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ ***************************************************************************/
++int BpGetEthernetMacInfo( PETHERNET_MAC_INFO pEnetInfos, int nNumEnetInfos );
++
++/**************************************************************************
++ * Name : BpGetSdramSize
++ *
++ * Description: This function returns a constant that describees the board's
++ * SDRAM type and size.
++ *
++ * Parameters : [OUT] pulSdramSize - Address of short word that the SDRAM size
++ * is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ ***************************************************************************/
++int BpGetSdramSize( unsigned long *pulSdramSize );
++
++/**************************************************************************
++ * Name : BpGetPsiSize
++ *
++ * Description: This function returns the persistent storage size in K bytes.
++ *
++ * Parameters : [OUT] pulPsiSize - Address of short word that the persistent
++ * storage size is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ ***************************************************************************/
++int BpGetPsiSize( unsigned long *pulPsiSize );
++
++/**************************************************************************
++ * Name : BpGetRj11InnerOuterPairGpios
++ *
++ * Description: This function returns the GPIO pin assignments for changing
++ * between the RJ11 inner pair and RJ11 outer pair.
++ *
++ * Parameters : [OUT] pusInner - Address of short word that the RJ11 inner pair
++ * GPIO pin is returned in.
++ * [OUT] pusOuter - Address of short word that the RJ11 outer pair
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, values are returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetRj11InnerOuterPairGpios( unsigned short *pusInner,
++ unsigned short *pusOuter );
++
++/**************************************************************************
++ * Name : BpGetPressAndHoldResetGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the press
++ * and hold reset button.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the press and hold
++ * reset button GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetPressAndHoldResetGpio( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetVoipResetGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the VOIP
++ * Reset operation.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the VOIP reset
++ * GPIO pin is returned in.
++ * [IN] dspNum - Address of the DSP to query.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetVoipResetGpio( unsigned char dspNum, unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetVoipIntrGpio
++ *
++ * Description: This function returns the GPIO pin assignment for VoIP interrupt.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the VOIP interrupt
++ * GPIO pin is returned in.
++ * [IN] dspNum - Address of the DSP to query.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetVoipIntrGpio( unsigned char dspNum, unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetPcmciaResetGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the PCMCIA
++ * Reset operation.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the PCMCIA reset
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetPcmciaResetGpio( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetUartRtsCtsGpios
++ *
++ * Description: This function returns the GPIO pin assignments for RTS and CTS
++ * UART signals.
++ *
++ * Parameters : [OUT] pusRts - Address of short word that the UART RTS GPIO
++ * pin is returned in.
++ * [OUT] pusCts - Address of short word that the UART CTS GPIO
++ * pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, values are returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetRtsCtsUartGpios( unsigned short *pusRts, unsigned short *pusCts );
++
++/**************************************************************************
++ * Name : BpGetAdslLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the ADSL
++ * LED.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the ADSL LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetAdslLedGpio( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetAdslFailLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the ADSL
++ * LED that is used when there is a DSL connection failure.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the ADSL LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetAdslFailLedGpio( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetWirelessLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the Wireless
++ * LED.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the Wireless LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetWirelessLedGpio( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetWirelessAntInUse
++ *
++ * Description: This function returns the antennas in use for wireless
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the Wireless Antenna
++ * is in use.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetWirelessAntInUse( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetWirelessSesBtnGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the Wireless
++ * Ses Button.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the Wireless Ses
++ * Button GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetWirelessSesBtnGpio( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetWirelessSesExtIntr
++ *
++ * Description: This function returns the external interrupt number for the
++ * Wireless Ses Button.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the Wireless Ses
++ * external interrup is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetWirelessSesExtIntr( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetWirelessSesLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the Wireless
++ * Ses Led.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the Wireless Ses
++ * Led GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetWirelessSesLedGpio( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetUsbLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the USB
++ * LED.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the USB LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetUsbLedGpio( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetHpnaLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the HPNA
++ * LED.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the HPNA LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetHpnaLedGpio( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetWanDataLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the WAN Data
++ * LED.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the WAN Data LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetWanDataLedGpio( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetPppLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the PPP
++ * LED.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the PPP LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetPppLedGpio( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetPppFailLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the PPP
++ * LED that is used when there is a PPP connection failure.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the PPP LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetPppFailLedGpio( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetVoipLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the VOIP
++ * LED.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the VOIP LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetVoipLedGpio( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetBootloaderPowerOnLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the power
++ * on LED that is set by the bootloader.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the alarm LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetBootloaderPowerOnLedGpio( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetBootloaderAlarmLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the alarm
++ * LED that is set by the bootloader.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the alarm LED
++ * GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetBootloaderAlarmLedGpio( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetBootloaderResetCfgLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the reset
++ * configuration LED that is set by the bootloader.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the reset
++ * configuration LED GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetBootloaderResetCfgLedGpio( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetBootloaderStopLedGpio
++ *
++ * Description: This function returns the GPIO pin assignment for the break
++ * into bootloader LED that is set by the bootloader.
++ *
++ * Parameters : [OUT] pusValue - Address of short word that the break into
++ * bootloader LED GPIO pin is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetBootloaderStopLedGpio( unsigned short *pusValue );
++
++/**************************************************************************
++ * Name : BpGetWirelessExtIntr
++ *
++ * Description: This function returns the Wireless external interrupt number.
++ *
++ * Parameters : [OUT] pulValue - Address of short word that the wireless
++ * external interrupt number is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetWirelessExtIntr( unsigned long *pulValue );
++
++/**************************************************************************
++ * Name : BpGetAdslDyingGaspExtIntr
++ *
++ * Description: This function returns the ADSL Dying Gasp external interrupt
++ * number.
++ *
++ * Parameters : [OUT] pulValue - Address of short word that the ADSL Dying Gasp
++ * external interrupt number is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetAdslDyingGaspExtIntr( unsigned long *pulValue );
++
++/**************************************************************************
++ * Name : BpGetVoipExtIntr
++ *
++ * Description: This function returns the VOIP external interrupt number.
++ *
++ * Parameters : [OUT] pulValue - Address of short word that the VOIP
++ * external interrupt number is returned in.
++ * [IN] dspNum - Address of the DSP to query.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetVoipExtIntr( unsigned char dspNum, unsigned long *pulValue );
++
++/**************************************************************************
++ * Name : BpGetHpnaExtIntr
++ *
++ * Description: This function returns the HPNA external interrupt number.
++ *
++ * Parameters : [OUT] pulValue - Address of short word that the HPNA
++ * external interrupt number is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetHpnaExtIntr( unsigned long *pulValue );
++
++/**************************************************************************
++ * Name : BpGetHpnaChipSelect
++ *
++ * Description: This function returns the HPNA chip select number.
++ *
++ * Parameters : [OUT] pulValue - Address of short word that the HPNA
++ * chip select number is returned in.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetHpnaChipSelect( unsigned long *pulValue );
++
++/**************************************************************************
++ * Name : BpGetVoipChipSelect
++ *
++ * Description: This function returns the VOIP chip select number.
++ *
++ * Parameters : [OUT] pulValue - Address of short word that the VOIP
++ * chip select number is returned in.
++ * [IN] dspNum - Address of the DSP to query.
++ *
++ * Returns : BP_SUCCESS - Success, value is returned.
++ * BP_BOARD_ID_NOT_SET - Error, BpSetBoardId has not been called.
++ * BP_VALUE_NOT_DEFINED - At least one return value is not defined
++ * for the board.
++ ***************************************************************************/
++int BpGetVoipChipSelect( unsigned char dspNum, unsigned long *pulValue );
++
++#endif /* __ASSEMBLER__ */
++
++#endif /* _BOARDPARMS_H */
++
+diff -urN linux.old/arch/mips/bcm963xx/include/6338_intr.h linux.dev/arch/mips/bcm963xx/include/6338_intr.h
+--- linux.old/arch/mips/bcm963xx/include/6338_intr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/include/6338_intr.h 2006-08-25 00:39:38.000000000 +0200
+@@ -0,0 +1,64 @@
++/*
++<:copyright-gpl
++ Copyright 2003 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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 __6338_INTR_H
++#define __6338_INTR_H
++
++/*=====================================================================*/
++/* BCM6338 External Interrupt Level Assignments */
++/*=====================================================================*/
++#define INTERRUPT_ID_EXTERNAL_0 3
++#define INTERRUPT_ID_EXTERNAL_1 4
++#define INTERRUPT_ID_EXTERNAL_2 5
++#define INTERRUPT_ID_EXTERNAL_3 6
++
++/*=====================================================================*/
++/* BCM6338 Timer Interrupt Level Assignments */
++/*=====================================================================*/
++#define MIPS_TIMER_INT 7
++
++/*=====================================================================*/
++/* Peripheral ISR Table Offset */
++/*=====================================================================*/
++#define INTERNAL_ISR_TABLE_OFFSET 8
++
++/*=====================================================================*/
++/* Logical Peripheral Interrupt IDs */
++/*=====================================================================*/
++
++#define INTERRUPT_ID_TIMER (INTERNAL_ISR_TABLE_OFFSET + 0)
++#define INTERRUPT_ID_SPI (INTERNAL_ISR_TABLE_OFFSET + 1)
++#define INTERRUPT_ID_UART (INTERNAL_ISR_TABLE_OFFSET + 2)
++#define INTERRUPT_ID_DG (INTERNAL_ISR_TABLE_OFFSET + 4)
++#define INTERRUPT_ID_ADSL (INTERNAL_ISR_TABLE_OFFSET + 5)
++#define INTERRUPT_ID_ATM (INTERNAL_ISR_TABLE_OFFSET + 6)
++#define INTERRUPT_ID_USBS (INTERNAL_ISR_TABLE_OFFSET + 7)
++#define INTERRUPT_ID_EMAC1 (INTERNAL_ISR_TABLE_OFFSET + 8)
++#define INTERRUPT_ID_EPHY (INTERNAL_ISR_TABLE_OFFSET + 9)
++#define INTERRUPT_ID_SDRAM (INTERNAL_ISR_TABLE_OFFSET + 10)
++#define INTERRUPT_ID_USB_CNTL_RX_DMA (INTERNAL_ISR_TABLE_OFFSET + 11)
++#define INTERRUPT_ID_USB_CNTL_TX_DMA (INTERNAL_ISR_TABLE_OFFSET + 12)
++#define INTERRUPT_ID_USB_BULK_RX_DMA (INTERNAL_ISR_TABLE_OFFSET + 13)
++#define INTERRUPT_ID_USB_BULK_TX_DMA (INTERNAL_ISR_TABLE_OFFSET + 14)
++#define INTERRUPT_ID_EMAC1_RX_DMA (INTERNAL_ISR_TABLE_OFFSET + 15)
++#define INTERRUPT_ID_EMAC1_TX_DMA (INTERNAL_ISR_TABLE_OFFSET + 16)
++#define INTERRUPT_ID_SDIO (INTERNAL_ISR_TABLE_OFFSET + 17)
++
++#endif /* __BCM6338_H */
++
+diff -urN linux.old/arch/mips/bcm963xx/include/6338_map_part.h linux.dev/arch/mips/bcm963xx/include/6338_map_part.h
+--- linux.old/arch/mips/bcm963xx/include/6338_map_part.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/include/6338_map_part.h 2006-08-25 00:39:38.000000000 +0200
+@@ -0,0 +1,334 @@
++/*
++<:copyright-gpl
++ Copyright 2004 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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 __BCM6338_MAP_H
++#define __BCM6338_MAP_H
++
++#include "bcmtypes.h"
++
++#define PERF_BASE 0xfffe0000
++#define TIMR_BASE 0xfffe0200
++#define UART_BASE 0xfffe0300
++#define GPIO_BASE 0xfffe0400
++#define SPI_BASE 0xfffe0c00
++
++typedef struct PerfControl {
++ uint32 RevID;
++ uint16 testControl;
++ uint16 blkEnables;
++#define EMAC_CLK_EN 0x0010
++#define USBS_CLK_EN 0x0010
++#define SAR_CLK_EN 0x0020
++
++#define SPI_CLK_EN 0x0200
++
++ uint32 pll_control;
++#define SOFT_RESET 0x00000001
++
++ uint32 IrqMask;
++ uint32 IrqStatus;
++
++ uint32 ExtIrqCfg;
++#define EI_SENSE_SHFT 0
++#define EI_STATUS_SHFT 5
++#define EI_CLEAR_SHFT 10
++#define EI_MASK_SHFT 15
++#define EI_INSENS_SHFT 20
++#define EI_LEVEL_SHFT 25
++
++ uint32 unused[4]; /* (18) */
++ uint32 BlockSoftReset; /* (28) */
++#define BSR_SPI 0x00000001
++#define BSR_EMAC 0x00000004
++#define BSR_USBH 0x00000008
++#define BSR_USBS 0x00000010
++#define BSR_ADSL 0x00000020
++#define BSR_DMAMEM 0x00000040
++#define BSR_SAR 0x00000080
++#define BSR_ACLC 0x00000100
++#define BSR_ADSL_MIPS_PLL 0x00000400
++#define BSR_ALL_BLOCKS \
++ (BSR_SPI | BSR_EMAC | BSR_USBH | BSR_USBS | BSR_ADSL | BSR_DMAMEM | \
++ BSR_SAR | BSR_ACLC | BSR_ADSL_MIPS_PLL)
++} PerfControl;
++
++#define PERF ((volatile PerfControl * const) PERF_BASE)
++
++
++typedef struct Timer {
++ uint16 unused0;
++ byte TimerMask;
++#define TIMER0EN 0x01
++#define TIMER1EN 0x02
++#define TIMER2EN 0x04
++ byte TimerInts;
++#define TIMER0 0x01
++#define TIMER1 0x02
++#define TIMER2 0x04
++#define WATCHDOG 0x08
++ uint32 TimerCtl0;
++ uint32 TimerCtl1;
++ uint32 TimerCtl2;
++#define TIMERENABLE 0x80000000
++#define RSTCNTCLR 0x40000000
++ uint32 TimerCnt0;
++ uint32 TimerCnt1;
++ uint32 TimerCnt2;
++ uint32 WatchDogDefCount;
++
++ /* Write 0xff00 0x00ff to Start timer
++ * Write 0xee00 0x00ee to Stop and re-load default count
++ * Read from this register returns current watch dog count
++ */
++ uint32 WatchDogCtl;
++
++ /* Number of 40-MHz ticks for WD Reset pulse to last */
++ uint32 WDResetCount;
++} Timer;
++
++#define TIMER ((volatile Timer * const) TIMR_BASE)
++typedef struct UartChannel {
++ byte unused0;
++ byte control;
++#define BRGEN 0x80 /* Control register bit defs */
++#define TXEN 0x40
++#define RXEN 0x20
++#define LOOPBK 0x10
++#define TXPARITYEN 0x08
++#define TXPARITYEVEN 0x04
++#define RXPARITYEN 0x02
++#define RXPARITYEVEN 0x01
++
++ byte config;
++#define XMITBREAK 0x40
++#define BITS5SYM 0x00
++#define BITS6SYM 0x10
++#define BITS7SYM 0x20
++#define BITS8SYM 0x30
++#define ONESTOP 0x07
++#define TWOSTOP 0x0f
++ /* 4-LSBS represent STOP bits/char
++ * in 1/8 bit-time intervals. Zero
++ * represents 1/8 stop bit interval.
++ * Fifteen represents 2 stop bits.
++ */
++ byte fifoctl;
++#define RSTTXFIFOS 0x80
++#define RSTRXFIFOS 0x40
++ /* 5-bit TimeoutCnt is in low bits of this register.
++ * This count represents the number of characters
++ * idle times before setting receive Irq when below threshold
++ */
++ uint32 baudword;
++ /* When divide SysClk/2/(1+baudword) we should get 32*bit-rate
++ */
++
++ byte txf_levl; /* Read-only fifo depth */
++ byte rxf_levl; /* Read-only fifo depth */
++ byte fifocfg; /* Upper 4-bits are TxThresh, Lower are
++ * RxThreshold. Irq can be asserted
++ * when rx fifo> thresh, txfifo<thresh
++ */
++ byte prog_out; /* Set value of DTR (Bit0), RTS (Bit1)
++ * if these bits are also enabled to GPIO_o
++ */
++#define DTREN 0x01
++#define RTSEN 0x02
++
++ byte unused1;
++ byte DeltaIPEdgeNoSense; /* Low 4-bits, set corr bit to 1 to
++ * detect irq on rising AND falling
++ * edges for corresponding GPIO_i
++ * if enabled (edge insensitive)
++ */
++ byte DeltaIPConfig_Mask; /* Upper 4 bits: 1 for posedge sense
++ * 0 for negedge sense if
++ * not configured for edge
++ * insensitive (see above)
++ * Lower 4 bits: Mask to enable change
++ * detection IRQ for corresponding
++ * GPIO_i
++ */
++ byte DeltaIP_SyncIP; /* Upper 4 bits show which bits
++ * have changed (may set IRQ).
++ * read automatically clears bit
++ * Lower 4 bits are actual status
++ */
++
++ uint16 intMask; /* Same Bit defs for Mask and status */
++ uint16 intStatus;
++#define DELTAIP 0x0001
++#define TXUNDERR 0x0002
++#define TXOVFERR 0x0004
++#define TXFIFOTHOLD 0x0008
++#define TXREADLATCH 0x0010
++#define TXFIFOEMT 0x0020
++#define RXUNDERR 0x0040
++#define RXOVFERR 0x0080
++#define RXTIMEOUT 0x0100
++#define RXFIFOFULL 0x0200
++#define RXFIFOTHOLD 0x0400
++#define RXFIFONE 0x0800
++#define RXFRAMERR 0x1000
++#define RXPARERR 0x2000
++#define RXBRK 0x4000
++
++ uint16 unused2;
++ uint16 Data; /* Write to TX, Read from RX */
++ /* bits 11:8 are BRK,PAR,FRM errors */
++
++ uint32 unused3;
++ uint32 unused4;
++} Uart;
++
++#define UART ((volatile Uart * const) UART_BASE)
++
++typedef struct GpioControl {
++ uint32 unused0;
++ uint32 GPIODir; /* bits 7:0 */
++ uint32 unused1;
++ uint32 GPIOio; /* bits 7:0 */
++ uint32 LEDCtrl;
++#define LED3_STROBE 0x08000000
++#define LED2_STROBE 0x04000000
++#define LED1_STROBE 0x02000000
++#define LED0_STROBE 0x01000000
++#define LED_TEST 0x00010000
++#define LED3_DISABLE_LINK_ACT 0x00008000
++#define LED2_DISABLE_LINK_ACT 0x00004000
++#define LED1_DISABLE_LINK_ACT 0x00002000
++#define LED0_DISABLE_LINK_ACT 0x00001000
++#define LED_INTERVAL_SET_MASK 0x00000f00
++#define LED_INTERVAL_SET_320MS 0x00000500
++#define LED_INTERVAL_SET_160MS 0x00000400
++#define LED_INTERVAL_SET_80MS 0x00000300
++#define LED_INTERVAL_SET_40MS 0x00000200
++#define LED_INTERVAL_SET_20MS 0x00000100
++#define LED3_ON 0x00000080
++#define LED2_ON 0x00000040
++#define LED1_ON 0x00000020
++#define LED0_ON 0x00000010
++#define LED3_ENABLE 0x00000008
++#define LED2_ENABLE 0x00000004
++#define LED1_ENABLE 0x00000002
++#define LED0_ENABLE 0x00000001
++ uint32 SpiSlaveCfg;
++#define SPI_SLAVE_RESET 0x00010000
++#define SPI_RESTRICT 0x00000400
++#define SPI_DELAY_DISABLE 0x00000200
++#define SPI_PROBE_MUX_SEL_MASK 0x000001e0
++#define SPI_SER_ADDR_CFG_MASK 0x0000000c
++#define SPI_MODE 0x00000001
++ uint32 vRegConfig;
++} GpioControl;
++
++#define GPIO ((volatile GpioControl * const) GPIO_BASE)
++
++/* Number to mask conversion macro used for GPIODir and GPIOio */
++#define GPIO_NUM_MAX_BITS_MASK 0x0f
++#define GPIO_NUM_TO_MASK(X) (1 << ((X) & GPIO_NUM_MAX_BITS_MASK))
++
++/*
++** Spi Controller
++*/
++
++typedef struct SpiControl {
++ uint16 spiCmd; /* (0x0): SPI command */
++#define SPI_CMD_START_IMMEDIATE 3
++
++#define SPI_CMD_COMMAND_SHIFT 0
++#define SPI_CMD_DEVICE_ID_SHIFT 4
++#define SPI_CMD_PREPEND_BYTE_CNT_SHIFT 8
++
++ byte spiIntStatus; /* (0x2): SPI interrupt status */
++ byte spiMaskIntStatus; /* (0x3): SPI masked interrupt status */
++
++ byte spiIntMask; /* (0x4): SPI interrupt mask */
++#define SPI_INTR_CMD_DONE 0x01
++#define SPI_INTR_CLEAR_ALL 0x1f
++
++ byte spiStatus; /* (0x5): SPI status */
++
++ byte spiClkCfg; /* (0x6): SPI clock configuration */
++
++ byte spiFillByte; /* (0x7): SPI fill byte */
++
++ byte unused0;
++ byte spiMsgTail; /* (0x9): msgtail */
++ byte unused1;
++ byte spiRxTail; /* (0xB): rxtail */
++
++ uint32 unused2[13]; /* (0x0c - 0x3c) reserved */
++
++ byte spiMsgCtl; /* (0x40) control byte */
++#define HALF_DUPLEX_W 1
++#define HALF_DUPLEX_R 2
++#define SPI_MSG_TYPE_SHIFT 6
++#define SPI_BYTE_CNT_SHIFT 0
++ byte spiMsgData[63]; /* (0x41 - 0x7f) msg data */
++ byte spiRxDataFifo[64]; /* (0x80 - 0xbf) rx data */
++ byte unused3[64]; /* (0xc0 - 0xff) reserved */
++} SpiControl;
++
++#define SPI ((volatile SpiControl * const) SPI_BASE)
++
++/*
++** External Bus Interface
++*/
++typedef struct EbiChipSelect {
++ uint32 base; /* base address in upper 24 bits */
++#define EBI_SIZE_8K 0
++#define EBI_SIZE_16K 1
++#define EBI_SIZE_32K 2
++#define EBI_SIZE_64K 3
++#define EBI_SIZE_128K 4
++#define EBI_SIZE_256K 5
++#define EBI_SIZE_512K 6
++#define EBI_SIZE_1M 7
++#define EBI_SIZE_2M 8
++#define EBI_SIZE_4M 9
++#define EBI_SIZE_8M 10
++#define EBI_SIZE_16M 11
++#define EBI_SIZE_32M 12
++#define EBI_SIZE_64M 13
++#define EBI_SIZE_128M 14
++#define EBI_SIZE_256M 15
++ uint32 config;
++#define EBI_ENABLE 0x00000001 /* .. enable this range */
++#define EBI_WAIT_STATES 0x0000000e /* .. mask for wait states */
++#define EBI_WTST_SHIFT 1 /* .. for shifting wait states */
++#define EBI_WORD_WIDE 0x00000010 /* .. 16-bit peripheral, else 8 */
++#define EBI_WREN 0x00000020 /* enable posted writes */
++#define EBI_POLARITY 0x00000040 /* .. set to invert something,
++ ** don't know what yet */
++#define EBI_TS_TA_MODE 0x00000080 /* .. use TS/TA mode */
++#define EBI_TS_SEL 0x00000100 /* .. drive tsize, not bs_b */
++#define EBI_FIFO 0x00000200 /* .. use fifo */
++#define EBI_RE 0x00000400 /* .. Reverse Endian */
++} EbiChipSelect;
++
++typedef struct MpiRegisters {
++ EbiChipSelect cs[1]; /* size chip select configuration */
++} MpiRegisters;
++
++#define MPI ((volatile MpiRegisters * const) MPI_BASE)
++
++
++#endif
++
+diff -urN linux.old/arch/mips/bcm963xx/include/6345_intr.h linux.dev/arch/mips/bcm963xx/include/6345_intr.h
+--- linux.old/arch/mips/bcm963xx/include/6345_intr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/include/6345_intr.h 2006-08-25 00:39:38.000000000 +0200
+@@ -0,0 +1,72 @@
++/*
++<:copyright-gpl
++ Copyright 2002 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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 __6345_INTR_H
++#define __6345_INTR_H
++
++
++/*=====================================================================*/
++/* BCM6345 External Interrupt Level Assignments */
++/*=====================================================================*/
++#define INTERRUPT_ID_EXTERNAL_0 3
++#define INTERRUPT_ID_EXTERNAL_1 4
++#define INTERRUPT_ID_EXTERNAL_2 5
++#define INTERRUPT_ID_EXTERNAL_3 6
++
++/*=====================================================================*/
++/* BCM6345 Timer Interrupt Level Assignments */
++/*=====================================================================*/
++#define MIPS_TIMER_INT 7
++
++/*=====================================================================*/
++/* Peripheral ISR Table Offset */
++/*=====================================================================*/
++#define INTERNAL_ISR_TABLE_OFFSET 8
++#define DMA_ISR_TABLE_OFFSET (INTERNAL_ISR_TABLE_OFFSET + 13)
++
++/*=====================================================================*/
++/* Logical Peripheral Interrupt IDs */
++/*=====================================================================*/
++
++/* Internal peripheral interrupt IDs */
++#define INTERRUPT_ID_TIMER (INTERNAL_ISR_TABLE_OFFSET + 0)
++#define INTERRUPT_ID_UART (INTERNAL_ISR_TABLE_OFFSET + 2)
++#define INTERRUPT_ID_ADSL (INTERNAL_ISR_TABLE_OFFSET + 3)
++#define INTERRUPT_ID_ATM (INTERNAL_ISR_TABLE_OFFSET + 4)
++#define INTERRUPT_ID_USB (INTERNAL_ISR_TABLE_OFFSET + 5)
++#define INTERRUPT_ID_EMAC (INTERNAL_ISR_TABLE_OFFSET + 8)
++#define INTERRUPT_ID_EPHY (INTERNAL_ISR_TABLE_OFFSET + 12)
++
++/* DMA channel interrupt IDs */
++#define INTERRUPT_ID_EMAC_RX_CHAN (DMA_ISR_TABLE_OFFSET + EMAC_RX_CHAN)
++#define INTERRUPT_ID_EMAC_TX_CHAN (DMA_ISR_TABLE_OFFSET + EMAC_TX_CHAN)
++#define INTERRUPT_ID_EBI_RX_CHAN (DMA_ISR_TABLE_OFFSET + EBI_RX_CHAN)
++#define INTERRUPT_ID_EBI_TX_CHAN (DMA_ISR_TABLE_OFFSET + EBI_TX_CHAN)
++#define INTERRUPT_ID_RESERVED_RX_CHAN (DMA_ISR_TABLE_OFFSET + RESERVED_RX_CHAN)
++#define INTERRUPT_ID_RESERVED_TX_CHAN (DMA_ISR_TABLE_OFFSET + RESERVED_TX_CHAN)
++#define INTERRUPT_ID_USB_BULK_RX_CHAN (DMA_ISR_TABLE_OFFSET + USB_BULK_RX_CHAN)
++#define INTERRUPT_ID_USB_BULK_TX_CHAN (DMA_ISR_TABLE_OFFSET + USB_BULK_TX_CHAN)
++#define INTERRUPT_ID_USB_CNTL_RX_CHAN (DMA_ISR_TABLE_OFFSET + USB_CNTL_RX_CHAN)
++#define INTERRUPT_ID_USB_CNTL_TX_CHAN (DMA_ISR_TABLE_OFFSET + USB_CNTL_TX_CHAN)
++#define INTERRUPT_ID_USB_ISO_RX_CHAN (DMA_ISR_TABLE_OFFSET + USB_ISO_RX_CHAN)
++#define INTERRUPT_ID_USB_ISO_TX_CHAN (DMA_ISR_TABLE_OFFSET + USB_ISO_TX_CHAN)
++
++
++#endif /* __BCM6345_H */
++
+diff -urN linux.old/arch/mips/bcm963xx/include/6345_map_part.h linux.dev/arch/mips/bcm963xx/include/6345_map_part.h
+--- linux.old/arch/mips/bcm963xx/include/6345_map_part.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/include/6345_map_part.h 2006-08-25 00:39:38.000000000 +0200
+@@ -0,0 +1,163 @@
++/*
++<:copyright-gpl
++ Copyright 2002 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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 __BCM6345_MAP_H
++#define __BCM6345_MAP_H
++
++
++#include "bcmtypes.h"
++#include "6345_intr.h"
++
++typedef struct IntControl {
++ uint32 RevID;
++ uint16 testControl;
++ uint16 blkEnables;
++#define USB_CLK_EN 0x0100
++#define EMAC_CLK_EN 0x0080
++#define UART_CLK_EN 0x0008
++#define CPU_CLK_EN 0x0001
++
++ uint32 pll_control;
++#define SOFT_RESET 0x00000001
++
++ uint32 IrqMask;
++ uint32 IrqStatus;
++
++ uint32 ExtIrqCfg;
++#define EI_SENSE_SHFT 0
++#define EI_STATUS_SHFT 4
++#define EI_CLEAR_SHFT 8
++#define EI_MASK_SHFT 12
++#define EI_INSENS_SHFT 16
++#define EI_LEVEL_SHFT 20
++} IntControl;
++
++#define INTC_BASE 0xfffe0000
++#define PERF ((volatile IntControl * const) INTC_BASE)
++
++#define TIMR_BASE 0xfffe0200
++typedef struct Timer {
++ uint16 unused0;
++ byte TimerMask;
++#define TIMER0EN 0x01
++#define TIMER1EN 0x02
++#define TIMER2EN 0x04
++ byte TimerInts;
++#define TIMER0 0x01
++#define TIMER1 0x02
++#define TIMER2 0x04
++#define WATCHDOG 0x08
++ uint32 TimerCtl0;
++ uint32 TimerCtl1;
++ uint32 TimerCtl2;
++#define TIMERENABLE 0x80000000
++#define RSTCNTCLR 0x40000000
++ uint32 TimerCnt0;
++ uint32 TimerCnt1;
++ uint32 TimerCnt2;
++ uint32 WatchDogDefCount;
++
++ /* Write 0xff00 0x00ff to Start timer
++ * Write 0xee00 0x00ee to Stop and re-load default count
++ * Read from this register returns current watch dog count
++ */
++ uint32 WatchDogCtl;
++
++ /* Number of 40-MHz ticks for WD Reset pulse to last */
++ uint32 WDResetCount;
++} Timer;
++
++#define TIMER ((volatile Timer * const) TIMR_BASE)
++
++typedef struct UartChannel {
++ byte unused0;
++ byte control;
++#define BRGEN 0x80 /* Control register bit defs */
++#define TXEN 0x40
++#define RXEN 0x20
++#define TXPARITYEN 0x08
++#define TXPARITYEVEN 0x04
++#define RXPARITYEN 0x02
++#define RXPARITYEVEN 0x01
++ byte config;
++#define BITS5SYM 0x00
++#define BITS6SYM 0x10
++#define BITS7SYM 0x20
++#define BITS8SYM 0x30
++#define XMITBREAK 0x40
++#define ONESTOP 0x07
++#define TWOSTOP 0x0f
++
++ byte fifoctl;
++#define RSTTXFIFOS 0x80
++#define RSTRXFIFOS 0x40
++ uint32 baudword;
++
++ byte txf_levl;
++ byte rxf_levl;
++ byte fifocfg;
++ byte prog_out;
++
++ byte unused1;
++ byte DeltaIPEdgeNoSense;
++ byte DeltaIPConfig_Mask;
++ byte DeltaIP_SyncIP;
++ uint16 intMask;
++ uint16 intStatus;
++#define TXUNDERR 0x0002
++#define TXOVFERR 0x0004
++#define TXFIFOEMT 0x0020
++#define RXOVFERR 0x0080
++#define RXFIFONE 0x0800
++#define RXFRAMERR 0x1000
++#define RXPARERR 0x2000
++#define RXBRK 0x4000
++
++ uint16 unused2;
++ uint16 Data;
++ uint32 unused3;
++ uint32 unused4;
++} Uart;
++
++#define UART_BASE 0xfffe0300
++#define UART ((volatile Uart * const) UART_BASE)
++
++typedef struct GpioControl {
++ uint16 unused0;
++ byte unused1;
++ byte TBusSel;
++
++ uint16 unused2;
++ uint16 GPIODir;
++ byte unused3;
++ byte Leds;
++ uint16 GPIOio;
++
++ uint32 UartCtl;
++} GpioControl;
++
++#define GPIO_BASE 0xfffe0400
++#define GPIO ((volatile GpioControl * const) GPIO_BASE)
++
++#define GPIO_NUM_MAX_BITS_MASK 0x0f
++#define GPIO_NUM_TO_MASK(X) (1 << ((X) & GPIO_NUM_MAX_BITS_MASK))
++
++
++#endif
++
+diff -urN linux.old/arch/mips/bcm963xx/include/6348_intr.h linux.dev/arch/mips/bcm963xx/include/6348_intr.h
+--- linux.old/arch/mips/bcm963xx/include/6348_intr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/include/6348_intr.h 2006-08-25 00:39:38.000000000 +0200
+@@ -0,0 +1,74 @@
++/*
++<:copyright-gpl
++ Copyright 2003 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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 __6348_INTR_H
++#define __6348_INTR_H
++
++
++/*=====================================================================*/
++/* BCM6348 External Interrupt Level Assignments */
++/*=====================================================================*/
++#define INTERRUPT_ID_EXTERNAL_0 3
++#define INTERRUPT_ID_EXTERNAL_1 4
++#define INTERRUPT_ID_EXTERNAL_2 5
++#define INTERRUPT_ID_EXTERNAL_3 6
++
++/*=====================================================================*/
++/* BCM6348 Timer Interrupt Level Assignments */
++/*=====================================================================*/
++#define MIPS_TIMER_INT 7
++
++/*=====================================================================*/
++/* Peripheral ISR Table Offset */
++/*=====================================================================*/
++#define INTERNAL_ISR_TABLE_OFFSET 8
++
++/*=====================================================================*/
++/* Logical Peripheral Interrupt IDs */
++/*=====================================================================*/
++
++#define INTERRUPT_ID_TIMER (INTERNAL_ISR_TABLE_OFFSET + 0)
++#define INTERRUPT_ID_SPI (INTERNAL_ISR_TABLE_OFFSET + 1)
++#define INTERRUPT_ID_UART (INTERNAL_ISR_TABLE_OFFSET + 2)
++#define INTERRUPT_ID_ADSL (INTERNAL_ISR_TABLE_OFFSET + 4)
++#define INTERRUPT_ID_ATM (INTERNAL_ISR_TABLE_OFFSET + 5)
++#define INTERRUPT_ID_USBS (INTERNAL_ISR_TABLE_OFFSET + 6)
++#define INTERRUPT_ID_EMAC2 (INTERNAL_ISR_TABLE_OFFSET + 7)
++#define INTERRUPT_ID_EMAC1 (INTERNAL_ISR_TABLE_OFFSET + 8)
++#define INTERRUPT_ID_EPHY (INTERNAL_ISR_TABLE_OFFSET + 9)
++#define INTERRUPT_ID_M2M (INTERNAL_ISR_TABLE_OFFSET + 10)
++#define INTERRUPT_ID_ACLC (INTERNAL_ISR_TABLE_OFFSET + 11)
++#define INTERRUPT_ID_USBH (INTERNAL_ISR_TABLE_OFFSET + 12)
++#define INTERRUPT_ID_SDRAM (INTERNAL_ISR_TABLE_OFFSET + 13)
++#define INTERRUPT_ID_USB_CNTL_RX_DMA (INTERNAL_ISR_TABLE_OFFSET + 14)
++#define INTERRUPT_ID_USB_CNTL_TX_DMA (INTERNAL_ISR_TABLE_OFFSET + 15)
++#define INTERRUPT_ID_USB_BULK_RX_DMA (INTERNAL_ISR_TABLE_OFFSET + 16)
++#define INTERRUPT_ID_USB_BULK_TX_DMA (INTERNAL_ISR_TABLE_OFFSET + 17)
++#define INTERRUPT_ID_USB_ISO_RX_DMA (INTERNAL_ISR_TABLE_OFFSET + 18)
++#define INTERRUPT_ID_USB_ISO_TX_DMA (INTERNAL_ISR_TABLE_OFFSET + 19)
++#define INTERRUPT_ID_EMAC1_RX_DMA (INTERNAL_ISR_TABLE_OFFSET + 20)
++#define INTERRUPT_ID_EMAC1_TX_DMA (INTERNAL_ISR_TABLE_OFFSET + 21)
++#define INTERRUPT_ID_EMAC2_RX_DMA (INTERNAL_ISR_TABLE_OFFSET + 22)
++#define INTERRUPT_ID_EMAC2_TX_DMA (INTERNAL_ISR_TABLE_OFFSET + 23)
++#define INTERRUPT_ID_MPI (INTERNAL_ISR_TABLE_OFFSET + 24)
++#define INTERRUPT_ID_DG (INTERNAL_ISR_TABLE_OFFSET + 25)
++
++
++#endif /* __BCM6348_H */
++
+diff -urN linux.old/arch/mips/bcm963xx/include/6348_map_part.h linux.dev/arch/mips/bcm963xx/include/6348_map_part.h
+--- linux.old/arch/mips/bcm963xx/include/6348_map_part.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/include/6348_map_part.h 2006-08-25 00:39:38.000000000 +0200
+@@ -0,0 +1,500 @@
++/*
++<:copyright-gpl
++ Copyright 2002 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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 __BCM6348_MAP_H
++#define __BCM6348_MAP_H
++
++#include "bcmtypes.h"
++
++#define PERF_BASE 0xfffe0000
++#define TIMR_BASE 0xfffe0200
++#define UART_BASE 0xfffe0300
++#define GPIO_BASE 0xfffe0400
++#define MPI_BASE 0xfffe2000 /* MPI control registers */
++#define USB_HOST_BASE 0xfffe1b00 /* USB host registers */
++#define USB_HOST_NON_OHCI 0xfffe1c00 /* USB host non-OHCI registers */
++
++typedef struct PerfControl {
++ uint32 RevID;
++ uint16 testControl;
++ uint16 blkEnables;
++#define EMAC_CLK_EN 0x0010
++#define SAR_CLK_EN 0x0020
++#define USBS_CLK_EN 0x0040
++#define USBH_CLK_EN 0x0100
++
++ uint32 pll_control;
++#define SOFT_RESET 0x00000001
++
++ uint32 IrqMask;
++ uint32 IrqStatus;
++
++ uint32 ExtIrqCfg;
++#define EI_SENSE_SHFT 0
++#define EI_STATUS_SHFT 5
++#define EI_CLEAR_SHFT 10
++#define EI_MASK_SHFT 15
++#define EI_INSENS_SHFT 20
++#define EI_LEVEL_SHFT 25
++
++ uint32 unused[4]; /* (18) */
++ uint32 BlockSoftReset; /* (28) */
++#define BSR_SPI 0x00000001
++#define BSR_EMAC 0x00000004
++#define BSR_USBH 0x00000008
++#define BSR_USBS 0x00000010
++#define BSR_ADSL 0x00000020
++#define BSR_DMAMEM 0x00000040
++#define BSR_SAR 0x00000080
++#define BSR_ACLC 0x00000100
++#define BSR_ADSL_MIPS_PLL 0x00000400
++#define BSR_ALL_BLOCKS \
++ (BSR_SPI | BSR_EMAC | BSR_USBH | BSR_USBS | BSR_ADSL | BSR_DMAMEM | \
++ BSR_SAR | BSR_ACLC | BSR_ADSL_MIPS_PLL)
++ uint32 unused2[2]; /* (2c) */
++ uint32 PllStrap; /* (34) */
++#define PLL_N1_SHFT 20
++#define PLL_N1_MASK (7<<PLL_N1_SHFT)
++#define PLL_N2_SHFT 15
++#define PLL_N2_MASK (0x1f<<PLL_N2_SHFT)
++#define PLL_M1_REF_SHFT 12
++#define PLL_M1_REF_MASK (7<<PLL_M1_REF_SHFT)
++#define PLL_M2_REF_SHFT 9
++#define PLL_M2_REF_MASK (7<<PLL_M2_REF_SHFT)
++#define PLL_M1_CPU_SHFT 6
++#define PLL_M1_CPU_MASK (7<<PLL_M1_CPU_SHFT)
++#define PLL_M1_BUS_SHFT 3
++#define PLL_M1_BUS_MASK (7<<PLL_M1_BUS_SHFT)
++#define PLL_M2_BUS_SHFT 0
++#define PLL_M2_BUS_MASK (7<<PLL_M2_BUS_SHFT)
++} PerfControl;
++
++#define PERF ((volatile PerfControl * const) PERF_BASE)
++
++typedef struct Timer {
++ uint16 unused0;
++ byte TimerMask;
++#define TIMER0EN 0x01
++#define TIMER1EN 0x02
++#define TIMER2EN 0x04
++ byte TimerInts;
++#define TIMER0 0x01
++#define TIMER1 0x02
++#define TIMER2 0x04
++#define WATCHDOG 0x08
++ uint32 TimerCtl0;
++ uint32 TimerCtl1;
++ uint32 TimerCtl2;
++#define TIMERENABLE 0x80000000
++#define RSTCNTCLR 0x40000000
++ uint32 TimerCnt0;
++ uint32 TimerCnt1;
++ uint32 TimerCnt2;
++ uint32 WatchDogDefCount;
++
++ /* Write 0xff00 0x00ff to Start timer
++ * Write 0xee00 0x00ee to Stop and re-load default count
++ * Read from this register returns current watch dog count
++ */
++ uint32 WatchDogCtl;
++
++ /* Number of 40-MHz ticks for WD Reset pulse to last */
++ uint32 WDResetCount;
++} Timer;
++
++#define TIMER ((volatile Timer * const) TIMR_BASE)
++
++typedef struct UartChannel {
++ byte unused0;
++ byte control;
++#define BRGEN 0x80 /* Control register bit defs */
++#define TXEN 0x40
++#define RXEN 0x20
++#define LOOPBK 0x10
++#define TXPARITYEN 0x08
++#define TXPARITYEVEN 0x04
++#define RXPARITYEN 0x02
++#define RXPARITYEVEN 0x01
++
++ byte config;
++#define XMITBREAK 0x40
++#define BITS5SYM 0x00
++#define BITS6SYM 0x10
++#define BITS7SYM 0x20
++#define BITS8SYM 0x30
++#define ONESTOP 0x07
++#define TWOSTOP 0x0f
++ /* 4-LSBS represent STOP bits/char
++ * in 1/8 bit-time intervals. Zero
++ * represents 1/8 stop bit interval.
++ * Fifteen represents 2 stop bits.
++ */
++ byte fifoctl;
++#define RSTTXFIFOS 0x80
++#define RSTRXFIFOS 0x40
++ /* 5-bit TimeoutCnt is in low bits of this register.
++ * This count represents the number of characters
++ * idle times before setting receive Irq when below threshold
++ */
++ uint32 baudword;
++ /* When divide SysClk/2/(1+baudword) we should get 32*bit-rate
++ */
++
++ byte txf_levl; /* Read-only fifo depth */
++ byte rxf_levl; /* Read-only fifo depth */
++ byte fifocfg; /* Upper 4-bits are TxThresh, Lower are
++ * RxThreshold. Irq can be asserted
++ * when rx fifo> thresh, txfifo<thresh
++ */
++ byte prog_out; /* Set value of DTR (Bit0), RTS (Bit1)
++ * if these bits are also enabled to GPIO_o
++ */
++#define DTREN 0x01
++#define RTSEN 0x02
++
++ byte unused1;
++ byte DeltaIPEdgeNoSense; /* Low 4-bits, set corr bit to 1 to
++ * detect irq on rising AND falling
++ * edges for corresponding GPIO_i
++ * if enabled (edge insensitive)
++ */
++ byte DeltaIPConfig_Mask; /* Upper 4 bits: 1 for posedge sense
++ * 0 for negedge sense if
++ * not configured for edge
++ * insensitive (see above)
++ * Lower 4 bits: Mask to enable change
++ * detection IRQ for corresponding
++ * GPIO_i
++ */
++ byte DeltaIP_SyncIP; /* Upper 4 bits show which bits
++ * have changed (may set IRQ).
++ * read automatically clears bit
++ * Lower 4 bits are actual status
++ */
++
++ uint16 intMask; /* Same Bit defs for Mask and status */
++ uint16 intStatus;
++#define DELTAIP 0x0001
++#define TXUNDERR 0x0002
++#define TXOVFERR 0x0004
++#define TXFIFOTHOLD 0x0008
++#define TXREADLATCH 0x0010
++#define TXFIFOEMT 0x0020
++#define RXUNDERR 0x0040
++#define RXOVFERR 0x0080
++#define RXTIMEOUT 0x0100
++#define RXFIFOFULL 0x0200
++#define RXFIFOTHOLD 0x0400
++#define RXFIFONE 0x0800
++#define RXFRAMERR 0x1000
++#define RXPARERR 0x2000
++#define RXBRK 0x4000
++
++ uint16 unused2;
++ uint16 Data; /* Write to TX, Read from RX */
++ /* bits 11:8 are BRK,PAR,FRM errors */
++
++ uint32 unused3;
++ uint32 unused4;
++} Uart;
++
++#define UART ((volatile Uart * const) UART_BASE)
++
++typedef struct GpioControl {
++ uint32 GPIODir_high; /* bits 36:32 */
++ uint32 GPIODir; /* bits 31:00 */
++ uint32 GPIOio_high; /* bits 36:32 */
++ uint32 GPIOio; /* bits 31:00 */
++ uint32 LEDCtrl;
++#define LED3_STROBE 0x08000000
++#define LED2_STROBE 0x04000000
++#define LED1_STROBE 0x02000000
++#define LED0_STROBE 0x01000000
++#define LED_TEST 0x00010000
++#define LED3_DISABLE_LINK_ACT 0x00008000
++#define LED2_DISABLE_LINK_ACT 0x00004000
++#define LED1_DISABLE_LINK_ACT 0x00002000
++#define LED0_DISABLE_LINK_ACT 0x00001000
++#define LED_INTERVAL_SET_MASK 0x00000f00
++#define LED_INTERVAL_SET_320MS 0x00000500
++#define LED_INTERVAL_SET_160MS 0x00000400
++#define LED_INTERVAL_SET_80MS 0x00000300
++#define LED_INTERVAL_SET_40MS 0x00000200
++#define LED_INTERVAL_SET_20MS 0x00000100
++#define LED3_ON 0x00000080
++#define LED2_ON 0x00000040
++#define LED1_ON 0x00000020
++#define LED0_ON 0x00000010
++#define LED3_ENABLE 0x00000008
++#define LED2_ENABLE 0x00000004
++#define LED1_ENABLE 0x00000002
++#define LED0_ENABLE 0x00000001
++ uint32 SpiSlaveCfg;
++#define SPI_SLAVE_RESET 0x00010000
++#define SPI_RESTRICT 0x00000400
++#define SPI_DELAY_DISABLE 0x00000200
++#define SPI_PROBE_MUX_SEL_MASK 0x000001e0
++#define SPI_SER_ADDR_CFG_MASK 0x0000000c
++#define SPI_MODE 0x00000001
++ uint32 GPIOMode;
++#define GROUP4_DIAG 0x00090000
++#define GROUP4_UTOPIA 0x00080000
++#define GROUP4_LEGACY_LED 0x00030000
++#define GROUP4_MII_SNOOP 0x00020000
++#define GROUP4_EXT_EPHY 0x00010000
++#define GROUP3_DIAG 0x00009000
++#define GROUP3_UTOPIA 0x00008000
++#define GROUP3_EXT_MII 0x00007000
++#define GROUP2_DIAG 0x00000900
++#define GROUP2_PCI 0x00000500
++#define GROUP1_DIAG 0x00000090
++#define GROUP1_UTOPIA 0x00000080
++#define GROUP1_SPI_UART 0x00000060
++#define GROUP1_SPI_MASTER 0x00000060
++#define GROUP1_MII_PCCARD 0x00000040
++#define GROUP1_MII_SNOOP 0x00000020
++#define GROUP1_EXT_EPHY 0x00000010
++#define GROUP0_DIAG 0x00000009
++#define GROUP0_EXT_MII 0x00000007
++
++} GpioControl;
++
++#define GPIO ((volatile GpioControl * const) GPIO_BASE)
++
++/* Number to mask conversion macro used for GPIODir and GPIOio */
++#define GPIO_NUM_TOTAL_BITS_MASK 0x3f
++#define GPIO_NUM_MAX_BITS_MASK 0x1f
++#define GPIO_NUM_TO_MASK(X) ( (((X) & GPIO_NUM_TOTAL_BITS_MASK) < 32) ? (1 << ((X) & GPIO_NUM_MAX_BITS_MASK)) : (0) )
++
++/* Number to mask conversion macro used for GPIODir_high and GPIOio_high */
++#define GPIO_NUM_MAX_BITS_MASK_HIGH 0x07
++#define GPIO_NUM_TO_MASK_HIGH(X) ( (((X) & GPIO_NUM_TOTAL_BITS_MASK) >= 32) ? (1 << ((X-32) & GPIO_NUM_MAX_BITS_MASK_HIGH)) : (0) )
++
++
++/*
++** External Bus Interface
++*/
++typedef struct EbiChipSelect {
++ uint32 base; /* base address in upper 24 bits */
++#define EBI_SIZE_8K 0
++#define EBI_SIZE_16K 1
++#define EBI_SIZE_32K 2
++#define EBI_SIZE_64K 3
++#define EBI_SIZE_128K 4
++#define EBI_SIZE_256K 5
++#define EBI_SIZE_512K 6
++#define EBI_SIZE_1M 7
++#define EBI_SIZE_2M 8
++#define EBI_SIZE_4M 9
++#define EBI_SIZE_8M 10
++#define EBI_SIZE_16M 11
++#define EBI_SIZE_32M 12
++#define EBI_SIZE_64M 13
++#define EBI_SIZE_128M 14
++#define EBI_SIZE_256M 15
++ uint32 config;
++#define EBI_ENABLE 0x00000001 /* .. enable this range */
++#define EBI_WAIT_STATES 0x0000000e /* .. mask for wait states */
++#define EBI_WTST_SHIFT 1 /* .. for shifting wait states */
++#define EBI_WORD_WIDE 0x00000010 /* .. 16-bit peripheral, else 8 */
++#define EBI_WREN 0x00000020 /* enable posted writes */
++#define EBI_POLARITY 0x00000040 /* .. set to invert something,
++ ** don't know what yet */
++#define EBI_TS_TA_MODE 0x00000080 /* .. use TS/TA mode */
++#define EBI_TS_SEL 0x00000100 /* .. drive tsize, not bs_b */
++#define EBI_FIFO 0x00000200 /* .. use fifo */
++#define EBI_RE 0x00000400 /* .. Reverse Endian */
++} EbiChipSelect;
++
++typedef struct MpiRegisters {
++ EbiChipSelect cs[7]; /* size chip select configuration */
++#define EBI_CS0_BASE 0
++#define EBI_CS1_BASE 1
++#define EBI_CS2_BASE 2
++#define EBI_CS3_BASE 3
++#define PCMCIA_COMMON_BASE 4
++#define PCMCIA_ATTRIBUTE_BASE 5
++#define PCMCIA_IO_BASE 6
++ uint32 unused0[2]; /* reserved */
++ uint32 ebi_control; /* ebi control */
++ uint32 unused1[4]; /* reserved */
++#define EBI_ACCESS_TIMEOUT 0x000007FF
++ uint32 pcmcia_cntl1; /* pcmcia control 1 */
++#define PCCARD_CARD_RESET 0x00040000
++#define CARDBUS_ENABLE 0x00008000
++#define PCMCIA_ENABLE 0x00004000
++#define PCMCIA_GPIO_ENABLE 0x00002000
++#define CARDBUS_IDSEL 0x00001F00
++#define VS2_OEN 0x00000080
++#define VS1_OEN 0x00000040
++#define VS2_OUT 0x00000020
++#define VS1_OUT 0x00000010
++#define VS2_IN 0x00000008
++#define VS1_IN 0x00000004
++#define CD2_IN 0x00000002
++#define CD1_IN 0x00000001
++#define VS_MASK 0x0000000C
++#define CD_MASK 0x00000003
++ uint32 unused2; /* reserved */
++ uint32 pcmcia_cntl2; /* pcmcia control 2 */
++#define PCMCIA_BYTESWAP_DIS 0x00000002
++#define PCMCIA_HALFWORD_EN 0x00000001
++#define RW_ACTIVE_CNT_BIT 2
++#define INACTIVE_CNT_BIT 8
++#define CE_SETUP_CNT_BIT 16
++#define CE_HOLD_CNT_BIT 24
++ uint32 unused3[40]; /* reserved */
++
++ uint32 sp0range; /* PCI to internal system bus address space */
++ uint32 sp0remap;
++ uint32 sp0cfg;
++ uint32 sp1range;
++ uint32 sp1remap;
++ uint32 sp1cfg;
++
++ uint32 EndianCfg;
++
++ uint32 l2pcfgctl; /* internal system bus to PCI IO/Cfg control */
++#define DIR_CFG_SEL 0x80000000 /* change from PCI I/O access to PCI config access */
++#define DIR_CFG_USEREG 0x40000000 /* use this register info for PCI configuration access */
++#define DEVICE_NUMBER 0x00007C00 /* device number for the PCI configuration access */
++#define FUNC_NUMBER 0x00000300 /* function number for the PCI configuration access */
++#define REG_NUMBER 0x000000FC /* register number for the PCI configuration access */
++#define CONFIG_TYPE 0x00000003 /* configuration type for the PCI configuration access */
++
++ uint32 l2pmrange1; /* internal system bus to PCI memory space */
++#define PCI_SIZE_64K 0xFFFF0000
++#define PCI_SIZE_128K 0xFFFE0000
++#define PCI_SIZE_256K 0xFFFC0000
++#define PCI_SIZE_512K 0xFFF80000
++#define PCI_SIZE_1M 0xFFF00000
++#define PCI_SIZE_2M 0xFFE00000
++#define PCI_SIZE_4M 0xFFC00000
++#define PCI_SIZE_8M 0xFF800000
++#define PCI_SIZE_16M 0xFF000000
++#define PCI_SIZE_32M 0xFE000000
++ uint32 l2pmbase1; /* kseg0 or kseg1 address & 0x1FFFFFFF */
++ uint32 l2pmremap1;
++#define CARDBUS_MEM 0x00000004
++#define MEM_WINDOW_EN 0x00000001
++ uint32 l2pmrange2;
++ uint32 l2pmbase2;
++ uint32 l2pmremap2;
++ uint32 l2piorange; /* internal system bus to PCI I/O space */
++ uint32 l2piobase;
++ uint32 l2pioremap;
++
++ uint32 pcimodesel;
++#define PCI2_INT_BUS_RD_PREFECH 0x000000F0
++#define PCI_BAR2_NOSWAP 0x00000002 /* BAR at offset 0x20 */
++#define PCI_BAR1_NOSWAP 0x00000001 /* BAR at affset 0x1c */
++
++ uint32 pciintstat; /* PCI interrupt mask/status */
++#define MAILBOX1_SENT 0x08
++#define MAILBOX0_SENT 0x04
++#define MAILBOX1_MSG_RCV 0x02
++#define MAILBOX0_MSG_RCV 0x01
++ uint32 locbuscntrl; /* internal system bus control */
++#define DIR_U2P_NOSWAP 0x00000002
++#define EN_PCI_GPIO 0x00000001
++ uint32 locintstat; /* internal system bus interrupt mask/status */
++#define CSERR 0x0200
++#define SERR 0x0100
++#define EXT_PCI_INT 0x0080
++#define DIR_FAILED 0x0040
++#define DIR_COMPLETE 0x0020
++#define PCI_CFG 0x0010
++ uint32 unused5[7];
++
++ uint32 mailbox0;
++ uint32 mailbox1;
++
++ uint32 pcicfgcntrl; /* internal system bus PCI configuration control */
++#define PCI_CFG_REG_WRITE_EN 0x00000080
++#define PCI_CFG_ADDR 0x0000003C
++ uint32 pcicfgdata; /* internal system bus PCI configuration data */
++
++ uint32 locch2ctl; /* PCI to interrnal system bus DMA (downstream) local control */
++#define MPI_DMA_HALT 0x00000008 /* idle after finish current memory burst */
++#define MPI_DMA_PKT_HALT 0x00000004 /* idle after an EOP flag is detected */
++#define MPI_DMA_STALL 0x00000002 /* idle after an EOP flag is detected */
++#define MPI_DMA_ENABLE 0x00000001 /* set to enable channel */
++ uint32 locch2intStat;
++#define MPI_DMA_NO_DESC 0x00000004 /* no valid descriptors */
++#define MPI_DMA_DONE 0x00000002 /* packet xfer complete */
++#define MPI_DMA_BUFF_DONE 0x00000001 /* buffer done */
++ uint32 locch2intMask;
++ uint32 unused6;
++ uint32 locch2descaddr;
++ uint32 locch2status1;
++#define LOCAL_DESC_STATE 0xE0000000
++#define PCI_DESC_STATE 0x1C000000
++#define BYTE_DONE 0x03FFC000
++#define RING_ADDR 0x00003FFF
++ uint32 locch2status2;
++#define BUFPTR_OFFSET 0x1FFF0000
++#define PCI_MASTER_STATE 0x000000C0
++#define LOC_MASTER_STATE 0x00000038
++#define CONTROL_STATE 0x00000007
++ uint32 unused7;
++
++ uint32 locch1Ctl; /*internal system bus to PCI DMA (upstream) local control */
++#define DMA_U2P_LE 0x00000200 /* local bus is little endian */
++#define DMA_U2P_NOSWAP 0x00000100 /* lccal bus is little endian but no data swapped */
++ uint32 locch1intstat;
++ uint32 locch1intmask;
++ uint32 unused8;
++ uint32 locch1descaddr;
++ uint32 locch1status1;
++ uint32 locch1status2;
++ uint32 unused9;
++
++ uint32 pcich1ctl; /* internal system bus to PCI DMA PCI control */
++ uint32 pcich1intstat;
++ uint32 pcich1intmask;
++ uint32 pcich1descaddr;
++ uint32 pcich1status1;
++ uint32 pcich1status2;
++
++ uint32 pcich2Ctl; /* PCI to internal system bus DMA PCI control */
++ uint32 pcich2intstat;
++ uint32 pcich2intmask;
++ uint32 pcich2descaddr;
++ uint32 pcich2status1;
++ uint32 pcich2status2;
++
++ uint32 perm_id; /* permanent device and vendor id */
++ uint32 perm_rev; /* permanent revision id */
++} MpiRegisters;
++
++#define MPI ((volatile MpiRegisters * const) MPI_BASE)
++
++/* PCI configuration address space start offset 0x40 */
++#define BRCM_PCI_CONFIG_TIMER 0x40
++#define BRCM_PCI_CONFIG_TIMER_RETRY_MASK 0x0000FF00
++#define BRCM_PCI_CONFIG_TIMER_TRDY_MASK 0x000000FF
++
++/* USB host non-Open HCI register, USB_HOST_NON_OHCI, bit definitions. */
++#define NON_OHCI_ENABLE_PORT1 0x00000001 /* Use USB port 1 for host, not dev */
++#define NON_OHCI_BYTE_SWAP 0x00000008 /* Swap USB host registers */
++
++#define USBH_NON_OHCI ((volatile unsigned long * const) USB_HOST_NON_OHCI)
++
++#endif
++
+diff -urN linux.old/arch/mips/bcm963xx/include/bcm_intr.h linux.dev/arch/mips/bcm963xx/include/bcm_intr.h
+--- linux.old/arch/mips/bcm963xx/include/bcm_intr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/include/bcm_intr.h 2006-08-25 00:39:38.000000000 +0200
+@@ -0,0 +1,59 @@
++/*
++<:copyright-gpl
++ Copyright 2003 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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 __BCM_INTR_H
++#define __BCM_INTR_H
++
++#ifdef __cplusplus
++ extern "C" {
++#endif
++
++#if defined(CONFIG_BCM96338)
++#include <6338_intr.h>
++#endif
++#if defined(CONFIG_BCM96345)
++#include <6345_intr.h>
++#endif
++#if defined(CONFIG_BCM96348)
++#include <6348_intr.h>
++#endif
++
++/* defines */
++struct pt_regs;
++typedef int (*FN_HANDLER) (int, void *, struct pt_regs *);
++
++/* prototypes */
++extern void enable_brcm_irq(unsigned int irq);
++extern void disable_brcm_irq(unsigned int irq);
++extern int request_external_irq(unsigned int irq,
++ FN_HANDLER handler, unsigned long irqflags,
++ const char * devname, void *dev_id);
++extern unsigned int BcmHalMapInterrupt(FN_HANDLER isr, unsigned int param,
++ unsigned int interruptId);
++extern void dump_intr_regs(void);
++
++/* compatibility definitions */
++#define BcmHalInterruptEnable(irq) enable_brcm_irq( irq )
++#define BcmHalInterruptDisable(irq) disable_brcm_irq( irq )
++
++#ifdef __cplusplus
++ }
++#endif
++
++#endif
+diff -urN linux.old/arch/mips/bcm963xx/include/bcm_map_part.h linux.dev/arch/mips/bcm963xx/include/bcm_map_part.h
+--- linux.old/arch/mips/bcm963xx/include/bcm_map_part.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/include/bcm_map_part.h 2006-08-25 00:39:38.000000000 +0200
+@@ -0,0 +1,34 @@
++/*
++<:copyright-gpl
++ Copyright 2004 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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 __BCM_MAP_PART_H
++#define __BCM_MAP_PART_H
++
++#if defined(CONFIG_BCM96338)
++#include <6338_map_part.h>
++#endif
++#if defined(CONFIG_BCM96345)
++#include <6345_map_part.h>
++#endif
++#if defined(CONFIG_BCM96348)
++#include <6348_map_part.h>
++#endif
++
++#endif
++
+diff -urN linux.old/arch/mips/bcm963xx/include/bcmpci.h linux.dev/arch/mips/bcm963xx/include/bcmpci.h
+--- linux.old/arch/mips/bcm963xx/include/bcmpci.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/include/bcmpci.h 2006-08-25 00:39:38.000000000 +0200
+@@ -0,0 +1,87 @@
++/*
++<:copyright-gpl
++ Copyright 2004 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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.
++:>
++*/
++
++//
++// bcmpci.h - bcm96348 PCI, Cardbus, and PCMCIA definition
++//
++#ifndef BCMPCI_H
++#define BCMPCI_H
++
++/* Memory window in internal system bus address space */
++#define BCM_PCI_MEM_BASE 0x08000000
++/* IO window in internal system bus address space */
++#define BCM_PCI_IO_BASE 0x0C000000
++
++#define BCM_PCI_ADDR_MASK 0x1fffffff
++
++/* Memory window size (range) */
++#define BCM_PCI_MEM_SIZE_16MB 0x01000000
++/* IO window size (range) */
++#define BCM_PCI_IO_SIZE_64KB 0x00010000
++
++/* PCI Configuration and I/O space acesss */
++#define BCM_PCI_CFG(d, f, o) ( (d << 11) | (f << 8) | (o/4 << 2) )
++
++/* fake USB PCI slot */
++#define USB_HOST_SLOT 9
++#define USB_BAR0_MEM_SIZE 0x0800
++
++#define BCM_HOST_MEM_SPACE1 0x10000000
++#define BCM_HOST_MEM_SPACE2 0x00000000
++
++/*
++ * EBI bus clock is 33MHz and share with PCI bus
++ * each clock cycle is 30ns.
++ */
++/* attribute memory access wait cnt for 4306 */
++#define PCMCIA_ATTR_CE_HOLD 3 // data hold time 70ns
++#define PCMCIA_ATTR_CE_SETUP 3 // data setup time 50ns
++#define PCMCIA_ATTR_INACTIVE 6 // time between read/write cycles 180ns. For the total cycle time 600ns (cnt1+cnt2+cnt3+cnt4)
++#define PCMCIA_ATTR_ACTIVE 10 // OE/WE pulse width 300ns
++
++/* common memory access wait cnt for 4306 */
++#define PCMCIA_MEM_CE_HOLD 1 // data hold time 30ns
++#define PCMCIA_MEM_CE_SETUP 1 // data setup time 30ns
++#define PCMCIA_MEM_INACTIVE 2 // time between read/write cycles 40ns. For the total cycle time 250ns (cnt1+cnt2+cnt3+cnt4)
++#define PCMCIA_MEM_ACTIVE 5 // OE/WE pulse width 150ns
++
++#define PCCARD_VCC_MASK 0x00070000 // Mask Reset also
++#define PCCARD_VCC_33V 0x00010000
++#define PCCARD_VCC_50V 0x00020000
++
++typedef enum {
++ MPI_CARDTYPE_NONE, // No Card in slot
++ MPI_CARDTYPE_PCMCIA, // 16-bit PCMCIA card in slot
++ MPI_CARDTYPE_CARDBUS, // 32-bit CardBus card in slot
++} CardType;
++
++#define CARDBUS_SLOT 0 // Slot 0 is default for CardBus
++
++#define pcmciaAttrOffset 0x00200000
++#define pcmciaMemOffset 0x00000000
++// Needs to be right above PCI I/O space. Give 0x8000 (32K) to PCMCIA.
++#define pcmciaIoOffset (BCM_PCI_IO_BASE + 0x80000)
++// Base Address is that mapped into the MPI ChipSelect registers.
++// UBUS bridge MemoryWindow 0 outputs a 0x00 for the base.
++#define pcmciaBase 0xbf000000
++#define pcmciaAttr (pcmciaAttrOffset | pcmciaBase)
++#define pcmciaMem (pcmciaMemOffset | pcmciaBase)
++#define pcmciaIo (pcmciaIoOffset | pcmciaBase)
++
++#endif
+diff -urN linux.old/arch/mips/bcm963xx/include/bcmTag.h linux.dev/arch/mips/bcm963xx/include/bcmTag.h
+--- linux.old/arch/mips/bcm963xx/include/bcmTag.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/include/bcmTag.h 2006-08-25 00:39:38.000000000 +0200
+@@ -0,0 +1,153 @@
++/*
++<:copyright-gpl
++ Copyright 2002 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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.
++:>
++*/
++//**************************************************************************************
++// File Name : bcmTag.h
++//
++// Description: add tag with validation system to the firmware image file to be uploaded
++// via http
++//
++// Created : 02/28/2002 seanl
++//**************************************************************************************
++
++#ifndef _BCMTAG_H_
++#define _BCMTAG_H_
++
++
++#define BCM_SIG_1 "Broadcom Corporation"
++#define BCM_SIG_2 "ver. 2.0" // was "firmware version 2.0" now it is split 6 char out for chip id.
++
++#define BCM_TAG_VER "6"
++#define BCM_TAG_VER_LAST "26"
++
++// file tag (head) structure all is in clear text except validationTokens (crc, md5, sha1, etc). Total: 128 unsigned chars
++#define TAG_LEN 256
++#define TAG_VER_LEN 4
++#define SIG_LEN 20
++#define SIG_LEN_2 14 // Original second SIG = 20 is now devided into 14 for SIG_LEN_2 and 6 for CHIP_ID
++#define CHIP_ID_LEN 6
++#define IMAGE_LEN 10
++#define ADDRESS_LEN 12
++#define FLAG_LEN 2
++#define TOKEN_LEN 20
++#define BOARD_ID_LEN 16
++#define RESERVED_LEN (TAG_LEN - TAG_VER_LEN - SIG_LEN - SIG_LEN_2 - CHIP_ID_LEN - BOARD_ID_LEN - \
++ (4*IMAGE_LEN) - (3*ADDRESS_LEN) - (3*FLAG_LEN) - (2*TOKEN_LEN))
++
++
++// TAG for downloadable image (kernel plus file system)
++typedef struct _FILE_TAG
++{
++ unsigned char tagVersion[TAG_VER_LEN]; // tag version. Will be 2 here.
++ unsigned char signiture_1[SIG_LEN]; // text line for company info
++ unsigned char signiture_2[SIG_LEN_2]; // additional info (can be version number)
++ unsigned char chipId[CHIP_ID_LEN]; // chip id
++ unsigned char boardId[BOARD_ID_LEN]; // board id
++ unsigned char bigEndian[FLAG_LEN]; // if = 1 - big, = 0 - little endia of the host
++ unsigned char totalImageLen[IMAGE_LEN]; // the sum of all the following length
++ unsigned char cfeAddress[ADDRESS_LEN]; // if non zero, cfe starting address
++ unsigned char cfeLen[IMAGE_LEN]; // if non zero, cfe size in clear ASCII text.
++ unsigned char rootfsAddress[ADDRESS_LEN]; // if non zero, filesystem starting address
++ unsigned char rootfsLen[IMAGE_LEN]; // if non zero, filesystem size in clear ASCII text.
++ unsigned char kernelAddress[ADDRESS_LEN]; // if non zero, kernel starting address
++ unsigned char kernelLen[IMAGE_LEN]; // if non zero, kernel size in clear ASCII text.
++ unsigned char dualImage[FLAG_LEN]; // if 1, dual image
++ unsigned char inactiveLen[FLAG_LEN]; // if 1, the image is INACTIVE; if 0, active
++ unsigned char reserved[RESERVED_LEN]; // reserved for later use
++ unsigned char imageValidationToken[TOKEN_LEN];// image validation token - can be crc, md5, sha; for
++ // now will be 4 unsigned char crc
++ unsigned char tagValidationToken[TOKEN_LEN]; // validation token for tag(from signiture_1 to end of // mageValidationToken)
++} FILE_TAG, *PFILE_TAG;
++
++#define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */
++#define CRC_LEN 4
++
++// only included if for bcmTag.exe program
++#ifdef BCMTAG_EXE_USE
++
++static unsigned long Crc32_table[256] = {
++ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
++ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
++ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
++ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
++ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
++ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
++ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
++ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
++ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
++ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
++ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
++ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
++ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
++ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
++ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
++ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
++ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
++ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
++ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
++ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
++ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
++ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
++ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
++ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
++ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
++ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
++ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
++ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
++ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
++ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
++ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
++ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
++ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
++ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
++ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
++ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
++ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
++ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
++ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
++ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
++ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
++ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
++ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
++ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
++ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
++ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
++ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
++ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
++ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
++ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
++ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
++ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
++ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
++ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
++ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
++ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
++ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
++ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
++ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
++ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
++ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
++ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
++ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
++ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
++};
++#endif // BCMTAG_USE
++
++
++#endif // _BCMTAG_H_
++
+diff -urN linux.old/arch/mips/bcm963xx/include/bcmtypes.h linux.dev/arch/mips/bcm963xx/include/bcmtypes.h
+--- linux.old/arch/mips/bcm963xx/include/bcmtypes.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/include/bcmtypes.h 2006-08-25 00:39:38.000000000 +0200
+@@ -0,0 +1,163 @@
++/*
++<:copyright-gpl
++ Copyright 2002 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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.
++:>
++*/
++
++//
++// bcmtypes.h - misc useful typedefs
++//
++#ifndef BCMTYPES_H
++#define BCMTYPES_H
++
++// These are also defined in typedefs.h in the application area, so I need to
++// protect against re-definition.
++
++#ifndef _TYPEDEFS_H_
++typedef unsigned char uint8;
++typedef unsigned short uint16;
++typedef unsigned long uint32;
++typedef signed char int8;
++typedef signed short int16;
++typedef signed long int32;
++#if !defined(__cplusplus)
++typedef int bool;
++#endif
++#endif
++
++typedef unsigned char byte;
++// typedef unsigned long sem_t;
++
++typedef unsigned long HANDLE,*PULONG,DWORD,*PDWORD;
++typedef signed long LONG,*PLONG;
++
++typedef unsigned int *PUINT;
++typedef signed int INT;
++
++typedef unsigned short *PUSHORT;
++typedef signed short SHORT,*PSHORT;
++typedef unsigned short WORD,*PWORD;
++
++typedef unsigned char *PUCHAR;
++typedef signed char *PCHAR;
++
++typedef void *PVOID;
++
++typedef unsigned char BOOLEAN, *PBOOL, *PBOOLEAN;
++
++typedef unsigned char BYTE,*PBYTE;
++
++//#ifndef __GNUC__
++//The following has been defined in Vxworks internally: vxTypesOld.h
++//redefine under vxworks will cause error
++typedef signed int *PINT;
++
++typedef signed char INT8;
++typedef signed short INT16;
++typedef signed long INT32;
++
++typedef unsigned char UINT8;
++typedef unsigned short UINT16;
++typedef unsigned long UINT32;
++
++typedef unsigned char UCHAR;
++typedef unsigned short USHORT;
++typedef unsigned int UINT;
++typedef unsigned long ULONG;
++
++typedef void VOID;
++typedef unsigned char BOOL;
++
++//#endif /* __GNUC__ */
++
++
++// These are also defined in typedefs.h in the application area, so I need to
++// protect against re-definition.
++#ifndef TYPEDEFS_H
++
++// Maximum and minimum values for a signed 16 bit integer.
++#define MAX_INT16 32767
++#define MIN_INT16 -32768
++
++// Useful for true/false return values. This uses the
++// Taligent notation (k for constant).
++typedef enum
++{
++ kFalse = 0,
++ kTrue = 1
++} Bool;
++
++#endif
++
++/* macros to protect against unaligned accesses */
++
++#if 0
++/* first arg is an address, second is a value */
++#define PUT16( a, d ) { \
++ *((byte *)a) = (byte)((d)>>8); \
++ *(((byte *)a)+1) = (byte)(d); \
++}
++
++#define PUT32( a, d ) { \
++ *((byte *)a) = (byte)((d)>>24); \
++ *(((byte *)a)+1) = (byte)((d)>>16); \
++ *(((byte *)a)+2) = (byte)((d)>>8); \
++ *(((byte *)a)+3) = (byte)(d); \
++}
++
++/* first arg is an address, returns a value */
++#define GET16( a ) ( \
++ (*((byte *)a) << 8) | \
++ (*(((byte *)a)+1)) \
++)
++
++#define GET32( a ) ( \
++ (*((byte *)a) << 24) | \
++ (*(((byte *)a)+1) << 16) | \
++ (*(((byte *)a)+2) << 8) | \
++ (*(((byte *)a)+3)) \
++)
++#endif
++
++#ifndef YES
++#define YES 1
++#endif
++
++#ifndef NO
++#define NO 0
++#endif
++
++#ifndef IN
++#define IN
++#endif
++
++#ifndef OUT
++#define OUT
++#endif
++
++#ifndef TRUE
++#define TRUE 1
++#endif
++
++#ifndef FALSE
++#define FALSE 0
++#endif
++
++#define READ32(addr) (*(volatile UINT32 *)((ULONG)&addr))
++#define READ16(addr) (*(volatile UINT16 *)((ULONG)&addr))
++#define READ8(addr) (*(volatile UINT8 *)((ULONG)&addr))
++
++#endif
+diff -urN linux.old/arch/mips/bcm963xx/include/board.h linux.dev/arch/mips/bcm963xx/include/board.h
+--- linux.old/arch/mips/bcm963xx/include/board.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/include/board.h 2006-08-25 01:52:34.000000000 +0200
+@@ -0,0 +1,373 @@
++/*
++<:copyright-gpl
++ Copyright 2002 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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: board.h */
++/* DATE: 97/02/18 */
++/* PURPOSE: Board specific information. This module should include */
++/* all base device addresses and board specific macros. */
++/* */
++/***********************************************************************/
++#ifndef _BOARD_H
++#define _BOARD_H
++
++/*****************************************************************************/
++/* Misc board definitions */
++/*****************************************************************************/
++
++#define DYING_GASP_API
++
++/*****************************************************************************/
++/* Physical Memory Map */
++/*****************************************************************************/
++
++#define PHYS_DRAM_BASE 0x00000000 /* Dynamic RAM Base */
++#define PHYS_FLASH_BASE 0x1FC00000 /* Flash Memory */
++
++/*****************************************************************************/
++/* Note that the addresses above are physical addresses and that programs */
++/* have to use converted addresses defined below: */
++/*****************************************************************************/
++#define DRAM_BASE (0x80000000 | PHYS_DRAM_BASE) /* cached DRAM */
++#define DRAM_BASE_NOCACHE (0xA0000000 | PHYS_DRAM_BASE) /* uncached DRAM */
++#define FLASH_BASE (0xA0000000 | PHYS_FLASH_BASE) /* uncached Flash */
++
++/*****************************************************************************/
++/* Select the PLL value to get the desired CPU clock frequency. */
++/* */
++/* */
++/*****************************************************************************/
++#define FPERIPH 50000000
++
++#define ONEK 1024
++#define BLK64K (64*ONEK)
++#define FLASH45_BLKS_BOOT_ROM 1
++#define FLASH45_LENGTH_BOOT_ROM (FLASH45_BLKS_BOOT_ROM * BLK64K)
++#define FLASH_RESERVED_AT_END (64*ONEK) /*reserved for PSI, scratch pad*/
++
++/*****************************************************************************/
++/* Note that the addresses above are physical addresses and that programs */
++/* have to use converted addresses defined below: */
++/*****************************************************************************/
++#define DRAM_BASE (0x80000000 | PHYS_DRAM_BASE) /* cached DRAM */
++#define DRAM_BASE_NOCACHE (0xA0000000 | PHYS_DRAM_BASE) /* uncached DRAM */
++#define FLASH_BASE (0xA0000000 | PHYS_FLASH_BASE) /* uncached Flash */
++
++/*****************************************************************************/
++/* Select the PLL value to get the desired CPU clock frequency. */
++/* */
++/* */
++/*****************************************************************************/
++#define FPERIPH 50000000
++
++#define SDRAM_TYPE_ADDRESS_OFFSET 16
++#define NVRAM_DATA_OFFSET 0x0580
++#define NVRAM_DATA_ID 0x0f1e2d3c
++#define BOARD_SDRAM_TYPE *(unsigned long *) \
++ (FLASH_BASE + SDRAM_TYPE_ADDRESS_OFFSET)
++
++#define ONEK 1024
++#define BLK64K (64*ONEK)
++
++// nvram and psi flash definitions for 45
++#define FLASH45_LENGTH_NVRAM ONEK // 1k nvram
++#define NVRAM_PSI_DEFAULT 24 // default psi in K byes
++
++/*****************************************************************************/
++/* NVRAM Offset and definition */
++/*****************************************************************************/
++
++#define NVRAM_VERSION_NUMBER 2
++#define NVRAM_VERSION_NUMBER_ADDRESS 0
++
++#define NVRAM_BOOTLINE_LEN 256
++#define NVRAM_BOARD_ID_STRING_LEN 16
++#define NVRAM_MAC_ADDRESS_LEN 6
++#define NVRAM_MAC_COUNT_MAX 32
++
++/*****************************************************************************/
++/* Misc Offsets */
++/*****************************************************************************/
++
++#define CFE_VERSION_OFFSET 0x0570
++#define CFE_VERSION_MARK_SIZE 5
++#define CFE_VERSION_SIZE 5
++
++typedef struct
++{
++ unsigned long ulVersion;
++ char szBootline[NVRAM_BOOTLINE_LEN];
++ char szBoardId[NVRAM_BOARD_ID_STRING_LEN];
++ unsigned long ulReserved1[2];
++ unsigned long ulNumMacAddrs;
++ unsigned char ucaBaseMacAddr[NVRAM_MAC_ADDRESS_LEN];
++ char chReserved[2];
++ unsigned long ulCheckSum;
++} NVRAM_DATA, *PNVRAM_DATA;
++
++
++/*****************************************************************************/
++/* board ioctl calls for flash, led and some other utilities */
++/*****************************************************************************/
++
++
++/* Defines. for board driver */
++#define BOARD_IOCTL_MAGIC 'B'
++#define BOARD_DRV_MAJOR 206
++
++#define MAC_ADDRESS_ANY (unsigned long) -1
++
++#define BOARD_IOCTL_FLASH_INIT \
++ _IOWR(BOARD_IOCTL_MAGIC, 0, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_FLASH_WRITE \
++ _IOWR(BOARD_IOCTL_MAGIC, 1, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_FLASH_READ \
++ _IOWR(BOARD_IOCTL_MAGIC, 2, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_GET_NR_PAGES \
++ _IOWR(BOARD_IOCTL_MAGIC, 3, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_DUMP_ADDR \
++ _IOWR(BOARD_IOCTL_MAGIC, 4, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_SET_MEMORY \
++ _IOWR(BOARD_IOCTL_MAGIC, 5, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_MIPS_SOFT_RESET \
++ _IOWR(BOARD_IOCTL_MAGIC, 6, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_LED_CTRL \
++ _IOWR(BOARD_IOCTL_MAGIC, 7, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_GET_ID \
++ _IOWR(BOARD_IOCTL_MAGIC, 8, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_GET_MAC_ADDRESS \
++ _IOWR(BOARD_IOCTL_MAGIC, 9, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_RELEASE_MAC_ADDRESS \
++ _IOWR(BOARD_IOCTL_MAGIC, 10, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_GET_PSI_SIZE \
++ _IOWR(BOARD_IOCTL_MAGIC, 11, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_GET_SDRAM_SIZE \
++ _IOWR(BOARD_IOCTL_MAGIC, 12, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_SET_MONITOR_FD \
++ _IOWR(BOARD_IOCTL_MAGIC, 13, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_WAKEUP_MONITOR_TASK \
++ _IOWR(BOARD_IOCTL_MAGIC, 14, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_GET_BOOTLINE \
++ _IOWR(BOARD_IOCTL_MAGIC, 15, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_SET_BOOTLINE \
++ _IOWR(BOARD_IOCTL_MAGIC, 16, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_GET_BASE_MAC_ADDRESS \
++ _IOWR(BOARD_IOCTL_MAGIC, 17, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_GET_CHIP_ID \
++ _IOWR(BOARD_IOCTL_MAGIC, 18, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_GET_NUM_ENET \
++ _IOWR(BOARD_IOCTL_MAGIC, 19, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_GET_CFE_VER \
++ _IOWR(BOARD_IOCTL_MAGIC, 20, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_GET_ENET_CFG \
++ _IOWR(BOARD_IOCTL_MAGIC, 21, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_GET_WLAN_ANT_INUSE \
++ _IOWR(BOARD_IOCTL_MAGIC, 22, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_SET_TRIGGER_EVENT \
++ _IOWR(BOARD_IOCTL_MAGIC, 23, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_GET_TRIGGER_EVENT \
++ _IOWR(BOARD_IOCTL_MAGIC, 24, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_UNSET_TRIGGER_EVENT \
++ _IOWR(BOARD_IOCTL_MAGIC, 25, BOARD_IOCTL_PARMS)
++
++#define BOARD_IOCTL_SET_SES_LED \
++ _IOWR(BOARD_IOCTL_MAGIC, 26, BOARD_IOCTL_PARMS)
++
++//<<JUNHON, 2004/09/15, get reset button status , tim hou , 05/04/12
++#define RESET_BUTTON_UP 1
++#define RESET_BUTTON_PRESSDOWN 0
++#define BOARD_IOCTL_GET_RESETHOLD \
++ _IOWR(BOARD_IOCTL_MAGIC, 27, BOARD_IOCTL_PARMS)
++//>>JUNHON, 2004/09/15
++
++// for the action in BOARD_IOCTL_PARMS for flash operation
++typedef enum
++{
++ PERSISTENT,
++ NVRAM,
++ BCM_IMAGE_CFE,
++ BCM_IMAGE_FS,
++ BCM_IMAGE_KERNEL,
++ BCM_IMAGE_WHOLE,
++ SCRATCH_PAD,
++ FLASH_SIZE,
++} BOARD_IOCTL_ACTION;
++
++
++typedef struct boardIoctParms
++{
++ char *string;
++ char *buf;
++ int strLen;
++ int offset;
++ BOARD_IOCTL_ACTION action; /* flash read/write: nvram, persistent, bcm image */
++ int result;
++} BOARD_IOCTL_PARMS;
++
++
++// LED defines
++typedef enum
++{
++ kLedAdsl,
++ kLedWireless,
++ kLedUsb,
++ kLedHpna,
++ kLedWanData,
++ kLedPPP,
++ kLedVoip,
++ kLedSes,
++ kLedLan,
++ kLedSelfTest,
++ kLedEnd, // NOTE: Insert the new led name before this one. Alway stay at the end.
++} BOARD_LED_NAME;
++
++typedef enum
++{
++ kLedStateOff, /* turn led off */
++ kLedStateOn, /* turn led on */
++ kLedStateFail, /* turn led on red */
++ kLedStateBlinkOnce, /* blink once, ~100ms and ignore the same call during the 100ms period */
++ kLedStateSlowBlinkContinues, /* slow blink continues at ~600ms interval */
++ kLedStateFastBlinkContinues, /* fast blink continues at ~200ms interval */
++} BOARD_LED_STATE;
++
++
++// virtual and physical map pair defined in board.c
++typedef struct ledmappair
++{
++ BOARD_LED_NAME ledName; // virtual led name
++ BOARD_LED_STATE ledInitState; // initial led state when the board boots.
++ unsigned short ledMask; // physical GPIO pin mask
++ unsigned short ledActiveLow; // reset bit to turn on LED
++ unsigned short ledMaskFail; // physical GPIO pin mask for state failure
++ unsigned short ledActiveLowFail;// reset bit to turn on LED
++} LED_MAP_PAIR, *PLED_MAP_PAIR;
++
++typedef void (*HANDLE_LED_FUNC)(BOARD_LED_NAME ledName, BOARD_LED_STATE ledState);
++
++/* Flash storage address information that is determined by the flash driver. */
++typedef struct flashaddrinfo
++{
++ int flash_persistent_start_blk;
++ int flash_persistent_number_blk;
++ int flash_persistent_length;
++ unsigned long flash_persistent_blk_offset;
++ int flash_scratch_pad_start_blk; // start before psi (SP_BUF_LEN)
++ int flash_scratch_pad_number_blk;
++ int flash_scratch_pad_length;
++ unsigned long flash_scratch_pad_blk_offset;
++ int flash_nvram_start_blk;
++ int flash_nvram_number_blk;
++ int flash_nvram_length;
++ unsigned long flash_nvram_blk_offset;
++} FLASH_ADDR_INFO, *PFLASH_ADDR_INFO;
++
++// scratch pad defines
++/* SP - Persisten Scratch Pad format:
++ sp header : 32 bytes
++ tokenId-1 : 8 bytes
++ tokenId-1 len : 4 bytes
++ tokenId-1 data
++ ....
++ tokenId-n : 8 bytes
++ tokenId-n len : 4 bytes
++ tokenId-n data
++*/
++
++#define MAGIC_NUM_LEN 8
++#define MAGIC_NUMBER "gOGoBrCm"
++#define TOKEN_NAME_LEN 16
++#define SP_VERSION 1
++#define SP_MAX_LEN 8 * 1024 // 8k buf before psi
++#define SP_RESERVERD 16
++
++typedef struct _SP_HEADER
++{
++ char SPMagicNum[MAGIC_NUM_LEN]; // 8 bytes of magic number
++ int SPVersion; // version number
++ int SPUsedLen; // used sp len
++ char SPReserved[SP_RESERVERD]; // reservied, total 32 bytes
++} SP_HEADER, *PSP_HEADER;
++
++typedef struct _TOKEN_DEF
++{
++ char tokenName[TOKEN_NAME_LEN];
++ int tokenLen;
++} SP_TOKEN, *PSP_TOKEN;
++
++
++/*****************************************************************************/
++/* Function Prototypes */
++/*****************************************************************************/
++#if !defined(__ASM_ASM_H)
++void dumpaddr( unsigned char *pAddr, int nLen );
++
++int kerSysNvRamGet(char *string, int strLen, int offset);
++int kerSysNvRamSet(char *string, int strLen, int offset);
++int kerSysPersistentGet(char *string, int strLen, int offset);
++int kerSysPersistentSet(char *string, int strLen, int offset);
++int kerSysScratchPadGet(char *tokName, char *tokBuf, int tokLen);
++int kerSysScratchPadSet(char *tokName, char *tokBuf, int tokLen);
++int kerSysBcmImageSet( int flash_start_addr, char *string, int size);
++int kerSysGetMacAddress( unsigned char *pucaAddr, unsigned long ulId );
++int kerSysReleaseMacAddress( unsigned char *pucaAddr );
++int kerSysGetSdramSize( void );
++void kerSysGetBootline(char *string, int strLen);
++void kerSysSetBootline(char *string, int strLen);
++void kerSysMipsSoftReset(void);
++void kerSysLedCtrl(BOARD_LED_NAME, BOARD_LED_STATE);
++void kerSysLedRegisterHwHandler( BOARD_LED_NAME, HANDLE_LED_FUNC, int );
++int kerSysFlashSizeGet(void);
++void kerSysRegisterDyingGaspHandler(char *devname, void *cbfn, void *context);
++void kerSysDeregisterDyingGaspHandler(char *devname);
++void kerSysWakeupMonitorTask( void );
++#endif
++
++#define BOOT_CFE 0
++#define BOOT_REDBOOT 1
++
++extern int boot_loader_type;
++
++#endif /* _BOARD_H */
++
+diff -urN linux.old/arch/mips/bcm963xx/int-handler.S linux.dev/arch/mips/bcm963xx/int-handler.S
+--- linux.old/arch/mips/bcm963xx/int-handler.S 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/int-handler.S 2006-08-25 02:13:33.000000000 +0200
+@@ -0,0 +1,59 @@
++/*
++<:copyright-gpl
++ Copyright 2002 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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.
++:>
++*/
++/*
++ * Generic interrupt handler for Broadcom MIPS boards
++ */
++
++#include <linux/config.h>
++
++#include <asm/asm.h>
++#include <asm/mipsregs.h>
++#include <asm/regdef.h>
++#include <asm/stackframe.h>
++
++/*
++ * MIPS IRQ Source
++ * -------- ------
++ * 0 Software (ignored)
++ * 1 Software (ignored)
++ * 2 Combined hardware interrupt (hw0)
++ * 3 Hardware
++ * 4 Hardware
++ * 5 Hardware
++ * 6 Hardware
++ * 7 R4k timer
++ */
++
++ .text
++ .set noreorder
++ .set noat
++ .align 5
++ NESTED(brcmIRQ, PT_SIZE, sp)
++ SAVE_ALL
++ CLI
++ .set noreorder
++ .set at
++
++ jal plat_irq_dispatch
++ move a0, sp
++
++ j ret_from_irq
++ nop
++
++ END(brcmIRQ)
+diff -urN linux.old/arch/mips/bcm963xx/irq.c linux.dev/arch/mips/bcm963xx/irq.c
+--- linux.old/arch/mips/bcm963xx/irq.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/irq.c 2006-08-25 03:54:34.000000000 +0200
+@@ -0,0 +1,256 @@
++/*
++<:copyright-gpl
++ Copyright 2002 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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.
++:>
++*/
++/*
++ * Interrupt control functions for Broadcom 963xx MIPS boards
++ */
++
++#include <asm/atomic.h>
++
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/module.h>
++
++#include <asm/irq.h>
++#include <asm/mipsregs.h>
++#include <asm/addrspace.h>
++#include <asm/signal.h>
++#include <bcm_map_part.h>
++#include <bcm_intr.h>
++
++static void irq_dispatch_int(struct pt_regs *regs)
++{
++ unsigned int pendingIrqs;
++ static unsigned int irqBit;
++ static unsigned int isrNumber = 31;
++
++ pendingIrqs = PERF->IrqStatus & PERF->IrqMask;
++ if (!pendingIrqs) {
++ return;
++ }
++
++ while (1) {
++ irqBit <<= 1;
++ isrNumber++;
++ if (isrNumber == 32) {
++ isrNumber = 0;
++ irqBit = 0x1;
++ }
++ if (pendingIrqs & irqBit) {
++ PERF->IrqMask &= ~irqBit; // mask
++ do_IRQ(isrNumber + INTERNAL_ISR_TABLE_OFFSET, regs);
++ break;
++ }
++ }
++}
++
++static void irq_dispatch_ext(uint32 irq, struct pt_regs *regs)
++{
++ if (!(PERF->ExtIrqCfg & (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)))) {
++ printk("**** Ext IRQ mask. Should not dispatch ****\n");
++ }
++ /* disable and clear interrupt in the controller */
++ PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT));
++ PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT));
++ do_IRQ(irq, regs);
++}
++
++
++extern void brcm_timer_interrupt(struct pt_regs *regs);
++
++asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
++{
++ u32 cause;
++ while((cause = (read_c0_cause()& CAUSEF_IP))) {
++ if (cause & CAUSEF_IP7)
++ brcm_timer_interrupt(regs);
++ else if (cause & CAUSEF_IP2)
++ irq_dispatch_int(regs);
++ else if (cause & CAUSEF_IP3)
++ irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_0, regs);
++ else if (cause & CAUSEF_IP4)
++ irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_1, regs);
++ else if (cause & CAUSEF_IP5)
++ irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_2, regs);
++ else if (cause & CAUSEF_IP6)
++ irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_3, regs);
++ local_irq_disable();
++ }
++}
++
++
++void enable_brcm_irq(unsigned int irq)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++ if( irq >= INTERNAL_ISR_TABLE_OFFSET ) {
++ PERF->IrqMask |= (1 << (irq - INTERNAL_ISR_TABLE_OFFSET));
++ }
++ else if (irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3) {
++ /* enable and clear interrupt in the controller */
++ PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT));
++ PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT));
++ }
++ local_irq_restore(flags);
++}
++
++void disable_brcm_irq(unsigned int irq)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++ if( irq >= INTERNAL_ISR_TABLE_OFFSET ) {
++ PERF->IrqMask &= ~(1 << (irq - INTERNAL_ISR_TABLE_OFFSET));
++ }
++ else if (irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3) {
++ /* disable interrupt in the controller */
++ PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT));
++ }
++ local_irq_restore(flags);
++}
++
++void ack_brcm_irq(unsigned int irq)
++{
++ /* Already done in brcm_irq_dispatch */
++}
++
++unsigned int startup_brcm_irq(unsigned int irq)
++{
++ enable_brcm_irq(irq);
++
++ return 0; /* never anything pending */
++}
++
++unsigned int startup_brcm_none(unsigned int irq)
++{
++ return 0;
++}
++
++void end_brcm_irq(unsigned int irq)
++{
++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
++ enable_brcm_irq(irq);
++}
++
++void end_brcm_none(unsigned int irq)
++{
++}
++
++static struct hw_interrupt_type brcm_irq_type = {
++ .typename = "MIPS",
++ .startup = startup_brcm_irq,
++ .shutdown = disable_brcm_irq,
++ .enable = enable_brcm_irq,
++ .disable = disable_brcm_irq,
++ .ack = ack_brcm_irq,
++ .end = end_brcm_irq,
++ .set_affinity = NULL
++};
++
++static struct hw_interrupt_type brcm_irq_no_end_type = {
++ .typename = "MIPS",
++ .startup = startup_brcm_none,
++ .shutdown = disable_brcm_irq,
++ .enable = enable_brcm_irq,
++ .disable = disable_brcm_irq,
++ .ack = ack_brcm_irq,
++ .end = end_brcm_none,
++ .set_affinity = NULL
++};
++
++void __init arch_init_irq(void)
++{
++ int i;
++
++ clear_c0_status(ST0_BEV);
++ change_c0_status(ST0_IM, (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4));
++
++ for (i = 0; i < NR_IRQS; i++) {
++ irq_desc[i].status = IRQ_DISABLED;
++ irq_desc[i].action = 0;
++ irq_desc[i].depth = 1;
++ irq_desc[i].handler = &brcm_irq_type;
++ }
++}
++
++int request_external_irq(unsigned int irq,
++ FN_HANDLER handler,
++ unsigned long irqflags,
++ const char * devname,
++ void *dev_id)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT)); // Clear
++ PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)); // Mask
++ PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_INSENS_SHFT)); // Edge insesnsitive
++ PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_LEVEL_SHFT)); // Level triggered
++ PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_SENSE_SHFT)); // Low level
++
++ local_irq_restore(flags);
++
++ return( request_irq(irq, handler, irqflags, devname, dev_id) );
++}
++
++/* VxWorks compatibility function(s). */
++
++unsigned int BcmHalMapInterrupt(FN_HANDLER pfunc, unsigned int param,
++ unsigned int interruptId)
++{
++ int nRet = -1;
++ char *devname;
++
++ devname = kmalloc(16, GFP_KERNEL);
++ if (devname)
++ sprintf( devname, "brcm_%d", interruptId );
++
++ /* Set the IRQ description to not automatically enable the interrupt at
++ * the end of an ISR. The driver that handles the interrupt must
++ * explicitly call BcmHalInterruptEnable or enable_brcm_irq. This behavior
++ * is consistent with interrupt handling on VxWorks.
++ */
++ irq_desc[interruptId].handler = &brcm_irq_no_end_type;
++
++ if( interruptId >= INTERNAL_ISR_TABLE_OFFSET )
++ {
++ nRet = request_irq( interruptId, pfunc, SA_SAMPLE_RANDOM | SA_INTERRUPT,
++ devname, (void *) param );
++ }
++ else if (interruptId >= INTERRUPT_ID_EXTERNAL_0 && interruptId <= INTERRUPT_ID_EXTERNAL_3)
++ {
++ nRet = request_external_irq( interruptId, pfunc, SA_SAMPLE_RANDOM | SA_INTERRUPT,
++ devname, (void *) param );
++ }
++
++ return( nRet );
++}
++
++
++EXPORT_SYMBOL(enable_brcm_irq);
++EXPORT_SYMBOL(disable_brcm_irq);
++EXPORT_SYMBOL(request_external_irq);
++EXPORT_SYMBOL(BcmHalMapInterrupt);
++
+diff -urN linux.old/arch/mips/bcm963xx/Kconfig linux.dev/arch/mips/bcm963xx/Kconfig
+--- linux.old/arch/mips/bcm963xx/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/Kconfig 2006-08-25 01:22:39.000000000 +0200
+@@ -0,0 +1,138 @@
++# Kernel and Driver configuration for Broadcom Commengine ADSL board
++choice
++ prompt "Broadcom Commengine ADSL board"
++ depends on MIPS_BRCM
++ default BCM96345
++ help
++ Select different Broadcom ADSL board
++
++config BCM96338
++ bool "96338 ADSL board"
++ select DMA_NONCOHERENT
++ select HW_HAS_PCI
++
++config BCM96345
++ bool "96345 ADSL board"
++ select DMA_NONCOHERENT
++ select HW_HAS_PCI
++
++config BCM96348
++ bool "96348 ADSL board"
++ select DMA_NONCOHERENT
++ select HW_HAS_PCI
++
++endchoice
++
++config BCM_BOARD
++ bool "Support for Broadcom Board"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_SERIAL
++ bool "Support for Serial Port"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_ENET
++ tristate "Support for Ethernet"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_USB
++ tristate "Support for USB"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_WLAN
++ tristate "Support for Wireless"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_PCI
++ bool "Support for PCI"
++ depends on BCM96338 || BCM96345 || BCM96348
++ select PCI
++
++config BCM_ATMAPI
++ tristate "Support for ATM"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_ATMTEST
++ tristate "Support for ATM Diagnostic"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_ADSL
++ tristate "Support for ADSL"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_ENDPOINT
++ tristate "Support for VOICE"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_PROCFS
++ tristate "Support for PROCFS"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_VDSL
++ tristate "Support for VDSL"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_SECURITY
++ tristate "Support for SECURITY"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_HPNA
++ tristate "Support for HPNA"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_BOARD_IMPL
++ int "Implementation index for ADSL Board"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_SERIAL_IMPL
++ int "Implementation index for Serial"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_ENET_IMPL
++ int "Implementation index for Ethernet"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_USB_IMPL
++ int "Implementation index for USB"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_WLAN_IMPL
++ int "Implementation index for WIRELESS"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_ATMAPI_IMPL
++ int "Implementation index for ATM"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_ATMTEST_IMPL
++ int "Implementation index for ATM Diagnostic"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_BLAA_IMPL
++ int "Implementation index for BLAA"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_ADSL_IMPL
++ int "Implementation index for ADSL"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_ENDPOINT_IMPL
++ int "Implementation index for VOICE"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_PROCFS_IMPL
++ int "Implementation index for PROCFS"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_VDSL_IMPL
++ int "Implementation index for VDSL"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_SECURITY_IMPL
++ int "Implementation index for SECURITY"
++ depends on BCM96338 || BCM96345 || BCM96348
++
++config BCM_HPNA_IMPL
++ int "Implementation index for HPNA"
++ depends on BCM96338 || BCM96345 || BCM96348
++
+diff -urN linux.old/arch/mips/bcm963xx/Makefile linux.dev/arch/mips/bcm963xx/Makefile
+--- linux.old/arch/mips/bcm963xx/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/Makefile 2006-08-25 02:04:27.000000000 +0200
+@@ -0,0 +1,23 @@
++#
++# Makefile for generic Broadcom MIPS boards
++#
++# Copyright (C) 2004 Broadcom Corporation
++#
++obj-y := irq.o prom.o setup.o time.o ser_init.o bcm63xx_led.o board.o boardparms.o int-handler.o
++
++SRCBASE := $(TOPDIR)
++EXTRA_CFLAGS += -I$(SRCBASE)/include
++#EXTRA_CFLAGS += -I$(INC_ADSLDRV_PATH) -DDBG
++EXTRA_CFLAGS += -I$(INC_ADSLDRV_PATH)
++
++
++ifeq "$(ADSL)" "ANNEX_B"
++EXTRA_CFLAGS += -DADSL_ANNEXB
++endif
++ifeq "$(ADSL)" "SADSL"
++EXTRA_CFLAGS += -DADSL_SADSL
++endif
++ifeq "$(ADSL)" "ANNEX_C"
++EXTRA_CFLAGS += -DADSL_ANNEXC
++endif
++
+diff -urN linux-2.6.17/arch/mips/bcm963xx/prom.c linux-2.6.17-brcm63xx/arch/mips/bcm963xx/prom.c
+--- linux-2.6.17/arch/mips/bcm963xx/prom.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-brcm63xx/arch/mips/bcm963xx/prom.c 2006-08-29 07:10:10.000000000 +0200
+@@ -0,0 +1,143 @@
++/*
++<:copyright-gpl
++ Copyright 2004 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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.
++:>
++*/
++/*
++ * prom.c: PROM library initialization code.
++ *
++ */
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/bootmem.h>
++#include <linux/blkdev.h>
++#include <asm/addrspace.h>
++#include <asm/bootinfo.h>
++#include <asm/cpu.h>
++#include <asm/time.h>
++
++#include <bcm_map_part.h>
++#include <board.h>
++#include "boardparms.h"
++#include "softdsl/AdslCoreDefs.h"
++
++
++//char arcs_cmdline[CL_SIZE] __initdata = {0};
++/* inv_xde */
++int boot_loader_type;
++int prom_argc;
++char **prom_argv, **prom_envp;
++
++extern int do_syslog(int, char *, int);
++extern void serial_init(void);
++extern void __init InitNvramInfo( void );
++extern void kerSysFlashInit( void );
++extern unsigned long get_nvram_start_addr(void);
++void __init create_root_nfs_cmdline( char *cmdline );
++
++#define MACH_BCM MACH_BCM96348
++
++const char *get_system_type(void)
++{
++ /*PNVRAM_DATA pNvramData = (PNVRAM_DATA) get_nvram_start_addr();
++
++ return( pNvramData->szBoardId );*/
++ return "brcm63xx";
++}
++
++unsigned long getMemorySize(void)
++{
++ unsigned long ulSdramType = BOARD_SDRAM_TYPE;
++
++ unsigned long ulSdramSize;
++
++ switch( ulSdramType )
++ {
++ case BP_MEMORY_16MB_1_CHIP:
++ case BP_MEMORY_16MB_2_CHIP:
++ ulSdramSize = 16 * 1024 * 1024;
++ break;
++ case BP_MEMORY_32MB_1_CHIP:
++ case BP_MEMORY_32MB_2_CHIP:
++ ulSdramSize = 32 * 1024 * 1024;
++ break;
++ case BP_MEMORY_64MB_2_CHIP:
++ ulSdramSize = 64 * 1024 * 1024;
++ break;
++ default:
++ ulSdramSize = 8 * 1024 * 1024;
++ break;
++ }
++ if (boot_loader_type == BOOT_CFE)
++ return ulSdramSize;
++ else
++ // assume that there is one contiguous memory map
++ return boot_mem_map.map[0].size;
++}
++
++/* --------------------------------------------------------------------------
++ Name: prom_init
++ -------------------------------------------------------------------------- */
++void __init prom_init(void)
++{
++ extern ulong r4k_interval;
++
++ serial_init();
++
++ prom_argc = fw_arg0;
++ prom_argv = (char **) fw_arg1;
++ prom_envp = (char **) fw_arg2;
++
++ if ((prom_argv > 0x80000000) && (prom_argv < 0x82000000)) {
++ strncpy(arcs_cmdline, prom_argv[1], CL_SIZE);
++ }
++
++ if (strncmp(arcs_cmdline, "boot_loader=RedBoot", 19) != 0) {
++ boot_loader_type = BOOT_CFE;
++ }
++ else {
++ boot_loader_type = BOOT_REDBOOT;
++ }
++
++ do_syslog(8, NULL, 8);
++
++ printk( "%s prom init\n", get_system_type() );
++
++ PERF->IrqMask = 0;
++
++ arcs_cmdline[0] = '\0';
++
++ if (boot_loader_type == BOOT_CFE)
++ add_memory_region(0, (getMemorySize() - ADSL_SDRAM_IMAGE_SIZE), BOOT_MEM_RAM);
++ else
++ add_memory_region(0, (0x01000000 - ADSL_SDRAM_IMAGE_SIZE), BOOT_MEM_RAM);
++
++ mips_machgroup = MACH_GROUP_BRCM;
++ mips_machtype = MACH_BCM;
++
++ BpSetBoardId("96348GW-10");
++}
++
++/* --------------------------------------------------------------------------
++ Name: prom_free_prom_memory
++Abstract:
++ -------------------------------------------------------------------------- */
++void __init prom_free_prom_memory(void)
++{
++
++}
++
+diff -urN linux.old/arch/mips/bcm963xx/ser_init.c linux.dev/arch/mips/bcm963xx/ser_init.c
+--- linux.old/arch/mips/bcm963xx/ser_init.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/ser_init.c 2006-08-25 00:39:38.000000000 +0200
+@@ -0,0 +1,180 @@
++/*
++<:copyright-gpl
++ Copyright 2004 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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.
++:>
++*/
++/*
++ * Broadcom bcm63xx serial port initialization, also prepare for printk
++ * by registering with console_init
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/console.h>
++#include <linux/sched.h>
++
++#include <asm/addrspace.h>
++#include <asm/irq.h>
++#include <asm/reboot.h>
++#include <asm/gdb-stub.h>
++#include <asm/mc146818rtc.h>
++
++#include <bcm_map_part.h>
++#include <board.h>
++
++#define SER63XX_DEFAULT_BAUD 115200
++#define BD_BCM63XX_TIMER_CLOCK_INPUT (FPERIPH)
++#define stUart ((volatile Uart * const) UART_BASE)
++
++// Transmit interrupts
++#define TXINT (TXFIFOEMT | TXUNDERR | TXOVFERR)
++// Receive interrupts
++#define RXINT (RXFIFONE | RXOVFERR)
++
++/* --------------------------------------------------------------------------
++ Name: serial_init
++ Purpose: Initalize the UART
++-------------------------------------------------------------------------- */
++void __init serial_init(void)
++{
++ UINT32 tmpVal = SER63XX_DEFAULT_BAUD;
++ ULONG clockFreqHz;
++
++#if defined(CONFIG_BCM96345)
++ // Make sure clock is ticking
++ PERF->blkEnables |= UART_CLK_EN;
++#endif
++
++ /* Dissable channel's receiver and transmitter. */
++ stUart->control &= ~(BRGEN|TXEN|RXEN);
++
++ /*--------------------------------------------------------------------*/
++ /* Write the table value to the clock select register. */
++ /* DPullen - this is the equation to use: */
++ /* value = clockFreqHz / baud / 32-1; */
++ /* (snmod) Actually you should also take into account any necessary */
++ /* rounding. Divide by 16, look at lsb, if 0, divide by 2 */
++ /* and subtract 1. If 1, just divide by 2 */
++ /*--------------------------------------------------------------------*/
++ clockFreqHz = BD_BCM63XX_TIMER_CLOCK_INPUT;
++ tmpVal = (clockFreqHz / tmpVal) / 16;
++ if( tmpVal & 0x01 )
++ tmpVal /= 2; //Rounding up, so sub is already accounted for
++ else
++ tmpVal = (tmpVal / 2) - 1; // Rounding down so we must sub 1
++ stUart->baudword = tmpVal;
++
++ /* Finally, re-enable the transmitter and receiver. */
++ stUart->control |= (BRGEN|TXEN|RXEN);
++
++ stUart->config = (BITS8SYM | ONESTOP);
++ // Set the FIFO interrupt depth ... stUart->fifocfg = 0xAA;
++ stUart->fifoctl = RSTTXFIFOS | RSTRXFIFOS;
++ stUart->intMask = 0;
++ stUart->intMask = RXINT | TXINT;
++}
++
++
++/* prom_putc()
++ * Output a character to the UART
++ */
++void prom_putc(char c)
++{
++ /* Wait for Tx uffer to empty */
++ while (! (READ16(stUart->intStatus) & TXFIFOEMT));
++ /* Send character */
++ stUart->Data = c;
++}
++
++/* prom_puts()
++ * Write a string to the UART
++ */
++void prom_puts(const char *s)
++{
++ while (*s) {
++ if (*s == '\n') {
++ prom_putc('\r');
++ }
++ prom_putc(*s++);
++ }
++}
++
++
++/* prom_getc_nowait()
++ * Returns a character from the UART
++ * Returns -1 if no characters available or corrupted
++ */
++int prom_getc_nowait(void)
++{
++ uint16 uStatus;
++ int cData = -1;
++
++ uStatus = READ16(stUart->intStatus);
++
++ if (uStatus & RXFIFONE) { /* Do we have a character? */
++ cData = READ16(stUart->Data) & 0xff; /* Read character */
++ if (uStatus & (RXFRAMERR | RXPARERR)) { /* If we got an error, throw it away */
++ cData = -1;
++ }
++ }
++
++ return cData;
++}
++
++/* prom_getc()
++ * Returns a charcter from the serial port
++ * Will block until it receives a valid character
++*/
++char prom_getc(void)
++{
++ int cData = -1;
++
++ /* Loop until we get a valid character */
++ while(cData == -1) {
++ cData = prom_getc_nowait();
++ }
++ return (char) cData;
++}
++
++/* prom_testc()
++ * Returns 0 if no characters available
++ */
++int prom_testc(void)
++{
++ uint16 uStatus;
++
++ uStatus = READ16(stUart->intStatus);
++
++ return (uStatus & RXFIFONE);
++}
++
++#if defined (CONFIG_REMOTE_DEBUG)
++/* Prevent other code from writing to the serial port */
++void _putc(char c) { }
++void _puts(const char *ptr) { }
++#else
++/* Low level outputs call prom routines */
++void _putc(char c) {
++ prom_putc(c);
++}
++void _puts(const char *ptr) {
++ prom_puts(ptr);
++}
++#endif
+diff -urN linux.old/arch/mips/bcm963xx/setup.c linux.dev/arch/mips/bcm963xx/setup.c
+--- linux.old/arch/mips/bcm963xx/setup.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/setup.c 2006-08-25 02:26:58.000000000 +0200
+@@ -0,0 +1,525 @@
++/*
++<:copyright-gpl
++ Copyright 2002 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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.
++:>
++*/
++/*
++ * Generic setup routines for Broadcom 963xx MIPS boards
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/kernel.h>
++#include <linux/kdev_t.h>
++#include <linux/types.h>
++#include <linux/console.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/module.h>
++#include <linux/pm.h>
++
++#include <asm/addrspace.h>
++#include <asm/bcache.h>
++#include <asm/irq.h>
++#include <asm/time.h>
++#include <asm/reboot.h>
++#include <asm/gdb-stub.h>
++
++extern void brcm_time_init(void);
++extern void brcm_timer_setup(struct irqaction *irq);
++extern unsigned long getMemorySize(void);
++
++#if defined(CONFIG_BCM96348) && defined(CONFIG_PCI)
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <bcm_map_part.h>
++#include <bcmpci.h>
++
++static volatile MpiRegisters * mpi = (MpiRegisters *)(MPI_BASE);
++#endif
++
++/* This function should be in a board specific directory. For now,
++ * assume that all boards that include this file use a Broadcom chip
++ * with a soft reset bit in the PLL control register.
++ */
++static void brcm_machine_restart(char *command)
++{
++ const unsigned long ulSoftReset = 0x00000001;
++ unsigned long *pulPllCtrl = (unsigned long *) 0xfffe0008;
++ *pulPllCtrl |= ulSoftReset;
++}
++
++static void brcm_machine_halt(void)
++{
++ printk("System halted\n");
++ while (1);
++}
++
++#if defined(CONFIG_BCM96348) && defined(CONFIG_PCI)
++
++static void mpi_SetLocalPciConfigReg(uint32 reg, uint32 value)
++{
++ /* write index then value */
++ mpi->pcicfgcntrl = PCI_CFG_REG_WRITE_EN + reg;;
++ mpi->pcicfgdata = value;
++}
++
++static uint32 mpi_GetLocalPciConfigReg(uint32 reg)
++{
++ /* write index then get value */
++ mpi->pcicfgcntrl = PCI_CFG_REG_WRITE_EN + reg;;
++ return mpi->pcicfgdata;
++}
++
++/*
++ * mpi_ResetPcCard: Set/Reset the PcCard
++ */
++static void mpi_ResetPcCard(int cardtype, BOOL bReset)
++{
++ if (cardtype == MPI_CARDTYPE_NONE) {
++ return;
++ }
++
++ if (cardtype == MPI_CARDTYPE_CARDBUS) {
++ bReset = ! bReset;
++ }
++
++ if (bReset) {
++ mpi->pcmcia_cntl1 = (mpi->pcmcia_cntl1 & ~PCCARD_CARD_RESET);
++ } else {
++ mpi->pcmcia_cntl1 = (mpi->pcmcia_cntl1 | PCCARD_CARD_RESET);
++ }
++}
++
++/*
++ * mpi_ConfigCs: Configure an MPI/EBI chip select
++ */
++static void mpi_ConfigCs(uint32 cs, uint32 base, uint32 size, uint32 flags)
++{
++ mpi->cs[cs].base = ((base & 0x1FFFFFFF) | size);
++ mpi->cs[cs].config = flags;
++}
++
++/*
++ * mpi_InitPcmciaSpace
++ */
++static void mpi_InitPcmciaSpace(void)
++{
++ // ChipSelect 4 controls PCMCIA Memory accesses
++ mpi_ConfigCs(PCMCIA_COMMON_BASE, pcmciaMem, EBI_SIZE_1M, (EBI_WORD_WIDE|EBI_ENABLE));
++ // ChipSelect 5 controls PCMCIA Attribute accesses
++ mpi_ConfigCs(PCMCIA_ATTRIBUTE_BASE, pcmciaAttr, EBI_SIZE_1M, (EBI_WORD_WIDE|EBI_ENABLE));
++ // ChipSelect 6 controls PCMCIA I/O accesses
++ mpi_ConfigCs(PCMCIA_IO_BASE, pcmciaIo, EBI_SIZE_64K, (EBI_WORD_WIDE|EBI_ENABLE));
++
++ mpi->pcmcia_cntl2 = ((PCMCIA_ATTR_ACTIVE << RW_ACTIVE_CNT_BIT) |
++ (PCMCIA_ATTR_INACTIVE << INACTIVE_CNT_BIT) |
++ (PCMCIA_ATTR_CE_SETUP << CE_SETUP_CNT_BIT) |
++ (PCMCIA_ATTR_CE_HOLD << CE_HOLD_CNT_BIT));
++
++ mpi->pcmcia_cntl2 |= (PCMCIA_HALFWORD_EN | PCMCIA_BYTESWAP_DIS);
++}
++
++/*
++ * cardtype_vcc_detect: PC Card's card detect and voltage sense connection
++ *
++ * CD1#/ CD2#/ VS1#/ VS2#/ Card Initial Vcc
++ * CCD1# CCD2# CVS1 CVS2 Type
++ *
++ * GND GND open open 16-bit 5 vdc
++ *
++ * GND GND GND open 16-bit 3.3 vdc
++ *
++ * GND GND open GND 16-bit x.x vdc
++ *
++ * GND GND GND GND 16-bit 3.3 & x.x vdc
++ *
++ *====================================================================
++ *
++ * CVS1 GND CCD1# open CardBus 3.3 vdc
++ *
++ * GND CVS2 open CCD2# CardBus x.x vdc
++ *
++ * GND CVS1 CCD2# open CardBus y.y vdc
++ *
++ * GND CVS2 GND CCD2# CardBus 3.3 & x.x vdc
++ *
++ * CVS2 GND open CCD1# CardBus x.x & y.y vdc
++ *
++ * GND CVS1 CCD2# open CardBus 3.3, x.x & y.y vdc
++ *
++ */
++static int cardtype_vcc_detect(void)
++{
++ uint32 data32;
++ int cardtype;
++
++ cardtype = MPI_CARDTYPE_NONE;
++ mpi->pcmcia_cntl1 = 0x0000A000; // Turn on the output enables and drive
++ // the CVS pins to 0.
++ data32 = mpi->pcmcia_cntl1;
++ switch (data32 & 0x00000003) // Test CD1# and CD2#, see if card is plugged in.
++ {
++ case 0x00000003: // No Card is in the slot.
++ printk("mpi: No Card is in the PCMCIA slot\n");
++ break;
++
++ case 0x00000002: // Partial insertion, No CD2#.
++ printk("mpi: Card in the PCMCIA slot partial insertion, no CD2 signal\n");
++ break;
++
++ case 0x00000001: // Partial insertion, No CD1#.
++ printk("mpi: Card in the PCMCIA slot partial insertion, no CD1 signal\n");
++ break;
++
++ case 0x00000000:
++ mpi->pcmcia_cntl1 = 0x0000A0C0; // Turn off the CVS output enables and
++ // float the CVS pins.
++ mdelay(1);
++ data32 = mpi->pcmcia_cntl1;
++ // Read the Register.
++ switch (data32 & 0x0000000C) // See what is on the CVS pins.
++ {
++ case 0x00000000: // CVS1 and CVS2 are tied to ground, only 1 option.
++ printk("mpi: Detected 3.3 & x.x 16-bit PCMCIA card\n");
++ cardtype = MPI_CARDTYPE_PCMCIA;
++ break;
++
++ case 0x00000004: // CVS1 is open or tied to CCD1/CCD2 and CVS2 is tied to ground.
++ // 2 valid voltage options.
++ switch (data32 & 0x00000003) // Test the values of CCD1 and CCD2.
++ {
++ case 0x00000003: // CCD1 and CCD2 are tied to 1 of the CVS pins.
++ // This is not a valid combination.
++ printk("mpi: Unknown card plugged into slot\n");
++ break;
++
++ case 0x00000002: // CCD2 is tied to either CVS1 or CVS2.
++ mpi->pcmcia_cntl1 = 0x0000A080; // Drive CVS1 to a 0.
++ mdelay(1);
++ data32 = mpi->pcmcia_cntl1;
++ if (data32 & 0x00000002) { // CCD2 is tied to CVS2, not valid.
++ printk("mpi: Unknown card plugged into slot\n");
++ } else { // CCD2 is tied to CVS1.
++ printk("mpi: Detected 3.3, x.x and y.y Cardbus card\n");
++ cardtype = MPI_CARDTYPE_CARDBUS;
++ }
++ break;
++
++ case 0x00000001: // CCD1 is tied to either CVS1 or CVS2.
++ // This is not a valid combination.
++ printk("mpi: Unknown card plugged into slot\n");
++ break;
++
++ case 0x00000000: // CCD1 and CCD2 are tied to ground.
++ printk("mpi: Detected x.x vdc 16-bit PCMCIA card\n");
++ cardtype = MPI_CARDTYPE_PCMCIA;
++ break;
++ }
++ break;
++
++ case 0x00000008: // CVS2 is open or tied to CCD1/CCD2 and CVS1 is tied to ground.
++ // 2 valid voltage options.
++ switch (data32 & 0x00000003) // Test the values of CCD1 and CCD2.
++ {
++ case 0x00000003: // CCD1 and CCD2 are tied to 1 of the CVS pins.
++ // This is not a valid combination.
++ printk("mpi: Unknown card plugged into slot\n");
++ break;
++
++ case 0x00000002: // CCD2 is tied to either CVS1 or CVS2.
++ mpi->pcmcia_cntl1 = 0x0000A040; // Drive CVS2 to a 0.
++ mdelay(1);
++ data32 = mpi->pcmcia_cntl1;
++ if (data32 & 0x00000002) { // CCD2 is tied to CVS1, not valid.
++ printk("mpi: Unknown card plugged into slot\n");
++ } else {// CCD2 is tied to CVS2.
++ printk("mpi: Detected 3.3 and x.x Cardbus card\n");
++ cardtype = MPI_CARDTYPE_CARDBUS;
++ }
++ break;
++
++ case 0x00000001: // CCD1 is tied to either CVS1 or CVS2.
++ // This is not a valid combination.
++ printk("mpi: Unknown card plugged into slot\n");
++ break;
++
++ case 0x00000000: // CCD1 and CCD2 are tied to ground.
++ cardtype = MPI_CARDTYPE_PCMCIA;
++ printk("mpi: Detected 3.3 vdc 16-bit PCMCIA card\n");
++ break;
++ }
++ break;
++
++ case 0x0000000C: // CVS1 and CVS2 are open or tied to CCD1/CCD2.
++ // 5 valid voltage options.
++
++ switch (data32 & 0x00000003) // Test the values of CCD1 and CCD2.
++ {
++ case 0x00000003: // CCD1 and CCD2 are tied to 1 of the CVS pins.
++ // This is not a valid combination.
++ printk("mpi: Unknown card plugged into slot\n");
++ break;
++
++ case 0x00000002: // CCD2 is tied to either CVS1 or CVS2.
++ // CCD1 is tied to ground.
++ mpi->pcmcia_cntl1 = 0x0000A040; // Drive CVS2 to a 0.
++ mdelay(1);
++ data32 = mpi->pcmcia_cntl1;
++ if (data32 & 0x00000002) { // CCD2 is tied to CVS1.
++ printk("mpi: Detected y.y vdc Cardbus card\n");
++ } else { // CCD2 is tied to CVS2.
++ printk("mpi: Detected x.x vdc Cardbus card\n");
++ }
++ cardtype = MPI_CARDTYPE_CARDBUS;
++ break;
++
++ case 0x00000001: // CCD1 is tied to either CVS1 or CVS2.
++ // CCD2 is tied to ground.
++
++ mpi->pcmcia_cntl1 = 0x0000A040; // Drive CVS2 to a 0.
++ mdelay(1);
++ data32 = mpi->pcmcia_cntl1;
++ if (data32 & 0x00000001) {// CCD1 is tied to CVS1.
++ printk("mpi: Detected 3.3 vdc Cardbus card\n");
++ } else { // CCD1 is tied to CVS2.
++ printk("mpi: Detected x.x and y.y Cardbus card\n");
++ }
++ cardtype = MPI_CARDTYPE_CARDBUS;
++ break;
++
++ case 0x00000000: // CCD1 and CCD2 are tied to ground.
++ cardtype = MPI_CARDTYPE_PCMCIA;
++ printk("mpi: Detected 5 vdc 16-bit PCMCIA card\n");
++ break;
++ }
++ break;
++
++ default:
++ printk("mpi: Unknown card plugged into slot\n");
++ break;
++
++ }
++ }
++ return cardtype;
++}
++
++/*
++ * mpi_DetectPcCard: Detect the plugged in PC-Card
++ * Return: < 0 => Unknown card detected
++ * 0 => No card detected
++ * 1 => 16-bit card detected
++ * 2 => 32-bit CardBus card detected
++ */
++static int mpi_DetectPcCard(void)
++{
++ int cardtype;
++
++ cardtype = cardtype_vcc_detect();
++ switch(cardtype) {
++ case MPI_CARDTYPE_PCMCIA:
++ mpi->pcmcia_cntl1 &= ~0x0000e000; // disable enable bits
++ //mpi->pcmcia_cntl1 = (mpi->pcmcia_cntl1 & ~PCCARD_CARD_RESET);
++ mpi->pcmcia_cntl1 |= (PCMCIA_ENABLE | PCMCIA_GPIO_ENABLE);
++ mpi_InitPcmciaSpace();
++ mpi_ResetPcCard(cardtype, FALSE);
++ // Hold card in reset for 10ms
++ mdelay(10);
++ mpi_ResetPcCard(cardtype, TRUE);
++ // Let card come out of reset
++ mdelay(100);
++ break;
++ case MPI_CARDTYPE_CARDBUS:
++ // 8 => CardBus Enable
++ // 1 => PCI Slot Number
++ // C => Float VS1 & VS2
++ mpi->pcmcia_cntl1 = (mpi->pcmcia_cntl1 & 0xFFFF0000) |
++ CARDBUS_ENABLE |
++ (CARDBUS_SLOT << 8)|
++ VS2_OEN |
++ VS1_OEN;
++ /* access to this memory window will be to/from CardBus */
++ mpi->l2pmremap1 |= CARDBUS_MEM;
++
++ // Need to reset the Cardbus Card. There's no CardManager to do this,
++ // and we need to be ready for PCI configuration.
++ mpi_ResetPcCard(cardtype, FALSE);
++ // Hold card in reset for 10ms
++ mdelay(10);
++ mpi_ResetPcCard(cardtype, TRUE);
++ // Let card come out of reset
++ mdelay(100);
++ break;
++ default:
++ break;
++ }
++ return cardtype;
++}
++
++static int mpi_init(void)
++{
++ unsigned long data;
++ unsigned int chipid;
++ unsigned int chiprev;
++ unsigned int sdramsize;
++
++ chipid = (PERF->RevID & 0xFFFF0000) >> 16;
++ chiprev = (PERF->RevID & 0xFF);
++ sdramsize = getMemorySize();
++ /*
++ * Init the pci interface
++ */
++ data = GPIO->GPIOMode; // GPIO mode register
++ data |= GROUP2_PCI | GROUP1_MII_PCCARD; // PCI internal arbiter + Cardbus
++ GPIO->GPIOMode = data; // PCI internal arbiter
++
++ /*
++ * In the BCM6348 CardBus support is defaulted to Slot 0
++ * because there is no external IDSEL for CardBus. To disable
++ * the CardBus and allow a standard PCI card in Slot 0
++ * set the cbus_idsel field to 0x1f.
++ */
++ /*
++ uData = mpi->pcmcia_cntl1;
++ uData |= CARDBUS_IDSEL;
++ mpi->pcmcia_cntl1 = uData;
++ */
++ // Setup PCI I/O Window range. Give 64K to PCI I/O
++ mpi->l2piorange = ~(BCM_PCI_IO_SIZE_64KB-1);
++ // UBUS to PCI I/O base address
++ mpi->l2piobase = BCM_PCI_IO_BASE & BCM_PCI_ADDR_MASK;
++ // UBUS to PCI I/O Window remap
++ mpi->l2pioremap = (BCM_PCI_IO_BASE | MEM_WINDOW_EN);
++
++ // enable PCI related GPIO pins and data swap between system and PCI bus
++ mpi->locbuscntrl = (EN_PCI_GPIO | DIR_U2P_NOSWAP);
++
++ /* Enable 6348 BusMaster and Memory access mode */
++ data = mpi_GetLocalPciConfigReg(PCI_COMMAND);
++ data |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
++ mpi_SetLocalPciConfigReg(PCI_COMMAND, data);
++
++ /* Configure two 16 MByte PCI to System memory regions. */
++ /* These memory regions are used when PCI device is a bus master */
++ /* Accesses to the SDRAM from PCI bus will be "byte swapped" for this region */
++ mpi_SetLocalPciConfigReg(PCI_BASE_ADDRESS_3, BCM_HOST_MEM_SPACE1);
++ mpi->sp0remap = 0x0;
++
++ /* Accesses to the SDRAM from PCI bus will not be "byte swapped" for this region */
++ mpi_SetLocalPciConfigReg(PCI_BASE_ADDRESS_4, BCM_HOST_MEM_SPACE2);
++ mpi->sp1remap = 0x0;
++ mpi->pcimodesel |= (PCI_BAR2_NOSWAP | 0x40);
++
++ if ((chipid == 0x6348) && (chiprev == 0xb0)) {
++ mpi->sp0range = ~(sdramsize-1);
++ mpi->sp1range = ~(sdramsize-1);
++ }
++ /*
++ * Change 6348 PCI Cfg Reg. offset 0x40 to PCI memory read retry count infinity
++ * by set 0 in bit 8~15. This resolve read Bcm4306 srom return 0xffff in
++ * first read.
++ */
++ data = mpi_GetLocalPciConfigReg(BRCM_PCI_CONFIG_TIMER);
++ data &= ~BRCM_PCI_CONFIG_TIMER_RETRY_MASK;
++ data |= 0x00000080;
++ mpi_SetLocalPciConfigReg(BRCM_PCI_CONFIG_TIMER, data);
++
++ /* enable pci interrupt */
++ mpi->locintstat |= (EXT_PCI_INT << 16);
++
++ mpi_DetectPcCard();
++
++ ioport_resource.start = BCM_PCI_IO_BASE;
++ ioport_resource.end = BCM_PCI_IO_BASE + BCM_PCI_IO_SIZE_64KB;
++
++#if defined(CONFIG_USB)
++ PERF->blkEnables |= USBH_CLK_EN;
++ mdelay(100);
++ *USBH_NON_OHCI = NON_OHCI_BYTE_SWAP;
++#endif
++
++ return 0;
++}
++#endif
++
++static int __init brcm63xx_setup(void)
++{
++ extern int panic_timeout;
++
++ _machine_restart = brcm_machine_restart;
++ _machine_halt = brcm_machine_halt;
++ pm_power_off = brcm_machine_halt;
++
++ board_time_init = brcm_time_init;
++ board_timer_setup = brcm_timer_setup;
++
++ panic_timeout = 5;
++
++#if defined(CONFIG_BCM96348) && defined(CONFIG_PCI)
++ /* mpi initialization */
++ mpi_init();
++#endif
++ return 0;
++}
++
++void plat_setup(void)
++{
++ brcm63xx_setup();
++}
++
++/***************************************************************************
++ * C++ New and delete operator functions
++ ***************************************************************************/
++
++/* void *operator new(unsigned int sz) */
++void *_Znwj(unsigned int sz)
++{
++ return( kmalloc(sz, GFP_KERNEL) );
++}
++
++/* void *operator new[](unsigned int sz)*/
++void *_Znaj(unsigned int sz)
++{
++ return( kmalloc(sz, GFP_KERNEL) );
++}
++
++/* placement new operator */
++/* void *operator new (unsigned int size, void *ptr) */
++void *ZnwjPv(unsigned int size, void *ptr)
++{
++ return ptr;
++}
++
++/* void operator delete(void *m) */
++void _ZdlPv(void *m)
++{
++ kfree(m);
++}
++
++/* void operator delete[](void *m) */
++void _ZdaPv(void *m)
++{
++ kfree(m);
++}
++
++EXPORT_SYMBOL(_Znwj);
++EXPORT_SYMBOL(_Znaj);
++EXPORT_SYMBOL(ZnwjPv);
++EXPORT_SYMBOL(_ZdlPv);
++EXPORT_SYMBOL(_ZdaPv);
++
+diff -urN linux.old/arch/mips/bcm963xx/softdsl/AdslCoreDefs.h linux.dev/arch/mips/bcm963xx/softdsl/AdslCoreDefs.h
+--- linux.old/arch/mips/bcm963xx/softdsl/AdslCoreDefs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/softdsl/AdslCoreDefs.h 2006-08-25 00:39:38.000000000 +0200
+@@ -0,0 +1,2 @@
++#define ADSL_SDRAM_IMAGE_SIZE (384*1024)
++
+diff -urN linux.old/arch/mips/bcm963xx/time.c linux.dev/arch/mips/bcm963xx/time.c
+--- linux.old/arch/mips/bcm963xx/time.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm963xx/time.c 2006-08-25 03:58:22.000000000 +0200
+@@ -0,0 +1,114 @@
++/*
++<:copyright-gpl
++ Copyright 2004 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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.
++:>
++*/
++/*
++ * Setup time for Broadcom 963xx MIPS boards
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/kernel_stat.h>
++#include <linux/sched.h>
++#include <linux/spinlock.h>
++#include <linux/interrupt.h>
++#include <linux/module.h>
++#include <linux/time.h>
++#include <linux/timex.h>
++
++#include <asm/mipsregs.h>
++#include <asm/ptrace.h>
++#include <asm/div64.h>
++#include <asm/time.h>
++
++#include <bcm_map_part.h>
++#include <bcm_intr.h>
++
++static unsigned long r4k_offset; /* Amount to increment compare reg each time */
++static unsigned long r4k_cur; /* What counter should be at next timer irq */
++
++/* *********************************************************************
++ * calculateCpuSpeed()
++ * Calculate the BCM6348 CPU speed by reading the PLL strap register
++ * and applying the following formula:
++ * cpu_clk = (.25 * 64MHz freq) * (N1 + 1) * (N2 + 2) / (M1_CPU + 1)
++ * Input parameters:
++ * none
++ * Return value:
++ * none
++ ********************************************************************* */
++
++static inline unsigned long __init calculateCpuSpeed(void)
++{
++ UINT32 pllStrap = PERF->PllStrap;
++ int n1 = (pllStrap & PLL_N1_MASK) >> PLL_N1_SHFT;
++ int n2 = (pllStrap & PLL_N2_MASK) >> PLL_N2_SHFT;
++ int m1cpu = (pllStrap & PLL_M1_CPU_MASK) >> PLL_M1_CPU_SHFT;
++
++ return (16 * (n1 + 1) * (n2 + 2) / (m1cpu + 1)) * 1000000;
++}
++
++
++static inline unsigned long __init cal_r4koff(void)
++{
++ mips_hpt_frequency = calculateCpuSpeed() / 2;
++ return (mips_hpt_frequency / HZ);
++}
++
++
++/*
++ * There are a lot of conceptually broken versions of the MIPS timer interrupt
++ * handler floating around. This one is rather different, but the algorithm
++ * is provably more robust.
++ */
++irqreturn_t brcm_timer_interrupt(struct pt_regs *regs)
++{
++ int irq = MIPS_TIMER_INT;
++
++ irq_enter();
++ kstat_this_cpu.irqs[irq]++;
++
++ timer_interrupt(irq, NULL, regs);
++ irq_exit();
++ return IRQ_HANDLED;
++}
++
++
++void __init brcm_time_init(void)
++{
++ unsigned int est_freq, flags;
++ local_irq_save(flags);
++
++ printk("calculating r4koff... ");
++ r4k_offset = cal_r4koff();
++ printk("%08lx(%d)\n", r4k_offset, (int)r4k_offset);
++
++ est_freq = 2 * r4k_offset * HZ;
++ est_freq += 5000; /* round */
++ est_freq -= est_freq % 10000;
++ printk("CPU frequency %d.%02d MHz\n", est_freq / 1000000,
++ (est_freq % 1000000) * 100 / 1000000);
++ local_irq_restore(flags);
++}
++
++
++void __init brcm_timer_setup(struct irqaction *irq)
++{
++ r4k_cur = (read_c0_count() + r4k_offset);
++ write_c0_compare(r4k_cur);
++ set_c0_status(IE_IRQ5);
++}
+diff -urN linux.old/arch/mips/Kconfig linux.dev/arch/mips/Kconfig
+--- linux.old/arch/mips/Kconfig 2006-08-25 00:43:39.000000000 +0200
++++ linux.dev/arch/mips/Kconfig 2006-08-25 01:57:46.000000000 +0200
+@@ -12,6 +12,15 @@
+ prompt "System type"
+ default SGI_IP22
+
++config MIPS_BRCM
++ bool "Support for the Broadcom boards"
++ select SYS_SUPPORTS_32BIT_KERNEL
++ select SYS_SUPPORTS_BIG_ENDIAN
++ select SYS_HAS_CPU_MIPS32_R1
++ select IRQ_CPU
++ help
++ This is a fmaily of boards based on the Broadcom MIPS32
++
+ config MIPS_MTX1
+ bool "4G Systems MTX-1 board"
+ select DMA_NONCOHERENT
+@@ -780,6 +789,7 @@
+
+ endchoice
+
++source "arch/mips/bcm963xx/Kconfig"
+ source "arch/mips/ddb5xxx/Kconfig"
+ source "arch/mips/gt64120/ev64120/Kconfig"
+ source "arch/mips/jazz/Kconfig"
+diff -urN linux.old/arch/mips/kernel/cpu-probe.c linux.dev/arch/mips/kernel/cpu-probe.c
+--- linux.old/arch/mips/kernel/cpu-probe.c 2006-08-25 00:43:39.000000000 +0200
++++ linux.dev/arch/mips/kernel/cpu-probe.c 2006-08-25 00:39:38.000000000 +0200
+@@ -568,6 +568,25 @@
+ return;
+ }
+
++static inline void cpu_probe_broadcom(struct cpuinfo_mips *c)
++{
++ decode_configs(c);
++ switch (c->processor_id & 0xff00) {
++ case PRID_IMP_BCM6338:
++ c->cputype = CPU_BCM6338;
++ break;
++ case PRID_IMP_BCM6345:
++ c->cputype = CPU_BCM6345;
++ break;
++ case PRID_IMP_BCM6348:
++ c->cputype = CPU_BCM6348;
++ break;
++ default:
++ c->cputype = CPU_UNKNOWN;
++ break;
++ }
++}
++
+ static inline void cpu_probe_mips(struct cpuinfo_mips *c)
+ {
+ decode_configs(c);
+@@ -704,6 +723,9 @@
+ case PRID_COMP_LEGACY:
+ cpu_probe_legacy(c);
+ break;
++ case PRID_COMP_BROADCOM:
++ cpu_probe_broadcom(c);
++ break;
+ case PRID_COMP_MIPS:
+ cpu_probe_mips(c);
+ break;
+diff -urN linux.old/arch/mips/kernel/proc.c linux.dev/arch/mips/kernel/proc.c
+--- linux.old/arch/mips/kernel/proc.c 2006-08-25 00:43:39.000000000 +0200
++++ linux.dev/arch/mips/kernel/proc.c 2006-08-25 00:39:38.000000000 +0200
+@@ -85,6 +85,9 @@
+ [CPU_VR4181A] = "NEC VR4181A",
+ [CPU_SR71000] = "Sandcraft SR71000",
+ [CPU_PR4450] = "Philips PR4450",
++ [CPU_BCM6338] = "BCM6338",
++ [CPU_BCM6345] = "BCM6345",
++ [CPU_BCM6348] = "BCM6348",
+ };
+
+
+diff -urN linux.old/arch/mips/Makefile linux.dev/arch/mips/Makefile
+--- linux.old/arch/mips/Makefile 2006-08-25 00:43:39.000000000 +0200
++++ linux.dev/arch/mips/Makefile 2006-08-25 15:39:54.000000000 +0200
+@@ -145,6 +145,15 @@
+ #
+
+ #
++# Broadcom board
++#
++core-$(CONFIG_MIPS_BRCM) += arch/mips/bcm963xx/
++cflags-$(CONFIG_MIPS_BRCM) += -Iinclude/asm-mips/mach-bcm963xx
++cflags-$(CONFIG_MIPS_BRCM) += -Iarch/mips/bcm963xx/include
++load-$(CONFIG_MIPS_BRCM) += 0xffffffff80010000
++
++
++#
+ # Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
+ #
+ core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/
+diff -urN linux.old/arch/mips/mm/c-r4k.c linux.dev/arch/mips/mm/c-r4k.c
+--- linux.old/arch/mips/mm/c-r4k.c 2006-08-25 00:43:39.000000000 +0200
++++ linux.dev/arch/mips/mm/c-r4k.c 2006-08-25 00:39:38.000000000 +0200
+@@ -914,6 +914,13 @@
+ if (!(config & MIPS_CONF_M))
+ panic("Don't know how to probe P-caches on this cpu.");
+
++ if (c->cputype == CPU_BCM6338 || c->cputype == CPU_BCM6345 || c->cputype == CPU_BCM6348)
++ {
++ printk("brcm mips: enabling icache and dcache...\n");
++ /* Enable caches */
++ write_c0_diag(read_c0_diag() | 0xC0000000);
++ }
++
+ /*
+ * So we seem to be a MIPS32 or MIPS64 CPU
+ * So let's probe the I-cache ...
+diff -urN linux.old/arch/mips/mm/tlbex.c linux.dev/arch/mips/mm/tlbex.c
+--- linux.old/arch/mips/mm/tlbex.c 2006-08-25 00:43:39.000000000 +0200
++++ linux.dev/arch/mips/mm/tlbex.c 2006-08-25 00:39:38.000000000 +0200
+@@ -882,6 +882,9 @@
+ case CPU_4KSC:
+ case CPU_20KC:
+ case CPU_25KF:
++ case CPU_BCM6338:
++ case CPU_BCM6345:
++ case CPU_BCM6348:
+ tlbw(p);
+ break;
+
+diff -urN linux-2.6.17/arch/mips/pci/fixup-bcm96348.c linux-2.6.17-brcm63xx/arch/mips/pci/fixup-bcm96348.c
+--- linux-2.6.17/arch/mips/pci/fixup-bcm96348.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-brcm63xx/arch/mips/pci/fixup-bcm96348.c 2006-08-29 10:25:22.000000000 +0200
+@@ -0,0 +1,93 @@
++/*
++<:copyright-gpl
++ Copyright 2002 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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/init.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++
++#include <bcmpci.h>
++#include <bcm_intr.h>
++#include <bcm_map_part.h>
++
++static volatile MpiRegisters * mpi = (MpiRegisters *)(MPI_BASE);
++
++static char irq_tab_bcm96348[] __initdata = {
++ [0] = INTERRUPT_ID_MPI,
++ [1] = INTERRUPT_ID_MPI,
++#if defined(CONFIG_USB)
++ [USB_HOST_SLOT] = INTERRUPT_ID_USBH
++#endif
++};
++
++int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ return irq_tab_bcm96348[slot];
++}
++
++static void bcm96348_fixup(struct pci_dev *dev)
++{
++ uint32 memaddr;
++ uint32 size;
++
++ memaddr = pci_resource_start(dev, 0);
++ size = pci_resource_len(dev, 0);
++
++ switch (PCI_SLOT(dev->devfn)) {
++ case 0:
++ // UBUS to PCI address range
++ // Memory Window 1. Mask determines which bits are decoded.
++ mpi->l2pmrange1 = ~(size-1);
++ // UBUS to PCI Memory base address. This is akin to the ChipSelect base
++ // register.
++ mpi->l2pmbase1 = memaddr & BCM_PCI_ADDR_MASK;
++ // UBUS to PCI Remap Address. Replaces the masked address bits in the
++ // range register with this setting.
++ // Also, enable direct I/O and direct Memory accesses
++ mpi->l2pmremap1 = (memaddr | MEM_WINDOW_EN);
++ break;
++
++ case 1:
++ // Memory Window 2
++ mpi->l2pmrange2 = ~(size-1);
++ // UBUS to PCI Memory base address.
++ mpi->l2pmbase2 = memaddr & BCM_PCI_ADDR_MASK;
++ // UBUS to PCI Remap Address
++ mpi->l2pmremap2 = (memaddr | MEM_WINDOW_EN);
++ break;
++
++#if defined(CONFIG_USB)
++ case USB_HOST_SLOT:
++ dev->resource[0].start = USB_HOST_BASE;
++ dev->resource[0].end = USB_HOST_BASE+USB_BAR0_MEM_SIZE-1;
++ break;
++#endif
++ }
++}
++
++int pcibios_plat_dev_init(struct pci_dev *dev)
++{
++ return 0;
++}
++
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_ANY_ID,
++ bcm96348_fixup);
++
++/*struct pci_fixup pcibios_fixups[] = {
++ { PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, bcm96348_fixup },
++ {0}
++};*/
+diff -urN linux.old/arch/mips/pci/Makefile linux.dev/arch/mips/pci/Makefile
+--- linux.old/arch/mips/pci/Makefile 2006-08-25 00:43:29.000000000 +0200
++++ linux.dev/arch/mips/pci/Makefile 2006-08-25 00:39:38.000000000 +0200
+@@ -18,6 +18,7 @@
+ obj-$(CONFIG_MIPS_TX3927) += ops-tx3927.o
+ obj-$(CONFIG_PCI_VR41XX) += ops-vr41xx.o pci-vr41xx.o
+ obj-$(CONFIG_NEC_CMBVR4133) += fixup-vr4133.o
++obj-$(CONFIG_BCM_PCI) += fixup-bcm96348.o pci-bcm96348.o ops-bcm96348.o
+
+ #
+ # These are still pretty much in the old state, watch, go blind.
+diff -urN linux.old/arch/mips/pci/ops-bcm96348.c linux.dev/arch/mips/pci/ops-bcm96348.c
+--- linux.old/arch/mips/pci/ops-bcm96348.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/pci/ops-bcm96348.c 2006-08-25 00:39:38.000000000 +0200
+@@ -0,0 +1,276 @@
++/*
++<:copyright-gpl
++ Copyright 2002 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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/types.h>
++#include <linux/pci.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <asm/addrspace.h>
++
++#include <bcm_intr.h>
++#include <bcm_map_part.h>
++#include <bcmpci.h>
++
++#include <linux/delay.h>
++
++#if defined(CONFIG_USB)
++#if 0
++#define DPRINT(x...) printk(x)
++#else
++#define DPRINT(x...)
++#endif
++
++static int
++pci63xx_int_read(unsigned int devfn, int where, u32 * value, int size);
++static int
++pci63xx_int_write(unsigned int devfn, int where, u32 * value, int size);
++
++static bool usb_mem_size_rd = FALSE;
++static uint32 usb_mem_base = 0;
++static uint32 usb_cfg_space_cmd_reg = 0;
++#endif
++static bool pci_mem_size_rd = FALSE;
++
++static volatile MpiRegisters * mpi = (MpiRegisters *)(MPI_BASE);
++
++static void mpi_SetupPciConfigAccess(uint32 addr)
++{
++ mpi->l2pcfgctl = (DIR_CFG_SEL | DIR_CFG_USEREG | addr) & ~CONFIG_TYPE;
++}
++
++static void mpi_ClearPciConfigAccess(void)
++{
++ mpi->l2pcfgctl = 0x00000000;
++}
++
++#if defined(CONFIG_USB)
++/* --------------------------------------------------------------------------
++ Name: pci63xx_int_write
++Abstract: PCI Config write on internal device(s)
++ -------------------------------------------------------------------------- */
++static int
++pci63xx_int_write(unsigned int devfn, int where, u32 * value, int size)
++{
++ if (PCI_SLOT(devfn) != USB_HOST_SLOT) {
++ return PCIBIOS_SUCCESSFUL;
++ }
++
++ switch (size) {
++ case 1:
++ DPRINT("W => Slot: %d Where: %2X Len: %d Data: %02X\n",
++ PCI_SLOT(devfn), where, size, *value);
++ break;
++ case 2:
++ DPRINT("W => Slot: %d Where: %2X Len: %d Data: %04X\n",
++ PCI_SLOT(devfn), where, size, *value);
++ switch (where) {
++ case PCI_COMMAND:
++ usb_cfg_space_cmd_reg = *value;
++ break;
++ default:
++ break;
++ }
++ break;
++ case 4:
++ DPRINT("W => Slot: %d Where: %2X Len: %d Data: %08lX\n",
++ PCI_SLOT(devfn), where, size, *value);
++ switch (where) {
++ case PCI_BASE_ADDRESS_0:
++ if (*value == 0xffffffff) {
++ usb_mem_size_rd = TRUE;
++ } else {
++ usb_mem_base = *value;
++ }
++ break;
++ default:
++ break;
++ }
++ break;
++ default:
++ break;
++ }
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++/* --------------------------------------------------------------------------
++ Name: pci63xx_int_read
++Abstract: PCI Config read on internal device(s)
++ -------------------------------------------------------------------------- */
++static int
++pci63xx_int_read(unsigned int devfn, int where, u32 * value, int size)
++{
++ uint32 retValue = 0xFFFFFFFF;
++
++ if (PCI_SLOT(devfn) != USB_HOST_SLOT) {
++ return PCIBIOS_SUCCESSFUL;
++ }
++
++ // For now, this is specific to the USB Host controller. We can
++ // make it more general if we have to...
++ // Emulate PCI Config accesses
++ switch (where) {
++ case PCI_VENDOR_ID:
++ case PCI_DEVICE_ID:
++ retValue = PCI_VENDOR_ID_BROADCOM | 0x63000000;
++ break;
++ case PCI_COMMAND:
++ case PCI_STATUS:
++ retValue = (0x0006 << 16) | usb_cfg_space_cmd_reg;
++ break;
++ case PCI_CLASS_REVISION:
++ case PCI_CLASS_DEVICE:
++ retValue = (PCI_CLASS_SERIAL_USB << 16) | (0x10 << 8) | 0x01;
++ break;
++ case PCI_BASE_ADDRESS_0:
++ if (usb_mem_size_rd) {
++ retValue = USB_BAR0_MEM_SIZE;
++ } else {
++ if (usb_mem_base != 0)
++ retValue = usb_mem_base;
++ else
++ retValue = USB_HOST_BASE;
++ }
++ usb_mem_size_rd = FALSE;
++ break;
++ case PCI_CACHE_LINE_SIZE:
++ case PCI_LATENCY_TIMER:
++ retValue = 0;
++ break;
++ case PCI_HEADER_TYPE:
++ retValue = PCI_HEADER_TYPE_NORMAL;
++ break;
++ case PCI_SUBSYSTEM_VENDOR_ID:
++ retValue = PCI_VENDOR_ID_BROADCOM;
++ break;
++ case PCI_SUBSYSTEM_ID:
++ retValue = 0x6300;
++ break;
++ case PCI_INTERRUPT_LINE:
++ retValue = INTERRUPT_ID_USBH;
++ break;
++ default:
++ break;
++ }
++
++ switch (size) {
++ case 1:
++ *value = (retValue >> ((where & 3) << 3)) & 0xff;
++ DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %02X\n",
++ PCI_SLOT(devfn), where, size, *value);
++ break;
++ case 2:
++ *value = (retValue >> ((where & 3) << 3)) & 0xffff;
++ DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %04X\n",
++ PCI_SLOT(devfn), where, size, *value);
++ break;
++ case 4:
++ *value = retValue;
++ DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %08lX\n",
++ PCI_SLOT(devfn), where, size, *value);
++ break;
++ default:
++ break;
++ }
++
++ return PCIBIOS_SUCCESSFUL;
++}
++#endif
++
++static int bcm96348_pcibios_read(struct pci_bus *bus, unsigned int devfn,
++ int where, int size, u32 * val)
++{
++ volatile unsigned char *ioBase = (unsigned char *)(mpi->l2piobase | KSEG1);
++ uint32 data;
++
++#if defined(CONFIG_USB)
++ if (PCI_SLOT(devfn) == USB_HOST_SLOT)
++ return pci63xx_int_read(devfn, where, val, size);
++#endif
++
++ mpi_SetupPciConfigAccess(BCM_PCI_CFG(PCI_SLOT(devfn), PCI_FUNC(devfn), where));
++ data = *(uint32 *)ioBase;
++ switch(size) {
++ case 1:
++ *val = (data >> ((where & 3) << 3)) & 0xff;
++ break;
++ case 2:
++ *val = (data >> ((where & 3) << 3)) & 0xffff;
++ break;
++ case 4:
++ *val = data;
++ /* Special case for reading PCI device range */
++ if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5)) {
++ if (pci_mem_size_rd) {
++ /* bcm6348 PCI memory window minimum size is 64K */
++ *val &= PCI_SIZE_64K;
++ }
++ }
++ break;
++ default:
++ break;
++ }
++ pci_mem_size_rd = FALSE;
++ mpi_ClearPciConfigAccess();
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int bcm96348_pcibios_write(struct pci_bus *bus, unsigned int devfn,
++ int where, int size, u32 val)
++{
++ volatile unsigned char *ioBase = (unsigned char *)(mpi->l2piobase | KSEG1);
++ uint32 data;
++
++#if defined(CONFIG_USB)
++ if (PCI_SLOT(devfn) == USB_HOST_SLOT)
++ return pci63xx_int_write(devfn, where, &val, size);
++#endif
++ mpi_SetupPciConfigAccess(BCM_PCI_CFG(PCI_SLOT(devfn), PCI_FUNC(devfn), where));
++ data = *(uint32 *)ioBase;
++ switch(size) {
++ case 1:
++ data = (data & ~(0xff << ((where & 3) << 3))) |
++ (val << ((where & 3) << 3));
++ break;
++ case 2:
++ data = (data & ~(0xffff << ((where & 3) << 3))) |
++ (val << ((where & 3) << 3));
++ break;
++ case 4:
++ data = val;
++ /* Special case for reading PCI device range */
++ if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5)) {
++ if (val == 0xffffffff)
++ pci_mem_size_rd = TRUE;
++ }
++ break;
++ default:
++ break;
++ }
++ *(uint32 *)ioBase = data;
++ udelay(500);
++ mpi_ClearPciConfigAccess();
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++struct pci_ops bcm96348_pci_ops = {
++ .read = bcm96348_pcibios_read,
++ .write = bcm96348_pcibios_write
++};
+diff -urN linux-2.6.17/arch/mips/pci/pci-bcm96348.c linux-2.6.17-brcm63xx/arch/mips/pci/pci-bcm96348.c
+--- linux-2.6.17/arch/mips/pci/pci-bcm96348.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-brcm63xx/arch/mips/pci/pci-bcm96348.c 2006-08-29 10:25:13.000000000 +0200
+@@ -0,0 +1,54 @@
++/*
++<:copyright-gpl
++ Copyright 2002 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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/types.h>
++#include <linux/pci.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++
++//#include <asm/pci_channel.h>
++#include <bcmpci.h>
++
++static struct resource bcm_pci_io_resource = {
++ .name = "bcm96348 pci IO space",
++ .start = BCM_PCI_IO_BASE,
++ .end = BCM_PCI_IO_BASE + BCM_PCI_IO_SIZE_64KB - 1,
++ .flags = IORESOURCE_IO
++};
++
++static struct resource bcm_pci_mem_resource = {
++ .name = "bcm96348 pci memory space",
++ .start = BCM_PCI_MEM_BASE,
++ .end = BCM_PCI_MEM_BASE + BCM_PCI_MEM_SIZE_16MB - 1,
++ .flags = IORESOURCE_MEM
++};
++
++extern struct pci_ops bcm96348_pci_ops;
++
++struct pci_controller bcm96348_controller = {
++ .pci_ops = &bcm96348_pci_ops,
++ .io_resource = &bcm_pci_io_resource,
++ .mem_resource = &bcm_pci_mem_resource,
++};
++
++static void bcm96348_pci_init(void)
++{
++ register_pci_controller(&bcm96348_controller);
++}
++
++arch_initcall(bcm96348_pci_init);
+diff -urN linux.old/drivers/serial/bcm63xx_cons.c linux.dev/drivers/serial/bcm63xx_cons.c
+--- linux.old/drivers/serial/bcm63xx_cons.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/serial/bcm63xx_cons.c 2006-08-25 15:37:34.000000000 +0200
+@@ -0,0 +1,1049 @@
++/*
++<:copyright-gpl
++ Copyright 2002 Broadcom Corp. All Rights Reserved.
++
++ This program is free software; you can distribute 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 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.
++:>
++*/
++
++/* Description: Serial port driver for the BCM963XX. */
++
++#define CARDNAME "bcm963xx_serial driver"
++#define VERSION "2.0"
++#define VER_STR CARDNAME " v" VERSION "\n"
++
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++
++/* for definition of struct console */
++#include <linux/console.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/serial.h>
++#include <linux/serialP.h>
++#include <asm/uaccess.h>
++
++#include <bcmtypes.h>
++#include <board.h>
++#include <bcm_map_part.h>
++#include <bcm_intr.h>
++
++static DEFINE_SPINLOCK(bcm963xx_serial_lock);
++
++extern void _putc(char);
++extern void _puts(const char *);
++
++typedef struct bcm_serial {
++ volatile Uart * port;
++ int type;
++ int flags;
++ int irq;
++ int baud_base;
++ int blocked_open;
++ unsigned short close_delay;
++ unsigned short closing_wait;
++ unsigned short line; /* port/line number */
++ unsigned short cflags; /* line configuration flag */
++ unsigned short x_char; /* xon/xoff character */
++ unsigned short read_status_mask; /* mask for read condition */
++ unsigned short ignore_status_mask; /* mask for ignore condition */
++ unsigned long event; /* mask used in BH */
++ int xmit_head; /* Position of the head */
++ int xmit_tail; /* Position of the tail */
++ int xmit_cnt; /* Count of the chars in the buffer */
++ int count; /* indicates how many times it has been opened */
++ int magic;
++
++ struct async_icount icount; /* keep track of things ... */
++ struct tty_struct *tty; /* tty associated */
++ struct termios normal_termios;
++
++ wait_queue_head_t open_wait;
++ wait_queue_head_t close_wait;
++
++ long session; /* Session of opening process */
++ long pgrp; /* pgrp of opening process */
++
++ unsigned char is_initialized;
++} Context;
++
++
++/*---------------------------------------------------------------------*/
++/* Define bits in the Interrupt Enable register */
++/*---------------------------------------------------------------------*/
++/* Enable receive interrupt */
++#define RXINT (RXFIFONE|RXOVFERR)
++
++/* Enable transmit interrupt */
++#define TXINT (TXFIFOEMT|TXUNDERR|TXOVFERR)
++
++/* Enable receiver line status interrupt */
++#define LSINT (RXBRK|RXPARERR|RXFRAMERR)
++
++#define BCM_NUM_UARTS 1
++
++#define BD_BCM63XX_TIMER_CLOCK_INPUT (FPERIPH)
++
++
++static struct bcm_serial multi[BCM_NUM_UARTS];
++static struct bcm_serial *lines[BCM_NUM_UARTS];
++static struct tty_driver *serial_driver;
++static struct termios *serial_termios[BCM_NUM_UARTS];
++static struct termios *serial_termios_locked[BCM_NUM_UARTS];
++
++
++static void bcm_stop (struct tty_struct *tty);
++static void bcm_start (struct tty_struct *tty);
++static inline void receive_chars (struct bcm_serial * info);
++static int startup (struct bcm_serial *info);
++static void shutdown (struct bcm_serial * info);
++static void change_speed( volatile Uart *pUart, tcflag_t cFlag );
++static void bcm63xx_cons_flush_chars (struct tty_struct *tty);
++static int bcm63xx_cons_write (struct tty_struct *tty,
++ const unsigned char *buf, int count);
++static int bcm63xx_cons_write_room (struct tty_struct *tty);
++static int bcm_chars_in_buffer (struct tty_struct *tty);
++static void bcm_flush_buffer (struct tty_struct *tty);
++static void bcm_throttle (struct tty_struct *tty);
++static void bcm_unthrottle (struct tty_struct *tty);
++static void bcm_send_xchar (struct tty_struct *tty, char ch);
++static int get_serial_info(struct bcm_serial *info, struct serial_struct *retinfo);
++static int set_serial_info (struct bcm_serial *info, struct serial_struct *new_info);
++static int get_lsr_info (struct bcm_serial *info, unsigned int *value);
++static void send_break (struct bcm_serial *info, int duration);
++static int bcm_ioctl (struct tty_struct * tty, struct file * file,
++ unsigned int cmd, unsigned long arg);
++static void bcm_set_termios (struct tty_struct *tty, struct termios *old_termios);
++static void bcm63xx_cons_close (struct tty_struct *tty, struct file *filp);
++static void bcm_hangup (struct tty_struct *tty);
++static int block_til_ready (struct tty_struct *tty, struct file *filp, struct bcm_serial *info);
++static int bcm63xx_cons_open (struct tty_struct * tty, struct file * filp);
++static int __init bcm63xx_serialinit(void);
++
++
++/*
++ * ------------------------------------------------------------
++ * rs_stop () and rs_start ()
++ *
++ * These routines are called before setting or resetting
++ * tty->stopped. They enable or disable transmitter interrupts,
++ * as necessary.
++ * ------------------------------------------------------------
++ */
++static void bcm_stop (struct tty_struct *tty)
++{
++}
++
++static void bcm_start (struct tty_struct *tty)
++{
++ _puts(CARDNAME " Start\n");
++}
++
++/*
++ * ------------------------------------------------------------
++ * receive_char ()
++ *
++ * This routine deals with inputs from any lines.
++ * ------------------------------------------------------------
++ */
++static inline void receive_chars (struct bcm_serial * info)
++{
++ struct tty_struct *tty = 0;
++ struct async_icount * icount;
++ int ignore = 0;
++ unsigned short status, tmp;
++ UCHAR ch = 0;
++ while ((status = info->port->intStatus) & RXINT)
++ {
++ char flag_char = TTY_NORMAL;
++
++ if (status & RXFIFONE)
++ ch = info->port->Data; // Read the character
++ tty = info->tty; /* now tty points to the proper dev */
++ icount = &info->icount;
++ if (! tty)
++ break;
++ if (!tty_buffer_request_room(tty, 1))
++ break;
++ icount->rx++;
++ if (status & RXBRK)
++ {
++ flag_char = TTY_BREAK;
++ icount->brk++;
++ }
++ // keep track of the statistics
++ if (status & (RXFRAMERR | RXPARERR | RXOVFERR))
++ {
++ if (status & RXPARERR) /* parity error */
++ icount->parity++;
++ else
++ if (status & RXFRAMERR) /* frame error */
++ icount->frame++;
++ if (status & RXOVFERR)
++ {
++ // Overflow. Reset the RX FIFO
++ info->port->fifoctl |= RSTRXFIFOS;
++ icount->overrun++;
++ }
++ // check to see if we should ignore the character
++ // and mask off conditions that should be ignored
++ if (status & info->ignore_status_mask)
++ {
++ if (++ignore > 100 )
++ break;
++ goto ignore_char;
++ }
++ // Mask off the error conditions we want to ignore
++ tmp = status & info->read_status_mask;
++ if (tmp & RXPARERR)
++ {
++ flag_char = TTY_PARITY;
++ }
++ else
++ if (tmp & RXFRAMERR)
++ {
++ flag_char = TTY_FRAME;
++ }
++ if (tmp & RXOVFERR)
++ {
++ tty_insert_flip_char(tty, ch, flag_char);
++ ch = 0;
++ flag_char = TTY_OVERRUN;
++ if (!tty_buffer_request_room(tty, 1))
++ break;
++ }
++ }
++ tty_insert_flip_char(tty, ch, flag_char);
++ }
++ignore_char:;
++ tty_flip_buffer_push(tty);
++ tty_schedule_flip(tty);
++
++}
++
++
++/*
++ * ------------------------------------------------------------
++ * bcm_interrupt ()
++ *
++ * this is the main interrupt routine for the chip.
++ * It deals with the multiple ports.
++ * ------------------------------------------------------------
++ */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++static irqreturn_t bcm_interrupt (int irq, void * dev, struct pt_regs * regs)
++#else
++static void bcm_interrupt (int irq, void * dev, struct pt_regs * regs)
++#endif
++{
++ struct bcm_serial * info = lines[0];
++ UINT16 intStat;
++
++ /* get pending interrupt flags from UART */
++
++ /* Mask with only the serial interrupts that are enabled */
++ intStat = info->port->intStatus & info->port->intMask;
++ while (intStat)
++ {
++ if (intStat & RXINT)
++ receive_chars (info);
++ else
++ if (intStat & TXINT)
++ info->port->intStatus = TXINT;
++ else /* don't know what it was, so let's mask it */
++ info->port->intMask &= ~intStat;
++
++ intStat = info->port->intStatus & info->port->intMask;
++ }
++
++ // Clear the interrupt
++ BcmHalInterruptEnable (INTERRUPT_ID_UART);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++ return IRQ_HANDLED;
++#endif
++}
++
++/*
++ * -------------------------------------------------------------------
++ * startup ()
++ *
++ * various initialization tasks
++ * -------------------------------------------------------------------
++ */
++static int startup (struct bcm_serial *info)
++{
++ // Port is already started...
++ return 0;
++}
++
++/*
++ * -------------------------------------------------------------------
++ * shutdown ()
++ *
++ * This routine will shutdown a serial port; interrupts are disabled, and
++ * DTR is dropped if the hangup on close termio flag is on.
++ * -------------------------------------------------------------------
++ */
++static void shutdown (struct bcm_serial * info)
++{
++ unsigned long flags;
++ if (!info->is_initialized)
++ return;
++
++ spin_lock_irqsave(&bcm963xx_serial_lock, flags);
++
++ info->port->control &= ~(BRGEN|TXEN|RXEN);
++ if (info->tty)
++ set_bit (TTY_IO_ERROR, &info->tty->flags);
++ info->is_initialized = 0;
++
++ spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
++}
++/*
++ * -------------------------------------------------------------------
++ * change_speed ()
++ *
++ * Set the baud rate, character size, parity and stop bits.
++ * -------------------------------------------------------------------
++ */
++static void change_speed( volatile Uart *pUart, tcflag_t cFlag )
++{
++ unsigned long ulFlags, ulBaud, ulClockFreqHz, ulTmp;
++
++ spin_lock_irqsave(&bcm963xx_serial_lock, ulFlags);
++ switch( cFlag & (CBAUD | CBAUDEX) )
++ {
++ case B115200:
++ ulBaud = 115200;
++ break;
++ case B57600:
++ ulBaud = 57600;
++ break;
++ case B38400:
++ ulBaud = 38400;
++ break;
++ case B19200:
++ ulBaud = 19200;
++ break;
++ case B9600:
++ ulBaud = 9600;
++ break;
++ case B4800:
++ ulBaud = 4800;
++ break;
++ case B2400:
++ ulBaud = 2400;
++ break;
++ case B1800:
++ ulBaud = 1800;
++ break;
++ case B1200:
++ ulBaud = 1200;
++ break;
++ case B600:
++ ulBaud = 600;
++ break;
++ case B300:
++ ulBaud = 300;
++ break;
++ case B200:
++ ulBaud = 200;
++ break;
++ case B150:
++ ulBaud = 150;
++ break;
++ case B134:
++ ulBaud = 134;
++ break;
++ case B110:
++ ulBaud = 110;
++ break;
++ case B75:
++ ulBaud = 75;
++ break;
++ case B50:
++ ulBaud = 50;
++ break;
++ default:
++ ulBaud = 115200;
++ break;
++ }
++
++ /* Calculate buad rate. */
++ ulClockFreqHz = BD_BCM63XX_TIMER_CLOCK_INPUT;
++ ulTmp = (ulClockFreqHz / ulBaud) / 16;
++ if( ulTmp & 0x01 )
++ ulTmp /= 2; /* Rounding up, so sub is already accounted for */
++ else
++ ulTmp = (ulTmp / 2) - 1; /* Rounding down so we must sub 1 */
++ pUart->baudword = ulTmp;
++
++ /* Set character size, stop bits and parity. */
++ switch( cFlag & CSIZE )
++ {
++ case CS5:
++ ulTmp = BITS5SYM; /* select transmit 5 bit data size */
++ break;
++ case CS6:
++ ulTmp = BITS6SYM; /* select transmit 6 bit data size */
++ break;
++ case CS7:
++ ulTmp = BITS7SYM; /* select transmit 7 bit data size */
++ break;
++ default:
++ ulTmp = BITS8SYM; /* select transmit 8 bit data size */
++ break;
++ }
++ if( cFlag & CSTOPB )
++ ulTmp |= TWOSTOP; /* select 2 stop bits */
++ else
++ ulTmp |= ONESTOP; /* select one stop bit */
++
++ /* Write these values into the config reg. */
++ pUart->config = ulTmp;
++ pUart->control &= ~(RXPARITYEN | TXPARITYEN | RXPARITYEVEN | TXPARITYEVEN);
++ switch( cFlag & (PARENB | PARODD) )
++ {
++ case PARENB|PARODD:
++ pUart->control |= RXPARITYEN | TXPARITYEN;
++ break;
++ case PARENB:
++ pUart->control |= RXPARITYEN | TXPARITYEN | RXPARITYEVEN | TXPARITYEVEN;
++ break;
++ default:
++ pUart->control |= 0;
++ break;
++ }
++
++ /* Reset and flush uart */
++ pUart->fifoctl = RSTTXFIFOS | RSTRXFIFOS;
++ spin_unlock_irqrestore(&bcm963xx_serial_lock, ulFlags);
++}
++
++
++/*
++ * -------------------------------------------------------------------
++ * bcm_flush_char ()
++ *
++ * Nothing to flush. Polled I/O is used.
++ * -------------------------------------------------------------------
++ */
++static void bcm63xx_cons_flush_chars (struct tty_struct *tty)
++{
++}
++
++
++/*
++ * -------------------------------------------------------------------
++ * bcm63xx_cons_write ()
++ *
++ * Main output routine using polled I/O.
++ * -------------------------------------------------------------------
++ */
++static int bcm63xx_cons_write (struct tty_struct *tty,
++ const unsigned char *buf, int count)
++{
++ int c;
++
++ for (c = 0; c < count; c++)
++ _putc(buf[c]);
++ return count;
++}
++
++/*
++ * -------------------------------------------------------------------
++ * bcm63xx_cons_write_room ()
++ *
++ * Compute the amount of space available for writing.
++ * -------------------------------------------------------------------
++ */
++static int bcm63xx_cons_write_room (struct tty_struct *tty)
++{
++ /* Pick a number. Any number. Polled I/O is used. */
++ return 1024;
++}
++
++/*
++ * -------------------------------------------------------------------
++ * bcm_chars_in_buffer ()
++ *
++ * compute the amount of char left to be transmitted
++ * -------------------------------------------------------------------
++ */
++static int bcm_chars_in_buffer (struct tty_struct *tty)
++{
++ return 0;
++}
++
++/*
++ * -------------------------------------------------------------------
++ * bcm_flush_buffer ()
++ *
++ * Empty the output buffer
++ * -------------------------------------------------------------------
++ */
++static void bcm_flush_buffer (struct tty_struct *tty)
++{
++ tty_wakeup(tty);
++}
++
++/*
++ * ------------------------------------------------------------
++ * bcm_throttle () and bcm_unthrottle ()
++ *
++ * This routine is called by the upper-layer tty layer to signal that
++ * incoming characters should be throttled (or not).
++ * ------------------------------------------------------------
++ */
++static void bcm_throttle (struct tty_struct *tty)
++{
++ struct bcm_serial *info = (struct bcm_serial *)tty->driver_data;
++ if (I_IXOFF(tty))
++ info->x_char = STOP_CHAR(tty);
++}
++
++static void bcm_unthrottle (struct tty_struct *tty)
++{
++ struct bcm_serial *info = (struct bcm_serial *)tty->driver_data;
++ if (I_IXOFF(tty))
++ {
++ if (info->x_char)
++ info->x_char = 0;
++ else
++ info->x_char = START_CHAR(tty);
++ }
++}
++
++static void bcm_send_xchar (struct tty_struct *tty, char ch)
++{
++ struct bcm_serial *info = (struct bcm_serial *)tty->driver_data;
++ info->x_char = ch;
++ if (ch)
++ bcm_start (info->tty);
++}
++
++/*
++ * ------------------------------------------------------------
++ * rs_ioctl () and friends
++ * ------------------------------------------------------------
++ */
++static int get_serial_info(struct bcm_serial *info, struct serial_struct *retinfo)
++{
++ struct serial_struct tmp;
++
++ if (!retinfo)
++ return -EFAULT;
++
++ memset (&tmp, 0, sizeof(tmp));
++ tmp.type = info->type;
++ tmp.line = info->line;
++ tmp.port = (int) info->port;
++ tmp.irq = info->irq;
++ tmp.flags = 0;
++ tmp.baud_base = info->baud_base;
++ tmp.close_delay = info->close_delay;
++ tmp.closing_wait = info->closing_wait;
++
++ return copy_to_user (retinfo, &tmp, sizeof(*retinfo));
++}
++
++static int set_serial_info (struct bcm_serial *info, struct serial_struct *new_info)
++{
++ struct serial_struct new_serial;
++ struct bcm_serial old_info;
++ int retval = 0;
++
++ if (!new_info)
++ return -EFAULT;
++
++ copy_from_user (&new_serial, new_info, sizeof(new_serial));
++ old_info = *info;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++
++ if (info->count > 1)
++ return -EBUSY;
++
++ /* OK, past this point, all the error checking has been done.
++ * At this point, we start making changes.....
++ */
++ info->baud_base = new_serial.baud_base;
++ info->type = new_serial.type;
++ info->close_delay = new_serial.close_delay;
++ info->closing_wait = new_serial.closing_wait;
++ retval = startup (info);
++ return retval;
++}
++
++/*
++ * get_lsr_info - get line status register info
++ *
++ * Purpose: Let user call ioctl() to get info when the UART physically
++ * is emptied. On bus types like RS485, the transmitter must
++ * release the bus after transmitting. This must be done when
++ * the transmit shift register is empty, not be done when the
++ * transmit holding register is empty. This functionality
++ * allows an RS485 driver to be written in user space.
++ */
++static int get_lsr_info (struct bcm_serial *info, unsigned int *value)
++{
++ return( 0 );
++}
++
++/*
++ * This routine sends a break character out the serial port.
++ */
++static void send_break (struct bcm_serial *info, int duration)
++{
++ unsigned long flags;
++
++ if (!info->port)
++ return;
++
++ current->state = TASK_INTERRUPTIBLE;
++
++ /*save_flags (flags);
++ cli();*/
++ spin_lock_irqsave(&bcm963xx_serial_lock, flags);
++
++ info->port->control |= XMITBREAK;
++ schedule_timeout(duration);
++ info->port->control &= ~XMITBREAK;
++
++ spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
++ //restore_flags (flags);
++}
++
++static int bcm_ioctl (struct tty_struct * tty, struct file * file,
++ unsigned int cmd, unsigned long arg)
++{
++ int error;
++ struct bcm_serial * info = (struct bcm_serial *)tty->driver_data;
++ int retval;
++
++ if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
++ (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
++ (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT))
++ {
++ if (tty->flags & (1 << TTY_IO_ERROR))
++ return -EIO;
++ }
++ switch (cmd)
++ {
++
++ case TCSBRK: /* SVID version: non-zero arg --> no break */
++ retval = tty_check_change (tty);
++ if (retval)
++ return retval;
++ tty_wait_until_sent (tty, 0);
++ if (!arg)
++ send_break (info, HZ/4); /* 1/4 second */
++ return 0;
++
++ case TCSBRKP: /* support for POSIX tcsendbreak() */
++ retval = tty_check_change (tty);
++ if (retval)
++ return retval;
++ tty_wait_until_sent (tty, 0);
++ send_break (info, arg ? arg*(HZ/10) : HZ/4);
++ return 0;
++
++ case TIOCGSOFTCAR:
++ error = access_ok (VERIFY_WRITE, (void *)arg, sizeof(long));
++ if (!error)
++ return -EFAULT;
++ else
++ {
++ put_user (C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg);
++ return 0;
++ }
++
++ case TIOCSSOFTCAR:
++ error = get_user (arg, (unsigned long *)arg);
++ if (error)
++ return error;
++ tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
++ return 0;
++
++ case TIOCGSERIAL:
++ error = access_ok (VERIFY_WRITE, (void *)arg, sizeof(struct serial_struct));
++ if (!error)
++ return -EFAULT;
++ else
++ return get_serial_info (info, (struct serial_struct *)arg);
++
++ case TIOCSSERIAL:
++ return set_serial_info (info, (struct serial_struct *) arg);
++
++ case TIOCSERGETLSR: /* Get line status register */
++ error = access_ok (VERIFY_WRITE, (void *)arg, sizeof(unsigned int));
++ if (!error)
++ return -EFAULT;
++ else
++ return get_lsr_info (info, (unsigned int *)arg);
++
++ case TIOCSERGSTRUCT:
++ error = access_ok (VERIFY_WRITE, (void *)arg, sizeof(struct bcm_serial));
++ if (!error)
++ return -EFAULT;
++ else
++ {
++ copy_to_user((struct bcm_serial *)arg, info, sizeof(struct bcm_serial));
++ return 0;
++ }
++
++ default:
++ return -ENOIOCTLCMD;
++ }
++ return 0;
++}
++
++static void bcm_set_termios (struct tty_struct *tty, struct termios *old_termios)
++{
++ struct bcm_serial *info = (struct bcm_serial *)tty->driver_data;
++
++ if( tty->termios->c_cflag != old_termios->c_cflag )
++ change_speed (info->port, tty->termios->c_cflag);
++}
++
++/*
++ * ------------------------------------------------------------
++ * bcm63xx_cons_close()
++ *
++ * This routine is called when the serial port gets closed. First, we
++ * wait for the last remaining data to be sent. Then, we turn off
++ * the transmit enable and receive enable flags.
++ * ------------------------------------------------------------
++ */
++static void bcm63xx_cons_close (struct tty_struct *tty, struct file *filp)
++{
++ struct bcm_serial * info = (struct bcm_serial *)tty->driver_data;
++ unsigned long flags;
++
++ if (!info)
++ return;
++
++ /*save_flags (flags);
++ cli();*/
++ spin_lock_irqsave(&bcm963xx_serial_lock, flags);
++
++ if (tty_hung_up_p (filp))
++ {
++ spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
++ //restore_flags (flags);
++ return;
++ }
++
++ if ((tty->count == 1) && (info->count != 1))
++ {
++
++ /* Uh, oh. tty->count is 1, which means that the tty
++ * structure will be freed. Info->count should always
++ * be one in these conditions. If it's greater than
++ * one, we've got real problems, since it means the
++ * serial port won't be shutdown.
++ */
++ printk("bcm63xx_cons_close: bad serial port count; tty->count is 1, "
++ "info->count is %d\n", info->count);
++ info->count = 1;
++ }
++
++ if (--info->count < 0)
++ {
++ printk("ds_close: bad serial port count for ttys%d: %d\n",
++ info->line, info->count);
++ info->count = 0;
++ }
++
++ if (info->count)
++ {
++ //restore_flags (flags);
++ spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
++ return;
++ }
++
++ /* Now we wait for the transmit buffer to clear; and we notify
++ * the line discipline to only process XON/XOFF characters.
++ */
++ tty->closing = 1;
++
++ /* At this point we stop accepting input. To do this, we
++ * disable the receive line status interrupts.
++ */
++ shutdown (info);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++ if (tty->driver->flush_buffer)
++ tty->driver->flush_buffer (tty);
++#else
++ if (tty->driver.flush_buffer)
++ tty->driver.flush_buffer (tty);
++#endif
++ if (tty->ldisc.flush_buffer)
++ tty->ldisc.flush_buffer (tty);
++
++ tty->closing = 0;
++ info->event = 0;
++ info->tty = 0;
++ if (tty->ldisc.num != tty_ldisc_get(N_TTY)->num)
++ {
++ if (tty->ldisc.close)
++ (tty->ldisc.close)(tty);
++ tty->ldisc = *tty_ldisc_get(N_TTY);
++ tty->termios->c_line = N_TTY;
++ if (tty->ldisc.open)
++ (tty->ldisc.open)(tty);
++ }
++ if (info->blocked_open)
++ {
++ if (info->close_delay)
++ {
++ current->state = TASK_INTERRUPTIBLE;
++ schedule_timeout(info->close_delay);
++ }
++ wake_up_interruptible (&info->open_wait);
++ }
++ wake_up_interruptible (&info->close_wait);
++
++ //restore_flags (flags);
++ spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
++}
++
++/*
++ * bcm_hangup () --- called by tty_hangup() when a hangup is signaled.
++ */
++static void bcm_hangup (struct tty_struct *tty)
++{
++
++ struct bcm_serial *info = (struct bcm_serial *)tty->driver_data;
++
++ shutdown (info);
++ info->event = 0;
++ info->count = 0;
++ info->tty = 0;
++ wake_up_interruptible (&info->open_wait);
++}
++
++/*
++ * ------------------------------------------------------------
++ * rs_open() and friends
++ * ------------------------------------------------------------
++ */
++static int block_til_ready (struct tty_struct *tty, struct file *filp,
++ struct bcm_serial *info)
++{
++ return 0;
++}
++
++/*
++ * This routine is called whenever a serial port is opened. It
++ * enables interrupts for a serial port. It also performs the
++ * serial-specific initialization for the tty structure.
++ */
++static int bcm63xx_cons_open (struct tty_struct * tty, struct file * filp)
++{
++ struct bcm_serial *info;
++ int retval, line;
++
++ // Make sure we're only opening on of the ports we support
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++ line = MINOR(tty->driver->cdev.dev) - tty->driver->minor_start;
++#else
++ line = MINOR(tty->device) - tty->driver.minor_start;
++#endif
++
++ if ((line < 0) || (line >= BCM_NUM_UARTS))
++ return -ENODEV;
++
++ info = lines[line];
++
++ tty->low_latency=1;
++ info->port->intMask = 0; /* Clear any pending interrupts */
++ info->port->intMask = RXINT; /* Enable RX */
++
++ info->count++;
++ tty->driver_data = info;
++ info->tty = tty;
++ BcmHalInterruptEnable (INTERRUPT_ID_UART);
++
++ // Start up serial port
++ retval = startup (info);
++ if (retval)
++ return retval;
++
++ retval = block_til_ready (tty, filp, info);
++ if (retval)
++ return retval;
++
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++ info->pgrp = process_group(current);
++ info->session = current->signal->session;
++#else
++ info->session = current->session;
++ info->pgrp = current->pgrp;
++#endif
++
++ return 0;
++}
++
++
++static struct tty_operations rs_ops = {
++ .open = bcm63xx_cons_open,
++ .close = bcm63xx_cons_close,
++ .write = bcm63xx_cons_write,
++ .flush_chars = bcm63xx_cons_flush_chars,
++ .write_room = bcm63xx_cons_write_room,
++ .chars_in_buffer = bcm_chars_in_buffer,
++ .flush_buffer = bcm_flush_buffer,
++ .ioctl = bcm_ioctl,
++ .throttle = bcm_throttle,
++ .unthrottle = bcm_unthrottle,
++ .send_xchar = bcm_send_xchar,
++ .set_termios = bcm_set_termios,
++ .stop = bcm_stop,
++ .start = bcm_start,
++ .hangup = bcm_hangup,
++};
++
++/* --------------------------------------------------------------------------
++ Name: bcm63xx_serialinit
++ Purpose: Initialize our BCM63xx serial driver
++-------------------------------------------------------------------------- */
++static int __init bcm63xx_serialinit(void)
++{
++ int i, flags;
++ struct bcm_serial * info;
++
++ // Print the driver version information
++ printk(VER_STR);
++ serial_driver = alloc_tty_driver(BCM_NUM_UARTS);
++ if (!serial_driver)
++ return -ENOMEM;
++
++ serial_driver->owner = THIS_MODULE;
++ serial_driver->devfs_name = "tts/";
++// serial_driver.magic = TTY_DRIVER_MAGIC;
++ serial_driver->name = "ttyS";
++ serial_driver->major = TTY_MAJOR;
++ serial_driver->minor_start = 64;
++// serial_driver.num = BCM_NUM_UARTS;
++ serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
++ serial_driver->subtype = SERIAL_TYPE_NORMAL;
++ serial_driver->init_termios = tty_std_termios;
++ serial_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
++ serial_driver->flags = TTY_DRIVER_REAL_RAW;
++
++ serial_driver->termios = serial_termios;
++ serial_driver->termios_locked = serial_termios_locked;
++
++ tty_set_operations(serial_driver, &rs_ops);
++
++ if (tty_register_driver (serial_driver))
++ panic("Couldn't register serial driver\n");
++
++ //save_flags(flags); cli();
++ spin_lock_irqsave(&bcm963xx_serial_lock, flags);
++
++ for (i = 0; i < BCM_NUM_UARTS; i++)
++ {
++ info = &multi[i];
++ lines[i] = info;
++ info->magic = SERIAL_MAGIC;
++ info->port = (Uart *) ((char *)UART_BASE + (i * 0x20));
++ info->tty = 0;
++ info->irq = (2 - i) + 8;
++ info->line = i;
++ info->close_delay = 50;
++ info->closing_wait = 3000;
++ info->x_char = 0;
++ info->event = 0;
++ info->count = 0;
++ info->blocked_open = 0;
++ info->normal_termios = serial_driver->init_termios;
++ init_waitqueue_head(&info->open_wait);
++ init_waitqueue_head(&info->close_wait);
++
++ /* If we are pointing to address zero then punt - not correctly
++ * set up in setup.c to handle this.
++ */
++ if (! info->port)
++ return 0;
++ BcmHalMapInterrupt(bcm_interrupt, 0, INTERRUPT_ID_UART);
++ }
++
++ /* order matters here... the trick is that flags
++ * is updated... in request_irq - to immediatedly obliterate
++ * it is unwise.
++ */
++ spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
++ return 0;
++}
++
++module_init(bcm63xx_serialinit);
++
++/* --------------------------------------------------------------------------
++ Name: bcm_console_print
++ Purpose: bcm_console_print is registered for printk.
++ The console_lock must be held when we get here.
++-------------------------------------------------------------------------- */
++static void bcm_console_print (struct console * cons, const char * str,
++ unsigned int count)
++{
++ unsigned int i;
++ //_puts(str);
++ for(i=0; i<count; i++, str++)
++ {
++ _putc(*str);
++ if (*str == 10)
++ {
++ _putc(13);
++ }
++ }
++}
++
++static struct tty_driver * bcm_console_device(struct console * c, int *index)
++{
++ *index = c->index;
++ return serial_driver;
++}
++
++static int __init bcm_console_setup(struct console * co, char * options)
++{
++ return 0;
++}
++
++static struct console bcm_sercons = {
++ .name = "ttyS",
++ .write = bcm_console_print,
++ .device = bcm_console_device,
++ .setup = bcm_console_setup,
++ .flags = CON_PRINTBUFFER,
++ .index = -1,
++};
++
++static int __init bcm63xx_console_init(void)
++{
++ register_console(&bcm_sercons);
++ return 0;
++}
++
++console_initcall(bcm63xx_console_init);
+diff -urN linux.old/drivers/serial/Makefile linux.dev/drivers/serial/Makefile
+--- linux.old/drivers/serial/Makefile 2006-06-18 03:49:35.000000000 +0200
++++ linux.dev/drivers/serial/Makefile 2006-08-25 15:38:44.000000000 +0200
+@@ -55,3 +55,4 @@
+ obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o
+ obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o
+ obj-$(CONFIG_SERIAL_AT91) += at91_serial.o
++obj-$(CONFIG_BCM_SERIAL) += bcm63xx_cons.o
+diff -urN linux.old/include/asm-mips/bootinfo.h linux.dev/include/asm-mips/bootinfo.h
+--- linux.old/include/asm-mips/bootinfo.h 2006-08-25 00:43:22.000000000 +0200
++++ linux.dev/include/asm-mips/bootinfo.h 2006-08-25 00:39:38.000000000 +0200
+@@ -218,6 +218,14 @@
+ #define MACH_GROUP_TITAN 22 /* PMC-Sierra Titan */
+ #define MACH_TITAN_YOSEMITE 1 /* PMC-Sierra Yosemite */
+
++/*
++ * Valid machtype for group BRCM
++ */
++#define MACH_GROUP_BRCM 23 /* Broadcom boards */
++#define MACH_BCM96338 0
++#define MACH_BCM96345 1
++#define MACH_BCM96348 2
++
+ #define CL_SIZE COMMAND_LINE_SIZE
+
+ const char *get_system_type(void);
+diff -urN linux.old/include/asm-mips/cpu.h linux.dev/include/asm-mips/cpu.h
+--- linux.old/include/asm-mips/cpu.h 2006-08-25 00:43:22.000000000 +0200
++++ linux.dev/include/asm-mips/cpu.h 2006-08-25 00:39:38.000000000 +0200
+@@ -103,6 +103,13 @@
+
+ #define PRID_IMP_SR71000 0x0400
+
++/* These are the PRID's for when 23:16 == PRID_COMP_BROADCOM
++ */
++
++#define PRID_IMP_BCM6338 0x9000
++#define PRID_IMP_BCM6345 0x8000
++#define PRID_IMP_BCM6348 0x9100
++
+ /*
+ * Definitions for 7:0 on legacy processors
+ */
+@@ -200,7 +207,10 @@
+ #define CPU_SB1A 62
+ #define CPU_74K 63
+ #define CPU_R14000 64
+-#define CPU_LAST 64
++#define CPU_BCM6338 65
++#define CPU_BCM6345 66
++#define CPU_BCM6348 67
++#define CPU_LAST 67
+
+ /*
+ * ISA Level encodings
+diff -urN linux.old/include/asm-mips/mach-bcm963xx/cpu-feature-overrides.h linux.dev/include/asm-mips/mach-bcm963xx/cpu-feature-overrides.h
+--- linux.old/include/asm-mips/mach-bcm963xx/cpu-feature-overrides.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/mach-bcm963xx/cpu-feature-overrides.h 2006-08-25 11:27:40.000000000 +0200
+@@ -0,0 +1,36 @@
++#ifndef __ASM_MACH_BCM963XX_CPU_FEATURE_OVERRIDES_H
++#define __ASM_MACH_BCM963XX_CPU_FEATURE_OVERRIDES_H
++
++#define cpu_has_tlb 1
++#define cpu_has_4kex 4
++#define cpu_has_4ktlb 8
++#define cpu_has_fpu 0
++#define cpu_has_32fpr 0
++#define cpu_has_counter 0x40
++#define cpu_has_watch 0
++#define cpu_has_mips16 0
++#define cpu_has_divec 0x200
++#define cpu_has_vce 0
++#define cpu_has_cache_cdex_p 0
++#define cpu_has_cache_cdex_s 0
++#define cpu_has_prefetch 0x40000
++#define cpu_has_mcheck 0x2000
++#define cpu_has_ejtag 0x4000
++#define cpu_has_llsc 0x10000
++#define cpu_has_vtag_icache 0
++#define cpu_has_dc_aliases 0
++#define cpu_has_ic_fills_f_dc 0
++
++#define cpu_has_nofpuex 0
++#define cpu_has_64bits 0
++#define cpu_has_64bit_zero_reg 0
++#define cpu_has_64bit_gp_regs 0
++#define cpu_has_64bit_addresses 0
++
++#define cpu_has_subset_pcaches 0
++
++#define cpu_dcache_line_size() 16
++#define cpu_icache_line_size() 16
++#define cpu_scache_line_size() 0
++
++#endif /* __ASM_MACH_BCM963XX_CPU_FEATURE_OVERRIDES_H */
+diff -urN linux.old/include/asm-mips/mach-generic/param.h linux.dev/include/asm-mips/mach-generic/param.h
+--- linux.old/include/asm-mips/mach-generic/param.h 2006-08-25 00:43:22.000000000 +0200
++++ linux.dev/include/asm-mips/mach-generic/param.h 2006-08-25 00:39:38.000000000 +0200
+@@ -8,6 +8,6 @@
+ #ifndef __ASM_MACH_GENERIC_PARAM_H
+ #define __ASM_MACH_GENERIC_PARAM_H
+
+-#define HZ 1000 /* Internal kernel timer frequency */
++#define HZ 200 /* Internal kernel timer frequency */
+
+ #endif /* __ASM_MACH_GENERIC_PARAM_H */
+diff -urN linux.old/include/asm-mips/module.h linux.dev/include/asm-mips/module.h
+--- linux.old/include/asm-mips/module.h 2006-08-25 00:43:22.000000000 +0200
++++ linux.dev/include/asm-mips/module.h 2006-08-25 00:39:38.000000000 +0200
+@@ -113,6 +113,12 @@
+ #define MODULE_PROC_FAMILY "RM9000 "
+ #elif defined CONFIG_CPU_SB1
+ #define MODULE_PROC_FAMILY "SB1 "
++#elif defined CONFIG_CPU_BCM6338
++#define MODULE_PROC_FAMILY "BCM6338 "
++#elif defined CONFIG_CPU_BCM6345
++#define MODULE_PROC_FAMILY "BCM6345 "
++#elif defined CONFIG_CPU_BCM6348
++#define MODULE_PROC_FAMILY "BCM6348 "
+ #else
+ #error MODULE_PROC_FAMILY undefined for your processor configuration
+ #endif
+
diff --git a/target/linux/brcm63xx-2.6/patches/040-bcm963xx_flashmap.patch b/target/linux/brcm63xx-2.6/patches/040-bcm963xx_flashmap.patch
new file mode 100644
index 0000000000..997cc980f9
--- /dev/null
+++ b/target/linux/brcm63xx-2.6/patches/040-bcm963xx_flashmap.patch
@@ -0,0 +1,213 @@
+diff -urN linux-2.6.17/drivers/mtd/maps/bcm963xx-flash.c linux-2.6.17-brcm63xx/drivers/mtd/maps/bcm963xx-flash.c
+--- linux-2.6.17/drivers/mtd/maps/bcm963xx-flash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-brcm63xx/drivers/mtd/maps/bcm963xx-flash.c 2006-08-30 13:03:16.000000000 +0200
+@@ -0,0 +1,135 @@
++/*
++ * $Id$
++ * Copyright (C) 2006 Florian Fainelli
++ * Copyright (C) $Date$ $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 St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* This is the BCM963xx flash map driver, in its actual state it only supports BCM96348 devices
++ * this driver is able to manage both bootloader we found on these boards : CFE and RedBoot
++ *
++ * RedBoot :
++ * - this bootloader allows us to parse partitions and therefore deduce the MTD partition table
++ *
++ * CFE :
++ * - we have to use a "physically mapped flash" defined bellow
++ *
++ */
++
++#include <asm/io.h>
++#include <linux/init.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <board.h>
++
++#define WINDOW_ADDR 0x1e400000 /* Real address of the flash */
++#define WINDOW_SIZE 0x800000 /* Size of flash */
++#define BUSWIDTH 2 /* Buswidth */
++#define EXTENDED_SIZE 0xBE400000 /* Extended flash addresse */
++
++extern int boot_loader_type; /* For RedBoot / CFE detection */
++extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts, unsigned long fis_origin);
++static struct mtd_partition *parsed_parts;
++
++static void __exit bcm963xx_mtd_cleanup(void);
++
++static struct mtd_info *bcm963xx_mtd_info;
++
++static struct map_info bcm963xx_map = {
++ .name = "bcm963xx",
++ .size = WINDOW_SIZE,
++ .bankwidth = BUSWIDTH,
++ .phys = WINDOW_ADDR,
++};
++
++static struct mtd_partition bcm963xx_parts[] = {
++ { name: "bootloader", size: 0, offset: 0, mask_flags: MTD_WRITEABLE },
++ { name: "rootfs", size: 0, offset: 0},
++ { name: "jffs2", size: 5 * 0x10000, offset: 57*0x10000}
++};
++
++static int bcm963xx_parts_size = sizeof(bcm963xx_parts) / sizeof(bcm963xx_parts[0]);
++
++static int __init bcm963xx_mtd_init(void)
++{
++ printk("bcm963xx: 0x%08x at 0x%08x\n", WINDOW_SIZE, WINDOW_ADDR);
++ bcm963xx_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
++
++ if (!bcm963xx_map.virt) {
++ printk("bcm963xx: Failed to ioremap\n");
++ return -EIO;
++ }
++
++ simple_map_init(&bcm963xx_map);
++
++ bcm963xx_mtd_info = do_map_probe("cfi_probe", &bcm963xx_map);
++
++ if (bcm963xx_mtd_info) {
++ bcm963xx_mtd_info->owner = THIS_MODULE;
++
++ if (boot_loader_type == BOOT_CFE)
++ {
++ add_mtd_device(bcm963xx_mtd_info);
++ add_mtd_partitions(bcm963xx_mtd_info, bcm963xx_parts, bcm963xx_parts_size);
++ return 0;
++ }
++ else
++ {
++ int parsed_nr_parts = 0;
++ char * part_type;
++
++ if (bcm963xx_mtd_info->size > 0x00400000) {
++ printk("Support for extended flash memory size : 0x%08X ; ONLY 64MBIT SUPPORT\n", bcm963xx_mtd_info->size);
++ bcm963xx_map.virt = (unsigned long)(EXTENDED_SIZE);
++ }
++
++#ifdef CONFIG_MTD_REDBOOT_PARTS
++ if (parsed_nr_parts == 0) {
++ int ret = parse_redboot_partitions(bcm963xx_mtd_info, &parsed_parts, 0);
++ if (ret > 0) {
++ part_type = "RedBoot";
++ parsed_nr_parts = ret;
++ }
++ }
++#endif
++ add_mtd_partitions(bcm963xx_mtd_info, parsed_parts, parsed_nr_parts);
++
++ return 0;
++ }
++ }
++ iounmap(bcm963xx_map.virt);
++ return -ENXIO;
++}
++
++static void __exit bcm963xx_mtd_cleanup(void)
++{
++ if (bcm963xx_mtd_info) {
++ del_mtd_partitions(bcm963xx_mtd_info);
++ map_destroy(bcm963xx_mtd_info);
++ }
++
++ if (bcm963xx_map.virt) {
++ iounmap(bcm963xx_map.virt);
++ bcm963xx_map.virt = 0;
++ }
++}
++
++module_init(bcm963xx_mtd_init);
++module_exit(bcm963xx_mtd_cleanup);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
+diff -urN linux-2.6.17/drivers/mtd/maps/Kconfig linux-2.6.17-brcm63xx/drivers/mtd/maps/Kconfig
+--- linux-2.6.17/drivers/mtd/maps/Kconfig 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-brcm63xx/drivers/mtd/maps/Kconfig 2006-08-30 13:03:06.000000000 +0200
+@@ -224,6 +224,13 @@
+ Flash memory access on 4G Systems MTX-1 Board. If you have one of
+ these boards and would like to use the flash chips on it, say 'Y'.
+
++config MTD_BCM963XX
++ tristate "BCM963xx Flash device"
++ depends on MIPS && MIPS_BRCM
++ help
++ Flash memory access on BCM963xx boards. Currently only works with
++ RedBoot, CFE support coming soon.
++
+ config MTD_DILNETPC
+ tristate "CFI Flash device mapped on DIL/Net PC"
+ depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT
+diff -urN linux-2.6.17/drivers/mtd/maps/Makefile linux-2.6.17-brcm63xx/drivers/mtd/maps/Makefile
+--- linux-2.6.17/drivers/mtd/maps/Makefile 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-brcm63xx/drivers/mtd/maps/Makefile 2006-08-30 13:03:06.000000000 +0200
+@@ -71,3 +71,4 @@
+ obj-$(CONFIG_MTD_OMAP_NOR) += omap_nor.o
+ obj-$(CONFIG_MTD_MTX1) += mtx-1_flash.o
+ obj-$(CONFIG_MTD_TQM834x) += tqm834x.o
++obj-$(CONFIG_MTD_BCM963XX) += bcm963xx-flash.o
+diff -urN linux-2.6.17/drivers/mtd/redboot.c linux-2.6.17-brcm63xx/drivers/mtd/redboot.c
+--- linux-2.6.17/drivers/mtd/redboot.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-brcm63xx/drivers/mtd/redboot.c 2006-08-30 13:03:06.000000000 +0200
+@@ -39,7 +39,7 @@
+ return 1;
+ }
+
+-static int parse_redboot_partitions(struct mtd_info *master,
++int parse_redboot_partitions(struct mtd_info *master,
+ struct mtd_partition **pparts,
+ unsigned long fis_origin)
+ {
+@@ -120,11 +120,19 @@
+ goto out;
+ }
+
++ if (!fis_origin) {
++ for (i = 0; i < numslots; i++) {
++ if (!strncmp(buf[i].name, "RedBoot", 8)) {
++ fis_origin = (buf[i].flash_base & (master->size << 1) - 1);
++ }
++ }
++ }
++
+ for (i = 0; i < numslots; i++) {
+ struct fis_list *new_fl, **prev;
+
+ if (buf[i].name[0] == 0xff)
+- continue;
++ break;
+ if (!redboot_checksum(&buf[i]))
+ break;
+
+@@ -135,11 +143,10 @@
+ goto out;
+ }
+ new_fl->img = &buf[i];
+- if (fis_origin) {
+- buf[i].flash_base -= fis_origin;
+- } else {
+- buf[i].flash_base &= master->size-1;
+- }
++ if (fis_origin) {
++ buf[i].flash_base -= fis_origin;
++ }
++ buf[i].flash_base &= (master->size << 1) - 1;
+
+ /* I'm sure the JFFS2 code has done me permanent damage.
+ * I now think the following is _normal_
diff --git a/target/linux/brcm63xx-2.6/patches/100-binary_hacks.patch b/target/linux/brcm63xx-2.6/patches/100-binary_hacks.patch
new file mode 100644
index 0000000000..d81d978308
--- /dev/null
+++ b/target/linux/brcm63xx-2.6/patches/100-binary_hacks.patch
@@ -0,0 +1,267 @@
+diff -urN linux.old/include/asm-mips/cpu-info.h linux.dev/include/asm-mips/cpu-info.h
+--- linux.old/include/asm-mips/cpu-info.h 2006-06-18 03:49:35.000000000 +0200
++++ linux.dev/include/asm-mips/cpu-info.h 2006-08-27 21:02:04.000000000 +0200
+@@ -63,7 +63,6 @@
+ * Capability and feature descriptor structure for MIPS CPU
+ */
+ unsigned long options;
+- unsigned long ases;
+ unsigned int processor_id;
+ unsigned int fpu_id;
+ unsigned int cputype;
+@@ -84,6 +83,7 @@
+ int tc_id; /* Thread Context number */
+ #endif /* CONFIG_MIPS_MT */
+ void *data; /* Additional data */
++ unsigned long ases;
+ } __attribute__((aligned(SMP_CACHE_BYTES)));
+
+ extern struct cpuinfo_mips cpu_data[];
+
+diff -urN linux.old/include/linux/netdevice.h linux.dev/include/linux/netdevice.h
+--- linux.old/include/linux/netdevice.h 2006-06-18 03:49:35.000000000 +0200
++++ linux.dev/include/linux/netdevice.h 2006-08-27 21:02:04.000000000 +0200
+@@ -266,8 +266,6 @@
+ * the interface.
+ */
+ char name[IFNAMSIZ];
+- /* device name hash chain */
+- struct hlist_node name_hlist;
+
+ /*
+ * I/O specific fields
+@@ -295,22 +293,6 @@
+
+ /* ------- Fields preinitialized in Space.c finish here ------- */
+
+- /* Net device features */
+- unsigned long features;
+-#define NETIF_F_SG 1 /* Scatter/gather IO. */
+-#define NETIF_F_IP_CSUM 2 /* Can checksum only TCP/UDP over IPv4. */
+-#define NETIF_F_NO_CSUM 4 /* Does not require checksum. F.e. loopack. */
+-#define NETIF_F_HW_CSUM 8 /* Can checksum all the packets. */
+-#define NETIF_F_HIGHDMA 32 /* Can DMA to high memory. */
+-#define NETIF_F_FRAGLIST 64 /* Scatter/gather IO. */
+-#define NETIF_F_HW_VLAN_TX 128 /* Transmit VLAN hw acceleration */
+-#define NETIF_F_HW_VLAN_RX 256 /* Receive VLAN hw acceleration */
+-#define NETIF_F_HW_VLAN_FILTER 512 /* Receive filtering on VLAN */
+-#define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */
+-#define NETIF_F_TSO 2048 /* Can offload TCP/IP segmentation */
+-#define NETIF_F_LLTX 4096 /* LockLess TX */
+-#define NETIF_F_UFO 8192 /* Can offload UDP Large Send*/
+-
+ struct net_device *next_sched;
+
+ /* Interface index. Unique device identifier */
+@@ -324,8 +306,6 @@
+ /* List of functions to handle Wireless Extensions (instead of ioctl).
+ * See <net/iw_handler.h> for details. Jean II */
+ const struct iw_handler_def * wireless_handlers;
+- /* Instance data managed by the core of Wireless Extensions. */
+- struct iw_public_data * wireless_data;
+
+ struct ethtool_ops *ethtool_ops;
+
+@@ -335,33 +315,37 @@
+ * will (read: may be cleaned up at will).
+ */
+
++ /* These may be needed for future network-power-down code. */
++ unsigned long trans_start; /* Time (in jiffies) of last Tx */
++ unsigned long last_rx; /* Time of last Rx */
+
+- unsigned int flags; /* interface flags (a la BSD) */
++ unsigned short flags; /* interface flags (a la BSD) */
+ unsigned short gflags;
+ unsigned short priv_flags; /* Like 'flags' but invisible to userspace. */
+- unsigned short padded; /* How much padding added by alloc_netdev() */
+-
+- unsigned char operstate; /* RFC2863 operstate */
+- unsigned char link_mode; /* mapping policy to operstate */
++ unsigned short __useless_padding;
+
+ unsigned mtu; /* interface MTU value */
+ unsigned short type; /* interface hardware type */
+ unsigned short hard_header_len; /* hardware hdr length */
++ void *priv; /* pointer to private data */
+
+ struct net_device *master; /* Pointer to master device of a group,
+ * which this device is member of.
+ */
+
+ /* Interface address info. */
+- unsigned char perm_addr[MAX_ADDR_LEN]; /* permanent hw address */
++ unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */
++ unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address, (before bcast
++ because most packets are unicast) */
+ unsigned char addr_len; /* hardware address length */
+- unsigned short dev_id; /* for shared network cards */
+
+ struct dev_mc_list *mc_list; /* Multicast mac addresses */
+ int mc_count; /* Number of installed mcasts */
+ int promiscuity;
+ int allmulti;
+
++ int watchdog_timeo; /* used by dev_watchdog() */
++ struct timer_list watchdog_timer;
+
+ /* Protocol specific pointers */
+
+@@ -378,29 +362,17 @@
+ struct list_head poll_list ____cacheline_aligned_in_smp;
+ /* Link to poll list */
+
+- int (*poll) (struct net_device *dev, int *quota);
+ int quota;
+ int weight;
+- unsigned long last_rx; /* Time of last Rx */
+ /* Interface address info used in eth_type_trans() */
+- unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address, (before bcast
+- because most packets are unicast) */
+-
+- unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */
+-
+-/*
+- * Cache line mostly used on queue transmit path (qdisc)
+- */
+- /* device queue lock */
+- spinlock_t queue_lock ____cacheline_aligned_in_smp;
+ struct Qdisc *qdisc;
+ struct Qdisc *qdisc_sleeping;
++ struct Qdisc *qdisc_ingress;
+ struct list_head qdisc_list;
+ unsigned long tx_queue_len; /* Max frames per queue allowed */
+
+ /* ingress path synchronizer */
+ spinlock_t ingress_lock;
+- struct Qdisc *qdisc_ingress;
+
+ /*
+ * One part is mostly used on xmit path (device)
+@@ -411,16 +383,13 @@
+ if nobody entered there.
+ */
+ int xmit_lock_owner;
+- void *priv; /* pointer to private data */
+- int (*hard_start_xmit) (struct sk_buff *skb,
+- struct net_device *dev);
+- /* These may be needed for future network-power-down code. */
+- unsigned long trans_start; /* Time (in jiffies) of last Tx */
+-
+- int watchdog_timeo; /* used by dev_watchdog() */
+- struct timer_list watchdog_timer;
+
+ /*
++ * Cache line mostly used on queue transmit path (qdisc)
++ */
++ /* device queue lock */
++ spinlock_t queue_lock ____cacheline_aligned_in_smp;
++/*
+ * refcnt is a very hot point, so align it on SMP
+ */
+ /* Number of references to this device */
+@@ -428,6 +397,8 @@
+
+ /* delayed register/unregister */
+ struct list_head todo_list;
++ /* device name hash chain */
++ struct hlist_node name_hlist;
+ /* device index hash chain */
+ struct hlist_node index_hlist;
+
+@@ -439,6 +410,22 @@
+ NETREG_RELEASED, /* called free_netdev */
+ } reg_state;
+
++ /* Net device features */
++ unsigned int features;
++#define NETIF_F_SG 1 /* Scatter/gather IO. */
++#define NETIF_F_IP_CSUM 2 /* Can checksum only TCP/UDP over IPv4. */
++#define NETIF_F_NO_CSUM 4 /* Does not require checksum. F.e. loopack. */
++#define NETIF_F_HW_CSUM 8 /* Can checksum all the packets. */
++#define NETIF_F_HIGHDMA 32 /* Can DMA to high memory. */
++#define NETIF_F_FRAGLIST 64 /* Scatter/gather IO. */
++#define NETIF_F_HW_VLAN_TX 128 /* Transmit VLAN hw acceleration */
++#define NETIF_F_HW_VLAN_RX 256 /* Receive VLAN hw acceleration */
++#define NETIF_F_HW_VLAN_FILTER 512 /* Receive filtering on VLAN */
++#define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */
++#define NETIF_F_TSO 2048 /* Can offload TCP/IP segmentation */
++#define NETIF_F_LLTX 4096 /* LockLess TX */
++#define NETIF_F_UFO 8192 /* Can offload UDP Large Send*/
++
+ /* Called after device is detached from network. */
+ void (*uninit)(struct net_device *dev);
+ /* Called after last user reference disappears. */
+@@ -447,7 +434,10 @@
+ /* Pointers to interface service routines. */
+ int (*open)(struct net_device *dev);
+ int (*stop)(struct net_device *dev);
++ int (*hard_start_xmit) (struct sk_buff *skb,
++ struct net_device *dev);
+ #define HAVE_NETDEV_POLL
++ int (*poll) (struct net_device *dev, int *quota);
+ int (*hard_header) (struct sk_buff *skb,
+ struct net_device *dev,
+ unsigned short type,
+@@ -490,6 +480,7 @@
+ int (*neigh_setup)(struct net_device *dev, struct neigh_parms *);
+ #ifdef CONFIG_NETPOLL
+ struct netpoll_info *npinfo;
++ int netpoll_rx;
+ #endif
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ void (*poll_controller)(struct net_device *dev);
+@@ -507,6 +498,17 @@
+ struct class_device class_dev;
+ /* space for optional statistics and wireless sysfs groups */
+ struct attribute_group *sysfs_groups[3];
++
++ unsigned char operstate; /* RFC2863 operstate */
++ unsigned char link_mode; /* mapping policy to operstate */
++ unsigned short dev_id; /* for shared network cards */
++
++ /* Instance data managed by the core of Wireless Extensions. */
++ struct iw_public_data * wireless_data;
++
++ unsigned char perm_addr[MAX_ADDR_LEN]; /* permanent hw address */
++
++ unsigned short padded; /* How much padding added by alloc_netdev() */
+ };
+
+ #define NETDEV_ALIGN 32
+@@ -587,9 +589,10 @@
+
+ struct softnet_data
+ {
+- struct net_device *output_queue;
++ int useless_padding[3];
+ struct sk_buff_head input_pkt_queue;
+ struct list_head poll_list;
++ struct net_device *output_queue;
+ struct sk_buff *completion_queue;
+
+ struct net_device backlog_dev; /* Sorry. 8) */
+diff -urN linux.old/include/linux/timer.h linux.dev/include/linux/timer.h
+--- linux.old/include/linux/timer.h 2006-06-18 03:49:35.000000000 +0200
++++ linux.dev/include/linux/timer.h 2006-08-27 21:02:04.000000000 +0200
+@@ -12,6 +12,9 @@
+ struct list_head entry;
+ unsigned long expires;
+
++ spinlock_t lock;
++ unsigned long magic;
++
+ void (*function)(unsigned long);
+ unsigned long data;
+
+diff -urN linux.old/kernel/timer.c linux.dev/kernel/timer.c
+--- linux.old/kernel/timer.c 2006-06-18 03:49:35.000000000 +0200
++++ linux.dev/kernel/timer.c 2006-08-27 21:02:04.000000000 +0200
+@@ -147,6 +147,7 @@
+ {
+ timer->entry.next = NULL;
+ timer->base = per_cpu(tvec_bases, raw_smp_processor_id());
++ spin_lock_init(&timer->lock);
+ }
+ EXPORT_SYMBOL(init_timer);
+
diff --git a/target/linux/control/kernel.control b/target/linux/control/kernel.control
new file mode 100644
index 0000000000..be5f10940d
--- /dev/null
+++ b/target/linux/control/kernel.control
@@ -0,0 +1,4 @@
+Package: kernel
+Priority: optional
+Section: sys
+Description: Virtual package for the Kernel
diff --git a/target/linux/control/kmod-atm.control b/target/linux/control/kmod-atm.control
new file mode 100644
index 0000000000..ae07126a6a
--- /dev/null
+++ b/target/linux/control/kmod-atm.control
@@ -0,0 +1,4 @@
+Package: kmod-atm
+Priority: optional
+Section: sys
+Description: ATM/ADSL support
diff --git a/target/linux/control/kmod-ax25.control b/target/linux/control/kmod-ax25.control
new file mode 100644
index 0000000000..18c4cef8fe
--- /dev/null
+++ b/target/linux/control/kmod-ax25.control
@@ -0,0 +1,4 @@
+Package: kmod-ax25
+Priority: optional
+Section: net
+Description: Kernel AX25 driver
diff --git a/target/linux/control/kmod-bluetooth.control b/target/linux/control/kmod-bluetooth.control
new file mode 100644
index 0000000000..9f5409a9b7
--- /dev/null
+++ b/target/linux/control/kmod-bluetooth.control
@@ -0,0 +1,4 @@
+Package: kmod-bluetooth
+Priority: optional
+Section: sys
+Description: Bluetooth support
diff --git a/target/linux/control/kmod-brcm-et.control b/target/linux/control/kmod-brcm-et.control
new file mode 100644
index 0000000000..3e65bc906a
--- /dev/null
+++ b/target/linux/control/kmod-brcm-et.control
@@ -0,0 +1,4 @@
+Package: kmod-brcm-et
+Priority: optional
+Section: sys
+Description: Proprietary driver for Broadcom Ethernet chipsets
diff --git a/target/linux/control/kmod-brcm-wl.control b/target/linux/control/kmod-brcm-wl.control
new file mode 100644
index 0000000000..cf610c3673
--- /dev/null
+++ b/target/linux/control/kmod-brcm-wl.control
@@ -0,0 +1,4 @@
+Package: kmod-brcm-wl
+Priority: optional
+Section: sys
+Description: Proprietary driver for Broadcom Wireless chipsets
diff --git a/target/linux/control/kmod-brcm-wl2.control b/target/linux/control/kmod-brcm-wl2.control
new file mode 100644
index 0000000000..4ae019ddf9
--- /dev/null
+++ b/target/linux/control/kmod-brcm-wl2.control
@@ -0,0 +1,5 @@
+Package: kmod-brcm-wl2
+Priority: optional
+Section: sys
+Description: Proprietary driver for Broadcom Wireless chipsets
+ New version with multi-BSS support
diff --git a/target/linux/control/kmod-cpmac.control b/target/linux/control/kmod-cpmac.control
new file mode 100644
index 0000000000..18f8e901b6
--- /dev/null
+++ b/target/linux/control/kmod-cpmac.control
@@ -0,0 +1,4 @@
+Package: kmod-cpmac
+Priority: optional
+Section: sys
+Description: AR7 CPMAC ethernet driver
diff --git a/target/linux/control/kmod-fs-cifs.control b/target/linux/control/kmod-fs-cifs.control
new file mode 100644
index 0000000000..832224764d
--- /dev/null
+++ b/target/linux/control/kmod-fs-cifs.control
@@ -0,0 +1,4 @@
+Package: kmod-fs-cifs
+Priority: optional
+Section: sys
+Description: Kernel modules for CIFS support
diff --git a/target/linux/control/kmod-fs-ext2.control b/target/linux/control/kmod-fs-ext2.control
new file mode 100644
index 0000000000..ec06cffe23
--- /dev/null
+++ b/target/linux/control/kmod-fs-ext2.control
@@ -0,0 +1,4 @@
+Package: kmod-fs-ext2
+Priority: optional
+Section: sys
+Description: Kernel modules for EXT2 filesystem support
diff --git a/target/linux/control/kmod-fs-ext3.control b/target/linux/control/kmod-fs-ext3.control
new file mode 100644
index 0000000000..735178895d
--- /dev/null
+++ b/target/linux/control/kmod-fs-ext3.control
@@ -0,0 +1,4 @@
+Package: kmod-fs-ext3
+Priority: optional
+Section: sys
+Description: Kernel modules for EXT3 filesystem support
diff --git a/target/linux/control/kmod-fs-hfsplus.control b/target/linux/control/kmod-fs-hfsplus.control
new file mode 100644
index 0000000000..bb59553338
--- /dev/null
+++ b/target/linux/control/kmod-fs-hfsplus.control
@@ -0,0 +1,4 @@
+Package: kmod-fs-hfsplus
+Priority: optional
+Section: sys
+Description: Kernel modules for HFS+ filesystem support
diff --git a/target/linux/control/kmod-fs-minix.control b/target/linux/control/kmod-fs-minix.control
new file mode 100644
index 0000000000..2169ba6acd
--- /dev/null
+++ b/target/linux/control/kmod-fs-minix.control
@@ -0,0 +1,4 @@
+Package: kmod-fs-minix
+Priority: optional
+Section: sys
+Description: Kernel modules for MINIX filesystem support
diff --git a/target/linux/control/kmod-fs-nfs.control b/target/linux/control/kmod-fs-nfs.control
new file mode 100644
index 0000000000..32dc9ff323
--- /dev/null
+++ b/target/linux/control/kmod-fs-nfs.control
@@ -0,0 +1,4 @@
+Package: kmod-fs-nfs
+Priority: optional
+Section: sys
+Description: Kernel modules for NFS support
diff --git a/target/linux/control/kmod-fs-vfat.control b/target/linux/control/kmod-fs-vfat.control
new file mode 100644
index 0000000000..cc2983313d
--- /dev/null
+++ b/target/linux/control/kmod-fs-vfat.control
@@ -0,0 +1,4 @@
+Package: kmod-fs-vfat
+Priority: optional
+Section: sys
+Description: Kernel modules for VFAT filesystem support
diff --git a/target/linux/control/kmod-fs-xfs.control b/target/linux/control/kmod-fs-xfs.control
new file mode 100644
index 0000000000..8efd35a666
--- /dev/null
+++ b/target/linux/control/kmod-fs-xfs.control
@@ -0,0 +1,4 @@
+Package: kmod-fs-xfs
+Priority: optional
+Section: sys
+Description: Kernel modules for XFS filesystem support
diff --git a/target/linux/control/kmod-imq.control b/target/linux/control/kmod-imq.control
new file mode 100644
index 0000000000..78925a40b5
--- /dev/null
+++ b/target/linux/control/kmod-imq.control
@@ -0,0 +1,4 @@
+Package: kmod-imq
+Priority: optional
+Section: net
+Description: Kernel support for the Intermediate Queueing device
diff --git a/target/linux/control/kmod-iptables-extra.control b/target/linux/control/kmod-iptables-extra.control
new file mode 100644
index 0000000000..96a3b1acc0
--- /dev/null
+++ b/target/linux/control/kmod-iptables-extra.control
@@ -0,0 +1,4 @@
+Package: kmod-iptables-extra
+Priority: optional
+Section: net
+Description: Extra kernel modules for iptables
diff --git a/target/linux/control/kmod-iptables.control b/target/linux/control/kmod-iptables.control
new file mode 100644
index 0000000000..7f97cc44b6
--- /dev/null
+++ b/target/linux/control/kmod-iptables.control
@@ -0,0 +1,4 @@
+Package: kmod-iptables
+Priority: optional
+Section: net
+Description: kernel modules for iptables
diff --git a/target/linux/control/kmod-loop.control b/target/linux/control/kmod-loop.control
new file mode 100644
index 0000000000..48bcb835d6
--- /dev/null
+++ b/target/linux/control/kmod-loop.control
@@ -0,0 +1,4 @@
+Package: kmod-loop
+Priority: optional
+Section: sys
+Description: Kernel module for mount loopback support
diff --git a/target/linux/control/kmod-lp.control b/target/linux/control/kmod-lp.control
new file mode 100644
index 0000000000..5d40813159
--- /dev/null
+++ b/target/linux/control/kmod-lp.control
@@ -0,0 +1,4 @@
+Package: kmod-lp
+Priority: optional
+Section: sys
+Description: Kernel modules for parallel port support and line printer
diff --git a/target/linux/control/kmod-nbd.control b/target/linux/control/kmod-nbd.control
new file mode 100644
index 0000000000..3c467223bf
--- /dev/null
+++ b/target/linux/control/kmod-nbd.control
@@ -0,0 +1,4 @@
+Package: kmod-nbd
+Priority: optional
+Section: sys
+Description: Kernel module for network block device
diff --git a/target/linux/control/kmod-net-airo.control b/target/linux/control/kmod-net-airo.control
new file mode 100644
index 0000000000..3693df589b
--- /dev/null
+++ b/target/linux/control/kmod-net-airo.control
@@ -0,0 +1,4 @@
+Package: kmod-net-airo
+Priority: optional
+Section: sys
+Description: Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards kernel support
diff --git a/target/linux/control/kmod-net-hermes-pci.control b/target/linux/control/kmod-net-hermes-pci.control
new file mode 100644
index 0000000000..911609d4f6
--- /dev/null
+++ b/target/linux/control/kmod-net-hermes-pci.control
@@ -0,0 +1,4 @@
+Package: kmod-net-hermes-pci
+Priority: optional
+Section: sys
+Description: Intersil Prism 2.5 PCI 802.11b adaptor support
diff --git a/target/linux/control/kmod-net-hermes-plx.control b/target/linux/control/kmod-net-hermes-plx.control
new file mode 100644
index 0000000000..8df07274d9
--- /dev/null
+++ b/target/linux/control/kmod-net-hermes-plx.control
@@ -0,0 +1,4 @@
+Package: kmod-net-hermes-plx
+Priority: optional
+Section: sys
+Description: Hermes in PLX9052 based PCI adaptor (Netgear MA301, etc.) kernel support
diff --git a/target/linux/control/kmod-net-hermes.control b/target/linux/control/kmod-net-hermes.control
new file mode 100644
index 0000000000..7fa91a9d20
--- /dev/null
+++ b/target/linux/control/kmod-net-hermes.control
@@ -0,0 +1,4 @@
+Package: kmod-net-hermes
+Priority: optional
+Section: sys
+Description: Hermes chipset 802.11b support (Orinoco/Prism2/Symbol) kernel support
diff --git a/target/linux/control/kmod-net-prism54.control b/target/linux/control/kmod-net-prism54.control
new file mode 100644
index 0000000000..2ba3111ea6
--- /dev/null
+++ b/target/linux/control/kmod-net-prism54.control
@@ -0,0 +1,4 @@
+Package: kmod-net-prism54
+Priority: optional
+Section: sys
+Description: Intersil Prism GT/Duette/Indigo PCI/PCMCIA cards kernel support
diff --git a/target/linux/control/kmod-nls-base.control b/target/linux/control/kmod-nls-base.control
new file mode 100644
index 0000000000..067f5dec86
--- /dev/null
+++ b/target/linux/control/kmod-nls-base.control
@@ -0,0 +1,4 @@
+Package: kmod-nls-base
+Priority: optional
+Section: sys
+Description: Kernel modules for basic native language support
diff --git a/target/linux/control/kmod-nls-cp437.control b/target/linux/control/kmod-nls-cp437.control
new file mode 100644
index 0000000000..f47146083f
--- /dev/null
+++ b/target/linux/control/kmod-nls-cp437.control
@@ -0,0 +1,4 @@
+Package: kmod-nls-cp437
+Priority: optional
+Section: sys
+Description: Kernel module for codepage 437
diff --git a/target/linux/control/kmod-nls-cp850.control b/target/linux/control/kmod-nls-cp850.control
new file mode 100644
index 0000000000..1a7d083f90
--- /dev/null
+++ b/target/linux/control/kmod-nls-cp850.control
@@ -0,0 +1,4 @@
+Package: kmod-nls-cp850
+Priority: optional
+Section: sys
+Description: Kernel module for codepage 850
diff --git a/target/linux/control/kmod-nls-iso8859-1.control b/target/linux/control/kmod-nls-iso8859-1.control
new file mode 100644
index 0000000000..91e40faa7a
--- /dev/null
+++ b/target/linux/control/kmod-nls-iso8859-1.control
@@ -0,0 +1,4 @@
+Package: kmod-nls-iso8859-1
+Priority: optional
+Section: sys
+Description: Kernel module for iso8859-1 charset support
diff --git a/target/linux/control/kmod-nls-iso8859-15.control b/target/linux/control/kmod-nls-iso8859-15.control
new file mode 100644
index 0000000000..f565e379e9
--- /dev/null
+++ b/target/linux/control/kmod-nls-iso8859-15.control
@@ -0,0 +1,4 @@
+Package: kmod-nls-iso8859-15
+Priority: optional
+Section: sys
+Description: Kernel module for iso8859-15 charset support
diff --git a/target/linux/control/kmod-nls-utf8.control b/target/linux/control/kmod-nls-utf8.control
new file mode 100644
index 0000000000..8c5b23c37e
--- /dev/null
+++ b/target/linux/control/kmod-nls-utf8.control
@@ -0,0 +1,4 @@
+Package: kmod-nls-utf8
+Priority: optional
+Section: sys
+Description: Kernel module for utf8 support
diff --git a/target/linux/control/kmod-pcmcia-core.control b/target/linux/control/kmod-pcmcia-core.control
new file mode 100644
index 0000000000..3e137ea06d
--- /dev/null
+++ b/target/linux/control/kmod-pcmcia-core.control
@@ -0,0 +1,4 @@
+Package: kmod-pcmcia-core
+Priority: optional
+Section: sys
+Description: PCMCIA/CardBus kernel support
diff --git a/target/linux/control/kmod-pcmcia-serial.control b/target/linux/control/kmod-pcmcia-serial.control
new file mode 100644
index 0000000000..7e8a03c957
--- /dev/null
+++ b/target/linux/control/kmod-pcmcia-serial.control
@@ -0,0 +1,4 @@
+Package: kmod-pcmcia-serial
+Priority: optional
+Section: sys
+Description: PCMCIA/CardBus serial device support
diff --git a/target/linux/control/kmod-pwc.control b/target/linux/control/kmod-pwc.control
new file mode 100644
index 0000000000..2860eedf3d
--- /dev/null
+++ b/target/linux/control/kmod-pwc.control
@@ -0,0 +1,4 @@
+Package: kmod-pwc
+Priority: optional
+Section: sys
+Description: Kernel driver for USB Philips Cameras
diff --git a/target/linux/control/kmod-sangam-atm-annex-a.control b/target/linux/control/kmod-sangam-atm-annex-a.control
new file mode 100644
index 0000000000..e07e724565
--- /dev/null
+++ b/target/linux/control/kmod-sangam-atm-annex-a.control
@@ -0,0 +1,4 @@
+Package: kmod-sangam-atm-annex-a
+Priority: optional
+Section: sys
+Description: AR7 Sangam ATM/ADSL driver (Annex A version)
diff --git a/target/linux/control/kmod-sangam-atm-annex-b.control b/target/linux/control/kmod-sangam-atm-annex-b.control
new file mode 100644
index 0000000000..7e6ff3f63e
--- /dev/null
+++ b/target/linux/control/kmod-sangam-atm-annex-b.control
@@ -0,0 +1,4 @@
+Package: kmod-sangam-atm-annex-b
+Priority: optional
+Section: sys
+Description: AR7 Sangam ATM/ADSL driver (Annex B version)
diff --git a/target/linux/control/kmod-softdog.control b/target/linux/control/kmod-softdog.control
new file mode 100644
index 0000000000..01aff7fe8e
--- /dev/null
+++ b/target/linux/control/kmod-softdog.control
@@ -0,0 +1,4 @@
+Package: kmod-softdog
+Priority: optional
+Section: sys
+Description: Kernel software watchdog driver
diff --git a/target/linux/control/kmod-soundcore.control b/target/linux/control/kmod-soundcore.control
new file mode 100644
index 0000000000..6b4fffa058
--- /dev/null
+++ b/target/linux/control/kmod-soundcore.control
@@ -0,0 +1,4 @@
+Package: kmod-soundcore
+Priority: optional
+Section: sys
+Description: Kernel support for audio soundcards
diff --git a/target/linux/control/kmod-usb-acm.control b/target/linux/control/kmod-usb-acm.control
new file mode 100644
index 0000000000..8d1fca496b
--- /dev/null
+++ b/target/linux/control/kmod-usb-acm.control
@@ -0,0 +1,4 @@
+Package: kmod-usb-acm
+Priority: optional
+Section: sys
+Description: Kernel modules for USB modems and ISDN
diff --git a/target/linux/control/kmod-usb-atm-speedtouch.control b/target/linux/control/kmod-usb-atm-speedtouch.control
new file mode 100644
index 0000000000..e8ded69d48
--- /dev/null
+++ b/target/linux/control/kmod-usb-atm-speedtouch.control
@@ -0,0 +1,4 @@
+Package: kmod-usb-atm-speedtouch
+Priority: optional
+Section: sys
+Description: Kernel driver for USB Speedtouch ADSL modem
diff --git a/target/linux/control/kmod-usb-atm.control b/target/linux/control/kmod-usb-atm.control
new file mode 100644
index 0000000000..0f4adadd4a
--- /dev/null
+++ b/target/linux/control/kmod-usb-atm.control
@@ -0,0 +1,5 @@
+Package: kmod-usb-atm
+Priority: optional
+Section: sys
+Source: buildroot internal
+Description: Kernel modules for USB ATM support
diff --git a/target/linux/control/kmod-usb-audio.control b/target/linux/control/kmod-usb-audio.control
new file mode 100644
index 0000000000..d30b8f2c70
--- /dev/null
+++ b/target/linux/control/kmod-usb-audio.control
@@ -0,0 +1,5 @@
+Package: kmod-usb-audio
+Priority: optional
+Section: sys
+Depends: kmod-soundcore
+Description: Kernel Support for USB Soundcards
diff --git a/target/linux/control/kmod-usb-core.control b/target/linux/control/kmod-usb-core.control
new file mode 100644
index 0000000000..fa1c13bbd8
--- /dev/null
+++ b/target/linux/control/kmod-usb-core.control
@@ -0,0 +1,4 @@
+Package: kmod-usb-core
+Priority: optional
+Section: sys
+Description: Kernel Support for USB
diff --git a/target/linux/control/kmod-usb-ohci.control b/target/linux/control/kmod-usb-ohci.control
new file mode 100644
index 0000000000..3d0edc863c
--- /dev/null
+++ b/target/linux/control/kmod-usb-ohci.control
@@ -0,0 +1,4 @@
+Package: kmod-usb-ohci
+Priority: optional
+Section: sys
+Description: Kernel driver for OHCI USB controllers
diff --git a/target/linux/control/kmod-usb-printer.control b/target/linux/control/kmod-usb-printer.control
new file mode 100644
index 0000000000..1c47a3d176
--- /dev/null
+++ b/target/linux/control/kmod-usb-printer.control
@@ -0,0 +1,4 @@
+Package: kmod-usb-printer
+Priority: optional
+Section: sys
+Description: Kernel modules for USB Printer support
diff --git a/target/linux/control/kmod-usb-serial-belkin.control b/target/linux/control/kmod-usb-serial-belkin.control
new file mode 100644
index 0000000000..d907a9702b
--- /dev/null
+++ b/target/linux/control/kmod-usb-serial-belkin.control
@@ -0,0 +1,4 @@
+Package: kmod-usb-serial-belkin
+Priority: optional
+Section: sys
+Description: Kernel Support for Belkin USB-to-Serial converters
diff --git a/target/linux/control/kmod-usb-serial-ftdi.control b/target/linux/control/kmod-usb-serial-ftdi.control
new file mode 100644
index 0000000000..e845294a5f
--- /dev/null
+++ b/target/linux/control/kmod-usb-serial-ftdi.control
@@ -0,0 +1,4 @@
+Package: kmod-usb-serial-ftdi
+Priority: optional
+Section: sys
+Description: Kernel Support for FTDI USB-to-Serial converters
diff --git a/target/linux/control/kmod-usb-serial-mct-u232.control b/target/linux/control/kmod-usb-serial-mct-u232.control
new file mode 100644
index 0000000000..b52b7ca7b3
--- /dev/null
+++ b/target/linux/control/kmod-usb-serial-mct-u232.control
@@ -0,0 +1,4 @@
+Package: kmod-usb-serial-mct-u232
+Priority: optional
+Section: sys
+Description: Kernel Support for Magic Control Technology USB-to-Serial converters
diff --git a/target/linux/control/kmod-usb-serial-pl2303.control b/target/linux/control/kmod-usb-serial-pl2303.control
new file mode 100644
index 0000000000..4de43bd510
--- /dev/null
+++ b/target/linux/control/kmod-usb-serial-pl2303.control
@@ -0,0 +1,4 @@
+Package: kmod-usb-serial-pl2303
+Priority: optional
+Section: sys
+Description: Kernel Support for Prolific PL2303 USB-to-Serial converters
diff --git a/target/linux/control/kmod-usb-serial-visor.control b/target/linux/control/kmod-usb-serial-visor.control
new file mode 100644
index 0000000000..951c00c51f
--- /dev/null
+++ b/target/linux/control/kmod-usb-serial-visor.control
@@ -0,0 +1,4 @@
+Package: kmod-usb-serial-visor
+Priority: optional
+Section: sys
+Description: Kernel Support for Handspring Visor / Palm m50x / Sony Clie Driver
diff --git a/target/linux/control/kmod-usb-serial.control b/target/linux/control/kmod-usb-serial.control
new file mode 100644
index 0000000000..136fca752f
--- /dev/null
+++ b/target/linux/control/kmod-usb-serial.control
@@ -0,0 +1,4 @@
+Package: kmod-usb-serial
+Priority: optional
+Section: sys
+Description: Kernel Support for USB-to-Serial converters
diff --git a/target/linux/control/kmod-usb-storage.control b/target/linux/control/kmod-usb-storage.control
new file mode 100644
index 0000000000..4ee70eb8a9
--- /dev/null
+++ b/target/linux/control/kmod-usb-storage.control
@@ -0,0 +1,4 @@
+Package: kmod-usb-storage
+Priority: optional
+Section: sys
+Description: Kernel modules for USB storage support
diff --git a/target/linux/control/kmod-usb-uhci.control b/target/linux/control/kmod-usb-uhci.control
new file mode 100644
index 0000000000..09966a8a0e
--- /dev/null
+++ b/target/linux/control/kmod-usb-uhci.control
@@ -0,0 +1,4 @@
+Package: kmod-usb-uhci
+Priority: optional
+Section: sys
+Description: Kernel driver for UHCI USB controllers
diff --git a/target/linux/control/kmod-usb2.control b/target/linux/control/kmod-usb2.control
new file mode 100644
index 0000000000..338865e524
--- /dev/null
+++ b/target/linux/control/kmod-usb2.control
@@ -0,0 +1,4 @@
+Package: kmod-usb2
+Priority: optional
+Section: sys
+Description: Kernel driver for USB2 controllers
diff --git a/target/linux/control/kmod-videodev.control b/target/linux/control/kmod-videodev.control
new file mode 100644
index 0000000000..57c0b1cdfe
--- /dev/null
+++ b/target/linux/control/kmod-videodev.control
@@ -0,0 +1,4 @@
+Package: kmod-videodev
+Priority: optional
+Section: sys
+Description: Video For Linux kernel support
diff --git a/target/linux/control/kmod-wd1100.control b/target/linux/control/kmod-wd1100.control
new file mode 100644
index 0000000000..32163200ec
--- /dev/null
+++ b/target/linux/control/kmod-wd1100.control
@@ -0,0 +1,4 @@
+Package: kmod-wd1100
+Priority: optional
+Section: sys
+Description: NatSemi SC1x00 series Watchdog kernel support
diff --git a/target/linux/generic-2.4/README b/target/linux/generic-2.4/README
new file mode 100644
index 0000000000..15d95232d7
--- /dev/null
+++ b/target/linux/generic-2.4/README
@@ -0,0 +1,98 @@
+Description of kernel patches:
+
+
+generic/
+ Generic patches for vanilla Linux kernel
+
+000-linux_mips.patch
+ This is the diff between vanilla linux-2.4.32 and linux-mips.org kernel
+ (CVS tag 2_4_32-rc1 used). The kernel source from linux-mips.org CVS repository has
+ newer drivers and code then vanilla linux-2.4.32 especially for the mips architecture.
+
+001-squashfs.patch
+ Support for the squashfs filesystem. It has better compression ratio then cramfs.
+
+002-squashfs_lzma.patch
+ LZMA Addon patch from Oleg I. Vdovikin for the squashfs filesystem.
+ Even better compression ratio.
+
+003-jffs2_compression.patch
+ Compression for jffs2 filesystem.
+
+004-exec_pagesize.patch
+
+005-mtd_flashtypes.patch
+ Additional mtd drivers for flash chips
+
+100-ebtables.patch
+ Filtering packets on ethernet layer. See http://ebtables.sf.net
+
+101-netfilter_ipp2p.patch
+ Netfilter ipp2p match module (matches traffic of most P2P networks)
+
+102-netfilter_layer7.patch
+
+103-netfilter_nat_pptp.patch
+ NAT support for PPTP and GRE
+
+104-netfilter_maxconn.patch
+
+105-netfilter_TTL.patch
+ Netfilter target for manipulating the TTL of IP packets
+
+106-mppe_mppc.patch
+ Microsoft PPP Encryption/Compression
+
+107-cifs.patch
+ CIFS (Common Internet File System) module.
+
+108-optional_aout_support.patch
+
+109-ipsec_nat_traversal.patch
+ Openswan patch for allowing IPSec through NAT
+
+110-netdev_random_core.patch
+ Support for gathering entropy from network devices for /dev/random
+
+200-i4l.patch
+
+201-hfc_usb_backport.patch
+
+202-pl2303_backport.patch
+
+203-hfsplus_fix.patch
+
+204-net_b44.patch
+ Support for the BCM47xx chipset in the b44 driver
+
+206-gcc_3.4_fixes.patch
+ mips specific gcc 3.4 fixes
+
+207-gcc_4.0_fixes.patch
+ gcc 4.0 fixes
+
+
+brcm/
+ Broadcom specific patches
+
+001-bcm47xx.patch
+ This is the broadcom specific code from asus (1941) GPL source tarball.
+ There are many small patches included, so it works with linux 2.4.32 kernel.
+ The original code is based on Linux 2.4.20.
+
+002-wl_fix.patch
+ The driver for the wireless lan chip on brcm47xx based routers is binary only.
+ This means it depends on older data structures in the kernel. We backported some
+ of the changes or changed some of the data structures to work with the binary modul.
+ This is a really bad hack, but without source code, there is no better chance to get
+ the driver working with newer kernels.
+
+003-bcm47xx_cache_fixes.patch
+
+
+ar7/
+ TI AR7 specific patches
+
+000-ar7_support.patch
+
+001-flash_map.patch
diff --git a/target/linux/generic-2.4/patches/000-linux_mips.patch b/target/linux/generic-2.4/patches/000-linux_mips.patch
new file mode 100644
index 0000000000..16177c53b9
--- /dev/null
+++ b/target/linux/generic-2.4/patches/000-linux_mips.patch
@@ -0,0 +1,27959 @@
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/common/au1xxx_irqmap.c linux-2.4.32-rc1.mips/arch/mips/au1000/common/au1xxx_irqmap.c
+--- linux-2.4.32-rc1/arch/mips/au1000/common/au1xxx_irqmap.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/common/au1xxx_irqmap.c 2005-01-30 09:01:27.000000000 +0100
+@@ -172,14 +172,14 @@
+ { AU1550_PSC1_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1550_PSC2_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1550_PSC3_INT, INTC_INT_HIGH_LEVEL, 0},
+- { AU1550_TOY_INT, INTC_INT_RISE_EDGE, 0 },
+- { AU1550_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+- { AU1550_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+- { AU1550_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
+- { AU1550_RTC_INT, INTC_INT_RISE_EDGE, 0 },
+- { AU1550_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+- { AU1550_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+- { AU1550_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
++ { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
++ { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
++ { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
++ { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
++ { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
++ { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
++ { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
++ { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1550_NAND_INT, INTC_INT_RISE_EDGE, 0},
+ { AU1550_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
+ { AU1550_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
+@@ -200,14 +200,14 @@
+ { AU1200_PSC1_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1200_AES_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1200_CAMERA_INT, INTC_INT_HIGH_LEVEL, 0},
+- { AU1200_TOY_INT, INTC_INT_RISE_EDGE, 0 },
+- { AU1200_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+- { AU1200_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+- { AU1200_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
+- { AU1200_RTC_INT, INTC_INT_RISE_EDGE, 0 },
+- { AU1200_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+- { AU1200_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+- { AU1200_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
++ { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
++ { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
++ { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
++ { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
++ { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
++ { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
++ { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
++ { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1200_NAND_INT, INTC_INT_RISE_EDGE, 0},
+ { AU1200_USB_INT, INTC_INT_HIGH_LEVEL, 0 },
+ { AU1200_LCD_INT, INTC_INT_HIGH_LEVEL, 0},
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/common/cputable.c linux-2.4.32-rc1.mips/arch/mips/au1000/common/cputable.c
+--- linux-2.4.32-rc1/arch/mips/au1000/common/cputable.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/common/cputable.c 2005-01-30 09:01:27.000000000 +0100
+@@ -39,7 +39,8 @@
+ { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1 },
+ { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 },
+ { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 },
+- { 0xffffffff, 0x04030200, "Au1200 AA", 0, 1 },
++ { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0 },
++ { 0xffffffff, 0x04030201, "Au1200 AC", 0, 0 },
+ { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 },
+ };
+
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/common/dbdma.c linux-2.4.32-rc1.mips/arch/mips/au1000/common/dbdma.c
+--- linux-2.4.32-rc1/arch/mips/au1000/common/dbdma.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/common/dbdma.c 2005-02-08 07:28:37.000000000 +0100
+@@ -41,6 +41,8 @@
+ #include <asm/au1xxx_dbdma.h>
+ #include <asm/system.h>
+
++#include <linux/module.h>
++
+ #if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
+
+ /*
+@@ -60,37 +62,10 @@
+ */
+ #define ALIGN_ADDR(x, a) ((((u32)(x)) + (a-1)) & ~(a-1))
+
+-static volatile dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE;
+-static int dbdma_initialized;
++static dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE;
++static int dbdma_initialized=0;
+ static void au1xxx_dbdma_init(void);
+
+-typedef struct dbdma_device_table {
+- u32 dev_id;
+- u32 dev_flags;
+- u32 dev_tsize;
+- u32 dev_devwidth;
+- u32 dev_physaddr; /* If FIFO */
+- u32 dev_intlevel;
+- u32 dev_intpolarity;
+-} dbdev_tab_t;
+-
+-typedef struct dbdma_chan_config {
+- u32 chan_flags;
+- u32 chan_index;
+- dbdev_tab_t *chan_src;
+- dbdev_tab_t *chan_dest;
+- au1x_dma_chan_t *chan_ptr;
+- au1x_ddma_desc_t *chan_desc_base;
+- au1x_ddma_desc_t *get_ptr, *put_ptr, *cur_ptr;
+- void *chan_callparam;
+- void (*chan_callback)(int, void *, struct pt_regs *);
+-} chan_tab_t;
+-
+-#define DEV_FLAGS_INUSE (1 << 0)
+-#define DEV_FLAGS_ANYUSE (1 << 1)
+-#define DEV_FLAGS_OUT (1 << 2)
+-#define DEV_FLAGS_IN (1 << 3)
+-
+ static dbdev_tab_t dbdev_tab[] = {
+ #ifdef CONFIG_SOC_AU1550
+ /* UARTS */
+@@ -156,13 +131,13 @@
+ { DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+
+- { DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
+- { DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+- { DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
+- { DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
++ { DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 4, 8, 0x10600000, 0, 0 },
++ { DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 4, 8, 0x10600004, 0, 0 },
++ { DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 4, 8, 0x10680000, 0, 0 },
++ { DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 4, 8, 0x10680004, 0, 0 },
+
+- { DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
+- { DSCR_CMD0_AES_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
++ { DSCR_CMD0_AES_RX, DEV_FLAGS_IN , 4, 32, 0x10300008, 0, 0 },
++ { DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 4, 32, 0x10300004, 0, 0 },
+
+ { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 },
+ { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 },
+@@ -172,9 +147,9 @@
+ { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 },
+ { DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+
+- { DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+- { DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+- { DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
++ { DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 32, 0x14004020, 0, 0 },
++ { DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 32, 0x14004040, 0, 0 },
++ { DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 32, 0x14004060, 0, 0 },
+ { DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+
+ { DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+@@ -183,6 +158,24 @@
+
+ { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
++
++ /* Provide 16 user definable device types */
++ { 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 },
++ { 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 },
+ };
+
+ #define DBDEV_TAB_SIZE (sizeof(dbdev_tab) / sizeof(dbdev_tab_t))
+@@ -202,6 +195,30 @@
+ return NULL;
+ }
+
++u32
++au1xxx_ddma_add_device(dbdev_tab_t *dev)
++{
++ u32 ret = 0;
++ dbdev_tab_t *p=NULL;
++ static u16 new_id=0x1000;
++
++ p = find_dbdev_id(0);
++ if ( NULL != p )
++ {
++ memcpy(p, dev, sizeof(dbdev_tab_t));
++ p->dev_id = DSCR_DEV2CUSTOM_ID(new_id,dev->dev_id);
++ ret = p->dev_id;
++ new_id++;
++#if 0
++ printk("add_device: id:%x flags:%x padd:%x\n",
++ p->dev_id, p->dev_flags, p->dev_physaddr );
++#endif
++ }
++
++ return ret;
++}
++EXPORT_SYMBOL(au1xxx_ddma_add_device);
++
+ /* Allocate a channel and return a non-zero descriptor if successful.
+ */
+ u32
+@@ -214,7 +231,7 @@
+ int i;
+ dbdev_tab_t *stp, *dtp;
+ chan_tab_t *ctp;
+- volatile au1x_dma_chan_t *cp;
++ au1x_dma_chan_t *cp;
+
+ /* We do the intialization on the first channel allocation.
+ * We have to wait because of the interrupt handler initialization
+@@ -224,9 +241,6 @@
+ au1xxx_dbdma_init();
+ dbdma_initialized = 1;
+
+- if ((srcid > DSCR_NDEV_IDS) || (destid > DSCR_NDEV_IDS))
+- return 0;
+-
+ if ((stp = find_dbdev_id(srcid)) == NULL) return 0;
+ if ((dtp = find_dbdev_id(destid)) == NULL) return 0;
+
+@@ -268,9 +282,9 @@
+ /* If kmalloc fails, it is caught below same
+ * as a channel not available.
+ */
+- ctp = (chan_tab_t *)kmalloc(sizeof(chan_tab_t), GFP_KERNEL);
++ ctp = (chan_tab_t *)
++ kmalloc(sizeof(chan_tab_t), GFP_KERNEL);
+ chan_tab_ptr[i] = ctp;
+- ctp->chan_index = chan = i;
+ break;
+ }
+ }
+@@ -278,10 +292,11 @@
+
+ if (ctp != NULL) {
+ memset(ctp, 0, sizeof(chan_tab_t));
++ ctp->chan_index = chan = i;
+ dcp = DDMA_CHANNEL_BASE;
+ dcp += (0x0100 * chan);
+ ctp->chan_ptr = (au1x_dma_chan_t *)dcp;
+- cp = (volatile au1x_dma_chan_t *)dcp;
++ cp = (au1x_dma_chan_t *)dcp;
+ ctp->chan_src = stp;
+ ctp->chan_dest = dtp;
+ ctp->chan_callback = callback;
+@@ -298,6 +313,9 @@
+ i |= DDMA_CFG_DED;
+ if (dtp->dev_intpolarity)
+ i |= DDMA_CFG_DP;
++ if ((stp->dev_flags & DEV_FLAGS_SYNC) ||
++ (dtp->dev_flags & DEV_FLAGS_SYNC))
++ i |= DDMA_CFG_SYNC;
+ cp->ddma_cfg = i;
+ au_sync();
+
+@@ -308,14 +326,14 @@
+ rv = (u32)(&chan_tab_ptr[chan]);
+ }
+ else {
+- /* Release devices.
+- */
++ /* Release devices */
+ stp->dev_flags &= ~DEV_FLAGS_INUSE;
+ dtp->dev_flags &= ~DEV_FLAGS_INUSE;
+ }
+ }
+ return rv;
+ }
++EXPORT_SYMBOL(au1xxx_dbdma_chan_alloc);
+
+ /* Set the device width if source or destination is a FIFO.
+ * Should be 8, 16, or 32 bits.
+@@ -343,6 +361,7 @@
+
+ return rv;
+ }
++EXPORT_SYMBOL(au1xxx_dbdma_set_devwidth);
+
+ /* Allocate a descriptor ring, initializing as much as possible.
+ */
+@@ -369,7 +388,8 @@
+ * and if we try that first we are likely to not waste larger
+ * slabs of memory.
+ */
+- desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t), GFP_KERNEL);
++ desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t),
++ GFP_KERNEL|GFP_DMA);
+ if (desc_base == 0)
+ return 0;
+
+@@ -380,7 +400,7 @@
+ kfree((const void *)desc_base);
+ i = entries * sizeof(au1x_ddma_desc_t);
+ i += (sizeof(au1x_ddma_desc_t) - 1);
+- if ((desc_base = (u32)kmalloc(i, GFP_KERNEL)) == 0)
++ if ((desc_base = (u32)kmalloc(i, GFP_KERNEL|GFP_DMA)) == 0)
+ return 0;
+
+ desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t));
+@@ -460,9 +480,14 @@
+ /* If source input is fifo, set static address.
+ */
+ if (stp->dev_flags & DEV_FLAGS_IN) {
+- src0 = stp->dev_physaddr;
+- src1 |= DSCR_SRC1_SAM(DSCR_xAM_STATIC);
++ if ( stp->dev_flags & DEV_FLAGS_BURSTABLE )
++ src1 |= DSCR_SRC1_SAM(DSCR_xAM_BURST);
++ else
++ src1 |= DSCR_SRC1_SAM(DSCR_xAM_STATIC);
++
+ }
++ if (stp->dev_physaddr)
++ src0 = stp->dev_physaddr;
+
+ /* Set up dest1. For now, assume no stride and increment.
+ * A channel attribute update can change this later.
+@@ -486,10 +511,18 @@
+ /* If destination output is fifo, set static address.
+ */
+ if (dtp->dev_flags & DEV_FLAGS_OUT) {
+- dest0 = dtp->dev_physaddr;
++ if ( dtp->dev_flags & DEV_FLAGS_BURSTABLE )
++ dest1 |= DSCR_DEST1_DAM(DSCR_xAM_BURST);
++ else
+ dest1 |= DSCR_DEST1_DAM(DSCR_xAM_STATIC);
+ }
++ if (dtp->dev_physaddr)
++ dest0 = dtp->dev_physaddr;
+
++#if 0
++ printk("did:%x sid:%x cmd0:%x cmd1:%x source0:%x source1:%x dest0:%x dest1:%x\n",
++ dtp->dev_id, stp->dev_id, cmd0, cmd1, src0, src1, dest0, dest1 );
++#endif
+ for (i=0; i<entries; i++) {
+ dp->dscr_cmd0 = cmd0;
+ dp->dscr_cmd1 = cmd1;
+@@ -498,6 +531,7 @@
+ dp->dscr_dest0 = dest0;
+ dp->dscr_dest1 = dest1;
+ dp->dscr_stat = 0;
++ dp->sw_context = dp->sw_status = 0;
+ dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(dp + 1));
+ dp++;
+ }
+@@ -510,13 +544,14 @@
+
+ return (u32)(ctp->chan_desc_base);
+ }
++EXPORT_SYMBOL(au1xxx_dbdma_ring_alloc);
+
+ /* Put a source buffer into the DMA ring.
+ * This updates the source pointer and byte count. Normally used
+ * for memory to fifo transfers.
+ */
+ u32
+-au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes)
++_au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes, u32 flags)
+ {
+ chan_tab_t *ctp;
+ au1x_ddma_desc_t *dp;
+@@ -543,24 +578,40 @@
+ */
+ dp->dscr_source0 = virt_to_phys(buf);
+ dp->dscr_cmd1 = nbytes;
+- dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */
+- ctp->chan_ptr->ddma_dbell = 0xffffffff; /* Make it go */
+-
++ /* Check flags */
++ if (flags & DDMA_FLAGS_IE)
++ dp->dscr_cmd0 |= DSCR_CMD0_IE;
++ if (flags & DDMA_FLAGS_NOIE)
++ dp->dscr_cmd0 &= ~DSCR_CMD0_IE;
+ /* Get next descriptor pointer.
+ */
+ ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
+
++ /*
++ * There is an errata on the Au1200/Au1550 parts that could result
++ * in "stale" data being DMA'd. It has to do with the snoop logic on
++ * the dache eviction buffer. NONCOHERENT_IO is on by default for
++ * these parts. If it is fixedin the future, these dma_cache_inv will
++ * just be nothing more than empty macros. See io.h.
++ * */
++ dma_cache_wback_inv(buf,nbytes);
++ dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */
++ au_sync();
++ dma_cache_wback_inv(dp, sizeof(dp));
++ ctp->chan_ptr->ddma_dbell = 0;
++
+ /* return something not zero.
+ */
+ return nbytes;
+ }
++EXPORT_SYMBOL(_au1xxx_dbdma_put_source);
+
+ /* Put a destination buffer into the DMA ring.
+ * This updates the destination pointer and byte count. Normally used
+ * to place an empty buffer into the ring for fifo to memory transfers.
+ */
+ u32
+-au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes)
++_au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes, u32 flags)
+ {
+ chan_tab_t *ctp;
+ au1x_ddma_desc_t *dp;
+@@ -582,11 +633,33 @@
+ if (dp->dscr_cmd0 & DSCR_CMD0_V)
+ return 0;
+
+- /* Load up buffer address and byte count.
+- */
++ /* Load up buffer address and byte count */
++
++ /* Check flags */
++ if (flags & DDMA_FLAGS_IE)
++ dp->dscr_cmd0 |= DSCR_CMD0_IE;
++ if (flags & DDMA_FLAGS_NOIE)
++ dp->dscr_cmd0 &= ~DSCR_CMD0_IE;
++
+ dp->dscr_dest0 = virt_to_phys(buf);
+ dp->dscr_cmd1 = nbytes;
++#if 0
++ printk("cmd0:%x cmd1:%x source0:%x source1:%x dest0:%x dest1:%x\n",
++ dp->dscr_cmd0, dp->dscr_cmd1, dp->dscr_source0,
++ dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1 );
++#endif
++ /*
++ * There is an errata on the Au1200/Au1550 parts that could result in
++ * "stale" data being DMA'd. It has to do with the snoop logic on the
++ * dache eviction buffer. NONCOHERENT_IO is on by default for these
++ * parts. If it is fixedin the future, these dma_cache_inv will just
++ * be nothing more than empty macros. See io.h.
++ * */
++ dma_cache_inv(buf,nbytes);
+ dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */
++ au_sync();
++ dma_cache_wback_inv(dp, sizeof(dp));
++ ctp->chan_ptr->ddma_dbell = 0;
+
+ /* Get next descriptor pointer.
+ */
+@@ -596,6 +669,7 @@
+ */
+ return nbytes;
+ }
++EXPORT_SYMBOL(_au1xxx_dbdma_put_dest);
+
+ /* Get a destination buffer into the DMA ring.
+ * Normally used to get a full buffer from the ring during fifo
+@@ -645,7 +719,7 @@
+ au1xxx_dbdma_stop(u32 chanid)
+ {
+ chan_tab_t *ctp;
+- volatile au1x_dma_chan_t *cp;
++ au1x_dma_chan_t *cp;
+ int halt_timeout = 0;
+
+ ctp = *((chan_tab_t **)chanid);
+@@ -665,6 +739,7 @@
+ cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V);
+ au_sync();
+ }
++EXPORT_SYMBOL(au1xxx_dbdma_stop);
+
+ /* Start using the current descriptor pointer. If the dbdma encounters
+ * a not valid descriptor, it will stop. In this case, we can just
+@@ -674,17 +749,17 @@
+ au1xxx_dbdma_start(u32 chanid)
+ {
+ chan_tab_t *ctp;
+- volatile au1x_dma_chan_t *cp;
++ au1x_dma_chan_t *cp;
+
+ ctp = *((chan_tab_t **)chanid);
+-
+ cp = ctp->chan_ptr;
+ cp->ddma_desptr = virt_to_phys(ctp->cur_ptr);
+ cp->ddma_cfg |= DDMA_CFG_EN; /* Enable channel */
+ au_sync();
+- cp->ddma_dbell = 0xffffffff; /* Make it go */
++ cp->ddma_dbell = 0;
+ au_sync();
+ }
++EXPORT_SYMBOL(au1xxx_dbdma_start);
+
+ void
+ au1xxx_dbdma_reset(u32 chanid)
+@@ -703,15 +778,21 @@
+
+ do {
+ dp->dscr_cmd0 &= ~DSCR_CMD0_V;
++ /* reset our SW status -- this is used to determine
++ * if a descriptor is in use by upper level SW. Since
++ * posting can reset 'V' bit.
++ */
++ dp->sw_status = 0;
+ dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
+ } while (dp != ctp->chan_desc_base);
+ }
++EXPORT_SYMBOL(au1xxx_dbdma_reset);
+
+ u32
+ au1xxx_get_dma_residue(u32 chanid)
+ {
+ chan_tab_t *ctp;
+- volatile au1x_dma_chan_t *cp;
++ au1x_dma_chan_t *cp;
+ u32 rv;
+
+ ctp = *((chan_tab_t **)chanid);
+@@ -746,15 +827,16 @@
+
+ kfree(ctp);
+ }
++EXPORT_SYMBOL(au1xxx_dbdma_chan_free);
+
+ static void
+ dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+ {
+- u32 intstat;
++ u32 intstat, flags;
+ u32 chan_index;
+ chan_tab_t *ctp;
+ au1x_ddma_desc_t *dp;
+- volatile au1x_dma_chan_t *cp;
++ au1x_dma_chan_t *cp;
+
+ intstat = dbdma_gptr->ddma_intstat;
+ au_sync();
+@@ -773,18 +855,26 @@
+ (ctp->chan_callback)(irq, ctp->chan_callparam, regs);
+
+ ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
+-
+ }
+
+-static void
+-au1xxx_dbdma_init(void)
++static void au1xxx_dbdma_init(void)
+ {
++ int irq_nr;
++
+ dbdma_gptr->ddma_config = 0;
+ dbdma_gptr->ddma_throttle = 0;
+ dbdma_gptr->ddma_inten = 0xffff;
+ au_sync();
+
+- if (request_irq(AU1550_DDMA_INT, dbdma_interrupt, SA_INTERRUPT,
++#if defined(CONFIG_SOC_AU1550)
++ irq_nr = AU1550_DDMA_INT;
++#elif defined(CONFIG_SOC_AU1200)
++ irq_nr = AU1200_DDMA_INT;
++#else
++ #error Unknown Au1x00 SOC
++#endif
++
++ if (request_irq(irq_nr, dbdma_interrupt, SA_INTERRUPT,
+ "Au1xxx dbdma", (void *)dbdma_gptr))
+ printk("Can't get 1550 dbdma irq");
+ }
+@@ -795,7 +885,8 @@
+ chan_tab_t *ctp;
+ au1x_ddma_desc_t *dp;
+ dbdev_tab_t *stp, *dtp;
+- volatile au1x_dma_chan_t *cp;
++ au1x_dma_chan_t *cp;
++ u32 i = 0;
+
+ ctp = *((chan_tab_t **)chanid);
+ stp = ctp->chan_src;
+@@ -820,15 +911,64 @@
+ dp = ctp->chan_desc_base;
+
+ do {
+- printk("dp %08x, cmd0 %08x, cmd1 %08x\n",
+- (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1);
+- printk("src0 %08x, src1 %08x, dest0 %08x\n",
+- dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0);
+- printk("dest1 %08x, stat %08x, nxtptr %08x\n",
+- dp->dscr_dest1, dp->dscr_stat, dp->dscr_nxtptr);
++ printk("Dp[%d]= %08x, cmd0 %08x, cmd1 %08x\n",
++ i++, (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1);
++ printk("src0 %08x, src1 %08x, dest0 %08x, dest1 %08x\n",
++ dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1);
++ printk("stat %08x, nxtptr %08x\n",
++ dp->dscr_stat, dp->dscr_nxtptr);
+ dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
+ } while (dp != ctp->chan_desc_base);
+ }
+
++/* Put a descriptor into the DMA ring.
++ * This updates the source/destination pointers and byte count.
++ */
++u32
++au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr )
++{
++ chan_tab_t *ctp;
++ au1x_ddma_desc_t *dp;
++ u32 nbytes=0;
++
++ /* I guess we could check this to be within the
++ * range of the table......
++ */
++ ctp = *((chan_tab_t **)chanid);
++
++ /* We should have multiple callers for a particular channel,
++ * an interrupt doesn't affect this pointer nor the descriptor,
++ * so no locking should be needed.
++ */
++ dp = ctp->put_ptr;
++
++ /* If the descriptor is valid, we are way ahead of the DMA
++ * engine, so just return an error condition.
++ */
++ if (dp->dscr_cmd0 & DSCR_CMD0_V)
++ return 0;
++
++ /* Load up buffer addresses and byte count.
++ */
++ dp->dscr_dest0 = dscr->dscr_dest0;
++ dp->dscr_source0 = dscr->dscr_source0;
++ dp->dscr_dest1 = dscr->dscr_dest1;
++ dp->dscr_source1 = dscr->dscr_source1;
++ dp->dscr_cmd1 = dscr->dscr_cmd1;
++ nbytes = dscr->dscr_cmd1;
++ /* Allow the caller to specifiy if an interrupt is generated */
++ dp->dscr_cmd0 &= ~DSCR_CMD0_IE;
++ dp->dscr_cmd0 |= dscr->dscr_cmd0 | DSCR_CMD0_V;
++ ctp->chan_ptr->ddma_dbell = 0;
++
++ /* Get next descriptor pointer.
++ */
++ ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
++
++ /* return something not zero.
++ */
++ return nbytes;
++}
++
+ #endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */
+
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/common/gpio.c linux-2.4.32-rc1.mips/arch/mips/au1000/common/gpio.c
+--- linux-2.4.32-rc1/arch/mips/au1000/common/gpio.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/common/gpio.c 2005-01-30 09:01:27.000000000 +0100
+@@ -0,0 +1,118 @@
++/*
++ * 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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <asm/au1000.h>
++#include <asm/au1xxx_gpio.h>
++
++#define gpio1 sys
++#if !defined(CONFIG_SOC_AU1000)
++static AU1X00_GPIO2 * const gpio2 = (AU1X00_GPIO2 *)GPIO2_BASE;
++
++#define GPIO2_OUTPUT_ENABLE_MASK 0x00010000
++
++int au1xxx_gpio2_read(int signal)
++{
++ signal -= 200;
++/* gpio2->dir &= ~(0x01 << signal); //Set GPIO to input */
++ return ((gpio2->pinstate >> signal) & 0x01);
++}
++
++void au1xxx_gpio2_write(int signal, int value)
++{
++ signal -= 200;
++
++ gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << signal) |
++ (value << signal);
++}
++
++void au1xxx_gpio2_tristate(int signal)
++{
++ signal -= 200;
++ gpio2->dir &= ~(0x01 << signal); /* Set GPIO to input */
++}
++#endif
++
++int au1xxx_gpio1_read(int signal)
++{
++/* gpio1->trioutclr |= (0x01 << signal); */
++ return ((gpio1->pinstaterd >> signal) & 0x01);
++}
++
++void au1xxx_gpio1_write(int signal, int value)
++{
++ if(value)
++ gpio1->outputset = (0x01 << signal);
++ else
++ gpio1->outputclr = (0x01 << signal); /* Output a Zero */
++}
++
++void au1xxx_gpio1_tristate(int signal)
++{
++ gpio1->trioutclr = (0x01 << signal); /* Tristate signal */
++}
++
++
++int au1xxx_gpio_read(int signal)
++{
++ if(signal >= 200)
++#if defined(CONFIG_SOC_AU1000)
++ return 0;
++#else
++ return au1xxx_gpio2_read(signal);
++#endif
++ else
++ return au1xxx_gpio1_read(signal);
++}
++
++void au1xxx_gpio_write(int signal, int value)
++{
++ if(signal >= 200)
++#if defined(CONFIG_SOC_AU1000)
++ ;
++#else
++ au1xxx_gpio2_write(signal, value);
++#endif
++ else
++ au1xxx_gpio1_write(signal, value);
++}
++
++void au1xxx_gpio_tristate(int signal)
++{
++ if(signal >= 200)
++#if defined(CONFIG_SOC_AU1000)
++ ;
++#else
++ au1xxx_gpio2_tristate(signal);
++#endif
++ else
++ au1xxx_gpio1_tristate(signal);
++}
++
++void au1xxx_gpio1_set_inputs(void)
++{
++ gpio1->pininputen = 0;
++}
++
++EXPORT_SYMBOL(au1xxx_gpio1_set_inputs);
++EXPORT_SYMBOL(au1xxx_gpio_tristate);
++EXPORT_SYMBOL(au1xxx_gpio_write);
++EXPORT_SYMBOL(au1xxx_gpio_read);
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/common/irq.c linux-2.4.32-rc1.mips/arch/mips/au1000/common/irq.c
+--- linux-2.4.32-rc1/arch/mips/au1000/common/irq.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/common/irq.c 2005-03-13 08:56:57.000000000 +0100
+@@ -303,8 +303,30 @@
+ };
+
+ #ifdef CONFIG_PM
+-void startup_match20_interrupt(void)
++void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *))
+ {
++ static struct irqaction action;
++ /* This is a big problem.... since we didn't use request_irq
++ when kernel/irq.c calls probe_irq_xxx this interrupt will
++ be probed for usage. This will end up disabling the device :(
++
++ Give it a bogus "action" pointer -- this will keep it from
++ getting auto-probed!
++
++ By setting the status to match that of request_irq() we
++ can avoid it. --cgray
++ */
++ action.dev_id = handler;
++ action.flags = 0;
++ action.mask = 0;
++ action.name = "Au1xxx TOY";
++ action.handler = handler;
++ action.next = NULL;
++
++ irq_desc[AU1000_TOY_MATCH2_INT].action = &action;
++ irq_desc[AU1000_TOY_MATCH2_INT].status
++ &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
++
+ local_enable_irq(AU1000_TOY_MATCH2_INT);
+ }
+ #endif
+@@ -508,6 +530,7 @@
+
+ if (!intc0_req0) return;
+
++#ifdef AU1000_USB_DEV_REQ_INT
+ /*
+ * Because of the tight timing of SETUP token to reply
+ * transactions, the USB devices-side packet complete
+@@ -518,6 +541,7 @@
+ do_IRQ(AU1000_USB_DEV_REQ_INT, regs);
+ return;
+ }
++#endif
+
+ irq = au_ffs(intc0_req0) - 1;
+ intc0_req0 &= ~(1<<irq);
+@@ -536,17 +560,7 @@
+
+ irq = au_ffs(intc0_req1) - 1;
+ intc0_req1 &= ~(1<<irq);
+-#ifdef CONFIG_PM
+- if (irq == AU1000_TOY_MATCH2_INT) {
+- mask_and_ack_rise_edge_irq(irq);
+- counter0_irq(irq, NULL, regs);
+- local_enable_irq(irq);
+- }
+- else
+-#endif
+- {
+- do_IRQ(irq, regs);
+- }
++ do_IRQ(irq, regs);
+ }
+
+
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/common/Makefile linux-2.4.32-rc1.mips/arch/mips/au1000/common/Makefile
+--- linux-2.4.32-rc1/arch/mips/au1000/common/Makefile 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/common/Makefile 2005-01-30 09:01:27.000000000 +0100
+@@ -19,9 +19,9 @@
+ export-objs = prom.o clocks.o power.o usbdev.o
+
+ obj-y := prom.o int-handler.o irq.o puts.o time.o reset.o cputable.o \
+- au1xxx_irqmap.o clocks.o power.o setup.o sleeper.o dma.o dbdma.o
++ au1xxx_irqmap.o clocks.o power.o setup.o sleeper.o dma.o dbdma.o gpio.o
+
+-export-objs += dma.o dbdma.o
++export-objs += dma.o dbdma.o gpio.o
+
+ obj-$(CONFIG_AU1X00_USB_DEVICE) += usbdev.o
+ obj-$(CONFIG_KGDB) += dbg_io.o
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/common/pci_fixup.c linux-2.4.32-rc1.mips/arch/mips/au1000/common/pci_fixup.c
+--- linux-2.4.32-rc1/arch/mips/au1000/common/pci_fixup.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/common/pci_fixup.c 2004-12-03 09:00:32.000000000 +0100
+@@ -75,9 +75,13 @@
+
+ #ifdef CONFIG_NONCOHERENT_IO
+ /*
+- * Set the NC bit in controller for pre-AC silicon
++ * Set the NC bit in controller for Au1500 pre-AC silicon
+ */
+- au_writel( 1<<16 | au_readl(Au1500_PCI_CFG), Au1500_PCI_CFG);
++ u32 prid = read_c0_prid();
++ if ( (prid & 0xFF000000) == 0x01000000 && prid < 0x01030202) {
++ au_writel( 1<<16 | au_readl(Au1500_PCI_CFG), Au1500_PCI_CFG);
++ printk("Non-coherent PCI accesses enabled\n");
++ }
+ printk("Non-coherent PCI accesses enabled\n");
+ #endif
+
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/common/pci_ops.c linux-2.4.32-rc1.mips/arch/mips/au1000/common/pci_ops.c
+--- linux-2.4.32-rc1/arch/mips/au1000/common/pci_ops.c 2004-02-18 14:36:30.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/common/pci_ops.c 2005-02-27 23:14:24.000000000 +0100
+@@ -162,6 +162,7 @@
+ static int config_access(unsigned char access_type, struct pci_dev *dev,
+ unsigned char where, u32 * data)
+ {
++ int error = PCIBIOS_SUCCESSFUL;
+ #if defined( CONFIG_SOC_AU1500 ) || defined( CONFIG_SOC_AU1550 )
+ unsigned char bus = dev->bus->number;
+ unsigned int dev_fn = dev->devfn;
+@@ -170,7 +171,6 @@
+ unsigned long offset, status;
+ unsigned long cfg_base;
+ unsigned long flags;
+- int error = PCIBIOS_SUCCESSFUL;
+ unsigned long entryLo0, entryLo1;
+
+ if (device > 19) {
+@@ -205,9 +205,8 @@
+ last_entryLo0 = last_entryLo1 = 0xffffffff;
+ }
+
+- /* Since the Au1xxx doesn't do the idsel timing exactly to spec,
+- * many board vendors implement their own off-chip idsel, so call
+- * it now. If it doesn't succeed, may as well bail out at this point.
++ /* Allow board vendors to implement their own off-chip idsel.
++ * If it doesn't succeed, may as well bail out at this point.
+ */
+ if (board_pci_idsel) {
+ if (board_pci_idsel(device, 1) == 0) {
+@@ -271,8 +270,11 @@
+ }
+
+ local_irq_restore(flags);
+- return error;
++#else
++ /* Fake out Config space access with no responder */
++ *data = 0xFFFFFFFF;
+ #endif
++ return error;
+ }
+ #endif
+
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/common/power.c linux-2.4.32-rc1.mips/arch/mips/au1000/common/power.c
+--- linux-2.4.32-rc1/arch/mips/au1000/common/power.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/common/power.c 2005-04-07 02:37:19.000000000 +0200
+@@ -50,7 +50,6 @@
+
+ static void calibrate_delay(void);
+
+-extern void set_au1x00_speed(unsigned int new_freq);
+ extern unsigned int get_au1x00_speed(void);
+ extern unsigned long get_au1x00_uart_baud_base(void);
+ extern void set_au1x00_uart_baud_base(unsigned long new_baud_base);
+@@ -116,6 +115,7 @@
+ sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK);
+ sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL);
+
++#ifndef CONFIG_SOC_AU1200
+ /* Shutdown USB host/device.
+ */
+ sleep_usbhost_enable = au_readl(USB_HOST_CONFIG);
+@@ -127,6 +127,7 @@
+
+ sleep_usbdev_enable = au_readl(USBD_ENABLE);
+ au_writel(0, USBD_ENABLE); au_sync();
++#endif
+
+ /* Save interrupt controller state.
+ */
+@@ -212,14 +213,12 @@
+ int au_sleep(void)
+ {
+ unsigned long wakeup, flags;
+- extern void save_and_sleep(void);
++ extern unsigned int save_and_sleep(void);
+
+ spin_lock_irqsave(&pm_lock,flags);
+
+ save_core_regs();
+
+- flush_cache_all();
+-
+ /** The code below is all system dependent and we should probably
+ ** have a function call out of here to set this up. You need
+ ** to configure the GPIO or timer interrupts that will bring
+@@ -227,27 +226,26 @@
+ ** For testing, the TOY counter wakeup is useful.
+ **/
+
+-#if 0
++#if 1
+ au_writel(au_readl(SYS_PINSTATERD) & ~(1 << 11), SYS_PINSTATERD);
+
+ /* gpio 6 can cause a wake up event */
+ wakeup = au_readl(SYS_WAKEMSK);
+ wakeup &= ~(1 << 8); /* turn off match20 wakeup */
+- wakeup |= 1 << 6; /* turn on gpio 6 wakeup */
++ wakeup = 1 << 5; /* turn on gpio 6 wakeup */
+ #else
+- /* For testing, allow match20 to wake us up.
+- */
++ /* For testing, allow match20 to wake us up. */
+ #ifdef SLEEP_TEST_TIMEOUT
+ wakeup_counter0_set(sleep_ticks);
+ #endif
+ wakeup = 1 << 8; /* turn on match20 wakeup */
+ wakeup = 0;
+ #endif
+- au_writel(1, SYS_WAKESRC); /* clear cause */
++ au_writel(0, SYS_WAKESRC); /* clear cause */
+ au_sync();
+ au_writel(wakeup, SYS_WAKEMSK);
+ au_sync();
+-
++ DPRINTK("Entering sleep!\n");
+ save_and_sleep();
+
+ /* after a wakeup, the cpu vectors back to 0x1fc00000 so
+@@ -255,6 +253,7 @@
+ */
+ restore_core_regs();
+ spin_unlock_irqrestore(&pm_lock, flags);
++ DPRINTK("Leaving sleep!\n");
+ return 0;
+ }
+
+@@ -285,7 +284,6 @@
+
+ if (retval)
+ return retval;
+-
+ au_sleep();
+ retval = pm_send_all(PM_RESUME, (void *) 0);
+ }
+@@ -296,7 +294,6 @@
+ void *buffer, size_t * len)
+ {
+ int retval = 0;
+- void au1k_wait(void);
+
+ if (!write) {
+ *len = 0;
+@@ -305,119 +302,9 @@
+ if (retval)
+ return retval;
+ suspend_mode = 1;
+- au1k_wait();
+- retval = pm_send_all(PM_RESUME, (void *) 0);
+- }
+- return retval;
+-}
+
+-
+-static int pm_do_freq(ctl_table * ctl, int write, struct file *file,
+- void *buffer, size_t * len)
+-{
+- int retval = 0, i;
+- unsigned long val, pll;
+-#define TMPBUFLEN 64
+-#define MAX_CPU_FREQ 396
+- char buf[TMPBUFLEN], *p;
+- unsigned long flags, intc0_mask, intc1_mask;
+- unsigned long old_baud_base, old_cpu_freq, baud_rate, old_clk,
+- old_refresh;
+- unsigned long new_baud_base, new_cpu_freq, new_clk, new_refresh;
+-
+- spin_lock_irqsave(&pm_lock, flags);
+- if (!write) {
+- *len = 0;
+- } else {
+- /* Parse the new frequency */
+- if (*len > TMPBUFLEN - 1) {
+- spin_unlock_irqrestore(&pm_lock, flags);
+- return -EFAULT;
+- }
+- if (copy_from_user(buf, buffer, *len)) {
+- spin_unlock_irqrestore(&pm_lock, flags);
+- return -EFAULT;
+- }
+- buf[*len] = 0;
+- p = buf;
+- val = simple_strtoul(p, &p, 0);
+- if (val > MAX_CPU_FREQ) {
+- spin_unlock_irqrestore(&pm_lock, flags);
+- return -EFAULT;
+- }
+-
+- pll = val / 12;
+- if ((pll > 33) || (pll < 7)) { /* 396 MHz max, 84 MHz min */
+- /* revisit this for higher speed cpus */
+- spin_unlock_irqrestore(&pm_lock, flags);
+- return -EFAULT;
+- }
+-
+- old_baud_base = get_au1x00_uart_baud_base();
+- old_cpu_freq = get_au1x00_speed();
+-
+- new_cpu_freq = pll * 12 * 1000000;
+- new_baud_base = (new_cpu_freq / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16));
+- set_au1x00_speed(new_cpu_freq);
+- set_au1x00_uart_baud_base(new_baud_base);
+-
+- old_refresh = au_readl(MEM_SDREFCFG) & 0x1ffffff;
+- new_refresh =
+- ((old_refresh * new_cpu_freq) /
+- old_cpu_freq) | (au_readl(MEM_SDREFCFG) & ~0x1ffffff);
+-
+- au_writel(pll, SYS_CPUPLL);
+- au_sync_delay(1);
+- au_writel(new_refresh, MEM_SDREFCFG);
+- au_sync_delay(1);
+-
+- for (i = 0; i < 4; i++) {
+- if (au_readl
+- (UART_BASE + UART_MOD_CNTRL +
+- i * 0x00100000) == 3) {
+- old_clk =
+- au_readl(UART_BASE + UART_CLK +
+- i * 0x00100000);
+- // baud_rate = baud_base/clk
+- baud_rate = old_baud_base / old_clk;
+- /* we won't get an exact baud rate and the error
+- * could be significant enough that our new
+- * calculation will result in a clock that will
+- * give us a baud rate that's too far off from
+- * what we really want.
+- */
+- if (baud_rate > 100000)
+- baud_rate = 115200;
+- else if (baud_rate > 50000)
+- baud_rate = 57600;
+- else if (baud_rate > 30000)
+- baud_rate = 38400;
+- else if (baud_rate > 17000)
+- baud_rate = 19200;
+- else
+- (baud_rate = 9600);
+- // new_clk = new_baud_base/baud_rate
+- new_clk = new_baud_base / baud_rate;
+- au_writel(new_clk,
+- UART_BASE + UART_CLK +
+- i * 0x00100000);
+- au_sync_delay(10);
+- }
+- }
++ retval = pm_send_all(PM_RESUME, (void *) 0);
+ }
+-
+-
+- /* We don't want _any_ interrupts other than
+- * match20. Otherwise our calibrate_delay()
+- * calculation will be off, potentially a lot.
+- */
+- intc0_mask = save_local_and_disable(0);
+- intc1_mask = save_local_and_disable(1);
+- local_enable_irq(AU1000_TOY_MATCH2_INT);
+- spin_unlock_irqrestore(&pm_lock, flags);
+- calibrate_delay();
+- restore_local_and_enable(0, intc0_mask);
+- restore_local_and_enable(1, intc1_mask);
+ return retval;
+ }
+
+@@ -425,7 +312,6 @@
+ static struct ctl_table pm_table[] = {
+ {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, &pm_do_suspend},
+ {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &pm_do_sleep},
+- {CTL_ACPI, "freq", NULL, 0, 0600, NULL, &pm_do_freq},
+ {0}
+ };
+
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/common/reset.c linux-2.4.32-rc1.mips/arch/mips/au1000/common/reset.c
+--- linux-2.4.32-rc1/arch/mips/au1000/common/reset.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/common/reset.c 2005-03-19 08:17:51.000000000 +0100
+@@ -37,8 +37,6 @@
+ #include <asm/system.h>
+ #include <asm/au1000.h>
+
+-extern int au_sleep(void);
+-
+ void au1000_restart(char *command)
+ {
+ /* Set all integrated peripherals to disabled states */
+@@ -144,6 +142,26 @@
+ au_writel(0x00, 0xb1900064); /* sys_auxpll */
+ au_writel(0x00, 0xb1900100); /* sys_pininputen */
+ break;
++ case 0x04000000: /* Au1200 */
++ au_writel(0x00, 0xb400300c); /* ddma */
++ au_writel(0x00, 0xb1a00004); /* psc 0 */
++ au_writel(0x00, 0xb1b00004); /* psc 1 */
++ au_writel(0x00d02000, 0xb4020004); /* ehci, ohci, udc, otg */
++ au_writel(0x00, 0xb5000004); /* lcd */
++ au_writel(0x00, 0xb060000c); /* sd0 */
++ au_writel(0x00, 0xb068000c); /* sd1 */
++ au_writel(0x00, 0xb1100100); /* swcnt */
++ au_writel(0x00, 0xb0300000); /* aes */
++ au_writel(0x00, 0xb4004000); /* cim */
++ au_writel(0x00, 0xb1100100); /* uart0_enable */
++ au_writel(0x00, 0xb1200100); /* uart1_enable */
++ au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */
++ au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */
++ au_writel(0x00, 0xb1900028); /* sys_clksrc */
++ au_writel(0x10, 0xb1900060); /* sys_cpupll */
++ au_writel(0x00, 0xb1900064); /* sys_auxpll */
++ au_writel(0x00, 0xb1900100); /* sys_pininputen */
++ break;
+
+ default:
+ break;
+@@ -163,32 +181,23 @@
+
+ void au1000_halt(void)
+ {
+-#if defined(CONFIG_MIPS_PB1550)
+- /* power off system */
+- printk("\n** Powering off Pb1550\n");
+- au_writew(au_readw(0xAF00001C) | (3<<14), 0xAF00001C);
+- au_sync();
+- while(1); /* should not get here */
+-#endif
+- printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+-#ifdef CONFIG_MIPS_MIRAGE
+- au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT);
+-#endif
+-#ifdef CONFIG_PM
+- au_sleep();
+-
+- /* should not get here */
+- printk(KERN_ERR "Unable to put cpu in sleep mode\n");
+- while(1);
+-#else
+- while (1)
++ /* Use WAIT in a low-power infinite spin loop */
++ while (1) {
+ __asm__(".set\tmips3\n\t"
+ "wait\n\t"
+ ".set\tmips0");
+-#endif
++ }
+ }
+
+ void au1000_power_off(void)
+ {
++ extern void board_power_off (void);
++
++ printk(KERN_NOTICE "\n** You can safely turn off the power\n");
++
++ /* Give board a chance to power-off */
++ board_power_off();
++
++ /* If board can't power-off, spin forever */
+ au1000_halt();
+ }
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/common/setup.c linux-2.4.32-rc1.mips/arch/mips/au1000/common/setup.c
+--- linux-2.4.32-rc1/arch/mips/au1000/common/setup.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/common/setup.c 2005-01-30 09:01:27.000000000 +0100
+@@ -174,6 +174,40 @@
+ initrd_end = (unsigned long)&__rd_end;
+ #endif
+
++#if defined(CONFIG_SOC_AU1200)
++#ifdef CONFIG_USB_EHCI_HCD
++ if ((argptr = strstr(argptr, "usb_ehci=")) == NULL) {
++ char usb_args[80];
++ argptr = prom_getcmdline();
++ memset(usb_args, 0, sizeof(usb_args));
++ sprintf(usb_args, " usb_ehci=base:0x%x,len:0x%x,irq:%d",
++ USB_EHCI_BASE, USB_EHCI_LEN, AU1000_USB_HOST_INT);
++ strcat(argptr, usb_args);
++ }
++#ifdef CONFIG_USB_AMD5536UDC
++ /* enable EHC + OHC + UDC clocks, memory and bus mastering */
++/* au_writel( 0x00DF207F, USB_MSR_BASE + 4); */
++ au_writel( 0xC0DF207F, USB_MSR_BASE + 4); // incl. prefetch
++#else
++ /* enable EHC + OHC clocks, memory and bus mastering */
++/* au_writel( 0x00DB200F, USB_MSR_BASE + 4); */
++ au_writel( 0xC0DB200F, USB_MSR_BASE + 4); /* incl. prefetch */
++#endif
++ udelay(1000);
++
++#else /* CONFIG_USB_EHCI_HCD */
++
++#ifdef CONFIG_USB_AMD5536UDC
++#ifndef CONFIG_USB_OHCI
++ /* enable UDC clocks, memory and bus mastering */
++/* au_writel( 0x00DC2070, USB_MSR_BASE + 4); */
++ au_writel( 0xC0DC2070, USB_MSR_BASE + 4); // incl. prefetch
++ udelay(1000);
++#endif
++#endif
++#endif /* CONFIG_USB_EHCI_HCD */
++#endif /* CONFIG_SOC_AU1200 */
++
+ #if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+ #ifdef CONFIG_USB_OHCI
+ if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) {
+@@ -187,19 +221,38 @@
+ #endif
+
+ #ifdef CONFIG_USB_OHCI
+- // enable host controller and wait for reset done
++#if defined(CONFIG_SOC_AU1200)
++#ifndef CONFIG_USB_EHCI_HCD
++#ifdef CONFIG_USB_AMD5536UDC
++ /* enable OHC + UDC clocks, memory and bus mastering */
++/* au_writel( 0x00DD2073, USB_MSR_BASE + 4); */
++ au_writel( 0xC0DD2073, USB_MSR_BASE + 4); // incl. prefetch
++#else
++ /* enable OHC clocks, memory and bus mastering */
++ au_writel( 0x00D12003, USB_MSR_BASE + 4);
++#endif
++ udelay(1000);
++printk("DEBUG: Reading Au1200 USB2 reg 0x%x\n", au_readl(USB_MSR_BASE + 4));
++#endif
++#else
++ /* Au1000, Au1500, Au1100, Au1550 */
++ /* enable host controller and wait for reset done */
+ au_writel(0x08, USB_HOST_CONFIG);
+ udelay(1000);
+ au_writel(0x0E, USB_HOST_CONFIG);
+ udelay(1000);
+- au_readl(USB_HOST_CONFIG); // throw away first read
++ au_readl(USB_HOST_CONFIG); /* throw away first read */
+ while (!(au_readl(USB_HOST_CONFIG) & 0x10))
+ au_readl(USB_HOST_CONFIG);
++#endif /* CONFIG_SOC_AU1200 */
+ #endif
+-#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
++#else
++
++#endif /* defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) */
++
+
+ #ifdef CONFIG_FB
+- // Needed if PCI video card in use
++ /* Needed if PCI video card in use */
+ conswitchp = &dummy_con;
+ #endif
+
+@@ -209,8 +262,7 @@
+ #endif
+
+ #ifdef CONFIG_BLK_DEV_IDE
+- /* Board setup takes precedence for unique devices.
+- */
++ /* Board setup takes precedence for unique devices. */
+ if ((ide_ops == NULL) || (ide_ops == &no_ide_ops))
+ ide_ops = &std_ide_ops;
+ #endif
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/common/sleeper.S linux-2.4.32-rc1.mips/arch/mips/au1000/common/sleeper.S
+--- linux-2.4.32-rc1/arch/mips/au1000/common/sleeper.S 2004-02-18 14:36:30.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/common/sleeper.S 2005-01-30 09:01:27.000000000 +0100
+@@ -15,17 +15,48 @@
+ #include <asm/addrspace.h>
+ #include <asm/regdef.h>
+ #include <asm/stackframe.h>
++#include <asm/au1000.h>
++
++/*
++ * Note: This file is *not* conditional on CONFIG_PM since Alchemy sleep
++ * need not be tied to any particular power management scheme.
++ */
++
++ .extern ___flush_cache_all
+
+ .text
+- .set macro
+- .set noat
+ .align 5
+
+-/* Save all of the processor general registers and go to sleep.
+- * A wakeup condition will get us back here to restore the registers.
++/*
++ * Save the processor general registers and go to sleep. A wakeup
++ * condition will get us back here to restore the registers.
+ */
+-LEAF(save_and_sleep)
+
++/* still need to fix alignment issues here */
++save_and_sleep_frmsz = 48
++NESTED(save_and_sleep, save_and_sleep_frmsz, ra)
++ .set noreorder
++ .set nomacro
++ .set noat
++ subu sp, save_and_sleep_frmsz
++ sw ra, save_and_sleep_frmsz-4(sp)
++ sw s0, save_and_sleep_frmsz-8(sp)
++ sw s1, save_and_sleep_frmsz-12(sp)
++ sw s2, save_and_sleep_frmsz-16(sp)
++ sw s3, save_and_sleep_frmsz-20(sp)
++ sw s4, save_and_sleep_frmsz-24(sp)
++ sw s5, save_and_sleep_frmsz-28(sp)
++ sw s6, save_and_sleep_frmsz-32(sp)
++ sw s7, save_and_sleep_frmsz-36(sp)
++ sw s8, save_and_sleep_frmsz-40(sp)
++ sw gp, save_and_sleep_frmsz-44(sp)
++
++ /* We only need to save the registers that the calling function
++ * hasn't saved for us. 0 is always zero. 8 - 15, 24 and 25 are
++ * temporaries and can be used without saving. 26 and 27 are reserved
++ * for interrupt/trap handling and expected to change. 29 is the
++ * stack pointer which is handled as a special case here.
++ */
+ subu sp, PT_SIZE
+ sw $1, PT_R1(sp)
+ sw $2, PT_R2(sp)
+@@ -34,14 +65,6 @@
+ sw $5, PT_R5(sp)
+ sw $6, PT_R6(sp)
+ sw $7, PT_R7(sp)
+- sw $8, PT_R8(sp)
+- sw $9, PT_R9(sp)
+- sw $10, PT_R10(sp)
+- sw $11, PT_R11(sp)
+- sw $12, PT_R12(sp)
+- sw $13, PT_R13(sp)
+- sw $14, PT_R14(sp)
+- sw $15, PT_R15(sp)
+ sw $16, PT_R16(sp)
+ sw $17, PT_R17(sp)
+ sw $18, PT_R18(sp)
+@@ -50,32 +73,47 @@
+ sw $21, PT_R21(sp)
+ sw $22, PT_R22(sp)
+ sw $23, PT_R23(sp)
+- sw $24, PT_R24(sp)
+- sw $25, PT_R25(sp)
+- sw $26, PT_R26(sp)
+- sw $27, PT_R27(sp)
+ sw $28, PT_R28(sp)
+- sw $29, PT_R29(sp)
+ sw $30, PT_R30(sp)
+ sw $31, PT_R31(sp)
++#define PT_C0STATUS PT_LO
++#define PT_CONTEXT PT_HI
++#define PT_PAGEMASK PT_EPC
++#define PT_CONFIG PT_BVADDR
+ mfc0 k0, CP0_STATUS
+- sw k0, 0x20(sp)
++ sw k0, PT_C0STATUS(sp) // 0x20
+ mfc0 k0, CP0_CONTEXT
+- sw k0, 0x1c(sp)
++ sw k0, PT_CONTEXT(sp) // 0x1c
+ mfc0 k0, CP0_PAGEMASK
+- sw k0, 0x18(sp)
++ sw k0, PT_PAGEMASK(sp) // 0x18
+ mfc0 k0, CP0_CONFIG
+- sw k0, 0x14(sp)
++ sw k0, PT_CONFIG(sp) // 0x14
++
++ .set macro
++ .set at
++
++ li t0, SYS_SLPPWR
++ sw zero, 0(t0) /* Get the processor ready to sleep */
++ sync
+
+ /* Now set up the scratch registers so the boot rom will
+ * return to this point upon wakeup.
++ * sys_scratch0 : SP
++ * sys_scratch1 : RA
++ */
++ li t0, SYS_SCRATCH0
++ li t1, SYS_SCRATCH1
++ sw sp, 0(t0)
++ la k0, resume_from_sleep
++ sw k0, 0(t1)
++
++/*
++ * Flush DCACHE to make sure context is in memory
+ */
+- la k0, 1f
+- lui k1, 0xb190
+- ori k1, 0x18
+- sw sp, 0(k1)
+- ori k1, 0x1c
+- sw k0, 0(k1)
++ la t1,___flush_cache_all /* _flush_cache_all is a function pointer */
++ lw t0,0(t1)
++ jal t0
++ nop
+
+ /* Put SDRAM into self refresh. Preload instructions into cache,
+ * issue a precharge, then auto refresh, then sleep commands to it.
+@@ -88,30 +126,65 @@
+ cache 0x14, 96(t0)
+ .set mips0
+
++ /* Put SDRAM to sleep */
+ sdsleep:
+- lui k0, 0xb400
+- sw zero, 0x001c(k0) /* Precharge */
+- sw zero, 0x0020(k0) /* Auto refresh */
+- sw zero, 0x0030(k0) /* SDRAM sleep */
++ li a0, MEM_PHYS_ADDR
++ or a0, a0, 0xA0000000
++#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100) || defined(CONFIG_SOC_AU1500)
++ lw k0, MEM_SDMODE0(a0)
++ sw zero, MEM_SDPRECMD(a0) /* Precharge */
++ sw zero, MEM_SDAUTOREF(a0) /* Auto Refresh */
++ sw zero, MEM_SDSLEEP(a0) /* Sleep */
+ sync
+-
+- lui k1, 0xb190
+- sw zero, 0x0078(k1) /* get ready to sleep */
++#endif
++#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
++ sw zero, MEM_SDPRECMD(a0) /* Precharge */
++ sw zero, MEM_SDSREF(a0)
++
++ #lw t0, MEM_SDSTAT(a0)
++ #and t0, t0, 0x01000000
++ li t0, 0x01000000
++refresh_not_set:
++ lw t1, MEM_SDSTAT(a0)
++ and t2, t1, t0
++ beq zero, t2, refresh_not_set
++ nop
++
++ li t0, ~0x30000000
++ lw t1, MEM_SDCONFIGA(a0)
++ and t1, t0, t1
++ sw t1, MEM_SDCONFIGA(a0)
+ sync
+- sw zero, 0x007c(k1) /* Put processor to sleep */
++#endif
++
++ li t0, SYS_SLEEP
++ sw zero, 0(t0) /* Put processor to sleep */
+ sync
++ nop
++ nop
++ nop
++ nop
++ nop
++ nop
++ nop
++ nop
++
+
+ /* This is where we return upon wakeup.
+ * Reload all of the registers and return.
+ */
+-1: nop
+- lw k0, 0x20(sp)
++resume_from_sleep:
++ nop
++ .set nomacro
++ .set noat
++
++ lw k0, PT_C0STATUS(sp) // 0x20
+ mtc0 k0, CP0_STATUS
+- lw k0, 0x1c(sp)
++ lw k0, PT_CONTEXT(sp) // 0x1c
+ mtc0 k0, CP0_CONTEXT
+- lw k0, 0x18(sp)
++ lw k0, PT_PAGEMASK(sp) // 0x18
+ mtc0 k0, CP0_PAGEMASK
+- lw k0, 0x14(sp)
++ lw k0, PT_CONFIG(sp) // 0x14
+ mtc0 k0, CP0_CONFIG
+ lw $1, PT_R1(sp)
+ lw $2, PT_R2(sp)
+@@ -120,14 +193,6 @@
+ lw $5, PT_R5(sp)
+ lw $6, PT_R6(sp)
+ lw $7, PT_R7(sp)
+- lw $8, PT_R8(sp)
+- lw $9, PT_R9(sp)
+- lw $10, PT_R10(sp)
+- lw $11, PT_R11(sp)
+- lw $12, PT_R12(sp)
+- lw $13, PT_R13(sp)
+- lw $14, PT_R14(sp)
+- lw $15, PT_R15(sp)
+ lw $16, PT_R16(sp)
+ lw $17, PT_R17(sp)
+ lw $18, PT_R18(sp)
+@@ -136,15 +201,36 @@
+ lw $21, PT_R21(sp)
+ lw $22, PT_R22(sp)
+ lw $23, PT_R23(sp)
+- lw $24, PT_R24(sp)
+- lw $25, PT_R25(sp)
+- lw $26, PT_R26(sp)
+- lw $27, PT_R27(sp)
+ lw $28, PT_R28(sp)
+- lw $29, PT_R29(sp)
+ lw $30, PT_R30(sp)
+ lw $31, PT_R31(sp)
++
++ .set macro
++ .set at
++
++ /* clear the wake source, but save it as the return value of the function */
++ li t0, SYS_WAKESRC
++ lw v0, 0(t0)
++ sw v0, PT_R2(sp)
++ sw zero, 0(t0)
++
+ addiu sp, PT_SIZE
+
++ lw gp, save_and_sleep_frmsz-44(sp)
++ lw s8, save_and_sleep_frmsz-40(sp)
++ lw s7, save_and_sleep_frmsz-36(sp)
++ lw s6, save_and_sleep_frmsz-32(sp)
++ lw s5, save_and_sleep_frmsz-28(sp)
++ lw s4, save_and_sleep_frmsz-24(sp)
++ lw s3, save_and_sleep_frmsz-20(sp)
++ lw s2, save_and_sleep_frmsz-16(sp)
++ lw s1, save_and_sleep_frmsz-12(sp)
++ lw s0, save_and_sleep_frmsz-8(sp)
++ lw ra, save_and_sleep_frmsz-4(sp)
++
++ addu sp, save_and_sleep_frmsz
+ jr ra
++ nop
++ .set reorder
+ END(save_and_sleep)
++
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/common/time.c linux-2.4.32-rc1.mips/arch/mips/au1000/common/time.c
+--- linux-2.4.32-rc1/arch/mips/au1000/common/time.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/common/time.c 2005-04-08 10:33:17.000000000 +0200
+@@ -50,7 +50,6 @@
+ #include <linux/mc146818rtc.h>
+ #include <linux/timex.h>
+
+-extern void startup_match20_interrupt(void);
+ extern void do_softirq(void);
+ extern volatile unsigned long wall_jiffies;
+ unsigned long missed_heart_beats = 0;
+@@ -59,14 +58,14 @@
+ static unsigned long r4k_cur; /* What counter should be at next timer irq */
+ extern rwlock_t xtime_lock;
+ int no_au1xxx_32khz;
+-void (*au1k_wait_ptr)(void);
++extern int allow_au1k_wait; /* default off for CP0 Counter */
+
+ /* Cycle counter value at the previous timer interrupt.. */
+ static unsigned int timerhi = 0, timerlo = 0;
+
+ #ifdef CONFIG_PM
+ #define MATCH20_INC 328
+-extern void startup_match20_interrupt(void);
++extern void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *));
+ static unsigned long last_pc0, last_match20;
+ #endif
+
+@@ -385,7 +384,6 @@
+ {
+ unsigned int est_freq;
+ extern unsigned long (*do_gettimeoffset)(void);
+- extern void au1k_wait(void);
+
+ printk("calculating r4koff... ");
+ r4k_offset = cal_r4koff();
+@@ -437,9 +435,6 @@
+ au_writel(0, SYS_TOYWRITE);
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
+
+- au_writel(au_readl(SYS_WAKEMSK) | (1<<8), SYS_WAKEMSK);
+- au_writel(~0, SYS_WAKESRC);
+- au_sync();
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
+
+ /* setup match20 to interrupt once every 10ms */
+@@ -447,13 +442,13 @@
+ au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
+ au_sync();
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
+- startup_match20_interrupt();
++ startup_match20_interrupt(counter0_irq);
+
+ do_gettimeoffset = do_fast_pm_gettimeoffset;
+
+ /* We can use the real 'wait' instruction.
+ */
+- au1k_wait_ptr = au1k_wait;
++ allow_au1k_wait = 1;
+ }
+
+ #else
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/db1x00/board_setup.c linux-2.4.32-rc1.mips/arch/mips/au1000/db1x00/board_setup.c
+--- linux-2.4.32-rc1/arch/mips/au1000/db1x00/board_setup.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/db1x00/board_setup.c 2005-03-19 08:17:51.000000000 +0100
+@@ -46,10 +46,22 @@
+ #include <asm/au1000.h>
+ #include <asm/db1x00.h>
+
+-extern struct rtc_ops no_rtc_ops;
++#if defined(CONFIG_BLK_DEV_IDE_AU1XXX) && defined(CONFIG_MIPS_DB1550)
++#include <asm/au1xxx_dbdma.h>
++extern struct ide_ops *ide_ops;
++extern struct ide_ops au1xxx_ide_ops;
++extern u32 au1xxx_ide_virtbase;
++extern u64 au1xxx_ide_physbase;
++extern int au1xxx_ide_irq;
++
++/* Ddma */
++chan_tab_t *ide_read_ch, *ide_write_ch;
++u32 au1xxx_ide_ddma_enable = 0, switch4ddma = 1; // PIO+ddma
++
++dbdev_tab_t new_dbdev_tab_element = { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 };
++#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX */
+
+-/* not correct for db1550 */
+-static BCSR * const bcsr = (BCSR *)0xAE000000;
++extern struct rtc_ops no_rtc_ops;
+
+ void board_reset (void)
+ {
+@@ -57,6 +69,13 @@
+ au_writel(0x00000000, 0xAE00001C);
+ }
+
++void board_power_off (void)
++{
++#ifdef CONFIG_MIPS_MIRAGE
++ au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT);
++#endif
++}
++
+ void __init board_setup(void)
+ {
+ u32 pin_func;
+@@ -108,8 +127,42 @@
+ au_writel(0x02000200, GPIO2_OUTPUT);
+ #endif
+
++#if defined(CONFIG_AU1XXX_SMC91111)
++#define CPLD_CONTROL (0xAF00000C)
++ {
++ extern uint32_t au1xxx_smc91111_base;
++ extern unsigned int au1xxx_smc91111_irq;
++ extern int au1xxx_smc91111_nowait;
++
++ au1xxx_smc91111_base = 0xAC000300;
++ au1xxx_smc91111_irq = AU1000_GPIO_8;
++ au1xxx_smc91111_nowait = 1;
++
++ /* set up the Static Bus timing - only 396Mhz */
++ bcsr->resets |= 0x7;
++ au_writel(0x00010003, MEM_STCFG0);
++ au_writel(0x000c00c0, MEM_STCFG2);
++ au_writel(0x85E1900D, MEM_STTIME2);
++ }
++#endif /* end CONFIG_SMC91111 */
+ au_sync();
+
++#if defined(CONFIG_BLK_DEV_IDE_AU1XXX) && defined(CONFIG_MIPS_DB1550)
++ /*
++ * Iniz IDE parameters
++ */
++ ide_ops = &au1xxx_ide_ops;
++ au1xxx_ide_irq = DAUGHTER_CARD_IRQ;
++ au1xxx_ide_physbase = AU1XXX_ATA_PHYS_ADDR;
++ au1xxx_ide_virtbase = KSEG1ADDR(AU1XXX_ATA_PHYS_ADDR);
++
++ /*
++ * change PIO or PIO+Ddma
++ * check the GPIO-6 pin condition. db1550:s6_dot
++ */
++ switch4ddma = (au_readl(SYS_PINSTATERD) & (1 << 6)) ? 1 : 0;
++#endif
++
+ #ifdef CONFIG_MIPS_DB1000
+ printk("AMD Alchemy Au1000/Db1000 Board\n");
+ #endif
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/db1x00/irqmap.c linux-2.4.32-rc1.mips/arch/mips/au1000/db1x00/irqmap.c
+--- linux-2.4.32-rc1/arch/mips/au1000/db1x00/irqmap.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/db1x00/irqmap.c 2005-01-30 09:06:19.000000000 +0100
+@@ -53,6 +53,7 @@
+ #ifdef CONFIG_MIPS_DB1550
+ { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 IRQ#
+ { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 1 IRQ#
++ { AU1000_GPIO_8, INTC_INT_LOW_LEVEL, 0 }, // Daughtercard IRQ#
+ #else
+ { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 Fully_Interted#
+ { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 STSCHG#
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/db1x00/Makefile linux-2.4.32-rc1.mips/arch/mips/au1000/db1x00/Makefile
+--- linux-2.4.32-rc1/arch/mips/au1000/db1x00/Makefile 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/db1x00/Makefile 2005-01-30 09:06:19.000000000 +0100
+@@ -17,4 +17,11 @@
+ obj-y := init.o board_setup.o irqmap.o
+ obj-$(CONFIG_WM97XX_COMODULE) += mirage_ts.o
+
++ifdef CONFIG_MIPS_DB1100
++ifdef CONFIG_MMC
++obj-y += mmc_support.o
++export-objs += mmc_support.o
++endif
++endif
++
+ include $(TOPDIR)/Rules.make
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/db1x00/mmc_support.c linux-2.4.32-rc1.mips/arch/mips/au1000/db1x00/mmc_support.c
+--- linux-2.4.32-rc1/arch/mips/au1000/db1x00/mmc_support.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/db1x00/mmc_support.c 2005-01-30 09:07:01.000000000 +0100
+@@ -0,0 +1,126 @@
++/*
++ * BRIEF MODULE DESCRIPTION
++ *
++ * MMC support routines for DB1100.
++ *
++ *
++ * Copyright (c) 2003-2004 Embedded Edge, LLC.
++ * Author: Embedded Edge, LLC.
++ * Contact: dan@embeddededge.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++
++#include <asm/irq.h>
++#include <asm/au1000.h>
++#include <asm/au1100_mmc.h>
++#include <asm/db1x00.h>
++
++
++/* SD/MMC controller support functions */
++
++/*
++ * Detect card.
++ */
++void mmc_card_inserted(int _n_, int *_res_)
++{
++ u32 gpios = au_readl(SYS_PINSTATERD);
++ u32 emptybit = (_n_) ? (1<<20) : (1<<19);
++ *_res_ = ((gpios & emptybit) == 0);
++}
++
++/*
++ * Check card write protection.
++ */
++void mmc_card_writable(int _n_, int *_res_)
++{
++ BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
++ unsigned long mmc_wp, board_specific;
++
++ if (_n_) {
++ mmc_wp = BCSR_BOARD_SD1_WP;
++ } else {
++ mmc_wp = BCSR_BOARD_SD0_WP;
++ }
++
++ board_specific = au_readl((unsigned long)(&bcsr->specific));
++
++ if (!(board_specific & mmc_wp)) {/* low means card writable */
++ *_res_ = 1;
++ } else {
++ *_res_ = 0;
++ }
++}
++
++/*
++ * Apply power to card slot.
++ */
++void mmc_power_on(int _n_)
++{
++ BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
++ unsigned long mmc_pwr, board_specific;
++
++ if (_n_) {
++ mmc_pwr = BCSR_BOARD_SD1_PWR;
++ } else {
++ mmc_pwr = BCSR_BOARD_SD0_PWR;
++ }
++
++ board_specific = au_readl((unsigned long)(&bcsr->specific));
++ board_specific |= mmc_pwr;
++
++ au_writel(board_specific, (int)(&bcsr->specific));
++ au_sync_delay(1);
++}
++
++/*
++ * Remove power from card slot.
++ */
++void mmc_power_off(int _n_)
++{
++ BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
++ unsigned long mmc_pwr, board_specific;
++
++ if (_n_) {
++ mmc_pwr = BCSR_BOARD_SD1_PWR;
++ } else {
++ mmc_pwr = BCSR_BOARD_SD0_PWR;
++ }
++
++ board_specific = au_readl((unsigned long)(&bcsr->specific));
++ board_specific &= ~mmc_pwr;
++
++ au_writel(board_specific, (int)(&bcsr->specific));
++ au_sync_delay(1);
++}
++
++EXPORT_SYMBOL(mmc_card_inserted);
++EXPORT_SYMBOL(mmc_card_writable);
++EXPORT_SYMBOL(mmc_power_on);
++EXPORT_SYMBOL(mmc_power_off);
++
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/ficmmp/au1200_ibutton.c linux-2.4.32-rc1.mips/arch/mips/au1000/ficmmp/au1200_ibutton.c
+--- linux-2.4.32-rc1/arch/mips/au1000/ficmmp/au1200_ibutton.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/ficmmp/au1200_ibutton.c 2005-02-03 07:35:29.000000000 +0100
+@@ -0,0 +1,270 @@
++/* ----------------------------------------------------------------------
++ * mtwilson_keys.c
++ *
++ * Copyright (C) 2003 Intrinsyc Software Inc.
++ *
++ * Intel Personal Media Player buttons
++ *
++ * 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.
++ *
++ * May 02, 2003 : Initial version [FB]
++ *
++ ------------------------------------------------------------------------*/
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/sched.h>
++#include <linux/miscdevice.h>
++#include <linux/errno.h>
++#include <linux/poll.h>
++#include <linux/delay.h>
++#include <linux/input.h>
++
++#include <asm/au1000.h>
++#include <asm/uaccess.h>
++#include <asm/au1xxx_gpio.h>
++#include <asm/irq.h>
++#include <asm/keyboard.h>
++#include <linux/time.h>
++
++#define DRIVER_VERSION "V1.0"
++#define DRIVER_AUTHOR "FIC"
++#define DRIVER_DESC "FIC Travis Media Player Button Driver"
++#define DRIVER_NAME "Au1200Button"
++
++#define BUTTON_MAIN (1<<1)
++#define BUTTON_SELECT (1<<6)
++#define BUTTON_GUIDE (1<<12)
++#define BUTTON_DOWN (1<<17)
++#define BUTTON_LEFT (1<<19)
++#define BUTTON_RIGHT (1<<26)
++#define BUTTON_UP (1<<28)
++
++#define BUTTON_MASK (\
++ BUTTON_MAIN \
++ | BUTTON_SELECT \
++ | BUTTON_GUIDE \
++ | BUTTON_DOWN \
++ | BUTTON_LEFT \
++ | BUTTON_RIGHT \
++ | BUTTON_UP \
++ )
++
++#define BUTTON_INVERT (\
++ BUTTON_MAIN \
++ | 0 \
++ | BUTTON_GUIDE \
++ | 0 \
++ | 0 \
++ | 0 \
++ | 0 \
++ )
++
++char button_map[32]={0,KEY_S,0,0,0,0,KEY_ENTER,0,0,0,0,0,KEY_G,0,0,0,0,KEY_DOWN,0,KEY_LEFT,0,0,0,0,0,0,KEY_RIGHT,0,KEY_UP,0,0,0};
++//char button_map[32]={0,0,0,0,0,0,KEY_ENTER,0,0,0,0,0,KEY_G,0,0,0,0,KEY_DOWN,0,KEY_LEFT,0,0,0,0,0,0,KEY_RIGHT,0,KEY_UP,0,0,0};
++
++//char button_map[32]={0,KEY_TAB,0,0,0,0,KEY_M,0,0,0,0,0,KEY_S,0,0,0,0,KEY_DOWN,0,KEY_LEFT,0,0,0,0,0,0,KEY_RIGHT,0,KEY_UP,0,0,0};
++//char button_map[32]={0,0,0,0,0,0,KEY_M,0,0,0,0,0,KEY_S,0,0,0,0,KEY_DOWN,0,KEY_LEFT,0,0,0,0,0,0,KEY_RIGHT,0,KEY_UP,0,0,0};
++
++#define BUTTON_COUNT (sizeof (button_map) / sizeof (button_map[0]))
++
++struct input_dev dev;
++struct timeval cur_tv;
++
++static unsigned int old_tv_usec = 0;
++
++static unsigned int read_button_state(void)
++{
++ unsigned int state;
++
++ state = au_readl(SYS_PINSTATERD) & BUTTON_MASK; /* get gpio status */
++
++ state ^= BUTTON_INVERT; /* invert main & guide button */
++
++ /* printk("au1200_ibutton.c: button state [0x%X]\r\n",state); */
++ return state;
++}
++
++//This function returns 0 if the allowed microseconds have elapsed since the last call to ths function, otherwise it returns 1 to indicate a bounce condition
++static unsigned int bounce()
++{
++
++ unsigned int elapsed_time;
++
++ do_gettimeofday (&cur_tv);
++
++ if (!old_tv_usec) {
++ old_tv_usec = cur_tv.tv_usec;
++ return 0;
++ }
++
++ if(cur_tv.tv_usec > old_tv_usec) {
++ /* If there hasn't been rollover */
++ elapsed_time = ((cur_tv.tv_usec - old_tv_usec));
++ }
++ else {
++ /* Accounting for rollover */
++ elapsed_time = ((1000000 - old_tv_usec + cur_tv.tv_usec));
++ }
++
++ if (elapsed_time > 250000) {
++ old_tv_usec = 0; /* reset the bounce time */
++ return 0;
++ }
++
++ return 1;
++}
++
++/* button interrupt handler */
++static void button_interrupt(int irq, void *dev, struct pt_regs *regs)
++{
++
++ unsigned int i,bit_mask, key_choice;
++ u32 button_state;
++
++ /* Report state to upper level */
++
++ button_state = read_button_state() & BUTTON_MASK; /* get new gpio status */
++
++ /* Return if this is a repeated (bouncing) event */
++ if(bounce())
++ return;
++
++ /* we want to make keystrokes */
++ for( i=0; i< BUTTON_COUNT; i++) {
++ bit_mask = 1<<i;
++ if (button_state & bit_mask) {
++ key_choice = button_map[i];
++ /* toggle key down */
++ input_report_key(dev, key_choice, 1);
++ /* toggle key up */
++ input_report_key(dev, key_choice, 0);
++ printk("ibutton gpio %d stat %x scan code %d\r\n",
++ i, button_state, key_choice);
++ /* Only report the first key event; it doesn't make
++ * sense for two keys to be pressed at the same time,
++ * and causes problems with the directional keys
++ * return;
++ */
++ }
++ }
++}
++
++static int
++button_translate(unsigned char scancode, unsigned char *keycode, char raw_mode)
++{
++ static int prev_scancode;
++
++ printk( "ibutton.c: translate: scancode=%x raw_mode=%x\n",
++ scancode, raw_mode);
++
++ if (scancode == 0xe0 || scancode == 0xe1) {
++ prev_scancode = scancode;
++ return 0;
++ }
++
++ if (scancode == 0x00 || scancode == 0xff) {
++ prev_scancode = 0;
++ return 0;
++ }
++
++ *keycode = scancode;
++
++ return 1;
++}
++
++/* init button hardware */
++static int button_hw_init(void)
++{
++ unsigned int ipinfunc=0;
++
++ printk("au1200_ibutton.c: Initializing buttons hardware\n");
++
++ // initialize GPIO pin function assignments
++
++ ipinfunc = au_readl(SYS_PINFUNC);
++
++ ipinfunc &= ~(SYS_PINFUNC_DMA | SYS_PINFUNC_S0A | SYS_PINFUNC_S0B);
++ au_writel( ipinfunc ,SYS_PINFUNC);
++
++ ipinfunc |= (SYS_PINFUNC_S0C);
++ au_writel( ipinfunc ,SYS_PINFUNC);
++
++ return 0;
++}
++
++/* button driver init */
++static int __init button_init(void)
++{
++ int ret, i;
++ unsigned int flag=0;
++
++ printk("au1200_ibutton.c: button_init()\r\n");
++
++ button_hw_init();
++
++ /* register all button irq handler */
++
++ for(i=0; i< sizeof(button_map)/sizeof(button_map[0]); i++)
++ {
++ /* register irq <-- gpio 1 ,6 ,12 , 17 ,19 , 26 ,28 */
++ if(button_map[i] != 0)
++ {
++ ret = request_irq(AU1000_GPIO_0 + i ,
++ &button_interrupt , SA_INTERRUPT ,
++ DRIVER_NAME , &dev);
++ if(ret) flag |= 1<<i;
++ }
++ }
++
++ printk("au1200_ibutton.c: request_irq,ret:0x%x\r\n",ret);
++
++ if (ret) {
++ printk("au1200_ibutton.c: request_irq:%X failed\r\n",flag);
++ return ret;
++ }
++
++ dev.name = DRIVER_NAME;
++ dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
++
++ for (i=0;i<sizeof(button_map)/sizeof(button_map[0]);i++)
++ {
++ dev.keybit[LONG(button_map[i])] |= BIT(button_map[i]);
++ }
++
++ input_register_device(&dev);
++
++ /* ready to receive interrupts */
++
++ return 0;
++}
++
++/* button driver exit */
++static void __exit button_exit(void)
++{
++ int i;
++
++ for(i=0;i<sizeof(button_map)/sizeof(button_map[0]);i++)
++ {
++ if(button_map[i] != 0)
++ {
++ free_irq( AU1000_GPIO_0 + i, &dev);
++ }
++ }
++
++ input_unregister_device(&dev);
++
++ printk("au1200_ibutton.c: button_exit()\r\n");
++}
++
++module_init(button_init);
++module_exit(button_exit);
++
++MODULE_AUTHOR( DRIVER_AUTHOR );
++MODULE_DESCRIPTION( DRIVER_DESC );
++MODULE_LICENSE("GPL");
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/ficmmp/au1xxx_dock.c linux-2.4.32-rc1.mips/arch/mips/au1000/ficmmp/au1xxx_dock.c
+--- linux-2.4.32-rc1/arch/mips/au1000/ficmmp/au1xxx_dock.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/ficmmp/au1xxx_dock.c 2005-01-30 09:01:27.000000000 +0100
+@@ -0,0 +1,261 @@
++/*
++ * Copyright (C) 2003 Metrowerks, All Rights Reserved.
++ *
++ * 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/config.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/sched.h>
++#include <linux/miscdevice.h>
++#include <linux/errno.h>
++#include <linux/poll.h>
++#include <asm/au1000.h>
++#include <asm/uaccess.h>
++#include <asm/au1xxx_gpio.h>
++
++
++#if defined(CONFIG_MIPS_FICMMP)
++ #define DOCK_GPIO 215
++#else
++ #error Unsupported Au1xxx Platform
++#endif
++
++#define MAKE_FLAG 0x20
++
++#undef DEBUG
++
++#define DEBUG 0
++//#define DEBUG 1
++
++#if DEBUG
++#define DPRINTK(format, args...) printk(__FUNCTION__ ": " format, ## args)
++#else
++#define DPRINTK(format, args...) do { } while (0)
++#endif
++
++/* Please note that this driver is based on a timer and is not interrupt
++ * driven. If you are going to make use of this driver, you will need to have
++ * your application open the dock listing from the /dev directory first.
++ */
++
++struct au1xxx_dock {
++ struct fasync_struct *fasync;
++ wait_queue_head_t read_wait;
++ int open_count;
++ unsigned int debounce;
++ unsigned int current;
++ unsigned int last;
++};
++
++static struct au1xxx_dock dock_info;
++
++
++static void dock_timer_periodic(void *data);
++
++static struct tq_struct dock_task = {
++ routine: dock_timer_periodic,
++ data: NULL
++};
++
++static int cleanup_flag = 0;
++static DECLARE_WAIT_QUEUE_HEAD(cleanup_wait_queue);
++
++
++static unsigned int read_dock_state(void)
++{
++ u32 state;
++
++ state = au1xxx_gpio_read(DOCK_GPIO);
++
++ /* printk( "Current Dock State: %d\n", state ); */
++
++ return state;
++}
++
++
++static void dock_timer_periodic(void *data)
++{
++ struct au1xxx_dock *dock = (struct au1xxx_dock *)data;
++ unsigned long dock_state;
++
++ /* If cleanup wants us to die */
++ if (cleanup_flag) {
++ /* now cleanup_module can return */
++ wake_up(&cleanup_wait_queue);
++ } else {
++ /* put ourselves back in the task queue */
++ queue_task(&dock_task, &tq_timer);
++ }
++
++ /* read current dock */
++ dock_state = read_dock_state();
++
++ /* if dock states hasn't changed */
++ /* save time and be done. */
++ if (dock_state == dock->current) {
++ return;
++ }
++
++ if (dock_state == dock->debounce) {
++ dock->current = dock_state;
++ } else {
++ dock->debounce = dock_state;
++ }
++ if (dock->current != dock->last) {
++ if (waitqueue_active(&dock->read_wait)) {
++ wake_up_interruptible(&dock->read_wait);
++ }
++ }
++}
++
++
++static ssize_t au1xxx_dock_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
++{
++ struct au1xxx_dock *dock = filp->private_data;
++ char event[3];
++ int last;
++ int cur;
++ int err;
++
++try_again:
++
++ while (dock->current == dock->last) {
++ if (filp->f_flags & O_NONBLOCK) {
++ return -EAGAIN;
++ }
++ interruptible_sleep_on(&dock->read_wait);
++ if (signal_pending(current)) {
++ return -ERESTARTSYS;
++ }
++ }
++
++ cur = dock->current;
++ last = dock->last;
++
++ if(cur != last)
++ {
++ event[0] = cur ? 'D' : 'U';
++ event[1] = '\r';
++ event[2] = '\n';
++ }
++ else
++ goto try_again;
++
++ dock->last = cur;
++ err = copy_to_user(buffer, &event, 3);
++ if (err) {
++ return err;
++ }
++
++ return 3;
++}
++
++
++static int au1xxx_dock_open(struct inode *inode, struct file *filp)
++{
++ struct au1xxx_dock *dock = &dock_info;
++
++ MOD_INC_USE_COUNT;
++
++ filp->private_data = dock;
++
++ if (dock->open_count++ == 0) {
++ dock_task.data = dock;
++ cleanup_flag = 0;
++ queue_task(&dock_task, &tq_timer);
++ }
++
++ return 0;
++}
++
++
++static unsigned int au1xxx_dock_poll(struct file *filp, poll_table *wait)
++{
++ struct au1xxx_dock *dock = filp->private_data;
++ int ret = 0;
++
++ DPRINTK("start\n");
++ poll_wait(filp, &dock->read_wait, wait);
++ if (dock->current != dock->last) {
++ ret = POLLIN | POLLRDNORM;
++ }
++ return ret;
++}
++
++
++static int au1xxx_dock_release(struct inode *inode, struct file *filp)
++{
++ struct au1xxx_dock *dock = filp->private_data;
++
++ DPRINTK("start\n");
++
++ if (--dock->open_count == 0) {
++ cleanup_flag = 1;
++ sleep_on(&cleanup_wait_queue);
++ }
++ MOD_DEC_USE_COUNT;
++
++ return 0;
++}
++
++
++
++static struct file_operations au1xxx_dock_fops = {
++ owner: THIS_MODULE,
++ read: au1xxx_dock_read,
++ poll: au1xxx_dock_poll,
++ open: au1xxx_dock_open,
++ release: au1xxx_dock_release,
++};
++
++/*
++ * The au1xxx dock is a misc device:
++ * Major 10 char
++ * Minor 22 /dev/dock
++ *
++ * This is /dev/misc/dock if devfs is used.
++ */
++
++static struct miscdevice au1xxx_dock_dev = {
++ minor: 23,
++ name: "dock",
++ fops: &au1xxx_dock_fops,
++};
++
++static int __init au1xxx_dock_init(void)
++{
++ struct au1xxx_dock *dock = &dock_info;
++ int ret;
++
++ DPRINTK("Initializing dock driver\n");
++ dock->open_count = 0;
++ cleanup_flag = 0;
++ init_waitqueue_head(&dock->read_wait);
++
++
++ /* yamon configures GPIO pins for the dock
++ * no initialization needed
++ */
++
++ ret = misc_register(&au1xxx_dock_dev);
++
++ DPRINTK("dock driver fully initialized.\n");
++
++ return ret;
++}
++
++
++static void __exit au1xxx_dock_exit(void)
++{
++ DPRINTK("unloading dock driver\n");
++ misc_deregister(&au1xxx_dock_dev);
++}
++
++
++module_init(au1xxx_dock_init);
++module_exit(au1xxx_dock_exit);
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/ficmmp/board_setup.c linux-2.4.32-rc1.mips/arch/mips/au1000/ficmmp/board_setup.c
+--- linux-2.4.32-rc1/arch/mips/au1000/ficmmp/board_setup.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/ficmmp/board_setup.c 2005-03-19 08:17:51.000000000 +0100
+@@ -0,0 +1,226 @@
++/*
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Alchemy Pb1200 board setup.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/config.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/ioport.h>
++#include <linux/mm.h>
++#include <linux/console.h>
++#include <linux/mc146818rtc.h>
++#include <linux/delay.h>
++#include <linux/ide.h>
++
++#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
++#include <linux/ide.h>
++#endif
++
++#include <asm/cpu.h>
++#include <asm/bootinfo.h>
++#include <asm/irq.h>
++#include <asm/keyboard.h>
++#include <asm/mipsregs.h>
++#include <asm/reboot.h>
++#include <asm/pgtable.h>
++#include <asm/au1000.h>
++#include <asm/ficmmp.h>
++#include <asm/au1xxx_dbdma.h>
++#include <asm/au1xxx_gpio.h>
++
++extern struct rtc_ops no_rtc_ops;
++
++/* value currently in the board configuration register */
++u16 ficmmp_config = 0;
++
++#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
++extern struct ide_ops *ide_ops;
++extern struct ide_ops au1xxx_ide_ops;
++extern u32 au1xxx_ide_virtbase;
++extern u64 au1xxx_ide_physbase;
++extern int au1xxx_ide_irq;
++
++u32 led_base_addr;
++/* Ddma */
++chan_tab_t *ide_read_ch, *ide_write_ch;
++u32 au1xxx_ide_ddma_enable = 0, switch4ddma = 1; // PIO+ddma
++
++dbdev_tab_t new_dbdev_tab_element = { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 };
++#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX */
++
++void board_reset (void)
++{
++ au_writel(0, 0xAD80001C);
++}
++
++void board_power_off (void)
++{
++}
++
++void __init board_setup(void)
++{
++ char *argptr = NULL;
++ u32 pin_func;
++ rtc_ops = &no_rtc_ops;
++
++ ficmmp_config_init(); //Initialize FIC control register
++
++#if 0
++ /* Enable PSC1 SYNC for AC97. Normaly done in audio driver,
++ * but it is board specific code, so put it here.
++ */
++ pin_func = au_readl(SYS_PINFUNC);
++ au_sync();
++ pin_func |= SYS_PF_MUST_BE_SET | SYS_PF_PSC1_S1;
++ au_writel(pin_func, SYS_PINFUNC);
++
++ au_writel(0, (u32)bcsr|0x10); /* turn off pcmcia power */
++ au_sync();
++#endif
++
++#if defined( CONFIG_I2C_ALGO_AU1550 )
++ {
++ u32 freq0, clksrc;
++
++ /* Select SMBUS in CPLD */
++ /* bcsr->resets &= ~(BCSR_RESETS_PCS0MUX); */
++
++ pin_func = au_readl(SYS_PINFUNC);
++ au_sync();
++ pin_func &= ~(3<<17 | 1<<4);
++ /* Set GPIOs correctly */
++ pin_func |= 2<<17;
++ au_writel(pin_func, SYS_PINFUNC);
++ au_sync();
++
++ /* The i2c driver depends on 50Mhz clock */
++ freq0 = au_readl(SYS_FREQCTRL0);
++ au_sync();
++ freq0 &= ~(SYS_FC_FRDIV1_MASK | SYS_FC_FS1 | SYS_FC_FE1);
++ freq0 |= (3<<SYS_FC_FRDIV1_BIT);
++ /* 396Mhz / (3+1)*2 == 49.5Mhz */
++ au_writel(freq0, SYS_FREQCTRL0);
++ au_sync();
++ freq0 |= SYS_FC_FE1;
++ au_writel(freq0, SYS_FREQCTRL0);
++ au_sync();
++
++ clksrc = au_readl(SYS_CLKSRC);
++ au_sync();
++ clksrc &= ~0x01f00000;
++ /* bit 22 is EXTCLK0 for PSC0 */
++ clksrc |= (0x3 << 22);
++ au_writel(clksrc, SYS_CLKSRC);
++ au_sync();
++ }
++#endif
++
++#ifdef CONFIG_FB_AU1200
++ argptr = prom_getcmdline();
++ strcat(argptr, " video=au1200fb:");
++#endif
++
++#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
++ /*
++ * Iniz IDE parameters
++ */
++ ide_ops = &au1xxx_ide_ops;
++ au1xxx_ide_irq = FICMMP_IDE_INT;
++ au1xxx_ide_physbase = AU1XXX_ATA_PHYS_ADDR;
++ au1xxx_ide_virtbase = KSEG1ADDR(AU1XXX_ATA_PHYS_ADDR);
++ switch4ddma = 0;
++ /*
++ ide_ops = &au1xxx_ide_ops;
++ au1xxx_ide_irq = FICMMP_IDE_INT;
++ au1xxx_ide_base = KSEG1ADDR(AU1XXX_ATA_BASE);
++ */
++ au1xxx_gpio_write(9, 1);
++ printk("B4001010: %X\n", *((u32*)0xB4001010));
++ printk("B4001014: %X\n", *((u32*)0xB4001014));
++ printk("B4001018: %X\n", *((u32*)0xB4001018));
++ printk("B1900100: %X\n", *((u32*)0xB1900100));
++
++#if 0
++ ficmmp_config_clear(FICMMP_CONFIG_IDERST);
++ mdelay(100);
++ ficmmp_config_set(FICMMP_CONFIG_IDERST);
++ mdelay(100);
++#endif
++ /*
++ * change PIO or PIO+Ddma
++ * check the GPIO-5 pin condition. pb1200:s18_dot
++ */
++/* switch4ddma = 0; //(au_readl(SYS_PINSTATERD) & (1 << 5)) ? 1 : 0; */
++#endif
++
++ /* The Pb1200 development board uses external MUX for PSC0 to
++ support SMB/SPI. bcsr->resets bit 12: 0=SMB 1=SPI
++ */
++#if defined(CONFIG_AU1550_PSC_SPI) && defined(CONFIG_I2C_ALGO_AU1550)
++ #error I2C and SPI are mutually exclusive. Both are physically connected to PSC0.\
++ Refer to Pb1200 documentation.
++#elif defined( CONFIG_AU1550_PSC_SPI )
++ //bcsr->resets |= BCSR_RESETS_PCS0MUX;
++#elif defined( CONFIG_I2C_ALGO_AU1550 )
++ //bcsr->resets &= (~BCSR_RESETS_PCS0MUX);
++#endif
++ au_sync();
++
++ printk("FIC Multimedia Player Board\n");
++ au1xxx_gpio_tristate(5);
++ printk("B1900100: %X\n", *((volatile u32*)0xB1900100));
++ printk("B190002C: %X\n", *((volatile u32*)0xB190002C));
++}
++
++int
++board_au1200fb_panel (void)
++{
++ au1xxx_gpio_tristate(6);
++
++ if (au1xxx_gpio_read(12) == 0)
++ return 9; /* FS453_640x480 (Composite/S-Video) */
++ else
++ return 7; /* Sharp 320x240 TFT */
++}
++
++int
++board_au1200fb_panel_init (void)
++{
++ /*Enable data buffers*/
++ ficmmp_config_clear(FICMMP_CONFIG_LCMDATAOUT);
++ /*Take LCD out of reset*/
++ ficmmp_config_set(FICMMP_CONFIG_LCMPWREN | FICMMP_CONFIG_LCMEN);
++ return 0;
++}
++
++int
++board_au1200fb_panel_shutdown (void)
++{
++ /*Disable data buffers*/
++ ficmmp_config_set(FICMMP_CONFIG_LCMDATAOUT);
++ /*Put LCD in reset, remove power*/
++ ficmmp_config_clear(FICMMP_CONFIG_LCMEN | FICMMP_CONFIG_LCMPWREN);
++ return 0;
++}
++
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/ficmmp/init.c linux-2.4.32-rc1.mips/arch/mips/au1000/ficmmp/init.c
+--- linux-2.4.32-rc1/arch/mips/au1000/ficmmp/init.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/ficmmp/init.c 2005-01-30 09:01:27.000000000 +0100
+@@ -0,0 +1,76 @@
++/*
++ *
++ * BRIEF MODULE DESCRIPTION
++ * PB1200 board setup
++ *
++ * 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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/init.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/bootmem.h>
++#include <asm/addrspace.h>
++#include <asm/bootinfo.h>
++#include <linux/config.h>
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++
++int prom_argc;
++char **prom_argv, **prom_envp;
++extern void __init prom_init_cmdline(void);
++extern char *prom_getenv(char *envname);
++
++const char *get_system_type(void)
++{
++ return "FIC Multimedia Player (Au1200)";
++}
++
++u32 mae_memsize = 0;
++
++int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
++{
++ unsigned char *memsize_str;
++ unsigned long memsize;
++
++ prom_argc = argc;
++ prom_argv = argv;
++ prom_envp = envp;
++
++ mips_machgroup = MACH_GROUP_ALCHEMY;
++ mips_machtype = MACH_PB1000; /* set the platform # */
++ prom_init_cmdline();
++
++ memsize_str = prom_getenv("memsize");
++ if (!memsize_str) {
++ memsize = 0x08000000;
++ } else {
++ memsize = simple_strtol(memsize_str, NULL, 0);
++ }
++
++ /* reserved 32MB for MAE driver */
++ memsize -= (32 * 1024 * 1024);
++ add_memory_region(0, memsize, BOOT_MEM_RAM);
++ mae_memsize = memsize; /* for drivers/char/au1xxx_mae.c */
++ return 0;
++}
++
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/ficmmp/irqmap.c linux-2.4.32-rc1.mips/arch/mips/au1000/ficmmp/irqmap.c
+--- linux-2.4.32-rc1/arch/mips/au1000/ficmmp/irqmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/ficmmp/irqmap.c 2005-01-30 09:01:27.000000000 +0100
+@@ -0,0 +1,61 @@
++/*
++ * BRIEF MODULE DESCRIPTION
++ * Au1xxx irq map table
++ *
++ * 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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/errno.h>
++#include <linux/init.h>
++#include <linux/irq.h>
++#include <linux/kernel_stat.h>
++#include <linux/module.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/timex.h>
++#include <linux/slab.h>
++#include <linux/random.h>
++#include <linux/delay.h>
++
++#include <asm/bitops.h>
++#include <asm/bootinfo.h>
++#include <asm/io.h>
++#include <asm/mipsregs.h>
++#include <asm/system.h>
++#include <asm/au1000.h>
++#include <asm/ficmmp.h>
++
++au1xxx_irq_map_t au1xxx_irq_map[] = {
++ { FICMMP_IDE_INT, INTC_INT_HIGH_LEVEL, 0 },
++ { AU1XXX_SMC91111_IRQ, INTC_INT_HIGH_LEVEL, 0 },
++ { AU1000_GPIO_1 , INTC_INT_FALL_EDGE, 0 }, // main button
++ { AU1000_GPIO_6 , INTC_INT_RISE_EDGE, 0 }, // select button
++ { AU1000_GPIO_12, INTC_INT_FALL_EDGE, 0 }, // guide button
++ { AU1000_GPIO_17, INTC_INT_RISE_EDGE, 0 }, // down button
++ { AU1000_GPIO_19, INTC_INT_RISE_EDGE, 0 }, // left button
++ { AU1000_GPIO_26, INTC_INT_RISE_EDGE, 0 }, // right button
++ { AU1000_GPIO_28, INTC_INT_RISE_EDGE, 0 }, // up button
++};
++
++int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
++
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/ficmmp/Makefile linux-2.4.32-rc1.mips/arch/mips/au1000/ficmmp/Makefile
+--- linux-2.4.32-rc1/arch/mips/au1000/ficmmp/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/ficmmp/Makefile 2005-01-30 09:01:27.000000000 +0100
+@@ -0,0 +1,25 @@
++#
++# Copyright 2000 MontaVista Software Inc.
++# Author: MontaVista Software, Inc.
++# ppopov@mvista.com or source@mvista.com
++#
++# Makefile for the Alchemy Semiconductor FIC board.
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++
++USE_STANDARD_AS_RULE := true
++
++O_TARGET := ficmmp.o
++
++obj-y := init.o board_setup.o irqmap.o au1200_ibutton.o au1xxx_dock.o
++
++ifdef CONFIG_MMC
++obj-y += mmc_support.o
++export-objs +=mmc_support.o
++endif
++
++
++include $(TOPDIR)/Rules.make
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/hydrogen3/board_setup.c linux-2.4.32-rc1.mips/arch/mips/au1000/hydrogen3/board_setup.c
+--- linux-2.4.32-rc1/arch/mips/au1000/hydrogen3/board_setup.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/hydrogen3/board_setup.c 2005-03-19 08:17:51.000000000 +0100
+@@ -51,12 +51,19 @@
+ {
+ }
+
++void board_power_off (void)
++{
++}
++
+ void __init board_setup(void)
+ {
+ u32 pin_func;
+
+ rtc_ops = &no_rtc_ops;
+
++ /* Set GPIO14 high to make CD/DAT1 high for MMC to work */
++ au_writel(1<<14, SYS_OUTPUTSET);
++
+ #ifdef CONFIG_AU1X00_USB_DEVICE
+ // 2nd USB port is USB device
+ pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/hydrogen3/buttons.c linux-2.4.32-rc1.mips/arch/mips/au1000/hydrogen3/buttons.c
+--- linux-2.4.32-rc1/arch/mips/au1000/hydrogen3/buttons.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/hydrogen3/buttons.c 2005-02-11 22:09:55.000000000 +0100
+@@ -0,0 +1,308 @@
++/*
++ * Copyright (C) 2003 Metrowerks, All Rights Reserved.
++ *
++ * 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/config.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/sched.h>
++#include <linux/miscdevice.h>
++#include <linux/errno.h>
++#include <linux/poll.h>
++#include <asm/au1000.h>
++#include <asm/uaccess.h>
++
++#define BUTTON_SELECT (1<<1)
++#define BUTTON_1 (1<<2)
++#define BUTTON_2 (1<<3)
++#define BUTTON_ONOFF (1<<6)
++#define BUTTON_3 (1<<7)
++#define BUTTON_4 (1<<8)
++#define BUTTON_LEFT (1<<9)
++#define BUTTON_DOWN (1<<10)
++#define BUTTON_RIGHT (1<<11)
++#define BUTTON_UP (1<<12)
++
++#define BUTTON_MASK (\
++ BUTTON_SELECT \
++ | BUTTON_1 \
++ | BUTTON_2 \
++ | BUTTON_ONOFF \
++ | BUTTON_3 \
++ | BUTTON_4 \
++ | BUTTON_LEFT \
++ | BUTTON_DOWN \
++ | BUTTON_RIGHT \
++ | BUTTON_UP \
++ )
++
++#define BUTTON_INVERT (\
++ BUTTON_SELECT \
++ | BUTTON_1 \
++ | BUTTON_2 \
++ | BUTTON_3 \
++ | BUTTON_4 \
++ | BUTTON_LEFT \
++ | BUTTON_DOWN \
++ | BUTTON_RIGHT \
++ | BUTTON_UP \
++ )
++
++
++
++#define MAKE_FLAG 0x20
++
++#undef DEBUG
++
++#define DEBUG 0
++//#define DEBUG 1
++
++#if DEBUG
++#define DPRINTK(format, args...) printk(__FUNCTION__ ": " format, ## args)
++#else
++#define DPRINTK(format, args...) do { } while (0)
++#endif
++
++/* Please note that this driver is based on a timer and is not interrupt
++ * driven. If you are going to make use of this driver, you will need to have
++ * your application open the buttons listing from the /dev directory first.
++ */
++
++struct hydrogen3_buttons {
++ struct fasync_struct *fasync;
++ wait_queue_head_t read_wait;
++ int open_count;
++ unsigned int debounce;
++ unsigned int current;
++ unsigned int last;
++};
++
++static struct hydrogen3_buttons buttons_info;
++
++
++static void button_timer_periodic(void *data);
++
++static struct tq_struct button_task = {
++ routine: button_timer_periodic,
++ data: NULL
++};
++
++static int cleanup_flag = 0;
++static DECLARE_WAIT_QUEUE_HEAD(cleanup_wait_queue);
++
++
++static unsigned int read_button_state(void)
++{
++ unsigned long state;
++
++ state = inl(SYS_PINSTATERD) & BUTTON_MASK;
++ state ^= BUTTON_INVERT;
++
++ DPRINTK( "Current Button State: %d\n", state );
++
++ return state;
++}
++
++
++static void button_timer_periodic(void *data)
++{
++ struct hydrogen3_buttons *buttons = (struct hydrogen3_buttons *)data;
++ unsigned long button_state;
++
++ // If cleanup wants us to die
++ if (cleanup_flag) {
++ wake_up(&cleanup_wait_queue); // now cleanup_module can return
++ } else {
++ queue_task(&button_task, &tq_timer); // put ourselves back in the task queue
++ }
++
++ // read current buttons
++ button_state = read_button_state();
++
++ // if no buttons are down and nothing to do then
++ // save time and be done.
++ if ((button_state == 0) && (buttons->current == 0)) {
++ return;
++ }
++
++ if (button_state == buttons->debounce) {
++ buttons->current = button_state;
++ } else {
++ buttons->debounce = button_state;
++ }
++// printk("0x%04x\n", button_state);
++ if (buttons->current != buttons->last) {
++ if (waitqueue_active(&buttons->read_wait)) {
++ wake_up_interruptible(&buttons->read_wait);
++ }
++ }
++}
++
++
++static ssize_t hydrogen3_buttons_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
++{
++ struct hydrogen3_buttons *buttons = filp->private_data;
++ char events[16];
++ int index;
++ int last;
++ int cur;
++ int bit;
++ int bit_mask;
++ int err;
++
++ DPRINTK("start\n");
++
++try_again:
++
++ while (buttons->current == buttons->last) {
++ if (filp->f_flags & O_NONBLOCK) {
++ return -EAGAIN;
++ }
++ interruptible_sleep_on(&buttons->read_wait);
++ if (signal_pending(current)) {
++ return -ERESTARTSYS;
++ }
++ }
++
++ cur = buttons->current;
++ last = buttons->last;
++
++ index = 0;
++ bit_mask = 1;
++ for (bit = 0; (bit < 16) && count; bit++) {
++ if ((cur ^ last) & bit_mask) {
++ if (cur & bit_mask) {
++ events[index] = (bit | MAKE_FLAG) + 'A';
++ last |= bit_mask;
++ } else {
++ events[index] = bit + 'A';
++ last &= ~bit_mask;
++ }
++ index++;
++ count--;
++ }
++ bit_mask <<= 1;
++ }
++ buttons->last = last;
++
++ if (index == 0) {
++ goto try_again;
++ }
++
++ err = copy_to_user(buffer, events, index);
++ if (err) {
++ return err;
++ }
++
++ return index;
++}
++
++
++static int hydrogen3_buttons_open(struct inode *inode, struct file *filp)
++{
++ struct hydrogen3_buttons *buttons = &buttons_info;
++
++ DPRINTK("start\n");
++ MOD_INC_USE_COUNT;
++
++ filp->private_data = buttons;
++
++ if (buttons->open_count++ == 0) {
++ button_task.data = buttons;
++ cleanup_flag = 0;
++ queue_task(&button_task, &tq_timer);
++ }
++
++ return 0;
++}
++
++
++static unsigned int hydrogen3_buttons_poll(struct file *filp, poll_table *wait)
++{
++ struct hydrogen3_buttons *buttons = filp->private_data;
++ int ret = 0;
++
++ DPRINTK("start\n");
++ poll_wait(filp, &buttons->read_wait, wait);
++ if (buttons->current != buttons->last) {
++ ret = POLLIN | POLLRDNORM;
++ }
++ return ret;
++}
++
++
++static int hydrogen3_buttons_release(struct inode *inode, struct file *filp)
++{
++ struct hydrogen3_buttons *buttons = filp->private_data;
++
++ DPRINTK("start\n");
++
++ if (--buttons->open_count == 0) {
++ cleanup_flag = 1;
++ sleep_on(&cleanup_wait_queue);
++ }
++ MOD_DEC_USE_COUNT;
++
++ return 0;
++}
++
++
++
++static struct file_operations hydrogen3_buttons_fops = {
++ owner: THIS_MODULE,
++ read: hydrogen3_buttons_read,
++ poll: hydrogen3_buttons_poll,
++ open: hydrogen3_buttons_open,
++ release: hydrogen3_buttons_release,
++};
++
++/*
++ * The hydrogen3 buttons is a misc device:
++ * Major 10 char
++ * Minor 22 /dev/buttons
++ *
++ * This is /dev/misc/buttons if devfs is used.
++ */
++
++static struct miscdevice hydrogen3_buttons_dev = {
++ minor: 22,
++ name: "buttons",
++ fops: &hydrogen3_buttons_fops,
++};
++
++static int __init hydrogen3_buttons_init(void)
++{
++ struct hydrogen3_buttons *buttons = &buttons_info;
++ int ret;
++
++ DPRINTK("Initializing buttons driver\n");
++ buttons->open_count = 0;
++ cleanup_flag = 0;
++ init_waitqueue_head(&buttons->read_wait);
++
++
++ // yamon configures GPIO pins for the buttons
++ // no initialization needed
++
++ ret = misc_register(&hydrogen3_buttons_dev);
++
++ DPRINTK("Buttons driver fully initialized.\n");
++
++ return ret;
++}
++
++
++static void __exit hydrogen3_buttons_exit(void)
++{
++ DPRINTK("unloading buttons driver\n");
++ misc_deregister(&hydrogen3_buttons_dev);
++}
++
++
++module_init(hydrogen3_buttons_init);
++module_exit(hydrogen3_buttons_exit);
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/hydrogen3/Makefile linux-2.4.32-rc1.mips/arch/mips/au1000/hydrogen3/Makefile
+--- linux-2.4.32-rc1/arch/mips/au1000/hydrogen3/Makefile 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/hydrogen3/Makefile 2005-02-11 22:09:55.000000000 +0100
+@@ -14,6 +14,11 @@
+
+ O_TARGET := hydrogen3.o
+
+-obj-y := init.o board_setup.o irqmap.o
++obj-y := init.o board_setup.o irqmap.o buttons.o
++
++ifdef CONFIG_MMC
++obj-y += mmc_support.o
++export-objs +=mmc_support.o
++endif
+
+ include $(TOPDIR)/Rules.make
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/hydrogen3/mmc_support.c linux-2.4.32-rc1.mips/arch/mips/au1000/hydrogen3/mmc_support.c
+--- linux-2.4.32-rc1/arch/mips/au1000/hydrogen3/mmc_support.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/hydrogen3/mmc_support.c 2005-02-02 05:27:06.000000000 +0100
+@@ -0,0 +1,89 @@
++/*
++ * BRIEF MODULE DESCRIPTION
++ *
++ * MMC support routines for Hydrogen3.
++ *
++ *
++ * Copyright (c) 2003-2004 Embedded Edge, LLC.
++ * Author: Embedded Edge, LLC.
++ * Contact: dan@embeddededge.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++
++#include <asm/irq.h>
++#include <asm/au1000.h>
++#include <asm/au1100_mmc.h>
++
++#define GPIO_17_WP 0x20000
++
++/* SD/MMC controller support functions */
++
++/*
++ * Detect card.
++ */
++void mmc_card_inserted(int _n_, int *_res_)
++{
++ u32 gpios = au_readl(SYS_PINSTATERD);
++ u32 emptybit = (1<<16);
++ *_res_ = ((gpios & emptybit) == 0);
++}
++
++/*
++ * Check card write protection.
++ */
++void mmc_card_writable(int _n_, int *_res_)
++{
++ unsigned long mmc_wp, board_specific;
++ board_specific = au_readl(SYS_OUTPUTSET);
++ mmc_wp=GPIO_17_WP;
++ if (!(board_specific & mmc_wp)) {/* low means card writable */
++ *_res_ = 1;
++ } else {
++ *_res_ = 0;
++ }
++}
++/*
++ * Apply power to card slot.
++ */
++void mmc_power_on(int _n_)
++{
++}
++
++/*
++ * Remove power from card slot.
++ */
++void mmc_power_off(int _n_)
++{
++}
++
++EXPORT_SYMBOL(mmc_card_inserted);
++EXPORT_SYMBOL(mmc_card_writable);
++EXPORT_SYMBOL(mmc_power_on);
++EXPORT_SYMBOL(mmc_power_off);
++
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/mtx-1/board_setup.c linux-2.4.32-rc1.mips/arch/mips/au1000/mtx-1/board_setup.c
+--- linux-2.4.32-rc1/arch/mips/au1000/mtx-1/board_setup.c 2004-02-18 14:36:30.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/mtx-1/board_setup.c 2004-11-26 09:37:16.000000000 +0100
+@@ -48,6 +48,12 @@
+
+ extern struct rtc_ops no_rtc_ops;
+
++void board_reset (void)
++{
++ /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
++ au_writel(0x00000000, 0xAE00001C);
++}
++
+ void __init board_setup(void)
+ {
+ rtc_ops = &no_rtc_ops;
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/mtx-1/irqmap.c linux-2.4.32-rc1.mips/arch/mips/au1000/mtx-1/irqmap.c
+--- linux-2.4.32-rc1/arch/mips/au1000/mtx-1/irqmap.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/mtx-1/irqmap.c 2004-11-26 09:37:16.000000000 +0100
+@@ -72,10 +72,10 @@
+ * A B C D
+ */
+ {
+- {INTA, INTB, INTC, INTD}, /* IDSEL 0 */
+- {INTA, INTB, INTC, INTD}, /* IDSEL 1 */
+- {INTA, INTB, INTC, INTD}, /* IDSEL 2 */
+- {INTA, INTB, INTC, INTD}, /* IDSEL 3 */
++ {INTA, INTB, INTX, INTX}, /* IDSEL 0 */
++ {INTB, INTA, INTX, INTX}, /* IDSEL 1 */
++ {INTC, INTD, INTX, INTX}, /* IDSEL 2 */
++ {INTD, INTC, INTX, INTX}, /* IDSEL 3 */
+ };
+ const long min_idsel = 0, max_idsel = 3, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/pb1000/board_setup.c linux-2.4.32-rc1.mips/arch/mips/au1000/pb1000/board_setup.c
+--- linux-2.4.32-rc1/arch/mips/au1000/pb1000/board_setup.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/pb1000/board_setup.c 2005-03-19 08:17:51.000000000 +0100
+@@ -58,6 +58,10 @@
+ {
+ }
+
++void board_power_off (void)
++{
++}
++
+ void __init board_setup(void)
+ {
+ u32 pin_func, static_cfg0;
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/pb1100/board_setup.c linux-2.4.32-rc1.mips/arch/mips/au1000/pb1100/board_setup.c
+--- linux-2.4.32-rc1/arch/mips/au1000/pb1100/board_setup.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/pb1100/board_setup.c 2005-03-19 08:17:51.000000000 +0100
+@@ -62,6 +62,10 @@
+ au_writel(0x00000000, 0xAE00001C);
+ }
+
++void board_power_off (void)
++{
++}
++
+ void __init board_setup(void)
+ {
+ u32 pin_func;
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/pb1100/Makefile linux-2.4.32-rc1.mips/arch/mips/au1000/pb1100/Makefile
+--- linux-2.4.32-rc1/arch/mips/au1000/pb1100/Makefile 2003-08-25 13:44:39.000000000 +0200
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/pb1100/Makefile 2005-01-30 09:10:29.000000000 +0100
+@@ -16,4 +16,10 @@
+
+ obj-y := init.o board_setup.o irqmap.o
+
++
++ifdef CONFIG_MMC
++obj-y += mmc_support.o
++export-objs += mmc_support.o
++endif
++
+ include $(TOPDIR)/Rules.make
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/pb1100/mmc_support.c linux-2.4.32-rc1.mips/arch/mips/au1000/pb1100/mmc_support.c
+--- linux-2.4.32-rc1/arch/mips/au1000/pb1100/mmc_support.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/pb1100/mmc_support.c 2005-01-30 09:10:29.000000000 +0100
+@@ -0,0 +1,126 @@
++/*
++ * BRIEF MODULE DESCRIPTION
++ *
++ * MMC support routines for PB1100.
++ *
++ *
++ * Copyright (c) 2003-2004 Embedded Edge, LLC.
++ * Author: Embedded Edge, LLC.
++ * Contact: dan@embeddededge.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++
++#include <asm/irq.h>
++#include <asm/au1000.h>
++#include <asm/au1100_mmc.h>
++#include <asm/pb1100.h>
++
++
++/* SD/MMC controller support functions */
++
++/*
++ * Detect card.
++ */
++void mmc_card_inserted(int _n_, int *_res_)
++{
++ u32 gpios = au_readl(SYS_PINSTATERD);
++ u32 emptybit = (_n_) ? (1<<15) : (1<<14);
++ *_res_ = ((gpios & emptybit) == 0);
++}
++
++/*
++ * Check card write protection.
++ */
++void mmc_card_writable(int _n_, int *_res_)
++{
++ BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
++ unsigned long mmc_wp, board_specific;
++
++ if (_n_) {
++ mmc_wp = BCSR_PCMCIA_SD1_WP;
++ } else {
++ mmc_wp = BCSR_PCMCIA_SD0_WP;
++ }
++
++ board_specific = au_readl((unsigned long)(&bcsr->pcmcia));
++
++ if (!(board_specific & mmc_wp)) {/* low means card writable */
++ *_res_ = 1;
++ } else {
++ *_res_ = 0;
++ }
++}
++
++/*
++ * Apply power to card slot.
++ */
++void mmc_power_on(int _n_)
++{
++ BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
++ unsigned long mmc_pwr, board_specific;
++
++ if (_n_) {
++ mmc_pwr = BCSR_PCMCIA_SD1_PWR;
++ } else {
++ mmc_pwr = BCSR_PCMCIA_SD0_PWR;
++ }
++
++ board_specific = au_readl((unsigned long)(&bcsr->pcmcia));
++ board_specific |= mmc_pwr;
++
++ au_writel(board_specific, (int)(&bcsr->pcmcia));
++ au_sync_delay(1);
++}
++
++/*
++ * Remove power from card slot.
++ */
++void mmc_power_off(int _n_)
++{
++ BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
++ unsigned long mmc_pwr, board_specific;
++
++ if (_n_) {
++ mmc_pwr = BCSR_PCMCIA_SD1_PWR;
++ } else {
++ mmc_pwr = BCSR_PCMCIA_SD0_PWR;
++ }
++
++ board_specific = au_readl((unsigned long)(&bcsr->pcmcia));
++ board_specific &= ~mmc_pwr;
++
++ au_writel(board_specific, (int)(&bcsr->pcmcia));
++ au_sync_delay(1);
++}
++
++EXPORT_SYMBOL(mmc_card_inserted);
++EXPORT_SYMBOL(mmc_card_writable);
++EXPORT_SYMBOL(mmc_power_on);
++EXPORT_SYMBOL(mmc_power_off);
++
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/pb1200/board_setup.c linux-2.4.32-rc1.mips/arch/mips/au1000/pb1200/board_setup.c
+--- linux-2.4.32-rc1/arch/mips/au1000/pb1200/board_setup.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/pb1200/board_setup.c 2005-03-19 08:17:51.000000000 +0100
+@@ -0,0 +1,221 @@
++/*
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Alchemy Pb1200 board setup.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/config.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/ioport.h>
++#include <linux/mm.h>
++#include <linux/console.h>
++#include <linux/mc146818rtc.h>
++#include <linux/delay.h>
++
++#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
++#include <linux/ide.h>
++#endif
++
++#include <asm/cpu.h>
++#include <asm/bootinfo.h>
++#include <asm/irq.h>
++#include <asm/keyboard.h>
++#include <asm/mipsregs.h>
++#include <asm/reboot.h>
++#include <asm/pgtable.h>
++#include <asm/au1000.h>
++#include <asm/au1xxx_dbdma.h>
++
++#ifdef CONFIG_MIPS_PB1200
++#include <asm/pb1200.h>
++#endif
++
++#ifdef CONFIG_MIPS_DB1200
++#include <asm/db1200.h>
++#define PB1200_ETH_INT DB1200_ETH_INT
++#define PB1200_IDE_INT DB1200_IDE_INT
++#endif
++
++extern struct rtc_ops no_rtc_ops;
++
++extern void _board_init_irq(void);
++extern void (*board_init_irq)(void);
++
++#ifdef CONFIG_BLK_DEV_IDE_AU1XXX
++extern struct ide_ops *ide_ops;
++extern struct ide_ops au1xxx_ide_ops;
++extern u32 au1xxx_ide_virtbase;
++extern u64 au1xxx_ide_physbase;
++extern int au1xxx_ide_irq;
++
++u32 led_base_addr;
++/* Ddma */
++chan_tab_t *ide_read_ch, *ide_write_ch;
++u32 au1xxx_ide_ddma_enable = 0, switch4ddma = 1; // PIO+ddma
++
++dbdev_tab_t new_dbdev_tab_element = { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 };
++#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX */
++
++void board_reset (void)
++{
++ bcsr->resets = 0;
++}
++
++void board_power_off (void)
++{
++ bcsr->resets = 0xC000;
++}
++
++void __init board_setup(void)
++{
++ char *argptr = NULL;
++ u32 pin_func;
++ rtc_ops = &no_rtc_ops;
++
++#if 0
++ /* Enable PSC1 SYNC for AC97. Normaly done in audio driver,
++ * but it is board specific code, so put it here.
++ */
++ pin_func = au_readl(SYS_PINFUNC);
++ au_sync();
++ pin_func |= SYS_PF_MUST_BE_SET | SYS_PF_PSC1_S1;
++ au_writel(pin_func, SYS_PINFUNC);
++
++ au_writel(0, (u32)bcsr|0x10); /* turn off pcmcia power */
++ au_sync();
++#endif
++
++#if defined( CONFIG_I2C_ALGO_AU1550 )
++ {
++ u32 freq0, clksrc;
++
++ /* Select SMBUS in CPLD */
++ bcsr->resets &= ~(BCSR_RESETS_PCS0MUX);
++
++ pin_func = au_readl(SYS_PINFUNC);
++ au_sync();
++ pin_func &= ~(3<<17 | 1<<4);
++ /* Set GPIOs correctly */
++ pin_func |= 2<<17;
++ au_writel(pin_func, SYS_PINFUNC);
++ au_sync();
++
++ /* The i2c driver depends on 50Mhz clock */
++ freq0 = au_readl(SYS_FREQCTRL0);
++ au_sync();
++ freq0 &= ~(SYS_FC_FRDIV1_MASK | SYS_FC_FS1 | SYS_FC_FE1);
++ freq0 |= (3<<SYS_FC_FRDIV1_BIT);
++ /* 396Mhz / (3+1)*2 == 49.5Mhz */
++ au_writel(freq0, SYS_FREQCTRL0);
++ au_sync();
++ freq0 |= SYS_FC_FE1;
++ au_writel(freq0, SYS_FREQCTRL0);
++ au_sync();
++
++ clksrc = au_readl(SYS_CLKSRC);
++ au_sync();
++ clksrc &= ~0x01f00000;
++ /* bit 22 is EXTCLK0 for PSC0 */
++ clksrc |= (0x3 << 22);
++ au_writel(clksrc, SYS_CLKSRC);
++ au_sync();
++ }
++#endif
++
++#ifdef CONFIG_FB_AU1200
++ argptr = prom_getcmdline();
++ strcat(argptr, " video=au1200fb:");
++#endif
++
++#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
++ /*
++ * Iniz IDE parameters
++ */
++ ide_ops = &au1xxx_ide_ops;
++ au1xxx_ide_irq = PB1200_IDE_INT;
++ au1xxx_ide_physbase = AU1XXX_ATA_PHYS_ADDR;
++ au1xxx_ide_virtbase = KSEG1ADDR(AU1XXX_ATA_PHYS_ADDR);
++ /*
++ * change PIO or PIO+Ddma
++ * check the GPIO-5 pin condition. pb1200:s18_dot */
++ switch4ddma = (au_readl(SYS_PINSTATERD) & (1 << 5)) ? 1 : 0;
++#endif
++
++ /* The Pb1200 development board uses external MUX for PSC0 to
++ support SMB/SPI. bcsr->resets bit 12: 0=SMB 1=SPI
++ */
++#if defined(CONFIG_AU1550_PSC_SPI) && defined(CONFIG_I2C_ALGO_AU1550)
++ #error I2C and SPI are mutually exclusive. Both are physically connected to PSC0.\
++ Refer to Pb1200/Db1200 documentation.
++#elif defined( CONFIG_AU1550_PSC_SPI )
++ bcsr->resets |= BCSR_RESETS_PCS0MUX;
++#elif defined( CONFIG_I2C_ALGO_AU1550 )
++ bcsr->resets &= (~BCSR_RESETS_PCS0MUX);
++#endif
++ au_sync();
++
++#ifdef CONFIG_MIPS_PB1200
++ printk("AMD Alchemy Pb1200 Board\n");
++#endif
++#ifdef CONFIG_MIPS_DB1200
++ printk("AMD Alchemy Db1200 Board\n");
++#endif
++
++ /* Setup Pb1200 External Interrupt Controller */
++ {
++ extern void (*board_init_irq)(void);
++ extern void _board_init_irq(void);
++ board_init_irq = _board_init_irq;
++ }
++}
++
++int
++board_au1200fb_panel (void)
++{
++ BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR;
++ int p;
++
++ p = bcsr->switches;
++ p >>= 8;
++ p &= 0x0F;
++ return p;
++}
++
++int
++board_au1200fb_panel_init (void)
++{
++ /* Apply power */
++ BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR;
++ bcsr->board |= (BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD | BCSR_BOARD_LCDBL);
++ return 0;
++}
++
++int
++board_au1200fb_panel_shutdown (void)
++{
++ /* Remove power */
++ BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR;
++ bcsr->board &= ~(BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD | BCSR_BOARD_LCDBL);
++ return 0;
++}
++
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/pb1200/init.c linux-2.4.32-rc1.mips/arch/mips/au1000/pb1200/init.c
+--- linux-2.4.32-rc1/arch/mips/au1000/pb1200/init.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/pb1200/init.c 2005-01-30 09:01:28.000000000 +0100
+@@ -0,0 +1,72 @@
++/*
++ *
++ * BRIEF MODULE DESCRIPTION
++ * PB1200 board setup
++ *
++ * 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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/init.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/bootmem.h>
++#include <asm/addrspace.h>
++#include <asm/bootinfo.h>
++#include <linux/config.h>
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++
++int prom_argc;
++char **prom_argv, **prom_envp;
++extern void __init prom_init_cmdline(void);
++extern char *prom_getenv(char *envname);
++
++const char *get_system_type(void)
++{
++ return "AMD Alchemy Au1200/Pb1200";
++}
++
++u32 mae_memsize = 0;
++
++int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
++{
++ unsigned char *memsize_str;
++ unsigned long memsize;
++
++ prom_argc = argc;
++ prom_argv = argv;
++ prom_envp = envp;
++
++ mips_machgroup = MACH_GROUP_ALCHEMY;
++ mips_machtype = MACH_PB1000; /* set the platform # */
++ prom_init_cmdline();
++
++ memsize_str = prom_getenv("memsize");
++ if (!memsize_str) {
++ memsize = 0x08000000;
++ } else {
++ memsize = simple_strtol(memsize_str, NULL, 0);
++ }
++ add_memory_region(0, memsize, BOOT_MEM_RAM);
++ return 0;
++}
++
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/pb1200/irqmap.c linux-2.4.32-rc1.mips/arch/mips/au1000/pb1200/irqmap.c
+--- linux-2.4.32-rc1/arch/mips/au1000/pb1200/irqmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/pb1200/irqmap.c 2005-01-30 09:01:28.000000000 +0100
+@@ -0,0 +1,180 @@
++/*
++ * BRIEF MODULE DESCRIPTION
++ * Au1xxx irq map table
++ *
++ * 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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/errno.h>
++#include <linux/init.h>
++#include <linux/irq.h>
++#include <linux/kernel_stat.h>
++#include <linux/module.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/timex.h>
++#include <linux/slab.h>
++#include <linux/random.h>
++#include <linux/delay.h>
++
++#include <asm/bitops.h>
++#include <asm/bootinfo.h>
++#include <asm/io.h>
++#include <asm/mipsregs.h>
++#include <asm/system.h>
++#include <asm/au1000.h>
++
++#ifdef CONFIG_MIPS_PB1200
++#include <asm/pb1200.h>
++#endif
++
++#ifdef CONFIG_MIPS_DB1200
++#include <asm/db1200.h>
++#define PB1200_INT_BEGIN DB1200_INT_BEGIN
++#define PB1200_INT_END DB1200_INT_END
++#endif
++
++au1xxx_irq_map_t au1xxx_irq_map[] = {
++ { AU1000_GPIO_7, INTC_INT_LOW_LEVEL, 0 }, // This is exteranl interrupt cascade
++};
++
++int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
++
++/*
++ * Support for External interrupts on the PbAu1200 Development platform.
++ */
++static volatile int pb1200_cascade_en=0;
++
++void pb1200_cascade_handler( int irq, void *dev_id, struct pt_regs *regs)
++{
++ unsigned short bisr = bcsr->int_status;
++ int extirq_nr = 0;
++
++ /* Clear all the edge interrupts. This has no effect on level */
++ bcsr->int_status = bisr;
++ for( ; bisr; bisr &= (bisr-1) )
++ {
++ extirq_nr = (PB1200_INT_BEGIN-1) + au_ffs(bisr);
++ /* Ack and dispatch IRQ */
++ do_IRQ(extirq_nr,regs);
++ }
++}
++
++inline void pb1200_enable_irq(unsigned int irq_nr)
++{
++ bcsr->intset_mask = 1<<(irq_nr - PB1200_INT_BEGIN);
++ bcsr->intset = 1<<(irq_nr - PB1200_INT_BEGIN);
++}
++
++inline void pb1200_disable_irq(unsigned int irq_nr)
++{
++ bcsr->intclr_mask = 1<<(irq_nr - PB1200_INT_BEGIN);
++ bcsr->intclr = 1<<(irq_nr - PB1200_INT_BEGIN);
++}
++
++static unsigned int pb1200_startup_irq( unsigned int irq_nr )
++{
++ if (++pb1200_cascade_en == 1)
++ {
++ request_irq(AU1000_GPIO_7, &pb1200_cascade_handler,
++ 0, "Pb1200 Cascade", &pb1200_cascade_handler );
++#ifdef CONFIG_MIPS_PB1200
++ /* We have a problem with CPLD rev3. Enable a workaround */
++ if( ((bcsr->whoami & BCSR_WHOAMI_CPLD)>>4) <= 3)
++ {
++ printk("\nWARNING!!!\n");
++ printk("\nWARNING!!!\n");
++ printk("\nWARNING!!!\n");
++ printk("\nWARNING!!!\n");
++ printk("\nWARNING!!!\n");
++ printk("\nWARNING!!!\n");
++ printk("Pb1200 must be at CPLD rev4. Please have Pb1200\n");
++ printk("updated to latest revision. This software will not\n");
++ printk("work on anything less than CPLD rev4\n");
++ printk("\nWARNING!!!\n");
++ printk("\nWARNING!!!\n");
++ printk("\nWARNING!!!\n");
++ printk("\nWARNING!!!\n");
++ printk("\nWARNING!!!\n");
++ printk("\nWARNING!!!\n");
++ while(1);
++ }
++#endif
++ }
++ pb1200_enable_irq(irq_nr);
++ return 0;
++}
++
++static void pb1200_shutdown_irq( unsigned int irq_nr )
++{
++ pb1200_disable_irq(irq_nr);
++ if (--pb1200_cascade_en == 0)
++ {
++ free_irq(AU1000_GPIO_7,&pb1200_cascade_handler );
++ }
++ return;
++}
++
++static inline void pb1200_mask_and_ack_irq(unsigned int irq_nr)
++{
++ pb1200_disable_irq( irq_nr );
++}
++
++static void pb1200_end_irq(unsigned int irq_nr)
++{
++ if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
++ pb1200_enable_irq(irq_nr);
++ }
++}
++
++static struct hw_interrupt_type external_irq_type =
++{
++#ifdef CONFIG_MIPS_PB1200
++ "Pb1200 Ext",
++#endif
++#ifdef CONFIG_MIPS_DB1200
++ "Db1200 Ext",
++#endif
++ pb1200_startup_irq,
++ pb1200_shutdown_irq,
++ pb1200_enable_irq,
++ pb1200_disable_irq,
++ pb1200_mask_and_ack_irq,
++ pb1200_end_irq,
++ NULL
++};
++
++void _board_init_irq(void)
++{
++ int irq_nr;
++
++ for (irq_nr = PB1200_INT_BEGIN; irq_nr <= PB1200_INT_END; irq_nr++)
++ {
++ irq_desc[irq_nr].handler = &external_irq_type;
++ pb1200_disable_irq(irq_nr);
++ }
++
++ /* GPIO_7 can not be hooked here, so it is hooked upon first
++ request of any source attached to the cascade */
++}
++
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/pb1200/Makefile linux-2.4.32-rc1.mips/arch/mips/au1000/pb1200/Makefile
+--- linux-2.4.32-rc1/arch/mips/au1000/pb1200/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/pb1200/Makefile 2005-01-30 09:01:27.000000000 +0100
+@@ -0,0 +1,25 @@
++#
++# Copyright 2000 MontaVista Software Inc.
++# Author: MontaVista Software, Inc.
++# ppopov@mvista.com or source@mvista.com
++#
++# Makefile for the Alchemy Semiconductor PB1000 board.
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++
++USE_STANDARD_AS_RULE := true
++
++O_TARGET := pb1200.o
++
++obj-y := init.o board_setup.o irqmap.o
++
++ifdef CONFIG_MMC
++obj-y += mmc_support.o
++export-objs +=mmc_support.o
++endif
++
++
++include $(TOPDIR)/Rules.make
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/pb1200/mmc_support.c linux-2.4.32-rc1.mips/arch/mips/au1000/pb1200/mmc_support.c
+--- linux-2.4.32-rc1/arch/mips/au1000/pb1200/mmc_support.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/pb1200/mmc_support.c 2005-01-30 09:01:28.000000000 +0100
+@@ -0,0 +1,141 @@
++/*
++ * BRIEF MODULE DESCRIPTION
++ *
++ * MMC support routines for PB1200.
++ *
++ *
++ * Copyright (c) 2003-2004 Embedded Edge, LLC.
++ * Author: Embedded Edge, LLC.
++ * Contact: dan@embeddededge.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++
++#include <asm/irq.h>
++#include <asm/au1000.h>
++#include <asm/au1100_mmc.h>
++
++#ifdef CONFIG_MIPS_PB1200
++#include <asm/pb1200.h>
++#endif
++
++#ifdef CONFIG_MIPS_DB1200
++/* NOTE: DB1200 only has SD0 pinned out and usable */
++#include <asm/db1200.h>
++#endif
++
++/* SD/MMC controller support functions */
++
++/*
++ * Detect card.
++ */
++void mmc_card_inserted(int socket, int *result)
++{
++ u16 mask;
++
++ if (socket)
++#ifdef CONFIG_MIPS_DB1200
++ mask = 0;
++#else
++ mask = BCSR_INT_SD1INSERT;
++#endif
++ else
++ mask = BCSR_INT_SD0INSERT;
++
++ *result = ((bcsr->sig_status & mask) != 0);
++}
++
++/*
++ * Check card write protection.
++ */
++void mmc_card_writable(int socket, int *result)
++{
++ u16 mask;
++
++ if (socket)
++#ifdef CONFIG_MIPS_DB1200
++ mask = 0;
++#else
++ mask = BCSR_STATUS_SD1WP;
++#endif
++ else
++ mask = BCSR_STATUS_SD0WP;
++
++ /* low means card writable */
++ if (!(bcsr->status & mask)) {
++ *result = 1;
++ } else {
++ *result = 0;
++ }
++}
++
++/*
++ * Apply power to card slot.
++ */
++void mmc_power_on(int socket)
++{
++ u16 mask;
++
++ if (socket)
++#ifdef CONFIG_MIPS_DB1200
++ mask = 0;
++#else
++ mask = BCSR_BOARD_SD1PWR;
++#endif
++ else
++ mask = BCSR_BOARD_SD0PWR;
++
++ bcsr->board |= mask;
++ au_sync_delay(1);
++}
++
++/*
++ * Remove power from card slot.
++ */
++void mmc_power_off(int socket)
++{
++ u16 mask;
++
++ if (socket)
++#ifdef CONFIG_MIPS_DB1200
++ mask = 0;
++#else
++ mask = BCSR_BOARD_SD1PWR;
++#endif
++ else
++ mask = BCSR_BOARD_SD0PWR;
++
++ bcsr->board &= ~mask;
++ au_sync_delay(1);
++}
++
++EXPORT_SYMBOL(mmc_card_inserted);
++EXPORT_SYMBOL(mmc_card_writable);
++EXPORT_SYMBOL(mmc_power_on);
++EXPORT_SYMBOL(mmc_power_off);
++
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/pb1500/board_setup.c linux-2.4.32-rc1.mips/arch/mips/au1000/pb1500/board_setup.c
+--- linux-2.4.32-rc1/arch/mips/au1000/pb1500/board_setup.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/pb1500/board_setup.c 2005-03-19 08:17:51.000000000 +0100
+@@ -62,6 +62,10 @@
+ au_writel(0x00000000, 0xAE00001C);
+ }
+
++void board_power_off (void)
++{
++}
++
+ void __init board_setup(void)
+ {
+ u32 pin_func;
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/pb1550/board_setup.c linux-2.4.32-rc1.mips/arch/mips/au1000/pb1550/board_setup.c
+--- linux-2.4.32-rc1/arch/mips/au1000/pb1550/board_setup.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/pb1550/board_setup.c 2005-03-19 08:17:51.000000000 +0100
+@@ -48,12 +48,31 @@
+
+ extern struct rtc_ops no_rtc_ops;
+
++#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
++extern struct ide_ops *ide_ops;
++extern struct ide_ops au1xxx_ide_ops;
++extern u32 au1xxx_ide_virtbase;
++extern u64 au1xxx_ide_physbase;
++extern unsigned int au1xxx_ide_irq;
++
++u32 au1xxx_ide_ddma_enable = 0, switch4ddma = 1; // PIO+ddma
++#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX */
++
+ void board_reset (void)
+ {
+ /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
+ au_writew(au_readw(0xAF00001C) & ~(1<<15), 0xAF00001C);
+ }
+
++void board_power_off (void)
++{
++ /* power off system */
++ printk("\n** Powering off Pb1550\n");
++ au_writew(au_readw(0xAF00001C) | (3<<14), 0xAF00001C);
++ au_sync();
++ while(1); /* should not get here */
++}
++
+ void __init board_setup(void)
+ {
+ u32 pin_func;
+@@ -78,5 +97,36 @@
+ au_writel(0, (u32)bcsr|0x10); /* turn off pcmcia power */
+ au_sync();
+
++#if defined(CONFIG_AU1XXX_SMC91111)
++#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
++#error "Resource conflict occured. Disable either Ethernet or IDE daughter card."
++#else
++#define CPLD_CONTROL (0xAF00000C)
++ {
++ /* set up the Static Bus timing */
++ /* only 396Mhz */
++ /* reset the DC */
++ au_writew(au_readw(CPLD_CONTROL) | 0x0f, CPLD_CONTROL);
++ au_writel(0x00010003, MEM_STCFG0);
++ au_writel(0x000c00c0, MEM_STCFG2);
++ au_writel(0x85E1900D, MEM_STTIME2);
++ }
++#endif
++#endif /* end CONFIG_SMC91111 */
++
++#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
++ /*
++ * Iniz IDE parameters
++ */
++ ide_ops = &au1xxx_ide_ops;
++ au1xxx_ide_irq = DAUGHTER_CARD_IRQ;;
++ au1xxx_ide_physbase = AU1XXX_ATA_PHYS_ADDR;
++ au1xxx_ide_virtbase = KSEG1ADDR(AU1XXX_ATA_PHYS_ADDR);
++ /*
++ * change PIO or PIO+Ddma
++ * check the GPIO-6 pin condition. pb1550:s15_dot
++ */
++ switch4ddma = (au_readl(SYS_PINSTATERD) & (1 << 6)) ? 1 : 0;
++#endif
+ printk("AMD Alchemy Pb1550 Board\n");
+ }
+diff -Nur linux-2.4.32-rc1/arch/mips/au1000/pb1550/irqmap.c linux-2.4.32-rc1.mips/arch/mips/au1000/pb1550/irqmap.c
+--- linux-2.4.32-rc1/arch/mips/au1000/pb1550/irqmap.c 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/au1000/pb1550/irqmap.c 2005-01-30 09:01:28.000000000 +0100
+@@ -50,6 +50,9 @@
+ au1xxx_irq_map_t au1xxx_irq_map[] = {
+ { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
+ { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
++#ifdef CONFIG_AU1XXX_SMC91111
++ { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 },
++#endif
+ };
+
+ int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+diff -Nur linux-2.4.32-rc1/arch/mips/config-shared.in linux-2.4.32-rc1.mips/arch/mips/config-shared.in
+--- linux-2.4.32-rc1/arch/mips/config-shared.in 2005-01-19 15:09:27.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/config-shared.in 2005-01-30 09:01:26.000000000 +0100
+@@ -21,16 +21,19 @@
+ comment 'Machine selection'
+ dep_bool 'Support for Acer PICA 1 chipset (EXPERIMENTAL)' CONFIG_ACER_PICA_61 $CONFIG_EXPERIMENTAL
+ dep_bool 'Support for Alchemy Bosporus board' CONFIG_MIPS_BOSPORUS $CONFIG_MIPS32
++dep_bool 'Support for FIC Multimedia Player board' CONFIG_MIPS_FICMMP $CONFIG_MIPS32
+ dep_bool 'Support for Alchemy Mirage board' CONFIG_MIPS_MIRAGE $CONFIG_MIPS32
+ dep_bool 'Support for Alchemy Db1000 board' CONFIG_MIPS_DB1000 $CONFIG_MIPS32
+ dep_bool 'Support for Alchemy Db1100 board' CONFIG_MIPS_DB1100 $CONFIG_MIPS32
+ dep_bool 'Support for Alchemy Db1500 board' CONFIG_MIPS_DB1500 $CONFIG_MIPS32
+ dep_bool 'Support for Alchemy Db1550 board' CONFIG_MIPS_DB1550 $CONFIG_MIPS32
++dep_bool 'Support for Alchemy Db1200 board' CONFIG_MIPS_DB1200 $CONFIG_MIPS32
+ dep_bool 'Support for Alchemy PB1000 board' CONFIG_MIPS_PB1000 $CONFIG_MIPS32
+ dep_bool 'Support for Alchemy PB1100 board' CONFIG_MIPS_PB1100 $CONFIG_MIPS32
+ dep_bool 'Support for Alchemy PB1500 board' CONFIG_MIPS_PB1500 $CONFIG_MIPS32
+-dep_bool 'Support for Alchemy Hydrogen3 board' CONFIG_MIPS_HYDROGEN3 $CONFIG_MIPS32
+ dep_bool 'Support for Alchemy PB1550 board' CONFIG_MIPS_PB1550 $CONFIG_MIPS32
++dep_bool 'Support for Alchemy PB1200 board' CONFIG_MIPS_PB1200 $CONFIG_MIPS32
++dep_bool 'Support for Alchemy Hydrogen3 board' CONFIG_MIPS_HYDROGEN3 $CONFIG_MIPS32
+ dep_bool 'Support for MyCable XXS1500 board' CONFIG_MIPS_XXS1500 $CONFIG_MIPS32
+ dep_bool 'Support for 4G Systems MTX-1 board' CONFIG_MIPS_MTX1 $CONFIG_MIPS32
+ dep_bool 'Support for Cogent CSB250 board' CONFIG_COGENT_CSB250 $CONFIG_MIPS32
+@@ -249,6 +252,12 @@
+ define_bool CONFIG_PC_KEYB y
+ define_bool CONFIG_NONCOHERENT_IO y
+ fi
++if [ "$CONFIG_MIPS_FICMMP" = "y" ]; then
++ define_bool CONFIG_SOC_AU1X00 y
++ define_bool CONFIG_SOC_AU1200 y
++ define_bool CONFIG_NONCOHERENT_IO y
++ define_bool CONFIG_PC_KEYB y
++fi
+ if [ "$CONFIG_MIPS_BOSPORUS" = "y" ]; then
+ define_bool CONFIG_SOC_AU1X00 y
+ define_bool CONFIG_SOC_AU1500 y
+@@ -263,6 +272,12 @@
+ define_bool CONFIG_SWAP_IO_SPACE_W y
+ define_bool CONFIG_SWAP_IO_SPACE_L y
+ fi
++if [ "$CONFIG_MIPS_PB1500" = "y" ]; then
++ define_bool CONFIG_SOC_AU1X00 y
++ define_bool CONFIG_SOC_AU1500 y
++ define_bool CONFIG_NONCOHERENT_IO y
++ define_bool CONFIG_PC_KEYB y
++fi
+ if [ "$CONFIG_MIPS_PB1100" = "y" ]; then
+ define_bool CONFIG_SOC_AU1X00 y
+ define_bool CONFIG_SOC_AU1100 y
+@@ -271,9 +286,15 @@
+ define_bool CONFIG_SWAP_IO_SPACE_W y
+ define_bool CONFIG_SWAP_IO_SPACE_L y
+ fi
+-if [ "$CONFIG_MIPS_PB1500" = "y" ]; then
++if [ "$CONFIG_MIPS_PB1550" = "y" ]; then
+ define_bool CONFIG_SOC_AU1X00 y
+- define_bool CONFIG_SOC_AU1500 y
++ define_bool CONFIG_SOC_AU1550 y
++ define_bool CONFIG_NONCOHERENT_IO n
++ define_bool CONFIG_PC_KEYB y
++fi
++if [ "$CONFIG_MIPS_PB1200" = "y" ]; then
++ define_bool CONFIG_SOC_AU1X00 y
++ define_bool CONFIG_SOC_AU1200 y
+ define_bool CONFIG_NONCOHERENT_IO y
+ define_bool CONFIG_PC_KEYB y
+ fi
+@@ -290,18 +311,24 @@
+ define_bool CONFIG_NONCOHERENT_IO y
+ define_bool CONFIG_PC_KEYB y
+ fi
++if [ "$CONFIG_MIPS_DB1100" = "y" ]; then
++ define_bool CONFIG_SOC_AU1X00 y
++ define_bool CONFIG_SOC_AU1100 y
++ define_bool CONFIG_NONCOHERENT_IO y
++ define_bool CONFIG_PC_KEYB y
++ define_bool CONFIG_SWAP_IO_SPACE y
++fi
+ if [ "$CONFIG_MIPS_DB1550" = "y" ]; then
+ define_bool CONFIG_SOC_AU1X00 y
+ define_bool CONFIG_SOC_AU1550 y
+ define_bool CONFIG_NONCOHERENT_IO y
+ define_bool CONFIG_PC_KEYB y
+ fi
+-if [ "$CONFIG_MIPS_DB1100" = "y" ]; then
++if [ "$CONFIG_MIPS_DB1200" = "y" ]; then
+ define_bool CONFIG_SOC_AU1X00 y
+- define_bool CONFIG_SOC_AU1100 y
++ define_bool CONFIG_SOC_AU1200 y
+ define_bool CONFIG_NONCOHERENT_IO y
+ define_bool CONFIG_PC_KEYB y
+- define_bool CONFIG_SWAP_IO_SPACE y
+ fi
+ if [ "$CONFIG_MIPS_HYDROGEN3" = "y" ]; then
+ define_bool CONFIG_SOC_AU1X00 y
+@@ -327,12 +354,6 @@
+ define_bool CONFIG_NONCOHERENT_IO y
+ define_bool CONFIG_PC_KEYB y
+ fi
+-if [ "$CONFIG_MIPS_PB1550" = "y" ]; then
+- define_bool CONFIG_SOC_AU1X00 y
+- define_bool CONFIG_SOC_AU1550 y
+- define_bool CONFIG_NONCOHERENT_IO n
+- define_bool CONFIG_PC_KEYB y
+-fi
+ if [ "$CONFIG_MIPS_COBALT" = "y" ]; then
+ define_bool CONFIG_BOOT_ELF32 y
+ define_bool CONFIG_COBALT_LCD y
+@@ -729,6 +750,13 @@
+ "$CONFIG_MIPS_PB1000" = "y" -o \
+ "$CONFIG_MIPS_PB1100" = "y" -o \
+ "$CONFIG_MIPS_PB1500" = "y" -o \
++ "$CONFIG_MIPS_PB1550" = "y" -o \
++ "$CONFIG_MIPS_PB1200" = "y" -o \
++ "$CONFIG_MIPS_DB1000" = "y" -o \
++ "$CONFIG_MIPS_DB1100" = "y" -o \
++ "$CONFIG_MIPS_DB1500" = "y" -o \
++ "$CONFIG_MIPS_DB1550" = "y" -o \
++ "$CONFIG_MIPS_DB1200" = "y" -o \
+ "$CONFIG_NEC_OSPREY" = "y" -o \
+ "$CONFIG_NEC_EAGLE" = "y" -o \
+ "$CONFIG_NINO" = "y" -o \
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig linux-2.4.32-rc1.mips/arch/mips/defconfig
+--- linux-2.4.32-rc1/arch/mips/defconfig 2005-01-19 15:09:27.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -235,11 +235,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -319,9 +314,11 @@
+ # CONFIG_SCSI_MEGARAID is not set
+ # CONFIG_SCSI_MEGARAID2 is not set
+ # CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ # CONFIG_SCSI_ATA_PIIX is not set
+ # CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
+ # CONFIG_SCSI_SATA_PROMISE is not set
+ # CONFIG_SCSI_SATA_SX4 is not set
+ # CONFIG_SCSI_SATA_SIL is not set
+@@ -465,7 +462,6 @@
+ # CONFIG_SERIAL is not set
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-atlas linux-2.4.32-rc1.mips/arch/mips/defconfig-atlas
+--- linux-2.4.32-rc1/arch/mips/defconfig-atlas 2005-01-19 15:09:27.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-atlas 2005-03-18 13:13:21.000000000 +0100
+@@ -28,8 +28,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -235,11 +235,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -317,9 +312,11 @@
+ # CONFIG_SCSI_MEGARAID is not set
+ # CONFIG_SCSI_MEGARAID2 is not set
+ # CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ # CONFIG_SCSI_ATA_PIIX is not set
+ # CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
+ # CONFIG_SCSI_SATA_PROMISE is not set
+ # CONFIG_SCSI_SATA_SX4 is not set
+ # CONFIG_SCSI_SATA_SIL is not set
+@@ -528,7 +525,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-bosporus linux-2.4.32-rc1.mips/arch/mips/defconfig-bosporus
+--- linux-2.4.32-rc1/arch/mips/defconfig-bosporus 2005-01-19 15:09:27.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-bosporus 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -208,9 +208,7 @@
+ CONFIG_MTD_BOSPORUS=y
+ # CONFIG_MTD_XXS1500 is not set
+ # CONFIG_MTD_MTX1 is not set
+-# CONFIG_MTD_DB1X00 is not set
+ # CONFIG_MTD_PB1550 is not set
+-# CONFIG_MTD_HYDROGEN3 is not set
+ # CONFIG_MTD_MIRAGE is not set
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ # CONFIG_MTD_OCELOT is not set
+@@ -229,7 +227,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOCPROBE is not set
+@@ -373,11 +370,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -457,9 +449,11 @@
+ # CONFIG_SCSI_MEGARAID is not set
+ # CONFIG_SCSI_MEGARAID2 is not set
+ # CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ # CONFIG_SCSI_ATA_PIIX is not set
+ # CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
+ # CONFIG_SCSI_SATA_PROMISE is not set
+ # CONFIG_SCSI_SATA_SX4 is not set
+ # CONFIG_SCSI_SATA_SIL is not set
+@@ -681,7 +675,6 @@
+ # CONFIG_AU1X00_USB_TTY is not set
+ # CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-capcella linux-2.4.32-rc1.mips/arch/mips/defconfig-capcella
+--- linux-2.4.32-rc1/arch/mips/defconfig-capcella 2005-01-19 15:09:27.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-capcella 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -228,11 +228,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -472,7 +467,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ # CONFIG_VR41XX_KIU is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-cobalt linux-2.4.32-rc1.mips/arch/mips/defconfig-cobalt
+--- linux-2.4.32-rc1/arch/mips/defconfig-cobalt 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-cobalt 2005-03-18 13:13:21.000000000 +0100
+@@ -28,8 +28,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -222,11 +222,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -505,7 +500,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=16
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-csb250 linux-2.4.32-rc1.mips/arch/mips/defconfig-csb250
+--- linux-2.4.32-rc1/arch/mips/defconfig-csb250 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-csb250 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ CONFIG_COGENT_CSB250=y
+@@ -268,11 +268,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -556,7 +551,6 @@
+ # CONFIG_AU1X00_USB_TTY is not set
+ # CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-db1000 linux-2.4.32-rc1.mips/arch/mips/defconfig-db1000
+--- linux-2.4.32-rc1/arch/mips/defconfig-db1000 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-db1000 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -214,11 +214,7 @@
+ # CONFIG_MTD_BOSPORUS is not set
+ # CONFIG_MTD_XXS1500 is not set
+ # CONFIG_MTD_MTX1 is not set
+-CONFIG_MTD_DB1X00=y
+-CONFIG_MTD_DB1X00_BOOT=y
+-CONFIG_MTD_DB1X00_USER=y
+ # CONFIG_MTD_PB1550 is not set
+-# CONFIG_MTD_HYDROGEN3 is not set
+ # CONFIG_MTD_MIRAGE is not set
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ # CONFIG_MTD_OCELOT is not set
+@@ -237,7 +233,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOCPROBE is not set
+@@ -342,11 +337,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -636,7 +626,6 @@
+ # CONFIG_AU1X00_USB_TTY is not set
+ # CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-db1100 linux-2.4.32-rc1.mips/arch/mips/defconfig-db1100
+--- linux-2.4.32-rc1/arch/mips/defconfig-db1100 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-db1100 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -214,11 +214,7 @@
+ # CONFIG_MTD_BOSPORUS is not set
+ # CONFIG_MTD_XXS1500 is not set
+ # CONFIG_MTD_MTX1 is not set
+-CONFIG_MTD_DB1X00=y
+-# CONFIG_MTD_DB1X00_BOOT is not set
+-CONFIG_MTD_DB1X00_USER=y
+ # CONFIG_MTD_PB1550 is not set
+-# CONFIG_MTD_HYDROGEN3 is not set
+ # CONFIG_MTD_MIRAGE is not set
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ # CONFIG_MTD_OCELOT is not set
+@@ -237,7 +233,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOCPROBE is not set
+@@ -342,11 +337,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -636,7 +626,6 @@
+ # CONFIG_AU1X00_USB_TTY is not set
+ # CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+@@ -884,6 +873,7 @@
+ # CONFIG_FB_PM2 is not set
+ # CONFIG_FB_PM3 is not set
+ # CONFIG_FB_CYBER2000 is not set
++CONFIG_FB_AU1100=y
+ # CONFIG_FB_MATROX is not set
+ # CONFIG_FB_ATY is not set
+ # CONFIG_FB_RADEON is not set
+@@ -895,7 +885,6 @@
+ # CONFIG_FB_VOODOO1 is not set
+ # CONFIG_FB_TRIDENT is not set
+ # CONFIG_FB_E1356 is not set
+-CONFIG_FB_AU1100=y
+ # CONFIG_FB_IT8181 is not set
+ # CONFIG_FB_VIRTUAL is not set
+ CONFIG_FBCON_ADVANCED=y
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-db1200 linux-2.4.32-rc1.mips/arch/mips/defconfig-db1200
+--- linux-2.4.32-rc1/arch/mips/defconfig-db1200 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-db1200 2005-03-18 13:13:21.000000000 +0100
+@@ -0,0 +1,1032 @@
++#
++# Automatically generated make config: don't edit
++#
++CONFIG_MIPS=y
++CONFIG_MIPS32=y
++# CONFIG_MIPS64 is not set
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++# CONFIG_MODVERSIONS is not set
++CONFIG_KMOD=y
++
++#
++# Machine selection
++#
++# CONFIG_ACER_PICA_61 is not set
++# CONFIG_MIPS_BOSPORUS is not set
++# CONFIG_MIPS_MIRAGE is not set
++# CONFIG_MIPS_DB1000 is not set
++# CONFIG_MIPS_DB1100 is not set
++# CONFIG_MIPS_DB1500 is not set
++# CONFIG_MIPS_DB1550 is not set
++# CONFIG_MIPS_PB1000 is not set
++# CONFIG_MIPS_PB1100 is not set
++# CONFIG_MIPS_PB1500 is not set
++# CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
++# CONFIG_MIPS_XXS1500 is not set
++# CONFIG_MIPS_MTX1 is not set
++# CONFIG_COGENT_CSB250 is not set
++# CONFIG_BAGET_MIPS is not set
++# CONFIG_CASIO_E55 is not set
++# CONFIG_MIPS_COBALT is not set
++# CONFIG_DECSTATION is not set
++# CONFIG_MIPS_EV64120 is not set
++# CONFIG_MIPS_EV96100 is not set
++# CONFIG_MIPS_IVR is not set
++# CONFIG_HP_LASERJET is not set
++# CONFIG_IBM_WORKPAD is not set
++# CONFIG_LASAT is not set
++# CONFIG_MIPS_ITE8172 is not set
++# CONFIG_MIPS_ATLAS is not set
++# CONFIG_MIPS_MAGNUM_4000 is not set
++# CONFIG_MIPS_MALTA is not set
++# CONFIG_MIPS_SEAD is not set
++# CONFIG_MOMENCO_OCELOT is not set
++# CONFIG_MOMENCO_OCELOT_G is not set
++# CONFIG_MOMENCO_OCELOT_C is not set
++# CONFIG_MOMENCO_JAGUAR_ATX is not set
++# CONFIG_PMC_BIG_SUR is not set
++# CONFIG_PMC_STRETCH is not set
++# CONFIG_PMC_YOSEMITE is not set
++# CONFIG_DDB5074 is not set
++# CONFIG_DDB5476 is not set
++# CONFIG_DDB5477 is not set
++# CONFIG_NEC_OSPREY is not set
++# CONFIG_NEC_EAGLE is not set
++# CONFIG_OLIVETTI_M700 is not set
++# CONFIG_NINO is not set
++# CONFIG_SGI_IP22 is not set
++# CONFIG_SGI_IP27 is not set
++# CONFIG_SIBYTE_SB1xxx_SOC is not set
++# CONFIG_SNI_RM200_PCI is not set
++# CONFIG_TANBAC_TB0226 is not set
++# CONFIG_TANBAC_TB0229 is not set
++# CONFIG_TOSHIBA_JMR3927 is not set
++# CONFIG_TOSHIBA_RBTX4927 is not set
++# CONFIG_VICTOR_MPC30X is not set
++# CONFIG_ZAO_CAPCELLA is not set
++# CONFIG_HIGHMEM is not set
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++# CONFIG_MIPS_AU1000 is not set
++
++#
++# CPU selection
++#
++CONFIG_CPU_MIPS32=y
++# CONFIG_CPU_MIPS64 is not set
++# CONFIG_CPU_R3000 is not set
++# CONFIG_CPU_TX39XX is not set
++# CONFIG_CPU_VR41XX is not set
++# CONFIG_CPU_R4300 is not set
++# CONFIG_CPU_R4X00 is not set
++# CONFIG_CPU_TX49XX is not set
++# CONFIG_CPU_R5000 is not set
++# CONFIG_CPU_R5432 is not set
++# CONFIG_CPU_R6000 is not set
++# CONFIG_CPU_NEVADA is not set
++# CONFIG_CPU_R8000 is not set
++# CONFIG_CPU_R10000 is not set
++# CONFIG_CPU_RM7000 is not set
++# CONFIG_CPU_RM9000 is not set
++# CONFIG_CPU_SB1 is not set
++CONFIG_PAGE_SIZE_4KB=y
++# CONFIG_PAGE_SIZE_16KB is not set
++# CONFIG_PAGE_SIZE_64KB is not set
++CONFIG_CPU_HAS_PREFETCH=y
++# CONFIG_VTAG_ICACHE is not set
++CONFIG_64BIT_PHYS_ADDR=y
++# CONFIG_CPU_ADVANCED is not set
++CONFIG_CPU_HAS_LLSC=y
++# CONFIG_CPU_HAS_LLDSCD is not set
++# CONFIG_CPU_HAS_WB is not set
++CONFIG_CPU_HAS_SYNC=y
++
++#
++# General setup
++#
++CONFIG_CPU_LITTLE_ENDIAN=y
++# CONFIG_BUILD_ELF64 is not set
++CONFIG_NET=y
++CONFIG_PCI=y
++CONFIG_PCI_NEW=y
++CONFIG_PCI_AUTO=y
++# CONFIG_PCI_NAMES is not set
++# CONFIG_ISA is not set
++# CONFIG_TC is not set
++# CONFIG_MCA is not set
++# CONFIG_SBUS is not set
++CONFIG_HOTPLUG=y
++
++#
++# PCMCIA/CardBus support
++#
++CONFIG_PCMCIA=m
++# CONFIG_CARDBUS is not set
++# CONFIG_TCIC is not set
++# CONFIG_I82092 is not set
++# CONFIG_I82365 is not set
++
++#
++# PCI Hotplug Support
++#
++# CONFIG_HOTPLUG_PCI is not set
++# CONFIG_HOTPLUG_PCI_COMPAQ is not set
++# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
++# CONFIG_HOTPLUG_PCI_SHPC is not set
++# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set
++# CONFIG_HOTPLUG_PCI_PCIE is not set
++# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
++CONFIG_SYSVIPC=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++CONFIG_SYSCTL=y
++CONFIG_KCORE_ELF=y
++# CONFIG_KCORE_AOUT is not set
++# CONFIG_BINFMT_AOUT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_MIPS32_COMPAT is not set
++# CONFIG_MIPS32_O32 is not set
++# CONFIG_MIPS32_N32 is not set
++# CONFIG_BINFMT_ELF32 is not set
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_OOM_KILLER is not set
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE="mem=96M"
++
++#
++# Memory Technology Devices (MTD)
++#
++# CONFIG_MTD is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play configuration
++#
++# CONFIG_PNP is not set
++# CONFIG_ISAPNP is not set
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_XD is not set
++# CONFIG_PARIDE is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_CISS_SCSI_TAPE is not set
++# CONFIG_CISS_MONITOR_THREAD is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_RAM is not set
++# CONFIG_BLK_DEV_INITRD is not set
++# CONFIG_BLK_STATS is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++# CONFIG_BLK_DEV_MD is not set
++# CONFIG_MD_LINEAR is not set
++# CONFIG_MD_RAID0 is not set
++# CONFIG_MD_RAID1 is not set
++# CONFIG_MD_RAID5 is not set
++# CONFIG_MD_MULTIPATH is not set
++# CONFIG_BLK_DEV_LVM is not set
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++# CONFIG_NETLINK_DEV is not set
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++CONFIG_FILTER=y
++CONFIG_UNIX=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_PNP=y
++# CONFIG_IP_PNP_DHCP is not set
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_INET_ECN is not set
++# CONFIG_SYN_COOKIES is not set
++
++#
++# IP: Netfilter Configuration
++#
++# CONFIG_IP_NF_CONNTRACK is not set
++# CONFIG_IP_NF_QUEUE is not set
++# CONFIG_IP_NF_IPTABLES is not set
++# CONFIG_IP_NF_ARPTABLES is not set
++# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
++# CONFIG_IP_NF_COMPAT_IPFWADM is not set
++
++#
++# IP: Virtual Server Configuration
++#
++# CONFIG_IP_VS is not set
++# CONFIG_IPV6 is not set
++# CONFIG_KHTTPD is not set
++
++#
++# SCTP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_SCTP is not set
++# CONFIG_ATM is not set
++# CONFIG_VLAN_8021Q is not set
++
++#
++#
++#
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_DECNET is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_LLC is not set
++# CONFIG_NET_DIVERT is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_FASTROUTE is not set
++# CONFIG_NET_HW_FLOWCONTROL is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++
++#
++# Telephony Support
++#
++# CONFIG_PHONE is not set
++# CONFIG_PHONE_IXJ is not set
++# CONFIG_PHONE_IXJ_PCMCIA is not set
++
++#
++# ATA/IDE/MFM/RLL support
++#
++CONFIG_IDE=y
++
++#
++# IDE, ATA and ATAPI Block devices
++#
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_HD_IDE is not set
++# CONFIG_BLK_DEV_HD is not set
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++CONFIG_IDEDISK_MULTI_MODE=y
++CONFIG_IDEDISK_STROKE=y
++CONFIG_BLK_DEV_IDECS=m
++# CONFIG_BLK_DEV_DELKIN is not set
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_BLK_DEV_IDESCSI is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++
++#
++# IDE chipset support/bugfixes
++#
++# CONFIG_BLK_DEV_CMD640 is not set
++# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
++# CONFIG_BLK_DEV_ISAPNP is not set
++# CONFIG_BLK_DEV_IDEPCI is not set
++# CONFIG_IDE_CHIPSETS is not set
++# CONFIG_IDEDMA_AUTO is not set
++# CONFIG_DMA_NONPCI is not set
++# CONFIG_BLK_DEV_ATARAID is not set
++# CONFIG_BLK_DEV_ATARAID_PDC is not set
++# CONFIG_BLK_DEV_ATARAID_HPT is not set
++# CONFIG_BLK_DEV_ATARAID_MEDLEY is not set
++# CONFIG_BLK_DEV_ATARAID_SII is not set
++
++#
++# SCSI support
++#
++CONFIG_SCSI=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++CONFIG_SD_EXTRA_DEVS=40
++CONFIG_CHR_DEV_ST=y
++# CONFIG_CHR_DEV_OSST is not set
++CONFIG_BLK_DEV_SR=y
++# CONFIG_BLK_DEV_SR_VENDOR is not set
++CONFIG_SR_EXTRA_DEVS=2
++# CONFIG_CHR_DEV_SG is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_DEBUG_QUEUES is not set
++# CONFIG_SCSI_MULTI_LUN is not set
++CONFIG_SCSI_CONSTANTS=y
++# CONFIG_SCSI_LOGGING is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_7000FASST is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AHA152X is not set
++# CONFIG_SCSI_AHA1542 is not set
++# CONFIG_SCSI_AHA1740 is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_IN2000 is not set
++# CONFIG_SCSI_AM53C974 is not set
++# CONFIG_SCSI_MEGARAID is not set
++# CONFIG_SCSI_MEGARAID2 is not set
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
++# CONFIG_SCSI_SATA_SVW is not set
++# CONFIG_SCSI_ATA_PIIX is not set
++# CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
++# CONFIG_SCSI_SATA_PROMISE is not set
++# CONFIG_SCSI_SATA_SX4 is not set
++# CONFIG_SCSI_SATA_SIL is not set
++# CONFIG_SCSI_SATA_SIS is not set
++# CONFIG_SCSI_SATA_ULI is not set
++# CONFIG_SCSI_SATA_VIA is not set
++# CONFIG_SCSI_SATA_VITESSE is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_CPQFCTS is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_DTC3280 is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_EATA_DMA is not set
++# CONFIG_SCSI_EATA_PIO is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_GENERIC_NCR5380 is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_NCR53C406A is not set
++# CONFIG_SCSI_NCR53C7xx is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_NCR53C8XX is not set
++# CONFIG_SCSI_SYM53C8XX is not set
++# CONFIG_SCSI_PAS16 is not set
++# CONFIG_SCSI_PCI2000 is not set
++# CONFIG_SCSI_PCI2220I is not set
++# CONFIG_SCSI_PSI240I is not set
++# CONFIG_SCSI_QLOGIC_FAS is not set
++# CONFIG_SCSI_QLOGIC_ISP is not set
++# CONFIG_SCSI_QLOGIC_FC is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_SIM710 is not set
++# CONFIG_SCSI_SYM53C416 is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_T128 is not set
++# CONFIG_SCSI_U14_34F is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# PCMCIA SCSI adapter support
++#
++# CONFIG_SCSI_PCMCIA is not set
++
++#
++# Fusion MPT device support
++#
++# CONFIG_FUSION is not set
++# CONFIG_FUSION_BOOT is not set
++# CONFIG_FUSION_ISENSE is not set
++# CONFIG_FUSION_CTL is not set
++# CONFIG_FUSION_LAN is not set
++
++#
++# IEEE 1394 (FireWire) support (EXPERIMENTAL)
++#
++# CONFIG_IEEE1394 is not set
++
++#
++# I2O device support
++#
++# CONFIG_I2O is not set
++# CONFIG_I2O_PCI is not set
++# CONFIG_I2O_BLOCK is not set
++# CONFIG_I2O_LAN is not set
++# CONFIG_I2O_SCSI is not set
++# CONFIG_I2O_PROC is not set
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++
++#
++# ARCnet devices
++#
++# CONFIG_ARCNET is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_ETHERTAP is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++# CONFIG_SUNLANCE is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNBMAC is not set
++# CONFIG_SUNQE is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_LANCE is not set
++# CONFIG_NET_VENDOR_SMC is not set
++# CONFIG_NET_VENDOR_RACAL is not set
++# CONFIG_HP100 is not set
++# CONFIG_NET_ISA is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_NET_POCKET is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_MYRI_SBUS is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PLIP is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++
++#
++# Wireless LAN (non-hamradio)
++#
++# CONFIG_NET_RADIO is not set
++
++#
++# Token Ring devices
++#
++# CONFIG_TR is not set
++# CONFIG_NET_FC is not set
++# CONFIG_RCPCI is not set
++# CONFIG_SHAPER is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++
++#
++# PCMCIA network device support
++#
++# CONFIG_NET_PCMCIA is not set
++
++#
++# Amateur Radio support
++#
++# CONFIG_HAMRADIO is not set
++
++#
++# IrDA (infrared) support
++#
++# CONFIG_IRDA is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Input core support
++#
++CONFIG_INPUT=y
++CONFIG_INPUT_KEYBDEV=y
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_UINPUT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++# CONFIG_VT_CONSOLE is not set
++# CONFIG_SERIAL is not set
++# CONFIG_SERIAL_EXTENDED is not set
++CONFIG_SERIAL_NONSTANDARD=y
++# CONFIG_COMPUTONE is not set
++# CONFIG_ROCKETPORT is not set
++# CONFIG_CYCLADES is not set
++# CONFIG_DIGIEPCA is not set
++# CONFIG_DIGI is not set
++# CONFIG_ESPSERIAL is not set
++# CONFIG_MOXA_INTELLIO is not set
++# CONFIG_MOXA_SMARTIO is not set
++# CONFIG_ISI is not set
++# CONFIG_SYNCLINK is not set
++# CONFIG_SYNCLINKMP is not set
++# CONFIG_N_HDLC is not set
++# CONFIG_RISCOM8 is not set
++# CONFIG_SPECIALIX is not set
++# CONFIG_SX is not set
++# CONFIG_RIO is not set
++# CONFIG_STALDRV is not set
++# CONFIG_SERIAL_TX3912 is not set
++# CONFIG_SERIAL_TX3912_CONSOLE is not set
++# CONFIG_SERIAL_TXX9 is not set
++# CONFIG_SERIAL_TXX9_CONSOLE is not set
++# CONFIG_TXX927_SERIAL is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_UNIX98_PTY_COUNT=256
++
++#
++# I2C support
++#
++# CONFIG_I2C is not set
++
++#
++# Mice
++#
++# CONFIG_BUSMOUSE is not set
++# CONFIG_MOUSE is not set
++
++#
++# Joysticks
++#
++# CONFIG_INPUT_GAMEPORT is not set
++# CONFIG_INPUT_NS558 is not set
++# CONFIG_INPUT_LIGHTNING is not set
++# CONFIG_INPUT_PCIGAME is not set
++# CONFIG_INPUT_CS461X is not set
++# CONFIG_INPUT_EMU10K1 is not set
++# CONFIG_INPUT_SERIO is not set
++# CONFIG_INPUT_SERPORT is not set
++
++#
++# Joysticks
++#
++# CONFIG_INPUT_ANALOG is not set
++# CONFIG_INPUT_A3D is not set
++# CONFIG_INPUT_ADI is not set
++# CONFIG_INPUT_COBRA is not set
++# CONFIG_INPUT_GF2K is not set
++# CONFIG_INPUT_GRIP is not set
++# CONFIG_INPUT_INTERACT is not set
++# CONFIG_INPUT_TMDC is not set
++# CONFIG_INPUT_SIDEWINDER is not set
++# CONFIG_INPUT_IFORCE_USB is not set
++# CONFIG_INPUT_IFORCE_232 is not set
++# CONFIG_INPUT_WARRIOR is not set
++# CONFIG_INPUT_MAGELLAN is not set
++# CONFIG_INPUT_SPACEORB is not set
++# CONFIG_INPUT_SPACEBALL is not set
++# CONFIG_INPUT_STINGER is not set
++# CONFIG_INPUT_DB9 is not set
++# CONFIG_INPUT_GAMECON is not set
++# CONFIG_INPUT_TURBOGRAFX is not set
++# CONFIG_QIC02_TAPE is not set
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_IPMI_PANIC_EVENT is not set
++# CONFIG_IPMI_DEVICE_INTERFACE is not set
++# CONFIG_IPMI_KCS is not set
++# CONFIG_IPMI_WATCHDOG is not set
++
++#
++# Watchdog Cards
++#
++# CONFIG_WATCHDOG is not set
++# CONFIG_SCx200 is not set
++# CONFIG_SCx200_GPIO is not set
++# CONFIG_AMD_PM768 is not set
++# CONFIG_NVRAM is not set
++# CONFIG_RTC is not set
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++# CONFIG_FTAPE is not set
++# CONFIG_AGP is not set
++
++#
++# Direct Rendering Manager (XFree86 DRI support)
++#
++# CONFIG_DRM is not set
++
++#
++# PCMCIA character devices
++#
++# CONFIG_PCMCIA_SERIAL_CS is not set
++# CONFIG_SYNCLINK_CS is not set
++
++#
++# File systems
++#
++# CONFIG_QUOTA is not set
++# CONFIG_QFMT_V2 is not set
++CONFIG_AUTOFS_FS=y
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_REISERFS_CHECK is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++# CONFIG_ADFS_FS is not set
++# CONFIG_ADFS_FS_RW is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BEFS_DEBUG is not set
++# CONFIG_BFS_FS is not set
++CONFIG_EXT3_FS=y
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++# CONFIG_UMSDOS_FS is not set
++CONFIG_VFAT_FS=y
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++CONFIG_TMPFS=y
++CONFIG_RAMFS=y
++# CONFIG_ISO9660_FS is not set
++# CONFIG_JOLIET is not set
++# CONFIG_ZISOFS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_JFS_DEBUG is not set
++# CONFIG_JFS_STATISTICS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_NTFS_FS is not set
++# CONFIG_NTFS_RW is not set
++# CONFIG_HPFS_FS is not set
++CONFIG_PROC_FS=y
++# CONFIG_DEVFS_FS is not set
++# CONFIG_DEVFS_MOUNT is not set
++# CONFIG_DEVFS_DEBUG is not set
++CONFIG_DEVPTS_FS=y
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_QNX4FS_RW is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_EXT2_FS=y
++# CONFIG_SYSV_FS is not set
++# CONFIG_UDF_FS is not set
++# CONFIG_UDF_RW is not set
++# CONFIG_UFS_FS is not set
++# CONFIG_UFS_FS_WRITE is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_XFS_QUOTA is not set
++# CONFIG_XFS_RT is not set
++# CONFIG_XFS_TRACE is not set
++# CONFIG_XFS_DEBUG is not set
++
++#
++# Network File Systems
++#
++# CONFIG_CODA_FS is not set
++# CONFIG_INTERMEZZO_FS is not set
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_DIRECTIO is not set
++CONFIG_ROOT_NFS=y
++# CONFIG_NFSD is not set
++# CONFIG_NFSD_V3 is not set
++# CONFIG_NFSD_TCP is not set
++CONFIG_SUNRPC=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++# CONFIG_SMB_FS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_NCPFS_PACKET_SIGNING is not set
++# CONFIG_NCPFS_IOCTL_LOCKING is not set
++# CONFIG_NCPFS_STRONG is not set
++# CONFIG_NCPFS_NFS_NS is not set
++# CONFIG_NCPFS_OS2_NS is not set
++# CONFIG_NCPFS_SMALLDOS is not set
++# CONFIG_NCPFS_NLS is not set
++# CONFIG_NCPFS_EXTRAS is not set
++# CONFIG_ZISOFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_SMB_NLS is not set
++CONFIG_NLS=y
++
++#
++# Native Language Support
++#
++CONFIG_NLS_DEFAULT="iso8859-1"
++# CONFIG_NLS_CODEPAGE_437 is not set
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ISO8859_1 is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Console drivers
++#
++# CONFIG_VGA_CONSOLE is not set
++# CONFIG_MDA_CONSOLE is not set
++
++#
++# Frame-buffer support
++#
++CONFIG_FB=y
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_FB_RIVA is not set
++# CONFIG_FB_CLGEN is not set
++# CONFIG_FB_PM2 is not set
++# CONFIG_FB_PM3 is not set
++# CONFIG_FB_CYBER2000 is not set
++# CONFIG_FB_MATROX is not set
++# CONFIG_FB_ATY is not set
++# CONFIG_FB_RADEON is not set
++# CONFIG_FB_ATY128 is not set
++# CONFIG_FB_INTEL is not set
++# CONFIG_FB_SIS is not set
++# CONFIG_FB_NEOMAGIC is not set
++# CONFIG_FB_3DFX is not set
++# CONFIG_FB_VOODOO1 is not set
++# CONFIG_FB_TRIDENT is not set
++# CONFIG_FB_E1356 is not set
++# CONFIG_FB_IT8181 is not set
++# CONFIG_FB_VIRTUAL is not set
++CONFIG_FBCON_ADVANCED=y
++# CONFIG_FBCON_MFB is not set
++# CONFIG_FBCON_CFB2 is not set
++# CONFIG_FBCON_CFB4 is not set
++# CONFIG_FBCON_CFB8 is not set
++CONFIG_FBCON_CFB16=y
++# CONFIG_FBCON_CFB24 is not set
++CONFIG_FBCON_CFB32=y
++# CONFIG_FBCON_AFB is not set
++# CONFIG_FBCON_ILBM is not set
++# CONFIG_FBCON_IPLAN2P2 is not set
++# CONFIG_FBCON_IPLAN2P4 is not set
++# CONFIG_FBCON_IPLAN2P8 is not set
++# CONFIG_FBCON_MAC is not set
++# CONFIG_FBCON_VGA_PLANES is not set
++# CONFIG_FBCON_VGA is not set
++# CONFIG_FBCON_HGA is not set
++# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
++CONFIG_FBCON_FONTS=y
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++# CONFIG_FONT_SUN8x16 is not set
++# CONFIG_FONT_SUN12x22 is not set
++# CONFIG_FONT_6x11 is not set
++# CONFIG_FONT_PEARL_8x8 is not set
++# CONFIG_FONT_ACORN_8x8 is not set
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++# CONFIG_SOUND_ALI5455 is not set
++# CONFIG_SOUND_BT878 is not set
++# CONFIG_SOUND_CMPCI is not set
++# CONFIG_SOUND_EMU10K1 is not set
++# CONFIG_MIDI_EMU10K1 is not set
++# CONFIG_SOUND_FUSION is not set
++# CONFIG_SOUND_CS4281 is not set
++# CONFIG_SOUND_ES1370 is not set
++# CONFIG_SOUND_ES1371 is not set
++# CONFIG_SOUND_ESSSOLO1 is not set
++# CONFIG_SOUND_MAESTRO is not set
++# CONFIG_SOUND_MAESTRO3 is not set
++# CONFIG_SOUND_FORTE is not set
++# CONFIG_SOUND_ICH is not set
++# CONFIG_SOUND_RME96XX is not set
++# CONFIG_SOUND_SONICVIBES is not set
++# CONFIG_SOUND_TRIDENT is not set
++# CONFIG_SOUND_MSNDCLAS is not set
++# CONFIG_SOUND_MSNDPIN is not set
++# CONFIG_SOUND_VIA82CXXX is not set
++# CONFIG_MIDI_VIA82CXXX is not set
++# CONFIG_SOUND_OSS is not set
++# CONFIG_SOUND_TVMIXER is not set
++# CONFIG_SOUND_AD1980 is not set
++# CONFIG_SOUND_WM97XX is not set
++
++#
++# USB support
++#
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++# CONFIG_USB_BANDWIDTH is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_EHCI_HCD is not set
++# CONFIG_USB_UHCI is not set
++# CONFIG_USB_UHCI_ALT is not set
++CONFIG_USB_OHCI=y
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_AUDIO is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_BLUETOOTH is not set
++# CONFIG_USB_MIDI is not set
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_HP8200e is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# USB Human Interface Devices (HID)
++#
++CONFIG_USB_HID=y
++CONFIG_USB_HIDINPUT=y
++CONFIG_USB_HIDDEV=y
++# CONFIG_USB_AIPTEK is not set
++# CONFIG_USB_WACOM is not set
++# CONFIG_USB_KBTAB is not set
++# CONFIG_USB_POWERMATE is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_DC2XX is not set
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_SCANNER is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_HPUSBSCSI is not set
++
++#
++# USB Multimedia devices
++#
++
++#
++# Video4Linux support is needed for USB Multimedia device support
++#
++
++#
++# USB Network adaptors
++#
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_CDCETHER is not set
++# CONFIG_USB_USBNET is not set
++
++#
++# USB port drivers
++#
++# CONFIG_USB_USS720 is not set
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_TIGL is not set
++# CONFIG_USB_BRLVGER is not set
++# CONFIG_USB_LCD is not set
++
++#
++# Support for USB gadgets
++#
++# CONFIG_USB_GADGET is not set
++
++#
++# Bluetooth support
++#
++# CONFIG_BLUEZ is not set
++
++#
++# Kernel hacking
++#
++CONFIG_CROSSCOMPILE=y
++# CONFIG_RUNTIME_DEBUG is not set
++# CONFIG_KGDB is not set
++# CONFIG_GDB_CONSOLE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_MIPS_UNCACHED is not set
++CONFIG_LOG_BUF_SHIFT=0
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++# CONFIG_CRC32 is not set
++CONFIG_ZLIB_INFLATE=m
++CONFIG_ZLIB_DEFLATE=m
++# CONFIG_FW_LOADER is not set
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-db1500 linux-2.4.32-rc1.mips/arch/mips/defconfig-db1500
+--- linux-2.4.32-rc1/arch/mips/defconfig-db1500 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-db1500 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -267,11 +267,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -555,7 +550,6 @@
+ # CONFIG_AU1X00_USB_TTY is not set
+ # CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-db1550 linux-2.4.32-rc1.mips/arch/mips/defconfig-db1550
+--- linux-2.4.32-rc1/arch/mips/defconfig-db1550 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-db1550 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -213,11 +213,9 @@
+ # CONFIG_MTD_BOSPORUS is not set
+ # CONFIG_MTD_XXS1500 is not set
+ # CONFIG_MTD_MTX1 is not set
+-# CONFIG_MTD_DB1X00 is not set
+ CONFIG_MTD_PB1550=y
+ CONFIG_MTD_PB1550_BOOT=y
+ CONFIG_MTD_PB1550_USER=y
+-# CONFIG_MTD_HYDROGEN3 is not set
+ # CONFIG_MTD_MIRAGE is not set
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ # CONFIG_MTD_OCELOT is not set
+@@ -236,7 +234,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOCPROBE is not set
+@@ -343,11 +340,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -633,7 +625,6 @@
+ # CONFIG_AU1X00_USB_TTY is not set
+ # CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-ddb5476 linux-2.4.32-rc1.mips/arch/mips/defconfig-ddb5476
+--- linux-2.4.32-rc1/arch/mips/defconfig-ddb5476 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-ddb5476 2005-03-18 13:13:21.000000000 +0100
+@@ -28,8 +28,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -226,11 +226,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -517,7 +512,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-ddb5477 linux-2.4.32-rc1.mips/arch/mips/defconfig-ddb5477
+--- linux-2.4.32-rc1/arch/mips/defconfig-ddb5477 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-ddb5477 2005-03-18 13:13:21.000000000 +0100
+@@ -28,8 +28,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -226,11 +226,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -434,7 +429,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-decstation linux-2.4.32-rc1.mips/arch/mips/defconfig-decstation
+--- linux-2.4.32-rc1/arch/mips/defconfig-decstation 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-decstation 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -223,11 +223,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -306,9 +301,11 @@
+ # CONFIG_SCSI_MEGARAID is not set
+ # CONFIG_SCSI_MEGARAID2 is not set
+ # CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ # CONFIG_SCSI_ATA_PIIX is not set
+ # CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
+ # CONFIG_SCSI_SATA_PROMISE is not set
+ # CONFIG_SCSI_SATA_SX4 is not set
+ # CONFIG_SCSI_SATA_SIL is not set
+@@ -477,7 +474,6 @@
+ CONFIG_SERIAL_DEC_CONSOLE=y
+ CONFIG_DZ=y
+ CONFIG_ZS=y
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-e55 linux-2.4.32-rc1.mips/arch/mips/defconfig-e55
+--- linux-2.4.32-rc1/arch/mips/defconfig-e55 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-e55 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -222,11 +222,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -426,7 +421,6 @@
+ # CONFIG_SERIAL_MULTIPORT is not set
+ # CONFIG_HUB6 is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ # CONFIG_VR41XX_KIU is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-eagle linux-2.4.32-rc1.mips/arch/mips/defconfig-eagle
+--- linux-2.4.32-rc1/arch/mips/defconfig-eagle 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-eagle 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -208,8 +208,8 @@
+ # Mapping drivers for chip access
+ #
+ CONFIG_MTD_PHYSMAP=y
+-CONFIG_MTD_PHYSMAP_START=1c000000
+-CONFIG_MTD_PHYSMAP_LEN=2000000
++CONFIG_MTD_PHYSMAP_START=0x1c000000
++CONFIG_MTD_PHYSMAP_LEN=0x2000000
+ CONFIG_MTD_PHYSMAP_BUSWIDTH=4
+ # CONFIG_MTD_PB1000 is not set
+ # CONFIG_MTD_PB1500 is not set
+@@ -217,9 +217,7 @@
+ # CONFIG_MTD_BOSPORUS is not set
+ # CONFIG_MTD_XXS1500 is not set
+ # CONFIG_MTD_MTX1 is not set
+-# CONFIG_MTD_DB1X00 is not set
+ # CONFIG_MTD_PB1550 is not set
+-# CONFIG_MTD_HYDROGEN3 is not set
+ # CONFIG_MTD_MIRAGE is not set
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ # CONFIG_MTD_OCELOT is not set
+@@ -238,7 +236,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOCPROBE is not set
+@@ -327,11 +324,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -587,7 +579,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ # CONFIG_VR41XX_KIU is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-ev64120 linux-2.4.32-rc1.mips/arch/mips/defconfig-ev64120
+--- linux-2.4.32-rc1/arch/mips/defconfig-ev64120 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-ev64120 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -230,11 +230,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -443,7 +438,6 @@
+ # CONFIG_SERIAL_CONSOLE is not set
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-ev96100 linux-2.4.32-rc1.mips/arch/mips/defconfig-ev96100
+--- linux-2.4.32-rc1/arch/mips/defconfig-ev96100 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-ev96100 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -232,11 +232,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -441,7 +436,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-ficmmp linux-2.4.32-rc1.mips/arch/mips/defconfig-ficmmp
+--- linux-2.4.32-rc1/arch/mips/defconfig-ficmmp 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-ficmmp 2005-03-18 13:13:21.000000000 +0100
+@@ -0,0 +1,862 @@
++#
++# Automatically generated make config: don't edit
++#
++CONFIG_MIPS=y
++CONFIG_MIPS32=y
++# CONFIG_MIPS64 is not set
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++# CONFIG_MODVERSIONS is not set
++CONFIG_KMOD=y
++
++#
++# Machine selection
++#
++# CONFIG_ACER_PICA_61 is not set
++# CONFIG_MIPS_BOSPORUS is not set
++# CONFIG_MIPS_MIRAGE is not set
++# CONFIG_MIPS_DB1000 is not set
++# CONFIG_MIPS_DB1100 is not set
++# CONFIG_MIPS_DB1500 is not set
++# CONFIG_MIPS_DB1550 is not set
++# CONFIG_MIPS_PB1000 is not set
++# CONFIG_MIPS_PB1100 is not set
++# CONFIG_MIPS_PB1500 is not set
++# CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
++# CONFIG_MIPS_XXS1500 is not set
++# CONFIG_MIPS_MTX1 is not set
++# CONFIG_COGENT_CSB250 is not set
++# CONFIG_BAGET_MIPS is not set
++# CONFIG_CASIO_E55 is not set
++# CONFIG_MIPS_COBALT is not set
++# CONFIG_DECSTATION is not set
++# CONFIG_MIPS_EV64120 is not set
++# CONFIG_MIPS_EV96100 is not set
++# CONFIG_MIPS_IVR is not set
++# CONFIG_HP_LASERJET is not set
++# CONFIG_IBM_WORKPAD is not set
++# CONFIG_LASAT is not set
++# CONFIG_MIPS_ITE8172 is not set
++# CONFIG_MIPS_ATLAS is not set
++# CONFIG_MIPS_MAGNUM_4000 is not set
++# CONFIG_MIPS_MALTA is not set
++# CONFIG_MIPS_SEAD is not set
++# CONFIG_MOMENCO_OCELOT is not set
++# CONFIG_MOMENCO_OCELOT_G is not set
++# CONFIG_MOMENCO_OCELOT_C is not set
++# CONFIG_MOMENCO_JAGUAR_ATX is not set
++# CONFIG_PMC_BIG_SUR is not set
++# CONFIG_PMC_STRETCH is not set
++# CONFIG_PMC_YOSEMITE is not set
++# CONFIG_DDB5074 is not set
++# CONFIG_DDB5476 is not set
++# CONFIG_DDB5477 is not set
++# CONFIG_NEC_OSPREY is not set
++# CONFIG_NEC_EAGLE is not set
++# CONFIG_OLIVETTI_M700 is not set
++# CONFIG_NINO is not set
++# CONFIG_SGI_IP22 is not set
++# CONFIG_SGI_IP27 is not set
++# CONFIG_SIBYTE_SB1xxx_SOC is not set
++# CONFIG_SNI_RM200_PCI is not set
++# CONFIG_TANBAC_TB0226 is not set
++# CONFIG_TANBAC_TB0229 is not set
++# CONFIG_TOSHIBA_JMR3927 is not set
++# CONFIG_TOSHIBA_RBTX4927 is not set
++# CONFIG_VICTOR_MPC30X is not set
++# CONFIG_ZAO_CAPCELLA is not set
++# CONFIG_HIGHMEM is not set
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++# CONFIG_MIPS_AU1000 is not set
++
++#
++# CPU selection
++#
++CONFIG_CPU_MIPS32=y
++# CONFIG_CPU_MIPS64 is not set
++# CONFIG_CPU_R3000 is not set
++# CONFIG_CPU_TX39XX is not set
++# CONFIG_CPU_VR41XX is not set
++# CONFIG_CPU_R4300 is not set
++# CONFIG_CPU_R4X00 is not set
++# CONFIG_CPU_TX49XX is not set
++# CONFIG_CPU_R5000 is not set
++# CONFIG_CPU_R5432 is not set
++# CONFIG_CPU_R6000 is not set
++# CONFIG_CPU_NEVADA is not set
++# CONFIG_CPU_R8000 is not set
++# CONFIG_CPU_R10000 is not set
++# CONFIG_CPU_RM7000 is not set
++# CONFIG_CPU_RM9000 is not set
++# CONFIG_CPU_SB1 is not set
++CONFIG_PAGE_SIZE_4KB=y
++# CONFIG_PAGE_SIZE_16KB is not set
++# CONFIG_PAGE_SIZE_64KB is not set
++CONFIG_CPU_HAS_PREFETCH=y
++# CONFIG_VTAG_ICACHE is not set
++CONFIG_64BIT_PHYS_ADDR=y
++# CONFIG_CPU_ADVANCED is not set
++CONFIG_CPU_HAS_LLSC=y
++# CONFIG_CPU_HAS_LLDSCD is not set
++# CONFIG_CPU_HAS_WB is not set
++CONFIG_CPU_HAS_SYNC=y
++
++#
++# General setup
++#
++CONFIG_CPU_LITTLE_ENDIAN=y
++# CONFIG_BUILD_ELF64 is not set
++CONFIG_NET=y
++# CONFIG_PCI is not set
++# CONFIG_PCI_NEW is not set
++CONFIG_PCI_AUTO=y
++# CONFIG_ISA is not set
++# CONFIG_TC is not set
++# CONFIG_MCA is not set
++# CONFIG_SBUS is not set
++# CONFIG_HOTPLUG is not set
++# CONFIG_PCMCIA is not set
++# CONFIG_HOTPLUG_PCI is not set
++CONFIG_SYSVIPC=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++CONFIG_SYSCTL=y
++CONFIG_KCORE_ELF=y
++# CONFIG_KCORE_AOUT is not set
++# CONFIG_BINFMT_AOUT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_MIPS32_COMPAT is not set
++# CONFIG_MIPS32_O32 is not set
++# CONFIG_MIPS32_N32 is not set
++# CONFIG_BINFMT_ELF32 is not set
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_OOM_KILLER is not set
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE="ide3=dma mem=96M root=/dev/hda2 rootflags=data=journal"
++
++#
++# Memory Technology Devices (MTD)
++#
++# CONFIG_MTD is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play configuration
++#
++# CONFIG_PNP is not set
++# CONFIG_ISAPNP is not set
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_XD is not set
++# CONFIG_PARIDE is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_CISS_SCSI_TAPE is not set
++# CONFIG_CISS_MONITOR_THREAD is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_RAM is not set
++# CONFIG_BLK_DEV_INITRD is not set
++# CONFIG_BLK_STATS is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++# CONFIG_BLK_DEV_MD is not set
++# CONFIG_MD_LINEAR is not set
++# CONFIG_MD_RAID0 is not set
++# CONFIG_MD_RAID1 is not set
++# CONFIG_MD_RAID5 is not set
++# CONFIG_MD_MULTIPATH is not set
++# CONFIG_BLK_DEV_LVM is not set
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++# CONFIG_NETLINK_DEV is not set
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++CONFIG_FILTER=y
++CONFIG_UNIX=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_INET_ECN is not set
++# CONFIG_SYN_COOKIES is not set
++
++#
++# IP: Netfilter Configuration
++#
++# CONFIG_IP_NF_CONNTRACK is not set
++# CONFIG_IP_NF_QUEUE is not set
++# CONFIG_IP_NF_IPTABLES is not set
++# CONFIG_IP_NF_ARPTABLES is not set
++# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
++# CONFIG_IP_NF_COMPAT_IPFWADM is not set
++
++#
++# IP: Virtual Server Configuration
++#
++# CONFIG_IP_VS is not set
++# CONFIG_IPV6 is not set
++# CONFIG_KHTTPD is not set
++
++#
++# SCTP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_SCTP is not set
++# CONFIG_ATM is not set
++# CONFIG_VLAN_8021Q is not set
++
++#
++#
++#
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_DECNET is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_LLC is not set
++# CONFIG_NET_DIVERT is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_FASTROUTE is not set
++# CONFIG_NET_HW_FLOWCONTROL is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++
++#
++# Telephony Support
++#
++# CONFIG_PHONE is not set
++# CONFIG_PHONE_IXJ is not set
++# CONFIG_PHONE_IXJ_PCMCIA is not set
++
++#
++# ATA/IDE/MFM/RLL support
++#
++CONFIG_IDE=y
++
++#
++# IDE, ATA and ATAPI Block devices
++#
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide.txt for help/info on IDE drives
++#
++CONFIG_BLK_DEV_HD_IDE=y
++CONFIG_BLK_DEV_HD=y
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++CONFIG_IDEDISK_MULTI_MODE=y
++CONFIG_IDEDISK_STROKE=y
++# CONFIG_BLK_DEV_IDECS is not set
++# CONFIG_BLK_DEV_DELKIN is not set
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_BLK_DEV_IDESCSI is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++
++#
++# IDE chipset support/bugfixes
++#
++# CONFIG_BLK_DEV_CMD640 is not set
++# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
++# CONFIG_BLK_DEV_ISAPNP is not set
++# CONFIG_IDE_CHIPSETS is not set
++# CONFIG_IDEDMA_AUTO is not set
++# CONFIG_DMA_NONPCI is not set
++# CONFIG_BLK_DEV_ATARAID is not set
++# CONFIG_BLK_DEV_ATARAID_PDC is not set
++# CONFIG_BLK_DEV_ATARAID_HPT is not set
++# CONFIG_BLK_DEV_ATARAID_MEDLEY is not set
++# CONFIG_BLK_DEV_ATARAID_SII is not set
++
++#
++# SCSI support
++#
++CONFIG_SCSI=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++CONFIG_SD_EXTRA_DEVS=40
++CONFIG_CHR_DEV_ST=y
++# CONFIG_CHR_DEV_OSST is not set
++CONFIG_BLK_DEV_SR=y
++# CONFIG_BLK_DEV_SR_VENDOR is not set
++CONFIG_SR_EXTRA_DEVS=2
++# CONFIG_CHR_DEV_SG is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_DEBUG_QUEUES is not set
++# CONFIG_SCSI_MULTI_LUN is not set
++CONFIG_SCSI_CONSTANTS=y
++# CONFIG_SCSI_LOGGING is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_SCSI_7000FASST is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AHA152X is not set
++# CONFIG_SCSI_AHA1542 is not set
++# CONFIG_SCSI_AHA1740 is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_IN2000 is not set
++# CONFIG_SCSI_AM53C974 is not set
++# CONFIG_SCSI_MEGARAID is not set
++# CONFIG_SCSI_MEGARAID2 is not set
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
++# CONFIG_SCSI_SATA_SVW is not set
++# CONFIG_SCSI_ATA_PIIX is not set
++# CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
++# CONFIG_SCSI_SATA_PROMISE is not set
++# CONFIG_SCSI_SATA_SX4 is not set
++# CONFIG_SCSI_SATA_SIL is not set
++# CONFIG_SCSI_SATA_SIS is not set
++# CONFIG_SCSI_SATA_ULI is not set
++# CONFIG_SCSI_SATA_VIA is not set
++# CONFIG_SCSI_SATA_VITESSE is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_DTC3280 is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_EATA_DMA is not set
++# CONFIG_SCSI_EATA_PIO is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_GENERIC_NCR5380 is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_NCR53C406A is not set
++# CONFIG_SCSI_NCR53C7xx is not set
++# CONFIG_SCSI_PAS16 is not set
++# CONFIG_SCSI_PCI2000 is not set
++# CONFIG_SCSI_PCI2220I is not set
++# CONFIG_SCSI_PSI240I is not set
++# CONFIG_SCSI_QLOGIC_FAS is not set
++# CONFIG_SCSI_SIM710 is not set
++# CONFIG_SCSI_SYM53C416 is not set
++# CONFIG_SCSI_T128 is not set
++# CONFIG_SCSI_U14_34F is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# Fusion MPT device support
++#
++# CONFIG_FUSION is not set
++# CONFIG_FUSION_BOOT is not set
++# CONFIG_FUSION_ISENSE is not set
++# CONFIG_FUSION_CTL is not set
++# CONFIG_FUSION_LAN is not set
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++
++#
++# ARCnet devices
++#
++# CONFIG_ARCNET is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_ETHERTAP is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++# CONFIG_SUNLANCE is not set
++# CONFIG_SUNBMAC is not set
++# CONFIG_SUNQE is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_LANCE is not set
++# CONFIG_NET_VENDOR_SMC is not set
++# CONFIG_NET_VENDOR_RACAL is not set
++# CONFIG_NET_ISA is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_NET_POCKET is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_MYRI_SBUS is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PLIP is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++
++#
++# Wireless LAN (non-hamradio)
++#
++# CONFIG_NET_RADIO is not set
++
++#
++# Token Ring devices
++#
++# CONFIG_TR is not set
++# CONFIG_NET_FC is not set
++# CONFIG_RCPCI is not set
++# CONFIG_SHAPER is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++
++#
++# Amateur Radio support
++#
++# CONFIG_HAMRADIO is not set
++
++#
++# IrDA (infrared) support
++#
++# CONFIG_IRDA is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Input core support
++#
++CONFIG_INPUT=y
++CONFIG_INPUT_KEYBDEV=y
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_UINPUT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++# CONFIG_SERIAL is not set
++# CONFIG_SERIAL_EXTENDED is not set
++CONFIG_SERIAL_NONSTANDARD=y
++# CONFIG_COMPUTONE is not set
++# CONFIG_ROCKETPORT is not set
++# CONFIG_CYCLADES is not set
++# CONFIG_DIGIEPCA is not set
++# CONFIG_DIGI is not set
++# CONFIG_ESPSERIAL is not set
++# CONFIG_MOXA_INTELLIO is not set
++# CONFIG_MOXA_SMARTIO is not set
++# CONFIG_ISI is not set
++# CONFIG_SYNCLINK is not set
++# CONFIG_SYNCLINKMP is not set
++# CONFIG_N_HDLC is not set
++# CONFIG_RISCOM8 is not set
++# CONFIG_SPECIALIX is not set
++# CONFIG_SX is not set
++# CONFIG_RIO is not set
++# CONFIG_STALDRV is not set
++# CONFIG_SERIAL_TX3912 is not set
++# CONFIG_SERIAL_TX3912_CONSOLE is not set
++# CONFIG_SERIAL_TXX9 is not set
++# CONFIG_SERIAL_TXX9_CONSOLE is not set
++# CONFIG_TXX927_SERIAL is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_UNIX98_PTY_COUNT=256
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_SCx200_ACB is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_CHARDEV is not set
++# CONFIG_I2C_PROC is not set
++
++#
++# Mice
++#
++# CONFIG_BUSMOUSE is not set
++# CONFIG_MOUSE is not set
++
++#
++# Joysticks
++#
++# CONFIG_INPUT_GAMEPORT is not set
++# CONFIG_INPUT_NS558 is not set
++# CONFIG_INPUT_LIGHTNING is not set
++# CONFIG_INPUT_PCIGAME is not set
++# CONFIG_INPUT_CS461X is not set
++# CONFIG_INPUT_EMU10K1 is not set
++# CONFIG_INPUT_SERIO is not set
++# CONFIG_INPUT_SERPORT is not set
++
++#
++# Joysticks
++#
++# CONFIG_INPUT_ANALOG is not set
++# CONFIG_INPUT_A3D is not set
++# CONFIG_INPUT_ADI is not set
++# CONFIG_INPUT_COBRA is not set
++# CONFIG_INPUT_GF2K is not set
++# CONFIG_INPUT_GRIP is not set
++# CONFIG_INPUT_INTERACT is not set
++# CONFIG_INPUT_TMDC is not set
++# CONFIG_INPUT_SIDEWINDER is not set
++# CONFIG_INPUT_IFORCE_USB is not set
++# CONFIG_INPUT_IFORCE_232 is not set
++# CONFIG_INPUT_WARRIOR is not set
++# CONFIG_INPUT_MAGELLAN is not set
++# CONFIG_INPUT_SPACEORB is not set
++# CONFIG_INPUT_SPACEBALL is not set
++# CONFIG_INPUT_STINGER is not set
++# CONFIG_INPUT_DB9 is not set
++# CONFIG_INPUT_GAMECON is not set
++# CONFIG_INPUT_TURBOGRAFX is not set
++# CONFIG_QIC02_TAPE is not set
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_IPMI_PANIC_EVENT is not set
++# CONFIG_IPMI_DEVICE_INTERFACE is not set
++# CONFIG_IPMI_KCS is not set
++# CONFIG_IPMI_WATCHDOG is not set
++
++#
++# Watchdog Cards
++#
++# CONFIG_WATCHDOG is not set
++# CONFIG_SCx200 is not set
++# CONFIG_SCx200_GPIO is not set
++# CONFIG_AMD_PM768 is not set
++# CONFIG_NVRAM is not set
++# CONFIG_RTC is not set
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++# CONFIG_FTAPE is not set
++# CONFIG_AGP is not set
++
++#
++# Direct Rendering Manager (XFree86 DRI support)
++#
++# CONFIG_DRM is not set
++
++#
++# File systems
++#
++# CONFIG_QUOTA is not set
++# CONFIG_QFMT_V2 is not set
++CONFIG_AUTOFS_FS=y
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_REISERFS_CHECK is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++# CONFIG_ADFS_FS is not set
++# CONFIG_ADFS_FS_RW is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BEFS_DEBUG is not set
++# CONFIG_BFS_FS is not set
++CONFIG_EXT3_FS=y
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++# CONFIG_UMSDOS_FS is not set
++CONFIG_VFAT_FS=y
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_TMPFS is not set
++CONFIG_RAMFS=y
++# CONFIG_ISO9660_FS is not set
++# CONFIG_JOLIET is not set
++# CONFIG_ZISOFS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_JFS_DEBUG is not set
++# CONFIG_JFS_STATISTICS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_NTFS_FS is not set
++# CONFIG_NTFS_RW is not set
++# CONFIG_HPFS_FS is not set
++CONFIG_PROC_FS=y
++# CONFIG_DEVFS_FS is not set
++# CONFIG_DEVFS_MOUNT is not set
++# CONFIG_DEVFS_DEBUG is not set
++CONFIG_DEVPTS_FS=y
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_QNX4FS_RW is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_EXT2_FS=y
++# CONFIG_SYSV_FS is not set
++# CONFIG_UDF_FS is not set
++# CONFIG_UDF_RW is not set
++# CONFIG_UFS_FS is not set
++# CONFIG_UFS_FS_WRITE is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_XFS_QUOTA is not set
++# CONFIG_XFS_RT is not set
++# CONFIG_XFS_TRACE is not set
++# CONFIG_XFS_DEBUG is not set
++
++#
++# Network File Systems
++#
++# CONFIG_CODA_FS is not set
++# CONFIG_INTERMEZZO_FS is not set
++# CONFIG_NFS_FS is not set
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_ROOT_NFS is not set
++# CONFIG_NFSD is not set
++# CONFIG_NFSD_V3 is not set
++# CONFIG_NFSD_TCP is not set
++# CONFIG_SUNRPC is not set
++# CONFIG_LOCKD is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_NCPFS_PACKET_SIGNING is not set
++# CONFIG_NCPFS_IOCTL_LOCKING is not set
++# CONFIG_NCPFS_STRONG is not set
++# CONFIG_NCPFS_NFS_NS is not set
++# CONFIG_NCPFS_OS2_NS is not set
++# CONFIG_NCPFS_SMALLDOS is not set
++# CONFIG_NCPFS_NLS is not set
++# CONFIG_NCPFS_EXTRAS is not set
++# CONFIG_ZISOFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_SMB_NLS is not set
++CONFIG_NLS=y
++
++#
++# Native Language Support
++#
++CONFIG_NLS_DEFAULT="iso8859-1"
++# CONFIG_NLS_CODEPAGE_437 is not set
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ISO8859_1 is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Console drivers
++#
++# CONFIG_VGA_CONSOLE is not set
++# CONFIG_MDA_CONSOLE is not set
++
++#
++# Frame-buffer support
++#
++CONFIG_FB=y
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_FB_CYBER2000 is not set
++# CONFIG_FB_VIRTUAL is not set
++CONFIG_FBCON_ADVANCED=y
++# CONFIG_FBCON_MFB is not set
++# CONFIG_FBCON_CFB2 is not set
++# CONFIG_FBCON_CFB4 is not set
++# CONFIG_FBCON_CFB8 is not set
++CONFIG_FBCON_CFB16=y
++# CONFIG_FBCON_CFB24 is not set
++# CONFIG_FBCON_CFB32 is not set
++# CONFIG_FBCON_AFB is not set
++# CONFIG_FBCON_ILBM is not set
++# CONFIG_FBCON_IPLAN2P2 is not set
++# CONFIG_FBCON_IPLAN2P4 is not set
++# CONFIG_FBCON_IPLAN2P8 is not set
++# CONFIG_FBCON_MAC is not set
++# CONFIG_FBCON_VGA_PLANES is not set
++# CONFIG_FBCON_VGA is not set
++# CONFIG_FBCON_HGA is not set
++# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
++CONFIG_FBCON_FONTS=y
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++# CONFIG_FONT_SUN8x16 is not set
++# CONFIG_FONT_SUN12x22 is not set
++# CONFIG_FONT_6x11 is not set
++# CONFIG_FONT_PEARL_8x8 is not set
++# CONFIG_FONT_ACORN_8x8 is not set
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++# CONFIG_SOUND_ALI5455 is not set
++# CONFIG_SOUND_BT878 is not set
++# CONFIG_SOUND_CMPCI is not set
++# CONFIG_SOUND_EMU10K1 is not set
++# CONFIG_MIDI_EMU10K1 is not set
++# CONFIG_SOUND_FUSION is not set
++# CONFIG_SOUND_CS4281 is not set
++# CONFIG_SOUND_ES1370 is not set
++# CONFIG_SOUND_ES1371 is not set
++# CONFIG_SOUND_ESSSOLO1 is not set
++# CONFIG_SOUND_MAESTRO is not set
++# CONFIG_SOUND_MAESTRO3 is not set
++# CONFIG_SOUND_FORTE is not set
++# CONFIG_SOUND_ICH is not set
++# CONFIG_SOUND_RME96XX is not set
++# CONFIG_SOUND_SONICVIBES is not set
++# CONFIG_SOUND_TRIDENT is not set
++# CONFIG_SOUND_MSNDCLAS is not set
++# CONFIG_SOUND_MSNDPIN is not set
++# CONFIG_SOUND_VIA82CXXX is not set
++# CONFIG_MIDI_VIA82CXXX is not set
++# CONFIG_SOUND_OSS is not set
++# CONFIG_SOUND_TVMIXER is not set
++# CONFIG_SOUND_AD1980 is not set
++# CONFIG_SOUND_WM97XX is not set
++
++#
++# USB support
++#
++# CONFIG_USB is not set
++
++#
++# Support for USB gadgets
++#
++# CONFIG_USB_GADGET is not set
++
++#
++# Bluetooth support
++#
++# CONFIG_BLUEZ is not set
++
++#
++# Kernel hacking
++#
++CONFIG_CROSSCOMPILE=y
++# CONFIG_RUNTIME_DEBUG is not set
++# CONFIG_KGDB is not set
++# CONFIG_GDB_CONSOLE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_MIPS_UNCACHED is not set
++CONFIG_LOG_BUF_SHIFT=0
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++# CONFIG_CRC32 is not set
++CONFIG_ZLIB_INFLATE=m
++CONFIG_ZLIB_DEFLATE=m
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-hp-lj linux-2.4.32-rc1.mips/arch/mips/defconfig-hp-lj
+--- linux-2.4.32-rc1/arch/mips/defconfig-hp-lj 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-hp-lj 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -184,8 +184,8 @@
+ # Mapping drivers for chip access
+ #
+ CONFIG_MTD_PHYSMAP=y
+-CONFIG_MTD_PHYSMAP_START=10040000
+-CONFIG_MTD_PHYSMAP_LEN=00fc0000
++CONFIG_MTD_PHYSMAP_START=0x10040000
++CONFIG_MTD_PHYSMAP_LEN=0x00fc0000
+ CONFIG_MTD_PHYSMAP_BUSWIDTH=4
+ # CONFIG_MTD_PB1000 is not set
+ # CONFIG_MTD_PB1500 is not set
+@@ -193,9 +193,7 @@
+ # CONFIG_MTD_BOSPORUS is not set
+ # CONFIG_MTD_XXS1500 is not set
+ # CONFIG_MTD_MTX1 is not set
+-# CONFIG_MTD_DB1X00 is not set
+ # CONFIG_MTD_PB1550 is not set
+-# CONFIG_MTD_HYDROGEN3 is not set
+ # CONFIG_MTD_MIRAGE is not set
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ # CONFIG_MTD_OCELOT is not set
+@@ -214,7 +212,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOCPROBE is not set
+@@ -304,11 +301,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -604,7 +596,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ # CONFIG_UNIX98_PTYS is not set
+
+ #
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-hydrogen3 linux-2.4.32-rc1.mips/arch/mips/defconfig-hydrogen3
+--- linux-2.4.32-rc1/arch/mips/defconfig-hydrogen3 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-hydrogen3 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-CONFIG_MIPS_HYDROGEN3=y
+ # CONFIG_MIPS_PB1550 is not set
++CONFIG_MIPS_HYDROGEN3=y
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -214,9 +214,7 @@
+ # CONFIG_MTD_BOSPORUS is not set
+ # CONFIG_MTD_XXS1500 is not set
+ # CONFIG_MTD_MTX1 is not set
+-# CONFIG_MTD_DB1X00 is not set
+ # CONFIG_MTD_PB1550 is not set
+-CONFIG_MTD_HYDROGEN3=y
+ # CONFIG_MTD_MIRAGE is not set
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ # CONFIG_MTD_OCELOT is not set
+@@ -235,7 +233,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOCPROBE is not set
+@@ -340,11 +337,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -590,7 +582,6 @@
+ # CONFIG_AU1X00_USB_TTY is not set
+ # CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+-CONFIG_MIPS_HYDROGEN3_BUTTONS=y
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+@@ -838,6 +829,7 @@
+ # CONFIG_FB_PM2 is not set
+ # CONFIG_FB_PM3 is not set
+ # CONFIG_FB_CYBER2000 is not set
++CONFIG_FB_AU1100=y
+ # CONFIG_FB_MATROX is not set
+ # CONFIG_FB_ATY is not set
+ # CONFIG_FB_RADEON is not set
+@@ -849,7 +841,6 @@
+ # CONFIG_FB_VOODOO1 is not set
+ # CONFIG_FB_TRIDENT is not set
+ # CONFIG_FB_E1356 is not set
+-CONFIG_FB_AU1100=y
+ # CONFIG_FB_IT8181 is not set
+ # CONFIG_FB_VIRTUAL is not set
+ CONFIG_FBCON_ADVANCED=y
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-ip22 linux-2.4.32-rc1.mips/arch/mips/defconfig-ip22
+--- linux-2.4.32-rc1/arch/mips/defconfig-ip22 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-ip22 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -235,11 +235,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -319,9 +314,11 @@
+ # CONFIG_SCSI_MEGARAID is not set
+ # CONFIG_SCSI_MEGARAID2 is not set
+ # CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ # CONFIG_SCSI_ATA_PIIX is not set
+ # CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
+ # CONFIG_SCSI_SATA_PROMISE is not set
+ # CONFIG_SCSI_SATA_SX4 is not set
+ # CONFIG_SCSI_SATA_SIL is not set
+@@ -465,7 +462,6 @@
+ # CONFIG_SERIAL is not set
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-it8172 linux-2.4.32-rc1.mips/arch/mips/defconfig-it8172
+--- linux-2.4.32-rc1/arch/mips/defconfig-it8172 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-it8172 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -186,8 +186,8 @@
+ # Mapping drivers for chip access
+ #
+ CONFIG_MTD_PHYSMAP=y
+-CONFIG_MTD_PHYSMAP_START=8000000
+-CONFIG_MTD_PHYSMAP_LEN=2000000
++CONFIG_MTD_PHYSMAP_START=0x8000000
++CONFIG_MTD_PHYSMAP_LEN=0x2000000
+ CONFIG_MTD_PHYSMAP_BUSWIDTH=4
+ # CONFIG_MTD_PB1000 is not set
+ # CONFIG_MTD_PB1500 is not set
+@@ -195,9 +195,7 @@
+ # CONFIG_MTD_BOSPORUS is not set
+ # CONFIG_MTD_XXS1500 is not set
+ # CONFIG_MTD_MTX1 is not set
+-# CONFIG_MTD_DB1X00 is not set
+ # CONFIG_MTD_PB1550 is not set
+-# CONFIG_MTD_HYDROGEN3 is not set
+ # CONFIG_MTD_MIRAGE is not set
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ # CONFIG_MTD_OCELOT is not set
+@@ -216,7 +214,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOCPROBE is not set
+@@ -304,11 +301,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -592,7 +584,6 @@
+ CONFIG_PC_KEYB=y
+ # CONFIG_IT8172_SCR0 is not set
+ # CONFIG_IT8172_SCR1 is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-ivr linux-2.4.32-rc1.mips/arch/mips/defconfig-ivr
+--- linux-2.4.32-rc1/arch/mips/defconfig-ivr 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-ivr 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -226,11 +226,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -516,7 +511,6 @@
+ CONFIG_QTRONIX_KEYBOARD=y
+ CONFIG_IT8172_CIR=y
+ # CONFIG_IT8172_SCR0 is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-jmr3927 linux-2.4.32-rc1.mips/arch/mips/defconfig-jmr3927
+--- linux-2.4.32-rc1/arch/mips/defconfig-jmr3927 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-jmr3927 2005-03-18 13:13:21.000000000 +0100
+@@ -28,8 +28,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -225,11 +225,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -454,7 +449,6 @@
+ # CONFIG_SERIAL_TXX9_CONSOLE is not set
+ CONFIG_TXX927_SERIAL=y
+ CONFIG_TXX927_SERIAL_CONSOLE=y
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ # CONFIG_UNIX98_PTYS is not set
+
+ #
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-lasat linux-2.4.32-rc1.mips/arch/mips/defconfig-lasat
+--- linux-2.4.32-rc1/arch/mips/defconfig-lasat 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-lasat 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -198,9 +198,7 @@
+ # CONFIG_MTD_BOSPORUS is not set
+ # CONFIG_MTD_XXS1500 is not set
+ # CONFIG_MTD_MTX1 is not set
+-# CONFIG_MTD_DB1X00 is not set
+ # CONFIG_MTD_PB1550 is not set
+-# CONFIG_MTD_HYDROGEN3 is not set
+ # CONFIG_MTD_MIRAGE is not set
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ # CONFIG_MTD_OCELOT is not set
+@@ -219,7 +217,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOCPROBE is not set
+@@ -303,11 +300,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -584,7 +576,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-malta linux-2.4.32-rc1.mips/arch/mips/defconfig-malta
+--- linux-2.4.32-rc1/arch/mips/defconfig-malta 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-malta 2005-04-19 14:19:34.000000000 +0200
+@@ -22,16 +22,19 @@
+ #
+ # CONFIG_ACER_PICA_61 is not set
+ # CONFIG_MIPS_BOSPORUS is not set
++# CONFIG_MIPS_FICMMP is not set
+ # CONFIG_MIPS_MIRAGE is not set
+ # CONFIG_MIPS_DB1000 is not set
+ # CONFIG_MIPS_DB1100 is not set
+ # CONFIG_MIPS_DB1500 is not set
+ # CONFIG_MIPS_DB1550 is not set
++# CONFIG_MIPS_DB1200 is not set
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_PB1200 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -237,11 +240,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -273,8 +271,83 @@
+ #
+ # ATA/IDE/MFM/RLL support
+ #
+-# CONFIG_IDE is not set
++CONFIG_IDE=y
++
++#
++# IDE, ATA and ATAPI Block devices
++#
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_HD_IDE is not set
+ # CONFIG_BLK_DEV_HD is not set
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++# CONFIG_IDEDISK_MULTI_MODE is not set
++# CONFIG_IDEDISK_STROKE is not set
++# CONFIG_BLK_DEV_IDECS is not set
++# CONFIG_BLK_DEV_DELKIN is not set
++CONFIG_BLK_DEV_IDECD=y
++CONFIG_BLK_DEV_IDETAPE=y
++CONFIG_BLK_DEV_IDEFLOPPY=y
++CONFIG_BLK_DEV_IDESCSI=y
++# CONFIG_IDE_TASK_IOCTL is not set
++
++#
++# IDE chipset support/bugfixes
++#
++# CONFIG_BLK_DEV_CMD640 is not set
++# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
++# CONFIG_BLK_DEV_ISAPNP is not set
++CONFIG_BLK_DEV_IDEPCI=y
++CONFIG_BLK_DEV_GENERIC=y
++CONFIG_IDEPCI_SHARE_IRQ=y
++CONFIG_BLK_DEV_IDEDMA_PCI=y
++# CONFIG_BLK_DEV_OFFBOARD is not set
++CONFIG_BLK_DEV_IDEDMA_FORCED=y
++CONFIG_IDEDMA_PCI_AUTO=y
++# CONFIG_IDEDMA_ONLYDISK is not set
++CONFIG_BLK_DEV_IDEDMA=y
++# CONFIG_IDEDMA_PCI_WIP is not set
++# CONFIG_BLK_DEV_ADMA100 is not set
++# CONFIG_BLK_DEV_AEC62XX is not set
++# CONFIG_BLK_DEV_ALI15X3 is not set
++# CONFIG_WDC_ALI15X3 is not set
++# CONFIG_BLK_DEV_AMD74XX is not set
++# CONFIG_AMD74XX_OVERRIDE is not set
++# CONFIG_BLK_DEV_ATIIXP is not set
++# CONFIG_BLK_DEV_CMD64X is not set
++# CONFIG_BLK_DEV_TRIFLEX is not set
++# CONFIG_BLK_DEV_CY82C693 is not set
++# CONFIG_BLK_DEV_CS5530 is not set
++# CONFIG_BLK_DEV_HPT34X is not set
++# CONFIG_HPT34X_AUTODMA is not set
++# CONFIG_BLK_DEV_HPT366 is not set
++CONFIG_BLK_DEV_PIIX=y
++# CONFIG_BLK_DEV_NS87415 is not set
++# CONFIG_BLK_DEV_OPTI621 is not set
++# CONFIG_BLK_DEV_PDC202XX_OLD is not set
++# CONFIG_PDC202XX_BURST is not set
++# CONFIG_BLK_DEV_PDC202XX_NEW is not set
++# CONFIG_BLK_DEV_RZ1000 is not set
++# CONFIG_BLK_DEV_SC1200 is not set
++# CONFIG_BLK_DEV_SVWKS is not set
++# CONFIG_BLK_DEV_SIIMAGE is not set
++# CONFIG_BLK_DEV_SIS5513 is not set
++# CONFIG_BLK_DEV_SLC90E66 is not set
++# CONFIG_BLK_DEV_TRM290 is not set
++# CONFIG_BLK_DEV_VIA82CXXX is not set
++# CONFIG_IDE_CHIPSETS is not set
++CONFIG_IDEDMA_AUTO=y
++# CONFIG_IDEDMA_IVB is not set
++# CONFIG_DMA_NONPCI is not set
++# CONFIG_BLK_DEV_ATARAID is not set
++# CONFIG_BLK_DEV_ATARAID_PDC is not set
++# CONFIG_BLK_DEV_ATARAID_HPT is not set
++# CONFIG_BLK_DEV_ATARAID_MEDLEY is not set
++# CONFIG_BLK_DEV_ATARAID_SII is not set
+
+ #
+ # SCSI support
+@@ -319,9 +392,11 @@
+ # CONFIG_SCSI_MEGARAID is not set
+ # CONFIG_SCSI_MEGARAID2 is not set
+ # CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ # CONFIG_SCSI_ATA_PIIX is not set
+ # CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
+ # CONFIG_SCSI_SATA_PROMISE is not set
+ # CONFIG_SCSI_SATA_SX4 is not set
+ # CONFIG_SCSI_SATA_SIL is not set
+@@ -524,7 +599,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-mirage linux-2.4.32-rc1.mips/arch/mips/defconfig-mirage
+--- linux-2.4.32-rc1/arch/mips/defconfig-mirage 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-mirage 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -209,9 +209,7 @@
+ # CONFIG_MTD_BOSPORUS is not set
+ # CONFIG_MTD_XXS1500 is not set
+ # CONFIG_MTD_MTX1 is not set
+-# CONFIG_MTD_DB1X00 is not set
+ # CONFIG_MTD_PB1550 is not set
+-# CONFIG_MTD_HYDROGEN3 is not set
+ CONFIG_MTD_MIRAGE=y
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ # CONFIG_MTD_OCELOT is not set
+@@ -230,7 +228,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOCPROBE is not set
+@@ -335,11 +332,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -560,7 +552,6 @@
+ # CONFIG_AU1X00_USB_TTY is not set
+ # CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-mpc30x linux-2.4.32-rc1.mips/arch/mips/defconfig-mpc30x
+--- linux-2.4.32-rc1/arch/mips/defconfig-mpc30x 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-mpc30x 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -228,11 +228,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -400,7 +395,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ # CONFIG_VR41XX_KIU is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-mtx-1 linux-2.4.32-rc1.mips/arch/mips/defconfig-mtx-1
+--- linux-2.4.32-rc1/arch/mips/defconfig-mtx-1 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-mtx-1 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ CONFIG_MIPS_MTX1=y
+ # CONFIG_COGENT_CSB250 is not set
+@@ -193,9 +193,7 @@
+ # CONFIG_MTD_BOSPORUS is not set
+ # CONFIG_MTD_XXS1500 is not set
+ CONFIG_MTD_MTX1=y
+-# CONFIG_MTD_DB1X00 is not set
+ # CONFIG_MTD_PB1550 is not set
+-# CONFIG_MTD_HYDROGEN3 is not set
+ # CONFIG_MTD_MIRAGE is not set
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ # CONFIG_MTD_OCELOT is not set
+@@ -214,7 +212,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOCPROBE is not set
+@@ -371,11 +368,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ CONFIG_BRIDGE=m
+ # CONFIG_X25 is not set
+@@ -479,9 +471,11 @@
+ # CONFIG_SCSI_MEGARAID is not set
+ # CONFIG_SCSI_MEGARAID2 is not set
+ # CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ # CONFIG_SCSI_ATA_PIIX is not set
+ # CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
+ # CONFIG_SCSI_SATA_PROMISE is not set
+ # CONFIG_SCSI_SATA_SX4 is not set
+ # CONFIG_SCSI_SATA_SIL is not set
+@@ -700,7 +694,6 @@
+ # CONFIG_AU1X00_USB_TTY is not set
+ # CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-nino linux-2.4.32-rc1.mips/arch/mips/defconfig-nino
+--- linux-2.4.32-rc1/arch/mips/defconfig-nino 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-nino 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -226,11 +226,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -339,7 +334,6 @@
+ # CONFIG_SERIAL_TXX9 is not set
+ # CONFIG_SERIAL_TXX9_CONSOLE is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ # CONFIG_UNIX98_PTYS is not set
+
+ #
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-ocelot linux-2.4.32-rc1.mips/arch/mips/defconfig-ocelot
+--- linux-2.4.32-rc1/arch/mips/defconfig-ocelot 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-ocelot 2005-03-18 13:13:21.000000000 +0100
+@@ -28,8 +28,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -194,9 +194,7 @@
+ # CONFIG_MTD_BOSPORUS is not set
+ # CONFIG_MTD_XXS1500 is not set
+ # CONFIG_MTD_MTX1 is not set
+-# CONFIG_MTD_DB1X00 is not set
+ # CONFIG_MTD_PB1550 is not set
+-# CONFIG_MTD_HYDROGEN3 is not set
+ # CONFIG_MTD_MIRAGE is not set
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ CONFIG_MTD_OCELOT=y
+@@ -215,7 +213,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ CONFIG_MTD_DOC2000=y
+ # CONFIG_MTD_DOC2001 is not set
+ CONFIG_MTD_DOCPROBE=y
+@@ -307,11 +304,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -513,7 +505,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-osprey linux-2.4.32-rc1.mips/arch/mips/defconfig-osprey
+--- linux-2.4.32-rc1/arch/mips/defconfig-osprey 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-osprey 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -227,11 +227,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -388,7 +383,6 @@
+ # CONFIG_SERIAL_MULTIPORT is not set
+ # CONFIG_HUB6 is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ # CONFIG_VR41XX_KIU is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-pb1000 linux-2.4.32-rc1.mips/arch/mips/defconfig-pb1000
+--- linux-2.4.32-rc1/arch/mips/defconfig-pb1000 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-pb1000 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ CONFIG_MIPS_PB1000=y
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -215,9 +215,7 @@
+ # CONFIG_MTD_BOSPORUS is not set
+ # CONFIG_MTD_XXS1500 is not set
+ # CONFIG_MTD_MTX1 is not set
+-# CONFIG_MTD_DB1X00 is not set
+ # CONFIG_MTD_PB1550 is not set
+-# CONFIG_MTD_HYDROGEN3 is not set
+ # CONFIG_MTD_MIRAGE is not set
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ # CONFIG_MTD_OCELOT is not set
+@@ -236,7 +234,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOCPROBE is not set
+@@ -324,11 +321,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -622,7 +614,6 @@
+ # CONFIG_AU1X00_USB_TTY is not set
+ # CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+@@ -707,7 +698,7 @@
+ #
+ # CONFIG_PCMCIA_SERIAL_CS is not set
+ # CONFIG_SYNCLINK_CS is not set
+-CONFIG_AU1X00_GPIO=m
++CONFIG_AU1X00_GPIO=y
+ # CONFIG_TS_AU1X00_ADS7846 is not set
+
+ #
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-pb1100 linux-2.4.32-rc1.mips/arch/mips/defconfig-pb1100
+--- linux-2.4.32-rc1/arch/mips/defconfig-pb1100 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-pb1100 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ CONFIG_MIPS_PB1100=y
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -198,9 +198,7 @@
+ # CONFIG_MTD_MTX1 is not set
+ CONFIG_MTD_PB1500_BOOT=y
+ CONFIG_MTD_PB1500_USER=y
+-# CONFIG_MTD_DB1X00 is not set
+ # CONFIG_MTD_PB1550 is not set
+-# CONFIG_MTD_HYDROGEN3 is not set
+ # CONFIG_MTD_MIRAGE is not set
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ # CONFIG_MTD_OCELOT is not set
+@@ -219,7 +217,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOCPROBE is not set
+@@ -324,11 +321,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -613,7 +605,6 @@
+ # CONFIG_AU1X00_USB_TTY is not set
+ # CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+@@ -859,6 +850,7 @@
+ # CONFIG_FB_PM2 is not set
+ # CONFIG_FB_PM3 is not set
+ # CONFIG_FB_CYBER2000 is not set
++CONFIG_FB_AU1100=y
+ # CONFIG_FB_MATROX is not set
+ # CONFIG_FB_ATY is not set
+ # CONFIG_FB_RADEON is not set
+@@ -870,7 +862,6 @@
+ # CONFIG_FB_VOODOO1 is not set
+ # CONFIG_FB_TRIDENT is not set
+ # CONFIG_FB_E1356 is not set
+-CONFIG_FB_AU1100=y
+ # CONFIG_FB_IT8181 is not set
+ # CONFIG_FB_VIRTUAL is not set
+ CONFIG_FBCON_ADVANCED=y
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-pb1200 linux-2.4.32-rc1.mips/arch/mips/defconfig-pb1200
+--- linux-2.4.32-rc1/arch/mips/defconfig-pb1200 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-pb1200 2005-03-18 13:13:21.000000000 +0100
+@@ -0,0 +1,1060 @@
++#
++# Automatically generated make config: don't edit
++#
++CONFIG_MIPS=y
++CONFIG_MIPS32=y
++# CONFIG_MIPS64 is not set
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++# CONFIG_MODVERSIONS is not set
++CONFIG_KMOD=y
++
++#
++# Machine selection
++#
++# CONFIG_ACER_PICA_61 is not set
++# CONFIG_MIPS_BOSPORUS is not set
++# CONFIG_MIPS_MIRAGE is not set
++# CONFIG_MIPS_DB1000 is not set
++# CONFIG_MIPS_DB1100 is not set
++# CONFIG_MIPS_DB1500 is not set
++# CONFIG_MIPS_DB1550 is not set
++# CONFIG_MIPS_PB1000 is not set
++# CONFIG_MIPS_PB1100 is not set
++# CONFIG_MIPS_PB1500 is not set
++# CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
++# CONFIG_MIPS_XXS1500 is not set
++# CONFIG_MIPS_MTX1 is not set
++# CONFIG_COGENT_CSB250 is not set
++# CONFIG_BAGET_MIPS is not set
++# CONFIG_CASIO_E55 is not set
++# CONFIG_MIPS_COBALT is not set
++# CONFIG_DECSTATION is not set
++# CONFIG_MIPS_EV64120 is not set
++# CONFIG_MIPS_EV96100 is not set
++# CONFIG_MIPS_IVR is not set
++# CONFIG_HP_LASERJET is not set
++# CONFIG_IBM_WORKPAD is not set
++# CONFIG_LASAT is not set
++# CONFIG_MIPS_ITE8172 is not set
++# CONFIG_MIPS_ATLAS is not set
++# CONFIG_MIPS_MAGNUM_4000 is not set
++# CONFIG_MIPS_MALTA is not set
++# CONFIG_MIPS_SEAD is not set
++# CONFIG_MOMENCO_OCELOT is not set
++# CONFIG_MOMENCO_OCELOT_G is not set
++# CONFIG_MOMENCO_OCELOT_C is not set
++# CONFIG_MOMENCO_JAGUAR_ATX is not set
++# CONFIG_PMC_BIG_SUR is not set
++# CONFIG_PMC_STRETCH is not set
++# CONFIG_PMC_YOSEMITE is not set
++# CONFIG_DDB5074 is not set
++# CONFIG_DDB5476 is not set
++# CONFIG_DDB5477 is not set
++# CONFIG_NEC_OSPREY is not set
++# CONFIG_NEC_EAGLE is not set
++# CONFIG_OLIVETTI_M700 is not set
++# CONFIG_NINO is not set
++# CONFIG_SGI_IP22 is not set
++# CONFIG_SGI_IP27 is not set
++# CONFIG_SIBYTE_SB1xxx_SOC is not set
++# CONFIG_SNI_RM200_PCI is not set
++# CONFIG_TANBAC_TB0226 is not set
++# CONFIG_TANBAC_TB0229 is not set
++# CONFIG_TOSHIBA_JMR3927 is not set
++# CONFIG_TOSHIBA_RBTX4927 is not set
++# CONFIG_VICTOR_MPC30X is not set
++# CONFIG_ZAO_CAPCELLA is not set
++# CONFIG_HIGHMEM is not set
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++CONFIG_SOC_AU1X00=y
++CONFIG_SOC_AU1200=y
++CONFIG_NONCOHERENT_IO=y
++CONFIG_PC_KEYB=y
++# CONFIG_MIPS_AU1000 is not set
++
++#
++# CPU selection
++#
++CONFIG_CPU_MIPS32=y
++# CONFIG_CPU_MIPS64 is not set
++# CONFIG_CPU_R3000 is not set
++# CONFIG_CPU_TX39XX is not set
++# CONFIG_CPU_VR41XX is not set
++# CONFIG_CPU_R4300 is not set
++# CONFIG_CPU_R4X00 is not set
++# CONFIG_CPU_TX49XX is not set
++# CONFIG_CPU_R5000 is not set
++# CONFIG_CPU_R5432 is not set
++# CONFIG_CPU_R6000 is not set
++# CONFIG_CPU_NEVADA is not set
++# CONFIG_CPU_R8000 is not set
++# CONFIG_CPU_R10000 is not set
++# CONFIG_CPU_RM7000 is not set
++# CONFIG_CPU_RM9000 is not set
++# CONFIG_CPU_SB1 is not set
++CONFIG_PAGE_SIZE_4KB=y
++# CONFIG_PAGE_SIZE_16KB is not set
++# CONFIG_PAGE_SIZE_64KB is not set
++CONFIG_CPU_HAS_PREFETCH=y
++# CONFIG_VTAG_ICACHE is not set
++CONFIG_64BIT_PHYS_ADDR=y
++# CONFIG_CPU_ADVANCED is not set
++CONFIG_CPU_HAS_LLSC=y
++# CONFIG_CPU_HAS_LLDSCD is not set
++# CONFIG_CPU_HAS_WB is not set
++CONFIG_CPU_HAS_SYNC=y
++
++#
++# General setup
++#
++CONFIG_CPU_LITTLE_ENDIAN=y
++# CONFIG_BUILD_ELF64 is not set
++CONFIG_NET=y
++CONFIG_PCI=y
++CONFIG_PCI_NEW=y
++CONFIG_PCI_AUTO=y
++# CONFIG_PCI_NAMES is not set
++# CONFIG_ISA is not set
++# CONFIG_TC is not set
++# CONFIG_MCA is not set
++# CONFIG_SBUS is not set
++CONFIG_HOTPLUG=y
++
++#
++# PCMCIA/CardBus support
++#
++CONFIG_PCMCIA=m
++# CONFIG_CARDBUS is not set
++# CONFIG_TCIC is not set
++# CONFIG_I82092 is not set
++# CONFIG_I82365 is not set
++CONFIG_PCMCIA_AU1X00=m
++
++#
++# PCI Hotplug Support
++#
++# CONFIG_HOTPLUG_PCI is not set
++# CONFIG_HOTPLUG_PCI_COMPAQ is not set
++# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
++# CONFIG_HOTPLUG_PCI_SHPC is not set
++# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set
++# CONFIG_HOTPLUG_PCI_PCIE is not set
++# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
++CONFIG_SYSVIPC=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++CONFIG_SYSCTL=y
++CONFIG_KCORE_ELF=y
++# CONFIG_KCORE_AOUT is not set
++# CONFIG_BINFMT_AOUT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_MIPS32_COMPAT is not set
++# CONFIG_MIPS32_O32 is not set
++# CONFIG_MIPS32_N32 is not set
++# CONFIG_BINFMT_ELF32 is not set
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_OOM_KILLER is not set
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE="mem=96M"
++# CONFIG_PM is not set
++
++#
++# Memory Technology Devices (MTD)
++#
++# CONFIG_MTD is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play configuration
++#
++# CONFIG_PNP is not set
++# CONFIG_ISAPNP is not set
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_XD is not set
++# CONFIG_PARIDE is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_CISS_SCSI_TAPE is not set
++# CONFIG_CISS_MONITOR_THREAD is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_RAM is not set
++# CONFIG_BLK_DEV_INITRD is not set
++# CONFIG_BLK_STATS is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++# CONFIG_BLK_DEV_MD is not set
++# CONFIG_MD_LINEAR is not set
++# CONFIG_MD_RAID0 is not set
++# CONFIG_MD_RAID1 is not set
++# CONFIG_MD_RAID5 is not set
++# CONFIG_MD_MULTIPATH is not set
++# CONFIG_BLK_DEV_LVM is not set
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++# CONFIG_NETLINK_DEV is not set
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++CONFIG_FILTER=y
++CONFIG_UNIX=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_PNP=y
++# CONFIG_IP_PNP_DHCP is not set
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_INET_ECN is not set
++# CONFIG_SYN_COOKIES is not set
++
++#
++# IP: Netfilter Configuration
++#
++# CONFIG_IP_NF_CONNTRACK is not set
++# CONFIG_IP_NF_QUEUE is not set
++# CONFIG_IP_NF_IPTABLES is not set
++# CONFIG_IP_NF_ARPTABLES is not set
++# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
++# CONFIG_IP_NF_COMPAT_IPFWADM is not set
++
++#
++# IP: Virtual Server Configuration
++#
++# CONFIG_IP_VS is not set
++# CONFIG_IPV6 is not set
++# CONFIG_KHTTPD is not set
++
++#
++# SCTP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_SCTP is not set
++# CONFIG_ATM is not set
++# CONFIG_VLAN_8021Q is not set
++
++#
++#
++#
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_DECNET is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_LLC is not set
++# CONFIG_NET_DIVERT is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_FASTROUTE is not set
++# CONFIG_NET_HW_FLOWCONTROL is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++
++#
++# Telephony Support
++#
++# CONFIG_PHONE is not set
++# CONFIG_PHONE_IXJ is not set
++# CONFIG_PHONE_IXJ_PCMCIA is not set
++
++#
++# ATA/IDE/MFM/RLL support
++#
++CONFIG_IDE=y
++
++#
++# IDE, ATA and ATAPI Block devices
++#
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_HD_IDE is not set
++# CONFIG_BLK_DEV_HD is not set
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++CONFIG_IDEDISK_MULTI_MODE=y
++CONFIG_IDEDISK_STROKE=y
++CONFIG_BLK_DEV_IDECS=m
++# CONFIG_BLK_DEV_DELKIN is not set
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_BLK_DEV_IDESCSI is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++
++#
++# IDE chipset support/bugfixes
++#
++# CONFIG_BLK_DEV_CMD640 is not set
++# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
++# CONFIG_BLK_DEV_ISAPNP is not set
++# CONFIG_BLK_DEV_IDEPCI is not set
++# CONFIG_IDE_CHIPSETS is not set
++# CONFIG_IDEDMA_AUTO is not set
++# CONFIG_DMA_NONPCI is not set
++# CONFIG_BLK_DEV_ATARAID is not set
++# CONFIG_BLK_DEV_ATARAID_PDC is not set
++# CONFIG_BLK_DEV_ATARAID_HPT is not set
++# CONFIG_BLK_DEV_ATARAID_MEDLEY is not set
++# CONFIG_BLK_DEV_ATARAID_SII is not set
++
++#
++# SCSI support
++#
++CONFIG_SCSI=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++CONFIG_SD_EXTRA_DEVS=40
++CONFIG_CHR_DEV_ST=y
++# CONFIG_CHR_DEV_OSST is not set
++CONFIG_BLK_DEV_SR=y
++# CONFIG_BLK_DEV_SR_VENDOR is not set
++CONFIG_SR_EXTRA_DEVS=2
++# CONFIG_CHR_DEV_SG is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_DEBUG_QUEUES is not set
++# CONFIG_SCSI_MULTI_LUN is not set
++CONFIG_SCSI_CONSTANTS=y
++# CONFIG_SCSI_LOGGING is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_7000FASST is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AHA152X is not set
++# CONFIG_SCSI_AHA1542 is not set
++# CONFIG_SCSI_AHA1740 is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_IN2000 is not set
++# CONFIG_SCSI_AM53C974 is not set
++# CONFIG_SCSI_MEGARAID is not set
++# CONFIG_SCSI_MEGARAID2 is not set
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
++# CONFIG_SCSI_SATA_SVW is not set
++# CONFIG_SCSI_ATA_PIIX is not set
++# CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
++# CONFIG_SCSI_SATA_PROMISE is not set
++# CONFIG_SCSI_SATA_SX4 is not set
++# CONFIG_SCSI_SATA_SIL is not set
++# CONFIG_SCSI_SATA_SIS is not set
++# CONFIG_SCSI_SATA_ULI is not set
++# CONFIG_SCSI_SATA_VIA is not set
++# CONFIG_SCSI_SATA_VITESSE is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_CPQFCTS is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_DTC3280 is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_EATA_DMA is not set
++# CONFIG_SCSI_EATA_PIO is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_GENERIC_NCR5380 is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_NCR53C406A is not set
++# CONFIG_SCSI_NCR53C7xx is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_NCR53C8XX is not set
++# CONFIG_SCSI_SYM53C8XX is not set
++# CONFIG_SCSI_PAS16 is not set
++# CONFIG_SCSI_PCI2000 is not set
++# CONFIG_SCSI_PCI2220I is not set
++# CONFIG_SCSI_PSI240I is not set
++# CONFIG_SCSI_QLOGIC_FAS is not set
++# CONFIG_SCSI_QLOGIC_ISP is not set
++# CONFIG_SCSI_QLOGIC_FC is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_SIM710 is not set
++# CONFIG_SCSI_SYM53C416 is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_T128 is not set
++# CONFIG_SCSI_U14_34F is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# PCMCIA SCSI adapter support
++#
++# CONFIG_SCSI_PCMCIA is not set
++
++#
++# Fusion MPT device support
++#
++# CONFIG_FUSION is not set
++# CONFIG_FUSION_BOOT is not set
++# CONFIG_FUSION_ISENSE is not set
++# CONFIG_FUSION_CTL is not set
++# CONFIG_FUSION_LAN is not set
++
++#
++# IEEE 1394 (FireWire) support (EXPERIMENTAL)
++#
++# CONFIG_IEEE1394 is not set
++
++#
++# I2O device support
++#
++# CONFIG_I2O is not set
++# CONFIG_I2O_PCI is not set
++# CONFIG_I2O_BLOCK is not set
++# CONFIG_I2O_LAN is not set
++# CONFIG_I2O_SCSI is not set
++# CONFIG_I2O_PROC is not set
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++
++#
++# ARCnet devices
++#
++# CONFIG_ARCNET is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_ETHERTAP is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++# CONFIG_MIPS_AU1X00_ENET is not set
++# CONFIG_SUNLANCE is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNBMAC is not set
++# CONFIG_SUNQE is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_LANCE is not set
++# CONFIG_NET_VENDOR_SMC is not set
++# CONFIG_NET_VENDOR_RACAL is not set
++# CONFIG_HP100 is not set
++# CONFIG_NET_ISA is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_NET_POCKET is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_MYRI_SBUS is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PLIP is not set
++CONFIG_PPP=m
++CONFIG_PPP_MULTILINK=y
++# CONFIG_PPP_FILTER is not set
++CONFIG_PPP_ASYNC=m
++# CONFIG_PPP_SYNC_TTY is not set
++CONFIG_PPP_DEFLATE=m
++# CONFIG_PPP_BSDCOMP is not set
++CONFIG_PPPOE=m
++# CONFIG_SLIP is not set
++
++#
++# Wireless LAN (non-hamradio)
++#
++# CONFIG_NET_RADIO is not set
++
++#
++# Token Ring devices
++#
++# CONFIG_TR is not set
++# CONFIG_NET_FC is not set
++# CONFIG_RCPCI is not set
++# CONFIG_SHAPER is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++
++#
++# PCMCIA network device support
++#
++# CONFIG_NET_PCMCIA is not set
++
++#
++# Amateur Radio support
++#
++# CONFIG_HAMRADIO is not set
++
++#
++# IrDA (infrared) support
++#
++# CONFIG_IRDA is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Input core support
++#
++CONFIG_INPUT=y
++CONFIG_INPUT_KEYBDEV=y
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_UINPUT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++# CONFIG_VT_CONSOLE is not set
++# CONFIG_SERIAL is not set
++# CONFIG_SERIAL_EXTENDED is not set
++CONFIG_SERIAL_NONSTANDARD=y
++# CONFIG_COMPUTONE is not set
++# CONFIG_ROCKETPORT is not set
++# CONFIG_CYCLADES is not set
++# CONFIG_DIGIEPCA is not set
++# CONFIG_DIGI is not set
++# CONFIG_ESPSERIAL is not set
++# CONFIG_MOXA_INTELLIO is not set
++# CONFIG_MOXA_SMARTIO is not set
++# CONFIG_ISI is not set
++# CONFIG_SYNCLINK is not set
++# CONFIG_SYNCLINKMP is not set
++# CONFIG_N_HDLC is not set
++# CONFIG_RISCOM8 is not set
++# CONFIG_SPECIALIX is not set
++# CONFIG_SX is not set
++# CONFIG_RIO is not set
++# CONFIG_STALDRV is not set
++# CONFIG_SERIAL_TX3912 is not set
++# CONFIG_SERIAL_TX3912_CONSOLE is not set
++# CONFIG_SERIAL_TXX9 is not set
++# CONFIG_SERIAL_TXX9_CONSOLE is not set
++CONFIG_AU1X00_UART=y
++CONFIG_AU1X00_SERIAL_CONSOLE=y
++# CONFIG_AU1X00_USB_TTY is not set
++# CONFIG_AU1X00_USB_RAW is not set
++# CONFIG_TXX927_SERIAL is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_UNIX98_PTY_COUNT=256
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_SCx200_ACB is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_CHARDEV is not set
++CONFIG_I2C_PROC=y
++
++#
++# Mice
++#
++# CONFIG_BUSMOUSE is not set
++# CONFIG_MOUSE is not set
++
++#
++# Joysticks
++#
++# CONFIG_INPUT_GAMEPORT is not set
++# CONFIG_INPUT_NS558 is not set
++# CONFIG_INPUT_LIGHTNING is not set
++# CONFIG_INPUT_PCIGAME is not set
++# CONFIG_INPUT_CS461X is not set
++# CONFIG_INPUT_EMU10K1 is not set
++# CONFIG_INPUT_SERIO is not set
++# CONFIG_INPUT_SERPORT is not set
++
++#
++# Joysticks
++#
++# CONFIG_INPUT_ANALOG is not set
++# CONFIG_INPUT_A3D is not set
++# CONFIG_INPUT_ADI is not set
++# CONFIG_INPUT_COBRA is not set
++# CONFIG_INPUT_GF2K is not set
++# CONFIG_INPUT_GRIP is not set
++# CONFIG_INPUT_INTERACT is not set
++# CONFIG_INPUT_TMDC is not set
++# CONFIG_INPUT_SIDEWINDER is not set
++# CONFIG_INPUT_IFORCE_USB is not set
++# CONFIG_INPUT_IFORCE_232 is not set
++# CONFIG_INPUT_WARRIOR is not set
++# CONFIG_INPUT_MAGELLAN is not set
++# CONFIG_INPUT_SPACEORB is not set
++# CONFIG_INPUT_SPACEBALL is not set
++# CONFIG_INPUT_STINGER is not set
++# CONFIG_INPUT_DB9 is not set
++# CONFIG_INPUT_GAMECON is not set
++# CONFIG_INPUT_TURBOGRAFX is not set
++# CONFIG_QIC02_TAPE is not set
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_IPMI_PANIC_EVENT is not set
++# CONFIG_IPMI_DEVICE_INTERFACE is not set
++# CONFIG_IPMI_KCS is not set
++# CONFIG_IPMI_WATCHDOG is not set
++
++#
++# Watchdog Cards
++#
++# CONFIG_WATCHDOG is not set
++# CONFIG_SCx200 is not set
++# CONFIG_SCx200_GPIO is not set
++# CONFIG_AMD_PM768 is not set
++# CONFIG_NVRAM is not set
++# CONFIG_RTC is not set
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++# CONFIG_FTAPE is not set
++# CONFIG_AGP is not set
++
++#
++# Direct Rendering Manager (XFree86 DRI support)
++#
++# CONFIG_DRM is not set
++
++#
++# PCMCIA character devices
++#
++# CONFIG_PCMCIA_SERIAL_CS is not set
++# CONFIG_SYNCLINK_CS is not set
++# CONFIG_AU1X00_GPIO is not set
++# CONFIG_TS_AU1X00_ADS7846 is not set
++
++#
++# File systems
++#
++# CONFIG_QUOTA is not set
++# CONFIG_QFMT_V2 is not set
++CONFIG_AUTOFS_FS=y
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_REISERFS_CHECK is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++# CONFIG_ADFS_FS is not set
++# CONFIG_ADFS_FS_RW is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BEFS_DEBUG is not set
++# CONFIG_BFS_FS is not set
++CONFIG_EXT3_FS=y
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++# CONFIG_UMSDOS_FS is not set
++CONFIG_VFAT_FS=y
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++CONFIG_TMPFS=y
++CONFIG_RAMFS=y
++# CONFIG_ISO9660_FS is not set
++# CONFIG_JOLIET is not set
++# CONFIG_ZISOFS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_JFS_DEBUG is not set
++# CONFIG_JFS_STATISTICS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_NTFS_FS is not set
++# CONFIG_NTFS_RW is not set
++# CONFIG_HPFS_FS is not set
++CONFIG_PROC_FS=y
++# CONFIG_DEVFS_FS is not set
++# CONFIG_DEVFS_MOUNT is not set
++# CONFIG_DEVFS_DEBUG is not set
++CONFIG_DEVPTS_FS=y
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_QNX4FS_RW is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_EXT2_FS=y
++# CONFIG_SYSV_FS is not set
++# CONFIG_UDF_FS is not set
++# CONFIG_UDF_RW is not set
++# CONFIG_UFS_FS is not set
++# CONFIG_UFS_FS_WRITE is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_XFS_QUOTA is not set
++# CONFIG_XFS_RT is not set
++# CONFIG_XFS_TRACE is not set
++# CONFIG_XFS_DEBUG is not set
++
++#
++# Network File Systems
++#
++# CONFIG_CODA_FS is not set
++# CONFIG_INTERMEZZO_FS is not set
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_DIRECTIO is not set
++CONFIG_ROOT_NFS=y
++# CONFIG_NFSD is not set
++# CONFIG_NFSD_V3 is not set
++# CONFIG_NFSD_TCP is not set
++CONFIG_SUNRPC=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++# CONFIG_SMB_FS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_NCPFS_PACKET_SIGNING is not set
++# CONFIG_NCPFS_IOCTL_LOCKING is not set
++# CONFIG_NCPFS_STRONG is not set
++# CONFIG_NCPFS_NFS_NS is not set
++# CONFIG_NCPFS_OS2_NS is not set
++# CONFIG_NCPFS_SMALLDOS is not set
++# CONFIG_NCPFS_NLS is not set
++# CONFIG_NCPFS_EXTRAS is not set
++# CONFIG_ZISOFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_SMB_NLS is not set
++CONFIG_NLS=y
++
++#
++# Native Language Support
++#
++CONFIG_NLS_DEFAULT="iso8859-1"
++# CONFIG_NLS_CODEPAGE_437 is not set
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ISO8859_1 is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Console drivers
++#
++# CONFIG_VGA_CONSOLE is not set
++# CONFIG_MDA_CONSOLE is not set
++
++#
++# Frame-buffer support
++#
++CONFIG_FB=y
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_FB_RIVA is not set
++# CONFIG_FB_CLGEN is not set
++# CONFIG_FB_PM2 is not set
++# CONFIG_FB_PM3 is not set
++# CONFIG_FB_CYBER2000 is not set
++# CONFIG_FB_MATROX is not set
++# CONFIG_FB_ATY is not set
++# CONFIG_FB_RADEON is not set
++# CONFIG_FB_ATY128 is not set
++# CONFIG_FB_INTEL is not set
++# CONFIG_FB_SIS is not set
++# CONFIG_FB_NEOMAGIC is not set
++# CONFIG_FB_3DFX is not set
++# CONFIG_FB_VOODOO1 is not set
++# CONFIG_FB_TRIDENT is not set
++# CONFIG_FB_E1356 is not set
++# CONFIG_FB_IT8181 is not set
++# CONFIG_FB_VIRTUAL is not set
++CONFIG_FBCON_ADVANCED=y
++# CONFIG_FBCON_MFB is not set
++# CONFIG_FBCON_CFB2 is not set
++# CONFIG_FBCON_CFB4 is not set
++# CONFIG_FBCON_CFB8 is not set
++CONFIG_FBCON_CFB16=y
++# CONFIG_FBCON_CFB24 is not set
++CONFIG_FBCON_CFB32=y
++# CONFIG_FBCON_AFB is not set
++# CONFIG_FBCON_ILBM is not set
++# CONFIG_FBCON_IPLAN2P2 is not set
++# CONFIG_FBCON_IPLAN2P4 is not set
++# CONFIG_FBCON_IPLAN2P8 is not set
++# CONFIG_FBCON_MAC is not set
++# CONFIG_FBCON_VGA_PLANES is not set
++# CONFIG_FBCON_VGA is not set
++# CONFIG_FBCON_HGA is not set
++# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
++CONFIG_FBCON_FONTS=y
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++# CONFIG_FONT_SUN8x16 is not set
++# CONFIG_FONT_SUN12x22 is not set
++# CONFIG_FONT_6x11 is not set
++# CONFIG_FONT_PEARL_8x8 is not set
++# CONFIG_FONT_ACORN_8x8 is not set
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++# CONFIG_SOUND_ALI5455 is not set
++# CONFIG_SOUND_BT878 is not set
++# CONFIG_SOUND_CMPCI is not set
++# CONFIG_SOUND_EMU10K1 is not set
++# CONFIG_MIDI_EMU10K1 is not set
++# CONFIG_SOUND_FUSION is not set
++# CONFIG_SOUND_CS4281 is not set
++# CONFIG_SOUND_ES1370 is not set
++# CONFIG_SOUND_ES1371 is not set
++# CONFIG_SOUND_ESSSOLO1 is not set
++# CONFIG_SOUND_MAESTRO is not set
++# CONFIG_SOUND_MAESTRO3 is not set
++# CONFIG_SOUND_FORTE is not set
++# CONFIG_SOUND_ICH is not set
++# CONFIG_SOUND_RME96XX is not set
++# CONFIG_SOUND_SONICVIBES is not set
++# CONFIG_SOUND_AU1X00 is not set
++CONFIG_SOUND_AU1550_PSC=y
++# CONFIG_SOUND_AU1550_I2S is not set
++# CONFIG_SOUND_TRIDENT is not set
++# CONFIG_SOUND_MSNDCLAS is not set
++# CONFIG_SOUND_MSNDPIN is not set
++# CONFIG_SOUND_VIA82CXXX is not set
++# CONFIG_MIDI_VIA82CXXX is not set
++# CONFIG_SOUND_OSS is not set
++# CONFIG_SOUND_TVMIXER is not set
++# CONFIG_SOUND_AD1980 is not set
++# CONFIG_SOUND_WM97XX is not set
++
++#
++# USB support
++#
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++# CONFIG_USB_BANDWIDTH is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_EHCI_HCD is not set
++# CONFIG_USB_UHCI is not set
++# CONFIG_USB_UHCI_ALT is not set
++CONFIG_USB_OHCI=y
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_AUDIO is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_BLUETOOTH is not set
++# CONFIG_USB_MIDI is not set
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_HP8200e is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# USB Human Interface Devices (HID)
++#
++CONFIG_USB_HID=y
++CONFIG_USB_HIDINPUT=y
++CONFIG_USB_HIDDEV=y
++# CONFIG_USB_AIPTEK is not set
++# CONFIG_USB_WACOM is not set
++# CONFIG_USB_KBTAB is not set
++# CONFIG_USB_POWERMATE is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_DC2XX is not set
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_SCANNER is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_HPUSBSCSI is not set
++
++#
++# USB Multimedia devices
++#
++
++#
++# Video4Linux support is needed for USB Multimedia device support
++#
++
++#
++# USB Network adaptors
++#
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_CDCETHER is not set
++# CONFIG_USB_USBNET is not set
++
++#
++# USB port drivers
++#
++# CONFIG_USB_USS720 is not set
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_TIGL is not set
++# CONFIG_USB_BRLVGER is not set
++# CONFIG_USB_LCD is not set
++
++#
++# Support for USB gadgets
++#
++# CONFIG_USB_GADGET is not set
++
++#
++# Bluetooth support
++#
++# CONFIG_BLUEZ is not set
++
++#
++# Kernel hacking
++#
++CONFIG_CROSSCOMPILE=y
++# CONFIG_RUNTIME_DEBUG is not set
++# CONFIG_KGDB is not set
++# CONFIG_GDB_CONSOLE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_MIPS_UNCACHED is not set
++CONFIG_LOG_BUF_SHIFT=0
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++# CONFIG_CRC32 is not set
++CONFIG_ZLIB_INFLATE=m
++CONFIG_ZLIB_DEFLATE=m
++# CONFIG_FW_LOADER is not set
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-pb1500 linux-2.4.32-rc1.mips/arch/mips/defconfig-pb1500
+--- linux-2.4.32-rc1/arch/mips/defconfig-pb1500 2005-01-19 15:09:28.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-pb1500 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ CONFIG_MIPS_PB1500=y
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -215,9 +215,7 @@
+ # CONFIG_MTD_MTX1 is not set
+ CONFIG_MTD_PB1500_BOOT=y
+ # CONFIG_MTD_PB1500_USER is not set
+-# CONFIG_MTD_DB1X00 is not set
+ # CONFIG_MTD_PB1550 is not set
+-# CONFIG_MTD_HYDROGEN3 is not set
+ # CONFIG_MTD_MIRAGE is not set
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ # CONFIG_MTD_OCELOT is not set
+@@ -236,7 +234,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOCPROBE is not set
+@@ -341,11 +338,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -675,7 +667,6 @@
+ # CONFIG_AU1X00_USB_TTY is not set
+ # CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-pb1550 linux-2.4.32-rc1.mips/arch/mips/defconfig-pb1550
+--- linux-2.4.32-rc1/arch/mips/defconfig-pb1550 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-pb1550 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ CONFIG_MIPS_PB1550=y
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -213,11 +213,9 @@
+ # CONFIG_MTD_BOSPORUS is not set
+ # CONFIG_MTD_XXS1500 is not set
+ # CONFIG_MTD_MTX1 is not set
+-# CONFIG_MTD_DB1X00 is not set
+ CONFIG_MTD_PB1550=y
+ CONFIG_MTD_PB1550_BOOT=y
+ CONFIG_MTD_PB1550_USER=y
+-# CONFIG_MTD_HYDROGEN3 is not set
+ # CONFIG_MTD_MIRAGE is not set
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ # CONFIG_MTD_OCELOT is not set
+@@ -236,7 +234,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOCPROBE is not set
+@@ -343,11 +340,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -633,7 +625,6 @@
+ # CONFIG_AU1X00_USB_TTY is not set
+ # CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-rbtx4927 linux-2.4.32-rc1.mips/arch/mips/defconfig-rbtx4927
+--- linux-2.4.32-rc1/arch/mips/defconfig-rbtx4927 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-rbtx4927 2005-03-18 13:13:21.000000000 +0100
+@@ -28,8 +28,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -223,11 +223,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -466,7 +461,6 @@
+ CONFIG_SERIAL_TXX9=y
+ CONFIG_SERIAL_TXX9_CONSOLE=y
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ # CONFIG_UNIX98_PTYS is not set
+
+ #
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-rm200 linux-2.4.32-rc1.mips/arch/mips/defconfig-rm200
+--- linux-2.4.32-rc1/arch/mips/defconfig-rm200 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-rm200 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -229,11 +229,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -340,7 +335,6 @@
+ # CONFIG_SERIAL is not set
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-sb1250-swarm linux-2.4.32-rc1.mips/arch/mips/defconfig-sb1250-swarm
+--- linux-2.4.32-rc1/arch/mips/defconfig-sb1250-swarm 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-sb1250-swarm 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -90,6 +90,7 @@
+ # CONFIG_SIBYTE_TBPROF is not set
+ CONFIG_SIBYTE_GENBUS_IDE=y
+ CONFIG_SMP_CAPABLE=y
++CONFIG_MIPS_RTC=y
+ # CONFIG_SNI_RM200_PCI is not set
+ # CONFIG_TANBAC_TB0226 is not set
+ # CONFIG_TANBAC_TB0229 is not set
+@@ -253,11 +254,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -469,7 +465,6 @@
+ CONFIG_SIBYTE_SB1250_DUART=y
+ CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y
+ CONFIG_SERIAL_CONSOLE=y
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-sead linux-2.4.32-rc1.mips/arch/mips/defconfig-sead
+--- linux-2.4.32-rc1/arch/mips/defconfig-sead 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-sead 2005-03-18 13:13:21.000000000 +0100
+@@ -28,8 +28,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -244,7 +244,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ # CONFIG_UNIX98_PTYS is not set
+
+ #
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-stretch linux-2.4.32-rc1.mips/arch/mips/defconfig-stretch
+--- linux-2.4.32-rc1/arch/mips/defconfig-stretch 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-stretch 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -240,11 +240,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -324,9 +319,11 @@
+ # CONFIG_SCSI_MEGARAID is not set
+ # CONFIG_SCSI_MEGARAID2 is not set
+ # CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ # CONFIG_SCSI_ATA_PIIX is not set
+ # CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
+ # CONFIG_SCSI_SATA_PROMISE is not set
+ # CONFIG_SCSI_SATA_SX4 is not set
+ # CONFIG_SCSI_SATA_SIL is not set
+@@ -516,7 +513,6 @@
+ # CONFIG_SERIAL_TXX9 is not set
+ # CONFIG_SERIAL_TXX9_CONSOLE is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-tb0226 linux-2.4.32-rc1.mips/arch/mips/defconfig-tb0226
+--- linux-2.4.32-rc1/arch/mips/defconfig-tb0226 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-tb0226 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -228,11 +228,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -312,9 +307,11 @@
+ # CONFIG_SCSI_MEGARAID is not set
+ # CONFIG_SCSI_MEGARAID2 is not set
+ # CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ # CONFIG_SCSI_ATA_PIIX is not set
+ # CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
+ # CONFIG_SCSI_SATA_PROMISE is not set
+ # CONFIG_SCSI_SATA_SX4 is not set
+ # CONFIG_SCSI_SATA_SIL is not set
+@@ -518,7 +515,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ # CONFIG_VR41XX_KIU is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-tb0229 linux-2.4.32-rc1.mips/arch/mips/defconfig-tb0229
+--- linux-2.4.32-rc1/arch/mips/defconfig-tb0229 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-tb0229 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -230,11 +230,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -445,7 +440,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ # CONFIG_VR41XX_KIU is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-ti1500 linux-2.4.32-rc1.mips/arch/mips/defconfig-ti1500
+--- linux-2.4.32-rc1/arch/mips/defconfig-ti1500 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-ti1500 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ CONFIG_MIPS_XXS1500=y
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -213,9 +213,7 @@
+ # CONFIG_MTD_BOSPORUS is not set
+ CONFIG_MTD_XXS1500=y
+ # CONFIG_MTD_MTX1 is not set
+-# CONFIG_MTD_DB1X00 is not set
+ # CONFIG_MTD_PB1550 is not set
+-# CONFIG_MTD_HYDROGEN3 is not set
+ # CONFIG_MTD_MIRAGE is not set
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ # CONFIG_MTD_OCELOT is not set
+@@ -234,7 +232,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOCPROBE is not set
+@@ -339,11 +336,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -600,7 +592,6 @@
+ # CONFIG_AU1X00_USB_TTY is not set
+ # CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-workpad linux-2.4.32-rc1.mips/arch/mips/defconfig-workpad
+--- linux-2.4.32-rc1/arch/mips/defconfig-workpad 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-workpad 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -222,11 +222,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -426,7 +421,6 @@
+ # CONFIG_SERIAL_MULTIPORT is not set
+ # CONFIG_HUB6 is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ # CONFIG_VR41XX_KIU is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-xxs1500 linux-2.4.32-rc1.mips/arch/mips/defconfig-xxs1500
+--- linux-2.4.32-rc1/arch/mips/defconfig-xxs1500 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-xxs1500 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ CONFIG_MIPS_XXS1500=y
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -213,9 +213,7 @@
+ # CONFIG_MTD_BOSPORUS is not set
+ CONFIG_MTD_XXS1500=y
+ # CONFIG_MTD_MTX1 is not set
+-# CONFIG_MTD_DB1X00 is not set
+ # CONFIG_MTD_PB1550 is not set
+-# CONFIG_MTD_HYDROGEN3 is not set
+ # CONFIG_MTD_MIRAGE is not set
+ # CONFIG_MTD_CSTM_MIPS_IXX is not set
+ # CONFIG_MTD_OCELOT is not set
+@@ -234,7 +232,6 @@
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOCPROBE is not set
+@@ -339,11 +336,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -671,7 +663,6 @@
+ # CONFIG_AU1X00_USB_TTY is not set
+ # CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/defconfig-yosemite linux-2.4.32-rc1.mips/arch/mips/defconfig-yosemite
+--- linux-2.4.32-rc1/arch/mips/defconfig-yosemite 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/defconfig-yosemite 2005-03-18 13:13:21.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -227,11 +227,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -310,9 +305,11 @@
+ # CONFIG_SCSI_MEGARAID is not set
+ # CONFIG_SCSI_MEGARAID2 is not set
+ # CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ # CONFIG_SCSI_ATA_PIIX is not set
+ # CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
+ # CONFIG_SCSI_SATA_PROMISE is not set
+ # CONFIG_SCSI_SATA_SX4 is not set
+ # CONFIG_SCSI_SATA_SIL is not set
+@@ -477,7 +474,6 @@
+ # CONFIG_SERIAL_TXX9 is not set
+ # CONFIG_SERIAL_TXX9_CONSOLE is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips/kernel/cpu-probe.c linux-2.4.32-rc1.mips/arch/mips/kernel/cpu-probe.c
+--- linux-2.4.32-rc1/arch/mips/kernel/cpu-probe.c 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/kernel/cpu-probe.c 2005-05-25 15:33:22.000000000 +0200
+@@ -34,21 +34,16 @@
+ ".set\tmips0");
+ }
+
+-/* The Au1xxx wait is available only if we run CONFIG_PM and
+- * the timer setup found we had a 32KHz counter available.
+- * There are still problems with functions that may call au1k_wait
+- * directly, but that will be discovered pretty quickly.
+- */
+-extern void (*au1k_wait_ptr)(void);
+-void au1k_wait(void)
++/* The Au1xxx wait is available only if using 32khz counter or
++ * external timer source, but specifically not CP0 Counter. */
++int allow_au1k_wait;
++
++static void au1k_wait(void)
+ {
+-#ifdef CONFIG_PM
+- unsigned long addr;
+ /* using the wait instruction makes CP0 counter unusable */
+- __asm__("la %0,au1k_wait\n\t"
+- ".set mips3\n\t"
+- "cache 0x14,0(%0)\n\t"
+- "cache 0x14,32(%0)\n\t"
++ __asm__(".set mips3\n\t"
++ "cache 0x14, 0(%0)\n\t"
++ "cache 0x14, 32(%0)\n\t"
+ "sync\n\t"
+ "nop\n\t"
+ "wait\n\t"
+@@ -57,11 +52,7 @@
+ "nop\n\t"
+ "nop\n\t"
+ ".set mips0\n\t"
+- : : "r" (addr));
+-#else
+- __asm__("nop\n\t"
+- "nop");
+-#endif
++ : : "r" (au1k_wait));
+ }
+
+ static inline void check_wait(void)
+@@ -100,20 +91,17 @@
+ cpu_wait = r4k_wait;
+ printk(" available.\n");
+ break;
+-#ifdef CONFIG_PM
+ case CPU_AU1000:
+ case CPU_AU1100:
+ case CPU_AU1500:
+ case CPU_AU1550:
+- if (au1k_wait_ptr != NULL) {
+- cpu_wait = au1k_wait_ptr;
++ case CPU_AU1200:
++ if (allow_au1k_wait) {
++ cpu_wait = au1k_wait;
+ printk(" available.\n");
+- }
+- else {
++ } else
+ printk(" unavailable.\n");
+- }
+ break;
+-#endif
+ default:
+ printk(" unavailable.\n");
+ break;
+diff -Nur linux-2.4.32-rc1/arch/mips/kernel/head.S linux-2.4.32-rc1.mips/arch/mips/kernel/head.S
+--- linux-2.4.32-rc1/arch/mips/kernel/head.S 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/kernel/head.S 2004-11-22 14:38:23.000000000 +0100
+@@ -43,9 +43,9 @@
+
+ /* Cache Error */
+ LEAF(except_vec2_generic)
++ .set push
+ .set noreorder
+ .set noat
+- .set mips0
+ /*
+ * This is a very bad place to be. Our cache error
+ * detection has triggered. If we have write-back data
+@@ -64,10 +64,9 @@
+
+ j cache_parity_error
+ nop
++ .set pop
+ END(except_vec2_generic)
+
+- .set at
+-
+ /*
+ * Special interrupt vector for embedded MIPS. This is a
+ * dedicated interrupt vector which reduces interrupt processing
+@@ -76,8 +75,11 @@
+ * size!
+ */
+ NESTED(except_vec4, 0, sp)
++ .set push
++ .set noreorder
+ 1: j 1b /* Dummy, will be replaced */
+ nop
++ .set pop
+ END(except_vec4)
+
+ /*
+@@ -87,8 +89,11 @@
+ * unconditional jump to this vector.
+ */
+ NESTED(except_vec_ejtag_debug, 0, sp)
++ .set push
++ .set noreorder
+ j ejtag_debug_handler
+ nop
++ .set pop
+ END(except_vec_ejtag_debug)
+
+ __FINIT
+@@ -97,6 +102,7 @@
+ * EJTAG debug exception handler.
+ */
+ NESTED(ejtag_debug_handler, PT_SIZE, sp)
++ .set push
+ .set noat
+ .set noreorder
+ mtc0 k0, CP0_DESAVE
+@@ -120,7 +126,7 @@
+ deret
+ .set mips0
+ nop
+- .set at
++ .set pop
+ END(ejtag_debug_handler)
+
+ __INIT
+@@ -132,13 +138,17 @@
+ * unconditional jump to this vector.
+ */
+ NESTED(except_vec_nmi, 0, sp)
++ .set push
++ .set noreorder
+ j nmi_handler
+ nop
++ .set pop
+ END(except_vec_nmi)
+
+ __FINIT
+
+ NESTED(nmi_handler, PT_SIZE, sp)
++ .set push
+ .set noat
+ .set noreorder
+ .set mips3
+@@ -147,8 +157,7 @@
+ move a0, sp
+ RESTORE_ALL
+ eret
+- .set at
+- .set mips0
++ .set pop
+ END(nmi_handler)
+
+ __INIT
+@@ -157,7 +166,20 @@
+ * Kernel entry point
+ */
+ NESTED(kernel_entry, 16, sp)
++ .set push
++ /*
++ * For the moment disable interrupts and mark the kernel mode.
++ * A full initialization of the CPU's status register is done
++ * later in per_cpu_trap_init().
++ */
++ mfc0 t0, CP0_STATUS
++ or t0, ST0_CU0|0x1f
++ xor t0, 0x1f
++ mtc0 t0, CP0_STATUS
++
+ .set noreorder
++ sll zero,3 # ehb
++ .set reorder
+
+ /*
+ * The firmware/bootloader passes argc/argp/envp
+@@ -170,8 +192,8 @@
+ la t1, (_end - 4)
+ 1:
+ addiu t0, 4
++ sw zero, (t0)
+ bne t0, t1, 1b
+- sw zero, (t0)
+
+ /*
+ * Stack for kernel and init, current variable
+@@ -182,7 +204,7 @@
+ sw t0, kernelsp
+
+ jal init_arch
+- nop
++ .set pop
+ END(kernel_entry)
+
+
+@@ -193,17 +215,26 @@
+ * function after setting up the stack and gp registers.
+ */
+ LEAF(smp_bootstrap)
+- .set push
+- .set noreorder
+- mtc0 zero, CP0_WIRED
+- CLI
++ .set push
++ /*
++ * For the moment disable interrupts and bootstrap exception
++ * vectors and mark the kernel mode. A full initialization of
++ * the CPU's status register is done later in
++ * per_cpu_trap_init().
++ */
+ mfc0 t0, CP0_STATUS
+- li t1, ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX|ST0_UX)
+- and t0, t1
+- or t0, (ST0_CU0);
++ or t0, ST0_CU0|ST0_BEV|0x1f
++ xor t0, ST0_BEV|0x1f
++ mtc0 t0, CP0_STATUS
++
++ .set noreorder
++ sll zero,3 # ehb
++ .set reorder
++
++ mtc0 zero, CP0_WIRED
++
+ jal start_secondary
+- mtc0 t0, CP0_STATUS
+- .set pop
++ .set pop
+ END(smp_bootstrap)
+ #endif
+
+diff -Nur linux-2.4.32-rc1/arch/mips/kernel/process.c linux-2.4.32-rc1.mips/arch/mips/kernel/process.c
+--- linux-2.4.32-rc1/arch/mips/kernel/process.c 2003-08-25 13:44:40.000000000 +0200
++++ linux-2.4.32-rc1.mips/arch/mips/kernel/process.c 2005-04-14 12:41:44.000000000 +0200
+@@ -128,6 +128,26 @@
+ return 1;
+ }
+
++void dump_regs(elf_greg_t *gp, struct pt_regs *regs)
++{
++ int i;
++
++ for (i = 0; i < EF_REG0; i++)
++ gp[i] = 0;
++ gp[EF_REG0] = 0;
++ for (i = 1; i <= 31; i++)
++ gp[EF_REG0 + i] = regs->regs[i];
++ gp[EF_REG26] = 0;
++ gp[EF_REG27] = 0;
++ gp[EF_LO] = regs->lo;
++ gp[EF_HI] = regs->hi;
++ gp[EF_CP0_EPC] = regs->cp0_epc;
++ gp[EF_CP0_BADVADDR] = regs->cp0_badvaddr;
++ gp[EF_CP0_STATUS] = regs->cp0_status;
++ gp[EF_CP0_CAUSE] = regs->cp0_cause;
++ gp[EF_UNUSED0] = 0;
++}
++
+ /*
+ * Create a kernel thread
+ */
+diff -Nur linux-2.4.32-rc1/arch/mips/kernel/scall_o32.S linux-2.4.32-rc1.mips/arch/mips/kernel/scall_o32.S
+--- linux-2.4.32-rc1/arch/mips/kernel/scall_o32.S 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/kernel/scall_o32.S 2005-02-07 22:21:53.000000000 +0100
+@@ -121,15 +121,14 @@
+
+ trace_a_syscall:
+ SAVE_STATIC
+- sw t2, PT_R1(sp)
++ move s0, t2
+ jal syscall_trace
+- lw t2, PT_R1(sp)
+
+ lw a0, PT_R4(sp) # Restore argument registers
+ lw a1, PT_R5(sp)
+ lw a2, PT_R6(sp)
+ lw a3, PT_R7(sp)
+- jalr t2
++ jalr s0
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+diff -Nur linux-2.4.32-rc1/arch/mips/kernel/setup.c linux-2.4.32-rc1.mips/arch/mips/kernel/setup.c
+--- linux-2.4.32-rc1/arch/mips/kernel/setup.c 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/kernel/setup.c 2005-01-13 22:15:57.000000000 +0100
+@@ -5,7 +5,7 @@
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Copyright (C) 1995 Waldorf Electronics
+- * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001 Ralf Baechle
++ * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 01, 05 Ralf Baechle
+ * Copyright (C) 1996 Stoned Elipot
+ * Copyright (C) 2000, 2001, 2002 Maciej W. Rozycki
+ */
+@@ -71,6 +71,8 @@
+ extern struct rtc_ops no_rtc_ops;
+ struct rtc_ops *rtc_ops;
+
++EXPORT_SYMBOL(rtc_ops);
++
+ #ifdef CONFIG_PC_KEYB
+ struct kbd_ops *kbd_ops;
+ #endif
+@@ -132,10 +134,6 @@
+ */
+ load_mmu();
+
+- /* Disable coprocessors and set FPU for 16/32 FPR register model */
+- clear_c0_status(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX|ST0_FR);
+- set_c0_status(ST0_CU0);
+-
+ start_kernel();
+ }
+
+diff -Nur linux-2.4.32-rc1/arch/mips/kernel/traps.c linux-2.4.32-rc1.mips/arch/mips/kernel/traps.c
+--- linux-2.4.32-rc1/arch/mips/kernel/traps.c 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/kernel/traps.c 2005-04-12 22:25:34.000000000 +0200
+@@ -452,9 +452,10 @@
+ }
+ ll_task = current;
+
++ compute_return_epc(regs);
++
+ regs->regs[(opcode & RT) >> 16] = value;
+
+- compute_return_epc(regs);
+ return;
+
+ sig:
+@@ -485,8 +486,8 @@
+ goto sig;
+ }
+ if (ll_bit == 0 || ll_task != current) {
+- regs->regs[reg] = 0;
+ compute_return_epc(regs);
++ regs->regs[reg] = 0;
+ return;
+ }
+
+@@ -495,9 +496,9 @@
+ goto sig;
+ }
+
++ compute_return_epc(regs);
+ regs->regs[reg] = 1;
+
+- compute_return_epc(regs);
+ return;
+
+ sig:
+@@ -887,12 +888,18 @@
+ void __init per_cpu_trap_init(void)
+ {
+ unsigned int cpu = smp_processor_id();
++ unsigned int status_set = ST0_CU0;
+
+- /* Some firmware leaves the BEV flag set, clear it. */
+- clear_c0_status(ST0_CU3|ST0_CU2|ST0_CU1|ST0_BEV|ST0_KX|ST0_SX|ST0_UX);
+-
++ /*
++ * Disable coprocessors and 64-bit addressing and set FPU for
++ * the 16/32 FPR register model. Reset the BEV flag that some
++ * firmware may have left set and the TS bit (for IP27). Set
++ * XX for ISA IV code to work.
++ */
+ if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
+- set_c0_status(ST0_XX);
++ status_set |= ST0_XX;
++ change_c0_status(ST0_CU|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
++ status_set);
+
+ /*
+ * Some MIPS CPUs have a dedicated interrupt vector which reduces the
+@@ -902,7 +909,7 @@
+ set_c0_cause(CAUSEF_IV);
+
+ cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
+- write_c0_context(cpu << 23);
++ TLBMISS_HANDLER_SETUP();
+
+ atomic_inc(&init_mm.mm_count);
+ current->active_mm = &init_mm;
+@@ -918,8 +925,6 @@
+ extern char except_vec4;
+ unsigned long i;
+
+- per_cpu_trap_init();
+-
+ /* Copy the generic exception handler code to it's final destination. */
+ memcpy((void *)(KSEG0 + 0x80), &except_vec1_generic, 0x80);
+
+@@ -1020,10 +1025,5 @@
+
+ flush_icache_range(KSEG0, KSEG0 + 0x400);
+
+- atomic_inc(&init_mm.mm_count); /* XXX UP? */
+- current->active_mm = &init_mm;
+-
+- /* XXX Must be done for all CPUs */
+- current_cpu_data.asid_cache = ASID_FIRST_VERSION;
+- TLBMISS_HANDLER_SETUP();
++ per_cpu_trap_init();
+ }
+diff -Nur linux-2.4.32-rc1/arch/mips/lib/rtc-no.c linux-2.4.32-rc1.mips/arch/mips/lib/rtc-no.c
+--- linux-2.4.32-rc1/arch/mips/lib/rtc-no.c 2004-02-18 14:36:30.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/lib/rtc-no.c 2005-01-13 22:15:57.000000000 +0100
+@@ -6,10 +6,9 @@
+ * Stub RTC routines to keep Linux from crashing on machine which don't
+ * have a RTC chip.
+ *
+- * Copyright (C) 1998, 2001 by Ralf Baechle
++ * Copyright (C) 1998, 2001, 2005 by Ralf Baechle
+ */
+ #include <linux/kernel.h>
+-#include <linux/module.h>
+ #include <linux/mc146818rtc.h>
+
+ static unsigned int shouldnt_happen(void)
+@@ -29,5 +28,3 @@
+ .rtc_write_data = (void *) &shouldnt_happen,
+ .rtc_bcd_mode = (void *) &shouldnt_happen
+ };
+-
+-EXPORT_SYMBOL(rtc_ops);
+diff -Nur linux-2.4.32-rc1/arch/mips/lib/rtc-std.c linux-2.4.32-rc1.mips/arch/mips/lib/rtc-std.c
+--- linux-2.4.32-rc1/arch/mips/lib/rtc-std.c 2004-02-18 14:36:30.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/lib/rtc-std.c 2005-01-13 22:15:57.000000000 +0100
+@@ -5,9 +5,8 @@
+ *
+ * RTC routines for PC style attached Dallas chip.
+ *
+- * Copyright (C) 1998, 2001 by Ralf Baechle
++ * Copyright (C) 1998, 2001, 05 by Ralf Baechle
+ */
+-#include <linux/module.h>
+ #include <linux/mc146818rtc.h>
+ #include <asm/io.h>
+
+@@ -33,5 +32,3 @@
+ &std_rtc_write_data,
+ &std_rtc_bcd_mode
+ };
+-
+-EXPORT_SYMBOL(rtc_ops);
+diff -Nur linux-2.4.32-rc1/arch/mips/Makefile linux-2.4.32-rc1.mips/arch/mips/Makefile
+--- linux-2.4.32-rc1/arch/mips/Makefile 2005-01-19 15:09:26.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/Makefile 2005-01-30 09:01:26.000000000 +0100
+@@ -211,7 +211,7 @@
+ endif
+
+ #
+-# Au1000 (Alchemy Semi PB1000) eval board
++# Au1x AMD Alchemy eval boards
+ #
+ ifdef CONFIG_MIPS_PB1000
+ LIBS += arch/mips/au1000/pb1000/pb1000.o \
+@@ -220,9 +220,6 @@
+ LOADADDR := 0x80100000
+ endif
+
+-#
+-# Au1100 (Alchemy Semi PB1100) eval board
+-#
+ ifdef CONFIG_MIPS_PB1100
+ LIBS += arch/mips/au1000/pb1100/pb1100.o \
+ arch/mips/au1000/common/au1000.o
+@@ -230,9 +227,6 @@
+ LOADADDR += 0x80100000
+ endif
+
+-#
+-# Au1500 (Alchemy Semi PB1500) eval board
+-#
+ ifdef CONFIG_MIPS_PB1500
+ LIBS += arch/mips/au1000/pb1500/pb1500.o \
+ arch/mips/au1000/common/au1000.o
+@@ -240,9 +234,6 @@
+ LOADADDR := 0x80100000
+ endif
+
+-#
+-# Au1x00 (AMD/Alchemy) eval boards
+-#
+ ifdef CONFIG_MIPS_DB1000
+ LIBS += arch/mips/au1000/db1x00/db1x00.o \
+ arch/mips/au1000/common/au1000.o
+@@ -313,6 +304,27 @@
+ LOADADDR += 0x80100000
+ endif
+
++ifdef CONFIG_MIPS_PB1200
++LIBS += arch/mips/au1000/pb1200/pb1200.o \
++ arch/mips/au1000/common/au1000.o
++SUBDIRS += arch/mips/au1000/pb1200 arch/mips/au1000/common
++LOADADDR += 0x80100000
++endif
++
++ifdef CONFIG_MIPS_DB1200
++LIBS += arch/mips/au1000/pb1200/pb1200.o \
++ arch/mips/au1000/common/au1000.o
++SUBDIRS += arch/mips/au1000/pb1200 arch/mips/au1000/common
++LOADADDR += 0x80100000
++endif
++
++ifdef CONFIG_MIPS_FICMMP
++LIBS += arch/mips/au1000/ficmmp/ficmmp.o \
++ arch/mips/au1000/common/au1000.o
++SUBDIRS += arch/mips/au1000/ficmmp arch/mips/au1000/common
++LOADADDR += 0x80100000
++endif
++
+
+ #
+ # Cogent CSB250
+diff -Nur linux-2.4.32-rc1/arch/mips/mm/cerr-sb1.c linux-2.4.32-rc1.mips/arch/mips/mm/cerr-sb1.c
+--- linux-2.4.32-rc1/arch/mips/mm/cerr-sb1.c 2004-02-18 14:36:30.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/mm/cerr-sb1.c 2004-12-13 18:37:23.000000000 +0100
+@@ -252,14 +252,14 @@
+
+ /* Masks to select bits for Hamming parity, mask_72_64[i] for bit[i] */
+ static const uint64_t mask_72_64[8] = {
+- 0x0738C808099264FFL,
+- 0x38C808099264FF07L,
+- 0xC808099264FF0738L,
+- 0x08099264FF0738C8L,
+- 0x099264FF0738C808L,
+- 0x9264FF0738C80809L,
+- 0x64FF0738C8080992L,
+- 0xFF0738C808099264L
++ 0x0738C808099264FFULL,
++ 0x38C808099264FF07ULL,
++ 0xC808099264FF0738ULL,
++ 0x08099264FF0738C8ULL,
++ 0x099264FF0738C808ULL,
++ 0x9264FF0738C80809ULL,
++ 0x64FF0738C8080992ULL,
++ 0xFF0738C808099264ULL
+ };
+
+ /* Calculate the parity on a range of bits */
+@@ -331,9 +331,9 @@
+ ((lru >> 4) & 0x3),
+ ((lru >> 6) & 0x3));
+ }
+- va = (taglo & 0xC0000FFFFFFFE000) | addr;
++ va = (taglo & 0xC0000FFFFFFFE000ULL) | addr;
+ if ((taglo & (1 << 31)) && (((taglo >> 62) & 0x3) == 3))
+- va |= 0x3FFFF00000000000;
++ va |= 0x3FFFF00000000000ULL;
+ valid = ((taghi >> 29) & 1);
+ if (valid) {
+ tlo_tmp = taglo & 0xfff3ff;
+@@ -474,7 +474,7 @@
+ : "r" ((way << 13) | addr));
+
+ taglo = ((unsigned long long)taglohi << 32) | taglolo;
+- pa = (taglo & 0xFFFFFFE000) | addr;
++ pa = (taglo & 0xFFFFFFE000ULL) | addr;
+ if (way == 0) {
+ lru = (taghi >> 14) & 0xff;
+ prom_printf("[Bank %d Set 0x%02x] LRU > %d %d %d %d > MRU\n",
+diff -Nur linux-2.4.32-rc1/arch/mips/mm/c-r4k.c linux-2.4.32-rc1.mips/arch/mips/mm/c-r4k.c
+--- linux-2.4.32-rc1/arch/mips/mm/c-r4k.c 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/mm/c-r4k.c 2005-02-06 22:55:42.000000000 +0100
+@@ -867,9 +867,16 @@
+ * normally they'd suffer from aliases but magic in the hardware deals
+ * with that for us so we don't need to take care ourselves.
+ */
+- if (c->cputype != CPU_R10000 && c->cputype != CPU_R12000)
+- if (c->dcache.waysize > PAGE_SIZE)
+- c->dcache.flags |= MIPS_CACHE_ALIASES;
++ switch (c->cputype) {
++ case CPU_R10000:
++ case CPU_R12000:
++ break;
++ case CPU_24K:
++ if (!(read_c0_config7() & (1 << 16)))
++ default:
++ if (c->dcache.waysize > PAGE_SIZE)
++ c->dcache.flags |= MIPS_CACHE_ALIASES;
++ }
+
+ switch (c->cputype) {
+ case CPU_20KC:
+@@ -1069,9 +1076,6 @@
+ probe_pcache();
+ setup_scache();
+
+- if (c->dcache.sets * c->dcache.ways > PAGE_SIZE)
+- c->dcache.flags |= MIPS_CACHE_ALIASES;
+-
+ r4k_blast_dcache_page_setup();
+ r4k_blast_dcache_page_indexed_setup();
+ r4k_blast_dcache_setup();
+diff -Nur linux-2.4.32-rc1/arch/mips/mm/tlbex-mips32.S linux-2.4.32-rc1.mips/arch/mips/mm/tlbex-mips32.S
+--- linux-2.4.32-rc1/arch/mips/mm/tlbex-mips32.S 2004-02-18 14:36:30.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/mm/tlbex-mips32.S 2004-11-29 00:33:15.000000000 +0100
+@@ -196,7 +196,7 @@
+ .set noat; \
+ SAVE_ALL; \
+ mfc0 a2, CP0_BADVADDR; \
+- STI; \
++ KMODE; \
+ .set at; \
+ move a0, sp; \
+ jal do_page_fault; \
+diff -Nur linux-2.4.32-rc1/arch/mips/mm/tlbex-r4k.S linux-2.4.32-rc1.mips/arch/mips/mm/tlbex-r4k.S
+--- linux-2.4.32-rc1/arch/mips/mm/tlbex-r4k.S 2004-02-18 14:36:30.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/mm/tlbex-r4k.S 2005-06-06 16:46:22.000000000 +0200
+@@ -184,13 +184,10 @@
+ P_MTC0 k0, CP0_ENTRYLO0 # load it
+ PTE_SRL k1, k1, 6 # convert to entrylo1
+ P_MTC0 k1, CP0_ENTRYLO1 # load it
+- b 1f
+- rm9000_tlb_hazard
++ mtc0_tlbw_hazard
+ tlbwr # write random tlb entry
+-1:
+- nop
+- rm9000_tlb_hazard
+- eret # return from trap
++ tlbw_eret_hazard
++ eret
+ END(except_vec0_r4000)
+
+ /* TLB refill, EXL == 0, R4600 version */
+@@ -468,13 +465,9 @@
+ PTE_PRESENT(k0, k1, nopage_tlbl)
+ PTE_MAKEVALID(k0, k1)
+ PTE_RELOAD(k1, k0)
+- rm9000_tlb_hazard
+- nop
+- b 1f
+- tlbwi
+-1:
+- nop
+- rm9000_tlb_hazard
++ mtc0_tlbw_hazard
++ tlbwi
++ tlbw_eret_hazard
+ .set mips3
+ eret
+ .set mips0
+@@ -496,13 +489,9 @@
+ PTE_WRITABLE(k0, k1, nopage_tlbs)
+ PTE_MAKEWRITE(k0, k1)
+ PTE_RELOAD(k1, k0)
+- rm9000_tlb_hazard
+- nop
+- b 1f
+- tlbwi
+-1:
+- nop
+- rm9000_tlb_hazard
++ mtc0_tlbw_hazard
++ tlbwi
++ tlbw_eret_hazard
+ .set mips3
+ eret
+ .set mips0
+@@ -529,13 +518,9 @@
+
+ /* Now reload the entry into the tlb. */
+ PTE_RELOAD(k1, k0)
+- rm9000_tlb_hazard
+- nop
+- b 1f
+- tlbwi
+-1:
+- rm9000_tlb_hazard
+- nop
++ mtc0_tlbw_hazard
++ tlbwi
++ tlbw_eret_hazard
+ .set mips3
+ eret
+ .set mips0
+diff -Nur linux-2.4.32-rc1/arch/mips/mm/tlb-r4k.c linux-2.4.32-rc1.mips/arch/mips/mm/tlb-r4k.c
+--- linux-2.4.32-rc1/arch/mips/mm/tlb-r4k.c 2005-01-19 15:09:29.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips/mm/tlb-r4k.c 2004-11-25 23:18:38.000000000 +0100
+@@ -3,17 +3,12 @@
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+- * r4xx0.c: R4000 processor variant specific MMU/Cache routines.
+- *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle ralf@gnu.org
+- *
+- * To do:
+- *
+- * - this code is a overbloated pig
+- * - many of the bug workarounds are not efficient at all, but at
+- * least they are functional ...
++ * Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved.
+ */
++#include <linux/config.h>
+ #include <linux/init.h>
+ #include <linux/sched.h>
+ #include <linux/mm.h>
+@@ -25,9 +20,6 @@
+ #include <asm/pgtable.h>
+ #include <asm/system.h>
+
+-#undef DEBUG_TLB
+-#undef DEBUG_TLBUPDATE
+-
+ extern char except_vec0_nevada, except_vec0_r4000, except_vec0_r4600;
+
+ /* CP0 hazard avoidance. */
+@@ -41,33 +33,23 @@
+ unsigned long old_ctx;
+ int entry;
+
+-#ifdef DEBUG_TLB
+- printk("[tlball]");
+-#endif
+-
+ local_irq_save(flags);
+ /* Save old context and create impossible VPN2 value */
+ old_ctx = read_c0_entryhi();
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+- BARRIER;
+
+ entry = read_c0_wired();
+
+ /* Blast 'em all away. */
+ while (entry < current_cpu_data.tlbsize) {
+- /*
+- * Make sure all entries differ. If they're not different
+- * MIPS32 will take revenge ...
+- */
+ write_c0_entryhi(KSEG0 + entry*0x2000);
+ write_c0_index(entry);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+- BARRIER;
+ entry++;
+ }
+- BARRIER;
++ tlbw_use_hazard();
+ write_c0_entryhi(old_ctx);
+ local_irq_restore(flags);
+ }
+@@ -76,12 +58,8 @@
+ {
+ int cpu = smp_processor_id();
+
+- if (cpu_context(cpu, mm) != 0) {
+-#ifdef DEBUG_TLB
+- printk("[tlbmm<%d>]", cpu_context(cpu, mm));
+-#endif
++ if (cpu_context(cpu, mm) != 0)
+ drop_mmu_context(mm,cpu);
+- }
+ }
+
+ void local_flush_tlb_range(struct mm_struct *mm, unsigned long start,
+@@ -93,10 +71,6 @@
+ unsigned long flags;
+ int size;
+
+-#ifdef DEBUG_TLB
+- printk("[tlbrange<%02x,%08lx,%08lx>]",
+- cpu_asid(cpu, mm), start, end);
+-#endif
+ local_irq_save(flags);
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ size = (size + 1) >> 1;
+@@ -112,7 +86,7 @@
+
+ write_c0_entryhi(start | newpid);
+ start += (PAGE_SIZE << 1);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ tlb_probe();
+ BARRIER;
+ idx = read_c0_index();
+@@ -122,10 +96,10 @@
+ continue;
+ /* Make sure all entries differ. */
+ write_c0_entryhi(KSEG0 + idx*0x2000);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+- BARRIER;
+ }
++ tlbw_use_hazard();
+ write_c0_entryhi(oldpid);
+ } else {
+ drop_mmu_context(mm, cpu);
+@@ -138,34 +112,30 @@
+ {
+ int cpu = smp_processor_id();
+
+- if (!vma || cpu_context(cpu, vma->vm_mm) != 0) {
++ if (cpu_context(cpu, vma->vm_mm) != 0) {
+ unsigned long flags;
+- int oldpid, newpid, idx;
++ unsigned long oldpid, newpid, idx;
+
+-#ifdef DEBUG_TLB
+- printk("[tlbpage<%d,%08lx>]", cpu_context(cpu, vma->vm_mm),
+- page);
+-#endif
+ newpid = cpu_asid(cpu, vma->vm_mm);
+ page &= (PAGE_MASK << 1);
+ local_irq_save(flags);
+ oldpid = read_c0_entryhi();
+ write_c0_entryhi(page | newpid);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ tlb_probe();
+ BARRIER;
+ idx = read_c0_index();
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+- if(idx < 0)
++ if (idx < 0)
+ goto finish;
+ /* Make sure all entries differ. */
+ write_c0_entryhi(KSEG0+idx*0x2000);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ tlb_write_indexed();
++ tlbw_use_hazard();
+
+ finish:
+- BARRIER;
+ write_c0_entryhi(oldpid);
+ local_irq_restore(flags);
+ }
+@@ -185,7 +155,7 @@
+
+ local_irq_save(flags);
+ write_c0_entryhi(page);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ tlb_probe();
+ BARRIER;
+ idx = read_c0_index();
+@@ -194,18 +164,19 @@
+ if (idx >= 0) {
+ /* Make sure all entries differ. */
+ write_c0_entryhi(KSEG0+idx*0x2000);
++ mtc0_tlbw_hazard();
+ tlb_write_indexed();
++ tlbw_use_hazard();
+ }
+- BARRIER;
+ write_c0_entryhi(oldpid);
++
+ local_irq_restore(flags);
+ }
+
+ EXPORT_SYMBOL(local_flush_tlb_one);
+
+-/* We will need multiple versions of update_mmu_cache(), one that just
+- * updates the TLB with the new pte(s), and another which also checks
+- * for the R4k "end of page" hardware bug and does the needy.
++/*
++ * Updates the TLB with the new pte(s).
+ */
+ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
+ {
+@@ -223,25 +194,16 @@
+
+ pid = read_c0_entryhi() & ASID_MASK;
+
+-#ifdef DEBUG_TLB
+- if ((pid != cpu_asid(cpu, vma->vm_mm)) ||
+- (cpu_context(vma->vm_mm) == 0)) {
+- printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d "
+- "tlbpid=%d\n", (int) (cpu_asid(cpu, vma->vm_mm)), pid);
+- }
+-#endif
+-
+ local_irq_save(flags);
+ address &= (PAGE_MASK << 1);
+ write_c0_entryhi(address | pid);
+ pgdp = pgd_offset(vma->vm_mm, address);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ tlb_probe();
+ BARRIER;
+ pmdp = pmd_offset(pgdp, address);
+ idx = read_c0_index();
+ ptep = pte_offset(pmdp, address);
+- BARRIER;
+ #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+ write_c0_entrylo0(ptep->pte_high);
+ ptep++;
+@@ -251,15 +213,13 @@
+ write_c0_entrylo1(pte_val(*ptep) >> 6);
+ #endif
+ write_c0_entryhi(address | pid);
+- BARRIER;
+- if (idx < 0) {
++ mtc0_tlbw_hazard();
++ if (idx < 0)
+ tlb_write_random();
+- } else {
++ else
+ tlb_write_indexed();
+- }
+- BARRIER;
++ tlbw_use_hazard();
+ write_c0_entryhi(pid);
+- BARRIER;
+ local_irq_restore(flags);
+ }
+
+@@ -279,24 +239,26 @@
+ asid = read_c0_entryhi() & ASID_MASK;
+ write_c0_entryhi(address | asid);
+ pgdp = pgd_offset(vma->vm_mm, address);
++ mtc0_tlbw_hazard();
+ tlb_probe();
++ BARRIER;
+ pmdp = pmd_offset(pgdp, address);
+ idx = read_c0_index();
+ ptep = pte_offset(pmdp, address);
+ write_c0_entrylo0(pte_val(*ptep++) >> 6);
+ write_c0_entrylo1(pte_val(*ptep) >> 6);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ if (idx < 0)
+ tlb_write_random();
+ else
+ tlb_write_indexed();
+- BARRIER;
++ tlbw_use_hazard();
+ local_irq_restore(flags);
+ }
+ #endif
+
+ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
+- unsigned long entryhi, unsigned long pagemask)
++ unsigned long entryhi, unsigned long pagemask)
+ {
+ unsigned long flags;
+ unsigned long wired;
+@@ -315,9 +277,9 @@
+ write_c0_entryhi(entryhi);
+ write_c0_entrylo0(entrylo0);
+ write_c0_entrylo1(entrylo1);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+- BARRIER;
++ tlbw_use_hazard();
+
+ write_c0_entryhi(old_ctx);
+ BARRIER;
+@@ -355,17 +317,15 @@
+ }
+
+ write_c0_index(temp_tlb_entry);
+- BARRIER;
+ write_c0_pagemask(pagemask);
+ write_c0_entryhi(entryhi);
+ write_c0_entrylo0(entrylo0);
+ write_c0_entrylo1(entrylo1);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+- BARRIER;
++ tlbw_use_hazard();
+
+ write_c0_entryhi(old_ctx);
+- BARRIER;
+ write_c0_pagemask(old_pagemask);
+ out:
+ local_irq_restore(flags);
+@@ -375,7 +335,7 @@
+ static void __init probe_tlb(unsigned long config)
+ {
+ struct cpuinfo_mips *c = &current_cpu_data;
+- unsigned int reg;
++ unsigned int config1;
+
+ /*
+ * If this isn't a MIPS32 / MIPS64 compliant CPU. Config 1 register
+@@ -385,16 +345,16 @@
+ if ((c->processor_id & 0xff0000) == PRID_COMP_LEGACY)
+ return;
+
+- reg = read_c0_config1();
++ config1 = read_c0_config1();
+ if (!((config >> 7) & 3))
+ panic("No TLB present");
+
+- c->tlbsize = ((reg >> 25) & 0x3f) + 1;
++ c->tlbsize = ((config1 >> 25) & 0x3f) + 1;
+ }
+
+ void __init r4k_tlb_init(void)
+ {
+- u32 config = read_c0_config();
++ unsigned int config = read_c0_config();
+
+ /*
+ * You should never change this register:
+diff -Nur linux-2.4.32-rc1/arch/mips64/defconfig linux-2.4.32-rc1.mips/arch/mips64/defconfig
+--- linux-2.4.32-rc1/arch/mips64/defconfig 2005-01-19 15:09:30.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/defconfig 2005-03-18 13:13:23.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -470,9 +470,11 @@
+ # CONFIG_SCSI_MEGARAID is not set
+ # CONFIG_SCSI_MEGARAID2 is not set
+ # CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ # CONFIG_SCSI_ATA_PIIX is not set
+ # CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
+ # CONFIG_SCSI_SATA_PROMISE is not set
+ # CONFIG_SCSI_SATA_SX4 is not set
+ # CONFIG_SCSI_SATA_SIL is not set
+@@ -658,7 +660,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips64/defconfig-atlas linux-2.4.32-rc1.mips/arch/mips64/defconfig-atlas
+--- linux-2.4.32-rc1/arch/mips64/defconfig-atlas 2005-01-19 15:09:30.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/defconfig-atlas 2005-03-18 13:13:23.000000000 +0100
+@@ -28,8 +28,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -232,11 +232,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -314,9 +309,11 @@
+ # CONFIG_SCSI_MEGARAID is not set
+ # CONFIG_SCSI_MEGARAID2 is not set
+ # CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ # CONFIG_SCSI_ATA_PIIX is not set
+ # CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
+ # CONFIG_SCSI_SATA_PROMISE is not set
+ # CONFIG_SCSI_SATA_SX4 is not set
+ # CONFIG_SCSI_SATA_SIL is not set
+@@ -474,7 +471,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips64/defconfig-decstation linux-2.4.32-rc1.mips/arch/mips64/defconfig-decstation
+--- linux-2.4.32-rc1/arch/mips64/defconfig-decstation 2005-01-19 15:09:30.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/defconfig-decstation 2005-03-18 13:13:23.000000000 +0100
+@@ -28,8 +28,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -224,11 +224,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -307,9 +302,11 @@
+ # CONFIG_SCSI_MEGARAID is not set
+ # CONFIG_SCSI_MEGARAID2 is not set
+ # CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ # CONFIG_SCSI_ATA_PIIX is not set
+ # CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
+ # CONFIG_SCSI_SATA_PROMISE is not set
+ # CONFIG_SCSI_SATA_SX4 is not set
+ # CONFIG_SCSI_SATA_SIL is not set
+@@ -477,7 +474,6 @@
+ CONFIG_SERIAL_DEC_CONSOLE=y
+ # CONFIG_DZ is not set
+ CONFIG_ZS=y
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips64/defconfig-ip22 linux-2.4.32-rc1.mips/arch/mips64/defconfig-ip22
+--- linux-2.4.32-rc1/arch/mips64/defconfig-ip22 2005-01-19 15:09:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/defconfig-ip22 2005-03-18 13:13:23.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -235,11 +235,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -319,9 +314,11 @@
+ # CONFIG_SCSI_MEGARAID is not set
+ # CONFIG_SCSI_MEGARAID2 is not set
+ # CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ # CONFIG_SCSI_ATA_PIIX is not set
+ # CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
+ # CONFIG_SCSI_SATA_PROMISE is not set
+ # CONFIG_SCSI_SATA_SX4 is not set
+ # CONFIG_SCSI_SATA_SIL is not set
+@@ -488,7 +485,6 @@
+ # CONFIG_SERIAL_TXX9_CONSOLE is not set
+ # CONFIG_TXX927_SERIAL is not set
+ CONFIG_IP22_SERIAL=y
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips64/defconfig-ip27 linux-2.4.32-rc1.mips/arch/mips64/defconfig-ip27
+--- linux-2.4.32-rc1/arch/mips64/defconfig-ip27 2005-01-19 15:09:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/defconfig-ip27 2005-03-18 13:13:23.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -470,9 +470,11 @@
+ # CONFIG_SCSI_MEGARAID is not set
+ # CONFIG_SCSI_MEGARAID2 is not set
+ # CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ # CONFIG_SCSI_ATA_PIIX is not set
+ # CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
+ # CONFIG_SCSI_SATA_PROMISE is not set
+ # CONFIG_SCSI_SATA_SX4 is not set
+ # CONFIG_SCSI_SATA_SIL is not set
+@@ -658,7 +660,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips64/defconfig-jaguar linux-2.4.32-rc1.mips/arch/mips64/defconfig-jaguar
+--- linux-2.4.32-rc1/arch/mips64/defconfig-jaguar 2005-01-19 15:09:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/defconfig-jaguar 2005-03-18 13:13:23.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -227,11 +227,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -403,7 +398,6 @@
+ # CONFIG_SERIAL_TXX9 is not set
+ # CONFIG_SERIAL_TXX9_CONSOLE is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips64/defconfig-malta linux-2.4.32-rc1.mips/arch/mips64/defconfig-malta
+--- linux-2.4.32-rc1/arch/mips64/defconfig-malta 2005-01-19 15:09:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/defconfig-malta 2005-04-19 14:19:34.000000000 +0200
+@@ -22,16 +22,19 @@
+ #
+ # CONFIG_ACER_PICA_61 is not set
+ # CONFIG_MIPS_BOSPORUS is not set
++# CONFIG_MIPS_FICMMP is not set
+ # CONFIG_MIPS_MIRAGE is not set
+ # CONFIG_MIPS_DB1000 is not set
+ # CONFIG_MIPS_DB1100 is not set
+ # CONFIG_MIPS_DB1500 is not set
+ # CONFIG_MIPS_DB1550 is not set
++# CONFIG_MIPS_DB1200 is not set
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_PB1200 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -146,9 +149,9 @@
+ CONFIG_BINFMT_ELF=y
+ CONFIG_MIPS32_COMPAT=y
+ CONFIG_MIPS32_O32=y
+-# CONFIG_MIPS32_N32 is not set
++CONFIG_MIPS32_N32=y
+ CONFIG_BINFMT_ELF32=y
+-# CONFIG_BINFMT_MISC is not set
++CONFIG_BINFMT_MISC=y
+ # CONFIG_OOM_KILLER is not set
+ # CONFIG_CMDLINE_BOOL is not set
+
+@@ -235,11 +238,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -271,8 +269,83 @@
+ #
+ # ATA/IDE/MFM/RLL support
+ #
+-# CONFIG_IDE is not set
++CONFIG_IDE=y
++
++#
++# IDE, ATA and ATAPI Block devices
++#
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_HD_IDE is not set
+ # CONFIG_BLK_DEV_HD is not set
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++# CONFIG_IDEDISK_MULTI_MODE is not set
++# CONFIG_IDEDISK_STROKE is not set
++# CONFIG_BLK_DEV_IDECS is not set
++# CONFIG_BLK_DEV_DELKIN is not set
++CONFIG_BLK_DEV_IDECD=y
++CONFIG_BLK_DEV_IDETAPE=y
++CONFIG_BLK_DEV_IDEFLOPPY=y
++# CONFIG_BLK_DEV_IDESCSI is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++
++#
++# IDE chipset support/bugfixes
++#
++# CONFIG_BLK_DEV_CMD640 is not set
++# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
++# CONFIG_BLK_DEV_ISAPNP is not set
++CONFIG_BLK_DEV_IDEPCI=y
++CONFIG_BLK_DEV_GENERIC=y
++CONFIG_IDEPCI_SHARE_IRQ=y
++CONFIG_BLK_DEV_IDEDMA_PCI=y
++# CONFIG_BLK_DEV_OFFBOARD is not set
++CONFIG_BLK_DEV_IDEDMA_FORCED=y
++CONFIG_IDEDMA_PCI_AUTO=y
++# CONFIG_IDEDMA_ONLYDISK is not set
++CONFIG_BLK_DEV_IDEDMA=y
++# CONFIG_IDEDMA_PCI_WIP is not set
++# CONFIG_BLK_DEV_ADMA100 is not set
++# CONFIG_BLK_DEV_AEC62XX is not set
++# CONFIG_BLK_DEV_ALI15X3 is not set
++# CONFIG_WDC_ALI15X3 is not set
++# CONFIG_BLK_DEV_AMD74XX is not set
++# CONFIG_AMD74XX_OVERRIDE is not set
++# CONFIG_BLK_DEV_ATIIXP is not set
++# CONFIG_BLK_DEV_CMD64X is not set
++# CONFIG_BLK_DEV_TRIFLEX is not set
++# CONFIG_BLK_DEV_CY82C693 is not set
++# CONFIG_BLK_DEV_CS5530 is not set
++# CONFIG_BLK_DEV_HPT34X is not set
++# CONFIG_HPT34X_AUTODMA is not set
++# CONFIG_BLK_DEV_HPT366 is not set
++CONFIG_BLK_DEV_PIIX=y
++# CONFIG_BLK_DEV_NS87415 is not set
++# CONFIG_BLK_DEV_OPTI621 is not set
++# CONFIG_BLK_DEV_PDC202XX_OLD is not set
++# CONFIG_PDC202XX_BURST is not set
++# CONFIG_BLK_DEV_PDC202XX_NEW is not set
++# CONFIG_BLK_DEV_RZ1000 is not set
++# CONFIG_BLK_DEV_SC1200 is not set
++# CONFIG_BLK_DEV_SVWKS is not set
++# CONFIG_BLK_DEV_SIIMAGE is not set
++# CONFIG_BLK_DEV_SIS5513 is not set
++# CONFIG_BLK_DEV_SLC90E66 is not set
++# CONFIG_BLK_DEV_TRM290 is not set
++# CONFIG_BLK_DEV_VIA82CXXX is not set
++# CONFIG_IDE_CHIPSETS is not set
++CONFIG_IDEDMA_AUTO=y
++# CONFIG_IDEDMA_IVB is not set
++# CONFIG_DMA_NONPCI is not set
++# CONFIG_BLK_DEV_ATARAID is not set
++# CONFIG_BLK_DEV_ATARAID_PDC is not set
++# CONFIG_BLK_DEV_ATARAID_HPT is not set
++# CONFIG_BLK_DEV_ATARAID_MEDLEY is not set
++# CONFIG_BLK_DEV_ATARAID_SII is not set
+
+ #
+ # SCSI support
+@@ -317,9 +390,11 @@
+ # CONFIG_SCSI_MEGARAID is not set
+ # CONFIG_SCSI_MEGARAID2 is not set
+ # CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ # CONFIG_SCSI_ATA_PIIX is not set
+ # CONFIG_SCSI_SATA_NV is not set
++# CONFIG_SCSI_SATA_QSTOR is not set
+ # CONFIG_SCSI_SATA_PROMISE is not set
+ # CONFIG_SCSI_SATA_SX4 is not set
+ # CONFIG_SCSI_SATA_SIL is not set
+@@ -477,7 +552,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips64/defconfig-ocelotc linux-2.4.32-rc1.mips/arch/mips64/defconfig-ocelotc
+--- linux-2.4.32-rc1/arch/mips64/defconfig-ocelotc 2005-01-19 15:09:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/defconfig-ocelotc 2005-03-18 13:13:23.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -231,11 +231,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -453,7 +448,6 @@
+ # CONFIG_SERIAL_TXX9 is not set
+ # CONFIG_SERIAL_TXX9_CONSOLE is not set
+ # CONFIG_TXX927_SERIAL is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips64/defconfig-sb1250-swarm linux-2.4.32-rc1.mips/arch/mips64/defconfig-sb1250-swarm
+--- linux-2.4.32-rc1/arch/mips64/defconfig-sb1250-swarm 2005-01-19 15:09:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/defconfig-sb1250-swarm 2005-03-18 13:13:23.000000000 +0100
+@@ -30,8 +30,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -90,6 +90,7 @@
+ # CONFIG_SIBYTE_TBPROF is not set
+ CONFIG_SIBYTE_GENBUS_IDE=y
+ CONFIG_SMP_CAPABLE=y
++CONFIG_MIPS_RTC=y
+ # CONFIG_SNI_RM200_PCI is not set
+ # CONFIG_TANBAC_TB0226 is not set
+ # CONFIG_TANBAC_TB0229 is not set
+@@ -253,11 +254,6 @@
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+-
+-#
+-# Appletalk devices
+-#
+-# CONFIG_DEV_APPLETALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+@@ -432,7 +428,6 @@
+ CONFIG_SIBYTE_SB1250_DUART=y
+ CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y
+ CONFIG_SERIAL_CONSOLE=y
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+diff -Nur linux-2.4.32-rc1/arch/mips64/defconfig-sead linux-2.4.32-rc1.mips/arch/mips64/defconfig-sead
+--- linux-2.4.32-rc1/arch/mips64/defconfig-sead 2005-01-19 15:09:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/defconfig-sead 2005-03-18 13:13:23.000000000 +0100
+@@ -28,8 +28,8 @@
+ # CONFIG_MIPS_PB1000 is not set
+ # CONFIG_MIPS_PB1100 is not set
+ # CONFIG_MIPS_PB1500 is not set
+-# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_PB1550 is not set
++# CONFIG_MIPS_HYDROGEN3 is not set
+ # CONFIG_MIPS_XXS1500 is not set
+ # CONFIG_MIPS_MTX1 is not set
+ # CONFIG_COGENT_CSB250 is not set
+@@ -242,7 +242,6 @@
+ CONFIG_SERIAL_CONSOLE=y
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set
+ # CONFIG_UNIX98_PTYS is not set
+
+ #
+diff -Nur linux-2.4.32-rc1/arch/mips64/kernel/binfmt_elfn32.c linux-2.4.32-rc1.mips/arch/mips64/kernel/binfmt_elfn32.c
+--- linux-2.4.32-rc1/arch/mips64/kernel/binfmt_elfn32.c 2003-08-25 13:44:40.000000000 +0200
++++ linux-2.4.32-rc1.mips/arch/mips64/kernel/binfmt_elfn32.c 2005-01-26 03:40:47.000000000 +0100
+@@ -116,4 +116,7 @@
+ #undef MODULE_DESCRIPTION
+ #undef MODULE_AUTHOR
+
++#undef TASK_SIZE
++#define TASK_SIZE TASK_SIZE32
++
+ #include "../../../fs/binfmt_elf.c"
+diff -Nur linux-2.4.32-rc1/arch/mips64/kernel/binfmt_elfo32.c linux-2.4.32-rc1.mips/arch/mips64/kernel/binfmt_elfo32.c
+--- linux-2.4.32-rc1/arch/mips64/kernel/binfmt_elfo32.c 2003-08-25 13:44:40.000000000 +0200
++++ linux-2.4.32-rc1.mips/arch/mips64/kernel/binfmt_elfo32.c 2005-01-26 03:40:47.000000000 +0100
+@@ -137,4 +137,7 @@
+ #undef MODULE_DESCRIPTION
+ #undef MODULE_AUTHOR
+
++#undef TASK_SIZE
++#define TASK_SIZE TASK_SIZE32
++
+ #include "../../../fs/binfmt_elf.c"
+diff -Nur linux-2.4.32-rc1/arch/mips64/kernel/head.S linux-2.4.32-rc1.mips/arch/mips64/kernel/head.S
+--- linux-2.4.32-rc1/arch/mips64/kernel/head.S 2004-02-18 14:36:30.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/kernel/head.S 2004-11-22 14:38:26.000000000 +0100
+@@ -91,6 +91,21 @@
+ __INIT
+
+ NESTED(kernel_entry, 16, sp) # kernel entry point
++ .set push
++ /*
++ * 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. A full initialization of the CPU's status
++ * register is done later in per_cpu_trap_init().
++ */
++ mfc0 t0, CP0_STATUS
++ or t0, ST0_CU0|ST0_KX|0x1f
++ xor t0, 0x1f
++ mtc0 t0, CP0_STATUS
++
++ .set noreorder
++ sll zero,3 # ehb
++ .set reorder
+
+ ori sp, 0xf # align stack on 16 byte.
+ xori sp, 0xf
+@@ -103,8 +118,6 @@
+
+ ARC64_TWIDDLE_PC
+
+- CLI # disable interrupts
+-
+ /*
+ * The firmware/bootloader passes argc/argp/envp
+ * to us as arguments. But clear bss first because
+@@ -125,6 +138,7 @@
+ dsubu sp, 4*SZREG # init stack pointer
+
+ j init_arch
++ .set pop
+ END(kernel_entry)
+
+ #ifdef CONFIG_SMP
+@@ -133,6 +147,23 @@
+ * function after setting up the stack and gp registers.
+ */
+ NESTED(smp_bootstrap, 16, sp)
++ .set push
++ /*
++ * For the moment disable interrupts and bootstrap exception
++ * vectors, mark the kernel mode and set ST0_KX so that the CPU
++ * does not spit fire when using 64-bit addresses. A full
++ * initialization of the CPU's status register is done later in
++ * per_cpu_trap_init().
++ */
++ mfc0 t0, CP0_STATUS
++ or t0, ST0_CU0|ST0_BEV|ST0_KX|0x1f
++ xor t0, ST0_BEV|0x1f
++ mtc0 t0, CP0_STATUS
++
++ .set noreorder
++ sll zero,3 # ehb
++ .set reorder
++
+ #ifdef CONFIG_SGI_IP27
+ GET_NASID_ASM t1
+ dli t0, KLDIR_OFFSET + (KLI_KERN_VARS * KLDIR_ENT_SIZE) + \
+@@ -146,19 +177,8 @@
+ ARC64_TWIDDLE_PC
+ #endif /* CONFIG_SGI_IP27 */
+
+- CLI
+-
+- /*
+- * For the moment set ST0_KU so the CPU will not spit fire when
+- * executing 64-bit instructions. The full initialization of the
+- * CPU's status register is done later in per_cpu_trap_init().
+- */
+- mfc0 t0, CP0_STATUS
+- or t0, ST0_KX
+- mtc0 t0, CP0_STATUS
+-
+ jal start_secondary # XXX: IP27: cboot
+-
++ .set pop
+ END(smp_bootstrap)
+ #endif /* CONFIG_SMP */
+
+diff -Nur linux-2.4.32-rc1/arch/mips64/kernel/ioctl32.c linux-2.4.32-rc1.mips/arch/mips64/kernel/ioctl32.c
+--- linux-2.4.32-rc1/arch/mips64/kernel/ioctl32.c 2005-01-19 15:09:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/kernel/ioctl32.c 2005-01-26 03:36:17.000000000 +0100
+@@ -2352,7 +2352,7 @@
+ IOCTL32_HANDLER(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout),
+ IOCTL32_DEFAULT(AUTOFS_IOC_EXPIRE),
+ IOCTL32_DEFAULT(AUTOFS_IOC_EXPIRE_MULTI),
+- IOCTL32_DEFAULT(AUTOFS_IOC_PROTSUBVER),
++ IOCTL32_DEFAULT(AUTOFS_IOC_PROTOSUBVER),
+ IOCTL32_DEFAULT(AUTOFS_IOC_ASKREGHOST),
+ IOCTL32_DEFAULT(AUTOFS_IOC_TOGGLEREGHOST),
+ IOCTL32_DEFAULT(AUTOFS_IOC_ASKUMOUNT),
+diff -Nur linux-2.4.32-rc1/arch/mips64/kernel/linux32.c linux-2.4.32-rc1.mips/arch/mips64/kernel/linux32.c
+--- linux-2.4.32-rc1/arch/mips64/kernel/linux32.c 2005-04-04 03:42:19.000000000 +0200
++++ linux-2.4.32-rc1.mips/arch/mips64/kernel/linux32.c 2005-04-22 15:01:00.000000000 +0200
+@@ -1101,6 +1101,7 @@
+ * specially as they have atomicity guarantees and can handle
+ * iovec's natively
+ */
++ inode = file->f_dentry->d_inode;
+ if (inode->i_sock) {
+ int err;
+ err = sock_readv_writev(type, inode, file, iov, count, tot_len);
+@@ -1187,72 +1188,19 @@
+ lseek back to original location. They fail just like lseek does on
+ non-seekable files. */
+
+-asmlinkage ssize_t sys32_pread(unsigned int fd, char * buf,
+- size_t count, u32 unused, u64 a4, u64 a5)
++asmlinkage ssize_t sys32_pread(unsigned int fd, char *buf,
++ size_t count, u32 unused, u64 a4, u64 a5)
+ {
+- ssize_t ret;
+- struct file * file;
+- ssize_t (*read)(struct file *, char *, size_t, loff_t *);
+- loff_t pos;
+-
+- ret = -EBADF;
+- file = fget(fd);
+- if (!file)
+- goto bad_file;
+- if (!(file->f_mode & FMODE_READ))
+- goto out;
+- pos = merge_64(a4, a5);
+- ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode,
+- file, pos, count);
+- if (ret)
+- goto out;
+- ret = -EINVAL;
+- if (!file->f_op || !(read = file->f_op->read))
+- goto out;
+- if (pos < 0)
+- goto out;
+- ret = read(file, buf, count, &pos);
+- if (ret > 0)
+- dnotify_parent(file->f_dentry, DN_ACCESS);
+-out:
+- fput(file);
+-bad_file:
+- return ret;
++ return sys_pread(fd, buf, count, merge_64(a4, a5));
+ }
+
+ asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char * buf,
+ size_t count, u32 unused, u64 a4, u64 a5)
+ {
+- ssize_t ret;
+- struct file * file;
+- ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
+- loff_t pos;
++ return sys_pwrite(fd, buf, count, merge_64(a4, a5));
++}
+
+- ret = -EBADF;
+- file = fget(fd);
+- if (!file)
+- goto bad_file;
+- if (!(file->f_mode & FMODE_WRITE))
+- goto out;
+- pos = merge_64(a4, a5);
+- ret = locks_verify_area(FLOCK_VERIFY_WRITE, file->f_dentry->d_inode,
+- file, pos, count);
+- if (ret)
+- goto out;
+- ret = -EINVAL;
+- if (!file->f_op || !(write = file->f_op->write))
+- goto out;
+- if (pos < 0)
+- goto out;
+
+- ret = write(file, buf, count, &pos);
+- if (ret > 0)
+- dnotify_parent(file->f_dentry, DN_MODIFY);
+-out:
+- fput(file);
+-bad_file:
+- return ret;
+-}
+ /*
+ * Ooo, nasty. We need here to frob 32-bit unsigned longs to
+ * 64-bit unsigned longs.
+diff -Nur linux-2.4.32-rc1/arch/mips64/kernel/process.c linux-2.4.32-rc1.mips/arch/mips64/kernel/process.c
+--- linux-2.4.32-rc1/arch/mips64/kernel/process.c 2003-08-25 13:44:40.000000000 +0200
++++ linux-2.4.32-rc1.mips/arch/mips64/kernel/process.c 2005-04-14 12:41:44.000000000 +0200
+@@ -125,6 +125,25 @@
+ return 1;
+ }
+
++void dump_regs(elf_greg_t *gp, struct pt_regs *regs)
++{
++ int i;
++
++ for (i = 0; i < EF_REG0; i++)
++ gp[i] = 0;
++ gp[EF_REG0] = 0;
++ for (i = 1; i <= 31; i++)
++ gp[EF_REG0 + i] = regs->regs[i];
++ gp[EF_REG26] = 0;
++ gp[EF_REG27] = 0;
++ gp[EF_LO] = regs->lo;
++ gp[EF_HI] = regs->hi;
++ gp[EF_CP0_EPC] = regs->cp0_epc;
++ gp[EF_CP0_BADVADDR] = regs->cp0_badvaddr;
++ gp[EF_CP0_STATUS] = regs->cp0_status;
++ gp[EF_CP0_CAUSE] = regs->cp0_cause;
++}
++
+ /*
+ * Create a kernel thread
+ */
+diff -Nur linux-2.4.32-rc1/arch/mips64/kernel/scall_64.S linux-2.4.32-rc1.mips/arch/mips64/kernel/scall_64.S
+--- linux-2.4.32-rc1/arch/mips64/kernel/scall_64.S 2005-01-19 15:09:32.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/kernel/scall_64.S 2005-02-07 22:21:54.000000000 +0100
+@@ -102,15 +102,14 @@
+
+ trace_a_syscall:
+ SAVE_STATIC
+- sd t2,PT_R1(sp)
++ move s0, t2
+ jal syscall_trace
+- ld t2,PT_R1(sp)
+
+ ld a0, PT_R4(sp) # Restore argument registers
+ ld a1, PT_R5(sp)
+ ld a2, PT_R6(sp)
+ ld a3, PT_R7(sp)
+- jalr t2
++ jalr s0
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+diff -Nur linux-2.4.32-rc1/arch/mips64/kernel/scall_n32.S linux-2.4.32-rc1.mips/arch/mips64/kernel/scall_n32.S
+--- linux-2.4.32-rc1/arch/mips64/kernel/scall_n32.S 2005-01-19 15:09:32.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/kernel/scall_n32.S 2005-02-07 22:21:54.000000000 +0100
+@@ -106,15 +106,14 @@
+
+ trace_a_syscall:
+ SAVE_STATIC
+- sd t2,PT_R1(sp)
++ move s0, t2
+ jal syscall_trace
+- ld t2,PT_R1(sp)
+
+ ld a0, PT_R4(sp) # Restore argument registers
+ ld a1, PT_R5(sp)
+ ld a2, PT_R6(sp)
+ ld a3, PT_R7(sp)
+- jalr t2
++ jalr s0
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+diff -Nur linux-2.4.32-rc1/arch/mips64/kernel/scall_o32.S linux-2.4.32-rc1.mips/arch/mips64/kernel/scall_o32.S
+--- linux-2.4.32-rc1/arch/mips64/kernel/scall_o32.S 2005-01-19 15:09:32.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/kernel/scall_o32.S 2005-02-14 04:52:57.000000000 +0100
+@@ -118,9 +118,8 @@
+ sd a6, PT_R10(sp)
+ sd a7, PT_R11(sp)
+
+- sd t2,PT_R1(sp)
++ move s0, t2
+ jal syscall_trace
+- ld t2,PT_R1(sp)
+
+ ld a0, PT_R4(sp) # Restore argument registers
+ ld a1, PT_R5(sp)
+@@ -129,7 +128,7 @@
+ ld a4, PT_R8(sp)
+ ld a5, PT_R9(sp)
+
+- jalr t2
++ jalr s0
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+@@ -576,6 +575,8 @@
+ sys_call_table:
+ syscalltable
+
++ .purgem sys
++
+ .macro sys function, nargs
+ .byte \nargs
+ .endm
+diff -Nur linux-2.4.32-rc1/arch/mips64/kernel/setup.c linux-2.4.32-rc1.mips/arch/mips64/kernel/setup.c
+--- linux-2.4.32-rc1/arch/mips64/kernel/setup.c 2005-01-19 15:09:32.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/kernel/setup.c 2004-11-22 14:38:26.000000000 +0100
+@@ -129,14 +129,6 @@
+ */
+ load_mmu();
+
+- /*
+- * On IP27, I am seeing the TS bit set when the kernel is loaded.
+- * Maybe because the kernel is in ckseg0 and not xkphys? Clear it
+- * anyway ...
+- */
+- clear_c0_status(ST0_BEV|ST0_TS|ST0_CU1|ST0_CU2|ST0_CU3);
+- set_c0_status(ST0_CU0|ST0_KX|ST0_SX|ST0_FR);
+-
+ start_kernel();
+ }
+
+diff -Nur linux-2.4.32-rc1/arch/mips64/kernel/signal_n32.c linux-2.4.32-rc1.mips/arch/mips64/kernel/signal_n32.c
+--- linux-2.4.32-rc1/arch/mips64/kernel/signal_n32.c 2005-01-19 15:09:33.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/kernel/signal_n32.c 2005-02-07 22:10:53.000000000 +0100
+@@ -68,7 +68,7 @@
+ };
+
+ extern asmlinkage int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc);
+-extern int inline setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc);
++extern int setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc);
+
+ asmlinkage void sysn32_rt_sigreturn(abi64_no_regargs, struct pt_regs regs)
+ {
+diff -Nur linux-2.4.32-rc1/arch/mips64/kernel/traps.c linux-2.4.32-rc1.mips/arch/mips64/kernel/traps.c
+--- linux-2.4.32-rc1/arch/mips64/kernel/traps.c 2005-01-19 15:09:33.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/kernel/traps.c 2005-04-12 22:25:34.000000000 +0200
+@@ -462,9 +462,10 @@
+ }
+ ll_task = current;
+
++ compute_return_epc(regs);
++
+ regs->regs[(opcode & RT) >> 16] = value;
+
+- compute_return_epc(regs);
+ return;
+
+ sig:
+@@ -495,8 +496,8 @@
+ goto sig;
+ }
+ if (ll_bit == 0 || ll_task != current) {
+- regs->regs[reg] = 0;
+ compute_return_epc(regs);
++ regs->regs[reg] = 0;
+ return;
+ }
+
+@@ -505,9 +506,9 @@
+ goto sig;
+ }
+
++ compute_return_epc(regs);
+ regs->regs[reg] = 1;
+
+- compute_return_epc(regs);
+ return;
+
+ sig:
+@@ -809,13 +810,18 @@
+ void __init per_cpu_trap_init(void)
+ {
+ unsigned int cpu = smp_processor_id();
++ unsigned int status_set = ST0_CU0|ST0_FR|ST0_KX|ST0_SX|ST0_UX;
+
+- /* Some firmware leaves the BEV flag set, clear it. */
+- clear_c0_status(ST0_CU1|ST0_CU2|ST0_CU3|ST0_BEV);
+- set_c0_status(ST0_CU0|ST0_FR|ST0_KX|ST0_SX|ST0_UX);
+-
++ /*
++ * Disable coprocessors, enable 64-bit addressing and set FPU
++ * for the 32/32 FPR register model. Reset the BEV flag that
++ * some firmware may have left set and the TS bit (for IP27).
++ * Set XX for ISA IV code to work.
++ */
+ if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
+- set_c0_status(ST0_XX);
++ status_set |= ST0_XX;
++ change_c0_status(ST0_CU|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
++ status_set);
+
+ /*
+ * Some MIPS CPUs have a dedicated interrupt vector which reduces the
+@@ -825,13 +831,11 @@
+ set_c0_cause(CAUSEF_IV);
+
+ cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
+- write_c0_context(((long)(&pgd_current[cpu])) << 23);
+- write_c0_wired(0);
++ TLBMISS_HANDLER_SETUP();
+
+ atomic_inc(&init_mm.mm_count);
+ current->active_mm = &init_mm;
+- if (current->mm)
+- BUG();
++ BUG_ON(current->mm);
+ enter_lazy_tlb(&init_mm, current, cpu);
+ }
+
+@@ -842,8 +846,6 @@
+ extern char except_vec4;
+ unsigned long i;
+
+- per_cpu_trap_init();
+-
+ /* Copy the generic exception handlers to their final destination. */
+ memcpy((void *) KSEG0 , &except_vec0_generic, 0x80);
+ memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80);
+@@ -933,6 +935,5 @@
+
+ flush_icache_range(KSEG0, KSEG0 + 0x400);
+
+- atomic_inc(&init_mm.mm_count); /* XXX UP? */
+- current->active_mm = &init_mm;
++ per_cpu_trap_init();
+ }
+diff -Nur linux-2.4.32-rc1/arch/mips64/mm/cerr-sb1.c linux-2.4.32-rc1.mips/arch/mips64/mm/cerr-sb1.c
+--- linux-2.4.32-rc1/arch/mips64/mm/cerr-sb1.c 2004-02-18 14:36:30.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/mm/cerr-sb1.c 2004-12-13 18:37:26.000000000 +0100
+@@ -252,14 +252,14 @@
+
+ /* Masks to select bits for Hamming parity, mask_72_64[i] for bit[i] */
+ static const uint64_t mask_72_64[8] = {
+- 0x0738C808099264FFL,
+- 0x38C808099264FF07L,
+- 0xC808099264FF0738L,
+- 0x08099264FF0738C8L,
+- 0x099264FF0738C808L,
+- 0x9264FF0738C80809L,
+- 0x64FF0738C8080992L,
+- 0xFF0738C808099264L
++ 0x0738C808099264FFULL,
++ 0x38C808099264FF07ULL,
++ 0xC808099264FF0738ULL,
++ 0x08099264FF0738C8ULL,
++ 0x099264FF0738C808ULL,
++ 0x9264FF0738C80809ULL,
++ 0x64FF0738C8080992ULL,
++ 0xFF0738C808099264ULL
+ };
+
+ /* Calculate the parity on a range of bits */
+@@ -331,9 +331,9 @@
+ ((lru >> 4) & 0x3),
+ ((lru >> 6) & 0x3));
+ }
+- va = (taglo & 0xC0000FFFFFFFE000) | addr;
++ va = (taglo & 0xC0000FFFFFFFE000ULL) | addr;
+ if ((taglo & (1 << 31)) && (((taglo >> 62) & 0x3) == 3))
+- va |= 0x3FFFF00000000000;
++ va |= 0x3FFFF00000000000ULL;
+ valid = ((taghi >> 29) & 1);
+ if (valid) {
+ tlo_tmp = taglo & 0xfff3ff;
+@@ -474,7 +474,7 @@
+ : "r" ((way << 13) | addr));
+
+ taglo = ((unsigned long long)taglohi << 32) | taglolo;
+- pa = (taglo & 0xFFFFFFE000) | addr;
++ pa = (taglo & 0xFFFFFFE000ULL) | addr;
+ if (way == 0) {
+ lru = (taghi >> 14) & 0xff;
+ prom_printf("[Bank %d Set 0x%02x] LRU > %d %d %d %d > MRU\n",
+diff -Nur linux-2.4.32-rc1/arch/mips64/mm/c-r4k.c linux-2.4.32-rc1.mips/arch/mips64/mm/c-r4k.c
+--- linux-2.4.32-rc1/arch/mips64/mm/c-r4k.c 2005-01-19 15:09:33.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/mm/c-r4k.c 2005-02-06 22:55:42.000000000 +0100
+@@ -867,9 +867,16 @@
+ * normally they'd suffer from aliases but magic in the hardware deals
+ * with that for us so we don't need to take care ourselves.
+ */
+- if (c->cputype != CPU_R10000 && c->cputype != CPU_R12000)
+- if (c->dcache.waysize > PAGE_SIZE)
+- c->dcache.flags |= MIPS_CACHE_ALIASES;
++ switch (c->cputype) {
++ case CPU_R10000:
++ case CPU_R12000:
++ break;
++ case CPU_24K:
++ if (!(read_c0_config7() & (1 << 16)))
++ default:
++ if (c->dcache.waysize > PAGE_SIZE)
++ c->dcache.flags |= MIPS_CACHE_ALIASES;
++ }
+
+ switch (c->cputype) {
+ case CPU_20KC:
+@@ -1070,9 +1077,6 @@
+ setup_scache();
+ coherency_setup();
+
+- if (c->dcache.sets * c->dcache.ways > PAGE_SIZE)
+- c->dcache.flags |= MIPS_CACHE_ALIASES;
+-
+ r4k_blast_dcache_page_setup();
+ r4k_blast_dcache_page_indexed_setup();
+ r4k_blast_dcache_setup();
+diff -Nur linux-2.4.32-rc1/arch/mips64/mm/tlbex-r4k.S linux-2.4.32-rc1.mips/arch/mips64/mm/tlbex-r4k.S
+--- linux-2.4.32-rc1/arch/mips64/mm/tlbex-r4k.S 2004-02-18 14:36:30.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/mm/tlbex-r4k.S 2005-06-06 16:46:22.000000000 +0200
+@@ -125,6 +125,33 @@
+ nop
+ END(except_vec1_r4k)
+
++ __FINIT
++
++ .align 5
++LEAF(handle_vec1_r4k)
++ .set noat
++ LOAD_PTE2 k1 k0 9f
++ ld k0, 0(k1) # get even pte
++ ld k1, 8(k1) # get odd pte
++ PTE_RELOAD k0 k1
++ mtc0_tlbw_hazard
++ tlbwr
++ tlbw_eret_hazard
++ eret
++
++9: # handle the vmalloc range
++ LOAD_KPTE2 k1 k0 invalid_vmalloc_address
++ ld k0, 0(k1) # get even pte
++ ld k1, 8(k1) # get odd pte
++ PTE_RELOAD k0 k1
++ mtc0_tlbw_hazard
++ tlbwr
++ tlbw_eret_hazard
++ eret
++END(handle_vec1_r4k)
++
++ __INIT
++
+ LEAF(except_vec1_sb1)
+ #if BCM1250_M3_WAR
+ dmfc0 k0, CP0_BADVADDR
+@@ -134,28 +161,24 @@
+ bnez k0, 1f
+ #endif
+ .set noat
+- dla k0, handle_vec1_r4k
++ dla k0, handle_vec1_sb1
+ jr k0
+ nop
+
+ 1: eret
+- nop
+ END(except_vec1_sb1)
+
+ __FINIT
+
+ .align 5
+-LEAF(handle_vec1_r4k)
++LEAF(handle_vec1_sb1)
+ .set noat
+ LOAD_PTE2 k1 k0 9f
+ ld k0, 0(k1) # get even pte
+ ld k1, 8(k1) # get odd pte
+ PTE_RELOAD k0 k1
+- rm9000_tlb_hazard
+- b 1f
+- tlbwr
+-1: nop
+- rm9000_tlb_hazard
++ mtc0_tlbw_hazard
++ tlbwr
+ eret
+
+ 9: # handle the vmalloc range
+@@ -163,13 +186,10 @@
+ ld k0, 0(k1) # get even pte
+ ld k1, 8(k1) # get odd pte
+ PTE_RELOAD k0 k1
+- rm9000_tlb_hazard
+- b 1f
+- tlbwr
+-1: nop
+- rm9000_tlb_hazard
++ mtc0_tlbw_hazard
++ tlbwr
+ eret
+-END(handle_vec1_r4k)
++END(handle_vec1_sb1)
+
+
+ __INIT
+@@ -195,10 +215,8 @@
+ ld k0, 0(k1) # get even pte
+ ld k1, 8(k1) # get odd pte
+ PTE_RELOAD k0 k1
+- rm9000_tlb_hazard
+- nop
++ mtc0_tlbw_hazard
+ tlbwr
+- rm9000_tlb_hazard
+ eret
+
+ 9: # handle the vmalloc range
+@@ -206,10 +224,8 @@
+ ld k0, 0(k1) # get even pte
+ ld k1, 8(k1) # get odd pte
+ PTE_RELOAD k0 k1
+- rm9000_tlb_hazard
+- nop
++ mtc0_tlbw_hazard
+ tlbwr
+- rm9000_tlb_hazard
+ eret
+ END(handle_vec1_r10k)
+
+diff -Nur linux-2.4.32-rc1/arch/mips64/mm/tlb-r4k.c linux-2.4.32-rc1.mips/arch/mips64/mm/tlb-r4k.c
+--- linux-2.4.32-rc1/arch/mips64/mm/tlb-r4k.c 2005-01-19 15:09:33.000000000 +0100
++++ linux-2.4.32-rc1.mips/arch/mips64/mm/tlb-r4k.c 2004-11-25 23:18:38.000000000 +0100
+@@ -1,24 +1,12 @@
+ /*
+- * Carsten Langgaard, carstenl@mips.com
+- * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved.
+- *
+- * This program is free software; you can distribute 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 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
++ * 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.
+ *
+- * 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.
+- *
+- * MIPS64 CPU variant specific MMU routines.
+- * These routine are not optimized in any way, they are done in a generic way
+- * so they can be used on all MIPS64 compliant CPUs, and also done in an
+- * attempt not to break anything for the R4xx0 style CPUs.
++ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
++ * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle ralf@gnu.org
++ * Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved.
+ */
+ #include <linux/init.h>
+ #include <linux/sched.h>
+@@ -30,9 +18,6 @@
+ #include <asm/pgtable.h>
+ #include <asm/system.h>
+
+-#undef DEBUG_TLB
+-#undef DEBUG_TLBUPDATE
+-
+ extern void except_vec1_r4k(void);
+
+ /* CP0 hazard avoidance. */
+@@ -46,31 +31,23 @@
+ unsigned long old_ctx;
+ int entry;
+
+-#ifdef DEBUG_TLB
+- printk("[tlball]");
+-#endif
+-
+ local_irq_save(flags);
+ /* Save old context and create impossible VPN2 value */
+ old_ctx = read_c0_entryhi();
+- write_c0_entryhi(XKPHYS);
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+- BARRIER;
+
+ entry = read_c0_wired();
+
+ /* Blast 'em all away. */
+- while(entry < current_cpu_data.tlbsize) {
+- /* Make sure all entries differ. */
+- write_c0_entryhi(XKPHYS+entry*0x2000);
++ while (entry < current_cpu_data.tlbsize) {
++ write_c0_entryhi(XKPHYS + entry*0x2000);
+ write_c0_index(entry);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+- BARRIER;
+ entry++;
+ }
+- BARRIER;
++ tlbw_use_hazard();
+ write_c0_entryhi(old_ctx);
+ local_irq_restore(flags);
+ }
+@@ -79,12 +56,8 @@
+ {
+ int cpu = smp_processor_id();
+
+- if (cpu_context(cpu, mm) != 0) {
+-#ifdef DEBUG_TLB
+- printk("[tlbmm<%d>]", mm->context);
+-#endif
++ if (cpu_context(cpu, mm) != 0)
+ drop_mmu_context(mm,cpu);
+- }
+ }
+
+ void local_flush_tlb_range(struct mm_struct *mm, unsigned long start,
+@@ -96,10 +69,6 @@
+ unsigned long flags;
+ int size;
+
+-#ifdef DEBUG_TLB
+- printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & ASID_MASK),
+- start, end);
+-#endif
+ local_irq_save(flags);
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ size = (size + 1) >> 1;
+@@ -110,25 +79,25 @@
+ start &= (PAGE_MASK << 1);
+ end += ((PAGE_SIZE << 1) - 1);
+ end &= (PAGE_MASK << 1);
+- while(start < end) {
++ while (start < end) {
+ int idx;
+
+ write_c0_entryhi(start | newpid);
+ start += (PAGE_SIZE << 1);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ tlb_probe();
+ BARRIER;
+ idx = read_c0_index();
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+- if(idx < 0)
++ if (idx < 0)
+ continue;
+ /* Make sure all entries differ. */
+ write_c0_entryhi(XKPHYS+idx*0x2000);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+- BARRIER;
+ }
++ tlbw_use_hazard();
+ write_c0_entryhi(oldpid);
+ } else {
+ drop_mmu_context(mm, cpu);
+@@ -145,28 +114,26 @@
+ unsigned long flags;
+ unsigned long oldpid, newpid, idx;
+
+-#ifdef DEBUG_TLB
+- printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page);
+-#endif
+ newpid = cpu_asid(cpu, vma->vm_mm);
+ page &= (PAGE_MASK << 1);
+ local_irq_save(flags);
+ oldpid = read_c0_entryhi();
+ write_c0_entryhi(page | newpid);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ tlb_probe();
+ BARRIER;
+ idx = read_c0_index();
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+- if(idx < 0)
++ if (idx < 0)
+ goto finish;
+ /* Make sure all entries differ. */
+ write_c0_entryhi(XKPHYS+idx*0x2000);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ tlb_write_indexed();
++ tlbw_use_hazard();
++
+ finish:
+- BARRIER;
+ write_c0_entryhi(oldpid);
+ local_irq_restore(flags);
+ }
+@@ -186,7 +153,7 @@
+
+ local_irq_save(flags);
+ write_c0_entryhi(page);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ tlb_probe();
+ BARRIER;
+ idx = read_c0_index();
+@@ -195,10 +162,12 @@
+ if (idx >= 0) {
+ /* Make sure all entries differ. */
+ write_c0_entryhi(KSEG0+idx*0x2000);
++ mtc0_tlbw_hazard();
+ tlb_write_indexed();
++ tlbw_use_hazard();
+ }
+- BARRIER;
+ write_c0_entryhi(oldpid);
++
+ local_irq_restore(flags);
+ }
+
+@@ -208,7 +177,6 @@
+ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
+ {
+ unsigned long flags;
+- unsigned int asid;
+ pgd_t *pgdp;
+ pmd_t *pmdp;
+ pte_t *ptep;
+@@ -222,70 +190,58 @@
+
+ pid = read_c0_entryhi() & ASID_MASK;
+
+-#ifdef DEBUG_TLB
+- if ((pid != (cpu_asid(smp_processor_id(), vma->vm_mm))) ||
+- (cpu_context(smp_processor_id(), vma->vm_mm) == 0)) {
+- printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d"
+- "tlbpid=%d\n", (int) (cpu_context(smp_processor_id(),
+- vma->vm_mm) & ASID_MASK), pid);
+- }
+-#endif
+-
+ local_irq_save(flags);
+ address &= (PAGE_MASK << 1);
+- write_c0_entryhi(address | (pid));
++ write_c0_entryhi(address | pid);
+ pgdp = pgd_offset(vma->vm_mm, address);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ tlb_probe();
+ BARRIER;
+ pmdp = pmd_offset(pgdp, address);
+ idx = read_c0_index();
+ ptep = pte_offset(pmdp, address);
+- BARRIER;
+ write_c0_entrylo0(pte_val(*ptep++) >> 6);
+ write_c0_entrylo1(pte_val(*ptep) >> 6);
+- write_c0_entryhi(address | (pid));
+- BARRIER;
+- if(idx < 0) {
++ write_c0_entryhi(address | pid);
++ mtc0_tlbw_hazard();
++ if (idx < 0)
+ tlb_write_random();
+- } else {
++ else
+ tlb_write_indexed();
+- }
+- BARRIER;
++ tlbw_use_hazard();
+ write_c0_entryhi(pid);
+- BARRIER;
+ local_irq_restore(flags);
+ }
+
+-void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
+- unsigned long entryhi, unsigned long pagemask)
++void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
++ unsigned long entryhi, unsigned long pagemask)
+ {
+- unsigned long flags;
+- unsigned long wired;
+- unsigned long old_pagemask;
+- unsigned long old_ctx;
+-
+- local_irq_save(flags);
+- /* Save old context and create impossible VPN2 value */
+- old_ctx = (read_c0_entryhi() & ASID_MASK);
+- old_pagemask = read_c0_pagemask();
+- wired = read_c0_wired();
+- write_c0_wired(wired + 1);
+- write_c0_index(wired);
+- BARRIER;
+- write_c0_pagemask(pagemask);
+- write_c0_entryhi(entryhi);
+- write_c0_entrylo0(entrylo0);
+- write_c0_entrylo1(entrylo1);
+- BARRIER;
+- tlb_write_indexed();
+- BARRIER;
+-
+- write_c0_entryhi(old_ctx);
+- BARRIER;
+- write_c0_pagemask(old_pagemask);
+- local_flush_tlb_all();
+- local_irq_restore(flags);
++ unsigned long flags;
++ unsigned long wired;
++ unsigned long old_pagemask;
++ unsigned long old_ctx;
++
++ local_irq_save(flags);
++ /* Save old context and create impossible VPN2 value */
++ old_ctx = read_c0_entryhi() & ASID_MASK;
++ old_pagemask = read_c0_pagemask();
++ wired = read_c0_wired();
++ write_c0_wired(wired + 1);
++ write_c0_index(wired);
++ BARRIER;
++ write_c0_pagemask(pagemask);
++ write_c0_entryhi(entryhi);
++ write_c0_entrylo0(entrylo0);
++ write_c0_entrylo1(entrylo1);
++ mtc0_tlbw_hazard();
++ tlb_write_indexed();
++ tlbw_use_hazard();
++
++ write_c0_entryhi(old_ctx);
++ BARRIER;
++ write_c0_pagemask(old_pagemask);
++ local_flush_tlb_all();
++ local_irq_restore(flags);
+ }
+
+ /*
+@@ -317,17 +273,15 @@
+ }
+
+ write_c0_index(temp_tlb_entry);
+- BARRIER;
+ write_c0_pagemask(pagemask);
+ write_c0_entryhi(entryhi);
+ write_c0_entrylo0(entrylo0);
+ write_c0_entrylo1(entrylo1);
+- BARRIER;
++ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+- BARRIER;
++ tlbw_use_hazard();
+
+ write_c0_entryhi(old_ctx);
+- BARRIER;
+ write_c0_pagemask(old_pagemask);
+ out:
+ local_irq_restore(flags);
+@@ -348,15 +302,23 @@
+ return;
+
+ config1 = read_c0_config1();
+- if (!((config1 >> 7) & 3))
+- panic("No MMU present");
++ if (!((config >> 7) & 3))
++ panic("No TLB present");
+
+ c->tlbsize = ((config1 >> 25) & 0x3f) + 1;
+ }
+
+ void __init r4k_tlb_init(void)
+ {
+- unsigned long config = read_c0_config();
++ unsigned int config = read_c0_config();
++
++ /*
++ * You should never change this register:
++ * - On R4600 1.7 the tlbp never hits for pages smaller than
++ * the value in the c0_pagemask register.
++ * - The entire mm handling assumes the c0_pagemask register to
++ * be set for 4kb pages.
++ */
+ probe_tlb(config);
+ write_c0_pagemask(PM_DEFAULT_MASK);
+ write_c0_wired(0);
+diff -Nur linux-2.4.32-rc1/drivers/char/au1000_gpio.c linux-2.4.32-rc1.mips/drivers/char/au1000_gpio.c
+--- linux-2.4.32-rc1/drivers/char/au1000_gpio.c 2003-08-25 13:44:41.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/char/au1000_gpio.c 2003-12-20 14:18:51.000000000 +0100
+@@ -246,7 +246,7 @@
+
+ static struct miscdevice au1000gpio_miscdev =
+ {
+- GPIO_MINOR,
++ MISC_DYNAMIC_MINOR,
+ "au1000_gpio",
+ &au1000gpio_fops
+ };
+diff -Nur linux-2.4.32-rc1/drivers/char/au1550_psc_spi.c linux-2.4.32-rc1.mips/drivers/char/au1550_psc_spi.c
+--- linux-2.4.32-rc1/drivers/char/au1550_psc_spi.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/char/au1550_psc_spi.c 2005-02-11 21:37:24.000000000 +0100
+@@ -0,0 +1,466 @@
++/*
++ * Driver for Alchemy Au1550 SPI on the PSC.
++ *
++ * Copyright 2004 Embedded Edge, LLC.
++ * dan@embeddededge.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/module.h>
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/miscdevice.h>
++#include <linux/init.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/au1000.h>
++#include <asm/au1550_spi.h>
++#include <asm/au1xxx_psc.h>
++
++#ifdef CONFIG_MIPS_PB1550
++#include <asm/pb1550.h>
++#endif
++
++#ifdef CONFIG_MIPS_DB1550
++#include <asm/db1x00.h>
++#endif
++
++#ifdef CONFIG_MIPS_PB1200
++#include <asm/pb1200.h>
++#endif
++
++/* This is just a simple programmed I/O SPI interface on the PSC of the 1550.
++ * We support open, close, write, and ioctl. The SPI is a full duplex
++ * interface, you can't read without writing. So, the write system call
++ * copies the bytes out to the SPI, and whatever is returned is placed
++ * in the same buffer. Kinda weird, maybe we'll change it, but for now
++ * it works OK.
++ * I didn't implement any DMA yet, and it's a debate about the necessity.
++ * The SPI clocks are usually quite fast, so data is sent/received as
++ * quickly as you can stuff the FIFO. The overhead of DMA and interrupts
++ * are usually far greater than the data transfer itself. If, however,
++ * we find applications that move large amounts of data, we may choose
++ * use the overhead of buffering and DMA to do the work.
++ */
++
++/* The maximum clock rate specified in the manual is 2mHz.
++*/
++#define MAX_BAUD_RATE (2 * 1000000)
++#define PSC_INTCLK_RATE (32 * 1000000)
++
++static int inuse;
++
++/* We have to know what the user requested for the data length
++ * so we know how to stuff the fifo. The FIFO is 32 bits wide,
++ * and we have to load it with the bits to go in a single transfer.
++ */
++static uint spi_datalen;
++
++static int
++au1550spi_master_done( int ms )
++{
++ int timeout=ms;
++ volatile psc_spi_t *sp;
++
++ sp = (volatile psc_spi_t *)SPI_PSC_BASE;
++
++ /* Loop until MD is set or timeout has expired */
++ while(!(sp->psc_spievent & PSC_SPIEVNT_MD) && timeout--) udelay(1000);
++
++ if ( !timeout )
++ return 0;
++ else
++ sp->psc_spievent |= PSC_SPIEVNT_MD;
++
++ return 1;
++}
++
++static int
++au1550spi_open(struct inode *inode, struct file *file)
++{
++ if (inuse)
++ return -EBUSY;
++
++ inuse = 1;
++
++ MOD_INC_USE_COUNT;
++
++ return 0;
++}
++
++static ssize_t
++au1550spi_write(struct file *fp, const char *bp, size_t count, loff_t *ppos)
++{
++ int bytelen, i;
++ size_t rcount, retval;
++ unsigned char sb, *rp, *wp;
++ uint fifoword, pcr, stat;
++ volatile psc_spi_t *sp;
++
++ /* Get the number of bytes per transfer.
++ */
++ bytelen = ((spi_datalen - 1) / 8) + 1;
++
++ /* User needs to send us multiple of this count.
++ */
++ if ((count % bytelen) != 0)
++ return -EINVAL;
++
++ rp = wp = (unsigned char *)bp;
++ retval = rcount = count;
++
++ /* Reset the FIFO.
++ */
++ sp = (volatile psc_spi_t *)SPI_PSC_BASE;
++ sp->psc_spipcr = (PSC_SPIPCR_RC | PSC_SPIPCR_TC);
++ au_sync();
++ do {
++ pcr = sp->psc_spipcr;
++ au_sync();
++ } while (pcr != 0);
++
++ /* Prime the transmit FIFO.
++ */
++ while (count > 0) {
++ fifoword = 0;
++ for (i=0; i<bytelen; i++) {
++ fifoword <<= 8;
++ if (get_user(sb, wp) < 0)
++ return -EFAULT;
++ fifoword |= sb;
++ wp++;
++ }
++ count -= bytelen;
++ if (count <= 0)
++ fifoword |= PSC_SPITXRX_LC;
++ sp->psc_spitxrx = fifoword;
++ au_sync();
++ stat = sp->psc_spistat;
++ au_sync();
++ if (stat & PSC_SPISTAT_TF)
++ break;
++ }
++
++ /* Start the transfer.
++ */
++ sp->psc_spipcr = PSC_SPIPCR_MS;
++ au_sync();
++
++ /* Now, just keep the transmit fifo full and empty the receive.
++ */
++ while (count > 0) {
++ stat = sp->psc_spistat;
++ au_sync();
++ while ((stat & PSC_SPISTAT_RE) == 0) {
++ fifoword = sp->psc_spitxrx;
++ au_sync();
++ for (i=0; i<bytelen; i++) {
++ sb = fifoword & 0xff;
++ if (put_user(sb, rp) < 0)
++ return -EFAULT;
++ fifoword >>= 8;
++ rp++;
++ }
++ rcount -= bytelen;
++ stat = sp->psc_spistat;
++ au_sync();
++ }
++ if ((stat & PSC_SPISTAT_TF) == 0) {
++ fifoword = 0;
++ for (i=0; i<bytelen; i++) {
++ fifoword <<= 8;
++ if (get_user(sb, wp) < 0)
++ return -EFAULT;
++ fifoword |= sb;
++ wp++;
++ }
++ count -= bytelen;
++ if (count <= 0)
++ fifoword |= PSC_SPITXRX_LC;
++ sp->psc_spitxrx = fifoword;
++ au_sync();
++ }
++ }
++
++ /* All of the bytes for transmit have been written. Hang
++ * out waiting for any residual bytes that are yet to be
++ * read from the fifo.
++ */
++ while (rcount > 0) {
++ stat = sp->psc_spistat;
++ au_sync();
++ if ((stat & PSC_SPISTAT_RE) == 0) {
++ fifoword = sp->psc_spitxrx;
++ au_sync();
++ for (i=0; i<bytelen; i++) {
++ sb = fifoword & 0xff;
++ if (put_user(sb, rp) < 0)
++ return -EFAULT;
++ fifoword >>= 8;
++ rp++;
++ }
++ rcount -= bytelen;
++ }
++ }
++
++ /* Wait for MasterDone event. 30ms timeout */
++ if (!au1550spi_master_done(30) ) retval = -EFAULT;
++ return retval;
++}
++
++static int
++au1550spi_release(struct inode *inode, struct file *file)
++{
++ MOD_DEC_USE_COUNT;
++
++ inuse = 0;
++
++ return 0;
++}
++
++/* Set the baud rate closest to the request, then return the actual
++ * value we are using.
++ */
++static uint
++set_baud_rate(uint baud)
++{
++ uint rate, tmpclk, brg, ctl, stat;
++ volatile psc_spi_t *sp;
++
++ /* For starters, the input clock is divided by two.
++ */
++ tmpclk = PSC_INTCLK_RATE/2;
++
++ rate = tmpclk / baud;
++
++ /* The dividers work as follows:
++ * baud = tmpclk / (2 * (brg + 1))
++ */
++ brg = (rate/2) - 1;
++
++ /* Test BRG to ensure it will fit into the 6 bits allocated.
++ */
++
++ /* Make sure the device is disabled while we make the change.
++ */
++ sp = (volatile psc_spi_t *)SPI_PSC_BASE;
++ ctl = sp->psc_spicfg;
++ au_sync();
++ sp->psc_spicfg = ctl & ~PSC_SPICFG_DE_ENABLE;
++ au_sync();
++ ctl = PSC_SPICFG_CLR_BAUD(ctl);
++ ctl |= PSC_SPICFG_SET_BAUD(brg);
++ sp->psc_spicfg = ctl;
++ au_sync();
++
++ /* If the device was running prior to getting here, wait for
++ * it to restart.
++ */
++ if (ctl & PSC_SPICFG_DE_ENABLE) {
++ do {
++ stat = sp->psc_spistat;
++ au_sync();
++ } while ((stat & PSC_SPISTAT_DR) == 0);
++ }
++
++ /* Return the actual value.
++ */
++ rate = tmpclk / (2 * (brg + 1));
++
++ return(rate);
++}
++
++static uint
++set_word_len(uint len)
++{
++ uint ctl, stat;
++ volatile psc_spi_t *sp;
++
++ if ((len < 4) || (len > 24))
++ return -EINVAL;
++
++ /* Make sure the device is disabled while we make the change.
++ */
++ sp = (volatile psc_spi_t *)SPI_PSC_BASE;
++ ctl = sp->psc_spicfg;
++ au_sync();
++ sp->psc_spicfg = ctl & ~PSC_SPICFG_DE_ENABLE;
++ au_sync();
++ ctl = PSC_SPICFG_CLR_LEN(ctl);
++ ctl |= PSC_SPICFG_SET_LEN(len);
++ sp->psc_spicfg = ctl;
++ au_sync();
++
++ /* If the device was running prior to getting here, wait for
++ * it to restart.
++ */
++ if (ctl & PSC_SPICFG_DE_ENABLE) {
++ do {
++ stat = sp->psc_spistat;
++ au_sync();
++ } while ((stat & PSC_SPISTAT_DR) == 0);
++ }
++
++ return 0;
++}
++
++static int
++au1550spi_ioctl(struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ int status;
++ u32 val;
++
++ status = 0;
++
++ switch(cmd) {
++ case AU1550SPI_WORD_LEN:
++ status = set_word_len(arg);
++ break;
++
++ case AU1550SPI_SET_BAUD:
++ if (get_user(val, (u32 *)arg))
++ return -EFAULT;
++
++ val = set_baud_rate(val);
++ if (put_user(val, (u32 *)arg))
++ return -EFAULT;
++ break;
++
++ default:
++ status = -ENOIOCTLCMD;
++
++ }
++
++ return status;
++}
++
++
++static struct file_operations au1550spi_fops =
++{
++ owner: THIS_MODULE,
++ write: au1550spi_write,
++ ioctl: au1550spi_ioctl,
++ open: au1550spi_open,
++ release: au1550spi_release,
++};
++
++
++static struct miscdevice au1550spi_miscdev =
++{
++ MISC_DYNAMIC_MINOR,
++ "au1550_spi",
++ &au1550spi_fops
++};
++
++
++int __init
++au1550spi_init(void)
++{
++ uint clk, rate, stat;
++ volatile psc_spi_t *sp;
++
++ /* Wire up Freq3 as a clock for the SPI. The PSC does
++ * factor of 2 divisor, so run a higher rate so we can
++ * get some granularity to the clock speeds.
++ * We can't do this in board set up because the frequency
++ * is computed too late.
++ */
++ rate = get_au1x00_speed();
++ rate /= PSC_INTCLK_RATE;
++
++ /* The FRDIV in the frequency control is (FRDIV + 1) * 2
++ */
++ rate /=2;
++ rate--;
++ clk = au_readl(SYS_FREQCTRL1);
++ au_sync();
++ clk &= ~SYS_FC_FRDIV3_MASK;
++ clk |= (rate << SYS_FC_FRDIV3_BIT);
++ clk |= SYS_FC_FE3;
++ au_writel(clk, SYS_FREQCTRL1);
++ au_sync();
++
++ /* Set up the clock source routing to get Freq3 to PSC0_intclk.
++ */
++ clk = au_readl(SYS_CLKSRC);
++ au_sync();
++ clk &= ~0x03e0;
++ clk |= (5 << 7);
++ au_writel(clk, SYS_CLKSRC);
++ au_sync();
++
++ /* Set up GPIO pin function to drive PSC0_SYNC1, which is
++ * the SPI Select.
++ */
++ clk = au_readl(SYS_PINFUNC);
++ au_sync();
++ clk |= 1;
++ au_writel(clk, SYS_PINFUNC);
++ au_sync();
++
++ /* Now, set up the PSC for SPI PIO mode.
++ */
++ sp = (volatile psc_spi_t *)SPI_PSC_BASE;
++ sp->psc_ctrl = PSC_CTRL_DISABLE;
++ au_sync();
++ sp->psc_sel = PSC_SEL_PS_SPIMODE;
++ sp->psc_spicfg = 0;
++ au_sync();
++ sp->psc_ctrl = PSC_CTRL_ENABLE;
++ au_sync();
++ do {
++ stat = sp->psc_spistat;
++ au_sync();
++ } while ((stat & PSC_SPISTAT_SR) == 0);
++
++ sp->psc_spicfg = (PSC_SPICFG_RT_FIFO8 | PSC_SPICFG_TT_FIFO8 |
++ PSC_SPICFG_DD_DISABLE | PSC_SPICFG_MO);
++ sp->psc_spicfg |= PSC_SPICFG_SET_LEN(8);
++ spi_datalen = 8;
++ sp->psc_spimsk = PSC_SPIMSK_ALLMASK;
++ au_sync();
++
++ set_baud_rate(1000000);
++
++ sp->psc_spicfg |= PSC_SPICFG_DE_ENABLE;
++ do {
++ stat = sp->psc_spistat;
++ au_sync();
++ } while ((stat & PSC_SPISTAT_DR) == 0);
++
++ misc_register(&au1550spi_miscdev);
++ printk("Au1550 SPI driver\n");
++ return 0;
++}
++
++
++void __exit
++au1550spi_exit(void)
++{
++ misc_deregister(&au1550spi_miscdev);
++}
++
++
++module_init(au1550spi_init);
++module_exit(au1550spi_exit);
+diff -Nur linux-2.4.32-rc1/drivers/char/Config.in linux-2.4.32-rc1.mips/drivers/char/Config.in
+--- linux-2.4.32-rc1/drivers/char/Config.in 2004-08-08 01:26:04.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/char/Config.in 2005-02-11 22:09:56.000000000 +0100
+@@ -313,14 +313,11 @@
+ if [ "$CONFIG_OBSOLETE" = "y" -a "$CONFIG_ALPHA_BOOK1" = "y" ]; then
+ bool 'Tadpole ANA H8 Support (OBSOLETE)' CONFIG_H8
+ fi
+-if [ "$CONFIG_MIPS" = "y" -a "$CONFIG_NEW_TIME_C" = "y" ]; then
+- tristate 'Generic MIPS RTC Support' CONFIG_MIPS_RTC
+-fi
+ if [ "$CONFIG_SGI_IP22" = "y" ]; then
+- bool 'SGI DS1286 RTC support' CONFIG_SGI_DS1286
++ tristate 'Dallas DS1286 RTC support' CONFIG_DS1286
+ fi
+ if [ "$CONFIG_SGI_IP27" = "y" ]; then
+- bool 'SGI M48T35 RTC support' CONFIG_SGI_IP27_RTC
++ tristate 'SGI M48T35 RTC support' CONFIG_SGI_IP27_RTC
+ fi
+ if [ "$CONFIG_TOSHIBA_RBTX4927" = "y" -o "$CONFIG_TOSHIBA_JMR3927" = "y" ]; then
+ tristate 'Dallas DS1742 RTC support' CONFIG_DS1742
+@@ -383,6 +380,11 @@
+ source drivers/char/drm/Config.in
+ fi
+ fi
++
++if [ "$CONFIG_X86" = "y" ]; then
++ tristate 'ACP Modem (Mwave) support' CONFIG_MWAVE
++fi
++
+ endmenu
+
+ if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then
+@@ -391,6 +393,7 @@
+ if [ "$CONFIG_SOC_AU1X00" = "y" ]; then
+ tristate ' Alchemy Au1x00 GPIO device support' CONFIG_AU1X00_GPIO
+ tristate ' Au1000/ADS7846 touchscreen support' CONFIG_TS_AU1X00_ADS7846
++ #tristate ' Alchemy Au1550 PSC SPI support' CONFIG_AU1550_PSC_SPI
+ fi
+ if [ "$CONFIG_MIPS_ITE8172" = "y" ]; then
+ tristate ' ITE GPIO' CONFIG_ITE_GPIO
+diff -Nur linux-2.4.32-rc1/drivers/char/decserial.c linux-2.4.32-rc1.mips/drivers/char/decserial.c
+--- linux-2.4.32-rc1/drivers/char/decserial.c 2003-08-25 13:44:41.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/char/decserial.c 2004-09-28 02:53:01.000000000 +0200
+@@ -3,95 +3,105 @@
+ * choose the right serial device at boot time
+ *
+ * triemer 6-SEP-1998
+- * sercons.c is designed to allow the three different kinds
++ * sercons.c is designed to allow the three different kinds
+ * of serial devices under the decstation world to co-exist
+- * in the same kernel. The idea here is to abstract
++ * in the same kernel. The idea here is to abstract
+ * the pieces of the drivers that are common to this file
+ * so that they do not clash at compile time and runtime.
+ *
+ * HK 16-SEP-1998 v0.002
+ * removed the PROM console as this is not a real serial
+ * device. Added support for PROM console in drivers/char/tty_io.c
+- * instead. Although it may work to enable more than one
++ * instead. Although it may work to enable more than one
+ * console device I strongly recommend to use only one.
++ *
++ * Copyright (C) 2004 Maciej W. Rozycki
+ */
+
+ #include <linux/config.h>
++#include <linux/errno.h>
+ #include <linux/init.h>
++
+ #include <asm/dec/machtype.h>
++#include <asm/dec/serial.h>
++
++extern int register_zs_hook(unsigned int channel,
++ struct dec_serial_hook *hook);
++extern int unregister_zs_hook(unsigned int channel);
++
++extern int register_dz_hook(unsigned int channel,
++ struct dec_serial_hook *hook);
++extern int unregister_dz_hook(unsigned int channel);
+
++int register_dec_serial_hook(unsigned int channel,
++ struct dec_serial_hook *hook)
++{
+ #ifdef CONFIG_ZS
+-extern int zs_init(void);
++ if (IOASIC)
++ return register_zs_hook(channel, hook);
+ #endif
+-
+ #ifdef CONFIG_DZ
+-extern int dz_init(void);
++ if (!IOASIC)
++ return register_dz_hook(channel, hook);
+ #endif
++ return 0;
++}
+
+-#ifdef CONFIG_SERIAL_DEC_CONSOLE
+-
++int unregister_dec_serial_hook(unsigned int channel)
++{
+ #ifdef CONFIG_ZS
+-extern void zs_serial_console_init(void);
++ if (IOASIC)
++ return unregister_zs_hook(channel);
+ #endif
+-
+ #ifdef CONFIG_DZ
+-extern void dz_serial_console_init(void);
+-#endif
+-
++ if (!IOASIC)
++ return unregister_dz_hook(channel);
+ #endif
++ return 0;
++}
+
+-/* rs_init - starts up the serial interface -
+- handle normal case of starting up the serial interface */
+
+-#ifdef CONFIG_SERIAL_DEC
++extern int zs_init(void);
++extern int dz_init(void);
+
++/*
++ * rs_init - starts up the serial interface -
++ * handle normal case of starting up the serial interface
++ */
+ int __init rs_init(void)
+ {
+-
+-#if defined(CONFIG_ZS) && defined(CONFIG_DZ)
+- if (IOASIC)
+- return zs_init();
+- else
+- return dz_init();
+-#else
+-
+ #ifdef CONFIG_ZS
+- return zs_init();
++ if (IOASIC)
++ return zs_init();
+ #endif
+-
+ #ifdef CONFIG_DZ
+- return dz_init();
+-#endif
+-
++ if (!IOASIC)
++ return dz_init();
+ #endif
++ return -ENXIO;
+ }
+
+ __initcall(rs_init);
+
+-#endif
+
+ #ifdef CONFIG_SERIAL_DEC_CONSOLE
+
+-/* dec_serial_console_init handles the special case of starting
+- * up the console on the serial port
++extern void zs_serial_console_init(void);
++extern void dz_serial_console_init(void);
++
++/*
++ * dec_serial_console_init handles the special case of starting
++ * up the console on the serial port
+ */
+ void __init dec_serial_console_init(void)
+ {
+-#if defined(CONFIG_ZS) && defined(CONFIG_DZ)
+- if (IOASIC)
+- zs_serial_console_init();
+- else
+- dz_serial_console_init();
+-#else
+-
+ #ifdef CONFIG_ZS
+- zs_serial_console_init();
++ if (IOASIC)
++ zs_serial_console_init();
+ #endif
+-
+ #ifdef CONFIG_DZ
+- dz_serial_console_init();
+-#endif
+-
++ if (!IOASIC)
++ dz_serial_console_init();
+ #endif
+ }
+
+diff -Nur linux-2.4.32-rc1/drivers/char/ds1286.c linux-2.4.32-rc1.mips/drivers/char/ds1286.c
+--- linux-2.4.32-rc1/drivers/char/ds1286.c 2004-02-18 14:36:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/char/ds1286.c 2004-01-10 06:21:39.000000000 +0100
+@@ -1,6 +1,10 @@
+ /*
+ * DS1286 Real Time Clock interface for Linux
+ *
++ * Copyright (C) 2003 TimeSys Corp.
++ * S. James Hill (James.Hill@timesys.com)
++ * (sjhill@realitydiluted.com)
++ *
+ * Copyright (C) 1998, 1999, 2000 Ralf Baechle
+ *
+ * Based on code written by Paul Gortmaker.
+@@ -29,6 +33,7 @@
+ #include <linux/types.h>
+ #include <linux/errno.h>
+ #include <linux/miscdevice.h>
++#include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/ioport.h>
+ #include <linux/fcntl.h>
+@@ -95,6 +100,12 @@
+ return -EIO;
+ }
+
++void rtc_ds1286_wait(void)
++{
++ unsigned char sec = CMOS_READ(RTC_SECONDS);
++ while (sec == CMOS_READ(RTC_SECONDS));
++}
++
+ static int ds1286_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+@@ -249,23 +260,22 @@
+ {
+ spin_lock_irq(&ds1286_lock);
+
+- if (ds1286_status & RTC_IS_OPEN)
+- goto out_busy;
++ if (ds1286_status & RTC_IS_OPEN) {
++ spin_unlock_irq(&ds1286_lock);
++ return -EBUSY;
++ }
+
+ ds1286_status |= RTC_IS_OPEN;
+
+- spin_lock_irq(&ds1286_lock);
++ spin_unlock_irq(&ds1286_lock);
+ return 0;
+-
+-out_busy:
+- spin_lock_irq(&ds1286_lock);
+- return -EBUSY;
+ }
+
+ static int ds1286_release(struct inode *inode, struct file *file)
+ {
++ spin_lock_irq(&ds1286_lock);
+ ds1286_status &= ~RTC_IS_OPEN;
+-
++ spin_unlock_irq(&ds1286_lock);
+ return 0;
+ }
+
+@@ -276,32 +286,6 @@
+ return 0;
+ }
+
+-/*
+- * The various file operations we support.
+- */
+-
+-static struct file_operations ds1286_fops = {
+- .llseek = no_llseek,
+- .read = ds1286_read,
+- .poll = ds1286_poll,
+- .ioctl = ds1286_ioctl,
+- .open = ds1286_open,
+- .release = ds1286_release,
+-};
+-
+-static struct miscdevice ds1286_dev=
+-{
+- .minor = RTC_MINOR,
+- .name = "rtc",
+- .fops = &ds1286_fops,
+-};
+-
+-int __init ds1286_init(void)
+-{
+- printk(KERN_INFO "DS1286 Real Time Clock Driver v%s\n", DS1286_VERSION);
+- return misc_register(&ds1286_dev);
+-}
+-
+ static char *days[] = {
+ "***", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+ };
+@@ -528,3 +512,38 @@
+ BCD_TO_BIN(alm_tm->tm_hour);
+ alm_tm->tm_sec = 0;
+ }
++
++static struct file_operations ds1286_fops = {
++ .owner = THIS_MODULE,
++ .llseek = no_llseek,
++ .read = ds1286_read,
++ .poll = ds1286_poll,
++ .ioctl = ds1286_ioctl,
++ .open = ds1286_open,
++ .release = ds1286_release,
++};
++
++static struct miscdevice ds1286_dev =
++{
++ .minor = RTC_MINOR,
++ .name = "rtc",
++ .fops = &ds1286_fops,
++};
++
++static int __init ds1286_init(void)
++{
++ printk(KERN_INFO "DS1286 Real Time Clock Driver v%s\n", DS1286_VERSION);
++ return misc_register(&ds1286_dev);
++}
++
++static void __exit ds1286_exit(void)
++{
++ misc_deregister(&ds1286_dev);
++}
++
++module_init(ds1286_init);
++module_exit(ds1286_exit);
++EXPORT_NO_SYMBOLS;
++
++MODULE_AUTHOR("Ralf Baechle");
++MODULE_LICENSE("GPL");
+diff -Nur linux-2.4.32-rc1/drivers/char/ds1742.c linux-2.4.32-rc1.mips/drivers/char/ds1742.c
+--- linux-2.4.32-rc1/drivers/char/ds1742.c 2004-02-18 14:36:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/char/ds1742.c 2004-01-09 20:27:16.000000000 +0100
+@@ -142,6 +142,7 @@
+ CMOS_WRITE(RTC_WRITE, RTC_CONTROL);
+
+ /* convert */
++ memset(&tm, 0, sizeof(struct rtc_time));
+ to_tm(t, &tm);
+
+ /* check each field one by one */
+@@ -216,6 +217,7 @@
+ unsigned long curr_time;
+
+ curr_time = rtc_ds1742_get_time();
++ memset(&tm, 0, sizeof(struct rtc_time));
+ to_tm(curr_time, &tm);
+
+ p = buf;
+@@ -251,8 +253,8 @@
+
+ void rtc_ds1742_wait(void)
+ {
+- while (CMOS_READ(RTC_SECONDS) & 1);
+- while (!(CMOS_READ(RTC_SECONDS) & 1));
++ unsigned char sec = CMOS_READ(RTC_SECONDS);
++ while (sec == CMOS_READ(RTC_SECONDS));
+ }
+
+ static int ds1742_ioctl(struct inode *inode, struct file *file,
+@@ -264,6 +266,7 @@
+ switch (cmd) {
+ case RTC_RD_TIME: /* Read the time/date from RTC */
+ curr_time = rtc_ds1742_get_time();
++ memset(&rtc_tm, 0, sizeof(struct rtc_time));
+ to_tm(curr_time, &rtc_tm);
+ rtc_tm.tm_year -= 1900;
+ return copy_to_user((void *) arg, &rtc_tm, sizeof(rtc_tm)) ?
+diff -Nur linux-2.4.32-rc1/drivers/char/dummy_keyb.c linux-2.4.32-rc1.mips/drivers/char/dummy_keyb.c
+--- linux-2.4.32-rc1/drivers/char/dummy_keyb.c 2003-08-25 13:44:41.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/char/dummy_keyb.c 2004-01-09 09:53:08.000000000 +0100
+@@ -140,3 +140,7 @@
+ {
+ printk("Dummy keyboard driver installed.\n");
+ }
++#ifdef CONFIG_MAGIC_SYSRQ
++unsigned char kbd_sysrq_key;
++unsigned char kbd_sysrq_xlate[128];
++#endif
+diff -Nur linux-2.4.32-rc1/drivers/char/dz.c linux-2.4.32-rc1.mips/drivers/char/dz.c
+--- linux-2.4.32-rc1/drivers/char/dz.c 2005-01-19 15:09:44.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/char/dz.c 2004-12-27 05:13:42.000000000 +0100
+@@ -1,11 +1,13 @@
+ /*
+- * dz.c: Serial port driver for DECStations equiped
++ * dz.c: Serial port driver for DECstations equipped
+ * with the DZ chipset.
+ *
+ * Copyright (C) 1998 Olivier A. D. Lebaillif
+ *
+ * Email: olivier.lebaillif@ifrsys.com
+ *
++ * Copyright (C) 2004 Maciej W. Rozycki
++ *
+ * [31-AUG-98] triemer
+ * Changed IRQ to use Harald's dec internals interrupts.h
+ * removed base_addr code - moving address assignment to setup.c
+@@ -24,6 +26,7 @@
+ #undef DEBUG_DZ
+
+ #include <linux/config.h>
++#include <linux/delay.h>
+ #include <linux/version.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+@@ -54,33 +57,56 @@
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+
+-#define CONSOLE_LINE (3) /* for definition of struct console */
++#ifdef CONFIG_MAGIC_SYSRQ
++#include <linux/sysrq.h>
++#endif
+
+ #include "dz.h"
+
+-#define DZ_INTR_DEBUG 1
+-
+ DECLARE_TASK_QUEUE(tq_serial);
+
+-static struct dz_serial *lines[4];
+-static unsigned char tmp_buffer[256];
++static struct dz_serial multi[DZ_NB_PORT]; /* Four serial lines in the DZ chip */
++static struct tty_driver serial_driver, callout_driver;
++
++static struct tty_struct *serial_table[DZ_NB_PORT];
++static struct termios *serial_termios[DZ_NB_PORT];
++static struct termios *serial_termios_locked[DZ_NB_PORT];
++
++static int serial_refcount;
+
+-#ifdef DEBUG_DZ
+ /*
+- * debugging code to send out chars via prom
++ * tmp_buf is used as a temporary buffer by serial_write. We need to
++ * lock it in case the copy_from_user blocks while swapping in a page,
++ * and some other program tries to do a serial write at the same time.
++ * Since the lock will only come under contention when the system is
++ * swapping and available memory is low, it makes sense to share one
++ * buffer across all the serial ports, since it significantly saves
++ * memory if large numbers of serial ports are open.
+ */
+-static void debug_console(const char *s, int count)
+-{
+- unsigned i;
++static unsigned char *tmp_buf;
++static DECLARE_MUTEX(tmp_buf_sem);
+
+- for (i = 0; i < count; i++) {
+- if (*s == 10)
+- prom_printf("%c", 13);
+- prom_printf("%c", *s++);
+- }
+-}
++static char *dz_name __initdata = "DECstation DZ serial driver version ";
++static char *dz_version __initdata = "1.03";
++
++static struct dz_serial *lines[DZ_NB_PORT];
++static unsigned char tmp_buffer[256];
++
++#ifdef CONFIG_SERIAL_DEC_CONSOLE
++static struct console dz_sercons;
++#endif
++#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
++ !defined(MODULE)
++static unsigned long break_pressed; /* break, really ... */
+ #endif
+
++static void change_speed (struct dz_serial *);
++
++static int baud_table[] = {
++ 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
++ 9600, 0
++};
++
+ /*
+ * ------------------------------------------------------------
+ * dz_in () and dz_out ()
+@@ -94,15 +120,16 @@
+ {
+ volatile unsigned short *addr =
+ (volatile unsigned short *) (info->port + offset);
++
+ return *addr;
+ }
+
+ static inline void dz_out(struct dz_serial *info, unsigned offset,
+ unsigned short value)
+ {
+-
+ volatile unsigned short *addr =
+ (volatile unsigned short *) (info->port + offset);
++
+ *addr = value;
+ }
+
+@@ -143,25 +170,24 @@
+
+ tmp |= mask; /* set the TX flag */
+ dz_out(info, DZ_TCR, tmp);
+-
+ }
+
+ /*
+ * ------------------------------------------------------------
+- * Here starts the interrupt handling routines. All of the
+- * following subroutines are declared as inline and are folded
+- * into dz_interrupt. They were separated out for readability's
+- * sake.
+ *
+- * Note: rs_interrupt() is a "fast" interrupt, which means that it
++ * Here starts the interrupt handling routines. All of the following
++ * subroutines are declared as inline and are folded into
++ * dz_interrupt(). They were separated out for readability's sake.
++ *
++ * Note: dz_interrupt() is a "fast" interrupt, which means that it
+ * runs with interrupts turned off. People who may want to modify
+- * rs_interrupt() should try to keep the interrupt handler as fast as
++ * dz_interrupt() should try to keep the interrupt handler as fast as
+ * possible. After you are done making modifications, it is not a bad
+ * idea to do:
+ *
+ * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer dz.c
+ *
+- * and look at the resulting assemble code in serial.s.
++ * and look at the resulting assemble code in dz.s.
+ *
+ * ------------------------------------------------------------
+ */
+@@ -188,101 +214,97 @@
+ * This routine deals with inputs from any lines.
+ * ------------------------------------------------------------
+ */
+-static inline void receive_chars(struct dz_serial *info_in)
++static inline void receive_chars(struct dz_serial *info_in,
++ struct pt_regs *regs)
+ {
+-
+ struct dz_serial *info;
+- struct tty_struct *tty = 0;
++ struct tty_struct *tty;
+ struct async_icount *icount;
+- int ignore = 0;
+- unsigned short status, tmp;
+- unsigned char ch;
+-
+- /* this code is going to be a problem...
+- the call to tty_flip_buffer is going to need
+- to be rethought...
+- */
+- do {
+- status = dz_in(info_in, DZ_RBUF);
+- info = lines[LINE(status)];
++ int lines_rx[DZ_NB_PORT] = { [0 ... DZ_NB_PORT - 1] = 0 };
++ unsigned short status;
++ unsigned char ch, flag;
++ int i;
+
+- /* punt so we don't get duplicate characters */
+- if (!(status & DZ_DVAL))
+- goto ignore_char;
+-
+- ch = UCHAR(status); /* grab the char */
+-
+-#if 0
+- if (info->is_console) {
+- if (ch == 0)
+- return; /* it's a break ... */
+- }
+-#endif
++ while ((status = dz_in(info_in, DZ_RBUF)) & DZ_DVAL) {
++ info = lines[LINE(status)];
++ tty = info->tty; /* point to the proper dev */
+
+- tty = info->tty; /* now tty points to the proper dev */
+- icount = &info->icount;
++ ch = UCHAR(status); /* grab the char */
+
+- if (!tty)
+- break;
+- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+- break;
++ if (!tty && (!info->hook || !info->hook->rx_char))
++ continue;
+
+- *tty->flip.char_buf_ptr = ch;
+- *tty->flip.flag_buf_ptr = 0;
++ icount = &info->icount;
+ icount->rx++;
+
+- /* keep track of the statistics */
+- if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) {
+- if (status & DZ_PERR) /* parity error */
+- icount->parity++;
+- else if (status & DZ_FERR) /* frame error */
+- icount->frame++;
+- if (status & DZ_OERR) /* overrun error */
+- icount->overrun++;
+-
+- /* check to see if we should ignore the character
+- and mask off conditions that should be ignored
++ flag = 0;
++ if (status & DZ_FERR) { /* frame error */
++ /*
++ * There is no separate BREAK status bit, so
++ * treat framing errors as BREAKs for Magic SysRq
++ * and SAK; normally, otherwise.
+ */
+-
+- if (status & info->ignore_status_mask) {
+- if (++ignore > 100)
+- break;
+- goto ignore_char;
++#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
++ !defined(MODULE)
++ if (info->line == dz_sercons.index) {
++ if (!break_pressed)
++ break_pressed = jiffies;
++ continue;
+ }
+- /* mask off the error conditions we want to ignore */
+- tmp = status & info->read_status_mask;
+-
+- if (tmp & DZ_PERR) {
+- *tty->flip.flag_buf_ptr = TTY_PARITY;
+-#ifdef DEBUG_DZ
+- debug_console("PERR\n", 5);
+-#endif
+- } else if (tmp & DZ_FERR) {
+- *tty->flip.flag_buf_ptr = TTY_FRAME;
+-#ifdef DEBUG_DZ
+- debug_console("FERR\n", 5);
+ #endif
++ flag = TTY_BREAK;
++ if (info->flags & DZ_SAK)
++ do_SAK(tty);
++ else
++ flag = TTY_FRAME;
++ } else if (status & DZ_OERR) /* overrun error */
++ flag = TTY_OVERRUN;
++ else if (status & DZ_PERR) /* parity error */
++ flag = TTY_PARITY;
++
++#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
++ !defined(MODULE)
++ if (break_pressed && info->line == dz_sercons.index) {
++ if (time_before(jiffies, break_pressed + HZ * 5)) {
++ handle_sysrq(ch, regs, NULL, NULL);
++ break_pressed = 0;
++ continue;
+ }
+- if (tmp & DZ_OERR) {
+-#ifdef DEBUG_DZ
+- debug_console("OERR\n", 5);
++ break_pressed = 0;
++ }
+ #endif
+- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
+- tty->flip.count++;
+- tty->flip.flag_buf_ptr++;
+- tty->flip.char_buf_ptr++;
+- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
+- }
+- }
++
++ if (info->hook && info->hook->rx_char) {
++ (*info->hook->rx_char)(ch, flag);
++ return;
+ }
+- tty->flip.flag_buf_ptr++;
+- tty->flip.char_buf_ptr++;
+- tty->flip.count++;
+- ignore_char:
+- } while (status & DZ_DVAL);
+
+- if (tty)
+- tty_flip_buffer_push(tty);
++ /* keep track of the statistics */
++ switch (flag) {
++ case TTY_FRAME:
++ icount->frame++;
++ break;
++ case TTY_PARITY:
++ icount->parity++;
++ break;
++ case TTY_OVERRUN:
++ icount->overrun++;
++ break;
++ case TTY_BREAK:
++ icount->brk++;
++ break;
++ default:
++ break;
++ }
++
++ if ((status & info->ignore_status_mask) == 0) {
++ tty_insert_flip_char(tty, ch, flag);
++ lines_rx[LINE(status)] = 1;
++ }
++ }
++ for (i = 0; i < DZ_NB_PORT; i++)
++ if (lines_rx[i])
++ tty_flip_buffer_push(lines[i]->tty);
+ }
+
+ /*
+@@ -292,20 +314,34 @@
+ * This routine deals with outputs to any lines.
+ * ------------------------------------------------------------
+ */
+-static inline void transmit_chars(struct dz_serial *info)
++static inline void transmit_chars(struct dz_serial *info_in)
+ {
++ struct dz_serial *info;
++ unsigned short status;
+ unsigned char tmp;
+
++ status = dz_in(info_in, DZ_CSR);
++ info = lines[LINE(status)];
+
++ if (info->hook || !info->tty) {
++ unsigned short mask, tmp;
+
+- if (info->x_char) { /* XON/XOFF chars */
++ mask = 1 << info->line;
++ tmp = dz_in(info, DZ_TCR); /* read the TX flag */
++ tmp &= ~mask; /* clear the TX flag */
++ dz_out(info, DZ_TCR, tmp);
++ return;
++ }
++
++ if (info->x_char) { /* XON/XOFF chars */
+ dz_out(info, DZ_TDR, info->x_char);
+ info->icount.tx++;
+ info->x_char = 0;
+ return;
+ }
+ /* if nothing to do or stopped or hardware stopped */
+- if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tty->hw_stopped) {
++ if (info->xmit_cnt <= 0 ||
++ info->tty->stopped || info->tty->hw_stopped) {
+ dz_stop(info->tty);
+ return;
+ }
+@@ -359,15 +395,14 @@
+ */
+ static void dz_interrupt(int irq, void *dev, struct pt_regs *regs)
+ {
+- struct dz_serial *info;
++ struct dz_serial *info = (struct dz_serial *)dev;
+ unsigned short status;
+
+ /* get the reason why we just got an irq */
+- status = dz_in((struct dz_serial *) dev, DZ_CSR);
+- info = lines[LINE(status)]; /* re-arrange info the proper port */
++ status = dz_in(info, DZ_CSR);
+
+ if (status & DZ_RDONE)
+- receive_chars(info); /* the receive function */
++ receive_chars(info, regs);
+
+ if (status & DZ_TRDY)
+ transmit_chars(info);
+@@ -514,7 +549,7 @@
+
+
+ info->cflags &= ~DZ_CREAD; /* turn off receive enable flag */
+- dz_out(info, DZ_LPR, info->cflags);
++ dz_out(info, DZ_LPR, info->cflags | info->line);
+
+ if (info->xmit_buf) { /* free Tx buffer */
+ free_page((unsigned long) info->xmit_buf);
+@@ -545,18 +580,21 @@
+ {
+ unsigned long flags;
+ unsigned cflag;
+- int baud;
++ int baud, i;
+
+- if (!info->tty || !info->tty->termios)
+- return;
++ if (!info->hook) {
++ if (!info->tty || !info->tty->termios)
++ return;
++ cflag = info->tty->termios->c_cflag;
++ } else {
++ cflag = info->hook->cflags;
++ }
+
+ save_flags(flags);
+ cli();
+
+ info->cflags = info->line;
+
+- cflag = info->tty->termios->c_cflag;
+-
+ switch (cflag & CSIZE) {
+ case CS5:
+ info->cflags |= DZ_CS5;
+@@ -579,7 +617,16 @@
+ if (cflag & PARODD)
+ info->cflags |= DZ_PARODD;
+
+- baud = tty_get_baud_rate(info->tty);
++ i = cflag & CBAUD;
++ if (i & CBAUDEX) {
++ i &= ~CBAUDEX;
++ if (!info->hook)
++ info->tty->termios->c_cflag &= ~CBAUDEX;
++ else
++ info->hook->cflags &= ~CBAUDEX;
++ }
++ baud = baud_table[i];
++
+ switch (baud) {
+ case 50:
+ info->cflags |= DZ_B50;
+@@ -629,16 +676,16 @@
+ }
+
+ info->cflags |= DZ_RXENAB;
+- dz_out(info, DZ_LPR, info->cflags);
++ dz_out(info, DZ_LPR, info->cflags | info->line);
+
+ /* setup accept flag */
+ info->read_status_mask = DZ_OERR;
+- if (I_INPCK(info->tty))
++ if (info->tty && I_INPCK(info->tty))
+ info->read_status_mask |= (DZ_FERR | DZ_PERR);
+
+ /* characters to ignore */
+ info->ignore_status_mask = 0;
+- if (I_IGNPAR(info->tty))
++ if (info->tty && I_IGNPAR(info->tty))
+ info->ignore_status_mask |= (DZ_FERR | DZ_PERR);
+
+ restore_flags(flags);
+@@ -694,7 +741,7 @@
+
+ down(&tmp_buf_sem);
+ while (1) {
+- c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
++ c = min(count, min(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
+ if (c <= 0)
+ break;
+
+@@ -707,7 +754,7 @@
+ save_flags(flags);
+ cli();
+
+- c = MIN(c, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
++ c = min(c, min(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
+ memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
+ info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE - 1));
+ info->xmit_cnt += c;
+@@ -727,7 +774,7 @@
+ save_flags(flags);
+ cli();
+
+- c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
++ c = min(count, min(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
+ if (c <= 0) {
+ restore_flags(flags);
+ break;
+@@ -845,7 +892,7 @@
+
+ /*
+ * ------------------------------------------------------------
+- * rs_ioctl () and friends
++ * dz_ioctl () and friends
+ * ------------------------------------------------------------
+ */
+ static int get_serial_info(struct dz_serial *info,
+@@ -958,6 +1005,9 @@
+ struct dz_serial *info = (struct dz_serial *) tty->driver_data;
+ int retval;
+
++ if (info->hook)
++ return -ENODEV;
++
+ if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+ (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
+ (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
+@@ -1252,19 +1302,14 @@
+ int retval, line;
+
+ line = MINOR(tty->device) - tty->driver.minor_start;
+-
+- /* The dz lines for the mouse/keyboard must be
+- * opened using their respective drivers.
+- */
+ if ((line < 0) || (line >= DZ_NB_PORT))
+ return -ENODEV;
++ info = lines[line];
+
+- if ((line == DZ_KEYBOARD) || (line == DZ_MOUSE))
++ if (info->hook)
+ return -ENODEV;
+
+- info = lines[line];
+ info->count++;
+-
+ tty->driver_data = info;
+ info->tty = tty;
+
+@@ -1285,14 +1330,21 @@
+ else
+ *tty->termios = info->callout_termios;
+ change_speed(info);
+-
+ }
++#ifdef CONFIG_SERIAL_DEC_CONSOLE
++ if (dz_sercons.cflag && dz_sercons.index == line) {
++ tty->termios->c_cflag = dz_sercons.cflag;
++ dz_sercons.cflag = 0;
++ change_speed(info);
++ }
++#endif
++
+ info->session = current->session;
+ info->pgrp = current->pgrp;
+ return 0;
+ }
+
+-static void show_serial_version(void)
++static void __init show_serial_version(void)
+ {
+ printk("%s%s\n", dz_name, dz_version);
+ }
+@@ -1300,7 +1352,6 @@
+ int __init dz_init(void)
+ {
+ int i;
+- long flags;
+ struct dz_serial *info;
+
+ /* Setup base handler, and timer table. */
+@@ -1311,9 +1362,9 @@
+ memset(&serial_driver, 0, sizeof(struct tty_driver));
+ serial_driver.magic = TTY_DRIVER_MAGIC;
+ #if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
+- serial_driver.name = "ttyS";
+-#else
+ serial_driver.name = "tts/%d";
++#else
++ serial_driver.name = "ttyS";
+ #endif
+ serial_driver.major = TTY_MAJOR;
+ serial_driver.minor_start = 64;
+@@ -1352,9 +1403,9 @@
+ */
+ callout_driver = serial_driver;
+ #if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
+- callout_driver.name = "cua";
+-#else
+ callout_driver.name = "cua/%d";
++#else
++ callout_driver.name = "cua";
+ #endif
+ callout_driver.major = TTYAUX_MAJOR;
+ callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+@@ -1363,25 +1414,27 @@
+ panic("Couldn't register serial driver");
+ if (tty_register_driver(&callout_driver))
+ panic("Couldn't register callout driver");
+- save_flags(flags);
+- cli();
+
+ for (i = 0; i < DZ_NB_PORT; i++) {
+ info = &multi[i];
+ lines[i] = info;
+- info->magic = SERIAL_MAGIC;
+-
++ info->tty = 0;
++ info->x_char = 0;
+ if (mips_machtype == MACH_DS23100 ||
+ mips_machtype == MACH_DS5100)
+ info->port = (unsigned long) KN01_DZ11_BASE;
+ else
+ info->port = (unsigned long) KN02_DZ11_BASE;
+-
+ info->line = i;
+- info->tty = 0;
++
++ if (info->hook && info->hook->init_info) {
++ (*info->hook->init_info)(info);
++ continue;
++ }
++
++ info->magic = SERIAL_MAGIC;
+ info->close_delay = 50;
+ info->closing_wait = 3000;
+- info->x_char = 0;
+ info->event = 0;
+ info->count = 0;
+ info->blocked_open = 0;
+@@ -1393,25 +1446,16 @@
+ info->normal_termios = serial_driver.init_termios;
+ init_waitqueue_head(&info->open_wait);
+ init_waitqueue_head(&info->close_wait);
+-
+- /*
+- * If we are pointing to address zero then punt - not correctly
+- * set up in setup.c to handle this.
+- */
+- if (!info->port)
+- return 0;
+-
+- printk("ttyS%02d at 0x%08x (irq = %d)\n", info->line,
+- info->port, dec_interrupt[DEC_IRQ_DZ11]);
+-
++ printk("ttyS%02d at 0x%08x (irq = %d) is a DC7085 DZ\n",
++ info->line, info->port, dec_interrupt[DEC_IRQ_DZ11]);
+ tty_register_devfs(&serial_driver, 0,
+- serial_driver.minor_start + info->line);
++ serial_driver.minor_start + info->line);
+ tty_register_devfs(&callout_driver, 0,
+- callout_driver.minor_start + info->line);
++ callout_driver.minor_start + info->line);
+ }
+
+- /* reset the chip */
+ #ifndef CONFIG_SERIAL_DEC_CONSOLE
++ /* reset the chip */
+ dz_out(info, DZ_CSR, DZ_CLR);
+ while (dz_in(info, DZ_CSR) & DZ_CLR);
+ iob();
+@@ -1420,43 +1464,104 @@
+ dz_out(info, DZ_CSR, DZ_MSE);
+ #endif
+
+- /* order matters here... the trick is that flags
+- is updated... in request_irq - to immediatedly obliterate
+- it is unwise. */
+- restore_flags(flags);
+-
+-
+ if (request_irq(dec_interrupt[DEC_IRQ_DZ11], dz_interrupt,
+- SA_INTERRUPT, "DZ", lines[0]))
++ 0, "DZ", lines[0]))
+ panic("Unable to register DZ interrupt");
+
++ for (i = 0; i < DZ_NB_PORT; i++)
++ if (lines[i]->hook) {
++ startup(lines[i]);
++ if (lines[i]->hook->init_channel)
++ (*lines[i]->hook->init_channel)(lines[i]);
++ }
++
+ return 0;
+ }
+
+-#ifdef CONFIG_SERIAL_DEC_CONSOLE
+-static void dz_console_put_char(unsigned char ch)
++/*
++ * polling I/O routines
++ */
++static int dz_poll_tx_char(void *handle, unsigned char ch)
+ {
+ unsigned long flags;
+- int loops = 2500;
+- unsigned short tmp = ch;
+- /* this code sends stuff out to serial device - spinning its
+- wheels and waiting. */
++ struct dz_serial *info = handle;
++ unsigned short csr, tcr, trdy, mask;
++ int loops = 10000;
++ int ret;
+
+- /* force the issue - point it at lines[3] */
+- dz_console = &multi[CONSOLE_LINE];
++ local_irq_save(flags);
++ csr = dz_in(info, DZ_CSR);
++ dz_out(info, DZ_CSR, csr & ~DZ_TIE);
++ tcr = dz_in(info, DZ_TCR);
++ tcr |= 1 << info->line;
++ mask = tcr;
++ dz_out(info, DZ_TCR, mask);
++ iob();
++ local_irq_restore(flags);
+
+- save_flags(flags);
+- cli();
++ while (loops--) {
++ trdy = dz_in(info, DZ_CSR);
++ if (!(trdy & DZ_TRDY))
++ continue;
++ trdy = (trdy & DZ_TLINE) >> 8;
++ if (trdy == info->line)
++ break;
++ mask &= ~(1 << trdy);
++ dz_out(info, DZ_TCR, mask);
++ iob();
++ udelay(2);
++ }
+
++ if (loops) {
++ dz_out(info, DZ_TDR, ch);
++ ret = 0;
++ } else
++ ret = -EAGAIN;
+
+- /* spin our wheels */
+- while (((dz_in(dz_console, DZ_CSR) & DZ_TRDY) != DZ_TRDY) && loops--);
++ dz_out(info, DZ_TCR, tcr);
++ dz_out(info, DZ_CSR, csr);
+
+- /* Actually transmit the character. */
+- dz_out(dz_console, DZ_TDR, tmp);
++ return ret;
++}
+
+- restore_flags(flags);
++static int dz_poll_rx_char(void *handle)
++{
++ return -ENODEV;
++}
++
++int register_dz_hook(unsigned int channel, struct dec_serial_hook *hook)
++{
++ struct dz_serial *info = multi + channel;
++
++ if (info->hook) {
++ printk("%s: line %d has already a hook registered\n",
++ __FUNCTION__, channel);
++
++ return 0;
++ } else {
++ hook->poll_rx_char = dz_poll_rx_char;
++ hook->poll_tx_char = dz_poll_tx_char;
++ info->hook = hook;
++
++ return 1;
++ }
++}
++
++int unregister_dz_hook(unsigned int channel)
++{
++ struct dz_serial *info = &multi[channel];
++
++ if (info->hook) {
++ info->hook = NULL;
++ return 1;
++ } else {
++ printk("%s: trying to unregister hook on line %d,"
++ " but none is registered\n", __FUNCTION__, channel);
++ return 0;
++ }
+ }
++
++#ifdef CONFIG_SERIAL_DEC_CONSOLE
+ /*
+ * -------------------------------------------------------------------
+ * dz_console_print ()
+@@ -1465,17 +1570,19 @@
+ * The console must be locked when we get here.
+ * -------------------------------------------------------------------
+ */
+-static void dz_console_print(struct console *cons,
++static void dz_console_print(struct console *co,
+ const char *str,
+ unsigned int count)
+ {
++ struct dz_serial *info = multi + co->index;
++
+ #ifdef DEBUG_DZ
+ prom_printf((char *) str);
+ #endif
+ while (count--) {
+ if (*str == '\n')
+- dz_console_put_char('\r');
+- dz_console_put_char(*str++);
++ dz_poll_tx_char(info, '\r');
++ dz_poll_tx_char(info, *str++);
+ }
+ }
+
+@@ -1486,12 +1593,12 @@
+
+ static int __init dz_console_setup(struct console *co, char *options)
+ {
++ struct dz_serial *info = multi + co->index;
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+ int cflag = CREAD | HUPCL | CLOCAL;
+ char *s;
+- unsigned short mask, tmp;
+
+ if (options) {
+ baud = simple_strtoul(options, NULL, 10);
+@@ -1542,44 +1649,31 @@
+ }
+ co->cflag = cflag;
+
+- /* TOFIX: force to console line */
+- dz_console = &multi[CONSOLE_LINE];
+ if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100))
+- dz_console->port = KN01_DZ11_BASE;
++ info->port = KN01_DZ11_BASE;
+ else
+- dz_console->port = KN02_DZ11_BASE;
+- dz_console->line = CONSOLE_LINE;
++ info->port = KN02_DZ11_BASE;
++ info->line = co->index;
+
+- dz_out(dz_console, DZ_CSR, DZ_CLR);
+- while ((tmp = dz_in(dz_console, DZ_CSR)) & DZ_CLR);
++ dz_out(info, DZ_CSR, DZ_CLR);
++ while (dz_in(info, DZ_CSR) & DZ_CLR);
+
+ /* enable scanning */
+- dz_out(dz_console, DZ_CSR, DZ_MSE);
++ dz_out(info, DZ_CSR, DZ_MSE);
+
+ /* Set up flags... */
+- dz_console->cflags = 0;
+- dz_console->cflags |= DZ_B9600;
+- dz_console->cflags |= DZ_CS8;
+- dz_console->cflags |= DZ_PARENB;
+- dz_out(dz_console, DZ_LPR, dz_console->cflags);
+-
+- mask = 1 << dz_console->line;
+- tmp = dz_in(dz_console, DZ_TCR); /* read the TX flag */
+- if (!(tmp & mask)) {
+- tmp |= mask; /* set the TX flag */
+- dz_out(dz_console, DZ_TCR, tmp);
+- }
++ dz_out(info, DZ_LPR, cflag | info->line);
++
+ return 0;
+ }
+
+-static struct console dz_sercons =
+-{
+- .name = "ttyS",
+- .write = dz_console_print,
+- .device = dz_console_device,
+- .setup = dz_console_setup,
+- .flags = CON_CONSDEV | CON_PRINTBUFFER,
+- .index = CONSOLE_LINE,
++static struct console dz_sercons = {
++ .name = "ttyS",
++ .write = dz_console_print,
++ .device = dz_console_device,
++ .setup = dz_console_setup,
++ .flags = CON_PRINTBUFFER,
++ .index = -1,
+ };
+
+ void __init dz_serial_console_init(void)
+diff -Nur linux-2.4.32-rc1/drivers/char/dz.h linux-2.4.32-rc1.mips/drivers/char/dz.h
+--- linux-2.4.32-rc1/drivers/char/dz.h 2002-08-03 02:39:43.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/char/dz.h 2004-09-28 02:53:01.000000000 +0200
+@@ -10,6 +10,8 @@
+ #ifndef DZ_SERIAL_H
+ #define DZ_SERIAL_H
+
++#include <asm/dec/serial.h>
++
+ #define SERIAL_MAGIC 0x5301
+
+ /*
+@@ -17,6 +19,7 @@
+ */
+ #define DZ_TRDY 0x8000 /* Transmitter empty */
+ #define DZ_TIE 0x4000 /* Transmitter Interrupt Enable */
++#define DZ_TLINE 0x0300 /* Transmitter Line Number */
+ #define DZ_RDONE 0x0080 /* Receiver data ready */
+ #define DZ_RIE 0x0040 /* Receive Interrupt Enable */
+ #define DZ_MSE 0x0020 /* Master Scan Enable */
+@@ -37,19 +40,30 @@
+ #define UCHAR(x) (unsigned char)(x & DZ_RBUF_MASK)
+
+ /*
+- * Definitions for the Transmit Register.
++ * Definitions for the Transmit Control Register.
+ */
+ #define DZ_LINE_KEYBOARD 0x0001
+ #define DZ_LINE_MOUSE 0x0002
+ #define DZ_LINE_MODEM 0x0004
+ #define DZ_LINE_PRINTER 0x0008
+
++#define DZ_MODEM_RTS 0x0800 /* RTS for the modem line (2) */
+ #define DZ_MODEM_DTR 0x0400 /* DTR for the modem line (2) */
++#define DZ_PRINT_RTS 0x0200 /* RTS for the printer line (3) */
++#define DZ_PRINT_DTR 0x0100 /* DTR for the printer line (3) */
++#define DZ_LNENB 0x000f /* Transmitter Line Enable */
+
+ /*
+ * Definitions for the Modem Status Register.
+ */
++#define DZ_MODEM_RI 0x0800 /* RI for the modem line (2) */
++#define DZ_MODEM_CD 0x0400 /* CD for the modem line (2) */
+ #define DZ_MODEM_DSR 0x0200 /* DSR for the modem line (2) */
++#define DZ_MODEM_CTS 0x0100 /* CTS for the modem line (2) */
++#define DZ_PRINT_RI 0x0008 /* RI for the printer line (2) */
++#define DZ_PRINT_CD 0x0004 /* CD for the printer line (2) */
++#define DZ_PRINT_DSR 0x0002 /* DSR for the printer line (2) */
++#define DZ_PRINT_CTS 0x0001 /* CTS for the printer line (2) */
+
+ /*
+ * Definitions for the Transmit Data Register.
+@@ -115,9 +129,6 @@
+
+ #define DZ_EVENT_WRITE_WAKEUP 0
+
+-#ifndef MIN
+-#define MIN(a,b) ((a) < (b) ? (a) : (b))
+-
+ #define DZ_INITIALIZED 0x80000000 /* Serial port was initialized */
+ #define DZ_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */
+ #define DZ_NORMAL_ACTIVE 0x20000000 /* Normal device is active */
+@@ -129,6 +140,7 @@
+ #define DZ_CLOSING_WAIT_INF 0
+ #define DZ_CLOSING_WAIT_NONE 65535
+
++#define DZ_SAK 0x0004 /* Secure Attention Key (Orange book) */
+ #define DZ_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
+ #define DZ_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */
+ #define DZ_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */
+@@ -166,79 +178,9 @@
+ long session; /* Session of opening process */
+ long pgrp; /* pgrp of opening process */
+
++ struct dec_serial_hook *hook; /* Hook on this channel. */
+ unsigned char is_console; /* flag indicating a serial console */
+ unsigned char is_initialized;
+ };
+
+-static struct dz_serial multi[DZ_NB_PORT]; /* Four serial lines in the DZ chip */
+-static struct dz_serial *dz_console;
+-static struct tty_driver serial_driver, callout_driver;
+-
+-static struct tty_struct *serial_table[DZ_NB_PORT];
+-static struct termios *serial_termios[DZ_NB_PORT];
+-static struct termios *serial_termios_locked[DZ_NB_PORT];
+-
+-static int serial_refcount;
+-
+-/*
+- * tmp_buf is used as a temporary buffer by serial_write. We need to
+- * lock it in case the copy_from_user blocks while swapping in a page,
+- * and some other program tries to do a serial write at the same time.
+- * Since the lock will only come under contention when the system is
+- * swapping and available memory is low, it makes sense to share one
+- * buffer across all the serial ports, since it significantly saves
+- * memory if large numbers of serial ports are open.
+- */
+-static unsigned char *tmp_buf;
+-static DECLARE_MUTEX(tmp_buf_sem);
+-
+-static char *dz_name = "DECstation DZ serial driver version ";
+-static char *dz_version = "1.02";
+-
+-static inline unsigned short dz_in (struct dz_serial *, unsigned);
+-static inline void dz_out (struct dz_serial *, unsigned, unsigned short);
+-
+-static inline void dz_sched_event (struct dz_serial *, int);
+-static inline void receive_chars (struct dz_serial *);
+-static inline void transmit_chars (struct dz_serial *);
+-static inline void check_modem_status (struct dz_serial *);
+-
+-static void dz_stop (struct tty_struct *);
+-static void dz_start (struct tty_struct *);
+-static void dz_interrupt (int, void *, struct pt_regs *);
+-static void do_serial_bh (void);
+-static void do_softint (void *);
+-static void do_serial_hangup (void *);
+-static void change_speed (struct dz_serial *);
+-static void dz_flush_chars (struct tty_struct *);
+-static void dz_console_print (struct console *, const char *, unsigned int);
+-static void dz_flush_buffer (struct tty_struct *);
+-static void dz_throttle (struct tty_struct *);
+-static void dz_unthrottle (struct tty_struct *);
+-static void dz_send_xchar (struct tty_struct *, char);
+-static void shutdown (struct dz_serial *);
+-static void send_break (struct dz_serial *, int);
+-static void dz_set_termios (struct tty_struct *, struct termios *);
+-static void dz_close (struct tty_struct *, struct file *);
+-static void dz_hangup (struct tty_struct *);
+-static void show_serial_version (void);
+-
+-static int dz_write (struct tty_struct *, int, const unsigned char *, int);
+-static int dz_write_room (struct tty_struct *);
+-static int dz_chars_in_buffer (struct tty_struct *);
+-static int startup (struct dz_serial *);
+-static int get_serial_info (struct dz_serial *, struct serial_struct *);
+-static int set_serial_info (struct dz_serial *, struct serial_struct *);
+-static int get_lsr_info (struct dz_serial *, unsigned int *);
+-static int dz_ioctl (struct tty_struct *, struct file *, unsigned int, unsigned long);
+-static int block_til_ready (struct tty_struct *, struct file *, struct dz_serial *);
+-static int dz_open (struct tty_struct *, struct file *);
+-
+-#ifdef MODULE
+-int init_module (void)
+-void cleanup_module (void)
+-#endif
+-
+-#endif
+-
+ #endif /* DZ_SERIAL_H */
+diff -Nur linux-2.4.32-rc1/drivers/char/ibm_workpad_keymap.map linux-2.4.32-rc1.mips/drivers/char/ibm_workpad_keymap.map
+--- linux-2.4.32-rc1/drivers/char/ibm_workpad_keymap.map 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/char/ibm_workpad_keymap.map 2003-12-20 15:20:44.000000000 +0100
+@@ -0,0 +1,343 @@
++# Keymap for IBM Workpad z50
++# US Mapping
++#
++# by Michael Klar <wyldfier@iname.com>
++#
++# This is a great big mess on account of how the Caps Lock key is handled as
++# LeftShift-RightShift. Right shift key had to be broken out, so don't use
++# use this map file as a basis for other keyboards that don't do the same
++# thing with Caps Lock.
++#
++# 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.
++
++keymaps 0-2,4-5,8,12,32-33,36-37
++strings as usual
++
++keycode 0 = F1 F11 Console_13
++ shiftr keycode 0 = F11
++ shift shiftr keycode 0 = F11
++ control keycode 0 = F1
++ alt keycode 0 = Console_1
++ control alt keycode 0 = Console_1
++keycode 1 = F3 F13 Console_15
++ shiftr keycode 1 = F13
++ shift shiftr keycode 1 = F13
++ control keycode 1 = F3
++ alt keycode 1 = Console_3
++ control alt keycode 1 = Console_3
++keycode 2 = F5 F15 Console_17
++ shiftr keycode 2 = F15
++ shift shiftr keycode 2 = F15
++ control keycode 2 = F5
++ alt keycode 2 = Console_5
++ control alt keycode 2 = Console_5
++keycode 3 = F7 F17 Console_19
++ shiftr keycode 3 = F17
++ shift shiftr keycode 3 = F17
++ control keycode 3 = F7
++ alt keycode 3 = Console_7
++ control alt keycode 3 = Console_7
++keycode 4 = F9 F19 Console_21
++ shiftr keycode 4 = F19
++ shift shiftr keycode 4 = F19
++ control keycode 4 = F9
++ alt keycode 4 = Console_9
++ control alt keycode 4 = Console_9
++#keycode 5 is contrast down
++#keycode 6 is contrast up
++keycode 7 = F11 F11 Console_23
++ shiftr keycode 7 = F11
++ shift shiftr keycode 7 = F11
++ control keycode 7 = F11
++ alt keycode 7 = Console_11
++ control alt keycode 7 = Console_11
++keycode 8 = F2 F12 Console_14
++ shiftr keycode 8 = F12
++ shift shiftr keycode 8 = F12
++ control keycode 8 = F2
++ alt keycode 8 = Console_2
++ control alt keycode 8 = Console_2
++keycode 9 = F4 F14 Console_16
++ shiftr keycode 9 = F14
++ shift shiftr keycode 9 = F14
++ control keycode 9 = F4
++ alt keycode 9 = Console_4
++ control alt keycode 9 = Console_4
++keycode 10 = F6 F16 Console_18
++ shiftr keycode 10 = F16
++ shift shiftr keycode 10 = F16
++ control keycode 10 = F6
++ alt keycode 10 = Console_6
++ control alt keycode 10 = Console_6
++keycode 11 = F8 F18 Console_20
++ shiftr keycode 11 = F18
++ shift shiftr keycode 11 = F18
++ control keycode 11 = F8
++ alt keycode 11 = Console_8
++ control alt keycode 11 = Console_8
++keycode 12 = F10 F20 Console_22
++ shiftr keycode 12 = F20
++ shift shiftr keycode 12 = F20
++ control keycode 12 = F10
++ alt keycode 12 = Console_10
++ control alt keycode 12 = Console_10
++#keycode 13 is brightness down
++#keycode 14 is brightness up
++keycode 15 = F12 F12 Console_24
++ shiftr keycode 15 = F12
++ shift shiftr keycode 15 = F12
++ control keycode 15 = F12
++ alt keycode 15 = Console_12
++ control alt keycode 15 = Console_12
++keycode 16 = apostrophe quotedbl
++ shiftr keycode 16 = quotedbl
++ shift shiftr keycode 16 = quotedbl
++ control keycode 16 = Control_g
++ alt keycode 16 = Meta_apostrophe
++keycode 17 = bracketleft braceleft
++ shiftr keycode 17 = braceleft
++ shift shiftr keycode 17 = braceleft
++ control keycode 17 = Escape
++ alt keycode 17 = Meta_bracketleft
++keycode 18 = minus underscore backslash
++ shiftr keycode 18 = underscore
++ shift shiftr keycode 18 = underscore
++ control keycode 18 = Control_underscore
++ shift control keycode 18 = Control_underscore
++ shiftr control keycode 18 = Control_underscore
++ shift shiftr control keycode 18 = Control_underscore
++ alt keycode 18 = Meta_minus
++keycode 19 = zero parenright braceright
++ shiftr keycode 19 = parenright
++ shift shiftr keycode 19 = parenright
++ alt keycode 19 = Meta_zero
++keycode 20 = p
++ shiftr keycode 20 = +P
++ shift shiftr keycode 20 = +p
++keycode 21 = semicolon colon
++ shiftr keycode 21 = colon
++ shift shiftr keycode 21 = colon
++ alt keycode 21 = Meta_semicolon
++keycode 22 = Up Scroll_Backward
++ shiftr keycode 22 = Scroll_Backward
++ shift shiftr keycode 22 = Scroll_Backward
++ alt keycode 22 = Prior
++keycode 23 = slash question
++ shiftr keycode 23 = question
++ shift shiftr keycode 23 = question
++ control keycode 23 = Delete
++ alt keycode 23 = Meta_slash
++
++keycode 27 = nine parenleft bracketright
++ shiftr keycode 27 = parenleft
++ shift shiftr keycode 27 = parenleft
++ alt keycode 27 = Meta_nine
++keycode 28 = o
++ shiftr keycode 28 = +O
++ shift shiftr keycode 28 = +o
++keycode 29 = l
++ shiftr keycode 29 = +L
++ shift shiftr keycode 29 = +l
++keycode 30 = period greater
++ shiftr keycode 30 = greater
++ shift shiftr keycode 30 = greater
++ control keycode 30 = Compose
++ alt keycode 30 = Meta_period
++
++keycode 32 = Left Decr_Console
++ shiftr keycode 32 = Decr_Console
++ shift shiftr keycode 32 = Decr_Console
++ alt keycode 32 = Home
++keycode 33 = bracketright braceright asciitilde
++ shiftr keycode 33 = braceright
++ shift shiftr keycode 33 = braceright
++ control keycode 33 = Control_bracketright
++ alt keycode 33 = Meta_bracketright
++keycode 34 = equal plus
++ shiftr keycode 34 = plus
++ shift shiftr keycode 34 = plus
++ alt keycode 34 = Meta_equal
++keycode 35 = eight asterisk bracketleft
++ shiftr keycode 35 = asterisk
++ shift shiftr keycode 35 = asterisk
++ control keycode 35 = Delete
++ alt keycode 35 = Meta_eight
++keycode 36 = i
++ shiftr keycode 36 = +I
++ shift shiftr keycode 36 = +i
++keycode 37 = k
++ shiftr keycode 37 = +K
++ shift shiftr keycode 37 = +k
++keycode 38 = comma less
++ shiftr keycode 38 = less
++ shift shiftr keycode 38 = less
++ alt keycode 38 = Meta_comma
++
++keycode 40 = h
++ shiftr keycode 40 = +H
++ shift shiftr keycode 40 = +h
++keycode 41 = y
++ shiftr keycode 41 = +Y
++ shift shiftr keycode 41 = +y
++keycode 42 = six asciicircum
++ shiftr keycode 42 = asciicircum
++ shift shiftr keycode 42 = asciicircum
++ control keycode 42 = Control_asciicircum
++ alt keycode 42 = Meta_six
++keycode 43 = seven ampersand braceleft
++ shiftr keycode 43 = ampersand
++ shift shiftr keycode 43 = ampersand
++ control keycode 43 = Control_underscore
++ alt keycode 43 = Meta_seven
++keycode 44 = u
++ shiftr keycode 44 = +U
++ shift shiftr keycode 44 = +u
++keycode 45 = j
++ shiftr keycode 45 = +J
++ shift shiftr keycode 45 = +j
++keycode 46 = m
++ shiftr keycode 46 = +M
++ shift shiftr keycode 46 = +m
++keycode 47 = n
++ shiftr keycode 47 = +N
++ shift shiftr keycode 47 = +n
++
++# This is the "Backspace" key:
++keycode 49 = Delete Delete
++ shiftr keycode 49 = Delete
++ shift shiftr keycode 49 = Delete
++ control keycode 49 = BackSpace
++ alt keycode 49 = Meta_Delete
++keycode 50 = Num_Lock
++ shift keycode 50 = Bare_Num_Lock
++ shiftr keycode 50 = Bare_Num_Lock
++ shift shiftr keycode 50 = Bare_Num_Lock
++# This is the "Delete" key:
++keycode 51 = Remove
++ control alt keycode 51 = Boot
++
++keycode 53 = backslash bar
++ shiftr keycode 53 = bar
++ shift shiftr keycode 53 = bar
++ control keycode 53 = Control_backslash
++ alt keycode 53 = Meta_backslash
++keycode 54 = Return
++ alt keycode 54 = Meta_Control_m
++keycode 55 = space space
++ shiftr keycode 55 = space
++ shift shiftr keycode 55 = space
++ control keycode 55 = nul
++ alt keycode 55 = Meta_space
++keycode 56 = g
++ shiftr keycode 56 = +G
++ shift shiftr keycode 56 = +g
++keycode 57 = t
++ shiftr keycode 57 = +T
++ shift shiftr keycode 57 = +t
++keycode 58 = five percent
++ shiftr keycode 58 = percent
++ shift shiftr keycode 58 = percent
++ control keycode 58 = Control_bracketright
++ alt keycode 58 = Meta_five
++keycode 59 = four dollar dollar
++ shiftr keycode 59 = dollar
++ shift shiftr keycode 59 = dollar
++ control keycode 59 = Control_backslash
++ alt keycode 59 = Meta_four
++keycode 60 = r
++ shiftr keycode 60 = +R
++ shift shiftr keycode 60 = +r
++keycode 61 = f
++ shiftr keycode 61 = +F
++ shift shiftr keycode 61 = +f
++ altgr keycode 61 = Hex_F
++keycode 62 = v
++ shiftr keycode 62 = +V
++ shift shiftr keycode 62 = +v
++keycode 63 = b
++ shiftr keycode 63 = +B
++ shift shiftr keycode 63 = +b
++ altgr keycode 63 = Hex_B
++
++keycode 67 = three numbersign
++ shiftr keycode 67 = numbersign
++ shift shiftr keycode 67 = numbersign
++ control keycode 67 = Escape
++ alt keycode 67 = Meta_three
++keycode 68 = e
++ shiftr keycode 68 = +E
++ shift shiftr keycode 68 = +e
++ altgr keycode 68 = Hex_E
++keycode 69 = d
++ shiftr keycode 69 = +D
++ shift shiftr keycode 69 = +d
++ altgr keycode 69 = Hex_D
++keycode 70 = c
++ shiftr keycode 70 = +C
++ shift shiftr keycode 70 = +c
++ altgr keycode 70 = Hex_C
++keycode 71 = Right Incr_Console
++ shiftr keycode 71 = Incr_Console
++ shift shiftr keycode 71 = Incr_Console
++ alt keycode 71 = End
++
++keycode 75 = two at at
++ shiftr keycode 75 = at
++ shift shiftr keycode 75 = at
++ control keycode 75 = nul
++ shift control keycode 75 = nul
++ shiftr control keycode 75 = nul
++ shift shiftr control keycode 75 = nul
++ alt keycode 75 = Meta_two
++keycode 76 = w
++ shiftr keycode 76 = +W
++ shift shiftr keycode 76 = +w
++keycode 77 = s
++ shiftr keycode 77 = +S
++ shift shiftr keycode 77 = +s
++keycode 78 = x
++ shiftr keycode 78 = +X
++ shift shiftr keycode 78 = +x
++keycode 79 = Down Scroll_Forward
++ shiftr keycode 79 = Scroll_Forward
++ shift shiftr keycode 79 = Scroll_Forward
++ alt keycode 79 = Next
++keycode 80 = Escape Escape
++ shiftr keycode 80 = Escape
++ shift shiftr keycode 80 = Escape
++ alt keycode 80 = Meta_Escape
++keycode 81 = Tab Tab
++ shiftr keycode 81 = Tab
++ shift shiftr keycode 81 = Tab
++ alt keycode 81 = Meta_Tab
++keycode 82 = grave asciitilde
++ shiftr keycode 82 = asciitilde
++ shift shiftr keycode 82 = asciitilde
++ control keycode 82 = nul
++ alt keycode 82 = Meta_grave
++keycode 83 = one exclam
++ shiftr keycode 83 = exclam
++ shift shiftr keycode 83 = exclam
++ alt keycode 83 = Meta_one
++keycode 84 = q
++ shiftr keycode 84 = +Q
++ shift shiftr keycode 84 = +q
++keycode 85 = a
++ shiftr keycode 85 = +A
++ shift shiftr keycode 85 = +a
++ altgr keycode 85 = Hex_A
++keycode 86 = z
++ shiftr keycode 86 = +Z
++ shift shiftr keycode 86 = +z
++
++# This is the windows key:
++keycode 88 = Decr_Console
++keycode 89 = Shift
++keycode 90 = Control
++keycode 91 = Control
++keycode 92 = Alt
++keycode 93 = AltGr
++keycode 94 = ShiftR
++ shift keycode 94 = Caps_Lock
+diff -Nur linux-2.4.32-rc1/drivers/char/indydog.c linux-2.4.32-rc1.mips/drivers/char/indydog.c
+--- linux-2.4.32-rc1/drivers/char/indydog.c 2003-08-25 13:44:41.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/char/indydog.c 2004-06-22 17:32:07.000000000 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * IndyDog 0.2 A Hardware Watchdog Device for SGI IP22
++ * IndyDog 0.3 A Hardware Watchdog Device for SGI IP22
+ *
+ * (c) Copyright 2002 Guido Guenther <agx@sigxcpu.org>, All Rights Reserved.
+ *
+@@ -7,10 +7,10 @@
+ * 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.
+- *
++ *
+ * based on softdog.c by Alan Cox <alan@redhat.com>
+ */
+-
++
+ #include <linux/module.h>
+ #include <linux/config.h>
+ #include <linux/types.h>
+@@ -19,13 +19,12 @@
+ #include <linux/mm.h>
+ #include <linux/miscdevice.h>
+ #include <linux/watchdog.h>
+-#include <linux/smp_lock.h>
+ #include <linux/init.h>
+ #include <asm/uaccess.h>
+ #include <asm/sgi/mc.h>
+
+-static unsigned long indydog_alive;
+-static int expect_close = 0;
++#define PFX "indydog: "
++static int indydog_alive;
+
+ #ifdef CONFIG_WATCHDOG_NOWAYOUT
+ static int nowayout = 1;
+@@ -33,10 +32,30 @@
+ static int nowayout = 0;
+ #endif
+
++#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */
++
+ MODULE_PARM(nowayout,"i");
+ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+-static inline void indydog_ping(void)
++static void indydog_start(void)
++{
++ u32 mc_ctrl0 = sgimc->cpuctrl0;
++
++ mc_ctrl0 = sgimc->cpuctrl0 | SGIMC_CCTRL0_WDOG;
++ sgimc->cpuctrl0 = mc_ctrl0;
++}
++
++static void indydog_stop(void)
++{
++ u32 mc_ctrl0 = sgimc->cpuctrl0;
++
++ mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG;
++ sgimc->cpuctrl0 = mc_ctrl0;
++
++ printk(KERN_INFO PFX "Stopped watchdog timer.\n");
++}
++
++static void indydog_ping(void)
+ {
+ sgimc->watchdogt = 0;
+ }
+@@ -46,18 +65,14 @@
+ */
+ static int indydog_open(struct inode *inode, struct file *file)
+ {
+- u32 mc_ctrl0;
+-
+- if (test_and_set_bit(0,&indydog_alive))
++ if (indydog_alive)
+ return -EBUSY;
+
+- if (nowayout) {
++ if (nowayout)
+ MOD_INC_USE_COUNT;
+- }
+
+ /* Activate timer */
+- mc_ctrl0 = sgimc->cpuctrl0 | SGIMC_CCTRL0_WDOG;
+- sgimc->cpuctrl0 = mc_ctrl0;
++ indydog_start();
+ indydog_ping();
+
+ indydog_alive = 1;
+@@ -69,63 +84,48 @@
+ static int indydog_release(struct inode *inode, struct file *file)
+ {
+ /* Shut off the timer.
+- * Lock it in if it's a module and we set nowayout. */
+- lock_kernel();
+- if (expect_close) {
+- u32 mc_ctrl0 = sgimc->cpuctrl0;
++ * Lock it in if it's a module and we defined ...NOWAYOUT */
++ if (!nowayout) {
++ u32 mc_ctrl0 = sgimc->cpuctrl0;
+ mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG;
+ sgimc->cpuctrl0 = mc_ctrl0;
+ printk(KERN_INFO "Stopped watchdog timer.\n");
+- } else
+- printk(KERN_CRIT "WDT device closed unexpectedly. WDT will not stop!\n");
+- clear_bit(0, &indydog_alive);
+- unlock_kernel();
++ }
++ indydog_alive = 0;
+
+ return 0;
+ }
+
+ static ssize_t indydog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+ {
+- /* Can't seek (pwrite) on this device */
++ /* Can't seek (pwrite) on this device */
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+
+- /*
+- * Refresh the timer.
+- */
++ /* Refresh the timer. */
+ if (len) {
+- if (!nowayout) {
+- size_t i;
+-
+- /* In case it was set long ago */
+- expect_close = 0;
+-
+- for (i = 0; i != len; i++) {
+- char c;
+- if (get_user(c, data + i))
+- return -EFAULT;
+- if (c == 'V')
+- expect_close = 1;
+- }
+- }
+ indydog_ping();
+- return 1;
+ }
+- return 0;
++ return len;
+ }
+
+ static int indydog_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
++ int options, retval = -EINVAL;
+ static struct watchdog_info ident = {
+- options: WDIOF_MAGICCLOSE,
+- identity: "Hardware Watchdog for SGI IP22",
++ .options = WDIOF_KEEPALIVEPING |
++ WDIOF_MAGICCLOSE,
++ .firmware_version = 0,
++ .identity = "Hardware Watchdog for SGI IP22",
+ };
++
+ switch (cmd) {
+ default:
+ return -ENOIOCTLCMD;
+ case WDIOC_GETSUPPORT:
+- if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
++ if (copy_to_user((struct watchdog_info *)arg,
++ &ident, sizeof(ident)))
+ return -EFAULT;
+ return 0;
+ case WDIOC_GETSTATUS:
+@@ -134,31 +134,53 @@
+ case WDIOC_KEEPALIVE:
+ indydog_ping();
+ return 0;
++ case WDIOC_GETTIMEOUT:
++ return put_user(WATCHDOG_TIMEOUT,(int *)arg);
++ case WDIOC_SETOPTIONS:
++ {
++ if (get_user(options, (int *)arg))
++ return -EFAULT;
++
++ if (options & WDIOS_DISABLECARD) {
++ indydog_stop();
++ retval = 0;
++ }
++
++ if (options & WDIOS_ENABLECARD) {
++ indydog_start();
++ retval = 0;
++ }
++
++ return retval;
++ }
+ }
+ }
+
+ static struct file_operations indydog_fops = {
+- owner: THIS_MODULE,
+- write: indydog_write,
+- ioctl: indydog_ioctl,
+- open: indydog_open,
+- release: indydog_release,
++ .owner = THIS_MODULE,
++ .write = indydog_write,
++ .ioctl = indydog_ioctl,
++ .open = indydog_open,
++ .release = indydog_release,
+ };
+
+ static struct miscdevice indydog_miscdev = {
+- minor: WATCHDOG_MINOR,
+- name: "watchdog",
+- fops: &indydog_fops,
++ .minor = WATCHDOG_MINOR,
++ .name = "watchdog",
++ .fops = &indydog_fops,
+ };
+
+-static const char banner[] __initdata = KERN_INFO "Hardware Watchdog Timer for SGI IP22: 0.2\n";
++static char banner[] __initdata =
++ KERN_INFO PFX "Hardware Watchdog Timer for SGI IP22: 0.3\n";
+
+ static int __init watchdog_init(void)
+ {
+ int ret = misc_register(&indydog_miscdev);
+-
+- if (ret)
++ if (ret) {
++ printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
++ WATCHDOG_MINOR, ret);
+ return ret;
++ }
+
+ printk(banner);
+
+@@ -172,4 +194,7 @@
+
+ module_init(watchdog_init);
+ module_exit(watchdog_exit);
++
++MODULE_AUTHOR("Guido Guenther <agx@sigxcpu.org>");
++MODULE_DESCRIPTION("Hardware Watchdog Device for SGI IP22");
+ MODULE_LICENSE("GPL");
+diff -Nur linux-2.4.32-rc1/drivers/char/ip27-rtc.c linux-2.4.32-rc1.mips/drivers/char/ip27-rtc.c
+--- linux-2.4.32-rc1/drivers/char/ip27-rtc.c 2004-02-18 14:36:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/char/ip27-rtc.c 2004-04-06 03:35:30.000000000 +0200
+@@ -44,6 +44,7 @@
+ #include <asm/sn/klconfig.h>
+ #include <asm/sn/sn0/ip27.h>
+ #include <asm/sn/sn0/hub.h>
++#include <asm/sn/sn_private.h>
+
+ static int rtc_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg);
+@@ -209,11 +210,8 @@
+
+ static int __init rtc_init(void)
+ {
+- nasid_t nid;
+-
+- nid = get_nasid();
+ rtc = (struct m48t35_rtc *)
+- (KL_CONFIG_CH_CONS_INFO(nid)->memory_base + IOC3_BYTEBUS_DEV0);
++ (KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base + IOC3_BYTEBUS_DEV0);
+
+ printk(KERN_INFO "Real Time Clock Driver v%s\n", RTC_VERSION);
+ if (misc_register(&rtc_dev)) {
+@@ -325,3 +323,7 @@
+
+ rtc_tm->tm_mon--;
+ }
++
++MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
++MODULE_DESCRIPTION("SGI IP27 M48T35 RTC driver");
++MODULE_LICENSE("GPL");
+diff -Nur linux-2.4.32-rc1/drivers/char/Makefile linux-2.4.32-rc1.mips/drivers/char/Makefile
+--- linux-2.4.32-rc1/drivers/char/Makefile 2004-08-08 01:26:04.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/char/Makefile 2005-02-11 22:09:56.000000000 +0100
+@@ -48,7 +48,12 @@
+ KEYBD =
+ endif
+ ifeq ($(CONFIG_VR41XX_KIU),y)
+- KEYMAP =
++ ifeq ($(CONFIG_IBM_WORKPAD),y)
++ KEYMAP = ibm_workpad_keymap.o
++ endif
++ ifeq ($(CONFIG_VICTOR_MPC30X),y)
++ KEYMAP = victor_mpc30x_keymap.o
++ endif
+ KEYBD = vr41xx_keyb.o
+ endif
+ endif
+@@ -251,7 +256,6 @@
+ obj-$(CONFIG_RTC) += rtc.o
+ obj-$(CONFIG_GEN_RTC) += genrtc.o
+ obj-$(CONFIG_EFI_RTC) += efirtc.o
+-obj-$(CONFIG_SGI_DS1286) += ds1286.o
+ obj-$(CONFIG_MIPS_RTC) += mips_rtc.o
+ obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
+ ifeq ($(CONFIG_PPC),)
+@@ -259,6 +263,7 @@
+ endif
+ obj-$(CONFIG_TOSHIBA) += toshiba.o
+ obj-$(CONFIG_I8K) += i8k.o
++obj-$(CONFIG_DS1286) += ds1286.o
+ obj-$(CONFIG_DS1620) += ds1620.o
+ obj-$(CONFIG_DS1742) += ds1742.o
+ obj-$(CONFIG_INTEL_RNG) += i810_rng.o
+@@ -269,6 +274,7 @@
+
+ obj-$(CONFIG_ITE_GPIO) += ite_gpio.o
+ obj-$(CONFIG_AU1X00_GPIO) += au1000_gpio.o
++obj-$(CONFIG_AU1550_PSC_SPI) += au1550_psc_spi.o
+ obj-$(CONFIG_AU1X00_USB_TTY) += au1000_usbtty.o
+ obj-$(CONFIG_AU1X00_USB_RAW) += au1000_usbraw.o
+ obj-$(CONFIG_COBALT_LCD) += lcd.o
+@@ -353,3 +359,9 @@
+
+ qtronixmap.c: qtronixmap.map
+ set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@
++
++ibm_workpad_keymap.c: ibm_workpad_keymap.map
++ set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@
++
++victor_mpc30x_keymap.c: victor_mpc30x_keymap.map
++ set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@
+diff -Nur linux-2.4.32-rc1/drivers/char/mips_rtc.c linux-2.4.32-rc1.mips/drivers/char/mips_rtc.c
+--- linux-2.4.32-rc1/drivers/char/mips_rtc.c 2004-01-05 14:53:56.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/char/mips_rtc.c 2004-06-28 14:54:53.000000000 +0200
+@@ -53,14 +53,6 @@
+ #include <asm/io.h>
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+-
+-/*
+- * Check machine
+- */
+-#if !defined(CONFIG_MIPS) || !defined(CONFIG_NEW_TIME_C)
+-#error "This driver is for MIPS machines with CONFIG_NEW_TIME_C defined"
+-#endif
+-
+ #include <asm/time.h>
+
+ static unsigned long rtc_status = 0; /* bitmapped status byte. */
+diff -Nur linux-2.4.32-rc1/drivers/char/sb1250_duart.c linux-2.4.32-rc1.mips/drivers/char/sb1250_duart.c
+--- linux-2.4.32-rc1/drivers/char/sb1250_duart.c 2004-02-18 14:36:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/char/sb1250_duart.c 2004-09-17 01:25:44.000000000 +0200
+@@ -328,10 +328,11 @@
+ if (c <= 0) break;
+
+ if (from_user) {
++ spin_unlock_irqrestore(&us->outp_lock, flags);
+ if (copy_from_user(us->outp_buf + us->outp_tail, buf, c)) {
+- spin_unlock_irqrestore(&us->outp_lock, flags);
+ return -EFAULT;
+ }
++ spin_lock_irqsave(&us->outp_lock, flags);
+ } else {
+ memcpy(us->outp_buf + us->outp_tail, buf, c);
+ }
+@@ -498,9 +499,31 @@
+ duart_set_cflag(us->line, tty->termios->c_cflag);
+ }
+
++static int get_serial_info(uart_state_t *us, struct serial_struct * retinfo) {
++
++ struct serial_struct tmp;
++
++ memset(&tmp, 0, sizeof(tmp));
++
++ tmp.type=PORT_SB1250;
++ tmp.line=us->line;
++ tmp.port=A_DUART_CHANREG(tmp.line,0);
++ tmp.irq=K_INT_UART_0 + tmp.line;
++ tmp.xmit_fifo_size=16; /* fixed by hw */
++ tmp.baud_base=5000000;
++ tmp.io_type=SERIAL_IO_MEM;
++
++ if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
++ return -EFAULT;
++
++ return 0;
++}
++
+ static int duart_ioctl(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned long arg)
+ {
++ uart_state_t *us = (uart_state_t *) tty->driver_data;
++
+ /* if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
+ return -ENODEV;*/
+ switch (cmd) {
+@@ -517,7 +540,7 @@
+ printk("Ignoring TIOCMSET\n");
+ break;
+ case TIOCGSERIAL:
+- printk("Ignoring TIOCGSERIAL\n");
++ return get_serial_info(us,(struct serial_struct *) arg);
+ break;
+ case TIOCSSERIAL:
+ printk("Ignoring TIOCSSERIAL\n");
+diff -Nur linux-2.4.32-rc1/drivers/char/serial.c linux-2.4.32-rc1.mips/drivers/char/serial.c
+--- linux-2.4.32-rc1/drivers/char/serial.c 2005-10-24 11:33:29.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/char/serial.c 2005-09-23 22:41:22.000000000 +0200
+@@ -62,6 +62,12 @@
+ * Robert Schwebel <robert@schwebel.de>,
+ * Juergen Beisert <jbeisert@eurodsn.de>,
+ * Theodore Ts'o <tytso@mit.edu>
++ *
++ * 10/00: Added suport for MIPS Atlas board.
++ * 11/00: Hooks for serial kernel debug port support added.
++ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard,
++ * carstenl@mips.com
++ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ */
+
+ static char *serial_version = "5.05c";
+@@ -413,6 +419,22 @@
+ return 0;
+ }
+
++#if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_SEAD)
++
++#include <asm/mips-boards/atlas.h>
++
++static _INLINE_ unsigned int serial_in(struct async_struct *info, int offset)
++{
++ return (*(volatile unsigned int *)(mips_io_port_base + ATLAS_UART_REGS_BASE + offset*8) & 0xff);
++}
++
++static _INLINE_ void serial_out(struct async_struct *info, int offset, int value)
++{
++ *(volatile unsigned int *)(mips_io_port_base + ATLAS_UART_REGS_BASE + offset*8) = value;
++}
++
++#else
++
+ static _INLINE_ unsigned int serial_in(struct async_struct *info, int offset)
+ {
+ switch (info->io_type) {
+@@ -447,6 +469,8 @@
+ outb(value, info->port+offset);
+ }
+ }
++#endif
++
+
+ /*
+ * We used to support using pause I/O for certain machines. We
+diff -Nur linux-2.4.32-rc1/drivers/char/victor_mpc30x_keymap.map linux-2.4.32-rc1.mips/drivers/char/victor_mpc30x_keymap.map
+--- linux-2.4.32-rc1/drivers/char/victor_mpc30x_keymap.map 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/char/victor_mpc30x_keymap.map 2004-02-05 18:04:42.000000000 +0100
+@@ -0,0 +1,102 @@
++# Victor Interlink MP-C303/304 keyboard keymap
++#
++# Copyright (C) 2003 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
++#
++# 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.
++keymaps 0-1,4-5,8-9,12
++alt_is_meta
++strings as usual
++compose as usual for "iso-8859-1"
++
++# First line
++keycode 89 = Escape
++keycode 9 = Delete
++
++# 2nd line
++keycode 73 = one exclam
++keycode 18 = two quotedbl
++keycode 92 = three numbersign
++ control keycode 92 = Escape
++keycode 53 = four dollar
++ control keycode 53 = Control_backslash
++keycode 21 = five percent
++ control keycode 21 = Control_bracketright
++keycode 50 = six ampersand
++ control keycode 50 = Control_underscore
++keycode 48 = seven apostrophe
++keycode 51 = eight parenleft
++keycode 16 = nine parenright
++keycode 80 = zero asciitilde
++ control keycode 80 = nul
++keycode 49 = minus equal
++keycode 30 = asciicircum asciitilde
++ control keycode 30 = Control_asciicircum
++keycode 5 = backslash bar
++ control keycode 5 = Control_backslash
++keycode 13 = BackSpace
++# 3rd line
++keycode 57 = Tab
++keycode 74 = q
++keycode 26 = w
++keycode 81 = e
++keycode 29 = r
++keycode 37 = t
++keycode 45 = y
++keycode 72 = u
++keycode 24 = i
++keycode 32 = o
++keycode 41 = p
++keycode 1 = at grave
++ control keycode 1 = nul
++keycode 54 = bracketleft braceleft
++keycode 63 = Return
++ alt keycode 63 = Meta_Control_m
++# 4th line
++keycode 23 = Caps_Lock
++keycode 34 = a
++keycode 66 = s
++keycode 52 = d
++keycode 20 = f
++keycode 84 = g
++keycode 67 = h
++keycode 64 = j
++keycode 17 = k
++keycode 83 = l
++keycode 22 = semicolon plus
++keycode 61 = colon asterisk
++ control keycode 61 = Control_g
++keycode 65 = bracketright braceright
++ control keycode 65 = Control_bracketright
++# 5th line
++keycode 91 = Shift
++keycode 76 = z
++keycode 68 = x
++keycode 28 = c
++keycode 36 = v
++keycode 44 = b
++keycode 19 = n
++keycode 27 = m
++keycode 35 = comma less
++keycode 3 = period greater
++ control keycode 3 = Compose
++keycode 38 = slash question
++ control keycode 38 = Delete
++ shift control keycode 38 = Delete
++keycode 6 = backslash underscore
++ control keycode 6 = Control_backslash
++keycode 55 = Up
++ alt keycode 55 = PageUp
++keycode 14 = Shift
++# 6th line
++keycode 56 = Control
++keycode 42 = Alt
++keycode 33 = space
++ control keycode 33 = nul
++keycode 7 = Left
++ alt keycode 7 = Home
++keycode 31 = Down
++ alt keycode 31 = PageDown
++keycode 47 = Right
++ alt keycode 47 = End
+diff -Nur linux-2.4.32-rc1/drivers/char/vr41xx_keyb.c linux-2.4.32-rc1.mips/drivers/char/vr41xx_keyb.c
+--- linux-2.4.32-rc1/drivers/char/vr41xx_keyb.c 2004-02-18 14:36:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/char/vr41xx_keyb.c 2004-02-17 13:08:55.000000000 +0100
+@@ -308,7 +308,7 @@
+ if (found != 0) {
+ kiu_base = VRC4173_KIU_OFFSET;
+ mkiuintreg = VRC4173_MKIUINTREG_OFFSET;
+- vrc4173_clock_supply(VRC4173_KIU_CLOCK);
++ vrc4173_supply_clock(VRC4173_KIU_CLOCK);
+ }
+ }
+ #endif
+@@ -325,7 +325,7 @@
+
+ if (current_cpu_data.cputype == CPU_VR4111 ||
+ current_cpu_data.cputype == CPU_VR4121)
+- vr41xx_clock_supply(KIU_CLOCK);
++ vr41xx_supply_clock(KIU_CLOCK);
+
+ kiu_writew(KIURST_KIURST, KIURST);
+
+diff -Nur linux-2.4.32-rc1/drivers/i2c/Config.in linux-2.4.32-rc1.mips/drivers/i2c/Config.in
+--- linux-2.4.32-rc1/drivers/i2c/Config.in 2004-04-14 15:05:29.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/i2c/Config.in 2005-02-11 20:49:04.000000000 +0100
+@@ -57,6 +57,10 @@
+ if [ "$CONFIG_SGI_IP22" = "y" ]; then
+ dep_tristate 'I2C SGI interfaces' CONFIG_I2C_ALGO_SGI $CONFIG_I2C
+ fi
++
++ if [ "$CONFIG_SOC_AU1550" = "y" -o "$CONFIG_SOC_AU1200" ]; then
++ dep_tristate 'Au1550/Au1200 SMBus interface' CONFIG_I2C_ALGO_AU1550 $CONFIG_I2C
++ fi
+
+ # This is needed for automatic patch generation: sensors code starts here
+ # This is needed for automatic patch generation: sensors code ends here
+diff -Nur linux-2.4.32-rc1/drivers/i2c/i2c-algo-au1550.c linux-2.4.32-rc1.mips/drivers/i2c/i2c-algo-au1550.c
+--- linux-2.4.32-rc1/drivers/i2c/i2c-algo-au1550.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/i2c/i2c-algo-au1550.c 2005-02-11 20:49:04.000000000 +0100
+@@ -0,0 +1,340 @@
++/*
++ * i2c-algo-au1550.c: SMBus (i2c) driver algorithms for Alchemy PSC interface
++ * Copyright (C) 2004 Embedded Edge, LLC <dan@embeddededge.com>
++ *
++ * The documentation describes this as an SMBus controller, but it doesn't
++ * understand any of the SMBus protocol in hardware. It's really an I2C
++ * controller that could emulate most of the SMBus in software.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/errno.h>
++#include <linux/delay.h>
++
++#include <asm/au1000.h>
++#include <asm/au1xxx_psc.h>
++
++#include <linux/i2c.h>
++#include <linux/i2c-algo-au1550.h>
++
++static int
++wait_xfer_done(struct i2c_algo_au1550_data *adap)
++{
++ u32 stat;
++ int i;
++ volatile psc_smb_t *sp;
++
++ sp = (volatile psc_smb_t *)(adap->psc_base);
++
++ /* Wait for Tx FIFO Underflow.
++ */
++ for (i = 0; i < adap->xfer_timeout; i++) {
++ stat = sp->psc_smbevnt;
++ au_sync();
++ if ((stat & PSC_SMBEVNT_TU) != 0) {
++ /* Clear it. */
++ sp->psc_smbevnt = PSC_SMBEVNT_TU;
++ au_sync();
++ return 0;
++ }
++ udelay(1);
++ }
++
++ return -ETIMEDOUT;
++}
++
++static int
++wait_ack(struct i2c_algo_au1550_data *adap)
++{
++ u32 stat;
++ volatile psc_smb_t *sp;
++
++ if (wait_xfer_done(adap))
++ return -ETIMEDOUT;
++
++ sp = (volatile psc_smb_t *)(adap->psc_base);
++
++ stat = sp->psc_smbevnt;
++ au_sync();
++
++ if ((stat & (PSC_SMBEVNT_DN | PSC_SMBEVNT_AN | PSC_SMBEVNT_AL)) != 0)
++ return -ETIMEDOUT;
++
++ return 0;
++}
++
++static int
++wait_master_done(struct i2c_algo_au1550_data *adap)
++{
++ u32 stat;
++ int i;
++ volatile psc_smb_t *sp;
++
++ sp = (volatile psc_smb_t *)(adap->psc_base);
++
++ /* Wait for Master Done.
++ */
++ for (i = 0; i < adap->xfer_timeout; i++) {
++ stat = sp->psc_smbevnt;
++ au_sync();
++ if ((stat & PSC_SMBEVNT_MD) != 0)
++ return 0;
++ udelay(1);
++ }
++
++ return -ETIMEDOUT;
++}
++
++static int
++do_address(struct i2c_algo_au1550_data *adap, unsigned int addr, int rd)
++{
++ volatile psc_smb_t *sp;
++ u32 stat;
++
++ sp = (volatile psc_smb_t *)(adap->psc_base);
++
++ /* Reset the FIFOs, clear events.
++ */
++ sp->psc_smbpcr = PSC_SMBPCR_DC;
++ sp->psc_smbevnt = PSC_SMBEVNT_ALLCLR;
++ au_sync();
++ do {
++ stat = sp->psc_smbpcr;
++ au_sync();
++ } while ((stat & PSC_SMBPCR_DC) != 0);
++
++ /* Write out the i2c chip address and specify operation
++ */
++ addr <<= 1;
++ if (rd)
++ addr |= 1;
++
++ /* Put byte into fifo, start up master.
++ */
++ sp->psc_smbtxrx = addr;
++ au_sync();
++ sp->psc_smbpcr = PSC_SMBPCR_MS;
++ au_sync();
++ if (wait_ack(adap))
++ return -EIO;
++ return 0;
++}
++
++static u32
++wait_for_rx_byte(struct i2c_algo_au1550_data *adap, u32 *ret_data)
++{
++ int j;
++ u32 data, stat;
++ volatile psc_smb_t *sp;
++
++ if (wait_xfer_done(adap))
++ return -EIO;
++
++ sp = (volatile psc_smb_t *)(adap->psc_base);
++
++ j = adap->xfer_timeout * 100;
++ do {
++ j--;
++ if (j <= 0)
++ return -EIO;
++
++ stat = sp->psc_smbstat;
++ au_sync();
++ if ((stat & PSC_SMBSTAT_RE) == 0)
++ j = 0;
++ else
++ udelay(1);
++ } while (j > 0);
++ data = sp->psc_smbtxrx;
++ au_sync();
++ *ret_data = data;
++
++ return 0;
++}
++
++static int
++i2c_read(struct i2c_algo_au1550_data *adap, unsigned char *buf,
++ unsigned int len)
++{
++ int i;
++ u32 data;
++ volatile psc_smb_t *sp;
++
++ if (len == 0)
++ return 0;
++
++ /* A read is performed by stuffing the transmit fifo with
++ * zero bytes for timing, waiting for bytes to appear in the
++ * receive fifo, then reading the bytes.
++ */
++
++ sp = (volatile psc_smb_t *)(adap->psc_base);
++
++ i = 0;
++ while (i < (len-1)) {
++ sp->psc_smbtxrx = 0;
++ au_sync();
++ if (wait_for_rx_byte(adap, &data))
++ return -EIO;
++
++ buf[i] = data;
++ i++;
++ }
++
++ /* The last byte has to indicate transfer done.
++ */
++ sp->psc_smbtxrx = PSC_SMBTXRX_STP;
++ au_sync();
++ if (wait_master_done(adap))
++ return -EIO;
++
++ data = sp->psc_smbtxrx;
++ au_sync();
++ buf[i] = data;
++ return 0;
++}
++
++static int
++i2c_write(struct i2c_algo_au1550_data *adap, unsigned char *buf,
++ unsigned int len)
++{
++ int i;
++ u32 data;
++ volatile psc_smb_t *sp;
++
++ if (len == 0)
++ return 0;
++
++ sp = (volatile psc_smb_t *)(adap->psc_base);
++
++ i = 0;
++ while (i < (len-1)) {
++ data = buf[i];
++ sp->psc_smbtxrx = data;
++ au_sync();
++ if (wait_ack(adap))
++ return -EIO;
++ i++;
++ }
++
++ /* The last byte has to indicate transfer done.
++ */
++ data = buf[i];
++ data |= PSC_SMBTXRX_STP;
++ sp->psc_smbtxrx = data;
++ au_sync();
++ if (wait_master_done(adap))
++ return -EIO;
++ return 0;
++}
++
++static int
++au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
++{
++ struct i2c_algo_au1550_data *adap = i2c_adap->algo_data;
++ struct i2c_msg *p;
++ int i, err = 0;
++
++ for (i = 0; !err && i < num; i++) {
++ p = &msgs[i];
++ err = do_address(adap, p->addr, p->flags & I2C_M_RD);
++ if (err || !p->len)
++ continue;
++ if (p->flags & I2C_M_RD)
++ err = i2c_read(adap, p->buf, p->len);
++ else
++ err = i2c_write(adap, p->buf, p->len);
++ }
++
++ /* Return the number of messages processed, or the error code.
++ */
++ if (err == 0)
++ err = num;
++ return err;
++}
++
++static u32
++au1550_func(struct i2c_adapter *adap)
++{
++ return I2C_FUNC_I2C;
++}
++
++static struct i2c_algorithm au1550_algo = {
++ .name = "Au1550 algorithm",
++ .id = I2C_ALGO_AU1550,
++ .master_xfer = au1550_xfer,
++ .functionality = au1550_func,
++};
++
++/*
++ * registering functions to load algorithms at runtime
++ * Prior to calling us, the 50MHz clock frequency and routing
++ * must have been set up for the PSC indicated by the adapter.
++ */
++int
++i2c_au1550_add_bus(struct i2c_adapter *i2c_adap)
++{
++ struct i2c_algo_au1550_data *adap = i2c_adap->algo_data;
++ volatile psc_smb_t *sp;
++ u32 stat;
++
++ i2c_adap->algo = &au1550_algo;
++
++ /* Now, set up the PSC for SMBus PIO mode.
++ */
++ sp = (volatile psc_smb_t *)(adap->psc_base);
++ sp->psc_ctrl = PSC_CTRL_DISABLE;
++ au_sync();
++ sp->psc_sel = PSC_SEL_PS_SMBUSMODE;
++ sp->psc_smbcfg = 0;
++ au_sync();
++ sp->psc_ctrl = PSC_CTRL_ENABLE;
++ au_sync();
++ do {
++ stat = sp->psc_smbstat;
++ au_sync();
++ } while ((stat & PSC_SMBSTAT_SR) == 0);
++
++ sp->psc_smbcfg = (PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 |
++ PSC_SMBCFG_DD_DISABLE);
++
++ /* Divide by 8 to get a 6.25 MHz clock. The later protocol
++ * timings are based on this clock.
++ */
++ sp->psc_smbcfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV2);
++ sp->psc_smbmsk = PSC_SMBMSK_ALLMASK;
++ au_sync();
++
++ /* Set the protocol timer values. See Table 71 in the
++ * Au1550 Data Book for standard timing values.
++ */
++ sp->psc_smbtmr = PSC_SMBTMR_SET_TH(2) | PSC_SMBTMR_SET_PS(15) | \
++ PSC_SMBTMR_SET_PU(11) | PSC_SMBTMR_SET_SH(11) | \
++ PSC_SMBTMR_SET_SU(11) | PSC_SMBTMR_SET_CL(15) | \
++ PSC_SMBTMR_SET_CH(11);
++ au_sync();
++
++ sp->psc_smbcfg |= PSC_SMBCFG_DE_ENABLE;
++ do {
++ stat = sp->psc_smbstat;
++ au_sync();
++ } while ((stat & PSC_SMBSTAT_DR) == 0);
++
++ return i2c_add_adapter(i2c_adap);
++}
++
++
++int
++i2c_au1550_del_bus(struct i2c_adapter *adap)
++{
++ return i2c_del_adapter(adap);
++}
++
++EXPORT_SYMBOL(i2c_au1550_add_bus);
++EXPORT_SYMBOL(i2c_au1550_del_bus);
++
++MODULE_AUTHOR("Dan Malek <dan@embeddededge.com>");
++MODULE_DESCRIPTION("SMBus Au1550 algorithm");
++MODULE_LICENSE("GPL");
+diff -Nur linux-2.4.32-rc1/drivers/i2c/i2c-au1550.c linux-2.4.32-rc1.mips/drivers/i2c/i2c-au1550.c
+--- linux-2.4.32-rc1/drivers/i2c/i2c-au1550.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/i2c/i2c-au1550.c 2005-02-11 20:49:04.000000000 +0100
+@@ -0,0 +1,154 @@
++/*
++ * i2c-au1550.c: SMBus (i2c) adapter for Alchemy PSC interface
++ * Copyright (C) 2004 Embedded Edge, LLC <dan@embeddededge.com>
++ *
++ * This is just a skeleton adapter to use with the Au1550 PSC
++ * algorithm. It was developed for the Pb1550, but will work with
++ * any Au1550 board that has a similar PSC configuration.
++ *
++ * 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/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/errno.h>
++
++#include <asm/au1000.h>
++#include <asm/au1xxx_psc.h>
++#if defined( CONFIG_MIPS_PB1550 )
++ #include <asm/pb1550.h>
++#endif
++#if defined( CONFIG_MIPS_PB1200 )
++ #include <asm/pb1200.h>
++#endif
++#if defined( CONFIG_MIPS_DB1200 )
++ #include <asm/db1200.h>
++#endif
++#if defined( CONFIG_MIPS_FICMMP )
++ #include <asm/ficmmp.h>
++#endif
++
++#include <linux/i2c.h>
++#include <linux/i2c-algo-au1550.h>
++
++
++
++static int
++pb1550_reg(struct i2c_client *client)
++{
++ return 0;
++}
++
++static int
++pb1550_unreg(struct i2c_client *client)
++{
++ return 0;
++}
++
++static void
++pb1550_inc_use(struct i2c_adapter *adap)
++{
++#ifdef MODULE
++ MOD_INC_USE_COUNT;
++#endif
++}
++
++static void
++pb1550_dec_use(struct i2c_adapter *adap)
++{
++#ifdef MODULE
++ MOD_DEC_USE_COUNT;
++#endif
++}
++
++static struct i2c_algo_au1550_data pb1550_i2c_info = {
++ SMBUS_PSC_BASE, 200, 200
++};
++
++static struct i2c_adapter pb1550_board_adapter = {
++ name: "pb1550 adapter",
++ id: I2C_HW_AU1550_PSC,
++ algo: NULL,
++ algo_data: &pb1550_i2c_info,
++ inc_use: pb1550_inc_use,
++ dec_use: pb1550_dec_use,
++ client_register: pb1550_reg,
++ client_unregister: pb1550_unreg,
++ client_count: 0,
++};
++
++int __init
++i2c_pb1550_init(void)
++{
++ /* This is where we would set up a 50MHz clock source
++ * and routing. On the Pb1550, the SMBus is PSC2, which
++ * uses a shared clock with USB. This has been already
++ * configured by Yamon as a 48MHz clock, close enough
++ * for our work.
++ */
++ if (i2c_au1550_add_bus(&pb1550_board_adapter) < 0)
++ return -ENODEV;
++
++ return 0;
++}
++
++/* BIG hack to support the control interface on the Wolfson WM8731
++ * audio codec on the Pb1550 board. We get an address and two data
++ * bytes to write, create an i2c message, and send it across the
++ * i2c transfer function. We do this here because we have access to
++ * the i2c adapter structure.
++ */
++static struct i2c_msg wm_i2c_msg; /* We don't want this stuff on the stack */
++static u8 i2cbuf[2];
++
++int
++pb1550_wm_codec_write(u8 addr, u8 reg, u8 val)
++{
++ wm_i2c_msg.addr = addr;
++ wm_i2c_msg.flags = 0;
++ wm_i2c_msg.buf = i2cbuf;
++ wm_i2c_msg.len = 2;
++ i2cbuf[0] = reg;
++ i2cbuf[1] = val;
++
++ return pb1550_board_adapter.algo->master_xfer(&pb1550_board_adapter, &wm_i2c_msg, 1);
++}
++
++/* the next function is needed by DVB driver. */
++int pb1550_i2c_xfer(struct i2c_msg msgs[], int num)
++{
++ return pb1550_board_adapter.algo->master_xfer(&pb1550_board_adapter, msgs, num);
++}
++
++EXPORT_SYMBOL(pb1550_wm_codec_write);
++EXPORT_SYMBOL(pb1550_i2c_xfer);
++
++MODULE_AUTHOR("Dan Malek, Embedded Edge, LLC.");
++MODULE_DESCRIPTION("SMBus adapter Alchemy pb1550");
++MODULE_LICENSE("GPL");
++
++int
++init_module(void)
++{
++ return i2c_pb1550_init();
++}
++
++void
++cleanup_module(void)
++{
++ i2c_au1550_del_bus(&pb1550_board_adapter);
++}
+diff -Nur linux-2.4.32-rc1/drivers/i2c/i2c-core.c linux-2.4.32-rc1.mips/drivers/i2c/i2c-core.c
+--- linux-2.4.32-rc1/drivers/i2c/i2c-core.c 2005-06-01 02:56:56.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/i2c/i2c-core.c 2005-05-23 14:12:30.000000000 +0200
+@@ -1280,6 +1280,9 @@
+ #ifdef CONFIG_I2C_MAX1617
+ extern int i2c_max1617_init(void);
+ #endif
++#ifdef CONFIG_I2C_ALGO_AU1550
++ extern int i2c_pb1550_init(void);
++#endif
+
+ #ifdef CONFIG_I2C_PROC
+ extern int sensors_init(void);
+@@ -1335,6 +1338,10 @@
+ i2c_max1617_init();
+ #endif
+
++#ifdef CONFIG_I2C_ALGO_AU1550
++ i2c_pb1550_init();
++#endif
++
+ /* -------------- proc interface ---- */
+ #ifdef CONFIG_I2C_PROC
+ sensors_init();
+diff -Nur linux-2.4.32-rc1/drivers/i2c/Makefile linux-2.4.32-rc1.mips/drivers/i2c/Makefile
+--- linux-2.4.32-rc1/drivers/i2c/Makefile 2004-02-18 14:36:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/i2c/Makefile 2005-02-11 20:49:04.000000000 +0100
+@@ -6,7 +6,7 @@
+
+ export-objs := i2c-core.o i2c-algo-bit.o i2c-algo-pcf.o \
+ i2c-algo-ite.o i2c-algo-sibyte.o i2c-algo-sgi.o \
+- i2c-proc.o
++ i2c-algo-au1550.o i2c-proc.o i2c-au1550.o
+
+ obj-$(CONFIG_I2C) += i2c-core.o
+ obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
+@@ -25,6 +25,7 @@
+ obj-$(CONFIG_I2C_ALGO_SIBYTE) += i2c-algo-sibyte.o i2c-sibyte.o
+ obj-$(CONFIG_I2C_MAX1617) += i2c-max1617.o
+ obj-$(CONFIG_I2C_ALGO_SGI) += i2c-algo-sgi.o
++obj-$(CONFIG_I2C_ALGO_AU1550) += i2c-algo-au1550.o i2c-au1550.o
+
+ # This is needed for automatic patch generation: sensors code starts here
+ # This is needed for automatic patch generation: sensors code ends here
+diff -Nur linux-2.4.32-rc1/drivers/media/video/indycam.c linux-2.4.32-rc1.mips/drivers/media/video/indycam.c
+--- linux-2.4.32-rc1/drivers/media/video/indycam.c 2004-02-18 14:36:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/media/video/indycam.c 2004-12-09 21:32:05.000000000 +0100
+@@ -50,13 +50,14 @@
+ 0x80, /* INDYCAM_GAMMA */
+ };
+
+- int err = 0;
+ struct indycam *camera;
+ struct i2c_client *client;
++ int err = 0;
+
+ client = kmalloc(sizeof(*client), GFP_KERNEL);
+- if (!client)
++ if (!client)
+ return -ENOMEM;
++
+ camera = kmalloc(sizeof(*camera), GFP_KERNEL);
+ if (!camera) {
+ err = -ENOMEM;
+@@ -67,7 +68,7 @@
+ client->adapter = adap;
+ client->addr = addr;
+ client->driver = &i2c_driver_indycam;
+- strcpy(client->name, "IndyCam client");
++ strcpy(client->name, "IndyCam client");
+ camera->client = client;
+
+ err = i2c_attach_client(client);
+@@ -75,18 +76,18 @@
+ goto out_free_camera;
+
+ camera->version = i2c_smbus_read_byte_data(client, INDYCAM_VERSION);
+- if (camera->version != CAMERA_VERSION_INDY &&
+- camera->version != CAMERA_VERSION_MOOSE) {
++ if ((camera->version != CAMERA_VERSION_INDY) &&
++ (camera->version != CAMERA_VERSION_MOOSE)) {
+ err = -ENODEV;
+ goto out_detach_client;
+ }
+- printk(KERN_INFO "Indycam v%d.%d detected.\n",
++ printk(KERN_INFO "IndyCam v%d.%d detected.\n",
+ INDYCAM_VERSION_MAJOR(camera->version),
+ INDYCAM_VERSION_MINOR(camera->version));
+
+ err = i2c_master_send(client, initseq, sizeof(initseq));
+ if (err)
+- printk(KERN_INFO "IndyCam initalization failed\n");
++ printk(KERN_ERR "IndyCam initalization failed.\n");
+
+ MOD_INC_USE_COUNT;
+ return 0;
+diff -Nur linux-2.4.32-rc1/drivers/media/video/vino.c linux-2.4.32-rc1.mips/drivers/media/video/vino.c
+--- linux-2.4.32-rc1/drivers/media/video/vino.c 2004-02-18 14:36:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/media/video/vino.c 2004-12-10 05:02:54.000000000 +0100
+@@ -5,6 +5,8 @@
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
++ * Copyright (C) 2004 Mikael Nousiainen <tmnousia@cc.hut.fi>
++ *
+ */
+
+ #include <linux/module.h>
+@@ -37,13 +39,23 @@
+ #define DEBUG(x...)
+ #endif
+
++/* Channels (who could have guessed) */
++#define VINO_CHAN_NONE 0
++#define VINO_CHAN_A 1
++#define VINO_CHAN_B 2
++
+ /* VINO video size */
+ #define VINO_PAL_WIDTH 768
+ #define VINO_PAL_HEIGHT 576
+ #define VINO_NTSC_WIDTH 646
+ #define VINO_NTSC_HEIGHT 486
+
+-/* set this to some sensible values. note: VINO_MIN_WIDTH has to be 8*x */
++/* Minimum value for Y-clipping (for smaller values the images
++ * will be corrupted) */
++#define VINO_MIN_Y_CLIPPING 2
++
++/* Set these to some sensible values.
++ * Note: the picture width has to be divisible by 8 */
+ #define VINO_MIN_WIDTH 32
+ #define VINO_MIN_HEIGHT 32
+
+@@ -64,9 +76,7 @@
+
+ struct vino_device {
+ struct video_device vdev;
+-#define VINO_CHAN_A 1
+-#define VINO_CHAN_B 2
+- int chan;
++ int chan; /* VINO_CHAN_NONE, VINO_CHAN_A or VINO_CHAN_B */
+ int alpha;
+ /* clipping... */
+ unsigned int left, right, top, bottom;
+@@ -106,7 +116,7 @@
+
+ struct vino_client {
+ struct i2c_client *driver;
+- int owner;
++ int owner; /* VINO_CHAN_NONE, VINO_CHAN_A or VINO_CHAN_B */
+ };
+
+ struct vino_video {
+@@ -362,6 +372,7 @@
+ static int dma_setup(struct vino_device *v)
+ {
+ u32 ctrl, intr;
++ int ofs;
+ struct sgi_vino_channel *ch;
+
+ ch = (v->chan == VINO_CHAN_A) ? &vino->a : &vino->b;
+@@ -377,14 +388,24 @@
+ ch->line_size = v->line_size - 8;
+ /* set the alpha register */
+ ch->alpha = v->alpha;
+- /* set cliping registers */
+- ch->clip_start = VINO_CLIP_ODD(v->top) | VINO_CLIP_EVEN(v->top+1) |
++ /* Set the clipping registers, this is the constant source of fun :)
++ * Y clipping start has to be >= 2 and end has to be start + height/2
++ * The values of top and bottom are even so dividing is not a problem
++ *
++ * The docs say that clipping values for the even field should be
++ * odd_end + something_to_skip_vertical_blanking + some_lines and
++ * even_start + height/2, though the image is good this way also
++ *
++ * TODO: for analog sources (SAA7191), the clipping values are a bit
++ * different and that case isn't yet handled
++ */
++ ofs = VINO_MIN_Y_CLIPPING; /* Should depend on input source */
++ ch->clip_start = VINO_CLIP_ODD(ofs + v->top / 2) |
++ VINO_CLIP_EVEN(ofs + v->top / 2 + 1) |
+ VINO_CLIP_X(v->left);
+- ch->clip_end = VINO_CLIP_ODD(v->bottom) | VINO_CLIP_EVEN(v->bottom+1) |
++ ch->clip_end = VINO_CLIP_ODD(ofs + v->bottom / 2 - 1) |
++ VINO_CLIP_EVEN(ofs + v->bottom / 2) |
+ VINO_CLIP_X(v->right);
+- /* FIXME: end-of-field bug workaround
+- VINO_CLIP_X(VINO_PAL_WIDTH);
+- */
+ /* init the frame rate and norm (full frame rate only for now...) */
+ ch->frame_rate = VINO_FRAMERT_RT(0x1fff) |
+ (get_capture_norm(v) == VIDEO_MODE_PAL ?
+@@ -510,6 +531,7 @@
+ static void vino_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+ {
+ u32 intr, ctrl;
++ int a_eof, b_eof;
+
+ spin_lock(&Vino->vino_lock);
+ ctrl = vino->control;
+@@ -525,12 +547,14 @@
+ vino->control = ctrl;
+ clear_eod(&Vino->chB);
+ }
++ a_eof = intr & VINO_INTSTAT_A_EOF;
++ b_eof = intr & VINO_INTSTAT_B_EOF;
+ vino->intr_status = ~intr;
+ spin_unlock(&Vino->vino_lock);
+- /* FIXME: For now we are assuming that interrupt means that frame is
+- * done. That's not true, but we can live with such brokeness for
+- * a while ;-) */
+- field_done(&Vino->chA);
++ if (a_eof)
++ field_done(&Vino->chA);
++ if (b_eof)
++ field_done(&Vino->chB);
+ }
+
+ static int vino_grab(struct vino_device *v, int frame)
+diff -Nur linux-2.4.32-rc1/drivers/mtd/devices/docprobe.c linux-2.4.32-rc1.mips/drivers/mtd/devices/docprobe.c
+--- linux-2.4.32-rc1/drivers/mtd/devices/docprobe.c 2003-06-13 16:51:34.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/mtd/devices/docprobe.c 2003-06-16 01:42:21.000000000 +0200
+@@ -89,10 +89,10 @@
+ 0xe4000000,
+ #elif defined(CONFIG_MOMENCO_OCELOT)
+ 0x2f000000,
+- 0xff000000,
++ 0xff000000,
+ #elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
+- 0xff000000,
+-##else
++ 0xff000000,
++#else
+ #warning Unknown architecture for DiskOnChip. No default probe locations defined
+ #endif
+ 0 };
+diff -Nur linux-2.4.32-rc1/drivers/mtd/devices/ms02-nv.c linux-2.4.32-rc1.mips/drivers/mtd/devices/ms02-nv.c
+--- linux-2.4.32-rc1/drivers/mtd/devices/ms02-nv.c 2003-06-13 16:51:34.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/mtd/devices/ms02-nv.c 2004-07-30 12:22:40.000000000 +0200
+@@ -1,10 +1,10 @@
+ /*
+- * Copyright (c) 2001 Maciej W. Rozycki
++ * Copyright (c) 2001 Maciej W. Rozycki
+ *
+- * 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 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.
+ *
+ * $Id: ms02-nv.c,v 1.2 2003/01/24 14:05:17 dwmw2 Exp $
+ */
+@@ -29,18 +29,18 @@
+
+
+ static char version[] __initdata =
+- "ms02-nv.c: v.1.0.0 13 Aug 2001 Maciej W. Rozycki.\n";
++ "ms02-nv.c: v.1.0.0 13 Aug 2001 Maciej W. Rozycki.\n";
+
+-MODULE_AUTHOR("Maciej W. Rozycki <macro@ds2.pg.gda.pl>");
++MODULE_AUTHOR("Maciej W. Rozycki <macro@linux-mips.org>");
+ MODULE_DESCRIPTION("DEC MS02-NV NVRAM module driver");
+ MODULE_LICENSE("GPL");
+
+
+ /*
+ * Addresses we probe for an MS02-NV at. Modules may be located
+- * at any 8MB boundary within a 0MB up to 112MB range or at any 32MB
+- * boundary within a 0MB up to 448MB range. We don't support a module
+- * at 0MB, though.
++ * at any 8MiB boundary within a 0MiB up to 112MiB range or at any 32MiB
++ * boundary within a 0MiB up to 448MiB range. We don't support a module
++ * at 0MiB, though.
+ */
+ static ulong ms02nv_addrs[] __initdata = {
+ 0x07000000, 0x06800000, 0x06000000, 0x05800000, 0x05000000,
+@@ -130,7 +130,7 @@
+
+ int ret = -ENODEV;
+
+- /* The module decodes 8MB of address space. */
++ /* The module decodes 8MiB of address space. */
+ mod_res = kmalloc(sizeof(*mod_res), GFP_KERNEL);
+ if (!mod_res)
+ return -ENOMEM;
+@@ -233,7 +233,7 @@
+ goto err_out_csr_res;
+ }
+
+- printk(KERN_INFO "mtd%d: %s at 0x%08lx, size %uMB.\n",
++ printk(KERN_INFO "mtd%d: %s at 0x%08lx, size %uMiB.\n",
+ mtd->index, ms02nv_name, addr, size >> 20);
+
+ mp->next = root_ms02nv_mtd;
+@@ -293,12 +293,12 @@
+
+ switch (mips_machtype) {
+ case MACH_DS5000_200:
+- csr = (volatile u32 *)KN02_CSR_ADDR;
++ csr = (volatile u32 *)KN02_CSR_BASE;
+ if (*csr & KN02_CSR_BNK32M)
+ stride = 2;
+ break;
+ case MACH_DS5000_2X0:
+- case MACH_DS5000:
++ case MACH_DS5900:
+ csr = (volatile u32 *)KN03_MCR_BASE;
+ if (*csr & KN03_MCR_BNK32M)
+ stride = 2;
+diff -Nur linux-2.4.32-rc1/drivers/mtd/devices/ms02-nv.h linux-2.4.32-rc1.mips/drivers/mtd/devices/ms02-nv.h
+--- linux-2.4.32-rc1/drivers/mtd/devices/ms02-nv.h 2002-11-29 00:53:13.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/mtd/devices/ms02-nv.h 2004-07-30 12:22:40.000000000 +0200
+@@ -1,32 +1,96 @@
+ /*
+- * Copyright (c) 2001 Maciej W. Rozycki
++ * Copyright (c) 2001, 2003 Maciej W. Rozycki
+ *
+- * 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.
++ * DEC MS02-NV (54-20948-01) battery backed-up NVRAM module for
++ * DECstation/DECsystem 5000/2x0 and DECsystem 5900 and 5900/260
++ * systems.
++ *
++ * 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.
++ *
++ * $Id: ms02-nv.h,v 1.3 2003/08/19 09:25:36 dwmw2 Exp $
+ */
+
+ #include <linux/ioport.h>
+ #include <linux/mtd/mtd.h>
+
++/*
++ * Addresses are decoded as follows:
++ *
++ * 0x000000 - 0x3fffff SRAM
++ * 0x400000 - 0x7fffff CSR
++ *
++ * Within the SRAM area the following ranges are forced by the system
++ * firmware:
++ *
++ * 0x000000 - 0x0003ff diagnostic area, destroyed upon a reboot
++ * 0x000400 - ENDofRAM storage area, available to operating systems
++ *
++ * but we can't really use the available area right from 0x000400 as
++ * the first word is used by the firmware as a status flag passed
++ * from an operating system. If anything but the valid data magic
++ * ID value is found, the firmware considers the SRAM clean, i.e.
++ * containing no valid data, and disables the battery resulting in
++ * data being erased as soon as power is switched off. So the choice
++ * for the start address of the user-available is 0x001000 which is
++ * nicely page aligned. The area between 0x000404 and 0x000fff may
++ * be used by the driver for own needs.
++ *
++ * The diagnostic area defines two status words to be read by an
++ * operating system, a magic ID to distinguish a MS02-NV board from
++ * anything else and a status information providing results of tests
++ * as well as the size of SRAM available, which can be 1MiB or 2MiB
++ * (that's what the firmware handles; no idea if 2MiB modules ever
++ * existed).
++ *
++ * The firmware only handles the MS02-NV board if installed in the
++ * last (15th) slot, so for any other location the status information
++ * stored in the SRAM cannot be relied upon. But from the hardware
++ * point of view there is no problem using up to 14 such boards in a
++ * system -- only the 1st slot needs to be filled with a DRAM module.
++ * The MS02-NV board is ECC-protected, like other MS02 memory boards.
++ *
++ * The state of the battery as provided by the CSR is reflected on
++ * the two onboard LEDs. When facing the battery side of the board,
++ * with the LEDs at the top left and the battery at the bottom right
++ * (i.e. looking from the back side of the system box), their meaning
++ * is as follows (the system has to be powered on):
++ *
++ * left LED battery disable status: lit = enabled
++ * right LED battery condition status: lit = OK
++ */
++
+ /* MS02-NV iomem register offsets. */
+ #define MS02NV_CSR 0x400000 /* control & status register */
+
++/* MS02-NV CSR status bits. */
++#define MS02NV_CSR_BATT_OK 0x01 /* battery OK */
++#define MS02NV_CSR_BATT_OFF 0x02 /* battery disabled */
++
++
+ /* MS02-NV memory offsets. */
+ #define MS02NV_DIAG 0x0003f8 /* diagnostic status */
+ #define MS02NV_MAGIC 0x0003fc /* MS02-NV magic ID */
+-#define MS02NV_RAM 0x000400 /* general-purpose RAM start */
++#define MS02NV_VALID 0x000400 /* valid data magic ID */
++#define MS02NV_RAM 0x001000 /* user-exposed RAM start */
+
+-/* MS02-NV diagnostic status constants. */
+-#define MS02NV_DIAG_SIZE_MASK 0xf0 /* RAM size mask */
+-#define MS02NV_DIAG_SIZE_SHIFT 0x10 /* RAM size shift (left) */
++/* MS02-NV diagnostic status bits. */
++#define MS02NV_DIAG_TEST 0x01 /* SRAM test done (?) */
++#define MS02NV_DIAG_RO 0x02 /* SRAM r/o test done */
++#define MS02NV_DIAG_RW 0x04 /* SRAM r/w test done */
++#define MS02NV_DIAG_FAIL 0x08 /* SRAM test failed */
++#define MS02NV_DIAG_SIZE_MASK 0xf0 /* SRAM size mask */
++#define MS02NV_DIAG_SIZE_SHIFT 0x10 /* SRAM size shift (left) */
+
+ /* MS02-NV general constants. */
+ #define MS02NV_ID 0x03021966 /* MS02-NV magic ID value */
++#define MS02NV_VALID_ID 0xbd100248 /* valid data magic ID value */
+ #define MS02NV_SLOT_SIZE 0x800000 /* size of the address space
+ decoded by the module */
+
++
+ typedef volatile u32 ms02nv_uint;
+
+ struct ms02nv_private {
+diff -Nur linux-2.4.32-rc1/drivers/mtd/maps/Config.in linux-2.4.32-rc1.mips/drivers/mtd/maps/Config.in
+--- linux-2.4.32-rc1/drivers/mtd/maps/Config.in 2003-06-13 16:51:34.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/mtd/maps/Config.in 2004-02-26 01:46:35.000000000 +0100
+@@ -51,11 +51,26 @@
+ dep_tristate ' Pb1000 MTD support' CONFIG_MTD_PB1000 $CONFIG_MIPS_PB1000
+ dep_tristate ' Pb1500 MTD support' CONFIG_MTD_PB1500 $CONFIG_MIPS_PB1500
+ dep_tristate ' Pb1100 MTD support' CONFIG_MTD_PB1100 $CONFIG_MIPS_PB1100
++ dep_tristate ' Bosporus MTD support' CONFIG_MTD_BOSPORUS $CONFIG_MIPS_BOSPORUS
++ dep_tristate ' XXS1500 boot flash device' CONFIG_MTD_XXS1500 $CONFIG_MIPS_XXS1500
++ dep_tristate ' MTX-1 flash device' CONFIG_MTD_MTX1 $CONFIG_MIPS_MTX1
+ if [ "$CONFIG_MTD_PB1500" = "y" -o "$CONFIG_MTD_PB1500" = "m" \
+ -o "$CONFIG_MTD_PB1100" = "y" -o "$CONFIG_MTD_PB1100" = "m" ]; then
+ bool ' Pb[15]00 boot flash device' CONFIG_MTD_PB1500_BOOT
+ bool ' Pb[15]00 user flash device (2nd 32MiB bank)' CONFIG_MTD_PB1500_USER
+ fi
++ tristate ' Db1x00 MTD support' CONFIG_MTD_DB1X00
++ if [ "$CONFIG_MTD_DB1X00" = "y" -o "$CONFIG_MTD_DB1X00" = "m" ]; then
++ bool ' Db1x00 boot flash device' CONFIG_MTD_DB1X00_BOOT
++ bool ' Db1x00 user flash device (2nd bank)' CONFIG_MTD_DB1X00_USER
++ fi
++ tristate ' Pb1550 MTD support' CONFIG_MTD_PB1550
++ if [ "$CONFIG_MTD_PB1550" = "y" -o "$CONFIG_MTD_PB1550" = "m" ]; then
++ bool ' Pb1550 Boot Flash' CONFIG_MTD_PB1550_BOOT
++ bool ' Pb1550 User Parameter Flash' CONFIG_MTD_PB1550_USER
++ fi
++ dep_tristate ' Hydrogen 3 MTD support' CONFIG_MTD_HYDROGEN3 $CONFIG_MIPS_HYDROGEN3
++ dep_tristate ' Mirage MTD support' CONFIG_MTD_MIRAGE $CONFIG_MIPS_MIRAGE
+ dep_tristate ' Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board' CONFIG_MTD_CSTM_MIPS_IXX $CONFIG_MTD_CFI $CONFIG_MTD_JEDEC $CONFIG_MTD_PARTITIONS
+ if [ "$CONFIG_MTD_CSTM_MIPS_IXX" = "y" -o "$CONFIG_MTD_CSTM_MIPS_IXX" = "m" ]; then
+ hex ' Physical start address of flash mapping' CONFIG_MTD_CSTM_MIPS_IXX_START 0x8000000
+diff -Nur linux-2.4.32-rc1/drivers/mtd/maps/db1x00-flash.c linux-2.4.32-rc1.mips/drivers/mtd/maps/db1x00-flash.c
+--- linux-2.4.32-rc1/drivers/mtd/maps/db1x00-flash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/mtd/maps/db1x00-flash.c 2005-02-03 07:35:29.000000000 +0100
+@@ -0,0 +1,283 @@
++/*
++ * Flash memory access on Alchemy Db1xxx boards
++ *
++ * (C) 2003 Pete Popov <ppopov@pacbell.net>
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++
++#include <asm/io.h>
++#include <asm/au1000.h>
++#include <asm/db1x00.h>
++
++#ifdef DEBUG_RW
++#define DBG(x...) printk(x)
++#else
++#define DBG(x...)
++#endif
++
++static unsigned long window_addr;
++static unsigned long window_size;
++static unsigned long flash_size;
++
++__u8 physmap_read8(struct map_info *map, unsigned long ofs)
++{
++ __u8 ret;
++ ret = __raw_readb(map->map_priv_1 + ofs);
++ DBG("read8 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++__u16 physmap_read16(struct map_info *map, unsigned long ofs)
++{
++ __u16 ret;
++ ret = __raw_readw(map->map_priv_1 + ofs);
++ DBG("read16 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++__u32 physmap_read32(struct map_info *map, unsigned long ofs)
++{
++ __u32 ret;
++ ret = __raw_readl(map->map_priv_1 + ofs);
++ DBG("read32 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
++{
++ DBG("physmap_copy from %x to %x\n", (unsigned)from, (unsigned)to);
++ memcpy_fromio(to, map->map_priv_1 + from, len);
++}
++
++void physmap_write8(struct map_info *map, __u8 d, unsigned long adr)
++{
++ DBG("write8 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writeb(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_write16(struct map_info *map, __u16 d, unsigned long adr)
++{
++ DBG("write16 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writew(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_write32(struct map_info *map, __u32 d, unsigned long adr)
++{
++ DBG("write32 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writel(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
++{
++ DBG("physmap_copy_to %x from %x\n", (unsigned)to, (unsigned)from);
++ memcpy_toio(map->map_priv_1 + to, from, len);
++}
++
++static struct map_info db1x00_map = {
++ name: "Db1x00 flash",
++ read8: physmap_read8,
++ read16: physmap_read16,
++ read32: physmap_read32,
++ copy_from: physmap_copy_from,
++ write8: physmap_write8,
++ write16: physmap_write16,
++ write32: physmap_write32,
++ copy_to: physmap_copy_to,
++};
++
++static unsigned char flash_buswidth = 4;
++
++/*
++ * The Db1x boards support different flash densities. We setup
++ * the mtd_partition structures below for default of 64Mbit
++ * flash densities, and override the partitions sizes, if
++ * necessary, after we check the board status register.
++ */
++
++#ifdef DB1X00_BOTH_BANKS
++/* both banks will be used. Combine the first bank and the first
++ * part of the second bank together into a single jffs/jffs2
++ * partition.
++ */
++static struct mtd_partition db1x00_partitions[] = {
++ {
++ name: "User FS",
++ size: 0x1c00000,
++ offset: 0x0000000
++ },{
++ name: "yamon",
++ size: 0x0100000,
++ offset: MTDPART_OFS_APPEND,
++ mask_flags: MTD_WRITEABLE
++ },{
++ name: "raw kernel",
++ size: (0x300000-0x40000), /* last 256KB is yamon env */
++ offset: MTDPART_OFS_APPEND,
++ }
++};
++#elif defined(DB1X00_BOOT_ONLY)
++static struct mtd_partition db1x00_partitions[] = {
++ {
++ name: "User FS",
++ size: 0x00c00000,
++ offset: 0x0000000
++ },{
++ name: "yamon",
++ size: 0x0100000,
++ offset: MTDPART_OFS_APPEND,
++ mask_flags: MTD_WRITEABLE
++ },{
++ name: "raw kernel",
++ size: (0x300000-0x40000), /* last 256KB is yamon env */
++ offset: MTDPART_OFS_APPEND,
++ }
++};
++#elif defined(DB1X00_USER_ONLY)
++static struct mtd_partition db1x00_partitions[] = {
++ {
++ name: "User FS",
++ size: 0x0e00000,
++ offset: 0x0000000
++ },{
++ name: "raw kernel",
++ size: MTDPART_SIZ_FULL,
++ offset: MTDPART_OFS_APPEND,
++ }
++};
++#else
++#error MTD_DB1X00 define combo error /* should never happen */
++#endif
++
++
++#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
++
++static struct mtd_partition *parsed_parts;
++static struct mtd_info *mymtd;
++
++/*
++ * Probe the flash density and setup window address and size
++ * based on user CONFIG options. There are times when we don't
++ * want the MTD driver to be probing the boot or user flash,
++ * so having the option to enable only one bank is important.
++ */
++int setup_flash_params()
++{
++ switch ((bcsr->status >> 14) & 0x3) {
++ case 0: /* 64Mbit devices */
++ flash_size = 0x800000; /* 8MB per part */
++#if defined(DB1X00_BOTH_BANKS)
++ window_addr = 0x1E000000;
++ window_size = 0x2000000;
++#elif defined(DB1X00_BOOT_ONLY)
++ window_addr = 0x1F000000;
++ window_size = 0x1000000;
++#else /* USER ONLY */
++ window_addr = 0x1E000000;
++ window_size = 0x1000000;
++#endif
++ break;
++ case 1:
++ /* 128 Mbit devices */
++ flash_size = 0x1000000; /* 16MB per part */
++#if defined(DB1X00_BOTH_BANKS)
++ window_addr = 0x1C000000;
++ window_size = 0x4000000;
++ /* USERFS from 0x1C00 0000 to 0x1FC0 0000 */
++ db1x00_partitions[0].size = 0x3C00000;
++#elif defined(DB1X00_BOOT_ONLY)
++ window_addr = 0x1E000000;
++ window_size = 0x2000000;
++ /* USERFS from 0x1E00 0000 to 0x1FC0 0000 */
++ db1x00_partitions[0].size = 0x1C00000;
++#else /* USER ONLY */
++ window_addr = 0x1C000000;
++ window_size = 0x2000000;
++ /* USERFS from 0x1C00 0000 to 0x1DE00000 */
++ db1x00_partitions[0].size = 0x1DE0000;
++#endif
++ break;
++ case 2:
++ /* 256 Mbit devices */
++ flash_size = 0x4000000; /* 64MB per part */
++#if defined(DB1X00_BOTH_BANKS)
++ return 1;
++#elif defined(DB1X00_BOOT_ONLY)
++ /* Boot ROM flash bank only; no user bank */
++ window_addr = 0x1C000000;
++ window_size = 0x4000000;
++ /* USERFS from 0x1C00 0000 to 0x1FC00000 */
++ db1x00_partitions[0].size = 0x3C00000;
++#else /* USER ONLY */
++ return 1;
++#endif
++ break;
++ default:
++ return 1;
++ }
++ return 0;
++}
++
++int __init db1x00_mtd_init(void)
++{
++ struct mtd_partition *parts;
++ int nb_parts = 0;
++ char *part_type;
++
++ /* Default flash buswidth */
++ db1x00_map.buswidth = flash_buswidth;
++
++ if (setup_flash_params())
++ return -ENXIO;
++
++ /*
++ * Static partition definition selection
++ */
++ part_type = "static";
++ parts = db1x00_partitions;
++ nb_parts = NB_OF(db1x00_partitions);
++ db1x00_map.size = window_size;
++
++ /*
++ * Now let's probe for the actual flash. Do it here since
++ * specific machine settings might have been set above.
++ */
++ printk(KERN_NOTICE "Db1xxx flash: probing %d-bit flash bus\n",
++ db1x00_map.buswidth*8);
++ db1x00_map.map_priv_1 =
++ (unsigned long)ioremap(window_addr, window_size);
++ mymtd = do_map_probe("cfi_probe", &db1x00_map);
++ if (!mymtd) return -ENXIO;
++ mymtd->module = THIS_MODULE;
++
++ add_mtd_partitions(mymtd, parts, nb_parts);
++ return 0;
++}
++
++static void __exit db1x00_mtd_cleanup(void)
++{
++ if (mymtd) {
++ del_mtd_partitions(mymtd);
++ map_destroy(mymtd);
++ if (parsed_parts)
++ kfree(parsed_parts);
++ }
++}
++
++module_init(db1x00_mtd_init);
++module_exit(db1x00_mtd_cleanup);
++
++MODULE_AUTHOR("Pete Popov");
++MODULE_DESCRIPTION("Db1x00 mtd map driver");
++MODULE_LICENSE("GPL");
+diff -Nur linux-2.4.32-rc1/drivers/mtd/maps/hydrogen3-flash.c linux-2.4.32-rc1.mips/drivers/mtd/maps/hydrogen3-flash.c
+--- linux-2.4.32-rc1/drivers/mtd/maps/hydrogen3-flash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/mtd/maps/hydrogen3-flash.c 2004-01-10 23:40:18.000000000 +0100
+@@ -0,0 +1,189 @@
++/*
++ * Flash memory access on Alchemy HydrogenIII boards
++ *
++ * (C) 2003 Pete Popov <ppopov@pacbell.net>
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++
++#include <asm/io.h>
++#include <asm/au1000.h>
++
++#ifdef DEBUG_RW
++#define DBG(x...) printk(x)
++#else
++#define DBG(x...)
++#endif
++
++#define WINDOW_ADDR 0x1E000000
++#define WINDOW_SIZE 0x02000000
++
++
++__u8 physmap_read8(struct map_info *map, unsigned long ofs)
++{
++ __u8 ret;
++ ret = __raw_readb(map->map_priv_1 + ofs);
++ DBG("read8 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++__u16 physmap_read16(struct map_info *map, unsigned long ofs)
++{
++ __u16 ret;
++ ret = __raw_readw(map->map_priv_1 + ofs);
++ DBG("read16 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++__u32 physmap_read32(struct map_info *map, unsigned long ofs)
++{
++ __u32 ret;
++ ret = __raw_readl(map->map_priv_1 + ofs);
++ DBG("read32 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
++{
++ DBG("physmap_copy from %x to %x\n", (unsigned)from, (unsigned)to);
++ memcpy_fromio(to, map->map_priv_1 + from, len);
++}
++
++void physmap_write8(struct map_info *map, __u8 d, unsigned long adr)
++{
++ DBG("write8 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writeb(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_write16(struct map_info *map, __u16 d, unsigned long adr)
++{
++ DBG("write16 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writew(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_write32(struct map_info *map, __u32 d, unsigned long adr)
++{
++ DBG("write32 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writel(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
++{
++ DBG("physmap_copy_to %x from %x\n", (unsigned)to, (unsigned)from);
++ memcpy_toio(map->map_priv_1 + to, from, len);
++}
++
++static struct map_info hydrogen3_map = {
++ name: "HydrogenIII flash",
++ read8: physmap_read8,
++ read16: physmap_read16,
++ read32: physmap_read32,
++ copy_from: physmap_copy_from,
++ write8: physmap_write8,
++ write16: physmap_write16,
++ write32: physmap_write32,
++ copy_to: physmap_copy_to,
++};
++
++static unsigned char flash_buswidth = 4;
++
++/* MTDPART_OFS_APPEND is vastly preferred to any attempt at statically lining
++ * up the offsets. */
++static struct mtd_partition hydrogen3_partitions[] = {
++ {
++ name: "User FS",
++ size: 0x1c00000,
++ offset: 0x0000000
++ },{
++ name: "yamon",
++ size: 0x0100000,
++ offset: MTDPART_OFS_APPEND,
++ mask_flags: MTD_WRITEABLE
++ },{
++ name: "raw kernel",
++ size: 0x02c0000,
++ offset: MTDPART_OFS_APPEND
++ }
++};
++
++#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
++
++static struct mtd_partition *parsed_parts;
++static struct mtd_info *mymtd;
++
++int __init hydrogen3_mtd_init(void)
++{
++ struct mtd_partition *parts;
++ int nb_parts = 0;
++ char *part_type;
++
++ /* Default flash buswidth */
++ hydrogen3_map.buswidth = flash_buswidth;
++
++ /*
++ * Static partition definition selection
++ */
++ part_type = "static";
++ parts = hydrogen3_partitions;
++ nb_parts = NB_OF(hydrogen3_partitions);
++ hydrogen3_map.size = WINDOW_SIZE;
++
++ /*
++ * Now let's probe for the actual flash. Do it here since
++ * specific machine settings might have been set above.
++ */
++ printk(KERN_NOTICE "HydrogenIII flash: probing %d-bit flash bus\n",
++ hydrogen3_map.buswidth*8);
++ hydrogen3_map.map_priv_1 =
++ (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
++ mymtd = do_map_probe("cfi_probe", &hydrogen3_map);
++ if (!mymtd) return -ENXIO;
++ mymtd->module = THIS_MODULE;
++
++ add_mtd_partitions(mymtd, parts, nb_parts);
++ return 0;
++}
++
++static void __exit hydrogen3_mtd_cleanup(void)
++{
++ if (mymtd) {
++ del_mtd_partitions(mymtd);
++ map_destroy(mymtd);
++ if (parsed_parts)
++ kfree(parsed_parts);
++ }
++}
++
++/*#ifndef MODULE
++
++static int __init _bootflashonly(char *str)
++{
++ bootflashonly = simple_strtol(str, NULL, 0);
++ return 1;
++}
++
++
++__setup("bootflashonly=", _bootflashonly);
++
++#endif*/
++
++
++module_init(hydrogen3_mtd_init);
++module_exit(hydrogen3_mtd_cleanup);
++
++MODULE_PARM(bootflashonly, "i");
++MODULE_PARM_DESC(bootflashonly, "1=use \"boot flash only\"");
++MODULE_AUTHOR("Pete Popov");
++MODULE_DESCRIPTION("HydrogenIII mtd map driver");
++MODULE_LICENSE("GPL");
+diff -Nur linux-2.4.32-rc1/drivers/mtd/maps/lasat.c linux-2.4.32-rc1.mips/drivers/mtd/maps/lasat.c
+--- linux-2.4.32-rc1/drivers/mtd/maps/lasat.c 2003-06-13 16:51:34.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/mtd/maps/lasat.c 2003-08-18 04:59:02.000000000 +0200
+@@ -1,15 +1,6 @@
+ /*
+ * Flash device on lasat 100 and 200 boards
+ *
+- * Presumably (C) 2002 Brian Murphy <brian@murphy.dk> or whoever he
+- * works for.
+- *
+- * 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.
+- *
+- * $Id: lasat.c,v 1.1 2003/01/24 14:26:38 dwmw2 Exp $
+- *
+ */
+
+ #include <linux/module.h>
+@@ -21,7 +12,6 @@
+ #include <linux/mtd/partitions.h>
+ #include <linux/config.h>
+ #include <asm/lasat/lasat.h>
+-#include <asm/lasat/lasat_mtd.h>
+
+ static struct mtd_info *mymtd;
+
+@@ -69,30 +59,33 @@
+ }
+
+ static struct map_info sp_map = {
+- .name = "SP flash",
+- .buswidth = 4,
+- .read8 = sp_read8,
+- .read16 = sp_read16,
+- .read32 = sp_read32,
+- .copy_from = sp_copy_from,
+- .write8 = sp_write8,
+- .write16 = sp_write16,
+- .write32 = sp_write32,
+- .copy_to = sp_copy_to
++ name: "SP flash",
++ buswidth: 4,
++ read8: sp_read8,
++ read16: sp_read16,
++ read32: sp_read32,
++ copy_from: sp_copy_from,
++ write8: sp_write8,
++ write16: sp_write16,
++ write32: sp_write32,
++ copy_to: sp_copy_to
+ };
+
+ static struct mtd_partition partition_info[LASAT_MTD_LAST];
+-static char *lasat_mtd_partnames[] = {"Bootloader", "Service", "Normal", "Filesystem", "Config"};
++static char *lasat_mtd_partnames[] = {"Bootloader", "Service", "Normal", "Config", "Filesystem"};
+
+ static int __init init_sp(void)
+ {
+ int i;
++ int nparts = 0;
+ /* this does not play well with the old flash code which
+ * protects and uprotects the flash when necessary */
+ printk(KERN_NOTICE "Unprotecting flash\n");
+ *lasat_misc->flash_wp_reg |= 1 << lasat_misc->flash_wp_bit;
+
+- sp_map.map_priv_1 = lasat_flash_partition_start(LASAT_MTD_BOOTLOADER);
++ sp_map.map_priv_1 = ioremap_nocache(
++ lasat_flash_partition_start(LASAT_MTD_BOOTLOADER),
++ lasat_board_info.li_flash_size);
+ sp_map.size = lasat_board_info.li_flash_size;
+
+ printk(KERN_NOTICE "sp flash device: %lx at %lx\n",
+@@ -109,12 +102,15 @@
+
+ for (i=0; i < LASAT_MTD_LAST; i++) {
+ size = lasat_flash_partition_size(i);
+- partition_info[i].size = size;
+- partition_info[i].offset = offset;
+- offset += size;
++ if (size != 0) {
++ nparts++;
++ partition_info[i].size = size;
++ partition_info[i].offset = offset;
++ offset += size;
++ }
+ }
+
+- add_mtd_partitions( mymtd, partition_info, LASAT_MTD_LAST );
++ add_mtd_partitions( mymtd, partition_info, nparts );
+ return 0;
+ }
+
+@@ -124,11 +120,11 @@
+ static void __exit cleanup_sp(void)
+ {
+ if (mymtd) {
+- del_mtd_partitions(mymtd);
+- map_destroy(mymtd);
++ del_mtd_partitions(mymtd);
++ map_destroy(mymtd);
+ }
+ if (sp_map.map_priv_1) {
+- sp_map.map_priv_1 = 0;
++ sp_map.map_priv_1 = 0;
+ }
+ }
+
+diff -Nur linux-2.4.32-rc1/drivers/mtd/maps/Makefile linux-2.4.32-rc1.mips/drivers/mtd/maps/Makefile
+--- linux-2.4.32-rc1/drivers/mtd/maps/Makefile 2003-06-13 16:51:34.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/mtd/maps/Makefile 2004-02-26 01:46:35.000000000 +0100
+@@ -52,7 +52,13 @@
+ obj-$(CONFIG_MTD_PB1000) += pb1xxx-flash.o
+ obj-$(CONFIG_MTD_PB1100) += pb1xxx-flash.o
+ obj-$(CONFIG_MTD_PB1500) += pb1xxx-flash.o
++obj-$(CONFIG_MTD_XXS1500) += xxs1500.o
++obj-$(CONFIG_MTD_MTX1) += mtx-1.o
+ obj-$(CONFIG_MTD_LASAT) += lasat.o
++obj-$(CONFIG_MTD_DB1X00) += db1x00-flash.o
++obj-$(CONFIG_MTD_PB1550) += pb1550-flash.o
++obj-$(CONFIG_MTD_HYDROGEN3) += hydrogen3-flash.o
++obj-$(CONFIG_MTD_BOSPORUS) += pb1xxx-flash.o
+ obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o
+ obj-$(CONFIG_MTD_EDB7312) += edb7312.o
+ obj-$(CONFIG_MTD_IMPA7) += impa7.o
+@@ -61,5 +67,6 @@
+ obj-$(CONFIG_MTD_UCLINUX) += uclinux.o
+ obj-$(CONFIG_MTD_NETtel) += nettel.o
+ obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o
++obj-$(CONFIG_MTD_MIRAGE) += mirage-flash.o
+
+ include $(TOPDIR)/Rules.make
+diff -Nur linux-2.4.32-rc1/drivers/mtd/maps/mirage-flash.c linux-2.4.32-rc1.mips/drivers/mtd/maps/mirage-flash.c
+--- linux-2.4.32-rc1/drivers/mtd/maps/mirage-flash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/mtd/maps/mirage-flash.c 2003-12-22 04:37:22.000000000 +0100
+@@ -0,0 +1,194 @@
++/*
++ * Flash memory access on AMD Mirage board.
++ *
++ * (C) 2003 Embedded Edge
++ * based on mirage-flash.c:
++ * (C) 2003 Pete Popov <ppopov@pacbell.net>
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++
++#include <asm/io.h>
++#include <asm/au1000.h>
++//#include <asm/mirage.h>
++
++#ifdef DEBUG_RW
++#define DBG(x...) printk(x)
++#else
++#define DBG(x...)
++#endif
++
++static unsigned long window_addr;
++static unsigned long window_size;
++static unsigned long flash_size;
++
++__u8 physmap_read8(struct map_info *map, unsigned long ofs)
++{
++ __u8 ret;
++ ret = __raw_readb(map->map_priv_1 + ofs);
++ DBG("read8 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++__u16 physmap_read16(struct map_info *map, unsigned long ofs)
++{
++ __u16 ret;
++ ret = __raw_readw(map->map_priv_1 + ofs);
++ DBG("read16 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++__u32 physmap_read32(struct map_info *map, unsigned long ofs)
++{
++ __u32 ret;
++ ret = __raw_readl(map->map_priv_1 + ofs);
++ DBG("read32 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
++{
++ DBG("physmap_copy from %x to %x\n", (unsigned)from, (unsigned)to);
++ memcpy_fromio(to, map->map_priv_1 + from, len);
++}
++
++void physmap_write8(struct map_info *map, __u8 d, unsigned long adr)
++{
++ DBG("write8 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writeb(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_write16(struct map_info *map, __u16 d, unsigned long adr)
++{
++ DBG("write16 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writew(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_write32(struct map_info *map, __u32 d, unsigned long adr)
++{
++ DBG("write32 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writel(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
++{
++ DBG("physmap_copy_to %x from %x\n", (unsigned)to, (unsigned)from);
++ memcpy_toio(map->map_priv_1 + to, from, len);
++}
++
++static struct map_info mirage_map = {
++ name: "Mirage flash",
++ read8: physmap_read8,
++ read16: physmap_read16,
++ read32: physmap_read32,
++ copy_from: physmap_copy_from,
++ write8: physmap_write8,
++ write16: physmap_write16,
++ write32: physmap_write32,
++ copy_to: physmap_copy_to,
++};
++
++static unsigned char flash_buswidth = 4;
++
++static struct mtd_partition mirage_partitions[] = {
++ {
++ name: "User FS",
++ size: 0x1c00000,
++ offset: 0x0000000
++ },{
++ name: "yamon",
++ size: 0x0100000,
++ offset: MTDPART_OFS_APPEND,
++ mask_flags: MTD_WRITEABLE
++ },{
++ name: "raw kernel",
++ size: (0x300000-0x40000), /* last 256KB is yamon env */
++ offset: MTDPART_OFS_APPEND,
++ }
++};
++
++#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
++
++static struct mtd_partition *parsed_parts;
++static struct mtd_info *mymtd;
++
++/*
++ * Probe the flash density and setup window address and size
++ * based on user CONFIG options. There are times when we don't
++ * want the MTD driver to be probing the boot or user flash,
++ * so having the option to enable only one bank is important.
++ */
++int setup_flash_params()
++{
++ flash_size = 0x4000000; /* 64MB per part */
++ /* Boot ROM flash bank only; no user bank */
++ window_addr = 0x1C000000;
++ window_size = 0x4000000;
++ /* USERFS from 0x1C00 0000 to 0x1FC00000 */
++ mirage_partitions[0].size = 0x3C00000;
++ return 0;
++}
++
++int __init mirage_mtd_init(void)
++{
++ struct mtd_partition *parts;
++ int nb_parts = 0;
++ char *part_type;
++
++ /* Default flash buswidth */
++ mirage_map.buswidth = flash_buswidth;
++
++ if (setup_flash_params())
++ return -ENXIO;
++
++ /*
++ * Static partition definition selection
++ */
++ part_type = "static";
++ parts = mirage_partitions;
++ nb_parts = NB_OF(mirage_partitions);
++ mirage_map.size = window_size;
++
++ /*
++ * Now let's probe for the actual flash. Do it here since
++ * specific machine settings might have been set above.
++ */
++ printk(KERN_NOTICE "Mirage flash: probing %d-bit flash bus\n",
++ mirage_map.buswidth*8);
++ mirage_map.map_priv_1 =
++ (unsigned long)ioremap(window_addr, window_size);
++ mymtd = do_map_probe("cfi_probe", &mirage_map);
++ if (!mymtd) return -ENXIO;
++ mymtd->module = THIS_MODULE;
++
++ add_mtd_partitions(mymtd, parts, nb_parts);
++ return 0;
++}
++
++static void __exit mirage_mtd_cleanup(void)
++{
++ if (mymtd) {
++ del_mtd_partitions(mymtd);
++ map_destroy(mymtd);
++ if (parsed_parts)
++ kfree(parsed_parts);
++ }
++}
++
++module_init(mirage_mtd_init);
++module_exit(mirage_mtd_cleanup);
++
++MODULE_AUTHOR("Embedded Edge");
++MODULE_DESCRIPTION("Mirage mtd map driver");
++MODULE_LICENSE("GPL");
+diff -Nur linux-2.4.32-rc1/drivers/mtd/maps/mtx-1.c linux-2.4.32-rc1.mips/drivers/mtd/maps/mtx-1.c
+--- linux-2.4.32-rc1/drivers/mtd/maps/mtx-1.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/mtd/maps/mtx-1.c 2003-06-27 02:04:35.000000000 +0200
+@@ -0,0 +1,181 @@
++/*
++ * Flash memory access on 4G Systems MTX-1 board
++ *
++ * (C) 2003 Pete Popov <ppopov@mvista.com>
++ * Bruno Randolf <bruno.randolf@4g-systems.de>
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++
++#include <asm/io.h>
++#include <asm/au1000.h>
++
++#ifdef DEBUG_RW
++#define DBG(x...) printk(x)
++#else
++#define DBG(x...)
++#endif
++
++#ifdef CONFIG_MIPS_MTX1
++#define WINDOW_ADDR 0x1E000000
++#define WINDOW_SIZE 0x2000000
++#endif
++
++__u8 physmap_read8(struct map_info *map, unsigned long ofs)
++{
++ __u8 ret;
++ ret = __raw_readb(map->map_priv_1 + ofs);
++ DBG("read8 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++__u16 physmap_read16(struct map_info *map, unsigned long ofs)
++{
++ __u16 ret;
++ ret = __raw_readw(map->map_priv_1 + ofs);
++ DBG("read16 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++__u32 physmap_read32(struct map_info *map, unsigned long ofs)
++{
++ __u32 ret;
++ ret = __raw_readl(map->map_priv_1 + ofs);
++ DBG("read32 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
++{
++ DBG("physmap_copy from %x to %x\n", (unsigned)from, (unsigned)to);
++ memcpy_fromio(to, map->map_priv_1 + from, len);
++}
++
++void physmap_write8(struct map_info *map, __u8 d, unsigned long adr)
++{
++ DBG("write8 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writeb(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_write16(struct map_info *map, __u16 d, unsigned long adr)
++{
++ DBG("write16 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writew(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_write32(struct map_info *map, __u32 d, unsigned long adr)
++{
++ DBG("write32 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writel(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
++{
++ DBG("physmap_copy_to %x from %x\n", (unsigned)to, (unsigned)from);
++ memcpy_toio(map->map_priv_1 + to, from, len);
++}
++
++
++
++static struct map_info mtx1_map = {
++ name: "MTX-1 flash",
++ read8: physmap_read8,
++ read16: physmap_read16,
++ read32: physmap_read32,
++ copy_from: physmap_copy_from,
++ write8: physmap_write8,
++ write16: physmap_write16,
++ write32: physmap_write32,
++ copy_to: physmap_copy_to,
++};
++
++
++static unsigned long flash_size = 0x01000000;
++static unsigned char flash_buswidth = 4;
++static struct mtd_partition mtx1_partitions[] = {
++ {
++ name: "user fs",
++ size: 0x1c00000,
++ offset: 0,
++ },{
++ name: "yamon",
++ size: 0x0100000,
++ offset: MTDPART_OFS_APPEND,
++ mask_flags: MTD_WRITEABLE
++ },{
++ name: "raw kernel",
++ size: 0x02c0000,
++ offset: MTDPART_OFS_APPEND,
++ },{
++ name: "yamon env vars",
++ size: 0x0040000,
++ offset: MTDPART_OFS_APPEND,
++ mask_flags: MTD_WRITEABLE
++ }
++};
++
++
++#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
++
++static struct mtd_partition *parsed_parts;
++static struct mtd_info *mymtd;
++
++int __init mtx1_mtd_init(void)
++{
++ struct mtd_partition *parts;
++ int nb_parts = 0;
++ char *part_type;
++
++ /* Default flash buswidth */
++ mtx1_map.buswidth = flash_buswidth;
++
++ /*
++ * Static partition definition selection
++ */
++ part_type = "static";
++ parts = mtx1_partitions;
++ nb_parts = NB_OF(mtx1_partitions);
++ mtx1_map.size = flash_size;
++
++ /*
++ * Now let's probe for the actual flash. Do it here since
++ * specific machine settings might have been set above.
++ */
++ printk(KERN_NOTICE "MTX-1 flash: probing %d-bit flash bus\n",
++ mtx1_map.buswidth*8);
++ mtx1_map.map_priv_1 =
++ (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
++ mymtd = do_map_probe("cfi_probe", &mtx1_map);
++ if (!mymtd) return -ENXIO;
++ mymtd->module = THIS_MODULE;
++
++ add_mtd_partitions(mymtd, parts, nb_parts);
++ return 0;
++}
++
++static void __exit mtx1_mtd_cleanup(void)
++{
++ if (mymtd) {
++ del_mtd_partitions(mymtd);
++ map_destroy(mymtd);
++ if (parsed_parts)
++ kfree(parsed_parts);
++ }
++}
++
++module_init(mtx1_mtd_init);
++module_exit(mtx1_mtd_cleanup);
++
++MODULE_AUTHOR("Pete Popov");
++MODULE_DESCRIPTION("MTX-1 CFI map driver");
++MODULE_LICENSE("GPL");
+diff -Nur linux-2.4.32-rc1/drivers/mtd/maps/pb1550-flash.c linux-2.4.32-rc1.mips/drivers/mtd/maps/pb1550-flash.c
+--- linux-2.4.32-rc1/drivers/mtd/maps/pb1550-flash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/mtd/maps/pb1550-flash.c 2004-02-26 01:48:48.000000000 +0100
+@@ -0,0 +1,270 @@
++/*
++ * Flash memory access on Alchemy Pb1550 board
++ *
++ * (C) 2004 Embedded Edge, LLC, based on pb1550-flash.c:
++ * (C) 2003 Pete Popov <ppopov@pacbell.net>
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++
++#include <asm/io.h>
++#include <asm/au1000.h>
++#include <asm/pb1550.h>
++
++#ifdef DEBUG_RW
++#define DBG(x...) printk(x)
++#else
++#define DBG(x...)
++#endif
++
++static unsigned long window_addr;
++static unsigned long window_size;
++
++__u8 physmap_read8(struct map_info *map, unsigned long ofs)
++{
++ __u8 ret;
++ ret = __raw_readb(map->map_priv_1 + ofs);
++ DBG("read8 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++__u16 physmap_read16(struct map_info *map, unsigned long ofs)
++{
++ __u16 ret;
++ ret = __raw_readw(map->map_priv_1 + ofs);
++ DBG("read16 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++__u32 physmap_read32(struct map_info *map, unsigned long ofs)
++{
++ __u32 ret;
++ ret = __raw_readl(map->map_priv_1 + ofs);
++ DBG("read32 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
++{
++ DBG("physmap_copy from %x to %x\n", (unsigned)from, (unsigned)to);
++ memcpy_fromio(to, map->map_priv_1 + from, len);
++}
++
++void physmap_write8(struct map_info *map, __u8 d, unsigned long adr)
++{
++ DBG("write8 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writeb(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_write16(struct map_info *map, __u16 d, unsigned long adr)
++{
++ DBG("write16 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writew(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_write32(struct map_info *map, __u32 d, unsigned long adr)
++{
++ DBG("write32 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writel(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
++{
++ DBG("physmap_copy_to %x from %x\n", (unsigned)to, (unsigned)from);
++ memcpy_toio(map->map_priv_1 + to, from, len);
++}
++
++static struct map_info pb1550_map = {
++ name: "Pb1550 flash",
++ read8: physmap_read8,
++ read16: physmap_read16,
++ read32: physmap_read32,
++ copy_from: physmap_copy_from,
++ write8: physmap_write8,
++ write16: physmap_write16,
++ write32: physmap_write32,
++ copy_to: physmap_copy_to,
++};
++
++static unsigned char flash_buswidth = 4;
++
++/*
++ * Support only 64MB NOR Flash parts
++ */
++
++#ifdef PB1550_BOTH_BANKS
++/* both banks will be used. Combine the first bank and the first
++ * part of the second bank together into a single jffs/jffs2
++ * partition.
++ */
++static struct mtd_partition pb1550_partitions[] = {
++ /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
++ * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash
++ * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash
++ */
++ {
++ name: "User FS",
++ size: (0x1FC00000 - 0x18000000),
++ offset: 0x0000000
++ },{
++ name: "yamon",
++ size: 0x0100000,
++ offset: MTDPART_OFS_APPEND,
++ mask_flags: MTD_WRITEABLE
++ },{
++ name: "raw kernel",
++ size: (0x300000 - 0x40000), /* last 256KB is yamon env */
++ offset: MTDPART_OFS_APPEND,
++ }
++};
++#elif defined(PB1550_BOOT_ONLY)
++static struct mtd_partition pb1550_partitions[] = {
++ /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
++ * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash
++ */
++ {
++ name: "User FS",
++ size: 0x03c00000,
++ offset: 0x0000000
++ },{
++ name: "yamon",
++ size: 0x0100000,
++ offset: MTDPART_OFS_APPEND,
++ mask_flags: MTD_WRITEABLE
++ },{
++ name: "raw kernel",
++ size: (0x300000-0x40000), /* last 256KB is yamon env */
++ offset: MTDPART_OFS_APPEND,
++ }
++};
++#elif defined(PB1550_USER_ONLY)
++static struct mtd_partition pb1550_partitions[] = {
++ /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
++ * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash
++ */
++ {
++ name: "User FS",
++ size: (0x4000000 - 0x200000), /* reserve 2MB for raw kernel */
++ offset: 0x0000000
++ },{
++ name: "raw kernel",
++ size: MTDPART_SIZ_FULL,
++ offset: MTDPART_OFS_APPEND,
++ }
++};
++#else
++#error MTD_PB1550 define combo error /* should never happen */
++#endif
++
++#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
++
++static struct mtd_partition *parsed_parts;
++static struct mtd_info *mymtd;
++
++/*
++ * Probe the flash density and setup window address and size
++ * based on user CONFIG options. There are times when we don't
++ * want the MTD driver to be probing the boot or user flash,
++ * so having the option to enable only one bank is important.
++ */
++int setup_flash_params()
++{
++ u16 boot_swapboot;
++ boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) |
++ ((bcsr->status >> 6) & 0x1);
++ printk("Pb1550 MTD: boot:swap %d\n", boot_swapboot);
++
++ switch (boot_swapboot) {
++ case 0: /* 512Mbit devices, both enabled */
++ case 1:
++ case 8:
++ case 9:
++#if defined(PB1550_BOTH_BANKS)
++ window_addr = 0x18000000;
++ window_size = 0x8000000;
++#elif defined(PB1550_BOOT_ONLY)
++ window_addr = 0x1C000000;
++ window_size = 0x4000000;
++#else /* USER ONLY */
++ window_addr = 0x1E000000;
++ window_size = 0x1000000;
++#endif
++ break;
++ case 0xC:
++ case 0xD:
++ case 0xE:
++ case 0xF:
++ /* 64 MB Boot NOR Flash is disabled */
++ /* and the start address is moved to 0x0C00000 */
++ window_addr = 0x0C000000;
++ window_size = 0x4000000;
++ default:
++ printk("Pb1550 MTD: unsupported boot:swap setting\n");
++ return 1;
++ }
++ return 0;
++}
++
++int __init pb1550_mtd_init(void)
++{
++ struct mtd_partition *parts;
++ int nb_parts = 0;
++ char *part_type;
++
++ /* Default flash buswidth */
++ pb1550_map.buswidth = flash_buswidth;
++
++ if (setup_flash_params())
++ return -ENXIO;
++
++ /*
++ * Static partition definition selection
++ */
++ part_type = "static";
++ parts = pb1550_partitions;
++ nb_parts = NB_OF(pb1550_partitions);
++ pb1550_map.size = window_size;
++
++ /*
++ * Now let's probe for the actual flash. Do it here since
++ * specific machine settings might have been set above.
++ */
++ printk(KERN_NOTICE "Pb1550 flash: probing %d-bit flash bus\n",
++ pb1550_map.buswidth*8);
++ pb1550_map.map_priv_1 =
++ (unsigned long)ioremap(window_addr, window_size);
++ mymtd = do_map_probe("cfi_probe", &pb1550_map);
++ if (!mymtd) return -ENXIO;
++ mymtd->module = THIS_MODULE;
++
++ add_mtd_partitions(mymtd, parts, nb_parts);
++ return 0;
++}
++
++static void __exit pb1550_mtd_cleanup(void)
++{
++ if (mymtd) {
++ del_mtd_partitions(mymtd);
++ map_destroy(mymtd);
++ if (parsed_parts)
++ kfree(parsed_parts);
++ }
++}
++
++module_init(pb1550_mtd_init);
++module_exit(pb1550_mtd_cleanup);
++
++MODULE_AUTHOR("Embedded Edge, LLC");
++MODULE_DESCRIPTION("Pb1550 mtd map driver");
++MODULE_LICENSE("GPL");
+diff -Nur linux-2.4.32-rc1/drivers/mtd/maps/pb1xxx-flash.c linux-2.4.32-rc1.mips/drivers/mtd/maps/pb1xxx-flash.c
+--- linux-2.4.32-rc1/drivers/mtd/maps/pb1xxx-flash.c 2003-06-13 16:51:34.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/mtd/maps/pb1xxx-flash.c 2003-05-19 08:27:22.000000000 +0200
+@@ -192,6 +192,34 @@
+ #else
+ #error MTD_PB1500 define combo error /* should never happen */
+ #endif
++#elif defined(CONFIG_MTD_BOSPORUS)
++static unsigned char flash_buswidth = 2;
++static unsigned long flash_size = 0x02000000;
++#define WINDOW_ADDR 0x1F000000
++#define WINDOW_SIZE 0x2000000
++static struct mtd_partition pb1xxx_partitions[] = {
++ {
++ name: "User FS",
++ size: 0x00400000,
++ offset: 0x00000000,
++ },{
++ name: "Yamon-2",
++ size: 0x00100000,
++ offset: 0x00400000,
++ },{
++ name: "Root FS",
++ size: 0x00700000,
++ offset: 0x00500000,
++ },{
++ name: "Yamon-1",
++ size: 0x00100000,
++ offset: 0x00C00000,
++ },{
++ name: "Kernel",
++ size: 0x00300000,
++ offset: 0x00D00000,
++ }
++};
+ #else
+ #error Unsupported board
+ #endif
+diff -Nur linux-2.4.32-rc1/drivers/mtd/maps/xxs1500.c linux-2.4.32-rc1.mips/drivers/mtd/maps/xxs1500.c
+--- linux-2.4.32-rc1/drivers/mtd/maps/xxs1500.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/mtd/maps/xxs1500.c 2003-08-02 04:06:01.000000000 +0200
+@@ -0,0 +1,186 @@
++/*
++ * Flash memory access on MyCable XXS1500 board
++ *
++ * (C) 2003 Pete Popov <ppopov@mvista.com>
++ *
++ * $Id: xxs1500.c,v 1.1.2.1 2003/06/13 21:15:46 ppopov Exp $
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++
++#include <asm/io.h>
++#include <asm/au1000.h>
++
++#ifdef DEBUG_RW
++#define DBG(x...) printk(x)
++#else
++#define DBG(x...)
++#endif
++
++#ifdef CONFIG_MIPS_XXS1500
++#define WINDOW_ADDR 0x1F000000
++#define WINDOW_SIZE 0x1000000
++#endif
++
++__u8 physmap_read8(struct map_info *map, unsigned long ofs)
++{
++ __u8 ret;
++ ret = __raw_readb(map->map_priv_1 + ofs);
++ DBG("read8 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++__u16 physmap_read16(struct map_info *map, unsigned long ofs)
++{
++ __u16 ret;
++ ret = __raw_readw(map->map_priv_1 + ofs);
++ DBG("read16 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++__u32 physmap_read32(struct map_info *map, unsigned long ofs)
++{
++ __u32 ret;
++ ret = __raw_readl(map->map_priv_1 + ofs);
++ DBG("read32 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
++ return ret;
++}
++
++void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
++{
++ DBG("physmap_copy from %x to %x\n", (unsigned)from, (unsigned)to);
++ memcpy_fromio(to, map->map_priv_1 + from, len);
++}
++
++void physmap_write8(struct map_info *map, __u8 d, unsigned long adr)
++{
++ DBG("write8 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writeb(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_write16(struct map_info *map, __u16 d, unsigned long adr)
++{
++ DBG("write16 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writew(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_write32(struct map_info *map, __u32 d, unsigned long adr)
++{
++ DBG("write32 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
++ __raw_writel(d, map->map_priv_1 + adr);
++ mb();
++}
++
++void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
++{
++ DBG("physmap_copy_to %x from %x\n", (unsigned)to, (unsigned)from);
++ memcpy_toio(map->map_priv_1 + to, from, len);
++}
++
++
++
++static struct map_info xxs1500_map = {
++ name: "XXS1500 flash",
++ read8: physmap_read8,
++ read16: physmap_read16,
++ read32: physmap_read32,
++ copy_from: physmap_copy_from,
++ write8: physmap_write8,
++ write16: physmap_write16,
++ write32: physmap_write32,
++ copy_to: physmap_copy_to,
++};
++
++
++static unsigned long flash_size = 0x00800000;
++static unsigned char flash_buswidth = 4;
++static struct mtd_partition xxs1500_partitions[] = {
++ {
++ name: "kernel image",
++ size: 0x00200000,
++ offset: 0,
++ },{
++ name: "user fs 0",
++ size: (0x00C00000-0x200000),
++ offset: MTDPART_OFS_APPEND,
++ },{
++ name: "yamon",
++ size: 0x00100000,
++ offset: MTDPART_OFS_APPEND,
++ mask_flags: MTD_WRITEABLE
++ },{
++ name: "user fs 1",
++ size: 0x2c0000,
++ offset: MTDPART_OFS_APPEND,
++ },{
++ name: "yamon env vars",
++ size: 0x040000,
++ offset: MTDPART_OFS_APPEND,
++ mask_flags: MTD_WRITEABLE
++ }
++};
++
++
++#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
++
++static struct mtd_partition *parsed_parts;
++static struct mtd_info *mymtd;
++
++int __init xxs1500_mtd_init(void)
++{
++ struct mtd_partition *parts;
++ int nb_parts = 0;
++ char *part_type;
++
++ /* Default flash buswidth */
++ xxs1500_map.buswidth = flash_buswidth;
++
++ /*
++ * Static partition definition selection
++ */
++ part_type = "static";
++ parts = xxs1500_partitions;
++ nb_parts = NB_OF(xxs1500_partitions);
++ xxs1500_map.size = flash_size;
++
++ /*
++ * Now let's probe for the actual flash. Do it here since
++ * specific machine settings might have been set above.
++ */
++ printk(KERN_NOTICE "XXS1500 flash: probing %d-bit flash bus\n",
++ xxs1500_map.buswidth*8);
++ xxs1500_map.map_priv_1 =
++ (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
++ mymtd = do_map_probe("cfi_probe", &xxs1500_map);
++ if (!mymtd) return -ENXIO;
++ mymtd->module = THIS_MODULE;
++
++ add_mtd_partitions(mymtd, parts, nb_parts);
++ return 0;
++}
++
++static void __exit xxs1500_mtd_cleanup(void)
++{
++ if (mymtd) {
++ del_mtd_partitions(mymtd);
++ map_destroy(mymtd);
++ if (parsed_parts)
++ kfree(parsed_parts);
++ }
++}
++
++module_init(xxs1500_mtd_init);
++module_exit(xxs1500_mtd_cleanup);
++
++MODULE_AUTHOR("Pete Popov");
++MODULE_DESCRIPTION("XXS1500 CFI map driver");
++MODULE_LICENSE("GPL");
+diff -Nur linux-2.4.32-rc1/drivers/net/defxx.c linux-2.4.32-rc1.mips/drivers/net/defxx.c
+--- linux-2.4.32-rc1/drivers/net/defxx.c 2004-11-17 12:54:21.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/net/defxx.c 2004-11-19 01:28:39.000000000 +0100
+@@ -10,24 +10,18 @@
+ *
+ * Abstract:
+ * A Linux device driver supporting the Digital Equipment Corporation
+- * FDDI EISA and PCI controller families. Supported adapters include:
++ * FDDI TURBOchannel, EISA and PCI controller families. Supported
++ * adapters include:
+ *
+- * DEC FDDIcontroller/EISA (DEFEA)
+- * DEC FDDIcontroller/PCI (DEFPA)
++ * DEC FDDIcontroller/TURBOchannel (DEFTA)
++ * DEC FDDIcontroller/EISA (DEFEA)
++ * DEC FDDIcontroller/PCI (DEFPA)
+ *
+- * Maintainers:
+- * LVS Lawrence V. Stefani
+- *
+- * Contact:
+- * The author may be reached at:
++ * The original author:
++ * LVS Lawrence V. Stefani <lstefani@yahoo.com>
+ *
+- * Inet: stefani@lkg.dec.com
+- * (NOTE! this address no longer works -jgarzik)
+- *
+- * Mail: Digital Equipment Corporation
+- * 550 King Street
+- * M/S: LKG1-3/M07
+- * Littleton, MA 01460
++ * Maintainers:
++ * macro Maciej W. Rozycki <macro@linux-mips.org>
+ *
+ * Credits:
+ * I'd like to thank Patricia Cross for helping me get started with
+@@ -197,16 +191,16 @@
+ * Sep 2000 tjeerd Fix leak on unload, cosmetic code cleanup
+ * Feb 2001 Skb allocation fixes
+ * Feb 2001 davej PCI enable cleanups.
++ * 04 Aug 2003 macro Converted to the DMA API.
++ * 14 Aug 2004 macro Fix device names reported.
++ * 26 Sep 2004 macro TURBOchannel support.
+ */
+
+ /* Include files */
+
+ #include <linux/module.h>
+-
+ #include <linux/kernel.h>
+-#include <linux/sched.h>
+ #include <linux/string.h>
+-#include <linux/ptrace.h>
+ #include <linux/errno.h>
+ #include <linux/ioport.h>
+ #include <linux/slab.h>
+@@ -215,19 +209,33 @@
+ #include <linux/delay.h>
+ #include <linux/init.h>
+ #include <linux/netdevice.h>
++#include <linux/fddidevice.h>
++#include <linux/skbuff.h>
++
+ #include <asm/byteorder.h>
+ #include <asm/bitops.h>
+ #include <asm/io.h>
+
+-#include <linux/fddidevice.h>
+-#include <linux/skbuff.h>
++#ifdef CONFIG_TC
++#include <asm/dec/tc.h>
++#else
++static int search_tc_card(const char *name) { return -ENODEV; }
++static void claim_tc_card(int slot) { }
++static void release_tc_card(int slot) { }
++static unsigned long get_tc_base_addr(int slot) { return 0; }
++static unsigned long get_tc_irq_nr(int slot) { return -1; }
++#endif
+
+ #include "defxx.h"
+
+-/* Version information string - should be updated prior to each new release!!! */
++/* Version information string should be updated prior to each new release! */
++#define DRV_NAME "defxx"
++#define DRV_VERSION "v1.07T"
++#define DRV_RELDATE "2004/09/26"
+
+ static char version[] __devinitdata =
+- "defxx.c:v1.05e 2001/02/03 Lawrence V. Stefani and others\n";
++ DRV_NAME ": " DRV_VERSION " " DRV_RELDATE
++ " Lawrence V. Stefani and others\n";
+
+ #define DYNAMIC_BUFFERS 1
+
+@@ -243,7 +251,7 @@
+ static void dfx_bus_init(struct net_device *dev);
+ static void dfx_bus_config_check(DFX_board_t *bp);
+
+-static int dfx_driver_init(struct net_device *dev);
++static int dfx_driver_init(struct net_device *dev, const char *print_name);
+ static int dfx_adap_init(DFX_board_t *bp, int get_buffers);
+
+ static int dfx_open(struct net_device *dev);
+@@ -337,48 +345,84 @@
+ int offset,
+ u8 data
+ )
++{
++ if (bp->bus_type == DFX_BUS_TYPE_TC)
++ {
++ volatile u8 *addr = (void *)(bp->base_addr + offset);
+
++ *addr = data;
++ mb();
++ }
++ else
+ {
+ u16 port = bp->base_addr + offset;
+
+ outb(data, port);
+ }
++}
+
+ static inline void dfx_port_read_byte(
+ DFX_board_t *bp,
+ int offset,
+ u8 *data
+ )
++{
++ if (bp->bus_type == DFX_BUS_TYPE_TC)
++ {
++ volatile u8 *addr = (void *)(bp->base_addr + offset);
+
++ mb();
++ *data = *addr;
++ }
++ else
+ {
+ u16 port = bp->base_addr + offset;
+
+ *data = inb(port);
+ }
++}
+
+ static inline void dfx_port_write_long(
+ DFX_board_t *bp,
+ int offset,
+ u32 data
+ )
++{
++ if (bp->bus_type == DFX_BUS_TYPE_TC)
++ {
++ volatile u32 *addr = (void *)(bp->base_addr + offset);
+
++ *addr = data;
++ mb();
++ }
++ else
+ {
+ u16 port = bp->base_addr + offset;
+
+ outl(data, port);
+ }
++}
+
+ static inline void dfx_port_read_long(
+ DFX_board_t *bp,
+ int offset,
+ u32 *data
+ )
++{
++ if (bp->bus_type == DFX_BUS_TYPE_TC)
++ {
++ volatile u32 *addr = (void *)(bp->base_addr + offset);
+
++ mb();
++ *data = *addr;
++ }
++ else
+ {
+ u16 port = bp->base_addr + offset;
+
+ *data = inl(port);
+ }
++}
+
+
+ /*
+@@ -393,8 +437,9 @@
+ * Condition code
+ *
+ * Arguments:
+- * pdev - pointer to pci device information (NULL for EISA)
+- * ioaddr - pointer to port (NULL for PCI)
++ * pdev - pointer to pci device information (NULL for EISA or TURBOchannel)
++ * bus_type - bus type (one of DFX_BUS_TYPE_*)
++ * handle - bus-specific data: slot (TC), pointer to port (EISA), NULL (PCI)
+ *
+ * Functional Description:
+ *
+@@ -410,54 +455,68 @@
+ * initialized and the board resources are read and stored in
+ * the device structure.
+ */
+-static int __devinit dfx_init_one_pci_or_eisa(struct pci_dev *pdev, long ioaddr)
++static int __devinit dfx_init_one_pci_or_eisa(struct pci_dev *pdev, u32 bus_type, long handle)
+ {
++ static int version_disp;
++ char *print_name = DRV_NAME;
+ struct net_device *dev;
+ DFX_board_t *bp; /* board pointer */
++ long ioaddr; /* pointer to port */
++ unsigned long len; /* resource length */
++ int alloc_size; /* total buffer size used */
+ int err;
+
+-#ifndef MODULE
+- static int version_disp;
+-
+- if (!version_disp) /* display version info if adapter is found */
+- {
++ if (!version_disp) { /* display version info if adapter is found */
+ version_disp = 1; /* set display flag to TRUE so that */
+ printk(version); /* we only display this string ONCE */
+ }
+-#endif
+
+- /*
+- * init_fddidev() allocates a device structure with private data, clears the device structure and private data,
+- * and calls fddi_setup() and register_netdev(). Not much left to do for us here.
+- */
+- dev = init_fddidev(NULL, sizeof(*bp));
++ if (pdev != NULL)
++ print_name = pdev->slot_name;
++
++ dev = alloc_fddidev(sizeof(*bp));
+ if (!dev) {
+- printk (KERN_ERR "defxx: unable to allocate fddidev, aborting\n");
++ printk(KERN_ERR "%s: unable to allocate fddidev, aborting\n",
++ print_name);
+ return -ENOMEM;
+ }
+
+ /* Enable PCI device. */
+- if (pdev != NULL) {
++ if (bus_type == DFX_BUS_TYPE_PCI) {
+ err = pci_enable_device (pdev);
+ if (err) goto err_out;
+ ioaddr = pci_resource_start (pdev, 1);
+ }
+
+ SET_MODULE_OWNER(dev);
++ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ bp = dev->priv;
+
+- if (!request_region (ioaddr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, dev->name)) {
+- printk (KERN_ERR "%s: Cannot reserve I/O resource 0x%x @ 0x%lx, aborting\n",
+- dev->name, PFI_K_CSR_IO_LEN, ioaddr);
++ if (bus_type == DFX_BUS_TYPE_TC) {
++ /* TURBOchannel board */
++ bp->slot = handle;
++ claim_tc_card(bp->slot);
++ ioaddr = get_tc_base_addr(handle) + PI_TC_K_CSR_OFFSET;
++ len = PI_TC_K_CSR_LEN;
++ } else if (bus_type == DFX_BUS_TYPE_EISA) {
++ /* EISA board */
++ ioaddr = handle;
++ len = PI_ESIC_K_CSR_IO_LEN;
++ } else
++ /* PCI board */
++ len = PFI_K_CSR_IO_LEN;
++ dev->base_addr = ioaddr; /* save port (I/O) base address */
++
++ if (!request_region(ioaddr, len, print_name)) {
++ printk(KERN_ERR "%s: Cannot reserve I/O resource "
++ "0x%lx @ 0x%lx, aborting\n", print_name, len, ioaddr);
+ err = -EBUSY;
+ goto err_out;
+ }
+
+ /* Initialize new device structure */
+
+- dev->base_addr = ioaddr; /* save port (I/O) base address */
+-
+ dev->get_stats = dfx_ctl_get_stats;
+ dev->open = dfx_open;
+ dev->stop = dfx_close;
+@@ -465,37 +524,54 @@
+ dev->set_multicast_list = dfx_ctl_set_multicast_list;
+ dev->set_mac_address = dfx_ctl_set_mac_address;
+
+- if (pdev == NULL) {
+- /* EISA board */
+- bp->bus_type = DFX_BUS_TYPE_EISA;
++ bp->bus_type = bus_type;
++ if (bus_type == DFX_BUS_TYPE_TC || bus_type == DFX_BUS_TYPE_EISA) {
++ /* TURBOchannel or EISA board */
+ bp->next = root_dfx_eisa_dev;
+ root_dfx_eisa_dev = dev;
+ } else {
+ /* PCI board */
+- bp->bus_type = DFX_BUS_TYPE_PCI;
+ bp->pci_dev = pdev;
+ pci_set_drvdata (pdev, dev);
+ pci_set_master (pdev);
+ }
+
+- if (dfx_driver_init(dev) != DFX_K_SUCCESS) {
++
++ if (dfx_driver_init(dev, print_name) != DFX_K_SUCCESS) {
+ err = -ENODEV;
+ goto err_out_region;
+ }
+
++ err = register_netdev(dev);
++ if (err)
++ goto err_out_kfree;
++
++ printk("%s: registered as %s\n", print_name, dev->name);
+ return 0;
+
++err_out_kfree:
++ alloc_size = sizeof(PI_DESCR_BLOCK) +
++ PI_CMD_REQ_K_SIZE_MAX + PI_CMD_RSP_K_SIZE_MAX +
++#ifndef DYNAMIC_BUFFERS
++ (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX) +
++#endif
++ sizeof(PI_CONSUMER_BLOCK) +
++ (PI_ALIGN_K_DESC_BLK - 1);
++ if (bp->kmalloced)
++ pci_free_consistent(pdev, alloc_size,
++ bp->kmalloced, bp->kmalloced_dma);
+ err_out_region:
+- release_region(ioaddr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN);
++ release_region(ioaddr, len);
+ err_out:
+- unregister_netdev(dev);
+- kfree(dev);
++ if (bp->bus_type == DFX_BUS_TYPE_TC)
++ release_tc_card(bp->slot);
++ free_netdev(dev);
+ return err;
+ }
+
+ static int __devinit dfx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+- return dfx_init_one_pci_or_eisa(pdev, 0);
++ return dfx_init_one_pci_or_eisa(pdev, DFX_BUS_TYPE_PCI, 0);
+ }
+
+ static int __init dfx_eisa_init(void)
+@@ -507,6 +583,7 @@
+
+ DBG_printk("In dfx_eisa_init...\n");
+
++#ifdef CONFIG_EISA
+ /* Scan for FDDI EISA controllers */
+
+ for (i=0; i < DFX_MAX_EISA_SLOTS; i++) /* only scan for up to 16 EISA slots */
+@@ -517,9 +594,27 @@
+ {
+ port = (i << 12); /* recalc base addr */
+
+- if (dfx_init_one_pci_or_eisa(NULL, port) == 0) rc = 0;
++ if (dfx_init_one_pci_or_eisa(NULL, DFX_BUS_TYPE_EISA, port) == 0) rc = 0;
+ }
+ }
++#endif
++ return rc;
++}
++
++static int __init dfx_tc_init(void)
++{
++ int rc = -ENODEV;
++ int slot; /* TC slot number */
++
++ DBG_printk("In dfx_tc_init...\n");
++
++ /* Scan for FDDI TC controllers */
++ while ((slot = search_tc_card("PMAF-F")) >= 0) {
++ if (dfx_init_one_pci_or_eisa(NULL, DFX_BUS_TYPE_TC, slot) == 0)
++ rc = 0;
++ else
++ break;
++ }
+ return rc;
+ }
+
+@@ -583,8 +678,9 @@
+
+ /* Initialize adapter based on bus type */
+
+- if (bp->bus_type == DFX_BUS_TYPE_EISA)
+- {
++ if (bp->bus_type == DFX_BUS_TYPE_TC) {
++ dev->irq = get_tc_irq_nr(bp->slot);
++ } else if (bp->bus_type == DFX_BUS_TYPE_EISA) {
+ /* Get the interrupt level from the ESIC chip */
+
+ dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &val);
+@@ -766,6 +862,7 @@
+ *
+ * Arguments:
+ * dev - pointer to device information
++ * print_name - printable device name
+ *
+ * Functional Description:
+ * This function allocates additional resources such as the host memory
+@@ -780,20 +877,21 @@
+ * or read adapter MAC address
+ *
+ * Assumptions:
+- * Memory allocated from kmalloc() call is physically contiguous, locked
+- * memory whose physical address equals its virtual address.
++ * Memory allocated from pci_alloc_consistent() call is physically
++ * contiguous, locked memory.
+ *
+ * Side Effects:
+ * Adapter is reset and should be in DMA_UNAVAILABLE state before
+ * returning from this routine.
+ */
+
+-static int __devinit dfx_driver_init(struct net_device *dev)
++static int __devinit dfx_driver_init(struct net_device *dev,
++ const char *print_name)
+ {
+ DFX_board_t *bp = dev->priv;
+ int alloc_size; /* total buffer size needed */
+ char *top_v, *curr_v; /* virtual addrs into memory block */
+- u32 top_p, curr_p; /* physical addrs into memory block */
++ dma_addr_t top_p, curr_p; /* physical addrs into memory block */
+ u32 data; /* host data register value */
+
+ DBG_printk("In dfx_driver_init...\n");
+@@ -837,26 +935,20 @@
+
+ /* Read the factory MAC address from the adapter then save it */
+
+- if (dfx_hw_port_ctrl_req(bp,
+- PI_PCTRL_M_MLA,
+- PI_PDATA_A_MLA_K_LO,
+- 0,
+- &data) != DFX_K_SUCCESS)
+- {
+- printk("%s: Could not read adapter factory MAC address!\n", dev->name);
++ if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_LO, 0,
++ &data) != DFX_K_SUCCESS) {
++ printk("%s: Could not read adapter factory MAC address!\n",
++ print_name);
+ return(DFX_K_FAILURE);
+- }
++ }
+ memcpy(&bp->factory_mac_addr[0], &data, sizeof(u32));
+
+- if (dfx_hw_port_ctrl_req(bp,
+- PI_PCTRL_M_MLA,
+- PI_PDATA_A_MLA_K_HI,
+- 0,
+- &data) != DFX_K_SUCCESS)
+- {
+- printk("%s: Could not read adapter factory MAC address!\n", dev->name);
++ if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_HI, 0,
++ &data) != DFX_K_SUCCESS) {
++ printk("%s: Could not read adapter factory MAC address!\n",
++ print_name);
+ return(DFX_K_FAILURE);
+- }
++ }
+ memcpy(&bp->factory_mac_addr[4], &data, sizeof(u16));
+
+ /*
+@@ -867,28 +959,27 @@
+ */
+
+ memcpy(dev->dev_addr, bp->factory_mac_addr, FDDI_K_ALEN);
+- if (bp->bus_type == DFX_BUS_TYPE_EISA)
+- printk("%s: DEFEA at I/O addr = 0x%lX, IRQ = %d, Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
+- dev->name,
+- dev->base_addr,
+- dev->irq,
+- dev->dev_addr[0],
+- dev->dev_addr[1],
+- dev->dev_addr[2],
+- dev->dev_addr[3],
+- dev->dev_addr[4],
+- dev->dev_addr[5]);
++ if (bp->bus_type == DFX_BUS_TYPE_TC)
++ printk("%s: DEFTA at addr = 0x%lX, IRQ = %d, "
++ "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
++ print_name, dev->base_addr, dev->irq,
++ dev->dev_addr[0], dev->dev_addr[1],
++ dev->dev_addr[2], dev->dev_addr[3],
++ dev->dev_addr[4], dev->dev_addr[5]);
++ else if (bp->bus_type == DFX_BUS_TYPE_EISA)
++ printk("%s: DEFEA at I/O addr = 0x%lX, IRQ = %d, "
++ "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
++ print_name, dev->base_addr, dev->irq,
++ dev->dev_addr[0], dev->dev_addr[1],
++ dev->dev_addr[2], dev->dev_addr[3],
++ dev->dev_addr[4], dev->dev_addr[5]);
+ else
+- printk("%s: DEFPA at I/O addr = 0x%lX, IRQ = %d, Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
+- dev->name,
+- dev->base_addr,
+- dev->irq,
+- dev->dev_addr[0],
+- dev->dev_addr[1],
+- dev->dev_addr[2],
+- dev->dev_addr[3],
+- dev->dev_addr[4],
+- dev->dev_addr[5]);
++ printk("%s: DEFPA at I/O addr = 0x%lX, IRQ = %d, "
++ "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
++ print_name, dev->base_addr, dev->irq,
++ dev->dev_addr[0], dev->dev_addr[1],
++ dev->dev_addr[2], dev->dev_addr[3],
++ dev->dev_addr[4], dev->dev_addr[5]);
+
+ /*
+ * Get memory for descriptor block, consumer block, and other buffers
+@@ -903,14 +994,15 @@
+ #endif
+ sizeof(PI_CONSUMER_BLOCK) +
+ (PI_ALIGN_K_DESC_BLK - 1);
+- bp->kmalloced = top_v = (char *) kmalloc(alloc_size, GFP_KERNEL);
+- if (top_v == NULL)
+- {
+- printk("%s: Could not allocate memory for host buffers and structures!\n", dev->name);
++ bp->kmalloced = top_v = pci_alloc_consistent(bp->pci_dev, alloc_size,
++ &bp->kmalloced_dma);
++ if (top_v == NULL) {
++ printk("%s: Could not allocate memory for host buffers "
++ "and structures!\n", print_name);
+ return(DFX_K_FAILURE);
+- }
++ }
+ memset(top_v, 0, alloc_size); /* zero out memory before continuing */
+- top_p = virt_to_bus(top_v); /* get physical address of buffer */
++ top_p = bp->kmalloced_dma; /* get physical address of buffer */
+
+ /*
+ * To guarantee the 8K alignment required for the descriptor block, 8K - 1
+@@ -924,7 +1016,7 @@
+ * for allocating the needed memory.
+ */
+
+- curr_p = (u32) (ALIGN(top_p, PI_ALIGN_K_DESC_BLK));
++ curr_p = ALIGN(top_p, PI_ALIGN_K_DESC_BLK);
+ curr_v = top_v + (curr_p - top_p);
+
+ /* Reserve space for descriptor block */
+@@ -965,14 +1057,20 @@
+
+ /* Display virtual and physical addresses if debug driver */
+
+- DBG_printk("%s: Descriptor block virt = %0lX, phys = %0X\n", dev->name, (long)bp->descr_block_virt, bp->descr_block_phys);
+- DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n", dev->name, (long)bp->cmd_req_virt, bp->cmd_req_phys);
+- DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n", dev->name, (long)bp->cmd_rsp_virt, bp->cmd_rsp_phys);
+- DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n", dev->name, (long)bp->rcv_block_virt, bp->rcv_block_phys);
+- DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n", dev->name, (long)bp->cons_block_virt, bp->cons_block_phys);
++ DBG_printk("%s: Descriptor block virt = %0lX, phys = %0X\n",
++ print_name,
++ (long)bp->descr_block_virt, bp->descr_block_phys);
++ DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n",
++ print_name, (long)bp->cmd_req_virt, bp->cmd_req_phys);
++ DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n",
++ print_name, (long)bp->cmd_rsp_virt, bp->cmd_rsp_phys);
++ DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n",
++ print_name, (long)bp->rcv_block_virt, bp->rcv_block_phys);
++ DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n",
++ print_name, (long)bp->cons_block_virt, bp->cons_block_phys);
+
+ return(DFX_K_SUCCESS);
+- }
++}
+
+
+ /*
+@@ -1218,7 +1316,9 @@
+
+ /* Register IRQ - support shared interrupts by passing device ptr */
+
+- ret = request_irq(dev->irq, (void *)dfx_interrupt, SA_SHIRQ, dev->name, dev);
++ ret = request_irq(dev->irq, (void *)dfx_interrupt,
++ (bp->bus_type == DFX_BUS_TYPE_TC) ? 0 : SA_SHIRQ,
++ dev->name, dev);
+ if (ret) {
+ printk(KERN_ERR "%s: Requested IRQ %d is busy\n", dev->name, dev->irq);
+ return ret;
+@@ -1737,7 +1837,7 @@
+ dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL,
+ (PFI_MODE_M_PDQ_INT_ENB + PFI_MODE_M_DMA_ENB));
+ }
+- else
++ else if (bp->bus_type == DFX_BUS_TYPE_EISA)
+ {
+ /* Disable interrupts at the ESIC */
+
+@@ -1755,6 +1855,13 @@
+ tmp |= PI_CONFIG_STAT_0_M_INT_ENB;
+ dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, tmp);
+ }
++ else {
++ /* TC doesn't share interrupts so no need to disable them */
++
++ /* Call interrupt service routine for this adapter */
++
++ dfx_int_common(dev);
++ }
+
+ spin_unlock(&bp->lock);
+ }
+@@ -2663,12 +2770,12 @@
+
+ static void my_skb_align(struct sk_buff *skb, int n)
+ {
+- u32 x=(u32)skb->data; /* We only want the low bits .. */
+- u32 v;
++ unsigned long x = (unsigned long)skb->data;
++ unsigned long v;
+
+- v=(x+n-1)&~(n-1); /* Where we want to be */
++ v = ALIGN(x, n); /* Where we want to be */
+
+- skb_reserve(skb, v-x);
++ skb_reserve(skb, v - x);
+ }
+
+
+@@ -2745,7 +2852,10 @@
+ */
+
+ my_skb_align(newskb, 128);
+- bp->descr_block_virt->rcv_data[i+j].long_1 = virt_to_bus(newskb->data);
++ bp->descr_block_virt->rcv_data[i + j].long_1 =
++ (u32)pci_map_single(bp->pci_dev, newskb->data,
++ NEW_SKB_SIZE,
++ PCI_DMA_FROMDEVICE);
+ /*
+ * p_rcv_buff_va is only used inside the
+ * kernel so we put the skb pointer here.
+@@ -2859,9 +2969,17 @@
+
+ my_skb_align(newskb, 128);
+ skb = (struct sk_buff *)bp->p_rcv_buff_va[entry];
++ pci_unmap_single(bp->pci_dev,
++ bp->descr_block_virt->rcv_data[entry].long_1,
++ NEW_SKB_SIZE,
++ PCI_DMA_FROMDEVICE);
+ skb_reserve(skb, RCV_BUFF_K_PADDING);
+ bp->p_rcv_buff_va[entry] = (char *)newskb;
+- bp->descr_block_virt->rcv_data[entry].long_1 = virt_to_bus(newskb->data);
++ bp->descr_block_virt->rcv_data[entry].long_1 =
++ (u32)pci_map_single(bp->pci_dev,
++ newskb->data,
++ NEW_SKB_SIZE,
++ PCI_DMA_FROMDEVICE);
+ } else
+ skb = NULL;
+ } else
+@@ -2934,7 +3052,7 @@
+ * is contained in a single physically contiguous buffer
+ * in which the virtual address of the start of packet
+ * (skb->data) can be converted to a physical address
+- * by using virt_to_bus().
++ * by using pci_map_single().
+ *
+ * Since the adapter architecture requires a three byte
+ * packet request header to prepend the start of packet,
+@@ -3082,12 +3200,13 @@
+ * skb->data.
+ * 6. The physical address of the start of packet
+ * can be determined from the virtual address
+- * by using virt_to_bus() and is only 32-bits
++ * by using pci_map_single() and is only 32-bits
+ * wide.
+ */
+
+ p_xmt_descr->long_0 = (u32) (PI_XMT_DESCR_M_SOP | PI_XMT_DESCR_M_EOP | ((skb->len) << PI_XMT_DESCR_V_SEG_LEN));
+- p_xmt_descr->long_1 = (u32) virt_to_bus(skb->data);
++ p_xmt_descr->long_1 = (u32)pci_map_single(bp->pci_dev, skb->data,
++ skb->len, PCI_DMA_TODEVICE);
+
+ /*
+ * Verify that descriptor is actually available
+@@ -3171,6 +3290,7 @@
+ {
+ XMT_DRIVER_DESCR *p_xmt_drv_descr; /* ptr to transmit driver descriptor */
+ PI_TYPE_2_CONSUMER *p_type_2_cons; /* ptr to rcv/xmt consumer block register */
++ u8 comp; /* local transmit completion index */
+ int freed = 0; /* buffers freed */
+
+ /* Service all consumed transmit frames */
+@@ -3188,7 +3308,11 @@
+ bp->xmt_total_bytes += p_xmt_drv_descr->p_skb->len;
+
+ /* Return skb to operating system */
+-
++ comp = bp->rcv_xmt_reg.index.xmt_comp;
++ pci_unmap_single(bp->pci_dev,
++ bp->descr_block_virt->xmt_data[comp].long_1,
++ p_xmt_drv_descr->p_skb->len,
++ PCI_DMA_TODEVICE);
+ dev_kfree_skb_irq(p_xmt_drv_descr->p_skb);
+
+ /*
+@@ -3297,6 +3421,7 @@
+ {
+ u32 prod_cons; /* rcv/xmt consumer block longword */
+ XMT_DRIVER_DESCR *p_xmt_drv_descr; /* ptr to transmit driver descriptor */
++ u8 comp; /* local transmit completion index */
+
+ /* Flush all outstanding transmit frames */
+
+@@ -3307,7 +3432,11 @@
+ p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[bp->rcv_xmt_reg.index.xmt_comp]);
+
+ /* Return skb to operating system */
+-
++ comp = bp->rcv_xmt_reg.index.xmt_comp;
++ pci_unmap_single(bp->pci_dev,
++ bp->descr_block_virt->xmt_data[comp].long_1,
++ p_xmt_drv_descr->p_skb->len,
++ PCI_DMA_TODEVICE);
+ dev_kfree_skb(p_xmt_drv_descr->p_skb);
+
+ /* Increment transmit error counter */
+@@ -3337,12 +3466,36 @@
+
+ static void __devexit dfx_remove_one_pci_or_eisa(struct pci_dev *pdev, struct net_device *dev)
+ {
+- DFX_board_t *bp = dev->priv;
++ DFX_board_t *bp = dev->priv;
++ unsigned long len; /* resource length */
++ int alloc_size; /* total buffer size used */
+
++ if (bp->bus_type == DFX_BUS_TYPE_TC) {
++ /* TURBOchannel board */
++ len = PI_TC_K_CSR_LEN;
++ } else if (bp->bus_type == DFX_BUS_TYPE_EISA) {
++ /* EISA board */
++ len = PI_ESIC_K_CSR_IO_LEN;
++ } else {
++ len = PFI_K_CSR_IO_LEN;
++ }
+ unregister_netdev(dev);
+- release_region(dev->base_addr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN );
+- if (bp->kmalloced) kfree(bp->kmalloced);
+- kfree(dev);
++ release_region(dev->base_addr, len);
++
++ if (bp->bus_type == DFX_BUS_TYPE_TC)
++ release_tc_card(bp->slot);
++
++ alloc_size = sizeof(PI_DESCR_BLOCK) +
++ PI_CMD_REQ_K_SIZE_MAX + PI_CMD_RSP_K_SIZE_MAX +
++#ifndef DYNAMIC_BUFFERS
++ (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX) +
++#endif
++ sizeof(PI_CONSUMER_BLOCK) +
++ (PI_ALIGN_K_DESC_BLK - 1);
++ if (bp->kmalloced)
++ pci_free_consistent(pdev, alloc_size, bp->kmalloced,
++ bp->kmalloced_dma);
++ free_netdev(dev);
+ }
+
+ static void __devexit dfx_remove_one (struct pci_dev *pdev)
+@@ -3353,21 +3506,22 @@
+ pci_set_drvdata(pdev, NULL);
+ }
+
+-static struct pci_device_id dfx_pci_tbl[] __devinitdata = {
++static struct pci_device_id dfx_pci_tbl[] = {
+ { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI, PCI_ANY_ID, PCI_ANY_ID, },
+ { 0, }
+ };
+ MODULE_DEVICE_TABLE(pci, dfx_pci_tbl);
+
+ static struct pci_driver dfx_driver = {
+- name: "defxx",
+- probe: dfx_init_one,
+- remove: __devexit_p(dfx_remove_one),
+- id_table: dfx_pci_tbl,
++ .name = "defxx",
++ .probe = dfx_init_one,
++ .remove = __devexit_p(dfx_remove_one),
++ .id_table = dfx_pci_tbl,
+ };
+
+ static int dfx_have_pci;
+ static int dfx_have_eisa;
++static int dfx_have_tc;
+
+
+ static void __exit dfx_eisa_cleanup(void)
+@@ -3388,12 +3542,7 @@
+
+ static int __init dfx_init(void)
+ {
+- int rc_pci, rc_eisa;
+-
+-/* when a module, this is printed whether or not devices are found in probe */
+-#ifdef MODULE
+- printk(version);
+-#endif
++ int rc_pci, rc_eisa, rc_tc;
+
+ rc_pci = pci_module_init(&dfx_driver);
+ if (rc_pci >= 0) dfx_have_pci = 1;
+@@ -3401,20 +3550,27 @@
+ rc_eisa = dfx_eisa_init();
+ if (rc_eisa >= 0) dfx_have_eisa = 1;
+
+- return ((rc_eisa < 0) ? 0 : rc_eisa) + ((rc_pci < 0) ? 0 : rc_pci);
++ rc_tc = dfx_tc_init();
++ if (rc_tc >= 0) dfx_have_tc = 1;
++
++ return ((rc_tc < 0) ? 0 : rc_tc) +
++ ((rc_eisa < 0) ? 0 : rc_eisa) +
++ ((rc_pci < 0) ? 0 : rc_pci);
+ }
+
+ static void __exit dfx_cleanup(void)
+ {
+ if (dfx_have_pci)
+ pci_unregister_driver(&dfx_driver);
+- if (dfx_have_eisa)
++ if (dfx_have_eisa || dfx_have_tc)
+ dfx_eisa_cleanup();
+-
+ }
+
+ module_init(dfx_init);
+ module_exit(dfx_cleanup);
++MODULE_AUTHOR("Lawrence V. Stefani");
++MODULE_DESCRIPTION("DEC FDDIcontroller EISA/PCI (DEFEA/DEFPA) driver "
++ DRV_VERSION " " DRV_RELDATE);
+ MODULE_LICENSE("GPL");
+
+
+diff -Nur linux-2.4.32-rc1/drivers/net/defxx.h linux-2.4.32-rc1.mips/drivers/net/defxx.h
+--- linux-2.4.32-rc1/drivers/net/defxx.h 2001-02-13 22:15:05.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/net/defxx.h 2004-10-03 20:06:48.000000000 +0200
+@@ -12,17 +12,11 @@
+ * Contains all definitions specified by port specification and required
+ * by the defxx.c driver.
+ *
+- * Maintainers:
+- * LVS Lawrence V. Stefani
+- *
+- * Contact:
+- * The author may be reached at:
++ * The original author:
++ * LVS Lawrence V. Stefani <lstefani@yahoo.com>
+ *
+- * Inet: stefani@lkg.dec.com
+- * Mail: Digital Equipment Corporation
+- * 550 King Street
+- * M/S: LKG1-3/M07
+- * Littleton, MA 01460
++ * Maintainers:
++ * macro Maciej W. Rozycki <macro@linux-mips.org>
+ *
+ * Modification History:
+ * Date Name Description
+@@ -30,6 +24,7 @@
+ * 09-Sep-96 LVS Added group_prom field. Moved read/write I/O
+ * macros to DEFXX.C.
+ * 12-Sep-96 LVS Removed packet request header pointers.
++ * 04 Aug 2003 macro Converted to the DMA API.
+ */
+
+ #ifndef _DEFXX_H_
+@@ -1467,6 +1462,11 @@
+
+ #endif /* #ifndef BIG_ENDIAN */
+
++/* Define TC PDQ CSR offset and length */
++
++#define PI_TC_K_CSR_OFFSET 0x100000
++#define PI_TC_K_CSR_LEN 0x80 /* 128 bytes */
++
+ /* Define EISA controller register offsets */
+
+ #define PI_ESIC_K_BURST_HOLDOFF 0x040
+@@ -1634,6 +1634,7 @@
+
+ #define DFX_BUS_TYPE_PCI 0 /* type code for DEC FDDIcontroller/PCI */
+ #define DFX_BUS_TYPE_EISA 1 /* type code for DEC FDDIcontroller/EISA */
++#define DFX_BUS_TYPE_TC 2 /* type code for DEC FDDIcontroller/TURBOchannel */
+
+ #define DFX_FC_PRH2_PRH1_PRH0 0x54003820 /* Packet Request Header bytes + FC */
+ #define DFX_PRH0_BYTE 0x20 /* Packet Request Header byte 0 */
+@@ -1704,17 +1705,19 @@
+ {
+ /* Keep virtual and physical pointers to locked, physically contiguous memory */
+
+- char *kmalloced; /* kfree this on unload */
++ char *kmalloced; /* pci_free_consistent this on unload */
++ dma_addr_t kmalloced_dma;
++ /* DMA handle for the above */
+ PI_DESCR_BLOCK *descr_block_virt; /* PDQ descriptor block virt address */
+- u32 descr_block_phys; /* PDQ descriptor block phys address */
++ dma_addr_t descr_block_phys; /* PDQ descriptor block phys address */
+ PI_DMA_CMD_REQ *cmd_req_virt; /* Command request buffer virt address */
+- u32 cmd_req_phys; /* Command request buffer phys address */
++ dma_addr_t cmd_req_phys; /* Command request buffer phys address */
+ PI_DMA_CMD_RSP *cmd_rsp_virt; /* Command response buffer virt address */
+- u32 cmd_rsp_phys; /* Command response buffer phys address */
++ dma_addr_t cmd_rsp_phys; /* Command response buffer phys address */
+ char *rcv_block_virt; /* LLC host receive queue buf blk virt */
+- u32 rcv_block_phys; /* LLC host receive queue buf blk phys */
++ dma_addr_t rcv_block_phys; /* LLC host receive queue buf blk phys */
+ PI_CONSUMER_BLOCK *cons_block_virt; /* PDQ consumer block virt address */
+- u32 cons_block_phys; /* PDQ consumer block phys address */
++ dma_addr_t cons_block_phys; /* PDQ consumer block phys address */
+
+ /* Keep local copies of Type 1 and Type 2 register data */
+
+@@ -1758,8 +1761,9 @@
+
+ struct net_device *dev; /* pointer to device structure */
+ struct net_device *next;
+- u32 bus_type; /* bus type (0 == PCI, 1 == EISA) */
+- u16 base_addr; /* base I/O address (same as dev->base_addr) */
++ u32 bus_type; /* bus type (0 == PCI, 1 == EISA, 2 == TC) */
++ long base_addr; /* base I/O address (same as dev->base_addr) */
++ int slot; /* TC slot number */
+ struct pci_dev * pci_dev;
+ u32 full_duplex_enb; /* FDDI Full Duplex enable (1 == on, 2 == off) */
+ u32 req_ttrt; /* requested TTRT value (in 80ns units) */
+diff -Nur linux-2.4.32-rc1/drivers/net/hamradio/hdlcdrv.c linux-2.4.32-rc1.mips/drivers/net/hamradio/hdlcdrv.c
+--- linux-2.4.32-rc1/drivers/net/hamradio/hdlcdrv.c 2002-02-25 20:37:59.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/net/hamradio/hdlcdrv.c 2004-05-04 14:04:27.000000000 +0200
+@@ -587,6 +587,8 @@
+ return -EINVAL;
+ s = (struct hdlcdrv_state *)dev->priv;
+
++ netif_stop_queue(dev);
++
+ if (s->ops && s->ops->close)
+ i = s->ops->close(dev);
+ if (s->skb)
+diff -Nur linux-2.4.32-rc1/drivers/net/irda/au1k_ir.c linux-2.4.32-rc1.mips/drivers/net/irda/au1k_ir.c
+--- linux-2.4.32-rc1/drivers/net/irda/au1k_ir.c 2004-02-18 14:36:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/net/irda/au1k_ir.c 2005-02-03 07:35:29.000000000 +0100
+@@ -81,10 +81,6 @@
+
+ #define RUN_AT(x) (jiffies + (x))
+
+-#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100)
+-static BCSR * const bcsr = (BCSR *)0xAE000000;
+-#endif
+-
+ static spinlock_t ir_lock = SPIN_LOCK_UNLOCKED;
+
+ /*
+diff -Nur linux-2.4.32-rc1/drivers/net/sgiseeq.c linux-2.4.32-rc1.mips/drivers/net/sgiseeq.c
+--- linux-2.4.32-rc1/drivers/net/sgiseeq.c 2005-01-19 15:09:56.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/net/sgiseeq.c 2005-09-23 16:35:27.000000000 +0200
+@@ -24,16 +24,16 @@
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/bitops.h>
++#include <asm/paccess.h>
+ #include <asm/page.h>
+ #include <asm/pgtable.h>
++#include <asm/sgi/mc.h>
+ #include <asm/sgi/hpc3.h>
+ #include <asm/sgi/ip22.h>
+ #include <asm/sgialib.h>
+
+ #include "sgiseeq.h"
+
+-static char *version = "sgiseeq.c: David S. Miller (dm@engr.sgi.com)\n";
+-
+ static char *sgiseeqstr = "SGI Seeq8003";
+
+ /*
+@@ -113,9 +113,9 @@
+
+ static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs)
+ {
+- hregs->rx_reset = HPC3_ERXRST_CRESET | HPC3_ERXRST_CLRIRQ;
++ hregs->reset = HPC3_ERST_CRESET | HPC3_ERST_CLRIRQ;
+ udelay(20);
+- hregs->rx_reset = 0;
++ hregs->reset = 0;
+ }
+
+ static inline void reset_hpc3_and_seeq(struct hpc3_ethregs *hregs,
+@@ -238,7 +238,6 @@
+
+ #define TSTAT_INIT_SEEQ (SEEQ_TCMD_IPT|SEEQ_TCMD_I16|SEEQ_TCMD_IC|SEEQ_TCMD_IUF)
+ #define TSTAT_INIT_EDLC ((TSTAT_INIT_SEEQ) | SEEQ_TCMD_RB2)
+-#define RDMACFG_INIT (HPC3_ERXDCFG_FRXDC | HPC3_ERXDCFG_FEOP | HPC3_ERXDCFG_FIRQ)
+
+ static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp,
+ struct sgiseeq_regs *sregs)
+@@ -260,8 +259,6 @@
+ sregs->tstat = TSTAT_INIT_SEEQ;
+ }
+
+- hregs->rx_dconfig |= RDMACFG_INIT;
+-
+ hregs->rx_ndptr = PHYSADDR(&sp->srings.rx_desc[0]);
+ hregs->tx_ndptr = PHYSADDR(&sp->srings.tx_desc[0]);
+
+@@ -432,7 +429,7 @@
+ spin_lock(&sp->tx_lock);
+
+ /* Ack the IRQ and set software state. */
+- hregs->rx_reset = HPC3_ERXRST_CLRIRQ;
++ hregs->reset = HPC3_ERST_CLRIRQ;
+
+ /* Always check for received packets. */
+ sgiseeq_rx(dev, sp, hregs, sregs);
+@@ -616,7 +613,7 @@
+
+ #define ALIGNED(x) ((((unsigned long)(x)) + 0xf) & ~(0xf))
+
+-int sgiseeq_init(struct hpc3_regs* regs, int irq)
++int sgiseeq_init(struct hpc3_regs* hpcregs, int irq, int has_eeprom)
+ {
+ struct net_device *dev;
+ struct sgiseeq_private *sp;
+@@ -629,7 +626,7 @@
+ goto err_out;
+ }
+ /* Make private data page aligned */
+- sp = (struct sgiseeq_private *) get_zeroed_page(GFP_KERNEL);
++ sp = (struct sgiseeq_private *) get_zeroed_page(GFP_KERNEL);
+ if (!sp) {
+ printk(KERN_ERR "Sgiseeq: Page alloc failed, aborting.\n");
+ err = -ENOMEM;
+@@ -644,7 +641,9 @@
+
+ #define EADDR_NVOFS 250
+ for (i = 0; i < 3; i++) {
+- unsigned short tmp = ip22_nvram_read(EADDR_NVOFS / 2 + i);
++ unsigned short tmp = has_eeprom ?
++ ip22_eeprom_read(&hpcregs->eeprom, EADDR_NVOFS / 2+i) :
++ ip22_nvram_read(EADDR_NVOFS / 2+i);
+
+ dev->dev_addr[2 * i] = tmp >> 8;
+ dev->dev_addr[2 * i + 1] = tmp & 0xff;
+@@ -654,8 +653,8 @@
+ gpriv = sp;
+ gdev = dev;
+ #endif
+- sp->sregs = (struct sgiseeq_regs *) &hpc3c0->eth_ext[0];
+- sp->hregs = &hpc3c0->ethregs;
++ sp->sregs = (struct sgiseeq_regs *) &hpcregs->eth_ext[0];
++ sp->hregs = &hpcregs->ethregs;
+ sp->name = sgiseeqstr;
+ sp->mode = SEEQ_RCMD_RBCAST;
+
+@@ -672,6 +671,11 @@
+ setup_rx_ring(sp->srings.rx_desc, SEEQ_RX_BUFFERS);
+ setup_tx_ring(sp->srings.tx_desc, SEEQ_TX_BUFFERS);
+
++ /* Setup PIO and DMA transfer timing */
++ sp->hregs->pconfig = 0x161;
++ sp->hregs->dconfig = HPC3_EDCFG_FIRQ | HPC3_EDCFG_FEOP |
++ HPC3_EDCFG_FRXDC | HPC3_EDCFG_PTO | 0x026;
++
+ /* Reset the chip. */
+ hpc3_eth_reset(sp->hregs);
+
+@@ -699,7 +703,7 @@
+ goto err_out_free_irq;
+ }
+
+- printk(KERN_INFO "%s: SGI Seeq8003 ", dev->name);
++ printk(KERN_INFO "%s: %s ", dev->name, sgiseeqstr);
+ for (i = 0; i < 6; i++)
+ printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
+
+@@ -721,10 +725,22 @@
+
+ static int __init sgiseeq_probe(void)
+ {
+- printk(version);
++ unsigned int tmp, ret1, ret2 = 0;
+
+ /* On board adapter on 1st HPC is always present */
+- return sgiseeq_init(hpc3c0, SGI_ENET_IRQ);
++ ret1 = sgiseeq_init(hpc3c0, SGI_ENET_IRQ, 0);
++ /* Let's see if second HPC is there */
++ if (!(ip22_is_fullhouse()) &&
++ get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1]) == 0) {
++ sgimc->giopar |= SGIMC_GIOPAR_MASTEREXP1 |
++ SGIMC_GIOPAR_EXP164 |
++ SGIMC_GIOPAR_HPC264;
++ hpc3c1->pbus_piocfg[0][0] = 0x3ffff;
++ /* interrupt/config register on Challenge S Mezz board */
++ hpc3c1->pbus_extregs[0][0] = 0x30;
++ ret2 = sgiseeq_init(hpc3c1, SGI_GIO_0_IRQ, 1);
++ }
++ return (ret1 & ret2) ? ret1 : 0;
+ }
+
+ static void __exit sgiseeq_exit(void)
+@@ -747,4 +763,6 @@
+ module_init(sgiseeq_probe);
+ module_exit(sgiseeq_exit);
+
++MODULE_DESCRIPTION("SGI Seeq 8003 driver");
++MODULE_AUTHOR("David S. Miller");
+ MODULE_LICENSE("GPL");
+diff -Nur linux-2.4.32-rc1/drivers/pci/pci.c linux-2.4.32-rc1.mips/drivers/pci/pci.c
+--- linux-2.4.32-rc1/drivers/pci/pci.c 2004-11-17 12:54:21.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/pci/pci.c 2004-11-19 01:28:41.000000000 +0100
+@@ -1281,11 +1281,17 @@
+ {
+ unsigned int buses;
+ unsigned short cr;
++ unsigned short bctl;
+ struct pci_bus *child;
+ int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
+
+ pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
+ DBG("Scanning behind PCI bridge %s, config %06x, pass %d\n", dev->slot_name, buses & 0xffffff, pass);
++ /* Disable MasterAbortMode during probing to avoid reporting
++ of bus errors (in some architectures) */
++ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bctl);
++ pci_write_config_word(dev, PCI_BRIDGE_CONTROL,
++ bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT);
+ if ((buses & 0xffff00) && !pcibios_assign_all_busses()) {
+ /*
+ * Bus already configured by firmware, process it in the first
+@@ -1351,6 +1357,7 @@
+ pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
+ pci_write_config_word(dev, PCI_COMMAND, cr);
+ }
++ pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl);
+ sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number);
+ return max;
+ }
+diff -Nur linux-2.4.32-rc1/drivers/pcmcia/au1000_db1x00.c linux-2.4.32-rc1.mips/drivers/pcmcia/au1000_db1x00.c
+--- linux-2.4.32-rc1/drivers/pcmcia/au1000_db1x00.c 2005-01-19 15:09:57.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/pcmcia/au1000_db1x00.c 2005-02-03 07:35:30.000000000 +0100
+@@ -1,6 +1,6 @@
+ /*
+ *
+- * Alchemy Semi Db1x00 boards specific pcmcia routines.
++ * AMD Alchemy DUAL-SLOT Db1x00 boards' specific pcmcia routines.
+ *
+ * Copyright 2002 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+@@ -54,9 +54,20 @@
+ #include <asm/au1000.h>
+ #include <asm/au1000_pcmcia.h>
+
++#if defined(CONFIG_MIPS_PB1200)
++#include <asm/pb1200.h>
++#elif defined(CONFIG_MIPS_DB1200)
++#include <asm/db1200.h>
++#else
+ #include <asm/db1x00.h>
++#endif
+
+-static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
++#define PCMCIA_MAX_SOCK 1
++#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK+1)
++
++/* VPP/VCC */
++#define SET_VCC_VPP(VCC, VPP, SLOT)\
++ ((((VCC)<<2) | ((VPP)<<0)) << ((SLOT)*8))
+
+ static int db1x00_pcmcia_init(struct pcmcia_init *init)
+ {
+@@ -76,7 +87,7 @@
+ db1x00_pcmcia_socket_state(unsigned sock, struct pcmcia_state *state)
+ {
+ u32 inserted;
+- unsigned char vs;
++ u16 vs;
+
+ if(sock > PCMCIA_MAX_SOCK) return -1;
+
+@@ -87,11 +98,11 @@
+
+ if (sock == 0) {
+ vs = bcsr->status & 0x3;
+- inserted = !(bcsr->status & (1<<4));
++ inserted = BOARD_CARD_INSERTED(0);
+ }
+ else {
+ vs = (bcsr->status & 0xC)>>2;
+- inserted = !(bcsr->status & (1<<5));
++ inserted = BOARD_CARD_INSERTED(1);
+ }
+
+ DEBUG(KERN_DEBUG "db1x00 socket %d: inserted %d, vs %d\n",
+@@ -144,16 +155,9 @@
+ if(info->sock > PCMCIA_MAX_SOCK) return -1;
+
+ if(info->sock == 0)
+-#ifdef CONFIG_MIPS_DB1550
+- info->irq = AU1000_GPIO_3;
++ info->irq = BOARD_PC0_INT;
+ else
+- info->irq = AU1000_GPIO_5;
+-#else
+- info->irq = AU1000_GPIO_2;
+- else
+- info->irq = AU1000_GPIO_5;
+-#endif
+-
++ info->irq = BOARD_PC1_INT;
+ return 0;
+ }
+
+diff -Nur linux-2.4.32-rc1/drivers/pcmcia/Config.in linux-2.4.32-rc1.mips/drivers/pcmcia/Config.in
+--- linux-2.4.32-rc1/drivers/pcmcia/Config.in 2004-02-18 14:36:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/pcmcia/Config.in 2004-02-22 06:21:34.000000000 +0100
+@@ -30,16 +30,14 @@
+ dep_tristate ' M8xx support' CONFIG_PCMCIA_M8XX $CONFIG_PCMCIA
+ fi
+ if [ "$CONFIG_SOC_AU1X00" = "y" ]; then
+- dep_tristate ' Au1x00 PCMCIA support' CONFIG_PCMCIA_AU1X00 $CONFIG_PCMCIA
+- if [ "$CONFIG_PCMCIA_AU1X00" != "n" ]; then
+- bool ' Pb1x00 board support' CONFIG_PCMCIA_PB1X00
+- bool ' Db1x00 board support' CONFIG_PCMCIA_DB1X00
+- bool ' XXS1500 board support' CONFIG_PCMCIA_XXS1500
+- fi
++ dep_tristate ' Au1x00 PCMCIA support' CONFIG_PCMCIA_AU1X00 $CONFIG_PCMCIA
+ fi
+ if [ "$CONFIG_SIBYTE_SB1xxx_SOC" = "y" ]; then
+ dep_bool ' SiByte PCMCIA support' CONFIG_PCMCIA_SIBYTE $CONFIG_PCMCIA $CONFIG_BLK_DEV_IDE_SIBYTE
+ fi
++ if [ "$CONFIG_VRC4171" = "y" -o "$CONFIG_VRC4171" = "m" ]; then
++ dep_tristate ' NEC VRC4171 Card Controllers support' CONFIG_PCMCIA_VRC4171 $CONFIG_PCMCIA
++ fi
+ if [ "$CONFIG_VRC4173" = "y" -o "$CONFIG_VRC4173" = "m" ]; then
+ dep_tristate ' NEC VRC4173 CARDU support' CONFIG_PCMCIA_VRC4173 $CONFIG_PCMCIA
+ fi
+diff -Nur linux-2.4.32-rc1/drivers/pcmcia/Makefile linux-2.4.32-rc1.mips/drivers/pcmcia/Makefile
+--- linux-2.4.32-rc1/drivers/pcmcia/Makefile 2004-02-18 14:36:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/pcmcia/Makefile 2005-02-03 07:35:30.000000000 +0100
+@@ -61,9 +61,18 @@
+
+ obj-$(CONFIG_PCMCIA_AU1X00) += au1x00_ss.o
+ au1000_ss-objs-y := au1000_generic.o
+-au1000_ss-objs-$(CONFIG_PCMCIA_PB1X00) += au1000_pb1x00.o
+-au1000_ss-objs-$(CONFIG_PCMCIA_DB1X00) += au1000_db1x00.o
+-au1000_ss-objs-$(CONFIG_PCMCIA_XXS1500) += au1000_xxs1500.o
++au1000_ss-objs-$(CONFIG_MIPS_PB1000) += au1000_pb1x00.o
++au1000_ss-objs-$(CONFIG_MIPS_PB1100) += au1000_pb1x00.o
++au1000_ss-objs-$(CONFIG_MIPS_PB1500) += au1000_pb1x00.o
++au1000_ss-objs-$(CONFIG_MIPS_PB1550) += au1000_pb1550.o
++au1000_ss-objs-$(CONFIG_MIPS_PB1200) += au1000_db1x00.o
++au1000_ss-objs-$(CONFIG_MIPS_DB1000) += au1000_db1x00.o
++au1000_ss-objs-$(CONFIG_MIPS_DB1100) += au1000_db1x00.o
++au1000_ss-objs-$(CONFIG_MIPS_DB1500) += au1000_db1x00.o
++au1000_ss-objs-$(CONFIG_MIPS_DB1550) += au1000_db1x00.o
++au1000_ss-objs-$(CONFIG_MIPS_DB1200) += au1000_db1x00.o
++au1000_ss-objs-$(CONFIG_MIPS_HYDROGEN3) += au1000_hydrogen3.o
++au1000_ss-objs-$(CONFIG_MIPS_XXS1500) += au1000_xxs1500.o
+
+ obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o
+ obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o
+@@ -89,6 +98,7 @@
+ sa1100_cs-objs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o sa1111_generic.o
+ sa1100_cs-objs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o
+
++obj-$(CONFIG_PCMCIA_VRC4171) += vrc4171_card.o
+ obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o
+
+ include $(TOPDIR)/Rules.make
+diff -Nur linux-2.4.32-rc1/drivers/pcmcia/vrc4171_card.c linux-2.4.32-rc1.mips/drivers/pcmcia/vrc4171_card.c
+--- linux-2.4.32-rc1/drivers/pcmcia/vrc4171_card.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/pcmcia/vrc4171_card.c 2004-01-19 16:54:58.000000000 +0100
+@@ -0,0 +1,886 @@
++/*
++ * vrc4171_card.c, NEC VRC4171 Card Controller driver for Socket Services.
++ *
++ * Copyright (C) 2003 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
++ *
++ * 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/init.h>
++#include <linux/ioport.h>
++#include <linux/irq.h>
++#include <linux/module.h>
++#include <linux/spinlock.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++
++#include <asm/io.h>
++#include <asm/vr41xx/vrc4171.h>
++
++#include <pcmcia/ss.h>
++
++#include "i82365.h"
++
++MODULE_DESCRIPTION("NEC VRC4171 Card Controllers driver for Socket Services");
++MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
++MODULE_LICENSE("GPL");
++
++#define CARD_MAX_SLOTS 2
++#define CARD_SLOTA 0
++#define CARD_SLOTB 1
++#define CARD_SLOTB_OFFSET 0x40
++
++#define CARD_MEM_START 0x10000000
++#define CARD_MEM_END 0x13ffffff
++#define CARD_MAX_MEM_OFFSET 0x3ffffff
++#define CARD_MAX_MEM_SPEED 1000
++
++#define CARD_CONTROLLER_INDEX 0x03e0
++#define CARD_CONTROLLER_DATA 0x03e1
++#define CARD_CONTROLLER_SIZE 2
++ /* Power register */
++ #define VPP_GET_VCC 0x01
++ #define POWER_ENABLE 0x10
++ #define CARD_VOLTAGE_SENSE 0x1f
++ #define VCC_3VORXV_CAPABLE 0x00
++ #define VCC_XV_ONLY 0x01
++ #define VCC_3V_CAPABLE 0x02
++ #define VCC_5V_ONLY 0x03
++ #define CARD_VOLTAGE_SELECT 0x2f
++ #define VCC_3V 0x01
++ #define VCC_5V 0x00
++ #define VCC_XV 0x02
++ #define VCC_STATUS_3V 0x02
++ #define VCC_STATUS_5V 0x01
++ #define VCC_STATUS_XV 0x03
++ #define GLOBAL_CONTROL 0x1e
++ #define EXWRBK 0x04
++ #define IRQPM_EN 0x08
++ #define CLRPMIRQ 0x10
++
++#define IO_MAX_MAPS 2
++#define MEM_MAX_MAPS 5
++
++enum {
++ SLOTB_PROBE = 0,
++ SLOTB_NOPROBE_IO,
++ SLOTB_NOPROBE_MEM,
++ SLOTB_NOPROBE_ALL
++};
++
++typedef struct vrc4171_socket {
++ int noprobe;
++ void (*handler)(void *, unsigned int);
++ void *info;
++ socket_cap_t cap;
++ spinlock_t event_lock;
++ uint16_t events;
++ struct socket_info_t *pcmcia_socket;
++ struct tq_struct tq_task;
++ char name[24];
++ int csc_irq;
++ int io_irq;
++} vrc4171_socket_t;
++
++static vrc4171_socket_t vrc4171_sockets[CARD_MAX_SLOTS];
++static int vrc4171_slotb = SLOTB_IS_NONE;
++static unsigned int vrc4171_irq;
++static uint16_t vrc4171_irq_mask = 0xdeb8;
++
++extern struct socket_info_t *pcmcia_register_socket(int slot,
++ struct pccard_operations *vtable,
++ int use_bus_pm);
++extern void pcmcia_unregister_socket(struct socket_info_t *s);
++
++static inline uint8_t exca_read_byte(int slot, uint8_t index)
++{
++ if (slot == CARD_SLOTB)
++ index += CARD_SLOTB_OFFSET;
++
++ outb(index, CARD_CONTROLLER_INDEX);
++ return inb(CARD_CONTROLLER_DATA);
++}
++
++static inline uint16_t exca_read_word(int slot, uint8_t index)
++{
++ uint16_t data;
++
++ if (slot == CARD_SLOTB)
++ index += CARD_SLOTB_OFFSET;
++
++ outb(index++, CARD_CONTROLLER_INDEX);
++ data = inb(CARD_CONTROLLER_DATA);
++
++ outb(index, CARD_CONTROLLER_INDEX);
++ data |= ((uint16_t)inb(CARD_CONTROLLER_DATA)) << 8;
++
++ return data;
++}
++
++static inline uint8_t exca_write_byte(int slot, uint8_t index, uint8_t data)
++{
++ if (slot == CARD_SLOTB)
++ index += CARD_SLOTB_OFFSET;
++
++ outb(index, CARD_CONTROLLER_INDEX);
++ outb(data, CARD_CONTROLLER_DATA);
++
++ return data;
++}
++
++static inline uint16_t exca_write_word(int slot, uint8_t index, uint16_t data)
++{
++ if (slot == CARD_SLOTB)
++ index += CARD_SLOTB_OFFSET;
++
++ outb(index++, CARD_CONTROLLER_INDEX);
++ outb(data, CARD_CONTROLLER_DATA);
++
++ outb(index, CARD_CONTROLLER_INDEX);
++ outb((uint8_t)(data >> 8), CARD_CONTROLLER_DATA);
++
++ return data;
++}
++
++static inline int search_nonuse_irq(void)
++{
++ int i;
++
++ for (i = 0; i < 16; i++) {
++ if (vrc4171_irq_mask & (1 << i)) {
++ vrc4171_irq_mask &= ~(1 << i);
++ return i;
++ }
++ }
++
++ return -1;
++}
++
++static int pccard_init(unsigned int slot)
++{
++ vrc4171_socket_t *socket = &vrc4171_sockets[slot];
++
++ socket->cap.features |= SS_CAP_PCCARD | SS_CAP_PAGE_REGS;
++ socket->cap.irq_mask = 0;
++ socket->cap.pci_irq = vrc4171_irq;
++ socket->cap.map_size = 0x1000;
++ socket->events = 0;
++ spin_lock_init(socket->event_lock);
++ socket->csc_irq = search_nonuse_irq();
++ socket->io_irq = search_nonuse_irq();
++
++ return 0;
++}
++
++static int pccard_suspend(unsigned int slot)
++{
++ return -EINVAL;
++}
++
++static int pccard_register_callback(unsigned int slot,
++ void (*handler)(void *, unsigned int),
++ void *info)
++{
++ vrc4171_socket_t *socket;
++
++ if (slot >= CARD_MAX_SLOTS)
++ return -EINVAL;
++
++ socket = &vrc4171_sockets[slot];
++
++ socket->handler = handler;
++ socket->info = info;
++
++ if (handler)
++ MOD_INC_USE_COUNT;
++ else
++ MOD_DEC_USE_COUNT;
++
++ return 0;
++}
++
++static int pccard_inquire_socket(unsigned int slot, socket_cap_t *cap)
++{
++ vrc4171_socket_t *socket;
++
++ if (slot >= CARD_MAX_SLOTS || cap == NULL)
++ return -EINVAL;
++
++ socket = &vrc4171_sockets[slot];
++
++ *cap = socket->cap;
++
++ return 0;
++}
++
++static int pccard_get_status(unsigned int slot, u_int *value)
++{
++ uint8_t status, sense;
++ u_int val = 0;
++
++ if (slot >= CARD_MAX_SLOTS || value == NULL)
++ return -EINVAL;
++
++ status = exca_read_byte(slot, I365_STATUS);
++ if (exca_read_byte(slot, I365_INTCTL) & I365_PC_IOCARD) {
++ if (status & I365_CS_STSCHG)
++ val |= SS_STSCHG;
++ } else {
++ if (!(status & I365_CS_BVD1))
++ val |= SS_BATDEAD;
++ else if ((status & (I365_CS_BVD1 | I365_CS_BVD2)) == I365_CS_BVD1)
++ val |= SS_BATWARN;
++ }
++ if ((status & I365_CS_DETECT) == I365_CS_DETECT)
++ val |= SS_DETECT;
++ if (status & I365_CS_WRPROT)
++ val |= SS_WRPROT;
++ if (status & I365_CS_READY)
++ val |= SS_READY;
++ if (status & I365_CS_POWERON)
++ val |= SS_POWERON;
++
++ sense = exca_read_byte(slot, CARD_VOLTAGE_SENSE);
++ switch (sense) {
++ case VCC_3VORXV_CAPABLE:
++ val |= SS_3VCARD | SS_XVCARD;
++ break;
++ case VCC_XV_ONLY:
++ val |= SS_XVCARD;
++ break;
++ case VCC_3V_CAPABLE:
++ val |= SS_3VCARD;
++ break;
++ default:
++ /* 5V only */
++ break;
++ }
++
++ *value = val;
++
++ return 0;
++}
++
++static inline u_char get_Vcc_value(uint8_t voltage)
++{
++ switch (voltage) {
++ case VCC_STATUS_3V:
++ return 33;
++ case VCC_STATUS_5V:
++ return 50;
++ default:
++ break;
++ }
++
++ return 0;
++}
++
++static inline u_char get_Vpp_value(uint8_t power, u_char Vcc)
++{
++ if ((power & 0x03) == 0x01 || (power & 0x03) == 0x02)
++ return Vcc;
++
++ return 0;
++}
++
++static int pccard_get_socket(unsigned int slot, socket_state_t *state)
++{
++ vrc4171_socket_t *socket;
++ uint8_t power, voltage, control, cscint;
++
++ if (slot >= CARD_MAX_SLOTS || state == NULL)
++ return -EINVAL;
++
++ socket = &vrc4171_sockets[slot];
++
++ power = exca_read_byte(slot, I365_POWER);
++ voltage = exca_read_byte(slot, CARD_VOLTAGE_SELECT);
++
++ state->Vcc = get_Vcc_value(voltage);
++ state->Vpp = get_Vpp_value(power, state->Vcc);
++
++ state->flags = 0;
++ if (power & POWER_ENABLE)
++ state->flags |= SS_PWR_AUTO;
++ if (power & I365_PWR_OUT)
++ state->flags |= SS_OUTPUT_ENA;
++
++ control = exca_read_byte(slot, I365_INTCTL);
++ if (control & I365_PC_IOCARD)
++ state->flags |= SS_IOCARD;
++ if (!(control & I365_PC_RESET))
++ state->flags |= SS_RESET;
++
++ cscint = exca_read_byte(slot, I365_CSCINT);
++ state->csc_mask = 0;
++ if (state->flags & SS_IOCARD) {
++ if (cscint & I365_CSC_STSCHG)
++ state->flags |= SS_STSCHG;
++ } else {
++ if (cscint & I365_CSC_BVD1)
++ state->csc_mask |= SS_BATDEAD;
++ if (cscint & I365_CSC_BVD2)
++ state->csc_mask |= SS_BATWARN;
++ }
++ if (cscint & I365_CSC_READY)
++ state->csc_mask |= SS_READY;
++ if (cscint & I365_CSC_DETECT)
++ state->csc_mask |= SS_DETECT;
++
++ return 0;
++}
++
++static inline uint8_t set_Vcc_value(u_char Vcc)
++{
++ switch (Vcc) {
++ case 33:
++ return VCC_3V;
++ case 50:
++ return VCC_5V;
++ }
++
++ /* Small voltage is chosen for safety. */
++ return VCC_3V;
++}
++
++static int pccard_set_socket(unsigned int slot, socket_state_t *state)
++{
++ vrc4171_socket_t *socket;
++ uint8_t voltage, power, control, cscint;
++
++ if (slot >= CARD_MAX_SLOTS ||
++ (state->Vpp != state->Vcc && state->Vpp != 0) ||
++ (state->Vcc != 50 && state->Vcc != 33 && state->Vcc != 0))
++ return -EINVAL;
++
++ socket = &vrc4171_sockets[slot];
++
++ spin_lock_irq(&socket->event_lock);
++
++ voltage = set_Vcc_value(state->Vcc);
++ exca_write_byte(slot, CARD_VOLTAGE_SELECT, voltage);
++
++ power = POWER_ENABLE;
++ if (state->Vpp == state->Vcc)
++ power |= VPP_GET_VCC;
++ if (state->flags & SS_OUTPUT_ENA)
++ power |= I365_PWR_OUT;
++ exca_write_byte(slot, I365_POWER, power);
++
++ control = 0;
++ if (state->io_irq != 0)
++ control |= socket->io_irq;
++ if (state->flags & SS_IOCARD)
++ control |= I365_PC_IOCARD;
++ if (state->flags & SS_RESET)
++ control &= ~I365_PC_RESET;
++ else
++ control |= I365_PC_RESET;
++ exca_write_byte(slot, I365_INTCTL, control);
++
++ cscint = 0;
++ exca_write_byte(slot, I365_CSCINT, cscint);
++ exca_read_byte(slot, I365_CSC); /* clear CardStatus change */
++ if (state->csc_mask != 0)
++ cscint |= socket->csc_irq << 8;
++ if (state->flags & SS_IOCARD) {
++ if (state->csc_mask & SS_STSCHG)
++ cscint |= I365_CSC_STSCHG;
++ } else {
++ if (state->csc_mask & SS_BATDEAD)
++ cscint |= I365_CSC_BVD1;
++ if (state->csc_mask & SS_BATWARN)
++ cscint |= I365_CSC_BVD2;
++ }
++ if (state->csc_mask & SS_READY)
++ cscint |= I365_CSC_READY;
++ if (state->csc_mask & SS_DETECT)
++ cscint |= I365_CSC_DETECT;
++ exca_write_byte(slot, I365_CSCINT, cscint);
++
++ spin_unlock_irq(&socket->event_lock);
++
++ return 0;
++}
++
++static int pccard_get_io_map(unsigned int slot, struct pccard_io_map *io)
++{
++ vrc4171_socket_t *socket;
++ uint8_t ioctl, addrwin;
++ u_char map;
++
++ if (slot >= CARD_MAX_SLOTS || io == NULL ||
++ io->map >= IO_MAX_MAPS)
++ return -EINVAL;
++
++ socket = &vrc4171_sockets[slot];
++ map = io->map;
++
++ io->start = exca_read_word(slot, I365_IO(map)+I365_W_START);
++ io->stop = exca_read_word(slot, I365_IO(map)+I365_W_STOP);
++
++ ioctl = exca_read_byte(slot, I365_IOCTL);
++ if (io->flags & I365_IOCTL_WAIT(map))
++ io->speed = 1;
++ else
++ io->speed = 0;
++
++ io->flags = 0;
++ if (ioctl & I365_IOCTL_16BIT(map))
++ io->flags |= MAP_16BIT;
++ if (ioctl & I365_IOCTL_IOCS16(map))
++ io->flags |= MAP_AUTOSZ;
++ if (ioctl & I365_IOCTL_0WS(map))
++ io->flags |= MAP_0WS;
++
++ addrwin = exca_read_byte(slot, I365_ADDRWIN);
++ if (addrwin & I365_ENA_IO(map))
++ io->flags |= MAP_ACTIVE;
++
++ return 0;
++}
++
++static int pccard_set_io_map(unsigned int slot, struct pccard_io_map *io)
++{
++ vrc4171_socket_t *socket;
++ uint8_t ioctl, addrwin;
++ u_char map;
++
++ if (slot >= CARD_MAX_SLOTS ||
++ io == NULL || io->map >= IO_MAX_MAPS ||
++ io->start > 0xffff || io->stop > 0xffff || io->start > io->stop)
++ return -EINVAL;
++
++ socket = &vrc4171_sockets[slot];
++ map = io->map;
++
++ addrwin = exca_read_byte(slot, I365_ADDRWIN);
++ if (addrwin & I365_ENA_IO(map)) {
++ addrwin &= ~I365_ENA_IO(map);
++ exca_write_byte(slot, I365_ADDRWIN, addrwin);
++ }
++
++ exca_write_word(slot, I365_IO(map)+I365_W_START, io->start);
++ exca_write_word(slot, I365_IO(map)+I365_W_STOP, io->stop);
++
++ ioctl = 0;
++ if (io->speed > 0)
++ ioctl |= I365_IOCTL_WAIT(map);
++ if (io->flags & MAP_16BIT)
++ ioctl |= I365_IOCTL_16BIT(map);
++ if (io->flags & MAP_AUTOSZ)
++ ioctl |= I365_IOCTL_IOCS16(map);
++ if (io->flags & MAP_0WS)
++ ioctl |= I365_IOCTL_0WS(map);
++ exca_write_byte(slot, I365_IOCTL, ioctl);
++
++ if (io->flags & MAP_ACTIVE) {
++ addrwin |= I365_ENA_IO(map);
++ exca_write_byte(slot, I365_ADDRWIN, addrwin);
++ }
++
++ return 0;
++}
++
++static int pccard_get_mem_map(unsigned int slot, struct pccard_mem_map *mem)
++{
++ vrc4171_socket_t *socket;
++ uint8_t addrwin;
++ u_long start, stop;
++ u_int offset;
++ u_char map;
++
++ if (slot >= CARD_MAX_SLOTS || mem == NULL || mem->map >= MEM_MAX_MAPS)
++ return -EINVAL;
++
++ socket = &vrc4171_sockets[slot];
++ map = mem->map;
++
++ mem->flags = 0;
++ mem->speed = 0;
++
++ addrwin = exca_read_byte(slot, I365_ADDRWIN);
++ if (addrwin & I365_ENA_MEM(map))
++ mem->flags |= MAP_ACTIVE;
++
++ start = exca_read_word(slot, I365_MEM(map)+I365_W_START);
++ if (start & I365_MEM_16BIT)
++ mem->flags |= MAP_16BIT;
++ mem->sys_start = (start & 0x3fffUL) << 12;
++
++ stop = exca_read_word(slot, I365_MEM(map)+I365_W_STOP);
++ if (start & I365_MEM_WS0)
++ mem->speed += 1;
++ if (start & I365_MEM_WS1)
++ mem->speed += 2;
++ mem->sys_stop = ((stop & 0x3fffUL) << 12) + 0xfffUL;
++
++ offset = exca_read_word(slot, I365_MEM(map)+I365_W_OFF);
++ if (offset & I365_MEM_REG)
++ mem->flags |= MAP_ATTRIB;
++ if (offset & I365_MEM_WRPROT)
++ mem->flags |= MAP_WRPROT;
++ mem->card_start = (offset & 0x3fffUL) << 12;
++
++ mem->sys_start += CARD_MEM_START;
++ mem->sys_stop += CARD_MEM_START;
++
++ return 0;
++}
++
++static int pccard_set_mem_map(unsigned int slot, struct pccard_mem_map *mem)
++{
++ vrc4171_socket_t *socket;
++ uint16_t start, stop, offset;
++ uint8_t addrwin;
++ u_char map;
++
++ if (slot >= CARD_MAX_SLOTS ||
++ mem == NULL || mem->map >= MEM_MAX_MAPS ||
++ mem->sys_start < CARD_MEM_START || mem->sys_start > CARD_MEM_END ||
++ mem->sys_stop < CARD_MEM_START || mem->sys_stop > CARD_MEM_END ||
++ mem->sys_start > mem->sys_stop ||
++ mem->card_start > CARD_MAX_MEM_OFFSET ||
++ mem->speed > CARD_MAX_MEM_SPEED)
++ return -EINVAL;
++
++ socket = &vrc4171_sockets[slot];
++ map = mem->map;
++
++ addrwin = exca_read_byte(slot, I365_ADDRWIN);
++ if (addrwin & I365_ENA_MEM(map)) {
++ addrwin &= ~I365_ENA_MEM(map);
++ exca_write_byte(slot, I365_ADDRWIN, addrwin);
++ }
++
++ start = (mem->sys_start >> 12) & 0x3fff;
++ if (mem->flags & MAP_16BIT)
++ start |= I365_MEM_16BIT;
++ exca_write_word(slot, I365_MEM(map)+I365_W_START, start);
++
++ stop = (mem->sys_stop >> 12) & 0x3fff;
++ switch (mem->speed) {
++ case 0:
++ break;
++ case 1:
++ stop |= I365_MEM_WS0;
++ break;
++ case 2:
++ stop |= I365_MEM_WS1;
++ break;
++ default:
++ stop |= I365_MEM_WS0 | I365_MEM_WS1;
++ break;
++ }
++ exca_write_word(slot, I365_MEM(map)+I365_W_STOP, stop);
++
++ offset = (mem->card_start >> 12) & 0x3fff;
++ if (mem->flags & MAP_ATTRIB)
++ offset |= I365_MEM_REG;
++ if (mem->flags & MAP_WRPROT)
++ offset |= I365_MEM_WRPROT;
++ exca_write_word(slot, I365_MEM(map)+I365_W_OFF, offset);
++
++ if (mem->flags & MAP_ACTIVE) {
++ addrwin |= I365_ENA_MEM(map);
++ exca_write_byte(slot, I365_ADDRWIN, addrwin);
++ }
++
++ return 0;
++}
++
++static void pccard_proc_setup(unsigned int slot, struct proc_dir_entry *base)
++{
++}
++
++static struct pccard_operations vrc4171_pccard_operations = {
++ .init = pccard_init,
++ .suspend = pccard_suspend,
++ .register_callback = pccard_register_callback,
++ .inquire_socket = pccard_inquire_socket,
++ .get_status = pccard_get_status,
++ .get_socket = pccard_get_socket,
++ .set_socket = pccard_set_socket,
++ .get_io_map = pccard_get_io_map,
++ .set_io_map = pccard_set_io_map,
++ .get_mem_map = pccard_get_mem_map,
++ .set_mem_map = pccard_set_mem_map,
++ .proc_setup = pccard_proc_setup,
++};
++
++static void pccard_bh(void *data)
++{
++ vrc4171_socket_t *socket = (vrc4171_socket_t *)data;
++ uint16_t events;
++
++ spin_lock_irq(&socket->event_lock);
++ events = socket->events;
++ socket->events = 0;
++ spin_unlock_irq(&socket->event_lock);
++
++ if (socket->handler)
++ socket->handler(socket->info, events);
++}
++
++static inline uint16_t get_events(int slot)
++{
++ uint16_t events = 0;
++ uint8_t status, csc;
++
++ status = exca_read_byte(slot, I365_STATUS);
++ csc = exca_read_byte(slot, I365_CSC);
++
++ if (exca_read_byte(slot, I365_INTCTL) & I365_PC_IOCARD) {
++ if ((csc & I365_CSC_STSCHG) && (status & I365_CS_STSCHG))
++ events |= SS_STSCHG;
++ } else {
++ if (csc & (I365_CSC_BVD1 | I365_CSC_BVD2)) {
++ if (!(status & I365_CS_BVD1))
++ events |= SS_BATDEAD;
++ else if ((status & (I365_CS_BVD1 | I365_CS_BVD2)) == I365_CS_BVD1)
++ events |= SS_BATWARN;
++ }
++ }
++ if ((csc & I365_CSC_READY) && (status & I365_CS_READY))
++ events |= SS_READY;
++ if ((csc & I365_CSC_DETECT) && ((status & I365_CS_DETECT) == I365_CS_DETECT))
++ events |= SS_DETECT;
++
++ return events;
++}
++
++static void pccard_status_change(int slot, vrc4171_socket_t *socket)
++{
++ uint16_t events;
++
++ socket->tq_task.routine = pccard_bh;
++ socket->tq_task.data = socket;
++
++ events = get_events(slot);
++ if (events) {
++ spin_lock(&socket->event_lock);
++ socket->events |= events;
++ spin_unlock(&socket->event_lock);
++ schedule_task(&socket->tq_task);
++ }
++}
++
++static void pccard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++ vrc4171_socket_t *socket;
++ uint16_t status;
++
++ status = vrc4171_get_irq_status();
++ if (status & IRQ_A) {
++ socket = &vrc4171_sockets[CARD_SLOTA];
++ if (socket->noprobe == SLOTB_PROBE) {
++ if (status & (1 << socket->csc_irq))
++ pccard_status_change(CARD_SLOTA, socket);
++ }
++ }
++
++ if (status & IRQ_B) {
++ socket = &vrc4171_sockets[CARD_SLOTB];
++ if (socket->noprobe == SLOTB_PROBE) {
++ if (status & (1 << socket->csc_irq))
++ pccard_status_change(CARD_SLOTB, socket);
++ }
++ }
++}
++
++static inline void reserve_using_irq(int slot)
++{
++ unsigned int irq;
++
++ irq = exca_read_byte(slot, I365_INTCTL);
++ irq &= 0x0f;
++ vrc4171_irq_mask &= ~(1 << irq);
++
++ irq = exca_read_byte(slot, I365_CSCINT);
++ irq = (irq & 0xf0) >> 4;
++ vrc4171_irq_mask &= ~(1 << irq);
++}
++
++static int __devinit vrc4171_add_socket(int slot)
++{
++ vrc4171_socket_t *socket;
++
++ if (slot >= CARD_MAX_SLOTS)
++ return -EINVAL;
++
++ socket = &vrc4171_sockets[slot];
++ if (socket->noprobe != SLOTB_PROBE) {
++ uint8_t addrwin;
++
++ switch (socket->noprobe) {
++ case SLOTB_NOPROBE_MEM:
++ addrwin = exca_read_byte(slot, I365_ADDRWIN);
++ addrwin &= 0x1f;
++ exca_write_byte(slot, I365_ADDRWIN, addrwin);
++ break;
++ case SLOTB_NOPROBE_IO:
++ addrwin = exca_read_byte(slot, I365_ADDRWIN);
++ addrwin &= 0xc0;
++ exca_write_byte(slot, I365_ADDRWIN, addrwin);
++ break;
++ default:
++ break;
++ }
++
++ reserve_using_irq(slot);
++
++ return 0;
++ }
++
++ sprintf(socket->name, "NEC VRC4171 Card Slot %1c", 'A' + slot);
++
++ socket->pcmcia_socket = pcmcia_register_socket(slot, &vrc4171_pccard_operations, 1);
++ if (socket->pcmcia_socket == NULL)
++ return -ENOMEM;
++
++ exca_write_byte(slot, I365_ADDRWIN, 0);
++
++ exca_write_byte(slot, GLOBAL_CONTROL, 0);
++
++ return 0;
++}
++
++static void vrc4171_remove_socket(int slot)
++{
++ vrc4171_socket_t *socket;
++
++ if (slot >= CARD_MAX_SLOTS)
++ return;
++
++ socket = &vrc4171_sockets[slot];
++
++ if (socket->pcmcia_socket != NULL) {
++ pcmcia_unregister_socket(socket->pcmcia_socket);
++ socket->pcmcia_socket = NULL;
++ }
++}
++
++static int __devinit vrc4171_card_setup(char *options)
++{
++ if (options == NULL || *options == '\0')
++ return 0;
++
++ if (strncmp(options, "irq:", 4) == 0) {
++ int irq;
++ options += 4;
++ irq = simple_strtoul(options, &options, 0);
++ if (irq >= 0 && irq < NR_IRQS)
++ vrc4171_irq = irq;
++
++ if (*options != ',')
++ return 0;
++ options++;
++ }
++
++ if (strncmp(options, "slota:", 6) == 0) {
++ options += 6;
++ if (*options != '\0') {
++ if (strncmp(options, "noprobe", 7) == 0) {
++ vrc4171_sockets[CARD_SLOTA].noprobe = 1;
++ options += 7;
++ }
++
++ if (*options != ',')
++ return 0;
++ options++;
++ } else
++ return 0;
++
++ }
++
++ if (strncmp(options, "slotb:", 6) == 0) {
++ options += 6;
++ if (*options != '\0') {
++ if (strncmp(options, "pccard", 6) == 0) {
++ vrc4171_slotb = SLOTB_IS_PCCARD;
++ options += 6;
++ } else if (strncmp(options, "cf", 2) == 0) {
++ vrc4171_slotb = SLOTB_IS_CF;
++ options += 2;
++ } else if (strncmp(options, "flashrom", 8) == 0) {
++ vrc4171_slotb = SLOTB_IS_FLASHROM;
++ options += 8;
++ } else if (strncmp(options, "none", 4) == 0) {
++ vrc4171_slotb = SLOTB_IS_NONE;
++ options += 4;
++ }
++
++ if (*options != ',')
++ return 0;
++ options++;
++
++ if ( strncmp(options, "memnoprobe", 10) == 0)
++ vrc4171_sockets[CARD_SLOTB].noprobe = SLOTB_NOPROBE_MEM;
++ if ( strncmp(options, "ionoprobe", 9) == 0)
++ vrc4171_sockets[CARD_SLOTB].noprobe = SLOTB_NOPROBE_IO;
++ if ( strncmp(options, "noprobe", 7) == 0)
++ vrc4171_sockets[CARD_SLOTB].noprobe = SLOTB_NOPROBE_ALL;
++ }
++ }
++
++ return 0;
++}
++
++__setup("vrc4171_card=", vrc4171_card_setup);
++
++static int __devinit vrc4171_card_init(void)
++{
++ int retval, slot;
++
++ vrc4171_set_multifunction_pin(vrc4171_slotb);
++
++ if (request_region(CARD_CONTROLLER_INDEX, CARD_CONTROLLER_SIZE,
++ "NEC VRC4171 Card Controller") == NULL)
++ return -EBUSY;
++
++ for (slot = 0; slot < CARD_MAX_SLOTS; slot++) {
++ if (slot == CARD_SLOTB && vrc4171_slotb == SLOTB_IS_NONE)
++ break;
++
++ retval = vrc4171_add_socket(slot);
++ if (retval != 0)
++ return retval;
++ }
++
++ retval = request_irq(vrc4171_irq, pccard_interrupt, SA_SHIRQ,
++ "NEC VRC4171 Card Controller", vrc4171_sockets);
++ if (retval < 0) {
++ for (slot = 0; slot < CARD_MAX_SLOTS; slot++)
++ vrc4171_remove_socket(slot);
++
++ return retval;
++ }
++
++ printk(KERN_INFO "NEC VRC4171 Card Controller, connected to IRQ %d\n", vrc4171_irq);
++
++ return 0;
++}
++
++static void __devexit vrc4171_card_exit(void)
++{
++ int slot;
++
++ for (slot = 0; slot < CARD_MAX_SLOTS; slot++)
++ vrc4171_remove_socket(slot);
++
++ release_region(CARD_CONTROLLER_INDEX, CARD_CONTROLLER_SIZE);
++}
++
++module_init(vrc4171_card_init);
++module_exit(vrc4171_card_exit);
+diff -Nur linux-2.4.32-rc1/drivers/scsi/NCR53C9x.h linux-2.4.32-rc1.mips/drivers/scsi/NCR53C9x.h
+--- linux-2.4.32-rc1/drivers/scsi/NCR53C9x.h 2004-02-18 14:36:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/scsi/NCR53C9x.h 2003-12-15 19:19:51.000000000 +0100
+@@ -144,12 +144,7 @@
+
+ #ifndef MULTIPLE_PAD_SIZES
+
+-#ifdef CONFIG_CPU_HAS_WB
+-#include <asm/wbflush.h>
+-#define esp_write(__reg, __val) do{(__reg) = (__val); wbflush();} while(0)
+-#else
+-#define esp_write(__reg, __val) ((__reg) = (__val))
+-#endif
++#define esp_write(__reg, __val) do{(__reg) = (__val); iob();} while(0)
+ #define esp_read(__reg) (__reg)
+
+ struct ESP_regs {
+diff -Nur linux-2.4.32-rc1/drivers/sound/au1550_i2s.c linux-2.4.32-rc1.mips/drivers/sound/au1550_i2s.c
+--- linux-2.4.32-rc1/drivers/sound/au1550_i2s.c 2005-01-19 15:10:04.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/sound/au1550_i2s.c 2005-02-08 08:07:50.000000000 +0100
+@@ -41,6 +41,7 @@
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
++
+ #include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/string.h>
+@@ -62,7 +63,45 @@
+ #include <asm/uaccess.h>
+ #include <asm/hardirq.h>
+ #include <asm/au1000.h>
++
++#if defined(CONFIG_SOC_AU1550)
+ #include <asm/pb1550.h>
++#endif
++
++#if defined(CONFIG_MIPS_PB1200)
++#define WM8731
++#define WM_MODE_USB
++#include <asm/pb1200.h>
++#endif
++
++#if defined(CONFIG_MIPS_FICMMP)
++#define WM8721
++#define WM_MODE_NORMAL
++#include <asm/ficmmp.h>
++#endif
++
++
++#define WM_VOLUME_MIN 47
++#define WM_VOLUME_SCALE 80
++
++#if defined(WM8731)
++ /* OSS interface to the wm i2s.. */
++ #define CODEC_NAME "Wolfson WM8731 I2S"
++ #define WM_I2S_STEREO_MASK (SOUND_MASK_PCM | SOUND_MASK_LINE)
++ #define WM_I2S_SUPPORTED_MASK (WM_I2S_STEREO_MASK | SOUND_MASK_MIC)
++ #define WM_I2S_RECORD_MASK (SOUND_MASK_MIC | SOUND_MASK_LINE1 | SOUND_MASK_LINE)
++#elif defined(WM8721)
++ #define CODEC_NAME "Wolfson WM8721 I2S"
++ #define WM_I2S_STEREO_MASK (SOUND_MASK_PCM)
++ #define WM_I2S_SUPPORTED_MASK (WM_I2S_STEREO_MASK)
++ #define WM_I2S_RECORD_MASK (0)
++#endif
++
++
++#define supported_mixer(FOO) ((FOO >= 0) && \
++ (FOO < SOUND_MIXER_NRDEVICES) && \
++ WM_I2S_SUPPORTED_MASK & (1<<FOO) )
++
+ #include <asm/au1xxx_psc.h>
+ #include <asm/au1xxx_dbdma.h>
+
+@@ -98,13 +137,51 @@
+ * 0 = no VRA, 1 = use VRA if codec supports it
+ * The framework is here, but we currently force no VRA.
+ */
++#if defined(CONFIG_MIPS_PB1200) | defined(CONFIG_MIPS_PB1550)
+ static int vra = 0;
++#elif defined(CONFIG_MIPS_FICMMP)
++static int vra = 1;
++#endif
++
++#define WM_REG_L_HEADPHONE_OUT 0x02
++#define WM_REG_R_HEADPHONE_OUT 0x03
++#define WM_REG_ANALOGUE_AUDIO_PATH_CTRL 0x04
++#define WM_REG_DIGITAL_AUDIO_PATH_CTRL 0x05
++#define WM_REG_POWER_DOWN_CTRL 0x06
++#define WM_REG_DIGITAL_AUDIO_IF 0x07
++#define WM_REG_SAMPLING_CONTROL 0x08
++#define WM_REG_ACTIVE_CTRL 0x09
++#define WM_REG_RESET 0x0F
++#define WM_SC_SR_96000 (0x7<<2)
++#define WM_SC_SR_88200 (0xF<<2)
++#define WM_SC_SR_48000 (0x0<<2)
++#define WM_SC_SR_44100 (0x8<<2)
++#define WM_SC_SR_32000 (0x6<<2)
++#define WM_SC_SR_8018 (0x9<<2)
++#define WM_SC_SR_8000 (0x1<<2)
++#define WM_SC_MODE_USB 1
++#define WM_SC_MODE_NORMAL 0
++#define WM_SC_BOSR_250FS (0<<1)
++#define WM_SC_BOSR_272FS (1<<1)
++#define WM_SC_BOSR_256FS (0<<1)
++#define WM_SC_BOSR_128FS (0<<1)
++#define WM_SC_BOSR_384FS (1<<1)
++#define WM_SC_BOSR_192FS (1<<1)
++
++#define WS_64FS 31
++#define WS_96FS 47
++#define WS_128FS 63
++#define WS_192FS 95
++
++#define MIN_Q_COUNT 2
++
+ MODULE_PARM(vra, "i");
+ MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it");
+
+ static struct au1550_state {
+ /* soundcore stuff */
+ int dev_audio;
++ int dev_mixer;
+
+ spinlock_t lock;
+ struct semaphore open_sem;
+@@ -114,6 +191,11 @@
+ int no_vra;
+ volatile psc_i2s_t *psc_addr;
+
++ int level_line;
++ int level_mic;
++ int level_left;
++ int level_right;
++
+ struct dmabuf {
+ u32 dmanr;
+ unsigned sample_rate;
+@@ -195,60 +277,224 @@
+ }
+ }
+
+-/* Just a place holder. The Wolfson codec is a write only device,
+- * so we would have to keep a local copy of the data.
+- */
+-#if 0
+-static u8
+-rdcodec(u8 addr)
+-{
+- return 0 /* data */;
+-}
+-#endif
+-
+-
+ static void
+-wrcodec(u8 ctlreg, u8 val)
++wrcodec(u8 ctlreg, u16 val)
+ {
+ int rcnt;
+ extern int pb1550_wm_codec_write(u8 addr, u8 reg, u8 val);
+-
+ /* The codec is a write only device, with a 16-bit control/data
+ * word. Although it is written as two bytes on the I2C, the
+ * format is actually 7 bits of register and 9 bits of data.
+ * The ls bit of the first byte is the ms bit of the data.
+ */
+ rcnt = 0;
+- while ((pb1550_wm_codec_write((0x36 >> 1), ctlreg, val) != 1)
+- && (rcnt < 50)) {
++ while ((pb1550_wm_codec_write((0x36 >> 1),
++ (ctlreg << 1) | ((val >> 8) & 0x01),
++ (u8) (val & 0x00FF)) != 1) &&
++ (rcnt < 50)) {
+ rcnt++;
+-#if 0
+- printk("Codec write retry %02x %02x\n", ctlreg, val);
+-#endif
+ }
++
++ au1550_delay(10);
++}
++
++static int
++au1550_open_mixdev(struct inode *inode, struct file *file)
++{
++ file->private_data = &au1550_state;
++ return 0;
++}
++
++static int
++au1550_release_mixdev(struct inode *inode, struct file *file)
++{
++ return 0;
++}
++
++static int wm_i2s_read_mixer(struct au1550_state *s, int oss_channel)
++{
++ int ret = 0;
++
++ if (WM_I2S_STEREO_MASK & (1 << oss_channel)) {
++ /* nice stereo mixers .. */
++
++ ret = s->level_left | (s->level_right << 8);
++ } else if (oss_channel == SOUND_MIXER_MIC) {
++ ret = 0;
++ /* TODO: Implement read mixer for input/output codecs */
++ }
++
++ return ret;
+ }
+
++static void wm_i2s_write_mixer(struct au1550_state *s, int oss_channel, unsigned int left, unsigned int right)
++{
++ if (WM_I2S_STEREO_MASK & (1 << oss_channel)) {
++ /* stereo mixers */
++ s->level_left = left;
++ s->level_right = right;
++
++ right = (right * WM_VOLUME_SCALE) / 100;
++ left = (left * WM_VOLUME_SCALE) / 100;
++ if (right > WM_VOLUME_SCALE)
++ right = WM_VOLUME_SCALE;
++ if (left > WM_VOLUME_SCALE)
++ left = WM_VOLUME_SCALE;
++
++ right += WM_VOLUME_MIN;
++ left += WM_VOLUME_MIN;
++
++ wrcodec(WM_REG_L_HEADPHONE_OUT, left);
++ wrcodec(WM_REG_R_HEADPHONE_OUT, right);
++
++ }else if (oss_channel == SOUND_MIXER_MIC) {
++ /* TODO: implement write mixer for input/output codecs */
++ }
++}
++
++/* a thin wrapper for write_mixer */
++static void wm_i2s_set_mixer(struct au1550_state *s, unsigned int oss_mixer, unsigned int val )
++{
++ unsigned int left,right;
++
++ /* cleanse input a little */
++ right = ((val >> 8) & 0xff) ;
++ left = (val & 0xff) ;
++
++ if (right > 100) right = 100;
++ if (left > 100) left = 100;
++
++ wm_i2s_write_mixer(s, oss_mixer, left, right);
++}
++
++static int
++au1550_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
++{
++ struct au1550_state *s = (struct au1550_state *)file->private_data;
++
++ int i, val = 0;
++
++ if (cmd == SOUND_MIXER_INFO) {
++ mixer_info info;
++ strncpy(info.id, CODEC_NAME, sizeof(info.id));
++ strncpy(info.name, CODEC_NAME, sizeof(info.name));
++ info.modify_counter = 0;
++ if (copy_to_user((void *)arg, &info, sizeof(info)))
++ return -EFAULT;
++ return 0;
++ }
++ if (cmd == SOUND_OLD_MIXER_INFO) {
++ _old_mixer_info info;
++ strncpy(info.id, CODEC_NAME, sizeof(info.id));
++ strncpy(info.name, CODEC_NAME, sizeof(info.name));
++ if (copy_to_user((void *)arg, &info, sizeof(info)))
++ return -EFAULT;
++ return 0;
++ }
++
++ if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int))
++ return -EINVAL;
++
++ if (cmd == OSS_GETVERSION)
++ return put_user(SOUND_VERSION, (int *)arg);
++
++ if (_SIOC_DIR(cmd) == _SIOC_READ) {
++ switch (_IOC_NR(cmd)) {
++ case SOUND_MIXER_RECSRC: /* give them the current record src */
++ val = 0;
++ /*
++ if (!codec->recmask_io) {
++ val = 0;
++ } else {
++ val = codec->recmask_io(codec, 1, 0);
++ }*/
++ break;
++
++ case SOUND_MIXER_DEVMASK: /* give them the supported mixers */
++ val = WM_I2S_SUPPORTED_MASK;
++ break;
++
++ case SOUND_MIXER_RECMASK:
++ /* Arg contains a bit for each supported recording
++ * source */
++ val = WM_I2S_RECORD_MASK;
++ break;
++
++ case SOUND_MIXER_STEREODEVS:
++ /* Mixer channels supporting stereo */
++ val = WM_I2S_STEREO_MASK;
++ break;
++
++ case SOUND_MIXER_CAPS:
++ val = SOUND_CAP_EXCL_INPUT;
++ break;
++
++ default: /* read a specific mixer */
++ i = _IOC_NR(cmd);
++
++ if (!supported_mixer(i))
++ return -EINVAL;
++
++ val = wm_i2s_read_mixer(s, i);
++ break;
++ }
++ return put_user(val, (int *)arg);
++ }
++
++ if (_SIOC_DIR(cmd) == (_SIOC_WRITE|_SIOC_READ)) {
++ if (get_user(val, (int *)arg))
++ return -EFAULT;
++
++ switch (_IOC_NR(cmd)) {
++ case SOUND_MIXER_RECSRC:
++ /* Arg contains a bit for each recording source */
++ if (!WM_I2S_RECORD_MASK)
++ return -EINVAL;
++ if (!val)
++ return 0;
++ if (!(val &= WM_I2S_RECORD_MASK))
++ return -EINVAL;
++
++ return 0;
++ default: /* write a specific mixer */
++ i = _IOC_NR(cmd);
++
++ if (!supported_mixer(i))
++ return -EINVAL;
++
++ wm_i2s_set_mixer(s, i, val);
++
++ return 0;
++ }
++}
++ return -EINVAL;
++}
++
++static loff_t
++au1550_llseek(struct file *file, loff_t offset, int origin)
++{
++ return -ESPIPE;
++}
++
++static /*const */ struct file_operations au1550_mixer_fops = {
++ owner:THIS_MODULE,
++ llseek:au1550_llseek,
++ ioctl:au1550_ioctl_mixdev,
++ open:au1550_open_mixdev,
++ release:au1550_release_mixdev,
++};
++
+ void
+-codec_init(void)
++codec_init(struct au1550_state *s)
+ {
+- wrcodec(0x1e, 0x00); /* Reset */
+- au1550_delay(200);
+- wrcodec(0x0c, 0x00); /* Power up everything */
+- au1550_delay(10);
+- wrcodec(0x12, 0x00); /* Deactivate codec */
+- au1550_delay(10);
+- wrcodec(0x08, 0x10); /* Select DAC outputs to line out */
+- au1550_delay(10);
+- wrcodec(0x0a, 0x00); /* Disable output mute */
+- au1550_delay(10);
+- wrcodec(0x05, 0x70); /* lower output volume on headphone */
+- au1550_delay(10);
+- wrcodec(0x0e, 0x02); /* Set slave, 16-bit, I2S modes */
+- au1550_delay(10);
+- wrcodec(0x10, 0x01); /* 12MHz (USB), 250fs */
+- au1550_delay(10);
+- wrcodec(0x12, 0x01); /* Activate codec */
+- au1550_delay(10);
++ wrcodec(WM_REG_RESET, 0x00); /* Reset */
++ wrcodec(WM_REG_POWER_DOWN_CTRL, 0x00); /* Power up everything */
++ wrcodec(WM_REG_ACTIVE_CTRL, 0x00); /* Deactivate codec */
++ wrcodec(WM_REG_ANALOGUE_AUDIO_PATH_CTRL, 0x10); /* Select DAC outputs to line out */
++ wrcodec(WM_REG_DIGITAL_AUDIO_PATH_CTRL, 0x00); /* Disable output mute */
++ wm_i2s_write_mixer(s, SOUND_MIXER_PCM, 74, 74);
++ wrcodec(WM_REG_DIGITAL_AUDIO_IF, 0x02); /* Set slave, 16-bit, I2S modes */
++ wrcodec(WM_REG_ACTIVE_CTRL, 0x01); /* Activate codec */
+ }
+
+ /* stop the ADC before calling */
+@@ -256,27 +502,16 @@
+ set_adc_rate(struct au1550_state *s, unsigned rate)
+ {
+ struct dmabuf *adc = &s->dma_adc;
+- struct dmabuf *dac = &s->dma_dac;
+
+- if (s->no_vra) {
+- /* calc SRC factor
+- */
++ #if defined(WM_MODE_USB)
+ adc->src_factor = (((SAMP_RATE*2) / rate) + 1) >> 1;
+ adc->sample_rate = SAMP_RATE / adc->src_factor;
+ return;
+- }
++ #else
++ //TODO: Need code for normal mode
++ #endif
+
+ adc->src_factor = 1;
+-
+-
+-#if 0
+- rate = rate > SAMP_RATE ? SAMP_RATE : rate;
+-
+- wrcodec(0, 0); /* I don't yet know what to write here if we vra */
+-
+- adc->sample_rate = rate;
+- dac->sample_rate = rate;
+-#endif
+ }
+
+ /* stop the DAC before calling */
+@@ -284,26 +519,89 @@
+ set_dac_rate(struct au1550_state *s, unsigned rate)
+ {
+ struct dmabuf *dac = &s->dma_dac;
+- struct dmabuf *adc = &s->dma_adc;
+
+- if (s->no_vra) {
+- /* calc SRC factor
+- */
+- dac->src_factor = (((SAMP_RATE*2) / rate) + 1) >> 1;
+- dac->sample_rate = SAMP_RATE / dac->src_factor;
+- return;
++ u16 sr, ws, div, bosr, mode;
++ volatile psc_i2s_t* ip = (volatile psc_i2s_t *)I2S_PSC_BASE;
++ u32 cfg;
++
++ #if defined(CONFIG_MIPS_FICMMP)
++ rate = ficmmp_set_i2s_sample_rate(rate);
++ #endif
++
++ switch(rate)
++ {
++ case 96000:
++ sr = WM_SC_SR_96000;
++ ws = WS_64FS;
++ div = PSC_I2SCFG_DIV2;
++ break;
++ case 88200:
++ sr = WM_SC_SR_88200;
++ ws = WS_64FS;
++ div = PSC_I2SCFG_DIV2;
++ break;
++ case 44100:
++ sr = WM_SC_SR_44100;
++ ws = WS_128FS;
++ div = PSC_I2SCFG_DIV2;
++ break;
++ case 48000:
++ sr = WM_SC_SR_48000;
++ ws = WS_128FS;
++ div = PSC_I2SCFG_DIV2;
++ break;
++ case 32000:
++ sr = WM_SC_SR_32000;
++ ws = WS_96FS;
++ div = PSC_I2SCFG_DIV4;
++ break;
++ case 8018:
++ sr = WM_SC_SR_8018;
++ ws = WS_128FS;
++ div = PSC_I2SCFG_DIV2;
++ break;
++ case 8000:
++ default:
++ sr = WM_SC_SR_8000;
++ ws = WS_96FS;
++ div = PSC_I2SCFG_DIV16;
++ break;
+ }
+
++ #if defined(WM_MODE_USB)
++ mode = WM_SC_MODE_USB;
++ #else
++ mode = WM_SC_MODE_NORMAL;
++ #endif
++
++ bosr = 0;
++
+ dac->src_factor = 1;
++ dac->sample_rate = rate;
+
+-#if 0
+- rate = rate > SAMP_RATE ? SAMP_RATE : rate;
++ /* Deactivate codec */
++ wrcodec(WM_REG_ACTIVE_CTRL, 0x00);
+
+- wrcodec(0, 0); /* I don't yet know what to write here if we vra */
++ /* Disable I2S controller */
++ ip->psc_i2scfg &= ~PSC_I2SCFG_DE_ENABLE;
++ /* Wait for device disabled */
++ while ((ip->psc_i2sstat & PSC_I2SSTAT_DR) == 1);
++
++ cfg = ip->psc_i2scfg;
++ /* Clear WS and DIVIDER values */
++ cfg &= ~(PSC_I2SCFG_WS_MASK | PSC_I2SCFG_DIV_MASK);
++ cfg |= PSC_I2SCFG_WS(ws) | div;
++ /* Reconfigure and enable */
++ ip->psc_i2scfg = cfg | PSC_I2SCFG_DE_ENABLE;
+
+- adc->sample_rate = rate;
+- dac->sample_rate = rate;
+-#endif
++ /* Wait for device enabled */
++ while ((ip->psc_i2sstat & PSC_I2SSTAT_DR) == 0);
++
++ /* Set appropriate sampling rate */
++ wrcodec(WM_REG_SAMPLING_CONTROL, bosr | mode | sr);
++
++ /* Activate codec */
++ wrcodec(WM_REG_ACTIVE_CTRL, 0x01);
+ }
+
+ static void
+@@ -354,8 +652,7 @@
+ ip->psc_i2spcr = PSC_I2SPCR_RP;
+ au_sync();
+
+- /* Wait for Receive Busy to show disabled.
+- */
++ /* Wait for Receive Busy to show disabled. */
+ do {
+ stat = ip->psc_i2sstat;
+ au_sync();
+@@ -463,7 +760,6 @@
+ if (db->num_channels == 1)
+ db->cnt_factor *= 2;
+ db->cnt_factor *= db->src_factor;
+-
+ db->count = 0;
+ db->dma_qcount = 0;
+ db->nextIn = db->nextOut = db->rawbuf;
+@@ -546,12 +842,13 @@
+ if (i2s_stat & (PSC_I2SSTAT_TF | PSC_I2SSTAT_TR | PSC_I2SSTAT_TF))
+ dbg("I2S status = 0x%08x", i2s_stat);
+ #endif
++
+ db->dma_qcount--;
+
+ if (db->count >= db->fragsize) {
+- if (au1xxx_dbdma_put_source(db->dmanr, db->nextOut,
+- db->fragsize) == 0) {
+- err("qcount < 2 and no ring room!");
++ if (au1xxx_dbdma_put_source(db->dmanr, db->nextOut, db->fragsize) == 0)
++ {
++ err("qcount < MIN_Q_COUNT and no ring room!");
+ }
+ db->nextOut += db->fragsize;
+ if (db->nextOut >= db->rawbuf + db->dmasize)
+@@ -606,65 +903,43 @@
+
+ }
+
+-static loff_t
+-au1550_llseek(struct file *file, loff_t offset, int origin)
+-{
+- return -ESPIPE;
+-}
+-
+-
+-#if 0
+-static int
+-au1550_open_mixdev(struct inode *inode, struct file *file)
+-{
+- file->private_data = &au1550_state;
+- return 0;
+-}
+-
+-static int
+-au1550_release_mixdev(struct inode *inode, struct file *file)
+-{
+- return 0;
+-}
+-
+-static int
+-mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd,
+- unsigned long arg)
+-{
+- return codec->mixer_ioctl(codec, cmd, arg);
+-}
+-
+-static int
+-au1550_ioctl_mixdev(struct inode *inode, struct file *file,
+- unsigned int cmd, unsigned long arg)
+-{
+- struct au1550_state *s = (struct au1550_state *)file->private_data;
+- struct ac97_codec *codec = s->codec;
+-
+- return mixdev_ioctl(codec, cmd, arg);
+-}
+-
+-static /*const */ struct file_operations au1550_mixer_fops = {
+- owner:THIS_MODULE,
+- llseek:au1550_llseek,
+- ioctl:au1550_ioctl_mixdev,
+- open:au1550_open_mixdev,
+- release:au1550_release_mixdev,
+-};
+-#endif
+-
+ static int
+ drain_dac(struct au1550_state *s, int nonblock)
+ {
+ unsigned long flags;
+ int count, tmo;
+
++ struct dmabuf *db = &s->dma_dac;
++
++ //DPRINTF();
+ if (s->dma_dac.mapped || !s->dma_dac.ready || s->dma_dac.stopped)
+ return 0;
+
+ for (;;) {
+ spin_lock_irqsave(&s->lock, flags);
+- count = s->dma_dac.count;
++ count = db->count;
++
++ /* Pad the ddma buffer with zeros if the amount remaining
++ * is not a multiple of fragsize */
++ if(count % db->fragsize != 0)
++ {
++ int pad = db->fragsize - (count % db->fragsize);
++ char* bufptr = db->nextIn;
++ char* bufend = db->rawbuf + db->dmasize;
++
++ if((bufend - bufptr) < pad)
++ printk("Error! ddma padding is bigger than available ring space!\n");
++ else
++ {
++ memset((void*)bufptr, 0, pad);
++ count += pad;
++ db->nextIn += pad;
++ db->count += pad;
++ if (db->dma_qcount == 0)
++ start_dac(s);
++ db->dma_qcount++;
++ }
++ }
+ spin_unlock_irqrestore(&s->lock, flags);
+ if (count <= 0)
+ break;
+@@ -672,9 +947,9 @@
+ break;
+ if (nonblock)
+ return -EBUSY;
+- tmo = 1000 * count / (s->no_vra ?
+- SAMP_RATE : s->dma_dac.sample_rate);
++ tmo = 1000 * count / s->dma_dac.sample_rate;
+ tmo /= s->dma_dac.dma_bytes_per_sample;
++
+ au1550_delay(tmo);
+ }
+ if (signal_pending(current))
+@@ -698,8 +973,7 @@
+ * If interpolating (no VRA), duplicate every audio frame src_factor times.
+ */
+ static int
+-translate_from_user(struct dmabuf *db, char* dmabuf, char* userbuf,
+- int dmacount)
++translate_from_user(struct dmabuf *db, char* dmabuf, char* userbuf, int dmacount)
+ {
+ int sample, i;
+ int interp_bytes_per_sample;
+@@ -737,11 +1011,12 @@
+
+ /* duplicate every audio frame src_factor times
+ */
+- for (i = 0; i < db->src_factor; i++)
++ for (i = 0; i < db->src_factor; i++) {
+ memcpy(dmabuf, dmasample, db->dma_bytes_per_sample);
++ dmabuf += interp_bytes_per_sample;
++ }
+
+ userbuf += db->user_bytes_per_sample;
+- dmabuf += interp_bytes_per_sample;
+ }
+
+ return num_samples * interp_bytes_per_sample;
+@@ -996,15 +1271,14 @@
+ * on the dma queue. If the queue count reaches zero,
+ * we know the dma has stopped.
+ */
+- while ((db->dma_qcount < 2) && (db->count >= db->fragsize)) {
++ while ((db->dma_qcount < MIN_Q_COUNT) && (db->count >= db->fragsize)) {
+ if (au1xxx_dbdma_put_source(db->dmanr, db->nextOut,
+ db->fragsize) == 0) {
+- err("qcount < 2 and no ring room!");
++ err("qcount < MIN_Q_COUNT and no ring room!");
+ }
+ db->nextOut += db->fragsize;
+ if (db->nextOut >= db->rawbuf + db->dmasize)
+ db->nextOut -= db->dmasize;
+- db->count -= db->fragsize;
+ db->total_bytes += db->dma_fragsize;
+ if (db->dma_qcount == 0)
+ start_dac(s);
+@@ -1017,7 +1291,6 @@
+ buffer += usercnt;
+ ret += usercnt;
+ } /* while (count > 0) */
+-
+ out:
+ up(&s->sem);
+ out2:
+@@ -1371,9 +1644,6 @@
+ s->dma_dac.cnt_factor;
+ abinfo.fragstotal = s->dma_dac.numfrag;
+ abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;
+-#ifdef AU1000_VERBOSE_DEBUG
+- dbg("bytes=%d, fragments=%d", abinfo.bytes, abinfo.fragments);
+-#endif
+ return copy_to_user((void *) arg, &abinfo,
+ sizeof(abinfo)) ? -EFAULT : 0;
+
+@@ -1536,13 +1806,9 @@
+ case SNDCTL_DSP_SETSYNCRO:
+ case SOUND_PCM_READ_FILTER:
+ return -EINVAL;
++ default: break;
+ }
+-
+-#if 0
+- return mixdev_ioctl(s->codec, cmd, arg);
+-#else
+ return 0;
+-#endif
+ }
+
+
+@@ -1664,15 +1930,15 @@
+ MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com");
+ MODULE_DESCRIPTION("Au1550 Audio Driver");
+
++#if defined(WM_MODE_USB)
+ /* Set up an internal clock for the PSC3. This will then get
+ * driven out of the Au1550 as the master.
+ */
+ static void
+ intclk_setup(void)
+ {
+- uint clk, rate, stat;
+-
+- /* Wire up Freq4 as a clock for the PSC3.
++ uint clk, rate;
++ /* Wire up Freq4 as a clock for the PSC.
+ * We know SMBus uses Freq3.
+ * By making changes to this rate, plus the word strobe
+ * size, we can make fine adjustments to the actual data rate.
+@@ -1700,11 +1966,17 @@
+ */
+ clk = au_readl(SYS_CLKSRC);
+ au_sync();
++#if defined(CONFIG_SOC_AU1550)
+ clk &= ~0x01f00000;
+ clk |= (6 << 22);
++#elif defined(CONFIG_SOC_AU1200)
++ clk &= ~0x3e000000;
++ clk |= (6 << 27);
++#endif
+ au_writel(clk, SYS_CLKSRC);
+ au_sync();
+ }
++#endif
+
+ static int __devinit
+ au1550_probe(void)
+@@ -1724,6 +1996,11 @@
+ init_MUTEX(&s->open_sem);
+ spin_lock_init(&s->lock);
+
++ /* CPLD Mux for I2s */
++
++#if defined(CONFIG_MIPS_PB1200)
++ bcsr->resets |= BCSR_RESETS_PCS1MUX;
++#endif
+
+ s->psc_addr = (volatile psc_i2s_t *)I2S_PSC_BASE;
+ ip = s->psc_addr;
+@@ -1765,9 +2042,8 @@
+
+ if ((s->dev_audio = register_sound_dsp(&au1550_audio_fops, -1)) < 0)
+ goto err_dev1;
+-#if 0
+- if ((s->codec->dev_mixer =
+- register_sound_mixer(&au1550_mixer_fops, -1)) < 0)
++#if 1
++ if ((s->dev_mixer = register_sound_mixer(&au1550_mixer_fops, -1)) < 0)
+ goto err_dev2;
+ #endif
+
+@@ -1777,7 +2053,6 @@
+ proc_au1550_dump, NULL);
+ #endif /* AU1550_DEBUG */
+
+- intclk_setup();
+
+ /* The GPIO for the appropriate PSC was configured by the
+ * board specific start up.
+@@ -1786,7 +2061,12 @@
+ */
+ ip->psc_ctrl = PSC_CTRL_DISABLE; /* Disable PSC */
+ au_sync();
++#if defined(WM_MODE_USB)
++ intclk_setup();
+ ip->psc_sel = (PSC_SEL_CLK_INTCLK | PSC_SEL_PS_I2SMODE);
++#else
++ ip->psc_sel = (PSC_SEL_CLK_EXTCLK | PSC_SEL_PS_I2SMODE);
++#endif
+ au_sync();
+
+ /* Enable PSC
+@@ -1806,42 +2086,18 @@
+ * Actual I2S mode (first bit delayed by one clock).
+ * Master mode (We provide the clock from the PSC).
+ */
+- val = PSC_I2SCFG_SET_LEN(16);
+-#ifdef TRY_441KHz
+- /* This really should be 250, but it appears that all of the
+- * PLLs, dividers and so on in the chain shift it. That's the
+- * problem with sourceing the clock instead of letting the very
+- * stable codec provide it. But, the PSC doesn't appear to want
+- * to work in slave mode, so this is what we get. It's not
+- * studio quality timing, but it's good enough for listening
+- * to mp3s.
+- */
+- val |= PSC_I2SCFG_SET_WS(252);
+-#else
+- val |= PSC_I2SCFG_SET_WS(250);
+-#endif
+- val |= PSC_I2SCFG_RT_FIFO8 | PSC_I2SCFG_TT_FIFO8 | \
++
++ val = PSC_I2SCFG_SET_LEN(16) | PSC_I2SCFG_WS(WS_128FS) | PSC_I2SCFG_RT_FIFO8 | PSC_I2SCFG_TT_FIFO8 | \
+ PSC_I2SCFG_BI | PSC_I2SCFG_XM;
+
+- ip->psc_i2scfg = val;
+- au_sync();
+- val |= PSC_I2SCFG_DE_ENABLE;
+- ip->psc_i2scfg = val;
+- au_sync();
++ ip->psc_i2scfg = val | PSC_I2SCFG_DE_ENABLE;
+
+- /* Wait for Device ready.
+- */
+- do {
+- val = ip->psc_i2sstat;
+- au_sync();
+- } while ((val & PSC_I2SSTAT_DR) == 0);
++ set_dac_rate(s, 8000); //Set default rate
+
+- val = ip->psc_i2scfg;
+- au_sync();
++ codec_init(s);
+
+- codec_init();
++ s->no_vra = vra ? 0 : 1;
+
+- s->no_vra = 1;
+ if (s->no_vra)
+ info("no VRA, interpolating and decimating");
+
+@@ -1866,6 +2122,8 @@
+ err_dev2:
+ unregister_sound_dsp(s->dev_audio);
+ #endif
++ err_dev2:
++ unregister_sound_dsp(s->dev_audio);
+ err_dev1:
+ au1xxx_dbdma_chan_free(s->dma_adc.dmanr);
+ err_dma2:
+diff -Nur linux-2.4.32-rc1/drivers/sound/au1550_psc.c linux-2.4.32-rc1.mips/drivers/sound/au1550_psc.c
+--- linux-2.4.32-rc1/drivers/sound/au1550_psc.c 2005-01-19 15:10:04.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/sound/au1550_psc.c 2005-01-30 09:01:28.000000000 +0100
+@@ -30,6 +30,7 @@
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
++
+ #include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/string.h>
+@@ -63,6 +64,14 @@
+ #include <asm/db1x00.h>
+ #endif
+
++#ifdef CONFIG_MIPS_PB1200
++#include <asm/pb1200.h>
++#endif
++
++#ifdef CONFIG_MIPS_DB1200
++#include <asm/db1200.h>
++#endif
++
+ #undef OSS_DOCUMENTED_MIXER_SEMANTICS
+
+ #define AU1550_MODULE_NAME "Au1550 psc audio"
+@@ -521,7 +530,14 @@
+ spin_unlock_irqrestore(&s->lock, flags);
+ }
+
+-
++/*
++ NOTE: The xmit slots cannot be changed on the fly when in full-duplex
++ because the AC'97 block must be stopped/started. When using this driver
++ in full-duplex (in & out at the same time), the DMA engine will stop if
++ you disable the block.
++ TODO: change implementation to properly restart adc/dac after setting
++ xmit slots.
++*/
+ static void
+ set_xmit_slots(int num_channels)
+ {
+@@ -565,6 +581,14 @@
+ } while ((stat & PSC_AC97STAT_DR) == 0);
+ }
+
++/*
++ NOTE: The recv slots cannot be changed on the fly when in full-duplex
++ because the AC'97 block must be stopped/started. When using this driver
++ in full-duplex (in & out at the same time), the DMA engine will stop if
++ you disable the block.
++ TODO: change implementation to properly restart adc/dac after setting
++ recv slots.
++*/
+ static void
+ set_recv_slots(int num_channels)
+ {
+@@ -608,7 +632,6 @@
+
+ spin_lock_irqsave(&s->lock, flags);
+
+- set_xmit_slots(db->num_channels);
+ au_writel(PSC_AC97PCR_TC, PSC_AC97PCR);
+ au_sync();
+ au_writel(PSC_AC97PCR_TS, PSC_AC97PCR);
+@@ -640,7 +663,6 @@
+ db->nextIn -= db->dmasize;
+ }
+
+- set_recv_slots(db->num_channels);
+ au1xxx_dbdma_start(db->dmanr);
+ au_writel(PSC_AC97PCR_RC, PSC_AC97PCR);
+ au_sync();
+@@ -752,12 +774,16 @@
+ if (ac97c_stat & (AC97C_XU | AC97C_XO | AC97C_TE))
+ dbg("AC97C status = 0x%08x", ac97c_stat);
+ #endif
++ /* There is a possiblity that we are getting 1 interrupt for
++ multiple descriptors. Use ddma api to find out how many
++ completed.
++ */
+ db->dma_qcount--;
+
+ if (db->count >= db->fragsize) {
+ if (au1xxx_dbdma_put_source(db->dmanr, db->nextOut,
+ db->fragsize) == 0) {
+- err("qcount < 2 and no ring room!");
++ err("qcount < 2 and no ring room1!");
+ }
+ db->nextOut += db->fragsize;
+ if (db->nextOut >= db->rawbuf + db->dmasize)
+@@ -941,11 +967,12 @@
+
+ /* duplicate every audio frame src_factor times
+ */
+- for (i = 0; i < db->src_factor; i++)
++ for (i = 0; i < db->src_factor; i++) {
+ memcpy(dmabuf, dmasample, db->dma_bytes_per_sample);
++ dmabuf += interp_bytes_per_sample;
++ }
+
+ userbuf += db->user_bytes_per_sample;
+- dmabuf += interp_bytes_per_sample;
+ }
+
+ return num_samples * interp_bytes_per_sample;
+@@ -1203,7 +1230,7 @@
+ while ((db->dma_qcount < 2) && (db->count >= db->fragsize)) {
+ if (au1xxx_dbdma_put_source(db->dmanr, db->nextOut,
+ db->fragsize) == 0) {
+- err("qcount < 2 and no ring room!");
++ err("qcount < 2 and no ring room!0");
+ }
+ db->nextOut += db->fragsize;
+ if (db->nextOut >= db->rawbuf + db->dmasize)
+@@ -1481,6 +1508,7 @@
+ return -EINVAL;
+ stop_adc(s);
+ s->dma_adc.num_channels = val;
++ set_recv_slots(val);
+ if ((ret = prog_dmabuf_adc(s)))
+ return ret;
+ }
+@@ -1538,6 +1566,7 @@
+ }
+
+ s->dma_dac.num_channels = val;
++ set_xmit_slots(val);
+ if ((ret = prog_dmabuf_dac(s)))
+ return ret;
+ }
+@@ -1832,10 +1861,8 @@
+ down(&s->open_sem);
+ }
+
+- stop_dac(s);
+- stop_adc(s);
+-
+ if (file->f_mode & FMODE_READ) {
++ stop_adc(s);
+ s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags =
+ s->dma_adc.subdivision = s->dma_adc.total_bytes = 0;
+ s->dma_adc.num_channels = 1;
+@@ -1846,6 +1873,7 @@
+ }
+
+ if (file->f_mode & FMODE_WRITE) {
++ stop_dac(s);
+ s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags =
+ s->dma_dac.subdivision = s->dma_dac.total_bytes = 0;
+ s->dma_dac.num_channels = 1;
+@@ -2091,6 +2119,9 @@
+ ac97_read_proc, &s->codec);
+ #endif
+
++ set_xmit_slots(1);
++ set_recv_slots(1);
++
+ return 0;
+
+ err_dev3:
+diff -Nur linux-2.4.32-rc1/drivers/sound/Config.in linux-2.4.32-rc1.mips/drivers/sound/Config.in
+--- linux-2.4.32-rc1/drivers/sound/Config.in 2005-01-19 15:10:04.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/sound/Config.in 2005-04-21 07:53:07.000000000 +0200
+@@ -72,10 +72,15 @@
+ if [ "$CONFIG_DDB5477" = "y" ]; then
+ dep_tristate ' NEC Vrc5477 AC97 sound' CONFIG_SOUND_VRC5477 $CONFIG_SOUND
+ fi
+-if [ "$CONFIG_SOC_AU1X00" = "y" -o "$CONFIG_SOC_AU1500" = "y" ]; then
+- dep_tristate ' Au1x00 Sound' CONFIG_SOUND_AU1X00 $CONFIG_SOUND
+- dep_tristate ' Au1550 PSC Sound' CONFIG_SOUND_AU1550_PSC $CONFIG_SOUND
+- dep_tristate ' Au1550 I2S Sound' CONFIG_SOUND_AU1550_I2S $CONFIG_SOUND
++if [ "$CONFIG_SOC_AU1000" = "y" -o \
++ "$CONFIG_SOC_AU1500" = "y" -o \
++ "$CONFIG_SOC_AU1100" = "y" ]; then
++ dep_tristate ' Au1x00 AC97 Sound' CONFIG_SOUND_AU1X00 $CONFIG_SOUND
++fi
++if [ "$CONFIG_SOC_AU1550" = "y" -o \
++ "$CONFIG_SOC_AU1200" = "y" ]; then
++ dep_tristate ' Au1550/Au1200 PSC AC97 Sound' CONFIG_SOUND_AU1550_PSC $CONFIG_SOUND
++ dep_tristate ' Au1550/Au1200 PSC I2S Sound' CONFIG_SOUND_AU1550_I2S $CONFIG_SOUND
+ fi
+
+ dep_tristate ' Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core' CONFIG_SOUND_TRIDENT $CONFIG_SOUND $CONFIG_PCI
+diff -Nur linux-2.4.32-rc1/drivers/tc/lk201.c linux-2.4.32-rc1.mips/drivers/tc/lk201.c
+--- linux-2.4.32-rc1/drivers/tc/lk201.c 2004-02-18 14:36:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/tc/lk201.c 2004-09-28 02:53:04.000000000 +0200
+@@ -5,7 +5,7 @@
+ * for more details.
+ *
+ * Copyright (C) 1999-2002 Harald Koerfgen <hkoerfg@web.de>
+- * Copyright (C) 2001, 2002, 2003 Maciej W. Rozycki <macro@ds2.pg.gda.pl>
++ * Copyright (C) 2001, 2002, 2003, 2004 Maciej W. Rozycki
+ */
+
+ #include <linux/config.h>
+@@ -23,8 +23,8 @@
+ #include <asm/keyboard.h>
+ #include <asm/dec/tc.h>
+ #include <asm/dec/machtype.h>
++#include <asm/dec/serial.h>
+
+-#include "zs.h"
+ #include "lk201.h"
+
+ /*
+@@ -55,19 +55,20 @@
+ unsigned char kbd_sysrq_key = -1;
+ #endif
+
+-#define KEYB_LINE 3
++#define KEYB_LINE_ZS 3
++#define KEYB_LINE_DZ 0
+
+-static int __init lk201_init(struct dec_serial *);
+-static void __init lk201_info(struct dec_serial *);
+-static void lk201_kbd_rx_char(unsigned char, unsigned char);
++static int __init lk201_init(void *);
++static void __init lk201_info(void *);
++static void lk201_rx_char(unsigned char, unsigned char);
+
+-struct zs_hook lk201_kbdhook = {
++static struct dec_serial_hook lk201_hook = {
+ .init_channel = lk201_init,
+ .init_info = lk201_info,
+ .rx_char = NULL,
+ .poll_rx_char = NULL,
+ .poll_tx_char = NULL,
+- .cflags = B4800 | CS8 | CSTOPB | CLOCAL
++ .cflags = B4800 | CS8 | CSTOPB | CLOCAL,
+ };
+
+ /*
+@@ -93,28 +94,28 @@
+ LK_CMD_ENB_BELL, LK_PARAM_VOLUME(4),
+ };
+
+-static struct dec_serial* lk201kbd_info;
++static void *lk201_handle;
+
+-static int lk201_send(struct dec_serial *info, unsigned char ch)
++static int lk201_send(unsigned char ch)
+ {
+- if (info->hook->poll_tx_char(info, ch)) {
++ if (lk201_hook.poll_tx_char(lk201_handle, ch)) {
+ printk(KERN_ERR "lk201: transmit timeout\n");
+ return -EIO;
+ }
+ return 0;
+ }
+
+-static inline int lk201_get_id(struct dec_serial *info)
++static inline int lk201_get_id(void)
+ {
+- return lk201_send(info, LK_CMD_REQ_ID);
++ return lk201_send(LK_CMD_REQ_ID);
+ }
+
+-static int lk201_reset(struct dec_serial *info)
++static int lk201_reset(void)
+ {
+ int i, r;
+
+ for (i = 0; i < sizeof(lk201_reset_string); i++) {
+- r = lk201_send(info, lk201_reset_string[i]);
++ r = lk201_send(lk201_reset_string[i]);
+ if (r < 0)
+ return r;
+ }
+@@ -203,24 +204,26 @@
+
+ static int write_kbd_rate(struct kbd_repeat *rep)
+ {
+- struct dec_serial* info = lk201kbd_info;
+ int delay, rate;
+ int i;
+
+ delay = rep->delay / 5;
+ rate = rep->rate;
+ for (i = 0; i < 4; i++) {
+- if (info->hook->poll_tx_char(info, LK_CMD_RPT_RATE(i)))
++ if (lk201_hook.poll_tx_char(lk201_handle,
++ LK_CMD_RPT_RATE(i)))
+ return 1;
+- if (info->hook->poll_tx_char(info, LK_PARAM_DELAY(delay)))
++ if (lk201_hook.poll_tx_char(lk201_handle,
++ LK_PARAM_DELAY(delay)))
+ return 1;
+- if (info->hook->poll_tx_char(info, LK_PARAM_RATE(rate)))
++ if (lk201_hook.poll_tx_char(lk201_handle,
++ LK_PARAM_RATE(rate)))
+ return 1;
+ }
+ return 0;
+ }
+
+-static int lk201kbd_rate(struct kbd_repeat *rep)
++static int lk201_kbd_rate(struct kbd_repeat *rep)
+ {
+ if (rep == NULL)
+ return -EINVAL;
+@@ -237,10 +240,8 @@
+ return 0;
+ }
+
+-static void lk201kd_mksound(unsigned int hz, unsigned int ticks)
++static void lk201_kd_mksound(unsigned int hz, unsigned int ticks)
+ {
+- struct dec_serial* info = lk201kbd_info;
+-
+ if (!ticks)
+ return;
+
+@@ -253,20 +254,19 @@
+ ticks = 7;
+ ticks = 7 - ticks;
+
+- if (info->hook->poll_tx_char(info, LK_CMD_ENB_BELL))
++ if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_ENB_BELL))
+ return;
+- if (info->hook->poll_tx_char(info, LK_PARAM_VOLUME(ticks)))
++ if (lk201_hook.poll_tx_char(lk201_handle, LK_PARAM_VOLUME(ticks)))
+ return;
+- if (info->hook->poll_tx_char(info, LK_CMD_BELL))
++ if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_BELL))
+ return;
+ }
+
+ void kbd_leds(unsigned char leds)
+ {
+- struct dec_serial* info = lk201kbd_info;
+ unsigned char l = 0;
+
+- if (!info) /* FIXME */
++ if (!lk201_handle) /* FIXME */
+ return;
+
+ /* FIXME -- Only Hold and Lock LEDs for now. --macro */
+@@ -275,13 +275,13 @@
+ if (leds & LED_CAP)
+ l |= LK_LED_LOCK;
+
+- if (info->hook->poll_tx_char(info, LK_CMD_LEDS_ON))
++ if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_LEDS_ON))
+ return;
+- if (info->hook->poll_tx_char(info, LK_PARAM_LED_MASK(l)))
++ if (lk201_hook.poll_tx_char(lk201_handle, LK_PARAM_LED_MASK(l)))
+ return;
+- if (info->hook->poll_tx_char(info, LK_CMD_LEDS_OFF))
++ if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_LEDS_OFF))
+ return;
+- if (info->hook->poll_tx_char(info, LK_PARAM_LED_MASK(~l)))
++ if (lk201_hook.poll_tx_char(lk201_handle, LK_PARAM_LED_MASK(~l)))
+ return;
+ }
+
+@@ -307,7 +307,7 @@
+ return 0x80;
+ }
+
+-static void lk201_kbd_rx_char(unsigned char ch, unsigned char stat)
++static void lk201_rx_char(unsigned char ch, unsigned char fl)
+ {
+ static unsigned char id[6];
+ static int id_i;
+@@ -316,9 +316,8 @@
+ static int prev_scancode;
+ unsigned char c = scancodeRemap[ch];
+
+- if (stat && stat != TTY_OVERRUN) {
+- printk(KERN_ERR "lk201: keyboard receive error: 0x%02x\n",
+- stat);
++ if (fl != TTY_NORMAL && fl != TTY_OVERRUN) {
++ printk(KERN_ERR "lk201: keyboard receive error: 0x%02x\n", fl);
+ return;
+ }
+
+@@ -335,7 +334,7 @@
+ /* OK, the power-up concluded. */
+ lk201_report(id);
+ if (id[2] == LK_STAT_PWRUP_OK)
+- lk201_get_id(lk201kbd_info);
++ lk201_get_id();
+ else {
+ id_i = 0;
+ printk(KERN_ERR "lk201: keyboard power-up "
+@@ -345,7 +344,7 @@
+ /* We got the ID; report it and start operation. */
+ id_i = 0;
+ lk201_id(id);
+- lk201_reset(lk201kbd_info);
++ lk201_reset();
+ }
+ return;
+ }
+@@ -398,29 +397,28 @@
+ tasklet_schedule(&keyboard_tasklet);
+ }
+
+-static void __init lk201_info(struct dec_serial *info)
++static void __init lk201_info(void *handle)
+ {
+ }
+
+-static int __init lk201_init(struct dec_serial *info)
++static int __init lk201_init(void *handle)
+ {
+ /* First install handlers. */
+- lk201kbd_info = info;
+- kbd_rate = lk201kbd_rate;
+- kd_mksound = lk201kd_mksound;
++ lk201_handle = handle;
++ kbd_rate = lk201_kbd_rate;
++ kd_mksound = lk201_kd_mksound;
+
+- info->hook->rx_char = lk201_kbd_rx_char;
++ lk201_hook.rx_char = lk201_rx_char;
+
+ /* Then just issue a reset -- the handlers will do the rest. */
+- lk201_send(info, LK_CMD_POWER_UP);
++ lk201_send(LK_CMD_POWER_UP);
+
+ return 0;
+ }
+
+ void __init kbd_init_hw(void)
+ {
+- extern int register_zs_hook(unsigned int, struct zs_hook *);
+- extern int unregister_zs_hook(unsigned int);
++ int keyb_line;
+
+ /* Maxine uses LK501 at the Access.Bus. */
+ if (!LK_IFACE)
+@@ -428,19 +426,15 @@
+
+ printk(KERN_INFO "lk201: DECstation LK keyboard driver v0.05.\n");
+
+- if (LK_IFACE_ZS) {
+- /*
+- * kbd_init_hw() is being called before
+- * rs_init() so just register the kbd hook
+- * and let zs_init do the rest :-)
+- */
+- if(!register_zs_hook(KEYB_LINE, &lk201_kbdhook))
+- unregister_zs_hook(KEYB_LINE);
+- } else {
+- /*
+- * TODO: modify dz.c to allow similar hooks
+- * for LK201 handling on DS2100, DS3100, and DS5000/200
+- */
+- printk(KERN_ERR "lk201: support for DZ11 not yet ready.\n");
+- }
++ /*
++ * kbd_init_hw() is being called before
++ * rs_init() so just register the kbd hook
++ * and let zs_init do the rest :-)
++ */
++ if (LK_IFACE_ZS)
++ keyb_line = KEYB_LINE_ZS;
++ else
++ keyb_line = KEYB_LINE_DZ;
++ if (!register_dec_serial_hook(keyb_line, &lk201_hook))
++ unregister_dec_serial_hook(keyb_line);
+ }
+diff -Nur linux-2.4.32-rc1/drivers/tc/zs.c linux-2.4.32-rc1.mips/drivers/tc/zs.c
+--- linux-2.4.32-rc1/drivers/tc/zs.c 2005-01-19 15:10:05.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/tc/zs.c 2004-12-27 05:13:50.000000000 +0100
+@@ -68,6 +68,8 @@
+ #include <asm/bitops.h>
+ #include <asm/uaccess.h>
+ #include <asm/bootinfo.h>
++#include <asm/dec/serial.h>
++
+ #ifdef CONFIG_DECSTATION
+ #include <asm/dec/interrupts.h>
+ #include <asm/dec/machtype.h>
+@@ -160,8 +162,8 @@
+ #ifdef CONFIG_SERIAL_DEC_CONSOLE
+ static struct console sercons;
+ #endif
+-#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) \
+- && !defined(MODULE)
++#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
++ !defined(MODULE)
+ static unsigned long break_pressed; /* break, really ... */
+ #endif
+
+@@ -196,7 +198,6 @@
+ /*
+ * Debugging.
+ */
+-#undef SERIAL_DEBUG_INTR
+ #undef SERIAL_DEBUG_OPEN
+ #undef SERIAL_DEBUG_FLOW
+ #undef SERIAL_DEBUG_THROTTLE
+@@ -221,10 +222,6 @@
+ static struct termios *serial_termios[NUM_CHANNELS];
+ static struct termios *serial_termios_locked[NUM_CHANNELS];
+
+-#ifndef MIN
+-#define MIN(a,b) ((a) < (b) ? (a) : (b))
+-#endif
+-
+ /*
+ * tmp_buf is used as a temporary buffer by serial_write. We need to
+ * lock it in case the copy_from_user blocks while swapping in a page,
+@@ -386,8 +383,6 @@
+ * -----------------------------------------------------------------------
+ */
+
+-static int tty_break; /* Set whenever BREAK condition is detected. */
+-
+ /*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+@@ -414,20 +409,15 @@
+ if (!tty && (!info->hook || !info->hook->rx_char))
+ continue;
+
+- if (tty_break) {
+- tty_break = 0;
+-#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE)
+- if (info->line == sercons.index) {
+- if (!break_pressed) {
+- break_pressed = jiffies;
+- goto ignore_char;
+- }
+- break_pressed = 0;
+- }
+-#endif
++ flag = TTY_NORMAL;
++ if (info->tty_break) {
++ info->tty_break = 0;
+ flag = TTY_BREAK;
+ if (info->flags & ZILOG_SAK)
+ do_SAK(tty);
++ /* Ignore the null char got when BREAK is removed. */
++ if (ch == 0)
++ continue;
+ } else {
+ if (stat & Rx_OVR) {
+ flag = TTY_OVERRUN;
+@@ -435,20 +425,22 @@
+ flag = TTY_FRAME;
+ } else if (stat & PAR_ERR) {
+ flag = TTY_PARITY;
+- } else
+- flag = 0;
+- if (flag)
++ }
++ if (flag != TTY_NORMAL)
+ /* reset the error indication */
+ write_zsreg(info->zs_channel, R0, ERR_RES);
+ }
+
+-#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE)
++#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
++ !defined(MODULE)
+ if (break_pressed && info->line == sercons.index) {
+- if (ch != 0 &&
+- time_before(jiffies, break_pressed + HZ*5)) {
++ /* Ignore the null char got when BREAK is removed. */
++ if (ch == 0)
++ continue;
++ if (time_before(jiffies, break_pressed + HZ * 5)) {
+ handle_sysrq(ch, regs, NULL, NULL);
+ break_pressed = 0;
+- goto ignore_char;
++ continue;
+ }
+ break_pressed = 0;
+ }
+@@ -459,23 +451,7 @@
+ return;
+ }
+
+- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+- static int flip_buf_ovf;
+- ++flip_buf_ovf;
+- continue;
+- }
+- tty->flip.count++;
+- {
+- static int flip_max_cnt;
+- if (flip_max_cnt < tty->flip.count)
+- flip_max_cnt = tty->flip.count;
+- }
+-
+- *tty->flip.flag_buf_ptr++ = flag;
+- *tty->flip.char_buf_ptr++ = ch;
+-#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE)
+- ignore_char:
+-#endif
++ tty_insert_flip_char(tty, ch, flag);
+ }
+ if (tty)
+ tty_flip_buffer_push(tty);
+@@ -517,11 +493,15 @@
+ /* Get status from Read Register 0 */
+ stat = read_zsreg(info->zs_channel, R0);
+
+- if (stat & BRK_ABRT) {
+-#ifdef SERIAL_DEBUG_INTR
+- printk("handling break....");
++ if ((stat & BRK_ABRT) && !(info->read_reg_zero & BRK_ABRT)) {
++#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
++ !defined(MODULE)
++ if (info->line == sercons.index) {
++ if (!break_pressed)
++ break_pressed = jiffies;
++ } else
+ #endif
+- tty_break = 1;
++ info->tty_break = 1;
+ }
+
+ if (info->zs_channel != info->zs_chan_a) {
+@@ -957,7 +937,7 @@
+ save_flags(flags);
+ while (1) {
+ cli();
+- c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
++ c = min(count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+ SERIAL_XMIT_SIZE - info->xmit_head));
+ if (c <= 0)
+ break;
+@@ -965,7 +945,7 @@
+ if (from_user) {
+ down(&tmp_buf_sem);
+ copy_from_user(tmp_buf, buf, c);
+- c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
++ c = min(c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+ SERIAL_XMIT_SIZE - info->xmit_head));
+ memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
+ up(&tmp_buf_sem);
+@@ -1282,46 +1262,48 @@
+ }
+
+ switch (cmd) {
+- case TIOCMGET:
+- error = verify_area(VERIFY_WRITE, (void *) arg,
+- sizeof(unsigned int));
+- if (error)
+- return error;
+- return get_modem_info(info, (unsigned int *) arg);
+- case TIOCMBIS:
+- case TIOCMBIC:
+- case TIOCMSET:
+- return set_modem_info(info, cmd, (unsigned int *) arg);
+- case TIOCGSERIAL:
+- error = verify_area(VERIFY_WRITE, (void *) arg,
+- sizeof(struct serial_struct));
+- if (error)
+- return error;
+- return get_serial_info(info,
+- (struct serial_struct *) arg);
+- case TIOCSSERIAL:
+- return set_serial_info(info,
+- (struct serial_struct *) arg);
+- case TIOCSERGETLSR: /* Get line status register */
+- error = verify_area(VERIFY_WRITE, (void *) arg,
+- sizeof(unsigned int));
+- if (error)
+- return error;
+- else
+- return get_lsr_info(info, (unsigned int *) arg);
++ case TIOCMGET:
++ error = verify_area(VERIFY_WRITE, (void *)arg,
++ sizeof(unsigned int));
++ if (error)
++ return error;
++ return get_modem_info(info, (unsigned int *)arg);
+
+- case TIOCSERGSTRUCT:
+- error = verify_area(VERIFY_WRITE, (void *) arg,
+- sizeof(struct dec_serial));
+- if (error)
+- return error;
+- copy_from_user((struct dec_serial *) arg,
+- info, sizeof(struct dec_serial));
+- return 0;
++ case TIOCMBIS:
++ case TIOCMBIC:
++ case TIOCMSET:
++ return set_modem_info(info, cmd, (unsigned int *)arg);
+
+- default:
+- return -ENOIOCTLCMD;
+- }
++ case TIOCGSERIAL:
++ error = verify_area(VERIFY_WRITE, (void *)arg,
++ sizeof(struct serial_struct));
++ if (error)
++ return error;
++ return get_serial_info(info, (struct serial_struct *)arg);
++
++ case TIOCSSERIAL:
++ return set_serial_info(info, (struct serial_struct *)arg);
++
++ case TIOCSERGETLSR: /* Get line status register */
++ error = verify_area(VERIFY_WRITE, (void *)arg,
++ sizeof(unsigned int));
++ if (error)
++ return error;
++ else
++ return get_lsr_info(info, (unsigned int *)arg);
++
++ case TIOCSERGSTRUCT:
++ error = verify_area(VERIFY_WRITE, (void *)arg,
++ sizeof(struct dec_serial));
++ if (error)
++ return error;
++ copy_from_user((struct dec_serial *)arg, info,
++ sizeof(struct dec_serial));
++ return 0;
++
++ default:
++ return -ENOIOCTLCMD;
++ }
+ return 0;
+ }
+
+@@ -1446,7 +1428,8 @@
+ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+ {
+ struct dec_serial *info = (struct dec_serial *) tty->driver_data;
+- unsigned long orig_jiffies, char_time;
++ unsigned long orig_jiffies;
++ int char_time;
+
+ if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent"))
+ return;
+@@ -1462,7 +1445,7 @@
+ if (char_time == 0)
+ char_time = 1;
+ if (timeout)
+- char_time = MIN(char_time, timeout);
++ char_time = min(char_time, timeout);
+ while ((read_zsreg(info->zs_channel, 1) & Tx_BUF_EMP) == 0) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(char_time);
+@@ -1714,7 +1697,7 @@
+
+ static void __init show_serial_version(void)
+ {
+- printk("DECstation Z8530 serial driver version 0.08\n");
++ printk("DECstation Z8530 serial driver version 0.09\n");
+ }
+
+ /* Initialize Z8530s zs_channels
+@@ -1994,8 +1977,9 @@
+ * polling I/O routines
+ */
+ static int
+-zs_poll_tx_char(struct dec_serial *info, unsigned char ch)
++zs_poll_tx_char(void *handle, unsigned char ch)
+ {
++ struct dec_serial *info = handle;
+ struct dec_zschannel *chan = info->zs_channel;
+ int ret;
+
+@@ -2017,8 +2001,9 @@
+ }
+
+ static int
+-zs_poll_rx_char(struct dec_serial *info)
++zs_poll_rx_char(void *handle)
+ {
++ struct dec_serial *info = handle;
+ struct dec_zschannel *chan = info->zs_channel;
+ int ret;
+
+@@ -2038,12 +2023,13 @@
+ return -ENODEV;
+ }
+
+-unsigned int register_zs_hook(unsigned int channel, struct zs_hook *hook)
++int register_zs_hook(unsigned int channel, struct dec_serial_hook *hook)
+ {
+ struct dec_serial *info = &zs_soft[channel];
+
+ if (info->hook) {
+- printk(__FUNCTION__": line %d has already a hook registered\n", channel);
++ printk("%s: line %d has already a hook registered\n",
++ __FUNCTION__, channel);
+
+ return 0;
+ } else {
+@@ -2055,7 +2041,7 @@
+ }
+ }
+
+-unsigned int unregister_zs_hook(unsigned int channel)
++int unregister_zs_hook(unsigned int channel)
+ {
+ struct dec_serial *info = &zs_soft[channel];
+
+@@ -2063,8 +2049,8 @@
+ info->hook = NULL;
+ return 1;
+ } else {
+- printk(__FUNCTION__": trying to unregister hook on line %d,"
+- " but none is registered\n", channel);
++ printk("%s: trying to unregister hook on line %d,"
++ " but none is registered\n", __FUNCTION__, channel);
+ return 0;
+ }
+ }
+@@ -2319,22 +2305,23 @@
+ write_zsreg(chan, 9, nine);
+ }
+
+-static int kgdbhook_init_channel(struct dec_serial* info)
++static int kgdbhook_init_channel(void *handle)
+ {
+ return 0;
+ }
+
+-static void kgdbhook_init_info(struct dec_serial* info)
++static void kgdbhook_init_info(void *handle)
+ {
+ }
+
+-static void kgdbhook_rx_char(struct dec_serial* info,
+- unsigned char ch, unsigned char stat)
++static void kgdbhook_rx_char(void *handle, unsigned char ch, unsigned char fl)
+ {
++ struct dec_serial *info = handle;
++
++ if (fl != TTY_NORMAL)
++ return;
+ if (ch == 0x03 || ch == '$')
+ breakpoint();
+- if (stat & (Rx_OVR|FRM_ERR|PAR_ERR))
+- write_zsreg(info->zs_channel, 0, ERR_RES);
+ }
+
+ /* This sets up the serial port we're using, and turns on
+@@ -2360,11 +2347,11 @@
+ * for /dev/ttyb which is determined in setup_arch() from the
+ * boot command line flags.
+ */
+-struct zs_hook zs_kgdbhook = {
+- init_channel : kgdbhook_init_channel,
+- init_info : kgdbhook_init_info,
+- cflags : B38400|CS8|CLOCAL,
+- rx_char : kgdbhook_rx_char,
++struct dec_serial_hook zs_kgdbhook = {
++ .init_channel = kgdbhook_init_channel,
++ .init_info = kgdbhook_init_info,
++ .rx_char = kgdbhook_rx_char,
++ .cflags = B38400 | CS8 | CLOCAL,
+ }
+
+ void __init zs_kgdb_hook(int tty_num)
+diff -Nur linux-2.4.32-rc1/drivers/tc/zs.h linux-2.4.32-rc1.mips/drivers/tc/zs.h
+--- linux-2.4.32-rc1/drivers/tc/zs.h 2004-02-18 14:36:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/tc/zs.h 2004-07-01 15:28:54.000000000 +0200
+@@ -1,14 +1,18 @@
+ /*
+- * macserial.h: Definitions for the Macintosh Z8530 serial driver.
++ * drivers/tc/zs.h: Definitions for the DECstation Z85C30 serial driver.
+ *
+ * Adapted from drivers/sbus/char/sunserial.h by Paul Mackerras.
++ * Adapted from drivers/macintosh/macserial.h by Harald Koerfgen.
+ *
+ * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
++ * Copyright (C) 2004 Maciej W. Rozycki
+ */
+ #ifndef _DECSERIAL_H
+ #define _DECSERIAL_H
+
++#include <asm/dec/serial.h>
++
+ #define NUM_ZSREGS 16
+
+ struct serial_struct {
+@@ -89,63 +93,50 @@
+ unsigned char curregs[NUM_ZSREGS];
+ };
+
+-struct dec_serial;
+-
+-struct zs_hook {
+- int (*init_channel)(struct dec_serial* info);
+- void (*init_info)(struct dec_serial* info);
+- void (*rx_char)(unsigned char ch, unsigned char stat);
+- int (*poll_rx_char)(struct dec_serial* info);
+- int (*poll_tx_char)(struct dec_serial* info,
+- unsigned char ch);
+- unsigned cflags;
+-};
+-
+ struct dec_serial {
+- struct dec_serial *zs_next; /* For IRQ servicing chain */
+- struct dec_zschannel *zs_channel; /* Channel registers */
+- struct dec_zschannel *zs_chan_a; /* A side registers */
+- unsigned char read_reg_zero;
+-
+- char soft_carrier; /* Use soft carrier on this channel */
+- char break_abort; /* Is serial console in, so process brk/abrt */
+- struct zs_hook *hook; /* Hook on this channel */
+- char is_cons; /* Is this our console. */
+- unsigned char tx_active; /* character is being xmitted */
+- unsigned char tx_stopped; /* output is suspended */
+-
+- /* We need to know the current clock divisor
+- * to read the bps rate the chip has currently
+- * loaded.
++ struct dec_serial *zs_next; /* For IRQ servicing chain. */
++ struct dec_zschannel *zs_channel; /* Channel registers. */
++ struct dec_zschannel *zs_chan_a; /* A side registers. */
++ unsigned char read_reg_zero;
++
++ struct dec_serial_hook *hook; /* Hook on this channel. */
++ int tty_break; /* Set on BREAK condition. */
++ int is_cons; /* Is this our console. */
++ int tx_active; /* Char is being xmitted. */
++ int tx_stopped; /* Output is suspended. */
++
++ /*
++ * We need to know the current clock divisor
++ * to read the bps rate the chip has currently loaded.
+ */
+- unsigned char clk_divisor; /* May be 1, 16, 32, or 64 */
+- int zs_baud;
++ int clk_divisor; /* May be 1, 16, 32, or 64. */
++ int zs_baud;
+
+- char change_needed;
++ char change_needed;
+
+ int magic;
+ int baud_base;
+ int port;
+ int irq;
+- int flags; /* defined in tty.h */
+- int type; /* UART type */
++ int flags; /* Defined in tty.h. */
++ int type; /* UART type. */
+ struct tty_struct *tty;
+ int read_status_mask;
+ int ignore_status_mask;
+ int timeout;
+ int xmit_fifo_size;
+ int custom_divisor;
+- int x_char; /* xon/xoff character */
++ int x_char; /* XON/XOFF character. */
+ int close_delay;
+ unsigned short closing_wait;
+ unsigned short closing_wait2;
+ unsigned long event;
+ unsigned long last_active;
+ int line;
+- int count; /* # of fd on device */
+- int blocked_open; /* # of blocked opens */
+- long session; /* Session of opening process */
+- long pgrp; /* pgrp of opening process */
++ int count; /* # of fds on device. */
++ int blocked_open; /* # of blocked opens. */
++ long session; /* Sess of opening process. */
++ long pgrp; /* Pgrp of opening process. */
+ unsigned char *xmit_buf;
+ int xmit_head;
+ int xmit_tail;
+diff -Nur linux-2.4.32-rc1/drivers/video/au1200fb.c linux-2.4.32-rc1.mips/drivers/video/au1200fb.c
+--- linux-2.4.32-rc1/drivers/video/au1200fb.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/video/au1200fb.c 2005-03-13 09:04:16.000000000 +0100
+@@ -0,0 +1,1564 @@
++/*
++ * BRIEF MODULE DESCRIPTION
++ * Au1200 LCD Driver.
++ *
++ * Copyright 2004 AMD
++ * Author: AMD
++ *
++ * Based on:
++ * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
++ * Created 28 Dec 1997 by Geert Uytterhoeven
++ *
++ * 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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/tty.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/fb.h>
++#include <linux/init.h>
++#include <asm/uaccess.h>
++
++#include <asm/au1000.h>
++#include <asm/au1xxx_gpio.h>
++#include "au1200fb.h"
++
++#include <video/fbcon.h>
++#include <video/fbcon-cfb16.h>
++#include <video/fbcon-cfb32.h>
++#define CMAPSIZE 16
++
++#define AU1200_LCD_GET_WINENABLE 1
++#define AU1200_LCD_SET_WINENABLE 2
++#define AU1200_LCD_GET_WINLOCATION 3
++#define AU1200_LCD_SET_WINLOCATION 4
++#define AU1200_LCD_GET_WINSIZE 5
++#define AU1200_LCD_SET_WINSIZE 6
++#define AU1200_LCD_GET_BACKCOLOR 7
++#define AU1200_LCD_SET_BACKCOLOR 8
++#define AU1200_LCD_GET_COLORKEY 9
++#define AU1200_LCD_SET_COLORKEY 10
++#define AU1200_LCD_GET_PANEL 11
++#define AU1200_LCD_SET_PANEL 12
++
++typedef struct au1200_lcd_getset_t
++{
++ unsigned int subcmd;
++ union {
++ struct {
++ int enable;
++ } winenable;
++ struct {
++ int x, y;
++ } winlocation;
++ struct {
++ int hsz, vsz;
++ } winsize;
++ struct {
++ unsigned int color;
++ } backcolor;
++ struct {
++ unsigned int key;
++ unsigned int mask;
++ } colorkey;
++ struct {
++ int panel;
++ char desc[80];
++ } panel;
++ };
++} au1200_lcd_getset_t;
++
++AU1200_LCD *lcd = (AU1200_LCD *)AU1200_LCD_ADDR;
++static int window_index = 0; /* default is zero */
++static int panel_index = -1; /* default is call board_au1200fb_panel */
++
++struct window_settings
++{
++ unsigned char name[64];
++ uint32 mode_backcolor;
++ uint32 mode_colorkey;
++ uint32 mode_colorkeymsk;
++ struct
++ {
++ int xres;
++ int yres;
++ int xpos;
++ int ypos;
++ uint32 mode_winctrl1; /* winctrl1[FRM,CCO,PO,PIPE] */
++ uint32 mode_winenable;
++ } w[4];
++};
++
++struct panel_settings
++{
++ unsigned char name[64];
++ /* panel physical dimensions */
++ uint32 Xres;
++ uint32 Yres;
++ /* panel timings */
++ uint32 mode_screen;
++ uint32 mode_horztiming;
++ uint32 mode_verttiming;
++ uint32 mode_clkcontrol;
++ uint32 mode_pwmdiv;
++ uint32 mode_pwmhi;
++ uint32 mode_outmask;
++ uint32 mode_fifoctrl;
++ uint32 mode_toyclksrc;
++ uint32 mode_backlight;
++ uint32 mode_auxpll;
++ int (*device_init)(void);
++ int (*device_shutdown)(void);
++};
++
++#if defined(__BIG_ENDIAN)
++#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_00
++#else
++#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01
++#endif
++
++extern int board_au1200fb_panel (void);
++extern int board_au1200fb_panel_init (void);
++extern int board_au1200fb_panel_shutdown (void);
++
++#if defined(CONFIG_FOCUS_ENHANCEMENTS)
++extern int board_au1200fb_focus_init_hdtv(void);
++extern int board_au1200fb_focus_init_component(void);
++extern int board_au1200fb_focus_init_cvsv(void);
++extern int board_au1200fb_focus_shutdown(void);
++#endif
++
++/*
++ * Default window configurations
++ */
++static struct window_settings windows[] =
++{
++ { /* Index 0 */
++ "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
++ /* mode_backcolor */ 0x006600ff,
++ /* mode_colorkey,msk*/ 0, 0,
++ {
++ {
++ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
++ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565|LCD_WINCTRL1_PO_16BPP,
++ /* mode_winenable*/ LCD_WINENABLE_WEN0,
++ },
++ {
++ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
++ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565|LCD_WINCTRL1_PO_16BPP,
++ /* mode_winenable*/ 0,
++ },
++ {
++ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
++ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565|LCD_WINCTRL1_PO_16BPP|LCD_WINCTRL1_PIPE,
++ /* mode_winenable*/ 0,
++ },
++ {
++ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
++ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565|LCD_WINCTRL1_PO_16BPP|LCD_WINCTRL1_PIPE,
++ /* mode_winenable*/ 0,
++ },
++ },
++ },
++
++ { /* Index 1 */
++ "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
++ /* mode_backcolor */ 0x006600ff,
++ /* mode_colorkey,msk*/ 0, 0,
++ {
++ {
++ /* xres, yres, xpos, ypos */ 320, 240, 5, 5,
++#if 0
++ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565|LCD_WINCTRL1_PO_16BPP,
++#endif
++ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_24BPP|LCD_WINCTRL1_PO_00,
++ /* mode_winenable*/ LCD_WINENABLE_WEN0,
++ },
++ {
++ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
++ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565|LCD_WINCTRL1_PO_16BPP,
++ /* mode_winenable*/ 0,
++ },
++ {
++ /* xres, yres, xpos, ypos */ 100, 100, 0, 0,
++ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565|LCD_WINCTRL1_PO_16BPP|LCD_WINCTRL1_PIPE,
++ /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/,
++ },
++ {
++ /* xres, yres, xpos, ypos */ 200, 25, 0, 0,
++ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565|LCD_WINCTRL1_PO_16BPP|LCD_WINCTRL1_PIPE,
++ /* mode_winenable*/ 0,
++ },
++ },
++ },
++ /* Need VGA 640 @ 24bpp, @ 32bpp */
++ /* Need VGA 800 @ 24bpp, @ 32bpp */
++ /* Need VGA 1024 @ 24bpp, @ 32bpp */
++} ;
++
++/*
++ * Controller configurations for various panels.
++ */
++static struct panel_settings panels[] =
++{
++ { /* Index 0: QVGA 320x240 H:33.3kHz V:110Hz */
++ "VGA_320x240",
++ 320, 240,
++ /* mode_screen */ LCD_SCREEN_SX_N(320) | LCD_SCREEN_SY_N(240),
++ /* mode_horztiming */ 0x00c4623b,
++ /* mode_verttiming */ 0x00502814,
++ /* mode_clkcontrol */ 0x00020002, /* /4=24Mhz */
++ /* mode_pwmdiv */ 0x00000000,
++ /* mode_pwmhi */ 0x00000000,
++ /* mode_outmask */ 0x00FFFFFF,
++ /* mode_fifoctrl */ 0x2f2f2f2f,
++ /* mode_toyclksrc */ 0x00000004, /* 96MHz AUXPLL directly */
++ /* mode_backlight */ 0x00000000,
++ /* mode_auxpll */ 8, /* 96MHz AUXPLL */
++ /* device_init */ NULL,
++ /* device_shutdown */ NULL,
++ },
++
++ { /* Index 1: VGA 640x480 H:30.3kHz V:58Hz */
++ "VGA_640x480",
++ 640, 480,
++ /* mode_screen */ 0x13f9df80,
++ /* mode_horztiming */ 0x003c5859,
++ /* mode_verttiming */ 0x00741201,
++ /* mode_clkcontrol */ 0x00020001, /* /4=24Mhz */
++ /* mode_pwmdiv */ 0x00000000,
++ /* mode_pwmhi */ 0x00000000,
++ /* mode_outmask */ 0x00FFFFFF,
++ /* mode_fifoctrl */ 0x2f2f2f2f,
++ /* mode_toyclksrc */ 0x00000004, /* AUXPLL directly */
++ /* mode_backlight */ 0x00000000,
++ /* mode_auxpll */ 8, /* 96MHz AUXPLL */
++ /* device_init */ NULL,
++ /* device_shutdown */ NULL,
++ },
++
++ { /* Index 2: SVGA 800x600 H:46.1kHz V:69Hz */
++ "SVGA_800x600",
++ 800, 600,
++ /* mode_screen */ 0x18fa5780,
++ /* mode_horztiming */ 0x00dc7e77,
++ /* mode_verttiming */ 0x00584805,
++ /* mode_clkcontrol */ 0x00020000, /* /2=48Mhz */
++ /* mode_pwmdiv */ 0x00000000,
++ /* mode_pwmhi */ 0x00000000,
++ /* mode_outmask */ 0x00FFFFFF,
++ /* mode_fifoctrl */ 0x2f2f2f2f,
++ /* mode_toyclksrc */ 0x00000004, /* AUXPLL directly */
++ /* mode_backlight */ 0x00000000,
++ /* mode_auxpll */ 8, /* 96MHz AUXPLL */
++ /* device_init */ NULL,
++ /* device_shutdown */ NULL,
++ },
++
++ { /* Index 3: XVGA 1024x768 H:56.2kHz V:70Hz */
++ "XVGA_1024x768",
++ 1024, 768,
++ /* mode_screen */ 0x1ffaff80,
++ /* mode_horztiming */ 0x007d0e57,
++ /* mode_verttiming */ 0x00740a01,
++ /* mode_clkcontrol */ 0x000A0000, /* /1 */
++ /* mode_pwmdiv */ 0x00000000,
++ /* mode_pwmhi */ 0x00000000,
++ /* mode_outmask */ 0x00FFFFFF,
++ /* mode_fifoctrl */ 0x2f2f2f2f,
++ /* mode_toyclksrc */ 0x00000004, /* AUXPLL directly */
++ /* mode_backlight */ 0x00000000,
++ /* mode_auxpll */ 6, /* 72MHz AUXPLL */
++ /* device_init */ NULL,
++ /* device_shutdown */ NULL,
++ },
++
++ { /* Index 4: XVGA 1280x1024 H:68.5kHz V:65Hz */
++ "XVGA_1280x1024",
++ 1280, 1024,
++ /* mode_screen */ 0x27fbff80,
++ /* mode_horztiming */ 0x00cdb2c7,
++ /* mode_verttiming */ 0x00600002,
++ /* mode_clkcontrol */ 0x000A0000, /* /1 */
++ /* mode_pwmdiv */ 0x00000000,
++ /* mode_pwmhi */ 0x00000000,
++ /* mode_outmask */ 0x00FFFFFF,
++ /* mode_fifoctrl */ 0x2f2f2f2f,
++ /* mode_toyclksrc */ 0x00000004, /* AUXPLL directly */
++ /* mode_backlight */ 0x00000000,
++ /* mode_auxpll */ 10, /* 120MHz AUXPLL */
++ /* device_init */ NULL,
++ /* device_shutdown */ NULL,
++ },
++
++ { /* Index 5: Samsung 1024x768 TFT */
++ "Samsung_1024x768_TFT",
++ 1024, 768,
++ /* mode_screen */ 0x1ffaff80,
++ /* mode_horztiming */ 0x018cc677,
++ /* mode_verttiming */ 0x00241217,
++ /* mode_clkcontrol */ 0x00000000, /* SCB 0x1 /4=24Mhz */
++ /* mode_pwmdiv */ 0x8000063f, /* SCB 0x0 */
++ /* mode_pwmhi */ 0x03400000, /* SCB 0x0 */
++ /* mode_outmask */ 0x00fcfcfc,
++ /* mode_fifoctrl */ 0x2f2f2f2f,
++ /* mode_toyclksrc */ 0x00000004, /* 96MHz AUXPLL directly */
++ /* mode_backlight */ 0x00000000,
++ /* mode_auxpll */ 8, /* 96MHz AUXPLL */
++ /* device_init */ board_au1200fb_panel_init,
++ /* device_shutdown */ board_au1200fb_panel_shutdown,
++ },
++
++ { /* Index 6: Toshiba 640x480 TFT */
++ "Toshiba_640x480_TFT",
++ 640, 480,
++ /* mode_screen */ LCD_SCREEN_SX_N(640) | LCD_SCREEN_SY_N(480),
++ /* mode_horztiming */ LCD_HORZTIMING_HPW_N(96) | LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(51),
++ /* mode_verttiming */ LCD_VERTTIMING_VPW_N(2) | LCD_VERTTIMING_VND1_N(11) | LCD_VERTTIMING_VND2_N(32) ,
++ /* mode_clkcontrol */ 0x00000000, /* /4=24Mhz */
++ /* mode_pwmdiv */ 0x8000063f,
++ /* mode_pwmhi */ 0x03400000,
++ /* mode_outmask */ 0x00fcfcfc,
++ /* mode_fifoctrl */ 0x2f2f2f2f,
++ /* mode_toyclksrc */ 0x00000004, /* 96MHz AUXPLL directly */
++ /* mode_backlight */ 0x00000000,
++ /* mode_auxpll */ 8, /* 96MHz AUXPLL */
++ /* device_init */ board_au1200fb_panel_init,
++ /* device_shutdown */ board_au1200fb_panel_shutdown,
++ },
++
++ { /* Index 7: Sharp 320x240 TFT */
++ "Sharp_320x240_TFT",
++ 320, 240,
++ /* mode_screen */ LCD_SCREEN_SX_N(320) | LCD_SCREEN_SY_N(240),
++ /* mode_horztiming */ LCD_HORZTIMING_HPW_N(60) | LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(2),
++ /* mode_verttiming */ LCD_VERTTIMING_VPW_N(2) | LCD_VERTTIMING_VND1_N(2) | LCD_VERTTIMING_VND2_N(5) ,
++ /* mode_clkcontrol */ LCD_CLKCONTROL_PCD_N(7), /* /16=6Mhz */
++ /* mode_pwmdiv */ 0x8000063f,
++ /* mode_pwmhi */ 0x03400000,
++ /* mode_outmask */ 0x00fcfcfc,
++ /* mode_fifoctrl */ 0x2f2f2f2f,
++ /* mode_toyclksrc */ 0x00000004, /* 96MHz AUXPLL directly */
++ /* mode_backlight */ 0x00000000,
++ /* mode_auxpll */ 8, /* 96MHz AUXPLL */
++ /* device_init */ board_au1200fb_panel_init,
++ /* device_shutdown */ board_au1200fb_panel_shutdown,
++ },
++ { /* Index 8: Toppoly TD070WGCB2 7" 854x480 TFT */
++ "Toppoly_TD070WGCB2",
++ 854, 480,
++ /* mode_screen */ LCD_SCREEN_SX_N(854) | LCD_SCREEN_SY_N(480),
++ /* mode_horztiming */ LCD_HORZTIMING_HND2_N(44) | LCD_HORZTIMING_HND1_N(44) | LCD_HORZTIMING_HPW_N(114),
++ /* mode_verttiming */ LCD_VERTTIMING_VND2_N(20) | LCD_VERTTIMING_VND1_N(21) | LCD_VERTTIMING_VPW_N(4),
++ /* mode_clkcontrol */ 0x00020001, /* /4=24Mhz */
++ /* mode_pwmdiv */ 0x8000063f,
++ /* mode_pwmhi */ 0x03400000,
++ /* mode_outmask */ 0x00FCFCFC,
++ /* mode_fifoctrl */ 0x2f2f2f2f,
++ /* mode_toyclksrc */ 0x00000004, /* AUXPLL directly */
++ /* mode_backlight */ 0x00000000,
++ /* mode_auxpll */ 8, /* 96MHz AUXPLL */
++ /* device_init */ board_au1200fb_panel_init,
++ /* device_shutdown */ board_au1200fb_panel_shutdown,
++ },
++#if defined(CONFIG_FOCUS_ENHANCEMENTS)
++ { /* Index 9: Focus FS453 TV-Out 640x480 */
++ "FS453_640x480 (Composite/S-Video)",
++ 640, 480,
++ /* mode_screen */ LCD_SCREEN_SX_N(640) | LCD_SCREEN_SY_N(480),
++ /* mode_horztiming */ LCD_HORZTIMING_HND2_N(143) | LCD_HORZTIMING_HND1_N(143) | LCD_HORZTIMING_HPW_N(10),
++ /* mode_verttiming */ LCD_VERTTIMING_VND2_N(30) | LCD_VERTTIMING_VND1_N(30) | LCD_VERTTIMING_VPW_N(5),
++ /* mode_clkcontrol */ 0x00480000 | (1<<17) | (1<<18), /* External Clock, 1:1 clock ratio */
++ /* mode_pwmdiv */ 0x00000000,
++ /* mode_pwmhi */ 0x00000000,
++ /* mode_outmask */ 0x00FFFFFF,
++ /* mode_fifoctrl */ 0x2f2f2f2f,
++ /* mode_toyclksrc */ 0x00000000,
++ /* mode_backlight */ 0x00000000,
++ /* mode_auxpll */ 8, /* 96MHz AUXPLL */
++ /* device_init */ board_au1200fb_focus_init_cvsv,
++ /* device_shutdown */ board_au1200fb_focus_shutdown,
++ },
++
++ { /* Index 10: Focus FS453 TV-Out 640x480 */
++ "FS453_640x480 (Component Video)",
++ 640, 480,
++ /* mode_screen */ LCD_SCREEN_SX_N(640) | LCD_SCREEN_SY_N(480),
++ /* mode_horztiming */ LCD_HORZTIMING_HND2_N(143) | LCD_HORZTIMING_HND1_N(143) | LCD_HORZTIMING_HPW_N(10),
++ /* mode_verttiming */ LCD_VERTTIMING_VND2_N(30) | LCD_VERTTIMING_VND1_N(30) | LCD_VERTTIMING_VPW_N(5),
++ /* mode_clkcontrol */ 0x00480000 | (1<<17) | (1<<18), /* External Clock, 1:1 clock ratio */
++ /* mode_pwmdiv */ 0x00000000,
++ /* mode_pwmhi */ 0x00000000,
++ /* mode_outmask */ 0x00FFFFFF,
++ /* mode_fifoctrl */ 0x2f2f2f2f,
++ /* mode_toyclksrc */ 0x00000000,
++ /* mode_backlight */ 0x00000000,
++ /* mode_auxpll */ 8, /* 96MHz AUXPLL */
++ /* device_init */ board_au1200fb_focus_init_component,
++ /* device_shutdown */ board_au1200fb_focus_shutdown,
++ },
++
++ { /* Index 11: Focus FS453 TV-Out 640x480 */
++ "FS453_640x480 (HDTV)",
++ 720, 480,
++ /* mode_screen */ LCD_SCREEN_SX_N(720) | LCD_SCREEN_SY_N(480),
++ /* mode_horztiming */ LCD_HORZTIMING_HND2_N(28) | LCD_HORZTIMING_HND1_N(46) | LCD_HORZTIMING_HPW_N(64),
++ /* mode_verttiming */ LCD_VERTTIMING_VND2_N(7) | LCD_VERTTIMING_VND1_N(31) | LCD_VERTTIMING_VPW_N(7),
++ /* mode_clkcontrol */ 0x00480000 | (1<<17) | (1<<18), /* External Clock, 1:1 clock ratio */
++ /* mode_pwmdiv */ 0x00000000,
++ /* mode_pwmhi */ 0x00000000,
++ /* mode_outmask */ 0x00FFFFFF,
++ /* mode_fifoctrl */ 0x2f2f2f2f,
++ /* mode_toyclksrc */ 0x00000000,
++ /* mode_backlight */ 0x00000000,
++ /* mode_auxpll */ 8, /* 96MHz AUXPLL */
++ /* device_init */ board_au1200fb_focus_init_hdtv,
++ /* device_shutdown */ board_au1200fb_focus_shutdown,
++ },
++#endif
++};
++
++#define NUM_PANELS (sizeof(panels) / sizeof(struct panel_settings))
++
++static struct window_settings *win;
++static struct panel_settings *panel;
++
++struct au1200fb_info {
++ struct fb_info_gen gen;
++ unsigned long fb_virt_start;
++ unsigned long fb_size;
++ unsigned long fb_phys;
++ int mmaped;
++ int nohwcursor;
++ int noblanking;
++
++ struct { unsigned red, green, blue, pad; } palette[256];
++
++#if defined(FBCON_HAS_CFB16)
++ u16 fbcon_cmap16[16];
++#endif
++#if defined(FBCON_HAS_CFB32)
++ u32 fbcon_cmap32[16];
++#endif
++};
++
++
++struct au1200fb_par {
++ struct fb_var_screeninfo var;
++
++ int line_length; /* in bytes */
++ int cmap_len; /* color-map length */
++};
++
++#ifndef CONFIG_FB_AU1200_DEVS
++#define CONFIG_FB_AU1200_DEVS 1
++#endif
++
++static struct au1200fb_info fb_infos[CONFIG_FB_AU1200_DEVS];
++static struct au1200fb_par fb_pars[CONFIG_FB_AU1200_DEVS];
++static struct display disps[CONFIG_FB_AU1200_DEVS];
++
++int au1200fb_init(void);
++void au1200fb_setup(char *options, int *ints);
++static int au1200fb_mmap(struct fb_info *fb, struct file *file,
++ struct vm_area_struct *vma);
++static int au1200_blank(int blank_mode, struct fb_info_gen *info);
++static int au1200fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
++ u_long arg, int con, struct fb_info *info);
++
++void au1200_nocursor(struct display *p, int mode, int xx, int yy){};
++
++static int au1200_setlocation (int plane, int xpos, int ypos);
++static int au1200_setsize (int plane, int xres, int yres);
++static void au1200_setmode(int plane);
++static void au1200_setpanel (struct panel_settings *newpanel);
++
++static struct fb_ops au1200fb_ops = {
++ owner: THIS_MODULE,
++ fb_get_fix: fbgen_get_fix,
++ fb_get_var: fbgen_get_var,
++ fb_set_var: fbgen_set_var,
++ fb_get_cmap: fbgen_get_cmap,
++ fb_set_cmap: fbgen_set_cmap,
++ fb_pan_display: fbgen_pan_display,
++ fb_ioctl: au1200fb_ioctl,
++ fb_mmap: au1200fb_mmap,
++};
++
++
++static int
++winbpp (unsigned int winctrl1)
++{
++ /* how many bytes of memory are needed for each pixel format */
++ switch (winctrl1 & LCD_WINCTRL1_FRM)
++ {
++ case LCD_WINCTRL1_FRM_1BPP: return 1; break;
++ case LCD_WINCTRL1_FRM_2BPP: return 2; break;
++ case LCD_WINCTRL1_FRM_4BPP: return 4; break;
++ case LCD_WINCTRL1_FRM_8BPP: return 8; break;
++ case LCD_WINCTRL1_FRM_12BPP: return 16; break;
++ case LCD_WINCTRL1_FRM_16BPP655: return 16; break;
++ case LCD_WINCTRL1_FRM_16BPP565: return 16; break;
++ case LCD_WINCTRL1_FRM_16BPP556: return 16; break;
++ case LCD_WINCTRL1_FRM_16BPPI1555: return 16; break;
++ case LCD_WINCTRL1_FRM_16BPPI5551: return 16; break;
++ case LCD_WINCTRL1_FRM_16BPPA1555: return 16; break;
++ case LCD_WINCTRL1_FRM_16BPPA5551: return 16; break;
++ case LCD_WINCTRL1_FRM_24BPP: return 32; break;
++ case LCD_WINCTRL1_FRM_32BPP: return 32; break;
++ default: return 0; break;
++ }
++}
++
++static int
++fbinfo2index (struct fb_info *fb_info)
++{
++ int i;
++ for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i)
++ {
++ if (fb_info == (struct fb_info *)(&fb_infos[i]))
++ return i;
++ }
++ printk("au1200fb: ERROR: fbinfo2index failed!\n");
++ return -1;
++}
++
++static void au1200_detect(void)
++{
++ /*
++ * This function should detect the current video mode settings
++ * and store it as the default video mode
++ * Yeh, well, we're not going to change any settings so we're
++ * always stuck with the default ...
++ */
++}
++
++static int au1200_encode_fix(struct fb_fix_screeninfo *fix,
++ const void *_par, struct fb_info_gen *_info)
++{
++ struct au1200fb_info *info = (struct au1200fb_info *) _info;
++ struct au1200fb_par *par = (struct au1200fb_par *) _par;
++ int plane;
++
++ plane = fbinfo2index(info);
++
++ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
++
++ fix->smem_start = info->fb_phys;
++ fix->smem_len = info->fb_size;
++ fix->type = FB_TYPE_PACKED_PIXELS;
++ fix->type_aux = 0;
++ fix->visual = (par->var.bits_per_pixel == 8) ?
++ FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
++ fix->ywrapstep = 0;
++ fix->xpanstep = 1;
++ fix->ypanstep = 1;
++ /* FIX!!!! why doesn't par->line_length work???? it does for au1100 */
++ fix->line_length = fb_pars[plane].line_length; /*par->line_length;*/
++ return 0;
++}
++
++static void set_color_bitfields(struct fb_var_screeninfo *var, int plane)
++{
++ if (var->bits_per_pixel == 8)
++ {
++ var->red.offset = 0;
++ var->red.length = 8;
++ var->green.offset = 0;
++ var->green.length = 8;
++ var->blue.offset = 0;
++ var->blue.length = 8;
++ var->transp.offset = 0;
++ var->transp.length = 0;
++ }
++ else
++
++ if (var->bits_per_pixel == 16)
++ {
++ /* FIX!!! How does CCO affect this ? */
++ /* FIX!!! Not exactly sure how many of these work with FB */
++ switch (win->w[plane].mode_winctrl1 & LCD_WINCTRL1_FRM)
++ {
++ case LCD_WINCTRL1_FRM_16BPP655:
++ var->red.offset = 10;
++ var->red.length = 6;
++ var->green.offset = 5;
++ var->green.length = 5;
++ var->blue.offset = 0;
++ var->blue.length = 5;
++ var->transp.offset = 0;
++ var->transp.length = 0;
++ break;
++
++ case LCD_WINCTRL1_FRM_16BPP565:
++ var->red.offset = 11;
++ var->red.length = 5;
++ var->green.offset = 5;
++ var->green.length = 6;
++ var->blue.offset = 0;
++ var->blue.length = 5;
++ var->transp.offset = 0;
++ var->transp.length = 0;
++ break;
++
++ case LCD_WINCTRL1_FRM_16BPP556:
++ var->red.offset = 11;
++ var->red.length = 5;
++ var->green.offset = 6;
++ var->green.length = 5;
++ var->blue.offset = 0;
++ var->blue.length = 6;
++ var->transp.offset = 0;
++ var->transp.length = 0;
++ break;
++
++ case LCD_WINCTRL1_FRM_16BPPI1555:
++ var->red.offset = 10;
++ var->red.length = 5;
++ var->green.offset = 5;
++ var->green.length = 5;
++ var->blue.offset = 0;
++ var->blue.length = 5;
++ var->transp.offset = 0;
++ var->transp.length = 0;
++ break;
++
++ case LCD_WINCTRL1_FRM_16BPPI5551:
++ var->red.offset = 11;
++ var->red.length = 5;
++ var->green.offset = 6;
++ var->green.length = 5;
++ var->blue.offset = 1;
++ var->blue.length = 5;
++ var->transp.offset = 0;
++ var->transp.length = 0;
++ break;
++
++ case LCD_WINCTRL1_FRM_16BPPA1555:
++ var->red.offset = 10;
++ var->red.length = 5;
++ var->green.offset = 5;
++ var->green.length = 5;
++ var->blue.offset = 0;
++ var->blue.length = 5;
++ var->transp.offset = 15;
++ var->transp.length = 1;
++ break;
++
++ case LCD_WINCTRL1_FRM_16BPPA5551:
++ var->red.offset = 11;
++ var->red.length = 5;
++ var->green.offset = 6;
++ var->green.length = 5;
++ var->blue.offset = 1;
++ var->blue.length = 5;
++ var->transp.offset = 0;
++ var->transp.length = 1;
++ break;
++
++ default:
++ printk("ERROR: Invalid PIXEL FORMAT!!!\n"); break;
++ }
++ }
++ else
++
++ if (var->bits_per_pixel == 32)
++ {
++ switch (win->w[plane].mode_winctrl1 & LCD_WINCTRL1_FRM)
++ {
++ case LCD_WINCTRL1_FRM_24BPP:
++ var->red.offset = 16;
++ var->red.length = 8;
++ var->green.offset = 8;
++ var->green.length = 8;
++ var->blue.offset = 0;
++ var->blue.length = 8;
++ var->transp.offset = 0;
++ var->transp.length = 0;
++ break;
++
++ case LCD_WINCTRL1_FRM_32BPP:
++ var->red.offset = 16;
++ var->red.length = 8;
++ var->green.offset = 8;
++ var->green.length = 8;
++ var->blue.offset = 0;
++ var->blue.length = 8;
++ var->transp.offset = 24;
++ var->transp.length = 8;
++ break;
++ }
++ }
++ var->red.msb_right = 0;
++ var->green.msb_right = 0;
++ var->blue.msb_right = 0;
++ var->transp.msb_right = 0;
++#if 0
++printk("set_color_bitfields(a=%d, r=%d..%d, g=%d..%d, b=%d..%d)\n",
++ var->transp.offset,
++ var->red.offset+var->red.length-1, var->red.offset,
++ var->green.offset+var->green.length-1, var->green.offset,
++ var->blue.offset+var->blue.length-1, var->blue.offset);
++#endif
++}
++
++static int au1200_decode_var(const struct fb_var_screeninfo *var,
++ void *_par, struct fb_info_gen *_info)
++{
++ struct au1200fb_par *par = (struct au1200fb_par *)_par;
++ int plane, bpp;
++
++ plane = fbinfo2index((struct fb_info *)_info);
++
++ /*
++ * Don't allow setting any of these yet: xres and yres don't
++ * make sense for LCD panels.
++ */
++ if (var->xres != win->w[plane].xres ||
++ var->yres != win->w[plane].yres ||
++ var->xres != win->w[plane].xres ||
++ var->yres != win->w[plane].yres) {
++ return -EINVAL;
++ }
++
++ bpp = winbpp(win->w[plane].mode_winctrl1);
++ if(var->bits_per_pixel != bpp) {
++ /* on au1200, window pixel format is independent of panel pixel */
++ printk("WARNING: bits_per_pizel != panel->bpp\n");
++ }
++
++ memset(par, 0, sizeof(struct au1200fb_par));
++ par->var = *var;
++
++ /* FIX!!! */
++ switch (var->bits_per_pixel) {
++ case 8:
++ par->var.bits_per_pixel = 8;
++ break;
++ case 16:
++ par->var.bits_per_pixel = 16;
++ break;
++ case 24:
++ case 32:
++ par->var.bits_per_pixel = 32;
++ break;
++ default:
++ printk("color depth %d bpp not supported\n",
++ var->bits_per_pixel);
++ return -EINVAL;
++
++ }
++ set_color_bitfields(&par->var, plane);
++ /* FIX!!! what is this for 24/32bpp? */
++ par->cmap_len = (par->var.bits_per_pixel == 8) ? 256 : 16;
++ return 0;
++}
++
++static int au1200_encode_var(struct fb_var_screeninfo *var,
++ const void *par, struct fb_info_gen *_info)
++{
++ *var = ((struct au1200fb_par *)par)->var;
++ return 0;
++}
++
++static void
++au1200_get_par(void *_par, struct fb_info_gen *_info)
++{
++ int index;
++
++ index = fbinfo2index((struct fb_info *)_info);
++ *(struct au1200fb_par *)_par = fb_pars[index];
++}
++
++static void au1200_set_par(const void *par, struct fb_info_gen *info)
++{
++ /* nothing to do: we don't change any settings */
++}
++
++static int au1200_getcolreg(unsigned regno, unsigned *red, unsigned *green,
++ unsigned *blue, unsigned *transp,
++ struct fb_info *info)
++{
++ struct au1200fb_info* i = (struct au1200fb_info*)info;
++
++ if (regno > 255)
++ return 1;
++
++ *red = i->palette[regno].red;
++ *green = i->palette[regno].green;
++ *blue = i->palette[regno].blue;
++ *transp = 0;
++
++ return 0;
++}
++
++static int au1200_setcolreg(unsigned regno, unsigned red, unsigned green,
++ unsigned blue, unsigned transp,
++ struct fb_info *info)
++{
++ struct au1200fb_info* i = (struct au1200fb_info *)info;
++ u32 rgbcol;
++ int plane, bpp;
++
++ plane = fbinfo2index((struct fb_info *)info);
++ bpp = winbpp(win->w[plane].mode_winctrl1);
++
++ if (regno > 255)
++ return 1;
++
++ i->palette[regno].red = red;
++ i->palette[regno].green = green;
++ i->palette[regno].blue = blue;
++
++ switch(bpp) {
++#ifdef FBCON_HAS_CFB8
++ case 8:
++ red >>= 10;
++ green >>= 10;
++ blue >>= 10;
++ panel_reg->lcd_pallettebase[regno] = (blue&0x1f) |
++ ((green&0x3f)<<5) | ((red&0x1f)<<11);
++ break;
++#endif
++#ifdef FBCON_HAS_CFB16
++/* FIX!!!! depends upon pixel format */
++ case 16:
++ i->fbcon_cmap16[regno] =
++ ((red & 0xf800) >> 0) |
++ ((green & 0xfc00) >> 5) |
++ ((blue & 0xf800) >> 11);
++ break;
++#endif
++#ifdef FBCON_HAS_CFB32
++ case 32:
++ i->fbcon_cmap32[regno] =
++ (((u32 )transp & 0xff00) << 16) |
++ (((u32 )red & 0xff00) << 8) |
++ (((u32 )green & 0xff00)) |
++ (((u32 )blue & 0xff00) >> 8);
++ break;
++#endif
++ default:
++ printk("unsupported au1200_setcolreg(%d)\n", bpp);
++ break;
++ }
++
++ return 0;
++}
++
++
++static int au1200_blank(int blank_mode, struct fb_info_gen *_info)
++{
++ struct au1200fb_info *fb_info = (struct au1200fb_info *)_info;
++ int plane;
++
++ /* Short-circuit screen blanking */
++ if (fb_info->noblanking)
++ return 0;
++
++ plane = fbinfo2index((struct fb_info *)_info);
++
++ switch (blank_mode) {
++ case VESA_NO_BLANKING:
++ /* printk("turn on panel\n"); */
++ au1200_setpanel(panel);
++ break;
++
++ case VESA_VSYNC_SUSPEND:
++ case VESA_HSYNC_SUSPEND:
++ case VESA_POWERDOWN:
++ /* printk("turn off panel\n"); */
++ au1200_setpanel(NULL);
++ break;
++ default:
++ break;
++
++ }
++ return 0;
++}
++
++static void au1200_set_disp(const void *unused, struct display *disp,
++ struct fb_info_gen *info)
++{
++ struct au1200fb_info *fb_info;
++ int plane;
++
++ fb_info = (struct au1200fb_info *)info;
++
++ disp->screen_base = (char *)fb_info->fb_virt_start;
++
++ switch (disp->var.bits_per_pixel) {
++#ifdef FBCON_HAS_CFB8
++ case 8:
++ disp->dispsw = &fbcon_cfb8;
++ if (fb_info->nohwcursor)
++ fbcon_cfb8.cursor = au1200_nocursor;
++ break;
++#endif
++#ifdef FBCON_HAS_CFB16
++ case 16:
++ disp->dispsw = &fbcon_cfb16;
++ disp->dispsw_data = fb_info->fbcon_cmap16;
++ if (fb_info->nohwcursor)
++ fbcon_cfb16.cursor = au1200_nocursor;
++ break;
++#endif
++#ifdef FBCON_HAS_CFB32
++ case 32:
++ disp->dispsw = &fbcon_cfb32;
++ disp->dispsw_data = fb_info->fbcon_cmap32;
++ if (fb_info->nohwcursor)
++ fbcon_cfb32.cursor = au1200_nocursor;
++ break;
++#endif
++ default:
++ disp->dispsw = &fbcon_dummy;
++ disp->dispsw_data = NULL;
++ break;
++ }
++}
++
++static int
++au1200fb_mmap(struct fb_info *_fb,
++ struct file *file,
++ struct vm_area_struct *vma)
++{
++ unsigned int len;
++ unsigned long start=0, off;
++
++ struct au1200fb_info *fb_info = (struct au1200fb_info *)_fb;
++
++ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
++ return -EINVAL;
++ }
++
++ start = fb_info->fb_phys & PAGE_MASK;
++ len = PAGE_ALIGN((start & ~PAGE_MASK) + fb_info->fb_size);
++
++ off = vma->vm_pgoff << PAGE_SHIFT;
++
++ if ((vma->vm_end - vma->vm_start + off) > len) {
++ return -EINVAL;
++ }
++
++ off += start;
++ vma->vm_pgoff = off >> PAGE_SHIFT;
++
++ pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
++ pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;
++
++ /* This is an IO map - tell maydump to skip this VMA */
++ vma->vm_flags |= VM_IO;
++
++ if (io_remap_page_range(vma->vm_start, off,
++ vma->vm_end - vma->vm_start,
++ vma->vm_page_prot)) {
++ return -EAGAIN;
++ }
++
++ fb_info->mmaped = 1;
++ return 0;
++}
++
++int au1200_pan_display(const struct fb_var_screeninfo *var,
++ struct fb_info_gen *info)
++{
++ return 0;
++}
++
++
++static int au1200fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
++ u_long arg, int con, struct fb_info *info)
++{
++ int plane;
++
++ plane = fbinfo2index(info);
++
++ /* printk("au1200fb: ioctl %d on plane %d\n", cmd, plane); */
++
++ if (cmd == 0x46FF)
++ {
++ au1200_lcd_getset_t iodata;
++
++ if (copy_from_user(&iodata, (void *) arg, sizeof(au1200_lcd_getset_t)))
++ return -EFAULT;
++
++ switch (iodata.subcmd)
++ {
++ case AU1200_LCD_GET_WINENABLE:
++ iodata.winenable.enable = (lcd->winenable & (1<<plane)) ? 1 : 0;
++ break;
++ case AU1200_LCD_SET_WINENABLE:
++ {
++ u32 winenable;
++ winenable = lcd->winenable;
++ winenable &= ~(1<<plane);
++ winenable |= (iodata.winenable.enable) ? (1<<plane) : 0;
++ lcd->winenable = winenable;
++ }
++ break;
++ case AU1200_LCD_GET_WINLOCATION:
++ iodata.winlocation.x =
++ (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OX) >> 21;
++ iodata.winlocation.y =
++ (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OY) >> 10;
++ break;
++ case AU1200_LCD_SET_WINLOCATION:
++ au1200_setlocation(plane, iodata.winlocation.x, iodata.winlocation.y);
++ break;
++ case AU1200_LCD_GET_WINSIZE:
++ iodata.winsize.hsz =
++ (lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZX) >> 11;
++ iodata.winsize.vsz =
++ (lcd->window[plane].winctrl0 & LCD_WINCTRL1_SZY) >> 0;
++ break;
++ case AU1200_LCD_SET_WINSIZE:
++ au1200_setsize(plane, iodata.winsize.hsz, iodata.winsize.vsz);
++ break;
++ case AU1200_LCD_GET_BACKCOLOR:
++ iodata.backcolor.color = lcd->backcolor;
++ break;
++ case AU1200_LCD_SET_BACKCOLOR:
++ lcd->backcolor = iodata.backcolor.color;
++ break;
++ case AU1200_LCD_GET_COLORKEY:
++ iodata.colorkey.key = lcd->colorkey;
++ iodata.colorkey.mask = lcd->colorkeymsk;
++ break;
++ case AU1200_LCD_SET_COLORKEY:
++ lcd->colorkey = iodata.colorkey.key;
++ lcd->colorkeymsk = iodata.colorkey.mask;
++ break;
++ case AU1200_LCD_GET_PANEL:
++ iodata.panel.panel = panel_index;
++ break;
++ case AU1200_LCD_SET_PANEL:
++ if ((iodata.panel.panel >= 0) && (iodata.panel.panel < NUM_PANELS))
++ {
++ struct panel_settings *newpanel;
++ panel_index = iodata.panel.panel;
++ newpanel = &panels[panel_index];
++ au1200_setpanel(newpanel);
++ }
++ break;
++ }
++
++ return copy_to_user((void *) arg, &iodata, sizeof(au1200_lcd_getset_t)) ? -EFAULT : 0;
++ }
++
++ return -EINVAL;
++}
++
++static struct fbgen_hwswitch au1200_switch = {
++ au1200_detect,
++ au1200_encode_fix,
++ au1200_decode_var,
++ au1200_encode_var,
++ au1200_get_par,
++ au1200_set_par,
++ au1200_getcolreg,
++ au1200_setcolreg,
++ au1200_pan_display,
++ au1200_blank,
++ au1200_set_disp
++};
++
++static void au1200_setpanel (struct panel_settings *newpanel)
++{
++ /*
++ * Perform global setup/init of LCD controller
++ */
++ uint32 winenable;
++
++ /* Make sure all windows disabled */
++ winenable = lcd->winenable;
++ lcd->winenable = 0;
++
++ /*
++ * Ensure everything is disabled before reconfiguring
++ */
++ if (lcd->screen & LCD_SCREEN_SEN)
++ {
++ /* Wait for vertical sync period */
++ lcd->intstatus = LCD_INT_SS;
++ while ((lcd->intstatus & LCD_INT_SS) == 0)
++ ;
++
++ lcd->screen &= ~LCD_SCREEN_SEN; /*disable the controller*/
++
++ do
++ {
++ lcd->intstatus = lcd->intstatus; /*clear interrupts*/
++ }
++ /*wait for controller to shut down*/
++ while ((lcd->intstatus & LCD_INT_SD) == 0);
++
++ /* Call shutdown of current panel (if up) */
++ /* this must occur last, because if an external clock is driving
++ the controller, the clock cannot be turned off before first
++ shutting down the controller.
++ */
++ if (panel->device_shutdown != NULL) panel->device_shutdown();
++ }
++
++ /* Check if only needing to turn off panel */
++ if (panel == NULL) return;
++
++ panel = newpanel;
++
++ printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres);
++
++ /*
++ * Setup clocking if internal LCD clock source (assumes sys_auxpll valid)
++ */
++ if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT))
++ {
++ uint32 sys_clksrc;
++ /* WARNING! This should really be a check since other peripherals can
++ be affected by changins sys_auxpll */
++ au_writel(panel->mode_auxpll, SYS_AUXPLL);
++ sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f;
++ sys_clksrc |= panel->mode_toyclksrc;
++ au_writel(sys_clksrc, SYS_CLKSRC);
++ }
++
++ /*
++ * Configure panel timings
++ */
++ lcd->screen = panel->mode_screen;
++ lcd->horztiming = panel->mode_horztiming;
++ lcd->verttiming = panel->mode_verttiming;
++ lcd->clkcontrol = panel->mode_clkcontrol;
++ lcd->pwmdiv = panel->mode_pwmdiv;
++ lcd->pwmhi = panel->mode_pwmhi;
++ lcd->outmask = panel->mode_outmask;
++ lcd->fifoctrl = panel->mode_fifoctrl;
++ au_sync();
++
++ /* FIX!!! Check window settings to make sure still valid for new geometry */
++ au1200_setlocation(0, win->w[0].xpos, win->w[0].ypos);
++ au1200_setlocation(1, win->w[1].xpos, win->w[1].ypos);
++ au1200_setlocation(2, win->w[2].xpos, win->w[2].ypos);
++ au1200_setlocation(3, win->w[3].xpos, win->w[3].ypos);
++ lcd->winenable = winenable;
++
++ /*
++ * Re-enable screen now that it is configured
++ */
++ lcd->screen |= LCD_SCREEN_SEN;
++ au_sync();
++
++ /* Call init of panel */
++ if (panel->device_init != NULL) panel->device_init();
++
++#if 0
++#define D(X) printk("%25s: %08X\n", #X, X)
++ D(lcd->screen);
++ D(lcd->horztiming);
++ D(lcd->verttiming);
++ D(lcd->clkcontrol);
++ D(lcd->pwmdiv);
++ D(lcd->pwmhi);
++ D(lcd->outmask);
++ D(lcd->fifoctrl);
++ D(lcd->window[0].winctrl0);
++ D(lcd->window[0].winctrl1);
++ D(lcd->window[0].winctrl2);
++ D(lcd->window[0].winbuf0);
++ D(lcd->window[0].winbuf1);
++ D(lcd->window[0].winbufctrl);
++ D(lcd->window[1].winctrl0);
++ D(lcd->window[1].winctrl1);
++ D(lcd->window[1].winctrl2);
++ D(lcd->window[1].winbuf0);
++ D(lcd->window[1].winbuf1);
++ D(lcd->window[1].winbufctrl);
++ D(lcd->window[2].winctrl0);
++ D(lcd->window[2].winctrl1);
++ D(lcd->window[2].winctrl2);
++ D(lcd->window[2].winbuf0);
++ D(lcd->window[2].winbuf1);
++ D(lcd->window[2].winbufctrl);
++ D(lcd->window[3].winctrl0);
++ D(lcd->window[3].winctrl1);
++ D(lcd->window[3].winctrl2);
++ D(lcd->window[3].winbuf0);
++ D(lcd->window[3].winbuf1);
++ D(lcd->window[3].winbufctrl);
++ D(lcd->winenable);
++ D(lcd->intenable);
++ D(lcd->intstatus);
++ D(lcd->backcolor);
++ D(lcd->winenable);
++ D(lcd->colorkey);
++ D(lcd->colorkeymsk);
++ D(lcd->hwc.cursorctrl);
++ D(lcd->hwc.cursorpos);
++ D(lcd->hwc.cursorcolor0);
++ D(lcd->hwc.cursorcolor1);
++ D(lcd->hwc.cursorcolor2);
++ D(lcd->hwc.cursorcolor3);
++#endif
++}
++
++static int au1200_setsize (int plane, int xres, int yres)
++{
++#if 0
++ uint32 winctrl0, winctrl1, winenable;
++ int xsz, ysz;
++
++ /* FIX!!! X*Y can not surpass allocated memory */
++
++ printk("setsize: x %d y %d\n", xres, yres);
++ winctrl1 = lcd->window[plane].winctrl1;
++ printk("org winctrl1 %08X\n", winctrl1);
++ winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY);
++
++ xres -= 1;
++ yres -= 1;
++ winctrl1 |= (xres << 11);
++ winctrl1 |= (yres << 0);
++
++ printk("new winctrl1 %08X\n", winctrl1);
++
++ /*winenable = lcd->winenable & (1 << plane); */
++ /*lcd->winenable &= ~(1 << plane); */
++ lcd->window[plane].winctrl1 = winctrl1;
++ /*lcd->winenable |= winenable; */
++#endif
++ return 0;
++}
++
++static int au1200_setlocation (int plane, int xpos, int ypos)
++{
++ uint32 winctrl0, winctrl1, winenable, fb_offset = 0;
++ int xsz, ysz;
++
++ /* FIX!!! NOT CHECKING FOR COMPLETE OFFSCREEN YET */
++
++ winctrl0 = lcd->window[plane].winctrl0;
++ winctrl1 = lcd->window[plane].winctrl1;
++ winctrl0 &= (LCD_WINCTRL0_A | LCD_WINCTRL0_AEN);
++ winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY);
++
++ /* Check for off-screen adjustments */
++ xsz = win->w[plane].xres;
++ ysz = win->w[plane].yres;
++ if ((xpos + win->w[plane].xres) > panel->Xres)
++ {
++ /* Off-screen to the right */
++ xsz = panel->Xres - xpos; /* off by 1 ??? */
++ /*printk("off screen right\n");*/
++ }
++
++ if ((ypos + win->w[plane].yres) > panel->Yres)
++ {
++ /* Off-screen to the bottom */
++ ysz = panel->Yres - ypos; /* off by 1 ??? */
++ /*printk("off screen bottom\n");*/
++ }
++
++ if (xpos < 0)
++ {
++ /* Off-screen to the left */
++ xsz = win->w[plane].xres + xpos;
++ fb_offset += (((0 - xpos) * winbpp(lcd->window[plane].winctrl1))/8);
++ xpos = 0;
++ /*printk("off screen left\n");*/
++ }
++
++ if (ypos < 0)
++ {
++ /* Off-screen to the top */
++ ysz = win->w[plane].yres + ypos;
++ fb_offset += ((0 - ypos) * fb_pars[plane].line_length);
++ ypos = 0;
++ /*printk("off screen top\n");*/
++ }
++
++ /* record settings */
++ win->w[plane].xpos = xpos;
++ win->w[plane].ypos = ypos;
++
++ xsz -= 1;
++ ysz -= 1;
++ winctrl0 |= (xpos << 21);
++ winctrl0 |= (ypos << 10);
++ winctrl1 |= (xsz << 11);
++ winctrl1 |= (ysz << 0);
++
++ /* Disable the window while making changes, then restore WINEN */
++ winenable = lcd->winenable & (1 << plane);
++ lcd->winenable &= ~(1 << plane);
++ lcd->window[plane].winctrl0 = winctrl0;
++ lcd->window[plane].winctrl1 = winctrl1;
++ lcd->window[plane].winbuf0 =
++ lcd->window[plane].winbuf1 = fb_infos[plane].fb_phys + fb_offset;
++ lcd->window[plane].winbufctrl = 0; /* select winbuf0 */
++ lcd->winenable |= winenable;
++
++ return 0;
++}
++
++static void au1200_setmode(int plane)
++{
++ /* Window/plane setup */
++ lcd->window[plane].winctrl1 = ( 0
++ | LCD_WINCTRL1_PRI_N(plane)
++ | win->w[plane].mode_winctrl1 /* FRM,CCO,PO,PIPE */
++ ) ;
++
++ au1200_setlocation(plane, win->w[plane].xpos, win->w[plane].ypos);
++
++ lcd->window[plane].winctrl2 = ( 0
++ | LCD_WINCTRL2_CKMODE_00
++ | LCD_WINCTRL2_DBM
++/* | LCD_WINCTRL2_RAM */
++ | LCD_WINCTRL2_BX_N(fb_pars[plane].line_length)
++ | LCD_WINCTRL2_SCX_1
++ | LCD_WINCTRL2_SCY_1
++ ) ;
++ lcd->winenable |= win->w[plane].mode_winenable;
++ au_sync();
++
++}
++
++static unsigned long
++au1200fb_alloc_fbmem (unsigned long size)
++{
++ /* __get_free_pages() fulfills a max request of 2MB */
++ /* do multiple requests to obtain large contigous mem */
++#define MAX_GFP 0x00200000
++
++ unsigned long mem, amem, alloced = 0, allocsize;
++
++ size += 0x1000;
++ allocsize = (size < MAX_GFP) ? size : MAX_GFP;
++
++ /* Get first chunk */
++ mem = (unsigned long )
++ __get_free_pages(GFP_ATOMIC | GFP_DMA, get_order(allocsize));
++ if (mem != 0) alloced = allocsize;
++
++ /* Get remaining, contiguous chunks */
++ while (alloced < size)
++ {
++ amem = (unsigned long )
++ __get_free_pages(GFP_ATOMIC | GFP_DMA, get_order(allocsize));
++ if (amem != 0)
++ alloced += allocsize;
++
++ /* check for contiguous mem alloced */
++ if ((amem == 0) || (amem + allocsize) != mem)
++ break;
++ else
++ mem = amem;
++ }
++ return mem;
++}
++
++int __init au1200fb_init(void)
++{
++ int num_panels = sizeof(panels)/sizeof(struct panel_settings);
++ struct au1200fb_info *fb_info;
++ struct display *disp;
++ struct au1200fb_par *par;
++ unsigned long page;
++ int plane, bpp;
++
++ /*
++ * Get the panel information/display mode
++ */
++ if (panel_index < 0)
++ panel_index = board_au1200fb_panel();
++ if ((panel_index < 0) || (panel_index >= num_panels)) {
++ printk("ERROR: INVALID PANEL %d\n", panel_index);
++ return -EINVAL;
++ }
++ panel = &panels[panel_index];
++ win = &windows[window_index];
++
++ printk("au1200fb: Panel %d %s\n", panel_index, panel->name);
++ printk("au1200fb: Win %d %s\n", window_index, win->name);
++
++ /* Global setup/init */
++ au1200_setpanel(panel);
++ lcd->intenable = 0;
++ lcd->intstatus = ~0;
++ lcd->backcolor = win->mode_backcolor;
++ lcd->winenable = 0;
++
++ /* Setup Color Key - FIX!!! */
++ lcd->colorkey = win->mode_colorkey;
++ lcd->colorkeymsk = win->mode_colorkeymsk;
++
++ /* Setup HWCursor - FIX!!! Need to support this eventually */
++ lcd->hwc.cursorctrl = 0;
++ lcd->hwc.cursorpos = 0;
++ lcd->hwc.cursorcolor0 = 0;
++ lcd->hwc.cursorcolor1 = 0;
++ lcd->hwc.cursorcolor2 = 0;
++ lcd->hwc.cursorcolor3 = 0;
++
++ /* Register each plane as a frame buffer device */
++ for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane)
++ {
++ fb_info = &fb_infos[plane];
++ disp = &disps[plane];
++ par = &fb_pars[plane];
++
++ bpp = winbpp(win->w[plane].mode_winctrl1);
++ if (win->w[plane].xres == 0)
++ win->w[plane].xres = panel->Xres;
++ if (win->w[plane].yres == 0)
++ win->w[plane].yres = panel->Yres;
++
++ par->var.xres =
++ par->var.xres_virtual = win->w[plane].xres;
++ par->var.yres =
++ par->var.yres_virtual = win->w[plane].yres;
++ par->var.bits_per_pixel = bpp;
++ par->line_length = win->w[plane].xres * bpp / 8; /* in bytes */
++ /*
++ * Allocate LCD framebuffer from system memory
++ * Set page reserved so that mmap will work. This is necessary
++ * since we'll be remapping normal memory.
++ */
++ fb_info->fb_size = (win->w[plane].xres * win->w[plane].yres * bpp) / 8;
++ fb_info->fb_virt_start = au1200fb_alloc_fbmem(fb_info->fb_size);
++ if (!fb_info->fb_virt_start) {
++ printk("Unable to allocate fb memory\n");
++ return -ENOMEM;
++ }
++ fb_info->fb_phys = virt_to_bus((void *)fb_info->fb_virt_start);
++ for (page = fb_info->fb_virt_start;
++ page < PAGE_ALIGN(fb_info->fb_virt_start + fb_info->fb_size);
++ page += PAGE_SIZE) {
++ SetPageReserved(virt_to_page(page));
++ }
++ /* Convert to kseg1 */
++ fb_info->fb_virt_start =
++ (void *)((u32)fb_info->fb_virt_start | 0xA0000000);
++ /* FIX!!! may wish to avoid this to save startup time??? */
++ memset((void *)fb_info->fb_virt_start, 0, fb_info->fb_size);
++
++ fb_info->gen.parsize = sizeof(struct au1200fb_par);
++ fb_info->gen.fbhw = &au1200_switch;
++ strcpy(fb_info->gen.info.modename, "Au1200 LCD");
++ fb_info->gen.info.changevar = NULL;
++ fb_info->gen.info.node = -1;
++
++ fb_info->gen.info.fbops = &au1200fb_ops;
++ fb_info->gen.info.disp = disp;
++ fb_info->gen.info.switch_con = &fbgen_switch;
++ fb_info->gen.info.updatevar = &fbgen_update_var;
++ fb_info->gen.info.blank = &fbgen_blank;
++ fb_info->gen.info.flags = FBINFO_FLAG_DEFAULT;
++
++ fb_info->nohwcursor = 1;
++ fb_info->noblanking = 1;
++
++ /* This should give a reasonable default video mode */
++ fbgen_get_var(&disp->var, -1, &fb_info->gen.info);
++ fbgen_do_set_var(&disp->var, 1, &fb_info->gen);
++ fbgen_set_disp(-1, &fb_info->gen);
++ fbgen_install_cmap(0, &fb_info->gen);
++
++ /* Turn on plane */
++ au1200_setmode(plane);
++
++ if (register_framebuffer(&fb_info->gen.info) < 0)
++ return -EINVAL;
++
++ printk(KERN_INFO "fb%d: %s plane %d @ %08X (%d x %d x %d)\n",
++ GET_FB_IDX(fb_info->gen.info.node),
++ fb_info->gen.info.modename, plane, fb_info->fb_phys,
++ win->w[plane].xres, win->w[plane].yres, bpp);
++ }
++ /* uncomment this if your driver cannot be unloaded */
++ /* MOD_INC_USE_COUNT; */
++ return 0;
++}
++
++void au1200fb_setup(char *options, int *ints)
++{
++ char* this_opt;
++ int i;
++ int num_panels = sizeof(panels)/sizeof(struct panel_settings);
++
++ if (!options || !*options)
++ return;
++
++ for(this_opt=strtok(options, ","); this_opt;
++ this_opt=strtok(NULL, ",")) {
++ if (!strncmp(this_opt, "panel:", 6)) {
++ int i;
++ long int li;
++ char *endptr;
++ this_opt += 6;
++
++ /* Panel name can be name, "bs" for board-switch, or number/index */
++ li = simple_strtol(this_opt, &endptr, 0);
++ if (*endptr == '\0') {
++ panel_index = (int)li;
++ }
++ else if (strcmp(this_opt, "bs") == 0) {
++ panel_index = board_au1200fb_panel();
++ }
++ else
++ for (i=0; i<num_panels; i++) {
++ if (!strcmp(this_opt, panels[i].name)) {
++ panel_index = i;
++ break;
++ }
++ }
++ }
++ else if (!strncmp(this_opt, "nohwcursor", 10)) {
++ printk("nohwcursor\n");
++ fb_infos[0].nohwcursor = 1;
++ }
++ }
++
++ printk("au1200fb: Panel %d %s\n", panel_index,
++ panels[panel_index].name);
++}
++
++
++
++#ifdef MODULE
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Au1200 LCD framebuffer driver");
++
++void au1200fb_cleanup(struct fb_info *info)
++{
++ unregister_framebuffer(info);
++}
++
++module_init(au1200fb_init);
++module_exit(au1200fb_cleanup);
++#endif /* MODULE */
++
++
+diff -Nur linux-2.4.32-rc1/drivers/video/au1200fb.h linux-2.4.32-rc1.mips/drivers/video/au1200fb.h
+--- linux-2.4.32-rc1/drivers/video/au1200fb.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/video/au1200fb.h 2005-02-11 22:16:44.000000000 +0100
+@@ -0,0 +1,288 @@
++/*
++ * BRIEF MODULE DESCRIPTION
++ * Hardware definitions for the Au1200 LCD controller
++ *
++ * Copyright 2004 AMD
++ * Author: AMD
++ *
++ * 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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 _AU1200LCD_H
++#define _AU1200LCD_H
++
++/********************************************************************/
++#define AU1200_LCD_ADDR 0xB5000000
++
++#define uint8 unsigned char
++#define uint32 unsigned int
++
++typedef volatile struct
++{
++ uint32 reserved0;
++ uint32 screen;
++ uint32 backcolor;
++ uint32 horztiming;
++ uint32 verttiming;
++ uint32 clkcontrol;
++ uint32 pwmdiv;
++ uint32 pwmhi;
++ uint32 reserved1;
++ uint32 winenable;
++ uint32 colorkey;
++ uint32 colorkeymsk;
++ struct
++ {
++ uint32 cursorctrl;
++ uint32 cursorpos;
++ uint32 cursorcolor0;
++ uint32 cursorcolor1;
++ uint32 cursorcolor2;
++ uint32 cursorcolor3;
++ } hwc;
++ uint32 intstatus;
++ uint32 intenable;
++ uint32 outmask;
++ uint32 fifoctrl;
++ uint32 reserved2[(0x0100-0x0058)/4];
++ struct
++ {
++ uint32 winctrl0;
++ uint32 winctrl1;
++ uint32 winctrl2;
++ uint32 winbuf0;
++ uint32 winbuf1;
++ uint32 winbufctrl;
++ uint32 winreserved0;
++ uint32 winreserved1;
++ } window[4];
++
++ uint32 reserved3[(0x0400-0x0180)/4];
++
++ uint32 palette[(0x0800-0x0400)/4];
++
++ uint8 cursorpattern[256];
++
++} AU1200_LCD;
++
++/* lcd_screen */
++#define LCD_SCREEN_SEN (1<<31)
++#define LCD_SCREEN_SX (0x07FF<<19)
++#define LCD_SCREEN_SY (0x07FF<< 8)
++#define LCD_SCREEN_SWP (1<<7)
++#define LCD_SCREEN_SWD (1<<6)
++#define LCD_SCREEN_ST (7<<0)
++#define LCD_SCREEN_ST_TFT (0<<0)
++#define LCD_SCREEN_SX_N(WIDTH) ((WIDTH-1)<<19)
++#define LCD_SCREEN_SY_N(HEIGHT) ((HEIGHT-1)<<8)
++#define LCD_SCREEN_ST_CSTN (1<<0)
++#define LCD_SCREEN_ST_CDSTN (2<<0)
++#define LCD_SCREEN_ST_M8STN (3<<0)
++#define LCD_SCREEN_ST_M4STN (4<<0)
++
++/* lcd_backcolor */
++#define LCD_BACKCOLOR_SBGR (0xFF<<16)
++#define LCD_BACKCOLOR_SBGG (0xFF<<8)
++#define LCD_BACKCOLOR_SBGB (0xFF<<0)
++#define LCD_BACKCOLOR_SBGR_N(N) ((N)<<16)
++#define LCD_BACKCOLOR_SBGG_N(N) ((N)<<8)
++#define LCD_BACKCOLOR_SBGB_N(N) ((N)<<0)
++
++/* lcd_winenable */
++#define LCD_WINENABLE_WEN3 (1<<3)
++#define LCD_WINENABLE_WEN2 (1<<2)
++#define LCD_WINENABLE_WEN1 (1<<1)
++#define LCD_WINENABLE_WEN0 (1<<0)
++
++/* lcd_colorkey */
++#define LCD_COLORKEY_CKR (0xFF<<16)
++#define LCD_COLORKEY_CKG (0xFF<<8)
++#define LCD_COLORKEY_CKB (0xFF<<0)
++#define LCD_COLORKEY_CKR_N(N) ((N)<<16)
++#define LCD_COLORKEY_CKG_N(N) ((N)<<8)
++#define LCD_COLORKEY_CKB_N(N) ((N)<<0)
++
++/* lcd_colorkeymsk */
++#define LCD_COLORKEYMSK_CKMR (0xFF<<16)
++#define LCD_COLORKEYMSK_CKMG (0xFF<<8)
++#define LCD_COLORKEYMSK_CKMB (0xFF<<0)
++#define LCD_COLORKEYMSK_CKMR_N(N) ((N)<<16)
++#define LCD_COLORKEYMSK_CKMG_N(N) ((N)<<8)
++#define LCD_COLORKEYMSK_CKMB_N(N) ((N)<<0)
++
++/* lcd windows control 0 */
++#define LCD_WINCTRL0_OX (0x07FF<<21)
++#define LCD_WINCTRL0_OY (0x07FF<<10)
++#define LCD_WINCTRL0_A (0x00FF<<2)
++#define LCD_WINCTRL0_AEN (1<<1)
++#define LCD_WINCTRL0_OX_N(N) ((N)<<21)
++#define LCD_WINCTRL0_OY_N(N) ((N)<<10)
++#define LCD_WINCTRL0_A_N(N) ((N)<<2)
++
++/* lcd windows control 1 */
++#define LCD_WINCTRL1_PRI (3<<30)
++#define LCD_WINCTRL1_PIPE (1<<29)
++#define LCD_WINCTRL1_FRM (0xF<<25)
++#define LCD_WINCTRL1_CCO (1<<24)
++#define LCD_WINCTRL1_PO (3<<22)
++#define LCD_WINCTRL1_SZX (0x07FF<<11)
++#define LCD_WINCTRL1_SZY (0x07FF<<0)
++#define LCD_WINCTRL1_FRM_1BPP (0<<25)
++#define LCD_WINCTRL1_FRM_2BPP (1<<25)
++#define LCD_WINCTRL1_FRM_4BPP (2<<25)
++#define LCD_WINCTRL1_FRM_8BPP (3<<25)
++#define LCD_WINCTRL1_FRM_12BPP (4<<25)
++#define LCD_WINCTRL1_FRM_16BPP655 (5<<25)
++#define LCD_WINCTRL1_FRM_16BPP565 (6<<25)
++#define LCD_WINCTRL1_FRM_16BPP556 (7<<25)
++#define LCD_WINCTRL1_FRM_16BPPI1555 (8<<25)
++#define LCD_WINCTRL1_FRM_16BPPI5551 (9<<25)
++#define LCD_WINCTRL1_FRM_16BPPA1555 (10<<25)
++#define LCD_WINCTRL1_FRM_16BPPA5551 (11<<25)
++#define LCD_WINCTRL1_FRM_24BPP (12<<25)
++#define LCD_WINCTRL1_FRM_32BPP (13<<25)
++#define LCD_WINCTRL1_PRI_N(N) ((N)<<30)
++#define LCD_WINCTRL1_PO_00 (0<<22)
++#define LCD_WINCTRL1_PO_01 (1<<22)
++#define LCD_WINCTRL1_PO_10 (2<<22)
++#define LCD_WINCTRL1_PO_11 (3<<22)
++#define LCD_WINCTRL1_SZX_N(N) ((N-1)<<11)
++#define LCD_WINCTRL1_SZY_N(N) ((N-1)<<0)
++
++/* lcd windows control 2 */
++#define LCD_WINCTRL2_CKMODE (3<<24)
++#define LCD_WINCTRL2_DBM (1<<23)
++#define LCD_WINCTRL2_RAM (3<<21)
++#define LCD_WINCTRL2_BX (0x1FFF<<8)
++#define LCD_WINCTRL2_SCX (0xF<<4)
++#define LCD_WINCTRL2_SCY (0xF<<0)
++#define LCD_WINCTRL2_CKMODE_00 (0<<24)
++#define LCD_WINCTRL2_CKMODE_01 (1<<24)
++#define LCD_WINCTRL2_CKMODE_10 (2<<24)
++#define LCD_WINCTRL2_CKMODE_11 (3<<24)
++#define LCD_WINCTRL2_RAM_NONE (0<<21)
++#define LCD_WINCTRL2_RAM_PALETTE (1<<21)
++#define LCD_WINCTRL2_RAM_GAMMA (2<<21)
++#define LCD_WINCTRL2_RAM_BUFFER (3<<21)
++#define LCD_WINCTRL2_BX_N(N) ((N)<<8)
++#define LCD_WINCTRL2_SCX_1 (0<<4)
++#define LCD_WINCTRL2_SCX_2 (1<<4)
++#define LCD_WINCTRL2_SCX_4 (2<<4)
++#define LCD_WINCTRL2_SCY_1 (0<<0)
++#define LCD_WINCTRL2_SCY_2 (1<<0)
++#define LCD_WINCTRL2_SCY_4 (2<<0)
++
++/* lcd windows buffer control */
++#define LCD_WINBUFCTRL_DB (1<<1)
++#define LCD_WINBUFCTRL_DBN (1<<0)
++
++/* lcd_intstatus, lcd_intenable */
++#define LCD_INT_IFO (0xF<<14)
++#define LCD_INT_IFU (0xF<<10)
++#define LCD_INT_OFO (1<<9)
++#define LCD_INT_OFU (1<<8)
++#define LCD_INT_WAIT (1<<3)
++#define LCD_INT_SD (1<<2)
++#define LCD_INT_SA (1<<1)
++#define LCD_INT_SS (1<<0)
++
++/* lcd_horztiming */
++#define LCD_HORZTIMING_HND2 (0x1FF<<18)
++#define LCD_HORZTIMING_HND1 (0x1FF<<9)
++#define LCD_HORZTIMING_HPW (0x1FF<<0)
++#define LCD_HORZTIMING_HND2_N(N)(((N)-1)<<18)
++#define LCD_HORZTIMING_HND1_N(N)(((N)-1)<<9)
++#define LCD_HORZTIMING_HPW_N(N) (((N)-1)<<0)
++
++/* lcd_verttiming */
++#define LCD_VERTTIMING_VND2 (0x1FF<<18)
++#define LCD_VERTTIMING_VND1 (0x1FF<<9)
++#define LCD_VERTTIMING_VPW (0x1FF<<0)
++#define LCD_VERTTIMING_VND2_N(N)(((N)-1)<<18)
++#define LCD_VERTTIMING_VND1_N(N)(((N)-1)<<9)
++#define LCD_VERTTIMING_VPW_N(N) (((N)-1)<<0)
++
++/* lcd_clkcontrol */
++#define LCD_CLKCONTROL_EXT (1<<22)
++#define LCD_CLKCONTROL_DELAY (3<<20)
++#define LCD_CLKCONTROL_CDD (1<<19)
++#define LCD_CLKCONTROL_IB (1<<18)
++#define LCD_CLKCONTROL_IC (1<<17)
++#define LCD_CLKCONTROL_IH (1<<16)
++#define LCD_CLKCONTROL_IV (1<<15)
++#define LCD_CLKCONTROL_BF (0x1F<<10)
++#define LCD_CLKCONTROL_PCD (0x3FF<<0)
++#define LCD_CLKCONTROL_BF_N(N) (((N)-1)<<10)
++#define LCD_CLKCONTROL_PCD_N(N) ((N)<<0)
++
++/* lcd_pwmdiv */
++#define LCD_PWMDIV_EN (1<<31)
++#define LCD_PWMDIV_PWMDIV (0x1FFFF<<0)
++#define LCD_PWMDIV_PWMDIV_N(N) ((N)<<0)
++
++/* lcd_pwmhi */
++#define LCD_PWMHI_PWMHI1 (0xFFFF<<16)
++#define LCD_PWMHI_PWMHI0 (0xFFFF<<0)
++#define LCD_PWMHI_PWMHI1_N(N) ((N)<<16)
++#define LCD_PWMHI_PWMHI0_N(N) ((N)<<0)
++
++/* lcd_hwccon */
++#define LCD_HWCCON_EN (1<<0)
++
++/* lcd_cursorpos */
++#define LCD_CURSORPOS_HWCXOFF (0x1F<<27)
++#define LCD_CURSORPOS_HWCXPOS (0x07FF<<16)
++#define LCD_CURSORPOS_HWCYOFF (0x1F<<11)
++#define LCD_CURSORPOS_HWCYPOS (0x07FF<<0)
++#define LCD_CURSORPOS_HWCXOFF_N(N) ((N)<<27)
++#define LCD_CURSORPOS_HWCXPOS_N(N) ((N)<<16)
++#define LCD_CURSORPOS_HWCYOFF_N(N) ((N)<<11)
++#define LCD_CURSORPOS_HWCYPOS_N(N) ((N)<<0)
++
++/* lcd_cursorcolor */
++#define LCD_CURSORCOLOR_HWCA (0xFF<<24)
++#define LCD_CURSORCOLOR_HWCR (0xFF<<16)
++#define LCD_CURSORCOLOR_HWCG (0xFF<<8)
++#define LCD_CURSORCOLOR_HWCB (0xFF<<0)
++#define LCD_CURSORCOLOR_HWCA_N(N) ((N)<<24)
++#define LCD_CURSORCOLOR_HWCR_N(N) ((N)<<16)
++#define LCD_CURSORCOLOR_HWCG_N(N) ((N)<<8)
++#define LCD_CURSORCOLOR_HWCB_N(N) ((N)<<0)
++
++/* lcd_fifoctrl */
++#define LCD_FIFOCTRL_F3IF (1<<29)
++#define LCD_FIFOCTRL_F3REQ (0x1F<<24)
++#define LCD_FIFOCTRL_F2IF (1<<29)
++#define LCD_FIFOCTRL_F2REQ (0x1F<<16)
++#define LCD_FIFOCTRL_F1IF (1<<29)
++#define LCD_FIFOCTRL_F1REQ (0x1F<<8)
++#define LCD_FIFOCTRL_F0IF (1<<29)
++#define LCD_FIFOCTRL_F0REQ (0x1F<<0)
++#define LCD_FIFOCTRL_F3REQ_N(N) ((N-1)<<24)
++#define LCD_FIFOCTRL_F2REQ_N(N) ((N-1)<<16)
++#define LCD_FIFOCTRL_F1REQ_N(N) ((N-1)<<8)
++#define LCD_FIFOCTRL_F0REQ_N(N) ((N-1)<<0)
++
++/* lcd_outmask */
++#define LCD_OUTMASK_MASK (0x00FFFFFF)
++
++/********************************************************************/
++#endif /* _AU1200LCD_H */
+diff -Nur linux-2.4.32-rc1/drivers/video/Config.in linux-2.4.32-rc1.mips/drivers/video/Config.in
+--- linux-2.4.32-rc1/drivers/video/Config.in 2004-02-18 14:36:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/video/Config.in 2005-02-11 22:16:44.000000000 +0100
+@@ -87,8 +87,8 @@
+ if [ "$CONFIG_HP300" = "y" ]; then
+ define_bool CONFIG_FB_HP300 y
+ fi
+- if [ "$ARCH" = "alpha" ]; then
+- tristate ' TGA framebuffer support' CONFIG_FB_TGA
++ if [ "$ARCH" = "alpha" -o "$CONFIG_TC" = "y" ]; then
++ tristate ' TGA/SFB+ framebuffer support' CONFIG_FB_TGA
+ fi
+ if [ "$CONFIG_X86" = "y" ]; then
+ bool ' VESA VGA graphics console' CONFIG_FB_VESA
+@@ -121,6 +121,17 @@
+ hex ' Framebuffer Base Address' CONFIG_E1355_FB_BASE a8200000
+ fi
+ fi
++ if [ "$CONFIG_SOC_AU1100" = "y" ]; then
++ bool ' Au1100 LCD Driver' CONFIG_FB_AU1100
++ fi
++
++ if [ "$CONFIG_SOC_AU1200" = "y" ]; then
++ bool ' Au1200 LCD Driver' CONFIG_FB_AU1200
++ if [ "$CONFIG_FB_AU1200" = "y" ]; then
++ int ' Number of planes (1 to 4)' CONFIG_FB_AU1200_DEVS 1
++ fi
++ fi
++
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ if [ "$CONFIG_PCI" != "n" ]; then
+ tristate ' Matrox acceleration (EXPERIMENTAL)' CONFIG_FB_MATROX
+@@ -178,9 +189,6 @@
+ bool ' Use CRT on Pb1100 ' CONFIG_PB1500_CRT
+ bool ' Use TFT Panel on Pb1100 ' CONFIG_PB1500_TFT
+ fi
+- if [ "$CONFIG_SOC_AU1100" = "y" ]; then
+- bool ' Au1100 LCD Driver' CONFIG_FB_AU1100
+- fi
+ fi
+ fi
+ fi
+diff -Nur linux-2.4.32-rc1/drivers/video/fbmem.c linux-2.4.32-rc1.mips/drivers/video/fbmem.c
+--- linux-2.4.32-rc1/drivers/video/fbmem.c 2005-06-01 02:56:56.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/video/fbmem.c 2005-05-25 19:14:24.000000000 +0200
+@@ -139,6 +139,8 @@
+ extern int e1356fb_setup(char*);
+ extern int au1100fb_init(void);
+ extern int au1100fb_setup(char*);
++extern int au1200fb_init(void);
++extern int au1200fb_setup(char*);
+ extern int pvr2fb_init(void);
+ extern int pvr2fb_setup(char*);
+ extern int sstfb_init(void);
+@@ -331,6 +333,9 @@
+ #ifdef CONFIG_FB_AU1100
+ { "au1100fb", au1100fb_init, au1100fb_setup },
+ #endif
++#ifdef CONFIG_FB_AU1200
++ { "au1200fb", au1200fb_init, au1200fb_setup },
++#endif
+ #ifdef CONFIG_FB_IT8181
+ { "it8181fb", it8181fb_init, it8181fb_setup },
+ #endif
+diff -Nur linux-2.4.32-rc1/drivers/video/ims332.h linux-2.4.32-rc1.mips/drivers/video/ims332.h
+--- linux-2.4.32-rc1/drivers/video/ims332.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/video/ims332.h 2003-12-22 17:02:20.000000000 +0100
+@@ -0,0 +1,275 @@
++/*
++ * linux/drivers/video/ims332.h
++ *
++ * Copyright 2003 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
++ *
++ * 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.
++ */
++#include <linux/types.h>
++
++/*
++ * IMS332 16-bit wide, 128-bit aligned registers.
++ */
++struct _ims332_reg {
++ volatile u16 r;
++ u16 pad[7];
++};
++
++struct _ims332_regs {
++#define IMS332_BOOT_PLL_MUTLIPLIER 0x00001f
++#define IMS332_BOOT_CLOCK_SOURCE_SEL 0x000020
++#define IMS332_BOOT_ADDRESS_ALIGNMENT 0x000040
++#define IMS332_BOOT_WRITE_ZERO 0xffff80
++ struct _ims332_reg boot;
++ struct _ims332_reg pad0[0x020 - 0x000];
++ struct _ims332_reg half_sync;
++ struct _ims332_reg back_porch;
++ struct _ims332_reg display;
++ struct _ims332_reg short_display;
++ struct _ims332_reg broad_pulse;
++ struct _ims332_reg vsync;
++ struct _ims332_reg vpre_equalise;
++ struct _ims332_reg vpost_equalise;
++ struct _ims332_reg vblank;
++ struct _ims332_reg vdisplay;
++ struct _ims332_reg line_time;
++ struct _ims332_reg line_start;
++ struct _ims332_reg mem_init;
++ struct _ims332_reg transfer_delay;
++ struct _ims332_reg pad1[0x03f - 0x02e];
++ struct _ims332_reg pixel_address_mask;
++ struct _ims332_reg pad2[0x05f - 0x040];
++
++#define IMS332_CTRL_A_BOOT_ENABLE_VTG 0x000001
++#define IMS332_CTRL_A_SCREEN_FORMAT 0x000002
++#define IMS332_CTRL_A_INTERLACED_STANDARD 0x000004
++#define IMS332_CTRL_A_OPERATING_MODE 0x000008
++#define IMS332_CTRL_A_FRAME_FLYBACK_PATTERN 0x000010
++#define IMS332_CTRL_A_DIGITAL_SYNC_FORMAT 0x000020
++#define IMS332_CTRL_A_ANALOGUE_VIDEO_FORMAT 0x000040
++#define IMS332_CTRL_A_BLANK_LEVEL 0x000080
++#define IMS332_CTRL_A_BLANK_IO 0x000100
++#define IMS332_CTRL_A_BLANK_FUNCTION_SWITCH 0x000200
++#define IMS332_CTRL_A_FORCE_BLANKING 0x000400
++#define IMS332_CTRL_A_TURN_OFF_BLANKING 0x000800
++#define IMS332_CTRL_A_VRAM_ADDRESS_INCREMENT 0x003000
++#define IMS332_CTRL_A_TURN_OFF_DMA 0x004000
++#define IMS332_CTRL_A_SYNC_DELAY 0x038000
++#define IMS332_CTRL_A_PIXEL_PORT_INTERLEAVING 0x040000
++#define IMS332_CTRL_A_DELAYED_SAMPLING 0x080000
++#define IMS332_CTRL_A_BITS_PER_PIXEL 0x700000
++#define IMS332_CTRL_A_CURSOR_DISABLE 0x800000
++ struct _ims332_reg config_control_a;
++ struct _ims332_reg pad3[0x06f - 0x060];
++
++#define IMS332_CTRL_B_WRITE_ZERO 0xffffff
++ struct _ims332_reg config_control_b;
++ struct _ims332_reg pad4[0x07f - 0x070];
++ struct _ims332_reg screen_top;
++ struct _ims332_reg pad5[0x0a0 - 0x080];
++ /* cursor color palette, 3 entries, reg no. 0xa1 - 0xa3 */
++ struct _ims332_reg cursor_color_palette0;
++ struct _ims332_reg cursor_color_palette1;
++ struct _ims332_reg cursor_color_palette2;
++ struct _ims332_reg pad6[0x0bf - 0x0a3];
++ struct _ims332_reg rgb_frame_checksum0;
++ struct _ims332_reg rgb_frame_checksum1;
++ struct _ims332_reg rgb_frame_checksum2;
++ struct _ims332_reg pad7[0x0c6 - 0x0c2];
++ struct _ims332_reg cursor_start;
++ struct _ims332_reg pad8[0x0ff - 0x0c7];
++ /* color palette, 256 entries of form 0x00BBGGRR, reg no. 0x100 - 0x1ff */
++ struct _ims332_reg color_palette[0x1ff - 0x0ff];
++ /* hardware cursor bitmap, reg no. 0x200 - 0x3ff */
++ struct _ims332_reg cursor_ram[0x3ff - 0x1ff];
++};
++
++/*
++ * In the functions below we use some weird looking helper variables to
++ * access most members of this struct, otherwise the compiler splits
++ * the read/write in two byte accesses.
++ */
++struct ims332_regs {
++ struct _ims332_regs rw;
++ char pad0[0x80000 - sizeof (struct _ims332_regs)];
++ struct _ims332_regs r;
++ char pad1[0xa0000 - (sizeof (struct _ims332_regs) + 0x80000)];
++ struct _ims332_regs w;
++} __attribute__((packed));
++
++static inline void ims332_control_reg_bits(struct ims332_regs *regs, u32 mask,
++ u32 val)
++{
++ volatile u16 *ctr = &(regs->r.config_control_a.r);
++ volatile u16 *ctw = &(regs->w.config_control_a.r);
++ u32 ctrl;
++
++ mb();
++ ctrl = *ctr;
++ rmb();
++ ctrl |= ((regs->rw.boot.r << 8) & 0x00ff0000);
++ ctrl |= val & mask;
++ ctrl &= ~(~val & mask);
++ wmb();
++ regs->rw.boot.r = (ctrl >> 8) & 0xff00;
++ wmb();
++ *ctw = ctrl & 0xffff;
++}
++
++/* FIXME: This is maxinefb specific. */
++static inline void ims332_bootstrap(struct ims332_regs *regs)
++{
++ volatile u16 *ctw = &(regs->w.config_control_a.r);
++ u32 ctrl = IMS332_CTRL_A_BOOT_ENABLE_VTG | IMS332_CTRL_A_TURN_OFF_DMA;
++
++ /* bootstrap sequence */
++ mb();
++ regs->rw.boot.r = 0;
++ wmb();
++ *ctw = 0;
++
++ /* init control A register */
++ wmb();
++ regs->rw.boot.r = (ctrl >> 8) & 0xff00;
++ wmb();
++ *ctw = ctrl & 0xffff;
++}
++
++static inline void ims332_blank_screen(struct ims332_regs *regs, int blank)
++{
++ ims332_control_reg_bits(regs, IMS332_CTRL_A_FORCE_BLANKING,
++ blank ? IMS332_CTRL_A_FORCE_BLANKING : 0);
++}
++
++static inline void ims332_set_color_depth(struct ims332_regs *regs, u32 depth)
++{
++ u32 dp;
++ u32 mask = (IMS332_CTRL_A_PIXEL_PORT_INTERLEAVING
++ | IMS332_CTRL_A_DELAYED_SAMPLING
++ | IMS332_CTRL_A_BITS_PER_PIXEL);
++
++ switch (depth) {
++ case 1: dp = 0 << 20; break;
++ case 2: dp = 1 << 20; break;
++ case 4: dp = 2 << 20; break;
++ case 8: dp = 3 << 20; break;
++ case 15: dp = (4 << 20) | IMS332_CTRL_A_PIXEL_PORT_INTERLEAVING; break;
++ case 16: dp = (5 << 20) | IMS332_CTRL_A_PIXEL_PORT_INTERLEAVING; break;
++ default: return;
++ }
++ ims332_control_reg_bits(regs, mask, dp);
++
++ if (depth <= 8) {
++ volatile u16 *pmask = &(regs->w.pixel_address_mask.r);
++ u32 dm = (1 << depth) - 1;
++
++ wmb();
++ regs->rw.boot.r = dm << 8;
++ wmb();
++ *pmask = dm << 8 | dm;
++ }
++}
++
++static inline void ims332_set_screen_top(struct ims332_regs *regs, u16 top)
++{
++ volatile u16 *st = &(regs->w.screen_top.r);
++
++ mb();
++ *st = top & 0xffff;
++}
++
++static inline void ims332_enable_cursor(struct ims332_regs *regs, int on)
++{
++ ims332_control_reg_bits(regs, IMS332_CTRL_A_CURSOR_DISABLE,
++ on ? 0 : IMS332_CTRL_A_CURSOR_DISABLE);
++}
++
++static inline void ims332_position_cursor(struct ims332_regs *regs,
++ u16 x, u16 y)
++{
++ volatile u16 *cp = &(regs->w.cursor_start.r);
++ u32 val = ((x & 0xfff) << 12) | (y & 0xfff);
++
++ if (x > 2303 || y > 2303)
++ return;
++
++ mb();
++ regs->rw.boot.r = (val >> 8) & 0xff00;
++ wmb();
++ *cp = val & 0xffff;
++}
++
++static inline void ims332_set_font(struct ims332_regs *regs, u8 fgc,
++ u16 width, u16 height)
++{
++ volatile u16 *cp0 = &(regs->w.cursor_color_palette0.r);
++ int i;
++
++ mb();
++ for (i = 0; i < 0x200; i++) {
++ volatile u16 *cram = &(regs->w.cursor_ram[i].r);
++
++ if (height << 6 <= i << 3)
++ *cram = 0x0000;
++ else if (width <= i % 8 << 3)
++ *cram = 0x0000;
++ else if (((width >> 3) & 0xffff) > i % 8)
++ *cram = 0x5555;
++ else
++ *cram = 0x5555 & ~(0xffff << (width % 8 << 1));
++ wmb();
++ }
++ regs->rw.boot.r = fgc << 8;
++ wmb();
++ *cp0 = fgc << 8 | fgc;
++}
++
++static inline void ims332_read_cmap(struct ims332_regs *regs, u8 reg,
++ u8* red, u8* green, u8* blue)
++{
++ volatile u16 *rptr = &(regs->r.color_palette[reg].r);
++ u16 val;
++
++ mb();
++ val = *rptr;
++ *red = val & 0xff;
++ *green = (val >> 8) & 0xff;
++ rmb();
++ *blue = (regs->rw.boot.r >> 8) & 0xff;
++}
++
++static inline void ims332_write_cmap(struct ims332_regs *regs, u8 reg,
++ u8 red, u8 green, u8 blue)
++{
++ volatile u16 *wptr = &(regs->w.color_palette[reg].r);
++
++ mb();
++ regs->rw.boot.r = blue << 8;
++ wmb();
++ *wptr = (green << 8) + red;
++}
++
++static inline void ims332_dump_regs(struct ims332_regs *regs)
++{
++ int i;
++
++ printk(__FUNCTION__);
++ ims332_control_reg_bits(regs, IMS332_CTRL_A_BOOT_ENABLE_VTG, 0);
++ for (i = 0; i < 0x100; i++) {
++ volatile u16 *cpad = (u16 *)((char *)(&regs->r) + sizeof(struct _ims332_reg) * i);
++ u32 val;
++
++ val = *cpad;
++ rmb();
++ val |= regs->rw.boot.r << 8;
++ rmb();
++ if (! (i % 8))
++ printk("\n%02x:", i);
++ printk(" %06x", val);
++ }
++ ims332_control_reg_bits(regs, IMS332_CTRL_A_BOOT_ENABLE_VTG,
++ IMS332_CTRL_A_BOOT_ENABLE_VTG);
++ printk("\n");
++}
+diff -Nur linux-2.4.32-rc1/drivers/video/Makefile linux-2.4.32-rc1.mips/drivers/video/Makefile
+--- linux-2.4.32-rc1/drivers/video/Makefile 2004-02-18 14:36:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/video/Makefile 2005-02-11 22:16:44.000000000 +0100
+@@ -87,6 +87,7 @@
+ obj-$(CONFIG_FB_MAXINE) += maxinefb.o
+ obj-$(CONFIG_FB_TX3912) += tx3912fb.o
+ obj-$(CONFIG_FB_AU1100) += au1100fb.o fbgen.o
++obj-$(CONFIG_FB_AU1200) += au1200fb.o fbgen.o
+ obj-$(CONFIG_FB_IT8181) += it8181fb.o fbgen.o
+
+ subdir-$(CONFIG_STI_CONSOLE) += sti
+diff -Nur linux-2.4.32-rc1/drivers/video/maxinefb.h linux-2.4.32-rc1.mips/drivers/video/maxinefb.h
+--- linux-2.4.32-rc1/drivers/video/maxinefb.h 2003-08-25 13:44:42.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/video/maxinefb.h 1970-01-01 01:00:00.000000000 +0100
+@@ -1,38 +0,0 @@
+-/*
+- * linux/drivers/video/maxinefb.h
+- *
+- * DECstation 5000/xx onboard framebuffer support, Copyright (C) 1999 by
+- * Michael Engel <engel@unix-ag.org> and Karsten Merker <merker@guug.de>
+- * 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.
+- */
+-
+-#include <asm/addrspace.h>
+-
+-/*
+- * IMS332 video controller register base address
+- */
+-#define MAXINEFB_IMS332_ADDRESS KSEG1ADDR(0x1c140000)
+-
+-/*
+- * Begin of DECstation 5000/xx onboard framebuffer memory, default resolution
+- * is 1024x768x8
+- */
+-#define DS5000_xx_ONBOARD_FBMEM_START KSEG1ADDR(0x0a000000)
+-
+-/*
+- * The IMS 332 video controller used in the DECstation 5000/xx series
+- * uses 32 bits wide registers; the following defines declare the
+- * register numbers, to get the real offset, these have to be multiplied
+- * by four.
+- */
+-
+-#define IMS332_REG_CURSOR_RAM 0x200 /* hardware cursor bitmap */
+-
+-/*
+- * The color palette entries have the form 0x00BBGGRR
+- */
+-#define IMS332_REG_COLOR_PALETTE 0x100 /* color palette, 256 entries */
+-#define IMS332_REG_CURSOR_COLOR_PALETTE 0x0a1 /* cursor color palette, */
+- /* 3 entries */
+diff -Nur linux-2.4.32-rc1/drivers/video/newport_con.c linux-2.4.32-rc1.mips/drivers/video/newport_con.c
+--- linux-2.4.32-rc1/drivers/video/newport_con.c 2003-08-25 13:44:42.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/video/newport_con.c 2004-09-23 15:32:29.000000000 +0200
+@@ -22,6 +22,7 @@
+ #include <linux/module.h>
+ #include <linux/slab.h>
+
++#include <asm/io.h>
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+ #include <asm/page.h>
+@@ -77,7 +78,7 @@
+ static inline void newport_render_background(int xstart, int ystart,
+ int xend, int yend, int ci)
+ {
+- newport_wait();
++ newport_wait(npregs);
+ npregs->set.wrmask = 0xffffffff;
+ npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+ NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX
+@@ -94,7 +95,7 @@
+ unsigned short i;
+
+ for (i = 0; i < 16; i++) {
+- newport_bfwait();
++ newport_bfwait(npregs);
+ newport_cmap_setaddr(npregs, color_table[i]);
+ newport_cmap_setrgb(npregs,
+ default_red[i],
+@@ -107,7 +108,7 @@
+ unsigned long i;
+
+ for (i = 0; i < LINUX_LOGO_COLORS; i++) {
+- newport_bfwait();
++ newport_bfwait(npregs);
+ newport_cmap_setaddr(npregs, i + 0x20);
+ newport_cmap_setrgb(npregs,
+ linux_logo_red[i],
+@@ -115,13 +116,13 @@
+ linux_logo_blue[i]);
+ }
+
+- newport_wait();
++ newport_wait(npregs);
+ npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+ NPORT_DMODE0_CHOST);
+
+ npregs->set.xystarti = ((newport_xsize - LOGO_W) << 16) | (0);
+ npregs->set.xyendi = ((newport_xsize - 1) << 16);
+- newport_wait();
++ newport_wait(npregs);
+
+ for (i = 0; i < LOGO_W * LOGO_H; i++)
+ npregs->go.hostrw0 = linux_logo[i] << 24;
+@@ -133,7 +134,7 @@
+ if (logo_active)
+ return;
+
+- newport_wait();
++ newport_wait(npregs);
+ npregs->set.wrmask = 0xffffffff;
+ npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+ NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX
+@@ -155,7 +156,7 @@
+ unsigned short treg;
+ int i;
+
+- newport_wait();
++ newport_wait(npregs);
+ treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+ newport_vc2_set(npregs, VC2_IREG_CONTROL,
+ (treg | VC2_CTRL_EVIDEO));
+@@ -165,7 +166,7 @@
+ npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM |
+ NPORT_DMODE_W2 | VC2_PROTOCOL);
+ for (i = 0; i < 128; i++) {
+- newport_bfwait();
++ newport_bfwait(npregs);
+ if (i == 92 || i == 94)
+ npregs->set.dcbdata0.byshort.s1 = 0xff00;
+ else
+@@ -205,7 +206,7 @@
+ npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM |
+ NPORT_DMODE_W2 | VC2_PROTOCOL);
+ for (i = 0; i < 128; i++) {
+- newport_bfwait();
++ newport_bfwait(npregs);
+ linetable[i] = npregs->set.dcbdata0.byshort.s1;
+ }
+
+@@ -216,12 +217,12 @@
+ npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM |
+ NPORT_DMODE_W2 | VC2_PROTOCOL);
+ do {
+- newport_bfwait();
++ newport_bfwait(npregs);
+ treg = npregs->set.dcbdata0.byshort.s1;
+ if ((treg & 1) == 0)
+ cols += (treg >> 7) & 0xfe;
+ if ((treg & 0x80) == 0) {
+- newport_bfwait();
++ newport_bfwait(npregs);
+ treg = npregs->set.dcbdata0.byshort.s1;
+ }
+ } while ((treg & 0x8000) == 0);
+@@ -291,16 +292,16 @@
+
+ if (!sgi_gfxaddr)
+ return NULL;
+- npregs = (struct newport_regs *) (KSEG1 + sgi_gfxaddr);
++ npregs = (struct newport_regs *) /* ioremap cannot fail */
++ ioremap(sgi_gfxaddr, sizeof(struct newport_regs));
+ npregs->cset.config = NPORT_CFG_GD0;
+
+- if (newport_wait()) {
+- return NULL;
+- }
++ if (newport_wait(npregs))
++ goto out_unmap;
+
+ npregs->set.xstarti = TESTVAL;
+ if (npregs->set._xstart.word != XSTI_TO_FXSTART(TESTVAL))
+- return NULL;
++ goto out_unmap;
+
+ for (i = 0; i < MAX_NR_CONSOLES; i++)
+ font_data[i] = FONT_DATA;
+@@ -310,6 +311,10 @@
+ newport_get_screensize();
+
+ return "SGI Newport";
++
++out_unmap:
++ iounmap((void *)npregs);
++ return NULL;
+ }
+
+ static void newport_init(struct vc_data *vc, int init)
+@@ -363,7 +368,7 @@
+ (charattr & 0xf0) >> 4);
+
+ /* Set the color and drawing mode. */
+- newport_wait();
++ newport_wait(npregs);
+ npregs->set.colori = charattr & 0xf;
+ npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+ NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB |
+@@ -372,7 +377,7 @@
+ /* Set coordinates for bitmap operation. */
+ npregs->set.xystarti = (xpos << 16) | ((ypos + topscan) & 0x3ff);
+ npregs->set.xyendi = ((xpos + 7) << 16);
+- newport_wait();
++ newport_wait(npregs);
+
+ /* Go, baby, go... */
+ RENDER(npregs, p);
+@@ -396,7 +401,7 @@
+ xpos + ((count - 1) << 3), ypos,
+ (charattr & 0xf0) >> 4);
+
+- newport_wait();
++ newport_wait(npregs);
+
+ /* Set the color and drawing mode. */
+ npregs->set.colori = charattr & 0xf;
+@@ -407,7 +412,7 @@
+ for (i = 0; i < count; i++, xpos += 8) {
+ p = &font_data[vc->vc_num][(scr_readw(s++) & 0xff) << 4];
+
+- newport_wait();
++ newport_wait(npregs);
+
+ /* Set coordinates for bitmap operation. */
+ npregs->set.xystarti =
+@@ -689,7 +694,7 @@
+ xe = xs;
+ xs = tmp;
+ }
+- newport_wait();
++ newport_wait(npregs);
+ npregs->set.drawmode0 = (NPORT_DMODE0_S2S | NPORT_DMODE0_BLOCK |
+ NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX
+ | NPORT_DMODE0_STOPY);
+@@ -706,35 +711,35 @@
+ #define DUMMY (void *) newport_dummy
+
+ const struct consw newport_con = {
+- con_startup: newport_startup,
+- con_init: newport_init,
+- con_deinit: newport_deinit,
+- con_clear: newport_clear,
+- con_putc: newport_putc,
+- con_putcs: newport_putcs,
+- con_cursor: newport_cursor,
+- con_scroll: newport_scroll,
+- con_bmove: newport_bmove,
+- con_switch: newport_switch,
+- con_blank: newport_blank,
+- con_font_op: newport_font_op,
+- con_set_palette: newport_set_palette,
+- con_scrolldelta: newport_scrolldelta,
+- con_set_origin: DUMMY,
+- con_save_screen: DUMMY
++ .con_startup = newport_startup,
++ .con_init = newport_init,
++ .con_deinit = newport_deinit,
++ .con_clear = newport_clear,
++ .con_putc = newport_putc,
++ .con_putcs = newport_putcs,
++ .con_cursor = newport_cursor,
++ .con_scroll = newport_scroll,
++ .con_bmove = newport_bmove,
++ .con_switch = newport_switch,
++ .con_blank = newport_blank,
++ .con_font_op = newport_font_op,
++ .con_set_palette = newport_set_palette,
++ .con_scrolldelta = newport_scrolldelta,
++ .con_set_origin = DUMMY,
++ .con_save_screen = DUMMY
+ };
+
+ #ifdef MODULE
+ static int __init newport_console_init(void)
+ {
+ take_over_console(&newport_con, 0, MAX_NR_CONSOLES - 1, 1);
+-
+ return 0;
+ }
+
+ static void __exit newport_console_exit(void)
+ {
+ give_up_console(&newport_con);
++ iounmap((void *)npregs);
+ }
+
+ module_init(newport_console_init);
+diff -Nur linux-2.4.32-rc1/drivers/video/tgafb.c linux-2.4.32-rc1.mips/drivers/video/tgafb.c
+--- linux-2.4.32-rc1/drivers/video/tgafb.c 2001-11-14 23:52:20.000000000 +0100
++++ linux-2.4.32-rc1.mips/drivers/video/tgafb.c 2004-10-30 01:15:02.000000000 +0200
+@@ -45,6 +45,15 @@
+ #include <linux/console.h>
+ #include <asm/io.h>
+
++#ifdef CONFIG_TC
++#include <asm/dec/tc.h>
++#else
++static int search_tc_card(const char *) { return -1; }
++static void claim_tc_card(int) { }
++static void release_tc_card(int) { }
++static unsigned long get_tc_base_addr(int) { return 0; }
++#endif
++
+ #include <video/fbcon.h>
+ #include <video/fbcon-cfb8.h>
+ #include <video/fbcon-cfb32.h>
+@@ -84,10 +93,10 @@
+ };
+
+ static unsigned int deep_presets[4] = {
+- 0x00014000,
+- 0x0001440d,
++ 0x00004000,
++ 0x0000440d,
+ 0xffffffff,
+- 0x0001441d
++ 0x0000441d
+ };
+
+ static unsigned int rasterop_presets[4] = {
+@@ -131,6 +140,13 @@
+ 0,
+ FB_VMODE_NONINTERLACED
+ }},
++ { "1280x1024-72", { /* mode #0 of PMAGD boards */
++ 1280, 1024, 1280, 1024, 0, 0, 0, 0,
++ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
++ 0, 0, -1, -1, FB_ACCELF_TEXT, 7692, 232, 32, 34, 3, 160, 3,
++ FB_SYNC_ON_GREEN,
++ FB_VMODE_NONINTERLACED
++ }},
+ { "800x600-56", {
+ 800, 600, 800, 600, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+@@ -488,7 +504,8 @@
+ continue;
+
+ mb();
+- TGA_WRITE_REG(deep_presets[fb_info.tga_type], TGA_DEEP_REG);
++ TGA_WRITE_REG(deep_presets[fb_info.tga_type] |
++ (par->sync_on_green ? 0x0 : 0x00010000), TGA_DEEP_REG);
+ while (TGA_READ_REG(TGA_CMD_STAT_REG) & 1) /* wait for not busy */
+ continue;
+ mb();
+@@ -548,7 +565,7 @@
+ BT463_WRITE(BT463_REG_ACC, BT463_CMD_REG_0, 0x40);
+ BT463_WRITE(BT463_REG_ACC, BT463_CMD_REG_1, 0x08);
+ BT463_WRITE(BT463_REG_ACC, BT463_CMD_REG_2,
+- (par->sync_on_green ? 0x80 : 0x40));
++ (par->sync_on_green ? 0xc0 : 0x40));
+
+ BT463_WRITE(BT463_REG_ACC, BT463_READ_MASK_0, 0xff);
+ BT463_WRITE(BT463_REG_ACC, BT463_READ_MASK_1, 0xff);
+@@ -921,19 +938,34 @@
+ int __init tgafb_init(void)
+ {
+ struct pci_dev *pdev;
++ int slot;
+
+ pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, NULL);
+ if (!pdev)
++ slot = search_tc_card("PMAGD");
++ if (!pdev && slot < 0)
+ return -ENXIO;
+
+ /* divine board type */
+
+- fb_info.tga_mem_base = (unsigned long)ioremap(pdev->resource[0].start, 0);
+- fb_info.tga_type = (readl(fb_info.tga_mem_base) >> 12) & 0x0f;
+- fb_info.tga_regs_base = fb_info.tga_mem_base + TGA_REGS_OFFSET;
+- fb_info.tga_fb_base = (fb_info.tga_mem_base
++ if (pdev) {
++ fb_info.tga_mem_base = (unsigned long)ioremap(pdev->resource[0].start,
++ 0);
++ fb_info.tga_type = (readl(fb_info.tga_mem_base) >> 12) & 0x0f;
++ fb_info.tga_regs_base = fb_info.tga_mem_base + TGA_REGS_OFFSET;
++ fb_info.tga_fb_base = (fb_info.tga_mem_base
+ + fb_offset_presets[fb_info.tga_type]);
+- pci_read_config_byte(pdev, PCI_REVISION_ID, &fb_info.tga_chip_rev);
++ pci_read_config_byte(pdev, PCI_REVISION_ID, &fb_info.tga_chip_rev);
++
++ } else {
++ claim_tc_card(slot);
++ fb_info.tga_mem_base = get_tc_base_addr(slot);
++ fb_info.tga_type = (readl(fb_info.tga_mem_base) >> 12) & 0x0f; /* ? */
++ fb_info.tga_regs_base = fb_info.tga_mem_base + TGA_REGS_OFFSET;
++ fb_info.tga_fb_base = (fb_info.tga_mem_base
++ + fb_offset_presets[fb_info.tga_type]);
++ fb_info.tga_chip_rev = TGA_READ_REG(TGA_START_REG) & 0xff;
++ }
+
+ /* setup framebuffer */
+
+@@ -950,40 +982,62 @@
+ fb_info.gen.fbhw = &tgafb_hwswitch;
+ fb_info.gen.fbhw->detect();
+
+- printk (KERN_INFO "tgafb: DC21030 [TGA] detected, rev=0x%02x\n", fb_info.tga_chip_rev);
+- printk (KERN_INFO "tgafb: at PCI bus %d, device %d, function %d\n",
+- pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
++ if (pdev) {
++ printk (KERN_INFO "tgafb: DC21030 [TGA] detected, rev=0x%02x\n",
++ fb_info.tga_chip_rev);
++ printk (KERN_INFO "tgafb: at PCI bus %d, device %d, function %d\n",
++ pdev->bus->number,
++ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
++ } else {
++ printk (KERN_INFO "tgafb: SFB+ detected, rev=0x%02x\n",
++ fb_info.tga_chip_rev);
++ }
+
+ switch (fb_info.tga_type)
+ {
+ case TGA_TYPE_8PLANE:
+- strcpy (fb_info.gen.info.modename,"Digital ZLXp-E1");
++ if (pdev)
++ strcpy (fb_info.gen.info.modename,"Digital ZLXp-E1");
++ else
++ strcpy (fb_info.gen.info.modename,"Digital ZLX-E1");
+ break;
+
+ case TGA_TYPE_24PLANE:
+- strcpy (fb_info.gen.info.modename,"Digital ZLXp-E2");
++ if (pdev)
++ strcpy (fb_info.gen.info.modename,"Digital ZLXp-E2");
++ else
++ strcpy (fb_info.gen.info.modename,"Digital ZLX-E2");
+ break;
+
+ case TGA_TYPE_24PLUSZ:
+- strcpy (fb_info.gen.info.modename,"Digital ZLXp-E3");
++ if (pdev)
++ strcpy (fb_info.gen.info.modename,"Digital ZLXp-E3");
++ else
++ strcpy (fb_info.gen.info.modename,"Digital ZLX-E3");
+ break;
+ }
+
+ /* This should give a reasonable default video mode */
+
+ if (!default_var_valid) {
+- default_var = tgafb_predefined[0].var;
++ if (pdev)
++ default_var = tgafb_predefined[0].var;
++ else
++ default_var = tgafb_predefined[1].var;
+ }
+ fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
+ disp.var.activate = FB_ACTIVATE_NOW;
+ fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
+ fbgen_set_disp(-1, &fb_info.gen);
+ fbgen_install_cmap(0, &fb_info.gen);
+- if (register_framebuffer(&fb_info.gen.info) < 0)
++ if (register_framebuffer(&fb_info.gen.info) < 0) {
++ if (slot >= 0)
++ release_tc_card(slot);
+ return -EINVAL;
+- printk(KERN_INFO "fb%d: %s frame buffer device at 0x%lx\n",
++ }
++ printk(KERN_INFO "fb%d: %s frame buffer device at 0x%llx\n",
+ GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename,
+- pdev->resource[0].start);
++ fb_info.tga_mem_base);
+ return 0;
+ }
+
+diff -Nur linux-2.4.32-rc1/drivers/video/tgafb.h linux-2.4.32-rc1.mips/drivers/video/tgafb.h
+--- linux-2.4.32-rc1/drivers/video/tgafb.h 2000-04-12 18:47:28.000000000 +0200
++++ linux-2.4.32-rc1.mips/drivers/video/tgafb.h 2004-10-30 01:15:02.000000000 +0200
+@@ -36,6 +36,7 @@
+ #define TGA_RASTEROP_REG 0x0034
+ #define TGA_PIXELSHIFT_REG 0x0038
+ #define TGA_DEEP_REG 0x0050
++#define TGA_START_REG 0x0054
+ #define TGA_PIXELMASK_REG 0x005c
+ #define TGA_CURSOR_BASE_REG 0x0060
+ #define TGA_HORIZ_REG 0x0064
+diff -Nur linux-2.4.32-rc1/fs/binfmt_elf.c linux-2.4.32-rc1.mips/fs/binfmt_elf.c
+--- linux-2.4.32-rc1/fs/binfmt_elf.c 2005-06-01 02:56:56.000000000 +0200
++++ linux-2.4.32-rc1.mips/fs/binfmt_elf.c 2005-05-23 14:12:31.000000000 +0200
+@@ -660,6 +660,9 @@
+ bprm->argc++;
+ }
+ }
++ } else {
++ /* Executables without an interpreter also need a personality */
++ SET_PERSONALITY(elf_ex, ibcs2_interpreter);
+ }
+
+ /* Flush all traces of the currently running executable */
+@@ -1211,7 +1214,11 @@
+ elf.e_entry = 0;
+ elf.e_phoff = sizeof(elf);
+ elf.e_shoff = 0;
++#ifdef ELF_CORE_EFLAGS
++ elf.e_flags = ELF_CORE_EFLAGS;
++#else
+ elf.e_flags = 0;
++#endif
+ elf.e_ehsize = sizeof(elf);
+ elf.e_phentsize = sizeof(struct elf_phdr);
+ elf.e_phnum = segs+1; /* Include notes */
+diff -Nur linux-2.4.32-rc1/fs/partitions/sgi.c linux-2.4.32-rc1.mips/fs/partitions/sgi.c
+--- linux-2.4.32-rc1/fs/partitions/sgi.c 2001-10-02 05:03:26.000000000 +0200
++++ linux-2.4.32-rc1.mips/fs/partitions/sgi.c 2004-08-11 22:30:07.000000000 +0200
+@@ -17,6 +17,11 @@
+ #include "check.h"
+ #include "sgi.h"
+
++#if CONFIG_BLK_DEV_MD
++extern void md_autodetect_dev(kdev_t dev);
++#endif
++
++
+ int sgi_partition(struct gendisk *hd, struct block_device *bdev, unsigned long first_sector, int current_minor)
+ {
+ int i, csum, magic;
+@@ -77,6 +82,10 @@
+ if(!blocks)
+ continue;
+ add_gd_partition(hd, current_minor, start, blocks);
++#ifdef CONFIG_BLK_DEV_MD
++ if (be32_to_cpu(p->type) == LINUX_RAID_PARTITION)
++ md_autodetect_dev(MKDEV(hd->major, current_minor));
++#endif
+ current_minor++;
+ }
+ printk("\n");
+diff -Nur linux-2.4.32-rc1/fs/proc/array.c linux-2.4.32-rc1.mips/fs/proc/array.c
+--- linux-2.4.32-rc1/fs/proc/array.c 2005-01-19 15:10:11.000000000 +0100
++++ linux-2.4.32-rc1.mips/fs/proc/array.c 2004-11-29 18:47:18.000000000 +0100
+@@ -368,15 +368,15 @@
+ task->cmin_flt,
+ task->maj_flt,
+ task->cmaj_flt,
+- task->times.tms_utime,
+- task->times.tms_stime,
+- task->times.tms_cutime,
+- task->times.tms_cstime,
++ hz_to_std(task->times.tms_utime),
++ hz_to_std(task->times.tms_stime),
++ hz_to_std(task->times.tms_cutime),
++ hz_to_std(task->times.tms_cstime),
+ priority,
+ nice,
+ 0UL /* removed */,
+ task->it_real_value,
+- task->start_time,
++ hz_to_std(task->start_time),
+ vsize,
+ mm ? mm->rss : 0, /* you might want to shift this left 3 */
+ task->rlim[RLIMIT_RSS].rlim_cur,
+@@ -615,14 +615,14 @@
+
+ len = sprintf(buffer,
+ "cpu %lu %lu\n",
+- task->times.tms_utime,
+- task->times.tms_stime);
++ hz_to_std(task->times.tms_utime),
++ hz_to_std(task->times.tms_stime));
+
+ for (i = 0 ; i < smp_num_cpus; i++)
+ len += sprintf(buffer + len, "cpu%d %lu %lu\n",
+ i,
+- task->per_cpu_utime[cpu_logical_map(i)],
+- task->per_cpu_stime[cpu_logical_map(i)]);
++ hz_to_std(task->per_cpu_utime[cpu_logical_map(i)]),
++ hz_to_std(task->per_cpu_stime[cpu_logical_map(i)]));
+
+ return len;
+ }
+diff -Nur linux-2.4.32-rc1/fs/proc/proc_misc.c linux-2.4.32-rc1.mips/fs/proc/proc_misc.c
+--- linux-2.4.32-rc1/fs/proc/proc_misc.c 2004-08-08 01:26:06.000000000 +0200
++++ linux-2.4.32-rc1.mips/fs/proc/proc_misc.c 2004-08-14 20:39:01.000000000 +0200
+@@ -308,16 +308,16 @@
+ {
+ int i, len = 0;
+ extern unsigned long total_forks;
+- unsigned long jif = jiffies;
++ unsigned long jif = hz_to_std(jiffies);
+ unsigned int sum = 0, user = 0, nice = 0, system = 0;
+ int major, disk;
+
+ for (i = 0 ; i < smp_num_cpus; i++) {
+ int cpu = cpu_logical_map(i), j;
+
+- user += kstat.per_cpu_user[cpu];
+- nice += kstat.per_cpu_nice[cpu];
+- system += kstat.per_cpu_system[cpu];
++ user += hz_to_std(kstat.per_cpu_user[cpu]);
++ nice += hz_to_std(kstat.per_cpu_nice[cpu]);
++ system += hz_to_std(kstat.per_cpu_system[cpu]);
+ #if !defined(CONFIG_ARCH_S390)
+ for (j = 0 ; j < NR_IRQS ; j++)
+ sum += kstat.irqs[cpu][j];
+@@ -331,10 +331,10 @@
+ proc_sprintf(page, &off, &len,
+ "cpu%d %u %u %u %lu\n",
+ i,
+- kstat.per_cpu_user[cpu_logical_map(i)],
+- kstat.per_cpu_nice[cpu_logical_map(i)],
+- kstat.per_cpu_system[cpu_logical_map(i)],
+- jif - ( kstat.per_cpu_user[cpu_logical_map(i)] \
++ hz_to_std(kstat.per_cpu_user[cpu_logical_map(i)]),
++ hz_to_std(kstat.per_cpu_nice[cpu_logical_map(i)]),
++ hz_to_std(kstat.per_cpu_system[cpu_logical_map(i)]),
++ jif - hz_to_std( kstat.per_cpu_user[cpu_logical_map(i)] \
+ + kstat.per_cpu_nice[cpu_logical_map(i)] \
+ + kstat.per_cpu_system[cpu_logical_map(i)]));
+ proc_sprintf(page, &off, &len,
+diff -Nur linux-2.4.32-rc1/include/asm-alpha/param.h linux-2.4.32-rc1.mips/include/asm-alpha/param.h
+--- linux-2.4.32-rc1/include/asm-alpha/param.h 2000-11-08 08:37:31.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-alpha/param.h 2000-11-28 04:59:03.000000000 +0100
+@@ -13,6 +13,9 @@
+ # else
+ # define HZ 1200
+ # endif
++#ifdef __KERNEL__
++# define hz_to_std(a) (a)
++#endif
+ #endif
+
+ #define EXEC_PAGESIZE 8192
+diff -Nur linux-2.4.32-rc1/include/asm-i386/param.h linux-2.4.32-rc1.mips/include/asm-i386/param.h
+--- linux-2.4.32-rc1/include/asm-i386/param.h 2000-10-27 20:04:43.000000000 +0200
++++ linux-2.4.32-rc1.mips/include/asm-i386/param.h 2000-11-23 03:00:55.000000000 +0100
+@@ -3,6 +3,9 @@
+
+ #ifndef HZ
+ #define HZ 100
++#ifdef __KERNEL__
++#define hz_to_std(a) (a)
++#endif
+ #endif
+
+ #define EXEC_PAGESIZE 4096
+diff -Nur linux-2.4.32-rc1/include/asm-ia64/param.h linux-2.4.32-rc1.mips/include/asm-ia64/param.h
+--- linux-2.4.32-rc1/include/asm-ia64/param.h 2004-04-14 15:05:40.000000000 +0200
++++ linux-2.4.32-rc1.mips/include/asm-ia64/param.h 2004-04-16 05:14:20.000000000 +0200
+@@ -7,9 +7,15 @@
+ * Based on <asm-i386/param.h>.
+ *
+ * Modified 1998, 1999, 2002-2003
+- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
++ * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
+ */
+
++#include <linux/config.h>
++
++#ifdef __KERNEL__
++#define hz_to_std(a) (a)
++#endif
++
+ #define EXEC_PAGESIZE 65536
+
+ #ifndef NGROUPS
+diff -Nur linux-2.4.32-rc1/include/asm-m68k/param.h linux-2.4.32-rc1.mips/include/asm-m68k/param.h
+--- linux-2.4.32-rc1/include/asm-m68k/param.h 2001-01-04 22:00:55.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-m68k/param.h 2001-01-11 05:02:45.000000000 +0100
+@@ -3,6 +3,9 @@
+
+ #ifndef HZ
+ #define HZ 100
++#ifdef __KERNEL__
++#define hz_to_std(a) (a)
++#endif
+ #endif
+
+ #define EXEC_PAGESIZE 8192
+diff -Nur linux-2.4.32-rc1/include/asm-mips/au1000_gpio.h linux-2.4.32-rc1.mips/include/asm-mips/au1000_gpio.h
+--- linux-2.4.32-rc1/include/asm-mips/au1000_gpio.h 2002-11-29 00:53:15.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/au1000_gpio.h 2005-01-30 09:01:28.000000000 +0100
+@@ -30,6 +30,13 @@
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
++/*
++ * Revision history
++ * 01/31/02 0.01 Initial release. Steve Longerbeam, MontaVista
++ * 10/12/03 0.1 Added Au1100/Au1500, GPIO2, and bit operations. K.C. Nishio, AMD
++ * 08/05/04 0.11 Added Au1550 and Au1200. K.C. Nishio
++ */
++
+ #ifndef __AU1000_GPIO_H
+ #define __AU1000_GPIO_H
+
+@@ -44,13 +51,94 @@
+ #define AU1000GPIO_TRISTATE _IOW (AU1000GPIO_IOC_MAGIC, 4, int)
+ #define AU1000GPIO_AVAIL_MASK _IOR (AU1000GPIO_IOC_MAGIC, 5, int)
+
++// bit operations
++#define AU1000GPIO_BIT_READ _IOW (AU1000GPIO_IOC_MAGIC, 6, int)
++#define AU1000GPIO_BIT_SET _IOW (AU1000GPIO_IOC_MAGIC, 7, int)
++#define AU1000GPIO_BIT_CLEAR _IOW (AU1000GPIO_IOC_MAGIC, 8, int)
++#define AU1000GPIO_BIT_TRISTATE _IOW (AU1000GPIO_IOC_MAGIC, 9, int)
++#define AU1000GPIO_BIT_INIT _IOW (AU1000GPIO_IOC_MAGIC, 10, int)
++#define AU1000GPIO_BIT_TERM _IOW (AU1000GPIO_IOC_MAGIC, 11, int)
++
++/* set this major numer same as the CRIS GPIO driver */
++#define AU1X00_GPIO_MAJOR (120)
++
++#define ENABLED_ZERO (0)
++#define ENABLED_ONE (1)
++#define ENABLED_10 (0x2)
++#define ENABLED_11 (0x3)
++#define ENABLED_111 (0x7)
++#define NOT_AVAIL (-1)
++#define AU1X00_MAX_PRIMARY_GPIO (32)
++
++#define AU1000_GPIO_MINOR_MAX AU1X00_MAX_PRIMARY_GPIO
++/* Au1100, 1500, 1550 and 1200 have the secondary GPIO block */
++#define AU1XX0_GPIO_MINOR_MAX (48)
++
++#define AU1X00_GPIO_NAME "gpio"
++
++/* GPIO pins which are not multiplexed */
++#if defined(CONFIG_SOC_AU1000)
++ #define NATIVE_GPIOPIN ((1 << 15) | (1 << 8) | (1 << 7) | (1 << 1) | (1 << 0))
++ #define NATIVE_GPIO2PIN (0)
++#elif defined(CONFIG_SOC_AU1100)
++ #define NATIVE_GPIOPIN ((1 << 23) | (1 << 22) | (1 << 21) | (1 << 20) | (1 << 19) | (1 << 18) | \
++ (1 << 17) | (1 << 16) | (1 << 7) | (1 << 1) | (1 << 0))
++ #define NATIVE_GPIO2PIN (0)
++#elif defined(CONFIG_SOC_AU1500)
++ #define NATIVE_GPIOPIN ((1 << 15) | (1 << 8) | (1 << 7) | (1 << 1) | (1 << 0))
++ /* exclude the PCI reset output signal: GPIO[200], DMA_REQ2 and DMA_REQ3 */
++ #define NATIVE_GPIO2PIN (0xfffe & ~((1 << 9) | (1 << 8)))
++#elif defined(CONFIG_SOC_AU1550)
++ #define NATIVE_GPIOPIN ((1 << 15) | (1 << 8) | (1 << 7) | (1 << 6) | (1 << 1) | (1 << 0))
++ /* please refere Au1550 Data Book, chapter 15 */
++ #define NATIVE_GPIO2PIN (1 << 5)
++#elif defined(CONFIG_SOC_AU1200)
++ #define NATIVE_GPIOPIN ((1 << 7) | (1 << 5))
++ #define NATIVE_GPIO2PIN (0)
++#endif
++
++/* minor as u32 */
++#define MINOR_TO_GPIOPIN(minor) ((minor < AU1X00_MAX_PRIMARY_GPIO) ? minor : (minor - AU1X00_MAX_PRIMARY_GPIO))
++#define IS_PRIMARY_GPIOPIN(minor) ((minor < AU1X00_MAX_PRIMARY_GPIO) ? 1 : 0)
++
++/*
++ * pin to minor mapping.
++ * GPIO0-GPIO31, minor=0-31.
++ * GPIO200-GPIO215, minor=32-47.
++ */
++typedef struct _au1x00_gpio_bit_ctl {
++ int direction; // The direction of this GPIO pin. 0: IN, 1: OUT.
++ int data; // Pin output when itized (0/1), or at the term. 0/1/-1 (tristate).
++} au1x00_gpio_bit_ctl;
++
++typedef struct _au1x00_gpio_driver {
++ const char *driver_name;
++ const char *name;
++ int name_base; /* offset of printed name */
++ short major; /* major device number */
++ short minor_start; /* start of minor device number*/
++ short num; /* number of devices */
++} au1x00_gpio_driver;
++
+ #ifdef __KERNEL__
+-extern u32 get_au1000_avail_gpio_mask(void);
+-extern int au1000gpio_tristate(u32 data);
+-extern int au1000gpio_in(u32 *data);
+-extern int au1000gpio_set(u32 data);
+-extern int au1000gpio_clear(u32 data);
+-extern int au1000gpio_out(u32 data);
++extern u32 get_au1000_avail_gpio_mask(u32 *avail_gpio2);
++extern int au1000gpio_tristate(u32 minor, u32 data);
++extern int au1000gpio_in(u32 minor, u32 *data);
++extern int au1000gpio_set(u32 minor, u32 data);
++extern int au1000gpio_clear(u32 minor, u32 data);
++extern int au1000gpio_out(u32 minor, u32 data);
++extern int au1000gpio_bit_read(u32 minor, u32 *read_data);
++extern int au1000gpio_bit_set(u32 minor);
++extern int au1000gpio_bit_clear(u32 minor);
++extern int au1000gpio_bit_tristate(u32 minor);
++extern int check_minor_to_gpio(u32 minor);
++extern int au1000gpio_bit_init(u32 minor, au1x00_gpio_bit_ctl *bit_opt);
++extern int au1000gpio_bit_term(u32 minor, au1x00_gpio_bit_ctl *bit_opt);
++
++extern void gpio_register_devfs (au1x00_gpio_driver *driver, unsigned int flags, unsigned minor);
++extern void gpio_unregister_devfs (au1x00_gpio_driver *driver, unsigned minor);
++extern int gpio_register_driver(au1x00_gpio_driver *driver);
++extern int gpio_unregister_driver(au1x00_gpio_driver *driver);
+ #endif
+
+ #endif
+diff -Nur linux-2.4.32-rc1/include/asm-mips/au1000.h linux-2.4.32-rc1.mips/include/asm-mips/au1000.h
+--- linux-2.4.32-rc1/include/asm-mips/au1000.h 2005-01-19 15:10:11.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/au1000.h 2005-01-30 09:01:28.000000000 +0100
+@@ -160,28 +160,356 @@
+ #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
+ #endif
+
+-/* SDRAM Controller */
++/*
++ * SDRAM Register Offsets
++ */
+ #if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1100)
+-#define MEM_SDMODE0 0xB4000000
+-#define MEM_SDMODE1 0xB4000004
+-#define MEM_SDMODE2 0xB4000008
+-
+-#define MEM_SDADDR0 0xB400000C
+-#define MEM_SDADDR1 0xB4000010
+-#define MEM_SDADDR2 0xB4000014
+-
+-#define MEM_SDREFCFG 0xB4000018
+-#define MEM_SDPRECMD 0xB400001C
+-#define MEM_SDAUTOREF 0xB4000020
+-
+-#define MEM_SDWRMD0 0xB4000024
+-#define MEM_SDWRMD1 0xB4000028
+-#define MEM_SDWRMD2 0xB400002C
++#define MEM_SDMODE0 (0x0000)
++#define MEM_SDMODE1 (0x0004)
++#define MEM_SDMODE2 (0x0008)
++#define MEM_SDADDR0 (0x000C)
++#define MEM_SDADDR1 (0x0010)
++#define MEM_SDADDR2 (0x0014)
++#define MEM_SDREFCFG (0x0018)
++#define MEM_SDPRECMD (0x001C)
++#define MEM_SDAUTOREF (0x0020)
++#define MEM_SDWRMD0 (0x0024)
++#define MEM_SDWRMD1 (0x0028)
++#define MEM_SDWRMD2 (0x002C)
++#define MEM_SDSLEEP (0x0030)
++#define MEM_SDSMCKE (0x0034)
++
++#ifndef ASSEMBLER
++/*typedef volatile struct
++{
++ uint32 sdmode0;
++ uint32 sdmode1;
++ uint32 sdmode2;
++ uint32 sdaddr0;
++ uint32 sdaddr1;
++ uint32 sdaddr2;
++ uint32 sdrefcfg;
++ uint32 sdautoref;
++ uint32 sdwrmd0;
++ uint32 sdwrmd1;
++ uint32 sdwrmd2;
++ uint32 sdsleep;
++ uint32 sdsmcke;
++
++} AU1X00_SDRAM;*/
++#endif
++
++/*
++ * MEM_SDMODE register content definitions
++ */
++#define MEM_SDMODE_F (1<<22)
++#define MEM_SDMODE_SR (1<<21)
++#define MEM_SDMODE_BS (1<<20)
++#define MEM_SDMODE_RS (3<<18)
++#define MEM_SDMODE_CS (7<<15)
++#define MEM_SDMODE_TRAS (15<<11)
++#define MEM_SDMODE_TMRD (3<<9)
++#define MEM_SDMODE_TWR (3<<7)
++#define MEM_SDMODE_TRP (3<<5)
++#define MEM_SDMODE_TRCD (3<<3)
++#define MEM_SDMODE_TCL (7<<0)
++
++#define MEM_SDMODE_BS_2Bank (0<<20)
++#define MEM_SDMODE_BS_4Bank (1<<20)
++#define MEM_SDMODE_RS_11Row (0<<18)
++#define MEM_SDMODE_RS_12Row (1<<18)
++#define MEM_SDMODE_RS_13Row (2<<18)
++#define MEM_SDMODE_RS_N(N) ((N)<<18)
++#define MEM_SDMODE_CS_7Col (0<<15)
++#define MEM_SDMODE_CS_8Col (1<<15)
++#define MEM_SDMODE_CS_9Col (2<<15)
++#define MEM_SDMODE_CS_10Col (3<<15)
++#define MEM_SDMODE_CS_11Col (4<<15)
++#define MEM_SDMODE_CS_N(N) ((N)<<15)
++#define MEM_SDMODE_TRAS_N(N) ((N)<<11)
++#define MEM_SDMODE_TMRD_N(N) ((N)<<9)
++#define MEM_SDMODE_TWR_N(N) ((N)<<7)
++#define MEM_SDMODE_TRP_N(N) ((N)<<5)
++#define MEM_SDMODE_TRCD_N(N) ((N)<<3)
++#define MEM_SDMODE_TCL_N(N) ((N)<<0)
++
++/*
++ * MEM_SDADDR register contents definitions
++ */
++#define MEM_SDADDR_E (1<<20)
++#define MEM_SDADDR_CSBA (0x03FF<<10)
++#define MEM_SDADDR_CSMASK (0x03FF<<0)
++#define MEM_SDADDR_CSBA_N(N) ((N)&(0x03FF<<22)>>12)
++#define MEM_SDADDR_CSMASK_N(N) ((N)&(0x03FF<<22)>>22)
++
++/*
++ * MEM_SDREFCFG register content definitions
++ */
++#define MEM_SDREFCFG_TRC (15<<28)
++#define MEM_SDREFCFG_TRPM (3<<26)
++#define MEM_SDREFCFG_E (1<<25)
++#define MEM_SDREFCFG_RE (0x1ffffff<<0)
++#define MEM_SDREFCFG_TRC_N(N) ((N)<<MEM_SDREFCFG_TRC)
++#define MEM_SDREFCFG_TRPM_N(N) ((N)<<MEM_SDREFCFG_TRPM)
++#define MEM_SDREFCFG_REF_N(N) (N)
++#endif
++
++/***********************************************************************/
++
++/*
++ * Au1550 SDRAM Register Offsets
++ */
++
++/***********************************************************************/
++
++#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
++#define MEM_SDMODE0 (0x0800)
++#define MEM_SDMODE1 (0x0808)
++#define MEM_SDMODE2 (0x0810)
++#define MEM_SDADDR0 (0x0820)
++#define MEM_SDADDR1 (0x0828)
++#define MEM_SDADDR2 (0x0830)
++#define MEM_SDCONFIGA (0x0840)
++#define MEM_SDCONFIGB (0x0848)
++#define MEM_SDSTAT (0x0850)
++#define MEM_SDERRADDR (0x0858)
++#define MEM_SDSTRIDE0 (0x0860)
++#define MEM_SDSTRIDE1 (0x0868)
++#define MEM_SDSTRIDE2 (0x0870)
++#define MEM_SDWRMD0 (0x0880)
++#define MEM_SDWRMD1 (0x0888)
++#define MEM_SDWRMD2 (0x0890)
++#define MEM_SDPRECMD (0x08C0)
++#define MEM_SDAUTOREF (0x08C8)
++#define MEM_SDSREF (0x08D0)
++#define MEM_SDSLEEP MEM_SDSREF
++
++#ifndef ASSEMBLER
++/*typedef volatile struct
++{
++ uint32 sdmode0;
++ uint32 reserved0;
++ uint32 sdmode1;
++ uint32 reserved1;
++ uint32 sdmode2;
++ uint32 reserved2[3];
++ uint32 sdaddr0;
++ uint32 reserved3;
++ uint32 sdaddr1;
++ uint32 reserved4;
++ uint32 sdaddr2;
++ uint32 reserved5[3];
++ uint32 sdconfiga;
++ uint32 reserved6;
++ uint32 sdconfigb;
++ uint32 reserved7;
++ uint32 sdstat;
++ uint32 reserved8;
++ uint32 sderraddr;
++ uint32 reserved9;
++ uint32 sdstride0;
++ uint32 reserved10;
++ uint32 sdstride1;
++ uint32 reserved11;
++ uint32 sdstride2;
++ uint32 reserved12[3];
++ uint32 sdwrmd0;
++ uint32 reserved13;
++ uint32 sdwrmd1;
++ uint32 reserved14;
++ uint32 sdwrmd2;
++ uint32 reserved15[11];
++ uint32 sdprecmd;
++ uint32 reserved16;
++ uint32 sdautoref;
++ uint32 reserved17;
++ uint32 sdsref;
++
++} AU1550_SDRAM;*/
++#endif
++#endif
++
++/*
++ * Physical base addresses for integrated peripherals
++ */
++
++#ifdef CONFIG_SOC_AU1000
++#define MEM_PHYS_ADDR 0x14000000
++#define STATIC_MEM_PHYS_ADDR 0x14001000
++#define DMA0_PHYS_ADDR 0x14002000
++#define DMA1_PHYS_ADDR 0x14002100
++#define DMA2_PHYS_ADDR 0x14002200
++#define DMA3_PHYS_ADDR 0x14002300
++#define DMA4_PHYS_ADDR 0x14002400
++#define DMA5_PHYS_ADDR 0x14002500
++#define DMA6_PHYS_ADDR 0x14002600
++#define DMA7_PHYS_ADDR 0x14002700
++#define IC0_PHYS_ADDR 0x10400000
++#define IC1_PHYS_ADDR 0x11800000
++#define AC97_PHYS_ADDR 0x10000000
++#define USBH_PHYS_ADDR 0x10100000
++#define USBD_PHYS_ADDR 0x10200000
++#define IRDA_PHYS_ADDR 0x10300000
++#define MAC0_PHYS_ADDR 0x10500000
++#define MAC1_PHYS_ADDR 0x10510000
++#define MACEN_PHYS_ADDR 0x10520000
++#define MACDMA0_PHYS_ADDR 0x14004000
++#define MACDMA1_PHYS_ADDR 0x14004200
++#define I2S_PHYS_ADDR 0x11000000
++#define UART0_PHYS_ADDR 0x11100000
++#define UART1_PHYS_ADDR 0x11200000
++#define UART2_PHYS_ADDR 0x11300000
++#define UART3_PHYS_ADDR 0x11400000
++#define SSI0_PHYS_ADDR 0x11600000
++#define SSI1_PHYS_ADDR 0x11680000
++#define SYS_PHYS_ADDR 0x11900000
++#define PCMCIA_IO_PHYS_ADDR 0xF00000000
++#define PCMCIA_ATTR_PHYS_ADDR 0xF40000000
++#define PCMCIA_MEM_PHYS_ADDR 0xF80000000
++#endif
++
++/********************************************************************/
+
+-#define MEM_SDSLEEP 0xB4000030
+-#define MEM_SDSMCKE 0xB4000034
++#ifdef CONFIG_SOC_AU1500
++#define MEM_PHYS_ADDR 0x14000000
++#define STATIC_MEM_PHYS_ADDR 0x14001000
++#define DMA0_PHYS_ADDR 0x14002000
++#define DMA1_PHYS_ADDR 0x14002100
++#define DMA2_PHYS_ADDR 0x14002200
++#define DMA3_PHYS_ADDR 0x14002300
++#define DMA4_PHYS_ADDR 0x14002400
++#define DMA5_PHYS_ADDR 0x14002500
++#define DMA6_PHYS_ADDR 0x14002600
++#define DMA7_PHYS_ADDR 0x14002700
++#define IC0_PHYS_ADDR 0x10400000
++#define IC1_PHYS_ADDR 0x11800000
++#define AC97_PHYS_ADDR 0x10000000
++#define USBH_PHYS_ADDR 0x10100000
++#define USBD_PHYS_ADDR 0x10200000
++#define PCI_PHYS_ADDR 0x14005000
++#define MAC0_PHYS_ADDR 0x11500000
++#define MAC1_PHYS_ADDR 0x11510000
++#define MACEN_PHYS_ADDR 0x11520000
++#define MACDMA0_PHYS_ADDR 0x14004000
++#define MACDMA1_PHYS_ADDR 0x14004200
++#define I2S_PHYS_ADDR 0x11000000
++#define UART0_PHYS_ADDR 0x11100000
++#define UART3_PHYS_ADDR 0x11400000
++#define GPIO2_PHYS_ADDR 0x11700000
++#define SYS_PHYS_ADDR 0x11900000
++#define PCI_MEM_PHYS_ADDR 0x400000000
++#define PCI_IO_PHYS_ADDR 0x500000000
++#define PCI_CONFIG0_PHYS_ADDR 0x600000000
++#define PCI_CONFIG1_PHYS_ADDR 0x680000000
++#define PCMCIA_IO_PHYS_ADDR 0xF00000000
++#define PCMCIA_ATTR_PHYS_ADDR 0xF40000000
++#define PCMCIA_MEM_PHYS_ADDR 0xF80000000
+ #endif
+
++/********************************************************************/
++
++#ifdef CONFIG_SOC_AU1100
++#define MEM_PHYS_ADDR 0x14000000
++#define STATIC_MEM_PHYS_ADDR 0x14001000
++#define DMA0_PHYS_ADDR 0x14002000
++#define DMA1_PHYS_ADDR 0x14002100
++#define DMA2_PHYS_ADDR 0x14002200
++#define DMA3_PHYS_ADDR 0x14002300
++#define DMA4_PHYS_ADDR 0x14002400
++#define DMA5_PHYS_ADDR 0x14002500
++#define DMA6_PHYS_ADDR 0x14002600
++#define DMA7_PHYS_ADDR 0x14002700
++#define IC0_PHYS_ADDR 0x10400000
++#define SD0_PHYS_ADDR 0x10600000
++#define SD1_PHYS_ADDR 0x10680000
++#define IC1_PHYS_ADDR 0x11800000
++#define AC97_PHYS_ADDR 0x10000000
++#define USBH_PHYS_ADDR 0x10100000
++#define USBD_PHYS_ADDR 0x10200000
++#define IRDA_PHYS_ADDR 0x10300000
++#define MAC0_PHYS_ADDR 0x10500000
++#define MACEN_PHYS_ADDR 0x10520000
++#define MACDMA0_PHYS_ADDR 0x14004000
++#define MACDMA1_PHYS_ADDR 0x14004200
++#define I2S_PHYS_ADDR 0x11000000
++#define UART0_PHYS_ADDR 0x11100000
++#define UART1_PHYS_ADDR 0x11200000
++#define UART3_PHYS_ADDR 0x11400000
++#define SSI0_PHYS_ADDR 0x11600000
++#define SSI1_PHYS_ADDR 0x11680000
++#define GPIO2_PHYS_ADDR 0x11700000
++#define SYS_PHYS_ADDR 0x11900000
++#define LCD_PHYS_ADDR 0x15000000
++#define PCMCIA_IO_PHYS_ADDR 0xF00000000
++#define PCMCIA_ATTR_PHYS_ADDR 0xF40000000
++#define PCMCIA_MEM_PHYS_ADDR 0xF80000000
++#endif
++
++/***********************************************************************/
++
++#ifdef CONFIG_SOC_AU1550
++#define MEM_PHYS_ADDR 0x14000000
++#define STATIC_MEM_PHYS_ADDR 0x14001000
++#define IC0_PHYS_ADDR 0x10400000
++#define IC1_PHYS_ADDR 0x11800000
++#define USBH_PHYS_ADDR 0x14020000
++#define USBD_PHYS_ADDR 0x10200000
++#define PCI_PHYS_ADDR 0x14005000
++#define MAC0_PHYS_ADDR 0x10500000
++#define MAC1_PHYS_ADDR 0x10510000
++#define MACEN_PHYS_ADDR 0x10520000
++#define MACDMA0_PHYS_ADDR 0x14004000
++#define MACDMA1_PHYS_ADDR 0x14004200
++#define UART0_PHYS_ADDR 0x11100000
++#define UART1_PHYS_ADDR 0x11200000
++#define UART3_PHYS_ADDR 0x11400000
++#define GPIO2_PHYS_ADDR 0x11700000
++#define SYS_PHYS_ADDR 0x11900000
++#define DDMA_PHYS_ADDR 0x14002000
++#define PE_PHYS_ADDR 0x14008000
++#define PSC0_PHYS_ADDR 0x11A00000
++#define PSC1_PHYS_ADDR 0x11B00000
++#define PSC2_PHYS_ADDR 0x10A00000
++#define PSC3_PHYS_ADDR 0x10B00000
++#define PCI_MEM_PHYS_ADDR 0x400000000
++#define PCI_IO_PHYS_ADDR 0x500000000
++#define PCI_CONFIG0_PHYS_ADDR 0x600000000
++#define PCI_CONFIG1_PHYS_ADDR 0x680000000
++#define PCMCIA_IO_PHYS_ADDR 0xF00000000
++#define PCMCIA_ATTR_PHYS_ADDR 0xF40000000
++#define PCMCIA_MEM_PHYS_ADDR 0xF80000000
++#endif
++
++/***********************************************************************/
++
++#ifdef CONFIG_SOC_AU1200
++#define MEM_PHYS_ADDR 0x14000000
++#define STATIC_MEM_PHYS_ADDR 0x14001000
++#define AES_PHYS_ADDR 0x10300000
++#define CIM_PHYS_ADDR 0x14004000
++#define IC0_PHYS_ADDR 0x10400000
++#define IC1_PHYS_ADDR 0x11800000
++#define USBM_PHYS_ADDR 0x14020000
++#define USBH_PHYS_ADDR 0x14020100
++#define UART0_PHYS_ADDR 0x11100000
++#define UART1_PHYS_ADDR 0x11200000
++#define GPIO2_PHYS_ADDR 0x11700000
++#define SYS_PHYS_ADDR 0x11900000
++#define DDMA_PHYS_ADDR 0x14002000
++#define PSC0_PHYS_ADDR 0x11A00000
++#define PSC1_PHYS_ADDR 0x11B00000
++#define PCMCIA_IO_PHYS_ADDR 0xF00000000
++#define PCMCIA_ATTR_PHYS_ADDR 0xF40000000
++#define PCMCIA_MEM_PHYS_ADDR 0xF80000000
++#define SD0_PHYS_ADDR 0x10600000
++#define SD1_PHYS_ADDR 0x10680000
++#define LCD_PHYS_ADDR 0x15000000
++#define SWCNT_PHYS_ADDR 0x1110010C
++#define MAEFE_PHYS_ADDR 0x14012000
++#define MAEBE_PHYS_ADDR 0x14010000
++#endif
++
++
+ /* Static Bus Controller */
+ #define MEM_STCFG0 0xB4001000
+ #define MEM_STTIME0 0xB4001004
+@@ -367,7 +695,7 @@
+ #define AU1000_MAC0_ENABLE 0xB0520000
+ #define AU1000_MAC1_ENABLE 0xB0520004
+ #define NUM_ETH_INTERFACES 2
+-#endif // CONFIG_SOC_AU1000
++#endif /* CONFIG_SOC_AU1000 */
+
+ /* Au1500 */
+ #ifdef CONFIG_SOC_AU1500
+@@ -438,7 +766,7 @@
+ #define AU1500_MAC0_ENABLE 0xB1520000
+ #define AU1500_MAC1_ENABLE 0xB1520004
+ #define NUM_ETH_INTERFACES 2
+-#endif // CONFIG_SOC_AU1500
++#endif /* CONFIG_SOC_AU1500 */
+
+ /* Au1100 */
+ #ifdef CONFIG_SOC_AU1100
+@@ -483,6 +811,22 @@
+ #define AU1000_GPIO_13 45
+ #define AU1000_GPIO_14 46
+ #define AU1000_GPIO_15 47
++#define AU1000_GPIO_16 48
++#define AU1000_GPIO_17 49
++#define AU1000_GPIO_18 50
++#define AU1000_GPIO_19 51
++#define AU1000_GPIO_20 52
++#define AU1000_GPIO_21 53
++#define AU1000_GPIO_22 54
++#define AU1000_GPIO_23 55
++#define AU1000_GPIO_24 56
++#define AU1000_GPIO_25 57
++#define AU1000_GPIO_26 58
++#define AU1000_GPIO_27 59
++#define AU1000_GPIO_28 60
++#define AU1000_GPIO_29 61
++#define AU1000_GPIO_30 62
++#define AU1000_GPIO_31 63
+
+ #define UART0_ADDR 0xB1100000
+ #define UART1_ADDR 0xB1200000
+@@ -494,7 +838,7 @@
+ #define AU1100_ETH0_BASE 0xB0500000
+ #define AU1100_MAC0_ENABLE 0xB0520000
+ #define NUM_ETH_INTERFACES 1
+-#endif // CONFIG_SOC_AU1100
++#endif /* CONFIG_SOC_AU1100 */
+
+ #ifdef CONFIG_SOC_AU1550
+ #define AU1550_UART0_INT 0
+@@ -511,14 +855,14 @@
+ #define AU1550_PSC1_INT 11
+ #define AU1550_PSC2_INT 12
+ #define AU1550_PSC3_INT 13
+-#define AU1550_TOY_INT 14
+-#define AU1550_TOY_MATCH0_INT 15
+-#define AU1550_TOY_MATCH1_INT 16
+-#define AU1550_TOY_MATCH2_INT 17
+-#define AU1550_RTC_INT 18
+-#define AU1550_RTC_MATCH0_INT 19
+-#define AU1550_RTC_MATCH1_INT 20
+-#define AU1550_RTC_MATCH2_INT 21
++#define AU1000_TOY_INT 14
++#define AU1000_TOY_MATCH0_INT 15
++#define AU1000_TOY_MATCH1_INT 16
++#define AU1000_TOY_MATCH2_INT 17
++#define AU1000_RTC_INT 18
++#define AU1000_RTC_MATCH0_INT 19
++#define AU1000_RTC_MATCH1_INT 20
++#define AU1000_RTC_MATCH2_INT 21
+ #define AU1550_NAND_INT 23
+ #define AU1550_USB_DEV_REQ_INT 24
+ #define AU1550_USB_DEV_SUS_INT 25
+@@ -573,7 +917,7 @@
+ #define AU1550_MAC0_ENABLE 0xB0520000
+ #define AU1550_MAC1_ENABLE 0xB0520004
+ #define NUM_ETH_INTERFACES 2
+-#endif // CONFIG_SOC_AU1550
++#endif /* CONFIG_SOC_AU1550 */
+
+ #ifdef CONFIG_SOC_AU1200
+ #define AU1200_UART0_INT 0
+@@ -590,14 +934,14 @@
+ #define AU1200_PSC1_INT 11
+ #define AU1200_AES_INT 12
+ #define AU1200_CAMERA_INT 13
+-#define AU1200_TOY_INT 14
+-#define AU1200_TOY_MATCH0_INT 15
+-#define AU1200_TOY_MATCH1_INT 16
+-#define AU1200_TOY_MATCH2_INT 17
+-#define AU1200_RTC_INT 18
+-#define AU1200_RTC_MATCH0_INT 19
+-#define AU1200_RTC_MATCH1_INT 20
+-#define AU1200_RTC_MATCH2_INT 21
++#define AU1000_TOY_INT 14
++#define AU1000_TOY_MATCH0_INT 15
++#define AU1000_TOY_MATCH1_INT 16
++#define AU1000_TOY_MATCH2_INT 17
++#define AU1000_RTC_INT 18
++#define AU1000_RTC_MATCH0_INT 19
++#define AU1000_RTC_MATCH1_INT 20
++#define AU1000_RTC_MATCH2_INT 21
+ #define AU1200_NAND_INT 23
+ #define AU1200_GPIO_204 24
+ #define AU1200_GPIO_205 25
+@@ -605,6 +949,7 @@
+ #define AU1200_GPIO_207 27
+ #define AU1200_GPIO_208_215 28 // Logical OR of 208:215
+ #define AU1200_USB_INT 29
++#define AU1000_USB_HOST_INT AU1200_USB_INT
+ #define AU1200_LCD_INT 30
+ #define AU1200_MAE_BOTH_INT 31
+ #define AU1000_GPIO_0 32
+@@ -643,21 +988,36 @@
+ #define UART0_ADDR 0xB1100000
+ #define UART1_ADDR 0xB1200000
+
+-#define USB_OHCI_BASE 0x14020000 // phys addr for ioremap
+-#define USB_HOST_CONFIG 0xB4027ffc
++#define USB_UOC_BASE 0x14020020
++#define USB_UOC_LEN 0x20
++#define USB_OHCI_BASE 0x14020100
++#define USB_OHCI_LEN 0x100
++#define USB_EHCI_BASE 0x14020200
++#define USB_EHCI_LEN 0x100
++#define USB_UDC_BASE 0x14022000
++#define USB_UDC_LEN 0x2000
++#define USB_MSR_BASE 0xB4020000
++#define USB_MSR_MCFG 4
++#define USBMSRMCFG_OMEMEN 0
++#define USBMSRMCFG_OBMEN 1
++#define USBMSRMCFG_EMEMEN 2
++#define USBMSRMCFG_EBMEN 3
++#define USBMSRMCFG_DMEMEN 4
++#define USBMSRMCFG_DBMEN 5
++#define USBMSRMCFG_GMEMEN 6
++#define USBMSRMCFG_OHCCLKEN 16
++#define USBMSRMCFG_EHCCLKEN 17
++#define USBMSRMCFG_UDCCLKEN 18
++#define USBMSRMCFG_PHYPLLEN 19
++#define USBMSRMCFG_RDCOMB 30
++#define USBMSRMCFG_PFEN 31
+
+-// these are here for prototyping on au1550 (do not exist on au1200)
+-#define AU1200_ETH0_BASE 0xB0500000
+-#define AU1200_ETH1_BASE 0xB0510000
+-#define AU1200_MAC0_ENABLE 0xB0520000
+-#define AU1200_MAC1_ENABLE 0xB0520004
+-#define NUM_ETH_INTERFACES 2
+-#endif // CONFIG_SOC_AU1200
++#endif /* CONFIG_SOC_AU1200 */
+
+ #define AU1000_LAST_INTC0_INT 31
++#define AU1000_LAST_INTC1_INT 63
+ #define AU1000_MAX_INTR 63
+
+-
+ /* Programmable Counters 0 and 1 */
+ #define SYS_BASE 0xB1900000
+ #define SYS_COUNTER_CNTRL (SYS_BASE + 0x14)
+@@ -728,6 +1088,8 @@
+ #define I2S_CONTROL_D (1<<1)
+ #define I2S_CONTROL_CE (1<<0)
+
++#ifndef CONFIG_SOC_AU1200
++
+ /* USB Host Controller */
+ #define USB_OHCI_LEN 0x00100000
+
+@@ -773,6 +1135,8 @@
+ #define USBDEV_ENABLE (1<<1)
+ #define USBDEV_CE (1<<0)
+
++#endif /* !CONFIG_SOC_AU1200 */
++
+ /* Ethernet Controllers */
+
+ /* 4 byte offsets from AU1000_ETH_BASE */
+@@ -1171,6 +1535,37 @@
+ #define SYS_PF_PSC1_S1 (1 << 1)
+ #define SYS_PF_MUST_BE_SET ((1 << 5) | (1 << 2))
+
++/* Au1200 Only */
++#ifdef CONFIG_SOC_AU1200
++#define SYS_PINFUNC_DMA (1<<31)
++#define SYS_PINFUNC_S0A (1<<30)
++#define SYS_PINFUNC_S1A (1<<29)
++#define SYS_PINFUNC_LP0 (1<<28)
++#define SYS_PINFUNC_LP1 (1<<27)
++#define SYS_PINFUNC_LD16 (1<<26)
++#define SYS_PINFUNC_LD8 (1<<25)
++#define SYS_PINFUNC_LD1 (1<<24)
++#define SYS_PINFUNC_LD0 (1<<23)
++#define SYS_PINFUNC_P1A (3<<21)
++#define SYS_PINFUNC_P1B (1<<20)
++#define SYS_PINFUNC_FS3 (1<<19)
++#define SYS_PINFUNC_P0A (3<<17)
++#define SYS_PINFUNC_CS (1<<16)
++#define SYS_PINFUNC_CIM (1<<15)
++#define SYS_PINFUNC_P1C (1<<14)
++#define SYS_PINFUNC_U1T (1<<12)
++#define SYS_PINFUNC_U1R (1<<11)
++#define SYS_PINFUNC_EX1 (1<<10)
++#define SYS_PINFUNC_EX0 (1<<9)
++#define SYS_PINFUNC_U0R (1<<8)
++#define SYS_PINFUNC_MC (1<<7)
++#define SYS_PINFUNC_S0B (1<<6)
++#define SYS_PINFUNC_S0C (1<<5)
++#define SYS_PINFUNC_P0B (1<<4)
++#define SYS_PINFUNC_U0T (1<<3)
++#define SYS_PINFUNC_S1B (1<<2)
++#endif
++
+ #define SYS_TRIOUTRD 0xB1900100
+ #define SYS_TRIOUTCLR 0xB1900100
+ #define SYS_OUTPUTRD 0xB1900108
+@@ -1298,7 +1693,6 @@
+ #define SD1_XMIT_FIFO 0xB0680000
+ #define SD1_RECV_FIFO 0xB0680004
+
+-
+ #if defined (CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
+ /* Au1500 PCI Controller */
+ #define Au1500_CFG_BASE 0xB4005000 // virtual, kseg0 addr
+@@ -1388,9 +1782,60 @@
+
+ #endif
+
++#ifndef _LANGUAGE_ASSEMBLY
++typedef volatile struct
++{
++ /* 0x0000 */ u32 toytrim;
++ /* 0x0004 */ u32 toywrite;
++ /* 0x0008 */ u32 toymatch0;
++ /* 0x000C */ u32 toymatch1;
++ /* 0x0010 */ u32 toymatch2;
++ /* 0x0014 */ u32 cntrctrl;
++ /* 0x0018 */ u32 scratch0;
++ /* 0x001C */ u32 scratch1;
++ /* 0x0020 */ u32 freqctrl0;
++ /* 0x0024 */ u32 freqctrl1;
++ /* 0x0028 */ u32 clksrc;
++ /* 0x002C */ u32 pinfunc;
++ /* 0x0030 */ u32 reserved0;
++ /* 0x0034 */ u32 wakemsk;
++ /* 0x0038 */ u32 endian;
++ /* 0x003C */ u32 powerctrl;
++ /* 0x0040 */ u32 toyread;
++ /* 0x0044 */ u32 rtctrim;
++ /* 0x0048 */ u32 rtcwrite;
++ /* 0x004C */ u32 rtcmatch0;
++ /* 0x0050 */ u32 rtcmatch1;
++ /* 0x0054 */ u32 rtcmatch2;
++ /* 0x0058 */ u32 rtcread;
++ /* 0x005C */ u32 wakesrc;
++ /* 0x0060 */ u32 cpupll;
++ /* 0x0064 */ u32 auxpll;
++ /* 0x0068 */ u32 reserved1;
++ /* 0x006C */ u32 reserved2;
++ /* 0x0070 */ u32 reserved3;
++ /* 0x0074 */ u32 reserved4;
++ /* 0x0078 */ u32 slppwr;
++ /* 0x007C */ u32 sleep;
++ /* 0x0080 */ u32 reserved5[32];
++ /* 0x0100 */ u32 trioutrd;
++#define trioutclr trioutrd
++ /* 0x0104 */ u32 reserved6;
++ /* 0x0108 */ u32 outputrd;
++#define outputset outputrd
++ /* 0x010C */ u32 outputclr;
++ /* 0x0110 */ u32 pinstaterd;
++#define pininputen pinstaterd
++
++} AU1X00_SYS;
++
++static AU1X00_SYS* const sys = (AU1X00_SYS *)SYS_BASE;
++
++#endif
+ /* Processor information base on prid.
+ * Copied from PowerPC.
+ */
++#ifndef _LANGUAGE_ASSEMBLY
+ struct cpu_spec {
+ /* CPU is matched via (PRID & prid_mask) == prid_value */
+ unsigned int prid_mask;
+@@ -1404,3 +1849,6 @@
+ extern struct cpu_spec cpu_specs[];
+ extern struct cpu_spec *cur_cpu_spec[];
+ #endif
++
++#endif
++
+diff -Nur linux-2.4.32-rc1/include/asm-mips/au1000_pcmcia.h linux-2.4.32-rc1.mips/include/asm-mips/au1000_pcmcia.h
+--- linux-2.4.32-rc1/include/asm-mips/au1000_pcmcia.h 2005-01-19 15:10:11.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/au1000_pcmcia.h 2005-01-30 09:01:28.000000000 +0100
+@@ -38,16 +38,41 @@
+ #define AU1X_SOCK0_PHYS_MEM 0xF80000000
+
+ /* pcmcia socket 1 needs external glue logic so the memory map
+- * differs from board to board.
++ * differs from board to board. the general rule is that
++ * static bus address bit 26 should be used to decode socket 0
++ * from socket 1. alas, some boards dont follow this...
++ * These really belong in a board-specific header file...
+ */
+-#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_PB1500)
+-#define AU1X_SOCK1_IO 0xF08000000
+-#define AU1X_SOCK1_PHYS_ATTR 0xF48000000
+-#define AU1X_SOCK1_PHYS_MEM 0xF88000000
+-#elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500) || defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_DB1550)
+-#define AU1X_SOCK1_IO 0xF04000000
+-#define AU1X_SOCK1_PHYS_ATTR 0xF44000000
+-#define AU1X_SOCK1_PHYS_MEM 0xF84000000
++#ifdef CONFIG_MIPS_PB1000
++#define SOCK1_DECODE (1<<27)
++#endif
++#ifdef CONFIG_MIPS_DB1000
++#define SOCK1_DECODE (1<<26)
++#endif
++#ifdef CONFIG_MIPS_DB1500
++#define SOCK1_DECODE (1<<26)
++#endif
++#ifdef CONFIG_MIPS_DB1100
++#define SOCK1_DECODE (1<<26)
++#endif
++#ifdef CONFIG_MIPS_DB1550
++#define SOCK1_DECODE (1<<26)
++#endif
++#ifdef CONFIG_MIPS_DB1200
++#define SOCK1_DECODE (1<<26)
++#endif
++#ifdef CONFIG_MIPS_PB1550
++#define SOCK1_DECODE (1<<26)
++#endif
++#ifdef CONFIG_MIPS_PB1200
++#define SOCK1_DECODE (1<<26)
++#endif
++
++/* The board has a second PCMCIA socket */
++#ifdef SOCK1_DECODE
++#define AU1X_SOCK1_IO (0xF00000000|SOCK1_DECODE)
++#define AU1X_SOCK1_PHYS_ATTR (0xF40000000|SOCK1_DECODE)
++#define AU1X_SOCK1_PHYS_MEM (0xF80000000|SOCK1_DECODE)
+ #endif
+
+ struct pcmcia_state {
+diff -Nur linux-2.4.32-rc1/include/asm-mips/au1100_mmc.h linux-2.4.32-rc1.mips/include/asm-mips/au1100_mmc.h
+--- linux-2.4.32-rc1/include/asm-mips/au1100_mmc.h 2005-01-19 15:10:11.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/au1100_mmc.h 2005-01-30 09:01:28.000000000 +0100
+@@ -39,16 +39,22 @@
+ #define __ASM_AU1100_MMC_H
+
+
+-#define NUM_AU1100_MMC_CONTROLLERS 2
+-
+-
+-#define AU1100_SD_IRQ 2
+-
++#if defined(CONFIG_SOC_AU1100)
++#define NUM_MMC_CONTROLLERS 2
++#define AU1X_MMC_INT AU1100_SD_INT
++#endif
++
++#if defined(CONFIG_SOC_AU1200)
++#define NUM_MMC_CONTROLLERS 2
++#define AU1X_MMC_INT AU1200_SD_INT
++#endif
+
+ #define SD0_BASE 0xB0600000
+ #define SD1_BASE 0xB0680000
+
+
++
++
+ /*
+ * Register offsets.
+ */
+@@ -201,5 +207,12 @@
+ #define SD_CMD_RT_1B (0x00810000)
+
+
++/* support routines required on a platform-specific basis */
++extern void mmc_card_inserted(int _n_, int *_res_);
++extern void mmc_card_writable(int _n_, int *_res_);
++extern void mmc_power_on(int _n_);
++extern void mmc_power_off(int _n_);
++
++
+ #endif /* __ASM_AU1100_MMC_H */
+
+diff -Nur linux-2.4.32-rc1/include/asm-mips/au1xxx_dbdma.h linux-2.4.32-rc1.mips/include/asm-mips/au1xxx_dbdma.h
+--- linux-2.4.32-rc1/include/asm-mips/au1xxx_dbdma.h 2005-01-19 15:10:11.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/au1xxx_dbdma.h 2005-01-30 09:01:28.000000000 +0100
+@@ -43,7 +43,7 @@
+ #define DDMA_GLOBAL_BASE 0xb4003000
+ #define DDMA_CHANNEL_BASE 0xb4002000
+
+-typedef struct dbdma_global {
++typedef volatile struct dbdma_global {
+ u32 ddma_config;
+ u32 ddma_intstat;
+ u32 ddma_throttle;
+@@ -60,7 +60,7 @@
+
+ /* The structure of a DMA Channel.
+ */
+-typedef struct au1xxx_dma_channel {
++typedef volatile struct au1xxx_dma_channel {
+ u32 ddma_cfg; /* See below */
+ u32 ddma_desptr; /* 32-byte aligned pointer to descriptor */
+ u32 ddma_statptr; /* word aligned pointer to status word */
+@@ -96,7 +96,7 @@
+ /* "Standard" DDMA Descriptor.
+ * Must be 32-byte aligned.
+ */
+-typedef struct au1xxx_ddma_desc {
++typedef volatile struct au1xxx_ddma_desc {
+ u32 dscr_cmd0; /* See below */
+ u32 dscr_cmd1; /* See below */
+ u32 dscr_source0; /* source phys address */
+@@ -105,6 +105,12 @@
+ u32 dscr_dest1; /* See below */
+ u32 dscr_stat; /* completion status */
+ u32 dscr_nxtptr; /* Next descriptor pointer (mostly) */
++ /* First 32bytes are HW specific!!!
++ Lets have some SW data following.. make sure its 32bytes
++ */
++ u32 sw_status;
++ u32 sw_context;
++ u32 sw_reserved[6];
+ } au1x_ddma_desc_t;
+
+ #define DSCR_CMD0_V (1 << 31) /* Descriptor valid */
+@@ -123,6 +129,8 @@
+ #define DSCR_CMD0_CV (0x1 << 2) /* Clear Valid when done */
+ #define DSCR_CMD0_ST_MASK (0x3 << 0) /* Status instruction */
+
++#define SW_STATUS_INUSE (1<<0)
++
+ /* Command 0 device IDs.
+ */
+ #ifdef CONFIG_SOC_AU1550
+@@ -169,8 +177,8 @@
+ #define DSCR_CMD0_SDMS_RX0 9
+ #define DSCR_CMD0_SDMS_TX1 10
+ #define DSCR_CMD0_SDMS_RX1 11
+-#define DSCR_CMD0_AES_TX 12
+-#define DSCR_CMD0_AES_RX 13
++#define DSCR_CMD0_AES_TX 13
++#define DSCR_CMD0_AES_RX 12
+ #define DSCR_CMD0_PSC0_TX 14
+ #define DSCR_CMD0_PSC0_RX 15
+ #define DSCR_CMD0_PSC1_TX 16
+@@ -189,6 +197,10 @@
+ #define DSCR_CMD0_THROTTLE 30
+ #define DSCR_CMD0_ALWAYS 31
+ #define DSCR_NDEV_IDS 32
++/* THis macro is used to find/create custom device types */
++#define DSCR_DEV2CUSTOM_ID(x,d) (((((x)&0xFFFF)<<8)|0x32000000)|((d)&0xFF))
++#define DSCR_CUSTOM2DEV_ID(x) ((x)&0xFF)
++
+
+ #define DSCR_CMD0_SID(x) (((x) & 0x1f) << 25)
+ #define DSCR_CMD0_DID(x) (((x) & 0x1f) << 20)
+@@ -277,6 +289,43 @@
+ */
+ #define NUM_DBDMA_CHANS 16
+
++/*
++ * Ddma API definitions
++ * FIXME: may not fit to this header file
++ */
++typedef struct dbdma_device_table {
++ u32 dev_id;
++ u32 dev_flags;
++ u32 dev_tsize;
++ u32 dev_devwidth;
++ u32 dev_physaddr; /* If FIFO */
++ u32 dev_intlevel;
++ u32 dev_intpolarity;
++} dbdev_tab_t;
++
++
++typedef struct dbdma_chan_config {
++ spinlock_t lock;
++
++ u32 chan_flags;
++ u32 chan_index;
++ dbdev_tab_t *chan_src;
++ dbdev_tab_t *chan_dest;
++ au1x_dma_chan_t *chan_ptr;
++ au1x_ddma_desc_t *chan_desc_base;
++ au1x_ddma_desc_t *get_ptr, *put_ptr, *cur_ptr;
++ void *chan_callparam;
++ void (*chan_callback)(int, void *, struct pt_regs *);
++} chan_tab_t;
++
++#define DEV_FLAGS_INUSE (1 << 0)
++#define DEV_FLAGS_ANYUSE (1 << 1)
++#define DEV_FLAGS_OUT (1 << 2)
++#define DEV_FLAGS_IN (1 << 3)
++#define DEV_FLAGS_BURSTABLE (1 << 4)
++#define DEV_FLAGS_SYNC (1 << 5)
++/* end Ddma API definitions */
++
+ /* External functions for drivers to use.
+ */
+ /* Use this to allocate a dbdma channel. The device ids are one of the
+@@ -299,8 +348,8 @@
+
+ /* Put buffers on source/destination descriptors.
+ */
+-u32 au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes);
+-u32 au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes);
++u32 _au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes, u32 flags);
++u32 _au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes, u32 flags);
+
+ /* Get a buffer from the destination descriptor.
+ */
+@@ -314,5 +363,25 @@
+ void au1xxx_dbdma_chan_free(u32 chanid);
+ void au1xxx_dbdma_dump(u32 chanid);
+
++u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr );
++
++u32 au1xxx_ddma_add_device( dbdev_tab_t *dev );
++
++/*
++ Some compatibilty macros --
++ Needed to make changes to API without breaking existing drivers
++*/
++#define au1xxx_dbdma_put_source(chanid,buf,nbytes)_au1xxx_dbdma_put_source(chanid, buf, nbytes, DDMA_FLAGS_IE)
++#define au1xxx_dbdma_put_source_flags(chanid,buf,nbytes,flags) _au1xxx_dbdma_put_source(chanid, buf, nbytes, flags)
++
++#define au1xxx_dbdma_put_dest(chanid,buf,nbytes) _au1xxx_dbdma_put_dest(chanid, buf, nbytes, DDMA_FLAGS_IE)
++#define au1xxx_dbdma_put_dest_flags(chanid,buf,nbytes,flags) _au1xxx_dbdma_put_dest(chanid, buf, nbytes, flags)
++
++/*
++ * Flags for the put_source/put_dest functions.
++ */
++#define DDMA_FLAGS_IE (1<<0)
++#define DDMA_FLAGS_NOIE (1<<1)
++
+ #endif /* _LANGUAGE_ASSEMBLY */
+ #endif /* _AU1000_DBDMA_H_ */
+diff -Nur linux-2.4.32-rc1/include/asm-mips/au1xxx_gpio.h linux-2.4.32-rc1.mips/include/asm-mips/au1xxx_gpio.h
+--- linux-2.4.32-rc1/include/asm-mips/au1xxx_gpio.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/au1xxx_gpio.h 2005-01-30 09:01:28.000000000 +0100
+@@ -0,0 +1,22 @@
++
++
++#ifndef __AU1XXX_GPIO_H
++#define __AU1XXX_GPIO_H
++
++void au1xxx_gpio1_set_inputs(void);
++void au1xxx_gpio_tristate(int signal);
++void au1xxx_gpio_write(int signal, int value);
++int au1xxx_gpio_read(int signal);
++
++typedef volatile struct
++{
++ u32 dir;
++ u32 reserved;
++ u32 output;
++ u32 pinstate;
++ u32 inten;
++ u32 enable;
++
++} AU1X00_GPIO2;
++
++#endif //__AU1XXX_GPIO_H
+diff -Nur linux-2.4.32-rc1/include/asm-mips/au1xxx_psc.h linux-2.4.32-rc1.mips/include/asm-mips/au1xxx_psc.h
+--- linux-2.4.32-rc1/include/asm-mips/au1xxx_psc.h 2005-01-19 15:10:11.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/au1xxx_psc.h 2005-01-30 09:01:28.000000000 +0100
+@@ -41,6 +41,11 @@
+ #define PSC3_BASE_ADDR 0xb0d00000
+ #endif
+
++#ifdef CONFIG_SOC_AU1200
++#define PSC0_BASE_ADDR 0xb1a00000
++#define PSC1_BASE_ADDR 0xb1b00000
++#endif
++
+ /* The PSC select and control registers are common to
+ * all protocols.
+ */
+@@ -226,6 +231,8 @@
+ #define PSC_I2SCFG_DD_DISABLE (1 << 27)
+ #define PSC_I2SCFG_DE_ENABLE (1 << 26)
+ #define PSC_I2SCFG_SET_WS(x) (((((x) / 2) - 1) & 0x7f) << 16)
++#define PSC_I2SCFG_WS(n) ((n&0xFF)<<16)
++#define PSC_I2SCFG_WS_MASK (PSC_I2SCFG_WS(0x3F))
+ #define PSC_I2SCFG_WI (1 << 15)
+
+ #define PSC_I2SCFG_DIV_MASK (3 << 13)
+diff -Nur linux-2.4.32-rc1/include/asm-mips/bootinfo.h linux-2.4.32-rc1.mips/include/asm-mips/bootinfo.h
+--- linux-2.4.32-rc1/include/asm-mips/bootinfo.h 2004-02-18 14:36:32.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/bootinfo.h 2005-01-30 09:01:28.000000000 +0100
+@@ -180,6 +180,9 @@
+ #define MACH_MTX1 7 /* 4G MTX-1 Au1500-based board */
+ #define MACH_CSB250 8 /* Cogent Au1500 */
+ #define MACH_PB1550 9 /* Au1550-based eval board */
++#define MACH_PB1200 10 /* Au1200-based eval board */
++#define MACH_DB1550 11 /* Au1550-based eval board */
++#define MACH_DB1200 12 /* Au1200-based eval board */
+
+ /*
+ * Valid machtype for group NEC_VR41XX
+diff -Nur linux-2.4.32-rc1/include/asm-mips/db1200.h linux-2.4.32-rc1.mips/include/asm-mips/db1200.h
+--- linux-2.4.32-rc1/include/asm-mips/db1200.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/db1200.h 2005-01-30 09:02:45.000000000 +0100
+@@ -0,0 +1,214 @@
++/*
++ * AMD Alchemy DB1200 Referrence Board
++ * Board Registers defines.
++ *
++ * ########################################################################
++ *
++ * This program is free software; you can distribute 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 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 __ASM_DB1200_H
++#define __ASM_DB1200_H
++
++#include <linux/types.h>
++
++// This is defined in au1000.h with bogus value
++#undef AU1X00_EXTERNAL_INT
++
++#define DBDMA_AC97_TX_CHAN DSCR_CMD0_PSC1_TX
++#define DBDMA_AC97_RX_CHAN DSCR_CMD0_PSC1_RX
++#define DBDMA_I2S_TX_CHAN DSCR_CMD0_PSC1_TX
++#define DBDMA_I2S_RX_CHAN DSCR_CMD0_PSC1_RX
++
++/* SPI and SMB are muxed on the Pb1200 board.
++ Refer to board documentation.
++ */
++#define SPI_PSC_BASE PSC0_BASE_ADDR
++#define SMBUS_PSC_BASE PSC0_BASE_ADDR
++/* AC97 and I2S are muxed on the Pb1200 board.
++ Refer to board documentation.
++ */
++#define AC97_PSC_BASE PSC1_BASE_ADDR
++#define I2S_PSC_BASE PSC1_BASE_ADDR
++
++#define BCSR_KSEG1_ADDR 0xB9800000
++
++typedef volatile struct
++{
++ /*00*/ u16 whoami;
++ u16 reserved0;
++ /*04*/ u16 status;
++ u16 reserved1;
++ /*08*/ u16 switches;
++ u16 reserved2;
++ /*0C*/ u16 resets;
++ u16 reserved3;
++
++ /*10*/ u16 pcmcia;
++ u16 reserved4;
++ /*14*/ u16 board;
++ u16 reserved5;
++ /*18*/ u16 disk_leds;
++ u16 reserved6;
++ /*1C*/ u16 system;
++ u16 reserved7;
++
++ /*20*/ u16 intclr;
++ u16 reserved8;
++ /*24*/ u16 intset;
++ u16 reserved9;
++ /*28*/ u16 intclr_mask;
++ u16 reserved10;
++ /*2C*/ u16 intset_mask;
++ u16 reserved11;
++
++ /*30*/ u16 sig_status;
++ u16 reserved12;
++ /*34*/ u16 int_status;
++ u16 reserved13;
++ /*38*/ u16 reserved14;
++ u16 reserved15;
++ /*3C*/ u16 reserved16;
++ u16 reserved17;
++
++} BCSR;
++
++static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
++
++/*
++ * Register bit definitions for the BCSRs
++ */
++#define BCSR_WHOAMI_DCID 0x000F
++#define BCSR_WHOAMI_CPLD 0x00F0
++#define BCSR_WHOAMI_BOARD 0x0F00
++
++#define BCSR_STATUS_PCMCIA0VS 0x0003
++#define BCSR_STATUS_PCMCIA1VS 0x000C
++#define BCSR_STATUS_SWAPBOOT 0x0040
++#define BCSR_STATUS_FLASHBUSY 0x0100
++#define BCSR_STATUS_IDECBLID 0x0200
++#define BCSR_STATUS_SD0WP 0x0400
++#define BCSR_STATUS_U0RXD 0x1000
++#define BCSR_STATUS_U1RXD 0x2000
++
++#define BCSR_SWITCHES_OCTAL 0x00FF
++#define BCSR_SWITCHES_DIP_1 0x0080
++#define BCSR_SWITCHES_DIP_2 0x0040
++#define BCSR_SWITCHES_DIP_3 0x0020
++#define BCSR_SWITCHES_DIP_4 0x0010
++#define BCSR_SWITCHES_DIP_5 0x0008
++#define BCSR_SWITCHES_DIP_6 0x0004
++#define BCSR_SWITCHES_DIP_7 0x0002
++#define BCSR_SWITCHES_DIP_8 0x0001
++#define BCSR_SWITCHES_ROTARY 0x0F00
++
++#define BCSR_RESETS_ETH 0x0001
++#define BCSR_RESETS_CAMERA 0x0002
++#define BCSR_RESETS_DC 0x0004
++#define BCSR_RESETS_IDE 0x0008
++#define BCSR_RESETS_TV 0x0010
++/* not resets but in the same register */
++#define BCSR_RESETS_PWMR1mUX 0x0800
++#define BCSR_RESETS_PCS0MUX 0x1000
++#define BCSR_RESETS_PCS1MUX 0x2000
++#define BCSR_RESETS_SPISEL 0x4000
++
++#define BCSR_PCMCIA_PC0VPP 0x0003
++#define BCSR_PCMCIA_PC0VCC 0x000C
++#define BCSR_PCMCIA_PC0DRVEN 0x0010
++#define BCSR_PCMCIA_PC0RST 0x0080
++#define BCSR_PCMCIA_PC1VPP 0x0300
++#define BCSR_PCMCIA_PC1VCC 0x0C00
++#define BCSR_PCMCIA_PC1DRVEN 0x1000
++#define BCSR_PCMCIA_PC1RST 0x8000
++
++#define BCSR_BOARD_LCDVEE 0x0001
++#define BCSR_BOARD_LCDVDD 0x0002
++#define BCSR_BOARD_LCDBL 0x0004
++#define BCSR_BOARD_CAMSNAP 0x0010
++#define BCSR_BOARD_CAMPWR 0x0020
++#define BCSR_BOARD_SD0PWR 0x0040
++
++#define BCSR_LEDS_DECIMALS 0x0003
++#define BCSR_LEDS_LED0 0x0100
++#define BCSR_LEDS_LED1 0x0200
++#define BCSR_LEDS_LED2 0x0400
++#define BCSR_LEDS_LED3 0x0800
++
++#define BCSR_SYSTEM_POWEROFF 0x4000
++#define BCSR_SYSTEM_RESET 0x8000
++
++/* Bit positions for the different interrupt sources */
++#define BCSR_INT_IDE 0x0001
++#define BCSR_INT_ETH 0x0002
++#define BCSR_INT_PC0 0x0004
++#define BCSR_INT_PC0STSCHG 0x0008
++#define BCSR_INT_PC1 0x0010
++#define BCSR_INT_PC1STSCHG 0x0020
++#define BCSR_INT_DC 0x0040
++#define BCSR_INT_FLASHBUSY 0x0080
++#define BCSR_INT_PC0INSERT 0x0100
++#define BCSR_INT_PC0EJECT 0x0200
++#define BCSR_INT_PC1INSERT 0x0400
++#define BCSR_INT_PC1EJECT 0x0800
++#define BCSR_INT_SD0INSERT 0x1000
++#define BCSR_INT_SD0EJECT 0x2000
++
++#define AU1XXX_SMC91111_PHYS_ADDR (0x19000300)
++#define AU1XXX_SMC91111_IRQ DB1200_ETH_INT
++
++#define AU1XXX_ATA_PHYS_ADDR (0x18800000)
++#define AU1XXX_ATA_PHYS_LEN (0x100)
++#define AU1XXX_ATA_REG_OFFSET (5)
++#define AU1XXX_ATA_INT DB1200_IDE_INT
++#define AU1XXX_ATA_DDMA_REQ DSCR_CMD0_DMA_REQ1;
++#define AU1XXX_ATA_RQSIZE 128
++
++#define NAND_PHYS_ADDR 0x20000000
++
++/*
++ * External Interrupts for Pb1200 as of 8/6/2004.
++ * Bit positions in the CPLD registers can be calculated by taking
++ * the interrupt define and subtracting the DB1200_INT_BEGIN value.
++ * *example: IDE bis pos is = 64 - 64
++ ETH bit pos is = 65 - 64
++ */
++#define DB1200_INT_BEGIN (AU1000_LAST_INTC1_INT + 1)
++#define DB1200_IDE_INT (DB1200_INT_BEGIN + 0)
++#define DB1200_ETH_INT (DB1200_INT_BEGIN + 1)
++#define DB1200_PC0_INT (DB1200_INT_BEGIN + 2)
++#define DB1200_PC0_STSCHG_INT (DB1200_INT_BEGIN + 3)
++#define DB1200_PC1_INT (DB1200_INT_BEGIN + 4)
++#define DB1200_PC1_STSCHG_INT (DB1200_INT_BEGIN + 5)
++#define DB1200_DC_INT (DB1200_INT_BEGIN + 6)
++#define DB1200_FLASHBUSY_INT (DB1200_INT_BEGIN + 7)
++#define DB1200_PC0_INSERT_INT (DB1200_INT_BEGIN + 8)
++#define DB1200_PC0_EJECT_INT (DB1200_INT_BEGIN + 9)
++#define DB1200_PC1_INSERT_INT (DB1200_INT_BEGIN + 10)
++#define DB1200_PC1_EJECT_INT (DB1200_INT_BEGIN + 11)
++#define DB1200_SD0_INSERT_INT (DB1200_INT_BEGIN + 12)
++#define DB1200_SD0_EJECT_INT (DB1200_INT_BEGIN + 13)
++
++#define DB1200_INT_END (DB1200_INT_BEGIN + 15)
++
++/* For drivers/pcmcia/au1000_db1x00.c */
++#define BOARD_PC0_INT DB1200_PC0_INT
++#define BOARD_PC1_INT DB1200_PC1_INT
++#define BOARD_CARD_INSERTED(SOCKET) bcsr->sig_status & (1<<(8+(2*SOCKET)))
++
++#endif /* __ASM_DB1200_H */
++
+diff -Nur linux-2.4.32-rc1/include/asm-mips/db1x00.h linux-2.4.32-rc1.mips/include/asm-mips/db1x00.h
+--- linux-2.4.32-rc1/include/asm-mips/db1x00.h 2005-01-19 15:10:11.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/db1x00.h 2005-01-30 09:06:19.000000000 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * AMD Alchemy DB1x00 Reference Boards
++ * AMD Alchemy DB1x00 Reference Boards (BUT NOT DB1200)
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+@@ -36,9 +36,18 @@
+ #define AC97_PSC_BASE PSC1_BASE_ADDR
+ #define SMBUS_PSC_BASE PSC2_BASE_ADDR
+ #define I2S_PSC_BASE PSC3_BASE_ADDR
++#define NAND_CS 1
++/* for drivers/pcmcia/au1000_db1x00.c */
++#define BOARD_PC0_INT AU1000_GPIO_3
++#define BOARD_PC1_INT AU1000_GPIO_5
++#define BOARD_CARD_INSERTED(SOCKET) !(bcsr->status & (1<<(4+SOCKET)))
+
+ #else
+ #define BCSR_KSEG1_ADDR 0xAE000000
++/* for drivers/pcmcia/au1000_db1x00.c */
++#define BOARD_PC0_INT AU1000_GPIO_2
++#define BOARD_PC1_INT AU1000_GPIO_5
++#define BOARD_CARD_INSERTED(SOCKET) !(bcsr->status & (1<<(4+SOCKET)))
+ #endif
+
+ /*
+@@ -66,6 +75,7 @@
+
+ } BCSR;
+
++static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
+
+ /*
+ * Register/mask bit definitions for the BCSRs
+@@ -130,14 +140,6 @@
+
+ #define BCSR_SWRESET_RESET 0x0080
+
+-/* PCMCIA Db1x00 specific defines */
+-#define PCMCIA_MAX_SOCK 1
+-#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK+1)
+-
+-/* VPP/VCC */
+-#define SET_VCC_VPP(VCC, VPP, SLOT)\
+- ((((VCC)<<2) | ((VPP)<<0)) << ((SLOT)*8))
+-
+ /* MTD CONFIG OPTIONS */
+ #if defined(CONFIG_MTD_DB1X00_BOOT) && defined(CONFIG_MTD_DB1X00_USER)
+ #define DB1X00_BOTH_BANKS
+@@ -147,48 +149,15 @@
+ #define DB1X00_USER_ONLY
+ #endif
+
+-/* SD controller macros */
+-/*
+- * Detect card.
+- */
+-#define mmc_card_inserted(_n_, _res_) \
+- do { \
+- BCSR * const bcsr = (BCSR *)0xAE000000; \
+- unsigned long mmc_wp, board_specific; \
+- if ((_n_)) { \
+- mmc_wp = BCSR_BOARD_SD1_WP; \
+- } else { \
+- mmc_wp = BCSR_BOARD_SD0_WP; \
+- } \
+- board_specific = au_readl((unsigned long)(&bcsr->specific)); \
+- if (!(board_specific & mmc_wp)) {/* low means card present */ \
+- *(int *)(_res_) = 1; \
+- } else { \
+- *(int *)(_res_) = 0; \
+- } \
+- } while (0)
+-
++#if defined(CONFIG_BLK_DEV_IDE_AU1XXX) && defined(CONFIG_MIPS_DB1550)
+ /*
+- * Apply power to card slot(s).
++ * Daughter card information.
+ */
+-#define mmc_power_on(_n_) \
+- do { \
+- BCSR * const bcsr = (BCSR *)0xAE000000; \
+- unsigned long mmc_pwr, mmc_wp, board_specific; \
+- if ((_n_)) { \
+- mmc_pwr = BCSR_BOARD_SD1_PWR; \
+- mmc_wp = BCSR_BOARD_SD1_WP; \
+- } else { \
+- mmc_pwr = BCSR_BOARD_SD0_PWR; \
+- mmc_wp = BCSR_BOARD_SD0_WP; \
+- } \
+- board_specific = au_readl((unsigned long)(&bcsr->specific)); \
+- if (!(board_specific & mmc_wp)) {/* low means card present */ \
+- board_specific |= mmc_pwr; \
+- au_writel(board_specific, (int)(&bcsr->specific)); \
+- au_sync(); \
+- } \
+- } while (0)
++#define DAUGHTER_CARD_IRQ (AU1000_GPIO_8)
++/* DC_IDE */
++#define AU1XXX_ATA_PHYS_ADDR (0x0C000000)
++#define AU1XXX_ATA_REG_OFFSET (5)
++#endif /* CONFIG_MIPS_DB1550 */
+
+ #endif /* __ASM_DB1X00_H */
+
+diff -Nur linux-2.4.32-rc1/include/asm-mips/elf.h linux-2.4.32-rc1.mips/include/asm-mips/elf.h
+--- linux-2.4.32-rc1/include/asm-mips/elf.h 2004-02-18 14:36:32.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/elf.h 2005-04-14 12:41:44.000000000 +0200
+@@ -66,9 +66,10 @@
+ #define USE_ELF_CORE_DUMP
+ #define ELF_EXEC_PAGESIZE PAGE_SIZE
+
+-#define ELF_CORE_COPY_REGS(_dest,_regs) \
+- memcpy((char *) &_dest, (char *) _regs, \
+- sizeof(struct pt_regs));
++extern void dump_regs(elf_greg_t *, struct pt_regs *regs);
++
++#define ELF_CORE_COPY_REGS(elf_regs, regs) \
++ dump_regs((elf_greg_t *)&(elf_regs), regs);
+
+ /* This yields a mask that user programs can use to figure out what
+ instruction set this cpu supports. This could be done in userspace,
+diff -Nur linux-2.4.32-rc1/include/asm-mips/ficmmp.h linux-2.4.32-rc1.mips/include/asm-mips/ficmmp.h
+--- linux-2.4.32-rc1/include/asm-mips/ficmmp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/ficmmp.h 2005-01-30 09:01:28.000000000 +0100
+@@ -0,0 +1,156 @@
++/*
++ * FIC MMP
++ *
++ * ########################################################################
++ *
++ * This program is free software; you can distribute 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 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 __ASM_FICMMP_H
++#define __ASM_FICMMP_H
++
++#include <linux/types.h>
++#include <asm/au1000.h>
++#include <asm/au1xxx_gpio.h>
++
++// This is defined in au1000.h with bogus value
++#undef AU1X00_EXTERNAL_INT
++
++#define DBDMA_AC97_TX_CHAN DSCR_CMD0_PSC1_TX
++#define DBDMA_AC97_RX_CHAN DSCR_CMD0_PSC1_RX
++#define DBDMA_I2S_TX_CHAN DSCR_CMD0_PSC1_TX
++#define DBDMA_I2S_RX_CHAN DSCR_CMD0_PSC1_RX
++/* SPI and SMB are muxed on the Pb1200 board.
++ Refer to board documentation.
++ */
++#define SPI_PSC_BASE PSC0_BASE_ADDR
++#define SMBUS_PSC_BASE PSC0_BASE_ADDR
++/* AC97 and I2S are muxed on the Pb1200 board.
++ Refer to board documentation.
++ */
++#define AC97_PSC_BASE PSC1_BASE_ADDR
++#define I2S_PSC_BASE PSC1_BASE_ADDR
++
++
++/*
++ * SMSC LAN91C111
++ */
++#define AU1XXX_SMC91111_PHYS_ADDR (0xAC000300)
++#define AU1XXX_SMC91111_IRQ AU1000_GPIO_5
++
++/* DC_IDE and DC_ETHERNET */
++#define FICMMP_IDE_INT AU1000_GPIO_4
++
++#define AU1XXX_ATA_PHYS_ADDR (0x0C800000)
++#define AU1XXX_ATA_REG_OFFSET (5)
++/*
++#define AU1XXX_ATA_BASE (0x0C800000)
++#define AU1XXX_ATA_END (0x0CFFFFFF)
++#define AU1XXX_ATA_MEM_SIZE (AU1XXX_ATA_END - AU1XXX_ATA_BASE +1)
++
++#define AU1XXX_ATA_REG_OFFSET (5)
++*/
++/* VPP/VCC */
++#define SET_VCC_VPP(VCC, VPP, SLOT)\
++ ((((VCC)<<2) | ((VPP)<<0)) << ((SLOT)*8))
++
++
++#define FICMMP_CONFIG_BASE 0xAD000000
++#define FICMMP_CONFIG_ENABLE 13
++
++#define FICMMP_CONFIG_I2SFREQ(N) (N<<0)
++#define FICMMP_CONFIG_I2SXTAL0 (1<<0)
++#define FICMMP_CONFIG_I2SXTAL1 (1<<1)
++#define FICMMP_CONFIG_I2SXTAL2 (1<<2)
++#define FICMMP_CONFIG_I2SXTAL3 (1<<3)
++#define FICMMP_CONFIG_ADV1 (1<<4)
++#define FICMMP_CONFIG_IDERST (1<<5)
++#define FICMMP_CONFIG_LCMEN (1<<6)
++#define FICMMP_CONFIG_CAMPWDN (1<<7)
++#define FICMMP_CONFIG_USBPWREN (1<<8)
++#define FICMMP_CONFIG_LCMPWREN (1<<9)
++#define FICMMP_CONFIG_TVOUTPWREN (1<<10)
++#define FICMMP_CONFIG_RS232PWREN (1<<11)
++#define FICMMP_CONFIG_LCMDATAOUT (1<<12)
++#define FICMMP_CONFIG_TVODATAOUT (1<<13)
++#define FICMMP_CONFIG_ADV3 (1<<14)
++#define FICMMP_CONFIG_ADV4 (1<<15)
++
++#define I2S_FREQ_8_192 (0x0)
++#define I2S_FREQ_11_2896 (0x1)
++#define I2S_FREQ_12_288 (0x2)
++#define I2S_FREQ_24_576 (0x3)
++//#define I2S_FREQ_12_288 (0x4)
++#define I2S_FREQ_16_9344 (0x5)
++#define I2S_FREQ_18_432 (0x6)
++#define I2S_FREQ_36_864 (0x7)
++#define I2S_FREQ_16_384 (0x8)
++#define I2S_FREQ_22_5792 (0x9)
++//#define I2S_FREQ_24_576 (0x10)
++#define I2S_FREQ_49_152 (0x11)
++//#define I2S_FREQ_24_576 (0x12)
++#define I2S_FREQ_33_8688 (0x13)
++//#define I2S_FREQ_36_864 (0x14)
++#define I2S_FREQ_73_728 (0x15)
++
++#define FICMMP_IDE_PWR 9
++#define FICMMP_FOCUS_RST 2
++
++static __inline void ficmmp_config_set(u16 bits)
++{
++ extern u16 ficmmp_config;
++ //printk("set_config: %X, Old: %X, New: %X\n", bits, ficmmp_config, ficmmp_config | bits);
++ ficmmp_config |= bits;
++ *((u16*)FICMMP_CONFIG_BASE) = ficmmp_config;
++}
++
++static __inline void ficmmp_config_clear(u16 bits)
++{
++ extern u16 ficmmp_config;
++// printk("clear_config: %X, Old: %X, New: %X\n", bits, ficmmp_config, ficmmp_config & ~bits);
++ ficmmp_config &= ~bits;
++ *((u16*)FICMMP_CONFIG_BASE) = ficmmp_config;
++}
++
++static __inline void ficmmp_config_init(void)
++{
++ au1xxx_gpio_write(FICMMP_CONFIG_ENABLE, 0); //Enable configuration latch
++ ficmmp_config_set(FICMMP_CONFIG_LCMDATAOUT | FICMMP_CONFIG_TVODATAOUT | FICMMP_CONFIG_IDERST); //Disable display data buffers
++ ficmmp_config_set(FICMMP_CONFIG_I2SFREQ(I2S_FREQ_36_864));
++}
++
++static __inline u32 ficmmp_set_i2s_sample_rate(u32 rate)
++{
++ u32 freq;
++
++ switch(rate)
++ {
++ case 88200:
++ case 44100:
++ case 8018: freq = I2S_FREQ_11_2896; break;
++ case 48000:
++ case 32000: //freq = I2S_FREQ_18_432; break;
++ case 8000: freq = I2S_FREQ_12_288; break;
++ default: freq = I2S_FREQ_12_288; rate = 8000;
++ }
++ ficmmp_config_clear(FICMMP_CONFIG_I2SFREQ(0xF));
++ ficmmp_config_set(FICMMP_CONFIG_I2SFREQ(freq));
++ return rate;
++}
++
++#endif /* __ASM_FICMMP_H */
++
+diff -Nur linux-2.4.32-rc1/include/asm-mips/hazards.h linux-2.4.32-rc1.mips/include/asm-mips/hazards.h
+--- linux-2.4.32-rc1/include/asm-mips/hazards.h 2004-02-18 14:36:32.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/hazards.h 2005-06-06 16:46:22.000000000 +0200
+@@ -3,7 +3,7 @@
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+- * Copyright (C) 2003 Ralf Baechle
++ * Copyright (C) 2003, 2004 Ralf Baechle
+ */
+ #ifndef _ASM_HAZARDS_H
+ #define _ASM_HAZARDS_H
+@@ -12,38 +12,200 @@
+
+ #ifdef __ASSEMBLY__
+
++ .macro _ssnop
++ sll $0, $0, 1
++ .endm
++
+ /*
+ * RM9000 hazards. When the JTLB is updated by tlbwi or tlbwr, a subsequent
+ * use of the JTLB for instructions should not occur for 4 cpu cycles and use
+ * for data translations should not occur for 3 cpu cycles.
+ */
+ #ifdef CONFIG_CPU_RM9000
+-#define rm9000_tlb_hazard \
++
++#define mtc0_tlbw_hazard \
+ .set push; \
+ .set mips32; \
+- ssnop; ssnop; ssnop; ssnop; \
++ _ssnop; _ssnop; _ssnop; _ssnop; \
+ .set pop
++
++#define tlbw_eret_hazard \
++ .set push; \
++ .set mips32; \
++ _ssnop; _ssnop; _ssnop; _ssnop; \
++ .set pop
++
+ #else
+-#define rm9000_tlb_hazard
++
++/*
++ * The taken branch will result in a two cycle penalty for the two killed
++ * instructions on R4000 / R4400. Other processors only have a single cycle
++ * hazard so this is nice trick to have an optimal code for a range of
++ * processors.
++ */
++#define mtc0_tlbw_hazard \
++ b . + 8
++#define tlbw_eret_hazard \
++ nop
+ #endif
+
++/*
++ * mtc0->mfc0 hazard
++ * The 24K has a 2 cycle mtc0/mfc0 execution hazard.
++ * It is a MIPS32R2 processor so ehb will clear the hazard.
++ */
++
++#ifdef CONFIG_CPU_MIPSR2
++/*
++ * Use a macro for ehb unless explicit support for MIPSR2 is enabled
++ */
++ .macro ehb
++ sll $0, $0, 3
++ .endm
++
++#define irq_enable_hazard \
++ ehb # irq_enable_hazard
++
++#define irq_disable_hazard \
++ ehb # irq_disable_hazard
++
++#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000)
++
++/*
++ * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
++ */
++
++#define irq_enable_hazard
++
++#define irq_disable_hazard
++
+ #else
+
+ /*
++ * Classic MIPS needs 1 - 3 nops or ssnops
++ */
++#define irq_enable_hazard
++#define irq_disable_hazard \
++ _ssnop; _ssnop; _ssnop
++
++#endif
++
++#else /* __ASSEMBLY__ */
++
++/*
+ * RM9000 hazards. When the JTLB is updated by tlbwi or tlbwr, a subsequent
+ * use of the JTLB for instructions should not occur for 4 cpu cycles and use
+ * for data translations should not occur for 3 cpu cycles.
+ */
+ #ifdef CONFIG_CPU_RM9000
+-#define rm9000_tlb_hazard() \
++
++#define mtc0_tlbw_hazard() \
+ __asm__ __volatile__( \
+ ".set\tmips32\n\t" \
+- "ssnop; ssnop; ssnop; ssnop\n\t" \
++ "_ssnop; _ssnop; _ssnop; _ssnop\n\t" \
++ ".set\tmips0")
++
++#define tlbw_use_hazard() \
++ __asm__ __volatile__( \
++ ".set\tmips32\n\t" \
++ "_ssnop; _ssnop; _ssnop; _ssnop\n\t" \
+ ".set\tmips0")
+ #else
+-#define rm9000_tlb_hazard() do { } while (0)
++
++/*
++ * Overkill warning ...
++ */
++#define mtc0_tlbw_hazard() \
++ __asm__ __volatile__( \
++ ".set noreorder\n\t" \
++ "nop; nop; nop; nop; nop; nop;\n\t" \
++ ".set reorder\n\t")
++
++#define tlbw_use_hazard() \
++ __asm__ __volatile__( \
++ ".set noreorder\n\t" \
++ "nop; nop; nop; nop; nop; nop;\n\t" \
++ ".set reorder\n\t")
++
+ #endif
+
++/*
++ * mtc0->mfc0 hazard
++ * The 24K has a 2 cycle mtc0/mfc0 execution hazard.
++ * It is a MIPS32R2 processor so ehb will clear the hazard.
++ */
++
++#ifdef CONFIG_CPU_MIPSR2
++/*
++ * Use a macro for ehb unless explicit support for MIPSR2 is enabled
++ */
++__asm__(
++ " .macro ehb \n\t"
++ " sll $0, $0, 3 \n\t"
++ " .endm \n\t"
++ " \n\t"
++ " .macro\tirq_enable_hazard \n\t"
++ " ehb \n\t"
++ " .endm \n\t"
++ " \n\t"
++ " .macro\tirq_disable_hazard \n\t"
++ " ehb \n\t"
++ " .endm");
++
++#define irq_enable_hazard() \
++ __asm__ __volatile__( \
++ "ehb\t\t\t\t# irq_enable_hazard")
++
++#define irq_disable_hazard() \
++ __asm__ __volatile__( \
++ "ehb\t\t\t\t# irq_disable_hazard")
++
++#elif defined(CONFIG_CPU_R10000)
++
++/*
++ * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
++ */
++
++__asm__(
++ " .macro\tirq_enable_hazard \n\t"
++ " .endm \n\t"
++ " \n\t"
++ " .macro\tirq_disable_hazard \n\t"
++ " .endm");
++
++#define irq_enable_hazard() do { } while (0)
++#define irq_disable_hazard() do { } while (0)
++
++#else
++
++/*
++ * Default for classic MIPS processors. Assume worst case hazards but don't
++ * care about the irq_enable_hazard - sooner or later the hardware will
++ * enable it and we don't care when exactly.
++ */
++
++__asm__(
++ " .macro _ssnop \n\t"
++ " sll $0, $2, 1 \n\t"
++ " .endm \n\t"
++ " \n\t"
++ " # \n\t"
++ " # There is a hazard but we do not care \n\t"
++ " # \n\t"
++ " .macro\tirq_enable_hazard \n\t"
++ " .endm \n\t"
++ " \n\t"
++ " .macro\tirq_disable_hazard \n\t"
++ " _ssnop; _ssnop; _ssnop \n\t"
++ " .endm");
++
++#define irq_enable_hazard() do { } while (0)
++#define irq_disable_hazard() \
++ __asm__ __volatile__( \
++ "_ssnop; _ssnop; _ssnop;\t\t# irq_disable_hazard")
++
+ #endif
+
++#endif /* __ASSEMBLY__ */
++
+ #endif /* _ASM_HAZARDS_H */
+diff -Nur linux-2.4.32-rc1/include/asm-mips/ide.h linux-2.4.32-rc1.mips/include/asm-mips/ide.h
+--- linux-2.4.32-rc1/include/asm-mips/ide.h 2003-08-25 13:44:43.000000000 +0200
++++ linux-2.4.32-rc1.mips/include/asm-mips/ide.h 2005-04-19 14:26:53.000000000 +0200
+@@ -32,12 +32,12 @@
+
+ extern struct ide_ops *ide_ops;
+
+-static __inline__ int ide_default_irq(ide_ioreg_t base)
++static inline int ide_default_irq(ide_ioreg_t base)
+ {
+ return ide_ops->ide_default_irq(base);
+ }
+
+-static __inline__ ide_ioreg_t ide_default_io_base(int index)
++static inline ide_ioreg_t ide_default_io_base(int index)
+ {
+ return ide_ops->ide_default_io_base(index);
+ }
+@@ -48,7 +48,7 @@
+ ide_ops->ide_init_hwif_ports(hw, data_port, ctrl_port, irq);
+ }
+
+-static __inline__ void ide_init_default_hwifs(void)
++static inline void ide_init_default_hwifs(void)
+ {
+ #ifndef CONFIG_BLK_DEV_IDEPCI
+ hw_regs_t hw;
+@@ -68,7 +68,89 @@
+ #define ide_ack_intr(hwif) ((hwif)->hw.ack_intr ? (hwif)->hw.ack_intr(hwif) : 1)
+ #endif
+
+-#include <asm-generic/ide_iops.h>
++/* MIPS port and memory-mapped I/O string operations. */
++
++static inline void __ide_flush_dcache_range(unsigned long addr, unsigned long size)
++{
++ if (cpu_has_dc_aliases) {
++ unsigned long end = addr + size;
++ for (; addr < end; addr += PAGE_SIZE)
++ flush_dcache_page(virt_to_page(addr));
++ }
++}
++
++static inline void __ide_insw(unsigned long port, void *addr,
++ unsigned int count)
++{
++ insw(port, addr, count);
++ __ide_flush_dcache_range((unsigned long)addr, count * 2);
++}
++
++static inline void __ide_insl(unsigned long port, void *addr, unsigned int count)
++{
++ insl(port, addr, count);
++ __ide_flush_dcache_range((unsigned long)addr, count * 4);
++}
++
++static inline void __ide_outsw(unsigned long port, const void *addr,
++ unsigned long count)
++{
++ outsw(port, addr, count);
++ __ide_flush_dcache_range((unsigned long)addr, count * 2);
++}
++
++static inline void __ide_outsl(unsigned long port, const void *addr,
++ unsigned long count)
++{
++ outsl(port, addr, count);
++ __ide_flush_dcache_range((unsigned long)addr, count * 4);
++}
++
++static inline void __ide_mm_insw(unsigned long port, void *addr, u32 count)
++{
++ unsigned long start = (unsigned long) addr;
++
++ while (count--) {
++ *(u16 *)addr = readw(port);
++ addr += 2;
++ }
++ __ide_flush_dcache_range(start, count * 2);
++}
++
++static inline void __ide_mm_insl(unsigned long port, void *addr, u32 count)
++{
++ unsigned long start = (unsigned long) addr;
++
++ while (count--) {
++ *(u32 *)addr = readl(port);
++ addr += 4;
++ }
++ __ide_flush_dcache_range(start, count * 4);
++}
++
++static inline void __ide_mm_outsw(unsigned long port, const void *addr,
++ u32 count)
++{
++ unsigned long start = (unsigned long) addr;
++
++ while (count--) {
++ writew(*(u16 *)addr, port);
++ addr += 2;
++ }
++ __ide_flush_dcache_range(start, count * 2);
++}
++
++static inline void __ide_mm_outsl(unsigned long port, const void *addr,
++ u32 count)
++{
++ unsigned long start = (unsigned long) addr;
++
++ while (count--) {
++ writel(*(u32 *)addr, port);
++ addr += 4;
++ }
++ __ide_flush_dcache_range(start, count * 4);
++}
+
+ #endif /* __KERNEL__ */
+
+diff -Nur linux-2.4.32-rc1/include/asm-mips/io.h linux-2.4.32-rc1.mips/include/asm-mips/io.h
+--- linux-2.4.32-rc1/include/asm-mips/io.h 2003-08-25 13:44:43.000000000 +0200
++++ linux-2.4.32-rc1.mips/include/asm-mips/io.h 2005-04-19 14:24:16.000000000 +0200
+@@ -392,7 +392,8 @@
+ return __ioswab32(__val);
+ }
+
+-static inline void __outsb(unsigned long port, void *addr, unsigned int count)
++static inline void __outsb(unsigned long port, const void *addr,
++ unsigned int count)
+ {
+ while (count--) {
+ outb(*(u8 *)addr, port);
+@@ -408,7 +409,8 @@
+ }
+ }
+
+-static inline void __outsw(unsigned long port, void *addr, unsigned int count)
++static inline void __outsw(unsigned long port, const void *addr,
++ unsigned int count)
+ {
+ while (count--) {
+ outw(*(u16 *)addr, port);
+@@ -424,7 +426,8 @@
+ }
+ }
+
+-static inline void __outsl(unsigned long port, void *addr, unsigned int count)
++static inline void __outsl(unsigned long port, const void *addr,
++ unsigned int count)
+ {
+ while (count--) {
+ outl(*(u32 *)addr, port);
+diff -Nur linux-2.4.32-rc1/include/asm-mips/mipsregs.h linux-2.4.32-rc1.mips/include/asm-mips/mipsregs.h
+--- linux-2.4.32-rc1/include/asm-mips/mipsregs.h 2005-01-19 15:10:12.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/mipsregs.h 2005-02-06 22:24:22.000000000 +0100
+@@ -757,10 +757,18 @@
+ #define read_c0_config1() __read_32bit_c0_register($16, 1)
+ #define read_c0_config2() __read_32bit_c0_register($16, 2)
+ #define read_c0_config3() __read_32bit_c0_register($16, 3)
++#define read_c0_config4() __read_32bit_c0_register($16, 4)
++#define read_c0_config5() __read_32bit_c0_register($16, 5)
++#define read_c0_config6() __read_32bit_c0_register($16, 6)
++#define read_c0_config7() __read_32bit_c0_register($16, 7)
+ #define write_c0_config(val) __write_32bit_c0_register($16, 0, val)
+ #define write_c0_config1(val) __write_32bit_c0_register($16, 1, val)
+ #define write_c0_config2(val) __write_32bit_c0_register($16, 2, val)
+ #define write_c0_config3(val) __write_32bit_c0_register($16, 3, val)
++#define write_c0_config4(val) __write_32bit_c0_register($16, 4, val)
++#define write_c0_config5(val) __write_32bit_c0_register($16, 5, val)
++#define write_c0_config6(val) __write_32bit_c0_register($16, 6, val)
++#define write_c0_config7(val) __write_32bit_c0_register($16, 7, val)
+
+ /*
+ * The WatchLo register. There may be upto 8 of them.
+@@ -874,42 +882,34 @@
+ */
+ static inline void tlb_probe(void)
+ {
+- rm9000_tlb_hazard();
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ "tlbp\n\t"
+ ".set reorder");
+- rm9000_tlb_hazard();
+ }
+
+ static inline void tlb_read(void)
+ {
+- rm9000_tlb_hazard();
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ "tlbr\n\t"
+ ".set reorder");
+- rm9000_tlb_hazard();
+ }
+
+ static inline void tlb_write_indexed(void)
+ {
+- rm9000_tlb_hazard();
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ "tlbwi\n\t"
+ ".set reorder");
+- rm9000_tlb_hazard();
+ }
+
+ static inline void tlb_write_random(void)
+ {
+- rm9000_tlb_hazard();
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ "tlbwr\n\t"
+ ".set reorder");
+- rm9000_tlb_hazard();
+ }
+
+ /*
+diff -Nur linux-2.4.32-rc1/include/asm-mips/mmu_context.h linux-2.4.32-rc1.mips/include/asm-mips/mmu_context.h
+--- linux-2.4.32-rc1/include/asm-mips/mmu_context.h 2005-01-19 15:10:12.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/mmu_context.h 2004-11-22 14:38:29.000000000 +0100
+@@ -27,7 +27,7 @@
+ #define TLBMISS_HANDLER_SETUP_PGD(pgd) \
+ pgd_current[smp_processor_id()] = (unsigned long)(pgd)
+ #define TLBMISS_HANDLER_SETUP() \
+- write_c0_context((unsigned long) smp_processor_id() << (23 + 3)); \
++ write_c0_context((unsigned long) smp_processor_id() << 23); \
+ TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
+ extern unsigned long pgd_current[];
+
+diff -Nur linux-2.4.32-rc1/include/asm-mips/pb1100.h linux-2.4.32-rc1.mips/include/asm-mips/pb1100.h
+--- linux-2.4.32-rc1/include/asm-mips/pb1100.h 2003-08-25 13:44:44.000000000 +0200
++++ linux-2.4.32-rc1.mips/include/asm-mips/pb1100.h 2005-01-30 09:10:29.000000000 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Alchemy Semi PB1100 Referrence Board
++ * AMD Alchemy PB1100 Reference Boards
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+@@ -27,55 +27,108 @@
+ #ifndef __ASM_PB1100_H
+ #define __ASM_PB1100_H
+
+-#define PB1100_IDENT 0xAE000000
+-#define BOARD_STATUS_REG 0xAE000004
+- #define PB1100_ROM_SEL (1<<15)
+- #define PB1100_ROM_SIZ (1<<14)
+- #define PB1100_SWAP_BOOT (1<<13)
+- #define PB1100_FLASH_WP (1<<12)
+- #define PB1100_ROM_H_STS (1<<11)
+- #define PB1100_ROM_L_STS (1<<10)
+- #define PB1100_FLASH_H_STS (1<<9)
+- #define PB1100_FLASH_L_STS (1<<8)
+- #define PB1100_SRAM_SIZ (1<<7)
+- #define PB1100_TSC_BUSY (1<<6)
+- #define PB1100_PCMCIA_VS_MASK (3<<4)
+- #define PB1100_RS232_CD (1<<3)
+- #define PB1100_RS232_CTS (1<<2)
+- #define PB1100_RS232_DSR (1<<1)
+- #define PB1100_RS232_RI (1<<0)
+-
+-#define PB1100_IRDA_RS232 0xAE00000C
+- #define PB1100_IRDA_FULL (0<<14) /* full power */
+- #define PB1100_IRDA_SHUTDOWN (1<<14)
+- #define PB1100_IRDA_TT (2<<14) /* 2/3 power */
+- #define PB1100_IRDA_OT (3<<14) /* 1/3 power */
+- #define PB1100_IRDA_FIR (1<<13)
+-
+-#define PCMCIA_BOARD_REG 0xAE000010
+- #define PB1100_SD_WP1_RO (1<<15) /* read only */
+- #define PB1100_SD_WP0_RO (1<<14) /* read only */
+- #define PB1100_SD_PWR1 (1<<11) /* applies power to SD1 */
+- #define PB1100_SD_PWR0 (1<<10) /* applies power to SD0 */
+- #define PB1100_SEL_SD_CONN1 (1<<9)
+- #define PB1100_SEL_SD_CONN0 (1<<8)
+- #define PC_DEASSERT_RST (1<<7)
+- #define PC_DRV_EN (1<<4)
+-
+-#define PB1100_G_CONTROL 0xAE000014 /* graphics control */
+-
+-#define PB1100_RST_VDDI 0xAE00001C
+- #define PB1100_SOFT_RESET (1<<15) /* clear to reset the board */
+- #define PB1100_VDDI_MASK (0x1F)
++#define BCSR_KSEG1_ADDR 0xAE000000
++
++/*
++ * Overlay data structure of the Pb1100 board registers.
++ * Registers located at physical 0E0000xx, KSEG1 0xAE0000xx
++ */
++typedef volatile struct
++{
++ /*00*/ unsigned short whoami;
++ unsigned short reserved0;
++ /*04*/ unsigned short status;
++ unsigned short reserved1;
++ /*08*/ unsigned short switches;
++ unsigned short reserved2;
++ /*0C*/ unsigned short resets;
++ unsigned short reserved3;
++ /*10*/ unsigned short pcmcia;
++ unsigned short reserved4;
++ /*14*/ unsigned short graphics;
++ unsigned short reserved5;
++ /*18*/ unsigned short leds;
++ unsigned short reserved6;
++ /*1C*/ unsigned short swreset;
++ unsigned short reserved7;
++
++} BCSR;
+
+-#define PB1100_LEDS 0xAE000018
+
+-/* 11:8 is 4 discreet LEDs. Clearing a bit illuminates the LED.
+- * 7:0 is the LED Display's decimal points.
++/*
++ * Register/mask bit definitions for the BCSRs
+ */
+-#define PB1100_HEX_LED 0xAE000018
++#define BCSR_WHOAMI_DCID 0x000F
++#define BCSR_WHOAMI_CPLD 0x00F0
++#define BCSR_WHOAMI_BOARD 0x0F00
++
++#define BCSR_STATUS_RS232_RI 0x0001
++#define BCSR_STATUS_RS232_DSR 0x0002
++#define BCSR_STATUS_RS232_CTS 0x0004
++#define BCSR_STATUS_RS232_CD 0x0008
++#define BCSR_STATUS_PCMCIA_VS_MASK 0x0030
++#define BCSR_STATUS_TSC_BUSY 0x0040
++#define BCSR_STATUS_SRAM_SIZ 0x0080
++#define BCSR_STATUS_FLASH_L_STS 0x0100
++#define BCSR_STATUS_FLASH_H_STS 0x0200
++#define BCSR_STATUS_ROM_H_STS 0x0400
++#define BCSR_STATUS_ROM_L_STS 0x0800
++#define BCSR_STATUS_FLASH_WP 0x1000
++#define BCSR_STATUS_SWAP_BOOT 0x2000
++#define BCSR_STATUS_ROM_SIZ 0x4000
++#define BCSR_STATUS_ROM_SEL 0x8000
++
++#define BCSR_SWITCHES_DIP 0x00FF
++#define BCSR_SWITCHES_DIP_1 0x0080
++#define BCSR_SWITCHES_DIP_2 0x0040
++#define BCSR_SWITCHES_DIP_3 0x0020
++#define BCSR_SWITCHES_DIP_4 0x0010
++#define BCSR_SWITCHES_DIP_5 0x0008
++#define BCSR_SWITCHES_DIP_6 0x0004
++#define BCSR_SWITCHES_DIP_7 0x0002
++#define BCSR_SWITCHES_DIP_8 0x0001
++#define BCSR_SWITCHES_ROTARY 0x0F00
++#define BCSR_SWITCHES_SDO_CL 0x8000
++
++#define BCSR_RESETS_PHY0 0x0001
++#define BCSR_RESETS_PHY1 0x0002
++#define BCSR_RESETS_DC 0x0004
++#define BCSR_RESETS_RS232_RTS 0x0100
++#define BCSR_RESETS_RS232_DTR 0x0200
++#define BCSR_RESETS_FIR_SEL 0x2000
++#define BCSR_RESETS_IRDA_MODE_MASK 0xC000
++#define BCSR_RESETS_IRDA_MODE_FULL 0x0000
++#define BCSR_RESETS_IRDA_MODE_OFF 0x4000
++#define BCSR_RESETS_IRDA_MODE_2_3 0x8000
++#define BCSR_RESETS_IRDA_MODE_1_3 0xC000
++
++#define BCSR_PCMCIA_PC0VPP 0x0003
++#define BCSR_PCMCIA_PC0VCC 0x000C
++#define BCSR_PCMCIA_PC0_DR_VEN 0x0010
++#define BCSR_PCMCIA_PC0RST 0x0080
++#define BCSR_PCMCIA_SEL_SD_CON0 0x0100
++#define BCSR_PCMCIA_SEL_SD_CON1 0x0200
++#define BCSR_PCMCIA_SD0_PWR 0x0400
++#define BCSR_PCMCIA_SD1_PWR 0x0800
++#define BCSR_PCMCIA_SD0_WP 0x4000
++#define BCSR_PCMCIA_SD1_WP 0x8000
++
++#define PB1100_G_CONTROL 0xAE000014
++#define BCSR_GRAPHICS_GPX_SMPASS 0x0010
++#define BCSR_GRAPHICS_GPX_BIG_ENDIAN 0x0020
++#define BCSR_GRAPHICS_GPX_RST 0x0040
++
++#define BCSR_LEDS_DECIMALS 0x00FF
++#define BCSR_LEDS_LED0 0x0100
++#define BCSR_LEDS_LED1 0x0200
++#define BCSR_LEDS_LED2 0x0400
++#define BCSR_LEDS_LED3 0x0800
++
++#define BCSR_SWRESET_RESET 0x0080
++#define BCSR_VDDI_VDI 0x001F
+
+-/* PCMCIA PB1100 specific defines */
++
++ /* PCMCIA Pb1x00 specific defines */
+ #define PCMCIA_MAX_SOCK 0
+ #define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK+1)
+
+@@ -83,3 +136,4 @@
+ #define SET_VCC_VPP(VCC, VPP) (((VCC)<<2) | ((VPP)<<0))
+
+ #endif /* __ASM_PB1100_H */
++
+diff -Nur linux-2.4.32-rc1/include/asm-mips/pb1200.h linux-2.4.32-rc1.mips/include/asm-mips/pb1200.h
+--- linux-2.4.32-rc1/include/asm-mips/pb1200.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/pb1200.h 2005-01-30 09:01:28.000000000 +0100
+@@ -0,0 +1,244 @@
++/*
++ * AMD Alchemy PB1200 Referrence Board
++ * Board Registers defines.
++ *
++ * ########################################################################
++ *
++ * This program is free software; you can distribute 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 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 __ASM_PB1200_H
++#define __ASM_PB1200_H
++
++#include <linux/types.h>
++
++// This is defined in au1000.h with bogus value
++#undef AU1X00_EXTERNAL_INT
++
++#define DBDMA_AC97_TX_CHAN DSCR_CMD0_PSC1_TX
++#define DBDMA_AC97_RX_CHAN DSCR_CMD0_PSC1_RX
++#define DBDMA_I2S_TX_CHAN DSCR_CMD0_PSC1_TX
++#define DBDMA_I2S_RX_CHAN DSCR_CMD0_PSC1_RX
++
++/* SPI and SMB are muxed on the Pb1200 board.
++ Refer to board documentation.
++ */
++#define SPI_PSC_BASE PSC0_BASE_ADDR
++#define SMBUS_PSC_BASE PSC0_BASE_ADDR
++/* AC97 and I2S are muxed on the Pb1200 board.
++ Refer to board documentation.
++ */
++#define AC97_PSC_BASE PSC1_BASE_ADDR
++#define I2S_PSC_BASE PSC1_BASE_ADDR
++
++#define BCSR_KSEG1_ADDR 0xAD800000
++
++typedef volatile struct
++{
++ /*00*/ u16 whoami;
++ u16 reserved0;
++ /*04*/ u16 status;
++ u16 reserved1;
++ /*08*/ u16 switches;
++ u16 reserved2;
++ /*0C*/ u16 resets;
++ u16 reserved3;
++
++ /*10*/ u16 pcmcia;
++ u16 reserved4;
++ /*14*/ u16 board;
++ u16 reserved5;
++ /*18*/ u16 disk_leds;
++ u16 reserved6;
++ /*1C*/ u16 system;
++ u16 reserved7;
++
++ /*20*/ u16 intclr;
++ u16 reserved8;
++ /*24*/ u16 intset;
++ u16 reserved9;
++ /*28*/ u16 intclr_mask;
++ u16 reserved10;
++ /*2C*/ u16 intset_mask;
++ u16 reserved11;
++
++ /*30*/ u16 sig_status;
++ u16 reserved12;
++ /*34*/ u16 int_status;
++ u16 reserved13;
++ /*38*/ u16 reserved14;
++ u16 reserved15;
++ /*3C*/ u16 reserved16;
++ u16 reserved17;
++
++} BCSR;
++
++static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
++
++/*
++ * Register bit definitions for the BCSRs
++ */
++#define BCSR_WHOAMI_DCID 0x000F
++#define BCSR_WHOAMI_CPLD 0x00F0
++#define BCSR_WHOAMI_BOARD 0x0F00
++
++#define BCSR_STATUS_PCMCIA0VS 0x0003
++#define BCSR_STATUS_PCMCIA1VS 0x000C
++#define BCSR_STATUS_SWAPBOOT 0x0040
++#define BCSR_STATUS_FLASHBUSY 0x0100
++#define BCSR_STATUS_IDECBLID 0x0200
++#define BCSR_STATUS_SD0WP 0x0400
++#define BCSR_STATUS_SD1WP 0x0800
++#define BCSR_STATUS_U0RXD 0x1000
++#define BCSR_STATUS_U1RXD 0x2000
++
++#define BCSR_SWITCHES_OCTAL 0x00FF
++#define BCSR_SWITCHES_DIP_1 0x0080
++#define BCSR_SWITCHES_DIP_2 0x0040
++#define BCSR_SWITCHES_DIP_3 0x0020
++#define BCSR_SWITCHES_DIP_4 0x0010
++#define BCSR_SWITCHES_DIP_5 0x0008
++#define BCSR_SWITCHES_DIP_6 0x0004
++#define BCSR_SWITCHES_DIP_7 0x0002
++#define BCSR_SWITCHES_DIP_8 0x0001
++#define BCSR_SWITCHES_ROTARY 0x0F00
++
++#define BCSR_RESETS_ETH 0x0001
++#define BCSR_RESETS_CAMERA 0x0002
++#define BCSR_RESETS_DC 0x0004
++#define BCSR_RESETS_IDE 0x0008
++/* not resets but in the same register */
++#define BCSR_RESETS_WSCFSM 0x0800
++#define BCSR_RESETS_PCS0MUX 0x1000
++#define BCSR_RESETS_PCS1MUX 0x2000
++#define BCSR_RESETS_SPISEL 0x4000
++#define BCSR_RESETS_SD1MUX 0x8000
++
++#define BCSR_PCMCIA_PC0VPP 0x0003
++#define BCSR_PCMCIA_PC0VCC 0x000C
++#define BCSR_PCMCIA_PC0DRVEN 0x0010
++#define BCSR_PCMCIA_PC0RST 0x0080
++#define BCSR_PCMCIA_PC1VPP 0x0300
++#define BCSR_PCMCIA_PC1VCC 0x0C00
++#define BCSR_PCMCIA_PC1DRVEN 0x1000
++#define BCSR_PCMCIA_PC1RST 0x8000
++
++#define BCSR_BOARD_LCDVEE 0x0001
++#define BCSR_BOARD_LCDVDD 0x0002
++#define BCSR_BOARD_LCDBL 0x0004
++#define BCSR_BOARD_CAMSNAP 0x0010
++#define BCSR_BOARD_CAMPWR 0x0020
++#define BCSR_BOARD_SD0PWR 0x0040
++#define BCSR_BOARD_SD1PWR 0x0080
++
++#define BCSR_LEDS_DECIMALS 0x00FF
++#define BCSR_LEDS_LED0 0x0100
++#define BCSR_LEDS_LED1 0x0200
++#define BCSR_LEDS_LED2 0x0400
++#define BCSR_LEDS_LED3 0x0800
++
++#define BCSR_SYSTEM_VDDI 0x001F
++#define BCSR_SYSTEM_POWEROFF 0x4000
++#define BCSR_SYSTEM_RESET 0x8000
++
++/* Bit positions for the different interrupt sources */
++#define BCSR_INT_IDE 0x0001
++#define BCSR_INT_ETH 0x0002
++#define BCSR_INT_PC0 0x0004
++#define BCSR_INT_PC0STSCHG 0x0008
++#define BCSR_INT_PC1 0x0010
++#define BCSR_INT_PC1STSCHG 0x0020
++#define BCSR_INT_DC 0x0040
++#define BCSR_INT_FLASHBUSY 0x0080
++#define BCSR_INT_PC0INSERT 0x0100
++#define BCSR_INT_PC0EJECT 0x0200
++#define BCSR_INT_PC1INSERT 0x0400
++#define BCSR_INT_PC1EJECT 0x0800
++#define BCSR_INT_SD0INSERT 0x1000
++#define BCSR_INT_SD0EJECT 0x2000
++#define BCSR_INT_SD1INSERT 0x4000
++#define BCSR_INT_SD1EJECT 0x8000
++
++#define AU1XXX_SMC91111_PHYS_ADDR (0x0D000300)
++#define AU1XXX_SMC91111_IRQ PB1200_ETH_INT
++
++#define AU1XXX_ATA_PHYS_ADDR (0x0C800000)
++#define AU1XXX_ATA_PHYS_LEN (0x100)
++#define AU1XXX_ATA_REG_OFFSET (5)
++#define AU1XXX_ATA_INT PB1200_IDE_INT
++#define AU1XXX_ATA_DDMA_REQ DSCR_CMD0_DMA_REQ1;
++#define AU1XXX_ATA_RQSIZE 128
++
++#define NAND_PHYS_ADDR 0x1C000000
++
++/* Timing values as described in databook, * ns value stripped of
++ * lower 2 bits.
++ * These defines are here rather than an SOC1200 generic file because
++ * the parts chosen on another board may be different and may require
++ * different timings.
++ */
++#define NAND_T_H (18 >> 2)
++#define NAND_T_PUL (30 >> 2)
++#define NAND_T_SU (30 >> 2)
++#define NAND_T_WH (30 >> 2)
++
++/* Bitfield shift amounts */
++#define NAND_T_H_SHIFT 0
++#define NAND_T_PUL_SHIFT 4
++#define NAND_T_SU_SHIFT 8
++#define NAND_T_WH_SHIFT 12
++
++#define NAND_TIMING ((NAND_T_H & 0xF) << NAND_T_H_SHIFT) | \
++ ((NAND_T_PUL & 0xF) << NAND_T_PUL_SHIFT) | \
++ ((NAND_T_SU & 0xF) << NAND_T_SU_SHIFT) | \
++ ((NAND_T_WH & 0xF) << NAND_T_WH_SHIFT)
++
++
++/*
++ * External Interrupts for Pb1200 as of 8/6/2004.
++ * Bit positions in the CPLD registers can be calculated by taking
++ * the interrupt define and subtracting the PB1200_INT_BEGIN value.
++ * *example: IDE bis pos is = 64 - 64
++ ETH bit pos is = 65 - 64
++ */
++#define PB1200_INT_BEGIN (AU1000_LAST_INTC1_INT + 1)
++#define PB1200_IDE_INT (PB1200_INT_BEGIN + 0)
++#define PB1200_ETH_INT (PB1200_INT_BEGIN + 1)
++#define PB1200_PC0_INT (PB1200_INT_BEGIN + 2)
++#define PB1200_PC0_STSCHG_INT (PB1200_INT_BEGIN + 3)
++#define PB1200_PC1_INT (PB1200_INT_BEGIN + 4)
++#define PB1200_PC1_STSCHG_INT (PB1200_INT_BEGIN + 5)
++#define PB1200_DC_INT (PB1200_INT_BEGIN + 6)
++#define PB1200_FLASHBUSY_INT (PB1200_INT_BEGIN + 7)
++#define PB1200_PC0_INSERT_INT (PB1200_INT_BEGIN + 8)
++#define PB1200_PC0_EJECT_INT (PB1200_INT_BEGIN + 9)
++#define PB1200_PC1_INSERT_INT (PB1200_INT_BEGIN + 10)
++#define PB1200_PC1_EJECT_INT (PB1200_INT_BEGIN + 11)
++#define PB1200_SD0_INSERT_INT (PB1200_INT_BEGIN + 12)
++#define PB1200_SD0_EJECT_INT (PB1200_INT_BEGIN + 13)
++#define PB1200_SD1_INSERT_INT (PB1200_INT_BEGIN + 14)
++#define PB1200_SD1_EJECT_INT (PB1200_INT_BEGIN + 15)
++
++#define PB1200_INT_END (PB1200_INT_BEGIN + 15)
++
++/* For drivers/pcmcia/au1000_db1x00.c */
++#define BOARD_PC0_INT PB1200_PC0_INT
++#define BOARD_PC1_INT PB1200_PC1_INT
++#define BOARD_CARD_INSERTED(SOCKET) bcsr->sig_status & (1<<(8+(2*SOCKET)))
++
++#endif /* __ASM_PB1200_H */
++
+diff -Nur linux-2.4.32-rc1/include/asm-mips/pb1550.h linux-2.4.32-rc1.mips/include/asm-mips/pb1550.h
+--- linux-2.4.32-rc1/include/asm-mips/pb1550.h 2005-01-19 15:10:12.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/pb1550.h 2005-01-30 09:01:28.000000000 +0100
+@@ -30,13 +30,11 @@
+
+ #define DBDMA_AC97_TX_CHAN DSCR_CMD0_PSC1_TX
+ #define DBDMA_AC97_RX_CHAN DSCR_CMD0_PSC1_RX
+-#define DBDMA_I2S_TX_CHAN DSCR_CMD0_PSC3_TX
+-#define DBDMA_I2S_RX_CHAN DSCR_CMD0_PSC3_RX
+-
+ #define SPI_PSC_BASE PSC0_BASE_ADDR
+ #define AC97_PSC_BASE PSC1_BASE_ADDR
+ #define SMBUS_PSC_BASE PSC2_BASE_ADDR
+ #define I2S_PSC_BASE PSC3_BASE_ADDR
++#define NAND_CS 1
+
+ #define BCSR_PHYS_ADDR 0xAF000000
+
+@@ -160,9 +158,23 @@
+ #define NAND_T_SU_SHIFT 8
+ #define NAND_T_WH_SHIFT 12
+
+-#define NAND_TIMING ((NAND_T_H & 0xF) << NAND_T_H_SHIFT) | \
+- ((NAND_T_PUL & 0xF) << NAND_T_PUL_SHIFT) | \
+- ((NAND_T_SU & 0xF) << NAND_T_SU_SHIFT) | \
+- ((NAND_T_WH & 0xF) << NAND_T_WH_SHIFT)
++#define NAND_TIMING ((NAND_T_H & 0xF) << NAND_T_H_SHIFT) | \
++ ((NAND_T_PUL & 0xF) << NAND_T_PUL_SHIFT) | \
++ ((NAND_T_SU & 0xF) << NAND_T_SU_SHIFT) | \
++ ((NAND_T_WH & 0xF) << NAND_T_WH_SHIFT)
++
++/*
++ * Daughter card information.
++ */
++#define DAUGHTER_CARD_BASE (0xAC000000)
++#define DAUGHTER_CARD_MEM_SIZE (0xADFFFFFF - DAUGHTER_CARD_BASE + 1)
++#define DAUGHTER_CARD_IRQ (AU1000_GPIO_3)
++
++/* DC_IDE and DC_ETHERNET */
++#define AU1XXX_ATA_PHYS_ADDR (0x0C000000)
++#define AU1XXX_ATA_REG_OFFSET (5)
++
++#define AU1XXX_SMC91111_PHYS_ADDR (0x0C000300)
++#define AU1XXX_SMC91111_IRQ AU1000_GPIO_3
+
+ #endif /* __ASM_PB1550_H */
+diff -Nur linux-2.4.32-rc1/include/asm-mips/reg.h linux-2.4.32-rc1.mips/include/asm-mips/reg.h
+--- linux-2.4.32-rc1/include/asm-mips/reg.h 2002-08-03 02:39:45.000000000 +0200
++++ linux-2.4.32-rc1.mips/include/asm-mips/reg.h 2005-04-14 12:41:44.000000000 +0200
+@@ -45,6 +45,9 @@
+ /*
+ * k0/k1 unsaved
+ */
++#define EF_REG26 32
++#define EF_REG27 33
++
+ #define EF_REG28 34
+ #define EF_REG29 35
+ #define EF_REG30 36
+@@ -60,6 +63,7 @@
+ #define EF_CP0_BADVADDR 41
+ #define EF_CP0_STATUS 42
+ #define EF_CP0_CAUSE 43
++#define EF_UNUSED0 44
+
+ #define EF_SIZE 180 /* size in bytes */
+
+diff -Nur linux-2.4.32-rc1/include/asm-mips/sgi/hpc3.h linux-2.4.32-rc1.mips/include/asm-mips/sgi/hpc3.h
+--- linux-2.4.32-rc1/include/asm-mips/sgi/hpc3.h 2003-08-25 13:44:44.000000000 +0200
++++ linux-2.4.32-rc1.mips/include/asm-mips/sgi/hpc3.h 2005-09-23 16:35:27.000000000 +0200
+@@ -128,26 +128,26 @@
+ volatile u32 rx_gfptr; /* current GIO fifo ptr */
+ volatile u32 rx_dfptr; /* current device fifo ptr */
+ u32 _unused1; /* padding */
+- volatile u32 rx_reset; /* reset register */
+-#define HPC3_ERXRST_CRESET 0x1 /* Reset dma channel and external controller */
+-#define HPC3_ERXRST_CLRIRQ 0x2 /* Clear channel interrupt */
+-#define HPC3_ERXRST_LBACK 0x4 /* Enable diagnostic loopback mode of Seeq8003 */
+-
+- volatile u32 rx_dconfig; /* DMA configuration register */
+-#define HPC3_ERXDCFG_D1 0x0000f /* Cycles to spend in D1 state for PIO */
+-#define HPC3_ERXDCFG_D2 0x000f0 /* Cycles to spend in D2 state for PIO */
+-#define HPC3_ERXDCFG_D3 0x00f00 /* Cycles to spend in D3 state for PIO */
+-#define HPC3_ERXDCFG_WCTRL 0x01000 /* Enable writes of desc into ex ctrl port */
+-#define HPC3_ERXDCFG_FRXDC 0x02000 /* Clear eop stat bits upon rxdc, hw seeq fix */
+-#define HPC3_ERXDCFG_FEOP 0x04000 /* Bad packet marker timeout enable */
+-#define HPC3_ERXDCFG_FIRQ 0x08000 /* Another bad packet timeout enable */
+-#define HPC3_ERXDCFG_PTO 0x30000 /* Programmed timeout value for above two */
+-
+- volatile u32 rx_pconfig; /* PIO configuration register */
+-#define HPC3_ERXPCFG_P1 0x000f /* Cycles to spend in P1 state for PIO */
+-#define HPC3_ERXPCFG_P2 0x00f0 /* Cycles to spend in P2 state for PIO */
+-#define HPC3_ERXPCFG_P3 0x0f00 /* Cycles to spend in P3 state for PIO */
+-#define HPC3_ERXPCFG_TST 0x1000 /* Diagnistic ram test feature bit */
++ volatile u32 reset; /* reset register */
++#define HPC3_ERST_CRESET 0x1 /* Reset dma channel and external controller */
++#define HPC3_ERST_CLRIRQ 0x2 /* Clear channel interrupt */
++#define HPC3_ERST_LBACK 0x4 /* Enable diagnostic loopback mode of Seeq8003 */
++
++ volatile u32 dconfig; /* DMA configuration register */
++#define HPC3_EDCFG_D1 0x0000f /* Cycles to spend in D1 state for PIO */
++#define HPC3_EDCFG_D2 0x000f0 /* Cycles to spend in D2 state for PIO */
++#define HPC3_EDCFG_D3 0x00f00 /* Cycles to spend in D3 state for PIO */
++#define HPC3_EDCFG_WCTRL 0x01000 /* Enable writes of desc into ex ctrl port */
++#define HPC3_EDCFG_FRXDC 0x02000 /* Clear eop stat bits upon rxdc, hw seeq fix */
++#define HPC3_EDCFG_FEOP 0x04000 /* Bad packet marker timeout enable */
++#define HPC3_EDCFG_FIRQ 0x08000 /* Another bad packet timeout enable */
++#define HPC3_EDCFG_PTO 0x30000 /* Programmed timeout value for above two */
++
++ volatile u32 pconfig; /* PIO configuration register */
++#define HPC3_EPCFG_P1 0x000f /* Cycles to spend in P1 state for PIO */
++#define HPC3_EPCFG_P2 0x00f0 /* Cycles to spend in P2 state for PIO */
++#define HPC3_EPCFG_P3 0x0f00 /* Cycles to spend in P3 state for PIO */
++#define HPC3_EPCFG_TST 0x1000 /* Diagnistic ram test feature bit */
+
+ u32 _unused2[0x1000/4 - 8]; /* padding */
+
+@@ -221,7 +221,7 @@
+ #define HPC3_BESTAT_PIDMASK 0x3f700 /* DMA channel parity identifier */
+
+ u32 _unused1[0x14000/4 - 5]; /* padding */
+-
++
+ /* Now direct PIO per-HPC3 peripheral access to external regs. */
+ volatile u32 scsi0_ext[256]; /* SCSI channel 0 external regs */
+ u32 _unused2[0x7c00/4];
+@@ -304,7 +304,7 @@
+ volatile u32 bbram[8192-50-14]; /* Battery backed ram */
+ };
+
+-/*
++/*
+ * It is possible to have two HPC3's within the address space on
+ * one machine, though only having one is more likely on an Indy.
+ */
+diff -Nur linux-2.4.32-rc1/include/asm-mips/tx4927/tx4927.h linux-2.4.32-rc1.mips/include/asm-mips/tx4927/tx4927.h
+--- linux-2.4.32-rc1/include/asm-mips/tx4927/tx4927.h 2003-08-25 13:44:44.000000000 +0200
++++ linux-2.4.32-rc1.mips/include/asm-mips/tx4927/tx4927.h 2004-11-22 19:02:10.000000000 +0100
+@@ -88,8 +88,8 @@
+
+
+ /* TX4927 Configuration registers (64-bit registers) */
+-#define TX4927_CONFIG_BASE 0xe300
+-#define TX4927_CONFIG_CCFG 0xe300
++#define TX4927_CONFIG_BASE 0xe000
++#define TX4927_CONFIG_CCFG 0xe000
+ #define TX4927_CONFIG_CCFG_RESERVED_42_63 BM_63_42
+ #define TX4927_CONFIG_CCFG_WDRST BM_41_41
+ #define TX4927_CONFIG_CCFG_WDREXEN BM_40_40
+@@ -124,14 +124,14 @@
+ #define TX4927_CONFIG_CCFG_ENDIAN BM_02_02
+ #define TX4927_CONFIG_CCFG_ARMODE BM_01_01
+ #define TX4927_CONFIG_CCFG_ACEHOLD BM_00_00
+-#define TX4927_CONFIG_REVID 0xe308
++#define TX4927_CONFIG_REVID 0xe008
+ #define TX4927_CONFIG_REVID_RESERVED_32_63 BM_32_63
+ #define TX4927_CONFIG_REVID_PCODE BM_16_31
+ #define TX4927_CONFIG_REVID_MJERREV BM_12_15
+ #define TX4927_CONFIG_REVID_MINEREV BM_08_11
+ #define TX4927_CONFIG_REVID_MJREV BM_04_07
+ #define TX4927_CONFIG_REVID_MINREV BM_00_03
+-#define TX4927_CONFIG_PCFG 0xe310
++#define TX4927_CONFIG_PCFG 0xe010
+ #define TX4927_CONFIG_PCFG_RESERVED_57_63 BM_57_63
+ #define TX4927_CONFIG_PCFG_DRVDATA BM_56_56
+ #define TX4927_CONFIG_PCFG_DRVCB BM_55_55
+@@ -197,10 +197,10 @@
+ #define TX4927_CONFIG_PCFG_DMASEL0_SIO1 BM_00_00
+ #define TX4927_CONFIG_PCFG_DMASEL0_ACLC0 BM_01_01
+ #define TX4927_CONFIG_PCFG_DMASEL0_ACLC2 BM_00_01
+-#define TX4927_CONFIG_TOEA 0xe318
++#define TX4927_CONFIG_TOEA 0xe018
+ #define TX4927_CONFIG_TOEA_RESERVED_36_63 BM_36_63
+ #define TX4927_CONFIG_TOEA_TOEA BM_00_35
+-#define TX4927_CONFIG_CLKCTR 0xe320
++#define TX4927_CONFIG_CLKCTR 0xe020
+ #define TX4927_CONFIG_CLKCTR_RESERVED_26_63 BM_26_63
+ #define TX4927_CONFIG_CLKCTR_ACLCKD BM_25_25
+ #define TX4927_CONFIG_CLKCTR_PIOCKD BM_24_24
+@@ -223,7 +223,7 @@
+ #define TX4927_CONFIG_CLKCTR_TM2RST BM_02_02
+ #define TX4927_CONFIG_CLKCTR_SIO0RST BM_01_01
+ #define TX4927_CONFIG_CLKCTR_SIO1RST BM_00_00
+-#define TX4927_CONFIG_GARBC 0xe330
++#define TX4927_CONFIG_GARBC 0xe030
+ #define TX4927_CONFIG_GARBC_RESERVED_10_63 BM_10_63
+ #define TX4927_CONFIG_GARBC_SET_09 BM_09_09
+ #define TX4927_CONFIG_GARBC_ARBMD BM_08_08
+@@ -243,7 +243,7 @@
+ #define TX4927_CONFIG_GARBC_PRIORITY_H3_PDMAC BM_00_00
+ #define TX4927_CONFIG_GARBC_PRIORITY_H3_DMAC BM_01_01
+ #define TX4927_CONFIG_GARBC_PRIORITY_H3_BAD_VALUE BM_00_01
+-#define TX4927_CONFIG_RAMP 0xe348
++#define TX4927_CONFIG_RAMP 0xe048
+ #define TX4927_CONFIG_RAMP_RESERVED_20_63 BM_20_63
+ #define TX4927_CONFIG_RAMP_RAMP BM_00_19
+ #define TX4927_CONFIG_LIMIT 0xefff
+@@ -456,7 +456,7 @@
+ #define TX4927_ACLC_ACINTSTS 0xf710
+ #define TX4927_ACLC_ACINTMSTS 0xf714
+ #define TX4927_ACLC_ACINTEN 0xf718
+-#define TX4927_ACLC_ACINTDIS 0xfR71c
++#define TX4927_ACLC_ACINTDIS 0xf71c
+ #define TX4927_ACLC_ACSEMAPH 0xf720
+ #define TX4927_ACLC_ACGPIDAT 0xf740
+ #define TX4927_ACLC_ACGPODAT 0xf744
+diff -Nur linux-2.4.32-rc1/include/asm-mips/unistd.h linux-2.4.32-rc1.mips/include/asm-mips/unistd.h
+--- linux-2.4.32-rc1/include/asm-mips/unistd.h 2005-01-19 15:10:12.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips/unistd.h 2004-11-24 21:30:06.000000000 +0100
+@@ -760,7 +760,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ /*
+@@ -788,7 +788,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ #define _syscall2(type,name,atype,a,btype,b) \
+@@ -813,7 +813,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ #define _syscall3(type,name,atype,a,btype,b,ctype,c) \
+@@ -839,7 +839,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ #define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \
+@@ -865,7 +865,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ #if (_MIPS_SIM == _MIPS_SIM_ABI32)
+@@ -902,7 +902,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ #define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \
+@@ -935,7 +935,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ #endif /* (_MIPS_SIM == _MIPS_SIM_ABI32) */
+@@ -966,7 +966,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ #define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \
+@@ -995,7 +995,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ #endif /* (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) */
+diff -Nur linux-2.4.32-rc1/include/asm-mips64/checksum.h linux-2.4.32-rc1.mips/include/asm-mips64/checksum.h
+--- linux-2.4.32-rc1/include/asm-mips64/checksum.h 2005-01-19 15:10:12.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips64/checksum.h 2005-09-20 12:58:50.000000000 +0200
+@@ -144,7 +144,7 @@
+ "daddu\t%0, %4\n\t"
+ "dsll32\t$1, %0, 0\n\t"
+ "daddu\t%0, $1\n\t"
+- "dsrl32\t%0, %0, 0\n\t"
++ "dsra32\t%0, %0, 0\n\t"
+ ".set\tat"
+ : "=&r" (sum)
+ : "0" (daddr), "r"(saddr),
+diff -Nur linux-2.4.32-rc1/include/asm-mips64/elf.h linux-2.4.32-rc1.mips/include/asm-mips64/elf.h
+--- linux-2.4.32-rc1/include/asm-mips64/elf.h 2004-02-18 14:36:32.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips64/elf.h 2005-04-14 12:41:44.000000000 +0200
+@@ -64,9 +64,10 @@
+ #define USE_ELF_CORE_DUMP
+ #define ELF_EXEC_PAGESIZE PAGE_SIZE
+
+-#define ELF_CORE_COPY_REGS(_dest,_regs) \
+- memcpy((char *) &_dest, (char *) _regs, \
+- sizeof(struct pt_regs));
++extern void dump_regs(elf_greg_t *, struct pt_regs *regs);
++
++#define ELF_CORE_COPY_REGS(elf_regs, regs) \
++ dump_regs((elf_greg_t *)&(elf_regs), regs);
+
+ /* This yields a mask that user programs can use to figure out what
+ instruction set this cpu supports. This could be done in userspace,
+diff -Nur linux-2.4.32-rc1/include/asm-mips64/hazards.h linux-2.4.32-rc1.mips/include/asm-mips64/hazards.h
+--- linux-2.4.32-rc1/include/asm-mips64/hazards.h 2004-02-18 14:36:32.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips64/hazards.h 2005-06-06 16:46:22.000000000 +0200
+@@ -3,7 +3,7 @@
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+- * Copyright (C) 2003 Ralf Baechle
++ * Copyright (C) 2003, 2004 Ralf Baechle
+ */
+ #ifndef _ASM_HAZARDS_H
+ #define _ASM_HAZARDS_H
+@@ -12,37 +12,200 @@
+
+ #ifdef __ASSEMBLY__
+
++ .macro _ssnop
++ sll $0, $0, 1
++ .endm
++
+ /*
+ * RM9000 hazards. When the JTLB is updated by tlbwi or tlbwr, a subsequent
+ * use of the JTLB for instructions should not occur for 4 cpu cycles and use
+ * for data translations should not occur for 3 cpu cycles.
+ */
+ #ifdef CONFIG_CPU_RM9000
+-#define rm9000_tlb_hazard \
++
++#define mtc0_tlbw_hazard \
++ .set push; \
+ .set mips32; \
+- ssnop; ssnop; ssnop; ssnop; \
+- .set mips0
++ _ssnop; _ssnop; _ssnop; _ssnop; \
++ .set pop
++
++#define tlbw_eret_hazard \
++ .set push; \
++ .set mips32; \
++ _ssnop; _ssnop; _ssnop; _ssnop; \
++ .set pop
++
+ #else
+-#define rm9000_tlb_hazard
++
++/*
++ * The taken branch will result in a two cycle penalty for the two killed
++ * instructions on R4000 / R4400. Other processors only have a single cycle
++ * hazard so this is nice trick to have an optimal code for a range of
++ * processors.
++ */
++#define mtc0_tlbw_hazard \
++ b . + 8
++#define tlbw_eret_hazard \
++ nop
+ #endif
+
++/*
++ * mtc0->mfc0 hazard
++ * The 24K has a 2 cycle mtc0/mfc0 execution hazard.
++ * It is a MIPS32R2 processor so ehb will clear the hazard.
++ */
++
++#ifdef CONFIG_CPU_MIPSR2
++/*
++ * Use a macro for ehb unless explicit support for MIPSR2 is enabled
++ */
++ .macro ehb
++ sll $0, $0, 3
++ .endm
++
++#define irq_enable_hazard \
++ ehb # irq_enable_hazard
++
++#define irq_disable_hazard \
++ ehb # irq_disable_hazard
++
++#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000)
++
++/*
++ * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
++ */
++
++#define irq_enable_hazard
++
++#define irq_disable_hazard
++
+ #else
+
+ /*
++ * Classic MIPS needs 1 - 3 nops or ssnops
++ */
++#define irq_enable_hazard
++#define irq_disable_hazard \
++ _ssnop; _ssnop; _ssnop
++
++#endif
++
++#else /* __ASSEMBLY__ */
++
++/*
+ * RM9000 hazards. When the JTLB is updated by tlbwi or tlbwr, a subsequent
+ * use of the JTLB for instructions should not occur for 4 cpu cycles and use
+ * for data translations should not occur for 3 cpu cycles.
+ */
+ #ifdef CONFIG_CPU_RM9000
+-#define rm9000_tlb_hazard() \
++
++#define mtc0_tlbw_hazard() \
++ __asm__ __volatile__( \
++ ".set\tmips32\n\t" \
++ "_ssnop; _ssnop; _ssnop; _ssnop\n\t" \
++ ".set\tmips0")
++
++#define tlbw_use_hazard() \
+ __asm__ __volatile__( \
+ ".set\tmips32\n\t" \
+- "ssnop; ssnop; ssnop; ssnop\n\t" \
++ "_ssnop; _ssnop; _ssnop; _ssnop\n\t" \
+ ".set\tmips0")
+ #else
+-#define rm9000_tlb_hazard() do { } while (0)
++
++/*
++ * Overkill warning ...
++ */
++#define mtc0_tlbw_hazard() \
++ __asm__ __volatile__( \
++ ".set noreorder\n\t" \
++ "nop; nop; nop; nop; nop; nop;\n\t" \
++ ".set reorder\n\t")
++
++#define tlbw_use_hazard() \
++ __asm__ __volatile__( \
++ ".set noreorder\n\t" \
++ "nop; nop; nop; nop; nop; nop;\n\t" \
++ ".set reorder\n\t")
++
+ #endif
+
++/*
++ * mtc0->mfc0 hazard
++ * The 24K has a 2 cycle mtc0/mfc0 execution hazard.
++ * It is a MIPS32R2 processor so ehb will clear the hazard.
++ */
++
++#ifdef CONFIG_CPU_MIPSR2
++/*
++ * Use a macro for ehb unless explicit support for MIPSR2 is enabled
++ */
++__asm__(
++ " .macro ehb \n\t"
++ " sll $0, $0, 3 \n\t"
++ " .endm \n\t"
++ " \n\t"
++ " .macro\tirq_enable_hazard \n\t"
++ " ehb \n\t"
++ " .endm \n\t"
++ " \n\t"
++ " .macro\tirq_disable_hazard \n\t"
++ " ehb \n\t"
++ " .endm");
++
++#define irq_enable_hazard() \
++ __asm__ __volatile__( \
++ "ehb\t\t\t\t# irq_enable_hazard")
++
++#define irq_disable_hazard() \
++ __asm__ __volatile__( \
++ "ehb\t\t\t\t# irq_disable_hazard")
++
++#elif defined(CONFIG_CPU_R10000)
++
++/*
++ * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
++ */
++
++__asm__(
++ " .macro\tirq_enable_hazard \n\t"
++ " .endm \n\t"
++ " \n\t"
++ " .macro\tirq_disable_hazard \n\t"
++ " .endm");
++
++#define irq_enable_hazard() do { } while (0)
++#define irq_disable_hazard() do { } while (0)
++
++#else
++
++/*
++ * Default for classic MIPS processors. Assume worst case hazards but don't
++ * care about the irq_enable_hazard - sooner or later the hardware will
++ * enable it and we don't care when exactly.
++ */
++
++__asm__(
++ " .macro _ssnop \n\t"
++ " sll $0, $2, 1 \n\t"
++ " .endm \n\t"
++ " \n\t"
++ " # \n\t"
++ " # There is a hazard but we do not care \n\t"
++ " # \n\t"
++ " .macro\tirq_enable_hazard \n\t"
++ " .endm \n\t"
++ " \n\t"
++ " .macro\tirq_disable_hazard \n\t"
++ " _ssnop; _ssnop; _ssnop \n\t"
++ " .endm");
++
++#define irq_enable_hazard() do { } while (0)
++#define irq_disable_hazard() \
++ __asm__ __volatile__( \
++ "_ssnop; _ssnop; _ssnop;\t\t# irq_disable_hazard")
++
+ #endif
+
++#endif /* __ASSEMBLY__ */
++
+ #endif /* _ASM_HAZARDS_H */
+diff -Nur linux-2.4.32-rc1/include/asm-mips64/ide.h linux-2.4.32-rc1.mips/include/asm-mips64/ide.h
+--- linux-2.4.32-rc1/include/asm-mips64/ide.h 2003-08-25 13:44:44.000000000 +0200
++++ linux-2.4.32-rc1.mips/include/asm-mips64/ide.h 2005-04-19 14:26:53.000000000 +0200
+@@ -32,12 +32,12 @@
+
+ extern struct ide_ops *ide_ops;
+
+-static __inline__ int ide_default_irq(ide_ioreg_t base)
++static inline int ide_default_irq(ide_ioreg_t base)
+ {
+ return ide_ops->ide_default_irq(base);
+ }
+
+-static __inline__ ide_ioreg_t ide_default_io_base(int index)
++static inline ide_ioreg_t ide_default_io_base(int index)
+ {
+ return ide_ops->ide_default_io_base(index);
+ }
+@@ -48,7 +48,7 @@
+ ide_ops->ide_init_hwif_ports(hw, data_port, ctrl_port, irq);
+ }
+
+-static __inline__ void ide_init_default_hwifs(void)
++static inline void ide_init_default_hwifs(void)
+ {
+ #ifndef CONFIG_BLK_DEV_IDEPCI
+ hw_regs_t hw;
+@@ -68,7 +68,89 @@
+ #define ide_ack_intr(hwif) ((hwif)->hw.ack_intr ? (hwif)->hw.ack_intr(hwif) : 1)
+ #endif
+
+-#include <asm-generic/ide_iops.h>
++/* MIPS port and memory-mapped I/O string operations. */
++
++static inline void __ide_flush_dcache_range(unsigned long addr, unsigned long size)
++{
++ if (cpu_has_dc_aliases) {
++ unsigned long end = addr + size;
++ for (; addr < end; addr += PAGE_SIZE)
++ flush_dcache_page(virt_to_page(addr));
++ }
++}
++
++static inline void __ide_insw(unsigned long port, void *addr,
++ unsigned int count)
++{
++ insw(port, addr, count);
++ __ide_flush_dcache_range((unsigned long)addr, count * 2);
++}
++
++static inline void __ide_insl(unsigned long port, void *addr, unsigned int count)
++{
++ insl(port, addr, count);
++ __ide_flush_dcache_range((unsigned long)addr, count * 4);
++}
++
++static inline void __ide_outsw(unsigned long port, const void *addr,
++ unsigned long count)
++{
++ outsw(port, addr, count);
++ __ide_flush_dcache_range((unsigned long)addr, count * 2);
++}
++
++static inline void __ide_outsl(unsigned long port, const void *addr,
++ unsigned long count)
++{
++ outsl(port, addr, count);
++ __ide_flush_dcache_range((unsigned long)addr, count * 4);
++}
++
++static inline void __ide_mm_insw(unsigned long port, void *addr, u32 count)
++{
++ unsigned long start = (unsigned long) addr;
++
++ while (count--) {
++ *(u16 *)addr = readw(port);
++ addr += 2;
++ }
++ __ide_flush_dcache_range(start, count * 2);
++}
++
++static inline void __ide_mm_insl(unsigned long port, void *addr, u32 count)
++{
++ unsigned long start = (unsigned long) addr;
++
++ while (count--) {
++ *(u32 *)addr = readl(port);
++ addr += 4;
++ }
++ __ide_flush_dcache_range(start, count * 4);
++}
++
++static inline void __ide_mm_outsw(unsigned long port, const void *addr,
++ u32 count)
++{
++ unsigned long start = (unsigned long) addr;
++
++ while (count--) {
++ writew(*(u16 *)addr, port);
++ addr += 2;
++ }
++ __ide_flush_dcache_range(start, count * 2);
++}
++
++static inline void __ide_mm_outsl(unsigned long port, const void *addr,
++ u32 count)
++{
++ unsigned long start = (unsigned long) addr;
++
++ while (count--) {
++ writel(*(u32 *)addr, port);
++ addr += 4;
++ }
++ __ide_flush_dcache_range(start, count * 4);
++}
+
+ #endif /* __KERNEL__ */
+
+diff -Nur linux-2.4.32-rc1/include/asm-mips64/io.h linux-2.4.32-rc1.mips/include/asm-mips64/io.h
+--- linux-2.4.32-rc1/include/asm-mips64/io.h 2004-02-18 14:36:32.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips64/io.h 2005-04-19 14:24:53.000000000 +0200
+@@ -414,7 +414,8 @@
+ return __ioswab32(__val);
+ }
+
+-static inline void __outsb(unsigned long port, void *addr, unsigned int count)
++static inline void __outsb(unsigned long port, const void *addr,
++ unsigned int count)
+ {
+ while (count--) {
+ outb(*(u8 *)addr, port);
+@@ -430,7 +431,8 @@
+ }
+ }
+
+-static inline void __outsw(unsigned long port, void *addr, unsigned int count)
++static inline void __outsw(unsigned long port, const void *addr,
++ unsigned int count)
+ {
+ while (count--) {
+ outw(*(u16 *)addr, port);
+@@ -446,7 +448,8 @@
+ }
+ }
+
+-static inline void __outsl(unsigned long port, void *addr, unsigned int count)
++static inline void __outsl(unsigned long port, const void *addr,
++ unsigned int count)
+ {
+ while (count--) {
+ outl(*(u32 *)addr, port);
+diff -Nur linux-2.4.32-rc1/include/asm-mips64/mipsregs.h linux-2.4.32-rc1.mips/include/asm-mips64/mipsregs.h
+--- linux-2.4.32-rc1/include/asm-mips64/mipsregs.h 2005-01-19 15:10:12.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips64/mipsregs.h 2005-02-06 22:24:22.000000000 +0100
+@@ -757,10 +757,18 @@
+ #define read_c0_config1() __read_32bit_c0_register($16, 1)
+ #define read_c0_config2() __read_32bit_c0_register($16, 2)
+ #define read_c0_config3() __read_32bit_c0_register($16, 3)
++#define read_c0_config4() __read_32bit_c0_register($16, 4)
++#define read_c0_config5() __read_32bit_c0_register($16, 5)
++#define read_c0_config6() __read_32bit_c0_register($16, 6)
++#define read_c0_config7() __read_32bit_c0_register($16, 7)
+ #define write_c0_config(val) __write_32bit_c0_register($16, 0, val)
+ #define write_c0_config1(val) __write_32bit_c0_register($16, 1, val)
+ #define write_c0_config2(val) __write_32bit_c0_register($16, 2, val)
+ #define write_c0_config3(val) __write_32bit_c0_register($16, 3, val)
++#define write_c0_config4(val) __write_32bit_c0_register($16, 4, val)
++#define write_c0_config5(val) __write_32bit_c0_register($16, 5, val)
++#define write_c0_config6(val) __write_32bit_c0_register($16, 6, val)
++#define write_c0_config7(val) __write_32bit_c0_register($16, 7, val)
+
+ /*
+ * The WatchLo register. There may be upto 8 of them.
+@@ -856,42 +864,34 @@
+ */
+ static inline void tlb_probe(void)
+ {
+- rm9000_tlb_hazard();
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ "tlbp\n\t"
+ ".set reorder");
+- rm9000_tlb_hazard();
+ }
+
+ static inline void tlb_read(void)
+ {
+- rm9000_tlb_hazard();
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ "tlbr\n\t"
+ ".set reorder");
+- rm9000_tlb_hazard();
+ }
+
+ static inline void tlb_write_indexed(void)
+ {
+- rm9000_tlb_hazard();
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ "tlbwi\n\t"
+ ".set reorder");
+- rm9000_tlb_hazard();
+ }
+
+ static inline void tlb_write_random(void)
+ {
+- rm9000_tlb_hazard();
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ "tlbwr\n\t"
+ ".set reorder");
+- rm9000_tlb_hazard();
+ }
+
+ /*
+diff -Nur linux-2.4.32-rc1/include/asm-mips64/reg.h linux-2.4.32-rc1.mips/include/asm-mips64/reg.h
+--- linux-2.4.32-rc1/include/asm-mips64/reg.h 2003-08-25 13:44:44.000000000 +0200
++++ linux-2.4.32-rc1.mips/include/asm-mips64/reg.h 2005-04-14 12:41:44.000000000 +0200
+@@ -46,6 +46,9 @@
+ /*
+ * k0/k1 unsaved
+ */
++#define EF_REG26 26
++#define EF_REG27 27
++
+ #define EF_REG28 28
+ #define EF_REG29 29
+ #define EF_REG30 30
+diff -Nur linux-2.4.32-rc1/include/asm-mips64/sgi/hpc3.h linux-2.4.32-rc1.mips/include/asm-mips64/sgi/hpc3.h
+--- linux-2.4.32-rc1/include/asm-mips64/sgi/hpc3.h 2003-08-25 13:44:44.000000000 +0200
++++ linux-2.4.32-rc1.mips/include/asm-mips64/sgi/hpc3.h 2005-09-23 16:35:27.000000000 +0200
+@@ -128,26 +128,26 @@
+ volatile u32 rx_gfptr; /* current GIO fifo ptr */
+ volatile u32 rx_dfptr; /* current device fifo ptr */
+ u32 _unused1; /* padding */
+- volatile u32 rx_reset; /* reset register */
+-#define HPC3_ERXRST_CRESET 0x1 /* Reset dma channel and external controller */
+-#define HPC3_ERXRST_CLRIRQ 0x2 /* Clear channel interrupt */
+-#define HPC3_ERXRST_LBACK 0x4 /* Enable diagnostic loopback mode of Seeq8003 */
+-
+- volatile u32 rx_dconfig; /* DMA configuration register */
+-#define HPC3_ERXDCFG_D1 0x0000f /* Cycles to spend in D1 state for PIO */
+-#define HPC3_ERXDCFG_D2 0x000f0 /* Cycles to spend in D2 state for PIO */
+-#define HPC3_ERXDCFG_D3 0x00f00 /* Cycles to spend in D3 state for PIO */
+-#define HPC3_ERXDCFG_WCTRL 0x01000 /* Enable writes of desc into ex ctrl port */
+-#define HPC3_ERXDCFG_FRXDC 0x02000 /* Clear eop stat bits upon rxdc, hw seeq fix */
+-#define HPC3_ERXDCFG_FEOP 0x04000 /* Bad packet marker timeout enable */
+-#define HPC3_ERXDCFG_FIRQ 0x08000 /* Another bad packet timeout enable */
+-#define HPC3_ERXDCFG_PTO 0x30000 /* Programmed timeout value for above two */
+-
+- volatile u32 rx_pconfig; /* PIO configuration register */
+-#define HPC3_ERXPCFG_P1 0x000f /* Cycles to spend in P1 state for PIO */
+-#define HPC3_ERXPCFG_P2 0x00f0 /* Cycles to spend in P2 state for PIO */
+-#define HPC3_ERXPCFG_P3 0x0f00 /* Cycles to spend in P3 state for PIO */
+-#define HPC3_ERXPCFG_TST 0x1000 /* Diagnistic ram test feature bit */
++ volatile u32 reset; /* reset register */
++#define HPC3_ERST_CRESET 0x1 /* Reset dma channel and external controller */
++#define HPC3_ERST_CLRIRQ 0x2 /* Clear channel interrupt */
++#define HPC3_ERST_LBACK 0x4 /* Enable diagnostic loopback mode of Seeq8003 */
++
++ volatile u32 dconfig; /* DMA configuration register */
++#define HPC3_EDCFG_D1 0x0000f /* Cycles to spend in D1 state for PIO */
++#define HPC3_EDCFG_D2 0x000f0 /* Cycles to spend in D2 state for PIO */
++#define HPC3_EDCFG_D3 0x00f00 /* Cycles to spend in D3 state for PIO */
++#define HPC3_EDCFG_WCTRL 0x01000 /* Enable writes of desc into ex ctrl port */
++#define HPC3_EDCFG_FRXDC 0x02000 /* Clear eop stat bits upon rxdc, hw seeq fix */
++#define HPC3_EDCFG_FEOP 0x04000 /* Bad packet marker timeout enable */
++#define HPC3_EDCFG_FIRQ 0x08000 /* Another bad packet timeout enable */
++#define HPC3_EDCFG_PTO 0x30000 /* Programmed timeout value for above two */
++
++ volatile u32 pconfig; /* PIO configuration register */
++#define HPC3_EPCFG_P1 0x000f /* Cycles to spend in P1 state for PIO */
++#define HPC3_EPCFG_P2 0x00f0 /* Cycles to spend in P2 state for PIO */
++#define HPC3_EPCFG_P3 0x0f00 /* Cycles to spend in P3 state for PIO */
++#define HPC3_EPCFG_TST 0x1000 /* Diagnistic ram test feature bit */
+
+ u32 _unused2[0x1000/4 - 8]; /* padding */
+
+@@ -221,7 +221,7 @@
+ #define HPC3_BESTAT_PIDMASK 0x3f700 /* DMA channel parity identifier */
+
+ u32 _unused1[0x14000/4 - 5]; /* padding */
+-
++
+ /* Now direct PIO per-HPC3 peripheral access to external regs. */
+ volatile u32 scsi0_ext[256]; /* SCSI channel 0 external regs */
+ u32 _unused2[0x7c00/4];
+@@ -304,7 +304,7 @@
+ volatile u32 bbram[8192-50-14]; /* Battery backed ram */
+ };
+
+-/*
++/*
+ * It is possible to have two HPC3's within the address space on
+ * one machine, though only having one is more likely on an Indy.
+ */
+diff -Nur linux-2.4.32-rc1/include/asm-mips64/sn/nmi.h linux-2.4.32-rc1.mips/include/asm-mips64/sn/nmi.h
+--- linux-2.4.32-rc1/include/asm-mips64/sn/nmi.h 2002-11-29 00:53:15.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips64/sn/nmi.h 2002-08-06 01:53:40.000000000 +0200
+@@ -8,7 +8,7 @@
+ #ifndef __ASM_SN_NMI_H
+ #define __ASM_SN_NMI_H
+
+-#ident "$Revision: 1.2.4.2 $"
++#ident "$Revision: 1.2.4.1 $"
+
+ #include <asm/sn/addrs.h>
+
+diff -Nur linux-2.4.32-rc1/include/asm-mips64/unistd.h linux-2.4.32-rc1.mips/include/asm-mips64/unistd.h
+--- linux-2.4.32-rc1/include/asm-mips64/unistd.h 2005-01-19 15:10:12.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-mips64/unistd.h 2004-11-24 21:30:06.000000000 +0100
+@@ -760,7 +760,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ /*
+@@ -788,7 +788,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ #define _syscall2(type,name,atype,a,btype,b) \
+@@ -813,7 +813,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ #define _syscall3(type,name,atype,a,btype,b,ctype,c) \
+@@ -839,7 +839,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ #define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \
+@@ -865,7 +865,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ #if (_MIPS_SIM == _MIPS_SIM_ABI32)
+@@ -902,7 +902,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ #define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \
+@@ -935,7 +935,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ #endif /* (_MIPS_SIM == _MIPS_SIM_ABI32) */
+@@ -966,7 +966,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ #define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \
+@@ -995,7 +995,7 @@
+ if (__a3 == 0) \
+ return (type) __v0; \
+ errno = __v0; \
+- return -1; \
++ return (type)-1; \
+ }
+
+ #endif /* (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) */
+diff -Nur linux-2.4.32-rc1/include/asm-ppc/param.h linux-2.4.32-rc1.mips/include/asm-ppc/param.h
+--- linux-2.4.32-rc1/include/asm-ppc/param.h 2003-06-13 16:51:38.000000000 +0200
++++ linux-2.4.32-rc1.mips/include/asm-ppc/param.h 2003-07-05 05:23:46.000000000 +0200
+@@ -3,6 +3,9 @@
+
+ #ifndef HZ
+ #define HZ 100
++#ifdef __KERNEL__
++#define hz_to_std(a) (a)
++#endif
+ #endif
+
+ #define EXEC_PAGESIZE 4096
+diff -Nur linux-2.4.32-rc1/include/asm-s390/param.h linux-2.4.32-rc1.mips/include/asm-s390/param.h
+--- linux-2.4.32-rc1/include/asm-s390/param.h 2001-02-13 23:13:44.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-s390/param.h 2001-03-09 21:34:48.000000000 +0100
+@@ -11,6 +11,9 @@
+
+ #ifndef HZ
+ #define HZ 100
++#ifdef __KERNEL__
++#define hz_to_std(a) (a)
++#endif
+ #endif
+
+ #define EXEC_PAGESIZE 4096
+diff -Nur linux-2.4.32-rc1/include/asm-sh/param.h linux-2.4.32-rc1.mips/include/asm-sh/param.h
+--- linux-2.4.32-rc1/include/asm-sh/param.h 2001-01-04 22:19:13.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-sh/param.h 2001-01-11 05:02:45.000000000 +0100
+@@ -3,6 +3,9 @@
+
+ #ifndef HZ
+ #define HZ 100
++#ifdef __KERNEL__
++#define hz_to_std(a) (a)
++#endif
+ #endif
+
+ #define EXEC_PAGESIZE 4096
+diff -Nur linux-2.4.32-rc1/include/asm-sparc/param.h linux-2.4.32-rc1.mips/include/asm-sparc/param.h
+--- linux-2.4.32-rc1/include/asm-sparc/param.h 2000-10-30 23:34:12.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-sparc/param.h 2000-11-23 03:00:56.000000000 +0100
+@@ -4,6 +4,9 @@
+
+ #ifndef HZ
+ #define HZ 100
++#ifdef __KERNEL__
++#define hz_to_std(a) (a)
++#endif
+ #endif
+
+ #define EXEC_PAGESIZE 8192 /* Thanks for sun4's we carry baggage... */
+diff -Nur linux-2.4.32-rc1/include/asm-sparc64/param.h linux-2.4.32-rc1.mips/include/asm-sparc64/param.h
+--- linux-2.4.32-rc1/include/asm-sparc64/param.h 2000-10-30 23:34:12.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/asm-sparc64/param.h 2000-11-23 03:00:56.000000000 +0100
+@@ -4,6 +4,9 @@
+
+ #ifndef HZ
+ #define HZ 100
++#ifdef __KERNEL__
++#define hz_to_std(a) (a)
++#endif
+ #endif
+
+ #define EXEC_PAGESIZE 8192 /* Thanks for sun4's we carry baggage... */
+diff -Nur linux-2.4.32-rc1/include/linux/i2c-algo-au1550.h linux-2.4.32-rc1.mips/include/linux/i2c-algo-au1550.h
+--- linux-2.4.32-rc1/include/linux/i2c-algo-au1550.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/linux/i2c-algo-au1550.h 2004-07-07 02:38:02.000000000 +0200
+@@ -0,0 +1,31 @@
++/*
++ * Copyright (C) 2004 Embedded Edge, LLC <dan@embeddededge.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., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef I2C_ALGO_AU1550_H
++#define I2C_ALGO_AU1550_H 1
++
++struct i2c_algo_au1550_data {
++ u32 psc_base;
++ int xfer_timeout;
++ int ack_timeout;
++};
++
++int i2c_au1550_add_bus(struct i2c_adapter *);
++int i2c_au1550_del_bus(struct i2c_adapter *);
++
++#endif /* I2C_ALGO_AU1550_H */
+diff -Nur linux-2.4.32-rc1/include/linux/i2c-id.h linux-2.4.32-rc1.mips/include/linux/i2c-id.h
+--- linux-2.4.32-rc1/include/linux/i2c-id.h 2004-02-18 14:36:32.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/linux/i2c-id.h 2004-07-07 02:38:02.000000000 +0200
+@@ -156,6 +156,8 @@
+
+ #define I2C_ALGO_SGI 0x130000 /* SGI algorithm */
+
++#define I2C_ALGO_AU1550 0x140000 /* Alchemy Au1550 PSC */
++
+ #define I2C_ALGO_EXP 0x800000 /* experimental */
+
+ #define I2C_ALGO_MASK 0xff0000 /* Mask for algorithms */
+@@ -204,6 +206,9 @@
+ #define I2C_HW_SGI_VINO 0x00
+ #define I2C_HW_SGI_MACE 0x01
+
++/* --- Au1550 PSC adapters */
++#define I2C_HW_AU1550_PSC 0x00
++
+ /* --- SMBus only adapters */
+ #define I2C_HW_SMBUS_PIIX4 0x00
+ #define I2C_HW_SMBUS_ALI15X3 0x01
+diff -Nur linux-2.4.32-rc1/include/linux/sched.h linux-2.4.32-rc1.mips/include/linux/sched.h
+--- linux-2.4.32-rc1/include/linux/sched.h 2005-01-19 15:10:12.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/linux/sched.h 2004-11-29 18:47:18.000000000 +0100
+@@ -617,6 +617,10 @@
+ extern int in_group_p(gid_t);
+ extern int in_egroup_p(gid_t);
+
++extern ATTRIB_NORET void cpu_idle(void);
++
++extern void release_task(struct task_struct * p);
++
+ extern void proc_caches_init(void);
+ extern void flush_signals(struct task_struct *);
+ extern void flush_signal_handlers(struct task_struct *);
+diff -Nur linux-2.4.32-rc1/include/linux/serial.h linux-2.4.32-rc1.mips/include/linux/serial.h
+--- linux-2.4.32-rc1/include/linux/serial.h 2002-08-03 02:39:45.000000000 +0200
++++ linux-2.4.32-rc1.mips/include/linux/serial.h 2004-07-31 02:17:57.000000000 +0200
+@@ -75,7 +75,8 @@
+ #define PORT_16654 11
+ #define PORT_16850 12
+ #define PORT_RSA 13 /* RSA-DV II/S card */
+-#define PORT_MAX 13
++#define PORT_SB1250 14
++#define PORT_MAX 14
+
+ #define SERIAL_IO_PORT 0
+ #define SERIAL_IO_HUB6 1
+diff -Nur linux-2.4.32-rc1/include/linux/swap.h linux-2.4.32-rc1.mips/include/linux/swap.h
+--- linux-2.4.32-rc1/include/linux/swap.h 2005-01-19 15:10:12.000000000 +0100
++++ linux-2.4.32-rc1.mips/include/linux/swap.h 2004-11-29 18:47:18.000000000 +0100
+@@ -1,6 +1,12 @@
+ #ifndef _LINUX_SWAP_H
+ #define _LINUX_SWAP_H
+
++#include <linux/config.h>
++
++#define MAX_SWAPFILES 32
++
++#ifdef __KERNEL__
++
+ #include <linux/spinlock.h>
+ #include <asm/page.h>
+
+@@ -8,8 +14,6 @@
+ #define SWAP_FLAG_PRIO_MASK 0x7fff
+ #define SWAP_FLAG_PRIO_SHIFT 0
+
+-#define MAX_SWAPFILES 32
+-
+ /*
+ * Magic header for a swap area. The first part of the union is
+ * what the swap magic looks like for the old (limited to 128MB)
+@@ -39,8 +43,6 @@
+ } info;
+ };
+
+-#ifdef __KERNEL__
+-
+ /*
+ * Max bad pages in the new format..
+ */
+diff -Nur linux-2.4.32-rc1/include/video/newport.h linux-2.4.32-rc1.mips/include/video/newport.h
+--- linux-2.4.32-rc1/include/video/newport.h 2001-04-12 21:20:31.000000000 +0200
++++ linux-2.4.32-rc1.mips/include/video/newport.h 2004-09-23 15:32:29.000000000 +0200
+@@ -291,8 +291,6 @@
+ unsigned int _unused2[0x1ef];
+ struct newport_cregs cgo;
+ };
+-extern struct newport_regs *npregs;
+-
+
+ typedef struct {
+ unsigned int drawmode1;
+@@ -450,38 +448,26 @@
+
+ /* Miscellaneous NEWPORT routines. */
+ #define BUSY_TIMEOUT 100000
+-static __inline__ int newport_wait(void)
++static __inline__ int newport_wait(struct newport_regs *regs)
+ {
+- int i = 0;
++ int t = BUSY_TIMEOUT;
+
+- while(i < BUSY_TIMEOUT)
+- if(!(npregs->cset.status & NPORT_STAT_GBUSY))
++ while (t--)
++ if (!(regs->cset.status & NPORT_STAT_GBUSY))
+ break;
+- if(i == BUSY_TIMEOUT)
+- return 1;
+- return 0;
++ return !t;
+ }
+
+-static __inline__ int newport_bfwait(void)
++static __inline__ int newport_bfwait(struct newport_regs *regs)
+ {
+- int i = 0;
++ int t = BUSY_TIMEOUT;
+
+- while(i < BUSY_TIMEOUT)
+- if(!(npregs->cset.status & NPORT_STAT_BBUSY))
++ while (t--)
++ if(!(regs->cset.status & NPORT_STAT_BBUSY))
+ break;
+- if(i == BUSY_TIMEOUT)
+- return 1;
+- return 0;
++ return !t;
+ }
+
+-/* newport.c and cons_newport.c routines */
+-extern struct graphics_ops *newport_probe (int, const char **);
+-
+-void newport_save (void *);
+-void newport_restore (void *);
+-void newport_reset (void);
+-int newport_ioctl (int card, int cmd, unsigned long arg);
+-
+ /*
+ * DCBMODE register defines:
+ */
+@@ -564,7 +550,7 @@
+ {
+ rex->set.dcbmode = DCB_XMAP0 | XM9_CRS_FIFO_AVAIL |
+ DCB_DATAWIDTH_1 | R_DCB_XMAP9_PROTOCOL;
+- newport_bfwait ();
++ newport_bfwait (rex);
+
+ while ((rex->set.dcbdata0.bybytes.b3 & 3) != XM9_FIFO_EMPTY)
+ ;
+diff -Nur linux-2.4.32-rc1/init/main.c linux-2.4.32-rc1.mips/init/main.c
+--- linux-2.4.32-rc1/init/main.c 2004-11-17 12:54:22.000000000 +0100
++++ linux-2.4.32-rc1.mips/init/main.c 2004-11-19 01:28:52.000000000 +0100
+@@ -296,7 +296,6 @@
+
+
+ extern void setup_arch(char **);
+-extern void cpu_idle(void);
+
+ unsigned long wait_init_idle;
+
+diff -Nur linux-2.4.32-rc1/kernel/exit.c linux-2.4.32-rc1.mips/kernel/exit.c
+--- linux-2.4.32-rc1/kernel/exit.c 2002-11-29 00:53:15.000000000 +0100
++++ linux-2.4.32-rc1.mips/kernel/exit.c 2003-01-11 18:53:18.000000000 +0100
+@@ -26,7 +26,7 @@
+
+ int getrusage(struct task_struct *, int, struct rusage *);
+
+-static void release_task(struct task_struct * p)
++void release_task(struct task_struct * p)
+ {
+ if (p != current) {
+ #ifdef CONFIG_SMP
+diff -Nur linux-2.4.32-rc1/kernel/signal.c linux-2.4.32-rc1.mips/kernel/signal.c
+--- linux-2.4.32-rc1/kernel/signal.c 2004-02-18 14:36:32.000000000 +0100
++++ linux-2.4.32-rc1.mips/kernel/signal.c 2004-01-20 16:10:34.000000000 +0100
+@@ -14,6 +14,7 @@
+ #include <linux/init.h>
+ #include <linux/sched.h>
+
++#include <asm/param.h>
+ #include <asm/uaccess.h>
+
+ /*
+@@ -28,6 +29,14 @@
+ #define SIG_SLAB_DEBUG 0
+ #endif
+
++#define DEBUG_SIG 0
++
++#if DEBUG_SIG
++#define SIG_SLAB_DEBUG (SLAB_DEBUG_FREE | SLAB_RED_ZONE /* | SLAB_POISON */)
++#else
++#define SIG_SLAB_DEBUG 0
++#endif
++
+ static kmem_cache_t *sigqueue_cachep;
+
+ atomic_t nr_queued_signals;
+@@ -270,6 +279,11 @@
+ signal_pending(current));
+ #endif
+
++#if DEBUG_SIG
++printk("SIG dequeue (%s:%d): %d ", current->comm, current->pid,
++ signal_pending(current));
++#endif
++
+ sig = next_signal(current, mask);
+ if (sig) {
+ if (current->notifier) {
+@@ -293,6 +307,10 @@
+ printk(" %d -> %d\n", signal_pending(current), sig);
+ #endif
+
++#if DEBUG_SIG
++printk(" %d -> %d\n", signal_pending(current), sig);
++#endif
++
+ return sig;
+ }
+
+@@ -540,6 +558,11 @@
+ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
+ #endif
+
++
++#if DEBUG_SIG
++printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
++#endif
++
+ ret = -EINVAL;
+ if (sig < 0 || sig > _NSIG)
+ goto out_nolock;
+@@ -778,8 +801,8 @@
+ info.si_uid = tsk->uid;
+
+ /* FIXME: find out whether or not this is supposed to be c*time. */
+- info.si_utime = tsk->times.tms_utime;
+- info.si_stime = tsk->times.tms_stime;
++ info.si_utime = hz_to_std(tsk->times.tms_utime);
++ info.si_stime = hz_to_std(tsk->times.tms_stime);
+
+ status = tsk->exit_code & 0x7f;
+ why = SI_KERNEL; /* shouldn't happen */
+diff -Nur linux-2.4.32-rc1/kernel/sys.c linux-2.4.32-rc1.mips/kernel/sys.c
+--- linux-2.4.32-rc1/kernel/sys.c 2003-11-28 19:26:21.000000000 +0100
++++ linux-2.4.32-rc1.mips/kernel/sys.c 2003-11-17 02:07:47.000000000 +0100
+@@ -801,16 +801,23 @@
+
+ asmlinkage long sys_times(struct tms * tbuf)
+ {
++ struct tms temp;
++
+ /*
+ * In the SMP world we might just be unlucky and have one of
+ * the times increment as we use it. Since the value is an
+ * atomically safe type this is just fine. Conceptually its
+ * as if the syscall took an instant longer to occur.
+ */
+- if (tbuf)
+- if (copy_to_user(tbuf, &current->times, sizeof(struct tms)))
++ if (tbuf) {
++ temp.tms_utime = hz_to_std(current->times.tms_utime);
++ temp.tms_stime = hz_to_std(current->times.tms_stime);
++ temp.tms_cutime = hz_to_std(current->times.tms_cutime);
++ temp.tms_cstime = hz_to_std(current->times.tms_cstime);
++ if (copy_to_user(tbuf, &temp, sizeof(struct tms)))
+ return -EFAULT;
+- return jiffies;
++ }
++ return hz_to_std(jiffies);
+ }
+
+ /*
+diff -Nur linux-2.4.32-rc1/lib/Makefile linux-2.4.32-rc1.mips/lib/Makefile
+--- linux-2.4.32-rc1/lib/Makefile 2004-04-14 15:05:40.000000000 +0200
++++ linux-2.4.32-rc1.mips/lib/Makefile 2004-04-16 05:14:21.000000000 +0200
+@@ -27,6 +27,7 @@
+ subdir-$(CONFIG_ZLIB_INFLATE) += zlib_inflate
+ subdir-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate
+
++-include $(TOPDIR)/arch/$(ARCH)/Makefile.lib
+ include $(TOPDIR)/drivers/net/Makefile.lib
+ include $(TOPDIR)/drivers/usb/Makefile.lib
+ include $(TOPDIR)/drivers/bluetooth/Makefile.lib
+diff -Nur linux-2.4.32-rc1/Makefile linux-2.4.32-rc1.mips/Makefile
+--- linux-2.4.32-rc1/Makefile 2005-10-24 11:33:30.000000000 +0200
++++ linux-2.4.32-rc1.mips/Makefile 2005-09-23 22:41:15.000000000 +0200
+@@ -462,10 +462,11 @@
+ $(MAKE) -C Documentation/DocBook mrproper
+
+ distclean: mrproper
+- rm -f core `find . \( -not -type d \) -and \
+- \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
+- -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
+- -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -type f -print` TAGS tags
++ find . \( -not -type d \) -and \
++ \( -name core -o -name '*.orig' -o -name '*.rej' \
++ -o -name '*~' -o -name '*.bak' -o -name '#*#' \
++ -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \
++ -o -name TAGS -o -name tags \) -print | env -i xargs rm -f
+
+ backup: mrproper
+ cd .. && tar cf - linux/ | gzip -9 > backup.gz
+@@ -492,7 +493,7 @@
+ $(MAKE) -C Documentation/DocBook man
+
+ sums:
+- find . -type f -print | sort | xargs sum > .SUMS
++ find . -type f -print | sort | env -i xargs sum > .SUMS
+
+ dep-files: scripts/mkdep archdep include/linux/version.h
+ rm -f .depend .hdepend
diff --git a/target/linux/generic-2.4/patches/001-squashfs.patch b/target/linux/generic-2.4/patches/001-squashfs.patch
new file mode 100644
index 0000000000..b2d9cf3707
--- /dev/null
+++ b/target/linux/generic-2.4/patches/001-squashfs.patch
@@ -0,0 +1,4070 @@
+diff --new-file -urp linux-2.4.32/fs/Config.in linux-2.4.32-squashfs3.0/fs/Config.in
+--- linux-2.4.32/fs/Config.in 2004-11-17 11:54:21.000000000 +0000
++++ linux-2.4.32-squashfs3.0/fs/Config.in 2006-03-07 21:12:36.000000000 +0000
+@@ -51,6 +51,14 @@ if [ "$CONFIG_JFFS2_FS" = "y" -o "$CONFI
+ int 'JFFS2 debugging verbosity (0 = quiet, 2 = noisy)' CONFIG_JFFS2_FS_DEBUG 0
+ fi
+ tristate 'Compressed ROM file system support' CONFIG_CRAMFS
++tristate 'Squashed file system support' CONFIG_SQUASHFS
++if [ "$CONFIG_SQUASHFS" = "y" -o "$CONFIG_SQUASHFS" = "m" ] ; then
++bool 'Additional options for memory constrained systems ' CONFIG_SQUASHFS_EMBEDDED
++fi
++if [ "$CONFIG_SQUASHFS_EMBEDDED" = "y" ] ; then
++int 'Number of fragments cached' CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE 3
++bool 'Use Vmalloc rather than Kmalloc' CONFIG_SQUASHFS_VMALLOC
++fi
+ bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS
+ define_bool CONFIG_RAMFS y
+
+diff --new-file -urp linux-2.4.32/fs/Makefile linux-2.4.32-squashfs3.0/fs/Makefile
+--- linux-2.4.32/fs/Makefile 2004-02-18 13:36:31.000000000 +0000
++++ linux-2.4.32-squashfs3.0/fs/Makefile 2006-03-07 21:12:36.000000000 +0000
+@@ -65,6 +65,7 @@ subdir-$(CONFIG_REISERFS_FS) += reiserfs
+ subdir-$(CONFIG_DEVPTS_FS) += devpts
+ subdir-$(CONFIG_SUN_OPENPROMFS) += openpromfs
+ subdir-$(CONFIG_BEFS_FS) += befs
++subdir-$(CONFIG_SQUASHFS) += squashfs
+ subdir-$(CONFIG_JFS_FS) += jfs
+ subdir-$(CONFIG_XFS_FS) += xfs
+
+diff --new-file -urp linux-2.4.32/fs/squashfs/inode.c linux-2.4.32-squashfs3.0/fs/squashfs/inode.c
+--- linux-2.4.32/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-squashfs3.0/fs/squashfs/inode.c 2006-03-07 21:12:36.000000000 +0000
+@@ -0,0 +1,2028 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * inode.c
++ */
++
++#include <linux/types.h>
++#include <linux/squashfs_fs.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/fs.h>
++#include <linux/smp_lock.h>
++#include <linux/locks.h>
++#include <linux/init.h>
++#include <linux/dcache.h>
++#include <linux/wait.h>
++#include <linux/zlib.h>
++#include <linux/blkdev.h>
++#include <linux/vmalloc.h>
++#include <asm/uaccess.h>
++#include <asm/semaphore.h>
++
++#include "squashfs.h"
++
++static struct super_block *squashfs_read_super(struct super_block *, void *, int);
++static void squashfs_put_super(struct super_block *);
++static int squashfs_statfs(struct super_block *, struct statfs *);
++static int squashfs_symlink_readpage(struct file *file, struct page *page);
++static int squashfs_readpage(struct file *file, struct page *page);
++static int squashfs_readpage4K(struct file *file, struct page *page);
++static int squashfs_readdir(struct file *, void *, filldir_t);
++static struct dentry *squashfs_lookup(struct inode *, struct dentry *);
++static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode);
++static long long read_blocklist(struct inode *inode, int index,
++ int readahead_blks, char *block_list,
++ unsigned short **block_p, unsigned int *bsize);
++
++static z_stream stream;
++
++static DECLARE_FSTYPE_DEV(squashfs_fs_type, "squashfs", squashfs_read_super);
++
++static unsigned char squashfs_filetype_table[] = {
++ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
++};
++
++static struct super_operations squashfs_ops = {
++ .statfs = squashfs_statfs,
++ .put_super = squashfs_put_super,
++};
++
++SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = {
++ .readpage = squashfs_symlink_readpage
++};
++
++SQSH_EXTERN struct address_space_operations squashfs_aops = {
++ .readpage = squashfs_readpage
++};
++
++SQSH_EXTERN struct address_space_operations squashfs_aops_4K = {
++ .readpage = squashfs_readpage4K
++};
++
++static struct file_operations squashfs_dir_ops = {
++ .read = generic_read_dir,
++ .readdir = squashfs_readdir
++};
++
++static struct inode_operations squashfs_dir_inode_ops = {
++ .lookup = squashfs_lookup
++};
++
++static struct buffer_head *get_block_length(struct super_block *s,
++ int *cur_index, int *offset, int *c_byte)
++{
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ unsigned short temp;
++ struct buffer_head *bh;
++
++ if (!(bh = sb_bread(s, *cur_index)))
++ goto out;
++
++ if (msblk->devblksize - *offset == 1) {
++ if (msblk->swap)
++ ((unsigned char *) &temp)[1] = *((unsigned char *)
++ (bh->b_data + *offset));
++ else
++ ((unsigned char *) &temp)[0] = *((unsigned char *)
++ (bh->b_data + *offset));
++ brelse(bh);
++ if (!(bh = sb_bread(s, ++(*cur_index))))
++ goto out;
++ if (msblk->swap)
++ ((unsigned char *) &temp)[0] = *((unsigned char *)
++ bh->b_data);
++ else
++ ((unsigned char *) &temp)[1] = *((unsigned char *)
++ bh->b_data);
++ *c_byte = temp;
++ *offset = 1;
++ } else {
++ if (msblk->swap) {
++ ((unsigned char *) &temp)[1] = *((unsigned char *)
++ (bh->b_data + *offset));
++ ((unsigned char *) &temp)[0] = *((unsigned char *)
++ (bh->b_data + *offset + 1));
++ } else {
++ ((unsigned char *) &temp)[0] = *((unsigned char *)
++ (bh->b_data + *offset));
++ ((unsigned char *) &temp)[1] = *((unsigned char *)
++ (bh->b_data + *offset + 1));
++ }
++ *c_byte = temp;
++ *offset += 2;
++ }
++
++ if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {
++ if (*offset == msblk->devblksize) {
++ brelse(bh);
++ if (!(bh = sb_bread(s, ++(*cur_index))))
++ goto out;
++ *offset = 0;
++ }
++ if (*((unsigned char *) (bh->b_data + *offset)) !=
++ SQUASHFS_MARKER_BYTE) {
++ ERROR("Metadata block marker corrupt @ %x\n",
++ *cur_index);
++ brelse(bh);
++ goto out;
++ }
++ (*offset)++;
++ }
++ return bh;
++
++out:
++ return NULL;
++}
++
++
++SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,
++ long long index, unsigned int length,
++ long long *next_index)
++{
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>
++ msblk->devblksize_log2) + 2];
++ unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
++ unsigned int cur_index = index >> msblk->devblksize_log2;
++ int bytes, avail_bytes, b = 0, k;
++ char *c_buffer;
++ unsigned int compressed;
++ unsigned int c_byte = length;
++
++ if (c_byte) {
++ bytes = msblk->devblksize - offset;
++ compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);
++ c_buffer = compressed ? msblk->read_data : buffer;
++ c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
++
++ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
++ ? "" : "un", (unsigned int) c_byte);
++
++ if (!(bh[0] = sb_getblk(s, cur_index)))
++ goto block_release;
++
++ for (b = 1; bytes < c_byte; b++) {
++ if (!(bh[b] = sb_getblk(s, ++cur_index)))
++ goto block_release;
++ bytes += msblk->devblksize;
++ }
++ ll_rw_block(READ, b, bh);
++ } else {
++ if (!(bh[0] = get_block_length(s, &cur_index, &offset,
++ &c_byte)))
++ goto read_failure;
++
++ bytes = msblk->devblksize - offset;
++ compressed = SQUASHFS_COMPRESSED(c_byte);
++ c_buffer = compressed ? msblk->read_data : buffer;
++ c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
++
++ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
++ ? "" : "un", (unsigned int) c_byte);
++
++ for (b = 1; bytes < c_byte; b++) {
++ if (!(bh[b] = sb_getblk(s, ++cur_index)))
++ goto block_release;
++ bytes += msblk->devblksize;
++ }
++ ll_rw_block(READ, b - 1, bh + 1);
++ }
++
++ if (compressed)
++ down(&msblk->read_data_mutex);
++
++ for (bytes = 0, k = 0; k < b; k++) {
++ avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
++ msblk->devblksize - offset :
++ c_byte - bytes;
++ wait_on_buffer(bh[k]);
++ if (!buffer_uptodate(bh[k]))
++ goto block_release;
++ memcpy(c_buffer + bytes, bh[k]->b_data + offset, avail_bytes);
++ bytes += avail_bytes;
++ offset = 0;
++ brelse(bh[k]);
++ }
++
++ /*
++ * uncompress block
++ */
++ if (compressed) {
++ int zlib_err;
++
++ stream.next_in = c_buffer;
++ stream.avail_in = c_byte;
++ stream.next_out = buffer;
++ stream.avail_out = msblk->read_size;
++
++ if (((zlib_err = zlib_inflateInit(&stream)) != Z_OK) ||
++ ((zlib_err = zlib_inflate(&stream, Z_FINISH))
++ != Z_STREAM_END) || ((zlib_err =
++ zlib_inflateEnd(&stream)) != Z_OK)) {
++ ERROR("zlib_fs returned unexpected result 0x%x\n",
++ zlib_err);
++ bytes = 0;
++ } else
++ bytes = stream.total_out;
++
++ up(&msblk->read_data_mutex);
++ }
++
++ if (next_index)
++ *next_index = index + c_byte + (length ? 0 :
++ (SQUASHFS_CHECK_DATA(msblk->sblk.flags)
++ ? 3 : 2));
++ return bytes;
++
++block_release:
++ while (--b >= 0)
++ brelse(bh[b]);
++
++read_failure:
++ ERROR("sb_bread failed reading block 0x%x\n", cur_index);
++ return 0;
++}
++
++
++SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer,
++ long long block, unsigned int offset,
++ int length, long long *next_block,
++ unsigned int *next_offset)
++{
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ int n, i, bytes, return_length = length;
++ long long next_index;
++
++ TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);
++
++ while ( 1 ) {
++ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
++ if (msblk->block_cache[i].block == block)
++ break;
++
++ down(&msblk->block_cache_mutex);
++
++ if (i == SQUASHFS_CACHED_BLKS) {
++ /* read inode header block */
++ for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;
++ n ; n --, i = (i + 1) %
++ SQUASHFS_CACHED_BLKS)
++ if (msblk->block_cache[i].block !=
++ SQUASHFS_USED_BLK)
++ break;
++
++ if (n == 0) {
++ wait_queue_t wait;
++
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&msblk->waitq, &wait);
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ up(&msblk->block_cache_mutex);
++ schedule();
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&msblk->waitq, &wait);
++ continue;
++ }
++ msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
++
++ if (msblk->block_cache[i].block ==
++ SQUASHFS_INVALID_BLK) {
++ if (!(msblk->block_cache[i].data =
++ kmalloc(SQUASHFS_METADATA_SIZE,
++ GFP_KERNEL))) {
++ ERROR("Failed to allocate cache"
++ "block\n");
++ up(&msblk->block_cache_mutex);
++ goto out;
++ }
++ }
++
++ msblk->block_cache[i].block = SQUASHFS_USED_BLK;
++ up(&msblk->block_cache_mutex);
++
++ if (!(msblk->block_cache[i].length =
++ squashfs_read_data(s,
++ msblk->block_cache[i].data,
++ block, 0, &next_index))) {
++ ERROR("Unable to read cache block [%llx:%x]\n",
++ block, offset);
++ goto out;
++ }
++
++ down(&msblk->block_cache_mutex);
++ wake_up(&msblk->waitq);
++ msblk->block_cache[i].block = block;
++ msblk->block_cache[i].next_index = next_index;
++ TRACE("Read cache block [%llx:%x]\n", block, offset);
++ }
++
++ if (msblk->block_cache[i].block != block) {
++ up(&msblk->block_cache_mutex);
++ continue;
++ }
++
++ if ((bytes = msblk->block_cache[i].length - offset) >= length) {
++ if (buffer)
++ memcpy(buffer, msblk->block_cache[i].data +
++ offset, length);
++ if (msblk->block_cache[i].length - offset == length) {
++ *next_block = msblk->block_cache[i].next_index;
++ *next_offset = 0;
++ } else {
++ *next_block = block;
++ *next_offset = offset + length;
++ }
++ up(&msblk->block_cache_mutex);
++ goto finish;
++ } else {
++ if (buffer) {
++ memcpy(buffer, msblk->block_cache[i].data +
++ offset, bytes);
++ buffer += bytes;
++ }
++ block = msblk->block_cache[i].next_index;
++ up(&msblk->block_cache_mutex);
++ length -= bytes;
++ offset = 0;
++ }
++ }
++
++finish:
++ return return_length;
++out:
++ return 0;
++}
++
++
++static int get_fragment_location(struct super_block *s, unsigned int fragment,
++ long long *fragment_start_block,
++ unsigned int *fragment_size)
++{
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ long long start_block =
++ msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];
++ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
++ struct squashfs_fragment_entry fragment_entry;
++
++ if (msblk->swap) {
++ struct squashfs_fragment_entry sfragment_entry;
++
++ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
++ start_block, offset,
++ sizeof(sfragment_entry), &start_block,
++ &offset))
++ goto out;
++ SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);
++ } else
++ if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
++ start_block, offset,
++ sizeof(fragment_entry), &start_block,
++ &offset))
++ goto out;
++
++ *fragment_start_block = fragment_entry.start_block;
++ *fragment_size = fragment_entry.size;
++
++ return 1;
++
++out:
++ return 0;
++}
++
++
++SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct
++ squashfs_fragment_cache *fragment)
++{
++ down(&msblk->fragment_mutex);
++ fragment->locked --;
++ wake_up(&msblk->fragment_wait_queue);
++ up(&msblk->fragment_mutex);
++}
++
++
++SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block
++ *s, long long start_block,
++ int length)
++{
++ int i, n;
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++
++ while ( 1 ) {
++ down(&msblk->fragment_mutex);
++
++ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&
++ msblk->fragment[i].block != start_block; i++);
++
++ if (i == SQUASHFS_CACHED_FRAGMENTS) {
++ for (i = msblk->next_fragment, n =
++ SQUASHFS_CACHED_FRAGMENTS; n &&
++ msblk->fragment[i].locked; n--, i = (i + 1) %
++ SQUASHFS_CACHED_FRAGMENTS);
++
++ if (n == 0) {
++ wait_queue_t wait;
++
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&msblk->fragment_wait_queue,
++ &wait);
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ up(&msblk->fragment_mutex);
++ schedule();
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&msblk->fragment_wait_queue,
++ &wait);
++ continue;
++ }
++ msblk->next_fragment = (msblk->next_fragment + 1) %
++ SQUASHFS_CACHED_FRAGMENTS;
++
++ if (msblk->fragment[i].data == NULL)
++ if (!(msblk->fragment[i].data = SQUASHFS_ALLOC
++ (SQUASHFS_FILE_MAX_SIZE))) {
++ ERROR("Failed to allocate fragment "
++ "cache block\n");
++ up(&msblk->fragment_mutex);
++ goto out;
++ }
++
++ msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
++ msblk->fragment[i].locked = 1;
++ up(&msblk->fragment_mutex);
++
++ if (!(msblk->fragment[i].length = squashfs_read_data(s,
++ msblk->fragment[i].data,
++ start_block, length, NULL))) {
++ ERROR("Unable to read fragment cache block "
++ "[%llx]\n", start_block);
++ msblk->fragment[i].locked = 0;
++ goto out;
++ }
++
++ msblk->fragment[i].block = start_block;
++ TRACE("New fragment %d, start block %lld, locked %d\n",
++ i, msblk->fragment[i].block,
++ msblk->fragment[i].locked);
++ break;
++ }
++
++ msblk->fragment[i].locked++;
++ up(&msblk->fragment_mutex);
++ TRACE("Got fragment %d, start block %lld, locked %d\n", i,
++ msblk->fragment[i].block,
++ msblk->fragment[i].locked);
++ break;
++ }
++
++ return &msblk->fragment[i];
++
++out:
++ return NULL;
++}
++
++
++static struct inode *squashfs_new_inode(struct super_block *s,
++ struct squashfs_base_inode_header *inodeb)
++{
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ struct inode *i = new_inode(s);
++
++ if (i) {
++ i->i_ino = inodeb->inode_number;
++ i->i_mtime = inodeb->mtime;
++ i->i_atime = inodeb->mtime;
++ i->i_ctime = inodeb->mtime;
++ i->i_uid = msblk->uid[inodeb->uid];
++ i->i_mode = inodeb->mode;
++ i->i_size = 0;
++ if (inodeb->guid == SQUASHFS_GUIDS)
++ i->i_gid = i->i_uid;
++ else
++ i->i_gid = msblk->guid[inodeb->guid];
++ }
++
++ return i;
++}
++
++
++static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode)
++{
++ struct inode *i;
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long block = SQUASHFS_INODE_BLK(inode) +
++ sblk->inode_table_start;
++ unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
++ long long next_block;
++ unsigned int next_offset;
++ union squashfs_inode_header id, sid;
++ struct squashfs_base_inode_header *inodeb = &id.base,
++ *sinodeb = &sid.base;
++
++ TRACE("Entered squashfs_iget\n");
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
++ offset, sizeof(*sinodeb), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,
++ sizeof(*sinodeb));
++ } else
++ if (!squashfs_get_cached_block(s, (char *) inodeb, block,
++ offset, sizeof(*inodeb), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ switch(inodeb->inode_type) {
++ case SQUASHFS_FILE_TYPE: {
++ unsigned int frag_size;
++ long long frag_blk;
++ struct squashfs_reg_inode_header *inodep = &id.reg;
++ struct squashfs_reg_inode_header *sinodep = &sid.reg;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ frag_blk = SQUASHFS_INVALID_BLK;
++ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
++ !get_fragment_location(s,
++ inodep->fragment, &frag_blk, &frag_size))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb)) == NULL)
++ goto failed_read1;
++
++ i->i_nlink = 1;
++ i->i_size = inodep->file_size;
++ i->i_fop = &generic_ro_fops;
++ i->i_mode |= S_IFREG;
++ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
++ i->i_blksize = PAGE_CACHE_SIZE;
++ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
++ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
++ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++ if (sblk->block_size > 4096)
++ i->i_data.a_ops = &squashfs_aops;
++ else
++ i->i_data.a_ops = &squashfs_aops_4K;
++
++ TRACE("File inode %x:%x, start_block %llx, "
++ "block_list_start %llx, offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, next_block,
++ next_offset);
++ break;
++ }
++ case SQUASHFS_LREG_TYPE: {
++ unsigned int frag_size;
++ long long frag_blk;
++ struct squashfs_lreg_inode_header *inodep = &id.lreg;
++ struct squashfs_lreg_inode_header *sinodep = &sid.lreg;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ frag_blk = SQUASHFS_INVALID_BLK;
++ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
++ !get_fragment_location(s,
++ inodep->fragment, &frag_blk, &frag_size))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb)) == NULL)
++ goto failed_read1;
++
++ i->i_nlink = inodep->nlink;
++ i->i_size = inodep->file_size;
++ i->i_fop = &generic_ro_fops;
++ i->i_mode |= S_IFREG;
++ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
++ i->i_blksize = PAGE_CACHE_SIZE;
++ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
++ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
++ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++ if (sblk->block_size > 4096)
++ i->i_data.a_ops = &squashfs_aops;
++ else
++ i->i_data.a_ops = &squashfs_aops_4K;
++
++ TRACE("File inode %x:%x, start_block %llx, "
++ "block_list_start %llx, offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, next_block,
++ next_offset);
++ break;
++ }
++ case SQUASHFS_DIR_TYPE: {
++ struct squashfs_dir_inode_header *inodep = &id.dir;
++ struct squashfs_dir_inode_header *sinodep = &sid.dir;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb)) == NULL)
++ goto failed_read1;
++
++ i->i_nlink = inodep->nlink;
++ i->i_size = inodep->file_size;
++ i->i_op = &squashfs_dir_inode_ops;
++ i->i_fop = &squashfs_dir_ops;
++ i->i_mode |= S_IFDIR;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->offset = inodep->offset;
++ SQUASHFS_I(i)->u.s2.directory_index_count = 0;
++ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
++
++ TRACE("Directory inode %x:%x, start_block %x, offset "
++ "%x\n", SQUASHFS_INODE_BLK(inode),
++ offset, inodep->start_block,
++ inodep->offset);
++ break;
++ }
++ case SQUASHFS_LDIR_TYPE: {
++ struct squashfs_ldir_inode_header *inodep = &id.ldir;
++ struct squashfs_ldir_inode_header *sinodep = &sid.ldir;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,
++ sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb)) == NULL)
++ goto failed_read1;
++
++ i->i_nlink = inodep->nlink;
++ i->i_size = inodep->file_size;
++ i->i_op = &squashfs_dir_inode_ops;
++ i->i_fop = &squashfs_dir_ops;
++ i->i_mode |= S_IFDIR;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->offset = inodep->offset;
++ SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
++ SQUASHFS_I(i)->u.s2.directory_index_offset =
++ next_offset;
++ SQUASHFS_I(i)->u.s2.directory_index_count =
++ inodep->i_count;
++ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
++
++ TRACE("Long directory inode %x:%x, start_block %x, "
++ "offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, inodep->offset);
++ break;
++ }
++ case SQUASHFS_SYMLINK_TYPE: {
++ struct squashfs_symlink_inode_header *inodep =
++ &id.symlink;
++ struct squashfs_symlink_inode_header *sinodep =
++ &sid.symlink;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,
++ sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb)) == NULL)
++ goto failed_read1;
++
++ i->i_nlink = inodep->nlink;
++ i->i_size = inodep->symlink_size;
++ i->i_op = &page_symlink_inode_operations;
++ i->i_data.a_ops = &squashfs_symlink_aops;
++ i->i_mode |= S_IFLNK;
++ SQUASHFS_I(i)->start_block = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++
++ TRACE("Symbolic link inode %x:%x, start_block %llx, "
++ "offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ next_block, next_offset);
++ break;
++ }
++ case SQUASHFS_BLKDEV_TYPE:
++ case SQUASHFS_CHRDEV_TYPE: {
++ struct squashfs_dev_inode_header *inodep = &id.dev;
++ struct squashfs_dev_inode_header *sinodep = &sid.dev;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if ((i = squashfs_new_inode(s, inodeb)) == NULL)
++ goto failed_read1;
++
++ i->i_nlink = inodep->nlink;
++ i->i_mode |= (inodeb->inode_type ==
++ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
++ S_IFBLK;
++ init_special_inode(i, i->i_mode, inodep->rdev);
++
++ TRACE("Device inode %x:%x, rdev %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->rdev);
++ break;
++ }
++ case SQUASHFS_FIFO_TYPE:
++ case SQUASHFS_SOCKET_TYPE: {
++ struct squashfs_ipc_inode_header *inodep = &id.ipc;
++ struct squashfs_ipc_inode_header *sinodep = &sid.ipc;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if ((i = squashfs_new_inode(s, inodeb)) == NULL)
++ goto failed_read1;
++
++ i->i_nlink = inodep->nlink;
++ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
++ ? S_IFIFO : S_IFSOCK;
++ init_special_inode(i, i->i_mode, 0);
++ break;
++ }
++ default:
++ ERROR("Unknown inode type %d in squashfs_iget!\n",
++ inodeb->inode_type);
++ goto failed_read1;
++ }
++
++ insert_inode_hash(i);
++ return i;
++
++failed_read:
++ ERROR("Unable to read inode [%llx:%x]\n", block, offset);
++
++failed_read1:
++ return NULL;
++}
++
++
++int read_fragment_index_table(struct super_block *s)
++{
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES
++ (sblk->fragments), GFP_KERNEL))) {
++ ERROR("Failed to allocate uid/gid table\n");
++ return 0;
++ }
++
++ if (SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments) &&
++ !squashfs_read_data(s, (char *)
++ msblk->fragment_index,
++ sblk->fragment_table_start,
++ SQUASHFS_FRAGMENT_INDEX_BYTES
++ (sblk->fragments) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++ ERROR("unable to read fragment index table\n");
++ return 0;
++ }
++
++ if (msblk->swap) {
++ int i;
++ long long fragment;
++
++ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments);
++ i++) {
++ SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),
++ &msblk->fragment_index[i], 1);
++ msblk->fragment_index[i] = fragment;
++ }
++ }
++
++ return 1;
++}
++
++
++static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)
++{
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ msblk->iget = squashfs_iget;
++ msblk->read_blocklist = read_blocklist;
++ msblk->read_fragment_index_table = read_fragment_index_table;
++
++ if (sblk->s_major == 1) {
++ if (!squashfs_1_0_supported(msblk)) {
++ SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "
++ "are unsupported\n");
++ SERROR("Please recompile with "
++ "Squashfs 1.0 support enabled\n");
++ return 0;
++ }
++ } else if (sblk->s_major == 2) {
++ if (!squashfs_2_0_supported(msblk)) {
++ SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "
++ "are unsupported\n");
++ SERROR("Please recompile with "
++ "Squashfs 2.0 support enabled\n");
++ return 0;
++ }
++ } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >
++ SQUASHFS_MINOR) {
++ SERROR("Major/Minor mismatch, trying to mount newer %d.%d "
++ "filesystem\n", sblk->s_major, sblk->s_minor);
++ SERROR("Please update your kernel\n");
++ return 0;
++ }
++
++ return 1;
++}
++
++
++static struct super_block *squashfs_read_super(struct super_block *s,
++ void *data, int silent)
++{
++ kdev_t dev = s->s_dev;
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int i;
++ struct inode *root;
++
++ msblk->devblksize = get_hardsect_size(dev);
++ if(msblk->devblksize < BLOCK_SIZE)
++ msblk->devblksize = BLOCK_SIZE;
++ msblk->devblksize_log2 = ffz(~msblk->devblksize);
++ set_blocksize(dev, msblk->devblksize);
++ s->s_blocksize = msblk->devblksize;
++ s->s_blocksize_bits = msblk->devblksize_log2;
++
++ init_MUTEX(&msblk->read_data_mutex);
++ init_MUTEX(&msblk->read_page_mutex);
++ init_MUTEX(&msblk->block_cache_mutex);
++ init_MUTEX(&msblk->fragment_mutex);
++
++ init_waitqueue_head(&msblk->waitq);
++ init_waitqueue_head(&msblk->fragment_wait_queue);
++
++ if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
++ sizeof(struct squashfs_super_block) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++ SERROR("unable to read superblock\n");
++ goto failed_mount;
++ }
++
++ /* Check it is a SQUASHFS superblock */
++ msblk->swap = 0;
++ if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) {
++ if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) {
++ struct squashfs_super_block ssblk;
++
++ WARNING("Mounting a different endian SQUASHFS "
++ "filesystem on %s\n", bdevname(dev));
++
++ SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);
++ memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));
++ msblk->swap = 1;
++ } else {
++ SERROR("Can't find a SQUASHFS superblock on %s\n",
++ bdevname(dev));
++ goto failed_mount;
++ }
++ }
++
++ /* Check the MAJOR & MINOR versions */
++ if(!supported_squashfs_filesystem(msblk, silent))
++ goto failed_mount;
++
++ TRACE("Found valid superblock on %s\n", bdevname(dev));
++ TRACE("Inodes are %scompressed\n",
++ SQUASHFS_UNCOMPRESSED_INODES
++ (sblk->flags) ? "un" : "");
++ TRACE("Data is %scompressed\n",
++ SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)
++ ? "un" : "");
++ TRACE("Check data is %s present in the filesystem\n",
++ SQUASHFS_CHECK_DATA(sblk->flags) ?
++ "" : "not");
++ TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);
++ TRACE("Block size %d\n", sblk->block_size);
++ TRACE("Number of inodes %d\n", sblk->inodes);
++ if (sblk->s_major > 1)
++ TRACE("Number of fragments %d\n", sblk->fragments);
++ TRACE("Number of uids %d\n", sblk->no_uids);
++ TRACE("Number of gids %d\n", sblk->no_guids);
++ TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);
++ TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);
++ if (sblk->s_major > 1)
++ TRACE("sblk->fragment_table_start %llx\n",
++ sblk->fragment_table_start);
++ TRACE("sblk->uid_start %llx\n", sblk->uid_start);
++
++ s->s_flags |= MS_RDONLY;
++ s->s_op = &squashfs_ops;
++
++ /* Init inode_table block pointer array */
++ if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *
++ SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
++ ERROR("Failed to allocate block cache\n");
++ goto failed_mount;
++ }
++
++ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
++ msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
++
++ msblk->next_cache = 0;
++
++ /* Allocate read_data block */
++ msblk->read_size = (sblk->block_size < SQUASHFS_METADATA_SIZE) ?
++ SQUASHFS_METADATA_SIZE :
++ sblk->block_size;
++
++ if (!(msblk->read_data = kmalloc(msblk->read_size, GFP_KERNEL))) {
++ ERROR("Failed to allocate read_data block\n");
++ goto failed_mount;
++ }
++
++ /* Allocate read_page block */
++ if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {
++ ERROR("Failed to allocate read_page block\n");
++ goto failed_mount;
++ }
++
++ /* Allocate uid and gid tables */
++ if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *
++ sizeof(unsigned int), GFP_KERNEL))) {
++ ERROR("Failed to allocate uid/gid table\n");
++ goto failed_mount;
++ }
++ msblk->guid = msblk->uid + sblk->no_uids;
++
++ if (msblk->swap) {
++ unsigned int suid[sblk->no_uids + sblk->no_guids];
++
++ if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,
++ ((sblk->no_uids + sblk->no_guids) *
++ sizeof(unsigned int)) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++ ERROR("unable to read uid/gid table\n");
++ goto failed_mount;
++ }
++
++ SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +
++ sblk->no_guids), (sizeof(unsigned int) * 8));
++ } else
++ if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,
++ ((sblk->no_uids + sblk->no_guids) *
++ sizeof(unsigned int)) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++ ERROR("unable to read uid/gid table\n");
++ goto failed_mount;
++ }
++
++
++ if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))
++ goto allocate_root;
++
++ if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *
++ SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {
++ ERROR("Failed to allocate fragment block cache\n");
++ goto failed_mount;
++ }
++
++ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {
++ msblk->fragment[i].locked = 0;
++ msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
++ msblk->fragment[i].data = NULL;
++ }
++
++ msblk->next_fragment = 0;
++
++ /* Allocate fragment index table */
++ if(msblk->read_fragment_index_table(s) == 0)
++ goto failed_mount;
++
++allocate_root:
++ if ((root = (msblk->iget)(s, sblk->root_inode)) == NULL)
++ goto failed_mount;
++
++ if ((s->s_root = d_alloc_root(root)) == NULL) {
++ ERROR("Root inode create failed\n");
++ iput(root);
++ goto failed_mount;
++ }
++
++ TRACE("Leaving squashfs_read_super\n");
++ return s;
++
++failed_mount:
++ kfree(msblk->fragment_index);
++ kfree(msblk->fragment);
++ kfree(msblk->uid);
++ kfree(msblk->read_page);
++ kfree(msblk->read_data);
++ kfree(msblk->block_cache);
++ kfree(msblk->fragment_index_2);
++ return NULL;
++}
++
++
++static int squashfs_statfs(struct super_block *s, struct statfs *buf)
++{
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ TRACE("Entered squashfs_statfs\n");
++
++ buf->f_type = SQUASHFS_MAGIC;
++ buf->f_bsize = sblk->block_size;
++ buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;
++ buf->f_bfree = buf->f_bavail = 0;
++ buf->f_files = sblk->inodes;
++ buf->f_ffree = 0;
++ buf->f_namelen = SQUASHFS_NAME_LEN;
++
++ return 0;
++}
++
++
++static int squashfs_symlink_readpage(struct file *file, struct page *page)
++{
++ struct inode *inode = page->mapping->host;
++ int index = page->index << PAGE_CACHE_SHIFT, length, bytes;
++ long long block = SQUASHFS_I(inode)->start_block;
++ int offset = SQUASHFS_I(inode)->offset;
++ void *pageaddr = kmap(page);
++
++ TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
++ "%llx, offset %x\n", page->index,
++ SQUASHFS_I(inode)->start_block,
++ SQUASHFS_I(inode)->offset);
++
++ for (length = 0; length < index; length += bytes) {
++ if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,
++ block, offset, PAGE_CACHE_SIZE, &block,
++ &offset))) {
++ ERROR("Unable to read symbolic link [%llx:%x]\n", block,
++ offset);
++ goto skip_read;
++ }
++ }
++
++ if (length != index) {
++ ERROR("(squashfs_symlink_readpage) length != index\n");
++ bytes = 0;
++ goto skip_read;
++ }
++
++ bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :
++ i_size_read(inode) - length;
++
++ if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,
++ offset, bytes, &block, &offset)))
++ ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);
++
++skip_read:
++ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++ kunmap(page);
++ SetPageUptodate(page);
++ UnlockPage(page);
++
++ return 0;
++}
++
++
++struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)
++{
++ struct meta_index *meta = NULL;
++ struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
++ int i;
++
++ down(&msblk->meta_index_mutex);
++
++ TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
++
++ if(msblk->meta_index == NULL)
++ goto not_allocated;
++
++ for (i = 0; i < SQUASHFS_META_NUMBER; i ++)
++ if (msblk->meta_index[i].inode_number == inode->i_ino &&
++ msblk->meta_index[i].offset >= offset &&
++ msblk->meta_index[i].offset <= index &&
++ msblk->meta_index[i].locked == 0) {
++ TRACE("locate_meta_index: entry %d, offset %d\n", i,
++ msblk->meta_index[i].offset);
++ meta = &msblk->meta_index[i];
++ offset = meta->offset;
++ }
++
++ if (meta)
++ meta->locked = 1;
++
++not_allocated:
++ up(&msblk->meta_index_mutex);
++
++ return meta;
++}
++
++
++struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)
++{
++ struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
++ struct meta_index *meta = NULL;
++ int i;
++
++ down(&msblk->meta_index_mutex);
++
++ TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
++
++ if(msblk->meta_index == NULL) {
++ if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *
++ SQUASHFS_META_NUMBER, GFP_KERNEL))) {
++ ERROR("Failed to allocate meta_index\n");
++ goto failed;
++ }
++ for(i = 0; i < SQUASHFS_META_NUMBER; i++) {
++ msblk->meta_index[i].inode_number = 0;
++ msblk->meta_index[i].locked = 0;
++ }
++ msblk->next_meta_index = 0;
++ }
++
++ for(i = SQUASHFS_META_NUMBER; i &&
++ msblk->meta_index[msblk->next_meta_index].locked; i --)
++ msblk->next_meta_index = (msblk->next_meta_index + 1) %
++ SQUASHFS_META_NUMBER;
++
++ if(i == 0) {
++ TRACE("empty_meta_index: failed!\n");
++ goto failed;
++ }
++
++ TRACE("empty_meta_index: returned meta entry %d, %p\n",
++ msblk->next_meta_index,
++ &msblk->meta_index[msblk->next_meta_index]);
++
++ meta = &msblk->meta_index[msblk->next_meta_index];
++ msblk->next_meta_index = (msblk->next_meta_index + 1) %
++ SQUASHFS_META_NUMBER;
++
++ meta->inode_number = inode->i_ino;
++ meta->offset = offset;
++ meta->skip = skip;
++ meta->entries = 0;
++ meta->locked = 1;
++
++failed:
++ up(&msblk->meta_index_mutex);
++ return meta;
++}
++
++
++void release_meta_index(struct inode *inode, struct meta_index *meta)
++{
++ meta->locked = 0;
++}
++
++
++static int read_block_index(struct super_block *s, int blocks, char *block_list,
++ long long *start_block, int *offset)
++{
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ unsigned int *block_listp;
++ int block = 0;
++
++ if (msblk->swap) {
++ char sblock_list[blocks << 2];
++
++ if (!squashfs_get_cached_block(s, sblock_list, *start_block,
++ *offset, blocks << 2, start_block, offset)) {
++ ERROR("Unable to read block list [%llx:%x]\n",
++ *start_block, *offset);
++ goto failure;
++ }
++ SQUASHFS_SWAP_INTS(((unsigned int *)block_list),
++ ((unsigned int *)sblock_list), blocks);
++ } else
++ if (!squashfs_get_cached_block(s, block_list, *start_block,
++ *offset, blocks << 2, start_block, offset)) {
++ ERROR("Unable to read block list [%llx:%x]\n",
++ *start_block, *offset);
++ goto failure;
++ }
++
++ for (block_listp = (unsigned int *) block_list; blocks;
++ block_listp++, blocks --)
++ block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
++
++ return block;
++
++failure:
++ return -1;
++}
++
++
++#define SIZE 256
++
++static inline int calculate_skip(int blocks) {
++ int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);
++ return skip >= 7 ? 7 : skip + 1;
++}
++
++
++static int get_meta_index(struct inode *inode, int index,
++ long long *index_block, int *index_offset,
++ long long *data_block, char *block_list)
++{
++ struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);
++ int offset = 0;
++ struct meta_index *meta;
++ struct meta_entry *meta_entry;
++ long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;
++ int cur_offset = SQUASHFS_I(inode)->offset;
++ long long cur_data_block = SQUASHFS_I(inode)->start_block;
++ int i;
++
++ index /= SQUASHFS_META_INDEXES * skip;
++
++ while ( offset < index ) {
++ meta = locate_meta_index(inode, index, offset + 1);
++
++ if (meta == NULL) {
++ if ((meta = empty_meta_index(inode, offset + 1,
++ skip)) == NULL)
++ goto all_done;
++ } else {
++ offset = index < meta->offset + meta->entries ? index :
++ meta->offset + meta->entries - 1;
++ meta_entry = &meta->meta_entry[offset - meta->offset];
++ cur_index_block = meta_entry->index_block + sblk->inode_table_start;
++ cur_offset = meta_entry->offset;
++ cur_data_block = meta_entry->data_block;
++ TRACE("get_meta_index: offset %d, meta->offset %d, "
++ "meta->entries %d\n", offset, meta->offset,
++ meta->entries);
++ TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
++ " data_block 0x%llx\n", cur_index_block,
++ cur_offset, cur_data_block);
++ }
++
++ for (i = meta->offset + meta->entries; i <= index &&
++ i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
++ int blocks = skip * SQUASHFS_META_INDEXES;
++
++ while (blocks) {
++ int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :
++ blocks;
++ int res = read_block_index(inode->i_sb, block,
++ block_list, &cur_index_block,
++ &cur_offset);
++
++ if (res == -1)
++ goto failed;
++
++ cur_data_block += res;
++ blocks -= block;
++ }
++
++ meta_entry = &meta->meta_entry[i - meta->offset];
++ meta_entry->index_block = cur_index_block - sblk->inode_table_start;
++ meta_entry->offset = cur_offset;
++ meta_entry->data_block = cur_data_block;
++ meta->entries ++;
++ offset ++;
++ }
++
++ TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
++ meta->offset, meta->entries);
++
++ release_meta_index(inode, meta);
++ }
++
++all_done:
++ *index_block = cur_index_block;
++ *index_offset = cur_offset;
++ *data_block = cur_data_block;
++
++ return offset * SQUASHFS_META_INDEXES * skip;
++
++failed:
++ release_meta_index(inode, meta);
++ return -1;
++}
++
++
++static long long read_blocklist(struct inode *inode, int index,
++ int readahead_blks, char *block_list,
++ unsigned short **block_p, unsigned int *bsize)
++{
++ long long block_ptr;
++ int offset;
++ long long block;
++ int res = get_meta_index(inode, index, &block_ptr, &offset, &block,
++ block_list);
++
++ TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"
++ " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,
++ block);
++
++ if(res == -1)
++ goto failure;
++
++ index -= res;
++
++ while ( index ) {
++ int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;
++ int res = read_block_index(inode->i_sb, blocks, block_list,
++ &block_ptr, &offset);
++ if (res == -1)
++ goto failure;
++ block += res;
++ index -= blocks;
++ }
++
++ if (read_block_index(inode->i_sb, 1, block_list,
++ &block_ptr, &offset) == -1)
++ goto failure;
++ *bsize = *((unsigned int *) block_list);
++
++ return block;
++
++failure:
++ return 0;
++}
++
++
++static int squashfs_readpage(struct file *file, struct page *page)
++{
++ struct inode *inode = page->mapping->host;
++ struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ unsigned char block_list[SIZE];
++ long long block;
++ unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;
++ int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);
++ void *pageaddr;
++ struct squashfs_fragment_cache *fragment = NULL;
++ char *data_ptr = msblk->read_page;
++
++ int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;
++ int start_index = page->index & ~mask;
++ int end_index = start_index | mask;
++
++ TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
++ page->index,
++ SQUASHFS_I(inode)->start_block);
++
++ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
++ PAGE_CACHE_SHIFT))
++ goto skip_read;
++
++ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++ || index < (i_size_read(inode) >>
++ sblk->block_log)) {
++ if ((block = (msblk->read_blocklist)(inode, index, 1,
++ block_list, NULL, &bsize)) == 0)
++ goto skip_read;
++
++ down(&msblk->read_page_mutex);
++
++ if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,
++ block, bsize, NULL))) {
++ ERROR("Unable to read page, block %llx, size %x\n", block,
++ bsize);
++ up(&msblk->read_page_mutex);
++ goto skip_read;
++ }
++ } else {
++ if ((fragment = get_cached_fragment(inode->i_sb,
++ SQUASHFS_I(inode)->
++ u.s1.fragment_start_block,
++ SQUASHFS_I(inode)->u.s1.fragment_size))
++ == NULL) {
++ ERROR("Unable to read page, block %llx, size %x\n",
++ SQUASHFS_I(inode)->
++ u.s1.fragment_start_block,
++ (int) SQUASHFS_I(inode)->
++ u.s1.fragment_size);
++ goto skip_read;
++ }
++ bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +
++ (i_size_read(inode) & (sblk->block_size
++ - 1));
++ byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;
++ data_ptr = fragment->data;
++ }
++
++ for (i = start_index; i <= end_index && byte_offset < bytes;
++ i++, byte_offset += PAGE_CACHE_SIZE) {
++ struct page *push_page;
++ int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ?
++ PAGE_CACHE_SIZE : bytes - byte_offset;
++
++ TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",
++ bytes, i, byte_offset, available_bytes);
++
++ if (i == page->index) {
++ pageaddr = kmap_atomic(page, KM_USER0);
++ memcpy(pageaddr, data_ptr + byte_offset,
++ available_bytes);
++ memset(pageaddr + available_bytes, 0,
++ PAGE_CACHE_SIZE - available_bytes);
++ kunmap_atomic(pageaddr, KM_USER0);
++ flush_dcache_page(page);
++ SetPageUptodate(page);
++ UnlockPage(page);
++ } else if ((push_page =
++ grab_cache_page_nowait(page->mapping, i))) {
++ pageaddr = kmap_atomic(push_page, KM_USER0);
++
++ memcpy(pageaddr, data_ptr + byte_offset,
++ available_bytes);
++ memset(pageaddr + available_bytes, 0,
++ PAGE_CACHE_SIZE - available_bytes);
++ kunmap_atomic(pageaddr, KM_USER0);
++ flush_dcache_page(push_page);
++ SetPageUptodate(push_page);
++ UnlockPage(push_page);
++ page_cache_release(push_page);
++ }
++ }
++
++ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++ || index < (i_size_read(inode) >>
++ sblk->block_log))
++ up(&msblk->read_page_mutex);
++ else
++ release_cached_fragment(msblk, fragment);
++
++ return 0;
++
++skip_read:
++ pageaddr = kmap_atomic(page, KM_USER0);
++ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++ kunmap_atomic(pageaddr, KM_USER0);
++ flush_dcache_page(page);
++ SetPageUptodate(page);
++ UnlockPage(page);
++
++ return 0;
++}
++
++
++static int squashfs_readpage4K(struct file *file, struct page *page)
++{
++ struct inode *inode = page->mapping->host;
++ struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ unsigned char block_list[SIZE];
++ long long block;
++ unsigned int bsize, bytes = 0;
++ void *pageaddr;
++
++ TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",
++ page->index,
++ SQUASHFS_I(inode)->start_block);
++
++ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
++ PAGE_CACHE_SHIFT)) {
++ pageaddr = kmap_atomic(page, KM_USER0);
++ goto skip_read;
++ }
++
++ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++ || page->index < (i_size_read(inode) >>
++ sblk->block_log)) {
++ block = (msblk->read_blocklist)(inode, page->index, 1,
++ block_list, NULL, &bsize);
++
++ down(&msblk->read_page_mutex);
++ bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
++ bsize, NULL);
++ pageaddr = kmap_atomic(page, KM_USER0);
++ if (bytes)
++ memcpy(pageaddr, msblk->read_page, bytes);
++ else
++ ERROR("Unable to read page, block %llx, size %x\n",
++ block, bsize);
++ up(&msblk->read_page_mutex);
++ } else {
++ struct squashfs_fragment_cache *fragment =
++ get_cached_fragment(inode->i_sb,
++ SQUASHFS_I(inode)->
++ u.s1.fragment_start_block,
++ SQUASHFS_I(inode)-> u.s1.fragment_size);
++ pageaddr = kmap_atomic(page, KM_USER0);
++ if (fragment) {
++ bytes = i_size_read(inode) & (sblk->block_size - 1);
++ memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->
++ u.s1.fragment_offset, bytes);
++ release_cached_fragment(msblk, fragment);
++ } else
++ ERROR("Unable to read page, block %llx, size %x\n",
++ SQUASHFS_I(inode)->
++ u.s1.fragment_start_block, (int)
++ SQUASHFS_I(inode)-> u.s1.fragment_size);
++ }
++
++skip_read:
++ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++ kunmap_atomic(pageaddr, KM_USER0);
++ flush_dcache_page(page);
++ SetPageUptodate(page);
++ UnlockPage(page);
++
++ return 0;
++}
++
++
++static int get_dir_index_using_offset(struct super_block *s, long long
++ *next_block, unsigned int *next_offset,
++ long long index_start,
++ unsigned int index_offset, int i_count,
++ long long f_pos)
++{
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int i, length = 0;
++ struct squashfs_dir_index index;
++
++ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
++ i_count, (unsigned int) f_pos);
++
++ f_pos -= 3;
++ if (f_pos == 0)
++ goto finish;
++
++ for (i = 0; i < i_count; i++) {
++ if (msblk->swap) {
++ struct squashfs_dir_index sindex;
++ squashfs_get_cached_block(s, (char *) &sindex,
++ index_start, index_offset,
++ sizeof(sindex), &index_start,
++ &index_offset);
++ SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);
++ } else
++ squashfs_get_cached_block(s, (char *) &index,
++ index_start, index_offset,
++ sizeof(index), &index_start,
++ &index_offset);
++
++ if (index.index > f_pos)
++ break;
++
++ squashfs_get_cached_block(s, NULL, index_start, index_offset,
++ index.size + 1, &index_start,
++ &index_offset);
++
++ length = index.index;
++ *next_block = index.start_block + sblk->directory_table_start;
++ }
++
++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++
++finish:
++ return length + 3;
++}
++
++
++static int get_dir_index_using_name(struct super_block *s, long long
++ *next_block, unsigned int *next_offset,
++ long long index_start,
++ unsigned int index_offset, int i_count,
++ const char *name, int size)
++{
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int i, length = 0;
++ char buffer[sizeof(struct squashfs_dir_index) + SQUASHFS_NAME_LEN + 1];
++ struct squashfs_dir_index *index = (struct squashfs_dir_index *) buffer;
++ char str[SQUASHFS_NAME_LEN + 1];
++
++ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
++
++ strncpy(str, name, size);
++ str[size] = '\0';
++
++ for (i = 0; i < i_count; i++) {
++ if (msblk->swap) {
++ struct squashfs_dir_index sindex;
++ squashfs_get_cached_block(s, (char *) &sindex,
++ index_start, index_offset,
++ sizeof(sindex), &index_start,
++ &index_offset);
++ SQUASHFS_SWAP_DIR_INDEX(index, &sindex);
++ } else
++ squashfs_get_cached_block(s, (char *) index,
++ index_start, index_offset,
++ sizeof(struct squashfs_dir_index),
++ &index_start, &index_offset);
++
++ squashfs_get_cached_block(s, index->name, index_start,
++ index_offset, index->size + 1,
++ &index_start, &index_offset);
++
++ index->name[index->size + 1] = '\0';
++
++ if (strcmp(index->name, str) > 0)
++ break;
++
++ length = index->index;
++ *next_block = index->start_block + sblk->directory_table_start;
++ }
++
++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++ return length + 3;
++}
++
++
++static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
++{
++ struct inode *i = file->f_dentry->d_inode;
++ struct squashfs_sb_info *msblk = &i->i_sb->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long next_block = SQUASHFS_I(i)->start_block +
++ sblk->directory_table_start;
++ int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0,
++ dir_count;
++ struct squashfs_dir_header dirh;
++ char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1];
++ struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
++
++ TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);
++
++ while(file->f_pos < 3) {
++ char *name;
++ int size, i_ino;
++
++ if(file->f_pos == 0) {
++ name = ".";
++ size = 1;
++ i_ino = i->i_ino;
++ } else {
++ name = "..";
++ size = 2;
++ i_ino = SQUASHFS_I(i)->u.s2.parent_inode;
++ }
++ TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",
++ (unsigned int) dirent, name, size, (int)
++ file->f_pos, i_ino,
++ squashfs_filetype_table[1]);
++
++ if (filldir(dirent, name, size,
++ file->f_pos, i_ino,
++ squashfs_filetype_table[1]) < 0) {
++ TRACE("Filldir returned less than 0\n");
++ goto finish;
++ }
++ file->f_pos += size;
++ dirs_read++;
++ }
++
++ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_start,
++ SQUASHFS_I(i)->u.s2.directory_index_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_count,
++ file->f_pos);
++
++ while (length < i_size_read(i)) {
++ /* read directory header */
++ if (msblk->swap) {
++ struct squashfs_dir_header sdirh;
++
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++ next_block, next_offset, sizeof(sdirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdirh);
++ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++ next_block, next_offset, sizeof(dirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(dirh);
++ }
++
++ dir_count = dirh.count + 1;
++ while (dir_count--) {
++ if (msblk->swap) {
++ struct squashfs_dir_entry sdire;
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ &sdire, next_block, next_offset,
++ sizeof(sdire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdire);
++ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ dire, next_block, next_offset,
++ sizeof(*dire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(*dire);
++ }
++
++ if (!squashfs_get_cached_block(i->i_sb, dire->name,
++ next_block, next_offset,
++ dire->size + 1, &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += dire->size + 1;
++
++ if (file->f_pos >= length)
++ continue;
++
++ dire->name[dire->size + 1] = '\0';
++
++ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",
++ (unsigned int) dirent, dire->name,
++ dire->size + 1, (int) file->f_pos,
++ dirh.start_block, dire->offset,
++ dirh.inode_number + dire->inode_number,
++ squashfs_filetype_table[dire->type]);
++
++ if (filldir(dirent, dire->name, dire->size + 1,
++ file->f_pos,
++ dirh.inode_number + dire->inode_number,
++ squashfs_filetype_table[dire->type])
++ < 0) {
++ TRACE("Filldir returned less than 0\n");
++ goto finish;
++ }
++ file->f_pos = length;
++ dirs_read++;
++ }
++ }
++
++finish:
++ return dirs_read;
++
++failed_read:
++ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++ next_offset);
++ return 0;
++}
++
++
++static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry)
++{
++ const unsigned char *name = dentry->d_name.name;
++ int len = dentry->d_name.len;
++ struct inode *inode = NULL;
++ struct squashfs_sb_info *msblk = &i->i_sb->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long next_block = SQUASHFS_I(i)->start_block +
++ sblk->directory_table_start;
++ int next_offset = SQUASHFS_I(i)->offset, length = 0,
++ dir_count;
++ struct squashfs_dir_header dirh;
++ char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN];
++ struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
++
++ TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
++
++ if (len > SQUASHFS_NAME_LEN)
++ goto exit_loop;
++
++ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_start,
++ SQUASHFS_I(i)->u.s2.directory_index_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_count, name,
++ len);
++
++ while (length < i_size_read(i)) {
++ /* read directory header */
++ if (msblk->swap) {
++ struct squashfs_dir_header sdirh;
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++ next_block, next_offset, sizeof(sdirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdirh);
++ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++ next_block, next_offset, sizeof(dirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(dirh);
++ }
++
++ dir_count = dirh.count + 1;
++ while (dir_count--) {
++ if (msblk->swap) {
++ struct squashfs_dir_entry sdire;
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ &sdire, next_block,next_offset,
++ sizeof(sdire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdire);
++ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ dire, next_block,next_offset,
++ sizeof(*dire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(*dire);
++ }
++
++ if (!squashfs_get_cached_block(i->i_sb, dire->name,
++ next_block, next_offset, dire->size + 1,
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += dire->size + 1;
++
++ if (name[0] < dire->name[0])
++ goto exit_loop;
++
++ if ((len == dire->size + 1) && !strncmp(name,
++ dire->name, len)) {
++ squashfs_inode_t ino =
++ SQUASHFS_MKINODE(dirh.start_block,
++ dire->offset);
++
++ TRACE("calling squashfs_iget for directory "
++ "entry %s, inode %x:%x, %d\n", name,
++ dirh.start_block, dire->offset,
++ dirh.inode_number + dire->inode_number);
++
++ inode = (msblk->iget)(i->i_sb, ino);
++
++ goto exit_loop;
++ }
++ }
++ }
++
++exit_loop:
++ d_add(dentry, inode);
++ return ERR_PTR(0);
++
++failed_read:
++ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++ next_offset);
++ goto exit_loop;
++}
++
++
++static void squashfs_put_super(struct super_block *s)
++{
++ int i;
++
++ struct squashfs_sb_info *sbi = &s->u.squashfs_sb;
++ if (sbi->block_cache)
++ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
++ if (sbi->block_cache[i].block !=
++ SQUASHFS_INVALID_BLK)
++ kfree(sbi->block_cache[i].data);
++ if (sbi->fragment)
++ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++)
++ SQUASHFS_FREE(sbi->fragment[i].data);
++ kfree(sbi->fragment);
++ kfree(sbi->block_cache);
++ kfree(sbi->read_data);
++ kfree(sbi->read_page);
++ kfree(sbi->uid);
++ kfree(sbi->fragment_index);
++ kfree(sbi->fragment_index_2);
++ sbi->block_cache = NULL;
++ sbi->uid = NULL;
++ sbi->read_data = NULL;
++ sbi->read_page = NULL;
++ sbi->fragment = NULL;
++ sbi->fragment_index = NULL;
++ sbi->fragment_index_2 = NULL;
++}
++
++
++static int __init init_squashfs_fs(void)
++{
++
++ printk(KERN_INFO "squashfs: version 3.0 (2006/03/15) "
++ "Phillip Lougher\n");
++
++ if (!(stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
++ ERROR("Failed to allocate zlib workspace\n");
++ return -ENOMEM;
++ }
++ return register_filesystem(&squashfs_fs_type);
++}
++
++
++static void __exit exit_squashfs_fs(void)
++{
++ vfree(stream.workspace);
++ unregister_filesystem(&squashfs_fs_type);
++}
++
++
++EXPORT_NO_SYMBOLS;
++
++module_init(init_squashfs_fs);
++module_exit(exit_squashfs_fs);
++MODULE_DESCRIPTION("squashfs, a compressed read-only filesystem");
++MODULE_AUTHOR("Phillip Lougher <phillip@lougher.org.uk>");
++MODULE_LICENSE("GPL");
+diff --new-file -urp linux-2.4.32/fs/squashfs/Makefile linux-2.4.32-squashfs3.0/fs/squashfs/Makefile
+--- linux-2.4.32/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-squashfs3.0/fs/squashfs/Makefile 2006-03-07 21:12:36.000000000 +0000
+@@ -0,0 +1,11 @@
++#
++# Makefile for the linux squashfs routines.
++#
++
++O_TARGET := squashfs.o
++
++obj-y := inode.o squashfs2_0.o
++
++obj-m := $(O_TARGET)
++
++include $(TOPDIR)/Rules.make
+diff --new-file -urp linux-2.4.32/fs/squashfs/squashfs2_0.c linux-2.4.32-squashfs3.0/fs/squashfs/squashfs2_0.c
+--- linux-2.4.32/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-squashfs3.0/fs/squashfs/squashfs2_0.c 2006-03-07 21:12:36.000000000 +0000
+@@ -0,0 +1,751 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs2_0.c
++ */
++
++#include <linux/types.h>
++#include <linux/squashfs_fs.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/fs.h>
++#include <linux/smp_lock.h>
++#include <linux/locks.h>
++#include <linux/init.h>
++#include <linux/dcache.h>
++#include <linux/wait.h>
++#include <linux/zlib.h>
++#include <linux/blkdev.h>
++#include <linux/vmalloc.h>
++#include <asm/uaccess.h>
++#include <asm/semaphore.h>
++#include "squashfs.h"
++
++static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);
++static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry);
++
++static struct file_operations squashfs_dir_ops_2 = {
++ .read = generic_read_dir,
++ .readdir = squashfs_readdir_2
++};
++
++static struct inode_operations squashfs_dir_inode_ops_2 = {
++ .lookup = squashfs_lookup_2
++};
++
++static unsigned char squashfs_filetype_table[] = {
++ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
++};
++
++static int read_fragment_index_table_2(struct super_block *s)
++{
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2
++ (sblk->fragments), GFP_KERNEL))) {
++ ERROR("Failed to allocate uid/gid table\n");
++ return 0;
++ }
++
++ if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&
++ !squashfs_read_data(s, (char *)
++ msblk->fragment_index_2,
++ sblk->fragment_table_start,
++ SQUASHFS_FRAGMENT_INDEX_BYTES_2
++ (sblk->fragments) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++ ERROR("unable to read fragment index table\n");
++ return 0;
++ }
++
++ if (msblk->swap) {
++ int i;
++ unsigned int fragment;
++
++ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);
++ i++) {
++ SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),
++ &msblk->fragment_index_2[i], 1);
++ msblk->fragment_index_2[i] = fragment;
++ }
++ }
++
++ return 1;
++}
++
++
++static int get_fragment_location_2(struct super_block *s, unsigned int fragment,
++ long long *fragment_start_block,
++ unsigned int *fragment_size)
++{
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ long long start_block =
++ msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];
++ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);
++ struct squashfs_fragment_entry_2 fragment_entry;
++
++ if (msblk->swap) {
++ struct squashfs_fragment_entry_2 sfragment_entry;
++
++ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
++ start_block, offset,
++ sizeof(sfragment_entry), &start_block,
++ &offset))
++ goto out;
++ SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);
++ } else
++ if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
++ start_block, offset,
++ sizeof(fragment_entry), &start_block,
++ &offset))
++ goto out;
++
++ *fragment_start_block = fragment_entry.start_block;
++ *fragment_size = fragment_entry.size;
++
++ return 1;
++
++out:
++ return 0;
++}
++
++
++static struct inode *squashfs_new_inode(struct super_block *s,
++ struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)
++{
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ struct inode *i = new_inode(s);
++
++ if (i) {
++ i->i_ino = ino;
++ i->i_mtime = sblk->mkfs_time;
++ i->i_atime = sblk->mkfs_time;
++ i->i_ctime = sblk->mkfs_time;
++ i->i_uid = msblk->uid[inodeb->uid];
++ i->i_mode = inodeb->mode;
++ i->i_nlink = 1;
++ i->i_size = 0;
++ if (inodeb->guid == SQUASHFS_GUIDS)
++ i->i_gid = i->i_uid;
++ else
++ i->i_gid = msblk->guid[inodeb->guid];
++ }
++
++ return i;
++}
++
++
++static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t inode)
++{
++ struct inode *i;
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ unsigned int block = SQUASHFS_INODE_BLK(inode) +
++ sblk->inode_table_start;
++ unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
++ unsigned int ino = SQUASHFS_MK_VFS_INODE(block
++ - sblk->inode_table_start, offset);
++ long long next_block;
++ unsigned int next_offset;
++ union squashfs_inode_header_2 id, sid;
++ struct squashfs_base_inode_header_2 *inodeb = &id.base,
++ *sinodeb = &sid.base;
++
++ TRACE("Entered squashfs_iget\n");
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
++ offset, sizeof(*sinodeb), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,
++ sizeof(*sinodeb));
++ } else
++ if (!squashfs_get_cached_block(s, (char *) inodeb, block,
++ offset, sizeof(*inodeb), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ switch(inodeb->inode_type) {
++ case SQUASHFS_FILE_TYPE: {
++ struct squashfs_reg_inode_header_2 *inodep = &id.reg;
++ struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;
++ long long frag_blk;
++ unsigned int frag_size;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ frag_blk = SQUASHFS_INVALID_BLK;
++ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
++ !get_fragment_location_2(s,
++ inodep->fragment, &frag_blk, &frag_size))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++ goto failed_read1;
++
++ i->i_size = inodep->file_size;
++ i->i_fop = &generic_ro_fops;
++ i->i_mode |= S_IFREG;
++ i->i_mtime = inodep->mtime;
++ i->i_atime = inodep->mtime;
++ i->i_ctime = inodep->mtime;
++ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
++ i->i_blksize = PAGE_CACHE_SIZE;
++ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
++ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
++ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++ if (sblk->block_size > 4096)
++ i->i_data.a_ops = &squashfs_aops;
++ else
++ i->i_data.a_ops = &squashfs_aops_4K;
++
++ TRACE("File inode %x:%x, start_block %x, "
++ "block_list_start %llx, offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, next_block,
++ next_offset);
++ break;
++ }
++ case SQUASHFS_DIR_TYPE: {
++ struct squashfs_dir_inode_header_2 *inodep = &id.dir;
++ struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++ goto failed_read1;
++
++ i->i_size = inodep->file_size;
++ i->i_op = &squashfs_dir_inode_ops_2;
++ i->i_fop = &squashfs_dir_ops_2;
++ i->i_mode |= S_IFDIR;
++ i->i_mtime = inodep->mtime;
++ i->i_atime = inodep->mtime;
++ i->i_ctime = inodep->mtime;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->offset = inodep->offset;
++ SQUASHFS_I(i)->u.s2.directory_index_count = 0;
++ SQUASHFS_I(i)->u.s2.parent_inode = 0;
++
++ TRACE("Directory inode %x:%x, start_block %x, offset "
++ "%x\n", SQUASHFS_INODE_BLK(inode),
++ offset, inodep->start_block,
++ inodep->offset);
++ break;
++ }
++ case SQUASHFS_LDIR_TYPE: {
++ struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;
++ struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,
++ sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++ goto failed_read1;
++
++ i->i_size = inodep->file_size;
++ i->i_op = &squashfs_dir_inode_ops_2;
++ i->i_fop = &squashfs_dir_ops_2;
++ i->i_mode |= S_IFDIR;
++ i->i_mtime = inodep->mtime;
++ i->i_atime = inodep->mtime;
++ i->i_ctime = inodep->mtime;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->offset = inodep->offset;
++ SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
++ SQUASHFS_I(i)->u.s2.directory_index_offset =
++ next_offset;
++ SQUASHFS_I(i)->u.s2.directory_index_count =
++ inodep->i_count;
++ SQUASHFS_I(i)->u.s2.parent_inode = 0;
++
++ TRACE("Long directory inode %x:%x, start_block %x, "
++ "offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, inodep->offset);
++ break;
++ }
++ case SQUASHFS_SYMLINK_TYPE: {
++ struct squashfs_symlink_inode_header_2 *inodep =
++ &id.symlink;
++ struct squashfs_symlink_inode_header_2 *sinodep =
++ &sid.symlink;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,
++ sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++ goto failed_read1;
++
++ i->i_size = inodep->symlink_size;
++ i->i_op = &page_symlink_inode_operations;
++ i->i_data.a_ops = &squashfs_symlink_aops;
++ i->i_mode |= S_IFLNK;
++ SQUASHFS_I(i)->start_block = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++
++ TRACE("Symbolic link inode %x:%x, start_block %llx, "
++ "offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ next_block, next_offset);
++ break;
++ }
++ case SQUASHFS_BLKDEV_TYPE:
++ case SQUASHFS_CHRDEV_TYPE: {
++ struct squashfs_dev_inode_header_2 *inodep = &id.dev;
++ struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++ goto failed_read1;
++
++ i->i_mode |= (inodeb->inode_type ==
++ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
++ S_IFBLK;
++ init_special_inode(i, i->i_mode, inodep->rdev);
++
++ TRACE("Device inode %x:%x, rdev %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->rdev);
++ break;
++ }
++ case SQUASHFS_FIFO_TYPE:
++ case SQUASHFS_SOCKET_TYPE: {
++ if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++ goto failed_read1;
++
++ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
++ ? S_IFIFO : S_IFSOCK;
++ init_special_inode(i, i->i_mode, 0);
++ break;
++ }
++ default:
++ ERROR("Unknown inode type %d in squashfs_iget!\n",
++ inodeb->inode_type);
++ goto failed_read1;
++ }
++
++ insert_inode_hash(i);
++ return i;
++
++failed_read:
++ ERROR("Unable to read inode [%x:%x]\n", block, offset);
++
++failed_read1:
++ return NULL;
++}
++
++
++static int get_dir_index_using_offset(struct super_block *s, long long
++ *next_block, unsigned int *next_offset,
++ long long index_start,
++ unsigned int index_offset, int i_count,
++ long long f_pos)
++{
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int i, length = 0;
++ struct squashfs_dir_index_2 index;
++
++ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
++ i_count, (unsigned int) f_pos);
++
++ if (f_pos == 0)
++ goto finish;
++
++ for (i = 0; i < i_count; i++) {
++ if (msblk->swap) {
++ struct squashfs_dir_index_2 sindex;
++ squashfs_get_cached_block(s, (char *) &sindex,
++ index_start, index_offset,
++ sizeof(sindex), &index_start,
++ &index_offset);
++ SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);
++ } else
++ squashfs_get_cached_block(s, (char *) &index,
++ index_start, index_offset,
++ sizeof(index), &index_start,
++ &index_offset);
++
++ if (index.index > f_pos)
++ break;
++
++ squashfs_get_cached_block(s, NULL, index_start, index_offset,
++ index.size + 1, &index_start,
++ &index_offset);
++
++ length = index.index;
++ *next_block = index.start_block + sblk->directory_table_start;
++ }
++
++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++
++finish:
++ return length;
++}
++
++
++static int get_dir_index_using_name(struct super_block *s, long long
++ *next_block, unsigned int *next_offset,
++ long long index_start,
++ unsigned int index_offset, int i_count,
++ const char *name, int size)
++{
++ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int i, length = 0;
++ char buffer[sizeof(struct squashfs_dir_index_2) + SQUASHFS_NAME_LEN + 1];
++ struct squashfs_dir_index_2 *index = (struct squashfs_dir_index_2 *) buffer;
++ char str[SQUASHFS_NAME_LEN + 1];
++
++ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
++
++ strncpy(str, name, size);
++ str[size] = '\0';
++
++ for (i = 0; i < i_count; i++) {
++ if (msblk->swap) {
++ struct squashfs_dir_index_2 sindex;
++ squashfs_get_cached_block(s, (char *) &sindex,
++ index_start, index_offset,
++ sizeof(sindex), &index_start,
++ &index_offset);
++ SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);
++ } else
++ squashfs_get_cached_block(s, (char *) index,
++ index_start, index_offset,
++ sizeof(struct squashfs_dir_index_2),
++ &index_start, &index_offset);
++
++ squashfs_get_cached_block(s, index->name, index_start,
++ index_offset, index->size + 1,
++ &index_start, &index_offset);
++
++ index->name[index->size + 1] = '\0';
++
++ if (strcmp(index->name, str) > 0)
++ break;
++
++ length = index->index;
++ *next_block = index->start_block + sblk->directory_table_start;
++ }
++
++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++ return length;
++}
++
++
++static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)
++{
++ struct inode *i = file->f_dentry->d_inode;
++ struct squashfs_sb_info *msblk = &i->i_sb->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long next_block = SQUASHFS_I(i)->start_block +
++ sblk->directory_table_start;
++ int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0,
++ dir_count;
++ struct squashfs_dir_header_2 dirh;
++ char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1];
++ struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer;
++
++ TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);
++
++ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_start,
++ SQUASHFS_I(i)->u.s2.directory_index_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_count,
++ file->f_pos);
++
++ while (length < i_size_read(i)) {
++ /* read directory header */
++ if (msblk->swap) {
++ struct squashfs_dir_header_2 sdirh;
++
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++ next_block, next_offset, sizeof(sdirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdirh);
++ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++ next_block, next_offset, sizeof(dirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(dirh);
++ }
++
++ dir_count = dirh.count + 1;
++ while (dir_count--) {
++ if (msblk->swap) {
++ struct squashfs_dir_entry_2 sdire;
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ &sdire, next_block, next_offset,
++ sizeof(sdire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdire);
++ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ dire, next_block, next_offset,
++ sizeof(*dire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(*dire);
++ }
++
++ if (!squashfs_get_cached_block(i->i_sb, dire->name,
++ next_block, next_offset,
++ dire->size + 1, &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += dire->size + 1;
++
++ if (file->f_pos >= length)
++ continue;
++
++ dire->name[dire->size + 1] = '\0';
++
++ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",
++ (unsigned int) dirent, dire->name,
++ dire->size + 1, (int) file->f_pos,
++ dirh.start_block, dire->offset,
++ squashfs_filetype_table[dire->type]);
++
++ if (filldir(dirent, dire->name, dire->size + 1,
++ file->f_pos, SQUASHFS_MK_VFS_INODE(
++ dirh.start_block, dire->offset),
++ squashfs_filetype_table[dire->type])
++ < 0) {
++ TRACE("Filldir returned less than 0\n");
++ goto finish;
++ }
++ file->f_pos = length;
++ dirs_read++;
++ }
++ }
++
++finish:
++ return dirs_read;
++
++failed_read:
++ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++ next_offset);
++ return 0;
++}
++
++
++static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry)
++{
++ const unsigned char *name = dentry->d_name.name;
++ int len = dentry->d_name.len;
++ struct inode *inode = NULL;
++ struct squashfs_sb_info *msblk = &i->i_sb->u.squashfs_sb;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long next_block = SQUASHFS_I(i)->start_block +
++ sblk->directory_table_start;
++ int next_offset = SQUASHFS_I(i)->offset, length = 0,
++ dir_count;
++ struct squashfs_dir_header_2 dirh;
++ char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN];
++ struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer;
++ int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;
++
++ TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
++
++ if (len > SQUASHFS_NAME_LEN)
++ goto exit_loop;
++
++ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_start,
++ SQUASHFS_I(i)->u.s2.directory_index_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_count, name,
++ len);
++
++ while (length < i_size_read(i)) {
++ /* read directory header */
++ if (msblk->swap) {
++ struct squashfs_dir_header_2 sdirh;
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++ next_block, next_offset, sizeof(sdirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdirh);
++ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++ next_block, next_offset, sizeof(dirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(dirh);
++ }
++
++ dir_count = dirh.count + 1;
++ while (dir_count--) {
++ if (msblk->swap) {
++ struct squashfs_dir_entry_2 sdire;
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ &sdire, next_block,next_offset,
++ sizeof(sdire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdire);
++ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ dire, next_block,next_offset,
++ sizeof(*dire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(*dire);
++ }
++
++ if (!squashfs_get_cached_block(i->i_sb, dire->name,
++ next_block, next_offset, dire->size + 1,
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += dire->size + 1;
++
++ if (sorted && name[0] < dire->name[0])
++ goto exit_loop;
++
++ if ((len == dire->size + 1) && !strncmp(name,
++ dire->name, len)) {
++ squashfs_inode_t ino =
++ SQUASHFS_MKINODE(dirh.start_block,
++ dire->offset);
++
++ TRACE("calling squashfs_iget for directory "
++ "entry %s, inode %x:%x, %d\n", name,
++ dirh.start_block, dire->offset, ino);
++
++ inode = (msblk->iget)(i->i_sb, ino);
++
++ goto exit_loop;
++ }
++ }
++ }
++
++exit_loop:
++ d_add(dentry, inode);
++ return ERR_PTR(0);
++
++failed_read:
++ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++ next_offset);
++ goto exit_loop;
++}
++
++
++int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
++{
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ msblk->iget = squashfs_iget_2;
++ msblk->read_fragment_index_table = read_fragment_index_table_2;
++
++ sblk->bytes_used = sblk->bytes_used_2;
++ sblk->uid_start = sblk->uid_start_2;
++ sblk->guid_start = sblk->guid_start_2;
++ sblk->inode_table_start = sblk->inode_table_start_2;
++ sblk->directory_table_start = sblk->directory_table_start_2;
++ sblk->fragment_table_start = sblk->fragment_table_start_2;
++
++ return 1;
++}
+diff --new-file -urp linux-2.4.32/fs/squashfs/squashfs.h linux-2.4.32-squashfs3.0/fs/squashfs/squashfs.h
+--- linux-2.4.32/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-squashfs3.0/fs/squashfs/squashfs.h 2006-03-07 21:12:36.000000000 +0000
+@@ -0,0 +1,85 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs.h
++ */
++
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++#endif
++#ifdef SQUASHFS_TRACE
++#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)
++#else
++#define TRACE(s, args...) {}
++#endif
++
++#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args)
++
++#define SERROR(s, args...) do { \
++ if (!silent) \
++ printk(KERN_ERR "SQUASHFS error: "s, ## args);\
++ } while(0)
++
++#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args)
++
++#define SQUASHFS_I(INO) (&INO->u.squashfs_i)
++
++#define i_size_read(INO) (INO->i_size)
++
++#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY)
++#define SQSH_EXTERN
++extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,
++ long long index, unsigned int length,
++ long long *next_index);
++extern int squashfs_get_cached_block(struct super_block *s, char *buffer,
++ long long block, unsigned int offset,
++ int length, long long *next_block,
++ unsigned int *next_offset);
++extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct
++ squashfs_fragment_cache *fragment);
++extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block
++ *s, long long start_block,
++ int length);
++extern struct address_space_operations squashfs_symlink_aops;
++extern struct address_space_operations squashfs_aops;
++extern struct address_space_operations squashfs_aops_4K;
++extern struct file_operations squashfs_dir_ops;
++extern struct inode_operations squashfs_dir_inode_ops;
++#else
++#define SQSH_EXTERN static
++#endif
++
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk);
++#else
++static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk)
++{
++ return 0;
++}
++#endif
++
++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk);
++#else
++static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
++{
++ return 0;
++}
++#endif
+diff --new-file -urp linux-2.4.32/include/linux/fs.h linux-2.4.32-squashfs3.0/include/linux/fs.h
+--- linux-2.4.32/include/linux/fs.h 2005-04-04 02:42:20.000000000 +0100
++++ linux-2.4.32-squashfs3.0/include/linux/fs.h 2006-03-07 21:12:36.000000000 +0000
+@@ -324,6 +324,7 @@ extern void set_bh_page(struct buffer_he
+ #include <linux/usbdev_fs_i.h>
+ #include <linux/jffs2_fs_i.h>
+ #include <linux/cramfs_fs_sb.h>
++#include <linux/squashfs_fs_i.h>
+
+ /*
+ * Attribute flags. These should be or-ed together to figure out what
+@@ -519,6 +520,7 @@ struct inode {
+ struct socket socket_i;
+ struct usbdev_inode_info usbdev_i;
+ struct jffs2_inode_info jffs2_i;
++ struct squashfs_inode_info squashfs_i;
+ void *generic_ip;
+ } u;
+ };
+@@ -734,6 +736,7 @@ struct nameidata {
+ #include <linux/usbdev_fs_sb.h>
+ #include <linux/cramfs_fs_sb.h>
+ #include <linux/jffs2_fs_sb.h>
++#include <linux/squashfs_fs_sb.h>
+
+ extern struct list_head super_blocks;
+ extern spinlock_t sb_lock;
+@@ -793,6 +796,7 @@ struct super_block {
+ struct usbdev_sb_info usbdevfs_sb;
+ struct jffs2_sb_info jffs2_sb;
+ struct cramfs_sb_info cramfs_sb;
++ struct squashfs_sb_info squashfs_sb;
+ void *generic_sbp;
+ } u;
+ /*
+diff --new-file -urp linux-2.4.32/include/linux/squashfs_fs.h linux-2.4.32-squashfs3.0/include/linux/squashfs_fs.h
+--- linux-2.4.32/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-squashfs3.0/include/linux/squashfs_fs.h 2006-03-07 21:12:36.000000000 +0000
+@@ -0,0 +1,915 @@
++#ifndef SQUASHFS_FS
++#define SQUASHFS_FS
++
++/*
++ * Squashfs
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs_fs.h
++ */
++
++#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++#define CONFIG_SQUASHFS_2_0_COMPATIBILITY
++#endif
++
++#ifdef CONFIG_SQUASHFS_VMALLOC
++#define SQUASHFS_ALLOC(a) vmalloc(a)
++#define SQUASHFS_FREE(a) vfree(a)
++#else
++#define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL)
++#define SQUASHFS_FREE(a) kfree(a)
++#endif
++#ifdef CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
++#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
++#else
++#define SQUASHFS_CACHED_FRAGMENTS 3
++#endif
++#define SQUASHFS_MAJOR 3
++#define SQUASHFS_MINOR 0
++#define SQUASHFS_MAGIC 0x73717368
++#define SQUASHFS_MAGIC_SWAP 0x68737173
++#define SQUASHFS_START 0
++
++/* size of metadata (inode and directory) blocks */
++#define SQUASHFS_METADATA_SIZE 8192
++#define SQUASHFS_METADATA_LOG 13
++
++/* default size of data blocks */
++#define SQUASHFS_FILE_SIZE 65536
++#define SQUASHFS_FILE_LOG 16
++
++#define SQUASHFS_FILE_MAX_SIZE 65536
++
++/* Max number of uids and gids */
++#define SQUASHFS_UIDS 256
++#define SQUASHFS_GUIDS 255
++
++/* Max length of filename (not 255) */
++#define SQUASHFS_NAME_LEN 256
++
++#define SQUASHFS_INVALID ((long long) 0xffffffffffff)
++#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff)
++#define SQUASHFS_INVALID_BLK ((long long) -1)
++#define SQUASHFS_USED_BLK ((long long) -2)
++
++/* Filesystem flags */
++#define SQUASHFS_NOI 0
++#define SQUASHFS_NOD 1
++#define SQUASHFS_CHECK 2
++#define SQUASHFS_NOF 3
++#define SQUASHFS_NO_FRAG 4
++#define SQUASHFS_ALWAYS_FRAG 5
++#define SQUASHFS_DUPLICATE 6
++
++#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1)
++
++#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_NOI)
++
++#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_NOD)
++
++#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_NOF)
++
++#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_NO_FRAG)
++
++#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_ALWAYS_FRAG)
++
++#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_DUPLICATE)
++
++#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_CHECK)
++
++#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
++ duplicate_checking) (noi | (nod << 1) | (check_data << 2) \
++ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
++ (duplicate_checking << 6))
++
++/* Max number of types and file types */
++#define SQUASHFS_DIR_TYPE 1
++#define SQUASHFS_FILE_TYPE 2
++#define SQUASHFS_SYMLINK_TYPE 3
++#define SQUASHFS_BLKDEV_TYPE 4
++#define SQUASHFS_CHRDEV_TYPE 5
++#define SQUASHFS_FIFO_TYPE 6
++#define SQUASHFS_SOCKET_TYPE 7
++#define SQUASHFS_LDIR_TYPE 8
++#define SQUASHFS_LREG_TYPE 9
++
++/* 1.0 filesystem type definitions */
++#define SQUASHFS_TYPES 5
++#define SQUASHFS_IPC_TYPE 0
++
++/* Flag whether block is compressed or uncompressed, bit is set if block is
++ * uncompressed */
++#define SQUASHFS_COMPRESSED_BIT (1 << 15)
++
++#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
++ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
++
++#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT))
++
++#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24)
++
++#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \
++ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \
++ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
++
++#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
++
++/*
++ * Inode number ops. Inodes consist of a compressed block number, and an
++ * uncompressed offset within that block
++ */
++#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16))
++
++#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff))
++
++#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\
++ << 16) + (B)))
++
++/* Compute 32 bit VFS inode number from squashfs inode number */
++#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \
++ ((b) >> 2) + 1))
++/* XXX */
++
++/* Translate between VFS mode and squashfs mode */
++#define SQUASHFS_MODE(a) ((a) & 0xfff)
++
++/* fragment and fragment table defines */
++#define SQUASHFS_FRAGMENT_BYTES(A) (A * sizeof(struct squashfs_fragment_entry))
++
++#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \
++ SQUASHFS_METADATA_SIZE - 1) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\
++ sizeof(long long))
++
++/* cached data constants for filesystem */
++#define SQUASHFS_CACHED_BLKS 8
++
++#define SQUASHFS_MAX_FILE_SIZE_LOG 64
++
++#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \
++ (SQUASHFS_MAX_FILE_SIZE_LOG - 2))
++
++#define SQUASHFS_MARKER_BYTE 0xff
++
++/* meta index cache */
++#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
++#define SQUASHFS_META_ENTRIES 31
++#define SQUASHFS_META_NUMBER 8
++#define SQUASHFS_SLOTS 4
++
++struct meta_entry {
++ long long data_block;
++ unsigned int index_block;
++ unsigned short offset;
++ unsigned short pad;
++};
++
++struct meta_index {
++ unsigned int inode_number;
++ unsigned int offset;
++ unsigned short entries;
++ unsigned short skip;
++ unsigned short locked;
++ unsigned short pad;
++ struct meta_entry meta_entry[SQUASHFS_META_ENTRIES];
++};
++
++
++/*
++ * definitions for structures on disk
++ */
++
++typedef long long squashfs_block_t;
++typedef long long squashfs_inode_t;
++
++struct squashfs_super_block {
++ unsigned int s_magic;
++ unsigned int inodes;
++ unsigned int bytes_used_2;
++ unsigned int uid_start_2;
++ unsigned int guid_start_2;
++ unsigned int inode_table_start_2;
++ unsigned int directory_table_start_2;
++ unsigned int s_major:16;
++ unsigned int s_minor:16;
++ unsigned int block_size_1:16;
++ unsigned int block_log:16;
++ unsigned int flags:8;
++ unsigned int no_uids:8;
++ unsigned int no_guids:8;
++ unsigned int mkfs_time /* time of filesystem creation */;
++ squashfs_inode_t root_inode;
++ unsigned int block_size;
++ unsigned int fragments;
++ unsigned int fragment_table_start_2;
++ long long bytes_used;
++ long long uid_start;
++ long long guid_start;
++ long long inode_table_start;
++ long long directory_table_start;
++ long long fragment_table_start;
++ long long unused;
++} __attribute__ ((packed));
++
++struct squashfs_dir_index {
++ unsigned int index;
++ unsigned int start_block;
++ unsigned char size;
++ unsigned char name[0];
++} __attribute__ ((packed));
++
++#define SQUASHFS_BASE_INODE_HEADER \
++ unsigned int inode_type:4; \
++ unsigned int mode:12; \
++ unsigned int uid:8; \
++ unsigned int guid:8; \
++ unsigned int mtime; \
++ unsigned int inode_number;
++
++struct squashfs_base_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ unsigned short rdev;
++} __attribute__ ((packed));
++
++struct squashfs_symlink_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ unsigned short symlink_size;
++ char symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ squashfs_block_t start_block;
++ unsigned int fragment;
++ unsigned int offset;
++ unsigned int file_size;
++ unsigned short block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_lreg_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ squashfs_block_t start_block;
++ unsigned int fragment;
++ unsigned int offset;
++ long long file_size;
++ unsigned short block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ unsigned int file_size:19;
++ unsigned int offset:13;
++ unsigned int start_block;
++ unsigned int parent_inode;
++} __attribute__ ((packed));
++
++struct squashfs_ldir_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ unsigned int file_size:27;
++ unsigned int offset:13;
++ unsigned int start_block;
++ unsigned int i_count:16;
++ unsigned int parent_inode;
++ struct squashfs_dir_index index[0];
++} __attribute__ ((packed));
++
++union squashfs_inode_header {
++ struct squashfs_base_inode_header base;
++ struct squashfs_dev_inode_header dev;
++ struct squashfs_symlink_inode_header symlink;
++ struct squashfs_reg_inode_header reg;
++ struct squashfs_lreg_inode_header lreg;
++ struct squashfs_dir_inode_header dir;
++ struct squashfs_ldir_inode_header ldir;
++ struct squashfs_ipc_inode_header ipc;
++};
++
++struct squashfs_dir_entry {
++ unsigned int offset:13;
++ unsigned int type:3;
++ unsigned int size:8;
++ int inode_number:16;
++ char name[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_header {
++ unsigned int count:8;
++ unsigned int start_block;
++ unsigned int inode_number;
++} __attribute__ ((packed));
++
++struct squashfs_fragment_entry {
++ long long start_block;
++ unsigned int size;
++ unsigned int unused;
++} __attribute__ ((packed));
++
++extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
++extern int squashfs_uncompress_init(void);
++extern int squashfs_uncompress_exit(void);
++
++/*
++ * macros to convert each packed bitfield structure from little endian to big
++ * endian and vice versa. These are needed when creating or using a filesystem
++ * on a machine with different byte ordering to the target architecture.
++ *
++ */
++
++#define SQUASHFS_SWAP_START \
++ int bits;\
++ int b_pos;\
++ unsigned long long val;\
++ unsigned char *s;\
++ unsigned char *d;
++
++#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\
++ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
++ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
++ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\
++ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\
++ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\
++ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\
++ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\
++ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
++ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
++ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
++ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
++ SQUASHFS_SWAP((s)->flags, d, 288, 8);\
++ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
++ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
++ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
++ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
++ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
++ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
++ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\
++ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\
++ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\
++ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\
++ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\
++ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\
++ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\
++ SQUASHFS_SWAP((s)->unused, d, 888, 64);\
++}
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
++ SQUASHFS_MEMSET(s, d, n);\
++ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++ SQUASHFS_SWAP((s)->uid, d, 16, 8);\
++ SQUASHFS_SWAP((s)->guid, d, 24, 8);\
++ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
++ SQUASHFS_SWAP((s)->inode_number, d, 64, 32);
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_ipc_inode_header))\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++}
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_dev_inode_header)); \
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_symlink_inode_header));\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_reg_inode_header));\
++ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\
++ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\
++ SQUASHFS_SWAP((s)->offset, d, 192, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\
++}
++
++#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_lreg_inode_header));\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\
++ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\
++ SQUASHFS_SWAP((s)->offset, d, 224, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_dir_inode_header));\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\
++ SQUASHFS_SWAP((s)->offset, d, 147, 13);\
++ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\
++ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\
++}
++
++#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_ldir_inode_header));\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\
++ SQUASHFS_SWAP((s)->offset, d, 155, 13);\
++ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\
++ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\
++ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\
++ SQUASHFS_SWAP((s)->index, d, 0, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\
++ SQUASHFS_SWAP((s)->size, d, 64, 8);\
++}
++
++#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\
++ SQUASHFS_SWAP((s)->count, d, 0, 8);\
++ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\
++ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\
++ SQUASHFS_SWAP((s)->offset, d, 0, 13);\
++ SQUASHFS_SWAP((s)->type, d, 13, 3);\
++ SQUASHFS_SWAP((s)->size, d, 16, 8);\
++ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\
++ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\
++ SQUASHFS_SWAP((s)->size, d, 64, 32);\
++}
++
++#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
++ int entry;\
++ int bit_position;\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, n * 2);\
++ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++ 16)\
++ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
++}
++
++#define SQUASHFS_SWAP_INTS(s, d, n) {\
++ int entry;\
++ int bit_position;\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, n * 4);\
++ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++ 32)\
++ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
++}
++
++#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\
++ int entry;\
++ int bit_position;\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, n * 8);\
++ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++ 64)\
++ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\
++}
++
++#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
++ int entry;\
++ int bit_position;\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, n * bits / 8);\
++ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++ bits)\
++ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
++
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++
++struct squashfs_base_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned int type:4;
++ unsigned int offset:4;
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned short rdev;
++} __attribute__ ((packed));
++
++struct squashfs_symlink_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned short symlink_size;
++ char symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned int mtime;
++ unsigned int start_block;
++ unsigned int file_size:32;
++ unsigned short block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned int file_size:19;
++ unsigned int offset:13;
++ unsigned int mtime;
++ unsigned int start_block:24;
++} __attribute__ ((packed));
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
++ SQUASHFS_MEMSET(s, d, n);\
++ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++ SQUASHFS_SWAP((s)->uid, d, 16, 4);\
++ SQUASHFS_SWAP((s)->guid, d, 20, 4);
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_ipc_inode_header_1));\
++ SQUASHFS_SWAP((s)->type, d, 24, 4);\
++ SQUASHFS_SWAP((s)->offset, d, 28, 4);\
++}
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_dev_inode_header_1));\
++ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_symlink_inode_header_1));\
++ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_reg_inode_header_1));\
++ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_dir_inode_header_1));\
++ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
++ SQUASHFS_SWAP((s)->offset, d, 43, 13);\
++ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
++}
++
++#endif
++
++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++
++struct squashfs_dir_index_2 {
++ unsigned int index:27;
++ unsigned int start_block:29;
++ unsigned char size;
++ unsigned char name[0];
++} __attribute__ ((packed));
++
++struct squashfs_base_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned short rdev;
++} __attribute__ ((packed));
++
++struct squashfs_symlink_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned short symlink_size;
++ char symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned int mtime;
++ unsigned int start_block;
++ unsigned int fragment;
++ unsigned int offset;
++ unsigned int file_size:32;
++ unsigned short block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned int file_size:19;
++ unsigned int offset:13;
++ unsigned int mtime;
++ unsigned int start_block:24;
++} __attribute__ ((packed));
++
++struct squashfs_ldir_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned int file_size:27;
++ unsigned int offset:13;
++ unsigned int mtime;
++ unsigned int start_block:24;
++ unsigned int i_count:16;
++ struct squashfs_dir_index_2 index[0];
++} __attribute__ ((packed));
++
++union squashfs_inode_header_2 {
++ struct squashfs_base_inode_header_2 base;
++ struct squashfs_dev_inode_header_2 dev;
++ struct squashfs_symlink_inode_header_2 symlink;
++ struct squashfs_reg_inode_header_2 reg;
++ struct squashfs_dir_inode_header_2 dir;
++ struct squashfs_ldir_inode_header_2 ldir;
++ struct squashfs_ipc_inode_header_2 ipc;
++};
++
++struct squashfs_dir_header_2 {
++ unsigned int count:8;
++ unsigned int start_block:24;
++} __attribute__ ((packed));
++
++struct squashfs_dir_entry_2 {
++ unsigned int offset:13;
++ unsigned int type:3;
++ unsigned int size:8;
++ char name[0];
++} __attribute__ ((packed));
++
++struct squashfs_fragment_entry_2 {
++ unsigned int start_block;
++ unsigned int size;
++} __attribute__ ((packed));
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
++ SQUASHFS_MEMSET(s, d, n);\
++ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++ SQUASHFS_SWAP((s)->uid, d, 16, 8);\
++ SQUASHFS_SWAP((s)->guid, d, 24, 8);\
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
++ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_dev_inode_header_2)); \
++ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_symlink_inode_header_2));\
++ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_reg_inode_header_2));\
++ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
++ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
++ SQUASHFS_SWAP((s)->offset, d, 128, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_dir_inode_header_2));\
++ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
++ SQUASHFS_SWAP((s)->offset, d, 51, 13);\
++ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
++}
++
++#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_ldir_inode_header_2));\
++ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
++ SQUASHFS_SWAP((s)->offset, d, 59, 13);\
++ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
++ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
++ SQUASHFS_SWAP((s)->index, d, 0, 27);\
++ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
++ SQUASHFS_SWAP((s)->size, d, 56, 8);\
++}
++#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
++ SQUASHFS_SWAP((s)->count, d, 0, 8);\
++ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
++}
++
++#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
++ SQUASHFS_SWAP((s)->offset, d, 0, 13);\
++ SQUASHFS_SWAP((s)->type, d, 13, 3);\
++ SQUASHFS_SWAP((s)->size, d, 16, 8);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
++ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
++ SQUASHFS_SWAP((s)->size, d, 32, 32);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
++
++/* fragment and fragment table defines */
++#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2))
++
++#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \
++ SQUASHFS_METADATA_SIZE - 1) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\
++ sizeof(int))
++
++#endif
++
++#ifdef __KERNEL__
++
++/*
++ * macros used to swap each structure entry, taking into account
++ * bitfields and different bitfield placing conventions on differing
++ * architectures
++ */
++
++#include <asm/byteorder.h>
++
++#ifdef __BIG_ENDIAN
++ /* convert from little endian to big endian */
++#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
++ tbits, b_pos)
++#else
++ /* convert from big endian to little endian */
++#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
++ tbits, 64 - tbits - b_pos)
++#endif
++
++#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
++ b_pos = pos % 8;\
++ val = 0;\
++ s = (unsigned char *)p + (pos / 8);\
++ d = ((unsigned char *) &val) + 7;\
++ for(bits = 0; bits < (tbits + b_pos); bits += 8) \
++ *d-- = *s++;\
++ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
++}
++
++#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n);
++
++#endif
++#endif
+diff --new-file -urp linux-2.4.32/include/linux/squashfs_fs_i.h linux-2.4.32-squashfs3.0/include/linux/squashfs_fs_i.h
+--- linux-2.4.32/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-squashfs3.0/include/linux/squashfs_fs_i.h 2006-03-07 21:12:36.000000000 +0000
+@@ -0,0 +1,44 @@
++#ifndef SQUASHFS_FS_I
++#define SQUASHFS_FS_I
++/*
++ * Squashfs
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs_fs_i.h
++ */
++
++struct squashfs_inode_info {
++ long long start_block;
++ unsigned int offset;
++ union {
++ struct {
++ long long fragment_start_block;
++ unsigned int fragment_size;
++ unsigned int fragment_offset;
++ long long block_list_start;
++ } s1;
++ struct {
++ long long directory_index_start;
++ unsigned int directory_index_offset;
++ unsigned int directory_index_count;
++ unsigned int parent_inode;
++ } s2;
++ } u;
++};
++#endif
+diff --new-file -urp linux-2.4.32/include/linux/squashfs_fs_sb.h linux-2.4.32-squashfs3.0/include/linux/squashfs_fs_sb.h
+--- linux-2.4.32/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-squashfs3.0/include/linux/squashfs_fs_sb.h 2006-03-07 21:12:36.000000000 +0000
+@@ -0,0 +1,74 @@
++#ifndef SQUASHFS_FS_SB
++#define SQUASHFS_FS_SB
++/*
++ * Squashfs
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs_fs_sb.h
++ */
++
++#include <linux/squashfs_fs.h>
++
++struct squashfs_cache {
++ long long block;
++ int length;
++ long long next_index;
++ char *data;
++};
++
++struct squashfs_fragment_cache {
++ long long block;
++ int length;
++ unsigned int locked;
++ char *data;
++};
++
++struct squashfs_sb_info {
++ struct squashfs_super_block sblk;
++ int devblksize;
++ int devblksize_log2;
++ int swap;
++ struct squashfs_cache *block_cache;
++ struct squashfs_fragment_cache *fragment;
++ int next_cache;
++ int next_fragment;
++ int next_meta_index;
++ unsigned int *uid;
++ unsigned int *guid;
++ long long *fragment_index;
++ unsigned int *fragment_index_2;
++ unsigned int read_size;
++ char *read_data;
++ char *read_page;
++ struct semaphore read_data_mutex;
++ struct semaphore read_page_mutex;
++ struct semaphore block_cache_mutex;
++ struct semaphore fragment_mutex;
++ struct semaphore meta_index_mutex;
++ wait_queue_head_t waitq;
++ wait_queue_head_t fragment_wait_queue;
++ struct meta_index *meta_index;
++ struct inode *(*iget)(struct super_block *s, squashfs_inode_t \
++ inode);
++ long long (*read_blocklist)(struct inode *inode, int \
++ index, int readahead_blks, char *block_list, \
++ unsigned short **block_p, unsigned int *bsize);
++ int (*read_fragment_index_table)(struct super_block *s);
++};
++#endif
+diff --new-file -urp linux-2.4.32/init/do_mounts.c linux-2.4.32-squashfs3.0/init/do_mounts.c
+--- linux-2.4.32/init/do_mounts.c 2003-11-28 18:26:21.000000000 +0000
++++ linux-2.4.32-squashfs3.0/init/do_mounts.c 2006-03-07 21:12:36.000000000 +0000
+@@ -15,6 +15,7 @@
+ #include <linux/minix_fs.h>
+ #include <linux/ext2_fs.h>
+ #include <linux/romfs_fs.h>
++#include <linux/squashfs_fs.h>
+ #include <linux/cramfs_fs.h>
+
+ #define BUILD_CRAMDISK
+@@ -476,6 +477,7 @@ static int __init crd_load(int in_fd, in
+ * minix
+ * ext2
+ * romfs
++ * squashfs
+ * cramfs
+ * gzip
+ */
+@@ -486,6 +488,7 @@ identify_ramdisk_image(int fd, int start
+ struct minix_super_block *minixsb;
+ struct ext2_super_block *ext2sb;
+ struct romfs_super_block *romfsb;
++ struct squashfs_super_block *squashfsb;
+ struct cramfs_super *cramfsb;
+ int nblocks = -1;
+ unsigned char *buf;
+@@ -497,6 +500,7 @@ identify_ramdisk_image(int fd, int start
+ minixsb = (struct minix_super_block *) buf;
+ ext2sb = (struct ext2_super_block *) buf;
+ romfsb = (struct romfs_super_block *) buf;
++ squashfsb = (struct squashfs_super_block *) buf;
+ cramfsb = (struct cramfs_super *) buf;
+ memset(buf, 0xe5, size);
+
+@@ -535,6 +539,15 @@ identify_ramdisk_image(int fd, int start
+ goto done;
+ }
+
++ /* squashfs is at block zero too */
++ if (squashfsb->s_magic == SQUASHFS_MAGIC) {
++ printk(KERN_NOTICE
++ "RAMDISK: squashfs filesystem found at block %d\n",
++ start_block);
++ nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
++ goto done;
++ }
++
+ /*
+ * Read block 1 to test for minix and ext2 superblock
+ */
+diff --new-file -urp linux-2.4.32/lib/Config.in linux-2.4.32-squashfs3.0/lib/Config.in
+--- linux-2.4.32/lib/Config.in 2003-11-28 18:26:21.000000000 +0000
++++ linux-2.4.32-squashfs3.0/lib/Config.in 2006-03-07 21:12:36.000000000 +0000
+@@ -10,6 +10,7 @@ tristate 'CRC32 functions' CONFIG_CRC32
+ # Do we need the compression support?
+ #
+ if [ "$CONFIG_CRAMFS" = "y" -o \
++ "$CONFIG_SQUASHFS" = "y" -o \
+ "$CONFIG_PPP_DEFLATE" = "y" -o \
+ "$CONFIG_CRYPTO_DEFLATE" = "y" -o \
+ "$CONFIG_JFFS2_FS" = "y" -o \
+@@ -17,6 +18,7 @@ if [ "$CONFIG_CRAMFS" = "y" -o \
+ define_tristate CONFIG_ZLIB_INFLATE y
+ else
+ if [ "$CONFIG_CRAMFS" = "m" -o \
++ "$CONFIG_SQUASHFS" = "m" -o \
+ "$CONFIG_PPP_DEFLATE" = "m" -o \
+ "$CONFIG_CRYPTO_DEFLATE" = "m" -o \
+ "$CONFIG_JFFS2_FS" = "m" -o \
diff --git a/target/linux/generic-2.4/patches/002-squashfs_lzma.patch b/target/linux/generic-2.4/patches/002-squashfs_lzma.patch
new file mode 100644
index 0000000000..d534154871
--- /dev/null
+++ b/target/linux/generic-2.4/patches/002-squashfs_lzma.patch
@@ -0,0 +1,883 @@
+diff -Nur linux-2.4.32/fs/squashfs/inode.c linux-2.4.32-owrt/fs/squashfs/inode.c
+--- linux-2.4.32/fs/squashfs/inode.c 2006-03-21 13:06:10.000000000 +0100
++++ linux-2.4.32-owrt/fs/squashfs/inode.c 2006-03-21 13:12:07.000000000 +0100
+@@ -4,6 +4,9 @@
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
+ *
++ * LZMA decompressor support added by Oleg I. Vdovikin
++ * Copyright (c) 2005 Oleg I.Vdovikin <oleg@cs.msu.su>
++ *
+ * 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,
+@@ -21,6 +24,7 @@
+ * inode.c
+ */
+
++#define SQUASHFS_LZMA
+ #include <linux/types.h>
+ #include <linux/squashfs_fs.h>
+ #include <linux/module.h>
+@@ -40,6 +44,20 @@
+
+ #include "squashfs.h"
+
++#ifdef SQUASHFS_LZMA
++#include "LzmaDecode.h"
++
++/* default LZMA settings, should be in sync with mksquashfs */
++#define LZMA_LC 3
++#define LZMA_LP 0
++#define LZMA_PB 2
++
++#define LZMA_WORKSPACE_SIZE ((LZMA_BASE_SIZE + \
++ (LZMA_LIT_SIZE << (LZMA_LC + LZMA_LP))) * sizeof(CProb))
++
++#endif
++
++
+ static struct super_block *squashfs_read_super(struct super_block *, void *, int);
+ static void squashfs_put_super(struct super_block *);
+ static int squashfs_statfs(struct super_block *, struct statfs *);
+@@ -53,7 +71,11 @@
+ int readahead_blks, char *block_list,
+ unsigned short **block_p, unsigned int *bsize);
+
++#ifdef SQUASHFS_LZMA
++static unsigned char lzma_workspace[LZMA_WORKSPACE_SIZE];
++#else
+ static z_stream stream;
++#endif
+
+ static DECLARE_FSTYPE_DEV(squashfs_fs_type, "squashfs", squashfs_read_super);
+
+@@ -229,6 +251,15 @@
+ if (compressed) {
+ int zlib_err;
+
++#ifdef SQUASHFS_LZMA
++ if ((zlib_err = LzmaDecode(lzma_workspace,
++ LZMA_WORKSPACE_SIZE, LZMA_LC, LZMA_LP, LZMA_PB,
++ c_buffer, c_byte, buffer, msblk->read_size, &bytes)) != LZMA_RESULT_OK)
++ {
++ ERROR("lzma returned unexpected result 0x%x\n", zlib_err);
++ bytes = 0;
++ }
++#else
+ stream.next_in = c_buffer;
+ stream.avail_in = c_byte;
+ stream.next_out = buffer;
+@@ -243,6 +274,7 @@
+ bytes = 0;
+ } else
+ bytes = stream.total_out;
++#endif
+
+ up(&msblk->read_data_mutex);
+ }
+@@ -2004,17 +2036,21 @@
+ printk(KERN_INFO "squashfs: version 3.0 (2006/03/15) "
+ "Phillip Lougher\n");
+
++#ifndef SQUASHFS_LZMA
+ if (!(stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
+ ERROR("Failed to allocate zlib workspace\n");
+ return -ENOMEM;
+ }
++#endif
+ return register_filesystem(&squashfs_fs_type);
+ }
+
+
+ static void __exit exit_squashfs_fs(void)
+ {
++#ifndef SQUASHFS_LZMA
+ vfree(stream.workspace);
++#endif
+ unregister_filesystem(&squashfs_fs_type);
+ }
+
+diff -Nur linux-2.4.32/fs/squashfs/LzmaDecode.c linux-2.4.32-owrt/fs/squashfs/LzmaDecode.c
+--- linux-2.4.32/fs/squashfs/LzmaDecode.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-owrt/fs/squashfs/LzmaDecode.c 2006-03-21 13:06:33.000000000 +0100
+@@ -0,0 +1,663 @@
++/*
++ LzmaDecode.c
++ LZMA Decoder
++
++ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
++ http://www.7-zip.org/
++
++ LZMA SDK is licensed under two licenses:
++ 1) GNU Lesser General Public License (GNU LGPL)
++ 2) Common Public License (CPL)
++ It means that you can select one of these two licenses and
++ follow rules of that license.
++
++ SPECIAL EXCEPTION:
++ Igor Pavlov, as the author of this code, expressly permits you to
++ statically or dynamically link your code (or bind by name) to the
++ interfaces of this file without subjecting your linked code to the
++ terms of the CPL or GNU LGPL. Any modifications or additions
++ to this file, however, are subject to the LGPL or CPL terms.
++*/
++
++#include "LzmaDecode.h"
++
++#ifndef Byte
++#define Byte unsigned char
++#endif
++
++#define kNumTopBits 24
++#define kTopValue ((UInt32)1 << kNumTopBits)
++
++#define kNumBitModelTotalBits 11
++#define kBitModelTotal (1 << kNumBitModelTotalBits)
++#define kNumMoveBits 5
++
++typedef struct _CRangeDecoder
++{
++ Byte *Buffer;
++ Byte *BufferLim;
++ UInt32 Range;
++ UInt32 Code;
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *InCallback;
++ int Result;
++ #endif
++ int ExtraBytes;
++} CRangeDecoder;
++
++Byte RangeDecoderReadByte(CRangeDecoder *rd)
++{
++ if (rd->Buffer == rd->BufferLim)
++ {
++ #ifdef _LZMA_IN_CB
++ UInt32 size;
++ rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
++ rd->BufferLim = rd->Buffer + size;
++ if (size == 0)
++ #endif
++ {
++ rd->ExtraBytes = 1;
++ return 0xFF;
++ }
++ }
++ return (*rd->Buffer++);
++}
++
++/* #define ReadByte (*rd->Buffer++) */
++#define ReadByte (RangeDecoderReadByte(rd))
++
++void RangeDecoderInit(CRangeDecoder *rd,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *inCallback
++ #else
++ Byte *stream, UInt32 bufferSize
++ #endif
++ )
++{
++ int i;
++ #ifdef _LZMA_IN_CB
++ rd->InCallback = inCallback;
++ rd->Buffer = rd->BufferLim = 0;
++ #else
++ rd->Buffer = stream;
++ rd->BufferLim = stream + bufferSize;
++ #endif
++ rd->ExtraBytes = 0;
++ rd->Code = 0;
++ rd->Range = (0xFFFFFFFF);
++ for(i = 0; i < 5; i++)
++ rd->Code = (rd->Code << 8) | ReadByte;
++}
++
++#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;
++#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
++#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
++
++UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
++{
++ RC_INIT_VAR
++ UInt32 result = 0;
++ int i;
++ for (i = numTotalBits; i > 0; i--)
++ {
++ /* UInt32 t; */
++ range >>= 1;
++
++ result <<= 1;
++ if (code >= range)
++ {
++ code -= range;
++ result |= 1;
++ }
++ /*
++ t = (code - range) >> 31;
++ t &= 1;
++ code -= range & (t - 1);
++ result = (result + result) | (1 - t);
++ */
++ RC_NORMALIZE
++ }
++ RC_FLUSH_VAR
++ return result;
++}
++
++int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
++{
++ UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
++ if (rd->Code < bound)
++ {
++ rd->Range = bound;
++ *prob += (kBitModelTotal - *prob) >> kNumMoveBits;
++ if (rd->Range < kTopValue)
++ {
++ rd->Code = (rd->Code << 8) | ReadByte;
++ rd->Range <<= 8;
++ }
++ return 0;
++ }
++ else
++ {
++ rd->Range -= bound;
++ rd->Code -= bound;
++ *prob -= (*prob) >> kNumMoveBits;
++ if (rd->Range < kTopValue)
++ {
++ rd->Code = (rd->Code << 8) | ReadByte;
++ rd->Range <<= 8;
++ }
++ return 1;
++ }
++}
++
++#define RC_GET_BIT2(prob, mi, A0, A1) \
++ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
++ if (code < bound) \
++ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
++ else \
++ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
++ RC_NORMALIZE
++
++#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
++
++int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
++{
++ int mi = 1;
++ int i;
++ #ifdef _LZMA_LOC_OPT
++ RC_INIT_VAR
++ #endif
++ for(i = numLevels; i > 0; i--)
++ {
++ #ifdef _LZMA_LOC_OPT
++ CProb *prob = probs + mi;
++ RC_GET_BIT(prob, mi)
++ #else
++ mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
++ #endif
++ }
++ #ifdef _LZMA_LOC_OPT
++ RC_FLUSH_VAR
++ #endif
++ return mi - (1 << numLevels);
++}
++
++int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
++{
++ int mi = 1;
++ int i;
++ int symbol = 0;
++ #ifdef _LZMA_LOC_OPT
++ RC_INIT_VAR
++ #endif
++ for(i = 0; i < numLevels; i++)
++ {
++ #ifdef _LZMA_LOC_OPT
++ CProb *prob = probs + mi;
++ RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
++ #else
++ int bit = RangeDecoderBitDecode(probs + mi, rd);
++ mi = mi + mi + bit;
++ symbol |= (bit << i);
++ #endif
++ }
++ #ifdef _LZMA_LOC_OPT
++ RC_FLUSH_VAR
++ #endif
++ return symbol;
++}
++
++Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
++{
++ int symbol = 1;
++ #ifdef _LZMA_LOC_OPT
++ RC_INIT_VAR
++ #endif
++ do
++ {
++ #ifdef _LZMA_LOC_OPT
++ CProb *prob = probs + symbol;
++ RC_GET_BIT(prob, symbol)
++ #else
++ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
++ #endif
++ }
++ while (symbol < 0x100);
++ #ifdef _LZMA_LOC_OPT
++ RC_FLUSH_VAR
++ #endif
++ return symbol;
++}
++
++Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
++{
++ int symbol = 1;
++ #ifdef _LZMA_LOC_OPT
++ RC_INIT_VAR
++ #endif
++ do
++ {
++ int bit;
++ int matchBit = (matchByte >> 7) & 1;
++ matchByte <<= 1;
++ #ifdef _LZMA_LOC_OPT
++ {
++ CProb *prob = probs + ((1 + matchBit) << 8) + symbol;
++ RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
++ }
++ #else
++ bit = RangeDecoderBitDecode(probs + ((1 + matchBit) << 8) + symbol, rd);
++ symbol = (symbol << 1) | bit;
++ #endif
++ if (matchBit != bit)
++ {
++ while (symbol < 0x100)
++ {
++ #ifdef _LZMA_LOC_OPT
++ CProb *prob = probs + symbol;
++ RC_GET_BIT(prob, symbol)
++ #else
++ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
++ #endif
++ }
++ break;
++ }
++ }
++ while (symbol < 0x100);
++ #ifdef _LZMA_LOC_OPT
++ RC_FLUSH_VAR
++ #endif
++ return symbol;
++}
++
++#define kNumPosBitsMax 4
++#define kNumPosStatesMax (1 << kNumPosBitsMax)
++
++#define kLenNumLowBits 3
++#define kLenNumLowSymbols (1 << kLenNumLowBits)
++#define kLenNumMidBits 3
++#define kLenNumMidSymbols (1 << kLenNumMidBits)
++#define kLenNumHighBits 8
++#define kLenNumHighSymbols (1 << kLenNumHighBits)
++
++#define LenChoice 0
++#define LenChoice2 (LenChoice + 1)
++#define LenLow (LenChoice2 + 1)
++#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
++#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
++#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
++
++int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
++{
++ if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
++ return RangeDecoderBitTreeDecode(p + LenLow +
++ (posState << kLenNumLowBits), kLenNumLowBits, rd);
++ if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
++ return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
++ (posState << kLenNumMidBits), kLenNumMidBits, rd);
++ return kLenNumLowSymbols + kLenNumMidSymbols +
++ RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
++}
++
++#define kNumStates 12
++
++#define kStartPosModelIndex 4
++#define kEndPosModelIndex 14
++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
++
++#define kNumPosSlotBits 6
++#define kNumLenToPosStates 4
++
++#define kNumAlignBits 4
++#define kAlignTableSize (1 << kNumAlignBits)
++
++#define kMatchMinLen 2
++
++#define IsMatch 0
++#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
++#define IsRepG0 (IsRep + kNumStates)
++#define IsRepG1 (IsRepG0 + kNumStates)
++#define IsRepG2 (IsRepG1 + kNumStates)
++#define IsRep0Long (IsRepG2 + kNumStates)
++#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
++#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
++#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
++#define LenCoder (Align + kAlignTableSize)
++#define RepLenCoder (LenCoder + kNumLenProbs)
++#define Literal (RepLenCoder + kNumLenProbs)
++
++#if Literal != LZMA_BASE_SIZE
++StopCompilingDueBUG
++#endif
++
++#ifdef _LZMA_OUT_READ
++
++typedef struct _LzmaVarState
++{
++ CRangeDecoder RangeDecoder;
++ Byte *Dictionary;
++ UInt32 DictionarySize;
++ UInt32 DictionaryPos;
++ UInt32 GlobalPos;
++ UInt32 Reps[4];
++ int lc;
++ int lp;
++ int pb;
++ int State;
++ int PreviousIsMatch;
++ int RemainLen;
++} LzmaVarState;
++
++int LzmaDecoderInit(
++ unsigned char *buffer, UInt32 bufferSize,
++ int lc, int lp, int pb,
++ unsigned char *dictionary, UInt32 dictionarySize,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *inCallback
++ #else
++ unsigned char *inStream, UInt32 inSize
++ #endif
++ )
++{
++ LzmaVarState *vs = (LzmaVarState *)buffer;
++ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
++ UInt32 i;
++ if (bufferSize < numProbs * sizeof(CProb) + sizeof(LzmaVarState))
++ return LZMA_RESULT_NOT_ENOUGH_MEM;
++ vs->Dictionary = dictionary;
++ vs->DictionarySize = dictionarySize;
++ vs->DictionaryPos = 0;
++ vs->GlobalPos = 0;
++ vs->Reps[0] = vs->Reps[1] = vs->Reps[2] = vs->Reps[3] = 1;
++ vs->lc = lc;
++ vs->lp = lp;
++ vs->pb = pb;
++ vs->State = 0;
++ vs->PreviousIsMatch = 0;
++ vs->RemainLen = 0;
++ dictionary[dictionarySize - 1] = 0;
++ for (i = 0; i < numProbs; i++)
++ p[i] = kBitModelTotal >> 1;
++ RangeDecoderInit(&vs->RangeDecoder,
++ #ifdef _LZMA_IN_CB
++ inCallback
++ #else
++ inStream, inSize
++ #endif
++ );
++ return LZMA_RESULT_OK;
++}
++
++int LzmaDecode(unsigned char *buffer,
++ unsigned char *outStream, UInt32 outSize,
++ UInt32 *outSizeProcessed)
++{
++ LzmaVarState *vs = (LzmaVarState *)buffer;
++ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
++ CRangeDecoder rd = vs->RangeDecoder;
++ int state = vs->State;
++ int previousIsMatch = vs->PreviousIsMatch;
++ Byte previousByte;
++ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
++ UInt32 nowPos = 0;
++ UInt32 posStateMask = (1 << (vs->pb)) - 1;
++ UInt32 literalPosMask = (1 << (vs->lp)) - 1;
++ int lc = vs->lc;
++ int len = vs->RemainLen;
++ UInt32 globalPos = vs->GlobalPos;
++
++ Byte *dictionary = vs->Dictionary;
++ UInt32 dictionarySize = vs->DictionarySize;
++ UInt32 dictionaryPos = vs->DictionaryPos;
++
++ if (len == -1)
++ {
++ *outSizeProcessed = 0;
++ return LZMA_RESULT_OK;
++ }
++
++ while(len > 0 && nowPos < outSize)
++ {
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ len--;
++ }
++ if (dictionaryPos == 0)
++ previousByte = dictionary[dictionarySize - 1];
++ else
++ previousByte = dictionary[dictionaryPos - 1];
++#else
++
++int LzmaDecode(
++ Byte *buffer, UInt32 bufferSize,
++ int lc, int lp, int pb,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *inCallback,
++ #else
++ unsigned char *inStream, UInt32 inSize,
++ #endif
++ unsigned char *outStream, UInt32 outSize,
++ UInt32 *outSizeProcessed)
++{
++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
++ CProb *p = (CProb *)buffer;
++ CRangeDecoder rd;
++ UInt32 i;
++ int state = 0;
++ int previousIsMatch = 0;
++ Byte previousByte = 0;
++ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
++ UInt32 nowPos = 0;
++ UInt32 posStateMask = (1 << pb) - 1;
++ UInt32 literalPosMask = (1 << lp) - 1;
++ int len = 0;
++ if (bufferSize < numProbs * sizeof(CProb))
++ return LZMA_RESULT_NOT_ENOUGH_MEM;
++ for (i = 0; i < numProbs; i++)
++ p[i] = kBitModelTotal >> 1;
++ RangeDecoderInit(&rd,
++ #ifdef _LZMA_IN_CB
++ inCallback
++ #else
++ inStream, inSize
++ #endif
++ );
++#endif
++
++ *outSizeProcessed = 0;
++ while(nowPos < outSize)
++ {
++ int posState = (int)(
++ (nowPos
++ #ifdef _LZMA_OUT_READ
++ + globalPos
++ #endif
++ )
++ & posStateMask);
++ #ifdef _LZMA_IN_CB
++ if (rd.Result != LZMA_RESULT_OK)
++ return rd.Result;
++ #endif
++ if (rd.ExtraBytes != 0)
++ return LZMA_RESULT_DATA_ERROR;
++ if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
++ {
++ CProb *probs = p + Literal + (LZMA_LIT_SIZE *
++ (((
++ (nowPos
++ #ifdef _LZMA_OUT_READ
++ + globalPos
++ #endif
++ )
++ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
++
++ if (state < 4) state = 0;
++ else if (state < 10) state -= 3;
++ else state -= 6;
++ if (previousIsMatch)
++ {
++ Byte matchByte;
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ matchByte = dictionary[pos];
++ #else
++ matchByte = outStream[nowPos - rep0];
++ #endif
++ previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
++ previousIsMatch = 0;
++ }
++ else
++ previousByte = LzmaLiteralDecode(probs, &rd);
++ outStream[nowPos++] = previousByte;
++ #ifdef _LZMA_OUT_READ
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #endif
++ }
++ else
++ {
++ previousIsMatch = 1;
++ if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
++ {
++ if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
++ {
++ if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
++ {
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos;
++ #endif
++ if (
++ (nowPos
++ #ifdef _LZMA_OUT_READ
++ + globalPos
++ #endif
++ )
++ == 0)
++ return LZMA_RESULT_DATA_ERROR;
++ state = state < 7 ? 9 : 11;
++ #ifdef _LZMA_OUT_READ
++ pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ previousByte = dictionary[pos];
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #else
++ previousByte = outStream[nowPos - rep0];
++ #endif
++ outStream[nowPos++] = previousByte;
++ continue;
++ }
++ }
++ else
++ {
++ UInt32 distance;
++ if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
++ distance = rep1;
++ else
++ {
++ if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
++ distance = rep2;
++ else
++ {
++ distance = rep3;
++ rep3 = rep2;
++ }
++ rep2 = rep1;
++ }
++ rep1 = rep0;
++ rep0 = distance;
++ }
++ len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
++ state = state < 7 ? 8 : 11;
++ }
++ else
++ {
++ int posSlot;
++ rep3 = rep2;
++ rep2 = rep1;
++ rep1 = rep0;
++ state = state < 7 ? 7 : 10;
++ len = LzmaLenDecode(p + LenCoder, &rd, posState);
++ posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
++ kNumPosSlotBits), kNumPosSlotBits, &rd);
++ if (posSlot >= kStartPosModelIndex)
++ {
++ int numDirectBits = ((posSlot >> 1) - 1);
++ rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
++ if (posSlot < kEndPosModelIndex)
++ {
++ rep0 += RangeDecoderReverseBitTreeDecode(
++ p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
++ }
++ else
++ {
++ rep0 += RangeDecoderDecodeDirectBits(&rd,
++ numDirectBits - kNumAlignBits) << kNumAlignBits;
++ rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
++ }
++ }
++ else
++ rep0 = posSlot;
++ rep0++;
++ }
++ if (rep0 == (UInt32)(0))
++ {
++ /* it's for stream version */
++ len = -1;
++ break;
++ }
++ if (rep0 > nowPos
++ #ifdef _LZMA_OUT_READ
++ + globalPos
++ #endif
++ )
++ {
++ return LZMA_RESULT_DATA_ERROR;
++ }
++ len += kMatchMinLen;
++ do
++ {
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ previousByte = dictionary[pos];
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #else
++ previousByte = outStream[nowPos - rep0];
++ #endif
++ outStream[nowPos++] = previousByte;
++ len--;
++ }
++ while(len > 0 && nowPos < outSize);
++ }
++ }
++
++ #ifdef _LZMA_OUT_READ
++ vs->RangeDecoder = rd;
++ vs->DictionaryPos = dictionaryPos;
++ vs->GlobalPos = globalPos + nowPos;
++ vs->Reps[0] = rep0;
++ vs->Reps[1] = rep1;
++ vs->Reps[2] = rep2;
++ vs->Reps[3] = rep3;
++ vs->State = state;
++ vs->PreviousIsMatch = previousIsMatch;
++ vs->RemainLen = len;
++ #endif
++
++ *outSizeProcessed = nowPos;
++ return LZMA_RESULT_OK;
++}
+diff -Nur linux-2.4.32/fs/squashfs/LzmaDecode.h linux-2.4.32-owrt/fs/squashfs/LzmaDecode.h
+--- linux-2.4.32/fs/squashfs/LzmaDecode.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32-owrt/fs/squashfs/LzmaDecode.h 2006-03-21 13:06:33.000000000 +0100
+@@ -0,0 +1,100 @@
++/*
++ LzmaDecode.h
++ LZMA Decoder interface
++
++ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
++ http://www.7-zip.org/
++
++ LZMA SDK is licensed under two licenses:
++ 1) GNU Lesser General Public License (GNU LGPL)
++ 2) Common Public License (CPL)
++ It means that you can select one of these two licenses and
++ follow rules of that license.
++
++ SPECIAL EXCEPTION:
++ Igor Pavlov, as the author of this code, expressly permits you to
++ statically or dynamically link your code (or bind by name) to the
++ interfaces of this file without subjecting your linked code to the
++ terms of the CPL or GNU LGPL. Any modifications or additions
++ to this file, however, are subject to the LGPL or CPL terms.
++*/
++
++#ifndef __LZMADECODE_H
++#define __LZMADECODE_H
++
++/* #define _LZMA_IN_CB */
++/* Use callback for input data */
++
++/* #define _LZMA_OUT_READ */
++/* Use read function for output data */
++
++/* #define _LZMA_PROB32 */
++/* It can increase speed on some 32-bit CPUs,
++ but memory usage will be doubled in that case */
++
++/* #define _LZMA_LOC_OPT */
++/* Enable local speed optimizations inside code */
++
++#ifndef UInt32
++#ifdef _LZMA_UINT32_IS_ULONG
++#define UInt32 unsigned long
++#else
++#define UInt32 unsigned int
++#endif
++#endif
++
++#ifdef _LZMA_PROB32
++#define CProb UInt32
++#else
++#define CProb unsigned short
++#endif
++
++#define LZMA_RESULT_OK 0
++#define LZMA_RESULT_DATA_ERROR 1
++#define LZMA_RESULT_NOT_ENOUGH_MEM 2
++
++#ifdef _LZMA_IN_CB
++typedef struct _ILzmaInCallback
++{
++ int (*Read)(void *object, unsigned char **buffer, UInt32 *bufferSize);
++} ILzmaInCallback;
++#endif
++
++#define LZMA_BASE_SIZE 1846
++#define LZMA_LIT_SIZE 768
++
++/*
++bufferSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)))* sizeof(CProb)
++bufferSize += 100 in case of _LZMA_OUT_READ
++by default CProb is unsigned short,
++but if specify _LZMA_PROB_32, CProb will be UInt32(unsigned int)
++*/
++
++#ifdef _LZMA_OUT_READ
++int LzmaDecoderInit(
++ unsigned char *buffer, UInt32 bufferSize,
++ int lc, int lp, int pb,
++ unsigned char *dictionary, UInt32 dictionarySize,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *inCallback
++ #else
++ unsigned char *inStream, UInt32 inSize
++ #endif
++);
++#endif
++
++int LzmaDecode(
++ unsigned char *buffer,
++ #ifndef _LZMA_OUT_READ
++ UInt32 bufferSize,
++ int lc, int lp, int pb,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *inCallback,
++ #else
++ unsigned char *inStream, UInt32 inSize,
++ #endif
++ #endif
++ unsigned char *outStream, UInt32 outSize,
++ UInt32 *outSizeProcessed);
++
++#endif
+diff -Nur linux-2.4.32/fs/squashfs/Makefile linux-2.4.32-owrt/fs/squashfs/Makefile
+--- linux-2.4.32/fs/squashfs/Makefile 2006-03-21 13:06:10.000000000 +0100
++++ linux-2.4.32-owrt/fs/squashfs/Makefile 2006-03-21 13:12:39.000000000 +0100
+@@ -4,7 +4,7 @@
+
+ O_TARGET := squashfs.o
+
+-obj-y := inode.o squashfs2_0.o
++obj-y := inode.o squashfs2_0.o LzmaDecode.o
+
+ obj-m := $(O_TARGET)
+
diff --git a/target/linux/generic-2.4/patches/003-jffs2_compression.patch b/target/linux/generic-2.4/patches/003-jffs2_compression.patch
new file mode 100644
index 0000000000..56c5b3cbc0
--- /dev/null
+++ b/target/linux/generic-2.4/patches/003-jffs2_compression.patch
@@ -0,0 +1,9119 @@
+diff -Nur linux-mips-cvs/Documentation/Configure.help linux-mips/Documentation/Configure.help
+--- linux-mips-cvs/Documentation/Configure.help 2005-01-20 03:19:21.000000000 +0100
++++ linux-mips/Documentation/Configure.help 2005-02-07 05:08:35.000000000 +0100
+@@ -17528,6 +17528,32 @@
+ If reporting bugs, please try to have available a full dump of the
+ messages at debug level 1 while the misbehaviour was occurring.
+
++ARMLIB compression support for BBC (EXPERIMENTAL)
++CONFIG_JFFS2_BBC_ARMLIB
++ This enables ARMLIB support for BBC.
++
++LZO1X-* compression support for BBC (EXPERIMENTAL)
++CONFIG_JFFS2_BBC_LZO
++ This enables LZO1X-1 and LZO1X-999 support for BBC. (fast & good
++ compressor, beats ZLIB in everything)
++
++LZARI compression support for BBC (EXPERIMENTAL)
++CONFIG_JFFS2_BBC_LZARI
++ This enables LempelZiv-Storer-Szymanski compression for BBC with
++ additional arithmetic coding (damn slow, but best compresor).
++
++LZHD compression support for BBC (EXPERIMENTAL)
++CONFIG_JFFS2_BBC_LZHD
++ This enables LempelZiv-Storer-Szymanski compression for BBC with
++ additional dynamic Huffman coding (a little faster than LZARI, and
++ it's compression ratio is a little worse than LZARI's)
++
++LZSS compression support for BBC (EXPERIMENTAL)
++CONFIG_JFFS2_BBC_LZSS
++ This enables simple LempelZiv-Storer-Szymanski compression for BBC
++ (faster than LZHD, and, and has a not-so-good compression ratio,
++ was included just for testing)
++
+ JFFS stats available in /proc filesystem
+ CONFIG_JFFS_PROC_FS
+ Enabling this option will cause statistics from mounted JFFS file systems
+diff -Nur linux-mips-cvs/fs/Config.in linux-mips/fs/Config.in
+--- linux-mips-cvs/fs/Config.in 2004-11-19 01:28:47.000000000 +0100
++++ linux-mips/fs/Config.in 2005-02-07 05:08:34.000000000 +0100
+@@ -50,6 +50,12 @@
+ if [ "$CONFIG_JFFS2_FS" = "y" -o "$CONFIG_JFFS2_FS" = "m" ] ; then
+ int 'JFFS2 debugging verbosity (0 = quiet, 2 = noisy)' CONFIG_JFFS2_FS_DEBUG 0
+ fi
++dep_mbool ' ARMLIB compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_ARMLIB $CONFIG_JFFS2_FS
++dep_mbool ' LZO1X-* compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_LZO $CONFIG_JFFS2_FS
++dep_mbool ' LZARI compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_LZARI $CONFIG_JFFS2_FS
++dep_mbool ' LZHD compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_LZHD $CONFIG_JFFS2_FS
++dep_mbool ' LZSS compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_LZSS $CONFIG_JFFS2_FS
++
+ tristate 'Compressed ROM file system support' CONFIG_CRAMFS
+ bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS
+ define_bool CONFIG_RAMFS y
+diff -Nur linux-mips-cvs/fs/jffs2/Config.in.bbc.inc linux-mips/fs/jffs2/Config.in.bbc.inc
+--- linux-mips-cvs/fs/jffs2/Config.in.bbc.inc 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips/fs/jffs2/Config.in.bbc.inc 2005-02-07 05:08:34.000000000 +0100
+@@ -0,0 +1,5 @@
++dep_mbool ' ARMLIB compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_ARMLIB $CONFIG_JFFS2_FS
++dep_mbool ' LZO1X-* compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_LZO $CONFIG_JFFS2_FS
++dep_mbool ' LZARI compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_LZARI $CONFIG_JFFS2_FS
++dep_mbool ' LZHD compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_LZHD $CONFIG_JFFS2_FS
++dep_mbool ' LZSS compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_LZSS $CONFIG_JFFS2_FS
+diff -Nur linux-mips-cvs/fs/jffs2/Configure.help.bbc.inc linux-mips/fs/jffs2/Configure.help.bbc.inc
+--- linux-mips-cvs/fs/jffs2/Configure.help.bbc.inc 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips/fs/jffs2/Configure.help.bbc.inc 2005-02-07 05:08:34.000000000 +0100
+@@ -0,0 +1,25 @@
++ARMLIB compression support for BBC (EXPERIMENTAL)
++CONFIG_JFFS2_BBC_ARMLIB
++ This enables ARMLIB support for BBC.
++
++LZO1X-* compression support for BBC (EXPERIMENTAL)
++CONFIG_JFFS2_BBC_LZO
++ This enables LZO1X-1 and LZO1X-999 support for BBC. (fast & good
++ compressor, beats ZLIB in everything)
++
++LZARI compression support for BBC (EXPERIMENTAL)
++CONFIG_JFFS2_BBC_LZARI
++ This enables LempelZiv-Storer-Szymanski compression for BBC with
++ additional arithmetic coding (damn slow, but best compresor).
++
++LZHD compression support for BBC (EXPERIMENTAL)
++CONFIG_JFFS2_BBC_LZHD
++ This enables LempelZiv-Storer-Szymanski compression for BBC with
++ additional dynamic Huffman coding (a little faster than LZARI, and
++ it's compression ratio is a little worse than LZARI's)
++
++LZSS compression support for BBC (EXPERIMENTAL)
++CONFIG_JFFS2_BBC_LZSS
++ This enables simple LempelZiv-Storer-Szymanski compression for BBC
++ (faster than LZHD, and, and has a not-so-good compression ratio,
++ was included just for testing)
+diff -Nur linux-mips-cvs/fs/jffs2/Kconfig.bbc.inc linux-mips/fs/jffs2/Kconfig.bbc.inc
+--- linux-mips-cvs/fs/jffs2/Kconfig.bbc.inc 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips/fs/jffs2/Kconfig.bbc.inc 2005-02-07 05:08:34.000000000 +0100
+@@ -0,0 +1,40 @@
++config JFFS2_BBC_ARMLIB
++ bool "ARMLIB compression support for BBC (EXPERIMENTAL)"
++ depends on JFFS2_FS && EXPERIMENTAL
++ default y
++ help
++ This enables ARMLIB support for BBC.
++
++config JFFS2_BBC_LZO
++ bool "LZO1X-* compression support for BBC (EXPERIMENTAL)"
++ depends on JFFS2_FS && EXPERIMENTAL
++ default y
++ help
++ This enables LZO1X-1 and LZO1X-999 support for BBC. (fast & good
++ compressor)
++
++config JFFS2_BBC_LZARI
++ bool "LZARI compression support for BBC (EXPERIMENTAL)"
++ depends on JFFS2_FS && EXPERIMENTAL
++ default y
++ help
++ This enables LempelZiv-Storer-Szymanski compression for BBC with
++ additional arithmetic coding (damn slow, but best compresor).
++
++config JFFS2_BBC_LZHD
++ bool "LZHD compression support for BBC (EXPERIMENTAL)"
++ depends on JFFS2_FS && EXPERIMENTAL
++ default y
++ help
++ This enables LempelZiv-Storer-Szymanski compression for BBC with
++ additional dynamic Huffman coding (a little faster than LZARI, and
++ it's compression ratio is a little worse than LZARI's)
++
++config JFFS2_BBC_LZSS
++ bool "LZSS compression support for BBC (EXPERIMENTAL)"
++ depends on JFFS2_FS && EXPERIMENTAL
++ default y
++ help
++ This enables simple LempelZiv-Storer-Szymanski compression for BBC
++ (faster than LZHD, and, and has a not-so-good compression ratio,
++ was included just for testing)
+diff -Nur linux-mips-cvs/fs/jffs2/Makefile linux-mips/fs/jffs2/Makefile
+--- linux-mips-cvs/fs/jffs2/Makefile 2003-08-13 19:19:25.000000000 +0200
++++ linux-mips/fs/jffs2/Makefile 2005-02-07 05:08:34.000000000 +0100
+@@ -10,9 +10,23 @@
+ # Note 2! The CFLAGS definitions are now in the main makefile...
+
+
++JFFS2_BBC_KERNEL_OBJS-y = jffs2_bbc_framework.o jffs2_bbc_fs.o
++
++JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_ARMLIB) += jffs2_bbc_armlib_comp.o
++JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_LZO) += jffs2_bbc_lzo_comp.o
++JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_LZSS) += jffs2_bbc_lzss_comp.o
++JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_LZARI) += jffs2_bbc_lzari_comp.o
++JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_LZHD) += jffs2_bbc_lzhd_comp.o
++
++JFFS2_BBC_KERNEL_OBJS := $(JFFS2_BBC_KERNEL_OBJS-y)
++
++JFFS2_BBC_MKFS_OBJS = jffs2_bbc_mkfs.o jffs2_bbc_framework.o jffs2_bbc_armlib_comp.o jffs2_bbc_lzo_comp.o\
++ jffs2_bbc_lzss_comp.o jffs2_bbc_lzari_comp.o jffs2_bbc_lzhd_comp.o
++
+ COMPR_OBJS := compr.o compr_rubin.o compr_rtime.o pushpull.o \
+ compr_zlib.o
+ JFFS2_OBJS := dir.o file.o ioctl.o nodelist.o malloc.o \
++ $(JFFS2_BBC_KERNEL_OBJS) \
+ read.o nodemgmt.o readinode.o super.o write.o scan.o gc.o \
+ symlink.o build.o erase.o background.o
+
+diff -Nur linux-mips-cvs/fs/jffs2/Makefile.bbc.inc linux-mips/fs/jffs2/Makefile.bbc.inc
+--- linux-mips-cvs/fs/jffs2/Makefile.bbc.inc 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips/fs/jffs2/Makefile.bbc.inc 2005-02-07 05:08:34.000000000 +0100
+@@ -0,0 +1,12 @@
++JFFS2_BBC_KERNEL_OBJS-y = jffs2_bbc_framework.o jffs2_bbc_fs.o
++
++JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_ARMLIB) += jffs2_bbc_armlib_comp.o
++JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_LZO) += jffs2_bbc_lzo_comp.o
++JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_LZSS) += jffs2_bbc_lzss_comp.o
++JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_LZARI) += jffs2_bbc_lzari_comp.o
++JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_LZHD) += jffs2_bbc_lzhd_comp.o
++
++JFFS2_BBC_KERNEL_OBJS := $(JFFS2_BBC_KERNEL_OBJS-y)
++
++JFFS2_BBC_MKFS_OBJS = jffs2_bbc_mkfs.o jffs2_bbc_framework.o jffs2_bbc_armlib_comp.o jffs2_bbc_lzo_comp.o\
++ jffs2_bbc_lzss_comp.o jffs2_bbc_lzari_comp.o jffs2_bbc_lzhd_comp.o
+diff -Nur linux-mips-cvs/fs/jffs2/compr_zlib.c linux-mips/fs/jffs2/compr_zlib.c
+--- linux-mips-cvs/fs/jffs2/compr_zlib.c 2003-01-11 18:53:17.000000000 +0100
++++ linux-mips/fs/jffs2/compr_zlib.c 2005-02-07 05:08:35.000000000 +0100
+@@ -85,7 +85,7 @@
+ vfree(inflate_workspace);
+ }
+
+-int zlib_compress(unsigned char *data_in, unsigned char *cpage_out,
++int jffs2_zlib_compress2(unsigned char *data_in, unsigned char *cpage_out,
+ __u32 *sourcelen, __u32 *dstlen)
+ {
+ z_stream strm;
+@@ -145,7 +145,7 @@
+ return 0;
+ }
+
+-void zlib_decompress(unsigned char *data_in, unsigned char *cpage_out,
++void jffs2_zlib_decompress2(unsigned char *data_in, unsigned char *cpage_out,
+ __u32 srclen, __u32 destlen)
+ {
+ z_stream strm;
+@@ -175,3 +175,19 @@
+ zlib_inflateEnd(&strm);
+ up(&inflate_sem);
+ }
++
++extern int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out, __u32 * sourcelen, __u32 * dstlen);
++extern void jffs2_zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, __u32 srclen, __u32 destlen);
++
++int zlib_compress(unsigned char *data_in, unsigned char *cpage_out,
++ __u32 *sourcelen, __u32 *dstlen)
++{
++ return jffs2_zlib_compress(data_in,cpage_out,sourcelen,dstlen);
++}
++
++void zlib_decompress(unsigned char *data_in, unsigned char *cpage_out,
++ __u32 srclen, __u32 destlen)
++{
++ jffs2_zlib_decompress(data_in,cpage_out,srclen,destlen);
++}
++
+diff -Nur linux-mips-cvs/fs/jffs2/file.c linux-mips/fs/jffs2/file.c
+--- linux-mips-cvs/fs/jffs2/file.c 2003-11-17 02:07:44.000000000 +0100
++++ linux-mips/fs/jffs2/file.c 2005-02-07 05:08:35.000000000 +0100
+@@ -35,6 +35,7 @@
+ *
+ */
+
++#include "jffs2_bbc_framework.h" /**BBC**/
+ #include <linux/kernel.h>
+ #include <linux/mtd/compatmac.h> /* for min() */
+ #include <linux/slab.h>
+@@ -459,6 +460,7 @@
+
+ comprbuf = kmalloc(cdatalen, GFP_KERNEL);
+ if (comprbuf) {
++ jffs2_bbc_model_set_act_sb(c); /**BBC**/
+ comprtype = jffs2_compress(page_address(pg)+ (file_ofs & (PAGE_CACHE_SIZE-1)), comprbuf, &datalen, &cdatalen);
+ }
+ if (comprtype == JFFS2_COMPR_NONE) {
+diff -Nur linux-mips-cvs/fs/jffs2/gc.c linux-mips/fs/jffs2/gc.c
+--- linux-mips-cvs/fs/jffs2/gc.c 2003-11-17 02:07:44.000000000 +0100
++++ linux-mips/fs/jffs2/gc.c 2005-02-07 05:08:35.000000000 +0100
+@@ -35,6 +35,7 @@
+ *
+ */
+
++#include "jffs2_bbc_framework.h" /**BBC**/
+ #include <linux/kernel.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/slab.h>
+@@ -651,6 +652,7 @@
+ writebuf = pg_ptr + (offset & (PAGE_CACHE_SIZE -1));
+
+ if (comprbuf) {
++ jffs2_bbc_model_set_act_sb(c); /**BBC**/
+ comprtype = jffs2_compress(writebuf, comprbuf, &datalen, &cdatalen);
+ }
+ if (comprtype) {
+diff -Nur linux-mips-cvs/fs/jffs2/hpatch linux-mips/fs/jffs2/hpatch
+--- linux-mips-cvs/fs/jffs2/hpatch 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips/fs/jffs2/hpatch 2005-02-07 05:08:34.000000000 +0100
+@@ -0,0 +1,191 @@
++#!/usr/bin/perl
++# A patch-like utility
++# Designed for patching different version of jffs2 with the same hpatch file
++#
++# Copyright (C) 2004, Ferenc Havasi
++#
++# 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.
++
++$filename_tmp1="file1.tmp";
++$filename_tmp2="file2.tmp";
++
++$filename_in="";
++$filename_out=$filename_tmp1;
++$filename_cnt=0;
++
++# Modes:
++# 0: expecting =
++# 1: normal_cmd
++# 2: skip until =
++# 3: expecting F (first state)
++$mode=3;
++
++%rules = ();
++
++sub file_end {
++ if (($mode!=2)&&($modified==1)) {
++ while (<SRC>) {
++ print DST $_;
++ }
++ close(SRC);
++ close(DST);
++ if ($cmd_name ne "") { $rules{"$cmd_name"}=1; }
++ $filename_result=$filename_out;
++ if ($filename_result ne $filename_in_save) {
++ open(RES,"<$filename_result") or die "Cannot open $filename_result.\n";
++ open(DST,">$filename_in_save") or die "Cannot open $filename_in_save.\n";
++ while (<RES>) {
++ print DST $_;
++ }
++ close(DST);
++ close(RES);
++ }
++ unlink($filename_tmp1) && unlink($filename_tmp2);
++ }
++ else {
++ close(SRC);
++ close(DST);
++ $filename_result=$filename_in;
++ if ($filename_result ne $filename_in_save) {
++ open(RES,"<$filename_result") or die "Cannot open $filename_result.\n";
++ open(DST,">$filename_in_save") or die "Cannot open $filename_in_save.\n";
++ while (<RES>) {
++ print DST $_;
++ }
++ close(DST);
++ close(RES);
++ }
++ unlink($filename_tmp1);
++ }
++ $modified=0;
++ foreach $rulename (keys %rules) {
++ if ($rules{"$rulename"}==0) { print(STDERR "On $filename_in_save error applying rule $rulename.\n"); }
++ }
++ %rules = ();
++}
++
++if ($#ARGV<0) {
++ print ("usage: hpatch hpatch_file\n");
++ exit;
++}
++
++open(CMD,"<$ARGV[0]") or die "Cannot open $ARGV[0].\n";
++$cmd_linenum=0;
++
++while (chomp($cmd_line=<CMD>)) {
++ $cmd_linenum++;
++ if ($cmd_line eq "") {next;}
++ #$cmd_line =~ s/\#.*//;
++ $cmd_line =~ s/\ *$//;
++ if ($cmd_line eq "") {next;}
++ if ($cmd_line =~ /^F(.*)/) {
++ $tmp_filename_in=$1;
++ if ($mode!=3) {
++ file_end();
++ }
++ $filename_in=$tmp_filename_in;
++ $filename_in_save=$filename_in;
++ open(SRC,"<$filename_in") or die "Cannot open $filename_in.\n";
++ open(DST,">$filename_out") or die "Cannot open $filename_out.\n";;
++ $modified=0;
++ $mode=0;
++ next;
++ }
++ if ($mode==3) {die "error: F expression expected in line $cmd_linenum\n";}
++ if ($cmd_line =~ /^=(.*)/) {
++ $tmp_cmd_name=$1;
++ if (($mode!=2)&&($modified==1)) {
++ while (<SRC>) {
++ print DST $_;
++ }
++ close(SRC);
++ close(DST);
++ if (($cmd_name ne "")) {$rules{"$cmd_name"}=1;};
++ $filename_cnt++;
++ if ($filename_cnt%2==1) {
++ $filename_in=$filename_tmp1;
++ $filename_out=$filename_tmp2;
++ }
++ else {
++ $filename_in=$filename_tmp2;
++ $filename_out=$filename_tmp1;
++ }
++ }
++ else {
++ close(SRC);
++ close(DST);
++ }
++ $mode=1;
++ $cmd_name=$tmp_cmd_name;
++ if (($cmd_name ne "")) {
++ if ($rules{"$cmd_name"}==1) {
++ $mode=2;
++ }
++ else {
++ $rules{"$cmd_name"}=0;
++ }
++ }
++ open(SRC,"<$filename_in") or die "Cannot open $filename_in.\n";
++ open(DST,">$filename_out") or die "Cannot open $filename_out.\n";
++ $modified=0;
++ next;
++ }
++ if ($mode == 0) {die "error: = expression expected in line $cmd_linenum\n";}
++ if ($mode == 2) {next;}
++ if ($cmd_line =~ /^!(.*)/) {
++ print "$1\n";
++ $modified=1;
++ next;
++ }
++ if ($cmd_line =~ /^\?(.*)/) {
++ $search_str=$1;
++ $found=0;
++ while (<SRC>) {
++ print DST $_;
++ if (index($_,$search_str)>=0) {$found=1; last;}
++ }
++ if ($found==0) { $mode=2; }
++ next;
++ }
++ if ($cmd_line =~ /^\+(.*)/) {
++ print DST "$1\n";
++ $modified=1;
++ next;
++ }
++ if ($cmd_line =~ /^\-(.*)/) {
++ $search_str=$1;
++ $found=0;
++ while (<SRC>) {
++ if (index($_,$search_str)>=0) {$saved_line=$_; $found=1; $modified=1; last;}
++ print DST $_;
++ }
++ if ($found==0) { $mode=2; }
++ next;
++ }
++ if ($cmd_line =~ /^i(.*)/) {
++ $filename_inc=$1;
++ open(INCSRC,"<$filename_inc") or die "Cannot open $filename_inc.\n";
++ while (<INCSRC>) {
++ print DST $_;
++ }
++ next;
++ }
++ if ($cmd_line =~ /^I/) {
++ print DST $saved_line;
++ next;
++ }
++}
++file_end();
++close(CMD);
+diff -Nur linux-mips-cvs/fs/jffs2/jffs2_bbc_armlib_comp.c linux-mips/fs/jffs2/jffs2_bbc_armlib_comp.c
+--- linux-mips-cvs/fs/jffs2/jffs2_bbc_armlib_comp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips/fs/jffs2/jffs2_bbc_armlib_comp.c 2005-02-07 05:08:34.000000000 +0100
+@@ -0,0 +1,2224 @@
++/*
++ * JFFS2-BBC: armlib compressor plugin
++ *
++ * $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++ *
++ * Copyright (C) 2004, Ferenc Havasi & Tamas Gergely
++ *
++ * 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 "jffs2_bbc_framework.h"
++
++#ifdef __KERNEL__
++#include <linux/string.h>
++#else
++#include <string.h>
++#endif
++
++//ORIGIN: include/DataStructures/TypeDefs.h
++
++/*******************************************************************************
++* FILE: TypeDefs.h
++* AUTHOR: Tamás Gergely
++* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*******************************************************************************/
++
++#ifndef TYPEDEFS_H
++#define TYPEDEFS_H
++
++#pragma pack(4)
++
++#ifndef bool
++#define bool char
++#define true 1
++#define false 0
++#endif
++
++#ifndef u8
++#define u8 unsigned char
++#endif
++#ifndef u16
++#define u16 unsigned short
++#endif
++#ifndef u32
++#define u32 unsigned long
++#endif
++#ifndef s8
++#define s8 signed char
++#endif
++#ifndef s16
++#define s16 signed short
++#endif
++#ifndef s32
++#define s32 signed long
++#endif
++
++typedef struct
++{
++ u32 capacity;
++ u32 size;
++ u32 alloc_size;
++ void *ptr;
++} vector;
++
++#define VECTOR_P_END(vct) ((void*)(((char*)((vct)->ptr)) + (vct)->size))
++#define VECTOR_S_END(vct) ((void*)(((char*)((vct).ptr)) + (vct).size))
++
++static void vector_clear(vector *);
++#ifdef JFFS2_BBC_ARMLIB_MODELGEN
++static void vector_reset(vector *);
++static void vector_clr_ptr(vector *);
++static void vector_add_u8(vector *, u8);
++static void vector_add_u16(vector *, u16);
++static void vector_add_u32(vector *, u32);
++static void vector_add_s8(vector *, s8);
++static void vector_add_s16(vector *, s16);
++static void vector_add_s32(vector *, s32);
++static void vector_add_ptr(vector *, void *);
++static void vector_concat(vector *, vector *);
++#endif
++
++#endif
++
++//ORIGIN: include/DataStructures/DataTypes.h
++
++/*******************************************************************************
++* FILE: DataTypes.h
++* AUTHOR: Tamás Gergely
++* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*******************************************************************************/
++
++#ifndef DATATYPES_H
++#define DATATYPES_H
++
++//#include "DataStructures/TypeDefs.h"
++
++typedef u16 THUMB_DataType;
++typedef u32 ARM_DataType;
++typedef u8 TokenType;
++typedef u8 PredictorType;
++typedef u8 *ProbDist;
++
++typedef vector RawData;
++typedef vector RawBlocks;
++typedef vector TokenStream;
++typedef vector TokenBlocks;
++typedef vector LatType;
++
++#define THUMB_DATA_LENGTH 16
++#define ARM_DATA_LENGTH 32
++#define TOKEN_LENGTH 8
++#define TOKEN_MAXVALUE 0xff
++#define PREDICTOR_LENGTH 8
++#define PREDICTOR_MAXVALUE 0xff
++
++#endif
++
++//ORIGIN: include/DataStructures/BitVector.h
++
++/*******************************************************************************
++* FILE: BitVector.h
++* AUTHOR: Tamás Gergely
++* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*******************************************************************************/
++
++#ifndef BITVECTOR_H
++#define BITVECTOR_H
++
++//#include "DataStructures/TypeDefs.h"
++
++typedef vector BitBlocks;
++
++#pragma pack(4)
++
++typedef struct
++{
++ u32 freebits;
++ u32 capacity;
++ u32 size;
++ u8 *base;
++ u8 *ptr;
++} BitVector;
++
++#ifdef JFFS2_BBC_ARMLIB_MODELGEN
++static void bitblocks_clear(BitBlocks *);
++static void bitvector_clear(BitVector *);
++static void bitvector_W_reset(BitVector *);
++static void bitvector_W_add0(BitVector *);
++static void bitvector_W_add1(BitVector *);
++static void bitvector_W_concat_b(BitVector *, BitVector *);
++static void bitvector_W_concat_v(BitVector *, vector *);
++static void bitvector_W_flush(BitVector *);
++static void bitvector_R_reset(BitVector *);
++static u8 bitvector_R_get1(BitVector *);
++static u8 bitvector_R_get8(BitVector *);
++#endif
++
++#define BITVECTOR_P_END(bv) ((void*)(((bv)->base)+((bv)->size)))
++#define BITVECTOR_S_END(bv) ((void*)( ((bv).base)+ ((bv).size)))
++#define BITVECTOR_SKIP(bv,num) ((bv)->ptr) += (num)
++
++#endif
++
++//ORIGIN: include/DataStructures/DecisionTree.h
++
++/*******************************************************************************
++* FILE: DecisionTree.h
++* AUTHOR: Tamás Gergely
++* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*******************************************************************************/
++
++#ifndef DECISIONTREE_H
++#define DECISIONTREE_H
++
++//#include "DataStructures/DataTypes.h"
++
++#pragma pack(4)
++
++#define TREENODETYPE_NULLNODE 0
++#define TREENODETYPE_NODE_BINARY_EQ 1
++#define TREENODETYPE_LEAF_P 2
++#define TREENODETYPE_LEAF_C 3
++#define TREENODETYPE_NODE_BINARY_LT 5
++#define TREENODETYPE_IS_NODE(n) (((n) == TREENODETYPE_NODE_BINARY_EQ) || \
++ ((n) == TREENODETYPE_NODE_BINARY_LT))
++#define TREENODETYPE_IS_NODE_BINARY(n) (((n) == TREENODETYPE_NODE_BINARY_EQ) || \
++ ((n) == TREENODETYPE_NODE_BINARY_LT))
++
++#define TREENODETYPE_IS_LEAF(n) (((n) == TREENODETYPE_LEAF_P) || \
++ ((n) == TREENODETYPE_LEAF_C))
++
++
++#define TREE_SUBTREE_RELATION_LEFT_EQ !=
++#define TREE_SUBTREE_RELATION_RIGHT_EQ ==
++#define TREE_SUBTREE_RELATION_LEFT_LT <
++#define TREE_SUBTREE_RELATION_RIGHT_LT >=
++
++#define GET_NODE_PTR_TYPE(n) (((TreeNodeDummy*)(n))->type)
++
++typedef struct
++{
++ u8 type;
++} TreeNodeDummy;
++
++typedef struct
++{
++ u8 type; // [TREENODETYPE_NODE_BINARY]
++ u8 attribute;
++ PredictorType value;
++ void *left;
++ void *right;
++} TreeNodeBinary;
++
++typedef struct
++{
++ u8 type; // [TREENODETYPE_LEAF_P]
++ u16 pairs;
++ PredictorType *probabilities;
++} TreeLeafP;
++
++typedef struct
++{
++ u8 type; // [TREENODETYPE_LEAF_C]
++ PredictorType predicted_class;
++} TreeLeafC;
++
++typedef struct
++{
++ u32 high;
++ u32 low;
++ u32 max;
++} ProbabilityType;
++
++
++typedef struct
++{
++ void *root;
++ u16 number_of_classes;
++ u16 number_of_predictors;
++ PredictorType *predictor_max_values;
++} DecisionTree;
++
++#ifdef JFFS2_BBC_ARMLIB_MODELGEN
++static void decisiontree_delete(DecisionTree *);
++static void decisiontree_get_probability_for_token(void *, PredictorType *, TokenType, ProbabilityType *);
++static TokenType decisiontree_get_token_for_range(void *, PredictorType *, u32, u32, ProbabilityType *);
++#endif
++
++#endif
++
++//ORIGIN: include/DataStructures/PredictorTable.h
++
++/*******************************************************************************
++* FILE: PredictorTable.h
++* AUTHOR: Tamás Gergely
++* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*******************************************************************************/
++
++#ifndef PREDICTORTABLE_H
++#define PREDICTORTABLE_H
++
++//#include "DataStructures/TypeDefs.h"
++//#include "DataStructures/DataTypes.h"
++////#include "DataStructures/Filter.h"
++////#include "DataStructures/Converter.h"
++////#include "DataStructures/Manipulator.h"
++
++#define NUMBER_OF_PREDICTORS_ARM 17
++
++#ifndef __KERNEL__
++#define NUMBER_OF_PREDICTORS_TXT 2
++#else
++#undef TXT_TOKENS
++#endif // __KERNEL__
++
++#ifdef TXT_TOKENS
++#define NUMBER_OF_PREDICTORS NUMBER_OF_PREDICTORS_TXT
++#define predictortable_reset predictortable_resetTXT
++#define predictortable_update predictortable_updateTXT
++#define predictortable_minvalue predictortable_minvalueTXT
++#define predictortable_maxvalue predictortable_maxvalueTXT
++#else
++#define NUMBER_OF_PREDICTORS NUMBER_OF_PREDICTORS_ARM
++#define predictortable_reset predictortable_resetARM
++#define predictortable_update predictortable_updateARM
++#define predictortable_minvalue predictortable_minvalueARM
++#define predictortable_maxvalue predictortable_maxvalueARM
++#endif
++
++
++#pragma pack(4)
++
++typedef struct
++{
++ PredictorType *predictors;
++} PredictorTable;
++
++#ifdef JFFS2_BBC_ARMLIB_MODELGEN
++static void predictortable_clear(PredictorTable *);
++static void predictortable_free(PredictorTable *);
++static void predictortable_resetARM(PredictorTable *);
++static void predictortable_updateARM(PredictorTable *, TokenType);
++static PredictorType predictortable_minvalueARM(PredictorTable *, u32);
++static PredictorType predictortable_maxvalueARM(PredictorTable *, u32);
++#endif
++
++#ifndef __KERNEL__
++/*
++static void predictortable_resetTXT(PredictorTable *);
++static void predictortable_updateTXT(PredictorTable *, TokenType);
++static PredictorType predictortable_minvalueTXT(PredictorTable *, u32);
++static PredictorType predictortable_maxvalueTXT(PredictorTable *, u32);
++*/
++#endif // __KERNEL__
++
++#endif
++
++//ORIGIN: include/DataStructures/ipack_model.h
++
++/*******************************************************************************
++* FILE: ipack_model.h
++* AUTHOR: Tamás Gergely
++* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*******************************************************************************/
++
++#ifndef IPACK_MODEL_H
++#define IPACK_MODEL_H
++
++//#include "DataStructures/DataTypes.h"
++//#include "DataStructures/DecisionTree.h"
++//#include "DataStructures/PredictorTable.h"
++
++#define PROBABILITY_SHIFT 12
++#define PROBABILITY_MAX 0x00001000l
++
++#define NUMBER_OF_TOKENS_ARM 16
++#define NUMBER_OF_TOKENS_PER_INSTRUCTION_ARM 8
++
++#ifndef __KERNEL__
++#define NUMBER_OF_TOKENS_TXT 256
++#define NUMBER_OF_TOKENS_PER_INSTRUCTION_TXT 4
++#else
++#undef TXT_TOKENS
++#endif // __KERNEL__
++
++#ifdef TXT_TOKENS
++#define NUMBER_OF_TOKENS NUMBER_OF_TOKENS_TXT
++#define NUMBER_OF_TOKENS_PER_INSTRUCTION NUMBER_OF_TOKENS_PER_INSTRUCTION_TXT
++#else
++#define NUMBER_OF_TOKENS NUMBER_OF_TOKENS_ARM
++#define NUMBER_OF_TOKENS_PER_INSTRUCTION NUMBER_OF_TOKENS_PER_INSTRUCTION_ARM
++#endif
++
++#pragma pack(4)
++
++/*
++ Data structure of an internal node of the tree
++*/
++typedef struct
++{
++ PredictorType *attribute_ptr;
++ u32 value; // PredictorType
++ void *right_child_ptr;
++} ipack_treenodeBin;
++/*
++ Data structure of a leaf with probabilities
++*/
++typedef struct
++{
++ u16 probabilities[0]; // PredictorType[0]
++} ipack_treeleafP;
++/*
++ Data structure of a leaf with class prediction
++*/
++typedef struct
++{
++ PredictorType predicted_class; // PredictorType
++} ipack_treeleafC;
++/*
++ Possible data structures of a tree node
++*/
++typedef union
++{
++ ipack_treenodeBin nodeBin;
++ ipack_treeleafP leafP;
++ ipack_treeleafC leafC;
++} ipack_node_data;
++/*
++ Tree node
++*/
++typedef struct
++{
++ u32 type; // u8
++ ipack_node_data data; // ipack_node_data
++} ipack_nodetype;
++/*
++ Nullnode
++*/
++typedef struct
++{
++ u32 type;
++ u16 probabilities[NUMBER_OF_TOKENS];
++} ipack_nullnode;
++/*
++ Model for ipack project
++*/
++typedef struct
++{
++ char ID[4]; // char[4]
++ char block_sign[4]; // only the first 2 are used!
++ void *tree_root_ptr; // void*
++ void *tree_code; // generated ARM code
++ PredictorType *predictors_ptr; // PredictorType*
++ ipack_nullnode nullnode;
++} ipack_model_type;
++
++typedef struct
++{
++ u32 high;
++ u32 low;
++} ipack_probability_type;
++
++
++static void ipack_model_get_probability_for_token(ipack_nodetype *, TokenType, ipack_probability_type *);
++static TokenType ipack_model_get_token_for_range(ipack_nodetype *, u32, u32, ipack_probability_type *);
++/*void ipack_model_predictortable_reset (PredictorType*);
++void ipack_model_predictortable_update (PredictorType*, TokenType);*/
++
++#ifndef __KERNEL__
++/*static void ipack_model_printinfo(ipack_model_type *);
++static void ipack_dumpmodel(void *);*/
++#endif
++
++#endif
++
++//ORIGIN: include/Builders/PredictorGenerator.h
++
++/*******************************************************************************
++* FILE: PredictorGenerator.h
++* AUTHOR: Tamás Gergely
++* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*******************************************************************************/
++
++#ifndef PREDICTORGENERATOR_H
++#define PREDICTORGENERATOR_H
++
++//#include "DataStructures.h"
++
++#ifdef JFFS2_BBC_ARMLIB_MODELGEN
++static PredictorTable *predictorgenerator_generate(void);
++#endif
++
++#endif
++
++//ORIGIN: include/Builders/Coder.h
++
++/*******************************************************************************
++* FILE: Coder.h
++* AUTHOR: Tamás Gergely
++* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*******************************************************************************/
++
++#ifndef CODER_H
++#define CODER_H
++
++#define CODER_VALUEBITS 16
++#define CODER_VALUEMAX 0x00010000l
++#define CODER_VALUE3RD 0x0000c000l
++#define CODER_VALUEHLF 0x00008000l
++#define CODER_VALUE1ST 0x00004000l
++
++#endif
++
++//ORIGIN: DataStructures/src/TypeDefs.c
++
++/*******************************************************************************
++* FILE: TypeDefs.c
++* AUTHOR: Tamás Gergely
++* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*******************************************************************************/
++
++//#include "ipack_common.h"
++//#include "DataStructures/TypeDefs.h"
++#ifndef __KERNEL__
++#include <memory.h>
++#endif
++
++#define VECTOR_ALLOC_SIZE 0x00001000
++
++static void vector_clear(vector * vct)
++{
++ if (vct->ptr)
++ jffs2_bbc_free(vct->ptr);
++ vct->capacity = 0;
++ vct->size = 0;
++ vct->ptr = 0;
++}
++
++#ifdef JFFS2_BBC_ARMLIB_MODELGEN
++static void vector_extend(vector * vct)
++{
++ void *tmp;
++ vct->capacity += vct->alloc_size;
++ tmp = jffs2_bbc_malloc(vct->capacity);
++ if (vct->ptr) {
++ memcpy(tmp, vct->ptr, vct->size);
++ jffs2_bbc_free(vct->ptr);
++ }
++ vct->ptr = tmp;
++}
++
++static void vector_reset(vector * vct)
++{
++ vct->capacity = 0;
++ vct->size = 0;
++ vct->alloc_size = VECTOR_ALLOC_SIZE;
++ vct->ptr = 0;
++}
++
++static void vector_clr_ptr(vector * vct)
++{
++ void **it;
++ void *end_it;
++ for (it = vct->ptr, end_it = (((char *) (vct->ptr)) + vct->size); it != end_it; it++) {
++ vector_clear(*it);
++ jffs2_bbc_free(*it);
++ }
++ if (vct->ptr)
++ jffs2_bbc_free(vct->ptr);
++ vct->capacity = 0;
++ vct->size = 0;
++ vct->ptr = 0;
++}
++
++static void vector_add_u8(vector * vct, u8 val)
++{
++ if ((vct->size) + sizeof(u8) > (vct->capacity)) {
++ vector_extend(vct);
++ }
++ *(u8 *) ((char *) (vct->ptr) + (vct->size)) = val;
++ vct->size += sizeof(u8);
++};
++
++static void vector_add_u16(vector * vct, u16 val)
++{
++ if ((vct->size) + sizeof(u16) > (vct->capacity)) {
++ vector_extend(vct);
++ }
++ *(u16 *) ((char *) (vct->ptr) + (vct->size)) = val;
++ vct->size += sizeof(u16);
++};
++
++static void vector_add_u32(vector * vct, u32 val)
++{
++ if ((vct->size) + sizeof(u32) > (vct->capacity)) {
++ vector_extend(vct);
++ }
++ *(u32 *) ((char *) (vct->ptr) + (vct->size)) = val;
++ vct->size += sizeof(u32);
++};
++
++static void vector_add_s8(vector * vct, s8 val)
++{
++ if ((vct->size) + sizeof(s8) > (vct->capacity)) {
++ vector_extend(vct);
++ }
++ *(s8 *) ((char *) (vct->ptr) + (vct->size)) = val;
++ vct->size += sizeof(s8);
++};
++
++static void vector_add_s16(vector * vct, s16 val)
++{
++ if ((vct->size) + sizeof(s16) > (vct->capacity)) {
++ vector_extend(vct);
++ }
++ *(s16 *) ((char *) (vct->ptr) + (vct->size)) = val;
++ vct->size += sizeof(s16);
++};
++
++static void vector_add_s32(vector * vct, s32 val)
++{
++ if ((vct->size) + sizeof(s32) > (vct->capacity)) {
++ vector_extend(vct);
++ }
++ *(s32 *) ((char *) (vct->ptr) + (vct->size)) = val;
++ vct->size += sizeof(s32);
++};
++
++static void vector_add_ptr(vector * vct, void *ptr)
++{
++ if ((vct->size) + sizeof(void *) > (vct->capacity)) {
++ vector_extend(vct);
++ }
++ *(void **) ((char *) (vct->ptr) + (vct->size)) = ptr;
++ vct->size += sizeof(void *);
++}
++
++static void vector_concat(vector * lhs, vector * rhs)
++{
++ void *tmp;
++ if (!(rhs->size)) {
++ return;
++ }
++ tmp = lhs->ptr;
++ lhs->capacity = (lhs->size) + (rhs->size);
++ lhs->ptr = jffs2_bbc_malloc(lhs->capacity);
++ if (tmp) {
++ memcpy(lhs->ptr, tmp, lhs->size);
++ jffs2_bbc_free(tmp);
++ }
++ memcpy((((u8 *) lhs->ptr) + lhs->size), rhs->ptr, rhs->size);
++ lhs->size += rhs->size;
++}
++
++#endif
++
++//ORIGIN: DataStructures/src/BitVector.c
++
++/*******************************************************************************
++* FILE: BitVector.c
++* AUTHOR: Tamás Gergely
++* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*******************************************************************************/
++
++//#include "ipack_common.h"
++//#include "DataStructures/BitVector.h"
++#ifndef __KERNEL__
++#include <memory.h>
++#endif
++
++#define VECTOR_ALLOC_SIZE 0x00001000
++
++#ifdef JFFS2_BBC_ARMLIB_MODELGEN
++
++static void bitblocks_clear(BitBlocks * this)
++{
++ BitVector **it;
++ void *end_it;
++ for (it = this->ptr, end_it = VECTOR_P_END(this); it != end_it; it++) {
++ bitvector_clear(*it);
++ jffs2_bbc_free(*it);
++ }
++ jffs2_bbc_free(this->ptr);
++ this->ptr = 0;
++}
++
++static void bitvector_clear(BitVector * this)
++{
++ if (this->base) {
++ jffs2_bbc_free(this->base);
++ }
++ this->freebits = 0;
++ this->capacity = 0;
++ this->size = 0;
++ this->base = 0;
++ this->ptr = 0;
++}
++
++static void bitvector_W_reset(BitVector * this)
++{
++ this->freebits = 0;
++ this->capacity = 0;
++ this->size = 0;
++ this->base = 0;
++ this->ptr = 0;
++}
++
++static void bitvector_W_add0(BitVector * this)
++{
++ if (!(this->freebits)) {
++ if (this->size == this->capacity) {
++ void *tmp = this->base;
++ this->capacity += VECTOR_ALLOC_SIZE;
++ this->base = jffs2_bbc_malloc(this->capacity);
++ this->ptr = ((u8 *) (this->base)) + this->size;
++ memcpy(this->base, tmp, this->size);
++ jffs2_bbc_free(tmp);
++ }
++ else {
++ this->ptr++;
++ }
++ this->size++;
++ this->freebits = 7;
++ *(this->ptr) = 0x00;
++ }
++ else {
++ this->freebits--;
++ (*(this->ptr)) <<= 1;
++ }
++}
++
++static void bitvector_W_add1(BitVector * this)
++{
++ if (!(this->freebits)) {
++ if (this->size == this->capacity) {
++ void *tmp = this->base;
++ this->capacity += VECTOR_ALLOC_SIZE;
++ this->base = jffs2_bbc_malloc(this->capacity);
++ this->ptr = ((u8 *) (this->base)) + this->size;
++ memcpy(this->base, tmp, this->size);
++ jffs2_bbc_free(tmp);
++ }
++ else {
++ this->ptr++;
++ }
++ this->size++;
++ this->freebits = 7;
++ *(this->ptr) = 0x01;
++ }
++ else {
++ this->freebits--;
++ (*(this->ptr)) <<= 1;
++ (*(this->ptr)) |= 0x01;
++ }
++}
++
++static void bitvector_W_concat_b(BitVector * lhs, BitVector * rhs)
++{
++ void *tmp;
++ if (!(rhs->size)) {
++ return;
++ }
++ tmp = lhs->base;
++ lhs->capacity = ((((lhs->size) + (rhs->size) - 1) / VECTOR_ALLOC_SIZE) + 1) * VECTOR_ALLOC_SIZE;
++ lhs->base = jffs2_bbc_malloc(lhs->capacity);
++ if (tmp) {
++ memcpy(lhs->base, tmp, lhs->size);
++ jffs2_bbc_free(tmp);
++ }
++ memcpy((((u8 *) (lhs->base)) + lhs->size), rhs->base, rhs->size);
++ lhs->freebits = 0;
++ lhs->size += rhs->size;
++ lhs->ptr = ((u8 *) (lhs->base)) + lhs->size;
++}
++
++static void bitvector_W_concat_v(BitVector * lhs, vector * rhs)
++{
++ void *tmp;
++ if (!(rhs->size)) {
++ return;
++ }
++ tmp = lhs->base;
++ lhs->capacity = ((((lhs->size) + (rhs->size) - 1) / VECTOR_ALLOC_SIZE) + 1) * VECTOR_ALLOC_SIZE;
++ lhs->base = jffs2_bbc_malloc(lhs->capacity);
++ if (tmp) {
++ memcpy(lhs->base, tmp, lhs->size);
++ jffs2_bbc_free(tmp);
++ }
++ memcpy((((u8 *) (lhs->base)) + lhs->size), rhs->ptr, rhs->size);
++ lhs->freebits = 0;
++ lhs->size += rhs->size;
++ lhs->ptr = ((u8 *) (lhs->base)) + lhs->size;
++}
++
++static void bitvector_W_flush(BitVector * this)
++{
++ (*(this->ptr)) <<= this->freebits;
++ this->freebits = 0;
++}
++
++static void bitvector_R_reset(BitVector * this)
++{
++ this->freebits = 7;
++ this->ptr = this->base;
++}
++
++static u8 bitvector_R_get1(BitVector * this)
++{
++ u8 tmp = ((*(this->ptr)) >> this->freebits) & 0x01;
++ if (!(this->freebits)) {
++ this->freebits = 7;
++ this->ptr++;
++ }
++ else {
++ this->freebits--;
++ }
++ return tmp;
++}
++
++static u8 bitvector_R_get8(BitVector * this)
++{
++ u8 tmp = (*(this->ptr));
++ this->ptr++;
++ return tmp;
++}
++
++#endif
++
++//ORIGIN: DataStructures/src/DecisionTree.c
++
++/*******************************************************************************
++* FILE: DecisionTree.c
++* AUTHOR: Tamás Gergely
++* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*******************************************************************************/
++
++//#include "ipack_common.h"
++//#include "DataStructures/DecisionTree.h"
++
++static void decisiontree_delete_node(void *root)
++{
++ u8 tmp = GET_NODE_PTR_TYPE(root);
++ if (TREENODETYPE_IS_NODE_BINARY(tmp)) {
++ decisiontree_delete_node(((TreeNodeBinary *) root)->left);
++ decisiontree_delete_node(((TreeNodeBinary *) root)->right);
++ }
++ else if ((tmp) == TREENODETYPE_LEAF_P) {
++ if (((TreeLeafP *) root)->probabilities) {
++ jffs2_bbc_free(((TreeLeafP *) root)->probabilities);
++ }
++ }
++ else if ((tmp) == TREENODETYPE_LEAF_C) {
++ }
++ jffs2_bbc_free(root);
++}
++
++#ifdef JFFS2_BBC_ARMLIB_MODELGEN
++
++static void decisiontree_delete(DecisionTree * dt)
++{
++ decisiontree_delete_node(dt->root);
++ jffs2_bbc_free(dt->predictor_max_values);
++}
++
++static void decisiontree_get_probability_for_token(void *root, PredictorType * preds, TokenType token, ProbabilityType * prob)
++{
++ void *tmp = root;
++ while (TREENODETYPE_IS_NODE(((TreeNodeBinary *) tmp)->type)) {
++ if (((TreeNodeBinary *) tmp)->type == TREENODETYPE_NODE_BINARY_EQ) {
++ if (preds[((TreeNodeBinary *) tmp)->attribute] TREE_SUBTREE_RELATION_LEFT_EQ((TreeNodeBinary *) tmp)->value) {
++ tmp = ((TreeNodeBinary *) tmp)->left;
++ }
++ else {
++ tmp = ((TreeNodeBinary *) tmp)->right;
++ }
++ }
++ else if (((TreeNodeBinary *) tmp)->type == TREENODETYPE_NODE_BINARY_LT) {
++ if (preds[((TreeNodeBinary *) tmp)->attribute] TREE_SUBTREE_RELATION_LEFT_LT((TreeNodeBinary *) tmp)->value) {
++ tmp = ((TreeNodeBinary *) tmp)->left;
++ }
++ else {
++ tmp = ((TreeNodeBinary *) tmp)->right;
++ }
++ }
++ }
++ prob->high = 0;
++ prob->low = 0;
++ prob->max = 0;
++ if (((TreeNodeBinary *) tmp)->type == TREENODETYPE_LEAF_P) {
++ u32 i;
++ u32 lngth = ((TreeLeafP *) tmp)->pairs << 1;
++ for (i = 0; i < lngth;) {
++ TokenType at = ((TreeLeafP *) tmp)->probabilities[i++];
++ TokenType av = ((TreeLeafP *) tmp)->probabilities[i++];
++ if (token > at)
++ prob->low += av;
++ if (token >= at)
++ prob->high += av;
++ prob->max += av;
++ }
++ }
++ else if (((TreeNodeBinary *) tmp)->type == TREENODETYPE_LEAF_C) {
++ if (((TreeLeafC *) tmp)->predicted_class == token) {
++ prob->high = TOKEN_MAXVALUE;
++ prob->max = TOKEN_MAXVALUE;
++ }
++ }
++}
++
++static TokenType decisiontree_get_token_for_range(void *root, PredictorType * preds, u32 value, u32 range, ProbabilityType * prob)
++{
++ void *tmp = root;
++ TokenType token = 0;
++ while (TREENODETYPE_IS_NODE(((TreeNodeBinary *) tmp)->type)) {
++ if (((TreeNodeBinary *) tmp)->type == TREENODETYPE_NODE_BINARY_EQ) {
++ if (preds[((TreeNodeBinary *) tmp)->attribute] TREE_SUBTREE_RELATION_LEFT_EQ((TreeNodeBinary *) tmp)->value) {
++ tmp = ((TreeNodeBinary *) tmp)->left;
++ }
++ else {
++ tmp = ((TreeNodeBinary *) tmp)->right;
++ }
++ }
++ else if (((TreeNodeBinary *) tmp)->type == TREENODETYPE_NODE_BINARY_LT) {
++ if (preds[((TreeNodeBinary *) tmp)->attribute] TREE_SUBTREE_RELATION_LEFT_LT((TreeNodeBinary *) tmp)->value) {
++ tmp = ((TreeNodeBinary *) tmp)->left;
++ }
++ else {
++ tmp = ((TreeNodeBinary *) tmp)->right;
++ }
++ }
++ }
++ prob->high = 0;
++ prob->low = 0;
++ prob->max = 0;
++ if (((TreeNodeBinary *) tmp)->type == TREENODETYPE_LEAF_P) {
++ u32 i;
++ u32 norm;
++ TokenType at = 0;
++ TokenType av;
++ u32 lngth = ((TreeLeafP *) tmp)->pairs << 1;
++ for (i = 0; i < lngth;) {
++ i++;
++ prob->max += ((TreeLeafP *) tmp)->probabilities[i++];
++ }
++ norm = (value * prob->max - 1) / range;
++ for (i = 0; prob->high <= norm;) {
++ at = ((TreeLeafP *) tmp)->probabilities[i++];
++ av = ((TreeLeafP *) tmp)->probabilities[i++];
++ prob->high += av;
++ if (prob->high <= norm)
++ prob->low += av;
++ }
++ token = at;
++ }
++ else if (((TreeNodeBinary *) tmp)->type == TREENODETYPE_LEAF_C) {
++ token = ((TreeLeafC *) tmp)->predicted_class;
++ prob->high = TOKEN_MAXVALUE;
++ prob->max = TOKEN_MAXVALUE;
++ }
++ return token;
++}
++#endif
++
++//ORIGIN: DataStructures/src/PredictorTable.c
++
++/*******************************************************************************
++* FILE: PredictorTable.c
++* AUTHOR: Tamás Gergely
++* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*******************************************************************************/
++
++//#include "ipack_common.h"
++//#include "DataStructures/PredictorTable.h"
++
++#ifdef JFFS2_BBC_ARMLIB_MODELGEN
++
++static void predictortable_clear(PredictorTable * table)
++{
++ table->predictors = 0;
++}
++
++static void predictortable_free(PredictorTable * table)
++{
++ if (table->predictors) {
++ jffs2_bbc_free(table->predictors);
++ table->predictors = 0;
++ }
++}
++
++static void predictortable_resetARM(PredictorTable * table)
++{
++ register PredictorType *ptr = table->predictors;
++ register PredictorType *end = ptr + NUMBER_OF_PREDICTORS_ARM;
++ while (ptr < end) {
++ *(ptr++) = 0;
++ }
++}
++
++static void predictortable_updateARM(PredictorTable * table, TokenType token)
++{
++ register PredictorType *ptr = table->predictors;
++ register u32 ndx = ptr[0] + 1;
++ ptr[ndx + 8] = ptr[ndx];
++ ptr[ndx] = token;
++ if (ndx == 8) {
++ ptr[0] = 0;
++ }
++ else {
++ ++ptr[0];
++ }
++}
++
++static PredictorType predictortable_minvalueARM(PredictorTable * table, u32 index)
++{
++ return 0;
++}
++
++static PredictorType predictortable_maxvalueARM(PredictorTable * table, u32 index)
++{
++ if (index == 0) {
++ return 7;
++ }
++ else {
++ return 15;
++ }
++}
++
++#endif
++
++#ifndef __KERNEL__
++
++/*static void predictortable_resetTXT(PredictorTable * table)
++{
++ register PredictorType *ptr = table->predictors;
++ register PredictorType *end = ptr + NUMBER_OF_PREDICTORS_TXT;
++ while (ptr < end) {
++ *(ptr++) = 0;
++ }
++}
++
++static void predictortable_updateTXT(PredictorTable * table, TokenType token)
++{ //TODO: modify
++ register PredictorType *ptr = table->predictors;
++// register u32 ndx;
++ ptr[0] = token;
++ if ((('a' <= token) && (token <= 'z')) || (('A' <= token) && (token <= 'Z'))) {
++ ++(ptr[1]);
++ }
++ else {
++ ptr[1] = 0;
++ }
++}
++
++static PredictorType predictortable_minvalueTXT(PredictorTable * table, u32 index)
++{
++ return 0;
++}
++
++static PredictorType predictortable_maxvalueTXT(PredictorTable * table, u32 index)
++{ //TODO: modify
++ return 254;
++}*/
++
++#endif // __KERNEL__
++
++//ORIGIN: DataStructures/src/ipack_model.c
++
++/*******************************************************************************
++* FILE: ipack_model.c
++* AUTHOR: Tamás Gergely
++* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*******************************************************************************/
++
++//#include "DataStructures/ipack_model.h"
++//#include "measuredef.h"
++//#include "ipack_common.h"
++
++#ifdef __MEASURE_TIME_MODEL_GETPROB
++#define __MT_P_MAX 256
++#define __MT_P_DIV 128
++#define __MT_P_MIN 0
++#endif
++
++static void ipack_model_get_probability_for_token(ipack_nodetype * tmp, TokenType token, ipack_probability_type * prob)
++{
++// register ipack_nodetype* tmp = model->tree_root_ptr;
++// register ipack_nodetype* tmp = root;
++ while (TREENODETYPE_IS_NODE(tmp->type)) {
++ if (tmp->type == TREENODETYPE_NODE_BINARY_EQ) {
++ if (*(tmp->data.nodeBin.attribute_ptr) TREE_SUBTREE_RELATION_LEFT_EQ tmp->data.nodeBin.value) {
++ ((char *) tmp) += sizeof(tmp->type) + sizeof(ipack_treenodeBin);
++ }
++ else {
++ tmp = tmp->data.nodeBin.right_child_ptr;
++ }
++ }
++ else if (tmp->type == TREENODETYPE_NODE_BINARY_LT) {
++ if (*(tmp->data.nodeBin.attribute_ptr) TREE_SUBTREE_RELATION_LEFT_LT tmp->data.nodeBin.value) {
++ ((char *) tmp) += sizeof(tmp->type) + sizeof(ipack_treenodeBin);
++ }
++ else {
++ tmp = tmp->data.nodeBin.right_child_ptr;
++ }
++ }
++ }
++ prob->high = 0;
++ prob->low = 0;
++// prob->max = 0;
++ if (tmp->type == TREENODETYPE_LEAF_P) {
++ if (token) {
++ prob->low = tmp->data.leafP.probabilities[token - 1];
++ }
++ prob->high = tmp->data.leafP.probabilities[token];
++// prob->max = tmp->data.leafP.probabilities[15];
++ }
++ else if (tmp->type == TREENODETYPE_LEAF_C) {
++ if (tmp->data.leafC.predicted_class == token) {
++ prob->high = TOKEN_MAXVALUE;
++// prob->max = TOKEN_MAXVALUE;
++ }
++ }
++}
++
++#ifndef IPACK_ARM_ASM
++
++//return ipack_model_get_token_for_range2(tmp,value,range,prob);
++
++static TokenType ipack_model_get_token_for_range(ipack_nodetype * tmp, u32 value, u32 range, ipack_probability_type * prob)
++{
++// register ipack_nodetype* tmp = model->tree_root_ptr;
++// register ipack_nodetype* tmp = root;
++ register TokenType token = 0;
++ while (TREENODETYPE_IS_NODE(tmp->type)) {
++ if (tmp->type == TREENODETYPE_NODE_BINARY_EQ) {
++ if (*(tmp->data.nodeBin.attribute_ptr) TREE_SUBTREE_RELATION_LEFT_EQ tmp->data.nodeBin.value) {
++ ((char *) tmp) += sizeof(tmp->type) + sizeof(ipack_treenodeBin);
++ }
++ else {
++ tmp = tmp->data.nodeBin.right_child_ptr;
++ }
++ }
++ else if (tmp->type == TREENODETYPE_NODE_BINARY_LT) {
++ if (*(tmp->data.nodeBin.attribute_ptr) TREE_SUBTREE_RELATION_LEFT_LT tmp->data.nodeBin.value) {
++ ((char *) tmp) += sizeof(tmp->type) + sizeof(ipack_treenodeBin);
++ }
++ else {
++ tmp = tmp->data.nodeBin.right_child_ptr;
++ }
++ }
++ }
++ prob->high = 0;
++ prob->low = 0;
++// prob->max = 0;
++ if (tmp->type == TREENODETYPE_LEAF_P) {
++ u32 i;
++ u32 norm;
++// prob->max = tmp->data.leafP.probabilities[15];
++/* norm = (value * prob->max -1)/range;
++ for(i = 0; i < 15; ++i) {
++ if(tmp->data.leafP.probabilities[i] > norm) {
++ break;
++ }
++ }*/
++ norm = ((value << PROBABILITY_SHIFT) - 1);
++ for (i = 0; i < NUMBER_OF_TOKENS; ++i) {
++ if (range * tmp->data.leafP.probabilities[i] > norm) {
++ break;
++ }
++ }
++ token = (TokenType) i;
++ prob->high = tmp->data.leafP.probabilities[i];
++ if (token) {
++ prob->low = tmp->data.leafP.probabilities[token - 1];
++ }
++ }
++ else if (tmp->type == TREENODETYPE_LEAF_C) {
++ token = tmp->data.leafC.predicted_class;
++ prob->high = PROBABILITY_MAX;
++// prob->max = PROBABILITY_MAX;
++ }
++ return token;
++}
++#endif
++/*
++void ipack_model_predictortable_reset(PredictorType* ptr)
++{
++// register PredictorType* ptr = model->predictors_ptr;
++// register PredictorType* ptr = preds;
++ register PredictorType* end = ptr + NUMBER_OF_PREDICTORS;
++ while(ptr < end) {
++ *(ptr++) = 0;
++ }
++}
++
++void ipack_model_predictortable_update(PredictorType* ptr, TokenType token)
++{
++// register PredictorType* ptr = model->predictors_ptr;
++// register PredictorType* ptr = preds;
++ register u32 ndx = ptr[0] + 1;
++ ptr[ndx + 8] = ptr[ndx];
++ ptr[ndx] = token;
++ if(ndx == 8) {
++ ptr[0] = 0;
++ } else {
++ ++ ptr[0];
++ }
++}*/
++/****************************************************************************/
++
++#ifndef __KERNEL__
++static void ipack_model_countpreds(void *ptr, ipack_nodetype * node, double *table, double val)
++{
++ if ((node->type == TREENODETYPE_NODE_BINARY_EQ) || (node->type == TREENODETYPE_NODE_BINARY_LT)) {
++ table[(u32) (node->data.nodeBin.attribute_ptr) - (u32) (ptr)] += val;
++ ipack_model_countpreds(ptr, (void *) (((u8 *) (node)) + sizeof(node->type) + sizeof(ipack_treenodeBin)), table, val / 2);
++ ipack_model_countpreds(ptr, node->data.nodeBin.right_child_ptr, table, val / 2);
++ }
++ else {
++ }
++}
++
++/*static void ipack_model_printinfo(ipack_model_type * model)
++{
++ double *prcnt = jffs2_bbc_malloc(sizeof(double) * NUMBER_OF_PREDICTORS);
++ u32 i;
++ for (i = 0; i < NUMBER_OF_PREDICTORS; i++) {
++ prcnt[i] = 0.0;
++ }
++ ipack_model_countpreds(model->predictors_ptr, model->tree_root_ptr, prcnt, 100);
++ for (i = 0; i < NUMBER_OF_PREDICTORS; i++) {
++ jffs2_bbc_print3(" p[%3d] = %10.6lf\n", (int) i, prcnt[i]);
++ }
++ jffs2_bbc_free(prcnt);
++}*/
++
++static void ipack_dumpnode(unsigned char **ptr, FILE * file, char *prefs)
++{
++ switch (*((*ptr)++)) {
++ u32 i;
++ u32 j;
++ u32 x;
++ u32 y;
++ case TREENODETYPE_NODE_BINARY_EQ:
++ x = *((*ptr)++);
++ y = *((*ptr)++);
++ fprintf(file, "%s+->\tBinary node: P[%u] equals %u\n", prefs, (unsigned int)x, (unsigned int)y);
++ for (j = 0; j < 4096 && prefs[j]; ++j);
++ prefs[j] = '\t';
++ prefs[++j] = '|';
++ ipack_dumpnode(ptr, file, prefs);
++ prefs[j--] = 0;
++ ipack_dumpnode(ptr, file, prefs);
++ prefs[j] = 0;
++ break;
++ case TREENODETYPE_NODE_BINARY_LT:
++ x = *((*ptr)++);
++ y = *((*ptr)++);
++ fprintf(file, "%s+->\tBinary node: P[%u] greater than %u\n", prefs, (unsigned int)x, (unsigned int)y);
++ for (j = 0; j < 4096 && prefs[j]; ++j);
++ prefs[j] = '\t';
++ prefs[++j] = '|';
++ ipack_dumpnode(ptr, file, prefs);
++ prefs[j--] = 0;
++ ipack_dumpnode(ptr, file, prefs);
++ prefs[j] = 0;
++ break;
++ case TREENODETYPE_LEAF_P:
++ x = *((*ptr)++);
++ fprintf(file, "%s+->\tLeaf: %u pairs\n", prefs, (unsigned int)x);
++ (*ptr) += (x << 1);
++ break;
++ case TREENODETYPE_LEAF_C:
++ x = *((*ptr)++);
++ fprintf(file, "%s+->\tLeaf: class %u\n", prefs, (unsigned int)x);
++ break;
++ default:
++ fprintf(file, "%s+->\tLeaf: nullnode\n", prefs);
++ }
++}
++
++/*static void ipack_dumpmodel(void *model)
++{
++ unsigned char *tmp_ptr = model;
++ FILE *file;
++ char C[4096];
++ if ((file = fopen("DUMPED_MODEL", "wa"))) {
++ int i;
++ for (i = 0; i < 4096; C[i++] = 0);
++ tmp_ptr += 8;
++ tmp_ptr += sizeof(u32);
++ ipack_dumpnode(&tmp_ptr, file, C);
++ fclose(file);
++ }
++}*/
++
++#endif
++
++//ORIGIN: Builders/src/PredictorGenerator.c
++
++/*******************************************************************************
++* FILE: PredictorGenerator.c
++* AUTHOR: Tamás Gergely
++* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*******************************************************************************/
++
++//#include "ipack_common.h"
++//#include "Builders/PredictorGenerator.h"
++
++#ifdef JFFS2_BBC_ARMLIB_MODELGEN
++static PredictorTable *predictorgenerator_generate( /*PredictorGeneratorSettings* settings */ )
++{
++ PredictorTable *ptr = jffs2_bbc_malloc(sizeof(PredictorTable));
++ predictortable_clear(ptr);
++ ptr->predictors = jffs2_bbc_malloc(NUMBER_OF_PREDICTORS * sizeof(PredictorType));
++ return ptr;
++}
++#endif
++
++//ORIGIN: Builders/src/ipack_armlib_compressor.c
++
++/*******************************************************************************
++* FILE: ipack_armlim_compressor.c
++* AUTHOR: Tamás Gergely
++* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*******************************************************************************/
++
++//#include "ipack_common.h"
++//#include "DataStructures.h"
++//#include "Builders/PredictorGenerator.h"
++//#include "Builders/Tokenizer.h"
++//#include "Builders/Coder.h"
++
++#define EC_NO_ERROR 0
++#define EC_NOT_IPMF_FILE -1
++#define EC_NOT_IPMF_MODEL -2
++#define EC_NOT_HG_BLOCK -3
++#define EC_WRONG_INPUT_LENGTH -501
++#define EC_CODER_WRONG_PROBABILITY 1
++#define EC_CODER_WRONG_RANGE 2
++#define EC_BUFFER_OVERFLOW 501
++#define EC_BUFFER_UNDERFLOW 502
++#define EC_UNKNOWN_TOKEN_TYPE 1001
++#define EC_UNKNOWN_FILTER 1002
++#define EC_UNKNOWN_CONVERTER 1003
++#define EC_UNKNOWN_MANIPULATOR 1004
++
++/*******************************************************************************
++
++ COMPRESSOR INIT FUNCTIONS
++
++*******************************************************************************/
++
++#define ROUND_UP_TO_DWORD(val) ( ( (val) + 3 ) & 0xfffffffc )
++
++#ifndef __KERNEL__
++int ipack_glb_endian_X;
++#endif
++
++static int ipack_compressor_init_tree(unsigned char **ptr, ipack_model_type * model, ipack_nodetype * node, void *nullnode)
++{
++ int retval = 0;
++ node->type = *((*ptr)++);
++ switch (node->type) {
++ u32 i;
++ u32 j;
++ u32 lngth;
++ u32 tmpret;
++ TokenType at;
++ u16 av;
++ case TREENODETYPE_NODE_BINARY_EQ:
++ case TREENODETYPE_NODE_BINARY_LT:
++ node->data.nodeBin.attribute_ptr = (model->predictors_ptr) + (*((*ptr)++));
++ node->data.nodeBin.value = *((*ptr)++);
++ retval = sizeof(node->data.nodeBin);
++ retval += ipack_compressor_init_tree(ptr, model, (void *) ROUND_UP_TO_DWORD(((u32) node) + sizeof(node->type) + sizeof(node->data.nodeBin)), nullnode);
++ node->data.nodeBin.right_child_ptr = (void *) ROUND_UP_TO_DWORD(((u32) node) + retval + sizeof(node->type));
++ retval += ipack_compressor_init_tree(ptr, model, node->data.nodeBin.right_child_ptr, nullnode);
++ break;
++ case TREENODETYPE_LEAF_P:
++ lngth = *((*ptr)++);
++ av = 0;
++ for (i = 0, j = 0; i < lngth; ++i) {
++ at = *((*ptr)++);
++ while (j < at) {
++ node->data.leafP.probabilities[j++] = av;
++ }
++ av += *((*ptr)++);
++ }
++ while (j < NUMBER_OF_TOKENS) {
++ node->data.leafP.probabilities[j++] = av;
++ }
++ for (i = 0; i < NUMBER_OF_TOKENS; ++i) {
++ node->data.leafP.probabilities[i] = ((node->data.leafP.probabilities[i] << PROBABILITY_SHIFT) / node->data.leafP.probabilities[NUMBER_OF_TOKENS - 1]);
++ }
++ retval = ROUND_UP_TO_DWORD(NUMBER_OF_TOKENS * sizeof(u16));
++ break;
++ case TREENODETYPE_LEAF_C:
++ node->data.leafC.predicted_class = *((*ptr)++);
++ retval = sizeof(node->data.leafC);
++ retval = ROUND_UP_TO_DWORD(retval);
++ break;
++ default:
++ return 0;
++ }
++ return retval + sizeof(node->type);
++}
++
++#define IPACK_TREE_CONVERT_REPLACE 0
++#define IPACK_TREE_CONVERT_KEEP 1
++
++static void *ipack_tree_to_code(ipack_model_type * model, int *code_size);
++
++static int ipack_armlib_convert_tree_to_code(ipack_model_type * model_img, int mode)
++{
++#ifdef IPACK_TREE_TO_CODE
++ int tree_size;
++
++ model_img->tree_code = ipack_tree_to_code(model_img, &tree_size);
++ jffs2_bbc_print2("Convertation done. Code size=%d\n", tree_size);
++ if (mode == IPACK_TREE_CONVERT_REPLACE) {
++ jffs2_bbc_print1("Freeing original tree.\n");
++ jffs2_bbc_free(model_img->tree_root_ptr);
++ model_img->tree_root_ptr = NULL;
++ }
++#endif
++ return 0;
++}
++
++
++static int ipack_armlib_compressor_init(void **model)
++{
++ int retval = EC_NO_ERROR;
++ unsigned char *tmp_ptr = *model;
++ u32 i;
++ ipack_model_type *model_img;
++ char tmp_c[2];
++
++ if (*(tmp_ptr++) != 'i') {
++ return EC_NOT_IPMF_FILE;
++ }
++ else if (*(tmp_ptr++) != 'P') {
++ return EC_NOT_IPMF_FILE;
++ }
++ else if (*(tmp_ptr++) != 'M') {
++ return EC_NOT_IPMF_FILE;
++ }
++ else if (*(tmp_ptr++) != 'F') {
++ return EC_NOT_IPMF_FILE;
++ }
++ tmp_c[0] = *(tmp_ptr++);
++ tmp_c[1] = *(tmp_ptr++);
++ tmp_ptr += 2;
++
++ //model_img = jffs2_bbc_malloc(*((u32*)tmp_ptr));
++ model_img = jffs2_bbc_malloc(sizeof(ipack_model_type) + ROUND_UP_TO_DWORD(NUMBER_OF_PREDICTORS));
++ model_img->tree_root_ptr = jffs2_bbc_malloc(*((u32 *) tmp_ptr)); //it is smaller a little but, but...
++
++ tmp_ptr += sizeof(u32);
++
++ model_img->ID[0] = 'i';
++ model_img->ID[1] = 'P';
++ model_img->ID[2] = 'M';
++ model_img->ID[3] = 'F';
++
++ model_img->block_sign[0] = tmp_c[0];
++ model_img->block_sign[1] = tmp_c[1];
++
++ model_img->nullnode.type = TREENODETYPE_LEAF_P;
++ for (i = 0; i < NUMBER_OF_TOKENS; ++i) {
++ model_img->nullnode.probabilities[i] = 0;
++ }
++ model_img->predictors_ptr = (void *) (((u32) model_img) + sizeof(ipack_model_type));
++ //model_img->tree_root_ptr = (void*)ROUND_UP_TO_DWORD(((u32)(model_img->predictors_ptr)) + NUMBER_OF_PREDICTORS);//ALIGN
++
++ ipack_compressor_init_tree(&tmp_ptr, model_img, model_img->tree_root_ptr, &(model_img->nullnode));
++
++#ifdef IPACK_TREE_TO_CODE
++#ifdef IPACK_AUTO_TREE_TO_CODE
++ jffs2_bbc_print1("Automatically converting tree to ARM code...\n");
++ ipack_armlib_convert_tree_to_code(model_img, IPACK_TREE_CONVERT_REPLACE);
++#else
++ model_img->tree_code = NULL;
++#endif
++#else
++ model_img->tree_code = NULL;
++#endif
++
++ jffs2_bbc_free(*model);
++ *model = model_img;
++ return retval;
++}
++
++/*******************************************************************************
++
++ COMPRESSOR DEINIT FUNCTIONS
++
++*******************************************************************************/
++
++
++/* Descructor of compressor (model will be freed with jffs2_bbc_free() after it)*/
++static void ipack_armlib_compressor_deinit(void)
++{
++}
++
++/*******************************************************************************
++
++ COMPRESS FUNCTIONS
++
++*******************************************************************************/
++
++static int writebits0(unsigned char **dest, u8 * freebits, u32 * opposite, unsigned char *end)
++{
++ if (!(*freebits)) {
++ ++(*dest);
++ *freebits = 7;
++ **dest = 0x00;
++ }
++ else {
++ --(*freebits);
++ (**dest) <<= 1;
++ }
++ if ((*dest == end) && !(*freebits)) {
++ return EC_BUFFER_OVERFLOW;
++ }
++ while (*opposite) {
++ --(*opposite);
++ if (!(*freebits)) {
++ ++(*dest);
++ *freebits = 7;
++ **dest = 0x01;
++ }
++ else {
++ --(*freebits);
++ (**dest) <<= 1;
++ (**dest) |= 0x01;
++ }
++ if ((*dest == end) && !(*freebits)) {
++ return EC_BUFFER_OVERFLOW;
++ }
++ }
++ return 0;
++}
++
++static int writebits1(unsigned char **dest, u8 * freebits, u32 * opposite, unsigned char *end)
++{
++ if (!(*freebits)) {
++ ++(*dest);
++ *freebits = 7;
++ **dest = 0x01;
++ }
++ else {
++ --(*freebits);
++ (**dest) <<= 1;
++ (**dest) |= 0x01;
++ }
++ if ((*dest == end) && !(*freebits)) {
++ return EC_BUFFER_OVERFLOW;
++ }
++ while (*opposite) {
++ --(*opposite);
++ if (!(*freebits)) {
++ ++(*dest);
++ *freebits = 7;
++ **dest = 0x00;
++ }
++ else {
++ --(*freebits);
++ (**dest) <<= 1;
++ }
++ if ((*dest == end) && !(*freebits)) {
++ return EC_BUFFER_OVERFLOW;
++ }
++ }
++ return 0;
++}
++
++
++
++
++/* Compress block
++ * *dstlen bytes are allocated.
++ * if it is not enough write *sourcelen over to the processed amount of data
++ * returns non zero if fails
++ */
++static int ipack_armlib_compress(void *model, unsigned char *input, unsigned char *output, unsigned long *sourcelen, unsigned long *dstlen)
++{
++ register u32 coder_high = CODER_VALUEMAX - 1;
++ register u32 coder_low = 0;
++ u32 coder_opbits = 0;
++ u8 bitvector_freebits = 8;
++ unsigned char *bitvector_ptr = output;
++ unsigned char *bitvector_end = output + (*dstlen - 1);
++ ARM_DataType *tmpp;
++ TokenStream tmpv;
++ TokenType *it;
++ void *end_it;
++
++ ipack_nodetype *treeroot = ((ipack_model_type *) model)->tree_root_ptr;
++ PredictorType *predctrs = ((ipack_model_type *) model)->predictors_ptr;
++
++#ifdef IPACK_TREE_TO_CODE
++ void (*treefunc) (ipack_nodetype *, TokenType, ipack_probability_type *);
++
++ treefunc = ((ipack_model_type *) model)->tree_code;
++ if (treefunc != NULL)
++ treefunc += 4;
++#endif
++
++ if ((*sourcelen % 4) != 0) {
++ return EC_WRONG_INPUT_LENGTH;
++ }
++ if (*dstlen <= 4) {
++ return EC_BUFFER_OVERFLOW;
++ }
++
++ if (((ipack_model_type *) model)->ID[0] != 'i') {
++ return EC_NOT_IPMF_MODEL;
++ }
++ else if (((ipack_model_type *) model)->ID[1] != 'P') {
++ return EC_NOT_IPMF_MODEL;
++ }
++ else if (((ipack_model_type *) model)->ID[2] != 'M') {
++ return EC_NOT_IPMF_MODEL;
++ }
++ else if (((ipack_model_type *) model)->ID[3] != 'F') {
++ return EC_NOT_IPMF_MODEL;
++ }
++#ifdef TXT_TOKENS
++ tmpv.capacity = (*sourcelen);
++#else
++ tmpv.capacity = (*sourcelen) << 1;
++#endif
++ tmpv.size = tmpv.capacity;
++ tmpv.ptr = jffs2_bbc_malloc(tmpv.size);
++ it = tmpv.ptr;
++
++#ifndef __KERNEL__
++ if (ipack_glb_endian_X) {
++ for (tmpp = (void *) input; (u32) tmpp < (u32) (input + *sourcelen); ++tmpp) {
++#ifdef TXT_TOKENS
++ *(it++) = (u8) ((*tmpp & 0xff000000) >> 24);
++ *(it++) = (u8) ((*tmpp & 0x00ff0000) >> 16);
++ *(it++) = (u8) ((*tmpp & 0x0000ff00) >> 8);
++ *(it++) = (u8) ((*tmpp & 0x000000ff));
++#else
++ *(it++) = (u8) ((*tmpp & 0x0000f000) >> 12);
++ *(it++) = (u8) ((*tmpp & 0x0000000f));
++ *(it++) = (u8) ((*tmpp & 0xf0000000) >> 28);
++ *(it++) = (u8) ((*tmpp & 0x000f0000) >> 16);
++ *(it++) = (u8) ((*tmpp & 0x00000f00) >> 8);
++ *(it++) = (u8) ((*tmpp & 0x00f00000) >> 20);
++ *(it++) = (u8) ((*tmpp & 0x0f000000) >> 24);
++ *(it++) = (u8) ((*tmpp & 0x000000f0) >> 4);
++#endif //TXT_TOKENS
++ }
++ }
++ else {
++#endif
++ for (tmpp = (void *) input; (u32) tmpp < (u32) (input + *sourcelen); ++tmpp) {
++#ifdef TXT_TOKENS
++ *(it++) = (u8) ((*tmpp & 0x000000ff));
++ *(it++) = (u8) ((*tmpp & 0x0000ff00) >> 8);
++ *(it++) = (u8) ((*tmpp & 0x00ff0000) >> 16);
++ *(it++) = (u8) ((*tmpp & 0xff000000) >> 24);
++#else
++ *(it++) = (u8) ((*tmpp & 0x00f00000) >> 20);
++ *(it++) = (u8) ((*tmpp & 0x0f000000) >> 24);
++ *(it++) = (u8) ((*tmpp & 0x000000f0) >> 4);
++ *(it++) = (u8) ((*tmpp & 0x00000f00) >> 8);
++ *(it++) = (u8) ((*tmpp & 0x000f0000) >> 16);
++ *(it++) = (u8) ((*tmpp & 0x0000f000) >> 12);
++ *(it++) = (u8) ((*tmpp & 0x0000000f));
++ *(it++) = (u8) ((*tmpp & 0xf0000000) >> 28);
++#endif //TXT_TOKENS
++ }
++#ifndef __KERNEL__
++ }
++#endif
++/*
++ ENCODE
++*/
++ { //predictor reset
++ register PredictorType *ptr = predctrs;
++ register PredictorType *end = ptr + NUMBER_OF_PREDICTORS;
++ while (ptr < end) {
++ *(ptr++) = 0;
++ }
++ }
++
++ //*(bitvector_ptr++) = 'H';
++ //*(bitvector_ptr++) = 'G';
++ *(bitvector_ptr++) = ((ipack_model_type *) model)->block_sign[0];
++ *(bitvector_ptr++) = ((ipack_model_type *) model)->block_sign[1];
++
++ *(bitvector_ptr++) = (unsigned char) (((*sourcelen) >> 8) & 0xff);
++ *(bitvector_ptr++) = (unsigned char) ((*sourcelen) & 0xff);
++ for (it = tmpv.ptr, end_it = VECTOR_S_END(tmpv); it != end_it; ++it) {
++ ipack_probability_type prob;
++ u32 range;
++
++#ifdef IPACK_TREE_TO_CODE
++ if (treefunc != NULL)
++ (*treefunc) (treeroot, *it, &prob);
++ else
++ ipack_model_get_probability_for_token(treeroot, *it, &prob);
++#else
++ ipack_model_get_probability_for_token(treeroot, *it, &prob);
++#endif
++
++ if (prob.high == prob.low) {
++ vector_clear(&tmpv);
++ return EC_CODER_WRONG_PROBABILITY;
++ }
++ range = coder_high - coder_low + 1;
++ coder_high = coder_low + ((range * prob.high) >> PROBABILITY_SHIFT) - 1;
++ coder_low += ((range * prob.low) >> PROBABILITY_SHIFT);
++ for (;;) {
++ if (coder_high < CODER_VALUEHLF) {
++ if (writebits0(&bitvector_ptr, &bitvector_freebits, &coder_opbits, bitvector_end)) {
++ vector_clear(&tmpv);
++ return EC_BUFFER_OVERFLOW;
++ }
++ }
++ else if (coder_low >= CODER_VALUEHLF) {
++ if (writebits1(&bitvector_ptr, &bitvector_freebits, &coder_opbits, bitvector_end)) {
++ vector_clear(&tmpv);
++ return EC_BUFFER_OVERFLOW;
++ }
++ coder_high -= CODER_VALUEHLF;
++ coder_low -= CODER_VALUEHLF;
++ }
++ else if ((CODER_VALUE1ST <= coder_low) && (coder_high < CODER_VALUE3RD)) {
++ ++coder_opbits;
++ coder_high -= CODER_VALUE1ST;
++ coder_low -= CODER_VALUE1ST;
++ }
++ else {
++ break;
++ }
++ coder_high <<= 1;
++ ++coder_high;
++ coder_low <<= 1;
++ if (coder_high < coder_low) {
++ vector_clear(&tmpv);
++ return EC_CODER_WRONG_RANGE;
++ }
++ }
++ {
++#ifdef TXT_TOKENS
++// register u32 ndx;
++ predctrs[0] = *it;
++ if ((('a' <= *it) && (*it <= 'z')) || (('A' <= *it) && (*it <= 'Z'))) {
++ ++(predctrs[1]);
++ }
++ else {
++ predctrs[1] = 0;
++ }
++#else
++ register u32 ndx = predctrs[0] + 1;
++ predctrs[ndx + 8] = predctrs[ndx];
++ predctrs[ndx] = *it;
++ if (ndx == 8) {
++ predctrs[0] = 0;
++ }
++ else {
++ ++predctrs[0];
++ }
++#endif
++ }
++
++ }
++ vector_clear(&tmpv);
++ ++coder_opbits;
++ if (coder_low < CODER_VALUE1ST) {
++ if (writebits0(&bitvector_ptr, &bitvector_freebits, &coder_opbits, bitvector_end)) {
++ return EC_BUFFER_OVERFLOW;
++ }
++ }
++ else {
++ if (writebits1(&bitvector_ptr, &bitvector_freebits, &coder_opbits, bitvector_end)) {
++ return EC_BUFFER_OVERFLOW;
++ }
++ }
++ (*(bitvector_ptr)) <<= bitvector_freebits;
++ *dstlen = ((u32) bitvector_ptr - (u32) output + 1);
++ return EC_NO_ERROR;
++}
++
++/*******************************************************************************
++
++ DECOMPRESS FUNCTIONS
++
++*******************************************************************************/
++
++typedef struct
++{
++ u32 high;
++ u32 low;
++ u32 value;
++ u32 overread;
++} ipack_decompressor_values;
++
++typedef struct
++{
++ u8 freebits;
++ unsigned char *ptr;
++ unsigned char *end;
++} ipack_decompressor_bitvector;
++
++static u8 ipack_bitvector_R_get1(ipack_decompressor_bitvector * bv)
++{
++ u8 tmp;
++ if (bv->ptr == bv->end) {
++ bv->freebits = 0;
++ return 0;
++ }
++ tmp = (*(bv->ptr) >> bv->freebits) & 0x01;
++ if (!(bv->freebits)) {
++ bv->freebits = 7;
++ ++(bv->ptr);
++ }
++ else {
++ --(bv->freebits);
++ }
++ return tmp;
++}
++
++/* Decompress block
++ * returns non zero if fails
++ */
++static int ipack_armlib_decompress(void *model, unsigned char *input, unsigned char *output, unsigned long sourcelen, unsigned long dstlen)
++{
++ ARM_DataType *data;
++ register u32 coder_high = CODER_VALUEMAX - 1;
++ register u32 coder_low = 0;
++ register u32 coder_value = 0;
++ u32 coder_overread = 0;
++ ipack_decompressor_bitvector bitvector;
++ u32 lngth;
++ u32 i;
++ u32 cntbytes;
++ TokenType tkns[8];
++ TokenType *tptr;
++
++ ipack_nodetype *treeroot = ((ipack_model_type *) model)->tree_root_ptr;
++ PredictorType *predctrs = ((ipack_model_type *) model)->predictors_ptr;
++
++#ifdef IPACK_TREE_TO_CODE
++ TokenType(*treefunc) (ipack_nodetype *, u32, u32, ipack_probability_type *);
++
++ treefunc = ((ipack_model_type *) model)->tree_code;
++#endif
++
++
++ if (((ipack_model_type *) model)->ID[0] != 'i') {
++ return EC_NOT_IPMF_MODEL;
++ }
++ else if (((ipack_model_type *) model)->ID[1] != 'P') {
++ return EC_NOT_IPMF_MODEL;
++ }
++ else if (((ipack_model_type *) model)->ID[2] != 'M') {
++ return EC_NOT_IPMF_MODEL;
++ }
++ else if (((ipack_model_type *) model)->ID[3] != 'F') {
++ return EC_NOT_IPMF_MODEL;
++ }
++
++ bitvector.freebits = 7;
++ bitvector.ptr = input;
++ bitvector.end = input + sourcelen;
++
++ /*if(*(bitvector.ptr++) != 'H') {
++ return EC_NOT_HG_BLOCK;
++ } else if(*(bitvector.ptr++) != 'G') {
++ return EC_NOT_HG_BLOCK;
++ } */
++ bitvector.ptr++;
++ bitvector.ptr++;
++
++ data = (void *) output;
++ cntbytes = *(bitvector.ptr++);
++ cntbytes <<= 8;
++ cntbytes += *(bitvector.ptr++);
++
++ { //predictor reset
++ register PredictorType *ptr = predctrs;
++ register PredictorType *end = ptr + NUMBER_OF_PREDICTORS;
++ while (ptr < end) {
++ *(ptr++) = 0;
++ }
++ }
++ for (i = 0; i < CODER_VALUEBITS; ++i) {
++ coder_value <<= 1;
++ coder_value += ipack_bitvector_R_get1(&bitvector);
++ }
++ lngth = dstlen >> 2;
++ if (lngth > (cntbytes >> 2)) {
++ lngth = cntbytes >> 2;
++ }
++ for (i = 0; (i < lngth); ++i) {
++ TokenType itoken;
++ u32 j;
++ tptr = tkns;
++ for (j = 0; j < NUMBER_OF_TOKENS_PER_INSTRUCTION; ++j) {
++ ipack_probability_type prob;
++ u32 range = coder_high - coder_low + 1;
++
++#ifdef IPACK_TREE_TO_CODE
++ if (treefunc != NULL)
++ itoken = (*treefunc) (treeroot, coder_value - coder_low + 1, range, &prob);
++ else
++#endif
++ itoken = ipack_model_get_token_for_range(treeroot, coder_value - coder_low + 1, range, &prob);
++
++
++ if (prob.high == prob.low) {
++ return EC_CODER_WRONG_PROBABILITY;
++ }
++ coder_high = coder_low + ((range * prob.high) >> PROBABILITY_SHIFT) - 1;
++ coder_low += ((range * prob.low) >> PROBABILITY_SHIFT);
++ for (;;) {
++ if (coder_high < CODER_VALUEHLF) {
++ }
++ else if (CODER_VALUEHLF <= coder_low) {
++ coder_value -= CODER_VALUEHLF;
++ coder_high -= CODER_VALUEHLF;
++ coder_low -= CODER_VALUEHLF;
++ }
++ else if ((CODER_VALUE1ST <= coder_low) && (coder_high < CODER_VALUE3RD)) {
++ coder_value -= CODER_VALUE1ST;
++ coder_high -= CODER_VALUE1ST;
++ coder_low -= CODER_VALUE1ST;
++ }
++ else {
++ break;
++ }
++ coder_low <<= 1;
++ coder_high <<= 1;
++ ++(coder_high);
++ coder_value <<= 1;
++ if (bitvector.ptr == bitvector.end) {
++ bitvector.freebits = 0;
++ }
++ coder_value += ((*(bitvector.ptr) >> bitvector.freebits) & 0x01);
++ if (bitvector.freebits) {
++ --bitvector.freebits;
++ }
++ else {
++ bitvector.freebits = 7;
++ ++bitvector.ptr;
++ }
++ if (coder_high < coder_low) {
++ return EC_CODER_WRONG_RANGE;
++ }
++ if ((bitvector.ptr == bitvector.end) && !(bitvector.freebits)) {
++ if ((coder_overread++) > CODER_VALUEBITS) {
++ return EC_BUFFER_UNDERFLOW;
++ }
++ }
++ }
++ {
++#ifdef TXT_TOKENS
++// register u32 ndx;
++ predctrs[0] = itoken;
++ if ((('a' <= itoken) && (itoken <= 'z')) || (('A' <= itoken) && (itoken <= 'Z'))) {
++ ++(predctrs[1]);
++ }
++ else {
++ predctrs[1] = 0;
++ }
++
++#else
++ register u32 ndx = predctrs[0] + 1;
++ predctrs[ndx + 8] = predctrs[ndx];
++ predctrs[ndx] = itoken;
++ if (ndx == 8) {
++ predctrs[0] = 0;
++ }
++ else {
++ ++predctrs[0];
++ }
++#endif
++ }
++
++ (*(tptr++)) = itoken;
++ }
++ tptr = tkns;
++#ifndef __KERNEL__
++ if (ipack_glb_endian_X) {
++#ifdef TXT_TOKENS
++ (*data) = ((*tptr) << 24);
++ ++tptr;
++ (*data) |= ((*tptr) << 16);
++ ++tptr;
++ (*data) |= ((*tptr) << 8);
++ ++tptr;
++ (*data) |= (*tptr);
++ ++data;
++#else
++ (*data) = (((*tptr) & 0xf) << 12);
++ ++tptr;
++ (*data) |= ((*tptr) & 0xf);
++ ++tptr;
++ (*data) |= (((*tptr) & 0xf) << 28);
++ ++tptr;
++ (*data) |= (((*tptr) & 0xf) << 16);
++ ++tptr;
++ (*data) |= (((*tptr) & 0xf) << 8);
++ ++tptr;
++ (*data) |= (((*tptr) & 0xf) << 20);
++ ++tptr;
++ (*data) |= (((*tptr) & 0xf) << 24);
++ ++tptr;
++ (*data) |= (((*tptr) & 0xf) << 4);
++ ++data;
++#endif
++ }
++ else {
++#endif
++#ifdef TXT_TOKENS
++ (*data) = (*tptr);
++ ++tptr;
++ (*data) |= ((*tptr) << 8);
++ ++tptr;
++ (*data) |= ((*tptr) << 16);
++ ++tptr;
++ (*data) |= ((*tptr) << 24);
++ ++data;
++#else
++ (*data) = (((*tptr) & 0xf) << 20);
++ ++tptr;
++ (*data) |= (((*tptr) & 0xf) << 24);
++ ++tptr;
++ (*data) |= (((*tptr) & 0xf) << 4);
++ ++tptr;
++ (*data) |= (((*tptr) & 0xf) << 8);
++ ++tptr;
++ (*data) |= (((*tptr) & 0xf) << 16);
++ ++tptr;
++ (*data) |= (((*tptr) & 0xf) << 12);
++ ++tptr;
++ (*data) |= ((*tptr) & 0xf);
++ ++tptr;
++ (*data) |= (((*tptr) & 0xf) << 28);
++ ++data;
++#endif
++#ifndef __KERNEL__
++ }
++#endif
++ }
++ return EC_NO_ERROR;
++}
++
++static int ipack_armlib_estimate(void *model, unsigned char *input, unsigned long sourcelen, unsigned long *dstlen, unsigned long *readtime, unsigned long *writetime)
++{
++ int i, tmp, tmp2, max, maxi;
++ int cnt_cond[] = { 0, 0, 0, 0 };
++ int cnt_inst[] = { 0, 0, 0, 0 };
++
++ // TODO: make a more precise estimation!!!
++ *readtime = JFFS2_BBC_ZLIB_READ_TIME * 6;
++ *writetime = JFFS2_BBC_ZLIB_WRITE_TIME * 2;
++
++ if (sourcelen % 4 != 0) {
++ *dstlen = sourcelen;
++ return 0;
++ }
++ for (i = 0; i < sourcelen; i++, input++) {
++ tmp2 = tmp = *input;
++ tmp = ((tmp) & 0xf0) >> 4;
++ tmp2 = tmp2 & 0xf;
++ if (tmp == 14)
++ cnt_cond[i % 4]++;
++ if ((tmp2 == 2) || (tmp2 == 3))
++ cnt_inst[i % 4]++;
++ }
++ maxi = -1;
++ max = -1;
++ for (i = 0; i < 4; i++)
++ if (max < cnt_cond[i]) {
++ max = cnt_cond[i];
++ maxi = i;
++ }
++ /*jffs2_bbc_print("armlib_EST: %d/%d : %d/%d %d/%d %d/%d %d/%d",
++ cnt_cond[maxi],cnt_inst[maxi],
++ cnt_cond[0],cnt_inst[0],
++ cnt_cond[1],cnt_inst[1],
++ cnt_cond[2],cnt_inst[2],
++ cnt_cond[3],cnt_inst[3]); */
++
++ if (cnt_cond[maxi] < (sourcelen >> 4)) {
++ *dstlen = sourcelen;
++ }
++ else {
++ *dstlen = sourcelen / 3;
++ }
++
++ return 0;
++}
++
++static char *ipack_armlib_proc_info(void);
++static int ipack_armlib_proc_command(char *command);
++static void ipack_armlib_destroy_model(void **model);
++
++struct jffs2_bbc_compressor_type jffs2_bbc_armlib = {
++ "armlib",
++ 0x464d5069,
++ {0, 0, 0, 0},
++ NULL, // init
++ ipack_armlib_compressor_init, // init_model
++ ipack_armlib_destroy_model, // destroy_model
++ ipack_armlib_compressor_deinit, // deinit
++ ipack_armlib_compress,
++ ipack_armlib_estimate,
++ ipack_armlib_decompress,
++ ipack_armlib_proc_info,
++ ipack_armlib_proc_command
++};
++
++
++static char *ipack_armlib_proc_info()
++{
++#ifdef IPACK_TREE_TO_CODE
++#ifdef IPACK_AUTO_TREE_TO_CODE
++ return "automatic tree to code conversion";
++#else
++ return "manual tree to code conversion possibility";
++#endif
++#else
++ return "tree in memory version";
++#endif
++}
++
++static int ipack_armlib_proc_command(char *command)
++{
++ struct jffs2_bbc_model_list_node *model;
++ ipack_model_type *armlib_model;
++
++ if ((*command == 'g') || (*command == 'G')) {
++ jffs2_bbc_print1("Converting tree(s) to ARM code... (keeping original)\n");
++ model = jffs2_bbc_armlib.models;
++ if (model == NULL)
++ jffs2_bbc_print1("no model found!\n");
++ while (model != NULL) {
++ armlib_model = model->model;
++ if (armlib_model == NULL) {
++ jffs2_bbc_print1("Error: NULL model!\n");
++ }
++ else {
++ ipack_armlib_convert_tree_to_code(armlib_model, IPACK_TREE_CONVERT_KEEP);
++ }
++ model = model->next_compr_model;
++ }
++ }
++ else if ((*command == 'r') || (*command == 'R')) {
++ jffs2_bbc_print1("Converting tree(s) to ARM code... (deleting original)\n");
++ model = jffs2_bbc_armlib.models;
++ if (model == NULL)
++ jffs2_bbc_print1("no model found!\n");
++ while (model != NULL) {
++ armlib_model = model->model;
++ if (armlib_model == NULL) {
++ jffs2_bbc_print1("Error: NULL model!\n");
++ }
++ else {
++ //armlib_model->tree_code = ipack_tree_to_code(armlib_model, &tree_size);
++ //jffs2_bbc_print("Convertation done. Code size=%d\n",tree_size);
++ ipack_armlib_convert_tree_to_code(armlib_model, IPACK_TREE_CONVERT_REPLACE);
++ }
++ model = model->next_compr_model;
++ }
++ }
++ else if ((*command == 'c') || (*command == 'C')) {
++ jffs2_bbc_print1("Deleting ARM representation of the tree(s)...\n");
++ model = jffs2_bbc_armlib.models;
++ if (model == NULL)
++ jffs2_bbc_print1("no model found!\n");
++ while (model != NULL) {
++ armlib_model = model->model;
++ if (armlib_model == NULL) {
++ jffs2_bbc_print1("Error: NULL model!\n");
++ }
++ else {
++ if (armlib_model->tree_code == NULL) {
++ jffs2_bbc_print1("already deleted.\n");
++ }
++ else {
++ if (armlib_model->tree_root_ptr == NULL) {
++ jffs2_bbc_print1("cannot delete this ARM tree - original tree has deleted\n");
++ }
++ else {
++ jffs2_bbc_print1("deleting...");
++ jffs2_bbc_free(armlib_model->tree_code);
++ armlib_model->tree_code = NULL;
++ jffs2_bbc_print1("done.\n");
++ }
++ }
++ }
++ model = model->next_compr_model;
++ }
++ }
++ else if (*command == '?') {
++ jffs2_bbc_print1("ARMLIB commands:\n");
++ jffs2_bbc_print1(" g: convert TREEs to ARM code and keep the original\n");
++ jffs2_bbc_print1(" r: convert TREEs to ARM code and remove the original\n");
++ jffs2_bbc_print1(" c: delete the original TREEs - if there is any\n");
++ }
++ else {
++ jffs2_bbc_print1("Unknown command.\n");
++ }
++ return 0;
++}
++
++static void ipack_armlib_destroy_model(void **model)
++{
++ ipack_model_type *model_img;
++
++ model_img = *model;
++ if (model_img == NULL) {
++ jffs2_bbc_print1("jffs2.bbc: armlib: NULL model at destoying model!\n");
++ return;
++ }
++ if (model_img->tree_code != NULL) {
++ //jffs2_bbc_print1("jffs2.bbc: armlib: debug: freeing code...\n");
++ jffs2_bbc_free(model_img->tree_code);
++ model_img->tree_code = NULL;
++ }
++ if (model_img->tree_root_ptr != NULL) {
++ //jffs2_bbc_print1("jffs2.bbc: armlib: debug: freeing tree...\n");
++ jffs2_bbc_free(model_img->tree_root_ptr);
++ model_img->tree_root_ptr = NULL;
++ }
++
++ jffs2_bbc_free(model_img);
++ *model = NULL;
++}
++
++struct jffs2_bbc_compressor_type *jffs2_bbc_armlib_init(int mode)
++{
++ if (jffs2_bbc_register_compressor(&jffs2_bbc_armlib) == 0)
++ return &jffs2_bbc_armlib;
++ else
++ return NULL;
++}
++
++void jffs2_bbc_armlib_deinit(void)
++{
++ jffs2_bbc_unregister_compressor(&jffs2_bbc_armlib);
++}
++
++/*END OF ARMLIB*/
+diff -Nur linux-mips-cvs/fs/jffs2/jffs2_bbc_framework.c linux-mips/fs/jffs2/jffs2_bbc_framework.c
+--- linux-mips-cvs/fs/jffs2/jffs2_bbc_framework.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips/fs/jffs2/jffs2_bbc_framework.c 2005-02-07 05:08:34.000000000 +0100
+@@ -0,0 +1,1324 @@
++/*
++ * JFFS2-BBC: Compression Framework
++ *
++ * $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++ *
++ * Copyright (C) 2004, Ferenc Havasi
++ *
++ * 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.
++ *
++ */
++
++/* USE JFFS2_BBC_STANDALONE define if you don't want to compile without JFFS2 */
++
++//#define DEBUG_COMPRESSORS
++//#define DEBUG_SHOW_BLOCK_SIZES
++
++#define JFFS2_BBC_STAT_BUFF_SIZE 8000
++
++#ifndef __KERNEL__
++
++#include <stdio.h>
++#include <malloc.h>
++typedef unsigned long uint32_t;
++
++#else
++
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++
++#endif
++
++#define JFFS2_BBC_ZLIB_BLOCK_SIGN_0 (120)
++#define JFFS2_BBC_ZLIB_BLOCK_SIGN_1 (94)
++
++#define JFFS2_BBC_DUMMY_BLOCKSIGN_0 (0x54)
++#define JFFS2_BBC_DUMMY_BLOCKSIGN_1 (0x01)
++
++#ifndef NULL
++#define NULL ((void*)(0))
++#endif
++
++#include "jffs2_bbc_framework.h"
++
++/*********************************************************************
++ * Global data *
++ *********************************************************************/
++
++static int jffs2_bbc_compression_mode = JFFS2_BBC_ZLIB_MODE;
++static struct jffs2_bbc_compressor_type *jffs2_bbc_manual_compressor = NULL;
++static struct jffs2_bbc_compressor_type *jffs2_bbc_compressors = NULL;
++static struct jffs2_bbc_model_list_node *jffs2_bbc_model_list = NULL;
++static void *last_sb = NULL; /* previously activated sb */
++
++/*********************************************************************
++ * Compressor initialization *
++ *********************************************************************/
++
++#ifndef JFFS2_BBC_STANDALONE
++
++#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_ARMLIB)
++struct jffs2_bbc_compressor_type *jffs2_bbc_armlib_init(void);
++void jffs2_bbc_armlib_deinit(void);
++#endif
++
++#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZO)
++struct jffs2_bbc_compressor_type *jffs2_bbc_lzo_init(void);
++void jffs2_bbc_lzo_deinit(void);
++#endif
++
++#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZSS)
++struct jffs2_bbc_compressor_type *jffs2_bbc_lzss_init(void);
++void jffs2_bbc_lzss_deinit(void);
++#endif
++
++#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZARI)
++struct jffs2_bbc_compressor_type *jffs2_bbc_lzari_init(void);
++void jffs2_bbc_lzari_deinit(void);
++#endif
++
++#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZHD)
++struct jffs2_bbc_compressor_type *jffs2_bbc_lzhd_init(void);
++void jffs2_bbc_lzhd_deinit(void);
++#endif
++
++void jffs2_bbc_compressor_init()
++{
++#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_ARMLIB)
++ jffs2_bbc_armlib_init();
++#endif
++#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZO)
++ jffs2_bbc_lzo_init();
++#endif
++#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZSS)
++ jffs2_bbc_lzss_init();
++#endif
++#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZARI)
++ jffs2_bbc_lzari_init();
++#endif
++#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZHD)
++ jffs2_bbc_lzhd_init();
++#endif
++}
++
++void jffs2_bbc_compressor_deinit()
++{
++#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZHD)
++ jffs2_bbc_lzhd_deinit();
++#endif
++#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZARI)
++ jffs2_bbc_lzari_deinit();
++#endif
++#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZSS)
++ jffs2_bbc_lzss_deinit();
++#endif
++#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZO)
++ jffs2_bbc_lzo_deinit();
++#endif
++#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_ARMLIB)
++ jffs2_bbc_armlib_deinit();
++#endif
++}
++
++#endif
++
++#ifndef JFFS2_BBC_STANDALONE
++
++/*********************************************************************
++ * ZLIB COMPRESSOR *
++ *********************************************************************/
++
++extern int jffs2_zlib_compress2(unsigned char *data_in, unsigned char *cpage_out, uint32_t * sourcelen, uint32_t * dstlen);
++extern void jffs2_zlib_decompress2(unsigned char *data_in, unsigned char *cpage_out, uint32_t srclen, uint32_t destlen);
++
++static int jffs2_bbc_zlib_compress(void *model, unsigned char *input, unsigned char *output, unsigned long *sourcelen, unsigned long *dstlen)
++{
++ return jffs2_zlib_compress2(input, output, sourcelen, dstlen);
++}
++
++static int jffs2_bbc_zlib_decompress(void *model, unsigned char *input, unsigned char *output, unsigned long sourcelen, unsigned long dstlen)
++{
++ jffs2_zlib_decompress2(input, output, sourcelen, dstlen);
++ return 0;
++}
++
++static int jffs2_bbc_zlib_estimate(void *model, unsigned char *input, unsigned long sourcelen, unsigned long *dstlen, unsigned long *readtime, unsigned long *writetime)
++{
++ *dstlen = sourcelen * 65 / 100;
++ *readtime = JFFS2_BBC_ZLIB_READ_TIME;
++ *writetime = JFFS2_BBC_ZLIB_WRITE_TIME;
++ return 0;
++}
++
++static struct jffs2_bbc_compressor_type jffs2_bbc_zlib = {
++ "zlib",
++ 0,
++ {JFFS2_BBC_ZLIB_BLOCK_SIGN_0, JFFS2_BBC_ZLIB_BLOCK_SIGN_1, 0, 0},
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ jffs2_bbc_zlib_compress,
++ jffs2_bbc_zlib_estimate,
++ jffs2_bbc_zlib_decompress,
++ NULL,
++ NULL,
++ 1
++};
++
++static struct jffs2_bbc_compressor_type *jffs2_bbc_original_compressor = &jffs2_bbc_zlib;
++
++#endif
++
++/*********************************************************************
++ * Compression mode handling *
++ *********************************************************************/
++
++int jffs2_bbc_get_compression_mode(void)
++{
++ return jffs2_bbc_compression_mode;
++}
++
++void jffs2_bbc_set_compression_mode(int mode)
++{
++ jffs2_bbc_compression_mode = mode;
++}
++
++void jffs2_bbc_set_manual_compressor(struct jffs2_bbc_compressor_type *c)
++{
++ jffs2_bbc_manual_compressor = c;
++ jffs2_bbc_set_compression_mode(JFFS2_BBC_MANUAL_MODE);
++}
++
++int jffs2_bbc_set_manual_compressor_by_name(char *name)
++{
++ struct jffs2_bbc_compressor_type *l;
++ int i;
++
++ l = jffs2_bbc_compressors;
++ while (l != NULL) {
++ for (i = 0; i < 1000; i++) {
++ if (l->name[i] == 0) {
++ jffs2_bbc_set_manual_compressor(l);
++ return 0;
++ }
++ else if (name[i] == 0)
++ i = 1000;
++ else if (name[i] != l->name[i])
++ i = 1000;
++ }
++ l = l->next;
++ }
++ jffs2_bbc_set_manual_compressor(NULL);
++ return 1;
++}
++
++static struct jffs2_bbc_compressor_type *jffs2_bbc_get_compressor_by_name(char *name)
++{
++ struct jffs2_bbc_compressor_type *l;
++ int i;
++
++#ifndef JFFS2_BBC_STANDALONE
++ l = jffs2_bbc_original_compressor;
++ for (i = 0; i < 1000; i++) {
++ if (l->name[i] == 0) {
++ return l;
++ }
++ else if (name[i] == 0)
++ i = 1000;
++ else if (name[i] != l->name[i])
++ i = 1000;
++ }
++#endif
++
++ l = jffs2_bbc_compressors;
++ while (l != NULL) {
++ for (i = 0; i < 1000; i++) {
++ if (l->name[i] == 0) {
++ return l;
++ }
++ else if (name[i] == 0)
++ i = 1000;
++ else if (name[i] != l->name[i])
++ i = 1000;
++ }
++ l = l->next;
++ }
++
++ return NULL;
++}
++
++int jffs2_bbc_disable_compressor_by_name(char *name)
++{
++ struct jffs2_bbc_compressor_type *l;
++
++ l = jffs2_bbc_get_compressor_by_name(name);
++ if (l == NULL) return 1;
++ l->enabled = 0;
++ return 0;
++}
++
++int jffs2_bbc_enable_compressor_by_name(char *name)
++{
++ struct jffs2_bbc_compressor_type *l;
++
++ l = jffs2_bbc_get_compressor_by_name(name);
++ if (l == NULL) return 1;
++ l->enabled = 1;
++ return 0;
++}
++
++void jffs2_bbc_compressor_command_by_name(char *name_and_command)
++{
++ struct jffs2_bbc_compressor_type *l;
++ int i;
++
++ l = jffs2_bbc_compressors;
++ while (l != NULL) {
++ for (i = 0; i < 1000; i++) {
++ if (l->name[i] == 0) {
++ if (name_and_command[i] != ':') {
++ jffs2_bbc_print1("jffs2.bbc: ':' missing after compressor name\n");
++ }
++ else {
++ if (l->proc_command != NULL)
++ l->proc_command(name_and_command + i + 1);
++ }
++ i = 1000;
++ return;
++ }
++ else if (name_and_command[i] == 0) {
++ i = 1000;
++ }
++ else if (name_and_command[i] != l->name[i]) {
++ i = 1000;
++ }
++ }
++ l = l->next;
++ }
++}
++
++struct jffs2_bbc_compressor_type *jffs2_bbc_get_manual_compressor(void)
++{
++ if (jffs2_bbc_get_compression_mode() != JFFS2_BBC_MANUAL_MODE) {
++ jffs2_bbc_manual_compressor = NULL;
++ }
++ return jffs2_bbc_manual_compressor;
++}
++
++/*********************************************************************
++ * Compressor handling *
++ *********************************************************************/
++
++struct jffs2_bbc_compressor_type *jffs2_bbc_get_compressor_list(void)
++{
++ return jffs2_bbc_compressors;
++}
++
++struct jffs2_bbc_model_list_node *jffs2_bbc_get_model_list(void)
++{
++ return jffs2_bbc_model_list;
++}
++
++int jffs2_bbc_register_compressor(struct jffs2_bbc_compressor_type *c)
++{
++ struct jffs2_bbc_compressor_type *l;
++ struct jffs2_bbc_model_list_node *l2;
++ int model_found = 0;
++
++ l = jffs2_bbc_compressors;
++ /* Check for confilcts */
++ while (l != NULL) {
++ c->name[15] = 0;
++ /*if (strcmp(c->name,l->name)==0) {
++ jffs2_bbc_print1("jffs2.bbc: compressor is already loaded.");
++ return -1;
++ } */
++ if ((l->model_file_sign == c->model_file_sign) && (c->model_file_sign != 0)) {
++ jffs2_bbc_print1("jffs2.bbc: already used model file sign. fail.");
++ return -1;
++ }
++ l = l->next;
++ }
++ /* Search and initialize model */
++ c->models = NULL;
++ c->mounted = 0;
++ if (c->init != NULL) {
++ if (c->init() != 0) {
++ jffs2_bbc_print2("jffs2.bbc: cannot initialize compressor %s.\n", c->name);
++ return -1;
++ }
++ }
++ if (c->model_file_sign != 0) {
++ l2 = jffs2_bbc_model_list;
++ while (1) {
++ if (l2 == NULL)
++ break;
++ if (c->model_file_sign == l2->sign) {
++ if (l2->compressor != NULL) {
++ jffs2_bbc_print2("jffs2.bbc: register for %s: BUG, model file already reserved!!!!\n", c->name);
++ }
++ else {
++ if (c->init_model(&(l2->model)) != 0) {
++ jffs2_bbc_print2("jffs2.bbc: cannot initialize compressor %s for a model", c->name);
++ }
++ else {
++ l2->compressor = c;
++ l2->next_compr_model = c->models;
++ c->models = l2;
++ c->mounted++;
++ model_found++;
++ }
++ }
++ }
++ l2 = l2->next_model;
++ }
++ /*if (model_found==0) {
++ jffs2_bbc_print2("jffs2.bbc: no macthing model file found for %s at this time (maybe later)\n",c->name);
++ } */
++ }
++ /* Insert to the end of the compressor list */
++ c->enabled = 1;
++ c->buffer = NULL;
++ c->buffer_size = 0;
++ c->stat_compr_orig = c->stat_compr_new = c->stat_decompr = 0;
++ c->next = NULL;
++ if (jffs2_bbc_compressors == NULL) {
++ jffs2_bbc_compressors = c;
++ }
++ else {
++ l = jffs2_bbc_compressors;
++ while (l->next != NULL)
++ l = l->next;
++ l->next = c;
++ }
++ return 0;
++}
++
++int jffs2_bbc_unregister_compressor(struct jffs2_bbc_compressor_type *c)
++{
++ struct jffs2_bbc_compressor_type *l;
++ struct jffs2_bbc_model_list_node *l2;
++
++ if (c->mounted != 0) {
++ jffs2_bbc_print1("jffs2.bbc: Compressor is in use. Sorry.");
++ return -1;
++ }
++ if (jffs2_bbc_compressors == NULL) {
++ jffs2_bbc_print1("jffs2.bbc: unregister: empty list.");
++ return -1;
++ }
++ else if (jffs2_bbc_compressors == c) {
++ if (c->deinit != NULL)
++ c->deinit();
++ jffs2_bbc_compressors = c->next;
++ }
++ else {
++ l = jffs2_bbc_compressors;
++ while (l->next != c) {
++ if (l->next == NULL) {
++ jffs2_bbc_print2("jffs2.bbc: unregister: cannot find compressor %s in the list.", c->name);
++ return -1;
++ }
++ l = l->next;
++ }
++ if (c->deinit != NULL)
++ c->deinit();
++ l->next = c->next;
++ }
++ if (c->buffer != NULL) {
++ jffs2_bbc_free(c->buffer);
++ c->buffer = NULL;
++ c->buffer_size = 0;
++ }
++
++ l2 = jffs2_bbc_model_list;
++ while (l2 != NULL) {
++ if (l2->compressor == c) {
++ jffs2_bbc_print1("jffs2.bbc: unregister: BUG: model found!!!");
++ l2->compressor = NULL;
++ l2->next_compr_model = NULL;
++ }
++ l2 = l2->next_model;
++ }
++
++ return 0;
++}
++
++int jffs2_bbc_model_new(void *sb, int i_num, void *model)
++{
++ struct jffs2_bbc_model_list_node *node;
++ struct jffs2_bbc_compressor_type *l;
++ char block_sign[2];
++
++ int sign;
++
++ /* check for conflicts... */
++ sign = *((int *) model);
++ block_sign[0] = *(((char *) model) + 4);
++ block_sign[1] = *(((char *) model) + 5);
++ node = jffs2_bbc_model_list;
++ while (node != NULL) {
++ if ((node->block_sign[0] == block_sign[0]) && (node->block_sign[1] == block_sign[1]) && (node->sb == sb)) {
++ //jffs2_bbc_print2("jffs2.bbc: model_new: model conflict (inode=%d)!\n",i_num);
++ return -1;
++ }
++ node = node->next_model;
++ }
++
++ /* insertion */
++ node = jffs2_bbc_malloc_small((long)sizeof(struct jffs2_bbc_model_list_node));
++ node->sb = sb;
++ node->model = model;
++ node->sign = *((int *) model);
++ node->block_sign[0] = *(((char *) model) + 4);
++ node->block_sign[1] = *(((char *) model) + 5);
++ node->inode = i_num;
++ node->next_model = jffs2_bbc_model_list;
++ node->compressor = NULL;
++ node->stat_decompr = 0;
++ node->next_compr_model = NULL;
++ jffs2_bbc_model_list = node;
++
++ /* search for matching compressor */
++ l = jffs2_bbc_compressors;
++ while (l != NULL) {
++ if (l->model_file_sign == sign) {
++ //jffs2_bbc_print2("jffs2.bbc: compressor for model found: %s ",l->name);
++ if (l->init_model(&(node->model)) != 0) {
++ jffs2_bbc_print1("jffs2.bbc: cannot initialize compressor for a model");
++ }
++ else {
++ l->mounted++;
++ node->compressor = l;
++ node->next_compr_model = l->models;
++ l->models = node;
++ }
++ break;
++ }
++ l = l->next;
++ }
++ return 0;
++}
++
++static void jffs2_bbc_model_del_from_compressor(struct jffs2_bbc_model_list_node *node)
++{
++ struct jffs2_bbc_model_list_node *l;
++
++ if (node->model != NULL) {
++ if (node->compressor != NULL) {
++ if (node->compressor->destroy_model == NULL) {
++ jffs2_bbc_free(node->model);
++ node->model = NULL;
++ }
++ else {
++ node->compressor->destroy_model(&(node->model));
++ if (node->model != NULL)
++ jffs2_bbc_print1("jffs2.bbc: warning: not NULL model after destroying!\n");
++ }
++ }
++ }
++
++ if (node->compressor == NULL) {
++ jffs2_bbc_print1("jffs2.bbc: jffs2_bbc_model_del_from_compressor: no compressor!\n");
++ return;
++ }
++ l = node->compressor->models;
++ if (l == NULL) {
++ jffs2_bbc_print1("jffs2.bbc: jffs2_bbc_model_del_from_compressor error, models=NULL!\n");
++ return;
++ }
++ if (l == node) {
++ node->compressor->models = node->next_compr_model;
++ node->compressor->mounted--;
++ return;
++ }
++ while (1) {
++ if (l->next_compr_model == node) {
++ l->next_compr_model = node->next_compr_model;
++ node->compressor->mounted--;
++ return;
++ }
++ l = l->next_compr_model;
++ if (l == NULL) {
++ jffs2_bbc_print1("jffs2.bbc: jffs2_bbc_model_del_from_compressor: not found\n");
++ return;
++ }
++ }
++}
++
++void jffs2_bbc_model_del(void *sb)
++{
++ struct jffs2_bbc_model_list_node *l, *l2;
++
++ l = jffs2_bbc_model_list;
++ if (l == NULL)
++ return;
++ if (l->sb == sb) {
++ jffs2_bbc_model_list = l->next_model;
++ jffs2_bbc_model_del_from_compressor(l);
++ jffs2_bbc_free_small(l);
++ jffs2_bbc_model_del(sb);
++ return;
++ }
++ while (1) {
++ if (l->next_model == NULL) {
++ break;
++ }
++ if (l->next_model->sb == sb) {
++ l2 = l->next_model;
++ l->next_model = l->next_model->next_model;
++ jffs2_bbc_model_del_from_compressor(l2);
++ jffs2_bbc_free_small(l2);
++ jffs2_bbc_model_del(sb);
++ return;
++ }
++ l = l->next_model;
++ }
++ last_sb = NULL;
++}
++
++void jffs2_bbc_model_set_act_sb(void *sb)
++{
++ last_sb = sb;
++}
++
++void *jffs2_bbc_model_get_act_sb(void)
++{
++ return last_sb;
++}
++
++void *jffs2_bbc_model_get_newest(struct jffs2_bbc_compressor_type *compressor)
++{
++ struct jffs2_bbc_model_list_node *m, *best_m;
++ int max_sign, sign;
++
++ if (compressor == NULL) {
++ jffs2_bbc_print1("jffs2.bbc: jffs2_bbc_model_get: NULL!!\n");
++ return NULL;
++ }
++
++ best_m = NULL;
++ max_sign = -1;
++ m = compressor->models;
++ while (m != NULL) {
++ if (m->sb == last_sb) {
++ sign = (int) (m->block_sign[0]) * 256 + (int) (m->block_sign[1]);
++ if (sign > max_sign) {
++ max_sign = sign;
++ best_m = m;
++ }
++ }
++ m = m->next_compr_model;
++ }
++ if (best_m != NULL)
++ return best_m->model;
++ else
++ return NULL;
++}
++
++/*********************************************************************
++ * Statistics *
++ *********************************************************************/
++
++static char *jffs2_bbc_stat_buff = NULL;
++
++char *jffs2_bbc_get_model_stats(void)
++{
++ char *b;
++ struct jffs2_bbc_model_list_node *m;
++ struct jffs2_bbc_compressor_type *c;
++
++ if (jffs2_bbc_stat_buff == NULL)
++ jffs2_bbc_stat_buff = jffs2_bbc_malloc(8000);
++
++ b = jffs2_bbc_stat_buff;
++
++ b += sprintf(b, "Loaded compressors:");
++ c = jffs2_bbc_compressors;
++ while (c != NULL) {
++ b += sprintf(b, "\n %s (%d) ", c->name, c->enabled);
++ if (c->model_file_sign != 0) {
++ b += sprintf(b, "m_sign=%d ", c->model_file_sign);
++ b += sprintf(b, "models=");
++ m = c->models;
++ while (m != NULL) {
++ b += sprintf(b, "(inode=%d)", m->inode);
++ m = m->next_compr_model;
++ }
++ }
++ else {
++ b += sprintf(b, "b_sign=(%d,%d) nomodel", (int) (c->block_sign[0]), (int) (c->block_sign[1]));
++ }
++ if (c->proc_info != NULL) {
++ b += sprintf(b, "\n %s", c->proc_info());
++ }
++ c = c->next;
++ }
++
++ m = jffs2_bbc_model_list;
++
++ if (m == NULL) {
++ b += sprintf(b, "\nPresent models: NONE\n");
++ }
++ else {
++ b += sprintf(b, "\nPresent models:\n");
++ while (m != NULL) {
++ b += sprintf(b, " b_sign=(%d,%d),inode=%d,decompr=%d", (int) (m->block_sign[0]), (int) (m->block_sign[1]), m->inode, m->stat_decompr);
++ if (m->compressor == NULL)
++ b += sprintf(b, ",compressor=NULL\n");
++ else
++ b += sprintf(b, ",compressor=%s\n", m->compressor->name);
++ m = m->next_model;
++ }
++ }
++
++ return jffs2_bbc_stat_buff;
++}
++
++/*********************************************************************
++ * Memory handling, debug *
++ *********************************************************************/
++
++static int jffs2_bbc_mem_counter = 0;
++
++#ifdef __KERNEL__
++
++void *jffs2_bbc_malloc(long size)
++{
++ void *addr = vmalloc(size);
++ if (addr != NULL)
++ jffs2_bbc_mem_counter++;
++ else {
++ jffs2_bbc_print2("DEBUG: not enough memory (%ld)\n", size);
++ }
++ return addr;
++}
++
++void jffs2_bbc_free(void *addr)
++{
++ jffs2_bbc_mem_counter--;
++ vfree(addr);
++}
++
++void *jffs2_bbc_malloc_small(long size)
++{
++ void *addr;
++ addr = kmalloc(size, 0);
++ if (addr != NULL)
++ jffs2_bbc_mem_counter++;
++ return addr;
++}
++
++void jffs2_bbc_free_small(void *addr)
++{
++ jffs2_bbc_mem_counter--;
++ kfree(addr);
++}
++
++#else
++
++void *jffs2_bbc_malloc(long size)
++{
++ void *addr = malloc(size);
++ if (addr != NULL)
++ jffs2_bbc_mem_counter++;
++ return addr;
++}
++
++void jffs2_bbc_free(void *addr)
++{
++ jffs2_bbc_mem_counter--;
++ free(addr);
++}
++
++void *jffs2_bbc_malloc_small(long size)
++{
++ return jffs2_bbc_malloc(size);
++}
++
++void jffs2_bbc_free_small(void *addr)
++{
++ jffs2_bbc_free(addr);
++}
++
++#endif
++
++int jffs2_bbc_test_memory_counter(int verbose)
++{
++ if (verbose > 0) {
++ jffs2_bbc_print2("jffs2.bbc: mem_counter=%d!\n", jffs2_bbc_mem_counter);
++ }
++ return jffs2_bbc_mem_counter;
++}
++
++int jffs2_bbc_get_memory_counter(void)
++{
++ return jffs2_bbc_mem_counter;
++}
++
++static char mem_stat[200];
++
++char *jffs2_bbc_get_mem_stats(void)
++{
++ sprintf(mem_stat, "Memcounter=%d\n", jffs2_bbc_mem_counter);
++ return mem_stat;
++}
++
++void jffs2_bbc_print_flush(void)
++{
++#ifdef __KERNEL__
++ return;
++#else
++ fflush(stdout);
++ fflush(stderr);
++#endif
++}
++
++/*********************************************************************
++ * FRAMEWORK - ZLIB REPLACEMENT *
++ *********************************************************************/
++
++#ifndef JFFS2_BBC_STANDALONE
++
++/* Temorary buffers */
++static char stat_str[JFFS2_BBC_STAT_BUFF_SIZE];
++static int tmp_buffer_size = 0;
++static char *tmp_buffer = NULL;
++
++/* Statistic - used by /proc/jffs2_bbc and mkfs.jffs2 */
++char *jffs2_bbc_get_compr_stats(void)
++{
++ struct jffs2_bbc_compressor_type *l;
++ char *s = stat_str;
++
++ s += sprintf(s, "Compression statistics:\n");
++ l = jffs2_bbc_original_compressor;
++ //s += sprintf(s, " zlib: compr=%d/%d decompr=%d\n", stat_zlib_compr_new, stat_zlib_compr_orig, stat_zlib_decompr);
++ s += sprintf(s, " %s: compr=%d/%d decompr=%d\n", l->name, l->stat_compr_new, l->stat_compr_orig, l->stat_decompr);
++ l = jffs2_bbc_get_compressor_list();
++ while (l != NULL) {
++ s += sprintf(s, " %s: compr=%d/%d decompr=%d\n", l->name, l->stat_compr_new, l->stat_compr_orig, l->stat_decompr);
++ l = l->next;
++ }
++ return stat_str;
++}
++
++static void jffs2_bbc_buffer_fill(unsigned char *buff, int size)
++{
++ for (; size > 0; size--, buff++)
++ *buff = 255;
++}
++
++
++static int jffs2_bbc_update_compr_buf(unsigned long size)
++{
++ struct jffs2_bbc_compressor_type *l;
++
++ if (size < 5000)
++ size = 5000;
++ if (tmp_buffer == NULL) {
++ tmp_buffer = jffs2_bbc_malloc(size);
++ jffs2_bbc_buffer_fill(tmp_buffer, size);
++ tmp_buffer_size = size;
++ }
++ else if (tmp_buffer_size < size) {
++ jffs2_bbc_free(tmp_buffer);
++ tmp_buffer = jffs2_bbc_malloc(size);
++ jffs2_bbc_buffer_fill(tmp_buffer, size);
++ tmp_buffer_size = size;
++ }
++ l = jffs2_bbc_get_compressor_list();
++ while (l != NULL) {
++ if (l->buffer == NULL) {
++ l->buffer_size = size;
++ l->buffer = jffs2_bbc_malloc(size);
++ jffs2_bbc_buffer_fill(l->buffer, size);
++ }
++ else if (l->buffer_size < size) {
++ jffs2_bbc_free(l->buffer);
++ l->buffer_size = size;
++ l->buffer = jffs2_bbc_malloc(size);
++ jffs2_bbc_buffer_fill(l->buffer, size);
++ }
++ l = l->next;
++ }
++ return 0;
++}
++
++#ifdef DEBUG_COMPRESSORS
++
++static unsigned char *debug_tmp_buff = NULL;
++static long debug_orig_srclen = -1;
++static long debug_orig_dstlen = -1;
++static int debug_mem_counter = -1;
++
++
++void debug_before_compress(struct jffs2_bbc_compressor_type *c, void *model, unsigned char *input, unsigned char *output, long *sourcelen, long *dstlen)
++{
++
++ debug_orig_srclen = *sourcelen; // for buffer overflow test
++ debug_orig_dstlen = *dstlen; // for buffer overflow test
++ output[debug_orig_dstlen + 1] = 255;
++
++ debug_mem_counter = jffs2_bbc_get_memory_counter(); // for memory guard
++}
++
++void debug_after_compress(struct jffs2_bbc_compressor_type *c, int back, void *model, unsigned char *input, unsigned char *output, long *sourcelen, long *dstlen)
++{
++ long dst_len = *dstlen;
++ long src_len = *sourcelen;
++ int i;
++
++ // Memory guard
++ if (debug_mem_counter != jffs2_bbc_get_memory_counter()) {
++ jffs2_bbc_print4("!!!!!!!! %s error: possible COMPRESSOR MEMORY LEAK: %d->%d\n", c->name, debug_mem_counter, jffs2_bbc_get_memory_counter());
++ debug_mem_counter = jffs2_bbc_get_memory_counter();
++ }
++
++ // Buffer overflow test
++ if (output[debug_orig_dstlen + 1] != 255) {
++ jffs2_bbc_print7("!!!!!!!! %s error: BUFFER OVERFLOW !!!!!!!!!!!! b[%d]=%d (srclen=%d dstlen=%d, back=%d)\n", c->name, (int) (debug_orig_dstlen + 1), (int) (output[debug_orig_dstlen + 1]), (int) (debug_orig_srclen), (int) (*dstlen), back);
++ }
++
++ // Decompression check
++ if (back == 0) {
++ if (debug_tmp_buff == NULL)
++ debug_tmp_buff = jffs2_bbc_malloc(17000);
++ for (i = 0; i < src_len; i++) debug_tmp_buff[i] = 0xf6;
++ c->decompress(model, output, debug_tmp_buff, dst_len, src_len);
++ // Memory guard for decompressor
++ if (debug_mem_counter != jffs2_bbc_get_memory_counter()) {
++ jffs2_bbc_print4("!!!!!!!! %s error: possible DECOMPRESSOR MEMORY LEAK: %d->%d\n", c->name, debug_mem_counter, jffs2_bbc_get_memory_counter());
++ debug_mem_counter = jffs2_bbc_get_memory_counter();
++ }
++
++ for (i = 0; i < src_len; i++)
++ if (input[i] != debug_tmp_buff[i]) {
++ jffs2_bbc_print7("!!!!!!!! %s error: BLOCK DECOMPRESSED BADLY (first bad: %d in %d: %d!=%d (compressed size=%d)) !!!!!!!!!!!!\n", c->name, i, src_len, (int)input[i], (int)debug_tmp_buff[i], dst_len);
++ break;
++ }
++ return;
++ }
++
++ // Return value test
++ //jffs2_bbc_print3("!!!!!!!! %s error: %d !!!!!!!!!!!!\n", c->name, back);
++}
++
++#endif
++
++int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t * sourcelen, uint32_t * dstlen)
++{
++ struct jffs2_bbc_compressor_type *c;
++ int back, back_zlib, mode, min, i, i2;
++ long tmp = 0, tmp_read_time = 1000, tmp_write_time = 1000, orig_src, orig_dest, src, dest;
++ struct jffs2_bbc_model_list_node *m;
++ void *sb;
++ unsigned char *tmp_p = NULL;
++
++ sb = jffs2_bbc_model_get_act_sb();
++
++ orig_src = *sourcelen;
++ orig_dest = *dstlen;
++
++ mode = jffs2_bbc_get_compression_mode();
++
++ if (mode == JFFS2_BBC_DUMMY_MODE) {
++ i=0; i2=0;
++ if (*dstlen>2) {
++ cpage_out[i++]=JFFS2_BBC_DUMMY_BLOCKSIGN_0;
++ cpage_out[i++]=JFFS2_BBC_DUMMY_BLOCKSIGN_1;
++ i2=i;
++ }
++ for (;((i < *dstlen) && (i < (*sourcelen)+i2));i++) {
++ cpage_out[i] = data_in[i-i2];
++ }
++ *sourcelen=i-i2;
++ *dstlen=i;
++ return 0;
++ }
++
++ if (mode == JFFS2_BBC_ZLIB_MODE) {
++ /*if (!jffs2_bbc_original_compressor->enabled) {
++ jffs2_bbc_print2("jffs2.bbc: WARNING: ZLIB mode but %s disabled! Enabling for this procedure...\n",jffs2_bbc_original_compressor->name);
++ }*/
++ back = jffs2_bbc_original_compressor->compress(NULL, data_in, cpage_out, sourcelen, dstlen);
++ jffs2_bbc_original_compressor->stat_compr_orig += *sourcelen;
++ jffs2_bbc_original_compressor->stat_compr_new += *dstlen;
++ return back;
++ }
++
++ jffs2_bbc_update_compr_buf(orig_dest);
++
++ if (mode == JFFS2_BBC_SIZE_MODE) {
++ // Testing all compressors
++ if (!jffs2_bbc_original_compressor->enabled) {
++ min = -1;
++ }
++ else {
++ back_zlib = jffs2_bbc_original_compressor->compress(NULL, data_in, cpage_out, sourcelen, dstlen);
++ min = *dstlen;
++ }
++ c = jffs2_bbc_get_compressor_list();
++ while (c != NULL) {
++ c->buffer_cnt = -1;
++ if (c->enabled == 0) {
++ c = c->next;
++ continue;
++ }
++ if (c->model_file_sign == 0) {
++ src = orig_src;
++ dest = orig_dest;
++#ifdef DEBUG_COMPRESSORS
++ debug_before_compress(c, NULL, data_in, c->buffer, &src, &dest);
++#endif
++ back = c->compress(NULL, data_in, c->buffer, &src, &dest);
++#ifdef DEBUG_COMPRESSORS
++ debug_after_compress(c, back, NULL, data_in, c->buffer, &src, &dest);
++#endif
++ if (back == 0) {
++ c->buffer_cnt = dest;
++ if ((min < 0) || (min > dest))
++ min = dest;
++ }
++ }
++ else {
++ m = c->models;
++ while (m != NULL) {
++ src = orig_src;
++ dest = orig_dest;
++ if (m->sb == sb) {
++ if (c->buffer_cnt == -1) {
++#ifdef DEBUG_COMPRESSORS
++ debug_before_compress(c, m->model, data_in, c->buffer, (long *) (&src), (long *) (&dest));
++#endif
++ back = c->compress(m->model, data_in, c->buffer, (long *) (&src), (long *) (&dest));
++#ifdef DEBUG_COMPRESSORS
++ debug_after_compress(c, back, m->model, data_in, c->buffer, (long *) (&src), (long *) (&dest));
++#endif
++ if (back == 0) {
++ c->buffer_cnt = dest;
++ if ((min < 0) || (min > dest))
++ min = dest;
++ }
++ }
++ else {
++#ifdef DEBUG_COMPRESSORS
++ debug_before_compress(c, m->model, data_in, tmp_buffer, &src, &dest);
++#endif
++ back = c->compress(m->model, data_in, tmp_buffer, &src, &dest);
++#ifdef DEBUG_COMPRESSORS
++ debug_after_compress(c, back, m->model, data_in, tmp_buffer, &src, &dest);
++#endif
++ if (back == 0) {
++ if (c->buffer_cnt > dest) {
++ c->buffer_cnt = dest;
++ tmp_p = c->buffer;
++ c->buffer = tmp_buffer;
++ tmp_buffer = tmp_p;
++ if ((min < 0) || (min > dest))
++ min = dest;
++ }
++ }
++ }
++ }
++ m = m->next_compr_model;
++ }
++ }
++ c = c->next;
++ }
++ //Finding the best and copy its result
++
++#ifdef DEBUG_SHOW_BLOCK_SIZES
++ jffs2_bbc_print1("\n");
++ if (jffs2_bbc_original_compressor->enabled) {
++ if (min == *dstlen) {
++ jffs2_bbc_print3("%s:%d* ", jffs2_bbc_original_compressor->name, (int) (*dstlen));
++ }
++ else {
++ jffs2_bbc_print3("%s:%d ", jffs2_bbc_original_compressor->name, (int) (*dstlen));
++ }
++ }
++ c = jffs2_bbc_get_compressor_list();
++ while (c != NULL) {
++ if (c->enabled == 0) {
++ c = c->next;
++ continue;
++ }
++ if (c->buffer_cnt == min)
++ jffs2_bbc_print3("%s:%d* ", c->name, c->buffer_cnt);
++ else
++ jffs2_bbc_print3("%s:%d ", c->name, c->buffer_cnt);
++ c = c->next;
++ }
++#endif
++
++ if (min == -1) {
++ return -1; // none of compressors work (maybe too short output buffer)
++ }
++
++ if (jffs2_bbc_original_compressor->enabled) {
++ if (min == *dstlen) {
++ jffs2_bbc_original_compressor->stat_compr_orig += *sourcelen;
++ jffs2_bbc_original_compressor->stat_compr_new += *dstlen;
++ return back_zlib;
++ }
++ }
++
++ c = jffs2_bbc_get_compressor_list();
++ while (c != NULL) {
++ if (c->enabled == 0) {
++ c = c->next;
++ continue;
++ }
++ if (c->buffer_cnt == min) {
++ *dstlen = c->buffer_cnt;
++ *sourcelen = orig_src;
++ for (i = 0; i < *dstlen; i++) {
++ cpage_out[i] = c->buffer[i];
++ }
++ c->stat_compr_orig += *sourcelen;
++ c->stat_compr_new += *dstlen;
++ return 0;
++ }
++ c = c->next;
++ }
++ jffs2_bbc_print1("jffs2.bbc: compr (full): BUG!!!\n");
++ return 0;
++ }
++
++ if ((mode == JFFS2_BBC_FASTR_MODE)||(mode == JFFS2_BBC_FASTW_MODE)||(mode == JFFS2_BBC_FASTS_MODE)) {
++ // Estimating all compressors
++ if (jffs2_bbc_original_compressor->enabled) {
++ back = jffs2_bbc_original_compressor->estimate(NULL, data_in, *sourcelen, &tmp, &tmp_read_time, &tmp_write_time);
++ }
++ else {
++ tmp = -1;
++ tmp_read_time = -1;
++ tmp_write_time = -1;
++ }
++ if (mode == JFFS2_BBC_FASTR_MODE) tmp = tmp_read_time;
++ if (mode == JFFS2_BBC_FASTW_MODE) tmp = tmp_write_time;
++ min = tmp;
++ c = jffs2_bbc_get_compressor_list();
++ while (c != NULL) {
++ src = orig_src;
++ dest = orig_dest;
++ c->buffer_cnt = -1;
++ if (c->enabled == 0) {
++ c = c->next;
++ continue;
++ }
++ if ((c->model_file_sign == 0) || (jffs2_bbc_model_get_newest(c) != NULL)) {
++ back = c->estimate(jffs2_bbc_model_get_newest(c), data_in, src, &dest, &tmp_read_time, &tmp_write_time);
++ if (mode == JFFS2_BBC_FASTR_MODE) dest = tmp_read_time;
++ if (mode == JFFS2_BBC_FASTW_MODE) dest = tmp_write_time;
++ if (back == 0) {
++ c->buffer_cnt = dest;
++ if ((min < 0) || (min > dest))
++ min = dest;
++ }
++ else {
++ c->buffer_cnt = -1;
++ }
++ }
++ c = c->next;
++ }
++ // Finding the best and compress with it
++ if (min == -1) {
++ return -1;
++ }
++ if (jffs2_bbc_original_compressor->enabled) {
++ if (min == tmp) {
++ back = jffs2_bbc_original_compressor->compress(NULL, data_in, cpage_out, sourcelen, dstlen);
++ jffs2_bbc_original_compressor->stat_compr_orig += *sourcelen;
++ jffs2_bbc_original_compressor->stat_compr_new += *dstlen;
++ return back;
++ }
++ }
++ c = jffs2_bbc_get_compressor_list();
++ while (c != NULL) {
++ if (c->enabled == 0) {
++ c = c->next;
++ continue;
++ }
++ if (c->buffer_cnt == min) {
++ back = c->compress(jffs2_bbc_model_get_newest(c), data_in, cpage_out, (unsigned long*)sourcelen, (unsigned long*)dstlen);
++ if ((back == 0) && (*dstlen < orig_dest) && (*dstlen > 4)) {
++ c->stat_compr_orig += *sourcelen;
++ c->stat_compr_new += *dstlen;
++ }
++ else { // fallback will always be available
++ *sourcelen = orig_src;
++ *dstlen = orig_dest;
++ back = jffs2_bbc_original_compressor->compress(NULL, data_in, cpage_out, sourcelen, dstlen);
++ jffs2_bbc_original_compressor->stat_compr_orig += *sourcelen;
++ jffs2_bbc_original_compressor->stat_compr_new += *dstlen;
++ return back;
++ }
++ return 0;
++ }
++ c = c->next;
++ }
++ jffs2_bbc_print1("jffs2.bbc: compress (fastX mode): BUG!!!\n");
++ return 0;
++ }
++
++ if (mode == JFFS2_BBC_MANUAL_MODE) {
++ c = jffs2_bbc_get_manual_compressor();
++ if (c != NULL) {
++ if (c->model_file_sign == 0) {
++ src = orig_src;
++ dest = orig_dest;
++ back = c->compress(NULL, data_in, cpage_out, &src, &dest);
++ if (back == 0) {
++ *dstlen = dest;
++ *sourcelen = src;
++ c->stat_compr_orig += *sourcelen;
++ c->stat_compr_new += *dstlen;
++ return 0;
++ }
++ }
++ else {
++ c->buffer_cnt = -1;
++ m = c->models;
++ min = -1;
++ while (m != NULL) {
++ src = orig_src;
++ dest = orig_dest;
++ if (m->sb == sb) {
++ if (min == -1) {
++ back = c->compress(m->model, data_in, cpage_out, (unsigned long*)sourcelen, (unsigned long*)dstlen);
++ if ((back == 0) && (*dstlen < orig_dest) && (*dstlen > 4)) {
++ min = dest;
++ tmp_p = cpage_out;
++ }
++ }
++ else {
++ back = c->compress(m->model, data_in, tmp_buffer, &src, &dest);
++ if ((back == 0) && (dest < orig_dest) && (dest > 4)) {
++ if (c->buffer_cnt > dest) {
++ if (min > dest) {
++ min = dest;
++ tmp_p = tmp_buffer;
++ }
++ }
++ }
++ }
++ }
++ m = m->next_compr_model;
++ }
++ if (min != -1) {
++ if (tmp_p != cpage_out) {
++ for (i = 0; i < min; i++)
++ cpage_out[i] = tmp_p[i];
++ *sourcelen = orig_src;
++ *dstlen = min;
++ }
++ c->stat_compr_orig += *sourcelen;
++ c->stat_compr_new += *dstlen;
++ return 0;
++ }
++ }
++ }
++ /*else {
++ jffs2_bbc_print1("iPack: manual mode without selected compressor!\n");
++ } */
++
++ /*if (!jffs2_bbc_original_compressor->enabled) {
++ jffs2_bbc_print2("jffs2.bbc: WARNING: %s must be enabled! Enabling for this procedure...\n",jffs2_bbc_original_compressor->name);
++ }*/
++ back = jffs2_bbc_original_compressor->compress(NULL, data_in, cpage_out, sourcelen, dstlen);
++ jffs2_bbc_original_compressor->stat_compr_orig += *sourcelen;
++ jffs2_bbc_original_compressor->stat_compr_new += *dstlen;
++ return back;
++
++
++ }
++
++ jffs2_bbc_print1("jffs2.bbc: compress: unimlemented compress mode!!!\n");
++ return 0;
++}
++
++void jffs2_zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, uint32_t srclen, uint32_t destlen)
++{
++ struct jffs2_bbc_model_list_node *m;
++ struct jffs2_bbc_compressor_type *c;
++ char d[2];
++ void *sb;
++ int i;
++
++ /* If the input too small... */
++ if (destlen<=2) {
++ cpage_out[0]=data_in[0];
++ if (destlen==2) cpage_out[1]=data_in[1];
++ return;
++ }
++
++ sb = jffs2_bbc_model_get_act_sb();
++ d[0] = *(data_in);
++ d[1] = *(data_in + 1);
++
++ d[0] &= 0x7f; // Variants support...
++
++ /* Search for model based decompressors... */
++ m = jffs2_bbc_get_model_list();
++ while (m != NULL) {
++ if ((d[0] == m->block_sign[0]) && (d[1] == m->block_sign[1]) && (sb == m->sb)) {
++ if (m->compressor == NULL) {
++ jffs2_bbc_print3("jffs2.bbc: decompressor for block_sign (%d,%d) not loaded!\n", (int) (d[0]), (int) (d[1]));
++ }
++ else {
++ m->compressor->decompress(m->model, data_in, cpage_out, srclen, destlen);
++ m->compressor->stat_decompr++;
++ m->stat_decompr++;
++ }
++ return;
++ }
++ m = m->next_model;
++ }
++ /* Is it ZLIB? */
++ if ((((int) d[0]) == (int)(jffs2_bbc_original_compressor->block_sign[0])) && (((int) d[1]) == (int)(jffs2_bbc_original_compressor->block_sign[1]))) {
++ jffs2_bbc_original_compressor->decompress(NULL, data_in, cpage_out, srclen, destlen);
++ jffs2_bbc_original_compressor->stat_decompr++;
++ return;
++ }
++ /* Search for non model based decompressors... */
++ c = jffs2_bbc_get_compressor_list();
++ while (c != NULL) {
++ if (c->model_file_sign == 0) {
++ if (((int) (d[0]) == (int) (c->block_sign[0])) && ((int) (d[1]) == (int) (c->block_sign[1]))) {
++ c->decompress(NULL, data_in, cpage_out, srclen, destlen);
++ c->stat_decompr++;
++ return;
++ }
++ }
++ c = c->next;
++ }
++ /* Is it DUMMY? */
++ if ((((int) d[0]) == JFFS2_BBC_DUMMY_BLOCKSIGN_0) && (((int) d[1]) == JFFS2_BBC_DUMMY_BLOCKSIGN_1)) {
++ for (i=0;i<destlen;i++) {
++ cpage_out[i]=data_in[i+2];
++ }
++ return;
++ }
++ /* No matching decompressor found... */
++ jffs2_bbc_print4("jffs2.bbc: cannot find model for decompress: bsign=(%d,%d),sb=%d. Using zlib.\n", (int) d[0], (int) d[1], (int) sb);
++ jffs2_bbc_original_compressor->decompress(NULL, data_in, cpage_out, srclen, destlen);
++ jffs2_bbc_original_compressor->stat_decompr++;
++}
++
++#endif
+diff -Nur linux-mips-cvs/fs/jffs2/jffs2_bbc_framework.h linux-mips/fs/jffs2/jffs2_bbc_framework.h
+--- linux-mips-cvs/fs/jffs2/jffs2_bbc_framework.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips/fs/jffs2/jffs2_bbc_framework.h 2005-02-07 05:08:34.000000000 +0100
+@@ -0,0 +1,202 @@
++/*
++ * JFFS2-BBC: Compression Framework - headers
++ *
++ * $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++ *
++ * Copyright (C) 2004, Ferenc Havasi
++ *
++ * 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 __JFFS2_BBC_FRAMEWORK_H__
++
++#define __JFFS2_BBC_FRAMEWORK_H__
++
++#define JFFS2_BBC_VERSION "0.54.3"
++
++#define JFFS2_BBC_CONFIG_FILE "bbc.conf"
++
++/*********************************************************************
++ * Compression mode handling *
++ *********************************************************************/
++
++#define JFFS2_BBC_ZLIB_MODE 1
++#define JFFS2_BBC_SIZE_MODE 2
++#define JFFS2_BBC_FASTR_MODE 3
++#define JFFS2_BBC_FASTW_MODE 4
++#define JFFS2_BBC_FASTS_MODE 5
++#define JFFS2_BBC_MANUAL_MODE 6
++#define JFFS2_BBC_DUMMY_MODE 7
++
++int jffs2_bbc_get_compression_mode(void);
++void jffs2_bbc_set_compression_mode(int mode);
++
++/*********************************************************************
++ * Read/write speed unit *
++ * everything is relative to the speed of zlib *
++ * bigger number means slower speed! *
++ *********************************************************************/
++
++#define JFFS2_BBC_ZLIB_READ_TIME 10000
++#define JFFS2_BBC_ZLIB_WRITE_TIME 10000
++
++/*********************************************************************
++ * Compressor handling *
++ *********************************************************************/
++
++struct jffs2_bbc_compressor_type
++{
++ char name[16];
++ int model_file_sign; /* 0 for no model file needed */
++ char block_sign[4]; /* only nomodel compressors, and only the first 2 _bytes are used! */
++ int (*init)(void);
++ int (*init_model)(void **model);
++ void (*destroy_model)(void **model);
++ void (*deinit)(void);
++ /* Compress block
++ * *dstlen bytes are allocated.
++ * if it is not enough write *sourcelen over to the processed amount of data
++ * returns non zero if fails
++ */
++ int (*compress)(void *model, unsigned char *input, unsigned char *output, unsigned long *sourcelen, unsigned long *dstlen);
++ int (*estimate)(void *model, unsigned char *input, unsigned long sourcelen,
++ unsigned long *dstlen, unsigned long *readtime, unsigned long *writetime);
++ /* Decompress block
++ * returns non zero if fails
++ */
++ int (*decompress)(void *model, unsigned char *input, unsigned char *output, unsigned long sourcelen, unsigned long dstlen);
++ char *(*proc_info)(void);
++ int (*proc_command)(char *command);
++ int enabled; /* filled by BBC */
++ int mounted; /* filled by BBC */
++ void *models; /* filled by BBC */
++ char *buffer; /* filled by BBC */
++ int buffer_size; /* filled by BBC */
++ int buffer_cnt; /* filled by BBC */
++ int buffer_tmp; /* filled by BBC */
++ int stat_compr_orig; /* filled by BBC */
++ int stat_compr_new; /* filled by BBC */
++ int stat_decompr; /* filled by BBC */
++ struct jffs2_bbc_compressor_type *next; /* filled by BBC */
++};
++
++/* It sets the compression mode to JFFS2_BBC_MANUAL_MODE */
++
++void jffs2_bbc_set_manual_compressor(struct jffs2_bbc_compressor_type *c); /* NULL = ZLIB */
++int jffs2_bbc_set_manual_compressor_by_name(char *name);
++int jffs2_bbc_disable_compressor_by_name(char *name);
++int jffs2_bbc_enable_compressor_by_name(char *name);
++void jffs2_bbc_compressor_command_by_name(char *name_and_command);
++
++/* If the compression mode is JFFS2_BCC_MANUAL_MODE the manually setted
++ compressor can be get using it. Otherwise it returns with NULL. */
++
++struct jffs2_bbc_compressor_type *jffs2_bbc_get_manual_compressor(void);
++
++struct jffs2_bbc_model_list_node
++{
++ void *sb; /* FS idendifier (JFFS2_SB_INFO(sb) at this moment) */
++ void *model; /* model data */
++ int sign; /* sign of the model (first 4 bytes) */
++ char block_sign[4]; /* block sign - only the first 2 bytes are used! */
++ int inode; /* inode number of the model file */
++ int stat_decompr;
++ struct jffs2_bbc_compressor_type *compressor;
++ struct jffs2_bbc_model_list_node *next_model;
++ struct jffs2_bbc_model_list_node *next_compr_model;
++};
++
++struct jffs2_bbc_compressor_type *jffs2_bbc_get_compressor_list(void);
++struct jffs2_bbc_model_list_node *jffs2_bbc_get_model_list(void);
++
++int jffs2_bbc_register_compressor(struct jffs2_bbc_compressor_type *c);
++int jffs2_bbc_unregister_compressor(struct jffs2_bbc_compressor_type *c);
++
++int jffs2_bbc_model_new(void *sb, int i_num, void *model);
++void jffs2_bbc_model_del(void *sb);
++void jffs2_bbc_model_set_act_sb(void *sb);
++void *jffs2_bbc_model_get_act_sb(void);
++void *jffs2_bbc_model_get_newest(struct jffs2_bbc_compressor_type *compressor);
++
++/*********************************************************************
++ * Compressor init function *
++ *********************************************************************/
++
++void jffs2_bbc_compressor_init(void);
++void jffs2_bbc_compressor_deinit(void);
++
++/*********************************************************************
++ * Statistics *
++ *********************************************************************/
++
++char *jffs2_bbc_get_compr_stats(void);
++char *jffs2_bbc_get_model_stats(void);
++
++/*********************************************************************
++ * Other *
++ *********************************************************************/
++
++
++void jffs2_bbc_print_flush(void);
++
++#ifdef __KERNEL__
++#include <linux/kernel.h>
++#define jffs2_bbc_print1(a) printk(a)
++#define jffs2_bbc_print2(a,b) printk(a,b)
++#define jffs2_bbc_print3(a,b,c) printk(a,b,c)
++#define jffs2_bbc_print4(a,b,c,d) printk(a,b,c,d)
++#define jffs2_bbc_print5(a,b,c,d,e) printk(a,b,c,d,e)
++#define jffs2_bbc_print6(a,b,c,d,e,f) printk(a,b,c,d,e,f)
++#define jffs2_bbc_print7(a,b,c,d,e,f,g) printk(a,b,c,d,e,f,g)
++#define jffs2_bbc_print8(a,b,c,d,e,f,g,h) printk(a,b,c,d,e,f,g,h)
++#define jffs2_bbc_print9(a,b,c,d,e,f,g,h,i) printk(a,b,c,d,e,f,g,h,i)
++#else
++#include <stdio.h>
++#define jffs2_bbc_print1(a) fprintf(stderr,a)
++#define jffs2_bbc_print2(a,b) fprintf(stderr,a,b)
++#define jffs2_bbc_print3(a,b,c) fprintf(stderr,a,b,c)
++#define jffs2_bbc_print4(a,b,c,d) fprintf(stderr,a,b,c,d)
++#define jffs2_bbc_print5(a,b,c,d,e) fprintf(stderr,a,b,c,d,e)
++#define jffs2_bbc_print6(a,b,c,d,e,f) fprintf(stderr,a,b,c,d,e,f)
++#define jffs2_bbc_print7(a,b,c,d,e,f,g) fprintf(stderr,a,b,c,d,e,f,g)
++#define jffs2_bbc_print8(a,b,c,d,e,f,g,h) fprintf(stderr,a,b,c,d,e,f,g,h)
++#define jffs2_bbc_print9(a,b,c,d,e,f,g,h,i) fprintf(stderr,a,b,c,d,e,f,g,h,i)
++#endif
++
++/* Handle endianness */
++#ifndef __KERNEL__
++
++#define ENDIAN_HOST_AND_TARGET_SAME 0
++#define ENDIAN_HOST_AND_TARGET_DIFFERENT 1
++
++extern int jffs2_bbc_glb_endian_X;
++
++#endif
++
++/* Allocating more than one page (tip. 4096 byte) */
++void *jffs2_bbc_malloc(long size);
++void jffs2_bbc_free(void *addr);
++
++/* Allocating less than one page (tip. 4096 byte) */
++void *jffs2_bbc_malloc_small(long size);
++void jffs2_bbc_free_small(void *addr);
++
++/* Memory guarding */
++int jffs2_bbc_test_memory_counter(int verbose);
++char *jffs2_bbc_get_mem_stats(void);
++int jffs2_bbc_get_memory_counter(void);
++
++#endif
+diff -Nur linux-mips-cvs/fs/jffs2/jffs2_bbc_fs.c linux-mips/fs/jffs2/jffs2_bbc_fs.c
+--- linux-mips-cvs/fs/jffs2/jffs2_bbc_fs.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips/fs/jffs2/jffs2_bbc_fs.c 2005-02-07 05:08:34.000000000 +0100
+@@ -0,0 +1,331 @@
++/*
++ * JFFS2-BBC: File System Extension for Linux Kernel
++ *
++ * $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++ *
++ * Copyright (C) 2004, Ferenc Havasi
++ *
++ * 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/kernel.h>
++#include <linux/fs.h>
++#include <linux/jffs2.h>
++#include <linux/proc_fs.h>
++#include <linux/version.h>
++
++#include "nodelist.h"
++
++#include "jffs2_bbc_framework.h"
++
++struct jffs2_bbc_fs_sb_list {
++ struct super_block *sb;
++ struct jffs2_bbc_fs_sb_list *next;
++};
++
++static struct jffs2_bbc_fs_sb_list *sb_list = NULL;
++
++void jffs2_bbc_proc_init(void);
++void jffs2_bbc_proc_deinit(void);
++
++void jffs2_bbc_load_model(void *sb_par) {
++ struct jffs2_sb_info *c;
++ //struct jffs2_inode_info *f;
++ struct dentry *config_dentry,*model_dentry;
++ struct qstr config_name,model_name;
++ struct file *config_file,*model_file;
++ char *buff=NULL,*model_buff;
++ int config_size,model_size;
++ int i,prev_i;
++ struct super_block *sb;
++ struct jffs2_bbc_fs_sb_list *sb_l;
++
++ sb = sb_par;
++ sb_l = jffs2_bbc_malloc_small(sizeof(struct jffs2_bbc_fs_sb_list));
++ sb_l->sb = sb;
++ sb_l->next = sb_list;
++ sb_list = sb_l;
++ config_name.name = JFFS2_BBC_CONFIG_FILE;
++ config_name.len = strlen(config_name.name);
++ config_name.hash = full_name_hash(config_name.name,config_name.len);
++ config_dentry = d_alloc(sb->s_root,&config_name);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
++ sb->s_root->d_inode->i_op->lookup(sb->s_root->d_inode,config_dentry);
++#else
++ sb->s_root->d_inode->i_op->lookup(sb->s_root->d_inode,config_dentry,NULL);
++#endif
++
++ if (config_dentry->d_inode != NULL) {
++ config_size = config_dentry->d_inode->i_size;
++ //printk("config_file_size=%d\n",config_size);
++ if (config_size > 0) {
++ buff = jffs2_bbc_malloc(config_size+1);
++ config_file = dentry_open(config_dentry,NULL,O_RDONLY);
++ kernel_read(config_file,0,buff,config_size);
++ buff[config_size] = 0;
++ for (prev_i = i = 0 ; i < config_size+1 ; i++) {
++ if (buff[i] == '\n') buff[i]=0;
++ if (buff[i] == 0) {
++ if (prev_i != i) {
++ if ((buff[prev_i] == '-') && (buff[prev_i+1] == 0)) break;
++ printk("reading model file %s... ",buff+prev_i);
++ model_name.name = buff+prev_i;
++ model_name.len = strlen(buff+prev_i);
++ model_name.hash = full_name_hash(model_name.name,model_name.len);
++ model_dentry = d_alloc(sb->s_root,&model_name);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
++ sb->s_root->d_inode->i_op->lookup(sb->s_root->d_inode,model_dentry);
++#else
++ sb->s_root->d_inode->i_op->lookup(sb->s_root->d_inode,model_dentry,NULL);
++#endif
++ if (model_dentry->d_inode != NULL) {
++ c = JFFS2_SB_INFO(model_dentry->d_inode->i_sb);
++ //f = JFFS2_INODE_INFO(model_dentry->d_inode);
++ model_size = model_dentry->d_inode->i_size;
++ model_buff = jffs2_bbc_malloc(model_size);
++ model_file = dentry_open(model_dentry,NULL,O_RDONLY);
++ kernel_read(model_file,0,model_buff,model_size);
++ if (jffs2_bbc_model_new(c,model_dentry->d_inode->i_ino,model_buff) != 0) {
++ printk("already loaded.\n");
++ jffs2_bbc_free(model_buff);
++ }
++ else {
++ printk("done (%d bytes readed from inode %d).\n",model_size,(int)(model_dentry->d_inode->i_ino));
++ }
++ }
++ else {
++ printk("not found.\n");
++ }
++ dput(model_dentry);
++ }
++ prev_i = i+1;
++ }
++ }
++ }
++ }
++ dput(config_dentry);
++ if (buff != NULL) jffs2_bbc_free(buff);
++}
++
++void jffs2_bbc_unload_model(void *sb_par)
++{
++ struct jffs2_sb_info *c;
++ struct super_block *sb = sb_par;
++ struct jffs2_bbc_fs_sb_list *sb_l,*sb_l2;
++ int done = 0;
++
++ c = JFFS2_SB_INFO(sb);
++ jffs2_bbc_model_del(c);
++ if (sb_list == NULL) printk("jffs2.bbc: error! NULL sb list!\n");
++ else {
++ if (sb_list->sb == sb) {
++ jffs2_bbc_free_small(sb_list);
++ sb_list = NULL;
++ done = 1;
++ }
++ else {
++ sb_l = sb_list;
++ while (sb_l->next != NULL) {
++ if (sb_l->next->sb == sb) {
++ sb_l2 = sb_l->next->next;
++ jffs2_bbc_free_small(sb_l->next);
++ sb_l->next = sb_l2;
++ done = 1;
++ }
++ sb_l = sb_l->next;
++ }
++
++ }
++ if (done == 0) {
++ printk("jffs2.bbc: cannot delete sb from sblist!\n");
++ }
++ }
++}
++
++static int jffs2_bbc_get_mounted(void) {
++ struct jffs2_bbc_fs_sb_list *sb_l;
++ int num = 0;
++
++ sb_l = sb_list;
++ while (sb_l != NULL) {
++ num++;
++ sb_l = sb_l->next;
++ }
++ return num;
++
++}
++
++int jffs2_bbc_proc_read(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++{
++ int len = 0, mode;
++
++ mode = jffs2_bbc_get_compression_mode();
++ len += sprintf(buf + len, "BBC version: %s\n", JFFS2_BBC_VERSION);
++ len += sprintf(buf+len,"Mounted jffs2 filesystems: %d\n",jffs2_bbc_get_mounted());
++ //len += sprintf(buf+len,"actual model file inode: %d\n",jffs2_bbc_model_get_inum());
++ len += sprintf(buf + len, "Compression mode: ");
++ if (mode == JFFS2_BBC_ZLIB_MODE)
++ len += sprintf(buf + len, "ZLIB mode");
++ else if (mode == JFFS2_BBC_SIZE_MODE)
++ len += sprintf(buf + len, "SIZE mode");
++ else if (mode == JFFS2_BBC_FASTR_MODE)
++ len += sprintf(buf + len, "FASTR mode");
++ else if (mode == JFFS2_BBC_FASTW_MODE)
++ len += sprintf(buf + len, "FASTW mode");
++ else if (mode == JFFS2_BBC_FASTS_MODE)
++ len += sprintf(buf + len, "FASTS mode");
++ else if (mode == JFFS2_BBC_DUMMY_MODE)
++ len += sprintf(buf + len, "DUMMY mode");
++ else if (mode == JFFS2_BBC_MANUAL_MODE) {
++ len += sprintf(buf + len, "MANUAL mode (");
++ if (jffs2_bbc_get_manual_compressor() != NULL)
++ len += sprintf(buf + len, "%s)", jffs2_bbc_get_manual_compressor()->name);
++ else
++ len += sprintf(buf + len, "ZLIB)");
++ }
++ else
++ len += sprintf(buf + len, "unknown mode");
++ len += sprintf(buf + len, "\n");
++ len += sprintf(buf + len, "%s", jffs2_bbc_get_compr_stats());
++ len += sprintf(buf + len, "%s", jffs2_bbc_get_model_stats());
++ len += sprintf(buf + len, "%s", jffs2_bbc_get_mem_stats());
++ *eof = 1;
++ return len;
++}
++
++int jffs2_bbc_proc_write(struct file *file, const char *buffer_orig, unsigned long count, void *data)
++{
++ char *buffer;
++ int i;
++ struct jffs2_bbc_fs_sb_list *sb_l;
++
++ if (buffer_orig == NULL) return 0;
++
++ buffer = jffs2_bbc_malloc(count+2);
++ for (i=0;i<count;i++) buffer[i]=buffer_orig[i];
++ buffer[count] = 0;
++ if ((*buffer == 'z') || (*buffer == 'Z')) {
++ jffs2_bbc_set_compression_mode(JFFS2_BBC_ZLIB_MODE);
++ jffs2_bbc_print1("jffs2.bbc: ZLIB compression mode activated.\n");
++ jffs2_bbc_free(buffer);
++ return count;
++ }
++ else if ((*buffer == 's') || (*buffer == 'S')) {
++ jffs2_bbc_set_compression_mode(JFFS2_BBC_SIZE_MODE);
++ jffs2_bbc_print1("jffs2.bbc: SIZE compression mode activated.\n");
++ jffs2_bbc_free(buffer);
++ return count;
++ }
++ else if ((*buffer == 'd') || (*buffer == 'D')) {
++ jffs2_bbc_set_compression_mode(JFFS2_BBC_DUMMY_MODE);
++ jffs2_bbc_print1("jffs2.bbc: DUMMY compression mode activated.\n");
++ jffs2_bbc_free(buffer);
++ return count;
++ }
++ else if (((*buffer == 'm') || (*buffer == 'M')) && (count >= 3) && (buffer[1] == ':')) {
++ jffs2_bbc_print1("jffs2.bbc: activating MANUAL mode.\n");
++ jffs2_bbc_set_manual_compressor_by_name(buffer + 2);
++ jffs2_bbc_free(buffer);
++ return count;
++ }
++ else if (((*buffer == '0')) && (count >= 3) && (buffer[1] == ':')) {
++ jffs2_bbc_print1("jffs2.bbc: disabling a compressor... ");
++ if (jffs2_bbc_disable_compressor_by_name(buffer + 2) == 0) {
++ jffs2_bbc_print1("done.\n");
++ }
++ else {
++ jffs2_bbc_print1("not found.\n");
++ }
++ jffs2_bbc_free(buffer);
++ return count;
++ }
++ else if (((*buffer == '1')) && (count >= 3) && (buffer[1] == ':')) {
++ jffs2_bbc_print1("jffs2.bbc: enabling a compressor... ");
++ if (jffs2_bbc_enable_compressor_by_name(buffer + 2) == 0) {
++ jffs2_bbc_print1("done.\n");
++ }
++ else {
++ jffs2_bbc_print1("not found.\n");
++ }
++ jffs2_bbc_free(buffer);
++ return count;
++ }
++ else if (((*buffer == 'c') || (*buffer == 'C')) && (count >= 3) && (buffer[1] == ':')) {
++ jffs2_bbc_compressor_command_by_name(buffer + 2);
++ jffs2_bbc_free(buffer);
++ return count;
++ }
++ else if ((*buffer == 'r') || (*buffer == 'R')) {
++ jffs2_bbc_print1("jffs2.bbc: reloading model files:\n");
++ sb_l = sb_list;
++ while (sb_l != NULL) {
++ jffs2_bbc_unload_model(sb_l->sb);
++ jffs2_bbc_load_model(sb_l->sb);
++ sb_l = sb_l->next;
++ }
++ jffs2_bbc_free(buffer);
++ return count;
++ }
++ else if (((buffer[0] == 'f') || (buffer[0] == 'F'))&&((buffer[1] == 'r') || (buffer[1] == 'R'))) {
++ jffs2_bbc_set_compression_mode(JFFS2_BBC_FASTR_MODE);
++ jffs2_bbc_print1("jffs2.bbc: FASTR compression mode activated.\n");
++ jffs2_bbc_free(buffer);
++ return count;
++ }
++ else if (((buffer[0] == 'f') || (buffer[0] == 'F'))&&((buffer[1] == 'w') || (buffer[1] == 'W'))) {
++ jffs2_bbc_set_compression_mode(JFFS2_BBC_FASTW_MODE);
++ jffs2_bbc_print1("jffs2.bbc: FASTW compression mode activated.\n");
++ jffs2_bbc_free(buffer);
++ return count;
++ }
++ else if (((buffer[0] == 'f') || (buffer[0] == 'F'))&&((buffer[1] == 's') || (buffer[1] == 'S'))) {
++ jffs2_bbc_set_compression_mode(JFFS2_BBC_FASTS_MODE);
++ jffs2_bbc_print1("jffs2.bbc: FASTS compression mode activated.\n");
++ jffs2_bbc_free(buffer);
++ return count;
++ }
++
++ jffs2_bbc_print1("jffs2.bbc: unkown command. Valid commands are:\n"
++ " z = switch to ZLIB compression mode\n"
++ " s = switch to SIZE compression mode\n"
++ " d = switch to DUMMY compression mode\n"
++ " fr = switch to FASTR compression mode\n"
++ " fw = switch to FASTW compression mode\n"
++ " fs = switch to FASTS compression mode\n"
++ " r = reread model files from actual file system\n"
++ " m:compressor_name = switch to MANUAL compression mode\n"
++ " 0:compressor_name = disable a compressor\n"
++ " 1:compressor_name = enable a compressor\n"
++ " c:compressor_name:command = enable a compressor\n");
++ jffs2_bbc_free(buffer);
++ return count;
++}
++
++void jffs2_bbc_proc_init()
++{
++ struct proc_dir_entry *res = create_proc_entry("jffs2_bbc", 0, NULL);
++ jffs2_bbc_compressor_init();
++ if (res) {
++ res->read_proc = jffs2_bbc_proc_read;
++ res->write_proc = jffs2_bbc_proc_write;
++ }
++}
++
++void jffs2_bbc_proc_deinit()
++{
++ jffs2_bbc_compressor_deinit();
++ remove_proc_entry("jffs2_bbc", NULL);
++}
+diff -Nur linux-mips-cvs/fs/jffs2/jffs2_bbc_fs.h linux-mips/fs/jffs2/jffs2_bbc_fs.h
+--- linux-mips-cvs/fs/jffs2/jffs2_bbc_fs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips/fs/jffs2/jffs2_bbc_fs.h 2005-02-07 05:08:34.000000000 +0100
+@@ -0,0 +1,30 @@
++/*
++ * JFFS2 BBC: File System Extension for Linux Kernel - headers
++ *
++ * $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++ *
++ * Copyright (C) 2004, Ferenc Havasi
++ *
++ * 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.
++ *
++ */
++
++extern int jffs2_bbc_inode_not_found;
++
++void jffs2_bbc_load_model(void *sb);
++void jffs2_bbc_unload_model(void *sb);
++
++void jffs2_bbc_proc_init(void);
++void jffs2_bbc_proc_deinit(void);
+diff -Nur linux-mips-cvs/fs/jffs2/jffs2_bbc_lzari_comp.c linux-mips/fs/jffs2/jffs2_bbc_lzari_comp.c
+--- linux-mips-cvs/fs/jffs2/jffs2_bbc_lzari_comp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips/fs/jffs2/jffs2_bbc_lzari_comp.c 2005-02-07 05:08:34.000000000 +0100
+@@ -0,0 +1,788 @@
++/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
++
++/*
++ jffs2_bbc_lzari_comp.c -- Lempel-Ziv-Arithmetic coding compression module for jffs2
++ Copyright (C) 2004 Patrik Kluba
++ Based on the LZARI source included in LDS (lossless datacompression sources)
++ Block-compression and bitstream modifications by Patrik Kluba
++ $Header: /openwrt/openwrt/package/linux/kernel-patches/301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*/
++
++/*
++Original copyright follows:
++
++**************************************************************
++ LZARI.C -- A Data Compression Program
++ (tab = 4 spaces)
++**************************************************************
++ 4/7/1989 Haruhiko Okumura
++ Use, distribute, and modify this program freely.
++ Please send me your improved versions.
++ PC-VAN SCIENCE
++ NIFTY-Serve PAF01022
++ CompuServe 74050,1022
++**************************************************************
++
++LZARI.C (c)1989 by Haruyasu Yoshizaki, Haruhiko Okumura, and Kenji Rikitake.
++All rights reserved. Permission granted for non-commercial use.
++
++*/
++
++/*
++
++ 2004-02-18 pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
++ Removed unused variables and fixed no return value
++
++ 2004-02-16 pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
++ Initial release
++
++*/
++
++/* lzari.c */
++
++#define N 4096 /* size of ring buffer */
++#define F 60 /* upper limit for match_length */
++#define THRESHOLD 2 /* encode string into position and length
++ if match_length is greater than this */
++#define NIL N /* index for root of binary search trees */
++
++static unsigned char
++ text_buf[N + F - 1]; /* ring buffer of size N,
++ with extra F-1 bytes to facilitate string comparison */
++static unsigned long match_position, match_length, /* of longest match. These are
++ set by the InsertNode() procedure. */
++ lson[N + 1], rson[N + 257], dad[N + 1]; /* left & right children &
++ parents -- These constitute binary search trees. */
++
++static void InitTree(void) /* Initialize trees */
++{
++ unsigned long i;
++
++ /* For i = 0 to N - 1, rson[i] and lson[i] will be the right and
++ left children of node i. These nodes need not be initialized.
++ Also, dad[i] is the parent of node i. These are initialized to
++ NIL (= N), which stands for 'not used.'
++ For i = 0 to 255, rson[N + i + 1] is the root of the tree
++ for strings that begin with character i. These are initialized
++ to NIL. Note there are 256 trees. */
++
++ for (i = N + 1; i <= N + 256; i++) rson[i] = NIL; /* root */
++ for (i = 0; i < N; i++) dad[i] = NIL; /* node */
++}
++
++static void InsertNode(unsigned long r)
++ /* Inserts string of length F, text_buf[r..r+F-1], into one of the
++ trees (text_buf[r]'th tree) and returns the longest-match position
++ and length via the global variables match_position and match_length.
++ If match_length = F, then removes the old node in favor of the new
++ one, because the old one will be deleted sooner.
++ Note r plays double role, as tree node and position in buffer. */
++{
++ unsigned long i, p, temp;
++ unsigned char *key;
++ signed long cmp;
++
++ cmp = 1; key = &text_buf[r]; p = N + 1 + key[0];
++ rson[r] = lson[r] = NIL; match_length = 0;
++ for ( ; ; ) {
++ if (cmp >= 0) {
++ if (rson[p] != NIL) p = rson[p];
++ else { rson[p] = r; dad[r] = p; return; }
++ } else {
++ if (lson[p] != NIL) p = lson[p];
++ else { lson[p] = r; dad[r] = p; return; }
++ }
++ for (i = 1; i < F; i++)
++ if ((cmp = key[i] - text_buf[p + i]) != 0) break;
++ if (i > THRESHOLD) {
++ if (i > match_length) {
++ match_position = (r - p) & (N - 1);
++ if ((match_length = i) >= F) break;
++ } else if (i == match_length) {
++ if ((temp = (r - p) & (N - 1)) < match_position)
++ match_position = temp;
++ }
++ }
++ }
++ dad[r] = dad[p]; lson[r] = lson[p]; rson[r] = rson[p];
++ dad[lson[p]] = r; dad[rson[p]] = r;
++ if (rson[dad[p]] == p) rson[dad[p]] = r;
++ else lson[dad[p]] = r;
++ dad[p] = NIL; /* remove p */
++}
++
++static void DeleteNode(unsigned long p) /* Delete node p from tree */
++{
++ unsigned long q;
++
++ if (dad[p] == NIL) return; /* not in tree */
++ if (rson[p] == NIL) q = lson[p];
++ else if (lson[p] == NIL) q = rson[p];
++ else {
++ q = lson[p];
++ if (rson[q] != NIL) {
++ do { q = rson[q]; } while (rson[q] != NIL);
++ rson[dad[q]] = lson[q]; dad[lson[q]] = dad[q];
++ lson[q] = lson[p]; dad[lson[p]] = q;
++ }
++ rson[q] = rson[p]; dad[rson[p]] = q;
++ }
++ dad[q] = dad[p];
++ if (rson[dad[p]] == p) rson[dad[p]] = q;
++ else lson[dad[p]] = q;
++ dad[p] = NIL;
++}
++
++/********** Arithmetic Compression **********/
++
++/* If you are not familiar with arithmetic compression, you should read
++ I. E. Witten, R. M. Neal, and J. G. Cleary,
++ Communications of the ACM, Vol. 30, pp. 520-540 (1987),
++ from which much have been borrowed. */
++
++#define M 15
++
++/* Q1 (= 2 to the M) must be sufficiently large, but not so
++ large as the unsigned long 4 * Q1 * (Q1 - 1) overflows. */
++
++#define Q1 (1UL << M)
++#define Q2 (2 * Q1)
++#define Q3 (3 * Q1)
++#define Q4 (4 * Q1)
++#define MAX_CUM (Q1 - 1)
++
++#define N_CHAR (256 - THRESHOLD + F)
++ /* character code = 0, 1, ..., N_CHAR - 1 */
++
++static unsigned long char_to_sym[N_CHAR], sym_to_char[N_CHAR + 1];
++static unsigned long
++ sym_freq[N_CHAR + 1], /* frequency for symbols */
++ sym_cum[N_CHAR + 1], /* cumulative freq for symbols */
++ position_cum[N + 1]; /* cumulative freq for positions */
++
++static void StartModel(void) /* Initialize model */
++{
++ unsigned long ch, sym, i;
++
++ sym_cum[N_CHAR] = 0;
++ for (sym = N_CHAR; sym >= 1; sym--) {
++ ch = sym - 1;
++ char_to_sym[ch] = sym; sym_to_char[sym] = ch;
++ sym_freq[sym] = 1;
++ sym_cum[sym - 1] = sym_cum[sym] + sym_freq[sym];
++ }
++ sym_freq[0] = 0; /* sentinel (!= sym_freq[1]) */
++ position_cum[N] = 0;
++ for (i = N; i >= 1; i--)
++ position_cum[i - 1] = position_cum[i] + 10000 / (i + 200);
++ /* empirical distribution function (quite tentative) */
++ /* Please devise a better mechanism! */
++}
++
++static void UpdateModel(unsigned long sym)
++{
++ unsigned long c, ch_i, ch_sym;
++ unsigned long i;
++ if (sym_cum[0] >= MAX_CUM) {
++ c = 0;
++ for (i = N_CHAR; i > 0; i--) {
++ sym_cum[i] = c;
++ c += (sym_freq[i] = (sym_freq[i] + 1) >> 1);
++ }
++ sym_cum[0] = c;
++ }
++ for (i = sym; sym_freq[i] == sym_freq[i - 1]; i--) ;
++ if (i < sym) {
++ ch_i = sym_to_char[i]; ch_sym = sym_to_char[sym];
++ sym_to_char[i] = ch_sym; sym_to_char[sym] = ch_i;
++ char_to_sym[ch_i] = sym; char_to_sym[ch_sym] = i;
++ }
++ sym_freq[i]++;
++ while (--i > 0) sym_cum[i]++;
++ sym_cum[0]++;
++}
++
++static unsigned long BinarySearchSym(unsigned long x)
++ /* 1 if x >= sym_cum[1],
++ N_CHAR if sym_cum[N_CHAR] > x,
++ i such that sym_cum[i - 1] > x >= sym_cum[i] otherwise */
++{
++ unsigned long i, j, k;
++
++ i = 1; j = N_CHAR;
++ while (i < j) {
++ k = (i + j) / 2;
++ if (sym_cum[k] > x) i = k + 1; else j = k;
++ }
++ return i;
++}
++
++unsigned long BinarySearchPos(unsigned long x)
++ /* 0 if x >= position_cum[1],
++ N - 1 if position_cum[N] > x,
++ i such that position_cum[i] > x >= position_cum[i + 1] otherwise */
++{
++ unsigned long i, j, k;
++
++ i = 1; j = N;
++ while (i < j) {
++ k = (i + j) / 2;
++ if (position_cum[k] > x) i = k + 1; else j = k;
++ }
++ return i - 1;
++}
++
++/* modified for block compression */
++/* on return, srclen will contain the number of successfully compressed bytes
++ and dstlen will contain completed compressed bytes */
++
++static int Encode(unsigned char *srcbuf, unsigned char *dstbuf, unsigned long *srclen,
++ unsigned long *dstlen)
++{
++ unsigned long c, i, len, r, s, last_match_length, sym, range;
++ unsigned long low = 0;
++ unsigned long high = Q4;
++ unsigned long shifts = 0; /* counts for magnifying low and high around Q2 */
++ unsigned char *ip, *op;
++ unsigned long written = 0;
++ unsigned long read = 0;
++ unsigned char buffer = 0;
++ unsigned char mask = 128;
++ unsigned char *srcend = srcbuf + *srclen;
++ unsigned char *dstend = dstbuf + *dstlen;
++ ip = srcbuf;
++ op = dstbuf;
++ StartModel();
++ InitTree(); /* initialize trees */
++ s = 0; r = N - F;
++ for (i = s; i < r; i++) text_buf[i] = ' '; /* Clear the buffer with
++ any character that will appear often. */
++ for (len = 0; (len < F) && (ip < srcend); len++)
++ text_buf[r + len] = *(ip++); /* Read F bytes into the last F bytes of
++ the buffer */
++ read = len;
++ for (i = 1; i <= F; i++) InsertNode(r - i); /* Insert the F strings,
++ each of which begins with one or more 'space' characters. Note
++ the order in which these strings are inserted. This way,
++ degenerate trees will be less likely to occur. */
++ InsertNode(r); /* Finally, insert the whole string just read. The
++ global variables match_length and match_position are set. */
++ do {
++ if (match_length > len) match_length = len; /* match_length
++ may be spuriously long near the end of text. */
++ if (match_length <= THRESHOLD) {
++ match_length = 1; /* Not long enough match. Send one byte. */
++ sym = char_to_sym[text_buf[r]];
++ range = high - low;
++ high = low + (range * sym_cum[sym - 1]) / sym_cum[0];
++ low += (range * sym_cum[sym ]) / sym_cum[0];
++ for ( ; ; ) {
++ if (high <= Q2) {
++ if ((mask >>= 1) == 0) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = buffer;
++ buffer = 0;
++ mask = 128;
++ written++;
++ *srclen = read;
++ }
++ for ( ; shifts > 0; shifts--) {
++ buffer |= mask;
++ if ((mask >>= 1) == 0) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = buffer;
++ buffer = 0;
++ mask = 128;
++ written++;
++ *srclen = read;
++ }
++ }
++ } else if (low >= Q2) {
++ buffer |= mask;
++ if ((mask >>= 1) == 0) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = buffer;
++ buffer = 0;
++ mask = 128;
++ written++;
++ *srclen = read;
++ }
++ for ( ; shifts > 0; shifts--) {
++ if ((mask >>= 1) == 0) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = buffer;
++ buffer = 0;
++ mask = 128;
++ written++;
++ *srclen = read;
++ }
++ }
++ low -= Q2;
++ high -= Q2;
++ } else if (low >= Q1 && high <= Q3) {
++ shifts++;
++ low -= Q1;
++ high -= Q1;
++ } else break;
++ low += low; high += high;
++ }
++ UpdateModel(sym);
++ } else {
++ sym = char_to_sym[255 - THRESHOLD + match_length];
++ range = high - low;
++ high = low + (range * sym_cum[sym - 1]) / sym_cum[0];
++ low += (range * sym_cum[sym ]) / sym_cum[0];
++ for ( ; ; ) {
++ if (high <= Q2) {
++ if ((mask >>= 1) == 0) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = buffer;
++ buffer = 0;
++ mask = 128;
++ written++;
++ *srclen = read;
++ }
++ for ( ; shifts > 0; shifts--) {
++ buffer |= mask;
++ if ((mask >>= 1) == 0) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = buffer;
++ buffer = 0;
++ mask = 128;
++ written++;
++ *srclen = read;
++ }
++ }
++ } else if (low >= Q2) {
++ buffer |= mask;
++ if ((mask >>= 1) == 0) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = buffer;
++ buffer = 0;
++ mask = 128;
++ written++;
++ *srclen = read;
++ }
++ for ( ; shifts > 0; shifts--) {
++ if ((mask >>= 1) == 0) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = buffer;
++ buffer = 0;
++ mask = 128;
++ written++;
++ *srclen = read;
++ }
++ }
++ low -= Q2;
++ high -= Q2;
++ } else if (low >= Q1 && high <= Q3) {
++ shifts++;
++ low -= Q1;
++ high -= Q1;
++ } else break;
++ low += low; high += high;
++ }
++ UpdateModel(sym);
++ range = high - low;
++ high = low + (range * position_cum[match_position - 1]) / position_cum[0];
++ low += (range * position_cum[match_position ]) / position_cum[0];
++ for ( ; ; ) {
++ if (high <= Q2) {
++ if ((mask >>= 1) == 0) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = buffer;
++ buffer = 0;
++ mask = 128;
++ written++;
++ *srclen = read;
++ }
++ for ( ; shifts > 0; shifts--) {
++ buffer |= mask;
++ if ((mask >>= 1) == 0) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = buffer;
++ buffer = 0;
++ mask = 128;
++ written++;
++ *srclen = read;
++ }
++ }
++ } else {
++ if (low >= Q2) {
++ buffer |= mask;
++ if ((mask >>= 1) == 0) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = buffer;
++ buffer = 0;
++ mask = 128;
++ written++;
++ *srclen = read;
++ }
++ for ( ; shifts > 0; shifts--) {
++ if ((mask >>= 1) == 0) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = buffer;
++ buffer = 0;
++ mask = 128;
++ written++;
++ *srclen = read;
++ }
++ }
++ low -= Q2;
++ high -= Q2;
++ } else {
++ if ((low >= Q1) && (high <= Q3)) {
++ shifts++;
++ low -= Q1;
++ high -= Q1;
++ } else {
++ break;
++ }
++ }
++ }
++ low += low;
++ high += high;
++ }
++ }
++ last_match_length = match_length;
++ for (i = 0; (i < last_match_length) && (ip < srcend); i++) {
++ c = *(ip++);
++ DeleteNode(s);
++ text_buf[s] = c;
++ if (s < F - 1)
++ text_buf[s + N] = c;
++ s = (s + 1) & (N - 1);
++ r = (r + 1) & (N - 1);
++ InsertNode(r);
++ }
++ read += i;
++ while (i++ < last_match_length) {
++ DeleteNode(s);
++ s = (s + 1) & (N - 1);
++ r = (r + 1) & (N - 1);
++ if (--len) InsertNode(r);
++ }
++ } while (len > 0);
++ shifts++;
++ if (low < Q1) {
++ if ((mask >>= 1) == 0) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = buffer;
++ buffer = 0;
++ mask = 128;
++ written++;
++ *srclen = read;
++ }
++ for ( ; shifts > 0; shifts--) {
++ buffer |= mask;
++ if ((mask >>= 1) == 0) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = buffer;
++ buffer = 0;
++ mask = 128;
++ written++;
++ *srclen = read;
++ }
++ }
++ } else {
++ buffer |= mask;
++ if ((mask >>= 1) == 0) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = buffer;
++ buffer = 0;
++ mask = 128;
++ written++;
++ *srclen = read;
++ }
++ for ( ; shifts > 0; shifts--) {
++ if ((mask >>= 1) == 0) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = buffer;
++ buffer = 0;
++ mask = 128;
++ written++;
++ *srclen = read;
++ }
++ }
++ }
++ for (i = 0; i < 7; i++) {
++ if ((mask >>= 1) == 0) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = buffer;
++ buffer = 0;
++ mask = 128;
++ written++;
++ *srclen = read;
++ }
++ }
++ *dstlen = written;
++ return 0;
++}
++
++static int Decode(unsigned char *srcbuf, unsigned char *dstbuf, unsigned long srclen,
++ unsigned long dstlen) /* Just the reverse of Encode(). */
++{
++ unsigned long i, r, j, k, c, range, sym;
++ unsigned char *ip, *op;
++ unsigned char *srcend = srcbuf + srclen;
++ unsigned char *dstend = dstbuf + dstlen;
++ unsigned char buffer = 0;
++ unsigned char mask = 0;
++ unsigned long low = 0;
++ unsigned long high = Q4;
++ unsigned long value = 0;
++ ip = srcbuf;
++ op = dstbuf;
++ for (i = 0; i < M + 2; i++) {
++ value *= 2;
++ if ((mask >>= 1) == 0) {
++ buffer = (ip >= srcend) ? 0 : *(ip++);
++ mask = 128;
++ }
++ value += ((buffer & mask) != 0);
++ }
++ StartModel();
++ for (i = 0; i < N - F; i++) text_buf[i] = ' ';
++ r = N - F;
++ while (op < dstend) {
++ range = high - low;
++ sym = BinarySearchSym((unsigned long)
++ (((value - low + 1) * sym_cum[0] - 1) / range));
++ high = low + (range * sym_cum[sym - 1]) / sym_cum[0];
++ low += (range * sym_cum[sym ]) / sym_cum[0];
++ for ( ; ; ) {
++ if (low >= Q2) {
++ value -= Q2; low -= Q2; high -= Q2;
++ } else if (low >= Q1 && high <= Q3) {
++ value -= Q1; low -= Q1; high -= Q1;
++ } else if (high > Q2) break;
++ low += low; high += high;
++ value *= 2;
++ if ((mask >>= 1) == 0) {
++ buffer = (ip >= srcend) ? 0 : *(ip++);
++ mask = 128;
++ }
++ value += ((buffer & mask) != 0);
++ }
++ c = sym_to_char[sym];
++ UpdateModel(sym);
++ if (c < 256) {
++ if (op >= dstend) return -1;
++ *(op++) = c;
++ text_buf[r++] = c;
++ r &= (N - 1);
++ } else {
++ j = c - 255 + THRESHOLD;
++ range = high - low;
++ i = BinarySearchPos((unsigned long)
++ (((value - low + 1) * position_cum[0] - 1) / range));
++ high = low + (range * position_cum[i ]) / position_cum[0];
++ low += (range * position_cum[i + 1]) / position_cum[0];
++ for ( ; ; ) {
++ if (low >= Q2) {
++ value -= Q2; low -= Q2; high -= Q2;
++ } else if (low >= Q1 && high <= Q3) {
++ value -= Q1; low -= Q1; high -= Q1;
++ } else if (high > Q2) break;
++ low += low; high += high;
++ value *= 2;
++ if ((mask >>= 1) == 0) {
++ buffer = (ip >= srcend) ? 0 : *(ip++);
++ mask = 128;
++ }
++ value += ((buffer & mask) != 0);
++ }
++ i = (r - i - 1) & (N - 1);
++ for (k = 0; k < j; k++) {
++ c = text_buf[(i + k) & (N - 1)];
++ if (op >= dstend) return -1;
++ *(op++) = c;
++ text_buf[r++] = c;
++ r &= (N - 1);
++ }
++ }
++ }
++ return 0;
++}
++
++/* interface to jffs2 bbc follows */
++
++#include "jffs2_bbc_framework.h"
++
++#define JFFS2_BBC_LZARI_BLOCK_SIGN {0x73, 0x9a, 0x1c, 0x4d}
++
++static int
++jffs2_bbc_lzari_compressor_init (void);
++
++static void
++jffs2_bbc_lzari_compressor_deinit (void);
++
++static int
++jffs2_bbc_lzari_compress (void *model, unsigned char *input,
++ unsigned char *output, unsigned long *sourcelen,
++ unsigned long *dstlen);
++
++static int
++jffs2_bbc_lzari_estimate (void *model, unsigned char *input,
++ unsigned long sourcelen, unsigned long *dstlen,
++ unsigned long *readtime, unsigned long *writetime);
++
++static int
++jffs2_bbc_lzari_decompress (void *model, unsigned char *input,
++ unsigned char *output, unsigned long sourcelen,
++ unsigned long dstlen);
++
++static char *
++jffs2_bbc_lzari_proc_info (void);
++
++static int
++jffs2_bbc_lzari_proc_command (char *command);
++
++struct jffs2_bbc_compressor_type jffs2_bbc_lzari = {
++ "lzari",
++ 0,
++ JFFS2_BBC_LZARI_BLOCK_SIGN,
++ jffs2_bbc_lzari_compressor_init,
++ NULL,
++ NULL,
++ jffs2_bbc_lzari_compressor_deinit,
++ jffs2_bbc_lzari_compress,
++ jffs2_bbc_lzari_estimate,
++ jffs2_bbc_lzari_decompress,
++ jffs2_bbc_lzari_proc_info,
++ jffs2_bbc_lzari_proc_command
++};
++
++static int
++jffs2_bbc_lzari_compressor_init (void)
++{
++ return 0;
++}
++
++static void
++jffs2_bbc_lzari_compressor_deinit (void)
++{
++}
++
++static int
++jffs2_bbc_lzari_compress (void *model, unsigned char *input,
++ unsigned char *output, unsigned long *sourcelen,
++ unsigned long *dstlen)
++{
++ int retval;
++ unsigned long dst = *dstlen;
++ *(output++) = jffs2_bbc_lzari.block_sign[0];
++ *(output++) = jffs2_bbc_lzari.block_sign[1];
++ dst -= 2;
++ retval = Encode(input, output, sourcelen, &dst);
++ dst += 2;
++ *dstlen = dst;
++ return retval;
++}
++
++static int
++jffs2_bbc_lzari_estimate (void *model, unsigned char *input,
++ unsigned long sourcelen, unsigned long *dstlen,
++ unsigned long *readtime, unsigned long *writetime)
++{
++ *dstlen = sourcelen / 2;
++ *readtime = JFFS2_BBC_ZLIB_READ_TIME * 15;
++ *writetime = JFFS2_BBC_ZLIB_WRITE_TIME * 7;
++ return 0;
++}
++
++static int
++jffs2_bbc_lzari_decompress (void *model, unsigned char *input,
++ unsigned char *output, unsigned long sourcelen,
++ unsigned long dstlen)
++{
++ if ( ( *(input++) != (unsigned char)jffs2_bbc_lzari.block_sign[0] ) ||
++ ( *(input++) != (unsigned char)jffs2_bbc_lzari.block_sign[1] )
++ ) {
++ return -1;
++ } else {
++ return Decode(input, output, sourcelen - 2, dstlen);
++ }
++}
++
++static char *
++jffs2_bbc_lzari_proc_info (void)
++{
++ return "Lempel-Ziv-Arithmetic coding compression module";
++}
++
++static int
++jffs2_bbc_lzari_proc_command (char *command)
++{
++ return 0;
++}
++
++struct jffs2_bbc_compressor_type *
++jffs2_bbc_lzari_init (int mode)
++{
++ if (jffs2_bbc_register_compressor (&jffs2_bbc_lzari) == 0)
++ {
++ return &jffs2_bbc_lzari;
++ }
++ else
++ {
++ return NULL;
++ }
++}
++
++void
++jffs2_bbc_lzari_deinit (void)
++{
++ jffs2_bbc_unregister_compressor (&jffs2_bbc_lzari);
++}
+diff -Nur linux-mips-cvs/fs/jffs2/jffs2_bbc_lzhd_comp.c linux-mips/fs/jffs2/jffs2_bbc_lzhd_comp.c
+--- linux-mips-cvs/fs/jffs2/jffs2_bbc_lzhd_comp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips/fs/jffs2/jffs2_bbc_lzhd_comp.c 2005-02-07 05:08:34.000000000 +0100
+@@ -0,0 +1,747 @@
++/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
++
++/*
++ jffs2_bbc_lzhd_comp.c -- Lempel-Ziv-(dynamic) Huffman compression module for jffs2
++ Copyright (C) 2004 Patrik Kluba
++ Based on the LZHUF source included in LDS (lossless datacompression sources)
++ Block-compression and bitstream modifications by Patrik Kluba
++ $Header: /openwrt/openwrt/package/linux/kernel-patches/301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*/
++
++/*
++Original copyright follows:
++
++**************************************************************
++ lzhuf.c
++ written by Haruyasu Yoshizaki 11/20/1988
++ some minor changes 4/6/1989
++ comments translated by Haruhiko Okumura 4/7/1989
++**************************************************************
++
++LZHUF.C (c)1989 by Haruyasu Yoshizaki, Haruhiko Okumura, and Kenji Rikitake.
++All rights reserved. Permission granted for non-commercial use.
++
++*/
++
++/*
++
++ 2004-02-18 pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
++ Replaced name lzh-d with lzhd
++ Fixed no return value
++
++ 2004-02-16 pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
++ Initial release
++
++*/
++
++/* required because of memmove */
++#ifndef __KERNEL__
++ #include <string.h>
++#else
++ #include <linux/string.h>
++#endif
++
++/* lzhuf.c */
++
++#define N 4096 /* size of ring buffer */
++#define F 60 /* upper limit for match_length */
++#define THRESHOLD 2 /* encode string into position and length
++ if match_length is greater than this */
++#define NIL N /* index for root of binary search trees */
++
++static unsigned char
++ text_buf[N + F - 1]; /* ring buffer of size N,
++ with extra F-1 bytes to facilitate string comparison */
++static unsigned long match_position, match_length, /* of longest match. These are
++ set by the InsertNode() procedure. */
++ lson[N + 1], rson[N + 257], dad[N + 1]; /* left & right children &
++ parents -- These constitute binary search trees. */
++
++static void InitTree(void) /* initialize trees */
++{
++ unsigned long i;
++
++ /* For i = 0 to N - 1, rson[i] and lson[i] will be the right and
++ left children of node i. These nodes need not be initialized.
++ Also, dad[i] is the parent of node i. These are initialized to
++ NIL (= N), which stands for 'not used.'
++ For i = 0 to 255, rson[N + i + 1] is the root of the tree
++ for strings that begin with character i. These are initialized
++ to NIL. Note there are 256 trees. */
++
++ for (i = N + 1; i <= N + 256; i++) rson[i] = NIL;
++ for (i = 0; i < N; i++) dad[i] = NIL;
++}
++
++static void InsertNode(unsigned long r)
++ /* Inserts string of length F, text_buf[r..r+F-1], into one of the
++ trees (text_buf[r]'th tree) and returns the longest-match position
++ and length via the global variables match_position and match_length.
++ If match_length = F, then removes the old node in favor of the new
++ one, because the old one will be deleted sooner.
++ Note r plays double role, as tree node and position in buffer. */
++{
++ unsigned long i, p, c;
++ signed long cmp;
++ unsigned char *key;
++
++ cmp = 1; key = &text_buf[r]; p = N + 1 + key[0];
++ rson[r] = lson[r] = NIL; match_length = 0;
++ for ( ; ; ) {
++ if (cmp >= 0) {
++ if (rson[p] != NIL) p = rson[p];
++ else { rson[p] = r; dad[r] = p; return; }
++ } else {
++ if (lson[p] != NIL) p = lson[p];
++ else { lson[p] = r; dad[r] = p; return; }
++ }
++ for (i = 1; i < F; i++)
++ if ((cmp = key[i] - text_buf[p + i]) != 0) break;
++ if (i > THRESHOLD) {
++ if (i > match_length) {
++ match_position = ((r - p) & (N - 1)) - 1;
++ if ((match_length = i) >= F) break;
++ }
++ if (i == match_length) {
++ if ((c = ((r - p) & (N - 1)) - 1) < match_position) {
++ match_position = c;
++ }
++ }
++ }
++ }
++ dad[r] = dad[p]; lson[r] = lson[p]; rson[r] = rson[p];
++ dad[lson[p]] = r; dad[rson[p]] = r;
++ if (rson[dad[p]] == p) rson[dad[p]] = r;
++ else lson[dad[p]] = r;
++ dad[p] = NIL; /* remove p */
++}
++
++static void DeleteNode(unsigned long p) /* deletes node p from tree */
++{
++ unsigned long q;
++
++ if (dad[p] == NIL) return; /* not in tree */
++ if (rson[p] == NIL) q = lson[p];
++ else if (lson[p] == NIL) q = rson[p];
++ else {
++ q = lson[p];
++ if (rson[q] != NIL) {
++ do { q = rson[q]; } while (rson[q] != NIL);
++ rson[dad[q]] = lson[q]; dad[lson[q]] = dad[q];
++ lson[q] = lson[p]; dad[lson[p]] = q;
++ }
++ rson[q] = rson[p]; dad[rson[p]] = q;
++ }
++ dad[q] = dad[p];
++ if (rson[dad[p]] == p) rson[dad[p]] = q; else lson[dad[p]] = q;
++ dad[p] = NIL;
++}
++
++/* Huffman coding */
++
++#define N_CHAR (256 - THRESHOLD + F)
++ /* kinds of characters (character code = 0..N_CHAR-1) */
++#define T (N_CHAR * 2 - 1) /* size of table */
++#define R (T - 1) /* position of root */
++#define MAX_FREQ 0x8000 /* updates tree when the */
++ /* root frequency comes to this value. */
++
++typedef unsigned long uchar; // much-much faster
++
++/* table for encoding and decoding the upper 6 bits of position */
++
++/* for encoding */
++static uchar p_len[64] = {
++ 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
++ 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
++ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
++ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
++ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
++ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
++ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
++ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
++};
++
++static uchar p_code[64] = {
++ 0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
++ 0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
++ 0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
++ 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
++ 0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
++ 0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
++ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
++ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
++};
++
++/* for decoding */
++static uchar d_code[256] = {
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
++ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
++ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
++ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
++ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
++ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
++ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
++ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
++ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
++ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
++ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
++ 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
++ 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
++ 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
++ 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
++ 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
++ 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
++ 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
++ 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
++ 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
++ 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
++ 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
++ 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
++ 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
++ 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
++ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
++ 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
++};
++
++static uchar d_len[256] = {
++ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
++ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
++ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
++ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
++ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
++ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
++ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
++ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
++ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
++ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
++ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
++ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
++ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
++ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
++ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
++ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
++ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
++ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
++ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
++ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
++ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
++ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
++ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
++ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
++ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
++ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
++ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
++ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
++ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
++ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
++ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
++ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
++};
++
++static unsigned long freq[T + 1]; /* frequency table */
++
++static unsigned long prnt[T + N_CHAR]; /* pointers to parent nodes, except for the */
++ /* elements [T..T + N_CHAR - 1] which are used to get */
++ /* the positions of leaves corresponding to the codes. */
++
++static unsigned long son[T]; /* pointers to child nodes (son[], son[] + 1) */
++
++/* initialization of tree */
++
++static void StartHuff(void)
++{
++ unsigned long i, j;
++
++ for (i = 0; i < N_CHAR; i++) {
++ freq[i] = 1;
++ son[i] = i + T;
++ prnt[i + T] = i;
++ }
++ i = 0; j = N_CHAR;
++ while (j <= R) {
++ freq[j] = freq[i] + freq[i + 1];
++ son[j] = i;
++ prnt[i] = prnt[i + 1] = j;
++ i += 2; j++;
++ }
++ freq[T] = 0xffff;
++ prnt[R] = 0;
++}
++
++/* reconstruction of tree */
++
++static void reconst(void)
++{
++ unsigned long f, l, i, j, k;
++
++ /* collect leaf nodes in the first half of the table */
++ /* and replace the freq by (freq + 1) / 2. */
++ j = 0;
++ for (i = 0; i < T; i++) {
++ if (son[i] >= T) {
++ freq[j] = (freq[i] + 1) / 2;
++ son[j] = son[i];
++ j++;
++ }
++ }
++ /* begin constructing tree by connecting sons */
++ for (i = 0, j = N_CHAR; j < T; i += 2, j++) {
++ k = i + 1;
++ f = freq[j] = freq[i] + freq[k];
++ for (k = j - 1; f < freq[k]; k--);
++ k++;
++ l = (j - k) * 2;
++ memmove(&freq[k + 1], &freq[k], l*sizeof(unsigned long));
++ freq[k] = f;
++ memmove(&son[k + 1], &son[k], l*sizeof(unsigned long));
++ son[k] = i;
++ }
++ /* connect prnt */
++ for (i = 0; i < T; i++) {
++ if ((k = son[i]) >= T) {
++ prnt[k] = i;
++ } else {
++ prnt[k] = prnt[k + 1] = i;
++ }
++ }
++}
++
++/* increment frequency of given code by one, and update tree */
++
++static void update(unsigned long c)
++{
++ unsigned long i, j, k, l;
++
++ if (freq[R] == MAX_FREQ) {
++ reconst();
++ }
++ c = prnt[c + T];
++ do {
++ k = ++freq[c];
++
++ /* if the order is disturbed, exchange nodes */
++ if (k > freq[l = c + 1]) {
++ while (k > freq[++l]);
++ l--;
++ freq[c] = freq[l];
++ freq[l] = k;
++
++ i = son[c];
++ prnt[i] = l;
++ if (i < T) prnt[i + 1] = l;
++
++ j = son[l];
++ son[l] = i;
++
++ prnt[j] = c;
++ if (j < T) prnt[j + 1] = c;
++ son[c] = j;
++
++ c = l;
++ }
++ } while (c = prnt[c]); /* repeat up to root */
++}
++
++/* modified for block compression */
++/* on return, srclen will contain the number of successfully compressed bytes
++ and dstlen will contain completed compressed bytes */
++
++static int Encode(unsigned char *srcbuf, unsigned char *dstbuf, unsigned long *srclen,
++ unsigned long *dstlen)
++{
++ unsigned long c, i, j, k, len, r, s, last_match_length, code_buf_ptr;
++ unsigned char code_buf[17], mask;
++ unsigned char *ip, *op;
++ unsigned long written = 0;
++ unsigned long read = 0;
++ unsigned short putbuf = 0;
++ uchar putlen = 0;
++ unsigned char *srcend = srcbuf + *srclen;
++ unsigned char *dstend = dstbuf + *dstlen;
++ ip = srcbuf;
++ op = dstbuf;
++ StartHuff();
++ InitTree(); /* initialize trees */
++ code_buf[0] = 0; /* code_buf[1..16] saves eight units of code, and
++ code_buf[0] works as eight flags, "1" representing that the unit
++ is an unencoded letter (1 byte), "0" a position-and-length pair
++ (2 bytes). Thus, eight units require at most 16 bytes of code. */
++ code_buf_ptr = mask = 1;
++ s = 0; r = N - F;
++ for (i = s; i < r; i++) text_buf[i] = ' '; /* Clear the buffer with
++ any character that will appear often. */
++ for (len = 0; (len < F) && (ip < srcend); len++)
++ text_buf[r + len] = *(ip++); /* Read F bytes into the last F bytes of
++ the buffer */
++ read = len;
++ for (i = 1; i <= F; i++) InsertNode(r - i); /* Insert the F strings,
++ each of which begins with one or more 'space' characters. Note
++ the order in which these strings are inserted. This way,
++ degenerate trees will be less likely to occur. */
++ InsertNode(r); /* Finally, insert the whole string just read. The
++ global variables match_length and match_position are set. */
++ do {
++ if (match_length > len) match_length = len; /* match_length
++ may be spuriously long near the end of text. */
++ if (match_length <= THRESHOLD) {
++ match_length = 1; /* Not long enough match. Send one byte. */
++ c = text_buf[r];
++ i = 0; j = 0; k = prnt[c + T];
++ do {
++ i >>= 1;
++ /* if node's address is odd-numbered, choose bigger brother node */
++ if (k & 1) i |= 0x8000;
++ j++;
++ } while ((k = prnt[k]) != R);
++ putbuf |= i >> putlen;
++ if ((putlen += j) >= 8) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = putbuf >> 8;
++ if ((putlen -= 8) >= 8) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = putbuf;
++ written += 2;
++ putlen -= 8;
++ putbuf = i << (j - putlen); /**warm**/
++ } else {
++ putbuf <<= 8;
++ written++;
++ }
++ *srclen = read;
++ }
++ update(c);
++ } else {
++ c = 255 - THRESHOLD + match_length;
++ i = 0; j = 0; k = prnt[c + T];
++ do {
++ i >>= 1;
++ /* if node's address is odd-numbered, choose bigger brother node */
++ if (k & 1) i |= 0x8000;
++ j++;
++ } while ((k = prnt[k]) != R);
++ putbuf |= i >> putlen;
++ if ((putlen += j) >= 8) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = putbuf >> 8;
++ if ((putlen -= 8) >= 8) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = putbuf;
++ written += 2;
++ putlen -= 8;
++ putbuf = i << (j - putlen); /**warm**/
++ } else {
++ putbuf <<= 8;
++ written++;
++ }
++ *srclen = read;
++ }
++ update(c);
++ j = p_len[match_position >> 6];
++ i = p_code[match_position >> 6] << 8;
++ putbuf |= i >> putlen;
++ if ((putlen += j) >= 8) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = putbuf >> 8;
++ if ((putlen -= 8) >= 8) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = putbuf;
++ written += 2;
++ putlen -= 8;
++ putbuf = i << (j - putlen); /**hot**/
++ } else {
++ putbuf <<= 8;
++ written++;
++ }
++ *srclen = read;
++ }
++ j = 6;
++ i = (match_position & 0x3f) << 10;
++ putbuf |= i >> putlen;
++ if ((putlen += j) >= 8) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = putbuf >> 8;
++ if ((putlen -= 8) >= 8) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = putbuf;
++ written += 2;
++ putlen -= 8;
++ putbuf = i << (j - putlen); /**hot**/
++ } else {
++ putbuf <<= 8;
++ written++;
++ }
++ *srclen = read;
++ }
++ }
++ last_match_length = match_length;
++ for (i = 0; (i < last_match_length) && (ip < srcend); i++) {
++ c = *(ip++);
++ DeleteNode(s);
++ text_buf[s] = c;
++ if (s < F - 1)
++ text_buf[s + N] = c;
++ s = (s + 1) & (N - 1);
++ r = (r + 1) & (N - 1);
++ InsertNode(r);
++ }
++ read += i;
++ while (i++ < last_match_length) {
++ DeleteNode(s);
++ s = (s + 1) & (N - 1);
++ r = (r + 1) & (N - 1);
++ if (--len) InsertNode(r);
++ }
++ } while (len > 0);
++ if (putlen) {
++ if (op >= dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ *(op++) = putbuf >> 8;
++ written++;
++ *srclen = read;
++ }
++ *dstlen = written;
++ return 0;
++}
++
++static int Decode(unsigned char *srcbuf, unsigned char *dstbuf, unsigned long srclen,
++ unsigned long dstlen) /* Just the reverse of Encode(). */
++{
++ unsigned long i, r, j, k, c;
++ unsigned char *ip, *op;
++ unsigned char *srcend = srcbuf + srclen;
++ unsigned char *dstend = dstbuf + dstlen;
++ unsigned short getbuf = 0;
++ uchar getlen = 0;
++ ip = srcbuf;
++ op = dstbuf;
++ StartHuff();
++ for (i = 0; i < N - F; i++) text_buf[i] = ' ';
++ r = N - F;
++ while (op < dstend) {
++ c = son[R];
++ /* travel from root to leaf, */
++ /* choosing the smaller child node (son[]) if the read bit is 0, */
++ /* the bigger (son[]+1} if 1 */
++ while (c < T) {
++ while (getlen <= 8) {
++ unsigned short t;
++ t = (ip >= srcend) ? 0 : *(ip++);
++ getbuf |= t << (8 - getlen);
++ getlen += 8;
++ }
++ c += ((signed short)getbuf < 0);
++ getbuf <<= 1;
++ getlen--;
++ c = son[c];
++ }
++ c -= T;
++ update(c);
++ if (c < 256) {
++ if (op >= dstend) return -1;
++ *(op++) = c;
++ text_buf[r++] = c;
++ r &= (N - 1);
++ } else {
++ j = c - 255 + THRESHOLD;
++ while (getlen <= 8) {
++ unsigned short t;
++ t = (ip >= srcend) ? 0 : *(ip++);
++ getbuf |= t << (8 - getlen);
++ getlen += 8;
++ }
++ i = getbuf >> 8;
++ getbuf <<= 8;
++ getlen -= 8;
++ c = d_code[i] << 6;
++ k = d_len[i];
++ /* read lower 6 bits verbatim */
++ k -= 2;
++ while (k--) {
++ while (getlen <= 8) {
++ unsigned short t;
++ t = (ip >= srcend) ? 0 : *(ip++);
++ getbuf |= t << (8 - getlen);
++ getlen += 8;
++ }
++ i = (i << 1) + ((signed short)getbuf < 0);
++ getbuf <<= 1;
++ getlen--;
++ }
++ i = c | (i & 0x3F);
++ i = r - i - 1;
++ i &= (N - 1);
++ for (k = 0; k < j; k++) {
++ c = text_buf[(i + k) & (N - 1)];
++ if (op >= dstend) return -1;
++ *(op++) = c;
++ text_buf[r++] = c;
++ r &= (N - 1);
++ }
++ }
++ }
++ return 0;
++}
++
++/* interface to jffs2 bbc follows */
++
++#include "jffs2_bbc_framework.h"
++
++
++#define JFFS2_BBC_LZHD_BLOCK_SIGN {0x3a, 0x98, 0xf7, 0xda}
++
++static int
++jffs2_bbc_lzhd_compressor_init (void);
++
++static void
++jffs2_bbc_lzhd_compressor_deinit (void);
++
++static int
++jffs2_bbc_lzhd_compress (void *model, unsigned char *input,
++ unsigned char *output, unsigned long *sourcelen,
++ unsigned long *dstlen);
++
++static int
++jffs2_bbc_lzhd_estimate (void *model, unsigned char *input,
++ unsigned long sourcelen, unsigned long *dstlen,
++ unsigned long *readtime, unsigned long *writetime);
++
++static int
++jffs2_bbc_lzhd_decompress (void *model, unsigned char *input,
++ unsigned char *output, unsigned long sourcelen,
++ unsigned long dstlen);
++
++static char *
++jffs2_bbc_lzhd_proc_info (void);
++
++static int
++jffs2_bbc_lzhd_proc_command (char *command);
++
++struct jffs2_bbc_compressor_type jffs2_bbc_lzhd = {
++ "lzhd",
++ 0,
++ JFFS2_BBC_LZHD_BLOCK_SIGN,
++ jffs2_bbc_lzhd_compressor_init,
++ NULL,
++ NULL,
++ jffs2_bbc_lzhd_compressor_deinit,
++ jffs2_bbc_lzhd_compress,
++ jffs2_bbc_lzhd_estimate,
++ jffs2_bbc_lzhd_decompress,
++ jffs2_bbc_lzhd_proc_info,
++ jffs2_bbc_lzhd_proc_command
++};
++
++static int
++jffs2_bbc_lzhd_compressor_init (void)
++{
++ return 0;
++}
++
++static void
++jffs2_bbc_lzhd_compressor_deinit (void)
++{
++}
++
++static int
++jffs2_bbc_lzhd_compress (void *model, unsigned char *input,
++ unsigned char *output, unsigned long *sourcelen,
++ unsigned long *dstlen)
++{
++ int retval;
++ unsigned long dst = *dstlen;
++ *(output++) = jffs2_bbc_lzhd.block_sign[0];
++ *(output++) = jffs2_bbc_lzhd.block_sign[1];
++ dst -= 2;
++ retval = Encode(input, output, sourcelen, &dst);
++ dst += 2;
++ *dstlen = dst;
++ return retval;
++}
++
++static int
++jffs2_bbc_lzhd_estimate (void *model, unsigned char *input,
++ unsigned long sourcelen, unsigned long *dstlen,
++ unsigned long *readtime, unsigned long *writetime)
++{
++ *dstlen = sourcelen * 55 / 100;
++ *readtime = JFFS2_BBC_ZLIB_READ_TIME * 8;
++ *writetime = JFFS2_BBC_ZLIB_WRITE_TIME * 65 / 10;
++ return 0;
++}
++
++static int
++jffs2_bbc_lzhd_decompress (void *model, unsigned char *input,
++ unsigned char *output, unsigned long sourcelen,
++ unsigned long dstlen)
++{
++ if ( ( *(input++) != (unsigned char)jffs2_bbc_lzhd.block_sign[0] ) ||
++ ( *(input++) != (unsigned char)jffs2_bbc_lzhd.block_sign[1] )
++ ) {
++ return -1;
++ } else {
++ return Decode(input, output, sourcelen - 2, dstlen);
++ }
++}
++
++static char *
++jffs2_bbc_lzhd_proc_info (void)
++{
++ return "Lempel-Ziv-(dynamic) Huffman compression module";
++}
++
++static int
++jffs2_bbc_lzhd_proc_command (char *command)
++{
++ return 0;
++}
++
++struct jffs2_bbc_compressor_type *
++jffs2_bbc_lzhd_init (int mode)
++{
++ if (jffs2_bbc_register_compressor (&jffs2_bbc_lzhd) == 0)
++ {
++ return &jffs2_bbc_lzhd;
++ }
++ else
++ {
++ return NULL;
++ }
++}
++
++void
++jffs2_bbc_lzhd_deinit (void)
++{
++ jffs2_bbc_unregister_compressor (&jffs2_bbc_lzhd);
++}
+diff -Nur linux-mips-cvs/fs/jffs2/jffs2_bbc_lzo_comp.c linux-mips/fs/jffs2/jffs2_bbc_lzo_comp.c
+--- linux-mips-cvs/fs/jffs2/jffs2_bbc_lzo_comp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips/fs/jffs2/jffs2_bbc_lzo_comp.c 2005-02-07 05:08:34.000000000 +0100
+@@ -0,0 +1,2435 @@
++/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
++
++/*
++ jffs2_bbc_lzo_comp.c -- LZO1X-1 (and -999) compression module for jffs2
++ Copyright (C) 2004 Patrik Kluba
++ Based on the original LZO sources
++ $Header: /openwrt/openwrt/package/linux/kernel-patches/301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*/
++
++/*
++ Original copyright notice follows:
++
++ lzo1x_9x.c -- implementation of the LZO1X-999 compression algorithm
++ lzo_ptr.h -- low-level pointer constructs
++ lzo_swd.ch -- sliding window dictionary
++ lzoconf.h -- configuration for the LZO real-time data compression library
++ lzo_mchw.ch -- matching functions using a window
++ minilzo.c -- mini subset of the LZO real-time data compression library
++ config1x.h -- configuration for the LZO1X algorithm
++ lzo1x.h -- public interface of the LZO1X compression algorithm
++
++ These files are part of the LZO real-time data compression library.
++
++ Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
++ All Rights Reserved.
++
++ The LZO library 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.
++
++ The LZO 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 LZO library; see the file COPYING.
++ If not, write to the Free Software Foundation, Inc.,
++ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++ Markus F.X.J. Oberhumer
++ <markus@oberhumer.com>
++*/
++
++/*
++
++ 2004-02-16 pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
++ Initial release
++ -removed all 16 bit code
++ -all sensitive data will be on 4 byte boundary
++ -removed check parts for library use
++ -removed all but LZO1X-* compression
++
++*/
++
++#ifndef __KERNEL__
++ #include <sys/types.h>
++ #include <stddef.h>
++ #include <string.h>
++ #include <limits.h>
++#else
++ #include <linux/kernel.h>
++ #include <linux/types.h>
++ #include <linux/stddef.h>
++ #include <linux/string.h>
++ #define USHRT_MAX 65535
++ /* #define UINT_MAX 4294967295U */
++#endif
++
++/* data type definitions */
++#define U32 unsigned long
++#define S32 signed long
++#define I32 long
++#define U16 unsigned short
++#define S16 signed short
++#define I16 short
++#define U8 unsigned char
++#define S8 signed char
++#define I8 char
++
++/*************************************/
++
++/* lzo_swd.ch */
++
++#define SWD_N N
++#define SWD_F F
++#define SWD_THRESHOLD THRESHOLD
++
++/* shortest unsigned int that 2 * SWD_F + SWD_N (currently 53248) fits in */
++typedef unsigned short swd_uint;
++/* upper limit of that data type */
++#define SWD_UINT_MAX USHRT_MAX
++
++/* minilzo.c */
++
++#define LZO_VERSION_DATE "Jul 12 2002"
++#define LZO_VERSION_STRING "1.08"
++#define LZO_VERSION 0x1080
++
++/* lzo_ptr.h */
++
++/* Integral types that have *exactly* the same number of bits as a lzo_voidp */
++typedef unsigned long lzo_ptr_t;
++typedef long lzo_sptr_t;
++
++
++/*************************************/
++
++/* config1x.h */
++
++#define M1_MAX_OFFSET 0x0400
++#define M2_MAX_OFFSET 0x0800
++#define M3_MAX_OFFSET 0x4000
++#define M4_MAX_OFFSET 0xbfff
++
++#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET)
++
++#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 MIN_LOOKAHEAD (M2_MAX_LEN + 1)
++
++/* minilzo.c */
++
++#define LZO_BYTE(x) ((unsigned char) ((x) & 0xff))
++
++#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b))
++#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b))
++#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c))
++#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c))
++
++#define lzo_sizeof(type) ((lzo_uint) (sizeof(type)))
++
++#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array))))
++
++#define LZO_SIZE(bits) (1u << (bits))
++#define LZO_MASK(bits) (LZO_SIZE(bits) - 1)
++
++#define LZO_LSIZE(bits) (1ul << (bits))
++#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1)
++
++#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits))
++#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1)
++
++#define LZO_STYPE_MAX(b) (((1l << (8*(b)-2)) - 1l) + (1l << (8*(b)-2)))
++#define LZO_UTYPE_MAX(b) (((1ul << (8*(b)-1)) - 1ul) + (1ul << (8*(b)-1)))
++
++#define _LZO_STRINGIZE(x) #x
++#define _LZO_MEXPAND(x) _LZO_STRINGIZE(x)
++
++#define _LZO_CONCAT2(a,b) a ## b
++#define _LZO_CONCAT3(a,b,c) a ## b ## c
++#define _LZO_CONCAT4(a,b,c,d) a ## b ## c ## d
++#define _LZO_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e
++
++#define _LZO_ECONCAT2(a,b) _LZO_CONCAT2(a,b)
++#define _LZO_ECONCAT3(a,b,c) _LZO_CONCAT3(a,b,c)
++#define _LZO_ECONCAT4(a,b,c,d) _LZO_CONCAT4(a,b,c,d)
++#define _LZO_ECONCAT5(a,b,c,d,e) _LZO_CONCAT5(a,b,c,d,e)
++
++#define lzo_dict_t const lzo_bytep
++#define lzo_dict_p lzo_dict_t *
++#define lzo_moff_t lzo_uint
++
++#define MEMCPY8_DS(dest,src,len) \
++ memcpy(dest,src,len); \
++ dest += len; \
++ src += len
++
++#define MEMCPY_DS(dest,src,len) \
++ do *dest++ = *src++; \
++ while (--len > 0)
++
++#define MEMMOVE_DS(dest,src,len) \
++ do *dest++ = *src++; \
++ while (--len > 0)
++
++#define BZERO8_PTR(s,l,n) memset((s),0,(lzo_uint)(l)*(n))
++
++#define LZO_BASE 65521u
++#define LZO_NMAX 5552
++
++#define LZO_DO1(buf,i) {s1 += buf[i]; s2 += s1;}
++#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1);
++#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2);
++#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4);
++#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8);
++
++#define IS_SIGNED(type) (((type) (-1)) < ((type) 0))
++#define IS_UNSIGNED(type) (((type) (-1)) > ((type) 0))
++
++#define IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
++
++#define D_BITS 14
++#define D_INDEX1(d,p) d = DM((0x21*DX3(p,5,5,6)) >> 5)
++#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f)
++
++#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B
++
++#define DL_MIN_LEN M2_MIN_LEN
++
++#define D_SIZE LZO_SIZE(D_BITS)
++#define D_MASK LZO_MASK(D_BITS)
++
++#define D_HIGH ((D_MASK >> 1) + 1)
++
++#define DINDEX1 D_INDEX1
++#define DINDEX2 D_INDEX2
++
++#define DX2(p,s1,s2) \
++ (((((lzo_uint32)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0])
++
++#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0])
++#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s)))
++#define DM(v) DMS(v,0)
++
++#define DENTRY(p,in) (p)
++#define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex]
++
++#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \
++ (m_pos == NULL || (m_off = (lzo_moff_t) (ip - m_pos)) > max_offset)
++
++#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \
++ (BOUNDS_CHECKING_OFF_IN_EXPR( \
++ (PTR_LT(m_pos,in) || \
++ (m_off = (lzo_moff_t) PTR_DIFF(ip,m_pos)) <= 0 || \
++ m_off > max_offset) ))
++
++#define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr)
++
++#define DD_BITS 0
++#define DD_SIZE LZO_SIZE(DD_BITS)
++#define DD_MASK LZO_MASK(DD_BITS)
++
++#define DL_BITS (D_BITS - DD_BITS)
++#define DL_SIZE LZO_SIZE(DL_BITS)
++#define DL_MASK LZO_MASK(DL_BITS)
++
++#define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in)
++#define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in)
++#define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in)
++
++#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src)
++#define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src))
++
++#define TEST_IP (ip < ip_end)
++#define TEST_OP (op <= op_end)
++
++#define NEED_IP(x) \
++ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun
++#define NEED_OP(x) \
++ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun
++#define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun
++
++/* lzo1x_9x.c */
++
++#define LZO_UINT_MAX UINT_MAX
++#define N M4_MAX_OFFSET
++#define THRESHOLD 1
++#define F 2048
++
++#define SWD_BEST_OFF (LZO_MAX3( M2_MAX_LEN, M3_MAX_LEN, M4_MAX_LEN ) + 1)
++
++/* ../include/lzoconf.h */
++
++typedef U32 lzo_uint32;
++typedef I32 lzo_int32;
++typedef U32 lzo_uint;
++typedef I32 lzo_int;
++typedef int lzo_bool;
++
++#define lzo_byte U8
++#define lzo_bytep U8 *
++#define lzo_charp char *
++#define lzo_voidp void *
++#define lzo_shortp short *
++#define lzo_ushortp unsigned short *
++#define lzo_uint32p lzo_uint32 *
++#define lzo_int32p lzo_int32 *
++#define lzo_uintp lzo_uint *
++#define lzo_intp lzo_int *
++#define lzo_voidpp lzo_voidp *
++#define lzo_bytepp lzo_bytep *
++#define lzo_sizeof_dict_t sizeof(lzo_bytep)
++
++#define LZO_E_OK 0
++#define LZO_E_ERROR (-1)
++#define LZO_E_OUT_OF_MEMORY (-2) /* not used right now */
++#define LZO_E_NOT_COMPRESSIBLE (-3) /* not used right now */
++#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_PTR_ALIGN_UP(_ptr,_size) \
++ ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size)))
++#define LZO_ALIGN(_ptr,_size) LZO_PTR_ALIGN_UP(_ptr,_size)
++
++typedef int
++ (*lzo_compress_t) (const lzo_byte * src, lzo_uint src_len,
++ lzo_byte * dst, lzo_uintp dst_len,
++ lzo_voidp wrkmem);
++
++typedef int
++ (*lzo_decompress_t) (const lzo_byte * src, lzo_uint src_len,
++ lzo_byte * dst, lzo_uintp dst_len,
++ lzo_voidp wrkmem);
++
++typedef int
++ (*lzo_optimize_t) (lzo_byte * src, lzo_uint src_len,
++ lzo_byte * dst, lzo_uintp dst_len,
++ lzo_voidp wrkmem);
++
++typedef int
++ (*lzo_compress_dict_t) (const lzo_byte * src, lzo_uint src_len,
++ lzo_byte * dst, lzo_uintp dst_len,
++ lzo_voidp wrkmem,
++ const lzo_byte * dict, lzo_uint dict_len);
++
++typedef int
++ (*lzo_decompress_dict_t) (const lzo_byte * src, lzo_uint src_len,
++ lzo_byte * dst, lzo_uintp dst_len,
++ lzo_voidp wrkmem,
++ const lzo_byte * dict, lzo_uint dict_len);
++
++typedef int
++ (*lzo_compress_asm_t) (const lzo_byte * src, lzo_uint src_len,
++ lzo_byte * dst, lzo_uintp dst_len,
++ lzo_voidp wrkmem);
++
++typedef int
++ (*lzo_decompress_asm_t) (const lzo_byte * src, lzo_uint src_len,
++ lzo_byte * dst, lzo_uintp dst_len,
++ lzo_voidp wrkmem);
++
++typedef void (*lzo_progress_callback_t) (lzo_uint, lzo_uint);
++
++typedef union
++{
++ lzo_bytep p;
++ lzo_uint u;
++} __lzo_pu_u;
++typedef union
++{
++ lzo_bytep p;
++ lzo_uint32 u32;
++} __lzo_pu32_u;
++typedef union
++{
++ void *vp;
++ lzo_bytep bp;
++ lzo_uint32 u32;
++ long l;
++} lzo_align_t;
++
++/* lzo1x.h */
++
++#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
++#define LZO1X_999_MEM_COMPRESS ((lzo_uint32) (14 * 16384L * sizeof(short)))
++
++/* lzo_ptr.h */
++
++#define PTR(a) ((lzo_ptr_t) (a))
++#define PTR_LINEAR(a) PTR(a)
++#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0)
++#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0)
++#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0)
++#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0)
++#define PTR_LT(a,b) (PTR(a) < PTR(b))
++#define PTR_GE(a,b) (PTR(a) >= PTR(b))
++#define PTR_DIFF(a,b) ((lzo_ptrdiff_t) (PTR(a) - PTR(b)))
++#define pd(a,b) ((lzo_uint) ((a)-(b)))
++
++typedef ptrdiff_t lzo_ptrdiff_t;
++
++typedef union
++{
++ char a_char;
++ unsigned char a_uchar;
++ short a_short;
++ unsigned short a_ushort;
++ int a_int;
++ unsigned int a_uint;
++ long a_long;
++ unsigned long a_ulong;
++ lzo_int a_lzo_int;
++ lzo_uint a_lzo_uint;
++ lzo_int32 a_lzo_int32;
++ lzo_uint32 a_lzo_uint32;
++ ptrdiff_t a_ptrdiff_t;
++ lzo_ptrdiff_t a_lzo_ptrdiff_t;
++ lzo_ptr_t a_lzo_ptr_t;
++ lzo_voidp a_lzo_voidp;
++ void *a_void_p;
++ lzo_bytep a_lzo_bytep;
++ lzo_bytepp a_lzo_bytepp;
++ lzo_uintp a_lzo_uintp;
++ lzo_uint *a_lzo_uint_p;
++ lzo_uint32p a_lzo_uint32p;
++ lzo_uint32 *a_lzo_uint32_p;
++ unsigned char *a_uchar_p;
++ char *a_char_p;
++}
++lzo_full_align_t;
++
++/* lzo_mchw.ch */
++
++typedef struct
++{
++ int init;
++
++ lzo_uint look;
++
++ lzo_uint m_len;
++ lzo_uint m_off;
++
++ lzo_uint last_m_len;
++ lzo_uint last_m_off;
++
++ const lzo_byte *bp;
++ const lzo_byte *ip;
++ const lzo_byte *in;
++ const lzo_byte *in_end;
++ lzo_byte *out;
++
++ lzo_progress_callback_t cb;
++
++ lzo_uint textsize;
++ lzo_uint codesize;
++ lzo_uint printcount;
++
++ unsigned long lit_bytes;
++ unsigned long match_bytes;
++ unsigned long rep_bytes;
++ unsigned long lazy;
++
++ lzo_uint r1_lit;
++ lzo_uint r1_m_len;
++
++ unsigned long m1a_m, m1b_m, m2_m, m3_m, m4_m;
++ unsigned long lit1_r, lit2_r, lit3_r;
++}
++lzo1x_999_t;
++
++#define getbyte(c) ((c).ip < (c).in_end ? *((c).ip)++ : (-1))
++
++/* lzo_swd.ch */
++
++#define SWD_UINT(x) ((swd_uint)(x))
++#define SWD_HSIZE 16384
++#define SWD_MAX_CHAIN 2048
++#define HEAD3(b,p) \
++ (((0x9f5f*(((((lzo_uint32)b[p]<<5)^b[p+1])<<5)^b[p+2]))>>5) & (SWD_HSIZE-1))
++#define HEAD2(b,p) (b[p] ^ ((unsigned)b[p+1]<<8))
++#define NIL2 SWD_UINT_MAX
++
++typedef struct
++{
++ lzo_uint n;
++ lzo_uint f;
++ lzo_uint threshold;
++
++ lzo_uint max_chain;
++ lzo_uint nice_length;
++ lzo_bool use_best_off;
++ lzo_uint lazy_insert;
++
++ lzo_uint m_len;
++ lzo_uint m_off;
++ lzo_uint look;
++ int b_char;
++
++ lzo_uint best_off[SWD_BEST_OFF];
++
++ lzo1x_999_t *c;
++ lzo_uint m_pos;
++
++ lzo_uint best_pos[SWD_BEST_OFF];
++
++ const lzo_byte *dict;
++ const lzo_byte *dict_end;
++ lzo_uint dict_len;
++
++ lzo_uint ip;
++ lzo_uint bp;
++ lzo_uint rp;
++ lzo_uint b_size;
++
++ unsigned char *b_wrap;
++
++ lzo_uint node_count;
++ lzo_uint first_rp;
++
++ unsigned char b[SWD_N + SWD_F + SWD_F];
++ swd_uint head3[SWD_HSIZE];
++ swd_uint succ3[SWD_N + SWD_F];
++ swd_uint best3[SWD_N + SWD_F];
++ swd_uint llen3[SWD_HSIZE];
++
++ swd_uint head2[65536L];
++}
++lzo1x_999_swd_t;
++
++#define s_head3(s,key) s->head3[key]
++#define swd_pos2off(s,pos) \
++ (s->bp > (pos) ? s->bp - (pos) : s->b_size - ((pos) - s->bp))
++
++static __inline__ void
++swd_getbyte (lzo1x_999_swd_t * s)
++{
++ int c;
++
++ if ((c = getbyte (*(s->c))) < 0)
++ {
++ if (s->look > 0)
++ --s->look;
++ }
++ else
++ {
++ s->b[s->ip] = LZO_BYTE (c);
++ if (s->ip < s->f)
++ s->b_wrap[s->ip] = LZO_BYTE (c);
++ }
++ if (++s->ip == s->b_size)
++ s->ip = 0;
++ if (++s->bp == s->b_size)
++ s->bp = 0;
++ if (++s->rp == s->b_size)
++ s->rp = 0;
++}
++
++static void
++swd_initdict (lzo1x_999_swd_t * s, const lzo_byte * dict, lzo_uint dict_len)
++{
++ s->dict = s->dict_end = NULL;
++ s->dict_len = 0;
++
++ if (!dict || dict_len <= 0)
++ return;
++ if (dict_len > s->n)
++ {
++ dict += dict_len - s->n;
++ dict_len = s->n;
++ }
++
++ s->dict = dict;
++ s->dict_len = dict_len;
++ s->dict_end = dict + dict_len;
++ memcpy (s->b, dict, dict_len);
++ s->ip = dict_len;
++}
++
++static void
++swd_insertdict (lzo1x_999_swd_t * s, lzo_uint node, lzo_uint len)
++{
++ lzo_uint key;
++
++ s->node_count = s->n - len;
++ s->first_rp = node;
++
++ while (len-- > 0)
++ {
++ key = HEAD3 (s->b, node);
++ s->succ3[node] = s_head3 (s, key);
++ s->head3[key] = SWD_UINT (node);
++ s->best3[node] = SWD_UINT (s->f + 1);
++ s->llen3[key]++;
++
++ key = HEAD2 (s->b, node);
++ s->head2[key] = SWD_UINT (node);
++
++ node++;
++ }
++}
++
++static int
++swd_init (lzo1x_999_swd_t * s, const lzo_byte * dict, lzo_uint dict_len)
++{
++
++ s->n = SWD_N;
++ s->f = SWD_F;
++ s->threshold = SWD_THRESHOLD;
++
++
++
++ s->max_chain = SWD_MAX_CHAIN;
++ s->nice_length = SWD_F;
++ s->use_best_off = 0;
++ s->lazy_insert = 0;
++
++ s->b_size = s->n + s->f;
++ if (2 * s->f >= s->n || s->b_size + s->f >= NIL2)
++ return LZO_E_ERROR;
++ s->b_wrap = s->b + s->b_size;
++ s->node_count = s->n;
++
++ memset (s->llen3, 0, sizeof (s->llen3[0]) * SWD_HSIZE);
++ memset (s->head2, 0xff, sizeof (s->head2[0]) * 65536L);
++
++ s->ip = 0;
++ swd_initdict (s, dict, dict_len);
++ s->bp = s->ip;
++ s->first_rp = s->ip;
++
++ s->look = (lzo_uint) (s->c->in_end - s->c->ip);
++ if (s->look > 0)
++ {
++ if (s->look > s->f)
++ s->look = s->f;
++ memcpy (&s->b[s->ip], s->c->ip, s->look);
++ s->c->ip += s->look;
++ s->ip += s->look;
++ }
++
++ if (s->ip == s->b_size)
++ s->ip = 0;
++
++ if (s->look >= 2 && s->dict_len > 0)
++ swd_insertdict (s, 0, s->dict_len);
++
++ s->rp = s->first_rp;
++ if (s->rp >= s->node_count)
++ s->rp -= s->node_count;
++ else
++ s->rp += s->b_size - s->node_count;
++
++ return LZO_E_OK;
++}
++
++static __inline__ void
++swd_remove_node (lzo1x_999_swd_t * s, lzo_uint node)
++{
++ if (s->node_count == 0)
++ {
++ lzo_uint key;
++
++ key = HEAD3 (s->b, node);
++
++ --s->llen3[key];
++
++ key = HEAD2 (s->b, node);
++
++ if ((lzo_uint) s->head2[key] == node)
++ s->head2[key] = NIL2;
++ }
++ else
++ --s->node_count;
++}
++
++static void
++swd_accept (lzo1x_999_swd_t * s, lzo_uint n)
++{
++
++ while (n--)
++ {
++ lzo_uint key;
++
++ swd_remove_node (s, s->rp);
++
++ key = HEAD3 (s->b, s->bp);
++ s->succ3[s->bp] = s_head3 (s, key);
++ s->head3[key] = SWD_UINT (s->bp);
++ s->best3[s->bp] = SWD_UINT (s->f + 1);
++ s->llen3[key]++;
++
++ key = HEAD2 (s->b, s->bp);
++ s->head2[key] = SWD_UINT (s->bp);;
++
++ swd_getbyte (s);
++ }
++}
++
++static void
++swd_search (lzo1x_999_swd_t * s, lzo_uint node, lzo_uint cnt)
++{
++ const unsigned char *p1;
++ const unsigned char *p2;
++ const unsigned char *px;
++
++ lzo_uint m_len = s->m_len;
++ const unsigned char *b = s->b;
++ const unsigned char *bp = s->b + s->bp;
++ const unsigned char *bx = s->b + s->bp + s->look;
++ unsigned char scan_end1;
++
++ scan_end1 = bp[m_len - 1];
++ for (; cnt-- > 0; node = s->succ3[node])
++ {
++ p1 = bp;
++ p2 = b + node;
++ px = bx;
++
++ if (p2[m_len - 1] == scan_end1 &&
++ p2[m_len] == p1[m_len] &&
++ p2[0] == p1[0] && p2[1] == p1[1])
++ {
++ lzo_uint i;
++
++ p1 += 2;
++ p2 += 2;
++ do
++ {
++ }
++ while (++p1 < px && *p1 == *++p2);
++
++ i = p1 - bp;
++
++ if (i < SWD_BEST_OFF)
++ {
++ if (s->best_pos[i] == 0)
++ s->best_pos[i] = node + 1;
++ }
++
++ if (i > m_len)
++ {
++ s->m_len = m_len = i;
++ s->m_pos = node;
++ if (m_len == s->look)
++ return;
++ if (m_len >= s->nice_length)
++ return;
++ if (m_len > (lzo_uint) s->best3[node])
++ return;
++ scan_end1 = bp[m_len - 1];
++ }
++ }
++ }
++}
++
++static lzo_bool
++swd_search2 (lzo1x_999_swd_t * s)
++{
++ lzo_uint key;
++
++ key = s->head2[HEAD2 (s->b, s->bp)];
++ if (key == NIL2)
++ return 0;
++
++ if (s->best_pos[2] == 0)
++ s->best_pos[2] = key + 1;
++
++ if (s->m_len < 2)
++ {
++ s->m_len = 2;
++ s->m_pos = key;
++ }
++ return 1;
++}
++
++static void
++swd_findbest (lzo1x_999_swd_t * s)
++{
++ lzo_uint key;
++ lzo_uint cnt, node;
++ lzo_uint len;
++
++ key = HEAD3 (s->b, s->bp);
++ node = s->succ3[s->bp] = s_head3 (s, key);
++ cnt = s->llen3[key]++;
++
++ if (cnt > s->max_chain && s->max_chain > 0)
++ cnt = s->max_chain;
++ s->head3[key] = SWD_UINT (s->bp);
++
++ s->b_char = s->b[s->bp];
++ len = s->m_len;
++ if (s->m_len >= s->look)
++ {
++ if (s->look == 0)
++ s->b_char = -1;
++ s->m_off = 0;
++ s->best3[s->bp] = SWD_UINT (s->f + 1);
++ }
++ else
++ {
++
++ if (swd_search2 (s))
++
++ if (s->look >= 3)
++ swd_search (s, node, cnt);
++ if (s->m_len > len)
++ s->m_off = swd_pos2off (s, s->m_pos);
++ s->best3[s->bp] = SWD_UINT (s->m_len);
++
++ if (s->use_best_off)
++ {
++ int i;
++ for (i = 2; i < SWD_BEST_OFF; i++)
++ if (s->best_pos[i] > 0)
++ s->best_off[i] =
++ swd_pos2off (s,
++ s->best_pos[i] -
++ 1);
++ else
++ s->best_off[i] = 0;
++ }
++
++ }
++
++ swd_remove_node (s, s->rp);
++
++ key = HEAD2 (s->b, s->bp);
++ s->head2[key] = SWD_UINT (s->bp);
++
++}
++
++/* lzo_mchw.ch */
++
++static int
++init_match (lzo1x_999_t * c, lzo1x_999_swd_t * s,
++ const lzo_byte * dict, lzo_uint dict_len, lzo_uint32 flags)
++{
++ int r;
++
++ c->init = 1;
++
++ s->c = c;
++
++ c->last_m_len = c->last_m_off = 0;
++
++ c->textsize = c->codesize = c->printcount = 0;
++ c->lit_bytes = c->match_bytes = c->rep_bytes = 0;
++ c->lazy = 0;
++
++ r = swd_init (s, dict, dict_len);
++ if (r != 0)
++ return r;
++
++ s->use_best_off = (flags & 1) ? 1 : 0;
++ return r;
++}
++
++static int
++find_match (lzo1x_999_t * c, lzo1x_999_swd_t * s,
++ lzo_uint this_len, lzo_uint skip)
++{
++ if (skip > 0)
++ {
++ swd_accept (s, this_len - skip);
++ c->textsize += this_len - skip + 1;
++ }
++ else
++ {
++ c->textsize += this_len - skip;
++ }
++
++ s->m_len = 1;
++ s->m_len = 1;
++
++ if (s->use_best_off)
++ memset (s->best_pos, 0, sizeof (s->best_pos));
++
++ swd_findbest (s);
++ c->m_len = s->m_len;
++ c->m_off = s->m_off;
++
++ swd_getbyte (s);
++
++ if (s->b_char < 0)
++ {
++ c->look = 0;
++ c->m_len = 0;
++ }
++ else
++ {
++ c->look = s->look + 1;
++ }
++ c->bp = c->ip - c->look;
++
++ if (c->cb && c->textsize > c->printcount)
++ {
++ (*c->cb) (c->textsize, c->codesize);
++ c->printcount += 1024;
++ }
++
++ return LZO_E_OK;
++}
++
++/* lzo1x_9x.c */
++
++static lzo_byte *
++code_match (lzo1x_999_t * c, lzo_byte * op, lzo_uint m_len, lzo_uint m_off)
++{
++ lzo_uint x_len = m_len;
++ lzo_uint x_off = m_off;
++
++ c->match_bytes += m_len;
++
++ if (m_len == 2)
++ {
++ m_off -= 1;
++
++ *op++ = LZO_BYTE (M1_MARKER | ((m_off & 3) << 2));
++ *op++ = LZO_BYTE (m_off >> 2);
++
++ c->m1a_m++;
++ }
++
++ else if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
++
++ {
++
++ m_off -= 1;
++ *op++ = LZO_BYTE (((m_len - 1) << 5) | ((m_off & 7) << 2));
++ *op++ = LZO_BYTE (m_off >> 3);
++ c->m2_m++;
++ }
++ else if (m_len == M2_MIN_LEN && m_off <= MX_MAX_OFFSET
++ && c->r1_lit >= 4)
++ {
++ m_off -= 1 + M2_MAX_OFFSET;
++
++ *op++ = LZO_BYTE (M1_MARKER | ((m_off & 3) << 2));
++ *op++ = LZO_BYTE (m_off >> 2);
++
++ c->m1b_m++;
++ }
++ else if (m_off <= M3_MAX_OFFSET)
++ {
++ m_off -= 1;
++ if (m_len <= M3_MAX_LEN)
++ *op++ = LZO_BYTE (M3_MARKER | (m_len - 2));
++ else
++ {
++ m_len -= M3_MAX_LEN;
++ *op++ = M3_MARKER | 0;
++ while (m_len > 255)
++ {
++ m_len -= 255;
++ *op++ = 0;
++ }
++ *op++ = LZO_BYTE (m_len);
++ }
++
++ *op++ = LZO_BYTE (m_off << 2);
++ *op++ = LZO_BYTE (m_off >> 6);
++
++ c->m3_m++;
++ }
++ else
++ {
++ lzo_uint k;
++
++ m_off -= 0x4000;
++ k = (m_off & 0x4000) >> 11;
++ if (m_len <= M4_MAX_LEN)
++ *op++ = LZO_BYTE (M4_MARKER | k | (m_len - 2));
++ else
++ {
++ m_len -= M4_MAX_LEN;
++ *op++ = LZO_BYTE (M4_MARKER | k | 0);
++ while (m_len > 255)
++ {
++ m_len -= 255;
++ *op++ = 0;
++ }
++ *op++ = LZO_BYTE (m_len);
++ }
++
++ *op++ = LZO_BYTE (m_off << 2);
++ *op++ = LZO_BYTE (m_off >> 6);
++
++ c->m4_m++;
++ }
++
++ c->last_m_len = x_len;
++ c->last_m_off = x_off;
++ return op;
++}
++
++static lzo_byte *
++STORE_RUN (lzo1x_999_t * c, lzo_byte * op, const lzo_byte * ii, lzo_uint t)
++{
++ c->lit_bytes += t;
++
++ if (op == c->out && t <= 238)
++ {
++ *op++ = LZO_BYTE (17 + t);
++ }
++ else if (t <= 3)
++ {
++ op[-2] |= LZO_BYTE (t);
++
++ c->lit1_r++;
++ }
++ else if (t <= 18)
++ {
++ *op++ = LZO_BYTE (t - 3);
++ c->lit2_r++;
++ }
++ else
++ {
++ lzo_uint tt = t - 18;
++
++ *op++ = 0;
++ while (tt > 255)
++ {
++ tt -= 255;
++ *op++ = 0;
++ }
++ *op++ = LZO_BYTE (tt);
++ c->lit3_r++;
++ }
++ do
++ *op++ = *ii++;
++ while (--t > 0);
++
++ return op;
++}
++
++static lzo_byte *
++code_run (lzo1x_999_t * c, lzo_byte * op, const lzo_byte * ii,
++ lzo_uint lit, lzo_uint m_len)
++{
++ if (lit > 0)
++ {
++ op = STORE_RUN (c, op, ii, lit);
++ c->r1_m_len = m_len;
++ c->r1_lit = lit;
++ }
++ else
++ {
++ c->r1_m_len = 0;
++ c->r1_lit = 0;
++ }
++
++ return op;
++}
++
++static int
++len_of_coded_match (lzo_uint m_len, lzo_uint m_off, lzo_uint lit)
++{
++ int n = 4;
++
++ if (m_len < 2)
++ return -1;
++ if (m_len == 2)
++ return (m_off <= M1_MAX_OFFSET && lit > 0
++ && lit < 4) ? 2 : -1;
++ if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
++ return 2;
++ if (m_len == M2_MIN_LEN && m_off <= MX_MAX_OFFSET && lit >= 4)
++ return 2;
++ if (m_off <= M3_MAX_OFFSET)
++ {
++ if (m_len <= M3_MAX_LEN)
++ return 3;
++ m_len -= M3_MAX_LEN;
++ while (m_len > 255)
++ {
++ m_len -= 255;
++ n++;
++ }
++ return n;
++ }
++ if (m_off <= M4_MAX_OFFSET)
++ {
++ if (m_len <= M4_MAX_LEN)
++ return 3;
++ m_len -= M4_MAX_LEN;
++ while (m_len > 255)
++ {
++ m_len -= 255;
++ n++;
++ }
++ return n;
++ }
++ return -1;
++}
++
++static lzo_int
++min_gain (lzo_uint ahead, lzo_uint lit1, lzo_uint lit2, int l1, int l2,
++ int l3)
++{
++ lzo_int lazy_match_min_gain = 0;
++
++ lazy_match_min_gain += ahead;
++
++ if (lit1 <= 3)
++ lazy_match_min_gain += (lit2 <= 3) ? 0 : 2;
++ else if (lit1 <= 18)
++ lazy_match_min_gain += (lit2 <= 18) ? 0 : 1;
++
++ lazy_match_min_gain += (l2 - l1) * 2;
++ if (l3 > 0)
++ lazy_match_min_gain -= (ahead - l3) * 2;
++
++ if (lazy_match_min_gain < 0)
++ lazy_match_min_gain = 0;
++
++ return lazy_match_min_gain;
++}
++
++static void
++better_match (const lzo1x_999_swd_t * swd, lzo_uint * m_len, lzo_uint * m_off)
++{
++ if (*m_len <= M2_MIN_LEN)
++ return;
++
++ if (*m_off <= M2_MAX_OFFSET)
++ return;
++
++ if (*m_off > M2_MAX_OFFSET &&
++ *m_len >= M2_MIN_LEN + 1 && *m_len <= M2_MAX_LEN + 1 &&
++ swd->best_off[*m_len - 1]
++ && swd->best_off[*m_len - 1] <= M2_MAX_OFFSET)
++ {
++ *m_len = *m_len - 1;
++ *m_off = swd->best_off[*m_len];
++ return;
++ }
++
++ if (*m_off > M3_MAX_OFFSET &&
++ *m_len >= M4_MAX_LEN + 1 && *m_len <= M2_MAX_LEN + 2 &&
++ swd->best_off[*m_len - 2]
++ && swd->best_off[*m_len - 2] <= M2_MAX_OFFSET)
++ {
++ *m_len = *m_len - 2;
++ *m_off = swd->best_off[*m_len];
++ return;
++ }
++
++ if (*m_off > M3_MAX_OFFSET &&
++ *m_len >= M4_MAX_LEN + 1 && *m_len <= M3_MAX_LEN + 1 &&
++ swd->best_off[*m_len - 1]
++ && swd->best_off[*m_len - 1] <= M3_MAX_OFFSET)
++ {
++ *m_len = *m_len - 1;
++ *m_off = swd->best_off[*m_len];
++ }
++
++}
++
++/* minilzo.c */
++
++static lzo_bool
++lzo_assert (int expr)
++{
++ return (expr) ? 1 : 0;
++}
++
++/* lzo1x_9x.c */
++
++static int
++lzo1x_999_compress_internal (const lzo_byte * in, lzo_uint in_len,
++ lzo_byte * out, lzo_uintp out_len,
++ lzo_voidp wrkmem,
++ const lzo_byte * dict, lzo_uint dict_len,
++ lzo_progress_callback_t cb,
++ int try_lazy,
++ lzo_uint good_length,
++ lzo_uint max_lazy,
++ lzo_uint nice_length,
++ lzo_uint max_chain, lzo_uint32 flags)
++{
++ lzo_byte *op;
++ const lzo_byte *ii;
++ lzo_uint lit;
++ lzo_uint m_len, m_off;
++ lzo1x_999_t cc;
++ lzo1x_999_t *const c = &cc;
++ lzo1x_999_swd_t *const swd = (lzo1x_999_swd_t *) wrkmem;
++ int r;
++
++ if (!lzo_assert
++ (LZO1X_999_MEM_COMPRESS >= lzo_sizeof (lzo1x_999_swd_t)))
++ return LZO_E_ERROR;
++
++ if (try_lazy < 0)
++ try_lazy = 1;
++
++ if (good_length <= 0)
++ good_length = 32;
++
++ if (max_lazy <= 0)
++ max_lazy = 32;
++
++ if (nice_length <= 0)
++ nice_length = 0;
++
++ if (max_chain <= 0)
++ max_chain = SWD_MAX_CHAIN;
++
++ c->init = 0;
++ c->ip = c->in = in;
++ c->in_end = in + in_len;
++ c->out = out;
++ c->cb = cb;
++ c->m1a_m = c->m1b_m = c->m2_m = c->m3_m = c->m4_m = 0;
++ c->lit1_r = c->lit2_r = c->lit3_r = 0;
++
++ op = out;
++ ii = c->ip;
++ lit = 0;
++ c->r1_lit = c->r1_m_len = 0;
++
++ r = init_match (c, swd, dict, dict_len, flags);
++ if (r != 0)
++ return r;
++ if (max_chain > 0)
++ swd->max_chain = max_chain;
++ if (nice_length > 0)
++ swd->nice_length = nice_length;
++
++ r = find_match (c, swd, 0, 0);
++ if (r != 0)
++ return r;
++ while (c->look > 0)
++ {
++ lzo_uint ahead;
++ lzo_uint max_ahead;
++ int l1, l2, l3;
++
++ c->codesize = op - out;
++
++ m_len = c->m_len;
++ m_off = c->m_off;
++
++ if (lit == 0)
++ ii = c->bp;
++
++ if (m_len < 2 ||
++ (m_len == 2
++ && (m_off > M1_MAX_OFFSET || lit == 0 || lit >= 4))
++ || (m_len == 2 && op == out) || (op == out && lit == 0))
++ {
++
++ m_len = 0;
++ }
++ else if (m_len == M2_MIN_LEN)
++ {
++
++ if (m_off > MX_MAX_OFFSET && lit >= 4)
++ m_len = 0;
++ }
++
++ if (m_len == 0)
++ {
++
++ lit++;
++ swd->max_chain = max_chain;
++ r = find_match (c, swd, 1, 0);
++ continue;
++ }
++
++ if (swd->use_best_off)
++ better_match (swd, &m_len, &m_off);
++
++ ahead = 0;
++ if (try_lazy <= 0 || m_len >= max_lazy)
++ {
++
++ l1 = 0;
++ max_ahead = 0;
++ }
++ else
++ {
++
++ l1 = len_of_coded_match (m_len, m_off, lit);
++
++ max_ahead = LZO_MIN (try_lazy, l1 - 1);
++
++ }
++
++ while (ahead < max_ahead && c->look > m_len)
++ {
++ lzo_int lazy_match_min_gain;
++
++ if (m_len >= good_length)
++ swd->max_chain = max_chain >> 2;
++ else
++ swd->max_chain = max_chain;
++ r = find_match (c, swd, 1, 0);
++ ahead++;
++
++ if (c->m_len < m_len)
++ continue;
++
++ if (c->m_len == m_len && c->m_off >= m_off)
++ continue;
++
++ if (swd->use_best_off)
++ better_match (swd, &c->m_len, &c->m_off);
++
++ l2 = len_of_coded_match (c->m_len, c->m_off,
++ lit + ahead);
++ if (l2 < 0)
++ continue;
++
++ l3 = (op == out) ? -1 : len_of_coded_match (ahead,
++ m_off,
++ lit);
++
++ lazy_match_min_gain =
++ min_gain (ahead, lit, lit + ahead, l1, l2,
++ l3);
++ if (c->m_len >= m_len + lazy_match_min_gain)
++ {
++ c->lazy++;
++
++ if (l3 > 0)
++ {
++
++ op = code_run (c, op, ii, lit, ahead);
++ lit = 0;
++
++ op = code_match (c, op, ahead, m_off);
++ }
++ else
++ {
++ lit += ahead;
++ }
++ goto lazy_match_done;
++ }
++ }
++
++ op = code_run (c, op, ii, lit, m_len);
++ lit = 0;
++
++ op = code_match (c, op, m_len, m_off);
++ swd->max_chain = max_chain;
++ r = find_match (c, swd, m_len, 1 + ahead);
++
++ lazy_match_done:;
++ }
++
++ if (lit > 0)
++ op = STORE_RUN (c, op, ii, lit);
++
++ *op++ = M4_MARKER | 1;
++ *op++ = 0;
++ *op++ = 0;
++
++ c->codesize = op - out;
++
++ *out_len = op - out;
++
++ if (c->cb)
++ (*c->cb) (c->textsize, c->codesize);
++
++ return LZO_E_OK;
++}
++
++static int
++lzo1x_999_compress_level (const lzo_byte * in, lzo_uint in_len,
++ lzo_byte * out, lzo_uintp out_len,
++ lzo_voidp wrkmem,
++ const lzo_byte * dict, lzo_uint dict_len,
++ lzo_progress_callback_t cb, int compression_level)
++{
++ static const struct
++ {
++ int try_lazy;
++ lzo_uint good_length;
++ lzo_uint max_lazy;
++ lzo_uint nice_length;
++ lzo_uint max_chain;
++ lzo_uint32 flags;
++ } c[9] =
++ {
++ {
++ 0, 0, 0, 8, 4, 0},
++ {
++ 0, 0, 0, 16, 8, 0},
++ {
++ 0, 0, 0, 32, 16, 0},
++ {
++ 1, 4, 4, 16, 16, 0},
++ {
++ 1, 8, 16, 32, 32, 0},
++ {
++ 1, 8, 16, 128, 128, 0},
++ {
++ 2, 8, 32, 128, 256, 0},
++ {
++ 2, 32, 128, F, 2048, 1},
++ {
++ 2, F, F, F, 4096, 1}
++ };
++
++ if (compression_level < 1 || compression_level > 9)
++ return LZO_E_ERROR;
++
++ compression_level -= 1;
++ return lzo1x_999_compress_internal (in, in_len, out, out_len, wrkmem,
++ dict, dict_len, cb,
++ c[compression_level].try_lazy,
++ c[compression_level].good_length,
++ c[compression_level].max_lazy,
++ 0,
++ c[compression_level].max_chain,
++ c[compression_level].flags);
++}
++
++static int
++lzo1x_999_compress (const lzo_byte * in, lzo_uint in_len,
++ lzo_byte * out, lzo_uintp out_len, lzo_voidp wrkmem)
++{
++ return lzo1x_999_compress_level (in, in_len, out, out_len, wrkmem,
++ NULL, 0, 0, 8);
++}
++
++/* minilzo.c */
++
++static const lzo_byte __lzo_copyright[] = LZO_VERSION_STRING;
++
++static lzo_uint
++_lzo1x_1_do_compress (const lzo_byte * in, lzo_uint in_len,
++ lzo_byte * out, lzo_uintp out_len, lzo_voidp wrkmem)
++{
++
++ register const lzo_byte *ip;
++
++ lzo_byte *op;
++ const lzo_byte *const in_end = in + in_len;
++ const lzo_byte *const ip_end = in + in_len - 8 - 5;
++ const lzo_byte *ii;
++ lzo_dict_p const dict = (lzo_dict_p) wrkmem;
++
++ op = out;
++ ip = in;
++ ii = ip;
++
++ ip += 4;
++ for (;;)
++ {
++ register const lzo_byte *m_pos;
++
++ lzo_uint m_off;
++ lzo_uint m_len;
++ lzo_uint dindex;
++
++ DINDEX1 (dindex, ip);
++ GINDEX (m_pos, m_off, dict, dindex, in);
++ if (LZO_CHECK_MPOS_NON_DET
++ (m_pos, m_off, in, ip, M4_MAX_OFFSET))
++ goto literal;
++
++ if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
++ goto try_match;
++ DINDEX2 (dindex, ip);
++ GINDEX (m_pos, m_off, dict, dindex, in);
++
++ if (LZO_CHECK_MPOS_NON_DET
++ (m_pos, m_off, in, ip, M4_MAX_OFFSET))
++ goto literal;
++ if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
++ goto try_match;
++ goto literal;
++
++ try_match:
++ if (m_pos[0] != ip[0] || m_pos[1] != ip[1])
++ {
++ }
++ else
++ {
++ if (m_pos[2] == ip[2])
++ {
++ goto match;
++ }
++ else
++ {
++ }
++ }
++
++ literal:
++ UPDATE_I (dict, 0, dindex, ip, in);
++ ++ip;
++ if (ip >= ip_end)
++ break;
++ continue;
++
++ match:
++ UPDATE_I (dict, 0, dindex, ip, in);
++
++ if (pd (ip, ii) > 0)
++ {
++ register lzo_uint t = pd (ip, ii);
++
++ if (t <= 3)
++ {
++ op[-2] |= LZO_BYTE (t);
++ }
++ else if (t <= 18)
++ *op++ = LZO_BYTE (t - 3);
++ else
++ {
++ register lzo_uint tt = t - 18;
++
++ *op++ = 0;
++ while (tt > 255)
++ {
++ tt -= 255;
++ *op++ = 0;
++ }
++ *op++ = LZO_BYTE (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++ = LZO_BYTE (((m_len -
++ 1) << 5) | ((m_off & 7) <<
++ 2));
++ *op++ = LZO_BYTE (m_off >> 3);
++ }
++ else if (m_off <= M3_MAX_OFFSET)
++ {
++ m_off -= 1;
++ *op++ = LZO_BYTE (M3_MARKER | (m_len - 2));
++ goto m3_m4_offset;
++ }
++ else
++
++ {
++ m_off -= 0x4000;
++
++ *op++ = LZO_BYTE (M4_MARKER |
++ ((m_off & 0x4000) >> 11) |
++ (m_len - 2));
++ goto m3_m4_offset;
++ }
++ }
++ else
++ {
++ {
++ const lzo_byte *end = in_end;
++ const lzo_byte *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++ = LZO_BYTE (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++ = LZO_BYTE (M4_MARKER |
++ ((m_off & 0x4000) >>
++ 11) | (m_len - 2));
++
++ else
++ {
++ m_len -= M4_MAX_LEN;
++ *op++ = LZO_BYTE (M4_MARKER |
++ ((m_off & 0x4000) >>
++ 11));
++ m3_m4_len:
++ while (m_len > 255)
++ {
++ m_len -= 255;
++ *op++ = 0;
++ }
++
++ *op++ = LZO_BYTE (m_len);
++ }
++ }
++
++ m3_m4_offset:
++ *op++ = LZO_BYTE ((m_off & 63) << 2);
++ *op++ = LZO_BYTE (m_off >> 6);
++ }
++ ii = ip;
++ if (ip >= ip_end)
++ break;
++ }
++
++ *out_len = op - out;
++ return pd (in_end, ii);
++}
++
++static int
++lzo1x_1_compress (const lzo_byte * in, lzo_uint in_len,
++ lzo_byte * out, lzo_uintp out_len, lzo_voidp wrkmem)
++{
++ lzo_byte *op = out;
++ lzo_uint t;
++
++ if (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)
++ {
++ const lzo_byte *ii = in + in_len - t;
++
++ if (op == out && t <= 238)
++ *op++ = LZO_BYTE (17 + t);
++ else if (t <= 3)
++ op[-2] |= LZO_BYTE (t);
++ else if (t <= 18)
++ *op++ = LZO_BYTE (t - 3);
++ else
++ {
++ lzo_uint tt = t - 18;
++
++ *op++ = 0;
++ while (tt > 255)
++ {
++ tt -= 255;
++ *op++ = 0;
++ }
++
++ *op++ = LZO_BYTE (tt);
++ }
++ do
++ *op++ = *ii++;
++ while (--t > 0);
++ }
++
++ *op++ = M4_MARKER | 1;
++ *op++ = 0;
++ *op++ = 0;
++
++ *out_len = op - out;
++ return 0;
++}
++
++static int
++lzo1x_decompress (const lzo_byte * in, lzo_uint in_len,
++ lzo_byte * out, lzo_uintp out_len, lzo_voidp wrkmem)
++{
++ register lzo_byte *op;
++ register const lzo_byte *ip;
++ register lzo_uint t;
++
++ register const lzo_byte *m_pos;
++
++ const lzo_byte *const ip_end = in + in_len;
++ lzo_byte *const op_end = out + *out_len;
++
++ *out_len = 0;
++
++ op = out;
++ ip = in;
++
++ if (*ip > 17)
++ {
++ t = *ip++ - 17;
++ if (t < 4)
++ goto match_next;
++ NEED_OP (t);
++ NEED_IP (t + 1);
++ do
++ *op++ = *ip++;
++ while (--t > 0);
++ goto first_literal_run;
++ }
++
++ while (TEST_IP && TEST_OP)
++ {
++ t = *ip++;
++ if (t >= 16)
++ goto match;
++ if (t == 0)
++ {
++ NEED_IP (1);
++ while (*ip == 0)
++ {
++ t += 255;
++ ip++;
++ NEED_IP (1);
++ }
++ t += 15 + *ip++;
++ }
++ NEED_OP (t + 3);
++ NEED_IP (t + 4);
++ if (PTR_ALIGNED2_4 (op, ip))
++ {
++ 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);
++ }
++ }
++ else
++ {
++ *op++ = *ip++;
++ *op++ = *ip++;
++ *op++ = *ip++;
++ 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;
++ TEST_LOOKBEHIND (m_pos, out);
++ NEED_OP (3);
++ *op++ = *m_pos++;
++ *op++ = *m_pos++;
++ *op++ = *m_pos;
++
++ goto match_done;
++
++ while (TEST_IP && TEST_OP)
++ {
++ match:
++ if (t >= 64)
++ {
++ m_pos = op - 1;
++ m_pos -= (t >> 2) & 7;
++ m_pos -= *ip++ << 3;
++ t = (t >> 5) - 1;
++ TEST_LOOKBEHIND (m_pos, out);
++ NEED_OP (t + 3 - 1);
++ goto copy_match;
++
++ }
++ else if (t >= 32)
++ {
++ t &= 31;
++ if (t == 0)
++ {
++ NEED_IP (1);
++ while (*ip == 0)
++ {
++ t += 255;
++ ip++;
++ NEED_IP (1);
++ }
++ t += 31 + *ip++;
++ }
++
++ m_pos = op - 1;
++ m_pos -= (ip[0] >> 2) + (ip[1] << 6);
++
++ ip += 2;
++ }
++ else if (t >= 16)
++ {
++ m_pos = op;
++ m_pos -= (t & 8) << 11;
++
++ t &= 7;
++ if (t == 0)
++ {
++ NEED_IP (1);
++ while (*ip == 0)
++ {
++ t += 255;
++ ip++;
++ NEED_IP (1);
++ }
++ t += 7 + *ip++;
++ }
++
++ m_pos -= (ip[0] >> 2) + (ip[1] << 6);
++
++ 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;
++ TEST_LOOKBEHIND (m_pos, out);
++ NEED_OP (2);
++ *op++ = *m_pos++;
++ *op++ = *m_pos;
++
++ goto match_done;
++ }
++
++ TEST_LOOKBEHIND (m_pos, out);
++ NEED_OP (t + 3 - 1);
++ if (t >= 2 * 4 - (3 - 1)
++ && PTR_ALIGNED2_4 (op, m_pos))
++ {
++ 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:
++ NEED_OP (t);
++ NEED_IP (t + 1);
++ do
++ *op++ = *ip++;
++ while (--t > 0);
++ t = *ip++;
++ }
++ }
++ *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;
++}
++
++/* lzo1x_oo.ch */
++
++#define NO_LIT LZO_UINT_MAX
++
++static void
++copy2 (lzo_byte * ip, const lzo_byte * m_pos, lzo_ptrdiff_t off)
++{
++ ip[0] = m_pos[0];
++ if (off == 1)
++ ip[1] = m_pos[0];
++ else
++ ip[1] = m_pos[1];
++}
++
++static void
++copy3 (lzo_byte * ip, const lzo_byte * m_pos, lzo_ptrdiff_t off)
++{
++ ip[0] = m_pos[0];
++ if (off == 1)
++ {
++ ip[2] = ip[1] = m_pos[0];
++ }
++ else if (off == 2)
++ {
++ ip[1] = m_pos[1];
++ ip[2] = m_pos[0];
++ }
++ else
++ {
++ ip[1] = m_pos[1];
++ ip[2] = m_pos[2];
++ }
++}
++
++static int
++lzo1x_optimize (lzo_byte * in, lzo_uint in_len,
++ lzo_byte * out, lzo_uintp out_len, lzo_voidp wrkmem)
++{
++ register lzo_byte *op;
++ register lzo_byte *ip;
++ register lzo_uint t;
++ register lzo_byte *m_pos;
++ lzo_uint nl;
++ const lzo_byte *const ip_end = in + in_len;
++ const lzo_byte *const op_end = out + *out_len;
++ lzo_byte *litp = NULL;
++ lzo_uint lit = 0;
++ lzo_uint next_lit = NO_LIT;
++ long o_m1_a = 0, o_m1_b = 0, o_m2 = 0, o_m3_a = 0, o_m3_b = 0;
++
++ *out_len = 0;
++
++ op = out;
++ ip = in;
++
++ if (*ip > 17)
++ {
++ t = *ip++ - 17;
++ if (t < 4)
++ goto match_next;
++ goto first_literal_run;
++ }
++
++ while (TEST_IP && TEST_OP)
++ {
++ t = *ip++;
++ if (t >= 16)
++ goto match;
++ litp = ip - 1;
++ if (t == 0)
++ {
++ t = 15;
++ while (*ip == 0)
++ t += 255, ip++;
++ t += *ip++;
++ }
++ lit = t + 3;
++ copy_literal_run:
++ *op++ = *ip++;
++ *op++ = *ip++;
++ *op++ = *ip++;
++ first_literal_run:
++ do
++ *op++ = *ip++;
++ while (--t > 0);
++
++ t = *ip++;
++
++ if (t >= 16)
++ goto match;
++ m_pos = op - 1 - 0x800;
++ m_pos -= t >> 2;
++ m_pos -= *ip++ << 2;
++ *op++ = *m_pos++;
++ *op++ = *m_pos++;
++ *op++ = *m_pos++;
++ lit = 0;
++ goto match_done;
++
++ while (TEST_IP && TEST_OP)
++ {
++ if (t < 16)
++ {
++ m_pos = op - 1;
++ m_pos -= t >> 2;
++ m_pos -= *ip++ << 2;
++
++ if (litp == NULL)
++ goto copy_m1;
++
++ nl = ip[-2] & 3;
++ if (nl == 0 && lit == 1 && ip[0] >= 16)
++ {
++ next_lit = nl;
++ lit += 2;
++ *litp = LZO_BYTE ((*litp & ~3) | lit);
++ copy2 (ip - 2, m_pos, op - m_pos);
++ o_m1_a++;
++ }
++ else if (nl == 0 && ip[0] < 16 && ip[0] != 0
++ && (lit + 2 + ip[0] < 16))
++ {
++ t = *ip++;
++ *litp &= ~3;
++ copy2 (ip - 3 + 1, m_pos, op - m_pos);
++ litp += 2;
++ if (lit > 0)
++ memmove (litp + 1, litp, lit);
++ lit += 2 + t + 3;
++ *litp = LZO_BYTE (lit - 3);
++
++ o_m1_b++;
++ *op++ = *m_pos++;
++ *op++ = *m_pos++;
++ goto copy_literal_run;
++ }
++ copy_m1:
++ *op++ = *m_pos++;
++ *op++ = *m_pos++;
++ }
++ else
++ {
++ match:
++ if (t >= 64)
++ {
++ m_pos = op - 1;
++ m_pos -= (t >> 2) & 7;
++ m_pos -= *ip++ << 3;
++ t = (t >> 5) - 1;
++ if (litp == NULL)
++ goto copy_m;
++
++ nl = ip[-2] & 3;
++ if (t == 1 && lit > 3 && nl == 0 &&
++ ip[0] < 16 && ip[0] != 0
++ && (lit + 3 + ip[0] < 16))
++ {
++ t = *ip++;
++ copy3 (ip - 1 - 2, m_pos,
++ op - m_pos);
++ lit += 3 + t + 3;
++ *litp = LZO_BYTE (lit - 3);
++ o_m2++;
++ *op++ = *m_pos++;
++ *op++ = *m_pos++;
++ *op++ = *m_pos++;
++ goto copy_literal_run;
++ }
++ }
++ else
++ {
++ if (t >= 32)
++ {
++ t &= 31;
++ if (t == 0)
++ {
++ t = 31;
++ while (*ip == 0)
++ t += 255,
++ ip++;
++ t += *ip++;
++ }
++ m_pos = op - 1;
++ m_pos -= *ip++ >> 2;
++ m_pos -= *ip++ << 6;
++ }
++ else
++ {
++ m_pos = op;
++ m_pos -= (t & 8) << 11;
++ t &= 7;
++ if (t == 0)
++ {
++ t = 7;
++ while (*ip == 0)
++ t += 255,
++ ip++;
++ t += *ip++;
++ }
++ m_pos -= *ip++ >> 2;
++ m_pos -= *ip++ << 6;
++ if (m_pos == op)
++ goto eof_found;
++ m_pos -= 0x4000;
++ }
++ if (litp == NULL)
++ goto copy_m;
++
++ nl = ip[-2] & 3;
++ if (t == 1 && lit == 0 && nl == 0
++ && ip[0] >= 16)
++ {
++ next_lit = nl;
++ lit += 3;
++ *litp = LZO_BYTE ((*litp & ~3)
++ | lit);
++ copy3 (ip - 3, m_pos,
++ op - m_pos);
++ o_m3_a++;
++ }
++ else if (t == 1 && lit <= 3 && nl == 0
++ && ip[0] < 16 && ip[0] != 0
++ && (lit + 3 + ip[0] < 16))
++ {
++ t = *ip++;
++ *litp &= ~3;
++ copy3 (ip - 4 + 1, m_pos,
++ op - m_pos);
++ litp += 2;
++ if (lit > 0)
++ memmove (litp + 1,
++ litp, lit);
++ lit += 3 + t + 3;
++ *litp = LZO_BYTE (lit - 3);
++
++ o_m3_b++;
++ *op++ = *m_pos++;
++ *op++ = *m_pos++;
++ *op++ = *m_pos++;
++ goto copy_literal_run;
++ }
++ }
++ copy_m:
++ *op++ = *m_pos++;
++ *op++ = *m_pos++;
++ do
++ *op++ = *m_pos++;
++ while (--t > 0);
++ }
++
++ match_done:
++ if (next_lit == NO_LIT)
++ {
++ t = ip[-2] & 3;
++ lit = t;
++ litp = ip - 2;
++ }
++ else
++ t = next_lit;
++ next_lit = NO_LIT;
++ if (t == 0)
++ break;
++ match_next:
++ do
++ *op++ = *ip++;
++ while (--t > 0);
++ t = *ip++;
++ }
++ }
++
++ *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));
++}
++
++/* interface to jffs2 bbc follows */
++
++#include "jffs2_bbc_framework.h"
++
++#define BLOCKSIZE 4096
++#define OUTBLOCKSIZE (BLOCKSIZE + BLOCKSIZE / 64 + 16 + 3)
++
++#define JFFS2_BBC_LZO_BLOCK_SIGN {0x3f, 0x47, 0x5a, 0x18}
++
++static int
++jffs2_bbc_lzo_compressor_init (void);
++
++static void
++jffs2_bbc_lzo_compressor_deinit (void);
++
++static int
++jffs2_bbc_lzo_compress (void *model, unsigned char *input,
++ unsigned char *output, unsigned long *sourcelen,
++ unsigned long *dstlen);
++
++static int
++jffs2_bbc_lzo_estimate (void *model, unsigned char *input,
++ unsigned long sourcelen, unsigned long *dstlen,
++ unsigned long *readtime, unsigned long *writetime);
++
++static int
++jffs2_bbc_lzo_decompress (void *model, unsigned char *input,
++ unsigned char *output, unsigned long sourcelen,
++ unsigned long dstlen);
++
++static char *
++jffs2_bbc_lzo_proc_info (void);
++
++static int
++jffs2_bbc_lzo_proc_command (char *command);
++
++struct jffs2_bbc_compressor_type jffs2_bbc_lzo = {
++ "lzo",
++ 0,
++ JFFS2_BBC_LZO_BLOCK_SIGN,
++ jffs2_bbc_lzo_compressor_init,
++ NULL,
++ NULL,
++ jffs2_bbc_lzo_compressor_deinit,
++ jffs2_bbc_lzo_compress,
++ jffs2_bbc_lzo_estimate,
++ jffs2_bbc_lzo_decompress,
++ jffs2_bbc_lzo_proc_info,
++ jffs2_bbc_lzo_proc_command
++};
++
++static int
++no_lzo1x_optimize (lzo_byte * src, lzo_uint src_len,
++ lzo_byte * dst, lzo_uintp dst_len, lzo_voidp wrkmem)
++{
++ return 0;
++}
++
++#ifdef __KERNEL__
++static lzo_compress_t lzo1x_compressor = lzo1x_1_compress;
++static lzo_optimize_t lzo1x_optimizer = no_lzo1x_optimize;
++static int lzo1x_compressor_type = 1;
++static int lzo1x_optimize_type = 0;
++static unsigned long lzo1x_compressor_memsize = LZO1X_1_MEM_COMPRESS;
++#else
++static lzo_compress_t lzo1x_compressor = lzo1x_999_compress;
++static lzo_optimize_t lzo1x_optimizer = lzo1x_optimize;
++static int lzo1x_compressor_type = 999;
++static int lzo1x_optimize_type = 1;
++static unsigned long lzo1x_compressor_memsize = LZO1X_999_MEM_COMPRESS;
++#endif
++
++static lzo_bytep wrkmem = NULL; /* temporary buffer for compression, used by lzo */
++static lzo_bytep cmprssmem = NULL; /* temporary buffer for compression, used by interface */
++
++static int
++jffs2_bbc_lzo_compressor_init (void)
++{
++ wrkmem = (lzo_bytep) jffs2_bbc_malloc (lzo1x_compressor_memsize);
++ cmprssmem = (lzo_bytep) jffs2_bbc_malloc (OUTBLOCKSIZE);
++ return !(wrkmem && cmprssmem);
++}
++
++static void
++jffs2_bbc_lzo_compressor_deinit (void)
++{
++ jffs2_bbc_free (wrkmem);
++ jffs2_bbc_free (cmprssmem);
++}
++
++static int
++jffs2_bbc_lzo_compress (void *model, unsigned char *input,
++ unsigned char *output, unsigned long *sourcelen,
++ unsigned long *dstlen)
++{
++ lzo_uint csize = OUTBLOCKSIZE;
++ lzo_uint isize = *sourcelen;
++ int retval;
++ if ((retval =
++ lzo1x_compressor (input, *sourcelen, cmprssmem, &csize,
++ wrkmem)) != LZO_E_OK)
++ {
++ *sourcelen = *dstlen = 0;
++ return retval;
++ }
++ else
++ {
++ retval = lzo1x_optimizer (cmprssmem, csize, input, &isize,
++ NULL);
++ csize += 2;
++ if (csize <= *dstlen) {
++ *dstlen = csize;
++ *(output++) = jffs2_bbc_lzo.block_sign[0];
++ *(output++) = jffs2_bbc_lzo.block_sign[1];
++ memcpy (output, cmprssmem, csize - 2);
++ return retval;
++ } else {
++ *sourcelen = *dstlen = 0;
++ return -1;
++ }
++ }
++}
++
++static int
++jffs2_bbc_lzo_estimate (void *model, unsigned char *input,
++ unsigned long sourcelen, unsigned long *dstlen,
++ unsigned long *readtime, unsigned long *writetime)
++{
++ *dstlen = sourcelen * 55 / 100;
++ *readtime = JFFS2_BBC_ZLIB_READ_TIME / 2;
++ *writetime = JFFS2_BBC_ZLIB_WRITE_TIME * 8 / 10; /* LZO1X-1 is much-much faster,
++ but LZO1X-999 is slow. The default mode for inside kernel compression is LZO1X-1
++ This should be *0.4 really */
++ return 0;
++}
++
++static int
++jffs2_bbc_lzo_decompress (void *model, unsigned char *input,
++ unsigned char *output, unsigned long sourcelen,
++ unsigned long dstlen)
++{
++ lzo_uint outlen = dstlen;
++ if ( ( *(input++) != (unsigned char)jffs2_bbc_lzo.block_sign[0] ) ||
++ ( *(input++) != (unsigned char)jffs2_bbc_lzo.block_sign[1] )
++ ) {
++ return -1;
++ } else {
++ return lzo1x_decompress (input, sourcelen - 2, output, &outlen, NULL);
++ }
++}
++
++static char *
++jffs2_bbc_lzo_proc_info (void)
++{
++ if (lzo1x_compressor_type == 1)
++ {
++ if (lzo1x_optimize_type == 1)
++ {
++ return "LZO1X-1 compression with optimization";
++ }
++ else
++ {
++ return "LZO1X-1 compression without optimization";
++ }
++ }
++ else if (lzo1x_compressor_type == 999)
++ {
++ if (lzo1x_optimize_type == 1)
++ {
++ return "LZO1X-999 compression with optimization";
++ }
++ else
++ {
++ return "LZO1X-999 compression without optimization";
++ }
++ }
++ else
++ {
++ return "Unknown configuration!";
++ }
++}
++
++static int
++jffs2_bbc_lzo_proc_command (char *command)
++{
++ switch (*command)
++ {
++ case 'o':
++ /* switch optimization off */
++ lzo1x_optimizer = no_lzo1x_optimize;
++ lzo1x_optimize_type = 0;
++ jffs2_bbc_print1 ("Compression optimization switched off.\n");
++ return 0;
++ case 'O':
++ /* switch optimization on */
++ lzo1x_optimizer = lzo1x_optimize;
++ lzo1x_optimize_type = 1;
++ jffs2_bbc_print1 ("Compression optimization switched on.\n");
++ return 0;
++ case '1':
++ /* switch compression to LZO1X-1 */
++ jffs2_bbc_free (wrkmem);
++ lzo1x_compressor_type = 1;
++ lzo1x_compressor = lzo1x_1_compress;
++ lzo1x_compressor_memsize = LZO1X_1_MEM_COMPRESS;
++ wrkmem = (lzo_bytep)
++ jffs2_bbc_malloc (lzo1x_compressor_memsize);
++ jffs2_bbc_print1 ("Compression type switched to LZO1X-1.\n");
++ return 0;
++ case '9':
++ /* switch compression to LZO1X-999 */
++ jffs2_bbc_free (wrkmem);
++ lzo1x_compressor_type = 999;
++ lzo1x_compressor = lzo1x_999_compress;
++ lzo1x_compressor_memsize = LZO1X_999_MEM_COMPRESS;
++ wrkmem = (lzo_bytep)
++ jffs2_bbc_malloc (lzo1x_compressor_memsize);
++ jffs2_bbc_print1
++ ("Compression type switched to LZO1X-999.\n");
++ return 0;
++ default:
++ jffs2_bbc_print1 ("Unknown command!\n");
++ return 0;
++ }
++}
++
++
++struct jffs2_bbc_compressor_type *
++jffs2_bbc_lzo_init (int mode)
++{
++ if (jffs2_bbc_register_compressor (&jffs2_bbc_lzo) == 0)
++ {
++ return &jffs2_bbc_lzo;
++ }
++ else
++ {
++ return NULL;
++ }
++}
++
++void
++jffs2_bbc_lzo_deinit (void)
++{
++ jffs2_bbc_unregister_compressor (&jffs2_bbc_lzo);
++}
+diff -Nur linux-mips-cvs/fs/jffs2/jffs2_bbc_lzss_comp.c linux-mips/fs/jffs2/jffs2_bbc_lzss_comp.c
+--- linux-mips-cvs/fs/jffs2/jffs2_bbc_lzss_comp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips/fs/jffs2/jffs2_bbc_lzss_comp.c 2005-02-07 05:08:34.000000000 +0100
+@@ -0,0 +1,385 @@
++/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
++
++/*
++ jffs2_bbc_lzss_comp.c -- Lempel-Ziv-Storer-Szymanski compression module for jffs2
++ Copyright (C) 2004 Patrik Kluba
++ Based on the LZSS source included in LDS (lossless datacompression sources)
++ Block-compression modifications by Patrik Kluba
++ $Header: /openwrt/openwrt/package/linux/kernel-patches/301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
++*/
++
++/*
++Original copyright follows:
++
++**************************************************************
++ LZSS.C -- A Data Compression Program
++**************************************************************
++ 4/6/1989 Haruhiko Okumura
++ Use, distribute, and modify this program freely.
++ Please send me your improved versions.
++ PC-VAN SCIENCE
++ NIFTY-Serve PAF01022
++ CompuServe 74050,1022
++**************************************************************
++
++*/
++
++/*
++
++ 2004-02-16 pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
++ Initial release
++
++*/
++
++/* lzss.c */
++
++#define N 4096 /* size of ring buffer */
++#define F 18 /* upper limit for match_length */
++#define THRESHOLD 2 /* encode string into position and length
++ if match_length is greater than this */
++#define NIL N /* index for root of binary search trees */
++
++static unsigned char
++ text_buf[N + F - 1]; /* ring buffer of size N,
++ with extra F-1 bytes to facilitate string comparison */
++static unsigned long match_position, match_length; /* of longest match. These are
++ set by the InsertNode() procedure. */
++static unsigned long lson[N + 1], rson[N + 257], dad[N + 1]; /* left & right children &
++ parents -- These constitute binary search trees. */
++
++static void InitTree(void) /* initialize trees */
++{
++ unsigned long i;
++
++ /* For i = 0 to N - 1, rson[i] and lson[i] will be the right and
++ left children of node i. These nodes need not be initialized.
++ Also, dad[i] is the parent of node i. These are initialized to
++ NIL (= N), which stands for 'not used.'
++ For i = 0 to 255, rson[N + i + 1] is the root of the tree
++ for strings that begin with character i. These are initialized
++ to NIL. Note there are 256 trees. */
++
++ for (i = N + 1; i <= N + 256; i++) rson[i] = NIL;
++ for (i = 0; i < N; i++) dad[i] = NIL;
++}
++
++static void InsertNode(unsigned long r)
++ /* Inserts string of length F, text_buf[r..r+F-1], into one of the
++ trees (text_buf[r]'th tree) and returns the longest-match position
++ and length via the global variables match_position and match_length.
++ If match_length = F, then removes the old node in favor of the new
++ one, because the old one will be deleted sooner.
++ Note r plays double role, as tree node and position in buffer. */
++{
++ unsigned long i, p;
++ unsigned char *key;
++ signed long cmp;
++
++ cmp = 1; key = &text_buf[r]; p = N + 1 + key[0];
++ rson[r] = lson[r] = NIL; match_length = 0;
++ for ( ; ; ) {
++ if (cmp >= 0) {
++ if (rson[p] != NIL) p = rson[p];
++ else { rson[p] = r; dad[r] = p; return; }
++ } else {
++ if (lson[p] != NIL) p = lson[p];
++ else { lson[p] = r; dad[r] = p; return; }
++ }
++ for (i = 1; i < F; i++)
++ if ((cmp = key[i] - text_buf[p + i]) != 0) break;
++ if (i > match_length) {
++ match_position = p;
++ if ((match_length = i) >= F) break;
++ }
++ }
++ dad[r] = dad[p]; lson[r] = lson[p]; rson[r] = rson[p];
++ dad[lson[p]] = r; dad[rson[p]] = r;
++ if (rson[dad[p]] == p) rson[dad[p]] = r;
++ else lson[dad[p]] = r;
++ dad[p] = NIL; /* remove p */
++}
++
++static void DeleteNode(unsigned long p) /* deletes node p from tree */
++{
++ unsigned long q;
++
++ if (dad[p] == NIL) return; /* not in tree */
++ if (rson[p] == NIL) q = lson[p];
++ else if (lson[p] == NIL) q = rson[p];
++ else {
++ q = lson[p];
++ if (rson[q] != NIL) {
++ do { q = rson[q]; } while (rson[q] != NIL);
++ rson[dad[q]] = lson[q]; dad[lson[q]] = dad[q];
++ lson[q] = lson[p]; dad[lson[p]] = q;
++ }
++ rson[q] = rson[p]; dad[rson[p]] = q;
++ }
++ dad[q] = dad[p];
++ if (rson[dad[p]] == p) rson[dad[p]] = q; else lson[dad[p]] = q;
++ dad[p] = NIL;
++}
++
++/* modified for block compression */
++/* on return, srclen will contain the number of successfully compressed bytes
++ and dstlen will contain completed compressed bytes */
++
++static int Encode(unsigned char *srcbuf, unsigned char *dstbuf, unsigned long *srclen,
++ unsigned long *dstlen)
++{
++ unsigned long i, len, r, c, s, last_match_length, code_buf_ptr;
++ unsigned char code_buf[17], mask;
++ unsigned char *ip, *op;
++ unsigned long written = 0;
++ unsigned long read = 0;
++ unsigned char *srcend = srcbuf + *srclen;
++ unsigned char *dstend = dstbuf + *dstlen;
++ ip = srcbuf;
++ op = dstbuf;
++ InitTree(); /* initialize trees */
++ code_buf[0] = 0; /* code_buf[1..16] saves eight units of code, and
++ code_buf[0] works as eight flags, "1" representing that the unit
++ is an unencoded letter (1 byte), "0" a position-and-length pair
++ (2 bytes). Thus, eight units require at most 16 bytes of code. */
++ code_buf_ptr = mask = 1;
++ s = 0; r = N - F;
++ for (i = s; i < r; i++) text_buf[i] = ' '; /* Clear the buffer with
++ any character that will appear often. */
++ for (len = 0; (len < F) && (ip < srcend); len++)
++ text_buf[r + len] = *(ip++); /* Read F bytes into the last F bytes of
++ the buffer */
++ read = len;
++ for (i = 1; i <= F; i++) InsertNode(r - i); /* Insert the F strings,
++ each of which begins with one or more 'space' characters. Note
++ the order in which these strings are inserted. This way,
++ degenerate trees will be less likely to occur. */
++ InsertNode(r); /* Finally, insert the whole string just read. The
++ global variables match_length and match_position are set. */
++ do {
++ if (match_length > len) match_length = len; /* match_length
++ may be spuriously long near the end of text. */
++ if (match_length <= THRESHOLD) {
++ match_length = 1; /* Not long enough match. Send one byte. */
++ code_buf[0] |= mask; /* 'send one byte' flag */
++ code_buf[code_buf_ptr++] = text_buf[r]; /* Send uncoded. */
++ } else {
++ code_buf[code_buf_ptr++] = match_position;
++ code_buf[code_buf_ptr++] = (((match_position >> 4) & 0xf0)
++ | (match_length - (THRESHOLD + 1))); /* Send position and
++ length pair. Note match_length > THRESHOLD. */
++ }
++ if ((mask <<= 1) == 0) { /* Shift mask left one bit. */
++ if ((op + code_buf_ptr) > dstend) {
++ *dstlen = written; /* written contains bytes of complete compressed
++ code */
++ return -1;
++ };
++ for (i = 0; i < code_buf_ptr; *(op++) = code_buf[i++]); /* Send at most 8 units of */
++ /* code together */
++ written += code_buf_ptr;
++ *srclen = read; /* this many bytes have been successfully compressed */
++ code_buf[0] = 0; code_buf_ptr = mask = 1;
++ }
++ last_match_length = match_length;
++ for (i = 0; (i < last_match_length) && (ip < srcend); i++) {
++ c = *(ip++);
++ DeleteNode(s); /* Delete old strings and */
++ text_buf[s] = c; /* read new bytes */
++ if (s < F - 1) text_buf[s + N] = c; /* If the position is
++ near the end of buffer, extend the buffer to make
++ string comparison easier. */
++ s = (s + 1) & (N - 1); r = (r + 1) & (N - 1);
++ /* Since this is a ring buffer, increment the position
++ modulo N. */
++ InsertNode(r); /* Register the string in text_buf[r..r+F-1] */
++ }
++ read += i;
++ while (i++ < last_match_length) { /* After the end of text, */
++ DeleteNode(s); /* no need to read, but */
++ s = (s + 1) & (N - 1); r = (r + 1) & (N - 1);
++ if (--len) InsertNode(r); /* buffer may not be empty. */
++ }
++ } while (len > 0); /* until length of string to be processed is zero */
++ if (code_buf_ptr > 1) { /* Send remaining code. */
++ if ((op + code_buf_ptr) > dstend) {
++ *dstlen = written;
++ return -1;
++ }
++ for (i = 0; i < code_buf_ptr; *(op++) = code_buf[i++]);
++ written += code_buf_ptr;
++ *srclen = read;
++ }
++ *dstlen = written;
++ return 0;
++}
++
++static int Decode(unsigned char *srcbuf, unsigned char *dstbuf, unsigned long srclen,
++ unsigned long dstlen) /* Just the reverse of Encode(). */
++{
++ unsigned long i, r, c, j, k, flags;
++ unsigned char *ip, *op;
++ unsigned long written;
++ unsigned long read;
++ unsigned char *srcend = srcbuf + srclen;
++ unsigned char *dstend = dstbuf + dstlen;
++ read = written = 0;
++ ip = srcbuf;
++ op = dstbuf;
++ for (i = 0; i < N - F; i++) text_buf[i] = ' ';
++ r = N - F; flags = 0;
++ for ( ; ; ) {
++ if (((flags >>= 1) & 256) == 0) {
++ if (ip >= srcend) return 0;
++ c = *(ip++);
++ flags = c | 0xff00; /* uses higher byte cleverly */
++ } /* to count eight */
++ if (flags & 1) {
++ if (ip >= srcend) return 0;
++ c = *(ip++);
++ if (op >= dstend) return -1;
++ *(op++) = text_buf[r++] = c; r &= (N - 1);
++ } else {
++ if ((ip + 2) > srcend) return 0;
++ i = *(ip++);
++ j = *(ip++);
++ i |= ((j & 0xf0) << 4); j = (j & 0x0f) + THRESHOLD;
++ if ((op + j + 1) > dstend) return -1;
++ for (k = 0; k <= j; k++) {
++ c = text_buf[(i + k) & (N - 1)];
++ *(op++) = text_buf[r++] = c; r &= (N - 1);
++ }
++ }
++ }
++}
++
++/* interface to jffs2 bbc follows */
++
++#include "jffs2_bbc_framework.h"
++
++
++#define JFFS2_BBC_LZSS_BLOCK_SIGN {0x27, 0x6f, 0x12, 0xc4}
++
++static int
++jffs2_bbc_lzss_compressor_init (void);
++
++static void
++jffs2_bbc_lzss_compressor_deinit (void);
++
++static int
++jffs2_bbc_lzss_compress (void *model, unsigned char *input,
++ unsigned char *output, unsigned long *sourcelen,
++ unsigned long *dstlen);
++
++static int
++jffs2_bbc_lzss_estimate (void *model, unsigned char *input,
++ unsigned long sourcelen, unsigned long *dstlen,
++ unsigned long *readtime, unsigned long *writetime);
++
++static int
++jffs2_bbc_lzss_decompress (void *model, unsigned char *input,
++ unsigned char *output, unsigned long sourcelen,
++ unsigned long dstlen);
++
++static char *
++jffs2_bbc_lzss_proc_info (void);
++
++static int
++jffs2_bbc_lzss_proc_command (char *command);
++
++struct jffs2_bbc_compressor_type jffs2_bbc_lzss = {
++ "lzss",
++ 0,
++ JFFS2_BBC_LZSS_BLOCK_SIGN,
++ jffs2_bbc_lzss_compressor_init,
++ NULL,
++ NULL,
++ jffs2_bbc_lzss_compressor_deinit,
++ jffs2_bbc_lzss_compress,
++ jffs2_bbc_lzss_estimate,
++ jffs2_bbc_lzss_decompress,
++ jffs2_bbc_lzss_proc_info,
++ jffs2_bbc_lzss_proc_command
++};
++
++static int
++jffs2_bbc_lzss_compressor_init (void)
++{
++ return 0;
++}
++
++static void
++jffs2_bbc_lzss_compressor_deinit (void)
++{
++}
++
++static int
++jffs2_bbc_lzss_compress (void *model, unsigned char *input,
++ unsigned char *output, unsigned long *sourcelen,
++ unsigned long *dstlen)
++{
++ int retval;
++ unsigned long dst = *dstlen;
++ *(output++) = jffs2_bbc_lzss.block_sign[0];
++ *(output++) = jffs2_bbc_lzss.block_sign[1];
++ dst -= 2;
++ retval = Encode(input, output, sourcelen, &dst);
++ dst += 2;
++ *dstlen = dst;
++ return retval;
++}
++
++static int
++jffs2_bbc_lzss_estimate (void *model, unsigned char *input,
++ unsigned long sourcelen, unsigned long *dstlen,
++ unsigned long *readtime, unsigned long *writetime)
++{
++ *dstlen = sourcelen * 60 / 100;
++ *readtime = JFFS2_BBC_ZLIB_READ_TIME * 12 / 10;
++ *writetime = JFFS2_BBC_ZLIB_WRITE_TIME * 3;
++ return 0;
++}
++
++static int
++jffs2_bbc_lzss_decompress (void *model, unsigned char *input,
++ unsigned char *output, unsigned long sourcelen,
++ unsigned long dstlen)
++{
++ if ( ( *(input++) != (unsigned char)jffs2_bbc_lzss.block_sign[0] ) ||
++ ( *(input++) != (unsigned char)jffs2_bbc_lzss.block_sign[1] )
++ ) {
++ return -1;
++ } else {
++ return Decode(input, output, sourcelen - 2, dstlen);
++ }
++}
++
++static char *
++jffs2_bbc_lzss_proc_info (void)
++{
++ return "Lempel-Ziv-Storer-Szymanski compression module";
++}
++
++static int
++jffs2_bbc_lzss_proc_command (char *command)
++{
++ return 0;
++}
++
++struct jffs2_bbc_compressor_type *
++jffs2_bbc_lzss_init (int mode)
++{
++ if (jffs2_bbc_register_compressor (&jffs2_bbc_lzss) == 0)
++ {
++ return &jffs2_bbc_lzss;
++ }
++ else
++ {
++ return NULL;
++ }
++}
++
++void
++jffs2_bbc_lzss_deinit (void)
++{
++ jffs2_bbc_unregister_compressor (&jffs2_bbc_lzss);
++}
+diff -Nur linux-mips-cvs/fs/jffs2/linux-2.4.25.hpatch linux-mips/fs/jffs2/linux-2.4.25.hpatch
+--- linux-mips-cvs/fs/jffs2/linux-2.4.25.hpatch 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips/fs/jffs2/linux-2.4.25.hpatch 2005-02-07 05:08:34.000000000 +0100
+@@ -0,0 +1,97 @@
++FMakefile
++=BBC insertion
++-COMPR_OBJS
++iMakefile.bbc.inc
+++
++I
++?JFFS2_OBJS
+++ $(JFFS2_BBC_KERNEL_OBJS) \
++
++F../Config.in
++=BBC insertion
++-tristate 'Compressed ROM file system support' CONFIG_CRAMFS
++iConfig.in.bbc.inc
+++
++I
++F../../Documentation/Configure.help
++=BBC insertion
++-JFFS stats available
++iConfigure.help.bbc.inc
+++
++I
++Fcompr_zlib.c
++=(de)compress->(de)compress2
++-int zlib_compress(unsigned char *data_in, unsigned char *cpage_out,
+++int jffs2_zlib_compress2(unsigned char *data_in, unsigned char *cpage_out,
++-void zlib_decompress(unsigned char *data_in, unsigned char *cpage_out,
+++void jffs2_zlib_decompress2(unsigned char *data_in, unsigned char *cpage_out,
++?inflateEnd(&strm);
++?}
+++
+++extern int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out, __u32 * sourcelen, __u32 * dstlen);
+++extern void jffs2_zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, __u32 srclen, __u32 destlen);
+++
+++int zlib_compress(unsigned char *data_in, unsigned char *cpage_out,
+++ __u32 *sourcelen, __u32 *dstlen)
+++{
+++ return jffs2_zlib_compress(data_in,cpage_out,sourcelen,dstlen);
+++}
+++
+++void zlib_decompress(unsigned char *data_in, unsigned char *cpage_out,
+++ __u32 srclen, __u32 destlen)
+++{
+++ jffs2_zlib_decompress(data_in,cpage_out,srclen,destlen);
+++}
+++
++
++Ffile.c
++=set_act_sb before write
++-#include
+++#include "jffs2_bbc_framework.h" /**BBC**/
++I
++?int jffs2_commit_write
++-jffs2_compress(
+++ jffs2_bbc_model_set_act_sb(c); /**BBC**/
++I
++
++Fgc.c
++=set_act_sb before write
++-#include
+++#include "jffs2_bbc_framework.h" /**BBC**/
++I
++?int jffs2_garbage_collect_dnode(
++-jffs2_compress(
+++ jffs2_bbc_model_set_act_sb(c); /**BBC**/
++I
++
++Fread.c
++=set_act_sb before read
++-#include
+++#include "jffs2_bbc_framework.h" /**BBC**/
++I
++?int jffs2_read_dnode(
++-jffs2_decompress(
+++ jffs2_bbc_model_set_act_sb(c); /**BBC**/
++I
++
++Fsuper.c
++=init, load_model
++-#include
+++#include "jffs2_bbc_fs.h" /**BBC**/
++I
++?struct super_block *jffs2_read_super(
++-return sb;
+++ jffs2_bbc_load_model(sb); /**BBC**/
++I
++?void jffs2_put_super
++?c = JFFS2_SB_INFO
+++ jffs2_bbc_unload_model(sb); /**BBC**/
++?init_jffs2_fs(void)
++?int ret;
+++
+++ jffs2_bbc_proc_init(); /**BBC**/
+++
++?exit_jffs2_fs(void)
++?{
+++ jffs2_bbc_proc_deinit(); /**BBC**/
+++
+diff -Nur linux-mips-cvs/fs/jffs2/read.c linux-mips/fs/jffs2/read.c
+--- linux-mips-cvs/fs/jffs2/read.c 2003-11-17 02:07:44.000000000 +0100
++++ linux-mips/fs/jffs2/read.c 2005-02-07 05:08:35.000000000 +0100
+@@ -35,6 +35,7 @@
+ *
+ */
+
++#include "jffs2_bbc_framework.h" /**BBC**/
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/jffs2.h>
+@@ -140,6 +141,7 @@
+ D2(printk(KERN_DEBUG "Data CRC matches calculated CRC %08x\n", crc));
+ if (ri->compr != JFFS2_COMPR_NONE) {
+ D2(printk(KERN_DEBUG "Decompress %d bytes from %p to %d bytes at %p\n", ri->csize, readbuf, ri->dsize, decomprbuf));
++ jffs2_bbc_model_set_act_sb(c); /**BBC**/
+ ret = jffs2_decompress(ri->compr, readbuf, decomprbuf, ri->csize, ri->dsize);
+ if (ret) {
+ printk(KERN_WARNING "Error: jffs2_decompress returned %d\n", ret);
+diff -Nur linux-mips-cvs/fs/jffs2/super.c linux-mips/fs/jffs2/super.c
+--- linux-mips-cvs/fs/jffs2/super.c 2003-01-11 18:53:17.000000000 +0100
++++ linux-mips/fs/jffs2/super.c 2005-02-07 05:08:35.000000000 +0100
+@@ -35,6 +35,7 @@
+ *
+ */
+
++#include "jffs2_bbc_fs.h" /**BBC**/
+ #include <linux/config.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+@@ -272,6 +273,7 @@
+ sb->s_magic = JFFS2_SUPER_MAGIC;
+ if (!(sb->s_flags & MS_RDONLY))
+ jffs2_start_garbage_collect_thread(c);
++ jffs2_bbc_load_model(sb); /**BBC**/
+ return sb;
+
+ out_root_i:
+@@ -288,6 +290,7 @@
+ void jffs2_put_super (struct super_block *sb)
+ {
+ struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
++ jffs2_bbc_unload_model(sb); /**BBC**/
+
+ D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n"));
+
+@@ -344,6 +347,9 @@
+ {
+ int ret;
+
++ jffs2_bbc_proc_init(); /**BBC**/
++
++
+ printk(KERN_NOTICE "JFFS2 version 2.1. (C) 2001 Red Hat, Inc., designed by Axis Communications AB.\n");
+
+ #ifdef JFFS2_OUT_OF_KERNEL
+@@ -388,6 +394,8 @@
+
+ static void __exit exit_jffs2_fs(void)
+ {
++ jffs2_bbc_proc_deinit(); /**BBC**/
++
+ jffs2_destroy_slab_caches();
+ jffs2_zlib_exit();
+ unregister_filesystem(&jffs2_fs_type);
diff --git a/target/linux/generic-2.4/patches/004-exec_pagesize.patch b/target/linux/generic-2.4/patches/004-exec_pagesize.patch
new file mode 100644
index 0000000000..a7b1d04064
--- /dev/null
+++ b/target/linux/generic-2.4/patches/004-exec_pagesize.patch
@@ -0,0 +1,11 @@
+--- linux.old/include/asm-mips/param.h 2005-01-19 15:10:12.000000000 +0100
++++ linux.dev/include/asm-mips/param.h 2005-05-30 02:42:06.000000000 +0200
+@@ -55,7 +55,7 @@
+ #endif /* defined(__KERNEL__) */
+ #endif /* defined(HZ) */
+
+-#define EXEC_PAGESIZE 65536
++#define EXEC_PAGESIZE 4096
+
+ #ifndef NGROUPS
+ #define NGROUPS 32
diff --git a/target/linux/generic-2.4/patches/005-mtd_flashtypes.patch b/target/linux/generic-2.4/patches/005-mtd_flashtypes.patch
new file mode 100644
index 0000000000..9115b9f611
--- /dev/null
+++ b/target/linux/generic-2.4/patches/005-mtd_flashtypes.patch
@@ -0,0 +1,925 @@
+diff -Nur linux-2.4.30/drivers/mtd/chips/Config.in linux-2.4.30.openwrt/drivers/mtd/chips/Config.in
+--- linux-2.4.30/drivers/mtd/chips/Config.in 2003-06-13 16:51:34.000000000 +0200
++++ linux-2.4.30.openwrt/drivers/mtd/chips/Config.in 2005-06-28 11:26:26.000000000 +0200
+@@ -45,6 +45,7 @@
+ dep_tristate ' Support for Intel/Sharp flash chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_GEN_PROBE
+ dep_tristate ' Support for AMD/Fujitsu flash chips' CONFIG_MTD_CFI_AMDSTD $CONFIG_MTD_GEN_PROBE
+ dep_tristate ' Support for ST (Advanced Architecture) flash chips' CONFIG_MTD_CFI_STAA $CONFIG_MTD_GEN_PROBE
++dep_tristate ' Support for SST flash chips' CONFIG_MTD_CFI_SSTSTD $CONFIG_MTD_GEN_PROBE
+
+ dep_tristate ' Support for RAM chips in bus mapping' CONFIG_MTD_RAM $CONFIG_MTD
+ dep_tristate ' Support for ROM chips in bus mapping' CONFIG_MTD_ROM $CONFIG_MTD
+diff -Nur linux-2.4.30/drivers/mtd/chips/Makefile linux-2.4.30.openwrt/drivers/mtd/chips/Makefile
+--- linux-2.4.30/drivers/mtd/chips/Makefile 2003-06-13 16:51:34.000000000 +0200
++++ linux-2.4.30.openwrt/drivers/mtd/chips/Makefile 2005-06-28 11:26:26.000000000 +0200
+@@ -18,6 +18,7 @@
+ obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o
+ obj-$(CONFIG_MTD_CFI) += cfi_probe.o
+ obj-$(CONFIG_MTD_CFI_STAA) += cfi_cmdset_0020.o
++obj-$(CONFIG_MTD_CFI_SSTSTD) += cfi_cmdset_0701.o
+ obj-$(CONFIG_MTD_CFI_AMDSTD) += cfi_cmdset_0002.o
+ obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o
+ obj-$(CONFIG_MTD_GEN_PROBE) += gen_probe.o
+diff -Nur linux-2.4.30/drivers/mtd/chips/cfi_cmdset_0701.c linux-2.4.30.openwrt/drivers/mtd/chips/cfi_cmdset_0701.c
+--- linux-2.4.30/drivers/mtd/chips/cfi_cmdset_0701.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30.openwrt/drivers/mtd/chips/cfi_cmdset_0701.c 2005-06-28 11:26:26.000000000 +0200
+@@ -0,0 +1,855 @@
++/*
++ * Common Flash Interface support:
++ * SST Standard Vendor Command Set (ID 0x0701)
++ *
++ * Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>
++ *
++ * 2_by_8 routines added by Simon Munton
++ *
++ * This code is GPL
++ *
++ * $Id: cfi_cmdset_0701.c,v 1.1 2005/03/16 13:50:00 wbx Exp $
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <asm/io.h>
++#include <asm/byteorder.h>
++
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/cfi.h>
++
++static int cfi_sststd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
++static int cfi_sststd_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
++static int cfi_sststd_erase_onesize(struct mtd_info *, struct erase_info *);
++static int cfi_sststd_erase_varsize(struct mtd_info *, struct erase_info *);
++static void cfi_sststd_sync (struct mtd_info *);
++static int cfi_sststd_suspend (struct mtd_info *);
++static void cfi_sststd_resume (struct mtd_info *);
++
++static void cfi_sststd_destroy(struct mtd_info *);
++
++struct mtd_info *cfi_cmdset_0701(struct map_info *, int);
++static struct mtd_info *cfi_sststd_setup (struct map_info *);
++
++
++static struct mtd_chip_driver cfi_sststd_chipdrv = {
++ probe: NULL, /* Not usable directly */
++ destroy: cfi_sststd_destroy,
++ name: "cfi_cmdset_0701",
++ module: THIS_MODULE
++};
++
++struct mtd_info *cfi_cmdset_0701(struct map_info *map, int primary)
++{
++ struct cfi_private *cfi = map->fldrv_priv;
++ int ofs_factor = cfi->interleave * cfi->device_type;
++ int i;
++ __u8 major, minor;
++ __u32 base = cfi->chips[0].start;
++
++ if (cfi->cfi_mode==1){
++ __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
++
++ cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
++ cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
++ cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
++
++ major = cfi_read_query(map, base + (adr+3)*ofs_factor);
++ minor = cfi_read_query(map, base + (adr+4)*ofs_factor);
++
++ printk(" SST Query Table v%c.%c at 0x%4.4X\n",
++ major, minor, adr);
++ cfi_send_gen_cmd(0xf0, 0x5555, base, map, cfi, cfi->device_type, NULL);
++
++ cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
++ cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
++ cfi_send_gen_cmd(0x90, 0x5555, base, map, cfi, cfi->device_type, NULL);
++ cfi->mfr = cfi_read_query(map, base);
++ cfi->id = cfi_read_query(map, base + ofs_factor);
++
++ cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
++ cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
++ cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
++
++ switch (cfi->device_type) {
++ case CFI_DEVICETYPE_X16:
++ cfi->addr_unlock1 = 0x5555;
++ cfi->addr_unlock2 = 0x2AAA;
++ break;
++ default:
++ printk(KERN_NOTICE "Eep. Unknown cfi_cmdset_0701 device type %d\n", cfi->device_type);
++ return NULL;
++ }
++ } /* CFI mode */
++
++ for (i=0; i< cfi->numchips; i++) {
++ cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
++ cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
++ cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
++ }
++
++ map->fldrv = &cfi_sststd_chipdrv;
++ MOD_INC_USE_COUNT;
++
++ cfi_send_gen_cmd(0xf0, 0x5555, base, map, cfi, cfi->device_type, NULL);
++ return cfi_sststd_setup(map);
++}
++
++static struct mtd_info *cfi_sststd_setup(struct map_info *map)
++{
++ struct cfi_private *cfi = map->fldrv_priv;
++ struct mtd_info *mtd;
++ unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
++
++ mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
++ printk("number of %s chips: %d\n", (cfi->cfi_mode)?"JEDEC":"CFI",cfi->numchips);
++
++ if (!mtd) {
++ printk("Failed to allocate memory for MTD device\n");
++ kfree(cfi->cmdset_priv);
++ return NULL;
++ }
++
++ memset(mtd, 0, sizeof(*mtd));
++ mtd->priv = map;
++ mtd->type = MTD_NORFLASH;
++ /* Also select the correct geometry setup too */
++ mtd->size = devsize * cfi->numchips;
++
++ if (cfi->cfiq->NumEraseRegions == 1) {
++ /* No need to muck about with multiple erase sizes */
++ mtd->erasesize = ((cfi->cfiq->EraseRegionInfo[0] >> 8) & ~0xff) * cfi->interleave;
++ } else {
++ unsigned long offset = 0;
++ int i,j;
++
++ mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
++ mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * mtd->numeraseregions, GFP_KERNEL);
++ if (!mtd->eraseregions) {
++ printk("Failed to allocate memory for MTD erase region info\n");
++ kfree(cfi->cmdset_priv);
++ return NULL;
++ }
++
++ for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
++ unsigned long ernum, ersize;
++ ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
++ ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1;
++
++ if (mtd->erasesize < ersize) {
++ mtd->erasesize = ersize;
++ }
++ for (j=0; j<cfi->numchips; j++) {
++ mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset;
++ mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize;
++ mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum;
++ }
++ offset += (ersize * ernum);
++ }
++
++ // debug
++ for (i=0; i<mtd->numeraseregions;i++){
++ printk("%d: offset=0x%x,size=0x%x,blocks=%d\n",
++ i,mtd->eraseregions[i].offset,
++ mtd->eraseregions[i].erasesize,
++ mtd->eraseregions[i].numblocks);
++ }
++ }
++
++ switch (CFIDEV_BUSWIDTH)
++ {
++ case 1:
++ case 2:
++ case 4:
++ if (mtd->numeraseregions > 1)
++ mtd->erase = cfi_sststd_erase_varsize;
++ else
++ mtd->erase = cfi_sststd_erase_onesize;
++ mtd->read = cfi_sststd_read;
++ mtd->write = cfi_sststd_write;
++ break;
++
++ default:
++ printk("Unsupported buswidth\n");
++ kfree(mtd);
++ kfree(cfi->cmdset_priv);
++ return NULL;
++ break;
++ }
++ mtd->sync = cfi_sststd_sync;
++ mtd->suspend = cfi_sststd_suspend;
++ mtd->resume = cfi_sststd_resume;
++ mtd->flags = MTD_CAP_NORFLASH;
++ map->fldrv = &cfi_sststd_chipdrv;
++ mtd->name = map->name;
++ MOD_INC_USE_COUNT;
++ return mtd;
++}
++
++static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
++{
++ DECLARE_WAITQUEUE(wait, current);
++ unsigned long timeo = jiffies + HZ;
++
++ retry:
++ cfi_spin_lock(chip->mutex);
++
++ if (chip->state != FL_READY){
++ printk("Waiting for chip to read, status = %d\n", chip->state);
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ add_wait_queue(&chip->wq, &wait);
++
++ cfi_spin_unlock(chip->mutex);
++
++ schedule();
++ remove_wait_queue(&chip->wq, &wait);
++ timeo = jiffies + HZ;
++
++ goto retry;
++ }
++
++ adr += chip->start;
++
++ chip->state = FL_READY;
++
++ map->copy_from(map, buf, adr, len);
++
++ wake_up(&chip->wq);
++ cfi_spin_unlock(chip->mutex);
++
++ return 0;
++}
++
++static int cfi_sststd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
++{
++ struct map_info *map = mtd->priv;
++ struct cfi_private *cfi = map->fldrv_priv;
++ unsigned long ofs;
++ int chipnum;
++ int ret = 0;
++
++ /* ofs: offset within the first chip that the first read should start */
++
++ chipnum = (from >> cfi->chipshift);
++ ofs = from - (chipnum << cfi->chipshift);
++
++
++ *retlen = 0;
++
++ while (len) {
++ unsigned long thislen;
++
++ if (chipnum >= cfi->numchips)
++ break;
++
++ if ((len + ofs -1) >> cfi->chipshift)
++ thislen = (1<<cfi->chipshift) - ofs;
++ else
++ thislen = len;
++
++ ret = do_read_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
++ if (ret)
++ break;
++
++ *retlen += thislen;
++ len -= thislen;
++ buf += thislen;
++
++ ofs = 0;
++ chipnum++;
++ }
++ return ret;
++}
++
++static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u32 datum, int fast)
++{
++ unsigned long timeo = jiffies + HZ;
++ unsigned int Last[4];
++ unsigned long Count = 0;
++ struct cfi_private *cfi = map->fldrv_priv;
++ DECLARE_WAITQUEUE(wait, current);
++ int ret = 0;
++
++ retry:
++ cfi_spin_lock(chip->mutex);
++
++ if (chip->state != FL_READY){
++ printk("Waiting for chip to write, status = %d\n", chip->state);
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ add_wait_queue(&chip->wq, &wait);
++
++ cfi_spin_unlock(chip->mutex);
++
++ schedule();
++ remove_wait_queue(&chip->wq, &wait);
++ printk("Wake up to write:\n");
++ timeo = jiffies + HZ;
++
++ goto retry;
++ }
++
++ chip->state = FL_WRITING;
++
++ adr += chip->start;
++ ENABLE_VPP(map);
++ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
++ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
++ cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
++
++ cfi_write(map, datum, adr);
++
++ cfi_spin_unlock(chip->mutex);
++ cfi_udelay(chip->word_write_time);
++ cfi_spin_lock(chip->mutex);
++
++ Last[0] = cfi_read(map, adr);
++ // printk("Last[0] is %x\n", Last[0]);
++ Last[1] = cfi_read(map, adr);
++ // printk("Last[1] is %x\n", Last[1]);
++ Last[2] = cfi_read(map, adr);
++ // printk("Last[2] is %x\n", Last[2]);
++
++ for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && Count < 10000; Count++){
++ cfi_spin_unlock(chip->mutex);
++ cfi_udelay(10);
++ cfi_spin_lock(chip->mutex);
++
++ Last[Count % 4] = cfi_read(map, adr);
++ // printk("Last[%d%%4] is %x\n", Count, Last[Count%4]);
++ }
++
++ if (Last[(Count - 1) % 4] != datum){
++ printk("Last[%ld] is %x, datum is %x\n",(Count - 1) % 4,Last[(Count - 1) % 4],datum);
++ cfi_send_gen_cmd(0xF0, 0, chip->start, map, cfi, cfi->device_type, NULL);
++ DISABLE_VPP(map);
++ ret = -EIO;
++ }
++ DISABLE_VPP(map);
++ chip->state = FL_READY;
++ wake_up(&chip->wq);
++ cfi_spin_unlock(chip->mutex);
++
++ return ret;
++}
++
++static int cfi_sststd_write (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf)
++{
++ struct map_info *map = mtd->priv;
++ struct cfi_private *cfi = map->fldrv_priv;
++ int ret = 0;
++ int chipnum;
++ unsigned long ofs, chipstart;
++
++ *retlen = 0;
++ if (!len)
++ return 0;
++
++ chipnum = to >> cfi->chipshift;
++ ofs = to - (chipnum << cfi->chipshift);
++ chipstart = cfi->chips[chipnum].start;
++
++ /* If it's not bus-aligned, do the first byte write */
++ if (ofs & (CFIDEV_BUSWIDTH-1)) {
++ unsigned long bus_ofs = ofs & ~(CFIDEV_BUSWIDTH-1);
++ int i = ofs - bus_ofs;
++ int n = 0;
++ u_char tmp_buf[4];
++ __u32 datum;
++
++ map->copy_from(map, tmp_buf, bus_ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH);
++ while (len && i < CFIDEV_BUSWIDTH)
++ tmp_buf[i++] = buf[n++], len--;
++
++ if (cfi_buswidth_is_2()) {
++ datum = *(__u16*)tmp_buf;
++ } else if (cfi_buswidth_is_4()) {
++ datum = *(__u32*)tmp_buf;
++ } else {
++ return -EINVAL; /* should never happen, but be safe */
++ }
++
++ ret = do_write_oneword(map, &cfi->chips[chipnum],
++ bus_ofs, datum, 0);
++ if (ret)
++ return ret;
++
++ ofs += n;
++ buf += n;
++ (*retlen) += n;
++
++ if (ofs >> cfi->chipshift) {
++ chipnum ++;
++ ofs = 0;
++ if (chipnum == cfi->numchips)
++ return 0;
++ }
++ }
++
++ /* We are now aligned, write as much as possible */
++ while(len >= CFIDEV_BUSWIDTH) {
++ __u32 datum;
++
++ if (cfi_buswidth_is_1()) {
++ datum = *(__u8*)buf;
++ } else if (cfi_buswidth_is_2()) {
++ datum = *(__u16*)buf;
++ } else if (cfi_buswidth_is_4()) {
++ datum = *(__u32*)buf;
++ } else {
++ return -EINVAL;
++ }
++ ret = do_write_oneword(map, &cfi->chips[chipnum],
++ ofs, datum, cfi->fast_prog);
++ if (ret) {
++ return ret;
++ }
++
++ ofs += CFIDEV_BUSWIDTH;
++ buf += CFIDEV_BUSWIDTH;
++ (*retlen) += CFIDEV_BUSWIDTH;
++ len -= CFIDEV_BUSWIDTH;
++
++ if (ofs >> cfi->chipshift) {
++ chipnum ++;
++ ofs = 0;
++ if (chipnum == cfi->numchips)
++ return 0;
++ chipstart = cfi->chips[chipnum].start;
++ }
++ }
++
++ if (len & (CFIDEV_BUSWIDTH-1)) {
++ int i = 0, n = 0;
++ u_char tmp_buf[4];
++ __u32 datum;
++
++ map->copy_from(map, tmp_buf, ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH);
++ while (len--)
++ tmp_buf[i++] = buf[n++];
++
++ if (cfi_buswidth_is_2()) {
++ datum = *(__u16*)tmp_buf;
++ } else if (cfi_buswidth_is_4()) {
++ datum = *(__u32*)tmp_buf;
++ } else {
++ return -EINVAL; /* should never happen, but be safe */
++ }
++
++ ret = do_write_oneword(map, &cfi->chips[chipnum],
++ ofs, datum, 0);
++ if (ret)
++ return ret;
++
++ (*retlen) += n;
++ }
++
++ return 0;
++}
++
++static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
++{
++ unsigned int status;
++ unsigned long timeo = jiffies + HZ;
++ struct cfi_private *cfi = map->fldrv_priv;
++ unsigned int rdy_mask;
++ DECLARE_WAITQUEUE(wait, current);
++
++ retry:
++ cfi_spin_lock(chip->mutex);
++
++ if (chip->state != FL_READY){
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ add_wait_queue(&chip->wq, &wait);
++
++ cfi_spin_unlock(chip->mutex);
++
++ schedule();
++ remove_wait_queue(&chip->wq, &wait);
++ timeo = jiffies + HZ;
++
++ goto retry;
++ }
++
++ chip->state = FL_ERASING;
++
++ adr += chip->start;
++ ENABLE_VPP(map);
++ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
++ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
++ cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
++ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
++ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
++ cfi_write(map, CMD(0x30), adr);
++
++ timeo = jiffies + (HZ*20);
++
++ cfi_spin_unlock(chip->mutex);
++ schedule_timeout(HZ);
++ cfi_spin_lock(chip->mutex);
++
++ rdy_mask = CMD(0x80);
++
++ /* Once the state machine's known to be working I'll do that */
++
++ while ( ( (status = cfi_read(map,adr)) & rdy_mask ) != rdy_mask ) {
++ static int z=0;
++
++ if (chip->state != FL_ERASING) {
++ /* Someone's suspended the erase. Sleep */
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ add_wait_queue(&chip->wq, &wait);
++
++ cfi_spin_unlock(chip->mutex);
++ printk("erase suspended. Sleeping\n");
++
++ schedule();
++ remove_wait_queue(&chip->wq, &wait);
++ timeo = jiffies + (HZ*2);
++ cfi_spin_lock(chip->mutex);
++ continue;
++ }
++
++ /* OK Still waiting */
++ if (time_after(jiffies, timeo)) {
++ chip->state = FL_READY;
++ cfi_spin_unlock(chip->mutex);
++ printk("waiting for erase to complete timed out.");
++ DISABLE_VPP(map);
++ return -EIO;
++ }
++
++ /* Latency issues. Drop the lock, wait a while and retry */
++ cfi_spin_unlock(chip->mutex);
++
++ z++;
++ if ( 0 && !(z % 100 ))
++ printk("chip not ready yet after erase. looping\n");
++
++ cfi_udelay(1);
++
++ cfi_spin_lock(chip->mutex);
++ continue;
++ }
++
++ /* Done and happy. */
++ DISABLE_VPP(map);
++ chip->state = FL_READY;
++ wake_up(&chip->wq);
++ cfi_spin_unlock(chip->mutex);
++ return 0;
++}
++
++static int cfi_sststd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
++{
++ struct map_info *map = mtd->priv;
++ struct cfi_private *cfi = map->fldrv_priv;
++ unsigned long adr, len;
++ int chipnum, ret = 0;
++ int i, first;
++ struct mtd_erase_region_info *regions = mtd->eraseregions;
++
++ if (instr->addr > mtd->size)
++ return -EINVAL;
++
++ if ((instr->len + instr->addr) > mtd->size)
++ return -EINVAL;
++
++ /* Check that both start and end of the requested erase are
++ * aligned with the erasesize at the appropriate addresses.
++ */
++
++ i = 0;
++
++ /* Skip all erase regions which are ended before the start of
++ the requested erase. Actually, to save on the calculations,
++ we skip to the first erase region which starts after the
++ start of the requested erase, and then go back one.
++ */
++
++ while (i < mtd->numeraseregions && instr->addr >= regions[i].offset)
++ i++;
++ i--;
++
++ /* OK, now i is pointing at the erase region in which this
++ erase request starts. Check the start of the requested
++ erase range is aligned with the erase size which is in
++ effect here.
++ */
++
++ if (instr->addr & (regions[i].erasesize-1))
++ return -EINVAL;
++
++ /* Remember the erase region we start on */
++ first = i;
++
++ /* Next, check that the end of the requested erase is aligned
++ * with the erase region at that address.
++ */
++
++ while (i<mtd->numeraseregions && (instr->addr + instr->len) >= regions[i].offset)
++ i++;
++
++ /* As before, drop back one to point at the region in which
++ the address actually falls
++ */
++ i--;
++
++ if ((instr->addr + instr->len) & (regions[i].erasesize-1))
++ return -EINVAL;
++
++ chipnum = instr->addr >> cfi->chipshift;
++ adr = instr->addr - (chipnum << cfi->chipshift);
++ len = instr->len;
++
++ i=first;
++
++ while(len) {
++ ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr);
++
++ if (ret)
++ return ret;
++
++ adr += regions[i].erasesize;
++ len -= regions[i].erasesize;
++
++ if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
++ i++;
++
++ if (adr >> cfi->chipshift) {
++ adr = 0;
++ chipnum++;
++
++ if (chipnum >= cfi->numchips)
++ break;
++ }
++ }
++
++ instr->state = MTD_ERASE_DONE;
++ if (instr->callback)
++ instr->callback(instr);
++
++ return 0;
++}
++
++static int cfi_sststd_erase_onesize(struct mtd_info *mtd, struct erase_info *instr)
++{
++ struct map_info *map = mtd->priv;
++ struct cfi_private *cfi = map->fldrv_priv;
++ unsigned long adr, len;
++ int chipnum, ret = 0;
++
++ if (instr->addr & (mtd->erasesize - 1))
++ return -EINVAL;
++
++ if (instr->len & (mtd->erasesize -1))
++ return -EINVAL;
++
++ if ((instr->len + instr->addr) > mtd->size)
++ return -EINVAL;
++
++ chipnum = instr->addr >> cfi->chipshift;
++ adr = instr->addr - (chipnum << cfi->chipshift);
++ len = instr->len;
++
++ while(len) {
++ ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr);
++
++ if (ret)
++ return ret;
++
++ adr += mtd->erasesize;
++ len -= mtd->erasesize;
++
++ if (adr >> cfi->chipshift) {
++ adr = 0;
++ chipnum++;
++
++ if (chipnum >= cfi->numchips)
++ break;
++ }
++ }
++
++ instr->state = MTD_ERASE_DONE;
++ if (instr->callback)
++ instr->callback(instr);
++
++ return 0;
++}
++
++static void cfi_sststd_sync (struct mtd_info *mtd)
++{
++ struct map_info *map = mtd->priv;
++ struct cfi_private *cfi = map->fldrv_priv;
++ int i;
++ struct flchip *chip;
++ int ret = 0;
++ DECLARE_WAITQUEUE(wait, current);
++
++ for (i=0; !ret && i<cfi->numchips; i++) {
++ chip = &cfi->chips[i];
++
++ retry:
++ cfi_spin_lock(chip->mutex);
++
++ switch(chip->state) {
++ case FL_READY:
++ case FL_STATUS:
++ case FL_CFI_QUERY:
++ case FL_JEDEC_QUERY:
++ chip->oldstate = chip->state;
++ chip->state = FL_SYNCING;
++ /* No need to wake_up() on this state change -
++ * as the whole point is that nobody can do anything
++ * with the chip now anyway.
++ */
++ case FL_SYNCING:
++ cfi_spin_unlock(chip->mutex);
++ break;
++
++ default:
++ /* Not an idle state */
++ add_wait_queue(&chip->wq, &wait);
++
++ cfi_spin_unlock(chip->mutex);
++
++ schedule();
++
++ remove_wait_queue(&chip->wq, &wait);
++
++ goto retry;
++ }
++ }
++
++ /* Unlock the chips again */
++
++ for (i--; i >=0; i--) {
++ chip = &cfi->chips[i];
++
++ cfi_spin_lock(chip->mutex);
++
++ if (chip->state == FL_SYNCING) {
++ chip->state = chip->oldstate;
++ wake_up(&chip->wq);
++ }
++ cfi_spin_unlock(chip->mutex);
++ }
++}
++
++
++static int cfi_sststd_suspend(struct mtd_info *mtd)
++{
++ struct map_info *map = mtd->priv;
++ struct cfi_private *cfi = map->fldrv_priv;
++ int i;
++ struct flchip *chip;
++ int ret = 0;
++//printk("suspend\n");
++
++ for (i=0; !ret && i<cfi->numchips; i++) {
++ chip = &cfi->chips[i];
++
++ cfi_spin_lock(chip->mutex);
++
++ switch(chip->state) {
++ case FL_READY:
++ case FL_STATUS:
++ case FL_CFI_QUERY:
++ case FL_JEDEC_QUERY:
++ chip->oldstate = chip->state;
++ chip->state = FL_PM_SUSPENDED;
++ /* No need to wake_up() on this state change -
++ * as the whole point is that nobody can do anything
++ * with the chip now anyway.
++ */
++ case FL_PM_SUSPENDED:
++ break;
++
++ default:
++ ret = -EAGAIN;
++ break;
++ }
++ cfi_spin_unlock(chip->mutex);
++ }
++
++ /* Unlock the chips again */
++
++ if (ret) {
++ for (i--; i >=0; i--) {
++ chip = &cfi->chips[i];
++
++ cfi_spin_lock(chip->mutex);
++
++ if (chip->state == FL_PM_SUSPENDED) {
++ chip->state = chip->oldstate;
++ wake_up(&chip->wq);
++ }
++ cfi_spin_unlock(chip->mutex);
++ }
++ }
++
++ return ret;
++}
++
++static void cfi_sststd_resume(struct mtd_info *mtd)
++{
++ struct map_info *map = mtd->priv;
++ struct cfi_private *cfi = map->fldrv_priv;
++ int i;
++ struct flchip *chip;
++//printk("resume\n");
++
++ for (i=0; i<cfi->numchips; i++) {
++
++ chip = &cfi->chips[i];
++
++ cfi_spin_lock(chip->mutex);
++
++ if (chip->state == FL_PM_SUSPENDED) {
++ chip->state = FL_READY;
++ cfi_write(map, CMD(0xF0), chip->start);
++ wake_up(&chip->wq);
++ }
++ else
++ printk("Argh. Chip not in PM_SUSPENDED state upon resume()\n");
++
++ cfi_spin_unlock(chip->mutex);
++ }
++}
++
++static void cfi_sststd_destroy(struct mtd_info *mtd)
++{
++ struct map_info *map = mtd->priv;
++ struct cfi_private *cfi = map->fldrv_priv;
++ kfree(cfi->cmdset_priv);
++ kfree(cfi);
++}
++
++#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
++#define cfi_sststd_init init_module
++#define cfi_sststd_exit cleanup_module
++#endif
++
++static char im_name[]="cfi_cmdset_0701";
++
++mod_init_t cfi_sststd_init(void)
++{
++ inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0701);
++ return 0;
++}
++
++mod_exit_t cfi_sststd_exit(void)
++{
++ inter_module_unregister(im_name);
++}
++
++module_init(cfi_sststd_init);
++module_exit(cfi_sststd_exit);
++
+diff -Nur linux-2.4.30/drivers/mtd/chips/cfi_probe.c linux-2.4.30.openwrt/drivers/mtd/chips/cfi_probe.c
+--- linux-2.4.30/drivers/mtd/chips/cfi_probe.c 2003-06-13 16:51:34.000000000 +0200
++++ linux-2.4.30.openwrt/drivers/mtd/chips/cfi_probe.c 2005-06-28 11:26:26.000000000 +0200
+@@ -67,8 +67,15 @@
+ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+ cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
+
+- if (!qry_present(map,base,cfi))
+- return 0;
++ if (!qry_present(map,base,cfi)) {
++ /* rather broken SST cfi probe (requires SST unlock) */
++ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
++ cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
++ cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
++ cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
++ if (!qry_present(map,base,cfi))
++ return 0;
++ }
+
+ if (!cfi->numchips) {
+ /* This is the first time we're called. Set up the CFI
+diff -Nur linux-2.4.30/drivers/mtd/chips/gen_probe.c linux-2.4.30.openwrt/drivers/mtd/chips/gen_probe.c
+--- linux-2.4.30/drivers/mtd/chips/gen_probe.c 2003-08-25 13:44:42.000000000 +0200
++++ linux-2.4.30.openwrt/drivers/mtd/chips/gen_probe.c 2005-06-28 11:29:23.000000000 +0200
+@@ -328,13 +328,18 @@
+ return cfi_cmdset_0001(map, primary);
+ #endif
+ #ifdef CONFIG_MTD_CFI_AMDSTD
++ case 0x0006:
+ case 0x0002:
+ return cfi_cmdset_0002(map, primary);
+ #endif
+ #ifdef CONFIG_MTD_CFI_STAA
+- case 0x0020:
++ case 0x0020:
+ return cfi_cmdset_0020(map, primary);
+ #endif
++#ifdef CONFIG_MTD_CFI_SSTSTD
++ case 0x0701:
++ return cfi_cmdset_0701(map, primary);
++#endif
+ }
+
+ return cfi_cmdset_unknown(map, primary);
diff --git a/target/linux/generic-2.4/patches/006-gcc4_fixes.patch b/target/linux/generic-2.4/patches/006-gcc4_fixes.patch
new file mode 100644
index 0000000000..4034d1b48b
--- /dev/null
+++ b/target/linux/generic-2.4/patches/006-gcc4_fixes.patch
@@ -0,0 +1,522 @@
+diff -rupN linux-2.4.32/Makefile linux-2.4.32.gcc4-fixes-v12/Makefile
+--- linux-2.4.32/Makefile 2005-11-17 13:27:30.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/Makefile 2005-11-17 13:32:13.000000000 +0100
+@@ -93,11 +93,17 @@ CPPFLAGS := -D__KERNEL__ -I$(HPATH)
+
+ CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \
+ -fno-strict-aliasing -fno-common
++CFLAGS += -fno-builtin-sprintf
+ ifndef CONFIG_FRAME_POINTER
+ CFLAGS += -fomit-frame-pointer
+ endif
+ AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)
+
++check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
++
++# disable pointer signedness warnings in gcc 4.0
++CFLAGS += $(call check_gcc,-Wno-pointer-sign,)
++
+ #
+ # ROOT_DEV specifies the default root-device when making the image.
+ # This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case
+diff -rupN linux-2.4.32/arch/i386/Makefile linux-2.4.32.gcc4-fixes-v12/arch/i386/Makefile
+--- linux-2.4.32/arch/i386/Makefile 2004-11-17 18:36:41.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/arch/i386/Makefile 2005-11-17 13:32:13.000000000 +0100
+@@ -23,8 +23,6 @@ LINKFLAGS =-T $(TOPDIR)/arch/i386/vmlinu
+
+ CFLAGS += -pipe
+
+-check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
+-
+ # prevent gcc from keeping the stack 16 byte aligned
+ CFLAGS += $(call check_gcc,-mpreferred-stack-boundary=2,)
+
+diff -rupN linux-2.4.32/arch/mips/Makefile linux-2.4.32.gcc4-fixes-v12/arch/mips/Makefile
+--- linux-2.4.32/arch/mips/Makefile 2005-01-19 18:00:52.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/arch/mips/Makefile 2005-11-17 13:32:13.000000000 +0100
+@@ -30,8 +30,6 @@ endif
+
+ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
+
+-check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
+-
+ #
+ #
+ # GCC uses -G 0 -mabicalls -fpic as default. We don't want PIC in the kernel
+diff -rupN linux-2.4.32/arch/mips64/Makefile linux-2.4.32.gcc4-fixes-v12/arch/mips64/Makefile
+--- linux-2.4.32/arch/mips64/Makefile 2005-01-19 18:00:52.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/arch/mips64/Makefile 2005-11-17 13:32:13.000000000 +0100
+@@ -26,7 +26,6 @@ ifdef CONFIG_CROSSCOMPILE
+ CROSS_COMPILE = $(tool-prefix)
+ endif
+
+-check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
+ check_gas = $(shell if $(CC) $(1) -Wa,-Z -c -o /dev/null -xassembler /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
+
+ #
+diff -rupN linux-2.4.32/arch/ppc/kernel/open_pic_defs.h linux-2.4.32.gcc4-fixes-v12/arch/ppc/kernel/open_pic_defs.h
+--- linux-2.4.32/arch/ppc/kernel/open_pic_defs.h 2003-06-14 13:30:19.000000000 +0200
++++ linux-2.4.32.gcc4-fixes-v12/arch/ppc/kernel/open_pic_defs.h 2005-11-17 13:32:13.000000000 +0100
+@@ -172,9 +172,6 @@ struct OpenPIC {
+ OpenPIC_Processor Processor[OPENPIC_MAX_PROCESSORS];
+ };
+
+-extern volatile struct OpenPIC *OpenPIC;
+-
+-
+ /*
+ * Current Task Priority Register
+ */
+diff -rupN linux-2.4.32/arch/x86_64/Makefile linux-2.4.32.gcc4-fixes-v12/arch/x86_64/Makefile
+--- linux-2.4.32/arch/x86_64/Makefile 2004-04-14 20:22:20.000000000 +0200
++++ linux-2.4.32.gcc4-fixes-v12/arch/x86_64/Makefile 2005-11-17 13:32:13.000000000 +0100
+@@ -38,8 +38,6 @@ OBJCOPY=$(CROSS_COMPILE)objcopy -O binar
+ LDFLAGS=-e stext
+ LINKFLAGS =-T $(TOPDIR)/arch/x86_64/vmlinux.lds $(LDFLAGS)
+
+-check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1 ; then echo "$(1)"; else echo "$(2)"; fi)
+-
+ CFLAGS += -mno-red-zone
+ CFLAGS += -mcmodel=kernel
+ CFLAGS += -pipe
+diff -rupN linux-2.4.32/arch/x86_64/ia32/ia32entry.S linux-2.4.32.gcc4-fixes-v12/arch/x86_64/ia32/ia32entry.S
+--- linux-2.4.32/arch/x86_64/ia32/ia32entry.S 2005-01-19 18:00:53.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/arch/x86_64/ia32/ia32entry.S 2005-11-17 13:32:13.000000000 +0100
+@@ -113,9 +113,18 @@ quiet_ni_syscall:
+ PTREGSCALL stub32_fork, sys32_fork
+ PTREGSCALL stub32_clone, sys32_clone
+ PTREGSCALL stub32_vfork, sys32_vfork
+- PTREGSCALL stub32_iopl, sys_iopl
+ PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend
+
++ .macro PTREGSCALL3 label, func, arg
++ .globl \label
++\label:
++ leaq \func(%rip),%rax
++ leaq -ARGOFFSET+8(%rsp),\arg /* 8 for return address */
++ jmp ia32_ptregs_common
++ .endm
++
++ PTREGSCALL3 stub32_iopl, sys_iopl, %rsi
++
+ ENTRY(ia32_ptregs_common)
+ popq %r11
+ SAVE_REST
+diff -rupN linux-2.4.32/arch/x86_64/kernel/entry.S linux-2.4.32.gcc4-fixes-v12/arch/x86_64/kernel/entry.S
+--- linux-2.4.32/arch/x86_64/kernel/entry.S 2003-11-29 00:28:11.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/arch/x86_64/kernel/entry.S 2005-11-17 13:32:13.000000000 +0100
+@@ -249,7 +249,16 @@ intret_signal_test:
+ PTREGSCALL stub_vfork, sys_vfork
+ PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend
+ PTREGSCALL stub_sigaltstack, sys_sigaltstack
+- PTREGSCALL stub_iopl, sys_iopl
++
++ .macro PTREGSCALL3 label,func,arg
++ .globl \label
++\label:
++ leaq \func(%rip),%rax
++ leaq -ARGOFFSET+8(%rsp),\arg /* 8 for return address */
++ jmp ptregscall_common
++ .endm
++
++ PTREGSCALL3 stub_iopl, sys_iopl, %rsi
+
+ ENTRY(ptregscall_common)
+ popq %r11
+diff -rupN linux-2.4.32/arch/x86_64/kernel/ioport.c linux-2.4.32.gcc4-fixes-v12/arch/x86_64/kernel/ioport.c
+--- linux-2.4.32/arch/x86_64/kernel/ioport.c 2003-11-29 00:28:11.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/arch/x86_64/kernel/ioport.c 2005-11-17 13:32:13.000000000 +0100
+@@ -81,9 +81,9 @@ asmlinkage long sys_ioperm(unsigned long
+ * code.
+ */
+
+-asmlinkage long sys_iopl(unsigned int level, struct pt_regs regs)
++asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs)
+ {
+- unsigned int old = (regs.eflags >> 12) & 3;
++ unsigned int old = (regs->eflags >> 12) & 3;
+
+ if (level > 3)
+ return -EINVAL;
+@@ -92,6 +92,6 @@ asmlinkage long sys_iopl(unsigned int le
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ }
+- regs.eflags = (regs.eflags & 0xffffffffffffcfff) | (level << 12);
++ regs->eflags = (regs->eflags &~ 0x3000UL) | (level << 12);
+ return 0;
+ }
+diff -rupN linux-2.4.32/drivers/acpi/bus.c linux-2.4.32.gcc4-fixes-v12/drivers/acpi/bus.c
+--- linux-2.4.32/drivers/acpi/bus.c 2005-01-19 18:00:53.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/drivers/acpi/bus.c 2005-11-17 13:32:13.000000000 +0100
+@@ -623,7 +623,7 @@ acpi_bus_generate_event (
+ int data)
+ {
+ struct acpi_bus_event *event = NULL;
+- u32 flags = 0;
++ unsigned long flags = 0;
+
+ ACPI_FUNCTION_TRACE("acpi_bus_generate_event");
+
+@@ -656,7 +656,7 @@ int
+ acpi_bus_receive_event (
+ struct acpi_bus_event *event)
+ {
+- u32 flags = 0;
++ unsigned long flags = 0;
+ struct acpi_bus_event *entry = NULL;
+
+ DECLARE_WAITQUEUE(wait, current);
+diff -rupN linux-2.4.32/drivers/sound/sound_firmware.c linux-2.4.32.gcc4-fixes-v12/drivers/sound/sound_firmware.c
+--- linux-2.4.32/drivers/sound/sound_firmware.c 2001-02-22 15:23:46.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/drivers/sound/sound_firmware.c 2005-11-17 13:32:13.000000000 +0100
+@@ -4,10 +4,11 @@
+ #include <linux/fs.h>
+ #include <linux/mm.h>
+ #include <linux/slab.h>
+-#include <linux/unistd.h>
++static int my_errno;
++#define errno my_errno
++#include <asm/unistd.h>
+ #include <asm/uaccess.h>
+
+-static int errno;
+ static int do_mod_firmware_load(const char *fn, char **fp)
+ {
+ int fd;
+diff -rupN linux-2.4.32/drivers/usb/host/ehci-q.c linux-2.4.32.gcc4-fixes-v12/drivers/usb/host/ehci-q.c
+--- linux-2.4.32/drivers/usb/host/ehci-q.c 2005-01-19 18:00:53.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/drivers/usb/host/ehci-q.c 2005-11-17 13:32:13.000000000 +0100
+@@ -199,8 +199,6 @@ ehci_urb_done (struct ehci_hcd *ehci, st
+ #ifdef INTR_AUTOMAGIC
+ struct urb *resubmit = 0;
+ struct usb_device *dev = 0;
+-
+- static int ehci_urb_enqueue (struct usb_hcd *, struct urb *, int);
+ #endif
+
+ if (likely (urb->hcpriv != 0)) {
+diff -rupN linux-2.4.32/drivers/usb/inode.c linux-2.4.32.gcc4-fixes-v12/drivers/usb/inode.c
+--- linux-2.4.32/drivers/usb/inode.c 2004-02-18 15:16:23.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/drivers/usb/inode.c 2005-11-17 13:32:13.000000000 +0100
+@@ -41,6 +41,9 @@
+ #include <linux/usbdevice_fs.h>
+ #include <asm/uaccess.h>
+
++static struct inode_operations usbdevfs_bus_inode_operations;
++static struct file_operations usbdevfs_bus_file_operations;
++
+ /* --------------------------------------------------------------------- */
+
+ /*
+diff -rupN linux-2.4.32/fs/hfs/trans.c linux-2.4.32.gcc4-fixes-v12/fs/hfs/trans.c
+--- linux-2.4.32/fs/hfs/trans.c 2001-02-22 15:23:47.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/fs/hfs/trans.c 2005-11-17 13:32:13.000000000 +0100
+@@ -33,6 +33,7 @@
+ #include <linux/hfs_fs_sb.h>
+ #include <linux/hfs_fs_i.h>
+ #include <linux/hfs_fs.h>
++#include <linux/compiler.h>
+
+ /*================ File-local variables ================*/
+
+@@ -78,7 +79,7 @@ static unsigned char mac2latin_map[128]
+ *
+ * Given a hexadecimal digit in ASCII, return the integer representation.
+ */
+-static inline const unsigned char dehex(char c) {
++static inline __attribute_const__ unsigned char dehex(char c) {
+ if ((c>='0')&&(c<='9')) {
+ return c-'0';
+ }
+diff -rupN linux-2.4.32/include/asm-i386/byteorder.h linux-2.4.32.gcc4-fixes-v12/include/asm-i386/byteorder.h
+--- linux-2.4.32/include/asm-i386/byteorder.h 2003-06-14 13:30:27.000000000 +0200
++++ linux-2.4.32.gcc4-fixes-v12/include/asm-i386/byteorder.h 2005-11-17 13:32:13.000000000 +0100
+@@ -2,6 +2,7 @@
+ #define _I386_BYTEORDER_H
+
+ #include <asm/types.h>
++#include <linux/compiler.h>
+
+ #ifdef __GNUC__
+
+@@ -10,7 +11,7 @@
+ #include <linux/config.h>
+ #endif
+
+-static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
++static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
+ {
+ #ifdef CONFIG_X86_BSWAP
+ __asm__("bswap %0" : "=r" (x) : "0" (x));
+@@ -26,7 +27,7 @@ static __inline__ __const__ __u32 ___arc
+
+ /* gcc should generate this for open coded C now too. May be worth switching to
+ it because inline assembly cannot be scheduled. -AK */
+-static __inline__ __const__ __u16 ___arch__swab16(__u16 x)
++static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
+ {
+ __asm__("xchgb %b0,%h0" /* swap bytes */
+ : "=q" (x)
+diff -rupN linux-2.4.32/include/asm-i386/processor.h linux-2.4.32.gcc4-fixes-v12/include/asm-i386/processor.h
+--- linux-2.4.32/include/asm-i386/processor.h 2004-02-18 15:16:24.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/include/asm-i386/processor.h 2005-11-17 13:32:13.000000000 +0100
+@@ -72,7 +72,6 @@ struct cpuinfo_x86 {
+ */
+
+ extern struct cpuinfo_x86 boot_cpu_data;
+-extern struct tss_struct init_tss[NR_CPUS];
+
+ #ifdef CONFIG_SMP
+ extern struct cpuinfo_x86 cpu_data[];
+@@ -357,6 +356,8 @@ struct tss_struct {
+ unsigned long __cacheline_filler[5];
+ };
+
++extern struct tss_struct init_tss[NR_CPUS];
++
+ struct thread_struct {
+ unsigned long esp0;
+ unsigned long eip;
+diff -rupN linux-2.4.32/include/asm-i386/string.h linux-2.4.32.gcc4-fixes-v12/include/asm-i386/string.h
+--- linux-2.4.32/include/asm-i386/string.h 2001-08-12 11:35:53.000000000 +0200
++++ linux-2.4.32.gcc4-fixes-v12/include/asm-i386/string.h 2005-11-17 13:32:13.000000000 +0100
+@@ -337,7 +337,7 @@ extern void __struct_cpy_bug (void);
+ #define struct_cpy(x,y) \
+ ({ \
+ if (sizeof(*(x)) != sizeof(*(y))) \
+- __struct_cpy_bug; \
++ __struct_cpy_bug(); \
+ memcpy(x, y, sizeof(*(x))); \
+ })
+
+diff -rupN linux-2.4.32/include/asm-m68k/setup.h linux-2.4.32.gcc4-fixes-v12/include/asm-m68k/setup.h
+--- linux-2.4.32/include/asm-m68k/setup.h 2000-01-29 13:07:40.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/include/asm-m68k/setup.h 2005-11-17 13:32:13.000000000 +0100
+@@ -361,12 +361,13 @@ extern int m68k_is040or060;
+ #ifndef __ASSEMBLY__
+ extern int m68k_num_memory; /* # of memory blocks found (and used) */
+ extern int m68k_realnum_memory; /* real # of memory blocks found */
+-extern struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
+
+ struct mem_info {
+ unsigned long addr; /* physical address of memory chunk */
+ unsigned long size; /* length of memory chunk (in bytes) */
+ };
++
++extern struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
+ #endif
+
+ #endif /* __KERNEL__ */
+diff -rupN linux-2.4.32/include/asm-ppc/byteorder.h linux-2.4.32.gcc4-fixes-v12/include/asm-ppc/byteorder.h
+--- linux-2.4.32/include/asm-ppc/byteorder.h 2003-06-14 13:30:28.000000000 +0200
++++ linux-2.4.32.gcc4-fixes-v12/include/asm-ppc/byteorder.h 2005-11-17 13:32:13.000000000 +0100
+@@ -2,6 +2,7 @@
+ #define _PPC_BYTEORDER_H
+
+ #include <asm/types.h>
++#include <linux/compiler.h>
+
+ #ifdef __GNUC__
+ #ifdef __KERNEL__
+@@ -50,7 +51,7 @@ extern __inline__ void st_le64(volatile
+ __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (taddr+4));
+ }
+
+-static __inline__ __const__ __u16 ___arch__swab16(__u16 value)
++static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 value)
+ {
+ __u16 result;
+
+@@ -58,7 +59,7 @@ static __inline__ __const__ __u16 ___arc
+ return result;
+ }
+
+-static __inline__ __const__ __u32 ___arch__swab32(__u32 value)
++static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 value)
+ {
+ __u32 result;
+
+diff -rupN linux-2.4.32/include/asm-ppc/time.h linux-2.4.32.gcc4-fixes-v12/include/asm-ppc/time.h
+--- linux-2.4.32/include/asm-ppc/time.h 2003-08-25 20:07:49.000000000 +0200
++++ linux-2.4.32.gcc4-fixes-v12/include/asm-ppc/time.h 2005-11-17 13:32:13.000000000 +0100
+@@ -12,6 +12,7 @@
+ #include <linux/config.h>
+ #include <linux/mc146818rtc.h>
+ #include <linux/threads.h>
++#include <linux/compiler.h>
+
+ #include <asm/processor.h>
+
+@@ -57,7 +58,7 @@ static __inline__ void set_dec(unsigned
+ /* Accessor functions for the timebase (RTC on 601) registers. */
+ /* If one day CONFIG_POWER is added just define __USE_RTC as 1 */
+ #ifdef CONFIG_6xx
+-extern __inline__ int const __USE_RTC(void) {
++extern __inline__ int __attribute_const__ __USE_RTC(void) {
+ return (mfspr(SPRN_PVR)>>16) == 1;
+ }
+ #else
+diff -rupN linux-2.4.32/include/asm-x86_64/byteorder.h linux-2.4.32.gcc4-fixes-v12/include/asm-x86_64/byteorder.h
+--- linux-2.4.32/include/asm-x86_64/byteorder.h 2002-11-30 17:12:31.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/include/asm-x86_64/byteorder.h 2005-11-17 13:32:13.000000000 +0100
+@@ -2,16 +2,17 @@
+ #define _X86_64_BYTEORDER_H
+
+ #include <asm/types.h>
++#include <linux/compiler.h>
+
+ #ifdef __GNUC__
+
+-static __inline__ __const__ __u64 ___arch__swab64(__u64 x)
++static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 x)
+ {
+ __asm__("bswapq %0" : "=r" (x) : "0" (x));
+ return x;
+ }
+
+-static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
++static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
+ {
+ __asm__("bswapl %0" : "=r" (x) : "0" (x));
+ return x;
+diff -rupN linux-2.4.32/include/asm-x86_64/processor.h linux-2.4.32.gcc4-fixes-v12/include/asm-x86_64/processor.h
+--- linux-2.4.32/include/asm-x86_64/processor.h 2005-11-17 13:27:30.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/include/asm-x86_64/processor.h 2005-11-17 13:32:13.000000000 +0100
+@@ -68,7 +68,6 @@ struct cpuinfo_x86 {
+ #define X86_VENDOR_UNKNOWN 0xff
+
+ extern struct cpuinfo_x86 boot_cpu_data;
+-extern struct tss_struct init_tss[NR_CPUS];
+
+ #ifdef CONFIG_SMP
+ extern struct cpuinfo_x86 cpu_data[];
+@@ -300,6 +299,8 @@ struct tss_struct {
+ u32 io_bitmap[IO_BITMAP_SIZE];
+ } __attribute__((packed)) ____cacheline_aligned;
+
++extern struct tss_struct init_tss[NR_CPUS];
++
+ struct thread_struct {
+ unsigned long rsp0;
+ unsigned long rip;
+diff -rupN linux-2.4.32/include/linux/byteorder/swab.h linux-2.4.32.gcc4-fixes-v12/include/linux/byteorder/swab.h
+--- linux-2.4.32/include/linux/byteorder/swab.h 2002-11-30 17:12:31.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/include/linux/byteorder/swab.h 2005-11-17 13:32:13.000000000 +0100
+@@ -15,6 +15,8 @@
+ *
+ */
+
++#include <linux/compiler.h>
++
+ /* casts are necessary for constants, because we never know how for sure
+ * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way.
+ */
+@@ -156,7 +158,7 @@
+ #endif /* OPTIMIZE */
+
+
+-static __inline__ __const__ __u16 __fswab16(__u16 x)
++static __inline__ __attribute_const__ __u16 __fswab16(__u16 x)
+ {
+ return __arch__swab16(x);
+ }
+@@ -169,7 +171,7 @@ static __inline__ void __swab16s(__u16 *
+ __arch__swab16s(addr);
+ }
+
+-static __inline__ __const__ __u32 __fswab24(__u32 x)
++static __inline__ __attribute_const__ __u32 __fswab24(__u32 x)
+ {
+ return __arch__swab24(x);
+ }
+@@ -182,7 +184,7 @@ static __inline__ void __swab24s(__u32 *
+ __arch__swab24s(addr);
+ }
+
+-static __inline__ __const__ __u32 __fswab32(__u32 x)
++static __inline__ __attribute_const__ __u32 __fswab32(__u32 x)
+ {
+ return __arch__swab32(x);
+ }
+@@ -196,7 +198,7 @@ static __inline__ void __swab32s(__u32 *
+ }
+
+ #ifdef __BYTEORDER_HAS_U64__
+-static __inline__ __const__ __u64 __fswab64(__u64 x)
++static __inline__ __attribute_const__ __u64 __fswab64(__u64 x)
+ {
+ # ifdef __SWAB_64_THRU_32__
+ __u32 h = x >> 32;
+diff -rupN linux-2.4.32/include/linux/compiler.h linux-2.4.32.gcc4-fixes-v12/include/linux/compiler.h
+--- linux-2.4.32/include/linux/compiler.h 2004-11-17 18:36:42.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/include/linux/compiler.h 2005-11-17 13:32:13.000000000 +0100
+@@ -27,6 +27,12 @@
+ #define __attribute_used__ /* not implemented */
+ #endif /* __GNUC__ */
+
++#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
++#define __attribute_const__ __attribute__((__const__))
++#else
++#define __attribute_const__ /* unimplemented */
++#endif
++
+ #if __GNUC__ == 3
+ #if __GNUC_MINOR__ >= 1
+ # define inline __inline__ __attribute__((always_inline))
+diff -rupN linux-2.4.32/include/linux/fs.h linux-2.4.32.gcc4-fixes-v12/include/linux/fs.h
+--- linux-2.4.32/include/linux/fs.h 2005-04-04 19:56:05.000000000 +0200
++++ linux-2.4.32.gcc4-fixes-v12/include/linux/fs.h 2005-11-17 13:32:13.000000000 +0100
+@@ -1559,7 +1559,6 @@ static inline int is_mounted(kdev_t dev)
+ unsigned long generate_cluster(kdev_t, int b[], int);
+ unsigned long generate_cluster_swab32(kdev_t, int b[], int);
+ extern kdev_t ROOT_DEV;
+-extern char root_device_name[];
+
+
+ extern void show_buffers(void);
+diff -rupN linux-2.4.32/include/linux/ufs_fs.h linux-2.4.32.gcc4-fixes-v12/include/linux/ufs_fs.h
+--- linux-2.4.32/include/linux/ufs_fs.h 2001-11-23 22:40:15.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/include/linux/ufs_fs.h 2005-11-17 13:32:13.000000000 +0100
+@@ -555,7 +555,6 @@ extern struct buffer_head * ufs_bread (s
+ extern struct file_operations ufs_dir_operations;
+
+ /* super.c */
+-extern struct file_system_type ufs_fs_type;
+ extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
+ extern void ufs_error (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
+ extern void ufs_panic (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
+diff -rupN linux-2.4.32/include/linux/usbdevice_fs.h linux-2.4.32.gcc4-fixes-v12/include/linux/usbdevice_fs.h
+--- linux-2.4.32/include/linux/usbdevice_fs.h 2003-11-29 00:28:14.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/include/linux/usbdevice_fs.h 2005-11-17 13:32:13.000000000 +0100
+@@ -185,8 +185,6 @@ extern struct file_operations usbdevfs_d
+ extern struct file_operations usbdevfs_devices_fops;
+ extern struct file_operations usbdevfs_device_file_operations;
+ extern struct inode_operations usbdevfs_device_inode_operations;
+-extern struct inode_operations usbdevfs_bus_inode_operations;
+-extern struct file_operations usbdevfs_bus_file_operations;
+ extern void usbdevfs_conn_disc_event(void);
+
+ #endif /* __KERNEL__ */
+diff -rupN linux-2.4.32/include/net/icmp.h linux-2.4.32.gcc4-fixes-v12/include/net/icmp.h
+--- linux-2.4.32/include/net/icmp.h 2001-04-28 12:35:26.000000000 +0200
++++ linux-2.4.32.gcc4-fixes-v12/include/net/icmp.h 2005-11-17 13:32:13.000000000 +0100
+@@ -23,6 +23,7 @@
+
+ #include <net/sock.h>
+ #include <net/protocol.h>
++#include <net/snmp.h>
+
+ struct icmp_err {
+ int errno;
+diff -rupN linux-2.4.32/include/net/ipv6.h linux-2.4.32.gcc4-fixes-v12/include/net/ipv6.h
+--- linux-2.4.32/include/net/ipv6.h 2004-11-17 18:36:43.000000000 +0100
++++ linux-2.4.32.gcc4-fixes-v12/include/net/ipv6.h 2005-11-17 13:32:13.000000000 +0100
+@@ -101,6 +101,7 @@ struct frag_hdr {
+ #ifdef __KERNEL__
+
+ #include <net/sock.h>
++#include <net/snmp.h>
+
+ /* sysctls */
+ extern int sysctl_ipv6_bindv6only;
diff --git a/target/linux/generic-2.4/patches/007-more_gcc4_fixes.patch b/target/linux/generic-2.4/patches/007-more_gcc4_fixes.patch
new file mode 100644
index 0000000000..b234c7028c
--- /dev/null
+++ b/target/linux/generic-2.4/patches/007-more_gcc4_fixes.patch
@@ -0,0 +1,1339 @@
+diff -rupN linux-2.4.32/drivers/atm/fore200e.c linux-2.4.32.more-gcc4-fixes-v1/drivers/atm/fore200e.c
+--- linux-2.4.32/drivers/atm/fore200e.c 2004-11-17 18:36:41.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/atm/fore200e.c 2005-11-17 13:31:16.000000000 +0100
+@@ -112,8 +112,8 @@
+ #endif
+
+
+-extern const struct atmdev_ops fore200e_ops;
+-extern const struct fore200e_bus fore200e_bus[];
++static const struct atmdev_ops fore200e_ops;
++static const struct fore200e_bus fore200e_bus[];
+
+ static struct fore200e* fore200e_boards = NULL;
+
+diff -rupN linux-2.4.32/drivers/atm/horizon.c linux-2.4.32.more-gcc4-fixes-v1/drivers/atm/horizon.c
+--- linux-2.4.32/drivers/atm/horizon.c 2004-02-18 15:16:22.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/atm/horizon.c 2005-11-17 13:31:16.000000000 +0100
+@@ -481,6 +481,7 @@ static inline void dump_skb (char * pref
+ return;
+ }
+
++#if 0 /* unused and in conflict with <asm-ppc/system.h> */
+ static inline void dump_regs (hrz_dev * dev) {
+ #ifdef DEBUG_HORIZON
+ PRINTD (DBG_REGS, "CONTROL 0: %#x", rd_regl (dev, CONTROL_0_REG));
+@@ -494,6 +495,7 @@ static inline void dump_regs (hrz_dev *
+ #endif
+ return;
+ }
++#endif
+
+ static inline void dump_framer (hrz_dev * dev) {
+ #ifdef DEBUG_HORIZON
+diff -rupN linux-2.4.32/drivers/atm/iphase.c linux-2.4.32.more-gcc4-fixes-v1/drivers/atm/iphase.c
+--- linux-2.4.32/drivers/atm/iphase.c 2004-11-17 18:36:41.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/atm/iphase.c 2005-11-17 13:31:16.000000000 +0100
+@@ -82,6 +82,7 @@ static IADEV *ia_dev[8];
+ static struct atm_dev *_ia_dev[8];
+ static int iadev_count;
+ static void ia_led_timer(unsigned long arg);
++static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb);
+ static struct timer_list ia_timer = { function: ia_led_timer };
+ struct atm_vcc *vcc_close_que[100];
+ static int IA_TX_BUF = DFL_TX_BUFFERS, IA_TX_BUF_SZ = DFL_TX_BUF_SZ;
+@@ -627,7 +628,6 @@ static int ia_que_tx (IADEV *iadev) {
+ int num_desc;
+ struct atm_vcc *vcc;
+ struct ia_vcc *iavcc;
+- static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb);
+ num_desc = ia_avail_descs(iadev);
+ while (num_desc && (skb = skb_dequeue(&iadev->tx_backlog))) {
+ if (!(vcc = ATM_SKB(skb)->vcc)) {
+diff -rupN linux-2.4.32/drivers/atm/iphase.h linux-2.4.32.more-gcc4-fixes-v1/drivers/atm/iphase.h
+--- linux-2.4.32/drivers/atm/iphase.h 2003-06-14 13:30:20.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/atm/iphase.h 2005-11-17 13:31:16.000000000 +0100
+@@ -68,8 +68,6 @@
+ #define IF_IADBG_SUNI_STAT 0x02000000 // suni statistics
+ #define IF_IADBG_RESET 0x04000000
+
+-extern unsigned int IADebugFlag;
+-
+ #define IF_IADBG(f) if (IADebugFlag & (f))
+
+ #ifdef CONFIG_ATM_IA_DEBUG /* Debug build */
+diff -rupN linux-2.4.32/drivers/block/nbd.c linux-2.4.32.more-gcc4-fixes-v1/drivers/block/nbd.c
+--- linux-2.4.32/drivers/block/nbd.c 2005-04-04 19:56:04.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/block/nbd.c 2005-11-17 13:31:16.000000000 +0100
+@@ -74,6 +74,29 @@ static int requests_in;
+ static int requests_out;
+ #endif
+
++static void
++nbd_end_request(struct request *req)
++{
++ struct buffer_head *bh;
++ unsigned nsect;
++ unsigned long flags;
++ int uptodate = (req->errors == 0) ? 1 : 0;
++
++#ifdef PARANOIA
++ requests_out++;
++#endif
++ spin_lock_irqsave(&io_request_lock, flags);
++ while((bh = req->bh) != NULL) {
++ nsect = bh->b_size >> 9;
++ blk_finished_io(nsect);
++ req->bh = bh->b_reqnext;
++ bh->b_reqnext = NULL;
++ bh->b_end_io(bh, uptodate);
++ }
++ blkdev_release_request(req);
++ spin_unlock_irqrestore(&io_request_lock, flags);
++}
++
+ static int nbd_open(struct inode *inode, struct file *file)
+ {
+ int dev;
+diff -rupN linux-2.4.32/drivers/block/paride/pd.c linux-2.4.32.more-gcc4-fixes-v1/drivers/block/paride/pd.c
+--- linux-2.4.32/drivers/block/paride/pd.c 2002-11-30 17:12:24.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/block/paride/pd.c 2005-11-17 13:31:16.000000000 +0100
+@@ -343,7 +343,14 @@ static char *pd_errs[17] = { "ERR","INDE
+
+ /* kernel glue structures */
+
+-extern struct block_device_operations pd_fops;
++static struct block_device_operations pd_fops = {
++ owner: THIS_MODULE,
++ open: pd_open,
++ release: pd_release,
++ ioctl: pd_ioctl,
++ check_media_change: pd_check_media,
++ revalidate: pd_revalidate
++};
+
+ static struct gendisk pd_gendisk = {
+ major: PD_MAJOR,
+@@ -355,15 +362,6 @@ static struct gendisk pd_gendisk = {
+ fops: &pd_fops,
+ };
+
+-static struct block_device_operations pd_fops = {
+- owner: THIS_MODULE,
+- open: pd_open,
+- release: pd_release,
+- ioctl: pd_ioctl,
+- check_media_change: pd_check_media,
+- revalidate: pd_revalidate
+-};
+-
+ void pd_init_units( void )
+
+ { int unit, j;
+diff -rupN linux-2.4.32/drivers/block/xd.c linux-2.4.32.more-gcc4-fixes-v1/drivers/block/xd.c
+--- linux-2.4.32/drivers/block/xd.c 2002-11-30 17:12:24.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/block/xd.c 2005-11-17 13:31:16.000000000 +0100
+@@ -125,7 +125,12 @@ static int xd_sizes[XD_MAXDRIVES << 6],
+ static int xd_blocksizes[XD_MAXDRIVES << 6];
+ static int xd_maxsect[XD_MAXDRIVES << 6];
+
+-extern struct block_device_operations xd_fops;
++static struct block_device_operations xd_fops = {
++ owner: THIS_MODULE,
++ open: xd_open,
++ release: xd_release,
++ ioctl: xd_ioctl,
++};
+
+ static struct gendisk xd_gendisk = {
+ major: MAJOR_NR,
+@@ -138,13 +143,6 @@ static struct gendisk xd_gendisk = {
+ fops: &xd_fops,
+ };
+
+-static struct block_device_operations xd_fops = {
+- owner: THIS_MODULE,
+- open: xd_open,
+- release: xd_release,
+- ioctl: xd_ioctl,
+-};
+-
+ static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int);
+ static DECLARE_WAIT_QUEUE_HEAD(xd_wait_open);
+ static u8 xd_valid[XD_MAXDRIVES] = { 0,0 };
+diff -rupN linux-2.4.32/drivers/cdrom/sbpcd.c linux-2.4.32.more-gcc4-fixes-v1/drivers/cdrom/sbpcd.c
+--- linux-2.4.32/drivers/cdrom/sbpcd.c 2001-11-06 12:12:06.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/cdrom/sbpcd.c 2005-11-17 13:31:16.000000000 +0100
+@@ -525,6 +525,8 @@ static int sbp_data(struct request *req)
+ static int cmd_out(void);
+ static int DiskInfo(void);
+ static int sbpcd_chk_disk_change(kdev_t);
++static int cmd_out_T(void);
++static int cc_DriveReset(void);
+
+ /*==========================================================================*/
+
+@@ -1213,8 +1215,6 @@ static int get_state_T(void)
+ {
+ int i;
+
+- static int cmd_out_T(void);
+-
+ clr_cmdbuf();
+ D_S[d].n_bytes=1;
+ drvcmd[0]=CMDT_STATUS;
+@@ -1362,7 +1362,6 @@ static int cmd_out_T(void)
+ #define CMDT_TRIES 1000
+ #define TEST_FALSE_FF 1
+
+- static int cc_DriveReset(void);
+ int i, j, l=0, m, ntries;
+ long flags;
+
+diff -rupN linux-2.4.32/drivers/char/ip2/i2lib.c linux-2.4.32.more-gcc4-fixes-v1/drivers/char/ip2/i2lib.c
+--- linux-2.4.32/drivers/char/ip2/i2lib.c 2005-01-19 18:00:53.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/char/ip2/i2lib.c 2005-11-17 13:31:16.000000000 +0100
+@@ -1262,7 +1262,7 @@ i2RetryFlushOutput(i2ChanStrPtr pCh)
+
+ }
+ if ( old_flags & STOPFL_FLAG ) {
+- if ( 1 == i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL) > 0 ) {
++ if ( 1 == i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL)) {
+ old_flags = 0; // Success - clear flags
+ }
+
+diff -rupN linux-2.4.32/drivers/char/rio/rio_linux.c linux-2.4.32.more-gcc4-fixes-v1/drivers/char/rio/rio_linux.c
+--- linux-2.4.32/drivers/char/rio/rio_linux.c 2002-02-26 13:26:56.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/char/rio/rio_linux.c 2005-11-17 13:31:16.000000000 +0100
+@@ -1205,8 +1205,8 @@ static int __init rio_init(void)
+ hp->Ivec = get_irq (pdev);
+ if (((1 << hp->Ivec) & rio_irqmask) == 0)
+ hp->Ivec = 0;
+- hp->CardP = (struct DpRam *)
+ hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
++ hp->CardP = (struct DpRam *) hp->Caddr;
+ hp->Type = RIO_PCI;
+ hp->Copy = rio_pcicopy;
+ hp->Mode = RIO_PCI_BOOT_FROM_RAM;
+@@ -1277,8 +1277,8 @@ static int __init rio_init(void)
+ if (((1 << hp->Ivec) & rio_irqmask) == 0)
+ hp->Ivec = 0;
+ hp->Ivec |= 0x8000; /* Mark as non-sharable */
+- hp->CardP = (struct DpRam *)
+ hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
++ hp->CardP = (struct DpRam *) hp->Caddr;
+ hp->Type = RIO_PCI;
+ hp->Copy = rio_pcicopy;
+ hp->Mode = RIO_PCI_BOOT_FROM_RAM;
+@@ -1329,8 +1329,8 @@ static int __init rio_init(void)
+ hp->PaddrP = rio_probe_addrs[i];
+ /* There was something about the IRQs of these cards. 'Forget what.--REW */
+ hp->Ivec = 0;
+- hp->CardP = (struct DpRam *)
+ hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
++ hp->CardP = (struct DpRam *) hp->Caddr;
+ hp->Type = RIO_AT;
+ hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL
+ * -- YES! this is now a normal copy. Only the
+diff -rupN linux-2.4.32/drivers/char/sonypi.c linux-2.4.32.more-gcc4-fixes-v1/drivers/char/sonypi.c
+--- linux-2.4.32/drivers/char/sonypi.c 2004-04-14 20:22:20.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/char/sonypi.c 2005-11-17 13:31:16.000000000 +0100
+@@ -60,6 +60,35 @@ static int compat; /* = 0 */
+ static int useinput = 1;
+ static unsigned long mask = 0xffffffff;
+
++static inline int sonypi_ec_write(u8 addr, u8 value) {
++#ifdef CONFIG_ACPI_EC
++ if (SONYPI_ACPI_ACTIVE)
++ return ec_write(addr, value);
++#endif
++ wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3, ITERATIONS_LONG);
++ outb_p(0x81, SONYPI_CST_IOPORT);
++ wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
++ outb_p(addr, SONYPI_DATA_IOPORT);
++ wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
++ outb_p(value, SONYPI_DATA_IOPORT);
++ wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
++ return 0;
++}
++
++static inline int sonypi_ec_read(u8 addr, u8 *value) {
++#ifdef CONFIG_ACPI_EC
++ if (SONYPI_ACPI_ACTIVE)
++ return ec_read(addr, value);
++#endif
++ wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3, ITERATIONS_LONG);
++ outb_p(0x80, SONYPI_CST_IOPORT);
++ wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
++ outb_p(addr, SONYPI_DATA_IOPORT);
++ wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
++ *value = inb_p(SONYPI_DATA_IOPORT);
++ return 0;
++}
++
+ /* Inits the queue */
+ static inline void sonypi_initq(void) {
+ sonypi_device.queue.head = sonypi_device.queue.tail = 0;
+diff -rupN linux-2.4.32/drivers/char/sonypi.h linux-2.4.32.more-gcc4-fixes-v1/drivers/char/sonypi.h
+--- linux-2.4.32/drivers/char/sonypi.h 2004-04-14 20:22:20.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/char/sonypi.h 2005-11-17 13:31:16.000000000 +0100
+@@ -401,37 +401,6 @@ struct sonypi_device {
+ #define SONYPI_ACPI_ACTIVE 0
+ #endif /* CONFIG_ACPI */
+
+-extern int verbose;
+-
+-static inline int sonypi_ec_write(u8 addr, u8 value) {
+-#ifdef CONFIG_ACPI_EC
+- if (SONYPI_ACPI_ACTIVE)
+- return ec_write(addr, value);
+-#endif
+- wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3, ITERATIONS_LONG);
+- outb_p(0x81, SONYPI_CST_IOPORT);
+- wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
+- outb_p(addr, SONYPI_DATA_IOPORT);
+- wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
+- outb_p(value, SONYPI_DATA_IOPORT);
+- wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
+- return 0;
+-}
+-
+-static inline int sonypi_ec_read(u8 addr, u8 *value) {
+-#ifdef CONFIG_ACPI_EC
+- if (SONYPI_ACPI_ACTIVE)
+- return ec_read(addr, value);
+-#endif
+- wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3, ITERATIONS_LONG);
+- outb_p(0x80, SONYPI_CST_IOPORT);
+- wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
+- outb_p(addr, SONYPI_DATA_IOPORT);
+- wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
+- *value = inb_p(SONYPI_DATA_IOPORT);
+- return 0;
+-}
+-
+ #endif /* __KERNEL__ */
+
+ #endif /* _SONYPI_PRIV_H_ */
+diff -rupN linux-2.4.32/drivers/char/sx.c linux-2.4.32.more-gcc4-fixes-v1/drivers/char/sx.c
+--- linux-2.4.32/drivers/char/sx.c 2005-01-19 18:00:53.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/char/sx.c 2005-11-17 13:31:16.000000000 +0100
+@@ -522,13 +522,13 @@ static int sx_busy_wait_eq (struct sx_bo
+
+ func_enter ();
+
+- for (i=0; i < TIMEOUT_1 > 0;i++)
++ for (i=0; i < TIMEOUT_1 ;i++)
+ if ((read_sx_byte (board, offset) & mask) == correctval) {
+ func_exit ();
+ return 1;
+ }
+
+- for (i=0; i < TIMEOUT_2 > 0;i++) {
++ for (i=0; i < TIMEOUT_2 ;i++) {
+ if ((read_sx_byte (board, offset) & mask) == correctval) {
+ func_exit ();
+ return 1;
+@@ -548,13 +548,13 @@ static int sx_busy_wait_neq (struct sx_b
+
+ func_enter ();
+
+- for (i=0; i < TIMEOUT_1 > 0;i++)
++ for (i=0; i < TIMEOUT_1 ;i++)
+ if ((read_sx_byte (board, offset) & mask) != badval) {
+ func_exit ();
+ return 1;
+ }
+
+- for (i=0; i < TIMEOUT_2 > 0;i++) {
++ for (i=0; i < TIMEOUT_2 ;i++) {
+ if ((read_sx_byte (board, offset) & mask) != badval) {
+ func_exit ();
+ return 1;
+diff -rupN linux-2.4.32/drivers/char/tpqic02.c linux-2.4.32.more-gcc4-fixes-v1/drivers/char/tpqic02.c
+--- linux-2.4.32/drivers/char/tpqic02.c 2004-08-08 10:56:31.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/char/tpqic02.c 2005-11-17 13:31:16.000000000 +0100
+@@ -202,6 +202,7 @@ static int mode_access; /* access mode:
+
+ static int qic02_get_resources(void);
+ static void qic02_release_resources(void);
++static void finish_rw(int cmd);
+
+ /* This is a pointer to the actual kernel buffer where the interrupt routines
+ * read from/write to. It is needed because the DMA channels 1 and 3 cannot
+@@ -820,7 +821,6 @@ static int get_ext_status3(void)
+ static int tp_sense(int ignore)
+ {
+ unsigned err = 0, exnr = 0, gs = 0;
+- static void finish_rw(int cmd);
+
+ if (TPQDBG(SENSE_TEXT))
+ printk(TPQIC02_NAME ": tp_sense(ignore=0x%x) enter\n",
+@@ -2173,16 +2173,6 @@ static ssize_t qic02_tape_write(struct f
+ * Don't rewind if the minor bits specify density 0.
+ */
+
+-static int qic02_tape_open(struct inode *inode, struct file *filp)
+-{
+- static int qic02_tape_open_no_use_count(struct inode *,
+- struct file *);
+- int open_error;
+-
+- open_error = qic02_tape_open_no_use_count(inode, filp);
+- return open_error;
+-}
+-
+ static int qic02_tape_open_no_use_count(struct inode *inode,
+ struct file *filp)
+ {
+@@ -2385,6 +2375,14 @@ static int qic02_tape_open_no_use_count(
+ } /* qic02_tape_open */
+
+
++static int qic02_tape_open(struct inode *inode, struct file *filp)
++{
++ int open_error;
++
++ open_error = qic02_tape_open_no_use_count(inode, filp);
++ return open_error;
++}
++
+ static int qic02_tape_release(struct inode *inode, struct file *filp)
+ {
+ kdev_t dev = inode->i_rdev;
+diff -rupN linux-2.4.32/drivers/i2c/i2c-core.c linux-2.4.32.more-gcc4-fixes-v1/drivers/i2c/i2c-core.c
+--- linux-2.4.32/drivers/i2c/i2c-core.c 2005-06-01 18:02:21.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/i2c/i2c-core.c 2005-11-17 13:31:16.000000000 +0100
+@@ -720,7 +720,7 @@ int i2cproc_cleanup(void)
+ * ----------------------------------------------------
+ */
+
+-int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg msgs[],int num)
++int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs,int num)
+ {
+ int ret;
+
+@@ -750,7 +750,7 @@ int i2c_master_send(struct i2c_client *c
+ msg.addr = client->addr;
+ msg.flags = client->flags & I2C_M_TEN;
+ msg.len = count;
+- (const char *)msg.buf = buf;
++ msg.buf = (char *)buf;
+
+ DEB2(printk(KERN_DEBUG "i2c-core.o: master_send: writing %d bytes on %s.\n",
+ count,client->adapter->name));
+diff -rupN linux-2.4.32/drivers/i2c/i2c-proc.c linux-2.4.32.more-gcc4-fixes-v1/drivers/i2c/i2c-proc.c
+--- linux-2.4.32/drivers/i2c/i2c-proc.c 2005-01-19 18:00:53.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/i2c/i2c-proc.c 2005-11-17 13:31:16.000000000 +0100
+@@ -205,7 +205,7 @@ void i2c_deregister_entry(int id)
+ table = i2c_entries[id]->ctl_table;
+ unregister_sysctl_table(i2c_entries[id]);
+ /* 2-step kfree needed to keep gcc happy about const points */
+- (const char *) temp = table[4].procname;
++ temp = (char *) table[4].procname;
+ kfree(temp);
+ kfree(table);
+ i2c_entries[id] = NULL;
+@@ -287,7 +287,7 @@ int i2c_proc_chips(ctl_table * ctl, int
+ if(copy_to_user(buffer, BUF, buflen))
+ return -EFAULT;
+ curbufsize += buflen;
+- (char *) buffer += buflen;
++ buffer = (char *) buffer + buflen;
+ }
+ *lenp = curbufsize;
+ filp->f_pos += curbufsize;
+@@ -318,7 +318,7 @@ int i2c_sysctl_chips(ctl_table * table,
+ sizeof(struct
+ i2c_chips_data)))
+ return -EFAULT;
+- (char *) oldval +=
++ oldval = (char *) oldval +
+ sizeof(struct i2c_chips_data);
+ nrels++;
+ }
+@@ -473,7 +473,7 @@ int i2c_parse_reals(int *nrels, void *bu
+ !((ret=get_user(nextchar, (char *) buffer))) &&
+ isspace((int) nextchar)) {
+ bufsize--;
+- ((char *) buffer)++;
++ buffer = (char *) buffer + 1;
+ }
+
+ if (ret)
+@@ -492,7 +492,7 @@ int i2c_parse_reals(int *nrels, void *bu
+ && (nextchar == '-')) {
+ min = 1;
+ bufsize--;
+- ((char *) buffer)++;
++ buffer = (char *) buffer + 1;
+ }
+ if (ret)
+ return -EFAULT;
+@@ -503,7 +503,7 @@ int i2c_parse_reals(int *nrels, void *bu
+ isdigit((int) nextchar)) {
+ res = res * 10 + nextchar - '0';
+ bufsize--;
+- ((char *) buffer)++;
++ buffer = (char *) buffer + 1;
+ }
+ if (ret)
+ return -EFAULT;
+@@ -517,7 +517,7 @@ int i2c_parse_reals(int *nrels, void *bu
+ if (bufsize && (nextchar == '.')) {
+ /* Skip the dot */
+ bufsize--;
+- ((char *) buffer)++;
++ buffer = (char *) buffer + 1;
+
+ /* Read digits while they are significant */
+ while (bufsize && (mag > 0) &&
+@@ -526,7 +526,7 @@ int i2c_parse_reals(int *nrels, void *bu
+ res = res * 10 + nextchar - '0';
+ mag--;
+ bufsize--;
+- ((char *) buffer)++;
++ buffer = (char *) buffer + 1;
+ }
+ if (ret)
+ return -EFAULT;
+@@ -542,7 +542,7 @@ int i2c_parse_reals(int *nrels, void *bu
+ !((ret=get_user(nextchar, (char *) buffer))) &&
+ !isspace((int) nextchar)) {
+ bufsize--;
+- ((char *) buffer)++;
++ buffer = (char *) buffer + 1;
+ }
+ if (ret)
+ return -EFAULT;
+@@ -574,7 +574,7 @@ int i2c_write_reals(int nrels, void *buf
+ if(put_user(' ', (char *) buffer))
+ return -EFAULT;
+ curbufsize++;
+- ((char *) buffer)++;
++ buffer = (char *) buffer + 1;
+ }
+
+ /* Fill BUF with the representation of the next string */
+@@ -615,7 +615,7 @@ int i2c_write_reals(int nrels, void *buf
+ if(copy_to_user(buffer, BUF, buflen))
+ return -EFAULT;
+ curbufsize += buflen;
+- (char *) buffer += buflen;
++ buffer = (char *) buffer + buflen;
+
+ nr++;
+ }
+diff -rupN linux-2.4.32/drivers/ide/legacy/hd.c linux-2.4.32.more-gcc4-fixes-v1/drivers/ide/legacy/hd.c
+--- linux-2.4.32/drivers/ide/legacy/hd.c 2003-06-14 13:30:22.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/ide/legacy/hd.c 2005-11-17 13:31:16.000000000 +0100
+@@ -694,7 +694,11 @@ static int hd_release(struct inode * ino
+ return 0;
+ }
+
+-extern struct block_device_operations hd_fops;
++static struct block_device_operations hd_fops = {
++ open: hd_open,
++ release: hd_release,
++ ioctl: hd_ioctl,
++};
+
+ static struct gendisk hd_gendisk = {
+ major: MAJOR_NR,
+@@ -718,12 +722,6 @@ static void hd_interrupt(int irq, void *
+ sti();
+ }
+
+-static struct block_device_operations hd_fops = {
+- open: hd_open,
+- release: hd_release,
+- ioctl: hd_ioctl,
+-};
+-
+ /*
+ * This is the hard disk IRQ description. The SA_INTERRUPT in sa_flags
+ * means we run the IRQ-handler with interrupts disabled: this is bad for
+diff -rupN linux-2.4.32/drivers/ieee1394/highlevel.c linux-2.4.32.more-gcc4-fixes-v1/drivers/ieee1394/highlevel.c
+--- linux-2.4.32/drivers/ieee1394/highlevel.c 2003-11-29 00:28:11.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/ieee1394/highlevel.c 2005-11-17 13:31:16.000000000 +0100
+@@ -500,7 +500,7 @@ int highlevel_read(struct hpsb_host *hos
+ rcode = RCODE_TYPE_ERROR;
+ }
+
+- (u8 *)data += partlength;
++ data += partlength;
+ length -= partlength;
+ addr += partlength;
+
+@@ -546,7 +546,7 @@ int highlevel_write(struct hpsb_host *ho
+ rcode = RCODE_TYPE_ERROR;
+ }
+
+- (u8 *)data += partlength;
++ data += partlength;
+ length -= partlength;
+ addr += partlength;
+
+diff -rupN linux-2.4.32/drivers/isdn/eicon/eicon.h linux-2.4.32.more-gcc4-fixes-v1/drivers/isdn/eicon/eicon.h
+--- linux-2.4.32/drivers/isdn/eicon/eicon.h 2002-08-07 00:52:20.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/isdn/eicon/eicon.h 2005-11-17 13:31:16.000000000 +0100
+@@ -344,7 +344,6 @@ typedef struct eicon_card {
+
+ #include "eicon_idi.h"
+
+-extern eicon_card *cards;
+ extern char *eicon_ctype_name[];
+
+
+diff -rupN linux-2.4.32/drivers/isdn/hisax/hfc_pci.c linux-2.4.32.more-gcc4-fixes-v1/drivers/isdn/hisax/hfc_pci.c
+--- linux-2.4.32/drivers/isdn/hisax/hfc_pci.c 2004-11-17 18:36:42.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/isdn/hisax/hfc_pci.c 2005-11-17 13:31:16.000000000 +0100
+@@ -1742,7 +1742,7 @@ setup_hfcpci(struct IsdnCard *card)
+ /* Allocate memory for FIFOS */
+ /* Because the HFC-PCI needs a 32K physical alignment, we */
+ /* need to allocate the double mem and align the address */
+- if (!((void *) cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) {
++ if (!(cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) {
+ printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
+ return 0;
+ }
+diff -rupN linux-2.4.32/drivers/md/lvm-internal.h linux-2.4.32.more-gcc4-fixes-v1/drivers/md/lvm-internal.h
+--- linux-2.4.32/drivers/md/lvm-internal.h 2003-11-29 00:28:12.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/md/lvm-internal.h 2005-11-17 13:31:16.000000000 +0100
+@@ -45,7 +45,6 @@ extern int loadtime;
+ extern const char *const lvm_name;
+
+
+-extern uint vg_count;
+ extern vg_t *vg[];
+ extern struct file_operations lvm_chr_fops;
+
+diff -rupN linux-2.4.32/drivers/media/video/bttvp.h linux-2.4.32.more-gcc4-fixes-v1/drivers/media/video/bttvp.h
+--- linux-2.4.32/drivers/media/video/bttvp.h 2003-11-29 00:28:12.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/media/video/bttvp.h 2005-11-17 13:31:16.000000000 +0100
+@@ -58,7 +58,6 @@ extern int pvr_boot(struct bttv *btv);
+
+ #define BTTV_MAX 16
+ extern unsigned int bttv_num; /* number of Bt848s in use */
+-extern struct bttv bttvs[BTTV_MAX];
+
+ #define UNSET -1U
+
+@@ -203,6 +202,8 @@ struct bttv {
+ int shutdown;
+ void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set);
+ };
++
++extern struct bttv bttvs[BTTV_MAX];
+ #endif
+
+ #define btwrite(dat,adr) writel((dat), (char *) (btv->bt848_mem+(adr)))
+diff -rupN linux-2.4.32/drivers/media/video/videodev.c linux-2.4.32.more-gcc4-fixes-v1/drivers/media/video/videodev.c
+--- linux-2.4.32/drivers/media/video/videodev.c 2004-08-08 10:56:31.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/media/video/videodev.c 2005-11-17 13:31:16.000000000 +0100
+@@ -489,7 +489,18 @@ static void videodev_proc_destroy_dev (s
+
+ #endif /* CONFIG_VIDEO_PROC_FS */
+
+-extern struct file_operations video_fops;
++static struct file_operations video_fops=
++{
++ owner: THIS_MODULE,
++ llseek: no_llseek,
++ read: video_read,
++ write: video_write,
++ ioctl: video_ioctl,
++ mmap: video_mmap,
++ open: video_open,
++ release: video_release,
++ poll: video_poll,
++};
+
+ /**
+ * video_register_device - register video4linux devices
+@@ -633,19 +644,6 @@ void video_unregister_device(struct vide
+ }
+
+
+-static struct file_operations video_fops=
+-{
+- owner: THIS_MODULE,
+- llseek: no_llseek,
+- read: video_read,
+- write: video_write,
+- ioctl: video_ioctl,
+- mmap: video_mmap,
+- open: video_open,
+- release: video_release,
+- poll: video_poll,
+-};
+-
+ /*
+ * Initialise video for linux
+ */
+diff -rupN linux-2.4.32/drivers/net/3c507.c linux-2.4.32.more-gcc4-fixes-v1/drivers/net/3c507.c
+--- linux-2.4.32/drivers/net/3c507.c 2003-11-29 00:28:12.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/3c507.c 2005-11-17 13:31:16.000000000 +0100
+@@ -306,6 +306,7 @@ static void el16_tx_timeout (struct net_
+ static void hardware_send_packet(struct net_device *dev, void *buf, short length, short pad);
+ static void init_82586_mem(struct net_device *dev);
+ static struct ethtool_ops netdev_ethtool_ops;
++static void init_rx_bufs(struct net_device *);
+
+
+ /* Check for a network adaptor of this type, and return '0' iff one exists.
+@@ -602,7 +603,6 @@ static void el16_interrupt(int irq, void
+ }
+
+ if ((status & 0x0070) != 0x0040 && netif_running(dev)) {
+- static void init_rx_bufs(struct net_device *);
+ /* The Rx unit is not ready, it must be hung. Restart the receiver by
+ initializing the rx buffers, and issuing an Rx start command. */
+ if (net_debug)
+diff -rupN linux-2.4.32/drivers/net/acenic.c linux-2.4.32.more-gcc4-fixes-v1/drivers/net/acenic.c
+--- linux-2.4.32/drivers/net/acenic.c 2003-08-25 20:07:43.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/acenic.c 2005-11-17 13:31:16.000000000 +0100
+@@ -594,6 +594,7 @@ static struct net_device *root_dev;
+
+ static int probed __initdata = 0;
+
++static void ace_watchdog(struct net_device *dev);
+
+ int __devinit acenic_probe (ACE_PROBE_ARG)
+ {
+@@ -665,7 +666,6 @@ int __devinit acenic_probe (ACE_PROBE_AR
+ dev->vlan_rx_kill_vid = ace_vlan_rx_kill_vid;
+ #endif
+ if (1) {
+- static void ace_watchdog(struct net_device *dev);
+ dev->tx_timeout = &ace_watchdog;
+ dev->watchdog_timeo = 5*HZ;
+ }
+diff -rupN linux-2.4.32/drivers/net/arcnet/arcnet.c linux-2.4.32.more-gcc4-fixes-v1/drivers/net/arcnet/arcnet.c
+--- linux-2.4.32/drivers/net/arcnet/arcnet.c 2003-08-25 20:07:43.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/arcnet/arcnet.c 2005-11-17 13:31:16.000000000 +0100
+@@ -277,7 +277,7 @@ static void release_arcbuf(struct net_de
+ BUGLVL(D_DURING) {
+ BUGMSG(D_DURING, "release_arcbuf: freed #%d; buffer queue is now: ",
+ bufnum);
+- for (i = lp->next_buf; i != lp->first_free_buf; i = ++i % 5)
++ for (i = lp->next_buf; i != lp->first_free_buf; i = (i+1) % 5)
+ BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]);
+ BUGMSG2(D_DURING, "\n");
+ }
+@@ -310,7 +310,7 @@ static int get_arcbuf(struct net_device
+
+ BUGLVL(D_DURING) {
+ BUGMSG(D_DURING, "get_arcbuf: got #%d; buffer queue is now: ", buf);
+- for (i = lp->next_buf; i != lp->first_free_buf; i = ++i % 5)
++ for (i = lp->next_buf; i != lp->first_free_buf; i = (i+1) % 5)
+ BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]);
+ BUGMSG2(D_DURING, "\n");
+ }
+diff -rupN linux-2.4.32/drivers/net/arlan.c linux-2.4.32.more-gcc4-fixes-v1/drivers/net/arlan.c
+--- linux-2.4.32/drivers/net/arlan.c 2002-08-07 00:52:20.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/arlan.c 2005-11-17 13:31:16.000000000 +0100
+@@ -12,7 +12,7 @@
+ # error FIXME: this driver requires a 32-bit platform
+ #endif
+
+-static const char *arlan_version = "C.Jennigs 97 & Elmer.Joandi@ut.ee Oct'98, http://www.ylenurme.ee/~elmer/655/";
++const char *arlan_version = "C.Jennigs 97 & Elmer.Joandi@ut.ee Oct'98, http://www.ylenurme.ee/~elmer/655/";
+
+ struct net_device *arlan_device[MAX_ARLANS];
+ int last_arlan;
+diff -rupN linux-2.4.32/drivers/net/arlan.h linux-2.4.32.more-gcc4-fixes-v1/drivers/net/arlan.h
+--- linux-2.4.32/drivers/net/arlan.h 2001-03-30 19:05:06.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/arlan.h 2005-11-17 13:31:16.000000000 +0100
+@@ -47,7 +47,6 @@ extern int init_arlan_proc(void);
+
+ extern struct net_device *arlan_device[MAX_ARLANS];
+ extern int arlan_debug;
+-extern char * siteName;
+ extern int arlan_entry_debug;
+ extern int arlan_exit_debug;
+ extern int testMemory;
+diff -rupN linux-2.4.32/drivers/net/bonding/bond_alb.c linux-2.4.32.more-gcc4-fixes-v1/drivers/net/bonding/bond_alb.c
+--- linux-2.4.32/drivers/net/bonding/bond_alb.c 2004-04-14 20:22:20.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/bonding/bond_alb.c 2005-11-17 13:31:16.000000000 +0100
+@@ -1275,7 +1275,7 @@ void bond_alb_deinitialize(struct bondin
+ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
+ {
+ struct bonding *bond = bond_dev->priv;
+- struct ethhdr *eth_data = (struct ethhdr *)skb->mac.raw = skb->data;
++ struct ethhdr *eth_data;
+ struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+ struct slave *tx_slave = NULL;
+ static u32 ip_bcast = 0xffffffff;
+@@ -1285,6 +1285,9 @@ int bond_alb_xmit(struct sk_buff *skb, s
+ u8 *hash_start = NULL;
+ int res = 1;
+
++ skb->mac.raw = (unsigned char *)skb->data;
++ eth_data = (struct ethhdr *)skb->mac.raw;
++
+ /* make sure that the curr_active_slave and the slaves list do
+ * not change during tx
+ */
+diff -rupN linux-2.4.32/drivers/net/de4x5.c linux-2.4.32.more-gcc4-fixes-v1/drivers/net/de4x5.c
+--- linux-2.4.32/drivers/net/de4x5.c 2004-02-18 15:16:23.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/de4x5.c 2005-11-17 13:31:16.000000000 +0100
+@@ -5109,7 +5109,7 @@ mii_get_phy(struct net_device *dev)
+ lp->useMII = TRUE;
+
+ /* Search the MII address space for possible PHY devices */
+- for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(++i)%DE4X5_MAX_MII) {
++ for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(i+1)%DE4X5_MAX_MII) {
+ lp->phy[lp->active].addr = i;
+ if (i==0) n++; /* Count cycles */
+ while (de4x5_reset_phy(dev)<0) udelay(100);/* Wait for reset */
+diff -rupN linux-2.4.32/drivers/net/depca.c linux-2.4.32.more-gcc4-fixes-v1/drivers/net/depca.c
+--- linux-2.4.32/drivers/net/depca.c 2003-06-14 13:30:23.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/depca.c 2005-11-17 13:31:16.000000000 +0100
+@@ -1746,7 +1746,7 @@ static int load_packet(struct net_device
+
+ /* set up the buffer descriptors */
+ len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
+- for (i = entry; i != end; i = (++i) & lp->txRingMask) {
++ for (i = entry; i != end; i = (i+1) & lp->txRingMask) {
+ /* clean out flags */
+ writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base);
+ writew(0x0000, &lp->tx_ring[i].misc); /* clears other error flags */
+diff -rupN linux-2.4.32/drivers/net/hamradio/baycom_epp.c linux-2.4.32.more-gcc4-fixes-v1/drivers/net/hamradio/baycom_epp.c
+--- linux-2.4.32/drivers/net/hamradio/baycom_epp.c 2002-11-30 17:12:25.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/hamradio/baycom_epp.c 2005-11-17 13:31:16.000000000 +0100
+@@ -60,8 +60,10 @@
+ #include <net/ax25.h>
+ #endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
+
++static int my_errno;
++#define errno my_errno
+ #define __KERNEL_SYSCALLS__
+-#include <linux/unistd.h>
++#include <asm/unistd.h>
+
+ /* --------------------------------------------------------------------- */
+
+@@ -370,8 +372,6 @@ static char eppconfig_path[256] = "/usr/
+
+ static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL };
+
+-static int errno;
+-
+ static int exec_eppfpga(void *b)
+ {
+ struct baycom_state *bc = (struct baycom_state *)b;
+diff -rupN linux-2.4.32/drivers/net/hamradio/soundmodem/sm.h linux-2.4.32.more-gcc4-fixes-v1/drivers/net/hamradio/soundmodem/sm.h
+--- linux-2.4.32/drivers/net/hamradio/soundmodem/sm.h 2002-08-07 00:52:20.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/hamradio/soundmodem/sm.h 2005-11-17 13:31:16.000000000 +0100
+@@ -151,7 +151,6 @@ struct hardware_info {
+ /* --------------------------------------------------------------------- */
+
+ extern const char sm_drvname[];
+-extern const char sm_drvinfo[];
+
+ /* --------------------------------------------------------------------- */
+ /*
+@@ -353,7 +352,6 @@ extern const struct hardware_info sm_hw_
+
+ extern const struct modem_tx_info *sm_modem_tx_table[];
+ extern const struct modem_rx_info *sm_modem_rx_table[];
+-extern const struct hardware_info *sm_hardware_table[];
+
+ /* --------------------------------------------------------------------- */
+
+diff -rupN linux-2.4.32/drivers/net/irda/donauboe.c linux-2.4.32.more-gcc4-fixes-v1/drivers/net/irda/donauboe.c
+--- linux-2.4.32/drivers/net/irda/donauboe.c 2003-06-14 13:30:23.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/irda/donauboe.c 2005-11-17 13:31:16.000000000 +0100
+@@ -209,7 +209,11 @@ static int do_probe = DO_PROBE;
+ #ifdef CRC_EXPORTED
+ extern __u16 const irda_crc16_table[];
+ #else
+-static __u16 const irda_crc16_table[256] = {
++/* Our local version of irda_crc16_table must have a unique
++ name to prevent extern-redefined-as-static compile errors.
++ This #define redirects the irda_fcs() macro to our version. */
++#define irda_crc16_table donauboe_irda_crc16_table
++static __u16 const donauboe_irda_crc16_table[256] = {
+ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+ 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+ 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+diff -rupN linux-2.4.32/drivers/net/rrunner.c linux-2.4.32.more-gcc4-fixes-v1/drivers/net/rrunner.c
+--- linux-2.4.32/drivers/net/rrunner.c 2003-06-14 13:30:23.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/rrunner.c 2005-11-17 13:31:16.000000000 +0100
+@@ -234,7 +234,7 @@ int __init rr_hippi_probe (struct net_de
+ * Don't access any registes before this point!
+ */
+ #ifdef __BIG_ENDIAN
+- writel(readl(&regs->HostCtrl) | NO_SWAP, &regs->HostCtrl);
++ writel(readl(&rrpriv->regs->HostCtrl) | NO_SWAP, &rrpriv->regs->HostCtrl);
+ #endif
+ /*
+ * Need to add a case for little-endian 64-bit hosts here.
+diff -rupN linux-2.4.32/drivers/net/sk98lin/skvpd.c linux-2.4.32.more-gcc4-fixes-v1/drivers/net/sk98lin/skvpd.c
+--- linux-2.4.32/drivers/net/sk98lin/skvpd.c 2005-04-04 19:56:04.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/sk98lin/skvpd.c 2005-11-17 13:31:16.000000000 +0100
+@@ -472,7 +472,7 @@ SK_IOC IoC) /* IO Context */
+ ((unsigned char)pAC->vpd.vpd_buf[0x40] == 0x3c) &&
+ ((unsigned char)pAC->vpd.vpd_buf[0x41] == 0x45) ) {
+ printk(KERN_INFO "sk98lin : humm... Asus mainboard with buggy VPD ? correcting data.\n");
+- (unsigned char)pAC->vpd.vpd_buf[0x40] = 0x38;
++ pAC->vpd.vpd_buf[0x40] = 0x38;
+ }
+
+ /* find the end tag of the RO area */
+diff -rupN linux-2.4.32/drivers/net/wan/comx-hw-comx.c linux-2.4.32.more-gcc4-fixes-v1/drivers/net/wan/comx-hw-comx.c
+--- linux-2.4.32/drivers/net/wan/comx-hw-comx.c 2002-11-30 17:12:26.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/wan/comx-hw-comx.c 2005-11-17 13:31:16.000000000 +0100
+@@ -92,9 +92,9 @@ struct comx_privdata {
+ };
+
+ static struct net_device *memory_used[(COMX_MEM_MAX - COMX_MEM_MIN) / 0x10000];
+-extern struct comx_hardware hicomx_hw;
+-extern struct comx_hardware comx_hw;
+-extern struct comx_hardware cmx_hw;
++static struct comx_hardware hicomx_hw;
++static struct comx_hardware comx_hw;
++static struct comx_hardware cmx_hw;
+
+ static void COMX_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+diff -rupN linux-2.4.32/drivers/net/wan/comx.h linux-2.4.32.more-gcc4-fixes-v1/drivers/net/wan/comx.h
+--- linux-2.4.32/drivers/net/wan/comx.h 2001-08-16 23:47:01.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/wan/comx.h 2005-11-17 13:31:16.000000000 +0100
+@@ -212,8 +212,6 @@ typedef u16 word;
+ #define SEEK_END 2
+ #endif
+
+-extern struct proc_dir_entry * comx_root_dir;
+-
+ extern int comx_register_hardware(struct comx_hardware *comx_hw);
+ extern int comx_unregister_hardware(char *name);
+ extern int comx_register_protocol(struct comx_protocol *comx_line);
+diff -rupN linux-2.4.32/drivers/net/wan/sdla_fr.c linux-2.4.32.more-gcc4-fixes-v1/drivers/net/wan/sdla_fr.c
+--- linux-2.4.32/drivers/net/wan/sdla_fr.c 2003-11-29 00:28:12.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/wan/sdla_fr.c 2005-11-17 13:31:16.000000000 +0100
+@@ -3929,7 +3929,7 @@ static int process_udp_mgmt_pkt(sdla_t*
+ break;
+ }
+
+- (void *)ptr_trc_el = card->u.f.curr_trc_el;
++ ptr_trc_el = (void *)card->u.f.curr_trc_el;
+
+ buffer_length = 0;
+ fr_udp_pkt->data[0x00] = 0x00;
+@@ -3980,7 +3980,7 @@ static int process_udp_mgmt_pkt(sdla_t*
+
+ ptr_trc_el ++;
+ if((void *)ptr_trc_el > card->u.f.trc_el_last)
+- (void*)ptr_trc_el = card->u.f.trc_el_base;
++ ptr_trc_el = (void*)card->u.f.trc_el_base;
+
+ buffer_length += sizeof(fpipemon_trc_hdr_t);
+ if(fpipemon_trc->fpipemon_trc_hdr.data_passed) {
+diff -rupN linux-2.4.32/drivers/net/wan/sdladrv.c linux-2.4.32.more-gcc4-fixes-v1/drivers/net/wan/sdladrv.c
+--- linux-2.4.32/drivers/net/wan/sdladrv.c 2001-09-23 21:06:34.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/wan/sdladrv.c 2005-11-17 13:31:16.000000000 +0100
+@@ -1002,7 +1002,7 @@ int sdla_peek (sdlahw_t* hw, unsigned lo
+ peek_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
+ curlen);
+ addr += curlen;
+- (char*)buf += curlen;
++ buf = (char*)buf + curlen;
+ len -= curlen;
+ }
+
+@@ -1086,7 +1086,7 @@ int sdla_poke (sdlahw_t* hw, unsigned lo
+ poke_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
+ curlen);
+ addr += curlen;
+- (char*)buf += curlen;
++ buf = (char*)buf + curlen;
+ len -= curlen;
+ }
+
+@@ -2127,10 +2127,10 @@ static int detect_s514 (sdlahw_t* hw)
+ modname, hw->irq);
+
+ /* map the physical PCI memory to virtual memory */
+- (void *)hw->dpmbase = ioremap((unsigned long)S514_mem_base_addr,
++ hw->dpmbase = (void *)ioremap((unsigned long)S514_mem_base_addr,
+ (unsigned long)MAX_SIZEOF_S514_MEMORY);
+ /* map the physical control register memory to virtual memory */
+- (void *)hw->vector = ioremap(
++ hw->vector = (unsigned long)ioremap(
+ (unsigned long)(S514_mem_base_addr + S514_CTRL_REG_BYTE),
+ (unsigned long)16);
+
+diff -rupN linux-2.4.32/drivers/net/wan/sdlamain.c linux-2.4.32.more-gcc4-fixes-v1/drivers/net/wan/sdlamain.c
+--- linux-2.4.32/drivers/net/wan/sdlamain.c 2003-11-29 00:28:12.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/net/wan/sdlamain.c 2005-11-17 13:31:16.000000000 +0100
+@@ -1027,7 +1027,7 @@ static int ioctl_dump (sdla_t* card, sdl
+ #endif
+ dump.length -= len;
+ dump.offset += len;
+- (char*)dump.ptr += len;
++ dump.ptr = (char*)dump.ptr + len;
+ }
+
+ sdla_mapmem(&card->hw, oldvec);/* restore DPM window position */
+diff -rupN linux-2.4.32/drivers/scsi/advansys.c linux-2.4.32.more-gcc4-fixes-v1/drivers/scsi/advansys.c
+--- linux-2.4.32/drivers/scsi/advansys.c 2005-01-19 18:00:53.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/scsi/advansys.c 2005-11-17 13:31:16.000000000 +0100
+@@ -3456,9 +3456,9 @@ do { \
+ /*
+ * Default EEPROM Configuration structure defined in a_init.c.
+ */
+-extern ADVEEP_3550_CONFIG Default_3550_EEPROM_Config;
+-extern ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config;
+-extern ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config;
++static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config;
++static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config;
++static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config;
+
+ /*
+ * DvcGetPhyAddr() flag arguments
+@@ -7171,7 +7171,7 @@ asc_isr_callback(ASC_DVC_VAR *asc_dvc_va
+ * then return the number of underrun bytes.
+ */
+ if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
+- qdonep->remain_bytes <= scp->request_bufflen != 0) {
++ qdonep->remain_bytes <= scp->request_bufflen) {
+ ASC_DBG1(1, "asc_isr_callback: underrun condition %u bytes\n",
+ (unsigned) qdonep->remain_bytes);
+ scp->resid = qdonep->remain_bytes;
+diff -rupN linux-2.4.32/drivers/scsi/atp870u.c linux-2.4.32.more-gcc4-fixes-v1/drivers/scsi/atp870u.c
+--- linux-2.4.32/drivers/scsi/atp870u.c 2002-08-07 00:52:21.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/scsi/atp870u.c 2005-11-17 13:31:16.000000000 +0100
+@@ -807,19 +807,19 @@ oktosend:
+ bttl = virt_to_bus(sgpnt[j].address);
+ l = sgpnt[j].length;
+ while (l > 0x10000) {
+- (unsigned short int) (((unsigned short int *) (prd))[i + 3]) = 0x0000;
+- (unsigned short int) (((unsigned short int *) (prd))[i + 2]) = 0x0000;
+- (unsigned long) (((unsigned long *) (prd))[i >> 1]) = bttl;
++ (((unsigned short int *) (prd))[i + 3]) = 0x0000;
++ (((unsigned short int *) (prd))[i + 2]) = 0x0000;
++ (((unsigned long *) (prd))[i >> 1]) = bttl;
+ l -= 0x10000;
+ bttl += 0x10000;
+ i += 0x04;
+ }
+- (unsigned long) (((unsigned long *) (prd))[i >> 1]) = bttl;
+- (unsigned short int) (((unsigned short int *) (prd))[i + 2]) = l;
+- (unsigned short int) (((unsigned short int *) (prd))[i + 3]) = 0;
++ (((unsigned long *) (prd))[i >> 1]) = bttl;
++ (((unsigned short int *) (prd))[i + 2]) = l;
++ (((unsigned short int *) (prd))[i + 3]) = 0;
+ i += 0x04;
+ }
+- (unsigned short int) (((unsigned short int *) (prd))[i - 1]) = 0x8000;
++ (((unsigned short int *) (prd))[i - 1]) = 0x8000;
+ } else {
+ /*
+ * For a linear request write a chain of blocks
+@@ -828,16 +828,16 @@ oktosend:
+ l = workrequ->request_bufflen;
+ i = 0;
+ while (l > 0x10000) {
+- (unsigned short int) (((unsigned short int *) (prd))[i + 3]) = 0x0000;
+- (unsigned short int) (((unsigned short int *) (prd))[i + 2]) = 0x0000;
+- (unsigned long) (((unsigned long *) (prd))[i >> 1]) = bttl;
++ (((unsigned short int *) (prd))[i + 3]) = 0x0000;
++ (((unsigned short int *) (prd))[i + 2]) = 0x0000;
++ (((unsigned long *) (prd))[i >> 1]) = bttl;
+ l -= 0x10000;
+ bttl += 0x10000;
+ i += 0x04;
+ }
+- (unsigned short int) (((unsigned short int *) (prd))[i + 3]) = 0x8000;
+- (unsigned short int) (((unsigned short int *) (prd))[i + 2]) = l;
+- (unsigned long) (((unsigned long *) (prd))[i >> 1]) = bttl;
++ (((unsigned short int *) (prd))[i + 3]) = 0x8000;
++ (((unsigned short int *) (prd))[i + 2]) = l;
++ (((unsigned long *) (prd))[i >> 1]) = bttl;
+ }
+ tmpcip = tmpcip + 4;
+ dev->id[target_id].prdaddru = virt_to_bus(dev->id[target_id].prd_tableu);
+diff -rupN linux-2.4.32/drivers/scsi/cpqfcTSstructs.h linux-2.4.32.more-gcc4-fixes-v1/drivers/scsi/cpqfcTSstructs.h
+--- linux-2.4.32/drivers/scsi/cpqfcTSstructs.h 2004-02-18 15:16:23.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/scsi/cpqfcTSstructs.h 2005-11-17 13:31:16.000000000 +0100
+@@ -965,7 +965,6 @@ void fcSestReset(CPQFCHBA *);
+
+ void cpqfc_pci_unmap(struct pci_dev *pcidev, Scsi_Cmnd * cmd, PTACHYON fcChip, __u32 x_ID);
+
+-extern const __u8 valid_al_pa[];
+ extern const int number_of_al_pa;
+
+ #define FCP_RESID_UNDER 0x80000
+diff -rupN linux-2.4.32/drivers/scsi/cpqfcTSworker.c linux-2.4.32.more-gcc4-fixes-v1/drivers/scsi/cpqfcTSworker.c
+--- linux-2.4.32/drivers/scsi/cpqfcTSworker.c 2003-06-14 13:30:24.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/scsi/cpqfcTSworker.c 2005-11-17 13:31:16.000000000 +0100
+@@ -48,6 +48,7 @@
+ #include "cpqfcTSchip.h"
+ #include "cpqfcTSstructs.h"
+ #include "cpqfcTStrigger.h"
++static const __u8 valid_al_pa[];
+
+ //#define LOGIN_DBG 1
+
+diff -rupN linux-2.4.32/drivers/sound/wavfront.c linux-2.4.32.more-gcc4-fixes-v1/drivers/sound/wavfront.c
+--- linux-2.4.32/drivers/sound/wavfront.c 2001-10-11 13:34:42.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/sound/wavfront.c 2005-11-17 13:31:16.000000000 +0100
+@@ -2484,11 +2484,11 @@ static int __init detect_wavefront (int
+ #include <linux/fs.h>
+ #include <linux/mm.h>
+ #include <linux/slab.h>
+-#include <linux/unistd.h>
++static int my_errno;
++#define errno my_errno
++#include <asm/unistd.h>
+ #include <asm/uaccess.h>
+
+-static int errno;
+-
+ static int
+ wavefront_download_firmware (char *path)
+
+diff -rupN linux-2.4.32/drivers/usb/audio.c linux-2.4.32.more-gcc4-fixes-v1/drivers/usb/audio.c
+--- linux-2.4.32/drivers/usb/audio.c 2004-11-17 18:36:42.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/drivers/usb/audio.c 2005-11-17 13:31:16.000000000 +0100
+@@ -462,6 +462,7 @@ struct usb_audio_state {
+
+ /* prevent picking up a bogus abs macro */
+ #undef abs
++#define abs my_abs
+ static inline int abs(int x)
+ {
+ if (x < 0)
+diff -rupN linux-2.4.32/fs/intermezzo/presto.c linux-2.4.32.more-gcc4-fixes-v1/fs/intermezzo/presto.c
+--- linux-2.4.32/fs/intermezzo/presto.c 2002-11-30 17:12:28.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/fs/intermezzo/presto.c 2005-11-17 13:31:16.000000000 +0100
+@@ -344,8 +344,8 @@ int izo_mark_cache(struct dentry *dentry
+ return -EBADF;
+ }
+
+- ((int)cache->cache_flags) &= and_flag;
+- ((int)cache->cache_flags) |= or_flag;
++ cache->cache_flags &= and_flag;
++ cache->cache_flags |= or_flag;
+ if (res)
+ *res = (int)cache->cache_flags;
+
+@@ -383,8 +383,8 @@ int izo_mark_fset(struct dentry *dentry,
+ make_bad_inode(dentry->d_inode);
+ return -EBADF;
+ }
+- ((int)fset->fset_flags) &= and_flag;
+- ((int)fset->fset_flags) |= or_flag;
++ fset->fset_flags &= and_flag;
++ fset->fset_flags |= or_flag;
+ if (res)
+ *res = (int)fset->fset_flags;
+
+diff -rupN linux-2.4.32/include/asm-ppc/spinlock.h linux-2.4.32.more-gcc4-fixes-v1/include/asm-ppc/spinlock.h
+--- linux-2.4.32/include/asm-ppc/spinlock.h 2003-06-14 13:30:28.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/include/asm-ppc/spinlock.h 2005-11-17 13:31:16.000000000 +0100
+@@ -40,7 +40,6 @@ typedef struct {
+ extern void _spin_lock(spinlock_t *lock);
+ extern void _spin_unlock(spinlock_t *lock);
+ extern int spin_trylock(spinlock_t *lock);
+-extern unsigned long __spin_trylock(volatile unsigned long *lock);
+
+ #define spin_lock(lp) _spin_lock(lp)
+ #define spin_unlock(lp) _spin_unlock(lp)
+diff -rupN linux-2.4.32/include/linux/fsfilter.h linux-2.4.32.more-gcc4-fixes-v1/include/linux/fsfilter.h
+--- linux-2.4.32/include/linux/fsfilter.h 2004-11-17 18:36:42.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/include/linux/fsfilter.h 2005-11-17 13:31:16.000000000 +0100
+@@ -70,7 +70,6 @@ struct filter_fs {
+ #define FILTER_FS_XFS 3
+ #define FILTER_FS_OBDFS 4
+ #define FILTER_FS_TMPFS 5
+-extern struct filter_fs filter_oppar[FILTER_FS_TYPES];
+
+ struct filter_fs *filter_get_filter_fs(const char *cache_type);
+ void filter_setup_journal_ops(struct filter_fs *ops, char *cache_type);
+diff -rupN linux-2.4.32/include/linux/generic_serial.h linux-2.4.32.more-gcc4-fixes-v1/include/linux/generic_serial.h
+--- linux-2.4.32/include/linux/generic_serial.h 2002-02-26 13:26:58.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/include/linux/generic_serial.h 2005-11-17 13:31:16.000000000 +0100
+@@ -98,6 +98,4 @@ int gs_setserial(struct gs_port *port,
+ int gs_getserial(struct gs_port *port, struct serial_struct *sp);
+ void gs_got_break(struct gs_port *port);
+
+-extern int gs_debug;
+-
+ #endif
+diff -rupN linux-2.4.32/include/linux/i2c.h linux-2.4.32.more-gcc4-fixes-v1/include/linux/i2c.h
+--- linux-2.4.32/include/linux/i2c.h 2005-06-01 18:02:21.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/include/linux/i2c.h 2005-11-17 13:31:16.000000000 +0100
+@@ -70,7 +70,7 @@ extern int i2c_master_recv(struct i2c_cl
+
+ /* Transfer num messages.
+ */
+-extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],int num);
++extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msg,int num);
+
+ /*
+ * Some adapter types (i.e. PCF 8584 based ones) may support slave behaviuor.
+@@ -197,7 +197,7 @@ struct i2c_algorithm {
+ to NULL. If an adapter algorithm can do SMBus access, set
+ smbus_xfer. If set to NULL, the SMBus protocol is simulated
+ using common I2C messages */
+- int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg msgs[],
++ int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg *msgs,
+ int num);
+ int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,
+ unsigned short flags, char read_write,
+diff -rupN linux-2.4.32/include/linux/intermezzo_fs.h linux-2.4.32.more-gcc4-fixes-v1/include/linux/intermezzo_fs.h
+--- linux-2.4.32/include/linux/intermezzo_fs.h 2005-01-19 18:00:53.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/include/linux/intermezzo_fs.h 2005-11-17 13:31:16.000000000 +0100
+@@ -321,7 +321,6 @@ int presto_fwrite(struct file *file, con
+ int presto_ispresto(struct inode *);
+
+ /* super.c */
+-extern struct file_system_type presto_fs_type;
+ extern int init_intermezzo_fs(void);
+
+ /* fileset.c */
+diff -rupN linux-2.4.32/include/linux/nbd.h linux-2.4.32.more-gcc4-fixes-v1/include/linux/nbd.h
+--- linux-2.4.32/include/linux/nbd.h 2002-08-07 00:52:26.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/include/linux/nbd.h 2005-11-17 13:31:16.000000000 +0100
+@@ -29,34 +29,6 @@
+
+ #include <linux/blk.h>
+
+-#ifdef PARANOIA
+-extern int requests_in;
+-extern int requests_out;
+-#endif
+-
+-static void
+-nbd_end_request(struct request *req)
+-{
+- struct buffer_head *bh;
+- unsigned nsect;
+- unsigned long flags;
+- int uptodate = (req->errors == 0) ? 1 : 0;
+-
+-#ifdef PARANOIA
+- requests_out++;
+-#endif
+- spin_lock_irqsave(&io_request_lock, flags);
+- while((bh = req->bh) != NULL) {
+- nsect = bh->b_size >> 9;
+- blk_finished_io(nsect);
+- req->bh = bh->b_reqnext;
+- bh->b_reqnext = NULL;
+- bh->b_end_io(bh, uptodate);
+- }
+- blkdev_release_request(req);
+- spin_unlock_irqrestore(&io_request_lock, flags);
+-}
+-
+ #define MAX_NBD 128
+
+ struct nbd_device {
+diff -rupN linux-2.4.32/include/net/irda/irlan_event.h linux-2.4.32.more-gcc4-fixes-v1/include/net/irda/irlan_event.h
+--- linux-2.4.32/include/net/irda/irlan_event.h 1999-03-09 11:36:02.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/include/net/irda/irlan_event.h 2005-11-17 13:31:16.000000000 +0100
+@@ -67,8 +67,6 @@ typedef enum {
+ IRLAN_WATCHDOG_TIMEOUT,
+ } IRLAN_EVENT;
+
+-extern char *irlan_state[];
+-
+ void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event,
+ struct sk_buff *skb);
+
+diff -rupN linux-2.4.32/include/net/irda/irttp.h linux-2.4.32.more-gcc4-fixes-v1/include/net/irda/irttp.h
+--- linux-2.4.32/include/net/irda/irttp.h 2003-06-14 13:30:29.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/include/net/irda/irttp.h 2005-11-17 13:31:16.000000000 +0100
+@@ -209,6 +209,4 @@ static inline int irttp_is_primary(struc
+ return(irlap_is_primary(self->lsap->lap->irlap));
+ }
+
+-extern struct irttp_cb *irttp;
+-
+ #endif /* IRTTP_H */
+diff -rupN linux-2.4.32/include/net/irda/qos.h linux-2.4.32.more-gcc4-fixes-v1/include/net/irda/qos.h
+--- linux-2.4.32/include/net/irda/qos.h 2001-07-21 11:47:34.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/include/net/irda/qos.h 2005-11-17 13:31:16.000000000 +0100
+@@ -83,7 +83,6 @@ struct qos_info {
+ extern int sysctl_max_baud_rate;
+ extern int sysctl_max_inactive_time;
+
+-extern __u32 baud_rates[];
+ extern __u32 data_sizes[];
+ extern __u32 min_turn_times[];
+ extern __u32 add_bofs[];
+diff -rupN linux-2.4.32/include/net/udp.h linux-2.4.32.more-gcc4-fixes-v1/include/net/udp.h
+--- linux-2.4.32/include/net/udp.h 2005-01-19 18:00:53.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/include/net/udp.h 2005-11-17 13:31:16.000000000 +0100
+@@ -25,6 +25,7 @@
+ #include <linux/udp.h>
+ #include <linux/poll.h>
+ #include <net/sock.h>
++#include <net/snmp.h>
+
+ #define UDP_HTABLE_SIZE 128
+
+diff -rupN linux-2.4.32/net/ipv6/ip6_fib.c linux-2.4.32.more-gcc4-fixes-v1/net/ipv6/ip6_fib.c
+--- linux-2.4.32/net/ipv6/ip6_fib.c 2005-11-17 13:27:30.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/net/ipv6/ip6_fib.c 2005-11-17 13:31:16.000000000 +0100
+@@ -95,7 +95,7 @@ static __u32 rt_sernum = 0;
+
+ static struct timer_list ip6_fib_timer = { function: fib6_run_gc };
+
+-static struct fib6_walker_t fib6_walker_list = {
++struct fib6_walker_t fib6_walker_list = {
+ &fib6_walker_list, &fib6_walker_list,
+ };
+
+diff -rupN linux-2.4.32/net/ipv6/sysctl_net_ipv6.c linux-2.4.32.more-gcc4-fixes-v1/net/ipv6/sysctl_net_ipv6.c
+--- linux-2.4.32/net/ipv6/sysctl_net_ipv6.c 2004-04-14 20:22:21.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/net/ipv6/sysctl_net_ipv6.c 2005-11-17 13:31:16.000000000 +0100
+@@ -31,17 +31,14 @@ ctl_table ipv6_table[] = {
+
+ #ifdef MODULE
+ static struct ctl_table_header *ipv6_sysctl_header;
+-static struct ctl_table ipv6_root_table[];
+-static struct ctl_table ipv6_net_table[];
+
+-
+-ctl_table ipv6_root_table[] = {
+- {CTL_NET, "net", NULL, 0, 0555, ipv6_net_table},
++static ctl_table ipv6_net_table[] = {
++ {NET_IPV6, "ipv6", NULL, 0, 0555, ipv6_table},
+ {0}
+ };
+
+-ctl_table ipv6_net_table[] = {
+- {NET_IPV6, "ipv6", NULL, 0, 0555, ipv6_table},
++static ctl_table ipv6_root_table[] = {
++ {CTL_NET, "net", NULL, 0, 0555, ipv6_net_table},
+ {0}
+ };
+
+diff -rupN linux-2.4.32/net/irda/qos.c linux-2.4.32.more-gcc4-fixes-v1/net/irda/qos.c
+--- linux-2.4.32/net/irda/qos.c 2003-11-29 00:28:15.000000000 +0100
++++ linux-2.4.32.more-gcc4-fixes-v1/net/irda/qos.c 2005-11-17 13:31:16.000000000 +0100
+@@ -97,7 +97,7 @@ static int irlap_param_min_turn_time(voi
+ int get);
+
+ __u32 min_turn_times[] = { 10000, 5000, 1000, 500, 100, 50, 10, 0 }; /* us */
+-__u32 baud_rates[] = { 2400, 9600, 19200, 38400, 57600, 115200, 576000,
++static __u32 baud_rates[] = { 2400, 9600, 19200, 38400, 57600, 115200, 576000,
+ 1152000, 4000000, 16000000 }; /* bps */
+ __u32 data_sizes[] = { 64, 128, 256, 512, 1024, 2048 }; /* bytes */
+ __u32 add_bofs[] = { 48, 24, 12, 5, 3, 2, 1, 0 }; /* bytes */
+diff -rupN linux-2.4.32/net/khttpd/prototypes.h linux-2.4.32.more-gcc4-fixes-v1/net/khttpd/prototypes.h
+--- linux-2.4.32/net/khttpd/prototypes.h 2001-08-16 23:47:03.000000000 +0200
++++ linux-2.4.32.more-gcc4-fixes-v1/net/khttpd/prototypes.h 2005-11-17 13:31:16.000000000 +0100
+@@ -49,7 +49,6 @@ extern int sysctl_khttpd_stop;
+ extern struct khttpd_threadinfo threadinfo[CONFIG_KHTTPD_NUMCPU];
+ extern char CurrentTime[];
+ extern atomic_t ConnectCount;
+-extern struct wait_queue main_wait[CONFIG_KHTTPD_NUMCPU];
+
+ /* misc.c */
+
diff --git a/target/linux/generic-2.4/patches/008-intel_flashchip_fix.patch b/target/linux/generic-2.4/patches/008-intel_flashchip_fix.patch
new file mode 100644
index 0000000000..b2397f6249
--- /dev/null
+++ b/target/linux/generic-2.4/patches/008-intel_flashchip_fix.patch
@@ -0,0 +1,101 @@
+diff -urN linux.old/drivers/mtd/chips/cfi_cmdset_0001.c linux.dev/drivers/mtd/chips/cfi_cmdset_0001.c
+--- linux.old/drivers/mtd/chips/cfi_cmdset_0001.c 2004-11-17 12:54:21.000000000 +0100
++++ linux.dev/drivers/mtd/chips/cfi_cmdset_0001.c 2006-03-16 17:25:04.000000000 +0100
+@@ -28,10 +28,18 @@
+ #include <linux/slab.h>
+ #include <linux/delay.h>
+ #include <linux/interrupt.h>
++#include <linux/notifier.h>
++#include <linux/reboot.h>
+ #include <linux/mtd/map.h>
+ #include <linux/mtd/cfi.h>
+ #include <linux/mtd/compatmac.h>
+
++#ifndef container_of
++#define container_of(ptr, type, member) ({ \
++ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
++ (type *)( (char *)__mptr - offsetof(type,member) );})
++#endif
++
+ // debugging, turns off buffer write mode #define FORCE_WORD_WRITE
+
+ static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
+@@ -45,6 +53,7 @@
+ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len);
+ static int cfi_intelext_suspend (struct mtd_info *);
+ static void cfi_intelext_resume (struct mtd_info *);
++static int cfi_intelext_reboot(struct notifier_block *nb, unsigned long val, void *v);
+
+ static void cfi_intelext_destroy(struct mtd_info *);
+
+@@ -288,6 +297,9 @@
+ map->fldrv = &cfi_intelext_chipdrv;
+ MOD_INC_USE_COUNT;
+ mtd->name = map->name;
++ mtd->reboot_notifier.notifier_call = cfi_intelext_reboot;
++ register_reboot_notifier(&mtd->reboot_notifier);
++
+ return mtd;
+
+ setup_err:
+@@ -1960,10 +1972,40 @@
+ }
+ }
+
++
++static void cfi_intelext_reset(struct mtd_info *mtd)
++{
++ struct map_info *map = mtd->priv;
++ struct cfi_private *cfi = map->fldrv_priv;
++ int i;
++ struct flchip *chip;
++
++ cfi_intelext_sync(mtd);
++ for (i=0; i<cfi->numchips; i++) {
++ chip = &cfi->chips[i];
++
++ spin_lock(chip->mutex);
++ cfi_write(map, CMD(0xFF), 0);
++ chip->state = FL_READY;
++ spin_unlock(chip->mutex);
++ }
++}
++
++static int cfi_intelext_reboot(struct notifier_block *nb, unsigned long val, void *v)
++{
++ struct mtd_info *mtd;
++
++ mtd = container_of(nb, struct mtd_info, reboot_notifier);
++ cfi_intelext_reset(mtd);
++ return NOTIFY_DONE;
++}
++
+ static void cfi_intelext_destroy(struct mtd_info *mtd)
+ {
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
++ cfi_intelext_reset(mtd);
++ unregister_reboot_notifier(&mtd->reboot_notifier);
+ kfree(cfi->cmdset_priv);
+ kfree(cfi->cfiq);
+ kfree(cfi);
+diff -urN linux.old/include/linux/mtd/mtd.h linux.dev/include/linux/mtd/mtd.h
+--- linux.old/include/linux/mtd/mtd.h 2003-08-25 13:44:44.000000000 +0200
++++ linux.dev/include/linux/mtd/mtd.h 2006-03-16 17:00:10.000000000 +0100
+@@ -10,6 +10,7 @@
+ #include <linux/version.h>
+ #include <linux/types.h>
+ #include <linux/mtd/compatmac.h>
++#include <linux/notifier.h>
+ #include <linux/module.h>
+ #include <linux/uio.h>
+
+@@ -217,6 +218,8 @@
+ int (*suspend) (struct mtd_info *mtd);
+ void (*resume) (struct mtd_info *mtd);
+
++ struct notifier_block reboot_notifier;
++
+ void *priv;
+ };
+
diff --git a/target/linux/generic-2.4/patches/009-calibrate_section.patch b/target/linux/generic-2.4/patches/009-calibrate_section.patch
new file mode 100644
index 0000000000..aedf6fd5b7
--- /dev/null
+++ b/target/linux/generic-2.4/patches/009-calibrate_section.patch
@@ -0,0 +1,11 @@
+--- linux.old/init/main.c 2006-09-02 20:59:53.000000000 +0200
++++ linux.dev/init/main.c 2006-09-02 21:00:01.000000000 +0200
+@@ -167,7 +167,7 @@
+ better than 1% */
+ #define LPS_PREC 8
+
+-void __init calibrate_delay(void)
++void calibrate_delay(void)
+ {
+ unsigned long ticks, loopbit;
+ int lps_precision = LPS_PREC;
diff --git a/target/linux/generic-2.4/patches/010-disable_old_squashfs_compatibility.patch b/target/linux/generic-2.4/patches/010-disable_old_squashfs_compatibility.patch
new file mode 100644
index 0000000000..8647652018
--- /dev/null
+++ b/target/linux/generic-2.4/patches/010-disable_old_squashfs_compatibility.patch
@@ -0,0 +1,25 @@
+diff -Nur linux-2.4.32/fs/squashfs/Makefile linux-2.4.32-owrt/fs/squashfs/Makefile
+--- linux-2.4.32/fs/squashfs/Makefile 2006-03-21 13:47:50.000000000 +0100
++++ linux-2.4.32-owrt/fs/squashfs/Makefile 2006-03-21 13:48:49.000000000 +0100
+@@ -4,7 +4,7 @@
+
+ O_TARGET := squashfs.o
+
+-obj-y := inode.o squashfs2_0.o LzmaDecode.o
++obj-y := inode.o LzmaDecode.o
+
+ obj-m := $(O_TARGET)
+
+diff -Nur linux-2.4.32/fs/squashfs/squashfs.h linux-2.4.32-owrt/fs/squashfs/squashfs.h
+--- linux-2.4.32/fs/squashfs/squashfs.h 2006-03-21 13:06:10.000000000 +0100
++++ linux-2.4.32-owrt/fs/squashfs/squashfs.h 2006-03-21 13:48:36.000000000 +0100
+@@ -24,6 +24,9 @@
+ #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
+ #undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
+ #endif
++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++#undef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++#endif
+ #ifdef SQUASHFS_TRACE
+ #define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)
+ #else
diff --git a/target/linux/generic-2.4/patches/050-build_flags.patch b/target/linux/generic-2.4/patches/050-build_flags.patch
new file mode 100644
index 0000000000..14a207df23
--- /dev/null
+++ b/target/linux/generic-2.4/patches/050-build_flags.patch
@@ -0,0 +1,83 @@
+diff -ur linux-2.4.32/arch/mips/Makefile linux-2.4.32-openwrt/arch/mips/Makefile
+--- linux-2.4.32/arch/mips/Makefile 2005-12-15 13:53:59.000000000 +0100
++++ linux-2.4.32-openwrt/arch/mips/Makefile 2005-12-15 14:02:33.000000000 +0100
+@@ -44,10 +44,10 @@
+ GCCFLAGS := -I $(TOPDIR)/include/asm/gcc
+ GCCFLAGS += -G 0 -mno-abicalls -fno-pic -pipe
+ GCCFLAGS += $(call check_gcc, -finline-limit=100000,)
+-LINKFLAGS += -G 0 -static -n
+-MODFLAGS += -mlong-calls
++LINKFLAGS += -G 0 -static -n -nostdlib
++MODFLAGS += -mlong-calls -fno-common
+
+-ifdef CONFIG_DEBUG_INFO
++ifdef CONFIG_REMOTE_DEBUG
+ GCCFLAGS += -g
+ ifdef CONFIG_SB1XXX_CORELIS
+ GCCFLAGS += -mno-sched-prolog -fno-omit-frame-pointer
+@@ -69,13 +69,13 @@
+ set_gccflags = $(shell \
+ while :; do \
+ cpu=$(1); isa=-$(2); \
+- for gcc_opt in -march= -mcpu=; do \
++ for gcc_opt in -march= -mtune=; do \
+ $(CC) $$gcc_opt$$cpu $$isa -S -o /dev/null \
+ -xc /dev/null > /dev/null 2>&1 && \
+ break 2; \
+ done; \
+ cpu=$(3); isa=-$(4); \
+- for gcc_opt in -march= -mcpu=; do \
++ for gcc_opt in -march= -mtune=; do \
+ $(CC) $$gcc_opt$$cpu $$isa -S -o /dev/null \
+ -xc /dev/null > /dev/null 2>&1 && \
+ break 2; \
+@@ -90,7 +90,7 @@
+ fi; \
+ gas_abi=-Wa,-32; gas_cpu=$$cpu; gas_isa=-Wa,$$isa; \
+ while :; do \
+- for gas_opt in -Wa,-march= -Wa,-mcpu=; do \
++ for gas_opt in -Wa,-march= -Wa,-mtune=; do \
+ $(CC) $$gas_abi $$gas_opt$$cpu $$gas_isa -Wa,-Z -c \
+ -o /dev/null -xassembler /dev/null > /dev/null 2>&1 && \
+ break 2; \
+@@ -172,6 +172,7 @@
+ endif
+
+ AFLAGS += $(GCCFLAGS)
++ASFLAGS += $(GCCFLAGS)
+ CFLAGS += $(GCCFLAGS)
+
+ LD += -m $(ld-emul)
+diff -ur linux-2.4.32/Makefile linux-2.4.32-openwrt/Makefile
+--- linux-2.4.32/Makefile 2005-12-15 13:53:59.000000000 +0100
++++ linux-2.4.32-openwrt/Makefile 2005-12-15 13:59:30.000000000 +0100
+@@ -17,7 +17,7 @@
+ FINDHPATH = $(HPATH)/asm $(HPATH)/linux $(HPATH)/scsi $(HPATH)/net $(HPATH)/math-emu
+
+ HOSTCC = gcc
+-HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
++HOSTCFLAGS = -Wall -Wstrict-prototypes -Os -fomit-frame-pointer
+
+ CROSS_COMPILE =
+
+@@ -88,10 +88,9 @@
+ #
+ # standard CFLAGS
+ #
+-
+ CPPFLAGS := -D__KERNEL__ -I$(HPATH)
+
+-CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \
++CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -Os \
+ -fno-strict-aliasing -fno-common
+ CFLAGS += -fno-builtin-sprintf
+ ifndef CONFIG_FRAME_POINTER
+@@ -104,6 +103,8 @@
+ # disable pointer signedness warnings in gcc 4.0
+ CFLAGS += $(call check_gcc,-Wno-pointer-sign,)
+
++CFLAGS += $(call check_gcc, -funit-at-a-time,)
++
+ #
+ # ROOT_DEV specifies the default root-device when making the image.
+ # This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case
diff --git a/target/linux/generic-2.4/patches/051-remove_pcmcia_modinst_compat.patch b/target/linux/generic-2.4/patches/051-remove_pcmcia_modinst_compat.patch
new file mode 100644
index 0000000000..091e4ba7a4
--- /dev/null
+++ b/target/linux/generic-2.4/patches/051-remove_pcmcia_modinst_compat.patch
@@ -0,0 +1,21 @@
+--- linux.old/Makefile Tue Oct 10 22:24:41 2006
++++ linux.dev/Makefile Tue Oct 10 22:26:19 2006
+@@ -427,17 +427,8 @@
+ depmod_opts := -b $(INSTALL_MOD_PATH) -r
+ endif
+ .PHONY: _modinst_post
+-_modinst_post: _modinst_post_pcmcia
++_modinst_post:
+ if [ -r System.map ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi
+-
+-# Backwards compatibilty symlinks for people still using old versions
+-# of pcmcia-cs with hard coded pathnames on insmod. Remove
+-# _modinst_post_pcmcia for kernel 2.4.1.
+-.PHONY: _modinst_post_pcmcia
+-_modinst_post_pcmcia:
+- cd $(MODLIB); \
+- mkdir -p pcmcia; \
+- find kernel -path '*/pcmcia/*' -name '*.o' | xargs -i -r ln -sf ../{} pcmcia
+
+ .PHONY: $(patsubst %, _modinst_%, $(SUBDIRS))
+ $(patsubst %, _modinst_%, $(SUBDIRS)) :
diff --git a/target/linux/generic-2.4/patches/100-wireless-extension.patch b/target/linux/generic-2.4/patches/100-wireless-extension.patch
new file mode 100644
index 0000000000..88e91831ff
--- /dev/null
+++ b/target/linux/generic-2.4/patches/100-wireless-extension.patch
@@ -0,0 +1,1121 @@
+diff -Nur linux-2.4.32/include/linux/netdevice.h linux-2.4.32-we/include/linux/netdevice.h
+--- linux-2.4.32/include/linux/netdevice.h 2004-11-17 12:54:22.000000000 +0100
++++ linux-2.4.32-we/include/linux/netdevice.h 2006-03-13 12:10:57.000000000 +0100
+@@ -295,7 +295,9 @@
+
+ /* List of functions to handle Wireless Extensions (instead of ioctl).
+ * See <net/iw_handler.h> for details. Jean II */
+- struct iw_handler_def * wireless_handlers;
++ const struct iw_handler_def * wireless_handlers;
++ /* Instance data managed by the core of Wireless Extensions. */
++ struct iw_public_data * wireless_data;
+
+ struct ethtool_ops *ethtool_ops;
+
+diff -Nur linux-2.4.32/include/linux/wireless.h linux-2.4.32-we/include/linux/wireless.h
+--- linux-2.4.32/include/linux/wireless.h 2003-11-28 19:26:21.000000000 +0100
++++ linux-2.4.32-we/include/linux/wireless.h 2006-03-13 12:11:02.000000000 +0100
+@@ -1,10 +1,10 @@
+ /*
+ * This file define a set of standard wireless extensions
+ *
+- * Version : 16 2.4.03
++ * Version : 18 12.3.05
+ *
+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+- * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
++ * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
+ */
+
+ #ifndef _LINUX_WIRELESS_H
+@@ -47,12 +47,12 @@
+ * # include/net/iw_handler.h
+ *
+ * Note as well that /proc/net/wireless implementation has now moved in :
+- * # include/linux/wireless.c
++ * # net/core/wireless.c
+ *
+ * Wireless Events (2002 -> onward) :
+ * --------------------------------
+ * Events are defined at the end of this file, and implemented in :
+- * # include/linux/wireless.c
++ * # net/core/wireless.c
+ *
+ * Other comments :
+ * --------------
+@@ -82,7 +82,7 @@
+ * (there is some stuff that will be added in the future...)
+ * I just plan to increment with each new version.
+ */
+-#define WIRELESS_EXT 16
++#define WIRELESS_EXT 18
+
+ /*
+ * Changes :
+@@ -175,6 +175,28 @@
+ * - 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
+ */
+
+ /**************************** CONSTANTS ****************************/
+@@ -249,9 +271,33 @@
+ #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */
+ #define SIOCGIWPOWER 0x8B2D /* get Power Management 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 16 ioctl are wireless device private.
++/* 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.
+@@ -266,8 +312,8 @@
+ * We now have 32 commands, so a bit more space ;-).
+ * Also, all 'odd' 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).
+- * And I repeat : you are not obliged to use them with iwspy, but you
++ * 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.
+ */
+
+@@ -290,6 +336,34 @@
+ #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
+
+@@ -352,6 +426,18 @@
+ #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 0x1 /* Value was updated since last read */
++#define IW_QUAL_LEVEL_UPDATED 0x2
++#define IW_QUAL_NOISE_UPDATED 0x4
++#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */
++#define IW_QUAL_LEVEL_INVALID 0x20
++#define IW_QUAL_NOISE_INVALID 0x40
++
++/* 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
+@@ -390,6 +476,7 @@
+ #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 */
+@@ -412,12 +499,113 @@
+ #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
++
++/* 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; }
++
++
+ /****************************** TYPES ******************************/
+
+ /* --------------------------- SUBTYPES --------------------------- */
+@@ -456,7 +644,7 @@
+ __s32 m; /* Mantissa */
+ __s16 e; /* Exponent */
+ __u8 i; /* List index (when in range struct) */
+- __u8 pad; /* Unused - just for alignement */
++ __u8 flags; /* Flags (fixed/auto) */
+ };
+
+ /*
+@@ -507,6 +695,132 @@
+ 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
++{
++ __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
++ __u8 essid_len;
++ __u8 num_channels; /* num entries in channel_list;
++ * 0 = scan all allowed channels */
++ __u8 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.
++ */
++ __u8 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.
++ */
++ __u32 min_channel_time; /* in TU */
++ __u32 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
++{
++ __u32 ext_flags; /* IW_ENCODE_EXT_* */
++ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
++ __u8 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 */
++ __u16 alg; /* IW_ENCODE_ALG_* */
++ __u16 key_len;
++ __u8 key[0];
++};
++
++/* SIOCSIWMLME data */
++struct iw_mlme
++{
++ __u16 cmd; /* IW_MLME_* */
++ __u16 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
++{
++ __u32 cmd; /* IW_PMKSA_* */
++ struct sockaddr bssid;
++ __u8 pmkid[IW_PMKID_LEN];
++};
++
++/* IWEVMICHAELMICFAILURE data */
++struct iw_michaelmicfailure
++{
++ __u32 flags;
++ struct sockaddr src_addr;
++ __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
++};
++
++/* IWEVPMKIDCAND data */
++#define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */
++struct iw_pmkid_cand
++{
++ __u32 flags; /* IW_PMKID_CAND_* */
++ __u32 index; /* the smaller the index, the higher the
++ * priority */
++ struct sockaddr bssid;
++};
++
+ /* ------------------------ WIRELESS STATS ------------------------ */
+ /*
+ * Wireless statistics (used for /proc/net/wireless)
+@@ -610,11 +924,12 @@
+ /* Old Frequency (backward compat - moved lower ) */
+ __u16 old_num_channels;
+ __u8 old_num_frequency;
+- /* Filler to keep "version" at the same offset */
+- __s32 old_freq[6];
++
++ /* Wireless event capability bitmasks */
++ __u32 event_capa[6];
+
+ /* signal level threshold range */
+- __s32 sensitivity;
++ __s32 sensitivity;
+
+ /* Quality of link & SNR stuff */
+ /* Quality range (link, level, noise)
+@@ -685,6 +1000,8 @@
+ 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 */
++
++ __u32 enc_capa; /* IW_ENC_CAPA_* bit field */
+ };
+
+ /*
+diff -Nur linux-2.4.32/include/net/iw_handler.h linux-2.4.32-we/include/net/iw_handler.h
+--- linux-2.4.32/include/net/iw_handler.h 2003-11-28 19:26:21.000000000 +0100
++++ linux-2.4.32-we/include/net/iw_handler.h 2006-03-13 12:10:57.000000000 +0100
+@@ -1,10 +1,10 @@
+ /*
+ * This file define the new driver API for Wireless Extensions
+ *
+- * Version : 5 4.12.02
++ * Version : 6 21.6.04
+ *
+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+- * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved.
++ * Copyright (c) 2001-2004 Jean Tourrilhes, All Rights Reserved.
+ */
+
+ #ifndef _IW_HANDLER_H
+@@ -206,7 +206,7 @@
+ * will be needed...
+ * I just plan to increment with each new version.
+ */
+-#define IW_HANDLER_VERSION 5
++#define IW_HANDLER_VERSION 6
+
+ /*
+ * Changes :
+@@ -224,11 +224,18 @@
+ * V4 to V5
+ * --------
+ * - Add new spy support : struct iw_spy_data & prototypes
++ *
++ * V5 to V6
++ * --------
++ * - Change the way we get to spy_data method for added safety
++ * - Remove spy #ifdef, they are always on -> cleaner code
++ * - Add IW_DESCR_FLAG_NOMAX flag for very large requests
++ * - Start migrating get_wireless_stats to struct iw_handler_def
+ */
+
+ /**************************** CONSTANTS ****************************/
+
+-/* Enable enhanced spy support. Disable to reduce footprint */
++/* Enhanced spy support available */
+ #define IW_WIRELESS_SPY
+ #define IW_WIRELESS_THRSPY
+
+@@ -258,6 +265,7 @@
+ #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 */
+
+@@ -311,23 +319,25 @@
+ /* Array of handlers for standard ioctls
+ * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWNAME]
+ */
+- iw_handler * standard;
++ const iw_handler * standard;
+
+ /* Array of handlers for private ioctls
+ * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
+ */
+- iw_handler * private;
++ const iw_handler * private;
+
+ /* Arguments of private handler. This one is just a list, so you
+ * can put it in any order you want and should not leave holes...
+ * We will automatically export that to user space... */
+- struct iw_priv_args * private_args;
++ const struct iw_priv_args * private_args;
+
+- /* Driver enhanced spy support */
+- long spy_offset; /* Spy data offset */
++ /* This field will be *removed* in the next version of WE */
++ long spy_offset; /* DO NOT USE */
+
+- /* In the long term, get_wireless_stats will move from
+- * 'struct net_device' to here, to minimise bloat. */
++ /* New location of get_wireless_stats, to de-bloat struct net_device.
++ * The old pointer in struct net_device will be gradually phased
++ * out, and drivers are encouraged to use this one... */
++ struct iw_statistics* (*get_wireless_stats)(struct net_device *dev);
+ };
+
+ /* ---------------------- IOCTL DESCRIPTION ---------------------- */
+@@ -374,18 +384,29 @@
+ */
+ struct iw_spy_data
+ {
+-#ifdef IW_WIRELESS_SPY
+ /* --- Standard spy support --- */
+ int spy_number;
+ u_char spy_address[IW_MAX_SPY][ETH_ALEN];
+ struct iw_quality spy_stat[IW_MAX_SPY];
+-#ifdef IW_WIRELESS_THRSPY
+ /* --- Enhanced spy support (event) */
+ struct iw_quality spy_thr_low; /* Low threshold */
+ struct iw_quality spy_thr_high; /* High threshold */
+ u_char spy_thr_under[IW_MAX_SPY];
+-#endif /* IW_WIRELESS_THRSPY */
+-#endif /* IW_WIRELESS_SPY */
++};
++
++/* --------------------- DEVICE WIRELESS DATA --------------------- */
++/*
++ * This is all the wireless data specific to a device instance that
++ * is managed by the core of Wireless Extensions.
++ * We only keep pointer to those structures, so that a driver is free
++ * to share them between instances.
++ * This structure should be initialised before registering the device.
++ * Access to this data follow the same rules as any other struct net_device
++ * data (i.e. valid as long as struct net_device exist, same locking rules).
++ */
++struct iw_public_data {
++ /* Driver enhanced spy support */
++ struct iw_spy_data * spy_data;
+ };
+
+ /**************************** PROTOTYPES ****************************/
+diff -Nur linux-2.4.32/net/core/dev.c linux-2.4.32-we/net/core/dev.c
+--- linux-2.4.32/net/core/dev.c 2005-04-04 03:42:20.000000000 +0200
++++ linux-2.4.32-we/net/core/dev.c 2006-03-13 12:10:57.000000000 +0100
+@@ -2426,7 +2426,7 @@
+ /* Follow me in net/core/wireless.c */
+ ret = wireless_process_ioctl(&ifr, cmd);
+ rtnl_unlock();
+- if (!ret && IW_IS_GET(cmd) &&
++ if (IW_IS_GET(cmd) &&
+ copy_to_user(arg, &ifr, sizeof(struct ifreq)))
+ return -EFAULT;
+ return ret;
+diff -Nur linux-2.4.32/net/core/wireless.c linux-2.4.32-we/net/core/wireless.c
+--- linux-2.4.32/net/core/wireless.c 2003-11-28 19:26:21.000000000 +0100
++++ linux-2.4.32-we/net/core/wireless.c 2006-03-13 12:11:02.000000000 +0100
+@@ -2,7 +2,7 @@
+ * This file implement the Wireless Extensions APIs.
+ *
+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+- * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved.
++ * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
+ *
+ * (As all part of the Linux kernel, this file is GPL)
+ */
+@@ -48,6 +48,16 @@
+ * o Add common spy support : iw_handler_set_spy(), wireless_spy_update()
+ * o Add enhanced spy support : iw_handler_set_thrspy() and event.
+ * o Add WIRELESS_EXT version display in /proc/net/wireless
++ *
++ * v6 - 18.06.04 - Jean II
++ * o Change get_spydata() method for added safety
++ * o Remove spy #ifdef, they are always on -> cleaner code
++ * o Allow any size GET request if user specifies length > max
++ * and if request has IW_DESCR_FLAG_NOMAX flag or is SIOCGIWPRIV
++ * o Start migrating get_wireless_stats to struct iw_handler_def
++ * o Add wmb() in iw_handler_set_spy() for non-coherent archs/cpus
++ * Based on patch from Pavel Roskin <proski@gnu.org> :
++ * o Fix kernel data leak to user space in private handler handling
+ */
+
+ /***************************** INCLUDES *****************************/
+@@ -64,11 +74,7 @@
+
+ /**************************** CONSTANTS ****************************/
+
+-/* Enough lenience, let's make sure things are proper... */
+-#define WE_STRICT_WRITE /* Check write buffer size */
+-/* I'll probably drop both the define and kernel message in the next version */
+-
+-/* Debuging stuff */
++/* Debugging stuff */
+ #undef WE_IOCTL_DEBUG /* Debug IOCTL API */
+ #undef WE_EVENT_DEBUG /* Debug Event dispatcher */
+ #undef WE_SPY_DEBUG /* Debug enhanced spy support */
+@@ -131,14 +137,14 @@
+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
+ /* SIOCGIWAP */
+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
+- /* -- hole -- */
+- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
++ /* SIOCSIWMLME */
++ { IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_mlme), sizeof(struct iw_mlme), 0},
+ /* SIOCGIWAPLIST */
+- { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, 0},
++ { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, IW_DESCR_FLAG_NOMAX},
+ /* SIOCSIWSCAN */
+- { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
++ { IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_scan_req), 0},
+ /* SIOCGIWSCAN */
+- { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, 0},
++ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, IW_DESCR_FLAG_NOMAX},
+ /* SIOCSIWESSID */
+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, IW_DESCR_FLAG_EVENT},
+ /* SIOCGIWESSID */
+@@ -179,6 +185,25 @@
+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
+ /* SIOCGIWPOWER */
+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
++ /* -- hole -- */
++ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
++ /* -- hole -- */
++ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
++ /* SIOCSIWGENIE */
++ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
++ /* SIOCGIWGENIE */
++ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
++ /* SIOCSIWAUTH */
++ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
++ /* SIOCGIWAUTH */
++ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
++ /* SIOCSIWENCODEEXT */
++ { IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_encode_ext), sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX, 0},
++ /* SIOCGIWENCODEEXT */
++ { IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_encode_ext), sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX, 0},
++ /* SIOCSIWPMKSA */
++ { IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_pmksa), sizeof(struct iw_pmksa), 0},
++ /* -- hole -- */
+ };
+ static const int standard_ioctl_num = (sizeof(standard_ioctl) /
+ sizeof(struct iw_ioctl_description));
+@@ -198,12 +223,22 @@
+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
+ /* IWEVEXPIRED */
+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
++ /* IWEVGENIE */
++ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
++ /* IWEVMICHAELMICFAILURE */
++ { IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_michaelmicfailure), 0},
++ /* IWEVASSOCREQIE */
++ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
++ /* IWEVASSOCRESPIE */
++ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
++ /* IWEVPMKIDCAND */
++ { IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_pmkid_cand), 0},
+ };
+ static const int standard_event_num = (sizeof(standard_event) /
+ sizeof(struct iw_ioctl_description));
+
+ /* Size (in bytes) of the various private data types */
+-static const char priv_type_size[] = {
++static const char iw_priv_type_size[] = {
+ 0, /* IW_PRIV_TYPE_NONE */
+ 1, /* IW_PRIV_TYPE_BYTE */
+ 1, /* IW_PRIV_TYPE_CHAR */
+@@ -270,12 +305,15 @@
+ */
+ static inline struct iw_statistics *get_wireless_stats(struct net_device *dev)
+ {
++ /* New location */
++ if((dev->wireless_handlers != NULL) &&
++ (dev->wireless_handlers->get_wireless_stats != NULL))
++ return dev->wireless_handlers->get_wireless_stats(dev);
++
++ /* Old location, will be phased out in next WE */
+ return (dev->get_wireless_stats ?
+ dev->get_wireless_stats(dev) :
+ (struct iw_statistics *) NULL);
+- /* In the future, get_wireless_stats may move from 'struct net_device'
+- * to 'struct iw_handler_def', to de-bloat struct net_device.
+- * Definitely worse a thought... */
+ }
+
+ /* ---------------------------------------------------------------- */
+@@ -310,14 +348,32 @@
+
+ /* ---------------------------------------------------------------- */
+ /*
+- * Number of private arguments
++ * Calculate size of private arguments
+ */
+ static inline int get_priv_size(__u16 args)
+ {
+ int num = args & IW_PRIV_SIZE_MASK;
+ int type = (args & IW_PRIV_TYPE_MASK) >> 12;
+
+- return num * priv_type_size[type];
++ return num * iw_priv_type_size[type];
++}
++
++/* ---------------------------------------------------------------- */
++/*
++ * Re-calculate the size of private arguments
++ */
++static inline int adjust_priv_size(__u16 args,
++ union iwreq_data * wrqu)
++{
++ int num = wrqu->data.length;
++ int max = args & IW_PRIV_SIZE_MASK;
++ int type = (args & IW_PRIV_TYPE_MASK) >> 12;
++
++ /* Make sure the driver doesn't goof up */
++ if (max < num)
++ num = max;
++
++ return num * iw_priv_type_size[type];
+ }
+
+
+@@ -350,11 +406,14 @@
+ dev->name,
+ stats->status,
+ stats->qual.qual,
+- stats->qual.updated & 1 ? '.' : ' ',
++ stats->qual.updated & IW_QUAL_QUAL_UPDATED
++ ? '.' : ' ',
+ ((__u8) stats->qual.level),
+- stats->qual.updated & 2 ? '.' : ' ',
++ stats->qual.updated & IW_QUAL_LEVEL_UPDATED
++ ? '.' : ' ',
+ ((__u8) stats->qual.noise),
+- stats->qual.updated & 4 ? '.' : ' ',
++ stats->qual.updated & IW_QUAL_NOISE_UPDATED
++ ? '.' : ' ',
+ stats->discard.nwid,
+ stats->discard.code,
+ stats->discard.fragment,
+@@ -470,13 +529,15 @@
+ /* Check NULL pointer */
+ if(iwr->u.data.pointer == NULL)
+ return -EFAULT;
+-#ifdef WE_STRICT_WRITE
++
+ /* Check if there is enough buffer up there */
+ if(iwr->u.data.length < dev->wireless_handlers->num_private_args) {
+- printk(KERN_ERR "%s (WE) : Buffer for request SIOCGIWPRIV too small (%d<%d)\n", dev->name, iwr->u.data.length, dev->wireless_handlers->num_private_args);
++ /* User space can't know in advance how large the buffer
++ * needs to be. Give it a hint, so that we can support
++ * any size buffer we want somewhat efficiently... */
++ iwr->u.data.length = dev->wireless_handlers->num_private_args;
+ return -E2BIG;
+ }
+-#endif /* WE_STRICT_WRITE */
+
+ /* Set the number of available ioctls. */
+ iwr->u.data.length = dev->wireless_handlers->num_private_args;
+@@ -505,7 +566,6 @@
+ const struct iw_ioctl_description * descr;
+ struct iw_request_info info;
+ int ret = -EINVAL;
+- int user_size = 0;
+
+ /* Get the description of the IOCTL */
+ if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
+@@ -536,8 +596,14 @@
+ #endif /* WE_SET_EVENT */
+ } else {
+ char * extra;
++ int extra_size;
++ int user_length = 0;
+ int err;
+
++ /* Calculate space needed by arguments. Always allocate
++ * for max space. Easier, and won't last long... */
++ extra_size = descr->max_tokens * descr->token_size;
++
+ /* Check what user space is giving us */
+ if(IW_IS_SET(cmd)) {
+ /* Check NULL pointer */
+@@ -554,18 +620,33 @@
+ if(iwr->u.data.pointer == NULL)
+ return -EFAULT;
+ /* Save user space buffer size for checking */
+- user_size = iwr->u.data.length;
++ user_length = iwr->u.data.length;
++
++ /* Don't check if user_length > max to allow forward
++ * compatibility. The test user_length < min is
++ * implied by the test at the end. */
++
++ /* Support for very large requests */
++ if((descr->flags & IW_DESCR_FLAG_NOMAX) &&
++ (user_length > descr->max_tokens)) {
++ /* Allow userspace to GET more than max so
++ * we can support any size GET requests.
++ * There is still a limit : -ENOMEM. */
++ extra_size = user_length * descr->token_size;
++ /* Note : user_length is originally a __u16,
++ * and token_size is controlled by us,
++ * so extra_size won't get negative and
++ * won't overflow... */
++ }
+ }
+
+ #ifdef WE_IOCTL_DEBUG
+ printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n",
+- dev->name, descr->max_tokens * descr->token_size);
++ dev->name, extra_size);
+ #endif /* WE_IOCTL_DEBUG */
+
+- /* Always allocate for max space. Easier, and won't last
+- * long... */
+- extra = kmalloc(descr->max_tokens * descr->token_size,
+- GFP_KERNEL);
++ /* Create the kernel buffer */
++ extra = kmalloc(extra_size, GFP_KERNEL);
+ if (extra == NULL) {
+ return -ENOMEM;
+ }
+@@ -591,14 +672,11 @@
+
+ /* If we have something to return to the user */
+ if (!ret && IW_IS_GET(cmd)) {
+-#ifdef WE_STRICT_WRITE
+ /* Check if there is enough buffer up there */
+- if(user_size < iwr->u.data.length) {
+- printk(KERN_ERR "%s (WE) : Buffer for request %04X too small (%d<%d)\n", dev->name, cmd, user_size, iwr->u.data.length);
++ if(user_length < iwr->u.data.length) {
+ kfree(extra);
+ return -E2BIG;
+ }
+-#endif /* WE_STRICT_WRITE */
+
+ err = copy_to_user(iwr->u.data.pointer, extra,
+ iwr->u.data.length *
+@@ -661,7 +739,7 @@
+ iw_handler handler)
+ {
+ struct iwreq * iwr = (struct iwreq *) ifr;
+- struct iw_priv_args * descr = NULL;
++ const struct iw_priv_args * descr = NULL;
+ struct iw_request_info info;
+ int extra_size = 0;
+ int i;
+@@ -701,7 +779,7 @@
+ ((extra_size + offset) <= IFNAMSIZ))
+ extra_size = 0;
+ } else {
+- /* Size of set arguments */
++ /* Size of get arguments */
+ extra_size = get_priv_size(descr->get_args);
+
+ /* Does it fits in iwr ? */
+@@ -771,6 +849,14 @@
+
+ /* If we have something to return to the user */
+ if (!ret && IW_IS_GET(cmd)) {
++
++ /* Adjust for the actual length if it's variable,
++ * avoid leaking kernel bits outside. */
++ if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) {
++ extra_size = adjust_priv_size(descr->get_args,
++ &(iwr->u));
++ }
++
+ err = copy_to_user(iwr->u.data.pointer, extra,
+ extra_size);
+ if (err)
+@@ -1042,9 +1128,25 @@
+ * One of the main advantage of centralising spy support here is that
+ * it becomes much easier to improve and extend it without having to touch
+ * the drivers. One example is the addition of the Spy-Threshold events.
+- * Note : IW_WIRELESS_SPY is defined in iw_handler.h
+ */
+
++/* ---------------------------------------------------------------- */
++/*
++ * Return the pointer to the spy data in the driver.
++ * Because this is called on the Rx path via wireless_spy_update(),
++ * we want it to be efficient...
++ */
++static inline struct iw_spy_data * get_spydata(struct net_device *dev)
++{
++ /* This is the new way */
++ if(dev->wireless_data)
++ return(dev->wireless_data->spy_data);
++
++ /* This is the old way. Doesn't work for multi-headed drivers.
++ * It will be removed in the next version of WE. */
++ return (dev->priv + dev->wireless_handlers->spy_offset);
++}
++
+ /*------------------------------------------------------------------*/
+ /*
+ * Standard Wireless Handler : set Spy List
+@@ -1054,16 +1156,26 @@
+ union iwreq_data * wrqu,
+ char * extra)
+ {
+-#ifdef IW_WIRELESS_SPY
+- struct iw_spy_data * spydata = (dev->priv +
+- dev->wireless_handlers->spy_offset);
++ struct iw_spy_data * spydata = get_spydata(dev);
+ struct sockaddr * address = (struct sockaddr *) extra;
+
++ /* Make sure driver is not buggy or using the old API */
++ if(!spydata)
++ return -EOPNOTSUPP;
++
+ /* Disable spy collection while we copy the addresses.
+- * As we don't disable interrupts, we need to do this to avoid races.
+- * As we are the only writer, this is good enough. */
++ * While we copy addresses, any call to wireless_spy_update()
++ * will NOP. This is OK, as anyway the addresses are changing. */
+ spydata->spy_number = 0;
+
++ /* We want to operate without locking, because wireless_spy_update()
++ * most likely will happen in the interrupt handler, and therefore
++ * have its own locking constraints and needs performance.
++ * The rtnl_lock() make sure we don't race with the other iw_handlers.
++ * This make sure wireless_spy_update() "see" that the spy list
++ * is temporarily disabled. */
++ wmb();
++
+ /* Are there are addresses to copy? */
+ if(wrqu->data.length > 0) {
+ int i;
+@@ -1089,13 +1201,14 @@
+ spydata->spy_address[i][5]);
+ #endif /* WE_SPY_DEBUG */
+ }
++
++ /* Make sure above is updated before re-enabling */
++ wmb();
++
+ /* Enable addresses */
+ spydata->spy_number = wrqu->data.length;
+
+ return 0;
+-#else /* IW_WIRELESS_SPY */
+- return -EOPNOTSUPP;
+-#endif /* IW_WIRELESS_SPY */
+ }
+
+ /*------------------------------------------------------------------*/
+@@ -1107,12 +1220,14 @@
+ union iwreq_data * wrqu,
+ char * extra)
+ {
+-#ifdef IW_WIRELESS_SPY
+- struct iw_spy_data * spydata = (dev->priv +
+- dev->wireless_handlers->spy_offset);
++ struct iw_spy_data * spydata = get_spydata(dev);
+ struct sockaddr * address = (struct sockaddr *) extra;
+ int i;
+
++ /* Make sure driver is not buggy or using the old API */
++ if(!spydata)
++ return -EOPNOTSUPP;
++
+ wrqu->data.length = spydata->spy_number;
+
+ /* Copy addresses. */
+@@ -1129,9 +1244,6 @@
+ for(i = 0; i < spydata->spy_number; i++)
+ spydata->spy_stat[i].updated = 0;
+ return 0;
+-#else /* IW_WIRELESS_SPY */
+- return -EOPNOTSUPP;
+-#endif /* IW_WIRELESS_SPY */
+ }
+
+ /*------------------------------------------------------------------*/
+@@ -1143,11 +1255,13 @@
+ union iwreq_data * wrqu,
+ char * extra)
+ {
+-#ifdef IW_WIRELESS_THRSPY
+- struct iw_spy_data * spydata = (dev->priv +
+- dev->wireless_handlers->spy_offset);
++ struct iw_spy_data * spydata = get_spydata(dev);
+ struct iw_thrspy * threshold = (struct iw_thrspy *) extra;
+
++ /* Make sure driver is not buggy or using the old API */
++ if(!spydata)
++ return -EOPNOTSUPP;
++
+ /* Just do it */
+ memcpy(&(spydata->spy_thr_low), &(threshold->low),
+ 2 * sizeof(struct iw_quality));
+@@ -1160,9 +1274,6 @@
+ #endif /* WE_SPY_DEBUG */
+
+ return 0;
+-#else /* IW_WIRELESS_THRSPY */
+- return -EOPNOTSUPP;
+-#endif /* IW_WIRELESS_THRSPY */
+ }
+
+ /*------------------------------------------------------------------*/
+@@ -1174,22 +1285,20 @@
+ union iwreq_data * wrqu,
+ char * extra)
+ {
+-#ifdef IW_WIRELESS_THRSPY
+- struct iw_spy_data * spydata = (dev->priv +
+- dev->wireless_handlers->spy_offset);
++ struct iw_spy_data * spydata = get_spydata(dev);
+ struct iw_thrspy * threshold = (struct iw_thrspy *) extra;
+
++ /* Make sure driver is not buggy or using the old API */
++ if(!spydata)
++ return -EOPNOTSUPP;
++
+ /* Just do it */
+ memcpy(&(threshold->low), &(spydata->spy_thr_low),
+ 2 * sizeof(struct iw_quality));
+
+ return 0;
+-#else /* IW_WIRELESS_THRSPY */
+- return -EOPNOTSUPP;
+-#endif /* IW_WIRELESS_THRSPY */
+ }
+
+-#ifdef IW_WIRELESS_THRSPY
+ /*------------------------------------------------------------------*/
+ /*
+ * Prepare and send a Spy Threshold event
+@@ -1227,7 +1336,6 @@
+ /* Send event to user space */
+ wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold);
+ }
+-#endif /* IW_WIRELESS_THRSPY */
+
+ /* ---------------------------------------------------------------- */
+ /*
+@@ -1240,12 +1348,14 @@
+ unsigned char * address,
+ struct iw_quality * wstats)
+ {
+-#ifdef IW_WIRELESS_SPY
+- struct iw_spy_data * spydata = (dev->priv +
+- dev->wireless_handlers->spy_offset);
++ struct iw_spy_data * spydata = get_spydata(dev);
+ int i;
+ int match = -1;
+
++ /* Make sure driver is not buggy or using the old API */
++ if(!spydata)
++ return;
++
+ #ifdef WE_SPY_DEBUG
+ printk(KERN_DEBUG "wireless_spy_update() : offset %ld, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_handlers->spy_offset, spydata, address[0], address[1], address[2], address[3], address[4], address[5]);
+ #endif /* WE_SPY_DEBUG */
+@@ -1257,7 +1367,7 @@
+ sizeof(struct iw_quality));
+ match = i;
+ }
+-#ifdef IW_WIRELESS_THRSPY
++
+ /* Generate an event if we cross the spy threshold.
+ * To avoid event storms, we have a simple hysteresis : we generate
+ * event only when we go under the low threshold or above the
+@@ -1277,6 +1387,4 @@
+ }
+ }
+ }
+-#endif /* IW_WIRELESS_THRSPY */
+-#endif /* IW_WIRELESS_SPY */
+ }
diff --git a/target/linux/generic-2.4/patches/106-mppe_mppc.patch b/target/linux/generic-2.4/patches/106-mppe_mppc.patch
new file mode 100644
index 0000000000..382b4623f2
--- /dev/null
+++ b/target/linux/generic-2.4/patches/106-mppe_mppc.patch
@@ -0,0 +1,1649 @@
+MPPE/MPPC kernel module for Linux
+
+Microsoft Point-to-Point Encryption / Compression support
+
+ http://www.polbox.com/h/hs001/linux-2.4.29-mppe-mppc-1.3.patch.gz
+
+diff -ruN linux-2.4.29.orig/Documentation/Configure.help linux-2.4.29/Documentation/Configure.help
+--- linux-2.4.29.orig/Documentation/Configure.help 2005-02-02 22:18:18.000000000 +0100
++++ linux-2.4.29/Documentation/Configure.help 2005-02-02 22:26:37.000000000 +0100
+@@ -9969,6 +9969,28 @@
+ module; it is called bsd_comp.o and will show up in the directory
+ modules once you have said "make modules". If unsure, say N.
+
++Microsoft PPP compression/encryption (MPPC/MPPE)
++CONFIG_PPP_MPPE_MPPC
++ Support for the Microsoft Point-To-Point Compression (RFC2118) and
++ Microsoft Point-To-Point Encryption (RFC3078). These protocols are
++ supported by Microsoft Windows and wide range of "hardware" access
++ servers. MPPE is common protocol in Virtual Private Networks. According
++ to RFC3078, MPPE supports 40, 56 and 128-bit key lengths. Depending on
++ PPP daemon configuration on both ends of the link, following scenarios
++ are possible:
++ - only compression (MPPC) is used,
++ - only encryption (MPPE) is used,
++ - compression and encryption (MPPC+MPPE) are used.
++
++ Please note that Hi/Fn (http://www.hifn.com) holds patent on MPPC so
++ you should check if this patent is valid in your country in order to
++ avoid legal problems.
++
++ For more information please visit http://free.polbox.pl/h/hs001
++
++ To compile this driver as a module, choose M here. The module will
++ be called ppp_mppe_mppc.o.
++
+ PPP over Ethernet
+ CONFIG_PPPOE
+ Support for PPP over Ethernet.
+diff -ruN linux-2.4.29.orig/crypto/Config.in linux-2.4.29/crypto/Config.in
+--- linux-2.4.29.orig/crypto/Config.in 2005-02-02 22:18:14.000000000 +0100
++++ linux-2.4.29/crypto/Config.in 2005-02-02 22:26:37.000000000 +0100
+@@ -11,7 +11,9 @@
+ "$CONFIG_INET6_AH" = "y" -o \
+ "$CONFIG_INET6_AH" = "m" -o \
+ "$CONFIG_INET6_ESP" = "y" -o \
+- "$CONFIG_INET6_ESP" = "m" ]; then
++ "$CONFIG_INET6_ESP" = "m" -o \
++ "$CONFIG_PPP_MPPE_MPPC" = "y" -o \
++ "$CONFIG_PPP_MPPE_MPPC" = "m" ]; then
+ define_bool CONFIG_CRYPTO y
+ else
+ bool 'Cryptographic API' CONFIG_CRYPTO
+@@ -51,11 +53,24 @@
+ "$CONFIG_INET6_AH" = "y" -o \
+ "$CONFIG_INET6_AH" = "m" -o \
+ "$CONFIG_INET6_ESP" = "y" -o \
+- "$CONFIG_INET6_ESP" = "m" ]; then
+- define_bool CONFIG_CRYPTO_SHA1 y
+- else
+- tristate ' SHA1 digest algorithm' CONFIG_CRYPTO_SHA1
++ "$CONFIG_INET6_ESP" = "m" -o \
++ "$CONFIG_PPP_MPPE_MPPC" = "y" -o \
++ "$CONFIG_PPP_MPPE_MPPC" = "m" ]; then
++ if [ "$CONFIG_INET_AH" = "y" -o \
++ "$CONFIG_INET_ESP" = "y" -o \
++ "$CONFIG_INET6_AH" = "y" -o \
++ "$CONFIG_INET6_ESP" = "y" -o \
++ "$CONFIG_PPP_MPPE_MPPC" = "y" ]; then
++ define_tristate CONFIG_CRYPTO_SHA1 y
++ else
++ if [ "$CONFIG_CRYPTO_SHA1" != "y" -a \
++ "$CONFIG_CRYPTO_SHA1" != "m" ]; then
++ define_tristate CONFIG_CRYPTO_SHA1 m
++ fi
++ fi
+ fi
++ tristate ' SHA1 digest algorithm' CONFIG_CRYPTO_SHA1
++
+ tristate ' SHA256 digest algorithm' CONFIG_CRYPTO_SHA256
+ tristate ' SHA384 and SHA512 digest algorithms' CONFIG_CRYPTO_SHA512
+ tristate ' Whirlpool digest algorithms' CONFIG_CRYPTO_WP512
+@@ -76,7 +91,20 @@
+ tristate ' TEA and XTEA cipher algorithms' CONFIG_CRYPTO_TEA
+ tristate ' Khazad cipher algorithm' CONFIG_CRYPTO_KHAZAD
+ tristate ' Anubis cipher algorithm' CONFIG_CRYPTO_ANUBIS
++
++ if [ "$CONFIG_PPP_MPPE_MPPC" = "y" -o \
++ "$CONFIG_PPP_MPPE_MPPC" = "m" ]; then
++ if [ "$CONFIG_PPP_MPPE_MPPC" = "y" ]; then
++ define_tristate CONFIG_CRYPTO_ARC4 y
++ else
++ if [ "$CONFIG_CRYPTO_ARC4" != "y" -a \
++ "$CONFIG_CRYPTO_ARC4" != "m" ]; then
++ define_tristate CONFIG_CRYPTO_ARC4 m
++ fi
++ fi
++ fi
+ tristate ' ARC4 cipher algorithm' CONFIG_CRYPTO_ARC4
++
+ if [ "$CONFIG_INET_IPCOMP" = "y" -o \
+ "$CONFIG_INET_IPCOMP" = "m" -o \
+ "$CONFIG_INET6_IPCOMP" = "y" -o \
+diff -ruN linux-2.4.29.orig/drivers/net/Config.in linux-2.4.29/drivers/net/Config.in
+--- linux-2.4.29.orig/drivers/net/Config.in 2005-02-02 22:17:31.000000000 +0100
++++ linux-2.4.29/drivers/net/Config.in 2005-02-02 22:26:37.000000000 +0100
+@@ -332,6 +332,7 @@
+ dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP
+ dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP
+ dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP
++ dep_tristate ' Microsoft PPP compression/encryption (MPPC/MPPE)' CONFIG_PPP_MPPE_MPPC $CONFIG_PPP
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP
+ fi
+diff -ruN linux-2.4.29.orig/drivers/net/Makefile linux-2.4.29/drivers/net/Makefile
+--- linux-2.4.29.orig/drivers/net/Makefile 2005-02-02 22:17:23.000000000 +0100
++++ linux-2.4.29/drivers/net/Makefile 2005-02-02 22:26:37.000000000 +0100
+@@ -163,6 +163,7 @@
+ obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o
+ obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o
+ obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o
++obj-$(CONFIG_PPP_MPPE_MPPC) += ppp_mppe_mppc.o
+ obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
+
+ obj-$(CONFIG_SLIP) += slip.o
+diff -ruN linux-2.4.29.orig/drivers/net/ppp_generic.c linux-2.4.29/drivers/net/ppp_generic.c
+--- linux-2.4.29.orig/drivers/net/ppp_generic.c 2005-02-02 22:17:24.000000000 +0100
++++ linux-2.4.29/drivers/net/ppp_generic.c 2005-02-02 22:26:37.000000000 +0100
+@@ -19,7 +19,7 @@
+ * PPP driver, written by Michael Callahan and Al Longyear, and
+ * subsequently hacked by Paul Mackerras.
+ *
+- * ==FILEVERSION 20020217==
++ * ==FILEVERSION 20040509==
+ */
+
+ #include <linux/config.h>
+@@ -102,6 +102,7 @@
+ spinlock_t rlock; /* lock for receive side 58 */
+ spinlock_t wlock; /* lock for transmit side 5c */
+ int mru; /* max receive unit 60 */
++ int mru_alloc; /* MAX(1500,MRU) for dev_alloc_skb() */
+ unsigned int flags; /* control bits 64 */
+ unsigned int xstate; /* transmit state bits 68 */
+ unsigned int rstate; /* receive state bits 6c */
+@@ -552,7 +553,9 @@
+ case PPPIOCSMRU:
+ if (get_user(val, (int *) arg))
+ break;
+- ppp->mru = val;
++ ppp->mru_alloc = ppp->mru = val;
++ if (ppp->mru_alloc < PPP_MRU)
++ ppp->mru_alloc = PPP_MRU; /* increase for broken peers */
+ err = 0;
+ break;
+
+@@ -1025,14 +1028,37 @@
+ case PPP_CCP:
+ /* peek at outbound CCP frames */
+ ppp_ccp_peek(ppp, skb, 0);
++ /*
++ * When LZS or MPPE/MPPC has been negotiated we don't send
++ * CCP_RESETACK after receiving CCP_RESETREQ; in fact pppd
++ * sends such a packet but we silently discard it here
++ */
++ if (CCP_CODE(skb->data+2) == CCP_RESETACK
++ && (ppp->xcomp->compress_proto == CI_MPPE
++ || ppp->xcomp->compress_proto == CI_LZS)) {
++ --ppp->stats.tx_packets;
++ ppp->stats.tx_bytes -= skb->len - 2;
++ kfree_skb(skb);
++ return;
++ }
+ break;
+ }
+
+ /* try to do packet compression */
+ if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0
+ && proto != PPP_LCP && proto != PPP_CCP) {
+- new_skb = alloc_skb(ppp->dev->mtu + ppp->dev->hard_header_len,
+- GFP_ATOMIC);
++ int comp_ovhd = 0;
++ /*
++ * because of possible data expansion when MPPC or LZS
++ * is used, allocate compressor's buffer 12.5% bigger
++ * than MTU
++ */
++ if (ppp->xcomp->compress_proto == CI_MPPE)
++ comp_ovhd = ((ppp->dev->mtu * 9) / 8) + 1 + MPPE_OVHD;
++ else if (ppp->xcomp->compress_proto == CI_LZS)
++ comp_ovhd = ((ppp->dev->mtu * 9) / 8) + 1 + LZS_OVHD;
++ new_skb = alloc_skb(ppp->dev->mtu + ppp->dev->hard_header_len
++ + comp_ovhd, GFP_ATOMIC);
+ if (new_skb == 0) {
+ printk(KERN_ERR "PPP: no memory (comp pkt)\n");
+ goto drop;
+@@ -1050,9 +1076,21 @@
+ skb = new_skb;
+ skb_put(skb, len);
+ skb_pull(skb, 2); /* pull off A/C bytes */
+- } else {
++ } else if (len == 0) {
+ /* didn't compress, or CCP not up yet */
+ kfree_skb(new_skb);
++ } else {
++ /*
++ * (len < 0)
++ * MPPE requires that we do not send unencrypted
++ * frames. The compressor will return -1 if we
++ * should drop the frame. We cannot simply test
++ * the compress_proto because MPPE and MPPC share
++ * the same number.
++ */
++ printk(KERN_ERR "ppp: compressor dropped pkt\n");
++ kfree_skb(new_skb);
++ goto drop;
+ }
+ }
+
+@@ -1540,14 +1578,15 @@
+ int len;
+
+ if (proto == PPP_COMP) {
+- ns = dev_alloc_skb(ppp->mru + PPP_HDRLEN);
++ ns = dev_alloc_skb(ppp->mru_alloc + PPP_HDRLEN);
+ if (ns == 0) {
+ printk(KERN_ERR "ppp_decompress_frame: no memory\n");
+ goto err;
+ }
+ /* the decompressor still expects the A/C bytes in the hdr */
+ len = ppp->rcomp->decompress(ppp->rc_state, skb->data - 2,
+- skb->len + 2, ns->data, ppp->mru + PPP_HDRLEN);
++ skb->len + 2, ns->data,
++ ppp->mru_alloc + PPP_HDRLEN);
+ if (len < 0) {
+ /* Pass the compressed frame to pppd as an
+ error indication. */
+@@ -1573,7 +1612,14 @@
+ return skb;
+
+ err:
+- ppp->rstate |= SC_DC_ERROR;
++ if (ppp->rcomp->compress_proto != CI_MPPE
++ && ppp->rcomp->compress_proto != CI_LZS) {
++ /*
++ * If decompression protocol isn't MPPE/MPPC or LZS, we set
++ * SC_DC_ERROR flag and wait for CCP_RESETACK
++ */
++ ppp->rstate |= SC_DC_ERROR;
++ }
+ ppp_receive_error(ppp);
+ return skb;
+ }
+@@ -2253,6 +2299,7 @@
+ /* Initialize the new ppp unit */
+ ppp->file.index = unit;
+ ppp->mru = PPP_MRU;
++ ppp->mru_alloc = PPP_MRU;
+ init_ppp_file(&ppp->file, INTERFACE);
+ ppp->file.hdrlen = PPP_HDRLEN - 2; /* don't count proto bytes */
+ for (i = 0; i < NUM_NP; ++i)
+diff -ruN linux-2.4.29.orig/drivers/net/ppp_mppe_mppc.c linux-2.4.29/drivers/net/ppp_mppe_mppc.c
+--- linux-2.4.29.orig/drivers/net/ppp_mppe_mppc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/net/ppp_mppe_mppc.c 2005-02-02 23:07:40.000000000 +0100
+@@ -0,0 +1,1312 @@
++/*
++ * ppp_mppe_mppc.c - MPPC/MPPE "compressor/decompressor" module.
++ *
++ * Copyright (c) 1994 Árpád Magosányi <mag@bunuel.tii.matav.hu>
++ * Copyright (c) 1999 Tim Hockin, Cobalt Networks Inc. <thockin@cobaltnet.com>
++ * Copyright (c) 2002-2005 Jan Dubiec <jdx@slackware.pl>
++ *
++ * Permission to use, copy, modify, and distribute this software and its
++ * documentation is hereby granted, provided that the above copyright
++ * notice appears in all copies. This software is provided without any
++ * warranty, express or implied.
++ *
++ * The code is based on MPPE kernel module written by Árpád Magosányi and
++ * Tim Hockin which can be found on http://planetmirror.com/pub/mppe/.
++ * I have added MPPC and 56 bit session keys support in MPPE.
++ *
++ * WARNING! Although this is open source code, its usage in some countries
++ * (in particular in the USA) may violate Stac Inc. patent for MPPC.
++ *
++ * ==FILEVERSION 20050202==
++ *
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <asm/scatterlist.h>
++#include <linux/vmalloc.h>
++#include <linux/crypto.h>
++
++#include <linux/ppp_defs.h>
++#include <linux/ppp-comp.h>
++
++/*
++ * In 2.4.x kernels macro offset_in_page() is not defined in linux/mm.h so
++ * we define it here; PAGE_MASK is defined in asm/page.h which is included
++ * by linux/mm.h.
++ */
++#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
++
++/*
++ * State for a mppc/mppe "(de)compressor".
++ */
++struct ppp_mppe_state {
++ struct crypto_tfm *arc4_tfm;
++ struct crypto_tfm *sha1_tfm;
++ u8 *sha1_digest;
++ u8 master_key[MPPE_MAX_KEY_LEN];
++ u8 session_key[MPPE_MAX_KEY_LEN];
++ u8 mppc; /* do we use compression (MPPC)? */
++ u8 mppe; /* do we use encryption (MPPE)? */
++ u8 keylen; /* key length in bytes */
++ u8 bitkeylen; /* key length in bits */
++ u16 ccount; /* coherency counter */
++ u16 bits; /* MPPC/MPPE control bits */
++ u8 stateless; /* do we use stateless mode? */
++ u8 nextflushed; /* set A bit in the next outgoing packet;
++ used only by compressor*/
++ u8 flushexpected; /* drop packets until A bit is received;
++ used only by decompressor*/
++ u8 *hist; /* MPPC history */
++ u16 *hash; /* Hash table; used only by compressor */
++ u16 histptr; /* history "cursor" */
++ int unit;
++ int debug;
++ int mru;
++ struct compstat stats;
++};
++
++#define MPPE_HIST_LEN 8192 /* MPPC history size */
++#define MPPE_MAX_CCOUNT 0x0FFF /* max. coherency counter value */
++
++#define MPPE_BIT_FLUSHED 0x80 /* bit A */
++#define MPPE_BIT_RESET 0x40 /* bit B */
++#define MPPE_BIT_COMP 0x20 /* bit C */
++#define MPPE_BIT_ENCRYPTED 0x10 /* bit D */
++
++#define MPPE_SALT0 0xD1 /* values used in MPPE key derivation */
++#define MPPE_SALT1 0x26 /* according to RFC3079 */
++#define MPPE_SALT2 0x9E
++
++#define MPPE_CCOUNT(x) ((((x)[4] & 0x0f) << 8) + (x)[5])
++#define MPPE_BITS(x) ((x)[4] & 0xf0)
++#define MPPE_CTRLHI(x) ((((x)->ccount & 0xf00)>>8)|((x)->bits))
++#define MPPE_CTRLLO(x) ((x)->ccount & 0xff)
++
++/*
++ * Kernel Crypto API needs its arguments to be in kmalloc'd memory, not in the
++ * module static data area. That means sha_pad needs to be kmalloc'd. It is done
++ * in mppe_module_init(). This has been pointed out on 30th July 2004 by Oleg
++ * Makarenko on pptpclient-devel mailing list.
++ */
++#define SHA1_PAD_SIZE 40
++struct sha_pad {
++ unsigned char sha_pad1[SHA1_PAD_SIZE];
++ unsigned char sha_pad2[SHA1_PAD_SIZE];
++};
++static struct sha_pad *sha_pad;
++
++static inline void
++setup_sg(struct scatterlist *sg, const void *address, unsigned int length)
++{
++ sg[0].page = virt_to_page(address);
++ sg[0].offset = offset_in_page(address);
++ sg[0].length = length;
++}
++
++static inline void
++arc4_setkey(struct ppp_mppe_state *state, const unsigned char *key,
++ const unsigned int keylen)
++{
++ crypto_cipher_setkey(state->arc4_tfm, key, keylen);
++}
++
++static inline void
++arc4_encrypt(struct ppp_mppe_state *state, const unsigned char *in,
++ const unsigned int len, unsigned char *out)
++{
++ struct scatterlist sgin[4], sgout[4];
++
++ setup_sg(sgin, in, len);
++ setup_sg(sgout, out, len);
++ crypto_cipher_encrypt(state->arc4_tfm, sgout, sgin, len);
++}
++
++#define arc4_decrypt arc4_encrypt
++
++/*
++ * Key Derivation, from RFC 3078, RFC 3079.
++ * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079.
++ */
++static void
++get_new_key_from_sha(struct ppp_mppe_state *state, unsigned char *interim_key)
++{
++ struct scatterlist sg[4];
++
++ setup_sg(&sg[0], state->master_key, state->keylen);
++ setup_sg(&sg[1], sha_pad->sha_pad1, sizeof(sha_pad->sha_pad1));
++ setup_sg(&sg[2], state->session_key, state->keylen);
++ setup_sg(&sg[3], sha_pad->sha_pad2, sizeof(sha_pad->sha_pad2));
++
++ crypto_digest_digest (state->sha1_tfm, sg, 4, state->sha1_digest);
++
++ memcpy(interim_key, state->sha1_digest, state->keylen);
++}
++
++static void
++mppe_change_key(struct ppp_mppe_state *state, int initialize)
++{
++ unsigned char interim_key[MPPE_MAX_KEY_LEN];
++
++ get_new_key_from_sha(state, interim_key);
++ if (initialize) {
++ memcpy(state->session_key, interim_key, state->keylen);
++ } else {
++ arc4_setkey(state, interim_key, state->keylen);
++ arc4_encrypt(state, interim_key, state->keylen, state->session_key);
++ }
++ if (state->keylen == 8) {
++ if (state->bitkeylen == 40) {
++ state->session_key[0] = MPPE_SALT0;
++ state->session_key[1] = MPPE_SALT1;
++ state->session_key[2] = MPPE_SALT2;
++ } else {
++ state->session_key[0] = MPPE_SALT0;
++ }
++ }
++ arc4_setkey(state, state->session_key, state->keylen);
++}
++
++/* increase 12-bit coherency counter */
++static inline void
++mppe_increase_ccount(struct ppp_mppe_state *state)
++{
++ state->ccount = (state->ccount + 1) & MPPE_MAX_CCOUNT;
++ if (state->mppe) {
++ if (state->stateless) {
++ mppe_change_key(state, 0);
++ state->nextflushed = 1;
++ } else {
++ if ((state->ccount & 0xff) == 0xff) {
++ mppe_change_key(state, 0);
++ }
++ }
++ }
++}
++
++/* allocate space for a MPPE/MPPC (de)compressor. */
++/* comp != 0 -> init compressor */
++/* comp = 0 -> init decompressor */
++static void *
++mppe_alloc(unsigned char *options, int opt_len, int comp)
++{
++ struct ppp_mppe_state *state;
++ unsigned int digestsize;
++ u8* fname;
++
++ fname = comp ? "mppe_comp_alloc" : "mppe_decomp_alloc";
++
++ /*
++ * Hack warning - additionally to the standard MPPC/MPPE configuration
++ * options, pppd passes to the (de)copressor 8 or 16 byte session key.
++ * Therefore options[1] contains MPPC/MPPE configuration option length
++ * (CILEN_MPPE = 6), but the real options length, depending on the key
++ * length, is 6+8 or 6+16.
++ */
++ if (opt_len < CILEN_MPPE) {
++ printk(KERN_WARNING "%s: wrong options length: %u\n", fname, opt_len);
++ return NULL;
++ }
++
++ if (options[0] != CI_MPPE || options[1] != CILEN_MPPE ||
++ (options[2] & ~MPPE_STATELESS) != 0 ||
++ options[3] != 0 || options[4] != 0 ||
++ (options[5] & ~(MPPE_128BIT|MPPE_56BIT|MPPE_40BIT|MPPE_MPPC)) != 0 ||
++ (options[5] & (MPPE_128BIT|MPPE_56BIT|MPPE_40BIT|MPPE_MPPC)) == 0) {
++ printk(KERN_WARNING "%s: options rejected: o[0]=%02x, o[1]=%02x, "
++ "o[2]=%02x, o[3]=%02x, o[4]=%02x, o[5]=%02x\n", fname, options[0],
++ options[1], options[2], options[3], options[4], options[5]);
++ return NULL;
++ }
++
++ state = (struct ppp_mppe_state *)kmalloc(sizeof(*state), GFP_KERNEL);
++ if (state == NULL) {
++ printk(KERN_ERR "%s: cannot allocate space for %scompressor\n", fname,
++ comp ? "" : "de");
++ return NULL;
++ }
++ memset(state, 0, sizeof(struct ppp_mppe_state));
++
++ state->mppc = options[5] & MPPE_MPPC; /* Do we use MPPC? */
++ state->mppe = options[5] & (MPPE_128BIT | MPPE_56BIT |
++ MPPE_40BIT); /* Do we use MPPE? */
++
++ if (state->mppc) {
++ /* allocate MPPC history */
++ state->hist = (u8*)vmalloc(2*MPPE_HIST_LEN*sizeof(u8));
++ if (state->hist == NULL) {
++ kfree(state);
++ printk(KERN_ERR "%s: cannot allocate space for MPPC history\n",
++ fname);
++ return NULL;
++ }
++
++ /* allocate hashtable for MPPC compressor */
++ if (comp) {
++ state->hash = (u16*)vmalloc(MPPE_HIST_LEN*sizeof(u16));
++ if (state->hash == NULL) {
++ vfree(state->hist);
++ kfree(state);
++ printk(KERN_ERR "%s: cannot allocate space for MPPC history\n",
++ fname);
++ return NULL;
++ }
++ }
++ }
++
++ if (state->mppe) { /* specific for MPPE */
++ /* Load ARC4 algorithm */
++ state->arc4_tfm = crypto_alloc_tfm("arc4", 0);
++ if (state->arc4_tfm == NULL) {
++ if (state->mppc) {
++ vfree(state->hash);
++ if (comp)
++ vfree(state->hist);
++ }
++ kfree(state);
++ printk(KERN_ERR "%s: cannot load ARC4 module\n", fname);
++ return NULL;
++ }
++
++ /* Load SHA1 algorithm */
++ state->sha1_tfm = crypto_alloc_tfm("sha1", 0);
++ if (state->sha1_tfm == NULL) {
++ crypto_free_tfm(state->arc4_tfm);
++ if (state->mppc) {
++ vfree(state->hash);
++ if (comp)
++ vfree(state->hist);
++ }
++ kfree(state);
++ printk(KERN_ERR "%s: cannot load SHA1 module\n", fname);
++ return NULL;
++ }
++
++ digestsize = crypto_tfm_alg_digestsize(state->sha1_tfm);
++ if (digestsize < MPPE_MAX_KEY_LEN) {
++ crypto_free_tfm(state->sha1_tfm);
++ crypto_free_tfm(state->arc4_tfm);
++ if (state->mppc) {
++ vfree(state->hash);
++ if (comp)
++ vfree(state->hist);
++ }
++ kfree(state);
++ printk(KERN_ERR "%s: CryptoAPI SHA1 digest size too small\n", fname);
++ }
++
++ state->sha1_digest = kmalloc(digestsize, GFP_KERNEL);
++ if (!state->sha1_digest) {
++ crypto_free_tfm(state->sha1_tfm);
++ crypto_free_tfm(state->arc4_tfm);
++ if (state->mppc) {
++ vfree(state->hash);
++ if (comp)
++ vfree(state->hist);
++ }
++ kfree(state);
++ printk(KERN_ERR "%s: cannot allocate space for SHA1 digest\n", fname);
++ }
++
++ memcpy(state->master_key, options+CILEN_MPPE, MPPE_MAX_KEY_LEN);
++ memcpy(state->session_key, state->master_key, MPPE_MAX_KEY_LEN);
++ /* initial key generation is done in mppe_init() */
++ }
++
++ MOD_INC_USE_COUNT;
++
++ return (void *) state;
++}
++
++static void *
++mppe_comp_alloc(unsigned char *options, int opt_len)
++{
++ return mppe_alloc(options, opt_len, 1);
++}
++
++static void *
++mppe_decomp_alloc(unsigned char *options, int opt_len)
++{
++ return mppe_alloc(options, opt_len, 0);
++}
++
++/* cleanup the (de)compressor */
++static void
++mppe_comp_free(void *arg)
++{
++ struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
++
++ if (state != NULL) {
++ if (state->mppe) {
++ if (state->sha1_tfm != NULL)
++ crypto_free_tfm(state->sha1_tfm);
++ if (state->arc4_tfm != NULL)
++ crypto_free_tfm(state->arc4_tfm);
++ }
++ if (state->hist != NULL)
++ vfree(state->hist);
++ if (state->hash != NULL)
++ vfree(state->hash);
++ kfree(state);
++ }
++
++ MOD_DEC_USE_COUNT;
++}
++
++/* init MPPC/MPPE (de)compresor */
++/* comp != 0 -> init compressor */
++/* comp = 0 -> init decompressor */
++static int
++mppe_init(void *arg, unsigned char *options, int opt_len, int unit,
++ int hdrlen, int mru, int debug, int comp)
++{
++ struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
++ u8* fname;
++
++ fname = comp ? "mppe_comp_init" : "mppe_decomp_init";
++
++ if (opt_len < CILEN_MPPE) {
++ if (debug)
++ printk(KERN_WARNING "%s: wrong options length: %u\n",
++ fname, opt_len);
++ return 0;
++ }
++
++ if (options[0] != CI_MPPE || options[1] != CILEN_MPPE ||
++ (options[2] & ~MPPE_STATELESS) != 0 ||
++ options[3] != 0 || options[4] != 0 ||
++ (options[5] & ~(MPPE_56BIT|MPPE_128BIT|MPPE_40BIT|MPPE_MPPC)) != 0 ||
++ (options[5] & (MPPE_56BIT|MPPE_128BIT|MPPE_40BIT|MPPE_MPPC)) == 0) {
++ if (debug)
++ printk(KERN_WARNING "%s: options rejected: o[0]=%02x, o[1]=%02x, "
++ "o[2]=%02x, o[3]=%02x, o[4]=%02x, o[5]=%02x\n", fname,
++ options[0], options[1], options[2], options[3], options[4],
++ options[5]);
++ return 0;
++ }
++
++ if ((options[5] & ~MPPE_MPPC) != MPPE_128BIT &&
++ (options[5] & ~MPPE_MPPC) != MPPE_56BIT &&
++ (options[5] & ~MPPE_MPPC) != MPPE_40BIT &&
++ (options[5] & MPPE_MPPC) != MPPE_MPPC) {
++ if (debug)
++ printk(KERN_WARNING "%s: don't know what to do: o[5]=%02x\n",
++ fname, options[5]);
++ return 0;
++ }
++
++ state->mppc = options[5] & MPPE_MPPC; /* Do we use MPPC? */
++ state->mppe = options[5] & (MPPE_128BIT | MPPE_56BIT |
++ MPPE_40BIT); /* Do we use MPPE? */
++ state->stateless = options[2] & MPPE_STATELESS; /* Do we use stateless mode? */
++
++ switch (state->mppe) {
++ case MPPE_40BIT: /* 40 bit key */
++ state->keylen = 8;
++ state->bitkeylen = 40;
++ break;
++ case MPPE_56BIT: /* 56 bit key */
++ state->keylen = 8;
++ state->bitkeylen = 56;
++ break;
++ case MPPE_128BIT: /* 128 bit key */
++ state->keylen = 16;
++ state->bitkeylen = 128;
++ break;
++ default:
++ state->keylen = 0;
++ state->bitkeylen = 0;
++ }
++
++ state->ccount = MPPE_MAX_CCOUNT;
++ state->bits = 0;
++ state->unit = unit;
++ state->debug = debug;
++ state->histptr = MPPE_HIST_LEN;
++ if (state->mppc) { /* reset history if MPPC was negotiated */
++ memset(state->hist, 0, 2*MPPE_HIST_LEN*sizeof(u8));
++ }
++
++ if (state->mppe) { /* generate initial session keys */
++ mppe_change_key(state, 1);
++ }
++
++ if (comp) { /* specific for compressor */
++ state->nextflushed = 1;
++ } else { /* specific for decompressor */
++ state->mru = mru;
++ state->flushexpected = 1;
++ }
++
++ return 1;
++}
++
++static int
++mppe_comp_init(void *arg, unsigned char *options, int opt_len, int unit,
++ int hdrlen, int debug)
++{
++ return mppe_init(arg, options, opt_len, unit, hdrlen, 0, debug, 1);
++}
++
++
++static int
++mppe_decomp_init(void *arg, unsigned char *options, int opt_len, int unit,
++ int hdrlen, int mru, int debug)
++{
++ return mppe_init(arg, options, opt_len, unit, hdrlen, mru, debug, 0);
++}
++
++static void
++mppe_comp_reset(void *arg)
++{
++ struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg;
++
++ if (state->debug)
++ printk(KERN_DEBUG "%s%d: resetting MPPC/MPPE compressor\n",
++ __FUNCTION__, state->unit);
++
++ state->nextflushed = 1;
++ if (state->mppe)
++ arc4_setkey(state, state->session_key, state->keylen);
++}
++
++static void
++mppe_decomp_reset(void *arg)
++{
++ /* When MPPC/MPPE is in use, we shouldn't receive any CCP Reset-Ack.
++ But when we receive such a packet, we just ignore it. */
++ return;
++}
++
++static void
++mppe_stats(void *arg, struct compstat *stats)
++{
++ struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg;
++
++ *stats = state->stats;
++}
++
++/***************************/
++/**** Compression stuff ****/
++/***************************/
++/* inserts 1 to 8 bits into the output buffer */
++static inline void putbits8(u8 *buf, u32 val, const u32 n, u32 *i, u32 *l)
++{
++ buf += *i;
++ if (*l >= n) {
++ *l = (*l) - n;
++ val <<= *l;
++ *buf = *buf | (val & 0xff);
++ if (*l == 0) {
++ *l = 8;
++ (*i)++;
++ *(++buf) = 0;
++ }
++ } else {
++ (*i)++;
++ *l = 8 - n + (*l);
++ val <<= *l;
++ *buf = *buf | ((val >> 8) & 0xff);
++ *(++buf) = val & 0xff;
++ }
++}
++
++/* inserts 9 to 16 bits into the output buffer */
++static inline void putbits16(u8 *buf, u32 val, const u32 n, u32 *i, u32 *l)
++{
++ buf += *i;
++ if (*l >= n - 8) {
++ (*i)++;
++ *l = 8 - n + (*l);
++ val <<= *l;
++ *buf = *buf | ((val >> 8) & 0xff);
++ *(++buf) = val & 0xff;
++ if (*l == 0) {
++ *l = 8;
++ (*i)++;
++ *(++buf) = 0;
++ }
++ } else {
++ (*i)++; (*i)++;
++ *l = 16 - n + (*l);
++ val <<= *l;
++ *buf = *buf | ((val >> 16) & 0xff);
++ *(++buf) = (val >> 8) & 0xff;
++ *(++buf) = val & 0xff;
++ }
++}
++
++/* inserts 17 to 24 bits into the output buffer */
++static inline void putbits24(u8 *buf, u32 val, const u32 n, u32 *i, u32 *l)
++{
++ buf += *i;
++ if (*l >= n - 16) {
++ (*i)++; (*i)++;
++ *l = 16 - n + (*l);
++ val <<= *l;
++ *buf = *buf | ((val >> 16) & 0xff);
++ *(++buf) = (val >> 8) & 0xff;
++ *(++buf) = val & 0xff;
++ if (*l == 0) {
++ *l = 8;
++ (*i)++;
++ *(++buf) = 0;
++ }
++ } else {
++ (*i)++; (*i)++; (*i)++;
++ *l = 24 - n + (*l);
++ val <<= *l;
++ *buf = *buf | ((val >> 24) & 0xff);
++ *(++buf) = (val >> 16) & 0xff;
++ *(++buf) = (val >> 8) & 0xff;
++ *(++buf) = val & 0xff;
++ }
++}
++
++static int
++mppc_compress(struct ppp_mppe_state *state, unsigned char *ibuf,
++ unsigned char *obuf, int isize, int osize)
++{
++ u32 olen, off, len, idx, i, l;
++ u8 *hist, *sbuf, *p, *q, *r, *s;
++
++ /*
++ At this point, to avoid possible buffer overflow caused by packet
++ expansion during/after compression, we should make sure that
++ osize >= (((isize*9)/8)+1)+2, but we don't do that because in
++ ppp_generic.c we simply allocate bigger obuf.
++
++ Maximum MPPC packet expansion is 12.5%. This is the worst case when
++ all octets in the input buffer are >= 0x80 and we cannot find any
++ repeated tokens. Additionally we have to reserve 2 bytes for MPPE/MPPC
++ status bits and coherency counter.
++ */
++
++ hist = state->hist + MPPE_HIST_LEN;
++ /* check if there is enough room at the end of the history */
++ if (state->histptr + isize >= 2*MPPE_HIST_LEN) {
++ state->bits |= MPPE_BIT_RESET;
++ state->histptr = MPPE_HIST_LEN;
++ memcpy(state->hist, hist, MPPE_HIST_LEN);
++ }
++ /* add packet to the history; isize must be <= MPPE_HIST_LEN */
++ sbuf = state->hist + state->histptr;
++ memcpy(sbuf, ibuf, isize);
++ state->histptr += isize;
++
++ /* compress data */
++ r = sbuf + isize;
++ *obuf = olen = i = 0;
++ l = 8;
++ while (i < isize - 2) {
++ s = q = sbuf + i;
++ idx = ((40543*((((s[0]<<4)^s[1])<<4)^s[2]))>>4) & 0x1fff;
++ p = hist + state->hash[idx];
++ state->hash[idx] = (u16) (s - hist);
++ off = s - p;
++ if (off > MPPE_HIST_LEN - 1 || off < 1 || *p++ != *s++ || *p++ != *s++ ||
++ *p++ != *s++) {
++ /* no match found; encode literal byte */
++ if (ibuf[i] < 0x80) { /* literal byte < 0x80 */
++ putbits8(obuf, (u32) ibuf[i], 8, &olen, &l);
++ } else { /* literal byte >= 0x80 */
++ putbits16(obuf, (u32) (0x100|(ibuf[i]&0x7f)), 9, &olen, &l);
++ }
++ ++i;
++ continue;
++ }
++ if (r - q >= 64) {
++ *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
++ *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
++ *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
++ *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
++ *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
++ *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
++ *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
++ *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
++ *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
++ *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
++ *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
++ *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
++ *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
++ *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
++ *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
++ *p++ != *s++;
++ if (s - q == 64) {
++ p--; s--;
++ while((*p++ == *s++) && (s < r) && (p < q));
++ }
++ } else {
++ while((*p++ == *s++) && (s < r) && (p < q));
++ }
++ len = s - q - 1;
++ i += len;
++
++ /* at least 3 character match found; code data */
++ /* encode offset */
++ if (off < 64) { /* 10-bit offset; 0 <= offset < 64 */
++ putbits16(obuf, 0x3c0|off, 10, &olen, &l);
++ } else if (off < 320) { /* 12-bit offset; 64 <= offset < 320 */
++ putbits16(obuf, 0xe00|(off-64), 12, &olen, &l);
++ } else if (off < 8192) { /* 16-bit offset; 320 <= offset < 8192 */
++ putbits16(obuf, 0xc000|(off-320), 16, &olen, &l);
++ } else {
++ /* This shouldn't happen; we return 0 what means "packet expands",
++ and we send packet uncompressed. */
++ if (state->debug)
++ printk(KERN_DEBUG "%s%d: wrong offset value: %d\n",
++ __FUNCTION__, state->unit, off);
++ return 0;
++ }
++ /* encode length of match */
++ if (len < 4) { /* length = 3 */
++ putbits8(obuf, 0, 1, &olen, &l);
++ } else if (len < 8) { /* 4 <= length < 8 */
++ putbits8(obuf, 0x08|(len&0x03), 4, &olen, &l);
++ } else if (len < 16) { /* 8 <= length < 16 */
++ putbits8(obuf, 0x30|(len&0x07), 6, &olen, &l);
++ } else if (len < 32) { /* 16 <= length < 32 */
++ putbits8(obuf, 0xe0|(len&0x0f), 8, &olen, &l);
++ } else if (len < 64) { /* 32 <= length < 64 */
++ putbits16(obuf, 0x3c0|(len&0x1f), 10, &olen, &l);
++ } else if (len < 128) { /* 64 <= length < 128 */
++ putbits16(obuf, 0xf80|(len&0x3f), 12, &olen, &l);
++ } else if (len < 256) { /* 128 <= length < 256 */
++ putbits16(obuf, 0x3f00|(len&0x7f), 14, &olen, &l);
++ } else if (len < 512) { /* 256 <= length < 512 */
++ putbits16(obuf, 0xfe00|(len&0xff), 16, &olen, &l);
++ } else if (len < 1024) { /* 512 <= length < 1024 */
++ putbits24(obuf, 0x3fc00|(len&0x1ff), 18, &olen, &l);
++ } else if (len < 2048) { /* 1024 <= length < 2048 */
++ putbits24(obuf, 0xff800|(len&0x3ff), 20, &olen, &l);
++ } else if (len < 4096) { /* 2048 <= length < 4096 */
++ putbits24(obuf, 0x3ff000|(len&0x7ff), 22, &olen, &l);
++ } else if (len < 8192) { /* 4096 <= length < 8192 */
++ putbits24(obuf, 0xffe000|(len&0xfff), 24, &olen, &l);
++ } else {
++ /* This shouldn't happen; we return 0 what means "packet expands",
++ and send packet uncompressed. */
++ if (state->debug)
++ printk(KERN_DEBUG "%s%d: wrong length of match value: %d\n",
++ __FUNCTION__, state->unit, len);
++ return 0;
++ }
++ }
++
++ /* Add remaining octets to the output */
++ while(isize - i > 0) {
++ if (ibuf[i] < 0x80) { /* literal byte < 0x80 */
++ putbits8(obuf, (u32) ibuf[i++], 8, &olen, &l);
++ } else { /* literal byte >= 0x80 */
++ putbits16(obuf, (u32) (0x100|(ibuf[i++]&0x7f)), 9, &olen, &l);
++ }
++ }
++ /* Reset unused bits of the last output octet */
++ if ((l != 0) && (l != 8)) {
++ putbits8(obuf, 0, l, &olen, &l);
++ }
++
++ return (int) olen;
++}
++
++int
++mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf,
++ int isize, int osize)
++{
++ struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
++ int proto, olen, complen, off;
++ unsigned char *wptr;
++
++ /* Check that the protocol is in the range we handle. */
++ proto = PPP_PROTOCOL(ibuf);
++ if (proto < 0x0021 || proto > 0x00fa)
++ return 0;
++
++ wptr = obuf;
++ /* Copy over the PPP header */
++ wptr[0] = PPP_ADDRESS(ibuf);
++ wptr[1] = PPP_CONTROL(ibuf);
++ wptr[2] = PPP_COMP >> 8;
++ wptr[3] = PPP_COMP;
++ wptr += PPP_HDRLEN + (MPPE_OVHD / 2); /* Leave two octets for MPPE/MPPC bits */
++
++ /*
++ * In ver. 0.99 protocol field was compressed. Deflate and BSD compress
++ * do PFC before actual compression, RCF2118 and RFC3078 are not precise
++ * on this topic so I decided to do PFC. Unfortunately this change caused
++ * incompatibility with older/other MPPE/MPPC modules. I have received
++ * a lot of complaints from unexperienced users so I have decided to revert
++ * to previous state, i.e. the protocol field is sent uncompressed now.
++ * Although this may be changed in the future.
++ *
++ * Receiving side (mppe_decompress()) still accepts packets with compressed
++ * and uncompressed protocol field so you shouldn't get "Unsupported protocol
++ * 0x2145 received" messages anymore.
++ */
++ //off = (proto > 0xff) ? 2 : 3; /* PFC - skip first protocol byte if 0 */
++ off = 2;
++
++ ibuf += off;
++
++ mppe_increase_ccount(state);
++
++ if (state->nextflushed) {
++ state->bits |= MPPE_BIT_FLUSHED;
++ state->nextflushed = 0;
++ if (state->mppe && !state->stateless) {
++ /*
++ * If this is the flag packet, the key has been already changed in
++ * mppe_increase_ccount() so we dont't do it once again.
++ */
++ if ((state->ccount & 0xff) != 0xff) {
++ arc4_setkey(state, state->session_key, state->keylen);
++ }
++ }
++ if (state->mppc) { /* reset history */
++ state->bits |= MPPE_BIT_RESET;
++ state->histptr = MPPE_HIST_LEN;
++ memset(state->hist + MPPE_HIST_LEN, 0, MPPE_HIST_LEN*sizeof(u8));
++ }
++ }
++
++ if (state->mppc && !state->mppe) { /* Do only compression */
++ complen = mppc_compress(state, ibuf, wptr, isize - off,
++ osize - PPP_HDRLEN - (MPPE_OVHD / 2));
++ /*
++ * TODO: Implement an heuristics to handle packet expansion in a smart
++ * way. Now, when a packet expands, we send it as uncompressed and
++ * when next packet is sent we have to reset compressor's history.
++ * Maybe it would be better to send such packet as compressed in order
++ * to keep history's continuity.
++ */
++ if ((complen > isize) || (complen > osize - PPP_HDRLEN) ||
++ (complen == 0)) {
++ /* packet expands */
++ state->nextflushed = 1;
++ memcpy(wptr, ibuf, isize - off);
++ olen = isize - (off - 2) + MPPE_OVHD;
++ (state->stats).inc_bytes += olen;
++ (state->stats).inc_packets++;
++ } else {
++ state->bits |= MPPE_BIT_COMP;
++ olen = complen + PPP_HDRLEN + (MPPE_OVHD / 2);
++ (state->stats).comp_bytes += olen;
++ (state->stats).comp_packets++;
++ }
++ } else { /* Do encryption with or without compression */
++ state->bits |= MPPE_BIT_ENCRYPTED;
++ if (!state->mppc && state->mppe) { /* Do only encryption */
++ /* read from ibuf, write to wptr, adjust for PPP_HDRLEN */
++ arc4_encrypt(state, ibuf, isize - off, wptr);
++ olen = isize - (off - 2) + MPPE_OVHD;
++ (state->stats).inc_bytes += olen;
++ (state->stats).inc_packets++;
++ } else { /* Do compression and then encryption - RFC3078 */
++ complen = mppc_compress(state, ibuf, wptr, isize - off,
++ osize - PPP_HDRLEN - (MPPE_OVHD / 2));
++ /*
++ * TODO: Implement an heuristics to handle packet expansion in a smart
++ * way. Now, when a packet expands, we send it as uncompressed and
++ * when next packet is sent we have to reset compressor's history.
++ * Maybe it would be good to send such packet as compressed in order
++ * to keep history's continuity.
++ */
++ if ((complen > isize) || (complen > osize - PPP_HDRLEN) ||
++ (complen == 0)) {
++ /* packet expands */
++ state->nextflushed = 1;
++ arc4_encrypt(state, ibuf, isize - off, wptr);
++ olen = isize - (off - 2) + MPPE_OVHD;
++ (state->stats).inc_bytes += olen;
++ (state->stats).inc_packets++;
++ } else {
++ state->bits |= MPPE_BIT_COMP;
++ /* Hack warning !!! RC4 implementation which we use does
++ encryption "in place" - it means that input and output
++ buffers can be *the same* memory area. Therefore we don't
++ need to use a temporary buffer. But be careful - other
++ implementations don't have to be so nice.
++ I used to use ibuf as temporary buffer here, but it led
++ packet sniffers into error. Thanks to Wilfried Weissmann
++ for pointing that. */
++ arc4_encrypt(state, wptr, complen, wptr);
++ olen = complen + PPP_HDRLEN + (MPPE_OVHD / 2);
++ (state->stats).comp_bytes += olen;
++ (state->stats).comp_packets++;
++ }
++ }
++ }
++
++ /* write status bits and coherency counter into the output buffer */
++ wptr = obuf + PPP_HDRLEN;
++ wptr[0] = MPPE_CTRLHI(state);
++ wptr[1] = MPPE_CTRLLO(state);
++
++ state->bits = 0;
++
++ (state->stats).unc_bytes += isize;
++ (state->stats).unc_packets++;
++
++ return olen;
++}
++
++/***************************/
++/*** Decompression stuff ***/
++/***************************/
++static inline u32 getbits(const u8 *buf, const u32 n, u32 *i, u32 *l)
++{
++ static const u32 m[] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
++ u32 res, ol;
++
++ ol = *l;
++ if (*l >= n) {
++ *l = (*l) - n;
++ res = (buf[*i] & m[ol]) >> (*l);
++ if (*l == 0) {
++ *l = 8;
++ (*i)++;
++ }
++ } else {
++ *l = 8 - n + (*l);
++ res = (buf[(*i)++] & m[ol]) << 8;
++ res = (res | buf[*i]) >> (*l);
++ }
++
++ return res;
++}
++
++static inline u32 getbyte(const u8 *buf, const u32 i, const u32 l)
++{
++ if (l == 8) {
++ return buf[i];
++ } else {
++ return (((buf[i] << 8) | buf[i+1]) >> l) & 0xff;
++ }
++}
++
++static inline void lamecopy(u8 *dst, u8 *src, u32 len)
++{
++ while (len--)
++ *dst++ = *src++;
++}
++
++static int
++mppc_decompress(struct ppp_mppe_state *state, unsigned char *ibuf,
++ unsigned char *obuf, int isize, int osize)
++{
++ u32 olen, off, len, bits, val, sig, i, l;
++ u8 *history, *s;
++
++ history = state->hist + state->histptr;
++ olen = len = i = 0;
++ l = 8;
++ bits = isize * 8;
++ while (bits >= 8) {
++ val = getbyte(ibuf, i++, l);
++ if (val < 0x80) { /* literal byte < 0x80 */
++ if (state->histptr < 2*MPPE_HIST_LEN) {
++ /* copy uncompressed byte to the history */
++ (state->hist)[(state->histptr)++] = (u8) val;
++ } else {
++ /* buffer overflow; drop packet */
++ if (state->debug)
++ printk(KERN_ERR "%s%d: trying to write outside history "
++ "buffer\n", __FUNCTION__, state->unit);
++ return DECOMP_ERROR;
++ }
++ olen++;
++ bits -= 8;
++ continue;
++ }
++
++ sig = val & 0xc0;
++ if (sig == 0x80) { /* literal byte >= 0x80 */
++ if (state->histptr < 2*MPPE_HIST_LEN) {
++ /* copy uncompressed byte to the history */
++ (state->hist)[(state->histptr)++] =
++ (u8) (0x80|((val&0x3f)<<1)|getbits(ibuf, 1 , &i ,&l));
++ } else {
++ /* buffer overflow; drop packet */
++ if (state->debug)
++ printk(KERN_ERR "%s%d: trying to write outside history "
++ "buffer\n", __FUNCTION__, state->unit);
++ return DECOMP_ERROR;
++ }
++ olen++;
++ bits -= 9;
++ continue;
++ }
++
++ /* Not a literal byte so it must be an (offset,length) pair */
++ /* decode offset */
++ sig = val & 0xf0;
++ if (sig == 0xf0) { /* 10-bit offset; 0 <= offset < 64 */
++ off = (((val&0x0f)<<2)|getbits(ibuf, 2 , &i ,&l));
++ bits -= 10;
++ } else {
++ if (sig == 0xe0) { /* 12-bit offset; 64 <= offset < 320 */
++ off = ((((val&0x0f)<<4)|getbits(ibuf, 4 , &i ,&l))+64);
++ bits -= 12;
++ } else {
++ if ((sig&0xe0) == 0xc0) {/* 16-bit offset; 320 <= offset < 8192 */
++ off = ((((val&0x1f)<<8)|getbyte(ibuf, i++, l))+320);
++ bits -= 16;
++ if (off > MPPE_HIST_LEN - 1) {
++ if (state->debug)
++ printk(KERN_DEBUG "%s%d: too big offset value: %d\n",
++ __FUNCTION__, state->unit, off);
++ return DECOMP_ERROR;
++ }
++ } else { /* this shouldn't happen */
++ if (state->debug)
++ printk(KERN_DEBUG "%s%d: cannot decode offset value\n",
++ __FUNCTION__, state->unit);
++ return DECOMP_ERROR;
++ }
++ }
++ }
++ /* decode length of match */
++ val = getbyte(ibuf, i, l);
++ if ((val & 0x80) == 0x00) { /* len = 3 */
++ len = 3;
++ bits--;
++ getbits(ibuf, 1 , &i ,&l);
++ } else if ((val & 0xc0) == 0x80) { /* 4 <= len < 8 */
++ len = 0x04 | ((val>>4) & 0x03);
++ bits -= 4;
++ getbits(ibuf, 4 , &i ,&l);
++ } else if ((val & 0xe0) == 0xc0) { /* 8 <= len < 16 */
++ len = 0x08 | ((val>>2) & 0x07);
++ bits -= 6;
++ getbits(ibuf, 6 , &i ,&l);
++ } else if ((val & 0xf0) == 0xe0) { /* 16 <= len < 32 */
++ len = 0x10 | (val & 0x0f);
++ bits -= 8;
++ i++;
++ } else {
++ bits -= 8;
++ val = (val << 8) | getbyte(ibuf, ++i, l);
++ if ((val & 0xf800) == 0xf000) { /* 32 <= len < 64 */
++ len = 0x0020 | ((val >> 6) & 0x001f);
++ bits -= 2;
++ getbits(ibuf, 2 , &i ,&l);
++ } else if ((val & 0xfc00) == 0xf800) { /* 64 <= len < 128 */
++ len = 0x0040 | ((val >> 4) & 0x003f);
++ bits -= 4;
++ getbits(ibuf, 4 , &i ,&l);
++ } else if ((val & 0xfe00) == 0xfc00) { /* 128 <= len < 256 */
++ len = 0x0080 | ((val >> 2) & 0x007f);
++ bits -= 6;
++ getbits(ibuf, 6 , &i ,&l);
++ } else if ((val & 0xff00) == 0xfe00) { /* 256 <= len < 512 */
++ len = 0x0100 | (val & 0x00ff);
++ bits -= 8;
++ i++;
++ } else {
++ bits -= 8;
++ val = (val << 8) | getbyte(ibuf, ++i, l);
++ if ((val & 0xff8000) == 0xff0000) { /* 512 <= len < 1024 */
++ len = 0x000200 | ((val >> 6) & 0x0001ff);
++ bits -= 2;
++ getbits(ibuf, 2 , &i ,&l);
++ } else if ((val & 0xffc000) == 0xff8000) {/* 1024 <= len < 2048 */
++ len = 0x000400 | ((val >> 4) & 0x0003ff);
++ bits -= 4;
++ getbits(ibuf, 4 , &i ,&l);
++ } else if ((val & 0xffe000) == 0xffc000) {/* 2048 <= len < 4096 */
++ len = 0x000800 | ((val >> 2) & 0x0007ff);
++ bits -= 6;
++ getbits(ibuf, 6 , &i ,&l);
++ } else if ((val & 0xfff000) == 0xffe000) {/* 4096 <= len < 8192 */
++ len = 0x001000 | (val & 0x000fff);
++ bits -= 8;
++ i++;
++ } else { /* this shouldn't happen */
++ if (state->debug)
++ printk(KERN_DEBUG "%s%d: wrong length code: 0x%X\n",
++ __FUNCTION__, state->unit, val);
++ return DECOMP_ERROR;
++ }
++ }
++ }
++ s = state->hist + state->histptr;
++ state->histptr += len;
++ olen += len;
++ if (state->histptr < 2*MPPE_HIST_LEN) {
++ /* copy uncompressed bytes to the history */
++
++ /* In some cases len may be greater than off. It means that memory
++ * areas pointed by s and s-off overlap. I had used memmove() here
++ * because I thought that it acts as libc's version. Unfortunately,
++ * I was wrong. :-) I got strange errors sometimes. Wilfried suggested
++ * using of byte by byte copying here and strange errors disappeared.
++ */
++ lamecopy(s, s - off, len);
++ } else {
++ /* buffer overflow; drop packet */
++ if (state->debug)
++ printk(KERN_ERR "%s%d: trying to write outside history "
++ "buffer\n", __FUNCTION__, state->unit);
++ return DECOMP_ERROR;
++ }
++ }
++
++ /* Do PFC decompression */
++ len = olen;
++ if ((history[0] & 0x01) != 0) {
++ obuf[0] = 0;
++ obuf++;
++ len++;
++ }
++
++ if (len <= osize) {
++ /* copy uncompressed packet to the output buffer */
++ memcpy(obuf, history, olen);
++ } else {
++ /* buffer overflow; drop packet */
++ if (state->debug)
++ printk(KERN_ERR "%s%d: too big uncompressed packet: %d\n",
++ __FUNCTION__, state->unit, len + (PPP_HDRLEN / 2));
++ return DECOMP_ERROR;
++ }
++
++ return (int) len;
++}
++
++int
++mppe_decompress(void *arg, unsigned char *ibuf, int isize,
++ unsigned char *obuf, int osize)
++{
++ struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg;
++ int seq, bits, uncomplen;
++
++ if (isize <= PPP_HDRLEN + MPPE_OVHD) {
++ if (state->debug) {
++ printk(KERN_DEBUG "%s%d: short packet (len=%d)\n", __FUNCTION__,
++ state->unit, isize);
++ }
++ return DECOMP_ERROR;
++ }
++
++ /* Get coherency counter and control bits from input buffer */
++ seq = MPPE_CCOUNT(ibuf);
++ bits = MPPE_BITS(ibuf);
++
++ if (state->stateless) {
++ /* RFC 3078, sec 8.1. */
++ mppe_increase_ccount(state);
++ if ((seq != state->ccount) && state->debug)
++ printk(KERN_DEBUG "%s%d: bad sequence number: %d, expected: %d\n",
++ __FUNCTION__, state->unit, seq, state->ccount);
++ while (seq != state->ccount)
++ mppe_increase_ccount(state);
++ } else {
++ /* RFC 3078, sec 8.2. */
++ if (state->flushexpected) { /* discard state */
++ if ((bits & MPPE_BIT_FLUSHED)) { /* we received expected FLUSH bit */
++ while (seq != state->ccount)
++ mppe_increase_ccount(state);
++ state->flushexpected = 0;
++ } else /* drop packet*/
++ return DECOMP_ERROR;
++ } else { /* normal state */
++ mppe_increase_ccount(state);
++ if (seq != state->ccount) {
++ /* Packet loss detected, enter the discard state. */
++ if (state->debug)
++ printk(KERN_DEBUG "%s%d: bad sequence number: %d, expected: %d\n",
++ __FUNCTION__, state->unit, seq, state->ccount);
++ state->flushexpected = 1;
++ return DECOMP_ERROR;
++ }
++ }
++ if (state->mppe && (bits & MPPE_BIT_FLUSHED)) {
++ arc4_setkey(state, state->session_key, state->keylen);
++ }
++ }
++
++ if (state->mppc && (bits & (MPPE_BIT_FLUSHED | MPPE_BIT_RESET))) {
++ state->histptr = MPPE_HIST_LEN;
++ if ((bits & MPPE_BIT_FLUSHED)) {
++ memset(state->hist + MPPE_HIST_LEN, 0, MPPE_HIST_LEN*sizeof(u8));
++ } else
++ if ((bits & MPPE_BIT_RESET)) {
++ memcpy(state->hist, state->hist + MPPE_HIST_LEN, MPPE_HIST_LEN);
++ }
++ }
++
++ /* Fill in the first part of the PPP header. The protocol field
++ comes from the decompressed data. */
++ obuf[0] = PPP_ADDRESS(ibuf);
++ obuf[1] = PPP_CONTROL(ibuf);
++ obuf += PPP_HDRLEN / 2;
++
++ if (state->mppe) { /* process encrypted packet */
++ if ((bits & MPPE_BIT_ENCRYPTED)) {
++ /* OK, packet encrypted, so decrypt it */
++ if (state->mppc && (bits & MPPE_BIT_COMP)) {
++ /* Hack warning !!! RC4 implementation which we use does
++ decryption "in place" - it means that input and output
++ buffers can be *the same* memory area. Therefore we don't
++ need to use a temporary buffer. But be careful - other
++ implementations don't have to be so nice. */
++ arc4_decrypt(state, ibuf + PPP_HDRLEN + (MPPE_OVHD / 2), isize -
++ PPP_HDRLEN - (MPPE_OVHD / 2), ibuf + PPP_HDRLEN +
++ (MPPE_OVHD / 2));
++ uncomplen = mppc_decompress(state, ibuf + PPP_HDRLEN +
++ (MPPE_OVHD / 2), obuf, isize -
++ PPP_HDRLEN - (MPPE_OVHD / 2),
++ osize - (PPP_HDRLEN / 2));
++ if (uncomplen == DECOMP_ERROR) {
++ state->flushexpected = 1;
++ return DECOMP_ERROR;
++ }
++ uncomplen += PPP_HDRLEN / 2;
++ (state->stats).comp_bytes += isize;
++ (state->stats).comp_packets++;
++ } else {
++ uncomplen = isize - MPPE_OVHD;
++ /* Decrypt the first byte in order to check if it is
++ compressed or uncompressed protocol field */
++ arc4_decrypt(state, ibuf + PPP_HDRLEN + (MPPE_OVHD / 2), 1, obuf);
++ /* Do PFC decompression */
++ if ((obuf[0] & 0x01) != 0) {
++ obuf[1] = obuf[0];
++ obuf[0] = 0;
++ obuf++;
++ uncomplen++;
++ }
++ /* And finally, decrypt the rest of the frame. */
++ arc4_decrypt(state, ibuf + PPP_HDRLEN + (MPPE_OVHD / 2) + 1,
++ isize - PPP_HDRLEN - (MPPE_OVHD / 2) - 1, obuf + 1);
++ (state->stats).inc_bytes += isize;
++ (state->stats).inc_packets++;
++ }
++ } else { /* this shouldn't happen */
++ if (state->debug)
++ printk(KERN_ERR "%s%d: encryption negotiated but not an "
++ "encrypted packet received\n", __FUNCTION__, state->unit);
++ mppe_change_key(state, 0);
++ state->flushexpected = 1;
++ return DECOMP_ERROR;
++ }
++ } else {
++ if (state->mppc) { /* no MPPE, only MPPC */
++ if ((bits & MPPE_BIT_COMP)) {
++ uncomplen = mppc_decompress(state, ibuf + PPP_HDRLEN +
++ (MPPE_OVHD / 2), obuf, isize -
++ PPP_HDRLEN - (MPPE_OVHD / 2),
++ osize - (PPP_HDRLEN / 2));
++ if (uncomplen == DECOMP_ERROR) {
++ state->flushexpected = 1;
++ return DECOMP_ERROR;
++ }
++ uncomplen += PPP_HDRLEN / 2;
++ (state->stats).comp_bytes += isize;
++ (state->stats).comp_packets++;
++ } else {
++ memcpy(obuf, ibuf + PPP_HDRLEN + (MPPE_OVHD / 2), isize -
++ PPP_HDRLEN - (MPPE_OVHD / 2));
++ uncomplen = isize - MPPE_OVHD;
++ (state->stats).inc_bytes += isize;
++ (state->stats).inc_packets++;
++ }
++ } else { /* this shouldn't happen */
++ if (state->debug)
++ printk(KERN_ERR "%s%d: error - not an MPPC or MPPE frame "
++ "received\n", __FUNCTION__, state->unit);
++ state->flushexpected = 1;
++ return DECOMP_ERROR;
++ }
++ }
++
++ (state->stats).unc_bytes += uncomplen;
++ (state->stats).unc_packets++;
++
++ return uncomplen;
++}
++
++
++/************************************************************
++ * Module interface table
++ ************************************************************/
++
++/* These are in ppp_generic.c */
++extern int ppp_register_compressor (struct compressor *cp);
++extern void ppp_unregister_compressor (struct compressor *cp);
++
++/*
++ * Functions exported to ppp_generic.c.
++ *
++ * In case of MPPC/MPPE there is no need to process incompressible data
++ * because such a data is sent in MPPC/MPPE frame. Therefore the (*incomp)
++ * callback function isn't needed.
++ */
++struct compressor ppp_mppe = {
++ CI_MPPE, /* compress_proto */
++ mppe_comp_alloc, /* comp_alloc */
++ mppe_comp_free, /* comp_free */
++ mppe_comp_init, /* comp_init */
++ mppe_comp_reset, /* comp_reset */
++ mppe_compress, /* compress */
++ mppe_stats, /* comp_stat */
++ mppe_decomp_alloc, /* decomp_alloc */
++ mppe_comp_free, /* decomp_free */
++ mppe_decomp_init, /* decomp_init */
++ mppe_decomp_reset, /* decomp_reset */
++ mppe_decompress, /* decompress */
++ NULL, /* incomp */
++ mppe_stats, /* decomp_stat */
++};
++
++/************************************************************
++ * Module support routines
++ ************************************************************/
++
++int __init mppe_module_init(void)
++{
++ int answer;
++
++ /* When the module is compiled into kernel, it is initialized before
++ * CryptoAPI. Therefore the code below reports that there is no crypto
++ * stuff in the kernel. Marlon de Boer who has pointed out the problem,
++ * has sent also a message to CryptoAPI developers, so maybe in the future
++ * the code will be uncommented.
++ *
++ if (!(crypto_alg_available("arc4", 0) && crypto_alg_available("sha1", 0))) {
++ printk(KERN_ERR "Kernel doesn't provide ARC4 and/or SHA1 algorithms "
++ "required by MPPE/MPPC. Check CryptoAPI configuration.\n");
++ return -ENODEV;
++ }
++ */
++
++ /* Allocate space for SHAPad1, SHAPad2 and ... */
++ sha_pad = kmalloc(sizeof(struct sha_pad), GFP_KERNEL);
++ if (sha_pad == NULL)
++ return -ENOMEM;
++ /* ... initialize them */
++ memset(sha_pad->sha_pad1, 0x00, sizeof(sha_pad->sha_pad1));
++ memset(sha_pad->sha_pad2, 0xf2, sizeof(sha_pad->sha_pad2));
++
++ answer = ppp_register_compressor(&ppp_mppe);
++ if (answer == 0) {
++ printk(KERN_INFO "MPPE/MPPC encryption/compression module registered\n");
++ }
++ return answer;
++}
++
++void __exit mppe_module_cleanup(void)
++{
++ kfree(sha_pad);
++ ppp_unregister_compressor(&ppp_mppe);
++ printk(KERN_INFO "MPPE/MPPC encryption/compression module unregistered\n");
++}
++
++module_init(mppe_module_init);
++module_exit(mppe_module_cleanup);
++
++MODULE_AUTHOR("Jan Dubiec <jdx@slackware.pl>");
++MODULE_DESCRIPTION("MPPE/MPPC encryption/compression module for Linux");
++MODULE_LICENSE("Dual BSD/GPL");
+diff -ruN linux-2.4.29.orig/include/linux/ppp-comp.h linux-2.4.29/include/linux/ppp-comp.h
+--- linux-2.4.29.orig/include/linux/ppp-comp.h 2005-02-02 22:18:25.000000000 +0100
++++ linux-2.4.29/include/linux/ppp-comp.h 2005-02-02 22:41:01.000000000 +0100
+@@ -28,7 +28,7 @@
+ */
+
+ /*
+- * ==FILEVERSION 980319==
++ * ==FILEVERSION 20040509==
+ *
+ * NOTE TO MAINTAINERS:
+ * If you modify this file at all, please set the above date.
+@@ -78,7 +78,7 @@
+
+ /* Compress a packet */
+ int (*compress) (void *state, unsigned char *rptr,
+- unsigned char *obuf, int isize, int osize);
++ unsigned char *obuf, int isize, int osize);
+
+ /* Return compression statistics */
+ void (*comp_stat) (void *state, struct compstat *stats);
+@@ -99,7 +99,7 @@
+
+ /* Decompress a packet. */
+ int (*decompress) (void *state, unsigned char *ibuf, int isize,
+- unsigned char *obuf, int osize);
++ unsigned char *obuf, int osize);
+
+ /* Update state for an incompressible packet received */
+ void (*incomp) (void *state, unsigned char *ibuf, int icnt);
+@@ -187,6 +187,42 @@
+ #define DEFLATE_CHK_SEQUENCE 0
+
+ /*
++ * Definitions for MPPE/MPPC.
++ */
++
++#define CI_MPPE 18 /* config option for MPPE */
++#define CILEN_MPPE 6 /* length of config option */
++
++#define MPPE_OVHD 4 /* MPPE overhead */
++#define MPPE_MAX_KEY_LEN 16 /* largest key length (128-bit) */
++
++#define MPPE_STATELESS 0x01 /* configuration bit H */
++#define MPPE_40BIT 0x20 /* configuration bit L */
++#define MPPE_56BIT 0x80 /* configuration bit M */
++#define MPPE_128BIT 0x40 /* configuration bit S */
++#define MPPE_MPPC 0x01 /* 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.
+ */
+
diff --git a/target/linux/generic-2.4/patches/107-cifs.patch b/target/linux/generic-2.4/patches/107-cifs.patch
new file mode 100644
index 0000000000..bdccf4de9f
--- /dev/null
+++ b/target/linux/generic-2.4/patches/107-cifs.patch
@@ -0,0 +1,22022 @@
+diff -urN linux-2.4.29.old/Documentation/Configure.help linux-2.4.29/Documentation/Configure.help
+--- linux-2.4.29.old/Documentation/Configure.help 2005-03-21 19:30:22.000000000 +0100
++++ linux-2.4.29/Documentation/Configure.help 2005-03-21 19:36:51.000000000 +0100
+@@ -17943,6 +17943,34 @@
+
+ If you don't know what all this is about, say N.
+
++CIFS (Common Internet File System) support
++CONFIG_CIFS
++ This is the client VFS module for the Common Internet File System
++ (CIFS) protocol which is the successor to the Server Message Block
++ (SMB) protocol, the native file sharing mechanism for most early
++ PC operating systems. CIFS is fully supported by current network
++ file servers such as Windows 2000, Windows 2003 (including
++ Windows XP) as well by Samba (which provides excellent CIFS
++ server support for Linux and many other operating systems).
++ The smbfs module should be used instead of this cifs module for
++ mounting to older SMB servers such as OS/2. The smbfs and cifs
++ modules can coexist and do not conflict.
++
++ The intent of this module is to provide the most advanced network
++ file system function for CIFS compliant servers, including better
++ POSIX compliance, secure per-user session establishment, high
++ performance safe distributed caching (oplock), optional packet
++ signing, Unicode support and other internationalization improvements
++ For more information see the project page at
++ http://us1.samba.org/samba/Linux_CIFS_client.html
++
++CIFS Debugging
++CONFIG_CIFS_DEBUG
++ If you are experiencing any problems with the CIFS filesystem, say
++ Y here. This will result in additional debugging messages to be
++ written to the system log. Under normal circumstances, this
++ results in very little overhead.
++
+ SMB file system support (to mount Windows shares etc.)
+ CONFIG_SMB_FS
+ SMB (Server Message Block) is the protocol Windows for Workgroups
+diff -urN linux-2.4.29.old/Documentation/filesystems/00-INDEX linux-2.4.29/Documentation/filesystems/00-INDEX
+--- linux-2.4.29.old/Documentation/filesystems/00-INDEX 2004-02-18 14:36:30.000000000 +0100
++++ linux-2.4.29/Documentation/filesystems/00-INDEX 2005-03-21 19:36:51.000000000 +0100
+@@ -10,6 +10,8 @@
+ - info for the BeOS file system (BFS)
+ bfs.txt
+ - info for the SCO UnixWare Boot Filesystem (BFS).
++cifs.txt
++ - info on the Common Internet File System (CIFS)
+ coda.txt
+ - description of the CODA filesystem.
+ cramfs.txt
+diff -urN linux-2.4.29.old/Documentation/filesystems/cifs.txt linux-2.4.29/Documentation/filesystems/cifs.txt
+--- linux-2.4.29.old/Documentation/filesystems/cifs.txt 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/Documentation/filesystems/cifs.txt 2005-03-21 19:36:51.000000000 +0100
+@@ -0,0 +1,51 @@
++ This is the client VFS module for the Common Internet File System
++ (CIFS) protocol which is the successor to the Server Message Block
++ (SMB) protocol, the native file sharing mechanism for most early
++ PC operating systems. CIFS is fully supported by current network
++ file servers such as Windows 2000, Windows 2003 (including
++ Windows XP) as well by Samba (which provides excellent CIFS
++ server support for Linux and many other operating systems), so
++ this network filesystem client can mount to a wide variety of
++ servers. The smbfs module should be used instead of this cifs module
++ for mounting to older SMB servers such as OS/2. The smbfs and cifs
++ modules can coexist and do not conflict. The CIFS VFS filesystem
++ module is designed to work well with servers that implement the
++ newer versions (dialects) of the SMB/CIFS protocol such as Samba,
++ the program written by Andrew Tridgell that turns any Unix host
++ into a SMB/CIFS file server.
++
++ The intent of this module is to provide the most advanced network
++ file system function for CIFS compliant servers, including better
++ POSIX compliance, secure per-user session establishment, high
++ performance safe distributed caching (oplock), optional packet
++ signing, large files, Unicode support and other internationalization
++ improvements. Since both Samba server and this filesystem client support
++ the CIFS Unix extensions, the combination can provide a reasonable
++ alternative to NFSv4 for fileserving in some Linux to Linux environments,
++ not just in Linux to Windows environments.
++
++ This filesystem has an optional mount utility (mount.cifs) that can
++ be obtained from the project page and installed in the path in the same
++ directory with the other mount helpers (such as mount.smbfs).
++ Mounting using the cifs filesystem without installing the mount helper
++ requires specifying the server's ip address.
++
++ For Linux 2.4:
++ mount //anything/here /mnt_target -o
++ user=username,pass=password,unc=//ip_address_of_server/sharename
++
++ For Linux 2.5:
++ mount //ip_address_of_server/sharename /mnt_target -o user=username, pass=password
++
++
++ For more information on the module see the project page at
++
++ http://us1.samba.org/samba/Linux_CIFS_client.html
++
++ For more information on CIFS see:
++
++ http://www.snia.org/tech_activities/CIFS
++
++ or the Samba site:
++
++ http://www.samba.org
+diff -urN linux-2.4.29.old/fs/cifs/asn1.c linux-2.4.29/fs/cifs/asn1.c
+--- linux-2.4.29.old/fs/cifs/asn1.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/asn1.c 2004-07-14 00:25:04.000000000 +0200
+@@ -0,0 +1,614 @@
++/*
++ * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
++ * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
++ *
++ * Copyright (c) 2000 RP Internet (www.rpi.net.au).
++ *
++ * 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/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include "cifspdu.h"
++#include "cifsglob.h"
++#include "cifs_debug.h"
++
++/*****************************************************************************
++ *
++ * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
++ *
++ *****************************************************************************/
++
++/* Class */
++#define ASN1_UNI 0 /* Universal */
++#define ASN1_APL 1 /* Application */
++#define ASN1_CTX 2 /* Context */
++#define ASN1_PRV 3 /* Private */
++
++/* Tag */
++#define ASN1_EOC 0 /* End Of Contents or N/A */
++#define ASN1_BOL 1 /* Boolean */
++#define ASN1_INT 2 /* Integer */
++#define ASN1_BTS 3 /* Bit String */
++#define ASN1_OTS 4 /* Octet String */
++#define ASN1_NUL 5 /* Null */
++#define ASN1_OJI 6 /* Object Identifier */
++#define ASN1_OJD 7 /* Object Description */
++#define ASN1_EXT 8 /* External */
++#define ASN1_SEQ 16 /* Sequence */
++#define ASN1_SET 17 /* Set */
++#define ASN1_NUMSTR 18 /* Numerical String */
++#define ASN1_PRNSTR 19 /* Printable String */
++#define ASN1_TEXSTR 20 /* Teletext String */
++#define ASN1_VIDSTR 21 /* Video String */
++#define ASN1_IA5STR 22 /* IA5 String */
++#define ASN1_UNITIM 23 /* Universal Time */
++#define ASN1_GENTIM 24 /* General Time */
++#define ASN1_GRASTR 25 /* Graphical String */
++#define ASN1_VISSTR 26 /* Visible String */
++#define ASN1_GENSTR 27 /* General String */
++
++/* Primitive / Constructed methods*/
++#define ASN1_PRI 0 /* Primitive */
++#define ASN1_CON 1 /* Constructed */
++
++/*
++ * Error codes.
++ */
++#define ASN1_ERR_NOERROR 0
++#define ASN1_ERR_DEC_EMPTY 2
++#define ASN1_ERR_DEC_EOC_MISMATCH 3
++#define ASN1_ERR_DEC_LENGTH_MISMATCH 4
++#define ASN1_ERR_DEC_BADVALUE 5
++
++#define SPNEGO_OID_LEN 7
++#define NTLMSSP_OID_LEN 10
++unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
++unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
++
++/*
++ * ASN.1 context.
++ */
++struct asn1_ctx {
++ int error; /* Error condition */
++ unsigned char *pointer; /* Octet just to be decoded */
++ unsigned char *begin; /* First octet */
++ unsigned char *end; /* Octet after last octet */
++};
++
++/*
++ * Octet string (not null terminated)
++ */
++struct asn1_octstr {
++ unsigned char *data;
++ unsigned int len;
++};
++
++static void
++asn1_open(struct asn1_ctx *ctx, unsigned char *buf, unsigned int len)
++{
++ ctx->begin = buf;
++ ctx->end = buf + len;
++ ctx->pointer = buf;
++ ctx->error = ASN1_ERR_NOERROR;
++}
++
++static unsigned char
++asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
++{
++ if (ctx->pointer >= ctx->end) {
++ ctx->error = ASN1_ERR_DEC_EMPTY;
++ return 0;
++ }
++ *ch = *(ctx->pointer)++;
++ return 1;
++}
++
++static unsigned char
++asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
++{
++ unsigned char ch;
++
++ *tag = 0;
++
++ do {
++ if (!asn1_octet_decode(ctx, &ch))
++ return 0;
++ *tag <<= 7;
++ *tag |= ch & 0x7F;
++ } while ((ch & 0x80) == 0x80);
++ return 1;
++}
++
++static unsigned char
++asn1_id_decode(struct asn1_ctx *ctx,
++ unsigned int *cls, unsigned int *con, unsigned int *tag)
++{
++ unsigned char ch;
++
++ if (!asn1_octet_decode(ctx, &ch))
++ return 0;
++
++ *cls = (ch & 0xC0) >> 6;
++ *con = (ch & 0x20) >> 5;
++ *tag = (ch & 0x1F);
++
++ if (*tag == 0x1F) {
++ if (!asn1_tag_decode(ctx, tag))
++ return 0;
++ }
++ return 1;
++}
++
++static unsigned char
++asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len)
++{
++ unsigned char ch, cnt;
++
++ if (!asn1_octet_decode(ctx, &ch))
++ return 0;
++
++ if (ch == 0x80)
++ *def = 0;
++ else {
++ *def = 1;
++
++ if (ch < 0x80)
++ *len = ch;
++ else {
++ cnt = (unsigned char) (ch & 0x7F);
++ *len = 0;
++
++ while (cnt > 0) {
++ if (!asn1_octet_decode(ctx, &ch))
++ return 0;
++ *len <<= 8;
++ *len |= ch;
++ cnt--;
++ }
++ }
++ }
++ return 1;
++}
++
++static unsigned char
++asn1_header_decode(struct asn1_ctx *ctx,
++ unsigned char **eoc,
++ unsigned int *cls, unsigned int *con, unsigned int *tag)
++{
++ unsigned int def, len;
++
++ if (!asn1_id_decode(ctx, cls, con, tag))
++ return 0;
++
++ if (!asn1_length_decode(ctx, &def, &len))
++ return 0;
++
++ if (def)
++ *eoc = ctx->pointer + len;
++ else
++ *eoc = NULL;
++ return 1;
++}
++
++static unsigned char
++asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
++{
++ unsigned char ch;
++
++ if (eoc == 0) {
++ if (!asn1_octet_decode(ctx, &ch))
++ return 0;
++
++ if (ch != 0x00) {
++ ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
++ return 0;
++ }
++
++ if (!asn1_octet_decode(ctx, &ch))
++ return 0;
++
++ if (ch != 0x00) {
++ ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
++ return 0;
++ }
++ return 1;
++ } else {
++ if (ctx->pointer != eoc) {
++ ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;
++ return 0;
++ }
++ return 1;
++ }
++}
++
++/* static unsigned char asn1_null_decode(struct asn1_ctx *ctx,
++ unsigned char *eoc)
++{
++ ctx->pointer = eoc;
++ return 1;
++}
++
++static unsigned char asn1_long_decode(struct asn1_ctx *ctx,
++ unsigned char *eoc, long *integer)
++{
++ unsigned char ch;
++ unsigned int len;
++
++ if (!asn1_octet_decode(ctx, &ch))
++ return 0;
++
++ *integer = (signed char) ch;
++ len = 1;
++
++ while (ctx->pointer < eoc) {
++ if (++len > sizeof(long)) {
++ ctx->error = ASN1_ERR_DEC_BADVALUE;
++ return 0;
++ }
++
++ if (!asn1_octet_decode(ctx, &ch))
++ return 0;
++
++ *integer <<= 8;
++ *integer |= ch;
++ }
++ return 1;
++}
++
++static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,
++ unsigned char *eoc,
++ unsigned int *integer)
++{
++ unsigned char ch;
++ unsigned int len;
++
++ if (!asn1_octet_decode(ctx, &ch))
++ return 0;
++
++ *integer = ch;
++ if (ch == 0)
++ len = 0;
++ else
++ len = 1;
++
++ while (ctx->pointer < eoc) {
++ if (++len > sizeof(unsigned int)) {
++ ctx->error = ASN1_ERR_DEC_BADVALUE;
++ return 0;
++ }
++
++ if (!asn1_octet_decode(ctx, &ch))
++ return 0;
++
++ *integer <<= 8;
++ *integer |= ch;
++ }
++ return 1;
++}
++
++static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
++ unsigned char *eoc,
++ unsigned long *integer)
++{
++ unsigned char ch;
++ unsigned int len;
++
++ if (!asn1_octet_decode(ctx, &ch))
++ return 0;
++
++ *integer = ch;
++ if (ch == 0)
++ len = 0;
++ else
++ len = 1;
++
++ while (ctx->pointer < eoc) {
++ if (++len > sizeof(unsigned long)) {
++ ctx->error = ASN1_ERR_DEC_BADVALUE;
++ return 0;
++ }
++
++ if (!asn1_octet_decode(ctx, &ch))
++ return 0;
++
++ *integer <<= 8;
++ *integer |= ch;
++ }
++ return 1;
++}
++
++static unsigned char
++asn1_octets_decode(struct asn1_ctx *ctx,
++ unsigned char *eoc,
++ unsigned char **octets, unsigned int *len)
++{
++ unsigned char *ptr;
++
++ *len = 0;
++
++ *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
++ if (*octets == NULL) {
++ return 0;
++ }
++
++ ptr = *octets;
++ while (ctx->pointer < eoc) {
++ if (!asn1_octet_decode(ctx, (unsigned char *) ptr++)) {
++ kfree(*octets);
++ *octets = NULL;
++ return 0;
++ }
++ (*len)++;
++ }
++ return 1;
++} */
++
++static unsigned char
++asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid)
++{
++ unsigned char ch;
++
++ *subid = 0;
++
++ do {
++ if (!asn1_octet_decode(ctx, &ch))
++ return 0;
++
++ *subid <<= 7;
++ *subid |= ch & 0x7F;
++ } while ((ch & 0x80) == 0x80);
++ return 1;
++}
++
++static unsigned char
++asn1_oid_decode(struct asn1_ctx *ctx,
++ unsigned char *eoc, unsigned long **oid, unsigned int *len)
++{
++ unsigned long subid;
++ unsigned int size;
++ unsigned long *optr;
++
++ size = eoc - ctx->pointer + 1;
++ *oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC);
++ if (*oid == NULL) {
++ return 0;
++ }
++
++ optr = *oid;
++
++ if (!asn1_subid_decode(ctx, &subid)) {
++ kfree(*oid);
++ *oid = NULL;
++ return 0;
++ }
++
++ if (subid < 40) {
++ optr[0] = 0;
++ optr[1] = subid;
++ } else if (subid < 80) {
++ optr[0] = 1;
++ optr[1] = subid - 40;
++ } else {
++ optr[0] = 2;
++ optr[1] = subid - 80;
++ }
++
++ *len = 2;
++ optr += 2;
++
++ while (ctx->pointer < eoc) {
++ if (++(*len) > size) {
++ ctx->error = ASN1_ERR_DEC_BADVALUE;
++ kfree(*oid);
++ *oid = NULL;
++ return 0;
++ }
++
++ if (!asn1_subid_decode(ctx, optr++)) {
++ kfree(*oid);
++ *oid = NULL;
++ return 0;
++ }
++ }
++ return 1;
++}
++
++static int
++compare_oid(unsigned long *oid1, unsigned int oid1len,
++ unsigned long *oid2, unsigned int oid2len)
++{
++ unsigned int i;
++
++ if (oid1len != oid2len)
++ return 0;
++ else {
++ for (i = 0; i < oid1len; i++) {
++ if (oid1[i] != oid2[i])
++ return 0;
++ }
++ return 1;
++ }
++}
++
++ /* BB check for endian conversion issues here */
++
++int
++decode_negTokenInit(unsigned char *security_blob, int length,
++ enum securityEnum *secType)
++{
++ struct asn1_ctx ctx;
++ unsigned char *end;
++ unsigned char *sequence_end;
++ unsigned long *oid;
++ unsigned int cls, con, tag, oidlen, rc;
++ int use_ntlmssp = FALSE;
++
++ *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */
++
++ /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
++
++ asn1_open(&ctx, security_blob, length);
++
++ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
++ cFYI(1, ("Error decoding negTokenInit header "));
++ return 0;
++ } else if ((cls != ASN1_APL) || (con != ASN1_CON)
++ || (tag != ASN1_EOC)) {
++ cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag));
++ return 0;
++ } else {
++ /* remember to free obj->oid */
++ rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
++ if (rc) {
++ if ((tag == ASN1_OJI) && (cls == ASN1_PRI)) {
++ rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
++ if (rc) {
++ rc = compare_oid(oid, oidlen,
++ SPNEGO_OID,
++ SPNEGO_OID_LEN);
++ kfree(oid);
++ }
++ } else
++ rc = 0;
++ }
++
++ if (!rc) {
++ cFYI(1, ("Error decoding negTokenInit header"));
++ return 0;
++ }
++
++ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
++ cFYI(1, ("Error decoding negTokenInit "));
++ return 0;
++ } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
++ || (tag != ASN1_EOC)) {
++ cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 0",
++ cls, con, tag, end, *end));
++ return 0;
++ }
++
++ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
++ cFYI(1, ("Error decoding negTokenInit "));
++ return 0;
++ } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
++ || (tag != ASN1_SEQ)) {
++ cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 1",
++ cls, con, tag, end, *end));
++ return 0;
++ }
++
++ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
++ cFYI(1, ("Error decoding 2nd part of negTokenInit "));
++ return 0;
++ } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
++ || (tag != ASN1_EOC)) {
++ cFYI(1,
++ ("cls = %d con = %d tag = %d end = %p (%d) exit 0",
++ cls, con, tag, end, *end));
++ return 0;
++ }
++
++ if (asn1_header_decode
++ (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
++ cFYI(1, ("Error decoding 2nd part of negTokenInit "));
++ return 0;
++ } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
++ || (tag != ASN1_SEQ)) {
++ cFYI(1,
++ ("cls = %d con = %d tag = %d end = %p (%d) exit 1",
++ cls, con, tag, end, *end));
++ return 0;
++ }
++
++ while (!asn1_eoc_decode(&ctx, sequence_end)) {
++ rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
++ if (!rc) {
++ cFYI(1,
++ ("Error 1 decoding negTokenInit header exit 2"));
++ return 0;
++ }
++ if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
++ asn1_oid_decode(&ctx, end, &oid, &oidlen);
++ cFYI(1,
++ ("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
++ oidlen, *oid, *(oid + 1), *(oid + 2),
++ *(oid + 3)));
++ rc = compare_oid(oid, oidlen, NTLMSSP_OID,
++ NTLMSSP_OID_LEN);
++ kfree(oid);
++ if (rc)
++ use_ntlmssp = TRUE;
++ } else {
++ cFYI(1,("This should be an oid what is going on? "));
++ }
++ }
++
++ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
++ cFYI(1,
++ ("Error decoding last part of negTokenInit exit 3"));
++ return 0;
++ } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { /* tag = 3 indicating mechListMIC */
++ cFYI(1,
++ ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
++ cls, con, tag, end, *end));
++ return 0;
++ }
++ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
++ cFYI(1,
++ ("Error decoding last part of negTokenInit exit 5"));
++ return 0;
++ } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
++ || (tag != ASN1_SEQ)) {
++ cFYI(1,
++ ("Exit 6 cls = %d con = %d tag = %d end = %p (%d)",
++ cls, con, tag, end, *end));
++ }
++
++ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
++ cFYI(1,
++ ("Error decoding last part of negTokenInit exit 7"));
++ return 0;
++ } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
++ cFYI(1,
++ ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
++ cls, con, tag, end, *end));
++ return 0;
++ }
++ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
++ cFYI(1,
++ ("Error decoding last part of negTokenInit exit 9"));
++ return 0;
++ } else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
++ || (tag != ASN1_GENSTR)) {
++ cFYI(1,
++ ("Exit 10 cls = %d con = %d tag = %d end = %p (%d)",
++ cls, con, tag, end, *end));
++ return 0;
++ }
++ cFYI(1, ("Need to call asn1_octets_decode() function for this %s", ctx.pointer)); /* is this UTF-8 or ASCII? */
++ }
++
++ /* if (use_kerberos)
++ *secType = Kerberos
++ else */
++ if (use_ntlmssp) {
++ *secType = NTLMSSP;
++ }
++
++ return 1;
++}
+diff -urN linux-2.4.29.old/fs/cifs/AUTHORS linux-2.4.29/fs/cifs/AUTHORS
+--- linux-2.4.29.old/fs/cifs/AUTHORS 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/AUTHORS 2004-07-14 00:25:04.000000000 +0200
+@@ -0,0 +1,37 @@
++Original Author
++===============
++Steve French (sfrench@samba.org)
++
++The author wishes to express his appreciation and thanks to:
++Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS
++improvements. Thanks to IBM for allowing me the time and test resources to pursue
++this project. Jim McDonough from IBM (and the Samba Team) for his help.
++The IBM Linux JFS team for explaining many esoteric Linux filesystem features.
++Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client)
++for proving years ago that a very good smb/cifs client could be done on a Unix like
++operating system. Volker Lendecke, Andrew Tridgell, Urban Widmark, John Newbigin
++and others for their work on the Linux smbfs module over the years. Thanks to
++the other members of the Storage Network Industry Association CIFS Technical
++Workgroup for their work specifying this highly complex protocol and finally
++thanks to the Samba team for their technical advice and encouragement.
++
++Patch Contributors
++------------------
++Zwane Mwaikambo
++Andi Kleen
++Amrut Joshi
++Shobhit Dayal
++Sergey Vlasov
++Richard Hughes
++Yury Umanets
++
++Test case and Bug Report contributors
++-------------------------------------
++Thanks to those in the community who have submitted detailed bug reports
++and debug of problems they have found: Jochen Dolze, David Blaine,
++Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori,
++Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
++Olaf Kirch, Kieron Briggs, Nick Millington and others.
++
++And thanks to the IBM LTC and Power test teams and SuSE testers for
++finding multiple bugs during excellent stress test runs.
+diff -urN linux-2.4.29.old/fs/cifs/CHANGES linux-2.4.29/fs/cifs/CHANGES
+--- linux-2.4.29.old/fs/cifs/CHANGES 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/CHANGES 2004-07-14 00:25:04.000000000 +0200
+@@ -0,0 +1,572 @@
++Version 1.20
++------------
++Make transaction counts more consistent. Merge /proc/fs/cifs/SimultaneousOps
++info into /proc/fs/cifs/DebugData. Fix oops in rare oops in readdir
++(in build_wildcard_path_from_dentry). Fix mknod to pass type field
++(block/char/fifo) properly. Remove spurious mount warning log entry when
++credentials passed as mount argument. Set major/minor device number in
++inode for block and char devices when unix extensions enabled.
++
++Version 1.19
++------------
++Fix /proc/fs/cifs/Stats and DebugData display to handle larger
++amounts of return data. Properly limit requests to MAX_REQ (50
++is the usual maximum active multiplex SMB/CIFS requests per server).
++Do not kill cifsd (and thus hurt the other SMB session) when more than one
++session to the same server (but with different userids) exists and one
++of the two user's smb sessions is being removed while leaving the other.
++Do not loop reconnecting in cifsd demultiplex thread when admin
++kills the thread without going through unmount.
++
++Version 1.18
++------------
++Do not rename hardlinked files (since that should be a noop). Flush
++cached write behind data when reopening a file after session abend,
++except when already in write. Grab per socket sem during reconnect
++to avoid oops in sendmsg if overlapping with reconnect. Do not
++reset cached inode file size on readdir for files open for write on
++client.
++
++
++Version 1.17
++------------
++Update number of blocks in file so du command is happier (in Linux a fake
++blocksize of 512 is required for calculating number of blocks in inode).
++Fix prepare write of partial pages to read in data from server if possible.
++Fix race on tcpStatus field between unmount and reconnection code, causing
++cifsd process sometimes to hang around forever. Improve out of memory
++checks in cifs_filldir
++
++Version 1.16
++------------
++Fix incorrect file size in file handle based setattr on big endian hardware.
++Fix oops in build_path_from_dentry when out of memory. Add checks for invalid
++and closing file structs in writepage/partialpagewrite. Add statistics
++for each mounted share (new menuconfig option). Fix endianness problem in
++volume information displayed in /proc/fs/cifs/DebugData (only affects
++affects big endian architectures). Prevent renames while constructing
++path names for open, mkdir and rmdir.
++
++Version 1.15
++------------
++Change to mempools for alloc smb request buffers and multiplex structs
++to better handle low memory problems (and potential deadlocks).
++
++Version 1.14
++------------
++Fix incomplete listings of large directories on Samba servers when Unix
++extensions enabled. Fix oops when smb_buffer can not be allocated. Fix
++rename deadlock when writing out dirty pages at same time.
++
++Version 1.13
++------------
++Fix open of files in which O_CREATE can cause the mode to change in
++some cases. Fix case in which retry of write overlaps file close.
++Fix PPC64 build error. Reduce excessive stack usage in smb password
++hashing. Fix overwrite of Linux user's view of file mode to Windows servers.
++
++Version 1.12
++------------
++Fixes for large file copy, signal handling, socket retry, buffer
++allocation and low memory situations.
++
++Version 1.11
++------------
++Better port 139 support to Windows servers (RFC1001/RFC1002 Session_Initialize)
++also now allowing support for specifying client netbiosname. NT4 support added.
++
++Version 1.10
++------------
++Fix reconnection (and certain failed mounts) to properly wake up the
++blocked users thread so it does not seem hung (in some cases was blocked
++until the cifs receive timeout expired). Fix spurious error logging
++to kernel log when application with open network files killed.
++
++Version 1.09
++------------
++Fix /proc/fs module unload warning message (that could be logged
++to the kernel log). Fix intermittent failure in connectathon
++test7 (hardlink count not immediately refreshed in case in which
++inode metadata can be incorrectly kept cached when time near zero)
++
++Version 1.08
++------------
++Allow file_mode and dir_mode (specified at mount time) to be enforced
++locally (the server already enforced its own ACLs too) for servers
++that do not report the correct mode (do not support the
++CIFS Unix Extensions).
++
++Version 1.07
++------------
++Fix some small memory leaks in some unmount error paths. Fix major leak
++of cache pages in readpages causing multiple read oriented stress
++testcases (including fsx, and even large file copy) to fail over time.
++
++Version 1.06
++------------
++Send NTCreateX with ATTR_POSIX if Linux/Unix extensions negotiated with server.
++This allows files that differ only in case and improves performance of file
++creation and file open to such servers. Fix semaphore conflict which causes
++slow delete of open file to Samba (which unfortunately can cause an oplock
++break to self while vfs_unlink held i_sem) which can hang for 20 seconds.
++
++Version 1.05
++------------
++fixes to cifs_readpages for fsx test case
++
++Version 1.04
++------------
++Fix caching data integrity bug when extending file size especially when no
++oplock on file. Fix spurious logging of valid already parsed mount options
++that are parsed outside of the cifs vfs such as nosuid.
++
++
++Version 1.03
++------------
++Connect to server when port number override not specified, and tcp port
++unitialized. Reset search to restart at correct file when kernel routine
++filldir returns error during large directory searches (readdir).
++
++Version 1.02
++------------
++Fix caching problem when files opened by multiple clients in which
++page cache could contain stale data, and write through did
++not occur often enough while file was still open when read ahead
++(read oplock) not allowed. Treat "sep=" when first mount option
++as an overrride of comma as the default separator between mount
++options.
++
++Version 1.01
++------------
++Allow passwords longer than 16 bytes. Allow null password string.
++
++Version 1.00
++------------
++Gracefully clean up failed mounts when attempting to mount to servers such as
++Windows 98 that terminate tcp sessions during prototocol negotiation. Handle
++embedded commas in mount parsing of passwords.
++
++Version 0.99
++------------
++Invalidate local inode cached pages on oplock break and when last file
++instance is closed so that the client does not continue using stale local
++copy rather than later modified server copy of file. Do not reconnect
++when server drops the tcp session prematurely before negotiate
++protocol response. Fix oops in roepen_file when dentry freed. Allow
++the support for CIFS Unix Extensions to be disabled via proc interface.
++
++Version 0.98
++------------
++Fix hang in commit_write during reconnection of open files under heavy load.
++Fix unload_nls oops in a mount failure path. Serialize writes to same socket
++which also fixes any possible races when cifs signatures are enabled in SMBs
++being sent out of signature sequence number order.
++
++Version 0.97
++------------
++Fix byte range locking bug (endian problem) causing bad offset and
++length.
++
++Version 0.96
++------------
++Fix oops (in send_sig) caused by CIFS unmount code trying to
++wake up the demultiplex thread after it had exited. Do not log
++error on harmless oplock release of closed handle.
++
++Version 0.95
++------------
++Fix unsafe global variable usage and password hash failure on gcc 3.3.1
++Fix problem reconnecting secondary mounts to same server after session
++failure. Fix invalid dentry - race in mkdir when directory gets created
++by another client between the lookup and mkdir.
++
++Version 0.94
++------------
++Fix to list processing in reopen_files. Fix reconnection when server hung
++but tcpip session still alive. Set proper timeout on socket read.
++
++Version 0.93
++------------
++Add missing mount options including iocharset. SMP fixes in write and open.
++Fix errors in reconnecting after TCP session failure. Fix module unloading
++of default nls codepage
++
++Version 0.92
++------------
++Active smb transactions should never go negative (fix double FreeXid). Fix
++list processing in file routines. Check return code on kmalloc in open.
++Fix spinlock usage for SMP.
++
++Version 0.91
++------------
++Fix oops in reopen_files when invalid dentry. drop dentry on server rename
++and on revalidate errors. Fix cases where pid is now tgid. Fix return code
++on create hard link when server does not support them.
++
++Version 0.90
++------------
++Fix scheduling while atomic error in getting inode info on newly created file.
++Fix truncate of existing files opened with O_CREAT but not O_TRUNC set.
++
++Version 0.89
++------------
++Fix oops on write to dead tcp session. Remove error log write for case when file open
++O_CREAT but not O_EXCL
++
++Version 0.88
++------------
++Fix non-POSIX behavior on rename of open file and delete of open file by taking
++advantage of trans2 SetFileInfo rename facility if available on target server.
++Retry on ENOSPC and EAGAIN socket errors.
++
++Version 0.87
++------------
++Fix oops on big endian readdir. Set blksize to be even power of two (2**blkbits) to fix
++allocation size miscalculation. After oplock token lost do not read through
++cache.
++
++Version 0.86
++------------
++Fix oops on empty file readahead. Fix for file size handling for locally cached files.
++
++Version 0.85
++------------
++Fix oops in mkdir when server fails to return inode info. Fix oops in reopen_files
++during auto reconnection to server after server recovered from failure.
++
++Version 0.84
++------------
++Finish support for Linux 2.5 open/create changes, which removes the
++redundant NTCreate/QPathInfo/close that was sent during file create.
++Enable oplock by default. Enable packet signing by default (needed to
++access many recent Windows servers)
++
++Version 0.83
++------------
++Fix oops when mounting to long server names caused by inverted parms to kmalloc.
++Fix MultiuserMount (/proc/fs/cifs configuration setting) so that when enabled
++we will choose a cifs user session (smb uid) that better matches the local
++uid if a) the mount uid does not match the current uid and b) we have another
++session to the same server (ip address) for a different mount which
++matches the current local uid.
++
++Version 0.82
++------------
++Add support for mknod of block or character devices. Fix oplock
++code (distributed caching) to properly send response to oplock
++break from server.
++
++Version 0.81
++------------
++Finish up CIFS packet digital signing for the default
++NTLM security case. This should help Windows 2003
++network interoperability since it is common for
++packet signing to be required now. Fix statfs (stat -f)
++which recently started returning errors due to
++invalid value (-1 instead of 0) being set in the
++struct kstatfs f_ffiles field.
++
++Version 0.80
++-----------
++Fix oops on stopping oplock thread when removing cifs when
++built as module.
++
++Version 0.79
++------------
++Fix mount options for ro (readonly), uid, gid and file and directory mode.
++
++Version 0.78
++------------
++Fix errors displayed on failed mounts to be more understandable.
++Fixed various incorrect or misleading smb to posix error code mappings.
++
++Version 0.77
++------------
++Fix display of NTFS DFS junctions to display as symlinks.
++They are the network equivalent. Fix oops in
++cifs_partialpagewrite caused by missing spinlock protection
++of openfile linked list. Allow writebehind caching errors to
++be returned to the application at file close.
++
++Version 0.76
++------------
++Clean up options displayed in /proc/mounts by show_options to
++be more consistent with other filesystems.
++
++Version 0.75
++------------
++Fix delete of readonly file to Windows servers. Reflect
++presence or absence of read only dos attribute in mode
++bits for servers that do not support CIFS Unix extensions.
++Fix shortened results on readdir of large directories to
++servers supporting CIFS Unix extensions (caused by
++incorrect resume key).
++
++Version 0.74
++------------
++Fix truncate bug (set file size) that could cause hangs e.g. running fsx
++
++Version 0.73
++------------
++unload nls if mount fails.
++
++Version 0.72
++------------
++Add resume key support to search (readdir) code to workaround
++Windows bug. Add /proc/fs/cifs/LookupCacheEnable which
++allows disabling caching of attribute information for
++lookups.
++
++Version 0.71
++------------
++Add more oplock handling (distributed caching code). Remove
++dead code. Remove excessive stack space utilization from
++symlink routines.
++
++Version 0.70
++------------
++Fix oops in get dfs referral (triggered when null path sent in to
++mount). Add support for overriding rsize at mount time.
++
++Version 0.69
++------------
++Fix buffer overrun in readdir which caused intermittent kernel oopses.
++Fix writepage code to release kmap on write data. Allow "-ip=" new
++mount option to be passed in on parameter distinct from the first part
++(server name portion of) the UNC name. Allow override of the
++tcp port of the target server via new mount option "-port="
++
++Version 0.68
++------------
++Fix search handle leak on rewind. Fix setuid and gid so that they are
++reflected in the local inode immediately. Cleanup of whitespace
++to make 2.4 and 2.5 versions more consistent.
++
++
++Version 0.67
++------------
++Fix signal sending so that captive thread (cifsd) exits on umount
++(which was causing the warning in kmem_cache_free of the request buffers
++at rmmod time). This had broken as a sideeffect of the recent global
++kernel change to daemonize. Fix memory leak in readdir code which
++showed up in "ls -R" (and applications that did search rewinding).
++
++Version 0.66
++------------
++Reconnect tids and fids after session reconnection (still do not
++reconnect byte range locks though). Fix problem caching
++lookup information for directory inodes, improving performance,
++especially in deep directory trees. Fix various build warnings.
++
++Version 0.65
++------------
++Finish fixes to commit write for caching/readahead consistency. fsx
++now works to Samba servers. Fix oops caused when readahead
++was interrupted by a signal.
++
++Version 0.64
++------------
++Fix data corruption (in partial page after truncate) that caused fsx to
++fail to Windows servers. Cleaned up some extraneous error logging in
++common error paths. Add generic sendfile support.
++
++Version 0.63
++------------
++Fix memory leak in AllocMidQEntry.
++Finish reconnection logic, so connection with server can be dropped
++(or server rebooted) and the cifs client will reconnect.
++
++Version 0.62
++------------
++Fix temporary socket leak when bad userid or password specified
++(or other SMBSessSetup failure). Increase maximum buffer size to slightly
++over 16K to allow negotiation of up to Samba and Windows server default read
++sizes. Add support for readpages
++
++Version 0.61
++------------
++Fix oops when username not passed in on mount. Extensive fixes and improvements
++to error logging (strip redundant newlines, change debug macros to ensure newline
++passed in and to be more consistent). Fix writepage wrong file handle problem,
++a readonly file handle could be incorrectly used to attempt to write out
++file updates through the page cache to multiply open files. This could cause
++the iozone benchmark to fail on the fwrite test. Fix bug mounting two different
++shares to the same Windows server when using different usernames
++(doing this to Samba servers worked but Windows was rejecting it) - now it is
++possible to use different userids when connecting to the same server from a
++Linux client. Fix oops when treeDisconnect called during unmount on
++previously freed socket.
++
++Version 0.60
++------------
++Fix oops in readpages caused by not setting address space operations in inode in
++rare code path.
++
++Version 0.59
++------------
++Includes support for deleting of open files and renaming over existing files (per POSIX
++requirement). Add readlink support for Windows junction points (directory symlinks).
++
++Version 0.58
++------------
++Changed read and write to go through pagecache. Added additional address space operations.
++Memory mapped operations now working.
++
++Version 0.57
++------------
++Added writepage code for additional memory mapping support. Fixed leak in xids causing
++the simultaneous operations counter (/proc/fs/cifs/SimultaneousOps) to increase on
++every stat call. Additional formatting cleanup.
++
++Version 0.56
++------------
++Fix bigendian bug in order of time conversion. Merge 2.5 to 2.4 version. Formatting cleanup.
++
++Version 0.55
++------------
++Fixes from Zwane Mwaikambo for adding missing return code checking in a few places.
++Also included a modified version of his fix to protect global list manipulation of
++the smb session and tree connection and mid related global variables.
++
++Version 0.54
++------------
++Fix problem with captive thread hanging around at unmount time. Adjust to 2.5.42-pre
++changes to superblock layout. Remove wasteful allocation of smb buffers (now the send
++buffer is reused for responses). Add more oplock handling. Additional minor cleanup.
++
++Version 0.53
++------------
++More stylistic updates to better match kernel style. Add additional statistics
++for filesystem which can be viewed via /proc/fs/cifs. Add more pieces of NTLMv2
++and CIFS Packet Signing enablement.
++
++Version 0.52
++------------
++Replace call to sleep_on with safer wait_on_event.
++Make stylistic changes to better match kernel style recommendations.
++Remove most typedef usage (except for the PDUs themselves).
++
++Version 0.51
++------------
++Update mount so the -unc mount option is no longer required (the ip address can be specified
++in a UNC style device name. Implementation of readpage/writepage started.
++
++Version 0.50
++------------
++Fix intermittent problem with incorrect smb header checking on badly
++fragmented tcp responses
++
++Version 0.49
++------------
++Fixes to setting of allocation size and file size.
++
++Version 0.48
++------------
++Various 2.5.38 fixes. Now works on 2.5.38
++
++Version 0.47
++------------
++Prepare for 2.5 kernel merge. Remove ifdefs.
++
++Version 0.46
++------------
++Socket buffer management fixes. Fix dual free.
++
++Version 0.45
++------------
++Various big endian fixes for hardlinks and symlinks and also for dfs.
++
++Version 0.44
++------------
++Various big endian fixes for servers with Unix extensions such as Samba
++
++Version 0.43
++------------
++Various FindNext fixes for incorrect filenames on large directory searches on big endian
++clients. basic posix file i/o tests now work on big endian machines, not just le
++
++Version 0.42
++------------
++SessionSetup and NegotiateProtocol now work from Big Endian machines.
++Various Big Endian fixes found during testing on the Linux on 390. Various fixes for compatibility with older
++versions of 2.4 kernel (now builds and works again on kernels at least as early as 2.4.7).
++
++Version 0.41
++------------
++Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked
++files now return the correct rumber of links on fstat as they are repeatedly linked and unlinked.
++
++Version 0.40
++------------
++Implemented "Raw" (i.e. not encapsulated in SPNEGO) NTLMSSP (i.e. the Security Provider Interface used to negotiate
++session advanced session authentication). Raw NTLMSSP is preferred by Windows 2000 Professional and Windows XP.
++Began implementing support for SPNEGO encapsulation of NTLMSSP based session authentication blobs
++(which is the mechanism preferred by Windows 2000 server in the absence of Kerberos).
++
++Version 0.38
++------------
++Introduced optional mount helper utility mount.cifs and made coreq changes to cifs vfs to enable
++it. Fixed a few bugs in the DFS code (e.g. bcc two bytes too short and incorrect uid in PDU).
++
++Version 0.37
++------------
++Rewrote much of connection and mount/unmount logic to handle bugs with
++multiple uses to same share, multiple users to same server etc.
++
++Version 0.36
++------------
++Fixed major problem with dentry corruption (missing call to dput)
++
++Version 0.35
++------------
++Rewrite of readdir code to fix bug. Various fixes for bigendian machines.
++Begin adding oplock support. Multiusermount and oplockEnabled flags added to /proc/fs/cifs
++although corresponding function not fully implemented in the vfs yet
++
++Version 0.34
++------------
++Fixed dentry caching bug, misc. cleanup
++
++Version 0.33
++------------
++Fixed 2.5 support to handle build and configure changes as well as misc. 2.5 changes. Now can build
++on current 2.5 beta version (2.5.24) of the Linux kernel as well as on 2.4 Linux kernels.
++Support for STATUS codes (newer 32 bit NT error codes) added. DFS support begun to be added.
++
++Version 0.32
++------------
++Unix extensions (symlink, readlink, hardlink, chmod and some chgrp and chown) implemented
++and tested against Samba 2.2.5
++
++
++Version 0.31
++------------
++1) Fixed lockrange to be correct (it was one byte too short)
++
++2) Fixed GETLK (i.e. the fcntl call to test a range of bytes in a file to see if locked) to correctly
++show range as locked when there is a conflict with an existing lock.
++
++3) default file perms are now 2767 (indicating support for mandatory locks) instead of 777 for directories
++in most cases. Eventually will offer optional ability to query server for the correct perms.
++
++3) Fixed eventual trap when mounting twice to different shares on the same server when the first succeeded
++but the second one was invalid and failed (the second one was incorrectly disconnecting the tcp and smb
++session)
++
++4) Fixed error logging of valid mount options
++
++5) Removed logging of password field.
++
++6) Moved negotiate, treeDisconnect and uloggoffX (only tConx and SessSetup remain in connect.c) to cifssmb.c
++and cleaned them up and made them more consistent with other cifs functions.
++
++7) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways
++(with or without Unix exentions) but FindNext and QueryPathInfo with the Unix extensions are not completed,
++nor is the symlink support using the Unix extensions
++
++8) Started adding the readlink and follow_link code
++
++Version 0.3
++-----------
++Initial drop
++
+diff -urN linux-2.4.29.old/fs/cifs/cifs_debug.c linux-2.4.29/fs/cifs/cifs_debug.c
+--- linux-2.4.29.old/fs/cifs/cifs_debug.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/cifs_debug.c 2004-07-14 00:25:04.000000000 +0200
+@@ -0,0 +1,797 @@
++/*
++ * fs/cifs_debug.c
++ *
++ * Copyright (C) International Business Machines Corp., 2000,2003
++ *
++ * Modified by Steve French (sfrench@us.ibm.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 <linux/fs.h>
++#include <linux/string.h>
++#include <linux/ctype.h>
++#include <linux/module.h>
++#include <linux/proc_fs.h>
++#include <asm/uaccess.h>
++#include "cifspdu.h"
++#include "cifsglob.h"
++#include "cifsproto.h"
++#include "cifs_debug.h"
++
++void
++cifs_dump_mem(char *label, void *data, int length)
++{
++ int i, j;
++ int *intptr = data;
++ char *charptr = data;
++ char buf[10], line[80];
++
++ printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n\n",
++ label, length, data);
++ for (i = 0; i < length; i += 16) {
++ line[0] = 0;
++ for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
++ sprintf(buf, " %08x", intptr[i / 4 + j]);
++ strcat(line, buf);
++ }
++ buf[0] = ' ';
++ buf[2] = 0;
++ for (j = 0; (j < 16) && (i + j < length); j++) {
++ buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.';
++ strcat(line, buf);
++ }
++ printk(KERN_DEBUG "%s\n", line);
++ }
++}
++
++#ifdef CONFIG_PROC_FS
++int
++cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
++ int count, int *eof, void *data)
++{
++ struct list_head *tmp;
++ struct list_head *tmp1;
++ struct mid_q_entry * mid_entry;
++ struct cifsSesInfo *ses;
++ struct cifsTconInfo *tcon;
++ int i;
++ int length = 0;
++ char * original_buf = buf;
++
++ *beginBuffer = buf + offset;
++
++
++ length =
++ sprintf(buf,
++ "Display Internal CIFS Data Structures for Debugging\n"
++ "---------------------------------------------------\n");
++ buf += length;
++
++ length = sprintf(buf, "Servers:\n");
++ buf += length;
++
++ i = 0;
++ read_lock(&GlobalSMBSeslock);
++ list_for_each(tmp, &GlobalSMBSessionList) {
++ i++;
++ ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
++ length =
++ sprintf(buf,
++ "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\tTCP status: %d",
++ i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse),
++ ses->serverOS, ses->serverNOS, ses->capabilities,ses->status,ses->server->tcpStatus);
++ buf += length;
++ if(ses->server) {
++ buf += sprintf(buf, "\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d",
++ atomic_read(&ses->server->socketUseCount),
++ ses->server->secMode,
++ atomic_read(&ses->server->inFlight));
++
++ length = sprintf(buf, "\nMIDs: \n");
++ buf += length;
++
++ spin_lock(&GlobalMid_Lock);
++ list_for_each(tmp1, &ses->server->pending_mid_q) {
++ mid_entry = list_entry(tmp1, struct
++ mid_q_entry,
++ qhead);
++ if(mid_entry) {
++ length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",mid_entry->midState,mid_entry->command,mid_entry->pid,mid_entry->tsk,mid_entry->mid);
++ buf += length;
++ }
++ }
++ spin_unlock(&GlobalMid_Lock);
++ }
++
++ }
++ read_unlock(&GlobalSMBSeslock);
++ sprintf(buf, "\n");
++ buf++;
++
++ length = sprintf(buf, "\nShares:\n");
++ buf += length;
++
++ i = 0;
++ read_lock(&GlobalSMBSeslock);
++ list_for_each(tmp, &GlobalTreeConnectionList) {
++ i++;
++ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
++ length =
++ sprintf(buf,
++ "\n%d) %s Uses: %d Type: %s Characteristics: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
++ i, tcon->treeName,
++ atomic_read(&tcon->useCount),
++ tcon->nativeFileSystem,
++ tcon->fsDevInfo.DeviceCharacteristics,
++ tcon->fsAttrInfo.Attributes,
++ tcon->fsAttrInfo.MaxPathNameComponentLength,tcon->tidStatus);
++ buf += length;
++ if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_DISK)
++ length = sprintf(buf, " type: DISK ");
++ else if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_CD_ROM)
++ length = sprintf(buf, " type: CDROM ");
++ else
++ length =
++ sprintf(buf, " type: %d ",
++ tcon->fsDevInfo.DeviceType);
++ buf += length;
++ if(tcon->tidStatus == CifsNeedReconnect) {
++ buf += sprintf(buf, "\tDISCONNECTED ");
++ length += 14;
++ }
++ }
++ read_unlock(&GlobalSMBSeslock);
++
++ length = sprintf(buf, "\n");
++ buf += length;
++
++ /* BB add code to dump additional info such as TCP session info now */
++ /* Now calculate total size of returned data */
++ length = buf - original_buf;
++
++ if(offset + count >= length)
++ *eof = 1;
++ if(length < offset) {
++ *eof = 1;
++ return 0;
++ } else {
++ length = length - offset;
++ }
++ if (length > count)
++ length = count;
++
++ return length;
++}
++
++#ifdef CONFIG_CIFS_STATS
++int
++cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
++ int count, int *eof, void *data)
++{
++ int item_length,i,length;
++ struct list_head *tmp;
++ struct cifsTconInfo *tcon;
++
++ *beginBuffer = buf + offset;
++
++ length = sprintf(buf,
++ "Resources in use\nCIFS Session: %d\n",
++ sesInfoAllocCount.counter);
++ buf += length;
++ item_length =
++ sprintf(buf,"Share (unique mount targets): %d\n",
++ tconInfoAllocCount.counter);
++ length += item_length;
++ buf += item_length;
++ item_length =
++ sprintf(buf,"SMB Request/Response Buffer: %d\n",
++ bufAllocCount.counter);
++ length += item_length;
++ buf += item_length;
++ item_length =
++ sprintf(buf,"Operations (MIDs): %d\n",
++ midCount.counter);
++ length += item_length;
++ buf += item_length;
++ item_length = sprintf(buf,
++ "\n%d session %d share reconnects\n",
++ tcpSesReconnectCount.counter,tconInfoReconnectCount.counter);
++ length += item_length;
++ buf += item_length;
++
++ item_length = sprintf(buf,
++ "Total vfs operations: %d maximum at one time: %d\n",
++ GlobalCurrentXid,GlobalMaxActiveXid);
++ length += item_length;
++ buf += item_length;
++
++ i = 0;
++ read_lock(&GlobalSMBSeslock);
++ list_for_each(tmp, &GlobalTreeConnectionList) {
++ i++;
++ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
++ item_length = sprintf(buf,"\n%d) %s",i, tcon->treeName);
++ buf += item_length;
++ length += item_length;
++ if(tcon->tidStatus == CifsNeedReconnect) {
++ buf += sprintf(buf, "\tDISCONNECTED ");
++ length += 14;
++ }
++ item_length = sprintf(buf,"\nSMBs: %d Oplock Breaks: %d",
++ atomic_read(&tcon->num_smbs_sent),
++ atomic_read(&tcon->num_oplock_brks));
++ buf += item_length;
++ length += item_length;
++ item_length = sprintf(buf,"\nReads: %d Bytes %lld",
++ atomic_read(&tcon->num_reads),
++ (long long)(tcon->bytes_read));
++ buf += item_length;
++ length += item_length;
++ item_length = sprintf(buf,"\nWrites: %d Bytes: %lld",
++ atomic_read(&tcon->num_writes),
++ (long long)(tcon->bytes_written));
++ buf += item_length;
++ length += item_length;
++ item_length = sprintf(buf,
++ "\nOpens: %d Deletes: %d\nMkdirs: %d Rmdirs: %d",
++ atomic_read(&tcon->num_opens),
++ atomic_read(&tcon->num_deletes),
++ atomic_read(&tcon->num_mkdirs),
++ atomic_read(&tcon->num_rmdirs));
++ buf += item_length;
++ length += item_length;
++ item_length = sprintf(buf,
++ "\nRenames: %d T2 Renames %d",
++ atomic_read(&tcon->num_renames),
++ atomic_read(&tcon->num_t2renames));
++ buf += item_length;
++ length += item_length;
++ }
++ read_unlock(&GlobalSMBSeslock);
++
++ buf += sprintf(buf,"\n");
++ length++;
++
++ if(offset + count >= length)
++ *eof = 1;
++ if(length < offset) {
++ *eof = 1;
++ return 0;
++ } else {
++ length = length - offset;
++ }
++ if (length > count)
++ length = count;
++
++ return length;
++}
++#endif
++
++struct proc_dir_entry *proc_fs_cifs;
++read_proc_t cifs_txanchor_read;
++static read_proc_t cifsFYI_read;
++static write_proc_t cifsFYI_write;
++static read_proc_t oplockEnabled_read;
++static write_proc_t oplockEnabled_write;
++static read_proc_t lookupFlag_read;
++static write_proc_t lookupFlag_write;
++static read_proc_t traceSMB_read;
++static write_proc_t traceSMB_write;
++static read_proc_t multiuser_mount_read;
++static write_proc_t multiuser_mount_write;
++static read_proc_t extended_security_read;
++static write_proc_t extended_security_write;
++static read_proc_t ntlmv2_enabled_read;
++static write_proc_t ntlmv2_enabled_write;
++static read_proc_t packet_signing_enabled_read;
++static write_proc_t packet_signing_enabled_write;
++static read_proc_t quotaEnabled_read;
++static write_proc_t quotaEnabled_write;
++static read_proc_t linuxExtensionsEnabled_read;
++static write_proc_t linuxExtensionsEnabled_write;
++
++void
++cifs_proc_init(void)
++{
++ struct proc_dir_entry *pde;
++
++ proc_fs_cifs = proc_mkdir("cifs", proc_root_fs);
++ if (proc_fs_cifs == NULL)
++ return;
++
++ proc_fs_cifs->owner = THIS_MODULE;
++ create_proc_read_entry("DebugData", 0, proc_fs_cifs,
++ cifs_debug_data_read, NULL);
++
++#ifdef CONFIG_CIFS_STATS
++ create_proc_read_entry("Stats", 0, proc_fs_cifs,
++ cifs_stats_read, NULL);
++#endif
++ pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs,
++ cifsFYI_read, NULL);
++ if (pde)
++ pde->write_proc = cifsFYI_write;
++
++ pde =
++ create_proc_read_entry("traceSMB", 0, proc_fs_cifs,
++ traceSMB_read, NULL);
++ if (pde)
++ pde->write_proc = traceSMB_write;
++
++ pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs,
++ oplockEnabled_read, NULL);
++ if (pde)
++ pde->write_proc = oplockEnabled_write;
++
++ pde = create_proc_read_entry("QuotaEnabled", 0, proc_fs_cifs,
++ quotaEnabled_read, NULL);
++ if (pde)
++ pde->write_proc = quotaEnabled_write;
++
++ pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
++ linuxExtensionsEnabled_read, NULL);
++ if (pde)
++ pde->write_proc = linuxExtensionsEnabled_write;
++
++ pde =
++ create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs,
++ multiuser_mount_read, NULL);
++ if (pde)
++ pde->write_proc = multiuser_mount_write;
++
++ pde =
++ create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs,
++ extended_security_read, NULL);
++ if (pde)
++ pde->write_proc = extended_security_write;
++
++ pde =
++ create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs,
++ lookupFlag_read, NULL);
++ if (pde)
++ pde->write_proc = lookupFlag_write;
++
++ pde =
++ create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
++ ntlmv2_enabled_read, NULL);
++ if (pde)
++ pde->write_proc = ntlmv2_enabled_write;
++
++ pde =
++ create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
++ packet_signing_enabled_read, NULL);
++ if (pde)
++ pde->write_proc = packet_signing_enabled_write;
++}
++
++void
++cifs_proc_clean(void)
++{
++ if (proc_fs_cifs == NULL)
++ return;
++
++ remove_proc_entry("DebugData", proc_fs_cifs);
++ remove_proc_entry("cifsFYI", proc_fs_cifs);
++ remove_proc_entry("traceSMB", proc_fs_cifs);
++#ifdef CONFIG_CIFS_STATS
++ remove_proc_entry("Stats", proc_fs_cifs);
++#endif
++ remove_proc_entry("MultiuserMount", proc_fs_cifs);
++ remove_proc_entry("OplockEnabled", proc_fs_cifs);
++ remove_proc_entry("NTLMV2Enabled",proc_fs_cifs);
++ remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
++ remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
++ remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
++ remove_proc_entry("QuotaEnabled",proc_fs_cifs);
++ remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
++ remove_proc_entry("cifs", proc_root_fs);
++}
++
++static int
++cifsFYI_read(char *page, char **start, off_t off, int count,
++ int *eof, void *data)
++{
++ int len;
++
++ len = sprintf(page, "%d\n", cifsFYI);
++
++ len -= off;
++ *start = page + off;
++
++ if (len > count)
++ len = count;
++ else
++ *eof = 1;
++
++ if (len < 0)
++ len = 0;
++
++ return len;
++}
++static int
++cifsFYI_write(struct file *file, const char *buffer,
++ unsigned long count, void *data)
++{
++ char c;
++ int rc;
++
++ rc = get_user(c, buffer);
++ if (rc)
++ return rc;
++ if (c == '0' || c == 'n' || c == 'N')
++ cifsFYI = 0;
++ else if (c == '1' || c == 'y' || c == 'Y')
++ cifsFYI = 1;
++
++ return count;
++}
++
++static int
++oplockEnabled_read(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ int len;
++
++ len = sprintf(page, "%d\n", oplockEnabled);
++
++ len -= off;
++ *start = page + off;
++
++ if (len > count)
++ len = count;
++ else
++ *eof = 1;
++
++ if (len < 0)
++ len = 0;
++
++ return len;
++}
++static int
++oplockEnabled_write(struct file *file, const char *buffer,
++ unsigned long count, void *data)
++{
++ char c;
++ int rc;
++
++ rc = get_user(c, buffer);
++ if (rc)
++ return rc;
++ if (c == '0' || c == 'n' || c == 'N')
++ oplockEnabled = 0;
++ else if (c == '1' || c == 'y' || c == 'Y')
++ oplockEnabled = 1;
++
++ return count;
++}
++
++static int
++quotaEnabled_read(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ int len;
++
++ len = sprintf(page, "%d\n", quotaEnabled);
++/* could also check if quotas are enabled in kernel
++ as a whole first */
++ len -= off;
++ *start = page + off;
++
++ if (len > count)
++ len = count;
++ else
++ *eof = 1;
++
++ if (len < 0)
++ len = 0;
++
++ return len;
++}
++static int
++quotaEnabled_write(struct file *file, const char *buffer,
++ unsigned long count, void *data)
++{
++ char c;
++ int rc;
++
++ rc = get_user(c, buffer);
++ if (rc)
++ return rc;
++ if (c == '0' || c == 'n' || c == 'N')
++ quotaEnabled = 0;
++ else if (c == '1' || c == 'y' || c == 'Y')
++ quotaEnabled = 1;
++
++ return count;
++}
++
++static int
++linuxExtensionsEnabled_read(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ int len;
++
++ len = sprintf(page, "%d\n", linuxExtEnabled);
++/* could also check if quotas are enabled in kernel
++ as a whole first */
++ len -= off;
++ *start = page + off;
++
++ if (len > count)
++ len = count;
++ else
++ *eof = 1;
++
++ if (len < 0)
++ len = 0;
++
++ return len;
++}
++static int
++linuxExtensionsEnabled_write(struct file *file, const char *buffer,
++ unsigned long count, void *data)
++{
++ char c;
++ int rc;
++
++ rc = get_user(c, buffer);
++ if (rc)
++ return rc;
++ if (c == '0' || c == 'n' || c == 'N')
++ linuxExtEnabled = 0;
++ else if (c == '1' || c == 'y' || c == 'Y')
++ linuxExtEnabled = 1;
++
++ return count;
++}
++
++
++static int
++lookupFlag_read(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ int len;
++
++ len = sprintf(page, "%d\n", lookupCacheEnabled);
++
++ len -= off;
++ *start = page + off;
++
++ if (len > count)
++ len = count;
++ else
++ *eof = 1;
++
++ if (len < 0)
++ len = 0;
++
++ return len;
++}
++static int
++lookupFlag_write(struct file *file, const char *buffer,
++ unsigned long count, void *data)
++{
++ char c;
++ int rc;
++
++ rc = get_user(c, buffer);
++ if (rc)
++ return rc;
++ if (c == '0' || c == 'n' || c == 'N')
++ lookupCacheEnabled = 0;
++ else if (c == '1' || c == 'y' || c == 'Y')
++ lookupCacheEnabled = 1;
++
++ return count;
++}
++static int
++traceSMB_read(char *page, char **start, off_t off, int count,
++ int *eof, void *data)
++{
++ int len;
++
++ len = sprintf(page, "%d\n", traceSMB);
++
++ len -= off;
++ *start = page + off;
++
++ if (len > count)
++ len = count;
++ else
++ *eof = 1;
++
++ if (len < 0)
++ len = 0;
++
++ return len;
++}
++static int
++traceSMB_write(struct file *file, const char *buffer,
++ unsigned long count, void *data)
++{
++ char c;
++ int rc;
++
++ rc = get_user(c, buffer);
++ if (rc)
++ return rc;
++ if (c == '0' || c == 'n' || c == 'N')
++ traceSMB = 0;
++ else if (c == '1' || c == 'y' || c == 'Y')
++ traceSMB = 1;
++
++ return count;
++}
++
++static int
++multiuser_mount_read(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ int len;
++
++ len = sprintf(page, "%d\n", multiuser_mount);
++
++ len -= off;
++ *start = page + off;
++
++ if (len > count)
++ len = count;
++ else
++ *eof = 1;
++
++ if (len < 0)
++ len = 0;
++
++ return len;
++}
++static int
++multiuser_mount_write(struct file *file, const char *buffer,
++ unsigned long count, void *data)
++{
++ char c;
++ int rc;
++
++ rc = get_user(c, buffer);
++ if (rc)
++ return rc;
++ if (c == '0' || c == 'n' || c == 'N')
++ multiuser_mount = 0;
++ else if (c == '1' || c == 'y' || c == 'Y')
++ multiuser_mount = 1;
++
++ return count;
++}
++
++static int
++extended_security_read(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ int len;
++
++ len = sprintf(page, "%d\n", extended_security);
++
++ len -= off;
++ *start = page + off;
++
++ if (len > count)
++ len = count;
++ else
++ *eof = 1;
++
++ if (len < 0)
++ len = 0;
++
++ return len;
++}
++static int
++extended_security_write(struct file *file, const char *buffer,
++ unsigned long count, void *data)
++{
++ char c;
++ int rc;
++
++ rc = get_user(c, buffer);
++ if (rc)
++ return rc;
++ if (c == '0' || c == 'n' || c == 'N')
++ extended_security = 0;
++ else if (c == '1' || c == 'y' || c == 'Y')
++ extended_security = 1;
++
++ return count;
++}
++
++static int
++ntlmv2_enabled_read(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ int len;
++
++ len = sprintf(page, "%d\n", ntlmv2_support);
++
++ len -= off;
++ *start = page + off;
++
++ if (len > count)
++ len = count;
++ else
++ *eof = 1;
++
++ if (len < 0)
++ len = 0;
++
++ return len;
++}
++static int
++ntlmv2_enabled_write(struct file *file, const char *buffer,
++ unsigned long count, void *data)
++{
++ char c;
++ int rc;
++
++ rc = get_user(c, buffer);
++ if (rc)
++ return rc;
++ if (c == '0' || c == 'n' || c == 'N')
++ ntlmv2_support = 0;
++ else if (c == '1' || c == 'y' || c == 'Y')
++ ntlmv2_support = 1;
++
++ return count;
++}
++
++static int
++packet_signing_enabled_read(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ int len;
++
++ len = sprintf(page, "%d\n", sign_CIFS_PDUs);
++
++ len -= off;
++ *start = page + off;
++
++ if (len > count)
++ len = count;
++ else
++ *eof = 1;
++
++ if (len < 0)
++ len = 0;
++
++ return len;
++}
++static int
++packet_signing_enabled_write(struct file *file, const char *buffer,
++ unsigned long count, void *data)
++{
++ char c;
++ int rc;
++
++ rc = get_user(c, buffer);
++ if (rc)
++ return rc;
++ if (c == '0' || c == 'n' || c == 'N')
++ sign_CIFS_PDUs = 0;
++ else if (c == '1' || c == 'y' || c == 'Y')
++ sign_CIFS_PDUs = 1;
++ else if (c == '2')
++ sign_CIFS_PDUs = 2;
++
++ return count;
++}
++
++
++#endif
+diff -urN linux-2.4.29.old/fs/cifs/cifs_debug.h linux-2.4.29/fs/cifs/cifs_debug.h
+--- linux-2.4.29.old/fs/cifs/cifs_debug.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/cifs_debug.h 2004-07-14 00:25:04.000000000 +0200
+@@ -0,0 +1,66 @@
++/*
++ *
++ * Copyright (c) International Business Machines Corp., 2000,2002
++ * Modified by Steve French (sfrench@us.ibm.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
++ *
++*/
++#define CIFS_DEBUG /* BB temporary */
++
++#ifndef _H_CIFS_DEBUG
++#define _H_CIFS_DEBUG
++
++void cifs_dump_mem(char *label, void *data, int length);
++extern int traceSMB; /* flag which enables the function below */
++void dump_smb(struct smb_hdr *, int);
++
++/*
++ * debug ON
++ * --------
++ */
++#ifdef CIFS_DEBUG
++
++
++/* information message: e.g., configuration, major event */
++extern int cifsFYI;
++#define cifsfyi(format,arg...) if (cifsFYI) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg)
++
++#define cFYI(button,prspec) if (button) cifsfyi prspec
++
++#define cifswarn(format, arg...) printk(KERN_WARNING ": " format "\n" , ## arg)
++
++/* debug event message: */
++extern int cifsERROR;
++
++#define cEVENT(format,arg...) if (cifsERROR) printk(KERN_EVENT __FILE__ ": " format "\n" , ## arg)
++
++/* error event message: e.g., i/o error */
++#define cifserror(format,arg...) if (cifsERROR) printk(KERN_ERR " CIFS VFS: " format "\n" "" , ## arg)
++
++#define cERROR(button, prspec) if (button) cifserror prspec
++
++/*
++ * debug OFF
++ * ---------
++ */
++#else /* _CIFS_DEBUG */
++#define cERROR(button,prspec)
++#define cEVENT(format,arg...)
++#define cFYI(button, prspec)
++#define cifserror(format,arg...)
++#endif /* _CIFS_DEBUG */
++
++#endif /* _H_CIFS_DEBUG */
+diff -urN linux-2.4.29.old/fs/cifs/cifsencrypt.c linux-2.4.29/fs/cifs/cifsencrypt.c
+--- linux-2.4.29.old/fs/cifs/cifsencrypt.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/cifsencrypt.c 2004-07-14 00:25:04.000000000 +0200
+@@ -0,0 +1,204 @@
++/*
++ * fs/cifs/cifsencrypt.c
++ *
++ * Copyright (C) International Business Machines Corp., 2003
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/fs.h>
++#include "cifspdu.h"
++#include "cifsglob.h"
++#include "cifs_debug.h"
++#include "md5.h"
++#include "cifs_unicode.h"
++
++/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
++/* the 16 byte signature must be allocated by the caller */
++/* Note we only use the 1st eight bytes */
++/* Note that the smb header signature field on input contains the
++ sequence number before this function is called */
++
++extern void mdfour(unsigned char *out, unsigned char *in, int n);
++extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
++
++static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature)
++{
++ struct MD5Context context;
++
++ if((cifs_pdu == NULL) || (signature == NULL))
++ return -EINVAL;
++
++ MD5Init(&context);
++ MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
++ MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
++ MD5Final(signature,&context);
++ return 0;
++}
++
++int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
++ __u32 * pexpected_response_sequence_number)
++{
++ int rc = 0;
++ char smb_signature[20];
++
++ /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
++ /* BB remember to add code to save expected sequence number in midQ entry BB */
++
++ if((cifs_pdu == NULL) || (ses == NULL))
++ return -EINVAL;
++
++ if((le32_to_cpu(cifs_pdu->Flags2) & SMBFLG2_SECURITY_SIGNATURE) == 0)
++ return rc;
++
++ spin_lock(&GlobalMid_Lock);
++ cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number);
++ cifs_pdu->Signature.Sequence.Reserved = 0;
++
++ *pexpected_response_sequence_number = ses->sequence_number++;
++ ses->sequence_number++;
++ spin_unlock(&GlobalMid_Lock);
++
++ rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature);
++ if(rc)
++ memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
++ else
++ memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
++
++ return rc;
++}
++
++int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
++ __u32 expected_sequence_number)
++{
++ unsigned int rc;
++ char server_response_sig[8];
++ char what_we_think_sig_should_be[20];
++
++ if((cifs_pdu == NULL) || (mac_key == NULL))
++ return -EINVAL;
++
++ if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
++ return 0;
++
++ if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
++ struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)cifs_pdu;
++ if(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
++ return 0;
++ }
++
++ /* BB what if signatures are supposed to be on for session but server does not
++ send one? BB */
++
++ /* Do not need to verify session setups with signature "BSRSPYL " */
++ if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0)
++ cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command));
++
++ expected_sequence_number = cpu_to_le32(expected_sequence_number);
++
++ /* save off the origiginal signature so we can modify the smb and check
++ its signature against what the server sent */
++ memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8);
++
++ cifs_pdu->Signature.Sequence.SequenceNumber = expected_sequence_number;
++ cifs_pdu->Signature.Sequence.Reserved = 0;
++
++ rc = cifs_calculate_signature(cifs_pdu, mac_key,
++ what_we_think_sig_should_be);
++
++ if(rc)
++ return rc;
++
++
++/* cifs_dump_mem("what we think it should be: ",what_we_think_sig_should_be,16); */
++
++ if(memcmp(server_response_sig, what_we_think_sig_should_be, 8))
++ return -EACCES;
++ else
++ return 0;
++
++}
++
++/* We fill in key by putting in 40 byte array which was allocated by caller */
++int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
++{
++ char temp_key[16];
++ if ((key == NULL) || (rn == NULL))
++ return -EINVAL;
++
++ E_md4hash(password, temp_key);
++ mdfour(key,temp_key,16);
++ memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE);
++ return 0;
++}
++
++int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_info)
++{
++ char temp_hash[16];
++ struct HMACMD5Context ctx;
++ char * ucase_buf;
++ wchar_t * unicode_buf;
++ unsigned int i,user_name_len,dom_name_len;
++
++ if(ses)
++ return -EINVAL;
++
++ E_md4hash(ses->password, temp_hash);
++
++ hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
++ user_name_len = strlen(ses->userName);
++ if(user_name_len > MAX_USERNAME_SIZE)
++ return -EINVAL;
++ dom_name_len = strlen(ses->domainName);
++ if(dom_name_len > MAX_USERNAME_SIZE)
++ return -EINVAL;
++
++ ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
++ unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
++
++ for(i=0;i<user_name_len;i++)
++ ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
++ ucase_buf[i] = 0;
++ user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
++ unicode_buf[user_name_len] = 0;
++ user_name_len++;
++
++ for(i=0;i<dom_name_len;i++)
++ ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
++ ucase_buf[i] = 0;
++ dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
++
++ unicode_buf[user_name_len + dom_name_len] = 0;
++ hmac_md5_update((const unsigned char *) unicode_buf,
++ (user_name_len+dom_name_len)*2,&ctx);
++
++ hmac_md5_final(ses->mac_signing_key,&ctx);
++ kfree(ucase_buf);
++ kfree(unicode_buf);
++ return 0;
++}
++void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response)
++{
++ struct HMACMD5Context context;
++ memcpy(v2_session_response + 8, ses->server->cryptKey,8);
++ /* gen_blob(v2_session_response + 16); */
++ hmac_md5_init_limK_to_64(ses->mac_signing_key, 16, &context);
++
++ hmac_md5_update(ses->server->cryptKey,8,&context);
++/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
++
++ hmac_md5_final(v2_session_response,&context);
++}
+diff -urN linux-2.4.29.old/fs/cifs/cifserr.c linux-2.4.29/fs/cifs/cifserr.c
+--- linux-2.4.29.old/fs/cifs/cifserr.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/cifserr.c 2004-07-14 00:25:04.000000000 +0200
+@@ -0,0 +1,70 @@
++/*
++ * fs/cifserr.c
++ *
++ * Copyright (c) International Business Machines Corp., 2002
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/errno.h>
++#include <linux/fs.h>
++#include <linux/smbno.h>
++#include "cifsfs.h"
++
++int map_cifs_error(int error_class, int error_code,
++ int status_codes_negotiated)
++{
++
++
++ if (status_codes_negotiated) {
++ switch (error_code) {
++ default:
++ return EIO;
++ }
++ } else
++ switch (error_class) {
++ case SUCCESS:
++ return 0;
++
++ case ERRDOS:
++ switch (error_code) {
++ case ERRbadfunc:
++ return EINVAL;
++ default:
++ return EIO;
++ }
++
++ case ERRSRV:
++ switch (error_code) {
++ default:
++ return EIO;
++ }
++
++ case ERRHRD:
++ switch (error_code) {
++ default:
++ return EIO;
++ }
++ default:
++ return EIO;
++ }
++ return 0;
++}
++
++int map_smb_error(int error_class, int error_code)
++{
++ return map_cifs_error(error_class, error_code, FALSE);
++}
+diff -urN linux-2.4.29.old/fs/cifs/cifsfs.c linux-2.4.29/fs/cifs/cifsfs.c
+--- linux-2.4.29.old/fs/cifs/cifsfs.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/cifsfs.c 2004-07-14 00:25:04.000000000 +0200
+@@ -0,0 +1,769 @@
++/*
++ * fs/cifs/cifsfs.c
++ *
++ * Copyright (C) International Business Machines Corp., 2002,2004
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * Common Internet FileSystem (CIFS) client
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++/* Note that BB means BUGBUG (ie something to fix eventually) */
++
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/mount.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/version.h>
++#include <linux/list.h>
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
++#include <linux/seq_file.h>
++#endif
++#include <linux/vfs.h>
++#include "cifsfs.h"
++#include "cifspdu.h"
++#define DECLARE_GLOBALS_HERE
++#include "cifsglob.h"
++#include "cifsproto.h"
++#include "cifs_debug.h"
++#include "cifs_fs_sb.h"
++#include <linux/mm.h>
++#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
++/* BB when mempool_resize is added back in, we will resize pool on new mount */
++#define CIFS_MIN_RCV_POOL 11 /* enough for progress to five servers */
++
++#ifdef CONFIG_CIFS_QUOTA
++static struct quotactl_ops cifs_quotactl_ops;
++#endif
++
++extern struct file_system_type cifs_fs_type;
++
++int cifsFYI = 0;
++int cifsERROR = 1;
++int traceSMB = 0;
++unsigned int oplockEnabled = 1;
++unsigned int quotaEnabled = 0;
++unsigned int linuxExtEnabled = 1;
++unsigned int lookupCacheEnabled = 1;
++unsigned int multiuser_mount = 0;
++unsigned int extended_security = 0;
++unsigned int ntlmv2_support = 0;
++unsigned int sign_CIFS_PDUs = 1;
++unsigned int CIFSMaximumBufferSize = CIFS_MAX_MSGSIZE;
++struct task_struct * oplockThread = NULL;
++
++extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
++ const char *);
++extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
++void cifs_proc_init(void);
++void cifs_proc_clean(void);
++
++static DECLARE_COMPLETION(cifs_oplock_exited);
++
++
++struct super_block *
++cifs_read_super(struct super_block *sb, void *data, int silent)
++{
++ struct inode *inode;
++ struct cifs_sb_info *cifs_sb;
++ int rc = 0;
++
++ sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
++ cifs_sb = CIFS_SB(sb);
++ if(cifs_sb == NULL)
++ return 0;
++ else
++ memset(cifs_sb,0,sizeof(struct cifs_sb_info));
++
++
++ rc = cifs_mount(sb, cifs_sb, data, NULL);
++
++ if (rc) {
++ if (!silent)
++ cERROR(1,
++ ("cifs_mount failed w/return code = %d", rc));
++ goto out_mount_failed;
++ }
++
++ sb->s_magic = CIFS_MAGIC_NUMBER;
++ sb->s_op = &cifs_super_ops;
++/* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
++ sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
++#ifdef CONFIG_CIFS_QUOTA
++ sb->s_qcop = &cifs_quotactl_ops;
++#endif
++ sb->s_blocksize = CIFS_MAX_MSGSIZE;
++ sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
++ inode = iget(sb, ROOT_I);
++
++ if (!inode) {
++ goto out_no_root;
++ }
++
++ sb->s_root = d_alloc_root(inode);
++
++ if (!sb->s_root) {
++ goto out_no_root;
++ }
++
++ return sb;
++
++out_no_root:
++ cERROR(1, ("cifs_read_super: get root inode failed"));
++ if (inode)
++ iput(inode);
++
++out_mount_failed:
++ if(cifs_sb->local_nls)
++ unload_nls(cifs_sb->local_nls);
++ sb->s_dev = 0;
++ return 0;
++}
++
++static void
++cifs_put_super(struct super_block *sb)
++{
++ int rc = 0;
++ struct cifs_sb_info *cifs_sb;
++
++ cFYI(1, ("In cifs_put_super"));
++ cifs_sb = CIFS_SB(sb);
++ if(cifs_sb == NULL) {
++ cFYI(1,("Empty cifs superblock info passed to unmount"));
++ return;
++ }
++ rc = cifs_umount(sb, cifs_sb);
++ if (rc) {
++ cERROR(1, ("cifs_umount failed with return code %d", rc));
++ }
++ unload_nls(cifs_sb->local_nls);
++ return;
++}
++
++static int
++cifs_statfs(struct super_block *sb, struct statfs *buf)
++{
++ int xid, rc;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++
++ xid = GetXid();
++
++ cifs_sb = CIFS_SB(sb);
++ pTcon = cifs_sb->tcon;
++
++ buf->f_type = CIFS_MAGIC_NUMBER;
++
++ /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
++ buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would presumably
++ be length of total path, note that some servers may be
++ able to support more than this, but best to be safe
++ since Win2k and others can not handle very long filenames */
++ buf->f_files = 0; /* undefined */
++ buf->f_ffree = 0; /* unlimited */
++
++ rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls);
++
++ /*
++ int f_type;
++ __fsid_t f_fsid;
++ int f_namelen; */
++ /* BB get from info put in tcon struct at mount time with call to QFSAttrInfo */
++ FreeXid(xid);
++ return 0; /* always return success? what if volume is no longer available? */
++}
++
++static int cifs_permission(struct inode * inode, int mask)
++{
++ /* the server does permission checks, we do not need to do it here */
++ return 0;
++}
++
++kmem_cache_t *cifs_req_cachep;
++kmem_cache_t *cifs_mid_cachep;
++kmem_cache_t *cifs_oplock_cachep;
++
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
++static struct inode *
++cifs_alloc_inode(struct super_block *sb)
++{
++ struct cifsInodeInfo *cifs_inode;
++ cifs_inode =
++ (struct cifsInodeInfo *) kmem_cache_alloc(cifs_inode_cachep,
++ SLAB_KERNEL);
++ if (!cifs_inode)
++ return NULL;
++ cifs_inode->cifsAttrs = 0x20; /* default */
++ atomic_set(&cifs_inode->inUse, 0);
++ cifs_inode->time = 0;
++ /* Until the file is open and we have gotten oplock
++ info back from the server, can not assume caching of
++ file data or metadata */
++ cifs_inode->clientCanCacheRead = FALSE;
++ cifs_inode->clientCanCacheAll = FALSE;
++ INIT_LIST_HEAD(&cifs_inode->openFileList);
++ return &cifs_inode->vfs_inode;
++}
++
++static void
++cifs_destroy_inode(struct inode *inode)
++{
++ kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
++}
++#endif
++
++/*
++ * cifs_show_options() is for displaying mount options in /proc/mounts.
++ * Not all settable options are displayed but most of the important
++ * ones are.
++ */
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
++static int
++cifs_show_options(struct seq_file *s, struct vfsmount *m)
++{
++ struct cifs_sb_info *cifs_sb;
++
++ cifs_sb = CIFS_SB(m->mnt_sb);
++
++ if (cifs_sb) {
++ if (cifs_sb->tcon) {
++ seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
++ if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->userName))
++ seq_printf(s, ",username=%s",
++ cifs_sb->tcon->ses->userName);
++ if(cifs_sb->tcon->ses->domainName)
++ seq_printf(s, ",domain=%s",
++ cifs_sb->tcon->ses->domainName);
++ }
++ seq_printf(s, ",rsize=%d",cifs_sb->rsize);
++ seq_printf(s, ",wsize=%d",cifs_sb->wsize);
++ }
++ return 0;
++}
++#endif
++
++#ifdef CONFIG_CIFS_QUOTA
++int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
++ struct fs_disk_quota * pdquota)
++{
++ int xid;
++ int rc = 0;
++ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
++ struct cifsTconInfo *pTcon;
++
++ if(cifs_sb)
++ pTcon = cifs_sb->tcon;
++ else
++ return -EIO;
++
++
++ xid = GetXid();
++ if(pTcon) {
++ cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
++ } else {
++ return -EIO;
++ }
++
++ FreeXid(xid);
++ return rc;
++}
++
++int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
++ struct fs_disk_quota * pdquota)
++{
++ int xid;
++ int rc = 0;
++ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
++ struct cifsTconInfo *pTcon;
++
++ if(cifs_sb)
++ pTcon = cifs_sb->tcon;
++ else
++ return -EIO;
++
++ xid = GetXid();
++ if(pTcon) {
++ cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
++ } else {
++ rc = -EIO;
++ }
++
++ FreeXid(xid);
++ return rc;
++}
++
++int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
++{
++ int xid;
++ int rc = 0;
++ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
++ struct cifsTconInfo *pTcon;
++
++ if(cifs_sb)
++ pTcon = cifs_sb->tcon;
++ else
++ return -EIO;
++
++ xid = GetXid();
++ if(pTcon) {
++ cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation));
++ } else {
++ rc = -EIO;
++ }
++
++ FreeXid(xid);
++ return rc;
++}
++
++int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
++{
++ int xid;
++ int rc = 0;
++ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
++ struct cifsTconInfo *pTcon;
++
++ if(cifs_sb) {
++ pTcon = cifs_sb->tcon;
++ } else {
++ return -EIO;
++ }
++ xid = GetXid();
++ if(pTcon) {
++ cFYI(1,("pqstats %p",qstats));
++ } else {
++ rc = -EIO;
++ }
++
++ FreeXid(xid);
++ return rc;
++}
++
++static struct quotactl_ops cifs_quotactl_ops = {
++ .set_xquota = cifs_xquota_set,
++ .get_xquota = cifs_xquota_set,
++ .set_xstate = cifs_xstate_set,
++ .get_xstate = cifs_xstate_get,
++};
++#endif
++
++static int cifs_remount(struct super_block *sb, int *flags, char *data)
++{
++ *flags |= MS_NODIRATIME;
++ return 0;
++}
++
++struct super_operations cifs_super_ops = {
++ .read_inode = cifs_read_inode,
++ .put_super = cifs_put_super,
++ .statfs = cifs_statfs,
++/* .alloc_inode = cifs_alloc_inode,
++ .destroy_inode = cifs_destroy_inode, */
++/* .drop_inode = generic_delete_inode,
++ .delete_inode = cifs_delete_inode, *//* Do not need the above two functions
++ unless later we add lazy close of inodes or unless the kernel forgets to call
++ us with the same number of releases (closes) as opens */
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
++ .show_options = cifs_show_options,
++#endif
++/* .umount_begin = cifs_umount_begin, *//* consider adding in the future */
++};
++
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
++static struct super_block *
++cifs_get_sb(struct file_system_type *fs_type,
++ int flags, const char *dev_name, void *data)
++{
++ int rc;
++ struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
++
++ cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
++
++ if (IS_ERR(sb))
++ return sb;
++
++ sb->s_flags = flags;
++
++ rc = cifs_read_super(sb, data, dev_name, flags & MS_VERBOSE ? 1 : 0);
++ if (rc) {
++ up_write(&sb->s_umount);
++ deactivate_super(sb);
++ return ERR_PTR(rc);
++ }
++ sb->s_flags |= MS_ACTIVE;
++ return sb;
++}
++#endif
++
++static ssize_t
++cifs_read_wrapper(struct file * file, char *read_data, size_t read_size,
++ loff_t * poffset)
++{
++ if(file == NULL)
++ return -EIO;
++ else if(file->f_dentry == NULL)
++ return -EIO;
++ else if(file->f_dentry->d_inode == NULL)
++ return -EIO;
++
++ if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) {
++ return generic_file_read(file,read_data,read_size,poffset);
++ } else {
++ /* BB do we need to lock inode from here until after invalidate? */
++/* if(file->f_dentry->d_inode->i_mapping) {
++ filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
++ filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
++ }*/
++/* cifs_revalidate(file->f_dentry);*/ /* BB fixme */
++
++ /* BB we should make timer configurable - perhaps
++ by simply calling cifs_revalidate here */
++ /* invalidate_remote_inode(file->f_dentry->d_inode);*/
++ return generic_file_read(file,read_data,read_size,poffset);
++ }
++}
++
++static ssize_t
++cifs_write_wrapper(struct file * file, const char *write_data,
++ size_t write_size, loff_t * poffset)
++{
++ ssize_t written;
++
++ if(file == NULL)
++ return -EIO;
++ else if(file->f_dentry == NULL)
++ return -EIO;
++ else if(file->f_dentry->d_inode == NULL)
++ return -EIO;
++
++ /* check whether we can cache writes locally */
++ written = generic_file_write(file,write_data,write_size,poffset);
++ if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll) {
++ if(file->f_dentry->d_inode->i_mapping) {
++ filemap_fdatasync(file->f_dentry->d_inode->i_mapping);
++ }
++ }
++ return written;
++}
++
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
++static struct file_system_type cifs_fs_type = {
++ .owner = THIS_MODULE,
++ .name = "cifs",
++ .get_sb = cifs_get_sb,
++ .kill_sb = kill_anon_super,
++ /* .fs_flags */
++};
++#endif
++
++static DECLARE_FSTYPE(cifs_fs_type, "cifs", cifs_read_super,0);
++
++
++struct inode_operations cifs_dir_inode_ops = {
++ .create = cifs_create,
++ .lookup = cifs_lookup,
++ .unlink = cifs_unlink,
++ .link = cifs_hardlink,
++ .mkdir = cifs_mkdir,
++ .rmdir = cifs_rmdir,
++ .rename = cifs_rename,
++ .permission = cifs_permission,
++ .revalidate = cifs_revalidate,
++ .setattr = cifs_setattr,
++ .symlink = cifs_symlink,
++ .mknod = cifs_mknod,
++};
++
++struct inode_operations cifs_file_inode_ops = {
++ .revalidate = cifs_revalidate,
++ .setattr = cifs_setattr,
++/* .getattr = cifs_getattr,*/
++ .rename = cifs_rename,
++ .permission = cifs_permission,
++#ifdef CONFIG_CIFS_XATTR
++ .setxattr = cifs_setxattr,
++ .getxattr = cifs_getxattr,
++ .listxattr = cifs_listxattr,
++ .removexattr = cifs_removexattr,
++#endif
++};
++
++struct inode_operations cifs_symlink_inode_ops = {
++ .readlink = cifs_readlink,
++ .follow_link = cifs_follow_link,
++ .permission = cifs_permission,
++ /* BB add the following two eventually */
++ /* revalidate: cifs_revalidate,
++ setattr: cifs_notify_change, *//* BB do we need notify change */
++#ifdef CONFIG_CIFS_XATTR
++ .setxattr = cifs_setxattr,
++ .getxattr = cifs_getxattr,
++ .listxattr = cifs_listxattr,
++ .removexattr = cifs_removexattr,
++#endif
++};
++
++struct file_operations cifs_file_ops = {
++ .read = cifs_read_wrapper,
++ .write = cifs_write_wrapper,
++ .open = cifs_open,
++ .release = cifs_close,
++ .lock = cifs_lock,
++ .fsync = cifs_fsync,
++ .flush = cifs_flush,
++ .mmap = cifs_file_mmap,
++/* .sendfile = generic_file_sendfile,*/
++#ifdef CONFIG_CIFS_FCNTL
++ .fcntl = cifs_fcntl,
++#endif
++};
++
++struct file_operations cifs_dir_ops = {
++ .readdir = cifs_readdir,
++ .release = cifs_closedir,
++ .read = generic_read_dir,
++#ifdef CONFIG_CIFS_FCNTL
++ .fcntl = cifs_fcntl,
++#endif
++};
++/*
++static void
++cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags)
++{
++ struct cifsInodeInfo *cifsi = (struct cifsInodeInfo *) inode;
++
++ if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
++ SLAB_CTOR_CONSTRUCTOR) {
++ inode_init_once(&cifsi->vfs_inode);
++ INIT_LIST_HEAD(&cifsi->lockList);
++ }
++}
++
++static int
++cifs_init_inodecache(void)
++{
++ cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
++ sizeof (struct cifsInodeInfo),
++ 0, SLAB_HWCACHE_ALIGN,
++ cifs_init_once, NULL);
++ if (cifs_inode_cachep == NULL)
++ return -ENOMEM;
++
++
++ return 0;
++}
++
++static void
++cifs_destroy_inodecache(void)
++{
++ if (kmem_cache_destroy(cifs_inode_cachep))
++ printk(KERN_WARNING "cifs_inode_cache: error freeing\n");
++} */
++
++static int
++cifs_init_request_bufs(void)
++{
++ cifs_req_cachep = kmem_cache_create("cifs_request",
++ CIFS_MAX_MSGSIZE +
++ MAX_CIFS_HDR_SIZE, 0,
++ SLAB_HWCACHE_ALIGN, NULL, NULL);
++ if (cifs_req_cachep == NULL)
++ return -ENOMEM;
++
++ return 0;
++}
++
++static void
++cifs_destroy_request_bufs(void)
++{
++ if (kmem_cache_destroy(cifs_req_cachep))
++ printk(KERN_WARNING
++ "cifs_destroy_request_cache: error not all structures were freed\n");
++}
++
++static int
++cifs_init_mids(void)
++{
++ cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
++ sizeof (struct mid_q_entry), 0,
++ SLAB_HWCACHE_ALIGN, NULL, NULL);
++ if (cifs_mid_cachep == NULL)
++ return -ENOMEM;
++ cifs_oplock_cachep = kmem_cache_create("cifs_oplock_struct",
++ sizeof (struct oplock_q_entry), 0,
++ SLAB_HWCACHE_ALIGN, NULL, NULL);
++ if (cifs_oplock_cachep == NULL) {
++ kmem_cache_destroy(cifs_mid_cachep);
++ return -ENOMEM;
++ }
++
++ return 0;
++}
++
++static void
++cifs_destroy_mids(void)
++{
++ if (kmem_cache_destroy(cifs_mid_cachep))
++ printk(KERN_WARNING
++ "cifs_destroy_mids: error not all structures were freed\n");
++ if (kmem_cache_destroy(cifs_oplock_cachep))
++ printk(KERN_WARNING
++ "error not all oplock structures were freed\n");
++}
++
++static int cifs_oplock_thread(void * dummyarg)
++{
++ struct oplock_q_entry * oplock_item;
++ struct cifsTconInfo *pTcon;
++ struct inode * inode;
++ __u16 netfid;
++ int rc = 0;
++
++ daemonize();
++ sprintf(current->comm,"cifsoplockd");
++
++ oplockThread = current;
++ do {
++ set_current_state(TASK_INTERRUPTIBLE);
++
++ schedule_timeout(1*HZ);
++ spin_lock(&GlobalMid_Lock);
++ if(list_empty(&GlobalOplock_Q)) {
++ spin_unlock(&GlobalMid_Lock);
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(39*HZ);
++ } else {
++ oplock_item = list_entry(GlobalOplock_Q.next,
++ struct oplock_q_entry, qhead);
++ if(oplock_item) {
++ cFYI(1,("found oplock item to write out"));
++ pTcon = oplock_item->tcon;
++ inode = oplock_item->pinode;
++ netfid = oplock_item->netfid;
++ spin_unlock(&GlobalMid_Lock);
++ DeleteOplockQEntry(oplock_item);
++ /* can not grab inode sem here since it would
++ deadlock when oplock received on delete
++ since vfs_unlink holds the i_sem across
++ the call */
++ /* down(&inode->i_sem);*/
++ if (S_ISREG(inode->i_mode)) {
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
++ rc = filemap_fdatasync(inode->i_mapping);
++ if(rc)
++ CIFS_I(inode)->write_behind_rc = rc;
++#else
++ filemap_fdatasync(inode->i_mapping);
++#endif
++ if(CIFS_I(inode)->clientCanCacheRead == 0)
++ invalidate_inode_pages(inode);
++ } else
++ rc = 0;
++ /* releasing a stale oplock after recent reconnection
++ of smb session using a now incorrect file
++ handle is not a data integrity issue but do
++ not bother sending an oplock release if session
++ to server still is disconnected since oplock
++ already released by the server in that case */
++ if(pTcon->tidStatus != CifsNeedReconnect) {
++ rc = CIFSSMBLock(0, pTcon,
++ netfid,
++ 0 /* len */ , 0 /* offset */, 0,
++ 0, LOCKING_ANDX_OPLOCK_RELEASE,
++ 0 /* wait flag */);
++ cFYI(1,("Oplock release rc = %d ",rc));
++ }
++ } else
++ spin_unlock(&GlobalMid_Lock);
++ }
++ } while(!signal_pending(current));
++ complete_and_exit (&cifs_oplock_exited, 0);
++}
++
++static int __init
++init_cifs(void)
++{
++ int rc = 0;
++#if CONFIG_PROC_FS
++ cifs_proc_init();
++#endif
++ INIT_LIST_HEAD(&GlobalServerList); /* BB not implemented yet */
++ INIT_LIST_HEAD(&GlobalSMBSessionList);
++ INIT_LIST_HEAD(&GlobalTreeConnectionList);
++ INIT_LIST_HEAD(&GlobalOplock_Q);
++/*
++ * Initialize Global counters
++ */
++ atomic_set(&sesInfoAllocCount, 0);
++ atomic_set(&tconInfoAllocCount, 0);
++ atomic_set(&tcpSesReconnectCount, 0);
++ atomic_set(&tconInfoReconnectCount, 0);
++
++ atomic_set(&bufAllocCount, 0);
++ atomic_set(&midCount, 0);
++ GlobalCurrentXid = 0;
++ GlobalTotalActiveXid = 0;
++ GlobalMaxActiveXid = 0;
++ GlobalSMBSeslock = RW_LOCK_UNLOCKED;
++ GlobalMid_Lock = SPIN_LOCK_UNLOCKED;
++
++/* rc = cifs_init_inodecache();*/
++ if (!rc) {
++ rc = cifs_init_mids();
++ if (!rc) {
++ rc = cifs_init_request_bufs();
++ if (!rc) {
++ rc = register_filesystem(&cifs_fs_type);
++ if (!rc) {
++ kernel_thread(cifs_oplock_thread, NULL,
++ CLONE_FS | CLONE_FILES | CLONE_VM);
++ return rc; /* Success */
++ } else
++ cifs_destroy_request_bufs();
++ }
++ cifs_destroy_mids();
++ }
++/* cifs_destroy_inodecache(); */
++ }
++#if CONFIG_PROC_FS
++ cifs_proc_clean();
++#endif
++ return rc;
++}
++
++static void __exit
++exit_cifs(void)
++{
++ cFYI(0, ("In unregister ie exit_cifs"));
++#if CONFIG_PROC_FS
++ cifs_proc_clean();
++#endif
++ unregister_filesystem(&cifs_fs_type);
++/* cifs_destroy_inodecache();*/
++ cifs_destroy_mids();
++ cifs_destroy_request_bufs();
++ if(oplockThread) {
++ send_sig(SIGTERM, oplockThread, 1);
++ wait_for_completion(&cifs_oplock_exited);
++ }
++}
++
++MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
++MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
++MODULE_DESCRIPTION
++ ("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows");
++module_init(init_cifs)
++module_exit(exit_cifs)
+diff -urN linux-2.4.29.old/fs/cifs/cifsfs.h linux-2.4.29/fs/cifs/cifsfs.h
+--- linux-2.4.29.old/fs/cifs/cifsfs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/cifsfs.h 2004-07-14 00:25:04.000000000 +0200
+@@ -0,0 +1,97 @@
++/*
++ * fs/cifs/cifsfs.h
++ *
++ * Copyright (c) International Business Machines Corp., 2002
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _CIFSFS_H
++#define _CIFSFS_H
++
++#define ROOT_I 2
++
++#ifndef FALSE
++#define FALSE 0
++#endif
++
++#ifndef TRUE
++#define TRUE 1
++#endif
++
++extern int map_cifs_error(int error_class, int error_code,
++ int status_codes_negotiated);
++
++extern struct address_space_operations cifs_addr_ops;
++
++/* Functions related to super block operations */
++extern struct super_operations cifs_super_ops;
++extern void cifs_put_inode(struct inode *);
++extern void cifs_read_inode(struct inode *);
++extern void cifs_delete_inode(struct inode *);
++/* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */
++
++/* Functions related to inodes */
++extern struct inode_operations cifs_dir_inode_ops;
++extern int cifs_create(struct inode *, struct dentry *, int);
++extern struct dentry *cifs_lookup(struct inode *, struct dentry *);
++extern int cifs_unlink(struct inode *, struct dentry *);
++extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
++extern int cifs_mknod(struct inode *, struct dentry *, int, int);
++extern int cifs_mkdir(struct inode *, struct dentry *, int);
++extern int cifs_rmdir(struct inode *, struct dentry *);
++extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
++ struct dentry *);
++extern int cifs_revalidate(struct dentry *);
++extern int cifs_setattr(struct dentry *, struct iattr *);
++
++extern struct inode_operations cifs_file_inode_ops;
++extern void cifs_truncate_file(struct inode *);
++extern struct inode_operations cifs_symlink_inode_ops;
++
++/* Functions related to files and directories */
++extern struct file_operations cifs_file_ops;
++extern int cifs_open(struct inode *inode, struct file *file);
++extern int cifs_close(struct inode *inode, struct file *file);
++extern int cifs_closedir(struct inode *inode, struct file *file);
++extern ssize_t cifs_read(struct file *file, char *read_data,
++ size_t read_size, loff_t * poffset);
++extern ssize_t cifs_write(struct file *file, const char *write_data,
++ size_t write_size, loff_t * poffset);
++extern int cifs_lock(struct file *, int, struct file_lock *);
++extern int cifs_fsync(struct file *, struct dentry *, int);
++extern int cifs_flush(struct file *);
++extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
++extern struct file_operations cifs_dir_ops;
++extern int cifs_dir_open(struct inode *inode, struct file *file);
++extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir);
++extern long cifs_fcntl(int, unsigned int, unsigned long, struct file *);
++
++/* Functions related to dir entries */
++extern struct dentry_operations cifs_dentry_ops;
++
++/* Functions related to symlinks */
++extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
++extern int cifs_readlink(struct dentry *direntry, char *buffer, int buflen);
++extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
++ const char *symname);
++extern int cifs_removexattr(struct dentry *, const char *);
++extern int cifs_setxattr(struct dentry *, const char *, const void *,
++ size_t, int);
++extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
++extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
++#define CIFS_VERSION "1.20"
++#endif /* _CIFSFS_H */
+diff -urN linux-2.4.29.old/fs/cifs/cifs_fs_sb.h linux-2.4.29/fs/cifs/cifs_fs_sb.h
+--- linux-2.4.29.old/fs/cifs/cifs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/cifs_fs_sb.h 2004-07-14 00:25:04.000000000 +0200
+@@ -0,0 +1,32 @@
++/*
++ * fs/cifs/cifs_fs_sb.h
++ *
++ * Copyright (c) International Business Machines Corp., 2002
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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.
++ *
++ */
++#ifndef _CIFS_FS_SB_H
++#define _CIFS_FS_SB_H
++
++struct cifs_sb_info {
++ struct cifsTconInfo *tcon; /* primary mount */
++ struct list_head nested_tcon_q;
++ struct nls_table *local_nls;
++ unsigned int rsize;
++ unsigned int wsize;
++ uid_t mnt_uid;
++ gid_t mnt_gid;
++ mode_t mnt_file_mode;
++ mode_t mnt_dir_mode;
++};
++#endif /* _CIFS_FS_SB_H */
+diff -urN linux-2.4.29.old/fs/cifs/cifsglob.h linux-2.4.29/fs/cifs/cifsglob.h
+--- linux-2.4.29.old/fs/cifs/cifsglob.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/cifsglob.h 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,413 @@
++/*
++ * fs/cifs/cifsglob.h
++ *
++ * Copyright (C) International Business Machines Corp., 2002,2003
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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.
++ *
++ */
++#include <linux/in.h>
++#include <linux/in6.h>
++#include "cifs_fs_sb.h"
++/*
++ * The sizes of various internal tables and strings
++ */
++#define MAX_UID_INFO 16
++#define MAX_SES_INFO 2
++#define MAX_TCON_INFO 4
++
++#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1
++#define MAX_SERVER_SIZE 15
++#define MAX_SHARE_SIZE 64 /* used to be 20 - this should still be enough */
++#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null
++ termination then *2 for unicode versions */
++#define MAX_PASSWORD_SIZE 16
++
++/*
++ * MAX_REQ is the maximum number of requests that WE will send
++ * on one socket concurently. It also matches the most common
++ * value of max multiplex returned by servers. We may
++ * eventually want to use the negotiated value (in case
++ * future servers can handle more) when we are more confident that
++ * we will not have problems oveloading the socket with pending
++ * write data.
++ */
++#define CIFS_MAX_REQ 50
++
++#define SERVER_NAME_LENGTH 15
++#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
++
++/* used to define string lengths for reversing unicode strings */
++/* (256+1)*2 = 514 */
++/* (max path length + 1 for null) * 2 for unicode */
++#define MAX_NAME 514
++
++#include "cifspdu.h"
++
++#ifndef FALSE
++#define FALSE 0
++#endif
++
++#ifndef TRUE
++#define TRUE 1
++#endif
++
++#ifndef XATTR_DOS_ATTRIB
++#define XATTR_DOS_ATTRIB "user.DOSATTRIB"
++#endif
++
++/*
++ * This information is kept on every Server we know about.
++ *
++ * Some things to note:
++ *
++ */
++#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
++
++/*
++ * CIFS vfs client Status information (based on what we know.)
++ */
++
++ /* associated with each tcp and smb session */
++enum statusEnum {
++ CifsNew = 0,
++ CifsGood,
++ CifsExiting,
++ CifsNeedReconnect
++};
++
++enum securityEnum {
++ NTLM = 0, /* Legacy NTLM012 auth with NTLM hash */
++ NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
++ RawNTLMSSP, /* NTLMSSP without SPNEGO */
++ NTLMSSP, /* NTLMSSP via SPNEGO */
++ Kerberos /* Kerberos via SPNEGO */
++};
++
++enum protocolEnum {
++ IPV4 = 0,
++ IPV6,
++ SCTP
++ /* Netbios frames protocol not supported at this time */
++};
++
++/*
++ *****************************************************************
++ * Except the CIFS PDUs themselves all the
++ * globally interesting structs should go here
++ *****************************************************************
++ */
++
++struct TCP_Server_Info {
++ char server_Name[SERVER_NAME_LEN_WITH_NULL]; /* 15 chars + X'20'in 16th */
++ char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; /* Unicode version of server_Name */
++ struct socket *ssocket;
++ union {
++ struct sockaddr_in sockAddr;
++ struct sockaddr_in6 sockAddr6;
++ } addr;
++ wait_queue_head_t response_q;
++ wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
++ struct list_head pending_mid_q;
++ void *Server_NlsInfo; /* BB - placeholder for future NLS info */
++ unsigned short server_codepage; /* codepage for the server */
++ unsigned long ip_address; /* IP addr for the server if known */
++ enum protocolEnum protocolType;
++ char versionMajor;
++ char versionMinor;
++ int svlocal:1; /* local server or remote */
++ atomic_t socketUseCount; /* number of open cifs sessions on socket */
++ atomic_t inFlight; /* number of requests on the wire to server */
++ enum statusEnum tcpStatus; /* what we think the status is */
++ struct semaphore tcpSem;
++ struct task_struct *tsk;
++ char server_GUID[16];
++ char secMode;
++ enum securityEnum secType;
++ unsigned int maxReq; /* Clients should submit no more */
++ /* than maxReq distinct unanswered SMBs to the server when using */
++ /* multiplexed reads or writes */
++ unsigned int maxBuf; /* maxBuf specifies the maximum */
++ /* message size the server can send or receive for non-raw SMBs */
++ unsigned int maxRw; /* maxRw specifies the maximum */
++ /* message size the server can send or receive for */
++ /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
++ char sessid[4]; /* unique token id for this session */
++ /* (returned on Negotiate */
++ int capabilities; /* allow selective disabling of caps by smb sess */
++ __u16 timeZone;
++ char cryptKey[CIFS_CRYPTO_KEY_SIZE];
++ char workstation_RFC1001_name[16]; /* 16th byte is always zero */
++};
++
++/*
++ * The following is our shortcut to user information. We surface the uid,
++ * and name. We always get the password on the fly in case it
++ * has changed. We also hang a list of sessions owned by this user off here.
++ */
++struct cifsUidInfo {
++ struct list_head userList;
++ struct list_head sessionList; /* SMB sessions for this user */
++ uid_t linux_uid;
++ char user[MAX_USERNAME_SIZE + 1]; /* ascii name of user */
++ /* BB may need ptr or callback for PAM or WinBind info */
++};
++
++/*
++ * Session structure. One of these for each uid session with a particular host
++ */
++struct cifsSesInfo {
++ struct list_head cifsSessionList;
++ struct semaphore sesSem;
++ struct cifsUidInfo *uidInfo; /* pointer to user info */
++ struct TCP_Server_Info *server; /* pointer to server info */
++ atomic_t inUse; /* # of mounts (tree connections) on this ses */
++ enum statusEnum status;
++ __u32 sequence_number; /* needed for CIFS PDU signature */
++ __u16 ipc_tid; /* special tid for connection to IPC share */
++ char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];
++ char *serverOS; /* name of operating system underlying the server */
++ char *serverNOS; /* name of network operating system that the server is running */
++ char *serverDomain; /* security realm of server */
++ int Suid; /* remote smb uid */
++ uid_t linux_uid; /* local Linux uid */
++ int capabilities;
++ char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */
++ char userName[MAX_USERNAME_SIZE + 1];
++ char domainName[MAX_USERNAME_SIZE + 1];
++ char * password;
++};
++
++/*
++ * there is one of these for each connection to a resource on a particular
++ * session
++ */
++struct cifsTconInfo {
++ struct list_head cifsConnectionList;
++ struct list_head openFileList;
++ struct semaphore tconSem;
++ struct cifsSesInfo *ses; /* pointer to session associated with */
++ char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource (in ASCII not UTF) */
++ char *nativeFileSystem;
++ __u16 tid; /* The 2 byte tree id */
++ __u16 Flags; /* optional support bits */
++ enum statusEnum tidStatus;
++ atomic_t useCount; /* how many mounts (explicit or implicit) to this share */
++#ifdef CONFIG_CIFS_STATS
++ atomic_t num_smbs_sent;
++ atomic_t num_writes;
++ atomic_t num_reads;
++ atomic_t num_oplock_brks;
++ atomic_t num_opens;
++ atomic_t num_deletes;
++ atomic_t num_mkdirs;
++ atomic_t num_rmdirs;
++ atomic_t num_renames;
++ atomic_t num_t2renames;
++ __u64 bytes_read;
++ __u64 bytes_written;
++ spinlock_t stat_lock;
++#endif
++ FILE_SYSTEM_DEVICE_INFO fsDevInfo;
++ FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */
++ FILE_SYSTEM_UNIX_INFO fsUnixInfo;
++ int retry:1;
++ /* BB add field for back pointer to sb struct? */
++};
++
++/*
++ * This info hangs off the cifsFileInfo structure. This is used to track
++ * byte stream locks on the file
++ */
++struct cifsLockInfo {
++ struct cifsLockInfo *next;
++ int start;
++ int length;
++ int type;
++};
++
++/*
++ * One of these for each open instance of a file
++ */
++struct cifsFileInfo {
++ struct list_head tlist; /* pointer to next fid owned by tcon */
++ struct list_head flist; /* next fid (file instance) for this inode */
++ unsigned int uid; /* allows finding which FileInfo structure */
++ __u32 pid; /* process id who opened file */
++ __u16 netfid; /* file id from remote */
++ /* BB add lock scope info here if needed */ ;
++ /* lock scope id (0 if none) */
++ struct file * pfile; /* needed for writepage */
++ struct inode * pInode; /* needed for oplock break */
++ int endOfSearch:1; /* we have reached end of search */
++ int closePend:1; /* file is marked to close */
++ int emptyDir:1;
++ int invalidHandle:1; /* file closed via session abend */
++ struct semaphore fh_sem; /* prevents reopen race after dead ses*/
++ char * search_resume_name;
++ unsigned int resume_name_length;
++ __u32 resume_key;
++};
++
++/*
++ * One of these for each file inode
++ */
++
++struct cifsInodeInfo {
++ struct list_head lockList;
++ /* BB add in lists for dirty pages - i.e. write caching info for oplock */
++ struct list_head openFileList;
++ int write_behind_rc;
++ __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
++ atomic_t inUse; /* num concurrent users (local openers cifs) of file*/
++ unsigned long time; /* jiffies of last update/check of inode */
++ int clientCanCacheRead:1; /* read oplock */
++ int clientCanCacheAll:1; /* read and writebehind oplock */
++ int oplockPending:1;
++ struct inode vfs_inode;
++};
++
++static inline struct cifsInodeInfo * CIFS_I(struct inode *inode)
++{
++ return (struct cifsInodeInfo *)&(inode->u);
++}
++
++static inline struct cifs_sb_info * CIFS_SB(struct super_block *sb)
++{
++ return (struct cifs_sb_info *) &(sb->u);
++}
++
++
++/* one of these for every pending CIFS request to the server */
++struct mid_q_entry {
++ struct list_head qhead; /* mids waiting on reply from this server */
++ __u16 mid; /* multiplex id */
++ __u16 pid; /* process id */
++ __u32 sequence_number; /* for CIFS signing */
++ __u16 command; /* smb command code */
++ struct timeval when_sent; /* time when smb sent */
++ struct cifsSesInfo *ses; /* smb was sent to this server */
++ struct task_struct *tsk; /* task waiting for response */
++ struct smb_hdr *resp_buf; /* response buffer */
++ int midState; /* wish this were enum but can not pass to wait_event */
++};
++
++struct oplock_q_entry {
++ struct list_head qhead;
++ struct inode * pinode;
++ struct cifsTconInfo * tcon;
++ __u16 netfid;
++};
++
++#define MID_FREE 0
++#define MID_REQUEST_ALLOCATED 1
++#define MID_REQUEST_SUBMITTED 2
++#define MID_RESPONSE_RECEIVED 4
++#define MID_RETRY_NEEDED 8 /* session closed while this request out */
++
++/*
++ *****************************************************************
++ * All constants go here
++ *****************************************************************
++ */
++
++#define UID_HASH (16)
++
++/*
++ * Note that ONE module should define _DECLARE_GLOBALS_HERE to cause the
++ * following to be declared.
++ */
++
++/****************************************************************************
++ * Locking notes. All updates to global variables and lists should be
++ * protected by spinlocks or semaphores.
++ *
++ * Spinlocks
++ * ---------
++ * GlobalMid_Lock protects:
++ * list operations on pending_mid_q and oplockQ
++ * updates to XID counters, multiplex id and SMB sequence numbers
++ * GlobalSMBSesLock protects:
++ * list operations on tcp and SMB session lists and tCon lists
++ * f_owner.lock protects certain per file struct operations
++ * mapping->page_lock protects certain per page operations
++ *
++ * Semaphores
++ * ----------
++ * sesSem operations on smb session
++ * tconSem operations on tree connection
++ * fh_sem file handle reconnection operations
++ *
++ ****************************************************************************/
++
++#ifdef DECLARE_GLOBALS_HERE
++#define GLOBAL_EXTERN
++#else
++#define GLOBAL_EXTERN extern
++#endif
++
++/*
++ * The list of servers that did not respond with NT LM 0.12.
++ * This list helps improve performance and eliminate the messages indicating
++ * that we had a communications error talking to the server in this list.
++ */
++GLOBAL_EXTERN struct servers_not_supported *NotSuppList; /*@z4a */
++
++/*
++ * The following is a hash table of all the users we know about.
++ */
++GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH];
++
++GLOBAL_EXTERN struct list_head GlobalServerList; /* BB not implemented yet */
++GLOBAL_EXTERN struct list_head GlobalSMBSessionList;
++GLOBAL_EXTERN struct list_head GlobalTreeConnectionList;
++GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
++
++GLOBAL_EXTERN struct list_head GlobalOplock_Q;
++
++/*
++ * Global transaction id (XID) information
++ */
++GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */
++GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
++GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
++GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above and list operations */
++ /* on midQ entries */
++GLOBAL_EXTERN char Local_System_Name[15];
++
++/*
++ * Global counters, updated atomically
++ */
++GLOBAL_EXTERN atomic_t sesInfoAllocCount;
++GLOBAL_EXTERN atomic_t tconInfoAllocCount;
++
++GLOBAL_EXTERN atomic_t tcpSesReconnectCount;
++GLOBAL_EXTERN atomic_t tconInfoReconnectCount;
++
++/* Various Debug counters to remove someday (BB) */
++GLOBAL_EXTERN atomic_t bufAllocCount;
++GLOBAL_EXTERN atomic_t midCount;
++
++/* Misc globals */
++GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
++ to be established on existing mount if we
++ have the uid/password or Kerberos credential
++ or equivalent for current user */
++GLOBAL_EXTERN unsigned int oplockEnabled;
++GLOBAL_EXTERN unsigned int quotaEnabled;
++GLOBAL_EXTERN unsigned int lookupCacheEnabled;
++GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
++ with more secure ntlmssp2 challenge/resp */
++GLOBAL_EXTERN unsigned int ntlmv2_support; /* better optional password hash */
++GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
++GLOBAL_EXTERN unsigned int linuxExtEnabled; /* enable Linux/Unix CIFS extensions */
++
+diff -urN linux-2.4.29.old/fs/cifs/cifspdu.h linux-2.4.29/fs/cifs/cifspdu.h
+--- linux-2.4.29.old/fs/cifs/cifspdu.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/cifspdu.h 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,1793 @@
++/*
++ * fs/cifs/cifspdu.h
++ *
++ * Copyright (c) International Business Machines Corp., 2002
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _CIFSPDU_H
++#define _CIFSPDU_H
++
++#include <net/sock.h>
++
++#define CIFS_PROT 0
++#define BAD_PROT CIFS_PROT+1
++
++/* SMB command codes */
++#define SMB_COM_CREATE_DIRECTORY 0x00
++#define SMB_COM_DELETE_DIRECTORY 0x01
++#define SMB_COM_CLOSE 0x04
++#define SMB_COM_DELETE 0x06
++#define SMB_COM_RENAME 0x07
++#define SMB_COM_LOCKING_ANDX 0x24
++#define SMB_COM_COPY 0x29
++#define SMB_COM_READ_ANDX 0x2E
++#define SMB_COM_WRITE_ANDX 0x2F
++#define SMB_COM_TRANSACTION2 0x32
++#define SMB_COM_TRANSACTION2_SECONDARY 0x33
++#define SMB_COM_FIND_CLOSE2 0x34
++#define SMB_COM_TREE_DISCONNECT 0x71
++#define SMB_COM_NEGOTIATE 0x72
++#define SMB_COM_SESSION_SETUP_ANDX 0x73
++#define SMB_COM_LOGOFF_ANDX 0x74
++#define SMB_COM_TREE_CONNECT_ANDX 0x75
++#define SMB_COM_NT_TRANSACT 0xA0
++#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1
++#define SMB_COM_NT_CREATE_ANDX 0xA2
++#define SMB_COM_NT_RENAME 0xA5
++
++/* Transact2 subcommand codes */
++#define TRANS2_OPEN 0x00
++#define TRANS2_FIND_FIRST 0x01
++#define TRANS2_FIND_NEXT 0x02
++#define TRANS2_QUERY_FS_INFORMATION 0x03
++#define TRANS2_QUERY_PATH_INFORMATION 0x05
++#define TRANS2_SET_PATH_INFORMATION 0x06
++#define TRANS2_QUERY_FILE_INFORMATION 0x07
++#define TRANS2_SET_FILE_INFORMATION 0x08
++#define TRANS2_GET_DFS_REFERRAL 0x10
++#define TRANS2_REPORT_DFS_INCOSISTENCY 0x11
++
++/* NT Transact subcommand codes */
++#define NT_TRANSACT_CREATE 0x01
++#define NT_TRANSACT_IOCTL 0x02
++#define NT_TRANSACT_SET_SECURITY_DESC 0x03
++#define NT_TRANSACT_NOTIFY_CHANGE 0x04
++#define NT_TRANSACT_RENAME 0x05
++#define NT_TRANSACT_QUERY_SECURITY_DESC 0x06
++#define NT_TRANSACT_GET_USER_QUOTA 0x07
++#define NT_TRANSACT_SET_USER_QUOTA 0x08
++
++#define MAX_CIFS_HDR_SIZE 256 /* chained NTCreateXReadX will probably be biggest */
++
++/* internal cifs vfs structures */
++/*****************************************************************
++ * All constants go here
++ *****************************************************************
++ */
++
++/*
++ * Starting value for maximum SMB size negotiation
++ */
++#define CIFS_MAX_MSGSIZE (4*4096)
++
++/*
++ * Size of encrypted user password in bytes
++ */
++#define CIFS_ENCPWD_SIZE (16)
++
++/*
++ * Size of the crypto key returned on the negotiate SMB in bytes
++ */
++#define CIFS_CRYPTO_KEY_SIZE (8)
++
++/*
++ * Size of the session key (crypto key encrypted with the password
++ */
++#define CIFS_SESSION_KEY_SIZE (24)
++
++/*
++ * Maximum user name length
++ */
++#define CIFS_UNLEN (20)
++
++/*
++ * Flags on SMB open
++ */
++#define SMBOPEN_WRITE_THROUGH 0x4000
++#define SMBOPEN_DENY_ALL 0x0010
++#define SMBOPEN_DENY_WRITE 0x0020
++#define SMBOPEN_DENY_READ 0x0030
++#define SMBOPEN_DENY_NONE 0x0040
++#define SMBOPEN_READ 0x0000
++#define SMBOPEN_WRITE 0x0001
++#define SMBOPEN_READWRITE 0x0002
++#define SMBOPEN_EXECUTE 0x0003
++
++#define SMBOPEN_OCREATE 0x0010
++#define SMBOPEN_OTRUNC 0x0002
++#define SMBOPEN_OAPPEND 0x0001
++
++/*
++ * SMB flag definitions
++ */
++#define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock primitives */
++#define SMBFLG_RCV_POSTED 0x02 /* obsolete */
++#define SMBFLG_RSVD 0x04
++#define SMBFLG_CASELESS 0x08 /* all pathnames treated as caseless (off implies case sensitive file handling requested) */
++#define SMBFLG_CANONICAL_PATH_FORMAT 0x10 /* obsolete */
++#define SMBFLG_OLD_OPLOCK 0x20 /* obsolete */
++#define SMBFLG_OLD_OPLOCK_NOTIFY 0x40 /* obsolete */
++#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */
++
++/*
++ * SMB flag2 definitions
++ */
++#define SMBFLG2_KNOWS_LONG_NAMES 0x0001 /* can send long (non-8.3) path names in response */
++#define SMBFLG2_KNOWS_EAS 0x0002
++#define SMBFLG2_SECURITY_SIGNATURE 0x0004
++#define SMBFLG2_IS_LONG_NAME 0x0040
++#define SMBFLG2_EXT_SEC 0x0800
++#define SMBFLG2_DFS 0x1000
++#define SMBFLG2_PAGING_IO 0x2000
++#define SMBFLG2_ERR_STATUS 0x4000
++#define SMBFLG2_UNICODE 0x8000
++
++/*
++ * These are the file access permission bits defined in CIFS for the
++ * NTCreateAndX as well as the level 0x107
++ * TRANS2_QUERY_PATH_INFORMATION API. The level 0x107, SMB_QUERY_FILE_ALL_INFO
++ * responds with the AccessFlags.
++ * The AccessFlags specifies the access permissions a caller has to the
++ * file and can have any suitable combination of the following values:
++ */
++
++#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */
++#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */
++#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */
++#define FILE_READ_EA 0x00000008 /* Extended attributes associated */
++ /* with the file can be read */
++#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */
++ /* with the file can be written */
++#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */
++ /* the file using system paging I/O */
++#define FILE_DELETE_CHILD 0x00000040
++#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */
++ /* file can be read */
++#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */
++ /* file can be written */
++#define DELETE 0x00010000 /* The file can be deleted */
++#define READ_CONTROL 0x00020000 /* The access control list and */
++ /* ownership associated with the */
++ /* file can be read */
++#define WRITE_DAC 0x00040000 /* The access control list and */
++ /* ownership associated with the */
++ /* file can be written. */
++#define WRITE_OWNER 0x00080000 /* Ownership information associated */
++ /* with the file can be written */
++#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
++ /* synchronize with the completion */
++ /* of an input/output request */
++#define GENERIC_ALL 0x10000000
++#define GENERIC_EXECUTE 0x20000000
++#define GENERIC_WRITE 0x40000000
++#define GENERIC_READ 0x80000000
++ /* In summary - Relevant file */
++ /* access flags from CIFS are */
++ /* file_read_data, file_write_data */
++ /* file_execute, file_read_attributes */
++ /* write_dac, and delete. */
++
++/*
++ * Invalid readdir handle
++ */
++#define CIFS_NO_HANDLE 0xFFFF
++
++/* IPC$ in ASCII */
++#define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
++
++/* IPC$ in Unicode */
++#define CIFS_IPC_UNICODE_RESOURCE "\x00\x49\x00\x50\x00\x43\x00\x24\x00\x00"
++
++/* Unicode Null terminate 2 bytes of 0 */
++#define UNICODE_NULL "\x00\x00"
++#define ASCII_NULL 0x00
++
++/*
++ * Server type values (returned on EnumServer API
++ */
++#define CIFS_SV_TYPE_DC 0x00000008
++#define CIFS_SV_TYPE_BACKDC 0x00000010
++
++/*
++ * Alias type flags (From EnumAlias API call
++ */
++#define CIFS_ALIAS_TYPE_FILE 0x0001
++#define CIFS_SHARE_TYPE_FILE 0x0000
++
++/*
++ * File Attribute flags
++ */
++#define ATTR_READONLY 0x0001
++#define ATTR_HIDDEN 0x0002
++#define ATTR_SYSTEM 0x0004
++#define ATTR_VOLUME 0x0008
++#define ATTR_DIRECTORY 0x0010
++#define ATTR_ARCHIVE 0x0020
++#define ATTR_DEVICE 0x0040
++#define ATTR_NORMAL 0x0080
++#define ATTR_TEMPORARY 0x0100
++#define ATTR_SPARSE 0x0200
++#define ATTR_REPARSE 0x0400
++#define ATTR_COMPRESSED 0x0800
++#define ATTR_OFFLINE 0x1000 /* ie file not immediately available - offline storage */
++#define ATTR_NOT_CONTENT_INDEXED 0x2000
++#define ATTR_ENCRYPTED 0x4000
++#define ATTR_POSIX_SEMANTICS 0x01000000
++#define ATTR_BACKUP_SEMANTICS 0x02000000
++#define ATTR_DELETE_ON_CLOSE 0x04000000
++#define ATTR_SEQUENTIAL_SCAN 0x08000000
++#define ATTR_RANDOM_ACCESS 0x10000000
++#define ATTR_NO_BUFFERING 0x20000000
++#define ATTR_WRITE_THROUGH 0x80000000
++
++/* ShareAccess flags */
++#define FILE_NO_SHARE 0x00000000
++#define FILE_SHARE_READ 0x00000001
++#define FILE_SHARE_WRITE 0x00000002
++#define FILE_SHARE_DELETE 0x00000004
++#define FILE_SHARE_ALL 0x00000007
++
++/* CreateDisposition flags */
++#define FILE_SUPERSEDE 0x00000000
++#define FILE_OPEN 0x00000001
++#define FILE_CREATE 0x00000002
++#define FILE_OPEN_IF 0x00000003
++#define FILE_OVERWRITE 0x00000004
++#define FILE_OVERWRITE_IF 0x00000005
++
++/* CreateOptions */
++#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */
++#define CREATE_WRITE_THROUGH 0x00000002
++#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */
++#define CREATE_RANDOM_ACCESS 0x00000800
++#define CREATE_DELETE_ON_CLOSE 0x00001000
++#define OPEN_REPARSE_POINT 0x00200000
++
++/* ImpersonationLevel flags */
++#define SECURITY_ANONYMOUS 0
++#define SECURITY_IDENTIFICATION 1
++#define SECURITY_IMPERSONATION 2
++#define SECURITY_DELEGATION 3
++
++/* SecurityFlags */
++#define SECURITY_CONTEXT_TRACKING 0x01
++#define SECURITY_EFFECTIVE_ONLY 0x02
++
++/*
++ * Default PID value, used in all SMBs where the PID is not important
++ */
++#define CIFS_DFT_PID 0x1234
++
++/*
++ * We use the same routine for Copy and Move SMBs. This flag is used to
++ * distinguish
++ */
++#define CIFS_COPY_OP 1
++#define CIFS_RENAME_OP 2
++
++#define GETU16(var) (*((__u16 *)var)) /* BB check for endian issues */
++#define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */
++
++#pragma pack(1)
++
++struct smb_hdr {
++ __u32 smb_buf_length; /* big endian on wire *//* BB length is only two or three bytes - with one or two byte type preceding it but that is always zero - we could mask the type byte off just in case BB */
++ __u8 Protocol[4];
++ __u8 Command;
++ union {
++ struct {
++ __u8 ErrorClass;
++ __u8 Reserved;
++ __u16 Error; /* note: treated as little endian (le) on wire */
++ } DosError;
++ __u32 CifsError; /* note: le */
++ } Status;
++ __u8 Flags;
++ __u16 Flags2; /* note: le */
++ __u16 PidHigh; /* note: le */
++ union {
++ struct {
++ __u32 SequenceNumber; /* le */
++ __u32 Reserved; /* zero */
++ } Sequence;
++ __u8 SecuritySignature[8]; /* le */
++ } Signature;
++ __u8 pad[2];
++ __u16 Tid;
++ __u16 Pid; /* note: le */
++ __u16 Uid;
++ __u16 Mid;
++ __u8 WordCount;
++};
++/* given a pointer to an smb_hdr retrieve the value of byte count */
++#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
++
++/* given a pointer to an smb_hdr retrieve the pointer to the byte area */
++#define pByteArea(smb_var) ((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
++
++/*
++ * Computer Name Length
++ */
++#define CNLEN 15
++
++/*
++ * Share Name Length @S8A
++ * Note: This length is limited by the SMB used to get @S8A
++ * the Share info. NetShareEnum only returns 13 @S8A
++ * chars, including the null termination. @S8A
++ */
++#define SNLEN 12 /*@S8A */
++
++/*
++ * Comment Length
++ */
++#define MAXCOMMENTLEN 40
++
++/*
++ * The OS/2 maximum path name
++ */
++#define MAX_PATHCONF 256
++
++/*
++ * SMB frame definitions (following must be packed structs)
++ * See the SNIA CIFS Specification for details.
++ *
++ * The Naming convention is the lower case version of the
++ * smb command code name for the struct and this is typedef to the
++ * uppercase version of the same name with the prefix SMB_ removed
++ * for brevity. Although typedefs are not commonly used for
++ * structure definitions in the Linux kernel, their use in the
++ * CIFS standards document, which this code is based on, may
++ * make this one of the cases where typedefs for structures make
++ * sense to improve readability for readers of the standards doc.
++ * Typedefs can always be removed later if they are too distracting
++ * and they are only used for the CIFSs PDUs themselves, not
++ * internal cifs vfs structures
++ *
++ */
++
++typedef struct negotiate_req {
++ struct smb_hdr hdr; /* wct = 0 */
++ __u16 ByteCount;
++ unsigned char DialectsArray[1];
++} NEGOTIATE_REQ;
++
++typedef struct negotiate_rsp {
++ struct smb_hdr hdr; /* wct = 17 */
++ __u16 DialectIndex;
++ __u8 SecurityMode;
++ __u16 MaxMpxCount;
++ __u16 MaxNumberVcs;
++ __u32 MaxBufferSize;
++ __u32 MaxRawSize;
++ __u32 SessionKey;
++ __u32 Capabilities; /* see below */
++ __u32 SystemTimeLow;
++ __u32 SystemTimeHigh;
++ __u16 ServerTimeZone;
++ __u8 EncryptionKeyLength;
++ __u16 ByteCount;
++ union {
++ unsigned char EncryptionKey[1]; /* if cap extended security is off */
++ /* followed by Domain name - if extended security is off */
++ /* followed by 16 bytes of server GUID */
++ /* followed by security blob if cap_extended_security negotiated */
++ struct {
++ unsigned char GUID[16];
++ unsigned char SecurityBlob[1];
++ } extended_response;
++ } u;
++} NEGOTIATE_RSP;
++
++/* SecurityMode bits */
++#define SECMODE_USER 0x01 /* off indicates share level security */
++#define SECMODE_PW_ENCRYPT 0x02
++#define SECMODE_SIGN_ENABLED 0x04 /* SMB security signatures enabled */
++#define SECMODE_SIGN_REQUIRED 0x08 /* SMB security signatures required */
++
++/* Negotiate response Capabilities */
++#define CAP_RAW_MODE 0x00000001
++#define CAP_MPX_MODE 0x00000002
++#define CAP_UNICODE 0x00000004
++#define CAP_LARGE_FILES 0x00000008
++#define CAP_NT_SMBS 0x00000010 /* implies CAP_NT_FIND */
++#define CAP_RPC_REMOTE_APIS 0x00000020
++#define CAP_STATUS32 0x00000040
++#define CAP_LEVEL_II_OPLOCKS 0x00000080
++#define CAP_LOCK_AND_READ 0x00000100
++#define CAP_NT_FIND 0x00000200
++#define CAP_DFS 0x00001000
++#define CAP_INFOLEVEL_PASSTHRU 0x00002000
++#define CAP_LARGE_READ_X 0x00004000
++#define CAP_LARGE_WRITE_X 0x00008000
++#define CAP_UNIX 0x00800000
++#define CAP_RESERVED 0x02000000
++#define CAP_BULK_TRANSFER 0x20000000
++#define CAP_COMPRESSED_DATA 0x40000000
++#define CAP_EXTENDED_SECURITY 0x80000000
++
++typedef union smb_com_session_setup_andx {
++ struct { /* request format */
++ struct smb_hdr hdr; /* wct = 12 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __u16 AndXOffset;
++ __u16 MaxBufferSize;
++ __u16 MaxMpxCount;
++ __u16 VcNumber;
++ __u32 SessionKey;
++ __u16 SecurityBlobLength;
++ __u32 Reserved;
++ __u32 Capabilities; /* see below */
++ __u16 ByteCount;
++ unsigned char SecurityBlob[1]; /* followed by */
++ /* STRING NativeOS */
++ /* STRING NativeLanMan */
++ } req; /* NTLM request format (with extended security */
++
++ struct { /* request format */
++ struct smb_hdr hdr; /* wct = 13 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __u16 AndXOffset;
++ __u16 MaxBufferSize;
++ __u16 MaxMpxCount;
++ __u16 VcNumber;
++ __u32 SessionKey;
++ __u16 CaseInsensitivePasswordLength; /* ASCII password length */
++ __u16 CaseSensitivePasswordLength; /* Unicode password length */
++ __u32 Reserved; /* see below */
++ __u32 Capabilities;
++ __u16 ByteCount;
++ unsigned char CaseInsensitivePassword[1]; /* followed by: */
++ /* unsigned char * CaseSensitivePassword; */
++ /* STRING AccountName */
++ /* STRING PrimaryDomain */
++ /* STRING NativeOS */
++ /* STRING NativeLanMan */
++ } req_no_secext; /* NTLM request format (without extended security */
++
++ struct { /* default (NTLM) response format */
++ struct smb_hdr hdr; /* wct = 4 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __u16 AndXOffset;
++ __u16 Action; /* see below */
++ __u16 SecurityBlobLength;
++ __u16 ByteCount;
++ unsigned char SecurityBlob[1]; /* followed by */
++/* unsigned char * NativeOS; */
++/* unsigned char * NativeLanMan; */
++/* unsigned char * PrimaryDomain; */
++ } resp; /* NTLM response format (with or without extended security */
++
++ struct { /* request format */
++ struct smb_hdr hdr; /* wct = 10 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __u16 AndXOffset;
++ __u16 MaxBufferSize;
++ __u16 MaxMpxCount;
++ __u16 VcNumber;
++ __u32 SessionKey;
++ __u16 PassswordLength;
++ __u32 Reserved;
++ __u16 ByteCount;
++ unsigned char AccountPassword[1]; /* followed by */
++ /* STRING AccountName */
++ /* STRING PrimaryDomain */
++ /* STRING NativeOS */
++ /* STRING NativeLanMan */
++ } old_req; /* pre-NTLM (LANMAN2.1) request format */
++
++ struct { /* default (NTLM) response format */
++ struct smb_hdr hdr; /* wct = 3 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __u16 AndXOffset;
++ __u16 Action; /* see below */
++ __u16 ByteCount;
++ unsigned char NativeOS[1]; /* followed by */
++/* unsigned char * NativeLanMan; */
++/* unsigned char * PrimaryDomain; */
++ } old_resp; /* pre-NTLM (LANMAN2.1) response format */
++} SESSION_SETUP_ANDX;
++
++#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
++
++/* Capabilities bits (for NTLM SessSetup request) */
++#define CAP_UNICODE 0x00000004
++#define CAP_LARGE_FILES 0x00000008
++#define CAP_NT_SMBS 0x00000010
++#define CAP_STATUS32 0x00000040
++#define CAP_LEVEL_II_OPLOCKS 0x00000080
++#define CAP_NT_FIND 0x00000200 /* reserved should be zero (presumably because NT_SMBs implies the same thing) */
++#define CAP_BULK_TRANSFER 0x20000000
++#define CAP_EXTENDED_SECURITY 0x80000000
++
++/* Action bits */
++#define GUEST_LOGIN 1
++
++typedef struct smb_com_tconx_req {
++ struct smb_hdr hdr; /* wct = 4 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __u16 AndXOffset;
++ __u16 Flags; /* see below */
++ __u16 PasswordLength;
++ __u16 ByteCount;
++ unsigned char Password[1]; /* followed by */
++/* STRING Path *//* \\server\share name */
++ /* STRING Service */
++} TCONX_REQ;
++
++typedef struct smb_com_tconx_rsp {
++ struct smb_hdr hdr; /* wct = 3 *//* note that Win2000 has sent wct=7 in some cases on responses. Four unspecified words followed OptionalSupport */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __u16 AndXOffset;
++ __u16 OptionalSupport; /* see below */
++ __u16 ByteCount;
++ unsigned char Service[1]; /* always ASCII, not Unicode */
++ /* STRING NativeFileSystem */
++} TCONX_RSP;
++
++/* tree connect Flags */
++#define DISCONNECT_TID 0x0001
++#define TCON_EXTENDED_SECINFO 0x0008
++/* OptionalSupport bits */
++#define SMB_SUPPORT_SEARCH_BITS 0x0001 /* must have bits (exclusive searches suppt. */
++#define SMB_SHARE_IS_IN_DFS 0x0002
++
++typedef struct smb_com_logoff_andx_req {
++
++ struct smb_hdr hdr; /* wct = 2 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __u16 AndXOffset;
++ __u16 ByteCount;
++} LOGOFF_ANDX_REQ;
++
++typedef struct smb_com_logoff_andx_rsp {
++ struct smb_hdr hdr; /* wct = 2 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __u16 AndXOffset;
++ __u16 ByteCount;
++} LOGOFF_ANDX_RSP;
++
++typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on tree_connect PDU to effect disconnect *//* probably the simplest SMB PDU */
++ struct {
++ struct smb_hdr hdr; /* wct = 0 */
++ __u16 ByteCount; /* bcc = 0 */
++ } req;
++ struct {
++ struct smb_hdr hdr; /* wct = 0 */
++ __u16 ByteCount; /* bcc = 0 */
++ } resp;
++} TREE_DISCONNECT;
++
++typedef struct smb_com_close_req {
++ struct smb_hdr hdr; /* wct = 3 */
++ __u16 FileID;
++ __u32 LastWriteTime; /* should be zero */
++ __u16 ByteCount; /* 0 */
++} CLOSE_REQ;
++
++typedef struct smb_com_close_rsp {
++ struct smb_hdr hdr; /* wct = 0 */
++ __u16 ByteCount; /* bct = 0 */
++} CLOSE_RSP;
++
++typedef struct smb_com_findclose_req {
++ struct smb_hdr hdr; /* wct = 1 */
++ __u16 FileID;
++ __u16 ByteCount; /* 0 */
++} FINDCLOSE_REQ;
++
++/* OpenFlags */
++#define REQ_OPLOCK 0x00000002
++#define REQ_BATCHOPLOCK 0x00000004
++#define REQ_OPENDIRONLY 0x00000008
++
++typedef struct smb_com_open_req { /* also handles create */
++ struct smb_hdr hdr; /* wct = 24 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __u16 AndXOffset;
++ __u8 Reserved; /* Must Be Zero */
++ __u16 NameLength;
++ __u32 OpenFlags;
++ __u32 RootDirectoryFid;
++ __u32 DesiredAccess;
++ __u64 AllocationSize;
++ __u32 FileAttributes;
++ __u32 ShareAccess;
++ __u32 CreateDisposition;
++ __u32 CreateOptions;
++ __u32 ImpersonationLevel;
++ __u8 SecurityFlags;
++ __u16 ByteCount;
++ char fileName[1];
++} OPEN_REQ;
++
++/* open response: oplock levels */
++#define OPLOCK_NONE 0
++#define OPLOCK_EXCLUSIVE 1
++#define OPLOCK_BATCH 2
++#define OPLOCK_READ 3 /* level 2 oplock */
++
++/* open response for CreateAction shifted left */
++#define CIFS_CREATE_ACTION 0x20000 /* file created */
++
++typedef struct smb_com_open_rsp {
++ struct smb_hdr hdr; /* wct = 34 BB */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __u16 AndXOffset;
++ __u8 OplockLevel;
++ __u16 Fid;
++ __u32 CreateAction;
++ __u64 CreationTime;
++ __u64 LastAccessTime;
++ __u64 LastWriteTime;
++ __u64 ChangeTime;
++ __u32 FileAttributes;
++ __u64 AllocationSize;
++ __u64 EndOfFile;
++ __u16 FileType;
++ __u16 DeviceState;
++ __u8 DirectoryFlag;
++ __u16 ByteCount; /* bct = 0 */
++} OPEN_RSP;
++
++typedef struct smb_com_write_req {
++ struct smb_hdr hdr; /* wct = 14 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __u16 AndXOffset;
++ __u16 Fid;
++ __u32 OffsetLow;
++ __u32 Reserved;
++ __u16 WriteMode;
++ __u16 Remaining;
++ __u16 DataLengthHigh;
++ __u16 DataLengthLow;
++ __u16 DataOffset;
++ __u32 OffsetHigh;
++ __u16 ByteCount;
++ __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
++ char Data[1];
++} WRITE_REQ;
++
++typedef struct smb_com_write_rsp {
++ struct smb_hdr hdr; /* wct = 6 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __u16 AndXOffset;
++ __u16 Count;
++ __u16 Remaining;
++ __u32 Reserved;
++ __u16 ByteCount;
++} WRITE_RSP;
++
++typedef struct smb_com_read_req {
++ struct smb_hdr hdr; /* wct = 12 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __u16 AndXOffset;
++ __u16 Fid;
++ __u32 OffsetLow;
++ __u16 MaxCount;
++ __u16 MinCount; /* obsolete */
++ __u32 MaxCountHigh;
++ __u16 Remaining;
++ __u32 OffsetHigh;
++ __u16 ByteCount;
++} READ_REQ;
++
++typedef struct smb_com_read_rsp {
++ struct smb_hdr hdr; /* wct = 12 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __u16 AndXOffset;
++ __u16 Remaining;
++ __u16 DataCompactionMode;
++ __u16 Reserved;
++ __u16 DataLength;
++ __u16 DataOffset;
++ __u16 DataLengthHigh;
++ __u64 Reserved2;
++ __u16 ByteCount;
++ __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
++ char Data[1];
++} READ_RSP;
++
++typedef struct locking_andx_range {
++ __u16 Pid;
++ __u16 Pad;
++ __u32 OffsetHigh;
++ __u32 OffsetLow;
++ __u32 LengthHigh;
++ __u32 LengthLow;
++} LOCKING_ANDX_RANGE;
++
++#define LOCKING_ANDX_SHARED_LOCK 0x01
++#define LOCKING_ANDX_OPLOCK_RELEASE 0x02
++#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x04
++#define LOCKING_ANDX_CANCEL_LOCK 0x08
++#define LOCKING_ANDX_LARGE_FILES 0x10 /* always on for us */
++
++typedef struct smb_com_lock_req {
++ struct smb_hdr hdr; /* wct = 8 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __u16 AndXOffset;
++ __u16 Fid;
++ __u8 LockType;
++ __u8 OplockLevel;
++ __u32 Timeout;
++ __u16 NumberOfUnlocks;
++ __u16 NumberOfLocks;
++ __u16 ByteCount;
++ LOCKING_ANDX_RANGE Locks[1];
++} LOCK_REQ;
++
++typedef struct smb_com_lock_rsp {
++ struct smb_hdr hdr; /* wct = 2 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __u16 AndXOffset;
++ __u16 ByteCount;
++} LOCK_RSP;
++
++typedef struct smb_com_rename_req {
++ struct smb_hdr hdr; /* wct = 1 */
++ __u16 SearchAttributes; /* target file attributes */
++ __u16 ByteCount;
++ __u8 BufferFormat; /* 4 = ASCII or Unicode */
++ unsigned char OldFileName[1];
++ /* followed by __u8 BufferFormat2 */
++ /* followed by NewFileName */
++} RENAME_REQ;
++
++ /* copy request flags */
++#define COPY_MUST_BE_FILE 0x0001
++#define COPY_MUST_BE_DIR 0x0002
++#define COPY_TARGET_MODE_ASCII 0x0004 /* if not set, binary */
++#define COPY_SOURCE_MODE_ASCII 0x0008 /* if not set, binary */
++#define COPY_VERIFY_WRITES 0x0010
++#define COPY_TREE 0x0020
++
++typedef struct smb_com_copy_req {
++ struct smb_hdr hdr; /* wct = 3 */
++ __u16 Tid2;
++ __u16 OpenFunction;
++ __u16 Flags;
++ __u16 ByteCount;
++ __u8 BufferFormat; /* 4 = ASCII or Unicode */
++ unsigned char OldFileName[1];
++ /* followed by __u8 BufferFormat2 */
++ /* followed by NewFileName string */
++} COPY_REQ;
++
++typedef struct smb_com_copy_rsp {
++ struct smb_hdr hdr; /* wct = 1 */
++ __u16 CopyCount; /* number of files copied */
++ __u16 ByteCount; /* may be zero */
++ __u8 BufferFormat; /* 0x04 - only present if errored file follows */
++ unsigned char ErrorFileName[1]; /* only present if error in copy */
++} COPY_RSP;
++
++#define CREATE_HARD_LINK 0x103
++#define MOVEFILE_COPY_ALLOWED 0x0002
++#define MOVEFILE_REPLACE_EXISTING 0x0001
++
++typedef struct smb_com_nt_rename_req { /* A5 - also used for create hardlink */
++ struct smb_hdr hdr; /* wct = 4 */
++ __u16 SearchAttributes; /* target file attributes */
++ __u16 Flags; /* spec says Information Level */
++ __u32 ClusterCount;
++ __u16 ByteCount;
++ __u8 BufferFormat; /* 4 = ASCII or Unicode */
++ unsigned char OldFileName[1];
++ /* followed by __u8 BufferFormat2 */
++ /* followed by NewFileName */
++} NT_RENAME_REQ;
++
++typedef struct smb_com_rename_rsp {
++ struct smb_hdr hdr; /* wct = 0 */
++ __u16 ByteCount; /* bct = 0 */
++} RENAME_RSP;
++
++typedef struct smb_com_delete_file_req {
++ struct smb_hdr hdr; /* wct = 1 */
++ __u16 SearchAttributes;
++ __u16 ByteCount;
++ __u8 BufferFormat; /* 4 = ASCII */
++ unsigned char fileName[1];
++} DELETE_FILE_REQ;
++
++typedef struct smb_com_delete_file_rsp {
++ struct smb_hdr hdr; /* wct = 0 */
++ __u16 ByteCount; /* bct = 0 */
++} DELETE_FILE_RSP;
++
++typedef struct smb_com_delete_directory_req {
++ struct smb_hdr hdr; /* wct = 0 */
++ __u16 ByteCount;
++ __u8 BufferFormat; /* 4 = ASCII */
++ unsigned char DirName[1];
++} DELETE_DIRECTORY_REQ;
++
++typedef struct smb_com_delete_directory_rsp {
++ struct smb_hdr hdr; /* wct = 0 */
++ __u16 ByteCount; /* bct = 0 */
++} DELETE_DIRECTORY_RSP;
++
++typedef struct smb_com_create_directory_req {
++ struct smb_hdr hdr; /* wct = 0 */
++ __u16 ByteCount;
++ __u8 BufferFormat; /* 4 = ASCII */
++ unsigned char DirName[1];
++} CREATE_DIRECTORY_REQ;
++
++typedef struct smb_com_create_directory_rsp {
++ struct smb_hdr hdr; /* wct = 0 */
++ __u16 ByteCount; /* bct = 0 */
++} CREATE_DIRECTORY_RSP;
++
++/***************************************************/
++/* NT Transact structure defintions follow */
++/* Currently only ioctl and notify are implemented */
++/***************************************************/
++typedef struct smb_com_transaction_ioctl_req {
++ struct smb_hdr hdr; /* wct = 23 */
++ __u8 MaxSetupCount;
++ __u16 Reserved;
++ __u32 TotalParameterCount;
++ __u32 TotalDataCount;
++ __u32 MaxParameterCount;
++ __u32 MaxDataCount;
++ __u32 ParameterCount;
++ __u32 ParameterOffset;
++ __u32 DataCount;
++ __u32 DataOffset;
++ __u8 SetupCount; /* four setup words follow subcommand */
++ /* SNIA spec incorrectly included spurious pad here */
++ __u16 SubCommand;/* 2 = IOCTL/FSCTL */
++ __u32 FunctionCode;
++ __u16 Fid;
++ __u8 IsFsctl; /* 1 = File System Control, 0 = device control (IOCTL)*/
++ __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/
++ __u16 ByteCount;
++ __u8 Pad[3];
++ __u8 Data[1];
++} TRANSACT_IOCTL_REQ;
++
++typedef struct smb_com_transaction_ioctl_rsp {
++ struct smb_hdr hdr; /* wct = 19 */
++ __u8 Reserved[3];
++ __u32 TotalParameterCount;
++ __u32 TotalDataCount;
++ __u32 ParameterCount;
++ __u32 ParameterOffset;
++ __u32 ParameterDisplacement;
++ __u32 DataCount;
++ __u32 DataOffset;
++ __u32 DataDisplacement;
++ __u8 SetupCount; /* 1 */
++ __u16 ReturnedDataLen;
++ __u16 ByteCount;
++ __u8 Pad[3];
++} TRANSACT_IOCTL_RSP;
++
++typedef struct smb_com_transaction_change_notify_req {
++ struct smb_hdr hdr; /* wct = 23 */
++ __u8 MaxSetupCount;
++ __u16 Reserved;
++ __u32 TotalParameterCount;
++ __u32 TotalDataCount;
++ __u32 MaxParameterCount;
++ __u32 MaxDataCount;
++ __u32 ParameterCount;
++ __u32 ParameterOffset;
++ __u32 DataCount;
++ __u32 DataOffset;
++ __u8 SetupCount; /* four setup words follow subcommand */
++ /* SNIA spec incorrectly included spurious pad here */
++ __u16 SubCommand;/* 4 = Change Notify */
++ __u32 CompletionFilter; /* operation to monitor */
++ __u16 Fid;
++ __u8 WatchTree; /* 1 = Monitor subdirectories */
++ __u8 Reserved2;
++ __u16 ByteCount;
++/* __u8 Pad[3];*/
++/* __u8 Data[1];*/
++} TRANSACT_CHANGE_NOTIFY_REQ;
++
++typedef struct smb_com_transaction_change_notify_rsp {
++ struct smb_hdr hdr; /* wct = 18 */
++ __u8 Reserved[3];
++ __u32 TotalParameterCount;
++ __u32 TotalDataCount;
++ __u32 ParameterCount;
++ __u32 ParameterOffset;
++ __u32 ParameterDisplacement;
++ __u32 DataCount;
++ __u32 DataOffset;
++ __u32 DataDisplacement;
++ __u8 SetupCount; /* 0 */
++ __u16 ByteCount;
++ /* __u8 Pad[3]; */
++} TRANSACT_CHANGE_NOTIFY_RSP;
++/* Completion Filter flags for Notify */
++#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
++#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
++#define FILE_NOTIFY_CHANGE_NAME 0x00000003
++#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004
++#define FILE_NOTIFY_CHANGE_SIZE 0x00000008
++#define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
++#define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020
++#define FILE_NOTIFY_CHANGE_CREATION 0x00000040
++#define FILE_NOTIFY_CHANGE_EA 0x00000080
++#define FILE_NOTIFY_CHANGE_SECURITY 0x00000100
++#define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200
++#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
++#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
++
++#define FILE_ACTION_ADDED 0x00000001
++#define FILE_ACTION_REMOVED 0x00000002
++#define FILE_ACTION_MODIFIED 0x00000003
++#define FILE_ACTION_RENAMED_OLD_NAME 0x00000004
++#define FILE_ACTION_RENAMED_NEW_NAME 0x00000005
++#define FILE_ACTION_ADDED_STREAM 0x00000006
++#define FILE_ACTION_REMOVED_STREAM 0x00000007
++#define FILE_ACTION_MODIFIED_STREAM 0x00000008
++
++/* response contains array of the following structures */
++struct file_notify_information {
++ __u32 NextEntryOffset;
++ __u32 Action;
++ __u32 FileNameLength;
++ __u8 FileName[1];
++};
++
++struct reparse_data {
++ __u32 ReparseTag;
++ __u16 ReparseDataLength;
++ __u16 Reserved;
++ __u16 AltNameOffset;
++ __u16 AltNameLen;
++ __u16 TargetNameOffset;
++ __u16 TargetNameLen;
++ char LinkNamesBuf[1];
++};
++
++struct cifs_quota_data {
++ __u32 rsrvd1; /* 0 */
++ __u32 sid_size;
++ __u64 rsrvd2; /* 0 */
++ __u64 space_used;
++ __u64 soft_limit;
++ __u64 hard_limit;
++ char sid[1]; /* variable size? */
++};
++
++/* quota sub commands */
++#define QUOTA_LIST_CONTINUE 0
++#define QUOTA_LIST_START 0x100
++#define QUOTA_FOR_SID 0x101
++
++typedef union smb_com_transaction2 {
++ struct {
++ struct smb_hdr hdr; /* wct = 14+ */
++ __u16 TotalParameterCount;
++ __u16 TotalDataCount;
++ __u16 MaxParameterCount;
++ __u16 MaxDataCount;
++ __u8 MaxSetupCount;
++ __u8 Reserved;
++ __u16 Flags;
++ __u32 Timeout;
++ __u16 Reserved2;
++ __u16 ParameterCount;
++ __u16 ParameterOffset;
++ __u16 DataCount;
++ __u16 DataOffset;
++ __u8 SetupCount;
++ __u8 Reserved3;
++ __u16 SubCommand; /* 1st setup word - can be followed by SetupCount words */
++ __u16 ByteCount; /* careful - setupcount is not always one */
++ } req;
++ struct {
++ struct smb_hdr hdr; /* wct = 0 */
++ __u16 TotalParameterCount;
++ __u16 TotalDataCount;
++ __u16 Reserved;
++ __u16 ParameterCount;
++ __u16 ParamterOffset;
++ __u16 ParameterDisplacement;
++ __u16 DataCount;
++ __u16 DataOffset;
++ __u16 DataDisplacement;
++ __u8 SetupCount;
++ __u8 Reserved1; /* should be zero setup words following */
++ __u16 ByteCount;
++ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
++ /* data area follows */
++ } resp;
++} TRANSACTION2;
++
++/* PathInfo/FileInfo infolevels */
++#define SMB_INFO_STANDARD 1
++#define SMB_INFO_QUERY_EAS_FROM_LIST 3
++#define SMB_INFO_QUERY_ALL_EAS 4
++#define SMB_INFO_IS_NAME_VALID 6
++#define SMB_QUERY_FILE_BASIC_INFO 0x101
++#define SMB_QUERY_FILE_STANDARD_INFO 0x102
++#define SMB_QUERY_FILE_EA_INFO 0x103
++#define SMB_QUERY_FILE_NAME_INFO 0x104
++#define SMB_QUERY_FILE_ALLOCATION_INFO 0x105
++#define SMB_QUERY_FILE_END_OF_FILEINFO 0x106
++#define SMB_QUERY_FILE_ALL_INFO 0x107
++#define SMB_QUERY_ALT_NAME_INFO 0x108
++#define SMB_QUERY_FILE_STREAM_INFO 0x109
++#define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B
++#define SMB_QUERY_FILE_UNIX_BASIC 0x200
++#define SMB_QUERY_FILE_UNIX_LINK 0x201
++
++#define SMB_SET_FILE_BASIC_INFO 0x101
++#define SMB_SET_FILE_DISPOSITION_INFO 0x102
++#define SMB_SET_FILE_ALLOCATION_INFO 0x103
++#define SMB_SET_FILE_END_OF_FILE_INFO 0x104
++#define SMB_SET_FILE_UNIX_BASIC 0x200
++#define SMB_SET_FILE_UNIX_LINK 0x201
++#define SMB_SET_FILE_UNIX_HLINK 0x203
++#define SMB_SET_FILE_BASIC_INFO2 0x3ec
++#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2
++#define SMB_FILE_ALL_INFO2 0x3fa
++#define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb
++#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc
++#define SMB_FILE_MOVE_CLUSTER_INFO 0x407
++#define SMB_FILE_QUOTA_INFO 0x408
++#define SMB_FILE_REPARSEPOINT_INFO 0x409
++#define SMB_FILE_MAXIMUM_INFO 0x40d
++
++/* Find File infolevels */
++#define SMB_FIND_FILE_DIRECTORY_INFO 0x101
++#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102
++#define SMB_FIND_FILE_NAMES_INFO 0x103
++#define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104
++#define SMB_FIND_FILE_UNIX 0x202
++
++typedef struct smb_com_transaction2_qpi_req {
++ struct smb_hdr hdr; /* wct = 14+ */
++ __u16 TotalParameterCount;
++ __u16 TotalDataCount;
++ __u16 MaxParameterCount;
++ __u16 MaxDataCount;
++ __u8 MaxSetupCount;
++ __u8 Reserved;
++ __u16 Flags;
++ __u32 Timeout;
++ __u16 Reserved2;
++ __u16 ParameterCount;
++ __u16 ParameterOffset;
++ __u16 DataCount;
++ __u16 DataOffset;
++ __u8 SetupCount;
++ __u8 Reserved3;
++ __u16 SubCommand; /* one setup word */
++ __u16 ByteCount;
++ __u8 Pad;
++ __u16 InformationLevel;
++ __u32 Reserved4;
++ char FileName[1];
++} TRANSACTION2_QPI_REQ;
++
++typedef struct smb_com_transaction2_qpi_rsp {
++ struct smb_hdr hdr; /* wct = 10 + SetupCount */
++ __u16 TotalParameterCount;
++ __u16 TotalDataCount;
++ __u16 Reserved;
++ __u16 ParameterCount;
++ __u16 ParameterOffset;
++ __u16 ParameterDisplacement;
++ __u16 DataCount;
++ __u16 DataOffset;
++ __u16 DataDisplacement;
++ __u8 SetupCount;
++ __u8 Reserved1; /* should be zero setup words following */
++ __u16 ByteCount;
++ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
++} TRANSACTION2_QPI_RSP;
++
++typedef struct smb_com_transaction2_spi_req {
++ struct smb_hdr hdr; /* wct = 15 */
++ __u16 TotalParameterCount;
++ __u16 TotalDataCount;
++ __u16 MaxParameterCount;
++ __u16 MaxDataCount;
++ __u8 MaxSetupCount;
++ __u8 Reserved;
++ __u16 Flags;
++ __u32 Timeout;
++ __u16 Reserved2;
++ __u16 ParameterCount;
++ __u16 ParameterOffset;
++ __u16 DataCount;
++ __u16 DataOffset;
++ __u8 SetupCount;
++ __u8 Reserved3;
++ __u16 SubCommand; /* one setup word */
++ __u16 ByteCount;
++ __u8 Pad;
++ __u16 Pad1;
++ __u16 InformationLevel;
++ __u32 Reserved4;
++ char FileName[1];
++} TRANSACTION2_SPI_REQ;
++
++typedef struct smb_com_transaction2_spi_rsp {
++ struct smb_hdr hdr; /* wct = 10 + SetupCount */
++ __u16 TotalParameterCount;
++ __u16 TotalDataCount;
++ __u16 Reserved;
++ __u16 ParameterCount;
++ __u16 ParameterOffset;
++ __u16 ParameterDisplacement;
++ __u16 DataCount;
++ __u16 DataOffset;
++ __u16 DataDisplacement;
++ __u8 SetupCount;
++ __u8 Reserved1; /* should be zero setup words following */
++ __u16 ByteCount;
++ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
++} TRANSACTION2_SPI_RSP;
++
++struct set_file_rename {
++ __u32 overwrite; /* 1 = overwrite dest */
++ __u32 root_fid; /* zero */
++ __u32 target_name_len;
++ char target_name[0]; /* Must be unicode */
++};
++
++struct smb_com_transaction2_sfi_req {
++ struct smb_hdr hdr; /* wct = 15 */
++ __u16 TotalParameterCount;
++ __u16 TotalDataCount;
++ __u16 MaxParameterCount;
++ __u16 MaxDataCount;
++ __u8 MaxSetupCount;
++ __u8 Reserved;
++ __u16 Flags;
++ __u32 Timeout;
++ __u16 Reserved2;
++ __u16 ParameterCount;
++ __u16 ParameterOffset;
++ __u16 DataCount;
++ __u16 DataOffset;
++ __u8 SetupCount;
++ __u8 Reserved3;
++ __u16 SubCommand; /* one setup word */
++ __u16 ByteCount;
++ __u8 Pad;
++ __u16 Pad1;
++ __u16 Fid;
++ __u16 InformationLevel;
++ __u16 Reserved4;
++};
++
++struct smb_com_transaction2_sfi_rsp {
++ struct smb_hdr hdr; /* wct = 10 + SetupCount */
++ __u16 TotalParameterCount;
++ __u16 TotalDataCount;
++ __u16 Reserved;
++ __u16 ParameterCount;
++ __u16 ParameterOffset;
++ __u16 ParameterDisplacement;
++ __u16 DataCount;
++ __u16 DataOffset;
++ __u16 DataDisplacement;
++ __u8 SetupCount;
++ __u8 Reserved1; /* should be zero setup words following */
++ __u16 ByteCount;
++ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
++};
++
++
++/*
++ * Flags on T2 FINDFIRST and FINDNEXT
++ */
++#define CIFS_SEARCH_CLOSE_ALWAYS 0x0001
++#define CIFS_SEARCH_CLOSE_AT_END 0x0002
++#define CIFS_SEARCH_RETURN_RESUME 0x0004
++#define CIFS_SEARCH_CONTINUE_FROM_LAST 0x0008
++#define CIFS_SEARCH_BACKUP_SEARCH 0x0010
++
++/*
++ * Size of the resume key on FINDFIRST and FINDNEXT calls
++ */
++#define CIFS_SMB_RESUME_KEY_SIZE 4
++
++typedef struct smb_com_transaction2_ffirst_req {
++ struct smb_hdr hdr; /* wct = 15 */
++ __u16 TotalParameterCount;
++ __u16 TotalDataCount;
++ __u16 MaxParameterCount;
++ __u16 MaxDataCount;
++ __u8 MaxSetupCount;
++ __u8 Reserved;
++ __u16 Flags;
++ __u32 Timeout;
++ __u16 Reserved2;
++ __u16 ParameterCount;
++ __u16 ParameterOffset;
++ __u16 DataCount;
++ __u16 DataOffset;
++ __u8 SetupCount; /* one */
++ __u8 Reserved3;
++ __u16 SubCommand; /* TRANS2_FIND_FIRST */
++ __u16 ByteCount;
++ __u8 Pad;
++ __u16 SearchAttributes;
++ __u16 SearchCount;
++ __u16 SearchFlags;
++ __u16 InformationLevel;
++ __u32 SearchStorageType;
++ char FileName[1];
++} TRANSACTION2_FFIRST_REQ;
++
++typedef struct smb_com_transaction2_ffirst_rsp {
++ struct smb_hdr hdr; /* wct = 10 */
++ __u16 TotalParameterCount;
++ __u16 TotalDataCount;
++ __u16 Reserved;
++ __u16 ParameterCount;
++ __u16 ParameterOffset;
++ __u16 ParameterDisplacement;
++ __u16 DataCount;
++ __u16 DataOffset;
++ __u16 DataDisplacement;
++ __u8 SetupCount;
++ __u8 Reserved1; /* should be zero setup words following */
++ __u16 ByteCount;
++} TRANSACTION2_FFIRST_RSP;
++
++typedef struct smb_com_transaction2_ffirst_rsp_parms {
++ __u16 SearchHandle;
++ __u16 SearchCount;
++ __u16 EndofSearch;
++ __u16 EAErrorOffset;
++ __u16 LastNameOffset;
++} T2_FFIRST_RSP_PARMS;
++
++typedef struct smb_com_transaction2_fnext_req {
++ struct smb_hdr hdr; /* wct = 15 */
++ __u16 TotalParameterCount;
++ __u16 TotalDataCount;
++ __u16 MaxParameterCount;
++ __u16 MaxDataCount;
++ __u8 MaxSetupCount;
++ __u8 Reserved;
++ __u16 Flags;
++ __u32 Timeout;
++ __u16 Reserved2;
++ __u16 ParameterCount;
++ __u16 ParameterOffset;
++ __u16 DataCount;
++ __u16 DataOffset;
++ __u8 SetupCount; /* one */
++ __u8 Reserved3;
++ __u16 SubCommand; /* TRANS2_FIND_NEXT */
++ __u16 ByteCount;
++ __u8 Pad;
++ __u16 SearchHandle;
++ __u16 SearchCount;
++ __u16 InformationLevel;
++ __u32 ResumeKey;
++ __u16 SearchFlags;
++ char ResumeFileName[1];
++} TRANSACTION2_FNEXT_REQ;
++
++typedef struct smb_com_transaction2_fnext_rsp {
++ struct smb_hdr hdr; /* wct = 10 */
++ __u16 TotalParameterCount;
++ __u16 TotalDataCount;
++ __u16 Reserved;
++ __u16 ParameterCount;
++ __u16 ParameterOffset;
++ __u16 ParameterDisplacement;
++ __u16 DataCount;
++ __u16 DataOffset;
++ __u16 DataDisplacement;
++ __u8 SetupCount;
++ __u8 Reserved1; /* should be zero setup words following */
++ __u16 ByteCount;
++} TRANSACTION2_FNEXT_RSP;
++
++typedef struct smb_com_transaction2_fnext_rsp_parms {
++ __u16 SearchCount;
++ __u16 EndofSearch;
++ __u16 EAErrorOffset;
++ __u16 LastNameOffset;
++} T2_FNEXT_RSP_PARMS;
++
++/* QFSInfo Levels */
++#define SMB_INFO_ALLOCATION 1
++#define SMB_INFO_VOLUME 2
++#define SMB_QUERY_FS_VOLUME_INFO 0x102
++#define SMB_QUERY_FS_SIZE_INFO 0x103
++#define SMB_QUERY_FS_DEVICE_INFO 0x104
++#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105
++#define SMB_QUERY_CIFS_UNIX_INFO 0x200
++#define SMB_QUERY_LABEL_INFO 0x3ea
++#define SMB_QUERY_FS_QUOTA_INFO 0x3ee
++
++typedef struct smb_com_transaction2_qfsi_req {
++ struct smb_hdr hdr; /* wct = 14+ */
++ __u16 TotalParameterCount;
++ __u16 TotalDataCount;
++ __u16 MaxParameterCount;
++ __u16 MaxDataCount;
++ __u8 MaxSetupCount;
++ __u8 Reserved;
++ __u16 Flags;
++ __u32 Timeout;
++ __u16 Reserved2;
++ __u16 ParameterCount;
++ __u16 ParameterOffset;
++ __u16 DataCount;
++ __u16 DataOffset;
++ __u8 SetupCount;
++ __u8 Reserved3;
++ __u16 SubCommand; /* one setup word */
++ __u16 ByteCount;
++ __u8 Pad;
++ __u16 InformationLevel;
++} TRANSACTION2_QFSI_REQ;
++
++typedef struct smb_com_transaction_qfsi_rsp {
++ struct smb_hdr hdr; /* wct = 10 + SetupCount */
++ __u16 TotalParameterCount;
++ __u16 TotalDataCount;
++ __u16 Reserved;
++ __u16 ParameterCount;
++ __u16 ParameterOffset;
++ __u16 ParameterDisplacement;
++ __u16 DataCount;
++ __u16 DataOffset;
++ __u16 DataDisplacement;
++ __u8 SetupCount;
++ __u8 Reserved1; /* should be zero setup words following */
++ __u16 ByteCount;
++ __u8 Pad; /* may be three bytes *//* followed by data area */
++} TRANSACTION2_QFSI_RSP;
++
++typedef struct smb_com_transaction2_get_dfs_refer_req {
++ struct smb_hdr hdr; /* wct = 15 */
++ __u16 TotalParameterCount;
++ __u16 TotalDataCount;
++ __u16 MaxParameterCount;
++ __u16 MaxDataCount;
++ __u8 MaxSetupCount;
++ __u8 Reserved;
++ __u16 Flags;
++ __u32 Timeout;
++ __u16 Reserved2;
++ __u16 ParameterCount;
++ __u16 ParameterOffset;
++ __u16 DataCount;
++ __u16 DataOffset;
++ __u8 SetupCount;
++ __u8 Reserved3;
++ __u16 SubCommand; /* one setup word */
++ __u16 ByteCount;
++ __u8 Pad[3]; /* Win2K has sent 0x0F01 (max resp length perhaps?) followed by one byte pad - doesn't seem to matter though */
++ __u16 MaxReferralLevel;
++ char RequestFileName[1];
++} TRANSACTION2_GET_DFS_REFER_REQ;
++
++typedef struct dfs_referral_level_3 {
++ __u16 VersionNumber;
++ __u16 ReferralSize;
++ __u16 ServerType; /* 0x0001 = CIFS server */
++ __u16 ReferralFlags; /* or proximity - not clear which since always set to zero - SNIA spec says 0x01 means strip off PathConsumed chars before submitting RequestFileName to remote node */
++ __u16 TimeToLive;
++ __u16 Proximity;
++ __u16 DfsPathOffset;
++ __u16 DfsAlternatePathOffset;
++ __u16 NetworkAddressOffset;
++} REFERRAL3;
++
++typedef struct smb_com_transaction_get_dfs_refer_rsp {
++ struct smb_hdr hdr; /* wct = 10 */
++ __u16 TotalParameterCount;
++ __u16 TotalDataCount;
++ __u16 Reserved;
++ __u16 ParameterCount;
++ __u16 ParameterOffset;
++ __u16 ParameterDisplacement;
++ __u16 DataCount;
++ __u16 DataOffset;
++ __u16 DataDisplacement;
++ __u8 SetupCount;
++ __u8 Reserved1; /* zero setup words following */
++ __u16 ByteCount;
++ __u8 Pad;
++ __u16 PathConsumed;
++ __u16 NumberOfReferrals;
++ __u16 DFSFlags;
++ __u16 Pad2;
++ REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */
++ /* followed by the strings pointed to by the referral structures */
++} TRANSACTION2_GET_DFS_REFER_RSP;
++
++/* DFS Flags */
++#define DFSREF_REFERRAL_SERVER 0x0001
++#define DFSREF_STORAGE_SERVER 0x0002
++
++/* IOCTL information */
++/* List of ioctl function codes that look to be of interest to remote clients like this. */
++/* Need to do some experimentation to make sure they all work remotely. */
++/* Some of the following such as the encryption/compression ones would be */
++/* invoked from tools via a specialized hook into the VFS rather than via the */
++/* standard vfs entry points */
++#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
++#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
++#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
++#define FSCTL_LOCK_VOLUME 0x00090018
++#define FSCTL_UNLOCK_VOLUME 0x0009001C
++#define FSCTL_GET_COMPRESSION 0x0009003C
++#define FSCTL_SET_COMPRESSION 0x0009C040
++#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C
++#define FSCTL_FILESYS_GET_STATISTICS 0x00090090
++#define FSCTL_SET_REPARSE_POINT 0x000900A4
++#define FSCTL_GET_REPARSE_POINT 0x000900A8
++#define FSCTL_DELETE_REPARSE_POINT 0x000900AC
++#define FSCTL_SET_SPARSE 0x000900C4
++#define FSCTL_SET_ZERO_DATA 0x000900C8
++#define FSCTL_SET_ENCRYPTION 0x000900D7
++#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB
++#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF
++#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3
++#define FSCTL_SIS_COPYFILE 0x00090100
++#define FSCTL_SIS_LINK_FILES 0x0009C104
++
++#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
++#define IO_REPARSE_TAG_HSM 0xC0000004
++#define IO_REPARSE_TAG_SIS 0x80000007
++
++/*
++ ************************************************************************
++ * All structs for everything above the SMB PDUs themselves
++ * (such as the T2 level specific data) go here
++ ************************************************************************
++ */
++
++/*
++ * Information on a server
++ */
++
++struct serverInfo {
++ char name[16];
++ unsigned char versionMajor;
++ unsigned char versionMinor;
++ unsigned long type;
++ unsigned int commentOffset;
++};
++
++/*
++ * The following structure is the format of the data returned on a NetShareEnum
++ * with level "90" (x5A)
++ */
++
++struct shareInfo {
++ char shareName[13];
++ char pad;
++ unsigned short type;
++ unsigned int commentOffset;
++};
++
++struct aliasInfo {
++ char aliasName[9];
++ char pad;
++ unsigned int commentOffset;
++ unsigned char type[2];
++};
++
++struct aliasInfo92 {
++ int aliasNameOffset;
++ int serverNameOffset;
++ int shareNameOffset;
++};
++
++typedef struct {
++ __u64 TotalAllocationUnits;
++ __u64 FreeAllocationUnits;
++ __u32 SectorsPerAllocationUnit;
++ __u32 BytesPerSector;
++} FILE_SYSTEM_INFO; /* size info, level 0x103 */
++
++typedef struct {
++ __u16 MajorVersionNumber;
++ __u16 MinorVersionNumber;
++ __u64 Capability;
++} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
++/* Linux/Unix extensions capability flags */
++#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
++#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002
++
++/* DeviceType Flags */
++#define FILE_DEVICE_CD_ROM 0x00000002
++#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
++#define FILE_DEVICE_DFS 0x00000006
++#define FILE_DEVICE_DISK 0x00000007
++#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
++#define FILE_DEVICE_FILE_SYSTEM 0x00000009
++#define FILE_DEVICE_NAMED_PIPE 0x00000011
++#define FILE_DEVICE_NETWORK 0x00000012
++#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
++#define FILE_DEVICE_NULL 0x00000015
++#define FILE_DEVICE_PARALLEL_PORT 0x00000016
++#define FILE_DEVICE_PRINTER 0x00000018
++#define FILE_DEVICE_SERIAL_PORT 0x0000001b
++#define FILE_DEVICE_STREAMS 0x0000001e
++#define FILE_DEVICE_TAPE 0x0000001f
++#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
++#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
++#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
++
++typedef struct {
++ __u32 DeviceType;
++ __u32 DeviceCharacteristics;
++} FILE_SYSTEM_DEVICE_INFO; /* device info, level 0x104 */
++
++typedef struct {
++ __u32 Attributes;
++ __u32 MaxPathNameComponentLength;
++ __u32 FileSystemNameLen;
++ char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */
++} FILE_SYSTEM_ATTRIBUTE_INFO;
++
++typedef struct { /* data block encoding of response to level 263 QPathInfo */
++ __u64 CreationTime;
++ __u64 LastAccessTime;
++ __u64 LastWriteTime;
++ __u64 ChangeTime;
++ __u32 Attributes;
++ __u32 Pad1;
++ __u64 AllocationSize;
++ __u64 EndOfFile; /* size ie offset to first free byte in file */
++ __u32 NumberOfLinks; /* hard links */
++ __u8 DeletePending;
++ __u8 Directory;
++ __u16 Pad2;
++ __u64 IndexNumber;
++ __u32 EASize;
++ __u32 AccessFlags;
++ __u64 IndexNumber1;
++ __u64 CurrentByteOffset;
++ __u32 Mode;
++ __u32 AlignmentRequirement;
++ __u32 FileNameLength;
++ char FileName[1];
++} FILE_ALL_INFO; /* level 263 QPathInfo */
++
++typedef struct {
++ __u64 EndOfFile;
++ __u64 NumOfBytes;
++ __u64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */
++ __u64 LastAccessTime;
++ __u64 LastModificationTime;
++ __u64 Uid;
++ __u64 Gid;
++ __u32 Type;
++ __u64 DevMajor;
++ __u64 DevMinor;
++ __u64 UniqueId;
++ __u64 Permissions;
++ __u64 Nlinks;
++} FILE_UNIX_BASIC_INFO; /* level 512 QPathInfo */
++
++typedef struct {
++ char LinkDest[1];
++} FILE_UNIX_LINK_INFO; /* level 513 QPathInfo */
++
++/* defines for enumerating possible values of the Unix type field below */
++#define UNIX_FILE 0
++#define UNIX_DIR 1
++#define UNIX_SYMLINK 2
++#define UNIX_CHARDEV 3
++#define UNIX_BLOCKDEV 4
++#define UNIX_FIFO 5
++#define UNIX_SOCKET 6
++
++typedef struct {
++ __u32 NextEntryOffset;
++ __u32 ResumeKey;
++ __u64 EndOfFile;
++ __u64 NumOfBytes;
++ __u64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */
++ __u64 LastAccessTime;
++ __u64 LastModificationTime;
++ __u64 Uid;
++ __u64 Gid;
++ __u32 Type;
++ __u64 DevMajor;
++ __u64 DevMinor;
++ __u64 UniqueId;
++ __u64 Permissions;
++ __u64 Nlinks;
++ char FileName[1];
++} FILE_UNIX_INFO;
++
++typedef struct {
++ __u64 CreationTime;
++ __u64 LastAccessTime;
++ __u64 LastWriteTime;
++ __u64 ChangeTime;
++ __u32 Attributes;
++ __u32 Pad;
++} FILE_BASIC_INFO; /* size info, level 0x101 */
++
++struct file_allocation_info {
++ __u64 AllocationSize;
++}; /* size info, level 0x103 */
++
++struct file_end_of_file_info {
++ __u64 FileSize; /* offset to end of file */
++}; /* size info, level 0x104 */
++
++typedef struct {
++ __u32 NextEntryOffset;
++ __u32 FileIndex;
++ __u64 CreationTime;
++ __u64 LastAccessTime;
++ __u64 LastWriteTime;
++ __u64 ChangeTime;
++ __u64 EndOfFile;
++ __u64 AllocationSize;
++ __u32 ExtFileAttributes;
++ __u32 FileNameLength;
++ char FileName[1];
++} FILE_DIRECTORY_INFO; /* level 257 FF response data area */
++
++struct gea {
++ unsigned char cbName;
++ char szName[1];
++};
++
++struct gealist {
++ unsigned long cbList;
++ struct gea list[1];
++};
++
++struct fea {
++ unsigned char EA_flags;
++ __u8 name_len;
++ __u16 value_len;
++ char szName[1];
++ /* optionally followed by value */
++};
++/* flags for _FEA.fEA */
++#define FEA_NEEDEA 0x80 /* need EA bit */
++
++struct fealist {
++ __u32 list_len;
++ struct fea list[1];
++};
++
++/* used to hold an arbitrary blob of data */
++struct data_blob {
++ __u8 *data;
++ size_t length;
++ void (*free) (struct data_blob * data_blob);
++};
++
++#ifdef CONFIG_CIFS_POSIX
++/*
++ For better POSIX semantics from Linux client, (even better
++ than the existing CIFS Unix Extensions) we need updated PDUs for:
++
++ 1) PosixCreateX - to set and return the mode, inode#, device info and
++ perhaps add a CreateDevice - to create Pipes and other special .inodes
++ Also note POSIX open flags
++ 2) Close - to return the last write time to do cache across close more safely
++ 3) PosixQFSInfo - to return statfs info
++ 4) FindFirst return unique inode number - what about resume key, two forms short (matches readdir) and full (enough info to cache inodes)
++ 5) Mkdir - set mode
++
++ And under consideration:
++ 6) FindClose2 (return nanosecond timestamp ??)
++ 7) Use nanosecond timestamps throughout all time fields if
++ corresponding attribute flag is set
++ 8) sendfile - handle based copy
++ 9) Direct i/o
++ 10) "POSIX ACL" support
++ 11) Misc fcntls?
++
++ what about fixing 64 bit alignment
++
++ There are also various legacy SMB/CIFS requests used as is
++
++ From existing Lanman and NTLM dialects:
++ --------------------------------------
++ NEGOTIATE
++ SESSION_SETUP_ANDX (BB which?)
++ TREE_CONNECT_ANDX (BB which wct?)
++ TREE_DISCONNECT (BB add volume timestamp on response)
++ LOGOFF_ANDX
++ DELETE (note delete open file behavior)
++ DELETE_DIRECTORY
++ READ_AND_X
++ WRITE_AND_X
++ LOCKING_AND_X (note posix lock semantics)
++ RENAME (note rename across dirs and open file rename posix behaviors)
++ NT_RENAME (for hardlinks) Is this good enough for all features?
++ FIND_CLOSE2
++ TRANSACTION2 (18 cases)
++ SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2
++ (BB verify that never need to set allocation size)
++ SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via Unix ext?)
++
++ COPY (note support for copy across directories) - FUTURE, OPTIONAL
++ setting/getting OS/2 EAs - FUTURE (BB can this handle
++ setting Linux xattrs perfectly) - OPTIONAL
++ dnotify - FUTURE, OPTIONAL
++ quota - FUTURE, OPTIONAL
++
++ Note that various requests implemented for NT interop such as
++ NT_TRANSACT (IOCTL) QueryReparseInfo
++ are unneeded to servers compliant with the CIFS POSIX extensions
++
++ From CIFS Unix Extensions:
++ -------------------------
++ T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
++ T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2)
++ T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK)
++ T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields
++ Actually need QUERY_FILE_UNIX_INFO since has inode num
++ BB what about a) blksize/blkbits/blocks
++ b) i_version
++ c) i_rdev
++ d) notify mask?
++ e) generation
++ f) size_seqcount
++ T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
++ TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
++ T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
++
++
++ */
++#endif
++
++#pragma pack() /* resume default structure packing */
++
++#endif /* _CIFSPDU_H */
+diff -urN linux-2.4.29.old/fs/cifs/cifsproto.h linux-2.4.29/fs/cifs/cifsproto.h
+--- linux-2.4.29.old/fs/cifs/cifsproto.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/cifsproto.h 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,254 @@
++/*
++ * fs/cifs/cifsproto.h
++ *
++ * Copyright (c) International Business Machines Corp., 2002
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _CIFSPROTO_H
++#define _CIFSPROTO_H
++#include <linux/nls.h>
++
++struct statfs;
++
++/*
++ *****************************************************************
++ * All Prototypes
++ *****************************************************************
++ */
++
++extern struct smb_hdr *cifs_buf_get(void);
++extern void cifs_buf_release(void *);
++extern int smb_send(struct socket *, struct smb_hdr *,
++ unsigned int /* length */ , struct sockaddr *);
++extern unsigned int _GetXid(void);
++extern void _FreeXid(unsigned int);
++#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
++#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,rc));}
++extern char *build_path_from_dentry(struct dentry *);
++extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
++extern void renew_parental_timestamps(struct dentry *direntry);
++extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
++ struct smb_hdr * /* input */ ,
++ struct smb_hdr * /* out */ ,
++ int * /* bytes returned */ , const int long_op);
++extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
++extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
++extern int is_valid_oplock_break(struct smb_hdr *smb);
++extern unsigned int smbCalcSize(struct smb_hdr *ptr);
++extern int decode_negTokenInit(unsigned char *security_blob, int length,
++ enum securityEnum *secType);
++extern int map_smb_to_linux_error(struct smb_hdr *smb);
++extern void header_assemble(struct smb_hdr *, char /* command */ ,
++ const struct cifsTconInfo *, int
++ /* length of fixed section (word count) in two byte units */
++ );
++struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *);
++void DeleteOplockQEntry(struct oplock_q_entry *);
++extern time_t cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
++extern u64 cifs_UnixTimeToNT(time_t);
++extern int cifs_get_inode_info(struct inode **pinode,
++ const unsigned char *search_path,
++ FILE_ALL_INFO * pfile_info,
++ struct super_block *sb, int xid);
++extern int cifs_get_inode_info_unix(struct inode **pinode,
++ const unsigned char *search_path,
++ struct super_block *sb,int xid);
++
++extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
++ struct nls_table * nls_info);
++extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
++
++extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
++ const char *tree, struct cifsTconInfo *tcon,
++ const struct nls_table *);
++
++extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
++ const char *searchName,
++ FILE_DIRECTORY_INFO * findData,
++ T2_FFIRST_RSP_PARMS * findParms,
++ const struct nls_table *nls_codepage,
++ int *pUnicodeFlag,
++ int *pUnixFlag /* if Unix extensions used */ );
++extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
++ FILE_DIRECTORY_INFO * findData,
++ T2_FNEXT_RSP_PARMS * findParms,
++ const __u16 searchHandle, char * resume_name,
++ int name_length, __u32 resume_key,
++ int *UnicodeFlag, int *pUnixFlag);
++
++extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
++ const __u16 search_handle);
++
++extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
++ const unsigned char *searchName,
++ FILE_ALL_INFO * findData,
++ const struct nls_table *nls_codepage);
++
++extern int CIFSSMBUnixQPathInfo(const int xid,
++ struct cifsTconInfo *tcon,
++ const unsigned char *searchName,
++ FILE_UNIX_BASIC_INFO * pFindData,
++ const struct nls_table *nls_codepage);
++
++extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
++ const unsigned char *searchName,
++ unsigned char **targetUNCs,
++ unsigned int *number_of_UNC_in_array,
++ const struct nls_table *nls_codepage);
++
++extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
++ const char *old_path,
++ const struct nls_table *nls_codepage);
++extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
++ const char *old_path, const struct nls_table *nls_codepage,
++ unsigned int *pnum_referrals, unsigned char ** preferrals);
++extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
++ struct statfs *FSData,
++ const struct nls_table *nls_codepage);
++extern int CIFSSMBQFSAttributeInfo(const int xid,
++ struct cifsTconInfo *tcon,
++ const struct nls_table *nls_codepage);
++extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
++ const struct nls_table *nls_codepage);
++extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
++ const struct nls_table *nls_codepage);
++
++extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon,
++ char *fileName, FILE_BASIC_INFO * data,
++ const struct nls_table *nls_codepage);
++extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
++ char *fileName, __u64 size,int setAllocationSizeFlag,
++ const struct nls_table *nls_codepage);
++extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
++ __u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag);
++extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
++ char *full_path, __u64 mode, __u64 uid,
++ __u64 gid, dev_t dev, const struct nls_table *nls_codepage);
++
++extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
++ const char *newName,
++ const struct nls_table *nls_codepage);
++extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
++ const char *name, const struct nls_table *nls_codepage);
++
++extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
++ const char *name,
++ const struct nls_table *nls_codepage);
++extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
++ const char *fromName, const char *toName,
++ const struct nls_table *nls_codepage);
++extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
++ int netfid, char * target_name, const struct nls_table *nls_codepage);
++extern int CIFSCreateHardLink(const int xid,
++ struct cifsTconInfo *tcon,
++ const char *fromName, const char *toName,
++ const struct nls_table *nls_codepage);
++extern int CIFSUnixCreateHardLink(const int xid,
++ struct cifsTconInfo *tcon,
++ const char *fromName, const char *toName,
++ const struct nls_table *nls_codepage);
++extern int CIFSUnixCreateSymLink(const int xid,
++ struct cifsTconInfo *tcon,
++ const char *fromName, const char *toName,
++ const struct nls_table *nls_codepage);
++extern int CIFSSMBUnixQuerySymLink(const int xid,
++ struct cifsTconInfo *tcon,
++ const unsigned char *searchName,
++ char *syminfo, const int buflen,
++ const struct nls_table *nls_codepage);
++extern int CIFSSMBQueryReparseLinkInfo(const int xid,
++ struct cifsTconInfo *tcon,
++ const unsigned char *searchName,
++ char *symlinkinfo, const int buflen, __u16 fid,
++ const struct nls_table *nls_codepage);
++
++extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
++ const char *fileName, const int disposition,
++ const int access_flags, const int omode,
++ __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
++ const struct nls_table *nls_codepage);
++extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
++ const int smb_file_id);
++
++extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
++ const int netfid, unsigned int count,
++ const __u64 lseek, unsigned int *nbytes, char **buf);
++extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
++ const int netfid, const unsigned int count,
++ const __u64 lseek, unsigned int *nbytes,
++ const char *buf, const int long_op);
++extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
++ const __u16 netfid, const __u64 len,
++ const __u64 offset, const __u32 numUnlock,
++ const __u32 numLock, const __u8 lockType,
++ const int waitFlag);
++
++extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
++extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
++
++extern struct cifsSesInfo *sesInfoAlloc(void);
++extern void sesInfoFree(struct cifsSesInfo *);
++extern struct cifsTconInfo *tconInfoAlloc(void);
++extern void tconInfoFree(struct cifsTconInfo *);
++
++extern int cifs_reconnect(struct TCP_Server_Info *server);
++
++extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *);
++extern int cifs_verify_signature(const struct smb_hdr *, const char * mac_key,
++ __u32 expected_sequence_number);
++extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
++extern void CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
++extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
++
++extern int CIFSBuildServerList(int xid, char *serverBufferList,
++ int recordlength, int *entries,
++ int *totalEntries, int *topoChangedFlag);
++extern int CIFSSMBQueryShares(int xid, struct cifsTconInfo *tcon,
++ struct shareInfo *shareList, int bufferLen,
++ int *entries, int *totalEntries);
++extern int CIFSSMBQueryAlias(int xid, struct cifsTconInfo *tcon,
++ struct aliasInfo *aliasList, int bufferLen,
++ int *entries, int *totalEntries);
++extern int CIFSSMBAliasInfo(int xid, struct cifsTconInfo *tcon,
++ char *aliasName, char *serverName,
++ char *shareName, char *comment);
++extern int CIFSSMBGetShareInfo(int xid, struct cifsTconInfo *tcon,
++ char *share, char *comment);
++extern int CIFSSMBGetUserPerms(int xid, struct cifsTconInfo *tcon,
++ char *userName, char *searchName, int *perms);
++extern int CIFSSMBSync(int xid, struct cifsTconInfo *tcon, int netfid, int pid);
++
++extern int CIFSSMBSeek(int xid,
++ struct cifsTconInfo *tcon,
++ int netfid,
++ int pid,
++ int whence, unsigned long offset, long long *newoffset);
++
++extern int CIFSSMBCopy(int xid,
++ struct cifsTconInfo *source_tcon,
++ const char *fromName,
++ const __u16 target_tid,
++ const char *toName, const int flags,
++ const struct nls_table *nls_codepage);
++extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
++ const int notify_subdirs,const __u16 netfid,__u32 filter,
++ const struct nls_table *nls_codepage);
++extern int CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
++ const unsigned char *searchName,
++ char * EAData, size_t size,
++ const struct nls_table *nls_codepage);
++#endif /* _CIFSPROTO_H */
+diff -urN linux-2.4.29.old/fs/cifs/cifssmb.c linux-2.4.29/fs/cifs/cifssmb.c
+--- linux-2.4.29.old/fs/cifs/cifssmb.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/cifssmb.c 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,3016 @@
++/*
++ * fs/cifs/cifssmb.c
++ *
++ * Copyright (C) International Business Machines Corp., 2002,2003
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * Contains the routines for constructing the SMB PDUs themselves
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++ /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
++ /* These are mostly routines that operate on a pathname, or on a tree id */
++ /* (mounted volume), but there are eight handle based routines which must be */
++ /* treated slightly different for reconnection purposes since we never want */
++ /* to reuse a stale file handle and the caller knows the file handle */
++
++#include <linux/fs.h>
++#include <linux/kernel.h>
++#include <linux/vfs.h>
++#include <asm/uaccess.h>
++#include "cifspdu.h"
++#include "cifsglob.h"
++#include "cifsproto.h"
++#include "cifs_unicode.h"
++#include "cifs_debug.h"
++
++#ifdef CONFIG_CIFS_POSIX
++static struct {
++ int index;
++ char *name;
++} protocols[] = {
++ {CIFS_PROT, "\2NT LM 0.12"},
++ {CIFS_PROT, "\2POSIX 2"},
++ {BAD_PROT, "\2"}
++};
++#else
++static struct {
++ int index;
++ char *name;
++} protocols[] = {
++ {CIFS_PROT, "\2NT LM 0.12"},
++ {BAD_PROT, "\2"}
++};
++#endif
++
++
++/* Mark as invalid, all open files on tree connections since they
++ were closed when session to server was lost */
++static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
++{
++ struct cifsFileInfo *open_file = NULL;
++ struct list_head * tmp;
++ struct list_head * tmp1;
++
++/* list all files open on tree connection and mark them invalid */
++ write_lock(&GlobalSMBSeslock);
++ list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
++ open_file = list_entry(tmp,struct cifsFileInfo, tlist);
++ if(open_file) {
++ open_file->invalidHandle = TRUE;
++ }
++ }
++ write_unlock(&GlobalSMBSeslock);
++ /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
++}
++
++static int
++smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
++ void **request_buf /* returned */ ,
++ void **response_buf /* returned */ )
++{
++ int rc = 0;
++ int timeout = 10 * HZ;
++
++ /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
++ check for tcp and smb session status done differently
++ for those three - in the calling routine */
++ if(tcon) {
++ if((tcon->ses) && (tcon->ses->server)){
++ struct nls_table *nls_codepage;
++ /* Give Demultiplex thread up to 10 seconds to
++ reconnect, should be greater than cifs socket
++ timeout which is 7 seconds */
++ while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
++ while ((tcon->ses->server->tcpStatus != CifsGood) && (timeout > 0)){
++ timeout = interruptible_sleep_on_timeout(&tcon->ses->server->response_q,timeout);
++ }
++ if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
++ /* on "soft" mounts we wait once */
++ if((tcon->retry == FALSE) ||
++ (tcon->ses->status == CifsExiting)) {
++ cFYI(1,("gave up waiting on reconnect in smb_init"));
++ return -EHOSTDOWN;
++ } /* else "hard" mount - keep retrying until
++ process is killed or server comes back up */
++ } else /* TCP session is reestablished now */
++ break;
++
++ }
++
++ nls_codepage = load_nls_default();
++ /* need to prevent multiple threads trying to
++ simultaneously reconnect the same SMB session */
++ down(&tcon->ses->sesSem);
++ if(tcon->ses->status == CifsNeedReconnect)
++ rc = cifs_setup_session(0, tcon->ses, nls_codepage);
++ if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
++ mark_open_files_invalid(tcon);
++ rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
++ nls_codepage);
++ up(&tcon->ses->sesSem);
++ if(rc == 0)
++ atomic_inc(&tconInfoReconnectCount);
++
++ cFYI(1, ("reconnect tcon rc = %d", rc));
++ /* Removed call to reopen open files here -
++ it is safer (and faster) to reopen files
++ one at a time as needed in read and write */
++
++ /* Check if handle based operation so we
++ know whether we can continue or not without
++ returning to caller to reset file handle */
++ switch(smb_command) {
++ case SMB_COM_READ_ANDX:
++ case SMB_COM_WRITE_ANDX:
++ case SMB_COM_CLOSE:
++ case SMB_COM_FIND_CLOSE2:
++ case SMB_COM_LOCKING_ANDX: {
++ unload_nls(nls_codepage);
++ return -EAGAIN;
++ }
++ }
++ } else {
++ up(&tcon->ses->sesSem);
++ }
++ unload_nls(nls_codepage);
++
++ } else {
++ return -EIO;
++ }
++ }
++ if(rc)
++ return rc;
++
++ *request_buf = cifs_buf_get();
++ if (*request_buf == 0) {
++ /* BB should we add a retry in here if not a writepage? */
++ return -ENOMEM;
++ }
++ /* Although the original thought was we needed the response buf for */
++ /* potential retries of smb operations it turns out we can determine */
++ /* from the mid flags when the request buffer can be resent without */
++ /* having to use a second distinct buffer for the response */
++ *response_buf = *request_buf;
++
++ header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
++ wct /*wct */ );
++
++#ifdef CONFIG_CIFS_STATS
++ if(tcon != NULL) {
++ atomic_inc(&tcon->num_smbs_sent);
++ }
++#endif
++ return rc;
++}
++
++int
++CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
++{
++ NEGOTIATE_REQ *pSMB;
++ NEGOTIATE_RSP *pSMBr;
++ int rc = 0;
++ int bytes_returned;
++ struct TCP_Server_Info * server;
++
++ if(ses->server)
++ server = ses->server;
++ else {
++ rc = -EIO;
++ return rc;
++ }
++ rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
++ (void **) &pSMB, (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
++ if (extended_security)
++ pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
++
++ pSMB->ByteCount = strlen(protocols[0].name) + 1;
++ strncpy(pSMB->DialectsArray, protocols[0].name, 30);
++ /* null guaranteed to be at end of source and target buffers anyway */
++
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc == 0) {
++ server->secMode = pSMBr->SecurityMode;
++ server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
++ /* one byte - no need to convert this or EncryptionKeyLen from le,*/
++ server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
++ /* probably no need to store and check maxvcs */
++ server->maxBuf =
++ min(le32_to_cpu(pSMBr->MaxBufferSize),
++ (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
++ server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
++ cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
++ GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
++ server->capabilities = le32_to_cpu(pSMBr->Capabilities);
++ server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
++ /* BB with UTC do we ever need to be using srvr timezone? */
++ if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
++ memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
++ CIFS_CRYPTO_KEY_SIZE);
++ } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
++ && (pSMBr->EncryptionKeyLength == 0)) {
++ /* decode security blob */
++ } else
++ rc = -EIO;
++
++ /* BB might be helpful to save off the domain of server here */
++
++ if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) {
++ if (pSMBr->ByteCount < 16)
++ rc = -EIO;
++ else if (pSMBr->ByteCount == 16) {
++ server->secType = RawNTLMSSP;
++ if (server->socketUseCount.counter > 1) {
++ if (memcmp
++ (server->server_GUID,
++ pSMBr->u.extended_response.
++ GUID, 16) != 0) {
++ cFYI(1,
++ ("UID of server does not match previous connection to same ip address"));
++ memcpy(server->
++ server_GUID,
++ pSMBr->u.
++ extended_response.
++ GUID, 16);
++ }
++ } else
++ memcpy(server->server_GUID,
++ pSMBr->u.extended_response.
++ GUID, 16);
++ } else {
++ rc = decode_negTokenInit(pSMBr->u.
++ extended_response.
++ SecurityBlob,
++ pSMBr->ByteCount -
++ 16, &server->secType);
++ }
++ } else
++ server->capabilities &= ~CAP_EXTENDED_SECURITY;
++ if(sign_CIFS_PDUs == FALSE) {
++ if(server->secMode & SECMODE_SIGN_REQUIRED)
++ cERROR(1,
++ ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
++ server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
++ } else if(sign_CIFS_PDUs == 1) {
++ if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
++ server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
++ }
++
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++ return rc;
++}
++
++int
++CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
++{
++ struct smb_hdr *smb_buffer;
++ struct smb_hdr *smb_buffer_response;
++ int rc = 0;
++ int length;
++
++ cFYI(1, ("In tree disconnect"));
++ /*
++ * If last user of the connection and
++ * connection alive - disconnect it
++ * If this is the last connection on the server session disconnect it
++ * (and inside session disconnect we should check if tcp socket needs
++ * to be freed and kernel thread woken up).
++ */
++ if (tcon)
++ down(&tcon->tconSem);
++ else
++ return -EIO;
++
++ atomic_dec(&tcon->useCount);
++ if (atomic_read(&tcon->useCount) > 0) {
++ up(&tcon->tconSem);
++ return -EBUSY;
++ }
++
++ /* No need to return error on this operation if tid invalidated and
++ closed on server already e.g. due to tcp session crashing */
++ if(tcon->tidStatus == CifsNeedReconnect) {
++ up(&tcon->tconSem);
++ return 0;
++ }
++
++ if((tcon->ses == 0) || (tcon->ses->server == 0)) {
++ up(&tcon->tconSem);
++ return -EIO;
++ }
++
++ rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
++ (void **) &smb_buffer, (void **) &smb_buffer_response);
++ if (rc) {
++ up(&tcon->tconSem);
++ return rc;
++ }
++ rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
++ &length, 0);
++ if (rc)
++ cFYI(1, (" Tree disconnect failed %d", rc));
++
++ if (smb_buffer)
++ cifs_buf_release(smb_buffer);
++ up(&tcon->tconSem);
++
++ /* No need to return error on this operation if tid invalidated and
++ closed on server already e.g. due to tcp session crashing */
++ if (rc == -EAGAIN)
++ rc = 0;
++
++ return rc;
++}
++
++int
++CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
++{
++ struct smb_hdr *smb_buffer_response;
++ LOGOFF_ANDX_REQ *pSMB;
++ int rc = 0;
++ int length;
++
++ cFYI(1, ("In SMBLogoff for session disconnect"));
++ if (ses)
++ down(&ses->sesSem);
++ else
++ return -EIO;
++
++ atomic_dec(&ses->inUse);
++ if (atomic_read(&ses->inUse) > 0) {
++ up(&ses->sesSem);
++ return -EBUSY;
++ }
++
++ rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL /* no tcon anymore */,
++ (void **) &pSMB, (void **) &smb_buffer_response);
++
++ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
++ pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
++
++ if (rc) {
++ up(&ses->sesSem);
++ return rc;
++ }
++
++ pSMB->hdr.Uid = ses->Suid;
++
++ pSMB->AndXCommand = 0xFF;
++ rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
++ smb_buffer_response, &length, 0);
++ if (ses->server) {
++ atomic_dec(&ses->server->socketUseCount);
++ if (atomic_read(&ses->server->socketUseCount) == 0) {
++ spin_lock(&GlobalMid_Lock);
++ ses->server->tcpStatus = CifsExiting;
++ spin_unlock(&GlobalMid_Lock);
++ rc = -ESHUTDOWN;
++ }
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++ up(&ses->sesSem);
++
++ /* if session dead then we do not need to do ulogoff,
++ since server closed smb session, no sense reporting
++ error */
++ if (rc == -EAGAIN)
++ rc = 0;
++ return rc;
++}
++
++int
++CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
++ const char *fileName, const struct nls_table *nls_codepage)
++{
++ DELETE_FILE_REQ *pSMB = NULL;
++ DELETE_FILE_RSP *pSMBr = NULL;
++ int rc = 0;
++ int bytes_returned;
++ int name_len;
++
++DelFileRetry:
++ rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len =
++ cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(fileName, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->fileName, fileName, name_len);
++ }
++ pSMB->SearchAttributes =
++ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
++ pSMB->ByteCount = name_len + 1;
++ pSMB->BufferFormat = 0x04;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("Error in RMFile = %d", rc));
++ }
++#ifdef CONFIG_CIFS_STATS
++ else {
++ atomic_inc(&tcon->num_deletes);
++ }
++#endif
++
++ if (pSMB)
++ cifs_buf_release(pSMB);
++ if (rc == -EAGAIN)
++ goto DelFileRetry;
++
++ return rc;
++}
++
++int
++CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
++ const char *dirName, const struct nls_table *nls_codepage)
++{
++ DELETE_DIRECTORY_REQ *pSMB = NULL;
++ DELETE_DIRECTORY_RSP *pSMBr = NULL;
++ int rc = 0;
++ int bytes_returned;
++ int name_len;
++
++ cFYI(1, ("In CIFSSMBRmDir"));
++RmDirRetry:
++ rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(dirName, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->DirName, dirName, name_len);
++ }
++
++ pSMB->ByteCount = name_len + 1;
++ pSMB->BufferFormat = 0x04;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("Error in RMDir = %d", rc));
++ }
++#ifdef CONFIG_CIFS_STATS
++ else {
++ atomic_inc(&tcon->num_rmdirs);
++ }
++#endif
++
++ if (pSMB)
++ cifs_buf_release(pSMB);
++ if (rc == -EAGAIN)
++ goto RmDirRetry;
++ return rc;
++}
++
++int
++CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
++ const char *name, const struct nls_table *nls_codepage)
++{
++ int rc = 0;
++ CREATE_DIRECTORY_REQ *pSMB = NULL;
++ CREATE_DIRECTORY_RSP *pSMBr = NULL;
++ int bytes_returned;
++ int name_len;
++
++ cFYI(1, ("In CIFSSMBMkDir"));
++MkDirRetry:
++ rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(name, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->DirName, name, name_len);
++ }
++
++ pSMB->ByteCount = name_len + 1 /* for buf format */ ;
++ pSMB->BufferFormat = 0x04;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("Error in Mkdir = %d", rc));
++ }
++#ifdef CONFIG_CIFS_STATS
++ else {
++ atomic_inc(&tcon->num_mkdirs);
++ }
++#endif
++ if (pSMB)
++ cifs_buf_release(pSMB);
++ if (rc == -EAGAIN)
++ goto MkDirRetry;
++ return rc;
++}
++
++int
++CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
++ const char *fileName, const int openDisposition,
++ const int access_flags, const int create_options, __u16 * netfid,
++ int *pOplock, FILE_ALL_INFO * pfile_info,
++ const struct nls_table *nls_codepage)
++{
++ int rc = -EACCES;
++ OPEN_REQ *pSMB = NULL;
++ OPEN_RSP *pSMBr = NULL;
++ int bytes_returned;
++ int name_len;
++
++openRetry:
++ rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ pSMB->AndXCommand = 0xFF; /* none */
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ pSMB->ByteCount = 1; /* account for one byte pad to word boundary */
++ name_len =
++ cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
++ fileName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ pSMB->NameLength = cpu_to_le16(name_len);
++ } else { /* BB improve the check for buffer overruns BB */
++ pSMB->ByteCount = 0; /* no pad */
++ name_len = strnlen(fileName, 530);
++ name_len++; /* trailing null */
++ pSMB->NameLength = cpu_to_le16(name_len);
++ strncpy(pSMB->fileName, fileName, name_len);
++ }
++ if (*pOplock & REQ_OPLOCK)
++ pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
++ else if (*pOplock & REQ_BATCHOPLOCK) {
++ pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
++ }
++ pSMB->DesiredAccess = cpu_to_le32(access_flags);
++ pSMB->AllocationSize = 0;
++ pSMB->FileAttributes = ATTR_NORMAL;
++ /* XP does not handle ATTR_POSIX_SEMANTICS */
++ /* but it helps speed up case sensitive checks for other
++ servers such as Samba */
++ if (tcon->ses->capabilities & CAP_UNIX)
++ pSMB->FileAttributes |= ATTR_POSIX_SEMANTICS;
++
++ /* if ((omode & S_IWUGO) == 0)
++ pSMB->FileAttributes |= ATTR_READONLY;*/
++ /* Above line causes problems due to vfs splitting create into two
++ pieces - need to set mode after file created not while it is
++ being created */
++ pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
++ pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
++ pSMB->CreateDisposition = cpu_to_le32(openDisposition);
++ pSMB->CreateOptions = cpu_to_le32(create_options);
++ pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
++ pSMB->SecurityFlags =
++ cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
++
++ pSMB->ByteCount += name_len;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++ /* long_op set to 1 to allow for oplock break timeouts */
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 1);
++ if (rc) {
++ cFYI(1, ("Error in Open = %d", rc));
++ } else {
++ *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
++ *netfid = pSMBr->Fid; /* cifs fid stays in le */
++ /* Let caller know file was created so we can set the mode. */
++ /* Do we care about the CreateAction in any other cases? */
++ if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
++ *pOplock |= CIFS_CREATE_ACTION;
++ if(pfile_info) {
++ memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
++ 36 /* CreationTime to Attributes */);
++ /* the file_info buf is endian converted by caller */
++ pfile_info->AllocationSize = pSMBr->AllocationSize;
++ pfile_info->EndOfFile = pSMBr->EndOfFile;
++ pfile_info->NumberOfLinks = cpu_to_le32(1);
++ }
++
++#ifdef CONFIG_CIFS_STATS
++ atomic_inc(&tcon->num_opens);
++#endif
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++ if (rc == -EAGAIN)
++ goto openRetry;
++ return rc;
++}
++
++/* If no buffer passed in, then caller wants to do the copy
++ as in the case of readpages so the SMB buffer must be
++ freed by the caller */
++
++int
++CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
++ const int netfid, const unsigned int count,
++ const __u64 lseek, unsigned int *nbytes, char **buf)
++{
++ int rc = -EACCES;
++ READ_REQ *pSMB = NULL;
++ READ_RSP *pSMBr = NULL;
++ char *pReadData = NULL;
++ int bytes_returned;
++
++ *nbytes = 0;
++ rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ /* tcon and ses pointer are checked in smb_init */
++ if (tcon->ses->server == NULL)
++ return -ECONNABORTED;
++
++ pSMB->AndXCommand = 0xFF; /* none */
++ pSMB->Fid = netfid;
++ pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
++ pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
++ pSMB->Remaining = 0;
++ pSMB->MaxCount = cpu_to_le16(count);
++ pSMB->MaxCountHigh = 0;
++ pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cERROR(1, ("Send error in read = %d", rc));
++ } else {
++ pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
++ *nbytes = pSMBr->DataLength;
++ /*check that DataLength would not go beyond end of SMB */
++ if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE)
++ || (pSMBr->DataLength > count)) {
++ cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
++ rc = -EIO;
++ *nbytes = 0;
++ } else {
++ pReadData =
++ (char *) (&pSMBr->hdr.Protocol) +
++ le16_to_cpu(pSMBr->DataOffset);
++/* if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
++ cERROR(1,("Faulting on read rc = %d",rc));
++ rc = -EFAULT;
++ }*/ /* can not use copy_to_user when using page cache*/
++ if(*buf)
++ memcpy(*buf,pReadData,pSMBr->DataLength);
++ }
++ }
++ if (pSMB) {
++ if(*buf)
++ cifs_buf_release(pSMB);
++ else
++ *buf = (char *)pSMB;
++ }
++
++ /* Note: On -EAGAIN error only caller can retry on handle based calls
++ since file handle passed in no longer valid */
++ return rc;
++}
++
++int
++CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
++ const int netfid, const unsigned int count,
++ const __u64 offset, unsigned int *nbytes, const char *buf,
++ const int long_op)
++{
++ int rc = -EACCES;
++ WRITE_REQ *pSMB = NULL;
++ WRITE_RSP *pSMBr = NULL;
++ int bytes_returned;
++
++ rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++ /* tcon and ses pointer are checked in smb_init */
++ if (tcon->ses->server == NULL)
++ return -ECONNABORTED;
++
++ pSMB->AndXCommand = 0xFF; /* none */
++ pSMB->Fid = netfid;
++ pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
++ pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
++ pSMB->Remaining = 0;
++ if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
++ pSMB->DataLengthLow =
++ (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
++ else
++ pSMB->DataLengthLow = count;
++ pSMB->DataLengthHigh = 0;
++ pSMB->DataOffset =
++ cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
++
++ memcpy(pSMB->Data,buf,pSMB->DataLengthLow);
++
++ pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
++ pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
++ if (rc) {
++ cFYI(1, ("Send error in write = %d", rc));
++ *nbytes = 0;
++ } else
++ *nbytes = le16_to_cpu(pSMBr->Count);
++
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ /* Note: On -EAGAIN error only caller can retry on handle based calls
++ since file handle passed in no longer valid */
++
++ return rc;
++}
++
++int
++CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
++ const __u16 smb_file_id, const __u64 len,
++ const __u64 offset, const __u32 numUnlock,
++ const __u32 numLock, const __u8 lockType, const int waitFlag)
++{
++ int rc = 0;
++ LOCK_REQ *pSMB = NULL;
++ LOCK_RSP *pSMBr = NULL;
++ int bytes_returned;
++ int timeout = 0;
++ __u64 temp;
++
++ cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
++ rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
++ timeout = -1; /* no response expected */
++ pSMB->Timeout = 0;
++ } else if (waitFlag == TRUE) {
++ timeout = 3; /* blocking operation, no timeout */
++ pSMB->Timeout = -1; /* blocking - do not time out */
++ } else {
++ pSMB->Timeout = 0;
++ }
++
++ pSMB->NumberOfLocks = cpu_to_le32(numLock);
++ pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
++ pSMB->LockType = lockType;
++ pSMB->AndXCommand = 0xFF; /* none */
++ pSMB->Fid = smb_file_id; /* netfid stays le */
++
++ if(numLock != 0) {
++ pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
++ /* BB where to store pid high? */
++ temp = cpu_to_le64(len);
++ pSMB->Locks[0].LengthLow = (__u32)(temp & 0xFFFFFFFF);
++ pSMB->Locks[0].LengthHigh = (__u32)(temp>>32);
++ temp = cpu_to_le64(offset);
++ pSMB->Locks[0].OffsetLow = (__u32)(temp & 0xFFFFFFFF);
++ pSMB->Locks[0].OffsetHigh = (__u32)(temp>>32);
++ pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
++ } else {
++ /* oplock break */
++ pSMB->ByteCount = 0;
++ }
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
++
++ if (rc) {
++ cFYI(1, ("Send error in Lock = %d", rc));
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ /* Note: On -EAGAIN error only caller can retry on handle based calls
++ since file handle passed in no longer valid */
++ return rc;
++}
++
++int
++CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
++{
++ int rc = 0;
++ CLOSE_REQ *pSMB = NULL;
++ CLOSE_RSP *pSMBr = NULL;
++ int bytes_returned;
++ cFYI(1, ("In CIFSSMBClose"));
++
++/* do not retry on dead session on close */
++ rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if(rc == -EAGAIN)
++ return 0;
++ if (rc)
++ return rc;
++
++ pSMB->FileID = (__u16) smb_file_id;
++ pSMB->LastWriteTime = 0;
++ pSMB->ByteCount = 0;
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ if(rc!=-EINTR) {
++ /* EINTR is expected when user ctl-c to kill app */
++ cERROR(1, ("Send error in Close = %d", rc));
++ }
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ /* Since session is dead, file will be closed on server already */
++ if(rc == -EAGAIN)
++ rc = 0;
++
++ return rc;
++}
++
++int
++CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
++ const char *fromName, const char *toName,
++ const struct nls_table *nls_codepage)
++{
++ int rc = 0;
++ RENAME_REQ *pSMB = NULL;
++ RENAME_RSP *pSMBr = NULL;
++ int bytes_returned;
++ int name_len, name_len2;
++
++ cFYI(1, ("In CIFSSMBRename"));
++renameRetry:
++ rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ pSMB->BufferFormat = 0x04;
++ pSMB->SearchAttributes =
++ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
++ ATTR_DIRECTORY);
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len =
++ cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ pSMB->OldFileName[name_len] = 0x04; /* pad */
++ /* protocol requires ASCII signature byte on Unicode string */
++ pSMB->OldFileName[name_len + 1] = 0x00;
++ name_len2 =
++ cifs_strtoUCS((wchar_t *) & pSMB->
++ OldFileName[name_len + 2], toName, 530,
++ nls_codepage);
++ name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
++ name_len2 *= 2; /* convert to bytes */
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(fromName, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->OldFileName, fromName, name_len);
++ name_len2 = strnlen(toName, 530);
++ name_len2++; /* trailing null */
++ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
++ strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
++ name_len2++; /* trailing null */
++ name_len2++; /* signature byte */
++ }
++
++ pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("Send error in rename = %d", rc));
++ }
++
++#ifdef CONFIG_CIFS_STATS
++ else {
++ atomic_inc(&tcon->num_renames);
++ }
++#endif
++
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ if (rc == -EAGAIN)
++ goto renameRetry;
++
++ return rc;
++}
++
++int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
++ int netfid, char * target_name, const struct nls_table * nls_codepage)
++{
++ struct smb_com_transaction2_sfi_req *pSMB = NULL;
++ struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
++ struct set_file_rename * rename_info;
++ char *data_offset;
++ char dummy_string[30];
++ int rc = 0;
++ int bytes_returned = 0;
++ int len_of_str;
++
++ cFYI(1, ("Rename to File by handle"));
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ pSMB->ParameterCount = 6;
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
++ Fid) - 4;
++ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
++
++ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
++ rename_info = (struct set_file_rename *) data_offset;
++ pSMB->MaxParameterCount = cpu_to_le16(2);
++ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
++ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount;
++ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
++ pSMB->TotalParameterCount = pSMB->ParameterCount;
++ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
++ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
++ /* construct random name ".cifs_tmp<inodenum><mid>" */
++ rename_info->overwrite = cpu_to_le32(1);
++ rename_info->root_fid = 0;
++ /* unicode only call */
++ if(target_name == NULL) {
++ sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
++ len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
++ } else {
++ len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
++ }
++ rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
++ pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
++ pSMB->ByteCount += pSMB->DataCount;
++ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
++ pSMB->TotalDataCount = pSMB->DataCount;
++ pSMB->Fid = netfid;
++ pSMB->InformationLevel =
++ cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
++ pSMB->Reserved4 = 0;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++ rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1,("Send error in Rename (by file handle) = %d", rc));
++ }
++#ifdef CONFIG_CIFS_STATS
++ else {
++ atomic_inc(&pTcon->num_t2renames);
++ }
++#endif
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ /* Note: On -EAGAIN error only caller can retry on handle based calls
++ since file handle passed in no longer valid */
++
++ return rc;
++}
++
++int
++CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
++ const __u16 target_tid, const char *toName, const int flags,
++ const struct nls_table *nls_codepage)
++{
++ int rc = 0;
++ COPY_REQ *pSMB = NULL;
++ COPY_RSP *pSMBr = NULL;
++ int bytes_returned;
++ int name_len, name_len2;
++
++ cFYI(1, ("In CIFSSMBCopy"));
++copyRetry:
++ rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ pSMB->BufferFormat = 0x04;
++ pSMB->Tid2 = target_tid;
++
++ if(flags & COPY_TREE)
++ pSMB->Flags |= COPY_TREE;
++ pSMB->Flags = cpu_to_le16(pSMB->Flags);
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName,
++ fromName,
++ 530 /* find define for this maxpathcomponent */,
++ nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ pSMB->OldFileName[name_len] = 0x04; /* pad */
++ /* protocol requires ASCII signature byte on Unicode string */
++ pSMB->OldFileName[name_len + 1] = 0x00;
++ name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
++ OldFileName[name_len + 2], toName, 530,
++ nls_codepage);
++ name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
++ name_len2 *= 2; /* convert to bytes */
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(fromName, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->OldFileName, fromName, name_len);
++ name_len2 = strnlen(toName, 530);
++ name_len2++; /* trailing null */
++ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
++ strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
++ name_len2++; /* trailing null */
++ name_len2++; /* signature byte */
++ }
++
++ pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("Send error in copy = %d with %d files copied",
++ rc, pSMBr->CopyCount));
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ if (rc == -EAGAIN)
++ goto copyRetry;
++
++ return rc;
++}
++
++int
++CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
++ const char *fromName, const char *toName,
++ const struct nls_table *nls_codepage)
++{
++ TRANSACTION2_SPI_REQ *pSMB = NULL;
++ TRANSACTION2_SPI_RSP *pSMBr = NULL;
++ char *data_offset;
++ int name_len;
++ int name_len_target;
++ int rc = 0;
++ int bytes_returned = 0;
++
++ cFYI(1, ("In Symlink Unix style"));
++createSymLinkRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len =
++ cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(fromName, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->FileName, fromName, name_len);
++ }
++ pSMB->ParameterCount = 6 + name_len;
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
++ InformationLevel) - 4;
++ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
++
++ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len_target =
++ cifs_strtoUCS((wchar_t *) data_offset, toName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len_target++; /* trailing null */
++ name_len_target *= 2;
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len_target = strnlen(toName, 530);
++ name_len_target++; /* trailing null */
++ strncpy(data_offset, toName, name_len_target);
++ }
++
++ pSMB->DataCount = name_len_target;
++ pSMB->MaxParameterCount = cpu_to_le16(2);
++ /* BB find exact max on data count below from sess */
++ pSMB->MaxDataCount = cpu_to_le16(1000);
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
++ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
++ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
++ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
++ pSMB->TotalDataCount = pSMB->DataCount;
++ pSMB->TotalParameterCount = pSMB->ParameterCount;
++ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
++ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
++ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
++ pSMB->Reserved4 = 0;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1,
++ ("Send error in SetPathInfo (create symlink) = %d",
++ rc));
++ }
++
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ if (rc == -EAGAIN)
++ goto createSymLinkRetry;
++
++ return rc;
++}
++
++int
++CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
++ const char *fromName, const char *toName,
++ const struct nls_table *nls_codepage)
++{
++ TRANSACTION2_SPI_REQ *pSMB = NULL;
++ TRANSACTION2_SPI_RSP *pSMBr = NULL;
++ char *data_offset;
++ int name_len;
++ int name_len_target;
++ int rc = 0;
++ int bytes_returned = 0;
++
++ cFYI(1, ("In Create Hard link Unix style"));
++createHardLinkRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(toName, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->FileName, toName, name_len);
++ }
++ pSMB->ParameterCount = 6 + name_len;
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
++ InformationLevel) - 4;
++ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
++
++ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len_target =
++ cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len_target++; /* trailing null */
++ name_len_target *= 2;
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len_target = strnlen(fromName, 530);
++ name_len_target++; /* trailing null */
++ strncpy(data_offset, fromName, name_len_target);
++ }
++
++ pSMB->DataCount = name_len_target;
++ pSMB->MaxParameterCount = cpu_to_le16(2);
++ /* BB find exact max on data count below from sess*/
++ pSMB->MaxDataCount = cpu_to_le16(1000);
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
++ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
++ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
++ pSMB->TotalParameterCount = pSMB->ParameterCount;
++ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
++ pSMB->TotalDataCount = pSMB->DataCount;
++ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
++ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
++ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
++ pSMB->Reserved4 = 0;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
++ }
++
++ if (pSMB)
++ cifs_buf_release(pSMB);
++ if (rc == -EAGAIN)
++ goto createHardLinkRetry;
++
++ return rc;
++}
++
++int
++CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
++ const char *fromName, const char *toName,
++ const struct nls_table *nls_codepage)
++{
++ int rc = 0;
++ NT_RENAME_REQ *pSMB = NULL;
++ RENAME_RSP *pSMBr = NULL;
++ int bytes_returned;
++ int name_len, name_len2;
++
++ cFYI(1, ("In CIFSCreateHardLink"));
++winCreateHardLinkRetry:
++
++ rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ pSMB->SearchAttributes =
++ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
++ ATTR_DIRECTORY);
++ pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
++ pSMB->ClusterCount = 0;
++
++ pSMB->BufferFormat = 0x04;
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len =
++ cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ pSMB->OldFileName[name_len] = 0; /* pad */
++ pSMB->OldFileName[name_len + 1] = 0x04;
++ name_len2 =
++ cifs_strtoUCS((wchar_t *) & pSMB->
++ OldFileName[name_len + 2], toName, 530,
++ nls_codepage);
++ name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
++ name_len2 *= 2; /* convert to bytes */
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(fromName, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->OldFileName, fromName, name_len);
++ name_len2 = strnlen(toName, 530);
++ name_len2++; /* trailing null */
++ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
++ strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
++ name_len2++; /* trailing null */
++ name_len2++; /* signature byte */
++ }
++
++ pSMB->ByteCount = 1 /* string type byte */ + name_len + name_len2;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++ if (rc == -EAGAIN)
++ goto winCreateHardLinkRetry;
++
++ return rc;
++}
++
++int
++CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
++ const unsigned char *searchName,
++ char *symlinkinfo, const int buflen,
++ const struct nls_table *nls_codepage)
++{
++/* SMB_QUERY_FILE_UNIX_LINK */
++ TRANSACTION2_QPI_REQ *pSMB = NULL;
++ TRANSACTION2_QPI_RSP *pSMBr = NULL;
++ int rc = 0;
++ int bytes_returned;
++ int name_len;
++
++ cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
++
++querySymLinkRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len =
++ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(searchName, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->FileName, searchName, name_len);
++ }
++
++ pSMB->TotalParameterCount =
++ 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
++ pSMB->TotalDataCount = 0;
++ pSMB->MaxParameterCount = cpu_to_le16(2);
++ /* BB find exact max data count below from sess structure BB */
++ pSMB->MaxDataCount = cpu_to_le16(4000);
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ParameterOffset = cpu_to_le16(offsetof(
++ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
++ pSMB->DataCount = 0;
++ pSMB->DataOffset = 0;
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
++ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
++ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
++ pSMB->ParameterCount = pSMB->TotalParameterCount;
++ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
++ pSMB->Reserved4 = 0;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
++ } else { /* decode response */
++ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
++ pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
++ if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
++ /* BB also check enough total bytes returned */
++ rc = -EIO; /* bad smb */
++ else {
++ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len = UniStrnlen((wchar_t *) ((char *)
++ &pSMBr->hdr.Protocol +pSMBr->DataOffset),
++ min_t(const int, buflen,pSMBr->DataCount) / 2);
++ cifs_strfromUCS_le(symlinkinfo,
++ (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
++ pSMBr->DataOffset),
++ name_len, nls_codepage);
++ } else {
++ strncpy(symlinkinfo,
++ (char *) &pSMBr->hdr.Protocol +
++ pSMBr->DataOffset,
++ min_t(const int, buflen, pSMBr->DataCount));
++ }
++ symlinkinfo[buflen] = 0;
++ /* just in case so calling code does not go off the end of buffer */
++ }
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++ if (rc == -EAGAIN)
++ goto querySymLinkRetry;
++ return rc;
++}
++
++
++
++int
++CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
++ const unsigned char *searchName,
++ char *symlinkinfo, const int buflen,__u16 fid,
++ const struct nls_table *nls_codepage)
++{
++ int rc = 0;
++ int bytes_returned;
++ int name_len;
++ struct smb_com_transaction_ioctl_req * pSMB;
++ struct smb_com_transaction_ioctl_rsp * pSMBr;
++
++ cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
++ rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ pSMB->TotalParameterCount = 0 ;
++ pSMB->TotalDataCount = 0;
++ pSMB->MaxParameterCount = cpu_to_le32(2);
++ /* BB find exact data count max from sess structure BB */
++ pSMB->MaxDataCount = cpu_to_le32(4000);
++ pSMB->MaxSetupCount = 4;
++ pSMB->Reserved = 0;
++ pSMB->ParameterOffset = 0;
++ pSMB->DataCount = 0;
++ pSMB->DataOffset = 0;
++ pSMB->SetupCount = 4;
++ pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
++ pSMB->ParameterCount = pSMB->TotalParameterCount;
++ pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
++ pSMB->IsFsctl = 1; /* FSCTL */
++ pSMB->IsRootFlag = 0;
++ pSMB->Fid = fid; /* file handle always le */
++ pSMB->ByteCount = 0;
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
++ } else { /* decode response */
++ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
++ pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
++ if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
++ /* BB also check enough total bytes returned */
++ rc = -EIO; /* bad smb */
++ else {
++ if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
++ /* could also validate reparse tag && better check name length */
++ struct reparse_data * reparse_buf = (struct reparse_data *)
++ ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
++ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len = UniStrnlen((wchar_t *)
++ (reparse_buf->LinkNamesBuf +
++ reparse_buf->TargetNameOffset),
++ min(buflen/2, reparse_buf->TargetNameLen / 2));
++ cifs_strfromUCS_le(symlinkinfo,
++ (wchar_t *) (reparse_buf->LinkNamesBuf +
++ reparse_buf->TargetNameOffset),
++ name_len, nls_codepage);
++ } else { /* ASCII names */
++ strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
++ reparse_buf->TargetNameOffset,
++ min_t(const int, buflen, reparse_buf->TargetNameLen));
++ }
++ } else {
++ rc = -EIO;
++ cFYI(1,("Invalid return data count on get reparse info ioctl"));
++ }
++ symlinkinfo[buflen] = 0; /* just in case so the caller
++ does not go off the end of the buffer */
++ cFYI(1,("readlink result - %s ",symlinkinfo));
++ }
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ /* Note: On -EAGAIN error only caller can retry on handle based calls
++ since file handle passed in no longer valid */
++
++ return rc;
++}
++
++int
++CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
++ const unsigned char *searchName,
++ FILE_ALL_INFO * pFindData,
++ const struct nls_table *nls_codepage)
++{
++/* level 263 SMB_QUERY_FILE_ALL_INFO */
++ TRANSACTION2_QPI_REQ *pSMB = NULL;
++ TRANSACTION2_QPI_RSP *pSMBr = NULL;
++ int rc = 0;
++ int bytes_returned;
++ int name_len;
++
++ cFYI(1, ("In QPathInfo path %s", searchName));
++QPathInfoRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len =
++ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(searchName, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->FileName, searchName, name_len);
++ }
++
++ pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
++ name_len /* includes null */ ;
++ pSMB->TotalDataCount = 0;
++ pSMB->MaxParameterCount = cpu_to_le16(2);
++ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ParameterOffset = cpu_to_le16(offsetof(
++ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
++ pSMB->DataCount = 0;
++ pSMB->DataOffset = 0;
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
++ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
++ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
++ pSMB->ParameterCount = pSMB->TotalParameterCount;
++ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
++ pSMB->Reserved4 = 0;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("Send error in QPathInfo = %d", rc));
++ } else { /* decode response */
++ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
++ /* BB also check enough total bytes returned */
++ /* BB we need to improve the validity checking
++ of these trans2 responses */
++ if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
++ rc = -EIO; /* bad smb */
++ else if (pFindData){
++ memcpy((char *) pFindData,
++ (char *) &pSMBr->hdr.Protocol +
++ pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
++ } else
++ rc = -ENOMEM;
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++ if (rc == -EAGAIN)
++ goto QPathInfoRetry;
++
++ return rc;
++}
++
++int
++CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
++ const unsigned char *searchName,
++ FILE_UNIX_BASIC_INFO * pFindData,
++ const struct nls_table *nls_codepage)
++{
++/* SMB_QUERY_FILE_UNIX_BASIC */
++ TRANSACTION2_QPI_REQ *pSMB = NULL;
++ TRANSACTION2_QPI_RSP *pSMBr = NULL;
++ int rc = 0;
++ int bytes_returned = 0;
++ int name_len;
++
++ cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
++UnixQPathInfoRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len =
++ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(searchName, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->FileName, searchName, name_len);
++ }
++
++ pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
++ name_len /* includes null */ ;
++ pSMB->TotalDataCount = 0;
++ pSMB->MaxParameterCount = cpu_to_le16(2);
++ /* BB find exact max SMB PDU from sess structure BB */
++ pSMB->MaxDataCount = cpu_to_le16(4000);
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ParameterOffset = cpu_to_le16(offsetof(
++ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
++ pSMB->DataCount = 0;
++ pSMB->DataOffset = 0;
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
++ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
++ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
++ pSMB->ParameterCount = pSMB->TotalParameterCount;
++ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
++ pSMB->Reserved4 = 0;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("Send error in QPathInfo = %d", rc));
++ } else { /* decode response */
++ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
++ /* BB also check if enough total bytes returned */
++ if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) ||
++ (pSMBr->DataOffset > 512) ||
++ (pSMBr->DataOffset < sizeof(struct smb_hdr))) {
++ cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
++ (int)pSMBr->DataOffset,bytes_returned));
++ rc = -EIO; /* bad smb */
++ } else {
++ memcpy((char *) pFindData,
++ (char *) &pSMBr->hdr.Protocol +
++ pSMBr->DataOffset,
++ sizeof (FILE_UNIX_BASIC_INFO));
++ }
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++ if (rc == -EAGAIN)
++ goto UnixQPathInfoRetry;
++
++ return rc;
++}
++
++int
++CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
++ const char *searchName, FILE_ALL_INFO * findData,
++ const struct nls_table *nls_codepage)
++{
++/* level 257 SMB_ */
++ TRANSACTION2_FFIRST_REQ *pSMB = NULL;
++ TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
++ int rc = 0;
++ int bytes_returned;
++ int name_len;
++
++ cFYI(1, ("In FindUnique"));
++findUniqueRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len =
++ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(searchName, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->FileName, searchName, name_len);
++ }
++
++ pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
++ pSMB->TotalDataCount = 0; /* no EAs */
++ pSMB->MaxParameterCount = cpu_to_le16(2);
++ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ParameterOffset = cpu_to_le16(
++ offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
++ pSMB->DataCount = 0;
++ pSMB->DataOffset = 0;
++ pSMB->SetupCount = 1; /* one byte, no need to le convert */
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
++ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
++ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount);
++ pSMB->ParameterCount = pSMB->TotalParameterCount;
++ pSMB->SearchAttributes =
++ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
++ ATTR_DIRECTORY);
++ pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
++ pSMB->SearchFlags = cpu_to_le16(1);
++ pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
++ pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++
++ if (rc) {
++ cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
++ } else { /* decode response */
++
++ /* BB fill in */
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++ if (rc == -EAGAIN)
++ goto findUniqueRetry;
++
++ return rc;
++}
++
++int
++CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
++ const char *searchName, FILE_DIRECTORY_INFO * findData,
++ T2_FFIRST_RSP_PARMS * findParms,
++ const struct nls_table *nls_codepage, int *pUnicodeFlag,
++ int *pUnixFlag)
++{
++/* level 257 SMB_ */
++ TRANSACTION2_FFIRST_REQ *pSMB = NULL;
++ TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
++ char *response_data;
++ int rc = 0;
++ int bytes_returned;
++ int name_len;
++
++ cFYI(1, ("In FindFirst"));
++findFirstRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len =
++ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(searchName, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->FileName, searchName, name_len);
++ }
++
++ pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
++ pSMB->TotalDataCount = 0; /* no EAs */
++ pSMB->MaxParameterCount = cpu_to_le16(10);
++ pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
++ MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
++ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
++ pSMB->ParameterCount = pSMB->TotalParameterCount;
++ pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
++ smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
++ pSMB->DataCount = 0;
++ pSMB->DataOffset = 0;
++ pSMB->SetupCount = 1; /* one byte no need to make endian neutral */
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
++ pSMB->SearchAttributes =
++ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
++ ATTR_DIRECTORY);
++ pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */
++ pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
++
++ /* test for Unix extensions */
++ if (tcon->ses->capabilities & CAP_UNIX) {
++ pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
++ *pUnixFlag = TRUE;
++ } else {
++ pSMB->InformationLevel =
++ cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
++ *pUnixFlag = FALSE;
++ }
++ pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++
++ if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
++ cFYI(1, ("Error in FindFirst = %d", rc));
++ } else { /* decode response */
++ /* BB add safety checks for these memcpys */
++ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
++ *pUnicodeFlag = TRUE;
++ else
++ *pUnicodeFlag = FALSE;
++ memcpy(findParms,
++ (char *) &pSMBr->hdr.Protocol +
++ le16_to_cpu(pSMBr->ParameterOffset),
++ sizeof (T2_FFIRST_RSP_PARMS));
++ /* search handle can stay LE and EAoffset not needed so not converted */
++ findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
++ findParms->LastNameOffset =
++ le16_to_cpu(findParms->LastNameOffset);
++ findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
++ response_data =
++ (char *) &pSMBr->hdr.Protocol +
++ le16_to_cpu(pSMBr->DataOffset);
++ memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ if (rc == -EAGAIN)
++ goto findFirstRetry;
++
++ return rc;
++}
++
++int
++CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
++ FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
++ const __u16 searchHandle, char * resume_file_name, int name_len,
++ __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
++{
++/* level 257 SMB_ */
++ TRANSACTION2_FNEXT_REQ *pSMB = NULL;
++ TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
++ char *response_data;
++ int rc = 0;
++ int bytes_returned;
++
++ cFYI(1, ("In FindNext"));
++
++ if(resume_file_name == NULL) {
++ return -EIO;
++ }
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ pSMB->TotalParameterCount = 14; /* includes 2 bytes of null string, converted to LE below */
++ pSMB->TotalDataCount = 0; /* no EAs */
++ pSMB->MaxParameterCount = cpu_to_le16(8);
++ pSMB->MaxDataCount =
++ cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ParameterOffset = cpu_to_le16(offsetof(
++ struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
++ pSMB->DataCount = 0;
++ pSMB->DataOffset = 0;
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
++ pSMB->SearchHandle = searchHandle; /* always kept as le */
++ findParms->SearchCount = 0; /* set to zero in case of error */
++ pSMB->SearchCount =
++ cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));
++ /* test for Unix extensions */
++ if (tcon->ses->capabilities & CAP_UNIX) {
++ pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
++ *pUnixFlag = TRUE;
++ } else {
++ pSMB->InformationLevel =
++ cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
++ *pUnixFlag = FALSE;
++ }
++ pSMB->ResumeKey = resume_key;
++ pSMB->SearchFlags =
++ cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
++ /* BB add check to make sure we do not cross end of smb */
++ if(name_len < CIFS_MAX_MSGSIZE) {
++ memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
++ pSMB->ByteCount += name_len;
++ }
++ pSMB->TotalParameterCount += name_len;
++ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
++ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
++ pSMB->ParameterCount = pSMB->TotalParameterCount;
++ /* BB improve error handling here */
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++
++ if (rc) {
++ if (rc == -EBADF)
++ rc = 0; /* search probably was closed at end of search above */
++ else
++ cFYI(1, ("FindNext returned = %d", rc));
++ } else { /* decode response */
++ /* BB add safety checks for these memcpys */
++ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
++ *pUnicodeFlag = TRUE;
++ else
++ *pUnicodeFlag = FALSE;
++ memcpy(findParms,
++ (char *) &pSMBr->hdr.Protocol +
++ le16_to_cpu(pSMBr->ParameterOffset),
++ sizeof (T2_FNEXT_RSP_PARMS));
++ findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
++ findParms->LastNameOffset =
++ le16_to_cpu(findParms->LastNameOffset);
++ findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
++ response_data =
++ (char *) &pSMBr->hdr.Protocol +
++ le16_to_cpu(pSMBr->DataOffset);
++ memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ /* Note: On -EAGAIN error only caller can retry on handle based calls
++ since file handle passed in no longer valid */
++
++ return rc;
++}
++
++int
++CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
++{
++ int rc = 0;
++ FINDCLOSE_REQ *pSMB = NULL;
++ CLOSE_RSP *pSMBr = NULL;
++ int bytes_returned;
++
++ cFYI(1, ("In CIFSSMBFindClose"));
++ rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ /* no sense returning error if session restarted
++ file handle has been closed */
++ if(rc == -EAGAIN)
++ return 0;
++ if (rc)
++ return rc;
++
++ pSMB->FileID = searchHandle;
++ pSMB->ByteCount = 0;
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cERROR(1, ("Send error in FindClose = %d", rc));
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ /* Since session is dead, search handle closed on server already */
++ if (rc == -EAGAIN)
++ rc = 0;
++
++ return rc;
++}
++
++int
++CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
++ const unsigned char *searchName,
++ unsigned char **targetUNCs,
++ unsigned int *number_of_UNC_in_array,
++ const struct nls_table *nls_codepage)
++{
++/* TRANS2_GET_DFS_REFERRAL */
++ TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
++ TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
++ struct dfs_referral_level_3 * referrals = NULL;
++ int rc = 0;
++ int bytes_returned;
++ int name_len;
++ unsigned int i;
++ char * temp;
++ *number_of_UNC_in_array = 0;
++ *targetUNCs = NULL;
++
++ cFYI(1, ("In GetDFSRefer the path %s", searchName));
++ if (ses == NULL)
++ return -ENODEV;
++getDFSRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ pSMB->hdr.Tid = ses->ipc_tid;
++ pSMB->hdr.Uid = ses->Suid;
++ if (ses->capabilities & CAP_STATUS32) {
++ pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
++ }
++ if (ses->capabilities & CAP_DFS) {
++ pSMB->hdr.Flags2 |= SMBFLG2_DFS;
++ }
++
++ if (ses->capabilities & CAP_UNICODE) {
++ pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
++ name_len =
++ cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
++ searchName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(searchName, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->RequestFileName, searchName, name_len);
++ }
++
++ pSMB->ParameterCount = 2 /* level */ + name_len /*includes null */ ;
++ pSMB->TotalDataCount = 0;
++ pSMB->DataCount = 0;
++ pSMB->DataOffset = 0;
++ pSMB->MaxParameterCount = 0;
++ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ParameterOffset = cpu_to_le16(offsetof(
++ struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
++ pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ;
++ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
++ pSMB->TotalParameterCount = pSMB->ParameterCount;
++ pSMB->MaxReferralLevel = cpu_to_le16(3);
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("Send error in GetDFSRefer = %d", rc));
++ } else { /* decode response */
++/* BB Add logic to parse referrals here */
++ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
++ pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
++ cFYI(1,
++ ("Decoding GetDFSRefer response. BCC: %d Offset %d",
++ pSMBr->ByteCount, pSMBr->DataOffset));
++ if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
++ rc = -EIO; /* bad smb */
++ else {
++ referrals =
++ (struct dfs_referral_level_3 *)
++ (8 /* sizeof start of data block */ +
++ pSMBr->DataOffset +
++ (char *) &pSMBr->hdr.Protocol);
++ cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",pSMBr->NumberOfReferrals,pSMBr->DFSFlags, referrals->ReferralSize,referrals->ServerType,referrals->ReferralFlags,referrals->TimeToLive));
++ /* BB This field is actually two bytes in from start of
++ data block so we could do safety check that DataBlock
++ begins at address of pSMBr->NumberOfReferrals */
++ *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
++
++ /* BB Fix below so can return more than one referral */
++ if(*number_of_UNC_in_array > 1)
++ *number_of_UNC_in_array = 1;
++
++ /* get the length of the strings describing refs */
++ name_len = 0;
++ for(i=0;i<*number_of_UNC_in_array;i++) {
++ /* make sure that DfsPathOffset not past end */
++ referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset);
++ if(referrals->DfsPathOffset > pSMBr->DataCount) {
++ /* if invalid referral, stop here and do
++ not try to copy any more */
++ *number_of_UNC_in_array = i;
++ break;
++ }
++ temp = ((char *)referrals) + referrals->DfsPathOffset;
++
++ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount);
++ } else {
++ name_len += strnlen(temp,pSMBr->DataCount);
++ }
++ referrals++;
++ /* BB add check that referral pointer does not fall off end PDU */
++
++ }
++ /* BB add check for name_len bigger than bcc */
++ *targetUNCs =
++ kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
++ /* copy the ref strings */
++ referrals =
++ (struct dfs_referral_level_3 *)
++ (8 /* sizeof data hdr */ +
++ pSMBr->DataOffset +
++ (char *) &pSMBr->hdr.Protocol);
++
++ for(i=0;i<*number_of_UNC_in_array;i++) {
++ temp = ((char *)referrals) + referrals->DfsPathOffset;
++ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
++ cifs_strfromUCS_le(*targetUNCs,
++ (wchar_t *) temp, name_len, nls_codepage);
++ } else {
++ strncpy(*targetUNCs,temp,name_len);
++ }
++ /* BB update target_uncs pointers */
++ referrals++;
++ }
++ temp = *targetUNCs;
++ temp[name_len] = 0;
++ }
++
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ if (rc == -EAGAIN)
++ goto getDFSRetry;
++
++ return rc;
++}
++
++int
++CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
++ struct statfs *FSData, const struct nls_table *nls_codepage)
++{
++/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
++ TRANSACTION2_QFSI_REQ *pSMB = NULL;
++ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
++ FILE_SYSTEM_INFO *response_data;
++ int rc = 0;
++ int bytes_returned = 0;
++
++ cFYI(1, ("In QFSInfo"));
++QFSInfoRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ pSMB->TotalParameterCount = 2; /* level */
++ pSMB->TotalDataCount = 0;
++ pSMB->MaxParameterCount = cpu_to_le16(2);
++ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
++ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
++ pSMB->ParameterCount = pSMB->TotalParameterCount;
++ pSMB->ParameterOffset = cpu_to_le16(offsetof(
++ struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
++ pSMB->DataCount = 0;
++ pSMB->DataOffset = 0;
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
++ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cERROR(1, ("Send error in QFSInfo = %d", rc));
++ } else { /* decode response */
++ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
++ cFYI(1,
++ ("Decoding qfsinfo response. BCC: %d Offset %d",
++ pSMBr->ByteCount, pSMBr->DataOffset));
++ if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
++ rc = -EIO; /* bad smb */
++ else {
++ response_data =
++ (FILE_SYSTEM_INFO
++ *) (((char *) &pSMBr->hdr.Protocol) +
++ pSMBr->DataOffset);
++ FSData->f_bsize =
++ le32_to_cpu(response_data->BytesPerSector) *
++ le32_to_cpu(response_data->
++ SectorsPerAllocationUnit);
++ FSData->f_blocks =
++ le64_to_cpu(response_data->TotalAllocationUnits);
++ FSData->f_bfree = FSData->f_bavail =
++ le64_to_cpu(response_data->FreeAllocationUnits);
++ cFYI(1,
++ ("Blocks: %lld Free: %lld Block size %ld",
++ (unsigned long long)FSData->f_blocks,
++ (unsigned long long)FSData->f_bfree,
++ FSData->f_bsize));
++ }
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ if (rc == -EAGAIN)
++ goto QFSInfoRetry;
++
++ return rc;
++}
++
++int
++CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
++ const struct nls_table *nls_codepage)
++{
++/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
++ TRANSACTION2_QFSI_REQ *pSMB = NULL;
++ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
++ FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
++ int rc = 0;
++ int bytes_returned = 0;
++
++ cFYI(1, ("In QFSAttributeInfo"));
++QFSAttributeRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ pSMB->TotalParameterCount = 2; /* level */
++ pSMB->TotalDataCount = 0;
++ pSMB->MaxParameterCount = cpu_to_le16(2);
++ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
++ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
++ pSMB->ParameterCount = pSMB->TotalParameterCount;
++ pSMB->ParameterOffset = cpu_to_le16(offsetof(
++ struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
++ pSMB->DataCount = 0;
++ pSMB->DataOffset = 0;
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
++ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
++ } else { /* decode response */
++ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
++ if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) { /* BB also check enough bytes returned */
++ rc = -EIO; /* bad smb */
++ } else {
++ response_data =
++ (FILE_SYSTEM_ATTRIBUTE_INFO
++ *) (((char *) &pSMBr->hdr.Protocol) +
++ pSMBr->DataOffset);
++ response_data->Attributes = le32_to_cpu(response_data->Attributes);
++ response_data->MaxPathNameComponentLength =
++ le32_to_cpu(response_data->MaxPathNameComponentLength);
++ response_data->FileSystemNameLen =
++ le32_to_cpu(response_data->FileSystemNameLen);
++ memcpy(&tcon->fsAttrInfo, response_data,
++ sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
++ }
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ if (rc == -EAGAIN)
++ goto QFSAttributeRetry;
++
++ return rc;
++}
++
++int
++CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
++ const struct nls_table *nls_codepage)
++{
++/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
++ TRANSACTION2_QFSI_REQ *pSMB = NULL;
++ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
++ FILE_SYSTEM_DEVICE_INFO *response_data;
++ int rc = 0;
++ int bytes_returned = 0;
++
++ cFYI(1, ("In QFSDeviceInfo"));
++QFSDeviceRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ pSMB->TotalParameterCount = 2; /* level */
++ pSMB->TotalDataCount = 0;
++ pSMB->MaxParameterCount = cpu_to_le16(2);
++ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
++ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
++ pSMB->ParameterCount = pSMB->TotalParameterCount;
++ pSMB->ParameterOffset = cpu_to_le16(offsetof(
++ struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
++
++ pSMB->DataCount = 0;
++ pSMB->DataOffset = 0;
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
++ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
++ } else { /* decode response */
++ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
++ if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
++ || (pSMBr->DataOffset > 512))
++ rc = -EIO; /* bad smb */
++ else {
++ response_data =
++ (FILE_SYSTEM_DEVICE_INFO
++ *) (((char *) &pSMBr->hdr.Protocol) +
++ pSMBr->DataOffset);
++ response_data->DeviceType =
++ le32_to_cpu(response_data->DeviceType);
++ response_data->DeviceCharacteristics =
++ le32_to_cpu(response_data->DeviceCharacteristics);
++ memcpy(&tcon->fsDevInfo, response_data,
++ sizeof (FILE_SYSTEM_DEVICE_INFO));
++ }
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ if (rc == -EAGAIN)
++ goto QFSDeviceRetry;
++
++ return rc;
++}
++
++int
++CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
++ const struct nls_table *nls_codepage)
++{
++/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
++ TRANSACTION2_QFSI_REQ *pSMB = NULL;
++ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
++ FILE_SYSTEM_UNIX_INFO *response_data;
++ int rc = 0;
++ int bytes_returned = 0;
++
++ cFYI(1, ("In QFSUnixInfo"));
++QFSUnixRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ pSMB->ParameterCount = 2; /* level */
++ pSMB->TotalDataCount = 0;
++ pSMB->DataCount = 0;
++ pSMB->DataOffset = 0;
++ pSMB->MaxParameterCount = cpu_to_le16(2);
++ pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ;
++ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
++ pSMB->TotalParameterCount = pSMB->ParameterCount;
++ pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
++ smb_com_transaction2_qfsi_req, InformationLevel) - 4);
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
++ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
++ } else { /* decode response */
++ pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
++ if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
++ rc = -EIO; /* bad smb */
++ } else {
++ response_data =
++ (FILE_SYSTEM_UNIX_INFO
++ *) (((char *) &pSMBr->hdr.Protocol) +
++ pSMBr->DataOffset);
++ response_data->MajorVersionNumber =
++ le16_to_cpu(response_data->MajorVersionNumber);
++ response_data->MinorVersionNumber =
++ le16_to_cpu(response_data->MinorVersionNumber);
++ response_data->Capability =
++ le64_to_cpu(response_data->Capability);
++ memcpy(&tcon->fsUnixInfo, response_data,
++ sizeof (FILE_SYSTEM_UNIX_INFO));
++ }
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ if (rc == -EAGAIN)
++ goto QFSUnixRetry;
++
++
++ return rc;
++}
++
++/* We can not use write of zero bytes trick to
++ set file size due to need for large file support. Also note that
++ this SetPathInfo is preferred to SetFileInfo based method in next
++ routine which is only needed to work around a sharing violation bug
++ in Samba which this routine can run into */
++
++int
++CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
++ __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
++{
++ struct smb_com_transaction2_spi_req *pSMB = NULL;
++ struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
++ struct file_end_of_file_info *parm_data;
++ int name_len;
++ int rc = 0;
++ int bytes_returned = 0;
++
++ cFYI(1, ("In SetEOF"));
++SetEOFRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len =
++ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(fileName, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->FileName, fileName, name_len);
++ }
++ pSMB->ParameterCount = 6 + name_len;
++ pSMB->DataCount = sizeof (struct file_end_of_file_info);
++ pSMB->MaxParameterCount = cpu_to_le16(2);
++ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
++ InformationLevel) - 4;
++ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
++ if(SetAllocation) {
++ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
++ pSMB->InformationLevel =
++ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
++ else
++ pSMB->InformationLevel =
++ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
++ } else /* Set File Size */ {
++ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
++ pSMB->InformationLevel =
++ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
++ else
++ pSMB->InformationLevel =
++ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
++ }
++
++ parm_data =
++ (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
++ pSMB->DataOffset);
++ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
++ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
++ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
++ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
++ pSMB->TotalDataCount = pSMB->DataCount;
++ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
++ pSMB->TotalParameterCount = pSMB->ParameterCount;
++ pSMB->Reserved4 = 0;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ parm_data->FileSize = cpu_to_le64(size);
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("SetPathInfo (file size) returned %d", rc));
++ }
++
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ if (rc == -EAGAIN)
++ goto SetEOFRetry;
++
++ return rc;
++}
++
++int
++CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
++ __u16 fid, __u32 pid_of_opener, int SetAllocation)
++{
++ struct smb_com_transaction2_sfi_req *pSMB = NULL;
++ struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
++ char *data_offset;
++ struct file_end_of_file_info *parm_data;
++ int rc = 0;
++ int bytes_returned = 0;
++ __u32 tmp;
++
++ cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
++ (long long)size));
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ tmp = cpu_to_le32(pid_of_opener); /* override pid of current process
++ so network fid will be valid */
++ pSMB->hdr.Pid = tmp & 0xFFFF;
++ tmp >>= 16;
++ pSMB->hdr.PidHigh = tmp & 0xFFFF;
++
++ pSMB->ParameterCount = 6;
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
++ Fid) - 4;
++ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
++
++ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
++
++ pSMB->DataCount = sizeof(struct file_end_of_file_info);
++ pSMB->MaxParameterCount = cpu_to_le16(2);
++ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
++ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
++ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
++ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
++ pSMB->TotalDataCount = pSMB->DataCount;
++ pSMB->TotalParameterCount = pSMB->ParameterCount;
++ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
++ parm_data =
++ (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
++ pSMB->DataOffset);
++ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */
++ parm_data->FileSize = cpu_to_le64(size);
++ pSMB->Fid = fid;
++ if(SetAllocation) {
++ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
++ pSMB->InformationLevel =
++ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
++ else
++ pSMB->InformationLevel =
++ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
++ } else /* Set File Size */ {
++ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
++ pSMB->InformationLevel =
++ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
++ else
++ pSMB->InformationLevel =
++ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
++ }
++ pSMB->Reserved4 = 0;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1,
++ ("Send error in SetFileInfo (SetFileSize) = %d",
++ rc));
++ }
++
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ /* Note: On -EAGAIN error only caller can retry on handle based calls
++ since file handle passed in no longer valid */
++
++ return rc;
++}
++
++int
++CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
++ FILE_BASIC_INFO * data, const struct nls_table *nls_codepage)
++{
++ TRANSACTION2_SPI_REQ *pSMB = NULL;
++ TRANSACTION2_SPI_RSP *pSMBr = NULL;
++ int name_len;
++ int rc = 0;
++ int bytes_returned = 0;
++ char *data_offset;
++
++ cFYI(1, ("In SetTimes"));
++
++SetTimesRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len =
++ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(fileName, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->FileName, fileName, name_len);
++ }
++
++ pSMB->ParameterCount = 6 + name_len;
++ pSMB->DataCount = sizeof (FILE_BASIC_INFO);
++ pSMB->MaxParameterCount = cpu_to_le16(2);
++ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
++ InformationLevel) - 4;
++ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
++ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
++ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
++ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
++ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
++
++ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
++ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
++ pSMB->TotalDataCount = pSMB->DataCount;
++ pSMB->TotalParameterCount = pSMB->ParameterCount;
++ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
++ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
++ else
++ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
++ pSMB->Reserved4 = 0;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("SetPathInfo (times) returned %d", rc));
++ }
++
++ if (pSMB)
++ cifs_buf_release(pSMB);
++
++ if (rc == -EAGAIN)
++ goto SetTimesRetry;
++
++ return rc;
++}
++
++int
++CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
++ char *fileName, __u64 mode, __u64 uid, __u64 gid,
++ dev_t device, const struct nls_table *nls_codepage)
++{
++ TRANSACTION2_SPI_REQ *pSMB = NULL;
++ TRANSACTION2_SPI_RSP *pSMBr = NULL;
++ int name_len;
++ int rc = 0;
++ int bytes_returned = 0;
++ FILE_UNIX_BASIC_INFO *data_offset;
++
++ cFYI(1, ("In SetUID/GID/Mode"));
++setPermsRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len =
++ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(fileName, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->FileName, fileName, name_len);
++ }
++
++ pSMB->ParameterCount = 6 + name_len;
++ pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO);
++ pSMB->MaxParameterCount = cpu_to_le16(2);
++ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
++ InformationLevel) - 4;
++ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
++ data_offset =
++ (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
++ pSMB->DataOffset);
++ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
++ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
++ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
++ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
++ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
++ pSMB->TotalParameterCount = pSMB->ParameterCount;
++ pSMB->TotalDataCount = pSMB->DataCount;
++ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
++ pSMB->Reserved4 = 0;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ data_offset->Uid = cpu_to_le64(uid);
++ data_offset->Gid = cpu_to_le64(gid);
++ /* better to leave device as zero when it is */
++ data_offset->DevMajor = cpu_to_le64(MAJOR(device));
++ data_offset->DevMinor = cpu_to_le64(MINOR(device));
++ data_offset->Permissions = cpu_to_le64(mode);
++
++ if(S_ISREG(mode))
++ data_offset->Type = cpu_to_le32(UNIX_FILE);
++ else if(S_ISDIR(mode))
++ data_offset->Type = cpu_to_le32(UNIX_DIR);
++ else if(S_ISLNK(mode))
++ data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
++ else if(S_ISCHR(mode))
++ data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
++ else if(S_ISBLK(mode))
++ data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
++ else if(S_ISFIFO(mode))
++ data_offset->Type = cpu_to_le32(UNIX_FIFO);
++ else if(S_ISSOCK(mode))
++ data_offset->Type = cpu_to_le32(UNIX_SOCKET);
++
++
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("SetPathInfo (perms) returned %d", rc));
++ }
++
++ if (pSMB)
++ cifs_buf_release(pSMB);
++ if (rc == -EAGAIN)
++ goto setPermsRetry;
++ return rc;
++}
++
++int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
++ const int notify_subdirs, const __u16 netfid,
++ __u32 filter, const struct nls_table *nls_codepage)
++{
++ int rc = 0;
++ struct smb_com_transaction_change_notify_req * pSMB = NULL;
++ struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
++ int bytes_returned;
++
++ cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
++ rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ pSMB->TotalParameterCount = 0 ;
++ pSMB->TotalDataCount = 0;
++ pSMB->MaxParameterCount = cpu_to_le32(2);
++ /* BB find exact data count max from sess structure BB */
++ pSMB->MaxDataCount = 0; /* same in little endian or be */
++ pSMB->MaxSetupCount = 4;
++ pSMB->Reserved = 0;
++ pSMB->ParameterOffset = 0;
++ pSMB->DataCount = 0;
++ pSMB->DataOffset = 0;
++ pSMB->SetupCount = 4; /* single byte does not need le conversion */
++ pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
++ pSMB->ParameterCount = pSMB->TotalParameterCount;
++ if(notify_subdirs)
++ pSMB->WatchTree = 1; /* one byte - no le conversion needed */
++ pSMB->Reserved2 = 0;
++ pSMB->CompletionFilter = cpu_to_le32(filter);
++ pSMB->Fid = netfid; /* file handle always le */
++ pSMB->ByteCount = 0;
++
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("Error in Notify = %d", rc));
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++/* if (rc == -EAGAIN)
++ goto NotifyRetry; */
++ return rc;
++}
++#ifdef CONFIG_CIFS_XATTR
++int
++CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
++ const unsigned char *searchName,
++ char * EAData, size_t size,
++ const struct nls_table *nls_codepage)
++{
++ /* BB assumes one setup word */
++ TRANSACTION2_QPI_REQ *pSMB = NULL;
++ TRANSACTION2_QPI_RSP *pSMBr = NULL;
++ int rc = 0;
++ int bytes_returned;
++ int name_len;
++
++ cFYI(1, ("In Query All EAs path %s", searchName));
++QAllEAsRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len =
++ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
++ /* find define for this maxpathcomponent */
++ , nls_codepage);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ } else { /* BB improve the check for buffer overruns BB */
++ name_len = strnlen(searchName, 530);
++ name_len++; /* trailing null */
++ strncpy(pSMB->FileName, searchName, name_len);
++ }
++
++ pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
++ name_len /* includes null */ ;
++ pSMB->TotalDataCount = 0;
++ pSMB->MaxParameterCount = cpu_to_le16(2);
++ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ pSMB->ParameterOffset = cpu_to_le16(offsetof(
++ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
++ pSMB->DataCount = 0;
++ pSMB->DataOffset = 0;
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
++ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
++ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
++ pSMB->ParameterCount = pSMB->TotalParameterCount;
++ pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
++ pSMB->Reserved4 = 0;
++ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
++ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("Send error in QueryAllEAs = %d", rc));
++ } else { /* decode response */
++ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
++ /* BB also check enough total bytes returned */
++ /* BB we need to improve the validity checking
++ of these trans2 responses */
++ if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512))
++ rc = -EIO; /* bad smb */
++ /* else if (pFindData){
++ memcpy((char *) pFindData,
++ (char *) &pSMBr->hdr.Protocol +
++ pSMBr->DataOffset, kl);
++ }*/ else {
++ /* check that length of list is not more than bcc */
++ /* check that each entry does not go beyond length
++ of list */
++ /* check that each element of each entry does not
++ go beyond end of list */
++ struct fealist * ea_response_data;
++ rc = 0;
++ /* validate_trans2_offsets() */
++ /* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
++ ea_response_data = (struct fealist *)
++ (((char *) &pSMBr->hdr.Protocol) +
++ pSMBr->DataOffset);
++ cFYI(1,("ea length %d",ea_response_data->list_len));
++ }
++ }
++ if (pSMB)
++ cifs_buf_release(pSMB);
++ if (rc == -EAGAIN)
++ goto QAllEAsRetry;
++
++ return rc;
++}
++#endif
+diff -urN linux-2.4.29.old/fs/cifs/cifs_unicode.c linux-2.4.29/fs/cifs/cifs_unicode.c
+--- linux-2.4.29.old/fs/cifs/cifs_unicode.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/cifs_unicode.c 2004-07-14 00:25:04.000000000 +0200
+@@ -0,0 +1,87 @@
++/*
++ * fs/cifs/cifs_unicode.c
++ *
++ * Copyright (c) International Business Machines Corp., 2000,2002
++ * Modified by Steve French (sfrench@us.ibm.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 <linux/fs.h>
++#include "cifs_unicode.h"
++#include "cifs_uniupr.h"
++#include "cifspdu.h"
++#include "cifs_debug.h"
++
++/*
++ * NAME: cifs_strfromUCS()
++ *
++ * FUNCTION: Convert little-endian unicode string to character string
++ *
++ */
++int
++cifs_strfromUCS_le(char *to, const wchar_t * from, /* LITTLE ENDIAN */
++ int len, const struct nls_table *codepage)
++{
++ int i;
++ int outlen = 0;
++
++ for (i = 0; (i < len) && from[i]; i++) {
++ int charlen;
++ /* 2.4.0 kernel or greater */
++ charlen =
++ codepage->uni2char(le16_to_cpu(from[i]), &to[outlen],
++ NLS_MAX_CHARSET_SIZE);
++ if (charlen > 0) {
++ outlen += charlen;
++ } else {
++ to[outlen++] = '?';
++ }
++ }
++ to[outlen] = 0;
++ return outlen;
++}
++
++/*
++ * NAME: cifs_strtoUCS()
++ *
++ * FUNCTION: Convert character string to unicode string
++ *
++ */
++int
++cifs_strtoUCS(wchar_t * to, const char *from, int len,
++ const struct nls_table *codepage)
++{
++ int charlen;
++ int i;
++
++ for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
++
++ /* works for 2.4.0 kernel or later */
++ charlen = codepage->char2uni(from, len, &to[i]);
++ if (charlen < 1) {
++ cERROR(1,
++ ("cifs_strtoUCS: char2uni returned %d",
++ charlen));
++ to[i] = cpu_to_le16(0x003f); /* a question mark */
++ charlen = 1;
++ }
++ to[i] = cpu_to_le16(to[i]);
++
++ }
++
++ to[i] = 0;
++ return i;
++}
++
+diff -urN linux-2.4.29.old/fs/cifs/cifs_unicode.h linux-2.4.29/fs/cifs/cifs_unicode.h
+--- linux-2.4.29.old/fs/cifs/cifs_unicode.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/cifs_unicode.h 2004-07-14 00:25:04.000000000 +0200
+@@ -0,0 +1,353 @@
++/*
++ * cifs_unicode: Unicode kernel case support
++ *
++ * Function:
++ * Convert a unicode character to upper or lower case using
++ * compressed tables.
++ *
++ * Copyright (c) International Business Machines Corp., 2000,2002
++ *
++ * 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
++ *
++ *
++ * Notes:
++ * These APIs are based on the C library functions. The semantics
++ * should match the C functions but with expanded size operands.
++ *
++ * The upper/lower functions are based on a table created by mkupr.
++ * This is a compressed table of upper and lower case conversion.
++ *
++ */
++
++#include <asm/byteorder.h>
++#include <linux/types.h>
++#include <linux/nls.h>
++
++#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
++
++/* Just define what we want from uniupr.h. We don't want to define the tables
++ * in each source file.
++ */
++#ifndef UNICASERANGE_DEFINED
++struct UniCaseRange {
++ wchar_t start;
++ wchar_t end;
++ signed char *table;
++};
++#endif /* UNICASERANGE_DEFINED */
++
++#ifndef UNIUPR_NOUPPER
++extern signed char CifsUniUpperTable[512];
++extern const struct UniCaseRange CifsUniUpperRange[];
++#endif /* UNIUPR_NOUPPER */
++
++#ifndef UNIUPR_NOLOWER
++extern signed char UniLowerTable[512];
++extern struct UniCaseRange UniLowerRange[];
++#endif /* UNIUPR_NOLOWER */
++
++#ifdef __KERNEL__
++int cifs_strfromUCS_le(char *, const wchar_t *, int, const struct nls_table *);
++int cifs_strtoUCS(wchar_t *, const char *, int, const struct nls_table *);
++#endif
++
++/*
++ * UniStrcat: Concatenate the second string to the first
++ *
++ * Returns:
++ * Address of the first string
++ */
++static inline wchar_t *
++UniStrcat(wchar_t * ucs1, const wchar_t * ucs2)
++{
++ wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */
++
++ while (*ucs1++) ; /* To end of first string */
++ ucs1--; /* Return to the null */
++ while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */
++ return anchor;
++}
++
++/*
++ * UniStrchr: Find a character in a string
++ *
++ * Returns:
++ * Address of first occurrence of character in string
++ * or NULL if the character is not in the string
++ */
++static inline wchar_t *
++UniStrchr(const wchar_t * ucs, wchar_t uc)
++{
++ while ((*ucs != uc) && *ucs)
++ ucs++;
++
++ if (*ucs == uc)
++ return (wchar_t *) ucs;
++ return NULL;
++}
++
++/*
++ * UniStrcmp: Compare two strings
++ *
++ * Returns:
++ * < 0: First string is less than second
++ * = 0: Strings are equal
++ * > 0: First string is greater than second
++ */
++static inline int
++UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2)
++{
++ while ((*ucs1 == *ucs2) && *ucs1) {
++ ucs1++;
++ ucs2++;
++ }
++ return (int) *ucs1 - (int) *ucs2;
++}
++
++/*
++ * UniStrcpy: Copy a string
++ */
++static inline wchar_t *
++UniStrcpy(wchar_t * ucs1, const wchar_t * ucs2)
++{
++ wchar_t *anchor = ucs1; /* save the start of result string */
++
++ while ((*ucs1++ = *ucs2++)) ;
++ return anchor;
++}
++
++/*
++ * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
++ */
++static inline size_t
++UniStrlen(const wchar_t * ucs1)
++{
++ int i = 0;
++
++ while (*ucs1++)
++ i++;
++ return i;
++}
++
++/*
++ * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a string (length limited)
++ */
++static inline size_t
++UniStrnlen(const wchar_t * ucs1, int maxlen)
++{
++ int i = 0;
++
++ while (*ucs1++) {
++ i++;
++ if (i >= maxlen)
++ break;
++ }
++ return i;
++}
++
++/*
++ * UniStrncat: Concatenate length limited string
++ */
++static inline wchar_t *
++UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
++{
++ wchar_t *anchor = ucs1; /* save pointer to string 1 */
++
++ while (*ucs1++) ;
++ ucs1--; /* point to null terminator of s1 */
++ while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */
++ ucs1++;
++ ucs2++;
++ }
++ *ucs1 = 0; /* Null terminate the result */
++ return (anchor);
++}
++
++/*
++ * UniStrncmp: Compare length limited string
++ */
++static inline int
++UniStrncmp(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
++{
++ if (!n)
++ return 0; /* Null strings are equal */
++ while ((*ucs1 == *ucs2) && *ucs1 && --n) {
++ ucs1++;
++ ucs2++;
++ }
++ return (int) *ucs1 - (int) *ucs2;
++}
++
++/*
++ * UniStrncmp_le: Compare length limited string - native to little-endian
++ */
++static inline int
++UniStrncmp_le(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
++{
++ if (!n)
++ return 0; /* Null strings are equal */
++ while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
++ ucs1++;
++ ucs2++;
++ }
++ return (int) *ucs1 - (int) __le16_to_cpu(*ucs2);
++}
++
++/*
++ * UniStrncpy: Copy length limited string with pad
++ */
++static inline wchar_t *
++UniStrncpy(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
++{
++ wchar_t *anchor = ucs1;
++
++ while (n-- && *ucs2) /* Copy the strings */
++ *ucs1++ = *ucs2++;
++
++ n++;
++ while (n--) /* Pad with nulls */
++ *ucs1++ = 0;
++ return anchor;
++}
++
++/*
++ * UniStrncpy_le: Copy length limited string with pad to little-endian
++ */
++static inline wchar_t *
++UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
++{
++ wchar_t *anchor = ucs1;
++
++ while (n-- && *ucs2) /* Copy the strings */
++ *ucs1++ = __le16_to_cpu(*ucs2++);
++
++ n++;
++ while (n--) /* Pad with nulls */
++ *ucs1++ = 0;
++ return anchor;
++}
++
++/*
++ * UniStrstr: Find a string in a string
++ *
++ * Returns:
++ * Address of first match found
++ * NULL if no matching string is found
++ */
++static inline wchar_t *
++UniStrstr(const wchar_t * ucs1, const wchar_t * ucs2)
++{
++ const wchar_t *anchor1 = ucs1;
++ const wchar_t *anchor2 = ucs2;
++
++ while (*ucs1) {
++ if (*ucs1 == *ucs2) { /* Partial match found */
++ ucs1++;
++ ucs2++;
++ } else {
++ if (!*ucs2) /* Match found */
++ return (wchar_t *) anchor1;
++ ucs1 = ++anchor1; /* No match */
++ ucs2 = anchor2;
++ }
++ }
++
++ if (!*ucs2) /* Both end together */
++ return (wchar_t *) anchor1; /* Match found */
++ return NULL; /* No match */
++}
++
++#ifndef UNIUPR_NOUPPER
++/*
++ * UniToupper: Convert a unicode character to upper case
++ */
++static inline wchar_t
++UniToupper(register wchar_t uc)
++{
++ register const struct UniCaseRange *rp;
++
++ if (uc < sizeof (CifsUniUpperTable)) { /* Latin characters */
++ return uc + CifsUniUpperTable[uc]; /* Use base tables */
++ } else {
++ rp = CifsUniUpperRange; /* Use range tables */
++ while (rp->start) {
++ if (uc < rp->start) /* Before start of range */
++ return uc; /* Uppercase = input */
++ if (uc <= rp->end) /* In range */
++ return uc + rp->table[uc - rp->start];
++ rp++; /* Try next range */
++ }
++ }
++ return uc; /* Past last range */
++}
++
++/*
++ * UniStrupr: Upper case a unicode string
++ */
++static inline wchar_t *
++UniStrupr(register wchar_t * upin)
++{
++ register wchar_t *up;
++
++ up = upin;
++ while (*up) { /* For all characters */
++ *up = UniToupper(*up);
++ up++;
++ }
++ return upin; /* Return input pointer */
++}
++#endif /* UNIUPR_NOUPPER */
++
++#ifndef UNIUPR_NOLOWER
++/*
++ * UniTolower: Convert a unicode character to lower case
++ */
++static inline wchar_t
++UniTolower(wchar_t uc)
++{
++ register struct UniCaseRange *rp;
++
++ if (uc < sizeof (UniLowerTable)) { /* Latin characters */
++ return uc + UniLowerTable[uc]; /* Use base tables */
++ } else {
++ rp = UniLowerRange; /* Use range tables */
++ while (rp->start) {
++ if (uc < rp->start) /* Before start of range */
++ return uc; /* Uppercase = input */
++ if (uc <= rp->end) /* In range */
++ return uc + rp->table[uc - rp->start];
++ rp++; /* Try next range */
++ }
++ }
++ return uc; /* Past last range */
++}
++
++/*
++ * UniStrlwr: Lower case a unicode string
++ */
++static inline wchar_t *
++UniStrlwr(register wchar_t * upin)
++{
++ register wchar_t *up;
++
++ up = upin;
++ while (*up) { /* For all characters */
++ *up = UniTolower(*up);
++ up++;
++ }
++ return upin; /* Return input pointer */
++}
++
++#endif
+diff -urN linux-2.4.29.old/fs/cifs/cifs_uniupr.h linux-2.4.29/fs/cifs/cifs_uniupr.h
+--- linux-2.4.29.old/fs/cifs/cifs_uniupr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/cifs_uniupr.h 2004-07-14 00:25:04.000000000 +0200
+@@ -0,0 +1,253 @@
++/*
++ * Copyright (c) International Business Machines Corp., 2000,2002
++ *
++ * 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
++ *
++ * uniupr.h - Unicode compressed case ranges
++ *
++*/
++
++#ifndef UNIUPR_NOUPPER
++/*
++ * Latin upper case
++ */
++signed char CifsUniUpperTable[512] = {
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 040-04f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 050-05f */
++ 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 060-06f */
++ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, 0, 0, 0, 0, 0, /* 070-07f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0c0-0cf */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0d0-0df */
++ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 0e0-0ef */
++ -32, -32, -32, -32, -32, -32, -32, 0, -32, -32, -32, -32, -32, -32, -32, 121, /* 0f0-0ff */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 100-10f */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 110-11f */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 120-12f */
++ 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 130-13f */
++ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, /* 140-14f */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 150-15f */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 160-16f */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 170-17f */
++ 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, /* 180-18f */
++ 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, /* 190-19f */
++ 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */
++ -1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */
++ 0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */
++ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */
++ 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */
++};
++
++/* Upper case range - Greek */
++static signed char UniCaseRangeU03a0[47] = {
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -38, -37, -37, -37, /* 3a0-3af */
++ 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 3b0-3bf */
++ -32, -32, -31, -32, -32, -32, -32, -32, -32, -32, -32, -32, -64,
++ -63, -63,
++};
++
++/* Upper case range - Cyrillic */
++static signed char UniCaseRangeU0430[48] = {
++ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 430-43f */
++ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 440-44f */
++ 0, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, 0, -80, -80, /* 450-45f */
++};
++
++/* Upper case range - Extended cyrillic */
++static signed char UniCaseRangeU0490[61] = {
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 490-49f */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4a0-4af */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4b0-4bf */
++ 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1,
++};
++
++/* Upper case range - Extended latin and greek */
++static signed char UniCaseRangeU1e00[509] = {
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e00-1e0f */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e10-1e1f */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e20-1e2f */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e30-1e3f */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e40-1e4f */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e50-1e5f */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e60-1e6f */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e70-1e7f */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e80-1e8f */
++ 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, -59, 0, -1, 0, -1, /* 1e90-1e9f */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ea0-1eaf */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1eb0-1ebf */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ec0-1ecf */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ed0-1edf */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ee0-1eef */
++ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
++ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f00-1f0f */
++ 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f10-1f1f */
++ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f20-1f2f */
++ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f30-1f3f */
++ 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f40-1f4f */
++ 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f50-1f5f */
++ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f60-1f6f */
++ 74, 74, 86, 86, 86, 86, 100, 100, 0, 0, 112, 112, 126, 126, 0, 0, /* 1f70-1f7f */
++ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f80-1f8f */
++ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f90-1f9f */
++ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fa0-1faf */
++ 8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fb0-1fbf */
++ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fc0-1fcf */
++ 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fd0-1fdf */
++ 8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fe0-1fef */
++ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++};
++
++/* Upper case range - Wide latin */
++static signed char UniCaseRangeUff40[27] = {
++ 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* ff40-ff4f */
++ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
++};
++
++/*
++ * Upper Case Range
++ */
++const struct UniCaseRange CifsUniUpperRange[] = {
++ {0x03a0, 0x03ce, UniCaseRangeU03a0},
++ {0x0430, 0x045f, UniCaseRangeU0430},
++ {0x0490, 0x04cc, UniCaseRangeU0490},
++ {0x1e00, 0x1ffc, UniCaseRangeU1e00},
++ {0xff40, 0xff5a, UniCaseRangeUff40},
++ {0, 0, NULL}
++};
++#endif
++
++#ifndef UNIUPR_NOLOWER
++/*
++ * Latin lower case
++ */
++static signed char CifsUniLowerTable[512] = {
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
++ 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 040-04f */
++ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, /* 050-05f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 060-06f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 070-07f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
++ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 0c0-0cf */
++ 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, /* 0d0-0df */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0e0-0ef */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0f0-0ff */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 100-10f */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 110-11f */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 120-12f */
++ 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, /* 130-13f */
++ 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, /* 140-14f */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 150-15f */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 160-16f */
++ 1, 0, 1, 0, 1, 0, 1, 0, -121, 1, 0, 1, 0, 1, 0, 0, /* 170-17f */
++ 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 79, 0, /* 180-18f */
++ 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 190-19f */
++ 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, /* 1a0-1af */
++ 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, /* 1b0-1bf */
++ 0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1, /* 1c0-1cf */
++ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, /* 1d0-1df */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e0-1ef */
++ 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1f0-1ff */
++};
++
++/* Lower case range - Greek */
++static signed char UniCaseRangeL0380[44] = {
++ 0, 0, 0, 0, 0, 0, 38, 0, 37, 37, 37, 0, 64, 0, 63, 63, /* 380-38f */
++ 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 390-39f */
++ 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32,
++};
++
++/* Lower case range - Cyrillic */
++static signed char UniCaseRangeL0400[48] = {
++ 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 0, 80, 80, /* 400-40f */
++ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 410-41f */
++ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 420-42f */
++};
++
++/* Lower case range - Extended cyrillic */
++static signed char UniCaseRangeL0490[60] = {
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 490-49f */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4a0-4af */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4b0-4bf */
++ 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
++};
++
++/* Lower case range - Extended latin and greek */
++static signed char UniCaseRangeL1e00[504] = {
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e00-1e0f */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e10-1e1f */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e20-1e2f */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e30-1e3f */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e40-1e4f */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e50-1e5f */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e60-1e6f */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e70-1e7f */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e80-1e8f */
++ 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 1e90-1e9f */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ea0-1eaf */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1eb0-1ebf */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ec0-1ecf */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ed0-1edf */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ee0-1eef */
++ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
++ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f00-1f0f */
++ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f10-1f1f */
++ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f20-1f2f */
++ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f30-1f3f */
++ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f40-1f4f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, /* 1f50-1f5f */
++ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f60-1f6f */
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f70-1f7f */
++ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f80-1f8f */
++ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f90-1f9f */
++ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1fa0-1faf */
++ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -74, -74, -9, 0, 0, 0, /* 1fb0-1fbf */
++ 0, 0, 0, 0, 0, 0, 0, 0, -86, -86, -86, -86, -9, 0, 0, 0, /* 1fc0-1fcf */
++ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -100, -100, 0, 0, 0, 0, /* 1fd0-1fdf */
++ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -112, -112, -7, 0, 0, 0, /* 1fe0-1fef */
++ 0, 0, 0, 0, 0, 0, 0, 0,
++};
++
++/* Lower case range - Wide latin */
++static signed char UniCaseRangeLff20[27] = {
++ 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* ff20-ff2f */
++ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
++};
++
++/*
++ * Lower Case Range
++ */
++const static struct UniCaseRange CifsUniLowerRange[] = {
++ 0x0380, 0x03ab, UniCaseRangeL0380,
++ 0x0400, 0x042f, UniCaseRangeL0400,
++ 0x0490, 0x04cb, UniCaseRangeL0490,
++ 0x1e00, 0x1ff7, UniCaseRangeL1e00,
++ 0xff20, 0xff3a, UniCaseRangeLff20,
++ 0, 0, 0
++};
++#endif
+diff -urN linux-2.4.29.old/fs/cifs/connect.c linux-2.4.29/fs/cifs/connect.c
+--- linux-2.4.29.old/fs/cifs/connect.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/connect.c 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,2924 @@
++/*
++ * fs/cifs/connect.c
++ *
++ * Copyright (C) International Business Machines Corp., 2002,2004
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <linux/fs.h>
++#include <linux/net.h>
++#include <linux/string.h>
++#include <linux/list.h>
++#include <linux/wait.h>
++#include <linux/version.h>
++#include <linux/ipv6.h>
++#include <linux/pagemap.h>
++#include <linux/ctype.h>
++#include <linux/utsname.h>
++#include <asm/uaccess.h>
++#include <asm/processor.h>
++#include "cifspdu.h"
++#include "cifsglob.h"
++#include "cifsproto.h"
++#include "cifs_unicode.h"
++#include "cifs_debug.h"
++#include "cifs_fs_sb.h"
++#include "ntlmssp.h"
++#include "nterr.h"
++#include "rfc1002pdu.h"
++
++#define CIFS_PORT 445
++#define RFC1001_PORT 139
++
++extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
++ unsigned char *p24);
++extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
++ unsigned char *p24);
++extern int cifs_inet_pton(int, const char *, void *dst);
++
++struct smb_vol {
++ char *username;
++ char *password;
++ char *domainname;
++ char *UNC;
++ char *UNCip;
++ char *iocharset; /* local code page for mapping to and from Unicode */
++ char source_rfc1001_name[16]; /* netbios name of client */
++ uid_t linux_uid;
++ gid_t linux_gid;
++ mode_t file_mode;
++ mode_t dir_mode;
++ int rw:1;
++ int retry:1;
++ int intr:1;
++ unsigned int rsize;
++ unsigned int wsize;
++ unsigned int sockopt;
++ unsigned short int port;
++};
++
++static int ipv4_connect(struct sockaddr_in *psin_server,
++ struct socket **csocket,
++ char * netb_name);
++static int ipv6_connect(struct sockaddr_in6 *psin_server,
++ struct socket **csocket);
++
++
++ /*
++ * cifs tcp session reconnection
++ *
++ * mark tcp session as reconnecting so temporarily locked
++ * mark all smb sessions as reconnecting for tcp session
++ * reconnect tcp session
++ * wake up waiters on reconnection? - (not needed currently)
++ */
++
++int
++cifs_reconnect(struct TCP_Server_Info *server)
++{
++ int rc = 0;
++ struct list_head *tmp;
++ struct cifsSesInfo *ses;
++ struct cifsTconInfo *tcon;
++ struct mid_q_entry * mid_entry;
++
++ spin_lock(&GlobalMid_Lock);
++ if(server->tcpStatus == CifsExiting) {
++ /* the demux thread will exit normally
++ next time through the loop */
++ spin_unlock(&GlobalMid_Lock);
++ return rc;
++ } else
++ server->tcpStatus = CifsNeedReconnect;
++ spin_unlock(&GlobalMid_Lock);
++ server->maxBuf = 0;
++
++ cFYI(1, ("Reconnecting tcp session "));
++
++ /* before reconnecting the tcp session, mark the smb session (uid)
++ and the tid bad so they are not used until reconnected */
++ read_lock(&GlobalSMBSeslock);
++ list_for_each(tmp, &GlobalSMBSessionList) {
++ ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
++ if (ses->server) {
++ if (ses->server == server) {
++ ses->status = CifsNeedReconnect;
++ ses->ipc_tid = 0;
++ }
++ }
++ /* else tcp and smb sessions need reconnection */
++ }
++ list_for_each(tmp, &GlobalTreeConnectionList) {
++ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
++ if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
++ tcon->tidStatus = CifsNeedReconnect;
++ }
++ }
++ read_unlock(&GlobalSMBSeslock);
++ /* do not want to be sending data on a socket we are freeing */
++ down(&server->tcpSem);
++ if(server->ssocket) {
++ cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
++ server->ssocket->flags));
++ server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
++ cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
++ server->ssocket->flags));
++ sock_release(server->ssocket);
++ server->ssocket = NULL;
++ }
++
++ spin_lock(&GlobalMid_Lock);
++ list_for_each(tmp, &server->pending_mid_q) {
++ mid_entry = list_entry(tmp, struct
++ mid_q_entry,
++ qhead);
++ if(mid_entry) {
++ if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
++ /* Mark other intransit requests as needing retry so
++ we do not immediately mark the session bad again
++ (ie after we reconnect below) as they timeout too */
++ mid_entry->midState = MID_RETRY_NEEDED;
++ }
++ }
++ }
++ spin_unlock(&GlobalMid_Lock);
++ up(&server->tcpSem);
++
++ while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
++ {
++ if(server->protocolType == IPV6) {
++ rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
++ } else {
++ rc = ipv4_connect(&server->addr.sockAddr,
++ &server->ssocket,
++ server->workstation_RFC1001_name);
++ }
++ if(rc) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(3 * HZ);
++ } else {
++ atomic_inc(&tcpSesReconnectCount);
++ spin_lock(&GlobalMid_Lock);
++ if(server->tcpStatus != CifsExiting)
++ server->tcpStatus = CifsGood;
++ spin_unlock(&GlobalMid_Lock);
++ /* atomic_set(&server->inFlight,0);*/
++ wake_up(&server->response_q);
++ }
++ }
++ return rc;
++}
++
++static int
++cifs_demultiplex_thread(struct TCP_Server_Info *server)
++{
++ int length;
++ unsigned int pdu_length, total_read;
++ struct smb_hdr *smb_buffer = NULL;
++ struct msghdr smb_msg;
++ mm_segment_t temp_fs;
++ struct iovec iov;
++ struct socket *csocket = server->ssocket;
++ struct list_head *tmp;
++ struct cifsSesInfo *ses;
++ struct task_struct *task_to_wake = NULL;
++ struct mid_q_entry *mid_entry;
++ char *temp;
++
++ daemonize();
++ sprintf(current->comm,"cifsd");
++ /* allow_signal(SIGKILL);*/
++ current->flags |= PF_MEMALLOC;
++ server->tsk = current; /* save process info to wake at shutdown */
++ cFYI(1, ("Demultiplex PID: %d", current->pid));
++
++ temp_fs = get_fs(); /* we must turn off socket api parm checking */
++ set_fs(get_ds());
++
++ while (server->tcpStatus != CifsExiting) {
++ if (smb_buffer == NULL)
++ smb_buffer = cifs_buf_get();
++ else
++ memset(smb_buffer, 0, sizeof (struct smb_hdr));
++
++ if (smb_buffer == NULL) {
++ cERROR(1,("Can not get memory for SMB response"));
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(HZ * 3); /* give system time to free memory */
++ continue;
++ }
++ iov.iov_base = smb_buffer;
++ iov.iov_len = sizeof (struct smb_hdr) - 1;
++ /* 1 byte less above since wct is not always returned in error cases */
++ smb_msg.msg_iov = &iov;
++ smb_msg.msg_iovlen = 1;
++ smb_msg.msg_control = NULL;
++ smb_msg.msg_controllen = 0;
++
++ length =
++ sock_recvmsg(csocket, &smb_msg,
++ sizeof (struct smb_hdr) -
++ 1 /* RFC1001 header and SMB header */ ,
++ MSG_PEEK /* flags see socket.h */ );
++
++ if(server->tcpStatus == CifsExiting) {
++ break;
++ } else if (server->tcpStatus == CifsNeedReconnect) {
++ cFYI(1,("Reconnecting after server stopped responding"));
++ cifs_reconnect(server);
++ cFYI(1,("call to reconnect done"));
++ csocket = server->ssocket;
++ continue;
++ } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(1); /* minimum sleep to prevent looping
++ allowing socket to clear and app threads to set
++ tcpStatus CifsNeedReconnect if server hung */
++ continue;
++ } else if (length <= 0) {
++ if(server->tcpStatus == CifsNew) {
++ cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
++ /* some servers kill tcp session rather than returning
++ smb negprot error in which case reconnecting here is
++ not going to help - return error to mount */
++ break;
++ }
++ if(length == -EINTR) {
++ cFYI(1,("cifsd thread killed"));
++ break;
++ }
++ cFYI(1,("Reconnecting after unexpected peek error %d",length));
++ cifs_reconnect(server);
++ csocket = server->ssocket;
++ wake_up(&server->response_q);
++ continue;
++ }
++
++ pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
++ /* Ony read pdu_length after below checks for too short (due
++ to e.g. int overflow) and too long ie beyond end of buf */
++ cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length));
++
++ temp = (char *) smb_buffer;
++ if (length > 3) {
++ if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
++ iov.iov_base = smb_buffer;
++ iov.iov_len = 4;
++ length = sock_recvmsg(csocket, &smb_msg, 4, 0);
++ cFYI(0,("Received 4 byte keep alive packet"));
++ } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
++ iov.iov_base = smb_buffer;
++ iov.iov_len = 4;
++ length = sock_recvmsg(csocket, &smb_msg, 4, 0);
++ cFYI(1,("Good RFC 1002 session rsp"));
++ } else if ((temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE)
++ && (length == 5)) {
++ /* we get this from Windows 98 instead of error on SMB negprot response */
++ cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
++ if(server->tcpStatus == CifsNew) {
++ /* if nack on negprot (rather than
++ ret of smb negprot error) reconnecting
++ not going to help, ret error to mount */
++ break;
++ } else {
++ /* give server a second to
++ clean up before reconnect attempt */
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(HZ);
++ /* always try 445 first on reconnect
++ since we get NACK on some if we ever
++ connected to port 139 (the NACK is
++ since we do not begin with RFC1001
++ session initialize frame) */
++ server->addr.sockAddr.sin_port = CIFS_PORT;
++ cifs_reconnect(server);
++ csocket = server->ssocket;
++ wake_up(&server->response_q);
++ continue;
++ }
++ } else if (temp[0] != (char) 0) {
++ cERROR(1,("Unknown RFC 1002 frame"));
++ cifs_dump_mem(" Received Data: ", temp, length);
++ cifs_reconnect(server);
++ csocket = server->ssocket;
++ continue;
++ } else {
++ if ((length != sizeof (struct smb_hdr) - 1)
++ || (pdu_length >
++ CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE)
++ || (pdu_length <
++ sizeof (struct smb_hdr) - 1)
++ ||
++ (checkSMBhdr
++ (smb_buffer, smb_buffer->Mid))) {
++ cERROR(1,
++ ("Invalid size or format for SMB found with length %d and pdu_lenght %d",
++ length, pdu_length));
++ cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
++ /* could we fix this network corruption by finding next
++ smb header (instead of killing the session) and
++ restart reading from next valid SMB found? */
++ cifs_reconnect(server);
++ csocket = server->ssocket;
++ continue;
++ } else { /* length ok */
++
++ length = 0;
++ iov.iov_base = smb_buffer;
++ iov.iov_len = pdu_length;
++ for (total_read = 0;
++ total_read < pdu_length;
++ total_read += length) {
++ length = sock_recvmsg(csocket, &smb_msg,
++ pdu_length - total_read, 0);
++ if (length == 0) {
++ cERROR(1,
++ ("Zero length receive when expecting %d ",
++ pdu_length - total_read));
++ cifs_reconnect(server);
++ csocket = server->ssocket;
++ continue;
++ }
++ }
++ }
++
++ dump_smb(smb_buffer, length);
++ if (checkSMB
++ (smb_buffer, smb_buffer->Mid, total_read)) {
++ cERROR(1, ("Bad SMB Received "));
++ continue;
++ }
++
++ task_to_wake = NULL;
++ spin_lock(&GlobalMid_Lock);
++ list_for_each(tmp, &server->pending_mid_q) {
++ mid_entry = list_entry(tmp, struct
++ mid_q_entry,
++ qhead);
++
++ if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
++ cFYI(1,
++ (" Mid 0x%x matched - waking up ",mid_entry->mid));
++ task_to_wake = mid_entry->tsk;
++ mid_entry->resp_buf =
++ smb_buffer;
++ mid_entry->midState =
++ MID_RESPONSE_RECEIVED;
++ }
++ }
++ spin_unlock(&GlobalMid_Lock);
++ if (task_to_wake) {
++ smb_buffer = NULL; /* will be freed by users thread after he is done */
++ wake_up_process(task_to_wake);
++ } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
++ cERROR(1, ("No task to wake, unknown frame rcvd!"));
++ cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
++ }
++ }
++ } else {
++ cFYI(0,
++ ("Frame less than four bytes received %d bytes long.",
++ length));
++ if (length > 0) {
++ length = sock_recvmsg(csocket, &smb_msg, length, 0); /* throw away junk frame */
++ cFYI(1,
++ (" with junk 0x%x in it ",
++ *(__u32 *) smb_buffer));
++ }
++ }
++ }
++ spin_lock(&GlobalMid_Lock);
++ server->tcpStatus = CifsExiting;
++ server->tsk = NULL;
++ atomic_set(&server->inFlight, 0);
++ spin_unlock(&GlobalMid_Lock);
++ /* Although there should not be any requests blocked on
++ this queue it can not hurt to be paranoid and try to wake up requests
++ that may haven been blocked when more than 50 at time were on the wire
++ to the same server - they now will see the session is in exit state
++ and get out of SendReceive. */
++ wake_up_all(&server->request_q);
++ /* give those requests time to exit */
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(HZ/8);
++
++ if(server->ssocket) {
++ sock_release(csocket);
++ server->ssocket = NULL;
++ }
++ set_fs(temp_fs);
++ if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
++ cifs_buf_release(smb_buffer);
++
++ read_lock(&GlobalSMBSeslock);
++ if (list_empty(&server->pending_mid_q)) {
++ /* loop through server session structures attached to this and mark them dead */
++ list_for_each(tmp, &GlobalSMBSessionList) {
++ ses =
++ list_entry(tmp, struct cifsSesInfo,
++ cifsSessionList);
++ if (ses->server == server) {
++ ses->status = CifsExiting;
++ ses->server = NULL;
++ }
++ }
++ read_unlock(&GlobalSMBSeslock);
++ } else {
++ spin_lock(&GlobalMid_Lock);
++ list_for_each(tmp, &server->pending_mid_q) {
++ mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
++ if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
++ cFYI(1,
++ (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
++ task_to_wake = mid_entry->tsk;
++ if(task_to_wake) {
++ wake_up_process(task_to_wake);
++ }
++ }
++ }
++ spin_unlock(&GlobalMid_Lock);
++ read_unlock(&GlobalSMBSeslock);
++ set_current_state(TASK_INTERRUPTIBLE);
++ /* 1/8th of sec is more than enough time for them to exit */
++ schedule_timeout(HZ/8);
++ }
++
++ if (list_empty(&server->pending_mid_q)) {
++ /* mpx threads have not exited yet give them
++ at least the smb send timeout time for long ops */
++ cFYI(1, ("Wait for exit from demultiplex thread"));
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(46 * HZ);
++ /* if threads still have not exited they are probably never
++ coming home not much else we can do but free the memory */
++ }
++ kfree(server);
++
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(HZ/4);
++ return 0;
++}
++
++static void *
++cifs_kcalloc(size_t size, int type)
++{
++ void *addr;
++ addr = kmalloc(size, type);
++ if (addr)
++ memset(addr, 0, size);
++ return addr;
++}
++
++static int
++cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
++{
++ char *value;
++ char *data;
++ unsigned int temp_len, i, j;
++ char separator[2];
++
++ separator[0] = ',';
++ separator[1] = 0;
++
++ memset(vol->source_rfc1001_name,0x20,15);
++ for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
++ /* does not have to be a perfect mapping since the field is
++ informational, only used for servers that do not support
++ port 445 and it can be overridden at mount time */
++ vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
++ }
++ vol->source_rfc1001_name[15] = 0;
++
++ vol->linux_uid = current->uid; /* current->euid instead? */
++ vol->linux_gid = current->gid;
++ vol->dir_mode = S_IRWXUGO;
++ /* 2767 perms indicate mandatory locking support */
++ vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
++
++ /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
++ vol->rw = TRUE;
++
++ if (!options)
++ return 1;
++
++ if(strncmp(options,"sep=",4) == 0) {
++ if(options[4] != 0) {
++ separator[0] = options[4];
++ options += 5;
++ } else {
++ cFYI(1,("Null separator not allowed"));
++ }
++ }
++
++ while ((data = strsep(&options, separator)) != NULL) {
++ if (!*data)
++ continue;
++ if ((value = strchr(data, '=')) != NULL)
++ *value++ = '\0';
++ if (strnicmp(data, "user", 4) == 0) {
++ if (!value || !*value) {
++ printk(KERN_WARNING
++ "CIFS: invalid or missing username\n");
++ return 1; /* needs_arg; */
++ }
++ if (strnlen(value, 200) < 200) {
++ vol->username = value;
++ } else {
++ printk(KERN_WARNING "CIFS: username too long\n");
++ return 1;
++ }
++ } else if (strnicmp(data, "pass", 4) == 0) {
++ if (!value || !*value) {
++ vol->password = NULL;
++ continue;
++ }
++ temp_len = strlen(value);
++ /* removed password length check, NTLM passwords
++ can be arbitrarily long */
++
++ /* if comma in password, the string will be
++ prematurely null terminated. Commas in password are
++ specified across the cifs mount interface by a double
++ comma ie ,, and a comma used as in other cases ie ','
++ as a parameter delimiter/separator is single and due
++ to the strsep above is temporarily zeroed. */
++
++ /* NB: password legally can have multiple commas and
++ the only illegal character in a password is null */
++
++ if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
++ /* reinsert comma */
++ value[temp_len] = separator[0];
++ temp_len+=2; /* move after the second comma */
++ while(value[temp_len] != 0) {
++ if((value[temp_len] == separator[0]) && (value[temp_len+1] != separator[0])) {
++ /* single comma indicating start of next parm */
++ break;
++ }
++ temp_len++;
++ }
++ if(value[temp_len] == 0) {
++ options = NULL;
++ } else {
++ value[temp_len] = 0;
++ /* move options to point to start of next parm */
++ options = value + temp_len + 1;
++ }
++ /* go from value to (value + temp_len) condensing double commas to singles */
++ vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
++ for(i=0,j=0;i<temp_len;i++,j++) {
++ vol->password[j] = value[i];
++ if(value[i] == separator[0] && value[i+1] == separator[0]) {
++ /* skip second comma */
++ i++;
++ }
++ }
++ /* value[temp_len] is zeroed above so
++ vol->password[temp_len] guaranteed to be null */
++ } else {
++ vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
++ strcpy(vol->password, value);
++ }
++ } else if (strnicmp(data, "ip", 2) == 0) {
++ if (!value || !*value) {
++ vol->UNCip = NULL;
++ } else if (strnlen(value, 35) < 35) {
++ vol->UNCip = value;
++ } else {
++ printk(KERN_WARNING "CIFS: ip address too long\n");
++ return 1;
++ }
++ } else if ((strnicmp(data, "unc", 3) == 0)
++ || (strnicmp(data, "target", 6) == 0)
++ || (strnicmp(data, "path", 4) == 0)) {
++ if (!value || !*value) {
++ printk(KERN_WARNING
++ "CIFS: invalid path to network resource\n");
++ return 1; /* needs_arg; */
++ }
++ if ((temp_len = strnlen(value, 300)) < 300) {
++ vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
++ if(vol->UNC == NULL)
++ return 1;
++ strcpy(vol->UNC,value);
++ if (strncmp(vol->UNC, "//", 2) == 0) {
++ vol->UNC[0] = '\\';
++ vol->UNC[1] = '\\';
++ } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
++ printk(KERN_WARNING
++ "CIFS: UNC Path does not begin with // or \\\\ \n");
++ return 1;
++ }
++ } else {
++ printk(KERN_WARNING "CIFS: UNC name too long\n");
++ return 1;
++ }
++ } else if ((strnicmp(data, "domain", 3) == 0)
++ || (strnicmp(data, "workgroup", 5) == 0)) {
++ if (!value || !*value) {
++ printk(KERN_WARNING "CIFS: invalid domain name\n");
++ return 1; /* needs_arg; */
++ }
++ /* BB are there cases in which a comma can be valid in
++ a domain name and need special handling? */
++ if (strnlen(value, 65) < 65) {
++ vol->domainname = value;
++ cFYI(1, ("Domain name set"));
++ } else {
++ printk(KERN_WARNING "CIFS: domain name too long\n");
++ return 1;
++ }
++ } else if (strnicmp(data, "iocharset", 9) == 0) {
++ if (!value || !*value) {
++ printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
++ return 1; /* needs_arg; */
++ }
++ if (strnlen(value, 65) < 65) {
++ if(strnicmp(value,"default",7))
++ vol->iocharset = value;
++ /* if iocharset not set load_nls_default used by caller */
++ cFYI(1, ("iocharset set to %s",value));
++ } else {
++ printk(KERN_WARNING "CIFS: iocharset name too long.\n");
++ return 1;
++ }
++ } else if (strnicmp(data, "uid", 3) == 0) {
++ if (value && *value) {
++ vol->linux_uid =
++ simple_strtoul(value, &value, 0);
++ }
++ } else if (strnicmp(data, "gid", 3) == 0) {
++ if (value && *value) {
++ vol->linux_gid =
++ simple_strtoul(value, &value, 0);
++ }
++ } else if (strnicmp(data, "file_mode", 4) == 0) {
++ if (value && *value) {
++ vol->file_mode =
++ simple_strtoul(value, &value, 0);
++ }
++ } else if (strnicmp(data, "dir_mode", 3) == 0) {
++ if (value && *value) {
++ vol->dir_mode =
++ simple_strtoul(value, &value, 0);
++ }
++ } else if (strnicmp(data, "port", 4) == 0) {
++ if (value && *value) {
++ vol->port =
++ simple_strtoul(value, &value, 0);
++ }
++ } else if (strnicmp(data, "rsize", 5) == 0) {
++ if (value && *value) {
++ vol->rsize =
++ simple_strtoul(value, &value, 0);
++ }
++ } else if (strnicmp(data, "wsize", 5) == 0) {
++ if (value && *value) {
++ vol->wsize =
++ simple_strtoul(value, &value, 0);
++ }
++ } else if (strnicmp(data, "sockopt", 5) == 0) {
++ if (value && *value) {
++ vol->sockopt =
++ simple_strtoul(value, &value, 0);
++ }
++ } else if (strnicmp(data, "netbiosname", 4) == 0) {
++ if (!value || !*value || (*value == ' ')) {
++ cFYI(1,("invalid (empty) netbiosname specified"));
++ } else {
++ memset(vol->source_rfc1001_name,0x20,15);
++ for(i=0;i<15;i++) {
++ /* BB are there cases in which a comma can be
++ valid in this workstation netbios name (and need
++ special handling)? */
++
++ /* We do not uppercase netbiosname for user */
++ if (value[i]==0)
++ break;
++ else
++ vol->source_rfc1001_name[i] = value[i];
++ }
++ /* The string has 16th byte zero still from
++ set at top of the function */
++ if((i==15) && (value[i] != 0))
++ printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
++ }
++ } else if (strnicmp(data, "credentials", 4) == 0) {
++ /* ignore */
++ } else if (strnicmp(data, "version", 3) == 0) {
++ /* ignore */
++ } else if (strnicmp(data, "rw", 2) == 0) {
++ vol->rw = TRUE;
++ } else if ((strnicmp(data, "suid", 4) == 0) ||
++ (strnicmp(data, "nosuid", 6) == 0) ||
++ (strnicmp(data, "exec", 4) == 0) ||
++ (strnicmp(data, "noexec", 6) == 0) ||
++ (strnicmp(data, "nodev", 5) == 0) ||
++ (strnicmp(data, "noauto", 6) == 0) ||
++ (strnicmp(data, "dev", 3) == 0)) {
++ /* The mount tool or mount.cifs helper (if present)
++ uses these opts to set flags, and the flags are read
++ by the kernel vfs layer before we get here (ie
++ before read super) so there is no point trying to
++ parse these options again and set anything and it
++ is ok to just ignore them */
++ continue;
++ } else if (strnicmp(data, "ro", 2) == 0) {
++ vol->rw = FALSE;
++ } else if (strnicmp(data, "hard", 4) == 0) {
++ vol->retry = 1;
++ } else if (strnicmp(data, "soft", 4) == 0) {
++ vol->retry = 0;
++ } else if (strnicmp(data, "nohard", 6) == 0) {
++ vol->retry = 0;
++ } else if (strnicmp(data, "nosoft", 6) == 0) {
++ vol->retry = 1;
++ } else if (strnicmp(data, "nointr", 6) == 0) {
++ vol->intr = 0;
++ } else if (strnicmp(data, "intr", 4) == 0) {
++ vol->intr = 1;
++ } else if (strnicmp(data, "noac", 4) == 0) {
++ printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
++ } else
++ printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
++ }
++ if (vol->UNC == NULL) {
++ if(devname == NULL) {
++ printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
++ return 1;
++ }
++ if ((temp_len = strnlen(devname, 300)) < 300) {
++ vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
++ if(vol->UNC == NULL)
++ return 1;
++ strcpy(vol->UNC,devname);
++ if (strncmp(vol->UNC, "//", 2) == 0) {
++ vol->UNC[0] = '\\';
++ vol->UNC[1] = '\\';
++ } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
++ printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
++ return 1;
++ }
++ } else {
++ printk(KERN_WARNING "CIFS: UNC name too long\n");
++ return 1;
++ }
++ }
++ if(vol->UNCip == 0)
++ vol->UNCip = &vol->UNC[2];
++
++ return 0;
++}
++
++static struct cifsSesInfo *
++cifs_find_tcp_session(__u32 new_target_ip_addr,
++ char *userName, struct TCP_Server_Info **psrvTcp)
++{
++ struct list_head *tmp;
++ struct cifsSesInfo *ses;
++
++ *psrvTcp = NULL;
++ read_lock(&GlobalSMBSeslock);
++ list_for_each(tmp, &GlobalSMBSessionList) {
++ ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
++ if (ses->server) {
++ if (ses->server->addr.sockAddr.sin_addr.s_addr ==
++ new_target_ip_addr) {
++ /* BB lock server and tcp session and increment use count here?? */
++ *psrvTcp = ses->server; /* found a match on the TCP session */
++ /* BB check if reconnection needed */
++ if (strncmp
++ (ses->userName, userName,
++ MAX_USERNAME_SIZE) == 0){
++ read_unlock(&GlobalSMBSeslock);
++ return ses; /* found exact match on both tcp and SMB sessions */
++ }
++ }
++ }
++ /* else tcp and smb sessions need reconnection */
++ }
++ read_unlock(&GlobalSMBSeslock);
++ return NULL;
++}
++
++static struct cifsTconInfo *
++find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
++{
++ struct list_head *tmp;
++ struct cifsTconInfo *tcon;
++
++ read_lock(&GlobalSMBSeslock);
++ list_for_each(tmp, &GlobalTreeConnectionList) {
++ cFYI(1, ("Next tcon - "));
++ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
++ if (tcon->ses) {
++ if (tcon->ses->server) {
++ cFYI(1,
++ (" old ip addr: %x == new ip %x ?",
++ tcon->ses->server->addr.sockAddr.sin_addr.
++ s_addr, new_target_ip_addr));
++ if (tcon->ses->server->addr.sockAddr.sin_addr.
++ s_addr == new_target_ip_addr) {
++ /* BB lock tcon and server and tcp session and increment use count here? */
++ /* found a match on the TCP session */
++ /* BB check if reconnection needed */
++ cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
++ tcon->treeName, uncName));
++ if (strncmp
++ (tcon->treeName, uncName,
++ MAX_TREE_SIZE) == 0) {
++ cFYI(1,
++ ("Matched UNC, old user: %s == new: %s ?",
++ tcon->treeName, uncName));
++ if (strncmp
++ (tcon->ses->userName,
++ userName,
++ MAX_USERNAME_SIZE) == 0) {
++ read_unlock(&GlobalSMBSeslock);
++ return tcon;/* also matched user (smb session)*/
++ }
++ }
++ }
++ }
++ }
++ }
++ read_unlock(&GlobalSMBSeslock);
++ return NULL;
++}
++
++int
++connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
++ const char *old_path, const struct nls_table *nls_codepage)
++{
++ unsigned char *referrals = NULL;
++ unsigned int num_referrals;
++ int rc = 0;
++
++ rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
++ &num_referrals, &referrals);
++
++ /* BB Add in code to: if valid refrl, if not ip address contact
++ the helper that resolves tcp names, mount to it, try to
++ tcon to it unmount it if fail */
++
++ if(referrals)
++ kfree(referrals);
++
++ return rc;
++}
++
++int
++get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
++ const char *old_path, const struct nls_table *nls_codepage,
++ unsigned int *pnum_referrals, unsigned char ** preferrals)
++{
++ char *temp_unc;
++ int rc = 0;
++
++ *pnum_referrals = 0;
++
++ if (pSesInfo->ipc_tid == 0) {
++ temp_unc = kmalloc(2 /* for slashes */ +
++ strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
++ + 1 + 4 /* slash IPC$ */ + 2,
++ GFP_KERNEL);
++ if (temp_unc == NULL)
++ return -ENOMEM;
++ temp_unc[0] = '\\';
++ temp_unc[1] = '\\';
++ strcpy(temp_unc + 2, pSesInfo->serverName);
++ strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
++ rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
++ cFYI(1,
++ ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
++ kfree(temp_unc);
++ }
++ if (rc == 0)
++ rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
++ pnum_referrals, nls_codepage);
++
++ return rc;
++}
++
++/* See RFC1001 section 14 on representation of Netbios names */
++static void rfc1002mangle(char * target,char * source, unsigned int length)
++{
++ unsigned int i,j;
++
++ for(i=0,j=0;i<(length);i++) {
++ /* mask a nibble at a time and encode */
++ target[j] = 'A' + (0x0F & (source[i] >> 4));
++ target[j+1] = 'A' + (0x0F & source[i]);
++ j+=2;
++ }
++
++}
++
++
++static int
++ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
++ char * netbios_name)
++{
++ int rc = 0;
++ int connected = 0;
++ unsigned short int orig_port = 0;
++
++ if(*csocket == NULL) {
++ rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
++ if (rc < 0) {
++ cERROR(1, ("Error %d creating socket",rc));
++ *csocket = NULL;
++ return rc;
++ } else {
++ /* BB other socket options to set KEEPALIVE, NODELAY? */
++ cFYI(1,("Socket created"));
++ (*csocket)->sk->allocation = GFP_NOFS;
++ }
++ }
++
++ psin_server->sin_family = AF_INET;
++ if(psin_server->sin_port) { /* user overrode default port */
++ rc = (*csocket)->ops->connect(*csocket,
++ (struct sockaddr *) psin_server,
++ sizeof (struct sockaddr_in),0);
++ if (rc >= 0)
++ connected = 1;
++ }
++
++ if(!connected) {
++ /* save original port so we can retry user specified port
++ later if fall back ports fail this time */
++ orig_port = psin_server->sin_port;
++
++ /* do not retry on the same port we just failed on */
++ if(psin_server->sin_port != htons(CIFS_PORT)) {
++ psin_server->sin_port = htons(CIFS_PORT);
++
++ rc = (*csocket)->ops->connect(*csocket,
++ (struct sockaddr *) psin_server,
++ sizeof (struct sockaddr_in),0);
++ if (rc >= 0)
++ connected = 1;
++ }
++ }
++ if (!connected) {
++ psin_server->sin_port = htons(RFC1001_PORT);
++ rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
++ psin_server, sizeof (struct sockaddr_in),0);
++ if (rc >= 0)
++ connected = 1;
++ }
++
++ /* give up here - unless we want to retry on different
++ protocol families some day */
++ if (!connected) {
++ if(orig_port)
++ psin_server->sin_port = orig_port;
++ cFYI(1,("Error %d connecting to server via ipv4",rc));
++ sock_release(*csocket);
++ *csocket = NULL;
++ return rc;
++ }
++ /* Eventually check for other socket options to change from
++ the default. sock_setsockopt not used because it expects
++ user space buffer */
++ (*csocket)->sk->rcvtimeo = 7 * HZ;
++
++ /* send RFC1001 sessinit */
++
++ if(psin_server->sin_port == htons(139)) {
++ /* some servers require RFC1001 sessinit before sending
++ negprot - BB check reconnection in case where second
++ sessinit is sent but no second negprot */
++ struct rfc1002_session_packet * ses_init_buf;
++ struct smb_hdr * smb_buf;
++ ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
++ if(ses_init_buf) {
++ ses_init_buf->trailer.session_req.called_len = 32;
++ rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
++ DEFAULT_CIFS_CALLED_NAME,16);
++ ses_init_buf->trailer.session_req.calling_len = 32;
++ /* calling name ends in null (byte 16) from old smb
++ convention. */
++ if(netbios_name && (netbios_name[0] !=0)) {
++ rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
++ netbios_name,16);
++ } else {
++ rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
++ "LINUX_CIFS_CLNT",16);
++ }
++ ses_init_buf->trailer.session_req.scope1 = 0;
++ ses_init_buf->trailer.session_req.scope2 = 0;
++ smb_buf = (struct smb_hdr *)ses_init_buf;
++ /* sizeof RFC1002_SESSION_REQUEST with no scope */
++ smb_buf->smb_buf_length = 0x81000044;
++ rc = smb_send(*csocket, smb_buf, 0x44,
++ (struct sockaddr *)psin_server);
++ kfree(ses_init_buf);
++ }
++ /* else the negprot may still work without this
++ even though malloc failed */
++
++ }
++
++ return rc;
++}
++
++static int
++ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
++{
++ int rc = 0;
++ int connected = 0;
++
++ if(*csocket == NULL) {
++ rc = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
++ if (rc < 0) {
++ cERROR(1, ("Error %d creating ipv6 socket",rc));
++ *csocket = NULL;
++ return rc;
++ } else {
++ /* BB other socket options to set KEEPALIVE, NODELAY? */
++ cFYI(1,("ipv6 Socket created"));
++ (*csocket)->sk->allocation = GFP_NOFS;
++ }
++ }
++
++ psin_server->sin6_family = AF_INET6;
++
++ if(psin_server->sin6_port) { /* user overrode default port */
++ rc = (*csocket)->ops->connect(*csocket,
++ (struct sockaddr *) psin_server,
++ sizeof (struct sockaddr_in6),0);
++ if (rc >= 0)
++ connected = 1;
++ }
++
++ if(!connected) {
++ /* do not retry on the same port we just failed on */
++ if(psin_server->sin6_port != htons(CIFS_PORT)) {
++ psin_server->sin6_port = htons(CIFS_PORT);
++
++ rc = (*csocket)->ops->connect(*csocket,
++ (struct sockaddr *) psin_server,
++ sizeof (struct sockaddr_in6),0);
++ if (rc >= 0)
++ connected = 1;
++ }
++ }
++ if (!connected) {
++ psin_server->sin6_port = htons(RFC1001_PORT);
++ rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
++ psin_server, sizeof (struct sockaddr_in6),0);
++ if (rc >= 0)
++ connected = 1;
++ }
++
++ /* give up here - unless we want to retry on different
++ protocol families some day */
++ if (!connected) {
++ cFYI(1,("Error %d connecting to server via ipv6",rc));
++ sock_release(*csocket);
++ *csocket = NULL;
++ return rc;
++ }
++ /* Eventually check for other socket options to change from
++ the default. sock_setsockopt not used because it expects
++ user space buffer */
++ (*csocket)->sk->rcvtimeo = 7 * HZ;
++
++ return rc;
++}
++
++int
++cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
++ char *mount_data, const char *devname)
++{
++ int rc = 0;
++ int xid;
++ struct socket *csocket = NULL;
++ struct sockaddr_in sin_server;
++ struct sockaddr_in6 sin_server6;
++ struct smb_vol volume_info;
++ struct cifsSesInfo *pSesInfo = NULL;
++ struct cifsSesInfo *existingCifsSes = NULL;
++ struct cifsTconInfo *tcon = NULL;
++ struct TCP_Server_Info *srvTcp = NULL;
++
++ xid = GetXid();
++
++ cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); /* BB removeme BB fixme */
++
++ memset(&volume_info,0,sizeof(struct smb_vol));
++ if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
++ if(volume_info.UNC)
++ kfree(volume_info.UNC);
++ if(volume_info.password)
++ kfree(volume_info.password);
++ FreeXid(xid);
++ return -EINVAL;
++ }
++
++ if (volume_info.username) {
++ cFYI(1, ("Username: %s ", volume_info.username));
++
++ } else {
++ cifserror("No username specified ");
++ /* In userspace mount helper we can get user name from alternate
++ locations such as env variables and files on disk */
++ if(volume_info.UNC)
++ kfree(volume_info.UNC);
++ if(volume_info.password)
++ kfree(volume_info.password);
++ FreeXid(xid);
++ return -EINVAL;
++ }
++
++ if (volume_info.UNCip && volume_info.UNC) {
++ rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
++
++ if(rc == 0) {
++ /* not ipv4 address, try ipv6 */
++ rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
++ }
++
++ if(rc != 1) {
++ /* we failed translating address */
++ if(volume_info.UNC)
++ kfree(volume_info.UNC);
++ if(volume_info.password)
++ kfree(volume_info.password);
++ FreeXid(xid);
++ return -EINVAL;
++ }
++
++ cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
++ /* success */
++ rc = 0;
++ } else if (volume_info.UNCip){
++ /* BB using ip addr as server name connect to the DFS root below */
++ cERROR(1,("Connecting to DFS root not implemented yet"));
++ if(volume_info.UNC)
++ kfree(volume_info.UNC);
++ if(volume_info.password)
++ kfree(volume_info.password);
++ FreeXid(xid);
++ return -EINVAL;
++ } else /* which servers DFS root would we conect to */ {
++ cERROR(1,
++ ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
++ if(volume_info.UNC)
++ kfree(volume_info.UNC);
++ if(volume_info.password)
++ kfree(volume_info.password);
++ FreeXid(xid);
++ return -EINVAL;
++ }
++
++ /* this is needed for ASCII cp to Unicode converts */
++ if(volume_info.iocharset == NULL) {
++ cifs_sb->local_nls = load_nls_default();
++ /* load_nls_default can not return null */
++ } else {
++ cifs_sb->local_nls = load_nls(volume_info.iocharset);
++ if(cifs_sb->local_nls == NULL) {
++ cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
++ if(volume_info.UNC)
++ kfree(volume_info.UNC);
++ if(volume_info.password)
++ kfree(volume_info.password);
++ FreeXid(xid);
++ return -ELIBACC;
++ }
++ }
++
++ existingCifsSes =
++ cifs_find_tcp_session(sin_server.sin_addr.s_addr,
++ volume_info.username, &srvTcp);
++ if (srvTcp) {
++ cFYI(1, ("Existing tcp session with server found "));
++ } else { /* create socket */
++ if(volume_info.port)
++ sin_server.sin_port = htons(volume_info.port);
++ else
++ sin_server.sin_port = 0;
++ rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
++ if (rc < 0) {
++ cERROR(1,
++ ("Error connecting to IPv4 socket. Aborting operation"));
++ if(csocket != NULL)
++ sock_release(csocket);
++ if(volume_info.UNC)
++ kfree(volume_info.UNC);
++ if(volume_info.password)
++ kfree(volume_info.password);
++ FreeXid(xid);
++ return rc;
++ }
++
++ srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
++ if (srvTcp == NULL) {
++ rc = -ENOMEM;
++ sock_release(csocket);
++ if(volume_info.UNC)
++ kfree(volume_info.UNC);
++ if(volume_info.password)
++ kfree(volume_info.password);
++ FreeXid(xid);
++ return rc;
++ } else {
++ memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
++ memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
++ atomic_set(&srvTcp->inFlight,0);
++ /* BB Add code for ipv6 case too */
++ srvTcp->ssocket = csocket;
++ srvTcp->protocolType = IPV4;
++ init_waitqueue_head(&srvTcp->response_q);
++ init_waitqueue_head(&srvTcp->request_q);
++ INIT_LIST_HEAD(&srvTcp->pending_mid_q);
++ /* at this point we are the only ones with the pointer
++ to the struct since the kernel thread not created yet
++ so no need to spinlock this init of tcpStatus */
++ srvTcp->tcpStatus = CifsNew;
++ init_MUTEX(&srvTcp->tcpSem);
++ kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
++ CLONE_FS | CLONE_FILES | CLONE_VM);
++ memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
++ }
++ }
++
++ if (existingCifsSes) {
++ pSesInfo = existingCifsSes;
++ cFYI(1, ("Existing smb sess found "));
++ if(volume_info.password)
++ kfree(volume_info.password);
++ /* volume_info.UNC freed at end of function */
++ } else if (!rc) {
++ cFYI(1, ("Existing smb sess not found "));
++ pSesInfo = sesInfoAlloc();
++ if (pSesInfo == NULL)
++ rc = -ENOMEM;
++ else {
++ pSesInfo->server = srvTcp;
++ sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
++ NIPQUAD(sin_server.sin_addr.s_addr));
++ }
++
++ if (!rc){
++ /* volume_info.password freed at unmount */
++ if (volume_info.password)
++ pSesInfo->password = volume_info.password;
++ if (volume_info.username)
++ strncpy(pSesInfo->userName,
++ volume_info.username,MAX_USERNAME_SIZE);
++ if (volume_info.domainname)
++ strncpy(pSesInfo->domainName,
++ volume_info.domainname,MAX_USERNAME_SIZE);
++ pSesInfo->linux_uid = volume_info.linux_uid;
++ down(&pSesInfo->sesSem);
++ rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
++ up(&pSesInfo->sesSem);
++ if(!rc)
++ atomic_inc(&srvTcp->socketUseCount);
++ } else
++ if(volume_info.password)
++ kfree(volume_info.password);
++ }
++
++ /* search for existing tcon to this server share */
++ if (!rc) {
++ if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
++ cifs_sb->rsize = volume_info.rsize;
++ else
++ cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
++ if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
++ cifs_sb->wsize = volume_info.wsize;
++ else
++ cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
++ if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
++ cifs_sb->rsize = PAGE_CACHE_SIZE;
++ cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
++ }
++ cifs_sb->mnt_uid = volume_info.linux_uid;
++ cifs_sb->mnt_gid = volume_info.linux_gid;
++ cifs_sb->mnt_file_mode = volume_info.file_mode;
++ cifs_sb->mnt_dir_mode = volume_info.dir_mode;
++ cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
++ tcon =
++ find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
++ volume_info.username);
++ if (tcon) {
++ cFYI(1, ("Found match on UNC path "));
++ /* we can have only one retry value for a connection
++ to a share so for resources mounted more than once
++ to the same server share the last value passed in
++ for the retry flag is used */
++ tcon->retry = volume_info.retry;
++ } else {
++ tcon = tconInfoAlloc();
++ if (tcon == NULL)
++ rc = -ENOMEM;
++ else {
++ /* check for null share name ie connect to dfs root */
++
++ /* BB check if this works for exactly length three strings */
++ if ((strchr(volume_info.UNC + 3, '\\') == NULL)
++ && (strchr(volume_info.UNC + 3, '/') ==
++ NULL)) {
++ rc = connect_to_dfs_path(xid,
++ pSesInfo,
++ "",
++ cifs_sb->
++ local_nls);
++ if(volume_info.UNC)
++ kfree(volume_info.UNC);
++ FreeXid(xid);
++ return -ENODEV;
++ } else {
++ rc = CIFSTCon(xid, pSesInfo,
++ volume_info.UNC,
++ tcon, cifs_sb->local_nls);
++ cFYI(1, ("CIFS Tcon rc = %d", rc));
++ }
++ if (!rc) {
++ atomic_inc(&pSesInfo->inUse);
++ tcon->retry = volume_info.retry;
++ }
++ }
++ }
++ }
++ if(pSesInfo) {
++ if (pSesInfo->capabilities & CAP_LARGE_FILES) {
++ sb->s_maxbytes = (u64) 1 << 63;
++ } else
++ sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
++ }
++
++/* on error free sesinfo and tcon struct if needed */
++ if (rc) {
++ /* if session setup failed, use count is zero but
++ we still need to free cifsd thread */
++ if(atomic_read(&srvTcp->socketUseCount) == 0) {
++ spin_lock(&GlobalMid_Lock);
++ srvTcp->tcpStatus = CifsExiting;
++ spin_unlock(&GlobalMid_Lock);
++ if(srvTcp->tsk)
++ send_sig(SIGKILL,srvTcp->tsk,1);
++ }
++ /* If find_unc succeeded then rc == 0 so we can not end */
++ if (tcon) /* up accidently freeing someone elses tcon struct */
++ tconInfoFree(tcon);
++ if (existingCifsSes == 0) {
++ if (pSesInfo) {
++ if ((pSesInfo->server) &&
++ (pSesInfo->status == CifsGood)) {
++ int temp_rc;
++ temp_rc = CIFSSMBLogoff(xid, pSesInfo);
++ /* if the socketUseCount is now zero */
++ if((temp_rc == -ESHUTDOWN) &&
++ (pSesInfo->server->tsk))
++ send_sig(SIGKILL,pSesInfo->server->tsk,1);
++ } else
++ cFYI(1, ("No session or bad tcon"));
++ sesInfoFree(pSesInfo);
++ /* pSesInfo = NULL; */
++ }
++ }
++ } else {
++ atomic_inc(&tcon->useCount);
++ cifs_sb->tcon = tcon;
++ tcon->ses = pSesInfo;
++
++ /* do not care if following two calls succeed - informational only */
++ CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls);
++ CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls);
++ if (tcon->ses->capabilities & CAP_UNIX)
++ CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls);
++ }
++
++ /* volume_info.password is freed above when existing session found
++ (in which case it is not needed anymore) but when new sesion is created
++ the password ptr is put in the new session structure (in which case the
++ password will be freed at unmount time) */
++ if(volume_info.UNC)
++ kfree(volume_info.UNC);
++ FreeXid(xid);
++ return rc;
++}
++
++static int
++CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
++ char session_key[CIFS_SESSION_KEY_SIZE],
++ const struct nls_table *nls_codepage)
++{
++ struct smb_hdr *smb_buffer;
++ struct smb_hdr *smb_buffer_response;
++ SESSION_SETUP_ANDX *pSMB;
++ SESSION_SETUP_ANDX *pSMBr;
++ char *bcc_ptr;
++ char *user = ses->userName;
++ char *domain = ses->domainName;
++ int rc = 0;
++ int remaining_words = 0;
++ int bytes_returned = 0;
++ int len;
++
++ cFYI(1, ("In sesssetup "));
++
++ smb_buffer = cifs_buf_get();
++ if (smb_buffer == 0) {
++ return -ENOMEM;
++ }
++ smb_buffer_response = smb_buffer;
++ pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
++
++ /* send SMBsessionSetup here */
++ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
++ NULL /* no tCon exists yet */ , 13 /* wct */ );
++
++ pSMB->req_no_secext.AndXCommand = 0xFF;
++ pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
++ pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
++
++ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
++ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
++
++ pSMB->req_no_secext.Capabilities =
++ CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
++ if (ses->capabilities & CAP_UNICODE) {
++ smb_buffer->Flags2 |= SMBFLG2_UNICODE;
++ pSMB->req_no_secext.Capabilities |= CAP_UNICODE;
++ }
++ if (ses->capabilities & CAP_STATUS32) {
++ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
++ pSMB->req_no_secext.Capabilities |= CAP_STATUS32;
++ }
++ if (ses->capabilities & CAP_DFS) {
++ smb_buffer->Flags2 |= SMBFLG2_DFS;
++ pSMB->req_no_secext.Capabilities |= CAP_DFS;
++ }
++ pSMB->req_no_secext.Capabilities =
++ cpu_to_le32(pSMB->req_no_secext.Capabilities);
++ /* pSMB->req_no_secext.CaseInsensitivePasswordLength =
++ CIFS_SESSION_KEY_SIZE; */
++ pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
++ pSMB->req_no_secext.CaseSensitivePasswordLength =
++ cpu_to_le16(CIFS_SESSION_KEY_SIZE);
++ bcc_ptr = pByteArea(smb_buffer);
++ /* memcpy(bcc_ptr, (char *) lm_session_key, CIFS_SESSION_KEY_SIZE);
++ bcc_ptr += CIFS_SESSION_KEY_SIZE; */
++ memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
++ bcc_ptr += CIFS_SESSION_KEY_SIZE;
++
++ if (ses->capabilities & CAP_UNICODE) {
++ if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
++ *bcc_ptr = 0;
++ bcc_ptr++;
++ }
++ if(user == NULL)
++ bytes_returned = 0; /* skill null user */
++ else
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
++ nls_codepage);
++ bcc_ptr += 2 * bytes_returned; /* convert num 16 bit words to bytes */
++ bcc_ptr += 2; /* trailing null */
++ if (domain == NULL)
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr,
++ "CIFS_LINUX_DOM", 32, nls_codepage);
++ else
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
++ nls_codepage);
++ bcc_ptr += 2 * bytes_returned;
++ bcc_ptr += 2;
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
++ 32, nls_codepage);
++ bcc_ptr += 2 * bytes_returned;
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
++ nls_codepage);
++ bcc_ptr += 2 * bytes_returned;
++ bcc_ptr += 2;
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
++ 64, nls_codepage);
++ bcc_ptr += 2 * bytes_returned;
++ bcc_ptr += 2;
++ } else {
++ if(user != NULL) {
++ strncpy(bcc_ptr, user, 200);
++ bcc_ptr += strnlen(user, 200);
++ }
++ *bcc_ptr = 0;
++ bcc_ptr++;
++ if (domain == NULL) {
++ strcpy(bcc_ptr, "CIFS_LINUX_DOM");
++ bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
++ } else {
++ strncpy(bcc_ptr, domain, 64);
++ bcc_ptr += strnlen(domain, 64);
++ *bcc_ptr = 0;
++ bcc_ptr++;
++ }
++ strcpy(bcc_ptr, "Linux version ");
++ bcc_ptr += strlen("Linux version ");
++ strcpy(bcc_ptr, UTS_RELEASE);
++ bcc_ptr += strlen(UTS_RELEASE) + 1;
++ strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
++ bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
++ }
++ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
++ smb_buffer->smb_buf_length += BCC(smb_buffer);
++ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
++
++ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
++ &bytes_returned, 1);
++ if (rc) {
++/* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
++ } else if ((smb_buffer_response->WordCount == 3)
++ || (smb_buffer_response->WordCount == 4)) {
++ pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
++ if (pSMBr->resp.Action & GUEST_LOGIN)
++ cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
++ if (ses) {
++ ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
++ cFYI(1, ("UID = %d ", ses->Suid));
++ /* response can have either 3 or 4 word count - Samba sends 3 */
++ bcc_ptr = pByteArea(smb_buffer_response);
++ if ((pSMBr->resp.hdr.WordCount == 3)
++ || ((pSMBr->resp.hdr.WordCount == 4)
++ && (pSMBr->resp.SecurityBlobLength <
++ pSMBr->resp.ByteCount))) {
++ if (pSMBr->resp.hdr.WordCount == 4)
++ bcc_ptr +=
++ pSMBr->resp.SecurityBlobLength;
++
++ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
++ if ((long) (bcc_ptr) % 2) {
++ remaining_words =
++ (BCC(smb_buffer_response)
++ - 1) / 2;
++ bcc_ptr++; /* Unicode strings must be word aligned */
++ } else {
++ remaining_words =
++ BCC
++ (smb_buffer_response) / 2;
++ }
++ len =
++ UniStrnlen((wchar_t *) bcc_ptr,
++ remaining_words - 1);
++/* We look for obvious messed up bcc or strings in response so we do not go off
++ the end since (at least) WIN2K and Windows XP have a major bug in not null
++ terminating last Unicode string in response */
++ ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
++ cifs_strfromUCS_le(ses->serverOS,
++ (wchar_t *)bcc_ptr, len,nls_codepage);
++ bcc_ptr += 2 * (len + 1);
++ remaining_words -= len + 1;
++ ses->serverOS[2 * len] = 0;
++ ses->serverOS[1 + (2 * len)] = 0;
++ if (remaining_words > 0) {
++ len = UniStrnlen((wchar_t *)bcc_ptr,
++ remaining_words
++ - 1);
++ ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
++ cifs_strfromUCS_le(ses->serverNOS,
++ (wchar_t *)bcc_ptr,len,nls_codepage);
++ bcc_ptr += 2 * (len + 1);
++ ses->serverNOS[2 * len] = 0;
++ ses->serverNOS[1 + (2 * len)] = 0;
++ remaining_words -= len + 1;
++ if (remaining_words > 0) {
++ len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
++ /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
++ ses->serverDomain =
++ cifs_kcalloc(2*(len+1),GFP_KERNEL);
++ cifs_strfromUCS_le(ses->serverDomain,
++ (wchar_t *)bcc_ptr,len,nls_codepage);
++ bcc_ptr += 2 * (len + 1);
++ ses->serverDomain[2*len] = 0;
++ ses->serverDomain[1+(2*len)] = 0;
++ } /* else no more room so create dummy domain string */
++ else
++ ses->serverDomain =
++ cifs_kcalloc(2,
++ GFP_KERNEL);
++ } else { /* no room so create dummy domain and NOS string */
++ ses->serverDomain =
++ cifs_kcalloc(2, GFP_KERNEL);
++ ses->serverNOS =
++ cifs_kcalloc(2, GFP_KERNEL);
++ }
++ } else { /* ASCII */
++ len = strnlen(bcc_ptr, 1024);
++ if (((long) bcc_ptr + len) - (long)
++ pByteArea(smb_buffer_response)
++ <= BCC(smb_buffer_response)) {
++ ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
++ strncpy(ses->serverOS,bcc_ptr, len);
++
++ bcc_ptr += len;
++ bcc_ptr[0] = 0; /* null terminate the string */
++ bcc_ptr++;
++
++ len = strnlen(bcc_ptr, 1024);
++ ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
++ strncpy(ses->serverNOS, bcc_ptr, len);
++ bcc_ptr += len;
++ bcc_ptr[0] = 0;
++ bcc_ptr++;
++
++ len = strnlen(bcc_ptr, 1024);
++ ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
++ strncpy(ses->serverDomain, bcc_ptr, len);
++ bcc_ptr += len;
++ bcc_ptr[0] = 0;
++ bcc_ptr++;
++ } else
++ cFYI(1,
++ ("Variable field of length %d extends beyond end of smb ",
++ len));
++ }
++ } else {
++ cERROR(1,
++ (" Security Blob Length extends beyond end of SMB"));
++ }
++ } else {
++ cERROR(1, ("No session structure passed in."));
++ }
++ } else {
++ cERROR(1,
++ (" Invalid Word count %d: ",
++ smb_buffer_response->WordCount));
++ rc = -EIO;
++ }
++
++ if (smb_buffer)
++ cifs_buf_release(smb_buffer);
++
++ return rc;
++}
++
++static int
++CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
++ char *SecurityBlob,int SecurityBlobLength,
++ const struct nls_table *nls_codepage)
++{
++ struct smb_hdr *smb_buffer;
++ struct smb_hdr *smb_buffer_response;
++ SESSION_SETUP_ANDX *pSMB;
++ SESSION_SETUP_ANDX *pSMBr;
++ char *bcc_ptr;
++ char *user = ses->userName;
++ char *domain = ses->domainName;
++ int rc = 0;
++ int remaining_words = 0;
++ int bytes_returned = 0;
++ int len;
++
++ cFYI(1, ("In spnego sesssetup "));
++
++ smb_buffer = cifs_buf_get();
++ if (smb_buffer == 0) {
++ return -ENOMEM;
++ }
++ smb_buffer_response = smb_buffer;
++ pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
++
++ /* send SMBsessionSetup here */
++ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
++ NULL /* no tCon exists yet */ , 12 /* wct */ );
++ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
++ pSMB->req.AndXCommand = 0xFF;
++ pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
++ pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
++
++ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
++ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
++
++ pSMB->req.Capabilities =
++ CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
++ CAP_EXTENDED_SECURITY;
++ if (ses->capabilities & CAP_UNICODE) {
++ smb_buffer->Flags2 |= SMBFLG2_UNICODE;
++ pSMB->req.Capabilities |= CAP_UNICODE;
++ }
++ if (ses->capabilities & CAP_STATUS32) {
++ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
++ pSMB->req.Capabilities |= CAP_STATUS32;
++ }
++ if (ses->capabilities & CAP_DFS) {
++ smb_buffer->Flags2 |= SMBFLG2_DFS;
++ pSMB->req.Capabilities |= CAP_DFS;
++ }
++ pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
++
++ pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
++ bcc_ptr = pByteArea(smb_buffer);
++ memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
++ bcc_ptr += SecurityBlobLength;
++
++ if (ses->capabilities & CAP_UNICODE) {
++ if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
++ *bcc_ptr = 0;
++ bcc_ptr++;
++ }
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
++ bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
++ bcc_ptr += 2; /* trailing null */
++ if (domain == NULL)
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr,
++ "CIFS_LINUX_DOM", 32, nls_codepage);
++ else
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
++ nls_codepage);
++ bcc_ptr += 2 * bytes_returned;
++ bcc_ptr += 2;
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
++ 32, nls_codepage);
++ bcc_ptr += 2 * bytes_returned;
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
++ nls_codepage);
++ bcc_ptr += 2 * bytes_returned;
++ bcc_ptr += 2;
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
++ 64, nls_codepage);
++ bcc_ptr += 2 * bytes_returned;
++ bcc_ptr += 2;
++ } else {
++ strncpy(bcc_ptr, user, 200);
++ bcc_ptr += strnlen(user, 200);
++ *bcc_ptr = 0;
++ bcc_ptr++;
++ if (domain == NULL) {
++ strcpy(bcc_ptr, "CIFS_LINUX_DOM");
++ bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
++ } else {
++ strncpy(bcc_ptr, domain, 64);
++ bcc_ptr += strnlen(domain, 64);
++ *bcc_ptr = 0;
++ bcc_ptr++;
++ }
++ strcpy(bcc_ptr, "Linux version ");
++ bcc_ptr += strlen("Linux version ");
++ strcpy(bcc_ptr, UTS_RELEASE);
++ bcc_ptr += strlen(UTS_RELEASE) + 1;
++ strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
++ bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
++ }
++ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
++ smb_buffer->smb_buf_length += BCC(smb_buffer);
++ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
++
++ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
++ &bytes_returned, 1);
++ if (rc) {
++/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
++ } else if ((smb_buffer_response->WordCount == 3)
++ || (smb_buffer_response->WordCount == 4)) {
++ pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
++ pSMBr->resp.SecurityBlobLength =
++ le16_to_cpu(pSMBr->resp.SecurityBlobLength);
++ if (pSMBr->resp.Action & GUEST_LOGIN)
++ cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
++ if (ses) {
++ ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
++ cFYI(1, ("UID = %d ", ses->Suid));
++ bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
++
++ /* BB Fix below to make endian neutral !! */
++
++ if ((pSMBr->resp.hdr.WordCount == 3)
++ || ((pSMBr->resp.hdr.WordCount == 4)
++ && (pSMBr->resp.SecurityBlobLength <
++ pSMBr->resp.ByteCount))) {
++ if (pSMBr->resp.hdr.WordCount == 4) {
++ bcc_ptr +=
++ pSMBr->resp.SecurityBlobLength;
++ cFYI(1,
++ ("Security Blob Length %d ",
++ pSMBr->resp.SecurityBlobLength));
++ }
++
++ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
++ if ((long) (bcc_ptr) % 2) {
++ remaining_words =
++ (BCC(smb_buffer_response)
++ - 1) / 2;
++ bcc_ptr++; /* Unicode strings must be word aligned */
++ } else {
++ remaining_words =
++ BCC
++ (smb_buffer_response) / 2;
++ }
++ len =
++ UniStrnlen((wchar_t *) bcc_ptr,
++ remaining_words - 1);
++/* We look for obvious messed up bcc or strings in response so we do not go off
++ the end since (at least) WIN2K and Windows XP have a major bug in not null
++ terminating last Unicode string in response */
++ ses->serverOS =
++ cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
++ cifs_strfromUCS_le(ses->serverOS,
++ (wchar_t *)
++ bcc_ptr, len,
++ nls_codepage);
++ bcc_ptr += 2 * (len + 1);
++ remaining_words -= len + 1;
++ ses->serverOS[2 * len] = 0;
++ ses->serverOS[1 + (2 * len)] = 0;
++ if (remaining_words > 0) {
++ len = UniStrnlen((wchar_t *)bcc_ptr,
++ remaining_words
++ - 1);
++ ses->serverNOS =
++ cifs_kcalloc(2 * (len + 1),
++ GFP_KERNEL);
++ cifs_strfromUCS_le(ses->serverNOS,
++ (wchar_t *)bcc_ptr,
++ len,
++ nls_codepage);
++ bcc_ptr += 2 * (len + 1);
++ ses->serverNOS[2 * len] = 0;
++ ses->serverNOS[1 + (2 * len)] = 0;
++ remaining_words -= len + 1;
++ if (remaining_words > 0) {
++ len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
++ /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
++ ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
++ cifs_strfromUCS_le(ses->serverDomain,
++ (wchar_t *)bcc_ptr,
++ len,
++ nls_codepage);
++ bcc_ptr += 2*(len+1);
++ ses->serverDomain[2*len] = 0;
++ ses->serverDomain[1+(2*len)] = 0;
++ } /* else no more room so create dummy domain string */
++ else
++ ses->serverDomain =
++ cifs_kcalloc(2,GFP_KERNEL);
++ } else { /* no room so create dummy domain and NOS string */
++ ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
++ ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
++ }
++ } else { /* ASCII */
++
++ len = strnlen(bcc_ptr, 1024);
++ if (((long) bcc_ptr + len) - (long)
++ pByteArea(smb_buffer_response)
++ <= BCC(smb_buffer_response)) {
++ ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
++ strncpy(ses->serverOS, bcc_ptr, len);
++
++ bcc_ptr += len;
++ bcc_ptr[0] = 0; /* null terminate the string */
++ bcc_ptr++;
++
++ len = strnlen(bcc_ptr, 1024);
++ ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
++ strncpy(ses->serverNOS, bcc_ptr, len);
++ bcc_ptr += len;
++ bcc_ptr[0] = 0;
++ bcc_ptr++;
++
++ len = strnlen(bcc_ptr, 1024);
++ ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
++ strncpy(ses->serverDomain, bcc_ptr, len);
++ bcc_ptr += len;
++ bcc_ptr[0] = 0;
++ bcc_ptr++;
++ } else
++ cFYI(1,
++ ("Variable field of length %d extends beyond end of smb ",
++ len));
++ }
++ } else {
++ cERROR(1,
++ (" Security Blob Length extends beyond end of SMB"));
++ }
++ } else {
++ cERROR(1, ("No session structure passed in."));
++ }
++ } else {
++ cERROR(1,
++ (" Invalid Word count %d: ",
++ smb_buffer_response->WordCount));
++ rc = -EIO;
++ }
++
++ if (smb_buffer)
++ cifs_buf_release(smb_buffer);
++
++ return rc;
++}
++
++static int
++CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
++ struct cifsSesInfo *ses, int * pNTLMv2_flag,
++ const struct nls_table *nls_codepage)
++{
++ struct smb_hdr *smb_buffer;
++ struct smb_hdr *smb_buffer_response;
++ SESSION_SETUP_ANDX *pSMB;
++ SESSION_SETUP_ANDX *pSMBr;
++ char *bcc_ptr;
++ char *domain = ses->domainName;
++ int rc = 0;
++ int remaining_words = 0;
++ int bytes_returned = 0;
++ int len;
++ int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
++ PNEGOTIATE_MESSAGE SecurityBlob;
++ PCHALLENGE_MESSAGE SecurityBlob2;
++
++ cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
++ *pNTLMv2_flag = FALSE;
++ smb_buffer = cifs_buf_get();
++ if (smb_buffer == 0) {
++ return -ENOMEM;
++ }
++ smb_buffer_response = smb_buffer;
++ pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
++ pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
++
++ /* send SMBsessionSetup here */
++ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
++ NULL /* no tCon exists yet */ , 12 /* wct */ );
++ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
++ pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
++
++ pSMB->req.AndXCommand = 0xFF;
++ pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
++ pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
++
++ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
++ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
++
++ pSMB->req.Capabilities =
++ CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
++ CAP_EXTENDED_SECURITY;
++ if (ses->capabilities & CAP_UNICODE) {
++ smb_buffer->Flags2 |= SMBFLG2_UNICODE;
++ pSMB->req.Capabilities |= CAP_UNICODE;
++ }
++ if (ses->capabilities & CAP_STATUS32) {
++ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
++ pSMB->req.Capabilities |= CAP_STATUS32;
++ }
++ if (ses->capabilities & CAP_DFS) {
++ smb_buffer->Flags2 |= SMBFLG2_DFS;
++ pSMB->req.Capabilities |= CAP_DFS;
++ }
++ pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
++
++ bcc_ptr = (char *) &pSMB->req.SecurityBlob;
++ SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
++ strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
++ SecurityBlob->MessageType = NtLmNegotiate;
++ SecurityBlob->NegotiateFlags =
++ NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
++ NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
++ /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
++ if(sign_CIFS_PDUs)
++ SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
++ if(ntlmv2_support)
++ SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
++ /* setup pointers to domain name and workstation name */
++ bcc_ptr += SecurityBlobLength;
++
++ SecurityBlob->WorkstationName.Buffer = 0;
++ SecurityBlob->WorkstationName.Length = 0;
++ SecurityBlob->WorkstationName.MaximumLength = 0;
++
++ if (domain == NULL) {
++ SecurityBlob->DomainName.Buffer = 0;
++ SecurityBlob->DomainName.Length = 0;
++ SecurityBlob->DomainName.MaximumLength = 0;
++ } else {
++ SecurityBlob->NegotiateFlags |=
++ NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
++ strncpy(bcc_ptr, domain, 63);
++ SecurityBlob->DomainName.Length = strnlen(domain, 64);
++ SecurityBlob->DomainName.MaximumLength =
++ cpu_to_le16(SecurityBlob->DomainName.Length);
++ SecurityBlob->DomainName.Buffer =
++ cpu_to_le32((long) &SecurityBlob->
++ DomainString -
++ (long) &SecurityBlob->Signature);
++ bcc_ptr += SecurityBlob->DomainName.Length;
++ SecurityBlobLength += SecurityBlob->DomainName.Length;
++ SecurityBlob->DomainName.Length =
++ cpu_to_le16(SecurityBlob->DomainName.Length);
++ }
++ if (ses->capabilities & CAP_UNICODE) {
++ if ((long) bcc_ptr % 2) {
++ *bcc_ptr = 0;
++ bcc_ptr++;
++ }
++
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
++ 32, nls_codepage);
++ bcc_ptr += 2 * bytes_returned;
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
++ nls_codepage);
++ bcc_ptr += 2 * bytes_returned;
++ bcc_ptr += 2; /* null terminate Linux version */
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
++ 64, nls_codepage);
++ bcc_ptr += 2 * bytes_returned;
++ *(bcc_ptr + 1) = 0;
++ *(bcc_ptr + 2) = 0;
++ bcc_ptr += 2; /* null terminate network opsys string */
++ *(bcc_ptr + 1) = 0;
++ *(bcc_ptr + 2) = 0;
++ bcc_ptr += 2; /* null domain */
++ } else { /* ASCII */
++ strcpy(bcc_ptr, "Linux version ");
++ bcc_ptr += strlen("Linux version ");
++ strcpy(bcc_ptr, UTS_RELEASE);
++ bcc_ptr += strlen(UTS_RELEASE) + 1;
++ strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
++ bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
++ bcc_ptr++; /* empty domain field */
++ *bcc_ptr = 0;
++ }
++ SecurityBlob->NegotiateFlags =
++ cpu_to_le32(SecurityBlob->NegotiateFlags);
++ pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
++ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
++ smb_buffer->smb_buf_length += BCC(smb_buffer);
++ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
++
++ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
++ &bytes_returned, 1);
++
++ if (smb_buffer_response->Status.CifsError ==
++ (NT_STATUS_MORE_PROCESSING_REQUIRED))
++ rc = 0;
++
++ if (rc) {
++/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
++ } else if ((smb_buffer_response->WordCount == 3)
++ || (smb_buffer_response->WordCount == 4)) {
++ pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
++ pSMBr->resp.SecurityBlobLength =
++ le16_to_cpu(pSMBr->resp.SecurityBlobLength);
++ if (pSMBr->resp.Action & GUEST_LOGIN)
++ cFYI(1, (" Guest login"));
++ /* Do we want to set anything in SesInfo struct when guest login? */
++
++ bcc_ptr = pByteArea(smb_buffer_response);
++ /* response can have either 3 or 4 word count - Samba sends 3 */
++
++ SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
++ if (SecurityBlob2->MessageType != NtLmChallenge) {
++ cFYI(1,
++ ("Unexpected NTLMSSP message type received %d",
++ SecurityBlob2->MessageType));
++ } else if (ses) {
++ ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
++ cFYI(1, ("UID = %d ", ses->Suid));
++ if ((pSMBr->resp.hdr.WordCount == 3)
++ || ((pSMBr->resp.hdr.WordCount == 4)
++ && (pSMBr->resp.SecurityBlobLength <
++ pSMBr->resp.ByteCount))) {
++ if (pSMBr->resp.hdr.WordCount == 4) {
++ bcc_ptr +=
++ pSMBr->resp.SecurityBlobLength;
++ cFYI(1,
++ ("Security Blob Length %d ",
++ pSMBr->resp.SecurityBlobLength));
++ }
++
++ cFYI(1, ("NTLMSSP Challenge rcvd "));
++
++ memcpy(ses->server->cryptKey,
++ SecurityBlob2->Challenge,
++ CIFS_CRYPTO_KEY_SIZE);
++ if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2)
++ *pNTLMv2_flag = TRUE;
++
++ if((SecurityBlob2->NegotiateFlags &
++ NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
++ || (sign_CIFS_PDUs > 1))
++ ses->server->secMode |=
++ SECMODE_SIGN_REQUIRED;
++ if ((SecurityBlob2->NegotiateFlags &
++ NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs))
++ ses->server->secMode |=
++ SECMODE_SIGN_ENABLED;
++
++ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
++ if ((long) (bcc_ptr) % 2) {
++ remaining_words =
++ (BCC(smb_buffer_response)
++ - 1) / 2;
++ bcc_ptr++; /* Unicode strings must be word aligned */
++ } else {
++ remaining_words =
++ BCC
++ (smb_buffer_response) / 2;
++ }
++ len =
++ UniStrnlen((wchar_t *) bcc_ptr,
++ remaining_words - 1);
++/* We look for obvious messed up bcc or strings in response so we do not go off
++ the end since (at least) WIN2K and Windows XP have a major bug in not null
++ terminating last Unicode string in response */
++ ses->serverOS =
++ cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
++ cifs_strfromUCS_le(ses->serverOS,
++ (wchar_t *)
++ bcc_ptr, len,
++ nls_codepage);
++ bcc_ptr += 2 * (len + 1);
++ remaining_words -= len + 1;
++ ses->serverOS[2 * len] = 0;
++ ses->serverOS[1 + (2 * len)] = 0;
++ if (remaining_words > 0) {
++ len = UniStrnlen((wchar_t *)
++ bcc_ptr,
++ remaining_words
++ - 1);
++ ses->serverNOS =
++ cifs_kcalloc(2 * (len + 1),
++ GFP_KERNEL);
++ cifs_strfromUCS_le(ses->
++ serverNOS,
++ (wchar_t *)
++ bcc_ptr,
++ len,
++ nls_codepage);
++ bcc_ptr += 2 * (len + 1);
++ ses->serverNOS[2 * len] = 0;
++ ses->serverNOS[1 +
++ (2 * len)] = 0;
++ remaining_words -= len + 1;
++ if (remaining_words > 0) {
++ len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
++ /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
++ ses->serverDomain =
++ cifs_kcalloc(2 *
++ (len +
++ 1),
++ GFP_KERNEL);
++ cifs_strfromUCS_le
++ (ses->
++ serverDomain,
++ (wchar_t *)
++ bcc_ptr, len,
++ nls_codepage);
++ bcc_ptr +=
++ 2 * (len + 1);
++ ses->
++ serverDomain[2
++ * len]
++ = 0;
++ ses->
++ serverDomain[1
++ +
++ (2
++ *
++ len)]
++ = 0;
++ } /* else no more room so create dummy domain string */
++ else
++ ses->serverDomain =
++ cifs_kcalloc(2,
++ GFP_KERNEL);
++ } else { /* no room so create dummy domain and NOS string */
++ ses->serverDomain =
++ cifs_kcalloc(2, GFP_KERNEL);
++ ses->serverNOS =
++ cifs_kcalloc(2, GFP_KERNEL);
++ }
++ } else { /* ASCII */
++ len = strnlen(bcc_ptr, 1024);
++ if (((long) bcc_ptr + len) - (long)
++ pByteArea(smb_buffer_response)
++ <= BCC(smb_buffer_response)) {
++ ses->serverOS =
++ cifs_kcalloc(len + 1,
++ GFP_KERNEL);
++ strncpy(ses->serverOS,
++ bcc_ptr, len);
++
++ bcc_ptr += len;
++ bcc_ptr[0] = 0; /* null terminate string */
++ bcc_ptr++;
++
++ len = strnlen(bcc_ptr, 1024);
++ ses->serverNOS =
++ cifs_kcalloc(len + 1,
++ GFP_KERNEL);
++ strncpy(ses->serverNOS, bcc_ptr, len);
++ bcc_ptr += len;
++ bcc_ptr[0] = 0;
++ bcc_ptr++;
++
++ len = strnlen(bcc_ptr, 1024);
++ ses->serverDomain =
++ cifs_kcalloc(len + 1,
++ GFP_KERNEL);
++ strncpy(ses->serverDomain, bcc_ptr, len);
++ bcc_ptr += len;
++ bcc_ptr[0] = 0;
++ bcc_ptr++;
++ } else
++ cFYI(1,
++ ("Variable field of length %d extends beyond end of smb ",
++ len));
++ }
++ } else {
++ cERROR(1,
++ (" Security Blob Length extends beyond end of SMB"));
++ }
++ } else {
++ cERROR(1, ("No session structure passed in."));
++ }
++ } else {
++ cERROR(1,
++ (" Invalid Word count %d: ",
++ smb_buffer_response->WordCount));
++ rc = -EIO;
++ }
++
++ if (smb_buffer)
++ cifs_buf_release(smb_buffer);
++
++ return rc;
++}
++
++static int
++CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
++ char *ntlm_session_key, int ntlmv2_flag,
++ const struct nls_table *nls_codepage)
++{
++ struct smb_hdr *smb_buffer;
++ struct smb_hdr *smb_buffer_response;
++ SESSION_SETUP_ANDX *pSMB;
++ SESSION_SETUP_ANDX *pSMBr;
++ char *bcc_ptr;
++ char *user = ses->userName;
++ char *domain = ses->domainName;
++ int rc = 0;
++ int remaining_words = 0;
++ int bytes_returned = 0;
++ int len;
++ int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
++ PAUTHENTICATE_MESSAGE SecurityBlob;
++
++ cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
++
++ smb_buffer = cifs_buf_get();
++ if (smb_buffer == 0) {
++ return -ENOMEM;
++ }
++ smb_buffer_response = smb_buffer;
++ pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
++ pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
++
++ /* send SMBsessionSetup here */
++ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
++ NULL /* no tCon exists yet */ , 12 /* wct */ );
++ pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
++ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
++ pSMB->req.AndXCommand = 0xFF;
++ pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
++ pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
++
++ pSMB->req.hdr.Uid = ses->Suid;
++
++ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
++ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
++
++ pSMB->req.Capabilities =
++ CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
++ CAP_EXTENDED_SECURITY;
++ if (ses->capabilities & CAP_UNICODE) {
++ smb_buffer->Flags2 |= SMBFLG2_UNICODE;
++ pSMB->req.Capabilities |= CAP_UNICODE;
++ }
++ if (ses->capabilities & CAP_STATUS32) {
++ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
++ pSMB->req.Capabilities |= CAP_STATUS32;
++ }
++ if (ses->capabilities & CAP_DFS) {
++ smb_buffer->Flags2 |= SMBFLG2_DFS;
++ pSMB->req.Capabilities |= CAP_DFS;
++ }
++ pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
++
++ bcc_ptr = (char *) &pSMB->req.SecurityBlob;
++ SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
++ strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
++ SecurityBlob->MessageType = NtLmAuthenticate;
++ bcc_ptr += SecurityBlobLength;
++ SecurityBlob->NegotiateFlags =
++ NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
++ NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
++ 0x80000000 | NTLMSSP_NEGOTIATE_128;
++ if(sign_CIFS_PDUs)
++ SecurityBlob->NegotiateFlags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
++ if(ntlmv2_flag)
++ SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
++
++/* setup pointers to domain name and workstation name */
++
++ SecurityBlob->WorkstationName.Buffer = 0;
++ SecurityBlob->WorkstationName.Length = 0;
++ SecurityBlob->WorkstationName.MaximumLength = 0;
++ SecurityBlob->SessionKey.Length = 0;
++ SecurityBlob->SessionKey.MaximumLength = 0;
++ SecurityBlob->SessionKey.Buffer = 0;
++
++ SecurityBlob->LmChallengeResponse.Length = 0;
++ SecurityBlob->LmChallengeResponse.MaximumLength = 0;
++ SecurityBlob->LmChallengeResponse.Buffer = 0;
++
++ SecurityBlob->NtChallengeResponse.Length =
++ cpu_to_le16(CIFS_SESSION_KEY_SIZE);
++ SecurityBlob->NtChallengeResponse.MaximumLength =
++ cpu_to_le16(CIFS_SESSION_KEY_SIZE);
++ memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
++ SecurityBlob->NtChallengeResponse.Buffer =
++ cpu_to_le32(SecurityBlobLength);
++ SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
++ bcc_ptr += CIFS_SESSION_KEY_SIZE;
++
++ if (ses->capabilities & CAP_UNICODE) {
++ if (domain == NULL) {
++ SecurityBlob->DomainName.Buffer = 0;
++ SecurityBlob->DomainName.Length = 0;
++ SecurityBlob->DomainName.MaximumLength = 0;
++ } else {
++ SecurityBlob->DomainName.Length =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
++ nls_codepage);
++ SecurityBlob->DomainName.Length *= 2;
++ SecurityBlob->DomainName.MaximumLength =
++ cpu_to_le16(SecurityBlob->DomainName.Length);
++ SecurityBlob->DomainName.Buffer =
++ cpu_to_le32(SecurityBlobLength);
++ bcc_ptr += SecurityBlob->DomainName.Length;
++ SecurityBlobLength += SecurityBlob->DomainName.Length;
++ SecurityBlob->DomainName.Length =
++ cpu_to_le16(SecurityBlob->DomainName.Length);
++ }
++ if (user == NULL) {
++ SecurityBlob->UserName.Buffer = 0;
++ SecurityBlob->UserName.Length = 0;
++ SecurityBlob->UserName.MaximumLength = 0;
++ } else {
++ SecurityBlob->UserName.Length =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
++ nls_codepage);
++ SecurityBlob->UserName.Length *= 2;
++ SecurityBlob->UserName.MaximumLength =
++ cpu_to_le16(SecurityBlob->UserName.Length);
++ SecurityBlob->UserName.Buffer =
++ cpu_to_le32(SecurityBlobLength);
++ bcc_ptr += SecurityBlob->UserName.Length;
++ SecurityBlobLength += SecurityBlob->UserName.Length;
++ SecurityBlob->UserName.Length =
++ cpu_to_le16(SecurityBlob->UserName.Length);
++ }
++
++ /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
++ SecurityBlob->WorkstationName.Length *= 2;
++ SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
++ SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
++ bcc_ptr += SecurityBlob->WorkstationName.Length;
++ SecurityBlobLength += SecurityBlob->WorkstationName.Length;
++ SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
++
++ if ((long) bcc_ptr % 2) {
++ *bcc_ptr = 0;
++ bcc_ptr++;
++ }
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
++ 32, nls_codepage);
++ bcc_ptr += 2 * bytes_returned;
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
++ nls_codepage);
++ bcc_ptr += 2 * bytes_returned;
++ bcc_ptr += 2; /* null term version string */
++ bytes_returned =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
++ 64, nls_codepage);
++ bcc_ptr += 2 * bytes_returned;
++ *(bcc_ptr + 1) = 0;
++ *(bcc_ptr + 2) = 0;
++ bcc_ptr += 2; /* null terminate network opsys string */
++ *(bcc_ptr + 1) = 0;
++ *(bcc_ptr + 2) = 0;
++ bcc_ptr += 2; /* null domain */
++ } else { /* ASCII */
++ if (domain == NULL) {
++ SecurityBlob->DomainName.Buffer = 0;
++ SecurityBlob->DomainName.Length = 0;
++ SecurityBlob->DomainName.MaximumLength = 0;
++ } else {
++ SecurityBlob->NegotiateFlags |=
++ NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
++ strncpy(bcc_ptr, domain, 63);
++ SecurityBlob->DomainName.Length = strnlen(domain, 64);
++ SecurityBlob->DomainName.MaximumLength =
++ cpu_to_le16(SecurityBlob->DomainName.Length);
++ SecurityBlob->DomainName.Buffer =
++ cpu_to_le32(SecurityBlobLength);
++ bcc_ptr += SecurityBlob->DomainName.Length;
++ SecurityBlobLength += SecurityBlob->DomainName.Length;
++ SecurityBlob->DomainName.Length =
++ cpu_to_le16(SecurityBlob->DomainName.Length);
++ }
++ if (user == NULL) {
++ SecurityBlob->UserName.Buffer = 0;
++ SecurityBlob->UserName.Length = 0;
++ SecurityBlob->UserName.MaximumLength = 0;
++ } else {
++ strncpy(bcc_ptr, user, 63);
++ SecurityBlob->UserName.Length = strnlen(user, 64);
++ SecurityBlob->UserName.MaximumLength =
++ cpu_to_le16(SecurityBlob->UserName.Length);
++ SecurityBlob->UserName.Buffer =
++ cpu_to_le32(SecurityBlobLength);
++ bcc_ptr += SecurityBlob->UserName.Length;
++ SecurityBlobLength += SecurityBlob->UserName.Length;
++ SecurityBlob->UserName.Length =
++ cpu_to_le16(SecurityBlob->UserName.Length);
++ }
++ /* BB fill in our workstation name if known BB */
++
++ strcpy(bcc_ptr, "Linux version ");
++ bcc_ptr += strlen("Linux version ");
++ strcpy(bcc_ptr, UTS_RELEASE);
++ bcc_ptr += strlen(UTS_RELEASE) + 1;
++ strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
++ bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
++ bcc_ptr++; /* null domain */
++ *bcc_ptr = 0;
++ }
++ SecurityBlob->NegotiateFlags =
++ cpu_to_le32(SecurityBlob->NegotiateFlags);
++ pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
++ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
++ smb_buffer->smb_buf_length += BCC(smb_buffer);
++ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
++
++ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
++ &bytes_returned, 1);
++ if (rc) {
++/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
++ } else if ((smb_buffer_response->WordCount == 3)
++ || (smb_buffer_response->WordCount == 4)) {
++ pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
++ pSMBr->resp.SecurityBlobLength =
++ le16_to_cpu(pSMBr->resp.SecurityBlobLength);
++ if (pSMBr->resp.Action & GUEST_LOGIN)
++ cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
++/* if(SecurityBlob2->MessageType != NtLm??){
++ cFYI("Unexpected message type on auth response is %d "));
++ } */
++ if (ses) {
++ cFYI(1,
++ ("Does UID on challenge %d match auth response UID %d ",
++ ses->Suid, smb_buffer_response->Uid));
++ ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
++ bcc_ptr = pByteArea(smb_buffer_response);
++ /* response can have either 3 or 4 word count - Samba sends 3 */
++ if ((pSMBr->resp.hdr.WordCount == 3)
++ || ((pSMBr->resp.hdr.WordCount == 4)
++ && (pSMBr->resp.SecurityBlobLength <
++ pSMBr->resp.ByteCount))) {
++ if (pSMBr->resp.hdr.WordCount == 4) {
++ bcc_ptr +=
++ pSMBr->resp.SecurityBlobLength;
++ cFYI(1,
++ ("Security Blob Length %d ",
++ pSMBr->resp.SecurityBlobLength));
++ }
++
++ cFYI(1,
++ ("NTLMSSP response to Authenticate "));
++
++ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
++ if ((long) (bcc_ptr) % 2) {
++ remaining_words =
++ (BCC(smb_buffer_response)
++ - 1) / 2;
++ bcc_ptr++; /* Unicode strings must be word aligned */
++ } else {
++ remaining_words = BCC(smb_buffer_response) / 2;
++ }
++ len =
++ UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
++/* We look for obvious messed up bcc or strings in response so we do not go off
++ the end since (at least) WIN2K and Windows XP have a major bug in not null
++ terminating last Unicode string in response */
++ ses->serverOS =
++ cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
++ cifs_strfromUCS_le(ses->serverOS,
++ (wchar_t *)
++ bcc_ptr, len,
++ nls_codepage);
++ bcc_ptr += 2 * (len + 1);
++ remaining_words -= len + 1;
++ ses->serverOS[2 * len] = 0;
++ ses->serverOS[1 + (2 * len)] = 0;
++ if (remaining_words > 0) {
++ len = UniStrnlen((wchar_t *)
++ bcc_ptr,
++ remaining_words
++ - 1);
++ ses->serverNOS =
++ cifs_kcalloc(2 * (len + 1),
++ GFP_KERNEL);
++ cifs_strfromUCS_le(ses->
++ serverNOS,
++ (wchar_t *)
++ bcc_ptr,
++ len,
++ nls_codepage);
++ bcc_ptr += 2 * (len + 1);
++ ses->serverNOS[2 * len] = 0;
++ ses->serverNOS[1+(2*len)] = 0;
++ remaining_words -= len + 1;
++ if (remaining_words > 0) {
++ len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
++ /* last string not always null terminated (e.g. for Windows XP & 2000) */
++ ses->serverDomain =
++ cifs_kcalloc(2 *
++ (len +
++ 1),
++ GFP_KERNEL);
++ cifs_strfromUCS_le
++ (ses->
++ serverDomain,
++ (wchar_t *)
++ bcc_ptr, len,
++ nls_codepage);
++ bcc_ptr +=
++ 2 * (len + 1);
++ ses->
++ serverDomain[2
++ * len]
++ = 0;
++ ses->
++ serverDomain[1
++ +
++ (2
++ *
++ len)]
++ = 0;
++ } /* else no more room so create dummy domain string */
++ else
++ ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
++ } else { /* no room so create dummy domain and NOS string */
++ ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
++ ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
++ }
++ } else { /* ASCII */
++ len = strnlen(bcc_ptr, 1024);
++ if (((long) bcc_ptr + len) -
++ (long) pByteArea(smb_buffer_response)
++ <= BCC(smb_buffer_response)) {
++ ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
++ strncpy(ses->serverOS,bcc_ptr, len);
++
++ bcc_ptr += len;
++ bcc_ptr[0] = 0; /* null terminate the string */
++ bcc_ptr++;
++
++ len = strnlen(bcc_ptr, 1024);
++ ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
++ strncpy(ses->serverNOS, bcc_ptr, len);
++ bcc_ptr += len;
++ bcc_ptr[0] = 0;
++ bcc_ptr++;
++
++ len = strnlen(bcc_ptr, 1024);
++ ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
++ strncpy(ses->serverDomain, bcc_ptr, len);
++ bcc_ptr += len;
++ bcc_ptr[0] = 0;
++ bcc_ptr++;
++ } else
++ cFYI(1,
++ ("Variable field of length %d extends beyond end of smb ",
++ len));
++ }
++ } else {
++ cERROR(1,
++ (" Security Blob Length extends beyond end of SMB"));
++ }
++ } else {
++ cERROR(1, ("No session structure passed in."));
++ }
++ } else {
++ cERROR(1,
++ (" Invalid Word count %d: ",
++ smb_buffer_response->WordCount));
++ rc = -EIO;
++ }
++
++ if (smb_buffer)
++ cifs_buf_release(smb_buffer);
++
++ return rc;
++}
++
++int
++CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
++ const char *tree, struct cifsTconInfo *tcon,
++ const struct nls_table *nls_codepage)
++{
++ struct smb_hdr *smb_buffer;
++ struct smb_hdr *smb_buffer_response;
++ TCONX_REQ *pSMB;
++ TCONX_RSP *pSMBr;
++ char *bcc_ptr;
++ int rc = 0;
++ int length;
++
++ if (ses == NULL)
++ return -EIO;
++
++ smb_buffer = cifs_buf_get();
++ if (smb_buffer == 0) {
++ return -ENOMEM;
++ }
++ smb_buffer_response = smb_buffer;
++
++ header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
++ NULL /*no tid */ , 4 /*wct */ );
++ smb_buffer->Uid = ses->Suid;
++ pSMB = (TCONX_REQ *) smb_buffer;
++ pSMBr = (TCONX_RSP *) smb_buffer_response;
++
++ pSMB->AndXCommand = 0xFF;
++ pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
++ pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
++ bcc_ptr = &(pSMB->Password[0]);
++ bcc_ptr++; /* skip password */
++
++ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
++ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
++
++ if (ses->capabilities & CAP_STATUS32) {
++ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
++ }
++ if (ses->capabilities & CAP_DFS) {
++ smb_buffer->Flags2 |= SMBFLG2_DFS;
++ }
++ if (ses->capabilities & CAP_UNICODE) {
++ smb_buffer->Flags2 |= SMBFLG2_UNICODE;
++ length =
++ cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
++ bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
++ bcc_ptr += 2; /* skip trailing null */
++ } else { /* ASCII */
++
++ strcpy(bcc_ptr, tree);
++ bcc_ptr += strlen(tree) + 1;
++ }
++ strcpy(bcc_ptr, "?????");
++ bcc_ptr += strlen("?????");
++ bcc_ptr += 1;
++ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
++ smb_buffer->smb_buf_length += BCC(smb_buffer);
++ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
++
++ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
++
++ /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
++ /* above now done in SendReceive */
++ if ((rc == 0) && (tcon != NULL)) {
++ tcon->tidStatus = CifsGood;
++ tcon->tid = smb_buffer_response->Tid;
++ bcc_ptr = pByteArea(smb_buffer_response);
++ length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
++ /* skip service field (NB: this field is always ASCII) */
++ bcc_ptr += length + 1;
++ strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
++ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
++ length = UniStrnlen((wchar_t *) bcc_ptr, 512);
++ if (((long) bcc_ptr + (2 * length)) -
++ (long) pByteArea(smb_buffer_response) <=
++ BCC(smb_buffer_response)) {
++ if(tcon->nativeFileSystem)
++ kfree(tcon->nativeFileSystem);
++ tcon->nativeFileSystem =
++ cifs_kcalloc(length + 2, GFP_KERNEL);
++ cifs_strfromUCS_le(tcon->nativeFileSystem,
++ (wchar_t *) bcc_ptr,
++ length, nls_codepage);
++ bcc_ptr += 2 * length;
++ bcc_ptr[0] = 0; /* null terminate the string */
++ bcc_ptr[1] = 0;
++ bcc_ptr += 2;
++ }
++ /* else do not bother copying these informational fields */
++ } else {
++ length = strnlen(bcc_ptr, 1024);
++ if (((long) bcc_ptr + length) -
++ (long) pByteArea(smb_buffer_response) <=
++ BCC(smb_buffer_response)) {
++ if(tcon->nativeFileSystem)
++ kfree(tcon->nativeFileSystem);
++ tcon->nativeFileSystem =
++ cifs_kcalloc(length + 1, GFP_KERNEL);
++ strncpy(tcon->nativeFileSystem, bcc_ptr,
++ length);
++ }
++ /* else do not bother copying these informational fields */
++ }
++ tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
++ cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
++ } else if ((rc == 0) && tcon == NULL) {
++ /* all we need to save for IPC$ connection */
++ ses->ipc_tid = smb_buffer_response->Tid;
++ }
++
++ if (smb_buffer)
++ cifs_buf_release(smb_buffer);
++ return rc;
++}
++
++int
++cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
++{
++ int rc = 0;
++ int xid;
++ struct cifsSesInfo *ses = NULL;
++ struct task_struct *cifsd_task;
++
++ xid = GetXid();
++
++ if (cifs_sb->tcon) {
++ ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
++ rc = CIFSSMBTDis(xid, cifs_sb->tcon);
++ if (rc == -EBUSY) {
++ FreeXid(xid);
++ return 0;
++ }
++ tconInfoFree(cifs_sb->tcon);
++ if ((ses) && (ses->server)) {
++ /* save off task so we do not refer to ses later */
++ cifsd_task = ses->server->tsk;
++ cFYI(1, ("About to do SMBLogoff "));
++ rc = CIFSSMBLogoff(xid, ses);
++ if (rc == -EBUSY) {
++ FreeXid(xid);
++ return 0;
++ } else if (rc == -ESHUTDOWN) {
++ cFYI(1,("Waking up socket by sending it signal"));
++ send_sig(SIGKILL,cifsd_task,1);
++ rc = 0;
++ } /* else - we have an smb session
++ left on this socket do not kill cifsd */
++ } else
++ cFYI(1, ("No session or bad tcon"));
++ }
++
++ cifs_sb->tcon = NULL;
++ if (ses) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(HZ / 2);
++ }
++ if (ses)
++ sesInfoFree(ses);
++
++ FreeXid(xid);
++ return rc; /* BB check if we should always return zero here */
++}
++
++int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
++ struct nls_table * nls_info)
++{
++ int rc = 0;
++ char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
++ int ntlmv2_flag = FALSE;
++
++ /* what if server changes its buffer size after dropping the session? */
++ if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
++ rc = CIFSSMBNegotiate(xid, pSesInfo);
++ if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
++ rc = CIFSSMBNegotiate(xid, pSesInfo);
++ if(rc == -EAGAIN)
++ rc = -EHOSTDOWN;
++ }
++ if(rc == 0) {
++ spin_lock(&GlobalMid_Lock);
++ if(pSesInfo->server->tcpStatus != CifsExiting)
++ pSesInfo->server->tcpStatus = CifsGood;
++ else
++ rc = -EHOSTDOWN;
++ spin_unlock(&GlobalMid_Lock);
++
++ }
++ }
++ if (!rc) {
++ pSesInfo->capabilities = pSesInfo->server->capabilities;
++ if(linuxExtEnabled == 0)
++ pSesInfo->capabilities &= (~CAP_UNIX);
++ pSesInfo->sequence_number = 0;
++ cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
++ pSesInfo->server->secMode,
++ pSesInfo->server->capabilities,
++ pSesInfo->server->timeZone));
++ if (extended_security
++ && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
++ && (pSesInfo->server->secType == NTLMSSP)) {
++ cFYI(1, ("New style sesssetup "));
++ rc = CIFSSpnegoSessSetup(xid, pSesInfo,
++ NULL /* security blob */,
++ 0 /* blob length */,
++ nls_info);
++ } else if (extended_security
++ && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
++ && (pSesInfo->server->secType == RawNTLMSSP)) {
++ cFYI(1, ("NTLMSSP sesssetup "));
++ rc = CIFSNTLMSSPNegotiateSessSetup(xid,
++ pSesInfo,
++ &ntlmv2_flag,
++ nls_info);
++ if (!rc) {
++ if(ntlmv2_flag) {
++ char * v2_response;
++ cFYI(1,("Can use more secure NTLM version 2 password hash"));
++ CalcNTLMv2_partial_mac_key(pSesInfo,
++ nls_info);
++ v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
++ if(v2_response) {
++ CalcNTLMv2_response(pSesInfo,v2_response);
++/* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
++ kfree(v2_response);
++ /* BB Put dummy sig in SessSetup PDU? */
++ } else
++ rc = -ENOMEM;
++
++ } else {
++ SMBNTencrypt(pSesInfo->password,
++ pSesInfo->server->cryptKey,
++ ntlm_session_key);
++
++ cifs_calculate_mac_key(pSesInfo->mac_signing_key,
++ ntlm_session_key,
++ pSesInfo->password);
++ }
++ /* for better security the weaker lanman hash not sent
++ in AuthSessSetup so we no longer calculate it */
++
++ rc = CIFSNTLMSSPAuthSessSetup(xid,
++ pSesInfo,
++ ntlm_session_key,
++ ntlmv2_flag,
++ nls_info);
++ }
++ } else { /* old style NTLM 0.12 session setup */
++ SMBNTencrypt(pSesInfo->password,
++ pSesInfo->server->cryptKey,
++ ntlm_session_key);
++
++ cifs_calculate_mac_key(pSesInfo->mac_signing_key,
++ ntlm_session_key, pSesInfo->password);
++ rc = CIFSSessSetup(xid, pSesInfo,
++ ntlm_session_key, nls_info);
++ }
++ if (rc) {
++ cERROR(1,("Send error in SessSetup = %d",rc));
++ } else {
++ cFYI(1,("CIFS Session Established successfully"));
++ pSesInfo->status = CifsGood;
++ }
++ }
++ return rc;
++}
++
+diff -urN linux-2.4.29.old/fs/cifs/dir.c linux-2.4.29/fs/cifs/dir.c
+--- linux-2.4.29.old/fs/cifs/dir.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/dir.c 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,425 @@
++/*
++ * fs/cifs/dir.c
++ *
++ * vfs operations that deal with dentries
++ *
++ * Copyright (C) International Business Machines Corp., 2002,2003
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <linux/fs.h>
++#include <linux/stat.h>
++#include <linux/slab.h>
++#include "cifsfs.h"
++#include "cifspdu.h"
++#include "cifsglob.h"
++#include "cifsproto.h"
++#include "cifs_debug.h"
++#include "cifs_fs_sb.h"
++
++void
++renew_parental_timestamps(struct dentry *direntry)
++{
++ /* BB check if there is a way to get the kernel to do this or if we really need this */
++ do {
++ direntry->d_time = jiffies;
++ direntry = direntry->d_parent;
++ } while (!IS_ROOT(direntry));
++}
++
++/* Note: caller must free return buffer */
++char *
++build_path_from_dentry(struct dentry *direntry)
++{
++ struct dentry *temp;
++ int namelen = 0;
++ char *full_path;
++
++ if(direntry == NULL)
++ return NULL; /* not much we can do if dentry is freed and
++ we need to reopen the file after it was closed implicitly
++ when the server crashed */
++
++cifs_bp_rename_retry:
++ for (temp = direntry; !IS_ROOT(temp);) {
++ namelen += (1 + temp->d_name.len);
++ temp = temp->d_parent;
++ if(temp == NULL) {
++ cERROR(1,("corrupt dentry"));
++ return NULL;
++ }
++ }
++
++ full_path = kmalloc(namelen+1, GFP_KERNEL);
++ if(full_path == NULL)
++ return full_path;
++ full_path[namelen] = 0; /* trailing null */
++
++ for (temp = direntry; !IS_ROOT(temp);) {
++ namelen -= 1 + temp->d_name.len;
++ if (namelen < 0) {
++ break;
++ } else {
++ full_path[namelen] = '\\';
++ strncpy(full_path + namelen + 1, temp->d_name.name,
++ temp->d_name.len);
++ cFYI(0, (" name: %s ", full_path + namelen));
++ }
++ temp = temp->d_parent;
++ if(temp == NULL) {
++ cERROR(1,("corrupt dentry"));
++ kfree(full_path);
++ return NULL;
++ }
++ }
++ if (namelen != 0) {
++ cERROR(1,
++ ("We did not end path lookup where we expected namelen is %d",
++ namelen));
++ /* presumably this is only possible if we were racing with a rename
++ of one of the parent directories (we can not lock the dentries
++ above us to prevent this, but retrying should be harmless) */
++ kfree(full_path);
++ namelen = 0;
++ goto cifs_bp_rename_retry;
++ }
++
++ return full_path;
++}
++
++/* Note: caller must free return buffer */
++char *
++build_wildcard_path_from_dentry(struct dentry *direntry)
++{
++ struct dentry *temp;
++ int namelen = 0;
++ char *full_path;
++
++ if(direntry == NULL)
++ return NULL; /* not much we can do if dentry is freed and
++ we need to reopen the file after it was closed implicitly
++ when the server crashed */
++
++cifs_bwp_rename_retry:
++ for (temp = direntry; !IS_ROOT(temp);) {
++ namelen += (1 + temp->d_name.len);
++ temp = temp->d_parent;
++ if(temp == NULL) {
++ cERROR(1,("corrupt dentry"));
++ return NULL;
++ }
++ }
++
++ full_path = kmalloc(namelen+3, GFP_KERNEL);
++ if(full_path == NULL)
++ return full_path;
++
++ full_path[namelen] = '\\';
++ full_path[namelen+1] = '*';
++ full_path[namelen+2] = 0; /* trailing null */
++
++ for (temp = direntry; !IS_ROOT(temp);) {
++ namelen -= 1 + temp->d_name.len;
++ if (namelen < 0) {
++ break;
++ } else {
++ full_path[namelen] = '\\';
++ strncpy(full_path + namelen + 1, temp->d_name.name,
++ temp->d_name.len);
++ cFYI(0, (" name: %s ", full_path + namelen));
++ }
++ temp = temp->d_parent;
++ if(temp == NULL) {
++ cERROR(1,("corrupt dentry"));
++ kfree(full_path);
++ return NULL;
++ }
++ }
++ if (namelen != 0) {
++ cERROR(1,
++ ("We did not end path lookup where we expected namelen is %d",
++ namelen));
++ /* presumably this is only possible if we were racing with a rename
++ of one of the parent directories (we can not lock the dentries
++ above us to prevent this, but retrying should be harmless) */
++ kfree(full_path);
++ namelen = 0;
++ goto cifs_bwp_rename_retry;
++ }
++
++ return full_path;
++}
++
++/* Inode operations in similar order to how they appear in the Linux file fs.h */
++
++int
++cifs_create(struct inode *inode, struct dentry *direntry, int mode)
++{
++ int rc = -ENOENT;
++ int xid;
++ int oplock = 0; /* no sense requested oplock if we are just going to
++ immediately close the file */
++ __u16 fileHandle;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ char *full_path = NULL;
++ FILE_ALL_INFO * buf = NULL;
++ struct inode *newinode = NULL;
++
++ xid = GetXid();
++
++ cifs_sb = CIFS_SB(inode->i_sb);
++ pTcon = cifs_sb->tcon;
++
++ down(&direntry->d_sb->s_vfs_rename_sem);
++ full_path = build_path_from_dentry(direntry);
++ up(&direntry->d_sb->s_vfs_rename_sem);
++ if(full_path == NULL) {
++ FreeXid(xid);
++ return -ENOMEM;
++ }
++
++ /* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */
++
++ buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
++ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OVERWRITE_IF,
++ GENERIC_WRITE, CREATE_NOT_DIR,
++ &fileHandle, &oplock, buf, cifs_sb->local_nls);
++ if (rc) {
++ cFYI(1, ("cifs_create returned 0x%x ", rc));
++ } else {
++ /* BB for case of overwriting existing file can we use the inode that was
++ passed in rather than creating new one?? */
++ if (pTcon->ses->capabilities & CAP_UNIX)
++ rc = cifs_get_inode_info_unix(&newinode, full_path,
++ inode->i_sb,xid);
++ else
++ rc = cifs_get_inode_info(&newinode, full_path,
++ buf, inode->i_sb,xid);
++
++ if (rc != 0) {
++ cFYI(1,("Create worked but get_inode_info failed with rc = %d",
++ rc));
++ } else {
++ direntry->d_op = &cifs_dentry_ops;
++ d_instantiate(direntry, newinode);
++ }
++ CIFSSMBClose(xid, pTcon, fileHandle);
++
++ if(newinode) {
++ newinode->i_mode = mode;
++ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
++ CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
++ (__u64)-1,
++ (__u64)-1,
++ 0 /* dev */,
++ cifs_sb->local_nls);
++ else { /* BB implement via Windows security descriptors */
++ /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
++ /* in the meantime could set r/o dos attribute when perms are eg:
++ mode & 0222 == 0 */
++ }
++ }
++ }
++
++ if (buf)
++ kfree(buf);
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++
++ return rc;
++}
++
++int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, int device_number)
++{
++ int rc = -EPERM;
++ int xid;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ char *full_path = NULL;
++ struct inode * newinode = NULL;
++
++ xid = GetXid();
++
++ cifs_sb = CIFS_SB(inode->i_sb);
++ pTcon = cifs_sb->tcon;
++
++ down(&direntry->d_sb->s_vfs_rename_sem);
++ full_path = build_path_from_dentry(direntry);
++ up(&direntry->d_sb->s_vfs_rename_sem);
++ if(full_path == NULL)
++ rc = -ENOMEM;
++
++ if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
++ rc = CIFSSMBUnixSetPerms(xid, pTcon,
++ full_path, mode, current->euid, current->egid,
++ device_number, cifs_sb->local_nls);
++ if(!rc) {
++ rc = cifs_get_inode_info_unix(&newinode, full_path,
++ inode->i_sb,xid);
++ direntry->d_op = &cifs_dentry_ops;
++ if(rc == 0)
++ d_instantiate(direntry, newinode);
++ }
++ }
++
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++
++ return rc;
++}
++
++
++struct dentry *
++cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry)
++{
++ int xid;
++ int rc = 0; /* to get around spurious gcc warning, set to zero here */
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ struct inode *newInode = NULL;
++ char *full_path = NULL;
++
++ xid = GetXid();
++
++ cFYI(1,
++ (" parent inode = 0x%p name is: %s and dentry = 0x%p",
++ parent_dir_inode, direntry->d_name.name, direntry));
++
++ /* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */
++
++ /* check whether path exists */
++
++ cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
++ pTcon = cifs_sb->tcon;
++
++ /* can not grab the rename sem here since it would
++ deadlock in the cases (beginning of sys_rename itself)
++ in which we already have the sb rename sem */
++ full_path = build_path_from_dentry(direntry);
++ if(full_path == NULL) {
++ FreeXid(xid);
++ return ERR_PTR(-ENOMEM);
++ }
++
++ if (direntry->d_inode != NULL) {
++ cFYI(1, (" non-NULL inode in lookup"));
++ } else {
++ cFYI(1, (" NULL inode in lookup"));
++ }
++ cFYI(1,
++ (" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
++
++ if (pTcon->ses->capabilities & CAP_UNIX)
++ rc = cifs_get_inode_info_unix(&newInode, full_path,
++ parent_dir_inode->i_sb,xid);
++ else
++ rc = cifs_get_inode_info(&newInode, full_path, NULL,
++ parent_dir_inode->i_sb,xid);
++
++ if ((rc == 0) && (newInode != NULL)) {
++ direntry->d_op = &cifs_dentry_ops;
++ d_add(direntry, newInode);
++
++ /* since paths are not looked up by component - the parent directories are presumed to be good here */
++ renew_parental_timestamps(direntry);
++
++ } else if (rc == -ENOENT) {
++ rc = 0;
++ d_add(direntry, NULL);
++ } else {
++ cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc));
++ /* BB special case check for Access Denied - watch security
++ exposure of returning dir info implicitly via different rc
++ if file exists or not but no access BB */
++ }
++
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++ return ERR_PTR(rc);
++}
++
++int
++cifs_dir_open(struct inode *inode, struct file *file)
++{ /* NB: currently unused since searches are opened in readdir */
++ int rc = 0;
++ int xid;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ char *full_path = NULL;
++
++ xid = GetXid();
++
++ cifs_sb = CIFS_SB(inode->i_sb);
++ pTcon = cifs_sb->tcon;
++
++ if(file->f_dentry) {
++ down(&file->f_dentry->d_sb->s_vfs_rename_sem);
++ full_path = build_wildcard_path_from_dentry(file->f_dentry);
++ up(&file->f_dentry->d_sb->s_vfs_rename_sem);
++ } else {
++ FreeXid(xid);
++ return -EIO;
++ }
++
++ cFYI(1, ("inode = 0x%p and full path is %s", inode, full_path));
++
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++ return rc;
++}
++
++static int
++cifs_d_revalidate(struct dentry *direntry, int flags)
++{
++ int isValid = 1;
++
++/* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */
++
++ if (direntry->d_inode) {
++ if (cifs_revalidate(direntry)) {
++ /* unlock_kernel(); */
++ return 0;
++ }
++ } else {
++ cFYI(1,
++ ("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p",
++ direntry->d_name.name, direntry));
++ }
++
++/* unlock_kernel(); */
++
++ return isValid;
++}
++
++/* static int cifs_d_delete(struct dentry *direntry)
++{
++ int rc = 0;
++
++ cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name));
++
++ return rc;
++} */
++
++struct dentry_operations cifs_dentry_ops = {
++ .d_revalidate = cifs_d_revalidate,
++/* d_delete: cifs_d_delete, *//* not needed except for debugging */
++ /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */
++};
+diff -urN linux-2.4.29.old/fs/cifs/file.c linux-2.4.29/fs/cifs/file.c
+--- linux-2.4.29.old/fs/cifs/file.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/file.c 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,2185 @@
++/*
++ * fs/cifs/file.c
++ *
++ * vfs operations that deal with files
++ *
++ * Copyright (C) International Business Machines Corp., 2002,2003
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <linux/fs.h>
++#include <linux/stat.h>
++#include <linux/fcntl.h>
++#include <linux/version.h>
++#include <linux/pagemap.h>
++#include <linux/smp_lock.h>
++#include <linux/list.h>
++#include <asm/div64.h>
++#include <linux/mm.h>
++#include <linux/types.h>
++#include "cifsfs.h"
++#include "cifspdu.h"
++#include "cifsglob.h"
++#include "cifsproto.h"
++#include "cifs_unicode.h"
++#include "cifs_debug.h"
++#include "cifs_fs_sb.h"
++
++int
++cifs_open(struct inode *inode, struct file *file)
++{
++ int rc = -EACCES;
++ int xid, oplock;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ struct cifsFileInfo *pCifsFile;
++ struct cifsInodeInfo *pCifsInode;
++ char *full_path = NULL;
++ int desiredAccess = 0x20197;
++ int disposition;
++ __u16 netfid;
++ FILE_ALL_INFO * buf = NULL;
++ time_t temp;
++
++ xid = GetXid();
++
++ cifs_sb = CIFS_SB(inode->i_sb);
++ pTcon = cifs_sb->tcon;
++
++ down(&inode->i_sb->s_vfs_rename_sem);
++ full_path = build_path_from_dentry(file->f_dentry);
++ up(&inode->i_sb->s_vfs_rename_sem);
++ if(full_path == NULL) {
++ FreeXid(xid);
++ return -ENOMEM;
++ }
++
++ cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
++ if ((file->f_flags & O_ACCMODE) == O_RDONLY)
++ desiredAccess = GENERIC_READ;
++ else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
++ desiredAccess = GENERIC_WRITE;
++ else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
++ /* GENERIC_ALL is too much permission to request */
++ /* can cause unnecessary access denied on create */
++ /* desiredAccess = GENERIC_ALL; */
++ desiredAccess = GENERIC_READ | GENERIC_WRITE;
++ }
++
++/*********************************************************************
++ * open flag mapping table:
++ *
++ * POSIX Flag CIFS Disposition
++ * ---------- ----------------
++ * O_CREAT FILE_OPEN_IF
++ * O_CREAT | O_EXCL FILE_CREATE
++ * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
++ * O_TRUNC FILE_OVERWRITE
++ * none of the above FILE_OPEN
++ *
++ * Note that there is not a direct match between disposition
++ * FILE_SUPERSEDE (ie create whether or not file exists although
++ * O_CREAT | O_TRUNC is similar but truncates the existing
++ * file rather than creating a new file as FILE_SUPERSEDE does
++ * (which uses the attributes / metadata passed in on open call)
++ *?
++ *? O_SYNC is a reasonable match to CIFS writethrough flag
++ *? and the read write flags match reasonably. O_LARGEFILE
++ *? is irrelevant because largefile support is always used
++ *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
++ * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
++ *********************************************************************/
++
++ /* For 2.4 case, file was already checked for existence
++ before create by vfs lookup and created in create
++ entry point, we are now just opening the newly
++ created file with the right desiredAccess flags */
++
++ if((file->f_flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
++ disposition = FILE_OPEN_IF;
++ else if((file->f_flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
++ disposition = FILE_OVERWRITE_IF;
++ else if((file->f_flags & O_CREAT) == O_CREAT)
++ disposition = FILE_OPEN_IF;
++ else
++ disposition = FILE_OPEN;
++
++ if (oplockEnabled)
++ oplock = REQ_OPLOCK;
++ else
++ oplock = FALSE;
++
++ /* BB pass O_SYNC flag through on file attributes .. BB */
++
++ /* Also refresh inode by passing in file_info buf returned by SMBOpen
++ and calling get_inode_info with returned buf (at least
++ helps non-Unix server case */
++
++ /* BB we can not do this if this is the second open of a file
++ and the first handle has writebehind data, we might be
++ able to simply do a filemap_fdatawrite/filemap_fdatawait first */
++ buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
++ if(buf==0) {
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++ return -ENOMEM;
++ }
++ rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
++ CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
++ if (rc) {
++ cFYI(1, ("cifs_open returned 0x%x ", rc));
++ cFYI(1, ("oplock: %d ", oplock));
++ } else {
++ file->private_data =
++ kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
++ if (file->private_data) {
++ memset(file->private_data, 0, sizeof(struct cifsFileInfo));
++ pCifsFile = (struct cifsFileInfo *) file->private_data;
++ pCifsFile->netfid = netfid;
++ pCifsFile->pid = current->pid;
++ init_MUTEX(&pCifsFile->fh_sem);
++ pCifsFile->pfile = file; /* needed for writepage */
++ pCifsFile->pInode = inode;
++ pCifsFile->invalidHandle = FALSE;
++ pCifsFile->closePend = FALSE;
++ write_lock(&GlobalSMBSeslock);
++ spin_lock(&files_lock);
++ list_add(&pCifsFile->tlist,&pTcon->openFileList);
++ pCifsInode = CIFS_I(file->f_dentry->d_inode);
++ if(pCifsInode) {
++ /* want handles we can use to read with first */
++ /* in the list so we do not have to walk the */
++ /* list to search for one in prepare_write */
++ if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
++ list_add_tail(&pCifsFile->flist,&pCifsInode->openFileList);
++ } else {
++ list_add(&pCifsFile->flist,&pCifsInode->openFileList);
++ }
++ spin_unlock(&files_lock);
++ write_unlock(&GlobalSMBSeslock);
++ if(pCifsInode->clientCanCacheRead) {
++ /* we have the inode open somewhere else
++ no need to discard cache data */
++ } else {
++ if(buf) {
++ /* BB need same check in cifs_create too? */
++
++ /* if not oplocked, invalidate inode pages if mtime
++ or file size changed */
++ temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
++ if((file->f_dentry->d_inode->i_mtime == temp) &&
++ (file->f_dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) {
++ cFYI(1,("inode unchanged on server"));
++ } else {
++ if(file->f_dentry->d_inode->i_mapping) {
++ /* BB no need to lock inode until after invalidate*/
++ /* since namei code should already have it locked?*/
++ filemap_fdatasync(file->f_dentry->d_inode->i_mapping);
++ }
++ cFYI(1,("invalidating remote inode since open detected it changed"));
++ invalidate_inode_pages(file->f_dentry->d_inode);
++ }
++ }
++ }
++ if (pTcon->ses->capabilities & CAP_UNIX)
++ rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
++ full_path, inode->i_sb,xid);
++ else
++ rc = cifs_get_inode_info(&file->f_dentry->d_inode,
++ full_path, buf, inode->i_sb,xid);
++
++ if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
++ pCifsInode->clientCanCacheAll = TRUE;
++ pCifsInode->clientCanCacheRead = TRUE;
++ cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
++ } else if((oplock & 0xF) == OPLOCK_READ)
++ pCifsInode->clientCanCacheRead = TRUE;
++ } else {
++ spin_unlock(&files_lock);
++ write_unlock(&GlobalSMBSeslock);
++ }
++ if(oplock & CIFS_CREATE_ACTION) {
++ /* time to set mode which we can not set earlier due
++ to problems creating new read-only files */
++ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
++ CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
++ (__u64)-1,
++ (__u64)-1,
++ 0 /* dev */,
++ cifs_sb->local_nls);
++ else {/* BB implement via Windows security descriptors */
++ /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
++ /* in the meantime could set r/o dos attribute when perms are eg:
++ mode & 0222 == 0 */
++ }
++ }
++ }
++ }
++
++ if (buf)
++ kfree(buf);
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++ return rc;
++}
++
++/* Try to reaquire byte range locks that were released when session */
++/* to server was lost */
++static int cifs_relock_file(struct cifsFileInfo * cifsFile)
++{
++ int rc = 0;
++
++/* BB list all locks open on this file and relock */
++
++ return rc;
++}
++
++static int cifs_reopen_file(struct inode *inode, struct file *file, int can_flush)
++{
++ int rc = -EACCES;
++ int xid, oplock;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ struct cifsFileInfo *pCifsFile;
++ struct cifsInodeInfo *pCifsInode;
++ char *full_path = NULL;
++ int desiredAccess = 0x20197;
++ int disposition = FILE_OPEN;
++ __u16 netfid;
++
++ if(inode == NULL)
++ return -EBADF;
++ if (file->private_data) {
++ pCifsFile = (struct cifsFileInfo *) file->private_data;
++ } else
++ return -EBADF;
++
++ xid = GetXid();
++ down(&pCifsFile->fh_sem);
++ if(pCifsFile->invalidHandle == FALSE) {
++ up(&pCifsFile->fh_sem);
++ FreeXid(xid);
++ return 0;
++ }
++
++ if(file->f_dentry == NULL) {
++ up(&pCifsFile->fh_sem);
++ cFYI(1,("failed file reopen, no valid name if dentry freed"));
++ FreeXid(xid);
++ return -EBADF;
++ }
++ cifs_sb = CIFS_SB(inode->i_sb);
++ pTcon = cifs_sb->tcon;
++/* can not grab rename sem here because various ops, including
++those that already have the rename sem can end up causing writepage
++to get called and if the server was down that means we end up here,
++and we can never tell if the caller already has the rename_sem */
++ full_path = build_path_from_dentry(file->f_dentry);
++ if(full_path == NULL) {
++ up(&pCifsFile->fh_sem);
++ FreeXid(xid);
++ return -ENOMEM;
++ }
++
++ cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
++ if ((file->f_flags & O_ACCMODE) == O_RDONLY)
++ desiredAccess = GENERIC_READ;
++ else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
++ desiredAccess = GENERIC_WRITE;
++ else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
++ /* GENERIC_ALL is too much permission to request */
++ /* can cause unnecessary access denied on create */
++ /* desiredAccess = GENERIC_ALL; */
++ desiredAccess = GENERIC_READ | GENERIC_WRITE;
++ }
++
++ if (oplockEnabled)
++ oplock = REQ_OPLOCK;
++ else
++ oplock = FALSE;
++
++
++ /* Can not refresh inode by passing in file_info buf to be returned
++ by SMBOpen and then calling get_inode_info with returned buf
++ since file might have write behind data that needs to be flushed
++ and server version of file size can be stale. If we
++ knew for sure that inode was not dirty locally we could do this */
++
++/* buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
++ if(buf==0) {
++ up(&pCifsFile->fh_sem);
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++ return -ENOMEM;
++ }*/
++ rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
++ CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls);
++ if (rc) {
++ up(&pCifsFile->fh_sem);
++ cFYI(1, ("cifs_open returned 0x%x ", rc));
++ cFYI(1, ("oplock: %d ", oplock));
++ } else {
++ pCifsFile->netfid = netfid;
++ pCifsFile->invalidHandle = FALSE;
++ up(&pCifsFile->fh_sem);
++ pCifsInode = CIFS_I(inode);
++ if(pCifsInode) {
++ if(can_flush) {
++ filemap_fdatasync(inode->i_mapping);
++ filemap_fdatawait(inode->i_mapping);
++ /* temporarily disable caching while we
++ go to server to get inode info */
++ pCifsInode->clientCanCacheAll = FALSE;
++ pCifsInode->clientCanCacheRead = FALSE;
++ if (pTcon->ses->capabilities & CAP_UNIX)
++ rc = cifs_get_inode_info_unix(&inode,
++ full_path, inode->i_sb,xid);
++ else
++ rc = cifs_get_inode_info(&inode,
++ full_path, NULL, inode->i_sb,xid);
++ } /* else we are writing out data to server already
++ and could deadlock if we tried to flush data, and
++ since we do not know if we have data that would
++ invalidate the current end of file on the server
++ we can not go to the server to get the new
++ inod info */
++ if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
++ pCifsInode->clientCanCacheAll = TRUE;
++ pCifsInode->clientCanCacheRead = TRUE;
++ cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
++ } else if((oplock & 0xF) == OPLOCK_READ) {
++ pCifsInode->clientCanCacheRead = TRUE;
++ pCifsInode->clientCanCacheAll = FALSE;
++ } else {
++ pCifsInode->clientCanCacheRead = FALSE;
++ pCifsInode->clientCanCacheAll = FALSE;
++ }
++ cifs_relock_file(pCifsFile);
++ }
++ }
++
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++ return rc;
++}
++
++int
++cifs_close(struct inode *inode, struct file *file)
++{
++ int rc = 0;
++ int xid;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ struct cifsFileInfo *pSMBFile =
++ (struct cifsFileInfo *) file->private_data;
++
++ xid = GetXid();
++
++ cifs_sb = CIFS_SB(inode->i_sb);
++ pTcon = cifs_sb->tcon;
++ if (pSMBFile) {
++ pSMBFile->closePend = TRUE;
++ spin_lock(&files_lock);
++ if(pTcon) {
++ /* no sense reconnecting to close a file that is
++ already closed */
++ if (pTcon->tidStatus != CifsNeedReconnect) {
++ spin_unlock(&files_lock);
++ rc = CIFSSMBClose(xid,pTcon,pSMBFile->netfid);
++ spin_lock(&files_lock);
++ }
++ }
++ list_del(&pSMBFile->flist);
++ list_del(&pSMBFile->tlist);
++ spin_unlock(&files_lock);
++ if(pSMBFile->search_resume_name)
++ kfree(pSMBFile->search_resume_name);
++ kfree(file->private_data);
++ file->private_data = NULL;
++ } else
++ rc = -EBADF;
++
++ if(list_empty(&(CIFS_I(inode)->openFileList))) {
++ cFYI(1,("closing last open instance for inode %p",inode));
++ /* if the file is not open we do not know if we can cache
++ info on this inode, much less write behind and read ahead */
++ CIFS_I(inode)->clientCanCacheRead = FALSE;
++ CIFS_I(inode)->clientCanCacheAll = FALSE;
++ }
++ if((rc ==0) && CIFS_I(inode)->write_behind_rc)
++ rc = CIFS_I(inode)->write_behind_rc;
++ FreeXid(xid);
++ return rc;
++}
++
++int
++cifs_closedir(struct inode *inode, struct file *file)
++{
++ int rc = 0;
++ int xid;
++ struct cifsFileInfo *pSMBFileStruct =
++ (struct cifsFileInfo *) file->private_data;
++
++ cFYI(1, ("Closedir inode = 0x%p with ", inode));
++
++ xid = GetXid();
++
++ if (pSMBFileStruct) {
++ cFYI(1, ("Freeing private data in close dir"));
++ kfree(file->private_data);
++ file->private_data = NULL;
++ }
++ FreeXid(xid);
++ return rc;
++}
++
++int
++cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
++{
++ int rc, xid;
++ __u32 lockType = LOCKING_ANDX_LARGE_FILES;
++ __u32 numLock = 0;
++ __u32 numUnlock = 0;
++ __u64 length;
++ int wait_flag = FALSE;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ length = 1 + pfLock->fl_end - pfLock->fl_start;
++
++ rc = -EACCES;
++
++ xid = GetXid();
++
++ cFYI(1,
++ ("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld",
++ cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
++ pfLock->fl_end));
++
++ if (pfLock->fl_flags & FL_POSIX)
++ cFYI(1, ("Posix "));
++ if (pfLock->fl_flags & FL_FLOCK)
++ cFYI(1, ("Flock "));
++/* if (pfLock->fl_flags & FL_SLEEP) {
++ cFYI(1, ("Blocking lock "));
++ wait_flag = TRUE;
++ } */
++ if (pfLock->fl_flags & FL_ACCESS)
++ cFYI(1, ("Process suspended by mandatory locking - not implemented yet "));
++ if (pfLock->fl_flags & FL_LEASE)
++ cFYI(1, ("Lease on file - not implemented yet"));
++ if (pfLock->fl_flags & (~(FL_POSIX | FL_FLOCK | FL_ACCESS | FL_LEASE)))
++ cFYI(1, ("Unknown lock flags 0x%x",pfLock->fl_flags));
++
++ if (pfLock->fl_type == F_WRLCK) {
++ cFYI(1, ("F_WRLCK "));
++ numLock = 1;
++ } else if (pfLock->fl_type == F_UNLCK) {
++ cFYI(1, ("F_UNLCK "));
++ numUnlock = 1;
++ } else if (pfLock->fl_type == F_RDLCK) {
++ cFYI(1, ("F_RDLCK "));
++ lockType |= LOCKING_ANDX_SHARED_LOCK;
++ numLock = 1;
++ } else if (pfLock->fl_type == F_EXLCK) {
++ cFYI(1, ("F_EXLCK "));
++ numLock = 1;
++ } else if (pfLock->fl_type == F_SHLCK) {
++ cFYI(1, ("F_SHLCK "));
++ lockType |= LOCKING_ANDX_SHARED_LOCK;
++ numLock = 1;
++ } else
++ cFYI(1, ("Unknown type of lock "));
++
++ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++ pTcon = cifs_sb->tcon;
++
++ if (file->private_data == NULL) {
++ FreeXid(xid);
++ return -EBADF;
++ }
++
++ if (IS_GETLK(cmd)) {
++ rc = CIFSSMBLock(xid, pTcon,
++ ((struct cifsFileInfo *) file->
++ private_data)->netfid,
++ length,
++ pfLock->fl_start, 0, 1, lockType,
++ 0 /* wait flag */ );
++ if (rc == 0) {
++ rc = CIFSSMBLock(xid, pTcon,
++ ((struct cifsFileInfo *) file->
++ private_data)->netfid,
++ length,
++ pfLock->fl_start, 1 /* numUnlock */ ,
++ 0 /* numLock */ , lockType,
++ 0 /* wait flag */ );
++ pfLock->fl_type = F_UNLCK;
++ if (rc != 0)
++ cERROR(1,
++ ("Error unlocking previously locked range %d during test of lock ",
++ rc));
++ rc = 0;
++
++ } else {
++ /* if rc == ERR_SHARING_VIOLATION ? */
++ rc = 0; /* do not change lock type to unlock since range in use */
++ }
++
++ FreeXid(xid);
++ return rc;
++ }
++
++ rc = CIFSSMBLock(xid, pTcon,
++ ((struct cifsFileInfo *) file->private_data)->
++ netfid, length,
++ pfLock->fl_start, numUnlock, numLock, lockType,
++ wait_flag);
++ FreeXid(xid);
++ return rc;
++}
++
++ssize_t
++cifs_write(struct file * file, const char *write_data,
++ size_t write_size, loff_t * poffset)
++{
++ int rc = 0;
++ unsigned int bytes_written = 0;
++ unsigned int total_written;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ int xid, long_op;
++ struct cifsFileInfo * open_file;
++
++ if(file->f_dentry == NULL)
++ return -EBADF;
++
++ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++ if(cifs_sb == NULL) {
++ return -EBADF;
++ }
++ pTcon = cifs_sb->tcon;
++
++ /*cFYI(1,
++ (" write %d bytes to offset %lld of %s", write_size,
++ *poffset, file->f_dentry->d_name.name)); */
++
++ if (file->private_data == NULL) {
++ return -EBADF;
++ } else {
++ open_file = (struct cifsFileInfo *) file->private_data;
++ }
++
++ xid = GetXid();
++ if(file->f_dentry->d_inode == NULL) {
++ FreeXid(xid);
++ return -EBADF;
++ }
++
++ if (*poffset > file->f_dentry->d_inode->i_size)
++ long_op = 2; /* writes past end of file can take a long time */
++ else
++ long_op = 1;
++
++ for (total_written = 0; write_size > total_written;
++ total_written += bytes_written) {
++ rc = -EAGAIN;
++ while(rc == -EAGAIN) {
++ if(file->private_data == NULL) {
++ /* file has been closed on us */
++ FreeXid(xid);
++ /* if we have gotten here we have written some data
++ and blocked, and the file has been freed on us
++ while we blocked so return what we managed to write */
++ return total_written;
++ }
++ if(open_file->closePend) {
++ FreeXid(xid);
++ if(total_written)
++ return total_written;
++ else
++ return -EBADF;
++ }
++ if (open_file->invalidHandle) {
++ if((file->f_dentry == NULL) ||
++ (file->f_dentry->d_inode == NULL)) {
++ FreeXid(xid);
++ return total_written;
++ }
++ /* we could deadlock if we called
++ filemap_fdatawait from here so tell
++ reopen_file not to flush data to server now */
++ rc = cifs_reopen_file(file->f_dentry->d_inode,
++ file,FALSE);
++ if(rc != 0)
++ break;
++ }
++
++ rc = CIFSSMBWrite(xid, pTcon,
++ open_file->netfid,
++ write_size - total_written, *poffset,
++ &bytes_written,
++ write_data + total_written, long_op);
++ }
++ if (rc || (bytes_written == 0)) {
++ if (total_written)
++ break;
++ else {
++ FreeXid(xid);
++ return rc;
++ }
++ } else
++ *poffset += bytes_written;
++ long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
++ }
++
++#ifdef CONFIG_CIFS_STATS
++ if(total_written > 0) {
++ atomic_inc(&pTcon->num_writes);
++ spin_lock(&pTcon->stat_lock);
++ pTcon->bytes_written += total_written;
++ spin_unlock(&pTcon->stat_lock);
++ }
++#endif
++
++ /* since the write may have blocked check these pointers again */
++ if(file->f_dentry) {
++ if(file->f_dentry->d_inode) {
++ file->f_dentry->d_inode->i_ctime = file->f_dentry->d_inode->i_mtime =
++ CURRENT_TIME;
++ if (total_written > 0) {
++ if (*poffset > file->f_dentry->d_inode->i_size)
++ file->f_dentry->d_inode->i_size = *poffset;
++ }
++ mark_inode_dirty_sync(file->f_dentry->d_inode);
++ }
++ }
++ FreeXid(xid);
++ return total_written;
++}
++
++static int
++cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
++{
++ struct address_space *mapping = page->mapping;
++ loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
++ char * write_data;
++ int rc = -EFAULT;
++ int bytes_written = 0;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ struct inode *inode;
++ struct cifsInodeInfo *cifsInode;
++ struct cifsFileInfo *open_file = NULL;
++ struct list_head *tmp;
++ struct list_head *tmp1;
++
++ if (!mapping) {
++ return -EFAULT;
++ } else if(!mapping->host) {
++ return -EFAULT;
++ }
++
++ inode = page->mapping->host;
++ cifs_sb = CIFS_SB(inode->i_sb);
++ pTcon = cifs_sb->tcon;
++
++ offset += (loff_t)from;
++ write_data = kmap(page);
++ write_data += from;
++
++ if((to > PAGE_CACHE_SIZE) || (from > to)) {
++ kunmap(page);
++ return -EIO;
++ }
++
++ /* racing with truncate? */
++ if(offset > mapping->host->i_size) {
++ kunmap(page);
++ return 0; /* don't care */
++ }
++
++ /* check to make sure that we are not extending the file */
++ if(mapping->host->i_size - offset < (loff_t)to)
++ to = (unsigned)(mapping->host->i_size - offset);
++
++
++ cifsInode = CIFS_I(mapping->host);
++ read_lock(&GlobalSMBSeslock);
++ /* BB we should start at the end */
++ list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
++ open_file = list_entry(tmp,struct cifsFileInfo, flist);
++ if(open_file->closePend)
++ continue;
++ /* We check if file is open for writing first */
++ if((open_file->pfile) &&
++ ((open_file->pfile->f_flags & O_RDWR) ||
++ (open_file->pfile->f_flags & O_WRONLY))) {
++ read_unlock(&GlobalSMBSeslock);
++ bytes_written = cifs_write(open_file->pfile, write_data,
++ to-from, &offset);
++ read_lock(&GlobalSMBSeslock);
++ /* Does mm or vfs already set times? */
++ inode->i_atime = inode->i_mtime = CURRENT_TIME;
++ if ((bytes_written > 0) && (offset)) {
++ rc = 0;
++ } else if(bytes_written < 0) {
++ if(rc == -EBADF) {
++ /* have seen a case in which
++ kernel seemed to have closed/freed a file
++ even with writes active so we might as well
++ see if there are other file structs to try
++ for the same inode before giving up */
++ continue;
++ } else
++ rc = bytes_written;
++ }
++ break; /* now that we found a valid file handle
++ and tried to write to it we are done, no
++ sense continuing to loop looking for another */
++ }
++ if(tmp->next == NULL) {
++ cFYI(1,("File instance %p removed",tmp));
++ break;
++ }
++ }
++ read_unlock(&GlobalSMBSeslock);
++ if(open_file == NULL) {
++ cFYI(1,("No writeable filehandles for inode"));
++ rc = -EIO;
++ }
++
++ kunmap(page);
++ return rc;
++}
++
++#if 0
++static int
++cifs_writepages(struct address_space *mapping, struct writeback_control *wbc)
++{
++ int rc = -EFAULT;
++ int xid;
++
++ xid = GetXid();
++/* call 16K write then Setpageuptodate */
++ FreeXid(xid);
++ return rc;
++}
++#endif
++
++static int
++cifs_writepage(struct page* page)
++{
++ int rc = -EFAULT;
++ int xid;
++
++ xid = GetXid();
++/* BB add check for wbc flags */
++ page_cache_get(page);
++ if (!Page_Uptodate(page)) {
++ cFYI(1,("ppw - page not up to date"));
++ }
++
++ rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE);
++ SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
++ unlock_page(page);
++#else
++ UnlockPage(page);
++#endif
++ page_cache_release(page);
++ FreeXid(xid);
++ return rc;
++}
++
++static int
++cifs_commit_write(struct file *file, struct page *page, unsigned offset,
++ unsigned to)
++{
++ int xid;
++ int rc = 0;
++ struct inode *inode = page->mapping->host;
++ loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
++ char * page_data;
++
++ xid = GetXid();
++ cFYI(1,("commit write for page %p up to position %lld for %d",page,position,to));
++ if (position > inode->i_size){
++ inode->i_size = position;
++ /*if (file->private_data == NULL) {
++ rc = -EBADF;
++ } else {
++ open_file = (struct cifsFileInfo *)file->private_data;
++ cifs_sb = CIFS_SB(inode->i_sb);
++ rc = -EAGAIN;
++ while(rc == -EAGAIN) {
++ if((open_file->invalidHandle) &&
++ (!open_file->closePend)) {
++ rc = cifs_reopen_file(file->f_dentry->d_inode,file);
++ if(rc != 0)
++ break;
++ }
++ if(!open_file->closePend) {
++ rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon,
++ position, open_file->netfid,
++ open_file->pid,FALSE);
++ } else {
++ rc = -EBADF;
++ break;
++ }
++ }
++ cFYI(1,(" SetEOF (commit write) rc = %d",rc));
++ }*/
++ }
++ if (!Page_Uptodate(page)) {
++ position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
++ /* can not rely on (or let) writepage write this data */
++ if(to < offset) {
++ cFYI(1,("Illegal offsets, can not copy from %d to %d",
++ offset,to));
++ FreeXid(xid);
++ return rc;
++ }
++ /* this is probably better than directly calling
++ partialpage_write since in this function
++ the file handle is known which we might as well
++ leverage */
++ /* BB check if anything else missing out of ppw */
++ /* such as updating last write time */
++ page_data = kmap(page);
++ rc = cifs_write(file, page_data+offset,to-offset,
++ &position);
++ if(rc > 0)
++ rc = 0;
++ /* else if rc < 0 should we set writebehind rc? */
++ kunmap(page);
++ } else {
++ set_page_dirty(page);
++ }
++
++ FreeXid(xid);
++ return rc;
++}
++
++int
++cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
++{
++ int xid;
++ int rc = 0;
++ struct inode * inode = file->f_dentry->d_inode;
++
++ xid = GetXid();
++
++ cFYI(1, ("Sync file - name: %s datasync: 0x%x ",
++ dentry->d_name.name, datasync));
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
++ rc = filemap_fdatasync(inode->i_mapping);
++#else
++ filemap_fdatasync(inode->i_mapping);
++#endif
++ if(rc == 0)
++ CIFS_I(inode)->write_behind_rc = 0;
++ FreeXid(xid);
++ return rc;
++}
++
++static int
++cifs_sync_page(struct page *page)
++{
++ struct address_space *mapping;
++ struct inode *inode;
++ unsigned long index = page->index;
++ unsigned int rpages = 0;
++ int rc = 0;
++
++ cFYI(1,("sync page %p",page));
++ mapping = page->mapping;
++ if (!mapping)
++ return 0;
++ inode = mapping->host;
++ if (!inode)
++ return 0;
++
++/* fill in rpages then
++ result = cifs_pagein_inode(inode, index, rpages); *//* BB finish */
++
++ cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
++
++ if (rc < 0)
++ return rc;
++ return 0;
++}
++
++/*
++ * As file closes, flush all cached write data for this inode checking
++ * for write behind errors.
++ *
++ */
++int cifs_flush(struct file *file)
++{
++ struct inode * inode = file->f_dentry->d_inode;
++ int rc = 0;
++
++ /* Rather than do the steps manually: */
++ /* lock the inode for writing */
++ /* loop through pages looking for write behind data (dirty pages) */
++ /* coalesce into contiguous 16K (or smaller) chunks to write to server */
++ /* send to server (prefer in parallel) */
++ /* deal with writebehind errors */
++ /* unlock inode for writing */
++ /* filemapfdatawrite appears easier for the time being */
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
++ rc = filemap_fdatasync(inode->i_mapping);
++#else
++ filemap_fdatasync(inode->i_mapping);
++#endif
++ if(rc == 0) /* reset wb rc if we were able to write out dirty pages */
++ CIFS_I(inode)->write_behind_rc = 0;
++
++ cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc));
++
++ return rc;
++}
++
++
++ssize_t
++cifs_read(struct file * file, char *read_data, size_t read_size,
++ loff_t * poffset)
++{
++ int rc = -EACCES;
++ unsigned int bytes_read = 0;
++ unsigned int total_read;
++ unsigned int current_read_size;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ int xid;
++ char * current_offset;
++ struct cifsFileInfo * open_file;
++
++ xid = GetXid();
++ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++ pTcon = cifs_sb->tcon;
++
++ if (file->private_data == NULL) {
++ FreeXid(xid);
++ return -EBADF;
++ }
++ open_file = (struct cifsFileInfo *)file->private_data;
++
++ if((file->f_flags & O_ACCMODE) == O_WRONLY) {
++ cFYI(1,("attempting read on write only file instance"));
++ }
++
++ for (total_read = 0,current_offset=read_data; read_size > total_read;
++ total_read += bytes_read,current_offset+=bytes_read) {
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
++ current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
++#else
++ current_read_size = min(read_size - total_read,cifs_sb->rsize);
++#endif
++ rc = -EAGAIN;
++ while(rc == -EAGAIN) {
++ if ((open_file->invalidHandle) && (!open_file->closePend)) {
++ rc = cifs_reopen_file(file->f_dentry->d_inode,
++ file,TRUE);
++ if(rc != 0)
++ break;
++ }
++
++ rc = CIFSSMBRead(xid, pTcon,
++ open_file->netfid,
++ current_read_size, *poffset,
++ &bytes_read, &current_offset);
++ }
++ if (rc || (bytes_read == 0)) {
++ if (total_read) {
++ break;
++ } else {
++ FreeXid(xid);
++ return rc;
++ }
++ } else {
++#ifdef CONFIG_CIFS_STATS
++ atomic_inc(&pTcon->num_reads);
++ spin_lock(&pTcon->stat_lock);
++ pTcon->bytes_read += total_read;
++ spin_unlock(&pTcon->stat_lock);
++#endif
++ *poffset += bytes_read;
++ }
++ }
++ FreeXid(xid);
++ return total_read;
++}
++
++int cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
++{
++ struct dentry * dentry = file->f_dentry;
++ int rc, xid;
++
++ xid = GetXid();
++ rc = cifs_revalidate(dentry);
++ if (rc) {
++ cFYI(1,("Validation prior to mmap failed, error=%d", rc));
++ FreeXid(xid);
++ return rc;
++ }
++ rc = generic_file_mmap(file, vma);
++ FreeXid(xid);
++ return rc;
++}
++
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
++static void cifs_copy_cache_pages(struct address_space *mapping,
++ struct list_head *pages, int bytes_read,
++ char *data,struct pagevec * plru_pvec)
++{
++ struct page *page;
++ char * target;
++
++ while (bytes_read > 0) {
++ if(list_empty(pages))
++ break;
++
++ page = list_entry(pages->prev, struct page, lru);
++ list_del(&page->lru);
++
++ if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
++ page_cache_release(page);
++ cFYI(1,("Add page cache failed"));
++ continue;
++ }
++
++ target = kmap_atomic(page,KM_USER0);
++
++ if(PAGE_CACHE_SIZE > bytes_read) {
++ memcpy(target,data,bytes_read);
++ /* zero the tail end of this partial page */
++ memset(target+bytes_read,0,PAGE_CACHE_SIZE-bytes_read);
++ bytes_read = 0;
++ } else {
++ memcpy(target,data,PAGE_CACHE_SIZE);
++ bytes_read -= PAGE_CACHE_SIZE;
++ }
++ kunmap_atomic(target,KM_USER0);
++
++ flush_dcache_page(page);
++ SetPageUptodate(page);
++ unlock_page(page);
++ if (!pagevec_add(plru_pvec, page))
++ __pagevec_lru_add(plru_pvec);
++ data += PAGE_CACHE_SIZE;
++ }
++ return;
++}
++
++
++static int
++cifs_readpages(struct file *file, struct address_space *mapping,
++ struct list_head *page_list, unsigned num_pages)
++{
++ int rc = -EACCES;
++ int xid;
++ loff_t offset;
++ struct page * page;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ int bytes_read = 0;
++ unsigned int read_size,i;
++ char * smb_read_data = NULL;
++ struct smb_com_read_rsp * pSMBr;
++ struct pagevec lru_pvec;
++ struct cifsFileInfo * open_file;
++
++ xid = GetXid();
++ if (file->private_data == NULL) {
++ FreeXid(xid);
++ return -EBADF;
++ }
++ open_file = (struct cifsFileInfo *)file->private_data;
++ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++ pTcon = cifs_sb->tcon;
++
++ pagevec_init(&lru_pvec, 0);
++
++ for(i = 0;i<num_pages;) {
++ unsigned contig_pages;
++ struct page * tmp_page;
++ unsigned long expected_index;
++
++ if(list_empty(page_list)) {
++ break;
++ }
++ page = list_entry(page_list->prev, struct page, lru);
++ offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
++
++ /* count adjacent pages that we will read into */
++ contig_pages = 0;
++ expected_index = list_entry(page_list->prev,struct page,lru)->index;
++ list_for_each_entry_reverse(tmp_page,page_list,lru) {
++ if(tmp_page->index == expected_index) {
++ contig_pages++;
++ expected_index++;
++ } else {
++ break;
++ }
++ }
++ if(contig_pages + i > num_pages) {
++ contig_pages = num_pages - i;
++ }
++
++ /* for reads over a certain size could initiate async read ahead */
++
++ read_size = contig_pages * PAGE_CACHE_SIZE;
++ /* Read size needs to be in multiples of one page */
++ read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK);
++
++ rc = -EAGAIN;
++ while(rc == -EAGAIN) {
++ if ((open_file->invalidHandle) && (!open_file->closePend)) {
++ rc = cifs_reopen_file(file->f_dentry->d_inode,
++ file, TRUE);
++ if(rc != 0)
++ break;
++ }
++
++ rc = CIFSSMBRead(xid, pTcon,
++ open_file->netfid,
++ read_size, offset,
++ &bytes_read, &smb_read_data);
++ /* BB need to check return code here */
++ if(rc== -EAGAIN) {
++ if(smb_read_data) {
++ cifs_buf_release(smb_read_data);
++ smb_read_data = NULL;
++ }
++ }
++ }
++ if ((rc < 0) || (smb_read_data == NULL)) {
++ cFYI(1,("Read error in readpages: %d",rc));
++ /* clean up remaing pages off list */
++ while (!list_empty(page_list) && (i < num_pages)) {
++ page = list_entry(page_list->prev, struct page, lru);
++ list_del(&page->lru);
++ page_cache_release(page);
++ }
++ break;
++ } else if (bytes_read > 0) {
++ pSMBr = (struct smb_com_read_rsp *)smb_read_data;
++ cifs_copy_cache_pages(mapping, page_list, bytes_read,
++ smb_read_data + 4 /* RFC1001 hdr */ +
++ le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
++
++ i += bytes_read >> PAGE_CACHE_SHIFT;
++#ifdef CONFIG_CIFS_STATS
++ atomic_inc(&pTcon->num_reads);
++ spin_lock(&pTcon->stat_lock);
++ pTcon->bytes_read += bytes_read;
++ spin_unlock(&pTcon->stat_lock);
++#endif
++ if((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
++ cFYI(1,("Partial page %d of %d read to cache",i++,num_pages));
++
++ i++; /* account for partial page */
++
++ /* server copy of file can have smaller size than client */
++ /* BB do we need to verify this common case ? this case is ok -
++ if we are at server EOF we will hit it on next read */
++
++ /* while(!list_empty(page_list) && (i < num_pages)) {
++ page = list_entry(page_list->prev,struct page, list);
++ list_del(&page->list);
++ page_cache_release(page);
++ }
++ break; */
++ }
++ } else {
++ cFYI(1,("No bytes read (%d) at offset %lld . Cleaning remaining pages from readahead list",bytes_read,offset));
++ /* BB turn off caching and do new lookup on file size at server? */
++ while (!list_empty(page_list) && (i < num_pages)) {
++ page = list_entry(page_list->prev, struct page, lru);
++ list_del(&page->lru);
++ page_cache_release(page); /* BB removeme - replace with zero of page? */
++ }
++ break;
++ }
++ if(smb_read_data) {
++ cifs_buf_release(smb_read_data);
++ smb_read_data = NULL;
++ }
++ bytes_read = 0;
++ }
++
++ pagevec_lru_add(&lru_pvec);
++
++/* need to free smb_read_data buf before exit */
++ if(smb_read_data) {
++ cifs_buf_release(smb_read_data);
++ smb_read_data = NULL;
++ }
++
++ FreeXid(xid);
++ return rc;
++}
++#endif
++
++static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * poffset)
++{
++ char * read_data;
++ int rc;
++
++ page_cache_get(page);
++ read_data = kmap(page);
++ /* for reads over a certain size could initiate async read ahead */
++
++ rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
++
++ if (rc < 0)
++ goto io_error;
++ else {
++ cFYI(1,("Bytes read %d ",rc));
++ }
++
++ file->f_dentry->d_inode->i_atime = CURRENT_TIME;
++
++ if(PAGE_CACHE_SIZE > rc) {
++ memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc);
++ }
++ flush_dcache_page(page);
++ SetPageUptodate(page);
++ rc = 0;
++
++io_error:
++ kunmap(page);
++ page_cache_release(page);
++ return rc;
++}
++
++static int
++cifs_readpage(struct file *file, struct page *page)
++{
++ loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
++ int rc = -EACCES;
++ int xid;
++
++ xid = GetXid();
++
++ if (file->private_data == NULL) {
++ FreeXid(xid);
++ return -EBADF;
++ }
++
++ cFYI(1,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset));
++
++ rc = cifs_readpage_worker(file,page,&offset);
++
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
++ unlock_page(page);
++#else
++ UnlockPage(page);
++#endif
++
++ FreeXid(xid);
++ return rc;
++}
++
++/* We do not want to update the file size from server for inodes
++ open for write - to avoid races with writepage extending
++ the file - in the future we could consider allowing
++ refreshing the inode only on increases in the file size
++ but this is tricky to do without racing with writebehind
++ page caching in the current Linux kernel design */
++
++int is_size_safe_to_change(struct cifsInodeInfo * cifsInode)
++{
++ struct list_head *tmp;
++ struct list_head *tmp1;
++ struct cifsFileInfo *open_file = NULL;
++ int rc = TRUE;
++
++ if(cifsInode == NULL)
++ return rc;
++
++ read_lock(&GlobalSMBSeslock);
++ list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
++ open_file = list_entry(tmp,struct cifsFileInfo, flist);
++ if(open_file == NULL)
++ break;
++ if(open_file->closePend)
++ continue;
++ /* We check if file is open for writing,
++ BB we could supplement this with a check to see if file size
++ changes have been flushed to server - ie inode metadata dirty */
++ if((open_file->pfile) &&
++ ((open_file->pfile->f_flags & O_RDWR) ||
++ (open_file->pfile->f_flags & O_WRONLY))) {
++ rc = FALSE;
++ break;
++ }
++ if(tmp->next == NULL) {
++ cFYI(1,("File instance %p removed",tmp));
++ break;
++ }
++ }
++ read_unlock(&GlobalSMBSeslock);
++ return rc;
++}
++
++
++void
++fill_in_inode(struct inode *tmp_inode,
++ FILE_DIRECTORY_INFO * pfindData, int *pobject_type)
++{
++ struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
++ struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
++
++ pfindData->ExtFileAttributes =
++ le32_to_cpu(pfindData->ExtFileAttributes);
++ pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
++ pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
++ cifsInfo->cifsAttrs = pfindData->ExtFileAttributes;
++ cifsInfo->time = jiffies;
++
++ /* Linux can not store file creation time unfortunately so ignore it */
++ tmp_inode->i_atime =
++ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
++ tmp_inode->i_mtime =
++ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
++ tmp_inode->i_ctime =
++ cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
++ /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
++ /* 2767 perms - indicate mandatory locking */
++ /* BB fill in uid and gid here? with help from winbind?
++ or retrieve from NTFS stream extended attribute */
++ if(atomic_read(&cifsInfo->inUse) == 0) {
++ tmp_inode->i_uid = cifs_sb->mnt_uid;
++ tmp_inode->i_gid = cifs_sb->mnt_gid;
++ /* set default mode. will override for dirs below */
++ tmp_inode->i_mode = cifs_sb->mnt_file_mode;
++ }
++
++ cFYI(0,
++ ("CIFS FFIRST: Attributes came in as 0x%x",
++ pfindData->ExtFileAttributes));
++ if (pfindData->ExtFileAttributes & ATTR_REPARSE) {
++ *pobject_type = DT_LNK;
++ /* BB can this and S_IFREG or S_IFDIR be set as in Windows? */
++ tmp_inode->i_mode |= S_IFLNK;
++ } else if (pfindData->ExtFileAttributes & ATTR_DIRECTORY) {
++ *pobject_type = DT_DIR;
++ /* override default perms since we do not lock dirs */
++ if(atomic_read(&cifsInfo->inUse) == 0) {
++ tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
++ }
++ tmp_inode->i_mode |= S_IFDIR;
++ } else {
++ *pobject_type = DT_REG;
++ tmp_inode->i_mode |= S_IFREG;
++ if(pfindData->ExtFileAttributes & ATTR_READONLY)
++ tmp_inode->i_mode &= ~(S_IWUGO);
++
++ }/* could add code here - to validate if device or weird share type? */
++
++ /* can not fill in nlink here as in qpathinfo version and Unx search */
++ if(atomic_read(&cifsInfo->inUse) == 0) {
++ atomic_set(&cifsInfo->inUse,1);
++ }
++ if(is_size_safe_to_change(cifsInfo)) {
++ /* can not safely change the file size here if the
++ client is writing to it due to potential races */
++ tmp_inode->i_size = pfindData->EndOfFile;
++
++ /* 512 bytes (2**9) is the fake blocksize that must be used */
++ /* for this calculation, even though the reported blocksize is larger */
++ tmp_inode->i_blocks = (512 - 1 + pfindData->AllocationSize) >> 9;
++ }
++
++ if (pfindData->AllocationSize < pfindData->EndOfFile)
++ cFYI(1, ("Possible sparse file: allocation size less than end of file "));
++ cFYI(1,
++ ("File Size %ld and blocks %ld and blocksize %ld",
++ (unsigned long) tmp_inode->i_size, tmp_inode->i_blocks,
++ tmp_inode->i_blksize));
++ if (S_ISREG(tmp_inode->i_mode)) {
++ cFYI(1, (" File inode "));
++ tmp_inode->i_op = &cifs_file_inode_ops;
++ tmp_inode->i_fop = &cifs_file_ops;
++ tmp_inode->i_data.a_ops = &cifs_addr_ops;
++ } else if (S_ISDIR(tmp_inode->i_mode)) {
++ cFYI(1, (" Directory inode"));
++ tmp_inode->i_op = &cifs_dir_inode_ops;
++ tmp_inode->i_fop = &cifs_dir_ops;
++ } else if (S_ISLNK(tmp_inode->i_mode)) {
++ cFYI(1, (" Symbolic Link inode "));
++ tmp_inode->i_op = &cifs_symlink_inode_ops;
++ } else {
++ cFYI(1, (" Init special inode "));
++ init_special_inode(tmp_inode, tmp_inode->i_mode,
++ kdev_t_to_nr(tmp_inode->i_rdev));
++ }
++}
++
++void
++unix_fill_in_inode(struct inode *tmp_inode,
++ FILE_UNIX_INFO * pfindData, int *pobject_type)
++{
++ struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
++ cifsInfo->time = jiffies;
++ atomic_inc(&cifsInfo->inUse);
++
++ tmp_inode->i_atime =
++ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
++ tmp_inode->i_mtime =
++ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
++ tmp_inode->i_ctime =
++ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
++
++ tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
++ pfindData->Type = le32_to_cpu(pfindData->Type);
++ if (pfindData->Type == UNIX_FILE) {
++ *pobject_type = DT_REG;
++ tmp_inode->i_mode |= S_IFREG;
++ } else if (pfindData->Type == UNIX_SYMLINK) {
++ *pobject_type = DT_LNK;
++ tmp_inode->i_mode |= S_IFLNK;
++ } else if (pfindData->Type == UNIX_DIR) {
++ *pobject_type = DT_DIR;
++ tmp_inode->i_mode |= S_IFDIR;
++ } else if (pfindData->Type == UNIX_CHARDEV) {
++ *pobject_type = DT_CHR;
++ tmp_inode->i_mode |= S_IFCHR;
++ tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
++ le64_to_cpu(pfindData->DevMinor) & MINORMASK);
++ } else if (pfindData->Type == UNIX_BLOCKDEV) {
++ *pobject_type = DT_BLK;
++ tmp_inode->i_mode |= S_IFBLK;
++ tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
++ le64_to_cpu(pfindData->DevMinor) & MINORMASK);
++ } else if (pfindData->Type == UNIX_FIFO) {
++ *pobject_type = DT_FIFO;
++ tmp_inode->i_mode |= S_IFIFO;
++ } else if (pfindData->Type == UNIX_SOCKET) {
++ *pobject_type = DT_SOCK;
++ tmp_inode->i_mode |= S_IFSOCK;
++ }
++
++ tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
++ tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
++ tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
++
++ pfindData->NumOfBytes = le64_to_cpu(pfindData->NumOfBytes);
++ if(is_size_safe_to_change(cifsInfo)) {
++ /* can not safely change the file size here if the
++ client is writing to it due to potential races */
++ pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
++ tmp_inode->i_size = pfindData->EndOfFile;
++
++ /* 512 bytes (2**9) is the fake blocksize that must be used */
++ /* for this calculation, not the real blocksize */
++ tmp_inode->i_blocks = (512 - 1 + pfindData->NumOfBytes) >> 9;
++ }
++
++ if (S_ISREG(tmp_inode->i_mode)) {
++ cFYI(1, ("File inode"));
++ tmp_inode->i_op = &cifs_file_inode_ops;
++ tmp_inode->i_fop = &cifs_file_ops;
++ tmp_inode->i_data.a_ops = &cifs_addr_ops;
++ } else if (S_ISDIR(tmp_inode->i_mode)) {
++ cFYI(1, ("Directory inode"));
++ tmp_inode->i_op = &cifs_dir_inode_ops;
++ tmp_inode->i_fop = &cifs_dir_ops;
++ } else if (S_ISLNK(tmp_inode->i_mode)) {
++ cFYI(1, ("Symbolic Link inode"));
++ tmp_inode->i_op = &cifs_symlink_inode_ops;
++/* tmp_inode->i_fop = *//* do not need to set to anything */
++ } else {
++ cFYI(1, ("Special inode"));
++ init_special_inode(tmp_inode, tmp_inode->i_mode,
++ kdev_t_to_nr(tmp_inode->i_rdev));
++ }
++}
++
++static void
++construct_dentry(struct qstr *qstring, struct file *file,
++ struct inode **ptmp_inode, struct dentry **pnew_dentry)
++{
++ struct dentry *tmp_dentry;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ struct cifsInodeInfo *pCifsI;
++
++ cFYI(1, ("For %s ", qstring->name));
++ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++ pTcon = cifs_sb->tcon;
++
++ qstring->hash = full_name_hash(qstring->name, qstring->len);
++ tmp_dentry = d_lookup(file->f_dentry, qstring);
++ if (tmp_dentry) {
++ cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
++ *ptmp_inode = tmp_dentry->d_inode;
++ /* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */
++ if(*ptmp_inode == NULL) {
++ *ptmp_inode = new_inode(file->f_dentry->d_sb);
++ if(*ptmp_inode == NULL)
++ return;
++ d_instantiate(tmp_dentry, *ptmp_inode);
++ insert_inode_hash(*ptmp_inode);
++ pCifsI = CIFS_I(*ptmp_inode);
++ INIT_LIST_HEAD(&pCifsI->openFileList);
++ /* can not enable caching for this inode
++ until a file instance is open and we
++ can check the oplock flag on the open
++ response */
++ (*ptmp_inode)->i_blksize = CIFS_MAX_MSGSIZE;
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
++ (*ptmp_inode)->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
++#endif
++ pCifsI->clientCanCacheRead = FALSE;
++ pCifsI->clientCanCacheAll = FALSE;
++ pCifsI->time = 0;
++ /* do not need to set cifs Attrs since
++ they are about to be overwritten
++ in fill_in_inode */
++ atomic_set(&pCifsI->inUse, 0);
++ }
++ } else {
++ tmp_dentry = d_alloc(file->f_dentry, qstring);
++ if(tmp_dentry == NULL) {
++ cERROR(1,("Failed allocating dentry"));
++ return;
++ }
++
++ if(ptmp_inode) {
++ *ptmp_inode = new_inode(file->f_dentry->d_sb);
++ if(*ptmp_inode == NULL)
++ return;
++ pCifsI = CIFS_I(*ptmp_inode);
++ insert_inode_hash(*ptmp_inode);
++ INIT_LIST_HEAD(&pCifsI->openFileList);
++ /* can not enable caching for this inode
++ until a file instance is open and we
++ can check the oplock flag on the open
++ response */
++ (*ptmp_inode)->i_blksize = CIFS_MAX_MSGSIZE;
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
++ (*ptmp_inode)->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
++#endif
++ pCifsI->clientCanCacheRead = FALSE;
++ pCifsI->clientCanCacheAll = FALSE;
++ pCifsI->time = 0;
++ /* do not need to set cifs Attrs since
++ they are about to be overwritten
++ in fill_in_inode */
++ atomic_set(&pCifsI->inUse, 0);
++ }
++ tmp_dentry->d_op = &cifs_dentry_ops;
++ d_instantiate(tmp_dentry, *ptmp_inode);
++ d_rehash(tmp_dentry);
++ }
++
++ tmp_dentry->d_time = jiffies;
++ *pnew_dentry = tmp_dentry;
++}
++
++static void reset_resume_key(struct file * dir_file,
++ unsigned char * filename,
++ unsigned int len,int Unicode,struct nls_table * nls_tab) {
++ struct cifsFileInfo *cifsFile;
++
++ cifsFile = (struct cifsFileInfo *)dir_file->private_data;
++ if(cifsFile == NULL)
++ return;
++ if(cifsFile->search_resume_name) {
++ kfree(cifsFile->search_resume_name);
++ }
++
++ if(Unicode)
++ len *= 2;
++ cifsFile->resume_name_length = len;
++
++ cifsFile->search_resume_name =
++ kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
++
++ if(cifsFile->search_resume_name == NULL) {
++ cERROR(1,("failed new resume key allocate, length %d",
++ cifsFile->resume_name_length));
++ return;
++ }
++ if(Unicode)
++ cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name,
++ filename, len, nls_tab);
++ else
++ memcpy(cifsFile->search_resume_name, filename,
++ cifsFile->resume_name_length);
++ cFYI(1,("Reset resume key to: %s with len %d",filename,len));
++ return;
++}
++
++
++
++static int
++cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
++ struct file *file, filldir_t filldir, void *direntry)
++{
++ struct inode *tmp_inode;
++ struct dentry *tmp_dentry;
++ int object_type,rc;
++
++ pqstring->name = pfindData->FileName;
++ pqstring->len = pfindData->FileNameLength;
++
++ construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
++ if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
++ return -ENOMEM;
++ }
++ fill_in_inode(tmp_inode, pfindData, &object_type);
++ rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
++ tmp_inode->i_ino, object_type);
++ if(rc) {
++ /* due to readdir error we need to recalculate resume
++ key so next readdir will restart on right entry */
++ cFYI(1,("Error %d on filldir of %s",rc ,pfindData->FileName));
++ }
++ dput(tmp_dentry);
++ return rc;
++}
++
++static int
++cifs_filldir_unix(struct qstr *pqstring,
++ FILE_UNIX_INFO * pUnixFindData, struct file *file,
++ filldir_t filldir, void *direntry)
++{
++ struct inode *tmp_inode;
++ struct dentry *tmp_dentry;
++ int object_type, rc;
++
++ pqstring->name = pUnixFindData->FileName;
++ pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
++
++ construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
++ if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
++ return -ENOMEM;
++ }
++
++ unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type);
++ rc = filldir(direntry, pUnixFindData->FileName, pqstring->len,
++ file->f_pos, tmp_inode->i_ino, object_type);
++ if(rc) {
++ /* due to readdir error we need to recalculate resume
++ key so next readdir will restart on right entry */
++ cFYI(1,("Error %d on filldir of %s",rc ,pUnixFindData->FileName));
++ }
++ dput(tmp_dentry);
++ return rc;
++}
++
++int
++cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
++{
++ int rc = 0;
++ int xid;
++ int Unicode = FALSE;
++ int UnixSearch = FALSE;
++ unsigned int bufsize, i;
++ __u16 searchHandle;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ struct cifsFileInfo *cifsFile = NULL;
++ char *full_path = NULL;
++ char *data;
++ struct qstr qstring;
++ T2_FFIRST_RSP_PARMS findParms;
++ T2_FNEXT_RSP_PARMS findNextParms;
++ FILE_DIRECTORY_INFO *pfindData;
++ FILE_DIRECTORY_INFO *lastFindData;
++ FILE_UNIX_INFO *pfindDataUnix;
++
++ xid = GetXid();
++
++ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++ pTcon = cifs_sb->tcon;
++ bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
++ if(bufsize > CIFS_MAX_MSGSIZE) {
++ FreeXid(xid);
++ return -EIO;
++ }
++ data = kmalloc(bufsize, GFP_KERNEL);
++ pfindData = (FILE_DIRECTORY_INFO *) data;
++
++ if(file->f_dentry == NULL) {
++ FreeXid(xid);
++ return -EIO;
++ }
++ down(&file->f_dentry->d_sb->s_vfs_rename_sem);
++ full_path = build_wildcard_path_from_dentry(file->f_dentry);
++ up(&file->f_dentry->d_sb->s_vfs_rename_sem);
++
++
++ cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
++
++ switch ((int) file->f_pos) {
++ case 0:
++ if (filldir(direntry, ".", 1, file->f_pos,
++ file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
++ cERROR(1, ("Filldir for current dir failed "));
++ break;
++ }
++ file->f_pos++;
++ /* fallthrough */
++ case 1:
++ if (filldir(direntry, "..", 2, file->f_pos,
++ file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
++ cERROR(1, ("Filldir for parent dir failed "));
++ break;
++ }
++ file->f_pos++;
++ /* fallthrough */
++ case 2:
++ if (file->private_data != NULL) {
++ cifsFile =
++ (struct cifsFileInfo *) file->private_data;
++ if (cifsFile->endOfSearch) {
++ if(cifsFile->emptyDir) {
++ cFYI(1, ("End of search, empty dir"));
++ rc = 0;
++ break;
++ }
++ } else {
++ cifsFile->invalidHandle = TRUE;
++ CIFSFindClose(xid, pTcon, cifsFile->netfid);
++ }
++ if(cifsFile->search_resume_name) {
++ kfree(cifsFile->search_resume_name);
++ cifsFile->search_resume_name = NULL;
++ }
++ }
++ rc = CIFSFindFirst(xid, pTcon, full_path, pfindData,
++ &findParms, cifs_sb->local_nls,
++ &Unicode, &UnixSearch);
++ cFYI(1, ("Count: %d End: %d ", findParms.SearchCount,
++ findParms.EndofSearch));
++
++ if (rc == 0) {
++ searchHandle = findParms.SearchHandle;
++ if(file->private_data == NULL)
++ file->private_data =
++ kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
++ if (file->private_data) {
++ memset(file->private_data, 0,
++ sizeof (struct cifsFileInfo));
++ cifsFile =
++ (struct cifsFileInfo *) file->private_data;
++ cifsFile->netfid = searchHandle;
++ cifsFile->invalidHandle = FALSE;
++ init_MUTEX(&cifsFile->fh_sem);
++ } else {
++ rc = -ENOMEM;
++ break;
++ }
++
++ renew_parental_timestamps(file->f_dentry);
++ lastFindData =
++ (FILE_DIRECTORY_INFO *) ((char *) pfindData +
++ findParms.LastNameOffset);
++ if((char *)lastFindData > (char *)pfindData + bufsize) {
++ cFYI(1,("last search entry past end of packet"));
++ rc = -EIO;
++ break;
++ }
++ /* Offset of resume key same for levels 257 and 514 */
++ cifsFile->resume_key = lastFindData->FileIndex;
++ if(UnixSearch == FALSE) {
++ cifsFile->resume_name_length =
++ le32_to_cpu(lastFindData->FileNameLength);
++ if(cifsFile->resume_name_length > bufsize - 64) {
++ cFYI(1,("Illegal resume file name length %d",
++ cifsFile->resume_name_length));
++ rc = -ENOMEM;
++ break;
++ }
++ cifsFile->search_resume_name =
++ kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
++ cFYI(1,("Last file: %s with name %d bytes long",
++ lastFindData->FileName,
++ cifsFile->resume_name_length));
++ memcpy(cifsFile->search_resume_name,
++ lastFindData->FileName,
++ cifsFile->resume_name_length);
++ } else {
++ pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
++ if (Unicode == TRUE) {
++ for(i=0;(pfindDataUnix->FileName[i]
++ | pfindDataUnix->FileName[i+1]);
++ i+=2) {
++ if(i > bufsize-64)
++ break;
++ }
++ cifsFile->resume_name_length = i + 2;
++ } else {
++ cifsFile->resume_name_length =
++ strnlen(pfindDataUnix->FileName,
++ bufsize-63);
++ }
++ if(cifsFile->resume_name_length > bufsize - 64) {
++ cFYI(1,("Illegal resume file name length %d",
++ cifsFile->resume_name_length));
++ rc = -ENOMEM;
++ break;
++ }
++ cifsFile->search_resume_name =
++ kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
++ cFYI(1,("Last file: %s with name %d bytes long",
++ pfindDataUnix->FileName,
++ cifsFile->resume_name_length));
++ memcpy(cifsFile->search_resume_name,
++ pfindDataUnix->FileName,
++ cifsFile->resume_name_length);
++ }
++ for (i = 2; i < (unsigned int)findParms.SearchCount + 2; i++) {
++ if (UnixSearch == FALSE) {
++ pfindData->FileNameLength =
++ le32_to_cpu(pfindData->FileNameLength);
++ if (Unicode == TRUE)
++ pfindData->FileNameLength =
++ cifs_strfromUCS_le
++ (pfindData->FileName,
++ (wchar_t *)
++ pfindData->FileName,
++ (pfindData->
++ FileNameLength) / 2,
++ cifs_sb->local_nls);
++ qstring.len = pfindData->FileNameLength;
++ if (((qstring.len != 1)
++ || (pfindData->FileName[0] != '.'))
++ && ((qstring.len != 2)
++ || (pfindData->
++ FileName[0] != '.')
++ || (pfindData->
++ FileName[1] != '.'))) {
++ if(cifs_filldir(&qstring,
++ pfindData,
++ file, filldir,
++ direntry)) {
++ /* do not end search if
++ kernel not ready to take
++ remaining entries yet */
++ reset_resume_key(file, pfindData->FileName,qstring.len,
++ Unicode, cifs_sb->local_nls);
++ findParms.EndofSearch = 0;
++ break;
++ }
++ file->f_pos++;
++ }
++ } else { /* UnixSearch */
++ pfindDataUnix =
++ (FILE_UNIX_INFO *) pfindData;
++ if (Unicode == TRUE)
++ qstring.len =
++ cifs_strfromUCS_le
++ (pfindDataUnix->FileName,
++ (wchar_t *)
++ pfindDataUnix->FileName,
++ MAX_PATHCONF,
++ cifs_sb->local_nls);
++ else
++ qstring.len =
++ strnlen(pfindDataUnix->
++ FileName,
++ MAX_PATHCONF);
++ if (((qstring.len != 1)
++ || (pfindDataUnix->
++ FileName[0] != '.'))
++ && ((qstring.len != 2)
++ || (pfindDataUnix->
++ FileName[0] != '.')
++ || (pfindDataUnix->
++ FileName[1] != '.'))) {
++ if(cifs_filldir_unix(&qstring,
++ pfindDataUnix,
++ file,
++ filldir,
++ direntry)) {
++ /* do not end search if
++ kernel not ready to take
++ remaining entries yet */
++ findParms.EndofSearch = 0;
++ reset_resume_key(file, pfindDataUnix->FileName,
++ qstring.len,Unicode,cifs_sb->local_nls);
++ break;
++ }
++ file->f_pos++;
++ }
++ }
++ /* works also for Unix ff struct since first field of both */
++ pfindData =
++ (FILE_DIRECTORY_INFO *) ((char *) pfindData
++ + le32_to_cpu(pfindData->NextEntryOffset));
++ /* BB also should check to make sure that pointer is not beyond the end of the SMB */
++ /* if(pfindData > lastFindData) rc = -EIO; break; */
++ } /* end for loop */
++ if ((findParms.EndofSearch != 0) && cifsFile) {
++ cifsFile->endOfSearch = TRUE;
++ if(findParms.SearchCount == 2)
++ cifsFile->emptyDir = TRUE;
++ }
++ } else {
++ if (cifsFile)
++ cifsFile->endOfSearch = TRUE;
++ /* unless parent directory gone do not return error */
++ rc = 0;
++ }
++ break;
++ default:
++ if (file->private_data == NULL) {
++ rc = -EBADF;
++ cFYI(1,
++ ("Readdir on closed srch, pos = %lld",
++ file->f_pos));
++ } else {
++ cifsFile = (struct cifsFileInfo *) file->private_data;
++ if (cifsFile->endOfSearch) {
++ rc = 0;
++ cFYI(1, ("End of search "));
++ break;
++ }
++ searchHandle = cifsFile->netfid;
++ rc = CIFSFindNext(xid, pTcon, pfindData,
++ &findNextParms, searchHandle,
++ cifsFile->search_resume_name,
++ cifsFile->resume_name_length,
++ cifsFile->resume_key,
++ &Unicode, &UnixSearch);
++ cFYI(1,("Count: %d End: %d ",
++ findNextParms.SearchCount,
++ findNextParms.EndofSearch));
++ if ((rc == 0) && (findNextParms.SearchCount != 0)) {
++ /* BB save off resume key, key name and name length */
++ lastFindData =
++ (FILE_DIRECTORY_INFO *) ((char *) pfindData
++ + findNextParms.LastNameOffset);
++ if((char *)lastFindData > (char *)pfindData + bufsize) {
++ cFYI(1,("last search entry past end of packet"));
++ rc = -EIO;
++ break;
++ }
++ /* Offset of resume key same for levels 257 and 514 */
++ cifsFile->resume_key = lastFindData->FileIndex;
++
++ if(UnixSearch == FALSE) {
++ cifsFile->resume_name_length =
++ le32_to_cpu(lastFindData->FileNameLength);
++ if(cifsFile->resume_name_length > bufsize - 64) {
++ cFYI(1,("Illegal resume file name length %d",
++ cifsFile->resume_name_length));
++ rc = -ENOMEM;
++ break;
++ }
++ /* Free the memory allocated by previous findfirst
++ or findnext call - we can not reuse the memory since
++ the resume name may not be same string length */
++ if(cifsFile->search_resume_name)
++ kfree(cifsFile->search_resume_name);
++ cifsFile->search_resume_name =
++ kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
++ cFYI(1,("Last file: %s with name %d bytes long",
++ lastFindData->FileName,
++ cifsFile->resume_name_length));
++ memcpy(cifsFile->search_resume_name,
++ lastFindData->FileName,
++ cifsFile->resume_name_length);
++ } else {
++ pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
++ if (Unicode == TRUE) {
++ for(i=0;(pfindDataUnix->FileName[i]
++ | pfindDataUnix->FileName[i+1]);
++ i+=2) {
++ if(i > bufsize-64)
++ break;
++ }
++ cifsFile->resume_name_length = i + 2;
++ } else {
++ cifsFile->resume_name_length =
++ strnlen(pfindDataUnix->
++ FileName,
++ MAX_PATHCONF);
++ }
++ if(cifsFile->resume_name_length > bufsize - 64) {
++ cFYI(1,("Illegal resume file name length %d",
++ cifsFile->resume_name_length));
++ rc = -ENOMEM;
++ break;
++ }
++ /* Free the memory allocated by previous findfirst
++ or findnext call - we can not reuse the memory since
++ the resume name may not be same string length */
++ if(cifsFile->search_resume_name)
++ kfree(cifsFile->search_resume_name);
++ cifsFile->search_resume_name =
++ kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
++ cFYI(1,("fnext last file: %s with name %d bytes long",
++ pfindDataUnix->FileName,
++ cifsFile->resume_name_length));
++ memcpy(cifsFile->search_resume_name,
++ pfindDataUnix->FileName,
++ cifsFile->resume_name_length);
++ }
++
++ for (i = 0; i < findNextParms.SearchCount; i++) {
++ pfindData->FileNameLength =
++ le32_to_cpu(pfindData->
++ FileNameLength);
++ if (UnixSearch == FALSE) {
++ if (Unicode == TRUE)
++ pfindData->FileNameLength =
++ cifs_strfromUCS_le
++ (pfindData->FileName,
++ (wchar_t *)
++ pfindData->FileName,
++ (pfindData->FileNameLength)/ 2,
++ cifs_sb->local_nls);
++ qstring.len =
++ pfindData->FileNameLength;
++ if (((qstring.len != 1)
++ || (pfindData->FileName[0] != '.'))
++ && ((qstring.len != 2)
++ || (pfindData->FileName[0] != '.')
++ || (pfindData->FileName[1] !=
++ '.'))) {
++ if(cifs_filldir
++ (&qstring,
++ pfindData,
++ file, filldir,
++ direntry)) {
++ /* do not end search if
++ kernel not ready to take
++ remaining entries yet */
++ findNextParms.EndofSearch = 0;
++ reset_resume_key(file, pfindData->FileName,qstring.len,
++ Unicode,cifs_sb->local_nls);
++ break;
++ }
++ file->f_pos++;
++ }
++ } else { /* UnixSearch */
++ pfindDataUnix =
++ (FILE_UNIX_INFO *)
++ pfindData;
++ if (Unicode == TRUE)
++ qstring.len =
++ cifs_strfromUCS_le
++ (pfindDataUnix->FileName,
++ (wchar_t *)
++ pfindDataUnix->FileName,
++ MAX_PATHCONF,
++ cifs_sb->local_nls);
++ else
++ qstring.len =
++ strnlen
++ (pfindDataUnix->
++ FileName,
++ MAX_PATHCONF);
++ if (((qstring.len != 1)
++ || (pfindDataUnix->
++ FileName[0] != '.'))
++ && ((qstring.len != 2)
++ || (pfindDataUnix->
++ FileName[0] != '.')
++ || (pfindDataUnix->
++ FileName[1] !=
++ '.'))) {
++ if(cifs_filldir_unix
++ (&qstring,
++ pfindDataUnix,
++ file, filldir,
++ direntry)) {
++ /* do not end search if
++ kernel not ready to take
++ remaining entries yet */
++ findNextParms.EndofSearch = 0;
++ reset_resume_key(file, pfindDataUnix->FileName,qstring.len,
++ Unicode,cifs_sb->local_nls);
++ break;
++ }
++ file->f_pos++;
++ }
++ }
++ pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData + le32_to_cpu(pfindData->NextEntryOffset)); /* works also for Unix find struct since this is the first field of both */
++ /* BB also should check to make sure that pointer is not beyond the end of the SMB */
++ } /* end for loop */
++ if (findNextParms.EndofSearch != 0) {
++ cifsFile->endOfSearch = TRUE;
++ }
++ } else {
++ cifsFile->endOfSearch = TRUE;
++ rc = 0; /* unless parent directory disappeared - do not return error here (eg Access Denied or no more files) */
++ }
++ }
++ } /* end switch */
++ if (data)
++ kfree(data);
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++
++ return rc;
++}
++int cifs_prepare_write(struct file *file, struct page *page,
++ unsigned from, unsigned to)
++{
++ int rc = 0;
++ loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
++ cFYI(1,("prepare write for page %p from %d to %d",page,from,to));
++ if (!Page_Uptodate(page)) {
++ /* if (to - from != PAGE_CACHE_SIZE) {
++ void *kaddr = kmap_atomic(page, KM_USER0);
++ memset(kaddr, 0, from);
++ memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
++ flush_dcache_page(page);
++ kunmap_atomic(kaddr, KM_USER0);
++ } */
++ /* If we are writing a full page it will be up to date,
++ no need to read from the server */
++ if((to==PAGE_CACHE_SIZE) && (from == 0))
++ SetPageUptodate(page);
++
++ /* might as well read a page, it is fast enough */
++ if((file->f_flags & O_ACCMODE) != O_WRONLY) {
++ rc = cifs_readpage_worker(file,page,&offset);
++ } else {
++ /* should we try using another
++ file handle if there is one - how would we lock it
++ to prevent close of that handle racing with this read? */
++ /* In any case this will be written out by commit_write */
++ }
++ }
++
++ /* BB should we pass any errors back? e.g. if we do not have read access to the file */
++ return 0;
++}
++
++
++struct address_space_operations cifs_addr_ops = {
++ .readpage = cifs_readpage,
++/* .readpages = cifs_readpages, */
++ .writepage = cifs_writepage,
++ .prepare_write = cifs_prepare_write,
++ .commit_write = cifs_commit_write,
++ .sync_page = cifs_sync_page,
++ /*.direct_IO = */
++};
+diff -urN linux-2.4.29.old/fs/cifs/inode.c linux-2.4.29/fs/cifs/inode.c
+--- linux-2.4.29.old/fs/cifs/inode.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/inode.c 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,1079 @@
++/*
++ * fs/cifs/inode.c
++ *
++ * Copyright (C) International Business Machines Corp., 2002,2003
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <linux/fs.h>
++#include <linux/stat.h>
++#include <linux/pagemap.h>
++#include <linux/version.h>
++#include <asm/div64.h>
++#include "cifsfs.h"
++#include "cifspdu.h"
++#include "cifsglob.h"
++#include "cifsproto.h"
++#include "cifs_debug.h"
++#include "cifs_fs_sb.h"
++
++extern int is_size_safe_to_change(struct cifsInodeInfo *);
++
++struct inode * get_cifs_inode(struct super_block * sb)
++{
++ struct inode * newinode;
++ newinode = new_inode(sb);
++ cFYI(1,("got new inode %p",newinode));
++ if(newinode) {
++ struct cifsInodeInfo * cifsInfo = CIFS_I(newinode);
++ cifsInfo->clientCanCacheRead = FALSE;
++ cifsInfo->clientCanCacheAll = FALSE;
++ INIT_LIST_HEAD(&cifsInfo->openFileList);
++ cifsInfo->cifsAttrs = 0x20; /* default */
++ newinode->i_blksize = CIFS_MAX_MSGSIZE;
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
++ newinode->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
++#endif
++ atomic_set(&cifsInfo->inUse, 0);
++ cifsInfo->time = 0;
++ insert_inode_hash(newinode);
++ }
++ return newinode;
++
++}
++
++int
++cifs_get_inode_info_unix(struct inode **pinode,
++ const unsigned char *search_path,
++ struct super_block *sb,int xid)
++{
++ int rc = 0;
++ FILE_UNIX_BASIC_INFO findData;
++ struct cifsTconInfo *pTcon;
++ struct inode *inode;
++ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
++ char *tmp_path;
++
++ pTcon = cifs_sb->tcon;
++ cFYI(1, (" Getting info on %s ", search_path));
++ /* we could have done a find first instead but this returns more info */
++ rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
++ cifs_sb->local_nls);
++ /* dump_mem("\nUnixQPathInfo return data", &findData, sizeof(findData)); */
++ if (rc) {
++ if (rc == -EREMOTE) {
++ tmp_path =
++ kmalloc(strnlen
++ (pTcon->treeName,
++ MAX_TREE_SIZE + 1) +
++ strnlen(search_path, MAX_PATHCONF) + 1,
++ GFP_KERNEL);
++ if (tmp_path == NULL) {
++ return -ENOMEM;
++ }
++ /* have to skip first of the double backslash of UNC name */
++ strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
++ strncat(tmp_path, search_path, MAX_PATHCONF);
++ rc = connect_to_dfs_path(xid, pTcon->ses,
++ /* treename + */ tmp_path,
++ cifs_sb->local_nls);
++ kfree(tmp_path);
++
++ /* BB fix up inode etc. */
++ } else if (rc) {
++ return rc;
++ }
++
++ } else {
++ struct cifsInodeInfo *cifsInfo;
++
++ /* get new inode */
++ if (*pinode == NULL) {
++ *pinode = get_cifs_inode(sb);
++ }
++ if(*pinode == NULL) {
++ return -ENOMEM;
++ }
++
++ inode = *pinode;
++ cifsInfo = CIFS_I(inode);
++
++ cFYI(1, (" Old time %ld ", cifsInfo->time));
++ cifsInfo->time = jiffies;
++ cFYI(1, (" New time %ld ", cifsInfo->time));
++ atomic_set(&cifsInfo->inUse,1); /* ok to set on every refresh of inode */
++
++ inode->i_atime =
++ cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
++ inode->i_mtime =
++ cifs_NTtimeToUnix(le64_to_cpu
++ (findData.LastModificationTime));
++ inode->i_ctime =
++ cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
++ inode->i_mode = le64_to_cpu(findData.Permissions);
++ findData.Type = le32_to_cpu(findData.Type);
++ if (findData.Type == UNIX_FILE) {
++ inode->i_mode |= S_IFREG;
++ } else if (findData.Type == UNIX_SYMLINK) {
++ inode->i_mode |= S_IFLNK;
++ } else if (findData.Type == UNIX_DIR) {
++ inode->i_mode |= S_IFDIR;
++ } else if (findData.Type == UNIX_CHARDEV) {
++ inode->i_mode |= S_IFCHR;
++ inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
++ le64_to_cpu(findData.DevMinor) & MINORMASK);
++ } else if (findData.Type == UNIX_BLOCKDEV) {
++ inode->i_mode |= S_IFBLK;
++ inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
++ le64_to_cpu(findData.DevMinor) & MINORMASK);
++ } else if (findData.Type == UNIX_FIFO) {
++ inode->i_mode |= S_IFIFO;
++ } else if (findData.Type == UNIX_SOCKET) {
++ inode->i_mode |= S_IFSOCK;
++ }
++ inode->i_uid = le64_to_cpu(findData.Uid);
++ inode->i_gid = le64_to_cpu(findData.Gid);
++ inode->i_nlink = le64_to_cpu(findData.Nlinks);
++ findData.NumOfBytes = le64_to_cpu(findData.NumOfBytes);
++ findData.EndOfFile = le64_to_cpu(findData.EndOfFile);
++
++ if(is_size_safe_to_change(cifsInfo)) {
++ /* can not safely change the file size here if the
++ client is writing to it due to potential races */
++ inode->i_size = findData.EndOfFile;
++/* blksize needs to be multiple of two. So safer to default to blksize
++ and blkbits set in superblock so 2**blkbits and blksize will match */
++/* inode->i_blksize =
++ (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
++
++ /* This seems incredibly stupid but it turns out that
++ i_blocks is not related to (i_size / i_blksize), instead a
++ size of 512 is required to be used for calculating num blocks */
++
++
++/* inode->i_blocks =
++ (inode->i_blksize - 1 + findData.NumOfBytes) >> inode->i_blkbits;*/
++
++ /* 512 bytes (2**9) is the fake blocksize that must be used */
++ /* for this calculation */
++ inode->i_blocks = (512 - 1 + findData.NumOfBytes) >> 9;
++ }
++
++ if (findData.NumOfBytes < findData.EndOfFile)
++ cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
++ cFYI(1,
++ ("Size %ld and blocks %ld ",
++ (unsigned long) inode->i_size, inode->i_blocks));
++ if (S_ISREG(inode->i_mode)) {
++ cFYI(1, (" File inode "));
++ inode->i_op = &cifs_file_inode_ops;
++ inode->i_fop = &cifs_file_ops;
++ inode->i_data.a_ops = &cifs_addr_ops;
++ } else if (S_ISDIR(inode->i_mode)) {
++ cFYI(1, (" Directory inode"));
++ inode->i_op = &cifs_dir_inode_ops;
++ inode->i_fop = &cifs_dir_ops;
++ } else if (S_ISLNK(inode->i_mode)) {
++ cFYI(1, (" Symbolic Link inode "));
++ inode->i_op = &cifs_symlink_inode_ops;
++/* tmp_inode->i_fop = *//* do not need to set to anything */
++ } else {
++ cFYI(1, (" Init special inode "));
++ init_special_inode(inode, inode->i_mode,
++ kdev_t_to_nr(inode->i_rdev));
++ }
++ }
++ return rc;
++}
++
++int
++cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
++ FILE_ALL_INFO * pfindData, struct super_block *sb, int xid)
++{
++ int rc = 0;
++ struct cifsTconInfo *pTcon;
++ struct inode *inode;
++ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
++ char *tmp_path;
++ char *buf = NULL;
++
++ pTcon = cifs_sb->tcon;
++ cFYI(1,("Getting info on %s ", search_path));
++
++ if((pfindData == NULL) && (*pinode != NULL)) {
++ if(CIFS_I(*pinode)->clientCanCacheRead) {
++ cFYI(1,("No need to revalidate inode sizes on cached file "));
++ return rc;
++ }
++ }
++
++ /* if file info not passed in then get it from server */
++ if(pfindData == NULL) {
++ buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
++ pfindData = (FILE_ALL_INFO *)buf;
++ /* could do find first instead but this returns more info */
++ rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
++ cifs_sb->local_nls);
++ }
++ /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
++ if (rc) {
++ if (rc == -EREMOTE) {
++ tmp_path =
++ kmalloc(strnlen
++ (pTcon->treeName,
++ MAX_TREE_SIZE + 1) +
++ strnlen(search_path, MAX_PATHCONF) + 1,
++ GFP_KERNEL);
++ if (tmp_path == NULL) {
++ if(buf)
++ kfree(buf);
++ return -ENOMEM;
++ }
++
++ strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
++ strncat(tmp_path, search_path, MAX_PATHCONF);
++ rc = connect_to_dfs_path(xid, pTcon->ses,
++ /* treename + */ tmp_path,
++ cifs_sb->local_nls);
++ kfree(tmp_path);
++ /* BB fix up inode etc. */
++ } else if (rc) {
++ if(buf)
++ kfree(buf);
++ return rc;
++ }
++ } else {
++ struct cifsInodeInfo *cifsInfo;
++
++ /* get new inode */
++ if (*pinode == NULL) {
++ *pinode = get_cifs_inode(sb);
++ }
++ if(*pinode == NULL)
++ return -ENOMEM;
++ inode = *pinode;
++ cifsInfo = CIFS_I(inode);
++ pfindData->Attributes = le32_to_cpu(pfindData->Attributes);
++ cifsInfo->cifsAttrs = pfindData->Attributes;
++ cFYI(1, (" Old time %ld ", cifsInfo->time));
++ cifsInfo->time = jiffies;
++ cFYI(1, (" New time %ld ", cifsInfo->time));
++
++/* blksize needs to be multiple of two. So safer to default to blksize
++ and blkbits set in superblock so 2**blkbits and blksize will match */
++/* inode->i_blksize =
++ (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
++
++ /* Linux can not store file creation time unfortunately so we ignore it */
++ inode->i_atime =
++ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
++ inode->i_mtime =
++ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
++ inode->i_ctime =
++ cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
++ cFYI(0,
++ (" Attributes came in as 0x%x ", pfindData->Attributes));
++
++ /* set default mode. will override for dirs below */
++ if(atomic_read(&cifsInfo->inUse) == 0)
++ /* new inode, can safely set these fields */
++ inode->i_mode = cifs_sb->mnt_file_mode;
++
++ if (pfindData->Attributes & ATTR_REPARSE) {
++ /* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */
++ inode->i_mode |= S_IFLNK;
++ } else if (pfindData->Attributes & ATTR_DIRECTORY) {
++ /* override default perms since we do not do byte range locking on dirs */
++ inode->i_mode = cifs_sb->mnt_dir_mode;
++ inode->i_mode |= S_IFDIR;
++ } else {
++ inode->i_mode |= S_IFREG;
++ /* treat the dos attribute of read-only as read-only mode e.g. 555 */
++ if(cifsInfo->cifsAttrs & ATTR_READONLY)
++ inode->i_mode &= ~(S_IWUGO);
++ /* BB add code here - validate if device or weird share or device type? */
++ }
++ if(is_size_safe_to_change(cifsInfo)) {
++ /* can not safely change the file size here if the
++ client is writing to it due to potential races */
++ inode->i_size = le64_to_cpu(pfindData->EndOfFile);
++
++ /* 512 bytes (2**9) is the fake blocksize that must be used */
++ /* for this calculation */
++ inode->i_blocks = (512 - 1 + pfindData->AllocationSize)
++ >> 9;
++ }
++ pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
++
++ cFYI(1,
++ (" Size %ld and blocks %ld ",
++ (unsigned long) inode->i_size, inode->i_blocks));
++ inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
++
++ /* BB fill in uid and gid here? with help from winbind?
++ or retrieve from NTFS stream extended attribute */
++ if(atomic_read(&cifsInfo->inUse) == 0) {
++ inode->i_uid = cifs_sb->mnt_uid;
++ inode->i_gid = cifs_sb->mnt_gid;
++ /* set so we do not keep refreshing these fields with
++ bad data after user has changed them in memory */
++ atomic_set(&cifsInfo->inUse,1);
++ }
++
++ if (S_ISREG(inode->i_mode)) {
++ cFYI(1, (" File inode "));
++ inode->i_op = &cifs_file_inode_ops;
++ inode->i_fop = &cifs_file_ops;
++ inode->i_data.a_ops = &cifs_addr_ops;
++ } else if (S_ISDIR(inode->i_mode)) {
++ cFYI(1, (" Directory inode "));
++ inode->i_op = &cifs_dir_inode_ops;
++ inode->i_fop = &cifs_dir_ops;
++ } else if (S_ISLNK(inode->i_mode)) {
++ cFYI(1, (" Symbolic Link inode "));
++ inode->i_op = &cifs_symlink_inode_ops;
++ } else {
++ init_special_inode(inode, inode->i_mode,
++ kdev_t_to_nr(inode->i_rdev));
++ }
++ }
++ if(buf)
++ kfree(buf);
++ return rc;
++}
++
++void
++cifs_read_inode(struct inode *inode)
++{ /* gets root inode */
++ int xid;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsInodeInfo *cifs_inode;
++
++ cifs_sb = CIFS_SB(inode->i_sb);
++ xid = GetXid();
++
++ cifs_inode = CIFS_I(inode);
++ cifs_inode->cifsAttrs = ATTR_DIRECTORY;
++ atomic_set(&cifs_inode->inUse, 0);
++ cifs_inode->time = 0;
++ inode->i_blksize = CIFS_MAX_MSGSIZE;
++ inode->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
++
++ INIT_LIST_HEAD(&cifs_inode->openFileList);
++
++ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
++ cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid);
++ else
++ cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid);
++ /* can not call macro FreeXid here since in a void func */
++ _FreeXid(xid);
++}
++
++int
++cifs_unlink(struct inode *inode, struct dentry *direntry)
++{
++ int rc = 0;
++ int xid;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ char *full_path = NULL;
++ struct cifsInodeInfo *cifsInode;
++ FILE_BASIC_INFO * pinfo_buf;
++
++ cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
++
++ xid = GetXid();
++
++ cifs_sb = CIFS_SB(inode->i_sb);
++ pTcon = cifs_sb->tcon;
++
++/* Unlink can be called from rename so we can not grab
++ the sem here since we deadlock otherwise */
++/* down(&direntry->d_sb->s_vfs_rename_sem);*/
++ full_path = build_path_from_dentry(direntry);
++/* up(&direntry->d_sb->s_vfs_rename_sem);*/
++ if(full_path == NULL) {
++ FreeXid(xid);
++ return -ENOMEM;
++ }
++ rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
++
++ if (!rc) {
++ direntry->d_inode->i_nlink--;
++ } else if (rc == -ENOENT) {
++ d_drop(direntry);
++ } else if (rc == -ETXTBSY) {
++ int oplock = FALSE;
++ __u16 netfid;
++
++ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
++ CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
++ &netfid, &oplock, NULL, cifs_sb->local_nls);
++ if(rc==0) {
++ CIFSSMBRenameOpenFile(xid,pTcon,netfid,
++ NULL, cifs_sb->local_nls);
++ CIFSSMBClose(xid, pTcon, netfid);
++ direntry->d_inode->i_nlink--;
++ }
++ } else if (rc == -EACCES) {
++ /* try only if r/o attribute set in local lookup data? */
++ pinfo_buf = (FILE_BASIC_INFO *)kmalloc(sizeof(FILE_BASIC_INFO),GFP_KERNEL);
++ if(pinfo_buf) {
++ memset(pinfo_buf,0,sizeof(FILE_BASIC_INFO));
++ /* ATTRS set to normal clears r/o bit */
++ pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
++ rc = CIFSSMBSetTimes(xid, pTcon, full_path, pinfo_buf,
++ cifs_sb->local_nls);
++ kfree(pinfo_buf);
++ }
++ if(rc==0) {
++ rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
++ if (!rc) {
++ direntry->d_inode->i_nlink--;
++ } else if (rc == -ETXTBSY) {
++ int oplock = FALSE;
++ __u16 netfid;
++
++ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
++ CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
++ &netfid, &oplock, NULL, cifs_sb->local_nls);
++ if(rc==0) {
++ CIFSSMBRenameOpenFile(xid,pTcon,netfid,NULL,cifs_sb->local_nls);
++ CIFSSMBClose(xid, pTcon, netfid);
++ direntry->d_inode->i_nlink--;
++ }
++ /* BB if rc = -ETXTBUSY goto the rename logic BB */
++ }
++ }
++ }
++ cifsInode = CIFS_I(direntry->d_inode);
++ cifsInode->time = 0; /* will force revalidate to get info when needed */
++ direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
++ CURRENT_TIME;
++ cifsInode = CIFS_I(inode);
++ cifsInode->time = 0; /* force revalidate of dir as well */
++
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++ return rc;
++}
++
++int
++cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
++{
++ int rc = 0;
++ int xid;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ char *full_path = NULL;
++ struct inode *newinode = NULL;
++
++ cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode));
++
++ xid = GetXid();
++
++ cifs_sb = CIFS_SB(inode->i_sb);
++ pTcon = cifs_sb->tcon;
++
++ down(&inode->i_sb->s_vfs_rename_sem);
++ full_path = build_path_from_dentry(direntry);
++ up(&inode->i_sb->s_vfs_rename_sem);
++ if(full_path == NULL) {
++ FreeXid(xid);
++ return -ENOMEM;
++ }
++ /* BB add setting the equivalent of mode via CreateX w/ACLs */
++ rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls);
++ if (rc) {
++ cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
++ d_drop(direntry);
++ } else {
++ inode->i_nlink++;
++ if (pTcon->ses->capabilities & CAP_UNIX)
++ rc = cifs_get_inode_info_unix(&newinode, full_path,
++ inode->i_sb,xid);
++ else
++ rc = cifs_get_inode_info(&newinode, full_path,NULL,
++ inode->i_sb,xid);
++
++ direntry->d_op = &cifs_dentry_ops;
++ d_instantiate(direntry, newinode);
++ if(direntry->d_inode)
++ direntry->d_inode->i_nlink = 2;
++ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
++ CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
++ (__u64)-1,
++ (__u64)-1,
++ 0 /* dev_t */,
++ cifs_sb->local_nls);
++ else { /* BB to be implemented via Windows secrty descriptors*/
++ /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
++ }
++ }
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++
++ return rc;
++}
++
++int
++cifs_rmdir(struct inode *inode, struct dentry *direntry)
++{
++ int rc = 0;
++ int xid;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ char *full_path = NULL;
++ struct cifsInodeInfo *cifsInode;
++
++ cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));
++
++ xid = GetXid();
++
++ cifs_sb = CIFS_SB(inode->i_sb);
++ pTcon = cifs_sb->tcon;
++
++ down(&inode->i_sb->s_vfs_rename_sem);
++ full_path = build_path_from_dentry(direntry);
++ up(&inode->i_sb->s_vfs_rename_sem);
++ if(full_path == NULL) {
++ FreeXid(xid);
++ return -ENOMEM;
++ }
++
++ rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls);
++
++ if (!rc) {
++ inode->i_nlink--;
++ direntry->d_inode->i_size = 0;
++ direntry->d_inode->i_nlink = 0;
++ }
++
++ cifsInode = CIFS_I(direntry->d_inode);
++ cifsInode->time = 0; /* force revalidate to go get info when needed */
++ direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
++ CURRENT_TIME;
++
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++ return rc;
++}
++
++int
++cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
++ struct inode *target_inode, struct dentry *target_direntry)
++{
++ char *fromName;
++ char *toName;
++ struct cifs_sb_info *cifs_sb_source;
++ struct cifs_sb_info *cifs_sb_target;
++ struct cifsTconInfo *pTcon;
++ int xid;
++ int rc = 0;
++
++ xid = GetXid();
++
++ cifs_sb_target = CIFS_SB(target_inode->i_sb);
++ cifs_sb_source = CIFS_SB(source_inode->i_sb);
++ pTcon = cifs_sb_source->tcon;
++
++ if (pTcon != cifs_sb_target->tcon) {
++ FreeXid(xid);
++ return -EXDEV; /* BB actually could be allowed if same server, but
++ different share. Might eventually add support for this */
++ }
++
++ /* we already have the rename sem so we do not need
++ to grab it again here to protect the path integrity */
++ fromName = build_path_from_dentry(source_direntry);
++ toName = build_path_from_dentry(target_direntry);
++ if((fromName == NULL) || (toName == NULL)) {
++ rc = -ENOMEM;
++ goto cifs_rename_exit;
++ }
++
++ rc = CIFSSMBRename(xid, pTcon, fromName, toName,
++ cifs_sb_source->local_nls);
++ if(rc == -EEXIST) {
++ /* check if they are the same file
++ because rename of hardlinked files is a noop */
++ FILE_UNIX_BASIC_INFO * info_buf_source;
++ FILE_UNIX_BASIC_INFO * info_buf_target;
++
++ info_buf_source =
++ kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),GFP_KERNEL);
++ if(info_buf_source != NULL) {
++ info_buf_target = info_buf_source+1;
++ rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
++ info_buf_source, cifs_sb_source->local_nls);
++ if(rc == 0) {
++ rc = CIFSSMBUnixQPathInfo(xid,pTcon,toName,
++ info_buf_target,
++ cifs_sb_target->local_nls);
++ }
++ if((rc == 0) &&
++ (info_buf_source->UniqueId ==
++ info_buf_target->UniqueId)) {
++ /* do not rename since the files are hardlinked
++ which is a noop */
++ } else {
++ /* we either can not tell the files are hardlinked
++ (as with Windows servers) or files are not hardlinked
++ so delete the target manually before renaming to
++ follow POSIX rather than Windows semantics */
++ cifs_unlink(target_inode, target_direntry);
++ rc = CIFSSMBRename(xid, pTcon, fromName, toName,
++ cifs_sb_source->local_nls);
++ }
++ kfree(info_buf_source);
++ } /* if we can not get memory just leave rc as EEXIST */
++ }
++
++ if((rc == -EIO)||(rc == -EEXIST)) {
++ int oplock = FALSE;
++ __u16 netfid;
++
++ rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
++ CREATE_NOT_DIR,
++ &netfid, &oplock, NULL, cifs_sb_source->local_nls);
++ if(rc==0) {
++ CIFSSMBRenameOpenFile(xid,pTcon,netfid,
++ toName, cifs_sb_source->local_nls);
++ CIFSSMBClose(xid, pTcon, netfid);
++ }
++ }
++
++cifs_rename_exit:
++ if (fromName)
++ kfree(fromName);
++ if (toName)
++ kfree(toName);
++
++ FreeXid(xid);
++ return rc;
++}
++
++int
++cifs_revalidate(struct dentry *direntry)
++{
++ int xid;
++ int rc = 0;
++ char *full_path;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsInodeInfo *cifsInode;
++ loff_t local_size;
++ time_t local_mtime;
++ int invalidate_inode = FALSE;
++
++ if(direntry->d_inode == NULL)
++ return -ENOENT;
++
++ cifsInode = CIFS_I(direntry->d_inode);
++
++ if(cifsInode == NULL)
++ return -ENOENT;
++
++ /* no sense revalidating inode info on file that no one can write */
++ if(CIFS_I(direntry->d_inode)->clientCanCacheRead)
++ return rc;
++
++ xid = GetXid();
++
++ cifs_sb = CIFS_SB(direntry->d_sb);
++
++ /* can not safely grab the rename sem here if
++ rename calls revalidate since that would deadlock */
++ full_path = build_path_from_dentry(direntry);
++ if(full_path == NULL) {
++ FreeXid(xid);
++ return -ENOMEM;
++ }
++ cFYI(1,
++ ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld",
++ full_path, direntry->d_inode,
++ direntry->d_inode->i_count.counter, direntry,
++ direntry->d_time, jiffies));
++
++ if (cifsInode->time == 0){
++ /* was set to zero previously to force revalidate */
++ } else if (time_before(jiffies, cifsInode->time + HZ) && lookupCacheEnabled) {
++ if((S_ISREG(direntry->d_inode->i_mode) == 0) ||
++ (direntry->d_inode->i_nlink == 1)) {
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++ return rc;
++ } else {
++ cFYI(1,("Have to revalidate file due to hardlinks"));
++ }
++ }
++
++ /* save mtime and size */
++ local_mtime = direntry->d_inode->i_mtime;
++ local_size = direntry->d_inode->i_size;
++
++ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
++ rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
++ direntry->d_sb,xid);
++ if(rc) {
++ cFYI(1,("error on getting revalidate info %d",rc));
++/* if(rc != -ENOENT)
++ rc = 0; */ /* BB should we cache info on certain errors? */
++ }
++ } else {
++ rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
++ direntry->d_sb,xid);
++ if(rc) {
++ cFYI(1,("error on getting revalidate info %d",rc));
++/* if(rc != -ENOENT)
++ rc = 0; */ /* BB should we cache info on certain errors? */
++ }
++ }
++ /* should we remap certain errors, access denied?, to zero */
++
++ /* if not oplocked, we invalidate inode pages if mtime
++ or file size had changed on server */
++
++ if((local_mtime == direntry->d_inode->i_mtime) &&
++ (local_size == direntry->d_inode->i_size)) {
++ cFYI(1,("cifs_revalidate - inode unchanged"));
++ } else {
++ /* file may have changed on server */
++ if(cifsInode->clientCanCacheRead) {
++ /* no need to invalidate inode pages since we were
++ the only ones who could have modified the file and
++ the server copy is staler than ours */
++ } else {
++ invalidate_inode = TRUE;
++ }
++ }
++
++ /* can not grab this sem since kernel filesys locking
++ documentation indicates i_sem may be taken by the kernel
++ on lookup and rename which could deadlock if we grab
++ the i_sem here as well */
++/* down(&direntry->d_inode->i_sem);*/
++ /* need to write out dirty pages here */
++ if(direntry->d_inode->i_mapping) {
++ /* do we need to lock inode until after invalidate completes below? */
++ filemap_fdatasync(direntry->d_inode->i_mapping);
++ }
++ if(invalidate_inode) {
++ filemap_fdatawait(direntry->d_inode->i_mapping);
++ /* may eventually have to do this for open files too */
++ if(list_empty(&(cifsInode->openFileList))) {
++ /* Has changed on server - flush read ahead pages */
++ cFYI(1,("Invalidating read ahead data on closed file"));
++ invalidate_inode_pages(direntry->d_inode);
++ }
++ }
++/* up(&direntry->d_inode->i_sem);*/
++
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++
++ return rc;
++}
++
++/* int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
++{
++ int err = cifs_revalidate(dentry);
++ if (!err)
++ generic_fillattr(dentry->d_inode, stat);
++ return err;
++} */
++
++void
++cifs_truncate_file(struct inode *inode)
++{ /* BB remove - may not need this function after all BB */
++ int xid;
++ int rc = -EIO;
++ int found = FALSE;
++ struct cifsFileInfo *open_file = NULL;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ struct cifsInodeInfo *cifsInode;
++ struct dentry *dirent;
++ struct list_head * tmp;
++ char *full_path = NULL;
++
++ xid = GetXid();
++
++ cifs_sb = CIFS_SB(inode->i_sb);
++ pTcon = cifs_sb->tcon;
++
++ /* To avoid spurious oplock breaks from server, in the case
++ of inodes that we already have open, avoid doing path
++ based setting of file size if we can do it by handle.
++ This keeps our caching token (oplock) and avoids
++ timeouts when the local oplock break takes longer to flush
++ writebehind data than the SMB timeout for the SetPathInfo
++ request would allow */
++ read_lock(&GlobalSMBSeslock);
++ cifsInode = CIFS_I(inode);
++ list_for_each(tmp, &cifsInode->openFileList) {
++ open_file = list_entry(tmp,struct cifsFileInfo, flist);
++ /* We check if file is open for writing first */
++ if((open_file->pfile) && (!open_file->invalidHandle) &&
++ ((open_file->pfile->f_flags & O_RDWR) ||
++ (open_file->pfile->f_flags & O_WRONLY))) {
++ read_unlock(&GlobalSMBSeslock);
++ found = TRUE;
++ rc = CIFSSMBSetFileSize(xid, pTcon, inode->i_size,
++ open_file->netfid,open_file->pid,FALSE);
++ if(rc == 0) {
++ FreeXid(xid);
++ return;
++ }
++ /* Do not need reopen and retry on EAGAIN since we will
++ retry by pathname below */
++ if(rc == -EAGAIN)
++ rc = -EHOSTDOWN;
++
++ break; /* now that we found one valid file handle no
++ sense continuing to loop trying others */
++ }
++ }
++ if(found == FALSE)
++ read_unlock(&GlobalSMBSeslock);
++
++ if (list_empty(&inode->i_dentry)) {
++ cERROR(1,
++ ("Can not get pathname from empty dentry in inode 0x%p ",
++ inode));
++ FreeXid(xid);
++ return;
++ }
++
++ dirent = list_entry(inode->i_dentry.next, struct dentry, d_alias);
++ if (dirent) {
++ full_path = build_path_from_dentry(dirent);
++ rc = CIFSSMBSetEOF(xid, pTcon, full_path, inode->i_size,FALSE,
++ cifs_sb->local_nls);
++ cFYI(1,(" SetEOF (truncate) rc = %d",rc));
++ if (!rc)
++ CIFSSMBSetEOF(xid,pTcon,full_path,inode->i_size,TRUE,cifs_sb->local_nls);
++ /* allocation size setting seems optional so ignore return code */
++ }
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++ return;
++}
++
++static int cifs_truncate_page(struct address_space *mapping, loff_t from)
++{
++ unsigned long index = from >> PAGE_CACHE_SHIFT;
++ unsigned offset = from & (PAGE_CACHE_SIZE-1);
++ struct page *page;
++ char *kaddr;
++ int rc = 0;
++
++ page = grab_cache_page(mapping, index);
++ if (!page)
++ return -ENOMEM;
++
++ kaddr = kmap_atomic(page, KM_USER0);
++ memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
++ flush_dcache_page(page);
++ kunmap_atomic(kaddr, KM_USER0);
++ unlock_page(page);
++ page_cache_release(page);
++ return rc;
++}
++
++int
++cifs_setattr(struct dentry *direntry, struct iattr *attrs)
++{
++ int xid;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ char *full_path = NULL;
++ int rc = -EACCES;
++ int found = FALSE;
++ struct cifsFileInfo *open_file = NULL;
++ FILE_BASIC_INFO time_buf;
++ int set_time = FALSE;
++ __u64 mode = 0xFFFFFFFFFFFFFFFFULL;
++ __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
++ __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
++ struct cifsInodeInfo *cifsInode;
++ struct list_head * tmp;
++
++ xid = GetXid();
++
++ cFYI(1,
++ (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
++ direntry->d_name.name, attrs->ia_valid));
++ cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
++ pTcon = cifs_sb->tcon;
++
++ down(&direntry->d_sb->s_vfs_rename_sem);
++ full_path = build_path_from_dentry(direntry);
++ up(&direntry->d_sb->s_vfs_rename_sem);
++ if(full_path == NULL) {
++ FreeXid(xid);
++ return -ENOMEM;
++ }
++ cifsInode = CIFS_I(direntry->d_inode);
++
++ /* BB check if we need to refresh inode from server now ? BB */
++
++ /* need to flush data before changing file size on server */
++ filemap_fdatasync(direntry->d_inode->i_mapping);
++
++ if (attrs->ia_valid & ATTR_SIZE) {
++ read_lock(&GlobalSMBSeslock);
++ /* To avoid spurious oplock breaks from server, in the case
++ of inodes that we already have open, avoid doing path
++ based setting of file size if we can do it by handle.
++ This keeps our caching token (oplock) and avoids
++ timeouts when the local oplock break takes longer to flush
++ writebehind data than the SMB timeout for the SetPathInfo
++ request would allow */
++ list_for_each(tmp, &cifsInode->openFileList) {
++ open_file = list_entry(tmp,struct cifsFileInfo, flist);
++ /* We check if file is open for writing first */
++ if((open_file->pfile) &&
++ ((open_file->pfile->f_flags & O_RDWR) ||
++ (open_file->pfile->f_flags & O_WRONLY))) {
++ if(open_file->invalidHandle == FALSE) {
++ /* we found a valid, writeable network file
++ handle to use to try to set the file size */
++ __u16 nfid = open_file->netfid;
++ __u32 npid = open_file->pid;
++ read_unlock(&GlobalSMBSeslock);
++ found = TRUE;
++ rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
++ nfid,npid,FALSE);
++ cFYI(1,("SetFileSize by handle (setattrs) rc = %d",rc));
++ /* Do not need reopen and retry on EAGAIN since we will
++ retry by pathname below */
++
++ break; /* now that we found one valid file handle no
++ sense continuing to loop trying others */
++ }
++ }
++ }
++ if(found == FALSE) {
++ read_unlock(&GlobalSMBSeslock);
++ }
++
++
++ if(rc != 0) {
++ /* Set file size by pathname rather than by handle either
++ because no valid, writeable file handle for it was found or
++ because there was an error setting it by handle */
++ rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,FALSE,
++ cifs_sb->local_nls);
++ cFYI(1,(" SetEOF by path (setattrs) rc = %d",rc));
++ }
++
++ /* Server is ok setting allocation size implicitly - no need to call: */
++ /*CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);*/
++
++ if (rc == 0) {
++ rc = vmtruncate(direntry->d_inode, attrs->ia_size);
++ cifs_truncate_page(direntry->d_inode->i_mapping, direntry->d_inode->i_size);
++ }
++ }
++ if (attrs->ia_valid & ATTR_UID) {
++ cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid));
++ uid = attrs->ia_uid;
++ /* entry->uid = cpu_to_le16(attr->ia_uid); */
++ }
++ if (attrs->ia_valid & ATTR_GID) {
++ cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid));
++ gid = attrs->ia_gid;
++ /* entry->gid = cpu_to_le16(attr->ia_gid); */
++ }
++
++ time_buf.Attributes = 0;
++ if (attrs->ia_valid & ATTR_MODE) {
++ cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode));
++ mode = attrs->ia_mode;
++ /* entry->mode = cpu_to_le16(attr->ia_mode); */
++ }
++
++ if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
++ && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
++ rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
++ 0 /* dev_t */, cifs_sb->local_nls);
++ else if (attrs->ia_valid & ATTR_MODE) {
++ if((mode & S_IWUGO) == 0) /* not writeable */ {
++ if((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
++ time_buf.Attributes =
++ cpu_to_le32(cifsInode->cifsAttrs | ATTR_READONLY);
++ } else if((mode & S_IWUGO) == S_IWUGO) {
++ if(cifsInode->cifsAttrs & ATTR_READONLY)
++ time_buf.Attributes =
++ cpu_to_le32(cifsInode->cifsAttrs & (~ATTR_READONLY));
++ }
++ /* BB to be implemented - via Windows security descriptors or streams */
++ /* CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,uid,gid,cifs_sb->local_nls);*/
++ }
++
++ if (attrs->ia_valid & ATTR_ATIME) {
++ set_time = TRUE;
++ time_buf.LastAccessTime =
++ cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
++ } else
++ time_buf.LastAccessTime = 0;
++
++ if (attrs->ia_valid & ATTR_MTIME) {
++ set_time = TRUE;
++ time_buf.LastWriteTime =
++ cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
++ } else
++ time_buf.LastWriteTime = 0;
++
++ if (attrs->ia_valid & ATTR_CTIME) {
++ set_time = TRUE;
++ time_buf.ChangeTime =
++ cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
++ } else
++ time_buf.ChangeTime = 0;
++
++ if (set_time | time_buf.Attributes) {
++ /* BB what if setting one attribute fails
++ (such as size) but time setting works */
++ time_buf.CreationTime = 0; /* do not change */
++ /* In the future we should experiment - try setting timestamps
++ via Handle (SetFileInfo) instead of by path */
++ rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
++ cifs_sb->local_nls);
++ }
++
++ /* do not need local check to inode_check_ok since the server does that */
++ if (!rc)
++ rc = inode_setattr(direntry->d_inode, attrs);
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++ return rc;
++}
++
++void
++cifs_delete_inode(struct inode *inode)
++{
++ cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
++ /* may have to add back in if and when safe distributed caching of
++ directories added e.g. via FindNotify */
++}
+diff -urN linux-2.4.29.old/fs/cifs/link.c linux-2.4.29/fs/cifs/link.c
+--- linux-2.4.29.old/fs/cifs/link.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/link.c 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,328 @@
++/*
++ * fs/cifs/link.c
++ *
++ * Copyright (C) International Business Machines Corp., 2002,2003
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <linux/fs.h>
++#include <linux/stat.h>
++#include "cifsfs.h"
++#include "cifspdu.h"
++#include "cifsglob.h"
++#include "cifsproto.h"
++#include "cifs_debug.h"
++#include "cifs_fs_sb.h"
++
++int
++cifs_hardlink(struct dentry *old_file, struct inode *inode,
++ struct dentry *direntry)
++{
++ int rc = -EACCES;
++ int xid;
++ char *fromName = NULL;
++ char *toName = NULL;
++ struct cifs_sb_info *cifs_sb_target;
++ struct cifsTconInfo *pTcon;
++ struct cifsInodeInfo *cifsInode;
++
++ xid = GetXid();
++
++ cifs_sb_target = CIFS_SB(inode->i_sb);
++ pTcon = cifs_sb_target->tcon;
++
++/* No need to check for cross device links since server will do that
++ BB note DFS case in future though (when we may have to check) */
++
++ down(&inode->i_sb->s_vfs_rename_sem);
++ fromName = build_path_from_dentry(old_file);
++ toName = build_path_from_dentry(direntry);
++ up(&inode->i_sb->s_vfs_rename_sem);
++ if((fromName == NULL) || (toName == NULL)) {
++ rc = -ENOMEM;
++ goto cifs_hl_exit;
++ }
++
++ if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
++ rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
++ cifs_sb_target->local_nls);
++ else {
++ rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
++ cifs_sb_target->local_nls);
++ if(rc == -EIO)
++ rc = -EOPNOTSUPP;
++ }
++
++/* if (!rc) */
++ {
++ /* renew_parental_timestamps(old_file);
++ inode->i_nlink++;
++ mark_inode_dirty(inode);
++ d_instantiate(direntry, inode); */
++ /* BB add call to either mark inode dirty or refresh its data and timestamp to current time */
++ }
++ d_drop(direntry); /* force new lookup from server */
++ cifsInode = CIFS_I(old_file->d_inode);
++ cifsInode->time = 0; /* will force revalidate to go get info when needed */
++
++cifs_hl_exit:
++ if (fromName)
++ kfree(fromName);
++ if (toName)
++ kfree(toName);
++ FreeXid(xid);
++ return rc;
++}
++
++int
++cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
++{
++ struct inode *inode = direntry->d_inode;
++ int rc = -EACCES;
++ int xid;
++ char *full_path = NULL;
++ char * target_path;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++
++ xid = GetXid();
++
++ down(&direntry->d_sb->s_vfs_rename_sem);
++ full_path = build_path_from_dentry(direntry);
++ up(&direntry->d_sb->s_vfs_rename_sem);
++
++ if(full_path == NULL) {
++ FreeXid(xid);
++ return -ENOMEM;
++ }
++ cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
++ cifs_sb = CIFS_SB(inode->i_sb);
++ pTcon = cifs_sb->tcon;
++ target_path = kmalloc(PATH_MAX, GFP_KERNEL);
++ if(target_path == NULL) {
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++ return -ENOMEM;
++ }
++ /* can not call the following line due to EFAULT in vfs_readlink which is presumably expecting a user space buffer */
++ /* length = cifs_readlink(direntry,target_path, sizeof(target_path) - 1); */
++
++/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
++ if (pTcon->ses->capabilities & CAP_UNIX)
++ rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
++ target_path,
++ PATH_MAX-1,
++ cifs_sb->local_nls);
++ else {
++ /* rc = CIFSSMBQueryReparseLinkInfo */
++ /* BB Add code to Query ReparsePoint info */
++ }
++ /* BB Anything else to do to handle recursive links? */
++ /* BB Should we be using page symlink ops here? */
++
++ if (rc == 0) {
++
++/* BB Add special case check for Samba DFS symlinks */
++
++ target_path[PATH_MAX-1] = 0;
++ rc = vfs_follow_link(nd, target_path);
++ }
++ /* else EACCESS */
++
++ if (target_path)
++ kfree(target_path);
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++ return rc;
++}
++
++int
++cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
++{
++ int rc = -EOPNOTSUPP;
++ int xid;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ char *full_path = NULL;
++ struct inode *newinode = NULL;
++
++ xid = GetXid();
++
++ cifs_sb = CIFS_SB(inode->i_sb);
++ pTcon = cifs_sb->tcon;
++
++ down(&inode->i_sb->s_vfs_rename_sem);
++ full_path = build_path_from_dentry(direntry);
++ up(&inode->i_sb->s_vfs_rename_sem);
++
++ if(full_path == NULL) {
++ FreeXid(xid);
++ return -ENOMEM;
++ }
++
++ cFYI(1, ("Full path: %s ", full_path));
++ cFYI(1, ("symname is %s", symname));
++
++ /* BB what if DFS and this volume is on different share? BB */
++ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
++ rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
++ cifs_sb->local_nls);
++ /* else
++ rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,cifs_sb_target->local_nls); */
++
++ if (rc == 0) {
++ if (pTcon->ses->capabilities & CAP_UNIX)
++ rc = cifs_get_inode_info_unix(&newinode, full_path,
++ inode->i_sb,xid);
++ else
++ rc = cifs_get_inode_info(&newinode, full_path, NULL,
++ inode->i_sb,xid);
++
++ if (rc != 0) {
++ cFYI(1,
++ ("Create symlink worked but get_inode_info failed with rc = %d ",
++ rc));
++ } else {
++ direntry->d_op = &cifs_dentry_ops;
++ d_instantiate(direntry, newinode);
++ }
++ }
++
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++ return rc;
++}
++
++int
++cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
++{
++ struct inode *inode = direntry->d_inode;
++ int rc = -EACCES;
++ int xid;
++ int oplock = FALSE;
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo *pTcon;
++ char *full_path = NULL;
++ char *tmp_path = NULL;
++ char * tmpbuffer;
++ unsigned char * referrals = NULL;
++ int num_referrals = 0;
++ int len;
++ __u16 fid;
++
++ xid = GetXid();
++ cifs_sb = CIFS_SB(inode->i_sb);
++ pTcon = cifs_sb->tcon;
++
++/* BB would it be safe against deadlock to grab this sem
++ even though rename itself grabs the sem and calls lookup? */
++/* down(&inode->i_sb->s_vfs_rename_sem);*/
++ full_path = build_path_from_dentry(direntry);
++/* up(&inode->i_sb->s_vfs_rename_sem);*/
++
++ if(full_path == NULL) {
++ FreeXid(xid);
++ return -ENOMEM;
++ }
++
++ cFYI(1,
++ ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
++ full_path, inode, pBuffer, buflen));
++ if(buflen > PATH_MAX)
++ len = PATH_MAX;
++ else
++ len = buflen;
++ tmpbuffer = kmalloc(len,GFP_KERNEL);
++ if(tmpbuffer == NULL) {
++ if (full_path)
++ kfree(full_path);
++ FreeXid(xid);
++ return -ENOMEM;
++ }
++
++/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
++ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
++ rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
++ tmpbuffer,
++ len - 1,
++ cifs_sb->local_nls);
++ else {
++ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
++ OPEN_REPARSE_POINT,&fid, &oplock, NULL, cifs_sb->local_nls);
++ if(!rc) {
++ rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
++ tmpbuffer,
++ len - 1,
++ fid,
++ cifs_sb->local_nls);
++ if(CIFSSMBClose(xid, pTcon, fid)) {
++ cFYI(1,("Error closing junction point (open for ioctl)"));
++ }
++ if(rc == -EIO) {
++ /* Query if DFS Junction */
++ tmp_path =
++ kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
++ GFP_KERNEL);
++ if (tmp_path) {
++ strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
++ strncat(tmp_path, full_path, MAX_PATHCONF);
++ rc = get_dfs_path(xid, pTcon->ses, tmp_path,
++ cifs_sb->local_nls, &num_referrals, &referrals);
++ cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc));
++ if((num_referrals == 0) && (rc == 0))
++ rc = -EACCES;
++ else {
++ cFYI(1,("num referral: %d",num_referrals));
++ if(referrals) {
++ cFYI(1,("referral string: %s ",referrals));
++ strncpy(tmpbuffer, referrals, len-1);
++ }
++ }
++ if(referrals)
++ kfree(referrals);
++ kfree(tmp_path);
++ if(referrals) {
++ kfree(referrals);
++ }
++ }
++ /* BB add code like else decode referrals then memcpy to
++ tmpbuffer and free referrals string array BB */
++ }
++ }
++ }
++ /* BB Anything else to do to handle recursive links? */
++ /* BB Should we be using page ops here? */
++
++ /* BB null terminate returned string in pBuffer? BB */
++ if (rc == 0) {
++ rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer);
++ cFYI(1,
++ ("vfs_readlink called from cifs_readlink returned %d",
++ rc));
++ }
++
++ if (tmpbuffer) {
++ kfree(tmpbuffer);
++ }
++ if (full_path) {
++ kfree(full_path);
++ }
++ FreeXid(xid);
++ return rc;
++}
+diff -urN linux-2.4.29.old/fs/cifs/Makefile linux-2.4.29/fs/cifs/Makefile
+--- linux-2.4.29.old/fs/cifs/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/Makefile 2004-07-14 00:25:04.000000000 +0200
+@@ -0,0 +1,10 @@
++#
++# Makefile for Linux CIFS VFS client
++#
++O_TARGET := cifs.o
++
++obj-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o cifsencrypt.o
++
++obj-m := $(O_TARGET)
++
++include $(TOPDIR)/Rules.make
+diff -urN linux-2.4.29.old/fs/cifs/md4.c linux-2.4.29/fs/cifs/md4.c
+--- linux-2.4.29.old/fs/cifs/md4.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/md4.c 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,203 @@
++/*
++ Unix SMB/Netbios implementation.
++ Version 1.9.
++ a implementation of MD4 designed for use in the SMB authentication protocol
++ Copyright (C) Andrew Tridgell 1997-1998.
++ Modified by Steve French (sfrench@us.ibm.com) 2002-2003
++
++ 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 <linux/module.h>
++#include <linux/fs.h>
++/* NOTE: This code makes no attempt to be fast! */
++
++static __u32
++F(__u32 X, __u32 Y, __u32 Z)
++{
++ return (X & Y) | ((~X) & Z);
++}
++
++static __u32
++G(__u32 X, __u32 Y, __u32 Z)
++{
++ return (X & Y) | (X & Z) | (Y & Z);
++}
++
++static __u32
++H(__u32 X, __u32 Y, __u32 Z)
++{
++ return X ^ Y ^ Z;
++}
++
++static __u32
++lshift(__u32 x, int s)
++{
++ x &= 0xFFFFFFFF;
++ return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
++}
++
++#define ROUND1(a,b,c,d,k,s) (*a) = lshift((*a) + F(*b,*c,*d) + X[k], s)
++#define ROUND2(a,b,c,d,k,s) (*a) = lshift((*a) + G(*b,*c,*d) + X[k] + (__u32)0x5A827999,s)
++#define ROUND3(a,b,c,d,k,s) (*a) = lshift((*a) + H(*b,*c,*d) + X[k] + (__u32)0x6ED9EBA1,s)
++
++/* this applies md4 to 64 byte chunks */
++static void
++mdfour64(__u32 * M, __u32 * A, __u32 *B, __u32 * C, __u32 *D)
++{
++ int j;
++ __u32 AA, BB, CC, DD;
++ __u32 X[16];
++
++
++ for (j = 0; j < 16; j++)
++ X[j] = M[j];
++
++ AA = *A;
++ BB = *B;
++ CC = *C;
++ DD = *D;
++
++ ROUND1(A, B, C, D, 0, 3);
++ ROUND1(D, A, B, C, 1, 7);
++ ROUND1(C, D, A, B, 2, 11);
++ ROUND1(B, C, D, A, 3, 19);
++ ROUND1(A, B, C, D, 4, 3);
++ ROUND1(D, A, B, C, 5, 7);
++ ROUND1(C, D, A, B, 6, 11);
++ ROUND1(B, C, D, A, 7, 19);
++ ROUND1(A, B, C, D, 8, 3);
++ ROUND1(D, A, B, C, 9, 7);
++ ROUND1(C, D, A, B, 10, 11);
++ ROUND1(B, C, D, A, 11, 19);
++ ROUND1(A, B, C, D, 12, 3);
++ ROUND1(D, A, B, C, 13, 7);
++ ROUND1(C, D, A, B, 14, 11);
++ ROUND1(B, C, D, A, 15, 19);
++
++ ROUND2(A, B, C, D, 0, 3);
++ ROUND2(D, A, B, C, 4, 5);
++ ROUND2(C, D, A, B, 8, 9);
++ ROUND2(B, C, D, A, 12, 13);
++ ROUND2(A, B, C, D, 1, 3);
++ ROUND2(D, A, B, C, 5, 5);
++ ROUND2(C, D, A, B, 9, 9);
++ ROUND2(B, C, D, A, 13, 13);
++ ROUND2(A, B, C, D, 2, 3);
++ ROUND2(D, A, B, C, 6, 5);
++ ROUND2(C, D, A, B, 10, 9);
++ ROUND2(B, C, D, A, 14, 13);
++ ROUND2(A, B, C, D, 3, 3);
++ ROUND2(D, A, B, C, 7, 5);
++ ROUND2(C, D, A, B, 11, 9);
++ ROUND2(B, C, D, A, 15, 13);
++
++ ROUND3(A, B, C, D, 0, 3);
++ ROUND3(D, A, B, C, 8, 9);
++ ROUND3(C, D, A, B, 4, 11);
++ ROUND3(B, C, D, A, 12, 15);
++ ROUND3(A, B, C, D, 2, 3);
++ ROUND3(D, A, B, C, 10, 9);
++ ROUND3(C, D, A, B, 6, 11);
++ ROUND3(B, C, D, A, 14, 15);
++ ROUND3(A, B, C, D, 1, 3);
++ ROUND3(D, A, B, C, 9, 9);
++ ROUND3(C, D, A, B, 5, 11);
++ ROUND3(B, C, D, A, 13, 15);
++ ROUND3(A, B, C, D, 3, 3);
++ ROUND3(D, A, B, C, 11, 9);
++ ROUND3(C, D, A, B, 7, 11);
++ ROUND3(B, C, D, A, 15, 15);
++
++ *A += AA;
++ *B += BB;
++ *C += CC;
++ *D += DD;
++
++ *A &= 0xFFFFFFFF;
++ *B &= 0xFFFFFFFF;
++ *C &= 0xFFFFFFFF;
++ *D &= 0xFFFFFFFF;
++
++ for (j = 0; j < 16; j++)
++ X[j] = 0;
++}
++
++static void
++copy64(__u32 * M, unsigned char *in)
++{
++ int i;
++
++ for (i = 0; i < 16; i++)
++ M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) |
++ (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0);
++}
++
++static void
++copy4(unsigned char *out, __u32 x)
++{
++ out[0] = x & 0xFF;
++ out[1] = (x >> 8) & 0xFF;
++ out[2] = (x >> 16) & 0xFF;
++ out[3] = (x >> 24) & 0xFF;
++}
++
++/* produce a md4 message digest from data of length n bytes */
++void
++mdfour(unsigned char *out, unsigned char *in, int n)
++{
++ unsigned char buf[128];
++ __u32 M[16];
++ __u32 b = n * 8;
++ int i;
++ __u32 A = 0x67452301;
++ __u32 B = 0xefcdab89;
++ __u32 C = 0x98badcfe;
++ __u32 D = 0x10325476;
++
++ while (n > 64) {
++ copy64(M, in);
++ mdfour64(M,&A,&B, &C, &D);
++ in += 64;
++ n -= 64;
++ }
++
++ for (i = 0; i < 128; i++)
++ buf[i] = 0;
++ memcpy(buf, in, n);
++ buf[n] = 0x80;
++
++ if (n <= 55) {
++ copy4(buf + 56, b);
++ copy64(M, buf);
++ mdfour64(M, &A, &B, &C, &D);
++ } else {
++ copy4(buf + 120, b);
++ copy64(M, buf);
++ mdfour64(M, &A, &B, &C, &D);
++ copy64(M, buf + 64);
++ mdfour64(M, &A, &B, &C, &D);
++ }
++
++ for (i = 0; i < 128; i++)
++ buf[i] = 0;
++ copy64(M, buf);
++
++ copy4(out, A);
++ copy4(out + 4, B);
++ copy4(out + 8, C);
++ copy4(out + 12, D);
++
++ A = B = C = D = 0;
++}
+diff -urN linux-2.4.29.old/fs/cifs/md5.c linux-2.4.29/fs/cifs/md5.c
+--- linux-2.4.29.old/fs/cifs/md5.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/md5.c 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,363 @@
++/*
++ * This code implements the MD5 message-digest algorithm.
++ * The algorithm is due to Ron Rivest. This code was
++ * written by Colin Plumb in 1993, no copyright is claimed.
++ * This code is in the public domain; do with it what you wish.
++ *
++ * Equivalent code is available from RSA Data Security, Inc.
++ * This code has been tested against that, and is equivalent,
++ * except that you don't need to include two pages of legalese
++ * with every copy.
++ *
++ * To compute the message digest of a chunk of bytes, declare an
++ * MD5Context structure, pass it to MD5Init, call MD5Update as
++ * needed on buffers full of bytes, and then call MD5Final, which
++ * will fill a supplied 16-byte array with the digest.
++ */
++
++/* This code slightly modified to fit into Samba by
++ abartlet@samba.org Jun 2001
++ and to fit the cifs vfs by
++ Steve French sfrench@us.ibm.com */
++
++#include <linux/string.h>
++#include "md5.h"
++
++static void MD5Transform(__u32 buf[4], __u32 const in[16]);
++
++/*
++ * Note: this code is harmless on little-endian machines.
++ */
++static void
++byteReverse(unsigned char *buf, unsigned longs)
++{
++ __u32 t;
++ do {
++ t = (__u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
++ ((unsigned) buf[1] << 8 | buf[0]);
++ *(__u32 *) buf = t;
++ buf += 4;
++ } while (--longs);
++}
++
++/*
++ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
++ * initialization constants.
++ */
++void
++MD5Init(struct MD5Context *ctx)
++{
++ ctx->buf[0] = 0x67452301;
++ ctx->buf[1] = 0xefcdab89;
++ ctx->buf[2] = 0x98badcfe;
++ ctx->buf[3] = 0x10325476;
++
++ ctx->bits[0] = 0;
++ ctx->bits[1] = 0;
++}
++
++/*
++ * Update context to reflect the concatenation of another buffer full
++ * of bytes.
++ */
++void
++MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
++{
++ register __u32 t;
++
++ /* Update bitcount */
++
++ t = ctx->bits[0];
++ if ((ctx->bits[0] = t + ((__u32) len << 3)) < t)
++ ctx->bits[1]++; /* Carry from low to high */
++ ctx->bits[1] += len >> 29;
++
++ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
++
++ /* Handle any leading odd-sized chunks */
++
++ if (t) {
++ unsigned char *p = (unsigned char *) ctx->in + t;
++
++ t = 64 - t;
++ if (len < t) {
++ memmove(p, buf, len);
++ return;
++ }
++ memmove(p, buf, t);
++ byteReverse(ctx->in, 16);
++ MD5Transform(ctx->buf, (__u32 *) ctx->in);
++ buf += t;
++ len -= t;
++ }
++ /* Process data in 64-byte chunks */
++
++ while (len >= 64) {
++ memmove(ctx->in, buf, 64);
++ byteReverse(ctx->in, 16);
++ MD5Transform(ctx->buf, (__u32 *) ctx->in);
++ buf += 64;
++ len -= 64;
++ }
++
++ /* Handle any remaining bytes of data. */
++
++ memmove(ctx->in, buf, len);
++}
++
++/*
++ * Final wrapup - pad to 64-byte boundary with the bit pattern
++ * 1 0* (64-bit count of bits processed, MSB-first)
++ */
++void
++MD5Final(unsigned char digest[16], struct MD5Context *ctx)
++{
++ unsigned int count;
++ unsigned char *p;
++
++ /* Compute number of bytes mod 64 */
++ count = (ctx->bits[0] >> 3) & 0x3F;
++
++ /* Set the first char of padding to 0x80. This is safe since there is
++ always at least one byte free */
++ p = ctx->in + count;
++ *p++ = 0x80;
++
++ /* Bytes of padding needed to make 64 bytes */
++ count = 64 - 1 - count;
++
++ /* Pad out to 56 mod 64 */
++ if (count < 8) {
++ /* Two lots of padding: Pad the first block to 64 bytes */
++ memset(p, 0, count);
++ byteReverse(ctx->in, 16);
++ MD5Transform(ctx->buf, (__u32 *) ctx->in);
++
++ /* Now fill the next block with 56 bytes */
++ memset(ctx->in, 0, 56);
++ } else {
++ /* Pad block to 56 bytes */
++ memset(p, 0, count - 8);
++ }
++ byteReverse(ctx->in, 14);
++
++ /* Append length in bits and transform */
++ ((__u32 *) ctx->in)[14] = ctx->bits[0];
++ ((__u32 *) ctx->in)[15] = ctx->bits[1];
++
++ MD5Transform(ctx->buf, (__u32 *) ctx->in);
++ byteReverse((unsigned char *) ctx->buf, 4);
++ memmove(digest, ctx->buf, 16);
++ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
++}
++
++/* The four core functions - F1 is optimized somewhat */
++
++/* #define F1(x, y, z) (x & y | ~x & z) */
++#define F1(x, y, z) (z ^ (x & (y ^ z)))
++#define F2(x, y, z) F1(z, x, y)
++#define F3(x, y, z) (x ^ y ^ z)
++#define F4(x, y, z) (y ^ (x | ~z))
++
++/* This is the central step in the MD5 algorithm. */
++#define MD5STEP(f, w, x, y, z, data, s) \
++ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
++
++/*
++ * The core of the MD5 algorithm, this alters an existing MD5 hash to
++ * reflect the addition of 16 longwords of new data. MD5Update blocks
++ * the data and converts bytes into longwords for this routine.
++ */
++static void
++MD5Transform(__u32 buf[4], __u32 const in[16])
++{
++ register __u32 a, b, c, d;
++
++ a = buf[0];
++ b = buf[1];
++ c = buf[2];
++ d = buf[3];
++
++ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
++ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
++ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
++ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
++ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
++ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
++ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
++ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
++ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
++ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
++ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
++ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
++ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
++ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
++ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
++ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
++
++ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
++ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
++ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
++ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
++ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
++ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
++ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
++ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
++ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
++ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
++ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
++ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
++ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
++ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
++ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
++ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
++
++ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
++ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
++ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
++ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
++ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
++ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
++ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
++ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
++ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
++ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
++ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
++ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
++ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
++ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
++ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
++ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
++
++ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
++ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
++ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
++ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
++ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
++ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
++ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
++ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
++ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
++ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
++ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
++ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
++ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
++ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
++ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
++ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
++
++ buf[0] += a;
++ buf[1] += b;
++ buf[2] += c;
++ buf[3] += d;
++}
++
++/***********************************************************************
++ the rfc 2104 version of hmac_md5 initialisation.
++***********************************************************************/
++void
++hmac_md5_init_rfc2104(unsigned char *key, int key_len,
++ struct HMACMD5Context *ctx)
++{
++ int i;
++
++ /* if key is longer than 64 bytes reset it to key=MD5(key) */
++ if (key_len > 64) {
++ unsigned char tk[16];
++ struct MD5Context tctx;
++
++ MD5Init(&tctx);
++ MD5Update(&tctx, key, key_len);
++ MD5Final(tk, &tctx);
++
++ key = tk;
++ key_len = 16;
++ }
++
++ /* start out by storing key in pads */
++ memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
++ memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
++ memcpy(ctx->k_ipad, key, key_len);
++ memcpy(ctx->k_opad, key, key_len);
++
++ /* XOR key with ipad and opad values */
++ for (i = 0; i < 64; i++) {
++ ctx->k_ipad[i] ^= 0x36;
++ ctx->k_opad[i] ^= 0x5c;
++ }
++
++ MD5Init(&ctx->ctx);
++ MD5Update(&ctx->ctx, ctx->k_ipad, 64);
++}
++
++/***********************************************************************
++ the microsoft version of hmac_md5 initialisation.
++***********************************************************************/
++void
++hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
++ struct HMACMD5Context *ctx)
++{
++ int i;
++
++ /* if key is longer than 64 bytes truncate it */
++ if (key_len > 64) {
++ key_len = 64;
++ }
++
++ /* start out by storing key in pads */
++ memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
++ memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
++ memcpy(ctx->k_ipad, key, key_len);
++ memcpy(ctx->k_opad, key, key_len);
++
++ /* XOR key with ipad and opad values */
++ for (i = 0; i < 64; i++) {
++ ctx->k_ipad[i] ^= 0x36;
++ ctx->k_opad[i] ^= 0x5c;
++ }
++
++ MD5Init(&ctx->ctx);
++ MD5Update(&ctx->ctx, ctx->k_ipad, 64);
++}
++
++/***********************************************************************
++ update hmac_md5 "inner" buffer
++***********************************************************************/
++void
++hmac_md5_update(const unsigned char *text, int text_len,
++ struct HMACMD5Context *ctx)
++{
++ MD5Update(&ctx->ctx, text, text_len); /* then text of datagram */
++}
++
++/***********************************************************************
++ finish off hmac_md5 "inner" buffer and generate outer one.
++***********************************************************************/
++void
++hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx)
++{
++ struct MD5Context ctx_o;
++
++ MD5Final(digest, &ctx->ctx);
++
++ MD5Init(&ctx_o);
++ MD5Update(&ctx_o, ctx->k_opad, 64);
++ MD5Update(&ctx_o, digest, 16);
++ MD5Final(digest, &ctx_o);
++}
++
++/***********************************************************
++ single function to calculate an HMAC MD5 digest from data.
++ use the microsoft hmacmd5 init method because the key is 16 bytes.
++************************************************************/
++void
++hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
++ unsigned char *digest)
++{
++ struct HMACMD5Context ctx;
++ hmac_md5_init_limK_to_64(key, 16, &ctx);
++ if (data_len != 0) {
++ hmac_md5_update(data, data_len, &ctx);
++ }
++ hmac_md5_final(digest, &ctx);
++}
+diff -urN linux-2.4.29.old/fs/cifs/md5.h linux-2.4.29/fs/cifs/md5.h
+--- linux-2.4.29.old/fs/cifs/md5.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/md5.h 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,38 @@
++#ifndef MD5_H
++#define MD5_H
++#ifndef HEADER_MD5_H
++/* Try to avoid clashes with OpenSSL */
++#define HEADER_MD5_H
++#endif
++
++struct MD5Context {
++ __u32 buf[4];
++ __u32 bits[2];
++ unsigned char in[64];
++};
++#endif /* !MD5_H */
++
++#ifndef _HMAC_MD5_H
++struct HMACMD5Context {
++ struct MD5Context ctx;
++ unsigned char k_ipad[65];
++ unsigned char k_opad[65];
++};
++#endif /* _HMAC_MD5_H */
++
++void MD5Init(struct MD5Context *context);
++void MD5Update(struct MD5Context *context, unsigned char const *buf,
++ unsigned len);
++void MD5Final(unsigned char digest[16], struct MD5Context *context);
++
++/* The following definitions come from lib/hmacmd5.c */
++
++void hmac_md5_init_rfc2104(unsigned char *key, int key_len,
++ struct HMACMD5Context *ctx);
++void hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
++ struct HMACMD5Context *ctx);
++void hmac_md5_update(const unsigned char *text, int text_len,
++ struct HMACMD5Context *ctx);
++void hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx);
++void hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
++ unsigned char *digest);
+diff -urN linux-2.4.29.old/fs/cifs/misc.c linux-2.4.29/fs/cifs/misc.c
+--- linux-2.4.29.old/fs/cifs/misc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/misc.c 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,463 @@
++/*
++ * fs/cifs/misc.c
++ *
++ * Copyright (C) International Business Machines Corp., 2002,2003
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/slab.h>
++#include <linux/ctype.h>
++#include "cifspdu.h"
++#include "cifsglob.h"
++#include "cifsproto.h"
++#include "cifs_debug.h"
++#include "smberr.h"
++#include "nterr.h"
++
++extern kmem_cache_t *cifs_req_cachep;
++extern struct task_struct * oplockThread;
++
++__u16 GlobalMid; /* multiplex id - rotating counter */
++
++/* The xid serves as a useful identifier for each incoming vfs request,
++ in a similar way to the mid which is useful to track each sent smb,
++ and CurrentXid can also provide a running counter (although it
++ will eventually wrap past zero) of the total vfs operations handled
++ since the cifs fs was mounted */
++
++unsigned int
++_GetXid(void)
++{
++ unsigned int xid;
++
++ spin_lock(&GlobalMid_Lock);
++ GlobalTotalActiveXid++;
++ if (GlobalTotalActiveXid > GlobalMaxActiveXid)
++ GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */
++ xid = GlobalCurrentXid++;
++ spin_unlock(&GlobalMid_Lock);
++ return xid;
++}
++
++void
++_FreeXid(unsigned int xid)
++{
++ spin_lock(&GlobalMid_Lock);
++ /* if(GlobalTotalActiveXid == 0)
++ BUG(); */
++ GlobalTotalActiveXid--;
++ spin_unlock(&GlobalMid_Lock);
++}
++
++struct cifsSesInfo *
++sesInfoAlloc(void)
++{
++ struct cifsSesInfo *ret_buf;
++
++ ret_buf =
++ (struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo),
++ GFP_KERNEL);
++ if (ret_buf) {
++ memset(ret_buf, 0, sizeof (struct cifsSesInfo));
++ write_lock(&GlobalSMBSeslock);
++ atomic_inc(&sesInfoAllocCount);
++ ret_buf->status = CifsNew;
++ list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList);
++ init_MUTEX(&ret_buf->sesSem);
++ write_unlock(&GlobalSMBSeslock);
++ }
++ return ret_buf;
++}
++
++void
++sesInfoFree(struct cifsSesInfo *buf_to_free)
++{
++ if (buf_to_free == NULL) {
++ cFYI(1, ("Null buffer passed to sesInfoFree"));
++ return;
++ }
++
++ write_lock(&GlobalSMBSeslock);
++ atomic_dec(&sesInfoAllocCount);
++ list_del(&buf_to_free->cifsSessionList);
++ write_unlock(&GlobalSMBSeslock);
++ if (buf_to_free->serverOS)
++ kfree(buf_to_free->serverOS);
++ if (buf_to_free->serverDomain)
++ kfree(buf_to_free->serverDomain);
++ if (buf_to_free->serverNOS)
++ kfree(buf_to_free->serverNOS);
++ if (buf_to_free->password)
++ kfree(buf_to_free->password);
++ kfree(buf_to_free);
++}
++
++struct cifsTconInfo *
++tconInfoAlloc(void)
++{
++ struct cifsTconInfo *ret_buf;
++ ret_buf =
++ (struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo),
++ GFP_KERNEL);
++ if (ret_buf) {
++ memset(ret_buf, 0, sizeof (struct cifsTconInfo));
++ write_lock(&GlobalSMBSeslock);
++ atomic_inc(&tconInfoAllocCount);
++ list_add(&ret_buf->cifsConnectionList,
++ &GlobalTreeConnectionList);
++ ret_buf->tidStatus = CifsNew;
++ INIT_LIST_HEAD(&ret_buf->openFileList);
++ init_MUTEX(&ret_buf->tconSem);
++#ifdef CONFIG_CIFS_STATS
++ ret_buf->stat_lock = SPIN_LOCK_UNLOCKED;
++#endif
++ write_unlock(&GlobalSMBSeslock);
++ }
++ return ret_buf;
++}
++
++void
++tconInfoFree(struct cifsTconInfo *buf_to_free)
++{
++ if (buf_to_free == NULL) {
++ cFYI(1, ("Null buffer passed to tconInfoFree"));
++ return;
++ }
++ write_lock(&GlobalSMBSeslock);
++ atomic_dec(&tconInfoAllocCount);
++ list_del(&buf_to_free->cifsConnectionList);
++ write_unlock(&GlobalSMBSeslock);
++ if (buf_to_free->nativeFileSystem)
++ kfree(buf_to_free->nativeFileSystem);
++ kfree(buf_to_free);
++}
++
++struct smb_hdr *
++cifs_buf_get(void)
++{
++ struct smb_hdr *ret_buf = NULL;
++
++/* We could use negotiated size instead of max_msgsize -
++ but it may be more efficient to always alloc same size
++ albeit slightly larger than necessary and maxbuffersize
++ defaults to this and can not be bigger */
++ ret_buf =
++ (struct smb_hdr *) kmem_cache_alloc(cifs_req_cachep, SLAB_KERNEL);
++
++ /* clear the first few header bytes */
++ if (ret_buf) {
++ memset(ret_buf, 0, sizeof (struct smb_hdr));
++ atomic_inc(&bufAllocCount);
++ }
++
++ return ret_buf;
++}
++
++void
++cifs_buf_release(void *buf_to_free)
++{
++
++ if (buf_to_free == NULL) {
++ cFYI(1, ("Null buffer passed to cifs_buf_release"));
++ return;
++ }
++ kmem_cache_free(cifs_req_cachep, buf_to_free);
++
++ atomic_dec(&bufAllocCount);
++ return;
++}
++
++void
++header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
++ const struct cifsTconInfo *treeCon, int word_count
++ /* length of fixed section (word count) in two byte units */
++ )
++{
++ int i;
++ __u32 tmp;
++ struct list_head* temp_item;
++ struct cifsSesInfo * ses;
++ char *temp = (char *) buffer;
++
++ for (i = 0; i < MAX_CIFS_HDR_SIZE; i++) {
++ temp[i] = 0; /* BB is this needed ?? */
++ }
++
++ buffer->smb_buf_length =
++ (2 * word_count) + sizeof (struct smb_hdr) -
++ 4 /* RFC 1001 length field does not count */ +
++ 2 /* for bcc field itself */ ;
++ /* Note that this is the only network field that has to be converted to big endian and it is done just before we send it */
++
++ buffer->Protocol[0] = 0xFF;
++ buffer->Protocol[1] = 'S';
++ buffer->Protocol[2] = 'M';
++ buffer->Protocol[3] = 'B';
++ buffer->Command = smb_command;
++ buffer->Flags = 0x00; /* case sensitive */
++ buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES;
++ tmp = cpu_to_le32(current->pid);
++ buffer->Pid = tmp & 0xFFFF;
++ tmp >>= 16;
++ buffer->PidHigh = tmp & 0xFFFF;
++ spin_lock(&GlobalMid_Lock);
++ GlobalMid++;
++ buffer->Mid = GlobalMid;
++ spin_unlock(&GlobalMid_Lock);
++ if (treeCon) {
++ buffer->Tid = treeCon->tid;
++ if (treeCon->ses) {
++ if (treeCon->ses->capabilities & CAP_UNICODE)
++ buffer->Flags2 |= SMBFLG2_UNICODE;
++ if (treeCon->ses->capabilities & CAP_STATUS32) {
++ buffer->Flags2 |= SMBFLG2_ERR_STATUS;
++ }
++
++ buffer->Uid = treeCon->ses->Suid; /* always in LE format */
++ if(multiuser_mount != 0) {
++ /* For the multiuser case, there are few obvious technically */
++ /* possible mechanisms to match the local linux user (uid) */
++ /* to a valid remote smb user (smb_uid): */
++ /* 1) Query Winbind (or other local pam/nss daemon */
++ /* for userid/password/logon_domain or credential */
++ /* 2) Query Winbind for uid to sid to username mapping */
++ /* and see if we have a matching password for existing*/
++ /* session for that user perhas getting password by */
++ /* adding a new pam_cifs module that stores passwords */
++ /* so that the cifs vfs can get at that for all logged*/
++ /* on users */
++ /* 3) (Which is the mechanism we have chosen) */
++ /* Search through sessions to the same server for a */
++ /* a match on the uid that was passed in on mount */
++ /* with the current processes uid (or euid?) and use */
++ /* that smb uid. If no existing smb session for */
++ /* that uid found, use the default smb session ie */
++ /* the smb session for the volume mounted which is */
++ /* the same as would be used if the multiuser mount */
++ /* flag were disabled. */
++
++ /* BB Add support for establishing new tCon and SMB Session */
++ /* with userid/password pairs found on the smb session */
++ /* for other target tcp/ip addresses BB */
++ if(current->uid != treeCon->ses->linux_uid) {
++ cFYI(1,("Multiuser mode and UID did not match tcon uid "));
++ read_lock(&GlobalSMBSeslock);
++ list_for_each(temp_item, &GlobalSMBSessionList) {
++ ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
++ if(ses->linux_uid == current->uid) {
++ if(ses->server == treeCon->ses->server) {
++ cFYI(1,("found matching uid substitute right smb_uid"));
++ buffer->Uid = ses->Suid;
++ break;
++ } else {
++ /* BB eventually call cifs_setup_session here */
++ cFYI(1,("local UID found but smb sess with this server does not exist"));
++ }
++ }
++ }
++ read_unlock(&GlobalSMBSeslock);
++ }
++ }
++ }
++ if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
++ buffer->Flags2 |= SMBFLG2_DFS;
++ if(treeCon->ses->server)
++ if(treeCon->ses->server->secMode &
++ (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
++ buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
++ }
++
++/* endian conversion of flags is now done just before sending */
++ buffer->WordCount = (char) word_count;
++ return;
++}
++
++int
++checkSMBhdr(struct smb_hdr *smb, __u16 mid)
++{
++ /* Make sure that this really is an SMB, that it is a response,
++ and that the message ids match */
++ if ((*(unsigned int *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&
++ (mid == smb->Mid)) {
++ if(smb->Flags & SMBFLG_RESPONSE)
++ return 0;
++ else {
++ /* only one valid case where server sends us request */
++ if(smb->Command == SMB_COM_LOCKING_ANDX)
++ return 0;
++ else
++ cERROR(1, ("Rcvd Request not response "));
++ }
++ } else { /* bad signature or mid */
++ if (*(unsigned int *) smb->Protocol != cpu_to_le32(0x424d53ff))
++ cERROR(1,
++ ("Bad protocol string signature header %x ",
++ *(unsigned int *) smb->Protocol));
++ if (mid != smb->Mid)
++ cERROR(1, ("Mids do not match"));
++ }
++ cERROR(1, ("bad smb detected. The Mid=%d", smb->Mid));
++ return 1;
++}
++
++int
++checkSMB(struct smb_hdr *smb, __u16 mid, int length)
++{
++ cFYI(0,
++ ("Entering checkSMB with Length: %x, smb_buf_length: %x ",
++ length, ntohl(smb->smb_buf_length)));
++ if (((unsigned int)length < 2 + sizeof (struct smb_hdr))
++ || (ntohl(smb->smb_buf_length) >
++ CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)) {
++ if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
++ cERROR(1, ("Length less than 2 + sizeof smb_hdr "));
++ if (((unsigned int)length >= sizeof (struct smb_hdr) - 1)
++ && (smb->Status.CifsError != 0))
++ return 0; /* some error cases do not return wct and bcc */
++
++ }
++ if (ntohl(smb->smb_buf_length) >
++ CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)
++ cERROR(1,
++ ("smb_buf_length greater than CIFS_MAX_MSGSIZE ... "));
++ cERROR(1,
++ ("bad smb detected. Illegal length. The mid=%d",
++ smb->Mid));
++ return 1;
++ }
++
++ if (checkSMBhdr(smb, mid))
++ return 1;
++
++ if ((4 + ntohl(smb->smb_buf_length) != smbCalcSize(smb))
++ || (4 + ntohl(smb->smb_buf_length) != (unsigned int)length)) {
++ return 0;
++ } else {
++ cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb)));
++ cERROR(1,
++ ("bad smb size detected. The Mid=%d", smb->Mid));
++ return 1;
++ }
++}
++int
++is_valid_oplock_break(struct smb_hdr *buf)
++{
++ struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf;
++ struct list_head *tmp;
++ struct list_head *tmp1;
++ struct cifsTconInfo *tcon;
++ struct cifsFileInfo *netfile;
++
++ /* could add check for smb response flag 0x80 */
++ cFYI(1,("Checking for oplock break"));
++ if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
++ return FALSE;
++ if(pSMB->hdr.Flags & SMBFLG_RESPONSE) {
++ /* no sense logging error on invalid handle on oplock
++ break - harmless race between close request and oplock
++ break response is expected from time to time writing out
++ large dirty files cached on the client */
++ if ((NT_STATUS_INVALID_HANDLE) ==
++ le32_to_cpu(pSMB->hdr.Status.CifsError)) {
++ cFYI(1,("invalid handle on oplock break"));
++ return TRUE;
++ } else if (ERRbadfid ==
++ le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
++ return TRUE;
++ } else {
++ return FALSE; /* on valid oplock brk we get "request" */
++ }
++ }
++ if(pSMB->hdr.WordCount != 8)
++ return FALSE;
++
++ cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel));
++ if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
++ return FALSE;
++
++ /* look up tcon based on tid & uid */
++ read_lock(&GlobalSMBSeslock);
++ list_for_each(tmp, &GlobalTreeConnectionList) {
++ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
++ if (tcon->tid == buf->Tid) {
++#ifdef CONFIG_CIFS_STATS
++ atomic_inc(&tcon->num_oplock_brks);
++#endif
++ list_for_each(tmp1,&tcon->openFileList){
++ netfile = list_entry(tmp1,struct cifsFileInfo,tlist);
++ if(pSMB->Fid == netfile->netfid) {
++ struct cifsInodeInfo *pCifsInode;
++ read_unlock(&GlobalSMBSeslock);
++ cFYI(1,("Matching file id, processing oplock break"));
++ pCifsInode =
++ CIFS_I(netfile->pInode);
++ pCifsInode->clientCanCacheAll = FALSE;
++ if(pSMB->OplockLevel == 0)
++ pCifsInode->clientCanCacheRead = FALSE;
++ pCifsInode->oplockPending = TRUE;
++ AllocOplockQEntry(netfile->pInode, netfile->netfid, tcon);
++ cFYI(1,("about to wake up oplock thd"));
++ wake_up_process(oplockThread);
++ return TRUE;
++ }
++ }
++ read_unlock(&GlobalSMBSeslock);
++ cFYI(1,("No matching file for oplock break on connection"));
++ return TRUE;
++ }
++ }
++ read_unlock(&GlobalSMBSeslock);
++ cFYI(1,("Can not process oplock break for non-existent connection"));
++ return TRUE;
++}
++
++void
++dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
++{
++ int i, j;
++ char debug_line[17];
++ unsigned char *buffer;
++
++ if (traceSMB == 0)
++ return;
++
++ buffer = (unsigned char *) smb_buf;
++ for (i = 0, j = 0; i < smb_buf_length; i++, j++) {
++ if (i % 8 == 0) { /* we have reached the beginning of line */
++ printk(KERN_DEBUG "| ");
++ j = 0;
++ }
++ printk("%0#4x ", buffer[i]);
++ debug_line[2 * j] = ' ';
++ if (isprint(buffer[i]))
++ debug_line[1 + (2 * j)] = buffer[i];
++ else
++ debug_line[1 + (2 * j)] = '_';
++
++ if (i % 8 == 7) { /* we have reached end of line, time to print ascii */
++ debug_line[16] = 0;
++ printk(" | %s\n", debug_line);
++ }
++ }
++ for (; j < 8; j++) {
++ printk(" ");
++ debug_line[2 * j] = ' ';
++ debug_line[1 + (2 * j)] = ' ';
++ }
++ printk( " | %s\n", debug_line);
++ return;
++}
+diff -urN linux-2.4.29.old/fs/cifs/netmisc.c linux-2.4.29/fs/cifs/netmisc.c
+--- linux-2.4.29.old/fs/cifs/netmisc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/netmisc.c 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,905 @@
++/*
++ * fs/cifs/netmisc.c
++ *
++ * Copyright (c) International Business Machines Corp., 2002
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * Error mapping routines from Samba libsmb/errormap.c
++ * Copyright (C) Andrew Tridgell 2001
++ *
++ *
++ * 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/net.h>
++#include <linux/string.h>
++#include <linux/in.h>
++#include <linux/ctype.h>
++#include <linux/fs.h>
++#include <asm/div64.h>
++#include <asm/byteorder.h>
++#include "cifsfs.h"
++#include "cifspdu.h"
++#include "cifsglob.h"
++#include "cifsproto.h"
++#include "smberr.h"
++#include "cifs_debug.h"
++#include "nterr.h"
++
++struct smb_to_posix_error {
++ __u16 smb_err;
++ int posix_code;
++};
++
++const struct smb_to_posix_error mapping_table_ERRDOS[] = {
++ {ERRbadfunc, -EINVAL},
++ {ERRbadfile, -ENOENT},
++ {ERRbadpath, -ENOTDIR},
++ {ERRnofids, -EMFILE},
++ {ERRnoaccess, -EACCES},
++ {ERRbadfid, -EBADF},
++ {ERRbadmcb, -EIO},
++ {ERRnomem, -ENOMEM},
++ {ERRbadmem, -EFAULT},
++ {ERRbadenv, -EFAULT},
++ {ERRbadformat, -EINVAL},
++ {ERRbadaccess, -EACCES},
++ {ERRbaddata, -EIO},
++ {ERRbaddrive, -ENXIO},
++ {ERRremcd, -EACCES},
++ {ERRdiffdevice, -EXDEV},
++ {ERRnofiles, -ENOENT},
++ {ERRbadshare, -ETXTBSY},
++ {ERRlock, -EACCES},
++ {ERRunsup, -EINVAL},
++ {ERRnosuchshare,-ENXIO},
++ {ERRfilexists, -EEXIST},
++ {ERRinvparm, -EINVAL},
++ {ERRdiskfull, -ENOSPC},
++ {ERRinvname, -ENOENT},
++ {ERRdirnotempty, -ENOTEMPTY},
++ {ERRnotlocked, -ENOLCK},
++ {ERRalreadyexists, -EEXIST},
++ {ERRmoredata, -EOVERFLOW},
++ {ErrQuota, -EDQUOT},
++ {ErrNotALink, -ENOLINK},
++ {ERRnetlogonNotStarted,-ENOPROTOOPT},
++ {0, 0}
++};
++
++const struct smb_to_posix_error mapping_table_ERRSRV[] = {
++ {ERRerror, -EIO},
++ {ERRbadpw, -EPERM},
++ {ERRbadtype, -EREMOTE},
++ {ERRaccess, -EACCES},
++ {ERRinvtid, -ENXIO},
++ {ERRinvnetname, -ENODEV},
++ {ERRinvdevice, -ENXIO},
++ {ERRqfull, -ENOSPC},
++ {ERRqtoobig, -ENOSPC},
++ {ERRqeof, -EIO},
++ {ERRinvpfid, -EBADF},
++ {ERRsmbcmd, -EBADRQC},
++ {ERRsrverror, -EIO},
++ {ERRbadBID, -EIO},
++ {ERRfilespecs, -EINVAL},
++ {ERRbadLink, -EIO},
++ {ERRbadpermits, -EINVAL},
++ {ERRbadPID, -ESRCH},
++ {ERRsetattrmode, -EINVAL},
++ {ERRpaused, -EHOSTDOWN},
++ {ERRmsgoff, -EHOSTDOWN},
++ {ERRnoroom, -ENOSPC},
++ {ERRrmuns, -EUSERS},
++ {ERRtimeout, -ETIME},
++ {ERRnoresource, -ENOBUFS},
++ {ERRtoomanyuids, -EUSERS},
++ {ERRbaduid, -EACCES},
++ {ERRusempx, -EIO},
++ {ERRusestd, -EIO},
++ {ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
++ {ERRaccountexpired, -EACCES},
++ {ERRbadclient, -EACCES},
++ {ERRbadLogonTime, -EACCES},
++ {ERRpasswordExpired, -EACCES},
++ {ERRnosupport, -EINVAL},
++ {0, 0}
++};
++
++const struct smb_to_posix_error mapping_table_ERRHRD[] = {
++ {0, 0}
++};
++
++/* Convert string containing dotted ip address to binary form */
++/* returns 0 if invalid address */
++
++/* BB add address family, change rc to status flag and return union or for ipv6 */
++/* will need parent to call something like inet_pton to convert ipv6 address BB */
++int
++cifs_inet_pton(int address_family, char *cp,void *dst)
++{
++ struct in_addr address;
++ int value;
++ int digit;
++ int i;
++ char temp;
++ char bytes[4];
++ char *end = bytes;
++ static const int addr_class_max[4] =
++ { 0xffffffff, 0xffffff, 0xffff, 0xff };
++
++ if(address_family != AF_INET)
++ return -EAFNOSUPPORT;
++
++ for (i = 0; i < 4; i++) {
++ bytes[i] = 0;
++ }
++
++ temp = *cp;
++
++ while (TRUE) {
++ if (!isdigit(temp))
++ return 0;
++
++ value = 0;
++ digit = 0;
++ for (;;) {
++ if (isascii(temp) && isdigit(temp)) {
++ value = (value * 10) + temp - '0';
++ temp = *++cp;
++ digit = 1;
++ } else
++ break;
++ }
++
++ if (temp == '.') {
++ if ((end > bytes + 2) || (value > 255))
++ return 0;
++ *end++ = value;
++ temp = *++cp;
++ } else if (temp == ':') {
++ cFYI(1,("IPv6 addresses not supported for CIFS mounts yet"));
++ return -1;
++ } else
++ break;
++ }
++
++ /* check for last characters */
++ if (temp != '\0' && (!isascii(temp) || !isspace(temp)))
++ if (temp != '\\') {
++ if (temp != '/')
++ return 0;
++ else
++ (*cp = '\\'); /* switch the slash the expected way */
++ }
++ if (value > addr_class_max[end - bytes])
++ return 0;
++
++ address.s_addr = *((int *) bytes) | htonl(value);
++ *((int *)dst) = address.s_addr;
++ return 1; /* success */
++}
++
++/*****************************************************************************
++convert a NT status code to a dos class/code
++ *****************************************************************************/
++/* NT status -> dos error map */
++static const struct {
++ __u8 dos_class;
++ __u16 dos_code;
++ __u32 ntstatus;
++} ntstatus_to_dos_map[] = {
++ {
++ ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, {
++ ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, {
++ ERRDOS, 87, NT_STATUS_INVALID_INFO_CLASS}, {
++ ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, {
++ ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA}, {
++ ERRDOS, ERRbadfid, NT_STATUS_INVALID_HANDLE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_BAD_INITIAL_STACK}, {
++ ERRDOS, 193, NT_STATUS_BAD_INITIAL_PC}, {
++ ERRDOS, 87, NT_STATUS_INVALID_CID}, {
++ ERRHRD, ERRgeneral, NT_STATUS_TIMER_NOT_CANCELED}, {
++ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER}, {
++ ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_DEVICE}, {
++ ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_FILE}, {
++ ERRDOS, ERRbadfunc, NT_STATUS_INVALID_DEVICE_REQUEST}, {
++ ERRDOS, 38, NT_STATUS_END_OF_FILE}, {
++ ERRDOS, 34, NT_STATUS_WRONG_VOLUME}, {
++ ERRDOS, 21, NT_STATUS_NO_MEDIA_IN_DEVICE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_MEDIA}, {
++ ERRDOS, 27, NT_STATUS_NONEXISTENT_SECTOR},
++/* { This NT error code was 'sqashed'
++ from NT_STATUS_MORE_PROCESSING_REQUIRED to NT_STATUS_OK
++ during the session setup } */
++ {
++ ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY}, {
++ ERRDOS, 487, NT_STATUS_CONFLICTING_ADDRESSES}, {
++ ERRDOS, 487, NT_STATUS_NOT_MAPPED_VIEW}, {
++ ERRDOS, 87, NT_STATUS_UNABLE_TO_FREE_VM}, {
++ ERRDOS, 87, NT_STATUS_UNABLE_TO_DELETE_SECTION}, {
++ ERRDOS, 2142, NT_STATUS_INVALID_SYSTEM_SERVICE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_INSTRUCTION}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_INVALID_LOCK_SEQUENCE}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_INVALID_VIEW_SIZE}, {
++ ERRDOS, 193, NT_STATUS_INVALID_FILE_FOR_SECTION}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_ALREADY_COMMITTED},
++/* { This NT error code was 'sqashed'
++ from NT_STATUS_ACCESS_DENIED to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
++ during the session setup } */
++ {
++ ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED}, {
++ ERRDOS, 111, NT_STATUS_BUFFER_TOO_SMALL}, {
++ ERRDOS, ERRbadfid, NT_STATUS_OBJECT_TYPE_MISMATCH}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NONCONTINUABLE_EXCEPTION}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_DISPOSITION}, {
++ ERRHRD, ERRgeneral, NT_STATUS_UNWIND}, {
++ ERRHRD, ERRgeneral, NT_STATUS_BAD_STACK}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_UNWIND_TARGET}, {
++ ERRDOS, 158, NT_STATUS_NOT_LOCKED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PARITY_ERROR}, {
++ ERRDOS, 487, NT_STATUS_UNABLE_TO_DECOMMIT_VM}, {
++ ERRDOS, 487, NT_STATUS_NOT_COMMITTED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_PORT_ATTRIBUTES}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PORT_MESSAGE_TOO_LONG}, {
++ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_MIX}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_QUOTA_LOWER}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DISK_CORRUPT_ERROR}, {
++ ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, { /* mapping changed since shell does lookup on * and expects file not found */
++ ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND}, {
++ ERRDOS, ERRalreadyexists, NT_STATUS_OBJECT_NAME_COLLISION}, {
++ ERRHRD, ERRgeneral, NT_STATUS_HANDLE_NOT_WAITABLE}, {
++ ERRDOS, ERRbadfid, NT_STATUS_PORT_DISCONNECTED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_ALREADY_ATTACHED}, {
++ ERRDOS, 161, NT_STATUS_OBJECT_PATH_INVALID}, {
++ ERRDOS, ERRbadpath, NT_STATUS_OBJECT_PATH_NOT_FOUND}, {
++ ERRDOS, 161, NT_STATUS_OBJECT_PATH_SYNTAX_BAD}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DATA_OVERRUN}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DATA_LATE_ERROR}, {
++ ERRDOS, 23, NT_STATUS_DATA_ERROR}, {
++ ERRDOS, 23, NT_STATUS_CRC_ERROR}, {
++ ERRDOS, ERRnomem, NT_STATUS_SECTION_TOO_BIG}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_PORT_CONNECTION_REFUSED}, {
++ ERRDOS, ERRbadfid, NT_STATUS_INVALID_PORT_HANDLE}, {
++ ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION}, {
++ ERRHRD, ERRgeneral, NT_STATUS_QUOTA_EXCEEDED}, {
++ ERRDOS, 87, NT_STATUS_INVALID_PAGE_PROTECTION}, {
++ ERRDOS, 288, NT_STATUS_MUTANT_NOT_OWNED}, {
++ ERRDOS, 298, NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED}, {
++ ERRDOS, 87, NT_STATUS_PORT_ALREADY_SET}, {
++ ERRDOS, 87, NT_STATUS_SECTION_NOT_IMAGE}, {
++ ERRDOS, 156, NT_STATUS_SUSPEND_COUNT_EXCEEDED}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_THREAD_IS_TERMINATING}, {
++ ERRDOS, 87, NT_STATUS_BAD_WORKING_SET_LIMIT}, {
++ ERRDOS, 87, NT_STATUS_INCOMPATIBLE_FILE_MAP}, {
++ ERRDOS, 87, NT_STATUS_SECTION_PROTECTION}, {
++ ERRDOS, 282, NT_STATUS_EAS_NOT_SUPPORTED}, {
++ ERRDOS, 255, NT_STATUS_EA_TOO_LARGE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NONEXISTENT_EA_ENTRY}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_EAS_ON_FILE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_EA_CORRUPT_ERROR}, {
++ ERRDOS, ERRlock, NT_STATUS_FILE_LOCK_CONFLICT}, {
++ ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED}, {
++ ERRDOS, ERRbadfile, NT_STATUS_DELETE_PENDING}, {
++ ERRDOS, ERRunsup, NT_STATUS_CTL_FILE_NOT_SUPPORTED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_UNKNOWN_REVISION}, {
++ ERRHRD, ERRgeneral, NT_STATUS_REVISION_MISMATCH}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_OWNER}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_PRIMARY_GROUP}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_IMPERSONATION_TOKEN}, {
++ ERRHRD, ERRgeneral, NT_STATUS_CANT_DISABLE_MANDATORY}, {
++ ERRDOS, 2215, NT_STATUS_NO_LOGON_SERVERS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_LOGON_SESSION}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PRIVILEGE}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_PRIVILEGE_NOT_HELD}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACCOUNT_NAME}, {
++ ERRHRD, ERRgeneral, NT_STATUS_USER_EXISTS},
++/* { This NT error code was 'sqashed'
++ from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
++ during the session setup } */
++ {
++ ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, {
++ ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
++ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
++ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_GROUP}, {
++ ERRHRD, ERRgeneral, NT_STATUS_LAST_ADMIN},
++/* { This NT error code was 'sqashed'
++ from NT_STATUS_WRONG_PASSWORD to NT_STATUS_LOGON_FAILURE
++ during the session setup } */
++ {
++ ERRSRV, ERRbadpw, NT_STATUS_WRONG_PASSWORD}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_PASSWORD}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
++ ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, {
++ ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, {
++ ERRSRV, 2242, NT_STATUS_PASSWORD_EXPIRED}, {
++ ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SUB_AUTHORITY}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACL}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SID}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SECURITY_DESCR}, {
++ ERRDOS, 127, NT_STATUS_PROCEDURE_NOT_FOUND}, {
++ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_FORMAT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_TOKEN}, {
++ ERRHRD, ERRgeneral, NT_STATUS_BAD_INHERITANCE_ACL}, {
++ ERRDOS, 158, NT_STATUS_RANGE_NOT_LOCKED}, {
++ ERRDOS, 112, NT_STATUS_DISK_FULL}, {
++ ERRHRD, ERRgeneral, NT_STATUS_SERVER_DISABLED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_SERVER_NOT_DISABLED}, {
++ ERRDOS, 68, NT_STATUS_TOO_MANY_GUIDS_REQUESTED}, {
++ ERRDOS, 259, NT_STATUS_GUIDS_EXHAUSTED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ID_AUTHORITY}, {
++ ERRDOS, 259, NT_STATUS_AGENTS_EXHAUSTED}, {
++ ERRDOS, 154, NT_STATUS_INVALID_VOLUME_LABEL}, {
++ ERRDOS, 14, NT_STATUS_SECTION_NOT_EXTENDED}, {
++ ERRDOS, 487, NT_STATUS_NOT_MAPPED_DATA}, {
++ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_DATA_NOT_FOUND}, {
++ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_TYPE_NOT_FOUND}, {
++ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_NAME_NOT_FOUND}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ARRAY_BOUNDS_EXCEEDED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DENORMAL_OPERAND}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DIVIDE_BY_ZERO}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INEXACT_RESULT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INVALID_OPERATION}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_OVERFLOW}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_STACK_CHECK}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_UNDERFLOW}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INTEGER_DIVIDE_BY_ZERO}, {
++ ERRDOS, 534, NT_STATUS_INTEGER_OVERFLOW}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PRIVILEGED_INSTRUCTION}, {
++ ERRDOS, ERRnomem, NT_STATUS_TOO_MANY_PAGING_FILES}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
++/* { This NT error code was 'sqashed'
++ from NT_STATUS_INSUFFICIENT_RESOURCES to NT_STATUS_INSUFF_SERVER_RESOURCES
++ during the session setup } */
++ {
++ ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, {
++ ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, {
++ ERRDOS, 23, NT_STATUS_DEVICE_DATA_ERROR}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_CONNECTED}, {
++ ERRDOS, 21, NT_STATUS_DEVICE_POWER_FAILURE}, {
++ ERRDOS, 487, NT_STATUS_FREE_VM_NOT_AT_BASE}, {
++ ERRDOS, 487, NT_STATUS_MEMORY_NOT_ALLOCATED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_WORKING_SET_QUOTA}, {
++ ERRDOS, 19, NT_STATUS_MEDIA_WRITE_PROTECTED}, {
++ ERRDOS, 21, NT_STATUS_DEVICE_NOT_READY}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_GROUP_ATTRIBUTES}, {
++ ERRHRD, ERRgeneral, NT_STATUS_BAD_IMPERSONATION_LEVEL}, {
++ ERRHRD, ERRgeneral, NT_STATUS_CANT_OPEN_ANONYMOUS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_BAD_VALIDATION_CLASS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_BAD_TOKEN_TYPE}, {
++ ERRDOS, 87, NT_STATUS_BAD_MASTER_BOOT_RECORD}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INSTRUCTION_MISALIGNMENT}, {
++ ERRDOS, ERRpipebusy, NT_STATUS_INSTANCE_NOT_AVAILABLE}, {
++ ERRDOS, ERRpipebusy, NT_STATUS_PIPE_NOT_AVAILABLE}, {
++ ERRDOS, ERRbadpipe, NT_STATUS_INVALID_PIPE_STATE}, {
++ ERRDOS, ERRpipebusy, NT_STATUS_PIPE_BUSY}, {
++ ERRDOS, ERRbadfunc, NT_STATUS_ILLEGAL_FUNCTION}, {
++ ERRDOS, ERRnotconnected, NT_STATUS_PIPE_DISCONNECTED}, {
++ ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_CLOSING}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PIPE_CONNECTED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PIPE_LISTENING}, {
++ ERRDOS, ERRbadpipe, NT_STATUS_INVALID_READ_MODE}, {
++ ERRDOS, 121, NT_STATUS_IO_TIMEOUT}, {
++ ERRDOS, 38, NT_STATUS_FILE_FORCED_CLOSED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STARTED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STOPPED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_COULD_NOT_INTERPRET}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_FILE_IS_A_DIRECTORY}, {
++ ERRDOS, ERRunsup, NT_STATUS_NOT_SUPPORTED}, {
++ ERRDOS, 51, NT_STATUS_REMOTE_NOT_LISTENING}, {
++ ERRDOS, 52, NT_STATUS_DUPLICATE_NAME}, {
++ ERRDOS, 53, NT_STATUS_BAD_NETWORK_PATH}, {
++ ERRDOS, 54, NT_STATUS_NETWORK_BUSY}, {
++ ERRDOS, 55, NT_STATUS_DEVICE_DOES_NOT_EXIST}, {
++ ERRDOS, 56, NT_STATUS_TOO_MANY_COMMANDS}, {
++ ERRDOS, 57, NT_STATUS_ADAPTER_HARDWARE_ERROR}, {
++ ERRDOS, 58, NT_STATUS_INVALID_NETWORK_RESPONSE}, {
++ ERRDOS, 59, NT_STATUS_UNEXPECTED_NETWORK_ERROR}, {
++ ERRDOS, 60, NT_STATUS_BAD_REMOTE_ADAPTER}, {
++ ERRDOS, 61, NT_STATUS_PRINT_QUEUE_FULL}, {
++ ERRDOS, 62, NT_STATUS_NO_SPOOL_SPACE}, {
++ ERRDOS, 63, NT_STATUS_PRINT_CANCELLED}, {
++ ERRDOS, 64, NT_STATUS_NETWORK_NAME_DELETED}, {
++ ERRDOS, 65, NT_STATUS_NETWORK_ACCESS_DENIED}, {
++ ERRDOS, 66, NT_STATUS_BAD_DEVICE_TYPE}, {
++ ERRDOS, ERRnosuchshare, NT_STATUS_BAD_NETWORK_NAME}, {
++ ERRDOS, 68, NT_STATUS_TOO_MANY_NAMES}, {
++ ERRDOS, 69, NT_STATUS_TOO_MANY_SESSIONS}, {
++ ERRDOS, 70, NT_STATUS_SHARING_PAUSED}, {
++ ERRDOS, 71, NT_STATUS_REQUEST_NOT_ACCEPTED}, {
++ ERRDOS, 72, NT_STATUS_REDIRECTOR_PAUSED}, {
++ ERRDOS, 88, NT_STATUS_NET_WRITE_FAULT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PROFILING_AT_LIMIT}, {
++ ERRDOS, ERRdiffdevice, NT_STATUS_NOT_SAME_DEVICE}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_FILE_RENAMED}, {
++ ERRDOS, 240, NT_STATUS_VIRTUAL_CIRCUIT_CLOSED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_SECURITY_ON_OBJECT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_CANT_WAIT}, {
++ ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_EMPTY}, {
++ ERRHRD, ERRgeneral, NT_STATUS_CANT_ACCESS_DOMAIN_INFO}, {
++ ERRHRD, ERRgeneral, NT_STATUS_CANT_TERMINATE_SELF}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SERVER_STATE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_STATE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_ROLE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_DOMAIN}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_EXISTS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_LIMIT_EXCEEDED}, {
++ ERRDOS, 300, NT_STATUS_OPLOCK_NOT_GRANTED}, {
++ ERRDOS, 301, NT_STATUS_INVALID_OPLOCK_PROTOCOL}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_CORRUPTION}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_ERROR}, {
++ ERRHRD, ERRgeneral, NT_STATUS_GENERIC_NOT_MAPPED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_BAD_DESCRIPTOR_FORMAT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_USER_BUFFER}, {
++ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_IO_ERROR}, {
++ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_CREATE_ERR}, {
++ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_MAP_ERROR}, {
++ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_EXTEND_ERR}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NOT_LOGON_PROCESS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_EXISTS}, {
++ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_1}, {
++ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_2}, {
++ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_3}, {
++ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_4}, {
++ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_5}, {
++ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_6}, {
++ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_7}, {
++ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_8}, {
++ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_9}, {
++ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_10}, {
++ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_11}, {
++ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_12}, {
++ ERRDOS, ERRbadpath, NT_STATUS_REDIRECTOR_NOT_STARTED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_REDIRECTOR_STARTED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PACKAGE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_BAD_FUNCTION_TABLE}, {
++ ERRDOS, 203, 0xc0000100}, {
++ ERRDOS, 145, NT_STATUS_DIRECTORY_NOT_EMPTY}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FILE_CORRUPT_ERROR}, {
++ ERRDOS, 267, NT_STATUS_NOT_A_DIRECTORY}, {
++ ERRHRD, ERRgeneral, NT_STATUS_BAD_LOGON_SESSION_STATE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_COLLISION}, {
++ ERRDOS, 206, NT_STATUS_NAME_TOO_LONG}, {
++ ERRDOS, 2401, NT_STATUS_FILES_OPEN}, {
++ ERRDOS, 2404, NT_STATUS_CONNECTION_IN_USE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_MESSAGE_NOT_FOUND}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_PROCESS_IS_TERMINATING}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LOGON_TYPE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_GUID_TRANSLATION}, {
++ ERRHRD, ERRgeneral, NT_STATUS_CANNOT_IMPERSONATE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_IMAGE_ALREADY_LOADED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_PRESENT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_NOT_EXIST}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_ALREADY_OWNED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_LID_OWNER}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_COMMAND}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_LID}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_SELECTOR}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_LDT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_SIZE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_OFFSET}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_DESCRIPTOR}, {
++ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NE_FORMAT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_RXACT_INVALID_STATE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_RXACT_COMMIT_FAILURE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_MAPPED_FILE_SIZE_ZERO}, {
++ ERRDOS, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES}, {
++ ERRHRD, ERRgeneral, NT_STATUS_CANCELLED}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_CANNOT_DELETE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_COMPUTER_NAME}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_FILE_DELETED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_ACCOUNT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_GROUP}, {
++ ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_USER}, {
++ ERRHRD, ERRgeneral, NT_STATUS_MEMBERS_PRIMARY_GROUP}, {
++ ERRDOS, ERRbadfid, NT_STATUS_FILE_CLOSED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_THREADS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_THREAD_NOT_IN_PROCESS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_TOKEN_ALREADY_IN_USE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA_EXCEEDED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_COMMITMENT_LIMIT}, {
++ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_LE_FORMAT}, {
++ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NOT_MZ}, {
++ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_PROTECT}, {
++ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_WIN_16}, {
++ ERRHRD, ERRgeneral, NT_STATUS_LOGON_SERVER_CONFLICT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_TIME_DIFFERENCE_AT_DC}, {
++ ERRHRD, ERRgeneral, NT_STATUS_SYNCHRONIZATION_REQUIRED}, {
++ ERRDOS, 126, NT_STATUS_DLL_NOT_FOUND}, {
++ ERRHRD, ERRgeneral, NT_STATUS_OPEN_FAILED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_IO_PRIVILEGE_FAILED}, {
++ ERRDOS, 182, NT_STATUS_ORDINAL_NOT_FOUND}, {
++ ERRDOS, 127, NT_STATUS_ENTRYPOINT_NOT_FOUND}, {
++ ERRHRD, ERRgeneral, NT_STATUS_CONTROL_C_EXIT}, {
++ ERRDOS, 64, NT_STATUS_LOCAL_DISCONNECT}, {
++ ERRDOS, 64, NT_STATUS_REMOTE_DISCONNECT}, {
++ ERRDOS, 51, NT_STATUS_REMOTE_RESOURCES}, {
++ ERRDOS, 59, NT_STATUS_LINK_FAILED}, {
++ ERRDOS, 59, NT_STATUS_LINK_TIMEOUT}, {
++ ERRDOS, 59, NT_STATUS_INVALID_CONNECTION}, {
++ ERRDOS, 59, NT_STATUS_INVALID_ADDRESS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DLL_INIT_FAILED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_MISSING_SYSTEMFILE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_UNHANDLED_EXCEPTION}, {
++ ERRHRD, ERRgeneral, NT_STATUS_APP_INIT_FAILURE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_CREATE_FAILED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_PAGEFILE}, {
++ ERRDOS, 124, NT_STATUS_INVALID_LEVEL}, {
++ ERRDOS, 86, NT_STATUS_WRONG_PASSWORD_CORE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_FLOAT_CONTEXT}, {
++ ERRDOS, 109, NT_STATUS_PIPE_BROKEN}, {
++ ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_CORRUPT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_IO_FAILED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_EVENT_PAIR}, {
++ ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_VOLUME}, {
++ ERRHRD, ERRgeneral, NT_STATUS_SERIAL_NO_DEVICE_INITED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_ALIAS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_ALIAS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_ALIAS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ALIAS_EXISTS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_LOGON_NOT_GRANTED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SECRETS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_SECRET_TOO_LONG}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_ERROR}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FULLSCREEN_MODE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_CONTEXT_IDS}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_LOGON_TYPE_NOT_GRANTED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NOT_REGISTRY_FILE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FT_MISSING_MEMBER}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_SERVICE_ENTRY}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_CHARACTER}, {
++ ERRHRD, ERRgeneral, NT_STATUS_UNMAPPABLE_CHARACTER}, {
++ ERRHRD, ERRgeneral, NT_STATUS_UNDEFINED_CHARACTER}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_VOLUME}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_WRONG_CYLINDER}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_UNKNOWN_ERROR}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_BAD_REGISTERS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DISK_RECALIBRATE_FAILED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DISK_OPERATION_FAILED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DISK_RESET_FAILED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_SHARED_IRQ_BUSY}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FT_ORPHANING}, {
++ ERRHRD, ERRgeneral, 0xc000016e}, {
++ ERRHRD, ERRgeneral, 0xc000016f}, {
++ ERRHRD, ERRgeneral, 0xc0000170}, {
++ ERRHRD, ERRgeneral, 0xc0000171}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PARTITION_FAILURE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_BLOCK_LENGTH}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_PARTITIONED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_LOCK_MEDIA}, {
++ ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_UNLOAD_MEDIA}, {
++ ERRHRD, ERRgeneral, NT_STATUS_EOM_OVERFLOW}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_MEDIA}, {
++ ERRHRD, ERRgeneral, 0xc0000179}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_MEMBER}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_MEMBER}, {
++ ERRHRD, ERRgeneral, NT_STATUS_KEY_DELETED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_LOG_SPACE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SIDS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_KEY_HAS_CHILDREN}, {
++ ERRHRD, ERRgeneral, NT_STATUS_CHILD_MUST_BE_VOLATILE}, {
++ ERRDOS, 87, NT_STATUS_DEVICE_CONFIGURATION_ERROR}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DRIVER_INTERNAL_ERROR}, {
++ ERRDOS, 22, NT_STATUS_INVALID_DEVICE_STATE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_PROTOCOL_ERROR}, {
++ ERRHRD, ERRgeneral, NT_STATUS_BACKUP_CONTROLLER}, {
++ ERRHRD, ERRgeneral, NT_STATUS_LOG_FILE_FULL}, {
++ ERRDOS, 19, NT_STATUS_TOO_LATE}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET},
++/* { This NT error code was 'sqashed'
++ from NT_STATUS_NO_TRUST_SAM_ACCOUNT to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
++ during the session setup } */
++ {
++ ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CORRUPT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_CANT_START}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
++ ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
++ ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CHANGED}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
++/* { This NT error code was 'sqashed'
++ from NT_STATUS_DOMAIN_TRUST_INCONSISTENT to NT_STATUS_LOGON_FAILURE
++ during the session setup } */
++ {
++ ERRDOS, ERRnoaccess, NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FS_DRIVER_REQUIRED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_USER_SESSION_KEY}, {
++ ERRDOS, 59, NT_STATUS_USER_SESSION_DELETED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_LANG_NOT_FOUND}, {
++ ERRDOS, ERRnomem, NT_STATUS_INSUFF_SERVER_RESOURCES}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_BUFFER_SIZE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_COMPONENT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_WILDCARD}, {
++ ERRDOS, 68, NT_STATUS_TOO_MANY_ADDRESSES}, {
++ ERRDOS, 52, NT_STATUS_ADDRESS_ALREADY_EXISTS}, {
++ ERRDOS, 64, NT_STATUS_ADDRESS_CLOSED}, {
++ ERRDOS, 64, NT_STATUS_CONNECTION_DISCONNECTED}, {
++ ERRDOS, 64, NT_STATUS_CONNECTION_RESET}, {
++ ERRDOS, 68, NT_STATUS_TOO_MANY_NODES}, {
++ ERRDOS, 59, NT_STATUS_TRANSACTION_ABORTED}, {
++ ERRDOS, 59, NT_STATUS_TRANSACTION_TIMED_OUT}, {
++ ERRDOS, 59, NT_STATUS_TRANSACTION_NO_RELEASE}, {
++ ERRDOS, 59, NT_STATUS_TRANSACTION_NO_MATCH}, {
++ ERRDOS, 59, NT_STATUS_TRANSACTION_RESPONDED}, {
++ ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_ID}, {
++ ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_TYPE}, {
++ ERRDOS, ERRunsup, NT_STATUS_NOT_SERVER_SESSION}, {
++ ERRDOS, ERRunsup, NT_STATUS_NOT_CLIENT_SESSION}, {
++ ERRHRD, ERRgeneral, NT_STATUS_CANNOT_LOAD_REGISTRY_FILE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DEBUG_ATTACH_FAILED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_SYSTEM_PROCESS_TERMINATED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DATA_NOT_ACCEPTED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_BROWSER_SERVERS_FOUND}, {
++ ERRHRD, ERRgeneral, NT_STATUS_VDM_HARD_ERROR}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DRIVER_CANCEL_TIMEOUT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_REPLY_MESSAGE_MISMATCH}, {
++ ERRHRD, ERRgeneral, NT_STATUS_MAPPED_ALIGNMENT}, {
++ ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, {
++ ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, {
++ ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, {
++ ERRSRV, 2242, NT_STATUS_PASSWORD_MUST_CHANGE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, {
++ ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW_READ}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FAIL_CHECK}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DUPLICATE_OBJECTID}, {
++ ERRHRD, ERRgeneral, NT_STATUS_OBJECTID_EXISTS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_CONVERT_TO_LARGE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_RETRY}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FOUND_OUT_OF_SCOPE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ALLOCATE_BUCKET}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PROPSET_NOT_FOUND}, {
++ ERRHRD, ERRgeneral, NT_STATUS_MARSHALL_OVERFLOW}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_VARIANT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND}, {
++ ERRDOS, ERRnoaccess, NT_STATUS_ACCOUNT_LOCKED_OUT}, {
++ ERRDOS, ERRbadfid, NT_STATUS_HANDLE_NOT_CLOSABLE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_REFUSED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_GRACEFUL_DISCONNECT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_ALREADY_ASSOCIATED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_NOT_ASSOCIATED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_INVALID}, {
++ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ACTIVE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NETWORK_UNREACHABLE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_HOST_UNREACHABLE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PROTOCOL_UNREACHABLE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PORT_UNREACHABLE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_REQUEST_ABORTED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ABORTED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_BAD_COMPRESSION_BUFFER}, {
++ ERRHRD, ERRgeneral, NT_STATUS_USER_MAPPED_FILE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_AUDIT_FAILED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_TIMER_RESOLUTION_NOT_SET}, {
++ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_COUNT_LIMIT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_LOGIN_TIME_RESTRICTION}, {
++ ERRHRD, ERRgeneral, NT_STATUS_LOGIN_WKSTA_RESTRICTION}, {
++ ERRDOS, 193, NT_STATUS_IMAGE_MP_UP_MISMATCH}, {
++ ERRHRD, ERRgeneral, 0xc000024a}, {
++ ERRHRD, ERRgeneral, 0xc000024b}, {
++ ERRHRD, ERRgeneral, 0xc000024c}, {
++ ERRHRD, ERRgeneral, 0xc000024d}, {
++ ERRHRD, ERRgeneral, 0xc000024e}, {
++ ERRHRD, ERRgeneral, 0xc000024f}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INSUFFICIENT_LOGON_INFO}, {
++ ERRHRD, ERRgeneral, NT_STATUS_BAD_DLL_ENTRYPOINT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_BAD_SERVICE_ENTRYPOINT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_LPC_REPLY_LOST}, {
++ ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT1}, {
++ ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT2}, {
++ ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_QUOTA_LIMIT}, {
++ ERRSRV, 3, NT_STATUS_PATH_NOT_COVERED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_NO_CALLBACK_ACTIVE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_LICENSE_QUOTA_EXCEEDED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_SHORT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_RECENT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PWD_HISTORY_CONFLICT}, {
++ ERRHRD, ERRgeneral, 0xc000025d}, {
++ ERRHRD, ERRgeneral, NT_STATUS_PLUGPLAY_NO_DEVICE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_UNSUPPORTED_COMPRESSION}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_HW_PROFILE}, {
++ ERRHRD, ERRgeneral, NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH}, {
++ ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, {
++ ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, {
++ ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, {
++ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LINKS}, {
++ ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, {
++ ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, {
++ ERRDOS, 21, 0xc000026e}, {
++ ERRDOS, 161, 0xc0000281}, {
++ ERRDOS, ERRnoaccess, 0xc000028a}, {
++ ERRDOS, ERRnoaccess, 0xc000028b}, {
++ ERRHRD, ERRgeneral, 0xc000028c}, {
++ ERRDOS, ERRnoaccess, 0xc000028d}, {
++ ERRDOS, ERRnoaccess, 0xc000028e}, {
++ ERRDOS, ERRnoaccess, 0xc000028f}, {
++ ERRDOS, ERRnoaccess, 0xc0000290}, {
++ERRDOS, ERRbadfunc, 0xc000029c},};
++
++/*****************************************************************************
++ Print an error message from the status code
++ *****************************************************************************/
++static void
++cifs_print_status(__u32 status_code)
++{
++ int idx = 0;
++
++ while (nt_errs[idx].nt_errstr != NULL) {
++ if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==
++ (status_code & 0xFFFFFF)) {
++ printk(KERN_NOTICE "Status code returned 0x%08x %s\n",
++ status_code,nt_errs[idx].nt_errstr);
++ }
++ idx++;
++ }
++ return;
++}
++
++
++static void
++ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
++{
++ int i;
++ if (ntstatus == 0) {
++ *eclass = 0;
++ *ecode = 0;
++ return;
++ }
++ for (i = 0; ntstatus_to_dos_map[i].ntstatus; i++) {
++ if (ntstatus == ntstatus_to_dos_map[i].ntstatus) {
++ *eclass = ntstatus_to_dos_map[i].dos_class;
++ *ecode = ntstatus_to_dos_map[i].dos_code;
++ return;
++ }
++ }
++ *eclass = ERRHRD;
++ *ecode = ERRgeneral;
++}
++
++int
++map_smb_to_linux_error(struct smb_hdr *smb)
++{
++ unsigned int i;
++ int rc = -EIO; /* if transport error smb error may not be set */
++ __u8 smberrclass;
++ __u16 smberrcode;
++
++ /* BB if NT Status codes - map NT BB */
++
++ /* old style smb error codes */
++ if (smb->Status.CifsError == 0)
++ return 0;
++
++ if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
++ /* translate the newer STATUS codes to old style errors and then to POSIX errors */
++ smb->Status.CifsError = le32_to_cpu(smb->Status.CifsError);
++ if(cifsFYI)
++ cifs_print_status(smb->Status.CifsError);
++ ntstatus_to_dos(smb->Status.CifsError, &smberrclass,
++ &smberrcode);
++ } else {
++ smberrclass = smb->Status.DosError.ErrorClass;
++ smb->Status.DosError.Error =
++ le16_to_cpu(smb->Status.DosError.Error);
++ smberrcode = smb->Status.DosError.Error;
++ }
++
++ /* old style errors */
++
++ /* DOS class smb error codes - map DOS */
++ if (smberrclass == ERRDOS) { /* one byte field no need to byte reverse */
++ for (i = 0;
++ i <
++ sizeof (mapping_table_ERRDOS) /
++ sizeof (struct smb_to_posix_error); i++) {
++ if (mapping_table_ERRDOS[i].smb_err == 0)
++ break;
++ else if (mapping_table_ERRDOS[i].smb_err == smberrcode) {
++ rc = mapping_table_ERRDOS[i].posix_code;
++ break;
++ }
++ /* else try the next error mapping one to see if it will match */
++ }
++ } else if (smberrclass == ERRSRV) { /* server class of error codes */
++ for (i = 0;
++ i <
++ sizeof (mapping_table_ERRSRV) /
++ sizeof (struct smb_to_posix_error); i++) {
++ if (mapping_table_ERRSRV[i].smb_err == 0)
++ break;
++ else if (mapping_table_ERRSRV[i].smb_err == smberrcode) {
++ rc = mapping_table_ERRSRV[i].posix_code;
++ break;
++ }
++ /* else try the next error mapping one to see if it will match */
++ }
++ }
++ /* else ERRHRD class errors or junk - return EIO */
++
++ cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", smberrcode,rc));
++
++ /* generic corrective action e.g. reconnect SMB session on ERRbaduid could be added */
++
++ return rc;
++}
++
++/*
++ * calculate the size of the SMB message based on the fixed header
++ * portion, the number of word parameters and the data portion of the message
++ */
++unsigned int
++smbCalcSize(struct smb_hdr *ptr)
++{
++ return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
++ BCC(ptr));
++}
++
++/* The following are taken from fs/ntfs/util.c */
++
++#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
++
++ /*
++ * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
++ * into Unix UTC (based 1970-01-01, in seconds).
++ */
++time_t
++cifs_NTtimeToUnix(__u64 ntutc)
++{
++ /* BB what about the timezone? BB */
++
++ /* Subtract the NTFS time offset, then convert to 1s intervals. */
++ u64 t;
++
++ t = ntutc - NTFS_TIME_OFFSET;
++ do_div(t, 10000000);
++ return (time_t)t;
++}
++
++/* Convert the Unix UTC into NT UTC. */
++__u64
++cifs_UnixTimeToNT(time_t t)
++{
++ __u64 dce_time;
++ /* Convert to 100ns intervals and then add the NTFS time offset. */
++ dce_time = (__u64) t * 10000000;
++ dce_time += NTFS_TIME_OFFSET;
++ return dce_time;
++}
+diff -urN linux-2.4.29.old/fs/cifs/nterr.c linux-2.4.29/fs/cifs/nterr.c
+--- linux-2.4.29.old/fs/cifs/nterr.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/nterr.c 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,687 @@
++/*
++ * Unix SMB/Netbios implementation.
++ * Version 1.9.
++ * RPC Pipe client / server routines
++ * Copyright (C) Luke Kenneth Casson Leighton 1997-2001.
++ *
++ * 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.
++ */
++
++/* NT error codes - see nterr.h */
++#include <linux/types.h>
++#include <linux/fs.h>
++#include "nterr.h"
++
++const struct nt_err_code_struct nt_errs[] = {
++ {"NT_STATUS_OK", NT_STATUS_OK},
++ {"NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL},
++ {"NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED},
++ {"NT_STATUS_INVALID_INFO_CLASS", NT_STATUS_INVALID_INFO_CLASS},
++ {"NT_STATUS_INFO_LENGTH_MISMATCH", NT_STATUS_INFO_LENGTH_MISMATCH},
++ {"NT_STATUS_ACCESS_VIOLATION", NT_STATUS_ACCESS_VIOLATION},
++ {"STATUS_BUFFER_OVERFLOW", STATUS_BUFFER_OVERFLOW},
++ {"NT_STATUS_IN_PAGE_ERROR", NT_STATUS_IN_PAGE_ERROR},
++ {"NT_STATUS_PAGEFILE_QUOTA", NT_STATUS_PAGEFILE_QUOTA},
++ {"NT_STATUS_INVALID_HANDLE", NT_STATUS_INVALID_HANDLE},
++ {"NT_STATUS_BAD_INITIAL_STACK", NT_STATUS_BAD_INITIAL_STACK},
++ {"NT_STATUS_BAD_INITIAL_PC", NT_STATUS_BAD_INITIAL_PC},
++ {"NT_STATUS_INVALID_CID", NT_STATUS_INVALID_CID},
++ {"NT_STATUS_TIMER_NOT_CANCELED", NT_STATUS_TIMER_NOT_CANCELED},
++ {"NT_STATUS_INVALID_PARAMETER", NT_STATUS_INVALID_PARAMETER},
++ {"NT_STATUS_NO_SUCH_DEVICE", NT_STATUS_NO_SUCH_DEVICE},
++ {"NT_STATUS_NO_SUCH_FILE", NT_STATUS_NO_SUCH_FILE},
++ {"NT_STATUS_INVALID_DEVICE_REQUEST",
++ NT_STATUS_INVALID_DEVICE_REQUEST},
++ {"NT_STATUS_END_OF_FILE", NT_STATUS_END_OF_FILE},
++ {"NT_STATUS_WRONG_VOLUME", NT_STATUS_WRONG_VOLUME},
++ {"NT_STATUS_NO_MEDIA_IN_DEVICE", NT_STATUS_NO_MEDIA_IN_DEVICE},
++ {"NT_STATUS_UNRECOGNIZED_MEDIA", NT_STATUS_UNRECOGNIZED_MEDIA},
++ {"NT_STATUS_NONEXISTENT_SECTOR", NT_STATUS_NONEXISTENT_SECTOR},
++ {"NT_STATUS_MORE_PROCESSING_REQUIRED",
++ NT_STATUS_MORE_PROCESSING_REQUIRED},
++ {"NT_STATUS_NO_MEMORY", NT_STATUS_NO_MEMORY},
++ {"NT_STATUS_CONFLICTING_ADDRESSES",
++ NT_STATUS_CONFLICTING_ADDRESSES},
++ {"NT_STATUS_NOT_MAPPED_VIEW", NT_STATUS_NOT_MAPPED_VIEW},
++ {"NT_STATUS_UNABLE_TO_FREE_VM", NT_STATUS_UNABLE_TO_FREE_VM},
++ {"NT_STATUS_UNABLE_TO_DELETE_SECTION",
++ NT_STATUS_UNABLE_TO_DELETE_SECTION},
++ {"NT_STATUS_INVALID_SYSTEM_SERVICE",
++ NT_STATUS_INVALID_SYSTEM_SERVICE},
++ {"NT_STATUS_ILLEGAL_INSTRUCTION", NT_STATUS_ILLEGAL_INSTRUCTION},
++ {"NT_STATUS_INVALID_LOCK_SEQUENCE",
++ NT_STATUS_INVALID_LOCK_SEQUENCE},
++ {"NT_STATUS_INVALID_VIEW_SIZE", NT_STATUS_INVALID_VIEW_SIZE},
++ {"NT_STATUS_INVALID_FILE_FOR_SECTION",
++ NT_STATUS_INVALID_FILE_FOR_SECTION},
++ {"NT_STATUS_ALREADY_COMMITTED", NT_STATUS_ALREADY_COMMITTED},
++ {"NT_STATUS_ACCESS_DENIED", NT_STATUS_ACCESS_DENIED},
++ {"NT_STATUS_BUFFER_TOO_SMALL", NT_STATUS_BUFFER_TOO_SMALL},
++ {"NT_STATUS_OBJECT_TYPE_MISMATCH", NT_STATUS_OBJECT_TYPE_MISMATCH},
++ {"NT_STATUS_NONCONTINUABLE_EXCEPTION",
++ NT_STATUS_NONCONTINUABLE_EXCEPTION},
++ {"NT_STATUS_INVALID_DISPOSITION", NT_STATUS_INVALID_DISPOSITION},
++ {"NT_STATUS_UNWIND", NT_STATUS_UNWIND},
++ {"NT_STATUS_BAD_STACK", NT_STATUS_BAD_STACK},
++ {"NT_STATUS_INVALID_UNWIND_TARGET",
++ NT_STATUS_INVALID_UNWIND_TARGET},
++ {"NT_STATUS_NOT_LOCKED", NT_STATUS_NOT_LOCKED},
++ {"NT_STATUS_PARITY_ERROR", NT_STATUS_PARITY_ERROR},
++ {"NT_STATUS_UNABLE_TO_DECOMMIT_VM",
++ NT_STATUS_UNABLE_TO_DECOMMIT_VM},
++ {"NT_STATUS_NOT_COMMITTED", NT_STATUS_NOT_COMMITTED},
++ {"NT_STATUS_INVALID_PORT_ATTRIBUTES",
++ NT_STATUS_INVALID_PORT_ATTRIBUTES},
++ {"NT_STATUS_PORT_MESSAGE_TOO_LONG",
++ NT_STATUS_PORT_MESSAGE_TOO_LONG},
++ {"NT_STATUS_INVALID_PARAMETER_MIX",
++ NT_STATUS_INVALID_PARAMETER_MIX},
++ {"NT_STATUS_INVALID_QUOTA_LOWER", NT_STATUS_INVALID_QUOTA_LOWER},
++ {"NT_STATUS_DISK_CORRUPT_ERROR", NT_STATUS_DISK_CORRUPT_ERROR},
++ {"NT_STATUS_OBJECT_NAME_INVALID", NT_STATUS_OBJECT_NAME_INVALID},
++ {"NT_STATUS_OBJECT_NAME_NOT_FOUND",
++ NT_STATUS_OBJECT_NAME_NOT_FOUND},
++ {"NT_STATUS_OBJECT_NAME_COLLISION",
++ NT_STATUS_OBJECT_NAME_COLLISION},
++ {"NT_STATUS_HANDLE_NOT_WAITABLE", NT_STATUS_HANDLE_NOT_WAITABLE},
++ {"NT_STATUS_PORT_DISCONNECTED", NT_STATUS_PORT_DISCONNECTED},
++ {"NT_STATUS_DEVICE_ALREADY_ATTACHED",
++ NT_STATUS_DEVICE_ALREADY_ATTACHED},
++ {"NT_STATUS_OBJECT_PATH_INVALID", NT_STATUS_OBJECT_PATH_INVALID},
++ {"NT_STATUS_OBJECT_PATH_NOT_FOUND",
++ NT_STATUS_OBJECT_PATH_NOT_FOUND},
++ {"NT_STATUS_OBJECT_PATH_SYNTAX_BAD",
++ NT_STATUS_OBJECT_PATH_SYNTAX_BAD},
++ {"NT_STATUS_DATA_OVERRUN", NT_STATUS_DATA_OVERRUN},
++ {"NT_STATUS_DATA_LATE_ERROR", NT_STATUS_DATA_LATE_ERROR},
++ {"NT_STATUS_DATA_ERROR", NT_STATUS_DATA_ERROR},
++ {"NT_STATUS_CRC_ERROR", NT_STATUS_CRC_ERROR},
++ {"NT_STATUS_SECTION_TOO_BIG", NT_STATUS_SECTION_TOO_BIG},
++ {"NT_STATUS_PORT_CONNECTION_REFUSED",
++ NT_STATUS_PORT_CONNECTION_REFUSED},
++ {"NT_STATUS_INVALID_PORT_HANDLE", NT_STATUS_INVALID_PORT_HANDLE},
++ {"NT_STATUS_SHARING_VIOLATION", NT_STATUS_SHARING_VIOLATION},
++ {"NT_STATUS_QUOTA_EXCEEDED", NT_STATUS_QUOTA_EXCEEDED},
++ {"NT_STATUS_INVALID_PAGE_PROTECTION",
++ NT_STATUS_INVALID_PAGE_PROTECTION},
++ {"NT_STATUS_MUTANT_NOT_OWNED", NT_STATUS_MUTANT_NOT_OWNED},
++ {"NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED",
++ NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED},
++ {"NT_STATUS_PORT_ALREADY_SET", NT_STATUS_PORT_ALREADY_SET},
++ {"NT_STATUS_SECTION_NOT_IMAGE", NT_STATUS_SECTION_NOT_IMAGE},
++ {"NT_STATUS_SUSPEND_COUNT_EXCEEDED",
++ NT_STATUS_SUSPEND_COUNT_EXCEEDED},
++ {"NT_STATUS_THREAD_IS_TERMINATING",
++ NT_STATUS_THREAD_IS_TERMINATING},
++ {"NT_STATUS_BAD_WORKING_SET_LIMIT",
++ NT_STATUS_BAD_WORKING_SET_LIMIT},
++ {"NT_STATUS_INCOMPATIBLE_FILE_MAP",
++ NT_STATUS_INCOMPATIBLE_FILE_MAP},
++ {"NT_STATUS_SECTION_PROTECTION", NT_STATUS_SECTION_PROTECTION},
++ {"NT_STATUS_EAS_NOT_SUPPORTED", NT_STATUS_EAS_NOT_SUPPORTED},
++ {"NT_STATUS_EA_TOO_LARGE", NT_STATUS_EA_TOO_LARGE},
++ {"NT_STATUS_NONEXISTENT_EA_ENTRY", NT_STATUS_NONEXISTENT_EA_ENTRY},
++ {"NT_STATUS_NO_EAS_ON_FILE", NT_STATUS_NO_EAS_ON_FILE},
++ {"NT_STATUS_EA_CORRUPT_ERROR", NT_STATUS_EA_CORRUPT_ERROR},
++ {"NT_STATUS_FILE_LOCK_CONFLICT", NT_STATUS_FILE_LOCK_CONFLICT},
++ {"NT_STATUS_LOCK_NOT_GRANTED", NT_STATUS_LOCK_NOT_GRANTED},
++ {"NT_STATUS_DELETE_PENDING", NT_STATUS_DELETE_PENDING},
++ {"NT_STATUS_CTL_FILE_NOT_SUPPORTED",
++ NT_STATUS_CTL_FILE_NOT_SUPPORTED},
++ {"NT_STATUS_UNKNOWN_REVISION", NT_STATUS_UNKNOWN_REVISION},
++ {"NT_STATUS_REVISION_MISMATCH", NT_STATUS_REVISION_MISMATCH},
++ {"NT_STATUS_INVALID_OWNER", NT_STATUS_INVALID_OWNER},
++ {"NT_STATUS_INVALID_PRIMARY_GROUP",
++ NT_STATUS_INVALID_PRIMARY_GROUP},
++ {"NT_STATUS_NO_IMPERSONATION_TOKEN",
++ NT_STATUS_NO_IMPERSONATION_TOKEN},
++ {"NT_STATUS_CANT_DISABLE_MANDATORY",
++ NT_STATUS_CANT_DISABLE_MANDATORY},
++ {"NT_STATUS_NO_LOGON_SERVERS", NT_STATUS_NO_LOGON_SERVERS},
++ {"NT_STATUS_NO_SUCH_LOGON_SESSION",
++ NT_STATUS_NO_SUCH_LOGON_SESSION},
++ {"NT_STATUS_NO_SUCH_PRIVILEGE", NT_STATUS_NO_SUCH_PRIVILEGE},
++ {"NT_STATUS_PRIVILEGE_NOT_HELD", NT_STATUS_PRIVILEGE_NOT_HELD},
++ {"NT_STATUS_INVALID_ACCOUNT_NAME", NT_STATUS_INVALID_ACCOUNT_NAME},
++ {"NT_STATUS_USER_EXISTS", NT_STATUS_USER_EXISTS},
++ {"NT_STATUS_NO_SUCH_USER", NT_STATUS_NO_SUCH_USER},
++ {"NT_STATUS_GROUP_EXISTS", NT_STATUS_GROUP_EXISTS},
++ {"NT_STATUS_NO_SUCH_GROUP", NT_STATUS_NO_SUCH_GROUP},
++ {"NT_STATUS_MEMBER_IN_GROUP", NT_STATUS_MEMBER_IN_GROUP},
++ {"NT_STATUS_MEMBER_NOT_IN_GROUP", NT_STATUS_MEMBER_NOT_IN_GROUP},
++ {"NT_STATUS_LAST_ADMIN", NT_STATUS_LAST_ADMIN},
++ {"NT_STATUS_WRONG_PASSWORD", NT_STATUS_WRONG_PASSWORD},
++ {"NT_STATUS_ILL_FORMED_PASSWORD", NT_STATUS_ILL_FORMED_PASSWORD},
++ {"NT_STATUS_PASSWORD_RESTRICTION", NT_STATUS_PASSWORD_RESTRICTION},
++ {"NT_STATUS_LOGON_FAILURE", NT_STATUS_LOGON_FAILURE},
++ {"NT_STATUS_ACCOUNT_RESTRICTION", NT_STATUS_ACCOUNT_RESTRICTION},
++ {"NT_STATUS_INVALID_LOGON_HOURS", NT_STATUS_INVALID_LOGON_HOURS},
++ {"NT_STATUS_INVALID_WORKSTATION", NT_STATUS_INVALID_WORKSTATION},
++ {"NT_STATUS_PASSWORD_EXPIRED", NT_STATUS_PASSWORD_EXPIRED},
++ {"NT_STATUS_ACCOUNT_DISABLED", NT_STATUS_ACCOUNT_DISABLED},
++ {"NT_STATUS_NONE_MAPPED", NT_STATUS_NONE_MAPPED},
++ {"NT_STATUS_TOO_MANY_LUIDS_REQUESTED",
++ NT_STATUS_TOO_MANY_LUIDS_REQUESTED},
++ {"NT_STATUS_LUIDS_EXHAUSTED", NT_STATUS_LUIDS_EXHAUSTED},
++ {"NT_STATUS_INVALID_SUB_AUTHORITY",
++ NT_STATUS_INVALID_SUB_AUTHORITY},
++ {"NT_STATUS_INVALID_ACL", NT_STATUS_INVALID_ACL},
++ {"NT_STATUS_INVALID_SID", NT_STATUS_INVALID_SID},
++ {"NT_STATUS_INVALID_SECURITY_DESCR",
++ NT_STATUS_INVALID_SECURITY_DESCR},
++ {"NT_STATUS_PROCEDURE_NOT_FOUND", NT_STATUS_PROCEDURE_NOT_FOUND},
++ {"NT_STATUS_INVALID_IMAGE_FORMAT", NT_STATUS_INVALID_IMAGE_FORMAT},
++ {"NT_STATUS_NO_TOKEN", NT_STATUS_NO_TOKEN},
++ {"NT_STATUS_BAD_INHERITANCE_ACL", NT_STATUS_BAD_INHERITANCE_ACL},
++ {"NT_STATUS_RANGE_NOT_LOCKED", NT_STATUS_RANGE_NOT_LOCKED},
++ {"NT_STATUS_DISK_FULL", NT_STATUS_DISK_FULL},
++ {"NT_STATUS_SERVER_DISABLED", NT_STATUS_SERVER_DISABLED},
++ {"NT_STATUS_SERVER_NOT_DISABLED", NT_STATUS_SERVER_NOT_DISABLED},
++ {"NT_STATUS_TOO_MANY_GUIDS_REQUESTED",
++ NT_STATUS_TOO_MANY_GUIDS_REQUESTED},
++ {"NT_STATUS_GUIDS_EXHAUSTED", NT_STATUS_GUIDS_EXHAUSTED},
++ {"NT_STATUS_INVALID_ID_AUTHORITY", NT_STATUS_INVALID_ID_AUTHORITY},
++ {"NT_STATUS_AGENTS_EXHAUSTED", NT_STATUS_AGENTS_EXHAUSTED},
++ {"NT_STATUS_INVALID_VOLUME_LABEL", NT_STATUS_INVALID_VOLUME_LABEL},
++ {"NT_STATUS_SECTION_NOT_EXTENDED", NT_STATUS_SECTION_NOT_EXTENDED},
++ {"NT_STATUS_NOT_MAPPED_DATA", NT_STATUS_NOT_MAPPED_DATA},
++ {"NT_STATUS_RESOURCE_DATA_NOT_FOUND",
++ NT_STATUS_RESOURCE_DATA_NOT_FOUND},
++ {"NT_STATUS_RESOURCE_TYPE_NOT_FOUND",
++ NT_STATUS_RESOURCE_TYPE_NOT_FOUND},
++ {"NT_STATUS_RESOURCE_NAME_NOT_FOUND",
++ NT_STATUS_RESOURCE_NAME_NOT_FOUND},
++ {"NT_STATUS_ARRAY_BOUNDS_EXCEEDED",
++ NT_STATUS_ARRAY_BOUNDS_EXCEEDED},
++ {"NT_STATUS_FLOAT_DENORMAL_OPERAND",
++ NT_STATUS_FLOAT_DENORMAL_OPERAND},
++ {"NT_STATUS_FLOAT_DIVIDE_BY_ZERO", NT_STATUS_FLOAT_DIVIDE_BY_ZERO},
++ {"NT_STATUS_FLOAT_INEXACT_RESULT", NT_STATUS_FLOAT_INEXACT_RESULT},
++ {"NT_STATUS_FLOAT_INVALID_OPERATION",
++ NT_STATUS_FLOAT_INVALID_OPERATION},
++ {"NT_STATUS_FLOAT_OVERFLOW", NT_STATUS_FLOAT_OVERFLOW},
++ {"NT_STATUS_FLOAT_STACK_CHECK", NT_STATUS_FLOAT_STACK_CHECK},
++ {"NT_STATUS_FLOAT_UNDERFLOW", NT_STATUS_FLOAT_UNDERFLOW},
++ {"NT_STATUS_INTEGER_DIVIDE_BY_ZERO",
++ NT_STATUS_INTEGER_DIVIDE_BY_ZERO},
++ {"NT_STATUS_INTEGER_OVERFLOW", NT_STATUS_INTEGER_OVERFLOW},
++ {"NT_STATUS_PRIVILEGED_INSTRUCTION",
++ NT_STATUS_PRIVILEGED_INSTRUCTION},
++ {"NT_STATUS_TOO_MANY_PAGING_FILES",
++ NT_STATUS_TOO_MANY_PAGING_FILES},
++ {"NT_STATUS_FILE_INVALID", NT_STATUS_FILE_INVALID},
++ {"NT_STATUS_ALLOTTED_SPACE_EXCEEDED",
++ NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
++ {"NT_STATUS_INSUFFICIENT_RESOURCES",
++ NT_STATUS_INSUFFICIENT_RESOURCES},
++ {"NT_STATUS_DFS_EXIT_PATH_FOUND", NT_STATUS_DFS_EXIT_PATH_FOUND},
++ {"NT_STATUS_DEVICE_DATA_ERROR", NT_STATUS_DEVICE_DATA_ERROR},
++ {"NT_STATUS_DEVICE_NOT_CONNECTED", NT_STATUS_DEVICE_NOT_CONNECTED},
++ {"NT_STATUS_DEVICE_POWER_FAILURE", NT_STATUS_DEVICE_POWER_FAILURE},
++ {"NT_STATUS_FREE_VM_NOT_AT_BASE", NT_STATUS_FREE_VM_NOT_AT_BASE},
++ {"NT_STATUS_MEMORY_NOT_ALLOCATED", NT_STATUS_MEMORY_NOT_ALLOCATED},
++ {"NT_STATUS_WORKING_SET_QUOTA", NT_STATUS_WORKING_SET_QUOTA},
++ {"NT_STATUS_MEDIA_WRITE_PROTECTED",
++ NT_STATUS_MEDIA_WRITE_PROTECTED},
++ {"NT_STATUS_DEVICE_NOT_READY", NT_STATUS_DEVICE_NOT_READY},
++ {"NT_STATUS_INVALID_GROUP_ATTRIBUTES",
++ NT_STATUS_INVALID_GROUP_ATTRIBUTES},
++ {"NT_STATUS_BAD_IMPERSONATION_LEVEL",
++ NT_STATUS_BAD_IMPERSONATION_LEVEL},
++ {"NT_STATUS_CANT_OPEN_ANONYMOUS", NT_STATUS_CANT_OPEN_ANONYMOUS},
++ {"NT_STATUS_BAD_VALIDATION_CLASS", NT_STATUS_BAD_VALIDATION_CLASS},
++ {"NT_STATUS_BAD_TOKEN_TYPE", NT_STATUS_BAD_TOKEN_TYPE},
++ {"NT_STATUS_BAD_MASTER_BOOT_RECORD",
++ NT_STATUS_BAD_MASTER_BOOT_RECORD},
++ {"NT_STATUS_INSTRUCTION_MISALIGNMENT",
++ NT_STATUS_INSTRUCTION_MISALIGNMENT},
++ {"NT_STATUS_INSTANCE_NOT_AVAILABLE",
++ NT_STATUS_INSTANCE_NOT_AVAILABLE},
++ {"NT_STATUS_PIPE_NOT_AVAILABLE", NT_STATUS_PIPE_NOT_AVAILABLE},
++ {"NT_STATUS_INVALID_PIPE_STATE", NT_STATUS_INVALID_PIPE_STATE},
++ {"NT_STATUS_PIPE_BUSY", NT_STATUS_PIPE_BUSY},
++ {"NT_STATUS_ILLEGAL_FUNCTION", NT_STATUS_ILLEGAL_FUNCTION},
++ {"NT_STATUS_PIPE_DISCONNECTED", NT_STATUS_PIPE_DISCONNECTED},
++ {"NT_STATUS_PIPE_CLOSING", NT_STATUS_PIPE_CLOSING},
++ {"NT_STATUS_PIPE_CONNECTED", NT_STATUS_PIPE_CONNECTED},
++ {"NT_STATUS_PIPE_LISTENING", NT_STATUS_PIPE_LISTENING},
++ {"NT_STATUS_INVALID_READ_MODE", NT_STATUS_INVALID_READ_MODE},
++ {"NT_STATUS_IO_TIMEOUT", NT_STATUS_IO_TIMEOUT},
++ {"NT_STATUS_FILE_FORCED_CLOSED", NT_STATUS_FILE_FORCED_CLOSED},
++ {"NT_STATUS_PROFILING_NOT_STARTED",
++ NT_STATUS_PROFILING_NOT_STARTED},
++ {"NT_STATUS_PROFILING_NOT_STOPPED",
++ NT_STATUS_PROFILING_NOT_STOPPED},
++ {"NT_STATUS_COULD_NOT_INTERPRET", NT_STATUS_COULD_NOT_INTERPRET},
++ {"NT_STATUS_FILE_IS_A_DIRECTORY", NT_STATUS_FILE_IS_A_DIRECTORY},
++ {"NT_STATUS_NOT_SUPPORTED", NT_STATUS_NOT_SUPPORTED},
++ {"NT_STATUS_REMOTE_NOT_LISTENING", NT_STATUS_REMOTE_NOT_LISTENING},
++ {"NT_STATUS_DUPLICATE_NAME", NT_STATUS_DUPLICATE_NAME},
++ {"NT_STATUS_BAD_NETWORK_PATH", NT_STATUS_BAD_NETWORK_PATH},
++ {"NT_STATUS_NETWORK_BUSY", NT_STATUS_NETWORK_BUSY},
++ {"NT_STATUS_DEVICE_DOES_NOT_EXIST",
++ NT_STATUS_DEVICE_DOES_NOT_EXIST},
++ {"NT_STATUS_TOO_MANY_COMMANDS", NT_STATUS_TOO_MANY_COMMANDS},
++ {"NT_STATUS_ADAPTER_HARDWARE_ERROR",
++ NT_STATUS_ADAPTER_HARDWARE_ERROR},
++ {"NT_STATUS_INVALID_NETWORK_RESPONSE",
++ NT_STATUS_INVALID_NETWORK_RESPONSE},
++ {"NT_STATUS_UNEXPECTED_NETWORK_ERROR",
++ NT_STATUS_UNEXPECTED_NETWORK_ERROR},
++ {"NT_STATUS_BAD_REMOTE_ADAPTER", NT_STATUS_BAD_REMOTE_ADAPTER},
++ {"NT_STATUS_PRINT_QUEUE_FULL", NT_STATUS_PRINT_QUEUE_FULL},
++ {"NT_STATUS_NO_SPOOL_SPACE", NT_STATUS_NO_SPOOL_SPACE},
++ {"NT_STATUS_PRINT_CANCELLED", NT_STATUS_PRINT_CANCELLED},
++ {"NT_STATUS_NETWORK_NAME_DELETED", NT_STATUS_NETWORK_NAME_DELETED},
++ {"NT_STATUS_NETWORK_ACCESS_DENIED",
++ NT_STATUS_NETWORK_ACCESS_DENIED},
++ {"NT_STATUS_BAD_DEVICE_TYPE", NT_STATUS_BAD_DEVICE_TYPE},
++ {"NT_STATUS_BAD_NETWORK_NAME", NT_STATUS_BAD_NETWORK_NAME},
++ {"NT_STATUS_TOO_MANY_NAMES", NT_STATUS_TOO_MANY_NAMES},
++ {"NT_STATUS_TOO_MANY_SESSIONS", NT_STATUS_TOO_MANY_SESSIONS},
++ {"NT_STATUS_SHARING_PAUSED", NT_STATUS_SHARING_PAUSED},
++ {"NT_STATUS_REQUEST_NOT_ACCEPTED", NT_STATUS_REQUEST_NOT_ACCEPTED},
++ {"NT_STATUS_REDIRECTOR_PAUSED", NT_STATUS_REDIRECTOR_PAUSED},
++ {"NT_STATUS_NET_WRITE_FAULT", NT_STATUS_NET_WRITE_FAULT},
++ {"NT_STATUS_PROFILING_AT_LIMIT", NT_STATUS_PROFILING_AT_LIMIT},
++ {"NT_STATUS_NOT_SAME_DEVICE", NT_STATUS_NOT_SAME_DEVICE},
++ {"NT_STATUS_FILE_RENAMED", NT_STATUS_FILE_RENAMED},
++ {"NT_STATUS_VIRTUAL_CIRCUIT_CLOSED",
++ NT_STATUS_VIRTUAL_CIRCUIT_CLOSED},
++ {"NT_STATUS_NO_SECURITY_ON_OBJECT",
++ NT_STATUS_NO_SECURITY_ON_OBJECT},
++ {"NT_STATUS_CANT_WAIT", NT_STATUS_CANT_WAIT},
++ {"NT_STATUS_PIPE_EMPTY", NT_STATUS_PIPE_EMPTY},
++ {"NT_STATUS_CANT_ACCESS_DOMAIN_INFO",
++ NT_STATUS_CANT_ACCESS_DOMAIN_INFO},
++ {"NT_STATUS_CANT_TERMINATE_SELF", NT_STATUS_CANT_TERMINATE_SELF},
++ {"NT_STATUS_INVALID_SERVER_STATE", NT_STATUS_INVALID_SERVER_STATE},
++ {"NT_STATUS_INVALID_DOMAIN_STATE", NT_STATUS_INVALID_DOMAIN_STATE},
++ {"NT_STATUS_INVALID_DOMAIN_ROLE", NT_STATUS_INVALID_DOMAIN_ROLE},
++ {"NT_STATUS_NO_SUCH_DOMAIN", NT_STATUS_NO_SUCH_DOMAIN},
++ {"NT_STATUS_DOMAIN_EXISTS", NT_STATUS_DOMAIN_EXISTS},
++ {"NT_STATUS_DOMAIN_LIMIT_EXCEEDED",
++ NT_STATUS_DOMAIN_LIMIT_EXCEEDED},
++ {"NT_STATUS_OPLOCK_NOT_GRANTED", NT_STATUS_OPLOCK_NOT_GRANTED},
++ {"NT_STATUS_INVALID_OPLOCK_PROTOCOL",
++ NT_STATUS_INVALID_OPLOCK_PROTOCOL},
++ {"NT_STATUS_INTERNAL_DB_CORRUPTION",
++ NT_STATUS_INTERNAL_DB_CORRUPTION},
++ {"NT_STATUS_INTERNAL_ERROR", NT_STATUS_INTERNAL_ERROR},
++ {"NT_STATUS_GENERIC_NOT_MAPPED", NT_STATUS_GENERIC_NOT_MAPPED},
++ {"NT_STATUS_BAD_DESCRIPTOR_FORMAT",
++ NT_STATUS_BAD_DESCRIPTOR_FORMAT},
++ {"NT_STATUS_INVALID_USER_BUFFER", NT_STATUS_INVALID_USER_BUFFER},
++ {"NT_STATUS_UNEXPECTED_IO_ERROR", NT_STATUS_UNEXPECTED_IO_ERROR},
++ {"NT_STATUS_UNEXPECTED_MM_CREATE_ERR",
++ NT_STATUS_UNEXPECTED_MM_CREATE_ERR},
++ {"NT_STATUS_UNEXPECTED_MM_MAP_ERROR",
++ NT_STATUS_UNEXPECTED_MM_MAP_ERROR},
++ {"NT_STATUS_UNEXPECTED_MM_EXTEND_ERR",
++ NT_STATUS_UNEXPECTED_MM_EXTEND_ERR},
++ {"NT_STATUS_NOT_LOGON_PROCESS", NT_STATUS_NOT_LOGON_PROCESS},
++ {"NT_STATUS_LOGON_SESSION_EXISTS", NT_STATUS_LOGON_SESSION_EXISTS},
++ {"NT_STATUS_INVALID_PARAMETER_1", NT_STATUS_INVALID_PARAMETER_1},
++ {"NT_STATUS_INVALID_PARAMETER_2", NT_STATUS_INVALID_PARAMETER_2},
++ {"NT_STATUS_INVALID_PARAMETER_3", NT_STATUS_INVALID_PARAMETER_3},
++ {"NT_STATUS_INVALID_PARAMETER_4", NT_STATUS_INVALID_PARAMETER_4},
++ {"NT_STATUS_INVALID_PARAMETER_5", NT_STATUS_INVALID_PARAMETER_5},
++ {"NT_STATUS_INVALID_PARAMETER_6", NT_STATUS_INVALID_PARAMETER_6},
++ {"NT_STATUS_INVALID_PARAMETER_7", NT_STATUS_INVALID_PARAMETER_7},
++ {"NT_STATUS_INVALID_PARAMETER_8", NT_STATUS_INVALID_PARAMETER_8},
++ {"NT_STATUS_INVALID_PARAMETER_9", NT_STATUS_INVALID_PARAMETER_9},
++ {"NT_STATUS_INVALID_PARAMETER_10", NT_STATUS_INVALID_PARAMETER_10},
++ {"NT_STATUS_INVALID_PARAMETER_11", NT_STATUS_INVALID_PARAMETER_11},
++ {"NT_STATUS_INVALID_PARAMETER_12", NT_STATUS_INVALID_PARAMETER_12},
++ {"NT_STATUS_REDIRECTOR_NOT_STARTED",
++ NT_STATUS_REDIRECTOR_NOT_STARTED},
++ {"NT_STATUS_REDIRECTOR_STARTED", NT_STATUS_REDIRECTOR_STARTED},
++ {"NT_STATUS_STACK_OVERFLOW", NT_STATUS_STACK_OVERFLOW},
++ {"NT_STATUS_NO_SUCH_PACKAGE", NT_STATUS_NO_SUCH_PACKAGE},
++ {"NT_STATUS_BAD_FUNCTION_TABLE", NT_STATUS_BAD_FUNCTION_TABLE},
++ {"NT_STATUS_DIRECTORY_NOT_EMPTY", NT_STATUS_DIRECTORY_NOT_EMPTY},
++ {"NT_STATUS_FILE_CORRUPT_ERROR", NT_STATUS_FILE_CORRUPT_ERROR},
++ {"NT_STATUS_NOT_A_DIRECTORY", NT_STATUS_NOT_A_DIRECTORY},
++ {"NT_STATUS_BAD_LOGON_SESSION_STATE",
++ NT_STATUS_BAD_LOGON_SESSION_STATE},
++ {"NT_STATUS_LOGON_SESSION_COLLISION",
++ NT_STATUS_LOGON_SESSION_COLLISION},
++ {"NT_STATUS_NAME_TOO_LONG", NT_STATUS_NAME_TOO_LONG},
++ {"NT_STATUS_FILES_OPEN", NT_STATUS_FILES_OPEN},
++ {"NT_STATUS_CONNECTION_IN_USE", NT_STATUS_CONNECTION_IN_USE},
++ {"NT_STATUS_MESSAGE_NOT_FOUND", NT_STATUS_MESSAGE_NOT_FOUND},
++ {"NT_STATUS_PROCESS_IS_TERMINATING",
++ NT_STATUS_PROCESS_IS_TERMINATING},
++ {"NT_STATUS_INVALID_LOGON_TYPE", NT_STATUS_INVALID_LOGON_TYPE},
++ {"NT_STATUS_NO_GUID_TRANSLATION", NT_STATUS_NO_GUID_TRANSLATION},
++ {"NT_STATUS_CANNOT_IMPERSONATE", NT_STATUS_CANNOT_IMPERSONATE},
++ {"NT_STATUS_IMAGE_ALREADY_LOADED", NT_STATUS_IMAGE_ALREADY_LOADED},
++ {"NT_STATUS_ABIOS_NOT_PRESENT", NT_STATUS_ABIOS_NOT_PRESENT},
++ {"NT_STATUS_ABIOS_LID_NOT_EXIST", NT_STATUS_ABIOS_LID_NOT_EXIST},
++ {"NT_STATUS_ABIOS_LID_ALREADY_OWNED",
++ NT_STATUS_ABIOS_LID_ALREADY_OWNED},
++ {"NT_STATUS_ABIOS_NOT_LID_OWNER", NT_STATUS_ABIOS_NOT_LID_OWNER},
++ {"NT_STATUS_ABIOS_INVALID_COMMAND",
++ NT_STATUS_ABIOS_INVALID_COMMAND},
++ {"NT_STATUS_ABIOS_INVALID_LID", NT_STATUS_ABIOS_INVALID_LID},
++ {"NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE",
++ NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE},
++ {"NT_STATUS_ABIOS_INVALID_SELECTOR",
++ NT_STATUS_ABIOS_INVALID_SELECTOR},
++ {"NT_STATUS_NO_LDT", NT_STATUS_NO_LDT},
++ {"NT_STATUS_INVALID_LDT_SIZE", NT_STATUS_INVALID_LDT_SIZE},
++ {"NT_STATUS_INVALID_LDT_OFFSET", NT_STATUS_INVALID_LDT_OFFSET},
++ {"NT_STATUS_INVALID_LDT_DESCRIPTOR",
++ NT_STATUS_INVALID_LDT_DESCRIPTOR},
++ {"NT_STATUS_INVALID_IMAGE_NE_FORMAT",
++ NT_STATUS_INVALID_IMAGE_NE_FORMAT},
++ {"NT_STATUS_RXACT_INVALID_STATE", NT_STATUS_RXACT_INVALID_STATE},
++ {"NT_STATUS_RXACT_COMMIT_FAILURE", NT_STATUS_RXACT_COMMIT_FAILURE},
++ {"NT_STATUS_MAPPED_FILE_SIZE_ZERO",
++ NT_STATUS_MAPPED_FILE_SIZE_ZERO},
++ {"NT_STATUS_TOO_MANY_OPENED_FILES",
++ NT_STATUS_TOO_MANY_OPENED_FILES},
++ {"NT_STATUS_CANCELLED", NT_STATUS_CANCELLED},
++ {"NT_STATUS_CANNOT_DELETE", NT_STATUS_CANNOT_DELETE},
++ {"NT_STATUS_INVALID_COMPUTER_NAME",
++ NT_STATUS_INVALID_COMPUTER_NAME},
++ {"NT_STATUS_FILE_DELETED", NT_STATUS_FILE_DELETED},
++ {"NT_STATUS_SPECIAL_ACCOUNT", NT_STATUS_SPECIAL_ACCOUNT},
++ {"NT_STATUS_SPECIAL_GROUP", NT_STATUS_SPECIAL_GROUP},
++ {"NT_STATUS_SPECIAL_USER", NT_STATUS_SPECIAL_USER},
++ {"NT_STATUS_MEMBERS_PRIMARY_GROUP",
++ NT_STATUS_MEMBERS_PRIMARY_GROUP},
++ {"NT_STATUS_FILE_CLOSED", NT_STATUS_FILE_CLOSED},
++ {"NT_STATUS_TOO_MANY_THREADS", NT_STATUS_TOO_MANY_THREADS},
++ {"NT_STATUS_THREAD_NOT_IN_PROCESS",
++ NT_STATUS_THREAD_NOT_IN_PROCESS},
++ {"NT_STATUS_TOKEN_ALREADY_IN_USE", NT_STATUS_TOKEN_ALREADY_IN_USE},
++ {"NT_STATUS_PAGEFILE_QUOTA_EXCEEDED",
++ NT_STATUS_PAGEFILE_QUOTA_EXCEEDED},
++ {"NT_STATUS_COMMITMENT_LIMIT", NT_STATUS_COMMITMENT_LIMIT},
++ {"NT_STATUS_INVALID_IMAGE_LE_FORMAT",
++ NT_STATUS_INVALID_IMAGE_LE_FORMAT},
++ {"NT_STATUS_INVALID_IMAGE_NOT_MZ", NT_STATUS_INVALID_IMAGE_NOT_MZ},
++ {"NT_STATUS_INVALID_IMAGE_PROTECT",
++ NT_STATUS_INVALID_IMAGE_PROTECT},
++ {"NT_STATUS_INVALID_IMAGE_WIN_16", NT_STATUS_INVALID_IMAGE_WIN_16},
++ {"NT_STATUS_LOGON_SERVER_CONFLICT",
++ NT_STATUS_LOGON_SERVER_CONFLICT},
++ {"NT_STATUS_TIME_DIFFERENCE_AT_DC",
++ NT_STATUS_TIME_DIFFERENCE_AT_DC},
++ {"NT_STATUS_SYNCHRONIZATION_REQUIRED",
++ NT_STATUS_SYNCHRONIZATION_REQUIRED},
++ {"NT_STATUS_DLL_NOT_FOUND", NT_STATUS_DLL_NOT_FOUND},
++ {"NT_STATUS_OPEN_FAILED", NT_STATUS_OPEN_FAILED},
++ {"NT_STATUS_IO_PRIVILEGE_FAILED", NT_STATUS_IO_PRIVILEGE_FAILED},
++ {"NT_STATUS_ORDINAL_NOT_FOUND", NT_STATUS_ORDINAL_NOT_FOUND},
++ {"NT_STATUS_ENTRYPOINT_NOT_FOUND", NT_STATUS_ENTRYPOINT_NOT_FOUND},
++ {"NT_STATUS_CONTROL_C_EXIT", NT_STATUS_CONTROL_C_EXIT},
++ {"NT_STATUS_LOCAL_DISCONNECT", NT_STATUS_LOCAL_DISCONNECT},
++ {"NT_STATUS_REMOTE_DISCONNECT", NT_STATUS_REMOTE_DISCONNECT},
++ {"NT_STATUS_REMOTE_RESOURCES", NT_STATUS_REMOTE_RESOURCES},
++ {"NT_STATUS_LINK_FAILED", NT_STATUS_LINK_FAILED},
++ {"NT_STATUS_LINK_TIMEOUT", NT_STATUS_LINK_TIMEOUT},
++ {"NT_STATUS_INVALID_CONNECTION", NT_STATUS_INVALID_CONNECTION},
++ {"NT_STATUS_INVALID_ADDRESS", NT_STATUS_INVALID_ADDRESS},
++ {"NT_STATUS_DLL_INIT_FAILED", NT_STATUS_DLL_INIT_FAILED},
++ {"NT_STATUS_MISSING_SYSTEMFILE", NT_STATUS_MISSING_SYSTEMFILE},
++ {"NT_STATUS_UNHANDLED_EXCEPTION", NT_STATUS_UNHANDLED_EXCEPTION},
++ {"NT_STATUS_APP_INIT_FAILURE", NT_STATUS_APP_INIT_FAILURE},
++ {"NT_STATUS_PAGEFILE_CREATE_FAILED",
++ NT_STATUS_PAGEFILE_CREATE_FAILED},
++ {"NT_STATUS_NO_PAGEFILE", NT_STATUS_NO_PAGEFILE},
++ {"NT_STATUS_INVALID_LEVEL", NT_STATUS_INVALID_LEVEL},
++ {"NT_STATUS_WRONG_PASSWORD_CORE", NT_STATUS_WRONG_PASSWORD_CORE},
++ {"NT_STATUS_ILLEGAL_FLOAT_CONTEXT",
++ NT_STATUS_ILLEGAL_FLOAT_CONTEXT},
++ {"NT_STATUS_PIPE_BROKEN", NT_STATUS_PIPE_BROKEN},
++ {"NT_STATUS_REGISTRY_CORRUPT", NT_STATUS_REGISTRY_CORRUPT},
++ {"NT_STATUS_REGISTRY_IO_FAILED", NT_STATUS_REGISTRY_IO_FAILED},
++ {"NT_STATUS_NO_EVENT_PAIR", NT_STATUS_NO_EVENT_PAIR},
++ {"NT_STATUS_UNRECOGNIZED_VOLUME", NT_STATUS_UNRECOGNIZED_VOLUME},
++ {"NT_STATUS_SERIAL_NO_DEVICE_INITED",
++ NT_STATUS_SERIAL_NO_DEVICE_INITED},
++ {"NT_STATUS_NO_SUCH_ALIAS", NT_STATUS_NO_SUCH_ALIAS},
++ {"NT_STATUS_MEMBER_NOT_IN_ALIAS", NT_STATUS_MEMBER_NOT_IN_ALIAS},
++ {"NT_STATUS_MEMBER_IN_ALIAS", NT_STATUS_MEMBER_IN_ALIAS},
++ {"NT_STATUS_ALIAS_EXISTS", NT_STATUS_ALIAS_EXISTS},
++ {"NT_STATUS_LOGON_NOT_GRANTED", NT_STATUS_LOGON_NOT_GRANTED},
++ {"NT_STATUS_TOO_MANY_SECRETS", NT_STATUS_TOO_MANY_SECRETS},
++ {"NT_STATUS_SECRET_TOO_LONG", NT_STATUS_SECRET_TOO_LONG},
++ {"NT_STATUS_INTERNAL_DB_ERROR", NT_STATUS_INTERNAL_DB_ERROR},
++ {"NT_STATUS_FULLSCREEN_MODE", NT_STATUS_FULLSCREEN_MODE},
++ {"NT_STATUS_TOO_MANY_CONTEXT_IDS", NT_STATUS_TOO_MANY_CONTEXT_IDS},
++ {"NT_STATUS_LOGON_TYPE_NOT_GRANTED",
++ NT_STATUS_LOGON_TYPE_NOT_GRANTED},
++ {"NT_STATUS_NOT_REGISTRY_FILE", NT_STATUS_NOT_REGISTRY_FILE},
++ {"NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED",
++ NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED},
++ {"NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR",
++ NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR},
++ {"NT_STATUS_FT_MISSING_MEMBER", NT_STATUS_FT_MISSING_MEMBER},
++ {"NT_STATUS_ILL_FORMED_SERVICE_ENTRY",
++ NT_STATUS_ILL_FORMED_SERVICE_ENTRY},
++ {"NT_STATUS_ILLEGAL_CHARACTER", NT_STATUS_ILLEGAL_CHARACTER},
++ {"NT_STATUS_UNMAPPABLE_CHARACTER", NT_STATUS_UNMAPPABLE_CHARACTER},
++ {"NT_STATUS_UNDEFINED_CHARACTER", NT_STATUS_UNDEFINED_CHARACTER},
++ {"NT_STATUS_FLOPPY_VOLUME", NT_STATUS_FLOPPY_VOLUME},
++ {"NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND",
++ NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND},
++ {"NT_STATUS_FLOPPY_WRONG_CYLINDER",
++ NT_STATUS_FLOPPY_WRONG_CYLINDER},
++ {"NT_STATUS_FLOPPY_UNKNOWN_ERROR", NT_STATUS_FLOPPY_UNKNOWN_ERROR},
++ {"NT_STATUS_FLOPPY_BAD_REGISTERS", NT_STATUS_FLOPPY_BAD_REGISTERS},
++ {"NT_STATUS_DISK_RECALIBRATE_FAILED",
++ NT_STATUS_DISK_RECALIBRATE_FAILED},
++ {"NT_STATUS_DISK_OPERATION_FAILED",
++ NT_STATUS_DISK_OPERATION_FAILED},
++ {"NT_STATUS_DISK_RESET_FAILED", NT_STATUS_DISK_RESET_FAILED},
++ {"NT_STATUS_SHARED_IRQ_BUSY", NT_STATUS_SHARED_IRQ_BUSY},
++ {"NT_STATUS_FT_ORPHANING", NT_STATUS_FT_ORPHANING},
++ {"NT_STATUS_PARTITION_FAILURE", NT_STATUS_PARTITION_FAILURE},
++ {"NT_STATUS_INVALID_BLOCK_LENGTH", NT_STATUS_INVALID_BLOCK_LENGTH},
++ {"NT_STATUS_DEVICE_NOT_PARTITIONED",
++ NT_STATUS_DEVICE_NOT_PARTITIONED},
++ {"NT_STATUS_UNABLE_TO_LOCK_MEDIA", NT_STATUS_UNABLE_TO_LOCK_MEDIA},
++ {"NT_STATUS_UNABLE_TO_UNLOAD_MEDIA",
++ NT_STATUS_UNABLE_TO_UNLOAD_MEDIA},
++ {"NT_STATUS_EOM_OVERFLOW", NT_STATUS_EOM_OVERFLOW},
++ {"NT_STATUS_NO_MEDIA", NT_STATUS_NO_MEDIA},
++ {"NT_STATUS_NO_SUCH_MEMBER", NT_STATUS_NO_SUCH_MEMBER},
++ {"NT_STATUS_INVALID_MEMBER", NT_STATUS_INVALID_MEMBER},
++ {"NT_STATUS_KEY_DELETED", NT_STATUS_KEY_DELETED},
++ {"NT_STATUS_NO_LOG_SPACE", NT_STATUS_NO_LOG_SPACE},
++ {"NT_STATUS_TOO_MANY_SIDS", NT_STATUS_TOO_MANY_SIDS},
++ {"NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED",
++ NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED},
++ {"NT_STATUS_KEY_HAS_CHILDREN", NT_STATUS_KEY_HAS_CHILDREN},
++ {"NT_STATUS_CHILD_MUST_BE_VOLATILE",
++ NT_STATUS_CHILD_MUST_BE_VOLATILE},
++ {"NT_STATUS_DEVICE_CONFIGURATION_ERROR",
++ NT_STATUS_DEVICE_CONFIGURATION_ERROR},
++ {"NT_STATUS_DRIVER_INTERNAL_ERROR",
++ NT_STATUS_DRIVER_INTERNAL_ERROR},
++ {"NT_STATUS_INVALID_DEVICE_STATE", NT_STATUS_INVALID_DEVICE_STATE},
++ {"NT_STATUS_IO_DEVICE_ERROR", NT_STATUS_IO_DEVICE_ERROR},
++ {"NT_STATUS_DEVICE_PROTOCOL_ERROR",
++ NT_STATUS_DEVICE_PROTOCOL_ERROR},
++ {"NT_STATUS_BACKUP_CONTROLLER", NT_STATUS_BACKUP_CONTROLLER},
++ {"NT_STATUS_LOG_FILE_FULL", NT_STATUS_LOG_FILE_FULL},
++ {"NT_STATUS_TOO_LATE", NT_STATUS_TOO_LATE},
++ {"NT_STATUS_NO_TRUST_LSA_SECRET", NT_STATUS_NO_TRUST_LSA_SECRET},
++ {"NT_STATUS_NO_TRUST_SAM_ACCOUNT", NT_STATUS_NO_TRUST_SAM_ACCOUNT},
++ {"NT_STATUS_TRUSTED_DOMAIN_FAILURE",
++ NT_STATUS_TRUSTED_DOMAIN_FAILURE},
++ {"NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE",
++ NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE},
++ {"NT_STATUS_EVENTLOG_FILE_CORRUPT",
++ NT_STATUS_EVENTLOG_FILE_CORRUPT},
++ {"NT_STATUS_EVENTLOG_CANT_START", NT_STATUS_EVENTLOG_CANT_START},
++ {"NT_STATUS_TRUST_FAILURE", NT_STATUS_TRUST_FAILURE},
++ {"NT_STATUS_MUTANT_LIMIT_EXCEEDED",
++ NT_STATUS_MUTANT_LIMIT_EXCEEDED},
++ {"NT_STATUS_NETLOGON_NOT_STARTED", NT_STATUS_NETLOGON_NOT_STARTED},
++ {"NT_STATUS_ACCOUNT_EXPIRED", NT_STATUS_ACCOUNT_EXPIRED},
++ {"NT_STATUS_POSSIBLE_DEADLOCK", NT_STATUS_POSSIBLE_DEADLOCK},
++ {"NT_STATUS_NETWORK_CREDENTIAL_CONFLICT",
++ NT_STATUS_NETWORK_CREDENTIAL_CONFLICT},
++ {"NT_STATUS_REMOTE_SESSION_LIMIT", NT_STATUS_REMOTE_SESSION_LIMIT},
++ {"NT_STATUS_EVENTLOG_FILE_CHANGED",
++ NT_STATUS_EVENTLOG_FILE_CHANGED},
++ {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
++ NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT},
++ {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
++ NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT},
++ {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
++ NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
++ {"NT_STATUS_DOMAIN_TRUST_INCONSISTENT",
++ NT_STATUS_DOMAIN_TRUST_INCONSISTENT},
++ {"NT_STATUS_FS_DRIVER_REQUIRED", NT_STATUS_FS_DRIVER_REQUIRED},
++ {"NT_STATUS_NO_USER_SESSION_KEY", NT_STATUS_NO_USER_SESSION_KEY},
++ {"NT_STATUS_USER_SESSION_DELETED", NT_STATUS_USER_SESSION_DELETED},
++ {"NT_STATUS_RESOURCE_LANG_NOT_FOUND",
++ NT_STATUS_RESOURCE_LANG_NOT_FOUND},
++ {"NT_STATUS_INSUFF_SERVER_RESOURCES",
++ NT_STATUS_INSUFF_SERVER_RESOURCES},
++ {"NT_STATUS_INVALID_BUFFER_SIZE", NT_STATUS_INVALID_BUFFER_SIZE},
++ {"NT_STATUS_INVALID_ADDRESS_COMPONENT",
++ NT_STATUS_INVALID_ADDRESS_COMPONENT},
++ {"NT_STATUS_INVALID_ADDRESS_WILDCARD",
++ NT_STATUS_INVALID_ADDRESS_WILDCARD},
++ {"NT_STATUS_TOO_MANY_ADDRESSES", NT_STATUS_TOO_MANY_ADDRESSES},
++ {"NT_STATUS_ADDRESS_ALREADY_EXISTS",
++ NT_STATUS_ADDRESS_ALREADY_EXISTS},
++ {"NT_STATUS_ADDRESS_CLOSED", NT_STATUS_ADDRESS_CLOSED},
++ {"NT_STATUS_CONNECTION_DISCONNECTED",
++ NT_STATUS_CONNECTION_DISCONNECTED},
++ {"NT_STATUS_CONNECTION_RESET", NT_STATUS_CONNECTION_RESET},
++ {"NT_STATUS_TOO_MANY_NODES", NT_STATUS_TOO_MANY_NODES},
++ {"NT_STATUS_TRANSACTION_ABORTED", NT_STATUS_TRANSACTION_ABORTED},
++ {"NT_STATUS_TRANSACTION_TIMED_OUT",
++ NT_STATUS_TRANSACTION_TIMED_OUT},
++ {"NT_STATUS_TRANSACTION_NO_RELEASE",
++ NT_STATUS_TRANSACTION_NO_RELEASE},
++ {"NT_STATUS_TRANSACTION_NO_MATCH", NT_STATUS_TRANSACTION_NO_MATCH},
++ {"NT_STATUS_TRANSACTION_RESPONDED",
++ NT_STATUS_TRANSACTION_RESPONDED},
++ {"NT_STATUS_TRANSACTION_INVALID_ID",
++ NT_STATUS_TRANSACTION_INVALID_ID},
++ {"NT_STATUS_TRANSACTION_INVALID_TYPE",
++ NT_STATUS_TRANSACTION_INVALID_TYPE},
++ {"NT_STATUS_NOT_SERVER_SESSION", NT_STATUS_NOT_SERVER_SESSION},
++ {"NT_STATUS_NOT_CLIENT_SESSION", NT_STATUS_NOT_CLIENT_SESSION},
++ {"NT_STATUS_CANNOT_LOAD_REGISTRY_FILE",
++ NT_STATUS_CANNOT_LOAD_REGISTRY_FILE},
++ {"NT_STATUS_DEBUG_ATTACH_FAILED", NT_STATUS_DEBUG_ATTACH_FAILED},
++ {"NT_STATUS_SYSTEM_PROCESS_TERMINATED",
++ NT_STATUS_SYSTEM_PROCESS_TERMINATED},
++ {"NT_STATUS_DATA_NOT_ACCEPTED", NT_STATUS_DATA_NOT_ACCEPTED},
++ {"NT_STATUS_NO_BROWSER_SERVERS_FOUND",
++ NT_STATUS_NO_BROWSER_SERVERS_FOUND},
++ {"NT_STATUS_VDM_HARD_ERROR", NT_STATUS_VDM_HARD_ERROR},
++ {"NT_STATUS_DRIVER_CANCEL_TIMEOUT",
++ NT_STATUS_DRIVER_CANCEL_TIMEOUT},
++ {"NT_STATUS_REPLY_MESSAGE_MISMATCH",
++ NT_STATUS_REPLY_MESSAGE_MISMATCH},
++ {"NT_STATUS_MAPPED_ALIGNMENT", NT_STATUS_MAPPED_ALIGNMENT},
++ {"NT_STATUS_IMAGE_CHECKSUM_MISMATCH",
++ NT_STATUS_IMAGE_CHECKSUM_MISMATCH},
++ {"NT_STATUS_LOST_WRITEBEHIND_DATA",
++ NT_STATUS_LOST_WRITEBEHIND_DATA},
++ {"NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID",
++ NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID},
++ {"NT_STATUS_PASSWORD_MUST_CHANGE", NT_STATUS_PASSWORD_MUST_CHANGE},
++ {"NT_STATUS_NOT_FOUND", NT_STATUS_NOT_FOUND},
++ {"NT_STATUS_NOT_TINY_STREAM", NT_STATUS_NOT_TINY_STREAM},
++ {"NT_STATUS_RECOVERY_FAILURE", NT_STATUS_RECOVERY_FAILURE},
++ {"NT_STATUS_STACK_OVERFLOW_READ", NT_STATUS_STACK_OVERFLOW_READ},
++ {"NT_STATUS_FAIL_CHECK", NT_STATUS_FAIL_CHECK},
++ {"NT_STATUS_DUPLICATE_OBJECTID", NT_STATUS_DUPLICATE_OBJECTID},
++ {"NT_STATUS_OBJECTID_EXISTS", NT_STATUS_OBJECTID_EXISTS},
++ {"NT_STATUS_CONVERT_TO_LARGE", NT_STATUS_CONVERT_TO_LARGE},
++ {"NT_STATUS_RETRY", NT_STATUS_RETRY},
++ {"NT_STATUS_FOUND_OUT_OF_SCOPE", NT_STATUS_FOUND_OUT_OF_SCOPE},
++ {"NT_STATUS_ALLOCATE_BUCKET", NT_STATUS_ALLOCATE_BUCKET},
++ {"NT_STATUS_PROPSET_NOT_FOUND", NT_STATUS_PROPSET_NOT_FOUND},
++ {"NT_STATUS_MARSHALL_OVERFLOW", NT_STATUS_MARSHALL_OVERFLOW},
++ {"NT_STATUS_INVALID_VARIANT", NT_STATUS_INVALID_VARIANT},
++ {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
++ NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND},
++ {"NT_STATUS_ACCOUNT_LOCKED_OUT", NT_STATUS_ACCOUNT_LOCKED_OUT},
++ {"NT_STATUS_HANDLE_NOT_CLOSABLE", NT_STATUS_HANDLE_NOT_CLOSABLE},
++ {"NT_STATUS_CONNECTION_REFUSED", NT_STATUS_CONNECTION_REFUSED},
++ {"NT_STATUS_GRACEFUL_DISCONNECT", NT_STATUS_GRACEFUL_DISCONNECT},
++ {"NT_STATUS_ADDRESS_ALREADY_ASSOCIATED",
++ NT_STATUS_ADDRESS_ALREADY_ASSOCIATED},
++ {"NT_STATUS_ADDRESS_NOT_ASSOCIATED",
++ NT_STATUS_ADDRESS_NOT_ASSOCIATED},
++ {"NT_STATUS_CONNECTION_INVALID", NT_STATUS_CONNECTION_INVALID},
++ {"NT_STATUS_CONNECTION_ACTIVE", NT_STATUS_CONNECTION_ACTIVE},
++ {"NT_STATUS_NETWORK_UNREACHABLE", NT_STATUS_NETWORK_UNREACHABLE},
++ {"NT_STATUS_HOST_UNREACHABLE", NT_STATUS_HOST_UNREACHABLE},
++ {"NT_STATUS_PROTOCOL_UNREACHABLE", NT_STATUS_PROTOCOL_UNREACHABLE},
++ {"NT_STATUS_PORT_UNREACHABLE", NT_STATUS_PORT_UNREACHABLE},
++ {"NT_STATUS_REQUEST_ABORTED", NT_STATUS_REQUEST_ABORTED},
++ {"NT_STATUS_CONNECTION_ABORTED", NT_STATUS_CONNECTION_ABORTED},
++ {"NT_STATUS_BAD_COMPRESSION_BUFFER",
++ NT_STATUS_BAD_COMPRESSION_BUFFER},
++ {"NT_STATUS_USER_MAPPED_FILE", NT_STATUS_USER_MAPPED_FILE},
++ {"NT_STATUS_AUDIT_FAILED", NT_STATUS_AUDIT_FAILED},
++ {"NT_STATUS_TIMER_RESOLUTION_NOT_SET",
++ NT_STATUS_TIMER_RESOLUTION_NOT_SET},
++ {"NT_STATUS_CONNECTION_COUNT_LIMIT",
++ NT_STATUS_CONNECTION_COUNT_LIMIT},
++ {"NT_STATUS_LOGIN_TIME_RESTRICTION",
++ NT_STATUS_LOGIN_TIME_RESTRICTION},
++ {"NT_STATUS_LOGIN_WKSTA_RESTRICTION",
++ NT_STATUS_LOGIN_WKSTA_RESTRICTION},
++ {"NT_STATUS_IMAGE_MP_UP_MISMATCH", NT_STATUS_IMAGE_MP_UP_MISMATCH},
++ {"NT_STATUS_INSUFFICIENT_LOGON_INFO",
++ NT_STATUS_INSUFFICIENT_LOGON_INFO},
++ {"NT_STATUS_BAD_DLL_ENTRYPOINT", NT_STATUS_BAD_DLL_ENTRYPOINT},
++ {"NT_STATUS_BAD_SERVICE_ENTRYPOINT",
++ NT_STATUS_BAD_SERVICE_ENTRYPOINT},
++ {"NT_STATUS_LPC_REPLY_LOST", NT_STATUS_LPC_REPLY_LOST},
++ {"NT_STATUS_IP_ADDRESS_CONFLICT1", NT_STATUS_IP_ADDRESS_CONFLICT1},
++ {"NT_STATUS_IP_ADDRESS_CONFLICT2", NT_STATUS_IP_ADDRESS_CONFLICT2},
++ {"NT_STATUS_REGISTRY_QUOTA_LIMIT", NT_STATUS_REGISTRY_QUOTA_LIMIT},
++ {"NT_STATUS_PATH_NOT_COVERED", NT_STATUS_PATH_NOT_COVERED},
++ {"NT_STATUS_NO_CALLBACK_ACTIVE", NT_STATUS_NO_CALLBACK_ACTIVE},
++ {"NT_STATUS_LICENSE_QUOTA_EXCEEDED",
++ NT_STATUS_LICENSE_QUOTA_EXCEEDED},
++ {"NT_STATUS_PWD_TOO_SHORT", NT_STATUS_PWD_TOO_SHORT},
++ {"NT_STATUS_PWD_TOO_RECENT", NT_STATUS_PWD_TOO_RECENT},
++ {"NT_STATUS_PWD_HISTORY_CONFLICT", NT_STATUS_PWD_HISTORY_CONFLICT},
++ {"NT_STATUS_PLUGPLAY_NO_DEVICE", NT_STATUS_PLUGPLAY_NO_DEVICE},
++ {"NT_STATUS_UNSUPPORTED_COMPRESSION",
++ NT_STATUS_UNSUPPORTED_COMPRESSION},
++ {"NT_STATUS_INVALID_HW_PROFILE", NT_STATUS_INVALID_HW_PROFILE},
++ {"NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH",
++ NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH},
++ {"NT_STATUS_DRIVER_ORDINAL_NOT_FOUND",
++ NT_STATUS_DRIVER_ORDINAL_NOT_FOUND},
++ {"NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND",
++ NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND},
++ {"NT_STATUS_RESOURCE_NOT_OWNED", NT_STATUS_RESOURCE_NOT_OWNED},
++ {"NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS},
++ {"NT_STATUS_QUOTA_LIST_INCONSISTENT",
++ NT_STATUS_QUOTA_LIST_INCONSISTENT},
++ {"NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE},
++ {"NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES},
++ {"STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES},
++ {"STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED},
++ {NULL, 0}
++};
+diff -urN linux-2.4.29.old/fs/cifs/nterr.h linux-2.4.29/fs/cifs/nterr.h
+--- linux-2.4.29.old/fs/cifs/nterr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/nterr.h 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,556 @@
++/*
++ Unix SMB/Netbios implementation.
++ Version 1.9.
++ NT error code constants
++ Copyright (C) Andrew Tridgell 1992-2000
++ Copyright (C) John H Terpstra 1996-2000
++ Copyright (C) Luke Kenneth Casson Leighton 1996-2000
++ Copyright (C) Paul Ashton 1998-2000
++
++ 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 _NTERR_H
++#define _NTERR_H
++
++struct nt_err_code_struct {
++ char *nt_errstr;
++ __u32 nt_errcode;
++};
++
++extern const struct nt_err_code_struct nt_errs[];
++
++/* Win32 Status codes. */
++
++#define STATUS_BUFFER_OVERFLOW 0x80000005
++#define STATUS_MORE_ENTRIES 0x0105
++#define ERROR_INVALID_PARAMETER 0x0057
++#define ERROR_INSUFFICIENT_BUFFER 0x007a
++#define STATUS_1804 0x070c
++#define STATUS_NOTIFY_ENUM_DIR 0x010c
++
++/* Win32 Error codes extracted using a loop in smbclient then printing a
++ netmon sniff to a file. */
++
++#define NT_STATUS_OK 0x0000
++#define STATUS_SOME_UNMAPPED 0x0107
++#define STATUS_BUFFER_OVERFLOW 0x80000005
++#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a
++#define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001
++#define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002
++#define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003
++#define NT_STATUS_INFO_LENGTH_MISMATCH 0xC0000000 | 0x0004
++#define NT_STATUS_ACCESS_VIOLATION 0xC0000000 | 0x0005
++#define NT_STATUS_IN_PAGE_ERROR 0xC0000000 | 0x0006
++#define NT_STATUS_PAGEFILE_QUOTA 0xC0000000 | 0x0007
++#define NT_STATUS_INVALID_HANDLE 0xC0000000 | 0x0008
++#define NT_STATUS_BAD_INITIAL_STACK 0xC0000000 | 0x0009
++#define NT_STATUS_BAD_INITIAL_PC 0xC0000000 | 0x000a
++#define NT_STATUS_INVALID_CID 0xC0000000 | 0x000b
++#define NT_STATUS_TIMER_NOT_CANCELED 0xC0000000 | 0x000c
++#define NT_STATUS_INVALID_PARAMETER 0xC0000000 | 0x000d
++#define NT_STATUS_NO_SUCH_DEVICE 0xC0000000 | 0x000e
++#define NT_STATUS_NO_SUCH_FILE 0xC0000000 | 0x000f
++#define NT_STATUS_INVALID_DEVICE_REQUEST 0xC0000000 | 0x0010
++#define NT_STATUS_END_OF_FILE 0xC0000000 | 0x0011
++#define NT_STATUS_WRONG_VOLUME 0xC0000000 | 0x0012
++#define NT_STATUS_NO_MEDIA_IN_DEVICE 0xC0000000 | 0x0013
++#define NT_STATUS_UNRECOGNIZED_MEDIA 0xC0000000 | 0x0014
++#define NT_STATUS_NONEXISTENT_SECTOR 0xC0000000 | 0x0015
++#define NT_STATUS_MORE_PROCESSING_REQUIRED 0xC0000000 | 0x0016
++#define NT_STATUS_NO_MEMORY 0xC0000000 | 0x0017
++#define NT_STATUS_CONFLICTING_ADDRESSES 0xC0000000 | 0x0018
++#define NT_STATUS_NOT_MAPPED_VIEW 0xC0000000 | 0x0019
++#define NT_STATUS_UNABLE_TO_FREE_VM 0x80000000 | 0x001a
++#define NT_STATUS_UNABLE_TO_DELETE_SECTION 0xC0000000 | 0x001b
++#define NT_STATUS_INVALID_SYSTEM_SERVICE 0xC0000000 | 0x001c
++#define NT_STATUS_ILLEGAL_INSTRUCTION 0xC0000000 | 0x001d
++#define NT_STATUS_INVALID_LOCK_SEQUENCE 0xC0000000 | 0x001e
++#define NT_STATUS_INVALID_VIEW_SIZE 0xC0000000 | 0x001f
++#define NT_STATUS_INVALID_FILE_FOR_SECTION 0xC0000000 | 0x0020
++#define NT_STATUS_ALREADY_COMMITTED 0xC0000000 | 0x0021
++#define NT_STATUS_ACCESS_DENIED 0xC0000000 | 0x0022
++#define NT_STATUS_BUFFER_TOO_SMALL 0xC0000000 | 0x0023
++#define NT_STATUS_OBJECT_TYPE_MISMATCH 0xC0000000 | 0x0024
++#define NT_STATUS_NONCONTINUABLE_EXCEPTION 0xC0000000 | 0x0025
++#define NT_STATUS_INVALID_DISPOSITION 0xC0000000 | 0x0026
++#define NT_STATUS_UNWIND 0xC0000000 | 0x0027
++#define NT_STATUS_BAD_STACK 0xC0000000 | 0x0028
++#define NT_STATUS_INVALID_UNWIND_TARGET 0xC0000000 | 0x0029
++#define NT_STATUS_NOT_LOCKED 0xC0000000 | 0x002a
++#define NT_STATUS_PARITY_ERROR 0xC0000000 | 0x002b
++#define NT_STATUS_UNABLE_TO_DECOMMIT_VM 0xC0000000 | 0x002c
++#define NT_STATUS_NOT_COMMITTED 0xC0000000 | 0x002d
++#define NT_STATUS_INVALID_PORT_ATTRIBUTES 0xC0000000 | 0x002e
++#define NT_STATUS_PORT_MESSAGE_TOO_LONG 0xC0000000 | 0x002f
++#define NT_STATUS_INVALID_PARAMETER_MIX 0xC0000000 | 0x0030
++#define NT_STATUS_INVALID_QUOTA_LOWER 0xC0000000 | 0x0031
++#define NT_STATUS_DISK_CORRUPT_ERROR 0xC0000000 | 0x0032
++#define NT_STATUS_OBJECT_NAME_INVALID 0xC0000000 | 0x0033
++#define NT_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000000 | 0x0034
++#define NT_STATUS_OBJECT_NAME_COLLISION 0xC0000000 | 0x0035
++#define NT_STATUS_HANDLE_NOT_WAITABLE 0xC0000000 | 0x0036
++#define NT_STATUS_PORT_DISCONNECTED 0xC0000000 | 0x0037
++#define NT_STATUS_DEVICE_ALREADY_ATTACHED 0xC0000000 | 0x0038
++#define NT_STATUS_OBJECT_PATH_INVALID 0xC0000000 | 0x0039
++#define NT_STATUS_OBJECT_PATH_NOT_FOUND 0xC0000000 | 0x003a
++#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD 0xC0000000 | 0x003b
++#define NT_STATUS_DATA_OVERRUN 0xC0000000 | 0x003c
++#define NT_STATUS_DATA_LATE_ERROR 0xC0000000 | 0x003d
++#define NT_STATUS_DATA_ERROR 0xC0000000 | 0x003e
++#define NT_STATUS_CRC_ERROR 0xC0000000 | 0x003f
++#define NT_STATUS_SECTION_TOO_BIG 0xC0000000 | 0x0040
++#define NT_STATUS_PORT_CONNECTION_REFUSED 0xC0000000 | 0x0041
++#define NT_STATUS_INVALID_PORT_HANDLE 0xC0000000 | 0x0042
++#define NT_STATUS_SHARING_VIOLATION 0xC0000000 | 0x0043
++#define NT_STATUS_QUOTA_EXCEEDED 0xC0000000 | 0x0044
++#define NT_STATUS_INVALID_PAGE_PROTECTION 0xC0000000 | 0x0045
++#define NT_STATUS_MUTANT_NOT_OWNED 0xC0000000 | 0x0046
++#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED 0xC0000000 | 0x0047
++#define NT_STATUS_PORT_ALREADY_SET 0xC0000000 | 0x0048
++#define NT_STATUS_SECTION_NOT_IMAGE 0xC0000000 | 0x0049
++#define NT_STATUS_SUSPEND_COUNT_EXCEEDED 0xC0000000 | 0x004a
++#define NT_STATUS_THREAD_IS_TERMINATING 0xC0000000 | 0x004b
++#define NT_STATUS_BAD_WORKING_SET_LIMIT 0xC0000000 | 0x004c
++#define NT_STATUS_INCOMPATIBLE_FILE_MAP 0xC0000000 | 0x004d
++#define NT_STATUS_SECTION_PROTECTION 0xC0000000 | 0x004e
++#define NT_STATUS_EAS_NOT_SUPPORTED 0xC0000000 | 0x004f
++#define NT_STATUS_EA_TOO_LARGE 0xC0000000 | 0x0050
++#define NT_STATUS_NONEXISTENT_EA_ENTRY 0xC0000000 | 0x0051
++#define NT_STATUS_NO_EAS_ON_FILE 0xC0000000 | 0x0052
++#define NT_STATUS_EA_CORRUPT_ERROR 0xC0000000 | 0x0053
++#define NT_STATUS_FILE_LOCK_CONFLICT 0xC0000000 | 0x0054
++#define NT_STATUS_LOCK_NOT_GRANTED 0xC0000000 | 0x0055
++#define NT_STATUS_DELETE_PENDING 0xC0000000 | 0x0056
++#define NT_STATUS_CTL_FILE_NOT_SUPPORTED 0xC0000000 | 0x0057
++#define NT_STATUS_UNKNOWN_REVISION 0xC0000000 | 0x0058
++#define NT_STATUS_REVISION_MISMATCH 0xC0000000 | 0x0059
++#define NT_STATUS_INVALID_OWNER 0xC0000000 | 0x005a
++#define NT_STATUS_INVALID_PRIMARY_GROUP 0xC0000000 | 0x005b
++#define NT_STATUS_NO_IMPERSONATION_TOKEN 0xC0000000 | 0x005c
++#define NT_STATUS_CANT_DISABLE_MANDATORY 0xC0000000 | 0x005d
++#define NT_STATUS_NO_LOGON_SERVERS 0xC0000000 | 0x005e
++#define NT_STATUS_NO_SUCH_LOGON_SESSION 0xC0000000 | 0x005f
++#define NT_STATUS_NO_SUCH_PRIVILEGE 0xC0000000 | 0x0060
++#define NT_STATUS_PRIVILEGE_NOT_HELD 0xC0000000 | 0x0061
++#define NT_STATUS_INVALID_ACCOUNT_NAME 0xC0000000 | 0x0062
++#define NT_STATUS_USER_EXISTS 0xC0000000 | 0x0063
++#define NT_STATUS_NO_SUCH_USER 0xC0000000 | 0x0064
++#define NT_STATUS_GROUP_EXISTS 0xC0000000 | 0x0065
++#define NT_STATUS_NO_SUCH_GROUP 0xC0000000 | 0x0066
++#define NT_STATUS_MEMBER_IN_GROUP 0xC0000000 | 0x0067
++#define NT_STATUS_MEMBER_NOT_IN_GROUP 0xC0000000 | 0x0068
++#define NT_STATUS_LAST_ADMIN 0xC0000000 | 0x0069
++#define NT_STATUS_WRONG_PASSWORD 0xC0000000 | 0x006a
++#define NT_STATUS_ILL_FORMED_PASSWORD 0xC0000000 | 0x006b
++#define NT_STATUS_PASSWORD_RESTRICTION 0xC0000000 | 0x006c
++#define NT_STATUS_LOGON_FAILURE 0xC0000000 | 0x006d
++#define NT_STATUS_ACCOUNT_RESTRICTION 0xC0000000 | 0x006e
++#define NT_STATUS_INVALID_LOGON_HOURS 0xC0000000 | 0x006f
++#define NT_STATUS_INVALID_WORKSTATION 0xC0000000 | 0x0070
++#define NT_STATUS_PASSWORD_EXPIRED 0xC0000000 | 0x0071
++#define NT_STATUS_ACCOUNT_DISABLED 0xC0000000 | 0x0072
++#define NT_STATUS_NONE_MAPPED 0xC0000000 | 0x0073
++#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED 0xC0000000 | 0x0074
++#define NT_STATUS_LUIDS_EXHAUSTED 0xC0000000 | 0x0075
++#define NT_STATUS_INVALID_SUB_AUTHORITY 0xC0000000 | 0x0076
++#define NT_STATUS_INVALID_ACL 0xC0000000 | 0x0077
++#define NT_STATUS_INVALID_SID 0xC0000000 | 0x0078
++#define NT_STATUS_INVALID_SECURITY_DESCR 0xC0000000 | 0x0079
++#define NT_STATUS_PROCEDURE_NOT_FOUND 0xC0000000 | 0x007a
++#define NT_STATUS_INVALID_IMAGE_FORMAT 0xC0000000 | 0x007b
++#define NT_STATUS_NO_TOKEN 0xC0000000 | 0x007c
++#define NT_STATUS_BAD_INHERITANCE_ACL 0xC0000000 | 0x007d
++#define NT_STATUS_RANGE_NOT_LOCKED 0xC0000000 | 0x007e
++#define NT_STATUS_DISK_FULL 0xC0000000 | 0x007f
++#define NT_STATUS_SERVER_DISABLED 0xC0000000 | 0x0080
++#define NT_STATUS_SERVER_NOT_DISABLED 0xC0000000 | 0x0081
++#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED 0xC0000000 | 0x0082
++#define NT_STATUS_GUIDS_EXHAUSTED 0xC0000000 | 0x0083
++#define NT_STATUS_INVALID_ID_AUTHORITY 0xC0000000 | 0x0084
++#define NT_STATUS_AGENTS_EXHAUSTED 0xC0000000 | 0x0085
++#define NT_STATUS_INVALID_VOLUME_LABEL 0xC0000000 | 0x0086
++#define NT_STATUS_SECTION_NOT_EXTENDED 0xC0000000 | 0x0087
++#define NT_STATUS_NOT_MAPPED_DATA 0xC0000000 | 0x0088
++#define NT_STATUS_RESOURCE_DATA_NOT_FOUND 0xC0000000 | 0x0089
++#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND 0xC0000000 | 0x008a
++#define NT_STATUS_RESOURCE_NAME_NOT_FOUND 0xC0000000 | 0x008b
++#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED 0xC0000000 | 0x008c
++#define NT_STATUS_FLOAT_DENORMAL_OPERAND 0xC0000000 | 0x008d
++#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO 0xC0000000 | 0x008e
++#define NT_STATUS_FLOAT_INEXACT_RESULT 0xC0000000 | 0x008f
++#define NT_STATUS_FLOAT_INVALID_OPERATION 0xC0000000 | 0x0090
++#define NT_STATUS_FLOAT_OVERFLOW 0xC0000000 | 0x0091
++#define NT_STATUS_FLOAT_STACK_CHECK 0xC0000000 | 0x0092
++#define NT_STATUS_FLOAT_UNDERFLOW 0xC0000000 | 0x0093
++#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000000 | 0x0094
++#define NT_STATUS_INTEGER_OVERFLOW 0xC0000000 | 0x0095
++#define NT_STATUS_PRIVILEGED_INSTRUCTION 0xC0000000 | 0x0096
++#define NT_STATUS_TOO_MANY_PAGING_FILES 0xC0000000 | 0x0097
++#define NT_STATUS_FILE_INVALID 0xC0000000 | 0x0098
++#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED 0xC0000000 | 0x0099
++#define NT_STATUS_INSUFFICIENT_RESOURCES 0xC0000000 | 0x009a
++#define NT_STATUS_DFS_EXIT_PATH_FOUND 0xC0000000 | 0x009b
++#define NT_STATUS_DEVICE_DATA_ERROR 0xC0000000 | 0x009c
++#define NT_STATUS_DEVICE_NOT_CONNECTED 0xC0000000 | 0x009d
++#define NT_STATUS_DEVICE_POWER_FAILURE 0xC0000000 | 0x009e
++#define NT_STATUS_FREE_VM_NOT_AT_BASE 0xC0000000 | 0x009f
++#define NT_STATUS_MEMORY_NOT_ALLOCATED 0xC0000000 | 0x00a0
++#define NT_STATUS_WORKING_SET_QUOTA 0xC0000000 | 0x00a1
++#define NT_STATUS_MEDIA_WRITE_PROTECTED 0xC0000000 | 0x00a2
++#define NT_STATUS_DEVICE_NOT_READY 0xC0000000 | 0x00a3
++#define NT_STATUS_INVALID_GROUP_ATTRIBUTES 0xC0000000 | 0x00a4
++#define NT_STATUS_BAD_IMPERSONATION_LEVEL 0xC0000000 | 0x00a5
++#define NT_STATUS_CANT_OPEN_ANONYMOUS 0xC0000000 | 0x00a6
++#define NT_STATUS_BAD_VALIDATION_CLASS 0xC0000000 | 0x00a7
++#define NT_STATUS_BAD_TOKEN_TYPE 0xC0000000 | 0x00a8
++#define NT_STATUS_BAD_MASTER_BOOT_RECORD 0xC0000000 | 0x00a9
++#define NT_STATUS_INSTRUCTION_MISALIGNMENT 0xC0000000 | 0x00aa
++#define NT_STATUS_INSTANCE_NOT_AVAILABLE 0xC0000000 | 0x00ab
++#define NT_STATUS_PIPE_NOT_AVAILABLE 0xC0000000 | 0x00ac
++#define NT_STATUS_INVALID_PIPE_STATE 0xC0000000 | 0x00ad
++#define NT_STATUS_PIPE_BUSY 0xC0000000 | 0x00ae
++#define NT_STATUS_ILLEGAL_FUNCTION 0xC0000000 | 0x00af
++#define NT_STATUS_PIPE_DISCONNECTED 0xC0000000 | 0x00b0
++#define NT_STATUS_PIPE_CLOSING 0xC0000000 | 0x00b1
++#define NT_STATUS_PIPE_CONNECTED 0xC0000000 | 0x00b2
++#define NT_STATUS_PIPE_LISTENING 0xC0000000 | 0x00b3
++#define NT_STATUS_INVALID_READ_MODE 0xC0000000 | 0x00b4
++#define NT_STATUS_IO_TIMEOUT 0xC0000000 | 0x00b5
++#define NT_STATUS_FILE_FORCED_CLOSED 0xC0000000 | 0x00b6
++#define NT_STATUS_PROFILING_NOT_STARTED 0xC0000000 | 0x00b7
++#define NT_STATUS_PROFILING_NOT_STOPPED 0xC0000000 | 0x00b8
++#define NT_STATUS_COULD_NOT_INTERPRET 0xC0000000 | 0x00b9
++#define NT_STATUS_FILE_IS_A_DIRECTORY 0xC0000000 | 0x00ba
++#define NT_STATUS_NOT_SUPPORTED 0xC0000000 | 0x00bb
++#define NT_STATUS_REMOTE_NOT_LISTENING 0xC0000000 | 0x00bc
++#define NT_STATUS_DUPLICATE_NAME 0xC0000000 | 0x00bd
++#define NT_STATUS_BAD_NETWORK_PATH 0xC0000000 | 0x00be
++#define NT_STATUS_NETWORK_BUSY 0xC0000000 | 0x00bf
++#define NT_STATUS_DEVICE_DOES_NOT_EXIST 0xC0000000 | 0x00c0
++#define NT_STATUS_TOO_MANY_COMMANDS 0xC0000000 | 0x00c1
++#define NT_STATUS_ADAPTER_HARDWARE_ERROR 0xC0000000 | 0x00c2
++#define NT_STATUS_INVALID_NETWORK_RESPONSE 0xC0000000 | 0x00c3
++#define NT_STATUS_UNEXPECTED_NETWORK_ERROR 0xC0000000 | 0x00c4
++#define NT_STATUS_BAD_REMOTE_ADAPTER 0xC0000000 | 0x00c5
++#define NT_STATUS_PRINT_QUEUE_FULL 0xC0000000 | 0x00c6
++#define NT_STATUS_NO_SPOOL_SPACE 0xC0000000 | 0x00c7
++#define NT_STATUS_PRINT_CANCELLED 0xC0000000 | 0x00c8
++#define NT_STATUS_NETWORK_NAME_DELETED 0xC0000000 | 0x00c9
++#define NT_STATUS_NETWORK_ACCESS_DENIED 0xC0000000 | 0x00ca
++#define NT_STATUS_BAD_DEVICE_TYPE 0xC0000000 | 0x00cb
++#define NT_STATUS_BAD_NETWORK_NAME 0xC0000000 | 0x00cc
++#define NT_STATUS_TOO_MANY_NAMES 0xC0000000 | 0x00cd
++#define NT_STATUS_TOO_MANY_SESSIONS 0xC0000000 | 0x00ce
++#define NT_STATUS_SHARING_PAUSED 0xC0000000 | 0x00cf
++#define NT_STATUS_REQUEST_NOT_ACCEPTED 0xC0000000 | 0x00d0
++#define NT_STATUS_REDIRECTOR_PAUSED 0xC0000000 | 0x00d1
++#define NT_STATUS_NET_WRITE_FAULT 0xC0000000 | 0x00d2
++#define NT_STATUS_PROFILING_AT_LIMIT 0xC0000000 | 0x00d3
++#define NT_STATUS_NOT_SAME_DEVICE 0xC0000000 | 0x00d4
++#define NT_STATUS_FILE_RENAMED 0xC0000000 | 0x00d5
++#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED 0xC0000000 | 0x00d6
++#define NT_STATUS_NO_SECURITY_ON_OBJECT 0xC0000000 | 0x00d7
++#define NT_STATUS_CANT_WAIT 0xC0000000 | 0x00d8
++#define NT_STATUS_PIPE_EMPTY 0xC0000000 | 0x00d9
++#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO 0xC0000000 | 0x00da
++#define NT_STATUS_CANT_TERMINATE_SELF 0xC0000000 | 0x00db
++#define NT_STATUS_INVALID_SERVER_STATE 0xC0000000 | 0x00dc
++#define NT_STATUS_INVALID_DOMAIN_STATE 0xC0000000 | 0x00dd
++#define NT_STATUS_INVALID_DOMAIN_ROLE 0xC0000000 | 0x00de
++#define NT_STATUS_NO_SUCH_DOMAIN 0xC0000000 | 0x00df
++#define NT_STATUS_DOMAIN_EXISTS 0xC0000000 | 0x00e0
++#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED 0xC0000000 | 0x00e1
++#define NT_STATUS_OPLOCK_NOT_GRANTED 0xC0000000 | 0x00e2
++#define NT_STATUS_INVALID_OPLOCK_PROTOCOL 0xC0000000 | 0x00e3
++#define NT_STATUS_INTERNAL_DB_CORRUPTION 0xC0000000 | 0x00e4
++#define NT_STATUS_INTERNAL_ERROR 0xC0000000 | 0x00e5
++#define NT_STATUS_GENERIC_NOT_MAPPED 0xC0000000 | 0x00e6
++#define NT_STATUS_BAD_DESCRIPTOR_FORMAT 0xC0000000 | 0x00e7
++#define NT_STATUS_INVALID_USER_BUFFER 0xC0000000 | 0x00e8
++#define NT_STATUS_UNEXPECTED_IO_ERROR 0xC0000000 | 0x00e9
++#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR 0xC0000000 | 0x00ea
++#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR 0xC0000000 | 0x00eb
++#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR 0xC0000000 | 0x00ec
++#define NT_STATUS_NOT_LOGON_PROCESS 0xC0000000 | 0x00ed
++#define NT_STATUS_LOGON_SESSION_EXISTS 0xC0000000 | 0x00ee
++#define NT_STATUS_INVALID_PARAMETER_1 0xC0000000 | 0x00ef
++#define NT_STATUS_INVALID_PARAMETER_2 0xC0000000 | 0x00f0
++#define NT_STATUS_INVALID_PARAMETER_3 0xC0000000 | 0x00f1
++#define NT_STATUS_INVALID_PARAMETER_4 0xC0000000 | 0x00f2
++#define NT_STATUS_INVALID_PARAMETER_5 0xC0000000 | 0x00f3
++#define NT_STATUS_INVALID_PARAMETER_6 0xC0000000 | 0x00f4
++#define NT_STATUS_INVALID_PARAMETER_7 0xC0000000 | 0x00f5
++#define NT_STATUS_INVALID_PARAMETER_8 0xC0000000 | 0x00f6
++#define NT_STATUS_INVALID_PARAMETER_9 0xC0000000 | 0x00f7
++#define NT_STATUS_INVALID_PARAMETER_10 0xC0000000 | 0x00f8
++#define NT_STATUS_INVALID_PARAMETER_11 0xC0000000 | 0x00f9
++#define NT_STATUS_INVALID_PARAMETER_12 0xC0000000 | 0x00fa
++#define NT_STATUS_REDIRECTOR_NOT_STARTED 0xC0000000 | 0x00fb
++#define NT_STATUS_REDIRECTOR_STARTED 0xC0000000 | 0x00fc
++#define NT_STATUS_STACK_OVERFLOW 0xC0000000 | 0x00fd
++#define NT_STATUS_NO_SUCH_PACKAGE 0xC0000000 | 0x00fe
++#define NT_STATUS_BAD_FUNCTION_TABLE 0xC0000000 | 0x00ff
++#define NT_STATUS_DIRECTORY_NOT_EMPTY 0xC0000000 | 0x0101
++#define NT_STATUS_FILE_CORRUPT_ERROR 0xC0000000 | 0x0102
++#define NT_STATUS_NOT_A_DIRECTORY 0xC0000000 | 0x0103
++#define NT_STATUS_BAD_LOGON_SESSION_STATE 0xC0000000 | 0x0104
++#define NT_STATUS_LOGON_SESSION_COLLISION 0xC0000000 | 0x0105
++#define NT_STATUS_NAME_TOO_LONG 0xC0000000 | 0x0106
++#define NT_STATUS_FILES_OPEN 0xC0000000 | 0x0107
++#define NT_STATUS_CONNECTION_IN_USE 0xC0000000 | 0x0108
++#define NT_STATUS_MESSAGE_NOT_FOUND 0xC0000000 | 0x0109
++#define NT_STATUS_PROCESS_IS_TERMINATING 0xC0000000 | 0x010a
++#define NT_STATUS_INVALID_LOGON_TYPE 0xC0000000 | 0x010b
++#define NT_STATUS_NO_GUID_TRANSLATION 0xC0000000 | 0x010c
++#define NT_STATUS_CANNOT_IMPERSONATE 0xC0000000 | 0x010d
++#define NT_STATUS_IMAGE_ALREADY_LOADED 0xC0000000 | 0x010e
++#define NT_STATUS_ABIOS_NOT_PRESENT 0xC0000000 | 0x010f
++#define NT_STATUS_ABIOS_LID_NOT_EXIST 0xC0000000 | 0x0110
++#define NT_STATUS_ABIOS_LID_ALREADY_OWNED 0xC0000000 | 0x0111
++#define NT_STATUS_ABIOS_NOT_LID_OWNER 0xC0000000 | 0x0112
++#define NT_STATUS_ABIOS_INVALID_COMMAND 0xC0000000 | 0x0113
++#define NT_STATUS_ABIOS_INVALID_LID 0xC0000000 | 0x0114
++#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE 0xC0000000 | 0x0115
++#define NT_STATUS_ABIOS_INVALID_SELECTOR 0xC0000000 | 0x0116
++#define NT_STATUS_NO_LDT 0xC0000000 | 0x0117
++#define NT_STATUS_INVALID_LDT_SIZE 0xC0000000 | 0x0118
++#define NT_STATUS_INVALID_LDT_OFFSET 0xC0000000 | 0x0119
++#define NT_STATUS_INVALID_LDT_DESCRIPTOR 0xC0000000 | 0x011a
++#define NT_STATUS_INVALID_IMAGE_NE_FORMAT 0xC0000000 | 0x011b
++#define NT_STATUS_RXACT_INVALID_STATE 0xC0000000 | 0x011c
++#define NT_STATUS_RXACT_COMMIT_FAILURE 0xC0000000 | 0x011d
++#define NT_STATUS_MAPPED_FILE_SIZE_ZERO 0xC0000000 | 0x011e
++#define NT_STATUS_TOO_MANY_OPENED_FILES 0xC0000000 | 0x011f
++#define NT_STATUS_CANCELLED 0xC0000000 | 0x0120
++#define NT_STATUS_CANNOT_DELETE 0xC0000000 | 0x0121
++#define NT_STATUS_INVALID_COMPUTER_NAME 0xC0000000 | 0x0122
++#define NT_STATUS_FILE_DELETED 0xC0000000 | 0x0123
++#define NT_STATUS_SPECIAL_ACCOUNT 0xC0000000 | 0x0124
++#define NT_STATUS_SPECIAL_GROUP 0xC0000000 | 0x0125
++#define NT_STATUS_SPECIAL_USER 0xC0000000 | 0x0126
++#define NT_STATUS_MEMBERS_PRIMARY_GROUP 0xC0000000 | 0x0127
++#define NT_STATUS_FILE_CLOSED 0xC0000000 | 0x0128
++#define NT_STATUS_TOO_MANY_THREADS 0xC0000000 | 0x0129
++#define NT_STATUS_THREAD_NOT_IN_PROCESS 0xC0000000 | 0x012a
++#define NT_STATUS_TOKEN_ALREADY_IN_USE 0xC0000000 | 0x012b
++#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED 0xC0000000 | 0x012c
++#define NT_STATUS_COMMITMENT_LIMIT 0xC0000000 | 0x012d
++#define NT_STATUS_INVALID_IMAGE_LE_FORMAT 0xC0000000 | 0x012e
++#define NT_STATUS_INVALID_IMAGE_NOT_MZ 0xC0000000 | 0x012f
++#define NT_STATUS_INVALID_IMAGE_PROTECT 0xC0000000 | 0x0130
++#define NT_STATUS_INVALID_IMAGE_WIN_16 0xC0000000 | 0x0131
++#define NT_STATUS_LOGON_SERVER_CONFLICT 0xC0000000 | 0x0132
++#define NT_STATUS_TIME_DIFFERENCE_AT_DC 0xC0000000 | 0x0133
++#define NT_STATUS_SYNCHRONIZATION_REQUIRED 0xC0000000 | 0x0134
++#define NT_STATUS_DLL_NOT_FOUND 0xC0000000 | 0x0135
++#define NT_STATUS_OPEN_FAILED 0xC0000000 | 0x0136
++#define NT_STATUS_IO_PRIVILEGE_FAILED 0xC0000000 | 0x0137
++#define NT_STATUS_ORDINAL_NOT_FOUND 0xC0000000 | 0x0138
++#define NT_STATUS_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0139
++#define NT_STATUS_CONTROL_C_EXIT 0xC0000000 | 0x013a
++#define NT_STATUS_LOCAL_DISCONNECT 0xC0000000 | 0x013b
++#define NT_STATUS_REMOTE_DISCONNECT 0xC0000000 | 0x013c
++#define NT_STATUS_REMOTE_RESOURCES 0xC0000000 | 0x013d
++#define NT_STATUS_LINK_FAILED 0xC0000000 | 0x013e
++#define NT_STATUS_LINK_TIMEOUT 0xC0000000 | 0x013f
++#define NT_STATUS_INVALID_CONNECTION 0xC0000000 | 0x0140
++#define NT_STATUS_INVALID_ADDRESS 0xC0000000 | 0x0141
++#define NT_STATUS_DLL_INIT_FAILED 0xC0000000 | 0x0142
++#define NT_STATUS_MISSING_SYSTEMFILE 0xC0000000 | 0x0143
++#define NT_STATUS_UNHANDLED_EXCEPTION 0xC0000000 | 0x0144
++#define NT_STATUS_APP_INIT_FAILURE 0xC0000000 | 0x0145
++#define NT_STATUS_PAGEFILE_CREATE_FAILED 0xC0000000 | 0x0146
++#define NT_STATUS_NO_PAGEFILE 0xC0000000 | 0x0147
++#define NT_STATUS_INVALID_LEVEL 0xC0000000 | 0x0148
++#define NT_STATUS_WRONG_PASSWORD_CORE 0xC0000000 | 0x0149
++#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT 0xC0000000 | 0x014a
++#define NT_STATUS_PIPE_BROKEN 0xC0000000 | 0x014b
++#define NT_STATUS_REGISTRY_CORRUPT 0xC0000000 | 0x014c
++#define NT_STATUS_REGISTRY_IO_FAILED 0xC0000000 | 0x014d
++#define NT_STATUS_NO_EVENT_PAIR 0xC0000000 | 0x014e
++#define NT_STATUS_UNRECOGNIZED_VOLUME 0xC0000000 | 0x014f
++#define NT_STATUS_SERIAL_NO_DEVICE_INITED 0xC0000000 | 0x0150
++#define NT_STATUS_NO_SUCH_ALIAS 0xC0000000 | 0x0151
++#define NT_STATUS_MEMBER_NOT_IN_ALIAS 0xC0000000 | 0x0152
++#define NT_STATUS_MEMBER_IN_ALIAS 0xC0000000 | 0x0153
++#define NT_STATUS_ALIAS_EXISTS 0xC0000000 | 0x0154
++#define NT_STATUS_LOGON_NOT_GRANTED 0xC0000000 | 0x0155
++#define NT_STATUS_TOO_MANY_SECRETS 0xC0000000 | 0x0156
++#define NT_STATUS_SECRET_TOO_LONG 0xC0000000 | 0x0157
++#define NT_STATUS_INTERNAL_DB_ERROR 0xC0000000 | 0x0158
++#define NT_STATUS_FULLSCREEN_MODE 0xC0000000 | 0x0159
++#define NT_STATUS_TOO_MANY_CONTEXT_IDS 0xC0000000 | 0x015a
++#define NT_STATUS_LOGON_TYPE_NOT_GRANTED 0xC0000000 | 0x015b
++#define NT_STATUS_NOT_REGISTRY_FILE 0xC0000000 | 0x015c
++#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x015d
++#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR 0xC0000000 | 0x015e
++#define NT_STATUS_FT_MISSING_MEMBER 0xC0000000 | 0x015f
++#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY 0xC0000000 | 0x0160
++#define NT_STATUS_ILLEGAL_CHARACTER 0xC0000000 | 0x0161
++#define NT_STATUS_UNMAPPABLE_CHARACTER 0xC0000000 | 0x0162
++#define NT_STATUS_UNDEFINED_CHARACTER 0xC0000000 | 0x0163
++#define NT_STATUS_FLOPPY_VOLUME 0xC0000000 | 0x0164
++#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND 0xC0000000 | 0x0165
++#define NT_STATUS_FLOPPY_WRONG_CYLINDER 0xC0000000 | 0x0166
++#define NT_STATUS_FLOPPY_UNKNOWN_ERROR 0xC0000000 | 0x0167
++#define NT_STATUS_FLOPPY_BAD_REGISTERS 0xC0000000 | 0x0168
++#define NT_STATUS_DISK_RECALIBRATE_FAILED 0xC0000000 | 0x0169
++#define NT_STATUS_DISK_OPERATION_FAILED 0xC0000000 | 0x016a
++#define NT_STATUS_DISK_RESET_FAILED 0xC0000000 | 0x016b
++#define NT_STATUS_SHARED_IRQ_BUSY 0xC0000000 | 0x016c
++#define NT_STATUS_FT_ORPHANING 0xC0000000 | 0x016d
++#define NT_STATUS_PARTITION_FAILURE 0xC0000000 | 0x0172
++#define NT_STATUS_INVALID_BLOCK_LENGTH 0xC0000000 | 0x0173
++#define NT_STATUS_DEVICE_NOT_PARTITIONED 0xC0000000 | 0x0174
++#define NT_STATUS_UNABLE_TO_LOCK_MEDIA 0xC0000000 | 0x0175
++#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA 0xC0000000 | 0x0176
++#define NT_STATUS_EOM_OVERFLOW 0xC0000000 | 0x0177
++#define NT_STATUS_NO_MEDIA 0xC0000000 | 0x0178
++#define NT_STATUS_NO_SUCH_MEMBER 0xC0000000 | 0x017a
++#define NT_STATUS_INVALID_MEMBER 0xC0000000 | 0x017b
++#define NT_STATUS_KEY_DELETED 0xC0000000 | 0x017c
++#define NT_STATUS_NO_LOG_SPACE 0xC0000000 | 0x017d
++#define NT_STATUS_TOO_MANY_SIDS 0xC0000000 | 0x017e
++#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x017f
++#define NT_STATUS_KEY_HAS_CHILDREN 0xC0000000 | 0x0180
++#define NT_STATUS_CHILD_MUST_BE_VOLATILE 0xC0000000 | 0x0181
++#define NT_STATUS_DEVICE_CONFIGURATION_ERROR 0xC0000000 | 0x0182
++#define NT_STATUS_DRIVER_INTERNAL_ERROR 0xC0000000 | 0x0183
++#define NT_STATUS_INVALID_DEVICE_STATE 0xC0000000 | 0x0184
++#define NT_STATUS_IO_DEVICE_ERROR 0xC0000000 | 0x0185
++#define NT_STATUS_DEVICE_PROTOCOL_ERROR 0xC0000000 | 0x0186
++#define NT_STATUS_BACKUP_CONTROLLER 0xC0000000 | 0x0187
++#define NT_STATUS_LOG_FILE_FULL 0xC0000000 | 0x0188
++#define NT_STATUS_TOO_LATE 0xC0000000 | 0x0189
++#define NT_STATUS_NO_TRUST_LSA_SECRET 0xC0000000 | 0x018a
++#define NT_STATUS_NO_TRUST_SAM_ACCOUNT 0xC0000000 | 0x018b
++#define NT_STATUS_TRUSTED_DOMAIN_FAILURE 0xC0000000 | 0x018c
++#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE 0xC0000000 | 0x018d
++#define NT_STATUS_EVENTLOG_FILE_CORRUPT 0xC0000000 | 0x018e
++#define NT_STATUS_EVENTLOG_CANT_START 0xC0000000 | 0x018f
++#define NT_STATUS_TRUST_FAILURE 0xC0000000 | 0x0190
++#define NT_STATUS_MUTANT_LIMIT_EXCEEDED 0xC0000000 | 0x0191
++#define NT_STATUS_NETLOGON_NOT_STARTED 0xC0000000 | 0x0192
++#define NT_STATUS_ACCOUNT_EXPIRED 0xC0000000 | 0x0193
++#define NT_STATUS_POSSIBLE_DEADLOCK 0xC0000000 | 0x0194
++#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT 0xC0000000 | 0x0195
++#define NT_STATUS_REMOTE_SESSION_LIMIT 0xC0000000 | 0x0196
++#define NT_STATUS_EVENTLOG_FILE_CHANGED 0xC0000000 | 0x0197
++#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT 0xC0000000 | 0x0198
++#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT 0xC0000000 | 0x0199
++#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT 0xC0000000 | 0x019a
++#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT 0xC0000000 | 0x019b
++#define NT_STATUS_FS_DRIVER_REQUIRED 0xC0000000 | 0x019c
++#define NT_STATUS_NO_USER_SESSION_KEY 0xC0000000 | 0x0202
++#define NT_STATUS_USER_SESSION_DELETED 0xC0000000 | 0x0203
++#define NT_STATUS_RESOURCE_LANG_NOT_FOUND 0xC0000000 | 0x0204
++#define NT_STATUS_INSUFF_SERVER_RESOURCES 0xC0000000 | 0x0205
++#define NT_STATUS_INVALID_BUFFER_SIZE 0xC0000000 | 0x0206
++#define NT_STATUS_INVALID_ADDRESS_COMPONENT 0xC0000000 | 0x0207
++#define NT_STATUS_INVALID_ADDRESS_WILDCARD 0xC0000000 | 0x0208
++#define NT_STATUS_TOO_MANY_ADDRESSES 0xC0000000 | 0x0209
++#define NT_STATUS_ADDRESS_ALREADY_EXISTS 0xC0000000 | 0x020a
++#define NT_STATUS_ADDRESS_CLOSED 0xC0000000 | 0x020b
++#define NT_STATUS_CONNECTION_DISCONNECTED 0xC0000000 | 0x020c
++#define NT_STATUS_CONNECTION_RESET 0xC0000000 | 0x020d
++#define NT_STATUS_TOO_MANY_NODES 0xC0000000 | 0x020e
++#define NT_STATUS_TRANSACTION_ABORTED 0xC0000000 | 0x020f
++#define NT_STATUS_TRANSACTION_TIMED_OUT 0xC0000000 | 0x0210
++#define NT_STATUS_TRANSACTION_NO_RELEASE 0xC0000000 | 0x0211
++#define NT_STATUS_TRANSACTION_NO_MATCH 0xC0000000 | 0x0212
++#define NT_STATUS_TRANSACTION_RESPONDED 0xC0000000 | 0x0213
++#define NT_STATUS_TRANSACTION_INVALID_ID 0xC0000000 | 0x0214
++#define NT_STATUS_TRANSACTION_INVALID_TYPE 0xC0000000 | 0x0215
++#define NT_STATUS_NOT_SERVER_SESSION 0xC0000000 | 0x0216
++#define NT_STATUS_NOT_CLIENT_SESSION 0xC0000000 | 0x0217
++#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE 0xC0000000 | 0x0218
++#define NT_STATUS_DEBUG_ATTACH_FAILED 0xC0000000 | 0x0219
++#define NT_STATUS_SYSTEM_PROCESS_TERMINATED 0xC0000000 | 0x021a
++#define NT_STATUS_DATA_NOT_ACCEPTED 0xC0000000 | 0x021b
++#define NT_STATUS_NO_BROWSER_SERVERS_FOUND 0xC0000000 | 0x021c
++#define NT_STATUS_VDM_HARD_ERROR 0xC0000000 | 0x021d
++#define NT_STATUS_DRIVER_CANCEL_TIMEOUT 0xC0000000 | 0x021e
++#define NT_STATUS_REPLY_MESSAGE_MISMATCH 0xC0000000 | 0x021f
++#define NT_STATUS_MAPPED_ALIGNMENT 0xC0000000 | 0x0220
++#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH 0xC0000000 | 0x0221
++#define NT_STATUS_LOST_WRITEBEHIND_DATA 0xC0000000 | 0x0222
++#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID 0xC0000000 | 0x0223
++#define NT_STATUS_PASSWORD_MUST_CHANGE 0xC0000000 | 0x0224
++#define NT_STATUS_NOT_FOUND 0xC0000000 | 0x0225
++#define NT_STATUS_NOT_TINY_STREAM 0xC0000000 | 0x0226
++#define NT_STATUS_RECOVERY_FAILURE 0xC0000000 | 0x0227
++#define NT_STATUS_STACK_OVERFLOW_READ 0xC0000000 | 0x0228
++#define NT_STATUS_FAIL_CHECK 0xC0000000 | 0x0229
++#define NT_STATUS_DUPLICATE_OBJECTID 0xC0000000 | 0x022a
++#define NT_STATUS_OBJECTID_EXISTS 0xC0000000 | 0x022b
++#define NT_STATUS_CONVERT_TO_LARGE 0xC0000000 | 0x022c
++#define NT_STATUS_RETRY 0xC0000000 | 0x022d
++#define NT_STATUS_FOUND_OUT_OF_SCOPE 0xC0000000 | 0x022e
++#define NT_STATUS_ALLOCATE_BUCKET 0xC0000000 | 0x022f
++#define NT_STATUS_PROPSET_NOT_FOUND 0xC0000000 | 0x0230
++#define NT_STATUS_MARSHALL_OVERFLOW 0xC0000000 | 0x0231
++#define NT_STATUS_INVALID_VARIANT 0xC0000000 | 0x0232
++#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND 0xC0000000 | 0x0233
++#define NT_STATUS_ACCOUNT_LOCKED_OUT 0xC0000000 | 0x0234
++#define NT_STATUS_HANDLE_NOT_CLOSABLE 0xC0000000 | 0x0235
++#define NT_STATUS_CONNECTION_REFUSED 0xC0000000 | 0x0236
++#define NT_STATUS_GRACEFUL_DISCONNECT 0xC0000000 | 0x0237
++#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED 0xC0000000 | 0x0238
++#define NT_STATUS_ADDRESS_NOT_ASSOCIATED 0xC0000000 | 0x0239
++#define NT_STATUS_CONNECTION_INVALID 0xC0000000 | 0x023a
++#define NT_STATUS_CONNECTION_ACTIVE 0xC0000000 | 0x023b
++#define NT_STATUS_NETWORK_UNREACHABLE 0xC0000000 | 0x023c
++#define NT_STATUS_HOST_UNREACHABLE 0xC0000000 | 0x023d
++#define NT_STATUS_PROTOCOL_UNREACHABLE 0xC0000000 | 0x023e
++#define NT_STATUS_PORT_UNREACHABLE 0xC0000000 | 0x023f
++#define NT_STATUS_REQUEST_ABORTED 0xC0000000 | 0x0240
++#define NT_STATUS_CONNECTION_ABORTED 0xC0000000 | 0x0241
++#define NT_STATUS_BAD_COMPRESSION_BUFFER 0xC0000000 | 0x0242
++#define NT_STATUS_USER_MAPPED_FILE 0xC0000000 | 0x0243
++#define NT_STATUS_AUDIT_FAILED 0xC0000000 | 0x0244
++#define NT_STATUS_TIMER_RESOLUTION_NOT_SET 0xC0000000 | 0x0245
++#define NT_STATUS_CONNECTION_COUNT_LIMIT 0xC0000000 | 0x0246
++#define NT_STATUS_LOGIN_TIME_RESTRICTION 0xC0000000 | 0x0247
++#define NT_STATUS_LOGIN_WKSTA_RESTRICTION 0xC0000000 | 0x0248
++#define NT_STATUS_IMAGE_MP_UP_MISMATCH 0xC0000000 | 0x0249
++#define NT_STATUS_INSUFFICIENT_LOGON_INFO 0xC0000000 | 0x0250
++#define NT_STATUS_BAD_DLL_ENTRYPOINT 0xC0000000 | 0x0251
++#define NT_STATUS_BAD_SERVICE_ENTRYPOINT 0xC0000000 | 0x0252
++#define NT_STATUS_LPC_REPLY_LOST 0xC0000000 | 0x0253
++#define NT_STATUS_IP_ADDRESS_CONFLICT1 0xC0000000 | 0x0254
++#define NT_STATUS_IP_ADDRESS_CONFLICT2 0xC0000000 | 0x0255
++#define NT_STATUS_REGISTRY_QUOTA_LIMIT 0xC0000000 | 0x0256
++#define NT_STATUS_PATH_NOT_COVERED 0xC0000000 | 0x0257
++#define NT_STATUS_NO_CALLBACK_ACTIVE 0xC0000000 | 0x0258
++#define NT_STATUS_LICENSE_QUOTA_EXCEEDED 0xC0000000 | 0x0259
++#define NT_STATUS_PWD_TOO_SHORT 0xC0000000 | 0x025a
++#define NT_STATUS_PWD_TOO_RECENT 0xC0000000 | 0x025b
++#define NT_STATUS_PWD_HISTORY_CONFLICT 0xC0000000 | 0x025c
++#define NT_STATUS_PLUGPLAY_NO_DEVICE 0xC0000000 | 0x025e
++#define NT_STATUS_UNSUPPORTED_COMPRESSION 0xC0000000 | 0x025f
++#define NT_STATUS_INVALID_HW_PROFILE 0xC0000000 | 0x0260
++#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH 0xC0000000 | 0x0261
++#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND 0xC0000000 | 0x0262
++#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0263
++#define NT_STATUS_RESOURCE_NOT_OWNED 0xC0000000 | 0x0264
++#define NT_STATUS_TOO_MANY_LINKS 0xC0000000 | 0x0265
++#define NT_STATUS_QUOTA_LIST_INCONSISTENT 0xC0000000 | 0x0266
++#define NT_STATUS_FILE_IS_OFFLINE 0xC0000000 | 0x0267
++#define NT_STATUS_NO_SUCH_JOB 0xC0000000 | 0xEDE /* scheduler */
++
++#endif /* _NTERR_H */
+diff -urN linux-2.4.29.old/fs/cifs/ntlmssp.h linux-2.4.29/fs/cifs/ntlmssp.h
+--- linux-2.4.29.old/fs/cifs/ntlmssp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/ntlmssp.h 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,101 @@
++/*
++ * fs/cifs/ntlmssp.h
++ *
++ * Copyright (c) International Business Machines Corp., 2002
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#pragma pack(1)
++
++#define NTLMSSP_SIGNATURE "NTLMSSP"
++/* Message Types */
++#define NtLmNegotiate 1
++#define NtLmChallenge 2
++#define NtLmAuthenticate 3
++#define UnknownMessage 8
++
++/* Negotiate Flags */
++#define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode
++#define NTLMSSP_NEGOTIATE_OEM 0x02 // Text strings are in OEM
++#define NTLMSSP_REQUEST_TARGET 0x04 // Server return its auth realm
++#define NTLMSSP_NEGOTIATE_SIGN 0x0010 // Request signature capability
++#define NTLMSSP_NEGOTIATE_SEAL 0x0020 // Request confidentiality
++#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
++#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal
++#define NTLMSSP_NEGOTIATE_NTLM 0x0200 // NTLM authentication
++#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
++#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
++#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 // client/server on same machine
++#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 // Sign for all security levels
++#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
++#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
++#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
++#define NTLMSSP_NEGOTIATE_NTLMV2 0x80000
++#define NTLMSSP_REQUEST_INIT_RESP 0x100000
++#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000
++#define NTLMSSP_REQUEST_NOT_NT_KEY 0x400000
++#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
++#define NTLMSSP_NEGOTIATE_128 0x20000000
++#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
++#define NTLMSSP_NEGOTIATE_56 0x80000000
++
++/* Although typedefs are not commonly used for structure definitions */
++/* in the Linux kernel, in this particular case they are useful */
++/* to more closely match the standards document for NTLMSSP from */
++/* OpenGroup and to make the code more closely match the standard in */
++/* appearance */
++
++typedef struct _SECURITY_BUFFER {
++ __u16 Length;
++ __u16 MaximumLength;
++ __u32 Buffer; /* offset to buffer */
++} SECURITY_BUFFER;
++
++typedef struct _NEGOTIATE_MESSAGE {
++ __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
++ __u32 MessageType; /* 1 */
++ __u32 NegotiateFlags;
++ SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */
++ SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */
++ char DomainString[0];
++ /* followed by WorkstationString */
++} NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
++
++typedef struct _CHALLENGE_MESSAGE {
++ __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
++ __u32 MessageType; /* 2 */
++ SECURITY_BUFFER TargetName;
++ __u32 NegotiateFlags;
++ __u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
++ __u8 Reserved[8];
++ SECURITY_BUFFER TargetInfoArray;
++} CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
++
++typedef struct _AUTHENTICATE_MESSAGE {
++ __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
++ __u32 MessageType; /* 3 */
++ SECURITY_BUFFER LmChallengeResponse;
++ SECURITY_BUFFER NtChallengeResponse;
++ SECURITY_BUFFER DomainName;
++ SECURITY_BUFFER UserName;
++ SECURITY_BUFFER WorkstationName;
++ SECURITY_BUFFER SessionKey;
++ __u32 NegotiateFlags;
++ char UserString[0];
++} AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
++
++#pragma pack() /* resume default structure packing */
+diff -urN linux-2.4.29.old/fs/cifs/README linux-2.4.29/fs/cifs/README
+--- linux-2.4.29.old/fs/cifs/README 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/README 2004-07-14 00:25:04.000000000 +0200
+@@ -0,0 +1,356 @@
++The CIFS VFS support for Linux supports many advanced network filesystem
++features such as heirarchical dfs like namespace, hardlinks, locking and more.
++It was designed to comply with the SNIA CIFS Technical Reference (which
++supersedes the 1992 X/Open SMB Standard) as well as to perform best practice
++practical interoperability with Windows 2000, Windows XP, Samba and equivalent
++servers.
++
++For questions or bug reports please contact:
++ sfrench@samba.org (sfrench@us.ibm.com)
++
++Build instructions:
++==================
++For Linux 2.4:
++1) Get the kernel source (e.g.from http://www.kernel.org)
++and download the cifs vfs source (see the project page
++at http://us1.samba.org/samba/Linux_CIFS_client.html)
++and change directory into the top of the kernel directory
++then patch the kernel (e.g. "patch -p1 < cifs_24.patch")
++to add the cifs vfs to your kernel configure options if
++it has not already been added (e.g. current SuSE and UL
++users do not need to apply the cifs_24.patch since the cifs vfs is
++already in the kernel configure menu) and then
++mkdir linux/fs/cifs and then copy the current cifs vfs files from
++the cifs download to your kernel build directory e.g.
++
++ cp <cifs_download_dir>/fs/cifs/* to <kernel_download_dir>/fs/cifs
++
++2) make menuconfig (or make xconfig)
++3) select cifs from within the network filesystem choices
++4) save and exit
++5) make dep
++6) make modules (or "make" if CIFS VFS not to be built as a module)
++
++For Linux 2.5:
++1) Download the kernel (e.g. from http://www.kernel.org or from bitkeeper
++at bk://linux.bkbits.net/linux-2.5) and change directory into the top
++of the kernel directory tree (e.g. /usr/src/linux-2.5.73)
++2) make menuconfig (or make xconfig)
++3) select cifs from within the network filesystem choices
++4) save and exit
++5) make
++
++
++Installation instructions:
++=========================
++If you have built the CIFS vfs as module (successfully) simply
++type "make modules_install" (or if you prefer, manually copy the file to
++the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.o).
++
++If you have built the CIFS vfs into the kernel itself, follow the instructions
++for your distribution on how to install a new kernel (usually you
++would simply type "make install").
++
++If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on
++the CIFS VFS web site) copy it to the same directory in which mount.smbfs and
++similar files reside (usually /sbin). Although the helper software is not
++required, mount.cifs is recommended. Eventually the Samba 3.0 utility program
++"net" may also be helpful since it may someday provide easier mount syntax for
++users who are used to Windows e.g. net use <mount point> <UNC name or cifs URL>
++Note that running the Winbind pam/nss module (logon service) on all of your
++Linux clients is useful in mapping Uids and Gids consistently across the
++domain to the proper network user. The mount.cifs mount helper can be
++trivially built from Samba 3.0 or later source e.g. by executing:
++
++ gcc samba/source/client/mount.cifs.c -o mount.cifs
++
++Note that when the mount.cifs utility is run suid (allowing user mounts),
++in order to reduce risks, the "nosuid" mount flag is passed in on mount to
++disallow execution of an suid program mounted on the remote target.
++When mount is executed as root, nosuid is not passed in by default,
++and execution of suid programs on the remote target would be enabled
++by default. This can be changed, as with nfs and other filesystems,
++by simply specifying "nosuid" among the mount options. For user mounts
++though to be able to pass the suid flag to mount requires rebuilding
++mount.cifs with the following flag:
++
++ gcc samba/source/client/mount.cifs.c -DCIFS_ALLOW_USR_SUID -o mount.cifs
++
++There is a corresponding manual page for cifs mounting in the Samba 3.0 and
++later source tree in docs/manpages/mount.cifs.8
++
++Samba Considerations
++====================
++To get the maximum benefit from the CIFS VFS, we recommend using a server that
++supports the SNIA CIFS Unix Extensions standard (e.g. Samba 2.2.5 or later or
++Samba 3.0) but the CIFS vfs works fine with a wide variety of CIFS servers.
++Note that uid, gid and file permissions will display default values if you do
++not have a server that supports the Unix extensions for CIFS (such as Samba
++2.2.5 or later). To enable the Unix CIFS Extensions in the Samba server, add
++the line:
++
++ unix extensions = yes
++
++to your smb.conf file on the server. Note that the following smb.conf settings
++are also useful (on the Samba server) when the majority of clients are Unix or
++Linux:
++
++ case sensitive = yes
++ delete readonly = yes
++ ea support = yes
++
++Note that ea support is required for supporting Linux xattrs.
++Some administrators also change the "map archive" and the "create mask"
++parameters from their default values. Creating special devices (mknod)
++remotely may require specifying a mkdev function to Samba if you are not using
++Samba 3.0.5 or later. For more information on these see the manual pages
++("man smb.conf") on the Samba server system. Note that the cifs vfs,
++unlike the smbfs vfs, does not read the smb.conf on the client system
++(the few optional settings are passed in on mount via -o parameters instead).
++Note that Samba 2.2.7 or later includes a fix that allows the CIFS VFS to delete
++open files (required for strict POSIX compliance). Windows Servers already
++supported this feature. Samba server does not allow symlinks that refer to files
++outside of the share, so in Samba versions prior to 3.0.5, most symlinks to
++files with absolute paths (ie beginning with slash) such as:
++ ln -s /mnt/foo bar
++would be forbidden. Samba 3.0.5 server or later includes the ability to create
++such symlinks safely by converting unsafe symlinks (ie symlinks to server
++files that are outside of the share) to a samba specific format on the server
++that is ignored by local server applications and non-cifs clients and that will
++not be traversed by the Samba server). This is opaque to the Linux client
++application using the cifs vfs. Absolute symlinks will work to Samba 3.0.5 or
++later, but only for remote clients using the CIFS Unix extensions, and will
++be invisbile to Windows clients and typically will not affect local
++applications running on the same server as Samba.
++
++Use instructions:
++================
++Once the CIFS VFS support is built into the kernel or installed as a module
++(cifs.o), you can use mount syntax like the following to access Samba or Windows
++servers:
++
++ mount -t cifs //9.53.216.11/e$ /mnt -o user=myname,pass=mypassword
++
++Before -o the option -v may be specified to make the mount.cifs
++mount helper display the mount steps more verbosely.
++After -o the following commonly used cifs vfs specific options
++are supported:
++
++ user=<username>
++ pass=<password>
++ domain=<domain name>
++
++Other cifs mount options are described below. Use of TCP names (in addition to
++ip addresses) is available if the mount helper (mount.cifs) is installed. If
++you do not trust the server to which are mounted, or if you do not have
++cifs signing enabled (and the physical network is insecure), consider use
++of the standard mount options "noexec" and "nosuid" to reduce the risk of
++running an altered binary on your local system (downloaded from a hostile server
++or altered by a hostile router).
++
++When using the mount helper mount.cifs, passwords may be specified via alternate
++mechanisms, instead of specifying it after -o using the normal "pass=" syntax
++on the command line:
++1) By including it in a credential file. Specify credentials=filename as one
++of the mount options. Credential files contain two lines
++ username=someuser
++ password=your_password
++2) By specifying the password in the PASSWD environment variable (similarly
++the user name can be taken from the USER environment variable).
++3) By specifying the password in a file by name via PASSWD_FILE
++4) By specifying the password in a file by file descriptor via PASSWD_FD
++
++If no password is provided, mount.cifs will prompt for password entry
++
++Restrictions
++============
++Servers must support the NTLM SMB dialect (which is the most recent, supported
++by Samba and Windows NT version 4, 2000 and XP and many other SMB/CIFS servers)
++Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC
++1001/1002 support for "Netbios-Over-TCP/IP." Neither of these is likely to be a
++problem as most servers support this. IPv6 support is planned for the future.
++
++CIFS VFS Mount Options
++======================
++A partial list of the supported mount options follows:
++ user The user name to use when trying to establish
++ the CIFS session.
++ password The user password. If the mount helper is
++ installed, the user will be prompted for password
++ if it is not supplied.
++ ip The ip address of the target server
++ unc The target server Universal Network Name (export) to
++ mount.
++ domain Set the SMB/CIFS workgroup name prepended to the
++ username during CIFS session establishment
++ uid If CIFS Unix extensions are not supported by the server
++ this overrides the default uid for inodes. For mounts to
++ servers which do support the CIFS Unix extensions, such
++ as a properly configured Samba server, the server provides
++ the uid, gid and mode. For servers which do not support
++ the Unix extensions, the default uid (and gid) returned on
++ lookup of existing files is the uid (gid) of the person
++ who executed the mount (root, except when mount.cifs
++ is configured setuid for user mounts) unless the "uid="
++ (gid) mount option is specified. For the uid (gid) of newly
++ created files and directories, ie files created since
++ the last mount of the server share, the expected uid
++ (gid) is cached as as long as the inode remains in
++ memory on the client. Also note that permission
++ checks (authorization checks) on accesses to a file occur
++ at the server, but there are cases in which an administrator
++ may want to restrict at the client as well. For those
++ servers which do not report a uid/gid owner
++ (such as Windows), permissions can also be checked at the
++ client, and a crude form of client side permission checking
++ can be enabled by specifying file_mode and dir_mode on
++ the client
++ gid If CIFS Unix extensions are not supported by the server
++ this overrides the default gid for inodes.
++ file_mode If CIFS Unix extensions are not supported by the server
++ this overrides the default mode for file inodes.
++ dir_mode If CIFS Unix extensions are not supported by the server
++ this overrides the default mode for directory inodes.
++ port attempt to contact the server on this tcp port, before
++ trying the usual ports (port 445, then 139).
++ iocharset Codepage used to convert local path names to and from
++ Unicode. Unicode is used by default for network path
++ names if the server supports it. If iocharset is
++ not specified then the nls_default specified
++ during the local client kernel build will be used.
++ If server does not support Unicode, this parameter is
++ unused.
++ rsize default read size
++ wsize default write size
++ rw mount the network share read-write (note that the
++ server may still consider the share read-only)
++ ro mount network share read-only
++ version used to distinguish different versions of the
++ mount helper utility (not typically needed)
++ sep if first mount option (after the -o), overrides
++ the comma as the separator between the mount
++ parms. e.g.
++ -o user=myname,password=mypassword,domain=mydom
++ could be passed instead with period as the separator by
++ -o sep=.user=myname.password=mypassword.domain=mydom
++ this might be useful when comma is contained within username
++ or password or domain. This option is less important
++ when the cifs mount helper cifs.mount (version 1.1 or later)
++ is used.
++ nosuid Do not allow remote executables with the suid bit
++ program to be executed. This is only meaningful for mounts
++ to servers such as Samba which support the CIFS Unix Extensions.
++ If you do not trust the servers in your network (your mount
++ targets) it is recommended that you specify this option for
++ greater security.
++ suid Allow remote files on this mountpoint with suid enabled to
++ be executed (default for mounts when executed as root,
++ nosuid is default for user mounts).
++ credentials Although ignored by the cifs kernel component, it is used by
++ the mount helper, mount.cifs. When mount.cifs is installed it
++ opens and reads the credential file specified in order
++ to obtain the userid and password arguments which are passed to
++ the cifs vfs.
++ guest Although ignored by the kernel component, the mount.cifs
++ mount helper will not prompt the user for a password
++ if guest is specified on the mount options. If no
++ password is specified a null password will be used.
++
++The mount.cifs mount helper also accepts a few mount options before -o
++including:
++
++ -S take password from stdin (equivalent to setting the environment
++ variable "PASSWD_FD=0"
++ -V print mount.cifs version
++ -? display simple usage information
++
++With recent 2.6 kernel versions of modutils, the version of the cifs kernel
++module can be displayed via modinfo.
++
++Misc /proc/fs/cifs Flags and Debug Info
++=======================================
++Informational pseudo-files:
++DebugData Displays information about active CIFS sessions
++ and shares.
++Stats Lists summary resource usage information as well as per
++ share statistics, if CONFIG_CIFS_STATS in enabled
++ in the kernel configuration.
++
++Configuration pseudo-files:
++MultiuserMount If set to one, more than one CIFS session to
++ the same server ip address can be established
++ if more than one uid accesses the same mount
++ point and if the uids user/password mapping
++ information is available. (default is 0)
++PacketSigningEnabled If set to one, cifs packet signing is enabled
++ and will be used if the server requires
++ it. If set to two, cifs packet signing is
++ required even if the server considers packet
++ signing optional. (default 1)
++cifsFYI If set to one, additional debug information is
++ logged to the system error log. (default 0)
++ExtendedSecurity If set to one, SPNEGO session establishment
++ is allowed which enables more advanced
++ secure CIFS session establishment (default 0)
++NTLMV2Enabled If set to one, more secure password hashes
++ are used when the server supports them and
++ when kerberos is not negotiated (default 0)
++traceSMB If set to one, debug information is logged to the
++ system error log with the start of smb requests
++ and responses (default 0)
++LookupCacheEnable If set to one, inode information is kept cached
++ for one second improving performance of lookups
++ (default 1)
++OplockEnabled If set to one, safe distributed caching enabled.
++ (default 1)
++LinuxExtensionsEnabled If set to one then the client will attempt to
++ use the CIFS "UNIX" extensions which are optional
++ protocol enhancements that allow CIFS servers
++ to return accurate UID/GID information as well
++ as support symbolic links. If you use servers
++ such as Samba that support the CIFS Unix
++ extensions but do not want to use symbolic link
++ support and want to map the uid and gid fields
++ to values supplied at mount (rather than the
++ actual values, then set this to zero. (default 1)
++
++These experimental features and tracing can be enabled by changing flags in
++/proc/fs/cifs (after the cifs module has been installed or built into the
++kernel, e.g. insmod cifs). To enable a feature set it to 1 e.g. to enable
++tracing to the kernel message log type:
++
++ echo 1 > /proc/fs/cifs/cifsFYI
++
++and for more extensive tracing including the start of smb requests and responses
++
++ echo 1 > /proc/fs/cifs/traceSMB
++
++Three other experimental features are under development and to test
++require enabling an ifdef (e.g. by adding "#define CIFS_FCNTL" in cifsglob.h)
++
++ CONFIG_CIFS_QUOTA
++
++ CONFIG_CIFS_XATTR
++
++ CONFIG_CIFS_FCNTL (fcntl needed for support of directory change
++ notification and perhaps later for file leases)
++
++Per share (per client mount) statistics are available in /proc/fs/cifs/DebugData
++if the kernel was configured with cifs statistics enabled. The statistics
++represent the number of successful (ie non-zero return code from the server)
++SMB responses to some of the more common commands (open, delete, mkdir etc.).
++Also recorded is the total bytes read and bytes written to the server for
++that share. Note that due to client caching effects this can be less than the
++number of bytes read and written by the application running on the client.
++The statistics for the number of total SMBs and oplock breaks are different in
++that they represent all for that share, not just those for which the server
++returned success.
++
++Also note that "cat /proc/fs/cifs/DebugData" will display information about
++the active sessions and the shares that are mounted. Note: NTLMv2 enablement
++will not work since they its implementation is not quite complete yet.
++Do not alter these configuration values unless you are doing specific testing.
++Enabling extended security works to Windows 2000 Workstations and XP but not to
++Windows 2000 server or Samba since it does not usually send "raw NTLMSSP"
++(instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not
++complete in the CIFS VFS yet).
+diff -urN linux-2.4.29.old/fs/cifs/rfc1002pdu.h linux-2.4.29/fs/cifs/rfc1002pdu.h
+--- linux-2.4.29.old/fs/cifs/rfc1002pdu.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/rfc1002pdu.h 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,79 @@
++/*
++ * fs/cifs/rfc1002pdu.h
++ *
++ * Protocol Data Unit definitions for RFC 1001/1002 support
++ *
++ * Copyright (c) International Business Machines Corp., 2004
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#pragma pack(1)
++
++/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
++
++ /* RFC 1002 session packet types */
++#define RFC1002_SESSION_MESASAGE 0x00
++#define RFC1002_SESSION_REQUEST 0x81
++#define RFC1002_POSITIVE_SESSION_RESPONSE 0x82
++#define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83
++#define RFC1002_RETARGET_SESSION_RESPONSE 0x83
++#define RFC1002_SESSION_KEEP_ALIVE 0x85
++
++ /* RFC 1002 flags (only one defined */
++#define RFC1002_LENGTH_EXTEND 0x80 /* high order bit of length (ie +64K) */
++
++struct rfc1002_session_packet {
++ __u8 type;
++ __u8 flags;
++ __u16 length;
++ union {
++ struct {
++ __u8 called_len;
++ __u8 called_name[32];
++ __u8 scope1; /* null */
++ __u8 calling_len;
++ __u8 calling_name[32];
++ __u8 scope2; /* null */
++ } session_req;
++ struct {
++ __u32 retarget_ip_addr;
++ __u16 port;
++ } retarget_resp;
++ __u8 neg_ses_resp_error_code;
++ /* POSITIVE_SESSION_RESPONSE packet does not include trailer.
++ SESSION_KEEP_ALIVE packet also does not include a trailer.
++ Trailer for the SESSION_MESSAGE packet is SMB/CIFS header */
++ } trailer;
++};
++
++/* Negative Session Response error codes */
++#define RFC1002_NOT_LISTENING_CALLED 0x80 /* not listening on called name */
++#define RFC1002_NOT_LISTENING_CALLING 0x81 /* not listening on calling name */
++#define RFC1002_NOT_PRESENT 0x82 /* called name not present */
++#define RFC1002_INSUFFICIENT_RESOURCE 0x83
++#define RFC1002_UNSPECIFIED_ERROR 0x8F
++
++/* RFC 1002 Datagram service packets are not defined here as they
++are not needed for the network filesystem client unless we plan on
++implementing broadcast resolution of the server ip address (from
++server netbios name). Currently server names are resolved only via DNS
++(tcp name) or ip address or an /etc/hosts equivalent mapping to ip address.*/
++
++#define DEFAULT_CIFS_CALLED_NAME "*SMBSERVER "
++
++#pragma pack() /* resume default structure packing */
++
+diff -urN linux-2.4.29.old/fs/cifs/smbdes.c linux-2.4.29/fs/cifs/smbdes.c
+--- linux-2.4.29.old/fs/cifs/smbdes.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/smbdes.c 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,408 @@
++/*
++ Unix SMB/Netbios implementation.
++ Version 1.9.
++
++ a partial implementation of DES designed for use in the
++ SMB authentication protocol
++
++ Copyright (C) Andrew Tridgell 1998
++ Modified by Steve French (sfrench@us.ibm.com) 2002,2004
++
++ 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.
++*/
++
++/* NOTES:
++
++ This code makes no attempt to be fast! In fact, it is a very
++ slow implementation
++
++ This code is NOT a complete DES implementation. It implements only
++ the minimum necessary for SMB authentication, as used by all SMB
++ products (including every copy of Microsoft Windows95 ever sold)
++
++ In particular, it can only do a unchained forward DES pass. This
++ means it is not possible to use this code for encryption/decryption
++ of data, instead it is only useful as a "hash" algorithm.
++
++ There is no entry point into this code that allows normal DES operation.
++
++ I believe this means that this code does not come under ITAR
++ regulations but this is NOT a legal opinion. If you are concerned
++ about the applicability of ITAR regulations to this code then you
++ should confirm it for yourself (and maybe let me know if you come
++ up with a different answer to the one above)
++*/
++#include <linux/slab.h>
++#define uchar unsigned char
++
++static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
++ 1, 58, 50, 42, 34, 26, 18,
++ 10, 2, 59, 51, 43, 35, 27,
++ 19, 11, 3, 60, 52, 44, 36,
++ 63, 55, 47, 39, 31, 23, 15,
++ 7, 62, 54, 46, 38, 30, 22,
++ 14, 6, 61, 53, 45, 37, 29,
++ 21, 13, 5, 28, 20, 12, 4
++};
++
++static uchar perm2[48] = { 14, 17, 11, 24, 1, 5,
++ 3, 28, 15, 6, 21, 10,
++ 23, 19, 12, 4, 26, 8,
++ 16, 7, 27, 20, 13, 2,
++ 41, 52, 31, 37, 47, 55,
++ 30, 40, 51, 45, 33, 48,
++ 44, 49, 39, 56, 34, 53,
++ 46, 42, 50, 36, 29, 32
++};
++
++static uchar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2,
++ 60, 52, 44, 36, 28, 20, 12, 4,
++ 62, 54, 46, 38, 30, 22, 14, 6,
++ 64, 56, 48, 40, 32, 24, 16, 8,
++ 57, 49, 41, 33, 25, 17, 9, 1,
++ 59, 51, 43, 35, 27, 19, 11, 3,
++ 61, 53, 45, 37, 29, 21, 13, 5,
++ 63, 55, 47, 39, 31, 23, 15, 7
++};
++
++static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
++ 4, 5, 6, 7, 8, 9,
++ 8, 9, 10, 11, 12, 13,
++ 12, 13, 14, 15, 16, 17,
++ 16, 17, 18, 19, 20, 21,
++ 20, 21, 22, 23, 24, 25,
++ 24, 25, 26, 27, 28, 29,
++ 28, 29, 30, 31, 32, 1
++};
++
++static uchar perm5[32] = { 16, 7, 20, 21,
++ 29, 12, 28, 17,
++ 1, 15, 23, 26,
++ 5, 18, 31, 10,
++ 2, 8, 24, 14,
++ 32, 27, 3, 9,
++ 19, 13, 30, 6,
++ 22, 11, 4, 25
++};
++
++static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
++ 39, 7, 47, 15, 55, 23, 63, 31,
++ 38, 6, 46, 14, 54, 22, 62, 30,
++ 37, 5, 45, 13, 53, 21, 61, 29,
++ 36, 4, 44, 12, 52, 20, 60, 28,
++ 35, 3, 43, 11, 51, 19, 59, 27,
++ 34, 2, 42, 10, 50, 18, 58, 26,
++ 33, 1, 41, 9, 49, 17, 57, 25
++};
++
++static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
++
++static uchar sbox[8][4][16] = {
++ {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
++ {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
++ {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
++ {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
++
++ {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
++ {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
++ {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
++ {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
++
++ {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
++ {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
++ {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
++ {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
++
++ {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
++ {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
++ {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
++ {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
++
++ {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
++ {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
++ {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
++ {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
++
++ {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
++ {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
++ {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
++ {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
++
++ {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
++ {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
++ {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
++ {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
++
++ {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
++ {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
++ {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
++ {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
++};
++
++static void
++permute(char *out, char *in, uchar * p, int n)
++{
++ int i;
++ for (i = 0; i < n; i++)
++ out[i] = in[p[i] - 1];
++}
++
++static void
++lshift(char *d, int count, int n)
++{
++ char out[64];
++ int i;
++ for (i = 0; i < n; i++)
++ out[i] = d[(i + count) % n];
++ for (i = 0; i < n; i++)
++ d[i] = out[i];
++}
++
++static void
++concat(char *out, char *in1, char *in2, int l1, int l2)
++{
++ while (l1--)
++ *out++ = *in1++;
++ while (l2--)
++ *out++ = *in2++;
++}
++
++static void
++xor(char *out, char *in1, char *in2, int n)
++{
++ int i;
++ for (i = 0; i < n; i++)
++ out[i] = in1[i] ^ in2[i];
++}
++
++static void
++dohash(char *out, char *in, char *key, int forw)
++{
++ int i, j, k;
++ char *pk1;
++ char c[28];
++ char d[28];
++ char *cd;
++ char ki[16][48];
++ char *pd1;
++ char l[32], r[32];
++ char *rl;
++
++ /* Have to reduce stack usage */
++ pk1 = kmalloc(56+56+64+64,GFP_KERNEL);
++ if(pk1 == NULL)
++ return;
++
++ cd = pk1 + 56;
++ pd1= cd + 56;
++ rl = pd1 + 64;
++
++ permute(pk1, key, perm1, 56);
++
++ for (i = 0; i < 28; i++)
++ c[i] = pk1[i];
++ for (i = 0; i < 28; i++)
++ d[i] = pk1[i + 28];
++
++ for (i = 0; i < 16; i++) {
++ lshift(c, sc[i], 28);
++ lshift(d, sc[i], 28);
++
++ concat(cd, c, d, 28, 28);
++ permute(ki[i], cd, perm2, 48);
++ }
++
++ permute(pd1, in, perm3, 64);
++
++ for (j = 0; j < 32; j++) {
++ l[j] = pd1[j];
++ r[j] = pd1[j + 32];
++ }
++
++ for (i = 0; i < 16; i++) {
++ char *er; /* er[48] */
++ char *erk; /* erk[48] */
++ char b[8][6];
++ char *cb; /* cb[32] */
++ char *pcb; /* pcb[32] */
++ char *r2; /* r2[32] */
++
++ er = kmalloc(48+48+32+32+32, GFP_KERNEL);
++ if(er == NULL) {
++ kfree(pk1);
++ return;
++ }
++ erk = er+48;
++ cb = erk+48;
++ pcb = cb+32;
++ r2 = pcb+32;
++
++ permute(er, r, perm4, 48);
++
++ xor(erk, er, ki[forw ? i : 15 - i], 48);
++
++ for (j = 0; j < 8; j++)
++ for (k = 0; k < 6; k++)
++ b[j][k] = erk[j * 6 + k];
++
++ for (j = 0; j < 8; j++) {
++ int m, n;
++ m = (b[j][0] << 1) | b[j][5];
++
++ n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] <<
++ 1) | b[j][4];
++
++ for (k = 0; k < 4; k++)
++ b[j][k] =
++ (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
++ }
++
++ for (j = 0; j < 8; j++)
++ for (k = 0; k < 4; k++)
++ cb[j * 4 + k] = b[j][k];
++ permute(pcb, cb, perm5, 32);
++
++ xor(r2, l, pcb, 32);
++
++ for (j = 0; j < 32; j++)
++ l[j] = r[j];
++
++ for (j = 0; j < 32; j++)
++ r[j] = r2[j];
++
++ kfree(er);
++ }
++
++ concat(rl, r, l, 32, 32);
++
++ permute(out, rl, perm6, 64);
++ kfree(pk1);
++}
++
++static void
++str_to_key(unsigned char *str, unsigned char *key)
++{
++ int i;
++
++ key[0] = str[0] >> 1;
++ key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
++ key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
++ key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
++ key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
++ key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
++ key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
++ key[7] = str[6] & 0x7F;
++ for (i = 0; i < 8; i++) {
++ key[i] = (key[i] << 1);
++ }
++}
++
++static void
++smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
++{
++ int i;
++ char *outb; /* outb[64] */
++ char *inb; /* inb[64] */
++ char *keyb; /* keyb[64] */
++ unsigned char key2[8];
++
++ outb = kmalloc(64 * 3,GFP_KERNEL);
++ if(outb == NULL)
++ return;
++
++ inb = outb + 64;
++ keyb = inb + 64;
++
++ str_to_key(key, key2);
++
++ for (i = 0; i < 64; i++) {
++ inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
++ keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
++ outb[i] = 0;
++ }
++
++ dohash(outb, inb, keyb, forw);
++
++ for (i = 0; i < 8; i++) {
++ out[i] = 0;
++ }
++
++ for (i = 0; i < 64; i++) {
++ if (outb[i])
++ out[i / 8] |= (1 << (7 - (i % 8)));
++ }
++ kfree(outb);
++}
++
++void
++E_P16(unsigned char *p14, unsigned char *p16)
++{
++ unsigned char sp8[8] =
++ { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
++ smbhash(p16, sp8, p14, 1);
++ smbhash(p16 + 8, sp8, p14 + 7, 1);
++}
++
++void
++E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
++{
++ smbhash(p24, c8, p21, 1);
++ smbhash(p24 + 8, c8, p21 + 7, 1);
++ smbhash(p24 + 16, c8, p21 + 14, 1);
++}
++
++void
++D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
++{
++ smbhash(out, in, p14, 0);
++ smbhash(out + 8, in + 8, p14 + 7, 0);
++}
++
++void
++E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out)
++{
++ smbhash(out, in, p14, 1);
++ smbhash(out + 8, in + 8, p14 + 7, 1);
++}
++
++void
++cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key)
++{
++ unsigned char buf[8];
++
++ smbhash(buf, in, key, 1);
++ smbhash(out, buf, key + 9, 1);
++}
++
++void
++cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key)
++{
++ unsigned char buf[8];
++ static unsigned char key2[8];
++
++ smbhash(buf, in, key, 1);
++ key2[0] = key[7];
++ smbhash(out, buf, key2, 1);
++}
++
++void
++cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
++{
++ static unsigned char key2[8];
++
++ smbhash(out, in, key, forw);
++ key2[0] = key[7];
++ smbhash(out + 8, in + 8, key2, forw);
++}
+diff -urN linux-2.4.29.old/fs/cifs/smbencrypt.c linux-2.4.29/fs/cifs/smbencrypt.c
+--- linux-2.4.29.old/fs/cifs/smbencrypt.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/smbencrypt.c 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,295 @@
++/*
++ Unix SMB/Netbios implementation.
++ Version 1.9.
++ SMB parameters and setup
++ Copyright (C) Andrew Tridgell 1992-2000
++ Copyright (C) Luke Kenneth Casson Leighton 1996-2000
++ Modified by Jeremy Allison 1995.
++ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
++ Modified by Steve French (sfrench@us.ibm.com) 2002-2003
++
++ 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 <linux/module.h>
++#include <linux/fs.h>
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/random.h>
++#include "cifs_unicode.h"
++#include "cifspdu.h"
++#include "md5.h"
++#include "cifs_debug.h"
++
++#ifndef FALSE
++#define FALSE 0
++#endif
++#ifndef TRUE
++#define TRUE 1
++#endif
++
++/* following came from the other byteorder.h to avoid include conflicts */
++#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
++#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
++#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val)))
++
++/*The following definitions come from lib/md4.c */
++
++void mdfour(unsigned char *out, unsigned char *in, int n);
++
++/*The following definitions come from libsmb/smbdes.c */
++
++void E_P16(unsigned char *p14, unsigned char *p16);
++void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24);
++void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out);
++void E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out);
++void cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key);
++void cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key);
++void cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key,
++ int forw);
++
++/*The following definitions come from libsmb/smbencrypt.c */
++
++void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
++void E_md4hash(const unsigned char *passwd, unsigned char *p16);
++void nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]);
++void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
++ unsigned char p24[24]);
++void NTLMSSPOWFencrypt(unsigned char passwd[8],
++ unsigned char *ntlmchalresp, unsigned char p24[24]);
++void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
++int decode_pw_buffer(char in_buffer[516], char *new_pwrd,
++ int new_pwrd_size, __u32 * new_pw_len);
++
++/*
++ This implements the X/Open SMB password encryption
++ It takes a password, a 8 byte "crypt key" and puts 24 bytes of
++ encrypted password into p24 */
++/* Note that password must be uppercased and null terminated */
++void
++SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
++{
++ unsigned char p14[15], p21[21];
++
++ memset(p21, '\0', 21);
++ memset(p14, '\0', 14);
++ strncpy((char *) p14, (char *) passwd, 14);
++
++/* strupper((char *)p14); *//* BB at least uppercase the easy range */
++ E_P16(p14, p21);
++
++ SMBOWFencrypt(p21, c8, p24);
++
++ memset(p14,0,15);
++ memset(p21,0,21);
++}
++
++/* Routines for Windows NT MD4 Hash functions. */
++static int
++_my_wcslen(__u16 * str)
++{
++ int len = 0;
++ while (*str++ != 0)
++ len++;
++ return len;
++}
++
++/*
++ * Convert a string into an NT UNICODE string.
++ * Note that regardless of processor type
++ * this must be in intel (little-endian)
++ * format.
++ */
++
++static int
++_my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
++{ /* not a very good conversion routine - change/fix */
++ int i;
++ __u16 val;
++
++ for (i = 0; i < len; i++) {
++ val = *src;
++ SSVAL(dst, 0, val);
++ dst++;
++ src++;
++ if (val == 0)
++ break;
++ }
++ return i;
++}
++
++/*
++ * Creates the MD4 Hash of the users password in NT UNICODE.
++ */
++
++void
++E_md4hash(const unsigned char *passwd, unsigned char *p16)
++{
++ int len;
++ __u16 wpwd[129];
++
++ /* Password cannot be longer than 128 characters */
++ if(passwd) {
++ len = strlen((char *) passwd);
++ if (len > 128) {
++ len = 128;
++ }
++ /* Password must be converted to NT unicode */
++ _my_mbstowcs(wpwd, passwd, len);
++ } else
++ len = 0;
++
++ wpwd[len] = 0; /* Ensure string is null terminated */
++ /* Calculate length in bytes */
++ len = _my_wcslen(wpwd) * sizeof (__u16);
++
++ mdfour(p16, (unsigned char *) wpwd, len);
++ memset(wpwd,0,129 * 2);
++}
++
++/* Does both the NT and LM owfs of a user's password */
++void
++nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16])
++{
++ char passwd[514];
++
++ memset(passwd, '\0', 514);
++ if (strlen(pwd) < 513)
++ strcpy(passwd, pwd);
++ else
++ memcpy(passwd, pwd, 512);
++ /* Calculate the MD4 hash (NT compatible) of the password */
++ memset(nt_p16, '\0', 16);
++ E_md4hash(passwd, nt_p16);
++
++ /* Mangle the passwords into Lanman format */
++ passwd[14] = '\0';
++/* strupper(passwd); */
++
++ /* Calculate the SMB (lanman) hash functions of the password */
++
++ memset(p16, '\0', 16);
++ E_P16((unsigned char *) passwd, (unsigned char *) p16);
++
++ /* clear out local copy of user's password (just being paranoid). */
++ memset(passwd, '\0', sizeof (passwd));
++}
++
++/* Does the NTLMv2 owfs of a user's password */
++void
++ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
++ const char *domain_n, unsigned char kr_buf[16],
++ const struct nls_table *nls_codepage)
++{
++ wchar_t * user_u;
++ wchar_t * dom_u;
++ int user_l, domain_l;
++ struct HMACMD5Context ctx;
++
++ /* might as well do one alloc to hold both (user_u and dom_u) */
++ user_u = kmalloc(2048 * sizeof(wchar_t),GFP_KERNEL);
++ if(user_u == NULL)
++ return;
++ dom_u = user_u + 1024;
++
++ /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
++ push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
++
++ /* BB user and domain may need to be uppercased */
++ user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage);
++ domain_l = cifs_strtoUCS(dom_u, domain_n, 511, nls_codepage);
++
++ user_l++; /* trailing null */
++ domain_l++;
++
++ hmac_md5_init_limK_to_64(owf, 16, &ctx);
++ hmac_md5_update((const unsigned char *) user_u, user_l * 2, &ctx);
++ hmac_md5_update((const unsigned char *) dom_u, domain_l * 2, &ctx);
++ hmac_md5_final(kr_buf, &ctx);
++
++ kfree(user_u);
++}
++
++/* Does the des encryption from the NT or LM MD4 hash. */
++void
++SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
++ unsigned char p24[24])
++{
++ unsigned char p21[21];
++
++ memset(p21, '\0', 21);
++
++ memcpy(p21, passwd, 16);
++ E_P24(p21, c8, p24);
++}
++
++/* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
++void
++NTLMSSPOWFencrypt(unsigned char passwd[8],
++ unsigned char *ntlmchalresp, unsigned char p24[24])
++{
++ unsigned char p21[21];
++
++ memset(p21, '\0', 21);
++ memcpy(p21, passwd, 8);
++ memset(p21 + 8, 0xbd, 8);
++
++ E_P24(p21, ntlmchalresp, p24);
++}
++
++/* Does the NT MD4 hash then des encryption. */
++
++void
++SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
++{
++ unsigned char p21[21];
++
++ memset(p21, '\0', 21);
++
++ E_md4hash(passwd, p21);
++ SMBOWFencrypt(p21, c8, p24);
++}
++
++/* Does the md5 encryption from the NT hash for NTLMv2. */
++void
++SMBOWFencrypt_ntv2(const unsigned char kr[16],
++ const struct data_blob * srv_chal,
++ const struct data_blob * cli_chal, unsigned char resp_buf[16])
++{
++ struct HMACMD5Context ctx;
++
++ hmac_md5_init_limK_to_64(kr, 16, &ctx);
++ hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
++ hmac_md5_update(cli_chal->data, cli_chal->length, &ctx);
++ hmac_md5_final(resp_buf, &ctx);
++}
++
++void
++SMBsesskeygen_ntv2(const unsigned char kr[16],
++ const unsigned char *nt_resp, __u8 sess_key[16])
++{
++ struct HMACMD5Context ctx;
++
++ hmac_md5_init_limK_to_64(kr, 16, &ctx);
++ hmac_md5_update(nt_resp, 16, &ctx);
++ hmac_md5_final((unsigned char *) sess_key, &ctx);
++}
++
++void
++SMBsesskeygen_ntv1(const unsigned char kr[16],
++ const unsigned char *nt_resp, __u8 sess_key[16])
++{
++ mdfour((unsigned char *) sess_key, (unsigned char *) kr, 16);
++}
+diff -urN linux-2.4.29.old/fs/cifs/smberr.c linux-2.4.29/fs/cifs/smberr.c
+--- linux-2.4.29.old/fs/cifs/smberr.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/smberr.c 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,240 @@
++/*
++ Unix SMB/Netbios implementation.
++ Version 1.9.
++ Copyright (C) Andrew Tridgell 1998
++ Copyright (C) Steve French (sfrench@us.ibm.com) 2002
++ 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 "smberr.h"
++#define NO_SYSLOG
++/* error code stuff - put together by Merik Karman
++ merik@blackadder.dsh.oz.au */
++ typedef const struct {
++ char *name;
++ int code;
++ char *message;
++ int posix_code;
++} err_code_struct;
++
++/* Dos Error Messages */
++err_code_struct dos_msgs[] = {
++ {"ERRbadfunc", ERRbadfunc, "Invalid function.", -EINVAL},
++ {"ERRbadfile", ERRbadfile, "File not found.", -ENOENT},
++ {"ERRbadpath", ERRbadpath, "Directory invalid.", -ENOENT},
++ {"ERRnofids", ERRnofids, "No file descriptors available", -EMFILE},
++ {"ERRnoaccess", ERRnoaccess, "Access denied.", -EACCES},
++ {"ERRbadfid", ERRbadfid, "Invalid file handle.", -EBADF},
++ {"ERRbadmcb", 7, "Memory control blocks destroyed.", -EIO},
++ {"ERRnomem", ERRnomem,
++ "Insufficient server memory to perform the requested function.",
++ -ENOMEM},
++ {"ERRbadmem", ERRbadmem, "Invalid memory block address.", -EFAULT},
++ {"ERRbadenv", ERRbadenv, "Invalid environment.", -EFAULT},
++ {"ERRbadformat", 11, "Invalid format.", -EINVAL},
++ {"ERRbadaccess", ERRbadaccess, "Invalid open mode." - EACCES},
++ {"ERRbaddata", ERRbaddata, "Invalid data.", -EIO},
++ {"ERR", ERRres, "reserved.", -EIO},
++ {"ERRbaddrive", ERRbaddrive, "Invalid drive specified.", -ENXIO},
++ {"ERRremcd", ERRremcd,
++ "A Delete Directory request attempted to remove the server's current directory.",
++ -EIO},
++ {"ERRdiffdevice", ERRdiffdevice, "Not same device.", -EXDEV},
++ {"ERRnofiles", ERRnofiles, "A File Search command can find no more files matching the specified criteria.", -ENOENT}, /* Note: must map to zero manually in some places such as readdir */
++ {"ERRbadshare", ERRbadshare,
++ "The sharing mode specified for an Open conflicts with existing FIDs on the file.",
++ -EXTBSY},
++ {"ERRlock", ERRlock,
++ "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process.",
++ -EACCES},
++ {"ERRunsup", ERRunsup, "The operation is unsupported", -EINVAL},
++ {"ERRnosuchshare", ERRnosuchshare,
++ "You specified an invalid share name", -ENXIO},
++ {"ERRfilexists", ERRfilexists,
++ "The file named in a Create Directory, Make New File or Link request already exists.",
++ -EEXIST},
++ {"ERRinvalidname", ERRinvalidname, "Invalid name", -ENOENT},
++ {"ERRdiskfull", ERRdiskfull, "Disk full", -ENOSPC}
++
++ {"ERRmoredata", ERRmoredata,
++ "There is more data to be returned.",},
++ {"ERRinvgroup", 2455, "Invalid workgroup (try the -W option)"},
++ {NULL, -1, NULL, -EIO}
++};
++
++/* Server Error Messages */
++err_code_struct server_msgs[] = {
++ {"ERRerror", 1, "Non-specific error code."},
++ {"ERRbadpw", 2,
++ "Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
++ {"ERRbadtype", 3, "reserved."},
++ {"ERRaccess", 4,
++ "The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."},
++ {"ERRinvnid", 5,
++ "The tree ID (TID) specified in a command was invalid."},
++ {"ERRinvnetname", 6, "Invalid network name in tree connect."},
++ {"ERRinvdevice", 7,
++ "Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
++ {"ERRqfull", 49,
++ "Print queue full (files) -- returned by open print file."},
++ {"ERRqtoobig", 50, "Print queue full -- no space."},
++ {"ERRqeof", 51, "EOF on print queue dump."},
++ {"ERRinvpfid", 52, "Invalid print file FID."},
++ {"ERRsmbcmd", 64,
++ "The server did not recognize the command received."},
++ {"ERRsrverror", 65,
++ "The server encountered an internal error, e.g., system file unavailable."},
++ {"ERRfilespecs", 67,
++ "The file handle (FID) and pathname parameters contained an invalid combination of values."},
++ {"ERRreserved", 68, "reserved."},
++ {"ERRbadpermits", 69,
++ "The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
++ {"ERRreserved", 70, "reserved."},
++ {"ERRsetattrmode", 71,
++ "The attribute mode in the Set File Attribute request is invalid."},
++ {"ERRpaused", 81, "Server is paused."},
++ {"ERRmsgoff", 82, "Not receiving messages."},
++ {"ERRnoroom", 83, "No room to buffer message."},
++ {"ERRrmuns", 87, "Too many remote user names."},
++ {"ERRtimeout", 88, "Operation timed out."},
++ {"ERRnoresource", 89,
++ "No resources currently available for request."},
++ {"ERRtoomanyuids", 90, "Too many UIDs active on this session."},
++ {"ERRbaduid", 91,
++ "The UID is not known as a valid ID on this session."},
++ {"ERRusempx", 250, "Temp unable to support Raw, use MPX mode."},
++ {"ERRusestd", 251,
++ "Temp unable to support Raw, use standard read/write."},
++ {"ERRcontmpx", 252, "Continue in MPX mode."},
++ {"ERRreserved", 253, "reserved."},
++ {"ERRreserved", 254, "reserved."},
++ {"ERRnosupport", 0xFFFF, "Function not supported."},
++ {NULL, -1, NULL}
++};
++
++/* Hard Error Messages */
++err_code_struct hard_msgs[] = {
++ {"ERRnowrite", 19,
++ "Attempt to write on write-protected diskette."},
++ {"ERRbadunit", 20, "Unknown unit."},
++ {"ERRnotready", 21, "Drive not ready."},
++ {"ERRbadcmd", 22, "Unknown command."},
++ {"ERRdata", 23, "Data error (CRC)."},
++ {"ERRbadreq", 24, "Bad request structure length."},
++ {"ERRseek", 25, "Seek error."},
++ {"ERRbadmedia", 26, "Unknown media type."},
++ {"ERRbadsector", 27, "Sector not found."},
++ {"ERRnopaper", 28, "Printer out of paper."},
++ {"ERRwrite", 29, "Write fault."},
++ {"ERRread", 30, "Read fault."},
++ {"ERRgeneral", 31, "General failure."},
++ {"ERRbadshare", 32, "An open conflicts with an existing open."},
++ {"ERRlock", 33,
++ "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
++ {"ERRwrongdisk", 34, "The wrong disk was found in a drive."},
++ {"ERRFCBUnavail", 35, "No FCBs are available to process request."},
++ {"ERRsharebufexc", 36, "A sharing buffer has been exceeded."},
++ {NULL, -1, NULL}
++};
++
++
++const struct {
++ int code;
++ char *class;
++ err_code_struct *err_msgs;
++} err_classes[] = {
++ {
++ 0, "SUCCESS", NULL}, {
++ 0x01, "ERRDOS", dos_msgs}, {
++ 0x02, "ERRSRV", server_msgs}, {
++ 0x03, "ERRHRD", hard_msgs}, {
++ 0x04, "ERRXOS", NULL}, {
++ 0xE1, "ERRRMX1", NULL}, {
++ 0xE2, "ERRRMX2", NULL}, {
++ 0xE3, "ERRRMX3", NULL}, {
++ 0xFF, "ERRCMD", NULL}, {
++-1, NULL, NULL}};
++
++
++/****************************************************************************
++return a SMB error string from a SMB buffer
++****************************************************************************/
++char *smb_dos_errstr(char *inbuf)
++{
++ static pstring ret;
++ int class = CVAL(inbuf, smb_rcls);
++ int num = SVAL(inbuf, smb_err);
++ int i, j;
++
++ for (i = 0; err_classes[i].class; i++)
++ if (err_classes[i].code == class) {
++ if (err_classes[i].err_msgs) {
++ err_code_struct *err =
++ err_classes[i].err_msgs;
++ for (j = 0; err[j].name; j++)
++ if (num == err[j].code) {
++ if (DEBUGLEVEL > 0)
++ slprintf(ret,
++ sizeof
++ (ret) - 1,
++ "%s - %s (%s)",
++ err_classes
++ [i].class,
++ err[j].
++ name,
++ err[j].
++ message);
++ else
++ slprintf(ret,
++ sizeof
++ (ret) - 1,
++ "%s - %s",
++ err_classes
++ [i].class,
++ err[j].
++ name);
++ return ret;
++ }
++ }
++
++ slprintf(ret, sizeof(ret) - 1, "%s - %d",
++ err_classes[i].class, num);
++ return ret;
++ }
++
++ slprintf(ret, sizeof(ret) - 1, "Error: Unknown error (%d,%d)",
++ class, num);
++ return (ret);
++}
++
++
++/*****************************************************************************
++ returns an WERROR error message.
++ *****************************************************************************/
++char *werror_str(WERROR status)
++{
++ static fstring msg;
++ slprintf(msg, sizeof(msg), "WIN32 code 0x%08x", W_ERROR_V(status));
++ return msg;
++}
++
++
++/*****************************************************************************
++map a unix errno to a win32 error
++ *****************************************************************************/
++WERROR map_werror_from_unix(int error)
++{
++ NTSTATUS status = map_nt_error_from_unix(error);
++ return ntstatus_to_werror(status);
++}
+diff -urN linux-2.4.29.old/fs/cifs/smberr.h linux-2.4.29/fs/cifs/smberr.h
+--- linux-2.4.29.old/fs/cifs/smberr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/smberr.h 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,113 @@
++/*
++ * fs/cifs/smberr.h
++ *
++ * Copyright (c) International Business Machines Corp., 2002
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * See Error Codes section of the SNIA CIFS Specification
++ * for more 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#define SUCCESS 0 /* The request was successful. */
++#define ERRDOS 0x01 /* Error is from the core DOS operating system set */
++#define ERRSRV 0x02 /* Error is generated by the file server daemon */
++#define ERRHRD 0x03 /* Error is a hardware error. */
++#define ERRCMD 0xFF /* Command was not in the "SMB" format. */
++
++/* The following error codes may be generated with the SUCCESS error class.*/
++
++#define SUCCESS 0 /* The request was successful. */
++
++/* The following error codes may be generated with the ERRDOS error class.*/
++
++#define ERRbadfunc 1 /* Invalid function. The server did not recognize or could not perform a system call generated by the server, e.g., set the DIRECTORY attribute on a data file, invalid seek mode. */
++#define ERRbadfile 2 /*File not found. The last component of a file's pathname could not be found. */
++#define ERRbadpath 3 /* Directory invalid. A directory component in a pathname could not be found. */
++#define ERRnofids 4 /* Too many open files. The server has no file handles available. */
++#define ERRnoaccess 5 /* Access denied, the client's context does not permit the requested function. This includes the following conditions: invalid rename command, write to Fid open for read only, read on Fid open for write only, attempt to delete a non-empty directory */
++#define ERRbadfid 6 /* Invalid file handle. The file handle specified was not recognized by the server. */
++#define ERRbadmcb 7 /* Memory control blocks destroyed. */
++#define ERRnomem 8 /* Insufficient server memory to perform the requested function. */
++#define ERRbadmem 9 /* Invalid memory block address. */
++#define ERRbadenv 10 /* Invalid environment. */
++#define ERRbadformat 11 /* Invalid format. */
++#define ERRbadaccess 12 /* Invalid open mode. */
++#define ERRbaddata 13 /* Invalid data (generated only by IOCTL calls within the server). */
++#define ERRbaddrive 15 /* Invalid drive specified. */
++#define ERRremcd 16 /* A Delete Directory request attempted to remove the server's current directory. */
++#define ERRdiffdevice 17 /* Not same device (e.g., a cross volume rename was attempted */
++#define ERRnofiles 18 /* A File Search command can find no more files matching the specified criteria. */
++#define ERRgeneral 31
++#define ERRbadshare 32 /* The sharing mode specified for an Open conflicts with existing FIDs on the file. */
++#define ERRlock 33 /* A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process. */
++#define ERRunsup 50
++#define ERRnosuchshare 67
++#define ERRfilexists 80 /* The file named in the request already exists. */
++#define ERRinvparm 87
++#define ERRdiskfull 112
++#define ERRinvname 123
++#define ERRdirnotempty 145
++#define ERRnotlocked 158
++#define ERRalreadyexists 183
++#define ERRbadpipe 230
++#define ERRpipebusy 231
++#define ERRpipeclosing 232
++#define ERRnotconnected 233
++#define ERRmoredata 234
++#define ErrQuota 0x200 /* The operation would cause a quota limit to be exceeded. */
++#define ErrNotALink 0x201 /* A link operation was performed on a pathname that
++ was not a link. */
++
++/* Following error codes may be generated with the ERRSRV error
++class.*/
++
++#define ERRerror 1 /* Non-specific error code. It is returned under the following conditions: resource other than disk space exhausted (e.g. TIDs), first SMB command was not negotiate, multiple negotiates attempted, and internal server error. */
++#define ERRbadpw 2 /* Bad password - name/password pair in a TreeConnect or Session Setup are invalid. */
++#define ERRbadtype 3 /* used for indicating DFS referral needed */
++#define ERRaccess 4 /* The client does not have the necessary access rights within the specified context for requested function. */
++#define ERRinvtid 5 /* The Tid specified in a command was invalid. */
++#define ERRinvnetname 6 /* Invalid network name in tree connect. */
++#define ERRinvdevice 7 /* Invalid device - printer request made to non-printer connection or non-printer request made to printer connection. */
++#define ERRqfull 49 /* Print queue full (files) -- returned by open print file. */
++#define ERRqtoobig 50 /* Print queue full -- no space. */
++#define ERRqeof 51 /* EOF on print queue dump */
++#define ERRinvpfid 52 /* Invalid print file FID. */
++#define ERRsmbcmd 64 /* The server did not recognize the command received. */
++#define ERRsrverror 65 /* The server encountered an internal error, e.g., system file unavailable. */
++#define ERRbadBID 66 /* (obsolete) */
++#define ERRfilespecs 67 /* The Fid and pathname parameters contained an invalid combination of values. */
++#define ERRbadLink 68 /* (obsolete) */
++#define ERRbadpermits 69 /* The access permissions specified for a file or directory are not a valid combination. */
++#define ERRbadPID 70
++#define ERRsetattrmode 71 /* attribute (mode) is invalid */
++#define ERRpaused 81 /* Server is paused */
++#define ERRmsgoff 82 /* reserved - messaging off */
++#define ERRnoroom 83 /* reserved - no room for message */
++#define ERRrmuns 87 /* reserved - too many remote names */
++#define ERRtimeout 88 /* operation timed out */
++#define ERRnoresource 89 /* No resources available for request */
++#define ERRtoomanyuids 90 /* Too many UIDs active on this session */
++#define ERRbaduid 91 /* The UID is not known as a valid user */
++#define ERRusempx 250 /* temporarily unable to use raw */
++#define ERRusestd 251 /* temporarily unable to use either raw or mpx */
++#define ERR_NOTIFY_ENUM_DIR 1024
++#define ERRaccountexpired 2239
++#define ERRbadclient 2240
++#define ERRbadLogonTime 2241
++#define ERRpasswordExpired 2242
++#define ERRnetlogonNotStarted 2455
++#define ERRnosupport 0xFFFF
+diff -urN linux-2.4.29.old/fs/cifs/TODO linux-2.4.29/fs/cifs/TODO
+--- linux-2.4.29.old/fs/cifs/TODO 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/TODO 2004-07-14 00:25:04.000000000 +0200
+@@ -0,0 +1,106 @@
++version 1.16 May 27, 2004
++
++A Partial List of Missing Features
++==================================
++
++Contributions are welcome. There are plenty of opportunities
++for visible, important contributions to this module. Here
++is a partial list of the known problems and missing features:
++
++a) Support for SecurityDescriptors for chmod/chgrp/chown so
++these can be supported for Windows servers
++
++b) Better pam/winbind integration
++
++c) multi-user mounts - multiplexed sessionsetups over single vc
++(ie tcp session) - prettying up needed
++
++d) Kerberos/SPNEGO session setup support - (started)
++
++e) NTLMv2 authentication (mostly implemented)
++
++f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup
++used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
++and raw NTLMSSP already. This is important when enabling
++extended security and mounting to Windows 2003 Servers
++
++f) Directory entry caching relies on a 1 second timer, rather than
++using FindNotify or equivalent. - (started)
++
++g) A few byte range testcases fail due to POSIX vs. Windows/CIFS
++style byte range lock differences
++
++h) quota support
++
++i) support for the Linux 2.5 kernel new feature get_xattr and set_xattr
++which will allow us to expose dos attributes as well as real
++ACLs. This support has been started in the current code, but is
++ifdeffed out.
++
++k) finish writepages support (multi-page write behind for improved
++performance) and syncpage
++
++l) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
++extra copy in/out of the socket buffers in some cases.
++
++m) finish support for IPv6. This is mostly complete but
++needs a simple inet_pton like function to convert ipv6
++addresses in string representation.
++
++o) Better optimize open (and pathbased setfilesize) to reduce the
++oplock breaks coming from windows srv. Piggyback identical file
++opens on top of each other by incrementing reference count rather
++than resending (helps reduce server resource utilization and avoid
++spurious oplock breaks).
++
++p) Improve performance of readpages by sending more than one read
++at a time when 8 pages or more are requested. Evaluate whether
++reads larger than 16K would be helpful.
++
++q) For support of Windows9x/98 we need to retry failed mounts
++to *SMBSERVER (default server name) with the uppercase hostname
++in the RFC1001 session_init request.
++
++r) Add Extended Attributed support (for storing UID/GID info
++to Windows servers)
++
++s) Finish fcntl D_NOTIFY support so kde and gnome file list windows
++will autorefresh
++
++t) Add GUI tool to configure /proc/fs/cifs settings and for display of
++the CIFS statistics
++
++KNOWN BUGS (updated May 27, 2004)
++====================================
++1) existing symbolic links (Windows reparse points) are recognized but
++can not be created remotely. They are implemented for Samba and those that
++support the CIFS Unix extensions but Samba has a bug currently handling
++symlink text beginning with slash
++2) follow_link and readdir code does not follow dfs junctions
++but recognizes them
++3) create of new files to FAT partitions on Windows servers can
++succeed but still return access denied (appears to be Windows
++server not cifs client problem) and has not been reproduced recently.
++NTFS partitions do not have this problem.
++4) debug connectathon lock test case 10 which fails against
++Samba (may be unmappable due to POSIX to Windows lock model
++differences but worth investigating). Also debug Samba to
++see why lock test case 7 takes longer to complete to Samba
++than to Windows.
++
++Misc testing to do
++==================
++1) check out max path names and max path name components against various server
++types. Try nested symlinks. Return max path name in stat -f information
++
++2) Modify file portion of ltp so it can run against a mounted network
++share and run it against cifs vfs.
++
++3) Additional performance testing and optimization using iozone and similar -
++there are some easy changes that can be done to parallelize sequential writes,
++and when signing is disabled to request larger read sizes (larger than
++negotiated size) and send larger write sizes to modern servers.
++
++4) More exhaustively test the recently added NT4 support against various
++NT4 service pack levels.
++
+diff -urN linux-2.4.29.old/fs/cifs/transport.c linux-2.4.29/fs/cifs/transport.c
+--- linux-2.4.29.old/fs/cifs/transport.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/fs/cifs/transport.c 2004-07-14 00:25:05.000000000 +0200
+@@ -0,0 +1,434 @@
++/*
++ * fs/cifs/transport.c
++ *
++ * Copyright (C) International Business Machines Corp., 2002,2004
++ * Author(s): Steve French (sfrench@us.ibm.com)
++ *
++ * 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; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/fs.h>
++#include <linux/list.h>
++#include <linux/wait.h>
++#include <linux/net.h>
++#include <linux/version.h>
++#include <asm/uaccess.h>
++#include <asm/processor.h>
++#include "cifspdu.h"
++#include "cifsglob.h"
++#include "cifsproto.h"
++#include "cifs_debug.h"
++
++extern kmem_cache_t *cifs_mid_cachep;
++extern kmem_cache_t *cifs_oplock_cachep;
++
++struct mid_q_entry *
++AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
++{
++ struct mid_q_entry *temp;
++
++ if (ses == NULL) {
++ cERROR(1, ("Null session passed in to AllocMidQEntry "));
++ return NULL;
++ }
++ if (ses->server == NULL) {
++ cERROR(1, ("Null TCP session in AllocMidQEntry"));
++ return NULL;
++ }
++
++ temp = (struct mid_q_entry *) kmem_cache_alloc(cifs_mid_cachep,
++ SLAB_KERNEL);
++ if (temp == NULL)
++ return temp;
++ else {
++ memset(temp, 0, sizeof (struct mid_q_entry));
++ temp->mid = smb_buffer->Mid; /* always LE */
++ temp->pid = current->pid;
++ temp->command = smb_buffer->Command;
++ cFYI(1, ("For smb_command %d", temp->command));
++ do_gettimeofday(&temp->when_sent);
++ temp->ses = ses;
++ temp->tsk = current;
++ }
++
++ spin_lock(&GlobalMid_Lock);
++ list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
++ atomic_inc(&midCount);
++ temp->midState = MID_REQUEST_ALLOCATED;
++ spin_unlock(&GlobalMid_Lock);
++ return temp;
++}
++
++void
++DeleteMidQEntry(struct mid_q_entry *midEntry)
++{
++ spin_lock(&GlobalMid_Lock);
++ midEntry->midState = MID_FREE;
++ list_del(&midEntry->qhead);
++ atomic_dec(&midCount);
++ spin_unlock(&GlobalMid_Lock);
++ cifs_buf_release(midEntry->resp_buf);
++ kmem_cache_free(cifs_mid_cachep, midEntry);
++}
++
++struct oplock_q_entry *
++AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
++{
++ struct oplock_q_entry *temp;
++ if ((pinode== NULL) || (tcon == NULL)) {
++ cERROR(1, ("Null parms passed to AllocOplockQEntry"));
++ return NULL;
++ }
++ temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
++ SLAB_KERNEL);
++ if (temp == NULL)
++ return temp;
++ else {
++ temp->pinode = pinode;
++ temp->tcon = tcon;
++ temp->netfid = fid;
++ spin_lock(&GlobalMid_Lock);
++ list_add_tail(&temp->qhead, &GlobalOplock_Q);
++ spin_unlock(&GlobalMid_Lock);
++ }
++ return temp;
++
++}
++
++void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry)
++{
++ spin_lock(&GlobalMid_Lock);
++ /* should we check if list empty first? */
++ list_del(&oplockEntry->qhead);
++ spin_unlock(&GlobalMid_Lock);
++ kmem_cache_free(cifs_oplock_cachep, oplockEntry);
++}
++
++int
++smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
++ unsigned int smb_buf_length, struct sockaddr *sin)
++{
++ int rc = 0;
++ int i = 0;
++ struct msghdr smb_msg;
++ struct iovec iov;
++ mm_segment_t temp_fs;
++
++ if(ssocket == NULL)
++ return -ENOTSOCK; /* BB eventually add reconnect code here */
++ iov.iov_base = smb_buffer;
++ iov.iov_len = smb_buf_length + 4;
++
++ smb_msg.msg_name = sin;
++ smb_msg.msg_namelen = sizeof (struct sockaddr);
++ smb_msg.msg_iov = &iov;
++ smb_msg.msg_iovlen = 1;
++ smb_msg.msg_control = NULL;
++ smb_msg.msg_controllen = 0;
++ smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
++
++ /* smb header is converted in header_assemble. bcc and rest of SMB word
++ area, and byte area if necessary, is converted to littleendian in
++ cifssmb.c and RFC1001 len is converted to bigendian in smb_send
++ Flags2 is converted in SendReceive */
++
++ smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
++ cFYI(1, ("Sending smb of length %d ", smb_buf_length));
++ dump_smb(smb_buffer, smb_buf_length + 4);
++
++ temp_fs = get_fs(); /* we must turn off socket api parm checking */
++ set_fs(get_ds());
++ while(iov.iov_len > 0) {
++ rc = sock_sendmsg(ssocket, &smb_msg, smb_buf_length + 4);
++ if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
++ i++;
++ if(i > 60) {
++ cERROR(1,
++ ("sends on sock %p stuck for 30 seconds",
++ ssocket));
++ rc = -EAGAIN;
++ break;
++ }
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(HZ/2);
++ continue;
++ }
++ if (rc < 0)
++ break;
++ iov.iov_base += rc;
++ iov.iov_len -= rc;
++ }
++ set_fs(temp_fs);
++
++ if (rc < 0) {
++ cERROR(1,("Error %d sending data on socket to server.", rc));
++ } else {
++ rc = 0;
++ }
++
++ return rc;
++}
++
++int
++SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
++ struct smb_hdr *in_buf, struct smb_hdr *out_buf,
++ int *pbytes_returned, const int long_op)
++{
++ int rc = 0;
++ unsigned int receive_len;
++ long timeout;
++ struct mid_q_entry *midQ;
++
++ if (ses == NULL) {
++ cERROR(1,("Null smb session"));
++ return -EIO;
++ }
++ if(ses->server == NULL) {
++ cERROR(1,("Null tcp session"));
++ return -EIO;
++ }
++
++ /* Ensure that we do not send more than 50 overlapping requests
++ to the same server. We may make this configurable later or
++ use ses->maxReq */
++ if(long_op == -1) {
++ /* oplock breaks must not be held up */
++ atomic_inc(&ses->server->inFlight);
++ } else {
++ spin_lock(&GlobalMid_Lock);
++ while(1) {
++ if(atomic_read(&ses->server->inFlight) >= CIFS_MAX_REQ){
++ spin_unlock(&GlobalMid_Lock);
++ wait_event(ses->server->request_q,
++ atomic_read(&ses->server->inFlight)
++ < CIFS_MAX_REQ);
++ spin_lock(&GlobalMid_Lock);
++ } else {
++ if(ses->server->tcpStatus == CifsExiting) {
++ spin_unlock(&GlobalMid_Lock);
++ return -ENOENT;
++ }
++
++ /* can not count locking commands against total since
++ they are allowed to block on server */
++
++ if(long_op < 3) {
++ /* update # of requests on the wire to server */
++ atomic_inc(&ses->server->inFlight);
++ }
++ spin_unlock(&GlobalMid_Lock);
++ break;
++ }
++ }
++ }
++ /* make sure that we sign in the same order that we send on this socket
++ and avoid races inside tcp sendmsg code that could cause corruption
++ of smb data */
++
++ down(&ses->server->tcpSem);
++
++ if (ses->server->tcpStatus == CifsExiting) {
++ rc = -ENOENT;
++ goto out_unlock;
++ } else if (ses->server->tcpStatus == CifsNeedReconnect) {
++ cFYI(1,("tcp session dead - return to caller to retry"));
++ rc = -EAGAIN;
++ goto out_unlock;
++ } else if (ses->status != CifsGood) {
++ /* check if SMB session is bad because we are setting it up */
++ if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
++ (in_buf->Command != SMB_COM_NEGOTIATE)) {
++ rc = -EAGAIN;
++ goto out_unlock;
++ } /* else ok - we are setting up session */
++ }
++ midQ = AllocMidQEntry(in_buf, ses);
++ if (midQ == NULL) {
++ up(&ses->server->tcpSem);
++ /* If not lock req, update # of requests on wire to server */
++ if(long_op < 3) {
++ atomic_dec(&ses->server->inFlight);
++ wake_up(&ses->server->request_q);
++ }
++ return -ENOMEM;
++ }
++
++ if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4) {
++ up(&ses->server->tcpSem);
++ cERROR(1,
++ ("Illegal length, greater than maximum frame, %d ",
++ in_buf->smb_buf_length));
++ DeleteMidQEntry(midQ);
++ /* If not lock req, update # of requests on wire to server */
++ if(long_op < 3) {
++ atomic_dec(&ses->server->inFlight);
++ wake_up(&ses->server->request_q);
++ }
++ return -EIO;
++ }
++
++ if (in_buf->smb_buf_length > 12)
++ in_buf->Flags2 = cpu_to_le16(in_buf->Flags2);
++
++ rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
++
++ midQ->midState = MID_REQUEST_SUBMITTED;
++ rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
++ (struct sockaddr *) &(ses->server->addr.sockAddr));
++ if(rc < 0) {
++ DeleteMidQEntry(midQ);
++ up(&ses->server->tcpSem);
++ /* If not lock req, update # of requests on wire to server */
++ if(long_op < 3) {
++ atomic_dec(&ses->server->inFlight);
++ wake_up(&ses->server->request_q);
++ }
++ return rc;
++ } else
++ up(&ses->server->tcpSem);
++ if (long_op == -1)
++ goto cifs_no_response_exit;
++ else if (long_op == 2) /* writes past end of file can take looooong time */
++ timeout = 300 * HZ;
++ else if (long_op == 1)
++ timeout = 45 * HZ; /* should be greater than
++ servers oplock break timeout (about 43 seconds) */
++ else if (long_op > 2) {
++ timeout = MAX_SCHEDULE_TIMEOUT;
++ } else
++ timeout = 15 * HZ;
++ /* wait for 15 seconds or until woken up due to response arriving or
++ due to last connection to this server being unmounted */
++ if (signal_pending(current)) {
++ /* if signal pending do not hold up user for full smb timeout
++ but we still give response a change to complete */
++ if(midQ->midState & MID_REQUEST_SUBMITTED) {
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ timeout = sleep_on_timeout(&ses->server->response_q,2 * HZ);
++ }
++ } else { /* using normal timeout */
++ /* timeout = wait_event_interruptible_timeout(ses->server->response_q,
++ (midQ->midState & MID_RESPONSE_RECEIVED) ||
++ ((ses->server->tcpStatus != CifsGood) &&
++ (ses->server->tcpStatus != CifsNew)),
++ timeout); */
++ /* Can not allow user interrupts- wreaks havoc with performance */
++ if(midQ->midState & MID_REQUEST_SUBMITTED) {
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ timeout = sleep_on_timeout(&ses->server->response_q,timeout);
++ }
++ }
++
++ spin_lock(&GlobalMid_Lock);
++ if (midQ->resp_buf) {
++ spin_unlock(&GlobalMid_Lock);
++ receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length);
++ } else {
++ cERROR(1,("No response buffer"));
++ if(midQ->midState == MID_REQUEST_SUBMITTED) {
++ if(ses->server->tcpStatus == CifsExiting)
++ rc = -EHOSTDOWN;
++ else {
++ ses->server->tcpStatus = CifsNeedReconnect;
++ midQ->midState = MID_RETRY_NEEDED;
++ }
++ }
++
++ if (rc != -EHOSTDOWN) {
++ if(midQ->midState == MID_RETRY_NEEDED) {
++ rc = -EAGAIN;
++ cFYI(1,("marking request for retry"));
++ } else {
++ rc = -EIO;
++ }
++ }
++ spin_unlock(&GlobalMid_Lock);
++ DeleteMidQEntry(midQ);
++ /* If not lock req, update # of requests on wire to server */
++ if(long_op < 3) {
++ atomic_dec(&ses->server->inFlight);
++ wake_up(&ses->server->request_q);
++ }
++ return rc;
++ }
++
++ if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
++ cERROR(1,
++ ("Frame too large received. Length: %d Xid: %d",
++ receive_len, xid));
++ rc = -EIO;
++ } else { /* rcvd frame is ok */
++
++ if (midQ->resp_buf && out_buf
++ && (midQ->midState == MID_RESPONSE_RECEIVED)) {
++ memcpy(out_buf, midQ->resp_buf,
++ receive_len +
++ 4 /* include 4 byte RFC1001 header */ );
++
++ dump_smb(out_buf, 92);
++ /* convert the length into a more usable form */
++ out_buf->smb_buf_length =
++ be32_to_cpu(out_buf->smb_buf_length);
++ if((out_buf->smb_buf_length > 24) &&
++ (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) {
++ rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */
++ if(rc)
++ cFYI(1,("Unexpected signature received from server"));
++ }
++
++ if (out_buf->smb_buf_length > 12)
++ out_buf->Flags2 = le16_to_cpu(out_buf->Flags2);
++ if (out_buf->smb_buf_length > 28)
++ out_buf->Pid = le16_to_cpu(out_buf->Pid);
++ if (out_buf->smb_buf_length > 28)
++ out_buf->PidHigh =
++ le16_to_cpu(out_buf->PidHigh);
++
++ *pbytes_returned = out_buf->smb_buf_length;
++
++ /* BB special case reconnect tid and reconnect uid here? */
++ rc = map_smb_to_linux_error(out_buf);
++
++ /* convert ByteCount if necessary */
++ if (receive_len >=
++ sizeof (struct smb_hdr) -
++ 4 /* do not count RFC1001 header */ +
++ (2 * out_buf->WordCount) + 2 /* bcc */ )
++ BCC(out_buf) = le16_to_cpu(BCC(out_buf));
++ } else {
++ rc = -EIO;
++ cFYI(1,("Bad MID state? "));
++ }
++ }
++cifs_no_response_exit:
++ DeleteMidQEntry(midQ);
++
++ if(long_op < 3) {
++ atomic_dec(&ses->server->inFlight);
++ wake_up(&ses->server->request_q);
++ }
++
++ return rc;
++
++out_unlock:
++ up(&ses->server->tcpSem);
++ /* If not lock req, update # of requests on wire to server */
++ if(long_op < 3) {
++ atomic_dec(&ses->server->inFlight);
++ wake_up(&ses->server->request_q);
++ }
++
++ return rc;
++}
+diff -urN linux-2.4.29.old/fs/Config.in linux-2.4.29/fs/Config.in
+--- linux-2.4.29.old/fs/Config.in 2005-03-21 19:30:22.000000000 +0100
++++ linux-2.4.29/fs/Config.in 2005-03-21 19:36:51.000000000 +0100
+@@ -146,6 +146,10 @@
+ define_bool CONFIG_LOCKD_V4 y
+ fi
+
++ dep_tristate 'CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)' CONFIG_CIFS $CONFIG_INET
++ dep_mbool ' CIFS statistics' CONFIG_CIFS_STATS $CONFIG_CIFS
++ dep_mbool ' CIFS POSIX Protocol Extensions' CONFIG_CIFS_POSIX $CONFIG_CIFS
++
+ dep_tristate 'SMB file system support (to mount Windows shares etc.)' CONFIG_SMB_FS $CONFIG_INET
+ if [ "$CONFIG_SMB_FS" != "n" ]; then
+ bool ' Use a default NLS' CONFIG_SMB_NLS_DEFAULT
+diff -urN linux-2.4.29.old/fs/Makefile linux-2.4.29/fs/Makefile
+--- linux-2.4.29.old/fs/Makefile 2005-03-21 19:30:22.000000000 +0100
++++ linux-2.4.29/fs/Makefile 2005-03-21 19:36:51.000000000 +0100
+@@ -37,6 +37,7 @@
+ subdir-$(CONFIG_VFAT_FS) += vfat
+ subdir-$(CONFIG_BFS_FS) += bfs
+ subdir-$(CONFIG_ISO9660_FS) += isofs
++subdir-$(CONFIG_CIFS) += cifs
+ subdir-$(CONFIG_DEVFS_FS) += devfs
+ subdir-$(CONFIG_HFSPLUS_FS) += hfsplus # Before hfs to find wrapped HFS+
+ subdir-$(CONFIG_HFS_FS) += hfs
+diff -urN linux-2.4.29.old/fs/nls/Config.in linux-2.4.29/fs/nls/Config.in
+--- linux-2.4.29.old/fs/nls/Config.in 2003-08-25 13:44:43.000000000 +0200
++++ linux-2.4.29/fs/nls/Config.in 2005-03-21 19:36:51.000000000 +0100
+@@ -11,6 +11,7 @@
+
+ # msdos and Joliet want NLS
+ if [ "$CONFIG_JOLIET" = "y" -o "$CONFIG_FAT_FS" != "n" \
++ -o "$CONFIG_CIFS" != "n" \
+ -o "$CONFIG_NTFS_FS" != "n" -o "$CONFIG_NCPFS_NLS" = "y" \
+ -o "$CONFIG_SMB_NLS" = "y" -o "$CONFIG_JFS_FS" != "n" \
+ -o "$CONFIG_BEFS_FS" != "n" -o "$CONFIG_HFSPLUS_FS" != "n" ]; then
diff --git a/target/linux/generic-2.4/patches/108-optional_aout_support.patch b/target/linux/generic-2.4/patches/108-optional_aout_support.patch
new file mode 100644
index 0000000000..56dc1991cf
--- /dev/null
+++ b/target/linux/generic-2.4/patches/108-optional_aout_support.patch
@@ -0,0 +1,688 @@
+diff -urPX nopatch linux-2.4.26/Documentation/Configure.help linux/Documentation/Configure.help
+--- linux-2.4.26/Documentation/Configure.help Sat Apr 17 02:10:25 2004
++++ linux/Documentation/Configure.help Sat Apr 17 02:13:54 2004
+@@ -4622,6 +4622,12 @@
+ will be called binfmt_elf.o. Saying M or N here is dangerous because
+ some crucial programs on your system might be in ELF format.
+
++ELF binaries with a.out format interpreters or a.out libraries
++CONFIG_BINFMT_ELF_AOUT
++ The kernel may support ELF executables which use an a.out format
++ interpreter (dynamic linker) and/or a.out shared libraries, in
++ addition to the usual ELF-ELF setups. You shouldn't need this.
++
+ Kernel support for a.out binaries
+ CONFIG_BINFMT_AOUT
+ A.out (Assembler.OUTput) is a set of formats for libraries and
+@@ -4635,13 +4641,11 @@
+ warrant removing support. However its removal is a good idea if you
+ wish to ensure that absolutely none of your programs will use this
+ older executable format. If you don't know what to answer at this
+- point then answer Y. If someone told you "You need a kernel with
++ point then answer N. If someone told you "You need a kernel with
+ QMAGIC support" then you'll have to say Y here. You may answer M to
+ compile a.out support as a module and later load the module when you
+ want to use a program or library in a.out format. The module will be
+- called binfmt_aout.o. Saying M or N here is dangerous though,
+- because some crucial programs on your system might still be in A.OUT
+- format.
++ called binfmt_aout.o.
+
+ OSF/1 v4 readv/writev compatibility
+ CONFIG_OSF4_COMPAT
+diff -urPX nopatch linux-2.4.26/arch/alpha/config.in linux/arch/alpha/config.in
+--- linux-2.4.26/arch/alpha/config.in Fri Feb 20 10:07:20 2004
++++ linux/arch/alpha/config.in Sat Apr 17 02:13:54 2004
+@@ -315,6 +315,9 @@
+ fi
+
+ bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
++if [ "$CONFIG_BINFMT_ELF" != "n" ]; then
++ bool ' ELF binaries with a.out format interpreters or a.out libraries' CONFIG_BINFMT_ELF_AOUT
++fi
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+ tristate 'Kernel support for Linux/Intel ELF binaries' CONFIG_BINFMT_EM86
+ source drivers/parport/Config.in
+diff -urPX nopatch linux-2.4.26/arch/alpha/defconfig linux/arch/alpha/defconfig
+--- linux-2.4.26/arch/alpha/defconfig Fri Feb 20 10:07:20 2004
++++ linux/arch/alpha/defconfig Sat Apr 17 02:13:54 2004
+@@ -72,6 +72,7 @@
+ # CONFIG_KCORE_AOUT is not set
+ # CONFIG_BINFMT_AOUT is not set
+ CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_ELF_AOUT is not set
+ # CONFIG_BINFMT_MISC is not set
+ # CONFIG_BINFMT_EM86 is not set
+
+diff -urPX nopatch linux-2.4.26/arch/arm/config.in linux/arch/arm/config.in
+--- linux-2.4.26/arch/arm/config.in Fri Feb 20 10:07:20 2004
++++ linux/arch/arm/config.in Sat Apr 17 02:13:54 2004
+@@ -499,6 +499,9 @@
+ A.OUT CONFIG_KCORE_AOUT" ELF
+ tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
+ bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
++if [ "$CONFIG_BINFMT_ELF" != "n" ]; then
++ bool ' ELF binaries with a.out format interpreters or a.out libraries' CONFIG_BINFMT_ELF_AOUT
++fi
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+ dep_bool 'Power Management support (experimental)' CONFIG_PM $CONFIG_EXPERIMENTAL
+ dep_tristate 'RISC OS personality' CONFIG_ARTHUR $CONFIG_CPU_32
+diff -urPX nopatch linux-2.4.26/arch/arm/defconfig linux/arch/arm/defconfig
+--- linux-2.4.26/arch/arm/defconfig Fri Feb 20 10:07:21 2004
++++ linux/arch/arm/defconfig Sat Apr 17 02:13:54 2004
+@@ -83,8 +83,9 @@
+ CONFIG_NWFPE=y
+ CONFIG_KCORE_ELF=y
+ # CONFIG_KCORE_AOUT is not set
+-CONFIG_BINFMT_AOUT=y
++# CONFIG_BINFMT_AOUT is not set
+ CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_ELF_AOUT is not set
+ # CONFIG_BINFMT_MISC is not set
+ # CONFIG_PM is not set
+ # CONFIG_ARTHUR is not set
+diff -urPX nopatch linux-2.4.26/arch/cris/config.in linux/arch/cris/config.in
+--- linux-2.4.26/arch/cris/config.in Fri Feb 20 10:07:21 2004
++++ linux/arch/cris/config.in Sat Apr 17 02:13:54 2004
+@@ -31,6 +31,9 @@
+ bool 'Sysctl support' CONFIG_SYSCTL
+
+ bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
++if [ "$CONFIG_BINFMT_ELF" != "n" ]; then
++ bool ' ELF binaries with a.out format interpreters or a.out libraries' CONFIG_BINFMT_ELF_AOUT
++fi
+
+ string 'Kernel command line' CONFIG_ETRAX_CMDLINE "root=/dev/mtdblock3"
+
+diff -urPX nopatch linux-2.4.26/arch/cris/defconfig linux/arch/cris/defconfig
+--- linux-2.4.26/arch/cris/defconfig Fri Feb 20 10:07:21 2004
++++ linux/arch/cris/defconfig Sat Apr 17 02:13:54 2004
+@@ -18,6 +18,7 @@
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ # CONFIG_SYSCTL is not set
+ CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_ELF_AOUT is not set
+ # CONFIG_ETRAX_KGDB is not set
+ # CONFIG_ETRAX_WATCHDOG is not set
+
+diff -urPX nopatch linux-2.4.26/arch/i386/config.in linux/arch/i386/config.in
+--- linux-2.4.26/arch/i386/config.in Fri Feb 20 10:07:21 2004
++++ linux/arch/i386/config.in Sat Apr 17 02:13:54 2004
+@@ -327,6 +327,9 @@
+ fi
+ tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
+ bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
++if [ "$CONFIG_BINFMT_ELF" != "n" ]; then
++ bool ' ELF binaries with a.out format interpreters or a.out libraries' CONFIG_BINFMT_ELF_AOUT
++fi
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+ bool 'Select task to kill on out of memory condition' CONFIG_OOM_KILLER
+
+diff -urPX nopatch linux-2.4.26/arch/i386/defconfig linux/arch/i386/defconfig
+--- linux-2.4.26/arch/i386/defconfig Sat Apr 17 02:10:25 2004
++++ linux/arch/i386/defconfig Sat Apr 17 02:23:27 2004
+@@ -110,9 +110,10 @@
+ CONFIG_SYSCTL=y
+ CONFIG_KCORE_ELF=y
+ # CONFIG_KCORE_AOUT is not set
+-CONFIG_BINFMT_AOUT=y
++# CONFIG_BINFMT_AOUT is not set
+ CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=y
++# CONFIG_BINFMT_ELF_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
+ # CONFIG_OOM_KILLER is not set
+ CONFIG_PM=y
+ # CONFIG_APM is not set
+diff -urPX nopatch linux-2.4.26/arch/ia64/config.in linux/arch/ia64/config.in
+--- linux-2.4.26/arch/ia64/config.in Fri Feb 20 10:07:21 2004
++++ linux/arch/ia64/config.in Sat Apr 17 02:13:54 2004
+@@ -124,6 +124,9 @@
+ bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
+ bool 'Sysctl support' CONFIG_SYSCTL
+ bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
++if [ "$CONFIG_BINFMT_ELF" != "n" ]; then
++ bool ' ELF binaries with a.out format interpreters or a.out libraries' CONFIG_BINFMT_ELF_AOUT
++fi
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+
+ if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
+diff -urPX nopatch linux-2.4.26/arch/ia64/defconfig linux/arch/ia64/defconfig
+--- linux-2.4.26/arch/ia64/defconfig Fri Feb 20 10:07:21 2004
++++ linux/arch/ia64/defconfig Sat Apr 17 02:13:54 2004
+@@ -60,6 +60,7 @@
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ CONFIG_SYSCTL=y
+ CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_ELF_AOUT is not set
+ # CONFIG_BINFMT_MISC is not set
+ CONFIG_ACPI=y
+ CONFIG_ACPI_EFI=y
+diff -urPX nopatch linux-2.4.26/arch/m68k/config.in linux/arch/m68k/config.in
+--- linux-2.4.26/arch/m68k/config.in Fri Feb 20 10:07:22 2004
++++ linux/arch/m68k/config.in Sat Apr 17 02:13:55 2004
+@@ -99,6 +99,9 @@
+ fi
+ tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
+ bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
++if [ "$CONFIG_BINFMT_ELF" != "n" ]; then
++ bool ' ELF binaries with a.out format interpreters or a.out libraries' CONFIG_BINFMT_ELF_AOUT
++fi
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+
+ if [ "$CONFIG_AMIGA" = "y" ]; then
+diff -urPX nopatch linux-2.4.26/arch/m68k/defconfig linux/arch/m68k/defconfig
+--- linux-2.4.26/arch/m68k/defconfig Fri Feb 20 10:07:22 2004
++++ linux/arch/m68k/defconfig Sat Apr 17 02:13:55 2004
+@@ -44,8 +44,9 @@
+ CONFIG_SYSCTL=y
+ CONFIG_KCORE_ELF=y
+ # CONFIG_KCORE_AOUT is not set
+-CONFIG_BINFMT_AOUT=y
++# CONFIG_BINFMT_AOUT is not set
+ CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_ELF_AOUT is not set
+ # CONFIG_BINFMT_MISC is not set
+ CONFIG_ZORRO=y
+ # CONFIG_AMIGA_PCMCIA is not set
+diff -urPX nopatch linux-2.4.26/arch/mips/config-shared.in linux/arch/mips/config-shared.in
+--- linux-2.4.26/arch/mips/config-shared.in Fri Feb 20 10:07:22 2004
++++ linux/arch/mips/config-shared.in Sat Apr 17 02:13:55 2004
+@@ -944,6 +944,9 @@
+ define_bool CONFIG_KCORE_AOUT n
+ define_bool CONFIG_BINFMT_AOUT n
+ bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
++if [ "$CONFIG_BINFMT_ELF" != "n" ]; then
++ bool ' ELF binaries with a.out format interpreters or a.out libraries' CONFIG_BINFMT_ELF_AOUT
++fi
+ dep_bool 'Kernel support for Linux/MIPS 32-bit binary compatibility' CONFIG_MIPS32_COMPAT $CONFIG_MIPS64
+ dep_bool 'Kernel support for o32 binaries' CONFIG_MIPS32_O32 $CONFIG_MIPS32_COMPAT
+ dep_bool 'Kernel support for n32 binaries' CONFIG_MIPS32_N32 $CONFIG_MIPS32_COMPAT
+diff -urPX nopatch linux-2.4.26/arch/mips/defconfig linux/arch/mips/defconfig
+--- linux-2.4.26/arch/mips/defconfig Fri Feb 20 10:07:22 2004
++++ linux/arch/mips/defconfig Sat Apr 17 02:13:55 2004
+@@ -139,6 +139,7 @@
+ # CONFIG_KCORE_AOUT is not set
+ # CONFIG_BINFMT_AOUT is not set
+ CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_ELF_AOUT is not set
+ # CONFIG_MIPS32_COMPAT is not set
+ # CONFIG_MIPS32_O32 is not set
+ # CONFIG_MIPS32_N32 is not set
+diff -urPX nopatch linux-2.4.26/arch/mips/kernel/irixelf.c linux/arch/mips/kernel/irixelf.c
+--- linux-2.4.26/arch/mips/kernel/irixelf.c Mon Aug 25 11:44:40 2003
++++ linux/arch/mips/kernel/irixelf.c Sat Apr 17 02:13:55 2004
+@@ -8,6 +8,7 @@
+ * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com).
+ */
+
++#include <linux/config.h>
+ #include <linux/module.h>
+
+ #include <linux/fs.h>
+@@ -48,7 +49,12 @@
+ extern int dump_fpu (elf_fpregset_t *);
+
+ static struct linux_binfmt irix_format = {
+- NULL, THIS_MODULE, load_irix_binary, load_irix_library,
++ NULL, THIS_MODULE, load_irix_binary,
++#ifdef CONFIG_BINFMT_ELF_AOUT
++ load_irix_library,
++#else
++ NULL,
++#endif
+ irix_core_dump, PAGE_SIZE
+ };
+
+@@ -787,6 +793,7 @@
+ goto out;
+ }
+
++#ifdef CONFIG_BINFMT_ELF_AOUT
+ /* This is really simpleminded and specialized - we are loading an
+ * a.out library that is given an ELF header.
+ */
+@@ -863,6 +870,7 @@
+ kfree(elf_phdata);
+ return 0;
+ }
++#endif
+
+ /* Called through irix_syssgi() to map an elf image given an FD,
+ * a phdr ptr USER_PHDRP in userspace, and a count CNT telling how many
+diff -urPX nopatch linux-2.4.26/arch/mips64/defconfig linux/arch/mips64/defconfig
+--- linux-2.4.26/arch/mips64/defconfig Fri Feb 20 10:07:24 2004
++++ linux/arch/mips64/defconfig Sat Apr 17 02:13:55 2004
+@@ -137,6 +137,7 @@
+ # CONFIG_KCORE_AOUT is not set
+ # CONFIG_BINFMT_AOUT is not set
+ CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_ELF_AOUT is not set
+ CONFIG_MIPS32_COMPAT=y
+ CONFIG_MIPS32_O32=y
+ # CONFIG_MIPS32_N32 is not set
+diff -urPX nopatch linux-2.4.26/arch/parisc/config.in linux/arch/parisc/config.in
+--- linux-2.4.26/arch/parisc/config.in Fri Feb 20 10:07:25 2004
++++ linux/arch/parisc/config.in Sat Apr 17 02:13:55 2004
+@@ -89,6 +89,9 @@
+ bool 'Sysctl support' CONFIG_SYSCTL
+ define_bool CONFIG_KCORE_ELF y
+ bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
++if [ "$CONFIG_BINFMT_ELF" != "n" ]; then
++ bool ' ELF binaries with a.out format interpreters or a.out libraries' CONFIG_BINFMT_ELF_AOUT
++fi
+ tristate 'Kernel support for SOM binaries' CONFIG_BINFMT_SOM
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+
+diff -urPX nopatch linux-2.4.26/arch/parisc/defconfig linux/arch/parisc/defconfig
+--- linux-2.4.26/arch/parisc/defconfig Fri Feb 20 10:07:25 2004
++++ linux/arch/parisc/defconfig Sat Apr 17 02:13:55 2004
+@@ -56,6 +56,7 @@
+ CONFIG_SYSCTL=y
+ CONFIG_KCORE_ELF=y
+ CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_ELF_AOUT is not set
+ CONFIG_BINFMT_SOM=y
+ # CONFIG_BINFMT_MISC is not set
+ # CONFIG_PM is not set
+diff -urPX nopatch linux-2.4.26/arch/ppc/config.in linux/arch/ppc/config.in
+--- linux-2.4.26/arch/ppc/config.in Sat Apr 17 02:10:25 2004
++++ linux/arch/ppc/config.in Sat Apr 17 02:13:55 2004
+@@ -384,6 +384,7 @@
+ fi
+ define_bool CONFIG_BINFMT_ELF y
+ define_bool CONFIG_KERNEL_ELF y
++bool 'ELF binaries with a.out format interpreters or a.out libraries' CONFIG_BINFMT_ELF_AOUT
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+ bool 'Select task to kill on out of memory condition' CONFIG_OOM_KILLER
+
+diff -urPX nopatch linux-2.4.26/arch/ppc/defconfig linux/arch/ppc/defconfig
+--- linux-2.4.26/arch/ppc/defconfig Fri Feb 20 10:07:25 2004
++++ linux/arch/ppc/defconfig Sat Apr 17 02:13:55 2004
+@@ -59,7 +59,8 @@
+ CONFIG_KCORE_ELF=y
+ CONFIG_BINFMT_ELF=y
+ CONFIG_KERNEL_ELF=y
+-CONFIG_BINFMT_MISC=m
++# CONFIG_BINFMT_ELF_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
+ # CONFIG_OOM_KILLER is not set
+ CONFIG_PCI_NAMES=y
+ CONFIG_HOTPLUG=y
+diff -urPX nopatch linux-2.4.26/arch/ppc64/config.in linux/arch/ppc64/config.in
+--- linux-2.4.26/arch/ppc64/config.in Fri Feb 20 10:07:25 2004
++++ linux/arch/ppc64/config.in Sat Apr 17 02:13:55 2004
+@@ -82,6 +82,9 @@
+ fi
+
+ bool 'Kernel support for 64 bit ELF binaries' CONFIG_BINFMT_ELF
++if [ "$CONFIG_BINFMT_ELF" != "n" ]; then
++ bool ' ELF binaries with a.out format interpreters or a.out libraries' CONFIG_BINFMT_ELF_AOUT
++fi
+
+ tristate 'Kernel support for 32 bit ELF binaries' CONFIG_BINFMT_ELF32
+
+diff -urPX nopatch linux-2.4.26/arch/ppc64/defconfig linux/arch/ppc64/defconfig
+--- linux-2.4.26/arch/ppc64/defconfig Fri Feb 20 10:07:25 2004
++++ linux/arch/ppc64/defconfig Sat Apr 17 02:13:55 2004
+@@ -56,6 +56,7 @@
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ CONFIG_KCORE_ELF=y
+ CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_ELF_AOUT is not set
+ CONFIG_BINFMT_ELF32=y
+ # CONFIG_BINFMT_MISC is not set
+ CONFIG_PCI_NAMES=y
+diff -urPX nopatch linux-2.4.26/arch/s390/config.in linux/arch/s390/config.in
+--- linux-2.4.26/arch/s390/config.in Fri Nov 28 18:26:19 2003
++++ linux/arch/s390/config.in Sat Apr 17 02:13:55 2004
+@@ -58,6 +58,9 @@
+ bool 'Sysctl support' CONFIG_SYSCTL
+ define_bool CONFIG_KCORE_ELF y
+ bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
++if [ "$CONFIG_BINFMT_ELF" != "n" ]; then
++ bool ' ELF binaries with a.out format interpreters or a.out libraries' CONFIG_BINFMT_ELF_AOUT
++fi
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+ bool 'Show crashed user process info' CONFIG_PROCESS_DEBUG
+ bool 'Pseudo page fault support' CONFIG_PFAULT
+diff -urPX nopatch linux-2.4.26/arch/s390/defconfig linux/arch/s390/defconfig
+--- linux-2.4.26/arch/s390/defconfig Fri Feb 20 10:07:26 2004
++++ linux/arch/s390/defconfig Sat Apr 17 02:13:55 2004
+@@ -46,6 +46,7 @@
+ CONFIG_SYSCTL=y
+ CONFIG_KCORE_ELF=y
+ CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_ELF_AOUT is not set
+ # CONFIG_BINFMT_MISC is not set
+ # CONFIG_PROCESS_DEBUG is not set
+ CONFIG_PFAULT=y
+diff -urPX nopatch linux-2.4.26/arch/s390x/config.in linux/arch/s390x/config.in
+--- linux-2.4.26/arch/s390x/config.in Fri Nov 28 18:26:19 2003
++++ linux/arch/s390x/config.in Sat Apr 17 02:13:55 2004
+@@ -61,6 +61,9 @@
+ bool 'Sysctl support' CONFIG_SYSCTL
+ define_bool CONFIG_KCORE_ELF y
+ bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
++if [ "$CONFIG_BINFMT_ELF" != "n" ]; then
++ bool ' ELF binaries with a.out format interpreters or a.out libraries' CONFIG_BINFMT_ELF_AOUT
++fi
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+ bool 'Show crashed user process info' CONFIG_PROCESS_DEBUG
+ bool 'Pseudo page fault support' CONFIG_PFAULT
+diff -urPX nopatch linux-2.4.26/arch/s390x/defconfig linux/arch/s390x/defconfig
+--- linux-2.4.26/arch/s390x/defconfig Fri Feb 20 10:07:26 2004
++++ linux/arch/s390x/defconfig Sat Apr 17 02:13:55 2004
+@@ -47,6 +47,7 @@
+ CONFIG_SYSCTL=y
+ CONFIG_KCORE_ELF=y
+ CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_ELF_AOUT is not set
+ # CONFIG_BINFMT_MISC is not set
+ # CONFIG_PROCESS_DEBUG is not set
+ CONFIG_PFAULT=y
+diff -urPX nopatch linux-2.4.26/arch/sh/config.in linux/arch/sh/config.in
+--- linux-2.4.26/arch/sh/config.in Fri Feb 20 10:07:26 2004
++++ linux/arch/sh/config.in Sat Apr 17 02:13:55 2004
+@@ -283,6 +283,9 @@
+ A.OUT CONFIG_KCORE_AOUT" ELF
+ fi
+ bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
++if [ "$CONFIG_BINFMT_ELF" != "n" ]; then
++ bool ' ELF binaries with a.out format interpreters or a.out libraries' CONFIG_BINFMT_ELF_AOUT
++fi
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+
+ bool 'Select task to kill on out of memory condition' CONFIG_OOM_KILLER
+diff -urPX nopatch linux-2.4.26/arch/sh/defconfig linux/arch/sh/defconfig
+--- linux-2.4.26/arch/sh/defconfig Fri Feb 20 10:07:26 2004
++++ linux/arch/sh/defconfig Sat Apr 17 02:13:55 2004
+@@ -48,6 +48,7 @@
+ CONFIG_KCORE_ELF=y
+ # CONFIG_KCORE_AOUT is not set
+ CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_ELF_AOUT is not set
+ # CONFIG_BINFMT_MISC is not set
+
+ #
+diff -urPX nopatch linux-2.4.26/arch/sparc/config.in linux/arch/sparc/config.in
+--- linux-2.4.26/arch/sparc/config.in Fri Feb 20 10:07:26 2004
++++ linux/arch/sparc/config.in Sat Apr 17 02:13:55 2004
+@@ -74,6 +74,9 @@
+ fi
+ tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
+ bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
++if [ "$CONFIG_BINFMT_ELF" != "n" ]; then
++ bool ' ELF binaries with a.out format interpreters or a.out libraries' CONFIG_BINFMT_ELF_AOUT
++fi
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+ bool 'SunOS binary emulation' CONFIG_SUNOS_EMUL
+ bool 'Select task to kill on out of memory condition' CONFIG_OOM_KILLER
+diff -urPX nopatch linux-2.4.26/arch/sparc/defconfig linux/arch/sparc/defconfig
+--- linux-2.4.26/arch/sparc/defconfig Sat Apr 17 02:10:25 2004
++++ linux/arch/sparc/defconfig Sat Apr 17 02:13:55 2004
+@@ -49,9 +49,10 @@
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ CONFIG_SYSCTL=y
+ CONFIG_KCORE_ELF=y
+-CONFIG_BINFMT_AOUT=y
++# CONFIG_BINFMT_AOUT is not set
+ CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=m
++# CONFIG_BINFMT_ELF_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
+ CONFIG_SUNOS_EMUL=y
+ # CONFIG_OOM_KILLER is not set
+
+diff -urPX nopatch linux-2.4.26/arch/sparc64/config.in linux/arch/sparc64/config.in
+--- linux-2.4.26/arch/sparc64/config.in Fri Feb 20 10:07:26 2004
++++ linux/arch/sparc64/config.in Sat Apr 17 02:13:55 2004
+@@ -77,6 +77,9 @@
+ bool ' Kernel support for 32-bit (ie. SunOS) a.out binaries' CONFIG_BINFMT_AOUT32
+ fi
+ bool 'Kernel support for 64-bit ELF binaries' CONFIG_BINFMT_ELF
++if [ "$CONFIG_BINFMT_ELF" != "n" ]; then
++ bool ' ELF binaries with a.out format interpreters or a.out libraries' CONFIG_BINFMT_ELF_AOUT
++fi
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+ bool 'SunOS binary emulation' CONFIG_SUNOS_EMUL
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+diff -urPX nopatch linux-2.4.26/arch/sparc64/defconfig linux/arch/sparc64/defconfig
+--- linux-2.4.26/arch/sparc64/defconfig Sat Apr 17 02:10:26 2004
++++ linux/arch/sparc64/defconfig Sat Apr 17 02:13:55 2004
+@@ -56,7 +56,8 @@
+ CONFIG_BINFMT_ELF32=y
+ # CONFIG_BINFMT_AOUT32 is not set
+ CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=m
++# CONFIG_BINFMT_ELF_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
+ # CONFIG_SUNOS_EMUL is not set
+ CONFIG_SOLARIS_EMUL=m
+ # CONFIG_OOM_KILLER is not set
+diff -urPX nopatch linux-2.4.26/arch/x86_64/config.in linux/arch/x86_64/config.in
+--- linux-2.4.26/arch/x86_64/config.in Sat Apr 17 02:10:26 2004
++++ linux/arch/x86_64/config.in Sat Apr 17 02:13:55 2004
+@@ -118,6 +118,9 @@
+ fi
+ #tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
+ bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
++if [ "$CONFIG_BINFMT_ELF" != "n" ]; then
++ bool ' ELF binaries with a.out format interpreters or a.out libraries' CONFIG_BINFMT_ELF_AOUT
++fi
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+
+ bool 'Power Management support' CONFIG_PM
+diff -urPX nopatch linux-2.4.26/arch/x86_64/defconfig linux/arch/x86_64/defconfig
+--- linux-2.4.26/arch/x86_64/defconfig Sat Apr 17 02:10:26 2004
++++ linux/arch/x86_64/defconfig Sat Apr 17 02:13:55 2004
+@@ -67,6 +67,7 @@
+ CONFIG_SYSCTL=y
+ CONFIG_KCORE_ELF=y
+ CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_ELF_AOUT is not set
+ # CONFIG_BINFMT_MISC is not set
+ CONFIG_PM=y
+ CONFIG_IA32_EMULATION=y
+diff -urPX nopatch linux-2.4.26/fs/binfmt_elf.c linux/fs/binfmt_elf.c
+--- linux-2.4.26/fs/binfmt_elf.c Sat Apr 17 02:10:31 2004
++++ linux/fs/binfmt_elf.c Sat Apr 17 02:13:55 2004
+@@ -9,6 +9,7 @@
+ * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com).
+ */
+
++#include <linux/config.h>
+ #include <linux/module.h>
+
+ #include <linux/fs.h>
+@@ -43,7 +44,9 @@
+ #include <linux/elf.h>
+
+ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
++#ifdef CONFIG_BINFMT_ELF_AOUT
+ static int load_elf_library(struct file*);
++#endif
+ static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int);
+ extern int dump_fpu (struct pt_regs *, elf_fpregset_t *);
+ extern void dump_thread(struct pt_regs *, struct user *);
+@@ -73,8 +76,14 @@
+ #define ELF_PAGEOFFSET(_v) ((_v) & (ELF_MIN_ALIGN-1))
+ #define ELF_PAGEALIGN(_v) (((_v) + ELF_MIN_ALIGN - 1) & ~(ELF_MIN_ALIGN - 1))
+
+-static struct linux_binfmt elf_format = {
+- NULL, THIS_MODULE, load_elf_binary, load_elf_library, elf_core_dump, ELF_EXEC_PAGESIZE
++static struct linux_binfmt elf_format = {
++ NULL, THIS_MODULE, load_elf_binary,
++#ifdef CONFIG_BINFMT_ELF_AOUT
++ load_elf_library,
++#else
++ NULL,
++#endif
++ elf_core_dump, ELF_EXEC_PAGESIZE
+ };
+
+ #define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE)
+@@ -369,6 +378,7 @@
+ return error;
+ }
+
++#ifdef CONFIG_BINFMT_ELF_AOUT
+ static unsigned long load_aout_interp(struct exec * interp_ex,
+ struct file * interpreter)
+ {
+@@ -413,6 +423,7 @@
+ out:
+ return elf_entry;
+ }
++#endif
+
+ /*
+ * These are the functions used to load ELF style executables and shared
+@@ -420,7 +431,9 @@
+ */
+
+ #define INTERPRETER_NONE 0
++#ifdef CONFIG_BINFMT_ELF_AOUT
+ #define INTERPRETER_AOUT 1
++#endif
+ #define INTERPRETER_ELF 2
+
+
+@@ -444,7 +457,9 @@
+ struct elfhdr elf_ex;
+ struct elfhdr interp_elf_ex;
+ struct exec interp_ex;
++#ifdef CONFIG_BINFMT_ELF_AOUT
+ char passed_fileno[6];
++#endif
+ struct files_struct *files;
+
+ /* Get the exec-header */
+@@ -556,6 +571,7 @@
+
+ /* Some simple consistency checks for the interpreter */
+ if (elf_interpreter) {
++#ifdef CONFIG_BINFMT_ELF_AOUT
+ interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
+
+ /* Now figure out which format our binary is */
+@@ -563,6 +579,9 @@
+ (N_MAGIC(interp_ex) != ZMAGIC) &&
+ (N_MAGIC(interp_ex) != QMAGIC))
+ interpreter_type = INTERPRETER_ELF;
++#else
++ interpreter_type = INTERPRETER_ELF;
++#endif
+
+ if (memcmp(interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
+ interpreter_type &= ~INTERPRETER_ELF;
+@@ -571,6 +590,7 @@
+ if (!interpreter_type)
+ goto out_free_dentry;
+
++#ifdef CONFIG_BINFMT_ELF_AOUT
+ /* Make sure only one type was selected */
+ if ((interpreter_type & INTERPRETER_ELF) &&
+ interpreter_type != INTERPRETER_ELF) {
+@@ -578,6 +598,7 @@
+ // printk(KERN_WARNING "ELF: Ambiguous type, using ELF\n");
+ interpreter_type = INTERPRETER_ELF;
+ }
++#endif
+ /* Verify the interpreter has a valid arch */
+ if ((interpreter_type == INTERPRETER_ELF) &&
+ !elf_check_arch(&interp_elf_ex))
+@@ -590,6 +611,7 @@
+ /* OK, we are done with that, now set up the arg stuff,
+ and then start this sucker up */
+
++#ifdef CONFIG_BINFMT_ELF_AOUT
+ if (!bprm->sh_bang) {
+ char * passed_p;
+
+@@ -605,6 +627,7 @@
+ }
+ }
+ }
++#endif
+
+ /* Flush all traces of the currently running executable */
+ retval = flush_old_exec(bprm);
+@@ -721,10 +744,12 @@
+ end_data += load_bias;
+
+ if (elf_interpreter) {
++#ifdef CONFIG_BINFMT_ELF_AOUT
+ if (interpreter_type == INTERPRETER_AOUT)
+ elf_entry = load_aout_interp(&interp_ex,
+ interpreter);
+ else
++#endif
+ elf_entry = load_elf_interp(&interp_elf_ex,
+ interpreter,
+ &interp_load_addr);
+@@ -743,7 +768,9 @@
+
+ kfree(elf_phdata);
+
++#ifdef CONFIG_BINFMT_ELF_AOUT
+ if (interpreter_type != INTERPRETER_AOUT)
++#endif
+ sys_close(elf_exec_fileno);
+
+ set_binfmt(&elf_format);
+@@ -757,10 +784,14 @@
+ &elf_ex,
+ load_addr, load_bias,
+ interp_load_addr,
++#ifdef CONFIG_BINFMT_ELF_AOUT
+ (interpreter_type == INTERPRETER_AOUT ? 0 : 1));
+ /* N.B. passed_fileno might not be initialized? */
+ if (interpreter_type == INTERPRETER_AOUT)
+ current->mm->arg_start += strlen(passed_fileno) + 1;
++#else
++ 1);
++#endif
+ current->mm->start_brk = current->mm->brk = elf_brk;
+ current->mm->end_code = end_code;
+ current->mm->start_code = start_code;
+@@ -838,9 +869,9 @@
+ goto out;
+ }
+
++#ifdef CONFIG_BINFMT_ELF_AOUT
+ /* This is really simpleminded and specialized - we are loading an
+ a.out library that is given an ELF header. */
+-
+ static int load_elf_library(struct file *file)
+ {
+ struct elf_phdr *elf_phdata;
+@@ -911,6 +942,7 @@
+ out:
+ return error;
+ }
++#endif
+
+ /*
+ * Note that some platforms still use traditional core dumps and not
+diff -urPX nopatch linux-2.4.26/fs/exec.c linux/fs/exec.c
+--- linux-2.4.26/fs/exec.c Fri Feb 20 10:07:36 2004
++++ linux/fs/exec.c Sat Apr 17 02:13:55 2004
+@@ -109,6 +109,7 @@
+ */
+ asmlinkage long sys_uselib(const char * library)
+ {
++#if defined(CONFIG_BINFMT_AOUT) || defined(CONFIG_BINFMT_ELF_AOUT)
+ struct file * file;
+ struct nameidata nd;
+ int error;
+@@ -155,6 +156,9 @@
+ exit:
+ path_release(&nd);
+ goto out;
++#else
++ return -ENOSYS;
++#endif
+ }
+
+ /*
diff --git a/target/linux/generic-2.4/patches/109-ipsec_nat_traversal.patch b/target/linux/generic-2.4/patches/109-ipsec_nat_traversal.patch
new file mode 100644
index 0000000000..fc4c29d27e
--- /dev/null
+++ b/target/linux/generic-2.4/patches/109-ipsec_nat_traversal.patch
@@ -0,0 +1,140 @@
+packaging/utils/nattpatch 2.4
+--- linux/include/net/sock.h 2002/02/06 15:25:10 1.1
++++ linux/include/net/sock.h 2002/05/22 12:14:56
+@@ -488,7 +488,13 @@
+ } bictcp;
+ };
+
+-
++#if 1
++#define UDP_OPT_IN_SOCK 1
++struct udp_opt {
++ __u32 esp_in_udp;
++};
++#endif
++
+ /*
+ * This structure really needs to be cleaned up.
+ * Most of it is for TCP, and not used by any of
+@@ -655,6 +661,9 @@
+ #if defined(CONFIG_SPX) || defined (CONFIG_SPX_MODULE)
+ struct spx_opt af_spx;
+ #endif /* CONFIG_SPX */
++#if 1
++ struct udp_opt af_udp;
++#endif
+
+ } tp_pinfo;
+
+--- linux/net/Config.in.orig Fri Feb 9 14:34:13 2001
++++ linux/net/Config.in Thu Feb 22 19:40:08 2001
+@@ -88,3 +88,5 @@
+ endmenu
+
++bool 'IPSEC NAT-Traversal' CONFIG_IPSEC_NAT_TRAVERSAL
++
+ endmenu
+--- linux/net/ipv4/udp.c.1 Wed Jan 28 15:57:05 2004
++++ linux/net/ipv4/udp.c Wed Jan 28 15:58:56 2004
+@@ -787,6 +787,9 @@
+
+ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
+ {
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++ struct udp_opt *tp = &(sk->tp_pinfo.af_udp);
++#endif
+ /*
+ * Charge it to the socket, dropping if the queue is full.
+ */
+@@ -804,6 +807,40 @@
+ }
+ #endif
+
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++ if (tp->esp_in_udp) {
++ /*
++ * Set skb->sk and xmit packet to ipsec_rcv.
++ *
++ * If ret != 0, ipsec_rcv refused the packet (not ESPinUDP),
++ * restore skb->sk and fall back to sock_queue_rcv_skb
++ */
++ struct inet_protocol *esp = NULL;
++
++#if defined(CONFIG_KLIPS) && !defined(CONFIG_KLIPS_MODULE)
++ /* optomize only when we know it is statically linked */
++ extern struct inet_protocol esp_protocol;
++ esp = &esp_protocol;
++#else
++ for (esp = (struct inet_protocol *)inet_protos[IPPROTO_ESP & (MAX_INET_PROTOS - 1)];
++ (esp) && (esp->protocol != IPPROTO_ESP);
++ esp = esp->next);
++#endif
++
++ if (esp && esp->handler) {
++ struct sock *sav_sk = skb->sk;
++ skb->sk = sk;
++ if (esp->handler(skb) == 0) {
++ skb->sk = sav_sk;
++ /*not sure we might count ESPinUDP as UDP...*/
++ UDP_INC_STATS_BH(UdpInDatagrams);
++ return 0;
++ }
++ skb->sk = sav_sk;
++ }
++ }
++#endif
++
+ if (sock_queue_rcv_skb(sk,skb)<0) {
+ UDP_INC_STATS_BH(UdpInErrors);
+ IP_INC_STATS_BH(IpInDiscards);
+@@ -1027,13 +1064,49 @@
+ return len;
+ }
+
++static int udp_setsockopt(struct sock *sk, int level, int optname,
++ char *optval, int optlen)
++{
++ struct udp_opt *tp = &(sk->tp_pinfo.af_udp);
++ int val;
++ int err = 0;
++
++ if (level != SOL_UDP)
++ return ip_setsockopt(sk, level, optname, optval, optlen);
++
++ if(optlen<sizeof(int))
++ return -EINVAL;
++
++ if (get_user(val, (int *)optval))
++ return -EFAULT;
++
++ lock_sock(sk);
++
++ switch(optname) {
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++#ifndef UDP_ESPINUDP
++#define UDP_ESPINUDP 100
++#endif
++ case UDP_ESPINUDP:
++ tp->esp_in_udp = val;
++ break;
++#endif
++ default:
++ err = -ENOPROTOOPT;
++ break;
++ }
++
++ release_sock(sk);
++ return err;
++}
++
+ struct proto udp_prot = {
+ name: "UDP",
+ close: udp_close,
+ connect: udp_connect,
+ disconnect: udp_disconnect,
+ ioctl: udp_ioctl,
+- setsockopt: ip_setsockopt,
++ setsockopt: udp_setsockopt,
+ getsockopt: ip_getsockopt,
+ sendmsg: udp_sendmsg,
+ recvmsg: udp_recvmsg,
diff --git a/target/linux/generic-2.4/patches/110-netdev_random_core.patch b/target/linux/generic-2.4/patches/110-netdev_random_core.patch
new file mode 100644
index 0000000000..784b65e41c
--- /dev/null
+++ b/target/linux/generic-2.4/patches/110-netdev_random_core.patch
@@ -0,0 +1,296 @@
+diff -urN linux-2.4.26-pre5/Documentation/Configure.help linux-2.4.26-pre5-netdev-core/Documentation/Configure.help
+--- linux-2.4.26-pre5/Documentation/Configure.help Sat Mar 20 10:08:18 2004
++++ linux-2.4.26-pre5-netdev-core/Documentation/Configure.help Sun Mar 21 10:16:14 2004
+@@ -10419,6 +10419,20 @@
+
+ If you don't know what to use this for, you don't need it.
+
++Allow Net Devices to contribute to /dev/random
++CONFIG_NET_RANDOM
++ If you say Y here, network device interrupts will contribute to the
++ kernel entropy pool. Normally, block devices and some other devices
++ feed the pool. Some systems, such as those that are headless or diskless,
++ need additional entropy sources. Some people, however, feel that network
++ devices should not contribute to /dev/random because an external attacker
++ could observe incoming packets in an attempt to learn the entropy pool's
++ state. If you say N, no network device will contribute entropy.
++
++ If you believe there is a chance of your network packets being observed
++ and you doubt the security of the entropy pool's one-way hash, do not
++ enable this. If unsure, say N.
++
+ Ethertap network tap (OBSOLETE)
+ CONFIG_ETHERTAP
+ If you say Y here (and have said Y to "Kernel/User network link
+diff -urN linux-2.4.26-pre5/drivers/net/Config.in linux-2.4.26-pre5-netdev-core/drivers/net/Config.in
+--- linux-2.4.26-pre5/drivers/net/Config.in Sat Mar 20 10:08:18 2004
++++ linux-2.4.26-pre5-netdev-core/drivers/net/Config.in Sun Mar 21 10:16:14 2004
+@@ -8,6 +8,7 @@
+ tristate 'Bonding driver support' CONFIG_BONDING
+ tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER
+ tristate 'Universal TUN/TAP device driver support' CONFIG_TUN
++bool 'Allow Net Devices to contribute to /dev/random' CONFIG_NET_RANDOM
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Ethertap network tap (OBSOLETE)' CONFIG_ETHERTAP
+ fi
+diff -urN linux-2.4.26-pre5/include/asm-alpha/signal.h linux-2.4.26-pre5-netdev-core/include/asm-alpha/signal.h
+--- linux-2.4.26-pre5/include/asm-alpha/signal.h Sat Dec 1 18:27:14 2001
++++ linux-2.4.26-pre5-netdev-core/include/asm-alpha/signal.h Sun Mar 21 10:16:14 2004
+@@ -121,7 +121,14 @@
+ #define SA_PROBE SA_ONESHOT
+ #define SA_SAMPLE_RANDOM SA_RESTART
+ #define SA_SHIRQ 0x40000000
++
++#ifdef CONFIG_NET_RANDOM
++#define SA_NET_RANDOM SA_SAMPLE_RANDOM
++#else
++#define SA_NET_RANDOM 0
+ #endif
++
++#endif /* __KERNEL__ */
+
+ #define SIG_BLOCK 1 /* for blocking signals */
+ #define SIG_UNBLOCK 2 /* for unblocking signals */
+diff -urN linux-2.4.26-pre5/include/asm-arm/signal.h linux-2.4.26-pre5-netdev-core/include/asm-arm/signal.h
+--- linux-2.4.26-pre5/include/asm-arm/signal.h Sat Sep 13 07:57:29 2003
++++ linux-2.4.26-pre5-netdev-core/include/asm-arm/signal.h Sun Mar 21 10:16:14 2004
+@@ -125,7 +125,14 @@
+ #define SA_PROBE 0x80000000
+ #define SA_SAMPLE_RANDOM 0x10000000
+ #define SA_SHIRQ 0x04000000
++
++#ifdef CONFIG_NET_RANDOM
++#define SA_NET_RANDOM SA_SAMPLE_RANDOM
++#else
++#define SA_NET_RANDOM 0
+ #endif
++
++#endif /* __KERNEL__ */
+
+ #define SIG_BLOCK 0 /* for blocking signals */
+ #define SIG_UNBLOCK 1 /* for unblocking signals */
+diff -urN linux-2.4.26-pre5/include/asm-cris/signal.h linux-2.4.26-pre5-netdev-core/include/asm-cris/signal.h
+--- linux-2.4.26-pre5/include/asm-cris/signal.h Sat Dec 1 18:27:14 2001
++++ linux-2.4.26-pre5-netdev-core/include/asm-cris/signal.h Sun Mar 21 10:16:14 2004
+@@ -120,7 +120,14 @@
+ #define SA_PROBE SA_ONESHOT
+ #define SA_SAMPLE_RANDOM SA_RESTART
+ #define SA_SHIRQ 0x04000000
++
++#ifdef CONFIG_NET_RANDOM
++#define SA_NET_RANDOM SA_SAMPLE_RANDOM
++#else
++#define SA_NET_RANDOM 0
+ #endif
++
++#endif /* __KERNEL__ */
+
+ #define SIG_BLOCK 0 /* for blocking signals */
+ #define SIG_UNBLOCK 1 /* for unblocking signals */
+diff -urN linux-2.4.26-pre5/include/asm-i386/signal.h linux-2.4.26-pre5-netdev-core/include/asm-i386/signal.h
+--- linux-2.4.26-pre5/include/asm-i386/signal.h Sun Mar 21 00:00:43 2004
++++ linux-2.4.26-pre5-netdev-core/include/asm-i386/signal.h Sun Mar 21 10:16:14 2004
+@@ -119,7 +119,14 @@
+ #define SA_PROBE SA_ONESHOT
+ #define SA_SAMPLE_RANDOM SA_RESTART
+ #define SA_SHIRQ 0x04000000
++
++#ifdef CONFIG_NET_RANDOM
++#define SA_NET_RANDOM SA_SAMPLE_RANDOM
++#else
++#define SA_NET_RANDOM 0
+ #endif
++
++#endif /* __KERNEL__ */
+
+ #define SIG_BLOCK 0 /* for blocking signals */
+ #define SIG_UNBLOCK 1 /* for unblocking signals */
+diff -urN linux-2.4.26-pre5/include/asm-ia64/signal.h linux-2.4.26-pre5-netdev-core/include/asm-ia64/signal.h
+--- linux-2.4.26-pre5/include/asm-ia64/signal.h Sat Mar 20 10:08:20 2004
++++ linux-2.4.26-pre5-netdev-core/include/asm-ia64/signal.h Sun Mar 21 10:16:14 2004
+@@ -117,6 +117,12 @@
+ #define SA_SHIRQ 0x04000000
+ #define SA_PERCPU_IRQ 0x02000000
+
++#ifdef CONFIG_NET_RANDOM
++#define SA_NET_RANDOM SA_SAMPLE_RANDOM
++#else
++#define SA_NET_RANDOM 0
++#endif
++
+ #endif /* __KERNEL__ */
+
+ #define SIG_BLOCK 0 /* for blocking signals */
+diff -urN linux-2.4.26-pre5/include/asm-m68k/signal.h linux-2.4.26-pre5-netdev-core/include/asm-m68k/signal.h
+--- linux-2.4.26-pre5/include/asm-m68k/signal.h Fri Feb 20 07:38:33 2004
++++ linux-2.4.26-pre5-netdev-core/include/asm-m68k/signal.h Sun Mar 21 10:16:14 2004
+@@ -116,7 +116,14 @@
+ #define SA_PROBE SA_ONESHOT
+ #define SA_SAMPLE_RANDOM SA_RESTART
+ #define SA_SHIRQ 0x04000000
++
++#ifdef CONFIG_NET_RANDOM
++#define SA_NET_RANDOM SA_SAMPLE_RANDOM
++#else
++#define SA_NET_RANDOM 0
+ #endif
++
++#endif /* __KERNEL__ */
+
+ #define SIG_BLOCK 0 /* for blocking signals */
+ #define SIG_UNBLOCK 1 /* for unblocking signals */
+diff -urN linux-2.4.26-pre5/include/asm-mips/signal.h linux-2.4.26-pre5-netdev-core/include/asm-mips/signal.h
+--- linux-2.4.26-pre5/include/asm-mips/signal.h Sat Sep 13 07:57:31 2003
++++ linux-2.4.26-pre5-netdev-core/include/asm-mips/signal.h Sun Mar 21 10:16:14 2004
+@@ -111,6 +111,12 @@
+ #define SA_SAMPLE_RANDOM SA_RESTART
+ #define SA_SHIRQ 0x02000000
+
++#ifdef CONFIG_NET_RANDOM
++#define SA_NET_RANDOM SA_SAMPLE_RANDOM
++#else
++#define SA_NET_RANDOM 0
++#endif
++
+ #endif /* __KERNEL__ */
+
+ #define SIG_BLOCK 1 /* for blocking signals */
+diff -urN linux-2.4.26-pre5/include/asm-mips64/signal.h linux-2.4.26-pre5-netdev-core/include/asm-mips64/signal.h
+--- linux-2.4.26-pre5/include/asm-mips64/signal.h Sat Sep 13 07:57:32 2003
++++ linux-2.4.26-pre5-netdev-core/include/asm-mips64/signal.h Sun Mar 21 10:16:14 2004
+@@ -119,6 +119,12 @@
+ #define SA_SAMPLE_RANDOM SA_RESTART
+ #define SA_SHIRQ 0x02000000
+
++#ifdef CONFIG_NET_RANDOM
++#define SA_NET_RANDOM SA_SAMPLE_RANDOM
++#else
++#define SA_NET_RANDOM 0
++#endif
++
+ #endif /* __KERNEL__ */
+
+ #define SIG_BLOCK 1 /* for blocking signals */
+diff -urN linux-2.4.26-pre5/include/asm-parisc/signal.h linux-2.4.26-pre5-netdev-core/include/asm-parisc/signal.h
+--- linux-2.4.26-pre5/include/asm-parisc/signal.h Sun Jan 11 18:48:21 2004
++++ linux-2.4.26-pre5-netdev-core/include/asm-parisc/signal.h Sun Mar 21 10:16:14 2004
+@@ -100,6 +100,12 @@
+ #define SA_SAMPLE_RANDOM SA_RESTART
+ #define SA_SHIRQ 0x04000000
+
++#ifdef CONFIG_NET_RANDOM
++#define SA_NET_RANDOM SA_SAMPLE_RANDOM
++#else
++#define SA_NET_RANDOM 0
++#endif
++
+ #endif /* __KERNEL__ */
+
+ #define SIG_BLOCK 0 /* for blocking signals */
+diff -urN linux-2.4.26-pre5/include/asm-ppc/signal.h linux-2.4.26-pre5-netdev-core/include/asm-ppc/signal.h
+--- linux-2.4.26-pre5/include/asm-ppc/signal.h Sat Sep 13 07:57:32 2003
++++ linux-2.4.26-pre5-netdev-core/include/asm-ppc/signal.h Sun Mar 21 10:16:14 2004
+@@ -111,6 +111,13 @@
+ #define SA_PROBE SA_ONESHOT
+ #define SA_SAMPLE_RANDOM SA_RESTART
+ #define SA_SHIRQ 0x04000000
++
++#ifdef CONFIG_NET_RANDOM
++#define SA_NET_RANDOM SA_SAMPLE_RANDOM
++#else
++#define SA_NET_RANDOM 0
++#endif
++
+ #endif /* __KERNEL__ */
+
+ #define SIG_BLOCK 0 /* for blocking signals */
+diff -urN linux-2.4.26-pre5/include/asm-s390/signal.h linux-2.4.26-pre5-netdev-core/include/asm-s390/signal.h
+--- linux-2.4.26-pre5/include/asm-s390/signal.h Fri Feb 20 07:38:34 2004
++++ linux-2.4.26-pre5-netdev-core/include/asm-s390/signal.h Sun Mar 21 10:16:14 2004
+@@ -129,7 +129,14 @@
+ #define SA_SHIRQ 0x04000000
+ #define SA_DOPATHGROUP 0x00100000
+ #define SA_FORCE 0x00200000
++
++#ifdef CONFIG_NET_RANDOM
++#define SA_NET_RANDOM SA_SAMPLE_RANDOM
++#else
++#define SA_NET_RANDOM 0
+ #endif
++
++#endif /* __KERNEL__ */
+
+ #define SIG_BLOCK 0 /* for blocking signals */
+ #define SIG_UNBLOCK 1 /* for unblocking signals */
+diff -urN linux-2.4.26-pre5/include/asm-s390x/signal.h linux-2.4.26-pre5-netdev-core/include/asm-s390x/signal.h
+--- linux-2.4.26-pre5/include/asm-s390x/signal.h Fri Feb 20 07:38:34 2004
++++ linux-2.4.26-pre5-netdev-core/include/asm-s390x/signal.h Sun Mar 21 10:16:14 2004
+@@ -129,7 +129,14 @@
+ #define SA_SHIRQ 0x04000000
+ #define SA_DOPATHGROUP 0x00100000
+ #define SA_FORCE 0x00200000
++
++#ifdef CONFIG_NET_RANDOM
++#define SA_NET_RANDOM SA_SAMPLE_RANDOM
++#else
++#define SA_NET_RANDOM 0
+ #endif
++
++#endif /* __KERNEL__ */
+
+ #define SIG_BLOCK 0 /* for blocking signals */
+ #define SIG_UNBLOCK 1 /* for unblocking signals */
+diff -urN linux-2.4.26-pre5/include/asm-sh/signal.h linux-2.4.26-pre5-netdev-core/include/asm-sh/signal.h
+--- linux-2.4.26-pre5/include/asm-sh/signal.h Sat Dec 1 18:27:13 2001
++++ linux-2.4.26-pre5-netdev-core/include/asm-sh/signal.h Sun Mar 21 10:16:14 2004
+@@ -107,7 +107,14 @@
+ #define SA_PROBE SA_ONESHOT
+ #define SA_SAMPLE_RANDOM SA_RESTART
+ #define SA_SHIRQ 0x04000000
++
++#ifdef CONFIG_NET_RANDOM
++#define SA_NET_RANDOM SA_SAMPLE_RANDOM
++#else
++#define SA_NET_RANDOM 0
+ #endif
++
++#endif /* __KERNEL__ */
+
+ #define SIG_BLOCK 0 /* for blocking signals */
+ #define SIG_UNBLOCK 1 /* for unblocking signals */
+diff -urN linux-2.4.26-pre5/include/asm-sparc/signal.h linux-2.4.26-pre5-netdev-core/include/asm-sparc/signal.h
+--- linux-2.4.26-pre5/include/asm-sparc/signal.h Sat Dec 1 18:27:14 2001
++++ linux-2.4.26-pre5-netdev-core/include/asm-sparc/signal.h Sun Mar 21 10:16:14 2004
+@@ -176,7 +176,14 @@
+ #define SA_PROBE SA_ONESHOT
+ #define SA_SAMPLE_RANDOM SA_RESTART
+ #define SA_STATIC_ALLOC 0x80
++
++#ifdef CONFIG_NET_RANDOM
++#define SA_NET_RANDOM SA_SAMPLE_RANDOM
++#else
++#define SA_NET_RANDOM 0
+ #endif
++
++#endif /* __KERNEL__ */
+
+ /* Type of a signal handler. */
+ #ifdef __KERNEL__
+diff -urN linux-2.4.26-pre5/include/asm-sparc64/signal.h linux-2.4.26-pre5-netdev-core/include/asm-sparc64/signal.h
+--- linux-2.4.26-pre5/include/asm-sparc64/signal.h Sat Dec 1 18:27:14 2001
++++ linux-2.4.26-pre5-netdev-core/include/asm-sparc64/signal.h Sun Mar 21 10:16:14 2004
+@@ -192,7 +192,14 @@
+ #define SA_PROBE SA_ONESHOT
+ #define SA_SAMPLE_RANDOM SA_RESTART
+ #define SA_STATIC_ALLOC 0x80
++
++#ifdef CONFIG_NET_RANDOM
++#define SA_NET_RANDOM SA_SAMPLE_RANDOM
++#else
++#define SA_NET_RANDOM 0
+ #endif
++
++#endif /* __KERNEL__ */
+
+ /* Type of a signal handler. */
+ #ifdef __KERNEL__
diff --git a/target/linux/generic-2.4/patches/112-bridging_performance.patch b/target/linux/generic-2.4/patches/112-bridging_performance.patch
new file mode 100644
index 0000000000..c5d86349d4
--- /dev/null
+++ b/target/linux/generic-2.4/patches/112-bridging_performance.patch
@@ -0,0 +1,22 @@
+--- linux.old/net/core/dev.c 2005-07-05 16:42:36.000000000 +0200
++++ linux.dev/net/core/dev.c 2005-07-08 19:32:46.000000000 +0200
+@@ -1289,6 +1289,19 @@
+ local_irq_save(flags);
+
+ netdev_rx_stat[this_cpu].total++;
++
++#ifdef CONFIG_BRIDGE
++ /* Optimisation for framebursting (allow interleaving of pkts by
++ * immediately processing the rx pkt instead of Qing the pkt and deferring
++ * the processing). Only optimise for bridging and guard against non
++ * TASKLET based netif_rx calls.
++ */
++ if (!in_irq() && (skb->dev->br_port != NULL) && br_handle_frame_hook != NULL) {
++ local_irq_restore(flags);
++ return netif_receive_skb(skb);
++ }
++#endif
++
+ if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
+ if (queue->input_pkt_queue.qlen) {
+ if (queue->throttle)
diff --git a/target/linux/generic-2.4/patches/113-even_more_gcc4_stuff.patch b/target/linux/generic-2.4/patches/113-even_more_gcc4_stuff.patch
new file mode 100644
index 0000000000..1b98717882
--- /dev/null
+++ b/target/linux/generic-2.4/patches/113-even_more_gcc4_stuff.patch
@@ -0,0 +1,367 @@
+diff -Nur linux.old/arch/mips/kernel/mips_ksyms.c linux.dev/arch/mips/kernel/mips_ksyms.c
+--- linux.old/arch/mips/kernel/mips_ksyms.c 2004-02-18 14:36:30.000000000 +0100
++++ linux.dev/arch/mips/kernel/mips_ksyms.c 2005-10-24 14:21:53.702396250 +0200
+@@ -30,6 +30,10 @@
+ #include <asm/floppy.h>
+ #endif
+
++asmlinkage long long __ashldi3 (long long, int);
++asmlinkage long long __ashrdi3 (long long, int);
++asmlinkage long long __lshrdi3 (long long, int);
++asmlinkage long long __muldi3 (long long, long long);
+ extern void *__bzero(void *__s, size_t __count);
+ extern long __strncpy_from_user_nocheck_asm(char *__to,
+ const char *__from, long __len);
+@@ -78,6 +82,13 @@
+ EXPORT_SYMBOL_NOVERS(__strnlen_user_asm);
+
+
++/* Compiler stuff */
++EXPORT_SYMBOL_NOVERS(__ashldi3);
++EXPORT_SYMBOL_NOVERS(__ashrdi3);
++EXPORT_SYMBOL_NOVERS(__lshrdi3);
++EXPORT_SYMBOL_NOVERS(__muldi3);
++
++
+ /* Networking helper routines. */
+ EXPORT_SYMBOL(csum_partial_copy);
+
+diff -Nur linux.old/arch/mips/lib/Makefile linux.dev/arch/mips/lib/Makefile
+--- linux.old/arch/mips/lib/Makefile 2004-02-18 14:36:30.000000000 +0100
++++ linux.dev/arch/mips/lib/Makefile 2005-10-24 14:21:53.774400750 +0200
+@@ -9,7 +9,8 @@
+ obj-y += csum_partial.o csum_partial_copy.o \
+ promlib.o rtc-std.o rtc-no.o memcpy.o \
+ memset.o watch.o strlen_user.o \
+- strncpy_user.o strnlen_user.o
++ strncpy_user.o strnlen_user.o \
++ ashldi3.o ashrdi3.o lshrdi3.o muldi3.o
+
+ export-objs := rtc-std.o rtc-no.o
+
+diff -Nur linux.old/arch/mips/lib/ashldi3.c linux.dev/arch/mips/lib/ashldi3.c
+--- linux.old/arch/mips/lib/ashldi3.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/lib/ashldi3.c 2005-10-24 14:21:53.774400750 +0200
+@@ -0,0 +1,62 @@
++/* ashrdi3.c extracted from gcc-2.95.2/libgcc2.c which is: */
++/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
++
++This file is part of GNU CC.
++
++GNU CC 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.
++
++GNU CC 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 GNU CC; see the file COPYING. If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA. */
++
++#define BITS_PER_UNIT 8
++
++typedef int SItype __attribute__ ((mode (SI)));
++typedef unsigned int USItype __attribute__ ((mode (SI)));
++typedef int DItype __attribute__ ((mode (DI)));
++typedef int word_type __attribute__ ((mode (__word__)));
++
++struct DIstruct {SItype high, low;};
++
++typedef union
++{
++ struct DIstruct s;
++ DItype ll;
++} DIunion;
++
++DItype
++__ashldi3 (DItype u, word_type b)
++{
++ DIunion w;
++ word_type bm;
++ DIunion uu;
++
++ if (b == 0)
++ return u;
++
++ uu.ll = u;
++
++ bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
++ if (bm <= 0)
++ {
++ w.s.low = 0;
++ w.s.high = (USItype)uu.s.low << -bm;
++ }
++ else
++ {
++ USItype carries = (USItype)uu.s.low >> bm;
++ w.s.low = (USItype)uu.s.low << b;
++ w.s.high = ((USItype)uu.s.high << b) | carries;
++ }
++
++ return w.ll;
++}
+diff -Nur linux.old/arch/mips/lib/ashrdi3.c linux.dev/arch/mips/lib/ashrdi3.c
+--- linux.old/arch/mips/lib/ashrdi3.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/lib/ashrdi3.c 2005-10-24 14:21:53.774400750 +0200
+@@ -0,0 +1,63 @@
++/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
++/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
++
++This file is part of GNU CC.
++
++GNU CC 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.
++
++GNU CC 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 GNU CC; see the file COPYING. If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA. */
++
++#define BITS_PER_UNIT 8
++
++typedef int SItype __attribute__ ((mode (SI)));
++typedef unsigned int USItype __attribute__ ((mode (SI)));
++typedef int DItype __attribute__ ((mode (DI)));
++typedef int word_type __attribute__ ((mode (__word__)));
++
++struct DIstruct {SItype high, low;};
++
++typedef union
++{
++ struct DIstruct s;
++ DItype ll;
++} DIunion;
++
++DItype
++__ashrdi3 (DItype u, word_type b)
++{
++ DIunion w;
++ word_type bm;
++ DIunion uu;
++
++ if (b == 0)
++ return u;
++
++ uu.ll = u;
++
++ bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
++ if (bm <= 0)
++ {
++ /* w.s.high = 1..1 or 0..0 */
++ w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
++ w.s.low = uu.s.high >> -bm;
++ }
++ else
++ {
++ USItype carries = (USItype)uu.s.high << bm;
++ w.s.high = uu.s.high >> b;
++ w.s.low = ((USItype)uu.s.low >> b) | carries;
++ }
++
++ return w.ll;
++}
+diff -Nur linux.old/arch/mips/lib/lshrdi3.c linux.dev/arch/mips/lib/lshrdi3.c
+--- linux.old/arch/mips/lib/lshrdi3.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/lib/lshrdi3.c 2005-10-24 14:21:53.774400750 +0200
+@@ -0,0 +1,62 @@
++/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
++/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
++
++This file is part of GNU CC.
++
++GNU CC 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.
++
++GNU CC 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 GNU CC; see the file COPYING. If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA. */
++
++#define BITS_PER_UNIT 8
++
++typedef int SItype __attribute__ ((mode (SI)));
++typedef unsigned int USItype __attribute__ ((mode (SI)));
++typedef int DItype __attribute__ ((mode (DI)));
++typedef int word_type __attribute__ ((mode (__word__)));
++
++struct DIstruct {SItype high, low;};
++
++typedef union
++{
++ struct DIstruct s;
++ DItype ll;
++} DIunion;
++
++DItype
++__lshrdi3 (DItype u, word_type b)
++{
++ DIunion w;
++ word_type bm;
++ DIunion uu;
++
++ if (b == 0)
++ return u;
++
++ uu.ll = u;
++
++ bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
++ if (bm <= 0)
++ {
++ w.s.high = 0;
++ w.s.low = (USItype)uu.s.high >> -bm;
++ }
++ else
++ {
++ USItype carries = (USItype)uu.s.high << bm;
++ w.s.high = (USItype)uu.s.high >> b;
++ w.s.low = ((USItype)uu.s.low >> b) | carries;
++ }
++
++ return w.ll;
++}
+diff -Nur linux.old/arch/mips/lib/muldi3.c linux.dev/arch/mips/lib/muldi3.c
+--- linux.old/arch/mips/lib/muldi3.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/lib/muldi3.c 2005-10-24 14:21:53.774400750 +0200
+@@ -0,0 +1,63 @@
++/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and
++ gcc-2.7.2.3/longlong.h which is: */
++/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
++
++This file is part of GNU CC.
++
++GNU CC 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.
++
++GNU CC 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 GNU CC; see the file COPYING. If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA. */
++
++#define BITS_PER_UNIT 8
++
++#define umul_ppmm(w1, w0, u, v) \
++ __asm__ ("multu %2,%3" \
++ : "=l" ((USItype)(w0)), \
++ "=h" ((USItype)(w1)) \
++ : "d" ((USItype)(u)), \
++ "d" ((USItype)(v)))
++
++#define __umulsidi3(u, v) \
++ ({DIunion __w; \
++ umul_ppmm (__w.s.high, __w.s.low, u, v); \
++ __w.ll; })
++
++typedef int SItype __attribute__ ((mode (SI)));
++typedef unsigned int USItype __attribute__ ((mode (SI)));
++typedef int DItype __attribute__ ((mode (DI)));
++typedef int word_type __attribute__ ((mode (__word__)));
++
++struct DIstruct {SItype high, low;};
++
++typedef union
++{
++ struct DIstruct s;
++ DItype ll;
++} DIunion;
++
++DItype
++__muldi3 (DItype u, DItype v)
++{
++ DIunion w;
++ DIunion uu, vv;
++
++ uu.ll = u,
++ vv.ll = v;
++
++ w.ll = __umulsidi3 (uu.s.low, vv.s.low);
++ w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
++ + (USItype) uu.s.high * (USItype) vv.s.low);
++
++ return w.ll;
++}
+diff -Nur linux.old/fs/cifs/cifsfs.c linux.dev/fs/cifs/cifsfs.c
+--- linux.old/fs/cifs/cifsfs.c 2005-10-24 13:48:27.599659000 +0200
++++ linux.dev/fs/cifs/cifsfs.c 2005-10-24 14:25:06.526447000 +0200
+@@ -50,8 +50,6 @@
+ static struct quotactl_ops cifs_quotactl_ops;
+ #endif
+
+-extern struct file_system_type cifs_fs_type;
+-
+ int cifsFYI = 0;
+ int cifsERROR = 1;
+ int traceSMB = 0;
+diff -Nur linux.old/include/asm-mips/uaccess.h linux.dev/include/asm-mips/uaccess.h
+--- linux.old/include/asm-mips/uaccess.h 2005-01-19 15:10:12.000000000 +0100
++++ linux.dev/include/asm-mips/uaccess.h 2005-10-24 14:11:48.563214250 +0200
+@@ -149,7 +149,7 @@
+ * Returns zero on success, or -EFAULT on error.
+ */
+ #define put_user(x,ptr) \
+- __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
++ __put_user_check((x),(ptr),sizeof(*(ptr)))
+
+ /*
+ * get_user: - Get a simple variable from user space.
+@@ -169,7 +169,7 @@
+ * On error, the variable @x is set to zero.
+ */
+ #define get_user(x,ptr) \
+- __get_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
++ __get_user_check((x),(ptr),sizeof(*(ptr)))
+
+ /*
+ * __put_user: - Write a simple value into user space, with less checking.
+@@ -191,7 +191,7 @@
+ * Returns zero on success, or -EFAULT on error.
+ */
+ #define __put_user(x,ptr) \
+- __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
++ __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
+
+ /*
+ * __get_user: - Get a simple variable from user space, with less checking.
+@@ -214,7 +214,7 @@
+ * On error, the variable @x is set to zero.
+ */
+ #define __get_user(x,ptr) \
+- __get_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
++ __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+
+ struct __large_struct { unsigned long buf[100]; };
+ #define __m(x) (*(struct __large_struct *)(x))
+@@ -232,7 +232,7 @@
+ #define __get_user_nocheck(x,ptr,size) \
+ ({ \
+ long __gu_err = 0; \
+- __typeof(*(ptr)) __gu_val = 0; \
++ __typeof(*(ptr)) __gu_val = (__typeof(*(ptr))) 0; \
+ long __gu_addr; \
+ __gu_addr = (long) (ptr); \
+ switch (size) { \
diff --git a/target/linux/generic-2.4/patches/200-i4l.patch b/target/linux/generic-2.4/patches/200-i4l.patch
new file mode 100644
index 0000000000..c9833e2a30
--- /dev/null
+++ b/target/linux/generic-2.4/patches/200-i4l.patch
@@ -0,0 +1,20247 @@
+diff -rNu linux-2.4.29.old/Documentation/isdn/CREDITS linux-2.4.29/Documentation/isdn/CREDITS
+--- linux-2.4.29.old/Documentation/isdn/CREDITS 2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/CREDITS 2005-03-22 15:06:50.246454160 +0100
+@@ -37,7 +37,7 @@
+ Andreas Kool (akool@Kool.f.EUnet.de)
+ For contribution of the isdnlog/isdnrep-tool
+
+-Pedro Roque Marques (pedro_m@yahoo.com)
++Pedro Roque Marques (roque@di.fc.ul.pt)
+ For lot of new ideas and the pcbit driver.
+
+ Eberhard Moenkeberg (emoenke@gwdg.de)
+diff -rNu linux-2.4.29.old/Documentation/isdn/HiSax.cert linux-2.4.29/Documentation/isdn/HiSax.cert
+--- linux-2.4.29.old/Documentation/isdn/HiSax.cert 2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/HiSax.cert 2005-03-22 15:06:50.264451424 +0100
+@@ -68,6 +68,8 @@
+ drivers/isdn/hisax/elsa.c
+ drivers/isdn/hisax/diva.c
+ drivers/isdn/hisax/hfc_pci.c
++drivers/isdn/hisax/hfc_usbr.c
++drivers/isdn/hisax/hfc_usb.c
+
+ Please send any changes, bugfixes and patches to me rather than implementing
+ them directly into the HiSax sources.
+diff -rNu linux-2.4.29.old/Documentation/isdn/INTERFACE linux-2.4.29/Documentation/isdn/INTERFACE
+--- linux-2.4.29.old/Documentation/isdn/INTERFACE 2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/INTERFACE 2005-03-22 15:06:50.288447776 +0100
+@@ -1,4 +1,4 @@
+-$Id: INTERFACE,v 1.1.4.1 2001/11/20 14:19:33 kai Exp $
++$Id: INTERFACE,v 1.17 2002/01/31 13:26:35 keil Exp $
+
+ Description of the Interface between Linklevel and Hardwarelevel
+ of isdn4linux:
+@@ -399,7 +399,7 @@
+ protocol-Id is one of the constants ISDN_PROTO_L3...
+ parm.fax = Pointer to T30_s fax struct. (fax usage only)
+
+- ISDN_CMD_GETL2: (currently unused)
++ ISDN_CMD_GETL3: (currently unused)
+
+ With this command, the HL-driver is told to return the current
+ setting of the Layer-3-protocol.
+@@ -781,3 +781,22 @@
+ arg = channel-number, locally to the driver. (starting with 0)
+ parm = unused.
+
++ ISDN_STAT_ALERT:
++
++ With this call, the HL-driver signals the receive of an ALERTING message to the LL.
++
++ Parameter:
++ driver = driver-Id
++ command = ISDN_STAT_ALERT
++ arg = channel-number, locally to the driver. (starting with 0)
++
++ ISDN_STAT_PROCEED:
++
++ With this call, the HL-driver signals the receive of an CALL PROCEEDING message
++ to the LL.
++
++ Parameter:
++ driver = driver-Id
++ command = ISDN_STAT_PROCEED
++ arg = channel-number, locally to the driver. (starting with 0)
++
+diff -rNu linux-2.4.29.old/Documentation/isdn/INTERFACE.fax linux-2.4.29/Documentation/isdn/INTERFACE.fax
+--- linux-2.4.29.old/Documentation/isdn/INTERFACE.fax 2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/INTERFACE.fax 2005-03-22 15:06:50.312444128 +0100
+@@ -1,4 +1,4 @@
+-$Id: INTERFACE.fax,v 1.1.4.1 2001/11/20 14:19:33 kai Exp $
++$Id: INTERFACE.fax,v 1.2 2000/08/06 09:22:50 armin Exp $
+
+
+ Description of the fax-subinterface between linklevel and hardwarelevel of
+diff -rNu linux-2.4.29.old/Documentation/isdn/README linux-2.4.29/Documentation/isdn/README
+--- linux-2.4.29.old/Documentation/isdn/README 2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/README 2005-03-22 15:06:50.340439872 +0100
+@@ -278,6 +278,12 @@
+ 1 = Add CPN to FCON message on
+ Bit 2: 0 = Add CDN to RING/FCON message off
+ 1 = Add CDN to RING/FCON message on
++ Bit 3: 0 = Do not signal RINGING
++ 1 = Signal RINGING if ALERT was received
++ Bit 4: 0 = Do not signal PROCEEDING
++ 1 = Signal PROCEEDING if CALL PROCEEDING
++ was received
++
+
+ Last but not least a (at the moment fairly primitive) device to request
+ the line-status (/dev/isdninfo) is made available.
+diff -rNu linux-2.4.29.old/Documentation/isdn/README.HiSax linux-2.4.29/Documentation/isdn/README.HiSax
+--- linux-2.4.29.old/Documentation/isdn/README.HiSax 2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/README.HiSax 2005-03-22 15:06:50.372435008 +0100
+@@ -41,10 +41,9 @@
+ ELSA Quickstep 3000PCI
+ ELSA PCMCIA
+ ITK ix1-micro Rev.2
+-Eicon Diva 2.0 ISA and PCI (S0 and U interface, no PRO version)
+-Eicon Diva 2.01 ISA and PCI
+-Eicon Diva 2.02 PCI
+-Eicon Diva Piccola
++Eicon.Diehl Diva 2.0 ISA and PCI (S0 and U interface, no PRO version)
++Eicon.Diehl Diva 2.01 ISA and PCI
++Eicon.Diehl Diva Piccola
+ ASUSCOM NETWORK INC. ISDNLink 128K PC adapter (order code I-IN100-ST-D)
+ Dynalink IS64PH (OEM version of ASUSCOM NETWORK INC. ISDNLink 128K adapter)
+ PCBIT-DP (OEM version of ASUSCOM NETWORK INC. ISDNLink)
+@@ -53,7 +52,6 @@
+ Sedlbauer Speed Star/Speed Star2 (PCMCIA)
+ Sedlbauer ISDN-Controller PC/104
+ USR Sportster internal TA (compatible Stollmann tina-pp V3)
+-USR internal TA PCI
+ ith Kommunikationstechnik GmbH MIC 16 ISA card
+ Traverse Technologie NETjet PCI S0 card and NETspider U card
+ Ovislink ISDN sc100-p card (NETjet driver)
+@@ -68,14 +66,14 @@
+ HFC-PCI based cards
+ Winbond W6692 based cards
+ HFC-S+, HFC-SP/PCMCIA cards
+-formula-n enternow
+-Gerdes Power ISDN
++HFC-USB ISDN TAs
+
+ Note: PCF, PCF-Pro: up to now, only the ISDN part is supported
+ PCC-8: not tested yet
+ Eicon.Diehl Diva U interface not tested
+
+ If you know other passive cards with the Siemens chipset, please let me know.
++To use the PNP cards you need the isapnptools.
+ You can combine any card, if there is no conflict between the resources
+ (io, mem, irq).
+
+@@ -91,15 +89,8 @@
+ modules. It is included in the normal "make [menu]config" target at the
+ kernel. Don't forget it, especially to select the right D-channel protocol.
+
+-Please note: In older versions of the HiSax driver, all PnP cards
+-needed to be configured with isapnp and worked only with the HiSax
+-driver used as a module.
+-
+-In the current version, HiSax will automatically use the in-kernel
+-ISAPnP support, provided you selected it during kernel configuration
+-(CONFIG_ISAPNP), if you don't give the io=, irq= command line parameters.
+-
+-The affected card types are: 4,7,12,14,19,27-30
++Please note: All PnP cards need to be configured with isapnp and will work
++only with the HiSax driver used as a module.
+
+ a) when built as a module
+ -------------------------
+@@ -200,8 +191,6 @@
+ 37 HFC 2BDS0 S+, SP irq,io
+ 38 NETspider U PCI card none
+ 39 HFC 2BDS0 SP/PCMCIA irq,io (set with cardmgr)
+- 40 hotplug interface
+- 41 Formula-n enter:now PCI none
+
+ At the moment IRQ sharing is only possible with PCI cards. Please make sure
+ that your IRQ is free and enabled for ISA use.
+@@ -227,13 +216,6 @@
+ (IO 1 (BASE 0x0180))
+ modprobe hisax type=4 protocol=2 irq=10 io0=0x580 io1=0x180
+
+- In the current version of HiSax, you can instead simply use
+-
+- modprobe hisax type=4 protocol=2
+-
+- if you configured your kernel for ISAPnP. Don't run isapnp in
+- this case!
+-
+ 6. Teles 16.3, Euro ISDN, I/O base 280 hex, IRQ 12 and
+ Teles 16.0, 1TR6, IRQ 5, Memory d0000 hex
+ modprobe hisax type=3,1 protocol=2,1 io=0x280 mem=0,0xd0000
+@@ -314,9 +296,7 @@
+ 36 W6692 based PCI cards none
+ 37 HFC 2BDS0 S+,SP/PCMCIA ONLY WORKS AS A MODULE !
+ 38 NETspider U PCI card none
+- 39 HFC 2BDS0 SP/PCMCIA ONLY WORKS AS A MODULE !
+- 40 hotplug interface ONLY WORKS AS A MODULE !
+- 41 Formula-n enter:now PCI none
++
+
+ Running the driver
+ ------------------
+diff -rNu linux-2.4.29.old/Documentation/isdn/README.act2000 linux-2.4.29/Documentation/isdn/README.act2000
+--- linux-2.4.29.old/Documentation/isdn/README.act2000 2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/README.act2000 2005-03-22 15:06:50.388432576 +0100
+@@ -1,4 +1,4 @@
+-$Id: README.act2000,v 1.1.4.1 2001/11/20 14:19:33 kai Exp $
++$Id: README.act2000,v 1.3 2000/08/06 09:22:51 armin Exp $
+
+ This document describes the ACT2000 driver for the
+ IBM Active 2000 ISDN card.
+diff -rNu linux-2.4.29.old/Documentation/isdn/README.audio linux-2.4.29/Documentation/isdn/README.audio
+--- linux-2.4.29.old/Documentation/isdn/README.audio 2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/README.audio 2005-03-22 15:06:50.404430144 +0100
+@@ -1,4 +1,4 @@
+-$Id: README.audio,v 1.1.4.1 2001/11/20 14:19:33 kai Exp $
++$Id: README.audio,v 1.8 1999/07/11 17:17:29 armin Exp $
+
+ ISDN subsystem for Linux.
+ Description of audio mode.
+diff -rNu linux-2.4.29.old/Documentation/isdn/README.eicon linux-2.4.29/Documentation/isdn/README.eicon
+--- linux-2.4.29.old/Documentation/isdn/README.eicon 2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/README.eicon 2005-03-22 15:06:50.479418744 +0100
+@@ -1,4 +1,4 @@
+-$Id: README.eicon,v 1.1.4.1 2001/11/20 14:19:33 kai Exp $
++$Id: README.eicon,v 1.10 2000/08/13 12:19:15 armin Exp $
+
+ (c) 1999,2000 Armin Schindler (mac@melware.de)
+ (c) 1999,2000 Cytronics & Melware (info@melware.de)
+diff -rNu linux-2.4.29.old/Documentation/isdn/README.hysdn linux-2.4.29/Documentation/isdn/README.hysdn
+--- linux-2.4.29.old/Documentation/isdn/README.hysdn 2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/README.hysdn 2005-03-22 15:06:50.522412208 +0100
+@@ -1,4 +1,4 @@
+-$Id: README.hysdn,v 1.1.4.1 2001/11/20 14:19:33 kai Exp $
++$Id: README.hysdn,v 1.3.6.1 2001/02/10 14:41:19 kai Exp $
+ The hysdn driver has been written by
+ by Werner Cornelius (werner@isdn4linux.de or werner@titro.de)
+ for Hypercope GmbH Aachen Germany. Hypercope agreed to publish this driver
+diff -rNu linux-2.4.29.old/Documentation/isdn/README.icn linux-2.4.29/Documentation/isdn/README.icn
+--- linux-2.4.29.old/Documentation/isdn/README.icn 2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/README.icn 2005-03-22 15:06:50.550407952 +0100
+@@ -1,4 +1,4 @@
+-$Id: README.icn,v 1.1.4.1 2001/11/20 14:19:33 kai Exp $
++$Id: README.icn,v 1.7 2000/08/06 09:22:51 armin Exp $
+
+ You can get the ICN-ISDN-card from:
+
+diff -rNu linux-2.4.29.old/Documentation/isdn/README.pcbit linux-2.4.29/Documentation/isdn/README.pcbit
+--- linux-2.4.29.old/Documentation/isdn/README.pcbit 2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/README.pcbit 2005-03-22 15:06:50.567405368 +0100
+@@ -37,4 +37,4 @@
+ regards,
+ Pedro.
+
+-<pedro_m@yahoo.com>
++<roque@di.fc.ul.pt>
+diff -rNu linux-2.4.29.old/Documentation/isdn/abcext_kernel.help linux-2.4.29/Documentation/isdn/abcext_kernel.help
+--- linux-2.4.29.old/Documentation/isdn/abcext_kernel.help 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/abcext_kernel.help 2005-03-22 15:06:50.600400352 +0100
+@@ -0,0 +1,166 @@
++
++ISDN-ABC-DW Extension
++CONFIG_ISDN_WITH_ABC
++ These are many brand new Options and Features for the
++ ISDN SUBSYSTEM. Including Logical Device bindings,
++ Compression and other good stuff for Optimizing your
++ ISDN System.
++
++ To Use this Extensions you MUST HAVE THE NEWEST
++ ISDN4K-UTILS. You must have Version 3.1-Beta6 or
++ higher. Elsewhere you can not configure this Extensions.
++
++ WARNING ! THIS STUF IS NOT PRODUCTION RELEASE THE
++ FUNCTION ARE UNDER DEVELOPMENT. This ist BETA-CODE.
++ You can use it at you Own Risk.
++
++ For more Information on these Extensions take a look at
++ "linux/Documentation/isdn/dw-abc-extension-howto.txt or
++ Online at the Web "http://www.mediatronix.de/i4l/index.html"
++
++ Please Report Bugs to "mario@mediatronix.de" or
++ "delefw@isdn4linux.de"
++
++D-Channel-Callback with Channel in use check
++CONFIG_ISDN_WITH_ABC_CALLB
++ When a Interface is declared as an Callback Interface,
++ the Interface is checking that the other Side is not
++ Calling on the same time before the Interface is Dialing.
++
++ See "linux/Documentation/isdn/dw-abc-extension-howto.txt"
++ for more Information
++
++ In most case answer with "Yes" when you have Callback devices,
++ otherwise leave it "No"
++
++Outgoing-EAZ-Support
++CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++ Enables the Feature to Define an other EAZ or MSN for
++ Outgoing calls on an Interface.
++
++ See "linux/Documentation/isdn/dw-abc-extension-howto.txt"
++ for more Information
++
++Least Cost Router Support
++CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++ This is the final Kernel Code for configuring an Least
++ Cost Router Softwarebased. The other Job is to do the
++ action in ISDNLOG. You need the ISDNLOG to use this
++ function. Currently the ISDNLOG have not the Support for
++ this Option.
++ So in most situations let the Option off.
++
++TCP keepalive detect and response
++CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE
++ This Option works only with the TCP/IP V4. It enables
++ the Function that ISDN Devices are Answering TCP_KEEPALIVE Pakets
++ localy. So that TCP KEEPALIVE Pakets not longer takes the Line
++ open.
++
++Drop frames Sourceadresse is not Interfaceadress
++CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR
++ This Option works only with the TCP/IP V4. It will allow only
++ the Transmitt of Pakets where the Sourceadresse is the Interface
++ adress. It is usefull when you have Lines with Dynamic IP.
++
++ See "linux/Documentation/isdn/dw-abc-extension-howto.txt"
++ for more Information
++
++Receive do not reset the Hanguptimer
++CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++ When you activate this option than the reiceive of pakets do
++ not reset the Hanguptimer. It is very usefull because if the
++ Paket vor your Network your Network generate an Response and
++ the Transmit is reseting the HUPTIMER. But when the Paket is
++ Rejected at your firewall your network generate no Response
++ and no Sendtraffic is generated. So in this case there is no
++ need to Reset the Huptimer because you have only received Data.
++ With that option only Transmitted Data/Pakets will reset the
++ HUPTIMER.
++
++Support of (device-channel) and Binding Groups
++CONFIG_ISDN_WITH_ABC_ICALL_BIND
++ This Option enables the Feature to Bind logical ISDN Interfaces
++ to an prefered ISDN Card or ISDN Card plus Channel. So you have
++ the Chance to keep Channels exclusively for one (or more)
++ Connection. Very usefull when you have more channels and Use
++ Calling Line Identification, because you can organize that your
++ call is going out over the Line with the right EAZ for the CLI.
++
++Skip channel if used external (Dial Only)
++CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
++ When you have more than One ISDN Card in your System and you
++ will Dialout with an Interface you can become the Situation
++ that an External Device such a Telephone or Fax is Using the
++ B-Channels. Normaly ISDN4Linux does not detect this Situation
++ and dial everytime of the "External Busy" line out. With this
++ Option Enabled the I4L will detect that he can not dialout on
++ This Card and dial over the next Card out.
++
++ See "linux/Documentation/isdn/dw-abc-extension-howto.txt"
++ for more Information
++
++Interface autodisable if Config error
++CONFIG_ISDN_WITH_ABC_CONN_ERROR
++ This Option will detect an Device which generate Telephone
++ Cost but does not Function correctly because there are
++ Configerrors on one of the Site. In this Situation the
++ Interface will be marked as Unsuably for some time to do
++ not call every time this Site.
++
++ See "linux/Documentation/isdn/dw-abc-extension-howto.txt"
++ for more Information
++
++UDP-Info-Support
++CONFIG_ISDN_WITH_ABC_UDP_CHECK
++ This is the Mainoption to Enable or Disable the UDP
++ Info Support. An Option to Controll ISDN-Interfaces
++ Remotely. For this very Complex thing take a look at
++
++ "linux/Documentation/isdn/dw-abc-extension-howto.txt"
++ for more Information.
++
++UDP Hangup Support
++CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP
++
++ Sorry no more Information!
++
++ See "linux/Documentation/isdn/dw-abc-extension-howto.txt"
++ for more Information
++
++UDP Dial Support
++CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL
++
++ Sorry no more Information!
++
++ See "linux/Documentation/isdn/dw-abc-extension-howto.txt"
++ for more Information
++
++Limit on the line frames to two
++CONFIG_ISDN_WITH_ABC_FRAME_LIMIT
++
++ This Option enables support for sending only 2 Pakets on
++ the Fly to the ISDN Driver. It is very usefull when you
++ will use the new RAW-IP Compression. Because of sending
++ Only 2 Pakets on the Fly makes the risk of overflowing
++ the ISDN Driver very smaller.
++
++ See "linux/Documentation/isdn/dw-abc-extension-howto.txt"
++ for more Information
++
++Compression with RAWIP and X75I
++CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
++
++ With this Option you have the ability to make Datacompression
++ on RAW-IP Lines. It is function on HDLC and X75I Connection,
++ but the Prefered L2-Protocol for Compression is X75I because
++ the HDLC Protocol have no Errorcorrection.
++
++ To Use this Option YOU MUST HAVE ENABLED THE OPTION:
++ Support synchronous PPP
++ and must load after loading the main isdndrivers the
++ Modul "isdn_bsdcomp".
++
++ See "linux/Documentation/isdn/dw-abc-extension-howto.txt"
++ for more Information
++
+diff -rNu linux-2.4.29.old/drivers/isdn/Config.in linux-2.4.29/drivers/isdn/Config.in
+--- linux-2.4.29.old/drivers/isdn/Config.in 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/Config.in 2005-03-22 15:06:44.259364336 +0100
+@@ -4,11 +4,9 @@
+
+ # only included if CONFIG_ISDN != n
+
+-define_bool CONFIG_ISDN_BOOL y
+ if [ "$CONFIG_INET" != "n" ]; then
+ bool ' Support synchronous PPP' CONFIG_ISDN_PPP
+ if [ "$CONFIG_ISDN_PPP" != "n" ]; then
+- dep_bool ' PPP filtering for ISDN' CONFIG_IPPP_FILTER $CONFIG_FILTER
+ bool ' Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ
+ bool ' Support generic MP (RFC 1717)' CONFIG_ISDN_MPP
+ dep_tristate ' Support BSD compression' CONFIG_ISDN_PPP_BSDCOMP $CONFIG_ISDN
+@@ -23,6 +21,30 @@
+ fi
+
+ mainmenu_option next_comment
++comment 'ISDN abc-dw-extension'
++bool 'Enable isdn-abc-dw-extension' CONFIG_ISDN_WITH_ABC
++if [ "$CONFIG_ISDN_WITH_ABC" != "n" ]; then
++ bool ' Use D-Channel-Callback with Channel in use check' CONFIG_ISDN_WITH_ABC_CALLB
++ bool ' Enable Outgoing-EAZ-Support' CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++ bool ' Enable LCR-Support (need isdnlog)' CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++ bool ' RX dont reset hanguptimeout' CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++ if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
++ bool ' Enable UDP-Info-Support' CONFIG_ISDN_WITH_ABC_UDP_CHECK
++ if [ "$CONFIG_ISDN_WITH_ABC_UDP_CHECK" != "n" ]; then
++ bool ' Enable Hangup-Support with UDP-INFO' CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP
++ bool ' Enable Dial-Support with UDP-INFO' CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL
++ fi
++ fi
++
++ bool ' Skip channel if used external (dial only)' CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
++ bool ' Support interface-auto-disable if config-error' CONFIG_ISDN_WITH_ABC_CONN_ERROR
++ if [ "$CONFIG_ISDN_PPP" != "n" ]; then
++ bool ' Enable Compression with rawip and x75i' CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
++ fi
++fi
++endmenu
++
++mainmenu_option next_comment
+ comment 'ISDN feature submodules'
+ dep_tristate 'isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN
+ dep_tristate 'Support isdn diversion services' CONFIG_ISDN_DIVERSION $CONFIG_ISDN
+@@ -34,7 +56,6 @@
+ comment 'Passive ISDN cards'
+ dep_tristate 'HiSax SiemensChipSet driver support' CONFIG_ISDN_DRV_HISAX $CONFIG_ISDN
+ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
+- define_bool CONFIG_ISDN_HISAX y
+ comment ' D-channel protocol features'
+ bool ' HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO
+ if [ "$CONFIG_HISAX_EURO" != "n" ]; then
+@@ -45,31 +66,28 @@
+ fi
+ bool ' HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
+ bool ' HiSax Support for US NI1' CONFIG_HISAX_NI1
+- int ' Maximum number of cards supported by HiSax' CONFIG_HISAX_MAX_CARDS 8
+ comment ' HiSax supported cards'
+- if [ "$CONFIG_ISA" != "n" ]; then
+- bool ' Teles 16.0/8.0' CONFIG_HISAX_16_0
+- bool ' Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
+- bool ' AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1
+- bool ' ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2
+- bool ' ASUSCOM ISA cards' CONFIG_HISAX_ASUSCOM
+- bool ' TELEINT cards' CONFIG_HISAX_TELEINT
+- bool ' HFC-S based cards' CONFIG_HISAX_HFCS
+- bool ' USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
+- bool ' MIC card' CONFIG_HISAX_MIC
+- bool ' Siemens I-Surf card' CONFIG_HISAX_ISURF
+- bool ' HST Saphir card' CONFIG_HISAX_HSTSAPHIR
+- fi
++ bool ' Teles 16.0/8.0' CONFIG_HISAX_16_0
++ bool ' Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
+ bool ' Teles PCI' CONFIG_HISAX_TELESPCI
+ bool ' Teles S0Box' CONFIG_HISAX_S0BOX
++ bool ' AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1
+ bool ' AVM PnP/PCI (Fritz!PnP/PCI)' CONFIG_HISAX_FRITZPCI
+ bool ' AVM A1 PCMCIA (Fritz)' CONFIG_HISAX_AVM_A1_PCMCIA
+ bool ' Elsa cards' CONFIG_HISAX_ELSA
++ bool ' ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2
+ bool ' Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA
++ bool ' ASUSCOM ISA cards' CONFIG_HISAX_ASUSCOM
++ bool ' TELEINT cards' CONFIG_HISAX_TELEINT
++ bool ' HFC-S based cards' CONFIG_HISAX_HFCS
+ bool ' Sedlbauer cards' CONFIG_HISAX_SEDLBAUER
++ bool ' USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
++ bool ' MIC card' CONFIG_HISAX_MIC
+ bool ' NETjet card' CONFIG_HISAX_NETJET
+ bool ' NETspider U card' CONFIG_HISAX_NETJET_U
+ bool ' Niccy PnP/PCI card' CONFIG_HISAX_NICCY
++ bool ' Siemens I-Surf card' CONFIG_HISAX_ISURF
++ bool ' HST Saphir card' CONFIG_HISAX_HSTSAPHIR
+ bool ' Telekom A4T card' CONFIG_HISAX_BKM_A4T
+ bool ' Scitel Quadro card' CONFIG_HISAX_SCT_QUADRO
+ bool ' Gazel cards' CONFIG_HISAX_GAZEL
+@@ -78,20 +96,27 @@
+ bool ' HFC-S+, HFC-SP, HFC-PCMCIA cards' CONFIG_HISAX_HFC_SX
+ if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
+ # bool ' TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
+- bool ' Formula-n enter:now PCI card' CONFIG_HISAX_ENTERNOW_PCI
+ if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
+ bool ' Am7930' CONFIG_HISAX_AMD7930
+ fi
+ fi
+ bool ' HiSax debugging' CONFIG_HISAX_DEBUG
+
+- dep_tristate 'Sedlbauer PCMCIA cards' CONFIG_HISAX_SEDLBAUER_CS $CONFIG_ISDN_DRV_HISAX $CONFIG_PCMCIA
+- dep_tristate 'ELSA PCMCIA MicroLink cards' CONFIG_HISAX_ELSA_CS $CONFIG_ISDN_DRV_HISAX $CONFIG_PCMCIA
+- dep_tristate 'AVM A1 PCMCIA cards' CONFIG_HISAX_AVM_A1_CS $CONFIG_ISDN_DRV_HISAX $CONFIG_PCMCIA $CONFIG_HISAX_AVM_A1_PCMCIA
+- dep_tristate 'ST5481 USB ISDN modem (EXPERIMENTAL)' CONFIG_HISAX_ST5481 $CONFIG_ISDN_DRV_HISAX $CONFIG_EXPERIMENTAL
+- dep_tristate 'AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)' CONFIG_HISAX_FRITZ_PCIPNP $CONFIG_ISDN_DRV_HISAX $CONFIG_EXPERIMENTAL
+- dep_tristate 'Auerswald devices ISDN support' CONFIG_USB_AUERISDN $CONFIG_ISDN_DRV_HISAX
++ dep_tristate 'Sedlbauer PCMCIA cards' CONFIG_HISAX_SEDLBAUER_CS $CONFIG_PCMCIA
++ dep_tristate 'ELSA PCMCIA MicroLink cards' CONFIG_HISAX_ELSA_CS $CONFIG_PCMCIA
++ dep_tristate 'Colognechip HFC-USB support' CONFIG_HISAX_HFC_USB_CS $CONFIG_HISAX $CONFIG_USB
++ dep_tristate 'ST5481 USB ISDN modem (EXPERIMENTAL)' CONFIG_HISAX_ST5481 $CONFIG_HISAX $CONFIG_USB $CONFIG_EXPERIMENTAL
++ dep_tristate 'Fritz!PCIv2 support (EXPERIMENTAL)' CONFIG_HISAX_FRITZ_PCIPNP $CONFIG_HISAX $CONFIG_EXPERIMENTAL
+
++ if [ "$CONFIG_HISAX_SEDLBAUER_CS" != "n" ]; then
++ define_bool CONFIG_HISAX_SEDLBAUER y
++ fi
++ if [ "$CONFIG_HISAX_ELSA_CS" != "n" ]; then
++ define_bool CONFIG_HISAX_ELSA y
++ fi
++ if [ "$CONFIG_HISAX_HFC_USB_CS" != "n" ]; then
++ define_bool CONFIG_HISAX_HFC_USB y
++ fi
+ fi
+ endmenu
+
+diff -rNu linux-2.4.29.old/drivers/isdn/Makefile linux-2.4.29/drivers/isdn/Makefile
+--- linux-2.4.29.old/drivers/isdn/Makefile 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/Makefile 2005-03-22 15:06:44.277361600 +0100
+@@ -2,7 +2,7 @@
+
+ # The target object and module list name.
+
+-O_TARGET := vmlinux-obj.o
++O_TARGET := isdn.a
+
+ # Objects that export symbols.
+
+@@ -32,9 +32,9 @@
+
+ # Object files in subdirectories
+
+-mod-subdirs := avmb1 eicon hisax
++mod-subdirs := avmb1 eicon
+ subdir-$(CONFIG_ISDN_DIVERSION) += divert
+-subdir-$(CONFIG_ISDN_HISAX) += hisax
++subdir-$(CONFIG_ISDN_DRV_HISAX) += hisax
+ subdir-$(CONFIG_ISDN_DRV_ICN) += icn
+ subdir-$(CONFIG_ISDN_DRV_PCBIT) += pcbit
+ subdir-$(CONFIG_ISDN_DRV_SC) += sc
+diff -rNu linux-2.4.29.old/drivers/isdn/act2000/act2000.h linux-2.4.29/drivers/isdn/act2000/act2000.h
+--- linux-2.4.29.old/drivers/isdn/act2000/act2000.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/act2000/act2000.h 2005-03-22 15:06:44.103388048 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: act2000.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id$
+ *
+ * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
+ *
+@@ -178,19 +178,19 @@
+ char regname[35]; /* Name used for request_region */
+ } act2000_card;
+
+-static inline void act2000_schedule_tx(act2000_card *card)
++extern __inline__ void act2000_schedule_tx(act2000_card *card)
+ {
+ queue_task(&card->snd_tq, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+ }
+
+-static inline void act2000_schedule_rx(act2000_card *card)
++extern __inline__ void act2000_schedule_rx(act2000_card *card)
+ {
+ queue_task(&card->rcv_tq, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+ }
+
+-static inline void act2000_schedule_poll(act2000_card *card)
++extern __inline__ void act2000_schedule_poll(act2000_card *card)
+ {
+ queue_task(&card->poll_tq, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+diff -rNu linux-2.4.29.old/drivers/isdn/act2000/act2000_isa.c linux-2.4.29/drivers/isdn/act2000/act2000_isa.c
+--- linux-2.4.29.old/drivers/isdn/act2000/act2000_isa.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/act2000/act2000_isa.c 2005-03-22 15:06:44.135383184 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: act2000_isa.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id$
+ *
+ * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
+ *
+@@ -178,8 +178,7 @@
+ card->flags &= ~ACT2000_FLAGS_PVALID;
+ }
+ if (!check_region(portbase, ISA_REGION)) {
+- if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL)
+- return -EIO;
++ request_region(portbase, ACT2000_PORTLEN, card->regname);
+ card->port = portbase;
+ card->flags |= ACT2000_FLAGS_PVALID;
+ return 0;
+@@ -341,6 +340,9 @@
+ while (skb->len) {
+ if (act2000_isa_writeb(card, *(skb->data))) {
+ /* Fifo is full, but more data to send */
++#if 0
++ printk(KERN_DEBUG "act2000_isa_send: %d bytes\n", l);
++#endif
+ test_and_clear_bit(ACT2000_LOCK_TX, (void *) &card->ilock);
+ /* Schedule myself */
+ act2000_schedule_tx(card);
+@@ -363,6 +365,9 @@
+ } else
+ dev_kfree_skb(skb);
+ card->sbuf = NULL;
++#if 0
++ printk(KERN_DEBUG "act2000_isa_send: %d bytes\n", l);
++#endif
+ }
+ }
+
+diff -rNu linux-2.4.29.old/drivers/isdn/act2000/act2000_isa.h linux-2.4.29/drivers/isdn/act2000/act2000_isa.h
+--- linux-2.4.29.old/drivers/isdn/act2000/act2000_isa.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/act2000/act2000_isa.h 2005-03-22 15:06:44.152380600 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: act2000_isa.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id$
+ *
+ * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/act2000/capi.c linux-2.4.29/drivers/isdn/act2000/capi.c
+--- linux-2.4.29.old/drivers/isdn/act2000/capi.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/act2000/capi.c 2005-03-22 15:06:44.172377560 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capi.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id$
+ *
+ * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
+ * CAPI encoder/decoder
+@@ -76,6 +76,10 @@
+ {{ 0x84, 0x03}, "DISCONNECT_B3_RESP"},
+ {{ 0x86, 0x03}, "DATA_B3_RESP"},
+ {{ 0xff, 0x03}, "MANUFACTURER_RESP"},
++#if 0
++/* CAPI 2.0 */
++ {{ 0x05, 0x80}, "LISTEN_REQ (CAPI 2.0)"},
++#endif
+ #endif
+ {{ 0x00, 0x00}, NULL},
+ };
+diff -rNu linux-2.4.29.old/drivers/isdn/act2000/capi.h linux-2.4.29/drivers/isdn/act2000/capi.h
+--- linux-2.4.29.old/drivers/isdn/act2000/capi.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/act2000/capi.h 2005-03-22 15:06:44.187375280 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capi.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id$
+ *
+ * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
+ *
+@@ -294,6 +294,19 @@
+ __u16 plci;
+ __u16 info;
+ } select_b3_protocol_conf;
++#if 0
++ struct listen_req {
++ __u32 controller;
++ __u32 infomask;
++ __u32 cipmask;
++ __u32 cipmask2;
++ __u16 dummy; /* 2 Length-bytes of 2 Structs MUST always be 0!!! */
++ } listen_req;
++ struct listen_conf {
++ __u32 controller;
++ __u16 info;
++ } listen_conf;
++#else
+ struct listen_req {
+ __u8 controller;
+ __u32 infomask __attribute__ ((packed));
+@@ -304,6 +317,7 @@
+ __u8 controller;
+ __u16 info __attribute__ ((packed));
+ } listen_conf;
++#endif
+ struct data_b3_req {
+ __u16 fakencci;
+ __u16 datalen;
+@@ -330,7 +344,7 @@
+ } msg;
+ } actcapi_msg;
+
+-static inline unsigned short
++extern __inline__ unsigned short
+ actcapi_nextsmsg(act2000_card *card)
+ {
+ unsigned long flags;
+diff -rNu linux-2.4.29.old/drivers/isdn/act2000/module.c linux-2.4.29/drivers/isdn/act2000/module.c
+--- linux-2.4.29.old/drivers/isdn/act2000/module.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/act2000/module.c 2005-03-22 15:06:44.202373000 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: module.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id$
+ *
+ * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
+ *
+@@ -630,6 +630,10 @@
+ card->interface.features =
+ ISDN_FEATURE_L2_X75I |
+ ISDN_FEATURE_L2_HDLC |
++#if 0
++/* Not yet! New Firmware is on the way ... */
++ ISDN_FEATURE_L2_TRANS |
++#endif
+ ISDN_FEATURE_L3_TRANS |
+ ISDN_FEATURE_P_UNKNOWN;
+ card->interface.hl_hdrlen = 20;
+@@ -843,6 +847,39 @@
+ }
+ printk(KERN_INFO "%s unloaded\n", DRIVERNAME);
+ }
++#if 0
++#ifndef MODULE
++void
++act2000_setup(char *str, int *ints)
++{
++ int i, j, argc, port, irq, bus;
++
++ argc = ints[0];
++ i = 1;
++ if (argc)
++ while (argc) {
++ port = irq = -1;
++ bus = 0;
++ if (argc) {
++ bus = ints[i];
++ i++;
++ argc--;
++ }
++ if (argc) {
++ port = ints[i];
++ i++;
++ argc--;
++ }
++ if (argc) {
++ irq = ints[i];
++ i++;
++ argc--;
++ }
++ act2000_addcard(bus, port, irq, act_id);
++ }
++}
++#endif
++#endif
+
+ module_init(act2000_init);
+ module_exit(act2000_exit);
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/avm_cs.c linux-2.4.29/drivers/isdn/avmb1/avm_cs.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/avm_cs.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/avm_cs.c 2005-03-22 15:06:44.696297912 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: avm_cs.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: avm_cs.c,v 1.6 2001/09/24 13:22:44 kai Exp $
+ *
+ * A PCMCIA client driver for AVM B1/M1/M2
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/avmcard.h linux-2.4.29/drivers/isdn/avmb1/avmcard.h
+--- linux-2.4.29.old/drivers/isdn/avmb1/avmcard.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/avmcard.h 2005-03-22 15:06:44.711295632 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: avmcard.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: avmcard.h,v 1.12 2001/09/24 13:22:44 kai Exp $
+ *
+ * Copyright 1999 by Carsten Paeth <calle@calle.de>
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/b1.c linux-2.4.29/drivers/isdn/avmb1/b1.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/b1.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/b1.c 2005-03-22 15:06:44.733292288 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: b1.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: b1.c,v 1.26 2001/09/24 13:22:44 kai Exp $
+ *
+ * Common module for AVM B1 cards.
+ *
+@@ -20,6 +20,7 @@
+ #include <linux/kernelcapi.h>
+ #include <asm/io.h>
+ #include <linux/init.h>
++#include <linux/isdn_compat.h>
+ #include <asm/uaccess.h>
+ #include <linux/netdevice.h>
+ #include "capilli.h"
+@@ -27,7 +28,7 @@
+ #include "capicmd.h"
+ #include "capiutil.h"
+
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.26 $";
+
+ /* ------------------------------------------------------------- */
+
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/b1dma.c linux-2.4.29/drivers/isdn/avmb1/b1dma.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/b1dma.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/b1dma.c 2005-03-22 15:06:44.750289704 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: b1dma.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: b1dma.c,v 1.18 2001/09/24 13:22:44 kai Exp $
+ *
+ * Common module for AVM B1 cards that support dma with AMCC
+ *
+@@ -21,6 +21,7 @@
+ #include <linux/kernelcapi.h>
+ #include <asm/io.h>
+ #include <linux/init.h>
++#include <linux/isdn_compat.h>
+ #include <asm/uaccess.h>
+ #include <linux/netdevice.h>
+ #include "capilli.h"
+@@ -28,7 +29,11 @@
+ #include "capicmd.h"
+ #include "capiutil.h"
+
+-static char *revision = "$Revision: 1.1.4.1 $";
++#if BITS_PER_LONG != 32
++#error FIXME: driver requires 32-bit platform
++#endif
++
++static char *revision = "$Revision: 1.18 $";
+
+ /* ------------------------------------------------------------- */
+
+@@ -851,7 +856,7 @@
+ __u8 flag;
+ int len = 0;
+ char *s;
+- u_long txaddr, txlen, rxaddr, rxlen, csr;
++ __u32 txaddr, txlen, rxaddr, rxlen, csr;
+
+ len += sprintf(page+len, "%-16s %s\n", "name", card->name);
+ len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
+@@ -907,12 +912,12 @@
+ save_flags(flags);
+ cli();
+
+- txaddr = (u_long)phys_to_virt(b1dmainmeml(card->mbase+0x2c));
+- txaddr -= (u_long)card->dma->sendbuf;
++ txaddr = (__u32)phys_to_virt(b1dmainmeml(card->mbase+0x2c));
++ txaddr -= (__u32)card->dma->sendbuf;
+ txlen = b1dmainmeml(card->mbase+0x30);
+
+- rxaddr = (u_long)phys_to_virt(b1dmainmeml(card->mbase+0x24));
+- rxaddr -= (u_long)card->dma->recvbuf;
++ rxaddr = (__u32)phys_to_virt(b1dmainmeml(card->mbase+0x24));
++ rxaddr -= (__u32)card->dma->recvbuf;
+ rxlen = b1dmainmeml(card->mbase+0x28);
+
+ csr = b1dmainmeml(card->mbase+AMCC_INTCSR);
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/b1isa.c linux-2.4.29/drivers/isdn/avmb1/b1isa.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/b1isa.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/b1isa.c 2005-03-22 15:06:44.766287272 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: b1isa.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: b1isa.c,v 1.14 2001/09/24 13:22:44 kai Exp $
+ *
+ * Module for AVM B1 ISA-card.
+ *
+@@ -19,12 +19,13 @@
+ #include <linux/capi.h>
+ #include <linux/init.h>
+ #include <asm/io.h>
++#include <linux/isdn_compat.h>
+ #include "capicmd.h"
+ #include "capiutil.h"
+ #include "capilli.h"
+ #include "avmcard.h"
+
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.14 $";
+
+ /* ------------------------------------------------------------- */
+
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/b1pci.c linux-2.4.29/drivers/isdn/avmb1/b1pci.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/b1pci.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/b1pci.c 2005-03-22 15:06:44.781284992 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: b1pci.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: b1pci.c,v 1.40 2001/09/24 13:22:44 kai Exp $
+ *
+ * Module for AVM B1 PCI-card.
+ *
+@@ -21,21 +21,24 @@
+ #include <linux/capi.h>
+ #include <asm/io.h>
+ #include <linux/init.h>
++#include <linux/isdn_compat.h>
+ #include "capicmd.h"
+ #include "capiutil.h"
+ #include "capilli.h"
+ #include "avmcard.h"
+
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.40 $";
+
+ /* ------------------------------------------------------------- */
+
++#ifndef COMPAT_HAS_2_2_PCI
+ static struct pci_device_id b1pci_pci_tbl[] __initdata = {
+ { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, PCI_ANY_ID, PCI_ANY_ID },
+ { } /* Terminating entry */
+ };
+
+ MODULE_DEVICE_TABLE(pci, b1pci_pci_tbl);
++#endif
+ MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 PCI card");
+ MODULE_AUTHOR("Carsten Paeth");
+ MODULE_LICENSE("GPL");
+@@ -416,14 +419,14 @@
+ }
+ param.irq = dev->irq;
+
+- if (pci_resource_start(dev, 2)) { /* B1 PCI V4 */
++ if (pci_resource_start_io(dev, 2)) { /* B1 PCI V4 */
+ #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+ driver = &b1pciv4_driver;
+
+ pci_set_master(dev);
+ #endif
+- param.membase = pci_resource_start(dev, 0);
+- param.port = pci_resource_start(dev, 2);
++ param.membase = pci_resource_start_mem(dev, 0);
++ param.port = pci_resource_start_io(dev, 2);
+
+ printk(KERN_INFO
+ "%s: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n",
+@@ -440,7 +443,7 @@
+ }
+ } else {
+ param.membase = 0;
+- param.port = pci_resource_start(dev, 1);
++ param.port = pci_resource_start_io(dev, 1);
+
+ printk(KERN_INFO
+ "%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/b1pcmcia.c linux-2.4.29/drivers/isdn/avmb1/b1pcmcia.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/b1pcmcia.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/b1pcmcia.c 2005-03-22 15:06:44.796282712 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: b1pcmcia.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: b1pcmcia.c,v 1.17 2001/09/24 13:22:44 kai Exp $
+ *
+ * Module for AVM B1/M1/M2 PCMCIA-card.
+ *
+@@ -25,7 +25,7 @@
+ #include "capilli.h"
+ #include "avmcard.h"
+
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.17 $";
+
+ /* ------------------------------------------------------------- */
+
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/c4.c linux-2.4.29/drivers/isdn/avmb1/c4.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/c4.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/c4.c 2005-03-22 15:06:44.812280280 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: c4.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: c4.c,v 1.38 2001/09/24 13:22:44 kai Exp $
+ *
+ * Module for AVM C4 & C2 card.
+ *
+@@ -18,6 +18,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/ioport.h>
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+ #include <linux/capi.h>
+ #include <linux/kernelcapi.h>
+ #include <linux/init.h>
+@@ -29,7 +30,7 @@
+ #include "capilli.h"
+ #include "avmcard.h"
+
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.38 $";
+
+ #undef CONFIG_C4_DEBUG
+ #undef CONFIG_C4_POLLDEBUG
+@@ -38,6 +39,7 @@
+
+ static int suppress_pollack;
+
++#ifndef COMPAT_HAS_2_2_PCI
+ static struct pci_device_id c4_pci_tbl[] __initdata = {
+ { PCI_VENDOR_ID_DEC,PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4 },
+ { PCI_VENDOR_ID_DEC,PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C2 },
+@@ -45,6 +47,7 @@
+ };
+
+ MODULE_DEVICE_TABLE(pci, c4_pci_tbl);
++#endif
+ MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM C2/C4 cards");
+ MODULE_AUTHOR("Carsten Paeth");
+ MODULE_LICENSE("GPL");
+@@ -1328,9 +1331,9 @@
+ }
+ pci_set_master(dev);
+
+- param.port = pci_resource_start(dev, 1);
++ param.port = pci_resource_start_io(dev, 1);
+ param.irq = dev->irq;
+- param.membase = pci_resource_start(dev, 0);
++ param.membase = pci_resource_start_mem(dev, 0);
+
+ printk(KERN_INFO
+ "%s: PCI BIOS reports AVM-C%d at i/o %#x, irq %d, mem %#x\n",
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capi.c linux-2.4.29/drivers/isdn/avmb1/capi.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/capi.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capi.c 2005-03-22 15:06:44.849274656 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capi.c,v 1.1.4.2 2001/12/09 18:45:13 kai Exp $
++/* $Id: capi.c,v 1.59 2001/11/07 22:35:48 kai Exp $
+ *
+ * CAPI 2.0 Interface for Linux
+ *
+@@ -23,6 +23,7 @@
+ #include <linux/smp_lock.h>
+ #include <linux/timer.h>
+ #include <linux/wait.h>
++#include <linux/isdn_compat.h>
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+ #include <linux/tty.h>
+ #ifdef CONFIG_PPP
+@@ -30,6 +31,9 @@
+ #include <linux/ppp_defs.h>
+ #include <linux/if_ppp.h>
+ #undef CAPI_PPP_ON_RAW_DEVICE
++#ifdef CAPI_PPP_ON_RAW_DEVICE
++#include <linux/ppp_channel.h>
++#endif /* CAPI_PPP_ON_RAW_DEVICE */
+ #endif /* CONFIG_PPP */
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+ #include <linux/skbuff.h>
+@@ -38,14 +42,16 @@
+ #include <linux/capi.h>
+ #include <linux/kernelcapi.h>
+ #include <linux/init.h>
++#ifdef HAVE_DEVFS_FS
+ #include <linux/devfs_fs_kernel.h>
++#endif /* HAVE_DEVFS_FS */
+ #include "capiutil.h"
+ #include "capicmd.h"
+ #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
+ #include "capifs.h"
+ #endif
+
+-static char *revision = "$Revision: 1.1.4.2 $";
++static char *revision = "$Revision: 1.59 $";
+
+ MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface");
+ MODULE_AUTHOR("Carsten Paeth");
+@@ -87,10 +93,10 @@
+ struct capincci *nccip;
+ unsigned int minor;
+
+- u16 applid;
+- u32 ncci;
+- u16 datahandle;
+- u16 msgid;
++ __u16 applid;
++ __u32 ncci;
++ __u16 datahandle;
++ __u16 msgid;
+
+ struct file *file;
+ struct tty_struct *tty;
+@@ -112,16 +118,22 @@
+ /* transmit path */
+ struct datahandle_queue {
+ struct datahandle_queue *next;
+- u16 datahandle;
++ __u16 datahandle;
+ } *ackqueue;
+ int nack;
+
++#ifdef CAPI_PPP_ON_RAW_DEVICE
++ /* interface to generic ppp layer */
++ struct ppp_channel chan;
++ int chan_connected;
++ int chan_index;
++#endif
+ };
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+
+ struct capincci {
+ struct capincci *next;
+- u32 ncci;
++ __u32 ncci;
+ struct capidev *cdev;
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+ struct capiminor *minorp;
+@@ -131,8 +143,8 @@
+ struct capidev {
+ struct capidev *next;
+ struct file *file;
+- u16 applid;
+- u16 errcode;
++ __u16 applid;
++ __u16 errcode;
+ unsigned int minor;
+ unsigned userflags;
+
+@@ -156,22 +168,28 @@
+ static struct capiminor *minors = 0;
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+
++#ifdef COMPAT_HAS_kmem_cache
+ static kmem_cache_t *capidev_cachep = 0;
+ static kmem_cache_t *capincci_cachep = 0;
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+ static kmem_cache_t *capiminor_cachep = 0;
+ static kmem_cache_t *capidh_cachep = 0;
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
++#endif
+
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+ /* -------- datahandles --------------------------------------------- */
+
+-static int capincci_add_ack(struct capiminor *mp, u16 datahandle)
++int capincci_add_ack(struct capiminor *mp, __u16 datahandle)
+ {
+ struct datahandle_queue *n, **pp;
+
+ n = (struct datahandle_queue *)
++#ifdef COMPAT_HAS_kmem_cache
+ kmem_cache_alloc(capidh_cachep, GFP_ATOMIC);
++#else
++ kmalloc(sizeof(struct datahandle_queue), GFP_ATOMIC);
++#endif
+ if (!n) {
+ printk(KERN_ERR "capi: alloc datahandle failed\n");
+ return -1;
+@@ -184,7 +202,7 @@
+ return 0;
+ }
+
+-static int capiminor_del_ack(struct capiminor *mp, u16 datahandle)
++int capiminor_del_ack(struct capiminor *mp, __u16 datahandle)
+ {
+ struct datahandle_queue **pp, *p;
+
+@@ -192,7 +210,11 @@
+ if ((*pp)->datahandle == datahandle) {
+ p = *pp;
+ *pp = (*pp)->next;
++#ifdef COMPAT_HAS_kmem_cache
+ kmem_cache_free(capidh_cachep, p);
++#else
++ kfree(p);
++#endif
+ mp->nack--;
+ return 0;
+ }
+@@ -200,7 +222,7 @@
+ return -1;
+ }
+
+-static void capiminor_del_all_ack(struct capiminor *mp)
++void capiminor_del_all_ack(struct capiminor *mp)
+ {
+ struct datahandle_queue **pp, *p;
+
+@@ -208,7 +230,11 @@
+ while (*pp) {
+ p = *pp;
+ *pp = (*pp)->next;
++#ifdef COMPAT_HAS_kmem_cache
+ kmem_cache_free(capidh_cachep, p);
++#else
++ kfree(p);
++#endif
+ mp->nack--;
+ }
+ }
+@@ -216,13 +242,17 @@
+
+ /* -------- struct capiminor ---------------------------------------- */
+
+-static struct capiminor *capiminor_alloc(u16 applid, u32 ncci)
++struct capiminor *capiminor_alloc(__u16 applid, __u32 ncci)
+ {
+ struct capiminor *mp, **pp;
+ unsigned int minor = 0;
+
+ MOD_INC_USE_COUNT;
++#ifdef COMPAT_HAS_kmem_cache
+ mp = (struct capiminor *)kmem_cache_alloc(capiminor_cachep, GFP_ATOMIC);
++#else
++ mp = (struct capiminor *)kmalloc(sizeof(struct capiminor), GFP_ATOMIC);
++#endif
+ if (!mp) {
+ MOD_DEC_USE_COUNT;
+ printk(KERN_ERR "capi: can't alloc capiminor\n");
+@@ -257,7 +287,7 @@
+ return mp;
+ }
+
+-static void capiminor_free(struct capiminor *mp)
++void capiminor_free(struct capiminor *mp)
+ {
+ struct capiminor **pp;
+
+@@ -271,7 +301,11 @@
+ skb_queue_purge(&mp->inqueue);
+ skb_queue_purge(&mp->outqueue);
+ capiminor_del_all_ack(mp);
++#ifdef COMPAT_HAS_kmem_cache
+ kmem_cache_free(capiminor_cachep, mp);
++#else
++ kfree(mp);
++#endif
+ MOD_DEC_USE_COUNT;
+ #ifdef _DEBUG_REFCOUNT
+ printk(KERN_DEBUG "capiminor_free %d\n", GET_USE_COUNT(THIS_MODULE));
+@@ -283,7 +317,7 @@
+ }
+ }
+
+-static struct capiminor *capiminor_find(unsigned int minor)
++struct capiminor *capiminor_find(unsigned int minor)
+ {
+ struct capiminor *p;
+ for (p = minors; p && p->minor != minor; p = p->next)
+@@ -294,7 +328,7 @@
+
+ /* -------- struct capincci ----------------------------------------- */
+
+-static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci)
++static struct capincci *capincci_alloc(struct capidev *cdev, __u32 ncci)
+ {
+ struct capincci *np, **pp;
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+@@ -302,7 +336,11 @@
+ kdev_t kdev;
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+
++#ifdef COMPAT_HAS_kmem_cache
+ np = (struct capincci *)kmem_cache_alloc(capincci_cachep, GFP_ATOMIC);
++#else
++ np = (struct capincci *)kmalloc(sizeof(struct capincci), GFP_ATOMIC);
++#endif
+ if (!np)
+ return 0;
+ memset(np, 0, sizeof(struct capincci));
+@@ -331,7 +369,7 @@
+ return np;
+ }
+
+-static void capincci_free(struct capidev *cdev, u32 ncci)
++static void capincci_free(struct capidev *cdev, __u32 ncci)
+ {
+ struct capincci *np, **pp;
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+@@ -367,7 +405,11 @@
+ }
+ }
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
++#ifdef COMPAT_HAS_kmem_cache
+ kmem_cache_free(capincci_cachep, np);
++#else
++ kfree(np);
++#endif
+ if (*pp == 0) return;
+ } else {
+ pp = &(*pp)->next;
+@@ -375,7 +417,7 @@
+ }
+ }
+
+-static struct capincci *capincci_find(struct capidev *cdev, u32 ncci)
++struct capincci *capincci_find(struct capidev *cdev, __u32 ncci)
+ {
+ struct capincci *p;
+
+@@ -393,7 +435,11 @@
+ struct capidev *cdev;
+ struct capidev **pp;
+
++#ifdef COMPAT_HAS_kmem_cache
+ cdev = (struct capidev *)kmem_cache_alloc(capidev_cachep, GFP_KERNEL);
++#else
++ cdev = (struct capidev *)kmalloc(sizeof(struct capidev), GFP_KERNEL);
++#endif
+ if (!cdev)
+ return 0;
+ memset(cdev, 0, sizeof(struct capidev));
+@@ -423,10 +469,14 @@
+ if (*pp)
+ *pp = cdev->next;
+
++#ifdef COMPAT_HAS_kmem_cache
+ kmem_cache_free(capidev_cachep, cdev);
++#else
++ kfree(cdev);
++#endif
+ }
+
+-static struct capidev *capidev_find(u16 applid)
++static struct capidev *capidev_find(__u16 applid)
+ {
+ struct capidev *p;
+ for (p=capidev_openlist; p; p = p->next) {
+@@ -439,13 +489,13 @@
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+ /* -------- handle data queue --------------------------------------- */
+
+-static struct sk_buff *
++struct sk_buff *
+ gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb)
+ {
+ struct sk_buff *nskb;
+ nskb = alloc_skb(CAPI_DATA_B3_RESP_LEN, GFP_ATOMIC);
+ if (nskb) {
+- u16 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4+4+2);
++ __u16 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4+4+2);
+ unsigned char *s = skb_put(nskb, CAPI_DATA_B3_RESP_LEN);
+ capimsg_setu16(s, 0, CAPI_DATA_B3_RESP_LEN);
+ capimsg_setu16(s, 2, mp->applid);
+@@ -458,11 +508,11 @@
+ return nskb;
+ }
+
+-static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
++int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
+ {
+ struct sk_buff *nskb;
+ unsigned int datalen;
+- u16 errcode, datahandle;
++ __u16 errcode, datahandle;
+
+ datalen = skb->len - CAPIMSG_LEN(skb->data);
+ if (mp->tty) {
+@@ -504,6 +554,28 @@
+ kfree_skb(skb);
+ return 0;
+
++#ifdef CAPI_PPP_ON_RAW_DEVICE
++ } else if (mp->chan_connected) {
++ if ((nskb = gen_data_b3_resp_for(mp, skb)) == 0) {
++ printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
++ return -1;
++ }
++ datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4);
++ errcode = (*capifuncs->capi_put_message)(mp->applid, nskb);
++ if (errcode != CAPI_NOERROR) {
++ printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
++ errcode);
++ kfree_skb(nskb);
++ return -1;
++ }
++ (void)skb_pull(skb, CAPIMSG_LEN(skb->data));
++#ifdef _DEBUG_DATAFLOW
++ printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ppp\n",
++ datahandle, skb->len);
++#endif
++ ppp_input(&mp->chan, skb);
++ return 0;
++#endif
+ } else if (mp->file) {
+ if (skb_queue_len(&mp->recvqueue) > CAPINC_MAX_RECVQUEUE) {
+ #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
+@@ -538,7 +610,7 @@
+ return -1;
+ }
+
+-static void handle_minor_recv(struct capiminor *mp)
++void handle_minor_recv(struct capiminor *mp)
+ {
+ struct sk_buff *skb;
+ while ((skb = skb_dequeue(&mp->inqueue)) != 0) {
+@@ -552,13 +624,13 @@
+ }
+ }
+
+-static int handle_minor_send(struct capiminor *mp)
++int handle_minor_send(struct capiminor *mp)
+ {
+ struct sk_buff *skb;
+- u16 len;
++ __u16 len;
+ int count = 0;
+- u16 errcode;
+- u16 datahandle;
++ __u16 errcode;
++ __u16 datahandle;
+
+ if (mp->tty && mp->ttyoutstop) {
+ #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
+@@ -569,7 +641,7 @@
+
+ while ((skb = skb_dequeue(&mp->outqueue)) != 0) {
+ datahandle = mp->datahandle;
+- len = (u16)skb->len;
++ len = (__u16)skb->len;
+ skb_push(skb, CAPI_DATA_B3_REQ_LEN);
+ memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
+ capimsg_setu16(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
+@@ -578,7 +650,7 @@
+ capimsg_setu8 (skb->data, 5, CAPI_REQ);
+ capimsg_setu16(skb->data, 6, mp->msgid++);
+ capimsg_setu32(skb->data, 8, mp->ncci); /* NCCI */
+- capimsg_setu32(skb->data, 12, (u32) skb->data); /* Data32 */
++ capimsg_setu32(skb->data, 12, (__u32) skb->data); /* Data32 */
+ capimsg_setu16(skb->data, 16, len); /* Data length */
+ capimsg_setu16(skb->data, 18, datahandle);
+ capimsg_setu16(skb->data, 20, 0); /* Flags */
+@@ -620,16 +692,16 @@
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+ /* -------- function called by lower level -------------------------- */
+
+-static void capi_signal(u16 applid, void *param)
++static void capi_signal(__u16 applid, void *param)
+ {
+ struct capidev *cdev = (struct capidev *)param;
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+ struct capiminor *mp;
+- u16 datahandle;
++ __u16 datahandle;
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+ struct capincci *np;
+ struct sk_buff *skb = 0;
+- u32 ncci;
++ __u32 ncci;
+
+ (void) (*capifuncs->capi_get_message) (applid, &skb);
+ if (!skb) {
+@@ -683,6 +755,12 @@
+ #endif
+ kfree_skb(skb);
+ (void)capiminor_del_ack(mp, datahandle);
++#ifdef CAPI_PPP_ON_RAW_DEVICE
++ if (mp->chan_connected) {
++ ppp_output_wakeup(&mp->chan);
++ return;
++ }
++#endif
+ if (mp->tty) {
+ if (mp->tty->ldisc.write_wakeup)
+ mp->tty->ldisc.write_wakeup(mp->tty);
+@@ -758,7 +836,7 @@
+ struct capidev *cdev = (struct capidev *)file->private_data;
+ struct sk_buff *skb;
+ int retval;
+- u16 mlen;
++ __u16 mlen;
+
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+@@ -998,7 +1076,7 @@
+ sizeof(ncci));
+ if (retval)
+ return -EFAULT;
+- nccip = capincci_find(cdev, (u32) ncci);
++ nccip = capincci_find(cdev, (__u32) ncci);
+ if (!nccip)
+ return 0;
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+@@ -1023,7 +1101,7 @@
+ sizeof(ncci));
+ if (retval)
+ return -EFAULT;
+- nccip = capincci_find(cdev, (u32) ncci);
++ nccip = capincci_find(cdev, (__u32) ncci);
+ if (!nccip || (mp = nccip->minorp) == 0)
+ return -ESRCH;
+ return mp->minor;
+@@ -1070,7 +1148,9 @@
+
+ static struct file_operations capi_fops =
+ {
++#ifdef COMPAT_HAS_FILEOP_OWNER
+ owner: THIS_MODULE,
++#endif
+ llseek: no_llseek,
+ read: capi_read,
+ write: capi_write,
+@@ -1233,6 +1313,45 @@
+ return -EINVAL;
+
+ switch (cmd) {
++#ifdef CAPI_PPP_ON_RAW_DEVICE
++ case PPPIOCATTACH:
++ {
++ int retval, val;
++ if (get_user(val, (int *) arg))
++ break;
++ if (mp->chan_connected)
++ return -EALREADY;
++ mp->chan.private = mp;
++#if 1
++ return -EINVAL;
++#else
++ mp->chan.ops = &ppp_ops;
++#endif
++
++ retval = ppp_register_channel(&mp->chan, val);
++ if (retval)
++ return retval;
++ mp->chan_connected = 1;
++ mp->chan_index = val;
++ }
++ return 0;
++ case PPPIOCDETACH:
++ {
++ if (!mp->chan_connected)
++ return -ENXIO;
++ ppp_unregister_channel(&mp->chan);
++ mp->chan_connected = 0;
++ }
++ return 0;
++ case PPPIOCGUNIT:
++ {
++ if (!mp->chan_connected)
++ return -ENXIO;
++ if (put_user(mp->chan_index, (int *) arg))
++ return -EFAULT;
++ }
++ return 0;
++#endif
+ }
+ return -EINVAL;
+ }
+@@ -1260,7 +1379,9 @@
+
+ static struct file_operations capinc_raw_fops =
+ {
++#ifdef COMPAT_HAS_FILEOP_OWNER
+ owner: THIS_MODULE,
++#endif
+ llseek: no_llseek,
+ read: capinc_raw_read,
+ write: capinc_raw_write,
+@@ -1272,7 +1393,7 @@
+
+ /* -------- tty_operations for capincci ----------------------------- */
+
+-static int capinc_tty_open(struct tty_struct * tty, struct file * file)
++int capinc_tty_open(struct tty_struct * tty, struct file * file)
+ {
+ struct capiminor *mp;
+
+@@ -1300,7 +1421,7 @@
+ return 0;
+ }
+
+-static void capinc_tty_close(struct tty_struct * tty, struct file * file)
++void capinc_tty_close(struct tty_struct * tty, struct file * file)
+ {
+ struct capiminor *mp;
+
+@@ -1325,8 +1446,8 @@
+ #endif
+ }
+
+-static int capinc_tty_write(struct tty_struct * tty, int from_user,
+- const unsigned char *buf, int count)
++int capinc_tty_write(struct tty_struct * tty, int from_user,
++ const unsigned char *buf, int count)
+ {
+ struct capiminor *mp = (struct capiminor *)tty->driver_data;
+ struct sk_buff *skb;
+@@ -1377,7 +1498,7 @@
+ return count;
+ }
+
+-static void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
++void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+ struct capiminor *mp = (struct capiminor *)tty->driver_data;
+ struct sk_buff *skb;
+@@ -1414,7 +1535,7 @@
+ }
+ }
+
+-static void capinc_tty_flush_chars(struct tty_struct *tty)
++void capinc_tty_flush_chars(struct tty_struct *tty)
+ {
+ struct capiminor *mp = (struct capiminor *)tty->driver_data;
+ struct sk_buff *skb;
+@@ -1440,7 +1561,7 @@
+ (void)handle_minor_recv(mp);
+ }
+
+-static int capinc_tty_write_room(struct tty_struct *tty)
++int capinc_tty_write_room(struct tty_struct *tty)
+ {
+ struct capiminor *mp = (struct capiminor *)tty->driver_data;
+ int room;
+@@ -1458,7 +1579,7 @@
+ return room;
+ }
+
+-static int capinc_tty_chars_in_buffer(struct tty_struct *tty)
++int capinc_tty_chars_in_buffer(struct tty_struct *tty)
+ {
+ struct capiminor *mp = (struct capiminor *)tty->driver_data;
+ if (!mp || !mp->nccip) {
+@@ -1476,7 +1597,7 @@
+ return mp->outbytes;
+ }
+
+-static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
++int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned long arg)
+ {
+ int error = 0;
+@@ -1488,14 +1609,14 @@
+ return error;
+ }
+
+-static void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old)
++void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old)
+ {
+ #ifdef _DEBUG_TTYFUNCS
+ printk(KERN_DEBUG "capinc_tty_set_termios\n");
+ #endif
+ }
+
+-static void capinc_tty_throttle(struct tty_struct * tty)
++void capinc_tty_throttle(struct tty_struct * tty)
+ {
+ struct capiminor *mp = (struct capiminor *)tty->driver_data;
+ #ifdef _DEBUG_TTYFUNCS
+@@ -1505,7 +1626,7 @@
+ mp->ttyinstop = 1;
+ }
+
+-static void capinc_tty_unthrottle(struct tty_struct * tty)
++void capinc_tty_unthrottle(struct tty_struct * tty)
+ {
+ struct capiminor *mp = (struct capiminor *)tty->driver_data;
+ #ifdef _DEBUG_TTYFUNCS
+@@ -1517,7 +1638,7 @@
+ }
+ }
+
+-static void capinc_tty_stop(struct tty_struct *tty)
++void capinc_tty_stop(struct tty_struct *tty)
+ {
+ struct capiminor *mp = (struct capiminor *)tty->driver_data;
+ #ifdef _DEBUG_TTYFUNCS
+@@ -1528,7 +1649,7 @@
+ }
+ }
+
+-static void capinc_tty_start(struct tty_struct *tty)
++void capinc_tty_start(struct tty_struct *tty)
+ {
+ struct capiminor *mp = (struct capiminor *)tty->driver_data;
+ #ifdef _DEBUG_TTYFUNCS
+@@ -1540,43 +1661,49 @@
+ }
+ }
+
+-static void capinc_tty_hangup(struct tty_struct *tty)
++void capinc_tty_hangup(struct tty_struct *tty)
+ {
+ #ifdef _DEBUG_TTYFUNCS
+ printk(KERN_DEBUG "capinc_tty_hangup\n");
+ #endif
+ }
+
+-static void capinc_tty_break_ctl(struct tty_struct *tty, int state)
++void capinc_tty_break_ctl(struct tty_struct *tty, int state)
+ {
+ #ifdef _DEBUG_TTYFUNCS
+ printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state);
+ #endif
+ }
+
+-static void capinc_tty_flush_buffer(struct tty_struct *tty)
++void capinc_tty_flush_buffer(struct tty_struct *tty)
+ {
+ #ifdef _DEBUG_TTYFUNCS
+ printk(KERN_DEBUG "capinc_tty_flush_buffer\n");
+ #endif
+ }
+
+-static void capinc_tty_set_ldisc(struct tty_struct *tty)
++void capinc_tty_set_ldisc(struct tty_struct *tty)
+ {
+ #ifdef _DEBUG_TTYFUNCS
+ printk(KERN_DEBUG "capinc_tty_set_ldisc\n");
+ #endif
+ }
+
+-static void capinc_tty_send_xchar(struct tty_struct *tty, char ch)
++void capinc_tty_send_xchar(struct tty_struct *tty, char ch)
+ {
+ #ifdef _DEBUG_TTYFUNCS
+ printk(KERN_DEBUG "capinc_tty_send_xchar(%d)\n", ch);
+ #endif
+ }
+
+-static int capinc_tty_read_proc(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
++int capinc_tty_read_proc(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ return 0;
++}
++
++int capinc_write_proc(struct file *file, const char *buffer,
++ unsigned long count, void *data)
+ {
+ return 0;
+ }
+@@ -1588,7 +1715,7 @@
+ static struct termios *capinc_tty_termios[CAPINC_NR_PORTS];
+ static struct termios *capinc_tty_termios_locked[CAPINC_NR_PORTS];
+
+-static int capinc_tty_init(void)
++int capinc_tty_init(void)
+ {
+ struct tty_driver *drv = &capinc_tty_driver;
+
+@@ -1646,7 +1773,7 @@
+ return 0;
+ }
+
+-static void capinc_tty_exit(void)
++void capinc_tty_exit(void)
+ {
+ struct tty_driver *drv = &capinc_tty_driver;
+ int retval;
+@@ -1771,8 +1898,9 @@
+
+ /* -------- init function and module interface ---------------------- */
+
++#ifdef COMPAT_HAS_kmem_cache
+
+-static void alloc_exit(void)
++static void __exit alloc_exit(void)
+ {
+ if (capidev_cachep) {
+ (void)kmem_cache_destroy(capidev_cachep);
+@@ -1837,8 +1965,9 @@
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+ return 0;
+ }
++#endif
+
+-static void lower_callback(unsigned int cmd, u32 contr, void *data)
++static void lower_callback(unsigned int cmd, __u32 contr, void *data)
+ {
+ struct capi_ncciinfo *np;
+ struct capidev *cdev;
+@@ -1900,15 +2029,19 @@
+ MOD_DEC_USE_COUNT;
+ return -EIO;
+ }
++#ifdef HAVE_DEVFS_FS
+ devfs_register_series (NULL, "capi/r%u", CAPINC_NR_PORTS,
+ DEVFS_FL_DEFAULT,
+ capi_rawmajor, 0,
+ S_IFCHR | S_IRUSR | S_IWUSR,
+ &capinc_raw_fops, NULL);
++#endif
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
++#ifdef HAVE_DEVFS_FS
+ devfs_register (NULL, "isdn/capi20", DEVFS_FL_DEFAULT,
+ capi_major, 0, S_IFCHR | S_IRUSR | S_IWUSR,
+ &capi_fops, NULL);
++#endif
+ printk(KERN_NOTICE "capi20: started up with major %d\n", capi_major);
+
+ if ((capifuncs = attach_capi_interface(&cuser)) == 0) {
+@@ -1918,9 +2051,11 @@
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+ devfs_unregister_chrdev(capi_rawmajor, "capi/r%d");
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
++#ifdef HAVE_DEVFS_FS
+ devfs_unregister(devfs_find_handle(NULL, "capi20",
+ capi_major, 0,
+ DEVFS_SPECIAL_CHR, 0));
++#endif
+ return -EIO;
+ }
+
+@@ -1934,8 +2069,10 @@
+ }
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+
++#ifdef COMPAT_HAS_kmem_cache
+ if (alloc_init() < 0) {
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
++#ifdef HAVE_DEVFS_FS
+ unsigned int j;
+ devfs_unregister_chrdev(capi_rawmajor, "capi/r%d");
+ for (j = 0; j < CAPINC_NR_PORTS; j++) {
+@@ -1943,16 +2080,20 @@
+ sprintf(devname, "capi/r%u", j);
+ devfs_unregister(devfs_find_handle(NULL, devname, capi_rawmajor, j, DEVFS_SPECIAL_CHR, 0));
+ }
++#endif
+ capinc_tty_exit();
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+ (void) detach_capi_interface(&cuser);
+ devfs_unregister_chrdev(capi_major, "capi20");
++#ifdef HAVE_DEVFS_FS
+ devfs_unregister(devfs_find_handle(NULL, "capi20",
+ capi_major, 0,
+ DEVFS_SPECIAL_CHR, 0));
++#endif
+ MOD_DEC_USE_COUNT;
+ return -ENOMEM;
+ }
++#endif /* COMPAT_HAS_kmem_cache */
+
+ (void)proc_init();
+
+@@ -1975,23 +2116,31 @@
+ static void __exit capi_exit(void)
+ {
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
++#ifdef HAVE_DEVFS_FS
+ unsigned int j;
+ #endif
++#endif
++#ifdef COMPAT_HAS_kmem_cache
+ alloc_exit();
++#endif
+ (void)proc_exit();
+
+ devfs_unregister_chrdev(capi_major, "capi20");
++#ifdef HAVE_DEVFS_FS
+ devfs_unregister(devfs_find_handle(NULL, "isdn/capi20", capi_major, 0, DEVFS_SPECIAL_CHR, 0));
++#endif
+
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+ capinc_tty_exit();
+ devfs_unregister_chrdev(capi_rawmajor, "capi/r%d");
++#ifdef HAVE_DEVFS_FS
+ for (j = 0; j < CAPINC_NR_PORTS; j++) {
+ char devname[32];
+ sprintf(devname, "capi/r%u", j);
+ devfs_unregister(devfs_find_handle(NULL, devname, capi_rawmajor, j, DEVFS_SPECIAL_CHR, 0));
+ }
+ #endif
++#endif
+ (void) detach_capi_interface(&cuser);
+ printk(KERN_NOTICE "capi: Rev %s: unloaded\n", rev);
+ }
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capicmd.h linux-2.4.29/drivers/isdn/avmb1/capicmd.h
+--- linux-2.4.29.old/drivers/isdn/avmb1/capicmd.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capicmd.h 2005-03-22 15:06:44.865272224 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capicmd.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capicmd.h,v 1.4 2001/09/24 13:22:44 kai Exp $
+ *
+ * CAPI 2.0 Interface for Linux
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capidev.h linux-2.4.29/drivers/isdn/avmb1/capidev.h
+--- linux-2.4.29.old/drivers/isdn/avmb1/capidev.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capidev.h 2005-03-22 15:06:44.880269944 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capidev.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capidev.h,v 1.8 2001/09/24 13:22:44 kai Exp $
+ *
+ * CAPI 2.0 Interface for Linux
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capidrv.c linux-2.4.29/drivers/isdn/avmb1/capidrv.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/capidrv.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capidrv.c 2005-03-22 15:06:44.918264168 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capidrv.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capidrv.c,v 1.45 2001/09/24 13:22:44 kai Exp $
+ *
+ * ISDN4Linux Driver, using capi20 interface (kernelcapi)
+ *
+@@ -35,7 +35,7 @@
+ #include "capicmd.h"
+ #include "capidrv.h"
+
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.45 $";
+ static int debugmode = 0;
+
+ MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux");
+@@ -105,7 +105,6 @@
+ int oldstate;
+ /* */
+ __u16 datahandle;
+- spinlock_t lock;
+ struct ncci_datahandle_queue {
+ struct ncci_datahandle_queue *next;
+ __u16 datahandle;
+@@ -423,7 +422,6 @@
+ nccip->plcip = plcip;
+ nccip->chan = plcip->chan;
+ nccip->datahandle = 0;
+- nccip->lock = SPIN_LOCK_UNLOCKED;
+
+ nccip->next = plcip->ncci_list;
+ plcip->ncci_list = nccip;
+@@ -480,7 +478,6 @@
+ __u16 datahandle, int len)
+ {
+ struct ncci_datahandle_queue *n, **pp;
+- unsigned long flags;
+
+ n = (struct ncci_datahandle_queue *)
+ kmalloc(sizeof(struct ncci_datahandle_queue), GFP_ATOMIC);
+@@ -491,31 +488,25 @@
+ n->next = 0;
+ n->datahandle = datahandle;
+ n->len = len;
+- spin_lock_irqsave(&nccip->lock, flags);
+ for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) ;
+ *pp = n;
+- spin_unlock_irqrestore(&nccip->lock, flags);
+ return 0;
+ }
+
+ static int capidrv_del_ack(struct capidrv_ncci *nccip, __u16 datahandle)
+ {
+ struct ncci_datahandle_queue **pp, *p;
+- unsigned long flags;
+ int len;
+
+- spin_lock_irqsave(&nccip->lock, flags);
+ for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) {
+ if ((*pp)->datahandle == datahandle) {
+ p = *pp;
+ len = p->len;
+ *pp = (*pp)->next;
+- spin_unlock_irqrestore(&nccip->lock, flags);
+ kfree(p);
+ return len;
+ }
+ }
+- spin_unlock_irqrestore(&nccip->lock, flags);
+ return -1;
+ }
+
+@@ -523,25 +514,13 @@
+
+ static void send_message(capidrv_contr * card, _cmsg * cmsg)
+ {
+- struct sk_buff *skb;
+- size_t len;
+- u16 err;
+-
++ struct sk_buff *skb;
++ size_t len;
+ capi_cmsg2message(cmsg, cmsg->buf);
+ len = CAPIMSG_LEN(cmsg->buf);
+ skb = alloc_skb(len, GFP_ATOMIC);
+- if(!skb) {
+- printk(KERN_ERR "no skb len(%d) memory\n", len);
+- return;
+- }
+ memcpy(skb_put(skb, len), cmsg->buf, len);
+- err = (*capifuncs->capi_put_message) (global.appid, skb);
+- if (err) {
+- printk(KERN_WARNING "%s: capi_put_message error: %04x\n",
+- __FUNCTION__, err);
+- kfree_skb(skb);
+- return;
+- }
++ (*capifuncs->capi_put_message) (global.appid, skb);
+ global.nsentctlpkt++;
+ }
+
+@@ -1932,8 +1911,10 @@
+ (void)capidrv_del_ack(nccip, datahandle);
+ return 0;
+ }
++#if 1
+ printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom, need %d\n",
+ card->contrnr, skb_headroom(skb), msglen);
++#endif
+ memcpy(skb_push(nskb, msglen), sendcmsg.buf, msglen);
+ errcode = (*capifuncs->capi_put_message) (global.appid, nskb);
+ if (errcode == CAPI_NOERROR) {
+@@ -2035,6 +2016,52 @@
+ send_message(card, &cmdcmsg);
+ }
+
++#if 0
++static void disable_dchannel_trace(capidrv_contr *card)
++{
++ __u8 manufacturer[CAPI_MANUFACTURER_LEN];
++ capi_version version;
++ __u16 contr = card->contrnr;
++ __u16 errcode;
++ __u16 avmversion[3];
++
++ errcode = (*capifuncs->capi_get_manufacturer)(contr, manufacturer);
++ if (errcode != CAPI_NOERROR) {
++ printk(KERN_ERR "%s: can't get manufacturer (0x%x)\n",
++ card->name, errcode);
++ return;
++ }
++ if (strstr(manufacturer, "AVM") == 0) {
++ printk(KERN_ERR "%s: not from AVM, no d-channel trace possible (%s)\n",
++ card->name, manufacturer);
++ return;
++ }
++ errcode = (*capifuncs->capi_get_version)(contr, &version);
++ if (errcode != CAPI_NOERROR) {
++ printk(KERN_ERR "%s: can't get version (0x%x)\n",
++ card->name, errcode);
++ return;
++ }
++ avmversion[0] = (version.majormanuversion >> 4) & 0x0f;
++ avmversion[1] = (version.majormanuversion << 4) & 0xf0;
++ avmversion[1] |= (version.minormanuversion >> 4) & 0x0f;
++ avmversion[2] |= version.minormanuversion & 0x0f;
++
++ if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 5)) {
++ printk(KERN_INFO "%s: D2 trace disabled\n", card->name);
++ } else {
++ printk(KERN_INFO "%s: D3 trace disabled\n", card->name);
++ }
++ capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid,
++ card->msgid++,
++ contr,
++ 0x214D5641, /* ManuID */
++ 0, /* Class */
++ 1, /* Function */
++ (_cstruct)"\004\000\000\000\000");
++ send_message(card, &cmdcmsg);
++}
++#endif
+
+ static void send_listen(capidrv_contr *card)
+ {
+@@ -2200,10 +2227,10 @@
+ free_ncci(card, card->bchans[card->nbchan-1].nccip);
+ if (card->bchans[card->nbchan-1].plcip)
+ free_plci(card, card->bchans[card->nbchan-1].plcip);
++ if (card->plci_list)
++ printk(KERN_ERR "capidrv: bug in free_plci()\n");
+ card->nbchan--;
+ }
+- if (card->plci_list)
+- printk(KERN_ERR "capidrv: bug in free_plci()\n");
+ kfree(card->bchans);
+ card->bchans = 0;
+
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capidrv.h linux-2.4.29/drivers/isdn/avmb1/capidrv.h
+--- linux-2.4.29.old/drivers/isdn/avmb1/capidrv.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capidrv.h 2005-03-22 15:06:44.935261584 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capidrv.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capidrv.h,v 1.4 2001/09/24 13:22:44 kai Exp $
+ *
+ * ISDN4Linux Driver, using capi20 interface (kernelcapi)
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capifs.c linux-2.4.29/drivers/isdn/avmb1/capifs.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/capifs.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capifs.c 2005-03-22 15:06:44.950259304 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capifs.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capifs.c,v 1.22 2001/09/24 13:22:44 kai Exp $
+ *
+ * Copyright 2000 by Carsten Paeth <calle@calle.de>
+ *
+@@ -25,6 +25,7 @@
+ #include <linux/major.h>
+ #include <linux/slab.h>
+ #include <linux/ctype.h>
++#include <linux/isdn_compat.h>
+ #include <asm/bitops.h>
+ #include <asm/uaccess.h>
+
+@@ -32,7 +33,7 @@
+ MODULE_AUTHOR("Carsten Paeth");
+ MODULE_LICENSE("GPL");
+
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.22 $";
+
+ struct capifs_ncci {
+ struct inode *inode;
+@@ -69,14 +70,21 @@
+ static int capifs_root_readdir(struct file *,void *,filldir_t);
+ static struct dentry *capifs_root_lookup(struct inode *,struct dentry *);
+ static int capifs_revalidate(struct dentry *, int);
++#ifdef COMPAT_VFS_2_4
+ static struct inode *capifs_new_inode(struct super_block *sb);
++#endif
+
+ static struct file_operations capifs_root_operations = {
++#ifdef COMPAT_VFS_2_4
+ read: generic_read_dir,
++#endif
+ readdir: capifs_root_readdir,
+ };
+
+ struct inode_operations capifs_root_inode_operations = {
++#ifndef COMPAT_VFS_2_4
++ default_file_ops: &capifs_root_operations, /* file operations */
++#endif
+ lookup: capifs_root_lookup,
+ };
+
+@@ -101,12 +109,20 @@
+ switch(nr)
+ {
+ case 0:
++#ifdef COMPAT_VFS_2_4
+ if (filldir(dirent, ".", 1, nr, inode->i_ino, DT_DIR) < 0)
++#else
++ if (filldir(dirent, ".", 1, nr, inode->i_ino) < 0)
++#endif
+ return 0;
+ filp->f_pos = ++nr;
+ /* fall through */
+ case 1:
++#ifdef COMPAT_VFS_2_4
+ if (filldir(dirent, "..", 2, nr, inode->i_ino, DT_DIR) < 0)
++#else
++ if (filldir(dirent, "..", 2, nr, inode->i_ino) < 0)
++#endif
+ return 0;
+ filp->f_pos = ++nr;
+ /* fall through */
+@@ -118,7 +134,11 @@
+ char *p = numbuf;
+ if (np->type) *p++ = np->type;
+ sprintf(p, "%u", np->num);
++#ifdef COMPAT_VFS_2_4
+ if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr, DT_UNKNOWN) < 0 )
++#else
++ if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr) < 0 )
++#endif
+ return 0;
+ }
+ filp->f_pos = ++nr;
+@@ -180,7 +200,7 @@
+
+ dentry->d_inode = np->inode;
+ if ( dentry->d_inode )
+- atomic_inc(&dentry->d_inode->i_count);
++ i_count_inc(dentry->d_inode->i_count);
+
+ d_add(dentry, dentry->d_inode);
+
+@@ -199,9 +219,9 @@
+
+ for ( i = 0 ; i < sbi->max_ncci ; i++ ) {
+ if ( (inode = sbi->nccis[i].inode) ) {
+- if (atomic_read(&inode->i_count) != 1 )
++ if (i_count_read(inode->i_count) != 1 )
+ printk("capifs_put_super: badness: entry %d count %d\n",
+- i, (unsigned)atomic_read(&inode->i_count));
++ i, (unsigned)i_count_read(inode->i_count));
+ inode->i_nlink--;
+ iput(inode);
+ }
+@@ -213,11 +233,24 @@
+
+ kfree(sbi->nccis);
+ kfree(sbi);
++#ifndef COMPAT_VFS_2_4
++ MOD_DEC_USE_COUNT;
++#endif
+ }
+
++#ifdef COMPAT_VFS_2_4
+ static int capifs_statfs(struct super_block *sb, struct statfs *buf);
++#else
++static int capifs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
++static void capifs_write_inode(struct inode *inode) { };
++static void capifs_read_inode(struct inode *inode);
++#endif
+
+ static struct super_operations capifs_sops = {
++#ifndef COMPAT_VFS_2_4
++ read_inode: capifs_read_inode,
++ write_inode: capifs_write_inode,
++#endif
+ put_super: capifs_put_super,
+ statfs: capifs_statfs,
+ };
+@@ -288,6 +321,10 @@
+ struct dentry * root;
+ struct capifs_sb_info *sbi;
+
++#ifndef COMPAT_VFS_2_4
++ MOD_INC_USE_COUNT;
++ lock_super(s);
++#endif
+ /* Super block already completed? */
+ if (s->s_root)
+ goto out;
+@@ -322,6 +359,7 @@
+ /*
+ * Get the root inode and dentry, but defer checking for errors.
+ */
++#ifdef COMPAT_VFS_2_4
+ root_inode = capifs_new_inode(s);
+ if (root_inode) {
+ root_inode->i_ino = 1;
+@@ -331,6 +369,10 @@
+ root_inode->i_nlink = 2;
+ }
+ root = d_alloc_root(root_inode);
++#else
++ root_inode = iget(s, 1); /* inode 1 == root directory */
++ root = d_alloc_root(root_inode, NULL);
++#endif
+
+ /*
+ * Check whether somebody else completed the super block.
+@@ -370,11 +412,34 @@
+ mounts = s;
+
+ out: /* Success ... somebody else completed the super block for us. */
++#ifndef COMPAT_VFS_2_4
++ unlock_super(s);
++#endif
+ return s;
+ fail:
++#ifndef COMPAT_VFS_2_4
++ unlock_super(s);
++ MOD_DEC_USE_COUNT;
++#endif
+ return NULL;
+ }
+
++#ifndef COMPAT_VFS_2_4
++static int capifs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
++{
++ struct statfs tmp;
++
++ tmp.f_type = CAPIFS_SUPER_MAGIC;
++ tmp.f_bsize = 1024;
++ tmp.f_blocks = 0;
++ tmp.f_bfree = 0;
++ tmp.f_bavail = 0;
++ tmp.f_files = 0;
++ tmp.f_ffree = 0;
++ tmp.f_namelen = NAME_MAX;
++ return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
++}
++#else
+ static int capifs_statfs(struct super_block *sb, struct statfs *buf)
+ {
+ buf->f_type = CAPIFS_SUPER_MAGIC;
+@@ -387,7 +452,9 @@
+ buf->f_namelen = NAME_MAX;
+ return 0;
+ }
++#endif
+
++#ifdef COMPAT_VFS_2_4
+ static struct inode *capifs_new_inode(struct super_block *sb)
+ {
+ struct inode *inode = new_inode(sb);
+@@ -399,8 +466,51 @@
+ }
+ return inode;
+ }
++#else
++static void capifs_read_inode(struct inode *inode)
++{
++ ino_t ino = inode->i_ino;
++ struct capifs_sb_info *sbi = SBI(inode->i_sb);
++
++ inode->i_mode = 0;
++ inode->i_nlink = 0;
++ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
++ inode->i_blocks = 0;
++ inode->i_blksize = 1024;
++ inode->i_uid = inode->i_gid = 0;
++
++ if ( ino == 1 ) {
++ inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
++ inode->i_op = &capifs_root_inode_operations;
++ inode->i_nlink = 2;
++ return;
++ }
+
++ ino -= 2;
++ if ( ino >= sbi->max_ncci )
++ return; /* Bogus */
++
++#ifdef COMPAT_VFS_2_4
++ init_special_inode(inode, S_IFCHR, 0);
++#else
++ inode->i_mode = S_IFCHR;
++ inode->i_op = &chrdev_inode_operations;
++#endif
++
++ return;
++}
++#endif
++
++#ifndef COMPAT_VFS_2_4
++static struct file_system_type capifs_fs_type = {
++ "capifs",
++ 0,
++ capifs_read_super,
++ NULL
++};
++#else
+ static DECLARE_FSTYPE(capifs_fs_type, "capifs", capifs_read_super, 0);
++#endif
+
+ void capifs_new_ncci(char type, unsigned int num, kdev_t device)
+ {
+@@ -421,16 +531,26 @@
+ break;
+ }
+ }
++#ifdef COMPAT_VFS_2_4
+ if ( ino >= sbi->max_ncci )
+ continue;
+
+ if ((np->inode = capifs_new_inode(sb)) != NULL) {
++#else
++ if ((np->inode = iget(sb, ino+2)) != NULL) {
++#endif
+ struct inode *inode = np->inode;
+ inode->i_uid = sbi->setuid ? sbi->uid : current->fsuid;
+ inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid;
++#ifdef COMPAT_VFS_2_4
+ inode->i_nlink = 1;
+ inode->i_ino = ino + 2;
+ init_special_inode(inode, sbi->mode|S_IFCHR, np->kdev);
++#else
++ inode->i_mode = sbi->mode | S_IFCHR;
++ inode->i_rdev = np->kdev;
++ inode->i_nlink++;
++#endif
+ }
+ }
+ }
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capifs.h linux-2.4.29/drivers/isdn/avmb1/capifs.h
+--- linux-2.4.29.old/drivers/isdn/avmb1/capifs.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capifs.h 2005-03-22 15:06:44.965257024 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capifs.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capifs.h,v 1.4 2001/09/24 13:22:44 kai Exp $
+ *
+ * Copyright 2000 by Carsten Paeth <calle@calle.de>
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capilli.h linux-2.4.29/drivers/isdn/avmb1/capilli.h
+--- linux-2.4.29.old/drivers/isdn/avmb1/capilli.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capilli.h 2005-03-22 15:06:44.980254744 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capilli.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capilli.h,v 1.5 2001/09/24 13:22:44 kai Exp $
+ *
+ * Kernel CAPI 2.0 Driver Interface for Linux
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capiutil.c linux-2.4.29/drivers/isdn/avmb1/capiutil.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/capiutil.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capiutil.c 2005-03-22 15:06:44.997252160 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capiutil.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capiutil.c,v 1.16 2001/09/24 13:22:44 kai Exp $
+ *
+ * CAPI 2.0 convert capi message to capi message struct
+ *
+@@ -19,6 +19,7 @@
+ #include <linux/init.h>
+ #include <asm/segment.h>
+ #include <linux/config.h>
++#include <linux/isdn_compat.h>
+ #include "capiutil.h"
+
+ MODULE_DESCRIPTION("CAPI4Linux: CAPI message conversion support");
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capiutil.h linux-2.4.29/drivers/isdn/avmb1/capiutil.h
+--- linux-2.4.29.old/drivers/isdn/avmb1/capiutil.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capiutil.h 2005-03-22 15:06:45.040245624 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capiutil.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capiutil.h,v 1.7 2001/09/24 13:22:44 kai Exp $
+ *
+ * CAPI 2.0 defines & types
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/kcapi.c linux-2.4.29/drivers/isdn/avmb1/kcapi.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/kcapi.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/kcapi.c 2005-03-22 15:06:45.062242280 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: kcapi.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: kcapi.c,v 1.28 2001/09/24 13:22:44 kai Exp $
+ *
+ * Kernel CAPI 2.0 Module
+ *
+@@ -21,6 +21,7 @@
+ #include <linux/proc_fs.h>
+ #include <linux/skbuff.h>
+ #include <linux/tqueue.h>
++#include <linux/isdn_compat.h>
+ #include <linux/capi.h>
+ #include <linux/kernelcapi.h>
+ #include <linux/locks.h>
+@@ -33,7 +34,7 @@
+ #include <linux/b1lli.h>
+ #endif
+
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.28 $";
+
+ /* ------------------------------------------------------------- */
+
+@@ -64,7 +65,6 @@
+ __u32 ncci;
+ __u32 winsize;
+ int nmsg;
+- spinlock_t lock;
+ struct msgidqueue *msgidqueue;
+ struct msgidqueue *msgidlast;
+ struct msgidqueue *msgidfree;
+@@ -104,14 +104,14 @@
+ #define APPL(a) (&applications[(a)-1])
+ #define VALID_APPLID(a) ((a) && (a) <= CAPI_MAXAPPL && APPL(a)->applid == a)
+ #define APPL_IS_FREE(a) (APPL(a)->applid == 0)
+-#define APPL_MARK_FREE(a) do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0)
+-#define APPL_MARK_USED(a) do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0)
++#define APPL_MARK_FREE(a) do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0);
++#define APPL_MARK_USED(a) do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0);
+
+ #define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f)
+
+ #define VALID_CARD(c) ((c) > 0 && (c) <= CAPI_MAXCONTR)
+ #define CARD(c) (&cards[(c)-1])
+-#define CARDNR(cp) ((((cp)-cards)+1) & 0xff)
++#define CARDNR(cp) (((cp)-cards)+1)
+
+ static struct capi_appl applications[CAPI_MAXAPPL];
+ static struct capi_ctr cards[CAPI_MAXCONTR];
+@@ -535,9 +535,13 @@
+ * of devices. Devices can only removed in
+ * user process, not in bh.
+ */
++#ifdef COMPAT_HAS_SCHEDULE_TASK
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&tq_state_notify) == 0)
+ MOD_DEC_USE_COUNT;
++#else
++ queue_task(&tq_state_notify, &tq_scheduler);
++#endif
+ return 0;
+ }
+
+@@ -546,13 +550,7 @@
+ static void notify_up(__u32 contr)
+ {
+ struct capi_interface_user *p;
+- __u16 appl;
+
+- for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
+- if (!VALID_APPLID(appl)) continue;
+- if (APPL(appl)->releasing) continue;
+- CARD(contr)->driver->register_appl(CARD(contr), appl, &APPL(appl)->rparam);
+- }
+ printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr);
+ spin_lock(&capi_users_lock);
+ for (p = capi_users; p; p = p->next) {
+@@ -639,7 +637,9 @@
+ kfree(np);
+ MOD_DEC_USE_COUNT;
+ }
++#ifdef COMPAT_HAS_SCHEDULE_TASK
+ MOD_DEC_USE_COUNT;
++#endif
+ }
+
+ /* -------- NCCI Handling ------------------------------------- */
+@@ -647,7 +647,6 @@
+ static inline void mq_init(struct capi_ncci * np)
+ {
+ int i;
+- np->lock = SPIN_LOCK_UNLOCKED;
+ np->msgidqueue = 0;
+ np->msgidlast = 0;
+ np->nmsg = 0;
+@@ -662,11 +661,8 @@
+ static inline int mq_enqueue(struct capi_ncci * np, __u16 msgid)
+ {
+ struct msgidqueue *mq;
+- spin_lock_bh(&np->lock);
+- if ((mq = np->msgidfree) == 0) {
+- spin_unlock_bh(&np->lock);
++ if ((mq = np->msgidfree) == 0)
+ return 0;
+- }
+ np->msgidfree = mq->next;
+ mq->msgid = msgid;
+ mq->next = 0;
+@@ -676,14 +672,12 @@
+ if (!np->msgidqueue)
+ np->msgidqueue = mq;
+ np->nmsg++;
+- spin_unlock_bh(&np->lock);
+ return 1;
+ }
+
+ static inline int mq_dequeue(struct capi_ncci * np, __u16 msgid)
+ {
+ struct msgidqueue **pp;
+- spin_lock_bh(&np->lock);
+ for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) {
+ if ((*pp)->msgid == msgid) {
+ struct msgidqueue *mq = *pp;
+@@ -693,11 +687,9 @@
+ mq->next = np->msgidfree;
+ np->msgidfree = mq;
+ np->nmsg--;
+- spin_unlock_bh(&np->lock);
+ return 1;
+ }
+ }
+- spin_unlock_bh(&np->lock);
+ return 0;
+ }
+
+@@ -720,16 +712,12 @@
+ nextpp = &(*pp)->next;
+ }
+ }
+- if (APPL(appl)->releasing) { /* only release if the application was marked for release */
+- printk(KERN_DEBUG "kcapi: appl %d releasing(%d)\n", appl, APPL(appl)->releasing);
+- APPL(appl)->releasing--;
+- if (APPL(appl)->releasing <= 0) {
+- APPL(appl)->signal = 0;
+- APPL_MARK_FREE(appl);
+- printk(KERN_INFO "kcapi: appl %d down\n", appl);
+- }
+- } else
+- printk(KERN_WARNING "kcapi: appl %d card%d released without request\n", appl, card->cnr);
++ APPL(appl)->releasing--;
++ if (APPL(appl)->releasing <= 0) {
++ APPL(appl)->signal = 0;
++ APPL_MARK_FREE(appl);
++ printk(KERN_INFO "kcapi: appl %d down\n", appl);
++ }
+ }
+ /*
+ * ncci management
+@@ -882,7 +870,16 @@
+
+ static void controllercb_ready(struct capi_ctr * card)
+ {
++ __u16 appl;
++
+ card->cardstate = CARD_RUNNING;
++
++ for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
++ if (!VALID_APPLID(appl)) continue;
++ if (APPL(appl)->releasing) continue;
++ card->driver->register_appl(card, appl, &APPL(appl)->rparam);
++ }
++
+ printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n",
+ CARDNR(card), card->name);
+
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/t1isa.c linux-2.4.29/drivers/isdn/avmb1/t1isa.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/t1isa.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/t1isa.c 2005-03-22 15:06:45.078239848 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: t1isa.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: t1isa.c,v 1.22 2001/09/24 13:22:44 kai Exp $
+ *
+ * Module for AVM T1 HEMA-card.
+ *
+@@ -19,13 +19,14 @@
+ #include <linux/capi.h>
+ #include <linux/kernelcapi.h>
+ #include <linux/init.h>
++#include <linux/isdn_compat.h>
+ #include <asm/io.h>
+ #include "capicmd.h"
+ #include "capiutil.h"
+ #include "capilli.h"
+ #include "avmcard.h"
+
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.22 $";
+
+ /* ------------------------------------------------------------- */
+
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/t1pci.c linux-2.4.29/drivers/isdn/avmb1/t1pci.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/t1pci.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/t1pci.c 2005-03-22 15:06:45.094237416 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: t1pci.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: t1pci.c,v 1.25 2001/09/24 13:22:44 kai Exp $
+ *
+ * Module for AVM T1 PCI-card.
+ *
+@@ -18,6 +18,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/ioport.h>
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+ #include <linux/capi.h>
+ #include <linux/init.h>
+ #include <asm/io.h>
+@@ -26,19 +27,21 @@
+ #include "capilli.h"
+ #include "avmcard.h"
+
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.25 $";
+
+ #undef CONFIG_T1PCI_DEBUG
+ #undef CONFIG_T1PCI_POLLDEBUG
+
+ /* ------------------------------------------------------------- */
+
++#ifndef COMPAT_HAS_2_2_PCI
+ static struct pci_device_id t1pci_pci_tbl[] __initdata = {
+ { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, PCI_ANY_ID, PCI_ANY_ID },
+ { } /* Terminating entry */
+ };
+
+ MODULE_DEVICE_TABLE(pci, t1pci_pci_tbl);
++#endif
+ MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 PCI card");
+ MODULE_AUTHOR("Carsten Paeth");
+ MODULE_LICENSE("GPL");
+@@ -264,9 +267,9 @@
+ }
+ pci_set_master(dev);
+
+- param.port = pci_resource_start(dev, 1);
++ param.port = pci_resource_start_io(dev, 1);
+ param.irq = dev->irq;
+- param.membase = pci_resource_start(dev, 0);
++ param.membase = pci_resource_start_mem(dev, 0);
+
+ printk(KERN_INFO
+ "%s: PCI BIOS reports AVM-T1-PCI at i/o %#x, irq %d, mem %#x\n",
+diff -rNu linux-2.4.29.old/drivers/isdn/divert/divert_procfs.c linux-2.4.29/drivers/isdn/divert/divert_procfs.c
+--- linux-2.4.29.old/drivers/isdn/divert/divert_procfs.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/divert/divert_procfs.c 2005-03-22 15:06:45.158227688 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: divert_procfs.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id$
+ *
+ * Filesystem handling for the diversion supplementary services.
+ *
+@@ -14,13 +14,16 @@
+ #include <linux/module.h>
+ #include <linux/version.h>
+ #include <linux/poll.h>
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+ #include <linux/smp_lock.h>
++#endif
+ #ifdef CONFIG_PROC_FS
+ #include <linux/proc_fs.h>
+ #else
+ #include <linux/fs.h>
+ #endif
+ #include <linux/isdnif.h>
++#include <linux/isdn_compat.h>
+ #include "isdn_divert.h"
+
+ /*********************************/
+@@ -80,7 +83,6 @@
+ isdn_divert_read(struct file *file, char *buf, size_t count, loff_t * off)
+ {
+ struct divert_info *inf;
+- loff_t pos = *off;
+ int len;
+
+ if (!*((struct divert_info **) file->private_data)) {
+@@ -92,11 +94,11 @@
+ return (0);
+
+ inf->usage_cnt--; /* new usage count */
+- file->private_data = &inf->next; /* next structure */
++ (struct divert_info **) file->private_data = &inf->next; /* next structure */
+ if ((len = strlen(inf->info_start)) <= count) {
+ if (copy_to_user(buf, inf->info_start, len))
+ return -EFAULT;
+- *off = pos + len;
++ file->f_pos += len;
+ return (len);
+ }
+ return (0);
+@@ -136,17 +138,23 @@
+ {
+ unsigned long flags;
+
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++ MOD_INC_USE_COUNT;
++#else
+ lock_kernel();
++#endif
+ save_flags(flags);
+ cli();
+ if_used++;
+ if (divert_info_head)
+- filep->private_data = &(divert_info_tail->next);
++ (struct divert_info **) filep->private_data = &(divert_info_tail->next);
+ else
+- filep->private_data = &divert_info_head;
++ (struct divert_info **) filep->private_data = &divert_info_head;
+ restore_flags(flags);
+ /* start_divert(); */
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+ unlock_kernel();
++#endif
+ return (0);
+ } /* isdn_divert_open */
+
+@@ -159,7 +167,9 @@
+ struct divert_info *inf;
+ unsigned long flags;
+
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+ lock_kernel();
++#endif
+ save_flags(flags);
+ cli();
+ if_used--;
+@@ -175,7 +185,11 @@
+ divert_info_head = divert_info_head->next;
+ kfree(inf);
+ }
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++ MOD_DEC_USE_COUNT;
++#else
+ unlock_kernel();
++#endif
+ return (0);
+ } /* isdn_divert_close */
+
+@@ -276,6 +290,9 @@
+ open: isdn_divert_open,
+ release: isdn_divert_close,
+ };
++#ifdef COMPAT_NO_SOFTNET
++struct inode_operations divert_file_inode_operations;
++#endif
+
+ /****************************/
+ /* isdn subdir in /proc/net */
+@@ -302,8 +319,16 @@
+ remove_proc_entry("isdn", proc_net);
+ return (-1);
+ }
++#ifdef COMPAT_NO_SOFTNET
++ memset(&divert_file_inode_operations, 0, sizeof(struct inode_operations));
++ divert_file_inode_operations.default_file_ops = &isdn_fops;
++ isdn_divert_entry->ops = &divert_file_inode_operations;
++#else
+ isdn_divert_entry->proc_fops = &isdn_fops;
++#ifdef COMPAT_HAS_FILEOP_OWNER
+ isdn_divert_entry->owner = THIS_MODULE;
++#endif
++#endif /* COMPAT_NO_SOFTNET */
+ #endif /* CONFIG_PROC_FS */
+
+ return (0);
+diff -rNu linux-2.4.29.old/drivers/isdn/divert/isdn_divert.c linux-2.4.29/drivers/isdn/divert/isdn_divert.c
+--- linux-2.4.29.old/drivers/isdn/divert/isdn_divert.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/divert/isdn_divert.c 2005-03-22 15:06:45.173225408 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_divert.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id$
+ *
+ * DSS1 main diversion supplementary handling for i4l.
+ *
+@@ -84,6 +84,9 @@
+ restore_flags(flags);
+ break;
+
++ case NETWORK_DIAL:
++ divert_if.dial_net_name(cs->deflect_dest);
++
+ case DEFLECT_AUTODEL:
+ default:
+ save_flags(flags);
+@@ -452,6 +455,7 @@
+ case DEFLECT_PROCEED:
+ case DEFLECT_REPORT:
+ case DEFLECT_REJECT:
++ case NETWORK_DIAL:
+ if (dv->rule.action == DEFLECT_PROCEED)
+ if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime)))
+ return(0); /* no external deflection needed */
+@@ -495,6 +499,11 @@
+ else
+ { cs->deflect_dest[0] = '\0';
+ retval = 4; /* only proceed */
++ if (cs->akt_state == NETWORK_DIAL) {
++ strcpy(cs->deflect_dest,dv->rule.to_nr);
++ cs->timer.expires = jiffies + 10;
++ retval = 0;
++ }
+ }
+ sprintf(cs->info,"%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n",
+ cs->akt_state,
+@@ -739,6 +748,18 @@
+ }
+
+
++#if 0
++ sprintf(st, "0x%lx 0x%lx",ic->arg, ic->parm.dss1_io.ll_id);
++ p = st + strlen(st);
++ p1 = ic->parm.dss1_io.data;
++ i = ic->parm.dss1_io.datalen;
++ while ((i > 0) && (p - st < 530))
++ { p += sprintf(p," %02x",(*p1++) & 0xFF);
++ i--;
++ }
++ sprintf(p, "\n");
++ put_info_buffer(st);
++#endif
+ break;
+
+ default:
+diff -rNu linux-2.4.29.old/drivers/isdn/divert/isdn_divert.h linux-2.4.29/drivers/isdn/divert/isdn_divert.h
+--- linux-2.4.29.old/drivers/isdn/divert/isdn_divert.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/divert/isdn_divert.h 2005-03-22 15:06:45.189222976 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_divert.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id$
+ *
+ * Header for the diversion supplementary ioctl interface.
+ *
+@@ -36,9 +36,10 @@
+ #define DEFLECT_PROCEED 2 /* deflect when externally triggered */
+ #define DEFLECT_ALERT 3 /* alert and deflect after delay */
+ #define DEFLECT_REJECT 4 /* reject immediately */
+-#define DIVERT_ACTIVATE 5 /* diversion activate */
+-#define DIVERT_DEACTIVATE 6 /* diversion deactivate */
+-#define DIVERT_REPORT 7 /* interrogation result */
++#define NETWORK_DIAL 5 /* dial a network interface */
++#define DIVERT_ACTIVATE 16 /* diversion activate */
++#define DIVERT_DEACTIVATE 17 /* diversion deactivate */
++#define DIVERT_REPORT 18 /* interrogation result */
+ #define DEFLECT_AUTODEL 255 /* only for internal use */
+
+ #define DEFLECT_ALL_IDS 0xFFFFFFFF /* all drivers selected */
+@@ -60,6 +61,7 @@
+ 2 = report call, send proceed, wait max waittime secs
+ 3 = report call, alert and deflect after waittime
+ 4 = report call, reject immediately
++ 5 = dial net interface specified in to_nr
+ actions 1-2 only take place if interface is opened
+ */
+ u_char waittime; /* maximum wait time for proceeding */
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/Divas_mod.c linux-2.4.29/drivers/isdn/eicon/Divas_mod.c
+--- linux-2.4.29.old/drivers/isdn/eicon/Divas_mod.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/Divas_mod.c 2005-03-22 15:06:45.229216896 +0100
+@@ -20,6 +20,7 @@
+ #include "adapter.h"
+ #include "uxio.h"
+
++#include <linux/isdn_compat.h>
+
+ MODULE_DESCRIPTION("ISDN4Linux: Driver for Eicon Diva Server cards");
+ MODULE_AUTHOR("Armin Schindler");
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/common.c linux-2.4.29/drivers/isdn/eicon/common.c
+--- linux-2.4.29.old/drivers/isdn/eicon/common.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/common.c 2005-03-22 15:06:45.301205952 +0100
+@@ -808,9 +808,7 @@
+
+ while(i--)
+ {
+- if (card->state == DIA_RUNNING)
+- DivaDoCardDpc(card);
+- card++;
++ DivaDoCardDpc(card++);
+ }
+ }
+
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon.h linux-2.4.29/drivers/isdn/eicon/eicon.h
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon.h 2005-03-22 15:06:45.371195312 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon.h,v 1.26 2001/09/24 13:22:47 kai Exp $
+ *
+ * ISDN low-level module for Eicon active ISDN-Cards.
+ *
+@@ -348,19 +348,19 @@
+ extern char *eicon_ctype_name[];
+
+
+-static inline void eicon_schedule_tx(eicon_card *card)
++extern __inline__ void eicon_schedule_tx(eicon_card *card)
+ {
+ queue_task(&card->snd_tq, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+ }
+
+-static inline void eicon_schedule_rx(eicon_card *card)
++extern __inline__ void eicon_schedule_rx(eicon_card *card)
+ {
+ queue_task(&card->rcv_tq, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+ }
+
+-static inline void eicon_schedule_ack(eicon_card *card)
++extern __inline__ void eicon_schedule_ack(eicon_card *card)
+ {
+ queue_task(&card->ack_tq, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_dsp.h linux-2.4.29/drivers/isdn/eicon/eicon_dsp.h
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_dsp.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_dsp.h 2005-03-22 15:06:45.386193032 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_dsp.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_dsp.h,v 1.8 2001/09/24 13:22:47 kai Exp $
+ *
+ * ISDN lowlevel-module for Eicon active cards.
+ * DSP definitions
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_idi.c linux-2.4.29/drivers/isdn/eicon/eicon_idi.c
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_idi.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_idi.c 2005-03-22 15:06:45.421187712 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_idi.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_idi.c,v 1.45 2001/11/07 22:35:48 kai Exp $
+ *
+ * ISDN lowlevel-module for Eicon active cards.
+ * IDI interface
+@@ -25,7 +25,7 @@
+
+ #undef EICON_FULL_SERVICE_OKTETT
+
+-char *eicon_idi_revision = "$Revision: 1.1.4.1 $";
++char *eicon_idi_revision = "$Revision: 1.45 $";
+
+ eicon_manifbuf *manbuf;
+
+@@ -1583,6 +1583,37 @@
+ return;
+ }
+
++#if 0
++ eicon_sff_dochead *doc = (eicon_sff_dochead *)skb->data;
++ eicon_sff_pagehead *page = (eicon_sff_pagehead *)skb->data + sizeof(eicon_sff_dochead);
++
++ printk(KERN_DEBUG"SFF: doc %d / page %d (skb : %d)\n",
++ sizeof(eicon_sff_dochead),
++ sizeof(eicon_sff_pagehead), skb->len);
++
++ if (skb->len >= sizeof(eicon_sff_dochead)) {
++ printk(KERN_DEBUG"SFF: id = 0x%x\n", doc->id);
++ printk(KERN_DEBUG"SFF: version = 0x%x\n", doc->version);
++ printk(KERN_DEBUG"SFF: reserved1 = 0x%x\n", doc->reserved1);
++ printk(KERN_DEBUG"SFF: userinfo = 0x%x\n", doc->userinfo);
++ printk(KERN_DEBUG"SFF: pagecount = 0x%x\n", doc->pagecount);
++ printk(KERN_DEBUG"SFF: off1pagehead = 0x%x\n", doc->off1pagehead);
++ printk(KERN_DEBUG"SFF: offnpagehead = 0x%x\n", doc->offnpagehead);
++ printk(KERN_DEBUG"SFF: offdocend = 0x%x\n", doc->offdocend);
++ }
++ if (skb->len >= (sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead))) {
++ printk(KERN_DEBUG"SFFp: id = 0x%x\n", page->pageheadid);
++ printk(KERN_DEBUG"SFFp: len = 0x%x\n", page->pageheadlen);
++ printk(KERN_DEBUG"SFFp: resvert = 0x%x\n", page->resvert);
++ printk(KERN_DEBUG"SFFp: reshoriz = 0x%x\n", page->reshoriz);
++ printk(KERN_DEBUG"SFFp: coding = 0x%x\n", page->coding);
++ printk(KERN_DEBUG"SFFp: reserved2 = 0x%x\n", page->reserved2);
++ printk(KERN_DEBUG"SFFp: linelength = 0x%x\n", page->linelength);
++ printk(KERN_DEBUG"SFFp: pagelength = 0x%x\n", page->pagelength);
++ printk(KERN_DEBUG"SFFp: offprevpage = 0x%x\n", page->offprevpage);
++ printk(KERN_DEBUG"SFFp: offnextpage = 0x%x\n", page->offnextpage);
++ }
++#endif
+
+
+ if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) {
+@@ -2054,8 +2085,7 @@
+ OutBuf.Len++;
+ } else {
+ *OutBuf.Next++ = 0;
+- *(__u16 *) OutBuf.Next = (__u16) LineBuf.Len;
+- OutBuf.Next += sizeof(__u16);
++ *((__u16 *) OutBuf.Next)++ = (__u16) LineBuf.Len;
+ OutBuf.Len += 3;
+ }
+ memcpy(OutBuf.Next, LineBuf.Data, LineBuf.Len);
+@@ -2385,6 +2415,12 @@
+ } else {
+ if (chan->e.B2Id)
+ idi_do_req(ccard, chan, REMOVE, 1);
++#if 0
++ if (chan->e.D3Id) {
++ idi_do_req(ccard, chan, REMOVE, 0);
++ idi_do_req(ccard, chan, ASSIGN, 0);
++ }
++#endif
+ chan->statectrl &= ~WAITING_FOR_HANGUP;
+ chan->statectrl &= ~IN_HOLD;
+ if (chan->statectrl & HAVE_CONN_REQ) {
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_idi.h linux-2.4.29/drivers/isdn/eicon/eicon_idi.h
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_idi.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_idi.h 2005-03-22 15:06:45.437185280 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_idi.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_idi.h,v 1.12 2001/09/24 13:22:47 kai Exp $
+ *
+ * ISDN lowlevel-module for the Eicon active cards.
+ * IDI-Interface
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_io.c linux-2.4.29/drivers/isdn/eicon/eicon_io.c
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_io.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_io.c 2005-03-22 15:06:45.453182848 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_io.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_io.c,v 1.15 2001/09/24 13:22:47 kai Exp $
+ *
+ * ISDN low-level module for Eicon active ISDN-Cards.
+ * Code for communicating with hardware.
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_isa.c linux-2.4.29/drivers/isdn/eicon/eicon_isa.c
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_isa.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_isa.c 2005-03-22 15:06:45.469180416 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_isa.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_isa.c,v 1.18 2001/11/07 22:35:48 kai Exp $
+ *
+ * ISDN low-level module for Eicon active ISDN-Cards.
+ * Hardware-specific code for old ISA cards.
+@@ -20,7 +20,7 @@
+ #define release_shmem release_region
+ #define request_shmem request_region
+
+-char *eicon_isa_revision = "$Revision: 1.1.4.1 $";
++char *eicon_isa_revision = "$Revision: 1.18 $";
+
+ #undef EICON_MCA_DEBUG
+
+@@ -38,8 +38,12 @@
+ static void
+ eicon_isa_release_shmem(eicon_isa_card *card) {
+ if (card->mvalid) {
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ iounmap(card->shmem);
+ release_mem_region(card->physmem, card->ramsize);
++#else
++ release_shmem((unsigned long)card->shmem, card->ramsize);
++#endif
+ }
+ card->mvalid = 0;
+ }
+@@ -94,12 +98,20 @@
+ Mem, Id);
+ return -1;
+ }
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ if (check_mem_region(Mem, RAMSIZE)) {
++#else
++ if (check_shmem(Mem, RAMSIZE)) {
++#endif
+ printk(KERN_WARNING "eicon_isa_boot: memory at 0x%x already in use.\n", Mem);
+ return -1;
+ }
+
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ amem = (unsigned long) ioremap(Mem, RAMSIZE);
++#else
++ amem = (unsigned long) Mem;
++#endif
+ writew(0x55aa, amem + 0x402);
+ if (readw(amem + 0x402) != 0x55aa) primary = 0;
+ writew(0, amem + 0x402);
+@@ -109,12 +121,16 @@
+ if (primary) {
+ printk(KERN_INFO "Eicon: assuming pri card at 0x%x\n", Mem);
+ writeb(0, amem + 0x3ffe);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ iounmap((unsigned char *)amem);
++#endif
+ return EICON_CTYPE_ISAPRI;
+ } else {
+ printk(KERN_INFO "Eicon: assuming bri card at 0x%x\n", Mem);
+ writeb(0, amem + 0x400);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ iounmap((unsigned char *)amem);
++#endif
+ return EICON_CTYPE_ISABRI;
+ }
+ return -1;
+@@ -151,6 +167,7 @@
+ else
+ card->ramsize = RAMSIZE;
+
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ if (check_mem_region(card->physmem, card->ramsize)) {
+ printk(KERN_WARNING "eicon_isa_boot: memory at 0x%lx already in use.\n",
+ card->physmem);
+@@ -159,6 +176,16 @@
+ }
+ request_mem_region(card->physmem, card->ramsize, "Eicon ISA ISDN");
+ card->shmem = (eicon_isa_shmem *) ioremap(card->physmem, card->ramsize);
++#else
++ /* Register shmem */
++ if (check_shmem((unsigned long)card->shmem, card->ramsize)) {
++ printk(KERN_WARNING "eicon_isa_boot: memory at 0x%lx already in use.\n",
++ (unsigned long)card->shmem);
++ kfree(code);
++ return -EBUSY;
++ }
++ request_shmem((unsigned long)card->shmem, card->ramsize, "Eicon ISA ISDN");
++#endif
+ #ifdef EICON_MCA_DEBUG
+ printk(KERN_INFO "eicon_isa_boot: card->ramsize = %d.\n", card->ramsize);
+ #endif
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_isa.h linux-2.4.29/drivers/isdn/eicon/eicon_isa.h
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_isa.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_isa.h 2005-03-22 15:06:45.485177984 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_isa.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_isa.h,v 1.11 2001/09/24 13:22:47 kai Exp $
+ *
+ * ISDN low-level module for Eicon active ISDN-Cards.
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_mod.c linux-2.4.29/drivers/isdn/eicon/eicon_mod.c
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_mod.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_mod.c 2005-03-22 15:06:45.505174944 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_mod.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_mod.c,v 1.44 2001/11/20 09:48:25 armin Exp $
+ *
+ * ISDN lowlevel-module for Eicon active cards.
+ *
+@@ -44,7 +44,7 @@
+ static eicon_card *cards = (eicon_card *) NULL; /* glob. var , contains
+ start of card-list */
+
+-static char *eicon_revision = "$Revision: 1.1.4.1 $";
++static char *eicon_revision = "$Revision: 1.44 $";
+
+ extern char *eicon_pci_revision;
+ extern char *eicon_isa_revision;
+@@ -639,6 +639,18 @@
+ static int
+ if_writecmd(const u_char * buf, int len, int user, int id, int channel)
+ {
++#if 0
++ /* Not yet used */
++ eicon_card *card = eicon_findcard(id);
++
++ if (card) {
++ if (!card->flags & EICON_FLAGS_RUNNING)
++ return (len);
++ return (len);
++ }
++ printk(KERN_ERR
++ "eicon: if_writecmd called with invalid driverId!\n");
++#endif
+ return (len);
+ }
+
+@@ -665,11 +677,8 @@
+ else
+ cnt = skb->len;
+
+- if (user) {
+- spin_unlock_irqrestore(&eicon_lock, flags);
++ if (user)
+ copy_to_user(p, skb->data, cnt);
+- spin_lock_irqsave(&eicon_lock, flags);
+- }
+ else
+ memcpy(p, skb->data, cnt);
+
+@@ -1459,6 +1468,7 @@
+
+ #ifndef MODULE
+
++#ifdef COMPAT_HAS_NEW_SETUP
+ static int __init
+ eicon_setup(char *line)
+ {
+@@ -1467,6 +1477,12 @@
+ char *str;
+
+ str = get_options(line, 4, ints);
++#else
++void
++eicon_setup(char *str, int *ints)
++{
++ int i, argc;
++#endif
+
+ argc = ints[0];
+ i = 1;
+@@ -1494,9 +1510,13 @@
+ #else
+ printk(KERN_INFO "Eicon ISDN active driver setup\n");
+ #endif
++#ifdef COMPAT_HAS_NEW_SETUP
+ return(1);
+ }
+ __setup("eicon=", eicon_setup);
++#else
++}
++#endif
+
+ #endif /* MODULE */
+
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_pci.c linux-2.4.29/drivers/isdn/eicon/eicon_pci.c
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_pci.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_pci.c 2005-03-22 15:06:45.522172360 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_pci.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_pci.c,v 1.18 2001/09/24 13:22:47 kai Exp $
+ *
+ * ISDN low-level module for Eicon active ISDN-Cards.
+ * Hardware-specific code for PCI cards.
+@@ -24,7 +24,7 @@
+ #include "adapter.h"
+ #include "uxio.h"
+
+-char *eicon_pci_revision = "$Revision: 1.1.4.1 $";
++char *eicon_pci_revision = "$Revision: 1.18 $";
+
+ #if CONFIG_PCI /* intire stuff is only for PCI */
+ #ifdef CONFIG_ISDN_DRV_EICON_PCI
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_pci.h linux-2.4.29/drivers/isdn/eicon/eicon_pci.h
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_pci.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_pci.h 2005-03-22 15:06:45.538169928 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_pci.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_pci.h,v 1.7 2001/09/24 13:22:47 kai Exp $
+ *
+ * ISDN low-level module for Eicon active ISDN-Cards (PCI part).
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/fourbri.c linux-2.4.29/drivers/isdn/eicon/fourbri.c
+--- linux-2.4.29.old/drivers/isdn/eicon/fourbri.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/fourbri.c 2005-03-22 15:06:45.553167648 +0100
+@@ -337,8 +337,7 @@
+ static int diva_server_4bri_start(card_t *card, byte *channels)
+ {
+ byte *ctl;
+- byte *shared;
+- int i;
++ byte *shared, i;
+ int adapter_num;
+
+ DPRINTF(("divas: start Diva Server 4BRI"));
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/kprintf.c linux-2.4.29/drivers/isdn/eicon/kprintf.c
+--- linux-2.4.29.old/drivers/isdn/eicon/kprintf.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/kprintf.c 2005-03-22 15:06:45.601160352 +0100
+@@ -18,6 +18,468 @@
+ #include "divalog.h"
+ #include "uxio.h"
+
++/*
++ * Implementation of printf and sprintf for kernel
++ */
++
++#define MAX_BUFF (80) /* limit size of temporary buffers */
++
++#define WRITE_CHAR(BUFFER, SIZE, C) \
++ if (--(SIZE) < 0) { (BUFFER)--; *(BUFFER) = '\0'; return; } *(BUFFER)++ = (C)
++
++
++/*
++ * convert a number to decimal ASCII
++ */
++
++static
++void do_decimal( char *temp,
++ int temp_len,
++ unsigned int value,
++ char *s)
++
++{
++ int i;
++
++ temp[0] = '\0';
++
++ for (i = 1; i < temp_len; i++)
++ {
++ temp[i] = (char) ((value % 10) + (int) '0');
++ value /= 10;
++ }
++
++ for (i = (temp_len - 1); temp[i] == '0'; i--)
++ {
++ ;
++ }
++
++ if (i == 0)
++ {
++ i++;
++ }
++
++ while (i >= 0)
++ {
++ *s++ = temp[i--];
++ }
++
++ return;
++}
++
++/*
++ * convert a number to octal ASCII
++ */
++
++static
++void do_octal( char *temp,
++ unsigned int value,
++ char *s)
++
++{
++ int i;
++
++ temp[0] = '\0';
++
++ for (i = 1; i <= 11; i++)
++ {
++ temp[i] = (char) ((value & 07) + (int) '0');
++ value >>= 3;
++ }
++ temp[11] &= '3';
++
++ for (i = 11; temp[i] == '0'; i--)
++ {
++ ;
++ }
++
++ if (i == 0)
++ {
++ i++;
++ }
++
++ while (i >= 0)
++ {
++ *s++ = temp[i--];
++ }
++
++ return;
++}
++
++/*
++ * convert a number to hex ASCII
++ */
++
++static
++void do_hex( char *temp,
++ unsigned int value,
++ char *s)
++
++{
++ int i;
++ static
++ char *dec_to_hex = "0123456789abcdef";
++
++ temp[0] = '\0';
++
++ for (i = 1; i <= 8; i++)
++ {
++ temp[i] = dec_to_hex[value & 0x0f];
++ value >>= 4;
++ }
++
++ for (i = 8; temp[i] == '0'; i--)
++ {
++ ;
++ }
++
++ if (i == 0)
++ {
++ i++;
++ }
++
++ while (i >= 0)
++ {
++ *s++ = temp[i--];
++ }
++
++ return;
++}
++
++/*
++ * convert a buffer to ASCII HEX
++ */
++
++static
++void do_buffer( char *buffer,
++ int length,
++ char *s)
++
++{
++ static
++ char hex_char [] = "0123456789abcdef";
++ char *b = buffer;
++ int hex_byte;
++ int nybble;
++
++ length = (length >= ((MAX_BUFF / 3) + 1)) ? (MAX_BUFF / 3) : length;
++
++ while (length)
++ {
++ hex_byte = (int) *b++;
++ nybble = (hex_byte >> 4) & 0xf;
++ *s++ = hex_char[nybble];
++ nybble = hex_byte & 0xf;
++ *s++ = hex_char[nybble];
++ *s++ = ' ';
++ length--;
++ }
++ *s = '\0';
++
++ return;
++}
++
++/*
++ * Body of sprintf function: behaves just like standard sprintf, except we
++ * have an extra argument (buffer size) which we use to ensure we don't
++ * overflow
++ */
++
++void Divas_vsprintf( char *buffer,
++ int size,
++ char *fmt,
++ va_list argptr)
++
++{
++ char c; /* single character buffer */
++ int i; /* handy scratch counter */
++ int f; /* format character (after %) */
++ char *str; /* pointer into string */
++ char temp[20]; /* temp buffer used in printing numbers */
++ char string[MAX_BUFF]; /* output from number conversion */
++ int length; /* length of string "str" */
++ char fill; /* fill character ' ' or '0' */
++ boolean_t leftjust; /* TRUE if left justified, else right justified */
++ int fmax, fmin; /* field specifiers % MIN . MAX s */
++ int leading; /* number of leading/trailing fill characters */
++ char sign; /* set to '-' for negative decimals */
++ int number; /* numeric argument */
++
++ char *buff_ptr; /* pointer to user's buffer of hex data */
++ int buff_len; /* length of hex data */
++
++ /* make sure we have somthing to write into */
++
++ if ((!buffer) || (size <= 0))
++ {
++ return;
++ }
++
++ while (TRUE)
++ {
++ /* echo characters until end or '%' encountered */
++
++ while ((c = *fmt++) != '%')
++ {
++ if (!c)
++ {
++ *buffer = '\0';
++ return;
++ }
++ WRITE_CHAR(buffer, size, c);
++ }
++
++ /* echo %% as % */
++
++ if (*fmt == '%')
++ {
++ WRITE_CHAR(buffer, size, *fmt);
++ continue;
++ }
++
++ /* %- turns on left-justify */
++
++ if ((leftjust = (boolean_t) ((*fmt == '-') ? TRUE : FALSE)))
++ {
++ fmt++;
++ }
++
++ /* %0 turns on zero filling */
++
++ if (*fmt == '0')
++ {
++ fill = '0';
++ }
++ else
++ {
++ fill = ' ';
++ }
++
++ /* minium field width specifier for %d, u, x, c, s */
++
++ fmin = 0;
++
++ if (*fmt == '*')
++ {
++ fmin = va_arg(argptr, int);
++ fmt++;
++ }
++ else
++ {
++ while ('0' <= *fmt && *fmt <= '9')
++ {
++ fmin = (fmin * 10) + (*fmt++ - '0');
++ }
++ }
++
++ /* maximum string width specifier for %s */
++
++ fmax = 0;
++
++ if (*fmt == '.')
++ {
++ if (*(++fmt) == '*')
++ {
++ fmax = va_arg(argptr, int);
++ fmt++;
++ }
++ else
++ {
++ while ('0' <= *fmt && *fmt <= '9')
++ {
++ fmax = (fmax * 10) + (*fmt++ - '0');
++ }
++ }
++ }
++
++ /* skip over 'l' option (ints are assumed same size as longs) */
++
++ if (*fmt == 'l')
++ {
++ fmt++;
++ }
++
++ /* get the format chacater */
++
++ if (!(f = *fmt++))
++ {
++ WRITE_CHAR(buffer, size, '%');
++ *buffer = '\0';
++ return;
++ }
++
++ sign = '\0'; /* sign == '-' for negative decimal */
++
++ str = string;
++
++ switch (f)
++ {
++ case 'c' :
++ string[0] = (char) va_arg(argptr, int);
++ string[1] = '\0';
++ fmax = 0;
++ fill = ' ';
++ break;
++
++ case 's' :
++ str = va_arg(argptr, char *);
++ fill = ' ';
++ break;
++
++ case 'D' :
++ case 'd' :
++ number = va_arg(argptr, int);
++ if (number < 0)
++ {
++ sign = '-';
++ number = -number;
++ }
++ do_decimal(temp, DIM(temp), (unsigned int) number, str);
++ fmax = 0;
++ break;
++
++ case 'U' :
++ case 'u' :
++ number = va_arg(argptr, int);
++ do_decimal(temp, DIM(temp), (unsigned int) number, str);
++ fmax = 0;
++ break;
++
++ case 'O' :
++ case 'o' :
++ number = va_arg(argptr, int);
++ do_octal(temp, (unsigned int) number, str);
++ fmax = 0;
++ break;
++
++ case 'X' :
++ case 'x' :
++ number = va_arg(argptr, int);
++ do_hex(temp, (unsigned int) number, str);
++ fmax = 0;
++ break;
++
++ case 'H' :
++ case 'h' :
++ buff_ptr = va_arg(argptr, char *);
++ buff_len = va_arg(argptr, int);
++ do_buffer(buff_ptr, buff_len, str);
++ fmax = 0;
++ break;
++
++ default :
++ WRITE_CHAR(buffer, size, ((char) f));
++ break;
++ }
++
++ /* get the length of the string */
++
++ length = 0;
++ while (str[length])
++ {
++ length++;
++ }
++
++ /* make sure we have fmax and fmin values that are O.K. */
++
++ if (fmin > DIM(string) || fmin < 0)
++ {
++ fmin = 0;
++ }
++
++ if (fmax > DIM(string) || fmax < 0)
++ {
++ fmax = 0;
++ }
++
++ /* figure out how many leading characters thare are */
++
++ leading = 0;
++
++ if (fmax || fmin)
++ {
++ if (fmax)
++ {
++ if (length > fmax)
++ {
++ length = fmax;
++ }
++ }
++
++ if (fmin)
++ {
++ leading = fmin - length;
++ }
++
++ if (sign == '-')
++ {
++ leading--;
++ }
++ }
++
++ /* output sign now, if fill is numeric */
++
++ if (sign == '-' && fill == '0')
++ {
++ WRITE_CHAR(buffer, size, '-');
++ }
++
++ /* if right justified, output fill characters */
++
++ if (!leftjust)
++ {
++ for (i = 0; i < leading; i++)
++ {
++ WRITE_CHAR(buffer, size, fill);
++ }
++ }
++
++ /* output sign now, if fill is spaces */
++
++ if (sign == '-' && fill == ' ')
++ {
++ WRITE_CHAR(buffer, size, '-');
++ }
++
++ /* now the actual value */
++
++ for (i = 0; i < length; i++)
++ {
++ WRITE_CHAR(buffer, size, str[i]);
++ }
++
++ /* if left justified, fill out with the fill character */
++
++ if (leftjust)
++ {
++ for (i = 0; i < leading; i++)
++ {
++ WRITE_CHAR(buffer, size, fill);
++ }
++ }
++ }
++}
++
++/*
++ * sprintf for kernel
++ *
++ * call our vsprintf assuming user has a big buffer....
++ */
++
++void DivasSprintf(char *buffer, char *fmt, ...)
++
++{
++ va_list argptr; /* pointer to additional args */
++
++ va_start(argptr, fmt);
++
++ Divas_vsprintf(buffer, 1024, fmt, argptr);
++
++ va_end(argptr);
++
++ return;
++}
++
+ void DivasPrintf(char *fmt, ...)
+
+ {
+@@ -40,7 +502,7 @@
+
+ /* call vsprintf to format the user's information */
+
+- vsnprintf(log.buffer, DIM(log.buffer), fmt, argptr);
++ Divas_vsprintf(log.buffer, DIM(log.buffer), fmt, argptr);
+
+ va_end(argptr);
+
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/lincfg.c linux-2.4.29/drivers/isdn/eicon/lincfg.c
+--- linux-2.4.29.old/drivers/isdn/eicon/lincfg.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/lincfg.c 2005-03-22 15:06:45.620157464 +0100
+@@ -26,6 +26,9 @@
+ #include "uxio.h"
+
+ #include <linux/pci.h>
++#ifndef COMPAT_HAS_2_2_PCI
++#include <linux/pci_ids.h>
++#endif
+ #include <linux/kernel.h>
+ #include <linux/ioport.h>
+
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/linchr.c linux-2.4.29/drivers/isdn/eicon/linchr.c
+--- linux-2.4.29.old/drivers/isdn/eicon/linchr.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/linchr.c 2005-03-22 15:06:45.635155184 +0100
+@@ -154,17 +154,17 @@
+ klog_t *pHeadItem;
+
+ if (BufferSize < sizeof(klog_t))
++ {
++ printk(KERN_WARNING "Divas: Divalog buffer specifed a size that is too small (%d - %d required)\n",
++ BufferSize, sizeof(klog_t));
+ return -EIO;
++ }
+
+ pHeadItem = (klog_t *) DivasLogFifoRead();
+
+ if (pHeadItem)
+ {
+- if(copy_to_user(pClientLogBuffer, pHeadItem, sizeof(klog_t)))
+- {
+- kfree(pHeadItem);
+- return -EFAULT;
+- }
++ memcpy(pClientLogBuffer, pHeadItem, sizeof(klog_t));
+ kfree(pHeadItem);
+ return sizeof(klog_t);
+ }
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/linio.c linux-2.4.29/drivers/isdn/eicon/linio.c
+--- linux-2.4.29.old/drivers/isdn/eicon/linio.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/linio.c 2005-03-22 15:06:45.651152752 +0100
+@@ -15,6 +15,7 @@
+ #include <linux/slab.h>
+ #include <linux/pci.h>
+ #include <linux/delay.h>
++#include <linux/isdn_compat.h>
+ #undef N_DATA
+
+ #include "uxio.h"
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/Makefile linux-2.4.29/drivers/isdn/hisax/Makefile
+--- linux-2.4.29.old/drivers/isdn/hisax/Makefile 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/Makefile 2005-03-22 15:06:45.819127216 +0100
+@@ -4,20 +4,17 @@
+
+ O_TARGET := vmlinux-obj.o
+
+-# Define maximum number of cards
+-
+-EXTRA_CFLAGS += -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS)
+-
+ # Objects that export symbols.
+
+-export-objs := config.o hisax_isac.o isdnhdlc.o
++export-objs := config.o fsm.o hisax_isac.o
+
+ # Multipart objects.
+
+ list-multi := hisax.o hisax_st5481.o
+ hisax-objs := config.o isdnl1.o tei.o isdnl2.o isdnl3.o \
+ lmgr.o q931.o callc.o fsm.o cert.o
+-hisax_st5481-objs := st5481_init.o st5481_usb.o st5481_d.o st5481_b.o
++hisax_st5481-objs := st5481_init.o st5481_usb.o st5481_d.o st5481_b.o \
++ st5481_hdlc.o
+
+ # Optional parts of multipart objects.
+ hisax-objs-$(CONFIG_HISAX_EURO) += l3dss1.o
+@@ -33,7 +30,7 @@
+ hisax-objs-$(CONFIG_HISAX_FRITZPCI) += avm_pci.o isac.o arcofi.o
+ hisax-objs-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o
+ hisax-objs-$(CONFIG_HISAX_IX1MICROR2) += ix1_micro.o isac.o arcofi.o hscx.o
+-hisax-objs-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o ipacx.o
++hisax-objs-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o
+ hisax-objs-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o
+ hisax-objs-$(CONFIG_HISAX_TELEINT) += teleint.o isac.o arcofi.o hfc_2bs0.o
+ hisax-objs-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o isar.o
+@@ -44,6 +41,7 @@
+ hisax-objs-$(CONFIG_HISAX_HFCS) += hfcscard.o hfc_2bds0.o
+ hisax-objs-$(CONFIG_HISAX_HFC_PCI) += hfc_pci.o
+ hisax-objs-$(CONFIG_HISAX_HFC_SX) += hfc_sx.o
++hisax-objs-$(CONFIG_HISAX_HFC_USB) += hfc_usbr.o
+ hisax-objs-$(CONFIG_HISAX_NICCY) += niccy.o isac.o arcofi.o hscx.o
+ hisax-objs-$(CONFIG_HISAX_ISURF) += isurf.o isac.o arcofi.o isar.o
+ hisax-objs-$(CONFIG_HISAX_HSTSAPHIR) += saphir.o isac.o arcofi.o hscx.o
+@@ -51,7 +49,6 @@
+ hisax-objs-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o
+ hisax-objs-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o
+ hisax-objs-$(CONFIG_HISAX_W6692) += w6692.o
+-hisax-objs-$(CONFIG_HISAX_ENTERNOW_PCI) += enternow_pci.o amd7930_fn.o
+ #hisax-objs-$(CONFIG_HISAX_TESTEMU) += testemu.o
+
+ hisax-objs += $(sort $(hisax-objs-y))
+@@ -61,10 +58,9 @@
+ obj-$(CONFIG_ISDN_DRV_HISAX) += hisax.o
+ obj-$(CONFIG_HISAX_SEDLBAUER_CS) += sedlbauer_cs.o
+ obj-$(CONFIG_HISAX_ELSA_CS) += elsa_cs.o
+-obj-$(CONFIG_HISAX_AVM_A1_CS) += avma1_cs.o
+-obj-$(CONFIG_HISAX_ST5481) += hisax_st5481.o isdnhdlc.o
+-obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_isac.o hisax_fcpcipnp.o
+-obj-$(CONFIG_USB_AUERISDN) += isdnhdlc.o
++obj-$(CONFIG_HISAX_HFC_USB_CS) += hfc_usb.o
++obj-$(CONFIG_HISAX_ST5481) += hisax_st5481.o
++obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_fcpcipnp.o hisax_isac.o
+
+ CERT := $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?)
+ CFLAGS_cert.o := -DCERTIFICATION=$(CERT)
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/amd7930.c linux-2.4.29/drivers/isdn/hisax/amd7930.c
+--- linux-2.4.29.old/drivers/isdn/hisax/amd7930.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/amd7930.c 2005-03-22 15:06:45.837124480 +0100
+@@ -0,0 +1,755 @@
++/* $Id: amd7930.c,v 1.8 2001/09/24 13:22:55 kai Exp $
++ *
++ * HiSax ISDN driver - chip specific routines for AMD 7930
++ *
++ * Author Brent Baccala
++ * Copyright by Brent Baccala <baccala@FreeSoft.org>
++ *
++ * This software may be used and distributed according to the terms
++ * of the GNU General Public License, incorporated herein by reference.
++ *
++ * - Existing ISDN HiSax driver provides all the smarts
++ * - it compiles, runs, talks to an isolated phone switch, connects
++ * to a Cisco, pings go through
++ * - AMD 7930 support only (no DBRI yet)
++ * - no US NI-1 support (may not work on US phone system - untested)
++ * - periodic packet loss, apparently due to lost interrupts
++ * - ISDN sometimes freezes, requiring reboot before it will work again
++ *
++ * The code is unreliable enough to be consider alpha
++ *
++ * This file is (c) under GNU General Public License
++ *
++ * Advanced Micro Devices' Am79C30A is an ISDN/audio chip used in the
++ * SparcStation 1+. The chip provides microphone and speaker interfaces
++ * which provide mono-channel audio at 8K samples per second via either
++ * 8-bit A-law or 8-bit mu-law encoding. Also, the chip features an
++ * ISDN BRI Line Interface Unit (LIU), I.430 S/T physical interface,
++ * which performs basic D channel LAPD processing and provides raw
++ * B channel data. The digital audio channel, the two ISDN B channels,
++ * and two 64 Kbps channels to the microprocessor are all interconnected
++ * via a multiplexer.
++ *
++ * This driver interfaces to the Linux HiSax ISDN driver, which performs
++ * all high-level Q.921 and Q.931 ISDN functions. The file is not
++ * itself a hardware driver; rather it uses functions exported by
++ * the AMD7930 driver in the sparcaudio subsystem (drivers/sbus/audio),
++ * allowing the chip to be simultaneously used for both audio and ISDN data.
++ * The hardware driver does _no_ buffering, but provides several callbacks
++ * which are called during interrupt service and should therefore run quickly.
++ *
++ * D channel transmission is performed by passing the hardware driver the
++ * address and size of an skb's data area, then waiting for a callback
++ * to signal successful transmission of the packet. A task is then
++ * queued to notify the HiSax driver that another packet may be transmitted.
++ *
++ * D channel reception is quite simple, mainly because of:
++ * 1) the slow speed of the D channel - 16 kbps, and
++ * 2) the presence of an 8- or 32-byte (depending on chip version) FIFO
++ * to buffer the D channel data on the chip
++ * Worst case scenario of back-to-back packets with the 8 byte buffer
++ * at 16 kbps yields an service time of 4 ms - long enough to preclude
++ * the need for fancy buffering. We queue a background task that copies
++ * data out of the receive buffer into an skb, and the hardware driver
++ * simply does nothing until we're done with the receive buffer and
++ * reset it for a new packet.
++ *
++ * B channel processing is more complex, because of:
++ * 1) the faster speed - 64 kbps,
++ * 2) the lack of any on-chip buffering (it interrupts for every byte), and
++ * 3) the lack of any chip support for HDLC encapsulation
++ *
++ * The HiSax driver can put each B channel into one of three modes -
++ * L1_MODE_NULL (channel disabled), L1_MODE_TRANS (transparent data relay),
++ * and L1_MODE_HDLC (HDLC encapsulation by low-level driver).
++ * L1_MODE_HDLC is the most common, used for almost all "pure" digital
++ * data sessions. L1_MODE_TRANS is used for ISDN audio.
++ *
++ * HDLC B channel transmission is performed via a large buffer into
++ * which the skb is copied while performing HDLC bit-stuffing. A CRC
++ * is computed and attached to the end of the buffer, which is then
++ * passed to the low-level routines for raw transmission. Once
++ * transmission is complete, the hardware driver is set to enter HDLC
++ * idle by successive transmission of mark (all 1) bytes, waiting for
++ * the ISDN driver to prepare another packet for transmission and
++ * deliver it.
++ *
++ * HDLC B channel reception is performed via an X-byte ring buffer
++ * divided into N sections of X/N bytes each. Defaults: X=256 bytes, N=4.
++ * As the hardware driver notifies us that each section is full, we
++ * hand it the next section and schedule a background task to peruse
++ * the received section, bit-by-bit, with an HDLC decoder. As
++ * packets are detected, they are copied into a large buffer while
++ * decoding HDLC bit-stuffing. The ending CRC is verified, and if
++ * it is correct, we alloc a new skb of the correct length (which we
++ * now know), copy the packet into it, and hand it to the upper layers.
++ * Optimization: for large packets, we hand the buffer (which also
++ * happens to be an skb) directly to the upper layer after an skb_trim,
++ * and alloc a new large buffer for future packets, thus avoiding a copy.
++ * Then we return to HDLC processing; state is saved between calls.
++ *
++ */
++
++#define __NO_VERSION__
++#include "hisax.h"
++#include "../../sbus/audio/amd7930.h"
++#include "isac.h"
++#include "isdnl1.h"
++#include "rawhdlc.h"
++#include <linux/interrupt.h>
++
++static const char *amd7930_revision = "$Revision: 1.8 $";
++
++#define RCV_BUFSIZE 1024 /* Size of raw receive buffer in bytes */
++#define RCV_BUFBLKS 4 /* Number of blocks to divide buffer into
++ * (must divide RCV_BUFSIZE) */
++
++static void Bchan_fill_fifo(struct BCState *, struct sk_buff *);
++
++static void
++Bchan_xmt_bh(struct BCState *bcs)
++{
++ struct sk_buff *skb;
++
++ if (bcs->hw.amd7930.tx_skb != NULL) {
++ dev_kfree_skb(bcs->hw.amd7930.tx_skb);
++ bcs->hw.amd7930.tx_skb = NULL;
++ }
++
++ if ((skb = skb_dequeue(&bcs->squeue))) {
++ Bchan_fill_fifo(bcs, skb);
++ } else {
++ clear_bit(BC_FLG_BUSY, &bcs->Flag);
++ bcs->event |= 1 << B_XMTBUFREADY;
++ queue_task(&bcs->tqueue, &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++ }
++}
++
++static void
++Bchan_xmit_callback(struct BCState *bcs)
++{
++ queue_task(&bcs->hw.amd7930.tq_xmt, &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++}
++
++/* B channel transmission: two modes (three, if you count L1_MODE_NULL)
++ *
++ * L1_MODE_HDLC - We need to do HDLC encapsulation before transmiting
++ * the packet (i.e. make_raw_hdlc_data). Since this can be a
++ * time-consuming operation, our completion callback just schedules
++ * a bottom half to do encapsulation for the next packet. In between,
++ * the link will just idle
++ *
++ * L1_MODE_TRANS - Data goes through, well, transparent. No HDLC encap,
++ * and we can't just let the link idle, so the "bottom half" actually
++ * gets called during the top half (it's our callback routine in this case),
++ * but it's a lot faster now since we don't call make_raw_hdlc_data
++ */
++
++static void
++Bchan_fill_fifo(struct BCState *bcs, struct sk_buff *skb)
++{
++ struct IsdnCardState *cs = bcs->cs;
++ int len;
++
++ if ((cs->debug & L1_DEB_HSCX) || (cs->debug & L1_DEB_HSCX_FIFO)) {
++ char tmp[1024];
++ char *t = tmp;
++
++ t += sprintf(t, "amd7930_fill_fifo %c cnt %d",
++ bcs->channel ? 'B' : 'A', skb->len);
++ if (cs->debug & L1_DEB_HSCX_FIFO)
++ QuickHex(t, skb->data, skb->len);
++ debugl1(cs, tmp);
++ }
++
++ if (bcs->mode == L1_MODE_HDLC) {
++ len = make_raw_hdlc_data(skb->data, skb->len,
++ bcs->hw.amd7930.tx_buff, RAW_BUFMAX);
++ if (len > 0)
++ amd7930_bxmit(0, bcs->channel,
++ bcs->hw.amd7930.tx_buff, len,
++ (void *) &Bchan_xmit_callback,
++ (void *) bcs);
++ dev_kfree_skb(skb);
++ } else if (bcs->mode == L1_MODE_TRANS) {
++ amd7930_bxmit(0, bcs->channel,
++ bcs->hw.amd7930.tx_buff, skb->len,
++ (void *) &Bchan_xmt_bh,
++ (void *) bcs);
++ bcs->hw.amd7930.tx_skb = skb;
++ } else {
++ dev_kfree_skb(skb);
++ }
++}
++
++static void
++Bchan_mode(struct BCState *bcs, int mode, int bc)
++{
++ struct IsdnCardState *cs = bcs->cs;
++
++ if (cs->debug & L1_DEB_HSCX) {
++ char tmp[40];
++ sprintf(tmp, "AMD 7930 mode %d bchan %d/%d",
++ mode, bc, bcs->channel);
++ debugl1(cs, tmp);
++ }
++ bcs->mode = mode;
++}
++
++/* Bchan_l2l1 is the entry point for upper layer routines that want to
++ * transmit on the B channel. PH_DATA_REQ is a normal packet that
++ * we either start transmitting (if idle) or queue (if busy).
++ * PH_PULL_REQ can be called to request a callback message (PH_PULL_CNF)
++ * once the link is idle. After a "pull" callback, the upper layer
++ * routines can use PH_PULL_IND to send data.
++ */
++
++static void
++Bchan_l2l1(struct PStack *st, int pr, void *arg)
++{
++ struct sk_buff *skb = arg;
++
++ switch (pr) {
++ case (PH_DATA_REQ):
++ if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
++ skb_queue_tail(&st->l1.bcs->squeue, skb);
++ } else {
++ test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
++ Bchan_fill_fifo(st->l1.bcs, skb);
++ }
++ break;
++ case (PH_PULL_IND):
++ if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
++ printk(KERN_WARNING "amd7930: this shouldn't happen\n");
++ break;
++ }
++ test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
++ Bchan_fill_fifo(st->l1.bcs, skb);
++ break;
++ case (PH_PULL_REQ):
++ if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
++ clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
++ st->l1.l1l2(st, PH_PULL_CNF, NULL);
++ } else
++ set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
++ break;
++ }
++}
++
++/* Receiver callback and bottom half - decodes HDLC at leisure (if
++ * L1_MODE_HDLC) and passes newly received skb on via bcs->rqueue. If
++ * a large packet is received, stick rv_skb (the buffer that the
++ * packet has been decoded into) on the receive queue and alloc a new
++ * (large) skb to act as buffer for future receives. If a small
++ * packet is received, leave rv_skb alone, alloc a new skb of the
++ * correct size, and copy the packet into it
++ */
++
++static void
++Bchan_recv_callback(struct BCState *bcs)
++{
++ struct amd7930_hw *hw = &bcs->hw.amd7930;
++
++ hw->rv_buff_in += RCV_BUFSIZE/RCV_BUFBLKS;
++ hw->rv_buff_in %= RCV_BUFSIZE;
++
++ if (hw->rv_buff_in != hw->rv_buff_out) {
++ amd7930_brecv(0, bcs->channel,
++ hw->rv_buff + hw->rv_buff_in,
++ RCV_BUFSIZE/RCV_BUFBLKS,
++ (void *) &Bchan_recv_callback, (void *) bcs);
++ }
++
++ queue_task(&hw->tq_rcv, &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++}
++
++static void
++Bchan_rcv_bh(struct BCState *bcs)
++{
++ struct IsdnCardState *cs = bcs->cs;
++ struct amd7930_hw *hw = &bcs->hw.amd7930;
++ struct sk_buff *skb;
++ int len;
++
++ if (cs->debug & L1_DEB_HSCX) {
++ char tmp[1024];
++
++ sprintf(tmp, "amd7930_Bchan_rcv (%d/%d)",
++ hw->rv_buff_in, hw->rv_buff_out);
++ debugl1(cs, tmp);
++ QuickHex(tmp, hw->rv_buff + hw->rv_buff_out,
++ RCV_BUFSIZE/RCV_BUFBLKS);
++ debugl1(cs, tmp);
++ }
++
++ do {
++ if (bcs->mode == L1_MODE_HDLC) {
++ while ((len = read_raw_hdlc_data(hw->hdlc_state,
++ hw->rv_buff + hw->rv_buff_out, RCV_BUFSIZE/RCV_BUFBLKS,
++ hw->rv_skb->tail, HSCX_BUFMAX))) {
++ if (len > 0 && (cs->debug & L1_DEB_HSCX_FIFO)) {
++ char tmp[1024];
++ char *t = tmp;
++
++ t += sprintf(t, "amd7930_Bchan_rcv %c cnt %d", bcs->channel ? 'B' : 'A', len);
++ QuickHex(t, hw->rv_skb->tail, len);
++ debugl1(cs, tmp);
++ }
++
++ if (len > HSCX_BUFMAX/2) {
++ /* Large packet received */
++
++ if (!(skb = dev_alloc_skb(HSCX_BUFMAX))) {
++ printk(KERN_WARNING "amd7930: receive out of memory");
++ } else {
++ skb_put(hw->rv_skb, len);
++ skb_queue_tail(&bcs->rqueue, hw->rv_skb);
++ hw->rv_skb = skb;
++ bcs->event |= 1 << B_RCVBUFREADY;
++ queue_task(&bcs->tqueue, &tq_immediate);
++ }
++ } else if (len > 0) {
++ /* Small packet received */
++
++ if (!(skb = dev_alloc_skb(len))) {
++ printk(KERN_WARNING "amd7930: receive out of memory\n");
++ } else {
++ memcpy(skb_put(skb, len), hw->rv_skb->tail, len);
++ skb_queue_tail(&bcs->rqueue, skb);
++ bcs->event |= 1 << B_RCVBUFREADY;
++ queue_task(&bcs->tqueue, &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++ }
++ } else {
++ /* Reception Error */
++ /* printk("amd7930: B channel receive error\n"); */
++ }
++ }
++ } else if (bcs->mode == L1_MODE_TRANS) {
++ if (!(skb = dev_alloc_skb(RCV_BUFSIZE/RCV_BUFBLKS))) {
++ printk(KERN_WARNING "amd7930: receive out of memory\n");
++ } else {
++ memcpy(skb_put(skb, RCV_BUFSIZE/RCV_BUFBLKS),
++ hw->rv_buff + hw->rv_buff_out,
++ RCV_BUFSIZE/RCV_BUFBLKS);
++ skb_queue_tail(&bcs->rqueue, skb);
++ bcs->event |= 1 << B_RCVBUFREADY;
++ queue_task(&bcs->tqueue, &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++ }
++ }
++
++ if (hw->rv_buff_in == hw->rv_buff_out) {
++ /* Buffer was filled up - need to restart receiver */
++ amd7930_brecv(0, bcs->channel,
++ hw->rv_buff + hw->rv_buff_in,
++ RCV_BUFSIZE/RCV_BUFBLKS,
++ (void *) &Bchan_recv_callback,
++ (void *) bcs);
++ }
++
++ hw->rv_buff_out += RCV_BUFSIZE/RCV_BUFBLKS;
++ hw->rv_buff_out %= RCV_BUFSIZE;
++
++ } while (hw->rv_buff_in != hw->rv_buff_out);
++}
++
++static void
++Bchan_close(struct BCState *bcs)
++{
++ struct sk_buff *skb;
++
++ Bchan_mode(bcs, 0, 0);
++ amd7930_bclose(0, bcs->channel);
++
++ if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
++ skb_queue_purge(&bcs->rqueue);
++ skb_queue_purge(&bcs->squeue);
++ }
++ test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
++}
++
++static int
++Bchan_open(struct BCState *bcs)
++{
++ struct amd7930_hw *hw = &bcs->hw.amd7930;
++
++ if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
++ skb_queue_head_init(&bcs->rqueue);
++ skb_queue_head_init(&bcs->squeue);
++ }
++ test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
++
++ amd7930_bopen(0, bcs->channel, 0xff);
++ hw->rv_buff_in = 0;
++ hw->rv_buff_out = 0;
++ hw->tx_skb = NULL;
++ init_hdlc_state(hw->hdlc_state, 0);
++ amd7930_brecv(0, bcs->channel,
++ hw->rv_buff + hw->rv_buff_in, RCV_BUFSIZE/RCV_BUFBLKS,
++ (void *) &Bchan_recv_callback, (void *) bcs);
++
++ bcs->event = 0;
++ bcs->tx_cnt = 0;
++ return (0);
++}
++
++static void
++Bchan_init(struct BCState *bcs)
++{
++ if (!(bcs->hw.amd7930.tx_buff = kmalloc(RAW_BUFMAX, GFP_ATOMIC))) {
++ printk(KERN_WARNING
++ "HiSax: No memory for amd7930.tx_buff\n");
++ return;
++ }
++ if (!(bcs->hw.amd7930.rv_buff = kmalloc(RCV_BUFSIZE, GFP_ATOMIC))) {
++ printk(KERN_WARNING
++ "HiSax: No memory for amd7930.rv_buff\n");
++ return;
++ }
++ if (!(bcs->hw.amd7930.rv_skb = dev_alloc_skb(HSCX_BUFMAX))) {
++ printk(KERN_WARNING
++ "HiSax: No memory for amd7930.rv_skb\n");
++ return;
++ }
++ if (!(bcs->hw.amd7930.hdlc_state = kmalloc(sizeof(struct hdlc_state),
++ GFP_ATOMIC))) {
++ printk(KERN_WARNING
++ "HiSax: No memory for amd7930.hdlc_state\n");
++ return;
++ }
++
++ bcs->hw.amd7930.tq_rcv.sync = 0;
++ bcs->hw.amd7930.tq_rcv.routine = (void (*)(void *)) &Bchan_rcv_bh;
++ bcs->hw.amd7930.tq_rcv.data = (void *) bcs;
++
++ bcs->hw.amd7930.tq_xmt.sync = 0;
++ bcs->hw.amd7930.tq_xmt.routine = (void (*)(void *)) &Bchan_xmt_bh;
++ bcs->hw.amd7930.tq_xmt.data = (void *) bcs;
++}
++
++static void
++Bchan_manl1(struct PStack *st, int pr,
++ void *arg)
++{
++ switch (pr) {
++ case (PH_ACTIVATE_REQ):
++ test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
++ Bchan_mode(st->l1.bcs, st->l1.mode, st->l1.bc);
++ st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
++ break;
++ case (PH_DEACTIVATE_REQ):
++ if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
++ Bchan_mode(st->l1.bcs, 0, 0);
++ test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
++ break;
++ }
++}
++
++int
++setstack_amd7930(struct PStack *st, struct BCState *bcs)
++{
++ if (Bchan_open(bcs))
++ return (-1);
++ st->l1.bcs = bcs;
++ st->l2.l2l1 = Bchan_l2l1;
++ st->ma.manl1 = Bchan_manl1;
++ setstack_manager(st);
++ bcs->st = st;
++ return (0);
++}
++
++
++static void
++amd7930_drecv_callback(void *arg, int error, unsigned int count)
++{
++ struct IsdnCardState *cs = (struct IsdnCardState *) arg;
++ static struct tq_struct task;
++ struct sk_buff *skb;
++
++ /* NOTE: This function is called directly from an interrupt handler */
++
++ if (1) {
++ if (!(skb = alloc_skb(count, GFP_ATOMIC)))
++ printk(KERN_WARNING "HiSax: D receive out of memory\n");
++ else {
++ memcpy(skb_put(skb, count), cs->rcvbuf, count);
++ skb_queue_tail(&cs->rq, skb);
++ }
++
++ task.routine = (void *) DChannel_proc_rcv;
++ task.data = (void *) cs;
++ queue_task(&task, &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++ }
++
++ if (cs->debug & L1_DEB_ISAC_FIFO) {
++ char tmp[128];
++ char *t = tmp;
++
++ t += sprintf(t, "amd7930 Drecv cnt %d", count);
++ if (error) t += sprintf(t, " ERR %x", error);
++ QuickHex(t, cs->rcvbuf, count);
++ debugl1(cs, tmp);
++ }
++
++ amd7930_drecv(0, cs->rcvbuf, MAX_DFRAME_LEN,
++ &amd7930_drecv_callback, cs);
++}
++
++static void
++amd7930_dxmit_callback(void *arg, int error)
++{
++ struct IsdnCardState *cs = (struct IsdnCardState *) arg;
++ static struct tq_struct task;
++
++ /* NOTE: This function is called directly from an interrupt handler */
++
++ /* may wish to do retransmission here, if error indicates collision */
++
++ if (cs->debug & L1_DEB_ISAC_FIFO) {
++ char tmp[128];
++ char *t = tmp;
++
++ t += sprintf(t, "amd7930 Dxmit cnt %d", cs->tx_skb->len);
++ if (error) t += sprintf(t, " ERR %x", error);
++ QuickHex(t, cs->tx_skb->data, cs->tx_skb->len);
++ debugl1(cs, tmp);
++ }
++
++ cs->tx_skb = NULL;
++
++ task.routine = (void *) DChannel_proc_xmt;
++ task.data = (void *) cs;
++ queue_task(&task, &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++}
++
++static void
++amd7930_Dchan_l2l1(struct PStack *st, int pr, void *arg)
++{
++ struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
++ struct sk_buff *skb = arg;
++ char str[64];
++
++ switch (pr) {
++ case (PH_DATA_REQ):
++ if (cs->tx_skb) {
++ skb_queue_tail(&cs->sq, skb);
++#ifdef L2FRAME_DEBUG /* psa */
++ if (cs->debug & L1_DEB_LAPD)
++ Logl2Frame(cs, skb, "PH_DATA Queued", 0);
++#endif
++ } else {
++ if ((cs->dlogflag) && (!(skb->data[2] & 1))) {
++ /* I-FRAME */
++ LogFrame(cs, skb->data, skb->len);
++ sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
++ dlogframe(cs, skb->data+4, skb->len-4,
++ str);
++ }
++ cs->tx_skb = skb;
++ cs->tx_cnt = 0;
++#ifdef L2FRAME_DEBUG /* psa */
++ if (cs->debug & L1_DEB_LAPD)
++ Logl2Frame(cs, skb, "PH_DATA", 0);
++#endif
++ amd7930_dxmit(0, skb->data, skb->len,
++ &amd7930_dxmit_callback, cs);
++ }
++ break;
++ case (PH_PULL_IND):
++ if (cs->tx_skb) {
++ if (cs->debug & L1_DEB_WARN)
++ debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
++ skb_queue_tail(&cs->sq, skb);
++ break;
++ }
++ if ((cs->dlogflag) && (!(skb->data[2] & 1))) { /* I-FRAME */
++ LogFrame(cs, skb->data, skb->len);
++ sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
++ dlogframe(cs, skb->data + 4, skb->len - 4,
++ str);
++ }
++ cs->tx_skb = skb;
++ cs->tx_cnt = 0;
++#ifdef L2FRAME_DEBUG /* psa */
++ if (cs->debug & L1_DEB_LAPD)
++ Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
++#endif
++ amd7930_dxmit(0, cs->tx_skb->data, cs->tx_skb->len,
++ &amd7930_dxmit_callback, cs);
++ break;
++ case (PH_PULL_REQ):
++#ifdef L2FRAME_DEBUG /* psa */
++ if (cs->debug & L1_DEB_LAPD)
++ debugl1(cs, "-> PH_REQUEST_PULL");
++#endif
++ if (!cs->tx_skb) {
++ test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
++ st->l1.l1l2(st, PH_PULL_CNF, NULL);
++ } else
++ test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
++ break;
++ }
++}
++
++int
++setDstack_amd7930(struct PStack *st, struct IsdnCardState *cs)
++{
++ st->l2.l2l1 = amd7930_Dchan_l2l1;
++ if (! cs->rcvbuf) {
++ printk("setDstack_amd7930: No cs->rcvbuf!\n");
++ } else {
++ amd7930_drecv(0, cs->rcvbuf, MAX_DFRAME_LEN,
++ &amd7930_drecv_callback, cs);
++ }
++ return (0);
++}
++
++static void
++manl1_msg(struct IsdnCardState *cs, int msg, void *arg) {
++ struct PStack *st;
++
++ st = cs->stlist;
++ while (st) {
++ st->ma.manl1(st, msg, arg);
++ st = st->next;
++ }
++}
++
++static void
++amd7930_new_ph(struct IsdnCardState *cs)
++{
++ switch (amd7930_get_liu_state(0)) {
++ case 3:
++ manl1_msg(cs, PH_POWERUP_CNF, NULL);
++ break;
++
++ case 7:
++ manl1_msg(cs, PH_I4_P8_IND, NULL);
++ break;
++
++ case 8:
++ manl1_msg(cs, PH_RSYNC_IND, NULL);
++ break;
++ }
++}
++
++/* amd7930 LIU state change callback */
++
++static void
++amd7930_liu_callback(struct IsdnCardState *cs)
++{
++ static struct tq_struct task;
++
++ if (!cs)
++ return;
++
++ if (cs->debug & L1_DEB_ISAC) {
++ char tmp[32];
++ sprintf(tmp, "amd7930_liu state %d", amd7930_get_liu_state(0));
++ debugl1(cs, tmp);
++ }
++
++ task.sync = 0;
++ task.routine = (void *) &amd7930_new_ph;
++ task.data = (void *) cs;
++ queue_task(&task, &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++}
++
++void
++amd7930_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
++{
++ u_char val;
++ char tmp[32];
++
++ if (cs->debug & L1_DEB_ISAC) {
++ char tmp[32];
++ sprintf(tmp, "amd7930_l1cmd msg %x", msg);
++ debugl1(cs, tmp);
++ }
++
++ switch(msg) {
++ case PH_RESET_REQ:
++ if (amd7930_get_liu_state(0) <= 3)
++ amd7930_liu_activate(0,0);
++ else
++ amd7930_liu_deactivate(0);
++ break;
++ case PH_ENABLE_REQ:
++ break;
++ case PH_INFO3_REQ:
++ amd7930_liu_activate(0,0);
++ break;
++ case PH_TESTLOOP_REQ:
++ break;
++ default:
++ if (cs->debug & L1_DEB_WARN) {
++ sprintf(tmp, "amd7930_l1cmd unknown %4x", msg);
++ debugl1(cs, tmp);
++ }
++ break;
++ }
++}
++
++static void init_amd7930(struct IsdnCardState *cs)
++{
++ Bchan_init(&cs->bcs[0]);
++ Bchan_init(&cs->bcs[1]);
++ cs->bcs[0].BC_SetStack = setstack_amd7930;
++ cs->bcs[1].BC_SetStack = setstack_amd7930;
++ cs->bcs[0].BC_Close = Bchan_close;
++ cs->bcs[1].BC_Close = Bchan_close;
++ Bchan_mode(cs->bcs, 0, 0);
++ Bchan_mode(cs->bcs + 1, 0, 0);
++}
++
++void
++release_amd7930(struct IsdnCardState *cs)
++{
++}
++
++static int
++amd7930_card_msg(struct IsdnCardState *cs, int mt, void *arg)
++{
++ switch (mt) {
++ case CARD_RESET:
++ return(0);
++ case CARD_RELEASE:
++ release_amd7930(cs);
++ return(0);
++ case CARD_INIT:
++ cs->l1cmd = amd7930_l1cmd;
++ amd7930_liu_init(0, &amd7930_liu_callback, (void *)cs);
++ init_amd7930(cs);
++ return(0);
++ case CARD_TEST:
++ return(0);
++ }
++ return(0);
++}
++
++int __init
++setup_amd7930(struct IsdnCard *card)
++{
++ struct IsdnCardState *cs = card->cs;
++ char tmp[64];
++
++ strcpy(tmp, amd7930_revision);
++ printk(KERN_INFO "HiSax: AMD7930 driver Rev. %s\n", HiSax_getrev(tmp));
++ if (cs->typ != ISDN_CTYPE_AMD7930)
++ return (0);
++
++ cs->irq = amd7930_get_irqnum(0);
++ if (cs->irq == 0)
++ return (0);
++
++ cs->cardmsg = &amd7930_card_msg;
++
++ return (1);
++}
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/arcofi.c linux-2.4.29/drivers/isdn/hisax/arcofi.c
+--- linux-2.4.29.old/drivers/isdn/hisax/arcofi.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/arcofi.c 2005-03-22 15:06:45.852122200 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: arcofi.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: arcofi.c,v 1.14 2001/09/24 13:22:55 kai Exp $
+ *
+ * Ansteuerung ARCOFI 2165
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/arcofi.h linux-2.4.29/drivers/isdn/hisax/arcofi.h
+--- linux-2.4.29.old/drivers/isdn/hisax/arcofi.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/arcofi.h 2005-03-22 15:06:45.872119160 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: arcofi.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id$
+ *
+ * Ansteuerung ARCOFI 2165
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/asuscom.c linux-2.4.29/drivers/isdn/hisax/asuscom.c
+--- linux-2.4.29.old/drivers/isdn/hisax/asuscom.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/asuscom.c 2005-03-22 15:06:45.889116576 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: asuscom.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: asuscom.c,v 1.14 2001/09/24 13:22:55 kai Exp $
+ *
+ * low level stuff for ASUSCOM NETWORK INC. ISDNLink cards
+ *
+@@ -14,7 +14,6 @@
+
+ #define __NO_VERSION__
+ #include <linux/init.h>
+-#include <linux/isapnp.h>
+ #include "hisax.h"
+ #include "isac.h"
+ #include "ipac.h"
+@@ -23,7 +22,7 @@
+
+ extern const char *CardType[];
+
+-const char *Asuscom_revision = "$Revision: 1.1.4.1 $";
++const char *Asuscom_revision = "$Revision: 1.14 $";
+
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+@@ -310,27 +309,6 @@
+ return(0);
+ }
+
+-#ifdef __ISAPNP__
+-static struct isapnp_device_id asus_ids[] __initdata = {
+- { ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
+- ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
+- (unsigned long) "Asus1688 PnP" },
+- { ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1690),
+- ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1690),
+- (unsigned long) "Asus1690 PnP" },
+- { ISAPNP_VENDOR('S', 'I', 'E'), ISAPNP_FUNCTION(0x0020),
+- ISAPNP_VENDOR('S', 'I', 'E'), ISAPNP_FUNCTION(0x0020),
+- (unsigned long) "Isurf2 PnP" },
+- { ISAPNP_VENDOR('E', 'L', 'F'), ISAPNP_FUNCTION(0x0000),
+- ISAPNP_VENDOR('E', 'L', 'F'), ISAPNP_FUNCTION(0x0000),
+- (unsigned long) "Iscas TE320" },
+- { 0, }
+-};
+-
+-static struct isapnp_device_id *adev = &asus_ids[0];
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+-
+ int __init
+ setup_asuscom(struct IsdnCard *card)
+ {
+@@ -343,45 +321,7 @@
+ printk(KERN_INFO "HiSax: Asuscom ISDNLink driver Rev. %s\n", HiSax_getrev(tmp));
+ if (cs->typ != ISDN_CTYPE_ASUSCOM)
+ return (0);
+-#ifdef __ISAPNP__
+- if (!card->para[1] && isapnp_present()) {
+- struct pci_bus *pb;
+- struct pci_dev *pd;
+-
+- while(adev->card_vendor) {
+- if ((pb = isapnp_find_card(adev->card_vendor,
+- adev->card_device, pnp_c))) {
+- pnp_c = pb;
+- pd = NULL;
+- if ((pd = isapnp_find_dev(pnp_c,
+- adev->vendor, adev->function, pd))) {
+- printk(KERN_INFO "HiSax: %s detected\n",
+- (char *)adev->driver_data);
+- pd->prepare(pd);
+- pd->deactivate(pd);
+- pd->activate(pd);
+- card->para[1] = pd->resource[0].start;
+- card->para[0] = pd->irq_resource[0].start;
+- if (!card->para[0] || !card->para[1]) {
+- printk(KERN_ERR "AsusPnP:some resources are missing %ld/%lx\n",
+- card->para[0], card->para[1]);
+- pd->deactivate(pd);
+- return(0);
+- }
+- break;
+- } else {
+- printk(KERN_ERR "AsusPnP: PnP error card found, no device\n");
+- }
+- }
+- adev++;
+- pnp_c=NULL;
+- }
+- if (!adev->card_vendor) {
+- printk(KERN_INFO "AsusPnP: no ISAPnP card found\n");
+- return(0);
+- }
+- }
+-#endif
++
+ bytecnt = 8;
+ cs->hw.asus.cfg_reg = card->para[1];
+ cs->irq = card->para[0];
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/avm_a1.c linux-2.4.29/drivers/isdn/hisax/avm_a1.c
+--- linux-2.4.29.old/drivers/isdn/hisax/avm_a1.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/avm_a1.c 2005-03-22 15:06:45.904114296 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: avm_a1.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: avm_a1.c,v 2.15 2001/09/24 13:22:55 kai Exp $
+ *
+ * low level stuff for AVM A1 (Fritz) isdn cards
+ *
+@@ -18,7 +18,7 @@
+ #include "isdnl1.h"
+
+ extern const char *CardType[];
+-static const char *avm_revision = "$Revision: 1.1.4.1 $";
++static const char *avm_revision = "$Revision: 2.15 $";
+
+ #define AVM_A1_STAT_ISAC 0x01
+ #define AVM_A1_STAT_HSCX 0x02
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/avm_a1p.c linux-2.4.29/drivers/isdn/hisax/avm_a1p.c
+--- linux-2.4.29.old/drivers/isdn/hisax/avm_a1p.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/avm_a1p.c 2005-03-22 15:06:45.919112016 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: avm_a1p.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: avm_a1p.c,v 2.9 2001/09/24 13:22:55 kai Exp $
+ *
+ * low level stuff for the following AVM cards:
+ * A1 PCMCIA
+@@ -57,7 +57,7 @@
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+
+-static const char *avm_revision = "$Revision: 1.1.4.1 $";
++static const char *avm_revision = "$Revision: 2.9 $";
+
+ static inline u_char
+ ReadISAC(struct IsdnCardState *cs, u_char offset)
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/avm_pci.c linux-2.4.29/drivers/isdn/hisax/avm_pci.c
+--- linux-2.4.29.old/drivers/isdn/hisax/avm_pci.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/avm_pci.c 2005-03-22 15:06:45.945108064 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: avm_pci.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: avm_pci.c,v 1.29 2001/09/24 13:22:55 kai Exp $
+ *
+ * low level stuff for AVM Fritz!PCI and ISA PnP isdn cards
+ *
+@@ -19,11 +19,11 @@
+ #include "isac.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
+-#include <linux/isapnp.h>
++#include <linux/isdn_compat.h>
+ #include <linux/interrupt.h>
+
+ extern const char *CardType[];
+-static const char *avm_pci_rev = "$Revision: 1.1.4.1 $";
++static const char *avm_pci_rev = "$Revision: 1.29 $";
+
+ #define AVM_FRITZ_PCI 1
+ #define AVM_FRITZ_PNP 2
+@@ -291,8 +291,7 @@
+ debugl1(cs, "hdlc_empty_fifo: incoming packet too large");
+ return;
+ }
+- p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx;
+- ptr = (u_int *)p;
++ ptr = (u_int *) p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx;
+ bcs->hw.hdlc.rcvidx += count;
+ if (cs->subtyp == AVM_FRITZ_PCI) {
+ outl(idx, cs->hw.avm.cfg_reg + 4);
+@@ -353,8 +352,7 @@
+ }
+ if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+ debugl1(cs, "hdlc_fill_fifo %d/%ld", count, bcs->tx_skb->len);
+- p = bcs->tx_skb->data;
+- ptr = (u_int *)p;
++ ptr = (u_int *) p = bcs->tx_skb->data;
+ skb_pull(bcs->tx_skb, count);
+ bcs->tx_cnt -= count;
+ bcs->hw.hdlc.count += count;
+@@ -766,10 +764,6 @@
+ }
+
+ static struct pci_dev *dev_avm __initdata = NULL;
+-#ifdef __ISAPNP__
+-static struct pci_bus *bus_avm __initdata = NULL;
+-static struct pci_dev *pnp_avm __initdata = NULL;
+-#endif
+
+ int __init
+ setup_avm_pcipnp(struct IsdnCard *card)
+@@ -783,47 +777,10 @@
+ if (cs->typ != ISDN_CTYPE_FRITZPCI)
+ return (0);
+ if (card->para[1]) {
+- /* old manual method */
+ cs->hw.avm.cfg_reg = card->para[1];
+ cs->irq = card->para[0];
+ cs->subtyp = AVM_FRITZ_PNP;
+ } else {
+-#ifdef __ISAPNP__
+- if (isapnp_present()) {
+- struct pci_bus *ba;
+- if ((ba = isapnp_find_card(
+- ISAPNP_VENDOR('A', 'V', 'M'),
+- ISAPNP_FUNCTION(0x0900), bus_avm))) {
+- bus_avm = ba;
+- pnp_avm = NULL;
+- if ((pnp_avm = isapnp_find_dev(bus_avm,
+- ISAPNP_VENDOR('A', 'V', 'M'),
+- ISAPNP_FUNCTION(0x0900), pnp_avm))) {
+- pnp_avm->prepare(pnp_avm);
+- pnp_avm->deactivate(pnp_avm);
+- pnp_avm->activate(pnp_avm);
+- cs->hw.avm.cfg_reg =
+- pnp_avm->resource[0].start;
+- cs->irq =
+- pnp_avm->irq_resource[0].start;
+- if (!cs->irq) {
+- printk(KERN_ERR "FritzPnP:No IRQ\n");
+- pnp_avm->deactivate(pnp_avm);
+- return(0);
+- }
+- if (!cs->hw.avm.cfg_reg) {
+- printk(KERN_ERR "FritzPnP:No IO address\n");
+- pnp_avm->deactivate(pnp_avm);
+- return(0);
+- }
+- cs->subtyp = AVM_FRITZ_PNP;
+- goto ready;
+- }
+- }
+- } else {
+- printk(KERN_INFO "FritzPnP: no ISA PnP present\n");
+- }
+-#endif
+ #if CONFIG_PCI
+ if (!pci_present()) {
+ printk(KERN_ERR "FritzPCI: no PCI bus present\n");
+@@ -838,7 +795,7 @@
+ }
+ if (pci_enable_device(dev_avm))
+ return(0);
+- cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
++ cs->hw.avm.cfg_reg = pci_resource_start_io(dev_avm, 1);
+ if (!cs->hw.avm.cfg_reg) {
+ printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
+ return(0);
+@@ -854,7 +811,6 @@
+ return (0);
+ #endif /* CONFIG_PCI */
+ }
+-ready:
+ cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
+ if (check_region((cs->hw.avm.cfg_reg), 32)) {
+ printk(KERN_WARNING
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/bkm_a4t.c linux-2.4.29/drivers/isdn/hisax/bkm_a4t.c
+--- linux-2.4.29.old/drivers/isdn/hisax/bkm_a4t.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/bkm_a4t.c 2005-03-22 15:06:45.962105480 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: bkm_a4t.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: bkm_a4t.c,v 1.22 2001/09/24 13:22:55 kai Exp $
+ *
+ * low level stuff for T-Berkom A4T
+ *
+@@ -20,11 +20,12 @@
+ #include "jade.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+ #include "bkm_ax.h"
+
+ extern const char *CardType[];
+
+-const char *bkm_a4t_revision = "$Revision: 1.1.4.1 $";
++const char *bkm_a4t_revision = "$Revision: 1.22 $";
+
+
+ static inline u_char
+@@ -293,13 +294,13 @@
+ u16 sub_sys;
+ u16 sub_vendor;
+
+- sub_vendor = dev_a4t->subsystem_vendor;
+- sub_sys = dev_a4t->subsystem_device;
++ pci_get_sub_vendor(dev_a4t,sub_vendor);
++ pci_get_sub_system(dev_a4t,sub_sys);
+ if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) {
+ if (pci_enable_device(dev_a4t))
+ return(0);
+ found = 1;
+- pci_memaddr = pci_resource_start(dev_a4t, 0);
++ pci_memaddr = pci_resource_start_mem(dev_a4t, 0);
+ cs->irq = dev_a4t->irq;
+ break;
+ }
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/bkm_a8.c linux-2.4.29/drivers/isdn/hisax/bkm_a8.c
+--- linux-2.4.29.old/drivers/isdn/hisax/bkm_a8.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/bkm_a8.c 2005-03-22 15:06:45.982102440 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: bkm_a8.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: bkm_a8.c,v 1.22 2001/09/24 13:22:55 kai Exp $
+ *
+ * low level stuff for Scitel Quadro (4*S0, passive)
+ *
+@@ -20,6 +20,7 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+ #include "bkm_ax.h"
+
+ #if CONFIG_PCI
+@@ -28,7 +29,7 @@
+
+ extern const char *CardType[];
+
+-const char sct_quadro_revision[] = "$Revision: 1.1.4.1 $";
++const char sct_quadro_revision[] = "$Revision: 1.22 $";
+
+ static const char *sct_quadro_subtypes[] =
+ {
+@@ -329,13 +330,13 @@
+ while ((dev_a8 = pci_find_device(PCI_VENDOR_ID_PLX,
+ PCI_DEVICE_ID_PLX_9050, dev_a8))) {
+
+- sub_vendor_id = dev_a8->subsystem_vendor;
+- sub_sys_id = dev_a8->subsystem_device;
++ pci_get_sub_vendor(dev_a8,sub_vendor_id);
++ pci_get_sub_system(dev_a8,sub_sys_id);
+ if ((sub_sys_id == PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO) &&
+ (sub_vendor_id == PCI_VENDOR_ID_BERKOM)) {
+ if (pci_enable_device(dev_a8))
+ return(0);
+- pci_ioaddr1 = pci_resource_start(dev_a8, 1);
++ pci_ioaddr1 = pci_resource_start_io(dev_a8, 1);
+ pci_irq = dev_a8->irq;
+ pci_bus = dev_a8->bus->number;
+ pci_device_fn = dev_a8->devfn;
+@@ -365,7 +366,7 @@
+ pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK;
+ pcibios_write_config_dword(pci_bus, pci_device_fn,
+ PCI_BASE_ADDRESS_1, pci_ioaddr1);
+- dev_a8->resource[ 1].start = pci_ioaddr1;
++ get_pcibase(dev_a8, 1) = pci_ioaddr1;
+ }
+ #endif /* End HACK */
+ }
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/bkm_ax.h linux-2.4.29/drivers/isdn/hisax/bkm_ax.h
+--- linux-2.4.29.old/drivers/isdn/hisax/bkm_ax.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/bkm_ax.h 2005-03-22 15:06:46.010098184 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: bkm_ax.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id$
+ *
+ * low level decls for T-Berkom cards A4T and Scitel Quadro (4*S0, passive)
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/callc.c linux-2.4.29/drivers/isdn/hisax/callc.c
+--- linux-2.4.29.old/drivers/isdn/hisax/callc.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/callc.c 2005-03-22 15:06:46.027095600 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: callc.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: callc.c,v 2.59 2002/02/09 21:19:11 keil Exp $
+ *
+ * Author Karsten Keil
+ * Copyright by Karsten Keil <keil@isdn4linux.de>
+@@ -26,7 +26,7 @@
+ #define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module))
+ #endif /* MODULE */
+
+-const char *lli_revision = "$Revision: 1.1.4.1 $";
++const char *lli_revision = "$Revision: 2.59 $";
+
+ extern struct IsdnCard cards[];
+ extern int nrcards;
+@@ -145,9 +145,11 @@
+ EV_PROCEED, /* 20 */
+ EV_ALERT, /* 21 */
+ EV_REDIR, /* 22 */
++ EV_ALERTING, /* 23 */
++ EV_PROCEEDING, /* 24 */
+ };
+
+-#define EVENT_COUNT (EV_REDIR + 1)
++#define EVENT_COUNT (EV_PROCEEDING + 1)
+
+ static char *strEvent[] =
+ {
+@@ -174,6 +176,8 @@
+ "EV_PROCEED",
+ "EV_ALERT",
+ "EV_REDIR",
++ "EV_ALERTING",
++ "EV_PROCEEDING",
+ };
+
+
+@@ -286,6 +290,22 @@
+ }
+
+ static void
++lli_alerting(struct FsmInst *fi, int event, void *arg)
++{
++ struct Channel *chanp = fi->userdata;
++
++ HL_LL(chanp, ISDN_STAT_ALERT);
++}
++
++static void
++lli_proceeding(struct FsmInst *fi, int event, void *arg)
++{
++ struct Channel *chanp = fi->userdata;
++
++ HL_LL(chanp, ISDN_STAT_PROCEED);
++}
++
++static void
+ lli_resume(struct FsmInst *fi, int event, void *arg)
+ {
+ struct Channel *chanp = fi->userdata;
+@@ -784,6 +804,8 @@
+ {ST_OUT_DIAL, EV_DISCONNECT_IND, lli_release_req},
+ {ST_OUT_DIAL, EV_RELEASE, lli_dhup_close},
+ {ST_OUT_DIAL, EV_NOSETUP_RSP, lli_no_setup_rsp},
++ {ST_OUT_DIAL, EV_PROCEEDING, lli_proceeding},
++ {ST_OUT_DIAL, EV_ALERTING, lli_alerting},
+ {ST_OUT_DIAL, EV_SETUP_ERR, lli_error},
+ {ST_IN_WAIT_LL, EV_LEASED_REL, lli_failure_l},
+ {ST_IN_WAIT_LL, EV_ACCEPTD, lli_setup_rsp},
+@@ -925,7 +947,7 @@
+ ic.driver = cs->myid;
+ ic.command = ISDN_STAT_REDIR;
+ ic.arg = chan;
+- ic.parm.num[0] = result;
++ (ulong)(ic.parm.num[0]) = result;
+ cs->iif.statcallb(&ic);
+ } /* stat_redir_result */
+
+@@ -997,8 +1019,13 @@
+ FsmEvent(&chanp->fi, EV_RELEASE, NULL);
+ break;
+ case (CC_PROCEED_SEND | INDICATION):
++ break;
+ case (CC_PROCEEDING | INDICATION):
++ FsmEvent(&chanp->fi, EV_PROCEEDING, NULL);
++ break;
+ case (CC_ALERTING | INDICATION):
++ FsmEvent(&chanp->fi, EV_ALERTING, NULL);
++ break;
+ case (CC_PROGRESS | INDICATION):
+ case (CC_NOTIFY | INDICATION):
+ break;
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/cert.c linux-2.4.29/drivers/isdn/hisax/cert.c
+--- linux-2.4.29.old/drivers/isdn/hisax/cert.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/cert.c 2005-03-22 15:06:46.042093320 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: cert.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: cert.c,v 2.6 2001/09/24 13:22:56 kai Exp $
+ *
+ * Author Karsten Keil
+ * Copyright by Karsten Keil <keil@isdn4linux.de>
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/config.c linux-2.4.29/drivers/isdn/hisax/config.c
+--- linux-2.4.29.old/drivers/isdn/hisax/config.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/config.c 2005-03-22 15:06:46.077088000 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: config.c,v 1.1.4.5 2001/12/09 19:19:26 kai Exp $
++/* $Id: config.c,v 2.84 2002/08/13 09:55:29 keil Exp $
+ *
+ * Author Karsten Keil
+ * Copyright by Karsten Keil <keil@isdn4linux.de>
+@@ -24,6 +24,11 @@
+ #include <linux/kernel_stat.h>
+ #include <linux/tqueue.h>
+ #include <linux/interrupt.h>
++
++#ifdef CONFIG_HISAX_HFC_USB
++#include "hisax_loadable.h"
++#endif
++
+ #define HISAX_STATUS_BUFSIZE 4096
+ #define INCLUDE_INLINE_FUNCS
+
+@@ -75,8 +80,7 @@
+ * 37 HFC 2BDS0 S+/SP p0=irq p1=iobase
+ * 38 Travers Technologies NETspider-U PCI card
+ * 39 HFC 2BDS0-SP PCMCIA p0=irq p1=iobase
+- * 40 hotplug interface
+- * 41 Formula-n enter:now ISDN PCI a/b none
++ * 40 HFC-S USB none
+ *
+ * protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1
+ *
+@@ -95,11 +99,17 @@
+ "Siemens I-Surf", "Acer P10", "HST Saphir", "Telekom A4T",
+ "Scitel Quadro", "Gazel", "HFC 2BDS0 PCI", "Winbond 6692",
+ "HFC 2BDS0 SX", "NETspider-U", "HFC-2BDS0-SP PCMCIA",
+- "Hotplug", "Formula-n enter:now PCI a/b",
++ "HFC-S USB",
+ };
+
+ void HiSax_closecard(int cardnr);
+
++#ifdef CONFIG_HISAX_HFC_USB
++#define DEFAULT_CARD ISDN_CTYPE_HFC_USB
++#define DEFAULT_CFG {0,0,0,0}
++EXPORT_SYMBOL(hisax_register_hfcusb);
++#endif
++
+ #ifdef CONFIG_HISAX_ELSA
+ #define DEFAULT_CARD ISDN_CTYPE_ELSA
+ #define DEFAULT_CFG {0,0,0,0}
+@@ -339,19 +349,27 @@
+ NULL, \
+ }
+
+-struct IsdnCard cards[HISAX_MAX_CARDS] = {
++#define EMPTY_CARD {0, DEFAULT_PROTO, {0, 0, 0, 0}, NULL}
++
++struct IsdnCard cards[] = {
+ FIRST_CARD,
++ EMPTY_CARD,
++ EMPTY_CARD,
++ EMPTY_CARD,
++ EMPTY_CARD,
++ EMPTY_CARD,
++ EMPTY_CARD,
++ EMPTY_CARD,
+ };
+
+-#define HISAX_IDSIZE (HISAX_MAX_CARDS*8)
+-static char HiSaxID[HISAX_IDSIZE] __devinitdata = { 0, };
++static char HiSaxID[64] __devinitdata = { 0, };
+
+ char *HiSax_id __devinitdata = HiSaxID;
+ #ifdef MODULE
+ /* Variables for insmod */
+-static int type[HISAX_MAX_CARDS] __devinitdata = { 0, };
+-static int protocol[HISAX_MAX_CARDS] __devinitdata = { 0, };
+-static int io[HISAX_MAX_CARDS] __devinitdata = { 0, };
++static int type[8] __devinitdata = { 0, };
++static int protocol[8] __devinitdata = { 0, };
++static int io[8] __devinitdata = { 0, };
+ #undef IO0_IO1
+ #ifdef CONFIG_HISAX_16_3
+ #define IO0_IO1
+@@ -361,27 +379,23 @@
+ #define IO0_IO1
+ #endif
+ #ifdef IO0_IO1
+-static int io0[HISAX_MAX_CARDS] __devinitdata = { 0, };
+-static int io1[HISAX_MAX_CARDS] __devinitdata = { 0, };
++static int io0[8] __devinitdata = { 0, };
++static int io1[8] __devinitdata = { 0, };
+ #endif
+-static int irq[HISAX_MAX_CARDS] __devinitdata = { 0, };
+-static int mem[HISAX_MAX_CARDS] __devinitdata = { 0, };
++static int irq[8] __devinitdata = { 0, };
++static int mem[8] __devinitdata = { 0, };
+ static char *id __devinitdata = HiSaxID;
+
+-#define PARM_PARA "1-" __MODULE_STRING(HISAX_MAX_CARDS) "i"
+-
+-MODULE_DESCRIPTION("ISDN4Linux: Driver for passive ISDN cards");
+ MODULE_AUTHOR("Karsten Keil");
+-MODULE_LICENSE("GPL");
+-MODULE_PARM(type, PARM_PARA);
+-MODULE_PARM(protocol, PARM_PARA);
+-MODULE_PARM(io, PARM_PARA);
+-MODULE_PARM(irq, PARM_PARA);
+-MODULE_PARM(mem, PARM_PARA);
++MODULE_PARM(type, "1-8i");
++MODULE_PARM(protocol, "1-8i");
++MODULE_PARM(io, "1-8i");
++MODULE_PARM(irq, "1-8i");
++MODULE_PARM(mem, "1-8i");
+ MODULE_PARM(id, "s");
+ #ifdef IO0_IO1
+-MODULE_PARM(io0, PARM_PARA);
+-MODULE_PARM(io1, PARM_PARA);
++MODULE_PARM(io0, "1-8i");
++MODULE_PARM(io1, "1-8i");
+ #endif
+ #endif /* MODULE */
+
+@@ -432,6 +446,7 @@
+ }
+
+ #ifndef MODULE
++#ifdef COMPAT_HAS_NEW_SETUP
+ #define MAX_ARG (HISAX_MAX_CARDS*5)
+ static int __init HiSax_setup(char *line)
+ {
+@@ -440,12 +455,16 @@
+ char *str;
+
+ str = get_options(line, MAX_ARG, ints);
++#else
++void __init HiSax_setup(char *str, int *ints)
++{
++ int i, j, argc;
++#endif
+ argc = ints[0];
+ printk(KERN_DEBUG "HiSax_setup: argc(%d) str(%s)\n", argc, str);
+ i = 0;
+ j = 1;
+ while (argc && (i < HISAX_MAX_CARDS)) {
+- cards[i].protocol = DEFAULT_PROTO;
+ if (argc) {
+ cards[i].typ = ints[j];
+ j++;
+@@ -473,19 +492,21 @@
+ }
+ i++;
+ }
+- if (str && *str) {
+- if (strlen(str) < HISAX_IDSIZE)
+- strcpy(HiSaxID, str);
+- else
+- printk(KERN_WARNING "HiSax: ID too long!");
+- } else
++ if (str && *str) {
++ strcpy(HiSaxID, str);
++ HiSax_id = HiSaxID;
++ } else {
+ strcpy(HiSaxID, "HiSax");
+-
+- HiSax_id = HiSaxID;
++ HiSax_id = HiSaxID;
++ }
++#ifdef COMPAT_HAS_NEW_SETUP
+ return 1;
+ }
+
+ __setup("hisax=", HiSax_setup);
++#else
++}
++#endif /* COMPAT_HAS_NEW_SETUP */
+ #endif /* MODULES */
+
+ #if CARD_TELES0
+@@ -560,6 +581,10 @@
+ extern int setup_hfcpci(struct IsdnCard *card);
+ #endif
+
++#if CONFIG_HISAX_HFC_USB
++extern int setup_hfc_usb(struct IsdnCard *card);
++#endif
++
+ #if CARD_HFC_SX
+ extern int setup_hfcsx(struct IsdnCard *card);
+ #endif
+@@ -604,10 +629,6 @@
+ extern int setup_netjet_u(struct IsdnCard *card);
+ #endif
+
+-#if CARD_FN_ENTERNOW_PCI
+-extern int setup_enternow_pci(struct IsdnCard *card);
+-#endif
+-
+ /*
+ * Find card with given driverId
+ */
+@@ -899,7 +920,8 @@
+ return 3;
+ }
+
+-static int __devinit checkcard(int cardnr, char *id, int *busy_flag)
++static int __devinit checkcard(int cardnr, char *id, int *busy_flag,
++ void *load_drv)
+ {
+ long flags;
+ int ret = 0;
+@@ -1093,6 +1115,12 @@
+ ret = setup_hfcsx(card);
+ break;
+ #endif
++#if CONFIG_HISAX_HFC_USB
++ case ISDN_CTYPE_HFC_USB:
++ cs->hw.hfcusb.drv = load_drv;
++ ret = setup_hfc_usb(card);
++ break;
++#endif
+ #if CARD_NICCY
+ case ISDN_CTYPE_NICCY:
+ ret = setup_niccy(card);
+@@ -1143,11 +1171,6 @@
+ ret = setup_netjet_u(card);
+ break;
+ #endif
+-#if CARD_FN_ENTERNOW_PCI
+- case ISDN_CTYPE_ENTERNOW:
+- ret = setup_enternow_pci(card);
+- break;
+-#endif
+ case ISDN_CTYPE_DYNAMIC:
+ ret = 2;
+ break;
+@@ -1186,6 +1209,9 @@
+ case ISDN_CTYPE_DYNAMIC:
+ ret = 0;
+ break;
++ case ISDN_CTYPE_HFC_USB:
++ ret = cs->cardmsg(cs, CARD_INIT, NULL);
++ break;
+ default:
+ ret = init_card(cs);
+ break;
+@@ -1257,16 +1283,13 @@
+ else
+ sprintf(ids, "%s%d", id, i);
+ }
+- if (checkcard(i, ids, busy_flag)) {
++ if (checkcard(i, ids, busy_flag, NULL)) {
+ foundcards++;
+ i++;
+ } else {
+- /* make sure we don't oops the module */
+- if (cards[i].typ > 0 && cards[i].typ <= ISDN_CTYPE_COUNT) {
+- printk(KERN_WARNING
+- "HiSax: Card %s not installed !\n",
+- CardType[cards[i].typ]);
+- }
++ printk(KERN_WARNING
++ "HiSax: Card %s not installed !\n",
++ CardType[cards[i].typ]);
+ HiSax_shiftcards(i);
+ nrcards--;
+ }
+@@ -1342,6 +1365,49 @@
+ #endif
+ }
+
++#ifdef CONFIG_HISAX_HFC_USB
++int
++hisax_register_hfcusb(struct hisax_drvreg *l1drv)
++{
++ int i;
++ char ids[30];
++
++ if (l1drv->version != HISAX_LOAD_VERSION)
++ return 1;
++
++ switch (l1drv->cmd) {
++ case HISAX_LOAD_CHKVER:
++ break; /* success */
++
++ case HISAX_LOAD_REGISTER:
++ for (i = 0; i < HISAX_MAX_CARDS; i++) {
++ if (!cards[i].typ)
++ break;
++ }
++ if (i >= HISAX_MAX_CARDS)
++ return 1; /* no space */
++ cards[i].typ = ISDN_CTYPE_HFC_USB; /* setup type */
++ cards[i].protocol = DEFAULT_PROTO;
++ sprintf(ids, "%s%d", l1drv->drvname, i);
++ if (checkcard(i, ids, NULL, (void *) l1drv)) {
++ nrcards++;
++ return 0;
++ }
++ if (cards[i].cs)
++ kfree((void *) cards[i].cs);
++ cards[i].cs = NULL;
++ cards[i].typ = 0; /* no card present */
++ return 1;
++ break;
++
++ default:
++ return 1; /* unknown command */
++ }
++
++ return 0;
++} /* hisax_register_hfcusb */
++#endif
++
+ static int __init HiSax_init(void)
+ {
+ int i, retval;
+@@ -1408,8 +1474,6 @@
+ if (protocol[i]) {
+ cards[j].protocol = protocol[i];
+ nzproto++;
+- } else {
+- cards[j].protocol = DEFAULT_PROTO;
+ }
+ switch (type[i]) {
+ case ISDN_CTYPE_16_0:
+@@ -1487,22 +1551,15 @@
+ } else {
+ /* QUADRO is a 4 BRI card */
+ cards[j++].para[0] = 1;
+- /* we need to check if further cards can be added */
+- if (j < HISAX_MAX_CARDS) {
+- cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+- cards[j].protocol = protocol[i];
+- cards[j++].para[0] = 2;
+- }
+- if (j < HISAX_MAX_CARDS) {
+- cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+- cards[j].protocol = protocol[i];
+- cards[j++].para[0] = 3;
+- }
+- if (j < HISAX_MAX_CARDS) {
+- cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+- cards[j].protocol = protocol[i];
+- cards[j].para[0] = 4;
+- }
++ cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
++ cards[j].protocol = protocol[i];
++ cards[j++].para[0] = 2;
++ cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
++ cards[j].protocol = protocol[i];
++ cards[j++].para[0] = 3;
++ cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
++ cards[j].protocol = protocol[i];
++ cards[j].para[0] = 4;
+ }
+ break;
+ }
+@@ -1526,10 +1583,15 @@
+ nrcards, (nrcards > 1) ? "s" : "");
+
+ /* Install only, if at least one card found */
+- if (!HiSax_inithardware(NULL))
+- return -ENODEV;
++ if (!HiSax_inithardware(NULL)) {
++ retval = -EIO;
++ goto out_isdnl1;
++ }
++
+ return 0;
+
++ out_isdnl1:
++ Isdnl1Free();
+ out_tei:
+ TeiFree();
+ out_isdnl2:
+@@ -1576,8 +1638,6 @@
+ cards[i].typ = type[i];
+ if (protocol[i]) {
+ cards[i].protocol = protocol[i];
+- } else {
+- cards[i].protocol = DEFAULT_PROTO;
+ }
+ }
+ cards[0].para[0] = pcm_irq;
+@@ -1595,8 +1655,7 @@
+ printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
+ nrcards, (nrcards > 1) ? "s" : "");
+
+- if (!HiSax_inithardware(busy_flag))
+- return -ENODEV;
++ HiSax_inithardware(busy_flag);
+ printk(KERN_NOTICE "HiSax: module installed\n");
+ #endif
+ return 0;
+@@ -1619,8 +1678,6 @@
+ cards[i].typ = type[i];
+ if (protocol[i]) {
+ cards[i].protocol = protocol[i];
+- } else {
+- cards[i].protocol = DEFAULT_PROTO;
+ }
+ }
+ cards[0].para[0] = pcm_irq;
+@@ -1638,8 +1695,7 @@
+ printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
+ nrcards, (nrcards > 1) ? "s" : "");
+
+- if (!HiSax_inithardware(busy_flag))
+- return -ENODEV;
++ HiSax_inithardware(busy_flag);
+ printk(KERN_NOTICE "HiSax: module installed\n");
+ #endif
+ return 0;
+@@ -1662,8 +1718,6 @@
+ cards[i].typ = type[i];
+ if (protocol[i]) {
+ cards[i].protocol = protocol[i];
+- } else {
+- cards[i].protocol = DEFAULT_PROTO;
+ }
+ }
+ cards[0].para[0] = pcm_irq;
+@@ -1681,8 +1735,7 @@
+ printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
+ nrcards, (nrcards > 1) ? "s" : "");
+
+- if (!HiSax_inithardware(busy_flag))
+- return -ENODEV;
++ HiSax_inithardware(busy_flag);
+ printk(KERN_NOTICE "HiSax: module installed\n");
+ #endif
+ return 0;
+@@ -1705,8 +1758,6 @@
+ cards[i].typ = type[i];
+ if (protocol[i]) {
+ cards[i].protocol = protocol[i];
+- } else {
+- cards[i].protocol = DEFAULT_PROTO;
+ }
+ }
+ cards[0].para[0] = pcm_irq;
+@@ -1724,8 +1775,7 @@
+ printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
+ nrcards, (nrcards > 1) ? "s" : "");
+
+- if (!HiSax_inithardware(busy_flag))
+- return -ENODEV;
++ HiSax_inithardware(busy_flag);
+ printk(KERN_NOTICE "HiSax: module installed\n");
+ #endif
+ return 0;
+@@ -1743,7 +1793,7 @@
+ sprintf(ids, "HiSax%d", nrcards);
+ else
+ sprintf(ids, "HiSax");
+- if (!checkcard(nrcards, ids, busy_flag)) {
++ if (!checkcard(nrcards, ids, busy_flag, NULL)) {
+ return -1;
+ }
+ ret = nrcards;
+@@ -1785,7 +1835,7 @@
+ cards[i].protocol = protocol;
+ sprintf(id, "%s%d", name, i);
+ nrcards++;
+- retval = checkcard(i, id, 0);
++ retval = checkcard(i, id, 0, NULL);
+ if (retval == 0) { // yuck
+ cards[i].typ = 0;
+ nrcards--;
+@@ -2117,9 +2167,6 @@
+ {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20_U, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA201, PCI_ANY_ID, PCI_ANY_ID},
+-//#########################################################################################
+- {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA202, PCI_ANY_ID, PCI_ANY_ID},
+-//#########################################################################################
+ #endif
+ #ifdef CONFIG_HISAX_ELSA
+ {PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK, PCI_ANY_ID, PCI_ANY_ID},
+@@ -2178,11 +2225,3 @@
+
+ module_init(HiSax_init);
+ module_exit(HiSax_exit);
+-
+-EXPORT_SYMBOL(FsmNew);
+-EXPORT_SYMBOL(FsmFree);
+-EXPORT_SYMBOL(FsmEvent);
+-EXPORT_SYMBOL(FsmChangeState);
+-EXPORT_SYMBOL(FsmInitTimer);
+-EXPORT_SYMBOL(FsmDelTimer);
+-EXPORT_SYMBOL(FsmRestartTimer);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/diva.c linux-2.4.29/drivers/isdn/hisax/diva.c
+--- linux-2.4.29.old/drivers/isdn/hisax/diva.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/diva.c 2005-03-22 15:06:46.106083592 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: diva.c,v 1.1.4.2 2002/08/30 11:21:00 keil Exp $
++/* $Id: diva.c,v 1.33 2001/09/24 13:22:56 kai Exp $
+ *
+ * low level stuff for Eicon.Diehl Diva Family ISDN cards
+ *
+@@ -22,14 +22,13 @@
+ #include "isac.h"
+ #include "hscx.h"
+ #include "ipac.h"
+-#include "ipacx.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
+-#include <linux/isapnp.h>
++#include <linux/isdn_compat.h>
+
+ extern const char *CardType[];
+
+-const char *Diva_revision = "$Revision: 1.1.4.2 $";
++const char *Diva_revision = "$Revision: 1.33 $";
+
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+@@ -51,7 +50,6 @@
+ #define DIVA_PCI 2
+ #define DIVA_IPAC_ISA 3
+ #define DIVA_IPAC_PCI 4
+-#define DIVA_IPACX_PCI 5
+
+ /* CTRL (Read) */
+ #define DIVA_IRQ_STAT 0x01
+@@ -71,12 +69,10 @@
+ #define PITA_MISC_REG 0x1c
+ #ifdef __BIG_ENDIAN
+ #define PITA_PARA_SOFTRESET 0x00000001
+-#define PITA_SER_SOFTRESET 0x00000002
+ #define PITA_PARA_MPX_MODE 0x00000004
+ #define PITA_INT0_ENABLE 0x00000200
+ #else
+ #define PITA_PARA_SOFTRESET 0x01000000
+-#define PITA_SER_SOFTRESET 0x02000000
+ #define PITA_PARA_MPX_MODE 0x04000000
+ #define PITA_INT0_ENABLE 0x00020000
+ #endif
+@@ -244,47 +240,6 @@
+ memwritereg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0), value);
+ }
+
+-/* IO-Functions for IPACX type cards */
+-static u_char
+-MemReadISAC_IPACX(struct IsdnCardState *cs, u_char offset)
+-{
+- return (memreadreg(cs->hw.diva.cfg_reg, offset));
+-}
+-
+-static void
+-MemWriteISAC_IPACX(struct IsdnCardState *cs, u_char offset, u_char value)
+-{
+- memwritereg(cs->hw.diva.cfg_reg, offset, value);
+-}
+-
+-static void
+-MemReadISACfifo_IPACX(struct IsdnCardState *cs, u_char * data, int size)
+-{
+- while(size--)
+- *data++ = memreadreg(cs->hw.diva.cfg_reg, 0);
+-}
+-
+-static void
+-MemWriteISACfifo_IPACX(struct IsdnCardState *cs, u_char * data, int size)
+-{
+- while(size--)
+- memwritereg(cs->hw.diva.cfg_reg, 0, *data++);
+-}
+-
+-static u_char
+-MemReadHSCX_IPACX(struct IsdnCardState *cs, int hscx, u_char offset)
+-{
+- return(memreadreg(cs->hw.diva.cfg_reg, offset +
+- (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1)));
+-}
+-
+-static void
+-MemWriteHSCX_IPACX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+-{
+- memwritereg(cs->hw.diva.cfg_reg, offset +
+- (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1), value);
+-}
+-
+ /*
+ * fast interrupt HSCX stuff goes here
+ */
+@@ -595,7 +550,7 @@
+ u_char exval;
+ struct BCState *bcs;
+
+- if (val & 0x01) { // EXB
++ if (val & 0x01) {
+ bcs = cs->bcs + 1;
+ exval = MemReadHSCX(cs, 1, HSCX_EXIR);
+ if (exval & 0x40) {
+@@ -622,7 +577,7 @@
+ debugl1(cs, "HSCX B interrupt %x", val);
+ Memhscx_interrupt(cs, val, 1);
+ }
+- if (val & 0x02) { // EXA
++ if (val & 0x02) {
+ bcs = cs->bcs;
+ exval = MemReadHSCX(cs, 0, HSCX_EXIR);
+ if (exval & 0x40) {
+@@ -644,7 +599,7 @@
+ } else if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "HSCX A EXIR %x", exval);
+ }
+- if (val & 0x04) { // ICA
++ if (val & 0x04) {
+ exval = MemReadHSCX(cs, 0, HSCX_ISTA);
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "HSCX A interrupt %x", exval);
+@@ -705,31 +660,12 @@
+ memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xC0);
+ }
+
+-static void
+-diva_irq_ipacx_pci(int intno, void *dev_id, struct pt_regs *regs)
+-{
+- struct IsdnCardState *cs = dev_id;
+- u_char val;
+- u_char *cfg;
+-
+- if (!cs) {
+- printk(KERN_WARNING "Diva: Spurious interrupt!\n");
+- return;
+- }
+- cfg = (u_char *) cs->hw.diva.pci_cfg;
+- val = *cfg;
+- if (!(val &PITA_INT0_STATUS)) return; // other shared IRQ
+- interrupt_ipacx(cs); // handler for chip
+- *cfg = PITA_INT0_STATUS; // Reset PLX interrupt
+-}
+-
+ void
+ release_io_diva(struct IsdnCardState *cs)
+ {
+ int bytecnt;
+
+- if ((cs->subtyp == DIVA_IPAC_PCI) ||
+- (cs->subtyp == DIVA_IPACX_PCI) ) {
++ if (cs->subtyp == DIVA_IPAC_PCI) {
+ u_int *cfg = (unsigned int *)cs->hw.diva.pci_cfg;
+
+ *cfg = 0; /* disable INT0/1 */
+@@ -776,16 +712,6 @@
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout((10*HZ)/1000);
+ memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0);
+- } else if (cs->subtyp == DIVA_IPACX_PCI) {
+- unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg +
+- PITA_MISC_REG);
+- *ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE;
+- set_current_state(TASK_UNINTERRUPTIBLE);
+- schedule_timeout((10*HZ)/1000);
+- *ireg = PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET;
+- set_current_state(TASK_UNINTERRUPTIBLE);
+- schedule_timeout((10*HZ)/1000);
+- MemWriteISAC_IPACX(cs, IPACX_MASK, 0xff); // Interrupts off
+ } else { /* DIVA 2.0 */
+ cs->hw.diva.ctrl_reg = 0; /* Reset On */
+ byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
+@@ -814,9 +740,7 @@
+ {
+ int blink = 0;
+
+- if ((cs->subtyp == DIVA_IPAC_ISA) ||
+- (cs->subtyp == DIVA_IPAC_PCI) ||
+- (cs->subtyp == DIVA_IPACX_PCI) )
++ if ((cs->subtyp == DIVA_IPAC_ISA) || (cs->subtyp == DIVA_IPAC_PCI))
+ return;
+ del_timer(&cs->hw.diva.tl);
+ if (cs->hw.diva.status & DIVA_ASSIGN)
+@@ -859,12 +783,6 @@
+ release_io_diva(cs);
+ return(0);
+ case CARD_INIT:
+- if (cs->subtyp == DIVA_IPACX_PCI) {
+- ireg = (unsigned int *)cs->hw.diva.pci_cfg;
+- *ireg = PITA_INT0_ENABLE;
+- init_ipacx(cs, 3); // init chip and enable interrupts
+- return (0);
+- }
+ if (cs->subtyp == DIVA_IPAC_PCI) {
+ ireg = (unsigned int *)cs->hw.diva.pci_cfg;
+ *ireg = PITA_INT0_ENABLE;
+@@ -901,9 +819,7 @@
+ }
+ break;
+ }
+- if ((cs->subtyp != DIVA_IPAC_ISA) &&
+- (cs->subtyp != DIVA_IPAC_PCI) &&
+- (cs->subtyp != DIVA_IPACX_PCI) )
++ if ((cs->subtyp != DIVA_IPAC_ISA) && (cs->subtyp != DIVA_IPAC_PCI))
+ diva_led_handler(cs);
+ return(0);
+ }
+@@ -911,40 +827,11 @@
+ static struct pci_dev *dev_diva __initdata = NULL;
+ static struct pci_dev *dev_diva_u __initdata = NULL;
+ static struct pci_dev *dev_diva201 __initdata = NULL;
+-static struct pci_dev *dev_diva202 __initdata = NULL;
+-
+-#ifdef __ISAPNP__
+-static struct isapnp_device_id diva_ids[] __initdata = {
+- { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
+- ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
+- (unsigned long) "Diva picola" },
+- { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
+- ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x51),
+- (unsigned long) "Diva picola" },
+- { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71),
+- ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71),
+- (unsigned long) "Diva 2.0" },
+- { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71),
+- ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x71),
+- (unsigned long) "Diva 2.0" },
+- { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1),
+- ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1),
+- (unsigned long) "Diva 2.01" },
+- { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1),
+- ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0xA1),
+- (unsigned long) "Diva 2.01" },
+- { 0, }
+-};
+-
+-static struct isapnp_device_id *pdev = &diva_ids[0];
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+-
+
+ int __init
+ setup_diva(struct IsdnCard *card)
+ {
+- int bytecnt = 8;
++ int bytecnt;
+ u_char val;
+ struct IsdnCardState *cs = card->cs;
+ char tmp[64];
+@@ -977,75 +864,8 @@
+ cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
+ }
+ cs->irq = card->para[0];
++ bytecnt = 8;
+ } else {
+-#ifdef __ISAPNP__
+- if (isapnp_present()) {
+- struct pci_bus *pb;
+- struct pci_dev *pd;
+-
+- while(pdev->card_vendor) {
+- if ((pb = isapnp_find_card(pdev->card_vendor,
+- pdev->card_device, pnp_c))) {
+- pnp_c = pb;
+- pd = NULL;
+- if ((pd = isapnp_find_dev(pnp_c,
+- pdev->vendor, pdev->function, pd))) {
+- printk(KERN_INFO "HiSax: %s detected\n",
+- (char *)pdev->driver_data);
+- pd->prepare(pd);
+- pd->deactivate(pd);
+- pd->activate(pd);
+- card->para[1] =
+- pd->resource[0].start;
+- card->para[0] =
+- pd->irq_resource[0].start;
+- if (!card->para[0] || !card->para[1]) {
+- printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",
+- card->para[0], card->para[1]);
+- pd->deactivate(pd);
+- return(0);
+- }
+- cs->hw.diva.cfg_reg = card->para[1];
+- cs->irq = card->para[0];
+- if (pdev->function == ISAPNP_FUNCTION(0xA1)) {
+- cs->subtyp = DIVA_IPAC_ISA;
+- cs->hw.diva.ctrl = 0;
+- cs->hw.diva.isac =
+- card->para[1] + DIVA_IPAC_DATA;
+- cs->hw.diva.hscx =
+- card->para[1] + DIVA_IPAC_DATA;
+- cs->hw.diva.isac_adr =
+- card->para[1] + DIVA_IPAC_ADR;
+- cs->hw.diva.hscx_adr =
+- card->para[1] + DIVA_IPAC_ADR;
+- test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+- } else {
+- cs->subtyp = DIVA_ISA;
+- cs->hw.diva.ctrl =
+- card->para[1] + DIVA_ISA_CTRL;
+- cs->hw.diva.isac =
+- card->para[1] + DIVA_ISA_ISAC_DATA;
+- cs->hw.diva.hscx =
+- card->para[1] + DIVA_HSCX_DATA;
+- cs->hw.diva.isac_adr =
+- card->para[1] + DIVA_ISA_ISAC_ADR;
+- cs->hw.diva.hscx_adr =
+- card->para[1] + DIVA_HSCX_ADR;
+- }
+- goto ready;
+- } else {
+- printk(KERN_ERR "Diva PnP: PnP error card found, no device\n");
+- return(0);
+- }
+- }
+- pdev++;
+- pnp_c=NULL;
+- }
+- if (!pdev->card_vendor) {
+- printk(KERN_INFO "Diva PnP: no ISAPnP card found\n");
+- }
+- }
+-#endif
+ #if CONFIG_PCI
+ if (!pci_present()) {
+ printk(KERN_ERR "Diva: no PCI bus present\n");
+@@ -1059,14 +879,14 @@
+ return(0);
+ cs->subtyp = DIVA_PCI;
+ cs->irq = dev_diva->irq;
+- cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2);
++ cs->hw.diva.cfg_reg = pci_resource_start_io(dev_diva, 2);
+ } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON,
+ PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) {
+ if (pci_enable_device(dev_diva_u))
+ return(0);
+ cs->subtyp = DIVA_PCI;
+ cs->irq = dev_diva_u->irq;
+- cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2);
++ cs->hw.diva.cfg_reg = pci_resource_start_io(dev_diva_u, 2);
+ } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON,
+ PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) {
+ if (pci_enable_device(dev_diva201))
+@@ -1074,19 +894,9 @@
+ cs->subtyp = DIVA_IPAC_PCI;
+ cs->irq = dev_diva201->irq;
+ cs->hw.diva.pci_cfg =
+- (ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096);
++ (ulong) ioremap(pci_resource_start_mem(dev_diva201, 0), 4096);
+ cs->hw.diva.cfg_reg =
+- (ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096);
+- } else if ((dev_diva202 = pci_find_device(PCI_VENDOR_ID_EICON,
+- PCI_DEVICE_ID_EICON_DIVA202, dev_diva202))) {
+- if (pci_enable_device(dev_diva202))
+- return(0);
+- cs->subtyp = DIVA_IPACX_PCI;
+- cs->irq = dev_diva202->irq;
+- cs->hw.diva.pci_cfg =
+- (ulong) ioremap(pci_resource_start(dev_diva202, 0), 4096);
+- cs->hw.diva.cfg_reg =
+- (ulong) ioremap(pci_resource_start(dev_diva202, 1), 4096);
++ (ulong) ioremap(pci_resource_start_mem(dev_diva201, 1), 4096);
+ } else {
+ printk(KERN_WARNING "Diva: No PCI card found\n");
+ return(0);
+@@ -1107,8 +917,7 @@
+ printk(KERN_WARNING "Diva: unable to config DIVA PCI\n");
+ return (0);
+ #endif /* CONFIG_PCI */
+- if ((cs->subtyp == DIVA_IPAC_PCI) ||
+- (cs->subtyp == DIVA_IPACX_PCI) ) {
++ if (cs->subtyp == DIVA_IPAC_PCI) {
+ cs->hw.diva.ctrl = 0;
+ cs->hw.diva.isac = 0;
+ cs->hw.diva.hscx = 0;
+@@ -1125,23 +934,18 @@
+ bytecnt = 32;
+ }
+ }
+-ready:
++
+ printk(KERN_INFO
+ "Diva: %s card configured at %#lx IRQ %d\n",
+ (cs->subtyp == DIVA_PCI) ? "PCI" :
+ (cs->subtyp == DIVA_ISA) ? "ISA" :
+- (cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" :
+- (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",
++ (cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" : "IPAC PCI",
+ cs->hw.diva.cfg_reg, cs->irq);
+- if ((cs->subtyp == DIVA_IPAC_PCI) ||
+- (cs->subtyp == DIVA_IPACX_PCI) ||
+- (cs->subtyp == DIVA_PCI) )
+- printk(KERN_INFO "Diva: %s space at %#lx\n",
+- (cs->subtyp == DIVA_PCI) ? "PCI" :
+- (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",
++ if ((cs->subtyp == DIVA_IPAC_PCI) || (cs->subtyp == DIVA_PCI))
++ printk(KERN_INFO "Diva: %s PCI space at %#lx\n",
++ (cs->subtyp == DIVA_PCI) ? "PCI" : "IPAC PCI",
+ cs->hw.diva.pci_cfg);
+- if ((cs->subtyp != DIVA_IPAC_PCI) &&
+- (cs->subtyp != DIVA_IPACX_PCI) ) {
++ if (cs->subtyp != DIVA_IPAC_PCI) {
+ if (check_region(cs->hw.diva.cfg_reg, bytecnt)) {
+ printk(KERN_WARNING
+ "HiSax: %s config port %lx-%lx already in use\n",
+@@ -1177,17 +981,6 @@
+ cs->irq_func = &diva_irq_ipac_pci;
+ val = memreadreg(cs->hw.diva.cfg_reg, IPAC_ID);
+ printk(KERN_INFO "Diva: IPAC version %x\n", val);
+- } else if (cs->subtyp == DIVA_IPACX_PCI) {
+- cs->readisac = &MemReadISAC_IPACX;
+- cs->writeisac = &MemWriteISAC_IPACX;
+- cs->readisacfifo = &MemReadISACfifo_IPACX;
+- cs->writeisacfifo = &MemWriteISACfifo_IPACX;
+- cs->BC_Read_Reg = &MemReadHSCX_IPACX;
+- cs->BC_Write_Reg = &MemWriteHSCX_IPACX;
+- cs->BC_Send_Data = 0; // function located in ipacx module
+- cs->irq_func = &diva_irq_ipacx_pci;
+- printk(KERN_INFO "Diva: IPACX Design Id: %x\n",
+- MemReadISAC_IPACX(cs, IPACX_ID) &0x3F);
+ } else { /* DIVA 2.0 */
+ cs->hw.diva.tl.function = (void *) diva_led_handler;
+ cs->hw.diva.tl.data = (long) cs;
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/elsa.c linux-2.4.29/drivers/isdn/hisax/elsa.c
+--- linux-2.4.29.old/drivers/isdn/hisax/elsa.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/elsa.c 2005-03-22 15:06:46.123081008 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: elsa.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: elsa.c,v 2.32 2001/09/24 13:22:56 kai Exp $
+ *
+ * low level stuff for Elsa isdn cards
+ *
+@@ -28,13 +28,13 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
+-#include <linux/isapnp.h>
++#include <linux/isdn_compat.h>
+ #include <linux/serial.h>
+ #include <linux/serial_reg.h>
+
+ extern const char *CardType[];
+
+-const char *Elsa_revision = "$Revision: 1.1.4.1 $";
++const char *Elsa_revision = "$Revision: 2.32 $";
+ const char *Elsa_Types[] =
+ {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro",
+ "PCMCIA", "QS 1000", "QS 3000", "Microlink PCI", "QS 3000 PCI",
+@@ -864,21 +864,6 @@
+ static struct pci_dev *dev_qs1000 __devinitdata = NULL;
+ static struct pci_dev *dev_qs3000 __devinitdata = NULL;
+
+-#ifdef __ISAPNP__
+-static struct isapnp_device_id elsa_ids[] __initdata = {
+- { ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0133),
+- ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0133),
+- (unsigned long) "Elsa QS1000" },
+- { ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0134),
+- ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0134),
+- (unsigned long) "Elsa QS3000" },
+- { 0, }
+-};
+-
+-static struct isapnp_device_id *pdev = &elsa_ids[0];
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+-
+ int __devinit
+ setup_elsa(struct IsdnCard *card)
+ {
+@@ -893,7 +878,6 @@
+ cs->hw.elsa.ctrl_reg = 0;
+ cs->hw.elsa.status = 0;
+ cs->hw.elsa.MFlag = 0;
+- cs->subtyp = 0;
+ if (cs->typ == ISDN_CTYPE_ELSA) {
+ cs->hw.elsa.base = card->para[0];
+ printk(KERN_INFO "Elsa: Microlink IO probing\n");
+@@ -955,60 +939,9 @@
+ return (0);
+ }
+ } else if (cs->typ == ISDN_CTYPE_ELSA_PNP) {
+-#ifdef __ISAPNP__
+- if (!card->para[1] && isapnp_present()) {
+- struct pci_bus *pb;
+- struct pci_dev *pd;
+-
+- while(pdev->card_vendor) {
+- if ((pb = isapnp_find_card(pdev->card_vendor,
+- pdev->card_device, pnp_c))) {
+- pnp_c = pb;
+- pd = NULL;
+- if ((pd = isapnp_find_dev(pnp_c,
+- pdev->vendor, pdev->function, pd))) {
+- printk(KERN_INFO "HiSax: %s detected\n",
+- (char *)pdev->driver_data);
+- pd->prepare(pd);
+- pd->deactivate(pd);
+- pd->activate(pd);
+- card->para[1] =
+- pd->resource[0].start;
+- card->para[0] =
+- pd->irq_resource[0].start;
+- if (!card->para[0] || !card->para[1]) {
+- printk(KERN_ERR "Elsa PnP:some resources are missing %ld/%lx\n",
+- card->para[0], card->para[1]);
+- pd->deactivate(pd);
+- return(0);
+- }
+- if (pdev->function == ISAPNP_FUNCTION(0x133))
+- cs->subtyp = ELSA_QS1000;
+- else
+- cs->subtyp = ELSA_QS3000;
+- break;
+- } else {
+- printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n");
+- return(0);
+- }
+- }
+- pdev++;
+- pnp_c=NULL;
+- }
+- if (!pdev->card_vendor) {
+- printk(KERN_INFO "Elsa PnP: no ISAPnP card found\n");
+- return(0);
+- }
+- }
+-#endif
+- if (card->para[1] && card->para[0]) {
+- cs->hw.elsa.base = card->para[1];
+- cs->irq = card->para[0];
+- if (!cs->subtyp)
+- cs->subtyp = ELSA_QS1000;
+- } else {
+- printk(KERN_ERR "Elsa PnP: no parameter\n");
+- }
++ cs->hw.elsa.base = card->para[1];
++ cs->irq = card->para[0];
++ cs->subtyp = ELSA_QS1000;
+ cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
+ cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
+ cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
+@@ -1058,16 +991,16 @@
+ return(0);
+ cs->subtyp = ELSA_QS1000PCI;
+ cs->irq = dev_qs1000->irq;
+- cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1);
+- cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3);
++ cs->hw.elsa.cfg = pci_resource_start_io(dev_qs1000, 1);
++ cs->hw.elsa.base = pci_resource_start_io(dev_qs1000, 3);
+ } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA,
+ PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) {
+ if (pci_enable_device(dev_qs3000))
+ return(0);
+ cs->subtyp = ELSA_QS3000PCI;
+ cs->irq = dev_qs3000->irq;
+- cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1);
+- cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3);
++ cs->hw.elsa.cfg = pci_resource_start_io(dev_qs3000, 1);
++ cs->hw.elsa.base = pci_resource_start_io(dev_qs3000, 3);
+ } else {
+ printk(KERN_WARNING "Elsa: No PCI card found\n");
+ return(0);
+@@ -1123,7 +1056,6 @@
+ break;
+ case ELSA_PCFPRO:
+ case ELSA_PCF:
+- case ELSA_QS3000:
+ case ELSA_QS3000PCI:
+ bytecnt = 16;
+ break;
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/elsa_cs.c linux-2.4.29/drivers/isdn/hisax/elsa_cs.c
+--- linux-2.4.29.old/drivers/isdn/hisax/elsa_cs.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/elsa_cs.c 2005-03-22 15:06:46.138078728 +0100
+@@ -72,7 +72,7 @@
+ MODULE_PARM(pc_debug, "i");
+ #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
+ static char *version =
+-"elsa_cs.c $Revision: 1.1.4.1 $ $Date: 2001/11/20 14:19:35 $ (K.Lichtenwalder)";
++"elsa_cs.c $Revision: 1.2 $ $Date: 2001/09/24 13:22:56 $ (K.Lichtenwalder)";
+ #else
+ #define DEBUG(n, args...)
+ #endif
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/elsa_ser.c linux-2.4.29/drivers/isdn/hisax/elsa_ser.c
+--- linux-2.4.29.old/drivers/isdn/hisax/elsa_ser.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/elsa_ser.c 2005-03-22 15:06:46.158075688 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: elsa_ser.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: elsa_ser.c,v 2.14 2001/09/24 13:22:56 kai Exp $
+ *
+ * stuff for the serial modem on ELSA cards
+ *
+@@ -396,6 +396,74 @@
+ }
+ }
+
++#if 0
++static inline void check_modem_status(struct IsdnCardState *cs)
++{
++ int status;
++ struct async_struct *info = cs->hw.elsa.info;
++ struct async_icount *icount;
++
++ status = serial_inp(info, UART_MSR);
++
++ if (status & UART_MSR_ANY_DELTA) {
++ icount = &info->state->icount;
++ /* update input line counters */
++ if (status & UART_MSR_TERI)
++ icount->rng++;
++ if (status & UART_MSR_DDSR)
++ icount->dsr++;
++ if (status & UART_MSR_DDCD) {
++ icount->dcd++;
++ }
++ if (status & UART_MSR_DCTS)
++ icount->cts++;
++// wake_up(&info->delta_msr_wait);
++ }
++
++ if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
++#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
++ printk("ttys%d CD now %s...", info->line,
++ (status & UART_MSR_DCD) ? "on" : "off");
++#endif
++ if (status & UART_MSR_DCD)
++// wake_up(&info->open_wait);
++;
++ else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
++ (info->flags & ASYNC_CALLOUT_NOHUP))) {
++#ifdef SERIAL_DEBUG_OPEN
++ printk("doing serial hangup...");
++#endif
++ if (info->tty)
++ tty_hangup(info->tty);
++ }
++ }
++#if 0
++ if (info->flags & ASYNC_CTS_FLOW) {
++ if (info->tty->hw_stopped) {
++ if (status & UART_MSR_CTS) {
++#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
++ printk("CTS tx start...");
++#endif
++ info->tty->hw_stopped = 0;
++ info->IER |= UART_IER_THRI;
++ serial_outp(info, UART_IER, info->IER);
++// rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
++ return;
++ }
++ } else {
++ if (!(status & UART_MSR_CTS)) {
++#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
++ printk("CTS tx stop...");
++#endif
++ info->tty->hw_stopped = 1;
++ info->IER &= ~UART_IER_THRI;
++ serial_outp(info, UART_IER, info->IER);
++ }
++ }
++ }
++#endif 0
++}
++#endif
+
+ static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs)
+ {
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/fsm.c linux-2.4.29/drivers/isdn/hisax/fsm.c
+--- linux-2.4.29.old/drivers/isdn/hisax/fsm.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/fsm.c 2005-03-22 15:06:46.174073256 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: fsm.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id$
+ *
+ * Finite state machine
+ *
+@@ -21,6 +21,14 @@
+
+ #define FSM_TIMER_DEBUG 0
+
++EXPORT_SYMBOL(FsmNew);
++EXPORT_SYMBOL(FsmFree);
++EXPORT_SYMBOL(FsmEvent);
++EXPORT_SYMBOL(FsmChangeState);
++EXPORT_SYMBOL(FsmInitTimer);
++EXPORT_SYMBOL(FsmDelTimer);
++EXPORT_SYMBOL(FsmRestartTimer);
++
+ int __init
+ FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount)
+ {
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/fsm.h linux-2.4.29/drivers/isdn/hisax/fsm.h
+--- linux-2.4.29.old/drivers/isdn/hisax/fsm.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/fsm.h 2005-03-22 15:06:46.189070976 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: fsm.h,v 1.1.2.1 2001/11/20 14:19:35 kai Exp $
++/* $Id$
+ *
+ * Finite state machine
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/gazel.c linux-2.4.29/drivers/isdn/hisax/gazel.c
+--- linux-2.4.29.old/drivers/isdn/hisax/gazel.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/gazel.c 2005-03-22 15:06:46.205068544 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: gazel.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: gazel.c,v 2.19 2001/09/24 13:22:56 kai Exp $
+ *
+ * low level stuff for Gazel isdn cards
+ *
+@@ -20,9 +20,10 @@
+ #include "isdnl1.h"
+ #include "ipac.h"
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+
+ extern const char *CardType[];
+-const char *gazel_revision = "$Revision: 1.1.4.1 $";
++const char *gazel_revision = "$Revision: 2.19 $";
+
+ #define R647 1
+ #define R685 2
+@@ -563,8 +564,8 @@
+ if (pci_enable_device(dev_tel))
+ return 1;
+ pci_irq = dev_tel->irq;
+- pci_ioaddr0 = pci_resource_start(dev_tel, 1);
+- pci_ioaddr1 = pci_resource_start(dev_tel, 2);
++ pci_ioaddr0 = pci_resource_start_io(dev_tel, 1);
++ pci_ioaddr1 = pci_resource_start_io(dev_tel, 2);
+ found = 1;
+ }
+ if (found)
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_2bds0.c linux-2.4.29/drivers/isdn/hisax/hfc_2bds0.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_2bds0.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_2bds0.c 2005-03-22 15:06:46.221066112 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfc_2bds0.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: hfc_2bds0.c,v 1.18 2001/09/24 13:22:56 kai Exp $
+ *
+ * specific routines for CCD's HFC 2BDS0
+ *
+@@ -616,6 +616,17 @@
+ */
+ if (!cs)
+ return;
++#if 0
++ if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
++ if (cs->debug)
++ debugl1(cs, "D-Channel Busy cleared");
++ stptr = cs->stlist;
++ while (stptr != NULL) {
++ stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
++ stptr = stptr->next;
++ }
++ }
++#endif
+ if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
+ switch (cs->dc.hfcd.ph_state) {
+ case (0):
+@@ -1090,6 +1101,32 @@
+ cs->hw.hfcD.mst_m |= HFCD_MASTER;
+ cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
+ break;
++#if 0
++ case (HW_TESTLOOP | REQUEST):
++ u_char val = 0;
++ if (1 & (int) arg)
++ val |= 0x0c;
++ if (2 & (int) arg)
++ val |= 0x3;
++ if (test_bit(HW_IOM1, &cs->HW_Flags)) {
++ /* IOM 1 Mode */
++ if (!val) {
++ cs->writeisac(cs, ISAC_SPCR, 0xa);
++ cs->writeisac(cs, ISAC_ADF1, 0x2);
++ } else {
++ cs->writeisac(cs, ISAC_SPCR, val);
++ cs->writeisac(cs, ISAC_ADF1, 0xa);
++ }
++ } else {
++ /* IOM 2 Mode */
++ cs->writeisac(cs, ISAC_SPCR, val);
++ if (val)
++ cs->writeisac(cs, ISAC_ADF1, 0x8);
++ else
++ cs->writeisac(cs, ISAC_ADF1, 0x0);
++ }
++ break;
++#endif
+ default:
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "hfcd_l1hw unknown pr %4x", pr);
+@@ -1106,6 +1143,20 @@
+ static void
+ hfc_dbusy_timer(struct IsdnCardState *cs)
+ {
++#if 0
++ struct PStack *stptr;
++ if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
++ if (cs->debug)
++ debugl1(cs, "D-Channel Busy");
++ test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
++ stptr = cs->stlist;
++
++ while (stptr != NULL) {
++ stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
++ stptr = stptr->next;
++ }
++ }
++#endif
+ }
+
+ unsigned int __init
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_2bds0.h linux-2.4.29/drivers/isdn/hisax/hfc_2bds0.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_2bds0.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_2bds0.h 2005-03-22 15:06:46.236063832 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfc_2bds0.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: hfc_2bds0.h,v 1.6 2001/09/24 13:22:56 kai Exp $
+ *
+ * specific defines for CCD's HFC 2BDS0
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_2bs0.c linux-2.4.29/drivers/isdn/hisax/hfc_2bs0.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_2bs0.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_2bs0.c 2005-03-22 15:06:46.272058360 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfc_2bs0.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: hfc_2bs0.c,v 1.20 2001/09/24 13:22:56 kai Exp $
+ *
+ * specific routines for CCD's HFC 2BS0
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_2bs0.h linux-2.4.29/drivers/isdn/hisax/hfc_2bs0.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_2bs0.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_2bs0.h 2005-03-22 15:06:46.288055928 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfc_2bs0.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: hfc_2bs0.h,v 1.5 2001/09/24 13:22:56 kai Exp $
+ *
+ * specific defines for CCD's HFC 2BS0
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_pci.c linux-2.4.29/drivers/isdn/hisax/hfc_pci.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_pci.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_pci.c 2005-03-22 15:06:46.305053344 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfc_pci.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: hfc_pci.c,v 1.48 2001/09/24 13:22:56 kai Exp $
+ *
+ * low level driver for CCD´s hfc-pci based cards
+ *
+@@ -22,11 +22,12 @@
+ #include "hfc_pci.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+ #include <linux/interrupt.h>
+
+ extern const char *CardType[];
+
+-static const char *hfcpci_revision = "$Revision: 1.1.4.1 $";
++static const char *hfcpci_revision = "$Revision: 1.48 $";
+
+ /* table entry in the PCI devices list */
+ typedef struct {
+@@ -76,8 +77,6 @@
+ {
+ unsigned long flags;
+
+- printk(KERN_INFO "HiSax: release hfcpci at %p\n",
+- cs->hw.hfcpci.pci_io);
+ save_flags(flags);
+ cli();
+ cs->hw.hfcpci.int_m2 = 0; /* interrupt output off ! */
+@@ -88,11 +87,13 @@
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */
+ Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */
++#if CONFIG_PCI
+ pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, 0); /* disable memory mapped ports + busmaster */
++#endif /* CONFIG_PCI */
+ del_timer(&cs->hw.hfcpci.timer);
+ kfree(cs->hw.hfcpci.share_start);
+ cs->hw.hfcpci.share_start = NULL;
+- iounmap((void *)cs->hw.hfcpci.pci_io);
++ vfree(cs->hw.hfcpci.pci_io);
+ }
+
+ /********************************************************************************/
+@@ -687,10 +688,6 @@
+ debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded",
+ bcs->channel, bcs->tx_skb->len);
+
+- if (bcs->st->lli.l1writewakeup &&
+- (PACKET_NOACK != bcs->tx_skb->pkt_type))
+- bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
+-
+ dev_kfree_skb_any(bcs->tx_skb);
+ cli();
+ bcs->tx_skb = skb_dequeue(&bcs->squeue); /* fetch next data */
+@@ -1146,6 +1143,20 @@
+ static void
+ hfcpci_dbusy_timer(struct IsdnCardState *cs)
+ {
++#if 0
++ struct PStack *stptr;
++ if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
++ if (cs->debug)
++ debugl1(cs, "D-Channel Busy");
++ test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
++ stptr = cs->stlist;
++
++ while (stptr != NULL) {
++ stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
++ stptr = stptr->next;
++ }
++ }
++#endif
+ }
+
+ /*************************************/
+@@ -1550,6 +1561,17 @@
+ */
+ if (!cs)
+ return;
++#if 0
++ if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
++ if (cs->debug)
++ debugl1(cs, "D-Channel Busy cleared");
++ stptr = cs->stlist;
++ while (stptr != NULL) {
++ stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
++ stptr = stptr->next;
++ }
++ }
++#endif
+ if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
+ if (!cs->hw.hfcpci.nt_mode)
+ switch (cs->dc.hfcpci.ph_state) {
+@@ -1712,7 +1734,7 @@
+ if (pci_enable_device(tmp_hfcpci))
+ continue;
+ pci_set_master(tmp_hfcpci);
+- if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK)))
++ if ((card->para[0]) && (card->para[0] != (get_pcibase(tmp_hfcpci, 0) & PCI_BASE_ADDRESS_IO_MASK)))
+ continue;
+ else
+ break;
+@@ -1729,7 +1751,7 @@
+ printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
+ return (0);
+ }
+- cs->hw.hfcpci.pci_io = (char *) dev_hfcpci->resource[ 1].start;
++ cs->hw.hfcpci.pci_io = (char *) get_pcibase(dev_hfcpci, 1);
+ printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
+ } else {
+ printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
+@@ -1746,7 +1768,7 @@
+ printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
+ return 0;
+ }
+- cs->hw.hfcpci.fifos = (void *)
++ (ulong) cs->hw.hfcpci.fifos =
+ (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000;
+ pcibios_write_config_dword(cs->hw.hfcpci.pci_bus,
+ cs->hw.hfcpci.pci_device_fn, 0x80,
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_pci.h linux-2.4.29/drivers/isdn/hisax/hfc_pci.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_pci.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_pci.h 2005-03-22 15:06:46.320051064 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfc_pci.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: hfc_pci.h,v 1.10 2001/09/24 13:22:56 kai Exp $
+ *
+ * specific defines for CCD's HFC 2BDS0 PCI chips
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_sx.c linux-2.4.29/drivers/isdn/hisax/hfc_sx.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_sx.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_sx.c 2005-03-22 15:06:46.350046504 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfc_sx.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: hfc_sx.c,v 1.12 2001/09/24 13:22:56 kai Exp $
+ *
+ * level driver for CCD´s hfc-s+/sp based cards
+ *
+@@ -17,11 +17,10 @@
+ #include "hfc_sx.h"
+ #include "isdnl1.h"
+ #include <linux/interrupt.h>
+-#include <linux/isapnp.h>
+
+ extern const char *CardType[];
+
+-static const char *hfcsx_revision = "$Revision: 1.1.4.1 $";
++static const char *hfcsx_revision = "$Revision: 1.12 $";
+
+ /***************************************/
+ /* IRQ-table for CCDs demo board */
+@@ -940,6 +939,20 @@
+ static void
+ hfcsx_dbusy_timer(struct IsdnCardState *cs)
+ {
++#if 0
++ struct PStack *stptr;
++ if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
++ if (cs->debug)
++ debugl1(cs, "D-Channel Busy");
++ test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
++ stptr = cs->stlist;
++
++ while (stptr != NULL) {
++ stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
++ stptr = stptr->next;
++ }
++ }
++#endif
+ }
+
+ /*************************************/
+@@ -1333,6 +1346,17 @@
+ */
+ if (!cs)
+ return;
++#if 0
++ if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
++ if (cs->debug)
++ debugl1(cs, "D-Channel Busy cleared");
++ stptr = cs->stlist;
++ while (stptr != NULL) {
++ stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
++ stptr = stptr->next;
++ }
++ }
++#endif
+ if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
+ if (!cs->hw.hfcsx.nt_mode)
+ switch (cs->dc.hfcsx.ph_state) {
+@@ -1461,17 +1485,7 @@
+ return (0);
+ }
+
+-#ifdef __ISAPNP__
+-static struct isapnp_device_id hfc_ids[] __initdata = {
+- { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620),
+- ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620),
+- (unsigned long) "Teles 16.3c2" },
+- { 0, }
+-};
+
+-static struct isapnp_device_id *hdev = &hfc_ids[0];
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+
+ int __devinit
+ setup_hfcsx(struct IsdnCard *card)
+@@ -1482,45 +1496,6 @@
+
+ strcpy(tmp, hfcsx_revision);
+ printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp));
+-#ifdef __ISAPNP__
+- if (!card->para[1] && isapnp_present()) {
+- struct pci_bus *pb;
+- struct pci_dev *pd;
+-
+- while(hdev->card_vendor) {
+- if ((pb = isapnp_find_card(hdev->card_vendor,
+- hdev->card_device, pnp_c))) {
+- pnp_c = pb;
+- pd = NULL;
+- if ((pd = isapnp_find_dev(pnp_c,
+- hdev->vendor, hdev->function, pd))) {
+- printk(KERN_INFO "HiSax: %s detected\n",
+- (char *)hdev->driver_data);
+- pd->prepare(pd);
+- pd->deactivate(pd);
+- pd->activate(pd);
+- card->para[1] = pd->resource[0].start;
+- card->para[0] = pd->irq_resource[0].start;
+- if (!card->para[0] || !card->para[1]) {
+- printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
+- card->para[0], card->para[1]);
+- pd->deactivate(pd);
+- return(0);
+- }
+- break;
+- } else {
+- printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
+- }
+- }
+- hdev++;
+- pnp_c=NULL;
+- }
+- if (!hdev->card_vendor) {
+- printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");
+- return(0);
+- }
+- }
+-#endif
+ cs->hw.hfcsx.base = card->para[1] & 0xfffe;
+ cs->irq = card->para[0];
+ cs->hw.hfcsx.int_s1 = 0;
+@@ -1603,3 +1578,7 @@
+ cs->auxcmd = &hfcsx_auxcmd;
+ return (1);
+ }
++
++
++
++
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_sx.h linux-2.4.29/drivers/isdn/hisax/hfc_sx.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_sx.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_sx.h 2005-03-22 15:06:46.365044224 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfc_sx.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id$
+ *
+ * specific defines for CCD's HFC 2BDS0 S+,SP chips
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_usb.c linux-2.4.29/drivers/isdn/hisax/hfc_usb.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_usb.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_usb.c 2005-03-22 15:06:46.381041792 +0100
+@@ -0,0 +1,1189 @@
++/* $Id: hfc_usb.c,v 2.3 2001/07/06 21:30:11 werner Exp $
++ *
++ *
++ *
++ * Author (C) 2001 Werner Cornelius (werner@isdn-development.de)
++ * modular driver for Colognechip HFC-USB chip
++ * as plugin for HiSax isdn driver
++ * type approval valid for HFC-S USB based TAs
++ *
++ * Copyright 2001 by Werner Cornelius (werner@isdn-development.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, 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 <linux/types.h>
++#include <linux/stddef.h>
++#include <linux/timer.h>
++#include <linux/config.h>
++#include <linux/isdn_compat.h>
++#include <linux/init.h>
++#include "hisax.h"
++#include <linux/module.h>
++#include <linux/kernel_stat.h>
++#include <linux/tqueue.h>
++#include <linux/usb.h>
++#include <linux/kernel.h>
++#include <linux/smp_lock.h>
++#include <linux/sched.h>
++#include "hisax_loadable.h"
++
++#define INCLUDE_INLINE_FUNCS
++
++/***********/
++/* defines */
++/***********/
++#define HFC_CTRL_TIMEOUT 5 /* 5ms timeout writing/reading regs */
++#define HFC_TIMER_T3 7000 /* timeout for l1 activation timer */
++
++#define HFCUSB_L1_STATECHANGE 0 /* L1 state changed */
++#define HFCUSB_L1_DRX 1 /* D-frame received */
++#define HFCUSB_L1_ERX 2 /* E-frame received */
++#define HFCUSB_L1_DTX 4 /* D-frames completed */
++
++#define MAX_BCH_SIZE 2048 /* allowed B-channel packet size */
++
++#define HFCUSB_RX_THRESHOLD 64 /* threshold for fifo report bit rx */
++#define HFCUSB_TX_THRESHOLD 64 /* threshold for fifo report bit tx */
++
++#define HFCUSB_CHIP_ID 0x16 /* Chip ID register index */
++#define HFCUSB_CIRM 0x00 /* cirm register index */
++#define HFCUSB_USB_SIZE 0x07 /* int length register */
++#define HFCUSB_USB_SIZE_I 0x06 /* iso length register */
++#define HFCUSB_F_CROSS 0x0b /* bit order register */
++#define HFCUSB_CLKDEL 0x37 /* bit delay register */
++#define HFCUSB_CON_HDLC 0xfa /* channel connect register */
++#define HFCUSB_HDLC_PAR 0xfb
++#define HFCUSB_SCTRL 0x31 /* S-bus control register (tx) */
++#define HFCUSB_SCTRL_E 0x32 /* same for E and special funcs */
++#define HFCUSB_SCTRL_R 0x33 /* S-bus control register (rx) */
++#define HFCUSB_F_THRES 0x0c /* threshold register */
++#define HFCUSB_FIFO 0x0f /* fifo select register */
++#define HFCUSB_F_USAGE 0x1a /* fifo usage register */
++#define HFCUSB_MST_MODE0 0x14
++#define HFCUSB_MST_MODE1 0x15
++#define HFCUSB_P_DATA 0x1f
++#define HFCUSB_INC_RES_F 0x0e
++#define HFCUSB_STATES 0x30
++
++#define HFCUSB_CHIPID 0x40 /* ID value of HFC-USB */
++
++/******************/
++/* fifo registers */
++/******************/
++#define HFCUSB_NUM_FIFOS 8 /* maximum number of fifos */
++#define HFCUSB_B1_TX 0 /* index for B1 transmit bulk/int */
++#define HFCUSB_B1_RX 1 /* index for B1 receive bulk/int */
++#define HFCUSB_B2_TX 2
++#define HFCUSB_B2_RX 3
++#define HFCUSB_D_TX 4
++#define HFCUSB_D_RX 5
++#define HFCUSB_PCM_TX 6
++#define HFCUSB_PCM_RX 7
++
++/************/
++/* LED mask */
++/************/
++#define LED_DRIVER 0x1
++#define LED_L1 0x2
++#define LED_BCH 0x4
++
++/**********/
++/* macros */
++/**********/
++#define Write_hfc(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),0,0,HFC_CTRL_TIMEOUT)
++#define Read_hfc(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT)
++
++#ifdef COMPAT_HAS_USB_IDTAB
++/****************************************/
++/* data defining the devices to be used */
++/****************************************/
++static __devinitdata const struct usb_device_id hfc_usb_idtab[3] = {
++ {USB_DEVICE(0x959, 0x2bd0)}, /* Colognechip ROM */
++ {USB_DEVICE(0x7b0, 0x0006)}, /* USB TA 128 */
++ {} /* end with an all-zeroes entry */
++};
++#endif
++
++/*************************************************/
++/* entry and size of output/input control buffer */
++/*************************************************/
++#define HFC_CTRL_BUFSIZE 32
++typedef struct {
++ __u8 hfc_reg; /* register number */
++ __u8 reg_val; /* value to be written (or read) */
++} ctrl_buft;
++
++/***************************************************************/
++/* structure defining input+output fifos (interrupt/bulk mode) */
++/***************************************************************/
++struct hfcusb_data; /* forward definition */
++typedef struct {
++ int fifonum; /* fifo index attached to this structure */
++ __u8 fifo_mask; /* mask for this fifo */
++ int active; /* fifo is currently active */
++ struct hfcusb_data *hfc; /* pointer to main structure */
++ int pipe; /* address of endpoint */
++ __u8 usb_maxlen; /* maximum length for usb transfer */
++ int max_size; /* maximum size of receive/send packet */
++ int transmode; /* transparent mode selected */
++ int framenum; /* number of frame when last tx completed */
++ int rx_offset; /* offset inside rx buffer */
++ int next_complete; /* complete marker */
++ __u8 *act_ptr; /* pointer to next data */
++ __u8 intervall; /* interrupt interval */
++ struct sk_buff *buff; /* actual used buffer */
++ urb_t urb; /* transfer structure for usb routines */
++ __u8 buffer[128]; /* buffer incoming/outgoing data */
++} usb_fifo;
++
++/*********************************************/
++/* structure holding all data for one device */
++/*********************************************/
++typedef struct hfcusb_data {
++ struct hisax_drvreg regd; /* register data and callbacks */
++ struct usb_device *dev; /* our device */
++ int if_used; /* used interface number */
++ int alt_used; /* used alternate config */
++ int ctrl_paksize; /* control pipe packet size */
++ int ctrl_in_pipe, ctrl_out_pipe; /* handles for control pipe */
++
++ /* control pipe background handling */
++ ctrl_buft ctrl_buff[HFC_CTRL_BUFSIZE]; /* buffer holding queued data */
++ volatile int ctrl_in_idx, ctrl_out_idx, ctrl_cnt; /* input/output pointer + count */
++ urb_t ctrl_urb; /* transfer structure for control channel */
++ devrequest ctrl_write; /* buffer for control write request */
++ devrequest ctrl_read; /* same for read request */
++
++ volatile __u8 dfifo_fill; /* value read from tx d-fifo */
++ volatile __u8 active_fifos; /* fifos currently active as bit mask */
++ volatile __u8 threshold_mask; /* threshold actually reported */
++ volatile __u8 service_request; /* fifo needs service from task */
++ volatile __u8 ctrl_fifo; /* last selected fifo */
++ volatile __u8 bch_enables; /* or mask for sctrl_r and sctrl register values */
++ volatile __u8 led_req; /* request status of adapters leds */
++ volatile __u8 led_act; /* active status of adapters leds */
++ usb_fifo fifos[HFCUSB_NUM_FIFOS]; /* structure holding all fifo data */
++
++ /* layer 1 activation/deactivation handling */
++ volatile __u8 l1_state; /* actual l1 state */
++ volatile ulong l1_event; /* event mask */
++ struct tq_struct l1_tq; /* l1 bh structure */
++ struct timer_list t3_timer; /* timer for activation/deactivation */
++ struct timer_list t4_timer; /* timer for activation/deactivation */
++} hfcusb_data;
++
++#if 0
++static void
++usb_dump_urb(purb_t purb)
++{
++ printk("urb :%p\n", purb);
++ printk("next :%p\n", purb->next);
++ printk("dev :%p\n", purb->dev);
++ printk("pipe :%08X\n", purb->pipe);
++ printk("status :%d\n", purb->status);
++ printk("transfer_flags :%08X\n", purb->transfer_flags);
++ printk("transfer_buffer :%p\n", purb->transfer_buffer);
++ printk("transfer_buffer_length:%d\n",
++ purb->transfer_buffer_length);
++ printk("actual_length :%d\n", purb->actual_length);
++ printk("setup_packet :%p\n", purb->setup_packet);
++ printk("start_frame :%d\n", purb->start_frame);
++ printk("number_of_packets :%d\n", purb->number_of_packets);
++ printk("interval :%d\n", purb->interval);
++ printk("error_count :%d\n", purb->error_count);
++ printk("context :%p\n", purb->context);
++ printk("complete :%p\n", purb->complete);
++}
++#endif
++
++/*************************************************************************/
++/* bottom half handler for L1 activation/deactiavtaion + D-chan + E-chan */
++/*************************************************************************/
++static void
++usb_l1d_bh(hfcusb_data * hfc)
++{
++
++ while (hfc->l1_event) {
++ if (test_and_clear_bit
++ (HFCUSB_L1_STATECHANGE, &hfc->l1_event)) {
++ if (hfc->l1_state == 7)
++ hfc->led_req |= LED_L1;
++ else
++ hfc->led_req &= ~LED_L1;
++ if ((hfc->l1_state == 7) ||
++ (hfc->l1_state == 3))
++ hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
++ (hfc->l1_state ==
++ 7) ? (PH_ACTIVATE |
++ INDICATION)
++ : (PH_DEACTIVATE | INDICATION),
++ NULL);
++ }
++ if (test_and_clear_bit(HFCUSB_L1_DRX, &hfc->l1_event)) {
++ hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
++ PH_DATA | INDICATION,
++ (void *) 0);
++ }
++ if (test_and_clear_bit(HFCUSB_L1_ERX, &hfc->l1_event)) {
++ hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
++ PH_DATA | INDICATION,
++ (void *) 1);
++ }
++ if (test_and_clear_bit(HFCUSB_L1_DTX, &hfc->l1_event)) {
++ hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
++ PH_DATA | CONFIRM, NULL);
++ }
++ } /* while */
++} /* usb_l1d_bh */
++
++/******************************************************/
++/* start next background transfer for control channel */
++/******************************************************/
++static void
++ctrl_start_transfer(hfcusb_data * hfc)
++{
++
++ if (hfc->ctrl_cnt) {
++ switch (hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg) {
++ case HFCUSB_F_USAGE:
++ hfc->ctrl_urb.pipe = hfc->ctrl_in_pipe;
++ hfc->ctrl_urb.setup_packet =
++ (u_char *) & hfc->ctrl_read;
++ hfc->ctrl_urb.transfer_buffer_length = 1;
++ hfc->ctrl_read.index =
++ hfc->ctrl_buff[hfc->ctrl_out_idx].
++ hfc_reg;
++ hfc->ctrl_urb.transfer_buffer =
++ (char *) &hfc->dfifo_fill;
++ break;
++
++ default: /* write register */
++ hfc->ctrl_urb.pipe = hfc->ctrl_out_pipe;
++ hfc->ctrl_urb.setup_packet =
++ (u_char *) & hfc->ctrl_write;
++ hfc->ctrl_urb.transfer_buffer = NULL;
++ hfc->ctrl_urb.transfer_buffer_length = 0;
++ hfc->ctrl_write.index =
++ hfc->ctrl_buff[hfc->ctrl_out_idx].
++ hfc_reg;
++ hfc->ctrl_write.value =
++ hfc->ctrl_buff[hfc->ctrl_out_idx].
++ reg_val;
++ break;
++ }
++ usb_submit_urb(&hfc->ctrl_urb); /* start transfer */
++ }
++} /* ctrl_start_transfer */
++
++/************************************/
++/* queue a control transfer request */
++/* return 0 on success. */
++/************************************/
++static int
++queue_control_request(hfcusb_data * hfc, __u8 reg, __u8 val)
++{
++ ctrl_buft *buf;
++
++ if (hfc->ctrl_cnt >= HFC_CTRL_BUFSIZE)
++ return (1); /* no space left */
++ buf = hfc->ctrl_buff + hfc->ctrl_in_idx; /* pointer to new index */
++ buf->hfc_reg = reg;
++ buf->reg_val = val;
++ if (++hfc->ctrl_in_idx >= HFC_CTRL_BUFSIZE)
++ hfc->ctrl_in_idx = 0; /* pointer wrap */
++ if (++hfc->ctrl_cnt == 1)
++ ctrl_start_transfer(hfc);
++ return (0);
++} /* queue_control_request */
++
++/**************************************/
++/* called when timer t3 or t4 expires */
++/**************************************/
++static void
++l1_timer_expire(hfcusb_data * hfc)
++{
++ if (timer_pending(&hfc->t4_timer))
++ del_timer(&hfc->t4_timer);
++ queue_control_request(hfc, HFCUSB_STATES, 0x40);
++ test_and_set_bit(HFCUSB_L1_STATECHANGE,
++ &hfc->l1_event);
++ queue_task(&hfc->l1_tq, &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++} /* l1_timer_expire */
++
++/**************************************************/
++/* (re)fills a tx-fifo urb. Queuing is done later */
++/**************************************************/
++static void
++fill_tx_urb(usb_fifo * fifo)
++{
++ struct sk_buff *skb;
++ long flags;
++ int i, ii = 0;
++
++ fifo->urb.dev = fifo->hfc->dev;
++ if ((fifo->buff)
++ && (fifo->urb.transfer_buffer_length < fifo->usb_maxlen)) {
++ switch (fifo->fifonum) {
++ case HFCUSB_B1_TX:
++ case HFCUSB_B2_TX:
++ skb = fifo->buff;
++ fifo->buff = NULL;
++ fifo->hfc->regd.bch_l1l2(fifo->hfc->regd.
++ arg_hisax,
++ (fifo->fifonum ==
++ HFCUSB_B1_TX) ? 0
++ : 1,
++ (PH_DATA |
++ CONFIRM),
++ (void *) skb);
++ fifo->hfc->service_request |=
++ fifo->fifo_mask;
++ return;
++ case HFCUSB_D_TX:
++ dev_kfree_skb_any(fifo->buff);
++ fifo->buff = NULL;
++ save_flags(flags);
++ cli();
++ fifo->hfc->dfifo_fill = 0xff; /* currently invalid data */
++ queue_control_request(fifo->hfc,
++ HFCUSB_FIFO,
++ HFCUSB_D_TX);
++ queue_control_request(fifo->hfc,
++ HFCUSB_F_USAGE, 0);
++ restore_flags(flags);
++ return;
++ default:
++ return; /* error, invalid fifo */
++ }
++ }
++
++ /* check if new buffer needed */
++ if (!fifo->buff) {
++ switch (fifo->fifonum) {
++ case HFCUSB_B1_TX:
++ if (fifo->hfc->regd.bsk[0])
++ fifo->buff = *fifo->hfc->regd.bsk[0]; /* B1-channel tx buffer */
++ break;
++ case HFCUSB_B2_TX:
++ if (fifo->hfc->regd.bsk[1])
++ fifo->buff = *fifo->hfc->regd.bsk[1]; /* B2-channel tx buffer */
++ break;
++ case HFCUSB_D_TX:
++ if (fifo->hfc->regd.dsq)
++ fifo->buff = skb_dequeue(fifo->hfc->regd.dsq); /* D-channel tx queue */
++ break;
++ default:
++ return; /* error, invalid fifo */
++ }
++ if (!fifo->buff) {
++ fifo->active = 0; /* we are inactive now */
++ fifo->hfc->active_fifos &= ~fifo->fifo_mask;
++ if (fifo->fifonum == HFCUSB_D_TX) {
++ test_and_set_bit(HFCUSB_L1_DTX,
++ &fifo->hfc->l1_event);
++ queue_task(&fifo->hfc->l1_tq,
++ &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++ }
++ return;
++ }
++ fifo->act_ptr = fifo->buff->data; /* start of data */
++ fifo->active = 1;
++ ii = 1;
++ fifo->hfc->active_fifos |= fifo->fifo_mask;
++ fifo->hfc->service_request &= ~fifo->fifo_mask;
++ }
++ /* fillup the send buffer */
++ i = fifo->buff->len - (fifo->act_ptr - fifo->buff->data); /* remaining length */
++ fifo->buffer[0] = !fifo->transmode; /* not eof */
++ if (i > (fifo->usb_maxlen - ii)) {
++ i = fifo->usb_maxlen - ii;
++ }
++ if (i)
++ memcpy(fifo->buffer + ii, fifo->act_ptr, i);
++ fifo->urb.transfer_buffer_length = i + ii;
++ fifo->rx_offset = ii;
++} /* fill_tx_urb */
++
++/************************************************/
++/* transmit completion routine for all tx fifos */
++/************************************************/
++static void
++tx_complete(purb_t urb)
++{
++ usb_fifo *fifo = (usb_fifo *) urb->context; /* pointer to our fifo */
++
++ fifo->hfc->service_request &= ~fifo->fifo_mask; /* no further handling */
++ fifo->framenum = usb_get_current_frame_number(fifo->hfc->dev);
++
++ /* check for deactivation or error */
++ if ((!fifo->active) || (urb->status)) {
++ fifo->hfc->active_fifos &= ~fifo->fifo_mask; /* we are inactive */
++ fifo->active = 0;
++ if ((fifo->buff) && (fifo->fifonum == HFCUSB_D_TX)) {
++ dev_kfree_skb_any(fifo->buff);
++ }
++ fifo->buff = NULL;
++ return;
++ }
++ fifo->act_ptr += (urb->transfer_buffer_length - fifo->rx_offset); /* adjust pointer */
++ fill_tx_urb(fifo); /* refill the urb */
++ fifo->hfc->threshold_mask |= fifo->fifo_mask; /* assume threshold reached */
++ if (fifo->buff)
++ fifo->hfc->service_request |= fifo->fifo_mask; /* need to restart */
++} /* tx_complete */
++
++/***********************************************/
++/* receive completion routine for all rx fifos */
++/***********************************************/
++static void
++rx_complete(purb_t urb)
++{
++ usb_fifo *fifo = (usb_fifo *) urb->context; /* pointer to our fifo */
++ hfcusb_data *hfc = fifo->hfc;
++ usb_fifo *txfifo;
++ __u8 last_state;
++ int i, ii, currcnt, hdlci;
++ struct sk_buff *skb;
++
++ urb->dev = hfc->dev; /* security init */
++ if ((!fifo->active) || (urb->status)) {
++ hfc->service_request &= ~fifo->fifo_mask; /* no further handling */
++ hfc->active_fifos &= ~fifo->fifo_mask; /* we are inactive */
++ fifo->urb.interval = 0; /* cancel automatic rescheduling */
++ if (fifo->buff) {
++ dev_kfree_skb_any(fifo->buff);
++ fifo->buff = NULL;
++ }
++ return;
++ }
++
++ /* first check for any status changes */
++ if ((urb->actual_length < fifo->rx_offset)
++ || (urb->actual_length > fifo->usb_maxlen))
++ return; /* error condition */
++
++ if (fifo->rx_offset) {
++ hfc->threshold_mask = fifo->buffer[1]; /* update threshold status */
++ fifo->next_complete = fifo->buffer[0] & 1;
++ if ((fifo->fifonum == HFCUSB_D_RX) &&
++ (hfc->led_req != hfc->led_act))
++ queue_control_request(hfc, HFCUSB_P_DATA, hfc->led_req);
++
++ /* check if rescheduling needed */
++ if ((i =
++ hfc->service_request & hfc->active_fifos & ~hfc->
++ threshold_mask)) {
++ currcnt =
++ usb_get_current_frame_number(hfc->dev);
++ txfifo = hfc->fifos + HFCUSB_B1_TX;
++ ii = 3;
++ while (ii--) {
++ if ((i & txfifo->fifo_mask)
++ && (currcnt != txfifo->framenum)) {
++ hfc->service_request &=
++ ~txfifo->fifo_mask;
++ if (!txfifo->buff)
++ fill_tx_urb(txfifo);
++ if (txfifo->buff)
++ usb_submit_urb(&txfifo->
++ urb);
++ }
++ txfifo += 2;
++ }
++ }
++
++ /* handle l1 events */
++ if ((fifo->buffer[0] >> 4) != hfc->l1_state) {
++ last_state = hfc->l1_state;
++ hfc->l1_state = fifo->buffer[0] >> 4; /* update status */
++ if (timer_pending(&hfc->t4_timer))
++ del_timer(&hfc->t4_timer);
++ if (((hfc->l1_state == 3) &&
++ ((last_state == 7) ||
++ (last_state == 8))) ||
++ ((timer_pending(&hfc->t3_timer) &&
++ (hfc->l1_state == 8)))) {
++ hfc->t4_timer.expires = jiffies + 2;
++ add_timer(&hfc->t4_timer);
++ } else {
++ if (timer_pending(&hfc->t3_timer)
++ && (hfc->l1_state == 7))
++ del_timer(&hfc->t3_timer); /* no longer needed */
++ test_and_set_bit(HFCUSB_L1_STATECHANGE,
++ &hfc->l1_event);
++ queue_task(&hfc->l1_tq, &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++ }
++ }
++ }
++
++ /* check the length for data and move if present */
++ if (fifo->next_complete || (urb->actual_length > fifo->rx_offset)) {
++ i = fifo->buff->len + urb->actual_length - fifo->rx_offset; /* new total length */
++ hdlci = (fifo->transmode) ? 0 : 3;
++ if (i <= (fifo->max_size + hdlci)) {
++ memcpy(fifo->act_ptr,
++ fifo->buffer + fifo->rx_offset,
++ urb->actual_length - fifo->rx_offset);
++ fifo->act_ptr +=
++ (urb->actual_length - fifo->rx_offset);
++ fifo->buff->len +=
++ (urb->actual_length - fifo->rx_offset);
++ } else
++ fifo->buff->len = fifo->max_size + 4; /* mark frame as to long */
++ if (fifo->next_complete && (urb->actual_length < fifo->usb_maxlen)) {
++ /* the frame is complete */
++ fifo->next_complete = 0;
++ if (((!*(fifo->act_ptr - 1)) || fifo->transmode) &&
++ (fifo->buff->len >= (hdlci + 1))
++ && (fifo->buff->len <=
++ (fifo->max_size + hdlci)) &&
++ ((skb = dev_alloc_skb(fifo->max_size + hdlci)) != NULL)) {
++ fifo->buff->len -= hdlci; /* adjust size */
++ switch (fifo->fifonum) {
++ case HFCUSB_D_RX:
++ skb_queue_tail(hfc->regd.
++ drq,
++ fifo->buff);
++ test_and_set_bit
++ (HFCUSB_L1_DRX,
++ &hfc->l1_event);
++ queue_task(&hfc->l1_tq,
++ &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++ break;
++
++ case HFCUSB_B1_RX:
++ if (hfc->regd.brq[0]) {
++ skb_queue_tail
++ (hfc->regd.
++ brq[0],
++ fifo->buff);
++ hfc->regd.
++ bch_l1l2(hfc->
++ regd.
++ arg_hisax,
++ 0,
++ PH_DATA
++ |
++ INDICATION,
++ (void *)
++ fifo->
++ buff);
++ } else
++ dev_kfree_skb_any
++ (fifo->buff);
++ break;
++
++ case HFCUSB_B2_RX:
++ if (hfc->regd.brq[1]) {
++ skb_queue_tail
++ (hfc->regd.
++ brq[1],
++ fifo->buff);
++ hfc->regd.
++ bch_l1l2(hfc->
++ regd.
++ arg_hisax,
++ 1,
++ PH_DATA
++ |
++ INDICATION,
++ (void
++ *)
++ fifo->
++ buff);
++ } else
++ dev_kfree_skb_any
++ (fifo->buff);
++ break;
++
++ case HFCUSB_PCM_RX:
++ skb_queue_tail(&hfc->regd.
++ erq,
++ fifo->buff);
++ test_and_set_bit
++ (HFCUSB_L1_ERX,
++ &hfc->l1_event);
++ queue_task(&hfc->l1_tq,
++ &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++ break;
++
++ default:
++ dev_kfree_skb_any(fifo->
++ buff);
++ break;
++ }
++ fifo->buff = skb;
++ }
++ fifo->buff->len = 0; /* reset counter */
++ fifo->act_ptr = fifo->buff->data; /* and pointer */
++ }
++ }
++ fifo->rx_offset = (urb->actual_length < fifo->usb_maxlen) ? 2 : 0;
++} /* rx_complete */
++
++/***************************************************/
++/* start the interrupt transfer for the given fifo */
++/***************************************************/
++static void
++start_rx_fifo(usb_fifo * fifo)
++{
++ if (fifo->buff)
++ return; /* still active */
++ if (!
++ (fifo->buff =
++ dev_alloc_skb(fifo->max_size + (fifo->transmode ? 0 : 3))))
++ return;
++ fifo->act_ptr = fifo->buff->data;
++ FILL_INT_URB(&fifo->urb, fifo->hfc->dev, fifo->pipe, fifo->buffer,
++ fifo->usb_maxlen, rx_complete, fifo, fifo->intervall);
++ fifo->next_complete = 0;
++ fifo->rx_offset = 2;
++ fifo->active = 1; /* must be marked active */
++ fifo->hfc->active_fifos |= fifo->fifo_mask;
++ if (usb_submit_urb(&fifo->urb)) {
++ fifo->active = 0;
++ fifo->hfc->active_fifos &= ~fifo->fifo_mask;
++ dev_kfree_skb_any(fifo->buff);
++ fifo->buff = NULL;
++ }
++} /* start_rx_fifo */
++
++/***************************************************************/
++/* control completion routine handling background control cmds */
++/***************************************************************/
++static void
++ctrl_complete(purb_t urb)
++{
++ hfcusb_data *hfc = (hfcusb_data *) urb->context;
++
++ urb->dev = hfc->dev;
++ if (hfc->ctrl_cnt) {
++ switch (hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg) {
++ case HFCUSB_FIFO:
++ hfc->ctrl_fifo =
++ hfc->ctrl_buff[hfc->ctrl_out_idx].
++ reg_val;
++ break;
++ case HFCUSB_F_USAGE:
++ if (!hfc->dfifo_fill) {
++ fill_tx_urb(hfc->fifos +
++ HFCUSB_D_TX);
++ if (hfc->fifos[HFCUSB_D_TX].buff)
++ usb_submit_urb(&hfc->
++ fifos
++ [HFCUSB_D_TX].
++ urb);
++ } else {
++ queue_control_request(hfc,
++ HFCUSB_FIFO,
++ HFCUSB_D_TX);
++ queue_control_request(hfc,
++ HFCUSB_F_USAGE,
++ 0);
++ }
++ break;
++ case HFCUSB_SCTRL_R:
++ switch (hfc->ctrl_fifo) {
++ case HFCUSB_B1_RX:
++ if (hfc->bch_enables & 1)
++ start_rx_fifo(hfc->
++ fifos
++ +
++ HFCUSB_B1_RX);
++ break;
++ case HFCUSB_B2_RX:
++ if (hfc->bch_enables & 2)
++ start_rx_fifo(hfc->
++ fifos
++ +
++ HFCUSB_B2_RX);
++ break;
++ }
++ if (hfc->bch_enables & 3)
++ hfc->led_req |= LED_BCH;
++ else
++ hfc->led_req &= ~LED_BCH;
++ break;
++ case HFCUSB_P_DATA:
++ hfc->led_act =
++ hfc->ctrl_buff[hfc->ctrl_out_idx].
++ reg_val;
++ break;
++ }
++ hfc->ctrl_cnt--; /* decrement actual count */
++ if (++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE)
++ hfc->ctrl_out_idx = 0; /* pointer wrap */
++ ctrl_start_transfer(hfc); /* start next transfer */
++ }
++} /* ctrl_complete */
++
++/*****************************************/
++/* Layer 1 + D channel access from HiSax */
++/*****************************************/
++static void
++hfcusb_l1_access(void *drvarg, int pr, void *arg)
++{
++ hfcusb_data *hfc = (hfcusb_data *) drvarg;
++
++ switch (pr) {
++ case (PH_DATA | REQUEST):
++ case (PH_PULL | INDICATION):
++ skb_queue_tail(hfc->regd.dsq,
++ (struct sk_buff *) arg);
++ if (!hfc->fifos[HFCUSB_D_TX].active
++ && !hfc->dfifo_fill) {
++ fill_tx_urb(hfc->fifos + HFCUSB_D_TX);
++ hfc->active_fifos |=
++ hfc->fifos[HFCUSB_D_TX].fifo_mask;
++ usb_submit_urb(&hfc->fifos[HFCUSB_D_TX].
++ urb);
++ }
++ break;
++ case (PH_ACTIVATE | REQUEST):
++ switch (hfc->l1_state) {
++ case 6:
++ case 8:
++ hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
++ (PH_DEACTIVATE |
++ INDICATION), NULL);
++
++ break;
++ case 7:
++ hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
++ (PH_ACTIVATE |
++ INDICATION), NULL);
++
++ break;
++ default:
++ queue_control_request(hfc, HFCUSB_STATES, 0x60); /* start activation */
++ hfc->t3_timer.expires =
++ jiffies + (HFC_TIMER_T3 * HZ) / 1000;
++ if (!timer_pending(&hfc->t3_timer))
++ add_timer(&hfc->t3_timer);
++ break;
++ }
++ break;
++
++ case (PH_DEACTIVATE | REQUEST):
++ queue_control_request(hfc, HFCUSB_STATES, 0x40); /* start deactivation */
++ break;
++ default:
++ printk(KERN_INFO "unknown hfcusb l1_access 0x%x\n",
++ pr);
++ break;
++ }
++} /* hfcusb_l1_access */
++
++/*******************************/
++/* B channel access from HiSax */
++/*******************************/
++static void
++hfcusb_bch_access(void *drvarg, int chan, int pr, void *arg)
++{
++ hfcusb_data *hfc = (hfcusb_data *) drvarg;
++ usb_fifo *fifo = hfc->fifos + (chan ? HFCUSB_B2_TX : HFCUSB_B1_TX);
++ long flags;
++
++ switch (pr) {
++ case (PH_DATA | REQUEST):
++ case (PH_PULL | INDICATION):
++ save_flags(flags);
++ cli();
++ if (!fifo->active) {
++ fill_tx_urb(fifo);
++ hfc->active_fifos |= fifo->fifo_mask;
++ usb_submit_urb(&fifo->urb);
++ }
++ restore_flags(flags);
++ break;
++ case (PH_ACTIVATE | REQUEST):
++ if (!((int) arg)) {
++ hfc->bch_enables &= ~(1 << chan);
++ if (fifo->active) {
++ fifo->active = 0;
++ usb_unlink_urb(&fifo->urb);
++ }
++ save_flags(flags);
++ cli();
++ queue_control_request(hfc, HFCUSB_FIFO,
++ fifo->fifonum);
++ queue_control_request(hfc,
++ HFCUSB_INC_RES_F, 2);
++ queue_control_request(hfc, HFCUSB_CON_HDLC,
++ 9);
++ queue_control_request(hfc, HFCUSB_SCTRL,
++ 0x40 +
++ hfc->bch_enables);
++ queue_control_request(hfc, HFCUSB_SCTRL_R,
++ hfc->bch_enables);
++ restore_flags(flags);
++ fifo++;
++ if (fifo->active) {
++ fifo->active = 0;
++ usb_unlink_urb(&fifo->urb);
++ }
++ return; /* fifo deactivated */
++ }
++ fifo->transmode = ((int) arg == L1_MODE_TRANS);
++ fifo->max_size =
++ ((fifo->transmode) ? fifo->
++ usb_maxlen : MAX_BCH_SIZE);
++ (fifo + 1)->transmode = fifo->transmode;
++ (fifo + 1)->max_size = fifo->max_size;
++ hfc->bch_enables |= (1 << chan);
++ save_flags(flags);
++ cli();
++ queue_control_request(hfc, HFCUSB_FIFO,
++ fifo->fifonum);
++ queue_control_request(hfc, HFCUSB_CON_HDLC,
++ ((!fifo->
++ transmode) ? 9 : 11));
++ queue_control_request(hfc, HFCUSB_INC_RES_F, 2);
++ queue_control_request(hfc, HFCUSB_SCTRL,
++ 0x40 + hfc->bch_enables);
++ if ((int) arg == L1_MODE_HDLC)
++ queue_control_request(hfc, HFCUSB_CON_HDLC,
++ 8);
++ queue_control_request(hfc, HFCUSB_FIFO,
++ fifo->fifonum + 1);
++ queue_control_request(hfc, HFCUSB_CON_HDLC,
++ ((!fifo->
++ transmode) ? 8 : 10));
++ queue_control_request(hfc, HFCUSB_INC_RES_F, 2);
++ queue_control_request(hfc, HFCUSB_SCTRL_R,
++ hfc->bch_enables);
++ restore_flags(flags);
++
++ break;
++
++ default:
++ printk(KERN_INFO
++ "unknown hfcusb bch_access chan %d 0x%x\n",
++ chan, pr);
++ break;
++ }
++} /* hfcusb_bch_access */
++
++/***************************************************************************/
++/* usb_init is called once when a new matching device is detected to setup */
++/* main parmeters. It registers the driver at the main hisax module. */
++/* on success 0 is returned. */
++/***************************************************************************/
++static int
++usb_init(hfcusb_data * hfc)
++{
++ usb_fifo *fifo;
++ int i;
++ u_char b;
++
++ /* check the chip id */
++ if ((Read_hfc(hfc, HFCUSB_CHIP_ID, &b) != 1) ||
++ (b != HFCUSB_CHIPID)) {
++ printk(KERN_INFO "HFC-USB: Invalid chip id 0x%02x\n", b);
++ return (1);
++ }
++
++ /* first set the needed config, interface and alternate */
++ usb_set_configuration(hfc->dev, 1);
++ usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used);
++
++ /* init the led state request */
++ hfc->led_req = LED_DRIVER;
++
++ /* now we initialise the chip */
++ Write_hfc(hfc, HFCUSB_CIRM, 0x10); /* aux = output, reset off */
++ Write_hfc(hfc, HFCUSB_P_DATA, 0); /* leds = off */
++ Write_hfc(hfc, HFCUSB_USB_SIZE,
++ (hfc->fifos[HFCUSB_B1_TX].usb_maxlen >> 3) |
++ ((hfc->fifos[HFCUSB_B1_RX].usb_maxlen >> 3) << 4));
++
++ /* enable PCM/GCI master mode */
++ Write_hfc(hfc, HFCUSB_MST_MODE1, 0); /* set default values */
++ Write_hfc(hfc, HFCUSB_MST_MODE0, 1); /* enable master mode */
++
++ /* init the fifos */
++ Write_hfc(hfc, HFCUSB_F_THRES, (HFCUSB_TX_THRESHOLD >> 3) |
++ ((HFCUSB_RX_THRESHOLD >> 3) << 4));
++
++ for (i = 0, fifo = hfc->fifos + i; i < HFCUSB_NUM_FIFOS;
++ i++, fifo++) {
++ Write_hfc(hfc, HFCUSB_FIFO, i); /* select the desired fifo */
++
++ fifo->transmode = 0; /* hdlc mode selected */
++ fifo->buff = NULL; /* init buffer pointer */
++ fifo->max_size =
++ (i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN;
++ Write_hfc(hfc, HFCUSB_HDLC_PAR, ((i <= HFCUSB_B2_RX) ? 0 : 2)); /* data length */
++ Write_hfc(hfc, HFCUSB_CON_HDLC, ((i & 1) ? 0x08 : 0x09)); /* rx hdlc, tx fill 1 */
++ Write_hfc(hfc, HFCUSB_INC_RES_F, 2); /* reset the fifo */
++ }
++
++ Write_hfc(hfc, HFCUSB_CLKDEL, 0x0f); /* clock delay value */
++ Write_hfc(hfc, HFCUSB_STATES, 3 | 0x10); /* set deactivated mode */
++ Write_hfc(hfc, HFCUSB_STATES, 3); /* enable state machine */
++
++ Write_hfc(hfc, HFCUSB_SCTRL_R, 0); /* disable both B receivers */
++ Write_hfc(hfc, HFCUSB_SCTRL, 0x40); /* disable B transmitters + cap mode */
++
++ /* init the l1 timer */
++ init_timer(&hfc->t3_timer);
++ hfc->t3_timer.data = (long) hfc;
++ hfc->t3_timer.function = (void *) l1_timer_expire;
++ hfc->t4_timer.data = (long) hfc;
++ hfc->t4_timer.function = (void *) l1_timer_expire;
++ hfc->l1_tq.routine = (void *) (void *) usb_l1d_bh;
++ hfc->l1_tq.sync = 0;
++ hfc->l1_tq.data = hfc;
++
++ /* init the background control machinery */
++ hfc->ctrl_read.requesttype = 0xc0;
++ hfc->ctrl_read.request = 1;
++ hfc->ctrl_read.length = 1;
++ hfc->ctrl_write.requesttype = 0x40;
++ hfc->ctrl_write.request = 0;
++ hfc->ctrl_write.length = 0;
++ FILL_CONTROL_URB(&hfc->ctrl_urb, hfc->dev, hfc->ctrl_out_pipe,
++ (u_char *) & hfc->ctrl_write, NULL, 0,
++ ctrl_complete, hfc);
++
++ /* init the TX-urbs */
++ fifo = hfc->fifos + HFCUSB_D_TX;
++ FILL_BULK_URB(&fifo->urb, hfc->dev, fifo->pipe,
++ (u_char *) fifo->buffer, 0, tx_complete, fifo);
++ fifo = hfc->fifos + HFCUSB_B1_TX;
++ FILL_BULK_URB(&fifo->urb, hfc->dev, fifo->pipe,
++ (u_char *) fifo->buffer, 0, tx_complete, fifo);
++ fifo = hfc->fifos + HFCUSB_B2_TX;
++ FILL_BULK_URB(&fifo->urb, hfc->dev, fifo->pipe,
++ (u_char *) fifo->buffer, 0, tx_complete, fifo);
++
++ /* init the E-buffer */
++ skb_queue_head_init(&hfc->regd.erq);
++
++ /* now register ourself at hisax */
++ hfc->regd.version = HISAX_LOAD_VERSION; /* set our version */
++ hfc->regd.cmd = HISAX_LOAD_REGISTER; /* register command */
++ hfc->regd.argl1 = (void *) hfc; /* argument for our local routine */
++ hfc->regd.dch_l2l1 = hfcusb_l1_access;
++ hfc->regd.bch_l2l1 = hfcusb_bch_access;
++ hfc->regd.drvname = "hfc_usb";
++ if (hisax_register_hfcusb(&hfc->regd)) {
++ printk(KERN_INFO "HFC-USB failed to register at hisax\n");
++ Write_hfc(hfc, HFCUSB_CIRM, 0x08); /* aux = input, reset on */
++ return (1);
++ }
++
++ /* startup the D- and E-channel fifos */
++ start_rx_fifo(hfc->fifos + HFCUSB_D_RX); /* D-fifo */
++ if (hfc->fifos[HFCUSB_PCM_RX].pipe)
++ start_rx_fifo(hfc->fifos + HFCUSB_PCM_RX); /* E-fifo */
++
++ return (0);
++} /* usb_init */
++
++/*************************************************/
++/* function called to probe a new plugged device */
++/*************************************************/
++static void *
++hfc_usb_probe(struct usb_device *dev, unsigned int interface
++#ifdef COMPAT_HAS_USB_IDTAB
++ , const struct usb_device_id *id_table)
++#else
++ )
++#endif
++{
++ hfcusb_data *context;
++ struct usb_interface *ifp = dev->actconfig->interface + interface;
++ struct usb_interface_descriptor *ifdp =
++ ifp->altsetting + ifp->act_altsetting;
++ struct usb_endpoint_descriptor *epd;
++ int i, idx, ep_msk;
++
++#ifdef COMPAT_HAS_USB_IDTAB
++ if (id_table && (dev->descriptor.idVendor == id_table->idVendor) &&
++ (dev->descriptor.idProduct == id_table->idProduct) &&
++#else
++ if ((((dev->descriptor.idVendor == 0x959) &&
++ (dev->descriptor.idProduct == 0x2bd0)) ||
++ ((dev->descriptor.idVendor == 0x7b0) &&
++ (dev->descriptor.idProduct == 0x0006))) &&
++#endif
++ (ifdp->bNumEndpoints >= 6) && (ifdp->bNumEndpoints <= 16)) {
++ if (!(context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL))) {
++ return (NULL); /* got no mem */
++ };
++ memset(context, 0, sizeof(hfcusb_data)); /* clear the structure */
++ i = ifdp->bNumEndpoints; /* get number of endpoints */
++ ep_msk = 0; /* none found */
++ epd = ifdp->endpoint; /* first endpoint descriptor */
++ while (i-- && ((ep_msk & 0xcf) != 0xcf)) {
++
++ idx = (((epd->bEndpointAddress & 0x7f) - 1) << 1); /* get endpoint base */
++ if (idx < 7) {
++ switch (epd->bmAttributes) {
++ case USB_ENDPOINT_XFER_INT:
++ if (!
++ (epd->
++ bEndpointAddress &
++ 0x80))
++ break; /* only interrupt in allowed */
++ idx++; /* input index is odd */
++ context->fifos[idx].pipe =
++ usb_rcvintpipe(dev,
++ epd->
++ bEndpointAddress);
++ break;
++
++ case USB_ENDPOINT_XFER_BULK:
++ if (epd->
++ bEndpointAddress &
++ 0x80)
++ break; /* only bulk out allowed */
++ context->fifos[idx].pipe =
++ usb_sndbulkpipe(dev,
++ epd->
++ bEndpointAddress);
++ break;
++ default:
++ context->fifos[idx].pipe = 0; /* reset data */
++ } /* switch attribute */
++
++ if (context->fifos[idx].pipe) {
++ context->fifos[idx].fifonum = idx;
++ context->fifos[idx].fifo_mask =
++ 1 << idx;
++ context->fifos[idx].hfc = context;
++ context->fifos[idx].usb_maxlen =
++ epd->wMaxPacketSize;
++ context->fifos[idx].intervall =
++ epd->bInterval;
++ ep_msk |= (1 << idx);
++ } else
++ ep_msk &= ~(1 << idx);
++ } /* idx < 7 */
++ epd++;
++ }
++
++ if ((ep_msk & 0x3f) != 0x3f) {
++ kfree(context);
++ return (NULL);
++ }
++ MOD_INC_USE_COUNT; /* lock our module */
++ context->dev = dev; /* save device */
++ context->if_used = interface; /* save used interface */
++ context->alt_used = ifp->act_altsetting; /* and alternate config */
++ context->ctrl_paksize = dev->descriptor.bMaxPacketSize0; /* control size */
++
++ /* create the control pipes needed for register access */
++ context->ctrl_in_pipe = usb_rcvctrlpipe(context->dev, 0);
++ context->ctrl_out_pipe = usb_sndctrlpipe(context->dev, 0);
++
++ /* init the chip and register the driver */
++ if (usb_init(context)) {
++ kfree(context);
++ MOD_DEC_USE_COUNT;
++ return (NULL);
++ }
++
++ printk(KERN_INFO
++ "HFC-USB: New device if=%d alt=%d registered\n",
++ context->if_used, context->alt_used);
++ return (context);
++ }
++
++ return (NULL); /* no matching entry */
++} /* hfc_usb_probe */
++
++/****************************************************/
++/* function called when an active device is removed */
++/****************************************************/
++static void
++hfc_usb_disconnect(struct usb_device *usbdev, void *drv_context)
++{
++ hfcusb_data *context = drv_context;
++ int i;
++ struct sk_buff *skb;
++
++ /* tell all fifos to terminate */
++ for (i = 0; i < HFCUSB_NUM_FIFOS; i++)
++ if (context->fifos[i].active) {
++ context->fifos[i].active = 0;
++ usb_unlink_urb(&context->fifos[i].urb);
++ }
++ while (context->active_fifos) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ /* Timeout 10ms */
++ schedule_timeout((10 * HZ) / 1000);
++ }
++ if (timer_pending(&context->t3_timer))
++ del_timer(&context->t3_timer);
++ context->regd.release_driver(context->regd.arg_hisax);
++ while ((skb = skb_dequeue(&context->regd.erq)) != NULL)
++ dev_kfree_skb_any(skb);
++
++ kfree(context); /* free our structure again */
++ MOD_DEC_USE_COUNT; /* and decrement the usage counter */
++} /* hfc_usb_disconnect */
++
++/************************************/
++/* our driver information structure */
++/************************************/
++static struct usb_driver hfc_drv = {
++ name:"hfc_usb",
++#ifdef COMPAT_HAS_USB_IDTAB
++ id_table:hfc_usb_idtab,
++#endif
++ probe:hfc_usb_probe,
++ disconnect:hfc_usb_disconnect,
++};
++
++static void __exit
++hfc_usb_exit(void)
++{
++
++ usb_deregister(&hfc_drv); /* release our driver */
++ printk(KERN_INFO "HFC-USB module removed\n");
++}
++
++static int __init
++hfc_usb_init(void)
++{
++ struct hisax_drvreg drv;
++
++ drv.version = HISAX_LOAD_VERSION; /* set our version */
++ drv.cmd = HISAX_LOAD_CHKVER; /* check command only */
++ if (hisax_register_hfcusb(&drv)) {
++ printk(KERN_INFO "HFC-USB <-> hisax version conflict\n");
++ return (-1); /* unable to register */
++ }
++ if (usb_register(&hfc_drv)) {
++ printk(KERN_INFO
++ "Unable to register HFC-USB module at usb stack\n");
++ return (-1); /* unable to register */
++ }
++
++ printk(KERN_INFO "HFC-USB module loaded\n");
++ return (0);
++}
++
++module_init(hfc_usb_init);
++module_exit(hfc_usb_exit);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_usbr.c linux-2.4.29/drivers/isdn/hisax/hfc_usbr.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_usbr.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_usbr.c 2005-03-22 15:06:46.397039360 +0100
+@@ -0,0 +1,471 @@
++/* $Id: hfc_usbr.c,v 2.5 2001/07/06 21:30:11 werner Exp $
++
++ * hfc_usb.c low level driver for CCD´s hfc-usb single chip controllers
++ * type approval valid for HFC-S USB based TAs
++ *
++ * Author Werner Cornelius (werner@isdn-development.de)
++ *
++ * Copyright 2001 by Werner Cornelius (werner@isdn4linux.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, 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.
++ *
++ */
++
++#define __NO_VERSION__
++#include <linux/init.h>
++#include "hisax.h"
++#include "isdnl1.h"
++#include "hisax_loadable.h"
++
++extern const char *CardType[];
++
++static const char *hfcusb_revision = "$Revision: 2.5 $";
++
++/*********************************/
++/* schedule a new b_channel task */
++/*********************************/
++static void
++hfcusb_sched_event(struct BCState *bcs, int event)
++{
++ bcs->event |= 1 << event;
++ queue_task(&bcs->tqueue, &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++}
++
++/************************************************/
++/* select a b-channel entry matching and active */
++/************************************************/
++static
++struct BCState *
++Sel_BCS(struct IsdnCardState *cs, int channel)
++{
++ if (cs->bcs[0].mode && (cs->bcs[0].channel == channel))
++ return (&cs->bcs[0]);
++ else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel))
++ return (&cs->bcs[1]);
++ else
++ return (NULL);
++}
++
++/**********************************************/
++/* transfer function (D-channel from l2 to l1 */
++/**********************************************/
++static void
++hfcusb_d_l2l1(struct PStack *st, int pr, void *arg)
++{
++ struct IsdnCardState *cs = st->l1.hardware;
++ struct hisax_drvreg *drv = cs->hw.hfcusb.drv;
++
++ if (drv) {
++ switch (pr) {
++ case (PH_DATA | REQUEST):
++ case (PH_PULL | INDICATION):
++ cs->hw.hfcusb.dch_tx_busy = 1;
++ break;
++ case (PH_PULL | REQUEST):
++ if (!cs->hw.hfcusb.dch_tx_busy) {
++ test_and_clear_bit(FLG_L1_PULL_REQ,
++ &st->l1.Flags);
++ st->l1.l1l2(st, PH_PULL | CONFIRM,
++ NULL);
++ } else
++ test_and_set_bit(FLG_L1_PULL_REQ,
++ &st->l1.Flags);
++ return;
++ }
++ drv->dch_l2l1(drv, pr, arg);
++ } else
++ debugl1(cs, "hfcusb l2l1 called without existing driver");
++} /* hfcusb_d_l2l1 */
++
++/*****************************/
++/* E-channel receive routine */
++/*****************************/
++static void
++EChannel_proc_rcv(struct IsdnCardState *cs)
++{
++ u_char *ptr;
++ struct sk_buff *skb;
++ struct hisax_drvreg *usbdrv =
++ (struct hisax_drvreg *) cs->hw.hfcusb.drv;
++
++
++ while ((skb = skb_dequeue(&usbdrv->erq)) != NULL) {
++ if (cs->debug & DEB_DLOG_HEX) {
++ ptr = cs->dlog;
++ if ((skb->len) < MAX_DLOG_SPACE / 3 - 10) {
++ *ptr++ = 'E';
++ *ptr++ = 'C';
++ *ptr++ = 'H';
++ *ptr++ = 'O';
++ *ptr++ = ':';
++ ptr += QuickHex(ptr, skb->data, skb->len);
++ ptr--;
++ *ptr++ = '\n';
++ *ptr = 0;
++ HiSax_putstatus(cs, NULL, cs->dlog);
++ } else
++ HiSax_putstatus(cs, "LogEcho: ",
++ "warning Frame too big (%d)",
++ skb->len);
++ }
++ dev_kfree_skb_any(skb);
++ }
++}
++
++/******************************************/
++/* transfer function called from L1 to L2 */
++/******************************************/
++static void
++hfcusb_d_l1l2(void *cs1, int pr, void *arg)
++{
++ struct IsdnCardState *cs = (struct IsdnCardState *) cs1;
++
++ switch (pr) {
++ case (PH_DATA | INDICATION):
++ if (!((int) arg))
++ DChannel_proc_rcv(cs);
++ else
++ EChannel_proc_rcv(cs);
++ break;
++
++ case (PH_DATA | CONFIRM):
++ cs->hw.hfcusb.dch_tx_busy = 0;
++ DChannel_proc_xmt(cs);
++ break;
++
++ case (PH_ACTIVATE | INDICATION):
++ case (PH_ACTIVATE | CONFIRM):
++ cs->stlist->l1.l1l2(cs->stlist, pr, arg);
++ if (cs->debug & L1_DEB_ISAC)
++ debugl1(cs, "layer 1 activated");
++ break;
++
++ case (PH_DEACTIVATE | INDICATION):
++ case (PH_DEACTIVATE | CONFIRM):
++ cs->stlist->l1.l1l2(cs->stlist, pr, arg);
++ if (cs->debug & L1_DEB_ISAC)
++ debugl1(cs, "layer 1 deactivated");
++ break;
++
++ default:
++ debugl1(cs, "unknown l1 msg 0x%x ", pr);
++ }
++} /* hfcusb_d_l1l2 */
++
++
++/******************************************/
++/* transfer function called from L1 to L2 */
++/******************************************/
++static void
++hfcusb_b_l1l2(void *cs1, int chan, int pr, void *arg)
++{
++ struct IsdnCardState *cs = (struct IsdnCardState *) cs1;
++ struct BCState *bcs = Sel_BCS(cs, chan);
++
++ switch (pr) {
++ case (PH_DATA | INDICATION):
++ if (!bcs)
++ return;
++ hfcusb_sched_event(bcs, B_RCVBUFREADY);
++ break;
++
++ case (PH_DATA | CONFIRM):
++ if (!bcs)
++ return;
++ bcs->tx_cnt -= bcs->tx_skb->len;
++ if (bcs->st->lli.l1writewakeup &&
++ (PACKET_NOACK != bcs->tx_skb->pkt_type))
++ bcs->st->lli.l1writewakeup(bcs->st,
++ bcs->tx_skb->
++ len);
++ dev_kfree_skb_any(bcs->tx_skb);
++ bcs->tx_skb = skb_dequeue(&bcs->squeue);
++ break;
++
++ case (PH_ACTIVATE | INDICATION):
++ case (PH_ACTIVATE | CONFIRM):
++ cs->stlist->l1.l1l2(cs->stlist, pr, arg);
++ if (cs->debug & L1_DEB_ISAC)
++ debugl1(cs, "layer 1 activated");
++ break;
++
++ case (PH_DEACTIVATE | INDICATION):
++ case (PH_DEACTIVATE | CONFIRM):
++ cs->stlist->l1.l1l2(cs->stlist, pr, arg);
++ if (cs->debug & L1_DEB_ISAC)
++ debugl1(cs, "layer 1 deactivated");
++ break;
++
++ default:
++ debugl1(cs, "unknown l1 b msg 0x%x ", pr);
++ }
++} /* hfcusb_b_l1l2 */
++
++
++/***********************************************/
++/* called during init setting l1 stack pointer */
++/***********************************************/
++void
++setstack_hfcusb(struct PStack *st, struct IsdnCardState *cs)
++{
++ st->l2.l2l1 = hfcusb_d_l2l1;
++}
++
++/**************************************/
++/* send B-channel data if not blocked */
++/**************************************/
++static void
++hfcusb_send_data(struct BCState *bcs)
++{
++ struct IsdnCardState *cs = bcs->cs;
++ struct hisax_drvreg *drv =
++ (struct hisax_drvreg *) cs->hw.hfcusb.drv;
++
++ if (!drv)
++ return;
++ drv->bch_l2l1(drv->argl1, bcs->channel, PH_DATA | REQUEST,
++ bcs->tx_skb);
++}
++
++/***************************************************************/
++/* activate/deactivate hardware for selected channels and mode */
++/***************************************************************/
++void
++mode_hfcusb(struct BCState *bcs, int mode, int bc)
++{
++ struct IsdnCardState *cs = bcs->cs;
++ struct hisax_drvreg *drv = cs->hw.hfcusb.drv;
++
++ if (!drv)
++ return;
++ if (cs->debug & L1_DEB_HSCX)
++ debugl1(cs, "HFCUSB bchannel mode %d bchan %d/%d",
++ mode, bc, bcs->channel);
++ bcs->mode = mode;
++ bcs->channel = bc;
++ if (mode) {
++ drv->bsk[bc] = &bcs->tx_skb;
++ drv->brq[bc] = &bcs->rqueue;
++ }
++ drv->bch_l2l1(drv->argl1, bc, PH_ACTIVATE | REQUEST,
++ (void *) mode);
++ if (!mode) {
++ drv->bsk[bc] = NULL;
++ drv->brq[bc] = NULL;
++ }
++}
++
++/******************************/
++/* Layer2 -> Layer 1 Transfer */
++/******************************/
++static void
++hfcusb_b_l2l1(struct PStack *st, int pr, void *arg)
++{
++ struct sk_buff *skb = arg;
++ struct hisax_drvreg *drv = st->l1.bcs->cs->hw.hfcusb.drv;
++ long flags;
++
++ switch (pr) {
++ case (PH_DATA | REQUEST):
++ save_flags(flags);
++ cli();
++ if (st->l1.bcs->tx_skb) {
++ skb_queue_tail(&st->l1.bcs->squeue, skb);
++ restore_flags(flags);
++ } else {
++ st->l1.bcs->tx_skb = skb;
++ st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
++ restore_flags(flags);
++ }
++ break;
++ case (PH_PULL | INDICATION):
++ if (st->l1.bcs->tx_skb) {
++ printk(KERN_WARNING
++ "hfc_l2l1: this shouldn't happen\n");
++ break;
++ }
++ save_flags(flags);
++ cli();
++ st->l1.bcs->tx_skb = skb;
++ st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
++ restore_flags(flags);
++ break;
++ case (PH_PULL | REQUEST):
++ if (!st->l1.bcs->tx_skb) {
++ test_and_clear_bit(FLG_L1_PULL_REQ,
++ &st->l1.Flags);
++ st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
++ } else
++ test_and_set_bit(FLG_L1_PULL_REQ,
++ &st->l1.Flags);
++ break;
++ case (PH_ACTIVATE | REQUEST):
++ if (drv) {
++ test_and_set_bit(BC_FLG_ACTIV,
++ &st->l1.bcs->Flag);
++ mode_hfcusb(st->l1.bcs, st->l1.mode,
++ st->l1.bc);
++ l1_msg_b(st, pr, arg);
++ }
++ break;
++ case (PH_DEACTIVATE | REQUEST):
++ l1_msg_b(st, pr, arg);
++ break;
++ case (PH_DEACTIVATE | CONFIRM):
++ test_and_clear_bit(BC_FLG_ACTIV,
++ &st->l1.bcs->Flag);
++ test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
++ mode_hfcusb(st->l1.bcs, 0, st->l1.bc);
++ st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
++ break;
++ }
++}
++
++/******************************************/
++/* deactivate B-channel access and queues */
++/******************************************/
++static void
++close_hfcusb(struct BCState *bcs)
++{
++ mode_hfcusb(bcs, 0, bcs->channel);
++ if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
++ skb_queue_purge(&bcs->rqueue);
++ skb_queue_purge(&bcs->squeue);
++ if (bcs->tx_skb) {
++ dev_kfree_skb_any(bcs->tx_skb);
++ bcs->tx_skb = NULL;
++ test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
++ }
++ }
++}
++
++/*************************************/
++/* init B-channel queues and control */
++/*************************************/
++static int
++open_hfcusbstate(struct IsdnCardState *cs, struct BCState *bcs)
++{
++ if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
++ skb_queue_head_init(&bcs->rqueue);
++ skb_queue_head_init(&bcs->squeue);
++ }
++ bcs->tx_skb = NULL;
++ test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
++ bcs->event = 0;
++ bcs->tx_cnt = 0;
++ return (0);
++}
++
++/*********************************/
++/* inits the stack for B-channel */
++/*********************************/
++static int
++setstack_2b(struct PStack *st, struct BCState *bcs)
++{
++ bcs->channel = st->l1.bc;
++ if (open_hfcusbstate(st->l1.hardware, bcs))
++ return (-1);
++ st->l1.bcs = bcs;
++ st->l2.l2l1 = hfcusb_b_l2l1;
++ setstack_manager(st);
++ bcs->st = st;
++ setstack_l1_B(st);
++ return (0);
++}
++
++/********************************/
++/* called for card init message */
++/********************************/
++void __devinit
++inithfcusb(struct IsdnCardState *cs)
++{
++ cs->setstack_d = setstack_hfcusb;
++ cs->BC_Send_Data = &hfcusb_send_data;
++ cs->bcs[0].BC_SetStack = setstack_2b;
++ cs->bcs[1].BC_SetStack = setstack_2b;
++ cs->bcs[0].BC_Close = close_hfcusb;
++ cs->bcs[1].BC_Close = close_hfcusb;
++ mode_hfcusb(cs->bcs, 0, 0);
++ mode_hfcusb(cs->bcs + 1, 0, 1);
++}
++
++
++
++/*******************************************/
++/* handle card messages from control layer */
++/*******************************************/
++static int
++hfcusb_card_msg(struct IsdnCardState *cs, int mt, void *arg)
++{
++ if (cs->debug & L1_DEB_ISAC)
++ debugl1(cs, "HFCUSB: card_msg %x", mt);
++ switch (mt) {
++ case CARD_INIT:
++ inithfcusb(cs);
++ return (0);
++ case CARD_RELEASE:
++ case CARD_RESET:
++ case CARD_TEST:
++ return (0);
++ }
++ return (0);
++}
++
++
++extern void
++ HiSax_closecard(int cardnr);
++/*****************************/
++/* release a driver instance */
++/* called when hardware is */
++/* no longer present. */
++/*****************************/
++static void
++release_hfcdrv(void *arg)
++{
++ struct IsdnCardState *cs = (struct IsdnCardState *) arg;
++
++ cs->hw.hfcusb.drv = NULL; /* disable any further use of driver */
++ HiSax_closecard(cs->cardnr);
++} /* release_hfcdrv */
++
++/*********************************************/
++/* called once when a new device is detected */
++/* initialises local data */
++/*********************************************/
++int
++setup_hfc_usb(struct IsdnCard *card)
++{
++ struct IsdnCardState *cs = card->cs;
++ char tmp[64];
++ struct hisax_drvreg *usbdrv =
++ (struct hisax_drvreg *) cs->hw.hfcusb.drv;
++
++ if (!usbdrv)
++ return (0); /* no driver data present */
++
++ strcpy(tmp, hfcusb_revision);
++ printk(KERN_INFO "HiSax: HFC-USB driver Rev. %s\n",
++ HiSax_getrev(tmp));
++
++ usbdrv->release_driver = &release_hfcdrv; /* release routine */
++ usbdrv->arg_hisax = (void *) cs; /* parameter for calling */
++ usbdrv->dch_l1l2 = &hfcusb_d_l1l2; /* access from L1 to HiSax */
++ usbdrv->bch_l1l2 = &hfcusb_b_l1l2;
++ usbdrv->drq = &cs->rq;
++ usbdrv->dsq = &cs->sq;
++ cs->cardmsg = &hfcusb_card_msg;
++ return (1); /* success */
++}
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfcscard.c linux-2.4.29/drivers/isdn/hisax/hfcscard.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hfcscard.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfcscard.c 2005-03-22 15:06:46.412037080 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfcscard.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: hfcscard.c,v 1.10 2001/09/24 13:22:56 kai Exp $
+ *
+ * low level stuff for hfcs based cards (Teles3c, ACER P10)
+ *
+@@ -12,14 +12,13 @@
+
+ #define __NO_VERSION__
+ #include <linux/init.h>
+-#include <linux/isapnp.h>
+ #include "hisax.h"
+ #include "hfc_2bds0.h"
+ #include "isdnl1.h"
+
+ extern const char *CardType[];
+
+-static const char *hfcs_revision = "$Revision: 1.1.4.1 $";
++static const char *hfcs_revision = "$Revision: 1.10 $";
+
+ static void
+ hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+@@ -140,36 +139,6 @@
+ return(0);
+ }
+
+-#ifdef __ISAPNP__
+-static struct isapnp_device_id hfc_ids[] __initdata = {
+- { ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
+- ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
+- (unsigned long) "Acer P10" },
+- { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
+- ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
+- (unsigned long) "Billion 2" },
+- { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
+- ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
+- (unsigned long) "Billion 1" },
+- { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
+- ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
+- (unsigned long) "IStar PnP" },
+- { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
+- ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
+- (unsigned long) "Teles 16.3c" },
+- { ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
+- ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
+- (unsigned long) "Tornado Tipa C" },
+- { ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
+- ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
+- (unsigned long) "Genius Speed Surfer" },
+- { 0, }
+-};
+-
+-static struct isapnp_device_id *hdev = &hfc_ids[0];
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+-
+ int __init
+ setup_hfcs(struct IsdnCard *card)
+ {
+@@ -178,46 +147,6 @@
+
+ strcpy(tmp, hfcs_revision);
+ printk(KERN_INFO "HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp));
+-
+-#ifdef __ISAPNP__
+- if (!card->para[1] && isapnp_present()) {
+- struct pci_bus *pb;
+- struct pci_dev *pd;
+-
+- while(hdev->card_vendor) {
+- if ((pb = isapnp_find_card(hdev->card_vendor,
+- hdev->card_device, pnp_c))) {
+- pnp_c = pb;
+- pd = NULL;
+- if ((pd = isapnp_find_dev(pnp_c,
+- hdev->vendor, hdev->function, pd))) {
+- printk(KERN_INFO "HiSax: %s detected\n",
+- (char *)hdev->driver_data);
+- pd->prepare(pd);
+- pd->deactivate(pd);
+- pd->activate(pd);
+- card->para[1] = pd->resource[0].start;
+- card->para[0] = pd->irq_resource[0].start;
+- if (!card->para[0] || !card->para[1]) {
+- printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
+- card->para[0], card->para[1]);
+- pd->deactivate(pd);
+- return(0);
+- }
+- break;
+- } else {
+- printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
+- }
+- }
+- hdev++;
+- pnp_c=NULL;
+- }
+- if (!hdev->card_vendor) {
+- printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");
+- return(0);
+- }
+- }
+-#endif
+ cs->hw.hfcD.addr = card->para[1] & 0xfffe;
+ cs->irq = card->para[0];
+ cs->hw.hfcD.cip = 0;
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax.h linux-2.4.29/drivers/isdn/hisax/hisax.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax.h 2005-03-22 15:06:46.431034192 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hisax.h,v 1.1.4.2 2001/12/09 19:15:28 kai Exp $
++/* $Id: hisax.h,v 2.64 2001/09/24 13:22:56 kai Exp $
+ *
+ * Basic declarations, defines and prototypes
+ *
+@@ -24,7 +24,9 @@
+ #include <linux/isdnif.h>
+ #include <linux/tty.h>
+ #include <linux/serial_reg.h>
++#ifndef COMPAT_NO_SOFTNET
+ #include <linux/netdevice.h>
++#endif
+
+ #define ERROR_STATISTIC
+
+@@ -68,9 +70,6 @@
+ #define DL_DATA 0x0220
+ #define DL_FLUSH 0x0224
+ #define DL_UNIT_DATA 0x0230
+-
+-#define MDL_BC_RELEASE 0x0278 // Formula-n enter:now
+-#define MDL_BC_ASSIGN 0x027C // Formula-n enter:now
+ #define MDL_ASSIGN 0x0280
+ #define MDL_REMOVE 0x0284
+ #define MDL_ERROR 0x0288
+@@ -472,8 +471,6 @@
+ #define BC_FLG_FTI_RUN 13
+ #define BC_FLG_LL_OK 14
+ #define BC_FLG_LL_CONN 15
+-#define BC_FLG_FTI_FTS 16
+-#define BC_FLG_FRH_WAIT 17
+
+ #define L1_MODE_NULL 0
+ #define L1_MODE_TRANS 1
+@@ -695,6 +692,13 @@
+ struct timer_list timer;
+ };
+
++#ifdef CONFIG_HISAX_HFC_USB
++struct hfcUSB_hw {
++ void *drv; /* pointer to driver structure */
++ int dch_tx_busy;
++};
++#endif
++
+ struct hfcSX_hw {
+ unsigned long base;
+ unsigned char cirm;
+@@ -838,17 +842,6 @@
+ int ph_state;
+ };
+
+-struct amd7930_chip {
+- u_char lmr1;
+- u_char ph_state;
+- u_char old_state;
+- u_char flg_t3;
+- unsigned int tx_xmtlen;
+- struct timer_list timer3;
+- void (*ph_command) (struct IsdnCardState *, u_char, char *);
+- void (*setIrqMask) (struct IsdnCardState *, u_char);
+-};
+-
+ struct icc_chip {
+ int ph_state;
+ u_char *mon_tx;
+@@ -902,6 +895,9 @@
+ struct njet_hw njet;
+ struct hfcD_hw hfcD;
+ struct hfcPCI_hw hfcpci;
++#ifdef CONFIG_HISAX_HFC_USB
++ struct hfcUSB_hw hfcusb;
++#endif
+ struct hfcSX_hw hfcsx;
+ struct ix1_hw niccy;
+ struct isurf_hw isurf;
+@@ -945,7 +941,6 @@
+ struct hfcpci_chip hfcpci;
+ struct hfcsx_chip hfcsx;
+ struct w6692_chip w6692;
+- struct amd7930_chip amd7930;
+ struct icc_chip icc;
+ } dc;
+ u_char *rcvbuf;
+@@ -967,6 +962,8 @@
+ #define MON0_TX 4
+ #define MON1_TX 8
+
++#define HISAX_MAX_CARDS 8
++
+ #define ISDN_CTYPE_16_0 1
+ #define ISDN_CTYPE_8_0 2
+ #define ISDN_CTYPE_16_3 3
+@@ -1006,8 +1003,8 @@
+ #define ISDN_CTYPE_HFC_SX 37
+ #define ISDN_CTYPE_NETJET_U 38
+ #define ISDN_CTYPE_HFC_SP_PCMCIA 39
+-#define ISDN_CTYPE_DYNAMIC 40
+-#define ISDN_CTYPE_ENTERNOW 41
++#define ISDN_CTYPE_HFC_USB 40
++#define ISDN_CTYPE_DYNAMIC 41
+ #define ISDN_CTYPE_COUNT 41
+
+
+@@ -1267,10 +1264,6 @@
+ #define CARD_NETJET_U 0
+ #endif
+
+-#ifdef CONFIG_HISAX_ENTERNOW_PCI
+-#define CARD_FN_ENTERNOW_PCI 1
+-#endif
+-
+ #define TEI_PER_CARD 1
+
+ /* L1 Debug */
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax_debug.h linux-2.4.29/drivers/isdn/hisax/hisax_debug.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax_debug.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax_debug.h 2005-03-22 15:06:46.452031000 +0100
+@@ -28,7 +28,7 @@
+
+ #define DBG(level, format, arg...) do { \
+ if (level & __debug_variable) \
+-printk(KERN_DEBUG "%s: " format "\n" , __FUNCTION__ , ## arg); \
++printk(KERN_DEBUG __FUNCTION__ ": " format "\n" , ## arg); \
+ } while (0)
+
+ #define DBG_PACKET(level,data,count) \
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax_fcpcipnp.c linux-2.4.29/drivers/isdn/hisax/hisax_fcpcipnp.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax_fcpcipnp.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax_fcpcipnp.c 2005-03-22 15:06:46.468028568 +0100
+@@ -20,22 +20,19 @@
+ *
+ * o POWER PC
+ * o clean up debugging
+- * o tx_skb at PH_DEACTIVATE time
+ */
+
+ #include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/pci.h>
+-#include <linux/isapnp.h>
++#include "hisax_isapnp.h"
+ #include <linux/kmod.h>
+ #include <linux/slab.h>
+ #include <linux/skbuff.h>
+ #include <linux/netdevice.h>
+-
+-#include <asm/io.h>
+-
+ #include "hisax_fcpcipnp.h"
++#include "hisax_isac.h"
+
+ // debugging cruft
+ #define __debug_variable debug
+@@ -46,10 +43,14 @@
+ MODULE_PARM(debug, "i");
+ #endif
+
+-MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
++MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>");
+ MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver");
+
+-static struct pci_device_id fcpci_ids[] __devinitdata = {
++#ifndef PCI_DEVICE_ID_AVM_A1_V2
++#define PCI_DEVICE_ID_AVM_A1_V2 0x0e00
++#endif
++
++static struct pci_device_id fcpci_ids[] __initdata = {
+ { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1 , PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0, (unsigned long) "Fritz!Card PCI" },
+ { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1_V2, PCI_ANY_ID, PCI_ANY_ID,
+@@ -58,7 +59,7 @@
+ };
+ MODULE_DEVICE_TABLE(pci, fcpci_ids);
+
+-static struct isapnp_device_id fcpnp_ids[] __devinitdata = {
++static struct isapnp_device_id fcpnp_ids[] __initdata = {
+ { ISAPNP_VENDOR('A', 'V', 'M'), ISAPNP_FUNCTION(0x0900),
+ ISAPNP_VENDOR('A', 'V', 'M'), ISAPNP_FUNCTION(0x0900),
+ (unsigned long) "Fritz!Card PnP" },
+@@ -68,7 +69,8 @@
+
+ static int protocol = 2; /* EURO-ISDN Default */
+ MODULE_PARM(protocol, "i");
+-MODULE_LICENSE("GPL");
++
++static LIST_HEAD(adapter_list);
+
+ // ----------------------------------------------------------------------
+
+@@ -147,7 +149,7 @@
+ outb(idx, adapter->io + AVM_INDEX);
+ val = inb(adapter->io + AVM_DATA + (offset & 0xf));
+ spin_unlock_irqrestore(&adapter->hw_lock, flags);
+- DBG(0x1000, " port %#x, value %#x",
++ DBG(0x1000, __FUNCTION__ " port %#x, value %#x",
+ offset, val);
+ return val;
+ }
+@@ -160,7 +162,7 @@
+ AVM_IDX_ISAC_REG_HIGH : AVM_IDX_ISAC_REG_LOW;
+ unsigned long flags;
+
+- DBG(0x1000, " port %#x, value %#x",
++ DBG(0x1000, __FUNCTION__ " port %#x, value %#x",
+ offset, value);
+ spin_lock_irqsave(&adapter->hw_lock, flags);
+ outb(idx, adapter->io + AVM_INDEX);
+@@ -240,7 +242,7 @@
+ outl(offset, adapter->io + AVM_ISACSX_INDEX);
+ val = inl(adapter->io + AVM_ISACSX_DATA);
+ spin_unlock_irqrestore(&adapter->hw_lock, flags);
+- DBG(0x1000, " port %#x, value %#x",
++ DBG(0x1000, __FUNCTION__ " port %#x, value %#x",
+ offset, val);
+
+ return val;
+@@ -252,7 +254,7 @@
+ struct fritz_adapter *adapter = isac->priv;
+ unsigned long flags;
+
+- DBG(0x1000, " port %#x, value %#x",
++ DBG(0x1000, __FUNCTION__ " port %#x, value %#x",
+ offset, value);
+ spin_lock_irqsave(&adapter->hw_lock, flags);
+ outl(offset, adapter->io + AVM_ISACSX_INDEX);
+@@ -375,6 +377,9 @@
+
+ DBG(0x40, "hdlc_fill_fifo");
+
++ if (!skb)
++ BUG();
++
+ if (skb->len == 0)
+ BUG();
+
+@@ -515,7 +520,6 @@
+ }
+ skb_push(bcs->tx_skb, bcs->tx_cnt);
+ bcs->tx_cnt = 0;
+- hdlc_fill_fifo(bcs);
+ }
+
+ static inline void hdlc_xpr_irq(struct fritz_bcs *bcs)
+@@ -536,7 +540,7 @@
+ dev_kfree_skb_irq(skb);
+ }
+
+-static void hdlc_irq_one(struct fritz_bcs *bcs, u32 stat)
++static void hdlc_irq(struct fritz_bcs *bcs, u32 stat)
+ {
+ DBG(0x10, "ch%d stat %#x", bcs->channel, stat);
+ if (stat & HDLC_INT_RPR) {
+@@ -553,7 +557,7 @@
+ }
+ }
+
+-static inline void hdlc_irq(struct fritz_adapter *adapter)
++static inline void hdlc_interrupt(struct fritz_adapter *adapter)
+ {
+ int nr;
+ u32 stat;
+@@ -562,7 +566,7 @@
+ stat = adapter->read_hdlc_status(adapter, nr);
+ DBG(0x10, "HDLC %c stat %#x", 'A' + nr, stat);
+ if (stat & HDLC_INT_MASK)
+- hdlc_irq_one(&adapter->bcs[nr], stat);
++ hdlc_irq(&adapter->bcs[nr], stat);
+ }
+ }
+
+@@ -584,14 +588,14 @@
+ adapter->write_ctrl(bcs, 5);
+ break;
+ case L1_MODE_TRANS:
++ bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
++ adapter->write_ctrl(bcs, 5);
++ bcs->ctrl.sr.cmd = HDLC_CMD_XRS;
++ adapter->write_ctrl(bcs, 1);
++ bcs->ctrl.sr.cmd = 0;
++ break;
+ case L1_MODE_HDLC:
+- bcs->rcvidx = 0;
+- bcs->tx_cnt = 0;
+- bcs->tx_skb = NULL;
+- if (mode == L1_MODE_TRANS)
+- bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
+- else
+- bcs->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
++ bcs->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
+ adapter->write_ctrl(bcs, 5);
+ bcs->ctrl.sr.cmd = HDLC_CMD_XRS;
+ adapter->write_ctrl(bcs, 1);
+@@ -645,10 +649,10 @@
+ return;
+ DBG(2, "STATUS0 %#x", val);
+ if (val & AVM_STATUS0_IRQ_ISAC)
+- isacsx_irq(&adapter->isac);
++ isacsx_interrupt(&adapter->isac);
+
+ if (val & AVM_STATUS0_IRQ_HDLC)
+- hdlc_irq(adapter);
++ hdlc_interrupt(adapter);
+ }
+
+ static void fcpci_irq(int intno, void *dev, struct pt_regs *regs)
+@@ -662,10 +666,10 @@
+ return;
+ DBG(2, "sval %#x", sval);
+ if (!(sval & AVM_STATUS0_IRQ_ISAC))
+- isac_irq(&adapter->isac);
++ isac_interrupt(&adapter->isac);
+
+ if (!(sval & AVM_STATUS0_IRQ_HDLC))
+- hdlc_irq(adapter);
++ hdlc_interrupt(adapter);
+ }
+
+ // ----------------------------------------------------------------------
+@@ -681,11 +685,6 @@
+ {
+ outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER |
+ AVM_STATUS0_ENA_IRQ, adapter->io + AVM_STATUS0);
+-
+- outb(AVM_STATUS1_ENA_IOM | adapter->irq,
+- adapter->io + AVM_STATUS1);
+- set_current_state(TASK_UNINTERRUPTIBLE);
+- schedule_timeout(50*HZ / 1000); /* Timeout 50ms */
+ }
+
+ // ----------------------------------------------------------------------
+@@ -693,6 +692,7 @@
+ static int __devinit fcpcipnp_setup(struct fritz_adapter *adapter)
+ {
+ u32 val = 0;
++ struct pci_dev *pdev = adapter->pci_dev;
+ int retval;
+
+ DBG(1,"");
+@@ -700,21 +700,21 @@
+ isac_init(&adapter->isac); // FIXME is this okay now
+
+ retval = -EBUSY;
+- if (!request_region(adapter->io, 32, "fcpcipnp"))
++ if (!request_region(adapter->io, 32, "hisax_fcpcipnp"))
+ goto err;
+
+ switch (adapter->type) {
+ case AVM_FRITZ_PCIV2:
+- retval = request_irq(adapter->irq, fcpci2_irq, SA_SHIRQ,
+- "fcpcipnp", adapter);
++ retval = request_irq(pdev->irq, fcpci2_irq, SA_SHIRQ,
++ "hisax_fcpcipnp", adapter);
+ break;
+ case AVM_FRITZ_PCI:
+- retval = request_irq(adapter->irq, fcpci_irq, SA_SHIRQ,
+- "fcpcipnp", adapter);
++ retval = request_irq(pdev->irq, fcpci_irq, SA_SHIRQ,
++ "hisax_fcpcipnp", adapter);
+ break;
+ case AVM_FRITZ_PNP:
+- retval = request_irq(adapter->irq, fcpci_irq, 0,
+- "fcpcipnp", adapter);
++ retval = request_irq(pdev->irq, fcpci_irq, 0,
++ "hisax_fcpcipnp", adapter);
+ break;
+ }
+ if (retval)
+@@ -808,11 +808,23 @@
+
+ static void __devexit fcpcipnp_release(struct fritz_adapter *adapter)
+ {
++ struct pci_dev *pdev = adapter->pci_dev;
++
+ DBG(1,"");
+
+ outb(0, adapter->io + AVM_STATUS0);
+- free_irq(adapter->irq, adapter);
++ free_irq(pdev->irq, adapter);
+ release_region(adapter->io, 32);
++
++ switch (adapter->type) {
++ case AVM_FRITZ_PCI:
++ case AVM_FRITZ_PCIV2:
++ pci_disable_device(pdev);
++ break;
++ case AVM_FRITZ_PNP:
++ pdev->deactivate(pdev);
++ break;
++ }
+ }
+
+ // ----------------------------------------------------------------------
+@@ -830,6 +842,8 @@
+
+ memset(adapter, 0, sizeof(struct fritz_adapter));
+
++ adapter->pci_dev = pdev;
++
+ SET_MODULE_OWNER(&adapter->isac.hisax_d_if);
+ adapter->isac.hisax_d_if.ifc.priv = &adapter->isac;
+ adapter->isac.hisax_d_if.ifc.l2l1 = isac_d_l2l1;
+@@ -840,6 +854,7 @@
+ adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i];
+ adapter->bcs[i].b_if.ifc.l2l1 = fritz_b_l2l1;
+ }
++ list_add(&adapter->list, &adapter_list);
+
+ pci_set_drvdata(pdev, adapter);
+
+@@ -854,6 +869,7 @@
+ static void delete_adapter(struct fritz_adapter *adapter)
+ {
+ hisax_unregister(&adapter->isac.hisax_d_if);
++ list_del(&adapter->list);
+ kfree(adapter);
+ }
+
+@@ -863,12 +879,15 @@
+ struct fritz_adapter *adapter;
+ int retval;
+
++ printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at %s\n",
++ (char *) ent->driver_data, pdev->slot_name);
++
+ retval = -ENOMEM;
+ adapter = new_adapter(pdev);
+ if (!adapter)
+ goto err;
+
+- if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2)
++ if (pdev->device == 0x0e00)
+ adapter->type = AVM_FRITZ_PCIV2;
+ else
+ adapter->type = AVM_FRITZ_PCI;
+@@ -876,12 +895,7 @@
+ retval = pci_enable_device(pdev);
+ if (retval)
+ goto err_free;
+-
+ adapter->io = pci_resource_start(pdev, 1);
+- adapter->irq = pdev->irq;
+-
+- printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at %s\n",
+- (char *) ent->driver_data, pdev->slot_name);
+
+ retval = fcpcipnp_setup(adapter);
+ if (retval)
+@@ -901,6 +915,9 @@
+ struct fritz_adapter *adapter;
+ int retval;
+
++ printk(KERN_INFO "hisax_fcpcipnp: found adapter %s\n",
++ (char *) ent->driver_data);
++
+ retval = -ENOMEM;
+ adapter = new_adapter(pdev);
+ if (!adapter)
+@@ -912,11 +929,8 @@
+ pdev->deactivate(pdev); // why?
+ pdev->activate(pdev);
+ adapter->io = pdev->resource[0].start;
+- adapter->irq = pdev->irq_resource[0].start;
+-
+- printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at IO %#x irq %d\n",
+- (char *) ent->driver_data, adapter->io, adapter->irq);
+-
++ pdev->irq = pdev->irq_resource[0].start;
++
+ retval = fcpcipnp_setup(adapter);
+ if (retval)
+ goto err_free;
+@@ -929,43 +943,35 @@
+ return retval;
+ }
+
+-static void __devexit fcpci_remove(struct pci_dev *pdev)
+-{
+- struct fritz_adapter *adapter = pci_get_drvdata(pdev);
+-
+- fcpcipnp_release(adapter);
+- pci_disable_device(pdev);
+- delete_adapter(adapter);
+-}
+-
+-static void __devexit fcpnp_remove(struct pci_dev *pdev)
++static void __devexit fcpcipnp_remove(struct pci_dev *pdev)
+ {
+ struct fritz_adapter *adapter = pci_get_drvdata(pdev);
+
+ fcpcipnp_release(adapter);
+- pdev->deactivate(pdev);
+ delete_adapter(adapter);
+ }
+
+ static struct pci_driver fcpci_driver = {
+- name: "fcpci",
+- probe: fcpci_probe,
+- remove: __devexit_p(fcpci_remove),
++ name: "fcpci",
++ probe: fcpci_probe,
++ remove: fcpcipnp_remove,
+ id_table: fcpci_ids,
+ };
+
+ static struct isapnp_driver fcpnp_driver = {
+- name: "fcpnp",
+- probe: fcpnp_probe,
+- remove: __devexit_p(fcpnp_remove),
++ name: "fcpnp",
++ probe: fcpnp_probe,
++ remove: fcpcipnp_remove,
+ id_table: fcpnp_ids,
+ };
+
+-static int __init hisax_fcpcipnp_init(void)
++static LIST_HEAD(isapnp_drivers);
++
++static int __init hisax_fcpci_init(void)
+ {
+ int retval, pci_nr_found;
+
+- printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n");
++ printk(KERN_INFO "hisax_fcpcipnp: Fritz!PCI/PnP ISDN driver v0.0.1\n");
+
+ retval = pci_register_driver(&fcpci_driver);
+ if (retval < 0)
+@@ -976,15 +982,14 @@
+ if (retval < 0)
+ goto out_unregister_pci;
+
+-#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
++#if !defined(CONFIG_HOTPLUG) && defined(MODULE)
+ if (pci_nr_found + retval == 0) {
+ retval = -ENODEV;
+ goto out_unregister_isapnp;
+- }
+ #endif
+ return 0;
+
+-#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
++#if !defined(CONFIG_HOTPLUG) && defined(MODULE)
+ out_unregister_isapnp:
+ isapnp_unregister_driver(&fcpnp_driver);
+ #endif
+@@ -994,11 +999,15 @@
+ return retval;
+ }
+
+-static void __exit hisax_fcpcipnp_exit(void)
++static void __exit hisax_fcpci_exit(void)
+ {
+ isapnp_unregister_driver(&fcpnp_driver);
+ pci_unregister_driver(&fcpci_driver);
+ }
+
+-module_init(hisax_fcpcipnp_init);
+-module_exit(hisax_fcpcipnp_exit);
++module_init(hisax_fcpci_init);
++module_exit(hisax_fcpci_exit);
++
++#ifdef __ISAPNP__
++#include "hisax_isapnp.c"
++#endif
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax_fcpcipnp.h linux-2.4.29/drivers/isdn/hisax/hisax_fcpcipnp.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax_fcpcipnp.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax_fcpcipnp.h 2005-03-22 15:06:46.484026136 +0100
+@@ -43,10 +43,12 @@
+ };
+
+ struct fritz_adapter {
++ struct list_head list;
++ struct pci_dev *pci_dev;
++
+ int type;
+ spinlock_t hw_lock;
+ unsigned int io;
+- unsigned int irq;
+ struct isac isac;
+
+ struct fritz_bcs bcs[2];
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax_isac.c linux-2.4.29/drivers/isdn/hisax/hisax_isac.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax_isac.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax_isac.c 2005-03-22 15:06:46.543017168 +0100
+@@ -34,7 +34,7 @@
+ static int debug = 1;
+ MODULE_PARM(debug, "i");
+
+-static char *ISACVer[] = {
++static char *ISACVer[] __devinitdata = {
+ "2086/2186 V1.1",
+ "2085 B1",
+ "2085 B2",
+@@ -42,10 +42,6 @@
+ };
+ #endif
+
+-MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
+-MODULE_DESCRIPTION("ISAC/ISAC-SX driver");
+-MODULE_LICENSE("GPL");
+-
+ #define DBG_WARN 0x0001
+ #define DBG_IRQ 0x0002
+ #define DBG_L1M 0x0004
+@@ -438,7 +434,7 @@
+ va_end(args);
+ }
+
+-static void isac_version(struct isac *cs)
++static void __devinit isac_version(struct isac *cs)
+ {
+ int val;
+
+@@ -602,7 +598,7 @@
+ }
+ }
+
+-void isac_irq(struct isac *isac)
++void isac_interrupt(struct isac *isac)
+ {
+ unsigned char val;
+
+@@ -635,8 +631,6 @@
+ if (val & ISAC_ISTA_SIN) {
+ DBG(DBG_WARN, "SIN");
+ }
+- isac->write_isac(isac, ISAC_MASK, 0xff);
+- isac->write_isac(isac, ISAC_MASK, 0x00);
+ }
+
+ // ======================================================================
+@@ -742,7 +736,7 @@
+ }
+ }
+
+-void isacsx_irq(struct isac *isac)
++void isacsx_interrupt(struct isac *isac)
+ {
+ unsigned char val;
+
+@@ -755,7 +749,7 @@
+ isacsx_cic_interrupt(isac);
+ }
+
+-void isac_init(struct isac *isac)
++void __devinit isac_init(struct isac *isac)
+ {
+ isac->tx_skb = NULL;
+ isac->l1m.fsm = &l1fsm;
+@@ -770,7 +764,7 @@
+ FsmInitTimer(&isac->l1m, &isac->timer);
+ }
+
+-void isac_setup(struct isac *isac)
++void __devinit isac_setup(struct isac *isac)
+ {
+ int val, eval;
+
+@@ -781,7 +775,7 @@
+
+ isac->write_isac(isac, ISAC_MASK, 0xff);
+ isac->mocr = 0xaa;
+- if (test_bit(ISAC_IOM1, &isac->flags)) {
++ if (test_bit(HW_IOM1, &isac->flags)) {
+ /* IOM 1 Mode */
+ isac->write_isac(isac, ISAC_ADF2, 0x0);
+ isac->write_isac(isac, ISAC_SPCR, 0xa);
+@@ -817,7 +811,7 @@
+ FsmEvent(&isac->l1m, (val >> 2) & 0xf, NULL);
+
+ isac->write_isac(isac, ISAC_MASK, 0x0);
+- // RESET Receiver and Transmitter
++ /* RESET Receiver and Transmitter */
+ isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_XRES | ISAC_CMDR_RRES);
+ }
+
+@@ -888,10 +882,10 @@
+ EXPORT_SYMBOL(isac_d_l2l1);
+
+ EXPORT_SYMBOL(isacsx_setup);
+-EXPORT_SYMBOL(isacsx_irq);
++EXPORT_SYMBOL(isacsx_interrupt);
+
+ EXPORT_SYMBOL(isac_setup);
+-EXPORT_SYMBOL(isac_irq);
++EXPORT_SYMBOL(isac_interrupt);
+
+ module_init(hisax_isac_init);
+ module_exit(hisax_isac_exit);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax_isac.h linux-2.4.29/drivers/isdn/hisax/hisax_isac.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax_isac.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax_isac.h 2005-03-22 15:06:46.559014736 +0100
+@@ -8,7 +8,7 @@
+ #define TIMER3_VALUE 7000
+ #define MAX_DFRAME_LEN_L1 300
+
+-#define ISAC_IOM1 0
++#define HW_IOM1 0
+
+ struct isac {
+ void *priv;
+@@ -37,9 +37,9 @@
+ void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg);
+
+ void isac_setup(struct isac *isac);
+-void isac_irq(struct isac *isac);
++void isac_interrupt(struct isac *isac);
+
+ void isacsx_setup(struct isac *isac);
+-void isacsx_irq(struct isac *isac);
++void isacsx_interrupt(struct isac *isac);
+
+ #endif
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax_isapnp.c linux-2.4.29/drivers/isdn/hisax/hisax_isapnp.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax_isapnp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax_isapnp.c 2005-03-22 15:06:46.576012152 +0100
+@@ -0,0 +1,105 @@
++// FIXME copied
++static const struct isapnp_device_id *
++isapnp_match_device(const struct isapnp_device_id *ids, struct pci_dev *dev)
++{
++ DBG(1,"");
++
++ while (ids->card_vendor || ids->card_device) {
++ if ((ids->card_vendor == ISAPNP_ANY_ID || ids->card_vendor == dev->bus->vendor) &&
++ (ids->card_device == ISAPNP_ANY_ID || ids->card_device == dev->bus->device) &&
++ (ids->vendor == ISAPNP_ANY_ID || ids->vendor == dev->vendor) &&
++ (ids->function == ISAPNP_ANY_ID || ids->function == dev->device))
++ return ids;
++ ids++;
++ }
++ return NULL;
++}
++
++/**
++ * pci_dev_driver - get the pci_driver of a device
++ * @dev: the device to query
++ *
++ * Returns the appropriate pci_driver structure or %NULL if there is no
++ * registered driver for the device.
++ */
++struct pci_driver *isapnp_dev_driver(const struct pci_dev *dev)
++{
++ return dev->driver;
++}
++
++static int isapnp_announce_device(struct isapnp_driver *drv, struct pci_dev *dev)
++{
++ const struct isapnp_device_id *id;
++ int ret = 0;
++
++ DBG(1,"");
++
++ if (drv->id_table) {
++ id = isapnp_match_device(drv->id_table, dev);
++ if (!id) {
++ ret = 0;
++ goto out;
++ }
++ } else
++ id = NULL;
++
++// dev_probe_lock();
++ if (drv->probe(dev, id) >= 0) {
++ dev->driver = (struct pci_driver *) drv;
++ ret = 1;
++ }
++// dev_probe_unlock();
++out:
++ return ret;
++}
++
++/**
++ * FIXME pci_register_driver - register a new pci driver
++ * @drv: the driver structure to register
++ *
++ * Adds the driver structure to the list of registered drivers
++ * Returns the number of pci devices which were claimed by the driver
++ * during registration. The driver remains registered even if the
++ * return value is zero.
++ */
++int isapnp_register_driver(struct isapnp_driver *drv)
++{
++ struct pci_dev *dev;
++ int count = 0;
++
++ DBG(1,"");
++
++ list_add_tail(&drv->node, &isapnp_drivers);
++ isapnp_for_each_dev(dev) {
++ if (!isapnp_dev_driver(dev))
++ count += isapnp_announce_device(drv, dev);
++ }
++ return count;
++}
++
++/**
++ * pci_unregister_driver - unregister a pci driver
++ * @drv: the driver structure to unregister
++ *
++ * Deletes the driver structure from the list of registered PCI drivers,
++ * gives it a chance to clean up by calling its remove() function for
++ * each device it was responsible for, and marks those devices as
++ * driverless.
++ */
++
++void isapnp_unregister_driver(struct isapnp_driver *drv)
++{
++ struct pci_dev *dev;
++
++ DBG(1,"");
++
++ list_del(&drv->node);
++ isapnp_for_each_dev(dev) {
++ if (dev->driver == (struct pci_driver *) drv) {
++ if (drv->remove)
++ drv->remove(dev);
++ dev->driver = NULL;
++ }
++ }
++}
++
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax_isapnp.h linux-2.4.29/drivers/isdn/hisax/hisax_isapnp.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax_isapnp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax_isapnp.h 2005-03-22 15:06:46.590010024 +0100
+@@ -0,0 +1,33 @@
++#ifndef __HISAX_ISAPNP_H__
++#define __HISAX_ISAPNP_H__
++
++#include <linux/isapnp.h>
++
++#ifdef COMPAT_NEED_ISAPNP_DRIVER
++struct isapnp_driver {
++ struct list_head node;
++ char *name;
++ const struct isapnp_device_id *id_table; /* NULL if wants all devices */
++ int (*probe) (struct pci_dev *dev, const struct isapnp_device_id *id); /* New device inserted */
++ void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */
++};
++#endif
++#ifdef __ISAPNP__
++
++int isapnp_register_driver(struct isapnp_driver *drv);
++void isapnp_unregister_driver(struct isapnp_driver *drv);
++
++#else
++
++static inline int isapnp_register_driver(struct isapnp_driver *drv)
++{
++ return 0;
++}
++
++static inline void isapnp_unregister_driver(struct isapnp_driver *drv)
++{
++}
++
++#endif
++
++#endif
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax_loadable.h linux-2.4.29/drivers/isdn/hisax/hisax_loadable.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax_loadable.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax_loadable.h 2005-03-22 15:06:46.606007592 +0100
+@@ -0,0 +1,74 @@
++/* $Id: hisax_loadable.h,v 2.1 2001/06/08 22:19:16 werner Exp $
++ *
++ *
++ * Author (C) 2001 Werner Cornelius (werner@isdn-development.de)
++ * modular driver for Colognechip HFC-USB chip
++ * as plugin for HiSax isdn driver
++ *
++ * Copyright 2001 by Werner Cornelius (werner@isdn4linux.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, 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 <linux/types.h>
++#include <linux/skbuff.h>
++
++/***************************************/
++/* additional defines for l1 constants */
++/***************************************/
++#define B1_DATA 0x1f0
++#define B1_SETMODE 0x1f4
++#define B2_DATA 0x1f8
++#define B2_SETMODE 0x1fc
++
++
++/********************************************************/
++/* structure used for register and release of L1 driver */
++/********************************************************/
++struct hisax_drvreg {
++ int version; /* actual version for check */
++ int cmd; /* command code */
++
++ /* function pointers set by hisax during register call */
++ void (*release_driver) (void *arg_hisax); /* set by hisax, release function for driver */
++ void (*dch_l1l2) (void *arg_hisax, int pr, void *arg); /* set by hisax, notify dch+l1 events */
++ void (*bch_l1l2) (void *arg_hisax, int chan, int pr, void *arg); /* set by hisax, notify bch events */
++ void *arg_hisax; /* argument when calling hisax main */
++ struct sk_buff_head *drq; /* pointer to D-receive queue */
++ struct sk_buff_head *dsq; /* pointer to D-send queue */
++ struct sk_buff_head erq; /* E-receive queue */
++ struct sk_buff_head *brq[2]; /* pointer to B-receive queues */
++ struct sk_buff **bsk[2]; /* pointer to B-transmit buffer */
++
++ /* function pointers set by l1 driver before calling the register function */
++ void (*dch_l2l1) (void *argl1, int pr, void *arg); /* function dch+l1 from hisax -> l1 */
++ void (*bch_l2l1) (void *argl1, int chan, int pr, void *arg); /* function bch from hisax -> l1 */
++ void *argl1; /* pointer to l1 data structure when calling l1 */
++
++ char *drvname; /* driver name for hisax usage */
++};
++
++/**************************/
++/* constants and commands */
++/**************************/
++#define HISAX_LOAD_VERSION 4 /* change when interface changes */
++#define HISAX_LOAD_CHKVER 0 /* check version command (returns 0 on success) */
++#define HISAX_LOAD_REGISTER 1 /* register the L1 driver and return 0 on success */
++
++/***************************************/
++/* definition of the register function */
++/***************************************/
++extern int hisax_register_hfcusb(struct hisax_drvreg *l1drv);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hscx.c linux-2.4.29/drivers/isdn/hisax/hscx.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hscx.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hscx.c 2005-03-22 15:06:46.621005312 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hscx.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: hscx.c,v 1.24 2001/09/24 13:22:56 kai Exp $
+ *
+ * HSCX specific routines
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hscx.h linux-2.4.29/drivers/isdn/hisax/hscx.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hscx.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hscx.h 2005-03-22 15:06:46.640002424 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hscx.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: hscx.h,v 1.8 2001/09/24 13:22:56 kai Exp $
+ *
+ * HSCX specific defines
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hscx_irq.c linux-2.4.29/drivers/isdn/hisax/hscx_irq.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hscx_irq.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hscx_irq.c 2005-03-22 15:06:46.655999992 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hscx_irq.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: hscx_irq.c,v 1.18 2001/09/24 13:22:56 kai Exp $
+ *
+ * low level b-channel stuff for Siemens HSCX
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/icc.c linux-2.4.29/drivers/isdn/hisax/icc.c
+--- linux-2.4.29.old/drivers/isdn/hisax/icc.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/icc.c 2005-03-22 15:06:46.672997408 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: icc.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: icc.c,v 1.8 2001/09/24 13:22:56 kai Exp $
+ *
+ * ICC specific routines
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/icc.h linux-2.4.29/drivers/isdn/hisax/icc.h
+--- linux-2.4.29.old/drivers/isdn/hisax/icc.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/icc.h 2005-03-22 15:06:46.687995128 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: icc.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: icc.h,v 1.4 2001/09/24 13:22:56 kai Exp $
+ *
+ * ICC specific routines
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/ipac.h linux-2.4.29/drivers/isdn/hisax/ipac.h
+--- linux-2.4.29.old/drivers/isdn/hisax/ipac.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/ipac.h 2005-03-22 15:06:46.702992848 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: ipac.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: ipac.h,v 1.7 2001/09/24 13:22:56 kai Exp $
+ *
+ * IPAC specific defines
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isac.c linux-2.4.29/drivers/isdn/hisax/isac.c
+--- linux-2.4.29.old/drivers/isdn/hisax/isac.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isac.c 2005-03-22 15:06:46.844971264 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isac.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isac.c,v 1.31 2001/09/24 13:22:56 kai Exp $
+ *
+ * ISAC specific routines
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isac.h linux-2.4.29/drivers/isdn/hisax/isac.h
+--- linux-2.4.29.old/drivers/isdn/hisax/isac.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isac.h 2005-03-22 15:06:47.111930680 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isac.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isac.h,v 1.9 2001/09/24 13:22:56 kai Exp $
+ *
+ * ISAC specific defines
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isar.c linux-2.4.29/drivers/isdn/hisax/isar.c
+--- linux-2.4.29.old/drivers/isdn/hisax/isar.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isar.c 2005-03-22 15:06:47.302901648 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isar.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isar.c,v 1.22 2001/09/23 12:00:05 keil Exp $
+ *
+ * isar.c ISAR (Siemens PSB 7110) specific routines
+ *
+@@ -21,12 +21,10 @@
+ #define DLE 0x10
+ #define ETX 0x03
+
+-#define FAXMODCNT 13
+-const u_char faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146};
+-static u_int modmask = 0x1fff;
+-static int frm_extra_delay = 2;
+-static int para_TOA = 6;
+-const u_char *FC1_CMD[] = {"FAE", "FTS", "FRS", "FTM", "FRM", "FTH", "FRH", "CTRL" };
++
++const u_char faxmodulation_s[] = "3,24,48,72,73,74,96,97,98,121,122,145,146";
++const u_char faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146};
++#define FAXMODCNT 13
+
+ void isar_setup(struct IsdnCardState *cs);
+ static void isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para);
+@@ -127,7 +125,7 @@
+ ireg->clsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_L);
+ #if DUMP_MBOXFRAME
+ if (cs->debug & L1_DEB_HSCX)
+- debugl1(cs, "irq_stat(%02x,%02x,%d)", ireg->iis, ireg->cmsb,
++ debugl1(cs, "rcv_mbox(%02x,%02x,%d)", ireg->iis, ireg->cmsb,
+ ireg->clsb);
+ #endif
+ }
+@@ -414,7 +412,6 @@
+ }
+ cs->debug = debug;
+ isar_setup(cs);
+-
+ ret = 0;
+ reterrflg:
+ restore_flags(flags);
+@@ -428,21 +425,6 @@
+ return(ret);
+ }
+
+-static inline void
+-ll_deliver_faxstat(struct BCState *bcs, u_char status)
+-{
+- isdn_ctrl ic;
+- struct Channel *chanp = (struct Channel *) bcs->st->lli.userdata;
+-
+- if (bcs->cs->debug & L1_DEB_HSCX)
+- debugl1(bcs->cs, "HL->LL FAXIND %x", status);
+- ic.driver = bcs->cs->myid;
+- ic.command = ISDN_STAT_FAXIND;
+- ic.arg = chanp->chan;
+- ic.parm.aux.cmd = status;
+- bcs->cs->iif.statcallb(&ic);
+-}
+-
+ extern void BChannel_bh(struct BCState *);
+ #define B_LL_NOCARRIER 8
+ #define B_LL_CONNECT 9
+@@ -599,6 +581,7 @@
+ if (ireg->cmsb & SART_NMD) { /* ABORT */
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "isar_rcv_frame: no more data");
++ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ bcs->hw.isar.rcvidx = 0;
+ send_DLE_ETX(bcs);
+ sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) |
+@@ -609,6 +592,7 @@
+ }
+ } else {
+ printk(KERN_WARNING "HiSax: skb out of memory\n");
++ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ }
+ break;
+ }
+@@ -633,9 +617,8 @@
+ bcs->hw.isar.rcvidx = 0;
+ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ } else {
+- if (ireg->cmsb & HDLC_FSD) {
++ if (ireg->cmsb & HDLC_FSD)
+ bcs->hw.isar.rcvidx = 0;
+- }
+ ptr = bcs->hw.isar.rcvbuf + bcs->hw.isar.rcvidx;
+ bcs->hw.isar.rcvidx += ireg->clsb;
+ rcv_mbox(cs, ireg, ptr);
+@@ -646,8 +629,6 @@
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "isar frame to short %d",
+ bcs->hw.isar.rcvidx);
+- printk(KERN_WARNING "ISAR: frame to short %d\n",
+- bcs->hw.isar.rcvidx);
+ } else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx))) {
+ printk(KERN_WARNING "ISAR: receive out of memory\n");
+ } else {
+@@ -658,7 +639,6 @@
+ isar_sched_event(bcs, B_RCVBUFREADY);
+ send_DLE_ETX(bcs);
+ isar_sched_event(bcs, B_LL_OK);
+- test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
+ }
+ bcs->hw.isar.rcvidx = 0;
+ }
+@@ -666,14 +646,13 @@
+ if (ireg->cmsb & SART_NMD) { /* ABORT */
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "isar_rcv_frame: no more data");
++ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ bcs->hw.isar.rcvidx = 0;
++ send_DLE_ETX(bcs);
+ sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) |
+ ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL);
+ bcs->hw.isar.state = STFAX_ESCAPE;
+- if (test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag)) {
+- send_DLE_ETX(bcs);
+- isar_sched_event(bcs, B_LL_NOCARRIER);
+- }
++ isar_sched_event(bcs, B_LL_NOCARRIER);
+ }
+ break;
+ default:
+@@ -977,6 +956,21 @@
+ }
+ }
+
++static inline void
++ll_deliver_faxstat(struct BCState *bcs, u_char status)
++{
++ isdn_ctrl ic;
++ struct Channel *chanp = (struct Channel *) bcs->st->lli.userdata;
++
++ if (bcs->cs->debug & L1_DEB_HSCX)
++ debugl1(bcs->cs, "HL->LL FAXIND %x", status);
++ ic.driver = bcs->cs->myid;
++ ic.command = ISDN_STAT_FAXIND;
++ ic.arg = chanp->chan;
++ ic.parm.aux.cmd = status;
++ bcs->cs->iif.statcallb(&ic);
++}
++
+ static void
+ isar_pump_statev_fax(struct BCState *bcs, u_char devt) {
+ struct IsdnCardState *cs = bcs->cs;
+@@ -1081,22 +1075,19 @@
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "pump stev RSP_DISC");
+ if (bcs->hw.isar.state == STFAX_ESCAPE) {
+- p1 = 5;
+ switch(bcs->hw.isar.newcmd) {
+ case 0:
+ bcs->hw.isar.state = STFAX_READY;
+ break;
+- case PCTRL_CMD_FTM:
+- p1 = 2;
+ case PCTRL_CMD_FTH:
++ case PCTRL_CMD_FTM:
++ p1 = 10;
+ sendmsg(cs, dps | ISAR_HIS_PUMPCTRL,
+ PCTRL_CMD_SILON, 1, &p1);
+ bcs->hw.isar.state = STFAX_SILDET;
+ break;
+- case PCTRL_CMD_FRM:
+- if (frm_extra_delay)
+- mdelay(frm_extra_delay);
+ case PCTRL_CMD_FRH:
++ case PCTRL_CMD_FRM:
+ p1 = bcs->hw.isar.mod = bcs->hw.isar.newmod;
+ bcs->hw.isar.newmod = 0;
+ bcs->hw.isar.cmd = bcs->hw.isar.newcmd;
+@@ -1215,9 +1206,6 @@
+ isar_pump_statev_modem(bcs, ireg->cmsb);
+ } else if (bcs->mode == L1_MODE_FAX) {
+ isar_pump_statev_fax(bcs, ireg->cmsb);
+- } else if (ireg->cmsb == PSEV_10MS_TIMER) {
+- if (cs->debug & L1_DEB_HSCX)
+- debugl1(cs, "pump stev TIMER");
+ } else {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "isar IIS_PSTEV pmode %d stat %x",
+@@ -1278,9 +1266,6 @@
+ if (test_and_clear_bit(BC_FLG_LL_CONN, &bcs->Flag)) {
+ isar_sched_event(bcs, B_LL_CONNECT);
+ }
+- if (test_and_clear_bit(BC_FLG_FTI_FTS, &bcs->Flag)) {
+- isar_sched_event(bcs, B_LL_OK);
+- }
+ }
+
+ static void
+@@ -1303,7 +1288,7 @@
+ } else {
+ param[5] = PV32P6_ATN;
+ }
+- param[0] = para_TOA; /* 6 db */
++ param[0] = 6; /* 6 db */
+ param[1] = PV32P2_V23R | PV32P2_V22A | PV32P2_V22B |
+ PV32P2_V22C | PV32P2_V21 | PV32P2_BEL;
+ param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B;
+@@ -1319,7 +1304,7 @@
+ } else {
+ param[1] = PFAXP2_ATN;
+ }
+- param[0] = para_TOA; /* 6 db */
++ param[0] = 6; /* 6 db */
+ sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param);
+ bcs->hw.isar.state = STFAX_NULL;
+ bcs->hw.isar.newcmd = 0;
+@@ -1348,6 +1333,7 @@
+ "\0\0");
+ break;
+ case L1_MODE_HDLC:
++ case L1_MODE_FAX:
+ param[0] = 0;
+ sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1,
+ param);
+@@ -1359,9 +1345,6 @@
+ sendmsg(cs, dps | ISAR_HIS_SARTCFG, ctrl, 2,
+ param);
+ break;
+- case L1_MODE_FAX:
+- /* SART must not configured with FAX */
+- break;
+ }
+ udelay(1000);
+ sendmsg(cs, dps | ISAR_HIS_BSTREQ, 0, 0, NULL);
+@@ -1465,7 +1448,6 @@
+
+ switch(cmd) {
+ case ISDN_FAX_CLASS1_FTM:
+- test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
+ if (bcs->hw.isar.state == STFAX_READY) {
+ p1 = para;
+ ctrl = PCTRL_CMD_FTM;
+@@ -1489,7 +1471,6 @@
+ }
+ break;
+ case ISDN_FAX_CLASS1_FTH:
+- test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
+ if (bcs->hw.isar.state == STFAX_READY) {
+ p1 = para;
+ ctrl = PCTRL_CMD_FTH;
+@@ -1513,7 +1494,6 @@
+ }
+ break;
+ case ISDN_FAX_CLASS1_FRM:
+- test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
+ if (bcs->hw.isar.state == STFAX_READY) {
+ p1 = para;
+ ctrl = PCTRL_CMD_FRM;
+@@ -1537,7 +1517,6 @@
+ }
+ break;
+ case ISDN_FAX_CLASS1_FRH:
+- test_and_set_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
+ if (bcs->hw.isar.state == STFAX_READY) {
+ p1 = para;
+ ctrl = PCTRL_CMD_FRH;
+@@ -1560,11 +1539,6 @@
+ bcs->hw.isar.state = STFAX_ESCAPE;
+ }
+ break;
+- case ISDN_FAXPUMP_HALT:
+- bcs->hw.isar.state = STFAX_NULL;
+- nom = 0;
+- ctrl = PCTRL_CMD_HALT;
+- break;
+ }
+ if (ctrl)
+ sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1);
+@@ -1658,15 +1632,6 @@
+ l1_msg_b(st, pr, arg);
+ break;
+ case (PH_DEACTIVATE | CONFIRM):
+- switch(st->l1.mode) {
+- case L1_MODE_TRANS:
+- case L1_MODE_HDLC:
+- case L1_MODE_V32:
+- break;
+- case L1_MODE_FAX:
+- isar_pump_cmd(st->l1.bcs, ISDN_FAXPUMP_HALT, 0);
+- break;
+- }
+ test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+ test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ if (st->l1.bcs->cs->debug & L1_DEB_HSCX)
+@@ -1758,51 +1723,6 @@
+ test_and_set_bit(BC_FLG_DLEETX,
+ &bcs->Flag);
+ break;
+- case ISDN_FAX_CLASS1_FTS:
+- if (ic->parm.aux.subcmd == AT_QUERY) {
+- ic->command = ISDN_STAT_FAXIND;
+- ic->parm.aux.cmd = ISDN_FAX_CLASS1_OK;
+- cs->iif.statcallb(ic);
+- return(0);
+- } else if (ic->parm.aux.subcmd == AT_EQ_QUERY) {
+- strcpy(ic->parm.aux.para, "0-255");
+- ic->command = ISDN_STAT_FAXIND;
+- ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY;
+- cs->iif.statcallb(ic);
+- return(0);
+- } else if (ic->parm.aux.subcmd == AT_EQ_VALUE) {
+- if (cs->debug & L1_DEB_HSCX)
+- debugl1(cs, "isar_auxcmd %s=%d",
+- FC1_CMD[ic->parm.aux.cmd], ic->parm.aux.para[0]);
+- if (bcs->hw.isar.state == STFAX_READY) {
+- if (! ic->parm.aux.para[0]) {
+- ic->command = ISDN_STAT_FAXIND;
+- ic->parm.aux.cmd = ISDN_FAX_CLASS1_OK;
+- cs->iif.statcallb(ic);
+- return(0);
+- }
+- if (! test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag)) {
+- /* n*10 ms */
+- bcs->hw.isar.ftimer.expires =
+- jiffies + ((ic->parm.aux.para[0] * 10 * HZ)/1000);
+- test_and_set_bit(BC_FLG_FTI_FTS, &bcs->Flag);
+- add_timer(&bcs->hw.isar.ftimer);
+- return(0);
+- } else {
+- if (cs->debug)
+- debugl1(cs, "isar FTS=%d and FTI busy",
+- ic->parm.aux.para[0]);
+- }
+- } else {
+- if (cs->debug)
+- debugl1(cs, "isar FTS=%d and isar.state not ready(%x)",
+- ic->parm.aux.para[0],bcs->hw.isar.state);
+- }
+- ic->command = ISDN_STAT_FAXIND;
+- ic->parm.aux.cmd = ISDN_FAX_CLASS1_ERROR;
+- cs->iif.statcallb(ic);
+- }
+- break;
+ case ISDN_FAX_CLASS1_FRM:
+ case ISDN_FAX_CLASS1_FRH:
+ case ISDN_FAX_CLASS1_FTM:
+@@ -1815,24 +1735,16 @@
+ cs->iif.statcallb(ic);
+ return(0);
+ } else if (ic->parm.aux.subcmd == AT_EQ_QUERY) {
+- char *p = ic->parm.aux.para;
+- for(i=0;i<FAXMODCNT;i++)
+- if ((1<<i) & modmask)
+- p += sprintf(p, "%d,", faxmodulation[i]);
+- p--;
+- *p=0;
++ strcpy(ic->parm.aux.para, faxmodulation_s);
+ ic->command = ISDN_STAT_FAXIND;
+ ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY;
+ cs->iif.statcallb(ic);
+ return(0);
+ } else if (ic->parm.aux.subcmd == AT_EQ_VALUE) {
+- if (cs->debug & L1_DEB_HSCX)
+- debugl1(cs, "isar_auxcmd %s=%d",
+- FC1_CMD[ic->parm.aux.cmd], ic->parm.aux.para[0]);
+ for(i=0;i<FAXMODCNT;i++)
+ if (faxmodulation[i]==ic->parm.aux.para[0])
+ break;
+- if ((i < FAXMODCNT) && ((1<<i) & modmask) &&
++ if ((FAXMODCNT > i) &&
+ test_bit(BC_FLG_INIT, &bcs->Flag)) {
+ isar_pump_cmd(bcs,
+ ic->parm.aux.cmd,
+@@ -1850,7 +1762,7 @@
+ break;
+ case (ISDN_CMD_IOCTL):
+ switch (ic->arg) {
+- case 9: /* load firmware */
++ case (9): /* load firmware */
+ features = ISDN_FEATURE_L2_MODEM |
+ ISDN_FEATURE_L2_FAX |
+ ISDN_FEATURE_L3_FCLASS1;
+@@ -1860,26 +1772,6 @@
+ else
+ ll_run(cs, features);
+ break;
+- case 20:
+- features = *(unsigned int *) ic->parm.num;
+- printk(KERN_DEBUG "HiSax: max modulation old(%04x) new(%04x)\n",
+- modmask, features);
+- modmask = features;
+- break;
+- case 21:
+- features = *(unsigned int *) ic->parm.num;
+- printk(KERN_DEBUG "HiSax: FRM extra delay old(%d) new(%d) ms\n",
+- frm_extra_delay, features);
+- if (features >= 0)
+- frm_extra_delay = features;
+- break;
+- case 22:
+- features = *(unsigned int *) ic->parm.num;
+- printk(KERN_DEBUG "HiSax: TOA old(%d) new(%d) db\n",
+- para_TOA, features);
+- if (features >= 0 && features < 32)
+- para_TOA = features;
+- break;
+ default:
+ printk(KERN_DEBUG "HiSax: invalid ioctl %d\n",
+ (int) ic->arg);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isar.h linux-2.4.29/drivers/isdn/hisax/isar.h
+--- linux-2.4.29.old/drivers/isdn/hisax/isar.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isar.h 2005-03-22 15:06:47.457878088 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isar.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isar.h,v 1.11 2001/09/24 13:22:56 kai Exp $
+ *
+ * ISAR (Siemens PSB 7110) specific defines
+ *
+@@ -28,8 +28,6 @@
+ #define ISAR_HIS_FIRM 0x1e
+ #define ISAR_HIS_STDSP 0x08
+ #define ISAR_HIS_DIAG 0x05
+-#define ISAR_HIS_WAITSTATE 0x27
+-#define ISAR_HIS_TIMERIRQ 0x25
+ #define ISAR_HIS_P0CFG 0x3c
+ #define ISAR_HIS_P12CFG 0x24
+ #define ISAR_HIS_SARTCFG 0x25
+@@ -45,10 +43,6 @@
+ #define ISAR_HIS_DPS2 0x80
+ #define SET_DPS(x) ((x<<6) & 0xc0)
+
+-#define ISAR_CMD_TIMERIRQ_OFF 0x20
+-#define ISAR_CMD_TIMERIRQ_ON 0x21
+-
+-
+ #define ISAR_IIS_MSCMSD 0x3f
+ #define ISAR_IIS_VNR 0x15
+ #define ISAR_IIS_DKEY 0x03
+@@ -213,8 +207,6 @@
+ #define STFAX_ESCAPE 5
+ #define STFAX_SILDET 6
+
+-#define ISDN_FAXPUMP_HALT 100
+-
+ extern int ISARVersion(struct IsdnCardState *cs, char *s);
+ extern void isar_int_main(struct IsdnCardState *cs);
+ extern void initisar(struct IsdnCardState *cs);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isdnl1.c linux-2.4.29/drivers/isdn/hisax/isdnl1.c
+--- linux-2.4.29.old/drivers/isdn/hisax/isdnl1.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isdnl1.c 2005-03-22 15:06:47.582859088 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnl1.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isdnl1.c,v 2.46 2001/09/24 13:22:56 kai Exp $
+ *
+ * common low level stuff for Siemens Chipsetbased isdn cards
+ *
+@@ -18,7 +18,7 @@
+ *
+ */
+
+-const char *l1_revision = "$Revision: 1.1.4.1 $";
++const char *l1_revision = "$Revision: 2.46 $";
+
+ #define __NO_VERSION__
+ #include <linux/init.h>
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isdnl1.h linux-2.4.29/drivers/isdn/hisax/isdnl1.h
+--- linux-2.4.29.old/drivers/isdn/hisax/isdnl1.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isdnl1.h 2005-03-22 15:06:47.615854072 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnl1.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isdnl1.h,v 2.12 2001/09/24 13:22:56 kai Exp $
+ *
+ * Layer 1 defines
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isdnl2.c linux-2.4.29/drivers/isdn/hisax/isdnl2.c
+--- linux-2.4.29.old/drivers/isdn/hisax/isdnl2.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isdnl2.c 2005-03-22 15:06:47.631851640 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnl2.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isdnl2.c,v 2.30 2001/09/24 13:22:56 kai Exp $
+ *
+ * Author Karsten Keil
+ * based on the teles driver from Jan den Ouden
+@@ -20,7 +20,7 @@
+ #include "hisax.h"
+ #include "isdnl2.h"
+
+-const char *l2_revision = "$Revision: 1.1.4.1 $";
++const char *l2_revision = "$Revision: 2.30 $";
+
+ static void l2m_debug(struct FsmInst *fi, char *fmt, ...);
+
+@@ -1418,8 +1418,8 @@
+ freewin(st);
+ st->l2.tei = -1;
+ stop_t200(st, 17);
+- st5_dl_release_l2l3(st);
+ FsmChangeState(fi, ST_L2_1);
++ st5_dl_release_l2l3(st);
+ }
+
+ static void
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isdnl2.h linux-2.4.29/drivers/isdn/hisax/isdnl2.h
+--- linux-2.4.29.old/drivers/isdn/hisax/isdnl2.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isdnl2.h 2005-03-22 15:06:47.647849208 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnl2.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id$
+ *
+ * Layer 2 defines
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isdnl3.c linux-2.4.29/drivers/isdn/hisax/isdnl3.c
+--- linux-2.4.29.old/drivers/isdn/hisax/isdnl3.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isdnl3.c 2005-03-22 15:06:47.663846776 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnl3.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isdnl3.c,v 2.22 2001/09/24 13:22:56 kai Exp $
+ *
+ * Author Karsten Keil
+ * based on the teles driver from Jan den Ouden
+@@ -21,7 +21,7 @@
+ #include "isdnl3.h"
+ #include <linux/config.h>
+
+-const char *l3_revision = "$Revision: 1.1.4.1 $";
++const char *l3_revision = "$Revision: 2.22 $";
+
+ static struct Fsm l3fsm;
+
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isdnl3.h linux-2.4.29/drivers/isdn/hisax/isdnl3.h
+--- linux-2.4.29.old/drivers/isdn/hisax/isdnl3.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isdnl3.h 2005-03-22 15:06:47.679844344 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnl3.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id$
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isurf.c linux-2.4.29/drivers/isdn/hisax/isurf.c
+--- linux-2.4.29.old/drivers/isdn/hisax/isurf.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isurf.c 2005-03-22 15:06:47.699841304 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isurf.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isurf.c,v 1.12 2001/09/24 13:22:56 kai Exp $
+ *
+ * low level stuff for Siemens I-Surf/I-Talk cards
+ *
+@@ -16,11 +16,10 @@
+ #include "isac.h"
+ #include "isar.h"
+ #include "isdnl1.h"
+-#include <linux/isapnp.h>
+
+ extern const char *CardType[];
+
+-static const char *ISurf_revision = "$Revision: 1.1.4.1 $";
++static const char *ISurf_revision = "$Revision: 1.12 $";
+
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+@@ -128,8 +127,10 @@
+ release_io_isurf(struct IsdnCardState *cs)
+ {
+ release_region(cs->hw.isurf.reset, 1);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ iounmap((unsigned char *)cs->hw.isurf.isar);
+ release_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE);
++#endif
+ }
+
+ static void
+@@ -194,10 +195,6 @@
+ return(isar_auxcmd(cs, ic));
+ }
+
+-#ifdef __ISAPNP__
+-static struct pci_bus *pnp_surf __devinitdata = NULL;
+-#endif
+-
+ int __init
+ setup_isurf(struct IsdnCard *card)
+ {
+@@ -215,58 +212,9 @@
+ cs->hw.isurf.phymem = card->para[2];
+ cs->irq = card->para[0];
+ } else {
+-#ifdef __ISAPNP__
+- struct pci_bus *pb;
+- struct pci_dev *pd;
+-
+- if (isapnp_present()) {
+- cs->subtyp = 0;
+- if ((pb = isapnp_find_card(
+- ISAPNP_VENDOR('S', 'I', 'E'),
+- ISAPNP_FUNCTION(0x0010), pnp_surf))) {
+- pnp_surf = pb;
+- pd = NULL;
+- if (!(pd = isapnp_find_dev(pnp_surf,
+- ISAPNP_VENDOR('S', 'I', 'E'),
+- ISAPNP_FUNCTION(0x0010), pd))) {
+- printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n");
+- return (0);
+- }
+- pd->prepare(pd);
+- pd->deactivate(pd);
+- pd->activate(pd);
+- /* The ISA-PnP logic apparently
+- * expects upper limit address to be
+- * set. Since the isa-pnp module
+- * doesn't do this, so we have to make
+- * up for it.
+- */
+- isapnp_cfg_begin(pd->bus->number, pd->devfn);
+- isapnp_write_word(ISAPNP_CFG_MEM+3,
+- pd->resource[8].end >> 8);
+- isapnp_cfg_end();
+- cs->hw.isurf.reset = pd->resource[0].start;
+- cs->hw.isurf.phymem = pd->resource[8].start;
+- cs->irq = pd->irq_resource[0].start;
+- if (!cs->irq || !cs->hw.isurf.reset || !cs->hw.isurf.phymem) {
+- printk(KERN_ERR "ISurfPnP:some resources are missing %d/%x/%lx\n",
+- cs->irq, cs->hw.isurf.reset, cs->hw.isurf.phymem);
+- pd->deactivate(pd);
+- return(0);
+- }
+- } else {
+- printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n");
+- return(0);
+- }
+- } else {
+- printk(KERN_INFO "ISurfPnP: no ISAPnP bus found\n");
+- return(0);
+- }
+-#else
+ printk(KERN_WARNING "HiSax: %s port/mem not set\n",
+ CardType[card->typ]);
+ return (0);
+-#endif
+ }
+ if (check_region(cs->hw.isurf.reset, 1)) {
+ printk(KERN_WARNING
+@@ -277,6 +225,7 @@
+ } else {
+ request_region(cs->hw.isurf.reset, 1, "isurf isdn");
+ }
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ if (check_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE)) {
+ printk(KERN_WARNING
+ "HiSax: %s memory region %lx-%lx already in use\n",
+@@ -292,6 +241,10 @@
+ cs->hw.isurf.isar =
+ (unsigned long) ioremap(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE);
+ cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET;
++#else
++ cs->hw.isurf.isar = cs->hw.isurf.phymem + ISURF_ISAR_OFFSET;
++ cs->hw.isurf.isac = cs->hw.isurf.phymem + ISURF_ISAC_OFFSET;
++#endif
+ printk(KERN_INFO
+ "ISurf: defined at 0x%x 0x%lx IRQ %d\n",
+ cs->hw.isurf.reset,
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/ix1_micro.c linux-2.4.29/drivers/isdn/hisax/ix1_micro.c
+--- linux-2.4.29.old/drivers/isdn/hisax/ix1_micro.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/ix1_micro.c 2005-03-22 15:06:47.714839024 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: ix1_micro.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: ix1_micro.c,v 2.12 2001/09/24 13:22:56 kai Exp $
+ *
+ * low level stuff for ITK ix1-micro Rev.2 isdn cards
+ * derived from the original file teles3.c from Karsten Keil
+@@ -19,14 +19,13 @@
+
+ #define __NO_VERSION__
+ #include <linux/init.h>
+-#include <linux/isapnp.h>
+ #include "hisax.h"
+ #include "isac.h"
+ #include "hscx.h"
+ #include "isdnl1.h"
+
+ extern const char *CardType[];
+-const char *ix1_revision = "$Revision: 1.1.4.1 $";
++const char *ix1_revision = "$Revision: 2.12 $";
+
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+@@ -219,21 +218,6 @@
+ return(0);
+ }
+
+-#ifdef __ISAPNP__
+-static struct isapnp_device_id itk_ids[] __initdata = {
+- { ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25),
+- ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25),
+- (unsigned long) "ITK micro 2" },
+- { ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x29),
+- ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x29),
+- (unsigned long) "ITK micro 2." },
+- { 0, }
+-};
+-
+-static struct isapnp_device_id *idev = &itk_ids[0];
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+-
+
+ int __init
+ setup_ix1micro(struct IsdnCard *card)
+@@ -246,45 +230,6 @@
+ if (cs->typ != ISDN_CTYPE_IX1MICROR2)
+ return (0);
+
+-#ifdef __ISAPNP__
+- if (!card->para[1] && isapnp_present()) {
+- struct pci_bus *pb;
+- struct pci_dev *pd;
+-
+- while(idev->card_vendor) {
+- if ((pb = isapnp_find_card(idev->card_vendor,
+- idev->card_device, pnp_c))) {
+- pnp_c = pb;
+- pd = NULL;
+- if ((pd = isapnp_find_dev(pnp_c,
+- idev->vendor, idev->function, pd))) {
+- printk(KERN_INFO "HiSax: %s detected\n",
+- (char *)idev->driver_data);
+- pd->prepare(pd);
+- pd->deactivate(pd);
+- pd->activate(pd);
+- card->para[1] = pd->resource[0].start;
+- card->para[0] = pd->irq_resource[0].start;
+- if (!card->para[0] || !card->para[1]) {
+- printk(KERN_ERR "ITK PnP:some resources are missing %ld/%lx\n",
+- card->para[0], card->para[1]);
+- pd->deactivate(pd);
+- return(0);
+- }
+- break;
+- } else {
+- printk(KERN_ERR "ITK PnP: PnP error card found, no device\n");
+- }
+- }
+- idev++;
+- pnp_c=NULL;
+- }
+- if (!idev->card_vendor) {
+- printk(KERN_INFO "ITK PnP: no ISAPnP card found\n");
+- return(0);
+- }
+- }
+-#endif
+ /* IO-Ports */
+ cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET;
+ cs->hw.ix1.hscx_ale = card->para[1] + HSCX_COMMAND_OFFSET;
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/jade.c linux-2.4.29/drivers/isdn/hisax/jade.c
+--- linux-2.4.29.old/drivers/isdn/hisax/jade.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/jade.c 2005-03-22 15:06:47.729836744 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: jade.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: jade.c,v 1.9 2001/09/24 13:22:56 kai Exp $
+ *
+ * JADE stuff (derived from original hscx.c)
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/jade.h linux-2.4.29/drivers/isdn/hisax/jade.h
+--- linux-2.4.29.old/drivers/isdn/hisax/jade.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/jade.h 2005-03-22 15:06:47.745834312 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: jade.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: jade.h,v 1.5 2001/09/24 13:22:56 kai Exp $
+ *
+ * JADE specific defines
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/jade_irq.c linux-2.4.29/drivers/isdn/hisax/jade_irq.c
+--- linux-2.4.29.old/drivers/isdn/hisax/jade_irq.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/jade_irq.c 2005-03-22 15:06:47.760832032 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: jade_irq.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: jade_irq.c,v 1.7 2001/09/24 13:22:56 kai Exp $
+ *
+ * Low level JADE IRQ stuff (derived from original hscx_irq.c)
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/l3_1tr6.c linux-2.4.29/drivers/isdn/hisax/l3_1tr6.c
+--- linux-2.4.29.old/drivers/isdn/hisax/l3_1tr6.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/l3_1tr6.c 2005-03-22 15:06:47.777829448 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: l3_1tr6.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: l3_1tr6.c,v 2.15 2001/09/24 13:22:56 kai Exp $
+ *
+ * German 1TR6 D-channel protocol
+ *
+@@ -20,7 +20,7 @@
+ #include <linux/ctype.h>
+
+ extern char *HiSax_getrev(const char *revision);
+-const char *l3_1tr6_revision = "$Revision: 1.1.4.1 $";
++const char *l3_1tr6_revision = "$Revision: 2.15 $";
+
+ #define MsgHead(ptr, cref, mty, dis) \
+ *ptr++ = dis; \
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/l3_1tr6.h linux-2.4.29/drivers/isdn/hisax/l3_1tr6.h
+--- linux-2.4.29.old/drivers/isdn/hisax/l3_1tr6.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/l3_1tr6.h 2005-03-22 15:06:47.796826560 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: l3_1tr6.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id$
+ *
+ * German 1TR6 D-channel protocol defines
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/l3dss1.c linux-2.4.29/drivers/isdn/hisax/l3dss1.c
+--- linux-2.4.29.old/drivers/isdn/hisax/l3dss1.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/l3dss1.c 2005-03-22 15:06:47.822822608 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: l3dss1.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: l3dss1.c,v 2.32 2001/09/24 13:22:56 kai Exp $
+ *
+ * EURO/DSS1 D-channel protocol
+ *
+@@ -27,7 +27,7 @@
+ #include <linux/config.h>
+
+ extern char *HiSax_getrev(const char *revision);
+-const char *dss1_revision = "$Revision: 1.1.4.1 $";
++const char *dss1_revision = "$Revision: 2.32 $";
+
+ #define EXT_BEARER_CAPS 1
+
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/l3dss1.h linux-2.4.29/drivers/isdn/hisax/l3dss1.h
+--- linux-2.4.29.old/drivers/isdn/hisax/l3dss1.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/l3dss1.h 2005-03-22 15:06:47.842819568 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: l3dss1.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id$
+ *
+ * DSS1 (Euro) D-channel protocol defines
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/l3ni1.c linux-2.4.29/drivers/isdn/hisax/l3ni1.c
+--- linux-2.4.29.old/drivers/isdn/hisax/l3ni1.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/l3ni1.c 2005-03-22 15:06:47.859816984 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: l3ni1.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: l3ni1.c,v 2.8 2001/09/24 13:22:56 kai Exp $
+ *
+ * NI1 D-channel protocol
+ *
+@@ -25,7 +25,7 @@
+ #include <linux/ctype.h>
+
+ extern char *HiSax_getrev(const char *revision);
+-const char *ni1_revision = "$Revision: 1.1.4.1 $";
++const char *ni1_revision = "$Revision: 2.8 $";
+
+ #define EXT_BEARER_CAPS 1
+
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/l3ni1.h linux-2.4.29/drivers/isdn/hisax/l3ni1.h
+--- linux-2.4.29.old/drivers/isdn/hisax/l3ni1.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/l3ni1.h 2005-03-22 15:06:47.877814248 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: l3ni1.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id$
+ *
+ * NI1 D-channel protocol
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/lmgr.c linux-2.4.29/drivers/isdn/hisax/lmgr.c
+--- linux-2.4.29.old/drivers/isdn/hisax/lmgr.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/lmgr.c 2005-03-22 15:06:47.895811512 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: lmgr.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id$
+ *
+ * Layermanagement module
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/md5sums.asc linux-2.4.29/drivers/isdn/hisax/md5sums.asc
+--- linux-2.4.29.old/drivers/isdn/hisax/md5sums.asc 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/md5sums.asc 2005-03-22 15:06:47.910809232 +0100
+@@ -1,33 +1,22 @@
+------BEGIN PGP SIGNED MESSAGE-----
+-Hash: SHA1
+-
+ # This are valid md5sums for certificated HiSax driver.
+ # The certification is valid only if the md5sums of all files match.
+ # The certification is valid only for ELSA Microlink PCI,
+-# Eicon Technology Diva 2.01 PCI, Sedlbauer SpeedFax+,
+-# HFC-S PCI A based cards and HFC-S USB based ISDN
+-# terminal adapters in the moment.
++# Eicon Technology Diva 2.01 PCI, Sedlbauer SpeedFax+,
++# HFC-S PCI A based cards and HFC-S USB based isdn tas
++# in the moment.
+ # Read ../../../Documentation/isdn/HiSax.cert for more informations.
+ #
+-cd4a9917e1147039d5dfc66440d42054 isac.c
+-211840e78b56c9d4753be9c85da21a50 isdnl1.c
+-5ce9b1fff42a02f9c2eb4fb81c701b1f isdnl2.c
+-6948de0c43513dd23c6706feb5fc2209 isdnl3.c
+-3730780b69368218d756024165efea79 tei.c
+-16e72710eb58da01415b877490f5d2ac callc.c
+-6abc55c77e0f3149ae9334f3257a1a1a cert.c
+-27bdb2800d4590e00da20eff241edc47 l3dss1.c
+-df8bb877b854c4302d396b554e4e84ef l3_1tr6.c
+-9d8b4bed15370063d1b16e47080f50e1 elsa.c
+-210f4a3f1eebca70229d786b15cf3e90 diva.c
+-4ddf21079dd77e892380f789bae250a7 sedlbauer.c
+-8200d818771e3cbdef2a3c3e818d25ac hfc_pci.c
++6f9433a8b696076562562d090e3c420f isac.c
++13c3eed869f5139f44c563e3a8fea1f5 isdnl1.c
++addcff863b0ff1e366c0f2ae9fa6e81e isdnl2.c
++7076deb94a363945c21ea27aca4a720a isdnl3.c
++51c603829b6cc4f8421f744ad657ceff tei.c
++669050ab5079f02887ed0239d86e5474 callc.c
++ecacd146b8f8881ef9349935dab3df4a cert.c
++fadeb3b85bb23bc1ac48470c0848d6fa l3dss1.c
++cf7dec9fac6283716904d26b99188476 l3_1tr6.c
++2f75c8765e1be13d114d5f4433cf364b elsa.c
++b4cf8a4dceed9ea6dcba65a85b4eecc7 diva.c
++dee3f8f40c6fe78a4b57729804b7e6cd sedlbauer.c
++0d79fe6dfc5bfaa4826970c41a6d273d hfc_pci.c
+ # end of md5sums
+------BEGIN PGP SIGNATURE-----
+-Version: GnuPG v1.0.6 (GNU/Linux)
+-Comment: For info see http://www.gnupg.org
+-
+-iD8DBQE9rE91DiY0VZsg4ukRAkKfAJ4xWUfqjc0hW+V+JPue5yr7mrt+RwCdGdSf
+-GIKgAEdRLzERmpt/bCCwAbY=
+-=FaHw
+------END PGP SIGNATURE-----
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/mic.c linux-2.4.29/drivers/isdn/hisax/mic.c
+--- linux-2.4.29.old/drivers/isdn/hisax/mic.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/mic.c 2005-03-22 15:06:47.926806800 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: mic.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: mic.c,v 1.12 2001/09/24 13:22:56 kai Exp $
+ *
+ * low level stuff for mic cards
+ *
+@@ -19,7 +19,7 @@
+
+ extern const char *CardType[];
+
+-const char *mic_revision = "$Revision: 1.1.4.1 $";
++const char *mic_revision = "$Revision: 1.12 $";
+
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/netjet.c linux-2.4.29/drivers/isdn/hisax/netjet.c
+--- linux-2.4.29.old/drivers/isdn/hisax/netjet.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/netjet.c 2005-03-22 15:06:47.941804520 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: netjet.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: netjet.c,v 1.29 2001/09/24 13:22:56 kai Exp $
+ *
+ * low level stuff for Traverse Technologie NETJet ISDN cards
+ *
+@@ -8,9 +8,7 @@
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+- * Thanks to Traverse Technologies Australia for documents and information
+- *
+- * 16-Apr-2002 - led code added - Guy Ellis (guy@traverse.com.au)
++ * Thanks to Traverse Technologie Australia for documents and information
+ *
+ */
+
+@@ -26,7 +24,7 @@
+ #include <asm/io.h>
+ #include "netjet.h"
+
+-const char *NETjet_revision = "$Revision: 1.1.4.1 $";
++const char *NETjet_revision = "$Revision: 1.29 $";
+
+ /* Interface functions */
+
+@@ -135,7 +133,6 @@
+ mode_tiger(struct BCState *bcs, int mode, int bc)
+ {
+ struct IsdnCardState *cs = bcs->cs;
+- u_char led;
+
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "Tiger mode %d bchan %d/%d",
+@@ -157,15 +154,6 @@
+ cs->hw.njet.dmactrl);
+ byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0);
+ }
+- if (cs->typ == ISDN_CTYPE_NETJET_S)
+- {
+- // led off
+- led = bc & 0x01;
+- led = 0x01 << (6 + led); // convert to mask
+- led = ~led;
+- cs->hw.njet.auxd &= led;
+- byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+- }
+ break;
+ case (L1_MODE_TRANS):
+ break;
+@@ -191,14 +179,6 @@
+ bcs->hw.tiger.sendp = bcs->hw.tiger.send;
+ bcs->hw.tiger.free = NETJET_DMA_TXSIZE;
+ test_and_set_bit(BC_FLG_EMPTY, &bcs->Flag);
+- if (cs->typ == ISDN_CTYPE_NETJET_S)
+- {
+- // led on
+- led = bc & 0x01;
+- led = 0x01 << (6 + led); // convert to mask
+- cs->hw.njet.auxd |= led;
+- byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+- }
+ break;
+ }
+ if (cs->debug & L1_DEB_HSCX)
+@@ -874,13 +854,9 @@
+ case (PH_ACTIVATE | REQUEST):
+ test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+ mode_tiger(st->l1.bcs, st->l1.mode, st->l1.bc);
+- /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */
+- st->l1.bcs->cs->cardmsg(st->l1.bcs->cs, MDL_BC_ASSIGN, (void *)(&st->l1.bc));
+ l1_msg_b(st, pr, arg);
+ break;
+ case (PH_DEACTIVATE | REQUEST):
+- /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */
+- st->l1.bcs->cs->cardmsg(st->l1.bcs->cs, MDL_BC_RELEASE, (void *)(&st->l1.bc));
+ l1_msg_b(st, pr, arg);
+ break;
+ case (PH_DEACTIVATE | CONFIRM):
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/netjet.h linux-2.4.29/drivers/isdn/hisax/netjet.h
+--- linux-2.4.29.old/drivers/isdn/hisax/netjet.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/netjet.h 2005-03-22 15:06:47.956802240 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: netjet.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: netjet.h,v 2.8 2001/09/24 13:22:56 kai Exp $
+ *
+ * NETjet common header file
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/niccy.c linux-2.4.29/drivers/isdn/hisax/niccy.c
+--- linux-2.4.29.old/drivers/isdn/hisax/niccy.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/niccy.c 2005-03-22 15:06:47.977799048 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: niccy.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: niccy.c,v 1.21 2001/10/20 22:05:00 kai Exp $
+ *
+ * low level stuff for Dr. Neuhaus NICCY PnP and NICCY PCI and
+ * compatible (SAGEM cybermodem)
+@@ -22,10 +22,10 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
+-#include <linux/isapnp.h>
++#include <linux/isdn_compat.h>
+
+ extern const char *CardType[];
+-const char *niccy_revision = "$Revision: 1.1.4.1 $";
++const char *niccy_revision = "$Revision: 1.21 $";
+
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+@@ -239,9 +239,6 @@
+ }
+
+ static struct pci_dev *niccy_dev __initdata = NULL;
+-#ifdef __ISAPNP__
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+
+ int __init
+ setup_niccy(struct IsdnCard *card)
+@@ -253,39 +250,7 @@
+ printk(KERN_INFO "HiSax: Niccy driver Rev. %s\n", HiSax_getrev(tmp));
+ if (cs->typ != ISDN_CTYPE_NICCY)
+ return (0);
+-#ifdef __ISAPNP__
+- if (!card->para[1] && isapnp_present()) {
+- struct pci_bus *pb;
+- struct pci_dev *pd;
+-
+- if ((pb = isapnp_find_card(
+- ISAPNP_VENDOR('S', 'D', 'A'),
+- ISAPNP_FUNCTION(0x0150), pnp_c))) {
+- pnp_c = pb;
+- pd = NULL;
+- if (!(pd = isapnp_find_dev(pnp_c,
+- ISAPNP_VENDOR('S', 'D', 'A'),
+- ISAPNP_FUNCTION(0x0150), pd))) {
+- printk(KERN_ERR "NiccyPnP: PnP error card found, no device\n");
+- return (0);
+- }
+- pd->prepare(pd);
+- pd->deactivate(pd);
+- pd->activate(pd);
+- card->para[1] = pd->resource[0].start;
+- card->para[2] = pd->resource[1].start;
+- card->para[0] = pd->irq_resource[0].start;
+- if (!card->para[0] || !card->para[1] || !card->para[2]) {
+- printk(KERN_ERR "NiccyPnP:some resources are missing %ld/%lx/%lx\n",
+- card->para[0], card->para[1], card->para[2]);
+- pd->deactivate(pd);
+- return(0);
+- }
+- } else {
+- printk(KERN_INFO "NiccyPnP: no ISAPnP card found\n");
+- }
+- }
+-#endif
++
+ if (card->para[1]) {
+ cs->hw.niccy.isac = card->para[1] + ISAC_PNP;
+ cs->hw.niccy.hscx = card->para[1] + HSCX_PNP;
+@@ -331,12 +296,12 @@
+ return(0);
+ }
+ cs->irq = niccy_dev->irq;
+- cs->hw.niccy.cfg_reg = pci_resource_start(niccy_dev, 0);
++ cs->hw.niccy.cfg_reg = pci_resource_start_io(niccy_dev, 0);
+ if (!cs->hw.niccy.cfg_reg) {
+ printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n");
+ return(0);
+ }
+- pci_ioaddr = pci_resource_start(niccy_dev, 1);
++ pci_ioaddr = pci_resource_start_io(niccy_dev, 1);
+ if (!pci_ioaddr) {
+ printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n");
+ return(0);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/nj_s.c linux-2.4.29/drivers/isdn/hisax/nj_s.c
+--- linux-2.4.29.old/drivers/isdn/hisax/nj_s.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/nj_s.c 2005-03-22 15:06:47.993796616 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: nj_s.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: nj_s.c,v 2.13 2001/09/24 13:22:56 kai Exp $
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+@@ -12,11 +12,12 @@
+ #include "isac.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+ #include <linux/interrupt.h>
+ #include <linux/ppp_defs.h>
+ #include "netjet.h"
+
+-const char *NETjet_S_revision = "$Revision: 1.1.4.1 $";
++const char *NETjet_S_revision = "$Revision: 2.13 $";
+
+ static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
+ {
+@@ -130,7 +131,6 @@
+ release_io_netjet(cs);
+ return(0);
+ case CARD_INIT:
+- reset_netjet_s(cs);
+ inittiger(cs);
+ clear_pending_isac_ints(cs);
+ initisac(cs);
+@@ -180,19 +180,11 @@
+ printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n");
+ return(0);
+ }
+- cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
++ cs->hw.njet.base = pci_resource_start_io(dev_netjet, 0);
+ if (!cs->hw.njet.base) {
+ printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n");
+ return(0);
+ }
+- /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
+- if ((dev_netjet->subsystem_vendor == 0x55) &&
+- (dev_netjet->subsystem_device == 0x02)) {
+- printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n");
+- printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n");
+- return(0);
+- }
+- /* end new code */
+ } else {
+ printk(KERN_WARNING "NETjet-S: No PCI card found\n");
+ return(0);
+@@ -263,6 +255,7 @@
+ } else {
+ request_region(cs->hw.njet.base, bytecnt, "netjet-s isdn");
+ }
++ reset_netjet_s(cs);
+ cs->readisac = &NETjet_ReadIC;
+ cs->writeisac = &NETjet_WriteIC;
+ cs->readisacfifo = &NETjet_ReadICfifo;
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/nj_u.c linux-2.4.29/drivers/isdn/hisax/nj_u.c
+--- linux-2.4.29.old/drivers/isdn/hisax/nj_u.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/nj_u.c 2005-03-22 15:06:48.008794336 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: nj_u.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: nj_u.c,v 2.14 2001/09/24 13:22:56 kai Exp $
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+@@ -12,11 +12,12 @@
+ #include "icc.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+ #include <linux/interrupt.h>
+ #include <linux/ppp_defs.h>
+ #include "netjet.h"
+
+-const char *NETjet_U_revision = "$Revision: 1.1.4.1 $";
++const char *NETjet_U_revision = "$Revision: 2.14 $";
+
+ static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
+ {
+@@ -181,7 +182,7 @@
+ printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n");
+ return(0);
+ }
+- cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
++ cs->hw.njet.base = pci_resource_start_io(dev_netjet, 0);
+ if (!cs->hw.njet.base) {
+ printk(KERN_WARNING "NETspider-U: No IO-Adr for PCI card found\n");
+ return(0);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/q931.c linux-2.4.29/drivers/isdn/hisax/q931.c
+--- linux-2.4.29.old/drivers/isdn/hisax/q931.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/q931.c 2005-03-22 15:06:48.032790688 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: q931.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: q931.c,v 1.12 2001/09/24 13:22:56 kai Exp $
+ *
+ * code to decode ITU Q.931 call control messages
+ *
+@@ -197,6 +197,31 @@
+
+ #define MT_N1_LEN (sizeof(mt_n1) / sizeof(struct MessageType))
+
++#if 0
++static struct MessageType fac_1tr6[] =
++{
++ {FAC_Sperre, "Sperre"},
++ {FAC_Forward1, "Forward 1"},
++ {FAC_Forward2, "Forward 2"},
++ {FAC_Konferenz, "Konferenz"},
++ {FAC_GrabBchan, "Grab Bchannel"},
++ {FAC_Reactivate, "Reactivate"},
++ {FAC_Konferenz3, "Dreier Konferenz"},
++ {FAC_Dienstwechsel1, "Einseitiger Dienstwechsel"},
++ {FAC_Dienstwechsel2, "Zweiseitiger Dienstwechsel"},
++ {FAC_NummernIdent, "Rufnummer-Identifizierung"},
++ {FAC_GBG, "GBG"},
++ {FAC_DisplayUebergeben, "Display Uebergeben"},
++ {FAC_DisplayUmgeleitet, "Display Umgeleitet"},
++ {FAC_Unterdruecke, "Unterdruecke Rufnummer"},
++ {FAC_Deactivate, "Deactivate"},
++ {FAC_Activate, "Activate"},
++ {FAC_SPV, "SPV"},
++ {FAC_Rueckwechsel, "Rueckwechsel"},
++ {FAC_Umleitung, "Umleitung"}
++};
++#define FAC_1TR6_LEN (sizeof(fac_1tr6) / sizeof(struct MessageType))
++#endif
+
+ static int
+ prbits(char *dest, u_char b, int start, int len)
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/rawhdlc.c linux-2.4.29/drivers/isdn/hisax/rawhdlc.c
+--- linux-2.4.29.old/drivers/isdn/hisax/rawhdlc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/rawhdlc.c 2005-03-22 15:06:48.047788408 +0100
+@@ -0,0 +1,543 @@
++/* $Id: rawhdlc.c,v 1.7 2001/09/24 13:22:57 kai Exp $
++ *
++ * support routines for cards that don't support HDLC
++ *
++ * Author Brent Baccala
++ * Copyright by Karsten Keil <keil@isdn4linux.de>
++ * by Brent Baccala <baccala@FreeSoft.org>
++ *
++ * This software may be used and distributed according to the terms
++ * of the GNU General Public License, incorporated herein by reference.
++ *
++ *
++ * Some passive ISDN cards, such as the Traverse NETJet and the AMD 7930,
++ * don't perform HDLC encapsulation over the B channel. Drivers for
++ * such cards use support routines in this file to perform B channel HDLC.
++ *
++ * Bit-synchronous HDLC encapsulation is a means of encapsulating packets
++ * over a continuously transmitting serial communications link.
++ * It looks like this:
++ *
++ * 11111111101111110...........0111111011111111111
++ * iiiiiiiiiffffffffdddddddddddffffffffiiiiiiiiiii
++ *
++ * i = idle f = flag d = data
++ *
++ * When idle, the channel sends a continuous string of ones (mark
++ * idle; illustrated), or a continuous string of flag characters (flag
++ * idle). The beginning of a data frame is marked by a flag character
++ * (01111110), then comes the actual data, followed by another flag
++ * character, after which another frame may be sent immediately (a
++ * single flag may serve as both the end of one frame and the start of
++ * the next), or the link may return to idle. Obviously, the flag
++ * character can not appear anywhere in the data (or a false
++ * end-of-frame would occur), so the transmitter performs
++ * "bit-stuffing" - inserting a zero bit after every five one bits,
++ * irregardless of the original bit after the five ones. Byte
++ * ordering is irrelevent at this point - the data is treated as a
++ * string of bits, not bytes. Since no more than 5 ones may now occur
++ * in a row, the flag sequence, with its 6 ones, is unique.
++ *
++ * Upon reception, a zero bit that occur after 5 one bits is simply
++ * discarded. A series of 6 one bits is end-of-frame, and a series of
++ * 7 one bits is an abort. Once bit-stuffing has been corrected for,
++ * an integer number of bytes should now be present. The last two
++ * of these bytes form the Frame Check Sequence, a CRC that is verified
++ * and then discarded. Note that bit-stuffing is performed on the FCS
++ * just as if it were regular data.
++ *
++ *
++ *
++ * int make_raw_hdlc_data(u_char *src, u_int slen,
++ * u_char *dst, u_int dsize)
++ *
++ * Used for transmission. Copies slen bytes from src to dst, performing
++ * HDLC encapsulation (flag bytes, bit-stuffing, CRC) in the process.
++ * dsize is size of destination buffer, and should be at least
++ * ((6*slen)/5)+5 bytes to ensure adequate space will be available.
++ * Function returns length (in bytes) of valid destination buffer, or
++ * 0 upon destination overflow.
++ *
++ * void init_hdlc_state(struct hdlc_state *stateptr, int mode)
++ *
++ * Initializes hdlc_state structure before first call to read_raw_hdlc_data
++ *
++ * mode = 0: Sane mode
++ * mode = 1/2:
++ * Insane mode; NETJet use a shared unsigned int memory block (
++ * with busmaster DMA), the bit pattern of every word is
++ * <8 B1> <8 B2> <8 Mon> <2 D> <4 C/I> <MX> <MR>
++ * according to Siemens IOM-2 interface, so we have to handle
++ * the src buffer as unsigned int and have to shift/mask the
++ * B-channel bytes.
++ * mode 1 -> B1 mode 2 -> B2 data is used
++ *
++ * int read_raw_hdlc_data(struct hdlc_state *saved_state,
++ * u_char *src, u_int slen,
++ * u_char *dst, u_int dsize)
++ *
++ * Used for reception. Scans source buffer bit-by-bit looking for
++ * valid HDLC frames, which are copied to destination buffer. HDLC
++ * state information is stored in a structure, which allows this
++ * function to process frames spread across several blocks of raw
++ * HDLC data. Part of the state information is bit offsets into
++ * the source and destination buffers.
++ *
++ * A return value >0 indicates the length of a valid frame, now
++ * stored in the destination buffer. In this case, the source
++ * buffer might not be completely processed, so this function should
++ * be called again with the same source buffer, possibly with a
++ * different destination buffer.
++ *
++ * A return value of zero indicates that the source buffer was
++ * completely processed without finding a valid end-of-packet;
++ * however, we might be in the middle of packet reception, so
++ * the function should be called again with the next block of
++ * raw HDLC data and the same destination buffer. It is NOT
++ * permitted to change the destination buffer in this case,
++ * since data may already have begun to be stored there.
++ *
++ * A return value of -1 indicates some kind of error - destination
++ * buffer overflow, CRC check failed, frame not a multiple of 8
++ * bits. Destination buffer probably contains invalid data, which
++ * should be discarded. Call function again with same source buffer
++ * and a new (or same) destination buffer.
++ *
++ * Suggested calling sequence:
++ *
++ * init_hdlc_state(...);
++ * for (EACH_RAW_DATA_BLOCK) {
++ * while (len = read_raw_hdlc_data(...)) {
++ * if (len == -1) DISCARD_FRAME;
++ * else PROCESS_FRAME;
++ * }
++ * }
++ *
++ *
++ * Test the code in this file as follows:
++ * gcc -DDEBUGME -o rawhdlctest rawhdlc.c
++ * ./rawhdlctest < rawdata
++ *
++ * The file "rawdata" can be easily generated from a HISAX B-channel
++ * hex dump (CF CF CF 02 ...) using the following perl script:
++ *
++ * while(<>) {
++ * @hexlist = split ' ';
++ * while ($hexstr = shift(@hexlist)) {
++ * printf "%c", hex($hexstr);
++ * }
++ * }
++ *
++ */
++
++#ifdef DEBUGME
++#include <stdio.h>
++#endif
++
++#include <linux/types.h>
++#include <linux/ppp_defs.h>
++#include "rawhdlc.h"
++
++/* There's actually an identical copy of this table in the PPP code
++ * (ppp_crc16_table), but I don't want this code dependent on PPP
++ */
++
++// static
++__u16 fcstab[256] =
++{
++ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
++ 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
++ 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
++ 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
++ 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
++ 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
++ 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
++ 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
++ 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
++ 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
++ 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
++ 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
++ 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
++ 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
++ 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
++ 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
++ 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
++ 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
++ 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
++ 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
++ 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
++ 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
++ 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
++ 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
++ 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
++ 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
++ 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
++ 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
++ 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
++ 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
++ 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
++ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
++};
++
++#define HDLC_ZERO_SEARCH 0
++#define HDLC_FLAG_SEARCH 1
++#define HDLC_FLAG_FOUND 2
++#define HDLC_FRAME_FOUND 3
++#define HDLC_NULL 4
++#define HDLC_PART 5
++#define HDLC_FULL 6
++
++#define HDLC_FLAG_VALUE 0x7e
++
++
++#define MAKE_RAW_BYTE for (j=0; j<8; j++) { \
++ bitcnt++;\
++ out_val >>= 1;\
++ if (val & 1) {\
++ s_one++;\
++ out_val |= 0x80;\
++ } else {\
++ s_one = 0;\
++ out_val &= 0x7f;\
++ }\
++ if (bitcnt==8) {\
++ if (d_cnt == dsize) return 0;\
++ dst[d_cnt++] = out_val;\
++ bitcnt = 0;\
++ }\
++ if (s_one == 5) {\
++ out_val >>= 1;\
++ out_val &= 0x7f;\
++ bitcnt++;\
++ s_one = 0;\
++ }\
++ if (bitcnt==8) {\
++ if (d_cnt == dsize) return 0;\
++ dst[d_cnt++] = out_val;\
++ bitcnt = 0;\
++ }\
++ val >>= 1;\
++ }
++
++/* Optimization suggestion: If needed, this function could be
++ * dramatically sped up using a state machine. Each state would
++ * correspond to having seen N one bits, and being offset M bits into
++ * the current output byte. N ranges from 0 to 4, M from 0 to 7, so
++ * we need 5*8 = 35 states. Each state would have a table with 256
++ * entries, one for each input character. Each entry would contain
++ * three output characters, an output state, an a byte increment
++ * that's either 1 or 2. All this could fit in four bytes; so we need
++ * 4 bytes * 256 characters = 1 KB for each state (35 KB total). Zero
++ * the output buffer before you start. For each character in your
++ * input, you look it up in the current state's table and get three
++ * bytes to be or'ed into the output at the current byte offset, and
++ * an byte increment to move your pointer forward. A simple Perl
++ * script could generate the tables. Given HDLC semantics, probably
++ * would be better to set output to all 1s, then use ands instead of ors.
++ * A smaller state machine could operate on nibbles instead of bytes.
++ * A state machine for 32-bit architectures could use word offsets
++ * instead of byte offsets, requiring 5*32 = 160 states; probably
++ * best to work on nibbles in such a case.
++ */
++
++
++int make_raw_hdlc_data(u_char *src, u_int slen, u_char *dst, u_int dsize)
++{
++ register u_int i,d_cnt=0;
++ register u_char j;
++ register u_char val;
++ register u_char s_one = 0;
++ register u_char out_val = 0;
++ register u_char bitcnt = 0;
++ u_int fcs;
++
++
++ dst[d_cnt++] = HDLC_FLAG_VALUE;
++ fcs = PPP_INITFCS;
++ for (i=0; i<slen; i++) {
++ val = src[i];
++ fcs = PPP_FCS (fcs, val);
++ MAKE_RAW_BYTE;
++ }
++ fcs ^= 0xffff;
++ val = fcs & 0xff;
++ MAKE_RAW_BYTE;
++ val = (fcs>>8) & 0xff;
++ MAKE_RAW_BYTE;
++ val = HDLC_FLAG_VALUE;
++ for (j=0; j<8; j++) {
++ bitcnt++;
++ out_val >>= 1;
++ if (val & 1)
++ out_val |= 0x80;
++ else
++ out_val &= 0x7f;
++ if (bitcnt==8) {
++ if (d_cnt == dsize) return 0;
++ dst[d_cnt++] = out_val;
++ bitcnt = 0;
++ }
++ val >>= 1;
++ }
++ if (bitcnt) {
++ while (8>bitcnt++) {
++ out_val >>= 1;
++ out_val |= 0x80;
++ }
++ if (d_cnt == dsize) return 0;
++ dst[d_cnt++] = out_val;
++ }
++
++ return d_cnt;
++}
++
++void init_hdlc_state(struct hdlc_state *stateptr, int mode)
++{
++ stateptr->state = HDLC_ZERO_SEARCH;
++ stateptr->r_one = 0;
++ stateptr->r_val = 0;
++ stateptr->o_bitcnt = 0;
++ stateptr->i_bitcnt = 0;
++ stateptr->insane_mode = mode;
++}
++
++/* Optimization suggestion: A similar state machine could surely
++ * be developed for this function as well.
++ */
++
++int read_raw_hdlc_data(struct hdlc_state *saved_state,
++ u_char *src, u_int slen, u_char *dst, u_int dsize)
++{
++ int retval=0;
++ register u_char val;
++ register u_char state = saved_state->state;
++ register u_char r_one = saved_state->r_one;
++ register u_char r_val = saved_state->r_val;
++ register u_int o_bitcnt = saved_state->o_bitcnt;
++ register u_int i_bitcnt = saved_state->i_bitcnt;
++ register u_int fcs = saved_state->fcs;
++ register u_int *isrc = (u_int *) src;
++
++ /* Use i_bitcnt (bit offset into source buffer) to reload "val"
++ * in case we're starting up again partway through a source buffer
++ */
++
++ if ((i_bitcnt >> 3) < slen) {
++ if (saved_state->insane_mode==1) {
++ val = isrc[(i_bitcnt >> 3)] & 0xff;
++ } else if (saved_state->insane_mode==2) {
++ val = (isrc[i_bitcnt >> 3] >>8) & 0xff;
++ } else {
++ val = src[i_bitcnt >> 3];
++ }
++ val >>= i_bitcnt & 7;
++ }
++
++ /* One bit per loop. Keep going until we've got something to
++ * report (retval != 0), or we exhaust the source buffer
++ */
++
++ while ((retval == 0) && ((i_bitcnt >> 3) < slen)) {
++ if ((i_bitcnt & 7) == 0) {
++ if (saved_state->insane_mode==1) {
++ val = isrc[(i_bitcnt >> 3)] & 0xff;
++ } else if (saved_state->insane_mode==2) {
++ val = (isrc[i_bitcnt >> 3] >>8) & 0xff;
++ } else {
++ val = src[i_bitcnt >> 3];
++ }
++#ifdef DEBUGME
++ printf("Input byte %d: 0x%2x\n", i_bitcnt>>3, val);
++#endif
++ if (val == 0xff) {
++ state = HDLC_ZERO_SEARCH;
++ o_bitcnt = 0;
++ r_one = 0;
++ i_bitcnt += 8;
++ continue;
++ }
++ }
++
++#ifdef DEBUGME
++ /* printf("Data bit=%d (%d/%d)\n", val&1, i_bitcnt>>3, i_bitcnt&7);*/
++#endif
++
++ if (state == HDLC_ZERO_SEARCH) {
++ if (val & 1) {
++ r_one++;
++ } else {
++ r_one=0;
++ state= HDLC_FLAG_SEARCH;
++ }
++ } else if (state == HDLC_FLAG_SEARCH) {
++ if (val & 1) {
++ r_one++;
++ if (r_one>6) {
++ state=HDLC_ZERO_SEARCH;
++ }
++ } else {
++ if (r_one==6) {
++ o_bitcnt=0;
++ r_val=0;
++ state=HDLC_FLAG_FOUND;
++ }
++ r_one=0;
++ }
++ } else if (state == HDLC_FLAG_FOUND) {
++ if (val & 1) {
++ r_one++;
++ if (r_one>6) {
++ state=HDLC_ZERO_SEARCH;
++ } else {
++ r_val >>= 1;
++ r_val |= 0x80;
++ o_bitcnt++;
++ }
++ } else {
++ if (r_one==6) {
++ o_bitcnt=0;
++ r_val=0;
++ r_one=0;
++ i_bitcnt++;
++ val >>= 1;
++ continue;
++ } else if (r_one!=5) {
++ r_val >>= 1;
++ r_val &= 0x7f;
++ o_bitcnt++;
++ }
++ r_one=0;
++ }
++ if ((state != HDLC_ZERO_SEARCH) &&
++ !(o_bitcnt & 7)) {
++#ifdef DEBUGME
++ printf("HDLC_FRAME_FOUND at i_bitcnt:%d\n",i_bitcnt);
++#endif
++ state=HDLC_FRAME_FOUND;
++ fcs = PPP_INITFCS;
++ dst[0] = r_val;
++ fcs = PPP_FCS (fcs, r_val);
++ }
++ } else if (state == HDLC_FRAME_FOUND) {
++ if (val & 1) {
++ r_one++;
++ if (r_one>6) {
++ state=HDLC_ZERO_SEARCH;
++ o_bitcnt=0;
++ } else {
++ r_val >>= 1;
++ r_val |= 0x80;
++ o_bitcnt++;
++ }
++ } else {
++ if (r_one==6) {
++ r_val=0;
++ r_one=0;
++ o_bitcnt++;
++ if (o_bitcnt & 7) {
++ /* Alignment error */
++#ifdef DEBUGME
++ printf("Alignment error\n");
++#endif
++ state=HDLC_FLAG_SEARCH;
++ retval = -1;
++ } else if (fcs==PPP_GOODFCS) {
++ /* Valid frame */
++ state=HDLC_FLAG_FOUND;
++ retval = (o_bitcnt>>3)-3;
++ } else {
++ /* CRC error */
++#ifdef DEBUGME
++ printf("CRC error; fcs was 0x%x, should have been 0x%x\n", fcs, PPP_GOODFCS);
++#endif
++ state=HDLC_FLAG_FOUND;
++ retval = -1;
++ }
++ } else if (r_one==5) {
++ r_one=0;
++ i_bitcnt++;
++ val >>= 1;
++ continue;
++ } else {
++ r_val >>= 1;
++ r_val &= 0x7f;
++ o_bitcnt++;
++ }
++ r_one=0;
++ }
++ if ((state == HDLC_FRAME_FOUND) &&
++ !(o_bitcnt & 7)) {
++ if ((o_bitcnt>>3)>=dsize) {
++ /* Buffer overflow error */
++#ifdef DEBUGME
++ printf("Buffer overflow error\n");
++#endif
++ r_val=0;
++ state=HDLC_FLAG_SEARCH;
++ retval = -1;
++ } else {
++ dst[(o_bitcnt>>3)-1] = r_val;
++ fcs = PPP_FCS (fcs, r_val);
++#ifdef DEBUGME
++ printf("Output byte %d: 0x%02x; FCS 0x%04x\n", (o_bitcnt>>3)-1, r_val, fcs);
++#endif
++ }
++ }
++ }
++ i_bitcnt ++;
++ val >>= 1;
++ }
++
++ /* We exhausted the source buffer before anything else happened
++ * (retval==0). Reset i_bitcnt in expectation of a new source
++ * buffer. Other, we either had an error or a valid frame, so
++ * reset o_bitcnt in expectation of a new destination buffer.
++ */
++
++ if (retval == 0) {
++ i_bitcnt = 0;
++ } else {
++ o_bitcnt = 0;
++ }
++
++ saved_state->state = state;
++ saved_state->r_one = r_one;
++ saved_state->r_val = r_val;
++ saved_state->fcs = fcs;
++ saved_state->o_bitcnt = o_bitcnt;
++ saved_state->i_bitcnt = i_bitcnt;
++
++ return (retval);
++}
++
++
++
++#ifdef DEBUGME
++
++char buffer[1024];
++char obuffer[1024];
++
++main()
++{
++ int buflen=0;
++ int len;
++ struct hdlc_state hdlc_state;
++
++ while((buffer[buflen] = getc(stdin)) != EOF && buflen<1024) buflen++;
++
++ printf("buflen = %d\n", buflen);
++
++ init_hdlc_state(&hdlc_state, 0);
++
++ while (len = read_raw_hdlc_data(&hdlc_state,buffer,buflen,obuffer,1024)) {
++ if (len == -1) printf("Error @ byte %d/bit %d\n",
++ hdlc_state.i_bitcnt>>3, hdlc_state.i_bitcnt & 7);
++ else {
++ printf("Frame received: len %d\n", len);
++ }
++ }
++
++ printf("Done\n");
++}
++
++#endif
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/rawhdlc.h linux-2.4.29/drivers/isdn/hisax/rawhdlc.h
+--- linux-2.4.29.old/drivers/isdn/hisax/rawhdlc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/rawhdlc.h 2005-03-22 15:06:48.076784000 +0100
+@@ -0,0 +1,28 @@
++/* $Id: rawhdlc.h,v 1.5 2001/09/24 13:22:57 kai Exp $
++ *
++ * Author Brent Baccala
++ * Copyright by Brent Baccala <baccala@FreeSoft.org>
++ *
++ * This software may be used and distributed according to the terms
++ * of the GNU General Public License, incorporated herein by reference.
++ *
++ */
++
++#ifndef RAWHDLC_H
++struct hdlc_state {
++ char insane_mode;
++ u_char state;
++ u_char r_one;
++ u_char r_val;
++ u_int o_bitcnt;
++ u_int i_bitcnt;
++ u_int fcs;
++};
++
++
++int make_raw_hdlc_data(u_char *src, u_int slen, u_char *dst, u_int dsize);
++void init_hdlc_state(struct hdlc_state *stateptr, int mode);
++int read_raw_hdlc_data(struct hdlc_state *saved_state,
++ u_char *src, u_int slen, u_char *dst, u_int dsize);
++#define RAWHDLC_H
++#endif
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/s0box.c linux-2.4.29/drivers/isdn/hisax/s0box.c
+--- linux-2.4.29.old/drivers/isdn/hisax/s0box.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/s0box.c 2005-03-22 15:06:48.092781568 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: s0box.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: s0box.c,v 2.6 2001/09/24 13:22:57 kai Exp $
+ *
+ * low level stuff for Creatix S0BOX
+ *
+@@ -18,7 +18,7 @@
+ #include "isdnl1.h"
+
+ extern const char *CardType[];
+-const char *s0box_revision = "$Revision: 1.1.4.1 $";
++const char *s0box_revision = "$Revision: 2.6 $";
+
+ static inline void
+ writereg(unsigned int padr, signed int addr, u_char off, u_char val) {
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/saphir.c linux-2.4.29/drivers/isdn/hisax/saphir.c
+--- linux-2.4.29.old/drivers/isdn/hisax/saphir.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/saphir.c 2005-03-22 15:06:48.107779288 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: saphir.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: saphir.c,v 1.10 2001/09/24 13:22:57 kai Exp $
+ *
+ * low level stuff for HST Saphir 1
+ *
+@@ -20,7 +20,7 @@
+ #include "isdnl1.h"
+
+ extern const char *CardType[];
+-static char *saphir_rev = "$Revision: 1.1.4.1 $";
++static char *saphir_rev = "$Revision: 1.10 $";
+
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/sedlbauer.c linux-2.4.29/drivers/isdn/hisax/sedlbauer.c
+--- linux-2.4.29.old/drivers/isdn/hisax/sedlbauer.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/sedlbauer.c 2005-03-22 15:06:48.123776856 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: sedlbauer.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: sedlbauer.c,v 1.34 2002/02/09 21:00:57 keil Exp $
+ *
+ * low level stuff for Sedlbauer cards
+ * includes support for the Sedlbauer speed star (speed star II),
+@@ -48,18 +48,19 @@
+ #include "isar.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
+-#include <linux/isapnp.h>
++#include <linux/isdn_compat.h>
+
+ extern const char *CardType[];
+
+-const char *Sedlbauer_revision = "$Revision: 1.1.4.1 $";
++const char *Sedlbauer_revision = "$Revision: 1.34 $";
+
+ const char *Sedlbauer_Types[] =
+ {"None", "speed card/win", "speed star", "speed fax+",
+ "speed win II / ISDN PC/104", "speed star II", "speed pci",
+- "speed fax+ pyramid", "speed fax+ pci"};
++ "speed fax+ pyramid", "speed fax+ pci", "HST Saphir III"};
+
+ #define PCI_SUBVENDOR_SPEEDFAX_PYRAMID 0x51
++#define PCI_SUBVENDOR_HST_SAPHIR3 0x52
+ #define PCI_SUBVENDOR_SEDLBAUER_PCI 0x53
+ #define PCI_SUBVENDOR_SPEEDFAX_PCI 0x54
+ #define PCI_SUB_ID_SEDLBAUER 0x01
+@@ -72,6 +73,7 @@
+ #define SEDL_SPEED_PCI 6
+ #define SEDL_SPEEDFAX_PYRAMID 7
+ #define SEDL_SPEEDFAX_PCI 8
++#define HST_SAPHIR3 9
+
+ #define SEDL_CHIP_TEST 0
+ #define SEDL_CHIP_ISAC_HSCX 1
+@@ -531,21 +533,6 @@
+
+ static struct pci_dev *dev_sedl __devinitdata = NULL;
+
+-#ifdef __ISAPNP__
+-static struct isapnp_device_id sedl_ids[] __initdata = {
+- { ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01),
+- ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01),
+- (unsigned long) "Speed win" },
+- { ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02),
+- ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02),
+- (unsigned long) "Speed Fax+" },
+- { 0, }
+-};
+-
+-static struct isapnp_device_id *pdev = &sedl_ids[0];
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+-
+ int __devinit
+ setup_sedlbauer(struct IsdnCard *card)
+ {
+@@ -581,57 +568,6 @@
+ bytecnt = 16;
+ }
+ } else {
+-#ifdef __ISAPNP__
+- if (isapnp_present()) {
+- struct pci_bus *pb;
+- struct pci_dev *pd;
+-
+- while(pdev->card_vendor) {
+- if ((pb = isapnp_find_card(pdev->card_vendor,
+- pdev->card_device, pnp_c))) {
+- pnp_c = pb;
+- pd = NULL;
+- if ((pd = isapnp_find_dev(pnp_c,
+- pdev->vendor, pdev->function, pd))) {
+- printk(KERN_INFO "HiSax: %s detected\n",
+- (char *)pdev->driver_data);
+- pd->prepare(pd);
+- pd->deactivate(pd);
+- pd->activate(pd);
+- card->para[1] =
+- pd->resource[0].start;
+- card->para[0] =
+- pd->irq_resource[0].start;
+- if (!card->para[0] || !card->para[1]) {
+- printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
+- card->para[0], card->para[1]);
+- pd->deactivate(pd);
+- return(0);
+- }
+- cs->hw.sedl.cfg_reg = card->para[1];
+- cs->irq = card->para[0];
+- if (pdev->function == ISAPNP_FUNCTION(0x2)) {
+- cs->subtyp = SEDL_SPEED_FAX;
+- cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+- bytecnt = 16;
+- } else {
+- cs->subtyp = SEDL_SPEED_CARD_WIN;
+- cs->hw.sedl.chip = SEDL_CHIP_TEST;
+- }
+- goto ready;
+- } else {
+- printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
+- return(0);
+- }
+- }
+- pdev++;
+- pnp_c=NULL;
+- }
+- if (!pdev->card_vendor) {
+- printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
+- }
+- }
+-#endif
+ /* Probe for Sedlbauer speed pci */
+ #if CONFIG_PCI
+ if (!pci_present()) {
+@@ -647,15 +583,15 @@
+ printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
+ return(0);
+ }
+- cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0);
++ cs->hw.sedl.cfg_reg = pci_resource_start_io(dev_sedl, 0);
+ } else {
+ printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
+ return(0);
+ }
+ cs->irq_flags |= SA_SHIRQ;
+ cs->hw.sedl.bus = SEDL_BUS_PCI;
+- sub_vendor_id = dev_sedl->subsystem_vendor;
+- sub_id = dev_sedl->subsystem_device;
++ pci_get_sub_vendor(dev_sedl,sub_vendor_id);
++ pci_get_sub_system(dev_sedl,sub_id);
+ printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n",
+ sub_vendor_id, sub_id);
+ printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n",
+@@ -670,6 +606,9 @@
+ } else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) {
+ cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+ cs->subtyp = SEDL_SPEEDFAX_PCI;
++ } else if (sub_vendor_id == PCI_SUBVENDOR_HST_SAPHIR3) {
++ cs->hw.sedl.chip = SEDL_CHIP_IPAC;
++ cs->subtyp = HST_SAPHIR3;
+ } else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) {
+ cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+ cs->subtyp = SEDL_SPEED_PCI;
+@@ -683,8 +622,8 @@
+ cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
+ byteout(cs->hw.sedl.cfg_reg, 0xff);
+ byteout(cs->hw.sedl.cfg_reg, 0x00);
+- byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
+- byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
++ byteout(cs->hw.sedl.cfg_reg +2, 0xdd);
++ byteout(cs->hw.sedl.cfg_reg +5, 0x02);
+ byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
+ save_flags(flags);
+ sti();
+@@ -697,7 +636,7 @@
+ return (0);
+ #endif /* CONFIG_PCI */
+ }
+-ready:
++
+ /* In case of the sedlbauer pcmcia card, this region is in use,
+ * reserved for us by the card manager. So we do not check it
+ * here, it would fail.
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/sportster.c linux-2.4.29/drivers/isdn/hisax/sportster.c
+--- linux-2.4.29.old/drivers/isdn/hisax/sportster.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/sportster.c 2005-03-22 15:06:48.169769864 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: sportster.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: sportster.c,v 1.16 2001/09/24 13:22:57 kai Exp $
+ *
+ * low level stuff for USR Sportster internal TA
+ *
+@@ -20,7 +20,7 @@
+ #include "isdnl1.h"
+
+ extern const char *CardType[];
+-const char *sportster_revision = "$Revision: 1.1.4.1 $";
++const char *sportster_revision = "$Revision: 1.16 $";
+
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/st5481-debug.h linux-2.4.29/drivers/isdn/hisax/st5481-debug.h
+--- linux-2.4.29.old/drivers/isdn/hisax/st5481-debug.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/st5481-debug.h 2005-03-22 15:06:48.184767584 +0100
+@@ -0,0 +1,103 @@
++#define ST5481_DEBUG 0x0
++
++#if ST5481_DEBUG
++
++
++/*
++ DEBUG flags. Set compile option ST5481_DEBUG with the following bits set to trace
++ the given subsections:
++
++ 0x01: USB
++ 0x02: D
++ 0x04: B
++ 0x08: PH
++ 0x10: PACKET_DUMP D out
++ 0x20: ISO_DUMP D out
++ 0x40: PACKET_DUMP D in
++ 0x80: ISO_DUMP in
++ 0x100: PACKET_DUMP B out
++ 0x200: ISO_DUMP B out
++ 0x400: PACKET_DUMP B in
++*/
++
++#define DBG(level, format, arg...) \
++if (level & ST5481_DEBUG) \
++printk(KERN_DEBUG __FUNCTION__ ": " format "\n" , ## arg) \
++
++static inline void
++dump_packet(const char *name,const u_char *data,int pkt_len)
++{
++#define DUMP_HDR_SIZE 200
++#define DUMP_TLR_SIZE 8
++ if (pkt_len) {
++ int i,len1,len2;
++
++ printk(KERN_DEBUG "%s: length=%d,data=",name,pkt_len);
++
++ if (pkt_len > DUMP_HDR_SIZE+ DUMP_TLR_SIZE) {
++ len1 = DUMP_HDR_SIZE;
++ len2 = DUMP_TLR_SIZE;
++ } else {
++ len1 = pkt_len > DUMP_HDR_SIZE ? DUMP_HDR_SIZE : pkt_len;
++ len2 = 0;
++ }
++ for (i = 0; i < len1; ++i) {
++ printk ("%.2x", data[i]);
++ }
++ if (len2) {
++ printk ("..");
++ for (i = pkt_len-DUMP_TLR_SIZE; i < pkt_len; ++i) {
++ printk ("%.2x", data[i]);
++ }
++ }
++ printk ("\n");
++ }
++#undef DUMP_HDR_SIZE
++#undef DUMP_TLR_SIZE
++}
++
++static inline void
++dump_iso_packet(const char *name,urb_t *urb)
++{
++ int i,j;
++ int len,ofs;
++ u_char *data;
++
++ printk(KERN_DEBUG "%s: packets=%d,errors=%d\n",
++ name,urb->number_of_packets,urb->error_count);
++ for (i = 0; i < urb->number_of_packets; ++i) {
++ if (urb->pipe & USB_DIR_IN) {
++ len = urb->iso_frame_desc[i].actual_length;
++ } else {
++ len = urb->iso_frame_desc[i].length;
++ }
++ ofs = urb->iso_frame_desc[i].offset;
++ printk(KERN_DEBUG "len=%.2d,ofs=%.3d ",len,ofs);
++ if (len) {
++ data = urb->transfer_buffer+ofs;
++ for (j=0; j < len; j++) {
++ printk ("%.2x", data[j]);
++ }
++ }
++ printk("\n");
++ }
++}
++
++#define DUMP_PACKET(level,data,count) \
++ if (level & ST5481_DEBUG) dump_packet(__FUNCTION__,data,count)
++#define DUMP_SKB(level,skb) \
++ if ((level & ST5481_DEBUG) && skb) dump_packet(__FUNCTION__,skb->data,skb->len)
++#define DUMP_ISO_PACKET(level,urb) \
++ if (level & ST5481_DEBUG) dump_iso_packet(__FUNCTION__,urb)
++
++#else
++
++#define DBG(level,format, arg...) do {} while (0)
++#define DUMP_PACKET(level,data,count) do {} while (0)
++#define DUMP_SKB(level,skb) do {} while (0)
++#define DUMP_ISO_PACKET(level,urb) do {} while (0)
++
++#endif
++
++
++
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/st5481.h linux-2.4.29/drivers/isdn/hisax/st5481.h
+--- linux-2.4.29.old/drivers/isdn/hisax/st5481.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/st5481.h 2005-03-22 15:06:48.201765000 +0100
+@@ -219,15 +219,15 @@
+ #define L1_EVENT_COUNT (EV_TIMER3 + 1)
+
+ #define ERR(format, arg...) \
+-printk(KERN_ERR "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg)
++printk(KERN_ERR __FILE__ ": " __FUNCTION__ ": " format "\n" , ## arg)
+
+ #define WARN(format, arg...) \
+-printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg)
++printk(KERN_WARNING __FILE__ ": " __FUNCTION__ ": " format "\n" , ## arg)
+
+ #define INFO(format, arg...) \
+-printk(KERN_INFO "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg)
++printk(KERN_INFO __FILE__ ": " __FUNCTION__ ": " format "\n" , ## arg)
+
+-#include "isdnhdlc.h"
++#include "st5481_hdlc.h"
+ #include "fsm.h"
+ #include "hisax_if.h"
+ #include <linux/skbuff.h>
+@@ -236,7 +236,7 @@
+ * FIFO handling
+ */
+
+-/* Generic FIFO structure */
++/* Generic FIFO structure */
+ struct fifo {
+ u_char r,w,count,size;
+ spinlock_t lock;
+@@ -270,7 +270,7 @@
+ index = -1;
+ } else {
+ // Return index where to get the next data to add to the FIFO
+- index = fifo->w++ & (fifo->size-1);
++ index = fifo->w++ & (fifo->size-1);
+ fifo->count++;
+ }
+ spin_unlock_irqrestore(&fifo->lock, flags);
+@@ -289,13 +289,13 @@
+ return -1;
+ }
+
+- spin_lock_irqsave(&fifo->lock, flags);
++ spin_lock_irqsave(&fifo->lock, flags);
+ if (!fifo->count) {
+ // FIFO empty
+ index = -1;
+ } else {
+ // Return index where to get the next data from the FIFO
+- index = fifo->r++ & (fifo->size-1);
++ index = fifo->r++ & (fifo->size-1);
+ fifo->count--;
+ }
+ spin_unlock_irqrestore(&fifo->lock, flags);
+@@ -309,7 +309,7 @@
+ typedef void (*ctrl_complete_t)(void *);
+
+ typedef struct ctrl_msg {
+- struct usb_ctrlrequest dr;
++ devrequest dr;
+ ctrl_complete_t complete;
+ void *context;
+ } ctrl_msg;
+@@ -336,7 +336,7 @@
+ };
+
+ struct st5481_d_out {
+- struct isdnhdlc_vars hdlc_state;
++ struct hdlc_vars hdlc_state;
+ struct urb *urb[2]; /* double buffering */
+ unsigned long busy;
+ struct sk_buff *tx_skb;
+@@ -344,7 +344,7 @@
+ };
+
+ struct st5481_b_out {
+- struct isdnhdlc_vars hdlc_state;
++ struct hdlc_vars hdlc_state;
+ struct urb *urb[2]; /* double buffering */
+ u_char flow_event;
+ u_long busy;
+@@ -352,7 +352,7 @@
+ };
+
+ struct st5481_in {
+- struct isdnhdlc_vars hdlc_state;
++ struct hdlc_vars hdlc_state;
+ struct urb *urb[2]; /* double buffering */
+ int mode;
+ int bufsize;
+@@ -478,7 +478,7 @@
+ if (level & __debug_variable) dump_iso_packet(__FUNCTION__,urb)
+
+ static void __attribute__((unused))
+-dump_iso_packet(const char *name,struct urb *urb)
++dump_iso_packet(const char *name,urb_t *urb)
+ {
+ int i,j;
+ int len,ofs;
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/st5481_b.c linux-2.4.29/drivers/isdn/hisax/st5481_b.c
+--- linux-2.4.29.old/drivers/isdn/hisax/st5481_b.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/st5481_b.c 2005-03-22 15:06:48.216762720 +0100
+@@ -67,28 +67,24 @@
+ bytes_sent = buf_size - len;
+ if (skb->len < bytes_sent)
+ bytes_sent = skb->len;
+- { /* swap tx bytes to get hearable audio data */
+- register unsigned char *src = skb->data;
+- register unsigned char *dest = urb->transfer_buffer+len;
+- register unsigned int count;
+- for (count = 0; count < bytes_sent; count++)
+- *dest++ = isdnhdlc_bit_rev_tab[*src++];
+- }
++
++ memcpy(urb->transfer_buffer+len, skb->data, bytes_sent);
++
+ len += bytes_sent;
+ } else {
+- len += isdnhdlc_encode(&b_out->hdlc_state,
+- skb->data, skb->len, &bytes_sent,
+- urb->transfer_buffer+len, buf_size-len);
++ len += hdlc_encode(&b_out->hdlc_state,
++ skb->data, skb->len, &bytes_sent,
++ urb->transfer_buffer+len, buf_size-len);
+ }
+
+ skb_pull(skb, bytes_sent);
+-
++
+ if (!skb->len) {
+ // Frame sent
+ b_out->tx_skb = NULL;
+ B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize);
+ dev_kfree_skb_any(skb);
+-
++
+ /* if (!(bcs->tx_skb = skb_dequeue(&bcs->sq))) { */
+ /* st5481B_sched_event(bcs, B_XMTBUFREADY); */
+ /* } */
+@@ -99,9 +95,9 @@
+ len = buf_size;
+ } else {
+ // Send flags
+- len += isdnhdlc_encode(&b_out->hdlc_state,
+- NULL, 0, &bytes_sent,
+- urb->transfer_buffer+len, buf_size-len);
++ len += hdlc_encode(&b_out->hdlc_state,
++ NULL, 0, &bytes_sent,
++ urb->transfer_buffer+len, buf_size-len);
+ }
+ }
+ }
+@@ -213,7 +209,7 @@
+ if (bcs->mode != L1_MODE_NULL) {
+ // Open the B channel
+ if (bcs->mode != L1_MODE_TRANS) {
+- isdnhdlc_out_init(&b_out->hdlc_state, 0, bcs->mode == L1_MODE_HDLC_56K);
++ hdlc_out_init(&b_out->hdlc_state, 0, bcs->mode == L1_MODE_HDLC_56K);
+ }
+ st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2, NULL, NULL);
+
+@@ -279,7 +275,7 @@
+ usb_b_out_complete, bcs);
+ }
+
+-static void st5481_release_b_out(struct st5481_bcs *bcs)
++static void __devexit st5481_release_b_out(struct st5481_bcs *bcs)
+ {
+ struct st5481_b_out *b_out = &bcs->b_out;
+
+@@ -320,7 +316,7 @@
+ /*
+ * Release buffers and URBs for the B channels
+ */
+-void st5481_release_b(struct st5481_bcs *bcs)
++void __devexit st5481_release_b(struct st5481_bcs *bcs)
+ {
+ DBG(4,"");
+
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/st5481_d.c linux-2.4.29/drivers/isdn/hisax/st5481_d.c
+--- linux-2.4.29.old/drivers/isdn/hisax/st5481_d.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/st5481_d.c 2005-03-22 15:06:48.231760440 +0100
+@@ -162,8 +162,8 @@
+ {ST_L1_F8, EV_TIMER3, l1_timer3},
+ {ST_L1_F8, EV_IND_DP, l1_go_f3},
+ {ST_L1_F8, EV_IND_AP, l1_go_f6},
+- {ST_L1_F8, EV_IND_AI8, l1_go_f7},
+- {ST_L1_F8, EV_IND_AI10, l1_go_f7},
++ {ST_L1_F8, EV_IND_AI8, l1_go_f8},
++ {ST_L1_F8, EV_IND_AI10, l1_go_f8},
+ {ST_L1_F8, EV_IND_RSY, l1_ignore},
+ };
+
+@@ -297,7 +297,7 @@
+ unsigned int num_packets, packet_offset;
+ int len, buf_size, bytes_sent;
+ struct sk_buff *skb;
+- struct iso_packet_descriptor *desc;
++ iso_packet_descriptor_t *desc;
+
+ if (d_out->fsm.state != ST_DOUT_NORMAL)
+ return;
+@@ -313,15 +313,15 @@
+ buf_size = NUM_ISO_PACKETS_D * SIZE_ISO_PACKETS_D_OUT;
+
+ if (skb) {
+- len = isdnhdlc_encode(&d_out->hdlc_state,
+- skb->data, skb->len, &bytes_sent,
+- urb->transfer_buffer, buf_size);
++ len = hdlc_encode(&d_out->hdlc_state,
++ skb->data, skb->len, &bytes_sent,
++ urb->transfer_buffer, buf_size);
+ skb_pull(skb,bytes_sent);
+ } else {
+ // Send flags or idle
+- len = isdnhdlc_encode(&d_out->hdlc_state,
+- NULL, 0, &bytes_sent,
+- urb->transfer_buffer, buf_size);
++ len = hdlc_encode(&d_out->hdlc_state,
++ NULL, 0, &bytes_sent,
++ urb->transfer_buffer, buf_size);
+ }
+
+ if (len < buf_size) {
+@@ -413,7 +413,7 @@
+
+ DBG(2,"len=%d",skb->len);
+
+- isdnhdlc_out_init(&d_out->hdlc_state, 1, 0);
++ hdlc_out_init(&d_out->hdlc_state, 1, 0);
+
+ if (test_and_set_bit(buf_nr, &d_out->busy)) {
+ WARN("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy);
+@@ -422,9 +422,9 @@
+ urb = d_out->urb[buf_nr];
+
+ DBG_SKB(0x10, skb);
+- len = isdnhdlc_encode(&d_out->hdlc_state,
+- skb->data, skb->len, &bytes_sent,
+- urb->transfer_buffer, 16);
++ len = hdlc_encode(&d_out->hdlc_state,
++ skb->data, skb->len, &bytes_sent,
++ urb->transfer_buffer, 16);
+ skb_pull(skb, bytes_sent);
+
+ if(len < 16)
+@@ -673,7 +673,7 @@
+ usb_d_out_complete, adapter);
+ }
+
+-static void st5481_release_d_out(struct st5481_adapter *adapter)
++static void __devexit st5481_release_d_out(struct st5481_adapter *adapter)
+ {
+ struct st5481_d_out *d_out = &adapter->d_out;
+
+@@ -723,7 +723,7 @@
+ return retval;
+ }
+
+-void st5481_release_d(struct st5481_adapter *adapter)
++void __devexit st5481_release_d(struct st5481_adapter *adapter)
+ {
+ DBG(2,"");
+
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/st5481_init.c linux-2.4.29/drivers/isdn/hisax/st5481_init.c
+--- linux-2.4.29.old/drivers/isdn/hisax/st5481_init.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/st5481_init.c 2005-03-22 15:06:48.268754816 +0100
+@@ -14,6 +14,7 @@
+ * TODO:
+ *
+ * b layer1 delay?
++ * hdlc as module
+ * hotplug / unregister issues
+ * mod_inc/dec_use_count
+ * unify parts of d/b channel usb handling
+@@ -177,7 +178,7 @@
+ static struct usb_driver st5481_usb_driver = {
+ name: "st5481_usb",
+ probe: probe_st5481,
+- disconnect: __devexit_p(disconnect_st5481),
++ disconnect: disconnect_st5481,
+ id_table: st5481_ids,
+ };
+
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/st5481_usb.c linux-2.4.29/drivers/isdn/hisax/st5481_usb.c
+--- linux-2.4.29.old/drivers/isdn/hisax/st5481_usb.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/st5481_usb.c 2005-03-22 15:06:48.284752384 +0100
+@@ -41,9 +41,9 @@
+ (unsigned char *)&ctrl->msg_fifo.data[r_index];
+
+ DBG(1,"request=0x%02x,value=0x%04x,index=%x",
+- ((struct ctrl_msg *)urb->setup_packet)->dr.bRequest,
+- ((struct ctrl_msg *)urb->setup_packet)->dr.wValue,
+- ((struct ctrl_msg *)urb->setup_packet)->dr.wIndex);
++ ((struct ctrl_msg *)urb->setup_packet)->dr.request,
++ ((struct ctrl_msg *)urb->setup_packet)->dr.value,
++ ((struct ctrl_msg *)urb->setup_packet)->dr.index);
+
+ // Prepare the URB
+ urb->dev = adapter->usb_dev;
+@@ -69,11 +69,11 @@
+ }
+ ctrl_msg = &ctrl->msg_fifo.data[w_index];
+
+- ctrl_msg->dr.bRequestType = requesttype;
+- ctrl_msg->dr.bRequest = request;
+- ctrl_msg->dr.wValue = cpu_to_le16p(&value);
+- ctrl_msg->dr.wIndex = cpu_to_le16p(&index);
+- ctrl_msg->dr.wLength = 0;
++ ctrl_msg->dr.requesttype = requesttype;
++ ctrl_msg->dr.request = request;
++ ctrl_msg->dr.value = cpu_to_le16p(&value);
++ ctrl_msg->dr.index = cpu_to_le16p(&index);
++ ctrl_msg->dr.length = 0;
+ ctrl_msg->complete = complete;
+ ctrl_msg->context = context;
+
+@@ -140,17 +140,17 @@
+
+ ctrl_msg = (struct ctrl_msg *)urb->setup_packet;
+
+- if (ctrl_msg->dr.bRequest == USB_REQ_CLEAR_FEATURE) {
++ if (ctrl_msg->dr.request == USB_REQ_CLEAR_FEATURE) {
+ /* Special case handling for pipe reset */
+- le16_to_cpus(&ctrl_msg->dr.wIndex);
++ le16_to_cpus(&ctrl_msg->dr.index);
+ usb_endpoint_running(adapter->usb_dev,
+- ctrl_msg->dr.wIndex & ~USB_DIR_IN,
+- (ctrl_msg->dr.wIndex & USB_DIR_IN) == 0);
++ ctrl_msg->dr.index & ~USB_DIR_IN,
++ (ctrl_msg->dr.index & USB_DIR_IN) == 0);
+
+ /* toggle is reset on clear */
+ usb_settoggle(adapter->usb_dev,
+- ctrl_msg->dr.wIndex & ~USB_DIR_IN,
+- (ctrl_msg->dr.wIndex & USB_DIR_IN) == 0,
++ ctrl_msg->dr.index & ~USB_DIR_IN,
++ (ctrl_msg->dr.index & USB_DIR_IN) == 0,
+ 0);
+
+
+@@ -235,7 +235,7 @@
+ struct usb_interface_descriptor *altsetting;
+ struct usb_endpoint_descriptor *endpoint;
+ int status;
+- struct urb *urb;
++ urb_t *urb;
+ u_char *buf;
+
+ DBG(1,"");
+@@ -307,7 +307,7 @@
+ * Release buffers and URBs for the interrupt and control
+ * endpoint.
+ */
+-void st5481_release_usb(struct st5481_adapter *adapter)
++void __devexit st5481_release_usb(struct st5481_adapter *adapter)
+ {
+ struct st5481_intr *intr = &adapter->intr;
+ struct st5481_ctrl *ctrl = &adapter->ctrl;
+@@ -443,7 +443,7 @@
+ return retval;
+ }
+
+-void st5481_release_isocpipes(struct urb* urb[2])
++void __devexit st5481_release_isocpipes(struct urb* urb[2])
+ {
+ int j;
+
+@@ -484,18 +484,16 @@
+ ptr = urb->transfer_buffer;
+ while (len > 0) {
+ if (in->mode == L1_MODE_TRANS) {
+- /* swap rx bytes to get hearable audio */
+- register unsigned char *dest = in->rcvbuf;
++ memcpy(in->rcvbuf, ptr, len);
+ status = len;
+- for (; len; len--)
+- *dest++ = isdnhdlc_bit_rev_tab[*ptr++];
++ len = 0;
+ } else {
+- status = isdnhdlc_decode(&in->hdlc_state, ptr, len, &count,
+- in->rcvbuf, in->bufsize);
++ status = hdlc_decode(&in->hdlc_state, ptr, len, &count,
++ in->rcvbuf, in->bufsize);
+ ptr += count;
+ len -= count;
+ }
+-
++
+ if (status > 0) {
+ // Good frame received
+ DBG(4,"count=%d",status);
+@@ -549,7 +547,7 @@
+ return retval;
+ }
+
+-void st5481_release_in(struct st5481_in *in)
++void __devexit st5481_release_in(struct st5481_in *in)
+ {
+ DBG(2,"");
+
+@@ -562,8 +560,7 @@
+ */
+ int st5481_isoc_flatten(struct urb *urb)
+ {
+- struct iso_packet_descriptor *pipd;
+- struct iso_packet_descriptor *pend;
++ piso_packet_descriptor_t pipd,pend;
+ unsigned char *src,*dst;
+ unsigned int len;
+
+@@ -624,10 +621,15 @@
+
+ if (in->mode != L1_MODE_NULL) {
+ if (in->mode != L1_MODE_TRANS)
+- isdnhdlc_rcv_init(&in->hdlc_state,
+- in->mode == L1_MODE_HDLC_56K);
++ hdlc_rcv_init(&in->hdlc_state,
++ in->mode == L1_MODE_HDLC_56K);
+
+ st5481_usb_pipe_reset(in->adapter, in->ep, NULL, NULL);
++#if 0
++ st5481_usb_device_ctrl_msg(in->adapter, in->counter,
++ in->packet_size,
++ st5481_start_rcv, in);
++#endif
+ st5481_usb_device_ctrl_msg(in->adapter, in->counter,
+ in->packet_size,
+ NULL, NULL);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/tei.c linux-2.4.29/drivers/isdn/hisax/tei.c
+--- linux-2.4.29.old/drivers/isdn/hisax/tei.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/tei.c 2005-03-22 15:06:48.316747520 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tei.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: tei.c,v 2.20 2001/09/24 13:22:57 kai Exp $
+ *
+ * Author Karsten Keil
+ * based on the teles driver from Jan den Ouden
+@@ -21,7 +21,7 @@
+ #include <linux/init.h>
+ #include <linux/random.h>
+
+-const char *tei_revision = "$Revision: 1.1.4.1 $";
++const char *tei_revision = "$Revision: 2.20 $";
+
+ #define ID_REQUEST 1
+ #define ID_ASSIGNED 2
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/teleint.c linux-2.4.29/drivers/isdn/hisax/teleint.c
+--- linux-2.4.29.old/drivers/isdn/hisax/teleint.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/teleint.c 2005-03-22 15:06:48.330745392 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: teleint.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: teleint.c,v 1.16 2001/09/24 13:22:57 kai Exp $
+ *
+ * low level stuff for TeleInt isdn cards
+ *
+@@ -19,7 +19,7 @@
+
+ extern const char *CardType[];
+
+-const char *TeleInt_revision = "$Revision: 1.1.4.1 $";
++const char *TeleInt_revision = "$Revision: 1.16 $";
+
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/teles0.c linux-2.4.29/drivers/isdn/hisax/teles0.c
+--- linux-2.4.29.old/drivers/isdn/hisax/teles0.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/teles0.c 2005-03-22 15:06:48.348742656 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: teles0.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: teles0.c,v 2.15 2001/09/24 13:22:57 kai Exp $
+ *
+ * low level stuff for Teles Memory IO isdn cards
+ *
+@@ -24,7 +24,7 @@
+
+ extern const char *CardType[];
+
+-const char *teles0_revision = "$Revision: 1.1.4.1 $";
++const char *teles0_revision = "$Revision: 2.15 $";
+
+ #define TELES_IOMEM_SIZE 0x400
+ #define byteout(addr,val) outb(val,addr)
+@@ -189,8 +189,10 @@
+ {
+ if (cs->hw.teles0.cfg_reg)
+ release_region(cs->hw.teles0.cfg_reg, 8);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ iounmap((unsigned char *)cs->hw.teles0.membase);
+ release_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE);
++#endif
+ }
+
+ static int
+@@ -327,6 +329,7 @@
+ /* 16.0 and 8.0 designed for IOM1 */
+ test_and_set_bit(HW_IOM1, &cs->HW_Flags);
+ cs->hw.teles0.phymem = card->para[1];
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ if (check_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE)) {
+ printk(KERN_WARNING
+ "HiSax: %s memory region %lx-%lx already in use\n",
+@@ -342,6 +345,9 @@
+ }
+ cs->hw.teles0.membase =
+ (unsigned long) ioremap(cs->hw.teles0.phymem, TELES_IOMEM_SIZE);
++#else
++ cs->hw.teles0.membase = cs->hw.teles0.phymem;
++#endif
+ printk(KERN_INFO
+ "HiSax: %s config irq:%d mem:0x%lX cfg:0x%X\n",
+ CardType[cs->typ], cs->irq,
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/teles3.c linux-2.4.29/drivers/isdn/hisax/teles3.c
+--- linux-2.4.29.old/drivers/isdn/hisax/teles3.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/teles3.c 2005-03-22 15:06:48.367739768 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: teles3.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: teles3.c,v 2.19 2001/09/24 13:22:57 kai Exp $
+ *
+ * low level stuff for Teles 16.3 & PNP isdn cards
+ *
+@@ -15,14 +15,13 @@
+ */
+ #define __NO_VERSION__
+ #include <linux/init.h>
+-#include <linux/isapnp.h>
+ #include "hisax.h"
+ #include "isac.h"
+ #include "hscx.h"
+ #include "isdnl1.h"
+
+ extern const char *CardType[];
+-const char *teles3_revision = "$Revision: 1.1.4.1 $";
++const char *teles3_revision = "$Revision: 2.19 $";
+
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+@@ -255,24 +254,6 @@
+ return(0);
+ }
+
+-#ifdef __ISAPNP__
+-static struct isapnp_device_id teles_ids[] __initdata = {
+- { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
+- ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
+- (unsigned long) "Teles 16.3 PnP" },
+- { ISAPNP_VENDOR('C', 'T', 'X'), ISAPNP_FUNCTION(0x0),
+- ISAPNP_VENDOR('C', 'T', 'X'), ISAPNP_FUNCTION(0x0),
+- (unsigned long) "Creatix 16.3 PnP" },
+- { ISAPNP_VENDOR('C', 'P', 'Q'), ISAPNP_FUNCTION(0x1002),
+- ISAPNP_VENDOR('C', 'P', 'Q'), ISAPNP_FUNCTION(0x1002),
+- (unsigned long) "Compaq ISDN S0" },
+- { 0, }
+-};
+-
+-static struct isapnp_device_id *tdev = &teles_ids[0];
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+-
+ int __devinit
+ setup_teles3(struct IsdnCard *card)
+ {
+@@ -286,47 +267,6 @@
+ && (cs->typ != ISDN_CTYPE_TELESPCMCIA) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA))
+ return (0);
+
+-#ifdef __ISAPNP__
+- if (!card->para[1] && isapnp_present()) {
+- struct pci_bus *pb;
+- struct pci_dev *pd;
+-
+- while(tdev->card_vendor) {
+- if ((pb = isapnp_find_card(tdev->card_vendor,
+- tdev->card_device, pnp_c))) {
+- pnp_c = pb;
+- pd = NULL;
+- if ((pd = isapnp_find_dev(pnp_c,
+- tdev->vendor, tdev->function, pd))) {
+- printk(KERN_INFO "HiSax: %s detected\n",
+- (char *)tdev->driver_data);
+- pd->prepare(pd);
+- pd->deactivate(pd);
+- pd->activate(pd);
+- card->para[3] = pd->resource[2].start;
+- card->para[2] = pd->resource[1].start;
+- card->para[1] = pd->resource[0].start;
+- card->para[0] = pd->irq_resource[0].start;
+- if (!card->para[0] || !card->para[1] || !card->para[2]) {
+- printk(KERN_ERR "Teles PnP:some resources are missing %ld/%lx/%lx\n",
+- card->para[0], card->para[1], card->para[2]);
+- pd->deactivate(pd);
+- return(0);
+- }
+- break;
+- } else {
+- printk(KERN_ERR "Teles PnP: PnP error card found, no device\n");
+- }
+- }
+- tdev++;
+- pnp_c=NULL;
+- }
+- if (!tdev->card_vendor) {
+- printk(KERN_INFO "Teles PnP: no ISAPnP card found\n");
+- return(0);
+- }
+- }
+-#endif
+ if (cs->typ == ISDN_CTYPE_16_3) {
+ cs->hw.teles3.cfg_reg = card->para[1];
+ switch (cs->hw.teles3.cfg_reg) {
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/telespci.c linux-2.4.29/drivers/isdn/hisax/telespci.c
+--- linux-2.4.29.old/drivers/isdn/hisax/telespci.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/telespci.c 2005-03-22 15:06:48.382737488 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: telespci.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: telespci.c,v 2.23 2001/09/24 13:22:57 kai Exp $
+ *
+ * low level stuff for Teles PCI isdn cards
+ *
+@@ -20,9 +20,10 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+
+ extern const char *CardType[];
+-const char *telespci_revision = "$Revision: 1.1.4.1 $";
++const char *telespci_revision = "$Revision: 2.23 $";
+
+ #define ZORAN_PO_RQ_PEN 0x02000000
+ #define ZORAN_PO_WR 0x00800000
+@@ -307,10 +308,10 @@
+ printk(KERN_WARNING "Teles: No IRQ for PCI card found\n");
+ return(0);
+ }
+- cs->hw.teles0.membase = (u_long) ioremap(pci_resource_start(dev_tel, 0),
++ cs->hw.teles0.membase = (u_long) ioremap(pci_resource_start_mem(dev_tel, 0),
+ PAGE_SIZE);
+ printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n",
+- pci_resource_start(dev_tel, 0), dev_tel->irq);
++ pci_resource_start_mem(dev_tel, 0), dev_tel->irq);
+ } else {
+ printk(KERN_WARNING "TelesPCI: No PCI card found\n");
+ return(0);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/w6692.c linux-2.4.29/drivers/isdn/hisax/w6692.c
+--- linux-2.4.29.old/drivers/isdn/hisax/w6692.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/w6692.c 2005-03-22 15:06:48.398735056 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: w6692.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: w6692.c,v 1.18 2001/09/24 13:22:57 kai Exp $
+ *
+ * Winbond W6692 specific routines
+ *
+@@ -18,6 +18,7 @@
+ #include "isdnl1.h"
+ #include <linux/interrupt.h>
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+
+ /* table entry in the PCI devices list */
+ typedef struct {
+@@ -29,20 +30,14 @@
+
+ static const PCI_ENTRY id_list[] =
+ {
+- {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, "Winbond", "W6692"},
+ {PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, "Dynalink/AsusCom", "IS64PH"},
+- {0, 0, "U.S.Robotics", "ISDN PCI Card TA"}
++ {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, "Winbond", "W6692"},
++ {0, 0, NULL, NULL}
+ };
+
+-#define W6692_SV_USR 0x16ec
+-#define W6692_SD_USR 0x3409
+-#define W6692_WINBOND 0
+-#define W6692_DYNALINK 1
+-#define W6692_USR 2
+-
+ extern const char *CardType[];
+
+-const char *w6692_revision = "$Revision: 1.1.4.1 $";
++const char *w6692_revision = "$Revision: 1.18 $";
+
+ #define DBUSY_TIMER_VALUE 80
+
+@@ -675,6 +670,16 @@
+ static void
+ DC_Close_W6692(struct IsdnCardState *cs)
+ {
++#if 0
++ if (cs->dc.w6692.mon_rx) {
++ kfree(cs->dc.w6692.mon_rx);
++ cs->dc.w6692.mon_rx = NULL;
++ }
++ if (cs->dc.w6692.mon_tx) {
++ kfree(cs->dc.w6692.mon_tx);
++ cs->dc.w6692.mon_tx = NULL;
++ }
++#endif
+ }
+
+ static void
+@@ -865,38 +870,31 @@
+ return (0);
+ }
+
+-void resetW6692(struct IsdnCardState *cs)
+-{
+- cs->writeW6692(cs, W_D_CTL, W_D_CTL_SRST);
+- schedule_timeout((10*HZ)/1000);
+- cs->writeW6692(cs, W_D_CTL, 0x00);
+- schedule_timeout((10*HZ)/1000);
+- cs->writeW6692(cs, W_IMASK, 0xff);
+- cs->writeW6692(cs, W_D_SAM, 0xff);
+- cs->writeW6692(cs, W_D_TAM, 0xff);
+- cs->writeW6692(cs, W_D_EXIM, 0x00);
+- cs->writeW6692(cs, W_D_MODE, W_D_MODE_RACT);
+- cs->writeW6692(cs, W_IMASK, 0x18);
+- if (cs->subtyp == W6692_USR) {
+- /* seems that USR implemented some power control features
+- * Pin 79 is connected to the oscilator circuit so we
+- * have to handle it here
+- */
+- cs->writeW6692(cs, W_PCTL, 0x80);
+- cs->writeW6692(cs, W_XDATA, 0x00);
+- }
+-}
+-
+ void __init initW6692(struct IsdnCardState *cs, int part)
+ {
+ if (part & 1) {
+ cs->tqueue.routine = (void *) (void *) W6692_bh;
+ cs->setstack_d = setstack_W6692;
+ cs->DC_Close = DC_Close_W6692;
++#if 0
++ cs->dc.w6692.mon_tx = NULL;
++ cs->dc.w6692.mon_rx = NULL;
++#endif
+ cs->dbusytimer.function = (void *) dbusy_timer_handler;
+ cs->dbusytimer.data = (long) cs;
+ init_timer(&cs->dbusytimer);
+- resetW6692(cs);
++
++ cs->writeW6692(cs, W_D_CTL, W_D_CTL_SRST);
++ cs->writeW6692(cs, W_D_CTL, 0x00);
++ cs->writeW6692(cs, W_IMASK, 0xff);
++#if 0
++ cs->dc.w6692.mocr = 0xaa;
++#endif
++ cs->writeW6692(cs, W_D_SAM, 0xff);
++ cs->writeW6692(cs, W_D_TAM, 0xff);
++ cs->writeW6692(cs, W_D_EXIM, 0x00);
++ cs->writeW6692(cs, W_D_MODE, W_D_MODE_RACT);
++ cs->writeW6692(cs, W_IMASK, 0x18);
+ ph_command(cs, W_L1CMD_RST);
+ cs->dc.w6692.ph_state = W_L1CMD_RST;
+ W6692_new_ph(cs);
+@@ -963,14 +961,9 @@
+ {
+ switch (mt) {
+ case CARD_RESET:
+- resetW6692(cs);
+ return (0);
+ case CARD_RELEASE:
+- cs->writeW6692(cs, W_IMASK, 0xff);
+ release_region(cs->hw.w6692.iobase, 256);
+- if (cs->subtyp == W6692_USR) {
+- cs->writeW6692(cs, W_XDATA, 0x04);
+- }
+ return (0);
+ case CARD_INIT:
+ initW6692(cs, 3);
+@@ -1013,7 +1006,6 @@
+ if (dev_w6692) {
+ if (pci_enable_device(dev_w6692))
+ continue;
+- cs->subtyp = id_idx;
+ break;
+ }
+ id_idx++;
+@@ -1023,14 +1015,7 @@
+ pci_irq = dev_w6692->irq;
+ /* I think address 0 is allways the configuration area */
+ /* and address 1 is the real IO space KKe 03.09.99 */
+- pci_ioaddr = pci_resource_start(dev_w6692, 1);
+- /* USR ISDN PCI card TA need some special handling */
+- if (cs->subtyp == W6692_WINBOND) {
+- if ((W6692_SV_USR == dev_w6692->subsystem_vendor) &&
+- (W6692_SD_USR == dev_w6692->subsystem_device)) {
+- cs->subtyp = W6692_USR;
+- }
+- }
++ pci_ioaddr = pci_resource_start_io(dev_w6692, 1);
+ }
+ if (!found) {
+ printk(KERN_WARNING "W6692: No PCI card found\n");
+@@ -1047,18 +1032,18 @@
+ }
+ cs->hw.w6692.iobase = pci_ioaddr;
+ printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n",
+- id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name,
+- pci_ioaddr, pci_irq);
++ id_list[id_idx].vendor_name, id_list[id_idx].card_name,
++ pci_ioaddr, dev_w6692->irq);
+ if (check_region((cs->hw.w6692.iobase), 256)) {
+ printk(KERN_WARNING
+ "HiSax: %s I/O ports %x-%x already in use\n",
+- id_list[cs->subtyp].card_name,
++ id_list[id_idx].card_name,
+ cs->hw.w6692.iobase,
+ cs->hw.w6692.iobase + 255);
+ return (0);
+ } else {
+ request_region(cs->hw.w6692.iobase, 256,
+- id_list[cs->subtyp].card_name);
++ id_list[id_idx].card_name);
+ }
+ #else
+ printk(KERN_WARNING "HiSax: W6692 and NO_PCI_BIOS\n");
+@@ -1068,7 +1053,7 @@
+
+ printk(KERN_INFO
+ "HiSax: %s config irq:%d I/O:%x\n",
+- id_list[cs->subtyp].card_name, cs->irq,
++ id_list[id_idx].card_name, cs->irq,
+ cs->hw.w6692.iobase);
+
+ cs->readW6692 = &ReadW6692;
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/w6692.h linux-2.4.29/drivers/isdn/hisax/w6692.h
+--- linux-2.4.29.old/drivers/isdn/hisax/w6692.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/w6692.h 2005-03-22 15:06:48.414732624 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: w6692.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: w6692.h,v 1.4 2001/09/24 13:22:57 kai Exp $
+ *
+ * Winbond W6692 specific defines
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/boardergo.c linux-2.4.29/drivers/isdn/hysdn/boardergo.c
+--- linux-2.4.29.old/drivers/isdn/hysdn/boardergo.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/boardergo.c 2005-03-22 15:06:48.468724416 +0100
+@@ -1,27 +1,41 @@
+-/* $Id: boardergo.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
+- *
++/* $Id: boardergo.c,v 1.9 2001/07/19 20:39:51 kai Exp $
++
+ * Linux driver for HYSDN cards, specific routines for ergo type boards.
+ *
+- * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH
+- * Copyright 1999 by Werner Cornelius (werner@titro.de)
+- *
+- * This software may be used and distributed according to the terms
+- * of the GNU General Public License, incorporated herein by reference.
+- *
+ * As all Linux supported cards Champ2, Ergo and Metro2/4 use the same
+ * DPRAM interface and layout with only minor differences all related
+ * stuff is done here, not in separate modules.
+ *
++ * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH
++ *
++ * Copyright 1999 by Werner Cornelius (werner@titro.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, 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.
++ *
+ */
+
++#define __NO_VERSION__
+ #include <linux/config.h>
+-#include <linux/sched.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <asm/io.h>
+ #include <linux/signal.h>
+ #include <linux/kernel.h>
+ #include <linux/ioport.h>
+ #include <linux/interrupt.h>
+ #include <linux/vmalloc.h>
+-#include <asm/io.h>
+
+ #include "hysdn_defs.h"
+ #include "boardergo.h"
+@@ -45,11 +59,10 @@
+ if (!card->irq_enabled)
+ return; /* other device interrupting or irq switched off */
+
+- save_flags(flags);
+- cli(); /* no further irqs allowed */
++ HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+
+ if (!(bytein(card->iobase + PCI9050_INTR_REG) & PCI9050_INTR_REG_STAT1)) {
+- restore_flags(flags); /* restore old state */
++ HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ return; /* no interrupt requested by E1 */
+ }
+ /* clear any pending ints on the board */
+@@ -63,7 +76,7 @@
+ queue_task(&card->irq_queue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+ }
+- restore_flags(flags);
++ HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ } /* ergo_interrupt */
+
+ /******************************************************************************/
+@@ -83,17 +96,15 @@
+ return; /* invalid call */
+
+ dpr = card->dpram; /* point to DPRAM */
++ HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+
+- save_flags(flags);
+- cli();
+ if (card->hw_lock) {
+- restore_flags(flags); /* hardware currently unavailable */
++ HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ return;
+ }
+ card->hw_lock = 1; /* we now lock the hardware */
+
+ do {
+- sti(); /* reenable other ints */
+ again = 0; /* assume loop not to be repeated */
+
+ if (!dpr->ToHyFlag) {
+@@ -113,15 +124,13 @@
+ again = 1; /* restart loop */
+ }
+ } /* a message has arrived for us */
+- cli(); /* no further ints */
+ if (again) {
+ dpr->ToHyInt = 1;
+ dpr->ToPcInt = 1; /* interrupt to E1 for all cards */
+ } else
+ card->hw_lock = 0; /* free hardware again */
+ } while (again); /* until nothing more to do */
+-
+- restore_flags(flags);
++ HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ } /* ergo_irq_bh */
+
+
+@@ -138,8 +147,7 @@
+ #ifdef CONFIG_HYSDN_CAPI
+ hycapi_capi_stop(card);
+ #endif /* CONFIG_HYSDN_CAPI */
+- save_flags(flags);
+- cli();
++ HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+ val = bytein(card->iobase + PCI9050_INTR_REG); /* get actual value */
+ val &= ~(PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1); /* mask irq */
+ byteout(card->iobase + PCI9050_INTR_REG, val);
+@@ -147,8 +155,7 @@
+ byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RESET); /* reset E1 processor */
+ card->state = CARD_STATE_UNUSED;
+ card->err_log_state = ERRLOG_STATE_OFF; /* currently no log active */
+-
+- restore_flags(flags);
++ HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ } /* ergo_stopcard */
+
+ /**************************************************************************/
+@@ -163,20 +170,17 @@
+ card->err_log_state = ERRLOG_STATE_OFF; /* must be off */
+ return;
+ }
+- save_flags(flags);
+- cli();
+-
++ HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+ if (((card->err_log_state == ERRLOG_STATE_OFF) && !on) ||
+ ((card->err_log_state == ERRLOG_STATE_ON) && on)) {
+- restore_flags(flags);
++ HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ return; /* nothing to do */
+ }
+ if (on)
+ card->err_log_state = ERRLOG_STATE_START; /* request start */
+ else
+ card->err_log_state = ERRLOG_STATE_STOP; /* request stop */
+-
+- restore_flags(flags);
++ HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ queue_task(&card->irq_queue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+ } /* ergo_set_errlog_state */
+@@ -245,9 +249,6 @@
+ while (!dpram->ToHyNoDpramErrLog); /* reread volatile register to flush PCI */
+
+ byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RUN); /* start E1 processor */
+- /* the interrupts are still masked */
+-
+- sti();
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */
+
+@@ -282,7 +283,6 @@
+ dst = sp->Data; /* point to data in spool structure */
+ buflen = sp->Len; /* maximum len of spooled data */
+ wr_mirror = sp->WrPtr; /* only once read */
+- sti();
+
+ /* try until all bytes written or error */
+ i = 0x1000; /* timeout value */
+@@ -358,9 +358,7 @@
+
+ if (card->debug_flags & LOG_POF_RECORD)
+ hysdn_addlog(card, "ERGO: pof boot success");
+- save_flags(flags);
+- cli();
+-
++ HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+ card->state = CARD_STATE_RUN; /* now card is running */
+ /* enable the cards interrupt */
+ byteout(card->iobase + PCI9050_INTR_REG,
+@@ -371,8 +369,7 @@
+ dpr->ToPcFlag = 0; /* reset data indicator */
+ dpr->ToHyInt = 1;
+ dpr->ToPcInt = 1; /* interrupt to E1 for all cards */
+-
+- restore_flags(flags);
++ HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ if ((hynet_enable & (1 << card->myid))
+ && (i = hysdn_net_create(card)))
+ {
+@@ -387,7 +384,6 @@
+ #endif /* CONFIG_HYSDN_CAPI */
+ return (0); /* success */
+ } /* data has arrived */
+- sti();
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout((50 * HZ) / 1000); /* Timeout 50ms */
+ } /* wait until timeout */
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/boardergo.h linux-2.4.29/drivers/isdn/hysdn/boardergo.h
+--- linux-2.4.29.old/drivers/isdn/hysdn/boardergo.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/boardergo.h 2005-03-22 15:06:48.485721832 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: boardergo.h,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Linux driver for HYSDN cards, definitions for ergo type boards (buffers..).
+ *
+@@ -10,6 +10,7 @@
+ *
+ */
+
++#include <linux/isdn_compat.h>
+
+ /************************************************/
+ /* defines for the dual port memory of the card */
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hycapi.c linux-2.4.29/drivers/isdn/hysdn/hycapi.c
+--- linux-2.4.29.old/drivers/isdn/hysdn/hycapi.c 2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hycapi.c 2005-03-22 15:06:48.500719552 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hycapi.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Linux driver for HYSDN cards, CAPI2.0-Interface.
+ *
+@@ -29,7 +29,7 @@
+ #include "hysdn_defs.h"
+ #include <linux/kernelcapi.h>
+
+-static char hycapi_revision[]="$Revision: 1.1.4.1 $";
++static char hycapi_revision[]="$Revision$";
+
+ unsigned int hycapi_enable = 0xffffffff;
+ MODULE_PARM(hycapi_enable, "i");
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hysdn_boot.c linux-2.4.29/drivers/isdn/hysdn/hysdn_boot.c
+--- linux-2.4.29.old/drivers/isdn/hysdn/hysdn_boot.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hysdn_boot.c 2005-03-22 15:06:48.516717120 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_boot.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Linux driver for HYSDN cards
+ * specific routines for booting and pof handling
+@@ -143,7 +143,7 @@
+ (boot->pof_recid == TAG_CABSDATA) ? "CABSDATA" : "ABSDATA",
+ datlen, boot->pof_recoffset);
+
+- if ((boot->last_error = card->writebootseq(card, boot->buf.BootBuf, datlen)) < 0)
++ if ((boot->last_error = card->writebootseq(card, boot->buf.BootBuf, datlen) < 0))
+ return (boot->last_error); /* error writing data */
+
+ if (boot->pof_recoffset + datlen >= boot->pof_reclen)
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hysdn_defs.h linux-2.4.29/drivers/isdn/hysdn/hysdn_defs.h
+--- linux-2.4.29.old/drivers/isdn/hysdn/hysdn_defs.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hysdn_defs.h 2005-03-22 15:06:48.533714536 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_defs.h,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id: hysdn_defs.h,v 1.10 2001/09/24 13:23:03 kai Exp $
+ *
+ * Linux driver for HYSDN cards
+ * global definitions and exported vars and functions.
+@@ -19,6 +19,11 @@
+ #include <linux/interrupt.h>
+ #include <linux/tqueue.h>
+ #include <linux/skbuff.h>
++#include <linux/isdn_compat.h>
++#include <linux/spinlock.h>
++
++#define HYSDN_SPIN_LOCK(a,b) spin_lock(a)
++#define HYSDN_SPIN_UNLOCK(a,b) spin_unlock(a)
+
+ /****************************/
+ /* storage type definitions */
+@@ -176,6 +181,7 @@
+ struct tq_struct irq_queue; /* interrupt task queue */
+ uchar volatile irq_enabled; /* interrupt enabled if != 0 */
+ uchar volatile hw_lock; /* hardware is currently locked -> no access */
++ spinlock_t irq_lock;
+
+ /* boot process */
+ void *boot; /* pointer to boot private data */
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hysdn_init.c linux-2.4.29/drivers/isdn/hysdn/hysdn_init.c
+--- linux-2.4.29.old/drivers/isdn/hysdn/hysdn_init.c 2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hysdn_init.c 2005-03-22 15:06:48.551711800 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_init.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Linux driver for HYSDN cards, init functions.
+ *
+@@ -21,6 +21,7 @@
+
+ #include "hysdn_defs.h"
+
++#ifndef COMPAT_HAS_2_2_PCI
+ static struct pci_device_id hysdn_pci_tbl[] __initdata = {
+ {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_METRO},
+ {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2},
+@@ -29,11 +30,12 @@
+ { } /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(pci, hysdn_pci_tbl);
++#endif
+ MODULE_DESCRIPTION("ISDN4Linux: Driver for HYSDN cards");
+ MODULE_AUTHOR("Werner Cornelius");
+ MODULE_LICENSE("GPL");
+
+-static char *hysdn_init_revision = "$Revision: 1.1.4.1 $";
++static char *hysdn_init_revision = "$Revision$";
+ int cardmax; /* number of found cards */
+ hysdn_card *card_root = NULL; /* pointer to first card */
+
+@@ -91,11 +93,11 @@
+ card->myid = cardmax; /* set own id */
+ card->bus = akt_pcidev->bus->number;
+ card->devfn = akt_pcidev->devfn; /* slot + function */
+- card->subsysid = akt_pcidev->subsystem_device;
++ pci_get_sub_system(akt_pcidev,card->subsysid);
+ card->irq = akt_pcidev->irq;
+- card->iobase = pci_resource_start(akt_pcidev, PCI_REG_PLX_IO_BASE);
+- card->plxbase = pci_resource_start(akt_pcidev, PCI_REG_PLX_MEM_BASE);
+- card->membase = pci_resource_start(akt_pcidev, PCI_REG_MEMORY_BASE);
++ card->iobase = pci_resource_start_io(akt_pcidev, PCI_REG_PLX_IO_BASE);
++ card->plxbase = pci_resource_start_mem(akt_pcidev, PCI_REG_PLX_MEM_BASE);
++ card->membase = pci_resource_start_mem(akt_pcidev, PCI_REG_MEMORY_BASE);
+ card->brdtype = BD_NONE; /* unknown */
+ card->debug_flags = DEF_DEB_FLAGS; /* set default debug */
+ card->faxchans = 0; /* default no fax channels */
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hysdn_net.c linux-2.4.29/drivers/isdn/hysdn/hysdn_net.c
+--- linux-2.4.29.old/drivers/isdn/hysdn/hysdn_net.c 2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hysdn_net.c 2005-03-22 15:06:48.567709368 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_net.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Linux driver for HYSDN cards, net (ethernet type) handling routines.
+ *
+@@ -29,7 +29,7 @@
+ MODULE_PARM(hynet_enable, "i");
+
+ /* store the actual version for log reporting */
+-char *hysdn_net_revision = "$Revision: 1.1.4.1 $";
++char *hysdn_net_revision = "$Revision$";
+
+ #define MAX_SKB_BUFFERS 20 /* number of buffers for keeping TX-data */
+
+@@ -45,6 +45,10 @@
+ /* additional vars may be added here */
+ char dev_name[9]; /* our own device name */
+
++#ifdef COMPAT_NO_SOFTNET
++ struct sk_buff *tx_skb; /* buffer for tx operation */
++
++#else
+ /* Tx control lock. This protects the transmit buffer ring
+ * state along with the "tx full" state of the driver. This
+ * means all netif_queue flow control actions are protected
+@@ -56,6 +60,7 @@
+ int sk_count; /* number of buffers currently in ring */
+
+ int is_open; /* flag controlling module locking */
++#endif
+ }; /* net_local */
+
+
+@@ -83,11 +88,19 @@
+ hysdn_card *card = dev->priv;
+ int i;
+
++#ifdef COMPAT_NO_SOFTNET
++ dev->tbusy = 0; /* non busy state */
++ dev->interrupt = 0;
++ if (!dev->start)
++ MOD_INC_USE_COUNT; /* increment only if device is down */
++ dev->start = 1; /* and started */
++#else
+ if (!((struct net_local *) dev)->is_open)
+ MOD_INC_USE_COUNT; /* increment only if interface is actually down */
+ ((struct net_local *) dev)->is_open = 1; /* device actually open */
+
+ netif_start_queue(dev); /* start tx-queueing */
++#endif
+
+ /* Fill in the MAC-level header (if not already set) */
+ if (!card->mac_addr[0]) {
+@@ -104,6 +117,7 @@
+ return (0);
+ } /* net_open */
+
++#ifndef COMPAT_NO_SOFTNET
+ /*******************************************/
+ /* flush the currently occupied tx-buffers */
+ /* must only be called when device closed */
+@@ -119,6 +133,7 @@
+ nl->sk_count--;
+ }
+ } /* flush_tx_buffers */
++#endif
+
+
+ /*********************************************************************/
+@@ -129,6 +144,15 @@
+ net_close(struct net_device *dev)
+ {
+
++#ifdef COMPAT_NO_SOFTNET
++ dev->tbusy = 1; /* we are busy */
++
++ if (dev->start)
++ MOD_DEC_USE_COUNT; /* dec only if device has been active */
++
++ dev->start = 0; /* and not started */
++
++#else
+ netif_stop_queue(dev); /* disable queueing */
+
+ if (((struct net_local *) dev)->is_open)
+@@ -136,9 +160,52 @@
+ ((struct net_local *) dev)->is_open = 0;
+ flush_tx_buffers((struct net_local *) dev);
+
++#endif
+ return (0); /* success */
+ } /* net_close */
+
++#ifdef COMPAT_NO_SOFTNET
++/************************************/
++/* send a packet on this interface. */
++/* only for kernel versions < 2.3.33 */
++/************************************/
++static int
++net_send_packet(struct sk_buff *skb, struct net_device *dev)
++{
++ struct net_local *lp = (struct net_local *) dev;
++
++ if (dev->tbusy) {
++ /*
++ * If we get here, some higher level has decided we are broken.
++ * There should really be a "kick me" function call instead.
++ * As ISDN may have higher timeouts than real ethernet 10s timeout
++ */
++ int tickssofar = jiffies - dev->trans_start;
++ if (tickssofar < (10000 * HZ) / 1000)
++ return 1;
++ printk(KERN_WARNING "%s: transmit timed out. \n", dev->name);
++ dev->tbusy = 0;
++ dev->trans_start = jiffies;
++ }
++ /*
++ * Block a timer-based transmit from overlapping. This could better be
++ * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
++ */
++ if (test_and_set_bit(0, (void *) &dev->tbusy) != 0)
++ printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
++
++ else {
++ lp->stats.tx_bytes += skb->len;
++ dev->trans_start = jiffies;
++ lp->tx_skb = skb; /* remember skb pointer */
++ queue_task(&((hysdn_card *) dev->priv)->irq_queue, &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++ }
++
++ return (0); /* success */
++} /* net_send_packet */
++
++#else
+ /************************************/
+ /* send a packet on this interface. */
+ /* new style for kernel >= 2.3.33 */
+@@ -176,6 +243,7 @@
+ return (0); /* success */
+ } /* net_send_packet */
+
++#endif
+
+
+ /***********************************************************************/
+@@ -190,6 +258,15 @@
+ if (!lp)
+ return; /* non existing device */
+
++#ifdef COMPAT_NO_SOFTNET
++ if (lp->tx_skb)
++ dev_kfree_skb(lp->tx_skb); /* free tx pointer */
++ lp->tx_skb = NULL; /* reset pointer */
++
++ lp->stats.tx_packets++;
++ lp->netdev.tbusy = 0;
++ mark_bh(NET_BH); /* Inform upper layers. */
++#else
+
+ if (!lp->sk_count)
+ return; /* error condition */
+@@ -203,6 +280,7 @@
+
+ if (lp->sk_count-- == MAX_SKB_BUFFERS) /* dec usage count */
+ netif_start_queue((struct net_device *) lp);
++#endif
+ } /* hysdn_tx_netack */
+
+ /*****************************************************/
+@@ -250,10 +328,15 @@
+ if (!lp)
+ return (NULL); /* non existing device */
+
++#ifdef COMPAT_NO_SOFTNET
++ return (lp->tx_skb); /* return packet pointer */
++
++#else
+ if (!lp->sk_count)
+ return (NULL); /* nothing available */
+
+ return (lp->skbs[lp->out_idx]); /* next packet to send */
++#endif
+ } /* hysdn_tx_netget */
+
+
+@@ -296,15 +379,21 @@
+ }
+ memset(dev, 0, sizeof(struct net_local)); /* clean the structure */
+
++#ifndef COMPAT_NO_SOFTNET
+ spin_lock_init(&((struct net_local *) dev)->lock);
++#endif
+
+ /* initialise necessary or informing fields */
+ dev->base_addr = card->iobase; /* IO address */
+ dev->irq = card->irq; /* irq */
+ dev->init = net_init; /* the init function of the device */
++#ifdef COMPAT_NO_SOFTNET
++ dev->name = ((struct net_local *) dev)->dev_name; /* device name */
++#else
+ if(dev->name) {
+ strcpy(dev->name, ((struct net_local *) dev)->dev_name);
+ }
++#endif
+ if ((i = register_netdev(dev))) {
+ printk(KERN_WARNING "HYSDN: unable to create network device\n");
+ kfree(dev);
+@@ -333,7 +422,9 @@
+ card->netif = NULL; /* clear out pointer */
+ dev->stop(dev); /* close the device */
+
++#ifndef COMPAT_NO_SOFTNET
+ flush_tx_buffers((struct net_local *) dev); /* empty buffers */
++#endif
+
+ unregister_netdev(dev); /* release the device */
+ kfree(dev); /* release the memory allocated */
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hysdn_pof.h linux-2.4.29/drivers/isdn/hysdn/hysdn_pof.h
+--- linux-2.4.29.old/drivers/isdn/hysdn/hysdn_pof.h 2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hysdn_pof.h 2005-03-22 15:06:48.583706936 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_pof.h,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Linux driver for HYSDN cards, definitions used for handling pof-files.
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hysdn_procconf.c linux-2.4.29/drivers/isdn/hysdn/hysdn_procconf.c
+--- linux-2.4.29.old/drivers/isdn/hysdn/hysdn_procconf.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hysdn_procconf.c 2005-03-22 15:06:48.598704656 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_procconf.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Linux driver for HYSDN cards, /proc/net filesystem dir and conf functions.
+ *
+@@ -17,11 +17,13 @@
+ #include <linux/poll.h>
+ #include <linux/proc_fs.h>
+ #include <linux/pci.h>
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+ #include <linux/smp_lock.h>
++#endif
+
+ #include "hysdn_defs.h"
+
+-static char *hysdn_procconf_revision = "$Revision: 1.1.4.1 $";
++static char *hysdn_procconf_revision = "$Revision$";
+
+ #define INFO_OUT_LEN 80 /* length of info line including lf */
+
+@@ -212,32 +214,29 @@
+ static ssize_t
+ hysdn_conf_read(struct file *file, char *buf, size_t count, loff_t * off)
+ {
+- loff_t pos = *off;
+ char *cp;
+ int i;
+
+ if (off != &file->f_pos) /* fs error check */
+ return -ESPIPE;
+
+- if (!(file->f_mode & FMODE_READ))
+- return -EPERM;
+-
+- if (!(cp = file->private_data))
+- return (-EFAULT); /* should never happen */
+-
+- i = strlen(cp); /* get total string length */
+-
+- if (pos != (unsigned)pos || pos >= i)
+- return 0;
+-
+- /* still bytes to transfer */
+- cp += pos; /* point to desired data offset */
+- i -= pos; /* remaining length */
+- if (i > count)
+- i = count; /* limit length to transfer */
+- if (copy_to_user(buf, cp, i))
+- return (-EFAULT); /* copy error */
+- *off = pos + i; /* adjust offset */
++ if (file->f_mode & FMODE_READ) {
++ if (!(cp = file->private_data))
++ return (-EFAULT); /* should never happen */
++ i = strlen(cp); /* get total string length */
++ if (*off < i) {
++ /* still bytes to transfer */
++ cp += *off; /* point to desired data offset */
++ i -= *off; /* remaining length */
++ if (i > count)
++ i = count; /* limit length to transfer */
++ if (copy_to_user(buf, cp, i))
++ return (-EFAULT); /* copy error */
++ *off += i; /* adjust offset */
++ } else
++ return (0);
++ } else
++ return (-EPERM); /* no permission to read */
+
+ return (i);
+ } /* hysdn_conf_read */
+@@ -254,7 +253,11 @@
+ char *cp, *tmp;
+
+ /* now search the addressed card */
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++ MOD_INC_USE_COUNT;
++#else
+ lock_kernel();
++#endif
+ card = card_root;
+ while (card) {
+ pd = card->procconf;
+@@ -263,7 +266,11 @@
+ card = card->next; /* search next entry */
+ }
+ if (!card) {
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++ MOD_DEC_USE_COUNT;
++#else
+ unlock_kernel();
++#endif
+ return (-ENODEV); /* device is unknown/invalid */
+ }
+ if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
+@@ -274,7 +281,11 @@
+ /* write only access -> write boot file or conf line */
+
+ if (!(cnf = kmalloc(sizeof(struct conf_writedata), GFP_KERNEL))) {
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++ MOD_DEC_USE_COUNT;
++#else
+ unlock_kernel();
++#endif
+ return (-EFAULT);
+ }
+ cnf->card = card;
+@@ -286,7 +297,11 @@
+ /* read access -> output card info data */
+
+ if (!(tmp = (char *) kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) {
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++ MOD_DEC_USE_COUNT;
++#else
+ unlock_kernel();
++#endif
+ return (-EFAULT); /* out of memory */
+ }
+ filep->private_data = tmp; /* start of string */
+@@ -320,10 +335,16 @@
+ *cp++ = '\n';
+ *cp = 0; /* end of string */
+ } else { /* simultaneous read/write access forbidden ! */
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++ MOD_DEC_USE_COUNT;
++#else
+ unlock_kernel();
++#endif
+ return (-EPERM); /* no permission this time */
+ }
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+ unlock_kernel();
++#endif
+ return (0);
+ } /* hysdn_conf_open */
+
+@@ -338,7 +359,9 @@
+ int retval = 0;
+ struct proc_dir_entry *pd;
+
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+ lock_kernel();
++#endif
+ /* search the addressed card */
+ card = card_root;
+ while (card) {
+@@ -348,7 +371,9 @@
+ card = card->next; /* search next entry */
+ }
+ if (!card) {
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+ unlock_kernel();
++#endif
+ return (-ENODEV); /* device is unknown/invalid */
+ }
+ if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
+@@ -371,7 +396,11 @@
+ if (filep->private_data)
+ kfree(filep->private_data); /* release memory */
+ }
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++ MOD_DEC_USE_COUNT;
++#else
+ unlock_kernel();
++#endif
+ return (retval);
+ } /* hysdn_conf_close */
+
+@@ -387,6 +416,9 @@
+ release: hysdn_conf_close,
+ };
+
++#ifdef COMPAT_NO_SOFTNET
++static struct inode_operations conf_inode_operations;
++#endif
+ /*****************************/
+ /* hysdn subdir in /proc/net */
+ /*****************************/
+@@ -415,8 +447,17 @@
+ if ((card->procconf = (void *) create_proc_entry(conf_name,
+ S_IFREG | S_IRUGO | S_IWUSR,
+ hysdn_proc_entry)) != NULL) {
++#ifdef COMPAT_NO_SOFTNET
++ memset(&conf_inode_operations, 0, sizeof(struct inode_operations));
++ conf_inode_operations.default_file_ops = &conf_fops;
++
++ ((struct proc_dir_entry *) card->procconf)->ops = &conf_inode_operations;
++#else
+ ((struct proc_dir_entry *) card->procconf)->proc_fops = &conf_fops;
++#ifdef COMPAT_HAS_FILEOP_OWNER
+ ((struct proc_dir_entry *) card->procconf)->owner = THIS_MODULE;
++#endif
++#endif
+ hysdn_proclog_init(card); /* init the log file entry */
+ }
+ card = card->next; /* next entry */
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hysdn_proclog.c linux-2.4.29/drivers/isdn/hysdn/hysdn_proclog.c
+--- linux-2.4.29.old/drivers/isdn/hysdn/hysdn_proclog.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hysdn_proclog.c 2005-03-22 15:06:48.613702376 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_proclog.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Linux driver for HYSDN cards, /proc/net filesystem log functions.
+ *
+@@ -16,7 +16,9 @@
+ #include <linux/poll.h>
+ #include <linux/proc_fs.h>
+ #include <linux/pci.h>
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+ #include <linux/smp_lock.h>
++#endif
+
+ #include "hysdn_defs.h"
+
+@@ -115,8 +117,7 @@
+ strcpy(ib->log_start, cp); /* set output string */
+ ib->next = NULL;
+ ib->proc_ctrl = pd; /* point to own control structure */
+- save_flags(flags);
+- cli();
++ HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+ ib->usage_cnt = pd->if_used;
+ if (!pd->log_head)
+ pd->log_head = ib; /* new head */
+@@ -124,7 +125,7 @@
+ pd->log_tail->next = ib; /* follows existing messages */
+ pd->log_tail = ib; /* new tail */
+ i = pd->del_lock++; /* get lock state */
+- restore_flags(flags);
++ HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+
+ /* delete old entrys */
+ if (!i)
+@@ -210,7 +211,6 @@
+ word ino;
+ struct procdata *pd = NULL;
+ hysdn_card *card;
+- loff_t pos = *off;
+
+ if (!*((struct log_data **) file->private_data)) {
+ if (file->f_flags & O_NONBLOCK)
+@@ -235,11 +235,11 @@
+ return (0);
+
+ inf->usage_cnt--; /* new usage count */
+- file->private_data = &inf->next; /* next structure */
++ (struct log_data **) file->private_data = &inf->next; /* next structure */
+ if ((len = strlen(inf->log_start)) <= count) {
+ if (copy_to_user(buf, inf->log_start, len))
+ return -EFAULT;
+- *off = pos + len;
++ file->f_pos += len;
+ return (len);
+ }
+ return (0);
+@@ -255,7 +255,11 @@
+ struct procdata *pd = NULL;
+ ulong flags;
+
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++ MOD_INC_USE_COUNT;
++#else
+ lock_kernel();
++#endif
+ card = card_root;
+ while (card) {
+ pd = card->proclog;
+@@ -264,7 +268,11 @@
+ card = card->next; /* search next entry */
+ }
+ if (!card) {
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++ MOD_DEC_USE_COUNT;
++#else
+ unlock_kernel();
++#endif
+ return (-ENODEV); /* device is unknown/invalid */
+ }
+ filep->private_data = card; /* remember our own card */
+@@ -274,19 +282,24 @@
+ } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
+
+ /* read access -> log/debug read */
+- save_flags(flags);
+- cli();
++ HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+ pd->if_used++;
+ if (pd->log_head)
+- filep->private_data = &(pd->log_tail->next);
++ (struct log_data **) filep->private_data = &(pd->log_tail->next);
+ else
+- filep->private_data = &(pd->log_head);
+- restore_flags(flags);
++ (struct log_data **) filep->private_data = &(pd->log_head);
++ HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ } else { /* simultaneous read/write access forbidden ! */
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++ MOD_DEC_USE_COUNT;
++#else
+ unlock_kernel();
++#endif
+ return (-EPERM); /* no permission this time */
+ }
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+ unlock_kernel();
++#endif
+ return (0);
+ } /* hysdn_log_open */
+
+@@ -306,7 +319,9 @@
+ int flags, retval = 0;
+
+
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+ lock_kernel();
++#endif
+ if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
+ /* write only access -> write debug level written */
+ retval = 0; /* success */
+@@ -314,8 +329,7 @@
+ /* read access -> log/debug read, mark one further file as closed */
+
+ pd = NULL;
+- save_flags(flags);
+- cli();
++ HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+ inf = *((struct log_data **) filep->private_data); /* get first log entry */
+ if (inf)
+ pd = (struct procdata *) inf->proc_ctrl; /* still entries there */
+@@ -338,7 +352,7 @@
+ inf->usage_cnt--; /* decrement usage count for buffers */
+ inf = inf->next;
+ }
+- restore_flags(flags);
++ HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+
+ if (pd)
+ if (pd->if_used <= 0) /* delete buffers if last file closed */
+@@ -348,7 +362,11 @@
+ kfree(inf);
+ }
+ } /* read access */
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++ MOD_DEC_USE_COUNT;
++#else
+ unlock_kernel();
++#endif
+
+ return (retval);
+ } /* hysdn_log_close */
+@@ -400,6 +418,9 @@
+ release: hysdn_log_close,
+ };
+
++#ifdef COMPAT_NO_SOFTNET
++struct inode_operations log_inode_operations;
++#endif
+
+ /***********************************************************************************/
+ /* hysdn_proclog_init is called when the module is loaded after creating the cards */
+@@ -414,10 +435,20 @@
+
+ if ((pd = (struct procdata *) kmalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) {
+ memset(pd, 0, sizeof(struct procdata));
++#ifdef COMPAT_NO_SOFTNET
++ memset(&log_inode_operations, 0, sizeof(struct inode_operations));
++ log_inode_operations.default_file_ops = &log_fops;
++#endif
+ sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid);
+ if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) {
++#ifdef COMPAT_NO_SOFTNET
++ pd->log->ops = &log_inode_operations; /* set new operations table */
++#else
+ pd->log->proc_fops = &log_fops;
++#ifdef COMPAT_HAS_FILEOP_OWNER
+ pd->log->owner = THIS_MODULE;
++#endif
++#endif
+ }
+
+ init_waitqueue_head(&(pd->rd_queue));
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hysdn_sched.c linux-2.4.29/drivers/isdn/hysdn/hysdn_sched.c
+--- linux-2.4.29.old/drivers/isdn/hysdn/hysdn_sched.c 2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hysdn_sched.c 2005-03-22 15:06:48.630699792 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_sched.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id: hysdn_sched.c,v 1.9 2001/09/24 13:23:03 kai Exp $
+ *
+ * Linux driver for HYSDN cards
+ * scheduler routines for handling exchange card <-> pc.
+@@ -12,11 +12,9 @@
+ */
+
+ #include <linux/config.h>
+-#include <linux/sched.h>
+ #include <linux/signal.h>
+ #include <linux/kernel.h>
+ #include <linux/ioport.h>
+-#include <linux/interrupt.h>
+ #include <asm/io.h>
+
+ #include "hysdn_defs.h"
+@@ -151,22 +149,19 @@
+
+ if (card->debug_flags & LOG_SCHED_ASYN)
+ hysdn_addlog(card, "async tx-cfg chan=%d len=%d", chan, strlen(line) + 1);
+-
+- save_flags(flags);
+- cli();
++ HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+ while (card->async_busy) {
+- sti();
+-
++ HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ if (card->debug_flags & LOG_SCHED_ASYN)
+ hysdn_addlog(card, "async tx-cfg delayed");
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */
+ if (!--cnt) {
+- restore_flags(flags);
++ HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ return (-ERR_ASYNC_TIME); /* timed out */
+ }
+- cli();
++ HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+ } /* wait for buffer to become free */
+
+ strcpy(card->async_data, line);
+@@ -177,31 +172,26 @@
+ /* now queue the task */
+ queue_task(&card->irq_queue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+- sti();
+-
++ HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ if (card->debug_flags & LOG_SCHED_ASYN)
+ hysdn_addlog(card, "async tx-cfg data queued");
+
+ cnt++; /* short delay */
+- cli();
+-
++ HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+ while (card->async_busy) {
+- sti();
+-
++ HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ if (card->debug_flags & LOG_SCHED_ASYN)
+ hysdn_addlog(card, "async tx-cfg waiting for tx-ready");
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */
+ if (!--cnt) {
+- restore_flags(flags);
++ HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ return (-ERR_ASYNC_TIME); /* timed out */
+ }
+- cli();
++ HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+ } /* wait for buffer to become free again */
+-
+- restore_flags(flags);
+-
++ HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ if (card->debug_flags & LOG_SCHED_ASYN)
+ hysdn_addlog(card, "async tx-cfg data send");
+
+diff -rNu linux-2.4.29.old/drivers/isdn/icn/icn.c linux-2.4.29/drivers/isdn/icn/icn.c
+--- linux-2.4.29.old/drivers/isdn/icn/icn.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/icn/icn.c 2005-03-22 15:06:48.722685808 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: icn.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * ISDN low-level module for the ICN active ISDN-Card.
+ *
+@@ -41,7 +41,7 @@
+ #undef MAP_DEBUG
+
+ static char
+-*revision = "$Revision: 1.1.4.1 $";
++*revision = "$Revision$";
+
+ static int icn_addcard(int, char *, char *);
+
+@@ -1634,6 +1634,7 @@
+ }
+
+ #ifndef MODULE
++#ifdef COMPAT_HAS_NEW_SETUP
+ static int __init
+ icn_setup(char *line)
+ {
+@@ -1643,6 +1644,14 @@
+ static char sid2[20];
+
+ str = get_options(line, 2, ints);
++#else
++void
++icn_setup(char *str, int *ints)
++{
++ char *p;
++ static char sid[20];
++ static char sid2[20];
++#endif
+ if (ints[0])
+ portbase = ints[1];
+ if (ints[0] > 1)
+@@ -1656,9 +1665,13 @@
+ icn_id2 = sid2;
+ }
+ }
++#ifdef COMPAT_HAS_NEW_SETUP
+ return(1);
+ }
+ __setup("icn=", icn_setup);
++#else
++}
++#endif
+ #endif /* MODULE */
+
+ static int __init icn_init(void)
+diff -rNu linux-2.4.29.old/drivers/isdn/icn/icn.h linux-2.4.29/drivers/isdn/icn/icn.h
+--- linux-2.4.29.old/drivers/isdn/icn/icn.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/icn/icn.h 2005-03-22 15:06:48.752681248 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: icn.h,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * ISDN lowlevel-module for the ICN active ISDN-Card.
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_audio.c linux-2.4.29/drivers/isdn/isdn_audio.c
+--- linux-2.4.29.old/drivers/isdn/isdn_audio.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_audio.c 2005-03-22 15:06:44.306357192 +0100
+@@ -1,9 +1,9 @@
+-/* $Id: isdn_audio.c,v 1.1.4.1 2001/11/20 14:19:33 kai Exp $
++/* $Id: isdn_audio.c,v 1.24 2002/08/13 09:57:26 keil Exp $
+ *
+ * Linux ISDN subsystem, audio conversion and compression (linklevel).
+ *
+ * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
+- * DTMF code (c) 1996 by Christian Mock (cm@kukuruz.ping.at)
++ * DTMF code (c) 1996 by Christian Mock (cm@tahina.priv.at)
+ * Silence detection (c) 1998 by Armin Schindler (mac@gismo.telekom.de)
+ *
+ * This software may be used and distributed according to the terms
+@@ -15,7 +15,7 @@
+ #include "isdn_audio.h"
+ #include "isdn_common.h"
+
+-char *isdn_audio_revision = "$Revision: 1.1.4.1 $";
++char *isdn_audio_revision = "$Revision: 1.24 $";
+
+ /*
+ * Misc. lookup-tables.
+@@ -169,19 +169,39 @@
+ 0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a
+ };
+
+-#define NCOEFF 8 /* number of frequencies to be analyzed */
+-#define DTMF_TRESH 4000 /* above this is dtmf */
++#define NCOEFF 16 /* number of frequencies to be analyzed */
++#define DTMF_TRESH 25000 /* above this is dtmf */
+ #define SILENCE_TRESH 200 /* below this is silence */
++#define H2_TRESH 20000 /* 2nd harmonic */
+ #define AMP_BITS 9 /* bits per sample, reduced to avoid overflow */
+ #define LOGRP 0
+ #define HIGRP 1
+
++typedef struct {
++ int grp; /* low/high group */
++ int k; /* k */
++ int k2; /* k fuer 2. harmonic */
++} dtmf_t;
++
+ /* For DTMF recognition:
+ * 2 * cos(2 * PI * k / N) precalculated for all k
+ */
+ static int cos2pik[NCOEFF] =
+ {
+- 55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332
++ 55812, 29528, 53603, 24032, 51193, 14443, 48590, 6517,
++ 38113, -21204, 33057, -32186, 25889, -45081, 18332, -55279
++};
++
++static dtmf_t dtmf_tones[8] =
++{
++ {LOGRP, 0, 1}, /* 697 Hz */
++ {LOGRP, 2, 3}, /* 770 Hz */
++ {LOGRP, 4, 5}, /* 852 Hz */
++ {LOGRP, 6, 7}, /* 941 Hz */
++ {HIGRP, 8, 9}, /* 1209 Hz */
++ {HIGRP, 10, 11}, /* 1336 Hz */
++ {HIGRP, 12, 13}, /* 1477 Hz */
++ {HIGRP, 14, 15} /* 1633 Hz */
+ };
+
+ static char dtmf_matrix[4][4] =
+@@ -208,7 +228,7 @@
+ : "memory", "ax");
+ #else
+ while (n--)
+- *buff = table[*(unsigned char *)buff], buff++;
++ *buff++ = table[*(unsigned char *)buff];
+ #endif
+ }
+
+@@ -479,18 +499,6 @@
+ sk2 = sk1;
+ sk1 = sk;
+ }
+- /* Avoid overflows */
+- sk >>= 1;
+- sk2 >>= 1;
+- /* compute |X(k)|**2 */
+- /* report overflows. This should not happen. */
+- /* Comment this out if desired */
+- if (sk < -32768 || sk > 32767)
+- printk(KERN_DEBUG
+- "isdn_audio: dtmf goertzel overflow, sk=%d\n", sk);
+- if (sk2 < -32768 || sk2 > 32767)
+- printk(KERN_DEBUG
+- "isdn_audio: dtmf goertzel overflow, sk2=%d\n", sk2);
+ result[k] =
+ ((sk * sk) >> AMP_BITS) -
+ ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) +
+@@ -514,58 +522,28 @@
+ int grp[2];
+ char what;
+ char *p;
+- int thresh;
+
+ while ((skb = skb_dequeue(&info->dtmf_queue))) {
+ result = (int *) skb->data;
+ s = info->dtmf_state;
+- grp[LOGRP] = grp[HIGRP] = -1;
++ grp[LOGRP] = grp[HIGRP] = -2;
+ silence = 0;
+- thresh = 0;
+- for (i = 0; i < NCOEFF; i++) {
+- if (result[i] > DTMF_TRESH) {
+- if (result[i] > thresh)
+- thresh = result[i];
+- }
+- else if (result[i] < SILENCE_TRESH)
++ for (i = 0; i < 8; i++) {
++ if ((result[dtmf_tones[i].k] > DTMF_TRESH) &&
++ (result[dtmf_tones[i].k2] < H2_TRESH))
++ grp[dtmf_tones[i].grp] = (grp[dtmf_tones[i].grp] == -2) ? i : -1;
++ else if ((result[dtmf_tones[i].k] < SILENCE_TRESH) &&
++ (result[dtmf_tones[i].k2] < SILENCE_TRESH))
+ silence++;
+ }
+- if (silence == NCOEFF)
++ if (silence == 8)
+ what = ' ';
+ else {
+- if (thresh > 0) {
+- thresh = thresh >> 4; /* touchtones must match within 12 dB */
+- for (i = 0; i < NCOEFF; i++) {
+- if (result[i] < thresh)
+- continue; /* ignore */
+- /* good level found. This is allowed only one time per group */
+- if (i < NCOEFF / 2) {
+- /* lowgroup*/
+- if (grp[LOGRP] >= 0) {
+- // Bad. Another tone found. */
+- grp[LOGRP] = -1;
+- break;
+- }
+- else
+- grp[LOGRP] = i;
+- }
+- else { /* higroup */
+- if (grp[HIGRP] >= 0) { // Bad. Another tone found. */
+- grp[HIGRP] = -1;
+- break;
+- }
+- else
+- grp[HIGRP] = i - NCOEFF/2;
+- }
+- }
+- if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
+- what = dtmf_matrix[grp[LOGRP]][grp[HIGRP]];
+- if (s->last != ' ' && s->last != '.')
+- s->last = what; /* min. 1 non-DTMF between DTMF */
+- } else
+- what = '.';
+- }
+- else
++ if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
++ what = dtmf_matrix[grp[LOGRP]][grp[HIGRP] - 4];
++ if (s->last != ' ' && s->last != '.')
++ s->last = what; /* min. 1 non-DTMF between DTMF */
++ } else
+ what = '.';
+ }
+ if ((what != s->last) && (what != ' ') && (what != '.')) {
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_audio.h linux-2.4.29/drivers/isdn/isdn_audio.h
+--- linux-2.4.29.old/drivers/isdn/isdn_audio.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_audio.h 2005-03-22 15:06:44.321354912 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_audio.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_audio.h,v 1.10 2001/09/24 13:22:42 kai Exp $
+ *
+ * Linux ISDN subsystem, audio conversion and compression (linklevel).
+ *
+@@ -20,7 +20,6 @@
+
+ typedef struct dtmf_state {
+ char last;
+- char llast;
+ int idx;
+ int buf[DTMF_NPOINTS];
+ } dtmf_state;
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_bsdcomp.c linux-2.4.29/drivers/isdn/isdn_bsdcomp.c
+--- linux-2.4.29.old/drivers/isdn/isdn_bsdcomp.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_bsdcomp.c 2005-03-22 15:06:44.339352176 +0100
+@@ -105,6 +105,14 @@
+
+ #define DEBUG 1
+
++#ifdef CONFIG_ISDN_WITH_ABC
++#define BSD_C_MALLOC(x) kmalloc((x),GFP_ATOMIC)
++#define BSD_C_FREE(x) kfree(x)
++#else
++#define BSD_C_MALLOC(x) vmalloc(x)
++#define BSD_C_FREE(x) vfree(x)
++#endif
++
+ /*
+ * A dictionary for doing BSD compress.
+ */
+@@ -285,7 +293,7 @@
+ * Release the dictionary
+ */
+ if (db->dict) {
+- vfree (db->dict);
++ BSD_C_FREE (db->dict);
+ db->dict = NULL;
+ }
+
+@@ -293,7 +301,7 @@
+ * Release the string buffer
+ */
+ if (db->lens) {
+- vfree (db->lens);
++ BSD_C_FREE (db->lens);
+ db->lens = NULL;
+ }
+
+@@ -350,14 +358,19 @@
+ * Allocate space for the dictionary. This may be more than one page in
+ * length.
+ */
+- db->dict = (struct bsd_dict *) vmalloc (hsize * sizeof (struct bsd_dict));
++ db->dict = (struct bsd_dict *) BSD_C_MALLOC (hsize * sizeof (struct bsd_dict));
++
++ MOD_INC_USE_COUNT;
++ /*
++ ** MOD_INC_USE_COUNT must be before bsd_free
++ ** bsd_free make MOD_DEC_USE_COUNT if db != NULL
++ */
++
+ if (!db->dict) {
+ bsd_free (db);
+ return NULL;
+ }
+
+- MOD_INC_USE_COUNT;
+-
+ /*
+ * If this is the compression buffer then there is no length data.
+ * For decompression, the length information is needed as well.
+@@ -365,7 +378,7 @@
+ if (!decomp)
+ db->lens = NULL;
+ else {
+- db->lens = (unsigned short *) vmalloc ((maxmaxcode + 1) *
++ db->lens = (unsigned short *) BSD_C_MALLOC ((maxmaxcode + 1) *
+ sizeof (db->lens[0]));
+ if (!db->lens) {
+ bsd_free (db); /* calls MOD_DEC_USE_COUNT; */
+@@ -478,7 +491,11 @@
+ int hval,disp,ilen,mxcode;
+ unsigned char *rptr = skb_in->data;
+ int isize = skb_in->len;
++#ifdef CONFIG_ISDN_WITH_ABC
++ long secure = 0;
++#endif
+
++#ifndef CONFIG_ISDN_WITH_ABC
+ #define OUTPUT(ent) \
+ { \
+ bitno -= n_bits; \
+@@ -490,17 +507,45 @@
+ bitno += 8; \
+ } while (bitno <= 24); \
+ }
++#else
++#define OUTPUT(ent) \
++ { \
++ secure = 0; \
++ bitno -= n_bits; \
++ accm |= ((ent) << bitno); \
++ do { \
++ if(skb_out && skb_tailroom(skb_out) > 0) \
++ *(skb_put(skb_out,1)) = (unsigned char) (accm>>24); \
++ accm <<= 8; \
++ bitno += 8; \
++ } while (bitno <= 24 && ++secure < 10000); \
++ if(secure >= 10000) { \
++ printk(KERN_DEBUG "BSD in OUTPUT secure counter reached\n"); \
++ return 0; \
++ } \
++ }
++#endif
+
+ /*
+ * If the protocol is not in the range we're interested in,
+ * just return without compressing the packet. If it is,
+ * the protocol becomes the first byte to compress.
+ */
++#ifdef CONFIG_ISDN_WITH_ABC
++ ent = proto;
++
++ if (proto < 0x21 || proto > 0xf9 || !(proto & 0x1) ) {
++
++ printk(KERN_DEBUG "bsd_compress called with %x\n",proto);
++ return 0;
++ }
++#else
+ printk(KERN_DEBUG "bsd_compress called with %x\n",proto);
+
+ ent = proto;
+ if (proto < 0x21 || proto > 0xf9 || !(proto & 0x1) )
+ return 0;
++#endif
+
+ db = (struct bsd_db *) state;
+ hshift = db->hshift;
+@@ -538,6 +583,9 @@
+
+ /* continue probing until a match or invalid entry */
+ disp = (hval == 0) ? 1 : hval;
++#ifdef CONFIG_ISDN_WITH_ABC
++ secure = 0;
++#endif
+
+ do {
+ hval += disp;
+@@ -546,7 +594,15 @@
+ dictp = dict_ptr (db, hval);
+ if (dictp->codem1 >= max_ent)
+ goto nomatch;
++#ifndef CONFIG_ISDN_WITH_ABC
+ } while (dictp->fcode != fcode);
++#else
++ } while (dictp->fcode != fcode && ++secure < 100000);
++ if(secure >= 100000) {
++ printk(KERN_DEBUG "BSD: compress while dictp->fcode != fcode secure-counter reached\n");
++ return 0;
++ }
++#endif
+
+ ent = dictp->codem1 + 1; /* finally found (prefix,suffix) */
+ continue;
+@@ -669,6 +725,9 @@
+ int ilen;
+ int codelen;
+ int extra;
++#ifdef CONFIG_ISDN_WITH_ABC
++ unsigned long secure = 0;
++#endif
+
+ db = (struct bsd_db *) state;
+ max_ent = db->max_ent;
+@@ -677,7 +736,9 @@
+ n_bits = db->n_bits;
+ tgtbitno = 32 - n_bits; /* bitno when we have a code */
+
++#ifndef CONFIG_ISDN_WITH_ABC
+ printk(KERN_DEBUG "bsd_decompress called\n");
++#endif
+
+ if(!skb_in || !skb_out) {
+ printk(KERN_ERR "bsd_decompress called with NULL parameter\n");
+@@ -795,7 +856,11 @@
+
+ p = skb_put(skb_out,codelen);
+ p += codelen;
++#ifdef CONFIG_ISDN_WITH_ABC
++ for(secure = 0; finchar > LAST && secure < 50000;secure++) {
++#else
+ while (finchar > LAST) {
++#endif
+ struct bsd_dict *dictp2 = dict_ptr (db, finchar);
+
+ dictp = dict_ptr (db, dictp2->cptr);
+@@ -822,6 +887,12 @@
+ }
+ }
+ *--p = finchar;
++#ifdef CONFIG_ISDN_WITH_ABC
++ if(secure >= 50000) {
++ printk(KERN_DEBUG "BSD: decompress secure-counter reached\n");
++ return DECOMP_FATALERROR;
++ }
++#endif
+
+ #ifdef DEBUG
+ if (--codelen != 0)
+@@ -851,12 +922,23 @@
+ /* look for a free hash table entry */
+ if (dictp->codem1 < max_ent) {
+ disp = (hval == 0) ? 1 : hval;
++#ifdef CONFIG_ISDN_WITH_ABC
++ secure = 0;
++#endif
+ do {
+ hval += disp;
+ if (hval >= db->hsize)
+ hval -= db->hsize;
+ dictp = dict_ptr (db, hval);
++#ifndef CONFIG_ISDN_WITH_ABC
+ } while (dictp->codem1 < max_ent);
++#else
++ } while (dictp->codem1 < max_ent && ++secure < 50000);
++ if(secure >= 50000) {
++ printk(KERN_DEBUG "BSD: decomp while (dictp->codem1 < max_ent) secure-counter reached\n");
++ return DECOMP_FATALERROR;
++ }
++#endif
+ }
+
+ /*
+@@ -895,11 +977,21 @@
+ db->comp_bytes += skb_in->len - BSD_OVHD;
+ db->uncomp_bytes += skb_out->len;
+
++#ifdef CONFIG_ISDN_WITH_ABC
++ /*
++ ** bsd_check will call bsd_clear
++ ** and so on the internal tables will be cleared.
++ **
++ ** I think that's not what we will at this point ?????
++ ** For me at works without bsd_check.
++ */
++#else
+ if (bsd_check(db)) {
+ if (db->debug)
+ printk(KERN_DEBUG "bsd_decomp%d: peer should have cleared dictionary on %d\n",
+ db->unit, db->seqno - 1);
+ }
++#endif
+ return skb_out->len;
+ }
+
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_common.c linux-2.4.29/drivers/isdn/isdn_common.c
+--- linux-2.4.29.old/drivers/isdn/isdn_common.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_common.c 2005-03-22 15:06:44.359349136 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_common.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_common.c,v 1.137 2002/02/09 21:19:11 keil Exp $
+ *
+ * Linux ISDN subsystem, common used functions (linklevel).
+ *
+@@ -19,6 +19,7 @@
+ #include <linux/vmalloc.h>
+ #include <linux/isdn.h>
+ #include <linux/smp_lock.h>
++#include <linux/list.h>
+ #include "isdn_common.h"
+ #include "isdn_tty.h"
+ #include "isdn_net.h"
+@@ -33,7 +34,9 @@
+ #include <linux/isdn_divertif.h>
+ #endif /* CONFIG_ISDN_DIVERSION */
+ #include "isdn_v110.h"
++#ifdef HAVE_DEVFS_FS
+ #include <linux/devfs_fs_kernel.h>
++#endif /* HAVE_DEVFS_FS */
+
+ /* Debugflags */
+ #undef ISDN_DEBUG_STATCALLB
+@@ -44,7 +47,7 @@
+
+ isdn_dev *dev;
+
+-static char *isdn_revision = "$Revision: 1.1.4.1 $";
++static char *isdn_revision = "$Revision: 1.137 $";
+
+ extern char *isdn_net_revision;
+ extern char *isdn_tty_revision;
+@@ -67,19 +70,19 @@
+
+ static int isdn_writebuf_stub(int, int, const u_char *, int, int);
+ static void set_global_features(void);
++#ifdef HAVE_DEVFS_FS
+ static void isdn_register_devfs(int);
+ static void isdn_unregister_devfs(int);
++#endif /* HAVE_DEVFS_FS */
+ static int isdn_wildmat(char *s, char *p);
+
+ void
+ isdn_lock_drivers(void)
+ {
+ int i;
+- isdn_ctrl cmd;
+
+- for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
+- if (!dev->drv[i])
+- continue;
++ for (i = 0; i < dev->drivers; i++) {
++ isdn_ctrl cmd;
+
+ cmd.driver = i;
+ cmd.arg = 0;
+@@ -101,10 +104,7 @@
+ {
+ int i;
+
+- for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
+- if (!dev->drv[i])
+- continue;
+-
++ for (i = 0; i < dev->drivers; i++)
+ if (dev->drv[i]->locks > 0) {
+ isdn_ctrl cmd;
+
+@@ -114,7 +114,6 @@
+ isdn_command(&cmd);
+ dev->drv[i]->locks--;
+ }
+- }
+ }
+
+ void
+@@ -473,6 +472,7 @@
+ dev->drv[di]->flags &= ~DRV_FLAG_RUNNING;
+ break;
+ case ISDN_STAT_ICALL:
++ case ISDN_STAT_ICALLW:
+ if (i < 0)
+ return -1;
+ #ifdef ISDN_DEBUG_STATCALLB
+@@ -718,7 +718,9 @@
+ dev->drvmap[i] = -1;
+ dev->chanmap[i] = -1;
+ dev->usage[i] &= ~ISDN_USAGE_DISABLED;
++#ifdef HAVE_DEVFS_FS
+ isdn_unregister_devfs(i);
++#endif /* HAVE_DEVFS_FS */
+ }
+ dev->drivers--;
+ dev->channels -= dev->drv[di]->channels;
+@@ -755,6 +757,10 @@
+ if (divert_if)
+ return(divert_if->stat_callback(c));
+ #endif /* CONFIG_ISDN_DIVERSION */
++ case ISDN_STAT_ALERT:
++ case ISDN_STAT_PROCEED:
++ isdn_tty_stat_callback(i, c);
++ break;
+ default:
+ return -1;
+ }
+@@ -900,72 +906,239 @@
+ return (dev->chanmap[minor]);
+ }
+
+-static char *
+-isdn_statstr(void)
++// ----------------------------------------------------------------------
++// /dev/isdninfo
++//
++// This device has somewhat insane semantics, but we need to support
++// them for the sake of compatibility.
++//
++// After opening, the first read will succeed and return the current state
++// Then, unless O_NONBLOCK is set, it will block until a state change happens
++// and then return the new state.
++// Also, if the buffer size for the read is too small, we'll just return
++// EOF
++
++struct isdnstatus_dev {
++ struct list_head list;
++ int update;
++};
++
++static DECLARE_WAIT_QUEUE_HEAD(isdnstatus_waitq);
++static LIST_HEAD(isdnstatus_devs);
++static spinlock_t isdnstatus_devs_lock = SPIN_LOCK_UNLOCKED;
++
++void
++isdn_info_update(void)
++{
++ struct list_head *p;
++ struct isdnstatus_dev *idev;
++
++ spin_lock(&isdnstatus_devs_lock);
++ list_for_each(p, &isdnstatus_devs) {
++ idev = list_entry(p, struct isdnstatus_dev, list);
++ idev->update = 1;
++ }
++ spin_unlock(&isdnstatus_devs_lock);
++ wake_up_interruptible(&isdnstatus_waitq);
++}
++
++static int
++isdnstatus_open(struct inode *ino, struct file *filep)
++{
++ struct isdnstatus_dev *p;
++
++ p = kmalloc(sizeof(struct isdnstatus_dev), GFP_USER);
++ if (!p)
++ return -ENOMEM;
++
++ /* At opening time we allow a single update */
++ p->update = 1;
++ spin_lock(&isdnstatus_devs_lock);
++ list_add(&p->list, &isdnstatus_devs);
++ spin_unlock(&isdnstatus_devs_lock);
++ filep->private_data = p;
++
++ return 0;
++}
++
++static void
++isdnstatus_close(struct inode *ino, struct file *filep)
++{
++ struct isdnstatus_dev *p = filep->private_data;
++
++ spin_lock(&isdnstatus_devs_lock);
++ list_del(&p->list);
++ spin_unlock(&isdnstatus_devs_lock);
++ kfree(p);
++}
++
++// FIXME we don't lock against the state changing whilst being
++// printed
++
++void
++isdn_statstr(char *buf)
+ {
+- static char istatbuf[2048];
+ char *p;
+ int i;
+
+- sprintf(istatbuf, "idmap:\t");
+- p = istatbuf + strlen(istatbuf);
++ p = buf;
++ p += sprintf(p, "idmap:\t");
+ for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+- sprintf(p, "%s ", (dev->drvmap[i] < 0) ? "-" : dev->drvid[dev->drvmap[i]]);
+- p = istatbuf + strlen(istatbuf);
++ p += sprintf(p, "%s ", (dev->drvmap[i] < 0) ? "-" : dev->drvid[dev->drvmap[i]]);
+ }
+- sprintf(p, "\nchmap:\t");
+- p = istatbuf + strlen(istatbuf);
++ p += sprintf(p, "\nchmap:\t");
+ for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+- sprintf(p, "%d ", dev->chanmap[i]);
+- p = istatbuf + strlen(istatbuf);
++ p += sprintf(p, "%d ", dev->chanmap[i]);
+ }
+- sprintf(p, "\ndrmap:\t");
+- p = istatbuf + strlen(istatbuf);
++ p += sprintf(p, "\ndrmap:\t");
+ for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+- sprintf(p, "%d ", dev->drvmap[i]);
+- p = istatbuf + strlen(istatbuf);
++ p += sprintf(p, "%d ", dev->drvmap[i]);
+ }
+- sprintf(p, "\nusage:\t");
+- p = istatbuf + strlen(istatbuf);
++ p += sprintf(p, "\nusage:\t");
+ for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+- sprintf(p, "%d ", dev->usage[i]);
+- p = istatbuf + strlen(istatbuf);
++ p += sprintf(p, "%d ", dev->usage[i]);
+ }
+- sprintf(p, "\nflags:\t");
+- p = istatbuf + strlen(istatbuf);
++ p += sprintf(p, "\nflags:\t");
+ for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
+ if (dev->drv[i]) {
+- sprintf(p, "%ld ", dev->drv[i]->online);
+- p = istatbuf + strlen(istatbuf);
++ p += sprintf(p, "%ld ", dev->drv[i]->online);
+ } else {
+- sprintf(p, "? ");
+- p = istatbuf + strlen(istatbuf);
++ p += sprintf(p, "? ");
+ }
+ }
+- sprintf(p, "\nphone:\t");
+- p = istatbuf + strlen(istatbuf);
++ p += sprintf(p, "\nphone:\t");
+ for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+- sprintf(p, "%s ", dev->num[i]);
+- p = istatbuf + strlen(istatbuf);
++ p += sprintf(p, "%s ", dev->num[i]);
+ }
+- sprintf(p, "\n");
+- return istatbuf;
++ p += sprintf(p, "\n");
+ }
+
+-/* Module interface-code */
++static ssize_t
++isdnstatus_read(struct file *file, char *buf, size_t count, loff_t * off)
++{
++ static DECLARE_MUTEX(istatbuf_mutex);
++ static char istatbuf[2048];
+
+-void
+-isdn_info_update(void)
++ DECLARE_WAITQUEUE(wait, current);
++ struct isdnstatus_dev *idev;
++ int retval = 0;
++ unsigned int len;
++
++ idev = file->private_data;
++
++ if (off != &file->f_pos)
++ return -ESPIPE;
++
++ add_wait_queue(&isdnstatus_waitq, &wait);
++ for (;;) {
++ set_current_state(TASK_INTERRUPTIBLE);
++
++ if (idev->update)
++ break;
++
++ retval = -EAGAIN;
++ if (file->f_flags & O_NONBLOCK)
++ break;
++
++ retval = -ERESTARTSYS;
++ if (signal_pending(current))
++ break;
++
++ schedule();
++ }
++ __set_current_state(TASK_RUNNING);
++ remove_wait_queue(&isdnstatus_waitq, &wait);
++
++ if (!idev->update)
++ goto out;
++
++ idev->update = 0;
++ down(&istatbuf_mutex);
++ isdn_statstr(istatbuf);
++ len = strlen(istatbuf);
++ if (len > count) {
++ retval = 0;
++ goto out_unlock;
++ }
++ if (copy_to_user(buf, istatbuf, len)) {
++ retval = -EFAULT;
++ goto out_unlock;
++ }
++ *off += len;
++ retval = len;
++
++ out_unlock:
++ up(&istatbuf_mutex);
++ out:
++ return retval;
++}
++
++static ssize_t
++isdnstatus_write(struct file *file, const char *buf, size_t count, loff_t * off)
+ {
+- infostruct *p = dev->infochain;
++ return -EINVAL;
++}
++
++static unsigned int
++isdnstatus_poll(struct file *file, poll_table * wait)
++{
++ struct isdnstatus_dev *idev;
++ unsigned int mask = 0;
++
++ idev = file->private_data;
+
+- while (p) {
+- *(p->private) = 1;
+- p = (infostruct *) p->next;
++ poll_wait(file, &isdnstatus_waitq, wait);
++ if (idev->update) {
++ mask |= POLLIN | POLLRDNORM;
+ }
+- wake_up_interruptible(&(dev->info_waitq));
++ return mask;
+ }
+
++static int
++isdnstatus_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
++{
++ int retval;
++ isdn_net_ioctl_phone phone;
++
++ switch (cmd) {
++ case IIOCGETDVR:
++ return (TTY_DV +
++ (NET_DV << 8) +
++ (INF_DV << 16));
++ case IIOCGETCPS:
++ if (arg) {
++ ulong *p = (ulong *) arg;
++ int i;
++ if ((retval = verify_area(VERIFY_WRITE, (void *) arg,
++ sizeof(ulong) * ISDN_MAX_CHANNELS * 2)))
++ return retval;
++ for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
++ put_user(dev->ibytes[i], p++);
++ put_user(dev->obytes[i], p++);
++ }
++ return 0;
++ } else
++ return -EINVAL;
++ break;
++#ifdef CONFIG_NETDEVICES
++ case IIOCNETGPN:
++ /* Get peer phone number of a connected
++ * isdn network interface */
++ if (arg) {
++ if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
++ return -EFAULT;
++ return isdn_net_getpeer(&phone, (isdn_net_ioctl_phone *) arg);
++ } else
++ return -EINVAL;
++#endif
++ default:
++ return -EINVAL;
++ }
++}
++
++// ----------------------------------------------------------------------
++
++
+ static ssize_t
+ isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
+ {
+@@ -976,37 +1149,16 @@
+ int chidx;
+ int retval;
+ char *p;
+- loff_t pos = *off;
+
+ if (off != &file->f_pos)
+ return -ESPIPE;
+
+- if (pos != (unsigned) pos)
+- return -EINVAL;
+-
++#ifndef COMPAT_HAVE_READ_LOCK_KERNEL
+ lock_kernel();
+- if (minor == ISDN_MINOR_STATUS) {
+- if (!file->private_data) {
+- if (file->f_flags & O_NONBLOCK) {
+- retval = -EAGAIN;
+- goto out;
+- }
+- interruptible_sleep_on(&(dev->info_waitq));
+- }
+- p = isdn_statstr();
+- file->private_data = 0;
+- if ((len = strlen(p)) <= count) {
+- if (copy_to_user(buf, p, len)) {
+- retval = -EFAULT;
+- goto out;
+- }
+- *off = pos + len;
+- retval = len;
+- goto out;
+- }
+- retval = 0;
+- goto out;
+- }
++#endif
++ if (minor == ISDN_MINOR_STATUS)
++ return isdnstatus_read(file, buf, count, off);
++
+ if (!dev->drivers) {
+ retval = -ENODEV;
+ goto out;
+@@ -1031,7 +1183,7 @@
+ cli();
+ len = isdn_readbchan(drvidx, chidx, p, 0, count,
+ &dev->drv[drvidx]->rcv_waitq[chidx]);
+- *off = pos + len;
++ *off += len;
+ restore_flags(flags);
+ if (copy_to_user(buf,p,len))
+ len = -EFAULT;
+@@ -1052,6 +1204,9 @@
+ }
+ interruptible_sleep_on(&(dev->drv[drvidx]->st_waitq));
+ }
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++ if(drvidx || (len = isdn_dw_abc_lcr_readstat(buf,count)) < 1) {
++#endif
+ if (dev->drv[drvidx]->interface->readstat) {
+ if (count > dev->drv[drvidx]->stavail)
+ count = dev->drv[drvidx]->stavail;
+@@ -1061,6 +1216,9 @@
+ } else {
+ len = 0;
+ }
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++ }
++#endif
+ save_flags(flags);
+ cli();
+ if (len)
+@@ -1068,7 +1226,7 @@
+ else
+ dev->drv[drvidx]->stavail = 0;
+ restore_flags(flags);
+- *off = pos + len;
++ *off += len;
+ retval = len;
+ goto out;
+ }
+@@ -1080,7 +1238,9 @@
+ #endif
+ retval = -ENODEV;
+ out:
++#ifndef COMPAT_HAVE_READ_LOCK_KERNEL
+ unlock_kernel();
++#endif
+ return retval;
+ }
+
+@@ -1092,15 +1252,18 @@
+ int chidx;
+ int retval;
+
++ if (minor == ISDN_MINOR_STATUS)
++ return isdnstatus_write(file, buf, count, off);
++
+ if (off != &file->f_pos)
+ return -ESPIPE;
+
+- if (minor == ISDN_MINOR_STATUS)
+- return -EPERM;
+ if (!dev->drivers)
+ return -ENODEV;
+
++#ifndef COMPAT_HAVE_WRITE_LOCK_KERNEL
+ lock_kernel();
++#endif
+ if (minor <= ISDN_MINOR_BMAX) {
+ printk(KERN_WARNING "isdn_write minor %d obsolete!\n", minor);
+ drvidx = isdn_minor2drv(minor);
+@@ -1145,7 +1308,9 @@
+ #endif
+ retval = -ENODEV;
+ out:
++#ifndef COMPAT_HAVE_WRITE_LOCK_KERNEL
+ unlock_kernel();
++#endif
+ return retval;
+ }
+
+@@ -1156,15 +1321,12 @@
+ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
+
++#ifndef COMPAT_HAVE_POLL_LOCK_KERNEL
+ lock_kernel();
+- if (minor == ISDN_MINOR_STATUS) {
+- poll_wait(file, &(dev->info_waitq), wait);
+- /* mask = POLLOUT | POLLWRNORM; */
+- if (file->private_data) {
+- mask |= POLLIN | POLLRDNORM;
+- }
+- goto out;
+- }
++#endif
++ if (minor == ISDN_MINOR_STATUS)
++ return isdnstatus_poll(file, wait);
++
+ if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) {
+ if (drvidx < 0) {
+ /* driver deregistered while file open */
+@@ -1186,7 +1348,9 @@
+ #endif
+ mask = POLLERR;
+ out:
++#ifndef COMPAT_HAVE_POLL_LOCK_KERNEL
+ unlock_kernel();
++#endif
+ return mask;
+ }
+
+@@ -1216,42 +1380,9 @@
+ #define phone iocpar.phone
+ #define cfg iocpar.cfg
+
+- if (minor == ISDN_MINOR_STATUS) {
+- switch (cmd) {
+- case IIOCGETDVR:
+- return (TTY_DV +
+- (NET_DV << 8) +
+- (INF_DV << 16));
+- case IIOCGETCPS:
+- if (arg) {
+- ulong *p = (ulong *) arg;
+- int i;
+- if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
+- sizeof(ulong) * ISDN_MAX_CHANNELS * 2)))
+- return ret;
+- for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+- put_user(dev->ibytes[i], p++);
+- put_user(dev->obytes[i], p++);
+- }
+- return 0;
+- } else
+- return -EINVAL;
+- break;
+-#ifdef CONFIG_NETDEVICES
+- case IIOCNETGPN:
+- /* Get peer phone number of a connected
+- * isdn network interface */
+- if (arg) {
+- if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+- return -EFAULT;
+- return isdn_net_getpeer(&phone, (isdn_net_ioctl_phone *) arg);
+- } else
+- return -EINVAL;
+-#endif
+- default:
+- return -EINVAL;
+- }
+- }
++ if (minor == ISDN_MINOR_STATUS)
++ return isdnstatus_ioctl(inode, file, cmd, arg);
++
+ if (!dev->drivers)
+ return -ENODEV;
+ if (minor <= ISDN_MINOR_BMAX) {
+@@ -1273,11 +1404,34 @@
+ */
+ switch (cmd) {
+ case IIOCNETDWRSET:
++#ifdef CONFIG_ISDN_WITH_ABC
++ if (arg) {
++
++ if (copy_from_user(name, (char *) arg, sizeof(name))) {
++
++ return(-EFAULT);
++
++ } else {
++
++ isdn_net_dev *p = isdn_net_findif(name);
++
++ if(p == NULL)
++ return(-EINVAL);
++
++ return(isdn_dw_abc_reset_interface(p->local,1));
++ }
++ }
++#else
+ printk(KERN_INFO "INFO: ISDN_DW_ABC_EXTENSION not enabled\n");
++#endif
+ return(-EINVAL);
+ case IIOCNETLCR:
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++ return(isdn_dw_abc_lcr_ioctl(arg));
++#else
+ printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
+ return -ENODEV;
++#endif
+ #ifdef CONFIG_NETDEVICES
+ case IIOCNETAIF:
+ /* Add a network-interface */
+@@ -1650,22 +1804,12 @@
+ int chidx;
+ int retval = -ENODEV;
+
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++ MOD_INC_USE_COUNT;
++#endif
+
+ if (minor == ISDN_MINOR_STATUS) {
+- infostruct *p;
+-
+- if ((p = kmalloc(sizeof(infostruct), GFP_KERNEL))) {
+- p->next = (char *) dev->infochain;
+- p->private = (char *) &(filep->private_data);
+- dev->infochain = p;
+- /* At opening we allow a single update */
+- filep->private_data = (char *) 1;
+- retval = 0;
+- goto out;
+- } else {
+- retval = -ENOMEM;
+- goto out;
+- }
++ return isdnstatus_open(ino, filep);
+ }
+ if (!dev->channels)
+ goto out;
+@@ -1688,6 +1832,9 @@
+ if (drvidx < 0)
+ goto out;
+ isdn_lock_drivers();
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++ if(!drvidx) isdn_dw_abc_lcr_open();
++#endif
+ retval = 0;
+ goto out;
+ }
+@@ -1700,6 +1847,10 @@
+ }
+ #endif
+ out:
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++ if (retval)
++ MOD_DEC_USE_COUNT;
++#endif
+ return retval;
+ }
+
+@@ -1708,25 +1859,11 @@
+ {
+ uint minor = MINOR(ino->i_rdev);
+
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+ lock_kernel();
++#endif
+ if (minor == ISDN_MINOR_STATUS) {
+- infostruct *p = dev->infochain;
+- infostruct *q = NULL;
+-
+- while (p) {
+- if (p->private == (char *) &(filep->private_data)) {
+- if (q)
+- q->next = p->next;
+- else
+- dev->infochain = (infostruct *) (p->next);
+- kfree(p);
+- goto out;
+- }
+- q = p;
+- p = (infostruct *) (p->next);
+- }
+- printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n");
+- goto out;
++ isdnstatus_close(ino, filep);
+ }
+ isdn_unlock_drivers();
+ if (minor <= ISDN_MINOR_BMAX)
+@@ -1734,6 +1871,12 @@
+ if (minor <= ISDN_MINOR_CTRLMAX) {
+ if (dev->profd == current)
+ dev->profd = NULL;
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++ {
++ int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
++ if(!drvidx) isdn_dw_abc_lcr_close();
++ }
++#endif
+ goto out;
+ }
+ #ifdef CONFIG_ISDN_PPP
+@@ -1742,13 +1885,19 @@
+ #endif
+
+ out:
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++ MOD_DEC_USE_COUNT;
++#else
+ unlock_kernel();
++#endif
+ return 0;
+ }
+
+ static struct file_operations isdn_fops =
+ {
++#ifdef COMPAT_HAS_FILEOP_OWNER
+ owner: THIS_MODULE,
++#endif
+ llseek: no_llseek,
+ read: isdn_read,
+ write: isdn_write,
+@@ -1801,6 +1950,15 @@
+ if (USG_NONE(dev->usage[i]) &&
+ (dev->drvmap[i] != -1)) {
+ int d = dev->drvmap[i];
++#ifdef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
++ if(jiffies < dev->dwabc_chan_external_inuse[i]) {
++
++ if((dev->dwabc_chan_external_inuse[i] - jiffies) > (HZ * 120))
++ dev->dwabc_chan_external_inuse[i] = 0;
++ else
++ continue;
++ }
++#endif
+ if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) &&
+ ((pre_dev != d) || (pre_chan != dev->chanmap[i])))
+ continue;
+@@ -1819,7 +1977,11 @@
+ restore_flags(flags);
+ return i;
+ } else {
++#ifdef CONFIG_ISDN_WITH_ABC
++ if ((pre_dev == d) && ((pre_chan == dev->chanmap[i]) || pre_chan > 1000)) {
++#else
+ if ((pre_dev == d) && (pre_chan == dev->chanmap[i])) {
++#endif
+ dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
+ dev->usage[i] |= usage;
+ isdn_info_update();
+@@ -2006,7 +2168,7 @@
+
+ if ((adding) && (d->rcverr))
+ kfree(d->rcverr);
+- if (!(d->rcverr = kmalloc(sizeof(int) * m, GFP_KERNEL))) {
++ if (!(d->rcverr = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) {
+ printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
+ return -1;
+ }
+@@ -2014,7 +2176,7 @@
+
+ if ((adding) && (d->rcvcount))
+ kfree(d->rcvcount);
+- if (!(d->rcvcount = kmalloc(sizeof(int) * m, GFP_KERNEL))) {
++ if (!(d->rcvcount = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) {
+ printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
+ if (!adding) kfree(d->rcverr);
+ return -1;
+@@ -2026,7 +2188,8 @@
+ skb_queue_purge(&d->rpqueue[j]);
+ kfree(d->rpqueue);
+ }
+- if (!(d->rpqueue = kmalloc(sizeof(struct sk_buff_head) * m, GFP_KERNEL))) {
++ if (!(d->rpqueue =
++ (struct sk_buff_head *) kmalloc(sizeof(struct sk_buff_head) * m, GFP_KERNEL))) {
+ printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");
+ if (!adding) {
+ kfree(d->rcvcount);
+@@ -2040,7 +2203,8 @@
+
+ if ((adding) && (d->rcv_waitq))
+ kfree(d->rcv_waitq);
+- d->rcv_waitq = kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_KERNEL);
++ d->rcv_waitq = (wait_queue_head_t *)
++ kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_KERNEL);
+ if (!d->rcv_waitq) {
+ printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
+ if (!adding) {
+@@ -2064,7 +2228,9 @@
+ if (dev->chanmap[k] < 0) {
+ dev->chanmap[k] = j;
+ dev->drvmap[k] = drvidx;
++#ifdef HAVE_DEVFS_FS
+ isdn_register_devfs(k);
++#endif /* HAVE_DEVFS_FS */
+ break;
+ }
+ restore_flags(flags);
+@@ -2128,6 +2294,7 @@
+ i_div->ll_cmd = isdn_command; /* set command function */
+ i_div->drv_to_name = map_drvname;
+ i_div->name_to_drv = map_namedrv;
++ i_div->dial_net_name = isdn_net_force_dial;
+ MOD_INC_USE_COUNT;
+ divert_if = i_div; /* remember interface */
+ return(DIVERT_NO_ERR);
+@@ -2165,7 +2332,7 @@
+ printk(KERN_WARNING "register_isdn: No write routine given.\n");
+ return 0;
+ }
+- if (!(d = kmalloc(sizeof(driver), GFP_KERNEL))) {
++ if (!(d = (driver *) kmalloc(sizeof(driver), GFP_KERNEL))) {
+ printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n");
+ return 0;
+ }
+@@ -2225,6 +2392,7 @@
+ return rev;
+ }
+
++#ifdef HAVE_DEVFS_FS
+ #ifdef CONFIG_DEVFS_FS
+
+ static devfs_handle_t devfs_handle;
+@@ -2314,6 +2482,7 @@
+ }
+
+ #endif /* CONFIG_DEVFS_FS */
++#endif /* HAVE_DEVFS_FS */
+
+ /*
+ * Allocate and initialize all data, register modem-devices
+@@ -2331,7 +2500,6 @@
+ init_timer(&dev->timer);
+ dev->timer.function = isdn_timer_funct;
+ init_MUTEX(&dev->sem);
+- init_waitqueue_head(&dev->info_waitq);
+ for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+ dev->drvmap[i] = -1;
+ dev->chanmap[i] = -1;
+@@ -2345,7 +2513,9 @@
+ vfree(dev);
+ return -EIO;
+ }
++#ifdef HAVE_DEVFS_FS
+ isdn_init_devfs();
++#endif /* HAVE_DEVFS_FS */
+ if ((i = isdn_tty_modem_init()) < 0) {
+ printk(KERN_WARNING "isdn: Could not register tty devices\n");
+ if (i == -3)
+@@ -2353,7 +2523,9 @@
+ if (i <= -2)
+ tty_unregister_driver(&dev->mdm.tty_modem);
+ vfree(dev);
++#ifdef HAVE_DEVFS_FS
+ isdn_cleanup_devfs();
++#endif /* HAVE_DEVFS_FS */
+ devfs_unregister_chrdev(ISDN_MAJOR, "isdn");
+ return -EIO;
+ }
+@@ -2364,7 +2536,9 @@
+ tty_unregister_driver(&dev->mdm.cua_modem);
+ for (i = 0; i < ISDN_MAX_CHANNELS; i++)
+ kfree(dev->mdm.info[i].xmit_buf - 4);
++#ifdef HAVE_DEVFS_FS
+ isdn_cleanup_devfs();
++#endif /* HAVE_DEVFS_FS */
+ devfs_unregister_chrdev(ISDN_MAJOR, "isdn");
+ vfree(dev);
+ return -EIO;
+@@ -2390,6 +2564,9 @@
+ printk("\n");
+ #endif
+ isdn_info_update();
++#ifdef CONFIG_ISDN_WITH_ABC
++ isdn_dw_abc_init_func();
++#endif
+ return 0;
+ }
+
+@@ -2398,7 +2575,7 @@
+ */
+ static void __exit isdn_exit(void)
+ {
+- unsigned long flags;
++ int flags;
+ int i;
+
+ #ifdef CONFIG_ISDN_PPP
+@@ -2432,13 +2609,18 @@
+ printk(KERN_WARNING "isdn: controldevice busy, remove cancelled\n");
+ restore_flags(flags);
+ } else {
++#ifdef HAVE_DEVFS_FS
+ isdn_cleanup_devfs();
++#endif /* HAVE_DEVFS_FS */
+ del_timer(&dev->timer);
+ restore_flags(flags);
+ /* call vfree with interrupts enabled, else it will hang */
+ vfree(dev);
+ printk(KERN_NOTICE "ISDN-subsystem unloaded\n");
+ }
++#ifdef CONFIG_ISDN_WITH_ABC
++ isdn_dw_abc_release_func();
++#endif
+ }
+
+ module_init(isdn_init);
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_common.h linux-2.4.29/drivers/isdn/isdn_common.h
+--- linux-2.4.29.old/drivers/isdn/isdn_common.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_common.h 2005-03-22 15:06:44.374346856 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_common.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_common.h,v 1.22 2001/09/24 13:22:42 kai Exp $
+ *
+ * header for Linux ISDN subsystem
+ * common used functions and debugging-switches (linklevel).
+@@ -24,6 +24,9 @@
+ #undef ISDN_DEBUG_NET_DIAL
+ #undef ISDN_DEBUG_NET_ICALL
+
++#ifdef CONFIG_ISDN_WITH_ABC
++int isdn_net_force_dial_lp(isdn_net_local *);
++#endif
+ /* Prototypes */
+ extern void isdn_MOD_INC_USE_COUNT(void);
+ extern void isdn_MOD_DEC_USE_COUNT(void);
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_concap.c linux-2.4.29/drivers/isdn/isdn_concap.c
+--- linux-2.4.29.old/drivers/isdn/isdn_concap.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_concap.c 2005-03-22 15:06:44.389344576 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_concap.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_concap.c,v 1.9 2001/09/24 13:22:42 kai Exp $
+ *
+ * Linux ISDN subsystem, protocol encapsulation
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_concap.h linux-2.4.29/drivers/isdn/isdn_concap.h
+--- linux-2.4.29.old/drivers/isdn/isdn_concap.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_concap.h 2005-03-22 15:06:44.405342144 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_concap.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_concap.h,v 1.4 2001/09/24 13:22:42 kai Exp $
+ *
+ * Linux ISDN subsystem, protocol encapsulation
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_dwabc.c linux-2.4.29/drivers/isdn/isdn_dwabc.c
+--- linux-2.4.29.old/drivers/isdn/isdn_dwabc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_dwabc.c 2005-03-22 15:06:44.421339712 +0100
+@@ -0,0 +1,1053 @@
++
++/* $Id: isdn_dwabc.c,v 1.27 2001/12/01 23:18:21 detabc Exp $
++
++ * Linux ISDN subsystem, abc-extension releated funktions.
++ *
++ * Copyright by abc GmbH
++ * written by Detlef Wengorz <detlefw@isdn4linux.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, or (at your option)
++ * any later version.
++ *
++ */
++
++#include <linux/config.h>
++#define __NO_VERSION__
++
++#ifdef CONFIG_ISDN_WITH_ABC
++
++static char *dwabcrevison = "$Revision: 1.27 $";
++
++#include <asm/semaphore.h>
++#define CONFIG_ISDN_WITH_ABC_NEED_DWSJIFFIES 1
++#include <linux/list.h>
++#include <linux/isdn.h>
++#include "isdn_common.h"
++#include "isdn_net.h"
++
++#include <linux/skbuff.h>
++
++#include <net/udp.h>
++#include <net/checksum.h>
++#include <linux/isdn_dwabc.h>
++
++
++#if CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS && CONFIG_ISDN_PPP
++#include <linux/isdn_ppp.h>
++extern struct isdn_ppp_compressor *isdn_ippp_comp_head;
++#define ipc_head isdn_ippp_comp_head
++#ifndef CI_BSD_COMPRESS
++#define CI_BSD_COMPRESS 21
++#endif
++#endif
++
++#define NBYTEORDER_30BYTES 0x1e00
++#define DWABC_TMRES (HZ / 10)
++
++#define VERBLEVEL (dev->net_verbose > 2)
++
++static struct timer_list dw_abc_timer;
++
++
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++static ISDN_DWSPINLOCK lcr_spin = ISDN_DWSPIN_UNLOCKED;
++#define LCR_LOCK() isdn_dwspin_trylock(&lcr_spin)
++#define LCR_ULOCK() isdn_dwspin_unlock(&lcr_spin)
++
++typedef struct ISDN_DW_ABC_LCR {
++
++ struct list_head dll;
++ char lcr_printbuf[64 + ISDN_MSNLEN + ISDN_MSNLEN];
++ char *lcr_poin;
++ char *lcr_epoin;
++
++} ISDN_DW_ABC_LCR;
++
++static LIST_HEAD(lcr_dll);
++static atomic_t lcr_open_count = ATOMIC_INIT(0);
++static volatile ulong lcr_call_counter = 0;
++
++
++static int myjiftime(char *p,u_long nj)
++{
++ sprintf(p,"%02ld:%02ld.%02ld",
++ ((nj / 100) / 60) % 100, (nj / 100) % 60,nj % 100);
++
++ return(8);
++}
++
++
++static void dw_lcr_clear_all(void)
++{
++ struct list_head *lh;
++
++ if(!LCR_LOCK()) {
++
++ while((lh = lcr_dll.next) != &lcr_dll) {
++
++ ISDN_DW_ABC_LCR *p = list_entry(lh,ISDN_DW_ABC_LCR,dll);
++ list_del(&p->dll);
++ kfree(p);
++ }
++
++ LCR_ULOCK();
++ }
++}
++
++void isdn_dw_abc_lcr_open(void)
++{ atomic_inc(&lcr_open_count); }
++
++void isdn_dw_abc_lcr_close(void)
++{
++ if(atomic_dec_and_test(&lcr_open_count))
++ dw_lcr_clear_all();
++}
++
++int isdn_dw_abc_lcr_lock(void)
++{ return(LCR_LOCK()); }
++
++void isdn_dw_abc_lcr_ulock(void)
++{ LCR_ULOCK(); }
++
++
++size_t isdn_dw_abc_lcr_readstat(char *buf,size_t count)
++{
++ size_t retw = 0;
++
++ while(buf != NULL && count > 0) {
++
++ struct list_head *lh = NULL;
++ ISDN_DW_ABC_LCR *p = NULL;
++ char *dp = NULL;
++ size_t n;
++
++ if((n = LCR_LOCK())) {
++
++ if(!retw)
++ retw = n;
++
++ break;
++ }
++
++
++ while((lh = lcr_dll.next) != &lcr_dll) {
++
++ p = list_entry(lh,ISDN_DW_ABC_LCR,dll);
++
++ if(p->lcr_poin >= p->lcr_epoin) {
++
++ list_del(&p->dll);
++ kfree(p);
++ p = NULL;
++
++ } else break;
++ }
++
++ if(p == NULL) {
++
++ LCR_ULOCK();
++ break;
++ }
++
++ n = p->lcr_epoin - p->lcr_poin;
++
++ if(n > count)
++ n = count;
++
++ dp = p->lcr_poin;
++ p->lcr_poin += n;
++ retw += n;
++ LCR_ULOCK();
++ copy_to_user(buf,dp,n);
++ buf += n;
++ }
++
++ return(retw);
++}
++
++
++static void isdn_dw_abc_lcr_clear_helper(isdn_net_local *lp)
++{
++ if(lp != NULL) {
++
++ void *a,*b;
++
++ a = lp->dw_abc_lcr_cmd;
++ b = lp->dw_abc_lcr_io;
++ lp->dw_abc_lcr_io = NULL;
++ lp->dw_abc_lcr_cmd = NULL;
++ lp->dw_abc_lcr_callid =
++ lp->dw_abc_lcr_start_request =
++ lp->dw_abc_lcr_end_request = 0;
++
++ if(a) kfree(a);
++ if(b) kfree(b);
++ }
++}
++
++void isdn_dw_abc_lcr_clear(isdn_net_local *lp)
++{
++ if(!LCR_LOCK()) {
++ isdn_dw_abc_lcr_clear_helper(lp);
++ LCR_ULOCK();
++ }
++}
++
++
++u_long isdn_dw_abc_lcr_call_number( isdn_net_local *lp,isdn_ctrl *call_cmd)
++{
++ u_long mid = 0;
++
++ if(LCR_LOCK())
++ return(0);
++
++ isdn_dw_abc_lcr_clear_helper(lp);
++
++ if( atomic_read(&lcr_open_count) > 0 &&
++ lp != NULL &&
++ call_cmd != NULL) {
++
++ ISDN_DW_ABC_LCR *lc = NULL;
++ int ab = 0;
++
++ if((lp->dw_abc_lcr_cmd =
++ ( isdn_ctrl *)kmalloc(sizeof(isdn_ctrl),GFP_ATOMIC)) == NULL) {
++
++no_mem_out:;
++ isdn_dw_abc_lcr_clear_helper(lp);
++ LCR_ULOCK();
++ printk(KERN_DEBUG "%s %d : LCR no memory\n",__FILE__,__LINE__);
++ return(0);
++ }
++
++ memcpy(lp->dw_abc_lcr_cmd,call_cmd,sizeof(*call_cmd));
++ while(!(lp->dw_abc_lcr_callid = mid = lcr_call_counter++));
++
++ lp->dw_abc_lcr_end_request = lp->dw_abc_lcr_start_request = jiffies;
++ lp->dw_abc_lcr_end_request += HZ * 3;
++
++ if((lc = (ISDN_DW_ABC_LCR *)kmalloc(sizeof(*lc),GFP_KERNEL)) == NULL)
++ goto no_mem_out;
++
++ lc->lcr_poin = lc->lcr_epoin = lc->lcr_printbuf;
++ lc->lcr_epoin += myjiftime(lc->lcr_epoin,jiffies);
++
++ sprintf(lc->lcr_epoin," DW_ABC_LCR\t%lu\t%.*s\t%.*s\n",
++ mid,
++ (int)ISDN_MSNLEN,
++ call_cmd->parm.setup.eazmsn,
++ (int)ISDN_MSNLEN,
++ call_cmd->parm.setup.phone);
++
++ lc->lcr_epoin += strlen(lc->lcr_epoin);
++ ab = lc->lcr_epoin - lc->lcr_poin;
++
++ list_add_tail(&lc->dll,&lcr_dll);
++ LCR_ULOCK();
++
++ if(ab > 0) {
++
++ if(dev->drv[0] != NULL ) {
++
++ dev->drv[0]->stavail += ab;
++ wake_up_interruptible(&dev->drv[0]->st_waitq);
++ }
++ }
++
++ } else LCR_ULOCK();
++
++ return(mid);
++}
++
++
++int isdn_dw_abc_lcr_ioctl(u_long arg)
++{
++ struct ISDN_DWABC_LCR_IOCTL i;
++ int need = sizeof(struct ISDN_DWABC_LCR_IOCTL);
++ isdn_net_dev *p;
++
++ memset(&i,0,sizeof(struct ISDN_DWABC_LCR_IOCTL));
++ copy_from_user(&i,(char *)arg,sizeof(int));
++
++ if(i.lcr_ioctl_sizeof < need)
++ need = i.lcr_ioctl_sizeof;
++
++ if(need > 0)
++ copy_from_user(&i,(char *)arg,need);
++
++ if(LCR_LOCK())
++ return(-EAGAIN);
++
++ p = dev->netdev;
++
++ for(;p ; p = p->next) {
++
++ isdn_net_local *lp = p->local;
++
++ if( lp->dw_abc_lcr_callid != i.lcr_ioctl_callid)
++ continue;
++
++ if(lp->dw_abc_lcr_cmd == NULL)
++ continue;
++
++ if(lp->dw_abc_lcr_io == NULL)
++ lp->dw_abc_lcr_io = (struct ISDN_DWABC_LCR_IOCTL *)
++ kmalloc(sizeof(struct ISDN_DWABC_LCR_IOCTL),GFP_ATOMIC);
++
++ if(lp->dw_abc_lcr_io == NULL) {
++
++ printk(KERN_DEBUG "%s %d : no memory\n",__FILE__,__LINE__);
++ continue;
++ }
++
++ memcpy(lp->dw_abc_lcr_io,&i,sizeof(struct ISDN_DWABC_LCR_IOCTL));
++
++ if(i.lcr_ioctl_flags & DWABC_LCR_FLG_NEWNUMBER) {
++
++ char *xx = i.lcr_ioctl_nr;
++ char *exx = xx + sizeof(i.lcr_ioctl_nr);
++ char *d = lp->dw_abc_lcr_cmd->parm.setup.phone;
++ char *ed = d + sizeof(lp->dw_abc_lcr_cmd->parm.setup.phone) - 1;
++
++ while(d < ed && xx < exx && *xx) *(d++) = *(xx++);
++ while(d < ed) *(d++) = 0;
++ *d = 0;
++ }
++ }
++
++ LCR_ULOCK();
++ return(0);
++}
++
++#endif
++
++
++#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK
++int dw_abc_udp_test(struct sk_buff *skb,struct net_device *ndev)
++{
++ if(ndev != NULL && skb != NULL && skb->protocol == htons(ETH_P_IP)) {
++
++ struct iphdr *iph = (struct iphdr *)skb->data;
++ isdn_net_local *lp = (isdn_net_local *) ndev->priv;
++ int rklen = skb->len;
++
++ if (skb->nh.raw > skb->data && skb->nh.raw < skb->tail) {
++
++ rklen -= (char *)skb->nh.raw - (char *)skb->data;
++ iph = (struct iphdr *)skb->nh.raw;
++ }
++
++ if(rklen >= 20 && iph->version == 4 &&
++ !(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_UDP_CHECK)) {
++
++ if( iph->tot_len == NBYTEORDER_30BYTES &&
++ iph->protocol == IPPROTO_UDP) {
++
++ struct udphdr *udp =
++ (struct udphdr *)((char *)iph + (iph->ihl << 2));
++
++ ushort usrc = ntohs(udp->source);
++
++ if( udp->dest == htons(25001) &&
++ usrc >= 20000 && usrc < 25000) {
++
++ char *p = (char *)(udp + 1);
++
++ if(p[0] == p[1]) {
++
++ char mc = 0;
++
++ switch(*p) {
++ case 0x30:
++
++ mc = *p;
++
++ if((lp->flags & ISDN_NET_CONNECTED) && (!lp->dialstate))
++ mc++;
++
++ break;
++
++ case 0x32:
++
++ mc = *p;
++#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL
++ if((lp->flags & ISDN_NET_CONNECTED) && (!lp->dialstate)) {
++
++ mc++;
++ break;
++ }
++
++ if(!isdn_net_force_dial_lp(lp)) mc++;
++#endif
++ break;
++
++ case 0x11:
++ mc = *p + 1;
++ isdn_dw_abc_reset_interface(lp,1);
++ break;
++
++ case 0x28: mc = *p + 1; break;
++ case 0x2a:
++ case 0x2c:
++
++ mc = *p;
++#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP
++ if(!(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_UDP_HANGUP)) {
++
++ if(lp->isdn_device >= 0) {
++
++ isdn_net_hangup(ndev);
++ mc = *p + 1;
++ }
++ }
++#endif
++ break;
++ }
++
++ if(mc) {
++
++ struct sk_buff *nskb;
++ int need = 2+sizeof(struct iphdr)+sizeof(struct udphdr);
++ int hneed = need + ndev->hard_header_len;
++
++ if((nskb = (struct sk_buff *)dev_alloc_skb(hneed)) != NULL) {
++
++ ushort n = sizeof(struct udphdr) + 2;
++ struct iphdr *niph;
++ struct udphdr *nup;
++ skb_reserve(nskb,ndev->hard_header_len);
++
++ if((niph = (struct iphdr *)skb_put(nskb,need))==NULL){
++
++ printk(KERN_DEBUG "%s: skb_put failt (%d bytes)\n", lp->name,hneed);
++ dev_kfree_skb(nskb);
++ return(0);
++ }
++
++ nup = (struct udphdr *)(niph + 1);
++ ((char *)(nup + 1))[0] = mc;
++ ((char *)(nup + 1))[1] = mc;
++ nup->source=udp->dest;
++ nup->dest=udp->source;
++ nup->len=htons(n);
++ nup->check=0; /* dont need checksum */
++ memset((void *)niph,0,sizeof(*niph));
++ niph->version=4;
++ niph->ihl=5;
++ niph->tot_len=NBYTEORDER_30BYTES;
++ niph->ttl = 32;
++ niph->protocol = IPPROTO_UDP;
++ niph->saddr=iph->daddr;
++ niph->daddr=iph->saddr;
++ niph->id=iph->id;
++ niph->check=ip_fast_csum((unsigned char *)niph,niph->ihl);
++ nskb->dev = ndev;
++ nskb->pkt_type = PACKET_HOST;
++ nskb->protocol = htons(ETH_P_IP);
++ nskb->mac.raw = nskb->data;
++ netif_rx(nskb);
++ }
++
++ return(1);
++ }
++ }
++ }
++ }
++ }
++ }
++
++ return(0);
++}
++#endif
++
++
++void isdn_dw_clear_if(ulong pm,isdn_net_local *lp)
++{
++ if(lp != NULL) {
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++ isdn_dw_abc_lcr_clear(lp);
++#endif
++ }
++}
++
++
++
++static void dw_abc_timer_func(u_long dont_need_yet)
++{
++ register u_long t;
++
++ if(!((t = ++isdn_dwabc_jiffies.msec_100) & 1))
++ if(isdn_dwabc_jiffies.msec_200++ & 1)
++ isdn_dwabc_jiffies.msec_400++;
++
++ if(!(t % 5))
++ if(isdn_dwabc_jiffies.msec_500++ & 1)
++ isdn_dwabc_jiffies.msec_1000++;
++
++ dw_abc_timer.expires = jiffies + DWABC_TMRES;
++ add_timer(&dw_abc_timer);
++}
++
++
++void isdn_dw_abc_init_func(void)
++{
++
++ init_timer(&dw_abc_timer);
++ dw_abc_timer.function = dw_abc_timer_func;
++
++
++ printk( KERN_INFO
++ "abc-extension %s Kernel 0x%06X\n"
++ "written by\nDetlef Wengorz <detlefw@isdn4linux.de>\n"
++ "Installed options:\n"
++#ifdef CONFIG_ISDN_WITH_ABC_CALLB
++ "CONFIG_ISDN_WITH_ABC_CALLB\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK
++ "CONFIG_ISDN_WITH_ABC_UDP_CHECK\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP
++ "CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL
++ "CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++ "CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++ "CONFIG_ISDN_WITH_ABC_LCR_SUPPORT\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++ "CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
++ "CONFIG_ISDN_WITH_ABC_CH_EXTINUSE\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++ "CONFIG_ISDN_WITH_ABC_CONN_ERROR\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
++ "CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS\n"
++#endif
++ "loaded\n",
++ dwabcrevison,LINUX_VERSION_CODE);
++ dwsjiffies = 0;
++ dw_abc_timer.expires = jiffies + DWABC_TMRES;
++ add_timer(&dw_abc_timer);
++}
++
++void isdn_dw_abc_release_func(void)
++{
++ del_timer(&dw_abc_timer);
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++ dw_lcr_clear_all();
++#endif
++ printk( KERN_INFO
++ "abc-extension %s Kernel 0x%06X\n"
++ "written by\n"
++ "Detlef Wengorz <detlefw@isdn4linux.de>\n"
++ "unloaded\n",
++ dwabcrevison,LINUX_VERSION_CODE);
++}
++
++
++void isdn_dwabc_test_phone(isdn_net_local *lp)
++{
++ if(lp != NULL) {
++
++ isdn_net_phone *h = lp->phone[0];
++ ulong oflags = lp->dw_abc_flags;
++ int secure = 0;
++
++ lp->dw_abc_flags = 0;
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++ *lp->dw_out_msn = 0;
++#endif
++
++ for(;h != NULL && secure < 1000;secure++,h = h->next) {
++
++ char *p = h->num;
++ char *ep = p + ISDN_MSNLEN;
++
++ for(;p < ep && *p && (*p <= ' ' || *p == '"' || *p == '\'');p++);
++
++ if(p >= ep)
++ continue;
++
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++ if(*p == '>') {
++
++ if(++p < ep && *p != '<' && *p != '>') {
++
++ char *d = lp->dw_out_msn;
++
++ for(;*p && (p < ep) && (*p == ' ' || *p == '\t');p++);
++ for(ep--;*p && (p < ep);) *(d++) = *(p++);
++ *d = 0;
++ continue;
++ }
++ }
++#endif
++
++ if(*p == '~') {
++
++ /* abc switch's */
++
++ for(p++;p < ep && *p;p++) switch(*p) {
++ case 'u': lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_NO_UDP_CHECK; break;
++ case 'h': lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_NO_UDP_HANGUP; break;
++ case 'd': lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_NO_UDP_DIAL; break;
++ case 'c': lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_NO_CH_EXTINUSE; break;
++ case 'e': lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_NO_CONN_ERROR; break;
++ case 'l': lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_NO_LCR; break;
++
++ case 'x':
++ case 'X': lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER; break;
++
++ case 'B': lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_BSD_COMPRESS; break;
++ case 'L': lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_LEASED_LINE; break;
++
++ case '"':
++ case ' ':
++ case '\t':
++ case '\'': break;
++
++ default:
++ printk(KERN_DEBUG"isdn_net: %s abc-switch <~%c> unknown\n",lp->name,*p);
++ break;
++ }
++ }
++ }
++
++ if(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_LEASED_LINE) {
++
++ lp->dw_abc_flags |=
++ ISDN_DW_ABC_FLAG_NO_UDP_CHECK |
++ ISDN_DW_ABC_FLAG_NO_UDP_HANGUP |
++ ISDN_DW_ABC_FLAG_NO_UDP_DIAL |
++ ISDN_DW_ABC_FLAG_NO_CH_EXTINUSE |
++ ISDN_DW_ABC_FLAG_NO_CONN_ERROR |
++ ISDN_DW_ABC_FLAG_NO_LCR;
++ }
++
++ if(dev->net_verbose && (lp->dw_abc_flags != oflags || dev->net_verbose > 4))
++ printk(KERN_DEBUG "isdn_net %s abc-flags 0x%lx\n",lp->name,lp->dw_abc_flags);
++
++ }
++}
++
++
++int isdn_dw_abc_reset_interface(isdn_net_local *lp,int with_message)
++{
++ int r = -EINVAL;
++
++ if(lp != NULL) {
++
++ r = 0;
++
++ lp->dw_abc_bchan_last_connect = 0;
++ lp->dw_abc_dialstart = 0;
++ lp->dw_abc_inuse_secure = 0;
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++ lp->dw_abc_bchan_errcnt = 0;
++#endif
++
++ if(with_message && dev->net_verbose > 0)
++ printk(KERN_INFO
++ "%s: NOTE: reset (clear) abc-interface-secure-counter\n",
++ lp->name);
++ }
++
++ return(r);
++}
++
++
++#if CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS && CONFIG_ISDN_PPP
++
++#define DWBSD_PKT_FIRST_LEN 16
++#define DWBSD_PKT_SWITCH 165
++#define DWBSD_PKT_BSD 189
++
++#define DWBSD_VERSION 0x2
++
++void dwabc_bsd_first_gen(isdn_net_local *lp)
++{
++ if(lp != NULL && lp->p_encap == ISDN_NET_ENCAP_RAWIP &&
++ (lp->dw_abc_flags & ISDN_DW_ABC_FLAG_BSD_COMPRESS)) {
++
++ struct sk_buff *skb = NULL;
++ char *p = NULL;
++ char *ep = NULL;
++
++ if((skb =(struct sk_buff *)dev_alloc_skb(128)) == NULL) {
++
++ printk(KERN_INFO "%s: dwabc: alloc-skb failed for 128 bytes\n",lp->name);
++ return;
++ }
++
++ skb_reserve(skb,64);
++ p = skb_put(skb,DWBSD_PKT_FIRST_LEN);
++ ep = p + DWBSD_PKT_FIRST_LEN;
++
++ *(p++) = DWBSD_PKT_SWITCH;
++ *(p++) = DWBSD_VERSION;
++ for(;p < ep;p++) *(p++) = 0;
++
++ isdn_net_write_super(lp, skb);
++
++ if(dev->net_verbose > 2)
++ printk(KERN_INFO "%s: dwabc: sending comm-header version 0x%x\n",lp->name,DWBSD_VERSION);
++ }
++}
++
++
++void dwabc_bsd_free(isdn_net_local *lp)
++{
++ if(lp != NULL) {
++
++ if(lp->dw_abc_bsd_stat_rx || lp->dw_abc_bsd_stat_tx) {
++
++ struct isdn_ppp_compressor *c = NULL;
++
++ if(!(c = (struct isdn_ppp_compressor *)lp->dw_abc_bsd_compressor)) {
++
++ printk(KERN_WARNING
++ "%s: PANIC: freeing bsd compressmemory without compressor\n",
++ lp->name);
++
++ } else {
++
++ if(lp->dw_abc_bsd_stat_rx) (*c->free)(lp->dw_abc_bsd_stat_rx);
++ if(lp->dw_abc_bsd_stat_tx) (*c->free)(lp->dw_abc_bsd_stat_tx);
++
++ if(dev->net_verbose > 2)
++ printk(KERN_INFO
++ "%s: free bsd compress-memory\n",
++ lp->name);
++ }
++ }
++
++ lp->dw_abc_bsd_compressor = NULL;
++ lp->dw_abc_bsd_stat_rx = NULL;
++ lp->dw_abc_bsd_stat_tx = NULL;
++ lp->dw_abc_if_flags &= ~ISDN_DW_ABC_IFFLAG_BSDAKTIV;
++
++ if(dev->net_verbose > 0) {
++
++ if(lp->dw_abc_bsd_rcv != lp->dw_abc_bsd_bsd_rcv) {
++
++ printk(KERN_INFO "%s: Receive %lu<-%lu kb\n",lp->name,
++ lp->dw_abc_bsd_rcv >> 10 , lp->dw_abc_bsd_bsd_rcv >> 10);
++ }
++
++
++ if(lp->dw_abc_bsd_snd != lp->dw_abc_bsd_bsd_snd) {
++
++ printk(KERN_INFO "%s: Send %lu->%lu kb\n",lp->name,
++ lp->dw_abc_bsd_snd >> 10 , lp->dw_abc_bsd_bsd_snd >> 10);
++ }
++ }
++
++ lp->dw_abc_bsd_rcv =
++ lp->dw_abc_bsd_bsd_rcv =
++ lp->dw_abc_bsd_snd =
++ lp->dw_abc_bsd_bsd_snd = 0;
++ }
++}
++
++
++int dwabc_bsd_init(isdn_net_local *lp)
++{
++ int r = 1;
++
++ if(lp != NULL) {
++
++ dwabc_bsd_free(lp);
++
++ if(lp->p_encap == ISDN_NET_ENCAP_RAWIP) {
++
++ void *rx = NULL;
++ void *tx = NULL;
++ struct isdn_ppp_comp_data *cp = NULL;
++ struct isdn_ppp_compressor *c = NULL;
++
++ if(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_BSD_COMPRESS) do {
++
++ for(c = ipc_head ;
++ c != NULL && c->num != CI_BSD_COMPRESS; c = c->next);
++
++ if(c == NULL) {
++
++ printk(KERN_INFO
++ "%s: Module isdn_bsdcompress not loaded\n",
++ lp->name);
++
++ break;
++ }
++
++ cp = (struct isdn_ppp_comp_data *)
++ kmalloc(sizeof(struct isdn_ppp_comp_data),GFP_ATOMIC);
++
++ if(cp == NULL) {
++
++ printk(KERN_INFO
++ "%s: allocation of isdn_ppp_comp_data failed\n",
++ lp->name);
++
++ break;
++ }
++
++ memset(cp,0,sizeof(*cp));
++ cp->num = CI_BSD_COMPRESS;
++ cp->optlen = 1;
++
++ /*
++ ** set BSD_VERSION 1 and 12 bits compressmode
++ */
++ *cp->options = (1 << 5) | 12;
++
++ if((rx = (*c->alloc)(cp)) == NULL) {
++
++ printk(KERN_INFO
++ "%s: allocation of bsd rx-memory failed\n",
++ lp->name);
++
++ break;
++ }
++
++ if(!(*c->init)(rx,cp,0,1)) {
++
++ printk(KERN_INFO
++ "%s: init of bsd rx-stream failed\n",lp->name);
++
++ break;
++ }
++
++ cp->flags = IPPP_COMP_FLAG_XMIT;
++
++ if((tx = (*c->alloc)(cp)) == NULL) {
++
++ printk(KERN_INFO
++ "%s: allocation of bsd tx-memory failed\n",
++ lp->name);
++
++ break;
++ }
++
++ if(!(*c->init)(tx,cp,0,1)) {
++
++ printk(KERN_INFO
++ "%s: init of bsd tx-stream failed\n",
++ lp->name);
++
++ break;
++ }
++
++ lp->dw_abc_bsd_compressor = (void *)c;
++ lp->dw_abc_bsd_stat_rx = rx;
++ lp->dw_abc_bsd_stat_tx = tx;
++ rx = tx = NULL;
++ r = 0;
++
++ if(dev->net_verbose > 2)
++ printk(KERN_INFO
++ "%s: bsd compress-memory and init ok\n",
++ lp->name);
++
++ } while(0);
++
++ if(cp != NULL)
++ kfree(cp);
++
++ if(c != NULL) {
++
++ if(tx != NULL) (*c->free)(tx);
++ if(rx != NULL) (*c->free)(rx);
++ }
++
++ } else if(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_BSD_COMPRESS) {
++
++ printk(KERN_INFO
++ "%s: bsd-compress only with encapsulation rawip allowed\n",
++ lp->name);
++ }
++ }
++
++ return(r);
++}
++
++struct sk_buff *dwabc_bsd_compress( isdn_net_local *lp,
++ struct sk_buff *skb,
++ struct net_device *ndev)
++{
++ if(lp != NULL && lp->p_encap == ISDN_NET_ENCAP_RAWIP &&
++ (lp->dw_abc_flags & ISDN_DW_ABC_FLAG_BSD_COMPRESS) &&
++ (lp->dw_abc_if_flags & ISDN_DW_ABC_IFFLAG_BSDAKTIV)) {
++
++ if(lp->dw_abc_bsd_stat_tx != NULL && lp->dw_abc_bsd_compressor) {
++
++ struct isdn_ppp_compressor *cp =
++ (struct isdn_ppp_compressor *)lp->dw_abc_bsd_compressor;
++
++ struct sk_buff *nskb = (struct sk_buff *)
++ dev_alloc_skb(skb->len * 2 + ndev->hard_header_len);
++
++ int l = 0;
++
++ if(nskb == NULL) {
++
++ (void)(*cp->reset)(lp->dw_abc_bsd_stat_tx,0,0,NULL,0,NULL);
++ printk(KERN_INFO "%s: dwabc-compress no memory\n",lp->name);
++
++ } else {
++
++ skb_reserve(nskb,ndev->hard_header_len);
++ *(unsigned char *)skb_put(nskb,1) = DWBSD_PKT_BSD;
++ l = (*cp->compress)(lp->dw_abc_bsd_stat_tx,skb,nskb,0x21);
++
++ if(l < 1 || l > skb->len) {
++
++ (void)(*cp->reset)(lp->dw_abc_bsd_stat_tx,0,0,NULL,0,NULL);
++ dev_kfree_skb(nskb);
++
++ } else {
++
++ u_short sqnr;
++
++ dev_kfree_skb(skb);
++ skb = nskb;
++ sqnr = ((*(u_char *)skb->data) << 8) +
++ ((u_char)skb->data[1]);
++
++ if(sqnr > 65500)
++ (void)(*cp->reset)
++ (lp->dw_abc_bsd_stat_tx,0,0,NULL,0,NULL);
++ }
++ }
++ }
++ }
++
++ return(skb);
++}
++
++struct sk_buff *dwabc_bsd_rx_pkt( isdn_net_local *lp,
++ struct sk_buff *skb,
++ struct net_device *ndev)
++{
++ struct sk_buff *r = skb;
++
++ if(lp != NULL && lp->p_encap == ISDN_NET_ENCAP_RAWIP &&
++ (lp->dw_abc_flags & ISDN_DW_ABC_FLAG_BSD_COMPRESS)) {
++
++ unsigned char *p = (unsigned char *)skb->data;
++ struct isdn_ppp_compressor *cp =
++ (struct isdn_ppp_compressor *)lp->dw_abc_bsd_compressor;
++
++ if(*p == DWBSD_PKT_SWITCH) {
++
++ if(skb->len == DWBSD_PKT_FIRST_LEN) {
++
++ if((lp->dw_abc_remote_version = p[1]) < 0x2) {
++
++ printk(KERN_INFO
++ "%s: I can't really talk with remote version 0x%x\n"
++ "Please upgrade remote or disable rawip-compression\n",
++ lp->name,
++ p[1]);
++ }
++
++ lp->dw_abc_if_flags |= ISDN_DW_ABC_IFFLAG_BSDAKTIV;
++ dev_kfree_skb(skb);
++
++ if(cp && lp->dw_abc_bsd_stat_tx)
++ (void)(*cp->reset)(lp->dw_abc_bsd_stat_tx,0,0,NULL,0,NULL);
++
++ if(dev->net_verbose > 2)
++ printk(KERN_INFO
++ "%s: receive comm-header rem-version 0x%02x\n",
++ lp->name,
++ lp->dw_abc_remote_version);
++
++ return(NULL);
++ }
++
++ } else if(*p == DWBSD_PKT_BSD && lp->dw_abc_bsd_stat_rx != NULL && cp) {
++
++ struct sk_buff *nskb = NULL;
++
++ if(test_and_set_bit(ISDN_DW_ABC_BITLOCK_RECEIVE,
++ &lp->dw_abc_bitlocks)) {
++
++ printk(KERN_INFO "%s: bsd-decomp called recursivly\n",lp->name);
++ dev_kfree_skb(skb);
++ dwabc_bsd_first_gen(lp);
++ return(NULL);
++ }
++
++ nskb = (struct sk_buff *)
++ dev_alloc_skb(2048 + ndev->hard_header_len);
++
++ if(nskb != NULL) {
++
++ int l = 0;
++ u_short sqnr;
++
++ skb_reserve(nskb,ndev->hard_header_len);
++ skb_pull(skb, 1);
++ sqnr = ((*(u_char *)skb->data) << 8) | ((u_char)skb->data[1]);
++
++ if(!sqnr && cp && lp->dw_abc_bsd_stat_rx)
++ (void)(*cp->reset)(lp->dw_abc_bsd_stat_rx,0,0,NULL,0,NULL);
++
++ if((l = (*cp->decompress)
++ (lp->dw_abc_bsd_stat_rx,skb,nskb,NULL)) < 1 || l>8000) {
++
++ printk(KERN_INFO "%s: abc-decomp failed\n",lp->name);
++ dev_kfree_skb(nskb);
++ dev_kfree_skb(skb);
++ nskb = NULL;
++ dwabc_bsd_first_gen(lp);
++
++ } else {
++
++ if (nskb->data[0] & 0x1)
++ skb_pull(nskb, 1); /* protocol ID is only 8 bit */
++ else
++ skb_pull(nskb, 2);
++
++ nskb->dev = skb->dev;
++ nskb->pkt_type = skb->pkt_type;
++ nskb->mac.raw = nskb->data;
++ dev_kfree_skb(skb);
++ }
++
++ } else {
++
++ printk(KERN_INFO "%s: PANIC abc-decomp no memory\n",lp->name);
++ dev_kfree_skb(skb);
++ dwabc_bsd_first_gen(lp);
++ }
++
++ clear_bit(ISDN_DW_ABC_BITLOCK_RECEIVE,&lp->dw_abc_bitlocks);
++ r = nskb;
++ }
++ }
++
++ return(r);
++}
++
++#else
++int dwabc_bsd_init(isdn_net_local *lp) { return(1); }
++void dwabc_bsd_free(isdn_net_local *lp) { return; }
++void dwabc_bsd_first_gen(isdn_net_local *lp) { return ; }
++
++struct sk_buff *dwabc_bsd_compress(isdn_net_local *lp,struct sk_buff *skb,struct net_device *ndev)
++{ return(skb); }
++
++struct sk_buff *dwabc_bsd_rx_pkt(isdn_net_local *lp,struct sk_buff *skb,struct net_device *ndev)
++{ return(skb); }
++#endif
++#endif
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_net.c linux-2.4.29/drivers/isdn/isdn_net.c
+--- linux-2.4.29.old/drivers/isdn/isdn_net.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_net.c 2005-03-22 15:06:44.447335760 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_net.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_net.c,v 1.153 2002/08/17 18:35:23 detabc Exp $
+ *
+ * Linux ISDN subsystem, network interfaces and related functions (linklevel).
+ *
+@@ -9,14 +9,6 @@
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+- * Data Over Voice (DOV) support added - Guy Ellis 23-Mar-02
+- * guy@traverse.com.au
+- * Outgoing calls - looks for a 'V' in first char of dialed number
+- * Incoming calls - checks first character of eaz as follows:
+- * Numeric - accept DATA only - original functionality
+- * 'V' - accept VOICE (DOV) only
+- * 'B' - accept BOTH DATA and DOV types
+- *
+ * Jan 2001: fix CISCO HDLC Bjoern A. Zeeb <i4l@zabbadoz.net>
+ * for info on the protocol, see
+ * http://i4l.zabbadoz.net/i4l/cisco-hdlc.txt
+@@ -38,6 +30,10 @@
+ #include "isdn_concap.h"
+ #endif
+
++#ifdef CONFIG_ISDN_WITH_ABC
++#include <linux/isdn_dwabc.h>
++#define isdn_net_log_skb(skb,lp) isdn_net_log_skb_dwabc(skb,lp,NULL)
++#endif
+
+ /*
+ * Outline of new tbusy handling:
+@@ -79,7 +75,11 @@
+ dev = lp->master;
+ else
+ dev = &n->dev;
++#ifdef COMPAT_NO_SOFTNET
++ return dev->start;
++#else
+ return netif_running(dev);
++#endif
+ }
+
+ /*
+@@ -143,6 +143,10 @@
+ atomic_inc(&lp->frame_cnt);
+ if (isdn_net_device_busy(lp))
+ isdn_net_device_stop_queue(lp);
++#if 0
++ printk(KERN_DEBUG "%s: inc_frame_cnt now %d\n", lp->name,
++ atomic_read(&lp->frame_cnt));
++#endif
+ }
+
+ static __inline__ void isdn_net_dec_frame_cnt(isdn_net_local *lp)
+@@ -157,11 +161,19 @@
+ isdn_net_device_wake_queue(lp);
+ }
+ }
++#if 0
++ printk(KERN_DEBUG "%s: dec_frame_cnt now %d\n", lp->name,
++ atomic_read(&lp->frame_cnt));
++#endif
+ }
+
+ static __inline__ void isdn_net_zero_frame_cnt(isdn_net_local *lp)
+ {
+ atomic_set(&lp->frame_cnt, 0);
++#if 0
++ printk(KERN_DEBUG "%s: zero_frame_cnt now %d\n", lp->name,
++ atomic_read(&lp->frame_cnt));
++#endif
+ }
+
+ /* For 2.2.x we leave the transmitter busy timeout at 2 secs, just
+@@ -173,23 +185,101 @@
+ * which might rely on the tx timeout. If so, we'll find out this way...
+ */
+
++#ifdef COMPAT_NO_SOFTNET
++#define ISDN_NET_TX_TIMEOUT (2*HZ)
++#else
+ #define ISDN_NET_TX_TIMEOUT (20*HZ)
++#endif
+
+ /* Prototypes */
+
++#ifndef CONFIG_ISDN_WITH_ABC
+ int isdn_net_force_dial_lp(isdn_net_local *);
++#endif
+ static int isdn_net_start_xmit(struct sk_buff *, struct net_device *);
+
+ static void isdn_net_ciscohdlck_connected(isdn_net_local *lp);
+ static void isdn_net_ciscohdlck_disconnected(isdn_net_local *lp);
+
+-char *isdn_net_revision = "$Revision: 1.1.4.1 $";
++char *isdn_net_revision = "$Revision: 1.153 $";
+
+ /*
+ * Code for raw-networking over ISDN
+ */
++#ifdef CONFIG_ISDN_WITH_ABC
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++static int isdn_dwabc_encap_with_conerr(isdn_net_local *lp)
++{
++ if(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_CONN_ERROR)
++ return(0);
++
++ return(
++ lp->p_encap == ISDN_NET_ENCAP_SYNCPPP ||
++ lp->p_encap == ISDN_NET_ENCAP_RAWIP ||
++ lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK ||
++ lp->p_encap == ISDN_NET_ENCAP_UIHDLC );
++}
++
++static int isdn_dwabc_conerr_ippktok(struct sk_buff *skb)
++{
++ struct iphdr *iph = (struct iphdr *)skb->data;
++ return(iph->version == 6 || (skb->len >= 20 && iph->version == 4));
++}
++
++#endif
++
++static int isdn_dwabc_is_interface_disabled(isdn_net_local *lp)
++{
++ if(lp == NULL)
++ return(0);
++
++ lp->dw_abc_inuse_secure = 0;
++ lp->dw_abc_dialstart = 0;
++
++ /*
++ ** check for jiffies overflow
++ */
++ if(lp->dw_abc_bchan_last_connect > jiffies) {
++
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++ lp->dw_abc_bchan_errcnt = 0;
++#endif
++ lp->dw_abc_bchan_last_connect = 0;
++ }
++
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++ if(!(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_CONN_ERROR) && isdn_dwabc_encap_with_conerr(lp)) {
++
++ if(lp->dw_abc_bchan_errcnt > 3 && !(lp->dw_abc_bchan_errcnt & 3)) {
+
++ ulong nj = jiffies;
++ ulong delay = lp->dw_abc_bchan_errcnt *
++ lp->dw_abc_bchan_errcnt *
++ lp->dw_abc_bchan_errcnt;
++
++ if(delay > 86400) delay = 86400;
++ delay = (lp->dw_abc_bchan_last_connect + delay * HZ);
++
++ if(delay > nj) {
++
++ printk(KERN_INFO
++ "%s: interface auto-disabled (bchannel connect-error %lu seconds left)\n",
++ lp->name,(delay - nj) / HZ);
++
++ return(1);
++ }
++ }
++ }
++#endif
++ return(0);
++}
++#endif
++
++#ifdef CONFIG_ISDN_WITH_ABC
++void
++#else
+ static void
++#endif
+ isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
+ {
+ if(skb) {
+@@ -297,6 +387,12 @@
+
+ save_flags(flags);
+ cli();
++#ifdef CONFIG_ISDN_WITH_ABC
++ isdn_dw_clear_if(0l,lp);
++ lp->dw_abc_if_flags &= ~ISDN_DW_ABC_IFFLAG_NODCHAN;
++ lp->dw_abc_inuse_secure = 0;
++ dwabc_bsd_free(lp);
++#endif
+ skb_queue_purge(&lp->super_tx_queue);
+
+ if (!lp->master) { /* reset only master device */
+@@ -351,6 +447,26 @@
+ if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) {
+ anymore = 1;
+ l->huptimer++;
++#ifdef CONFIG_ISDN_WITH_ABC
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++ if( isdn_dwabc_encap_with_conerr(l) && l->dw_abc_bchan_errcnt > 0) {
++
++ int n = 180;
++
++ if(l->dw_abc_bchan_errcnt > 3) n = 120;
++ if(l->dw_abc_bchan_errcnt > 6) n = 90;
++ if(l->dw_abc_bchan_errcnt > 9) n = 60;
++
++ if(l->huptimer > n) {
++
++ printk(KERN_INFO "%s: bchan conf-error auto-secure-hangup\n",l->name);
++ isdn_net_hangup(&p->dev);
++ p = (isdn_net_dev *) p->next;
++ continue;
++ }
++ }
++#endif
++#endif
+ /*
+ * if there is some dialmode where timeout-hangup
+ * should _not_ be done, check for that here
+@@ -465,8 +581,32 @@
+ printk(KERN_INFO "%s: Chargesum is %d\n", lp->name,
+ lp->charge);
+ isdn_net_unbind_channel(lp);
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++ if(lp->dw_abc_bchan_errcnt) {
++
++ printk(KERN_INFO
++ "%s: Note: bchannel-error-counter is %hd\n",
++ lp->name,
++ lp->dw_abc_bchan_errcnt);
++ }
++#endif
+ return 1;
+ }
++#ifdef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
++ if(!(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_CH_EXTINUSE)) {
++ if((lp->dialstate == 4 || lp->dialstate == 12) &&
++ lp->dw_abc_dialstart && (idx < ISDN_MAX_CHANNELS)) {
++
++ if((jiffies - lp->dw_abc_dialstart) < (HZ >>2)) {
++
++ lp->dw_abc_if_flags |= ISDN_DW_ABC_IFFLAG_NODCHAN;
++ lp->dialstate = 1;
++ dev->dwabc_chan_external_inuse[idx] = jiffies + HZ * 30;
++ printk(KERN_INFO "%s: Channel %d look like external in use\n",lp->name,idx);
++ }
++ }
++ }
++#endif
+ break;
+ #ifdef CONFIG_ISDN_X25
+ case ISDN_STAT_BHUP:
+@@ -507,6 +647,19 @@
+ }
+ }
+ printk(KERN_INFO "isdn_net: %s connected\n", lp->name);
++#ifdef CONFIG_ISDN_WITH_ABC
++ if(!dwabc_bsd_init(lp)) dwabc_bsd_first_gen(lp);
++ lp->dw_abc_bchan_last_connect = jiffies;
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++ if(!(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_CONN_ERROR)) {
++
++ lp->dw_abc_bchan_errcnt += isdn_dwabc_encap_with_conerr(lp);
++
++ if(lp->dw_abc_bchan_errcnt > 32000)
++ lp->dw_abc_bchan_errcnt = 32000;
++ }
++#endif
++#endif
+ /* If first Chargeinfo comes before B-Channel connect,
+ * we correct the timestamp here.
+ */
+@@ -578,7 +731,6 @@
+ int i;
+ unsigned long flags;
+ isdn_ctrl cmd;
+- u_char *phone_number;
+
+ while (p) {
+ isdn_net_local *lp = p->local;
+@@ -597,6 +749,47 @@
+ */
+ save_flags(flags);
+ cli();
++#ifdef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
++ if(!(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_CH_EXTINUSE) &&
++ (lp->dw_abc_if_flags & ISDN_DW_ABC_IFFLAG_NODCHAN)) {
++
++ int chi = 0;
++ short lsecure = 0;
++
++ lsecure = lp->dw_abc_inuse_secure;
++ isdn_net_unbind_channel(lp);
++ lp->dw_abc_inuse_secure = lsecure + 1;
++
++ /* Grab a free ISDN-Channel */
++ if ((lsecure >= ISDN_MAX_CHANNELS ) || (chi =
++ isdn_get_free_channel(
++ ISDN_USAGE_NET,
++ lp->l2_proto,
++ lp->l3_proto,
++ lp->pre_device,
++ lp->pre_channel,
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++ (*lp->dw_out_msn) ? lp->dw_out_msn : lp->msn)
++#else
++ lp->msn)
++#endif
++ ) < 0) {
++
++ restore_flags(flags);
++ isdn_net_unreachable(&p->dev, NULL,
++ "DWABC: redial-external-inuse NO FREE CHANNEL\n");
++ isdn_net_hangup(&p->dev);
++ break;
++ }
++
++ isdn_net_bind_channel(lp, chi);
++ lp->dialstate = 1;
++ lp->dialstarted = 0;
++ lp->dialwait_timer = 0;
++ }
++
++ lp->dw_abc_if_flags &= ~ISDN_DW_ABC_IFFLAG_NODCHAN;
++#endif
+ lp->dial = lp->phone[1];
+ restore_flags(flags);
+ if (!lp->dial) {
+@@ -621,18 +814,69 @@
+ cmd.arg = lp->isdn_channel;
+ cmd.command = ISDN_CMD_CLREAZ;
+ isdn_command(&cmd);
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++ sprintf(cmd.parm.num, "%s",
++ isdn_map_eaz2msn((*lp->dw_out_msn) ? lp->dw_out_msn : lp->msn, cmd.driver));
++#else
+ sprintf(cmd.parm.num, "%s", isdn_map_eaz2msn(lp->msn, cmd.driver));
++#endif
+ cmd.command = ISDN_CMD_SETEAZ;
+ isdn_command(&cmd);
+ lp->dialretry = 0;
+ anymore = 1;
+ lp->dialstate++;
++#ifdef CONFIG_ISDN_WITH_ABC
++ lp->onhtime = lp->dw_abc_old_onhtime;
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++ isdn_dw_abc_lcr_clear(lp);
++#endif
++#endif
+ /* Fall through */
+ case 3:
+ /* Setup interface, dial current phone-number, switch to next number.
+ * If list of phone-numbers is exhausted, increment
+ * retry-counter.
+ */
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++ if(!isdn_dw_abc_lcr_lock()) {
++
++ if( lp->dw_abc_lcr_cmd != NULL &&
++ lp->dw_abc_lcr_start_request !=
++ lp->dw_abc_lcr_end_request) {
++
++ if( lp->dw_abc_lcr_io == NULL &&
++ lp->dw_abc_lcr_start_request <= jiffies &&
++ lp->dw_abc_lcr_end_request > jiffies) {
++
++ isdn_dw_abc_lcr_ulock();
++ anymore = 1;
++ break;
++ }
++
++ if(lp->dw_abc_lcr_io != NULL) {
++
++ if(lp->dw_abc_lcr_io->lcr_ioctl_flags &
++ DWABC_LCR_FLG_DISABLE) {
++
++ isdn_dw_abc_lcr_ulock();
++ isdn_net_hangup(&p->dev);
++ break;
++ }
++
++ if(lp->dw_abc_lcr_io->lcr_ioctl_flags &
++ DWABC_LCR_FLG_NEWHUPTIME) {
++ lp->onhtime = lp->dw_abc_lcr_io->lcr_ioctl_onhtime;
++ }
++ }
++
++ memcpy(&cmd,lp->dw_abc_lcr_cmd,sizeof(cmd));
++ isdn_dw_abc_lcr_ulock();
++ goto dw_abc_lcr_next_click;
++ }
++
++ isdn_dw_abc_lcr_ulock();
++ }
++#endif
+ if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) {
+ char *s;
+ if (dev->global_flags & ISDN_GLOBAL_STOPPED)
+@@ -677,20 +921,7 @@
+ break;
+ }
+
+- cmd.driver = lp->isdn_device;
+- cmd.command = ISDN_CMD_DIAL;
+- cmd.parm.setup.si2 = 0;
+-
+- /* check for DOV */
+- phone_number = lp->dial->num;
+- if ((*phone_number == 'v') ||
+- (*phone_number == 'V')) { /* DOV call */
+- cmd.parm.setup.si1 = 1;
+- } else { /* DATA call */
+- cmd.parm.setup.si1 = 7;
+- }
+-
+- strcpy(cmd.parm.setup.phone, phone_number);
++ sprintf(cmd.parm.setup.phone, "%s", lp->dial->num);
+ /*
+ * Switch to next number or back to start if at end of list.
+ */
+@@ -710,17 +941,70 @@
+ }
+ }
+ restore_flags(flags);
++ cmd.driver = lp->isdn_device;
++ cmd.command = ISDN_CMD_DIAL;
++ cmd.parm.setup.si1 = 7;
++ cmd.parm.setup.si2 = 0;
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++ sprintf(cmd.parm.setup.eazmsn, "%s",
++ isdn_map_eaz2msn((*lp->dw_out_msn) ? lp->dw_out_msn : lp->msn, cmd.driver));
++#else
+ sprintf(cmd.parm.setup.eazmsn, "%s",
+ isdn_map_eaz2msn(lp->msn, cmd.driver));
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++ /*
++ ** if callback-out we dont need
++ ** low-cost-routing LCR
++ */
++ if(!(lp->flags & ISDN_NET_CBOUT) &&
++ !(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_LCR)) {
++
++ isdn_dw_abc_lcr_call_number(lp,&cmd);
++
++ if(lp->dw_abc_lcr_start_request != lp->dw_abc_lcr_end_request) {
++
++ if(dev->net_verbose > 2) {
++
++ printk(KERN_INFO
++ "%s: Waiting for LCR-response from isdnlog %s -> %s...\n",
++ lp->name,
++ cmd.parm.setup.eazmsn,
++ cmd.parm.setup.phone);
++ }
++
++ anymore = 1;
++ break;
++ }
++ }
++
++dw_abc_lcr_next_click:;
++ isdn_dw_abc_lcr_clear(lp);
++#endif
+ i = isdn_dc2minor(lp->isdn_device, lp->isdn_channel);
+ if (i >= 0) {
+ strcpy(dev->num[i], cmd.parm.setup.phone);
+ dev->usage[i] |= ISDN_USAGE_OUTGOING;
+ isdn_info_update();
+ }
+- printk(KERN_INFO "%s: dialing %d %s... %s\n", lp->name,
+- lp->dialretry, cmd.parm.setup.phone,
+- (cmd.parm.setup.si1 == 1) ? "DOV" : "");
++#ifdef CONFIG_ISDN_WITH_ABC
++ printk(KERN_INFO "%s: dialing %d %s -> %s...\n", lp->name,
++ lp->dialretry,
++ cmd.parm.setup.eazmsn,
++ cmd.parm.setup.phone);
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++ if(lp->dw_abc_bchan_errcnt) {
++
++ printk(KERN_INFO
++ "%s: Note: bchannel-error-counter is %hd\n",
++ lp->name,
++ lp->dw_abc_bchan_errcnt);
++ }
++#endif
++#else
++ printk(KERN_INFO "%s: dialing %d %s...\n", lp->name,
++ lp->dialretry, cmd.parm.setup.phone);
++#endif
+ lp->dtimer = 0;
+ #ifdef ISDN_DEBUG_NET_DIAL
+ printk(KERN_DEBUG "dial: d=%d c=%d\n", lp->isdn_device,
+@@ -741,6 +1025,10 @@
+ lp->dialstate =
+ (lp->cbdelay &&
+ (lp->flags & ISDN_NET_CBOUT)) ? 12 : 4;
++#ifdef CONFIG_ISDN_WITH_ABC
++ lp->dw_abc_if_flags &= ~ISDN_DW_ABC_IFFLAG_NODCHAN;
++ lp->dw_abc_dialstart = jiffies;
++#endif
+ break;
+ case 4:
+ /* Wait for D-Channel-connect.
+@@ -890,6 +1178,15 @@
+ isdn_command(&cmd);
+ printk(KERN_INFO "%s: Chargesum is %d\n", lp->name, lp->charge);
+ isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++ if(lp->dw_abc_bchan_errcnt) {
++
++ printk(KERN_INFO
++ "%s: Note: bchannel-error-counter is %hd\n",
++ lp->name,
++ lp->dw_abc_bchan_errcnt);
++ }
++#endif
+ }
+ isdn_net_unbind_channel(lp);
+ }
+@@ -899,8 +1196,13 @@
+ unsigned short dest;
+ } ip_ports;
+
++#ifdef CONFIG_ISDN_WITH_ABC
++void
++isdn_net_log_skb_dwabc(struct sk_buff * skb, isdn_net_local * lp,char *reason)
++#else
+ static void
+ isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp)
++#endif
+ {
+ u_char *p = skb->nh.raw; /* hopefully, this was set correctly */
+ unsigned short proto = ntohs(skb->protocol);
+@@ -972,7 +1274,13 @@
+ break;
+ }
+ printk(KERN_INFO
++#ifdef CONFIG_ISDN_WITH_ABC
++ "%s %s: %d.%d.%d.%d -> %d.%d.%d.%d%s\n",
++ (reason == NULL) ? "OPEN" : reason,
++ (lp != NULL) ? lp->name : "",
++#else
+ "OPEN: %d.%d.%d.%d -> %d.%d.%d.%d%s\n",
++#endif
+
+ p[12], p[13], p[14], p[15],
+ p[16], p[17], p[18], p[19],
+@@ -980,7 +1288,13 @@
+ break;
+ case ETH_P_ARP:
+ printk(KERN_INFO
++#ifdef CONFIG_ISDN_WITH_ABC
++ "%s %s: ARP %d.%d.%d.%d -> *.*.*.* ?%d.%d.%d.%d\n",
++ (reason == NULL) ? "OPEN" : reason,
++ (lp != NULL) ? lp->name : "",
++#else
+ "OPEN: ARP %d.%d.%d.%d -> *.*.*.* ?%d.%d.%d.%d\n",
++#endif
+ p[14], p[15], p[16], p[17],
+ p[24], p[25], p[26], p[27]);
+ break;
+@@ -1004,11 +1318,22 @@
+ }
+
+ spin_lock_bh(&lp->xmit_lock);
++
+ if (!isdn_net_lp_busy(lp)) {
++#ifdef CONFIG_ISDN_WITH_ABC
++ if(!skb_queue_empty(&lp->super_tx_queue)) {
++ /*
++ ** don't reverse the frame flow
++ ** compression need frames in order and maybe other's too
++ */
++ skb_queue_tail(&lp->super_tx_queue, skb);
++ skb = skb_dequeue(&lp->super_tx_queue);
++ }
++#endif
+ isdn_net_writebuf_skb(lp, skb);
+- } else {
+- skb_queue_tail(&lp->super_tx_queue, skb);
+- }
++
++ } else skb_queue_tail(&lp->super_tx_queue, skb);
++
+ spin_unlock_bh(&lp->xmit_lock);
+ }
+
+@@ -1056,7 +1381,6 @@
+ printk(KERN_WARNING "%s: HL driver queue full\n", lp->name);
+ goto error;
+ }
+-
+ lp->transcount += len;
+ isdn_net_inc_frame_cnt(lp);
+ return;
+@@ -1064,9 +1388,19 @@
+ error:
+ dev_kfree_skb(skb);
+ lp->stats.tx_errors++;
+-
+ }
+
++#if 0
++int isdn_net_send_skb(struct net_device *ndev, isdn_net_local * lp,struct sk_buff *skb)
++{
++ if (isdn_net_lp_busy(lp)) {
++ printk(KERN_WARNING "isdn_net_send_skb: HL channel busy\n");
++ return 1;
++ }
++ isdn_net_writebuf_skb(lp, skb);
++ return 0;
++}
++#endif
+
+ /*
+ * Helper function for isdn_net_start_xmit.
+@@ -1109,7 +1443,54 @@
+
+ /* Reset hangup-timeout */
+ lp->huptimer = 0; // FIXME?
++#ifdef CONFIG_ISDN_WITH_ABC
++
++ if(test_and_set_bit(ISDN_DW_ABC_BITLOCK_SEND,&lp->dw_abc_bitlocks)) {
++
++ if(dev->net_verbose > 2)
++ printk(KERN_INFO "%s: isdn_net_xmit called recursivly\n",lp->name);
++
++ spin_unlock_bh(&lp->xmit_lock);
++ return(1);
++ }
++
++ if(skb != NULL) {
++
++ int l = skb->len;
++ int nl = l;
++
++ if( lp->p_encap == ISDN_NET_ENCAP_RAWIP &&
++ (lp->dw_abc_if_flags & ISDN_DW_ABC_IFFLAG_BSDAKTIV)) {
++
++ if((skb = dwabc_bsd_compress(lp,skb,ndev)) != NULL) {
++
++ int r = 0;
++ nl = skb->len;
++ skb_queue_tail(&lp->super_tx_queue,skb);
++
++ if(l != nl && (r = isdn_dc2minor(lp->isdn_device,lp->isdn_channel)) >= 0) {
++
++ dev->obytes[r] += l - nl;
++ lp->stats.tx_bytes += l - nl;
++ }
++ }
++
++ } else skb_queue_tail(&lp->super_tx_queue,skb);
++
++ if(lp->p_encap == ISDN_NET_ENCAP_RAWIP) {
++
++ lp->dw_abc_bsd_snd += l;
++ lp->dw_abc_bsd_bsd_snd += nl;
++ }
++ }
++ clear_bit(ISDN_DW_ABC_BITLOCK_SEND,&lp->dw_abc_bitlocks);
++
++ while(!isdn_net_lp_busy(lp) && (skb = skb_dequeue(&lp->super_tx_queue)))
++ isdn_net_writebuf_skb(lp, skb);
++
++#else
+ isdn_net_writebuf_skb(lp, skb);
++#endif
+ spin_unlock_bh(&lp->xmit_lock);
+
+ /* the following stuff is here for backwards compatibility.
+@@ -1143,6 +1524,69 @@
+
+ return retv;
+
++#if 0
++ if (lp->cps > lp->triggercps) {
++ /* Device overloaded */
++
++ /*
++ * Packet-delivery via round-robin over master
++ * and all connected slaves.
++ */
++ if (lp->master) {
++ /* Slaves always deliver themselves */
++ spin_lock_bh(&lp->xmit_lock);
++ if (!isdn_net_lp_busy(lp)) {
++ isdn_net_writebuf_skb(lp, skb);
++ ret = 0;
++ } else {
++ isdn_net_device_stop_queue(lp);
++ ret = 1;
++ }
++ ret = isdn_net_send_skb(ndev, lp, skb);
++ spin_unlock_bh(&lp->xmit_lock);
++ } else {
++ isdn_net_local *slp = (isdn_net_local *) (lp->srobin->priv);
++ /* Master delivers via srobin and maintains srobin */
++ if (lp->srobin == ndev) {
++ spin_lock_bh(&lp->xmit_lock);
++ ret = isdn_net_send_skb(ndev, lp, skb);
++ spin_unlock_bh(&lp->xmit_lock);
++ } else {
++ ret = isdn_net_start_xmit(skb, lp->srobin);
++ }
++ lp->srobin = (slp->slave) ? slp->slave : ndev;
++ slp = (isdn_net_local *) (lp->srobin->priv);
++ if (!((slp->flags & ISDN_NET_CONNECTED) && (slp->dialstate == 0)))
++ lp->srobin = ndev;
++ }
++ /* Slave-startup using delay-variable */
++ if (lp->slave) {
++ if (!lp->sqfull) {
++ /* First time overload: set timestamp only */
++ lp->sqfull = 1;
++ lp->sqfull_stamp = jiffies;
++ } else {
++ /* subsequent overload: if slavedelay exceeded, start dialing */
++ if ((jiffies - lp->sqfull_stamp) > lp->slavedelay)
++ isdn_net_force_dial_lp((isdn_net_local *) lp->slave->priv);
++ }
++ }
++ } else {
++ /* Not overloaded, deliver locally */
++ spin_lock_bh(&lp->xmit_lock);
++ if (!isdn_net_lp_busy(lp)) {
++ isdn_net_writebuf_skb(lp, skb);
++ ret = 0;
++ } else {
++ isdn_net_device_stop_queue(lp);
++ ret = 1;
++ }
++ spin_unlock_bh(&lp->xmit_lock);
++ if (lp->sqfull && ((jiffies - lp->sqfull_stamp) > (lp->slavedelay + (10 * HZ))))
++ lp->sqfull = 0;
++ }
++ return ret;
++#endif
+ }
+
+ static void
+@@ -1161,6 +1605,7 @@
+ }
+
+
++#ifndef COMPAT_NO_SOFTNET
+ void isdn_net_tx_timeout(struct net_device * ndev)
+ {
+ isdn_net_local *lp = (isdn_net_local *) ndev->priv;
+@@ -1188,19 +1633,206 @@
+ ndev->trans_start = jiffies;
+ netif_wake_queue(ndev);
+ }
++#endif
+
+ /*
+ * Try sending a packet.
+ * If this interface isn't connected to a ISDN-Channel, find a free channel,
+ * and start dialing.
+ */
++#ifdef CONFIG_ISDN_WITH_ABC
++static int dwabc_isdn_net_start_xmit(struct sk_buff *,struct net_device *);
++
++static int isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
++{
++ if(skb == NULL || ndev == NULL)
++ return(dwabc_isdn_net_start_xmit(skb,ndev));
++#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK
++ if(!(((isdn_net_local *)ndev->priv)->dw_abc_flags &
++ ISDN_DW_ABC_FLAG_NO_UDP_CHECK)) {
++
++ if(dw_abc_udp_test(skb,ndev)) {
++ dev_kfree_skb(skb);
++ return(0);
++ }
++ }
++#endif
++ return(dwabc_isdn_net_start_xmit(skb,ndev));
++}
++
++
++#ifdef CONFIG_ISDN_WITH_ABC
++int isdn_auto_dial_helper( isdn_net_local *lp,
++ struct sk_buff *skb,
++ int dm_manual_allowed)
++/**********************************************************************
++ return's:
++ -1 dial not allowed or impossible
++ 0 interface is connected
++ 1 dial is started
++***********************************************************************/
++{
++ int retw = -1;
++ int chi;
++ ulong flags;
++ char *errmsg = NULL;
++
++#ifdef ISDN_DEBUG_NET_DUMP
++ {
++ char *buf = skb->data;
++ isdn_dumppkt("S:", buf, skb->len, 40);
++ }
++#endif
++ if (lp->flags & ISDN_NET_CONNECTED)
++ return(0);
++
++ save_flags(flags);
++ cli();
++
++ do {
++
++ /* Log packet, which triggered dialing */
++ if (dev->net_verbose)
++ isdn_net_log_skb(skb, lp);
++ /* only do autodial if allowed by config */
++ if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) {
++ errmsg = "dial rejected: interface not in dialmode `auto'";
++
++ if(dm_manual_allowed &&
++ !(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_MANUAL)) {
++
++ errmsg =
++ "dial rejected: interface not in dialmode `auto or manual'";
++ }
++ break;
++ }
++
++ if (!lp->phone[1]) {
++
++ errmsg = "No phone number";
++ break;
++ }
++
++ if(lp->dialwait_timer <= 0) {
++
++ if( lp->dialstarted > 0 &&
++ lp->dialtimeout > 0 &&
++ jiffies < (lp->dialstarted + lp->dialtimeout + lp->dialwait)) {
++
++ lp->dialwait_timer =
++ lp->dialstarted + lp->dialtimeout + lp->dialwait;
++ }
++ }
++
++ if(lp->dialwait_timer > 0) {
++
++ if(jiffies < lp->dialwait_timer) {
++
++ errmsg = "dial rejected: retry-time not reached";
++ break;
++
++ } else lp->dialwait_timer = 0;
++ }
++#ifdef CONFIG_ISDN_WITH_ABC
++ if(isdn_dwabc_is_interface_disabled(lp))
++ break;
++#endif
++ /* Grab a free ISDN-Channel */
++ if (((chi =
++ isdn_get_free_channel(
++ ISDN_USAGE_NET,
++ lp->l2_proto,
++ lp->l3_proto,
++ lp->pre_device,
++ lp->pre_channel,
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++ (*lp->dw_out_msn) ? lp->dw_out_msn :
++#endif
++ lp->msn)
++ ) < 0) &&
++ ((chi =
++ isdn_get_free_channel(
++ ISDN_USAGE_NET,
++ lp->l2_proto,
++ lp->l3_proto,
++ lp->pre_device,
++ lp->pre_channel^1,
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++ (*lp->dw_out_msn) ? lp->dw_out_msn :
++#endif
++ lp->msn)
++ ) < 0)) {
++
++ errmsg = "No channel";
++ break;
++ }
++
++ lp->dialstate = 1;
++ /* Connect interface with channel */
++ isdn_net_bind_channel(lp, chi);
++#ifdef CONFIG_ISDN_PPP
++ if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
++ /* no 'first_skb' handling for syncPPP */
++ if (isdn_ppp_bind(lp) < 0) {
++ isdn_net_unbind_channel(lp);
++ break;
++ }
++
++ isdn_net_dial(); /* Initiate dialing */
++ netif_stop_queue(&lp->netdev->dev);
++ retw = 1;
++ break;
++ /* let upper layer requeue skb packet */
++ }
++#endif
++ /* Initiate dialing */
++ isdn_net_dial();
++ isdn_net_device_stop_queue(lp);
++ retw = 1;
++
++ } while(0);
++
++ if(retw < 0 && errmsg != NULL)
++ isdn_net_unreachable(&lp->netdev->dev, skb, errmsg);
++
++ restore_flags(flags);
++ return(retw);
++}
++#endif
++
++
++
++static int
++dwabc_isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
++#else
+ static int
+ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
++#endif
+ {
+ isdn_net_local *lp = (isdn_net_local *) ndev->priv;
+ #ifdef CONFIG_ISDN_X25
+ struct concap_proto * cprot = lp -> netdev -> cprot;
+ #endif
++#ifdef COMPAT_NO_SOFTNET
++ /* some comment as with the softnet TX timeout
++ when this happens, it's a bug in the HL card driver
++ and should be fixed there, so we can supposedly get rid of
++ this here at all.
++ I added a debugging message to find out if it ever occurs --KG
++ */
++
++ if (ndev->tbusy) {
++ if (jiffies - ndev->trans_start < ISDN_NET_TX_TIMEOUT)
++ return 1;
++ if (!lp->dialstate){
++ lp->stats.tx_errors++;
++ printk(KERN_WARNING "isdn_tx_timeout dev %s dialstate %d\n",
++ ndev->name, lp->dialstate);
++ }
++ ndev->trans_start = jiffies;
++ netif_wake_queue(ndev);
++ }
++#endif
+ #ifdef CONFIG_ISDN_X25
+ /* At this point hard_start_xmit() passes control to the encapsulation
+ protocol (if present).
+@@ -1220,6 +1852,40 @@
+ } else
+ #endif
+ /* auto-dialing xmit function */
++#ifdef CONFIG_ISDN_WITH_ABC
++ {
++ int r;
++
++ isdn_net_adjust_hdr(skb, ndev);
++
++ if(!(r = isdn_auto_dial_helper(lp,skb,0))) {
++
++ /*
++ ** Device is connected to an ISDN channel
++ */
++ ndev->trans_start = jiffies;
++
++ if (!lp->dialstate) {
++
++ /*
++ ** ISDN connection is established, try sending
++ */
++ r = isdn_net_xmit(ndev, skb);
++
++ } else r = 1;
++
++ if(r)
++ netif_stop_queue(ndev);
++
++ } else if(r < 0) {
++
++ dev_kfree_skb(skb);
++ r = 0;
++ }
++
++ return(r);
++ }
++#else
+ {
+ #ifdef ISDN_DEBUG_NET_DUMP
+ u_char *buf;
+@@ -1256,6 +1922,14 @@
+ } else
+ lp->dialwait_timer = 0;
+ }
++#ifdef CONFIG_ISDN_WITH_ABC
++ if(isdn_dwabc_is_interface_disabled(lp)) {
++
++ dev_kfree_skb(skb);
++ restore_flags(flags);
++ return(0);
++ }
++#endif
+ /* Grab a free ISDN-Channel */
+ if (((chi =
+ isdn_get_free_channel(
+@@ -1264,6 +1938,9 @@
+ lp->l3_proto,
+ lp->pre_device,
+ lp->pre_channel,
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++ (*lp->dw_out_msn) ? lp->dw_out_msn :
++#endif
+ lp->msn)
+ ) < 0) &&
+ ((chi =
+@@ -1273,6 +1950,9 @@
+ lp->l3_proto,
+ lp->pre_device,
+ lp->pre_channel^1,
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++ (*lp->dw_out_msn) ? lp->dw_out_msn :
++#endif
+ lp->msn)
+ ) < 0)) {
+ restore_flags(flags);
+@@ -1296,16 +1976,6 @@
+ restore_flags(flags);
+ return 0; /* STN (skb to nirvana) ;) */
+ }
+-#ifdef CONFIG_IPPP_FILTER
+- if (isdn_ppp_autodial_filter(skb, lp)) {
+- isdn_ppp_free(lp);
+- isdn_net_unbind_channel(lp);
+- restore_flags(flags);
+- isdn_net_unreachable(ndev, skb, "dial rejected: packet filtered");
+- dev_kfree_skb(skb);
+- return 0;
+- }
+-#endif
+ restore_flags(flags);
+ isdn_net_dial(); /* Initiate dialing */
+ netif_stop_queue(ndev);
+@@ -1337,6 +2007,7 @@
+ }
+ }
+ return 1;
++#endif
+ }
+
+ /*
+@@ -1356,6 +2027,9 @@
+ if( cprot && cprot -> pops ) cprot -> pops -> close( cprot );
+ #endif
+ netif_stop_queue(dev);
++#ifdef COMPAT_NO_SOFTNET
++ dev->start = 0;
++#endif
+ if ((p = (((isdn_net_local *) dev->priv)->slave))) {
+ /* If this interface has slaves, stop them also */
+ while (p) {
+@@ -1776,6 +2450,10 @@
+ }
+
+ switch (type) {
++ case CISCO_TYPE_INET:
++ skb->protocol = htons(ETH_P_IP);
++ netif_rx(skb);
++ break;
+ case CISCO_TYPE_SLARP:
+ isdn_net_ciscohdlck_slarp_in(lp, skb);
+ goto out_free;
+@@ -1785,11 +2463,11 @@
+ "\"no cdp enable\" on cisco.\n", lp->name);
+ goto out_free;
+ default:
+- /* no special cisco protocol */
+- skb->protocol = htons(type);
+- netif_rx(skb);
+- return;
++ printk(KERN_WARNING "%s: Unknown Cisco type 0x%04x\n",
++ lp->name, type);
++ goto out_free;
+ }
++ return;
+
+ out_free:
+ kfree_skb(skb);
+@@ -1803,9 +2481,19 @@
+ {
+ isdn_net_local *lp = (isdn_net_local *) ndev->priv;
+ isdn_net_local *olp = lp; /* original 'lp' */
++#ifdef CONFIG_ISDN_PPP
++ int proto = PPP_PROTOCOL(skb->data);
++#endif
+ #ifdef CONFIG_ISDN_X25
+ struct concap_proto *cprot = lp -> netdev -> cprot;
+ #endif
++#ifdef CONFIG_ISDN_WITH_ABC
++ struct net_device *ondev = ndev;
++#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++ ulong lp_huptimer = 0;
++ ulong olp_huptimer = 0;
++#endif
++#endif
+ lp->transcount += skb->len;
+
+ lp->stats.rx_packets++;
+@@ -1819,6 +2507,10 @@
+ lp->stats.rx_packets++;
+ lp->stats.rx_bytes += skb->len;
+ }
++#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++ lp_huptimer = lp->huptimer;
++ olp_huptimer = olp->huptimer;
++#endif
+ skb->dev = ndev;
+ skb->pkt_type = PACKET_HOST;
+ skb->mac.raw = skb->data;
+@@ -1840,9 +2532,40 @@
+ /* Fall through */
+ case ISDN_NET_ENCAP_RAWIP:
+ /* RAW-IP without MAC-Header */
++#ifdef CONFIG_ISDN_WITH_ABC
++ if(olp->p_encap == ISDN_NET_ENCAP_RAWIP) {
++
++ ushort l = skb->len;
++ short r = 0;
++
++ olp->dw_abc_bsd_bsd_rcv += l;
++
++ if((skb = dwabc_bsd_rx_pkt(olp,skb,ondev)) == NULL) {
++
++ olp->dw_abc_bsd_rcv += l;
++ return;
++ }
++
++ olp->dw_abc_bsd_rcv += skb->len;
++
++ if( l != skb->len &&
++ (r=isdn_dc2minor(olp->isdn_device,olp->isdn_channel))>=0) {
++
++ dev->ibytes[r] += skb->len - l;
++ olp->stats.rx_bytes += skb->len - l;
++
++ if(olp != lp)
++ lp->stats.rx_bytes += skb->len - l;
++ }
++ }
++#endif
+ olp->huptimer = 0;
+ lp->huptimer = 0;
+ skb->protocol = htons(ETH_P_IP);
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++ if(isdn_dwabc_conerr_ippktok(skb))
++ lp->dw_abc_bchan_errcnt = 0;
++#endif
+ break;
+ case ISDN_NET_ENCAP_CISCOHDLCK:
+ isdn_net_ciscohdlck_receive(lp, skb);
+@@ -1862,8 +2585,22 @@
+ break;
+ #ifdef CONFIG_ISDN_PPP
+ case ISDN_NET_ENCAP_SYNCPPP:
+- /* huptimer is done in isdn_ppp_push_higher */
++ /*
++ * If encapsulation is syncppp, don't reset
++ * huptimer on LCP packets.
++ */
++ if (proto != PPP_LCP) {
++ olp->huptimer = 0;
++ lp->huptimer = 0;
++ }
+ isdn_ppp_receive(lp->netdev, olp, skb);
++#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++ if(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER) {
++
++ lp->huptimer = lp_huptimer + 1;
++ olp->huptimer = olp_huptimer+ 1;
++ }
++#endif
+ return;
+ #endif
+
+@@ -1873,6 +2610,15 @@
+ if(cprot) if(cprot -> pops)
+ if( cprot -> pops -> data_ind){
+ cprot -> pops -> data_ind(cprot,skb);
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++ lp->dw_abc_bchan_errcnt = 0;
++#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++ if(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER) {
++ lp->huptimer = lp_huptimer;
++ olp->huptimer = olp_huptimer;
++ }
++#endif
++#endif
+ return;
+ };
+ #endif /* CONFIG_ISDN_X25 */
+@@ -1882,6 +2628,15 @@
+ return;
+ }
+
++#ifdef CONFIG_ISDN_WITH_ABC
++#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++ if(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER) {
++
++ lp->huptimer = lp_huptimer;
++ olp->huptimer = olp_huptimer;
++ }
++#endif
++#endif
+ netif_rx(skb);
+ return;
+ }
+@@ -2160,8 +2915,10 @@
+ isdn_net_phone *n;
+ ulong flags;
+ char nr[32];
+- char *my_eaz;
+-
++#ifdef CONFIG_ISDN_WITH_ABC
++ if(dev->net_verbose > 2)
++ printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=0x%04X\n", di, ch, idx,dev->usage[idx]);
++#endif
+ /* Search name in netdev-chain */
+ save_flags(flags);
+ cli();
+@@ -2180,17 +2937,15 @@
+ eaz = setup->eazmsn;
+ if (dev->net_verbose > 1)
+ printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", nr, si1, si2, eaz);
+- /* Accept DATA and VOICE calls at this stage
+- local eaz is checked later for allowed call types */
+- if ((si1 != 7) && (si1 != 1)) {
+- restore_flags(flags);
+- if (dev->net_verbose > 1)
+- printk(KERN_INFO "isdn_net: Service-Indicator not 1 or 7, ignored\n");
+- return 0;
+- }
+-
+-n = (isdn_net_phone *) 0;
+-p = dev->netdev;
++ /* Accept only calls with Si1 = 7 (Data-Transmission) */
++ if (si1 != 7) {
++ restore_flags(flags);
++ if (dev->net_verbose > 1)
++ printk(KERN_INFO "isdn_net: Service-Indicator not 7, ignored\n");
++ return 0;
++ }
++ n = (isdn_net_phone *) 0;
++ p = dev->netdev;
+ ematch = wret = swapped = 0;
+ #ifdef ISDN_DEBUG_NET_ICALL
+ printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx,
+@@ -2210,25 +2965,8 @@
+ break;
+ }
+ swapped = 0;
+- /* check acceptable call types for DOV */
+- my_eaz = isdn_map_eaz2msn(lp->msn, di);
+- if (si1 == 1) { /* it's a DOV call, check if we allow it */
+- if (*my_eaz == 'v' || *my_eaz == 'V' ||
+- *my_eaz == 'b' || *my_eaz == 'B')
+- my_eaz++; /* skip to allow a match */
+- else
+- my_eaz = 0; /* force non match */
+- } else { /* it's a DATA call, check if we allow it */
+- if (*my_eaz == 'b' || *my_eaz == 'B')
+- my_eaz++; /* skip to allow a match */
+- }
+- if (my_eaz)
+- matchret = isdn_msncmp(eaz, my_eaz);
+- else
+- matchret = 1;
+- if (!matchret)
+- ematch = 1;
+-
++ if (!(matchret = isdn_msncmp(eaz, isdn_map_eaz2msn(lp->msn, di))))
++ ematch = 1;
+ /* Remember if more numbers eventually can match */
+ if (matchret > wret)
+ wret = matchret;
+@@ -2236,17 +2974,122 @@
+ printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
+ lp->name, lp->msn, lp->flags, lp->dialstate);
+ #endif
++#ifdef CONFIG_ISDN_WITH_ABC_CALLB
++ if ((!matchret) && /* EAZ is matching */
++ (((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */
++ (USG_NONE(dev->usage[idx]))) || /* and ch. unused or */
++ (lp->dialstate == 4) || (lp->dialstate == 12) || /* if dialing */
++ ((lp->flags & ISDN_NET_CBOUT) != 0 && /* init a callback */
++ lp->outgoing != 0 )))
++
++ /*
++ ** we dont stop call's anymore (both sides call's syncron)
++ ** it will be problem in any case.
++ ** both sides will make the same.
++ ** i try later to make a switch (check the phon-numbers)
++ ** to detect with side must be stop the call.
++ */
++#else
+ if ((!matchret) && /* EAZ is matching */
+ (((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */
+ (USG_NONE(dev->usage[idx]))) || /* and ch. unused or */
+ ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing */
+ (!(lp->flags & ISDN_NET_CALLBACK))) /* but no callback */
+ )))
++#endif
+ {
+ #ifdef ISDN_DEBUG_NET_ICALL
+ printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n",
+ lp->pre_device, lp->pre_channel);
+ #endif
++#ifdef CONFIG_ISDN_WITH_ABC
++#ifdef CONFIG_ISDN_WITH_ABC_CALLB
++ {
++ int use_this_call = 0;
++
++ if(!(lp->flags & ISDN_NET_CBOUT) && ((lp->dialstate == 4) || (lp->dialstate == 12))) {
++
++ /*
++ ** searching for a diff. in the calling-number and the EAZ
++ ** the remote will make the same
++ */
++
++ char *pnr = nr;
++ char *pea = eaz;
++
++ for(;*pnr;pnr++);
++ for(;*pea;pea++);
++ for(pnr--,pea--;pnr >= nr && pea >= eaz && *pea != *pnr;pnr--,pea--);
++
++ if(pnr < nr || pea < eaz || *pea > *pnr) {
++
++ p = (isdn_net_dev *) p->next;
++ continue;
++ }
++
++ use_this_call = 1;
++ }
++
++ if( use_this_call ||
++ ((lp->flags & ISDN_NET_CBOUT) && (lp->flags & ISDN_NET_CONNECTED))) {
++
++ /*
++ ** the incoming call was to quick.
++ ** the callback-delay-time ist not reached.
++ ** in that case we can stop the call
++ */
++
++ if(lp->isdn_device > -1 && lp->isdn_channel > -1) {
++
++ int minor = isdn_dc2minor(lp->isdn_device,lp->isdn_channel);
++
++ if(lp->isdn_device != di || lp->isdn_channel != ch) {
++
++ isdn_ctrl cmd;
++
++ memset((void *)&cmd,0,sizeof(cmd));
++ cmd.driver = lp->isdn_device;
++ cmd.command = ISDN_CMD_HANGUP;
++ cmd.arg = lp->isdn_channel;
++ (void) dev->drv[cmd.driver]->interface->command(&cmd);
++ isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
++
++ if(dev->net_verbose > 1) {
++
++ printk(KERN_INFO
++ "%s: found outgoing call hangup old call on di %d ch %d\n",
++ lp->name,lp->isdn_device,lp->isdn_channel);
++ }
++
++ } else if (dev->net_verbose > 1) {
++
++ printk(KERN_INFO "%s: found outgoing call on same di %d ch %d\n",
++ lp->name,lp->isdn_device,lp->isdn_channel);
++ }
++
++ if(minor >= 0) {
++
++ dev->rx_netdev[minor] = NULL;
++ dev->st_netdev[minor] = NULL;
++ }
++
++ isdn_free_channel(lp->isdn_device,
++ lp->isdn_channel, ISDN_USAGE_NET);
++
++ } else if (dev->net_verbose > 1) {
++
++ printk(KERN_INFO "%s: found outgoing call reset callstate \n",lp->name);
++ }
++
++ lp->flags &= ~ISDN_NET_CONNECTED;
++ lp->isdn_device = -1;
++ lp->isdn_channel = -1;
++ lp->dtimer = 0;
++ lp->dialstate = 0;
++ }
++ }
++#endif
++#endif
+ if (dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) {
+ if ((lp->pre_channel != ch) ||
+ (lp->pre_device != di)) {
+@@ -2375,6 +3218,12 @@
+ continue;
+ }
+ }
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++ if(isdn_dwabc_is_interface_disabled(lp)) {
++ restore_flags(flags);
++ return 3;
++ }
++#endif
+ if (lp->flags & ISDN_NET_CALLBACK) {
+ int chi;
+ /*
+@@ -2427,6 +3276,47 @@
+ restore_flags(flags);
+ return 0;
+ } else {
++#ifdef CONFIG_ISDN_WITH_ABC_CALLB
++ {
++ /*
++ ** this is a sanity-check.
++ ** check for double use (device and channel)
++ ** will be very near to a kernel-crash in that case
++ */
++ isdn_net_dev *sp = dev->netdev;
++ int s_shl;
++ isdn_net_local *ml;
++
++ for(s_shl=0; s_shl < 2048 && sp != NULL; sp = (isdn_net_dev *)sp->next, s_shl++) {
++
++ if(sp == p || (ml = sp->local) == NULL)
++ continue;
++
++ if(ml->isdn_device != di || ml->isdn_channel != ch)
++ continue;
++
++ if(ml->dialstate != 4 && ml->dialstate != 12) {
++
++ /*
++ ** wrong situation
++ */
++ break;
++ }
++
++ isdn_net_unbind_channel(ml);
++ }
++
++ if(sp != NULL) {
++
++ printk(KERN_DEBUG
++"%s: call from %s -> %s (drv %d chan %d duplicated with %s) \n",
++ lp->name, nr, eaz,di,ch,
++ sp->local->name );
++
++ restore_flags(flags);
++ return 3;
++ }}
++#endif
+ printk(KERN_DEBUG "%s: call from %s -> %s accepted\n", lp->name, nr,
+ eaz);
+ /* if this interface is dialing, it does it probably on a different
+@@ -2516,7 +3406,11 @@
+ lp->l3_proto,
+ lp->pre_device,
+ lp->pre_channel,
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++ (*lp->dw_out_msn) ? lp->dw_out_msn : lp->msn)
++#else
+ lp->msn)
++#endif
+ ) < 0) {
+ printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name);
+ restore_flags(flags);
+@@ -2599,7 +3493,11 @@
+ strcpy(netdev->local->name, " ");
+ else
+ strcpy(netdev->local->name, name);
++#ifdef COMPAT_NO_SOFTNET
++ netdev->dev.name = netdev->local->name;
++#else
+ strcpy(netdev->dev.name, netdev->local->name);
++#endif
+ netdev->dev.priv = netdev->local;
+ netdev->dev.init = isdn_net_init;
+ netdev->local->p_encap = ISDN_NET_ENCAP_RAWIP;
+@@ -2617,11 +3515,13 @@
+ ((isdn_net_local *) q->priv)->slave = &(netdev->dev);
+ } else {
+ /* Device shall be a master */
++#ifndef COMPAT_NO_SOFTNET
+ /*
+ * Watchdog timer (currently) for master only.
+ */
+ netdev->dev.tx_timeout = isdn_net_tx_timeout;
+ netdev->dev.watchdog_timeo = ISDN_NET_TX_TIMEOUT;
++#endif
+ if (register_netdev(&netdev->dev) != 0) {
+ printk(KERN_WARNING "isdn_net: Could not register net-device\n");
+ kfree(netdev->local);
+@@ -2658,6 +3558,9 @@
+ netdev->local->hupflags = ISDN_INHUP; /* Do hangup even on incoming calls */
+ netdev->local->onhtime = 10; /* Default hangup-time for saving costs
+ of those who forget configuring this */
++#ifdef CONFIG_ISDN_WITH_ABC
++ netdev->local->dw_abc_old_onhtime = netdev->local->onhtime;
++#endif
+ netdev->local->dialmax = 1;
+ netdev->local->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL; /* Hangup before Callback, manual dial */
+ netdev->local->cbdelay = 25; /* Wait 5 secs before Callback */
+@@ -2831,7 +3734,6 @@
+
+ /* If binding is exclusive, try to grab the channel */
+ save_flags(flags);
+- cli();
+ if ((i = isdn_get_free_channel(ISDN_USAGE_NET,
+ lp->l2_proto, lp->l3_proto, drvidx,
+ chidx, lp->msn)) < 0) {
+@@ -2859,6 +3761,9 @@
+ lp->pre_device = drvidx;
+ lp->pre_channel = chidx;
+ lp->onhtime = cfg->onhtime;
++#ifdef CONFIG_ISDN_WITH_ABC
++ lp->dw_abc_old_onhtime = lp->onhtime;
++#endif
+ lp->charge = cfg->charge;
+ lp->l2_proto = cfg->l2_proto;
+ lp->l3_proto = cfg->l3_proto;
+@@ -2932,6 +3837,9 @@
+ }
+ }
+ lp->p_encap = cfg->p_encap;
++#ifdef CONFIG_ISDN_WITH_ABC
++ isdn_dw_abc_reset_interface(lp,0);
++#endif
+ return 0;
+ }
+ return -ENODEV;
+@@ -3007,6 +3915,9 @@
+ strcpy(n->num, phone->phone);
+ n->next = p->local->phone[phone->outgoing & 1];
+ p->local->phone[phone->outgoing & 1] = n;
++#ifdef CONFIG_ISDN_WITH_ABC
++ isdn_dwabc_test_phone(p->local);
++#endif
+ return 0;
+ }
+ return -ENODEV;
+@@ -3100,6 +4011,9 @@
+ else
+ p->local->phone[inout] = n->next;
+ kfree(n);
++#ifdef CONFIG_ISDN_WITH_ABC
++ isdn_dwabc_test_phone(p->local);
++#endif
+ restore_flags(flags);
+ return 0;
+ }
+@@ -3135,6 +4049,9 @@
+ p->local->phone[i] = NULL;
+ }
+ p->local->dial = NULL;
++#ifdef CONFIG_ISDN_WITH_ABC
++ isdn_dwabc_test_phone(p->local);
++#endif
+ restore_flags(flags);
+ return 0;
+ }
+@@ -3218,6 +4135,10 @@
+ /* If no more net-devices remain, disable auto-hangup timer */
+ if (dev->netdev == NULL)
+ isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
++#ifdef CONFIG_ISDN_WITH_ABC
++ isdn_dw_clear_if(~0l,p->local);
++ dwabc_bsd_free(p->local);
++#endif
+ restore_flags(flags);
+ kfree(p->local);
+ kfree(p);
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_net.h linux-2.4.29/drivers/isdn/isdn_net.h
+--- linux-2.4.29.old/drivers/isdn/isdn_net.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_net.h 2005-03-22 15:06:44.463333328 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_net.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_net.h,v 1.23 2001/11/07 22:35:48 kai Exp $
+ *
+ * header for Linux ISDN subsystem, network related functions (linklevel).
+ *
+@@ -26,6 +26,7 @@
+ #define CISCO_ADDR_BROADCAST 0x8f
+ #define CISCO_CTRL 0x00
+ #define CISCO_TYPE_CDP 0x2000
++#define CISCO_TYPE_INET 0x0800
+ #define CISCO_TYPE_SLARP 0x8035
+ #define CISCO_SLARP_REQUEST 0
+ #define CISCO_SLARP_REPLY 1
+@@ -106,8 +107,6 @@
+ spin_lock_irqsave(&nd->queue_lock, flags);
+
+ lp = nd->queue;
+-// printk(KERN_DEBUG __FUNCTION__": lp:%s(%p) nlp:%s(%p) last(%p)\n",
+-// lp->name, lp, nlp->name, nlp, lp->last);
+ nlp->last = lp->last;
+ lp->last->next = nlp;
+ lp->last = nlp;
+@@ -127,20 +126,12 @@
+ if (lp->master)
+ master_lp = (isdn_net_local *) lp->master->priv;
+
+-// printk(KERN_DEBUG __FUNCTION__": lp:%s(%p) mlp:%s(%p) last(%p) next(%p) mndq(%p)\n",
+-// lp->name, lp, master_lp->name, master_lp, lp->last, lp->next, master_lp->netdev->queue);
+ spin_lock_irqsave(&master_lp->netdev->queue_lock, flags);
+ lp->last->next = lp->next;
+ lp->next->last = lp->last;
+- if (master_lp->netdev->queue == lp) {
++ if (master_lp->netdev->queue == lp)
+ master_lp->netdev->queue = lp->next;
+- if (lp->next == lp) { /* last in queue */
+- master_lp->netdev->queue = master_lp->netdev->local;
+- }
+- }
+ lp->next = lp->last = lp; /* (re)set own pointers */
+-// printk(KERN_DEBUG __FUNCTION__": mndq(%p)\n",
+-// master_lp->netdev->queue);
+ spin_unlock_irqrestore(&master_lp->netdev->queue_lock, flags);
+ }
+
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_ppp.c linux-2.4.29/drivers/isdn/isdn_ppp.c
+--- linux-2.4.29.old/drivers/isdn/isdn_ppp.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_ppp.c 2005-03-22 15:06:44.481330592 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_ppp.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_ppp.c,v 1.94 2001/11/07 22:35:48 kai Exp $
+ *
+ * Linux ISDN subsystem, functions for synchronous PPP (linklevel).
+ *
+@@ -13,9 +13,6 @@
+ #include <linux/isdn.h>
+ #include <linux/poll.h>
+ #include <linux/ppp-comp.h>
+-#ifdef CONFIG_IPPP_FILTER
+-#include <linux/filter.h>
+-#endif
+
+ #include "isdn_common.h"
+ #include "isdn_ppp.h"
+@@ -72,11 +69,19 @@
+ static int isdn_ppp_bundle(struct ippp_struct *, int unit);
+ #endif /* CONFIG_ISDN_MPP */
+
+-char *isdn_ppp_revision = "$Revision: 1.1.4.1 $";
++char *isdn_ppp_revision = "$Revision: 1.94 $";
+
+ static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
+
++#ifndef CONFIG_ISDN_WITH_ABC
+ static struct isdn_ppp_compressor *ipc_head = NULL;
++#else
++ /*
++ ** make compressor's common usable
++ */
++struct isdn_ppp_compressor *isdn_ippp_comp_head = NULL;
++#define ipc_head isdn_ippp_comp_head
++#endif
+
+ /*
+ * frame log (debug)
+@@ -110,11 +115,8 @@
+ unsigned long flags;
+ struct ippp_struct *is;
+
+- if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+- printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
+- __FUNCTION__, lp->ppp_slot);
++ if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS)
+ return 0;
+- }
+
+ save_flags(flags);
+ cli();
+@@ -130,12 +132,7 @@
+ lp->netdev->pb->ref_ct--;
+ spin_unlock(&lp->netdev->pb->lock);
+ #endif /* CONFIG_ISDN_MPP */
+- if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+- printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n",
+- __FUNCTION__, lp->ppp_slot);
+- restore_flags(flags);
+- return 0;
+- }
++
+ is = ippp_table[lp->ppp_slot];
+ if ((is->state & IPPP_CONNECT))
+ isdn_ppp_closewait(lp->ppp_slot); /* force wakeup on ippp device */
+@@ -231,13 +228,12 @@
+ void
+ isdn_ppp_wakeup_daemon(isdn_net_local * lp)
+ {
+- if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
+- printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
+- __FUNCTION__, lp->ppp_slot);
++ if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS)
+ return;
+- }
++
+ ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
+- wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
++
++ wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
+ }
+
+ /*
+@@ -250,14 +246,13 @@
+ {
+ struct ippp_struct *is;
+
+- if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
+- printk(KERN_ERR "%s: slot(%d) out of range\n",
+- __FUNCTION__, slot);
++ if (slot < 0 || slot >= ISDN_MAX_CHANNELS)
+ return 0;
+- }
+ is = ippp_table[slot];
++
+ if (is->state)
+ wake_up_interruptible(&is->wq);
++
+ is->state = IPPP_CLOSEWAIT;
+ return 1;
+ }
+@@ -295,9 +290,11 @@
+ return -EBUSY;
+ }
+ is = file->private_data = ippp_table[slot];
+-
+- printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n",
+- slot, min, is->state);
++
++#if 0
++ if (is->debug & 0x1)
++#endif
++ printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n", slot, min, is->state);
+
+ /* compression stuff */
+ is->link_compressor = is->compressor = NULL;
+@@ -327,10 +324,7 @@
+ */
+ is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */
+ #endif
+-#ifdef CONFIG_IPPP_FILTER
+- is->pass_filter.filter = NULL;
+- is->active_filter.filter = NULL;
+-#endif
++
+ is->state = IPPP_OPEN;
+
+ return 0;
+@@ -349,20 +343,12 @@
+ return;
+ is = file->private_data;
+
+- if (!is) {
+- printk(KERN_ERR "%s: no file->private_data\n", __FUNCTION__);
+- return;
+- }
+ if (is->debug & 0x1)
+ printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", min, (long) is->lp);
+
+ if (is->lp) { /* a lp address says: this link is still up */
+ isdn_net_dev *p = is->lp->netdev;
+
+- if (!p) {
+- printk(KERN_ERR "%s: no lp->netdev\n", __FUNCTION__);
+- return;
+- }
+ is->state &= ~IPPP_CONNECT; /* -> effect: no call of wakeup */
+ /*
+ * isdn_net_hangup() calls isdn_ppp_free()
+@@ -385,18 +371,8 @@
+ slhc_free(is->slcomp);
+ is->slcomp = NULL;
+ #endif
+-#ifdef CONFIG_IPPP_FILTER
+- if (is->pass_filter.filter) {
+- kfree(is->pass_filter.filter);
+- is->pass_filter.filter = NULL;
+- }
+- if (is->active_filter.filter) {
+- kfree(is->active_filter.filter);
+- is->active_filter.filter = NULL;
+- }
+-#endif
+
+-/* TODO: if this was the previous master: link the stuff to the new master */
++/* TODO: if this was the previous master: link the the stuff to the new master */
+ if(is->comp_stat)
+ is->compressor->free(is->comp_stat);
+ if(is->link_comp_stat)
+@@ -509,13 +485,15 @@
+ if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
+ if (lp) {
+ /* OK .. we are ready to send buffers */
+- is->pppcfg = val; /* isdn_ppp_xmit test for SC_ENABLE_IP !!! */
+ netif_wake_queue(&lp->netdev->dev);
+- break;
+ }
+ }
+ is->pppcfg = val;
+ break;
++#if 0
++ case PPPIOCGSTAT: /* read PPP statistic information */
++ break;
++#endif
+ case PPPIOCGIDLE: /* get idle time information */
+ if (lp) {
+ struct ppp_idle pidle;
+@@ -604,39 +582,6 @@
+ }
+ return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo));
+ }
+-#ifdef CONFIG_IPPP_FILTER
+- case PPPIOCSPASS:
+- case PPPIOCSACTIVE:
+- {
+- struct sock_fprog uprog, *filtp;
+- struct sock_filter *code = NULL;
+- int len, err;
+-
+- if (copy_from_user(&uprog, (void *) arg, sizeof(uprog)))
+- return -EFAULT;
+- if (uprog.len > 0 && uprog.len < 65536) {
+- len = uprog.len * sizeof(struct sock_filter);
+- code = kmalloc(len, GFP_KERNEL);
+- if (code == NULL)
+- return -ENOMEM;
+- if (copy_from_user(code, uprog.filter, len)) {
+- kfree(code);
+- return -EFAULT;
+- }
+- err = sk_chk_filter(code, uprog.len);
+- if (err) {
+- kfree(code);
+- return err;
+- }
+- }
+- filtp = (cmd == PPPIOCSPASS) ? &is->pass_filter : &is->active_filter;
+- if (filtp->filter)
+- kfree(filtp->filter);
+- filtp->filter = code;
+- filtp->len = uprog.len;
+- break;
+- }
+-#endif /* CONFIG_IPPP_FILTER */
+ default:
+ break;
+ }
+@@ -699,7 +644,7 @@
+ struct ippp_struct *is;
+
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
+- printk(KERN_WARNING "ippp: illegal slot(%d).\n", slot);
++ printk(KERN_WARNING "ippp: illegal slot.\n");
+ return 0;
+ }
+ is = ippp_table[slot];
+@@ -976,8 +921,7 @@
+
+ slot = lp->ppp_slot;
+ if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+- printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot(%d)\n",
+- lp->ppp_slot);
++ printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot %d\n", lp->ppp_slot);
+ kfree_skb(skb);
+ return;
+ }
+@@ -1026,23 +970,19 @@
+ {
+ struct net_device *dev = &net_dev->dev;
+ struct ippp_struct *is, *mis;
+- isdn_net_local *mlp = NULL;
+ int slot;
+
+ slot = lp->ppp_slot;
+ if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+- printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot(%d)\n",
+- lp->ppp_slot);
++ printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot %d\n", lp->ppp_slot);
+ goto drop_packet;
+ }
+ is = ippp_table[slot];
+
+ if (lp->master) { // FIXME?
+- mlp = (isdn_net_local *) lp->master->priv;
+- slot = mlp->ppp_slot;
++ slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
+ if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+- printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n",
+- lp->ppp_slot);
++ printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot %d\n", lp->ppp_slot);
+ goto drop_packet;
+ }
+ }
+@@ -1076,11 +1016,6 @@
+ case PPP_VJC_UNCOMP:
+ if (is->debug & 0x20)
+ printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
+- if (net_dev->local->ppp_slot < 0) {
+- printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
+- __FUNCTION__, net_dev->local->ppp_slot);
+- goto drop_packet;
+- }
+ if (slhc_remember(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
+ printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
+ goto drop_packet;
+@@ -1102,11 +1037,6 @@
+ }
+ skb_put(skb, skb_old->len + 128);
+ memcpy(skb->data, skb_old->data, skb_old->len);
+- if (net_dev->local->ppp_slot < 0) {
+- printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
+- __FUNCTION__, net_dev->local->ppp_slot);
+- goto drop_packet;
+- }
+ pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp,
+ skb->data, skb_old->len);
+ kfree_skb(skb_old);
+@@ -1133,36 +1063,12 @@
+ return;
+ }
+
+-#ifdef CONFIG_IPPP_FILTER
+- /* check if the packet passes the pass and active filters
+- * the filter instructions are constructed assuming
+- * a four-byte PPP header on each packet (which is still present) */
+- skb_push(skb, 4);
+- skb->data[0] = 0; /* indicate inbound */
+-
+- if (is->pass_filter.filter
+- && sk_run_filter(skb, is->pass_filter.filter,
+- is->pass_filter.len) == 0) {
+- if (is->debug & 0x2)
+- printk(KERN_DEBUG "IPPP: inbound frame filtered.\n");
+- kfree_skb(skb);
+- return;
+- }
+- if (!(is->active_filter.filter
+- && sk_run_filter(skb, is->active_filter.filter,
+- is->active_filter.len) == 0)) {
+- if (is->debug & 0x2)
+- printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
+- lp->huptimer = 0;
+- if (mlp)
+- mlp->huptimer = 0;
+- }
+- skb_pull(skb, 4);
+-#else /* CONFIG_IPPP_FILTER */
+- lp->huptimer = 0;
+- if (mlp)
+- mlp->huptimer = 0;
+-#endif /* CONFIG_IPPP_FILTER */
++ /* Reset hangup-timer */
++ lp->huptimer = 0;
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++ lp->dw_abc_bchan_errcnt = 0;
++#endif
++
+ skb->dev = dev;
+ skb->mac.raw = skb->data;
+ netif_rx(skb);
+@@ -1199,6 +1105,7 @@
+ return skb_push(skb,len);
+ }
+
++
+ /*
+ * send ppp frame .. we expect a PIDCOMPressable proto --
+ * (here: currently always PPP_IP,PPP_VJC_COMP,PPP_VJC_UNCOMP)
+@@ -1214,25 +1121,23 @@
+ isdn_net_dev *nd;
+ unsigned int proto = PPP_IP; /* 0x21 */
+ struct ippp_struct *ipt,*ipts;
+- int slot, retval = 0;
++ int slot;
+
+ mlp = (isdn_net_local *) (netdev->priv);
+ nd = mlp->netdev; /* get master lp */
+
+ slot = mlp->ppp_slot;
+ if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+- printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
+- mlp->ppp_slot);
++ printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot %d\n", mlp->ppp_slot);
+ kfree_skb(skb);
+- goto out;
++ return 0;
+ }
+ ipts = ippp_table[slot];
+
+ if (!(ipts->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */
+ if (ipts->debug & 0x1)
+ printk(KERN_INFO "%s: IP frame delayed.\n", netdev->name);
+- retval = 1;
+- goto out;
++ return 1;
+ }
+
+ switch (ntohs(skb->protocol)) {
+@@ -1246,25 +1151,24 @@
+ printk(KERN_ERR "isdn_ppp: skipped unsupported protocol: %#x.\n",
+ skb->protocol);
+ dev_kfree_skb(skb);
+- goto out;
++ return 0;
+ }
+
+ lp = isdn_net_get_locked_lp(nd);
+ if (!lp) {
+ printk(KERN_WARNING "%s: all channels busy - requeuing!\n", netdev->name);
+- retval = 1;
+- goto out;
++ return 1;
+ }
+ /* we have our lp locked from now on */
+
+ slot = lp->ppp_slot;
+ if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+- printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
+- lp->ppp_slot);
++ printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot %d\n", lp->ppp_slot);
+ kfree_skb(skb);
+- goto unlock;
++ return 0;
+ }
+ ipt = ippp_table[slot];
++ lp->huptimer = 0;
+
+ /*
+ * after this line .. requeueing in the device queue is no longer allowed!!!
+@@ -1275,34 +1179,6 @@
+ */
+ skb_pull(skb,IPPP_MAX_HEADER);
+
+-#ifdef CONFIG_IPPP_FILTER
+- /* check if we should pass this packet
+- * the filter instructions are constructed assuming
+- * a four-byte PPP header on each packet */
+- skb_push(skb, 4);
+- skb->data[0] = 1; /* indicate outbound */
+- *(u_int16_t *)(skb->data + 2) = htons(proto);
+-
+- if (ipt->pass_filter.filter
+- && sk_run_filter(skb, ipt->pass_filter.filter,
+- ipt->pass_filter.len) == 0) {
+- if (ipt->debug & 0x4)
+- printk(KERN_DEBUG "IPPP: outbound frame filtered.\n");
+- kfree_skb(skb);
+- goto unlock;
+- }
+- if (!(ipt->active_filter.filter
+- && sk_run_filter(skb, ipt->active_filter.filter,
+- ipt->active_filter.len) == 0)) {
+- if (ipt->debug & 0x4)
+- printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
+- lp->huptimer = 0;
+- }
+- skb_pull(skb, 4);
+-#else /* CONFIG_IPPP_FILTER */
+- lp->huptimer = 0;
+-#endif /* CONFIG_IPPP_FILTER */
+-
+ if (ipt->debug & 0x4)
+ printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);
+ if (ipts->debug & 0x40)
+@@ -1440,54 +1316,9 @@
+
+ unlock:
+ spin_unlock_bh(&lp->xmit_lock);
+- out:
+- return retval;
++ return 0;
+ }
+
+-#ifdef CONFIG_IPPP_FILTER
+-/*
+- * check if this packet may trigger auto-dial.
+- */
+-
+-int isdn_ppp_autodial_filter(struct sk_buff *skb, isdn_net_local *lp)
+-{
+- struct ippp_struct *is = ippp_table[lp->ppp_slot];
+- u_int16_t proto;
+- int drop = 0;
+-
+- switch (ntohs(skb->protocol)) {
+- case ETH_P_IP:
+- proto = PPP_IP;
+- break;
+- case ETH_P_IPX:
+- proto = PPP_IPX;
+- break;
+- default:
+- printk(KERN_ERR "isdn_ppp_autodial_filter: unsupported protocol 0x%x.\n",
+- skb->protocol);
+- return 1;
+- }
+-
+- /* the filter instructions are constructed assuming
+- * a four-byte PPP header on each packet. we have to
+- * temporarily remove part of the fake header stuck on
+- * earlier.
+- */
+- skb_pull(skb, IPPP_MAX_HEADER - 4);
+- skb->data[0] = 1; /* indicate outbound */
+- *(u_int16_t *)(skb->data + 2) = htons(proto);
+-
+- drop |= is->pass_filter.filter
+- && sk_run_filter(skb, is->pass_filter.filter,
+- is->pass_filter.len) == 0;
+- drop |= is->active_filter.filter
+- && sk_run_filter(skb, is->active_filter.filter,
+- is->active_filter.len) == 0;
+-
+- skb_push(skb, IPPP_MAX_HEADER - 4);
+- return drop;
+-}
+-#endif
+ #ifdef CONFIG_ISDN_MPP
+
+ /* this is _not_ rfc1990 header, but something we convert both short and long
+@@ -1537,15 +1368,8 @@
+
+ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
+ {
+- struct ippp_struct * is;
+-
+- if (lp->ppp_slot < 0) {
+- printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+- __FUNCTION__, lp->ppp_slot);
+- return(-EINVAL);
+- }
+-
+- is = ippp_table[lp->ppp_slot];
++ struct ippp_struct * is = ippp_table[lp->ppp_slot];
++
+ if (add_to) {
+ if( lp->netdev->pb )
+ lp->netdev->pb->ref_ct--;
+@@ -1591,8 +1415,7 @@
+ stats = &mp->stats;
+ slot = lp->ppp_slot;
+ if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+- printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
+- __FUNCTION__, lp->ppp_slot);
++ printk(KERN_ERR "isdn_ppp_mp_receive: lp->ppp_slot %d\n", lp->ppp_slot);
+ stats->frame_drops++;
+ dev_kfree_skb(skb);
+ spin_unlock_irqrestore(&mp->lock, flags);
+@@ -1628,8 +1451,7 @@
+ for (lpq = net_dev->queue;;) {
+ slot = lpq->ppp_slot;
+ if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+- printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
+- __FUNCTION__, lpq->ppp_slot);
++ printk(KERN_ERR "isdn_ppp_mp_receive: lpq->ppp_slot %d\n", lpq->ppp_slot);
+ } else {
+ u32 lls = ippp_table[slot]->last_link_seqno;
+ if (MP_LT(lls, minseq))
+@@ -1861,14 +1683,9 @@
+ struct sk_buff * skb;
+ unsigned int tot_len;
+
+- if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+- printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+- __FUNCTION__, lp->ppp_slot);
+- return;
+- }
+ if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) {
+ if( ippp_table[lp->ppp_slot]->debug & 0x40 )
+- printk(KERN_DEBUG "isdn_mppp: reassembly: frame %d, "
++ printk(KERN_DEBUG"isdn_mppp: reassembly: frame %d, "
+ "len %d\n", MP_SEQ(from), from->len );
+ skb = from;
+ skb_pull(skb, MP_HEADER_LEN);
+@@ -1987,10 +1804,8 @@
+ memset(&t, 0, sizeof(struct ppp_stats));
+ if (dev->flags & IFF_UP) {
+ t.p.ppp_ipackets = lp->stats.rx_packets;
+- t.p.ppp_ibytes = lp->stats.rx_bytes;
+ t.p.ppp_ierrors = lp->stats.rx_errors;
+ t.p.ppp_opackets = lp->stats.tx_packets;
+- t.p.ppp_obytes = lp->stats.tx_bytes;
+ t.p.ppp_oerrors = lp->stats.tx_errors;
+ #ifdef CONFIG_ISDN_PPP_VJ
+ if (slot >= 0 && ippp_table[slot]->slcomp) {
+@@ -2018,6 +1833,9 @@
+ int len;
+ isdn_net_local *lp = (isdn_net_local *) dev->priv;
+
++#if 0
++ printk(KERN_DEBUG "ippp, dev_ioctl: cmd %#08x , %d \n", cmd, lp->ppp_slot);
++#endif
+
+ if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
+ return -EINVAL;
+@@ -2431,7 +2249,7 @@
+ return;
+ }
+ rs->state = CCPResetSentReq;
+- /* We always expect an Ack if the decompressor doesn't
++ /* We always expect an Ack if the decompressor doesnt
+ know better */
+ rs->expra = 1;
+ rs->dlen = 0;
+@@ -2582,7 +2400,13 @@
+ }
+
+ if(type) { /* type=1 => Link compression */
++#if 0
++ compressor = is->link_compressor;
++ stat = is->link_comp_stat;
++ new_proto = PPP_LINK_COMP;
++#else
+ return skb_in;
++#endif
+ }
+ else {
+ if(!master) {
+@@ -2630,31 +2454,18 @@
+ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
+ struct sk_buff *skb,int proto)
+ {
+- struct ippp_struct *is;
++ struct ippp_struct *is = ippp_table[lp->ppp_slot];
+ struct ippp_struct *mis;
+ int len;
+ struct isdn_ppp_resetparams rsparm;
+ unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
+
+- printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n",
+- lp->ppp_slot);
+- if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+- printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+- __FUNCTION__, lp->ppp_slot);
+- return;
+- }
+- is = ippp_table[lp->ppp_slot];
++ printk(KERN_DEBUG "Received CCP frame from peer\n");
+ isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
+
+- if(lp->master) {
+- int slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
+- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+- printk(KERN_ERR "%s: slot(%d) out of range\n",
+- __FUNCTION__, slot);
+- return;
+- }
+- mis = ippp_table[slot];
+- } else
++ if(lp->master)
++ mis = ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot];
++ else
+ mis = is;
+
+ switch(skb->data[0]) {
+@@ -2806,18 +2617,13 @@
+
+ static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb)
+ {
+- struct ippp_struct *mis,*is;
+- int proto, slot = lp->ppp_slot;
++ struct ippp_struct *mis,*is = ippp_table[lp->ppp_slot];
++ int proto;
+ unsigned char *data;
+
+ if(!skb || skb->len < 3)
+ return;
+- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+- printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+- __FUNCTION__, slot);
+- return;
+- }
+- is = ippp_table[slot];
++
+ /* Daemon may send with or without address and control field comp */
+ data = skb->data;
+ if(!(is->pppcfg & SC_COMP_AC) && data[0] == 0xff && data[1] == 0x03) {
+@@ -2833,17 +2639,12 @@
+ printk(KERN_DEBUG "Received CCP frame from daemon:\n");
+ isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
+
+- if (lp->master) {
+- slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
+- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+- printk(KERN_ERR "%s: slot(%d) out of range\n",
+- __FUNCTION__, slot);
+- return;
+- }
+- mis = ippp_table[slot];
+- } else
+- mis = is;
+- if (mis != is)
++ if(lp->master)
++ mis = ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot];
++ else
++ mis = is;
++
++ if(mis != is)
+ printk(KERN_DEBUG "isdn_ppp: Ouch! Master CCP sends on slave slot!\n");
+
+ switch(data[2]) {
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_ppp.h linux-2.4.29/drivers/isdn/isdn_ppp.h
+--- linux-2.4.29.old/drivers/isdn/isdn_ppp.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_ppp.h 2005-03-22 15:06:44.497328160 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_ppp.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_ppp.h,v 1.18 2001/09/24 13:22:42 kai Exp $
+ *
+ * header for Linux ISDN subsystem, functions for synchronous PPP (linklevel).
+ *
+@@ -19,7 +19,6 @@
+ extern void isdn_ppp_cleanup(void);
+ extern int isdn_ppp_free(isdn_net_local *);
+ extern int isdn_ppp_bind(isdn_net_local *);
+-extern int isdn_ppp_autodial_filter(struct sk_buff *, isdn_net_local *);
+ extern int isdn_ppp_xmit(struct sk_buff *, struct net_device *);
+ extern void isdn_ppp_receive(isdn_net_dev *, isdn_net_local *, struct sk_buff *);
+ extern int isdn_ppp_dev_ioctl(struct net_device *, struct ifreq *, int);
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_tty.c linux-2.4.29/drivers/isdn/isdn_tty.c
+--- linux-2.4.29.old/drivers/isdn/isdn_tty.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_tty.c 2005-03-22 15:06:44.524324056 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_tty.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_tty.c,v 1.104 2002/02/09 21:19:11 keil Exp $
+ *
+ * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
+ *
+@@ -53,7 +53,7 @@
+ static int si2bit[8] =
+ {4, 1, 4, 4, 4, 4, 4, 4};
+
+-char *isdn_tty_revision = "$Revision: 1.1.4.1 $";
++char *isdn_tty_revision = "$Revision: 1.104 $";
+
+
+ /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
+@@ -321,7 +321,10 @@
+ info->send_outstanding++;
+ info->msr &= ~UART_MSR_CTS;
+ info->lsr &= ~UART_LSR_TEMT;
+- tty_wakeup(tty);
++ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
++ tty->ldisc.write_wakeup)
++ (tty->ldisc.write_wakeup) (tty);
++ wake_up_interruptible(&tty->write_wait);
+ return;
+ }
+ if (slen < 0) {
+@@ -1211,7 +1214,10 @@
+ /* If DLE decoding results in zero-transmit, but
+ * c originally was non-zero, do a wakeup.
+ */
+- tty_wakeup(tty);
++ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
++ tty->ldisc.write_wakeup)
++ (tty->ldisc.write_wakeup) (tty);
++ wake_up_interruptible(&tty->write_wait);
+ info->msr |= UART_MSR_CTS;
+ info->lsr |= UART_LSR_TEMT;
+ }
+@@ -1232,6 +1238,7 @@
+ }
+ }
+ } else
++#ifdef ISDN_TTY_FCLASS1
+ if (TTY_IS_FCLASS1(info)) {
+ int cc = isdn_tty_handleDLEdown(info, m, c);
+
+@@ -1252,6 +1259,7 @@
+ info->xmit_count += cc;
+ } else
+ #endif
++#endif
+ info->xmit_count += c;
+ } else {
+ info->msr |= UART_MSR_CTS;
+@@ -1329,7 +1337,10 @@
+ isdn_tty_cleanup_xmit(info);
+ info->xmit_count = 0;
+ restore_flags(flags);
+- tty_wakeup(tty);
++ wake_up_interruptible(&tty->write_wait);
++ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
++ tty->ldisc.write_wakeup)
++ (tty->ldisc.write_wakeup) (tty);
+ }
+
+ static void
+@@ -1858,7 +1869,8 @@
+ isdn_tty_shutdown(info);
+ if (tty->driver.flush_buffer)
+ tty->driver.flush_buffer(tty);
+- tty_ldisc_flush(tty);
++ if (tty->ldisc.flush_buffer)
++ tty->ldisc.flush_buffer(tty);
+ info->tty = 0;
+ info->ncarrier = 0;
+ tty->closing = 0;
+@@ -2306,6 +2318,22 @@
+ isdn_tty_at_cout("\r\n", info);
+ }
+ return 1;
++ case ISDN_STAT_ALERT:
++#ifdef ISDN_TTY_STAT_DEBUG
++ printk(KERN_DEBUG "tty_STAT_ALERT ttyI%d\n", info->line);
++#endif
++ /* Signal RINGING to tty-device if requested */
++ if (info->emu.mdmreg[REG_ALERT] & BIT_ALERT)
++ isdn_tty_modem_result(RESULT_RINGING, info);
++ return 1;
++ case ISDN_STAT_PROCEED:
++#ifdef ISDN_TTY_STAT_DEBUG
++ printk(KERN_DEBUG "tty_STAT_PROCEED ttyI%d\n", info->line);
++#endif
++ /* Signal PROCEEDING to tty-device if requested */
++ if (info->emu.mdmreg[REG_PROCEED] & BIT_PROCEED)
++ isdn_tty_modem_result(RESULT_PROCEEDING, info);
++ return 1;
+ case ISDN_STAT_DCONN:
+ #ifdef ISDN_TTY_STAT_DEBUG
+ printk(KERN_DEBUG "tty_STAT_DCONN ttyI%d\n", info->line);
+@@ -2618,7 +2646,7 @@
+ static char *msg[] =
+ {"OK", "CONNECT", "RING", "NO CARRIER", "ERROR",
+ "CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER",
+- "RINGING", "NO MSN/EAZ", "VCON", "RUNG"};
++ "RINGING", "NO MSN/EAZ", "VCON", "RUNG", "PROCEEDING"};
+ ulong flags;
+ char s[ISDN_MSNLEN+10];
+
+@@ -2781,7 +2809,8 @@
+ restore_flags(flags);
+ return;
+ }
+- tty_ldisc_flush(info->tty);
++ if (info->tty->ldisc.flush_buffer)
++ info->tty->ldisc.flush_buffer(info->tty);
+ if ((info->flags & ISDN_ASYNC_CHECK_CD) &&
+ (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
+ (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) {
+@@ -3296,9 +3325,11 @@
+ #ifdef CONFIG_ISDN_TTY_FAX
+ if (TTY_IS_FCLASS2(info))
+ sprintf(rs, "\r\n2");
++#ifdef ISDN_TTY_FCLASS1
+ else if (TTY_IS_FCLASS1(info))
+ sprintf(rs, "\r\n1");
+ #endif
++#endif
+ isdn_tty_at_cout(rs, info);
+ break;
+ case '=':
+@@ -3313,6 +3344,7 @@
+ m->mdmreg[REG_PSIZE] * 16;
+ break;
+ #ifdef CONFIG_ISDN_TTY_FAX
++#ifdef ISDN_TTY_FCLASS1
+ case '1':
+ p[0]++;
+ if (!(dev->global_features &
+@@ -3324,6 +3356,7 @@
+ info->xmit_size =
+ m->mdmreg[REG_PSIZE] * 16;
+ break;
++#endif
+ case '2':
+ p[0]++;
+ if (!(dev->global_features &
+@@ -3348,9 +3381,11 @@
+ p[0]++;
+ strcpy(rs, "\r\n0,");
+ #ifdef CONFIG_ISDN_TTY_FAX
++#ifdef ISDN_TTY_FCLASS1
+ if (dev->global_features &
+ ISDN_FEATURE_L3_FCLASS1)
+ strcat(rs, "1,");
++#endif
+ if (dev->global_features &
+ ISDN_FEATURE_L3_FCLASS2)
+ strcat(rs, "2,");
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_tty.h linux-2.4.29/drivers/isdn/isdn_tty.h
+--- linux-2.4.29.old/drivers/isdn/isdn_tty.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_tty.h 2005-03-22 15:06:44.545320864 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_tty.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_tty.h,v 1.25 2002/02/09 21:19:11 keil Exp $
+ *
+ * header for Linux ISDN subsystem, tty related functions (linklevel).
+ *
+@@ -78,6 +78,10 @@
+ #define BIT_CPNFCON 2
+ #define REG_CDN 23
+ #define BIT_CDN 4
++#define REG_ALERT 23
++#define BIT_ALERT 8
++#define REG_PROCEED 23
++#define BIT_PROCEED 16
+
+ /* defines for result codes */
+ #define RESULT_OK 0
+@@ -93,10 +97,13 @@
+ #define RESULT_NO_MSN_EAZ 10
+ #define RESULT_VCON 11
+ #define RESULT_RUNG 12
++#define RESULT_PROCEEDING 13
+
++#ifdef ISDN_TTY_FCLASS1
+ #define TTY_IS_FCLASS1(info) \
+ ((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \
+ (info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS1))
++#endif
+ #define TTY_IS_FCLASS2(info) \
+ ((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \
+ (info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS2))
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_ttyfax.c linux-2.4.29/drivers/isdn/isdn_ttyfax.c
+--- linux-2.4.29.old/drivers/isdn/isdn_ttyfax.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_ttyfax.c 2005-03-22 15:06:44.561318432 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_ttyfax.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_ttyfax.c,v 1.9 2001/09/24 13:22:43 kai Exp $
+ *
+ * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel).
+ *
+@@ -20,7 +20,7 @@
+ #include "isdn_ttyfax.h"
+
+
+-static char *isdn_tty_fax_revision = "$Revision: 1.1.4.1 $";
++static char *isdn_tty_fax_revision = "$Revision: 1.9 $";
+
+ #define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; }
+
+@@ -148,6 +148,7 @@
+ }
+ }
+
++#ifdef ISDN_TTY_FCLASS1
+ int
+ isdn_tty_fax_command1(modem_info * info, isdn_ctrl * c)
+ {
+@@ -186,6 +187,7 @@
+ }
+ return (0);
+ }
++#endif
+
+ int
+ isdn_tty_fax_command(modem_info * info, isdn_ctrl * c)
+@@ -193,8 +195,10 @@
+ T30_s *f = info->fax;
+ char rs[10];
+
++#ifdef ISDN_TTY_FCLASS1
+ if (TTY_IS_FCLASS1(info))
+ return (isdn_tty_fax_command1(info, c));
++#endif
+
+ #ifdef ISDN_TTY_FAX_CMD_DEBUG
+ printk(KERN_DEBUG "isdn_tty: Fax cmd %d on ttyI%d\n",
+@@ -312,6 +316,7 @@
+ }
+ }
+
++#ifdef ISDN_TTY_FCLASS1
+ /*
+ * Parse AT+F.. FAX class 1 commands
+ */
+@@ -403,6 +408,7 @@
+ }
+ return 1;
+ }
++#endif
+
+ /*
+ * Parse AT+F.. FAX class 2 commands
+@@ -970,6 +976,70 @@
+ }
+ return 0;
+ }
++#if 0
++ /* LO=n - Flow control opts */
++ if (!strncmp(p[0], "LO", 2)) { /* TODO */
++ p[0] += 2;
++ switch (*p[0]) {
++ case '?':
++ p[0]++;
++ sprintf(rs, "\r\n%d", f->lo);
++ isdn_tty_at_cout(rs, info);
++ break;
++ case '=':
++ p[0]++;
++ if (*p[0] == '?') {
++ p[0]++;
++ sprintf(rs, "\r\n0,1,2");
++ isdn_tty_at_cout(rs, info);
++ } else {
++ par = isdn_getnum(p);
++ if ((par < 0) || (par > 2))
++ PARSE_ERROR1;
++ f->lo = par;
++#ifdef ISDN_TTY_FAX_STAT_DEBUG
++ printk(KERN_DEBUG "isdn_tty: Fax FLO=%d\n", par);
++#endif
++ }
++ break;
++ default:
++ PARSE_ERROR1;
++ }
++ return 0;
++ }
++#endif
++#if 0
++ /* LPL=n - Doc for polling cmd */
++ if (!strncmp(p[0], "LPL", 3)) { /* TODO */
++ p[0] += 3;
++ switch (*p[0]) {
++ case '?':
++ p[0]++;
++ sprintf(rs, "\r\n%d", f->lpl);
++ isdn_tty_at_cout(rs, info);
++ break;
++ case '=':
++ p[0]++;
++ if (*p[0] == '?') {
++ p[0]++;
++ sprintf(rs, "\r\n0,1");
++ isdn_tty_at_cout(rs, info);
++ } else {
++ par = isdn_getnum(p);
++ if ((par < 0) || (par > 1))
++ PARSE_ERROR1;
++ f->lpl = par;
++#ifdef ISDN_TTY_FAX_STAT_DEBUG
++ printk(KERN_DEBUG "isdn_tty: Fax FLPL=%d\n", par);
++#endif
++ }
++ break;
++ default:
++ PARSE_ERROR1;
++ }
++ return 0;
++ }
++#endif
+
+ /* MDL? - DCE Model */
+ if (!strncmp(p[0], "MDL?", 4)) {
+@@ -1049,6 +1119,38 @@
+ }
+ return 0;
+ }
++#if 0
++ /* PTS=n - Page transfer status */
++ if (!strncmp(p[0], "PTS", 3)) { /* TODO */
++ p[0] += 3;
++ switch (*p[0]) {
++ case '?':
++ p[0]++;
++ sprintf(rs, "\r\n%d", f->pts);
++ isdn_tty_at_cout(rs, info);
++ break;
++ case '=':
++ p[0]++;
++ if (*p[0] == '?') {
++ p[0]++;
++ sprintf(rs, "\r\n0-5");
++ isdn_tty_at_cout(rs, info);
++ } else {
++ par = isdn_getnum(p);
++ if ((par < 0) || (par > 5))
++ PARSE_ERROR1;
++ f->pts = par;
++#ifdef ISDN_TTY_FAX_STAT_DEBUG
++ printk(KERN_DEBUG "isdn_tty: Fax FPTS=%d\n", par);
++#endif
++ }
++ break;
++ default:
++ PARSE_ERROR1;
++ }
++ return 0;
++ }
++#endif
+
+ /* REL=n - Phase C received EOL alignment */
+ if (!strncmp(p[0], "REL", 3)) {
+@@ -1091,6 +1193,38 @@
+ isdn_tty_at_cout(rs, info);
+ return 0;
+ }
++#if 0
++ /* SPL=n - Enable polling */
++ if (!strncmp(p[0], "SPL", 3)) { /* TODO */
++ p[0] += 3;
++ switch (*p[0]) {
++ case '?':
++ p[0]++;
++ sprintf(rs, "\r\n%d", f->spl);
++ isdn_tty_at_cout(rs, info);
++ break;
++ case '=':
++ p[0]++;
++ if (*p[0] == '?') {
++ p[0]++;
++ sprintf(rs, "\r\n0,1");
++ isdn_tty_at_cout(rs, info);
++ } else {
++ par = isdn_getnum(p);
++ if ((par < 0) || (par > 1))
++ PARSE_ERROR1;
++ f->spl = par;
++#ifdef ISDN_TTY_FAX_STAT_DEBUG
++ printk(KERN_DEBUG "isdn_tty: Fax FSPL=%d\n", par);
++#endif
++ }
++ break;
++ default:
++ PARSE_ERROR1;
++ }
++ return 0;
++ }
++#endif
+
+ /* Phase C Transmit Data Block Size */
+ if (!strncmp(p[0], "TBC=", 4)) { /* dummy, not used */
+@@ -1116,7 +1250,9 @@
+ {
+ if (TTY_IS_FCLASS2(info))
+ return (isdn_tty_cmd_FCLASS2(p, info));
++#ifdef ISDN_TTY_FCLASS1
+ else if (TTY_IS_FCLASS1(info))
+ return (isdn_tty_cmd_FCLASS1(p, info));
++#endif
+ PARSE_ERROR1;
+ }
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_ttyfax.h linux-2.4.29/drivers/isdn/isdn_ttyfax.h
+--- linux-2.4.29.old/drivers/isdn/isdn_ttyfax.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_ttyfax.h 2005-03-22 15:06:44.576316152 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_ttyfax.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_ttyfax.h,v 1.3 2001/09/24 13:22:43 kai Exp $
+ *
+ * header for Linux ISDN subsystem, tty_fax related functions (linklevel).
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_v110.c linux-2.4.29/drivers/isdn/isdn_v110.c
+--- linux-2.4.29.old/drivers/isdn/isdn_v110.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_v110.c 2005-03-22 15:06:44.593313568 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_v110.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_v110.c,v 1.8 2001/09/24 13:22:43 kai Exp $
+ *
+ * Linux ISDN subsystem, V.110 related functions (linklevel).
+ *
+@@ -19,7 +19,7 @@
+
+ #undef ISDN_V110_DEBUG
+
+-char *isdn_v110_revision = "$Revision: 1.1.4.1 $";
++char *isdn_v110_revision = "$Revision: 1.8 $";
+
+ #define V110_38400 255
+ #define V110_19200 15
+@@ -138,6 +138,14 @@
+ return;
+ #ifdef ISDN_V110_DEBUG
+ printk(KERN_DEBUG "v110 close\n");
++#if 0
++ printk(KERN_DEBUG "isdn_v110_close: nbytes=%d\n", v->nbytes);
++ printk(KERN_DEBUG "isdn_v110_close: nbits=%d\n", v->nbits);
++ printk(KERN_DEBUG "isdn_v110_close: key=%d\n", v->key);
++ printk(KERN_DEBUG "isdn_v110_close: SyncInit=%d\n", v->SyncInit);
++ printk(KERN_DEBUG "isdn_v110:close: decodelen=%d\n", v->decodelen);
++ printk(KERN_DEBUG "isdn_v110_close: framelen=%d\n", v->framelen);
++#endif
+ #endif
+ kfree(v->encodebuf);
+ kfree(v);
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_v110.h linux-2.4.29/drivers/isdn/isdn_v110.h
+--- linux-2.4.29.old/drivers/isdn/isdn_v110.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_v110.h 2005-03-22 15:06:44.608311288 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_v110.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_v110.h,v 1.5 2001/09/24 13:22:43 kai Exp $
+ *
+ * Linux ISDN subsystem, V.110 related functions (linklevel).
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_x25iface.c linux-2.4.29/drivers/isdn/isdn_x25iface.c
+--- linux-2.4.29.old/drivers/isdn/isdn_x25iface.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_x25iface.c 2005-03-22 15:06:44.626308552 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_x25iface.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_x25iface.c,v 1.10 2001/09/24 13:22:43 kai Exp $
+ *
+ * Linux ISDN subsystem, X.25 related functions
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_x25iface.h linux-2.4.29/drivers/isdn/isdn_x25iface.h
+--- linux-2.4.29.old/drivers/isdn/isdn_x25iface.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_x25iface.h 2005-03-22 15:06:44.645305664 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_x25iface.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_x25iface.h,v 1.4 2001/09/24 13:22:43 kai Exp $
+ *
+ * header for Linux ISDN subsystem, x.25 related functions
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/isdnloop/isdnloop.c linux-2.4.29/drivers/isdn/isdnloop/isdnloop.c
+--- linux-2.4.29.old/drivers/isdn/isdnloop/isdnloop.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdnloop/isdnloop.c 2005-03-22 15:06:48.813671976 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnloop.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id: isdnloop.c,v 1.17 2001/08/30 10:45:42 kai Exp $
+ *
+ * ISDN low-level module implementing a dummy loop driver.
+ *
+@@ -14,7 +14,7 @@
+ #include <linux/init.h>
+ #include "isdnloop.h"
+
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision$";
+ static char *isdnloop_id;
+
+ MODULE_DESCRIPTION("ISDN4Linux: Pseudo Driver that simulates an ISDN card");
+@@ -22,8 +22,8 @@
+ MODULE_LICENSE("GPL");
+ MODULE_PARM(isdnloop_id, "s");
+ MODULE_PARM_DESC(isdnloop_id, "ID-String of first card");
+-
+-static int isdnloop_addcard(char *);
++
++ static int isdnloop_addcard(char *);
+
+ /*
+ * Free queue completely.
+@@ -1542,11 +1542,7 @@
+ } else
+ strcpy(rev, " ??? ");
+ printk(KERN_NOTICE "isdnloop-ISDN-driver Rev%s\n", rev);
+-
+- if (isdnloop_id)
+- return (isdnloop_addcard(isdnloop_id));
+-
+- return 0;
++ return (isdnloop_addcard(isdnloop_id));
+ }
+
+ static void __exit
+diff -rNu linux-2.4.29.old/drivers/isdn/isdnloop/isdnloop.h linux-2.4.29/drivers/isdn/isdnloop/isdnloop.h
+--- linux-2.4.29.old/drivers/isdn/isdnloop/isdnloop.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdnloop/isdnloop.h 2005-03-22 15:06:48.834668784 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnloop.h,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Loopback lowlevel module for testing of linklevel.
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/callbacks.c linux-2.4.29/drivers/isdn/pcbit/callbacks.c
+--- linux-2.4.29.old/drivers/isdn/pcbit/callbacks.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/callbacks.c 2005-03-22 15:06:48.909657384 +0100
+@@ -3,7 +3,7 @@
+ *
+ * Copyright (C) 1996 Universidade de Lisboa
+ *
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License, incorporated herein by reference.
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/callbacks.h linux-2.4.29/drivers/isdn/pcbit/callbacks.h
+--- linux-2.4.29.old/drivers/isdn/pcbit/callbacks.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/callbacks.h 2005-03-22 15:06:48.953650696 +0100
+@@ -3,7 +3,7 @@
+ *
+ * Copyright (C) 1996 Universidade de Lisboa
+ *
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License, incorporated herein by reference.
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/capi.c linux-2.4.29/drivers/isdn/pcbit/capi.c
+--- linux-2.4.29.old/drivers/isdn/pcbit/capi.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/capi.c 2005-03-22 15:06:49.042637168 +0100
+@@ -4,7 +4,7 @@
+ *
+ * Copyright (C) 1996 Universidade de Lisboa
+ *
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License, incorporated herein by reference.
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/capi.h linux-2.4.29/drivers/isdn/pcbit/capi.h
+--- linux-2.4.29.old/drivers/isdn/pcbit/capi.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/capi.h 2005-03-22 15:06:49.071632760 +0100
+@@ -3,7 +3,7 @@
+ *
+ * Copyright (C) 1996 Universidade de Lisboa
+ *
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License, incorporated herein by reference.
+@@ -63,7 +63,8 @@
+ extern int capi_decode_debug_188(u_char *hdr, ushort hdrlen);
+ #endif
+
+-static inline struct pcbit_chan *
++extern __inline__
++struct pcbit_chan *
+ capi_channel(struct pcbit_dev *dev, struct sk_buff *skb)
+ {
+ ushort callref;
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/drv.c linux-2.4.29/drivers/isdn/pcbit/drv.c
+--- linux-2.4.29.old/drivers/isdn/pcbit/drv.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/drv.c 2005-03-22 15:06:49.091629720 +0100
+@@ -3,7 +3,7 @@
+ *
+ * Copyright (C) 1996 Universidade de Lisboa
+ *
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License, incorporated herein by reference.
+@@ -35,7 +35,9 @@
+ #include <linux/isdnif.h>
+ #include <asm/string.h>
+ #include <asm/io.h>
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ #include <linux/ioport.h>
++#endif
+
+ #include "pcbit.h"
+ #include "edss1.h"
+@@ -89,6 +91,7 @@
+
+ if (mem_base >= 0xA0000 && mem_base <= 0xFFFFF ) {
+ dev->ph_mem = mem_base;
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ if (check_mem_region(dev->ph_mem, 4096)) {
+ printk(KERN_WARNING
+ "PCBIT: memory region %lx-%lx already in use\n",
+@@ -100,6 +103,9 @@
+ request_mem_region(dev->ph_mem, 4096, "PCBIT mem");
+ }
+ dev->sh_mem = (unsigned char*)ioremap(dev->ph_mem, 4096);
++#else
++ dev->sh_mem = (unsigned char*) mem_base;
++#endif
+ }
+ else
+ {
+@@ -112,8 +118,10 @@
+ dev->b1 = kmalloc(sizeof(struct pcbit_chan), GFP_KERNEL);
+ if (!dev->b1) {
+ printk("pcbit_init: couldn't malloc pcbit_chan struct\n");
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ iounmap((unsigned char*)dev->sh_mem);
+ release_mem_region(dev->ph_mem, 4096);
++#endif
+ kfree(dev);
+ return -ENOMEM;
+ }
+@@ -122,8 +130,10 @@
+ if (!dev->b2) {
+ printk("pcbit_init: couldn't malloc pcbit_chan struct\n");
+ kfree(dev->b1);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ iounmap((unsigned char*)dev->sh_mem);
+ release_mem_region(dev->ph_mem, 4096);
++#endif
+ kfree(dev);
+ return -ENOMEM;
+ }
+@@ -144,8 +154,10 @@
+ {
+ kfree(dev->b1);
+ kfree(dev->b2);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ iounmap((unsigned char*)dev->sh_mem);
+ release_mem_region(dev->ph_mem, 4096);
++#endif
+ kfree(dev);
+ dev_pcbit[board] = NULL;
+ return -EIO;
+@@ -166,8 +178,10 @@
+ free_irq(irq, dev);
+ kfree(dev->b1);
+ kfree(dev->b2);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ iounmap((unsigned char*)dev->sh_mem);
+ release_mem_region(dev->ph_mem, 4096);
++#endif
+ kfree(dev);
+ dev_pcbit[board] = NULL;
+ return -EIO;
+@@ -197,8 +211,10 @@
+ free_irq(irq, dev);
+ kfree(dev->b1);
+ kfree(dev->b2);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ iounmap((unsigned char*)dev->sh_mem);
+ release_mem_region(dev->ph_mem, 4096);
++#endif
+ kfree(dev);
+ dev_pcbit[board] = NULL;
+ return -EIO;
+@@ -235,8 +251,10 @@
+ del_timer(&dev->b2->fsm_timer);
+ kfree(dev->b1);
+ kfree(dev->b2);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ iounmap((unsigned char*)dev->sh_mem);
+ release_mem_region(dev->ph_mem, 4096);
++#endif
+ kfree(dev);
+ }
+ }
+@@ -430,7 +448,7 @@
+ switch(dev->l2_state) {
+ case L2_LWMODE:
+ /* check (size <= rdp_size); write buf into board */
+- if (len < 0 || len > BANK4 + 1)
++ if (len > BANK4 + 1)
+ {
+ printk("pcbit_writecmd: invalid length %d\n", len);
+ return -EINVAL;
+@@ -609,6 +627,20 @@
+ dev->b1->s_refnum,
+ dev->b2->s_refnum);
+ #endif
++#if 0
++ if (dev->b1->s_refnum == refnum)
++ chan = dev->b1;
++ else {
++
++ if (dev->b2->s_refnum == refnum)
++ chan = dev->b2;
++ else {
++ chan = NULL;
++ printk(KERN_WARNING "Connection Confirm - refnum doesn't match chan\n");
++ break;
++ }
++ }
++#else
+ /* We just try to find a channel in the right state */
+
+ if (dev->b1->fsm_state == ST_CALL_INIT)
+@@ -622,6 +654,7 @@
+ break;
+ }
+ }
++#endif
+ if (capi_decode_conn_conf(chan, skb, &complete)) {
+ printk(KERN_DEBUG "conn_conf indicates error\n");
+ pcbit_fsm_event(dev, chan, EV_ERROR, NULL);
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/edss1.c linux-2.4.29/drivers/isdn/pcbit/edss1.c
+--- linux-2.4.29.old/drivers/isdn/pcbit/edss1.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/edss1.c 2005-03-22 15:06:49.119625464 +0100
+@@ -4,7 +4,7 @@
+ *
+ * Copyright (C) 1996 Universidade de Lisboa
+ *
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License, incorporated herein by reference.
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/edss1.h linux-2.4.29/drivers/isdn/pcbit/edss1.h
+--- linux-2.4.29.old/drivers/isdn/pcbit/edss1.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/edss1.h 2005-03-22 15:06:49.161619080 +0100
+@@ -3,7 +3,7 @@
+ *
+ * Copyright (C) 1996 Universidade de Lisboa
+ *
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License, incorporated herein by reference.
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/layer2.c linux-2.4.29/drivers/isdn/pcbit/layer2.c
+--- linux-2.4.29.old/drivers/isdn/pcbit/layer2.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/layer2.c 2005-03-22 15:06:49.195613912 +0100
+@@ -3,7 +3,7 @@
+ *
+ * Copyright (C) 1996 Universidade de Lisboa
+ *
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License, incorporated herein by reference.
+@@ -369,11 +369,16 @@
+
+ if (dev->read_frame) {
+ printk(KERN_DEBUG "pcbit_receive: Type 0 frame and read_frame != NULL\n");
++#if 0
++ pcbit_l2_error(dev);
++ return;
++#else
+ /* discard previous queued frame */
+ if (dev->read_frame->skb)
+ kfree_skb(dev->read_frame->skb);
+ kfree(dev->read_frame);
+ dev->read_frame = NULL;
++#endif
+ }
+ frame = kmalloc(sizeof(struct frame_buf), GFP_ATOMIC);
+
+@@ -449,10 +454,14 @@
+
+ if (!(frame = dev->read_frame)) {
+ printk("Type 1 frame and no frame queued\n");
++#if 1
+ /* usually after an error: toss frame */
+ dev->readptr += tt;
+ if (dev->readptr > dev->sh_mem + BANK2 + BANKLEN)
+ dev->readptr -= BANKLEN;
++#else
++ pcbit_l2_error(dev);
++#endif
+ return;
+
+ }
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/layer2.h linux-2.4.29/drivers/isdn/pcbit/layer2.h
+--- linux-2.4.29.old/drivers/isdn/pcbit/layer2.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/layer2.h 2005-03-22 15:06:49.228608896 +0100
+@@ -3,7 +3,7 @@
+ *
+ * Copyright (C) 1996 Universidade de Lisboa
+ *
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License, incorporated herein by reference.
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/module.c linux-2.4.29/drivers/isdn/pcbit/module.c
+--- linux-2.4.29.old/drivers/isdn/pcbit/module.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/module.c 2005-03-22 15:06:49.251605400 +0100
+@@ -3,7 +3,7 @@
+ *
+ * Copyright (C) 1996 Universidade de Lisboa
+ *
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License, incorporated herein by reference.
+@@ -92,6 +92,7 @@
+ }
+
+ #ifndef MODULE
++#ifdef COMPAT_HAS_NEW_SETUP
+ #define MAX_PARA (MAX_PCBIT_CARDS * 2)
+ static int __init pcbit_setup(char *line)
+ {
+@@ -100,6 +101,11 @@
+ int ints[MAX_PARA+1];
+
+ str = get_options(line, MAX_PARA, ints);
++#else
++void pcbit_setup(char *str, int *ints)
++{
++ int i, j, argc;
++#endif
+ argc = ints[0];
+ i = 0;
+ j = 1;
+@@ -118,9 +124,13 @@
+
+ i++;
+ }
++#ifdef COMPAT_HAS_NEW_SETUP
+ return(1);
+ }
+ __setup("pcbit=", pcbit_setup);
++#else
++}
++#endif
+ #endif
+
+ module_init(pcbit_init);
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/pcbit.h linux-2.4.29/drivers/isdn/pcbit/pcbit.h
+--- linux-2.4.29.old/drivers/isdn/pcbit/pcbit.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/pcbit.h 2005-03-22 15:06:49.284600384 +0100
+@@ -3,7 +3,7 @@
+ *
+ * Copyright (C) 1996 Universidade de Lisboa
+ *
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License, incorporated herein by reference.
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/card.h linux-2.4.29/drivers/isdn/sc/card.h
+--- linux-2.4.29.old/drivers/isdn/sc/card.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/card.h 2005-03-22 15:06:49.333592936 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: card.h,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Driver parameters for SpellCaster ISA ISDN adapters
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/command.c linux-2.4.29/drivers/isdn/sc/command.c
+--- linux-2.4.29.old/drivers/isdn/sc/command.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/command.c 2005-03-22 15:06:49.348590656 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: command.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Copyright (C) 1996 SpellCaster Telecommunications Inc.
+ *
+@@ -95,7 +95,7 @@
+ if(adapter[i]->driverId == driver)
+ return i;
+ }
+- return -ENODEV;
++ return -NODEV;
+ }
+
+ /*
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/debug.c linux-2.4.29/drivers/isdn/sc/debug.c
+--- linux-2.4.29.old/drivers/isdn/sc/debug.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/debug.c 2005-03-22 15:06:49.363588376 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: debug.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Copyright (C) 1996 SpellCaster Telecommunications Inc.
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/debug.h linux-2.4.29/drivers/isdn/sc/debug.h
+--- linux-2.4.29.old/drivers/isdn/sc/debug.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/debug.h 2005-03-22 15:06:49.378586096 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: debug.h,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Copyright (C) 1996 SpellCaster Telecommunications Inc.
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/event.c linux-2.4.29/drivers/isdn/sc/event.c
+--- linux-2.4.29.old/drivers/isdn/sc/event.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/event.c 2005-03-22 15:06:49.394583664 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: event.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Copyright (C) 1996 SpellCaster Telecommunications Inc.
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/init.c linux-2.4.29/drivers/isdn/sc/init.c
+--- linux-2.4.29.old/drivers/isdn/sc/init.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/init.c 2005-03-22 15:06:49.432577888 +0100
+@@ -514,6 +514,15 @@
+ schedule_timeout(HZ);
+ sig = readl(rambase + SIG_OFFSET);
+ pr_debug("Looking for a signature, got 0x%x\n", sig);
++#if 0
++/*
++ * For Gary:
++ * If it's a timing problem, it should be gone with the above schedule()
++ * Another possible reason may be the missing volatile in the original
++ * code. readl() does this for us.
++ */
++ printk(""); /* Hack! Doesn't work without this !!!??? */
++#endif
+ if(sig == SIGNATURE)
+ return PRI_BOARD;
+
+@@ -525,6 +534,9 @@
+ schedule_timeout(HZ);
+ sig = readl(rambase + SIG_OFFSET);
+ pr_debug("Looking for a signature, got 0x%x\n", sig);
++#if 0
++ printk(""); /* Hack! Doesn't work without this !!!??? */
++#endif
+ if(sig == SIGNATURE)
+ return BRI_BOARD;
+
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/interrupt.c linux-2.4.29/drivers/isdn/sc/interrupt.c
+--- linux-2.4.29.old/drivers/isdn/sc/interrupt.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/interrupt.c 2005-03-22 15:06:49.447575608 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: interrupt.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Copyright (C) 1996 SpellCaster Telecommunications Inc.
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/ioctl.c linux-2.4.29/drivers/isdn/sc/ioctl.c
+--- linux-2.4.29.old/drivers/isdn/sc/ioctl.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/ioctl.c 2005-03-22 15:06:49.463573176 +0100
+@@ -23,6 +23,9 @@
+
+ extern board *adapter[];
+
++#if 0
++static char *ChannelStates[] = { "Idle", "Ready", "Connecting", "Connected", "Disconnecting" };
++#endif
+
+ int GetStatus(int card, boardInfo *);
+
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/message.c linux-2.4.29/drivers/isdn/sc/message.c
+--- linux-2.4.29.old/drivers/isdn/sc/message.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/message.c 2005-03-22 15:06:49.478570896 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: message.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * functions for sending and receiving control messages
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/message.h linux-2.4.29/drivers/isdn/sc/message.h
+--- linux-2.4.29.old/drivers/isdn/sc/message.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/message.h 2005-03-22 15:06:49.495568312 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: message.h,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Copyright (C) 1996 SpellCaster Telecommunications Inc.
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/packet.c linux-2.4.29/drivers/isdn/sc/packet.c
+--- linux-2.4.29.old/drivers/isdn/sc/packet.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/packet.c 2005-03-22 15:06:49.514565424 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: packet.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Copyright (C) 1996 SpellCaster Telecommunications Inc.
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/shmem.c linux-2.4.29/drivers/isdn/sc/shmem.c
+--- linux-2.4.29.old/drivers/isdn/sc/shmem.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/shmem.c 2005-03-22 15:06:49.560558432 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: shmem.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Copyright (C) 1996 SpellCaster Telecommunications Inc.
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/timer.c linux-2.4.29/drivers/isdn/sc/timer.c
+--- linux-2.4.29.old/drivers/isdn/sc/timer.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/timer.c 2005-03-22 15:06:49.575556152 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: timer.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Copyright (C) 1996 SpellCaster Telecommunications Inc.
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/tpam/tpam.h linux-2.4.29/drivers/isdn/tpam/tpam.h
+--- linux-2.4.29.old/drivers/isdn/tpam/tpam.h 2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/tpam/tpam.h 2005-03-22 15:06:49.648545056 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam.h,v 1.1.2.1 2001/11/20 14:19:37 kai Exp $
++/* $Id: tpam.h,v 1.3 2001/09/24 13:23:12 kai Exp $
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver)
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/tpam/tpam_commands.c linux-2.4.29/drivers/isdn/tpam/tpam_commands.c
+--- linux-2.4.29.old/drivers/isdn/tpam/tpam_commands.c 2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/tpam/tpam_commands.c 2005-03-22 15:06:49.664542624 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam_commands.c,v 1.1.2.1 2001/11/20 14:19:37 kai Exp $
++/* $Id: tpam_commands.c,v 1.3 2001/09/24 13:23:12 kai Exp $
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver - ISDN commands)
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/tpam/tpam_crcpc.c linux-2.4.29/drivers/isdn/tpam/tpam_crcpc.c
+--- linux-2.4.29.old/drivers/isdn/tpam/tpam_crcpc.c 2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/tpam/tpam_crcpc.c 2005-03-22 15:06:49.681540040 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam_crcpc.c,v 1.1.2.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver - CRC encoding)
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/tpam/tpam_hdlc.c linux-2.4.29/drivers/isdn/tpam/tpam_hdlc.c
+--- linux-2.4.29.old/drivers/isdn/tpam/tpam_hdlc.c 2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/tpam/tpam_hdlc.c 2005-03-22 15:06:49.702536848 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam_hdlc.c,v 1.1.2.1 2001/11/20 14:19:37 kai Exp $
++/* $Id: tpam_hdlc.c,v 1.3 2001/09/24 13:23:12 kai Exp $
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver - HDLC encoding)
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/tpam/tpam_main.c linux-2.4.29/drivers/isdn/tpam/tpam_main.c
+--- linux-2.4.29.old/drivers/isdn/tpam/tpam_main.c 2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/tpam/tpam_main.c 2005-03-22 15:06:49.717534568 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam_main.c,v 1.1.2.2 2001/12/09 18:45:14 kai Exp $
++/* $Id$
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver - main routines)
+ *
+@@ -254,7 +254,7 @@
+ name: "tpam",
+ id_table: tpam_pci_tbl,
+ probe: tpam_probe,
+- remove: __devexit_p(tpam_remove),
++ remove: tpam_remove,
+ };
+
+ static int __init tpam_init(void) {
+diff -rNu linux-2.4.29.old/drivers/isdn/tpam/tpam_memory.c linux-2.4.29/drivers/isdn/tpam/tpam_memory.c
+--- linux-2.4.29.old/drivers/isdn/tpam/tpam_memory.c 2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/tpam/tpam_memory.c 2005-03-22 15:06:49.734531984 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam_memory.c,v 1.1.2.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver - Board Memory Access)
+ *
+diff -rNu linux-2.4.29.old/drivers/isdn/tpam/tpam_nco.c linux-2.4.29/drivers/isdn/tpam/tpam_nco.c
+--- linux-2.4.29.old/drivers/isdn/tpam/tpam_nco.c 2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/tpam/tpam_nco.c 2005-03-22 15:06:49.749529704 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam_nco.c,v 1.1.2.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Turbo PAM ISDN driver for Linux.
+ * (Kernel Driver - Low Level NCO Manipulation)
+diff -rNu linux-2.4.29.old/drivers/isdn/tpam/tpam_queues.c linux-2.4.29/drivers/isdn/tpam/tpam_queues.c
+--- linux-2.4.29.old/drivers/isdn/tpam/tpam_queues.c 2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/tpam/tpam_queues.c 2005-03-22 15:06:49.764527424 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam_queues.c,v 1.1.2.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver)
+ *
+@@ -146,7 +146,6 @@
+ do {
+ hpic = readl(card->bar0 + TPAM_HPIC_REGISTER);
+ if (waiting_too_long++ > 0xfffffff) {
+- kfree_skb(skb);
+ spin_unlock(&card->lock);
+ printk(KERN_ERR "TurboPAM(tpam_irq): "
+ "waiting too long...\n");
+diff -rNu linux-2.4.29.old/include/linux/b1lli.h linux-2.4.29/include/linux/b1lli.h
+--- linux-2.4.29.old/include/linux/b1lli.h 2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/b1lli.h 2005-03-22 15:06:49.881509640 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: b1lli.h,v 1.8.8.3 2001/09/23 22:25:05 kai Exp $
++/* $Id$
+ *
+ * ISDN lowlevel-module for AVM B1-card.
+ *
+diff -rNu linux-2.4.29.old/include/linux/b1pcmcia.h linux-2.4.29/include/linux/b1pcmcia.h
+--- linux-2.4.29.old/include/linux/b1pcmcia.h 2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/b1pcmcia.h 2005-03-22 15:06:49.862512528 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: b1pcmcia.h,v 1.1.8.2 2001/09/23 22:25:05 kai Exp $
++/* $Id$
+ *
+ * Exported functions of module b1pcmcia to be called by
+ * avm_cs card services module.
+diff -rNu linux-2.4.29.old/include/linux/capi.h linux-2.4.29/include/linux/capi.h
+--- linux-2.4.29.old/include/linux/capi.h 2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/capi.h 2005-03-22 15:06:49.922503408 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capi.h,v 1.1.4.1 2001/11/20 14:19:38 kai Exp $
++/* $Id$
+ *
+ * CAPI 2.0 Interface for Linux
+ *
+diff -rNu linux-2.4.29.old/include/linux/concap.h linux-2.4.29/include/linux/concap.h
+--- linux-2.4.29.old/include/linux/concap.h 2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/concap.h 2005-03-22 15:06:49.906505840 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: concap.h,v 1.2.8.1 2001/09/23 22:25:05 kai Exp $
++/* $Id: concap.h,v 1.3 2001/09/24 13:23:13 kai Exp $
+ *
+ * Copyright 1997 by Henner Eisen <eis@baty.hanse.de>
+ *
+@@ -11,6 +11,7 @@
+ #ifdef __KERNEL__
+ #include <linux/skbuff.h>
+ #include <linux/netdevice.h>
++#include <linux/isdn_compat.h>
+
+ /* Stuff to support encapsulation protocols genericly. The encapsulation
+ protocol is processed at the uppermost layer of the network interface.
+diff -rNu linux-2.4.29.old/include/linux/hysdn_if.h linux-2.4.29/include/linux/hysdn_if.h
+--- linux-2.4.29.old/include/linux/hysdn_if.h 2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/hysdn_if.h 2005-03-22 15:06:49.974495504 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_if.h,v 1.1.8.3 2001/09/23 22:25:05 kai Exp $
++/* $Id$
+ *
+ * Linux driver for HYSDN cards
+ * ioctl definitions shared by hynetmgr and driver.
+diff -rNu linux-2.4.29.old/include/linux/isdn/tpam.h linux-2.4.29/include/linux/isdn/tpam.h
+--- linux-2.4.29.old/include/linux/isdn/tpam.h 2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/isdn/tpam.h 2005-03-22 15:06:49.947499608 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam.h,v 1.1.2.1 2001/11/20 14:19:38 kai Exp $
++/* $Id$
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver)
+ *
+diff -rNu linux-2.4.29.old/include/linux/isdn.h linux-2.4.29/include/linux/isdn.h
+--- linux-2.4.29.old/include/linux/isdn.h 2005-03-22 14:47:31.000000000 +0100
++++ linux-2.4.29/include/linux/isdn.h 2005-03-22 15:06:50.001491400 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn.h,v 1.1.4.1 2001/11/20 14:19:38 kai Exp $
++/* $Id: isdn.h,v 1.125 2001/12/01 23:18:21 detabc Exp $
+ *
+ * Main header for the Linux ISDN subsystem (linklevel).
+ *
+@@ -14,6 +14,7 @@
+ #ifndef __ISDN_H__
+ #define __ISDN_H__
+
++#include <linux/isdn_compat.h>
+ #include <linux/ioctl.h>
+
+ #ifdef CONFIG_COBALT_MICRO_SERVER
+@@ -93,9 +94,15 @@
+ #define ISDN_LMSNLEN 255 /* Length of tty's Listen-MSN string */
+ #define ISDN_CMSGLEN 50 /* Length of CONNECT-Message to add for Modem */
+
++#ifdef BIG_PHONE_NUMBERS
+ #define ISDN_MSNLEN 32
+ #define NET_DV 0x06 /* Data version for isdn_net_ioctl_cfg */
+ #define TTY_DV 0x06 /* Data version for iprofd etc. */
++#else
++#define ISDN_MSNLEN 20
++#define NET_DV 0x05 /* Data version for isdn_net_ioctl_cfg */
++#define TTY_DV 0x05 /* Data version for iprofd etc. */
++#endif
+
+ #define INF_DV 0x01 /* Data version for /dev/isdninfo */
+
+@@ -187,6 +194,61 @@
+ #define ISDN_MINOR_PPPMAX (128 + (ISDN_MAX_CHANNELS-1))
+ #define ISDN_MINOR_STATUS 255
+
++#ifndef CONFIG_ISDN_WITH_ABC
++#undef CONFIG_ISDN_WITH_ABC_CALLB
++#undef CONFIG_ISDN_WITH_ABC_UDP_CHECK
++#undef CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP
++#undef CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL
++#undef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++#undef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++#undef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++#undef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
++#undef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++#undef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
++#else /* CONFIG_ISDN_WITH_ABC */
++#include <linux/isdn_dwabc.h>
++
++
++typedef struct DWABCJIFFIES {
++
++ u_long msec_1000;
++ u_long msec_500;
++ u_long msec_400;
++ u_long msec_200;
++ u_long msec_100;
++
++} DWABCJIFFIES;
++
++
++#ifdef CONFIG_ISDN_WITH_ABC_NEED_DWSJIFFIES
++DWABCJIFFIES isdn_dwabc_jiffies;
++#else
++extern DWABCJIFFIES isdn_dwabc_jiffies;
++#endif
++#define dwsjiffies (isdn_dwabc_jiffies.msec_1000)
++
++#define ISDN_DW_ABC_FLAG_UNUSED00001 0x00000001L
++#define ISDN_DW_ABC_FLAG_NO_UDP_CHECK 0x00000002L
++#define ISDN_DW_ABC_FLAG_NO_UDP_HANGUP 0x00000004L
++#define ISDN_DW_ABC_FLAG_NO_UDP_DIAL 0x00000008L
++#define ISDN_DW_ABC_FLAG_UNUSED00010 0x00000010L
++#define ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER 0x00000020L
++#define ISDN_DW_ABC_FLAG_NO_CH_EXTINUSE 0x00000040L
++#define ISDN_DW_ABC_FLAG_NO_CONN_ERROR 0x00000080L
++#define ISDN_DW_ABC_FLAG_BSD_COMPRESS 0x00000100L
++#define ISDN_DW_ABC_FLAG_NO_LCR 0x00000200L
++#define ISDN_DW_ABC_FLAG_LEASED_LINE 0x00001000L
++
++#define ISDN_DW_ABC_IFFLAG_NODCHAN 0x00000001L
++#define ISDN_DW_ABC_IFFLAG_BSDAKTIV 0x00000002L
++
++#define ISDN_DW_ABC_BITLOCK_SEND 0
++#define ISDN_DW_ABC_BITLOCK_RECEIVE 1
++
++#endif /* CONFIG_ISDN_WITH_ABC */
++
++
++
+ #ifdef CONFIG_ISDN_PPP
+
+ #ifdef CONFIG_ISDN_PPP_VJ
+@@ -204,9 +266,11 @@
+ # include <linux/concap.h>
+ #endif
+
++#ifdef HAVE_DEVFS_FS
+ #ifdef CONFIG_DEVFS_FS
+ # include <linux/devfs_fs_kernel.h>
+ #endif
++#endif /* HAVE_DEVFS_FS */
+
+ #include <linux/isdnif.h>
+
+@@ -272,6 +336,12 @@
+ #define ISDN_NET_CALLBACK 0x04 /* activate callback */
+ #define ISDN_NET_CBHUP 0x08 /* hangup before callback */
+ #define ISDN_NET_CBOUT 0x10 /* remote machine does callback */
++#if 0
++/* Unused??? */
++#define ISDN_NET_CLONE 0x08 /* clone a tmp interface when called */
++#define ISDN_NET_TMP 0x10 /* tmp interface until getting an IP */
++#define ISDN_NET_DYNAMIC 0x20 /* this link is dynamically allocated */
++#endif
+
+ #define ISDN_NET_MAGIC 0x49344C02 /* for paranoia-checking */
+
+@@ -386,6 +456,38 @@
+ char cisco_debserint; /* debugging flag of cisco hdlc with slarp */
+ struct timer_list cisco_timer;
+ struct tq_struct tqueue;
++#ifdef CONFIG_ISDN_WITH_ABC
++ ulong dw_abc_flags;
++ ulong dw_abc_if_flags;
++ int dw_abc_inuse_secure;
++ ulong dw_abc_dialstart;
++ int dw_abc_old_onhtime;
++ int dw_abc_remote_version;
++ int dw_abc_bitlocks;
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++ char dw_out_msn[ISDN_MSNLEN]; /* eaz for outgoing call if *out_msn != 0 */
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++ ulong dw_abc_lcr_callid;
++ ulong dw_abc_lcr_start_request;
++ ulong dw_abc_lcr_end_request;
++ isdn_ctrl *dw_abc_lcr_cmd;
++ struct ISDN_DWABC_LCR_IOCTL *dw_abc_lcr_io;
++#endif
++ ulong dw_abc_bchan_last_connect;
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++ short dw_abc_bchan_errcnt;
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
++ void *dw_abc_bsd_compressor;
++ void *dw_abc_bsd_stat_rx;
++ void *dw_abc_bsd_stat_tx;
++#endif
++ ulong dw_abc_bsd_snd;
++ ulong dw_abc_bsd_bsd_snd;
++ ulong dw_abc_bsd_rcv;
++ ulong dw_abc_bsd_bsd_rcv;
++#endif
+ } isdn_net_local;
+
+ /* the interface itself */
+@@ -608,12 +710,13 @@
+ int tflags; /* Timer-Flags: */
+ /* see ISDN_TIMER_..defines */
+ int global_flags;
+- infostruct *infochain; /* List of open info-devs. */
+- wait_queue_head_t info_waitq; /* Wait-Queue for isdninfo */
+ struct timer_list timer; /* Misc.-function Timer */
+ int chanmap[ISDN_MAX_CHANNELS];/* Map minor->device-channel */
+ int drvmap[ISDN_MAX_CHANNELS]; /* Map minor->driver-index */
+ int usage[ISDN_MAX_CHANNELS]; /* Used by tty/ip/voice */
++#ifdef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
++ ulong dwabc_chan_external_inuse[ISDN_MAX_CHANNELS];
++#endif
+ char num[ISDN_MAX_CHANNELS][ISDN_MSNLEN];
+ /* Remote number of active ch.*/
+ int m_idx[ISDN_MAX_CHANNELS]; /* Index for mdm.... */
+@@ -631,6 +734,7 @@
+ isdn_v110_stream *v110[ISDN_MAX_CHANNELS]; /* V.110 private data */
+ struct semaphore sem; /* serialize list access*/
+ unsigned long global_features;
++#ifdef HAVE_DEVFS_FS
+ #ifdef CONFIG_DEVFS_FS
+ devfs_handle_t devfs_handle_isdninfo;
+ devfs_handle_t devfs_handle_isdnctrl;
+@@ -640,10 +744,41 @@
+ devfs_handle_t devfs_handle_ipppX[ISDN_MAX_CHANNELS];
+ #endif
+ #endif /* CONFIG_DEVFS_FS */
++#endif /* HAVE_DEVFS_FS */
+ } isdn_dev;
+
+ extern isdn_dev *dev;
+
++#ifdef CONFIG_ISDN_WITH_ABC
++extern int isdn_auto_dial_helper(isdn_net_local *,struct sk_buff *,int);
++extern void dwisdn_nfw_send(isdn_net_local *lp,int drop_only);
++extern void isdn_net_unreachable(struct net_device *,struct sk_buff *,char *);
++extern void isdn_net_log_skb_dwabc(struct sk_buff *,isdn_net_local *,char *);
++extern void isdn_net_hangup(struct net_device *d);
++extern void isdn_dw_clear_if(ulong pm,isdn_net_local *);
++extern void isdn_dwabc_test_phone(isdn_net_local *);
++extern void isdn_dw_abc_init_func(void);
++extern void isdn_dw_abc_release_func(void);
++extern int isdn_dw_abc_reset_interface(isdn_net_local *,int);
++extern int dwabc_bsd_init(isdn_net_local *lp);
++extern void dwabc_bsd_free(isdn_net_local *lp);
++extern struct sk_buff *dwabc_bsd_compress(isdn_net_local *,struct sk_buff *,struct net_device *);
++extern void dwabc_bsd_first_gen(isdn_net_local *);
++extern struct sk_buff *dwabc_bsd_rx_pkt(isdn_net_local *,struct sk_buff *,struct net_device *);
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++extern size_t isdn_dw_abc_lcr_readstat(char *,size_t);
++extern ulong isdn_dw_abc_lcr_call_number(isdn_net_local *,isdn_ctrl *);
++extern void isdn_dw_abc_lcr_open(void);
++extern void isdn_dw_abc_lcr_close(void);
++extern int isdn_dw_abc_lcr_ioctl(ulong);
++extern void isdn_dw_abc_lcr_clear(isdn_net_local *);
++extern int isdn_dw_abc_lcr_lock(void);
++extern void isdn_dw_abc_lcr_ulock(void);
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK
++extern int dw_abc_udp_test(struct sk_buff *skb,struct net_device *ndev);
++#endif
++#endif
+
+ #endif /* __KERNEL__ */
+
+diff -rNu linux-2.4.29.old/include/linux/isdn_compat.h linux-2.4.29/include/linux/isdn_compat.h
+--- linux-2.4.29.old/include/linux/isdn_compat.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/include/linux/isdn_compat.h 2005-03-22 15:06:50.017488968 +0100
+@@ -0,0 +1,261 @@
++/* $Id: isdn_compat.h,v 1.53 2001/09/24 13:23:13 kai Exp $
++ *
++ * Linux ISDN subsystem
++ * Compatibility for various Linux kernel versions
++ *
++ * This software may be used and distributed according to the terms
++ * of the GNU General Public License, incorporated herein by reference.
++ *
++ */
++
++#ifndef _LINUX_ISDN_COMPAT_H
++#define _LINUX_ISDN_COMPAT_H
++
++#ifdef __KERNEL__
++
++#ifndef ISDN_COMPAT_NOT_GENERIC
++/* when using std2kern -u, this part is left out and instead provided
++ by the .ctrl files */
++
++#include <linux/version.h>
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)
++
++#define set_current_state(sta) (current->state = sta)
++#define module_init(x) int init_module(void) { return x(); }
++#define module_exit(x) void cleanup_module(void) { x(); }
++#define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0 = 0; } while (0)
++#define init_MUTEX(x) *(x)=MUTEX
++#define init_MUTEX_LOCKED(x) *(x)=MUTEX_LOCKED
++#define __devinit
++#define __devinitdata
++
++#else /* 2.2.18 and later */
++
++#define COMPAT_HAS_NEW_SETUP
++#define COMPAT_HAS_NEW_WAITQ
++
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
++
++#define dev_kfree_skb_irq(a) dev_kfree_skb(a)
++#define dev_kfree_skb_any(a) dev_kfree_skb(a)
++#define COMPAT_HAS_2_2_PCI
++#define get_pcibase(ps, nr) ps->base_address[nr]
++#define pci_resource_start_io(pdev, nr) ((pdev)->base_address[nr] & PCI_BASE_ADDRESS_IO_MASK)
++#define pci_resource_start_mem(pdev, nr) ((pdev)->base_address[nr] & PCI_BASE_ADDRESS_MEM_MASK)
++#define pci_get_sub_vendor(pdev, id) pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &id)
++#define pci_get_sub_system(pdev, id) pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &id)
++
++#define __exit
++#define __devinit
++#define __devinitdata
++
++#define net_device device
++#define COMPAT_NO_SOFTNET
++#define netif_running(d) test_bit(LINK_STATE_START, &d->state)
++#define COMPAT_NEED_MPPP_DEFS
++#define spin_lock_bh(lock)
++#define spin_unlock_bh(lock)
++#define COMPAT_NEED_SPIN_LOCK_BH
++#define i_count_read(ic) ic
++#define i_count_inc(ic) ic++
++#define COMPAT_USE_MODCOUNT_LOCK
++#define devfs_register_chrdev(m,n,f) register_chrdev(m,n,f)
++#define devfs_unregister_chrdev(m,n) unregister_chrdev(m,n)
++#define COMPAT_NEED_PCI_IDS
++#define in_irq() (local_irq_count[smp_processor_id()] != 0)
++
++#else /* 2.4.0 and later */
++
++#define pci_resource_start_io(pdev, nr) pci_resource_start(pdev, nr)
++#define pci_resource_start_mem(pdev, nr) pci_resource_start(pdev, nr)
++#define get_pcibase(ps, nr) ps->resource[nr].start
++#define pci_get_sub_system(pdev, id) id = pdev->subsystem_device
++#define pci_get_sub_vendor(pdev, id) id = pdev->subsystem_vendor
++
++#define BIG_PHONE_NUMBERS
++#define COMPAT_HAS_ISA_IOREMAP
++#define i_count_read(ic) atomic_read(&ic)
++#define i_count_inc(ic) atomic_inc(&ic)
++#define COMPAT_HAS_FILEOP_OWNER
++#define COMPAT_HAVE_NEW_FILLDIR
++#define COMPAT_has_fileops_in_inode
++#define COMPAT_HAS_init_special_inode
++#define COMPAT_d_alloc_root_one_parameter
++#define HAVE_DEVFS_FS
++#define COMPAT_HAS_SCHEDULE_TASK
++#define COMPAT_HAS_USB_IDTAB
++
++#endif
++
++#endif /* ISDN_COMPAT_GENERIC */
++
++#ifdef COMPAT_HAS_2_2_PCI
++#include <linux/pci.h>
++#ifdef __powerpc__
++static inline int pci_enable_device(struct pci_dev *dev)
++{
++ u16 cmd;
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_SERR;
++ cmd &= ~PCI_COMMAND_FAST_BACK;
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++ return(0);
++}
++#else
++static inline int pci_enable_device(struct pci_dev *dev)
++{
++ return 0;
++}
++#endif /* __powerpc__ */
++
++#define PCI_ANY_ID (~0)
++
++/* as this is included multiple times, we make it inline */
++
++static inline struct pci_dev * pci_find_subsys(unsigned int vendor, unsigned int device,
++ unsigned int ss_vendor, unsigned int ss_device,
++ struct pci_dev *from)
++{
++ unsigned short subsystem_vendor, subsystem_device;
++
++ while ((from = pci_find_device(vendor, device, from))) {
++ pci_read_config_word(from, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
++ pci_read_config_word(from, PCI_SUBSYSTEM_ID, &subsystem_device);
++ if ((ss_vendor == PCI_ANY_ID || subsystem_vendor == ss_vendor) &&
++ (ss_device == PCI_ANY_ID || subsystem_device == ss_device))
++ return from;
++ }
++ return NULL;
++}
++#endif
++
++#ifdef COMPAT_NO_SOFTNET
++#include <linux/netdevice.h>
++
++/*
++ * Tell upper layers that the network device is ready to xmit more frames.
++ */
++static void __inline__ netif_wake_queue(struct net_device * dev)
++{
++ dev->tbusy = 0;
++ mark_bh(NET_BH);
++}
++
++/*
++ * called during net_device open()
++ */
++static void __inline__ netif_start_queue(struct net_device * dev)
++{
++ dev->tbusy = 0;
++ /* actually, we never use the interrupt flag at all */
++ dev->interrupt = 0;
++ dev->start = 1;
++}
++
++/*
++ * Ask upper layers to temporarily cease passing us more xmit frames.
++ */
++static void __inline__ netif_stop_queue(struct net_device * dev)
++{
++ dev->tbusy = 1;
++}
++
++#endif /* COMPAT_NO_SOFTNET */
++
++#ifndef COMPAT_HAS_NEW_WAITQ
++typedef struct wait_queue wait_queue_t;
++typedef struct wait_queue *wait_queue_head_t;
++
++#define DECLARE_WAITQUEUE(wait, current) struct wait_queue wait = { current, NULL }
++#define DECLARE_WAIT_QUEUE_HEAD(wait) wait_queue_head_t wait
++#define init_waitqueue_head(x) *(x)=NULL
++#define init_waitqueue_entry(q,p) ((q)->task)=(p)
++#endif /* COMPAT_HAS_NEW_WAITQ */
++
++#ifdef COMPAT_NEED_PCI_IDS
++
++#define PCI_ANY_ID (~0)
++
++#define PCI_VENDOR_ID_DYNALINK 0x0675
++#define PCI_DEVICE_ID_DYNALINK_IS64PH 0x1702
++
++#define PCI_DEVICE_ID_WINBOND2_6692 0x6692
++
++#define PCI_DEVICE_ID_PLX_R685 0x1030
++#define PCI_DEVICE_ID_PLX_DJINN_ITOO 0x1151
++#define PCI_DEVICE_ID_PLX_R753 0x1152
++
++#define PCI_VENDOR_ID_ELSA 0x1048
++#define PCI_DEVICE_ID_ELSA_MICROLINK 0x1000
++#define PCI_DEVICE_ID_ELSA_QS3000 0x3000
++
++#define PCI_VENDOR_ID_EICON 0x1133
++#define PCI_DEVICE_ID_EICON_DIVA20PRO 0xe001
++#define PCI_DEVICE_ID_EICON_DIVA20 0xe002
++#define PCI_DEVICE_ID_EICON_DIVA20PRO_U 0xe003
++#define PCI_DEVICE_ID_EICON_DIVA20_U 0xe004
++#define PCI_DEVICE_ID_EICON_DIVA201 0xe005
++#define PCI_DEVICE_ID_EICON_MAESTRA 0xe010
++#define PCI_DEVICE_ID_EICON_MAESTRAQ 0xe012
++#define PCI_DEVICE_ID_EICON_MAESTRAQ_U 0xe013
++#define PCI_DEVICE_ID_EICON_MAESTRAP 0xe014
++
++#define PCI_VENDOR_ID_CCD 0x1397
++#define PCI_DEVICE_ID_CCD_2BD0 0x2BD0
++#define PCI_DEVICE_ID_CCD_B000 0xB000
++#define PCI_DEVICE_ID_CCD_B006 0xB006
++#define PCI_DEVICE_ID_CCD_B007 0xB007
++#define PCI_DEVICE_ID_CCD_B008 0xB008
++#define PCI_DEVICE_ID_CCD_B009 0xB009
++#define PCI_DEVICE_ID_CCD_B00A 0xB00A
++#define PCI_DEVICE_ID_CCD_B00B 0xB00B
++#define PCI_DEVICE_ID_CCD_B00C 0xB00C
++#define PCI_DEVICE_ID_CCD_B100 0xB100
++
++#define PCI_VENDOR_ID_ASUSTEK 0x1043
++#define PCI_DEVICE_ID_ASUSTEK_0675 0x0675
++
++#define PCI_VENDOR_ID_BERKOM 0x0871
++#define PCI_DEVICE_ID_BERKOM_A1T 0xFFA1
++#define PCI_DEVICE_ID_BERKOM_T_CONCEPT 0xFFA2
++#define PCI_DEVICE_ID_BERKOM_A4T 0xFFA4
++#define PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO 0xFFA8
++
++#define PCI_DEVICE_ID_SATSAGEM_NICCY 0x1016
++
++#define PCI_DEVICE_ID_TIGERJET_100 0x0002
++
++#define PCI_VENDOR_ID_ANIGMA 0x1051
++#define PCI_DEVICE_ID_ANIGMA_MC145575 0x0100
++
++#define PCI_VENDOR_ID_ZOLTRIX 0x15b0
++#define PCI_DEVICE_ID_ZOLTRIX_2BD0 0x2BD0
++
++#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E 0x0070
++#define PCI_DEVICE_ID_DIGI_DF_M_E 0x0071
++#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A 0x0072
++#define PCI_DEVICE_ID_DIGI_DF_M_A 0x0073
++
++#define PCI_DEVICE_ID_AVM_B1 0x0700
++#define PCI_DEVICE_ID_AVM_C4 0x0800
++#define PCI_DEVICE_ID_AVM_C2 0x1100
++#define PCI_DEVICE_ID_AVM_T1 0x1200
++
++#define PCI_VENDOR_ID_HYPERCOPE 0x1365
++#define PCI_DEVICE_ID_HYPERCOPE_PLX 0x9050
++#define PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO 0x0104
++#define PCI_SUBDEVICE_ID_HYPERCOPE_ERGO 0x0106
++#define PCI_SUBDEVICE_ID_HYPERCOPE_METRO 0x0107
++#define PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2 0x0108
++#define PCI_SUBDEVICE_ID_HYPERCOPE_PLEXUS 0x0109
++
++#define PCI_VENDOR_ID_ABOCOM 0x13D1
++#define PCI_DEVICE_ID_ABOCOM_2BD1 0x2BD1
++
++#endif /* COMPAT_NEED_PCI_IDS */
++
++#endif /* __KERNEL__ */
++#endif /* _LINUX_ISDN_COMPAT_H */
+diff -rNu linux-2.4.29.old/include/linux/isdn_divertif.h linux-2.4.29/include/linux/isdn_divertif.h
+--- linux-2.4.29.old/include/linux/isdn_divertif.h 2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/isdn_divertif.h 2005-03-22 15:06:50.032486688 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_divertif.h,v 1.1.4.1 2001/11/20 14:19:38 kai Exp $
++/* $Id$
+ *
+ * Header for the diversion supplementary interface for i4l.
+ *
+@@ -14,7 +14,7 @@
+ /***********************************************************/
+ /* magic value is also used to control version information */
+ /***********************************************************/
+-#define DIVERT_IF_MAGIC 0x25873401
++#define DIVERT_IF_MAGIC 0x25873402
+ #define DIVERT_CMD_REG 0x00 /* register command */
+ #define DIVERT_CMD_REL 0x01 /* release command */
+ #define DIVERT_NO_ERR 0x00 /* return value no error */
+@@ -34,6 +34,7 @@
+ int (*ll_cmd)(isdn_ctrl *); /* supplied by hl on return */
+ char * (*drv_to_name)(int); /* map a driver id to name, supplied by hl */
+ int (*name_to_drv)(char *); /* map a driver id to name, supplied by hl */
++ int (*dial_net_name)(char *); /* force dial of a ll net interface */
+ } isdn_divert_if;
+
+ /*********************/
+diff -rNu linux-2.4.29.old/include/linux/isdn_dwabc.h linux-2.4.29/include/linux/isdn_dwabc.h
+--- linux-2.4.29.old/include/linux/isdn_dwabc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/include/linux/isdn_dwabc.h 2005-03-22 15:06:50.048484256 +0100
+@@ -0,0 +1,84 @@
++/* $Id: isdn_dwabc.h,v 1.9 2001/09/26 20:32:08 detabc Exp $
++ *
++ * Header for the Linux ISDN abc-extension.
++ *
++ * Copyright by abc GmbH
++ * written by Detlef Wengorz <detlefw@isdn4linux.de>
++ *
++ * This software may be used and distributed according to the terms
++ * of the GNU General Public License, incorporated herein by reference.
++ *
++ */
++
++#ifndef ISDN_DWABC_H
++#define ISDN_DWABC_H
++
++#ifdef __KERNEL__
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/smp.h>
++#include <linux/spinlock.h>
++#include <linux/errno.h>
++
++
++typedef struct ISDN_DWSPINLOCK {
++
++ spinlock_t spin;
++ short owner;
++ short my_flags;
++ ulong irq_flags;
++
++} ISDN_DWSPINLOCK;
++
++#define ISDN_DWSPIN_UNLOCKED \
++ (ISDN_DWSPINLOCK) { \
++ spin: SPIN_LOCK_UNLOCKED, \
++ owner: -1, \
++ my_flags: 0, \
++ irq_flags: 0, \
++ }
++
++#define ISDN_DWSPIN_INIT(x) \
++ do { *(x) = ISDN_DWSPIN_UNLOCKED; } while(0);
++
++static __inline__ int isdn_dwspin_trylock(ISDN_DWSPINLOCK *spin)
++{
++ if(!spin_trylock(&spin->spin)) {
++
++ if(spin->owner == smp_processor_id())
++ return(-EAGAIN);
++
++ spin_lock(&spin->spin);
++ }
++
++ spin->owner = smp_processor_id();
++ return(0);
++}
++
++static __inline__ void isdn_dwspin_unlock(ISDN_DWSPINLOCK *spin)
++{
++ spin->owner = -1;
++ spin_unlock(&spin->spin);
++}
++
++
++#else
++#include <sys/types.h>
++#endif
++
++#define DWABC_LCR_FLG_NEWNUMBER 0x00000001L
++#define DWABC_LCR_FLG_DISABLE 0x00000002L
++#define DWABC_LCR_FLG_NEWHUPTIME 0x00000004L
++
++
++struct ISDN_DWABC_LCR_IOCTL {
++
++ int lcr_ioctl_sizeof; /* mustbe sizeof(ISDN_DWABC_LCR_IOCTL) */
++ u_short lcr_ioctl_onhtime; /* new hanguptime */
++ u_long lcr_ioctl_callid; /* callid from lcr-subsystem */
++ u_long lcr_ioctl_flags; /* see above */
++ char lcr_ioctl_nr[32]; /* new destination phonenumber */
++};
++
++#endif
+diff -rNu linux-2.4.29.old/include/linux/isdn_lzscomp.h linux-2.4.29/include/linux/isdn_lzscomp.h
+--- linux-2.4.29.old/include/linux/isdn_lzscomp.h 2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/isdn_lzscomp.h 2005-03-22 15:06:50.089478024 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_lzscomp.h,v 1.1.4.1 2001/11/20 14:19:38 kai Exp $
++/* $Id$
+ *
+ * Header for isdn_lzscomp.c
+ * Concentrated here to not mess up half a dozen kernel headers with code
+diff -rNu linux-2.4.29.old/include/linux/isdn_ppp.h linux-2.4.29/include/linux/isdn_ppp.h
+--- linux-2.4.29.old/include/linux/isdn_ppp.h 2005-03-22 14:47:31.000000000 +0100
++++ linux-2.4.29/include/linux/isdn_ppp.h 2005-03-22 15:06:50.116473920 +0100
+@@ -8,6 +8,7 @@
+ #ifndef _LINUX_ISDN_PPP_H
+ #define _LINUX_ISDN_PPP_H
+
++#include <linux/isdn_compat.h>
+
+ #define CALLTYPE_INCOMING 0x1
+ #define CALLTYPE_OUTGOING 0x2
+@@ -33,6 +34,11 @@
+ #define PPPIOCSCOMPRESSOR _IOW('t',135,int)
+ #define PPPIOCGIFNAME _IOR('t',136, char [IFNAMSIZ] )
+
++#ifdef COMPAT_NEED_MPPP_DEFS
++#define PPP_MP 0x003d
++#define PPP_COMPFRAG 0x00fb
++#define PPP_CCPFRAG 0x80fb
++#endif
+
+ #define SC_MP_PROT 0x00000200
+ #define SC_REJ_MP_PROT 0x00000400
+@@ -65,9 +71,6 @@
+
+ #include <linux/config.h>
+
+-#ifdef CONFIG_IPPP_FILTER
+-#include <linux/filter.h>
+-#endif
+
+ #define DECOMP_ERR_NOMEM (-10)
+
+@@ -226,10 +229,6 @@
+ unsigned char *cbuf;
+ struct slcompress *slcomp;
+ #endif
+-#ifdef CONFIG_IPPP_FILTER
+- struct sock_fprog pass_filter; /* filter for packets to pass */
+- struct sock_fprog active_filter; /* filter for pkts to reset idle */
+-#endif
+ unsigned long debug;
+ struct isdn_ppp_compressor *compressor,*decompressor;
+ struct isdn_ppp_compressor *link_compressor,*link_decompressor;
+diff -rNu linux-2.4.29.old/include/linux/isdnif.h linux-2.4.29/include/linux/isdnif.h
+--- linux-2.4.29.old/include/linux/isdnif.h 2005-03-22 14:47:31.000000000 +0100
++++ linux-2.4.29/include/linux/isdnif.h 2005-03-22 15:06:50.132471488 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnif.h,v 1.1.4.1 2001/11/20 14:19:38 kai Exp $
++/* $Id: isdnif.h,v 1.43 2002/02/09 21:19:11 keil Exp $
+ *
+ * Linux ISDN subsystem
+ * Definition of the interface between the subsystem and its low-level drivers.
+@@ -14,6 +14,7 @@
+ #ifndef __ISDNIF_H__
+ #define __ISDNIF_H__
+
++#include <linux/isdn_compat.h>
+
+ /*
+ * Values for general protocol-selection
+@@ -213,6 +214,8 @@
+ #define ISDN_STAT_FAXIND 276 /* FAX indications from HL-driver */
+ #define ISDN_STAT_AUDIO 277 /* DTMF, DSP indications */
+ #define ISDN_STAT_DISCH 278 /* Disable/Enable channel usage */
++#define ISDN_STAT_ALERT 279 /* Signal alerting */
++#define ISDN_STAT_PROCEED 280 /* Signal proceeding */
+
+ /*
+ * Audio commands
+diff -rNu linux-2.4.29.old/include/linux/kernelcapi.h linux-2.4.29/include/linux/kernelcapi.h
+--- linux-2.4.29.old/include/linux/kernelcapi.h 2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/kernelcapi.h 2005-03-22 15:06:50.147469208 +0100
+@@ -1,12 +1,10 @@
+-/* $Id: kernelcapi.h,v 1.1.4.2 2002/01/28 18:25:10 kai Exp $
++/*
++ * $Id: kernelcapi.h,v 1.9 2000/11/28 09:34:02 kai Exp $
+ *
+ * Kernel CAPI 2.0 Interface for Linux
+ *
+ * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
+ *
+- * This software may be used and distributed according to the terms
+- * of the GNU General Public License, incorporated herein by reference.
+- *
+ */
+
+ #ifndef __KERNELCAPI_H__
diff --git a/target/linux/generic-2.4/patches/201-hfc_usb_backport.patch b/target/linux/generic-2.4/patches/201-hfc_usb_backport.patch
new file mode 100644
index 0000000000..4ef20fa8ba
--- /dev/null
+++ b/target/linux/generic-2.4/patches/201-hfc_usb_backport.patch
@@ -0,0 +1,2663 @@
+diff -rNu linux-2.4.29.old/drivers/Makefile linux-2.4.29/drivers/Makefile
+--- linux-2.4.29.old/drivers/Makefile 2005-03-22 14:47:41.000000000 +0100
++++ linux-2.4.29/drivers/Makefile 2005-03-22 15:15:20.012957872 +0100
+@@ -38,7 +38,7 @@
+ subdir-$(CONFIG_MD) += md
+ subdir-$(CONFIG_IEEE1394) += ieee1394
+ subdir-$(CONFIG_PNP) += pnp
+-subdir-$(CONFIG_ISDN_BOOL) += isdn
++subdir-$(CONFIG_ISDN) += isdn
+ subdir-$(CONFIG_ATM) += atm
+ subdir-$(CONFIG_FC4) += fc4
+
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_usb.c linux-2.4.29/drivers/isdn/hisax/hfc_usb.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_usb.c 2005-03-22 15:13:58.233390256 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_usb.c 2005-03-22 15:14:57.475384104 +0100
+@@ -1,13 +1,11 @@
+-/* $Id: hfc_usb.c,v 2.3 2001/07/06 21:30:11 werner Exp $
++/*
++ * hfc_usb.c
+ *
++ * modular HiSax ISDN driver for Colognechip HFC-USB chip
+ *
+- *
+- * Author (C) 2001 Werner Cornelius (werner@isdn-development.de)
+- * modular driver for Colognechip HFC-USB chip
+- * as plugin for HiSax isdn driver
+- * type approval valid for HFC-S USB based TAs
+- *
+- * Copyright 2001 by Werner Cornelius (werner@isdn-development.de)
++ * Authors : Peter Sprenger (sprenger@moving-byters.de)
++ * Martin Bachem (info@colognechip.com)
++ * based on the first hfc_usb driver of Werner Cornelius (werner@isdn-development.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
+@@ -23,70 +21,90 @@
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+- */
++ * 2005_Mar_16 grsch
++ * ported 2.6.8 hfc_usb.c to 2.4.20 format
++ * Gregor Schaffrath <gschaff@ran-dom.org>
++*/
++
+
+ #include <linux/types.h>
+ #include <linux/stddef.h>
+ #include <linux/timer.h>
+ #include <linux/config.h>
+-#include <linux/isdn_compat.h>
+ #include <linux/init.h>
+ #include "hisax.h"
+ #include <linux/module.h>
+ #include <linux/kernel_stat.h>
+-#include <linux/tqueue.h>
+ #include <linux/usb.h>
+ #include <linux/kernel.h>
+ #include <linux/smp_lock.h>
+ #include <linux/sched.h>
++#include "hisax_if.h"
+ #include "hisax_loadable.h"
+
++static const char *hfcusb_revision = "4.0";
++
++/*
++ to enable much mire debug messages in this driver, define
++ VERBOSE_USB_DEBUG and VERBOSE_ISDN_DEBUG
++ below
++*/
++
++#define VERBOSE_USB_DEBUG
++#define VERBOSE_ISDN_DEBUG
++
+ #define INCLUDE_INLINE_FUNCS
+
++#define TRUE 1
++#define FALSE 0
++
++
+ /***********/
+ /* defines */
+ /***********/
+-#define HFC_CTRL_TIMEOUT 5 /* 5ms timeout writing/reading regs */
+-#define HFC_TIMER_T3 7000 /* timeout for l1 activation timer */
+-
+-#define HFCUSB_L1_STATECHANGE 0 /* L1 state changed */
+-#define HFCUSB_L1_DRX 1 /* D-frame received */
+-#define HFCUSB_L1_ERX 2 /* E-frame received */
+-#define HFCUSB_L1_DTX 4 /* D-frames completed */
+-
+-#define MAX_BCH_SIZE 2048 /* allowed B-channel packet size */
+-
+-#define HFCUSB_RX_THRESHOLD 64 /* threshold for fifo report bit rx */
+-#define HFCUSB_TX_THRESHOLD 64 /* threshold for fifo report bit tx */
+-
+-#define HFCUSB_CHIP_ID 0x16 /* Chip ID register index */
+-#define HFCUSB_CIRM 0x00 /* cirm register index */
+-#define HFCUSB_USB_SIZE 0x07 /* int length register */
+-#define HFCUSB_USB_SIZE_I 0x06 /* iso length register */
+-#define HFCUSB_F_CROSS 0x0b /* bit order register */
+-#define HFCUSB_CLKDEL 0x37 /* bit delay register */
+-#define HFCUSB_CON_HDLC 0xfa /* channel connect register */
++#define HFC_CTRL_TIMEOUT 20 //(HZ * USB_CTRL_GET_TIMEOUT)
++/* 5ms timeout writing/reading regs */
++#define HFC_TIMER_T3 8000 /* timeout for l1 activation timer */
++#define HFC_TIMER_T4 500 /* time for state change interval */
++
++#define HFCUSB_L1_STATECHANGE 0 /* L1 state changed */
++#define HFCUSB_L1_DRX 1 /* D-frame received */
++#define HFCUSB_L1_ERX 2 /* E-frame received */
++#define HFCUSB_L1_DTX 4 /* D-frames completed */
++
++#define MAX_BCH_SIZE 2048 /* allowed B-channel packet size */
++
++#define HFCUSB_RX_THRESHOLD 64 /* threshold for fifo report bit rx */
++#define HFCUSB_TX_THRESHOLD 64 /* threshold for fifo report bit tx */
++
++#define HFCUSB_CHIP_ID 0x16 /* Chip ID register index */
++#define HFCUSB_CIRM 0x00 /* cirm register index */
++#define HFCUSB_USB_SIZE 0x07 /* int length register */
++#define HFCUSB_USB_SIZE_I 0x06 /* iso length register */
++#define HFCUSB_F_CROSS 0x0b /* bit order register */
++#define HFCUSB_CLKDEL 0x37 /* bit delay register */
++#define HFCUSB_CON_HDLC 0xfa /* channel connect register */
+ #define HFCUSB_HDLC_PAR 0xfb
+-#define HFCUSB_SCTRL 0x31 /* S-bus control register (tx) */
+-#define HFCUSB_SCTRL_E 0x32 /* same for E and special funcs */
+-#define HFCUSB_SCTRL_R 0x33 /* S-bus control register (rx) */
+-#define HFCUSB_F_THRES 0x0c /* threshold register */
+-#define HFCUSB_FIFO 0x0f /* fifo select register */
+-#define HFCUSB_F_USAGE 0x1a /* fifo usage register */
++#define HFCUSB_SCTRL 0x31 /* S-bus control register (tx) */
++#define HFCUSB_SCTRL_E 0x32 /* same for E and special funcs */
++#define HFCUSB_SCTRL_R 0x33 /* S-bus control register (rx) */
++#define HFCUSB_F_THRES 0x0c /* threshold register */
++#define HFCUSB_FIFO 0x0f /* fifo select register */
++#define HFCUSB_F_USAGE 0x1a /* fifo usage register */
+ #define HFCUSB_MST_MODE0 0x14
+ #define HFCUSB_MST_MODE1 0x15
+ #define HFCUSB_P_DATA 0x1f
+ #define HFCUSB_INC_RES_F 0x0e
+ #define HFCUSB_STATES 0x30
+
+-#define HFCUSB_CHIPID 0x40 /* ID value of HFC-USB */
++#define HFCUSB_CHIPID 0x40 /* ID value of HFC-USB */
+
+ /******************/
+ /* fifo registers */
+ /******************/
+-#define HFCUSB_NUM_FIFOS 8 /* maximum number of fifos */
+-#define HFCUSB_B1_TX 0 /* index for B1 transmit bulk/int */
+-#define HFCUSB_B1_RX 1 /* index for B1 receive bulk/int */
++#define HFCUSB_NUM_FIFOS 8 /* maximum number of fifos */
++#define HFCUSB_B1_TX 0 /* index for B1 transmit bulk/int */
++#define HFCUSB_B1_RX 1 /* index for B1 receive bulk/int */
+ #define HFCUSB_B2_TX 2
+ #define HFCUSB_B2_RX 3
+ #define HFCUSB_D_TX 4
+@@ -94,198 +112,162 @@
+ #define HFCUSB_PCM_TX 6
+ #define HFCUSB_PCM_RX 7
+
+-/************/
+-/* LED mask */
+-/************/
+-#define LED_DRIVER 0x1
+-#define LED_L1 0x2
+-#define LED_BCH 0x4
++/*
++* used to switch snd_transfer_mode for different TA modes e.g. the Billion USB TA just
++* supports ISO out, while the Cologne Chip EVAL TA just supports BULK out
++*/
++#define USB_INT 0
++#define USB_BULK 1
++#define USB_ISOC 2
++
++#define ISOC_PACKETS_D 8
++#define ISOC_PACKETS_B 8
++#define ISO_BUFFER_SIZE 128
++
++// ISO send definitions
++#define SINK_MAX 68
++#define SINK_MIN 48
++#define SINK_DMIN 12
++#define SINK_DMAX 18
++#define BITLINE_INF (-64*8)
++
++
++
+
+ /**********/
+ /* macros */
+ /**********/
+-#define Write_hfc(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),0,0,HFC_CTRL_TIMEOUT)
+-#define Read_hfc(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT)
+-
+-#ifdef COMPAT_HAS_USB_IDTAB
+-/****************************************/
+-/* data defining the devices to be used */
+-/****************************************/
+-static __devinitdata const struct usb_device_id hfc_usb_idtab[3] = {
+- {USB_DEVICE(0x959, 0x2bd0)}, /* Colognechip ROM */
+- {USB_DEVICE(0x7b0, 0x0006)}, /* USB TA 128 */
+- {} /* end with an all-zeroes entry */
+-};
+-#endif
++#define write_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),NULL,0,HFC_CTRL_TIMEOUT)
++#define read_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT)
+
+ /*************************************************/
+ /* entry and size of output/input control buffer */
+ /*************************************************/
+ #define HFC_CTRL_BUFSIZE 32
+-typedef struct {
++typedef struct
++{
+ __u8 hfc_reg; /* register number */
+ __u8 reg_val; /* value to be written (or read) */
++ int action; /* data for action handler */
++
+ } ctrl_buft;
+
++typedef struct
++{
++ int vendor; // vendor id
++ int prod_id; // product id
++ char *vend_name; // vendor string
++ __u8 led_scheme; // led display scheme
++ __u8 led_invert; // invert led aux port settings
++ __u8 led_bits[8]; // array of 8 possible LED bitmask settings
++
++} vendor_data;
++
+ /***************************************************************/
+ /* structure defining input+output fifos (interrupt/bulk mode) */
+ /***************************************************************/
+-struct hfcusb_data; /* forward definition */
+-typedef struct {
+- int fifonum; /* fifo index attached to this structure */
+- __u8 fifo_mask; /* mask for this fifo */
+- int active; /* fifo is currently active */
++
++struct usb_fifo; /* forward definition */
++typedef struct iso_urb_struct
++{
++ struct urb *purb;
++ __u8 buffer[ISO_BUFFER_SIZE]; /* buffer incoming/outgoing data */
++ struct usb_fifo *owner_fifo; // pointer to owner fifo
++} iso_urb_struct;
++
++
++struct hfcusb_data; /* forward definition */
++typedef struct usb_fifo
++{
++ int fifonum; /* fifo index attached to this structure */
++ int active; /* fifo is currently active */
+ struct hfcusb_data *hfc; /* pointer to main structure */
+- int pipe; /* address of endpoint */
+- __u8 usb_maxlen; /* maximum length for usb transfer */
+- int max_size; /* maximum size of receive/send packet */
+- int transmode; /* transparent mode selected */
+- int framenum; /* number of frame when last tx completed */
+- int rx_offset; /* offset inside rx buffer */
+- int next_complete; /* complete marker */
+- __u8 *act_ptr; /* pointer to next data */
+- __u8 intervall; /* interrupt interval */
+- struct sk_buff *buff; /* actual used buffer */
+- urb_t urb; /* transfer structure for usb routines */
+- __u8 buffer[128]; /* buffer incoming/outgoing data */
++ int pipe; /* address of endpoint */
++ __u8 usb_packet_maxlen; /* maximum length for usb transfer */
++ unsigned int max_size; /* maximum size of receive/send packet */
++ __u8 intervall; /* interrupt interval */
++ struct sk_buff *skbuff; /* actual used buffer */
++ struct urb *urb; /* transfer structure for usb routines */
++ __u8 buffer[128]; /* buffer incoming/outgoing data */
++ int bit_line; /* how much bits are in the fifo? */
++
++ volatile __u8 usb_transfer_mode;/* switched between ISO and INT */
++ iso_urb_struct iso[2]; /* need two urbs to have one always for pending */
++ struct hisax_if *hif; /* hisax interface */
++ int delete_flg; /* only delete skbuff once */
++ int last_urblen; /* remember length of last packet */
++
+ } usb_fifo;
+
++
+ /*********************************************/
+ /* structure holding all data for one device */
+ /*********************************************/
+-typedef struct hfcusb_data {
+- struct hisax_drvreg regd; /* register data and callbacks */
+- struct usb_device *dev; /* our device */
+- int if_used; /* used interface number */
+- int alt_used; /* used alternate config */
+- int ctrl_paksize; /* control pipe packet size */
++typedef struct hfcusb_data
++{
++ // HiSax Interface for loadable Layer1 drivers
++ struct hisax_d_if d_if; /* see hisax_if.h */
++ struct hisax_b_if b_if[2]; /* see hisax_if.h */
++ int protocol;
++
++ struct usb_device *dev; /* our device */
++ int if_used; /* used interface number */
++ int alt_used; /* used alternate config */
++ int ctrl_paksize; /* control pipe packet size */
+ int ctrl_in_pipe, ctrl_out_pipe; /* handles for control pipe */
++ int cfg_used; /* configuration index used */
++ int vend_idx; // vendor found
++
++ int b_mode[2]; // B-channel mode
++
++ int l1_activated; // layer 1 activated
++
++ int packet_size,iso_packet_size;
+
+ /* control pipe background handling */
+ ctrl_buft ctrl_buff[HFC_CTRL_BUFSIZE]; /* buffer holding queued data */
+- volatile int ctrl_in_idx, ctrl_out_idx, ctrl_cnt; /* input/output pointer + count */
+- urb_t ctrl_urb; /* transfer structure for control channel */
+- devrequest ctrl_write; /* buffer for control write request */
+- devrequest ctrl_read; /* same for read request */
+-
+- volatile __u8 dfifo_fill; /* value read from tx d-fifo */
+- volatile __u8 active_fifos; /* fifos currently active as bit mask */
+- volatile __u8 threshold_mask; /* threshold actually reported */
+- volatile __u8 service_request; /* fifo needs service from task */
+- volatile __u8 ctrl_fifo; /* last selected fifo */
+- volatile __u8 bch_enables; /* or mask for sctrl_r and sctrl register values */
+- volatile __u8 led_req; /* request status of adapters leds */
+- volatile __u8 led_act; /* active status of adapters leds */
++ volatile int ctrl_in_idx, ctrl_out_idx,
++ ctrl_cnt; /* input/output pointer + count */
++ struct urb *ctrl_urb; /* transfer structure for control channel */
++
++ struct usb_ctrlrequest ctrl_write; /* buffer for control write request */
++ struct usb_ctrlrequest ctrl_read; /* same for read request */
++
++ __u8 led_state,led_new_data,led_b_active;
++
++ volatile __u8 threshold_mask; /* threshold actually reported */
++ volatile __u8 bch_enables; /* or mask for sctrl_r and sctrl register values */
++
+ usb_fifo fifos[HFCUSB_NUM_FIFOS]; /* structure holding all fifo data */
+
+- /* layer 1 activation/deactivation handling */
+- volatile __u8 l1_state; /* actual l1 state */
+- volatile ulong l1_event; /* event mask */
+- struct tq_struct l1_tq; /* l1 bh structure */
+- struct timer_list t3_timer; /* timer for activation/deactivation */
+- struct timer_list t4_timer; /* timer for activation/deactivation */
++ volatile __u8 l1_state; /* actual l1 state */
++ struct timer_list t3_timer; /* timer 3 for activation/deactivation */
++ struct timer_list t4_timer; /* timer 4 for activation/deactivation */
++ struct timer_list led_timer; /* timer flashing leds */
++
+ } hfcusb_data;
+
+-#if 0
+-static void
+-usb_dump_urb(purb_t purb)
+-{
+- printk("urb :%p\n", purb);
+- printk("next :%p\n", purb->next);
+- printk("dev :%p\n", purb->dev);
+- printk("pipe :%08X\n", purb->pipe);
+- printk("status :%d\n", purb->status);
+- printk("transfer_flags :%08X\n", purb->transfer_flags);
+- printk("transfer_buffer :%p\n", purb->transfer_buffer);
+- printk("transfer_buffer_length:%d\n",
+- purb->transfer_buffer_length);
+- printk("actual_length :%d\n", purb->actual_length);
+- printk("setup_packet :%p\n", purb->setup_packet);
+- printk("start_frame :%d\n", purb->start_frame);
+- printk("number_of_packets :%d\n", purb->number_of_packets);
+- printk("interval :%d\n", purb->interval);
+- printk("error_count :%d\n", purb->error_count);
+- printk("context :%p\n", purb->context);
+- printk("complete :%p\n", purb->complete);
+-}
+-#endif
+
+-/*************************************************************************/
+-/* bottom half handler for L1 activation/deactiavtaion + D-chan + E-chan */
+-/*************************************************************************/
+-static void
+-usb_l1d_bh(hfcusb_data * hfc)
+-{
++static void collect_rx_frame(usb_fifo *fifo,__u8 *data,int len,int finish);
++
+
+- while (hfc->l1_event) {
+- if (test_and_clear_bit
+- (HFCUSB_L1_STATECHANGE, &hfc->l1_event)) {
+- if (hfc->l1_state == 7)
+- hfc->led_req |= LED_L1;
+- else
+- hfc->led_req &= ~LED_L1;
+- if ((hfc->l1_state == 7) ||
+- (hfc->l1_state == 3))
+- hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
+- (hfc->l1_state ==
+- 7) ? (PH_ACTIVATE |
+- INDICATION)
+- : (PH_DEACTIVATE | INDICATION),
+- NULL);
+- }
+- if (test_and_clear_bit(HFCUSB_L1_DRX, &hfc->l1_event)) {
+- hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
+- PH_DATA | INDICATION,
+- (void *) 0);
+- }
+- if (test_and_clear_bit(HFCUSB_L1_ERX, &hfc->l1_event)) {
+- hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
+- PH_DATA | INDICATION,
+- (void *) 1);
+- }
+- if (test_and_clear_bit(HFCUSB_L1_DTX, &hfc->l1_event)) {
+- hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
+- PH_DATA | CONFIRM, NULL);
+- }
+- } /* while */
+-} /* usb_l1d_bh */
+
+ /******************************************************/
+ /* start next background transfer for control channel */
+ /******************************************************/
+-static void
+-ctrl_start_transfer(hfcusb_data * hfc)
++static void ctrl_start_transfer(hfcusb_data * hfc)
+ {
+-
+- if (hfc->ctrl_cnt) {
+- switch (hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg) {
+- case HFCUSB_F_USAGE:
+- hfc->ctrl_urb.pipe = hfc->ctrl_in_pipe;
+- hfc->ctrl_urb.setup_packet =
+- (u_char *) & hfc->ctrl_read;
+- hfc->ctrl_urb.transfer_buffer_length = 1;
+- hfc->ctrl_read.index =
+- hfc->ctrl_buff[hfc->ctrl_out_idx].
+- hfc_reg;
+- hfc->ctrl_urb.transfer_buffer =
+- (char *) &hfc->dfifo_fill;
+- break;
+-
+- default: /* write register */
+- hfc->ctrl_urb.pipe = hfc->ctrl_out_pipe;
+- hfc->ctrl_urb.setup_packet =
+- (u_char *) & hfc->ctrl_write;
+- hfc->ctrl_urb.transfer_buffer = NULL;
+- hfc->ctrl_urb.transfer_buffer_length = 0;
+- hfc->ctrl_write.index =
+- hfc->ctrl_buff[hfc->ctrl_out_idx].
+- hfc_reg;
+- hfc->ctrl_write.value =
+- hfc->ctrl_buff[hfc->ctrl_out_idx].
+- reg_val;
+- break;
+- }
+- usb_submit_urb(&hfc->ctrl_urb); /* start transfer */
++ int err;
++ if(hfc->ctrl_cnt)
++ {
++ hfc->ctrl_urb->pipe = hfc->ctrl_out_pipe;
++ hfc->ctrl_urb->setup_packet = (u_char *) & hfc->ctrl_write;
++ hfc->ctrl_urb->transfer_buffer = NULL;
++ hfc->ctrl_urb->transfer_buffer_length = 0;
++ hfc->ctrl_write.wIndex = hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg;
++ hfc->ctrl_write.wValue = hfc->ctrl_buff[hfc->ctrl_out_idx].reg_val;
++ err = usb_submit_urb(hfc->ctrl_urb); /* start transfer */
++ printk(KERN_DEBUG "ctrl_start_transfer: submit %d\n", err);
+ }
+ } /* ctrl_start_transfer */
+
+@@ -293,897 +275,1418 @@
+ /* queue a control transfer request */
+ /* return 0 on success. */
+ /************************************/
+-static int
+-queue_control_request(hfcusb_data * hfc, __u8 reg, __u8 val)
++static int queue_control_request(hfcusb_data * hfc, __u8 reg, __u8 val,int action)
+ {
+ ctrl_buft *buf;
+
+- if (hfc->ctrl_cnt >= HFC_CTRL_BUFSIZE)
+- return (1); /* no space left */
+- buf = hfc->ctrl_buff + hfc->ctrl_in_idx; /* pointer to new index */
++#ifdef VERBOSE_USB_DEBUG
++ printk ("HFC_USB: queue_control_request reg: %x, val: %x\n", reg, val);
++#endif
++
++ if(hfc->ctrl_cnt >= HFC_CTRL_BUFSIZE) return(1); /* no space left */
++ buf = &hfc->ctrl_buff[hfc->ctrl_in_idx]; /* pointer to new index */
+ buf->hfc_reg = reg;
+ buf->reg_val = val;
++ buf->action=action;
+ if (++hfc->ctrl_in_idx >= HFC_CTRL_BUFSIZE)
+ hfc->ctrl_in_idx = 0; /* pointer wrap */
+ if (++hfc->ctrl_cnt == 1)
+ ctrl_start_transfer(hfc);
+- return (0);
+-} /* queue_control_request */
++ return(0);
++} /* queue_control_request */
+
+-/**************************************/
+-/* called when timer t3 or t4 expires */
+-/**************************************/
+-static void
+-l1_timer_expire(hfcusb_data * hfc)
+-{
+- if (timer_pending(&hfc->t4_timer))
+- del_timer(&hfc->t4_timer);
+- queue_control_request(hfc, HFCUSB_STATES, 0x40);
+- test_and_set_bit(HFCUSB_L1_STATECHANGE,
+- &hfc->l1_event);
+- queue_task(&hfc->l1_tq, &tq_immediate);
+- mark_bh(IMMEDIATE_BH);
+-} /* l1_timer_expire */
+-
+-/**************************************************/
+-/* (re)fills a tx-fifo urb. Queuing is done later */
+-/**************************************************/
+-static void
+-fill_tx_urb(usb_fifo * fifo)
+-{
+- struct sk_buff *skb;
+- long flags;
+- int i, ii = 0;
+-
+- fifo->urb.dev = fifo->hfc->dev;
+- if ((fifo->buff)
+- && (fifo->urb.transfer_buffer_length < fifo->usb_maxlen)) {
+- switch (fifo->fifonum) {
+- case HFCUSB_B1_TX:
+- case HFCUSB_B2_TX:
+- skb = fifo->buff;
+- fifo->buff = NULL;
+- fifo->hfc->regd.bch_l1l2(fifo->hfc->regd.
+- arg_hisax,
+- (fifo->fifonum ==
+- HFCUSB_B1_TX) ? 0
+- : 1,
+- (PH_DATA |
+- CONFIRM),
+- (void *) skb);
+- fifo->hfc->service_request |=
+- fifo->fifo_mask;
+- return;
+- case HFCUSB_D_TX:
+- dev_kfree_skb_any(fifo->buff);
+- fifo->buff = NULL;
+- save_flags(flags);
+- cli();
+- fifo->hfc->dfifo_fill = 0xff; /* currently invalid data */
+- queue_control_request(fifo->hfc,
+- HFCUSB_FIFO,
+- HFCUSB_D_TX);
+- queue_control_request(fifo->hfc,
+- HFCUSB_F_USAGE, 0);
+- restore_flags(flags);
+- return;
+- default:
+- return; /* error, invalid fifo */
+- }
++
++static int control_action_handler(hfcusb_data *hfc,int reg,int val,int action)
++{
++ if(!action) return(1); // no action defined
++
++ return(0);
++}
++
++
++/***************************************************************/
++/* control completion routine handling background control cmds */
++/***************************************************************/
++static void ctrl_complete(struct urb *urb)
++{
++ hfcusb_data *hfc = (hfcusb_data *) urb->context;
++ ctrl_buft *buf;
++
++ printk(KERN_DEBUG "ctrl_complete cnt %d\n", hfc->ctrl_cnt);
++ urb->dev = hfc->dev;
++ if(hfc->ctrl_cnt)
++ {
++ buf=&hfc->ctrl_buff[hfc->ctrl_out_idx];
++ control_action_handler(hfc,buf->hfc_reg,buf->reg_val,buf->action);
++
++ hfc->ctrl_cnt--; /* decrement actual count */
++ if(++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE) hfc->ctrl_out_idx = 0; /* pointer wrap */
++
++ ctrl_start_transfer(hfc); /* start next transfer */
++ }
++} /* ctrl_complete */
++
++
++
++#define LED_OFF 0 // no LED support
++#define LED_SCHEME1 1 // LED standard scheme
++#define LED_SCHEME2 2 // not used yet...
++
++#define LED_POWER_ON 1
++#define LED_POWER_OFF 2
++#define LED_S0_ON 3
++#define LED_S0_OFF 4
++#define LED_B1_ON 5
++#define LED_B1_OFF 6
++#define LED_B1_DATA 7
++#define LED_B2_ON 8
++#define LED_B2_OFF 9
++#define LED_B2_DATA 10
++
++#define LED_NORMAL 0 // LEDs are normal
++#define LED_INVERTED 1 // LEDs are inverted
++
++// time for LED flashing
++#define LED_TIME 250
++
++vendor_data vdata[]=
++{
++ {0x959, 0x2bd0, "ISDN USB TA (Cologne Chip HFC-S USB based)", LED_OFF,LED_NORMAL,{4,0,2,1}}, /* CologneChip Eval TA */
++ {0x7b0, 0x0007, "Billion tiny USB ISDN TA 128", LED_SCHEME1, LED_INVERTED, {8,0x40,0x20,0x10}}, /* Billion TA */
++ {0x742, 0x2008, "Stollmann USB TA", LED_SCHEME1, LED_NORMAL, {4,0,2,1}}, /* Stollmann TA */
++ {0x8e3, 0x0301, "Olitec USB RNIS", LED_SCHEME1, LED_NORMAL, {2,0,1,4}}, /* Olitec TA */
++ {0x675, 0x1688, "DrayTec USB ISDN TA", LED_SCHEME1, LED_NORMAL, {4,0,2,1}}, /* Draytec TA */
++ {0x7fa, 0x0846, "Bewan Modem RNIS USB", LED_SCHEME1, LED_INVERTED, {8,0x40,0x20,0x10}}, /* Bewan TA */
++ {0} // EOL element
++};
++
++/***************************************************/
++/* write led data to auxport & invert if necessary */
++/***************************************************/
++static void write_led(hfcusb_data * hfc,__u8 led_state)
++{
++ if(led_state!=hfc->led_state)
++ {
++ hfc->led_state=led_state;
++ queue_control_request(hfc, HFCUSB_P_DATA,(vdata[hfc->vend_idx].led_invert) ? ~led_state : led_state,1);
++ }
++}
++
++/******************************************/
++/* invert B-channel LEDs if data is sent */
++/******************************************/
++static void led_timer(hfcusb_data * hfc)
++{
++ static int cnt=0;
++ __u8 led_state=hfc->led_state;
++
++ if(cnt)
++ {
++ if(hfc->led_b_active&1) led_state|=vdata[hfc->vend_idx].led_bits[2];
++ if(hfc->led_b_active&2) led_state|=vdata[hfc->vend_idx].led_bits[3];
++ }
++ else
++ {
++ if(!(hfc->led_b_active&1) || hfc->led_new_data&1) led_state&=~vdata[hfc->vend_idx].led_bits[2];
++ if(!(hfc->led_b_active&2) || hfc->led_new_data&2) led_state&=~vdata[hfc->vend_idx].led_bits[3];
+ }
+
+- /* check if new buffer needed */
+- if (!fifo->buff) {
+- switch (fifo->fifonum) {
+- case HFCUSB_B1_TX:
+- if (fifo->hfc->regd.bsk[0])
+- fifo->buff = *fifo->hfc->regd.bsk[0]; /* B1-channel tx buffer */
++ write_led(hfc,led_state);
++ hfc->led_new_data=0;
++
++ cnt=!cnt;
++ // restart 4 hz timer
++ hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
++ if(!timer_pending(&hfc->led_timer)) add_timer(&hfc->led_timer);
++}
++
++/**************************/
++/* handle LED requests */
++/**************************/
++static void handle_led(hfcusb_data * hfc,int event)
++{
++ __u8 led_state=hfc->led_state;
++
++ // if no scheme -> no LED action
++ if(vdata[hfc->vend_idx].led_scheme==LED_OFF) return;
++
++ switch(event)
++ {
++ case LED_POWER_ON:
++ led_state|=vdata[hfc->vend_idx].led_bits[0];
++ break;
++ case LED_POWER_OFF: // no Power off handling
++ break;
++ case LED_S0_ON:
++ led_state|=vdata[hfc->vend_idx].led_bits[1];
++ break;
++ case LED_S0_OFF:
++ led_state&=~vdata[hfc->vend_idx].led_bits[1];
+ break;
+- case HFCUSB_B2_TX:
+- if (fifo->hfc->regd.bsk[1])
+- fifo->buff = *fifo->hfc->regd.bsk[1]; /* B2-channel tx buffer */
++ case LED_B1_ON:
++ hfc->led_b_active|=1;
+ break;
+- case HFCUSB_D_TX:
+- if (fifo->hfc->regd.dsq)
+- fifo->buff = skb_dequeue(fifo->hfc->regd.dsq); /* D-channel tx queue */
++ case LED_B1_OFF:
++ hfc->led_b_active&=~1;
+ break;
+- default:
+- return; /* error, invalid fifo */
++ case LED_B1_DATA:
++ hfc->led_new_data|=1;
++ break;
++ case LED_B2_ON:
++ hfc->led_b_active|=2;
++ break;
++ case LED_B2_OFF:
++ hfc->led_b_active&=~2;
++ break;
++ case LED_B2_DATA:
++ hfc->led_new_data|=2;
++ break;
++ }
++
++ write_led(hfc,led_state);
++}
++
++/********************************/
++/* called when timer t3 expires */
++/********************************/
++static void l1_timer_expire_t3(hfcusb_data * hfc)
++{
++ //printk (KERN_INFO "HFC-USB: l1_timer_expire_t3\n");
++
++ hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);
++#ifdef VERBOSE_USB_DEBUG
++ printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n");
++#endif
++ hfc->l1_activated=FALSE;
++ handle_led(hfc,LED_S0_OFF);
++}
++
++/********************************/
++/* called when timer t4 expires */
++/********************************/
++static void l1_timer_expire_t4(hfcusb_data * hfc)
++{
++ //printk (KERN_INFO "HFC-USB: l1_timer_expire_t4\n");
++
++ hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);
++#ifdef VERBOSE_USB_DEBUG
++ printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n");
++#endif
++ hfc->l1_activated=FALSE;
++ handle_led(hfc,LED_S0_OFF);
++}
++
++/*****************************/
++/* handle S0 state changes */
++/*****************************/
++static void state_handler(hfcusb_data * hfc,__u8 state)
++{
++ __u8 old_state;
++
++ old_state=hfc->l1_state;
++
++ // range check
++ if(state==old_state || state<1 || state>8) return;
++
++#ifdef VERBOSE_ISDN_DEBUG
++ printk(KERN_INFO "HFC-USB: new S0 state:%d old_state:%d\n",state,old_state);
++#endif
++
++ if(state<4 || state==7 || state==8)
++ {
++ if(timer_pending(&hfc->t3_timer)) del_timer(&hfc->t3_timer);
++ //printk(KERN_INFO "HFC-USB: T3 deactivated\n");
++ }
++
++ if(state>=7)
++ {
++ if(timer_pending(&hfc->t4_timer)) del_timer(&hfc->t4_timer);
++ //printk(KERN_INFO "HFC-USB: T4 deactivated\n");
++ }
++
++ if(state==7 && !hfc->l1_activated)
++ {
++ hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_ACTIVATE | INDICATION,NULL);
++ //printk(KERN_INFO "HFC-USB: PH_ACTIVATE | INDICATION sent\n");
++ hfc->l1_activated=TRUE;
++ handle_led(hfc,LED_S0_ON);
++ }
++ else
++ if(state<=3 /* && activated*/)
++ {
++ if(old_state==7 || old_state==8)
++ {
++ //printk(KERN_INFO "HFC-USB: T4 activated\n");
++ hfc->t4_timer.expires = jiffies + (HFC_TIMER_T4 * HZ) / 1000;
++ if(!timer_pending(&hfc->t4_timer)) add_timer(&hfc->t4_timer);
+ }
+- if (!fifo->buff) {
+- fifo->active = 0; /* we are inactive now */
+- fifo->hfc->active_fifos &= ~fifo->fifo_mask;
+- if (fifo->fifonum == HFCUSB_D_TX) {
+- test_and_set_bit(HFCUSB_L1_DTX,
+- &fifo->hfc->l1_event);
+- queue_task(&fifo->hfc->l1_tq,
+- &tq_immediate);
+- mark_bh(IMMEDIATE_BH);
+- }
+- return;
++ else
++ {
++ hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);
++ //printk(KERN_INFO "HFC-USB: PH_DEACTIVATE | INDICATION sent\n");
++ hfc->l1_activated=FALSE;
++ handle_led(hfc,LED_S0_OFF);
+ }
+- fifo->act_ptr = fifo->buff->data; /* start of data */
+- fifo->active = 1;
+- ii = 1;
+- fifo->hfc->active_fifos |= fifo->fifo_mask;
+- fifo->hfc->service_request &= ~fifo->fifo_mask;
+- }
+- /* fillup the send buffer */
+- i = fifo->buff->len - (fifo->act_ptr - fifo->buff->data); /* remaining length */
+- fifo->buffer[0] = !fifo->transmode; /* not eof */
+- if (i > (fifo->usb_maxlen - ii)) {
+- i = fifo->usb_maxlen - ii;
+- }
+- if (i)
+- memcpy(fifo->buffer + ii, fifo->act_ptr, i);
+- fifo->urb.transfer_buffer_length = i + ii;
+- fifo->rx_offset = ii;
+-} /* fill_tx_urb */
+-
+-/************************************************/
+-/* transmit completion routine for all tx fifos */
+-/************************************************/
+-static void
+-tx_complete(purb_t urb)
++ }
++
++ hfc->l1_state=state;
++}
++
++
++/* prepare iso urb */
++static void fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, void *buf,
++ int num_packets, int packet_size, int interval, usb_complete_t complete, void *context)
+ {
+- usb_fifo *fifo = (usb_fifo *) urb->context; /* pointer to our fifo */
++ int k;
+
+- fifo->hfc->service_request &= ~fifo->fifo_mask; /* no further handling */
+- fifo->framenum = usb_get_current_frame_number(fifo->hfc->dev);
++ spin_lock_init(&urb->lock); // do we really need spin_lock_init ?
++ urb->dev = dev;
++ urb->pipe = pipe;
++ urb->complete = complete;
++ urb->number_of_packets = num_packets;
++ urb->transfer_buffer_length = packet_size * num_packets;
++ urb->context = context;
++ urb->transfer_buffer = buf;
++ urb->transfer_flags = 0;
++ urb->transfer_flags = USB_ISO_ASAP;
++ urb->actual_length = 0;
++ urb->interval = interval;
++ for (k = 0; k < num_packets; k++) {
++ urb->iso_frame_desc[k].offset = packet_size * k;
++ urb->iso_frame_desc[k].length = packet_size;
++ urb->iso_frame_desc[k].actual_length = 0;
++ }
++}
+
+- /* check for deactivation or error */
+- if ((!fifo->active) || (urb->status)) {
+- fifo->hfc->active_fifos &= ~fifo->fifo_mask; /* we are inactive */
+- fifo->active = 0;
+- if ((fifo->buff) && (fifo->fifonum == HFCUSB_D_TX)) {
+- dev_kfree_skb_any(fifo->buff);
++/* allocs urbs and start isoc transfer with two pending urbs to avoid gaps in the transfer chain */
++static int start_isoc_chain(usb_fifo * fifo, int num_packets_per_urb,usb_complete_t complete,int packet_size)
++{
++ int i, k, errcode;
++
++#ifdef VERBOSE_USB_DEBUG
++ printk(KERN_INFO "HFC-USB: starting ISO-chain for Fifo %i\n", fifo->fifonum);
++#endif
++
++
++ // allocate Memory for Iso out Urbs
++ for (i = 0; i < 2; i++) {
++ if (!(fifo->iso[i].purb)) {
++ fifo->iso[i].purb = usb_alloc_urb(num_packets_per_urb);
++ fifo->iso[i].owner_fifo = (struct usb_fifo *) fifo;
++
++ // Init the first iso
++ if (ISO_BUFFER_SIZE >= (fifo->usb_packet_maxlen * num_packets_per_urb))
++ {
++
++ fill_isoc_urb(fifo->iso[i].purb, fifo->hfc->dev, fifo->pipe, fifo->iso[i].buffer,
++ num_packets_per_urb, fifo->usb_packet_maxlen, fifo->intervall,
++ complete, &fifo->iso[i]);
++
++ memset(fifo->iso[i].buffer, 0, sizeof(fifo->iso[i].buffer));
++
++ // defining packet delimeters in fifo->buffer
++ for(k = 0; k < num_packets_per_urb; k++)
++ {
++ fifo->iso[i].purb->iso_frame_desc[k].offset = k*packet_size;
++ fifo->iso[i].purb->iso_frame_desc[k].length = packet_size;
++ }
++ }
+ }
+- fifo->buff = NULL;
+- return;
++
++ fifo->bit_line = BITLINE_INF;
++
++ errcode = usb_submit_urb(fifo->iso[i].purb);
++ fifo->active = (errcode >= 0) ? 1 : 0;
++ if(errcode < 0)
++ {
++ printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i.%i \n", errcode, i);
++ };
++
+ }
+- fifo->act_ptr += (urb->transfer_buffer_length - fifo->rx_offset); /* adjust pointer */
+- fill_tx_urb(fifo); /* refill the urb */
+- fifo->hfc->threshold_mask |= fifo->fifo_mask; /* assume threshold reached */
+- if (fifo->buff)
+- fifo->hfc->service_request |= fifo->fifo_mask; /* need to restart */
+-} /* tx_complete */
+
+-/***********************************************/
+-/* receive completion routine for all rx fifos */
+-/***********************************************/
+-static void
+-rx_complete(purb_t urb)
++ // errcode = (usb_submit_urb(fifo->iso[0].purb, GFP_KERNEL));
++ return(fifo->active);
++}
++
++/* stops running iso chain and frees their pending urbs */
++static void stop_isoc_chain(usb_fifo * fifo)
+ {
+- usb_fifo *fifo = (usb_fifo *) urb->context; /* pointer to our fifo */
+- hfcusb_data *hfc = fifo->hfc;
+- usb_fifo *txfifo;
+- __u8 last_state;
+- int i, ii, currcnt, hdlci;
+- struct sk_buff *skb;
+-
+- urb->dev = hfc->dev; /* security init */
+- if ((!fifo->active) || (urb->status)) {
+- hfc->service_request &= ~fifo->fifo_mask; /* no further handling */
+- hfc->active_fifos &= ~fifo->fifo_mask; /* we are inactive */
+- fifo->urb.interval = 0; /* cancel automatic rescheduling */
+- if (fifo->buff) {
+- dev_kfree_skb_any(fifo->buff);
+- fifo->buff = NULL;
++ int i;
++
++ for(i = 0; i < 2; i++)
++ {
++ if(fifo->iso[i].purb)
++ {
++#ifdef VERBOSE_USB_DEBUG
++ printk(KERN_INFO "HFC-USB: Stopping iso chain for fifo %i.%i\n", fifo->fifonum, i);
++#endif
++ usb_unlink_urb(fifo->iso[i].purb);
++ usb_free_urb(fifo->iso[i].purb);
++ fifo->iso[i].purb = NULL;
+ }
+- return;
+ }
++ if (fifo->urb) {
++ usb_unlink_urb(fifo->urb);
++ usb_free_urb(fifo->urb);
++ fifo->urb = NULL;
++ }
++ fifo->active = 0;
++}
+
+- /* first check for any status changes */
+- if ((urb->actual_length < fifo->rx_offset)
+- || (urb->actual_length > fifo->usb_maxlen))
+- return; /* error condition */
+-
+- if (fifo->rx_offset) {
+- hfc->threshold_mask = fifo->buffer[1]; /* update threshold status */
+- fifo->next_complete = fifo->buffer[0] & 1;
+- if ((fifo->fifonum == HFCUSB_D_RX) &&
+- (hfc->led_req != hfc->led_act))
+- queue_control_request(hfc, HFCUSB_P_DATA, hfc->led_req);
+-
+- /* check if rescheduling needed */
+- if ((i =
+- hfc->service_request & hfc->active_fifos & ~hfc->
+- threshold_mask)) {
+- currcnt =
+- usb_get_current_frame_number(hfc->dev);
+- txfifo = hfc->fifos + HFCUSB_B1_TX;
+- ii = 3;
+- while (ii--) {
+- if ((i & txfifo->fifo_mask)
+- && (currcnt != txfifo->framenum)) {
+- hfc->service_request &=
+- ~txfifo->fifo_mask;
+- if (!txfifo->buff)
+- fill_tx_urb(txfifo);
+- if (txfifo->buff)
+- usb_submit_urb(&txfifo->
+- urb);
++// defines how much ISO packets are handled in one URB
++static int iso_packets[8]={ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B,
++ ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D};
++
++/*****************************************************/
++/* transmit completion routine for all ISO tx fifos */
++/*****************************************************/
++static void tx_iso_complete(struct urb *urb)
++{
++ iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context;
++ usb_fifo *fifo = context_iso_urb->owner_fifo;
++ hfcusb_data *hfc = fifo->hfc;
++ int k, tx_offset, num_isoc_packets, sink, len, current_len,errcode,frame_complete,transp_mode,fifon;
++ __u8 threshbit;
++ __u8 threshtable[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
++
++ fifon=fifo->fifonum;
++ tx_offset=0;
++ // very weird error code when using ohci drivers, for now : ignore this error ... (MB)
++ if(urb->status == -EOVERFLOW)
++ {
++ urb->status = 0;
++#ifdef VERBOSE_USB_DEBUG
++ printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN for fifo %i \n",fifon);
++#endif
++ }
++
++ if(fifo->active && !urb->status)
++ {
++ transp_mode=0;
++ if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE;
++
++ threshbit = threshtable[fifon] & hfc->threshold_mask; // is threshold set for our channel?
++ num_isoc_packets=iso_packets[fifon];
++
++ if(fifon >= HFCUSB_D_TX)
++ {
++ sink = (threshbit) ? SINK_DMIN : SINK_DMAX; // how much bit go to the sink for D-channel?
++ }
++ else
++ {
++ sink = (threshbit) ? SINK_MIN : SINK_MAX; // how much bit go to the sink for B-channel?
++ }
++
++ // prepare ISO Urb
++ fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,context_iso_urb->buffer, num_isoc_packets,
++ fifo->usb_packet_maxlen, fifo->intervall, tx_iso_complete, urb->context);
++ memset(context_iso_urb->buffer, 0, sizeof(context_iso_urb->buffer));
++
++ frame_complete=FALSE;
++
++ // Generate Iso Packets
++ for(k = 0; k < num_isoc_packets; ++k)
++ {
++ if(fifo->skbuff)
++ {
++ len = fifo->skbuff->len; // remaining length
++
++ fifo->bit_line -= sink; // we lower data margin every msec
++ current_len = (0 - fifo->bit_line) / 8;
++ if(current_len > 14) current_len = 14; // maximum 15 byte for every ISO packet makes our life easier
++ current_len = (len <= current_len) ? len : current_len;
++ fifo->bit_line += current_len * 8; // how much bit do we put on the line?
++
++ context_iso_urb->buffer[tx_offset] = 0;
++ if(current_len == len)
++ {
++ if(!transp_mode)
++ {
++ context_iso_urb->buffer[tx_offset] = 1; // here frame completion
++ fifo->bit_line += 32; // add 2 byte flags and 16bit CRC at end of ISDN frame
++ }
++ frame_complete = TRUE;
++ }
++
++ // copy bytes from buffer into ISO_URB
++ memcpy(context_iso_urb->buffer+tx_offset+1,fifo->skbuff->data,current_len);
++ skb_pull(fifo->skbuff,current_len);
++
++ // define packet delimeters within the URB buffer
++ urb->iso_frame_desc[k].offset = tx_offset;
++ urb->iso_frame_desc[k].length = current_len + 1;
++
++ tx_offset += (current_len + 1);
++ // printk(KERN_INFO "HFC-USB: fifonum:%d,%d bytes to send, %d bytes ISO packet,bitline:%d,sink:%d,threshbit:%d,threshmask:%x\n",fifon,len,current_len,fifo->bit_line,sink,threshbit,hfc->threshold_mask);
++ if(!transp_mode)
++ {
++ if(fifon==HFCUSB_B1_TX) handle_led(hfc,LED_B1_DATA);
++ if(fifon==HFCUSB_B2_TX) handle_led(hfc,LED_B2_DATA);
++ }
++ }
++ else
++ {
++ // we have no more data - generate 1 byte ISO packets
++ urb->iso_frame_desc[k].offset = tx_offset++;
++
++ urb->iso_frame_desc[k].length = 1;
++ fifo->bit_line -= sink; // we lower data margin every msec
++
++ if(fifo->bit_line < BITLINE_INF)
++ {
++ fifo->bit_line = BITLINE_INF;
++ //printk (KERN_INFO "HFC-USB: BITLINE_INF underrun\n");
+ }
+- txfifo += 2;
+ }
+- }
+
+- /* handle l1 events */
+- if ((fifo->buffer[0] >> 4) != hfc->l1_state) {
+- last_state = hfc->l1_state;
+- hfc->l1_state = fifo->buffer[0] >> 4; /* update status */
+- if (timer_pending(&hfc->t4_timer))
+- del_timer(&hfc->t4_timer);
+- if (((hfc->l1_state == 3) &&
+- ((last_state == 7) ||
+- (last_state == 8))) ||
+- ((timer_pending(&hfc->t3_timer) &&
+- (hfc->l1_state == 8)))) {
+- hfc->t4_timer.expires = jiffies + 2;
+- add_timer(&hfc->t4_timer);
+- } else {
+- if (timer_pending(&hfc->t3_timer)
+- && (hfc->l1_state == 7))
+- del_timer(&hfc->t3_timer); /* no longer needed */
+- test_and_set_bit(HFCUSB_L1_STATECHANGE,
+- &hfc->l1_event);
+- queue_task(&hfc->l1_tq, &tq_immediate);
+- mark_bh(IMMEDIATE_BH);
++ if(frame_complete)
++ {
++ // delete the buffer only once, here or in hfc_usb_l2l1() in a PH_DATA|REQUEST
++ fifo->delete_flg=TRUE;
++
++ fifo->hif->l1l2(fifo->hif,PH_DATA|CONFIRM,(void*)fifo->skbuff->truesize);
++
++ if(fifo->skbuff && fifo->delete_flg)
++ {
++ dev_kfree_skb_any(fifo->skbuff);
++ //printk(KERN_INFO "HFC-USB: skbuff=NULL on fifo:%d\n",fifo->fifonum);
++ fifo->skbuff = NULL;
++ fifo->delete_flg=FALSE;
++ }
++
++ frame_complete=FALSE;
+ }
++ }
++
++ errcode = usb_submit_urb(urb);
++ if(errcode < 0)
++ {
++ printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n", errcode);
++ }
++ }
++ else
++ {
++ if(urb->status)
++ {
++ printk(KERN_INFO "HFC-USB: tx_iso_complete : urb->status %i, fifonum %i\n", urb->status,fifon);
+ }
+ }
+
+- /* check the length for data and move if present */
+- if (fifo->next_complete || (urb->actual_length > fifo->rx_offset)) {
+- i = fifo->buff->len + urb->actual_length - fifo->rx_offset; /* new total length */
+- hdlci = (fifo->transmode) ? 0 : 3;
+- if (i <= (fifo->max_size + hdlci)) {
+- memcpy(fifo->act_ptr,
+- fifo->buffer + fifo->rx_offset,
+- urb->actual_length - fifo->rx_offset);
+- fifo->act_ptr +=
+- (urb->actual_length - fifo->rx_offset);
+- fifo->buff->len +=
+- (urb->actual_length - fifo->rx_offset);
+- } else
+- fifo->buff->len = fifo->max_size + 4; /* mark frame as to long */
+- if (fifo->next_complete && (urb->actual_length < fifo->usb_maxlen)) {
+- /* the frame is complete */
+- fifo->next_complete = 0;
+- if (((!*(fifo->act_ptr - 1)) || fifo->transmode) &&
+- (fifo->buff->len >= (hdlci + 1))
+- && (fifo->buff->len <=
+- (fifo->max_size + hdlci)) &&
+- ((skb = dev_alloc_skb(fifo->max_size + hdlci)) != NULL)) {
+- fifo->buff->len -= hdlci; /* adjust size */
+- switch (fifo->fifonum) {
+- case HFCUSB_D_RX:
+- skb_queue_tail(hfc->regd.
+- drq,
+- fifo->buff);
+- test_and_set_bit
+- (HFCUSB_L1_DRX,
+- &hfc->l1_event);
+- queue_task(&hfc->l1_tq,
+- &tq_immediate);
+- mark_bh(IMMEDIATE_BH);
+- break;
++} /* tx_iso_complete */
+
+- case HFCUSB_B1_RX:
+- if (hfc->regd.brq[0]) {
+- skb_queue_tail
+- (hfc->regd.
+- brq[0],
+- fifo->buff);
+- hfc->regd.
+- bch_l1l2(hfc->
+- regd.
+- arg_hisax,
+- 0,
+- PH_DATA
+- |
+- INDICATION,
+- (void *)
+- fifo->
+- buff);
+- } else
+- dev_kfree_skb_any
+- (fifo->buff);
+- break;
+-
+- case HFCUSB_B2_RX:
+- if (hfc->regd.brq[1]) {
+- skb_queue_tail
+- (hfc->regd.
+- brq[1],
+- fifo->buff);
+- hfc->regd.
+- bch_l1l2(hfc->
+- regd.
+- arg_hisax,
+- 1,
+- PH_DATA
+- |
+- INDICATION,
+- (void
+- *)
+- fifo->
+- buff);
+- } else
+- dev_kfree_skb_any
+- (fifo->buff);
+- break;
++/*****************************************************/
++/* receive completion routine for all ISO tx fifos */
++/*****************************************************/
++static void rx_iso_complete(struct urb *urb)
++{
++ iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context;
++ usb_fifo *fifo = context_iso_urb->owner_fifo;
++ hfcusb_data *hfc = fifo->hfc;
++ int k, len, errcode, offset, num_isoc_packets,fifon;
++ __u8 *buf;
+
+- case HFCUSB_PCM_RX:
+- skb_queue_tail(&hfc->regd.
+- erq,
+- fifo->buff);
+- test_and_set_bit
+- (HFCUSB_L1_ERX,
+- &hfc->l1_event);
+- queue_task(&hfc->l1_tq,
+- &tq_immediate);
+- mark_bh(IMMEDIATE_BH);
+- break;
++ fifon=fifo->fifonum;
++ // very weird error code when using ohci drivers, for now : ignore this error ... (MB)
++ if(urb->status == -EOVERFLOW)
++ {
++ urb->status = 0;
++#ifdef VERBOSE_USB_DEBUG
++ printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN for fifo %i \n",fifon);
++#endif
++ }
+
+- default:
+- dev_kfree_skb_any(fifo->
+- buff);
+- break;
++ if(fifo->active && !urb->status)
++ {
++ num_isoc_packets=iso_packets[fifon];
++
++ // Generate D-Channel Iso Packets
++ for(k = 0; k < num_isoc_packets; ++k)
++ {
++ len=urb->iso_frame_desc[k].actual_length;
++ offset=urb->iso_frame_desc[k].offset;
++ buf=context_iso_urb->buffer+offset;
++
++ if(fifo->last_urblen!=fifo->usb_packet_maxlen)
++ {
++ // the threshold mask is in the 2nd status byte
++ hfc->threshold_mask=buf[1];
++ // the S0 state is in the upper half of the 1st status byte
++ state_handler(hfc,buf[0] >> 4);
++ // if we have more than the 2 status bytes -> collect data
++ if(len>2) collect_rx_frame(fifo,buf+2,len-2,buf[0]&1);
+ }
+- fifo->buff = skb;
+- }
+- fifo->buff->len = 0; /* reset counter */
+- fifo->act_ptr = fifo->buff->data; /* and pointer */
++ else collect_rx_frame(fifo,buf,len,0);
++
++ fifo->last_urblen=len;
++
++ }
++
++ // prepare ISO Urb
++ fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,context_iso_urb->buffer, num_isoc_packets,
++ fifo->usb_packet_maxlen, fifo->intervall, rx_iso_complete, urb->context);
++
++ errcode = usb_submit_urb(urb);
++ if(errcode < 0)
++ {
++ printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n", errcode);
++ }
++ }
++ else
++ {
++ if(urb->status)
++ {
++ printk(KERN_INFO "HFC-USB: rx_iso_complete : urb->status %i, fifonum %i\n", urb->status,fifon);
++ }
++ }
++} /* rx_iso_complete */
++
++
++/*****************************************************/
++/* collect data from interrupt or isochron in */
++/*****************************************************/
++static void collect_rx_frame(usb_fifo *fifo,__u8 *data,int len,int finish)
++{
++ hfcusb_data *hfc = fifo->hfc;
++ int transp_mode,fifon;
++
++ fifon=fifo->fifonum;
++ transp_mode=0;
++ if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE;
++
++ //printk(KERN_INFO "HFC-USB: got %d bytes finish:%d max_size:%d fifo:%d\n",len,finish,fifo->max_size,fifon);
++ if(!fifo->skbuff)
++ {
++ // allocate sk buffer
++ fifo->skbuff=dev_alloc_skb(fifo->max_size + 3);
++ if(!fifo->skbuff)
++ {
++ printk(KERN_INFO "HFC-USB: cannot allocate buffer (dev_alloc_skb) fifo:%d\n",fifon);
++ return;
++ }
++
++ }
++
++ if(len && fifo->skbuff->len+len<fifo->max_size)
++ {
++ memcpy(skb_put(fifo->skbuff,len),data,len);
++ }
++ else printk(KERN_INFO "HCF-USB: got frame exceeded fifo->max_size:%d\n",fifo->max_size);
++
++ // give transparent data up, when 128 byte are available
++ if(transp_mode && fifo->skbuff->len>=128)
++ {
++ fifo->hif->l1l2(fifo->hif,PH_DATA | INDICATION,fifo->skbuff);
++ fifo->skbuff = NULL; // buffer was freed from upper layer
++ return;
++ }
++
++ // we have a complete hdlc packet
++ if(finish)
++ {
++ if(!fifo->skbuff->data[fifo->skbuff->len-1])
++ {
++ skb_trim(fifo->skbuff,fifo->skbuff->len-3); // remove CRC & status
++
++ //printk(KERN_INFO "HFC-USB: got frame %d bytes on fifo:%d\n",fifo->skbuff->len,fifon);
++
++ if(fifon==HFCUSB_PCM_RX) fifo->hif->l1l2(fifo->hif,PH_DATA_E | INDICATION,fifo->skbuff);
++ else fifo->hif->l1l2(fifo->hif,PH_DATA | INDICATION,fifo->skbuff);
++
++ fifo->skbuff = NULL; // buffer was freed from upper layer
++ }
++ else
++ {
++ printk(KERN_INFO "HFC-USB: got frame %d bytes but CRC ERROR!!!\n",fifo->skbuff->len);
++
++ skb_trim(fifo->skbuff,0); // clear whole buffer
++ }
++ }
++
++ // LED flashing only in HDLC mode
++ if(!transp_mode)
++ {
++ if(fifon==HFCUSB_B1_RX) handle_led(hfc,LED_B1_DATA);
++ if(fifon==HFCUSB_B2_RX) handle_led(hfc,LED_B2_DATA);
++ }
++}
++
++/***********************************************/
++/* receive completion routine for all rx fifos */
++/***********************************************/
++static void rx_complete(struct urb *urb)
++{
++ int len;
++ __u8 *buf;
++ usb_fifo *fifo = (usb_fifo *) urb->context; /* pointer to our fifo */
++ hfcusb_data *hfc = fifo->hfc;
++
++ urb->dev = hfc->dev; /* security init */
++
++ if((!fifo->active) || (urb->status)) {
++#ifdef VERBOSE_USB_DEBUG
++ printk(KERN_INFO "HFC-USB: RX-Fifo %i is going down (%i)\n", fifo->fifonum, urb->status);
++#endif
++ fifo->urb->interval = 0; /* cancel automatic rescheduling */
++ if(fifo->skbuff) {
++ dev_kfree_skb_any(fifo->skbuff);
++ fifo->skbuff = NULL;
+ }
++ return;
+ }
+- fifo->rx_offset = (urb->actual_length < fifo->usb_maxlen) ? 2 : 0;
+-} /* rx_complete */
++
++ len=urb->actual_length;
++ buf=fifo->buffer;
++
++ if(fifo->last_urblen!=fifo->usb_packet_maxlen) {
++ // the threshold mask is in the 2nd status byte
++ hfc->threshold_mask=buf[1];
++ // the S0 state is in the upper half of the 1st status byte
++ state_handler(hfc,buf[0] >> 4);
++ // if we have more than the 2 status bytes -> collect data
++ if(len>2) collect_rx_frame(fifo,buf+2,urb->actual_length-2,buf[0]&1);
++ } else
++ collect_rx_frame(fifo,buf,urb->actual_length,0);
++
++ fifo->last_urblen=urb->actual_length;
++
++
++} /* rx_complete */
++
++
+
+ /***************************************************/
+ /* start the interrupt transfer for the given fifo */
+ /***************************************************/
+-static void
+-start_rx_fifo(usb_fifo * fifo)
++static void start_int_fifo(usb_fifo * fifo)
+ {
+- if (fifo->buff)
+- return; /* still active */
+- if (!
+- (fifo->buff =
+- dev_alloc_skb(fifo->max_size + (fifo->transmode ? 0 : 3))))
+- return;
+- fifo->act_ptr = fifo->buff->data;
+- FILL_INT_URB(&fifo->urb, fifo->hfc->dev, fifo->pipe, fifo->buffer,
+- fifo->usb_maxlen, rx_complete, fifo, fifo->intervall);
+- fifo->next_complete = 0;
+- fifo->rx_offset = 2;
+- fifo->active = 1; /* must be marked active */
+- fifo->hfc->active_fifos |= fifo->fifo_mask;
+- if (usb_submit_urb(&fifo->urb)) {
++ int errcode;
++
++#ifdef VERBOSE_USB_DEBUG
++ printk(KERN_INFO "HFC-USB: starting intr IN fifo:%d\n", fifo->fifonum);
++#endif
++ if (!fifo->urb) {
++ fifo->urb = usb_alloc_urb(0);
++ if (!fifo->urb)
++ return;
++ }
++ usb_fill_int_urb(fifo->urb, fifo->hfc->dev, fifo->pipe, fifo->buffer,
++ fifo->usb_packet_maxlen, rx_complete, fifo, fifo->intervall);
++ fifo->active = 1; /* must be marked active */
++ errcode = usb_submit_urb(fifo->urb);
++
++ if(errcode)
++ {
++ printk(KERN_INFO "HFC-USB: submit URB error(start_int_info): status:%i\n", errcode);
+ fifo->active = 0;
+- fifo->hfc->active_fifos &= ~fifo->fifo_mask;
+- dev_kfree_skb_any(fifo->buff);
+- fifo->buff = NULL;
++ fifo->skbuff = NULL;
+ }
+-} /* start_rx_fifo */
++} /* start_int_fifo */
+
+-/***************************************************************/
+-/* control completion routine handling background control cmds */
+-/***************************************************************/
+-static void
+-ctrl_complete(purb_t urb)
++/*****************************/
++/* set the B-channel mode */
++/*****************************/
++static void set_hfcmode(hfcusb_data *hfc,int channel,int mode)
+ {
+- hfcusb_data *hfc = (hfcusb_data *) urb->context;
++ __u8 val,idx_table[2]={0,2};
+
+- urb->dev = hfc->dev;
+- if (hfc->ctrl_cnt) {
+- switch (hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg) {
+- case HFCUSB_FIFO:
+- hfc->ctrl_fifo =
+- hfc->ctrl_buff[hfc->ctrl_out_idx].
+- reg_val;
+- break;
+- case HFCUSB_F_USAGE:
+- if (!hfc->dfifo_fill) {
+- fill_tx_urb(hfc->fifos +
+- HFCUSB_D_TX);
+- if (hfc->fifos[HFCUSB_D_TX].buff)
+- usb_submit_urb(&hfc->
+- fifos
+- [HFCUSB_D_TX].
+- urb);
+- } else {
+- queue_control_request(hfc,
+- HFCUSB_FIFO,
+- HFCUSB_D_TX);
+- queue_control_request(hfc,
+- HFCUSB_F_USAGE,
+- 0);
+- }
+- break;
+- case HFCUSB_SCTRL_R:
+- switch (hfc->ctrl_fifo) {
+- case HFCUSB_B1_RX:
+- if (hfc->bch_enables & 1)
+- start_rx_fifo(hfc->
+- fifos
+- +
+- HFCUSB_B1_RX);
+- break;
+- case HFCUSB_B2_RX:
+- if (hfc->bch_enables & 2)
+- start_rx_fifo(hfc->
+- fifos
+- +
+- HFCUSB_B2_RX);
+- break;
+- }
+- if (hfc->bch_enables & 3)
+- hfc->led_req |= LED_BCH;
+- else
+- hfc->led_req &= ~LED_BCH;
+- break;
+- case HFCUSB_P_DATA:
+- hfc->led_act =
+- hfc->ctrl_buff[hfc->ctrl_out_idx].
+- reg_val;
+- break;
+- }
+- hfc->ctrl_cnt--; /* decrement actual count */
+- if (++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE)
+- hfc->ctrl_out_idx = 0; /* pointer wrap */
+- ctrl_start_transfer(hfc); /* start next transfer */
++#ifdef VERBOSE_ISDN_DEBUG
++ printk (KERN_INFO "HFC-USB: setting channel %d to mode %d\n",channel,mode);
++#endif
++
++ hfc->b_mode[channel]=mode;
++
++ // setup CON_HDLC
++ val=0;
++ if(mode!=L1_MODE_NULL) val=8; // enable fifo?
++ if(mode==L1_MODE_TRANS) val|=2; // set transparent bit
++
++ queue_control_request(hfc,HFCUSB_FIFO,idx_table[channel],1); // set FIFO to transmit register
++ queue_control_request(hfc,HFCUSB_CON_HDLC,val,1);
++ queue_control_request(hfc,HFCUSB_INC_RES_F,2,1); // reset fifo
++
++ queue_control_request(hfc,HFCUSB_FIFO,idx_table[channel]+1,1); // set FIFO to receive register
++ queue_control_request(hfc,HFCUSB_CON_HDLC,val,1);
++ queue_control_request(hfc,HFCUSB_INC_RES_F,2,1); // reset fifo
++
++ val=0x40;
++ if(hfc->b_mode[0]) val|=1;
++ if(hfc->b_mode[1]) val|=2;
++ queue_control_request(hfc,HFCUSB_SCTRL,val,1);
++
++ val=0;
++ if(hfc->b_mode[0]) val|=1;
++ if(hfc->b_mode[1]) val|=2;
++ queue_control_request(hfc,HFCUSB_SCTRL_R,val,1);
++
++ if(mode==L1_MODE_NULL)
++ {
++ if(channel) handle_led(hfc,LED_B2_OFF);
++ else handle_led(hfc,LED_B1_OFF);
+ }
+-} /* ctrl_complete */
++ else
++ {
++ if(channel) handle_led(hfc,LED_B2_ON);
++ else handle_led(hfc,LED_B1_ON);
++ }
++}
+
+-/*****************************************/
+-/* Layer 1 + D channel access from HiSax */
+-/*****************************************/
+-static void
+-hfcusb_l1_access(void *drvarg, int pr, void *arg)
+-{
+- hfcusb_data *hfc = (hfcusb_data *) drvarg;
+-
+- switch (pr) {
+- case (PH_DATA | REQUEST):
+- case (PH_PULL | INDICATION):
+- skb_queue_tail(hfc->regd.dsq,
+- (struct sk_buff *) arg);
+- if (!hfc->fifos[HFCUSB_D_TX].active
+- && !hfc->dfifo_fill) {
+- fill_tx_urb(hfc->fifos + HFCUSB_D_TX);
+- hfc->active_fifos |=
+- hfc->fifos[HFCUSB_D_TX].fifo_mask;
+- usb_submit_urb(&hfc->fifos[HFCUSB_D_TX].
+- urb);
+- }
+- break;
+- case (PH_ACTIVATE | REQUEST):
+- switch (hfc->l1_state) {
+- case 6:
+- case 8:
+- hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
+- (PH_DEACTIVATE |
+- INDICATION), NULL);
++/*
++ --------------------------------------------------------------------------------------
++ from here : hisax_if callback routines :
++ - void hfc_usb_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg) {
+
+- break;
+- case 7:
+- hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
+- (PH_ACTIVATE |
+- INDICATION), NULL);
++ l1 to l2 routines :
++ - static void hfc_usb_l1l2(hfcusb_data * hfc)
+
+- break;
+- default:
+- queue_control_request(hfc, HFCUSB_STATES, 0x60); /* start activation */
+- hfc->t3_timer.expires =
+- jiffies + (HFC_TIMER_T3 * HZ) / 1000;
+- if (!timer_pending(&hfc->t3_timer))
+- add_timer(&hfc->t3_timer);
+- break;
+- }
+- break;
++*/
+
+- case (PH_DEACTIVATE | REQUEST):
+- queue_control_request(hfc, HFCUSB_STATES, 0x40); /* start deactivation */
+- break;
+- default:
+- printk(KERN_INFO "unknown hfcusb l1_access 0x%x\n",
+- pr);
+- break;
+- }
+-} /* hfcusb_l1_access */
+-
+-/*******************************/
+-/* B channel access from HiSax */
+-/*******************************/
+-static void
+-hfcusb_bch_access(void *drvarg, int chan, int pr, void *arg)
+-{
+- hfcusb_data *hfc = (hfcusb_data *) drvarg;
+- usb_fifo *fifo = hfc->fifos + (chan ? HFCUSB_B2_TX : HFCUSB_B1_TX);
+- long flags;
+-
+- switch (pr) {
+- case (PH_DATA | REQUEST):
+- case (PH_PULL | INDICATION):
+- save_flags(flags);
+- cli();
+- if (!fifo->active) {
+- fill_tx_urb(fifo);
+- hfc->active_fifos |= fifo->fifo_mask;
+- usb_submit_urb(&fifo->urb);
+- }
+- restore_flags(flags);
+- break;
+- case (PH_ACTIVATE | REQUEST):
+- if (!((int) arg)) {
+- hfc->bch_enables &= ~(1 << chan);
+- if (fifo->active) {
+- fifo->active = 0;
+- usb_unlink_urb(&fifo->urb);
++void hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg)
++{
++ usb_fifo *fifo = my_hisax_if->priv;
++ hfcusb_data *hfc = fifo->hfc;
++
++ switch (pr) {
++ case PH_ACTIVATE | REQUEST:
++ if(fifo->fifonum==HFCUSB_D_TX)
++ {
++#ifdef VERBOSE_ISDN_DEBUG
++ printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_ACTIVATE | REQUEST\n");
++#endif
++ queue_control_request(hfc, HFCUSB_STATES,0x60,1); /* make activation */
++ hfc->t3_timer.expires = jiffies + (HFC_TIMER_T3 * HZ) / 1000;
++ if(!timer_pending(&hfc->t3_timer)) add_timer(&hfc->t3_timer);
+ }
+- save_flags(flags);
+- cli();
+- queue_control_request(hfc, HFCUSB_FIFO,
+- fifo->fifonum);
+- queue_control_request(hfc,
+- HFCUSB_INC_RES_F, 2);
+- queue_control_request(hfc, HFCUSB_CON_HDLC,
+- 9);
+- queue_control_request(hfc, HFCUSB_SCTRL,
+- 0x40 +
+- hfc->bch_enables);
+- queue_control_request(hfc, HFCUSB_SCTRL_R,
+- hfc->bch_enables);
+- restore_flags(flags);
+- fifo++;
+- if (fifo->active) {
+- fifo->active = 0;
+- usb_unlink_urb(&fifo->urb);
++ else
++ {
++#ifdef VERBOSE_ISDN_DEBUG
++ printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_ACTIVATE | REQUEST\n");
++#endif
++ set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)arg);
++ fifo->hif->l1l2(fifo->hif,PH_ACTIVATE | INDICATION, NULL);
+ }
+- return; /* fifo deactivated */
+- }
+- fifo->transmode = ((int) arg == L1_MODE_TRANS);
+- fifo->max_size =
+- ((fifo->transmode) ? fifo->
+- usb_maxlen : MAX_BCH_SIZE);
+- (fifo + 1)->transmode = fifo->transmode;
+- (fifo + 1)->max_size = fifo->max_size;
+- hfc->bch_enables |= (1 << chan);
+- save_flags(flags);
+- cli();
+- queue_control_request(hfc, HFCUSB_FIFO,
+- fifo->fifonum);
+- queue_control_request(hfc, HFCUSB_CON_HDLC,
+- ((!fifo->
+- transmode) ? 9 : 11));
+- queue_control_request(hfc, HFCUSB_INC_RES_F, 2);
+- queue_control_request(hfc, HFCUSB_SCTRL,
+- 0x40 + hfc->bch_enables);
+- if ((int) arg == L1_MODE_HDLC)
+- queue_control_request(hfc, HFCUSB_CON_HDLC,
+- 8);
+- queue_control_request(hfc, HFCUSB_FIFO,
+- fifo->fifonum + 1);
+- queue_control_request(hfc, HFCUSB_CON_HDLC,
+- ((!fifo->
+- transmode) ? 8 : 10));
+- queue_control_request(hfc, HFCUSB_INC_RES_F, 2);
+- queue_control_request(hfc, HFCUSB_SCTRL_R,
+- hfc->bch_enables);
+- restore_flags(flags);
+-
+- break;
+-
+- default:
+- printk(KERN_INFO
+- "unknown hfcusb bch_access chan %d 0x%x\n",
+- chan, pr);
+- break;
+- }
+-} /* hfcusb_bch_access */
++ break;
++ case PH_DEACTIVATE | REQUEST:
++ if(fifo->fifonum==HFCUSB_D_TX)
++ {
++#ifdef VERBOSE_ISDN_DEBUG
++ printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DEACTIVATE | REQUEST\n");
++#endif
++ printk (KERN_INFO "HFC-USB: ISDN TE device should not deativate...\n");
++ }
++ else
++ {
++#ifdef VERBOSE_ISDN_DEBUG
++ printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DEACTIVATE | REQUEST\n");
++#endif
++ set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)L1_MODE_NULL);
++ fifo->hif->l1l2(fifo->hif,PH_DEACTIVATE | INDICATION, NULL);
++ }
++ break;
++ case PH_DATA | REQUEST:
++ if(fifo->skbuff && fifo->delete_flg)
++ {
++ dev_kfree_skb_any(fifo->skbuff);
++ //printk(KERN_INFO "skbuff=NULL on fifo:%d\n",fifo->fifonum);
++ fifo->skbuff = NULL;
++ fifo->delete_flg=FALSE;
++ }
++
++ fifo->skbuff=arg; // we have a new buffer
++
++ //if(fifo->fifonum==HFCUSB_D_TX) printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DATA | REQUEST\n");
++ //else printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DATA | REQUEST\n");
++ break;
++ default:
++ printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1: unkown state : %#x\n", pr);
++ break;
++ }
++}
++
++// valid configurations
++#define CNF_4INT3ISO 1 // 4 INT IN, 3 ISO OUT
++#define CNF_3INT3ISO 2 // 3 INT IN, 3 ISO OUT
++#define CNF_4ISO3ISO 3 // 4 ISO IN, 3 ISO OUT
++#define CNF_3ISO3ISO 4 // 3 ISO IN, 3 ISO OUT
++
++
++/*
++ --------------------------------------------------------------------------------------
++ From here on USB initialization and deactivation related routines are implemented :
++
++ - hfc_usb_init :
++ is the main Entry Point for the USB Subsystem when the device get plugged
++ in. This function calls usb_register with usb_driver as parameter.
++ Here, further entry points for probing (hfc_usb_probe) and disconnecting
++ the device (hfc_usb_disconnect) are published, as the id_table
++
++ - hfc_usb_probe
++ this function is called by the usb subsystem, and steps through the alternate
++ settings of the currently plugged in device to detect all Endpoints needed to
++ run an ISDN TA.
++ Needed EndPoints are
++ 3 (+1) IntIn EndPoints (D-in, E-in, B1-in, B2-in, (E-in)) or
++ 3 (+1) Isochron In Endpoints (D-out, B1-out, B2-out) and 3 IsoOut Endpoints
++ The currently used transfer mode of on the Out-Endpoints will be stored in
++ hfc->usb_transfer_mode and is either USB_INT or USB_ISO
++ When a valid alternate setting could be found, the usb_init (see blow)
++ function is called
++
++ - usb_init
++ Here, the HFC_USB Chip itself gets initialized and the USB framework to send/receive
++ Data to/from the several EndPoints are initialized:
++ The E- and D-Channel Int-In chain gets started
++ The IsoChain for the Iso-Out traffic get started
++
++ - hfc_usb_disconnect
++ this function is called by the usb subsystem and has to free all resources
++ and stop all usb traffic to allow a proper hotplugging disconnect.
++
++*/
+
+ /***************************************************************************/
+ /* usb_init is called once when a new matching device is detected to setup */
+-/* main parmeters. It registers the driver at the main hisax module. */
++/* main parameters. It registers the driver at the main hisax module. */
+ /* on success 0 is returned. */
+ /***************************************************************************/
+-static int
+-usb_init(hfcusb_data * hfc)
++static int usb_init(hfcusb_data * hfc)
+ {
+ usb_fifo *fifo;
+- int i;
++ int i, err;
+ u_char b;
+-
++ struct hisax_b_if *p_b_if[2];
++
+ /* check the chip id */
+- if ((Read_hfc(hfc, HFCUSB_CHIP_ID, &b) != 1) ||
+- (b != HFCUSB_CHIPID)) {
++ printk(KERN_INFO "HFCUSB_CHIP_ID begin\n");
++ if (read_usb(hfc, HFCUSB_CHIP_ID, &b) != 1) {
++ printk(KERN_INFO "HFC-USB: cannot read chip id\n");
++ return(1);
++ }
++ printk(KERN_INFO "HFCUSB_CHIP_ID %x\n", b);
++ if (b != HFCUSB_CHIPID) {
+ printk(KERN_INFO "HFC-USB: Invalid chip id 0x%02x\n", b);
+- return (1);
++ return(1);
+ }
+
+ /* first set the needed config, interface and alternate */
+- usb_set_configuration(hfc->dev, 1);
+- usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used);
++ printk(KERN_INFO "usb_init 1\n");
++// usb_set_configuration(hfc->dev, 1);
++ printk(KERN_INFO "usb_init 2\n");
++ err = usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used);
++ printk(KERN_INFO "usb_init usb_set_interface return %d\n", err);
++ /* now we initialize the chip */
++ write_usb(hfc, HFCUSB_CIRM, 8); // do reset
++ write_usb(hfc, HFCUSB_CIRM, 0x10); // aux = output, reset off
+
+- /* init the led state request */
+- hfc->led_req = LED_DRIVER;
++ // set USB_SIZE to match the the wMaxPacketSize for INT or BULK transfers
++ write_usb(hfc, HFCUSB_USB_SIZE,(hfc->packet_size/8) | ((hfc->packet_size/8) << 4));
+
+- /* now we initialise the chip */
+- Write_hfc(hfc, HFCUSB_CIRM, 0x10); /* aux = output, reset off */
+- Write_hfc(hfc, HFCUSB_P_DATA, 0); /* leds = off */
+- Write_hfc(hfc, HFCUSB_USB_SIZE,
+- (hfc->fifos[HFCUSB_B1_TX].usb_maxlen >> 3) |
+- ((hfc->fifos[HFCUSB_B1_RX].usb_maxlen >> 3) << 4));
++ // set USB_SIZE_I to match the the wMaxPacketSize for ISO transfers
++ write_usb(hfc, HFCUSB_USB_SIZE_I, hfc->iso_packet_size);
+
+ /* enable PCM/GCI master mode */
+- Write_hfc(hfc, HFCUSB_MST_MODE1, 0); /* set default values */
+- Write_hfc(hfc, HFCUSB_MST_MODE0, 1); /* enable master mode */
++ write_usb(hfc, HFCUSB_MST_MODE1, 0); /* set default values */
++ write_usb(hfc, HFCUSB_MST_MODE0, 1); /* enable master mode */
+
+ /* init the fifos */
+- Write_hfc(hfc, HFCUSB_F_THRES, (HFCUSB_TX_THRESHOLD >> 3) |
+- ((HFCUSB_RX_THRESHOLD >> 3) << 4));
++ write_usb(hfc, HFCUSB_F_THRES, (HFCUSB_TX_THRESHOLD/8) |((HFCUSB_RX_THRESHOLD/8) << 4));
+
+- for (i = 0, fifo = hfc->fifos + i; i < HFCUSB_NUM_FIFOS;
+- i++, fifo++) {
+- Write_hfc(hfc, HFCUSB_FIFO, i); /* select the desired fifo */
+-
+- fifo->transmode = 0; /* hdlc mode selected */
+- fifo->buff = NULL; /* init buffer pointer */
+- fifo->max_size =
+- (i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN;
+- Write_hfc(hfc, HFCUSB_HDLC_PAR, ((i <= HFCUSB_B2_RX) ? 0 : 2)); /* data length */
+- Write_hfc(hfc, HFCUSB_CON_HDLC, ((i & 1) ? 0x08 : 0x09)); /* rx hdlc, tx fill 1 */
+- Write_hfc(hfc, HFCUSB_INC_RES_F, 2); /* reset the fifo */
+- }
+-
+- Write_hfc(hfc, HFCUSB_CLKDEL, 0x0f); /* clock delay value */
+- Write_hfc(hfc, HFCUSB_STATES, 3 | 0x10); /* set deactivated mode */
+- Write_hfc(hfc, HFCUSB_STATES, 3); /* enable state machine */
++ fifo = hfc->fifos;
++ for(i = 0; i < HFCUSB_NUM_FIFOS; i++)
++ {
++ write_usb(hfc, HFCUSB_FIFO, i); /* select the desired fifo */
++ fifo[i].skbuff = NULL; /* init buffer pointer */
++ fifo[i].max_size = (i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN;
++ fifo[i].last_urblen=0;
++ write_usb(hfc, HFCUSB_HDLC_PAR, ((i <= HFCUSB_B2_RX) ? 0 : 2)); // set 2 bit for D- & E-channel
++ write_usb(hfc, HFCUSB_CON_HDLC, ((i==HFCUSB_D_TX) ? 0x09 : 0x08)); // rx hdlc, enable IFF for D-channel
++ write_usb(hfc, HFCUSB_INC_RES_F, 2); /* reset the fifo */
++ }
+
+- Write_hfc(hfc, HFCUSB_SCTRL_R, 0); /* disable both B receivers */
+- Write_hfc(hfc, HFCUSB_SCTRL, 0x40); /* disable B transmitters + cap mode */
++ write_usb(hfc, HFCUSB_CLKDEL, 0x0f); /* clock delay value */
++ write_usb(hfc, HFCUSB_STATES, 3 | 0x10); /* set deactivated mode */
++ write_usb(hfc, HFCUSB_STATES, 3); /* enable state machine */
++
++ write_usb(hfc, HFCUSB_SCTRL_R, 0); /* disable both B receivers */
++ write_usb(hfc, HFCUSB_SCTRL, 0x40); /* disable B transmitters + capacitive mode */
++
++ // set both B-channel to not connected
++ hfc->b_mode[0]=L1_MODE_NULL;
++ hfc->b_mode[1]=L1_MODE_NULL;
++
++ hfc->l1_activated=FALSE;
++ hfc->led_state=0;
++ hfc->led_new_data=0;
+
+- /* init the l1 timer */
++ /* init the t3 timer */
+ init_timer(&hfc->t3_timer);
+ hfc->t3_timer.data = (long) hfc;
+- hfc->t3_timer.function = (void *) l1_timer_expire;
++ hfc->t3_timer.function = (void *) l1_timer_expire_t3;
++ /* init the t4 timer */
++ init_timer(&hfc->t4_timer);
+ hfc->t4_timer.data = (long) hfc;
+- hfc->t4_timer.function = (void *) l1_timer_expire;
+- hfc->l1_tq.routine = (void *) (void *) usb_l1d_bh;
+- hfc->l1_tq.sync = 0;
+- hfc->l1_tq.data = hfc;
+-
+- /* init the background control machinery */
+- hfc->ctrl_read.requesttype = 0xc0;
+- hfc->ctrl_read.request = 1;
+- hfc->ctrl_read.length = 1;
+- hfc->ctrl_write.requesttype = 0x40;
+- hfc->ctrl_write.request = 0;
+- hfc->ctrl_write.length = 0;
+- FILL_CONTROL_URB(&hfc->ctrl_urb, hfc->dev, hfc->ctrl_out_pipe,
+- (u_char *) & hfc->ctrl_write, NULL, 0,
+- ctrl_complete, hfc);
+-
+- /* init the TX-urbs */
+- fifo = hfc->fifos + HFCUSB_D_TX;
+- FILL_BULK_URB(&fifo->urb, hfc->dev, fifo->pipe,
+- (u_char *) fifo->buffer, 0, tx_complete, fifo);
+- fifo = hfc->fifos + HFCUSB_B1_TX;
+- FILL_BULK_URB(&fifo->urb, hfc->dev, fifo->pipe,
+- (u_char *) fifo->buffer, 0, tx_complete, fifo);
+- fifo = hfc->fifos + HFCUSB_B2_TX;
+- FILL_BULK_URB(&fifo->urb, hfc->dev, fifo->pipe,
+- (u_char *) fifo->buffer, 0, tx_complete, fifo);
+-
+- /* init the E-buffer */
+- skb_queue_head_init(&hfc->regd.erq);
+-
+- /* now register ourself at hisax */
+- hfc->regd.version = HISAX_LOAD_VERSION; /* set our version */
+- hfc->regd.cmd = HISAX_LOAD_REGISTER; /* register command */
+- hfc->regd.argl1 = (void *) hfc; /* argument for our local routine */
+- hfc->regd.dch_l2l1 = hfcusb_l1_access;
+- hfc->regd.bch_l2l1 = hfcusb_bch_access;
+- hfc->regd.drvname = "hfc_usb";
+- if (hisax_register_hfcusb(&hfc->regd)) {
+- printk(KERN_INFO "HFC-USB failed to register at hisax\n");
+- Write_hfc(hfc, HFCUSB_CIRM, 0x08); /* aux = input, reset on */
+- return (1);
+- }
+-
+- /* startup the D- and E-channel fifos */
+- start_rx_fifo(hfc->fifos + HFCUSB_D_RX); /* D-fifo */
+- if (hfc->fifos[HFCUSB_PCM_RX].pipe)
+- start_rx_fifo(hfc->fifos + HFCUSB_PCM_RX); /* E-fifo */
++ hfc->t4_timer.function = (void *) l1_timer_expire_t4;
++ /* init the led timer */
++ init_timer(&hfc->led_timer);
++ hfc->led_timer.data = (long) hfc;
++ hfc->led_timer.function = (void *) led_timer;
++ // trigger 4 hz led timer
++ hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
++ if(!timer_pending(&hfc->led_timer)) add_timer(&hfc->led_timer);
++
++ // init the background machinery for control requests
++ hfc->ctrl_read.bRequestType = 0xc0;
++ hfc->ctrl_read.bRequest = 1;
++ hfc->ctrl_read.wLength = 1;
++ hfc->ctrl_write.bRequestType = 0x40;
++ hfc->ctrl_write.bRequest = 0;
++ hfc->ctrl_write.wLength = 0;
++ usb_fill_control_urb(hfc->ctrl_urb, hfc->dev, hfc->ctrl_out_pipe,(u_char *) & hfc->ctrl_write, NULL, 0, ctrl_complete, hfc);
++
++ /* Init All Fifos */
++ for(i = 0; i < HFCUSB_NUM_FIFOS; i++)
++ {
++ hfc->fifos[i].iso[0].purb = NULL;
++ hfc->fifos[i].iso[1].purb = NULL;
++ hfc->fifos[i].active = 0;
++ }
++
++ // register like Germaschewski :
++ hfc->d_if.owner = THIS_MODULE;
++ hfc->d_if.ifc.priv = &hfc->fifos[HFCUSB_D_TX];
++ hfc->d_if.ifc.l2l1 = hfc_usb_l2l1;
++
++ for (i=0; i<2; i++)
++ {
++ hfc->b_if[i].ifc.priv = &hfc->fifos[HFCUSB_B1_TX+i*2];
++ hfc->b_if[i].ifc.l2l1 = hfc_usb_l2l1;
++ p_b_if[i] = &hfc->b_if[i];
++ }
++
++ hfc->protocol = 2; /* default EURO ISDN, should be a module_param */
++ hisax_register(&hfc->d_if, p_b_if, "hfc_usb", hfc->protocol);
++
++ for (i=0; i<4; i++)
++ hfc->fifos[i].hif=&p_b_if[i/2]->ifc;
++ for (i=4; i<8; i++)
++ hfc->fifos[i].hif=&hfc->d_if.ifc;
++
++ // 3 (+1) INT IN + 3 ISO OUT
++ if(hfc->cfg_used == CNF_3INT3ISO || hfc->cfg_used == CNF_4INT3ISO)
++ {
++ start_int_fifo(hfc->fifos + HFCUSB_D_RX); // Int IN D-fifo
++ if(hfc->fifos[HFCUSB_PCM_RX].pipe) start_int_fifo(hfc->fifos + HFCUSB_PCM_RX); // E-fifo
++ start_int_fifo(hfc->fifos + HFCUSB_B1_RX); // Int IN B1-fifo
++ start_int_fifo(hfc->fifos + HFCUSB_B2_RX); // Int IN B2-fifo
++ }
++
++ // 3 (+1) ISO IN + 3 ISO OUT
++ if(hfc->cfg_used==CNF_3ISO3ISO || hfc->cfg_used==CNF_4ISO3ISO)
++ {
++ start_isoc_chain(hfc->fifos + HFCUSB_D_RX, ISOC_PACKETS_D, rx_iso_complete,16);
++ if(hfc->fifos[HFCUSB_PCM_RX].pipe) start_isoc_chain(hfc->fifos + HFCUSB_PCM_RX, ISOC_PACKETS_D, rx_iso_complete,16);
++ start_isoc_chain(hfc->fifos + HFCUSB_B1_RX, ISOC_PACKETS_B, rx_iso_complete,16);
++ start_isoc_chain(hfc->fifos + HFCUSB_B2_RX, ISOC_PACKETS_B, rx_iso_complete,16);
++ }
++
++ start_isoc_chain(hfc->fifos + HFCUSB_D_TX, ISOC_PACKETS_D, tx_iso_complete,1);
++ start_isoc_chain(hfc->fifos + HFCUSB_B1_TX, ISOC_PACKETS_B, tx_iso_complete,1);
++ start_isoc_chain(hfc->fifos + HFCUSB_B2_TX, ISOC_PACKETS_B, tx_iso_complete,1);
++
++ handle_led(hfc,LED_POWER_ON);
++
++ return(0);
++} /* usb_init */
++
++
++/****************************************/
++/* data defining the devices to be used */
++/****************************************/
++// static __devinitdata const struct usb_device_id hfc_usb_idtab[3] = {
++static struct usb_device_id hfc_usb_idtab[] = {
++ {USB_DEVICE(0x7b0, 0x0007)}, /* Billion USB TA 2 */
++ {USB_DEVICE(0x742, 0x2008)}, /* Stollmann USB TA */
++ {USB_DEVICE(0x959, 0x2bd0)}, /* Colognechip USB eval TA */
++ {USB_DEVICE(0x8e3, 0x0301)}, /* OliTec ISDN USB */
++ {USB_DEVICE(0x675, 0x1688)}, /* DrayTec ISDN USB */
++ {USB_DEVICE(0x7fa, 0x0846)}, /* Bewan ISDN USB TA */
++ {} /* end with an all-zeroes entry */
++};
++
++MODULE_AUTHOR("Peter Sprenger (sprenger@moving-byters.de)/Martin Bachem (info@colognechip.com)");
++MODULE_DESCRIPTION("HFC I4L USB driver");
++MODULE_DEVICE_TABLE(usb, hfc_usb_idtab);
++MODULE_LICENSE("GPL");
++
++#define EP_NUL 1 // Endpoint at this position not allowed
++#define EP_NOP 2 // all type of endpoints allowed at this position
++#define EP_ISO 3 // Isochron endpoint mandatory at this position
++#define EP_BLK 4 // Bulk endpoint mandatory at this position
++#define EP_INT 5 // Interrupt endpoint mandatory at this position
++
++// this array represents all endpoints possible in the HCF-USB
++// the last 2 entries are the configuration number and the minimum interval for Interrupt endpoints
++int validconf[][18]=
++{
++ // INT in, ISO out config
++ {EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NOP,EP_INT,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_4INT3ISO,2},
++ {EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_3INT3ISO,2},
++ // ISO in, ISO out config
++ {EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NOP,EP_ISO,CNF_4ISO3ISO,2},
++ {EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NUL,EP_NUL,CNF_3ISO3ISO,2},
++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // EOL element
++};
++
++// string description of chosen config
++char *conf_str[]=
++{
++ "4 Interrupt IN + 3 Isochron OUT",
++ "3 Interrupt IN + 3 Isochron OUT",
++ "4 Isochron IN + 3 Isochron OUT",
++ "3 Isochron IN + 3 Isochron OUT"
++};
+
+- return (0);
+-} /* usb_init */
+
+ /*************************************************/
+ /* function called to probe a new plugged device */
+ /*************************************************/
+-static void *
+-hfc_usb_probe(struct usb_device *dev, unsigned int interface
+-#ifdef COMPAT_HAS_USB_IDTAB
+- , const struct usb_device_id *id_table)
+-#else
+- )
+-#endif
++//static int hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
++static void* hfc_usb_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)
+ {
++ //struct usb_device *dev= interface_to_usbdev(intf);
++ struct usb_interface* intf = dev->actconfig->interface + ifnum;
+ hfcusb_data *context;
+- struct usb_interface *ifp = dev->actconfig->interface + interface;
+- struct usb_interface_descriptor *ifdp =
+- ifp->altsetting + ifp->act_altsetting;
+- struct usb_endpoint_descriptor *epd;
+- int i, idx, ep_msk;
+-
+-#ifdef COMPAT_HAS_USB_IDTAB
+- if (id_table && (dev->descriptor.idVendor == id_table->idVendor) &&
+- (dev->descriptor.idProduct == id_table->idProduct) &&
+-#else
+- if ((((dev->descriptor.idVendor == 0x959) &&
+- (dev->descriptor.idProduct == 0x2bd0)) ||
+- ((dev->descriptor.idVendor == 0x7b0) &&
+- (dev->descriptor.idProduct == 0x0006))) &&
+-#endif
+- (ifdp->bNumEndpoints >= 6) && (ifdp->bNumEndpoints <= 16)) {
+- if (!(context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL))) {
+- return (NULL); /* got no mem */
+- };
+- memset(context, 0, sizeof(hfcusb_data)); /* clear the structure */
+- i = ifdp->bNumEndpoints; /* get number of endpoints */
+- ep_msk = 0; /* none found */
+- epd = ifdp->endpoint; /* first endpoint descriptor */
+- while (i-- && ((ep_msk & 0xcf) != 0xcf)) {
+-
+- idx = (((epd->bEndpointAddress & 0x7f) - 1) << 1); /* get endpoint base */
+- if (idx < 7) {
+- switch (epd->bmAttributes) {
+- case USB_ENDPOINT_XFER_INT:
+- if (!
+- (epd->
+- bEndpointAddress &
+- 0x80))
+- break; /* only interrupt in allowed */
+- idx++; /* input index is odd */
+- context->fifos[idx].pipe =
+- usb_rcvintpipe(dev,
+- epd->
+- bEndpointAddress);
+- break;
+-
+- case USB_ENDPOINT_XFER_BULK:
+- if (epd->
+- bEndpointAddress &
+- 0x80)
+- break; /* only bulk out allowed */
+- context->fifos[idx].pipe =
+- usb_sndbulkpipe(dev,
+- epd->
+- bEndpointAddress);
+- break;
+- default:
+- context->fifos[idx].pipe = 0; /* reset data */
+- } /* switch attribute */
+-
+- if (context->fifos[idx].pipe) {
+- context->fifos[idx].fifonum = idx;
+- context->fifos[idx].fifo_mask =
+- 1 << idx;
+- context->fifos[idx].hfc = context;
+- context->fifos[idx].usb_maxlen =
+- epd->wMaxPacketSize;
+- context->fifos[idx].intervall =
+- epd->bInterval;
+- ep_msk |= (1 << idx);
+- } else
+- ep_msk &= ~(1 << idx);
+- } /* idx < 7 */
+- epd++;
+- }
++ //struct usb_host_interface *iface = intf->cur_altsetting;
++ //struct usb_host_interface *iface_used = NULL;
++ //struct usb_host_endpoint *ep;
++ struct usb_endpoint_descriptor* ep;
++ //int ifnum = iface->desc.bInterfaceNumber;
++ struct usb_interface_descriptor* intfdesc = intf->altsetting + intf->act_altsetting;
++ struct usb_interface_descriptor* intfdesc_used = NULL;
++ int i, idx, alt_idx, probe_alt_setting, vend_idx, cfg_used, *vcf, attr, cfg_found, cidx, ep_addr;
++ int cmptbl[16],small_match,iso_packet_size,packet_size,alt_used=0;
++
++// usb_show_device(dev);
++// usb_show_device_descriptor(&dev->descriptor);
++// usb_show_interface_descriptor(&iface->desc);
++ vend_idx=0xffff;
++ for(i=0;vdata[i].vendor;i++)
++ {
++ if(dev->descriptor.idVendor==vdata[i].vendor && dev->descriptor.idProduct==vdata[i].prod_id) vend_idx=i;
++ }
++
+
+- if ((ep_msk & 0x3f) != 0x3f) {
+- kfree(context);
+- return (NULL);
+- }
+- MOD_INC_USE_COUNT; /* lock our module */
+- context->dev = dev; /* save device */
+- context->if_used = interface; /* save used interface */
+- context->alt_used = ifp->act_altsetting; /* and alternate config */
+- context->ctrl_paksize = dev->descriptor.bMaxPacketSize0; /* control size */
+-
+- /* create the control pipes needed for register access */
+- context->ctrl_in_pipe = usb_rcvctrlpipe(context->dev, 0);
+- context->ctrl_out_pipe = usb_sndctrlpipe(context->dev, 0);
+-
+- /* init the chip and register the driver */
+- if (usb_init(context)) {
+- kfree(context);
+- MOD_DEC_USE_COUNT;
+- return (NULL);
+- }
++#ifdef VERBOSE_USB_DEBUG
++ printk(KERN_INFO "HFC-USB: probing interface(%d) actalt(%d)\n",
++ ifnum, intfdesc->bAlternateSetting);
++ /* printk(KERN_INFO "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n",
++ ifnum, intfdesc->bAlternateSetting, intf->driver->minor); */
++#endif
+
+- printk(KERN_INFO
+- "HFC-USB: New device if=%d alt=%d registered\n",
+- context->if_used, context->alt_used);
+- return (context);
+- }
++ if (vend_idx != 0xffff) {
++#ifdef VERBOSE_USB_DEBUG
++ printk(KERN_INFO "HFC-USB: found vendor idx:%d name:%s\n",vend_idx,vdata[vend_idx].vend_name);
++#endif
++ /* if vendor and product ID is OK, start probing a matching alternate setting ... */
++ alt_idx = 0;
++ small_match=0xffff;
++ // default settings
++ iso_packet_size=16;
++ packet_size=64;
++
++ while (alt_idx < intf->num_altsetting) {
++ //iface = intf->altsetting + alt_idx;
++ intfdesc = intf->altsetting + alt_idx;
++ probe_alt_setting = intfdesc->bAlternateSetting;
++ cfg_used=0;
+
+- return (NULL); /* no matching entry */
+-} /* hfc_usb_probe */
++#ifdef VERBOSE_USB_DEBUG
++ printk(KERN_INFO "HFC-USB: test alt_setting %d\n", probe_alt_setting);
++#endif
++ // check for config EOL element
++ while (validconf[cfg_used][0]) {
++ cfg_found=TRUE;
++ vcf=validconf[cfg_used];
++ ep = intfdesc->endpoint; /* first endpoint descriptor */
++
++#ifdef VERBOSE_USB_DEBUG
++ printk(KERN_INFO "HFC-USB: (if=%d alt=%d cfg_used=%d)\n",
++ ifnum, probe_alt_setting, cfg_used);
++#endif
++ // copy table
++ memcpy(cmptbl,vcf,16*sizeof(int));
++
++ // check for all endpoints in this alternate setting
++ for (i=0; i < intfdesc->bNumEndpoints; i++) {
++ ep_addr = ep->bEndpointAddress;
++ idx = ((ep_addr & 0x7f)-1)*2; /* get endpoint base */
++ if (ep_addr & 0x80)
++ idx++;
++ attr = ep->bmAttributes;
++
++ if (cmptbl[idx] == EP_NUL) {
++ printk(KERN_INFO "HFC-USB: cfg_found=FALSE in idx:%d attr:%d cmptbl[%d]:%d\n",
++ idx, attr, idx, cmptbl[idx]);
++ cfg_found = FALSE;
++ }
++
++ if (attr == USB_ENDPOINT_XFER_INT && cmptbl[idx] == EP_INT)
++ cmptbl[idx] = EP_NUL;
++ if (attr == USB_ENDPOINT_XFER_BULK && cmptbl[idx] == EP_BLK)
++ cmptbl[idx] = EP_NUL;
++ if (attr == USB_ENDPOINT_XFER_ISOC && cmptbl[idx] == EP_ISO)
++ cmptbl[idx] = EP_NUL;
++
++ // check if all INT endpoints match minimum interval
++ if (attr == USB_ENDPOINT_XFER_INT && ep->bInterval < vcf[17]) {
++#ifdef VERBOSE_USB_DEBUG
++ if (cfg_found)
++ printk(KERN_INFO "HFC-USB: Interrupt Endpoint interval < %d found - skipping config\n",
++ vcf[17]);
++#endif
++ cfg_found = FALSE;
++ }
++
++ ep++;
++ }
++
++ for (i = 0; i < 16; i++) {
++ // printk(KERN_INFO "HFC-USB: cmptbl[%d]:%d\n", i, cmptbl[i]);
++
++ // all entries must be EP_NOP or EP_NUL for a valid config
++ if (cmptbl[i] != EP_NOP && cmptbl[i] != EP_NUL)
++ cfg_found = FALSE;
++ }
++
++ // we check for smallest match, to provide configuration priority
++ // configurations with smaller index have higher priority
++ if (cfg_found) {
++ if (cfg_used < small_match) {
++ small_match = cfg_used;
++ alt_used = probe_alt_setting;
++ //iface_used = iface;
++ intfdesc_used = intfdesc;
++ }
++#ifdef VERBOSE_USB_DEBUG
++ printk(KERN_INFO "HFC-USB: small_match=%x %x\n", small_match, alt_used);
++#endif
++ }
++
++ cfg_used++;
++ }
++
++ alt_idx++;
++ } /* (alt_idx < intf->num_altsetting) */
++#ifdef VERBOSE_USB_DEBUG
++ printk(KERN_INFO "HFC-USB: final small_match=%x alt_used=%x\n",small_match, alt_used);
++#endif
++ // yiipiee, we found a valid config
++ if (small_match != 0xffff) {
++ //iface = iface_used;
++ intfdesc = intfdesc_used;
++
++ if (!(context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL)))
++ return(NULL); /* got no mem */
++ memset(context, 0, sizeof(hfcusb_data)); /* clear the structure */
++
++ ep = intfdesc->endpoint; /* first endpoint descriptor */
++ vcf = validconf[small_match];
++
++ for (i = 0; i < intfdesc->bNumEndpoints; i++) {
++ ep_addr = ep->bEndpointAddress;
++ idx = ((ep_addr & 0x7f)-1)*2; /* get endpoint base */
++ if (ep_addr & 0x80)
++ idx++;
++ cidx = idx & 7;
++ attr = ep->bmAttributes;
++
++ // only initialize used endpoints
++ if (vcf[idx] != EP_NOP && vcf[idx] != EP_NUL) {
++ switch (attr) {
++ case USB_ENDPOINT_XFER_INT:
++ context->fifos[cidx].pipe = usb_rcvintpipe(dev, ep->bEndpointAddress);
++ context->fifos[cidx].usb_transfer_mode = USB_INT;
++ packet_size = ep->wMaxPacketSize; // remember max packet size
++#ifdef VERBOSE_USB_DEBUG
++ printk (KERN_INFO "HFC-USB: Interrupt-In Endpoint found %d ms(idx:%d cidx:%d)!\n",
++ ep->bInterval, idx, cidx);
++#endif
++ break;
++ case USB_ENDPOINT_XFER_BULK:
++ if (ep_addr & 0x80)
++ context->fifos[cidx].pipe = usb_rcvbulkpipe(dev, ep->bEndpointAddress);
++ else
++ context->fifos[cidx].pipe = usb_sndbulkpipe(dev, ep->bEndpointAddress);
++ context->fifos[cidx].usb_transfer_mode = USB_BULK;
++ packet_size = ep->wMaxPacketSize; // remember max packet size
++#ifdef VERBOSE_USB_DEBUG
++ printk (KERN_INFO "HFC-USB: Bulk Endpoint found (idx:%d cidx:%d)!\n",
++ idx, cidx);
++#endif
++ break;
++ case USB_ENDPOINT_XFER_ISOC:
++ if (ep_addr & 0x80)
++ context->fifos[cidx].pipe = usb_rcvisocpipe(dev, ep->bEndpointAddress);
++ else
++ context->fifos[cidx].pipe = usb_sndisocpipe(dev, ep->bEndpointAddress);
++ context->fifos[cidx].usb_transfer_mode = USB_ISOC;
++ iso_packet_size = ep->wMaxPacketSize; // remember max packet size
++#ifdef VERBOSE_USB_DEBUG
++ printk (KERN_INFO "HFC-USB: ISO Endpoint found (idx:%d cidx:%d)!\n",
++ idx, cidx);
++#endif
++ break;
++ default:
++ context->fifos[cidx].pipe = 0; /* reset data */
++ } /* switch attribute */
++
++ if (context->fifos[cidx].pipe) {
++ context->fifos[cidx].fifonum = cidx;
++ context->fifos[cidx].hfc = context;
++ context->fifos[cidx].usb_packet_maxlen = ep->wMaxPacketSize;
++ context->fifos[cidx].intervall = ep->bInterval;
++ context->fifos[cidx].skbuff = NULL;
++#ifdef VERBOSE_USB_DEBUG
++ printk (KERN_INFO "HFC-USB: fifo%d pktlen %d interval %d\n",
++ context->fifos[cidx].fifonum,
++ context->fifos[cidx].usb_packet_maxlen,
++ context->fifos[cidx].intervall);
++#endif
++ }
++ }
++
++ ep++;
++ }
++
++ // now share our luck
++ context->dev = dev; /* save device */
++ context->if_used = ifnum; /* save used interface */
++ context->alt_used = alt_used; /* and alternate config */
++ context->ctrl_paksize = dev->descriptor.bMaxPacketSize0; /* control size */
++ context->cfg_used=vcf[16]; // store used config
++ context->vend_idx=vend_idx; // store found vendor
++ context->packet_size=packet_size;
++ context->iso_packet_size=iso_packet_size;
++
++ /* create the control pipes needed for register access */
++ context->ctrl_in_pipe = usb_rcvctrlpipe(context->dev, 0);
++ context->ctrl_out_pipe = usb_sndctrlpipe(context->dev, 0);
++ context->ctrl_urb = usb_alloc_urb(0);
++
++ printk(KERN_INFO "HFC-USB: detected \"%s\" configuration: %s (if=%d alt=%d)\n",
++ vdata[vend_idx].vend_name, conf_str[small_match], context->if_used, context->alt_used);
++
++ /* init the chip and register the driver */
++ if (usb_init(context))
++ {
++ if (context->ctrl_urb) {
++ usb_unlink_urb(context->ctrl_urb);
++ usb_free_urb(context->ctrl_urb);
++ context->ctrl_urb = NULL;
++ }
++ kfree(context);
++ return(NULL);
++ }
++ //usb_set_intfdata(intf, context);
++ //intf->private_data = context;
++ return(context);
++ }
++ }
++ return(NULL);
++}
+
+ /****************************************************/
+ /* function called when an active device is removed */
+ /****************************************************/
+-static void
+-hfc_usb_disconnect(struct usb_device *usbdev, void *drv_context)
++//static void hfc_usb_disconnect(struct usb_interface *intf)
++static void hfc_usb_disconnect(struct usb_device *usbdev, void* drv_context)
+ {
+- hfcusb_data *context = drv_context;
++ //hfcusb_data *context = intf->private_data;
++ hfcusb_data* context = drv_context;
+ int i;
+- struct sk_buff *skb;
+
+- /* tell all fifos to terminate */
+- for (i = 0; i < HFCUSB_NUM_FIFOS; i++)
+- if (context->fifos[i].active) {
+- context->fifos[i].active = 0;
+- usb_unlink_urb(&context->fifos[i].urb);
+- }
+- while (context->active_fifos) {
+- set_current_state(TASK_INTERRUPTIBLE);
+- /* Timeout 10ms */
+- schedule_timeout((10 * HZ) / 1000);
+- }
++ printk(KERN_INFO "HFC-USB: device disconnect\n");
++
++ //intf->private_data = NULL;
++ if (!context)
++ return;
+ if (timer_pending(&context->t3_timer))
+ del_timer(&context->t3_timer);
+- context->regd.release_driver(context->regd.arg_hisax);
+- while ((skb = skb_dequeue(&context->regd.erq)) != NULL)
+- dev_kfree_skb_any(skb);
++ if (timer_pending(&context->t4_timer))
++ del_timer(&context->t4_timer);
++ if (timer_pending(&context->led_timer))
++ del_timer(&context->led_timer);
++
++ hisax_unregister(&context->d_if);
+
++ /* tell all fifos to terminate */
++ for(i = 0; i < HFCUSB_NUM_FIFOS; i++) {
++ if(context->fifos[i].usb_transfer_mode == USB_ISOC) {
++ if(context->fifos[i].active > 0) {
++ stop_isoc_chain(&context->fifos[i]);
++#ifdef VERBOSE_USB_DEBUG
++ printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: stopping ISOC chain Fifo no %i\n", i);
++#endif
++ }
++ } else {
++ if(context->fifos[i].active > 0) {
++ context->fifos[i].active = 0;
++#ifdef VERBOSE_USB_DEBUG
++ printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: unlinking URB for Fifo no %i\n", i);
++#endif
++ }
++ if (context->fifos[i].urb) {
++ usb_unlink_urb(context->fifos[i].urb);
++ usb_free_urb(context->fifos[i].urb);
++ context->fifos[i].urb = NULL;
++ }
++ }
++ context->fifos[i].active = 0;
++ }
++ if (context->ctrl_urb) {
++ usb_unlink_urb(context->ctrl_urb);
++ usb_free_urb(context->ctrl_urb);
++ context->ctrl_urb = NULL;
++ }
+ kfree(context); /* free our structure again */
+- MOD_DEC_USE_COUNT; /* and decrement the usage counter */
+ } /* hfc_usb_disconnect */
+
++
+ /************************************/
+ /* our driver information structure */
+ /************************************/
+ static struct usb_driver hfc_drv = {
+ name:"hfc_usb",
+-#ifdef COMPAT_HAS_USB_IDTAB
+ id_table:hfc_usb_idtab,
+-#endif
+ probe:hfc_usb_probe,
+ disconnect:hfc_usb_disconnect,
+ };
+
+-static void __exit
+-hfc_usb_exit(void)
+-{
+
++static void __exit hfc_usb_exit(void)
++{
++#ifdef VERBOSE_USB_DEBUG
++ printk ("HFC-USB: calling \"hfc_usb_exit\" ...\n");
++#endif
+ usb_deregister(&hfc_drv); /* release our driver */
+ printk(KERN_INFO "HFC-USB module removed\n");
+ }
+
+-static int __init
+-hfc_usb_init(void)
++static int __init hfc_usb_init(void)
+ {
+- struct hisax_drvreg drv;
++ printk ("HFC-USB: driver module revision %s loaded\n", hfcusb_revision);
+
+- drv.version = HISAX_LOAD_VERSION; /* set our version */
+- drv.cmd = HISAX_LOAD_CHKVER; /* check command only */
+- if (hisax_register_hfcusb(&drv)) {
+- printk(KERN_INFO "HFC-USB <-> hisax version conflict\n");
+- return (-1); /* unable to register */
+- }
+- if (usb_register(&hfc_drv)) {
+- printk(KERN_INFO
+- "Unable to register HFC-USB module at usb stack\n");
+- return (-1); /* unable to register */
++ if(usb_register(&hfc_drv))
++ {
++ printk(KERN_INFO "HFC-USB: Unable to register HFC-USB module at usb stack\n");
++ return(-1); /* unable to register */
+ }
+-
+- printk(KERN_INFO "HFC-USB module loaded\n");
+- return (0);
++ return(0);
+ }
+
++
++
++
++
+ module_init(hfc_usb_init);
+ module_exit(hfc_usb_exit);
++
diff --git a/target/linux/generic-2.4/patches/202-pl2303_backport.patch b/target/linux/generic-2.4/patches/202-pl2303_backport.patch
new file mode 100644
index 0000000000..f889ad2964
--- /dev/null
+++ b/target/linux/generic-2.4/patches/202-pl2303_backport.patch
@@ -0,0 +1,40 @@
+diff -ur linux-2.4.32/drivers/usb/serial/pl2303.c linux-2.4.32.openwrt/drivers/usb/serial/pl2303.c
+--- linux-2.4.32/drivers/usb/serial/pl2303.c 2005-06-01 02:56:56.000000000 +0200
++++ linux-2.4.32.openwrt/drivers/usb/serial/pl2303.c 2005-11-18 12:22:23.000000000 +0100
+@@ -78,6 +78,11 @@
+ { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) },
+ { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) },
+ { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) },
++ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) },
++ { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) },
++ { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) },
++ { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) },
++ { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) },
+ { } /* Terminating entry */
+ };
+
+diff -ur linux-2.4.32/drivers/usb/serial/pl2303.h linux-2.4.32.openwrt/drivers/usb/serial/pl2303.h
+--- linux-2.4.32/drivers/usb/serial/pl2303.h 2004-02-18 14:36:31.000000000 +0100
++++ linux-2.4.32.openwrt/drivers/usb/serial/pl2303.h 2005-11-18 12:23:38.000000000 +0100
+@@ -41,3 +41,21 @@
+
+ #define SITECOM_VENDOR_ID 0x6189
+ #define SITECOM_PRODUCT_ID 0x2068
++
++/* Alcatel OT535/735 USB cable */
++#define ALCATEL_VENDOR_ID 0x11f7
++#define ALCATEL_PRODUCT_ID 0x02df
++
++/* Samsung I330 phone cradle */
++#define SAMSUNG_VENDOR_ID 0x04e8
++#define SAMSUNG_PRODUCT_ID 0x8001
++
++#define SIEMENS_VENDOR_ID 0x11f5
++#define SIEMENS_PRODUCT_ID_X65 0x0003
++
++#define SYNTECH_VENDOR_ID 0x0745
++#define SYNTECH_PRODUCT_ID 0x0001
++
++/* Nokia CA-42 Cable */
++#define NOKIA_CA42_VENDOR_ID 0x078b
++#define NOKIA_CA42_PRODUCT_ID 0x1234
diff --git a/target/linux/generic-2.4/patches/203-hfsplus_fix.patch b/target/linux/generic-2.4/patches/203-hfsplus_fix.patch
new file mode 100644
index 0000000000..695a2d36b5
--- /dev/null
+++ b/target/linux/generic-2.4/patches/203-hfsplus_fix.patch
@@ -0,0 +1,23 @@
+diff -urN linux-2.4.30.old/fs/hfsplus/super.c linux-2.4.30.dev/fs/hfsplus/super.c
+--- linux-2.4.30.old/fs/hfsplus/super.c 2003-08-25 13:44:43.000000000 +0200
++++ linux-2.4.30.dev/fs/hfsplus/super.c 2005-04-27 19:54:40.000000000 +0200
+@@ -240,8 +240,7 @@
+ if (!(*flags & MS_RDONLY)) {
+ struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr;
+
+- if ((vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_INCNSTNT)) ||
+- !(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
++ if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
+ printk("HFS+-fs warning: Filesystem was not cleanly unmounted, "
+ "running fsck.hfsplus is recommended. leaving read-only.\n");
+ sb->s_flags |= MS_RDONLY;
+@@ -343,8 +342,7 @@
+ /* Set up operations so we can load metadata */
+ sb->s_op = &hfsplus_sops;
+
+- if ((vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_INCNSTNT)) ||
+- !(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
++ if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
+ if (!silent)
+ printk("HFS+-fs warning: Filesystem was not cleanly unmounted, "
+ "running fsck.hfsplus is recommended. mounting read-only.\n");
diff --git a/target/linux/generic-2.4/patches/206-gcc_3.4_fixes.patch b/target/linux/generic-2.4/patches/206-gcc_3.4_fixes.patch
new file mode 100644
index 0000000000..9cf055346a
--- /dev/null
+++ b/target/linux/generic-2.4/patches/206-gcc_3.4_fixes.patch
@@ -0,0 +1,225 @@
+diff -Nur linux-2.4.30/arch/mips/kernel/signal.c linux-2.4.30.openwrt/arch/mips/kernel/signal.c
+--- linux-2.4.30/arch/mips/kernel/signal.c 2005-07-02 13:00:13.000000000 +0200
++++ linux-2.4.30.openwrt/arch/mips/kernel/signal.c 2005-07-02 13:00:49.000000000 +0200
+@@ -6,8 +6,10 @@
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1994 - 1999 Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
++ * Copyright (C) 2004 Maciej W. Rozycki
+ */
+ #include <linux/config.h>
++#include <linux/compiler.h>
+ #include <linux/sched.h>
+ #include <linux/mm.h>
+ #include <linux/smp.h>
+@@ -76,7 +78,9 @@
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+ save_static_function(sys_sigsuspend);
+-static_unused int _sys_sigsuspend(struct pt_regs regs)
++static int _sys_sigsuspend(struct pt_regs regs)
++ __asm__("_sys_sigsuspend") __attribute_used__;
++static int _sys_sigsuspend(struct pt_regs regs)
+ {
+ sigset_t *uset, saveset, newset;
+
+@@ -102,7 +106,9 @@
+ }
+
+ save_static_function(sys_rt_sigsuspend);
+-static_unused int _sys_rt_sigsuspend(struct pt_regs regs)
++static int _sys_rt_sigsuspend(struct pt_regs regs)
++ __asm__("_sys_rt_sigsuspend") __attribute_used__;
++static int _sys_rt_sigsuspend(struct pt_regs regs)
+ {
+ sigset_t *unewset, saveset, newset;
+ size_t sigsetsize;
+diff -Nur linux-2.4.30/arch/mips/kernel/syscall.c linux-2.4.30.openwrt/arch/mips/kernel/syscall.c
+--- linux-2.4.30/arch/mips/kernel/syscall.c 2005-07-02 13:00:13.000000000 +0200
++++ linux-2.4.30.openwrt/arch/mips/kernel/syscall.c 2005-07-02 13:00:49.000000000 +0200
+@@ -5,6 +5,7 @@
+ *
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
+ * Copyright (C) 2000 Silicon Graphics, Inc.
++ * Copyright (C) 2004 Maciej W. Rozycki
+ *
+ * TODO: Implement the compatibility syscalls.
+ * Don't waste that much memory for empty entries in the syscall
+@@ -158,7 +159,9 @@
+ }
+
+ save_static_function(sys_fork);
+-static_unused int _sys_fork(struct pt_regs regs)
++static int _sys_fork(struct pt_regs regs)
++ __asm__("_sys_fork") __attribute_used__;
++static int _sys_fork(struct pt_regs regs)
+ {
+ int res;
+
+@@ -168,7 +171,9 @@
+
+
+ save_static_function(sys_clone);
+-static_unused int _sys_clone(struct pt_regs regs)
++static int _sys_clone(struct pt_regs regs)
++ __asm__("_sys_clone") __attribute_used__;
++static int _sys_clone(struct pt_regs regs)
+ {
+ unsigned long clone_flags;
+ unsigned long newsp;
+diff -Nur linux-2.4.30/arch/mips/ld.script.in linux-2.4.30.openwrt/arch/mips/ld.script.in
+--- linux-2.4.30/arch/mips/ld.script.in 2005-07-02 13:00:22.000000000 +0200
++++ linux-2.4.30.openwrt/arch/mips/ld.script.in 2005-07-02 13:00:42.000000000 +0200
+@@ -9,6 +9,7 @@
+ {
+ _ftext = . ;
+ *(.text)
++ *(.fixup)
+ *(.rodata)
+ *(.rodata.*)
+ *(.rodata1)
+diff -Nur linux-2.4.30/arch/mips64/kernel/signal.c linux-2.4.30.openwrt/arch/mips64/kernel/signal.c
+--- linux-2.4.30/arch/mips64/kernel/signal.c 2005-07-02 13:00:13.000000000 +0200
++++ linux-2.4.30.openwrt/arch/mips64/kernel/signal.c 2005-07-02 13:00:49.000000000 +0200
+@@ -6,8 +6,10 @@
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2000 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
++ * Copyright (C) 2004 Maciej W. Rozycki
+ */
+ #include <linux/config.h>
++#include <linux/compiler.h>
+ #include <linux/sched.h>
+ #include <linux/mm.h>
+ #include <linux/smp.h>
+@@ -75,7 +77,9 @@
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+ save_static_function(sys_rt_sigsuspend);
+-static_unused int _sys_rt_sigsuspend(abi64_no_regargs, struct pt_regs regs)
++static int _sys_rt_sigsuspend(abi64_no_regargs, struct pt_regs regs)
++ __asm__("_sys_rt_sigsuspend") __attribute_used__;
++static int _sys_rt_sigsuspend(abi64_no_regargs, struct pt_regs regs)
+ {
+ sigset_t *unewset, saveset, newset;
+ size_t sigsetsize;
+diff -Nur linux-2.4.30/arch/mips64/kernel/signal32.c linux-2.4.30.openwrt/arch/mips64/kernel/signal32.c
+--- linux-2.4.30/arch/mips64/kernel/signal32.c 2005-07-02 13:00:13.000000000 +0200
++++ linux-2.4.30.openwrt/arch/mips64/kernel/signal32.c 2005-07-02 13:00:49.000000000 +0200
+@@ -6,7 +6,9 @@
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2000 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
++ * Copyright (C) 2004 Maciej W. Rozycki
+ */
++#include <linux/compiler.h>
+ #include <linux/sched.h>
+ #include <linux/mm.h>
+ #include <linux/smp.h>
+@@ -192,7 +194,9 @@
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+ save_static_function(sys32_sigsuspend);
+-static_unused int _sys32_sigsuspend(abi64_no_regargs, struct pt_regs regs)
++static int _sys32_sigsuspend(abi64_no_regargs, struct pt_regs regs)
++ __asm__("_sys32_sigsuspend") __attribute_used__;
++static int _sys32_sigsuspend(abi64_no_regargs, struct pt_regs regs)
+ {
+ sigset32_t *uset;
+ sigset_t newset, saveset;
+@@ -219,7 +223,9 @@
+ }
+
+ save_static_function(sys32_rt_sigsuspend);
+-static_unused int _sys32_rt_sigsuspend(abi64_no_regargs, struct pt_regs regs)
++static int _sys32_rt_sigsuspend(abi64_no_regargs, struct pt_regs regs)
++ __asm__("_sys32_rt_sigsuspend") __attribute_used__;
++static int _sys32_rt_sigsuspend(abi64_no_regargs, struct pt_regs regs)
+ {
+ sigset32_t *uset;
+ sigset_t newset, saveset;
+diff -Nur linux-2.4.30/arch/mips64/kernel/syscall.c linux-2.4.30.openwrt/arch/mips64/kernel/syscall.c
+--- linux-2.4.30/arch/mips64/kernel/syscall.c 2005-07-02 13:00:13.000000000 +0200
++++ linux-2.4.30.openwrt/arch/mips64/kernel/syscall.c 2005-07-02 13:00:49.000000000 +0200
+@@ -6,7 +6,9 @@
+ * Copyright (C) 1995 - 2000, 2001 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2001 MIPS Technologies, Inc.
++ * Copyright (C) 2004 Maciej W. Rozycki
+ */
++#include <linux/compiler.h>
+ #include <linux/errno.h>
+ #include <linux/linkage.h>
+ #include <linux/mm.h>
+@@ -151,7 +153,9 @@
+ }
+
+ save_static_function(sys_fork);
+-static_unused int _sys_fork(abi64_no_regargs, struct pt_regs regs)
++static int _sys_fork(abi64_no_regargs, struct pt_regs regs)
++ __asm__("_sys_fork") __attribute_used__;
++static int _sys_fork(abi64_no_regargs, struct pt_regs regs)
+ {
+ int res;
+
+@@ -160,7 +164,9 @@
+ }
+
+ save_static_function(sys_clone);
+-static_unused int _sys_clone(abi64_no_regargs, struct pt_regs regs)
++static int _sys_clone(abi64_no_regargs, struct pt_regs regs)
++ __asm__("_sys_clone") __attribute_used__;
++static int _sys_clone(abi64_no_regargs, struct pt_regs regs)
+ {
+ unsigned long clone_flags;
+ unsigned long newsp;
+diff -Nur linux-2.4.30/include/asm-mips/ptrace.h linux-2.4.30.openwrt/include/asm-mips/ptrace.h
+--- linux-2.4.30/include/asm-mips/ptrace.h 2005-07-02 13:00:13.000000000 +0200
++++ linux-2.4.30.openwrt/include/asm-mips/ptrace.h 2005-07-02 13:00:49.000000000 +0200
+@@ -4,6 +4,7 @@
+ * for more details.
+ *
+ * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000 by Ralf Baechle
++ * Copyright (C) 2004 Maciej W. Rozycki
+ *
+ * Machine dependent structs and defines to help the user use
+ * the ptrace system call.
+@@ -64,12 +65,10 @@
+ "sw\t$22,"__str(PT_R22)"($29)\n\t" \
+ "sw\t$23,"__str(PT_R23)"($29)\n\t" \
+ "sw\t$30,"__str(PT_R30)"($29)\n\t" \
++ "j\t_" #symbol "\n\t" \
+ ".end\t" #symbol "\n\t" \
+ ".size\t" #symbol",. - " #symbol)
+
+-/* Used in declaration of save_static functions. */
+-#define static_unused static __attribute__((unused))
+-
+ #endif /* !__ASSEMBLY__ */
+
+ /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+diff -Nur linux-2.4.30/include/asm-mips64/ptrace.h linux-2.4.30.openwrt/include/asm-mips64/ptrace.h
+--- linux-2.4.30/include/asm-mips64/ptrace.h 2005-07-02 13:00:13.000000000 +0200
++++ linux-2.4.30.openwrt/include/asm-mips64/ptrace.h 2005-07-02 13:00:49.000000000 +0200
+@@ -5,6 +5,7 @@
+ *
+ * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
++ * Copyright (C) 2004 Maciej W. Rozycki
+ */
+ #ifndef _ASM_PTRACE_H
+ #define _ASM_PTRACE_H
+@@ -61,12 +62,10 @@
+ "sd\t$22,"__str(PT_R22)"($29)\n\t" \
+ "sd\t$23,"__str(PT_R23)"($29)\n\t" \
+ "sd\t$30,"__str(PT_R30)"($29)\n\t" \
++ "j\t_" #symbol "\n\t" \
+ ".end\t" #symbol "\n\t" \
+ ".size\t" #symbol",. - " #symbol)
+
+-/* Used in declaration of save_static functions. */
+-#define static_unused static __attribute__((unused))
+-
+ #define abi64_no_regargs \
+ unsigned long __dummy0, \
+ unsigned long __dummy1, \
diff --git a/target/linux/generic-2.4/patches/208-usb2_fix.patch b/target/linux/generic-2.4/patches/208-usb2_fix.patch
new file mode 100644
index 0000000000..f8e5be12c1
--- /dev/null
+++ b/target/linux/generic-2.4/patches/208-usb2_fix.patch
@@ -0,0 +1,15 @@
+diff -ur linux-2.4.30.dev/drivers/usb/host/ehci-q.c linux-tmp/drivers/usb/host/ehci-q.c
+--- linux-2.4.30.dev/drivers/usb/host/ehci-q.c 2005-01-19 15:10:07.000000000 +0100
++++ linux-tmp/drivers/usb/host/ehci-q.c 2005-03-30 05:11:12.000000000 +0200
+@@ -783,6 +765,11 @@
+ if (!(cmd & CMD_ASE)) {
+ /* in case a clear of CMD_ASE didn't take yet */
+ (void) handshake (&ehci->regs->status, STS_ASS, 0, 150);
++
++ /* force async head to be valid */
++ writel ((u32)ehci->async->qh_dma,
++ &ehci->regs->async_next);
++
+ cmd |= CMD_ASE | CMD_RUN;
+ writel (cmd, &ehci->regs->command);
+ ehci->hcd.state = USB_STATE_RUNNING;
diff --git a/target/linux/generic-2.4/patches/209-build_fixes.patch b/target/linux/generic-2.4/patches/209-build_fixes.patch
new file mode 100644
index 0000000000..235ee042a5
--- /dev/null
+++ b/target/linux/generic-2.4/patches/209-build_fixes.patch
@@ -0,0 +1,48 @@
+diff -urN linux.old/Makefile linux.dev/Makefile
+--- linux.old/Makefile 2005-08-26 13:41:41.689634168 +0200
++++ linux.dev/Makefile 2005-08-26 13:44:34.233403528 +0200
+@@ -354,7 +354,7 @@
+ @rm -f .ver1
+
+ include/linux/version.h: ./Makefile
+- @expr length "$(KERNELRELEASE)" \<= $(uts_len) > /dev/null || \
++ @-expr length "$(KERNELRELEASE)" \<= $(uts_len) > /dev/null || \
+ (echo KERNELRELEASE \"$(KERNELRELEASE)\" exceeds $(uts_len) characters >&2; false)
+ @echo \#define UTS_RELEASE \"$(KERNELRELEASE)\" > .ver
+ @echo \#define LINUX_VERSION_CODE `expr $(VERSION) \\* 65536 + $(PATCHLEVEL) \\* 256 + $(SUBLEVEL)` >> .ver
+@@ -509,7 +509,7 @@
+ ifdef CONFIG_MODVERSIONS
+ $(MAKE) update-modverfile
+ endif
+- scripts/mkdep -- `find $(FINDHPATH) \( -name SCCS -o -name .svn \) -prune -o -follow -name \*.h ! -name modversions.h -print` > .hdepend
++ find $(FINDHPATH) \( -name SCCS -o -name .svn \) -prune -o -follow -name \*.h ! -name modversions.h -print | xargs scripts/mkdep -- > .hdepend
+ scripts/mkdep -- init/*.c > .depend
+
+ ifdef CONFIG_MODVERSIONS
+--- linux.old/Rules.make 2005-08-31 00:37:34.363109288 +0200
++++ linux.dev/Rules.make 2005-08-31 13:59:20.140676296 +0200
+@@ -126,7 +126,7 @@
+ # This make dependencies quickly
+ #
+ fastdep: dummy
+- $(TOPDIR)/scripts/mkdep $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -- $(wildcard *.[chS]) > .depend
++ find -name '*.[chS]' | xargs $(TOPDIR)/scripts/mkdep $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -- > .depend
+ ifdef ALL_SUB_DIRS
+ $(MAKE) $(patsubst %,_sfdep_%,$(ALL_SUB_DIRS)) _FASTDEP_ALL_SUB_DIRS="$(ALL_SUB_DIRS)"
+ endif
+@@ -176,7 +176,14 @@
+ _modinst__: dummy
+ ifneq "$(strip $(ALL_MOBJS))" ""
+ mkdir -p $(MODLIB)/kernel/$(MOD_DESTDIR)
+- cp $(sort $(ALL_MOBJS)) $(MODLIB)/kernel/$(MOD_DESTDIR)
++ #@cp $(sort $(ALL_MOBJS)) $(MODLIB)/kernel/$(MOD_DESTDIR)
++ for f in $(ALL_MOBJS) ; do \
++ $(OBJCOPY) -R __ksymtab -R .comment -R .note -x \
++ `$(NM) $$f | cut -f3- -d' ' | sed -n \
++ -e 's/__module_parm_\(.*\)/-K \1/p' \
++ -e 's/__ks..tab_\(.*\)/-K \1/p'` \
++ $$f $(MODLIB)/kernel/$(MOD_DESTDIR)$(MOD_TARGET)`basename $$f`; \
++ done
+ endif
+
+ .PHONY: modules_install
diff --git a/target/linux/generic-2.4/patches/210-fix-irq-serial.patch b/target/linux/generic-2.4/patches/210-fix-irq-serial.patch
new file mode 100644
index 0000000000..630dc04977
--- /dev/null
+++ b/target/linux/generic-2.4/patches/210-fix-irq-serial.patch
@@ -0,0 +1,21 @@
+--- linux-2.4.30/drivers/char/serial.c 2005-06-29 20:44:46.000000000 +0200
++++ linux-2.4.30.serial/drivers/char/serial.c 2005-06-29 21:15:12.000000000 +0200
+@@ -5455,18 +5455,6 @@
+ sizeof(struct rs_multiport_struct));
+ #endif
+ }
+-#ifdef CONFIG_SERIAL_CONSOLE
+- /*
+- * The interrupt of the serial console port
+- * can't be shared.
+- */
+- if (sercons.flags & CON_CONSDEV) {
+- for(i = 0; i < NR_PORTS; i++)
+- if (i != sercons.index &&
+- rs_table[i].irq == rs_table[sercons.index].irq)
+- rs_table[i].irq = 0;
+- }
+-#endif
+ show_serial_version();
+
+ /* Initialize the tty_driver structure */
diff --git a/target/linux/generic-2.4/patches/212-htb_time_fix.patch b/target/linux/generic-2.4/patches/212-htb_time_fix.patch
new file mode 100644
index 0000000000..7281093b02
--- /dev/null
+++ b/target/linux/generic-2.4/patches/212-htb_time_fix.patch
@@ -0,0 +1,75 @@
+--- linux.old/net/sched/sch_htb.c 2005-11-15 14:09:41.548066000 +0100
++++ linux.dev/net/sched/sch_htb.c 2005-11-15 14:08:34.000000000 +0100
+@@ -369,7 +369,7 @@
+ struct list_head *l;
+ list_for_each (l,q->hash+i) {
+ struct htb_class *cl = list_entry(l,struct htb_class,hlist);
+- long diff = PSCHED_TDIFF_SAFE(q->now, cl->t_c, (u32)cl->mbuffer, 0);
++ long long diff = PSCHED_TDIFF_SAFE(q->now, cl->t_c, (u32)cl->mbuffer, 0);
+ printk(KERN_DEBUG "htb*c%x m=%d t=%ld c=%ld pq=%lu df=%ld ql=%d "
+ "pa=%x f:",
+ cl->classid,cl->cmode,cl->tokens,cl->ctokens,
+@@ -617,7 +617,7 @@
+ * mode transitions per time unit. The speed gain is about 1/6.
+ */
+ static __inline__ enum htb_cmode
+-htb_class_mode(struct htb_class *cl,long *diff)
++htb_class_mode(struct htb_class *cl,long long *diff)
+ {
+ long toks;
+
+@@ -650,7 +650,7 @@
+ * to mode other than HTB_CAN_SEND (see htb_add_to_wait_tree).
+ */
+ static void
+-htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, long *diff)
++htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, long long *diff)
+ {
+ enum htb_cmode new_mode = htb_class_mode(cl,diff);
+
+@@ -815,7 +815,8 @@
+ static void htb_charge_class(struct htb_sched *q,struct htb_class *cl,
+ int level,int bytes)
+ {
+- long toks,diff;
++ long long diff;
++ long toks;
+ enum htb_cmode old_mode;
+ HTB_DBG(5,1,"htb_chrg_cl cl=%X lev=%d len=%d\n",cl->classid,level,bytes);
+
+@@ -831,7 +832,7 @@
+ #ifdef HTB_DEBUG
+ if (diff > cl->mbuffer || diff < 0 || PSCHED_TLESS(q->now, cl->t_c)) {
+ if (net_ratelimit())
+- printk(KERN_ERR "HTB: bad diff in charge, cl=%X diff=%lX now=%Lu then=%Lu j=%lu\n",
++ printk(KERN_ERR "HTB: bad diff in charge, cl=%X diff=%Ld now=%Lu then=%Lu j=%lu\n",
+ cl->classid, diff,
+ (unsigned long long) q->now,
+ (unsigned long long) cl->t_c,
+@@ -848,7 +849,7 @@
+ }
+ HTB_ACCNT (ctokens,cbuffer,ceil);
+ cl->t_c = q->now;
+- HTB_DBG(5,2,"htb_chrg_clp cl=%X diff=%ld tok=%ld ctok=%ld\n",cl->classid,diff,cl->tokens,cl->ctokens);
++ HTB_DBG(5,2,"htb_chrg_clp cl=%X diff=%Ld tok=%ld ctok=%ld\n",cl->classid,diff,cl->tokens,cl->ctokens);
+
+ old_mode = cl->cmode; diff = 0;
+ htb_change_class_mode(q,cl,&diff);
+@@ -887,7 +888,7 @@
+ level,q->wait_pq[level].rb_node,q->row_mask[level]);
+ for (i = 0; i < 500; i++) {
+ struct htb_class *cl;
+- long diff;
++ long long diff;
+ rb_node_t *p = q->wait_pq[level].rb_node;
+ if (!p) return 0;
+ while (p->rb_left) p = p->rb_left;
+@@ -902,7 +903,7 @@
+ #ifdef HTB_DEBUG
+ if (diff > cl->mbuffer || diff < 0 || PSCHED_TLESS(q->now, cl->t_c)) {
+ if (net_ratelimit())
+- printk(KERN_ERR "HTB: bad diff in events, cl=%X diff=%lX now=%Lu then=%Lu j=%lu\n",
++ printk(KERN_ERR "HTB: bad diff in events, cl=%X diff=%Ld now=%Lu then=%Lu j=%lu\n",
+ cl->classid, diff,
+ (unsigned long long) q->now,
+ (unsigned long long) cl->t_c,
diff --git a/target/linux/generic-2.4/patches/213-htb_disable_hysteresis.patch b/target/linux/generic-2.4/patches/213-htb_disable_hysteresis.patch
new file mode 100644
index 0000000000..5d0ff92662
--- /dev/null
+++ b/target/linux/generic-2.4/patches/213-htb_disable_hysteresis.patch
@@ -0,0 +1,11 @@
+--- linux.old/net/sched/sch_htb.c 2005-11-15 14:09:41.548066000 +0100
++++ linux.dev/net/sched/sch_htb.c 2005-11-15 14:08:34.000000000 +0100
+@@ -74,7 +74,7 @@
+ #define HTB_EWMAC 2 /* rate average over HTB_EWMAC*HTB_HSIZE sec */
+ #define HTB_DEBUG 1 /* compile debugging support (activated by tc tool) */
+ #define HTB_RATECM 1 /* whether to use rate computer */
+-#define HTB_HYSTERESIS 1/* whether to use mode hysteresis for speedup */
++#define HTB_HYSTERESIS 0/* whether to use mode hysteresis for speedup */
+ #define HTB_QLOCK(S) spin_lock_bh(&(S)->dev->queue_lock)
+ #define HTB_QUNLOCK(S) spin_unlock_bh(&(S)->dev->queue_lock)
+ #define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */
diff --git a/target/linux/generic-2.4/patches/222-sound.patch b/target/linux/generic-2.4/patches/222-sound.patch
new file mode 100644
index 0000000000..351e8c2072
--- /dev/null
+++ b/target/linux/generic-2.4/patches/222-sound.patch
@@ -0,0 +1,27 @@
+diff -rNu linux-2.4.30/drivers/sound/sound_core.c linux-2.4.30.new/drivers/sound/sound_core.c
+--- linux-2.4.30/drivers/sound/sound_core.c 2001-10-01 05:26:08.000000000 +1000
++++ linux-2.4.30.new/drivers/sound/sound_core.c 2005-08-27 22:52:55.061719968 +1000
+@@ -174,9 +174,9 @@
+ }
+
+ if (r == low)
+- sprintf (name_buf, "%s", name);
++ snprintf (name_buf, sizeof(name_buf), "%s", name);
+ else
+- sprintf (name_buf, "%s%d", name, (r - low) / SOUND_STEP);
++ snprintf (name_buf, sizeof(name_buf), "%s%d", name, (r - low) / SOUND_STEP);
+ s->de = devfs_register (devfs_handle, name_buf,
+ DEVFS_FL_NONE, SOUND_MAJOR, s->unit_minor,
+ S_IFCHR | mode, fops, NULL);
+@@ -507,9 +507,9 @@
+ * ALSA toplevel modules for soundcards, thus we need
+ * load them at first. [Jaroslav Kysela <perex@jcu.cz>]
+ */
+- sprintf(mod, "sound-slot-%i", unit>>4);
++ snprintf(mod, sizeof(mod), "sound-slot-%i", unit>>4);
+ request_module(mod);
+- sprintf(mod, "sound-service-%i-%i", unit>>4, chain);
++ snprintf(mod, sizeof(mod), "sound-service-%i-%i", unit>>4, chain);
+ request_module(mod);
+ spin_lock(&sound_loader_lock);
+ s = __look_for_unit(chain, unit);
diff --git a/target/linux/generic-2.4/patches/224-atm_hotplug.patch b/target/linux/generic-2.4/patches/224-atm_hotplug.patch
new file mode 100644
index 0000000000..c431d8c6bc
--- /dev/null
+++ b/target/linux/generic-2.4/patches/224-atm_hotplug.patch
@@ -0,0 +1,98 @@
+diff -urN linux.old/include/linux/atmdev.h linux.dev/include/linux/atmdev.h
+--- linux.old/include/linux/atmdev.h 2005-11-17 12:51:55.883585000 +0100
++++ linux.dev/include/linux/atmdev.h 2005-11-17 13:49:22.012671000 +0100
+@@ -408,6 +408,7 @@
+ struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops,
+ int number,atm_dev_flags_t *flags); /* number == -1: pick first available */
+ struct atm_dev *atm_dev_lookup(int number);
++void atm_dev_set_link_status(struct atm_dev *dev, int status);
+ void atm_dev_deregister(struct atm_dev *dev);
+ void shutdown_atm_dev(struct atm_dev *dev);
+ void vcc_insert_socket(struct sock *sk);
+diff -urN linux.old/net/atm/resources.c linux.dev/net/atm/resources.c
+--- linux.old/net/atm/resources.c 2003-11-28 19:26:21.000000000 +0100
++++ linux.dev/net/atm/resources.c 2005-11-17 14:27:26.514267750 +0100
+@@ -10,6 +10,7 @@
+ #include <linux/sonet.h>
+ #include <linux/kernel.h> /* for barrier */
+ #include <linux/module.h>
++#include <linux/kmod.h>
+ #include <linux/bitops.h>
+ #include <net/sock.h> /* for struct sock */
+ #include <asm/segment.h> /* for get_fs_long and put_fs_long */
+@@ -70,6 +71,44 @@
+ return dev;
+ }
+
++#ifdef CONFIG_HOTPLUG
++static void atm_run_sbin_hotplug(struct atm_dev *dev, char *action)
++{
++ char *argv[3], *envp[5], ifname[12 + IFNAMSIZ], atmname[255], action_str[32];
++ int i;
++
++ sprintf(ifname, "INTERFACE=atm%d", dev->number);
++ sprintf(atmname, "ATMDRIVER=%s", dev->type);
++ sprintf(action_str, "ACTION=%s", action);
++
++ i = 0;
++ argv[i++] = hotplug_path;
++ argv[i++] = "net";
++ argv[i] = 0;
++
++ i = 0;
++ /* minimal command environment */
++ envp [i++] = "HOME=/";
++ envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
++ envp [i++] = ifname;
++ envp [i++] = atmname;
++ envp [i++] = action_str;
++ envp [i] = 0;
++
++ return call_usermodehelper(argv [0], argv, envp);
++}
++#endif
++
++void atm_dev_set_link_status(struct atm_dev *dev, int status)
++{
++#ifdef CONFIG_HOTPLUG
++ if (status)
++ atm_run_sbin_hotplug(dev, "up");
++ else
++ atm_run_sbin_hotplug(dev, "down");
++#endif
++}
++
+ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
+ int number, atm_dev_flags_t *flags)
+ {
+@@ -123,7 +162,10 @@
+ }
+ }
+ #endif
+-
++#ifdef CONFIG_HOTPLUG
++ atm_run_sbin_hotplug(dev, "register");
++#endif
++
+ return dev;
+ }
+
+@@ -131,6 +173,10 @@
+ void atm_dev_deregister(struct atm_dev *dev)
+ {
+ unsigned long warning_time;
++
++#ifdef CONFIG_HOTPLUG
++ atm_run_sbin_hotplug(dev, "unregister");
++#endif
+
+ #ifdef CONFIG_PROC_FS
+ if (dev->ops->proc_read)
+@@ -399,6 +445,7 @@
+ }
+
+
++EXPORT_SYMBOL(atm_dev_set_link_status);
+ EXPORT_SYMBOL(atm_dev_register);
+ EXPORT_SYMBOL(atm_dev_deregister);
+ EXPORT_SYMBOL(atm_dev_lookup);
diff --git a/target/linux/generic-2.4/patches/225-string_lib_useful_exports.patch b/target/linux/generic-2.4/patches/225-string_lib_useful_exports.patch
new file mode 100644
index 0000000000..b89f765173
--- /dev/null
+++ b/target/linux/generic-2.4/patches/225-string_lib_useful_exports.patch
@@ -0,0 +1,170 @@
+diff -ruN linux-2.4.32-old/lib/string.c linux-2.4.32-new/lib/string.c
+--- linux-2.4.32-old/lib/string.c 2004-11-17 12:54:22.000000000 +0100
++++ linux-2.4.32-new/lib/string.c 2006-01-17 14:41:17.000000000 +0100
+@@ -50,6 +50,7 @@
+ }
+ return (int)c1 - (int)c2;
+ }
++EXPORT_SYMBOL(strnicmp);
+ #endif
+
+ char * ___strtok;
+@@ -68,6 +69,7 @@
+ /* nothing */;
+ return tmp;
+ }
++EXPORT_SYMBOL(strcpy);
+ #endif
+
+ #ifndef __HAVE_ARCH_STRNCPY
+@@ -90,6 +92,7 @@
+
+ return tmp;
+ }
++EXPORT_SYMBOL(strncpy);
+ #endif
+
+ #ifndef __HAVE_ARCH_STRCAT
+@@ -109,6 +112,7 @@
+
+ return tmp;
+ }
++EXPORT_SYMBOL(strcat);
+ #endif
+
+ #ifndef __HAVE_ARCH_STRNCAT
+@@ -138,6 +142,7 @@
+
+ return tmp;
+ }
++EXPORT_SYMBOL(strncat);
+ #endif
+
+ #ifndef __HAVE_ARCH_STRCMP
+@@ -157,6 +162,7 @@
+
+ return __res;
+ }
++EXPORT_SYMBOL(strcmp);
+ #endif
+
+ #ifndef __HAVE_ARCH_STRNCMP
+@@ -178,6 +184,7 @@
+
+ return __res;
+ }
++EXPORT_SYMBOL(strncmp);
+ #endif
+
+ #ifndef __HAVE_ARCH_STRCHR
+@@ -193,6 +200,7 @@
+ return NULL;
+ return (char *) s;
+ }
++EXPORT_SYMBOL(strchr);
+ #endif
+
+ #ifndef __HAVE_ARCH_STRRCHR
+@@ -210,6 +218,7 @@
+ } while (--p >= s);
+ return NULL;
+ }
++EXPORT_SYMBOL(strrchr);
+ #endif
+
+ #ifndef __HAVE_ARCH_STRLEN
+@@ -225,6 +234,7 @@
+ /* nothing */;
+ return sc - s;
+ }
++EXPORT_SYMBOL(strlen);
+ #endif
+
+ #ifndef __HAVE_ARCH_STRNLEN
+@@ -241,6 +251,7 @@
+ /* nothing */;
+ return sc - s;
+ }
++EXPORT_SYMBOL(strnlen);
+ #endif
+
+ #ifndef __HAVE_ARCH_STRSPN
+@@ -268,6 +279,7 @@
+
+ return count;
+ }
++EXPORT_SYMBOL(strspn);
+ #endif
+
+ #ifndef __HAVE_ARCH_STRPBRK
+@@ -288,6 +300,7 @@
+ }
+ return NULL;
+ }
++EXPORT_SYMBOL(strpbrk);
+ #endif
+
+ #ifndef __HAVE_ARCH_STRTOK
+@@ -345,6 +358,7 @@
+
+ return sbegin;
+ }
++EXPORT_SYMBOL(strsep);
+ #endif
+
+ #ifndef __HAVE_ARCH_MEMSET
+@@ -365,6 +379,7 @@
+
+ return s;
+ }
++EXPORT_SYMBOL(memset);
+ #endif
+
+ #ifndef __HAVE_ARCH_BCOPY
+@@ -409,6 +424,7 @@
+
+ return dest;
+ }
++EXPORT_SYMBOL(memcpy);
+ #endif
+
+ #ifndef __HAVE_ARCH_MEMMOVE
+@@ -439,6 +455,7 @@
+
+ return dest;
+ }
++EXPORT_SYMBOL(memmove);
+ #endif
+
+ #ifndef __HAVE_ARCH_MEMCMP
+@@ -458,6 +475,7 @@
+ break;
+ return res;
+ }
++EXPORT_SYMBOL(memcmp);
+ #endif
+
+ #ifndef __HAVE_ARCH_MEMSCAN
+@@ -482,6 +500,7 @@
+ }
+ return (void *) p;
+ }
++EXPORT_SYMBOL(memscan);
+ #endif
+
+ #ifndef __HAVE_ARCH_STRSTR
+@@ -506,6 +525,7 @@
+ }
+ return NULL;
+ }
++EXPORT_SYMBOL(strstr);
+ #endif
+
+ #ifndef __HAVE_ARCH_MEMCHR
+@@ -528,5 +548,5 @@
+ }
+ return NULL;
+ }
+-
++EXPORT_SYMBOL(memchr);
+ #endif
diff --git a/target/linux/generic-2.4/patches/226-atm_br2684.patch b/target/linux/generic-2.4/patches/226-atm_br2684.patch
new file mode 100644
index 0000000000..56f00155de
--- /dev/null
+++ b/target/linux/generic-2.4/patches/226-atm_br2684.patch
@@ -0,0 +1,578 @@
+diff -urN linux-2.4.32/net/atm/br2684.c linux-2.4.32.new/net/atm/br2684.c
+--- linux-2.4.32/net/atm/br2684.c 2004-08-08 01:26:06.000000000 +0200
++++ linux-2.4.32.new/net/atm/br2684.c 2006-02-06 18:59:40.000000000 +0100
+@@ -55,36 +55,55 @@
+ #define skb_debug(skb) do {} while (0)
+ #endif
+
++#define BR2684_LLC_LEN 3
++#define BR2684_SNAP_LEN 3
++#define BR2684_ETHERTYPE_LEN 2
++#define BR2684_PID_LEN 2
++#define BR2684_PAD_LEN 2
++
++static unsigned char llc_common[] = { 0xaa, 0xaa, 0x03 };
++static unsigned char snap_bridged[] = { 0x00, 0x80, 0xc2 };
++static unsigned char snap_routed[] = { 0x00, 0x00, 0x00 };
++static unsigned char pid_ipv4[] = { 0x00, 0x07 };
++static unsigned char ethertype_ipv4[] = { 0x08, 0x00 };
++static unsigned char ethertype_ipv6[] = { 0x86, 0xdd };
++static unsigned char pad_bridged[] = { 0x00, 0x00 };
++
+ static unsigned char llc_oui_pid_pad[] =
+ { 0xAA, 0xAA, 0x03, 0x00, 0x80, 0xC2, 0x00, 0x07, 0x00, 0x00 };
++static unsigned char llc_oui_ipv6[] =
++ { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x86, 0xdd };
++static unsigned char llc_oui_ipv4[] =
++ { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00 };
+ #define PADLEN (2)
+
+ enum br2684_encaps {
+- e_vc = BR2684_ENCAPS_VC,
++ e_vc = BR2684_ENCAPS_VC,
+ e_llc = BR2684_ENCAPS_LLC,
+ };
+
+ struct br2684_vcc {
+- struct atm_vcc *atmvcc;
++ struct atm_vcc *atmvcc;
+ struct br2684_dev *brdev;
+ /* keep old push,pop functions for chaining */
+- void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb);
++ void (*old_push) (struct atm_vcc * vcc, struct sk_buff * skb);
+ /* void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); */
+ enum br2684_encaps encaps;
++ enum br2684_payload payload;
+ struct list_head brvccs;
+ #ifdef CONFIG_ATM_BR2684_IPFILTER
+ struct br2684_filter filter;
+-#endif /* CONFIG_ATM_BR2684_IPFILTER */
++#endif /* CONFIG_ATM_BR2684_IPFILTER */
+ #ifndef FASTER_VERSION
+ unsigned copies_needed, copies_failed;
+-#endif /* FASTER_VERSION */
++#endif /* FASTER_VERSION */
+ };
+
+ struct br2684_dev {
+ struct net_device net_dev;
+ struct list_head br2684_devs;
+ int number;
+- struct list_head brvccs; /* one device <=> one vcc (before xmas) */
++ struct list_head brvccs; /* one device <=> one vcc (before xmas) */
+ struct net_device_stats stats;
+ int mac_was_set;
+ };
+@@ -173,24 +192,84 @@
+ }
+ skb = skb2;
+ }
+- skb_push(skb, minheadroom);
+- if (brvcc->encaps == e_llc)
+- memcpy(skb->data, llc_oui_pid_pad, 10);
+- else
+- memset(skb->data, 0, 2);
+-#endif /* FASTER_VERSION */
++
++ /* This skb_push is a problem: routed packets need less headroom than
++ * bridged packets.
++ */
++
++/* skb_push(skb, minheadroom); */
++ if (brvcc->encaps == e_llc) {
++ int offset = 0;
++ int actual_headroom;
++
++ actual_headroom =
++ BR2684_LLC_LEN +
++ BR2684_SNAP_LEN +
++ ((brvcc->payload == p_bridged) ?
++ (BR2684_PID_LEN + BR2684_PAD_LEN) :
++ BR2684_ETHERTYPE_LEN);
++
++ skb_push(skb, actual_headroom);
++ memcpy(skb->data, llc_common, BR2684_LLC_LEN);
++ offset += BR2684_LLC_LEN;
++
++ if (brvcc->payload == p_bridged) {
++ memcpy(skb->data + offset, snap_bridged,
++ BR2684_SNAP_LEN);
++ offset += BR2684_SNAP_LEN;
++ /* pid_ipv4 is poorly named. should probably be
++ * pid_ethernet
++ */
++ memcpy(skb->data + offset, pid_ipv4,
++ BR2684_PID_LEN);
++ offset += BR2684_PID_LEN;
++ memcpy(skb->data + offset, pad_bridged,
++ BR2684_PAD_LEN);
++ offset += BR2684_PAD_LEN;
++ } else if (brvcc->payload == p_routed) {
++ unsigned short prot =
++ __constant_ntohs(skb->protocol);
++ memcpy(skb->data + offset, snap_routed,
++ BR2684_SNAP_LEN);
++ offset += BR2684_SNAP_LEN;
++
++ switch (prot) {
++ case ETH_P_IP:
++ memcpy(skb->data + offset,
++ ethertype_ipv4,
++ BR2684_ETHERTYPE_LEN);
++ break;
++ case ETH_P_IPV6:
++ memcpy(skb->data + offset,
++ ethertype_ipv6,
++ BR2684_ETHERTYPE_LEN);
++ break;
++ default:
++ dev_kfree_skb(skb);
++ return 0;
++ }
++ offset += BR2684_ETHERTYPE_LEN;
++
++ }
++ } else {
++ skb_push(skb, 2);
++ if (brvcc->payload == p_bridged)
++ memset(skb->data, 0, 2);
++ }
++#endif /* FASTER_VERSION */
+ skb_debug(skb);
+
+ ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
+- DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev);
++ DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc,
++ atmvcc->dev);
+ if (!atm_may_send(atmvcc, skb->truesize)) {
+ /* we free this here for now, because we cannot know in a higher
+- layer whether the skb point it supplied wasn't freed yet.
+- now, it always is.
+- */
++ layer whether the skb point it supplied wasn't freed yet.
++ now, it always is.
++ */
+ dev_kfree_skb(skb);
+ return 0;
+- }
++ }
+ atomic_add(skb->truesize, &atmvcc->sk->wmem_alloc);
+ ATM_SKB(skb)->atm_options = atmvcc->atm_options;
+ brdev->stats.tx_packets++;
+@@ -428,18 +507,39 @@
+ atm_return(atmvcc, skb->truesize);
+ DPRINTK("skb from brdev %p\n", brdev);
+ if (brvcc->encaps == e_llc) {
++ /* accept packets that have "ipv[46]" in the snap header */
++ /* 8 - 2 == sizeof(llc_oui_ipv6) - BR2684_ETHERTYPE_LEN */
++ if (memcmp(skb->data, llc_oui_ipv6, 8 - 2) == 0) {
++ plen = sizeof(llc_oui_ipv6);
++
++ if (memcmp(skb->data + 6, ethertype_ipv6, 2) == 0)
++ skb->protocol =
++ __constant_htons(ETH_P_IPV6);
++ else if (memcmp(skb->data + 6, ethertype_ipv4, 2)
++ == 0)
++ skb->protocol = __constant_htons(ETH_P_IP);
++ else {
++ brdev->stats.rx_errors++;
++ dev_kfree_skb(skb);
++ return;
++ }
++ skb_pull(skb, plen);
++ skb->nh.raw = skb->data;
++ skb->pkt_type = PACKET_HOST;
++ }
++
+ /* let us waste some time for checking the encapsulation.
+ Note, that only 7 char is checked so frames with a valid FCS
+ are also accepted (but FCS is not checked of course) */
+- if (memcmp(skb->data, llc_oui_pid_pad, 7)) {
++ else if (memcmp(skb->data, llc_oui_pid_pad, 7) == 0) {
++ skb_pull(skb, plen - ETH_HLEN);
++ skb->protocol =
++ eth_type_trans(skb, &brdev->net_dev);
++ } else {
+ brdev->stats.rx_errors++;
+ dev_kfree_skb(skb);
+ return;
+ }
+-
+- /* Strip FCS if present */
+- if (skb->len > 7 && skb->data[7] == 0x01)
+- __skb_trim(skb, skb->len - 4);
+ } else {
+ plen = PADLEN + ETH_HLEN; /* pad, dstmac,srcmac, ethtype */
+ /* first 2 chars should be 0 */
+@@ -448,13 +548,14 @@
+ dev_kfree_skb(skb);
+ return;
+ }
++ skb_pull(skb, plen - ETH_HLEN);
++ skb->protocol = eth_type_trans(skb, &brdev->net_dev);
+ }
+ if (skb->len < plen) {
+ brdev->stats.rx_errors++;
+ dev_kfree_skb(skb); /* dev_ not needed? */
+ return;
+ }
+-
+ #ifdef FASTER_VERSION
+ /* FIXME: tcpdump shows that pointer to mac header is 2 bytes earlier,
+ than should be. What else should I set? */
+@@ -465,30 +566,29 @@
+ skb->protocol = ((u16 *) skb->data)[-1];
+ #else /* some protocols might require this: */
+ skb->protocol = br_type_trans(skb, &brdev->net_dev);
+-#endif /* CONFIG_BR2684_FAST_TRANS */
++#endif /* CONFIG_BR2684_FAST_TRANS */
+ #else
+- skb_pull(skb, plen - ETH_HLEN);
+- skb->protocol = eth_type_trans(skb, &brdev->net_dev);
+-#endif /* FASTER_VERSION */
++ /* skb_pull(skb, plen - ETH_HLEN); */
++ /* skb->protocol = eth_type_trans(skb, &brdev->net_dev); */
++#endif /* FASTER_VERSION */
+ #ifdef CONFIG_ATM_BR2684_IPFILTER
+ if (packet_fails_filter(skb->protocol, brvcc, skb)) {
+ brdev->stats.rx_dropped++;
+ dev_kfree_skb(skb);
+ return;
+ }
+-#endif /* CONFIG_ATM_BR2684_IPFILTER */
++#endif /* CONFIG_ATM_BR2684_IPFILTER */
+ skb->dev = &brdev->net_dev;
+- ATM_SKB(skb)->vcc = atmvcc; /* needed ? */
++ /* ATM_SKB(skb)->vcc = atmvcc; *//* needed ? */
+ DPRINTK("received packet's protocol: %x\n", ntohs(skb->protocol));
+ skb_debug(skb);
+- if (!(brdev->net_dev.flags & IFF_UP)) { /* sigh, interface is down */
++ if (!(brdev->net_dev.flags & IFF_UP)) { /* sigh, interface is down */
+ brdev->stats.rx_dropped++;
+ dev_kfree_skb(skb);
+ return;
+ }
+ brdev->stats.rx_packets++;
+ brdev->stats.rx_bytes += skb->len;
+- memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
+ netif_rx(skb);
+ }
+
+@@ -525,10 +625,10 @@
+ err = -EEXIST;
+ goto error;
+ }
+- if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO ||
+- be.fcs_auto || be.has_vpiid || be.send_padding || (be.encaps !=
+- BR2684_ENCAPS_VC && be.encaps != BR2684_ENCAPS_LLC) ||
+- be.min_size != 0) {
++ if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO
++ || be.fcs_auto || be.has_vpiid || be.send_padding
++ || (be.encaps != BR2684_ENCAPS_VC
++ && be.encaps != BR2684_ENCAPS_LLC) || be.min_size != 0) {
+ err = -EINVAL;
+ goto error;
+ }
+@@ -554,18 +654,21 @@
+ brvcc->atmvcc = atmvcc;
+ atmvcc->user_back = brvcc;
+ brvcc->encaps = (enum br2684_encaps) be.encaps;
++ brvcc->payload = (enum br2684_payload) be.payload;
+ brvcc->old_push = atmvcc->push;
+ barrier();
+ atmvcc->push = br2684_push;
+ skb_queue_head_init(&copy);
+ skb_migrate(&atmvcc->sk->receive_queue, &copy);
+ while ((skb = skb_dequeue(&copy))) {
++#ifdef notdef
+ BRPRIV(skb->dev)->stats.rx_bytes -= skb->len;
+ BRPRIV(skb->dev)->stats.rx_packets--;
++#endif
+ br2684_push(atmvcc, skb);
+ }
+ return 0;
+- error:
++ error:
+ write_unlock_irq(&devs_lock);
+ MOD_DEC_USE_COUNT;
+ return err;
+@@ -608,12 +711,25 @@
+
+ if (ni.ifname[0] != '\0') {
+ memcpy(brdev->net_dev.name, ni.ifname,
+- sizeof(brdev->net_dev.name));
+- brdev->net_dev.name[sizeof(brdev->net_dev.name) - 1] = '\0';
++ sizeof(brdev->net_dev.name));
++ brdev->net_dev.name[sizeof(brdev->net_dev.name) - 1] =
++ '\0';
+ } else
+ sprintf(brdev->net_dev.name, "nas%d", brdev->number);
+ DPRINTK("registered netdev %s\n", brdev->net_dev.name);
+- ether_setup(&brdev->net_dev);
++ if (ni.payload == p_routed) {
++ brdev->net_dev.hard_header_len = 0;
++ brdev->net_dev.addr_len = 0;
++ brdev->net_dev.mtu = 1500;
++
++ /* Type PPP seems most suitable */
++ brdev->net_dev.type = ARPHRD_PPP;
++ brdev->net_dev.flags =
++ IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
++ brdev->net_dev.tx_queue_len = 100;
++ } else {
++ ether_setup(&brdev->net_dev);
++ }
+ brdev->mac_was_set = 0;
+ #ifdef FASTER_VERSION
+ my_eth_header = brdev->net_dev.hard_header;
+@@ -677,12 +793,11 @@
+ err = br2684_setfilt(atmvcc, arg);
+ MOD_DEC_USE_COUNT;
+ return err;
+-#endif /* CONFIG_ATM_BR2684_IPFILTER */
++#endif /* CONFIG_ATM_BR2684_IPFILTER */
+ }
+ return -ENOIOCTLCMD;
+ }
+
+-#ifdef CONFIG_PROC_FS
+ /* Never put more than 256 bytes in at once */
+ static int br2684_proc_engine(loff_t pos, char *buf)
+ {
+@@ -692,52 +807,62 @@
+ list_for_each(lhd, &br2684_devs) {
+ brdev = list_entry_brdev(lhd);
+ if (pos-- == 0)
+- return sprintf(buf, "dev %.16s: num=%d, mac=%02X:%02X:"
+- "%02X:%02X:%02X:%02X (%s)\n", brdev->net_dev.name,
+- brdev->number,
+- brdev->net_dev.dev_addr[0],
+- brdev->net_dev.dev_addr[1],
+- brdev->net_dev.dev_addr[2],
+- brdev->net_dev.dev_addr[3],
+- brdev->net_dev.dev_addr[4],
+- brdev->net_dev.dev_addr[5],
+- brdev->mac_was_set ? "set" : "auto");
++ return sprintf(buf,
++ "dev %.16s: num=%d, mac=%02X:%02X:"
++ "%02X:%02X:%02X:%02X (%s)\n",
++ brdev->net_dev.name, brdev->number,
++ brdev->net_dev.dev_addr[0],
++ brdev->net_dev.dev_addr[1],
++ brdev->net_dev.dev_addr[2],
++ brdev->net_dev.dev_addr[3],
++ brdev->net_dev.dev_addr[4],
++ brdev->net_dev.dev_addr[5],
++ brdev->
++ mac_was_set ? "set" : "auto");
+ list_for_each(lhc, &brdev->brvccs) {
+ brvcc = list_entry_brvcc(lhc);
+ if (pos-- == 0)
+- return sprintf(buf, " vcc %d.%d.%d: encaps=%s"
++ return sprintf(buf,
++ " vcc %d.%d.%d: encaps=%s"
++ ", payload=%s"
+ #ifndef FASTER_VERSION
+- ", failed copies %u/%u"
+-#endif /* FASTER_VERSION */
+- "\n", brvcc->atmvcc->dev->number,
+- brvcc->atmvcc->vpi, brvcc->atmvcc->vci,
+- (brvcc->encaps == e_llc) ? "LLC" : "VC"
++ ", failed copies %u/%u"
++#endif /* FASTER_VERSION */
++ "\n",
++ brvcc->atmvcc->dev->number,
++ brvcc->atmvcc->vpi,
++ brvcc->atmvcc->vci,
++ (brvcc->encaps ==
++ e_llc) ? "LLC" : "VC",
++ (brvcc->payload ==
++ p_bridged) ? "bridged" :
++ "routed"
+ #ifndef FASTER_VERSION
+- , brvcc->copies_failed
+- , brvcc->copies_needed
+-#endif /* FASTER_VERSION */
++ , brvcc->copies_failed,
++ brvcc->copies_needed
++#endif /* FASTER_VERSION */
+ );
+ #ifdef CONFIG_ATM_BR2684_IPFILTER
+ #define b1(var, byte) ((u8 *) &brvcc->filter.var)[byte]
+ #define bs(var) b1(var, 0), b1(var, 1), b1(var, 2), b1(var, 3)
+ if (brvcc->filter.netmask != 0 && pos-- == 0)
+- return sprintf(buf, " filter=%d.%d.%d.%d/"
+- "%d.%d.%d.%d\n", bs(prefix), bs(netmask));
++ return sprintf(buf,
++ " filter=%d.%d.%d.%d/"
++ "%d.%d.%d.%d\n", bs(prefix),
++ bs(netmask));
+ #undef bs
+ #undef b1
+-#endif /* CONFIG_ATM_BR2684_IPFILTER */
++#endif /* CONFIG_ATM_BR2684_IPFILTER */
+ }
+ }
+ return 0;
+ }
+
+ static ssize_t br2684_proc_read(struct file *file, char *buf, size_t count,
+- loff_t *pos)
++ loff_t * pos)
+ {
+ unsigned long page;
+ int len = 0, x, left;
+- loff_t n = *pos;
+-
+ page = get_free_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+@@ -746,7 +871,7 @@
+ left = count;
+ read_lock(&devs_lock);
+ for (;;) {
+- x = br2684_proc_engine(n, &((char *) page)[len]);
++ x = br2684_proc_engine(*pos, &((char *) page)[len]);
+ if (x == 0)
+ break;
+ if (x > left)
+@@ -761,12 +886,11 @@
+ }
+ len += x;
+ left -= x;
+- n++;
++ (*pos)++;
+ if (left < 256)
+ break;
+ }
+ read_unlock(&devs_lock);
+- *pos = n;
+ if (len > 0 && copy_to_user(buf, (char *) page, len))
+ len = -EFAULT;
+ free_page(page);
+@@ -774,23 +898,20 @@
+ }
+
+ static struct file_operations br2684_proc_operations = {
+- read: br2684_proc_read,
++ read:br2684_proc_read,
+ };
+
+ extern struct proc_dir_entry *atm_proc_root; /* from proc.c */
+-#endif /* CONFIG_PROC_FS */
+
+ /* the following avoids some spurious warnings from the compiler */
+ #define UNUSED __attribute__((unused))
+
+ static int __init UNUSED br2684_init(void)
+ {
+-#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *p;
+ if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL)
+ return -ENOMEM;
+ p->proc_fops = &br2684_proc_operations;
+-#endif /* CONFIG_PROC_FS */
+ br2684_ioctl_set(br2684_ioctl);
+ return 0;
+ }
+@@ -799,9 +920,7 @@
+ {
+ struct br2684_dev *brdev;
+ br2684_ioctl_set(NULL);
+-#ifdef CONFIG_PROC_FS
+ remove_proc_entry("br2684", atm_proc_root);
+-#endif /* CONFIG_PROC_FS */
+ while (!list_empty(&br2684_devs)) {
+ brdev = list_entry_brdev(br2684_devs.next);
+ unregister_netdev(&brdev->net_dev);
+diff -urN linux-2.4.32/net/atm/common.c linux-2.4.32.new/net/atm/common.c
+--- linux-2.4.32/net/atm/common.c 2004-02-18 14:36:32.000000000 +0100
++++ linux-2.4.32.new/net/atm/common.c 2006-02-06 17:26:52.000000000 +0100
+@@ -158,6 +158,7 @@
+ }
+ #ifdef CONFIG_ATM_BR2684_MODULE
+ EXPORT_SYMBOL(br2684_ioctl_set);
++EXPORT_SYMBOL(br2684_ioctl_hook);
+ #endif
+ #endif
+
+--- linux-2.4.32/include/linux/atmbr2684.h 2002-08-03 02:39:45.000000000 +0200
++++ linux-2.4.32.new/include/linux/atmbr2684.h 2006-02-06 19:01:24.000000000 +0100
+@@ -3,6 +3,7 @@
+
+ #include <linux/atm.h>
+ #include <linux/if.h> /* For IFNAMSIZ */
++#include <linux/if_ether.h> /* ETH_P_* */
+
+ /*
+ * Type of media we're bridging (ethernet, token ring, etc) Currently only
+@@ -36,15 +37,24 @@
+ #define BR2684_ENCAPS_AUTODETECT (2) /* Unsuported */
+
+ /*
++ * Is this VC bridged or routed?
++ */
++
++#define BR2684_PAYLOAD_ROUTED (0)
++#define BR2684_PAYLOAD_BRIDGED (1)
++
++
++/*
+ * This is for the ATM_NEWBACKENDIF call - these are like socket families:
+ * the first element of the structure is the backend number and the rest
+ * is per-backend specific
+ */
+ struct atm_newif_br2684 {
+- atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */
+- int media; /* BR2684_MEDIA_* */
+- char ifname[IFNAMSIZ];
+- int mtu;
++ atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */
++ int media; /* BR2684_MEDIA_* */
++ char ifname[IFNAMSIZ];
++ int mtu;
++ int payload; /* bridged or routed */
+ };
+
+ /*
+@@ -68,16 +78,17 @@
+ * is per-backend specific
+ */
+ struct atm_backend_br2684 {
+- atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */
++ atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */
+ struct br2684_if_spec ifspec;
+- int fcs_in; /* BR2684_FCSIN_* */
+- int fcs_out; /* BR2684_FCSOUT_* */
+- int fcs_auto; /* 1: fcs_{in,out} disabled if no FCS rx'ed */
+- int encaps; /* BR2684_ENCAPS_* */
+- int has_vpiid; /* 1: use vpn_id - Unsupported */
+- __u8 vpn_id[7];
+- int send_padding; /* unsupported */
+- int min_size; /* we will pad smaller packets than this */
++ int fcs_in; /* BR2684_FCSIN_* */
++ int fcs_out; /* BR2684_FCSOUT_* */
++ int fcs_auto; /* 1: fcs_{in,out} disabled if no FCS rx'ed */
++ int encaps; /* BR2684_ENCAPS_* */
++ int payload; /* BR2684_PAYLOAD_* */
++ int has_vpiid; /* 1: use vpn_id - Unsupported */
++ __u8 vpn_id[7];
++ int send_padding; /* unsupported */
++ int min_size; /* we will pad smaller packets than this */
+ };
+
+ /*
+@@ -95,7 +106,12 @@
+ struct br2684_filter filter;
+ };
+
++enum br2684_payload {
++ p_routed = BR2684_PAYLOAD_ROUTED,
++ p_bridged = BR2684_PAYLOAD_BRIDGED,
++};
++
+ #define BR2684_SETFILT _IOW( 'a', ATMIOC_BACKEND + 0, \
+ struct br2684_filter_set)
+
+-#endif /* _LINUX_ATMBR2684_H */
++#endif /* _LINUX_ATMBR2684_H */
diff --git a/target/linux/generic-2.4/patches/227-jffs2_eofdetect.patch b/target/linux/generic-2.4/patches/227-jffs2_eofdetect.patch
new file mode 100644
index 0000000000..fe97be5b3f
--- /dev/null
+++ b/target/linux/generic-2.4/patches/227-jffs2_eofdetect.patch
@@ -0,0 +1,97 @@
+diff -ur linux.old/fs/jffs2/build.c linux.dev/fs/jffs2/build.c
+--- linux.old/fs/jffs2/build.c 2003-06-13 16:51:37.000000000 +0200
++++ linux.dev/fs/jffs2/build.c 2006-06-23 22:15:21.000000000 +0200
+@@ -31,6 +31,10 @@
+ * provisions above, a recipient may use your version of this file
+ * under either the RHEPL or the GPL.
+ *
++ * Modification for automatically cleaning the filesystem after
++ * a specially marked block
++ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
++ *
+ * $Id: build.c,v 1.16.2.3 2003/04/30 09:43:32 dwmw2 Exp $
+ *
+ */
+@@ -38,6 +42,7 @@
+ #include <linux/kernel.h>
+ #include <linux/jffs2.h>
+ #include <linux/slab.h>
++#include <linux/mtd/mtd.h>
+ #include "nodelist.h"
+
+ int jffs2_build_inode_pass1(struct jffs2_sb_info *, struct jffs2_inode_cache *);
+@@ -89,6 +94,18 @@
+ if (ret)
+ return ret;
+
++ if (c->flags & (1 << 7)) {
++ printk("%s(): unlocking the mtd device... ", __func__);
++ if (c->mtd->unlock)
++ c->mtd->unlock(c->mtd, 0, c->mtd->size);
++ printk("done.\n");
++
++ printk("%s(): erasing all blocks after the end marker... ", __func__);
++ jffs2_erase_pending_blocks(c);
++ jffs2_mark_erased_blocks(c);
++ printk("done.\n");
++ }
++
+ D1(printk(KERN_DEBUG "Scanned flash completely\n"));
+ /* Now build the data map for each inode, marking obsoleted nodes
+ as such, and also increase nlink of any children. */
+diff -ur linux.old/fs/jffs2/scan.c linux.dev/fs/jffs2/scan.c
+--- linux.old/fs/jffs2/scan.c 2006-06-23 21:57:32.000000000 +0200
++++ linux.dev/fs/jffs2/scan.c 2006-06-23 22:01:35.000000000 +0200
+@@ -31,6 +31,10 @@
+ * provisions above, a recipient may use your version of this file
+ * under either the RHEPL or the GPL.
+ *
++ * Modification for automatically cleaning the filesystem after
++ * a specially marked block
++ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
++ *
+ * $Id: scan.c,v 1.51.2.4 2003/11/02 13:51:18 dwmw2 Exp $
+ *
+ */
+@@ -88,7 +92,12 @@
+ for (i=0; i<c->nr_blocks; i++) {
+ struct jffs2_eraseblock *jeb = &c->blocks[i];
+
+- ret = jffs2_scan_eraseblock(c, jeb);
++
++ if (c->flags & (1 << 7))
++ ret = 1;
++ else
++ ret = jffs2_scan_eraseblock(c, jeb);
++
+ if (ret < 0)
+ return ret;
+
+@@ -181,6 +190,7 @@
+
+ while(ofs < jeb->offset + c->sector_size) {
+ ssize_t retlen;
++ unsigned char *buf = (unsigned char *) &node;
+ ACCT_PARANOIA_CHECK(jeb);
+
+ if (ofs & 3) {
+@@ -202,8 +212,18 @@
+ break;
+ }
+
+- err = c->mtd->read(c->mtd, ofs, sizeof(node), &retlen, (char *)&node);
++ err = c->mtd->read(c->mtd, ofs, sizeof(node), &retlen, buf);
++ if ((buf[0] == 0xde) &&
++ (buf[1] == 0xad) &&
++ (buf[2] == 0xc0) &&
++ (buf[3] == 0xde)) {
++
++ /* end of filesystem. erase everything after this point */
++ c->flags |= (1 << 7);
++ printk("jffs2_scan_eraseblock(): End of filesystem marker found at 0x%x\n", jeb->offset);
+
++ return 1;
++ }
+ if (err) {
+ D1(printk(KERN_WARNING "mtd->read(0x%x bytes from 0x%x) returned %d\n", sizeof(node), ofs, err));
+ return err;
diff --git a/target/linux/generic-2.4/patches/228-more_usb_fixes.patch b/target/linux/generic-2.4/patches/228-more_usb_fixes.patch
new file mode 100644
index 0000000000..40b24cac0f
--- /dev/null
+++ b/target/linux/generic-2.4/patches/228-more_usb_fixes.patch
@@ -0,0 +1,861 @@
+diff -ur linux.old/drivers/scsi/hosts.c linux.dev/drivers/scsi/hosts.c
+--- linux.old/drivers/scsi/hosts.c 2003-06-13 16:51:36.000000000 +0200
++++ linux.dev/drivers/scsi/hosts.c 2006-07-30 12:34:30.000000000 +0200
+@@ -107,8 +107,21 @@
+ if (shn) shn->host_registered = 0;
+ /* else {} : This should not happen, we should panic here... */
+
++ /* If we are removing the last host registered, it is safe to reuse
++ * its host number (this avoids "holes" at boot time) (DB)
++ * It is also safe to reuse those of numbers directly below which have
++ * been released earlier (to avoid some holes in numbering).
++ */
++ if(sh->host_no == max_scsi_hosts - 1) {
++ while(--max_scsi_hosts >= next_scsi_host) {
++ shpnt = scsi_hostlist;
++ while(shpnt && shpnt->host_no != max_scsi_hosts - 1)
++ shpnt = shpnt->next;
++ if(shpnt)
++ break;
++ }
++ }
+ next_scsi_host--;
+-
+ kfree((char *) sh);
+ }
+
+diff -ur linux.old/drivers/usb/hcd.c linux.dev/drivers/usb/hcd.c
+--- linux.old/drivers/usb/hcd.c 2004-04-14 15:05:32.000000000 +0200
++++ linux.dev/drivers/usb/hcd.c 2006-07-30 11:49:06.000000000 +0200
+@@ -1105,7 +1105,8 @@
+ break;
+ case PIPE_BULK:
+ allowed |= USB_DISABLE_SPD | USB_QUEUE_BULK
+- | USB_ZERO_PACKET | URB_NO_INTERRUPT;
++ | USB_ZERO_PACKET | URB_NO_INTERRUPT
++ | URB_NO_TRANSFER_DMA_MAP;
+ break;
+ case PIPE_INTERRUPT:
+ allowed |= USB_DISABLE_SPD;
+@@ -1212,7 +1213,8 @@
+ urb->setup_packet,
+ sizeof (struct usb_ctrlrequest),
+ PCI_DMA_TODEVICE);
+- if (urb->transfer_buffer_length != 0)
++ if (urb->transfer_buffer_length != 0
++ && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+ urb->transfer_dma = pci_map_single (
+ hcd->pdev,
+ urb->transfer_buffer,
+diff -ur linux.old/drivers/usb/host/ehci-hcd.c linux.dev/drivers/usb/host/ehci-hcd.c
+--- linux.old/drivers/usb/host/ehci-hcd.c 2006-07-30 11:31:57.000000000 +0200
++++ linux.dev/drivers/usb/host/ehci-hcd.c 2006-07-30 11:48:14.000000000 +0200
+@@ -399,6 +399,27 @@
+ ehci_mem_cleanup (ehci);
+ return retval;
+ }
++
++{
++ int misc_reg;
++ u32 vendor_id;
++
++ pci_read_config_dword (ehci->hcd.pdev, PCI_VENDOR_ID, &vendor_id);
++ if (vendor_id == 0x31041106) {
++ /* VIA 6212 */
++ printk(KERN_INFO "EHCI: Enabling VIA 6212 workarounds\n", misc_reg);
++ pci_read_config_byte(ehci->hcd.pdev, 0x49, &misc_reg);
++ misc_reg &= ~0x20;
++ pci_write_config_byte(ehci->hcd.pdev, 0x49, misc_reg);
++ pci_read_config_byte(ehci->hcd.pdev, 0x49, &misc_reg);
++
++ pci_read_config_byte(ehci->hcd.pdev, 0x4b, &misc_reg);
++ misc_reg |= 0x20;
++ pci_write_config_byte(ehci->hcd.pdev, 0x4b, misc_reg);
++ pci_read_config_byte(ehci->hcd.pdev, 0x4b, &misc_reg);
++ }
++}
++
+ writel (INTR_MASK, &ehci->regs->intr_enable);
+ writel (ehci->periodic_dma, &ehci->regs->frame_list);
+
+diff -ur linux.old/drivers/usb/host/ehci-q.c linux.dev/drivers/usb/host/ehci-q.c
+--- linux.old/drivers/usb/host/ehci-q.c 2006-07-30 11:31:57.000000000 +0200
++++ linux.dev/drivers/usb/host/ehci-q.c 2006-07-30 12:10:15.000000000 +0200
+@@ -791,6 +791,8 @@
+ writel (cmd, &ehci->regs->command);
+ ehci->hcd.state = USB_STATE_RUNNING;
+ /* posted write need not be known to HC yet ... */
++
++ timer_action (ehci, TIMER_IO_WATCHDOG);
+ }
+ }
+
+diff -ur linux.old/drivers/usb/host/usb-uhci.c linux.dev/drivers/usb/host/usb-uhci.c
+--- linux.old/drivers/usb/host/usb-uhci.c 2004-11-17 12:54:21.000000000 +0100
++++ linux.dev/drivers/usb/host/usb-uhci.c 2006-07-30 12:10:16.000000000 +0200
+@@ -2491,7 +2491,7 @@
+ ((urb_priv_t*)urb->hcpriv)->flags=0;
+ }
+
+- if ((urb->status != -ECONNABORTED) && (urb->status != ECONNRESET) &&
++ if ((urb->status != -ECONNABORTED) && (urb->status != -ECONNRESET) &&
+ (urb->status != -ENOENT)) {
+
+ urb->status = -EINPROGRESS;
+@@ -3034,6 +3034,21 @@
+
+ pci_set_master(dev);
+
++ {
++ u8 misc_reg;
++ u32 vendor_id;
++
++ pci_read_config_dword (dev, PCI_VENDOR_ID, &vendor_id);
++ if (vendor_id == 0x30381106) {
++ /* VIA 6212 */
++ printk(KERN_INFO "UHCI: Enabling VIA 6212 workarounds\n");
++ pci_read_config_byte(dev, 0x41, &misc_reg);
++ misc_reg &= ~0x10;
++ pci_write_config_byte(dev, 0x41, misc_reg);
++ pci_read_config_byte(dev, 0x41, &misc_reg);
++ }
++ }
++
+ /* Search for the IO base address.. */
+ for (i = 0; i < 6; i++) {
+
+diff -ur linux.old/drivers/usb/storage/transport.c linux.dev/drivers/usb/storage/transport.c
+--- linux.old/drivers/usb/storage/transport.c 2005-04-04 03:42:19.000000000 +0200
++++ linux.dev/drivers/usb/storage/transport.c 2006-07-30 12:22:56.000000000 +0200
+@@ -54,6 +54,22 @@
+ #include <linux/sched.h>
+ #include <linux/errno.h>
+ #include <linux/slab.h>
++#include <linux/pci.h>
++#include "../hcd.h"
++
++/* These definitions mirror those in pci.h, so they can be used
++ * interchangeably with their PCI_ counterparts */
++enum dma_data_direction {
++ DMA_BIDIRECTIONAL = 0,
++ DMA_TO_DEVICE = 1,
++ DMA_FROM_DEVICE = 2,
++ DMA_NONE = 3,
++};
++
++#define dma_map_sg(d,s,n,dir) pci_map_sg(d,s,n,dir)
++#define dma_unmap_sg(d,s,n,dir) pci_unmap_sg(d,s,n,dir)
++
++
+
+ /***********************************************************************
+ * Helper routines
+@@ -554,6 +570,543 @@
+ return US_BULK_TRANSFER_SHORT;
+ }
+
++/*-------------------------------------------------------------------*/
++/**
++ * usb_buffer_unmap_sg - free DMA mapping(s) for a scatterlist
++ * @dev: device to which the scatterlist will be mapped
++ * @pipe: endpoint defining the mapping direction
++ * @sg: the scatterlist to unmap
++ * @n_hw_ents: the positive return value from usb_buffer_map_sg
++ *
++ * Reverses the effect of usb_buffer_map_sg().
++ */
++static void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
++ struct scatterlist *sg, int n_hw_ents)
++{
++ struct usb_bus *bus;
++ struct usb_hcd *hcd;
++ struct pci_dev *pdev;
++
++ if (!dev
++ || !(bus = dev->bus)
++ || !(hcd = bus->hcpriv)
++ || !(pdev = hcd->pdev)
++ || !pdev->dma_mask)
++ return;
++
++ dma_unmap_sg (pdev, sg, n_hw_ents,
++ usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
++}
++
++/**
++ * usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint
++ * @dev: device to which the scatterlist will be mapped
++ * @pipe: endpoint defining the mapping direction
++ * @sg: the scatterlist to map
++ * @nents: the number of entries in the scatterlist
++ *
++ * Return value is either < 0 (indicating no buffers could be mapped), or
++ * the number of DMA mapping array entries in the scatterlist.
++ *
++ * The caller is responsible for placing the resulting DMA addresses from
++ * the scatterlist into URB transfer buffer pointers, and for setting the
++ * URB_NO_TRANSFER_DMA_MAP transfer flag in each of those URBs.
++ *
++ * Top I/O rates come from queuing URBs, instead of waiting for each one
++ * to complete before starting the next I/O. This is particularly easy
++ * to do with scatterlists. Just allocate and submit one URB for each DMA
++ * mapping entry returned, stopping on the first error or when all succeed.
++ * Better yet, use the usb_sg_*() calls, which do that (and more) for you.
++ *
++ * This call would normally be used when translating scatterlist requests,
++ * rather than usb_buffer_map(), since on some hardware (with IOMMUs) it
++ * may be able to coalesce mappings for improved I/O efficiency.
++ *
++ * Reverse the effect of this call with usb_buffer_unmap_sg().
++ */
++static int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
++ struct scatterlist *sg, int nents)
++{
++ struct usb_bus *bus;
++ struct usb_hcd *hcd;
++ struct pci_dev *pdev;
++
++ if (!dev
++ || usb_pipecontrol (pipe)
++ || !(bus = dev->bus)
++ || !(hcd = bus->hcpriv)
++ || !(pdev = hcd->pdev)
++ || !pdev->dma_mask)
++ return -1;
++
++ // FIXME generic api broken like pci, can't report errors
++ return dma_map_sg (pdev, sg, nents,
++ usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
++}
++
++static void sg_clean (struct usb_sg_request *io)
++{
++ struct usb_hcd *hcd = io->dev->bus->hcpriv;
++ struct pci_dev *pdev = hcd->pdev;
++
++ if (io->urbs) {
++ while (io->entries--)
++ usb_free_urb (io->urbs [io->entries]);
++ kfree (io->urbs);
++ io->urbs = 0;
++ }
++ if (pdev->dma_mask != 0)
++ usb_buffer_unmap_sg (io->dev, io->pipe, io->sg, io->nents);
++ io->dev = 0;
++}
++
++static void sg_complete (struct urb *urb)
++{
++ struct usb_sg_request *io = (struct usb_sg_request *) urb->context;
++
++ spin_lock (&io->lock);
++
++ /* In 2.5 we require hcds' endpoint queues not to progress after fault
++ * reports, until the completion callback (this!) returns. That lets
++ * device driver code (like this routine) unlink queued urbs first,
++ * if it needs to, since the HC won't work on them at all. So it's
++ * not possible for page N+1 to overwrite page N, and so on.
++ *
++ * That's only for "hard" faults; "soft" faults (unlinks) sometimes
++ * complete before the HCD can get requests away from hardware,
++ * though never during cleanup after a hard fault.
++ */
++ if (io->status
++ && (io->status != -ECONNRESET
++ || urb->status != -ECONNRESET)
++ && urb->actual_length) {
++ US_DEBUGP("Error: %s ep%d%s scatterlist error %d/%d\n",
++ io->dev->devpath,
++ usb_pipeendpoint (urb->pipe),
++ usb_pipein (urb->pipe) ? "in" : "out",
++ urb->status, io->status);
++ // BUG ();
++ }
++
++ if (urb->status && urb->status != -ECONNRESET) {
++ int i, found, status;
++
++ io->status = urb->status;
++
++ /* the previous urbs, and this one, completed already.
++ * unlink pending urbs so they won't rx/tx bad data.
++ */
++ for (i = 0, found = 0; i < io->entries; i++) {
++ if (!io->urbs [i])
++ continue;
++ if (found) {
++ status = usb_unlink_urb (io->urbs [i]);
++ if (status != -EINPROGRESS && status != -EBUSY)
++ US_DEBUGP("Error: %s, unlink --> %d\n", __FUNCTION__, status);
++ } else if (urb == io->urbs [i])
++ found = 1;
++ }
++ }
++ urb->dev = 0;
++
++ /* on the last completion, signal usb_sg_wait() */
++ io->bytes += urb->actual_length;
++ io->count--;
++ if (!io->count)
++ complete (&io->complete);
++
++ spin_unlock (&io->lock);
++}
++
++/**
++ * usb_sg_init - initializes scatterlist-based bulk/interrupt I/O request
++ * @io: request block being initialized. until usb_sg_wait() returns,
++ * treat this as a pointer to an opaque block of memory,
++ * @dev: the usb device that will send or receive the data
++ * @pipe: endpoint "pipe" used to transfer the data
++ * @period: polling rate for interrupt endpoints, in frames or
++ * (for high speed endpoints) microframes; ignored for bulk
++ * @sg: scatterlist entries
++ * @nents: how many entries in the scatterlist
++ * @length: how many bytes to send from the scatterlist, or zero to
++ * send every byte identified in the list.
++ * @mem_flags: SLAB_* flags affecting memory allocations in this call
++ *
++ * Returns zero for success, else a negative errno value. This initializes a
++ * scatter/gather request, allocating resources such as I/O mappings and urb
++ * memory (except maybe memory used by USB controller drivers).
++ *
++ * The request must be issued using usb_sg_wait(), which waits for the I/O to
++ * complete (or to be canceled) and then cleans up all resources allocated by
++ * usb_sg_init().
++ *
++ * The request may be canceled with usb_sg_cancel(), either before or after
++ * usb_sg_wait() is called.
++ */
++int usb_sg_init (
++ struct usb_sg_request *io,
++ struct usb_device *dev,
++ unsigned pipe,
++ unsigned period,
++ struct scatterlist *sg,
++ int nents,
++ size_t length,
++ int mem_flags
++)
++{
++ int i;
++ int urb_flags;
++ int dma;
++ struct usb_hcd *hcd;
++
++ hcd = dev->bus->hcpriv;
++
++ if (!io || !dev || !sg
++ || usb_pipecontrol (pipe)
++ || usb_pipeisoc (pipe)
++ || nents <= 0)
++ return -EINVAL;
++
++ spin_lock_init (&io->lock);
++ io->dev = dev;
++ io->pipe = pipe;
++ io->sg = sg;
++ io->nents = nents;
++
++ /* not all host controllers use DMA (like the mainstream pci ones);
++ * they can use PIO (sl811) or be software over another transport.
++ */
++ dma = (hcd->pdev->dma_mask != 0);
++ if (dma)
++ io->entries = usb_buffer_map_sg (dev, pipe, sg, nents);
++ else
++ io->entries = nents;
++
++ /* initialize all the urbs we'll use */
++ if (io->entries <= 0)
++ return io->entries;
++
++ io->count = 0;
++ io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags);
++ if (!io->urbs)
++ goto nomem;
++
++ urb_flags = USB_ASYNC_UNLINK | URB_NO_INTERRUPT | URB_NO_TRANSFER_DMA_MAP;
++ if (usb_pipein (pipe))
++ urb_flags |= URB_SHORT_NOT_OK;
++
++ for (i = 0; i < io->entries; i++, io->count = i) {
++ unsigned len;
++
++ io->urbs [i] = usb_alloc_urb (0);
++ if (!io->urbs [i]) {
++ io->entries = i;
++ goto nomem;
++ }
++
++ io->urbs [i]->dev = 0;
++ io->urbs [i]->pipe = pipe;
++ io->urbs [i]->interval = period;
++ io->urbs [i]->transfer_flags = urb_flags;
++
++ io->urbs [i]->complete = sg_complete;
++ io->urbs [i]->context = io;
++ io->urbs [i]->status = -EINPROGRESS;
++ io->urbs [i]->actual_length = 0;
++
++ if (dma) {
++ /* hc may use _only_ transfer_dma */
++ io->urbs [i]->transfer_dma = sg_dma_address (sg + i);
++ len = sg_dma_len (sg + i);
++ } else {
++ /* hc may use _only_ transfer_buffer */
++ io->urbs [i]->transfer_buffer =
++ page_address (sg [i].page) + sg [i].offset;
++ len = sg [i].length;
++ }
++
++ if (length) {
++ len = min_t (unsigned, len, length);
++ length -= len;
++ if (length == 0)
++ io->entries = i + 1;
++ }
++ io->urbs [i]->transfer_buffer_length = len;
++ }
++ io->urbs [--i]->transfer_flags &= ~URB_NO_INTERRUPT;
++
++ /* transaction state */
++ io->status = 0;
++ io->bytes = 0;
++ init_completion (&io->complete);
++ return 0;
++
++nomem:
++ sg_clean (io);
++ return -ENOMEM;
++}
++
++/**
++ * usb_sg_cancel - stop scatter/gather i/o issued by usb_sg_wait()
++ * @io: request block, initialized with usb_sg_init()
++ *
++ * This stops a request after it has been started by usb_sg_wait().
++ * It can also prevents one initialized by usb_sg_init() from starting,
++ * so that call just frees resources allocated to the request.
++ */
++void usb_sg_cancel (struct usb_sg_request *io)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave (&io->lock, flags);
++
++ /* shut everything down, if it didn't already */
++ if (!io->status) {
++ int i;
++
++ io->status = -ECONNRESET;
++ for (i = 0; i < io->entries; i++) {
++ int retval;
++
++ if (!io->urbs [i]->dev)
++ continue;
++ retval = usb_unlink_urb (io->urbs [i]);
++ if (retval != -EINPROGRESS && retval != -EBUSY)
++ US_DEBUGP("WARNING: %s, unlink --> %d\n", __FUNCTION__, retval);
++ }
++ }
++ spin_unlock_irqrestore (&io->lock, flags);
++}
++
++/**
++ * usb_sg_wait - synchronously execute scatter/gather request
++ * @io: request block handle, as initialized with usb_sg_init().
++ * some fields become accessible when this call returns.
++ * Context: !in_interrupt ()
++ *
++ * This function blocks until the specified I/O operation completes. It
++ * leverages the grouping of the related I/O requests to get good transfer
++ * rates, by queueing the requests. At higher speeds, such queuing can
++ * significantly improve USB throughput.
++ *
++ * There are three kinds of completion for this function.
++ * (1) success, where io->status is zero. The number of io->bytes
++ * transferred is as requested.
++ * (2) error, where io->status is a negative errno value. The number
++ * of io->bytes transferred before the error is usually less
++ * than requested, and can be nonzero.
++ * (3) cancelation, a type of error with status -ECONNRESET that
++ * is initiated by usb_sg_cancel().
++ *
++ * When this function returns, all memory allocated through usb_sg_init() or
++ * this call will have been freed. The request block parameter may still be
++ * passed to usb_sg_cancel(), or it may be freed. It could also be
++ * reinitialized and then reused.
++ *
++ * Data Transfer Rates:
++ *
++ * Bulk transfers are valid for full or high speed endpoints.
++ * The best full speed data rate is 19 packets of 64 bytes each
++ * per frame, or 1216 bytes per millisecond.
++ * The best high speed data rate is 13 packets of 512 bytes each
++ * per microframe, or 52 KBytes per millisecond.
++ *
++ * The reason to use interrupt transfers through this API would most likely
++ * be to reserve high speed bandwidth, where up to 24 KBytes per millisecond
++ * could be transferred. That capability is less useful for low or full
++ * speed interrupt endpoints, which allow at most one packet per millisecond,
++ * of at most 8 or 64 bytes (respectively).
++ */
++void usb_sg_wait (struct usb_sg_request *io)
++{
++ int i, entries = io->entries;
++
++ /* queue the urbs. */
++ spin_lock_irq (&io->lock);
++ for (i = 0; i < entries && !io->status; i++) {
++ int retval;
++
++ io->urbs [i]->dev = io->dev;
++ retval = usb_submit_urb (io->urbs [i]);
++
++ /* after we submit, let completions or cancelations fire;
++ * we handshake using io->status.
++ */
++ spin_unlock_irq (&io->lock);
++ switch (retval) {
++ /* maybe we retrying will recover */
++ case -ENXIO: // hc didn't queue this one
++ case -EAGAIN:
++ case -ENOMEM:
++ io->urbs [i]->dev = 0;
++ retval = 0;
++ i--;
++ yield ();
++ break;
++
++ /* no error? continue immediately.
++ *
++ * NOTE: to work better with UHCI (4K I/O buffer may
++ * need 3K of TDs) it may be good to limit how many
++ * URBs are queued at once; N milliseconds?
++ */
++ case 0:
++ cpu_relax ();
++ break;
++
++ /* fail any uncompleted urbs */
++ default:
++ spin_lock_irq (&io->lock);
++ io->count -= entries - i;
++ if (io->status == -EINPROGRESS)
++ io->status = retval;
++ if (io->count == 0)
++ complete (&io->complete);
++ spin_unlock_irq (&io->lock);
++
++ io->urbs [i]->dev = 0;
++ io->urbs [i]->status = retval;
++
++ US_DEBUGP("%s, submit --> %d\n", __FUNCTION__, retval);
++ usb_sg_cancel (io);
++ }
++ spin_lock_irq (&io->lock);
++ if (retval && io->status == -ECONNRESET)
++ io->status = retval;
++ }
++ spin_unlock_irq (&io->lock);
++
++ /* OK, yes, this could be packaged as non-blocking.
++ * So could the submit loop above ... but it's easier to
++ * solve neither problem than to solve both!
++ */
++ wait_for_completion (&io->complete);
++
++ sg_clean (io);
++}
++
++/*
++ * Interpret the results of a URB transfer
++ *
++ * This function prints appropriate debugging messages, clears halts on
++ * non-control endpoints, and translates the status to the corresponding
++ * USB_STOR_XFER_xxx return code.
++ */
++static int interpret_urb_result(struct us_data *us, unsigned int pipe,
++ unsigned int length, int result, unsigned int partial)
++{
++ US_DEBUGP("Status code %d; transferred %u/%u\n",
++ result, partial, length);
++ switch (result) {
++
++ /* no error code; did we send all the data? */
++ case 0:
++ if (partial != length) {
++ US_DEBUGP("-- short transfer\n");
++ return USB_STOR_XFER_SHORT;
++ }
++
++ US_DEBUGP("-- transfer complete\n");
++ return USB_STOR_XFER_GOOD;
++
++ /* stalled */
++ case -EPIPE:
++ /* for control endpoints, (used by CB[I]) a stall indicates
++ * a failed command */
++ if (usb_pipecontrol(pipe)) {
++ US_DEBUGP("-- stall on control pipe\n");
++ return USB_STOR_XFER_STALLED;
++ }
++
++ /* for other sorts of endpoint, clear the stall */
++ US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
++ if (usb_stor_clear_halt(us, pipe) < 0)
++ return USB_STOR_XFER_ERROR;
++ return USB_STOR_XFER_STALLED;
++
++ /* timeout or excessively long NAK */
++ case -ETIMEDOUT:
++ US_DEBUGP("-- timeout or NAK\n");
++ return USB_STOR_XFER_ERROR;
++
++ /* babble - the device tried to send more than we wanted to read */
++ case -EOVERFLOW:
++ US_DEBUGP("-- babble\n");
++ return USB_STOR_XFER_LONG;
++
++ /* the transfer was cancelled by abort, disconnect, or timeout */
++ case -ECONNRESET:
++ US_DEBUGP("-- transfer cancelled\n");
++ return USB_STOR_XFER_ERROR;
++
++ /* short scatter-gather read transfer */
++ case -EREMOTEIO:
++ US_DEBUGP("-- short read transfer\n");
++ return USB_STOR_XFER_SHORT;
++
++ /* abort or disconnect in progress */
++ case -EIO:
++ US_DEBUGP("-- abort or disconnect in progress\n");
++ return USB_STOR_XFER_ERROR;
++
++ /* the catch-all error case */
++ default:
++ US_DEBUGP("-- unknown error\n");
++ return USB_STOR_XFER_ERROR;
++ }
++}
++
++/*
++ * Transfer a scatter-gather list via bulk transfer
++ *
++ * This function does basically the same thing as usb_stor_bulk_msg()
++ * above, but it uses the usbcore scatter-gather library.
++ */
++int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
++ struct scatterlist *sg, int num_sg, unsigned int length,
++ unsigned int *act_len)
++{
++ int result;
++
++ /* don't submit s-g requests during abort/disconnect processing */
++ if (us->flags & ABORTING_OR_DISCONNECTING)
++ return USB_STOR_XFER_ERROR;
++
++ /* initialize the scatter-gather request block */
++ US_DEBUGP("%s: xfer %u bytes, %d entries\n", __FUNCTION__,
++ length, num_sg);
++ result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0,
++ sg, num_sg, length, SLAB_NOIO);
++ if (result) {
++ US_DEBUGP("usb_sg_init returned %d\n", result);
++ return USB_STOR_XFER_ERROR;
++ }
++
++ /* since the block has been initialized successfully, it's now
++ * okay to cancel it */
++ set_bit(US_FLIDX_SG_ACTIVE, &us->flags);
++
++ /* did an abort/disconnect occur during the submission? */
++ if (us->flags & ABORTING_OR_DISCONNECTING) {
++
++ /* cancel the request, if it hasn't been cancelled already */
++ if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) {
++ US_DEBUGP("-- cancelling sg request\n");
++ usb_sg_cancel(&us->current_sg);
++ }
++ }
++
++ /* wait for the completion of the transfer */
++ usb_sg_wait(&us->current_sg);
++ clear_bit(US_FLIDX_SG_ACTIVE, &us->flags);
++
++ result = us->current_sg.status;
++ if (act_len)
++ *act_len = us->current_sg.bytes;
++ return interpret_urb_result(us, pipe, length, result,
++ us->current_sg.bytes);
++}
++
+ /*
+ * Transfer an entire SCSI command's worth of data payload over the bulk
+ * pipe.
+@@ -569,6 +1122,8 @@
+ struct scatterlist *sg;
+ unsigned int total_transferred = 0;
+ unsigned int transfer_amount;
++ unsigned int partial;
++ unsigned int pipe;
+
+ /* calculate how much we want to transfer */
+ transfer_amount = usb_stor_transfer_length(srb);
+@@ -585,23 +1140,34 @@
+ * make the appropriate requests for each, until done
+ */
+ sg = (struct scatterlist *) srb->request_buffer;
+- for (i = 0; i < srb->use_sg; i++) {
+-
+- /* transfer the lesser of the next buffer or the
+- * remaining data */
+- if (transfer_amount - total_transferred >=
+- sg[i].length) {
+- result = usb_stor_transfer_partial(us,
+- sg[i].address, sg[i].length);
+- total_transferred += sg[i].length;
+- } else
+- result = usb_stor_transfer_partial(us,
+- sg[i].address,
+- transfer_amount - total_transferred);
+-
+- /* if we get an error, end the loop here */
+- if (result)
+- break;
++ if (us->pusb_dev->speed == USB_SPEED_HIGH) {
++ /* calculate the appropriate pipe information */
++ if (us->srb->sc_data_direction == SCSI_DATA_READ)
++ pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
++ else
++ pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
++ /* use the usb core scatter-gather primitives */
++ result = usb_stor_bulk_transfer_sglist(us, pipe,
++ sg, srb->use_sg, transfer_amount, &partial);
++ } else {
++ for (i = 0; i < srb->use_sg; i++) {
++
++ /* transfer the lesser of the next buffer or the
++ * remaining data */
++ if (transfer_amount - total_transferred >=
++ sg[i].length) {
++ result = usb_stor_transfer_partial(us,
++ sg[i].address, sg[i].length);
++ total_transferred += sg[i].length;
++ } else
++ result = usb_stor_transfer_partial(us,
++ sg[i].address,
++ transfer_amount - total_transferred);
++
++ /* if we get an error, end the loop here */
++ if (result)
++ break;
++ }
+ }
+ }
+ else
+diff -ur linux.old/drivers/usb/storage/transport.h linux.dev/drivers/usb/storage/transport.h
+--- linux.old/drivers/usb/storage/transport.h 2003-08-25 13:44:42.000000000 +0200
++++ linux.dev/drivers/usb/storage/transport.h 2006-07-30 12:10:16.000000000 +0200
+@@ -127,6 +127,16 @@
+ #define US_BULK_TRANSFER_ABORTED 3 /* transfer canceled */
+
+ /*
++ * usb_stor_bulk_transfer_xxx() return codes, in order of severity
++ */
++
++#define USB_STOR_XFER_GOOD 0 /* good transfer */
++#define USB_STOR_XFER_SHORT 1 /* transferred less than expected */
++#define USB_STOR_XFER_STALLED 2 /* endpoint stalled */
++#define USB_STOR_XFER_LONG 3 /* device tried to send too much */
++#define USB_STOR_XFER_ERROR 4 /* transfer died in the middle */
++
++/*
+ * Transport return codes
+ */
+
+diff -ur linux.old/drivers/usb/storage/usb.h linux.dev/drivers/usb/storage/usb.h
+--- linux.old/drivers/usb/storage/usb.h 2005-04-04 03:42:20.000000000 +0200
++++ linux.dev/drivers/usb/storage/usb.h 2006-07-30 12:11:06.000000000 +0200
+@@ -111,6 +111,60 @@
+ typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*);
+ typedef void (*extra_data_destructor)(void *); /* extra data destructor */
+
++/* Dynamic flag definitions: used in set_bit() etc. */
++#define US_FLIDX_URB_ACTIVE 18 /* 0x00040000 current_urb is in use */
++#define US_FLIDX_SG_ACTIVE 19 /* 0x00080000 current_sg is in use */
++#define US_FLIDX_ABORTING 20 /* 0x00100000 abort is in progress */
++#define US_FLIDX_DISCONNECTING 21 /* 0x00200000 disconnect in progress */
++#define ABORTING_OR_DISCONNECTING ((1UL << US_FLIDX_ABORTING) | \
++ (1UL << US_FLIDX_DISCONNECTING))
++#define US_FLIDX_RESETTING 22 /* 0x00400000 device reset in progress */
++
++/* processing state machine states */
++#define US_STATE_IDLE 1
++#define US_STATE_RUNNING 2
++#define US_STATE_RESETTING 3
++#define US_STATE_ABORTING 4
++
++/**
++ * struct usb_sg_request - support for scatter/gather I/O
++ * @status: zero indicates success, else negative errno
++ * @bytes: counts bytes transferred.
++ *
++ * These requests are initialized using usb_sg_init(), and then are used
++ * as request handles passed to usb_sg_wait() or usb_sg_cancel(). Most
++ * members of the request object aren't for driver access.
++ *
++ * The status and bytecount values are valid only after usb_sg_wait()
++ * returns. If the status is zero, then the bytecount matches the total
++ * from the request.
++ *
++ * After an error completion, drivers may need to clear a halt condition
++ * on the endpoint.
++ */
++struct usb_sg_request {
++ int status;
++ size_t bytes;
++
++ /*
++ * members below are private to usbcore,
++ * and are not provided for driver access!
++ */
++ spinlock_t lock;
++
++ struct usb_device *dev;
++ int pipe;
++ struct scatterlist *sg;
++ int nents;
++
++ int entries;
++ struct urb **urbs;
++
++ int count;
++ struct completion complete;
++};
++
++
+ /* we allocate one of these for every device that we remember */
+ struct us_data {
+ struct us_data *next; /* next device */
+@@ -171,6 +225,7 @@
+ struct urb *current_urb; /* non-int USB requests */
+ struct completion current_done; /* the done flag */
+ unsigned int tag; /* tag for bulk CBW/CSW */
++ struct usb_sg_request current_sg; /* scatter-gather req. */
+
+ /* the semaphore for sleeping the control thread */
+ struct semaphore sema; /* to sleep thread on */
+diff -ur linux.old/include/linux/usb.h linux.dev/include/linux/usb.h
+--- linux.old/include/linux/usb.h 2004-11-17 12:54:22.000000000 +0100
++++ linux.dev/include/linux/usb.h 2006-07-30 12:19:19.000000000 +0200
+@@ -483,6 +483,8 @@
+ #define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt needed */
+ /* ... less overhead for QUEUE_BULK */
+ #define USB_TIMEOUT_KILLED 0x1000 // only set by HCD!
++#define URB_NO_TRANSFER_DMA_MAP 0x0400 /* urb->transfer_dma valid on submit */
++#define URB_NO_SETUP_DMA_MAP 0x0800 /* urb->setup_dma valid on submit */
+
+ struct iso_packet_descriptor
+ {
diff --git a/target/linux/generic-2.4/patches/229-pppoe_mtu_fix.patch b/target/linux/generic-2.4/patches/229-pppoe_mtu_fix.patch
new file mode 100644
index 0000000000..c2e4f064ca
--- /dev/null
+++ b/target/linux/generic-2.4/patches/229-pppoe_mtu_fix.patch
@@ -0,0 +1,12 @@
+--- linux-2.4.30/drivers/net/pppoe.c.old 2006-10-10 13:49:12.000000000 +0200
++++ linux-2.4.30/drivers/net/pppoe.c 2006-10-10 13:50:02.000000000 +0200
+@@ -639,6 +639,9 @@
+ po->chan.hdrlen = (sizeof(struct pppoe_hdr) +
+ dev->hard_header_len);
+
++ if (po->chan.mtu > dev->mtu - sizeof(struct pppoe_hdr))
++ po->chan.mtu = dev->mtu - sizeof(struct pppoe_hdr);
++
+ po->chan.private = sk;
+ po->chan.ops = &pppoe_chan_ops;
+
diff --git a/target/linux/generic-2.4/patches/601-netfilter_ipp2p_0.8.1rc1.patch b/target/linux/generic-2.4/patches/601-netfilter_ipp2p_0.8.1rc1.patch
new file mode 100644
index 0000000000..bfaa6e4b76
--- /dev/null
+++ b/target/linux/generic-2.4/patches/601-netfilter_ipp2p_0.8.1rc1.patch
@@ -0,0 +1,929 @@
+diff -urN linux.old/include/linux/netfilter_ipv4/ipt_ipp2p.h linux.dev/include/linux/netfilter_ipv4/ipt_ipp2p.h
+--- linux.old/include/linux/netfilter_ipv4/ipt_ipp2p.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/linux/netfilter_ipv4/ipt_ipp2p.h 2006-03-23 14:37:56.000000000 +0100
+@@ -0,0 +1,31 @@
++#ifndef __IPT_IPP2P_H
++#define __IPT_IPP2P_H
++#define IPP2P_VERSION "0.8.1_rc1"
++
++struct ipt_p2p_info {
++ int cmd;
++ int debug;
++};
++
++#endif //__IPT_IPP2P_H
++
++#define SHORT_HAND_IPP2P 1 /* --ipp2p switch*/
++//#define SHORT_HAND_DATA 4 /* --ipp2p-data switch*/
++#define SHORT_HAND_NONE 5 /* no short hand*/
++
++#define IPP2P_EDK (1 << 1)
++#define IPP2P_DATA_KAZAA (1 << 2)
++#define IPP2P_DATA_EDK (1 << 3)
++#define IPP2P_DATA_DC (1 << 4)
++#define IPP2P_DC (1 << 5)
++#define IPP2P_DATA_GNU (1 << 6)
++#define IPP2P_GNU (1 << 7)
++#define IPP2P_KAZAA (1 << 8)
++#define IPP2P_BIT (1 << 9)
++#define IPP2P_APPLE (1 << 10)
++#define IPP2P_SOUL (1 << 11)
++#define IPP2P_WINMX (1 << 12)
++#define IPP2P_ARES (1 << 13)
++#define IPP2P_MUTE (1 << 14)
++#define IPP2P_WASTE (1 << 15)
++#define IPP2P_XDCC (1 << 16)
+diff -urN linux.old/net/ipv4/netfilter/Config.in linux.dev/net/ipv4/netfilter/Config.in
+--- linux.old/net/ipv4/netfilter/Config.in 2006-03-23 14:35:20.000000000 +0100
++++ linux.dev/net/ipv4/netfilter/Config.in 2006-03-23 14:35:58.000000000 +0100
+@@ -29,6 +29,7 @@
+ dep_tristate ' TOS match support' CONFIG_IP_NF_MATCH_TOS $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' recent match support' CONFIG_IP_NF_MATCH_RECENT $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' ECN match support' CONFIG_IP_NF_MATCH_ECN $CONFIG_IP_NF_IPTABLES
++ dep_tristate ' peer to peer traffic match support' CONFIG_IP_NF_MATCH_IPP2P $CONFIG_IP_NF_IPTABLES
+
+ dep_tristate ' DSCP match support' CONFIG_IP_NF_MATCH_DSCP $CONFIG_IP_NF_IPTABLES
+
+diff -urN linux.old/net/ipv4/netfilter/Makefile linux.dev/net/ipv4/netfilter/Makefile
+--- linux.old/net/ipv4/netfilter/Makefile 2006-03-23 14:35:20.000000000 +0100
++++ linux.dev/net/ipv4/netfilter/Makefile 2006-03-23 14:35:58.000000000 +0100
+@@ -76,6 +76,7 @@
+ obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
+ obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
+ obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
++obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o
+
+ obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
+ obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
+diff -urN linux.old/net/ipv4/netfilter/ipt_ipp2p.c linux.dev/net/ipv4/netfilter/ipt_ipp2p.c
+--- linux.old/net/ipv4/netfilter/ipt_ipp2p.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/net/ipv4/netfilter/ipt_ipp2p.c 2006-03-23 14:37:18.000000000 +0100
+@@ -0,0 +1,868 @@
++#if defined(MODVERSIONS)
++#include <linux/modversions.h>
++#endif
++#include <linux/module.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/version.h>
++#include <linux/netfilter_ipv4/ipt_ipp2p.h>
++#include <net/tcp.h>
++#include <net/udp.h>
++
++#define get_u8(X,O) (*(__u8 *)(X + O))
++#define get_u16(X,O) (*(__u16 *)(X + O))
++#define get_u32(X,O) (*(__u32 *)(X + O))
++
++MODULE_AUTHOR("Eicke Friedrich/Klaus Degner <ipp2p@ipp2p.org>");
++MODULE_DESCRIPTION("An extension to iptables to identify P2P traffic.");
++MODULE_LICENSE("GPL");
++
++
++/*Search for UDP eDonkey/eMule/Kad commands*/
++int
++udp_search_edk (unsigned char *haystack, int packet_len)
++{
++ unsigned char *t = haystack;
++ t += 8;
++
++ switch (t[0]) {
++ case 0xe3:
++ { /*edonkey*/
++ switch (t[1])
++ {
++ /* client -> server status request */
++ case 0x96:
++ if (packet_len == 14) return ((IPP2P_EDK * 100) + 50);
++ break;
++ /* server -> client status request */
++ case 0x97: if (packet_len == 42) return ((IPP2P_EDK * 100) + 51);
++ break;
++ /* server description request */
++ /* e3 2a ff f0 .. | size == 6 */
++ case 0xa2: if ( (packet_len == 14) && ( get_u16(t,2) == __constant_htons(0xfff0) ) ) return ((IPP2P_EDK * 100) + 52);
++ break;
++ /* server description response */
++ /* e3 a3 ff f0 .. | size > 40 && size < 200 */
++ //case 0xa3: return ((IPP2P_EDK * 100) + 53);
++ // break;
++ case 0x9a: if (packet_len==26) return ((IPP2P_EDK * 100) + 54);
++ break;
++
++ case 0x92: if (packet_len==18) return ((IPP2P_EDK * 100) + 55);
++ break;
++ }
++ break;
++ }
++ case 0xe4:
++ {
++ switch (t[1])
++ {
++ /* e4 20 .. | size == 43 */
++ case 0x20: if ((packet_len == 43) && (t[2] != 0x00) && (t[34] != 0x00)) return ((IPP2P_EDK * 100) + 60);
++ break;
++ /* e4 00 .. 00 | size == 35 ? */
++ case 0x00: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 61);
++ break;
++ /* e4 10 .. 00 | size == 35 ? */
++ case 0x10: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 62);
++ break;
++ /* e4 18 .. 00 | size == 35 ? */
++ case 0x18: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 63);
++ break;
++ /* e4 52 .. | size = 44 */
++ case 0x52: if (packet_len == 44 ) return ((IPP2P_EDK * 100) + 64);
++ break;
++ /* e4 58 .. | size == 6 */
++ case 0x58: if (packet_len == 14 ) return ((IPP2P_EDK * 100) + 65);
++ break;
++ /* e4 59 .. | size == 2 */
++ case 0x59: if (packet_len == 10 )return ((IPP2P_EDK * 100) + 66);
++ break;
++ /* e4 28 .. | packet_len == 52,77,102,127... */
++ case 0x28: if (((packet_len-52) % 25) == 0) return ((IPP2P_EDK * 100) + 67);
++ break;
++ /* e4 50 xx xx | size == 4 */
++ case 0x50: if (packet_len == 12) return ((IPP2P_EDK * 100) + 68);
++ break;
++ /* e4 40 xx xx | size == 48 */
++ case 0x40: if (packet_len == 56) return ((IPP2P_EDK * 100) + 69);
++ break;
++ }
++ break;
++ }
++ } /* end of switch (t[0]) */
++ return 0;
++}/*udp_search_edk*/
++
++
++/*Search for UDP Gnutella commands*/
++int
++udp_search_gnu (unsigned char *haystack, int packet_len)
++{
++ unsigned char *t = haystack;
++ t += 8;
++
++ if (memcmp(t, "GND", 3) == 0) return ((IPP2P_GNU * 100) + 51);
++ if (memcmp(t, "GNUTELLA ", 9) == 0) return ((IPP2P_GNU * 100) + 52);
++ return 0;
++}/*udp_search_gnu*/
++
++
++/*Search for UDP KaZaA commands*/
++int
++udp_search_kazaa (unsigned char *haystack, int packet_len)
++{
++ unsigned char *t = haystack;
++
++ if (t[packet_len-1] == 0x00){
++ t += (packet_len - 6);
++ if (memcmp(t, "KaZaA", 5) == 0) return (IPP2P_KAZAA * 100 +50);
++ }
++
++ return 0;
++}/*udp_search_kazaa*/
++
++/*Search for UDP DirectConnect commands*/
++int
++udp_search_directconnect (unsigned char *haystack, int packet_len)
++{
++ unsigned char *t = haystack;
++ if ((*(t + 8) == 0x24) && (*(t + packet_len - 1) == 0x7c)) {
++ t+=8;
++ if (memcmp(t, "SR ", 3) == 0) return ((IPP2P_DC * 100) + 60);
++ if (memcmp(t, "Ping ", 5) == 0) return ((IPP2P_DC * 100) + 61);
++ }
++ return 0;
++}/*udp_search_directconnect*/
++
++
++
++/*Search for UDP BitTorrent commands*/
++int
++udp_search_bit (unsigned char *haystack, int packet_len)
++{
++ switch(packet_len)
++ {
++ case 24:
++ /* ^ 00 00 04 17 27 10 19 80 */
++ if ((ntohl(get_u32(haystack, 8)) == 0x00000417) && (ntohl(get_u32(haystack, 12)) == 0x27101980))
++ return (IPP2P_BIT * 100 + 50);
++ break;
++ case 44:
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000400) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
++ return (IPP2P_BIT * 100 + 51);
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000400))
++ return (IPP2P_BIT * 100 + 61);
++ break;
++ case 65:
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000404) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
++ return (IPP2P_BIT * 100 + 52);
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000404))
++ return (IPP2P_BIT * 100 + 62);
++ break;
++ case 67:
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000406) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
++ return (IPP2P_BIT * 100 + 53);
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000406))
++ return (IPP2P_BIT * 100 + 63);
++ break;
++ case 211:
++ if (get_u32(haystack, 8) == __constant_htonl(0x00000405))
++ return (IPP2P_BIT * 100 + 54);
++ break;
++ case 29:
++ if ((get_u32(haystack, 8) == __constant_htonl(0x00000401)))
++ return (IPP2P_BIT * 100 + 55);
++ break;
++ case 52:
++ if (get_u32(haystack,8) == __constant_htonl(0x00000827) &&
++ get_u32(haystack,12) == __constant_htonl(0x37502950))
++ return (IPP2P_BIT * 100 + 80);
++ break;
++ default:
++ /* this packet does not have a constant size */
++ if (packet_len >= 40 && get_u32(haystack, 16) == __constant_htonl(0x00000402) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
++ return (IPP2P_BIT * 100 + 56);
++ break;
++ }
++
++ /* some extra-bitcomet rules:
++ * "d1:" [a|r] "d2:id20:"
++ */
++ if (packet_len > 30 && get_u8(haystack, 8) == 'd' && get_u8(haystack, 9) == '1' && get_u8(haystack, 10) == ':' )
++ {
++ if (get_u8(haystack, 11) == 'a' || get_u8(haystack, 11) == 'r')
++ {
++ if (memcmp(haystack+12,"d2:id20:",8)==0)
++ return (IPP2P_BIT * 100 + 57);
++ }
++ }
++
++#if 0
++ /* bitlord rules */
++ /* packetlen must be bigger than 40 */
++ /* first 4 bytes are zero */
++ if (packet_len > 40 && get_u32(haystack, 8) == 0x00000000)
++ {
++ /* first rule: 00 00 00 00 01 00 00 xx xx xx xx 00 00 00 00*/
++ if (get_u32(haystack, 12) == 0x00000000 &&
++ get_u32(haystack, 16) == 0x00010000 &&
++ get_u32(haystack, 24) == 0x00000000 )
++ return (IPP2P_BIT * 100 + 71);
++
++ /* 00 01 00 00 0d 00 00 xx xx xx xx 00 00 00 00*/
++ if (get_u32(haystack, 12) == 0x00000001 &&
++ get_u32(haystack, 16) == 0x000d0000 &&
++ get_u32(haystack, 24) == 0x00000000 )
++ return (IPP2P_BIT * 100 + 71);
++
++
++ }
++#endif
++
++ return 0;
++}/*udp_search_bit*/
++
++
++
++/*Search for Ares commands*/
++//#define IPP2P_DEBUG_ARES
++int
++search_ares (const unsigned char *payload, const u16 plen)
++//int search_ares (unsigned char *haystack, int packet_len, int head_len)
++{
++// const unsigned char *t = haystack + head_len;
++
++ /* all ares packets start with */
++ if (payload[1] == 0 && (plen - payload[0]) == 3)
++ {
++ switch (payload[2])
++ {
++ case 0x5a:
++ /* ares connect */
++ if ( plen == 6 && payload[5] == 0x05 ) return ((IPP2P_ARES * 100) + 1);
++ break;
++ case 0x09:
++ /* ares search, min 3 chars --> 14 bytes
++ * lets define a search can be up to 30 chars --> max 34 bytes
++ */
++ if ( plen >= 14 && plen <= 34 ) return ((IPP2P_ARES * 100) + 1);
++ break;
++#ifdef IPP2P_DEBUG_ARES
++ default:
++ printk(KERN_DEBUG "Unknown Ares command %x recognized, len: %u \n", (unsigned int) payload[2],plen);
++#endif /* IPP2P_DEBUG_ARES */
++ }
++ }
++
++#if 0
++ /* found connect packet: 03 00 5a 04 03 05 */
++ /* new version ares 1.8: 03 00 5a xx xx 05 */
++ if ((plen) == 6){ /* possible connect command*/
++ if ((payload[0] == 0x03) && (payload[1] == 0x00) && (payload[2] == 0x5a) && (payload[5] == 0x05))
++ return ((IPP2P_ARES * 100) + 1);
++ }
++ if ((plen) == 60){ /* possible download command*/
++ if ((payload[59] == 0x0a) && (payload[58] == 0x0a)){
++ if (memcmp(t, "PUSH SHA1:", 10) == 0) /* found download command */
++ return ((IPP2P_ARES * 100) + 2);
++ }
++ }
++#endif
++
++ return 0;
++} /*search_ares*/
++
++/*Search for SoulSeek commands*/
++int
++search_soul (const unsigned char *payload, const u16 plen)
++{
++//#define IPP2P_DEBUG_SOUL
++ /* match: xx xx xx xx | xx = sizeof(payload) - 4 */
++ if (get_u32(payload, 0) == (plen - 4)){
++ const __u32 m=get_u32(payload, 4);
++ /* match 00 yy yy 00, yy can be everything */
++ if ( get_u8(payload, 4) == 0x00 && get_u8(payload, 7) == 0x00 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "0: Soulseek command 0x%x recognized\n",get_u32(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 1);
++ }
++
++ /* next match: 01 yy 00 00 | yy can be everything */
++ if ( get_u8(payload, 4) == 0x01 && get_u16(payload, 6) == 0x0000 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "1: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 2);
++ }
++
++ /* other soulseek commandos are: 1-5,7,9,13-18,22,23,26,28,35-37,40-46,50,51,60,62-69,91,92,1001 */
++ /* try to do this in an intelligent way */
++ /* get all small commandos */
++ switch(m)
++ {
++ case 7:
++ case 9:
++ case 22:
++ case 23:
++ case 26:
++ case 28:
++ case 50:
++ case 51:
++ case 60:
++ case 91:
++ case 92:
++ case 1001:
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "2: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 3);
++ }
++
++ if (m > 0 && m < 6 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "3: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 4);
++ }
++ if (m > 12 && m < 19 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "4: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 5);
++ }
++
++ if (m > 34 && m < 38 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "5: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 6);
++ }
++
++ if (m > 39 && m < 47 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "6: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 7);
++ }
++
++ if (m > 61 && m < 70 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "7: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 8);
++ }
++
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "unknown SOULSEEK command: 0x%x, first 16 bit: 0x%x, first 8 bit: 0x%x ,soulseek ???\n",get_u32(payload, 4),get_u16(payload, 4) >> 16,get_u8(payload, 4) >> 24);
++#endif /* IPP2P_DEBUG_SOUL */
++ }
++
++ /* match 14 00 00 00 01 yy 00 00 00 STRING(YY) 01 00 00 00 00 46|50 00 00 00 00 */
++ /* without size at the beginning !!! */
++ if ( get_u32(payload, 0) == 0x14 && get_u8(payload, 4) == 0x01 )
++ {
++ __u32 y=get_u32(payload, 5);
++ /* we need 19 chars + string */
++ if ( (y + 19) <= (plen) )
++ {
++ const unsigned char *w=payload+9+y;
++ if (get_u32(w, 0) == 0x01 && ( get_u16(w, 4) == 0x4600 || get_u16(w, 4) == 0x5000) && get_u32(w, 6) == 0x00);
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "Soulssek special client command recognized\n");
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 9);
++ }
++ }
++ return 0;
++}
++
++
++/*Search for WinMX commands*/
++int
++search_winmx (const unsigned char *payload, const u16 plen)
++{
++//#define IPP2P_DEBUG_WINMX
++ if (((plen) == 4) && (memcmp(payload, "SEND", 4) == 0)) return ((IPP2P_WINMX * 100) + 1);
++ if (((plen) == 3) && (memcmp(payload, "GET", 3) == 0)) return ((IPP2P_WINMX * 100) + 2);
++ //if (packet_len < (head_len + 10)) return 0;
++ if (plen < 10) return 0;
++
++ if ((memcmp(payload, "SEND", 4) == 0) || (memcmp(payload, "GET", 3) == 0)){
++ u16 c=4;
++ const u16 end=plen-2;
++ u8 count=0;
++ while (c < end)
++ {
++ if (payload[c]== 0x20 && payload[c+1] == 0x22)
++ {
++ c++;
++ count++;
++ if (count>=2) return ((IPP2P_WINMX * 100) + 3);
++ }
++ c++;
++ }
++ }
++
++ if ( plen == 149 && payload[0] == '8' )
++ {
++#ifdef IPP2P_DEBUG_WINMX
++ printk(KERN_INFO "maybe WinMX\n");
++#endif
++ if (get_u32(payload,17) == 0 && get_u32(payload,21) == 0 && get_u32(payload,25) == 0 &&
++// get_u32(payload,33) == __constant_htonl(0x71182b1a) && get_u32(payload,37) == __constant_htonl(0x05050000) &&
++// get_u32(payload,133) == __constant_htonl(0x31097edf) && get_u32(payload,145) == __constant_htonl(0xdcb8f792))
++ get_u16(payload,39) == 0 && get_u16(payload,135) == __constant_htons(0x7edf) && get_u16(payload,147) == __constant_htons(0xf792))
++
++ {
++#ifdef IPP2P_DEBUG_WINMX
++ printk(KERN_INFO "got WinMX\n");
++#endif
++ return ((IPP2P_WINMX * 100) + 4);
++ }
++ }
++ return 0;
++} /*search_winmx*/
++
++
++/*Search for appleJuice commands*/
++int
++search_apple (const unsigned char *payload, const u16 plen)
++{
++ if ( (plen > 7) && (payload[6] == 0x0d) && (payload[7] == 0x0a) && (memcmp(payload, "ajprot", 6) == 0)) return (IPP2P_APPLE * 100);
++
++ return 0;
++}
++
++
++/*Search for BitTorrent commands*/
++int
++search_bittorrent (const unsigned char *payload, const u16 plen)
++{
++ if (plen > 20)
++ {
++ /* test for match 0x13+"BitTorrent protocol" */
++ if (payload[0] == 0x13)
++ {
++ if (memcmp(payload+1, "BitTorrent protocol", 19) == 0) return (IPP2P_BIT * 100);
++ }
++
++ /* get tracker commandos, all starts with GET /
++ * then it can follow: scrape| announce
++ * and then ?hash_info=
++ */
++ if (memcmp(payload,"GET /",5) == 0)
++ {
++ /* message scrape */
++ if ( memcmp(payload+5,"scrape?info_hash=",17)==0 ) return (IPP2P_BIT * 100 + 1);
++ /* message announce */
++ if ( memcmp(payload+5,"announce?info_hash=",19)==0 ) return (IPP2P_BIT * 100 + 2);
++ }
++ }
++ else
++ {
++ /* bitcomet encryptes the first packet, so we have to detect another
++ * one later in the flow */
++ /* first try failed, too many missdetections */
++ //if ( size == 5 && get_u32(t,0) == __constant_htonl(1) && t[4] < 3) return (IPP2P_BIT * 100 + 3);
++
++ /* second try: block request packets */
++ if ( plen == 17 && get_u32(payload,0) == __constant_htonl(0x0d) && payload[4] == 0x06 && get_u32(payload,13) == __constant_htonl(0x4000) ) return (IPP2P_BIT * 100 + 3);
++ }
++
++ return 0;
++}
++
++
++
++/*check for Kazaa get command*/
++int
++search_kazaa (const unsigned char *payload, const u16 plen)
++
++{
++ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a) && memcmp(payload, "GET /.hash=", 11) == 0)
++ return (IPP2P_DATA_KAZAA * 100);
++
++ return 0;
++}
++
++
++/*check for gnutella get command*/
++int
++search_gnu (const unsigned char *payload, const u16 plen)
++{
++ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
++ {
++ if (memcmp(payload, "GET /get/", 9) == 0) return ((IPP2P_DATA_GNU * 100) + 1);
++ if (memcmp(payload, "GET /uri-res/", 13) == 0) return ((IPP2P_DATA_GNU * 100) + 2);
++ }
++ return 0;
++}
++
++
++/*check for gnutella get commands and other typical data*/
++int
++search_all_gnu (const unsigned char *payload, const u16 plen)
++{
++
++ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
++ {
++
++ if (memcmp(payload, "GNUTELLA CONNECT/", 17) == 0) return ((IPP2P_GNU * 100) + 1);
++ if (memcmp(payload, "GNUTELLA/", 9) == 0) return ((IPP2P_GNU * 100) + 2);
++
++
++ if ((memcmp(payload, "GET /get/", 9) == 0) || (memcmp(payload, "GET /uri-res/", 13) == 0))
++ {
++ u16 c=8;
++ const u16 end=plen-22;
++ while (c < end) {
++ if ( payload[c] == 0x0a && payload[c+1] == 0x0d && ((memcmp(&payload[c+2], "X-Gnutella-", 11) == 0) || (memcmp(&payload[c+2], "X-Queue:", 8) == 0)))
++ return ((IPP2P_GNU * 100) + 3);
++ c++;
++ }
++ }
++ }
++ return 0;
++}
++
++
++/*check for KaZaA download commands and other typical data*/
++int
++search_all_kazaa (const unsigned char *payload, const u16 plen)
++{
++ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
++ {
++
++ if (memcmp(payload, "GIVE ", 5) == 0) return ((IPP2P_KAZAA * 100) + 1);
++
++ if (memcmp(payload, "GET /", 5) == 0) {
++ u16 c = 8;
++ const u16 end=plen-22;
++ while (c < end) {
++ if ( payload[c] == 0x0a && payload[c+1] == 0x0d && ((memcmp(&payload[c+2], "X-Kazaa-Username: ", 18) == 0) || (memcmp(&payload[c+2], "User-Agent: PeerEnabler/", 24) == 0)))
++ return ((IPP2P_KAZAA * 100) + 2);
++ c++;
++ }
++ }
++ }
++ return 0;
++}
++
++/*fast check for edonkey file segment transfer command*/
++int
++search_edk (const unsigned char *payload, const u16 plen)
++{
++ if (payload[0] != 0xe3)
++ return 0;
++ else {
++ if (payload[5] == 0x47)
++ return (IPP2P_DATA_EDK * 100);
++ else
++ return 0;
++ }
++}
++
++
++
++/*intensive but slower search for some edonkey packets including size-check*/
++int
++search_all_edk (const unsigned char *payload, const u16 plen)
++{
++ if (payload[0] != 0xe3)
++ return 0;
++ else {
++ //t += head_len;
++ const u16 cmd = get_u16(payload, 1);
++ if (cmd == (plen - 5)) {
++ switch (payload[5]) {
++ case 0x01: return ((IPP2P_EDK * 100) + 1); /*Client: hello or Server:hello*/
++ case 0x4c: return ((IPP2P_EDK * 100) + 9); /*Client: Hello-Answer*/
++ }
++ }
++ return 0;
++ }
++}
++
++
++/*fast check for Direct Connect send command*/
++int
++search_dc (const unsigned char *payload, const u16 plen)
++{
++
++ if (payload[0] != 0x24 )
++ return 0;
++ else {
++ if (memcmp(&payload[1], "Send|", 5) == 0)
++ return (IPP2P_DATA_DC * 100);
++ else
++ return 0;
++ }
++
++}
++
++
++/*intensive but slower check for all direct connect packets*/
++int
++search_all_dc (const unsigned char *payload, const u16 plen)
++{
++// unsigned char *t = haystack;
++
++ if (payload[0] == 0x24 && payload[plen-1] == 0x7c)
++ {
++ const unsigned char *t=&payload[1];
++ /* Client-Hub-Protocol */
++ if (memcmp(t, "Lock ", 5) == 0) return ((IPP2P_DC * 100) + 1);
++ /* Client-Client-Protocol, some are already recognized by client-hub (like lock) */
++ if (memcmp(t, "MyNick ", 7) == 0) return ((IPP2P_DC * 100) + 38);
++ }
++ return 0;
++}
++
++/*check for mute*/
++int
++search_mute (const unsigned char *payload, const u16 plen)
++{
++ if ( plen == 209 || plen == 345 || plen == 473 || plen == 609 || plen == 1121 )
++ {
++ //printk(KERN_DEBUG "size hit: %u",size);
++ if (memcmp(payload,"PublicKey: ",11) == 0 )
++ {
++ return ((IPP2P_MUTE * 100) + 0);
++
++/* if (memcmp(t+size-14,"\x0aEndPublicKey\x0a",14) == 0)
++ {
++ printk(KERN_DEBUG "end pubic key hit: %u",size);
++
++ }*/
++ }
++ }
++ return 0;
++}
++
++
++/* check for xdcc */
++int
++search_xdcc (const unsigned char *payload, const u16 plen)
++{
++ /* search in small packets only */
++ if (plen > 20 && plen < 200 && payload[plen-1] == 0x0a && payload[plen-2] == 0x0d && memcmp(payload,"PRIVMSG ",8) == 0)
++ {
++
++ u16 x=10;
++ const u16 end=plen - 13;
++
++ /* is seems to be a irc private massage, chedck for xdcc command */
++ while (x < end)
++ {
++ if (payload[x] == ':')
++ {
++ if ( memcmp(&payload[x+1],"xdcc send #",11) == 0 )
++ return ((IPP2P_XDCC * 100) + 0);
++ }
++ x++;
++ }
++ }
++ return 0;
++}
++
++/* search for waste */
++int search_waste(const unsigned char *payload, const u16 plen)
++{
++ if ( plen >= 8 && memcmp(payload,"GET.sha1:",9) == 0)
++ return ((IPP2P_WASTE * 100) + 0);
++
++ return 0;
++}
++
++
++static struct {
++ int command;
++ __u8 short_hand; /*for fucntions included in short hands*/
++ int packet_len;
++ int (*function_name) (const unsigned char *, const u16);
++} matchlist[] = {
++ {IPP2P_EDK,SHORT_HAND_IPP2P,20, &search_all_edk},
++// {IPP2P_DATA_KAZAA,SHORT_HAND_DATA,200, &search_kazaa},
++// {IPP2P_DATA_EDK,SHORT_HAND_DATA,60, &search_edk},
++// {IPP2P_DATA_DC,SHORT_HAND_DATA,26, &search_dc},
++ {IPP2P_DC,SHORT_HAND_IPP2P,5, search_all_dc},
++// {IPP2P_DATA_GNU,SHORT_HAND_DATA,40, &search_gnu},
++ {IPP2P_GNU,SHORT_HAND_IPP2P,5, &search_all_gnu},
++ {IPP2P_KAZAA,SHORT_HAND_IPP2P,5, &search_all_kazaa},
++ {IPP2P_BIT,SHORT_HAND_IPP2P,20, &search_bittorrent},
++ {IPP2P_APPLE,SHORT_HAND_IPP2P,5, &search_apple},
++ {IPP2P_SOUL,SHORT_HAND_IPP2P,5, &search_soul},
++ {IPP2P_WINMX,SHORT_HAND_IPP2P,2, &search_winmx},
++ {IPP2P_ARES,SHORT_HAND_IPP2P,5, &search_ares},
++ {IPP2P_MUTE,SHORT_HAND_NONE,200, &search_mute},
++ {IPP2P_WASTE,SHORT_HAND_NONE,5, &search_waste},
++ {IPP2P_XDCC,SHORT_HAND_NONE,5, &search_xdcc},
++ {0,0,0,NULL}
++};
++
++
++static struct {
++ int command;
++ __u8 short_hand; /*for fucntions included in short hands*/
++ int packet_len;
++ int (*function_name) (unsigned char *, int);
++} udp_list[] = {
++ {IPP2P_KAZAA,SHORT_HAND_IPP2P,14, &udp_search_kazaa},
++ {IPP2P_BIT,SHORT_HAND_IPP2P,23, &udp_search_bit},
++ {IPP2P_GNU,SHORT_HAND_IPP2P,11, &udp_search_gnu},
++ {IPP2P_EDK,SHORT_HAND_IPP2P,9, &udp_search_edk},
++ {IPP2P_DC,SHORT_HAND_IPP2P,12, &udp_search_directconnect},
++ {0,0,0,NULL}
++};
++
++
++static int
++match(const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *matchinfo,
++ int offset,
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++ const void *hdr,
++ u_int16_t datalen,
++#endif
++
++ int *hotdrop)
++{
++ const struct ipt_p2p_info *info = matchinfo;
++ unsigned char *haystack;
++ struct iphdr *ip = skb->nh.iph;
++ int p2p_result = 0, i = 0;
++// int head_len;
++ int hlen = ntohs(ip->tot_len)-(ip->ihl*4); /*hlen = packet-data length*/
++
++ /*must not be a fragment*/
++ if (offset) {
++ if (info->debug) printk("IPP2P.match: offset found %i \n",offset);
++ return 0;
++ }
++
++ /*make sure that skb is linear*/
++ if(skb_is_nonlinear(skb)){
++ if (info->debug) printk("IPP2P.match: nonlinear skb found\n");
++ return 0;
++ }
++
++
++ haystack=(char *)ip+(ip->ihl*4); /*haystack = packet data*/
++
++ switch (ip->protocol){
++ case IPPROTO_TCP: /*what to do with a TCP packet*/
++ {
++ struct tcphdr *tcph = (void *) ip + ip->ihl * 4;
++
++ if (tcph->fin) return 0; /*if FIN bit is set bail out*/
++ if (tcph->syn) return 0; /*if SYN bit is set bail out*/
++ if (tcph->rst) return 0; /*if RST bit is set bail out*/
++
++ haystack += tcph->doff * 4; /*get TCP-Header-Size*/
++ hlen -= tcph->doff * 4;
++ while (matchlist[i].command) {
++ if ((((info->cmd & matchlist[i].command) == matchlist[i].command) ||
++ ((info->cmd & matchlist[i].short_hand) == matchlist[i].short_hand)) &&
++ (hlen > matchlist[i].packet_len)) {
++ p2p_result = matchlist[i].function_name(haystack, hlen);
++ if (p2p_result)
++ {
++ if (info->debug) printk("IPP2P.debug:TCP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
++ p2p_result, NIPQUAD(ip->saddr),ntohs(tcph->source), NIPQUAD(ip->daddr),ntohs(tcph->dest),hlen);
++ return p2p_result;
++ }
++ }
++ i++;
++ }
++ return p2p_result;
++ }
++
++ case IPPROTO_UDP: /*what to do with an UDP packet*/
++ {
++ struct udphdr *udph = (void *) ip + ip->ihl * 4;
++
++ while (udp_list[i].command){
++ if ((((info->cmd & udp_list[i].command) == udp_list[i].command) ||
++ ((info->cmd & udp_list[i].short_hand) == udp_list[i].short_hand)) &&
++ (hlen > udp_list[i].packet_len)) {
++ p2p_result = udp_list[i].function_name(haystack, hlen);
++ if (p2p_result){
++ if (info->debug) printk("IPP2P.debug:UDP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
++ p2p_result, NIPQUAD(ip->saddr),ntohs(udph->source), NIPQUAD(ip->daddr),ntohs(udph->dest),hlen);
++ return p2p_result;
++ }
++ }
++ i++;
++ }
++ return p2p_result;
++ }
++
++ default: return 0;
++ }
++}
++
++
++
++static int
++checkentry(const char *tablename,
++ const struct ipt_ip *ip,
++ void *matchinfo,
++ unsigned int matchsize,
++ unsigned int hook_mask)
++{
++ /* Must specify -p tcp */
++/* if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) {
++ * printk("ipp2p: Only works on TCP packets, use -p tcp\n");
++ * return 0;
++ * }*/
++ return 1;
++}
++
++
++
++
++static struct ipt_match ipp2p_match = {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++ { NULL, NULL },
++ "ipp2p",
++ &match,
++ &checkentry,
++ NULL,
++ THIS_MODULE
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++ .name = "ipp2p",
++ .match = &match,
++ .checkentry = &checkentry,
++ .me = THIS_MODULE,
++#endif
++};
++
++
++static int __init init(void)
++{
++ printk(KERN_INFO "IPP2P v%s loading\n", IPP2P_VERSION);
++ return ipt_register_match(&ipp2p_match);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_match(&ipp2p_match);
++ printk(KERN_INFO "IPP2P v%s unloaded\n", IPP2P_VERSION);
++}
++
++module_init(init);
++module_exit(fini);
++
++
diff --git a/target/linux/generic-2.4/patches/602-netfilter_layer7_2.1nbd.patch b/target/linux/generic-2.4/patches/602-netfilter_layer7_2.1nbd.patch
new file mode 100644
index 0000000000..d67725d854
--- /dev/null
+++ b/target/linux/generic-2.4/patches/602-netfilter_layer7_2.1nbd.patch
@@ -0,0 +1,2083 @@
+diff -urN linux.old/Documentation/Configure.help linux.dev/Documentation/Configure.help
+--- linux.old/Documentation/Configure.help 2006-01-31 16:55:22.467939000 +0100
++++ linux.dev/Documentation/Configure.help 2006-01-31 16:58:24.751331500 +0100
+@@ -29151,6 +29151,18 @@
+
+ If unsure, say N.
+
++CONFIG_IP_NF_MATCH_LAYER7
++ Say Y if you want to be able to classify connections (and their
++ packets) based on regular expression matching of their application
++ layer data. This is one way to classify applications such as
++ peer-to-peer filesharing systems that do not always use the same
++ port.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
++CONFIG_IP_NF_MATCH_LAYER7_DEBUG
++ Say Y to get lots of debugging output.
++
+ #
+ # A couple of things I keep forgetting:
+ # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet,
+diff -urN linux.old/include/linux/netfilter_ipv4/ip_conntrack.h linux.dev/include/linux/netfilter_ipv4/ip_conntrack.h
+--- linux.old/include/linux/netfilter_ipv4/ip_conntrack.h 2005-11-16 20:12:54.000000000 +0100
++++ linux.dev/include/linux/netfilter_ipv4/ip_conntrack.h 2006-01-31 16:58:24.775333000 +0100
+@@ -207,6 +207,17 @@
+ } nat;
+ #endif /* CONFIG_IP_NF_NAT_NEEDED */
+
++#if defined(CONFIG_IP_NF_MATCH_LAYER7) || defined(CONFIG_IP_NF_MATCH_LAYER7_MODULE)
++ struct {
++ unsigned int numpackets; /* surely this is kept track of somewhere else, right? I can't find it... */
++ char * app_proto; /* "http", "ftp", etc. NULL if unclassifed */
++
++ /* the application layer data so far. NULL if ->numpackets > numpackets */
++ char * app_data;
++
++ unsigned int app_data_len;
++ } layer7;
++#endif
+ };
+
+ /* get master conntrack via master expectation */
+diff -urN linux.old/include/linux/netfilter_ipv4/ipt_layer7.h linux.dev/include/linux/netfilter_ipv4/ipt_layer7.h
+--- linux.old/include/linux/netfilter_ipv4/ipt_layer7.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/linux/netfilter_ipv4/ipt_layer7.h 2006-01-31 19:29:03.774017500 +0100
+@@ -0,0 +1,27 @@
++/*
++ By Matthew Strait <quadong@users.sf.net>, Dec 2003.
++ 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
++*/
++
++#ifndef _IPT_LAYER7_H
++#define _IPT_LAYER7_H
++
++#define MAX_PATTERN_LEN 8192
++#define MAX_PROTOCOL_LEN 256
++
++typedef char *(*proc_ipt_search) (char *, char, char *);
++
++struct ipt_layer7_info {
++ char protocol[MAX_PROTOCOL_LEN];
++ char invert:1;
++ char pattern[MAX_PATTERN_LEN];
++ char pkt;
++};
++
++#endif /* _IPT_LAYER7_H */
+diff -urN linux.old/net/ipv4/netfilter/Config.in linux.dev/net/ipv4/netfilter/Config.in
+--- linux.old/net/ipv4/netfilter/Config.in 2006-01-31 16:55:32.364558000 +0100
++++ linux.dev/net/ipv4/netfilter/Config.in 2006-01-31 16:58:24.803334750 +0100
+@@ -44,6 +44,9 @@
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ dep_tristate ' Unclean match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_UNCLEAN $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' Owner match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_OWNER $CONFIG_IP_NF_IPTABLES
++ dep_tristate ' Layer 7 match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_LAYER7 $CONFIG_IP_NF_CONNTRACK
++ dep_mbool ' Layer 7 debugging output (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_LAYER7_DEBUG $CONFIG_IP_NF_MATCH_LAYER7
++
+ fi
+ # The targets
+ dep_tristate ' Packet filtering' CONFIG_IP_NF_FILTER $CONFIG_IP_NF_IPTABLES
+diff -urN linux.old/net/ipv4/netfilter/Makefile linux.dev/net/ipv4/netfilter/Makefile
+--- linux.old/net/ipv4/netfilter/Makefile 2006-01-31 16:55:32.372558000 +0100
++++ linux.dev/net/ipv4/netfilter/Makefile 2006-01-31 16:58:24.803334750 +0100
+@@ -87,6 +87,7 @@
+ obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
+ obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
+ obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
++obj-$(CONFIG_IP_NF_MATCH_LAYER7) += ipt_layer7.o
+
+ # targets
+ obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
+diff -urN linux.old/net/ipv4/netfilter/ip_conntrack_core.c linux.dev/net/ipv4/netfilter/ip_conntrack_core.c
+--- linux.old/net/ipv4/netfilter/ip_conntrack_core.c 2005-04-04 03:42:20.000000000 +0200
++++ linux.dev/net/ipv4/netfilter/ip_conntrack_core.c 2006-01-31 16:58:24.811335250 +0100
+@@ -346,6 +346,14 @@
+ }
+ kfree(ct->master);
+ }
++
++ #if defined(CONFIG_IP_NF_MATCH_LAYER7) || defined(CONFIG_IP_NF_MATCH_LAYER7_MODULE)
++ if(ct->layer7.app_proto)
++ kfree(ct->layer7.app_proto);
++ if(ct->layer7.app_data)
++ kfree(ct->layer7.app_data);
++ #endif
++
+ WRITE_UNLOCK(&ip_conntrack_lock);
+
+ if (master)
+diff -urN linux.old/net/ipv4/netfilter/ip_conntrack_standalone.c linux.dev/net/ipv4/netfilter/ip_conntrack_standalone.c
+--- linux.old/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-04-04 03:42:20.000000000 +0200
++++ linux.dev/net/ipv4/netfilter/ip_conntrack_standalone.c 2006-01-31 16:58:24.815335500 +0100
+@@ -107,6 +107,13 @@
+ len += sprintf(buffer + len, "[ASSURED] ");
+ len += sprintf(buffer + len, "use=%u ",
+ atomic_read(&conntrack->ct_general.use));
++
++ #if defined(CONFIG_IP_NF_MATCH_LAYER7) || defined(CONFIG_IP_NF_MATCH_LAYER7_MODULE)
++ if(conntrack->layer7.app_proto)
++ len += sprintf(buffer + len, "l7proto=%s ",
++ conntrack->layer7.app_proto);
++ #endif
++
+ len += sprintf(buffer + len, "\n");
+
+ return len;
+diff -urN linux.old/net/ipv4/netfilter/ipt_layer7.c linux.dev/net/ipv4/netfilter/ipt_layer7.c
+--- linux.old/net/ipv4/netfilter/ipt_layer7.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/net/ipv4/netfilter/ipt_layer7.c 2006-01-31 19:31:38.591693000 +0100
+@@ -0,0 +1,595 @@
++/*
++ Kernel module to match application layer (OSI layer 7)
++ data in connections.
++
++ http://l7-filter.sf.net
++
++ By Matthew Strait and Ethan Sommer, 2003-2005.
++
++ 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
++
++ Based on ipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>
++ and cls_layer7.c (C) 2003 Matthew Strait, Ethan Sommer, Justin Levandoski
++*/
++
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_conntrack.h>
++#include <linux/proc_fs.h>
++#include <linux/ctype.h>
++#include <net/ip.h>
++#include <net/tcp.h>
++#include <linux/netfilter_ipv4/lockhelp.h>
++
++#include "regexp/regexp.c"
++
++#include <linux/netfilter_ipv4/ipt_layer7.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++
++MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("iptables application layer match module");
++
++static int maxdatalen = 2048; // this is the default
++MODULE_PARM(maxdatalen,"i");
++MODULE_PARM_DESC(maxdatalen,"maximum bytes of data looked at by l7-filter");
++
++#if defined(CONFIG_IP_NF_MATCH_LAYER7_DEBUG)
++ #define DPRINTK(format,args...) printk(format,##args)
++#else
++ #define DPRINTK(format,args...)
++#endif
++
++#define TOTAL_PACKETS master_conntrack->layer7.numpackets
++
++/* Number of packets whose data we look at.
++This can be modified through /proc/net/layer7_numpackets */
++static int num_packets = 10;
++
++static struct pattern_cache {
++ char * regex_string;
++ regexp * pattern;
++ struct pattern_cache * next;
++} * first_pattern_cache = NULL;
++
++/* I'm new to locking. Here are my assumptions:
++
++- No one will write to /proc/net/layer7_numpackets over and over very fast;
++ if they did, nothing awful would happen.
++
++- This code will never be processing the same packet twice at the same time,
++ because iptables rules are traversed in order.
++
++- It doesn't matter if two packets from different connections are in here at
++ the same time, because they don't share any data.
++
++- It _does_ matter if two packets from the same connection are here at the same
++ time. In this case, we have to protect the conntracks and the list of
++ compiled patterns.
++*/
++DECLARE_RWLOCK(ct_lock);
++DECLARE_LOCK(list_lock);
++
++#if CONFIG_IP_NF_MATCH_LAYER7_DEBUG
++/* Converts an unfriendly string into a friendly one by
++replacing unprintables with periods and all whitespace with " ". */
++static char * friendly_print(unsigned char * s)
++{
++ char * f = kmalloc(strlen(s) + 1, GFP_ATOMIC);
++ int i;
++
++ if(!f) {
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in friendly_print, bailing.\n");
++ return NULL;
++ }
++
++ for(i = 0; i < strlen(s); i++){
++ if(isprint(s[i]) && s[i] < 128) f[i] = s[i];
++ else if(isspace(s[i])) f[i] = ' ';
++ else f[i] = '.';
++ }
++ f[i] = '\0';
++ return f;
++}
++
++static char dec2hex(int i)
++{
++ switch (i) {
++ case 0 ... 9:
++ return (char)(i + '0');
++ break;
++ case 10 ... 15:
++ return (char)(i - 10 + 'a');
++ break;
++ default:
++ if (net_ratelimit())
++ printk("Problem in dec2hex\n");
++ return '\0';
++ }
++}
++
++static char * hex_print(unsigned char * s)
++{
++ char * g = kmalloc(strlen(s)*3 + 1, GFP_ATOMIC);
++ int i;
++
++ if(!g) {
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in hex_print, bailing.\n");
++ return NULL;
++ }
++
++ for(i = 0; i < strlen(s); i++) {
++ g[i*3 ] = dec2hex(s[i]/16);
++ g[i*3 + 1] = dec2hex(s[i]%16);
++ g[i*3 + 2] = ' ';
++ }
++ g[i*3] = '\0';
++
++ return g;
++}
++#endif // DEBUG
++
++/* Use instead of regcomp. As we expect to be seeing the same regexps over and
++over again, it make sense to cache the results. */
++static regexp * compile_and_cache(char * regex_string, char * protocol)
++{
++ struct pattern_cache * node = first_pattern_cache;
++ struct pattern_cache * last_pattern_cache = first_pattern_cache;
++ struct pattern_cache * tmp;
++ unsigned int len;
++
++ while (node != NULL) {
++ if (!strcmp(node->regex_string, regex_string))
++ return node->pattern;
++
++ last_pattern_cache = node;/* points at the last non-NULL node */
++ node = node->next;
++ }
++
++ /* If we reach the end of the list, then we have not yet cached
++ the pattern for this regex. Let's do that now.
++ Be paranoid about running out of memory to avoid list corruption. */
++ tmp = kmalloc(sizeof(struct pattern_cache), GFP_ATOMIC);
++
++ if(!tmp) {
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in compile_and_cache, bailing.\n");
++ return NULL;
++ }
++
++ tmp->regex_string = kmalloc(strlen(regex_string) + 1, GFP_ATOMIC);
++ tmp->pattern = kmalloc(sizeof(struct regexp), GFP_ATOMIC);
++ tmp->next = NULL;
++
++ if(!tmp->regex_string || !tmp->pattern) {
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in compile_and_cache, bailing.\n");
++ kfree(tmp->regex_string);
++ kfree(tmp->pattern);
++ kfree(tmp);
++ return NULL;
++ }
++
++ /* Ok. The new node is all ready now. */
++ node = tmp;
++
++ if(first_pattern_cache == NULL) /* list is empty */
++ first_pattern_cache = node; /* make node the beginning */
++ else
++ last_pattern_cache->next = node; /* attach node to the end */
++
++ /* copy the string and compile the regex */
++ len = strlen(regex_string);
++ DPRINTK("About to compile this: \"%s\"\n", regex_string);
++ node->pattern = regcomp(regex_string, &len);
++ if ( !node->pattern ) {
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: Error compiling regexp \"%s\" (%s)\n", regex_string, protocol);
++ /* pattern is now cached as NULL, so we won't try again. */
++ }
++
++ strcpy(node->regex_string, regex_string);
++ return node->pattern;
++}
++
++static int can_handle(const struct sk_buff *skb)
++{
++ if(!skb->nh.iph) /* not IP */
++ return 0;
++ if(skb->nh.iph->protocol != IPPROTO_TCP &&
++ skb->nh.iph->protocol != IPPROTO_UDP &&
++ skb->nh.iph->protocol != IPPROTO_ICMP)
++ return 0;
++ return 1;
++}
++
++/* Returns offset the into the skb->data that the application data starts */
++static int app_data_offset(const struct sk_buff *skb)
++{
++ /* In case we are ported somewhere (ebtables?) where skb->nh.iph
++ isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */
++ int ip_hl = 4*skb->nh.iph->ihl;
++
++ if( skb->nh.iph->protocol == IPPROTO_TCP ) {
++ /* 12 == offset into TCP header for the header length field.
++ Can't get this with skb->h.th->doff because the tcphdr
++ struct doesn't get set when routing (this is confirmed to be
++ true in Netfilter as well as QoS.) */
++ int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4);
++
++ return ip_hl + tcp_hl;
++ } else if( skb->nh.iph->protocol == IPPROTO_UDP ) {
++ return ip_hl + 8; /* UDP header is always 8 bytes */
++ } else if( skb->nh.iph->protocol == IPPROTO_ICMP ) {
++ return ip_hl + 8; /* ICMP header is 8 bytes */
++ } else {
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: tried to handle unknown protocol!\n");
++ return ip_hl + 8; /* something reasonable */
++ }
++}
++
++/* handles whether there's a match when we aren't appending data anymore */
++static int match_no_append(struct ip_conntrack * conntrack, struct ip_conntrack * master_conntrack,
++ enum ip_conntrack_info ctinfo, enum ip_conntrack_info master_ctinfo,
++ struct ipt_layer7_info * info)
++{
++ /* If we're in here, throw the app data away */
++ WRITE_LOCK(&ct_lock);
++ if(master_conntrack->layer7.app_data != NULL) {
++
++ #ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
++ if(!master_conntrack->layer7.app_proto) {
++ char * f = friendly_print(master_conntrack->layer7.app_data);
++ char * g = hex_print(master_conntrack->layer7.app_data);
++ DPRINTK("\nl7-filter gave up after %d bytes (%d packets):\n%s\n",
++ strlen(f),
++ TOTAL_PACKETS, f);
++ kfree(f);
++ DPRINTK("In hex: %s\n", g);
++ kfree(g);
++ }
++ #endif
++
++ kfree(master_conntrack->layer7.app_data);
++ master_conntrack->layer7.app_data = NULL; /* don't free again */
++ }
++ WRITE_UNLOCK(&ct_lock);
++
++ if(master_conntrack->layer7.app_proto){
++ /* Here child connections set their .app_proto (for /proc/net/ip_conntrack) */
++ WRITE_LOCK(&ct_lock);
++ if(!conntrack->layer7.app_proto) {
++ conntrack->layer7.app_proto = kmalloc(strlen(master_conntrack->layer7.app_proto)+1, GFP_ATOMIC);
++ if(!conntrack->layer7.app_proto){
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in match_no_append, bailing.\n");
++ WRITE_UNLOCK(&ct_lock);
++ return 1;
++ }
++ strcpy(conntrack->layer7.app_proto, master_conntrack->layer7.app_proto);
++ }
++ WRITE_UNLOCK(&ct_lock);
++
++ return (!strcmp(master_conntrack->layer7.app_proto, info->protocol));
++ }
++ else {
++ /* If not classified, set to "unknown" to distinguish from
++ connections that are still being tested. */
++ WRITE_LOCK(&ct_lock);
++ master_conntrack->layer7.app_proto = kmalloc(strlen("unknown")+1, GFP_ATOMIC);
++ if(!master_conntrack->layer7.app_proto){
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in match_no_append, bailing.\n");
++ WRITE_UNLOCK(&ct_lock);
++ return 1;
++ }
++ strcpy(master_conntrack->layer7.app_proto, "unknown");
++ WRITE_UNLOCK(&ct_lock);
++ return 0;
++ }
++}
++
++static int add_datastr(char *target, int offset, char *app_data, int len)
++{
++ int length = 0, i;
++
++ /* Strip nulls. Make everything lower case (our regex lib doesn't
++ do case insensitivity). Add it to the end of the current data. */
++ for(i = 0; i < maxdatalen-offset-1 && i < len; i++) {
++ if(app_data[i] != '\0') {
++ target[length+offset] =
++ /* the kernel version of tolower mungs 'upper ascii' */
++ isascii(app_data[i])? tolower(app_data[i]) : app_data[i];
++ length++;
++ }
++ }
++
++ target[length+offset] = '\0';
++
++ return length;
++}
++
++/* add the new app data to the conntrack. Return number of bytes added. */
++static int add_data(struct ip_conntrack * master_conntrack,
++ char * app_data, int appdatalen)
++{
++ int length;
++
++ length = add_datastr(master_conntrack->layer7.app_data, master_conntrack->layer7.app_data_len, app_data, appdatalen);
++ master_conntrack->layer7.app_data_len += length;
++
++ return length;
++}
++
++/* Returns true on match and false otherwise. */
++static int match(/* const */struct sk_buff *skb, const struct net_device *in,
++ const struct net_device *out, const void *matchinfo,
++ int offset, int *hotdrop)
++{
++ struct ipt_layer7_info * info = (struct ipt_layer7_info *)matchinfo;
++ enum ip_conntrack_info master_ctinfo, ctinfo;
++ struct ip_conntrack *master_conntrack, *conntrack;
++ unsigned char *app_data, *tmp_data;
++ unsigned int pattern_result, appdatalen;
++ regexp * comppattern;
++
++ if(!can_handle(skb)){
++ DPRINTK("layer7: This is some protocol I can't handle.\n");
++ return info->invert;
++ }
++
++ /* Treat the parent and all its children together as one connection,
++ except for the purpose of setting conntrack->layer7.app_proto in the
++ actual connection. This makes /proc/net/ip_conntrack somewhat more
++ satisfying. */
++ if(!(conntrack = ip_conntrack_get((struct sk_buff *)skb, &ctinfo)) ||
++ !(master_conntrack = ip_conntrack_get((struct sk_buff *)skb, &master_ctinfo))) {
++ DPRINTK("layer7: packet is not from a known connection, giving up.\n");
++ return info->invert;
++ }
++
++ /* Try to get a master conntrack (and its master etc) for FTP, etc. */
++ while (master_ct(master_conntrack) != NULL)
++ master_conntrack = master_ct(master_conntrack);
++
++ if(!skb->cb[0]){
++ WRITE_LOCK(&ct_lock);
++ master_conntrack->layer7.numpackets++;/*starts at 0 via memset*/
++ WRITE_UNLOCK(&ct_lock);
++ }
++
++ /* if we've classified it or seen too many packets */
++ if(!info->pkt && (TOTAL_PACKETS > num_packets ||
++ master_conntrack->layer7.app_proto)) {
++
++ pattern_result = match_no_append(conntrack, master_conntrack, ctinfo, master_ctinfo, info);
++
++ /* skb->cb[0] == seen. Avoid doing things twice if there are two l7
++ rules. I'm not sure that using cb for this purpose is correct, although
++ it says "put your private variables there". But it doesn't look like it
++ is being used for anything else in the skbs that make it here. How can
++ I write to cb without making the compiler angry? */
++ skb->cb[0] = 1; /* marking it seen here is probably irrelevant, but consistant */
++
++ return (pattern_result ^ info->invert);
++ }
++
++ if(skb_is_nonlinear(skb)){
++ if(skb_linearize(skb, GFP_ATOMIC) != 0){
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: failed to linearize packet, bailing.\n");
++ return info->invert;
++ }
++ }
++
++ /* now that the skb is linearized, it's safe to set these. */
++ app_data = skb->data + app_data_offset(skb);
++ appdatalen = skb->tail - app_data;
++
++ LOCK_BH(&list_lock);
++ /* the return value gets checked later, when we're ready to use it */
++ comppattern = compile_and_cache(info->pattern, info->protocol);
++ UNLOCK_BH(&list_lock);
++
++ if (info->pkt) {
++ tmp_data = kmalloc(maxdatalen, GFP_ATOMIC);
++ if(!tmp_data){
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
++ return info->invert;
++ }
++
++ tmp_data[0] = '\0';
++ add_datastr(tmp_data, 0, app_data, appdatalen);
++ pattern_result = ((comppattern && regexec(comppattern, tmp_data)) ? 1 : 0);
++ kfree(tmp_data);
++ tmp_data = NULL;
++
++ return (pattern_result ^ info->invert);
++ }
++
++ /* On the first packet of a connection, allocate space for app data */
++ WRITE_LOCK(&ct_lock);
++ if(TOTAL_PACKETS == 1 && !skb->cb[0] && !master_conntrack->layer7.app_data) {
++ master_conntrack->layer7.app_data = kmalloc(maxdatalen, GFP_ATOMIC);
++ if(!master_conntrack->layer7.app_data){
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
++ WRITE_UNLOCK(&ct_lock);
++ return info->invert;
++ }
++
++ master_conntrack->layer7.app_data[0] = '\0';
++ }
++ WRITE_UNLOCK(&ct_lock);
++
++ /* Can be here, but unallocated, if numpackets is increased near
++ the beginning of a connection */
++ if(master_conntrack->layer7.app_data == NULL)
++ return (info->invert); /* unmatched */
++
++ if(!skb->cb[0]){
++ int newbytes;
++ WRITE_LOCK(&ct_lock);
++ newbytes = add_data(master_conntrack, app_data, appdatalen);
++ WRITE_UNLOCK(&ct_lock);
++
++ if(newbytes == 0) { /* didn't add any data */
++ skb->cb[0] = 1;
++ /* Didn't match before, not going to match now */
++ return info->invert;
++ }
++ }
++
++ /* If looking for "unknown", then never match. "Unknown" means that
++ we've given up; we're still trying with these packets. */
++ if(!strcmp(info->protocol, "unknown")) {
++ pattern_result = 0;
++ /* If the regexp failed to compile, don't bother running it */
++ } else if(comppattern && regexec(comppattern, master_conntrack->layer7.app_data)) {
++ DPRINTK("layer7: regexec positive: %s!\n", info->protocol);
++ pattern_result = 1;
++ } else pattern_result = 0;
++
++ if(pattern_result) {
++ WRITE_LOCK(&ct_lock);
++ master_conntrack->layer7.app_proto = kmalloc(strlen(info->protocol)+1, GFP_ATOMIC);
++ if(!master_conntrack->layer7.app_proto){
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
++ WRITE_UNLOCK(&ct_lock);
++ return (pattern_result ^ info->invert);
++ }
++ strcpy(master_conntrack->layer7.app_proto, info->protocol);
++ WRITE_UNLOCK(&ct_lock);
++ }
++
++ /* mark the packet seen */
++ skb->cb[0] = 1;
++
++ return (pattern_result ^ info->invert);
++}
++
++static int checkentry(const char *tablename, const struct ipt_ip *ip,
++ void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
++{
++ if (matchsize != IPT_ALIGN(sizeof(struct ipt_layer7_info)))
++ return 0;
++ return 1;
++}
++
++static struct ipt_match layer7_match = {
++ .name = "layer7",
++ .match = &match,
++ .checkentry = &checkentry,
++ .me = THIS_MODULE
++};
++
++/* taken from drivers/video/modedb.c */
++static int my_atoi(const char *s)
++{
++ int val = 0;
++
++ for (;; s++) {
++ switch (*s) {
++ case '0'...'9':
++ val = 10*val+(*s-'0');
++ break;
++ default:
++ return val;
++ }
++ }
++}
++
++/* write out num_packets to userland. */
++static int layer7_read_proc(char* page, char ** start, off_t off, int count,
++ int* eof, void * data)
++{
++ if(num_packets > 99 && net_ratelimit())
++ printk(KERN_ERR "layer7: NOT REACHED. num_packets too big\n");
++
++ page[0] = num_packets/10 + '0';
++ page[1] = num_packets%10 + '0';
++ page[2] = '\n';
++ page[3] = '\0';
++
++ *eof=1;
++
++ return 3;
++}
++
++/* Read in num_packets from userland */
++static int layer7_write_proc(struct file* file, const char* buffer,
++ unsigned long count, void *data)
++{
++ char * foo = kmalloc(count, GFP_ATOMIC);
++
++ if(!foo){
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory, bailing. num_packets unchanged.\n");
++ return count;
++ }
++
++ copy_from_user(foo, buffer, count);
++
++ num_packets = my_atoi(foo);
++ kfree (foo);
++
++ /* This has an arbitrary limit to make the math easier. I'm lazy.
++ But anyway, 99 is a LOT! If you want more, you're doing it wrong! */
++ if(num_packets > 99) {
++ printk(KERN_WARNING "layer7: num_packets can't be > 99.\n");
++ num_packets = 99;
++ } else if(num_packets < 1) {
++ printk(KERN_WARNING "layer7: num_packets can't be < 1.\n");
++ num_packets = 1;
++ }
++
++ return count;
++}
++
++/* register the proc file */
++static void layer7_init_proc(void)
++{
++ struct proc_dir_entry* entry;
++ entry = create_proc_entry("layer7_numpackets", 0644, proc_net);
++ entry->read_proc = layer7_read_proc;
++ entry->write_proc = layer7_write_proc;
++}
++
++static void layer7_cleanup_proc(void)
++{
++ remove_proc_entry("layer7_numpackets", proc_net);
++}
++
++static int __init init(void)
++{
++ layer7_init_proc();
++ if(maxdatalen < 1) {
++ printk(KERN_WARNING "layer7: maxdatalen can't be < 1, using 1\n");
++ maxdatalen = 1;
++ }
++ /* This is not a hard limit. It's just here to prevent people from
++ bringing their slow machines to a grinding halt. */
++ else if(maxdatalen > 65536) {
++ printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, using 65536\n");
++ maxdatalen = 65536;
++ }
++ return ipt_register_match(&layer7_match);
++}
++
++static void __exit fini(void)
++{
++ layer7_cleanup_proc();
++ ipt_unregister_match(&layer7_match);
++}
++
++module_init(init);
++module_exit(fini);
+diff -urN linux.old/net/ipv4/netfilter/regexp/regexp.c linux.dev/net/ipv4/netfilter/regexp/regexp.c
+--- linux.old/net/ipv4/netfilter/regexp/regexp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/net/ipv4/netfilter/regexp/regexp.c 2006-01-31 16:58:24.819335750 +0100
+@@ -0,0 +1,1195 @@
++/*
++ * regcomp and regexec -- regsub and regerror are elsewhere
++ * @(#)regexp.c 1.3 of 18 April 87
++ *
++ * Copyright (c) 1986 by University of Toronto.
++ * Written by Henry Spencer. Not derived from licensed software.
++ *
++ * Permission is granted to anyone to use this software for any
++ * purpose on any computer system, and to redistribute it freely,
++ * subject to the following restrictions:
++ *
++ * 1. The author is not responsible for the consequences of use of
++ * this software, no matter how awful, even if they arise
++ * from defects in it.
++ *
++ * 2. The origin of this software must not be misrepresented, either
++ * by explicit claim or by omission.
++ *
++ * 3. Altered versions must be plainly marked as such, and must not
++ * be misrepresented as being the original software.
++ *
++ * Beware that some of this code is subtly aware of the way operator
++ * precedence is structured in regular expressions. Serious changes in
++ * regular-expression syntax might require a total rethink.
++ *
++ * This code was modified by Ethan Sommer to work within the kernel
++ * (it now uses kmalloc etc..)
++ *
++ * Modified slightly by Matthew Strait to use more modern C.
++ */
++
++#include "regexp.h"
++#include "regmagic.h"
++
++/* added by ethan and matt. Lets it work in both kernel and user space.
++(So iptables can use it, for instance.) Yea, it goes both ways... */
++#if __KERNEL__
++ #define malloc(foo) kmalloc(foo,GFP_ATOMIC)
++#else
++ #define printk(format,args...) printf(format,##args)
++#endif
++
++void regerror(char * s)
++{
++ printk("<3>Regexp: %s\n", s);
++ /* NOTREACHED */
++}
++
++/*
++ * The "internal use only" fields in regexp.h are present to pass info from
++ * compile to execute that permits the execute phase to run lots faster on
++ * simple cases. They are:
++ *
++ * regstart char that must begin a match; '\0' if none obvious
++ * reganch is the match anchored (at beginning-of-line only)?
++ * regmust string (pointer into program) that match must include, or NULL
++ * regmlen length of regmust string
++ *
++ * Regstart and reganch permit very fast decisions on suitable starting points
++ * for a match, cutting down the work a lot. Regmust permits fast rejection
++ * of lines that cannot possibly match. The regmust tests are costly enough
++ * that regcomp() supplies a regmust only if the r.e. contains something
++ * potentially expensive (at present, the only such thing detected is * or +
++ * at the start of the r.e., which can involve a lot of backup). Regmlen is
++ * supplied because the test in regexec() needs it and regcomp() is computing
++ * it anyway.
++ */
++
++/*
++ * Structure for regexp "program". This is essentially a linear encoding
++ * of a nondeterministic finite-state machine (aka syntax charts or
++ * "railroad normal form" in parsing technology). Each node is an opcode
++ * plus a "next" pointer, possibly plus an operand. "Next" pointers of
++ * all nodes except BRANCH implement concatenation; a "next" pointer with
++ * a BRANCH on both ends of it is connecting two alternatives. (Here we
++ * have one of the subtle syntax dependencies: an individual BRANCH (as
++ * opposed to a collection of them) is never concatenated with anything
++ * because of operator precedence.) The operand of some types of node is
++ * a literal string; for others, it is a node leading into a sub-FSM. In
++ * particular, the operand of a BRANCH node is the first node of the branch.
++ * (NB this is *not* a tree structure: the tail of the branch connects
++ * to the thing following the set of BRANCHes.) The opcodes are:
++ */
++
++/* definition number opnd? meaning */
++#define END 0 /* no End of program. */
++#define BOL 1 /* no Match "" at beginning of line. */
++#define EOL 2 /* no Match "" at end of line. */
++#define ANY 3 /* no Match any one character. */
++#define ANYOF 4 /* str Match any character in this string. */
++#define ANYBUT 5 /* str Match any character not in this string. */
++#define BRANCH 6 /* node Match this alternative, or the next... */
++#define BACK 7 /* no Match "", "next" ptr points backward. */
++#define EXACTLY 8 /* str Match this string. */
++#define NOTHING 9 /* no Match empty string. */
++#define STAR 10 /* node Match this (simple) thing 0 or more times. */
++#define PLUS 11 /* node Match this (simple) thing 1 or more times. */
++#define OPEN 20 /* no Mark this point in input as start of #n. */
++ /* OPEN+1 is number 1, etc. */
++#define CLOSE 30 /* no Analogous to OPEN. */
++
++/*
++ * Opcode notes:
++ *
++ * BRANCH The set of branches constituting a single choice are hooked
++ * together with their "next" pointers, since precedence prevents
++ * anything being concatenated to any individual branch. The
++ * "next" pointer of the last BRANCH in a choice points to the
++ * thing following the whole choice. This is also where the
++ * final "next" pointer of each individual branch points; each
++ * branch starts with the operand node of a BRANCH node.
++ *
++ * BACK Normal "next" pointers all implicitly point forward; BACK
++ * exists to make loop structures possible.
++ *
++ * STAR,PLUS '?', and complex '*' and '+', are implemented as circular
++ * BRANCH structures using BACK. Simple cases (one character
++ * per match) are implemented with STAR and PLUS for speed
++ * and to minimize recursive plunges.
++ *
++ * OPEN,CLOSE ...are numbered at compile time.
++ */
++
++/*
++ * A node is one char of opcode followed by two chars of "next" pointer.
++ * "Next" pointers are stored as two 8-bit pieces, high order first. The
++ * value is a positive offset from the opcode of the node containing it.
++ * An operand, if any, simply follows the node. (Note that much of the
++ * code generation knows about this implicit relationship.)
++ *
++ * Using two bytes for the "next" pointer is vast overkill for most things,
++ * but allows patterns to get big without disasters.
++ */
++#define OP(p) (*(p))
++#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
++#define OPERAND(p) ((p) + 3)
++
++/*
++ * See regmagic.h for one further detail of program structure.
++ */
++
++
++/*
++ * Utility definitions.
++ */
++#ifndef CHARBITS
++#define UCHARAT(p) ((int)*(unsigned char *)(p))
++#else
++#define UCHARAT(p) ((int)*(p)&CHARBITS)
++#endif
++
++#define FAIL(m) { regerror(m); return(NULL); }
++#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?')
++#define META "^$.[()|?+*\\"
++
++/*
++ * Flags to be passed up and down.
++ */
++#define HASWIDTH 01 /* Known never to match null string. */
++#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */
++#define SPSTART 04 /* Starts with * or +. */
++#define WORST 0 /* Worst case. */
++
++/*
++ * Global work variables for regcomp().
++ */
++static char *regparse; /* Input-scan pointer. */
++static int regnpar; /* () count. */
++static char regdummy;
++static char *regcode; /* Code-emit pointer; &regdummy = don't. */
++static long regsize; /* Code size. */
++
++/*
++ * Forward declarations for regcomp()'s friends.
++ */
++#ifndef STATIC
++#define STATIC static
++#endif
++STATIC char *reg(int paren,int *flagp);
++STATIC char *regbranch(int *flagp);
++STATIC char *regpiece(int *flagp);
++STATIC char *regatom(int *flagp);
++STATIC char *regnode(char op);
++STATIC char *regnext(char *p);
++STATIC void regc(char b);
++STATIC void reginsert(char op, char *opnd);
++STATIC void regtail(char *p, char *val);
++STATIC void regoptail(char *p, char *val);
++
++
++__kernel_size_t my_strcspn(const char *s1,const char *s2)
++{
++ char *scan1;
++ char *scan2;
++ int count;
++
++ count = 0;
++ for (scan1 = (char *)s1; *scan1 != '\0'; scan1++) {
++ for (scan2 = (char *)s2; *scan2 != '\0';) /* ++ moved down. */
++ if (*scan1 == *scan2++)
++ return(count);
++ count++;
++ }
++ return(count);
++}
++
++/*
++ - regcomp - compile a regular expression into internal code
++ *
++ * We can't allocate space until we know how big the compiled form will be,
++ * but we can't compile it (and thus know how big it is) until we've got a
++ * place to put the code. So we cheat: we compile it twice, once with code
++ * generation turned off and size counting turned on, and once "for real".
++ * This also means that we don't allocate space until we are sure that the
++ * thing really will compile successfully, and we never have to move the
++ * code and thus invalidate pointers into it. (Note that it has to be in
++ * one piece because free() must be able to free it all.)
++ *
++ * Beware that the optimization-preparation code in here knows about some
++ * of the structure of the compiled regexp.
++ */
++regexp *
++regcomp(char *exp,int *patternsize)
++{
++ register regexp *r;
++ register char *scan;
++ register char *longest;
++ register int len;
++ int flags;
++ /* commented out by ethan
++ extern char *malloc();
++ */
++
++ if (exp == NULL)
++ FAIL("NULL argument");
++
++ /* First pass: determine size, legality. */
++ regparse = exp;
++ regnpar = 1;
++ regsize = 0L;
++ regcode = &regdummy;
++ regc(MAGIC);
++ if (reg(0, &flags) == NULL)
++ return(NULL);
++
++ /* Small enough for pointer-storage convention? */
++ if (regsize >= 32767L) /* Probably could be 65535L. */
++ FAIL("regexp too big");
++
++ /* Allocate space. */
++ *patternsize=sizeof(regexp) + (unsigned)regsize;
++ r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize);
++ if (r == NULL)
++ FAIL("out of space");
++
++ /* Second pass: emit code. */
++ regparse = exp;
++ regnpar = 1;
++ regcode = r->program;
++ regc(MAGIC);
++ if (reg(0, &flags) == NULL)
++ return(NULL);
++
++ /* Dig out information for optimizations. */
++ r->regstart = '\0'; /* Worst-case defaults. */
++ r->reganch = 0;
++ r->regmust = NULL;
++ r->regmlen = 0;
++ scan = r->program+1; /* First BRANCH. */
++ if (OP(regnext(scan)) == END) { /* Only one top-level choice. */
++ scan = OPERAND(scan);
++
++ /* Starting-point info. */
++ if (OP(scan) == EXACTLY)
++ r->regstart = *OPERAND(scan);
++ else if (OP(scan) == BOL)
++ r->reganch++;
++
++ /*
++ * If there's something expensive in the r.e., find the
++ * longest literal string that must appear and make it the
++ * regmust. Resolve ties in favor of later strings, since
++ * the regstart check works with the beginning of the r.e.
++ * and avoiding duplication strengthens checking. Not a
++ * strong reason, but sufficient in the absence of others.
++ */
++ if (flags&SPSTART) {
++ longest = NULL;
++ len = 0;
++ for (; scan != NULL; scan = regnext(scan))
++ if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
++ longest = OPERAND(scan);
++ len = strlen(OPERAND(scan));
++ }
++ r->regmust = longest;
++ r->regmlen = len;
++ }
++ }
++
++ return(r);
++}
++
++/*
++ - reg - regular expression, i.e. main body or parenthesized thing
++ *
++ * Caller must absorb opening parenthesis.
++ *
++ * Combining parenthesis handling with the base level of regular expression
++ * is a trifle forced, but the need to tie the tails of the branches to what
++ * follows makes it hard to avoid.
++ */
++static char *
++reg(int paren, int *flagp /* Parenthesized? */ )
++{
++ register char *ret;
++ register char *br;
++ register char *ender;
++ register int parno = 0; /* 0 makes gcc happy */
++ int flags;
++
++ *flagp = HASWIDTH; /* Tentatively. */
++
++ /* Make an OPEN node, if parenthesized. */
++ if (paren) {
++ if (regnpar >= NSUBEXP)
++ FAIL("too many ()");
++ parno = regnpar;
++ regnpar++;
++ ret = regnode(OPEN+parno);
++ } else
++ ret = NULL;
++
++ /* Pick up the branches, linking them together. */
++ br = regbranch(&flags);
++ if (br == NULL)
++ return(NULL);
++ if (ret != NULL)
++ regtail(ret, br); /* OPEN -> first. */
++ else
++ ret = br;
++ if (!(flags&HASWIDTH))
++ *flagp &= ~HASWIDTH;
++ *flagp |= flags&SPSTART;
++ while (*regparse == '|') {
++ regparse++;
++ br = regbranch(&flags);
++ if (br == NULL)
++ return(NULL);
++ regtail(ret, br); /* BRANCH -> BRANCH. */
++ if (!(flags&HASWIDTH))
++ *flagp &= ~HASWIDTH;
++ *flagp |= flags&SPSTART;
++ }
++
++ /* Make a closing node, and hook it on the end. */
++ ender = regnode((paren) ? CLOSE+parno : END);
++ regtail(ret, ender);
++
++ /* Hook the tails of the branches to the closing node. */
++ for (br = ret; br != NULL; br = regnext(br))
++ regoptail(br, ender);
++
++ /* Check for proper termination. */
++ if (paren && *regparse++ != ')') {
++ FAIL("unmatched ()");
++ } else if (!paren && *regparse != '\0') {
++ if (*regparse == ')') {
++ FAIL("unmatched ()");
++ } else
++ FAIL("junk on end"); /* "Can't happen". */
++ /* NOTREACHED */
++ }
++
++ return(ret);
++}
++
++/*
++ - regbranch - one alternative of an | operator
++ *
++ * Implements the concatenation operator.
++ */
++static char *
++regbranch(int *flagp)
++{
++ register char *ret;
++ register char *chain;
++ register char *latest;
++ int flags;
++
++ *flagp = WORST; /* Tentatively. */
++
++ ret = regnode(BRANCH);
++ chain = NULL;
++ while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
++ latest = regpiece(&flags);
++ if (latest == NULL)
++ return(NULL);
++ *flagp |= flags&HASWIDTH;
++ if (chain == NULL) /* First piece. */
++ *flagp |= flags&SPSTART;
++ else
++ regtail(chain, latest);
++ chain = latest;
++ }
++ if (chain == NULL) /* Loop ran zero times. */
++ (void) regnode(NOTHING);
++
++ return(ret);
++}
++
++/*
++ - regpiece - something followed by possible [*+?]
++ *
++ * Note that the branching code sequences used for ? and the general cases
++ * of * and + are somewhat optimized: they use the same NOTHING node as
++ * both the endmarker for their branch list and the body of the last branch.
++ * It might seem that this node could be dispensed with entirely, but the
++ * endmarker role is not redundant.
++ */
++static char *
++regpiece(int *flagp)
++{
++ register char *ret;
++ register char op;
++ register char *next;
++ int flags;
++
++ ret = regatom(&flags);
++ if (ret == NULL)
++ return(NULL);
++
++ op = *regparse;
++ if (!ISMULT(op)) {
++ *flagp = flags;
++ return(ret);
++ }
++
++ if (!(flags&HASWIDTH) && op != '?')
++ FAIL("*+ operand could be empty");
++ *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
++
++ if (op == '*' && (flags&SIMPLE))
++ reginsert(STAR, ret);
++ else if (op == '*') {
++ /* Emit x* as (x&|), where & means "self". */
++ reginsert(BRANCH, ret); /* Either x */
++ regoptail(ret, regnode(BACK)); /* and loop */
++ regoptail(ret, ret); /* back */
++ regtail(ret, regnode(BRANCH)); /* or */
++ regtail(ret, regnode(NOTHING)); /* null. */
++ } else if (op == '+' && (flags&SIMPLE))
++ reginsert(PLUS, ret);
++ else if (op == '+') {
++ /* Emit x+ as x(&|), where & means "self". */
++ next = regnode(BRANCH); /* Either */
++ regtail(ret, next);
++ regtail(regnode(BACK), ret); /* loop back */
++ regtail(next, regnode(BRANCH)); /* or */
++ regtail(ret, regnode(NOTHING)); /* null. */
++ } else if (op == '?') {
++ /* Emit x? as (x|) */
++ reginsert(BRANCH, ret); /* Either x */
++ regtail(ret, regnode(BRANCH)); /* or */
++ next = regnode(NOTHING); /* null. */
++ regtail(ret, next);
++ regoptail(ret, next);
++ }
++ regparse++;
++ if (ISMULT(*regparse))
++ FAIL("nested *?+");
++
++ return(ret);
++}
++
++/*
++ - regatom - the lowest level
++ *
++ * Optimization: gobbles an entire sequence of ordinary characters so that
++ * it can turn them into a single node, which is smaller to store and
++ * faster to run. Backslashed characters are exceptions, each becoming a
++ * separate node; the code is simpler that way and it's not worth fixing.
++ */
++static char *
++regatom(int *flagp)
++{
++ register char *ret;
++ int flags;
++
++ *flagp = WORST; /* Tentatively. */
++
++ switch (*regparse++) {
++ case '^':
++ ret = regnode(BOL);
++ break;
++ case '$':
++ ret = regnode(EOL);
++ break;
++ case '.':
++ ret = regnode(ANY);
++ *flagp |= HASWIDTH|SIMPLE;
++ break;
++ case '[': {
++ register int class;
++ register int classend;
++
++ if (*regparse == '^') { /* Complement of range. */
++ ret = regnode(ANYBUT);
++ regparse++;
++ } else
++ ret = regnode(ANYOF);
++ if (*regparse == ']' || *regparse == '-')
++ regc(*regparse++);
++ while (*regparse != '\0' && *regparse != ']') {
++ if (*regparse == '-') {
++ regparse++;
++ if (*regparse == ']' || *regparse == '\0')
++ regc('-');
++ else {
++ class = UCHARAT(regparse-2)+1;
++ classend = UCHARAT(regparse);
++ if (class > classend+1)
++ FAIL("invalid [] range");
++ for (; class <= classend; class++)
++ regc(class);
++ regparse++;
++ }
++ } else
++ regc(*regparse++);
++ }
++ regc('\0');
++ if (*regparse != ']')
++ FAIL("unmatched []");
++ regparse++;
++ *flagp |= HASWIDTH|SIMPLE;
++ }
++ break;
++ case '(':
++ ret = reg(1, &flags);
++ if (ret == NULL)
++ return(NULL);
++ *flagp |= flags&(HASWIDTH|SPSTART);
++ break;
++ case '\0':
++ case '|':
++ case ')':
++ FAIL("internal urp"); /* Supposed to be caught earlier. */
++ break;
++ case '?':
++ case '+':
++ case '*':
++ FAIL("?+* follows nothing");
++ break;
++ case '\\':
++ if (*regparse == '\0')
++ FAIL("trailing \\");
++ ret = regnode(EXACTLY);
++ regc(*regparse++);
++ regc('\0');
++ *flagp |= HASWIDTH|SIMPLE;
++ break;
++ default: {
++ register int len;
++ register char ender;
++
++ regparse--;
++ len = my_strcspn((const char *)regparse, (const char *)META);
++ if (len <= 0)
++ FAIL("internal disaster");
++ ender = *(regparse+len);
++ if (len > 1 && ISMULT(ender))
++ len--; /* Back off clear of ?+* operand. */
++ *flagp |= HASWIDTH;
++ if (len == 1)
++ *flagp |= SIMPLE;
++ ret = regnode(EXACTLY);
++ while (len > 0) {
++ regc(*regparse++);
++ len--;
++ }
++ regc('\0');
++ }
++ break;
++ }
++
++ return(ret);
++}
++
++/*
++ - regnode - emit a node
++ */
++static char * /* Location. */
++regnode(char op)
++{
++ register char *ret;
++ register char *ptr;
++
++ ret = regcode;
++ if (ret == &regdummy) {
++ regsize += 3;
++ return(ret);
++ }
++
++ ptr = ret;
++ *ptr++ = op;
++ *ptr++ = '\0'; /* Null "next" pointer. */
++ *ptr++ = '\0';
++ regcode = ptr;
++
++ return(ret);
++}
++
++/*
++ - regc - emit (if appropriate) a byte of code
++ */
++static void
++regc(char b)
++{
++ if (regcode != &regdummy)
++ *regcode++ = b;
++ else
++ regsize++;
++}
++
++/*
++ - reginsert - insert an operator in front of already-emitted operand
++ *
++ * Means relocating the operand.
++ */
++static void
++reginsert(char op, char* opnd)
++{
++ register char *src;
++ register char *dst;
++ register char *place;
++
++ if (regcode == &regdummy) {
++ regsize += 3;
++ return;
++ }
++
++ src = regcode;
++ regcode += 3;
++ dst = regcode;
++ while (src > opnd)
++ *--dst = *--src;
++
++ place = opnd; /* Op node, where operand used to be. */
++ *place++ = op;
++ *place++ = '\0';
++ *place++ = '\0';
++}
++
++/*
++ - regtail - set the next-pointer at the end of a node chain
++ */
++static void
++regtail(char *p, char *val)
++{
++ register char *scan;
++ register char *temp;
++ register int offset;
++
++ if (p == &regdummy)
++ return;
++
++ /* Find last node. */
++ scan = p;
++ for (;;) {
++ temp = regnext(scan);
++ if (temp == NULL)
++ break;
++ scan = temp;
++ }
++
++ if (OP(scan) == BACK)
++ offset = scan - val;
++ else
++ offset = val - scan;
++ *(scan+1) = (offset>>8)&0377;
++ *(scan+2) = offset&0377;
++}
++
++/*
++ - regoptail - regtail on operand of first argument; nop if operandless
++ */
++static void
++regoptail(char *p, char *val)
++{
++ /* "Operandless" and "op != BRANCH" are synonymous in practice. */
++ if (p == NULL || p == &regdummy || OP(p) != BRANCH)
++ return;
++ regtail(OPERAND(p), val);
++}
++
++/*
++ * regexec and friends
++ */
++
++/*
++ * Global work variables for regexec().
++ */
++static char *reginput; /* String-input pointer. */
++static char *regbol; /* Beginning of input, for ^ check. */
++static char **regstartp; /* Pointer to startp array. */
++static char **regendp; /* Ditto for endp. */
++
++/*
++ * Forwards.
++ */
++STATIC int regtry(regexp *prog, char *string);
++STATIC int regmatch(char *prog);
++STATIC int regrepeat(char *p);
++
++#ifdef DEBUG
++int regnarrate = 0;
++void regdump();
++STATIC char *regprop(char *op);
++#endif
++
++/*
++ - regexec - match a regexp against a string
++ */
++int
++regexec(regexp *prog, char *string)
++{
++ register char *s;
++
++ /* Be paranoid... */
++ if (prog == NULL || string == NULL) {
++ printk("<3>Regexp: NULL parameter\n");
++ return(0);
++ }
++
++ /* Check validity of program. */
++ if (UCHARAT(prog->program) != MAGIC) {
++ printk("<3>Regexp: corrupted program\n");
++ return(0);
++ }
++
++ /* If there is a "must appear" string, look for it. */
++ if (prog->regmust != NULL) {
++ s = string;
++ while ((s = strchr(s, prog->regmust[0])) != NULL) {
++ if (strncmp(s, prog->regmust, prog->regmlen) == 0)
++ break; /* Found it. */
++ s++;
++ }
++ if (s == NULL) /* Not present. */
++ return(0);
++ }
++
++ /* Mark beginning of line for ^ . */
++ regbol = string;
++
++ /* Simplest case: anchored match need be tried only once. */
++ if (prog->reganch)
++ return(regtry(prog, string));
++
++ /* Messy cases: unanchored match. */
++ s = string;
++ if (prog->regstart != '\0')
++ /* We know what char it must start with. */
++ while ((s = strchr(s, prog->regstart)) != NULL) {
++ if (regtry(prog, s))
++ return(1);
++ s++;
++ }
++ else
++ /* We don't -- general case. */
++ do {
++ if (regtry(prog, s))
++ return(1);
++ } while (*s++ != '\0');
++
++ /* Failure. */
++ return(0);
++}
++
++/*
++ - regtry - try match at specific point
++ */
++static int /* 0 failure, 1 success */
++regtry(regexp *prog, char *string)
++{
++ register int i;
++ register char **sp;
++ register char **ep;
++
++ reginput = string;
++ regstartp = prog->startp;
++ regendp = prog->endp;
++
++ sp = prog->startp;
++ ep = prog->endp;
++ for (i = NSUBEXP; i > 0; i--) {
++ *sp++ = NULL;
++ *ep++ = NULL;
++ }
++ if (regmatch(prog->program + 1)) {
++ prog->startp[0] = string;
++ prog->endp[0] = reginput;
++ return(1);
++ } else
++ return(0);
++}
++
++/*
++ - regmatch - main matching routine
++ *
++ * Conceptually the strategy is simple: check to see whether the current
++ * node matches, call self recursively to see whether the rest matches,
++ * and then act accordingly. In practice we make some effort to avoid
++ * recursion, in particular by going through "ordinary" nodes (that don't
++ * need to know whether the rest of the match failed) by a loop instead of
++ * by recursion.
++ */
++static int /* 0 failure, 1 success */
++regmatch(char *prog)
++{
++ register char *scan = prog; /* Current node. */
++ char *next; /* Next node. */
++
++#ifdef DEBUG
++ if (scan != NULL && regnarrate)
++ fprintf(stderr, "%s(\n", regprop(scan));
++#endif
++ while (scan != NULL) {
++#ifdef DEBUG
++ if (regnarrate)
++ fprintf(stderr, "%s...\n", regprop(scan));
++#endif
++ next = regnext(scan);
++
++ switch (OP(scan)) {
++ case BOL:
++ if (reginput != regbol)
++ return(0);
++ break;
++ case EOL:
++ if (*reginput != '\0')
++ return(0);
++ break;
++ case ANY:
++ if (*reginput == '\0')
++ return(0);
++ reginput++;
++ break;
++ case EXACTLY: {
++ register int len;
++ register char *opnd;
++
++ opnd = OPERAND(scan);
++ /* Inline the first character, for speed. */
++ if (*opnd != *reginput)
++ return(0);
++ len = strlen(opnd);
++ if (len > 1 && strncmp(opnd, reginput, len) != 0)
++ return(0);
++ reginput += len;
++ }
++ break;
++ case ANYOF:
++ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
++ return(0);
++ reginput++;
++ break;
++ case ANYBUT:
++ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
++ return(0);
++ reginput++;
++ break;
++ case NOTHING:
++ case BACK:
++ break;
++ case OPEN+1:
++ case OPEN+2:
++ case OPEN+3:
++ case OPEN+4:
++ case OPEN+5:
++ case OPEN+6:
++ case OPEN+7:
++ case OPEN+8:
++ case OPEN+9: {
++ register int no;
++ register char *save;
++
++ no = OP(scan) - OPEN;
++ save = reginput;
++
++ if (regmatch(next)) {
++ /*
++ * Don't set startp if some later
++ * invocation of the same parentheses
++ * already has.
++ */
++ if (regstartp[no] == NULL)
++ regstartp[no] = save;
++ return(1);
++ } else
++ return(0);
++ }
++ break;
++ case CLOSE+1:
++ case CLOSE+2:
++ case CLOSE+3:
++ case CLOSE+4:
++ case CLOSE+5:
++ case CLOSE+6:
++ case CLOSE+7:
++ case CLOSE+8:
++ case CLOSE+9:
++ {
++ register int no;
++ register char *save;
++
++ no = OP(scan) - CLOSE;
++ save = reginput;
++
++ if (regmatch(next)) {
++ /*
++ * Don't set endp if some later
++ * invocation of the same parentheses
++ * already has.
++ */
++ if (regendp[no] == NULL)
++ regendp[no] = save;
++ return(1);
++ } else
++ return(0);
++ }
++ break;
++ case BRANCH: {
++ register char *save;
++
++ if (OP(next) != BRANCH) /* No choice. */
++ next = OPERAND(scan); /* Avoid recursion. */
++ else {
++ do {
++ save = reginput;
++ if (regmatch(OPERAND(scan)))
++ return(1);
++ reginput = save;
++ scan = regnext(scan);
++ } while (scan != NULL && OP(scan) == BRANCH);
++ return(0);
++ /* NOTREACHED */
++ }
++ }
++ break;
++ case STAR:
++ case PLUS: {
++ register char nextch;
++ register int no;
++ register char *save;
++ register int min;
++
++ /*
++ * Lookahead to avoid useless match attempts
++ * when we know what character comes next.
++ */
++ nextch = '\0';
++ if (OP(next) == EXACTLY)
++ nextch = *OPERAND(next);
++ min = (OP(scan) == STAR) ? 0 : 1;
++ save = reginput;
++ no = regrepeat(OPERAND(scan));
++ while (no >= min) {
++ /* If it could work, try it. */
++ if (nextch == '\0' || *reginput == nextch)
++ if (regmatch(next))
++ return(1);
++ /* Couldn't or didn't -- back up. */
++ no--;
++ reginput = save + no;
++ }
++ return(0);
++ }
++ break;
++ case END:
++ return(1); /* Success! */
++ break;
++ default:
++ printk("<3>Regexp: memory corruption\n");
++ return(0);
++ break;
++ }
++
++ scan = next;
++ }
++
++ /*
++ * We get here only if there's trouble -- normally "case END" is
++ * the terminating point.
++ */
++ printk("<3>Regexp: corrupted pointers\n");
++ return(0);
++}
++
++/*
++ - regrepeat - repeatedly match something simple, report how many
++ */
++static int
++regrepeat(char *p)
++{
++ register int count = 0;
++ register char *scan;
++ register char *opnd;
++
++ scan = reginput;
++ opnd = OPERAND(p);
++ switch (OP(p)) {
++ case ANY:
++ count = strlen(scan);
++ scan += count;
++ break;
++ case EXACTLY:
++ while (*opnd == *scan) {
++ count++;
++ scan++;
++ }
++ break;
++ case ANYOF:
++ while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
++ count++;
++ scan++;
++ }
++ break;
++ case ANYBUT:
++ while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
++ count++;
++ scan++;
++ }
++ break;
++ default: /* Oh dear. Called inappropriately. */
++ printk("<3>Regexp: internal foulup\n");
++ count = 0; /* Best compromise. */
++ break;
++ }
++ reginput = scan;
++
++ return(count);
++}
++
++/*
++ - regnext - dig the "next" pointer out of a node
++ */
++static char*
++regnext(char *p)
++{
++ register int offset;
++
++ if (p == &regdummy)
++ return(NULL);
++
++ offset = NEXT(p);
++ if (offset == 0)
++ return(NULL);
++
++ if (OP(p) == BACK)
++ return(p-offset);
++ else
++ return(p+offset);
++}
++
++#ifdef DEBUG
++
++STATIC char *regprop();
++
++/*
++ - regdump - dump a regexp onto stdout in vaguely comprehensible form
++ */
++void
++regdump(regexp *r)
++{
++ register char *s;
++ register char op = EXACTLY; /* Arbitrary non-END op. */
++ register char *next;
++ /* extern char *strchr(); */
++
++
++ s = r->program + 1;
++ while (op != END) { /* While that wasn't END last time... */
++ op = OP(s);
++ printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */
++ next = regnext(s);
++ if (next == NULL) /* Next ptr. */
++ printf("(0)");
++ else
++ printf("(%d)", (s-r->program)+(next-s));
++ s += 3;
++ if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
++ /* Literal string, where present. */
++ while (*s != '\0') {
++ putchar(*s);
++ s++;
++ }
++ s++;
++ }
++ putchar('\n');
++ }
++
++ /* Header fields of interest. */
++ if (r->regstart != '\0')
++ printf("start `%c' ", r->regstart);
++ if (r->reganch)
++ printf("anchored ");
++ if (r->regmust != NULL)
++ printf("must have \"%s\"", r->regmust);
++ printf("\n");
++}
++
++/*
++ - regprop - printable representation of opcode
++ */
++static char *
++regprop(char *op)
++{
++#define BUFLEN 50
++ register char *p;
++ static char buf[BUFLEN];
++
++ strcpy(buf, ":");
++
++ switch (OP(op)) {
++ case BOL:
++ p = "BOL";
++ break;
++ case EOL:
++ p = "EOL";
++ break;
++ case ANY:
++ p = "ANY";
++ break;
++ case ANYOF:
++ p = "ANYOF";
++ break;
++ case ANYBUT:
++ p = "ANYBUT";
++ break;
++ case BRANCH:
++ p = "BRANCH";
++ break;
++ case EXACTLY:
++ p = "EXACTLY";
++ break;
++ case NOTHING:
++ p = "NOTHING";
++ break;
++ case BACK:
++ p = "BACK";
++ break;
++ case END:
++ p = "END";
++ break;
++ case OPEN+1:
++ case OPEN+2:
++ case OPEN+3:
++ case OPEN+4:
++ case OPEN+5:
++ case OPEN+6:
++ case OPEN+7:
++ case OPEN+8:
++ case OPEN+9:
++ snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "OPEN%d", OP(op)-OPEN);
++ p = NULL;
++ break;
++ case CLOSE+1:
++ case CLOSE+2:
++ case CLOSE+3:
++ case CLOSE+4:
++ case CLOSE+5:
++ case CLOSE+6:
++ case CLOSE+7:
++ case CLOSE+8:
++ case CLOSE+9:
++ snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "CLOSE%d", OP(op)-CLOSE);
++ p = NULL;
++ break;
++ case STAR:
++ p = "STAR";
++ break;
++ case PLUS:
++ p = "PLUS";
++ break;
++ default:
++ printk("<3>Regexp: corrupted opcode\n");
++ break;
++ }
++ if (p != NULL)
++ strncat(buf, p, BUFLEN-strlen(buf));
++ return(buf);
++}
++#endif
++
++
+diff -urN linux.old/net/ipv4/netfilter/regexp/regexp.h linux.dev/net/ipv4/netfilter/regexp/regexp.h
+--- linux.old/net/ipv4/netfilter/regexp/regexp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/net/ipv4/netfilter/regexp/regexp.h 2006-01-31 16:58:24.819335750 +0100
+@@ -0,0 +1,40 @@
++/*
++ * Definitions etc. for regexp(3) routines.
++ *
++ * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
++ * not the System V one.
++ */
++
++#ifndef REGEXP_H
++#define REGEXP_H
++
++/*
++http://www.opensource.apple.com/darwinsource/10.3/expect-1/expect/expect.h ,
++which contains a version of this library, says:
++
++ *
++ * NSUBEXP must be at least 10, and no greater than 117 or the parser
++ * will not work properly.
++ *
++
++However, it looks rather like this library is limited to 10. If you think
++otherwise, let us know.
++*/
++
++#define NSUBEXP 10
++typedef struct regexp {
++ char *startp[NSUBEXP];
++ char *endp[NSUBEXP];
++ char regstart; /* Internal use only. */
++ char reganch; /* Internal use only. */
++ char *regmust; /* Internal use only. */
++ int regmlen; /* Internal use only. */
++ char program[1]; /* Unwarranted chumminess with compiler. */
++} regexp;
++
++regexp * regcomp(char *exp, int *patternsize);
++int regexec(regexp *prog, char *string);
++void regsub(regexp *prog, char *source, char *dest);
++void regerror(char *s);
++
++#endif
+diff -urN linux.old/net/ipv4/netfilter/regexp/regmagic.h linux.dev/net/ipv4/netfilter/regexp/regmagic.h
+--- linux.old/net/ipv4/netfilter/regexp/regmagic.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/net/ipv4/netfilter/regexp/regmagic.h 2006-01-31 16:58:24.823336000 +0100
+@@ -0,0 +1,5 @@
++/*
++ * The first byte of the regexp internal "program" is actually this magic
++ * number; the start node begins in the second byte.
++ */
++#define MAGIC 0234
+diff -urN linux.old/net/ipv4/netfilter/regexp/regsub.c linux.dev/net/ipv4/netfilter/regexp/regsub.c
+--- linux.old/net/ipv4/netfilter/regexp/regsub.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/net/ipv4/netfilter/regexp/regsub.c 2006-01-31 16:58:24.823336000 +0100
+@@ -0,0 +1,95 @@
++/*
++ * regsub
++ * @(#)regsub.c 1.3 of 2 April 86
++ *
++ * Copyright (c) 1986 by University of Toronto.
++ * Written by Henry Spencer. Not derived from licensed software.
++ *
++ * Permission is granted to anyone to use this software for any
++ * purpose on any computer system, and to redistribute it freely,
++ * subject to the following restrictions:
++ *
++ * 1. The author is not responsible for the consequences of use of
++ * this software, no matter how awful, even if they arise
++ * from defects in it.
++ *
++ * 2. The origin of this software must not be misrepresented, either
++ * by explicit claim or by omission.
++ *
++ * 3. Altered versions must be plainly marked as such, and must not
++ * be misrepresented as being the original software.
++ *
++ *
++ * This code was modified by Ethan Sommer to work within the kernel
++ * (it now uses kmalloc etc..)
++ *
++ */
++#include "regexp.h"
++#include "regmagic.h"
++#include <linux/string.h>
++
++
++#ifndef CHARBITS
++#define UCHARAT(p) ((int)*(unsigned char *)(p))
++#else
++#define UCHARAT(p) ((int)*(p)&CHARBITS)
++#endif
++
++#if 0
++//void regerror(char * s)
++//{
++// printk("regexp(3): %s", s);
++// /* NOTREACHED */
++//}
++#endif
++
++/*
++ - regsub - perform substitutions after a regexp match
++ */
++void
++regsub(regexp * prog, char * source, char * dest)
++{
++ register char *src;
++ register char *dst;
++ register char c;
++ register int no;
++ register int len;
++
++ /* Not necessary and gcc doesn't like it -MLS */
++ /*extern char *strncpy();*/
++
++ if (prog == NULL || source == NULL || dest == NULL) {
++ regerror("NULL parm to regsub");
++ return;
++ }
++ if (UCHARAT(prog->program) != MAGIC) {
++ regerror("damaged regexp fed to regsub");
++ return;
++ }
++
++ src = source;
++ dst = dest;
++ while ((c = *src++) != '\0') {
++ if (c == '&')
++ no = 0;
++ else if (c == '\\' && '0' <= *src && *src <= '9')
++ no = *src++ - '0';
++ else
++ no = -1;
++
++ if (no < 0) { /* Ordinary character. */
++ if (c == '\\' && (*src == '\\' || *src == '&'))
++ c = *src++;
++ *dst++ = c;
++ } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
++ len = prog->endp[no] - prog->startp[no];
++ (void) strncpy(dst, prog->startp[no], len);
++ dst += len;
++ if (len != 0 && *(dst-1) == '\0') { /* strncpy hit NUL. */
++ regerror("damaged match string");
++ return;
++ }
++ }
++ }
++ *dst++ = '\0';
++}
diff --git a/target/linux/generic-2.4/patches/603-netfilter_nat_pptp.patch b/target/linux/generic-2.4/patches/603-netfilter_nat_pptp.patch
new file mode 100644
index 0000000000..6a7a16fb9a
--- /dev/null
+++ b/target/linux/generic-2.4/patches/603-netfilter_nat_pptp.patch
@@ -0,0 +1,2412 @@
+diff -urN linux-2.4.29-old/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.29-dev/include/linux/netfilter_ipv4/ip_conntrack.h
+--- linux-2.4.29-old/include/linux/netfilter_ipv4/ip_conntrack.h 2005-04-02 19:04:11.000000000 +0200
++++ linux-2.4.29-dev/include/linux/netfilter_ipv4/ip_conntrack.h 2005-04-02 19:41:05.000000000 +0200
+@@ -50,16 +50,19 @@
+
+ #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
+ #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
++#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
+
+ /* per conntrack: protocol private data */
+ union ip_conntrack_proto {
+ /* insert conntrack proto private data here */
+ struct ip_ct_tcp tcp;
+ struct ip_ct_icmp icmp;
++ struct ip_ct_gre gre;
+ };
+
+ union ip_conntrack_expect_proto {
+ /* insert expect proto private data here */
++ struct ip_ct_gre_expect gre;
+ };
+
+ /* Add protocol helper include file here */
+@@ -67,6 +70,7 @@
+
+ #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
+ #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
++#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
+
+ /* per expectation: application helper private data */
+ union ip_conntrack_expect_help {
+@@ -74,6 +78,7 @@
+ struct ip_ct_amanda_expect exp_amanda_info;
+ struct ip_ct_ftp_expect exp_ftp_info;
+ struct ip_ct_irc_expect exp_irc_info;
++ struct ip_ct_pptp_expect exp_pptp_info;
+
+ #ifdef CONFIG_IP_NF_NAT_NEEDED
+ union {
+@@ -87,14 +92,17 @@
+ /* insert conntrack helper private data (master) here */
+ struct ip_ct_ftp_master ct_ftp_info;
+ struct ip_ct_irc_master ct_irc_info;
++ struct ip_ct_pptp_master ct_pptp_info;
+ };
+
+ #ifdef CONFIG_IP_NF_NAT_NEEDED
+ #include <linux/netfilter_ipv4/ip_nat.h>
++#include <linux/netfilter_ipv4/ip_nat_pptp.h>
+
+ /* per conntrack: nat application helper private data */
+ union ip_conntrack_nat_help {
+ /* insert nat helper private data here */
++ struct ip_nat_pptp nat_pptp_info;
+ };
+ #endif
+
+diff -urN linux-2.4.29-old/include/linux/netfilter_ipv4/ip_conntrack_pptp.h linux-2.4.29-dev/include/linux/netfilter_ipv4/ip_conntrack_pptp.h
+--- linux-2.4.29-old/include/linux/netfilter_ipv4/ip_conntrack_pptp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29-dev/include/linux/netfilter_ipv4/ip_conntrack_pptp.h 2005-04-02 19:09:07.000000000 +0200
+@@ -0,0 +1,313 @@
++/* PPTP constants and structs */
++#ifndef _CONNTRACK_PPTP_H
++#define _CONNTRACK_PPTP_H
++
++/* state of the control session */
++enum pptp_ctrlsess_state {
++ PPTP_SESSION_NONE, /* no session present */
++ PPTP_SESSION_ERROR, /* some session error */
++ PPTP_SESSION_STOPREQ, /* stop_sess request seen */
++ PPTP_SESSION_REQUESTED, /* start_sess request seen */
++ PPTP_SESSION_CONFIRMED, /* session established */
++};
++
++/* state of the call inside the control session */
++enum pptp_ctrlcall_state {
++ PPTP_CALL_NONE,
++ PPTP_CALL_ERROR,
++ PPTP_CALL_OUT_REQ,
++ PPTP_CALL_OUT_CONF,
++ PPTP_CALL_IN_REQ,
++ PPTP_CALL_IN_REP,
++ PPTP_CALL_IN_CONF,
++ PPTP_CALL_CLEAR_REQ,
++};
++
++
++/* conntrack private data */
++struct ip_ct_pptp_master {
++ enum pptp_ctrlsess_state sstate; /* session state */
++
++ /* everything below is going to be per-expectation in newnat,
++ * since there could be more than one call within one session */
++ enum pptp_ctrlcall_state cstate; /* call state */
++ u_int16_t pac_call_id; /* call id of PAC, host byte order */
++ u_int16_t pns_call_id; /* call id of PNS, host byte order */
++};
++
++/* conntrack_expect private member */
++struct ip_ct_pptp_expect {
++ enum pptp_ctrlcall_state cstate; /* call state */
++ u_int16_t pac_call_id; /* call id of PAC */
++ u_int16_t pns_call_id; /* call id of PNS */
++};
++
++
++#ifdef __KERNEL__
++
++#include <linux/netfilter_ipv4/lockhelp.h>
++DECLARE_LOCK_EXTERN(ip_pptp_lock);
++
++#define IP_CONNTR_PPTP PPTP_CONTROL_PORT
++
++union pptp_ctrl_union {
++ void *rawreq;
++ struct PptpStartSessionRequest *sreq;
++ struct PptpStartSessionReply *srep;
++ struct PptpStopSessionRequest *streq;
++ struct PptpStopSessionReply *strep;
++ struct PptpOutCallRequest *ocreq;
++ struct PptpOutCallReply *ocack;
++ struct PptpInCallRequest *icreq;
++ struct PptpInCallReply *icack;
++ struct PptpInCallConnected *iccon;
++ struct PptpClearCallRequest *clrreq;
++ struct PptpCallDisconnectNotify *disc;
++ struct PptpWanErrorNotify *wanerr;
++ struct PptpSetLinkInfo *setlink;
++};
++
++
++
++#define PPTP_CONTROL_PORT 1723
++
++#define PPTP_PACKET_CONTROL 1
++#define PPTP_PACKET_MGMT 2
++
++#define PPTP_MAGIC_COOKIE 0x1a2b3c4d
++
++struct pptp_pkt_hdr {
++ __u16 packetLength;
++ __u16 packetType;
++ __u32 magicCookie;
++};
++
++/* PptpControlMessageType values */
++#define PPTP_START_SESSION_REQUEST 1
++#define PPTP_START_SESSION_REPLY 2
++#define PPTP_STOP_SESSION_REQUEST 3
++#define PPTP_STOP_SESSION_REPLY 4
++#define PPTP_ECHO_REQUEST 5
++#define PPTP_ECHO_REPLY 6
++#define PPTP_OUT_CALL_REQUEST 7
++#define PPTP_OUT_CALL_REPLY 8
++#define PPTP_IN_CALL_REQUEST 9
++#define PPTP_IN_CALL_REPLY 10
++#define PPTP_IN_CALL_CONNECT 11
++#define PPTP_CALL_CLEAR_REQUEST 12
++#define PPTP_CALL_DISCONNECT_NOTIFY 13
++#define PPTP_WAN_ERROR_NOTIFY 14
++#define PPTP_SET_LINK_INFO 15
++
++#define PPTP_MSG_MAX 15
++
++/* PptpGeneralError values */
++#define PPTP_ERROR_CODE_NONE 0
++#define PPTP_NOT_CONNECTED 1
++#define PPTP_BAD_FORMAT 2
++#define PPTP_BAD_VALUE 3
++#define PPTP_NO_RESOURCE 4
++#define PPTP_BAD_CALLID 5
++#define PPTP_REMOVE_DEVICE_ERROR 6
++
++struct PptpControlHeader {
++ __u16 messageType;
++ __u16 reserved;
++};
++
++/* FramingCapability Bitmap Values */
++#define PPTP_FRAME_CAP_ASYNC 0x1
++#define PPTP_FRAME_CAP_SYNC 0x2
++
++/* BearerCapability Bitmap Values */
++#define PPTP_BEARER_CAP_ANALOG 0x1
++#define PPTP_BEARER_CAP_DIGITAL 0x2
++
++struct PptpStartSessionRequest {
++ __u16 protocolVersion;
++ __u8 reserved1;
++ __u8 reserved2;
++ __u32 framingCapability;
++ __u32 bearerCapability;
++ __u16 maxChannels;
++ __u16 firmwareRevision;
++ __u8 hostName[64];
++ __u8 vendorString[64];
++};
++
++/* PptpStartSessionResultCode Values */
++#define PPTP_START_OK 1
++#define PPTP_START_GENERAL_ERROR 2
++#define PPTP_START_ALREADY_CONNECTED 3
++#define PPTP_START_NOT_AUTHORIZED 4
++#define PPTP_START_UNKNOWN_PROTOCOL 5
++
++struct PptpStartSessionReply {
++ __u16 protocolVersion;
++ __u8 resultCode;
++ __u8 generalErrorCode;
++ __u32 framingCapability;
++ __u32 bearerCapability;
++ __u16 maxChannels;
++ __u16 firmwareRevision;
++ __u8 hostName[64];
++ __u8 vendorString[64];
++};
++
++/* PptpStopReasons */
++#define PPTP_STOP_NONE 1
++#define PPTP_STOP_PROTOCOL 2
++#define PPTP_STOP_LOCAL_SHUTDOWN 3
++
++struct PptpStopSessionRequest {
++ __u8 reason;
++};
++
++/* PptpStopSessionResultCode */
++#define PPTP_STOP_OK 1
++#define PPTP_STOP_GENERAL_ERROR 2
++
++struct PptpStopSessionReply {
++ __u8 resultCode;
++ __u8 generalErrorCode;
++};
++
++struct PptpEchoRequest {
++ __u32 identNumber;
++};
++
++/* PptpEchoReplyResultCode */
++#define PPTP_ECHO_OK 1
++#define PPTP_ECHO_GENERAL_ERROR 2
++
++struct PptpEchoReply {
++ __u32 identNumber;
++ __u8 resultCode;
++ __u8 generalErrorCode;
++ __u16 reserved;
++};
++
++/* PptpFramingType */
++#define PPTP_ASYNC_FRAMING 1
++#define PPTP_SYNC_FRAMING 2
++#define PPTP_DONT_CARE_FRAMING 3
++
++/* PptpCallBearerType */
++#define PPTP_ANALOG_TYPE 1
++#define PPTP_DIGITAL_TYPE 2
++#define PPTP_DONT_CARE_BEARER_TYPE 3
++
++struct PptpOutCallRequest {
++ __u16 callID;
++ __u16 callSerialNumber;
++ __u32 minBPS;
++ __u32 maxBPS;
++ __u32 bearerType;
++ __u32 framingType;
++ __u16 packetWindow;
++ __u16 packetProcDelay;
++ __u16 reserved1;
++ __u16 phoneNumberLength;
++ __u16 reserved2;
++ __u8 phoneNumber[64];
++ __u8 subAddress[64];
++};
++
++/* PptpCallResultCode */
++#define PPTP_OUTCALL_CONNECT 1
++#define PPTP_OUTCALL_GENERAL_ERROR 2
++#define PPTP_OUTCALL_NO_CARRIER 3
++#define PPTP_OUTCALL_BUSY 4
++#define PPTP_OUTCALL_NO_DIAL_TONE 5
++#define PPTP_OUTCALL_TIMEOUT 6
++#define PPTP_OUTCALL_DONT_ACCEPT 7
++
++struct PptpOutCallReply {
++ __u16 callID;
++ __u16 peersCallID;
++ __u8 resultCode;
++ __u8 generalErrorCode;
++ __u16 causeCode;
++ __u32 connectSpeed;
++ __u16 packetWindow;
++ __u16 packetProcDelay;
++ __u32 physChannelID;
++};
++
++struct PptpInCallRequest {
++ __u16 callID;
++ __u16 callSerialNumber;
++ __u32 callBearerType;
++ __u32 physChannelID;
++ __u16 dialedNumberLength;
++ __u16 dialingNumberLength;
++ __u8 dialedNumber[64];
++ __u8 dialingNumber[64];
++ __u8 subAddress[64];
++};
++
++/* PptpInCallResultCode */
++#define PPTP_INCALL_ACCEPT 1
++#define PPTP_INCALL_GENERAL_ERROR 2
++#define PPTP_INCALL_DONT_ACCEPT 3
++
++struct PptpInCallReply {
++ __u16 callID;
++ __u16 peersCallID;
++ __u8 resultCode;
++ __u8 generalErrorCode;
++ __u16 packetWindow;
++ __u16 packetProcDelay;
++ __u16 reserved;
++};
++
++struct PptpInCallConnected {
++ __u16 peersCallID;
++ __u16 reserved;
++ __u32 connectSpeed;
++ __u16 packetWindow;
++ __u16 packetProcDelay;
++ __u32 callFramingType;
++};
++
++struct PptpClearCallRequest {
++ __u16 callID;
++ __u16 reserved;
++};
++
++struct PptpCallDisconnectNotify {
++ __u16 callID;
++ __u8 resultCode;
++ __u8 generalErrorCode;
++ __u16 causeCode;
++ __u16 reserved;
++ __u8 callStatistics[128];
++};
++
++struct PptpWanErrorNotify {
++ __u16 peersCallID;
++ __u16 reserved;
++ __u32 crcErrors;
++ __u32 framingErrors;
++ __u32 hardwareOverRuns;
++ __u32 bufferOverRuns;
++ __u32 timeoutErrors;
++ __u32 alignmentErrors;
++};
++
++struct PptpSetLinkInfo {
++ __u16 peersCallID;
++ __u16 reserved;
++ __u32 sendAccm;
++ __u32 recvAccm;
++};
++
++
++struct pptp_priv_data {
++ __u16 call_id;
++ __u16 mcall_id;
++ __u16 pcall_id;
++};
++
++#endif /* __KERNEL__ */
++#endif /* _CONNTRACK_PPTP_H */
+diff -urN linux-2.4.29-old/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h linux-2.4.29-dev/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
+--- linux-2.4.29-old/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29-dev/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h 2005-04-02 19:10:45.000000000 +0200
+@@ -0,0 +1,123 @@
++#ifndef _CONNTRACK_PROTO_GRE_H
++#define _CONNTRACK_PROTO_GRE_H
++#include <asm/byteorder.h>
++
++/* GRE PROTOCOL HEADER */
++
++/* GRE Version field */
++#define GRE_VERSION_1701 0x0
++#define GRE_VERSION_PPTP 0x1
++
++/* GRE Protocol field */
++#define GRE_PROTOCOL_PPTP 0x880B
++
++/* GRE Flags */
++#define GRE_FLAG_C 0x80
++#define GRE_FLAG_R 0x40
++#define GRE_FLAG_K 0x20
++#define GRE_FLAG_S 0x10
++#define GRE_FLAG_A 0x80
++
++#define GRE_IS_C(f) ((f)&GRE_FLAG_C)
++#define GRE_IS_R(f) ((f)&GRE_FLAG_R)
++#define GRE_IS_K(f) ((f)&GRE_FLAG_K)
++#define GRE_IS_S(f) ((f)&GRE_FLAG_S)
++#define GRE_IS_A(f) ((f)&GRE_FLAG_A)
++
++/* GRE is a mess: Four different standards */
++struct gre_hdr {
++#if defined(__LITTLE_ENDIAN_BITFIELD)
++ __u16 rec:3,
++ srr:1,
++ seq:1,
++ key:1,
++ routing:1,
++ csum:1,
++ version:3,
++ reserved:4,
++ ack:1;
++#elif defined(__BIG_ENDIAN_BITFIELD)
++ __u16 csum:1,
++ routing:1,
++ key:1,
++ seq:1,
++ srr:1,
++ rec:3,
++ ack:1,
++ reserved:4,
++ version:3;
++#else
++#error "Adjust your <asm/byteorder.h> defines"
++#endif
++ __u16 protocol;
++};
++
++/* modified GRE header for PPTP */
++struct gre_hdr_pptp {
++ __u8 flags; /* bitfield */
++ __u8 version; /* should be GRE_VERSION_PPTP */
++ __u16 protocol; /* should be GRE_PROTOCOL_PPTP */
++ __u16 payload_len; /* size of ppp payload, not inc. gre header */
++ __u16 call_id; /* peer's call_id for this session */
++ __u32 seq; /* sequence number. Present if S==1 */
++ __u32 ack; /* seq number of highest packet recieved by */
++ /* sender in this session */
++};
++
++
++/* this is part of ip_conntrack */
++struct ip_ct_gre {
++ unsigned int stream_timeout;
++ unsigned int timeout;
++};
++
++/* this is part of ip_conntrack_expect */
++struct ip_ct_gre_expect {
++ struct ip_ct_gre_keymap *keymap_orig, *keymap_reply;
++};
++
++#ifdef __KERNEL__
++struct ip_conntrack_expect;
++
++/* structure for original <-> reply keymap */
++struct ip_ct_gre_keymap {
++ struct list_head list;
++
++ struct ip_conntrack_tuple tuple;
++};
++
++
++/* add new tuple->key_reply pair to keymap */
++int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp,
++ struct ip_conntrack_tuple *t,
++ int reply);
++
++/* change an existing keymap entry */
++void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
++ struct ip_conntrack_tuple *t);
++
++/* delete keymap entries */
++void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp);
++
++
++/* get pointer to gre key, if present */
++static inline u_int32_t *gre_key(struct gre_hdr *greh)
++{
++ if (!greh->key)
++ return NULL;
++ if (greh->csum || greh->routing)
++ return (u_int32_t *) (greh+sizeof(*greh)+4);
++ return (u_int32_t *) (greh+sizeof(*greh));
++}
++
++/* get pointer ot gre csum, if present */
++static inline u_int16_t *gre_csum(struct gre_hdr *greh)
++{
++ if (!greh->csum)
++ return NULL;
++ return (u_int16_t *) (greh+sizeof(*greh));
++}
++
++#endif /* __KERNEL__ */
++
++#endif /* _CONNTRACK_PROTO_GRE_H */
+diff -urN linux-2.4.29-old/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.4.29-dev/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
+--- linux-2.4.29-old/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2003-11-28 19:26:21.000000000 +0100
++++ linux-2.4.29-dev/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2005-04-02 19:07:18.000000000 +0200
+@@ -14,7 +14,7 @@
+ union ip_conntrack_manip_proto
+ {
+ /* Add other protocols here. */
+- u_int16_t all;
++ u_int32_t all;
+
+ struct {
+ u_int16_t port;
+@@ -25,6 +25,9 @@
+ struct {
+ u_int16_t id;
+ } icmp;
++ struct {
++ u_int32_t key;
++ } gre;
+ };
+
+ /* The manipulable part of the tuple. */
+@@ -44,7 +47,7 @@
+ u_int32_t ip;
+ union {
+ /* Add other protocols here. */
+- u_int16_t all;
++ u_int32_t all;
+
+ struct {
+ u_int16_t port;
+@@ -55,6 +58,9 @@
+ struct {
+ u_int8_t type, code;
+ } icmp;
++ struct {
++ u_int32_t key;
++ } gre;
+ } u;
+
+ /* The protocol. */
+@@ -80,10 +86,16 @@
+ #ifdef __KERNEL__
+
+ #define DUMP_TUPLE(tp) \
+-DEBUGP("tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n", \
++DEBUGP("tuple %p: %u %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", \
+ (tp), (tp)->dst.protonum, \
+- NIPQUAD((tp)->src.ip), ntohs((tp)->src.u.all), \
+- NIPQUAD((tp)->dst.ip), ntohs((tp)->dst.u.all))
++ NIPQUAD((tp)->src.ip), ntohl((tp)->src.u.all), \
++ NIPQUAD((tp)->dst.ip), ntohl((tp)->dst.u.all))
++
++#define DUMP_TUPLE_RAW(x) \
++ DEBUGP("tuple %p: %u %u.%u.%u.%u:0x%08x -> %u.%u.%u.%u:0x%08x\n",\
++ (x), (x)->dst.protonum, \
++ NIPQUAD((x)->src.ip), ntohl((x)->src.u.all), \
++ NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.all))
+
+ #define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
+
+diff -urN linux-2.4.29-old/include/linux/netfilter_ipv4/ip_nat_pptp.h linux-2.4.29-dev/include/linux/netfilter_ipv4/ip_nat_pptp.h
+--- linux-2.4.29-old/include/linux/netfilter_ipv4/ip_nat_pptp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29-dev/include/linux/netfilter_ipv4/ip_nat_pptp.h 2005-04-02 19:07:18.000000000 +0200
+@@ -0,0 +1,11 @@
++/* PPTP constants and structs */
++#ifndef _NAT_PPTP_H
++#define _NAT_PPTP_H
++
++/* conntrack private data */
++struct ip_nat_pptp {
++ u_int16_t pns_call_id; /* NAT'ed PNS call id */
++ u_int16_t pac_call_id; /* NAT'ed PAC call id */
++};
++
++#endif /* _NAT_PPTP_H */
+diff -urN linux-2.4.29-old/net/ipv4/netfilter/Config.in linux-2.4.29-dev/net/ipv4/netfilter/Config.in
+--- linux-2.4.29-old/net/ipv4/netfilter/Config.in 2005-04-02 19:04:11.000000000 +0200
++++ linux-2.4.29-dev/net/ipv4/netfilter/Config.in 2005-04-02 19:07:18.000000000 +0200
+@@ -10,6 +10,8 @@
+ dep_tristate ' Amanda protocol support' CONFIG_IP_NF_AMANDA $CONFIG_IP_NF_CONNTRACK
+ dep_tristate ' TFTP protocol support' CONFIG_IP_NF_TFTP $CONFIG_IP_NF_CONNTRACK
+ dep_tristate ' IRC protocol support' CONFIG_IP_NF_IRC $CONFIG_IP_NF_CONNTRACK
++ dep_tristate ' GRE protocol support' CONFIG_IP_NF_CT_PROTO_GRE $CONFIG_IP_NF_CONNTRACK
++ dep_tristate ' PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE
+ fi
+
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+@@ -67,6 +69,20 @@
+ define_bool CONFIG_IP_NF_NAT_NEEDED y
+ dep_tristate ' MASQUERADE target support' CONFIG_IP_NF_TARGET_MASQUERADE $CONFIG_IP_NF_NAT
+ dep_tristate ' REDIRECT target support' CONFIG_IP_NF_TARGET_REDIRECT $CONFIG_IP_NF_NAT
++ if [ "$CONFIG_IP_NF_PPTP" = "m" ]; then
++ define_tristate CONFIG_IP_NF_NAT_PPTP m
++ else
++ if [ "$CONFIG_IP_NF_PPTP" = "y" ]; then
++ define_tristate CONFIG_IP_NF_NAT_PPTP $CONFIG_IP_NF_NAT
++ fi
++ fi
++ if [ "$CONFIG_IP_NF_CT_PROTO_GRE" = "m" ]; then
++ define_tristate CONFIG_IP_NF_NAT_PROTO_GRE m
++ else
++ if [ "$CONFIG_IP_NF_CT_PROTO_GRE" = "y" ]; then
++ define_tristate CONFIG_IP_NF_NAT_PROTO_GRE $CONFIG_IP_NF_NAT
++ fi
++ fi
+ if [ "$CONFIG_IP_NF_AMANDA" = "m" ]; then
+ define_tristate CONFIG_IP_NF_NAT_AMANDA m
+ else
+diff -urN linux-2.4.29-old/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.29-dev/net/ipv4/netfilter/ip_conntrack_core.c
+--- linux-2.4.29-old/net/ipv4/netfilter/ip_conntrack_core.c 2005-04-02 19:04:11.000000000 +0200
++++ linux-2.4.29-dev/net/ipv4/netfilter/ip_conntrack_core.c 2005-04-02 19:07:18.000000000 +0200
+@@ -142,6 +142,8 @@
+ tuple->dst.ip = iph->daddr;
+ tuple->dst.protonum = iph->protocol;
+
++ tuple->src.u.all = tuple->dst.u.all = 0;
++
+ ret = protocol->pkt_to_tuple((u_int32_t *)iph + iph->ihl,
+ len - 4*iph->ihl,
+ tuple);
+@@ -157,6 +159,8 @@
+ inverse->dst.ip = orig->src.ip;
+ inverse->dst.protonum = orig->dst.protonum;
+
++ inverse->src.u.all = inverse->dst.u.all = 0;
++
+ return protocol->invert_tuple(inverse, orig);
+ }
+
+@@ -954,8 +958,8 @@
+ * so there is no need to use the tuple lock too */
+
+ DEBUGP("ip_conntrack_expect_related %p\n", related_to);
+- DEBUGP("tuple: "); DUMP_TUPLE(&expect->tuple);
+- DEBUGP("mask: "); DUMP_TUPLE(&expect->mask);
++ DEBUGP("tuple: "); DUMP_TUPLE_RAW(&expect->tuple);
++ DEBUGP("mask: "); DUMP_TUPLE_RAW(&expect->mask);
+
+ old = LIST_FIND(&ip_conntrack_expect_list, resent_expect,
+ struct ip_conntrack_expect *, &expect->tuple,
+@@ -1072,15 +1076,14 @@
+
+ MUST_BE_READ_LOCKED(&ip_conntrack_lock);
+ WRITE_LOCK(&ip_conntrack_expect_tuple_lock);
+-
+ DEBUGP("change_expect:\n");
+- DEBUGP("exp tuple: "); DUMP_TUPLE(&expect->tuple);
+- DEBUGP("exp mask: "); DUMP_TUPLE(&expect->mask);
+- DEBUGP("newtuple: "); DUMP_TUPLE(newtuple);
++ DEBUGP("exp tuple: "); DUMP_TUPLE_RAW(&expect->tuple);
++ DEBUGP("exp mask: "); DUMP_TUPLE_RAW(&expect->mask);
++ DEBUGP("newtuple: "); DUMP_TUPLE_RAW(newtuple);
+ if (expect->ct_tuple.dst.protonum == 0) {
+ /* Never seen before */
+ DEBUGP("change expect: never seen before\n");
+- if (!ip_ct_tuple_equal(&expect->tuple, newtuple)
++ if (!ip_ct_tuple_mask_cmp(&expect->tuple, newtuple, &expect->mask)
+ && LIST_FIND(&ip_conntrack_expect_list, expect_clash,
+ struct ip_conntrack_expect *, newtuple, &expect->mask)) {
+ /* Force NAT to find an unused tuple */
+diff -urN linux-2.4.29-old/net/ipv4/netfilter/ip_conntrack_pptp_priv.h linux-2.4.29-dev/net/ipv4/netfilter/ip_conntrack_pptp_priv.h
+--- linux-2.4.29-old/net/ipv4/netfilter/ip_conntrack_pptp_priv.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29-dev/net/ipv4/netfilter/ip_conntrack_pptp_priv.h 2005-04-02 19:14:10.000000000 +0200
+@@ -0,0 +1,24 @@
++#ifndef _IP_CT_PPTP_PRIV_H
++#define _IP_CT_PPTP_PRIV_H
++
++/* PptpControlMessageType names */
++static const char *strMName[] = {
++ "UNKNOWN_MESSAGE",
++ "START_SESSION_REQUEST",
++ "START_SESSION_REPLY",
++ "STOP_SESSION_REQUEST",
++ "STOP_SESSION_REPLY",
++ "ECHO_REQUEST",
++ "ECHO_REPLY",
++ "OUT_CALL_REQUEST",
++ "OUT_CALL_REPLY",
++ "IN_CALL_REQUEST",
++ "IN_CALL_REPLY",
++ "IN_CALL_CONNECT",
++ "CALL_CLEAR_REQUEST",
++ "CALL_DISCONNECT_NOTIFY",
++ "WAN_ERROR_NOTIFY",
++ "SET_LINK_INFO"
++};
++
++#endif
+diff -urN linux-2.4.29-old/net/ipv4/netfilter/ip_conntrack_proto_gre.c linux-2.4.29-dev/net/ipv4/netfilter/ip_conntrack_proto_gre.c
+--- linux-2.4.29-old/net/ipv4/netfilter/ip_conntrack_proto_gre.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29-dev/net/ipv4/netfilter/ip_conntrack_proto_gre.c 2005-04-02 19:14:31.000000000 +0200
+@@ -0,0 +1,333 @@
++/*
++ * ip_conntrack_proto_gre.c - Version 1.2
++ *
++ * Connection tracking protocol helper module for GRE.
++ *
++ * GRE is a generic encapsulation protocol, which is generally not very
++ * suited for NAT, as it has no protocol-specific part as port numbers.
++ *
++ * It has an optional key field, which may help us distinguishing two
++ * connections between the same two hosts.
++ *
++ * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
++ *
++ * PPTP is built on top of a modified version of GRE, and has a mandatory
++ * field called "CallID", which serves us for the same purpose as the key
++ * field in plain GRE.
++ *
++ * Documentation about PPTP can be found in RFC 2637
++ *
++ * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
++ *
++ * Development of this code funded by Astaro AG (http://www.astaro.com/)
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/timer.h>
++#include <linux/netfilter.h>
++#include <linux/ip.h>
++#include <linux/in.h>
++#include <linux/list.h>
++
++#include <linux/netfilter_ipv4/lockhelp.h>
++
++DECLARE_RWLOCK(ip_ct_gre_lock);
++#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_ct_gre_lock)
++#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_ct_gre_lock)
++
++#include <linux/netfilter_ipv4/listhelp.h>
++#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
++#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
++#include <linux/netfilter_ipv4/ip_conntrack_core.h>
++
++#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
++#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
++MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE");
++
++/* shamelessly stolen from ip_conntrack_proto_udp.c */
++#define GRE_TIMEOUT (30*HZ)
++#define GRE_STREAM_TIMEOUT (180*HZ)
++
++#if 0
++#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
++ ": " format, ## args)
++#define DUMP_TUPLE_GRE(x) printk("%u.%u.%u.%u:0x%x -> %u.%u.%u.%u:0x%x:%u:0x%x\n", \
++ NIPQUAD((x)->src.ip), ntohl((x)->src.u.gre.key), \
++ NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.gre.key))
++#else
++#define DEBUGP(x, args...)
++#define DUMP_TUPLE_GRE(x)
++#endif
++
++/* GRE KEYMAP HANDLING FUNCTIONS */
++static LIST_HEAD(gre_keymap_list);
++
++static inline int gre_key_cmpfn(const struct ip_ct_gre_keymap *km,
++ const struct ip_conntrack_tuple *t)
++{
++ return ((km->tuple.src.ip == t->src.ip) &&
++ (km->tuple.dst.ip == t->dst.ip) &&
++ (km->tuple.dst.protonum == t->dst.protonum) &&
++ (km->tuple.dst.u.all == t->dst.u.all));
++}
++
++/* look up the source key for a given tuple */
++static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t)
++{
++ struct ip_ct_gre_keymap *km;
++ u_int32_t key;
++
++ READ_LOCK(&ip_ct_gre_lock);
++ km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
++ struct ip_ct_gre_keymap *, t);
++ if (!km) {
++ READ_UNLOCK(&ip_ct_gre_lock);
++ return 0;
++ }
++
++ key = km->tuple.src.u.gre.key;
++ READ_UNLOCK(&ip_ct_gre_lock);
++
++ return key;
++}
++
++/* add a single keymap entry, associate with specified expect */
++int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp,
++ struct ip_conntrack_tuple *t, int reply)
++{
++ struct ip_ct_gre_keymap *km;
++
++ km = kmalloc(sizeof(*km), GFP_ATOMIC);
++ if (!km)
++ return -1;
++
++ /* initializing list head should be sufficient */
++ memset(km, 0, sizeof(*km));
++
++ memcpy(&km->tuple, t, sizeof(*t));
++
++ if (!reply)
++ exp->proto.gre.keymap_orig = km;
++ else
++ exp->proto.gre.keymap_reply = km;
++
++ DEBUGP("adding new entry %p: ", km);
++ DUMP_TUPLE_GRE(&km->tuple);
++
++ WRITE_LOCK(&ip_ct_gre_lock);
++ list_append(&gre_keymap_list, km);
++ WRITE_UNLOCK(&ip_ct_gre_lock);
++
++ return 0;
++}
++
++/* change the tuple of a keymap entry (used by nat helper) */
++void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
++ struct ip_conntrack_tuple *t)
++{
++ DEBUGP("changing entry %p to: ", km);
++ DUMP_TUPLE_GRE(t);
++
++ WRITE_LOCK(&ip_ct_gre_lock);
++ memcpy(&km->tuple, t, sizeof(km->tuple));
++ WRITE_UNLOCK(&ip_ct_gre_lock);
++}
++
++/* destroy the keymap entries associated with specified expect */
++void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp)
++{
++ DEBUGP("entering for exp %p\n", exp);
++ WRITE_LOCK(&ip_ct_gre_lock);
++ if (exp->proto.gre.keymap_orig) {
++ DEBUGP("removing %p from list\n", exp->proto.gre.keymap_orig);
++ list_del(&exp->proto.gre.keymap_orig->list);
++ kfree(exp->proto.gre.keymap_orig);
++ exp->proto.gre.keymap_orig = NULL;
++ }
++ if (exp->proto.gre.keymap_reply) {
++ DEBUGP("removing %p from list\n", exp->proto.gre.keymap_reply);
++ list_del(&exp->proto.gre.keymap_reply->list);
++ kfree(exp->proto.gre.keymap_reply);
++ exp->proto.gre.keymap_reply = NULL;
++ }
++ WRITE_UNLOCK(&ip_ct_gre_lock);
++}
++
++
++/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
++
++/* invert gre part of tuple */
++static int gre_invert_tuple(struct ip_conntrack_tuple *tuple,
++ const struct ip_conntrack_tuple *orig)
++{
++ tuple->dst.u.gre.key = orig->src.u.gre.key;
++ tuple->src.u.gre.key = orig->dst.u.gre.key;
++
++ return 1;
++}
++
++/* gre hdr info to tuple */
++static int gre_pkt_to_tuple(const void *datah, size_t datalen,
++ struct ip_conntrack_tuple *tuple)
++{
++ struct gre_hdr *grehdr = (struct gre_hdr *) datah;
++ struct gre_hdr_pptp *pgrehdr = (struct gre_hdr_pptp *) datah;
++ u_int32_t srckey;
++
++ /* core guarantees 8 protocol bytes, no need for size check */
++
++ switch (grehdr->version) {
++ case GRE_VERSION_1701:
++ if (!grehdr->key) {
++ DEBUGP("Can't track GRE without key\n");
++ return 0;
++ }
++ tuple->dst.u.gre.key = *(gre_key(grehdr));
++ break;
++
++ case GRE_VERSION_PPTP:
++ if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
++ DEBUGP("GRE_VERSION_PPTP but unknown proto\n");
++ return 0;
++ }
++ tuple->dst.u.gre.key = htonl(ntohs(pgrehdr->call_id));
++ break;
++
++ default:
++ printk(KERN_WARNING "unknown GRE version %hu\n",
++ grehdr->version);
++ return 0;
++ }
++
++ srckey = gre_keymap_lookup(tuple);
++
++#if 0
++ DEBUGP("found src key %x for tuple ", ntohl(srckey));
++ DUMP_TUPLE_GRE(tuple);
++#endif
++ tuple->src.u.gre.key = srckey;
++
++ return 1;
++}
++
++/* print gre part of tuple */
++static unsigned int gre_print_tuple(char *buffer,
++ const struct ip_conntrack_tuple *tuple)
++{
++ return sprintf(buffer, "srckey=0x%x dstkey=0x%x ",
++ ntohl(tuple->src.u.gre.key),
++ ntohl(tuple->dst.u.gre.key));
++}
++
++/* print private data for conntrack */
++static unsigned int gre_print_conntrack(char *buffer,
++ const struct ip_conntrack *ct)
++{
++ return sprintf(buffer, "timeout=%u, stream_timeout=%u ",
++ (ct->proto.gre.timeout / HZ),
++ (ct->proto.gre.stream_timeout / HZ));
++}
++
++/* Returns verdict for packet, and may modify conntrack */
++static int gre_packet(struct ip_conntrack *ct,
++ struct iphdr *iph, size_t len,
++ enum ip_conntrack_info conntrackinfo)
++{
++ /* If we've seen traffic both ways, this is a GRE connection.
++ * Extend timeout. */
++ if (ct->status & IPS_SEEN_REPLY) {
++ ip_ct_refresh_acct(ct, ct->proto.gre.stream_timeout);
++ /* Also, more likely to be important, and not a probe. */
++ set_bit(IPS_ASSURED_BIT, &ct->status);
++ } else
++ ip_ct_refresh_acct(ct, ct->proto.gre.timeout);
++
++ return NF_ACCEPT;
++}
++
++/* Called when a new connection for this protocol found. */
++static int gre_new(struct ip_conntrack *ct,
++ struct iphdr *iph, size_t len)
++{
++ DEBUGP(": ");
++ DUMP_TUPLE_GRE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
++
++ /* initialize to sane value. Ideally a conntrack helper
++ * (e.g. in case of pptp) is increasing them */
++ ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT;
++ ct->proto.gre.timeout = GRE_TIMEOUT;
++
++ return 1;
++}
++
++/* Called when a conntrack entry has already been removed from the hashes
++ * and is about to be deleted from memory */
++static void gre_destroy(struct ip_conntrack *ct)
++{
++ struct ip_conntrack_expect *master = ct->master;
++
++ DEBUGP(" entering\n");
++
++ if (!master) {
++ DEBUGP("no master exp for ct %p\n", ct);
++ return;
++ }
++
++ ip_ct_gre_keymap_destroy(master);
++}
++
++/* protocol helper struct */
++static struct ip_conntrack_protocol gre = { { NULL, NULL }, IPPROTO_GRE,
++ "gre",
++ gre_pkt_to_tuple,
++ gre_invert_tuple,
++ gre_print_tuple,
++ gre_print_conntrack,
++ gre_packet,
++ gre_new,
++ gre_destroy,
++ NULL,
++ THIS_MODULE };
++
++/* ip_conntrack_proto_gre initialization */
++static int __init init(void)
++{
++ int retcode;
++
++ if ((retcode = ip_conntrack_protocol_register(&gre))) {
++ printk(KERN_ERR "Unable to register conntrack protocol "
++ "helper for gre: %d\n", retcode);
++ return -EIO;
++ }
++
++ return 0;
++}
++
++static void __exit fini(void)
++{
++ struct list_head *pos, *n;
++
++ /* delete all keymap entries */
++ WRITE_LOCK(&ip_ct_gre_lock);
++ list_for_each_safe(pos, n, &gre_keymap_list) {
++ DEBUGP("deleting keymap %p at module unload time\n", pos);
++ list_del(pos);
++ kfree(pos);
++ }
++ WRITE_UNLOCK(&ip_ct_gre_lock);
++
++ ip_conntrack_protocol_unregister(&gre);
++}
++
++EXPORT_SYMBOL(ip_ct_gre_keymap_add);
++EXPORT_SYMBOL(ip_ct_gre_keymap_change);
++EXPORT_SYMBOL(ip_ct_gre_keymap_destroy);
++
++module_init(init);
++module_exit(fini);
+diff -urN linux-2.4.29-old/net/ipv4/netfilter/ip_nat_core.c linux-2.4.29-dev/net/ipv4/netfilter/ip_nat_core.c
+--- linux-2.4.29-old/net/ipv4/netfilter/ip_nat_core.c 2005-01-19 15:10:13.000000000 +0100
++++ linux-2.4.29-dev/net/ipv4/netfilter/ip_nat_core.c 2005-04-02 19:07:18.000000000 +0200
+@@ -424,7 +424,7 @@
+ *tuple = *orig_tuple;
+ while ((rptr = find_best_ips_proto_fast(tuple, mr, conntrack, hooknum))
+ != NULL) {
+- DEBUGP("Found best for "); DUMP_TUPLE(tuple);
++ DEBUGP("Found best for "); DUMP_TUPLE_RAW(tuple);
+ /* 3) The per-protocol part of the manip is made to
+ map into the range to make a unique tuple. */
+
+@@ -564,9 +564,9 @@
+ HOOK2MANIP(hooknum)==IP_NAT_MANIP_SRC ? "SRC" : "DST",
+ conntrack);
+ DEBUGP("Original: ");
+- DUMP_TUPLE(&orig_tp);
++ DUMP_TUPLE_RAW(&orig_tp);
+ DEBUGP("New: ");
+- DUMP_TUPLE(&new_tuple);
++ DUMP_TUPLE_RAW(&new_tuple);
+ #endif
+
+ /* We now have two tuples (SRCIP/SRCPT/DSTIP/DSTPT):
+diff -urN linux-2.4.29-old/net/ipv4/netfilter/ip_nat_pptp.c linux-2.4.29-dev/net/ipv4/netfilter/ip_nat_pptp.c
+--- linux-2.4.29-old/net/ipv4/netfilter/ip_nat_pptp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29-dev/net/ipv4/netfilter/ip_nat_pptp.c 2005-04-02 19:14:52.000000000 +0200
+@@ -0,0 +1,475 @@
++/*
++ * ip_nat_pptp.c - Version 1.5
++ *
++ * NAT support for PPTP (Point to Point Tunneling Protocol).
++ * PPTP is a a protocol for creating virtual private networks.
++ * It is a specification defined by Microsoft and some vendors
++ * working with Microsoft. PPTP is built on top of a modified
++ * version of the Internet Generic Routing Encapsulation Protocol.
++ * GRE is defined in RFC 1701 and RFC 1702. Documentation of
++ * PPTP can be found in RFC 2637
++ *
++ * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
++ *
++ * Development of this code funded by Astaro AG (http://www.astaro.com/)
++ *
++ * TODO: - Support for multiple calls within one session
++ * (needs netfilter newnat code)
++ * - NAT to a unique tuple, not to TCP source port
++ * (needs netfilter tuple reservation)
++ *
++ * Changes:
++ * 2002-02-10 - Version 1.3
++ * - Use ip_nat_mangle_tcp_packet() because of cloned skb's
++ * in local connections (Philip Craig <philipc@snapgear.com>)
++ * - add checks for magicCookie and pptp version
++ * - make argument list of pptp_{out,in}bound_packet() shorter
++ * - move to C99 style initializers
++ * - print version number at module loadtime
++ * 2003-09-22 - Version 1.5
++ * - use SNATed tcp sourceport as callid, since we get called before
++ * TCP header is mangled (Philip Craig <philipc@snapgear.com>)
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <net/tcp.h>
++#include <linux/netfilter_ipv4/ip_nat.h>
++#include <linux/netfilter_ipv4/ip_nat_rule.h>
++#include <linux/netfilter_ipv4/ip_nat_helper.h>
++#include <linux/netfilter_ipv4/ip_nat_pptp.h>
++#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
++#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
++#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
++
++#define IP_NAT_PPTP_VERSION "1.5"
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
++MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
++
++
++#if 0
++#include "ip_conntrack_pptp_priv.h"
++#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
++ ": " format, ## args)
++#else
++#define DEBUGP(format, args...)
++#endif
++
++static unsigned int
++pptp_nat_expected(struct sk_buff **pskb,
++ unsigned int hooknum,
++ struct ip_conntrack *ct,
++ struct ip_nat_info *info)
++{
++ struct ip_conntrack *master = master_ct(ct);
++ struct ip_nat_multi_range mr;
++ struct ip_ct_pptp_master *ct_pptp_info;
++ struct ip_nat_pptp *nat_pptp_info;
++ u_int32_t newip, newcid;
++ int ret;
++
++ IP_NF_ASSERT(info);
++ IP_NF_ASSERT(master);
++ IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
++
++ DEBUGP("we have a connection!\n");
++
++ LOCK_BH(&ip_pptp_lock);
++ ct_pptp_info = &master->help.ct_pptp_info;
++ nat_pptp_info = &master->nat.help.nat_pptp_info;
++
++ /* need to alter GRE tuple because conntrack expectfn() used 'wrong'
++ * (unmanipulated) values */
++ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
++ DEBUGP("completing tuples with NAT info \n");
++ /* we can do this, since we're unconfirmed */
++ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
++ htonl(ct_pptp_info->pac_call_id)) {
++ /* assume PNS->PAC */
++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
++ htonl(nat_pptp_info->pns_call_id);
++ ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
++ htonl(nat_pptp_info->pns_call_id);
++ newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
++ newcid = htonl(nat_pptp_info->pac_call_id);
++ } else {
++ /* assume PAC->PNS */
++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
++ htonl(nat_pptp_info->pac_call_id);
++ ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
++ htonl(nat_pptp_info->pac_call_id);
++ newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
++ newcid = htonl(nat_pptp_info->pns_call_id);
++ }
++ } else {
++ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
++ htonl(ct_pptp_info->pac_call_id)) {
++ /* assume PNS->PAC */
++ newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
++ newcid = htonl(ct_pptp_info->pns_call_id);
++ }
++ else {
++ /* assume PAC->PNS */
++ newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
++ newcid = htonl(ct_pptp_info->pac_call_id);
++ }
++ }
++
++ mr.rangesize = 1;
++ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED;
++ mr.range[0].min_ip = mr.range[0].max_ip = newip;
++ mr.range[0].min = mr.range[0].max =
++ ((union ip_conntrack_manip_proto ) { newcid });
++ DEBUGP("change ip to %u.%u.%u.%u\n",
++ NIPQUAD(newip));
++ DEBUGP("change key to 0x%x\n", ntohl(newcid));
++ ret = ip_nat_setup_info(ct, &mr, hooknum);
++
++ UNLOCK_BH(&ip_pptp_lock);
++
++ return ret;
++
++}
++
++/* outbound packets == from PNS to PAC */
++static inline unsigned int
++pptp_outbound_pkt(struct sk_buff **pskb,
++ struct ip_conntrack *ct,
++ enum ip_conntrack_info ctinfo,
++ struct ip_conntrack_expect *exp)
++
++{
++ struct iphdr *iph = (*pskb)->nh.iph;
++ struct tcphdr *tcph = (void *) iph + iph->ihl*4;
++ struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *)
++ ((void *)tcph + tcph->doff*4);
++
++ struct PptpControlHeader *ctlh;
++ union pptp_ctrl_union pptpReq;
++ struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
++ struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
++
++ u_int16_t msg, *cid = NULL, new_callid;
++
++ /* FIXME: size checks !!! */
++ ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
++ pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
++
++ new_callid = htons(ct_pptp_info->pns_call_id);
++
++ switch (msg = ntohs(ctlh->messageType)) {
++ case PPTP_OUT_CALL_REQUEST:
++ cid = &pptpReq.ocreq->callID;
++ /* FIXME: ideally we would want to reserve a call ID
++ * here. current netfilter NAT core is not able to do
++ * this :( For now we use TCP source port. This breaks
++ * multiple calls within one control session */
++
++ /* save original call ID in nat_info */
++ nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id;
++
++ /* don't use tcph->source since we are at a DSTmanip
++ * hook (e.g. PREROUTING) and pkt is not mangled yet */
++ new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port;
++
++ /* save new call ID in ct info */
++ ct_pptp_info->pns_call_id = ntohs(new_callid);
++ break;
++ case PPTP_IN_CALL_REPLY:
++ cid = &pptpReq.icreq->callID;
++ break;
++ case PPTP_CALL_CLEAR_REQUEST:
++ cid = &pptpReq.clrreq->callID;
++ break;
++ default:
++ DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
++ (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
++ /* fall through */
++
++ case PPTP_SET_LINK_INFO:
++ /* only need to NAT in case PAC is behind NAT box */
++ case PPTP_START_SESSION_REQUEST:
++ case PPTP_START_SESSION_REPLY:
++ case PPTP_STOP_SESSION_REQUEST:
++ case PPTP_STOP_SESSION_REPLY:
++ case PPTP_ECHO_REQUEST:
++ case PPTP_ECHO_REPLY:
++ /* no need to alter packet */
++ return NF_ACCEPT;
++ }
++
++ IP_NF_ASSERT(cid);
++
++ DEBUGP("altering call id from 0x%04x to 0x%04x\n",
++ ntohs(*cid), ntohs(new_callid));
++
++ /* mangle packet */
++ ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)cid - (void *)pptph,
++ sizeof(new_callid), (char *)&new_callid,
++ sizeof(new_callid));
++
++ return NF_ACCEPT;
++}
++
++/* inbound packets == from PAC to PNS */
++static inline unsigned int
++pptp_inbound_pkt(struct sk_buff **pskb,
++ struct ip_conntrack *ct,
++ enum ip_conntrack_info ctinfo,
++ struct ip_conntrack_expect *oldexp)
++{
++ struct iphdr *iph = (*pskb)->nh.iph;
++ struct tcphdr *tcph = (void *) iph + iph->ihl*4;
++ struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *)
++ ((void *)tcph + tcph->doff*4);
++
++ struct PptpControlHeader *ctlh;
++ union pptp_ctrl_union pptpReq;
++ struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
++ struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
++
++ u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL;
++ u_int32_t old_dst_ip;
++
++ struct ip_conntrack_tuple t, inv_t;
++ struct ip_conntrack_tuple *orig_t, *reply_t;
++
++ /* FIXME: size checks !!! */
++ ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
++ pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
++
++ new_pcid = htons(nat_pptp_info->pns_call_id);
++
++ switch (msg = ntohs(ctlh->messageType)) {
++ case PPTP_OUT_CALL_REPLY:
++ pcid = &pptpReq.ocack->peersCallID;
++ cid = &pptpReq.ocack->callID;
++ if (!oldexp) {
++ DEBUGP("outcall but no expectation\n");
++ break;
++ }
++ old_dst_ip = oldexp->tuple.dst.ip;
++ t = oldexp->tuple;
++ invert_tuplepr(&inv_t, &t);
++
++ /* save original PAC call ID in nat_info */
++ nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;
++
++ /* alter expectation */
++ orig_t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
++ reply_t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
++ if (t.src.ip == orig_t->src.ip && t.dst.ip == orig_t->dst.ip) {
++ /* expectation for PNS->PAC direction */
++ t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id);
++ t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id);
++ inv_t.src.ip = reply_t->src.ip;
++ inv_t.dst.ip = reply_t->dst.ip;
++ inv_t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id);
++ inv_t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id);
++ } else {
++ /* expectation for PAC->PNS direction */
++ t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id);
++ t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id);
++ inv_t.src.ip = orig_t->src.ip;
++ inv_t.dst.ip = orig_t->dst.ip;
++ inv_t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id);
++ inv_t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id);
++ }
++
++ if (!ip_conntrack_change_expect(oldexp, &t)) {
++ DEBUGP("successfully changed expect\n");
++ } else {
++ DEBUGP("can't change expect\n");
++ }
++ ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_orig, &t);
++ ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_reply, &inv_t);
++ break;
++ case PPTP_IN_CALL_CONNECT:
++ pcid = &pptpReq.iccon->peersCallID;
++ if (!oldexp)
++ break;
++ old_dst_ip = oldexp->tuple.dst.ip;
++ t = oldexp->tuple;
++
++ /* alter expectation, no need for callID */
++ if (t.dst.ip == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip) {
++ /* expectation for PNS->PAC direction */
++ t.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
++ } else {
++ /* expectation for PAC->PNS direction */
++ t.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
++ }
++
++ if (!ip_conntrack_change_expect(oldexp, &t)) {
++ DEBUGP("successfully changed expect\n");
++ } else {
++ DEBUGP("can't change expect\n");
++ }
++ break;
++ case PPTP_IN_CALL_REQUEST:
++ /* only need to nat in case PAC is behind NAT box */
++ break;
++ case PPTP_WAN_ERROR_NOTIFY:
++ pcid = &pptpReq.wanerr->peersCallID;
++ break;
++ case PPTP_CALL_DISCONNECT_NOTIFY:
++ pcid = &pptpReq.disc->callID;
++ break;
++
++ default:
++ DEBUGP("unknown inbound packet %s\n",
++ (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
++ /* fall through */
++
++ case PPTP_START_SESSION_REQUEST:
++ case PPTP_START_SESSION_REPLY:
++ case PPTP_STOP_SESSION_REQUEST:
++ case PPTP_STOP_SESSION_REPLY:
++ case PPTP_ECHO_REQUEST:
++ case PPTP_ECHO_REPLY:
++ /* no need to alter packet */
++ return NF_ACCEPT;
++ }
++
++ /* mangle packet */
++ IP_NF_ASSERT(pcid);
++ DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
++ ntohs(*pcid), ntohs(new_pcid));
++ ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)pcid - (void *)pptph,
++ sizeof(new_pcid), (char *)&new_pcid,
++ sizeof(new_pcid));
++
++ if (new_cid) {
++ IP_NF_ASSERT(cid);
++ DEBUGP("altering call id from 0x%04x to 0x%04x\n",
++ ntohs(*cid), ntohs(new_cid));
++ ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
++ (void *)cid - (void *)pptph,
++ sizeof(new_cid), (char *)&new_cid,
++ sizeof(new_cid));
++ }
++
++ /* great, at least we don't need to resize packets */
++ return NF_ACCEPT;
++}
++
++
++static unsigned int tcp_help(struct ip_conntrack *ct,
++ struct ip_conntrack_expect *exp,
++ struct ip_nat_info *info,
++ enum ip_conntrack_info ctinfo,
++ unsigned int hooknum, struct sk_buff **pskb)
++{
++ struct iphdr *iph = (*pskb)->nh.iph;
++ struct tcphdr *tcph = (void *) iph + iph->ihl*4;
++ unsigned int datalen = (*pskb)->len - iph->ihl*4 - tcph->doff*4;
++ struct pptp_pkt_hdr *pptph;
++
++ int dir;
++
++ DEBUGP("entering\n");
++
++ /* Only mangle things once: DST for original direction
++ and SRC for reply direction. */
++ dir = CTINFO2DIR(ctinfo);
++ if (!((HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
++ && dir == IP_CT_DIR_ORIGINAL)
++ || (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST
++ && dir == IP_CT_DIR_REPLY))) {
++ DEBUGP("Not touching dir %s at hook %s\n",
++ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
++ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
++ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
++ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT"
++ : hooknum == NF_IP_LOCAL_IN ? "INPUT" : "???");
++ return NF_ACCEPT;
++ }
++
++ /* if packet is too small, just skip it */
++ if (datalen < sizeof(struct pptp_pkt_hdr)+
++ sizeof(struct PptpControlHeader)) {
++ DEBUGP("pptp packet too short\n");
++ return NF_ACCEPT;
++ }
++
++ pptph = (struct pptp_pkt_hdr *) ((void *)tcph + tcph->doff*4);
++
++ /* if it's not a control message, we can't handle it */
++ if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
++ ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
++ DEBUGP("not a pptp control packet\n");
++ return NF_ACCEPT;
++ }
++
++ LOCK_BH(&ip_pptp_lock);
++
++ if (dir == IP_CT_DIR_ORIGINAL) {
++ /* reuqests sent by client to server (PNS->PAC) */
++ pptp_outbound_pkt(pskb, ct, ctinfo, exp);
++ } else {
++ /* response from the server to the client (PAC->PNS) */
++ pptp_inbound_pkt(pskb, ct, ctinfo, exp);
++ }
++
++ UNLOCK_BH(&ip_pptp_lock);
++
++ return NF_ACCEPT;
++}
++
++/* nat helper struct for control connection */
++static struct ip_nat_helper pptp_tcp_helper = {
++ .list = { NULL, NULL },
++ .name = "pptp",
++ .flags = IP_NAT_HELPER_F_ALWAYS,
++ .me = THIS_MODULE,
++ .tuple = { .src = { .ip = 0,
++ .u = { .tcp = { .port =
++ __constant_htons(PPTP_CONTROL_PORT) }
++ }
++ },
++ .dst = { .ip = 0,
++ .u = { .all = 0 },
++ .protonum = IPPROTO_TCP
++ }
++ },
++
++ .mask = { .src = { .ip = 0,
++ .u = { .tcp = { .port = 0xFFFF } }
++ },
++ .dst = { .ip = 0,
++ .u = { .all = 0 },
++ .protonum = 0xFFFF
++ }
++ },
++ .help = tcp_help,
++ .expect = pptp_nat_expected
++};
++
++
++static int __init init(void)
++{
++ DEBUGP("%s: registering NAT helper\n", __FILE__);
++ if (ip_nat_helper_register(&pptp_tcp_helper)) {
++ printk(KERN_ERR "Unable to register NAT application helper "
++ "for pptp\n");
++ return -EIO;
++ }
++
++ printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
++ return 0;
++}
++
++static void __exit fini(void)
++{
++ DEBUGP("cleanup_module\n" );
++ ip_nat_helper_unregister(&pptp_tcp_helper);
++ printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
++}
++
++module_init(init);
++module_exit(fini);
+diff -urN linux-2.4.29-old/net/ipv4/netfilter/ip_nat_proto_gre.c linux-2.4.29-dev/net/ipv4/netfilter/ip_nat_proto_gre.c
+--- linux-2.4.29-old/net/ipv4/netfilter/ip_nat_proto_gre.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29-dev/net/ipv4/netfilter/ip_nat_proto_gre.c 2005-04-02 19:15:10.000000000 +0200
+@@ -0,0 +1,202 @@
++/*
++ * ip_nat_proto_gre.c - Version 1.2
++ *
++ * NAT protocol helper module for GRE.
++ *
++ * GRE is a generic encapsulation protocol, which is generally not very
++ * suited for NAT, as it has no protocol-specific part as port numbers.
++ *
++ * It has an optional key field, which may help us distinguishing two
++ * connections between the same two hosts.
++ *
++ * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
++ *
++ * PPTP is built on top of a modified version of GRE, and has a mandatory
++ * field called "CallID", which serves us for the same purpose as the key
++ * field in plain GRE.
++ *
++ * Documentation about PPTP can be found in RFC 2637
++ *
++ * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
++ *
++ * Development of this code funded by Astaro AG (http://www.astaro.com/)
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/netfilter_ipv4/ip_nat.h>
++#include <linux/netfilter_ipv4/ip_nat_rule.h>
++#include <linux/netfilter_ipv4/ip_nat_protocol.h>
++#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
++MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
++
++#if 0
++#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
++ ": " format, ## args)
++#else
++#define DEBUGP(x, args...)
++#endif
++
++/* is key in given range between min and max */
++static int
++gre_in_range(const struct ip_conntrack_tuple *tuple,
++ enum ip_nat_manip_type maniptype,
++ const union ip_conntrack_manip_proto *min,
++ const union ip_conntrack_manip_proto *max)
++{
++ u_int32_t key;
++
++ if (maniptype == IP_NAT_MANIP_SRC)
++ key = tuple->src.u.gre.key;
++ else
++ key = tuple->dst.u.gre.key;
++
++ return ntohl(key) >= ntohl(min->gre.key)
++ && ntohl(key) <= ntohl(max->gre.key);
++}
++
++/* generate unique tuple ... */
++static int
++gre_unique_tuple(struct ip_conntrack_tuple *tuple,
++ const struct ip_nat_range *range,
++ enum ip_nat_manip_type maniptype,
++ const struct ip_conntrack *conntrack)
++{
++ u_int32_t min, i, range_size;
++ u_int32_t key = 0, *keyptr;
++
++ if (maniptype == IP_NAT_MANIP_SRC)
++ keyptr = &tuple->src.u.gre.key;
++ else
++ keyptr = &tuple->dst.u.gre.key;
++
++ if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
++
++ DEBUGP("%p: NATing GRE PPTP\n", conntrack);
++ min = 1;
++ range_size = 0xffff;
++
++ } else {
++ min = ntohl(range->min.gre.key);
++ range_size = ntohl(range->max.gre.key) - min + 1;
++ }
++
++ DEBUGP("min = %u, range_size = %u\n", min, range_size);
++
++ for (i = 0; i < range_size; i++, key++) {
++ *keyptr = htonl(min + key % range_size);
++ if (!ip_nat_used_tuple(tuple, conntrack))
++ return 1;
++ }
++
++ DEBUGP("%p: no NAT mapping\n", conntrack);
++
++ return 0;
++}
++
++/* manipulate a GRE packet according to maniptype */
++static void
++gre_manip_pkt(struct iphdr *iph, size_t len,
++ const struct ip_conntrack_manip *manip,
++ enum ip_nat_manip_type maniptype)
++{
++ struct gre_hdr *greh = (struct gre_hdr *)((u_int32_t *)iph+iph->ihl);
++ struct gre_hdr_pptp *pgreh = (struct gre_hdr_pptp *) greh;
++
++ /* we only have destination manip of a packet, since 'source key'
++ * is not present in the packet itself */
++ if (maniptype == IP_NAT_MANIP_DST) {
++ /* key manipulation is always dest */
++ switch (greh->version) {
++ case 0:
++ if (!greh->key) {
++ DEBUGP("can't nat GRE w/o key\n");
++ break;
++ }
++ if (greh->csum) {
++ /* FIXME: Never tested this code... */
++ *(gre_csum(greh)) =
++ ip_nat_cheat_check(~*(gre_key(greh)),
++ manip->u.gre.key,
++ *(gre_csum(greh)));
++ }
++ *(gre_key(greh)) = manip->u.gre.key;
++ break;
++ case GRE_VERSION_PPTP:
++ DEBUGP("call_id -> 0x%04x\n",
++ ntohl(manip->u.gre.key));
++ pgreh->call_id = htons(ntohl(manip->u.gre.key));
++ break;
++ default:
++ DEBUGP("can't nat unknown GRE version\n");
++ break;
++ }
++ }
++}
++
++/* print out a nat tuple */
++static unsigned int
++gre_print(char *buffer,
++ const struct ip_conntrack_tuple *match,
++ const struct ip_conntrack_tuple *mask)
++{
++ unsigned int len = 0;
++
++ if (mask->src.u.gre.key)
++ len += sprintf(buffer + len, "srckey=0x%x ",
++ ntohl(match->src.u.gre.key));
++
++ if (mask->dst.u.gre.key)
++ len += sprintf(buffer + len, "dstkey=0x%x ",
++ ntohl(match->src.u.gre.key));
++
++ return len;
++}
++
++/* print a range of keys */
++static unsigned int
++gre_print_range(char *buffer, const struct ip_nat_range *range)
++{
++ if (range->min.gre.key != 0
++ || range->max.gre.key != 0xFFFF) {
++ if (range->min.gre.key == range->max.gre.key)
++ return sprintf(buffer, "key 0x%x ",
++ ntohl(range->min.gre.key));
++ else
++ return sprintf(buffer, "keys 0x%u-0x%u ",
++ ntohl(range->min.gre.key),
++ ntohl(range->max.gre.key));
++ } else
++ return 0;
++}
++
++/* nat helper struct */
++static struct ip_nat_protocol gre =
++ { { NULL, NULL }, "GRE", IPPROTO_GRE,
++ gre_manip_pkt,
++ gre_in_range,
++ gre_unique_tuple,
++ gre_print,
++ gre_print_range
++ };
++
++static int __init init(void)
++{
++ if (ip_nat_protocol_register(&gre))
++ return -EIO;
++
++ return 0;
++}
++
++static void __exit fini(void)
++{
++ ip_nat_protocol_unregister(&gre);
++}
++
++module_init(init);
++module_exit(fini);
+diff -urN linux-2.4.29-old/net/ipv4/netfilter/Makefile linux-2.4.29-dev/net/ipv4/netfilter/Makefile
+--- linux-2.4.29-old/net/ipv4/netfilter/Makefile 2005-04-02 19:04:11.000000000 +0200
++++ linux-2.4.29-dev/net/ipv4/netfilter/Makefile 2005-04-02 19:07:18.000000000 +0200
+@@ -36,23 +36,32 @@
+ ifdef CONFIG_IP_NF_AMANDA
+ export-objs += ip_conntrack_amanda.o
+ endif
+-
+ obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
+ obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
+ ifdef CONFIG_IP_NF_FTP
+ export-objs += ip_conntrack_ftp.o
+ endif
+-
+ obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
+ ifdef CONFIG_IP_NF_IRC
+ export-objs += ip_conntrack_irc.o
+ endif
++obj-$(CONFIG_IP_NF_CT_PROTO_GRE) += ip_conntrack_proto_gre.o
++ifdef CONFIG_IP_NF_CT_PROTO_GRE
++ export-objs += ip_conntrack_proto_gre.o
++endif
++obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o
++ifdef CONFIG_IP_NF_NAT_PPTP
++ export-objs += ip_conntrack_pptp.o
++endif
++
+
+ # NAT helpers
+ obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
+ obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
+ obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
+ obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
++obj-$(CONFIG_IP_NF_NAT_PROTO_GRE) += ip_nat_proto_gre.o
++obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
+
+ # generic IP tables
+ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
+--- linux-2.4.32/net/ipv4/netfilter/ip_conntrack_pptp.c 1970-01-01 01:00:00.000000000 +0100
++++ /home/florian//openwrt/trunk/openwrt/build_mipsel/linux/net/ipv4/netfilter/ip_conntrack_pptp.c 2006-02-04 18:23:27.000000000 +0100
+@@ -0,0 +1,635 @@
++/*
++ * ip_conntrack_pptp.c - Version 1.9
++ *
++ * Connection tracking support for PPTP (Point to Point Tunneling Protocol).
++ * PPTP is a a protocol for creating virtual private networks.
++ * It is a specification defined by Microsoft and some vendors
++ * working with Microsoft. PPTP is built on top of a modified
++ * version of the Internet Generic Routing Encapsulation Protocol.
++ * GRE is defined in RFC 1701 and RFC 1702. Documentation of
++ * PPTP can be found in RFC 2637
++ *
++ * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
++ *
++ * Development of this code funded by Astaro AG (http://www.astaro.com/)
++ *
++ * Limitations:
++ * - We blindly assume that control connections are always
++ * established in PNS->PAC direction. This is a violation
++ * of RFFC2673
++ *
++ * TODO: - finish support for multiple calls within one session
++ * (needs expect reservations in newnat)
++ * - testing of incoming PPTP calls
++ *
++ * Changes:
++ * 2002-02-05 - Version 1.3
++ * - Call ip_conntrack_unexpect_related() from
++ * pptp_timeout_related() to destroy expectations in case
++ * CALL_DISCONNECT_NOTIFY or tcp fin packet was seen
++ * (Philip Craig <philipc@snapgear.com>)
++ * - Add Version information at module loadtime
++ * 2002-02-10 - Version 1.6
++ * - move to C99 style initializers
++ * - remove second expectation if first arrives
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/netfilter.h>
++#include <linux/ip.h>
++#include <net/checksum.h>
++#include <net/tcp.h>
++
++#include <linux/netfilter_ipv4/lockhelp.h>
++#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
++#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
++#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
++
++#define IP_CT_PPTP_VERSION "1.9"
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
++MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP");
++
++DECLARE_LOCK(ip_pptp_lock);
++
++#if 0
++#include "ip_conntrack_pptp_priv.h"
++#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
++ ": " format, ## args)
++#else
++#define DEBUGP(format, args...)
++#endif
++
++#define SECS *HZ
++#define MINS * 60 SECS
++#define HOURS * 60 MINS
++#define DAYS * 24 HOURS
++
++#define PPTP_GRE_TIMEOUT (10 MINS)
++#define PPTP_GRE_STREAM_TIMEOUT (5 DAYS)
++
++static int pptp_expectfn(struct ip_conntrack *ct)
++{
++ struct ip_conntrack *master;
++ struct ip_conntrack_expect *exp;
++
++ DEBUGP("increasing timeouts\n");
++ /* increase timeout of GRE data channel conntrack entry */
++ ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
++ ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT;
++
++ master = master_ct(ct);
++ if (!master) {
++ DEBUGP(" no master!!!\n");
++ return 0;
++ }
++
++ exp = ct->master;
++ if (!exp) {
++ DEBUGP("no expectation!!\n");
++ return 0;
++ }
++
++ DEBUGP("completing tuples with ct info\n");
++ /* we can do this, since we're unconfirmed */
++ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
++ htonl(master->help.ct_pptp_info.pac_call_id)) {
++ /* assume PNS->PAC */
++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
++ htonl(master->help.ct_pptp_info.pns_call_id);
++ ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
++ htonl(master->help.ct_pptp_info.pns_call_id);
++ } else {
++ /* assume PAC->PNS */
++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
++ htonl(master->help.ct_pptp_info.pac_call_id);
++ ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
++ htonl(master->help.ct_pptp_info.pac_call_id);
++ }
++
++ /* delete other expectation */
++ if (exp->expected_list.next != &exp->expected_list) {
++ struct ip_conntrack_expect *other_exp;
++ struct list_head *cur_item, *next;
++
++ for (cur_item = master->sibling_list.next;
++ cur_item != &master->sibling_list; cur_item = next) {
++ next = cur_item->next;
++ other_exp = list_entry(cur_item,
++ struct ip_conntrack_expect,
++ expected_list);
++ /* remove only if occurred at same sequence number */
++ if (other_exp != exp && other_exp->seq == exp->seq) {
++ DEBUGP("unexpecting other direction\n");
++ ip_ct_gre_keymap_destroy(other_exp);
++ ip_conntrack_unexpect_related(other_exp);
++ }
++ }
++ }
++
++ return 0;
++}
++
++/* timeout GRE data connections */
++static int pptp_timeout_related(struct ip_conntrack *ct)
++{
++ struct list_head *cur_item, *next;
++ struct ip_conntrack_expect *exp;
++ enum ip_conntrack_info ctinfo;
++ struct iphdr *iph;
++
++ /* FIXME: do we have to lock something ? */
++ for (cur_item = ct->sibling_list.next;
++ cur_item != &ct->sibling_list; cur_item = next) {
++ next = cur_item->next;
++ exp = list_entry(cur_item, struct ip_conntrack_expect,
++ expected_list);
++
++ ip_ct_gre_keymap_destroy(exp);
++ if (!exp->sibling) {
++ ip_conntrack_unexpect_related(exp);
++ continue;
++ }
++
++ DEBUGP("setting timeout of conntrack %p to 0\n",
++ exp->sibling);
++ exp->sibling->proto.gre.timeout = 0;
++ exp->sibling->proto.gre.stream_timeout = 0;
++ ip_ct_refresh_acct(exp->sibling, ctinfo, iph, 0);
++ }
++
++ return 0;
++}
++
++/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
++static inline int
++exp_gre(struct ip_conntrack *master,
++ u_int32_t seq,
++ u_int16_t callid,
++ u_int16_t peer_callid)
++{
++ struct ip_conntrack_expect exp;
++ struct ip_conntrack_tuple inv_tuple;
++
++ memset(&exp, 0, sizeof(exp));
++ /* tuple in original direction, PNS->PAC */
++ exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
++ exp.tuple.src.u.gre.key = htonl(ntohs(peer_callid));
++ exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
++ exp.tuple.dst.u.gre.key = htonl(ntohs(callid));
++ exp.tuple.dst.protonum = IPPROTO_GRE;
++
++ exp.mask.src.ip = 0xffffffff;
++ exp.mask.src.u.all = 0;
++ exp.mask.dst.u.all = 0;
++ exp.mask.dst.u.gre.key = 0xffffffff;
++ exp.mask.dst.ip = 0xffffffff;
++ exp.mask.dst.protonum = 0xffff;
++
++ exp.seq = seq;
++ exp.expectfn = pptp_expectfn;
++
++ exp.help.exp_pptp_info.pac_call_id = ntohs(callid);
++ exp.help.exp_pptp_info.pns_call_id = ntohs(peer_callid);
++
++ DEBUGP("calling expect_related ");
++ DUMP_TUPLE_RAW(&exp.tuple);
++
++ /* Add GRE keymap entries */
++ if (ip_ct_gre_keymap_add(&exp, &exp.tuple, 0) != 0)
++ return 1;
++
++ invert_tuplepr(&inv_tuple, &exp.tuple);
++ if (ip_ct_gre_keymap_add(&exp, &inv_tuple, 1) != 0) {
++ ip_ct_gre_keymap_destroy(&exp);
++ return 1;
++ }
++
++ if (ip_conntrack_expect_related(master, &exp) != 0) {
++ ip_ct_gre_keymap_destroy(&exp);
++ DEBUGP("cannot expect_related()\n");
++ return 1;
++ }
++
++ /* tuple in reply direction, PAC->PNS */
++ exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
++ exp.tuple.src.u.gre.key = htonl(ntohs(callid));
++ exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
++ exp.tuple.dst.u.gre.key = htonl(ntohs(peer_callid));
++
++ DEBUGP("calling expect_related ");
++ DUMP_TUPLE_RAW(&exp.tuple);
++
++ /* Add GRE keymap entries */
++ ip_ct_gre_keymap_add(&exp, &exp.tuple, 0);
++ invert_tuplepr(&inv_tuple, &exp.tuple);
++ ip_ct_gre_keymap_add(&exp, &inv_tuple, 1);
++ /* FIXME: cannot handle error correctly, since we need to free
++ * the above keymap :( */
++
++ if (ip_conntrack_expect_related(master, &exp) != 0) {
++ /* free the second pair of keypmaps */
++ ip_ct_gre_keymap_destroy(&exp);
++ DEBUGP("cannot expect_related():\n");
++ return 1;
++ }
++
++ return 0;
++}
++
++static inline int
++pptp_inbound_pkt(struct tcphdr *tcph,
++ struct pptp_pkt_hdr *pptph,
++ size_t datalen,
++ struct ip_conntrack *ct,
++ enum ip_conntrack_info ctinfo)
++{
++ struct PptpControlHeader *ctlh;
++ union pptp_ctrl_union pptpReq;
++
++ struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
++ u_int16_t msg, *cid, *pcid;
++ u_int32_t seq;
++
++ ctlh = (struct PptpControlHeader *)
++ ((char *) pptph + sizeof(struct pptp_pkt_hdr));
++ pptpReq.rawreq = (void *)
++ ((char *) ctlh + sizeof(struct PptpControlHeader));
++
++ msg = ntohs(ctlh->messageType);
++ DEBUGP("inbound control message %s\n", strMName[msg]);
++
++ switch (msg) {
++ case PPTP_START_SESSION_REPLY:
++ /* server confirms new control session */
++ if (info->sstate < PPTP_SESSION_REQUESTED) {
++ DEBUGP("%s without START_SESS_REQUEST\n",
++ strMName[msg]);
++ break;
++ }
++ if (pptpReq.srep->resultCode == PPTP_START_OK)
++ info->sstate = PPTP_SESSION_CONFIRMED;
++ else
++ info->sstate = PPTP_SESSION_ERROR;
++ break;
++
++ case PPTP_STOP_SESSION_REPLY:
++ /* server confirms end of control session */
++ if (info->sstate > PPTP_SESSION_STOPREQ) {
++ DEBUGP("%s without STOP_SESS_REQUEST\n",
++ strMName[msg]);
++ break;
++ }
++ if (pptpReq.strep->resultCode == PPTP_STOP_OK)
++ info->sstate = PPTP_SESSION_NONE;
++ else
++ info->sstate = PPTP_SESSION_ERROR;
++ break;
++
++ case PPTP_OUT_CALL_REPLY:
++ /* server accepted call, we now expect GRE frames */
++ if (info->sstate != PPTP_SESSION_CONFIRMED) {
++ DEBUGP("%s but no session\n", strMName[msg]);
++ break;
++ }
++ if (info->cstate != PPTP_CALL_OUT_REQ &&
++ info->cstate != PPTP_CALL_OUT_CONF) {
++ DEBUGP("%s without OUTCALL_REQ\n", strMName[msg]);
++ break;
++ }
++ if (pptpReq.ocack->resultCode != PPTP_OUTCALL_CONNECT) {
++ info->cstate = PPTP_CALL_NONE;
++ break;
++ }
++
++ cid = &pptpReq.ocack->callID;
++ pcid = &pptpReq.ocack->peersCallID;
++
++ info->pac_call_id = ntohs(*cid);
++
++ if (htons(info->pns_call_id) != *pcid) {
++ DEBUGP("%s for unknown callid %u\n",
++ strMName[msg], ntohs(*pcid));
++ break;
++ }
++
++ DEBUGP("%s, CID=%X, PCID=%X\n", strMName[msg],
++ ntohs(*cid), ntohs(*pcid));
++
++ info->cstate = PPTP_CALL_OUT_CONF;
++
++ seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
++ if (exp_gre(ct, seq, *cid, *pcid) != 0)
++ printk("ip_conntrack_pptp: error during exp_gre\n");
++ break;
++
++ case PPTP_IN_CALL_REQUEST:
++ /* server tells us about incoming call request */
++ if (info->sstate != PPTP_SESSION_CONFIRMED) {
++ DEBUGP("%s but no session\n", strMName[msg]);
++ break;
++ }
++ pcid = &pptpReq.icack->peersCallID;
++ DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid));
++ info->cstate = PPTP_CALL_IN_REQ;
++ info->pac_call_id= ntohs(*pcid);
++ break;
++
++ case PPTP_IN_CALL_CONNECT:
++ /* server tells us about incoming call established */
++ if (info->sstate != PPTP_SESSION_CONFIRMED) {
++ DEBUGP("%s but no session\n", strMName[msg]);
++ break;
++ }
++ if (info->sstate != PPTP_CALL_IN_REP
++ && info->sstate != PPTP_CALL_IN_CONF) {
++ DEBUGP("%s but never sent IN_CALL_REPLY\n",
++ strMName[msg]);
++ break;
++ }
++
++ pcid = &pptpReq.iccon->peersCallID;
++ cid = &info->pac_call_id;
++
++ if (info->pns_call_id != ntohs(*pcid)) {
++ DEBUGP("%s for unknown CallID %u\n",
++ strMName[msg], ntohs(*cid));
++ break;
++ }
++
++ DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid));
++ info->cstate = PPTP_CALL_IN_CONF;
++
++ /* we expect a GRE connection from PAC to PNS */
++ seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
++ if (exp_gre(ct, seq, *cid, *pcid) != 0)
++ printk("ip_conntrack_pptp: error during exp_gre\n");
++
++ break;
++
++ case PPTP_CALL_DISCONNECT_NOTIFY:
++ /* server confirms disconnect */
++ cid = &pptpReq.disc->callID;
++ DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid));
++ info->cstate = PPTP_CALL_NONE;
++
++ /* untrack this call id, unexpect GRE packets */
++ pptp_timeout_related(ct);
++ break;
++
++ case PPTP_WAN_ERROR_NOTIFY:
++ break;
++
++ case PPTP_ECHO_REQUEST:
++ case PPTP_ECHO_REPLY:
++ /* I don't have to explain these ;) */
++ break;
++ default:
++ DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)
++ ? strMName[msg]:strMName[0], msg);
++ break;
++ }
++
++ return NF_ACCEPT;
++
++}
++
++static inline int
++pptp_outbound_pkt(struct tcphdr *tcph,
++ struct pptp_pkt_hdr *pptph,
++ size_t datalen,
++ struct ip_conntrack *ct,
++ enum ip_conntrack_info ctinfo)
++{
++ struct PptpControlHeader *ctlh;
++ union pptp_ctrl_union pptpReq;
++ struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
++ u_int16_t msg, *cid, *pcid;
++
++ ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
++ pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
++
++ msg = ntohs(ctlh->messageType);
++ DEBUGP("outbound control message %s\n", strMName[msg]);
++
++ switch (msg) {
++ case PPTP_START_SESSION_REQUEST:
++ /* client requests for new control session */
++ if (info->sstate != PPTP_SESSION_NONE) {
++ DEBUGP("%s but we already have one",
++ strMName[msg]);
++ }
++ info->sstate = PPTP_SESSION_REQUESTED;
++ break;
++ case PPTP_STOP_SESSION_REQUEST:
++ /* client requests end of control session */
++ info->sstate = PPTP_SESSION_STOPREQ;
++ break;
++
++ case PPTP_OUT_CALL_REQUEST:
++ /* client initiating connection to server */
++ if (info->sstate != PPTP_SESSION_CONFIRMED) {
++ DEBUGP("%s but no session\n",
++ strMName[msg]);
++ break;
++ }
++ info->cstate = PPTP_CALL_OUT_REQ;
++ /* track PNS call id */
++ cid = &pptpReq.ocreq->callID;
++ DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid));
++ info->pns_call_id = ntohs(*cid);
++ break;
++ case PPTP_IN_CALL_REPLY:
++ /* client answers incoming call */
++ if (info->cstate != PPTP_CALL_IN_REQ
++ && info->cstate != PPTP_CALL_IN_REP) {
++ DEBUGP("%s without incall_req\n",
++ strMName[msg]);
++ break;
++ }
++ if (pptpReq.icack->resultCode != PPTP_INCALL_ACCEPT) {
++ info->cstate = PPTP_CALL_NONE;
++ break;
++ }
++ pcid = &pptpReq.icack->peersCallID;
++ if (info->pac_call_id != ntohs(*pcid)) {
++ DEBUGP("%s for unknown call %u\n",
++ strMName[msg], ntohs(*pcid));
++ break;
++ }
++ DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*pcid));
++ /* part two of the three-way handshake */
++ info->cstate = PPTP_CALL_IN_REP;
++ info->pns_call_id = ntohs(pptpReq.icack->callID);
++ break;
++
++ case PPTP_CALL_CLEAR_REQUEST:
++ /* client requests hangup of call */
++ if (info->sstate != PPTP_SESSION_CONFIRMED) {
++ DEBUGP("CLEAR_CALL but no session\n");
++ break;
++ }
++ /* FUTURE: iterate over all calls and check if
++ * call ID is valid. We don't do this without newnat,
++ * because we only know about last call */
++ info->cstate = PPTP_CALL_CLEAR_REQ;
++ break;
++ case PPTP_SET_LINK_INFO:
++ break;
++ case PPTP_ECHO_REQUEST:
++ case PPTP_ECHO_REPLY:
++ /* I don't have to explain these ;) */
++ break;
++ default:
++ DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)?
++ strMName[msg]:strMName[0], msg);
++ /* unknown: no need to create GRE masq table entry */
++ break;
++ }
++
++ return NF_ACCEPT;
++}
++
++
++/* track caller id inside control connection, call expect_related */
++static int
++conntrack_pptp_help(const struct iphdr *iph, size_t len,
++ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
++
++{
++ struct pptp_pkt_hdr *pptph;
++
++ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
++ u_int32_t tcplen = len - iph->ihl * 4;
++ u_int32_t datalen = tcplen - tcph->doff * 4;
++ void *datalimit;
++ int dir = CTINFO2DIR(ctinfo);
++ struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
++
++ int oldsstate, oldcstate;
++ int ret;
++
++ /* don't do any tracking before tcp handshake complete */
++ if (ctinfo != IP_CT_ESTABLISHED
++ && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
++ DEBUGP("ctinfo = %u, skipping\n", ctinfo);
++ return NF_ACCEPT;
++ }
++
++ /* not a complete TCP header? */
++ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
++ DEBUGP("tcplen = %u\n", tcplen);
++ return NF_ACCEPT;
++ }
++
++ /* checksum invalid? */
++ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
++ csum_partial((char *) tcph, tcplen, 0))) {
++ printk(KERN_NOTICE __FILE__ ": bad csum\n");
++ /* W2K PPTP server sends TCP packets with wrong checksum :(( */
++ //return NF_ACCEPT;
++ }
++
++ if (tcph->fin || tcph->rst) {
++ DEBUGP("RST/FIN received, timeouting GRE\n");
++ /* can't do this after real newnat */
++ info->cstate = PPTP_CALL_NONE;
++
++ /* untrack this call id, unexpect GRE packets */
++ pptp_timeout_related(ct);
++ }
++
++
++ pptph = (struct pptp_pkt_hdr *) ((void *) tcph + tcph->doff * 4);
++ datalimit = (void *) pptph + datalen;
++
++ /* not a full pptp packet header? */
++ if ((void *) pptph+sizeof(*pptph) >= datalimit) {
++ DEBUGP("no full PPTP header, can't track\n");
++ return NF_ACCEPT;
++ }
++
++ /* if it's not a control message we can't do anything with it */
++ if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
++ ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
++ DEBUGP("not a control packet\n");
++ return NF_ACCEPT;
++ }
++
++ oldsstate = info->sstate;
++ oldcstate = info->cstate;
++
++ LOCK_BH(&ip_pptp_lock);
++
++ /* FIXME: We just blindly assume that the control connection is always
++ * established from PNS->PAC. However, RFC makes no guarantee */
++ if (dir == IP_CT_DIR_ORIGINAL)
++ /* client -> server (PNS -> PAC) */
++ ret = pptp_outbound_pkt(tcph, pptph, datalen, ct, ctinfo);
++ else
++ /* server -> client (PAC -> PNS) */
++ ret = pptp_inbound_pkt(tcph, pptph, datalen, ct, ctinfo);
++ DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
++ oldsstate, info->sstate, oldcstate, info->cstate);
++ UNLOCK_BH(&ip_pptp_lock);
++
++ return ret;
++}
++
++/* control protocol helper */
++static struct ip_conntrack_helper pptp = {
++ .list = { NULL, NULL },
++ .name = "pptp",
++ .flags = IP_CT_HELPER_F_REUSE_EXPECT,
++ .me = THIS_MODULE,
++ .max_expected = 2,
++ .timeout = 0,
++ .tuple = { .src = { .ip = 0,
++ .u = { .tcp = { .port =
++ __constant_htons(PPTP_CONTROL_PORT) } }
++ },
++ .dst = { .ip = 0,
++ .u = { .all = 0 },
++ .protonum = IPPROTO_TCP
++ }
++ },
++ .mask = { .src = { .ip = 0,
++ .u = { .tcp = { .port = 0xffff } }
++ },
++ .dst = { .ip = 0,
++ .u = { .all = 0 },
++ .protonum = 0xffff
++ }
++ },
++ .help = conntrack_pptp_help
++};
++
++/* ip_conntrack_pptp initialization */
++static int __init init(void)
++{
++ int retcode;
++
++ DEBUGP(__FILE__ ": registering helper\n");
++ if ((retcode = ip_conntrack_helper_register(&pptp))) {
++ printk(KERN_ERR "Unable to register conntrack application "
++ "helper for pptp: %d\n", retcode);
++ return -EIO;
++ }
++
++ printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION);
++ return 0;
++}
++
++static void __exit fini(void)
++{
++ ip_conntrack_helper_unregister(&pptp);
++ printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
++}
++
++module_init(init);
++module_exit(fini);
++
++EXPORT_SYMBOL(ip_pptp_lock);
diff --git a/target/linux/generic-2.4/patches/604-netfilter_maxconn.patch b/target/linux/generic-2.4/patches/604-netfilter_maxconn.patch
new file mode 100644
index 0000000000..001ed67b88
--- /dev/null
+++ b/target/linux/generic-2.4/patches/604-netfilter_maxconn.patch
@@ -0,0 +1,20 @@
+--- ../../buildroot-unpacked/build_mipsel/linux/net/ipv4/netfilter/ip_conntrack_core.c 2004-11-28 22:59:36.000000000 -0500
++++ linux/net/ipv4/netfilter/ip_conntrack_core.c 2004-11-30 05:05:32.000000000 -0500
+@@ -1386,7 +1386,7 @@
+ nf_unregister_sockopt(&so_getorigdst);
+ }
+
+-static int hashsize = 0;
++static int hashsize = 5953;
+ MODULE_PARM(hashsize, "i");
+
+ int __init ip_conntrack_init(void)
+@@ -1407,7 +1407,7 @@
+ if (ip_conntrack_htable_size < 16)
+ ip_conntrack_htable_size = 16;
+ }
+- ip_conntrack_max = 8 * ip_conntrack_htable_size;
++ ip_conntrack_max = ip_conntrack_htable_size;
+
+ printk("ip_conntrack version %s (%u buckets, %d max)"
+ " - %Zd bytes per conntrack\n", IP_CONNTRACK_VERSION,
diff --git a/target/linux/generic-2.4/patches/605-netfilter_TTL.patch b/target/linux/generic-2.4/patches/605-netfilter_TTL.patch
new file mode 100644
index 0000000000..0aa3c80432
--- /dev/null
+++ b/target/linux/generic-2.4/patches/605-netfilter_TTL.patch
@@ -0,0 +1,180 @@
+diff -urN linux-2.4.30.old/Documentation/Configure.help linux-2.4.30.dev/Documentation/Configure.help
+--- linux-2.4.30.old/Documentation/Configure.help 2005-04-27 11:35:46.000000000 +0200
++++ linux-2.4.30.dev/Documentation/Configure.help 2005-04-27 11:43:49.000000000 +0200
+@@ -3209,6 +3209,15 @@
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
++TTL target support
++CONFIG_IP_NF_TARGET_TTL
++ This option adds a `TTL' target, which enables the user to set
++ the TTL value or increment / decrement the TTL value by a given
++ amount.
++
++ If you want to compile it as a module, say M here and read
++ Documentation/modules.txt. If unsure, say `N'.
++
+ ipchains (2.2-style) support
+ CONFIG_IP_NF_COMPAT_IPCHAINS
+ This option places ipchains (with masquerading and redirection
+diff -urN linux-2.4.30.old/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.4.30.dev/include/linux/netfilter_ipv4/ipt_TTL.h
+--- linux-2.4.30.old/include/linux/netfilter_ipv4/ipt_TTL.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30.dev/include/linux/netfilter_ipv4/ipt_TTL.h 2005-04-27 11:43:49.000000000 +0200
+@@ -0,0 +1,21 @@
++/* TTL modification module for IP tables
++ * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
++
++#ifndef _IPT_TTL_H
++#define _IPT_TTL_H
++
++enum {
++ IPT_TTL_SET = 0,
++ IPT_TTL_INC,
++ IPT_TTL_DEC
++};
++
++#define IPT_TTL_MAXMODE IPT_TTL_DEC
++
++struct ipt_TTL_info {
++ u_int8_t mode;
++ u_int8_t ttl;
++};
++
++
++#endif
+diff -urN linux-2.4.30.old/net/ipv4/netfilter/Config.in linux-2.4.30.dev/net/ipv4/netfilter/Config.in
+--- linux-2.4.30.old/net/ipv4/netfilter/Config.in 2005-04-27 11:35:45.000000000 +0200
++++ linux-2.4.30.dev/net/ipv4/netfilter/Config.in 2005-04-27 11:43:49.000000000 +0200
+@@ -129,6 +129,7 @@
+ dep_tristate ' MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
+ fi
+ dep_tristate ' LOG target support' CONFIG_IP_NF_TARGET_LOG $CONFIG_IP_NF_IPTABLES
++ dep_tristate ' TTL target support' CONFIG_IP_NF_TARGET_TTL $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' ULOG target support' CONFIG_IP_NF_TARGET_ULOG $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' TCPMSS target support' CONFIG_IP_NF_TARGET_TCPMSS $CONFIG_IP_NF_IPTABLES
+ fi
+diff -urN linux-2.4.30.old/net/ipv4/netfilter/ipt_TTL.c linux-2.4.30.dev/net/ipv4/netfilter/ipt_TTL.c
+--- linux-2.4.30.old/net/ipv4/netfilter/ipt_TTL.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30.dev/net/ipv4/netfilter/ipt_TTL.c 2005-04-27 11:43:49.000000000 +0200
+@@ -0,0 +1,110 @@
++/* TTL modification target for IP tables
++ * (C) 2000 by Harald Welte <laforge@gnumonks.org>
++ *
++ * Version: $Revision: 1.1 $
++ *
++ * This software is distributed under the terms of GNU GPL
++ */
++
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/ip.h>
++#include <net/checksum.h>
++
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_TTL.h>
++
++MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
++MODULE_DESCRIPTION("IP tables TTL modification module");
++MODULE_LICENSE("GPL");
++
++static unsigned int ipt_ttl_target(struct sk_buff **pskb, unsigned int hooknum,
++ const struct net_device *in, const struct net_device *out,
++ const void *targinfo, void *userinfo)
++{
++ struct iphdr *iph = (*pskb)->nh.iph;
++ const struct ipt_TTL_info *info = targinfo;
++ u_int16_t diffs[2];
++ int new_ttl;
++
++ switch (info->mode) {
++ case IPT_TTL_SET:
++ new_ttl = info->ttl;
++ break;
++ case IPT_TTL_INC:
++ new_ttl = iph->ttl + info->ttl;
++ if (new_ttl > 255)
++ new_ttl = 255;
++ break;
++ case IPT_TTL_DEC:
++ new_ttl = iph->ttl - info->ttl;
++ if (new_ttl < 0)
++ new_ttl = 0;
++ break;
++ default:
++ new_ttl = iph->ttl;
++ break;
++ }
++
++ if (new_ttl != iph->ttl) {
++ diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
++ iph->ttl = new_ttl;
++ diffs[1] = htons(((unsigned)iph->ttl) << 8);
++ iph->check = csum_fold(csum_partial((char *)diffs,
++ sizeof(diffs),
++ iph->check^0xFFFF));
++ (*pskb)->nfcache |= NFC_ALTERED;
++ }
++
++ return IPT_CONTINUE;
++}
++
++static int ipt_ttl_checkentry(const char *tablename,
++ const struct ipt_entry *e,
++ void *targinfo,
++ unsigned int targinfosize,
++ unsigned int hook_mask)
++{
++ struct ipt_TTL_info *info = targinfo;
++
++ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
++ printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
++ targinfosize,
++ IPT_ALIGN(sizeof(struct ipt_TTL_info)));
++ return 0;
++ }
++
++ if (strcmp(tablename, "mangle")) {
++ printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
++ return 0;
++ }
++
++ if (info->mode > IPT_TTL_MAXMODE) {
++ printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
++ info->mode);
++ return 0;
++ }
++
++ if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
++ printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct ipt_target ipt_TTL = { { NULL, NULL }, "TTL",
++ ipt_ttl_target, ipt_ttl_checkentry, NULL, THIS_MODULE };
++
++static int __init init(void)
++{
++ return ipt_register_target(&ipt_TTL);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_target(&ipt_TTL);
++}
++
++module_init(init);
++module_exit(fini);
+diff -urN linux-2.4.30.old/net/ipv4/netfilter/Makefile linux-2.4.30.dev/net/ipv4/netfilter/Makefile
+--- linux-2.4.30.old/net/ipv4/netfilter/Makefile 2005-04-27 11:35:45.000000000 +0200
++++ linux-2.4.30.dev/net/ipv4/netfilter/Makefile 2005-04-27 11:43:49.000000000 +0200
+@@ -112,6 +112,7 @@
+ obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
+ obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
+ obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
++obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
+ obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
+ obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
+
diff --git a/target/linux/generic-2.4/patches/606-netfilter_NETMAP.patch b/target/linux/generic-2.4/patches/606-netfilter_NETMAP.patch
new file mode 100644
index 0000000000..ccd639181e
--- /dev/null
+++ b/target/linux/generic-2.4/patches/606-netfilter_NETMAP.patch
@@ -0,0 +1,159 @@
+diff -urN linux-2.4.30.orig/Documentation/Configure.help linux-2.4.30/Documentation/Configure.help
+--- linux-2.4.30.orig/Documentation/Configure.help 2005-07-01 02:06:36.000000000 +0200
++++ linux-2.4.30/Documentation/Configure.help 2005-07-01 00:41:09.000000000 +0200
+@@ -3086,6 +3086,17 @@
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
++NETMAP target support
++CONFIG_IP_NF_TARGET_NETMAP
++ NETMAP is an implementation of static 1:1 NAT mapping of network
++ addresses. It maps the network address part, while keeping the
++ host address part intact. It is similar to Fast NAT, except that
++ Netfilter's connection tracking doesn't work well with Fast NAT.
++
++ If you want to compile it as a module, say M here and read
++ Documentation/modules.txt. The module will be called
++ ipt_NETMAP.o. If unsure, say `N'.
++
+ Packet mangling
+ CONFIG_IP_NF_MANGLE
+ This option adds a `mangle' table to iptables: see the man page for
+diff -urN linux-2.4.30.orig/net/ipv4/netfilter/Config.in linux-2.4.30/net/ipv4/netfilter/Config.in
+--- linux-2.4.30.orig/net/ipv4/netfilter/Config.in 2005-07-01 02:06:35.000000000 +0200
++++ linux-2.4.30/net/ipv4/netfilter/Config.in 2005-07-01 00:41:09.000000000 +0200
+@@ -69,6 +69,7 @@
+ define_bool CONFIG_IP_NF_NAT_NEEDED y
+ dep_tristate ' MASQUERADE target support' CONFIG_IP_NF_TARGET_MASQUERADE $CONFIG_IP_NF_NAT
+ dep_tristate ' REDIRECT target support' CONFIG_IP_NF_TARGET_REDIRECT $CONFIG_IP_NF_NAT
++ dep_tristate ' NETMAP target support' CONFIG_IP_NF_TARGET_NETMAP $CONFIG_IP_NF_NAT
+ if [ "$CONFIG_IP_NF_PPTP" = "m" ]; then
+ define_tristate CONFIG_IP_NF_NAT_PPTP m
+ else
+diff -urN linux-2.4.30.orig/net/ipv4/netfilter/ipt_NETMAP.c linux-2.4.30/net/ipv4/netfilter/ipt_NETMAP.c
+--- linux-2.4.30.orig/net/ipv4/netfilter/ipt_NETMAP.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30/net/ipv4/netfilter/ipt_NETMAP.c 2005-07-01 00:41:09.000000000 +0200
+@@ -0,0 +1,112 @@
++/* NETMAP - static NAT mapping of IP network addresses (1:1).
++ The mapping can be applied to source (POSTROUTING),
++ destination (PREROUTING), or both (with separate rules).
++
++ Author: Svenning Soerensen <svenning@post5.tele.dk>
++*/
++
++#include <linux/config.h>
++#include <linux/ip.h>
++#include <linux/module.h>
++#include <linux/netdevice.h>
++#include <linux/netfilter.h>
++#include <linux/netfilter_ipv4.h>
++#include <linux/netfilter_ipv4/ip_nat_rule.h>
++
++#define MODULENAME "NETMAP"
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>");
++MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target");
++
++#if 0
++#define DEBUGP printk
++#else
++#define DEBUGP(format, args...)
++#endif
++
++static int
++check(const char *tablename,
++ const struct ipt_entry *e,
++ void *targinfo,
++ unsigned int targinfosize,
++ unsigned int hook_mask)
++{
++ const struct ip_nat_multi_range *mr = targinfo;
++
++ if (strcmp(tablename, "nat") != 0) {
++ DEBUGP(MODULENAME":check: bad table `%s'.\n", tablename);
++ return 0;
++ }
++ if (targinfosize != IPT_ALIGN(sizeof(*mr))) {
++ DEBUGP(MODULENAME":check: size %u.\n", targinfosize);
++ return 0;
++ }
++ if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_POST_ROUTING))) {
++ DEBUGP(MODULENAME":check: bad hooks %x.\n", hook_mask);
++ return 0;
++ }
++ if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) {
++ DEBUGP(MODULENAME":check: bad MAP_IPS.\n");
++ return 0;
++ }
++ if (mr->rangesize != 1) {
++ DEBUGP(MODULENAME":check: bad rangesize %u.\n", mr->rangesize);
++ return 0;
++ }
++ return 1;
++}
++
++static unsigned int
++target(struct sk_buff **pskb,
++ unsigned int hooknum,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *targinfo,
++ void *userinfo)
++{
++ struct ip_conntrack *ct;
++ enum ip_conntrack_info ctinfo;
++ u_int32_t new_ip, netmask;
++ const struct ip_nat_multi_range *mr = targinfo;
++ struct ip_nat_multi_range newrange;
++
++ IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING
++ || hooknum == NF_IP_POST_ROUTING);
++ ct = ip_conntrack_get(*pskb, &ctinfo);
++
++ netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip);
++
++ if (hooknum == NF_IP_PRE_ROUTING)
++ new_ip = (*pskb)->nh.iph->daddr & ~netmask;
++ else
++ new_ip = (*pskb)->nh.iph->saddr & ~netmask;
++ new_ip |= mr->range[0].min_ip & netmask;
++
++ newrange = ((struct ip_nat_multi_range)
++ { 1, { { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS,
++ new_ip, new_ip,
++ mr->range[0].min, mr->range[0].max } } });
++
++ /* Hand modified range to generic setup. */
++ return ip_nat_setup_info(ct, &newrange, hooknum);
++}
++
++static struct ipt_target target_module = {
++ .name = MODULENAME,
++ .target = target,
++ .checkentry = check,
++ .me = THIS_MODULE
++};
++
++static int __init init(void)
++{
++ return ipt_register_target(&target_module);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_target(&target_module);
++}
++
++module_init(init);
++module_exit(fini);
+diff -urN linux-2.4.30.orig/net/ipv4/netfilter/Makefile linux-2.4.30/net/ipv4/netfilter/Makefile
+--- linux-2.4.30.orig/net/ipv4/netfilter/Makefile 2005-07-01 02:06:35.000000000 +0200
++++ linux-2.4.30/net/ipv4/netfilter/Makefile 2005-07-01 00:41:09.000000000 +0200
+@@ -110,6 +110,7 @@
+ obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
+ obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
+ obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
++obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
+ obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
+ obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
+ obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
diff --git a/target/linux/generic-2.4/patches/607-netfilter_connmark.patch b/target/linux/generic-2.4/patches/607-netfilter_connmark.patch
new file mode 100644
index 0000000000..154314dc41
--- /dev/null
+++ b/target/linux/generic-2.4/patches/607-netfilter_connmark.patch
@@ -0,0 +1,351 @@
+diff -urN linux.old/include/linux/netfilter_ipv4/ip_conntrack.h linux.dev/include/linux/netfilter_ipv4/ip_conntrack.h
+--- linux.old/include/linux/netfilter_ipv4/ip_conntrack.h 2005-08-20 20:02:06.619827000 +0200
++++ linux.dev/include/linux/netfilter_ipv4/ip_conntrack.h 2005-08-20 20:19:23.302029232 +0200
+@@ -226,6 +226,9 @@
+ unsigned int app_data_len;
+ } layer7;
+ #endif
++#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
++ unsigned long mark;
++#endif
+ };
+
+ /* get master conntrack via master expectation */
+diff -urN linux.old/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux.dev/include/linux/netfilter_ipv4/ipt_CONNMARK.h
+--- linux.old/include/linux/netfilter_ipv4/ipt_CONNMARK.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2005-08-20 20:19:41.058329864 +0200
+@@ -0,0 +1,25 @@
++#ifndef _IPT_CONNMARK_H_target
++#define _IPT_CONNMARK_H_target
++
++/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
++ * by Henrik Nordstrom <hno@marasystems.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.
++ */
++
++enum {
++ IPT_CONNMARK_SET = 0,
++ IPT_CONNMARK_SAVE,
++ IPT_CONNMARK_RESTORE
++};
++
++struct ipt_connmark_target_info {
++ unsigned long mark;
++ unsigned long mask;
++ u_int8_t mode;
++};
++
++#endif /*_IPT_CONNMARK_H_target*/
+diff -urN linux.old/include/linux/netfilter_ipv4/ipt_connmark.h linux.dev/include/linux/netfilter_ipv4/ipt_connmark.h
+--- linux.old/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/linux/netfilter_ipv4/ipt_connmark.h 2005-08-20 20:19:41.058329864 +0200
+@@ -0,0 +1,18 @@
++#ifndef _IPT_CONNMARK_H
++#define _IPT_CONNMARK_H
++
++/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
++ * by Henrik Nordstrom <hno@marasystems.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.
++ */
++
++struct ipt_connmark_info {
++ unsigned long mark, mask;
++ u_int8_t invert;
++};
++
++#endif /*_IPT_CONNMARK_H*/
+diff -urN linux.old/net/ipv4/netfilter/Config.in linux.dev/net/ipv4/netfilter/Config.in
+--- linux.old/net/ipv4/netfilter/Config.in 2005-08-20 20:02:09.325416000 +0200
++++ linux.dev/net/ipv4/netfilter/Config.in 2005-08-20 20:29:11.546602464 +0200
+@@ -6,7 +6,8 @@
+
+ tristate 'Connection tracking (required for masq/NAT)' CONFIG_IP_NF_CONNTRACK
+ if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
+- dep_tristate ' FTP protocol support' CONFIG_IP_NF_FTP $CONFIG_IP_NF_CONNTRACK
++ bool ' Connection mark tracking support' CONFIG_IP_NF_CONNTRACK_MARK
++ dep_tristate ' FTP protocol support' CONFIG_IP_NF_FTP $CONFIG_IP_NF_CONNTRACKa
+ dep_tristate ' Amanda protocol support' CONFIG_IP_NF_AMANDA $CONFIG_IP_NF_CONNTRACK
+ dep_tristate ' TFTP protocol support' CONFIG_IP_NF_TFTP $CONFIG_IP_NF_CONNTRACK
+ dep_tristate ' IRC protocol support' CONFIG_IP_NF_IRC $CONFIG_IP_NF_CONNTRACK
+@@ -42,6 +43,9 @@
+ if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
+ dep_tristate ' Connection state match support' CONFIG_IP_NF_MATCH_STATE $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' Connection tracking match support' CONFIG_IP_NF_MATCH_CONNTRACK $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
++ if [ "$CONFIG_IP_NF_CONNTRACK_MARK" != "n" ]; then
++ dep_tristate ' Connection mark match support' CONFIG_IP_NF_MATCH_CONNMARK $CONFIG_IP_NF_IPTABLES
++ fi
+ fi
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ dep_tristate ' Unclean match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_UNCLEAN $CONFIG_IP_NF_IPTABLES
+@@ -125,6 +129,9 @@
+
+ dep_tristate ' MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
+ fi
++ if [ "$CONFIG_IP_NF_CONNTRACK_MARK" != "n" ]; then
++ dep_tristate ' CONNMARK target support' CONFIG_IP_NF_TARGET_CONNMARK $CONFIG_IP_NF_IPTABLES
++ fi
+ dep_tristate ' LOG target support' CONFIG_IP_NF_TARGET_LOG $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' TTL target support' CONFIG_IP_NF_TARGET_TTL $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' ULOG target support' CONFIG_IP_NF_TARGET_ULOG $CONFIG_IP_NF_IPTABLES
+diff -urN linux.old/net/ipv4/netfilter/Makefile linux.dev/net/ipv4/netfilter/Makefile
+--- linux.old/net/ipv4/netfilter/Makefile 2005-08-20 20:02:09.326416000 +0200
++++ linux.dev/net/ipv4/netfilter/Makefile 2005-08-20 20:29:54.081136232 +0200
+@@ -93,6 +93,7 @@
+
+ obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
+ obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
++obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
+ obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
+ obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
+ obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
+@@ -110,6 +111,7 @@
+ obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
+ obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
+ obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
++obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
+ obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
+ obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
+ obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
+diff -urN linux.old/net/ipv4/netfilter/ip_conntrack_core.c linux.dev/net/ipv4/netfilter/ip_conntrack_core.c
+--- linux.old/net/ipv4/netfilter/ip_conntrack_core.c 2005-08-20 20:02:06.828795000 +0200
++++ linux.dev/net/ipv4/netfilter/ip_conntrack_core.c 2005-08-20 20:33:23.308328864 +0200
+@@ -755,6 +755,9 @@
+ __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
+ conntrack->master = expected;
+ expected->sibling = conntrack;
++#ifdef CONFIG_IP_NF_CONNTRACK_MARK
++ conntrack->mark = expected->expectant->mark;
++#endif
+ LIST_DELETE(&ip_conntrack_expect_list, expected);
+ expected->expectant->expecting--;
+ nf_conntrack_get(&master_ct(conntrack)->infos[0]);
+diff -urN linux.old/net/ipv4/netfilter/ip_conntrack_standalone.c linux.dev/net/ipv4/netfilter/ip_conntrack_standalone.c
+--- linux.old/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-08-20 20:02:06.583833000 +0200
++++ linux.dev/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-08-20 20:32:15.364657872 +0200
+@@ -107,6 +107,9 @@
+ len += sprintf(buffer + len, "[ASSURED] ");
+ len += sprintf(buffer + len, "use=%u ",
+ atomic_read(&conntrack->ct_general.use));
++ #if defined(CONFIG_IP_NF_CONNTRACK_MARK)
++ len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
++ #endif
+
+ #if defined(CONFIG_IP_NF_MATCH_LAYER7) || defined(CONFIG_IP_NF_MATCH_LAYER7_MODULE)
+ if(conntrack->layer7.app_proto)
+diff -urN linux.old/net/ipv4/netfilter/ipt_CONNMARK.c linux.dev/net/ipv4/netfilter/ipt_CONNMARK.c
+--- linux.old/net/ipv4/netfilter/ipt_CONNMARK.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/net/ipv4/netfilter/ipt_CONNMARK.c 2005-08-20 20:21:28.666970864 +0200
+@@ -0,0 +1,118 @@
++/* This kernel module is used to modify the connection mark values, or
++ * to optionally restore the skb nfmark from the connection mark
++ *
++ * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
++ * by Henrik Nordstrom <hno@marasystems.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 <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/ip.h>
++#include <net/checksum.h>
++
++MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
++MODULE_DESCRIPTION("IP tables CONNMARK matching module");
++MODULE_LICENSE("GPL");
++
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
++#include <linux/netfilter_ipv4/ip_conntrack.h>
++
++static unsigned int
++target(struct sk_buff **pskb,
++ unsigned int hooknum,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *targinfo,
++ void *userinfo)
++{
++ const struct ipt_connmark_target_info *markinfo = targinfo;
++ unsigned long diff;
++ unsigned long nfmark;
++ unsigned long newmark;
++
++ enum ip_conntrack_info ctinfo;
++ struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
++ if (ct) {
++ switch(markinfo->mode) {
++ case IPT_CONNMARK_SET:
++ newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
++ if (newmark != ct->mark)
++ ct->mark = newmark;
++ break;
++ case IPT_CONNMARK_SAVE:
++ newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
++ if (ct->mark != newmark)
++ ct->mark = newmark;
++ break;
++ case IPT_CONNMARK_RESTORE:
++ nfmark = (*pskb)->nfmark;
++ diff = (ct->mark ^ nfmark & markinfo->mask);
++ if (diff != 0) {
++ (*pskb)->nfmark = nfmark ^ diff;
++ (*pskb)->nfcache |= NFC_ALTERED;
++ }
++ break;
++ }
++ }
++
++ return IPT_CONTINUE;
++}
++
++static int
++checkentry(const char *tablename,
++ const struct ipt_entry *e,
++ void *targinfo,
++ unsigned int targinfosize,
++ unsigned int hook_mask)
++{
++ struct ipt_connmark_target_info *matchinfo = targinfo;
++ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
++ printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
++ targinfosize,
++ IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
++ return 0;
++ }
++
++ if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
++ if (strcmp(tablename, "mangle") != 0) {
++ printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
++ return 0;
++ }
++ }
++
++ return 1;
++}
++
++static struct ipt_target ipt_connmark_reg = {
++ .name = "CONNMARK",
++ .target = &target,
++ .checkentry = &checkentry,
++ .me = THIS_MODULE
++};
++
++static int __init init(void)
++{
++ return ipt_register_target(&ipt_connmark_reg);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_target(&ipt_connmark_reg);
++}
++
++module_init(init);
++module_exit(fini);
+diff -urN linux.old/net/ipv4/netfilter/ipt_connmark.c linux.dev/net/ipv4/netfilter/ipt_connmark.c
+--- linux.old/net/ipv4/netfilter/ipt_connmark.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/net/ipv4/netfilter/ipt_connmark.c 2005-08-20 20:21:28.666970864 +0200
+@@ -0,0 +1,83 @@
++/* This kernel module matches connection mark values set by the
++ * CONNMARK target
++ *
++ * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
++ * by Henrik Nordstrom <hno@marasystems.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 <linux/module.h>
++#include <linux/skbuff.h>
++
++MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
++MODULE_DESCRIPTION("IP tables connmark match module");
++MODULE_LICENSE("GPL");
++
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_connmark.h>
++#include <linux/netfilter_ipv4/ip_conntrack.h>
++
++static int
++match(const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *matchinfo,
++ int offset,
++ const void *hdr,
++ u_int16_t datalen,
++ int *hotdrop)
++{
++ const struct ipt_connmark_info *info = matchinfo;
++ enum ip_conntrack_info ctinfo;
++ struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
++ if (!ct)
++ return 0;
++
++ return ((ct->mark & info->mask) == info->mark) ^ info->invert;
++}
++
++static int
++checkentry(const char *tablename,
++ const struct ipt_ip *ip,
++ void *matchinfo,
++ unsigned int matchsize,
++ unsigned int hook_mask)
++{
++ if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
++ return 0;
++
++ return 1;
++}
++
++static struct ipt_match connmark_match = {
++ .name = "connmark",
++ .match = &match,
++ .checkentry = &checkentry,
++ .me = THIS_MODULE
++};
++
++static int __init init(void)
++{
++ return ipt_register_match(&connmark_match);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_match(&connmark_match);
++}
++
++module_init(init);
++module_exit(fini);
diff --git a/target/linux/generic-2.4/patches/608-netfilter_ipset.patch b/target/linux/generic-2.4/patches/608-netfilter_ipset.patch
new file mode 100644
index 0000000000..8cf5c694d0
--- /dev/null
+++ b/target/linux/generic-2.4/patches/608-netfilter_ipset.patch
@@ -0,0 +1,5725 @@
+diff -Naur linux-old/Documentation/Configure.help linux-new/Documentation/Configure.help
+--- linux-old/Documentation/Configure.help 2005-07-23 23:34:46.000000000 +0200
++++ linux-new/Documentation/Configure.help 2005-08-10 22:13:01.000000000 +0200
+@@ -3209,6 +3209,75 @@
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
++IP set support
++CONFIG_IP_NF_SET
++ This option adds IP set support to the kernel.
++
++ In order to define and use sets, you need userlevel utilities: an
++ iptables binary which knows about IP sets and the program ipset(8),
++ by which you can define and setup the sets themselves.
++
++ If you want to compile it as a module, say M here and read
++ <file:Documentation/modules.txt>. If unsure, say `N'.
++
++set match support
++CONFIG_IP_NF_MATCH_SET
++ This option adds IP set match support.
++ You need the ipset utility to create and set up the sets.
++
++ If you want to compile it as a module, say M here and read
++ <file:Documentation/modules.txt>. If unsure, say `N'.
++
++SET target support
++CONFIG_IP_NF_TARGET_SET
++ This option adds IP set target support.
++ You need the ipset utility to create and set up the sets.
++
++ If you want to compile it as a module, say M here and read
++ <file:Documentation/modules.txt>. If unsure, say `N'.
++
++ipmap set type support
++CONFIG_IP_NF_SET_IPMAP
++ This option adds the ipmap set type support.
++
++ If you want to compile it as a module, say M here and read
++ <file:Documentation/modules.txt>. If unsure, say `N'.
++
++macipmap set type support
++CONFIG_IP_NF_SET_MACIPMAP
++ This option adds the macipmap set type support.
++
++ If you want to compile it as a module, say M here and read
++ <file:Documentation/modules.txt>. If unsure, say `N'.
++
++portmap set type support
++CONFIG_IP_NF_SET_PORTMAP
++ This option adds the portmap set type support.
++
++ If you want to compile it as a module, say M here and read
++ <file:Documentation/modules.txt>. If unsure, say `N'.
++
++iphash set type support
++CONFIG_IP_NF_SET_IPHASH
++ This option adds the iphash set type support.
++
++ If you want to compile it as a module, say M here and read
++ <file:Documentation/modules.txt>. If unsure, say `N'.
++
++nethash set type support
++CONFIG_IP_NF_SET_NETHASH
++ This option adds the nethash set type support.
++
++ If you want to compile it as a module, say M here and read
++ <file:Documentation/modules.txt>. If unsure, say `N'.
++
++iptree set type support
++CONFIG_IP_NF_SET_IPTREE
++ This option adds the iptree set type support.
++
++ If you want to compile it as a module, say M here and read
++ <file:Documentation/modules.txt>. If unsure, say `N'.
++
+ TTL target support
+ CONFIG_IP_NF_TARGET_TTL
+ This option adds a `TTL' target, which enables the user to set
+diff -Naur linux-old/include/linux/netfilter_ipv4/ip_set.h linux-new/include/linux/netfilter_ipv4/ip_set.h
+--- linux-old/include/linux/netfilter_ipv4/ip_set.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/include/linux/netfilter_ipv4/ip_set.h 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,489 @@
++#ifndef _IP_SET_H
++#define _IP_SET_H
++
++/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
++ * Patrick Schaaf <bof@bof.de>
++ * Martin Josefsson <gandalf@wlug.westbo.se>
++ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/*
++ * A sockopt of such quality has hardly ever been seen before on the open
++ * market! This little beauty, hardly ever used: above 64, so it's
++ * traditionally used for firewalling, not touched (even once!) by the
++ * 2.0, 2.2 and 2.4 kernels!
++ *
++ * Comes with its own certificate of authenticity, valid anywhere in the
++ * Free world!
++ *
++ * Rusty, 19.4.2000
++ */
++#define SO_IP_SET 83
++
++/*
++ * Heavily modify by Joakim Axelsson 08.03.2002
++ * - Made it more modulebased
++ *
++ * Additional heavy modifications by Jozsef Kadlecsik 22.02.2004
++ * - bindings added
++ * - in order to "deal with" backward compatibility, renamed to ipset
++ */
++
++/*
++ * Used so that the kernel module and ipset-binary can match their versions
++ */
++#define IP_SET_PROTOCOL_VERSION 2
++
++#define IP_SET_MAXNAMELEN 32 /* set names and set typenames */
++
++/* Lets work with our own typedef for representing an IP address.
++ * We hope to make the code more portable, possibly to IPv6...
++ *
++ * The representation works in HOST byte order, because most set types
++ * will perform arithmetic operations and compare operations.
++ *
++ * For now the type is an uint32_t.
++ *
++ * Make sure to ONLY use the functions when translating and parsing
++ * in order to keep the host byte order and make it more portable:
++ * parse_ip()
++ * parse_mask()
++ * parse_ipandmask()
++ * ip_tostring()
++ * (Joakim: where are they???)
++ */
++
++typedef uint32_t ip_set_ip_t;
++
++/* Sets are identified by an id in kernel space. Tweak with ip_set_id_t
++ * and IP_SET_INVALID_ID if you want to increase the max number of sets.
++ */
++typedef uint16_t ip_set_id_t;
++
++#define IP_SET_INVALID_ID 65535
++
++/* How deep we follow bindings */
++#define IP_SET_MAX_BINDINGS 6
++
++/*
++ * Option flags for kernel operations (ipt_set_info)
++ */
++#define IPSET_SRC 0x01 /* Source match/add */
++#define IPSET_DST 0x02 /* Destination match/add */
++#define IPSET_MATCH_INV 0x04 /* Inverse matching */
++
++/*
++ * Set types (flavours)
++ */
++#define IPSET_TYPE_IP 0 /* IP address type of set */
++#define IPSET_TYPE_PORT 1 /* Port type of set */
++
++/* Reserved keywords */
++#define IPSET_TOKEN_DEFAULT ":default:"
++#define IPSET_TOKEN_ALL ":all:"
++
++/* SO_IP_SET operation constants, and their request struct types.
++ *
++ * Operation ids:
++ * 0-99: commands with version checking
++ * 100-199: add/del/test/bind/unbind
++ * 200-299: list, save, restore
++ */
++
++/* Single shot operations:
++ * version, create, destroy, flush, rename and swap
++ *
++ * Sets are identified by name.
++ */
++
++#define IP_SET_REQ_STD \
++ unsigned op; \
++ unsigned version; \
++ char name[IP_SET_MAXNAMELEN]
++
++#define IP_SET_OP_CREATE 0x00000001 /* Create a new (empty) set */
++struct ip_set_req_create {
++ IP_SET_REQ_STD;
++ char typename[IP_SET_MAXNAMELEN];
++};
++
++#define IP_SET_OP_DESTROY 0x00000002 /* Remove a (empty) set */
++struct ip_set_req_std {
++ IP_SET_REQ_STD;
++};
++
++#define IP_SET_OP_FLUSH 0x00000003 /* Remove all IPs in a set */
++/* Uses ip_set_req_std */
++
++#define IP_SET_OP_RENAME 0x00000004 /* Rename a set */
++/* Uses ip_set_req_create */
++
++#define IP_SET_OP_SWAP 0x00000005 /* Swap two sets */
++/* Uses ip_set_req_create */
++
++union ip_set_name_index {
++ char name[IP_SET_MAXNAMELEN];
++ ip_set_id_t index;
++};
++
++#define IP_SET_OP_GET_BYNAME 0x00000006 /* Get set index by name */
++struct ip_set_req_get_set {
++ unsigned op;
++ unsigned version;
++ union ip_set_name_index set;
++};
++
++#define IP_SET_OP_GET_BYINDEX 0x00000007 /* Get set name by index */
++/* Uses ip_set_req_get_set */
++
++#define IP_SET_OP_VERSION 0x00000100 /* Ask kernel version */
++struct ip_set_req_version {
++ unsigned op;
++ unsigned version;
++};
++
++/* Double shots operations:
++ * add, del, test, bind and unbind.
++ *
++ * First we query the kernel to get the index and type of the target set,
++ * then issue the command. Validity of IP is checked in kernel in order
++ * to minimalize sockopt operations.
++ */
++
++/* Get minimal set data for add/del/test/bind/unbind IP */
++#define IP_SET_OP_ADT_GET 0x00000010 /* Get set and type */
++struct ip_set_req_adt_get {
++ unsigned op;
++ unsigned version;
++ union ip_set_name_index set;
++ char typename[IP_SET_MAXNAMELEN];
++};
++
++#define IP_SET_REQ_BYINDEX \
++ unsigned op; \
++ ip_set_id_t index;
++
++struct ip_set_req_adt {
++ IP_SET_REQ_BYINDEX;
++};
++
++#define IP_SET_OP_ADD_IP 0x00000101 /* Add an IP to a set */
++/* Uses ip_set_req_adt, with type specific addage */
++
++#define IP_SET_OP_DEL_IP 0x00000102 /* Remove an IP from a set */
++/* Uses ip_set_req_adt, with type specific addage */
++
++#define IP_SET_OP_TEST_IP 0x00000103 /* Test an IP in a set */
++/* Uses ip_set_req_adt, with type specific addage */
++
++#define IP_SET_OP_BIND_SET 0x00000104 /* Bind an IP to a set */
++/* Uses ip_set_req_bind, with type specific addage */
++struct ip_set_req_bind {
++ IP_SET_REQ_BYINDEX;
++ char binding[IP_SET_MAXNAMELEN];
++};
++
++#define IP_SET_OP_UNBIND_SET 0x00000105 /* Unbind an IP from a set */
++/* Uses ip_set_req_bind, with type speficic addage
++ * index = 0 means unbinding for all sets */
++
++#define IP_SET_OP_TEST_BIND_SET 0x00000106 /* Test binding an IP to a set */
++/* Uses ip_set_req_bind, with type specific addage */
++
++/* Multiple shots operations: list, save, restore.
++ *
++ * - check kernel version and query the max number of sets
++ * - get the basic information on all sets
++ * and size required for the next step
++ * - get actual set data: header, data, bindings
++ */
++
++/* Get max_sets and the index of a queried set
++ */
++#define IP_SET_OP_MAX_SETS 0x00000020
++struct ip_set_req_max_sets {
++ unsigned op;
++ unsigned version;
++ ip_set_id_t max_sets; /* max_sets */
++ ip_set_id_t sets; /* real number of sets */
++ union ip_set_name_index set; /* index of set if name used */
++};
++
++/* Get the id and name of the sets plus size for next step */
++#define IP_SET_OP_LIST_SIZE 0x00000201
++#define IP_SET_OP_SAVE_SIZE 0x00000202
++struct ip_set_req_setnames {
++ unsigned op;
++ ip_set_id_t index; /* set to list/save */
++ size_t size; /* size to get setdata/bindings */
++ /* followed by sets number of struct ip_set_name_list */
++};
++
++struct ip_set_name_list {
++ char name[IP_SET_MAXNAMELEN];
++ char typename[IP_SET_MAXNAMELEN];
++ ip_set_id_t index;
++ ip_set_id_t id;
++};
++
++/* The actual list operation */
++#define IP_SET_OP_LIST 0x00000203
++struct ip_set_req_list {
++ IP_SET_REQ_BYINDEX;
++ /* sets number of struct ip_set_list in reply */
++};
++
++struct ip_set_list {
++ ip_set_id_t index;
++ ip_set_id_t binding;
++ u_int32_t ref;
++ size_t header_size; /* Set header data of header_size */
++ size_t members_size; /* Set members data of members_size */
++ size_t bindings_size; /* Set bindings data of bindings_size */
++};
++
++struct ip_set_hash_list {
++ ip_set_ip_t ip;
++ ip_set_id_t binding;
++};
++
++/* The save operation */
++#define IP_SET_OP_SAVE 0x00000204
++/* Uses ip_set_req_list, in the reply replaced by
++ * sets number of struct ip_set_save plus a marker
++ * ip_set_save followed by ip_set_hash_save structures.
++ */
++struct ip_set_save {
++ ip_set_id_t index;
++ ip_set_id_t binding;
++ size_t header_size; /* Set header data of header_size */
++ size_t members_size; /* Set members data of members_size */
++};
++
++/* At restoring, ip == 0 means default binding for the given set: */
++struct ip_set_hash_save {
++ ip_set_ip_t ip;
++ ip_set_id_t id;
++ ip_set_id_t binding;
++};
++
++/* The restore operation */
++#define IP_SET_OP_RESTORE 0x00000205
++/* Uses ip_set_req_setnames followed by ip_set_restore structures
++ * plus a marker ip_set_restore, followed by ip_set_hash_save
++ * structures.
++ */
++struct ip_set_restore {
++ char name[IP_SET_MAXNAMELEN];
++ char typename[IP_SET_MAXNAMELEN];
++ ip_set_id_t index;
++ size_t header_size; /* Create data of header_size */
++ size_t members_size; /* Set members data of members_size */
++};
++
++static inline int bitmap_bytes(ip_set_ip_t a, ip_set_ip_t b)
++{
++ return 4 * ((((b - a + 8) / 8) + 3) / 4);
++}
++
++#ifdef __KERNEL__
++
++#define ip_set_printk(format, args...) \
++ do { \
++ printk("%s: %s: ", __FILE__, __FUNCTION__); \
++ printk(format "\n" , ## args); \
++ } while (0)
++
++#if defined(IP_SET_DEBUG)
++#define DP(format, args...) \
++ do { \
++ printk("%s: %s (DBG): ", __FILE__, __FUNCTION__);\
++ printk(format "\n" , ## args); \
++ } while (0)
++#define IP_SET_ASSERT(x) \
++ do { \
++ if (!(x)) \
++ printk("IP_SET_ASSERT: %s:%i(%s)\n", \
++ __FILE__, __LINE__, __FUNCTION__); \
++ } while (0)
++#else
++#define DP(format, args...)
++#define IP_SET_ASSERT(x)
++#endif
++
++struct ip_set;
++
++/*
++ * The ip_set_type definition - one per set type, e.g. "ipmap".
++ *
++ * Each individual set has a pointer, set->type, going to one
++ * of these structures. Function pointers inside the structure implement
++ * the real behaviour of the sets.
++ *
++ * If not mentioned differently, the implementation behind the function
++ * pointers of a set_type, is expected to return 0 if ok, and a negative
++ * errno (e.g. -EINVAL) on error.
++ */
++struct ip_set_type {
++ struct list_head list; /* next in list of set types */
++
++ /* test for IP in set (kernel: iptables -m set src|dst)
++ * return 0 if not in set, 1 if in set.
++ */
++ int (*testip_kernel) (struct ip_set *set,
++ const struct sk_buff * skb,
++ u_int32_t flags,
++ ip_set_ip_t *ip);
++
++ /* test for IP in set (userspace: ipset -T set IP)
++ * return 0 if not in set, 1 if in set.
++ */
++ int (*testip) (struct ip_set *set,
++ const void *data, size_t size,
++ ip_set_ip_t *ip);
++
++ /*
++ * Size of the data structure passed by when
++ * adding/deletin/testing an entry.
++ */
++ size_t reqsize;
++
++ /* Add IP into set (userspace: ipset -A set IP)
++ * Return -EEXIST if the address is already in the set,
++ * and -ERANGE if the address lies outside the set bounds.
++ * If the address was not already in the set, 0 is returned.
++ */
++ int (*addip) (struct ip_set *set,
++ const void *data, size_t size,
++ ip_set_ip_t *ip);
++
++ /* Add IP into set (kernel: iptables ... -j SET set src|dst)
++ * Return -EEXIST if the address is already in the set,
++ * and -ERANGE if the address lies outside the set bounds.
++ * If the address was not already in the set, 0 is returned.
++ */
++ int (*addip_kernel) (struct ip_set *set,
++ const struct sk_buff * skb,
++ u_int32_t flags,
++ ip_set_ip_t *ip);
++
++ /* remove IP from set (userspace: ipset -D set --entry x)
++ * Return -EEXIST if the address is NOT in the set,
++ * and -ERANGE if the address lies outside the set bounds.
++ * If the address really was in the set, 0 is returned.
++ */
++ int (*delip) (struct ip_set *set,
++ const void *data, size_t size,
++ ip_set_ip_t *ip);
++
++ /* remove IP from set (kernel: iptables ... -j SET --entry x)
++ * Return -EEXIST if the address is NOT in the set,
++ * and -ERANGE if the address lies outside the set bounds.
++ * If the address really was in the set, 0 is returned.
++ */
++ int (*delip_kernel) (struct ip_set *set,
++ const struct sk_buff * skb,
++ u_int32_t flags,
++ ip_set_ip_t *ip);
++
++ /* new set creation - allocated type specific items
++ */
++ int (*create) (struct ip_set *set,
++ const void *data, size_t size);
++
++ /* retry the operation after successfully tweaking the set
++ */
++ int (*retry) (struct ip_set *set);
++
++ /* set destruction - free type specific items
++ * There is no return value.
++ * Can be called only when child sets are destroyed.
++ */
++ void (*destroy) (struct ip_set *set);
++
++ /* set flushing - reset all bits in the set, or something similar.
++ * There is no return value.
++ */
++ void (*flush) (struct ip_set *set);
++
++ /* Listing: size needed for header
++ */
++ size_t header_size;
++
++ /* Listing: Get the header
++ *
++ * Fill in the information in "data".
++ * This function is always run after list_header_size() under a
++ * writelock on the set. Therefor is the length of "data" always
++ * correct.
++ */
++ void (*list_header) (const struct ip_set *set,
++ void *data);
++
++ /* Listing: Get the size for the set members
++ */
++ int (*list_members_size) (const struct ip_set *set);
++
++ /* Listing: Get the set members
++ *
++ * Fill in the information in "data".
++ * This function is always run after list_member_size() under a
++ * writelock on the set. Therefor is the length of "data" always
++ * correct.
++ */
++ void (*list_members) (const struct ip_set *set,
++ void *data);
++
++ char typename[IP_SET_MAXNAMELEN];
++ char typecode;
++ int protocol_version;
++
++ /* Set this to THIS_MODULE if you are a module, otherwise NULL */
++ struct module *me;
++};
++
++extern int ip_set_register_set_type(struct ip_set_type *set_type);
++extern void ip_set_unregister_set_type(struct ip_set_type *set_type);
++
++/* A generic ipset */
++struct ip_set {
++ char name[IP_SET_MAXNAMELEN]; /* the name of the set */
++ rwlock_t lock; /* lock for concurrency control */
++ ip_set_id_t id; /* set id for swapping */
++ ip_set_id_t binding; /* default binding for the set */
++ atomic_t ref; /* in kernel and in hash references */
++ struct ip_set_type *type; /* the set types */
++ void *data; /* pooltype specific data */
++};
++
++/* Structure to bind set elements to sets */
++struct ip_set_hash {
++ struct list_head list; /* list of clashing entries in hash */
++ ip_set_ip_t ip; /* ip from set */
++ ip_set_id_t id; /* set id */
++ ip_set_id_t binding; /* set we bind the element to */
++};
++
++/* register and unregister set references */
++extern ip_set_id_t ip_set_get_byname(const char name[IP_SET_MAXNAMELEN]);
++extern ip_set_id_t ip_set_get_byindex(ip_set_id_t id);
++extern void ip_set_put(ip_set_id_t id);
++
++/* API for iptables set match, and SET target */
++extern void ip_set_addip_kernel(ip_set_id_t id,
++ const struct sk_buff *skb,
++ const u_int32_t *flags);
++extern void ip_set_delip_kernel(ip_set_id_t id,
++ const struct sk_buff *skb,
++ const u_int32_t *flags);
++extern int ip_set_testip_kernel(ip_set_id_t id,
++ const struct sk_buff *skb,
++ const u_int32_t *flags);
++
++#endif /* __KERNEL__ */
++
++#endif /*_IP_SET_H*/
+diff -Naur linux-old/include/linux/netfilter_ipv4/ip_set_iphash.h linux-new/include/linux/netfilter_ipv4/ip_set_iphash.h
+--- linux-old/include/linux/netfilter_ipv4/ip_set_iphash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/include/linux/netfilter_ipv4/ip_set_iphash.h 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,30 @@
++#ifndef __IP_SET_IPHASH_H
++#define __IP_SET_IPHASH_H
++
++#include <linux/netfilter_ipv4/ip_set.h>
++
++#define SETTYPE_NAME "iphash"
++#define MAX_RANGE 0x0000FFFF
++
++struct ip_set_iphash {
++ ip_set_ip_t *members; /* the iphash proper */
++ uint32_t initval; /* initval for jhash_1word */
++ uint32_t prime; /* prime for double hashing */
++ uint32_t hashsize; /* hash size */
++ uint16_t probes; /* max number of probes */
++ uint16_t resize; /* resize factor in percent */
++ ip_set_ip_t netmask; /* netmask */
++};
++
++struct ip_set_req_iphash_create {
++ uint32_t hashsize;
++ uint16_t probes;
++ uint16_t resize;
++ ip_set_ip_t netmask;
++};
++
++struct ip_set_req_iphash {
++ ip_set_ip_t ip;
++};
++
++#endif /* __IP_SET_IPHASH_H */
+diff -Naur linux-old/include/linux/netfilter_ipv4/ip_set_ipmap.h linux-new/include/linux/netfilter_ipv4/ip_set_ipmap.h
+--- linux-old/include/linux/netfilter_ipv4/ip_set_ipmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/include/linux/netfilter_ipv4/ip_set_ipmap.h 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,56 @@
++#ifndef __IP_SET_IPMAP_H
++#define __IP_SET_IPMAP_H
++
++#include <linux/netfilter_ipv4/ip_set.h>
++
++#define SETTYPE_NAME "ipmap"
++#define MAX_RANGE 0x0000FFFF
++
++struct ip_set_ipmap {
++ void *members; /* the ipmap proper */
++ ip_set_ip_t first_ip; /* host byte order, included in range */
++ ip_set_ip_t last_ip; /* host byte order, included in range */
++ ip_set_ip_t netmask; /* subnet netmask */
++ ip_set_ip_t sizeid; /* size of set in IPs */
++ u_int16_t hosts; /* number of hosts in a subnet */
++};
++
++struct ip_set_req_ipmap_create {
++ ip_set_ip_t from;
++ ip_set_ip_t to;
++ ip_set_ip_t netmask;
++};
++
++struct ip_set_req_ipmap {
++ ip_set_ip_t ip;
++};
++
++unsigned int
++mask_to_bits(ip_set_ip_t mask)
++{
++ unsigned int bits = 32;
++ ip_set_ip_t maskaddr;
++
++ if (mask == 0xFFFFFFFF)
++ return bits;
++
++ maskaddr = 0xFFFFFFFE;
++ while (--bits >= 0 && maskaddr != mask)
++ maskaddr <<= 1;
++
++ return bits;
++}
++
++ip_set_ip_t
++range_to_mask(ip_set_ip_t from, ip_set_ip_t to, unsigned int *bits)
++{
++ ip_set_ip_t mask = 0xFFFFFFFE;
++
++ *bits = 32;
++ while (--(*bits) >= 0 && mask && (to & mask) != from)
++ mask <<= 1;
++
++ return mask;
++}
++
++#endif /* __IP_SET_IPMAP_H */
+diff -Naur linux-old/include/linux/netfilter_ipv4/ip_set_iptree.h linux-new/include/linux/netfilter_ipv4/ip_set_iptree.h
+--- linux-old/include/linux/netfilter_ipv4/ip_set_iptree.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/include/linux/netfilter_ipv4/ip_set_iptree.h 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,39 @@
++#ifndef __IP_SET_IPTREE_H
++#define __IP_SET_IPTREE_H
++
++#include <linux/netfilter_ipv4/ip_set.h>
++
++#define SETTYPE_NAME "iptree"
++#define MAX_RANGE 0x0000FFFF
++
++struct ip_set_iptreed {
++ unsigned long expires[255]; /* x.x.x.ADDR */
++};
++
++struct ip_set_iptreec {
++ struct ip_set_iptreed *tree[255]; /* x.x.ADDR.* */
++};
++
++struct ip_set_iptreeb {
++ struct ip_set_iptreec *tree[255]; /* x.ADDR.*.* */
++};
++
++struct ip_set_iptree {
++ unsigned int timeout;
++ unsigned int gc_interval;
++#ifdef __KERNEL__
++ struct timer_list gc;
++ struct ip_set_iptreeb *tree[255]; /* ADDR.*.*.* */
++#endif
++};
++
++struct ip_set_req_iptree_create {
++ unsigned int timeout;
++};
++
++struct ip_set_req_iptree {
++ ip_set_ip_t ip;
++ unsigned int timeout;
++};
++
++#endif /* __IP_SET_IPTREE_H */
+diff -Naur linux-old/include/linux/netfilter_ipv4/ip_set_jhash.h linux-new/include/linux/netfilter_ipv4/ip_set_jhash.h
+--- linux-old/include/linux/netfilter_ipv4/ip_set_jhash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/include/linux/netfilter_ipv4/ip_set_jhash.h 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,148 @@
++#ifndef _LINUX_IPSET_JHASH_H
++#define _LINUX_IPSET_JHASH_H
++
++/* This is a copy of linux/jhash.h but the types u32/u8 are changed
++ * to __u32/__u8 so that the header file can be included into
++ * userspace code as well. Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
++ */
++
++/* jhash.h: Jenkins hash support.
++ *
++ * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
++ *
++ * http://burtleburtle.net/bob/hash/
++ *
++ * These are the credits from Bob's sources:
++ *
++ * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
++ * hash(), hash2(), hash3, and mix() are externally useful functions.
++ * Routines to test the hash are included if SELF_TEST is defined.
++ * You can use this free for any purpose. It has no warranty.
++ *
++ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
++ *
++ * I've modified Bob's hash to be useful in the Linux kernel, and
++ * any bugs present are surely my fault. -DaveM
++ */
++
++/* NOTE: Arguments are modified. */
++#define __jhash_mix(a, b, c) \
++{ \
++ a -= b; a -= c; a ^= (c>>13); \
++ b -= c; b -= a; b ^= (a<<8); \
++ c -= a; c -= b; c ^= (b>>13); \
++ a -= b; a -= c; a ^= (c>>12); \
++ b -= c; b -= a; b ^= (a<<16); \
++ c -= a; c -= b; c ^= (b>>5); \
++ a -= b; a -= c; a ^= (c>>3); \
++ b -= c; b -= a; b ^= (a<<10); \
++ c -= a; c -= b; c ^= (b>>15); \
++}
++
++/* The golden ration: an arbitrary value */
++#define JHASH_GOLDEN_RATIO 0x9e3779b9
++
++/* The most generic version, hashes an arbitrary sequence
++ * of bytes. No alignment or length assumptions are made about
++ * the input key.
++ */
++static inline __u32 jhash(void *key, __u32 length, __u32 initval)
++{
++ __u32 a, b, c, len;
++ __u8 *k = key;
++
++ len = length;
++ a = b = JHASH_GOLDEN_RATIO;
++ c = initval;
++
++ while (len >= 12) {
++ a += (k[0] +((__u32)k[1]<<8) +((__u32)k[2]<<16) +((__u32)k[3]<<24));
++ b += (k[4] +((__u32)k[5]<<8) +((__u32)k[6]<<16) +((__u32)k[7]<<24));
++ c += (k[8] +((__u32)k[9]<<8) +((__u32)k[10]<<16)+((__u32)k[11]<<24));
++
++ __jhash_mix(a,b,c);
++
++ k += 12;
++ len -= 12;
++ }
++
++ c += length;
++ switch (len) {
++ case 11: c += ((__u32)k[10]<<24);
++ case 10: c += ((__u32)k[9]<<16);
++ case 9 : c += ((__u32)k[8]<<8);
++ case 8 : b += ((__u32)k[7]<<24);
++ case 7 : b += ((__u32)k[6]<<16);
++ case 6 : b += ((__u32)k[5]<<8);
++ case 5 : b += k[4];
++ case 4 : a += ((__u32)k[3]<<24);
++ case 3 : a += ((__u32)k[2]<<16);
++ case 2 : a += ((__u32)k[1]<<8);
++ case 1 : a += k[0];
++ };
++
++ __jhash_mix(a,b,c);
++
++ return c;
++}
++
++/* A special optimized version that handles 1 or more of __u32s.
++ * The length parameter here is the number of __u32s in the key.
++ */
++static inline __u32 jhash2(__u32 *k, __u32 length, __u32 initval)
++{
++ __u32 a, b, c, len;
++
++ a = b = JHASH_GOLDEN_RATIO;
++ c = initval;
++ len = length;
++
++ while (len >= 3) {
++ a += k[0];
++ b += k[1];
++ c += k[2];
++ __jhash_mix(a, b, c);
++ k += 3; len -= 3;
++ }
++
++ c += length * 4;
++
++ switch (len) {
++ case 2 : b += k[1];
++ case 1 : a += k[0];
++ };
++
++ __jhash_mix(a,b,c);
++
++ return c;
++}
++
++
++/* A special ultra-optimized versions that knows they are hashing exactly
++ * 3, 2 or 1 word(s).
++ *
++ * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
++ * done at the end is not done here.
++ */
++static inline __u32 jhash_3words(__u32 a, __u32 b, __u32 c, __u32 initval)
++{
++ a += JHASH_GOLDEN_RATIO;
++ b += JHASH_GOLDEN_RATIO;
++ c += initval;
++
++ __jhash_mix(a, b, c);
++
++ return c;
++}
++
++static inline __u32 jhash_2words(__u32 a, __u32 b, __u32 initval)
++{
++ return jhash_3words(a, b, 0, initval);
++}
++
++static inline __u32 jhash_1word(__u32 a, __u32 initval)
++{
++ return jhash_3words(a, 0, 0, initval);
++}
++
++#endif /* _LINUX_IPSET_JHASH_H */
+diff -Naur linux-old/include/linux/netfilter_ipv4/ip_set_macipmap.h linux-new/include/linux/netfilter_ipv4/ip_set_macipmap.h
+--- linux-old/include/linux/netfilter_ipv4/ip_set_macipmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/include/linux/netfilter_ipv4/ip_set_macipmap.h 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,38 @@
++#ifndef __IP_SET_MACIPMAP_H
++#define __IP_SET_MACIPMAP_H
++
++#include <linux/netfilter_ipv4/ip_set.h>
++
++#define SETTYPE_NAME "macipmap"
++#define MAX_RANGE 0x0000FFFF
++
++/* general flags */
++#define IPSET_MACIP_MATCHUNSET 1
++
++/* per ip flags */
++#define IPSET_MACIP_ISSET 1
++
++struct ip_set_macipmap {
++ void *members; /* the macipmap proper */
++ ip_set_ip_t first_ip; /* host byte order, included in range */
++ ip_set_ip_t last_ip; /* host byte order, included in range */
++ u_int32_t flags;
++};
++
++struct ip_set_req_macipmap_create {
++ ip_set_ip_t from;
++ ip_set_ip_t to;
++ u_int32_t flags;
++};
++
++struct ip_set_req_macipmap {
++ ip_set_ip_t ip;
++ unsigned char ethernet[ETH_ALEN];
++};
++
++struct ip_set_macip {
++ unsigned short flags;
++ unsigned char ethernet[ETH_ALEN];
++};
++
++#endif /* __IP_SET_MACIPMAP_H */
+diff -Naur linux-old/include/linux/netfilter_ipv4/ip_set_malloc.h linux-new/include/linux/netfilter_ipv4/ip_set_malloc.h
+--- linux-old/include/linux/netfilter_ipv4/ip_set_malloc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/include/linux/netfilter_ipv4/ip_set_malloc.h 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,27 @@
++#ifndef _IP_SET_MALLOC_H
++#define _IP_SET_MALLOC_H
++
++#ifdef __KERNEL__
++
++/* Memory allocation and deallocation */
++static size_t max_malloc_size = 131072; /* Guaranteed: slab.c */
++
++static inline void * ip_set_malloc(size_t bytes)
++{
++ if (bytes > max_malloc_size)
++ return vmalloc(bytes);
++ else
++ return kmalloc(bytes, GFP_KERNEL);
++}
++
++static inline void ip_set_free(void * data, size_t bytes)
++{
++ if (bytes > max_malloc_size)
++ vfree(data);
++ else
++ kfree(data);
++}
++
++#endif /* __KERNEL__ */
++
++#endif /*_IP_SET_MALLOC_H*/
+diff -Naur linux-old/include/linux/netfilter_ipv4/ip_set_nethash.h linux-new/include/linux/netfilter_ipv4/ip_set_nethash.h
+--- linux-old/include/linux/netfilter_ipv4/ip_set_nethash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/include/linux/netfilter_ipv4/ip_set_nethash.h 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,55 @@
++#ifndef __IP_SET_NETHASH_H
++#define __IP_SET_NETHASH_H
++
++#include <linux/netfilter_ipv4/ip_set.h>
++
++#define SETTYPE_NAME "nethash"
++#define MAX_RANGE 0x0000FFFF
++
++struct ip_set_nethash {
++ ip_set_ip_t *members; /* the nethash proper */
++ uint32_t initval; /* initval for jhash_1word */
++ uint32_t prime; /* prime for double hashing */
++ uint32_t hashsize; /* hash size */
++ uint16_t probes; /* max number of probes */
++ uint16_t resize; /* resize factor in percent */
++ unsigned char cidr[30]; /* CIDR sizes */
++};
++
++struct ip_set_req_nethash_create {
++ uint32_t hashsize;
++ uint16_t probes;
++ uint16_t resize;
++};
++
++struct ip_set_req_nethash {
++ ip_set_ip_t ip;
++ unsigned char cidr;
++};
++
++static unsigned char shifts[] = {255, 253, 249, 241, 225, 193, 129, 1};
++
++static inline ip_set_ip_t
++pack(ip_set_ip_t ip, unsigned char cidr)
++{
++ ip_set_ip_t addr, *paddr = &addr;
++ unsigned char n, t, *a;
++
++ addr = htonl(ip & (0xFFFFFFFF << (32 - (cidr))));
++#ifdef __KERNEL__
++ DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr);
++#endif
++ n = cidr / 8;
++ t = cidr % 8;
++ a = &((unsigned char *)paddr)[n];
++ *a = *a /(1 << (8 - t)) + shifts[t];
++#ifdef __KERNEL__
++ DP("n: %u, t: %u, a: %u", n, t, *a);
++ DP("ip:%u.%u.%u.%u/%u, %u.%u.%u.%u",
++ HIPQUAD(ip), cidr, NIPQUAD(addr));
++#endif
++
++ return ntohl(addr);
++}
++
++#endif /* __IP_SET_NETHASH_H */
+diff -Naur linux-old/include/linux/netfilter_ipv4/ip_set_portmap.h linux-new/include/linux/netfilter_ipv4/ip_set_portmap.h
+--- linux-old/include/linux/netfilter_ipv4/ip_set_portmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/include/linux/netfilter_ipv4/ip_set_portmap.h 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,25 @@
++#ifndef __IP_SET_PORTMAP_H
++#define __IP_SET_PORTMAP_H
++
++#include <linux/netfilter_ipv4/ip_set.h>
++
++#define SETTYPE_NAME "portmap"
++#define MAX_RANGE 0x0000FFFF
++#define INVALID_PORT (MAX_RANGE + 1)
++
++struct ip_set_portmap {
++ void *members; /* the portmap proper */
++ ip_set_ip_t first_port; /* host byte order, included in range */
++ ip_set_ip_t last_port; /* host byte order, included in range */
++};
++
++struct ip_set_req_portmap_create {
++ ip_set_ip_t from;
++ ip_set_ip_t to;
++};
++
++struct ip_set_req_portmap {
++ ip_set_ip_t port;
++};
++
++#endif /* __IP_SET_PORTMAP_H */
+diff -Naur linux-old/include/linux/netfilter_ipv4/ip_set_prime.h linux-new/include/linux/netfilter_ipv4/ip_set_prime.h
+--- linux-old/include/linux/netfilter_ipv4/ip_set_prime.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/include/linux/netfilter_ipv4/ip_set_prime.h 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,34 @@
++#ifndef __IP_SET_PRIME_H
++#define __IP_SET_PRIME_H
++
++static inline unsigned make_prime_bound(unsigned nr)
++{
++ unsigned long long nr64 = nr;
++ unsigned long long x = 1;
++ nr = 1;
++ while (x <= nr64) { x <<= 2; nr <<= 1; }
++ return nr;
++}
++
++static inline int make_prime_check(unsigned nr)
++{
++ unsigned x = 3;
++ unsigned b = make_prime_bound(nr);
++ while (x <= b) {
++ if (0 == (nr % x)) return 0;
++ x += 2;
++ }
++ return 1;
++}
++
++static unsigned make_prime(unsigned nr)
++{
++ if (0 == (nr & 1)) nr--;
++ while (nr > 1) {
++ if (make_prime_check(nr)) return nr;
++ nr -= 2;
++ }
++ return 2;
++}
++
++#endif /* __IP_SET_PRIME_H */
+diff -Naur linux-old/include/linux/netfilter_ipv4/ipt_set.h linux-new/include/linux/netfilter_ipv4/ipt_set.h
+--- linux-old/include/linux/netfilter_ipv4/ipt_set.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/include/linux/netfilter_ipv4/ipt_set.h 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,21 @@
++#ifndef _IPT_SET_H
++#define _IPT_SET_H
++
++#include <linux/netfilter_ipv4/ip_set.h>
++
++struct ipt_set_info {
++ ip_set_id_t index;
++ u_int32_t flags[IP_SET_MAX_BINDINGS + 1];
++};
++
++/* match info */
++struct ipt_set_info_match {
++ struct ipt_set_info match_set;
++};
++
++struct ipt_set_info_target {
++ struct ipt_set_info add_set;
++ struct ipt_set_info del_set;
++};
++
++#endif /*_IPT_SET_H*/
+diff -Naur linux-old/net/ipv4/netfilter/Config.in linux-new/net/ipv4/netfilter/Config.in
+--- linux-old/net/ipv4/netfilter/Config.in 2005-07-23 23:34:46.000000000 +0200
++++ linux-new/net/ipv4/netfilter/Config.in 2005-08-10 22:13:01.000000000 +0200
+@@ -21,6 +21,20 @@
+ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
+ # The simple matches.
+ dep_tristate ' limit match support' CONFIG_IP_NF_MATCH_LIMIT $CONFIG_IP_NF_IPTABLES
++
++ dep_tristate ' IP set support' CONFIG_IP_NF_SET $CONFIG_IP_NF_IPTABLES
++ if [ "$CONFIG_IP_NF_SET" != "n" ]; then
++ int ' Maximum number of sets' CONFIG_IP_NF_SET_MAX 256
++ int ' Hash size for bindings of IP sets' CONFIG_IP_NF_SET_HASHSIZE 1024
++ dep_tristate ' set match support' CONFIG_IP_NF_MATCH_SET $CONFIG_IP_NF_SET
++ dep_tristate ' SET target support' CONFIG_IP_NF_TARGET_SET $CONFIG_IP_NF_SET
++ dep_tristate ' ipmap set type support' CONFIG_IP_NF_SET_IPMAP $CONFIG_IP_NF_SET
++ dep_tristate ' portmap set type support' CONFIG_IP_NF_SET_PORTMAP $CONFIG_IP_NF_SET
++ dep_tristate ' macipmap set type support' CONFIG_IP_NF_SET_MACIPMAP $CONFIG_IP_NF_SET
++ dep_tristate ' iphash set type support' CONFIG_IP_NF_SET_IPHASH $CONFIG_IP_NF_SET
++ dep_tristate ' nethash set type support' CONFIG_IP_NF_SET_NETHASH $CONFIG_IP_NF_SET
++ dep_tristate ' iptree set type support' CONFIG_IP_NF_SET_IPTREE $CONFIG_IP_NF_SET
++ fi
+ dep_tristate ' MAC address match support' CONFIG_IP_NF_MATCH_MAC $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' Packet type match support' CONFIG_IP_NF_MATCH_PKTTYPE $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' netfilter MARK match support' CONFIG_IP_NF_MATCH_MARK $CONFIG_IP_NF_IPTABLES
+diff -Naur linux-old/net/ipv4/netfilter/ip_set.c linux-new/net/ipv4/netfilter/ip_set.c
+--- linux-old/net/ipv4/netfilter/ip_set.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/net/ipv4/netfilter/ip_set.c 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,2002 @@
++/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
++ * Patrick Schaaf <bof@bof.de>
++ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* Kernel module for IP set management */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kmod.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++#include <linux/random.h>
++#include <linux/jhash.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <asm/softirq.h>
++#include <asm/semaphore.h>
++#include <linux/spinlock.h>
++#include <linux/vmalloc.h>
++
++#define ASSERT_READ_LOCK(x) /* dont use that */
++#define ASSERT_WRITE_LOCK(x)
++#include <linux/netfilter_ipv4/listhelp.h>
++#include <linux/netfilter_ipv4/ip_set.h>
++
++static struct list_head set_type_list; /* all registered sets */
++static struct ip_set **ip_set_list; /* all individual sets */
++static DECLARE_RWLOCK(ip_set_lock); /* protects the lists and the hash */
++static DECLARE_MUTEX(ip_set_app_mutex); /* serializes user access */
++static ip_set_id_t ip_set_max = CONFIG_IP_NF_SET_MAX;
++static ip_set_id_t ip_set_bindings_hash_size = CONFIG_IP_NF_SET_HASHSIZE;
++static struct list_head *ip_set_hash; /* hash of bindings */
++static unsigned int ip_set_hash_random; /* random seed */
++
++/* Arrgh */
++#ifdef MODULE
++#define __MOD_INC(foo) __MOD_INC_USE_COUNT(foo)
++#define __MOD_DEC(foo) __MOD_DEC_USE_COUNT(foo)
++#define __MOD_INC_SELF MOD_INC_USE_COUNT
++#define __MOD_DEC_SELF MOD_DEC_USE_COUNT
++#else
++#define __MOD_INC(foo)
++#define __MOD_DEC(foo)
++#define __MOD_INC_SELF
++#define __MOD_DEC_SELF
++#endif
++
++/*
++ * Sets are identified either by the index in ip_set_list or by id.
++ * The id never changes and is used to find a key in the hash.
++ * The index may change by swapping and used at all other places
++ * (set/SET netfilter modules, binding value, etc.)
++ *
++ * Userspace requests are serialized by ip_set_mutex and sets can
++ * be deleted only from userspace. Therefore ip_set_list locking
++ * must obey the following rules:
++ *
++ * - kernel requests: read and write locking mandatory
++ * - user requests: read locking optional, write locking mandatory
++ */
++
++static inline void
++__ip_set_get(ip_set_id_t index)
++{
++ atomic_inc(&ip_set_list[index]->ref);
++}
++
++static inline void
++__ip_set_put(ip_set_id_t index)
++{
++ atomic_dec(&ip_set_list[index]->ref);
++}
++
++/*
++ * Binding routines
++ */
++
++static inline int
++ip_hash_cmp(const struct ip_set_hash *set_hash,
++ ip_set_id_t id, ip_set_ip_t ip)
++{
++ return set_hash->id == id && set_hash->ip == ip;
++}
++
++static ip_set_id_t
++ip_set_find_in_hash(ip_set_id_t id, ip_set_ip_t ip)
++{
++ u_int32_t key = jhash_2words(id, ip, ip_set_hash_random)
++ % ip_set_bindings_hash_size;
++ struct ip_set_hash *set_hash;
++
++ MUST_BE_READ_LOCKED(&ip_set_lock);
++ IP_SET_ASSERT(ip_set_list[id]);
++ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));
++
++ set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
++ struct ip_set_hash *, id, ip);
++
++ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
++ HIPQUAD(ip),
++ set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");
++
++ return (set_hash != NULL ? set_hash->binding : IP_SET_INVALID_ID);
++}
++
++static inline void
++__set_hash_del(struct ip_set_hash *set_hash)
++{
++ MUST_BE_WRITE_LOCKED(&ip_set_lock);
++ IP_SET_ASSERT(ip_set_list[set_hash->binding]);
++
++ __ip_set_put(set_hash->binding);
++ list_del(&set_hash->list);
++ kfree(set_hash);
++}
++
++static int
++ip_set_hash_del(ip_set_id_t id, ip_set_ip_t ip)
++{
++ u_int32_t key = jhash_2words(id, ip, ip_set_hash_random)
++ % ip_set_bindings_hash_size;
++ struct ip_set_hash *set_hash;
++
++ IP_SET_ASSERT(ip_set_list[id]);
++ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));
++ WRITE_LOCK(&ip_set_lock);
++ set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
++ struct ip_set_hash *, id, ip);
++ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
++ HIPQUAD(ip),
++ set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");
++
++ if (set_hash != NULL)
++ __set_hash_del(set_hash);
++ WRITE_UNLOCK(&ip_set_lock);
++ return 0;
++}
++
++static int
++ip_set_hash_add(ip_set_id_t id, ip_set_ip_t ip, ip_set_id_t binding)
++{
++ u_int32_t key = jhash_2words(id, ip, ip_set_hash_random)
++ % ip_set_bindings_hash_size;
++ struct ip_set_hash *set_hash;
++ int ret = 0;
++
++ IP_SET_ASSERT(ip_set_list[id]);
++ IP_SET_ASSERT(ip_set_list[binding]);
++ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
++ HIPQUAD(ip), ip_set_list[binding]->name);
++ WRITE_LOCK(&ip_set_lock);
++ set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
++ struct ip_set_hash *, id, ip);
++ if (!set_hash) {
++ set_hash = kmalloc(sizeof(struct ip_set_hash), GFP_KERNEL);
++ if (!set_hash) {
++ ret = -ENOMEM;
++ goto unlock;
++ }
++ INIT_LIST_HEAD(&set_hash->list);
++ set_hash->id = id;
++ set_hash->ip = ip;
++ list_add(&ip_set_hash[key], &set_hash->list);
++ } else {
++ IP_SET_ASSERT(ip_set_list[set_hash->binding]);
++ DP("overwrite binding: %s",
++ ip_set_list[set_hash->binding]->name);
++ __ip_set_put(set_hash->binding);
++ }
++ set_hash->binding = binding;
++ __ip_set_get(set_hash->binding);
++ unlock:
++ WRITE_UNLOCK(&ip_set_lock);
++ return ret;
++}
++
++#define FOREACH_HASH_DO(fn, args...) \
++({ \
++ ip_set_id_t __key; \
++ struct ip_set_hash *__set_hash; \
++ \
++ for (__key = 0; __key < ip_set_bindings_hash_size; __key++) { \
++ list_for_each_entry(__set_hash, &ip_set_hash[__key], list) \
++ fn(__set_hash , ## args); \
++ } \
++})
++
++#define FOREACH_HASH_RW_DO(fn, args...) \
++({ \
++ ip_set_id_t __key; \
++ struct ip_set_hash *__set_hash, *__n; \
++ \
++ MUST_BE_WRITE_LOCKED(&ip_set_lock); \
++ for (__key = 0; __key < ip_set_bindings_hash_size; __key++) { \
++ list_for_each_entry_safe(__set_hash, __n, &ip_set_hash[__key], list)\
++ fn(__set_hash , ## args); \
++ } \
++})
++
++/* Add, del and test set entries from kernel */
++
++#define follow_bindings(index, set, ip) \
++((index = ip_set_find_in_hash((set)->id, ip)) != IP_SET_INVALID_ID \
++ || (index = (set)->binding) != IP_SET_INVALID_ID)
++
++int
++ip_set_testip_kernel(ip_set_id_t index,
++ const struct sk_buff *skb,
++ const u_int32_t *flags)
++{
++ struct ip_set *set;
++ ip_set_ip_t ip;
++ int res, i = 0;
++
++ IP_SET_ASSERT(flags[i]);
++ READ_LOCK(&ip_set_lock);
++ do {
++ set = ip_set_list[index];
++ IP_SET_ASSERT(set);
++ DP("set %s, index %u", set->name, index);
++ read_lock_bh(&set->lock);
++ res = set->type->testip_kernel(set, skb, flags[i], &ip);
++ read_unlock_bh(&set->lock);
++ } while (res > 0
++ && flags[++i]
++ && follow_bindings(index, set, ip));
++ READ_UNLOCK(&ip_set_lock);
++
++ return res;
++}
++
++void
++ip_set_addip_kernel(ip_set_id_t index,
++ const struct sk_buff *skb,
++ const u_int32_t *flags)
++{
++ struct ip_set *set;
++ ip_set_ip_t ip;
++ int res, i= 0;
++
++ IP_SET_ASSERT(flags[i]);
++ retry:
++ READ_LOCK(&ip_set_lock);
++ do {
++ set = ip_set_list[index];
++ IP_SET_ASSERT(set);
++ DP("set %s, index %u", set->name, index);
++ write_lock_bh(&set->lock);
++ res = set->type->addip_kernel(set, skb, flags[i], &ip);
++ write_unlock_bh(&set->lock);
++ } while ((res == 0 || res == -EEXIST)
++ && flags[++i]
++ && follow_bindings(index, set, ip));
++ READ_UNLOCK(&ip_set_lock);
++
++ if (res == -EAGAIN
++ && set->type->retry
++ && (res = set->type->retry(set)) == 0)
++ goto retry;
++}
++
++void
++ip_set_delip_kernel(ip_set_id_t index,
++ const struct sk_buff *skb,
++ const u_int32_t *flags)
++{
++ struct ip_set *set;
++ ip_set_ip_t ip;
++ int res, i = 0;
++
++ IP_SET_ASSERT(flags[i]);
++ READ_LOCK(&ip_set_lock);
++ do {
++ set = ip_set_list[index];
++ IP_SET_ASSERT(set);
++ DP("set %s, index %u", set->name, index);
++ write_lock_bh(&set->lock);
++ res = set->type->delip_kernel(set, skb, flags[i], &ip);
++ write_unlock_bh(&set->lock);
++ } while ((res == 0 || res == -EEXIST)
++ && flags[++i]
++ && follow_bindings(index, set, ip));
++ READ_UNLOCK(&ip_set_lock);
++}
++
++/* Register and deregister settype */
++
++static inline int
++set_type_equal(const struct ip_set_type *set_type, const char *str2)
++{
++ return !strncmp(set_type->typename, str2, IP_SET_MAXNAMELEN - 1);
++}
++
++static inline struct ip_set_type *
++find_set_type(const char *name)
++{
++ return LIST_FIND(&set_type_list,
++ set_type_equal,
++ struct ip_set_type *,
++ name);
++}
++
++int
++ip_set_register_set_type(struct ip_set_type *set_type)
++{
++ int ret = 0;
++
++ if (set_type->protocol_version != IP_SET_PROTOCOL_VERSION) {
++ ip_set_printk("'%s' uses wrong protocol version %u (want %u)",
++ set_type->typename,
++ set_type->protocol_version,
++ IP_SET_PROTOCOL_VERSION);
++ return -EINVAL;
++ }
++
++ WRITE_LOCK(&ip_set_lock);
++ if (find_set_type(set_type->typename)) {
++ /* Duplicate! */
++ ip_set_printk("'%s' already registered!",
++ set_type->typename);
++ ret = -EINVAL;
++ goto unlock;
++ }
++ __MOD_INC_SELF;
++ list_append(&set_type_list, set_type);
++ DP("'%s' registered.", set_type->typename);
++ unlock:
++ WRITE_UNLOCK(&ip_set_lock);
++ return ret;
++}
++
++void
++ip_set_unregister_set_type(struct ip_set_type *set_type)
++{
++ WRITE_LOCK(&ip_set_lock);
++ if (!find_set_type(set_type->typename)) {
++ ip_set_printk("'%s' not registered?",
++ set_type->typename);
++ goto unlock;
++ }
++ LIST_DELETE(&set_type_list, set_type);
++ __MOD_DEC_SELF;
++ DP("'%s' unregistered.", set_type->typename);
++ unlock:
++ WRITE_UNLOCK(&ip_set_lock);
++
++}
++
++/*
++ * Userspace routines
++ */
++
++/*
++ * Find set by name, reference it once. The reference makes sure the
++ * thing pointed to, does not go away under our feet. Drop the reference
++ * later, using ip_set_put().
++ */
++ip_set_id_t
++ip_set_get_byname(const char *name)
++{
++ ip_set_id_t i, index = IP_SET_INVALID_ID;
++
++ down(&ip_set_app_mutex);
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] != NULL
++ && strcmp(ip_set_list[i]->name, name) == 0) {
++ __ip_set_get(i);
++ index = i;
++ break;
++ }
++ }
++ up(&ip_set_app_mutex);
++ return index;
++}
++
++/*
++ * Find set by index, reference it once. The reference makes sure the
++ * thing pointed to, does not go away under our feet. Drop the reference
++ * later, using ip_set_put().
++ */
++ip_set_id_t
++ip_set_get_byindex(ip_set_id_t index)
++{
++ down(&ip_set_app_mutex);
++
++ if (index >= ip_set_max)
++ return IP_SET_INVALID_ID;
++
++ if (ip_set_list[index])
++ __ip_set_get(index);
++ else
++ index = IP_SET_INVALID_ID;
++
++ up(&ip_set_app_mutex);
++ return index;
++}
++
++/*
++ * If the given set pointer points to a valid set, decrement
++ * reference count by 1. The caller shall not assume the index
++ * to be valid, after calling this function.
++ */
++void ip_set_put(ip_set_id_t index)
++{
++ down(&ip_set_app_mutex);
++ if (ip_set_list[index])
++ __ip_set_put(index);
++ up(&ip_set_app_mutex);
++}
++
++/* Find a set by name or index */
++static ip_set_id_t
++ip_set_find_byname(const char *name)
++{
++ ip_set_id_t i, index = IP_SET_INVALID_ID;
++
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] != NULL
++ && strcmp(ip_set_list[i]->name, name) == 0) {
++ index = i;
++ break;
++ }
++ }
++ return index;
++}
++
++static ip_set_id_t
++ip_set_find_byindex(ip_set_id_t index)
++{
++ if (index >= ip_set_max || ip_set_list[index] == NULL)
++ index = IP_SET_INVALID_ID;
++
++ return index;
++}
++
++/*
++ * Add, del, test, bind and unbind
++ */
++
++static inline int
++__ip_set_testip(struct ip_set *set,
++ const void *data,
++ size_t size,
++ ip_set_ip_t *ip)
++{
++ int res;
++
++ read_lock_bh(&set->lock);
++ res = set->type->testip(set, data, size, ip);
++ read_unlock_bh(&set->lock);
++
++ return res;
++}
++
++static int
++__ip_set_addip(ip_set_id_t index,
++ const void *data,
++ size_t size)
++{
++ struct ip_set *set = ip_set_list[index];
++ ip_set_ip_t ip;
++ int res;
++
++ IP_SET_ASSERT(set);
++ do {
++ write_lock_bh(&set->lock);
++ res = set->type->addip(set, data, size, &ip);
++ write_unlock_bh(&set->lock);
++ } while (res == -EAGAIN
++ && set->type->retry
++ && (res = set->type->retry(set)) == 0);
++
++ return res;
++}
++
++static int
++ip_set_addip(ip_set_id_t index,
++ const void *data,
++ size_t size)
++{
++
++ return __ip_set_addip(index,
++ data + sizeof(struct ip_set_req_adt),
++ size - sizeof(struct ip_set_req_adt));
++}
++
++static int
++ip_set_delip(ip_set_id_t index,
++ const void *data,
++ size_t size)
++{
++ struct ip_set *set = ip_set_list[index];
++ ip_set_ip_t ip;
++ int res;
++
++ IP_SET_ASSERT(set);
++ write_lock_bh(&set->lock);
++ res = set->type->delip(set,
++ data + sizeof(struct ip_set_req_adt),
++ size - sizeof(struct ip_set_req_adt),
++ &ip);
++ write_unlock_bh(&set->lock);
++
++ return res;
++}
++
++static int
++ip_set_testip(ip_set_id_t index,
++ const void *data,
++ size_t size)
++{
++ struct ip_set *set = ip_set_list[index];
++ ip_set_ip_t ip;
++ int res;
++
++ IP_SET_ASSERT(set);
++ res = __ip_set_testip(set,
++ data + sizeof(struct ip_set_req_adt),
++ size - sizeof(struct ip_set_req_adt),
++ &ip);
++
++ return (res > 0 ? -EEXIST : res);
++}
++
++static int
++ip_set_bindip(ip_set_id_t index,
++ const void *data,
++ size_t size)
++{
++ struct ip_set *set = ip_set_list[index];
++ struct ip_set_req_bind *req_bind;
++ ip_set_id_t binding;
++ ip_set_ip_t ip;
++ int res;
++
++ IP_SET_ASSERT(set);
++ if (size < sizeof(struct ip_set_req_bind))
++ return -EINVAL;
++
++ req_bind = (struct ip_set_req_bind *) data;
++ req_bind->binding[IP_SET_MAXNAMELEN - 1] = '\0';
++
++ if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {
++ /* Default binding of a set */
++ char *binding_name;
++
++ if (size != sizeof(struct ip_set_req_bind) + IP_SET_MAXNAMELEN)
++ return -EINVAL;
++
++ binding_name = (char *)(data + sizeof(struct ip_set_req_bind));
++ binding_name[IP_SET_MAXNAMELEN - 1] = '\0';
++
++ binding = ip_set_find_byname(binding_name);
++ if (binding == IP_SET_INVALID_ID)
++ return -ENOENT;
++
++ WRITE_LOCK(&ip_set_lock);
++ /* Sets as binding values are referenced */
++ if (set->binding != IP_SET_INVALID_ID)
++ __ip_set_put(set->binding);
++ set->binding = binding;
++ __ip_set_get(set->binding);
++ WRITE_UNLOCK(&ip_set_lock);
++
++ return 0;
++ }
++ binding = ip_set_find_byname(req_bind->binding);
++ if (binding == IP_SET_INVALID_ID)
++ return -ENOENT;
++
++ res = __ip_set_testip(set,
++ data + sizeof(struct ip_set_req_bind),
++ size - sizeof(struct ip_set_req_bind),
++ &ip);
++ DP("set %s, ip: %u.%u.%u.%u, binding %s",
++ set->name, HIPQUAD(ip), ip_set_list[binding]->name);
++
++ if (res >= 0)
++ res = ip_set_hash_add(set->id, ip, binding);
++
++ return res;
++}
++
++#define FOREACH_SET_DO(fn, args...) \
++({ \
++ ip_set_id_t __i; \
++ struct ip_set *__set; \
++ \
++ for (__i = 0; __i < ip_set_max; __i++) { \
++ __set = ip_set_list[__i]; \
++ if (__set != NULL) \
++ fn(__set , ##args); \
++ } \
++})
++
++static inline void
++__set_hash_del_byid(struct ip_set_hash *set_hash, ip_set_id_t id)
++{
++ if (set_hash->id == id)
++ __set_hash_del(set_hash);
++}
++
++static inline void
++__unbind_default(struct ip_set *set)
++{
++ if (set->binding != IP_SET_INVALID_ID) {
++ /* Sets as binding values are referenced */
++ __ip_set_put(set->binding);
++ set->binding = IP_SET_INVALID_ID;
++ }
++}
++
++static int
++ip_set_unbindip(ip_set_id_t index,
++ const void *data,
++ size_t size)
++{
++ struct ip_set *set;
++ struct ip_set_req_bind *req_bind;
++ ip_set_ip_t ip;
++ int res;
++
++ DP("");
++ if (size < sizeof(struct ip_set_req_bind))
++ return -EINVAL;
++
++ req_bind = (struct ip_set_req_bind *) data;
++ req_bind->binding[IP_SET_MAXNAMELEN - 1] = '\0';
++
++ DP("%u %s", index, req_bind->binding);
++ if (index == IP_SET_INVALID_ID) {
++ /* unbind :all: */
++ if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {
++ /* Default binding of sets */
++ WRITE_LOCK(&ip_set_lock);
++ FOREACH_SET_DO(__unbind_default);
++ WRITE_UNLOCK(&ip_set_lock);
++ return 0;
++ } else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {
++ /* Flush all bindings of all sets*/
++ WRITE_LOCK(&ip_set_lock);
++ FOREACH_HASH_RW_DO(__set_hash_del);
++ WRITE_UNLOCK(&ip_set_lock);
++ return 0;
++ }
++ DP("unreachable reached!");
++ return -EINVAL;
++ }
++
++ set = ip_set_list[index];
++ IP_SET_ASSERT(set);
++ if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {
++ /* Default binding of set */
++ ip_set_id_t binding = ip_set_find_byindex(set->binding);
++
++ if (binding == IP_SET_INVALID_ID)
++ return -ENOENT;
++
++ WRITE_LOCK(&ip_set_lock);
++ /* Sets in hash values are referenced */
++ __ip_set_put(set->binding);
++ set->binding = IP_SET_INVALID_ID;
++ WRITE_UNLOCK(&ip_set_lock);
++
++ return 0;
++ } else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {
++ /* Flush all bindings */
++
++ WRITE_LOCK(&ip_set_lock);
++ FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id);
++ WRITE_UNLOCK(&ip_set_lock);
++ return 0;
++ }
++
++ res = __ip_set_testip(set,
++ data + sizeof(struct ip_set_req_bind),
++ size - sizeof(struct ip_set_req_bind),
++ &ip);
++
++ DP("set %s, ip: %u.%u.%u.%u", set->name, HIPQUAD(ip));
++ if (res >= 0)
++ res = ip_set_hash_del(set->id, ip);
++
++ return res;
++}
++
++static int
++ip_set_testbind(ip_set_id_t index,
++ const void *data,
++ size_t size)
++{
++ struct ip_set *set = ip_set_list[index];
++ struct ip_set_req_bind *req_bind;
++ ip_set_id_t binding;
++ ip_set_ip_t ip;
++ int res;
++
++ IP_SET_ASSERT(set);
++ if (size < sizeof(struct ip_set_req_bind))
++ return -EINVAL;
++
++ req_bind = (struct ip_set_req_bind *) data;
++ req_bind->binding[IP_SET_MAXNAMELEN - 1] = '\0';
++
++ if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {
++ /* Default binding of set */
++ char *binding_name;
++
++ if (size != sizeof(struct ip_set_req_bind) + IP_SET_MAXNAMELEN)
++ return -EINVAL;
++
++ binding_name = (char *)(data + sizeof(struct ip_set_req_bind));
++ binding_name[IP_SET_MAXNAMELEN - 1] = '\0';
++
++ binding = ip_set_find_byname(binding_name);
++ if (binding == IP_SET_INVALID_ID)
++ return -ENOENT;
++
++ res = (set->binding == binding) ? -EEXIST : 0;
++
++ return res;
++ }
++ binding = ip_set_find_byname(req_bind->binding);
++ if (binding == IP_SET_INVALID_ID)
++ return -ENOENT;
++
++
++ res = __ip_set_testip(set,
++ data + sizeof(struct ip_set_req_bind),
++ size - sizeof(struct ip_set_req_bind),
++ &ip);
++ DP("set %s, ip: %u.%u.%u.%u, binding %s",
++ set->name, HIPQUAD(ip), ip_set_list[binding]->name);
++
++ if (res >= 0)
++ res = (ip_set_find_in_hash(set->id, ip) == binding)
++ ? -EEXIST : 0;
++
++ return res;
++}
++
++static struct ip_set_type *
++find_set_type_rlock(const char *typename)
++{
++ struct ip_set_type *type;
++
++ READ_LOCK(&ip_set_lock);
++ type = find_set_type(typename);
++ if (type == NULL)
++ READ_UNLOCK(&ip_set_lock);
++
++ return type;
++}
++
++static int
++find_free_id(const char *name,
++ ip_set_id_t *index,
++ ip_set_id_t *id)
++{
++ ip_set_id_t i;
++
++ *id = IP_SET_INVALID_ID;
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] == NULL) {
++ if (*id == IP_SET_INVALID_ID)
++ *id = *index = i;
++ } else if (strcmp(name, ip_set_list[i]->name) == 0)
++ /* Name clash */
++ return -EEXIST;
++ }
++ if (*id == IP_SET_INVALID_ID)
++ /* No free slot remained */
++ return -ERANGE;
++ /* Check that index is usable as id (swapping) */
++ check:
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] != NULL
++ && ip_set_list[i]->id == *id) {
++ *id = i;
++ goto check;
++ }
++ }
++ return 0;
++}
++
++/*
++ * Create a set
++ */
++static int
++ip_set_create(const char *name,
++ const char *typename,
++ ip_set_id_t restore,
++ const void *data,
++ size_t size)
++{
++ struct ip_set *set;
++ ip_set_id_t index, id;
++ int res = 0;
++
++ DP("setname: %s, typename: %s, id: %u", name, typename, restore);
++ /*
++ * First, and without any locks, allocate and initialize
++ * a normal base set structure.
++ */
++ set = kmalloc(sizeof(struct ip_set), GFP_KERNEL);
++ if (!set)
++ return -ENOMEM;
++ set->lock = RW_LOCK_UNLOCKED;
++ strncpy(set->name, name, IP_SET_MAXNAMELEN);
++ set->binding = IP_SET_INVALID_ID;
++ atomic_set(&set->ref, 0);
++
++ /*
++ * Next, take the &ip_set_lock, check that we know the type,
++ * and take a reference on the type, to make sure it
++ * stays available while constructing our new set.
++ *
++ * After referencing the type, we drop the &ip_set_lock,
++ * and let the new set construction run without locks.
++ */
++ set->type = find_set_type_rlock(typename);
++ if (set->type == NULL) {
++ /* Try loading the module */
++ char modulename[IP_SET_MAXNAMELEN + strlen("ip_set_") + 1];
++ strcpy(modulename, "ip_set_");
++ strcat(modulename, typename);
++ DP("try to load %s", modulename);
++ request_module(modulename);
++ set->type = find_set_type_rlock(typename);
++ }
++ if (set->type == NULL) {
++ ip_set_printk("no set type '%s', set '%s' not created",
++ typename, name);
++ kfree(set);
++ return -ENOENT;
++ }
++ __MOD_INC(set->type->me);
++ READ_UNLOCK(&ip_set_lock);
++
++ /*
++ * Without holding any locks, create private part.
++ */
++ res = set->type->create(set, data, size);
++ if (res != 0) {
++ __MOD_DEC(set->type->me);
++ kfree(set);
++ return res;
++ }
++
++ /* BTW, res==0 here. */
++
++ /*
++ * Here, we have a valid, constructed set. &ip_set_lock again,
++ * find free id/index and check that it is not already in
++ * ip_set_list.
++ */
++ WRITE_LOCK(&ip_set_lock);
++ if ((res = find_free_id(set->name, &index, &id)) != 0) {
++ DP("no free id!");
++ goto cleanup;
++ }
++
++ /* Make sure restore gets the same index */
++ if (restore != IP_SET_INVALID_ID && index != restore) {
++ DP("Can't restore, sets are screwed up");
++ res = -ERANGE;
++ goto cleanup;
++ }
++
++ /*
++ * Finally! Add our shiny new set to the list, and be done.
++ */
++ DP("create: '%s' created with index %u, id %u!", set->name, index, id);
++ set->id = id;
++ ip_set_list[index] = set;
++ WRITE_UNLOCK(&ip_set_lock);
++ return res;
++
++ cleanup:
++ WRITE_UNLOCK(&ip_set_lock);
++ set->type->destroy(set);
++ __MOD_DEC(set->type->me);
++ kfree(set);
++ return res;
++}
++
++/*
++ * Destroy a given existing set
++ */
++static void
++ip_set_destroy_set(ip_set_id_t index)
++{
++ struct ip_set *set = ip_set_list[index];
++
++ IP_SET_ASSERT(set);
++ DP("set: %s", set->name);
++ WRITE_LOCK(&ip_set_lock);
++ FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id);
++ if (set->binding != IP_SET_INVALID_ID)
++ __ip_set_put(set->binding);
++ ip_set_list[index] = NULL;
++ WRITE_UNLOCK(&ip_set_lock);
++
++ /* Must call it without holding any lock */
++ set->type->destroy(set);
++ __MOD_DEC(set->type->me);
++ kfree(set);
++}
++
++/*
++ * Destroy a set - or all sets
++ * Sets must not be referenced/used.
++ */
++static int
++ip_set_destroy(ip_set_id_t index)
++{
++ ip_set_id_t i;
++
++ /* ref modification always protected by the mutex */
++ if (index != IP_SET_INVALID_ID) {
++ if (atomic_read(&ip_set_list[index]->ref))
++ return -EBUSY;
++ ip_set_destroy_set(index);
++ } else {
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] != NULL
++ && (atomic_read(&ip_set_list[i]->ref)))
++ return -EBUSY;
++ }
++
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] != NULL)
++ ip_set_destroy_set(i);
++ }
++ }
++ return 0;
++}
++
++static void
++ip_set_flush_set(struct ip_set *set)
++{
++ DP("set: %s %u", set->name, set->id);
++
++ write_lock_bh(&set->lock);
++ set->type->flush(set);
++ write_unlock_bh(&set->lock);
++}
++
++/*
++ * Flush data in a set - or in all sets
++ */
++static int
++ip_set_flush(ip_set_id_t index)
++{
++ if (index != IP_SET_INVALID_ID) {
++ IP_SET_ASSERT(ip_set_list[index]);
++ ip_set_flush_set(ip_set_list[index]);
++ } else
++ FOREACH_SET_DO(ip_set_flush_set);
++
++ return 0;
++}
++
++/* Rename a set */
++static int
++ip_set_rename(ip_set_id_t index, const char *name)
++{
++ struct ip_set *set = ip_set_list[index];
++ ip_set_id_t i;
++ int res = 0;
++
++ DP("set: %s to %s", set->name, name);
++ WRITE_LOCK(&ip_set_lock);
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] != NULL
++ && strncmp(ip_set_list[i]->name,
++ name,
++ IP_SET_MAXNAMELEN - 1) == 0) {
++ res = -EEXIST;
++ goto unlock;
++ }
++ }
++ strncpy(set->name, name, IP_SET_MAXNAMELEN);
++ unlock:
++ WRITE_UNLOCK(&ip_set_lock);
++ return res;
++}
++
++/*
++ * Swap two sets so that name/index points to the other.
++ * References are also swapped.
++ */
++static int
++ip_set_swap(ip_set_id_t from_index, ip_set_id_t to_index)
++{
++ struct ip_set *from = ip_set_list[from_index];
++ struct ip_set *to = ip_set_list[to_index];
++ char from_name[IP_SET_MAXNAMELEN];
++ u_int32_t from_ref;
++
++ DP("set: %s to %s", from->name, to->name);
++ /* Type can't be changed. Artifical restriction. */
++ if (from->type->typecode != to->type->typecode)
++ return -ENOEXEC;
++
++ /* No magic here: ref munging protected by the mutex */
++ WRITE_LOCK(&ip_set_lock);
++ strncpy(from_name, from->name, IP_SET_MAXNAMELEN);
++ from_ref = atomic_read(&from->ref);
++
++ strncpy(from->name, to->name, IP_SET_MAXNAMELEN);
++ atomic_set(&from->ref, atomic_read(&to->ref));
++ strncpy(to->name, from_name, IP_SET_MAXNAMELEN);
++ atomic_set(&to->ref, from_ref);
++
++ ip_set_list[from_index] = to;
++ ip_set_list[to_index] = from;
++
++ WRITE_UNLOCK(&ip_set_lock);
++ return 0;
++}
++
++/*
++ * List set data
++ */
++
++static inline void
++__set_hash_bindings_size_list(struct ip_set_hash *set_hash,
++ ip_set_id_t id, size_t *size)
++{
++ if (set_hash->id == id)
++ *size += sizeof(struct ip_set_hash_list);
++}
++
++static inline void
++__set_hash_bindings_size_save(struct ip_set_hash *set_hash,
++ ip_set_id_t id, size_t *size)
++{
++ if (set_hash->id == id)
++ *size += sizeof(struct ip_set_hash_save);
++}
++
++static inline void
++__set_hash_bindings(struct ip_set_hash *set_hash,
++ ip_set_id_t id, void *data, int *used)
++{
++ if (set_hash->id == id) {
++ struct ip_set_hash_list *hash_list =
++ (struct ip_set_hash_list *)(data + *used);
++
++ hash_list->ip = set_hash->ip;
++ hash_list->binding = set_hash->binding;
++ *used += sizeof(struct ip_set_hash_list);
++ }
++}
++
++static int ip_set_list_set(ip_set_id_t index,
++ void *data,
++ int *used,
++ int len)
++{
++ struct ip_set *set = ip_set_list[index];
++ struct ip_set_list *set_list;
++
++ /* Pointer to our header */
++ set_list = (struct ip_set_list *) (data + *used);
++
++ DP("set: %s, used: %d %p %p", set->name, *used, data, data + *used);
++
++ /* Get and ensure header size */
++ if (*used + sizeof(struct ip_set_list) > len)
++ goto not_enough_mem;
++ *used += sizeof(struct ip_set_list);
++
++ read_lock_bh(&set->lock);
++ /* Get and ensure set specific header size */
++ set_list->header_size = set->type->header_size;
++ if (*used + set_list->header_size > len)
++ goto unlock_set;
++
++ /* Fill in the header */
++ set_list->index = index;
++ set_list->binding = set->binding;
++ set_list->ref = atomic_read(&set->ref);
++
++ /* Fill in set spefific header data */
++ DP("call list_header");
++ set->type->list_header(set, data + *used);
++ DP("call list_header, done");
++ *used += set_list->header_size;
++
++ /* Get and ensure set specific members size */
++ DP("call list_members_size");
++ set_list->members_size = set->type->list_members_size(set);
++ DP("call list_members_size, done");
++ if (*used + set_list->members_size > len)
++ goto unlock_set;
++
++ /* Fill in set spefific members data */
++ DP("call list_members");
++ set->type->list_members(set, data + *used);
++ DP("call list_members, done");
++ *used += set_list->members_size;
++ read_unlock_bh(&set->lock);
++
++ /* Bindings */
++
++ /* Get and ensure set specific bindings size */
++ set_list->bindings_size = 0;
++ FOREACH_HASH_DO(__set_hash_bindings_size_list,
++ set->id, &set_list->bindings_size);
++ if (*used + set_list->bindings_size > len)
++ goto not_enough_mem;
++
++ /* Fill in set spefific bindings data */
++ FOREACH_HASH_DO(__set_hash_bindings, set->id, data, used);
++
++ return 0;
++
++ unlock_set:
++ read_unlock_bh(&set->lock);
++ not_enough_mem:
++ DP("not enough mem, try again");
++ return -EAGAIN;
++}
++
++/*
++ * Save sets
++ */
++static int ip_set_save_set(ip_set_id_t index,
++ void *data,
++ int *used,
++ int len)
++{
++ struct ip_set *set;
++ struct ip_set_save *set_save;
++
++ /* Pointer to our header */
++ set_save = (struct ip_set_save *) (data + *used);
++
++ /* Get and ensure header size */
++ if (*used + sizeof(struct ip_set_save) > len)
++ goto not_enough_mem;
++ *used += sizeof(struct ip_set_save);
++
++ set = ip_set_list[index];
++ DP("set: %s, used: %u(%u) %p %p", set->name, *used, len,
++ data, data + *used);
++
++ read_lock_bh(&set->lock);
++ /* Get and ensure set specific header size */
++ set_save->header_size = set->type->header_size;
++ if (*used + set_save->header_size > len)
++ goto unlock_set;
++
++ /* Fill in the header */
++ set_save->index = index;
++ set_save->binding = set->binding;
++
++ /* Fill in set spefific header data */
++ set->type->list_header(set, data + *used);
++ *used += set_save->header_size;
++
++ DP("set header filled: %s, used: %u %p %p", set->name, *used,
++ data, data + *used);
++ /* Get and ensure set specific members size */
++ set_save->members_size = set->type->list_members_size(set);
++ if (*used + set_save->members_size > len)
++ goto unlock_set;
++
++ /* Fill in set spefific members data */
++ set->type->list_members(set, data + *used);
++ *used += set_save->members_size;
++ read_unlock_bh(&set->lock);
++ DP("set members filled: %s, used: %u %p %p", set->name, *used,
++ data, data + *used);
++ return 0;
++
++ unlock_set:
++ read_unlock_bh(&set->lock);
++ not_enough_mem:
++ DP("not enough mem, try again");
++ return -EAGAIN;
++}
++
++static inline void
++__set_hash_save_bindings(struct ip_set_hash *set_hash,
++ ip_set_id_t id,
++ void *data,
++ int *used,
++ int len,
++ int *res)
++{
++ if (*res == 0
++ && (id == IP_SET_INVALID_ID || set_hash->id == id)) {
++ struct ip_set_hash_save *hash_save =
++ (struct ip_set_hash_save *)(data + *used);
++ /* Ensure bindings size */
++ if (*used + sizeof(struct ip_set_hash_save) > len) {
++ *res = -ENOMEM;
++ return;
++ }
++ hash_save->id = set_hash->id;
++ hash_save->ip = set_hash->ip;
++ hash_save->binding = set_hash->binding;
++ *used += sizeof(struct ip_set_hash_save);
++ }
++}
++
++static int ip_set_save_bindings(ip_set_id_t index,
++ void *data,
++ int *used,
++ int len)
++{
++ int res = 0;
++ struct ip_set_save *set_save;
++
++ DP("used %u, len %u", *used, len);
++ /* Get and ensure header size */
++ if (*used + sizeof(struct ip_set_save) > len)
++ return -ENOMEM;
++
++ /* Marker */
++ set_save = (struct ip_set_save *) (data + *used);
++ set_save->index = IP_SET_INVALID_ID;
++ *used += sizeof(struct ip_set_save);
++
++ DP("marker added used %u, len %u", *used, len);
++ /* Fill in bindings data */
++ if (index != IP_SET_INVALID_ID)
++ /* Sets are identified by id in hash */
++ index = ip_set_list[index]->id;
++ FOREACH_HASH_DO(__set_hash_save_bindings, index, data, used, len, &res);
++
++ return res;
++}
++
++/*
++ * Restore sets
++ */
++static int ip_set_restore(void *data,
++ int len)
++{
++ int res = 0;
++ int line = 0, used = 0, members_size;
++ struct ip_set *set;
++ struct ip_set_hash_save *hash_save;
++ struct ip_set_restore *set_restore;
++ ip_set_id_t index;
++
++ /* Loop to restore sets */
++ while (1) {
++ line++;
++
++ DP("%u %u %u", used, sizeof(struct ip_set_restore), len);
++ /* Get and ensure header size */
++ if (used + sizeof(struct ip_set_restore) > len)
++ return line;
++ set_restore = (struct ip_set_restore *) (data + used);
++ used += sizeof(struct ip_set_restore);
++
++ /* Ensure data size */
++ if (used
++ + set_restore->header_size
++ + set_restore->members_size > len)
++ return line;
++
++ /* Check marker */
++ if (set_restore->index == IP_SET_INVALID_ID) {
++ line--;
++ goto bindings;
++ }
++
++ /* Try to create the set */
++ DP("restore %s %s", set_restore->name, set_restore->typename);
++ res = ip_set_create(set_restore->name,
++ set_restore->typename,
++ set_restore->index,
++ data + used,
++ set_restore->header_size);
++
++ if (res != 0)
++ return line;
++ used += set_restore->header_size;
++
++ index = ip_set_find_byindex(set_restore->index);
++ DP("index %u, restore_index %u", index, set_restore->index);
++ if (index != set_restore->index)
++ return line;
++ /* Try to restore members data */
++ set = ip_set_list[index];
++ members_size = 0;
++ DP("members_size %u reqsize %u",
++ set_restore->members_size, set->type->reqsize);
++ while (members_size + set->type->reqsize <=
++ set_restore->members_size) {
++ line++;
++ DP("members: %u, line %u", members_size, line);
++ res = __ip_set_addip(index,
++ data + used + members_size,
++ set->type->reqsize);
++ if (!(res == 0 || res == -EEXIST))
++ return line;
++ members_size += set->type->reqsize;
++ }
++
++ DP("members_size %u %u",
++ set_restore->members_size, members_size);
++ if (members_size != set_restore->members_size)
++ return line++;
++ used += set_restore->members_size;
++ }
++
++ bindings:
++ /* Loop to restore bindings */
++ while (used < len) {
++ line++;
++
++ DP("restore binding, line %u", line);
++ /* Get and ensure size */
++ if (used + sizeof(struct ip_set_hash_save) > len)
++ return line;
++ hash_save = (struct ip_set_hash_save *) (data + used);
++ used += sizeof(struct ip_set_hash_save);
++
++ /* hash_save->id is used to store the index */
++ index = ip_set_find_byindex(hash_save->id);
++ DP("restore binding index %u, id %u, %u -> %u",
++ index, hash_save->id, hash_save->ip, hash_save->binding);
++ if (index != hash_save->id)
++ return line;
++
++ set = ip_set_list[hash_save->id];
++ /* Null valued IP means default binding */
++ if (hash_save->ip)
++ res = ip_set_hash_add(set->id,
++ hash_save->ip,
++ hash_save->binding);
++ else {
++ IP_SET_ASSERT(set->binding == IP_SET_INVALID_ID);
++ WRITE_LOCK(&ip_set_lock);
++ set->binding = hash_save->binding;
++ __ip_set_get(set->binding);
++ WRITE_UNLOCK(&ip_set_lock);
++ DP("default binding: %u", set->binding);
++ }
++ if (res != 0)
++ return line;
++ }
++ if (used != len)
++ return line;
++
++ return 0;
++}
++
++static int
++ip_set_sockfn_set(struct sock *sk, int optval, void *user, unsigned int len)
++{
++ void *data;
++ int res = 0; /* Assume OK */
++ unsigned *op;
++ struct ip_set_req_adt *req_adt;
++ ip_set_id_t index = IP_SET_INVALID_ID;
++ int (*adtfn)(ip_set_id_t index,
++ const void *data, size_t size);
++ struct fn_table {
++ int (*fn)(ip_set_id_t index,
++ const void *data, size_t size);
++ } adtfn_table[] =
++ { { ip_set_addip }, { ip_set_delip }, { ip_set_testip},
++ { ip_set_bindip}, { ip_set_unbindip }, { ip_set_testbind },
++ };
++
++ DP("optval=%d, user=%p, len=%d", optval, user, len);
++ if (!capable(CAP_NET_ADMIN))
++ return -EPERM;
++ if (optval != SO_IP_SET)
++ return -EBADF;
++ if (len <= sizeof(unsigned)) {
++ ip_set_printk("short userdata (want >%zu, got %u)",
++ sizeof(unsigned), len);
++ return -EINVAL;
++ }
++ data = vmalloc(len);
++ if (!data) {
++ DP("out of mem for %u bytes", len);
++ return -ENOMEM;
++ }
++ if (copy_from_user(data, user, len) != 0) {
++ res = -EFAULT;
++ goto done;
++ }
++ if (down_interruptible(&ip_set_app_mutex)) {
++ res = -EINTR;
++ goto done;
++ }
++
++ op = (unsigned *)data;
++ DP("op=%x", *op);
++
++ if (*op < IP_SET_OP_VERSION) {
++ /* Check the version at the beginning of operations */
++ struct ip_set_req_version *req_version =
++ (struct ip_set_req_version *) data;
++ if (req_version->version != IP_SET_PROTOCOL_VERSION) {
++ res = -EPROTO;
++ goto done;
++ }
++ }
++
++ switch (*op) {
++ case IP_SET_OP_CREATE:{
++ struct ip_set_req_create *req_create
++ = (struct ip_set_req_create *) data;
++
++ if (len <= sizeof(struct ip_set_req_create)) {
++ ip_set_printk("short CREATE data (want >%zu, got %u)",
++ sizeof(struct ip_set_req_create), len);
++ res = -EINVAL;
++ goto done;
++ }
++ req_create->name[IP_SET_MAXNAMELEN - 1] = '\0';
++ req_create->typename[IP_SET_MAXNAMELEN - 1] = '\0';
++ res = ip_set_create(req_create->name,
++ req_create->typename,
++ IP_SET_INVALID_ID,
++ data + sizeof(struct ip_set_req_create),
++ len - sizeof(struct ip_set_req_create));
++ goto done;
++ }
++ case IP_SET_OP_DESTROY:{
++ struct ip_set_req_std *req_destroy
++ = (struct ip_set_req_std *) data;
++
++ if (len != sizeof(struct ip_set_req_std)) {
++ ip_set_printk("invalid DESTROY data (want %zu, got %u)",
++ sizeof(struct ip_set_req_std), len);
++ res = -EINVAL;
++ goto done;
++ }
++ if (strcmp(req_destroy->name, IPSET_TOKEN_ALL) == 0) {
++ /* Destroy all sets */
++ index = IP_SET_INVALID_ID;
++ } else {
++ req_destroy->name[IP_SET_MAXNAMELEN - 1] = '\0';
++ index = ip_set_find_byname(req_destroy->name);
++
++ if (index == IP_SET_INVALID_ID) {
++ res = -ENOENT;
++ goto done;
++ }
++ }
++
++ res = ip_set_destroy(index);
++ goto done;
++ }
++ case IP_SET_OP_FLUSH:{
++ struct ip_set_req_std *req_flush =
++ (struct ip_set_req_std *) data;
++
++ if (len != sizeof(struct ip_set_req_std)) {
++ ip_set_printk("invalid FLUSH data (want %zu, got %u)",
++ sizeof(struct ip_set_req_std), len);
++ res = -EINVAL;
++ goto done;
++ }
++ if (strcmp(req_flush->name, IPSET_TOKEN_ALL) == 0) {
++ /* Flush all sets */
++ index = IP_SET_INVALID_ID;
++ } else {
++ req_flush->name[IP_SET_MAXNAMELEN - 1] = '\0';
++ index = ip_set_find_byname(req_flush->name);
++
++ if (index == IP_SET_INVALID_ID) {
++ res = -ENOENT;
++ goto done;
++ }
++ }
++ res = ip_set_flush(index);
++ goto done;
++ }
++ case IP_SET_OP_RENAME:{
++ struct ip_set_req_create *req_rename
++ = (struct ip_set_req_create *) data;
++
++ if (len != sizeof(struct ip_set_req_create)) {
++ ip_set_printk("invalid RENAME data (want %zu, got %u)",
++ sizeof(struct ip_set_req_create), len);
++ res = -EINVAL;
++ goto done;
++ }
++
++ req_rename->name[IP_SET_MAXNAMELEN - 1] = '\0';
++ req_rename->typename[IP_SET_MAXNAMELEN - 1] = '\0';
++
++ index = ip_set_find_byname(req_rename->name);
++ if (index == IP_SET_INVALID_ID) {
++ res = -ENOENT;
++ goto done;
++ }
++ res = ip_set_rename(index, req_rename->typename);
++ goto done;
++ }
++ case IP_SET_OP_SWAP:{
++ struct ip_set_req_create *req_swap
++ = (struct ip_set_req_create *) data;
++ ip_set_id_t to_index;
++
++ if (len != sizeof(struct ip_set_req_create)) {
++ ip_set_printk("invalid SWAP data (want %zu, got %u)",
++ sizeof(struct ip_set_req_create), len);
++ res = -EINVAL;
++ goto done;
++ }
++
++ req_swap->name[IP_SET_MAXNAMELEN - 1] = '\0';
++ req_swap->typename[IP_SET_MAXNAMELEN - 1] = '\0';
++
++ index = ip_set_find_byname(req_swap->name);
++ if (index == IP_SET_INVALID_ID) {
++ res = -ENOENT;
++ goto done;
++ }
++ to_index = ip_set_find_byname(req_swap->typename);
++ if (to_index == IP_SET_INVALID_ID) {
++ res = -ENOENT;
++ goto done;
++ }
++ res = ip_set_swap(index, to_index);
++ goto done;
++ }
++ default:
++ break; /* Set identified by id */
++ }
++
++ /* There we may have add/del/test/bind/unbind/test_bind operations */
++ if (*op < IP_SET_OP_ADD_IP || *op > IP_SET_OP_TEST_BIND_SET) {
++ res = -EBADMSG;
++ goto done;
++ }
++ adtfn = adtfn_table[*op - IP_SET_OP_ADD_IP].fn;
++
++ if (len < sizeof(struct ip_set_req_adt)) {
++ ip_set_printk("short data in adt request (want >=%zu, got %u)",
++ sizeof(struct ip_set_req_adt), len);
++ res = -EINVAL;
++ goto done;
++ }
++ req_adt = (struct ip_set_req_adt *) data;
++
++ /* -U :all: :all:|:default: uses IP_SET_INVALID_ID */
++ if (!(*op == IP_SET_OP_UNBIND_SET
++ && req_adt->index == IP_SET_INVALID_ID)) {
++ index = ip_set_find_byindex(req_adt->index);
++ if (index == IP_SET_INVALID_ID) {
++ res = -ENOENT;
++ goto done;
++ }
++ }
++ res = adtfn(index, data, len);
++
++ done:
++ up(&ip_set_app_mutex);
++ vfree(data);
++ if (res > 0)
++ res = 0;
++ DP("final result %d", res);
++ return res;
++}
++
++static int
++ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len)
++{
++ int res = 0;
++ unsigned *op;
++ ip_set_id_t index = IP_SET_INVALID_ID;
++ void *data;
++ int copylen = *len;
++
++ DP("optval=%d, user=%p, len=%d", optval, user, *len);
++ if (!capable(CAP_NET_ADMIN))
++ return -EPERM;
++ if (optval != SO_IP_SET)
++ return -EBADF;
++ if (*len < sizeof(unsigned)) {
++ ip_set_printk("short userdata (want >=%zu, got %d)",
++ sizeof(unsigned), *len);
++ return -EINVAL;
++ }
++ data = vmalloc(*len);
++ if (!data) {
++ DP("out of mem for %d bytes", *len);
++ return -ENOMEM;
++ }
++ if (copy_from_user(data, user, *len) != 0) {
++ res = -EFAULT;
++ goto done;
++ }
++ if (down_interruptible(&ip_set_app_mutex)) {
++ res = -EINTR;
++ goto done;
++ }
++
++ op = (unsigned *) data;
++ DP("op=%x", *op);
++
++ if (*op < IP_SET_OP_VERSION) {
++ /* Check the version at the beginning of operations */
++ struct ip_set_req_version *req_version =
++ (struct ip_set_req_version *) data;
++ if (req_version->version != IP_SET_PROTOCOL_VERSION) {
++ res = -EPROTO;
++ goto done;
++ }
++ }
++
++ switch (*op) {
++ case IP_SET_OP_VERSION: {
++ struct ip_set_req_version *req_version =
++ (struct ip_set_req_version *) data;
++
++ if (*len != sizeof(struct ip_set_req_version)) {
++ ip_set_printk("invalid VERSION (want %zu, got %d)",
++ sizeof(struct ip_set_req_version),
++ *len);
++ res = -EINVAL;
++ goto done;
++ }
++
++ req_version->version = IP_SET_PROTOCOL_VERSION;
++ res = copy_to_user(user, req_version,
++ sizeof(struct ip_set_req_version));
++ goto done;
++ }
++ case IP_SET_OP_GET_BYNAME: {
++ struct ip_set_req_get_set *req_get
++ = (struct ip_set_req_get_set *) data;
++
++ if (*len != sizeof(struct ip_set_req_get_set)) {
++ ip_set_printk("invalid GET_BYNAME (want %zu, got %d)",
++ sizeof(struct ip_set_req_get_set), *len);
++ res = -EINVAL;
++ goto done;
++ }
++ req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
++ index = ip_set_find_byname(req_get->set.name);
++ req_get->set.index = index;
++ goto copy;
++ }
++ case IP_SET_OP_GET_BYINDEX: {
++ struct ip_set_req_get_set *req_get
++ = (struct ip_set_req_get_set *) data;
++
++ if (*len != sizeof(struct ip_set_req_get_set)) {
++ ip_set_printk("invalid GET_BYINDEX (want %zu, got %d)",
++ sizeof(struct ip_set_req_get_set), *len);
++ res = -EINVAL;
++ goto done;
++ }
++ req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
++ index = ip_set_find_byindex(req_get->set.index);
++ strncpy(req_get->set.name,
++ index == IP_SET_INVALID_ID ? ""
++ : ip_set_list[index]->name, IP_SET_MAXNAMELEN);
++ goto copy;
++ }
++ case IP_SET_OP_ADT_GET: {
++ struct ip_set_req_adt_get *req_get
++ = (struct ip_set_req_adt_get *) data;
++
++ if (*len != sizeof(struct ip_set_req_adt_get)) {
++ ip_set_printk("invalid ADT_GET (want %zu, got %d)",
++ sizeof(struct ip_set_req_adt_get), *len);
++ res = -EINVAL;
++ goto done;
++ }
++ req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
++ index = ip_set_find_byname(req_get->set.name);
++ if (index != IP_SET_INVALID_ID) {
++ req_get->set.index = index;
++ strncpy(req_get->typename,
++ ip_set_list[index]->type->typename,
++ IP_SET_MAXNAMELEN - 1);
++ } else {
++ res = -ENOENT;
++ goto done;
++ }
++ goto copy;
++ }
++ case IP_SET_OP_MAX_SETS: {
++ struct ip_set_req_max_sets *req_max_sets
++ = (struct ip_set_req_max_sets *) data;
++ ip_set_id_t i;
++
++ if (*len != sizeof(struct ip_set_req_max_sets)) {
++ ip_set_printk("invalid MAX_SETS (want %zu, got %d)",
++ sizeof(struct ip_set_req_max_sets), *len);
++ res = -EINVAL;
++ goto done;
++ }
++
++ if (strcmp(req_max_sets->set.name, IPSET_TOKEN_ALL) == 0) {
++ req_max_sets->set.index = IP_SET_INVALID_ID;
++ } else {
++ req_max_sets->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
++ req_max_sets->set.index =
++ ip_set_find_byname(req_max_sets->set.name);
++ if (req_max_sets->set.index == IP_SET_INVALID_ID) {
++ res = -ENOENT;
++ goto done;
++ }
++ }
++ req_max_sets->max_sets = ip_set_max;
++ req_max_sets->sets = 0;
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] != NULL)
++ req_max_sets->sets++;
++ }
++ goto copy;
++ }
++ case IP_SET_OP_LIST_SIZE:
++ case IP_SET_OP_SAVE_SIZE: {
++ struct ip_set_req_setnames *req_setnames
++ = (struct ip_set_req_setnames *) data;
++ struct ip_set_name_list *name_list;
++ struct ip_set *set;
++ ip_set_id_t i;
++ int used;
++
++ if (*len < sizeof(struct ip_set_req_setnames)) {
++ ip_set_printk("short LIST_SIZE (want >=%zu, got %d)",
++ sizeof(struct ip_set_req_setnames), *len);
++ res = -EINVAL;
++ goto done;
++ }
++
++ req_setnames->size = 0;
++ used = sizeof(struct ip_set_req_setnames);
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] == NULL)
++ continue;
++ name_list = (struct ip_set_name_list *)
++ (data + used);
++ used += sizeof(struct ip_set_name_list);
++ if (used > copylen) {
++ res = -EAGAIN;
++ goto done;
++ }
++ set = ip_set_list[i];
++ /* Fill in index, name, etc. */
++ name_list->index = i;
++ name_list->id = set->id;
++ strncpy(name_list->name,
++ set->name,
++ IP_SET_MAXNAMELEN - 1);
++ strncpy(name_list->typename,
++ set->type->typename,
++ IP_SET_MAXNAMELEN - 1);
++ DP("filled %s of type %s, index %u\n",
++ name_list->name, name_list->typename,
++ name_list->index);
++ if (!(req_setnames->index == IP_SET_INVALID_ID
++ || req_setnames->index == i))
++ continue;
++ /* Update size */
++ switch (*op) {
++ case IP_SET_OP_LIST_SIZE: {
++ req_setnames->size += sizeof(struct ip_set_list)
++ + set->type->header_size
++ + set->type->list_members_size(set);
++ FOREACH_HASH_DO(__set_hash_bindings_size_list,
++ i, &req_setnames->size);
++ break;
++ }
++ case IP_SET_OP_SAVE_SIZE: {
++ req_setnames->size += sizeof(struct ip_set_save)
++ + set->type->header_size
++ + set->type->list_members_size(set);
++ FOREACH_HASH_DO(__set_hash_bindings_size_save,
++ i, &req_setnames->size);
++ break;
++ }
++ default:
++ break;
++ }
++ }
++ if (copylen != used) {
++ res = -EAGAIN;
++ goto done;
++ }
++ goto copy;
++ }
++ case IP_SET_OP_LIST: {
++ struct ip_set_req_list *req_list
++ = (struct ip_set_req_list *) data;
++ ip_set_id_t i;
++ int used;
++
++ if (*len < sizeof(struct ip_set_req_list)) {
++ ip_set_printk("short LIST (want >=%zu, got %d)",
++ sizeof(struct ip_set_req_list), *len);
++ res = -EINVAL;
++ goto done;
++ }
++ index = req_list->index;
++ if (index != IP_SET_INVALID_ID
++ && ip_set_find_byindex(index) != index) {
++ res = -ENOENT;
++ goto done;
++ }
++ used = 0;
++ if (index == IP_SET_INVALID_ID) {
++ /* List all sets */
++ for (i = 0; i < ip_set_max && res == 0; i++) {
++ if (ip_set_list[i] != NULL)
++ res = ip_set_list_set(i, data, &used, *len);
++ }
++ } else {
++ /* List an individual set */
++ res = ip_set_list_set(index, data, &used, *len);
++ }
++ if (res != 0)
++ goto done;
++ else if (copylen != used) {
++ res = -EAGAIN;
++ goto done;
++ }
++ goto copy;
++ }
++ case IP_SET_OP_SAVE: {
++ struct ip_set_req_list *req_save
++ = (struct ip_set_req_list *) data;
++ ip_set_id_t i;
++ int used;
++
++ if (*len < sizeof(struct ip_set_req_list)) {
++ ip_set_printk("short SAVE (want >=%zu, got %d)",
++ sizeof(struct ip_set_req_list), *len);
++ res = -EINVAL;
++ goto done;
++ }
++ index = req_save->index;
++ if (index != IP_SET_INVALID_ID
++ && ip_set_find_byindex(index) != index) {
++ res = -ENOENT;
++ goto done;
++ }
++ used = 0;
++ if (index == IP_SET_INVALID_ID) {
++ /* Save all sets */
++ for (i = 0; i < ip_set_max && res == 0; i++) {
++ if (ip_set_list[i] != NULL)
++ res = ip_set_save_set(i, data, &used, *len);
++ }
++ } else {
++ /* Save an individual set */
++ res = ip_set_save_set(index, data, &used, *len);
++ }
++ if (res == 0)
++ res = ip_set_save_bindings(index, data, &used, *len);
++
++ if (res != 0)
++ goto done;
++ else if (copylen != used) {
++ res = -EAGAIN;
++ goto done;
++ }
++ goto copy;
++ }
++ case IP_SET_OP_RESTORE: {
++ struct ip_set_req_setnames *req_restore
++ = (struct ip_set_req_setnames *) data;
++ int line;
++
++ if (*len < sizeof(struct ip_set_req_setnames)
++ || *len != req_restore->size) {
++ ip_set_printk("invalid RESTORE (want =%zu, got %d)",
++ req_restore->size, *len);
++ res = -EINVAL;
++ goto done;
++ }
++ line = ip_set_restore(data + sizeof(struct ip_set_req_setnames),
++ req_restore->size - sizeof(struct ip_set_req_setnames));
++ DP("ip_set_restore: %u", line);
++ if (line != 0) {
++ res = -EAGAIN;
++ req_restore->size = line;
++ copylen = sizeof(struct ip_set_req_setnames);
++ goto copy;
++ }
++ goto done;
++ }
++ default:
++ res = -EBADMSG;
++ goto done;
++ } /* end of switch(op) */
++
++ copy:
++ DP("set %s, copylen %u", index != IP_SET_INVALID_ID
++ && ip_set_list[index]
++ ? ip_set_list[index]->name
++ : ":all:", copylen);
++ if (res == 0)
++ res = copy_to_user(user, data, copylen);
++ else
++ copy_to_user(user, data, copylen);
++
++ done:
++ up(&ip_set_app_mutex);
++ vfree(data);
++ if (res > 0)
++ res = 0;
++ DP("final result %d", res);
++ return res;
++}
++
++static struct nf_sockopt_ops so_set = {
++ .pf = PF_INET,
++ .set_optmin = SO_IP_SET,
++ .set_optmax = SO_IP_SET + 1,
++ .set = &ip_set_sockfn_set,
++ .get_optmin = SO_IP_SET,
++ .get_optmax = SO_IP_SET + 1,
++ .get = &ip_set_sockfn_get,
++ .use = 0
++};
++
++static int max_sets, hash_size;
++MODULE_PARM(max_sets, "i");
++MODULE_PARM_DESC(max_sets, "maximal number of sets");
++MODULE_PARM(hash_size, "i");
++MODULE_PARM_DESC(hash_size, "hash size for bindings");
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("module implementing core IP set support");
++
++static int __init init(void)
++{
++ int res;
++ ip_set_id_t i;
++
++ get_random_bytes(&ip_set_hash_random, 4);
++ if (max_sets)
++ ip_set_max = max_sets;
++ ip_set_list = vmalloc(sizeof(struct ip_set *) * ip_set_max);
++ if (!ip_set_list) {
++ printk(KERN_ERR "Unable to create ip_set_list\n");
++ return -ENOMEM;
++ }
++ memset(ip_set_list, 0, sizeof(struct ip_set *) * ip_set_max);
++ if (hash_size)
++ ip_set_bindings_hash_size = hash_size;
++ ip_set_hash = vmalloc(sizeof(struct list_head) * ip_set_bindings_hash_size);
++ if (!ip_set_hash) {
++ printk(KERN_ERR "Unable to create ip_set_hash\n");
++ vfree(ip_set_list);
++ return -ENOMEM;
++ }
++ for (i = 0; i < ip_set_bindings_hash_size; i++)
++ INIT_LIST_HEAD(&ip_set_hash[i]);
++
++ INIT_LIST_HEAD(&set_type_list);
++
++ res = nf_register_sockopt(&so_set);
++ if (res != 0) {
++ ip_set_printk("SO_SET registry failed: %d", res);
++ vfree(ip_set_list);
++ vfree(ip_set_hash);
++ return res;
++ }
++ return 0;
++}
++
++static void __exit fini(void)
++{
++ /* There can't be any existing set or binding. Racy. */
++ nf_unregister_sockopt(&so_set);
++ vfree(ip_set_list);
++ vfree(ip_set_hash);
++ DP("these are the famous last words");
++}
++
++EXPORT_SYMBOL(ip_set_register_set_type);
++EXPORT_SYMBOL(ip_set_unregister_set_type);
++
++EXPORT_SYMBOL(ip_set_get_byname);
++EXPORT_SYMBOL(ip_set_get_byindex);
++EXPORT_SYMBOL(ip_set_put);
++
++EXPORT_SYMBOL(ip_set_addip_kernel);
++EXPORT_SYMBOL(ip_set_delip_kernel);
++EXPORT_SYMBOL(ip_set_testip_kernel);
++
++module_init(init);
++module_exit(fini);
+diff -Naur linux-old/net/ipv4/netfilter/ip_set_iphash.c linux-new/net/ipv4/netfilter/ip_set_iphash.c
+--- linux-old/net/ipv4/netfilter/ip_set_iphash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/net/ipv4/netfilter/ip_set_iphash.c 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,379 @@
++/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* Kernel module implementing an ip hash set */
++
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ip_set.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <asm/softirq.h>
++#include <linux/spinlock.h>
++#include <linux/vmalloc.h>
++#include <linux/random.h>
++
++#include <net/ip.h>
++
++#include <linux/netfilter_ipv4/ip_set_malloc.h>
++#include <linux/netfilter_ipv4/ip_set_iphash.h>
++#include <linux/netfilter_ipv4/ip_set_jhash.h>
++#include <linux/netfilter_ipv4/ip_set_prime.h>
++
++static inline __u32
++jhash_ip(const struct ip_set_iphash *map, ip_set_ip_t ip)
++{
++ return jhash_1word(ip, map->initval);
++}
++
++static inline __u32
++randhash_ip(const struct ip_set_iphash *map, ip_set_ip_t ip)
++{
++ return (1 + ip % map->prime);
++}
++
++static inline __u32
++hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
++ __u32 jhash, randhash, id;
++ u_int16_t i;
++
++ *hash_ip = ip & map->netmask;
++ jhash = jhash_ip(map, *hash_ip);
++ randhash = randhash_ip(map, *hash_ip);
++ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u, %u.%u.%u.%u",
++ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip), HIPQUAD(map->netmask));
++
++ for (i = 0; i < map->probes; i++) {
++ id = (jhash + i * randhash) % map->hashsize;
++ DP("hash key: %u", id);
++ if (map->members[id] == *hash_ip)
++ return id;
++ /* No shortcut at testing - there can be deleted
++ * entries. */
++ }
++ return UINT_MAX;
++}
++
++static inline int
++__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ return (hash_id(set, ip, hash_ip) != UINT_MAX);
++}
++
++static int
++testip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_iphash *req =
++ (struct ip_set_req_iphash *) data;
++
++ if (size != sizeof(struct ip_set_req_iphash)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_iphash),
++ size);
++ return -EINVAL;
++ }
++ return __testip(set, req->ip, hash_ip);
++}
++
++static int
++testip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ return __testip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++}
++
++static inline int
++__addip(struct ip_set_iphash *map, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ __u32 jhash, randhash, probe;
++ u_int16_t i;
++
++ *hash_ip = ip & map->netmask;
++ jhash = jhash_ip(map, *hash_ip);
++ randhash = randhash_ip(map, *hash_ip);
++
++ for (i = 0; i < map->probes; i++) {
++ probe = (jhash + i * randhash) % map->hashsize;
++ if (map->members[probe] == *hash_ip)
++ return -EEXIST;
++ if (!map->members[probe]) {
++ map->members[probe] = *hash_ip;
++ return 0;
++ }
++ }
++ /* Trigger rehashing */
++ return -EAGAIN;
++}
++
++static int
++addip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_iphash *req =
++ (struct ip_set_req_iphash *) data;
++
++ if (size != sizeof(struct ip_set_req_iphash)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_iphash),
++ size);
++ return -EINVAL;
++ }
++ return __addip((struct ip_set_iphash *) set->data, req->ip, hash_ip);
++}
++
++static int
++addip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ return __addip((struct ip_set_iphash *) set->data,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++}
++
++static int retry(struct ip_set *set)
++{
++ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
++ ip_set_ip_t hash_ip, *members;
++ u_int32_t i, hashsize;
++ unsigned newbytes;
++ int res;
++ struct ip_set_iphash tmp = {
++ .hashsize = map->hashsize,
++ .probes = map->probes,
++ .resize = map->resize,
++ .netmask = map->netmask,
++ };
++
++ if (map->resize == 0)
++ return -ERANGE;
++
++ again:
++ res = 0;
++
++ /* Calculate new parameters */
++ get_random_bytes(&tmp.initval, 4);
++ hashsize = tmp.hashsize + (tmp.hashsize * map->resize)/100;
++ if (hashsize == tmp.hashsize)
++ hashsize++;
++ tmp.prime = make_prime(hashsize);
++
++ ip_set_printk("rehashing of set %s triggered: "
++ "hashsize grows from %u to %u",
++ set->name, tmp.hashsize, hashsize);
++ tmp.hashsize = hashsize;
++
++ newbytes = hashsize * sizeof(ip_set_ip_t);
++ tmp.members = ip_set_malloc(newbytes);
++ if (!tmp.members) {
++ DP("out of memory for %d bytes", newbytes);
++ return -ENOMEM;
++ }
++ memset(tmp.members, 0, newbytes);
++
++ write_lock_bh(&set->lock);
++ map = (struct ip_set_iphash *) set->data; /* Play safe */
++ for (i = 0; i < map->hashsize && res == 0; i++) {
++ if (map->members[i])
++ res = __addip(&tmp, map->members[i], &hash_ip);
++ }
++ if (res) {
++ /* Failure, try again */
++ write_unlock_bh(&set->lock);
++ ip_set_free(tmp.members, newbytes);
++ goto again;
++ }
++
++ /* Success at resizing! */
++ members = map->members;
++ hashsize = map->hashsize;
++
++ map->initval = tmp.initval;
++ map->prime = tmp.prime;
++ map->hashsize = tmp.hashsize;
++ map->members = tmp.members;
++ write_unlock_bh(&set->lock);
++
++ ip_set_free(members, hashsize * sizeof(ip_set_ip_t));
++
++ return 0;
++}
++
++static inline int
++__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
++ ip_set_ip_t id = hash_id(set, ip, hash_ip);
++
++ if (id == UINT_MAX)
++ return -EEXIST;
++
++ map->members[id] = 0;
++ return 0;
++}
++
++static int
++delip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_iphash *req =
++ (struct ip_set_req_iphash *) data;
++
++ if (size != sizeof(struct ip_set_req_iphash)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_iphash),
++ size);
++ return -EINVAL;
++ }
++ return __delip(set, req->ip, hash_ip);
++}
++
++static int
++delip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ return __delip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++}
++
++static int create(struct ip_set *set, const void *data, size_t size)
++{
++ unsigned newbytes;
++ struct ip_set_req_iphash_create *req =
++ (struct ip_set_req_iphash_create *) data;
++ struct ip_set_iphash *map;
++
++ if (size != sizeof(struct ip_set_req_iphash_create)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_iphash_create),
++ size);
++ return -EINVAL;
++ }
++
++ if (req->hashsize < 1) {
++ ip_set_printk("hashsize too small");
++ return -ENOEXEC;
++ }
++
++ map = kmalloc(sizeof(struct ip_set_iphash), GFP_KERNEL);
++ if (!map) {
++ DP("out of memory for %d bytes",
++ sizeof(struct ip_set_iphash));
++ return -ENOMEM;
++ }
++ get_random_bytes(&map->initval, 4);
++ map->prime = make_prime(req->hashsize);
++ map->hashsize = req->hashsize;
++ map->probes = req->probes;
++ map->resize = req->resize;
++ map->netmask = req->netmask;
++ newbytes = map->hashsize * sizeof(ip_set_ip_t);
++ map->members = ip_set_malloc(newbytes);
++ if (!map->members) {
++ DP("out of memory for %d bytes", newbytes);
++ kfree(map);
++ return -ENOMEM;
++ }
++ memset(map->members, 0, newbytes);
++
++ set->data = map;
++ return 0;
++}
++
++static void destroy(struct ip_set *set)
++{
++ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
++
++ ip_set_free(map->members, map->hashsize * sizeof(ip_set_ip_t));
++ kfree(map);
++
++ set->data = NULL;
++}
++
++static void flush(struct ip_set *set)
++{
++ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
++ memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
++}
++
++static void list_header(const struct ip_set *set, void *data)
++{
++ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
++ struct ip_set_req_iphash_create *header =
++ (struct ip_set_req_iphash_create *) data;
++
++ header->hashsize = map->hashsize;
++ header->probes = map->probes;
++ header->resize = map->resize;
++ header->netmask = map->netmask;
++}
++
++static int list_members_size(const struct ip_set *set)
++{
++ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
++
++ return (map->hashsize * sizeof(ip_set_ip_t));
++}
++
++static void list_members(const struct ip_set *set, void *data)
++{
++ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
++ int bytes = map->hashsize * sizeof(ip_set_ip_t);
++
++ memcpy(data, map->members, bytes);
++}
++
++static struct ip_set_type ip_set_iphash = {
++ .typename = SETTYPE_NAME,
++ .typecode = IPSET_TYPE_IP,
++ .protocol_version = IP_SET_PROTOCOL_VERSION,
++ .create = &create,
++ .destroy = &destroy,
++ .flush = &flush,
++ .reqsize = sizeof(struct ip_set_req_iphash),
++ .addip = &addip,
++ .addip_kernel = &addip_kernel,
++ .retry = &retry,
++ .delip = &delip,
++ .delip_kernel = &delip_kernel,
++ .testip = &testip,
++ .testip_kernel = &testip_kernel,
++ .header_size = sizeof(struct ip_set_req_iphash_create),
++ .list_header = &list_header,
++ .list_members_size = &list_members_size,
++ .list_members = &list_members,
++ .me = THIS_MODULE,
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("iphash type of IP sets");
++
++static int __init init(void)
++{
++ return ip_set_register_set_type(&ip_set_iphash);
++}
++
++static void __exit fini(void)
++{
++ /* FIXME: possible race with ip_set_create() */
++ ip_set_unregister_set_type(&ip_set_iphash);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Naur linux-old/net/ipv4/netfilter/ip_set_ipmap.c linux-new/net/ipv4/netfilter/ip_set_ipmap.c
+--- linux-old/net/ipv4/netfilter/ip_set_ipmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/net/ipv4/netfilter/ip_set_ipmap.c 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,314 @@
++/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
++ * Patrick Schaaf <bof@bof.de>
++ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* Kernel module implementing an IP set type: the single bitmap type */
++
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ip_set.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <asm/softirq.h>
++#include <linux/spinlock.h>
++
++#include <linux/netfilter_ipv4/ip_set_ipmap.h>
++
++static inline ip_set_ip_t
++ip_to_id(const struct ip_set_ipmap *map, ip_set_ip_t ip)
++{
++ return (ip - map->first_ip)/map->hosts;
++}
++
++static inline int
++__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
++
++ if (ip < map->first_ip || ip > map->last_ip)
++ return -ERANGE;
++
++ *hash_ip = ip & map->netmask;
++ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
++ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip));
++ return !!test_bit(ip_to_id(map, *hash_ip), map->members);
++}
++
++static int
++testip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_ipmap *req =
++ (struct ip_set_req_ipmap *) data;
++
++ if (size != sizeof(struct ip_set_req_ipmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_ipmap),
++ size);
++ return -EINVAL;
++ }
++ return __testip(set, req->ip, hash_ip);
++}
++
++static int
++testip_kernel(struct ip_set *set,
++ const struct sk_buff *skb,
++ u_int32_t flags,
++ ip_set_ip_t *hash_ip)
++{
++ int res;
++
++ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
++ flags & IPSET_SRC ? "SRC" : "DST",
++ NIPQUAD(skb->nh.iph->saddr),
++ NIPQUAD(skb->nh.iph->daddr));
++
++ res = __testip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++ return (res < 0 ? 0 : res);
++}
++
++static inline int
++__addip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
++
++ if (ip < map->first_ip || ip > map->last_ip)
++ return -ERANGE;
++
++ *hash_ip = ip & map->netmask;
++ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
++ if (test_and_set_bit(ip_to_id(map, *hash_ip), map->members))
++ return -EEXIST;
++
++ return 0;
++}
++
++static int
++addip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_ipmap *req =
++ (struct ip_set_req_ipmap *) data;
++
++ if (size != sizeof(struct ip_set_req_ipmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_ipmap),
++ size);
++ return -EINVAL;
++ }
++ DP("%u.%u.%u.%u", HIPQUAD(req->ip));
++ return __addip(set, req->ip, hash_ip);
++}
++
++static int
++addip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ return __addip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++}
++
++static inline int
++__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
++
++ if (ip < map->first_ip || ip > map->last_ip)
++ return -ERANGE;
++
++ *hash_ip = ip & map->netmask;
++ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
++ if (!test_and_clear_bit(ip_to_id(map, *hash_ip), map->members))
++ return -EEXIST;
++
++ return 0;
++}
++
++static int
++delip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_ipmap *req =
++ (struct ip_set_req_ipmap *) data;
++
++ if (size != sizeof(struct ip_set_req_ipmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_ipmap),
++ size);
++ return -EINVAL;
++ }
++ return __delip(set, req->ip, hash_ip);
++}
++
++static int
++delip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ return __delip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++}
++
++static int create(struct ip_set *set, const void *data, size_t size)
++{
++ int newbytes;
++ struct ip_set_req_ipmap_create *req =
++ (struct ip_set_req_ipmap_create *) data;
++ struct ip_set_ipmap *map;
++
++ if (size != sizeof(struct ip_set_req_ipmap_create)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_ipmap_create),
++ size);
++ return -EINVAL;
++ }
++
++ DP("from %u.%u.%u.%u to %u.%u.%u.%u",
++ HIPQUAD(req->from), HIPQUAD(req->to));
++
++ if (req->from > req->to) {
++ DP("bad ip range");
++ return -ENOEXEC;
++ }
++
++ if (req->to - req->from > MAX_RANGE) {
++ ip_set_printk("range too big (max %d addresses)",
++ MAX_RANGE);
++ return -ENOEXEC;
++ }
++
++ map = kmalloc(sizeof(struct ip_set_ipmap), GFP_KERNEL);
++ if (!map) {
++ DP("out of memory for %d bytes",
++ sizeof(struct ip_set_ipmap));
++ return -ENOMEM;
++ }
++ map->first_ip = req->from;
++ map->last_ip = req->to;
++ map->netmask = req->netmask;
++
++ if (req->netmask == 0xFFFFFFFF) {
++ map->hosts = 1;
++ map->sizeid = map->last_ip - map->first_ip + 1;
++ } else {
++ unsigned int mask_bits, netmask_bits;
++ ip_set_ip_t mask;
++
++ map->first_ip &= map->netmask; /* Should we better bark? */
++
++ mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits);
++ netmask_bits = mask_to_bits(map->netmask);
++
++ if (!mask || netmask_bits <= mask_bits)
++ return -ENOEXEC;
++
++ map->hosts = 2 << (32 - netmask_bits - 1);
++ map->sizeid = 2 << (netmask_bits - mask_bits - 1);
++ }
++ newbytes = bitmap_bytes(0, map->sizeid - 1);
++ map->members = kmalloc(newbytes, GFP_KERNEL);
++ if (!map->members) {
++ DP("out of memory for %d bytes", newbytes);
++ kfree(map);
++ return -ENOMEM;
++ }
++ memset(map->members, 0, newbytes);
++
++ set->data = map;
++ return 0;
++}
++
++static void destroy(struct ip_set *set)
++{
++ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
++
++ kfree(map->members);
++ kfree(map);
++
++ set->data = NULL;
++}
++
++static void flush(struct ip_set *set)
++{
++ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
++ memset(map->members, 0, bitmap_bytes(0, map->sizeid - 1));
++}
++
++static void list_header(const struct ip_set *set, void *data)
++{
++ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
++ struct ip_set_req_ipmap_create *header =
++ (struct ip_set_req_ipmap_create *) data;
++
++ header->from = map->first_ip;
++ header->to = map->last_ip;
++ header->netmask = map->netmask;
++}
++
++static int list_members_size(const struct ip_set *set)
++{
++ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
++
++ return bitmap_bytes(0, map->sizeid - 1);
++}
++
++static void list_members(const struct ip_set *set, void *data)
++{
++ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
++ int bytes = bitmap_bytes(0, map->sizeid - 1);
++
++ memcpy(data, map->members, bytes);
++}
++
++static struct ip_set_type ip_set_ipmap = {
++ .typename = SETTYPE_NAME,
++ .typecode = IPSET_TYPE_IP,
++ .protocol_version = IP_SET_PROTOCOL_VERSION,
++ .create = &create,
++ .destroy = &destroy,
++ .flush = &flush,
++ .reqsize = sizeof(struct ip_set_req_ipmap),
++ .addip = &addip,
++ .addip_kernel = &addip_kernel,
++ .delip = &delip,
++ .delip_kernel = &delip_kernel,
++ .testip = &testip,
++ .testip_kernel = &testip_kernel,
++ .header_size = sizeof(struct ip_set_req_ipmap_create),
++ .list_header = &list_header,
++ .list_members_size = &list_members_size,
++ .list_members = &list_members,
++ .me = THIS_MODULE,
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("ipmap type of IP sets");
++
++static int __init init(void)
++{
++ return ip_set_register_set_type(&ip_set_ipmap);
++}
++
++static void __exit fini(void)
++{
++ /* FIXME: possible race with ip_set_create() */
++ ip_set_unregister_set_type(&ip_set_ipmap);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Naur linux-old/net/ipv4/netfilter/ip_set_iptree.c linux-new/net/ipv4/netfilter/ip_set_iptree.c
+--- linux-old/net/ipv4/netfilter/ip_set_iptree.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/net/ipv4/netfilter/ip_set_iptree.c 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,511 @@
++/* Copyright (C) 2005 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* Kernel module implementing an IP set type: the iptree type */
++
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ip_set.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++
++#include <linux/netfilter_ipv4/ip_set_iptree.h>
++
++/* Garbage collection interval in seconds: */
++#define IPTREE_GC_TIME 5*60
++/* Sleep so many milliseconds before trying again
++ * to delete the gc timer at destroying a set */
++#define IPTREE_DESTROY_SLEEP 100
++
++static kmem_cache_t *branch_cachep;
++static kmem_cache_t *leaf_cachep;
++
++#define ABCD(a,b,c,d,addrp) do { \
++ a = ((unsigned char *)addrp)[3]; \
++ b = ((unsigned char *)addrp)[2]; \
++ c = ((unsigned char *)addrp)[1]; \
++ d = ((unsigned char *)addrp)[0]; \
++} while (0)
++
++#define TESTIP_WALK(map, elem, branch) do { \
++ if ((map)->tree[elem]) { \
++ branch = (map)->tree[elem]; \
++ } else \
++ return 0; \
++} while (0)
++
++static inline int
++__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ struct ip_set_iptreeb *btree;
++ struct ip_set_iptreec *ctree;
++ struct ip_set_iptreed *dtree;
++ unsigned char a,b,c,d;
++
++ *hash_ip = ip;
++ ABCD(a, b, c, d, hash_ip);
++ DP("%u %u %u %u timeout %u", a, b, c, d, map->timeout);
++ TESTIP_WALK(map, a, btree);
++ TESTIP_WALK(btree, b, ctree);
++ TESTIP_WALK(ctree, c, dtree);
++ DP("%lu %lu", dtree->expires[d], jiffies);
++ return !!(map->timeout ? (time_after(dtree->expires[d], jiffies))
++ : dtree->expires[d]);
++}
++
++static int
++testip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_iptree *req =
++ (struct ip_set_req_iptree *) data;
++
++ if (size != sizeof(struct ip_set_req_iptree)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_iptree),
++ size);
++ return -EINVAL;
++ }
++ return __testip(set, req->ip, hash_ip);
++}
++
++static int
++testip_kernel(struct ip_set *set,
++ const struct sk_buff *skb,
++ u_int32_t flags,
++ ip_set_ip_t *hash_ip)
++{
++ int res;
++
++ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
++ flags & IPSET_SRC ? "SRC" : "DST",
++ NIPQUAD(skb->nh.iph->saddr),
++ NIPQUAD(skb->nh.iph->daddr));
++
++ res = __testip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++ return (res < 0 ? 0 : res);
++}
++
++#define ADDIP_WALK(map, elem, branch, type, cachep) do { \
++ if ((map)->tree[elem]) { \
++ DP("found %u", elem); \
++ branch = (map)->tree[elem]; \
++ } else { \
++ branch = (type *) \
++ kmem_cache_alloc(cachep, GFP_KERNEL); \
++ if (branch == NULL) \
++ return -ENOMEM; \
++ memset(branch, 0, sizeof(*branch)); \
++ (map)->tree[elem] = branch; \
++ DP("alloc %u", elem); \
++ } \
++} while (0)
++
++static inline int
++__addip(struct ip_set *set, ip_set_ip_t ip, unsigned int timeout,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ struct ip_set_iptreeb *btree;
++ struct ip_set_iptreec *ctree;
++ struct ip_set_iptreed *dtree;
++ unsigned char a,b,c,d;
++ int ret = 0;
++
++ *hash_ip = ip;
++ ABCD(a, b, c, d, hash_ip);
++ DP("%u %u %u %u timeout %u", a, b, c, d, timeout);
++ ADDIP_WALK(map, a, btree, struct ip_set_iptreeb, branch_cachep);
++ ADDIP_WALK(btree, b, ctree, struct ip_set_iptreec, branch_cachep);
++ ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreed, leaf_cachep);
++ if (dtree->expires[d]
++ && (!map->timeout || time_after(dtree->expires[d], jiffies)))
++ ret = -EEXIST;
++ dtree->expires[d] = map->timeout ? (timeout * HZ + jiffies) : 1;
++ DP("%u %lu", d, dtree->expires[d]);
++ return ret;
++}
++
++static int
++addip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ struct ip_set_req_iptree *req =
++ (struct ip_set_req_iptree *) data;
++
++ if (size != sizeof(struct ip_set_req_iptree)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_iptree),
++ size);
++ return -EINVAL;
++ }
++ DP("%u.%u.%u.%u %u", HIPQUAD(req->ip), req->timeout);
++ return __addip(set, req->ip,
++ req->timeout ? req->timeout : map->timeout,
++ hash_ip);
++}
++
++static int
++addip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++
++ return __addip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ map->timeout,
++ hash_ip);
++}
++
++#define DELIP_WALK(map, elem, branch) do { \
++ if ((map)->tree[elem]) { \
++ branch = (map)->tree[elem]; \
++ } else \
++ return -EEXIST; \
++} while (0)
++
++static inline int
++__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ struct ip_set_iptreeb *btree;
++ struct ip_set_iptreec *ctree;
++ struct ip_set_iptreed *dtree;
++ unsigned char a,b,c,d;
++
++ *hash_ip = ip;
++ ABCD(a, b, c, d, hash_ip);
++ DELIP_WALK(map, a, btree);
++ DELIP_WALK(btree, b, ctree);
++ DELIP_WALK(ctree, c, dtree);
++
++ if (dtree->expires[d]) {
++ dtree->expires[d] = 0;
++ return 0;
++ }
++ return -EEXIST;
++}
++
++static int
++delip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_iptree *req =
++ (struct ip_set_req_iptree *) data;
++
++ if (size != sizeof(struct ip_set_req_iptree)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_iptree),
++ size);
++ return -EINVAL;
++ }
++ return __delip(set, req->ip, hash_ip);
++}
++
++static int
++delip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ return __delip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++}
++
++#define LOOP_WALK_BEGIN(map, i, branch) \
++ for (i = 0; i < 255; i++) { \
++ if (!(map)->tree[i]) \
++ continue; \
++ branch = (map)->tree[i]
++
++#define LOOP_WALK_END }
++
++static void ip_tree_gc(unsigned long ul_set)
++{
++ struct ip_set *set = (void *) ul_set;
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ struct ip_set_iptreeb *btree;
++ struct ip_set_iptreec *ctree;
++ struct ip_set_iptreed *dtree;
++ unsigned char a,b,c,d;
++ unsigned char i,j,k;
++
++ i = j = k = 0;
++ DP("gc: %s", set->name);
++ write_lock_bh(&set->lock);
++ LOOP_WALK_BEGIN(map, a, btree);
++ LOOP_WALK_BEGIN(btree, b, ctree);
++ LOOP_WALK_BEGIN(ctree, c, dtree);
++ for (d = 0; d < 255; d++) {
++ if (dtree->expires[d]) {
++ DP("gc: %u %u %u %u: expires %lu jiffies %lu",
++ a, b, c, d,
++ dtree->expires[d], jiffies);
++ if (map->timeout
++ && time_before(dtree->expires[d], jiffies))
++ dtree->expires[d] = 0;
++ else
++ k = 1;
++ }
++ }
++ if (k == 0) {
++ DP("gc: %s: leaf %u %u %u empty",
++ set->name, a, b, c);
++ kmem_cache_free(leaf_cachep, dtree);
++ ctree->tree[c] = NULL;
++ } else {
++ DP("gc: %s: leaf %u %u %u not empty",
++ set->name, a, b, c);
++ j = 1;
++ k = 0;
++ }
++ LOOP_WALK_END;
++ if (j == 0) {
++ DP("gc: %s: branch %u %u empty",
++ set->name, a, b);
++ kmem_cache_free(branch_cachep, ctree);
++ btree->tree[b] = NULL;
++ } else {
++ DP("gc: %s: branch %u %u not empty",
++ set->name, a, b);
++ i = 1;
++ j = k = 0;
++ }
++ LOOP_WALK_END;
++ if (i == 0) {
++ DP("gc: %s: branch %u empty",
++ set->name, a);
++ kmem_cache_free(branch_cachep, btree);
++ map->tree[a] = NULL;
++ } else {
++ DP("gc: %s: branch %u not empty",
++ set->name, a);
++ i = j = k = 0;
++ }
++ LOOP_WALK_END;
++ write_unlock_bh(&set->lock);
++
++ map->gc.expires = jiffies + map->gc_interval * HZ;
++ add_timer(&map->gc);
++}
++
++static int create(struct ip_set *set, const void *data, size_t size)
++{
++ struct ip_set_req_iptree_create *req =
++ (struct ip_set_req_iptree_create *) data;
++ struct ip_set_iptree *map;
++
++ if (size != sizeof(struct ip_set_req_iptree_create)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_iptree_create),
++ size);
++ return -EINVAL;
++ }
++
++ map = kmalloc(sizeof(struct ip_set_iptree), GFP_KERNEL);
++ if (!map) {
++ DP("out of memory for %d bytes",
++ sizeof(struct ip_set_iptree));
++ return -ENOMEM;
++ }
++ memset(map, 0, sizeof(*map));
++ map->timeout = req->timeout;
++ set->data = map;
++
++ /* If there is no timeout for the entries,
++ * we still have to call gc because delete
++ * do not clean up empty branches */
++ map->gc_interval = IPTREE_GC_TIME;
++ init_timer(&map->gc);
++ map->gc.data = (unsigned long) set;
++ map->gc.function = ip_tree_gc;
++ map->gc.expires = jiffies + map->gc_interval * HZ;
++ add_timer(&map->gc);
++
++ return 0;
++}
++
++static void __flush(struct ip_set_iptree *map)
++{
++ struct ip_set_iptreeb *btree;
++ struct ip_set_iptreec *ctree;
++ struct ip_set_iptreed *dtree;
++ unsigned int a,b,c;
++
++ LOOP_WALK_BEGIN(map, a, btree);
++ LOOP_WALK_BEGIN(btree, b, ctree);
++ LOOP_WALK_BEGIN(ctree, c, dtree);
++ kmem_cache_free(leaf_cachep, dtree);
++ LOOP_WALK_END;
++ kmem_cache_free(branch_cachep, ctree);
++ LOOP_WALK_END;
++ kmem_cache_free(branch_cachep, btree);
++ LOOP_WALK_END;
++}
++
++static void destroy(struct ip_set *set)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++
++ while (!del_timer(&map->gc))
++ msleep(IPTREE_DESTROY_SLEEP);
++ __flush(map);
++ kfree(map);
++ set->data = NULL;
++}
++
++static void flush(struct ip_set *set)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ unsigned int timeout = map->timeout;
++
++ __flush(map);
++ memset(map, 0, sizeof(*map));
++ map->timeout = timeout;
++}
++
++static void list_header(const struct ip_set *set, void *data)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ struct ip_set_req_iptree_create *header =
++ (struct ip_set_req_iptree_create *) data;
++
++ header->timeout = map->timeout;
++}
++
++static int list_members_size(const struct ip_set *set)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ struct ip_set_iptreeb *btree;
++ struct ip_set_iptreec *ctree;
++ struct ip_set_iptreed *dtree;
++ unsigned char a,b,c,d;
++ unsigned int count = 0;
++
++ LOOP_WALK_BEGIN(map, a, btree);
++ LOOP_WALK_BEGIN(btree, b, ctree);
++ LOOP_WALK_BEGIN(ctree, c, dtree);
++ for (d = 0; d < 255; d++) {
++ if (dtree->expires[d]
++ && (!map->timeout || time_after(dtree->expires[d], jiffies)))
++ count++;
++ }
++ LOOP_WALK_END;
++ LOOP_WALK_END;
++ LOOP_WALK_END;
++
++ DP("members %u", count);
++ return (count * sizeof(struct ip_set_req_iptree));
++}
++
++static void list_members(const struct ip_set *set, void *data)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ struct ip_set_iptreeb *btree;
++ struct ip_set_iptreec *ctree;
++ struct ip_set_iptreed *dtree;
++ unsigned char a,b,c,d;
++ size_t offset = 0;
++ struct ip_set_req_iptree *entry;
++
++ LOOP_WALK_BEGIN(map, a, btree);
++ LOOP_WALK_BEGIN(btree, b, ctree);
++ LOOP_WALK_BEGIN(ctree, c, dtree);
++ for (d = 0; d < 255; d++) {
++ if (dtree->expires[d]
++ && (!map->timeout || time_after(dtree->expires[d], jiffies))) {
++ entry = (struct ip_set_req_iptree *)(data + offset);
++ entry->ip = ((a << 24) | (b << 16) | (c << 8) | d);
++ entry->timeout = !map->timeout ? 0
++ : (dtree->expires[d] - jiffies)/HZ;
++ offset += sizeof(struct ip_set_req_iptree);
++ }
++ }
++ LOOP_WALK_END;
++ LOOP_WALK_END;
++ LOOP_WALK_END;
++}
++
++static struct ip_set_type ip_set_iptree = {
++ .typename = SETTYPE_NAME,
++ .typecode = IPSET_TYPE_IP,
++ .protocol_version = IP_SET_PROTOCOL_VERSION,
++ .create = &create,
++ .destroy = &destroy,
++ .flush = &flush,
++ .reqsize = sizeof(struct ip_set_req_iptree),
++ .addip = &addip,
++ .addip_kernel = &addip_kernel,
++ .delip = &delip,
++ .delip_kernel = &delip_kernel,
++ .testip = &testip,
++ .testip_kernel = &testip_kernel,
++ .header_size = sizeof(struct ip_set_req_iptree_create),
++ .list_header = &list_header,
++ .list_members_size = &list_members_size,
++ .list_members = &list_members,
++ .me = THIS_MODULE,
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("iptree type of IP sets");
++
++static int __init init(void)
++{
++ int ret;
++
++ branch_cachep = kmem_cache_create("ip_set_iptreeb",
++ sizeof(struct ip_set_iptreeb),
++ 0, 0, NULL, NULL);
++ if (!branch_cachep) {
++ printk(KERN_ERR "Unable to create ip_set_iptreeb slab cache\n");
++ ret = -ENOMEM;
++ goto out;
++ }
++ leaf_cachep = kmem_cache_create("ip_set_iptreed",
++ sizeof(struct ip_set_iptreed),
++ 0, 0, NULL, NULL);
++ if (!leaf_cachep) {
++ printk(KERN_ERR "Unable to create ip_set_iptreed slab cache\n");
++ ret = -ENOMEM;
++ goto free_branch;
++ }
++ ret = ip_set_register_set_type(&ip_set_iptree);
++ if (ret == 0)
++ goto out;
++
++ kmem_cache_destroy(leaf_cachep);
++ free_branch:
++ kmem_cache_destroy(branch_cachep);
++ out:
++ return ret;
++}
++
++static void __exit fini(void)
++{
++ /* FIXME: possible race with ip_set_create() */
++ ip_set_unregister_set_type(&ip_set_iptree);
++ kmem_cache_destroy(leaf_cachep);
++ kmem_cache_destroy(branch_cachep);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Naur linux-old/net/ipv4/netfilter/ip_set_macipmap.c linux-new/net/ipv4/netfilter/ip_set_macipmap.c
+--- linux-old/net/ipv4/netfilter/ip_set_macipmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/net/ipv4/netfilter/ip_set_macipmap.c 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,340 @@
++/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
++ * Patrick Schaaf <bof@bof.de>
++ * Martin Josefsson <gandalf@wlug.westbo.se>
++ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* Kernel module implementing an IP set type: the macipmap type */
++
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ip_set.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <asm/softirq.h>
++#include <linux/spinlock.h>
++#include <linux/if_ether.h>
++#include <linux/vmalloc.h>
++
++#include <linux/netfilter_ipv4/ip_set_malloc.h>
++#include <linux/netfilter_ipv4/ip_set_macipmap.h>
++
++static int
++testip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_macipmap *map = (struct ip_set_macipmap *) set->data;
++ struct ip_set_macip *table = (struct ip_set_macip *) map->members;
++ struct ip_set_req_macipmap *req = (struct ip_set_req_macipmap *) data;
++
++ if (size != sizeof(struct ip_set_req_macipmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_macipmap),
++ size);
++ return -EINVAL;
++ }
++
++ if (req->ip < map->first_ip || req->ip > map->last_ip)
++ return -ERANGE;
++
++ *hash_ip = req->ip;
++ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
++ set->name, HIPQUAD(req->ip), HIPQUAD(*hash_ip));
++ if (test_bit(IPSET_MACIP_ISSET,
++ &table[req->ip - map->first_ip].flags)) {
++ return (memcmp(req->ethernet,
++ &table[req->ip - map->first_ip].ethernet,
++ ETH_ALEN) == 0);
++ } else {
++ return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
++ }
++}
++
++static int
++testip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_macipmap *map =
++ (struct ip_set_macipmap *) set->data;
++ struct ip_set_macip *table =
++ (struct ip_set_macip *) map->members;
++ ip_set_ip_t ip;
++
++ ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr);
++ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
++ flags & IPSET_SRC ? "SRC" : "DST",
++ NIPQUAD(skb->nh.iph->saddr),
++ NIPQUAD(skb->nh.iph->daddr));
++
++ if (ip < map->first_ip || ip > map->last_ip)
++ return 0;
++
++ *hash_ip = ip;
++ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
++ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip));
++ if (test_bit(IPSET_MACIP_ISSET, &table[ip - map->first_ip].flags)) {
++ /* Is mac pointer valid?
++ * If so, compare... */
++ return (skb->mac.raw >= skb->head
++ && (skb->mac.raw + ETH_HLEN) <= skb->data
++ && (memcmp(skb->mac.ethernet->h_source,
++ &table[ip - map->first_ip].ethernet,
++ ETH_ALEN) == 0));
++ } else {
++ return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
++ }
++}
++
++/* returns 0 on success */
++static inline int
++__addip(struct ip_set *set,
++ ip_set_ip_t ip, unsigned char *ethernet, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_macipmap *map =
++ (struct ip_set_macipmap *) set->data;
++ struct ip_set_macip *table =
++ (struct ip_set_macip *) map->members;
++
++ if (ip < map->first_ip || ip > map->last_ip)
++ return -ERANGE;
++ if (test_and_set_bit(IPSET_MACIP_ISSET,
++ &table[ip - map->first_ip].flags))
++ return -EEXIST;
++
++ *hash_ip = ip;
++ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
++ memcpy(&table[ip - map->first_ip].ethernet, ethernet, ETH_ALEN);
++ return 0;
++}
++
++static int
++addip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_macipmap *req =
++ (struct ip_set_req_macipmap *) data;
++
++ if (size != sizeof(struct ip_set_req_macipmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_macipmap),
++ size);
++ return -EINVAL;
++ }
++ return __addip(set, req->ip, req->ethernet, hash_ip);
++}
++
++static int
++addip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ ip_set_ip_t ip;
++
++ ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr);
++
++ if (!(skb->mac.raw >= skb->head
++ && (skb->mac.raw + ETH_HLEN) <= skb->data))
++ return -EINVAL;
++
++ return __addip(set, ip, skb->mac.ethernet->h_source, hash_ip);
++}
++
++static inline int
++__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_macipmap *map =
++ (struct ip_set_macipmap *) set->data;
++ struct ip_set_macip *table =
++ (struct ip_set_macip *) map->members;
++
++ if (ip < map->first_ip || ip > map->last_ip)
++ return -ERANGE;
++ if (!test_and_clear_bit(IPSET_MACIP_ISSET,
++ &table[ip - map->first_ip].flags))
++ return -EEXIST;
++
++ *hash_ip = ip;
++ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
++ return 0;
++}
++
++static int
++delip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_macipmap *req =
++ (struct ip_set_req_macipmap *) data;
++
++ if (size != sizeof(struct ip_set_req_macipmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_macipmap),
++ size);
++ return -EINVAL;
++ }
++ return __delip(set, req->ip, hash_ip);
++}
++
++static int
++delip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ return __delip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++}
++
++static inline size_t members_size(ip_set_id_t from, ip_set_id_t to)
++{
++ return (size_t)((to - from + 1) * sizeof(struct ip_set_macip));
++}
++
++static int create(struct ip_set *set, const void *data, size_t size)
++{
++ int newbytes;
++ struct ip_set_req_macipmap_create *req =
++ (struct ip_set_req_macipmap_create *) data;
++ struct ip_set_macipmap *map;
++
++ if (size != sizeof(struct ip_set_req_macipmap_create)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_macipmap_create),
++ size);
++ return -EINVAL;
++ }
++
++ DP("from %u.%u.%u.%u to %u.%u.%u.%u",
++ HIPQUAD(req->from), HIPQUAD(req->to));
++
++ if (req->from > req->to) {
++ DP("bad ip range");
++ return -ENOEXEC;
++ }
++
++ if (req->to - req->from > MAX_RANGE) {
++ ip_set_printk("range too big (max %d addresses)",
++ MAX_RANGE);
++ return -ENOEXEC;
++ }
++
++ map = kmalloc(sizeof(struct ip_set_macipmap), GFP_KERNEL);
++ if (!map) {
++ DP("out of memory for %d bytes",
++ sizeof(struct ip_set_macipmap));
++ return -ENOMEM;
++ }
++ map->flags = req->flags;
++ map->first_ip = req->from;
++ map->last_ip = req->to;
++ newbytes = members_size(map->first_ip, map->last_ip);
++ map->members = ip_set_malloc(newbytes);
++ DP("members: %u %p", newbytes, map->members);
++ if (!map->members) {
++ DP("out of memory for %d bytes", newbytes);
++ kfree(map);
++ return -ENOMEM;
++ }
++ memset(map->members, 0, newbytes);
++
++ set->data = map;
++ return 0;
++}
++
++static void destroy(struct ip_set *set)
++{
++ struct ip_set_macipmap *map =
++ (struct ip_set_macipmap *) set->data;
++
++ ip_set_free(map->members, members_size(map->first_ip, map->last_ip));
++ kfree(map);
++
++ set->data = NULL;
++}
++
++static void flush(struct ip_set *set)
++{
++ struct ip_set_macipmap *map =
++ (struct ip_set_macipmap *) set->data;
++ memset(map->members, 0, members_size(map->first_ip, map->last_ip));
++}
++
++static void list_header(const struct ip_set *set, void *data)
++{
++ struct ip_set_macipmap *map =
++ (struct ip_set_macipmap *) set->data;
++ struct ip_set_req_macipmap_create *header =
++ (struct ip_set_req_macipmap_create *) data;
++
++ DP("list_header %x %x %u", map->first_ip, map->last_ip,
++ map->flags);
++
++ header->from = map->first_ip;
++ header->to = map->last_ip;
++ header->flags = map->flags;
++}
++
++static int list_members_size(const struct ip_set *set)
++{
++ struct ip_set_macipmap *map =
++ (struct ip_set_macipmap *) set->data;
++
++ DP("%u", members_size(map->first_ip, map->last_ip));
++ return members_size(map->first_ip, map->last_ip);
++}
++
++static void list_members(const struct ip_set *set, void *data)
++{
++ struct ip_set_macipmap *map =
++ (struct ip_set_macipmap *) set->data;
++
++ int bytes = members_size(map->first_ip, map->last_ip);
++
++ DP("members: %u %p", bytes, map->members);
++ memcpy(data, map->members, bytes);
++}
++
++static struct ip_set_type ip_set_macipmap = {
++ .typename = SETTYPE_NAME,
++ .typecode = IPSET_TYPE_IP,
++ .protocol_version = IP_SET_PROTOCOL_VERSION,
++ .create = &create,
++ .destroy = &destroy,
++ .flush = &flush,
++ .reqsize = sizeof(struct ip_set_req_macipmap),
++ .addip = &addip,
++ .addip_kernel = &addip_kernel,
++ .delip = &delip,
++ .delip_kernel = &delip_kernel,
++ .testip = &testip,
++ .testip_kernel = &testip_kernel,
++ .header_size = sizeof(struct ip_set_req_macipmap_create),
++ .list_header = &list_header,
++ .list_members_size = &list_members_size,
++ .list_members = &list_members,
++ .me = THIS_MODULE,
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("macipmap type of IP sets");
++
++static int __init init(void)
++{
++ return ip_set_register_set_type(&ip_set_macipmap);
++}
++
++static void __exit fini(void)
++{
++ /* FIXME: possible race with ip_set_create() */
++ ip_set_unregister_set_type(&ip_set_macipmap);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Naur linux-old/net/ipv4/netfilter/ip_set_nethash.c linux-new/net/ipv4/netfilter/ip_set_nethash.c
+--- linux-old/net/ipv4/netfilter/ip_set_nethash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/net/ipv4/netfilter/ip_set_nethash.c 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,450 @@
++/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* Kernel module implementing a cidr nethash set */
++
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ip_set.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <asm/softirq.h>
++#include <linux/spinlock.h>
++#include <linux/vmalloc.h>
++#include <linux/random.h>
++
++#include <net/ip.h>
++
++#include <linux/netfilter_ipv4/ip_set_malloc.h>
++#include <linux/netfilter_ipv4/ip_set_nethash.h>
++#include <linux/netfilter_ipv4/ip_set_jhash.h>
++#include <linux/netfilter_ipv4/ip_set_prime.h>
++
++static inline __u32
++jhash_ip(const struct ip_set_nethash *map, ip_set_ip_t ip)
++{
++ return jhash_1word(ip, map->initval);
++}
++
++static inline __u32
++randhash_ip(const struct ip_set_nethash *map, ip_set_ip_t ip)
++{
++ return (1 + ip % map->prime);
++}
++
++static inline __u32
++hash_id_cidr(struct ip_set_nethash *map,
++ ip_set_ip_t ip,
++ unsigned char cidr,
++ ip_set_ip_t *hash_ip)
++{
++ __u32 jhash, randhash, id;
++ u_int16_t i;
++
++ *hash_ip = pack(ip, cidr);
++ jhash = jhash_ip(map, *hash_ip);
++ randhash = randhash_ip(map, *hash_ip);
++
++ for (i = 0; i < map->probes; i++) {
++ id = (jhash + i * randhash) % map->hashsize;
++ DP("hash key: %u", id);
++ if (map->members[id] == *hash_ip)
++ return id;
++ }
++ return UINT_MAX;
++}
++
++static inline __u32
++hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++ __u32 id = UINT_MAX;
++ int i;
++
++ for (i = 0; i < 30 && map->cidr[i]; i++) {
++ id = hash_id_cidr(map, ip, map->cidr[i], hash_ip);
++ if (id != UINT_MAX)
++ break;
++ }
++ return id;
++}
++
++static inline int
++__testip_cidr(struct ip_set *set, ip_set_ip_t ip, unsigned char cidr,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++
++ return (hash_id_cidr(map, ip, cidr, hash_ip) != UINT_MAX);
++}
++
++static inline int
++__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ return (hash_id(set, ip, hash_ip) != UINT_MAX);
++}
++
++static int
++testip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_nethash *req =
++ (struct ip_set_req_nethash *) data;
++
++ if (size != sizeof(struct ip_set_req_nethash)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_nethash),
++ size);
++ return -EINVAL;
++ }
++ return (req->cidr == 32 ? __testip(set, req->ip, hash_ip)
++ : __testip_cidr(set, req->ip, req->cidr, hash_ip));
++}
++
++static int
++testip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ return __testip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++}
++
++static inline int
++__addip_base(struct ip_set_nethash *map, ip_set_ip_t ip)
++{
++ __u32 jhash, randhash, probe;
++ u_int16_t i;
++
++ jhash = jhash_ip(map, ip);
++ randhash = randhash_ip(map, ip);
++
++ for (i = 0; i < map->probes; i++) {
++ probe = (jhash + i * randhash) % map->hashsize;
++ if (map->members[probe] == ip)
++ return -EEXIST;
++ if (!map->members[probe]) {
++ map->members[probe] = ip;
++ return 0;
++ }
++ }
++ /* Trigger rehashing */
++ return -EAGAIN;
++}
++
++static inline int
++__addip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
++ ip_set_ip_t *hash_ip)
++{
++ *hash_ip = pack(ip, cidr);
++ DP("%u.%u.%u.%u/%u, %u.%u.%u.%u", HIPQUAD(ip), cidr, HIPQUAD(*hash_ip));
++
++ return __addip_base(map, *hash_ip);
++}
++
++static void
++update_cidr_sizes(struct ip_set_nethash *map, unsigned char cidr)
++{
++ unsigned char next;
++ int i;
++
++ for (i = 0; i < 30 && map->cidr[i]; i++) {
++ if (map->cidr[i] == cidr) {
++ return;
++ } else if (map->cidr[i] < cidr) {
++ next = map->cidr[i];
++ map->cidr[i] = cidr;
++ cidr = next;
++ }
++ }
++ if (i < 30)
++ map->cidr[i] = cidr;
++}
++
++static int
++addip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_nethash *req =
++ (struct ip_set_req_nethash *) data;
++ int ret;
++
++ if (size != sizeof(struct ip_set_req_nethash)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_nethash),
++ size);
++ return -EINVAL;
++ }
++ ret = __addip((struct ip_set_nethash *) set->data,
++ req->ip, req->cidr, hash_ip);
++
++ if (ret == 0)
++ update_cidr_sizes((struct ip_set_nethash *) set->data,
++ req->cidr);
++
++ return ret;
++}
++
++static int
++addip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++ int ret = -ERANGE;
++ ip_set_ip_t ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr);
++
++ if (map->cidr[0])
++ ret = __addip(map, ip, map->cidr[0], hash_ip);
++
++ return ret;
++}
++
++static int retry(struct ip_set *set)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++ ip_set_ip_t *members;
++ u_int32_t i, hashsize;
++ unsigned newbytes;
++ int res;
++ struct ip_set_nethash tmp = {
++ .hashsize = map->hashsize,
++ .probes = map->probes,
++ .resize = map->resize
++ };
++
++ if (map->resize == 0)
++ return -ERANGE;
++
++ memcpy(tmp.cidr, map->cidr, 30 * sizeof(unsigned char));
++ again:
++ res = 0;
++
++ /* Calculate new parameters */
++ get_random_bytes(&tmp.initval, 4);
++ hashsize = tmp.hashsize + (tmp.hashsize * map->resize)/100;
++ if (hashsize == tmp.hashsize)
++ hashsize++;
++ tmp.prime = make_prime(hashsize);
++
++ ip_set_printk("rehashing of set %s triggered: "
++ "hashsize grows from %u to %u",
++ set->name, tmp.hashsize, hashsize);
++ tmp.hashsize = hashsize;
++
++ newbytes = hashsize * sizeof(ip_set_ip_t);
++ tmp.members = ip_set_malloc(newbytes);
++ if (!tmp.members) {
++ DP("out of memory for %d bytes", newbytes);
++ return -ENOMEM;
++ }
++ memset(tmp.members, 0, newbytes);
++
++ write_lock_bh(&set->lock);
++ map = (struct ip_set_nethash *) set->data; /* Play safe */
++ for (i = 0; i < map->hashsize && res == 0; i++) {
++ if (map->members[i])
++ res = __addip_base(&tmp, map->members[i]);
++ }
++ if (res) {
++ /* Failure, try again */
++ write_unlock_bh(&set->lock);
++ ip_set_free(tmp.members, newbytes);
++ goto again;
++ }
++
++ /* Success at resizing! */
++ members = map->members;
++ hashsize = map->hashsize;
++
++ map->initval = tmp.initval;
++ map->prime = tmp.prime;
++ map->hashsize = tmp.hashsize;
++ map->members = tmp.members;
++ write_unlock_bh(&set->lock);
++
++ ip_set_free(members, hashsize * sizeof(ip_set_ip_t));
++
++ return 0;
++}
++
++static inline int
++__delip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
++ ip_set_ip_t *hash_ip)
++{
++ ip_set_ip_t id = hash_id_cidr(map, ip, cidr, hash_ip);
++
++ if (id == UINT_MAX)
++ return -EEXIST;
++
++ map->members[id] = 0;
++ return 0;
++}
++
++static int
++delip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_nethash *req =
++ (struct ip_set_req_nethash *) data;
++
++ if (size != sizeof(struct ip_set_req_nethash)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_nethash),
++ size);
++ return -EINVAL;
++ }
++ /* TODO: no garbage collection in map->cidr */
++ return __delip((struct ip_set_nethash *) set->data,
++ req->ip, req->cidr, hash_ip);
++}
++
++static int
++delip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++ int ret = -ERANGE;
++ ip_set_ip_t ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr);
++
++ if (map->cidr[0])
++ ret = __delip(map, ip, map->cidr[0], hash_ip);
++
++ return ret;
++}
++
++static int create(struct ip_set *set, const void *data, size_t size)
++{
++ unsigned newbytes;
++ struct ip_set_req_nethash_create *req =
++ (struct ip_set_req_nethash_create *) data;
++ struct ip_set_nethash *map;
++
++ if (size != sizeof(struct ip_set_req_nethash_create)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_nethash_create),
++ size);
++ return -EINVAL;
++ }
++
++ if (req->hashsize < 1) {
++ ip_set_printk("hashsize too small");
++ return -ENOEXEC;
++ }
++
++ map = kmalloc(sizeof(struct ip_set_nethash), GFP_KERNEL);
++ if (!map) {
++ DP("out of memory for %d bytes",
++ sizeof(struct ip_set_nethash));
++ return -ENOMEM;
++ }
++ get_random_bytes(&map->initval, 4);
++ map->prime = make_prime(req->hashsize);
++ map->hashsize = req->hashsize;
++ map->probes = req->probes;
++ map->resize = req->resize;
++ memset(map->cidr, 0, 30 * sizeof(unsigned char));
++ newbytes = map->hashsize * sizeof(ip_set_ip_t);
++ map->members = ip_set_malloc(newbytes);
++ if (!map->members) {
++ DP("out of memory for %d bytes", newbytes);
++ kfree(map);
++ return -ENOMEM;
++ }
++ memset(map->members, 0, newbytes);
++
++ set->data = map;
++ return 0;
++}
++
++static void destroy(struct ip_set *set)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++
++ ip_set_free(map->members, map->hashsize * sizeof(ip_set_ip_t));
++ kfree(map);
++
++ set->data = NULL;
++}
++
++static void flush(struct ip_set *set)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++ memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
++ memset(map->cidr, 0, 30 * sizeof(unsigned char));
++}
++
++static void list_header(const struct ip_set *set, void *data)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++ struct ip_set_req_nethash_create *header =
++ (struct ip_set_req_nethash_create *) data;
++
++ header->hashsize = map->hashsize;
++ header->probes = map->probes;
++ header->resize = map->resize;
++}
++
++static int list_members_size(const struct ip_set *set)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++
++ return (map->hashsize * sizeof(ip_set_ip_t));
++}
++
++static void list_members(const struct ip_set *set, void *data)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++ int bytes = map->hashsize * sizeof(ip_set_ip_t);
++
++ memcpy(data, map->members, bytes);
++}
++
++static struct ip_set_type ip_set_nethash = {
++ .typename = SETTYPE_NAME,
++ .typecode = IPSET_TYPE_IP,
++ .protocol_version = IP_SET_PROTOCOL_VERSION,
++ .create = &create,
++ .destroy = &destroy,
++ .flush = &flush,
++ .reqsize = sizeof(struct ip_set_req_nethash),
++ .addip = &addip,
++ .addip_kernel = &addip_kernel,
++ .retry = &retry,
++ .delip = &delip,
++ .delip_kernel = &delip_kernel,
++ .testip = &testip,
++ .testip_kernel = &testip_kernel,
++ .header_size = sizeof(struct ip_set_req_nethash_create),
++ .list_header = &list_header,
++ .list_members_size = &list_members_size,
++ .list_members = &list_members,
++ .me = THIS_MODULE,
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("nethash type of IP sets");
++
++static int __init init(void)
++{
++ return ip_set_register_set_type(&ip_set_nethash);
++}
++
++static void __exit fini(void)
++{
++ /* FIXME: possible race with ip_set_create() */
++ ip_set_unregister_set_type(&ip_set_nethash);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Naur linux-old/net/ipv4/netfilter/ip_set_portmap.c linux-new/net/ipv4/netfilter/ip_set_portmap.c
+--- linux-old/net/ipv4/netfilter/ip_set_portmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/net/ipv4/netfilter/ip_set_portmap.c 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,321 @@
++/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* Kernel module implementing a port set type as a bitmap */
++
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/udp.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ip_set.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <asm/softirq.h>
++#include <linux/spinlock.h>
++
++#include <net/ip.h>
++
++#include <linux/netfilter_ipv4/ip_set_portmap.h>
++
++static inline ip_set_ip_t
++get_port(const struct sk_buff *skb, u_int32_t flags)
++{
++ struct iphdr *iph = skb->nh.iph;
++ u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
++
++ switch (iph->protocol) {
++ case IPPROTO_TCP: {
++ struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
++
++ /* See comments at tcp_match in ip_tables.c */
++ if (offset != 0
++ || (offset == 0
++ && (skb->len - iph->ihl * 4) < sizeof(struct tcphdr)))
++ return INVALID_PORT;
++
++ return ntohs(flags & IPSET_SRC ?
++ tcph->source : tcph->dest);
++ }
++ case IPPROTO_UDP: {
++ struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
++
++ if (offset != 0
++ || (offset == 0
++ && (skb->len - iph->ihl * 4) < sizeof(struct udphdr)))
++ return INVALID_PORT;
++
++ return ntohs(flags & IPSET_SRC ?
++ udph->source : udph->dest);
++ }
++ default:
++ return INVALID_PORT;
++ }
++}
++
++static inline int
++__testport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
++{
++ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
++
++ if (port < map->first_port || port > map->last_port)
++ return -ERANGE;
++
++ *hash_port = port;
++ DP("set: %s, port:%u, %u", set->name, port, *hash_port);
++ return !!test_bit(port - map->first_port, map->members);
++}
++
++static int
++testport(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_port)
++{
++ struct ip_set_req_portmap *req =
++ (struct ip_set_req_portmap *) data;
++
++ if (size != sizeof(struct ip_set_req_portmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_portmap),
++ size);
++ return -EINVAL;
++ }
++ return __testport(set, req->port, hash_port);
++}
++
++static int
++testport_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_port)
++{
++ int res;
++ ip_set_ip_t port = get_port(skb, flags);
++
++ DP("flag %s port %u", flags & IPSET_SRC ? "SRC" : "DST", port);
++ if (port == INVALID_PORT)
++ return 0;
++
++ res = __testport(set, port, hash_port);
++
++ return (res < 0 ? 0 : res);
++}
++
++static inline int
++__addport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
++{
++ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
++
++ if (port < map->first_port || port > map->last_port)
++ return -ERANGE;
++ if (test_and_set_bit(port - map->first_port, map->members))
++ return -EEXIST;
++
++ *hash_port = port;
++ DP("port %u", port);
++ return 0;
++}
++
++static int
++addport(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_port)
++{
++ struct ip_set_req_portmap *req =
++ (struct ip_set_req_portmap *) data;
++
++ if (size != sizeof(struct ip_set_req_portmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_portmap),
++ size);
++ return -EINVAL;
++ }
++ return __addport(set, req->port, hash_port);
++}
++
++static int
++addport_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_port)
++{
++ ip_set_ip_t port = get_port(skb, flags);
++
++ if (port == INVALID_PORT)
++ return -EINVAL;
++
++ return __addport(set, port, hash_port);
++}
++
++static inline int
++__delport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
++{
++ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
++
++ if (port < map->first_port || port > map->last_port)
++ return -ERANGE;
++ if (!test_and_clear_bit(port - map->first_port, map->members))
++ return -EEXIST;
++
++ *hash_port = port;
++ DP("port %u", port);
++ return 0;
++}
++
++static int
++delport(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_port)
++{
++ struct ip_set_req_portmap *req =
++ (struct ip_set_req_portmap *) data;
++
++ if (size != sizeof(struct ip_set_req_portmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_portmap),
++ size);
++ return -EINVAL;
++ }
++ return __delport(set, req->port, hash_port);
++}
++
++static int
++delport_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_port)
++{
++ ip_set_ip_t port = get_port(skb, flags);
++
++ if (port == INVALID_PORT)
++ return -EINVAL;
++
++ return __delport(set, port, hash_port);
++}
++
++static int create(struct ip_set *set, const void *data, size_t size)
++{
++ int newbytes;
++ struct ip_set_req_portmap_create *req =
++ (struct ip_set_req_portmap_create *) data;
++ struct ip_set_portmap *map;
++
++ if (size != sizeof(struct ip_set_req_portmap_create)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_portmap_create),
++ size);
++ return -EINVAL;
++ }
++
++ DP("from %u to %u", req->from, req->to);
++
++ if (req->from > req->to) {
++ DP("bad port range");
++ return -ENOEXEC;
++ }
++
++ if (req->to - req->from > MAX_RANGE) {
++ ip_set_printk("range too big (max %d ports)",
++ MAX_RANGE);
++ return -ENOEXEC;
++ }
++
++ map = kmalloc(sizeof(struct ip_set_portmap), GFP_KERNEL);
++ if (!map) {
++ DP("out of memory for %d bytes",
++ sizeof(struct ip_set_portmap));
++ return -ENOMEM;
++ }
++ map->first_port = req->from;
++ map->last_port = req->to;
++ newbytes = bitmap_bytes(req->from, req->to);
++ map->members = kmalloc(newbytes, GFP_KERNEL);
++ if (!map->members) {
++ DP("out of memory for %d bytes", newbytes);
++ kfree(map);
++ return -ENOMEM;
++ }
++ memset(map->members, 0, newbytes);
++
++ set->data = map;
++ return 0;
++}
++
++static void destroy(struct ip_set *set)
++{
++ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
++
++ kfree(map->members);
++ kfree(map);
++
++ set->data = NULL;
++}
++
++static void flush(struct ip_set *set)
++{
++ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
++ memset(map->members, 0, bitmap_bytes(map->first_port, map->last_port));
++}
++
++static void list_header(const struct ip_set *set, void *data)
++{
++ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
++ struct ip_set_req_portmap_create *header =
++ (struct ip_set_req_portmap_create *) data;
++
++ DP("list_header %u %u", map->first_port, map->last_port);
++
++ header->from = map->first_port;
++ header->to = map->last_port;
++}
++
++static int list_members_size(const struct ip_set *set)
++{
++ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
++
++ return bitmap_bytes(map->first_port, map->last_port);
++}
++
++static void list_members(const struct ip_set *set, void *data)
++{
++ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
++ int bytes = bitmap_bytes(map->first_port, map->last_port);
++
++ memcpy(data, map->members, bytes);
++}
++
++static struct ip_set_type ip_set_portmap = {
++ .typename = SETTYPE_NAME,
++ .typecode = IPSET_TYPE_PORT,
++ .protocol_version = IP_SET_PROTOCOL_VERSION,
++ .create = &create,
++ .destroy = &destroy,
++ .flush = &flush,
++ .reqsize = sizeof(struct ip_set_req_portmap),
++ .addip = &addport,
++ .addip_kernel = &addport_kernel,
++ .delip = &delport,
++ .delip_kernel = &delport_kernel,
++ .testip = &testport,
++ .testip_kernel = &testport_kernel,
++ .header_size = sizeof(struct ip_set_req_portmap_create),
++ .list_header = &list_header,
++ .list_members_size = &list_members_size,
++ .list_members = &list_members,
++ .me = THIS_MODULE,
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("portmap type of IP sets");
++
++static int __init init(void)
++{
++ return ip_set_register_set_type(&ip_set_portmap);
++}
++
++static void __exit fini(void)
++{
++ /* FIXME: possible race with ip_set_create() */
++ ip_set_unregister_set_type(&ip_set_portmap);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Naur linux-old/net/ipv4/netfilter/ipt_set.c linux-new/net/ipv4/netfilter/ipt_set.c
+--- linux-old/net/ipv4/netfilter/ipt_set.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/net/ipv4/netfilter/ipt_set.c 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,114 @@
++/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
++ * Patrick Schaaf <bof@bof.de>
++ * Martin Josefsson <gandalf@wlug.westbo.se>
++ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* Kernel module to match an IP set. */
++
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ip_set.h>
++#include <linux/netfilter_ipv4/ipt_set.h>
++
++static inline int
++match_set(const struct ipt_set_info *info,
++ const struct sk_buff *skb,
++ int inv)
++{
++ if (ip_set_testip_kernel(info->index, skb, info->flags))
++ inv = !inv;
++ return inv;
++}
++
++static int
++match(const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *matchinfo,
++ int offset,
++ const void *hdr,
++ u_int16_t datalen,
++ int *hotdrop)
++{
++ const struct ipt_set_info_match *info = matchinfo;
++
++ return match_set(&info->match_set,
++ skb,
++ info->match_set.flags[0] & IPSET_MATCH_INV);
++}
++
++static int
++checkentry(const char *tablename,
++ const struct ipt_ip *ip,
++ void *matchinfo,
++ unsigned int matchsize,
++ unsigned int hook_mask)
++{
++ struct ipt_set_info_match *info =
++ (struct ipt_set_info_match *) matchinfo;
++ ip_set_id_t index;
++
++ if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) {
++ ip_set_printk("invalid matchsize %d", matchsize);
++ return 0;
++ }
++
++ index = ip_set_get_byindex(info->match_set.index);
++
++ if (index == IP_SET_INVALID_ID) {
++ ip_set_printk("Cannot find set indentified by id %u to match",
++ info->match_set.index);
++ return 0; /* error */
++ }
++ if (info->match_set.flags[IP_SET_MAX_BINDINGS] != 0) {
++ ip_set_printk("That's nasty!");
++ return 0; /* error */
++ }
++
++ return 1;
++}
++
++static void destroy(void *matchinfo, unsigned int matchsize)
++{
++ struct ipt_set_info_match *info = matchinfo;
++
++ if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) {
++ ip_set_printk("invalid matchsize %d", matchsize);
++ return;
++ }
++
++ ip_set_put(info->match_set.index);
++}
++
++static struct ipt_match set_match = {
++ .name = "set",
++ .match = &match,
++ .checkentry = &checkentry,
++ .destroy = &destroy,
++ .me = THIS_MODULE
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("iptables IP set match module");
++
++static int __init init(void)
++{
++ return ipt_register_match(&set_match);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_match(&set_match);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Naur linux-old/net/ipv4/netfilter/ipt_SET.c linux-new/net/ipv4/netfilter/ipt_SET.c
+--- linux-old/net/ipv4/netfilter/ipt_SET.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-new/net/ipv4/netfilter/ipt_SET.c 2005-08-10 22:13:00.000000000 +0200
+@@ -0,0 +1,127 @@
++/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
++ * Patrick Schaaf <bof@bof.de>
++ * Martin Josefsson <gandalf@wlug.westbo.se>
++ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* ipt_SET.c - netfilter target to manipulate IP sets */
++
++#include <linux/types.h>
++#include <linux/ip.h>
++#include <linux/timer.h>
++#include <linux/module.h>
++#include <linux/netfilter.h>
++#include <linux/netdevice.h>
++#include <linux/if.h>
++#include <linux/inetdevice.h>
++#include <net/protocol.h>
++#include <net/checksum.h>
++#include <linux/netfilter_ipv4.h>
++#include <linux/netfilter_ipv4/ip_nat_rule.h>
++#include <linux/netfilter_ipv4/ipt_set.h>
++
++static unsigned int
++target(struct sk_buff **pskb,
++ unsigned int hooknum,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *targinfo,
++ void *userinfo)
++{
++ const struct ipt_set_info_target *info = targinfo;
++
++ if (info->add_set.index != IP_SET_INVALID_ID)
++ ip_set_addip_kernel(info->add_set.index,
++ *pskb,
++ info->add_set.flags);
++ if (info->del_set.index != IP_SET_INVALID_ID)
++ ip_set_delip_kernel(info->del_set.index,
++ *pskb,
++ info->del_set.flags);
++
++ return IPT_CONTINUE;
++}
++
++static int
++checkentry(const char *tablename,
++ const struct ipt_entry *e,
++ void *targinfo,
++ unsigned int targinfosize, unsigned int hook_mask)
++{
++ struct ipt_set_info_target *info =
++ (struct ipt_set_info_target *) targinfo;
++ ip_set_id_t index;
++
++ if (targinfosize != IPT_ALIGN(sizeof(*info))) {
++ DP("bad target info size %u", targinfosize);
++ return 0;
++ }
++
++ if (info->add_set.index != IP_SET_INVALID_ID) {
++ index = ip_set_get_byindex(info->add_set.index);
++ if (index == IP_SET_INVALID_ID) {
++ ip_set_printk("cannot find add_set index %u as target",
++ info->add_set.index);
++ return 0; /* error */
++ }
++ }
++
++ if (info->del_set.index != IP_SET_INVALID_ID) {
++ index = ip_set_get_byindex(info->del_set.index);
++ if (index == IP_SET_INVALID_ID) {
++ ip_set_printk("cannot find del_set index %u as target",
++ info->del_set.index);
++ return 0; /* error */
++ }
++ }
++ if (info->add_set.flags[IP_SET_MAX_BINDINGS] != 0
++ || info->del_set.flags[IP_SET_MAX_BINDINGS] != 0) {
++ ip_set_printk("That's nasty!");
++ return 0; /* error */
++ }
++ return 1;
++}
++
++static void destroy(void *targetinfo, unsigned int targetsize)
++{
++ struct ipt_set_info_target *info = targetinfo;
++
++ if (targetsize != IPT_ALIGN(sizeof(struct ipt_set_info_target))) {
++ ip_set_printk("invalid targetsize %d", targetsize);
++ return;
++ }
++
++ if (info->add_set.index != IP_SET_INVALID_ID)
++ ip_set_put(info->add_set.index);
++ if (info->del_set.index != IP_SET_INVALID_ID)
++ ip_set_put(info->del_set.index);
++}
++
++static struct ipt_target SET_target = {
++ .name = "SET",
++ .target = target,
++ .checkentry = checkentry,
++ .destroy = destroy,
++ .me = THIS_MODULE
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("iptables IP set target module");
++
++static int __init init(void)
++{
++ return ipt_register_target(&SET_target);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_target(&SET_target);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Naur linux-old/net/ipv4/netfilter/Makefile linux-new/net/ipv4/netfilter/Makefile
+--- linux-old/net/ipv4/netfilter/Makefile 2005-07-23 23:34:46.000000000 +0200
++++ linux-new/net/ipv4/netfilter/Makefile 2005-08-10 22:13:01.000000000 +0200
+@@ -75,6 +75,18 @@
+ obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
+ obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
+ obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
++obj-$(CONFIG_IP_NF_MATCH_SET) += ipt_set.o
++obj-$(CONFIG_IP_NF_TARGET_SET) += ipt_SET.o
++ifdef CONFIG_IP_NF_SET
++ obj-$(CONFIG_IP_NF_SET) += ip_set.o
++ export-objs += ip_set.o
++endif
++obj-$(CONFIG_IP_NF_SET_IPMAP) += ip_set_ipmap.o
++obj-$(CONFIG_IP_NF_SET_PORTMAP) += ip_set_portmap.o
++obj-$(CONFIG_IP_NF_SET_MACIPMAP) += ip_set_macipmap.o
++obj-$(CONFIG_IP_NF_SET_IPHASH) += ip_set_iphash.o
++obj-$(CONFIG_IP_NF_SET_NETHASH) += ip_set_nethash.o
++obj-$(CONFIG_IP_NF_SET_IPTREE) += ip_set_iptree.o
+ obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
+ obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o
+
diff --git a/target/linux/generic-2.4/patches/609-netfilter_string.patch b/target/linux/generic-2.4/patches/609-netfilter_string.patch
new file mode 100644
index 0000000000..c8e1a2d2de
--- /dev/null
+++ b/target/linux/generic-2.4/patches/609-netfilter_string.patch
@@ -0,0 +1,348 @@
+diff -Nur linux-2.4.32/include/linux/netfilter_ipv4/ipt_string.h linux-2.4.32.patch/include/linux/netfilter_ipv4/ipt_string.h
+--- linux-2.4.32/include/linux/netfilter_ipv4/ipt_string.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32.patch/include/linux/netfilter_ipv4/ipt_string.h 2005-12-16 00:40:19.082509250 +0100
+@@ -0,0 +1,18 @@
++#ifndef _IPT_STRING_H
++#define _IPT_STRING_H
++
++#define IPT_STRING_MAX_PATTERN_SIZE 128
++#define IPT_STRING_MAX_ALGO_NAME_SIZE 16
++
++struct ipt_string_info
++{
++ u_int16_t from_offset;
++ u_int16_t to_offset;
++ char algo[IPT_STRING_MAX_ALGO_NAME_SIZE];
++ char pattern[IPT_STRING_MAX_PATTERN_SIZE];
++ u_int8_t patlen;
++ u_int8_t invert;
++ struct ts_config __attribute__((aligned(8))) *config;
++};
++
++#endif /*_IPT_STRING_H*/
+diff -Nur linux-2.4.32/include/linux/textsearch.h linux-2.4.32.patch/include/linux/textsearch.h
+--- linux-2.4.32/include/linux/textsearch.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32.patch/include/linux/textsearch.h 2005-12-16 11:15:34.838073000 +0100
+@@ -0,0 +1,205 @@
++#ifndef __LINUX_TEXTSEARCH_H
++#define __LINUX_TEXTSEARCH_H
++
++#ifdef __KERNEL__
++
++#include <linux/types.h>
++#include <linux/list.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++
++#ifdef __CHECKER__
++#define __bitwise__ __attribute__((bitwise))
++#else
++#define __bitwise__
++#endif
++#ifdef __CHECK_ENDIAN__
++#define __bitwise __bitwise__
++#else
++#define __bitwise
++#endif
++
++typedef __u16 __bitwise __le16;
++typedef __u16 __bitwise __be16;
++typedef __u32 __bitwise __le32;
++typedef __u32 __bitwise __be32;
++#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
++typedef __u64 __bitwise __le64;
++typedef __u64 __bitwise __be64;
++#endif
++
++#ifdef __KERNEL__
++typedef unsigned __bitwise__ gfp_t;
++#endif
++
++struct ts_config;
++
++/**
++ * TS_AUTOLOAD - Automatically load textsearch modules when needed
++ */
++#define TS_AUTOLOAD 1
++
++/**
++ * struct ts_state - search state
++ * @offset: offset for next match
++ * @cb: control buffer, for persistant variables of get_next_block()
++ */
++struct ts_state
++{
++ unsigned int offset;
++ char cb[40];
++};
++
++/**
++ * struct ts_ops - search module operations
++ * @name: name of search algorithm
++ * @init: initialization function to prepare a search
++ * @find: find the next occurrence of the pattern
++ * @destroy: destroy algorithm specific parts of a search configuration
++ * @get_pattern: return head of pattern
++ * @get_pattern_len: return length of pattern
++ * @owner: module reference to algorithm
++ */
++struct ts_ops
++{
++ const char *name;
++ struct ts_config * (*init)(const void *, unsigned int, gfp_t);
++ unsigned int (*find)(struct ts_config *,
++ struct ts_state *);
++ void (*destroy)(struct ts_config *);
++ void * (*get_pattern)(struct ts_config *);
++ unsigned int (*get_pattern_len)(struct ts_config *);
++ struct module *owner;
++ struct list_head list;
++};
++
++/**
++ * struct ts_config - search configuration
++ * @ops: operations of chosen algorithm
++ * @get_next_block: callback to fetch the next block to search in
++ * @finish: callback to finalize a search
++ */
++struct ts_config
++{
++ struct ts_ops *ops;
++
++ /**
++ * get_next_block - fetch next block of data
++ * @consumed: number of bytes consumed by the caller
++ * @dst: destination buffer
++ * @conf: search configuration
++ * @state: search state
++ *
++ * Called repeatedly until 0 is returned. Must assign the
++ * head of the next block of data to &*dst and return the length
++ * of the block or 0 if at the end. consumed == 0 indicates
++ * a new search. May store/read persistant values in state->cb.
++ */
++ unsigned int (*get_next_block)(unsigned int consumed,
++ const u8 **dst,
++ struct ts_config *conf,
++ struct ts_state *state);
++
++ /**
++ * finish - finalize/clean a series of get_next_block() calls
++ * @conf: search configuration
++ * @state: search state
++ *
++ * Called after the last use of get_next_block(), may be used
++ * to cleanup any leftovers.
++ */
++ void (*finish)(struct ts_config *conf,
++ struct ts_state *state);
++};
++
++/**
++ * textsearch_next - continue searching for a pattern
++ * @conf: search configuration
++ * @state: search state
++ *
++ * Continues a search looking for more occurrences of the pattern.
++ * textsearch_find() must be called to find the first occurrence
++ * in order to reset the state.
++ *
++ * Returns the position of the next occurrence of the pattern or
++ * UINT_MAX if not match was found.
++ */
++static inline unsigned int textsearch_next(struct ts_config *conf,
++ struct ts_state *state)
++{
++ unsigned int ret = conf->ops->find(conf, state);
++
++ if (conf->finish)
++ conf->finish(conf, state);
++
++ return ret;
++}
++
++/**
++ * textsearch_find - start searching for a pattern
++ * @conf: search configuration
++ * @state: search state
++ *
++ * Returns the position of first occurrence of the pattern or
++ * UINT_MAX if no match was found.
++ */
++static inline unsigned int textsearch_find(struct ts_config *conf,
++ struct ts_state *state)
++{
++ state->offset = 0;
++ return textsearch_next(conf, state);
++}
++
++/**
++ * textsearch_get_pattern - return head of the pattern
++ * @conf: search configuration
++ */
++static inline void *textsearch_get_pattern(struct ts_config *conf)
++{
++ return conf->ops->get_pattern(conf);
++}
++
++/**
++ * textsearch_get_pattern_len - return length of the pattern
++ * @conf: search configuration
++ */
++static inline unsigned int textsearch_get_pattern_len(struct ts_config *conf)
++{
++ return conf->ops->get_pattern_len(conf);
++}
++
++extern int textsearch_register(struct ts_ops *);
++extern int textsearch_unregister(struct ts_ops *);
++extern struct ts_config *textsearch_prepare(const char *, const void *,
++ unsigned int, gfp_t, int);
++extern void textsearch_destroy(struct ts_config *conf);
++extern unsigned int textsearch_find_continuous(struct ts_config *,
++ struct ts_state *,
++ const void *, unsigned int);
++
++
++#define TS_PRIV_ALIGNTO 8
++#define TS_PRIV_ALIGN(len) (((len) + TS_PRIV_ALIGNTO-1) & ~(TS_PRIV_ALIGNTO-1))
++
++static inline struct ts_config *alloc_ts_config(size_t payload,
++ gfp_t gfp_mask)
++{
++ struct ts_config *conf;
++
++ conf = kmalloc(TS_PRIV_ALIGN(sizeof(*conf)) + payload, gfp_mask);
++ if (conf == NULL)
++ return -ENOMEM;
++
++ memset(conf, 0, TS_PRIV_ALIGN(sizeof(*conf)) + payload);
++ return conf;
++}
++
++static inline void *ts_config_priv(struct ts_config *conf)
++{
++ return ((u8 *) conf + TS_PRIV_ALIGN(sizeof(struct ts_config)));
++}
++
++#endif /* __KERNEL__ */
++
++#endif
+diff -Nur linux-2.4.32/net/ipv4/netfilter/Config.in linux-2.4.32.patch/net/ipv4/netfilter/Config.in
+--- linux-2.4.32/net/ipv4/netfilter/Config.in 2005-01-19 15:10:13.000000000 +0100
++++ linux-2.4.32.patch/net/ipv4/netfilter/Config.in 2005-12-16 00:41:43.023755250 +0100
+@@ -42,6 +42,7 @@
+ fi
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ dep_tristate ' Unclean match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_UNCLEAN $CONFIG_IP_NF_IPTABLES
++ dep_tristate ' String match support (EXPERIMENTAL) ' CONFIG_IP_NF_MATCH_STRING $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' Owner match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_OWNER $CONFIG_IP_NF_IPTABLES
+ fi
+ # The targets
+diff -Nur linux-2.4.32/net/ipv4/netfilter/ipt_string.c linux-2.4.32.patch/net/ipv4/netfilter/ipt_string.c
+--- linux-2.4.32/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32.patch/net/ipv4/netfilter/ipt_string.c 2005-12-16 00:40:48.436343750 +0100
+@@ -0,0 +1,91 @@
++/* String matching match for iptables
++ *
++ * (C) 2005 Pablo Neira Ayuso <pablo@eurodev.net>
++ *
++ * 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/init.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_string.h>
++#include <linux/textsearch.h>
++
++MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>");
++MODULE_DESCRIPTION("IP tables string match module");
++MODULE_LICENSE("GPL");
++
++static int match(const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *matchinfo,
++ int offset,
++ int *hotdrop)
++{
++ struct ts_state state;
++ struct ipt_string_info *conf = (struct ipt_string_info *) matchinfo;
++
++ memset(&state, 0, sizeof(struct ts_state));
++
++ return (skb_find_text((struct sk_buff *)skb, conf->from_offset,
++ conf->to_offset, conf->config, &state)
++ != UINT_MAX) && !conf->invert;
++}
++
++#define STRING_TEXT_PRIV(m) ((struct ipt_string_info *) m)
++
++static int checkentry(const char *tablename,
++ const struct ipt_ip *ip,
++ void *matchinfo,
++ unsigned int matchsize,
++ unsigned int hook_mask)
++{
++ struct ipt_string_info *conf = matchinfo;
++ struct ts_config *ts_conf;
++
++ if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
++ return 0;
++
++ /* Damn, can't handle this case properly with iptables... */
++ if (conf->from_offset > conf->to_offset)
++ return 0;
++
++ ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen,
++ GFP_KERNEL, TS_AUTOLOAD);
++ if (IS_ERR(ts_conf))
++ return 0;
++
++ conf->config = ts_conf;
++
++ return 1;
++}
++
++static void destroy(void *matchinfo, unsigned int matchsize)
++{
++ textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config);
++}
++
++static struct ipt_match string_match = {
++ .name = "string",
++ .match = match,
++ .checkentry = checkentry,
++ .destroy = destroy,
++ .me = THIS_MODULE
++};
++
++static int __init init(void)
++{
++ return ipt_register_match(&string_match);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_match(&string_match);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Nur linux-2.4.32/net/ipv4/netfilter/Makefile linux-2.4.32.patch/net/ipv4/netfilter/Makefile
+--- linux-2.4.32/net/ipv4/netfilter/Makefile 2003-08-25 13:44:44.000000000 +0200
++++ linux-2.4.32.patch/net/ipv4/netfilter/Makefile 2005-12-16 00:42:10.929499250 +0100
+@@ -85,6 +85,7 @@
+ obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
+ obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
+ obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
++obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
+ obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
+
+ # targets
diff --git a/target/linux/generic-2.4/patches/610-netfilter_connbytes.patch b/target/linux/generic-2.4/patches/610-netfilter_connbytes.patch
new file mode 100644
index 0000000000..95bc10f2bc
--- /dev/null
+++ b/target/linux/generic-2.4/patches/610-netfilter_connbytes.patch
@@ -0,0 +1,439 @@
+--- linux/net/ipv4/netfilter/Config.in.org 2005-11-13 15:53:59.457222512 +0100
++++ linux/net/ipv4/netfilter/Config.in 2005-11-13 15:56:25.241060000 +0100
+@@ -11,6 +11,8 @@
+ dep_tristate ' Amanda protocol support' CONFIG_IP_NF_AMANDA $CONFIG_IP_NF_CONNTRACK
+ dep_tristate ' TFTP protocol support' CONFIG_IP_NF_TFTP $CONFIG_IP_NF_CONNTRACK
+ dep_tristate ' IRC protocol support' CONFIG_IP_NF_IRC $CONFIG_IP_NF_CONNTRACK
++ dep_tristate ' Connection tracking flow accounting' CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK
++ dep_tristate ' Connection byte counter support' CONFIG_IP_NF_MATCH_CONNBYTES $CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' GRE protocol support' CONFIG_IP_NF_CT_PROTO_GRE $CONFIG_IP_NF_CONNTRACK
+ dep_tristate ' PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE
+ fi
+--- linux/net/ipv4/netfilter/Makefile.org 2005-11-12 16:48:38.000000000 +0100
++++ linux/net/ipv4/netfilter/Makefile 2005-11-13 15:56:38.663019552 +0100
+@@ -94,6 +94,7 @@
+ obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
+ obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
+ obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
++obj-$(CONFIG_IP_NF_MATCH_CONNBYTES) += ipt_connbytes.o
+ obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
+ obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
+ obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
+--- linux/net/ipv4/netfilter/ip_conntrack_amanda.c.org 2004-02-18 14:36:32.000000000 +0100
++++ linux/net/ipv4/netfilter/ip_conntrack_amanda.c 2005-11-13 15:40:00.000000000 +0100
+@@ -75,7 +75,7 @@
+
+ /* increase the UDP timeout of the master connection as replies from
+ * Amanda clients to the server can be quite delayed */
+- ip_ct_refresh(ct, master_timeout * HZ);
++ ip_ct_refresh_acct(ct,ctinfo,NULL, master_timeout * HZ);
+
+ /* Search for "CONNECT " string */
+ do {
+--- linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c.org 2003-11-28 19:26:21.000000000 +0100
++++ linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2005-11-13 15:45:41.045992536 +0100
+@@ -211,7 +211,7 @@
+ set_bit(IPS_ASSURED_BIT, &conntrack->status);
+
+ WRITE_UNLOCK(&tcp_lock);
+- ip_ct_refresh(conntrack, *tcp_timeouts[newconntrack]);
++ ip_ct_refresh_acct(conntrack,ctinfo,iph, *tcp_timeouts[newconntrack]);
+ }
+
+ return NF_ACCEPT;
+--- linux/net/ipv4/netfilter/ip_conntrack_proto_udp.c.org 2003-11-28 19:26:21.000000000 +0100
++++ linux/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2005-11-13 15:47:38.348159896 +0100
+@@ -47,16 +47,16 @@
+ /* Returns verdict for packet, and may modify conntracktype */
+ static int udp_packet(struct ip_conntrack *conntrack,
+ struct iphdr *iph, size_t len,
+- enum ip_conntrack_info conntrackinfo)
++ enum ip_conntrack_info ctinfo)
+ {
+ /* If we've seen traffic both ways, this is some kind of UDP
+ stream. Extend timeout. */
+ if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
+- ip_ct_refresh(conntrack, ip_ct_udp_timeout_stream);
++ ip_ct_refresh_acct(conntrack,ctinfo,iph,ip_ct_udp_timeout_stream);
+ /* Also, more likely to be important, and not a probe */
+ set_bit(IPS_ASSURED_BIT, &conntrack->status);
+ } else
+- ip_ct_refresh(conntrack, ip_ct_udp_timeout);
++ ip_ct_refresh_acct(conntrack,ctinfo,iph, ip_ct_udp_timeout);
+
+ return NF_ACCEPT;
+ }
+--- linux/net/ipv4/netfilter/ip_conntrack_standalone.c.org 2005-11-12 16:48:38.000000000 +0100
++++ linux/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-11-13 15:51:07.608347512 +0100
+@@ -79,6 +79,18 @@
+ return len;
+ }
+
++#if defined(CONFIG_IP_NF_CT_ACCT) || \
++ defined(CONFIG_IP_NF_CT_ACCT_MODULE)
++static unsigned int
++print_counters(char *buffer, struct ip_conntrack_counter *counter)
++{
++ return sprintf(buffer, "packets=%llu bytes=%llu ",
++ counter->packets, counter->bytes);
++}
++#else
++#define print_counters(x, y) 0
++#endif
++
+ static unsigned int
+ print_conntrack(char *buffer, struct ip_conntrack *conntrack)
+ {
+@@ -98,11 +110,15 @@
+ len += print_tuple(buffer + len,
+ &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+ proto);
++ len += print_counters(buffer + len,
++ &conntrack->counters[IP_CT_DIR_ORIGINAL]);
+ if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
+ len += sprintf(buffer + len, "[UNREPLIED] ");
+ len += print_tuple(buffer + len,
+ &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
+ proto);
++ len += print_counters(buffer + len,
++ &conntrack->counters[IP_CT_DIR_REPLY]);
+ if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
+ len += sprintf(buffer + len, "[ASSURED] ");
+ len += sprintf(buffer + len, "use=%u ",
+@@ -478,7 +494,7 @@
+ EXPORT_SYMBOL(ip_conntrack_helper_register);
+ EXPORT_SYMBOL(ip_conntrack_helper_unregister);
+ EXPORT_SYMBOL(ip_ct_iterate_cleanup);
+-EXPORT_SYMBOL(ip_ct_refresh);
++EXPORT_SYMBOL(ip_ct_refresh_acct);
+ EXPORT_SYMBOL(ip_ct_find_proto);
+ EXPORT_SYMBOL(__ip_ct_find_proto);
+ EXPORT_SYMBOL(ip_ct_find_helper);
+--- linux/net/ipv4/netfilter/ip_conntrack_proto_generic.c.org 2003-11-28 19:26:21.000000000 +0100
++++ linux/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2005-11-13 15:44:20.734201784 +0100
+@@ -41,9 +41,9 @@
+ /* Returns verdict for packet, or -1 for invalid. */
+ static int established(struct ip_conntrack *conntrack,
+ struct iphdr *iph, size_t len,
+- enum ip_conntrack_info conntrackinfo)
++ enum ip_conntrack_info ctinfo)
+ {
+- ip_ct_refresh(conntrack, ip_ct_generic_timeout);
++ ip_ct_refresh_acct(conntrack, ctinfo,iph,ip_ct_generic_timeout);
+ return NF_ACCEPT;
+ }
+
+--- linux/net/ipv4/netfilter/ip_conntrack_proto_icmp.c.org 2003-11-28 19:26:21.000000000 +0100
++++ linux/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2005-11-13 15:44:50.733641176 +0100
+@@ -82,7 +82,7 @@
+ ct->timeout.function((unsigned long)ct);
+ } else {
+ atomic_inc(&ct->proto.icmp.count);
+- ip_ct_refresh(ct, ip_ct_icmp_timeout);
++ ip_ct_refresh_acct(ct,ctinfo,iph, ip_ct_icmp_timeout);
+ }
+
+ return NF_ACCEPT;
+--- linux/net/ipv4/netfilter/ip_conntrack_core.c.org 2005-11-12 16:48:38.000000000 +0100
++++ linux/net/ipv4/netfilter/ip_conntrack_core.c 2005-11-13 15:43:23.882844504 +0100
+@@ -1196,22 +1196,40 @@
+
+ MOD_DEC_USE_COUNT;
+ }
++static inline void ct_add_counters(struct ip_conntrack *ct,
++ enum ip_conntrack_info ctinfo,
++ const struct iphdr *iph)
++{
++#if defined(CONFIG_IP_NF_CT_ACCT) || \
++ defined(CONFIG_IP_NF_CT_ACCT_MODULE)
++ if (iph) {
++ ct->counters[CTINFO2DIR(ctinfo)].packets++;
++ ct->counters[CTINFO2DIR(ctinfo)].bytes +=
++ ntohs(iph->tot_len);
++ }
++#endif
++}
+
+ /* Refresh conntrack for this many jiffies. */
+-void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
++void ip_ct_refresh_acct(struct ip_conntrack *ct,
++ enum ip_conntrack_info ctinfo,
++ const struct iphdr *iph,
++ unsigned long extra_jiffies)
+ {
+ IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
+
+ WRITE_LOCK(&ip_conntrack_lock);
+ /* If not in hash table, timer will not be active yet */
+- if (!is_confirmed(ct))
++ if (!is_confirmed(ct)) {
+ ct->timeout.expires = extra_jiffies;
+- else {
++ ct_add_counters(ct, ctinfo,iph);
++ } else {
+ /* Need del_timer for race avoidance (may already be dying). */
+ if (del_timer(&ct->timeout)) {
+ ct->timeout.expires = jiffies + extra_jiffies;
+ add_timer(&ct->timeout);
+ }
++ ct_add_counters(ct, ctinfo, iph);
+ }
+ WRITE_UNLOCK(&ip_conntrack_lock);
+ }
+--- linux/include/linux/netfilter_ipv4/ip_conntrack.h.org 2005-11-12 16:48:38.000000000 +0100
++++ linux/include/linux/netfilter_ipv4/ip_conntrack.h 2005-11-13 15:39:04.000000000 +0100
+@@ -164,6 +164,12 @@
+ union ip_conntrack_expect_help help;
+ };
+
++struct ip_conntrack_counter
++{
++ u_int64_t packets;
++ u_int64_t bytes;
++};
++
+ struct ip_conntrack_helper;
+
+ struct ip_conntrack
+@@ -181,6 +187,12 @@
+ /* Timer function; drops refcnt when it goes off. */
+ struct timer_list timeout;
+
++#if defined(CONFIG_IP_NF_CT_ACCT) || \
++ defined(CONFIG_IP_NF_CT_ACCT_MODULE)
++ /* Accounting Information (same cache line as other written members) */
++ struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
++#endif
++
+ /* If we're expecting another related connection, this will be
+ in expected linked list */
+ struct list_head sibling_list;
+@@ -264,8 +276,10 @@
+ const struct ip_conntrack_tuple *orig);
+
+ /* Refresh conntrack for this many jiffies */
+-extern void ip_ct_refresh(struct ip_conntrack *ct,
+- unsigned long extra_jiffies);
++extern void ip_ct_refresh_acct(struct ip_conntrack *ct,
++ enum ip_conntrack_info ctinfo,
++ const struct iphdr *iph,
++ unsigned long extra_jiffies);
+
+ /* These are for NAT. Icky. */
+ /* Call me when a conntrack is destroyed. */
+--- linux/net/ipv4/netfilter/ipt_connbytes.c.org 1970-01-01 01:00:00.000000000 +0100
++++ linux/net/ipv4/netfilter/ipt_connbytes.c 2005-11-13 16:22:02.021433872 +0100
+@@ -0,0 +1,163 @@
++/* Kernel module to match connection tracking byte counter.
++ * GPL (C) 2002 Martin Devera (devik@cdi.cz).
++ *
++ * 2004-07-20 Harald Welte <laforge at netfilter.org>
++ * - reimplemented to use per-connection accounting counters
++ * - add functionality to match number of packets
++ * - add functionality to match average packet size
++ * - add support to match directions seperately
++ *
++ * 2004-10-24 Piotr Chytla <pch at fouk.org>
++ * - Connbytes with per-connection accouting backported to 2.4
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/types.h>
++#include <linux/netfilter_ipv4/ip_conntrack.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_connbytes.h>
++
++#include <asm/div64.h>
++
++static u_int64_t mydiv(u_int64_t arg1,u_int32_t arg2)
++{
++ do_div(arg1,arg2);
++ return arg1;
++}
++
++static int
++match(const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *matchinfo,
++ int offset,
++ const void *hdr,
++ u_int16_t datalen,
++ int *hotdrop)
++{
++ static u_int64_t what;
++ const struct ipt_connbytes_info *sinfo = matchinfo;
++ enum ip_conntrack_info ctinfo;
++ struct ip_conntrack *ct;
++
++ if (!(ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo)))
++ return 0; /* no match */
++ switch (sinfo->what) {
++ case IPT_CONNBYTES_PKTS:
++ switch (sinfo->direction) {
++ case IPT_CONNBYTES_DIR_ORIGINAL:
++ what = ct->counters[IP_CT_DIR_ORIGINAL].packets;
++ break;
++ case IPT_CONNBYTES_DIR_REPLY:
++ what = ct->counters[IP_CT_DIR_REPLY].packets;
++ break;
++ case IPT_CONNBYTES_DIR_BOTH:
++ what = ct->counters[IP_CT_DIR_ORIGINAL].packets;
++ what += ct->counters[IP_CT_DIR_REPLY].packets;
++ break;
++ }
++ break;
++ case IPT_CONNBYTES_BYTES:
++ switch (sinfo->direction) {
++ case IPT_CONNBYTES_DIR_ORIGINAL:
++ what = ct->counters[IP_CT_DIR_ORIGINAL].bytes;
++ break;
++ case IPT_CONNBYTES_DIR_REPLY:
++ what = ct->counters[IP_CT_DIR_REPLY].bytes;
++ break;
++ case IPT_CONNBYTES_DIR_BOTH:
++ what = ct->counters[IP_CT_DIR_ORIGINAL].bytes;
++ what += ct->counters[IP_CT_DIR_REPLY].bytes;
++ break;
++ }
++ break;
++ case IPT_CONNBYTES_AVGPKT:
++ switch (sinfo->direction) {
++ case IPT_CONNBYTES_DIR_ORIGINAL:
++ {
++ u_int32_t pkts32;
++
++ if (ct->counters[IP_CT_DIR_ORIGINAL].packets > 0xfffffffff)
++ pkts32 = 0xffffffff;
++ else
++ pkts32 = ct->counters[IP_CT_DIR_ORIGINAL].packets;
++ what = mydiv(ct->counters[IP_CT_DIR_ORIGINAL].bytes,pkts32);
++ }
++ break;
++ case IPT_CONNBYTES_DIR_REPLY:
++ {
++ u_int32_t pkts32;
++
++ if (ct->counters[IP_CT_DIR_REPLY].packets > 0xffffffff)
++ pkts32 = 0xffffffff;
++ else
++ pkts32 = ct->counters[IP_CT_DIR_REPLY].packets;
++ what = mydiv(ct->counters[IP_CT_DIR_REPLY].bytes,pkts32);
++ }
++ break;
++ case IPT_CONNBYTES_DIR_BOTH:
++ {
++ u_int64_t bytes;
++ u_int64_t pkts;
++ u_int32_t pkts32;
++ bytes = ct->counters[IP_CT_DIR_ORIGINAL].bytes +
++ ct->counters[IP_CT_DIR_REPLY].bytes;
++ pkts = ct->counters[IP_CT_DIR_ORIGINAL].packets +
++ ct->counters[IP_CT_DIR_REPLY].packets;
++ if (pkts > 0xffffffff)
++ pkts32 = 0xffffffff;
++ else
++ pkts32 = pkts;
++ what = mydiv(bytes,pkts);
++ }
++ break;
++ }
++ break;
++ }
++ if (sinfo->count.to)
++ return (what <= sinfo->count.to && what >= sinfo->count.from);
++ else
++ return (what >= sinfo->count.from);
++}
++
++static int check(const char *tablename,
++ const struct ipt_ip *ip,
++ void *matchinfo,
++ unsigned int matchsize,
++ unsigned int hook_mask)
++{
++ const struct ipt_connbytes_info *sinfo = matchinfo;
++
++ if (matchsize != IPT_ALIGN(sizeof(struct ipt_connbytes_info)))
++ return 0;
++ if (sinfo->what != IPT_CONNBYTES_PKTS &&
++ sinfo->what != IPT_CONNBYTES_BYTES &&
++ sinfo->what != IPT_CONNBYTES_AVGPKT)
++ return 0;
++
++ if (sinfo->direction != IPT_CONNBYTES_DIR_ORIGINAL &&
++ sinfo->direction != IPT_CONNBYTES_DIR_REPLY &&
++ sinfo->direction != IPT_CONNBYTES_DIR_BOTH)
++ return 0;
++
++ return 1;
++}
++
++static struct ipt_match state_match
++= { { NULL, NULL }, "connbytes", &match, &check, NULL, THIS_MODULE };
++
++static int __init init(void)
++{
++ return ipt_register_match(&state_match);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_match(&state_match);
++}
++
++module_init(init);
++module_exit(fini);
++MODULE_LICENSE("GPL");
+--- linux/include/linux/netfilter_ipv4/ipt_connbytes.h.org 1970-01-01 01:00:00.000000000 +0100
++++ linux/include/linux/netfilter_ipv4/ipt_connbytes.h 2005-11-13 16:11:24.567341624 +0100
+@@ -0,0 +1,25 @@
++#ifndef _IPT_CONNBYTES_H
++#define _IPT_CONNBYTES_H
++enum ipt_connbytes_what {
++ IPT_CONNBYTES_PKTS,
++ IPT_CONNBYTES_BYTES,
++ IPT_CONNBYTES_AVGPKT,
++};
++
++enum ipt_connbytes_direction {
++ IPT_CONNBYTES_DIR_ORIGINAL,
++ IPT_CONNBYTES_DIR_REPLY,
++ IPT_CONNBYTES_DIR_BOTH,
++};
++
++struct ipt_connbytes_info
++{
++ struct {
++ u_int64_t from; /* count to be matched */
++ u_int64_t to; /* count to be matched */
++ } count;
++ u_int8_t what; /* ipt_connbytes_what */
++ u_int8_t direction; /* ipt_connbytes_direction */
++};
++
++#endif
+--- linux-2.4.32/net/ipv4/netfilter/ip_conntrack_proto_gre.c 2006-02-04 19:16:25.000000000 +0100
++++ /home/florian//openwrt/trunk/openwrt/build_mipsel/linux/net/ipv4/netfilter/ip_conntrack_proto_gre.c 2006-02-04 18:19:08.000000000 +0100
+@@ -237,16 +237,16 @@
+ /* Returns verdict for packet, and may modify conntrack */
+ static int gre_packet(struct ip_conntrack *ct,
+ struct iphdr *iph, size_t len,
+- enum ip_conntrack_info conntrackinfo)
++ enum ip_conntrack_info ctinfo)
+ {
+ /* If we've seen traffic both ways, this is a GRE connection.
+ * Extend timeout. */
+ if (ct->status & IPS_SEEN_REPLY) {
+- ip_ct_refresh_acct(ct, ct->proto.gre.stream_timeout);
++ ip_ct_refresh_acct(ct, ctinfo, iph, ct->proto.gre.stream_timeout);
+ /* Also, more likely to be important, and not a probe. */
+ set_bit(IPS_ASSURED_BIT, &ct->status);
+ } else
+- ip_ct_refresh_acct(ct, ct->proto.gre.timeout);
++ ip_ct_refresh_acct(ct, ctinfo, iph, ct->proto.gre.timeout);
+
+ return NF_ACCEPT;
+ }
diff --git a/target/linux/generic-2.4/patches/611-netfilter_condition.patch b/target/linux/generic-2.4/patches/611-netfilter_condition.patch
new file mode 100644
index 0000000000..6c16c29f0c
--- /dev/null
+++ b/target/linux/generic-2.4/patches/611-netfilter_condition.patch
@@ -0,0 +1,625 @@
+diff -ruN linux-2.4.30-old/Documentation/Configure.help linux-2.4.30-new/Documentation/Configure.help
+--- linux-2.4.30-old/Documentation/Configure.help 2005-11-13 21:52:27.000000000 +0100
++++ linux-2.4.30-new/Documentation/Configure.help 2005-11-13 22:20:15.000000000 +0100
+@@ -2979,6 +2979,14 @@
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
++Condition variable match support
++CONFIG_IP_NF_MATCH_CONDITION
++ This option allows you to match firewall rules against condition
++ variables stored in the /proc/net/ipt_condition directory.
++
++ If you want to compile it as a module, say M here and read
++ Documentation/modules.txt. If unsure, say `N'.
++
+ conntrack match support
+ CONFIG_IP_NF_MATCH_CONNTRACK
+ This is a general conntrack match module, a superset of the state match.
+@@ -3354,6 +3362,14 @@
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
++Condition variable match support
++CONFIG_IP6_NF_MATCH_CONDITION
++ This option allows you to match firewall rules against condition
++ variables stored in the /proc/net/ipt_condition directory.
++
++ If you want to compile it as a module, say M here and read
++ Documentation/modules.txt. If unsure, say `N'.
++
+ Multiple port match support
+ CONFIG_IP6_NF_MATCH_MULTIPORT
+ Multiport matching allows you to match TCP or UDP packets based on
+diff -ruN linux-2.4.30-old/include/linux/netfilter_ipv4/ipt_condition.h linux-2.4.30-new/include/linux/netfilter_ipv4/ipt_condition.h
+--- linux-2.4.30-old/include/linux/netfilter_ipv4/ipt_condition.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30-new/include/linux/netfilter_ipv4/ipt_condition.h 2005-11-13 22:20:14.000000000 +0100
+@@ -0,0 +1,11 @@
++#ifndef __IPT_CONDITION_MATCH__
++#define __IPT_CONDITION_MATCH__
++
++#define CONDITION_NAME_LEN 32
++
++struct condition_info {
++ char name[CONDITION_NAME_LEN];
++ int invert;
++};
++
++#endif
+diff -ruN linux-2.4.30-old/include/linux/netfilter_ipv6/ip6t_condition.h linux-2.4.30-new/include/linux/netfilter_ipv6/ip6t_condition.h
+--- linux-2.4.30-old/include/linux/netfilter_ipv6/ip6t_condition.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30-new/include/linux/netfilter_ipv6/ip6t_condition.h 2005-11-13 22:20:14.000000000 +0100
+@@ -0,0 +1,11 @@
++#ifndef __IP6T_CONDITION_MATCH__
++#define __IP6T_CONDITION_MATCH__
++
++#define CONDITION6_NAME_LEN 32
++
++struct condition6_info {
++ char name[CONDITION6_NAME_LEN];
++ int invert;
++};
++
++#endif
+diff -ruN linux-2.4.30-old/net/ipv4/netfilter/Config.in linux-2.4.30-new/net/ipv4/netfilter/Config.in
+--- linux-2.4.30-old/net/ipv4/netfilter/Config.in 2005-11-13 21:52:27.000000000 +0100
++++ linux-2.4.30-new/net/ipv4/netfilter/Config.in 2005-11-13 22:20:15.000000000 +0100
+@@ -43,6 +43,7 @@
+ dep_tristate ' netfilter MARK match support' CONFIG_IP_NF_MATCH_MARK $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' Multiple port match support' CONFIG_IP_NF_MATCH_MULTIPORT $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' TOS match support' CONFIG_IP_NF_MATCH_TOS $CONFIG_IP_NF_IPTABLES
++ dep_tristate ' condition match support' CONFIG_IP_NF_MATCH_CONDITION $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' recent match support' CONFIG_IP_NF_MATCH_RECENT $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' ECN match support' CONFIG_IP_NF_MATCH_ECN $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' peer to peer traffic match support' CONFIG_IP_NF_MATCH_IPP2P $CONFIG_IP_NF_IPTABLES
+diff -ruN linux-2.4.30-old/net/ipv4/netfilter/Makefile linux-2.4.30-new/net/ipv4/netfilter/Makefile
+--- linux-2.4.30-old/net/ipv4/netfilter/Makefile 2005-11-13 21:52:27.000000000 +0100
++++ linux-2.4.30-new/net/ipv4/netfilter/Makefile 2005-11-13 22:20:15.000000000 +0100
+@@ -94,6 +94,7 @@
+ obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
+ obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
+ obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
++obj-$(CONFIG_IP_NF_MATCH_CONDITION) += ipt_condition.o
+
+ obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
+
+diff -ruN linux-2.4.30-old/net/ipv4/netfilter/ipt_condition.c linux-2.4.30-new/net/ipv4/netfilter/ipt_condition.c
+--- linux-2.4.30-old/net/ipv4/netfilter/ipt_condition.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30-new/net/ipv4/netfilter/ipt_condition.c 2005-11-13 22:20:14.000000000 +0100
+@@ -0,0 +1,256 @@
++/*-------------------------------------------*\
++| Netfilter Condition Module |
++| |
++| Description: This module allows firewall |
++| rules to match using condition variables |
++| stored in /proc files. |
++| |
++| Author: Stephane Ouellette 2002-10-22 |
++| <ouellettes@videotron.ca> |
++| |
++| History: |
++| 2003-02-10 Second version with improved |
++| locking and simplified code. |
++| |
++| This software is distributed under the |
++| terms of the GNU GPL. |
++\*-------------------------------------------*/
++
++#include<linux/module.h>
++#include<linux/proc_fs.h>
++#include<linux/spinlock.h>
++#include<linux/string.h>
++#include<asm/atomic.h>
++#include<linux/netfilter_ipv4/ip_tables.h>
++#include<linux/netfilter_ipv4/ipt_condition.h>
++
++
++#ifndef CONFIG_PROC_FS
++#error "Proc file system support is required for this module"
++#endif
++
++
++MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
++MODULE_DESCRIPTION("Allows rules to match against condition variables");
++MODULE_LICENSE("GPL");
++
++
++struct condition_variable {
++ struct condition_variable *next;
++ struct proc_dir_entry *status_proc;
++ atomic_t refcount;
++ int enabled; /* TRUE == 1, FALSE == 0 */
++};
++
++
++static rwlock_t list_lock;
++static struct condition_variable *head = NULL;
++static struct proc_dir_entry *proc_net_condition = NULL;
++
++
++static int
++ipt_condition_read_info(char *buffer, char **start, off_t offset,
++ int length, int *eof, void *data)
++{
++ struct condition_variable *var =
++ (struct condition_variable *) data;
++
++ if (offset == 0) {
++ *start = buffer;
++ buffer[0] = (var->enabled) ? '1' : '0';
++ buffer[1] = '\n';
++ return 2;
++ }
++
++ *eof = 1;
++ return 0;
++}
++
++
++static int
++ipt_condition_write_info(struct file *file, const char *buffer,
++ unsigned long length, void *data)
++{
++ struct condition_variable *var =
++ (struct condition_variable *) data;
++
++ if (length) {
++ /* Match only on the first character */
++ switch (buffer[0]) {
++ case '0':
++ var->enabled = 0;
++ break;
++ case '1':
++ var->enabled = 1;
++ }
++ }
++
++ return (int) length;
++}
++
++
++static int
++match(const struct sk_buff *skb, const struct net_device *in,
++ const struct net_device *out, const void *matchinfo, int offset,
++ const void *hdr, u_int16_t datalen, int *hotdrop)
++{
++ const struct condition_info *info =
++ (const struct condition_info *) matchinfo;
++ struct condition_variable *var;
++ int condition_status = 0;
++
++ read_lock(&list_lock);
++
++ for (var = head; var; var = var->next) {
++ if (strcmp(info->name, var->status_proc->name) == 0) {
++ condition_status = var->enabled;
++ break;
++ }
++ }
++
++ read_unlock(&list_lock);
++
++ return condition_status ^ info->invert;
++}
++
++
++
++static int
++checkentry(const char *tablename, const struct ipt_ip *ip,
++ void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
++{
++ struct condition_info *info = (struct condition_info *) matchinfo;
++ struct condition_variable *var, *newvar;
++
++ if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
++ return 0;
++
++ /* The first step is to check if the condition variable already exists. */
++ /* Here, a read lock is sufficient because we won't change the list */
++ read_lock(&list_lock);
++
++ for (var = head; var; var = var->next) {
++ if (strcmp(info->name, var->status_proc->name) == 0) {
++ atomic_inc(&var->refcount);
++ read_unlock(&list_lock);
++ return 1;
++ }
++ }
++
++ read_unlock(&list_lock);
++
++ /* At this point, we need to allocate a new condition variable */
++ newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
++
++ if (!newvar)
++ return -ENOMEM;
++
++ /* Create the condition variable's proc file entry */
++ newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
++
++ if (!newvar->status_proc) {
++ /*
++ * There are two possibilities:
++ * 1- Another condition variable with the same name has been created, which is valid.
++ * 2- There was a memory allocation error.
++ */
++ kfree(newvar);
++ read_lock(&list_lock);
++
++ for (var = head; var; var = var->next) {
++ if (strcmp(info->name, var->status_proc->name) == 0) {
++ atomic_inc(&var->refcount);
++ read_unlock(&list_lock);
++ return 1;
++ }
++ }
++
++ read_unlock(&list_lock);
++ return -ENOMEM;
++ }
++
++ atomic_set(&newvar->refcount, 1);
++ newvar->enabled = 0;
++ newvar->status_proc->owner = THIS_MODULE;
++ newvar->status_proc->data = newvar;
++ wmb();
++ newvar->status_proc->read_proc = ipt_condition_read_info;
++ newvar->status_proc->write_proc = ipt_condition_write_info;
++
++ write_lock(&list_lock);
++
++ newvar->next = head;
++ head = newvar;
++
++ write_unlock(&list_lock);
++
++ return 1;
++}
++
++
++static void
++destroy(void *matchinfo, unsigned int matchsize)
++{
++ struct condition_info *info = (struct condition_info *) matchinfo;
++ struct condition_variable *var, *prev = NULL;
++
++ if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
++ return;
++
++ write_lock(&list_lock);
++
++ for (var = head; var && strcmp(info->name, var->status_proc->name);
++ prev = var, var = var->next);
++
++ if (var && atomic_dec_and_test(&var->refcount)) {
++ if (prev)
++ prev->next = var->next;
++ else
++ head = var->next;
++
++ write_unlock(&list_lock);
++ remove_proc_entry(var->status_proc->name, proc_net_condition);
++ kfree(var);
++ } else
++ write_unlock(&list_lock);
++}
++
++
++static struct ipt_match condition_match = {
++ .name = "condition",
++ .match = &match,
++ .checkentry = &checkentry,
++ .destroy = &destroy,
++ .me = THIS_MODULE
++};
++
++
++static int __init
++init(void)
++{
++ int errorcode;
++
++ rwlock_init(&list_lock);
++ proc_net_condition = proc_mkdir("ipt_condition", proc_net);
++
++ if (proc_net_condition) {
++ errorcode = ipt_register_match(&condition_match);
++
++ if (errorcode)
++ remove_proc_entry("ipt_condition", proc_net);
++ } else
++ errorcode = -EACCES;
++
++ return errorcode;
++}
++
++
++static void __exit
++fini(void)
++{
++ ipt_unregister_match(&condition_match);
++ remove_proc_entry("ipt_condition", proc_net);
++}
++
++module_init(init);
++module_exit(fini);
+diff -ruN linux-2.4.30-old/net/ipv6/netfilter/Config.in linux-2.4.30-new/net/ipv6/netfilter/Config.in
+--- linux-2.4.30-old/net/ipv6/netfilter/Config.in 2003-06-13 16:51:39.000000000 +0200
++++ linux-2.4.30-new/net/ipv6/netfilter/Config.in 2005-11-13 22:20:15.000000000 +0100
+@@ -17,6 +17,7 @@
+ if [ "$CONFIG_IP6_NF_IPTABLES" != "n" ]; then
+ # The simple matches.
+ dep_tristate ' limit match support' CONFIG_IP6_NF_MATCH_LIMIT $CONFIG_IP6_NF_IPTABLES
++ dep_tristate ' condition match support' CONFIG_IP6_NF_MATCH_CONDITION $CONFIG_IP6_NF_IPTABLES
+ dep_tristate ' MAC address match support' CONFIG_IP6_NF_MATCH_MAC $CONFIG_IP6_NF_IPTABLES
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ dep_tristate ' Routing header match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_RT $CONFIG_IP6_NF_IPTABLES
+diff -ruN linux-2.4.30-old/net/ipv6/netfilter/Makefile linux-2.4.30-new/net/ipv6/netfilter/Makefile
+--- linux-2.4.30-old/net/ipv6/netfilter/Makefile 2003-06-13 16:51:39.000000000 +0200
++++ linux-2.4.30-new/net/ipv6/netfilter/Makefile 2005-11-13 22:20:15.000000000 +0100
+@@ -14,6 +14,7 @@
+ # Link order matters here.
+ obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
+ obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o
++obj-$(CONFIG_IP6_NF_MATCH_CONDITION) += ip6t_condition.o
+ obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
+ obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
+ obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
+diff -ruN linux-2.4.30-old/net/ipv6/netfilter/ip6t_condition.c linux-2.4.30-new/net/ipv6/netfilter/ip6t_condition.c
+--- linux-2.4.30-old/net/ipv6/netfilter/ip6t_condition.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30-new/net/ipv6/netfilter/ip6t_condition.c 2005-11-13 22:20:14.000000000 +0100
+@@ -0,0 +1,254 @@
++/*-------------------------------------------*\
++| Netfilter Condition Module for IPv6 |
++| |
++| Description: This module allows firewall |
++| rules to match using condition variables |
++| stored in /proc files. |
++| |
++| Author: Stephane Ouellette 2003-02-10 |
++| <ouellettes@videotron.ca> |
++| |
++| This software is distributed under the |
++| terms of the GNU GPL. |
++\*-------------------------------------------*/
++
++#include<linux/module.h>
++#include<linux/proc_fs.h>
++#include<linux/spinlock.h>
++#include<linux/string.h>
++#include<asm/atomic.h>
++#include<linux/netfilter_ipv6/ip6_tables.h>
++#include<linux/netfilter_ipv6/ip6t_condition.h>
++
++
++#ifndef CONFIG_PROC_FS
++#error "Proc file system support is required for this module"
++#endif
++
++
++MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
++MODULE_DESCRIPTION("Allows rules to match against condition variables");
++MODULE_LICENSE("GPL");
++
++
++struct condition_variable {
++ struct condition_variable *next;
++ struct proc_dir_entry *status_proc;
++ atomic_t refcount;
++ int enabled; /* TRUE == 1, FALSE == 0 */
++};
++
++
++static rwlock_t list_lock;
++static struct condition_variable *head = NULL;
++static struct proc_dir_entry *proc_net_condition = NULL;
++
++
++static int
++ipt_condition_read_info(char *buffer, char **start, off_t offset,
++ int length, int *eof, void *data)
++{
++ struct condition_variable *var =
++ (struct condition_variable *) data;
++
++ if (offset == 0) {
++ *start = buffer;
++ buffer[0] = (var->enabled) ? '1' : '0';
++ buffer[1] = '\n';
++ return 2;
++ }
++
++ *eof = 1;
++ return 0;
++}
++
++
++static int
++ipt_condition_write_info(struct file *file, const char *buffer,
++ unsigned long length, void *data)
++{
++ struct condition_variable *var =
++ (struct condition_variable *) data;
++
++ if (length) {
++ /* Match only on the first character */
++ switch (buffer[0]) {
++ case '0':
++ var->enabled = 0;
++ break;
++ case '1':
++ var->enabled = 1;
++ }
++ }
++
++ return (int) length;
++}
++
++
++static int
++match(const struct sk_buff *skb, const struct net_device *in,
++ const struct net_device *out, const void *matchinfo, int offset,
++ const void *hdr, u_int16_t datalen, int *hotdrop)
++{
++ const struct condition6_info *info =
++ (const struct condition6_info *) matchinfo;
++ struct condition_variable *var;
++ int condition_status = 0;
++
++ read_lock(&list_lock);
++
++ for (var = head; var; var = var->next) {
++ if (strcmp(info->name, var->status_proc->name) == 0) {
++ condition_status = var->enabled;
++ break;
++ }
++ }
++
++ read_unlock(&list_lock);
++
++ return condition_status ^ info->invert;
++}
++
++
++
++static int
++checkentry(const char *tablename, const struct ip6t_ip6 *ip,
++ void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
++{
++ struct condition6_info *info =
++ (struct condition6_info *) matchinfo;
++ struct condition_variable *var, *newvar;
++
++ if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
++ return 0;
++
++ /* The first step is to check if the condition variable already exists. */
++ /* Here, a read lock is sufficient because we won't change the list */
++ read_lock(&list_lock);
++
++ for (var = head; var; var = var->next) {
++ if (strcmp(info->name, var->status_proc->name) == 0) {
++ atomic_inc(&var->refcount);
++ read_unlock(&list_lock);
++ return 1;
++ }
++ }
++
++ read_unlock(&list_lock);
++
++ /* At this point, we need to allocate a new condition variable */
++ newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
++
++ if (!newvar)
++ return -ENOMEM;
++
++ /* Create the condition variable's proc file entry */
++ newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
++
++ if (!newvar->status_proc) {
++ /*
++ * There are two possibilities:
++ * 1- Another condition variable with the same name has been created, which is valid.
++ * 2- There was a memory allocation error.
++ */
++ kfree(newvar);
++ read_lock(&list_lock);
++
++ for (var = head; var; var = var->next) {
++ if (strcmp(info->name, var->status_proc->name) == 0) {
++ atomic_inc(&var->refcount);
++ read_unlock(&list_lock);
++ return 1;
++ }
++ }
++
++ read_unlock(&list_lock);
++ return -ENOMEM;
++ }
++
++ atomic_set(&newvar->refcount, 1);
++ newvar->enabled = 0;
++ newvar->status_proc->owner = THIS_MODULE;
++ newvar->status_proc->data = newvar;
++ wmb();
++ newvar->status_proc->read_proc = ipt_condition_read_info;
++ newvar->status_proc->write_proc = ipt_condition_write_info;
++
++ write_lock(&list_lock);
++
++ newvar->next = head;
++ head = newvar;
++
++ write_unlock(&list_lock);
++
++ return 1;
++}
++
++
++static void
++destroy(void *matchinfo, unsigned int matchsize)
++{
++ struct condition6_info *info =
++ (struct condition6_info *) matchinfo;
++ struct condition_variable *var, *prev = NULL;
++
++ if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
++ return;
++
++ write_lock(&list_lock);
++
++ for (var = head; var && strcmp(info->name, var->status_proc->name);
++ prev = var, var = var->next);
++
++ if (var && atomic_dec_and_test(&var->refcount)) {
++ if (prev)
++ prev->next = var->next;
++ else
++ head = var->next;
++
++ write_unlock(&list_lock);
++ remove_proc_entry(var->status_proc->name, proc_net_condition);
++ kfree(var);
++ } else
++ write_unlock(&list_lock);
++}
++
++
++static struct ip6t_match condition_match = {
++ .name = "condition",
++ .match = &match,
++ .checkentry = &checkentry,
++ .destroy = &destroy,
++ .me = THIS_MODULE
++};
++
++
++static int __init
++init(void)
++{
++ int errorcode;
++
++ rwlock_init(&list_lock);
++ proc_net_condition = proc_mkdir("ip6t_condition", proc_net);
++
++ if (proc_net_condition) {
++ errorcode = ipt_register_match(&condition_match);
++
++ if (errorcode)
++ remove_proc_entry("ip6t_condition", proc_net);
++ } else
++ errorcode = -EACCES;
++
++ return errorcode;
++}
++
++
++static void __exit
++fini(void)
++{
++ ipt_unregister_match(&condition_match);
++ remove_proc_entry("ip6t_condition", proc_net);
++}
++
++module_init(init);
++module_exit(fini);
diff --git a/target/linux/generic-2.4/patches/612-netfilter_quota.patch b/target/linux/generic-2.4/patches/612-netfilter_quota.patch
new file mode 100644
index 0000000000..a0a019c171
--- /dev/null
+++ b/target/linux/generic-2.4/patches/612-netfilter_quota.patch
@@ -0,0 +1,147 @@
+diff -ruN linux-2.4.30-old/Documentation/Configure.help linux-2.4.30-new/Documentation/Configure.help
+--- linux-2.4.30-old/Documentation/Configure.help 2005-11-13 22:30:42.000000000 +0100
++++ linux-2.4.30-new/Documentation/Configure.help 2005-11-13 22:31:17.000000000 +0100
+@@ -2888,6 +2888,13 @@
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
++quota match support
++CONFIG_IP_NF_MATCH_QUOTA
++ This match implements network quotas.
++
++ If you want to compile it as a module, say M here and read
++ Documentation/modules.txt. If unsure, say `N'.
++
+ skb->pkt_type packet match support
+ CONFIG_IP_NF_MATCH_PKTTYPE
+ This patch allows you to match packet in accrodance
+diff -ruN linux-2.4.30-old/include/linux/netfilter_ipv4/ipt_quota.h linux-2.4.30-new/include/linux/netfilter_ipv4/ipt_quota.h
+--- linux-2.4.30-old/include/linux/netfilter_ipv4/ipt_quota.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30-new/include/linux/netfilter_ipv4/ipt_quota.h 2005-11-13 22:31:17.000000000 +0100
+@@ -0,0 +1,12 @@
++#ifndef _IPT_QUOTA_H
++#define _IPT_QUOTA_H
++
++/* print debug info in both kernel/netfilter module & iptable library */
++//#define DEBUG_IPT_QUOTA
++
++struct ipt_quota_info {
++ u_int64_t quota;
++ struct ipt_quota_info *master;
++};
++
++#endif /*_IPT_QUOTA_H*/
+diff -ruN linux-2.4.30-old/net/ipv4/netfilter/Config.in linux-2.4.30-new/net/ipv4/netfilter/Config.in
+--- linux-2.4.30-old/net/ipv4/netfilter/Config.in 2005-11-13 22:30:42.000000000 +0100
++++ linux-2.4.30-new/net/ipv4/netfilter/Config.in 2005-11-13 22:31:17.000000000 +0100
+@@ -24,6 +24,7 @@
+ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
+ # The simple matches.
+ dep_tristate ' limit match support' CONFIG_IP_NF_MATCH_LIMIT $CONFIG_IP_NF_IPTABLES
++ dep_tristate ' quota match support' CONFIG_IP_NF_MATCH_QUOTA $CONFIG_IP_NF_IPTABLES
+
+ dep_tristate ' IP set support' CONFIG_IP_NF_SET $CONFIG_IP_NF_IPTABLES
+ if [ "$CONFIG_IP_NF_SET" != "n" ]; then
+diff -ruN linux-2.4.30-old/net/ipv4/netfilter/Makefile linux-2.4.30-new/net/ipv4/netfilter/Makefile
+--- linux-2.4.30-old/net/ipv4/netfilter/Makefile 2005-11-13 22:30:42.000000000 +0100
++++ linux-2.4.30-new/net/ipv4/netfilter/Makefile 2005-11-13 22:31:17.000000000 +0100
+@@ -74,6 +74,7 @@
+ # matches
+ obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
+ obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
++obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
+ obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
+ obj-$(CONFIG_IP_NF_MATCH_SET) += ipt_set.o
+ obj-$(CONFIG_IP_NF_TARGET_SET) += ipt_SET.o
+diff -ruN linux-2.4.30-old/net/ipv4/netfilter/ipt_quota.c linux-2.4.30-new/net/ipv4/netfilter/ipt_quota.c
+--- linux-2.4.30-old/net/ipv4/netfilter/ipt_quota.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30-new/net/ipv4/netfilter/ipt_quota.c 2005-11-13 22:31:17.000000000 +0100
+@@ -0,0 +1,88 @@
++/*
++ * netfilter module to enforce network quotas
++ *
++ * Sam Johnston <samj@samj.net>
++ *
++ * 30/01/05: Fixed on SMP --Pablo Neira <pablo@eurodev.net>
++ */
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/spinlock.h>
++#include <linux/interrupt.h>
++
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_quota.h>
++
++MODULE_LICENSE("GPL");
++
++static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
++
++static int
++match(const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *matchinfo,
++ int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
++{
++ struct ipt_quota_info *q =
++ ((struct ipt_quota_info *) matchinfo)->master;
++
++ spin_lock_bh(&quota_lock);
++
++ if (q->quota >= datalen) {
++ /* we can afford this one */
++ q->quota -= datalen;
++ spin_unlock_bh(&quota_lock);
++
++#ifdef DEBUG_IPT_QUOTA
++ printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
++#endif
++ return 1;
++ }
++
++ /* so we do not allow even small packets from now on */
++ q->quota = 0;
++
++#ifdef DEBUG_IPT_QUOTA
++ printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
++#endif
++
++ spin_unlock_bh(&quota_lock);
++ return 0;
++}
++
++static int
++checkentry(const char *tablename,
++ const struct ipt_ip *ip,
++ void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
++{
++ /* TODO: spinlocks? sanity checks? */
++ struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
++
++ if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
++ return 0;
++
++ /* For SMP, we only want to use one set of counters. */
++ q->master = q;
++
++ return 1;
++}
++
++static struct ipt_match quota_match
++ = { {NULL, NULL}, "quota", &match, &checkentry, NULL, THIS_MODULE };
++
++static int __init
++init(void)
++{
++ return ipt_register_match(&quota_match);
++}
++
++static void __exit
++fini(void)
++{
++ ipt_unregister_match(&quota_match);
++}
++
++module_init(init);
++module_exit(fini);
++
diff --git a/target/linux/generic-2.4/patches/613-netfilter_nat_h323.patch b/target/linux/generic-2.4/patches/613-netfilter_nat_h323.patch
new file mode 100644
index 0000000000..983d4fef3a
--- /dev/null
+++ b/target/linux/generic-2.4/patches/613-netfilter_nat_h323.patch
@@ -0,0 +1,821 @@
+diff -urN linux-2.4.32/net/ipv4/netfilter/Config.in linux-2.4.32.new/net/ipv4/netfilter/Config.in
+--- linux-2.4.32/net/ipv4/netfilter/Config.in 2006-03-01 00:49:36.652505800 +0100
++++ linux-2.4.32.new/net/ipv4/netfilter/Config.in 2006-03-01 00:50:18.692114808 +0100
+@@ -15,6 +15,7 @@
+ dep_tristate ' Connection byte counter support' CONFIG_IP_NF_MATCH_CONNBYTES $CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' GRE protocol support' CONFIG_IP_NF_CT_PROTO_GRE $CONFIG_IP_NF_CONNTRACK
+ dep_tristate ' PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE
++ dep_tristate ' H.323 (netmeeting) support' CONFIG_IP_NF_H323 $CONFIG_IP_NF_CONNTRACK
+ fi
+
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+@@ -111,6 +112,13 @@
+ define_tristate CONFIG_IP_NF_NAT_AMANDA $CONFIG_IP_NF_NAT
+ fi
+ fi
++ if [ "$CONFIG_IP_NF_H323" = "m" ]; then
++ define_tristate CONFIG_IP_NF_NAT_H323 m
++ else
++ if [ "$CONFIG_IP_NF_H323" = "y" ]; then
++ define_tristate CONFIG_IP_NF_NAT_H323 $CONFIG_IP_NF_NAT
++ fi
++ fi
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ dep_tristate ' Basic SNMP-ALG support (EXPERIMENTAL)' CONFIG_IP_NF_NAT_SNMP_BASIC $CONFIG_IP_NF_NAT
+ fi
+diff -urN linux-2.4.32/net/ipv4/netfilter/Makefile linux-2.4.32.new/net/ipv4/netfilter/Makefile
+--- linux-2.4.32/net/ipv4/netfilter/Makefile 2006-03-01 00:49:36.654505496 +0100
++++ linux-2.4.32.new/net/ipv4/netfilter/Makefile 2006-03-01 00:50:18.693114656 +0100
+@@ -53,6 +53,10 @@
+ ifdef CONFIG_IP_NF_NAT_PPTP
+ export-objs += ip_conntrack_pptp.o
+ endif
++obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
++ifdef CONFIG_IP_NF_NAT_H323
++ export-objs += ip_conntrack_h323.o
++endif
+
+
+ # NAT helpers
+@@ -62,6 +66,7 @@
+ obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
+ obj-$(CONFIG_IP_NF_NAT_PROTO_GRE) += ip_nat_proto_gre.o
+ obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
++obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
+
+ # generic IP tables
+ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
+diff -urN linux-2.4.32/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.4.32.new/net/ipv4/netfilter/ip_conntrack_h323.c
+--- linux-2.4.32/net/ipv4/netfilter/ip_conntrack_h323.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32.new/net/ipv4/netfilter/ip_conntrack_h323.c 2006-03-01 00:50:18.694114504 +0100
+@@ -0,0 +1,302 @@
++/*
++ * H.323 'brute force' extension for H.323 connection tracking.
++ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
++ * (http://www.coritel.it/projects/sofia/nat/)
++ * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
++ * the unregistered helpers to the conntrack entries.
++ */
++
++
++#include <linux/module.h>
++#include <linux/netfilter.h>
++#include <linux/ip.h>
++#include <net/checksum.h>
++#include <net/tcp.h>
++
++#include <linux/netfilter_ipv4/lockhelp.h>
++#include <linux/netfilter_ipv4/ip_conntrack.h>
++#include <linux/netfilter_ipv4/ip_conntrack_core.h>
++#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
++#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
++#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
++
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
++MODULE_LICENSE("GPL");
++
++DECLARE_LOCK(ip_h323_lock);
++struct module *ip_conntrack_h323 = THIS_MODULE;
++
++#define DEBUGP(format, args...)
++
++static int h245_help(const struct iphdr *iph, size_t len,
++ struct ip_conntrack *ct,
++ enum ip_conntrack_info ctinfo)
++{
++ struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
++ unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
++ unsigned char *data_limit;
++ u_int32_t tcplen = len - iph->ihl * 4;
++ u_int32_t datalen = tcplen - tcph->doff * 4;
++ int dir = CTINFO2DIR(ctinfo);
++ struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
++ struct ip_conntrack_expect expect, *exp = &expect;
++ struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
++ u_int16_t data_port;
++ u_int32_t data_ip;
++ unsigned int i;
++
++ DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
++ NIPQUAD(iph->saddr), ntohs(tcph->source),
++ NIPQUAD(iph->daddr), ntohs(tcph->dest));
++
++ /* Can't track connections formed before we registered */
++ if (!info)
++ return NF_ACCEPT;
++
++ /* Until there's been traffic both ways, don't look in packets. */
++ if (ctinfo != IP_CT_ESTABLISHED
++ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
++ DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
++ return NF_ACCEPT;
++ }
++
++ /* Not whole TCP header or too short packet? */
++ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
++ DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
++ return NF_ACCEPT;
++ }
++
++ /* Checksum invalid? Ignore. */
++ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
++ csum_partial((char *)tcph, tcplen, 0))) {
++ DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
++ tcph, tcplen, NIPQUAD(iph->saddr),
++ NIPQUAD(iph->daddr));
++ return NF_ACCEPT;
++ }
++
++ data_limit = (unsigned char *) data + datalen;
++ /* bytes: 0123 45
++ ipadrr port */
++ for (i = 0; data < (data_limit - 5); data++, i++) {
++ memcpy(&data_ip, data, sizeof(u_int32_t));
++ if (data_ip == iph->saddr) {
++ memcpy(&data_port, data + 4, sizeof(u_int16_t));
++ memset(&expect, 0, sizeof(expect));
++ /* update the H.225 info */
++ DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
++ NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
++ NIPQUAD(iph->saddr), ntohs(data_port));
++ LOCK_BH(&ip_h323_lock);
++ info->is_h225 = H225_PORT + 1;
++ exp_info->port = data_port;
++ exp_info->dir = dir;
++ exp_info->offset = i;
++
++ exp->seq = ntohl(tcph->seq) + i;
++
++ exp->tuple = ((struct ip_conntrack_tuple)
++ { { ct->tuplehash[!dir].tuple.src.ip,
++ { 0 } },
++ { data_ip,
++ { data_port },
++ IPPROTO_UDP }});
++ exp->mask = ((struct ip_conntrack_tuple)
++ { { 0xFFFFFFFF, { 0 } },
++ { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
++
++ exp->expectfn = NULL;
++
++ /* Ignore failure; should only happen with NAT */
++ ip_conntrack_expect_related(ct, exp);
++
++ UNLOCK_BH(&ip_h323_lock);
++ }
++ }
++
++ return NF_ACCEPT;
++
++}
++
++/* H.245 helper is not registered! */
++static struct ip_conntrack_helper h245 =
++ { { NULL, NULL },
++ "H.245", /* name */
++ IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
++ NULL, /* module */
++ 8, /* max_ expected */
++ 240, /* timeout */
++ { { 0, { 0 } }, /* tuple */
++ { 0, { 0 }, IPPROTO_TCP } },
++ { { 0, { 0xFFFF } }, /* mask */
++ { 0, { 0 }, 0xFFFF } },
++ h245_help /* helper */
++ };
++
++static int h225_expect(struct ip_conntrack *ct)
++{
++ WRITE_LOCK(&ip_conntrack_lock);
++ ct->helper = &h245;
++ DEBUGP("h225_expect: helper for %p added\n", ct);
++ WRITE_UNLOCK(&ip_conntrack_lock);
++
++ return NF_ACCEPT; /* unused */
++}
++
++static int h225_help(const struct iphdr *iph, size_t len,
++ struct ip_conntrack *ct,
++ enum ip_conntrack_info ctinfo)
++{
++ struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
++ unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
++ unsigned char *data_limit;
++ u_int32_t tcplen = len - iph->ihl * 4;
++ u_int32_t datalen = tcplen - tcph->doff * 4;
++ int dir = CTINFO2DIR(ctinfo);
++ struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
++ struct ip_conntrack_expect expect, *exp = &expect;
++ struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
++ u_int16_t data_port;
++ u_int32_t data_ip;
++ unsigned int i;
++
++ DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
++ NIPQUAD(iph->saddr), ntohs(tcph->source),
++ NIPQUAD(iph->daddr), ntohs(tcph->dest));
++
++ /* Can't track connections formed before we registered */
++ if (!info)
++ return NF_ACCEPT;
++
++ /* Until there's been traffic both ways, don't look in packets. */
++ if (ctinfo != IP_CT_ESTABLISHED
++ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
++ DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
++ return NF_ACCEPT;
++ }
++
++ /* Not whole TCP header or too short packet? */
++ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
++ DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
++ return NF_ACCEPT;
++ }
++
++ /* Checksum invalid? Ignore. */
++ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
++ csum_partial((char *)tcph, tcplen, 0))) {
++ DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
++ tcph, tcplen, NIPQUAD(iph->saddr),
++ NIPQUAD(iph->daddr));
++ return NF_ACCEPT;
++ }
++
++ data_limit = (unsigned char *) data + datalen;
++ /* bytes: 0123 45
++ ipadrr port */
++ for (i = 0; data < (data_limit - 5); data++, i++) {
++ memcpy(&data_ip, data, sizeof(u_int32_t));
++ if (data_ip == iph->saddr) {
++ memcpy(&data_port, data + 4, sizeof(u_int16_t));
++ if (data_port == tcph->source) {
++ /* Signal address */
++ DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
++ NIPQUAD(iph->saddr));
++ /* Update the H.225 info so that NAT can mangle the address/port
++ even when we have no expected connection! */
++#ifdef CONFIG_IP_NF_NAT_NEEDED
++ LOCK_BH(&ip_h323_lock);
++ info->dir = dir;
++ info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
++ info->offset[IP_CT_DIR_ORIGINAL] = i;
++ UNLOCK_BH(&ip_h323_lock);
++#endif
++ } else {
++ memset(&expect, 0, sizeof(expect));
++
++ /* update the H.225 info */
++ LOCK_BH(&ip_h323_lock);
++ info->is_h225 = H225_PORT;
++ exp_info->port = data_port;
++ exp_info->dir = dir;
++ exp_info->offset = i;
++
++ exp->seq = ntohl(tcph->seq) + i;
++
++ exp->tuple = ((struct ip_conntrack_tuple)
++ { { ct->tuplehash[!dir].tuple.src.ip,
++ { 0 } },
++ { data_ip,
++ { data_port },
++ IPPROTO_TCP }});
++ exp->mask = ((struct ip_conntrack_tuple)
++ { { 0xFFFFFFFF, { 0 } },
++ { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
++
++ exp->expectfn = h225_expect;
++
++ /* Ignore failure */
++ ip_conntrack_expect_related(ct, exp);
++
++ DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
++ NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
++ NIPQUAD(iph->saddr), ntohs(data_port));
++
++ UNLOCK_BH(&ip_h323_lock);
++ }
++#ifdef CONFIG_IP_NF_NAT_NEEDED
++ } else if (data_ip == iph->daddr) {
++ memcpy(&data_port, data + 4, sizeof(u_int16_t));
++ if (data_port == tcph->dest) {
++ /* Signal address */
++ DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
++ NIPQUAD(iph->daddr));
++ /* Update the H.225 info so that NAT can mangle the address/port
++ even when we have no expected connection! */
++ LOCK_BH(&ip_h323_lock);
++ info->dir = dir;
++ info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
++ info->offset[IP_CT_DIR_REPLY] = i;
++ UNLOCK_BH(&ip_h323_lock);
++ }
++#endif
++ }
++ }
++
++ return NF_ACCEPT;
++
++}
++
++static struct ip_conntrack_helper h225 =
++ { { NULL, NULL },
++ "H.225", /* name */
++ IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
++ THIS_MODULE, /* module */
++ 2, /* max_expected */
++ 240, /* timeout */
++ { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
++ { 0, { 0 }, IPPROTO_TCP } },
++ { { 0, { 0xFFFF } }, /* mask */
++ { 0, { 0 }, 0xFFFF } },
++ h225_help /* helper */
++ };
++
++static int __init init(void)
++{
++ return ip_conntrack_helper_register(&h225);
++}
++
++static void __exit fini(void)
++{
++ /* Unregister H.225 helper */
++ ip_conntrack_helper_unregister(&h225);
++}
++
++#ifdef CONFIG_IP_NF_NAT_NEEDED
++EXPORT_SYMBOL(ip_h323_lock);
++#endif
++
++module_init(init);
++module_exit(fini);
+diff -urN linux-2.4.32/net/ipv4/netfilter/ip_nat_h323.c linux-2.4.32.new/net/ipv4/netfilter/ip_nat_h323.c
+--- linux-2.4.32/net/ipv4/netfilter/ip_nat_h323.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32.new/net/ipv4/netfilter/ip_nat_h323.c 2006-03-01 00:50:18.698113896 +0100
+@@ -0,0 +1,403 @@
++/*
++ * H.323 'brute force' extension for NAT alteration.
++ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
++ * (http://www.coritel.it/projects/sofia/nat.html)
++ * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
++ * the unregistered helpers to the conntrack entries.
++ */
++
++
++#include <linux/module.h>
++#include <linux/netfilter.h>
++#include <linux/ip.h>
++#include <net/checksum.h>
++#include <net/tcp.h>
++
++#include <linux/netfilter_ipv4/lockhelp.h>
++#include <linux/netfilter_ipv4/ip_nat.h>
++#include <linux/netfilter_ipv4/ip_nat_helper.h>
++#include <linux/netfilter_ipv4/ip_nat_rule.h>
++#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
++#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
++#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
++
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
++MODULE_LICENSE("GPL");
++
++DECLARE_LOCK_EXTERN(ip_h323_lock);
++struct module *ip_nat_h323 = THIS_MODULE;
++
++#define DEBUGP(format, args...)
++
++
++static unsigned int
++h225_nat_expected(struct sk_buff **pskb,
++ unsigned int hooknum,
++ struct ip_conntrack *ct,
++ struct ip_nat_info *info);
++
++static unsigned int h225_nat_help(struct ip_conntrack *ct,
++ struct ip_conntrack_expect *exp,
++ struct ip_nat_info *info,
++ enum ip_conntrack_info ctinfo,
++ unsigned int hooknum,
++ struct sk_buff **pskb);
++
++static struct ip_nat_helper h245 =
++ { { NULL, NULL },
++ "H.245", /* name */
++ 0, /* flags */
++ NULL, /* module */
++ { { 0, { 0 } }, /* tuple */
++ { 0, { 0 }, IPPROTO_TCP } },
++ { { 0, { 0xFFFF } }, /* mask */
++ { 0, { 0 }, 0xFFFF } },
++ h225_nat_help, /* helper */
++ h225_nat_expected /* expectfn */
++ };
++
++static unsigned int
++h225_nat_expected(struct sk_buff **pskb,
++ unsigned int hooknum,
++ struct ip_conntrack *ct,
++ struct ip_nat_info *info)
++{
++ struct ip_nat_multi_range mr;
++ u_int32_t newdstip, newsrcip, newip;
++ u_int16_t port;
++ struct ip_ct_h225_expect *exp_info;
++ struct ip_ct_h225_master *master_info;
++ struct ip_conntrack *master = master_ct(ct);
++ unsigned int is_h225, ret;
++
++ IP_NF_ASSERT(info);
++ IP_NF_ASSERT(master);
++
++ IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
++
++ DEBUGP("h225_nat_expected: We have a connection!\n");
++ master_info = &ct->master->expectant->help.ct_h225_info;
++ exp_info = &ct->master->help.exp_h225_info;
++
++ LOCK_BH(&ip_h323_lock);
++
++ DEBUGP("master: ");
++ DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
++ DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
++ DEBUGP("conntrack: ");
++ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
++ if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
++ /* Make connection go to the client. */
++ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
++ newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
++ DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
++ NIPQUAD(newsrcip), NIPQUAD(newdstip));
++ } else {
++ /* Make the connection go to the server */
++ newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
++ newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
++ DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
++ NIPQUAD(newsrcip), NIPQUAD(newdstip));
++ }
++ port = exp_info->port;
++ is_h225 = master_info->is_h225 == H225_PORT;
++ UNLOCK_BH(&ip_h323_lock);
++
++ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
++ newip = newsrcip;
++ else
++ newip = newdstip;
++
++ DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
++
++ mr.rangesize = 1;
++ /* We don't want to manip the per-protocol, just the IPs... */
++ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
++ mr.range[0].min_ip = mr.range[0].max_ip = newip;
++
++ /* ... unless we're doing a MANIP_DST, in which case, make
++ sure we map to the correct port */
++ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
++ mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
++ mr.range[0].min = mr.range[0].max
++ = ((union ip_conntrack_manip_proto)
++ { port });
++ }
++
++ ret = ip_nat_setup_info(ct, &mr, hooknum);
++
++ if (is_h225) {
++ DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
++ /* NAT expectfn called with ip_nat_lock write-locked */
++ info->helper = &h245;
++ }
++ return ret;
++}
++
++static int h323_signal_address_fixup(struct ip_conntrack *ct,
++ struct sk_buff **pskb,
++ enum ip_conntrack_info ctinfo)
++{
++ struct iphdr *iph = (*pskb)->nh.iph;
++ struct tcphdr *tcph = (void *)iph + iph->ihl*4;
++ unsigned char *data;
++ u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
++ u_int32_t datalen = tcplen - tcph->doff*4;
++ struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
++ u_int32_t newip;
++ u_int16_t port;
++ u_int8_t buffer[6];
++ int i;
++
++ MUST_BE_LOCKED(&ip_h323_lock);
++
++ DEBUGP("h323_signal_address_fixup: %s %s\n",
++ between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
++ ? "yes" : "no",
++ between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
++ ? "yes" : "no");
++ if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
++ || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
++ return 1;
++
++ DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n",
++ info->offset[IP_CT_DIR_ORIGINAL],
++ info->offset[IP_CT_DIR_REPLY],
++ tcplen);
++ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
++ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
++
++ for (i = 0; i < IP_CT_DIR_MAX; i++) {
++ DEBUGP("h323_signal_address_fixup: %s %s\n",
++ info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
++ i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
++ if (!between(info->seq[i], ntohl(tcph->seq),
++ ntohl(tcph->seq) + datalen))
++ continue;
++ if (!between(info->seq[i] + 6, ntohl(tcph->seq),
++ ntohl(tcph->seq) + datalen)) {
++ /* Partial retransmisison. It's a cracker being funky. */
++ if (net_ratelimit()) {
++ printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
++ info->seq[i],
++ ntohl(tcph->seq),
++ ntohl(tcph->seq) + datalen);
++ }
++ return 0;
++ }
++
++ /* Change address inside packet to match way we're mapping
++ this connection. */
++ if (i == IP_CT_DIR_ORIGINAL) {
++ newip = ct->tuplehash[!info->dir].tuple.dst.ip;
++ port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
++ } else {
++ newip = ct->tuplehash[!info->dir].tuple.src.ip;
++ port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
++ }
++
++ data = (char *) tcph + tcph->doff * 4 + info->offset[i];
++
++ DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n",
++ i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
++ data[0], data[1], data[2], data[3],
++ (data[4] << 8 | data[5]));
++
++ /* Modify the packet */
++ memcpy(buffer, &newip, 4);
++ memcpy(buffer + 4, &port, 2);
++ if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, info->offset[i],
++ 6, buffer, 6))
++ return 0;
++
++ DEBUGP("h323_signal_address_fixup: new %s IP:port %u.%u.%u.%u:%u\n",
++ i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
++ data[0], data[1], data[2], data[3],
++ (data[4] << 8 | data[5]));
++ }
++
++ return 1;
++}
++
++static int h323_data_fixup(struct ip_ct_h225_expect *info,
++ struct ip_conntrack *ct,
++ struct sk_buff **pskb,
++ enum ip_conntrack_info ctinfo,
++ struct ip_conntrack_expect *expect)
++{
++ u_int32_t newip;
++ u_int16_t port;
++ u_int8_t buffer[6];
++ struct ip_conntrack_tuple newtuple;
++ struct iphdr *iph = (*pskb)->nh.iph;
++ struct tcphdr *tcph = (void *)iph + iph->ihl*4;
++ unsigned char *data;
++ u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
++ struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
++ int is_h225;
++
++ MUST_BE_LOCKED(&ip_h323_lock);
++ DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
++ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
++ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
++
++ if (!between(expect->seq + 6, ntohl(tcph->seq),
++ ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
++ /* Partial retransmisison. It's a cracker being funky. */
++ if (net_ratelimit()) {
++ printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
++ expect->seq,
++ ntohl(tcph->seq),
++ ntohl(tcph->seq) + tcplen - tcph->doff * 4);
++ }
++ return 0;
++ }
++
++ /* Change address inside packet to match way we're mapping
++ this connection. */
++ if (info->dir == IP_CT_DIR_REPLY) {
++ /* Must be where client thinks server is */
++ newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
++ /* Expect something from client->server */
++ newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
++ newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
++ } else {
++ /* Must be where server thinks client is */
++ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
++ /* Expect something from server->client */
++ newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
++ newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
++ }
++
++ is_h225 = (master_info->is_h225 == H225_PORT);
++
++ if (is_h225) {
++ newtuple.dst.protonum = IPPROTO_TCP;
++ newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
++ } else {
++ newtuple.dst.protonum = IPPROTO_UDP;
++ newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
++ }
++
++ /* Try to get same port: if not, try to change it. */
++ for (port = ntohs(info->port); port != 0; port++) {
++ if (is_h225)
++ newtuple.dst.u.tcp.port = htons(port);
++ else
++ newtuple.dst.u.udp.port = htons(port);
++
++ if (ip_conntrack_change_expect(expect, &newtuple) == 0)
++ break;
++ }
++ if (port == 0) {
++ DEBUGP("h323_data_fixup: no free port found!\n");
++ return 0;
++ }
++
++ port = htons(port);
++
++ data = (char *) tcph + tcph->doff * 4 + info->offset;
++
++ DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n",
++ data[0], data[1], data[2], data[3],
++ (data[4] << 8 | data[5]));
++
++ /* Modify the packet */
++ memcpy(buffer, &newip, 4);
++ memcpy(buffer + 4, &port, 2);
++ if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, info->offset,
++ 6, buffer, 6))
++ return 0;
++
++ DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n",
++ data[0], data[1], data[2], data[3],
++ (data[4] << 8 | data[5]));
++
++ return 1;
++}
++
++static unsigned int h225_nat_help(struct ip_conntrack *ct,
++ struct ip_conntrack_expect *exp,
++ struct ip_nat_info *info,
++ enum ip_conntrack_info ctinfo,
++ unsigned int hooknum,
++ struct sk_buff **pskb)
++{
++ int dir;
++ struct ip_ct_h225_expect *exp_info;
++
++ /* Only mangle things once: original direction in POST_ROUTING
++ and reply direction on PRE_ROUTING. */
++ dir = CTINFO2DIR(ctinfo);
++ DEBUGP("nat_h323: dir %s at hook %s\n",
++ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
++ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
++ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
++ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
++ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
++ || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
++ DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
++ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
++ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
++ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
++ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
++ return NF_ACCEPT;
++ }
++
++ if (!exp) {
++ LOCK_BH(&ip_h323_lock);
++ if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
++ UNLOCK_BH(&ip_h323_lock);
++ return NF_DROP;
++ }
++ UNLOCK_BH(&ip_h323_lock);
++ return NF_ACCEPT;
++ }
++
++ exp_info = &exp->help.exp_h225_info;
++
++ LOCK_BH(&ip_h323_lock);
++ if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
++ UNLOCK_BH(&ip_h323_lock);
++ return NF_DROP;
++ }
++ UNLOCK_BH(&ip_h323_lock);
++
++ return NF_ACCEPT;
++}
++
++static struct ip_nat_helper h225 =
++ { { NULL, NULL },
++ "H.225", /* name */
++ IP_NAT_HELPER_F_ALWAYS, /* flags */
++ THIS_MODULE, /* module */
++ { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
++ { 0, { 0 }, IPPROTO_TCP } },
++ { { 0, { 0xFFFF } }, /* mask */
++ { 0, { 0 }, 0xFFFF } },
++ h225_nat_help, /* helper */
++ h225_nat_expected /* expectfn */
++ };
++
++static int __init init(void)
++{
++ int ret;
++
++ ret = ip_nat_helper_register(&h225);
++
++ if (ret != 0)
++ printk("ip_nat_h323: cannot initialize the module!\n");
++
++ return ret;
++}
++
++static void __exit fini(void)
++{
++ ip_nat_helper_unregister(&h225);
++}
++
++module_init(init);
++module_exit(fini);
+diff -urN linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack.h
+--- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h 2006-03-01 00:49:36.474532856 +0100
++++ linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack.h 2006-03-01 00:50:18.699113744 +0100
+@@ -71,6 +71,7 @@
+ #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
+ #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
+ #include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
++#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
+
+ /* per expectation: application helper private data */
+ union ip_conntrack_expect_help {
+@@ -79,6 +80,7 @@
+ struct ip_ct_ftp_expect exp_ftp_info;
+ struct ip_ct_irc_expect exp_irc_info;
+ struct ip_ct_pptp_expect exp_pptp_info;
++ struct ip_ct_h225_expect exp_h225_info;
+
+ #ifdef CONFIG_IP_NF_NAT_NEEDED
+ union {
+@@ -93,6 +95,7 @@
+ struct ip_ct_ftp_master ct_ftp_info;
+ struct ip_ct_irc_master ct_irc_info;
+ struct ip_ct_pptp_master ct_pptp_info;
++ struct ip_ct_h225_master ct_h225_info;
+ };
+
+ #ifdef CONFIG_IP_NF_NAT_NEEDED
+diff -urN linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack_h323.h
+--- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_h323.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2006-03-01 00:50:18.700113592 +0100
+@@ -0,0 +1,30 @@
++#ifndef _IP_CONNTRACK_H323_H
++#define _IP_CONNTRACK_H323_H
++/* H.323 connection tracking. */
++
++#ifdef __KERNEL__
++/* Protects H.323 related data */
++DECLARE_LOCK_EXTERN(ip_h323_lock);
++#endif
++
++/* Default H.225 port */
++#define H225_PORT 1720
++
++/* This structure is per expected connection */
++struct ip_ct_h225_expect {
++ u_int16_t port; /* Port of the H.225 helper/RTCP/RTP channel */
++ enum ip_conntrack_dir dir; /* Direction of the original connection */
++ unsigned int offset; /* offset of the address in the payload */
++};
++
++/* This structure exists only once per master */
++struct ip_ct_h225_master {
++ int is_h225; /* H.225 or H.245 connection */
++#ifdef CONFIG_IP_NF_NAT_NEEDED
++ enum ip_conntrack_dir dir; /* Direction of the original connection */
++ u_int32_t seq[IP_CT_DIR_MAX]; /* Exceptional packet mangling for signal addressess... */
++ unsigned int offset[IP_CT_DIR_MAX]; /* ...and the offset of the addresses in the payload */
++#endif
++};
++
++#endif /* _IP_CONNTRACK_H323_H */
diff --git a/target/linux/generic-2.4/patches/614-netfilter_nat_rtsp.patch b/target/linux/generic-2.4/patches/614-netfilter_nat_rtsp.patch
new file mode 100644
index 0000000000..6ae3e7b0aa
--- /dev/null
+++ b/target/linux/generic-2.4/patches/614-netfilter_nat_rtsp.patch
@@ -0,0 +1,1523 @@
+diff -urN linux-2.4.32/net/ipv4/netfilter/Config.in linux-2.4.32.new/net/ipv4/netfilter/Config.in
+--- linux-2.4.32/net/ipv4/netfilter/Config.in 2006-03-01 00:53:57.884792456 +0100
++++ linux-2.4.32.new/net/ipv4/netfilter/Config.in 2006-03-01 00:55:14.462150928 +0100
+@@ -16,6 +16,7 @@
+ dep_tristate ' GRE protocol support' CONFIG_IP_NF_CT_PROTO_GRE $CONFIG_IP_NF_CONNTRACK
+ dep_tristate ' PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE
+ dep_tristate ' H.323 (netmeeting) support' CONFIG_IP_NF_H323 $CONFIG_IP_NF_CONNTRACK
++ dep_tristate ' RTSP protocol support' CONFIG_IP_NF_RTSP $CONFIG_IP_NF_CONNTRACK
+ fi
+
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+@@ -119,6 +120,13 @@
+ define_tristate CONFIG_IP_NF_NAT_H323 $CONFIG_IP_NF_NAT
+ fi
+ fi
++ if [ "$CONFIG_IP_NF_RTSP" = "m" ]; then
++ define_tristate CONFIG_IP_NF_NAT_RTSP m
++ else
++ if [ "$CONFIG_IP_NF_RTSP" = "y" ]; then
++ define_tristate CONFIG_IP_NF_NAT_RTSP $CONFIG_IP_NF_NAT
++ fi
++ fi
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ dep_tristate ' Basic SNMP-ALG support (EXPERIMENTAL)' CONFIG_IP_NF_NAT_SNMP_BASIC $CONFIG_IP_NF_NAT
+ fi
+diff -urN linux-2.4.32/net/ipv4/netfilter/Makefile linux-2.4.32.new/net/ipv4/netfilter/Makefile
+--- linux-2.4.32/net/ipv4/netfilter/Makefile 2006-03-01 00:53:57.886792152 +0100
++++ linux-2.4.32.new/net/ipv4/netfilter/Makefile 2006-03-01 00:55:14.463150776 +0100
+@@ -57,6 +57,11 @@
+ ifdef CONFIG_IP_NF_NAT_H323
+ export-objs += ip_conntrack_h323.o
+ endif
++obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
++ifdef CONFIG_IP_NF_NAT_RTSP
++ export-objs += ip_conntrack_rtsp.o
++endif
++
+
+
+ # NAT helpers
+@@ -67,6 +72,7 @@
+ obj-$(CONFIG_IP_NF_NAT_PROTO_GRE) += ip_nat_proto_gre.o
+ obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
+ obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
++obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
+
+ # generic IP tables
+ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
+diff -urN linux-2.4.32/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.4.32.new/net/ipv4/netfilter/ip_conntrack_rtsp.c
+--- linux-2.4.32/net/ipv4/netfilter/ip_conntrack_rtsp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32.new/net/ipv4/netfilter/ip_conntrack_rtsp.c 2006-03-01 00:55:14.465150472 +0100
+@@ -0,0 +1,507 @@
++/*
++ * RTSP extension for IP connection tracking
++ * (C) 2003 by Tom Marshall <tmarshall@real.com>
++ * based on ip_conntrack_irc.c
++ *
++ * 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.
++ *
++ * Module load syntax:
++ * insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
++ * max_outstanding=n setup_timeout=secs
++ *
++ * If no ports are specified, the default will be port 554.
++ *
++ * With max_outstanding you can define the maximum number of not yet
++ * answered SETUP requests per RTSP session (default 8).
++ * With setup_timeout you can specify how long the system waits for
++ * an expected data channel (default 300 seconds).
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/netfilter.h>
++#include <linux/ip.h>
++#include <net/checksum.h>
++#include <net/tcp.h>
++
++#include <linux/netfilter_ipv4/lockhelp.h>
++#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
++#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
++
++#include <linux/ctype.h>
++#define NF_NEED_STRNCASECMP
++#define NF_NEED_STRTOU16
++#define NF_NEED_STRTOU32
++#define NF_NEED_NEXTLINE
++#include <linux/netfilter_helpers.h>
++#define NF_NEED_MIME_NEXTLINE
++#include <linux/netfilter_mime.h>
++
++#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
++
++#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
++#ifdef IP_NF_RTSP_DEBUG
++#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
++#else
++#define DEBUGP(fmt, args...)
++#endif
++
++#define MAX_PORTS 8
++static int ports[MAX_PORTS];
++static int num_ports = 0;
++static int max_outstanding = 8;
++static unsigned int setup_timeout = 300;
++
++MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
++MODULE_DESCRIPTION("RTSP connection tracking module");
++MODULE_LICENSE("GPL");
++#ifdef MODULE_PARM
++MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
++MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
++MODULE_PARM(max_outstanding, "i");
++MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
++MODULE_PARM(setup_timeout, "i");
++MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
++#endif
++
++DECLARE_LOCK(ip_rtsp_lock);
++struct module* ip_conntrack_rtsp = THIS_MODULE;
++
++/*
++ * Max mappings we will allow for one RTSP connection (for RTP, the number
++ * of allocated ports is twice this value). Note that SMIL burns a lot of
++ * ports so keep this reasonably high. If this is too low, you will see a
++ * lot of "no free client map entries" messages.
++ */
++#define MAX_PORT_MAPS 16
++
++/*** default port list was here in the masq code: 554, 3030, 4040 ***/
++
++#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
++
++/*
++ * Parse an RTSP packet.
++ *
++ * Returns zero if parsing failed.
++ *
++ * Parameters:
++ * IN ptcp tcp data pointer
++ * IN tcplen tcp data len
++ * IN/OUT ptcpoff points to current tcp offset
++ * OUT phdrsoff set to offset of rtsp headers
++ * OUT phdrslen set to length of rtsp headers
++ * OUT pcseqoff set to offset of CSeq header
++ * OUT pcseqlen set to length of CSeq header
++ */
++static int
++rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
++ uint* phdrsoff, uint* phdrslen,
++ uint* pcseqoff, uint* pcseqlen)
++{
++ uint entitylen = 0;
++ uint lineoff;
++ uint linelen;
++
++ if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
++ {
++ return 0;
++ }
++
++ *phdrsoff = *ptcpoff;
++ while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
++ {
++ if (linelen == 0)
++ {
++ if (entitylen > 0)
++ {
++ *ptcpoff += min(entitylen, tcplen - *ptcpoff);
++ }
++ break;
++ }
++ if (lineoff+linelen > tcplen)
++ {
++ INFOP("!! overrun !!\n");
++ break;
++ }
++
++ if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
++ {
++ *pcseqoff = lineoff;
++ *pcseqlen = linelen;
++ }
++ if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
++ {
++ uint off = lineoff+15;
++ SKIP_WSPACE(ptcp+lineoff, linelen, off);
++ nf_strtou32(ptcp+off, &entitylen);
++ }
++ }
++ *phdrslen = (*ptcpoff) - (*phdrsoff);
++
++ return 1;
++}
++
++/*
++ * Find lo/hi client ports (if any) in transport header
++ * In:
++ * ptcp, tcplen = packet
++ * tranoff, tranlen = buffer to search
++ *
++ * Out:
++ * pport_lo, pport_hi = lo/hi ports (host endian)
++ *
++ * Returns nonzero if any client ports found
++ *
++ * Note: it is valid (and expected) for the client to request multiple
++ * transports, so we need to parse the entire line.
++ */
++static int
++rtsp_parse_transport(char* ptran, uint tranlen,
++ struct ip_ct_rtsp_expect* prtspexp)
++{
++ int rc = 0;
++ uint off = 0;
++
++ if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
++ nf_strncasecmp(ptran, "Transport:", 10) != 0)
++ {
++ INFOP("sanity check failed\n");
++ return 0;
++ }
++ DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
++ off += 10;
++ SKIP_WSPACE(ptran, tranlen, off);
++
++ /* Transport: tran;field;field=val,tran;field;field=val,... */
++ while (off < tranlen)
++ {
++ const char* pparamend;
++ uint nextparamoff;
++
++ pparamend = memchr(ptran+off, ',', tranlen-off);
++ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
++ nextparamoff = pparamend-ptran;
++
++ while (off < nextparamoff)
++ {
++ const char* pfieldend;
++ uint nextfieldoff;
++
++ pfieldend = memchr(ptran+off, ';', nextparamoff-off);
++ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
++
++ if (strncmp(ptran+off, "client_port=", 12) == 0)
++ {
++ u_int16_t port;
++ uint numlen;
++
++ off += 12;
++ numlen = nf_strtou16(ptran+off, &port);
++ off += numlen;
++ if (prtspexp->loport != 0 && prtspexp->loport != port)
++ {
++ DEBUGP("multiple ports found, port %hu ignored\n", port);
++ }
++ else
++ {
++ prtspexp->loport = prtspexp->hiport = port;
++ if (ptran[off] == '-')
++ {
++ off++;
++ numlen = nf_strtou16(ptran+off, &port);
++ off += numlen;
++ prtspexp->pbtype = pb_range;
++ prtspexp->hiport = port;
++
++ // If we have a range, assume rtp:
++ // loport must be even, hiport must be loport+1
++ if ((prtspexp->loport & 0x0001) != 0 ||
++ prtspexp->hiport != prtspexp->loport+1)
++ {
++ DEBUGP("incorrect range: %hu-%hu, correcting\n",
++ prtspexp->loport, prtspexp->hiport);
++ prtspexp->loport &= 0xfffe;
++ prtspexp->hiport = prtspexp->loport+1;
++ }
++ }
++ else if (ptran[off] == '/')
++ {
++ off++;
++ numlen = nf_strtou16(ptran+off, &port);
++ off += numlen;
++ prtspexp->pbtype = pb_discon;
++ prtspexp->hiport = port;
++ }
++ rc = 1;
++ }
++ }
++
++ /*
++ * Note we don't look for the destination parameter here.
++ * If we are using NAT, the NAT module will handle it. If not,
++ * and the client is sending packets elsewhere, the expectation
++ * will quietly time out.
++ */
++
++ off = nextfieldoff;
++ }
++
++ off = nextparamoff;
++ }
++
++ return rc;
++}
++
++/*** conntrack functions ***/
++
++/* outbound packet: client->server */
++static int
++help_out(const struct iphdr* iph, size_t pktlen,
++ struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
++{
++ int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */
++ struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
++ uint tcplen = pktlen - iph->ihl * 4;
++ char* pdata = (char*)tcph + tcph->doff * 4;
++ uint datalen = tcplen - tcph->doff * 4;
++ uint dataoff = 0;
++
++ struct ip_conntrack_expect exp;
++
++ while (dataoff < datalen)
++ {
++ uint cmdoff = dataoff;
++ uint hdrsoff = 0;
++ uint hdrslen = 0;
++ uint cseqoff = 0;
++ uint cseqlen = 0;
++ uint lineoff = 0;
++ uint linelen = 0;
++ uint off;
++ int rc;
++
++ if (!rtsp_parse_message(pdata, datalen, &dataoff,
++ &hdrsoff, &hdrslen,
++ &cseqoff, &cseqlen))
++ {
++ break; /* not a valid message */
++ }
++
++ if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
++ {
++ continue; /* not a SETUP message */
++ }
++ DEBUGP("found a setup message\n");
++
++ memset(&exp, 0, sizeof(exp));
++
++ off = 0;
++ while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
++ &lineoff, &linelen))
++ {
++ if (linelen == 0)
++ {
++ break;
++ }
++ if (off > hdrsoff+hdrslen)
++ {
++ INFOP("!! overrun !!");
++ break;
++ }
++
++ if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
++ {
++ rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
++ &exp.help.exp_rtsp_info);
++ }
++ }
++
++ if (exp.help.exp_rtsp_info.loport == 0)
++ {
++ DEBUGP("no udp transports found\n");
++ continue; /* no udp transports found */
++ }
++
++ DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
++ (int)exp.help.exp_rtsp_info.pbtype,
++ exp.help.exp_rtsp_info.loport,
++ exp.help.exp_rtsp_info.hiport);
++
++ LOCK_BH(&ip_rtsp_lock);
++ exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
++ exp.help.exp_rtsp_info.len = hdrslen;
++
++ exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
++ exp.mask.src.ip = 0xffffffff;
++ exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
++ exp.mask.dst.ip = 0xffffffff;
++ exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
++ exp.mask.dst.u.udp.port = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
++ exp.tuple.dst.protonum = IPPROTO_UDP;
++ exp.mask.dst.protonum = 0xffff;
++
++ DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
++ NIPQUAD(exp.tuple.src.ip),
++ ntohs(exp.tuple.src.u.tcp.port),
++ NIPQUAD(exp.tuple.dst.ip),
++ ntohs(exp.tuple.dst.u.tcp.port));
++
++ /* pass the request off to the nat helper */
++ rc = ip_conntrack_expect_related(ct, &exp);
++ UNLOCK_BH(&ip_rtsp_lock);
++ if (rc == 0)
++ {
++ DEBUGP("ip_conntrack_expect_related succeeded\n");
++ }
++ else
++ {
++ INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
++ }
++ }
++
++ return NF_ACCEPT;
++}
++
++/* inbound packet: server->client */
++static int
++help_in(const struct iphdr* iph, size_t pktlen,
++ struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
++{
++ return NF_ACCEPT;
++}
++
++static int
++help(const struct iphdr* iph, size_t pktlen,
++ struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
++{
++ /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
++ struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
++ u_int32_t tcplen = pktlen - iph->ihl * 4;
++
++ /* Until there's been traffic both ways, don't look in packets. */
++ if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
++ {
++ DEBUGP("conntrackinfo = %u\n", ctinfo);
++ return NF_ACCEPT;
++ }
++
++ /* Not whole TCP header? */
++ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
++ {
++ DEBUGP("tcplen = %u\n", (unsigned)tcplen);
++ return NF_ACCEPT;
++ }
++
++ /* Checksum invalid? Ignore. */
++ /* FIXME: Source route IP option packets --RR */
++ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
++ csum_partial((char*)tcph, tcplen, 0)))
++ {
++ DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
++ tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
++ return NF_ACCEPT;
++ }
++
++ switch (CTINFO2DIR(ctinfo))
++ {
++ case IP_CT_DIR_ORIGINAL:
++ help_out(iph, pktlen, ct, ctinfo);
++ break;
++ case IP_CT_DIR_REPLY:
++ help_in(iph, pktlen, ct, ctinfo);
++ break;
++ }
++
++ return NF_ACCEPT;
++}
++
++static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
++static char rtsp_names[MAX_PORTS][10];
++
++/* This function is intentionally _NOT_ defined as __exit */
++static void
++fini(void)
++{
++ int i;
++ for (i = 0; i < num_ports; i++)
++ {
++ DEBUGP("unregistering port %d\n", ports[i]);
++ ip_conntrack_helper_unregister(&rtsp_helpers[i]);
++ }
++}
++
++static int __init
++init(void)
++{
++ int i, ret;
++ struct ip_conntrack_helper *hlpr;
++ char *tmpname;
++
++ printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
++
++ if (max_outstanding < 1)
++ {
++ printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
++ return -EBUSY;
++ }
++ if (setup_timeout < 0)
++ {
++ printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
++ return -EBUSY;
++ }
++
++ /* If no port given, default to standard rtsp port */
++ if (ports[0] == 0)
++ {
++ ports[0] = RTSP_PORT;
++ }
++
++ for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
++ {
++ hlpr = &rtsp_helpers[i];
++ memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
++ hlpr->tuple.src.u.tcp.port = htons(ports[i]);
++ hlpr->tuple.dst.protonum = IPPROTO_TCP;
++ hlpr->mask.src.u.tcp.port = 0xFFFF;
++ hlpr->mask.dst.protonum = 0xFFFF;
++ hlpr->max_expected = max_outstanding;
++ hlpr->timeout = setup_timeout;
++ hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
++ hlpr->me = ip_conntrack_rtsp;
++ hlpr->help = help;
++
++ tmpname = &rtsp_names[i][0];
++ if (ports[i] == RTSP_PORT)
++ {
++ sprintf(tmpname, "rtsp");
++ }
++ else
++ {
++ sprintf(tmpname, "rtsp-%d", i);
++ }
++ hlpr->name = tmpname;
++
++ DEBUGP("port #%d: %d\n", i, ports[i]);
++
++ ret = ip_conntrack_helper_register(hlpr);
++
++ if (ret)
++ {
++ printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
++ fini();
++ return -EBUSY;
++ }
++ num_ports++;
++ }
++ return 0;
++}
++
++#ifdef CONFIG_IP_NF_NAT_NEEDED
++EXPORT_SYMBOL(ip_rtsp_lock);
++#endif
++
++module_init(init);
++module_exit(fini);
+diff -urN linux-2.4.32/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.4.32.new/net/ipv4/netfilter/ip_nat_rtsp.c
+--- linux-2.4.32/net/ipv4/netfilter/ip_nat_rtsp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32.new/net/ipv4/netfilter/ip_nat_rtsp.c 2006-03-01 00:55:14.467150168 +0100
+@@ -0,0 +1,621 @@
++/*
++ * RTSP extension for TCP NAT alteration
++ * (C) 2003 by Tom Marshall <tmarshall@real.com>
++ * based on ip_nat_irc.c
++ *
++ * 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.
++ *
++ * Module load syntax:
++ * insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
++ * stunaddr=<address>
++ * destaction=[auto|strip|none]
++ *
++ * If no ports are specified, the default will be port 554 only.
++ *
++ * stunaddr specifies the address used to detect that a client is using STUN.
++ * If this address is seen in the destination parameter, it is assumed that
++ * the client has already punched a UDP hole in the firewall, so we don't
++ * mangle the client_port. If none is specified, it is autodetected. It
++ * only needs to be set if you have multiple levels of NAT. It should be
++ * set to the external address that the STUN clients detect. Note that in
++ * this case, it will not be possible for clients to use UDP with servers
++ * between the NATs.
++ *
++ * If no destaction is specified, auto is used.
++ * destaction=auto: strip destination parameter if it is not stunaddr.
++ * destaction=strip: always strip destination parameter (not recommended).
++ * destaction=none: do not touch destination parameter (not recommended).
++ */
++
++#include <linux/module.h>
++#include <linux/netfilter_ipv4.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/kernel.h>
++#include <net/tcp.h>
++#include <linux/netfilter_ipv4/ip_nat.h>
++#include <linux/netfilter_ipv4/ip_nat_helper.h>
++#include <linux/netfilter_ipv4/ip_nat_rule.h>
++#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
++#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
++
++#include <linux/inet.h>
++#include <linux/ctype.h>
++#define NF_NEED_STRNCASECMP
++#define NF_NEED_STRTOU16
++#include <linux/netfilter_helpers.h>
++#define NF_NEED_MIME_NEXTLINE
++#include <linux/netfilter_mime.h>
++
++#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
++#ifdef IP_NF_RTSP_DEBUG
++#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
++#else
++#define DEBUGP(fmt, args...)
++#endif
++
++#define MAX_PORTS 8
++#define DSTACT_AUTO 0
++#define DSTACT_STRIP 1
++#define DSTACT_NONE 2
++
++static int ports[MAX_PORTS];
++static char* stunaddr = NULL;
++static char* destaction = NULL;
++
++static int num_ports = 0;
++static u_int32_t extip = 0;
++static int dstact = 0;
++
++MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
++MODULE_DESCRIPTION("RTSP network address translation module");
++MODULE_LICENSE("GPL");
++#ifdef MODULE_PARM
++MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
++MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
++MODULE_PARM(stunaddr, "s");
++MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
++MODULE_PARM(destaction, "s");
++MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
++#endif
++
++/* protects rtsp part of conntracks */
++DECLARE_LOCK_EXTERN(ip_rtsp_lock);
++
++#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
++
++/*** helper functions ***/
++
++static void
++get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
++{
++ struct iphdr* iph = (struct iphdr*)skb->nh.iph;
++ struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
++
++ *pptcpdata = (char*)tcph + tcph->doff*4;
++ *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
++}
++
++/*** nat functions ***/
++
++/*
++ * Mangle the "Transport:" header:
++ * - Replace all occurences of "client_port=<spec>"
++ * - Handle destination parameter
++ *
++ * In:
++ * ct, ctinfo = conntrack context
++ * pskb = packet
++ * tranoff = Transport header offset from TCP data
++ * tranlen = Transport header length (incl. CRLF)
++ * rport_lo = replacement low port (host endian)
++ * rport_hi = replacement high port (host endian)
++ *
++ * Returns packet size difference.
++ *
++ * Assumes that a complete transport header is present, ending with CR or LF
++ */
++static int
++rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
++ struct ip_conntrack_expect* exp,
++ struct sk_buff** pskb, uint tranoff, uint tranlen)
++{
++ char* ptcp;
++ uint tcplen;
++ char* ptran;
++ char rbuf1[16]; /* Replacement buffer (one port) */
++ uint rbuf1len; /* Replacement len (one port) */
++ char rbufa[16]; /* Replacement buffer (all ports) */
++ uint rbufalen; /* Replacement len (all ports) */
++ u_int32_t newip;
++ u_int16_t loport, hiport;
++ uint off = 0;
++ uint diff; /* Number of bytes we removed */
++
++ struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
++ struct ip_conntrack_tuple t;
++
++ char szextaddr[15+1];
++ uint extaddrlen;
++ int is_stun;
++
++ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
++ ptran = ptcp+tranoff;
++
++ if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
++ tranlen < 10 || !iseol(ptran[tranlen-1]) ||
++ nf_strncasecmp(ptran, "Transport:", 10) != 0)
++ {
++ INFOP("sanity check failed\n");
++ return 0;
++ }
++ off += 10;
++ SKIP_WSPACE(ptcp+tranoff, tranlen, off);
++
++ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
++ t = exp->tuple;
++ t.dst.ip = newip;
++
++ extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
++ : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
++ DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
++
++ rbuf1len = rbufalen = 0;
++ switch (prtspexp->pbtype)
++ {
++ case pb_single:
++ for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
++ {
++ t.dst.u.udp.port = htons(loport);
++ if (ip_conntrack_change_expect(exp, &t) == 0)
++ {
++ DEBUGP("using port %hu\n", loport);
++ break;
++ }
++ }
++ if (loport != 0)
++ {
++ rbuf1len = sprintf(rbuf1, "%hu", loport);
++ rbufalen = sprintf(rbufa, "%hu", loport);
++ }
++ break;
++ case pb_range:
++ for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
++ {
++ t.dst.u.udp.port = htons(loport);
++ if (ip_conntrack_change_expect(exp, &t) == 0)
++ {
++ hiport = loport + ~exp->mask.dst.u.udp.port;
++ DEBUGP("using ports %hu-%hu\n", loport, hiport);
++ break;
++ }
++ }
++ if (loport != 0)
++ {
++ rbuf1len = sprintf(rbuf1, "%hu", loport);
++ rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
++ }
++ break;
++ case pb_discon:
++ for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
++ {
++ t.dst.u.udp.port = htons(loport);
++ if (ip_conntrack_change_expect(exp, &t) == 0)
++ {
++ DEBUGP("using port %hu (1 of 2)\n", loport);
++ break;
++ }
++ }
++ for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
++ {
++ t.dst.u.udp.port = htons(hiport);
++ if (ip_conntrack_change_expect(exp, &t) == 0)
++ {
++ DEBUGP("using port %hu (2 of 2)\n", hiport);
++ break;
++ }
++ }
++ if (loport != 0 && hiport != 0)
++ {
++ rbuf1len = sprintf(rbuf1, "%hu", loport);
++ if (hiport == loport+1)
++ {
++ rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
++ }
++ else
++ {
++ rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
++ }
++ }
++ break;
++ }
++
++ if (rbuf1len == 0)
++ {
++ return 0; /* cannot get replacement port(s) */
++ }
++
++ /* Transport: tran;field;field=val,tran;field;field=val,... */
++ while (off < tranlen)
++ {
++ uint saveoff;
++ const char* pparamend;
++ uint nextparamoff;
++
++ pparamend = memchr(ptran+off, ',', tranlen-off);
++ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
++ nextparamoff = pparamend-ptcp;
++
++ /*
++ * We pass over each param twice. On the first pass, we look for a
++ * destination= field. It is handled by the security policy. If it
++ * is present, allowed, and equal to our external address, we assume
++ * that STUN is being used and we leave the client_port= field alone.
++ */
++ is_stun = 0;
++ saveoff = off;
++ while (off < nextparamoff)
++ {
++ const char* pfieldend;
++ uint nextfieldoff;
++
++ pfieldend = memchr(ptran+off, ';', nextparamoff-off);
++ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
++
++ if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
++ {
++ if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
++ {
++ is_stun = 1;
++ }
++ if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
++ {
++ diff = nextfieldoff-off;
++ if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
++ off, diff, NULL, 0))
++ {
++ /* mangle failed, all we can do is bail */
++ return 0;
++ }
++ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
++ ptran = ptcp+tranoff;
++ tranlen -= diff;
++ nextparamoff -= diff;
++ nextfieldoff -= diff;
++ }
++ }
++
++ off = nextfieldoff;
++ }
++ if (is_stun)
++ {
++ continue;
++ }
++ off = saveoff;
++ while (off < nextparamoff)
++ {
++ const char* pfieldend;
++ uint nextfieldoff;
++
++ pfieldend = memchr(ptran+off, ';', nextparamoff-off);
++ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
++
++ if (strncmp(ptran+off, "client_port=", 12) == 0)
++ {
++ u_int16_t port;
++ uint numlen;
++ uint origoff;
++ uint origlen;
++ char* rbuf = rbuf1;
++ uint rbuflen = rbuf1len;
++
++ off += 12;
++ origoff = (ptran-ptcp)+off;
++ origlen = 0;
++ numlen = nf_strtou16(ptran+off, &port);
++ off += numlen;
++ origlen += numlen;
++ if (port != prtspexp->loport)
++ {
++ DEBUGP("multiple ports found, port %hu ignored\n", port);
++ }
++ else
++ {
++ if (ptran[off] == '-' || ptran[off] == '/')
++ {
++ off++;
++ origlen++;
++ numlen = nf_strtou16(ptran+off, &port);
++ off += numlen;
++ origlen += numlen;
++ rbuf = rbufa;
++ rbuflen = rbufalen;
++ }
++
++ /*
++ * note we cannot just memcpy() if the sizes are the same.
++ * the mangle function does skb resizing, checks for a
++ * cloned skb, and updates the checksums.
++ *
++ * parameter 4 below is offset from start of tcp data.
++ */
++ diff = origlen-rbuflen;
++ if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
++ origoff, origlen, rbuf, rbuflen))
++ {
++ /* mangle failed, all we can do is bail */
++ return 0;
++ }
++ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
++ ptran = ptcp+tranoff;
++ tranlen -= diff;
++ nextparamoff -= diff;
++ nextfieldoff -= diff;
++ }
++ }
++
++ off = nextfieldoff;
++ }
++
++ off = nextparamoff;
++ }
++
++ return 1;
++}
++
++static unsigned int
++expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
++{
++ struct ip_nat_multi_range mr;
++ u_int32_t newdstip, newsrcip, newip;
++
++ struct ip_conntrack *master = master_ct(ct);
++
++ IP_NF_ASSERT(info);
++ IP_NF_ASSERT(master);
++
++ IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
++
++ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
++ newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
++ newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
++
++ DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
++ NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
++
++ mr.rangesize = 1;
++ /* We don't want to manip the per-protocol, just the IPs. */
++ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
++ mr.range[0].min_ip = mr.range[0].max_ip = newip;
++
++ return ip_nat_setup_info(ct, &mr, hooknum);
++}
++
++static uint
++help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
++ struct ip_conntrack_expect* exp, struct sk_buff** pskb)
++{
++ char* ptcp;
++ uint tcplen;
++ uint hdrsoff;
++ uint hdrslen;
++ uint lineoff;
++ uint linelen;
++ uint off;
++
++ struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
++ struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
++
++ struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
++
++ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
++
++ hdrsoff = exp->seq - ntohl(tcph->seq);
++ hdrslen = prtspexp->len;
++ off = hdrsoff;
++
++ while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
++ {
++ if (linelen == 0)
++ {
++ break;
++ }
++ if (off > hdrsoff+hdrslen)
++ {
++ INFOP("!! overrun !!");
++ break;
++ }
++ DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
++
++ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
++ {
++ uint oldtcplen = tcplen;
++ if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
++ {
++ break;
++ }
++ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
++ hdrslen -= (oldtcplen-tcplen);
++ off -= (oldtcplen-tcplen);
++ lineoff -= (oldtcplen-tcplen);
++ linelen -= (oldtcplen-tcplen);
++ DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
++ }
++ }
++
++ return NF_ACCEPT;
++}
++
++static uint
++help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
++ struct ip_conntrack_expect* exp, struct sk_buff** pskb)
++{
++ /* XXX: unmangle */
++ return NF_ACCEPT;
++}
++
++static uint
++help(struct ip_conntrack* ct,
++ struct ip_conntrack_expect* exp,
++ struct ip_nat_info* info,
++ enum ip_conntrack_info ctinfo,
++ unsigned int hooknum,
++ struct sk_buff** pskb)
++{
++ struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
++ struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
++ uint datalen;
++ int dir;
++ struct ip_ct_rtsp_expect* ct_rtsp_info;
++ int rc = NF_ACCEPT;
++
++ if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
++ {
++ DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
++ return NF_ACCEPT;
++ }
++
++ ct_rtsp_info = &exp->help.exp_rtsp_info;
++
++ /*
++ * Only mangle things once: original direction in POST_ROUTING
++ * and reply direction on PRE_ROUTING.
++ */
++ dir = CTINFO2DIR(ctinfo);
++ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
++ || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
++ {
++ DEBUGP("Not touching dir %s at hook %s\n",
++ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
++ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
++ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
++ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
++ return NF_ACCEPT;
++ }
++ DEBUGP("got beyond not touching\n");
++
++ datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
++
++ LOCK_BH(&ip_rtsp_lock);
++ /* Ensure the packet contains all of the marked data */
++ if (!between(exp->seq + ct_rtsp_info->len,
++ ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
++ {
++ /* Partial retransmission? Probably a hacker. */
++ if (net_ratelimit())
++ {
++ INFOP("partial packet %u/%u in %u/%u\n",
++ exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
++ }
++ UNLOCK_BH(&ip_rtsp_lock);
++ return NF_DROP;
++ }
++
++ switch (dir)
++ {
++ case IP_CT_DIR_ORIGINAL:
++ rc = help_out(ct, ctinfo, exp, pskb);
++ break;
++ case IP_CT_DIR_REPLY:
++ rc = help_in(ct, ctinfo, exp, pskb);
++ break;
++ }
++ UNLOCK_BH(&ip_rtsp_lock);
++
++ return rc;
++}
++
++static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
++static char rtsp_names[MAX_PORTS][10];
++
++/* This function is intentionally _NOT_ defined as __exit */
++static void
++fini(void)
++{
++ int i;
++
++ for (i = 0; i < num_ports; i++)
++ {
++ DEBUGP("unregistering helper for port %d\n", ports[i]);
++ ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
++ }
++}
++
++static int __init
++init(void)
++{
++ int ret = 0;
++ int i;
++ struct ip_nat_helper* hlpr;
++ char* tmpname;
++
++ printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
++
++ if (ports[0] == 0)
++ {
++ ports[0] = RTSP_PORT;
++ }
++
++ for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
++ {
++ hlpr = &ip_nat_rtsp_helpers[i];
++ memset(hlpr, 0, sizeof(struct ip_nat_helper));
++
++ hlpr->tuple.dst.protonum = IPPROTO_TCP;
++ hlpr->tuple.src.u.tcp.port = htons(ports[i]);
++ hlpr->mask.src.u.tcp.port = 0xFFFF;
++ hlpr->mask.dst.protonum = 0xFFFF;
++ hlpr->help = help;
++ hlpr->flags = 0;
++ hlpr->me = THIS_MODULE;
++ hlpr->expect = expected;
++
++ tmpname = &rtsp_names[i][0];
++ if (ports[i] == RTSP_PORT)
++ {
++ sprintf(tmpname, "rtsp");
++ }
++ else
++ {
++ sprintf(tmpname, "rtsp-%d", i);
++ }
++ hlpr->name = tmpname;
++
++ DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
++ ret = ip_nat_helper_register(hlpr);
++
++ if (ret)
++ {
++ printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
++ fini();
++ return 1;
++ }
++ num_ports++;
++ }
++ if (stunaddr != NULL)
++ {
++ extip = in_aton(stunaddr);
++ }
++ if (destaction != NULL)
++ {
++ if (strcmp(destaction, "auto") == 0)
++ {
++ dstact = DSTACT_AUTO;
++ }
++ if (strcmp(destaction, "strip") == 0)
++ {
++ dstact = DSTACT_STRIP;
++ }
++ if (strcmp(destaction, "none") == 0)
++ {
++ dstact = DSTACT_NONE;
++ }
++ }
++ return ret;
++}
++
++module_init(init);
++module_exit(fini);
+--- linux-2.4.32/arch/mips/kernel/mips_ksyms.c 2006-03-01 00:49:34.142887320 +0100
++++ linux-2.4.32.new/arch/mips/kernel/mips_ksyms.c 2006-03-01 00:55:14.469149864 +0100
+@@ -52,6 +52,7 @@
+ /*
+ * String functions
+ */
++EXPORT_SYMBOL_NOVERS(memchr);
+ EXPORT_SYMBOL_NOVERS(memcmp);
+ EXPORT_SYMBOL_NOVERS(memset);
+ EXPORT_SYMBOL_NOVERS(memcpy);
+diff -urN linux-2.4.32/include/linux/netfilter_helpers.h linux-2.4.32.new/include/linux/netfilter_helpers.h
+--- linux-2.4.32/include/linux/netfilter_helpers.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32.new/include/linux/netfilter_helpers.h 2006-03-01 00:55:14.470149712 +0100
+@@ -0,0 +1,133 @@
++/*
++ * Helpers for netfiler modules. This file provides implementations for basic
++ * functions such as strncasecmp(), etc.
++ *
++ * gcc will warn for defined but unused functions, so we only include the
++ * functions requested. The following macros are used:
++ * NF_NEED_STRNCASECMP nf_strncasecmp()
++ * NF_NEED_STRTOU16 nf_strtou16()
++ * NF_NEED_STRTOU32 nf_strtou32()
++ */
++#ifndef _NETFILTER_HELPERS_H
++#define _NETFILTER_HELPERS_H
++
++/* Only include these functions for kernel code. */
++#ifdef __KERNEL__
++
++#include <linux/ctype.h>
++#define iseol(c) ( (c) == '\r' || (c) == '\n' )
++
++/*
++ * The standard strncasecmp()
++ */
++#ifdef NF_NEED_STRNCASECMP
++static int
++nf_strncasecmp(const char* s1, const char* s2, u_int32_t len)
++{
++ if (s1 == NULL || s2 == NULL)
++ {
++ if (s1 == NULL && s2 == NULL)
++ {
++ return 0;
++ }
++ return (s1 == NULL) ? -1 : 1;
++ }
++ while (len > 0 && tolower(*s1) == tolower(*s2))
++ {
++ len--;
++ s1++;
++ s2++;
++ }
++ return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) );
++}
++#endif /* NF_NEED_STRNCASECMP */
++
++/*
++ * Parse a string containing a 16-bit unsigned integer.
++ * Returns the number of chars used, or zero if no number is found.
++ */
++#ifdef NF_NEED_STRTOU16
++static int
++nf_strtou16(const char* pbuf, u_int16_t* pval)
++{
++ int n = 0;
++
++ *pval = 0;
++ while (isdigit(pbuf[n]))
++ {
++ *pval = (*pval * 10) + (pbuf[n] - '0');
++ n++;
++ }
++
++ return n;
++}
++#endif /* NF_NEED_STRTOU16 */
++
++/*
++ * Parse a string containing a 32-bit unsigned integer.
++ * Returns the number of chars used, or zero if no number is found.
++ */
++#ifdef NF_NEED_STRTOU32
++static int
++nf_strtou32(const char* pbuf, u_int32_t* pval)
++{
++ int n = 0;
++
++ *pval = 0;
++ while (pbuf[n] >= '0' && pbuf[n] <= '9')
++ {
++ *pval = (*pval * 10) + (pbuf[n] - '0');
++ n++;
++ }
++
++ return n;
++}
++#endif /* NF_NEED_STRTOU32 */
++
++/*
++ * Given a buffer and length, advance to the next line and mark the current
++ * line.
++ */
++#ifdef NF_NEED_NEXTLINE
++static int
++nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
++{
++ uint off = *poff;
++ uint physlen = 0;
++
++ if (off >= len)
++ {
++ return 0;
++ }
++
++ while (p[off] != '\n')
++ {
++ if (len-off <= 1)
++ {
++ return 0;
++ }
++
++ physlen++;
++ off++;
++ }
++
++ /* if we saw a crlf, physlen needs adjusted */
++ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
++ {
++ physlen--;
++ }
++
++ /* advance past the newline */
++ off++;
++
++ *plineoff = *poff;
++ *plinelen = physlen;
++ *poff = off;
++
++ return 1;
++}
++#endif /* NF_NEED_NEXTLINE */
++
++#endif /* __KERNEL__ */
++
++#endif /* _NETFILTER_HELPERS_H */
+diff -urN linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
+--- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 2006-03-01 00:55:14.472149408 +0100
+@@ -0,0 +1,68 @@
++/*
++ * RTSP extension for IP connection tracking.
++ * (C) 2003 by Tom Marshall <tmarshall@real.com>
++ * based on ip_conntrack_irc.h
++ *
++ * 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 _IP_CONNTRACK_RTSP_H
++#define _IP_CONNTRACK_RTSP_H
++
++/* #define IP_NF_RTSP_DEBUG */
++#define IP_NF_RTSP_VERSION "0.01"
++
++/* port block types */
++typedef enum {
++ pb_single, /* client_port=x */
++ pb_range, /* client_port=x-y */
++ pb_discon /* client_port=x/y (rtspbis) */
++} portblock_t;
++
++/* We record seq number and length of rtsp headers here, all in host order. */
++
++/*
++ * This structure is per expected connection. It is a member of struct
++ * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored
++ * there and we are expected to only store the length of the data which
++ * needs replaced. If a packet contains multiple RTSP messages, we create
++ * one expected connection per message.
++ *
++ * We use these variables to mark the entire header block. This may seem
++ * like overkill, but the nature of RTSP requires it. A header may appear
++ * multiple times in a message. We must treat two Transport headers the
++ * same as one Transport header with two entries.
++ */
++struct ip_ct_rtsp_expect
++{
++ u_int32_t len; /* length of header block */
++ portblock_t pbtype; /* Type of port block that was requested */
++ u_int16_t loport; /* Port that was requested, low or first */
++ u_int16_t hiport; /* Port that was requested, high or second */
++#if 0
++ uint method; /* RTSP method */
++ uint cseq; /* CSeq from request */
++#endif
++};
++
++/* This structure exists only once per master */
++struct ip_ct_rtsp_master
++{
++ /* Empty (?) */
++};
++
++
++#ifdef __KERNEL__
++
++#include <linux/netfilter_ipv4/lockhelp.h>
++
++#define RTSP_PORT 554
++
++/* Protects rtsp part of conntracks */
++DECLARE_LOCK_EXTERN(ip_rtsp_lock);
++
++#endif /* __KERNEL__ */
++
++#endif /* _IP_CONNTRACK_RTSP_H */
+diff -urN linux-2.4.32/include/linux/netfilter_mime.h linux-2.4.32.new/include/linux/netfilter_mime.h
+--- linux-2.4.32/include/linux/netfilter_mime.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32.new/include/linux/netfilter_mime.h 2006-03-01 00:55:14.473149256 +0100
+@@ -0,0 +1,90 @@
++/*
++ * MIME functions for netfilter modules. This file provides implementations
++ * for basic MIME parsing. MIME headers are used in many protocols, such as
++ * HTTP, RTSP, SIP, etc.
++ *
++ * gcc will warn for defined but unused functions, so we only include the
++ * functions requested. The following macros are used:
++ * NF_NEED_MIME_NEXTLINE nf_mime_nextline()
++ */
++#ifndef _NETFILTER_MIME_H
++#define _NETFILTER_MIME_H
++
++/* Only include these functions for kernel code. */
++#ifdef __KERNEL__
++
++#include <linux/kernel.h>
++#include <linux/ctype.h>
++
++/*
++ * Given a buffer and length, advance to the next line and mark the current
++ * line. If the current line is empty, *plinelen will be set to zero. If
++ * not, it will be set to the actual line length (including CRLF).
++ *
++ * 'line' in this context means logical line (includes LWS continuations).
++ * Returns 1 on success, 0 on failure.
++ */
++#ifdef NF_NEED_MIME_NEXTLINE
++static int
++nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
++{
++ uint off = *poff;
++ uint physlen = 0;
++ int is_first_line = 1;
++
++ if (off >= len)
++ {
++ return 0;
++ }
++
++ do
++ {
++ while (p[off] != '\n')
++ {
++ if (len-off <= 1)
++ {
++ return 0;
++ }
++
++ physlen++;
++ off++;
++ }
++
++ /* if we saw a crlf, physlen needs adjusted */
++ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
++ {
++ physlen--;
++ }
++
++ /* advance past the newline */
++ off++;
++
++ /* check for an empty line */
++ if (physlen == 0)
++ {
++ break;
++ }
++
++ /* check for colon on the first physical line */
++ if (is_first_line)
++ {
++ is_first_line = 0;
++ if (memchr(p+(*poff), ':', physlen) == NULL)
++ {
++ return 0;
++ }
++ }
++ }
++ while (p[off] == ' ' || p[off] == '\t');
++
++ *plineoff = *poff;
++ *plinelen = (physlen == 0) ? 0 : (off - *poff);
++ *poff = off;
++
++ return 1;
++}
++#endif /* NF_NEED_MIME_NEXTLINE */
++
++#endif /* __KERNEL__ */
++
++#endif /* _NETFILTER_MIME_H */
+--- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h 2006-03-01 00:53:57.889791696 +0100
++++ linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack.h 2006-03-01 01:06:32.178122440 +0100
+@@ -72,6 +72,7 @@
+ #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
+ #include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
+ #include <linux/netfilter_ipv4/ip_conntrack_h323.h>
++#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
+
+ /* per expectation: application helper private data */
+ union ip_conntrack_expect_help {
+@@ -81,6 +82,7 @@
+ struct ip_ct_irc_expect exp_irc_info;
+ struct ip_ct_pptp_expect exp_pptp_info;
+ struct ip_ct_h225_expect exp_h225_info;
++ struct ip_ct_rtsp_expect exp_rtsp_info;
+
+ #ifdef CONFIG_IP_NF_NAT_NEEDED
+ union {
+@@ -96,6 +98,7 @@
+ struct ip_ct_irc_master ct_irc_info;
+ struct ip_ct_pptp_master ct_pptp_info;
+ struct ip_ct_h225_master ct_h225_info;
++ struct ip_ct_rtsp_master ct_rtsp_info;
+ };
+
+ #ifdef CONFIG_IP_NF_NAT_NEEDED
diff --git a/target/linux/generic-2.4/patches/615-netfilter_nat_mms.patch b/target/linux/generic-2.4/patches/615-netfilter_nat_mms.patch
new file mode 100644
index 0000000000..3871d59395
--- /dev/null
+++ b/target/linux/generic-2.4/patches/615-netfilter_nat_mms.patch
@@ -0,0 +1,739 @@
+diff -urN linux-2.4.32/net/ipv4/netfilter/Config.in linux-2.4.32.new/net/ipv4/netfilter/Config.in
+--- linux-2.4.32/net/ipv4/netfilter/Config.in 2006-03-01 01:12:48.268947944 +0100
++++ linux-2.4.32.new/net/ipv4/netfilter/Config.in 2006-03-01 01:14:53.455916632 +0100
+@@ -17,6 +17,7 @@
+ dep_tristate ' PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE
+ dep_tristate ' H.323 (netmeeting) support' CONFIG_IP_NF_H323 $CONFIG_IP_NF_CONNTRACK
+ dep_tristate ' RTSP protocol support' CONFIG_IP_NF_RTSP $CONFIG_IP_NF_CONNTRACK
++ dep_tristate ' MMS protocol support' CONFIG_IP_NF_MMS $CONFIG_IP_NF_CONNTRACK
+ fi
+
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+@@ -127,6 +128,13 @@
+ define_tristate CONFIG_IP_NF_NAT_RTSP $CONFIG_IP_NF_NAT
+ fi
+ fi
++ if [ "$CONFIG_IP_NF_MMS" = "m" ]; then
++ define_tristate CONFIG_IP_NF_NAT_MMS m
++ else
++ if [ "$CONFIG_IP_NF_MMS" = "y" ]; then
++ define_tristate CONFIG_IP_NF_NAT_MMS $CONFIG_IP_NF_NAT
++ fi
++ fi
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ dep_tristate ' Basic SNMP-ALG support (EXPERIMENTAL)' CONFIG_IP_NF_NAT_SNMP_BASIC $CONFIG_IP_NF_NAT
+ fi
+diff -urN linux-2.4.32/net/ipv4/netfilter/Makefile linux-2.4.32.new/net/ipv4/netfilter/Makefile
+--- linux-2.4.32/net/ipv4/netfilter/Makefile 2006-03-01 01:12:48.270947640 +0100
++++ linux-2.4.32.new/net/ipv4/netfilter/Makefile 2006-03-01 01:15:25.263081208 +0100
+@@ -61,6 +61,10 @@
+ ifdef CONFIG_IP_NF_NAT_RTSP
+ export-objs += ip_conntrack_rtsp.o
+ endif
++obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
++ifdef CONFIG_IP_NF_NAT_MMS
++ export-objs += ip_conntrack_mms.o
++endif
+
+
+
+@@ -73,6 +77,7 @@
+ obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
+ obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
+ obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
++obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
+
+ # generic IP tables
+ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
+diff -urN linux-2.4.32/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.4.32.new/net/ipv4/netfilter/ip_conntrack_mms.c
+--- linux-2.4.32/net/ipv4/netfilter/ip_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32.new/net/ipv4/netfilter/ip_conntrack_mms.c 2006-03-01 01:13:32.991149136 +0100
+@@ -0,0 +1,292 @@
++/* MMS extension for IP connection tracking
++ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
++ * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
++ *
++ * ip_conntrack_mms.c v0.3 2002-09-22
++ *
++ * 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.
++ *
++ * Module load syntax:
++ * insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
++ *
++ * Please give the ports of all MMS servers You wish to connect to.
++ * If you don't specify ports, the default will be TCP port 1755.
++ *
++ * More info on MMS protocol, firewalls and NAT:
++ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
++ * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
++ *
++ * The SDP project people are reverse-engineering MMS:
++ * http://get.to/sdp
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/netfilter.h>
++#include <linux/ip.h>
++#include <linux/ctype.h>
++#include <net/checksum.h>
++#include <net/tcp.h>
++
++#include <linux/netfilter_ipv4/lockhelp.h>
++#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
++#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
++
++DECLARE_LOCK(ip_mms_lock);
++struct module *ip_conntrack_mms = THIS_MODULE;
++
++#define MAX_PORTS 8
++static int ports[MAX_PORTS];
++static int ports_c;
++#ifdef MODULE_PARM
++MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
++#endif
++
++#define DEBUGP(format, args...)
++
++#ifdef CONFIG_IP_NF_NAT_NEEDED
++EXPORT_SYMBOL(ip_mms_lock);
++#endif
++
++MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
++MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
++MODULE_LICENSE("GPL");
++
++/* #define isdigit(c) (c >= '0' && c <= '9') */
++
++/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
++static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
++{
++ int i;
++ for (i = 0; i < unicode_size; ++i) {
++ string[i] = (char)(unicode[i]);
++ }
++ string[unicode_size] = 0x00;
++}
++
++__inline static int atoi(char *s)
++{
++ int i=0;
++ while (isdigit(*s)) {
++ i = i*10 + *(s++) - '0';
++ }
++ return i;
++}
++
++/* convert ip address string like "192.168.0.10" to unsigned int */
++__inline static u_int32_t asciiiptoi(char *s)
++{
++ unsigned int i, j, k;
++
++ for(i=k=0; k<3; ++k, ++s, i<<=8) {
++ i+=atoi(s);
++ for(j=0; (*(++s) != '.') && (j<3); ++j)
++ ;
++ }
++ i+=atoi(s);
++ return ntohl(i);
++}
++
++int parse_mms(const char *data,
++ const unsigned int datalen,
++ u_int32_t *mms_ip,
++ u_int16_t *mms_proto,
++ u_int16_t *mms_port,
++ char **mms_string_b,
++ char **mms_string_e,
++ char **mms_padding_e)
++{
++ int unicode_size, i;
++ char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
++ char getlengthstring[28];
++
++ for(unicode_size=0;
++ (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
++ unicode_size++)
++ if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
++ return -1; /* out of bounds - incomplete packet */
++
++ unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
++ DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
++
++ /* IP address ? */
++ *mms_ip = asciiiptoi(tempstring+2);
++
++ i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
++
++ /* protocol ? */
++ if(strncmp(tempstring+3+i, "TCP", 3)==0)
++ *mms_proto = IPPROTO_TCP;
++ else if(strncmp(tempstring+3+i, "UDP", 3)==0)
++ *mms_proto = IPPROTO_UDP;
++
++ /* port ? */
++ *mms_port = atoi(tempstring+7+i);
++
++ /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port"
++ unicode string, one to the end of the string, and one to the end
++ of the packet, since we must keep track of the number of bytes
++ between end of the unicode string and the end of packet (padding) */
++ *mms_string_b = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
++ *mms_string_e = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
++ *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
++ return 0;
++}
++
++
++static int help(const struct iphdr *iph, size_t len,
++ struct ip_conntrack *ct,
++ enum ip_conntrack_info ctinfo)
++{
++ /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
++ struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
++ const char *data = (const char *)tcph + tcph->doff * 4;
++ unsigned int tcplen = len - iph->ihl * 4;
++ unsigned int datalen = tcplen - tcph->doff * 4;
++ int dir = CTINFO2DIR(ctinfo);
++ struct ip_conntrack_expect expect, *exp = &expect;
++ struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
++
++ u_int32_t mms_ip;
++ u_int16_t mms_proto;
++ char mms_proto_string[8];
++ u_int16_t mms_port;
++ char *mms_string_b, *mms_string_e, *mms_padding_e;
++
++ /* Until there's been traffic both ways, don't look in packets. */
++ if (ctinfo != IP_CT_ESTABLISHED
++ && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
++ DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
++ return NF_ACCEPT;
++ }
++
++ /* Not whole TCP header? */
++ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
++ DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
++ return NF_ACCEPT;
++ }
++
++ /* Checksum invalid? Ignore. */
++ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
++ csum_partial((char *)tcph, tcplen, 0))) {
++ DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
++ tcph, tcplen, NIPQUAD(iph->saddr),
++ NIPQUAD(iph->daddr));
++ return NF_ACCEPT;
++ }
++
++ /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
++ if( (MMS_SRV_MSG_OFFSET < datalen) &&
++ ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
++ DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n",
++ (u8)*(data+36), (u8)*(data+37),
++ (u8)*(data+38), (u8)*(data+39),
++ datalen);
++ if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
++ &mms_string_b, &mms_string_e, &mms_padding_e))
++ if(net_ratelimit())
++ printk(KERN_WARNING
++ "ip_conntrack_mms: Unable to parse data payload\n");
++
++ memset(&expect, 0, sizeof(expect));
++
++ sprintf(mms_proto_string, "(%u)", mms_proto);
++ DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
++ mms_proto == IPPROTO_TCP ? "TCP"
++ : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
++ NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
++ NIPQUAD(mms_ip),
++ mms_port);
++
++ /* it's possible that the client will just ask the server to tunnel
++ the stream over the same TCP session (from port 1755): there's
++ shouldn't be a need to add an expectation in that case, but it
++ makes NAT packet mangling so much easier */
++ LOCK_BH(&ip_mms_lock);
++
++ DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
++
++ exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
++ exp_mms_info->len = (mms_string_e - mms_string_b);
++ exp_mms_info->padding = (mms_padding_e - mms_string_e);
++ exp_mms_info->port = mms_port;
++
++ DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
++ exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
++
++ exp->tuple = ((struct ip_conntrack_tuple)
++ { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
++ { mms_ip,
++ { (__u16) ntohs(mms_port) },
++ mms_proto } }
++ );
++ exp->mask = ((struct ip_conntrack_tuple)
++ { { 0xFFFFFFFF, { 0 } },
++ { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
++ exp->expectfn = NULL;
++ ip_conntrack_expect_related(ct, &expect);
++ UNLOCK_BH(&ip_mms_lock);
++ }
++
++ return NF_ACCEPT;
++}
++
++static struct ip_conntrack_helper mms[MAX_PORTS];
++static char mms_names[MAX_PORTS][10];
++
++/* Not __exit: called from init() */
++static void fini(void)
++{
++ int i;
++ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
++ DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
++ ports[i]);
++ ip_conntrack_helper_unregister(&mms[i]);
++ }
++}
++
++static int __init init(void)
++{
++ int i, ret;
++ char *tmpname;
++
++ if (ports[0] == 0)
++ ports[0] = MMS_PORT;
++
++ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
++ memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
++ mms[i].tuple.src.u.tcp.port = htons(ports[i]);
++ mms[i].tuple.dst.protonum = IPPROTO_TCP;
++ mms[i].mask.src.u.tcp.port = 0xFFFF;
++ mms[i].mask.dst.protonum = 0xFFFF;
++ mms[i].max_expected = 1;
++ mms[i].timeout = 0;
++ mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
++ mms[i].me = THIS_MODULE;
++ mms[i].help = help;
++
++ tmpname = &mms_names[i][0];
++ if (ports[i] == MMS_PORT)
++ sprintf(tmpname, "mms");
++ else
++ sprintf(tmpname, "mms-%d", ports[i]);
++ mms[i].name = tmpname;
++
++ DEBUGP("ip_conntrack_mms: registering helper for port %d\n",
++ ports[i]);
++ ret = ip_conntrack_helper_register(&mms[i]);
++
++ if (ret) {
++ fini();
++ return ret;
++ }
++ ports_c++;
++ }
++ return 0;
++}
++
++module_init(init);
++module_exit(fini);
+diff -urN linux-2.4.32/net/ipv4/netfilter/ip_nat_mms.c linux-2.4.32.new/net/ipv4/netfilter/ip_nat_mms.c
+--- linux-2.4.32/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32.new/net/ipv4/netfilter/ip_nat_mms.c 2006-03-01 01:13:32.992148984 +0100
+@@ -0,0 +1,330 @@
++/* MMS extension for TCP NAT alteration.
++ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
++ * based on ip_nat_ftp.c and ip_nat_irc.c
++ *
++ * ip_nat_mms.c v0.3 2002-09-22
++ *
++ * 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.
++ *
++ * Module load syntax:
++ * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
++ *
++ * Please give the ports of all MMS servers You wish to connect to.
++ * If you don't specify ports, the default will be TCP port 1755.
++ *
++ * More info on MMS protocol, firewalls and NAT:
++ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
++ * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
++ *
++ * The SDP project people are reverse-engineering MMS:
++ * http://get.to/sdp
++ */
++
++
++#include <linux/module.h>
++#include <linux/netfilter_ipv4.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <net/tcp.h>
++#include <linux/netfilter_ipv4/ip_nat.h>
++#include <linux/netfilter_ipv4/ip_nat_helper.h>
++#include <linux/netfilter_ipv4/ip_nat_rule.h>
++#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
++#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
++
++#define DEBUGP(format, args...)
++#define DUMP_BYTES(address, counter)
++
++#define MAX_PORTS 8
++static int ports[MAX_PORTS];
++static int ports_c = 0;
++
++#ifdef MODULE_PARM
++MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
++#endif
++
++MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
++MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
++MODULE_LICENSE("GPL");
++
++DECLARE_LOCK_EXTERN(ip_mms_lock);
++
++
++static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
++ struct ip_conntrack *ct,
++ struct sk_buff **pskb,
++ enum ip_conntrack_info ctinfo,
++ struct ip_conntrack_expect *expect)
++{
++ u_int32_t newip;
++ struct ip_conntrack_tuple t;
++ struct iphdr *iph = (*pskb)->nh.iph;
++ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
++ char *data = (char *)tcph + tcph->doff * 4;
++ int i, j, k, port;
++ u_int16_t mms_proto;
++
++ u_int32_t *mms_chunkLenLV = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
++ u_int32_t *mms_chunkLenLM = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
++ u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
++
++ int zero_padding;
++
++ char buffer[28]; /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
++ char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
++ char proto_string[6];
++
++ MUST_BE_LOCKED(&ip_mms_lock);
++
++ /* what was the protocol again ? */
++ mms_proto = expect->tuple.dst.protonum;
++ sprintf(proto_string, "%u", mms_proto);
++
++ DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
++ expect->seq, ct_mms_info->len, ntohl(tcph->seq),
++ mms_proto == IPPROTO_UDP ? "UDP"
++ : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
++
++ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
++
++ /* Alter conntrack's expectations. */
++ t = expect->tuple;
++ t.dst.ip = newip;
++ for (port = ct_mms_info->port; port != 0; port++) {
++ t.dst.u.tcp.port = htons(port);
++ if (ip_conntrack_change_expect(expect, &t) == 0) {
++ DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
++ break;
++ }
++ }
++
++ if(port == 0)
++ return 0;
++
++ sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
++ NIPQUAD(newip),
++ expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
++ : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
++ port);
++ DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
++
++ memset(unicode_buffer, 0, sizeof(char)*75);
++
++ for (i=0; i<strlen(buffer); ++i)
++ *(unicode_buffer+i*2)=*(buffer+i);
++
++ DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
++ DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
++ DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
++
++ /* add end of packet to it */
++ for (j=0; j<ct_mms_info->padding; ++j) {
++ DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n",
++ i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
++ *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
++ }
++
++ /* pad with zeroes at the end ? see explanation of weird math below */
++ zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
++ for (k=0; k<zero_padding; ++k)
++ *(unicode_buffer+i*2+j+k)= (char)0;
++
++ DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
++ DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
++ *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
++
++ /* explanation, before I forget what I did:
++ strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
++ divide by 8 and add 3 to compute the mms_chunkLenLM field,
++ but note that things may have to be padded with zeroes to align by 8
++ bytes, hence we add 7 and divide by 8 to get the correct length */
++ *mms_chunkLenLM = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
++ *mms_chunkLenLV = *mms_chunkLenLM+2;
++ *mms_messageLength = *mms_chunkLenLV*8;
++
++ DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
++ *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
++
++ ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
++ expect->seq - ntohl(tcph->seq),
++ ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
++ strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
++ DUMP_BYTES(unicode_buffer, 60);
++
++ return 1;
++}
++
++static unsigned int
++mms_nat_expected(struct sk_buff **pskb,
++ unsigned int hooknum,
++ struct ip_conntrack *ct,
++ struct ip_nat_info *info)
++{
++ struct ip_nat_multi_range mr;
++ u_int32_t newdstip, newsrcip, newip;
++
++ struct ip_conntrack *master = master_ct(ct);
++
++ IP_NF_ASSERT(info);
++ IP_NF_ASSERT(master);
++
++ IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
++
++ DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
++
++ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
++ newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
++ DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
++ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
++ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
++ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
++ NIPQUAD(newsrcip), NIPQUAD(newdstip));
++
++ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
++ newip = newsrcip;
++ else
++ newip = newdstip;
++
++ DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
++
++ mr.rangesize = 1;
++ /* We don't want to manip the per-protocol, just the IPs. */
++ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
++ mr.range[0].min_ip = mr.range[0].max_ip = newip;
++
++ return ip_nat_setup_info(ct, &mr, hooknum);
++}
++
++
++static unsigned int mms_nat_help(struct ip_conntrack *ct,
++ struct ip_conntrack_expect *exp,
++ struct ip_nat_info *info,
++ enum ip_conntrack_info ctinfo,
++ unsigned int hooknum,
++ struct sk_buff **pskb)
++{
++ struct iphdr *iph = (*pskb)->nh.iph;
++ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
++ unsigned int datalen;
++ int dir;
++ struct ip_ct_mms_expect *ct_mms_info;
++
++ if (!exp)
++ DEBUGP("ip_nat_mms: no exp!!");
++
++ ct_mms_info = &exp->help.exp_mms_info;
++
++ /* Only mangle things once: original direction in POST_ROUTING
++ and reply direction on PRE_ROUTING. */
++ dir = CTINFO2DIR(ctinfo);
++ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
++ ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
++ DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
++ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
++ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
++ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
++ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
++ return NF_ACCEPT;
++ }
++ DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
++ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
++ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
++ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
++ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
++
++ datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
++
++ DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
++ exp->seq + ct_mms_info->len,
++ ntohl(tcph->seq),
++ ntohl(tcph->seq) + datalen);
++
++ LOCK_BH(&ip_mms_lock);
++ /* Check wether the whole IP/proto/port pattern is carried in the payload */
++ if (between(exp->seq + ct_mms_info->len,
++ ntohl(tcph->seq),
++ ntohl(tcph->seq) + datalen)) {
++ if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
++ UNLOCK_BH(&ip_mms_lock);
++ return NF_DROP;
++ }
++ } else {
++ /* Half a match? This means a partial retransmisison.
++ It's a cracker being funky. */
++ if (net_ratelimit()) {
++ printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
++ exp->seq, ct_mms_info->len,
++ ntohl(tcph->seq),
++ ntohl(tcph->seq) + datalen);
++ }
++ UNLOCK_BH(&ip_mms_lock);
++ return NF_DROP;
++ }
++ UNLOCK_BH(&ip_mms_lock);
++
++ return NF_ACCEPT;
++}
++
++static struct ip_nat_helper mms[MAX_PORTS];
++static char mms_names[MAX_PORTS][10];
++
++/* Not __exit: called from init() */
++static void fini(void)
++{
++ int i;
++
++ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
++ DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
++ ip_nat_helper_unregister(&mms[i]);
++ }
++}
++
++static int __init init(void)
++{
++ int i, ret = 0;
++ char *tmpname;
++
++ if (ports[0] == 0)
++ ports[0] = MMS_PORT;
++
++ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
++
++ memset(&mms[i], 0, sizeof(struct ip_nat_helper));
++
++ mms[i].tuple.dst.protonum = IPPROTO_TCP;
++ mms[i].tuple.src.u.tcp.port = htons(ports[i]);
++ mms[i].mask.dst.protonum = 0xFFFF;
++ mms[i].mask.src.u.tcp.port = 0xFFFF;
++ mms[i].help = mms_nat_help;
++ mms[i].me = THIS_MODULE;
++ mms[i].flags = 0;
++ mms[i].expect = mms_nat_expected;
++
++ tmpname = &mms_names[i][0];
++ if (ports[i] == MMS_PORT)
++ sprintf(tmpname, "mms");
++ else
++ sprintf(tmpname, "mms-%d", i);
++ mms[i].name = tmpname;
++
++ DEBUGP("ip_nat_mms: register helper for port %d\n",
++ ports[i]);
++ ret = ip_nat_helper_register(&mms[i]);
++
++ if (ret) {
++ printk("ip_nat_mms: error registering "
++ "helper for port %d\n", ports[i]);
++ fini();
++ return ret;
++ }
++ ports_c++;
++ }
++
++ return ret;
++}
++
++module_init(init);
++module_exit(fini);
+diff -urN linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack.h
+--- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h 2006-03-01 01:12:47.910002512 +0100
++++ linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack.h 2006-03-01 01:16:16.710260048 +0100
+@@ -73,6 +73,7 @@
+ #include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
+ #include <linux/netfilter_ipv4/ip_conntrack_h323.h>
+ #include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
++#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
+
+ /* per expectation: application helper private data */
+ union ip_conntrack_expect_help {
+@@ -83,6 +84,7 @@
+ struct ip_ct_pptp_expect exp_pptp_info;
+ struct ip_ct_h225_expect exp_h225_info;
+ struct ip_ct_rtsp_expect exp_rtsp_info;
++ struct ip_ct_mms_expect exp_mms_info;
+
+ #ifdef CONFIG_IP_NF_NAT_NEEDED
+ union {
+@@ -99,6 +101,7 @@
+ struct ip_ct_pptp_master ct_pptp_info;
+ struct ip_ct_h225_master ct_h225_info;
+ struct ip_ct_rtsp_master ct_rtsp_info;
++ struct ip_ct_mms_master ct_mms_info;
+ };
+
+ #ifdef CONFIG_IP_NF_NAT_NEEDED
+diff -urN linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack_mms.h
+--- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack_mms.h 2006-03-01 01:13:32.993148832 +0100
+@@ -0,0 +1,31 @@
++#ifndef _IP_CONNTRACK_MMS_H
++#define _IP_CONNTRACK_MMS_H
++/* MMS tracking. */
++
++#ifdef __KERNEL__
++#include <linux/netfilter_ipv4/lockhelp.h>
++
++DECLARE_LOCK_EXTERN(ip_mms_lock);
++
++#define MMS_PORT 1755
++#define MMS_SRV_MSG_ID 196610
++
++#define MMS_SRV_MSG_OFFSET 36
++#define MMS_SRV_UNICODE_STRING_OFFSET 60
++#define MMS_SRV_CHUNKLENLV_OFFSET 16
++#define MMS_SRV_CHUNKLENLM_OFFSET 32
++#define MMS_SRV_MESSAGELENGTH_OFFSET 8
++#endif
++
++/* This structure is per expected connection */
++struct ip_ct_mms_expect {
++ u_int32_t len;
++ u_int32_t padding;
++ u_int16_t port;
++};
++
++/* This structure exists only once per master */
++struct ip_ct_mms_master {
++};
++
++#endif /* _IP_CONNTRACK_MMS_H */
diff --git a/target/linux/generic-2.4/patches/616-netfilter_imq.patch b/target/linux/generic-2.4/patches/616-netfilter_imq.patch
new file mode 100644
index 0000000000..e2e45af882
--- /dev/null
+++ b/target/linux/generic-2.4/patches/616-netfilter_imq.patch
@@ -0,0 +1,748 @@
+diff -aurN linux-2.4.28-orig/Documentation/Configure.help linux-2.4.28/Documentation/Configure.help
+--- linux-2.4.28-orig/Documentation/Configure.help 2004-11-17 11:54:20.000000000 +0000
++++ linux-2.4.28/Documentation/Configure.help 2004-12-14 11:43:42.000000000 +0000
+@@ -3147,6 +3147,22 @@
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
++IMQ target support
++CONFIG_IP_NF_TARGET_IMQ
++ This option adds a `IMQ' target which is used to specify if and
++ to which imq device packets should get enqueued/dequeued.
++
++ If you want to compile it as a module, say M here and read
++ <file:Documentation/modules.txt>. If unsure, say `N'.
++
++IMQ target support
++CONFIG_IP6_NF_TARGET_IMQ
++ This option adds a `IMQ' target which is used to specify if and
++ to which imq device packets should get enqueued/dequeued.
++
++ If you want to compile it as a module, say M here and read
++ <file:Documentation/modules.txt>. If unsure, say `N'.
++
+ MARK target support
+ CONFIG_IP_NF_TARGET_MARK
+ This option adds a `MARK' target, which allows you to create rules
+@@ -9799,6 +9815,20 @@
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called bonding.o.
+
++Intermediate queueing device support
++CONFIG_IMQ
++ The imq device(s) is used as placeholder for QoS queueing disciplines.
++ Every packet entering/leaving the ip stack can be directed through
++ the imq device where it's enqueued/dequeued to the attached qdisc.
++ This allows you to treat network devices as classes and distribute
++ bandwidth among them. Iptables is used to specify through which imq
++ device, if any, packets travel.
++
++ If you want to compile this as a module ( = code which ca be
++ inserted in and removed from the running kernel whenever you want),
++ say M here and read <file:Documentation/modules.txt>. The module
++ will be called imq.o
++
+ SLIP (serial line) support
+ CONFIG_SLIP
+ Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to
+diff -aurN linux-2.4.28-orig/drivers/net/Config.in linux-2.4.28/drivers/net/Config.in
+--- linux-2.4.28-orig/drivers/net/Config.in 2004-08-07 23:26:04.000000000 +0000
++++ linux-2.4.28/drivers/net/Config.in 2004-12-14 11:43:42.000000000 +0000
+@@ -7,6 +7,11 @@
+ tristate 'Dummy net driver support' CONFIG_DUMMY
+ tristate 'Bonding driver support' CONFIG_BONDING
+ tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER
++if [ "$CONFIG_NETFILTER" = "y" ]; then
++ tristate 'IMQ (intermediate queueing device) support' CONFIG_IMQ
++else
++ comment 'IMQ needs CONFIG_NETFILTER enabled'
++fi
+ tristate 'Universal TUN/TAP device driver support' CONFIG_TUN
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Ethertap network tap (OBSOLETE)' CONFIG_ETHERTAP
+diff -aurN linux-2.4.28-orig/drivers/net/Makefile linux-2.4.28/drivers/net/Makefile
+--- linux-2.4.28-orig/drivers/net/Makefile 2004-08-07 23:26:04.000000000 +0000
++++ linux-2.4.28/drivers/net/Makefile 2004-12-14 11:43:42.000000000 +0000
+@@ -170,6 +170,7 @@
+
+ obj-$(CONFIG_STRIP) += strip.o
+ obj-$(CONFIG_DUMMY) += dummy.o
++obj-$(CONFIG_IMQ) += imq.o
+ obj-$(CONFIG_DE600) += de600.o
+ obj-$(CONFIG_DE620) += de620.o
+ obj-$(CONFIG_AT1500) += lance.o
+diff -aurN linux-2.4.28-orig/drivers/net/imq.c linux-2.4.28/drivers/net/imq.c
+--- linux-2.4.28-orig/drivers/net/imq.c 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.4.28/drivers/net/imq.c 2004-12-14 11:43:42.000000000 +0000
+@@ -0,0 +1,321 @@
++/*
++ * Pseudo-driver for the intermediate queue device.
++ *
++ * 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: Patrick McHardy, <kaber@trash.net>
++ *
++ * The first version was written by Martin Devera, <devik@cdi.cz>
++ *
++ * Credits: Jan Rafaj <imq2t@cedric.vabo.cz>
++ * - Update patch to 2.4.21
++ * Sebastian Strollo <sstrollo@nortelnetworks.com>
++ * - Fix "Dead-loop on netdevice imq"-issue
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/config.h>
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++#include <linux/rtnetlink.h>
++#include <linux/if_arp.h>
++#include <linux/netfilter.h>
++#include <linux/netfilter_ipv4.h>
++#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
++#include <linux/netfilter_ipv6.h>
++#endif
++#include <linux/imq.h>
++#include <net/pkt_sched.h>
++
++static nf_hookfn imq_nf_hook;
++
++static struct nf_hook_ops imq_ingress_ipv4 = {
++ { NULL, NULL},
++ imq_nf_hook,
++ PF_INET,
++ NF_IP_PRE_ROUTING,
++ NF_IP_PRI_MANGLE + 1
++};
++
++static struct nf_hook_ops imq_egress_ipv4 = {
++ { NULL, NULL},
++ imq_nf_hook,
++ PF_INET,
++ NF_IP_POST_ROUTING,
++ NF_IP_PRI_LAST
++};
++
++#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
++static struct nf_hook_ops imq_ingress_ipv6 = {
++ { NULL, NULL},
++ imq_nf_hook,
++ PF_INET6,
++ NF_IP6_PRE_ROUTING,
++ NF_IP6_PRI_MANGLE + 1
++};
++
++static struct nf_hook_ops imq_egress_ipv6 = {
++ { NULL, NULL},
++ imq_nf_hook,
++ PF_INET6,
++ NF_IP6_POST_ROUTING,
++ NF_IP6_PRI_LAST
++};
++#endif
++
++static unsigned int numdevs = 2;
++
++MODULE_PARM(numdevs, "i");
++MODULE_PARM_DESC(numdevs, "number of imq devices");
++
++static struct net_device *imq_devs;
++
++
++static struct net_device_stats *imq_get_stats(struct net_device *dev)
++{
++ return (struct net_device_stats *)dev->priv;
++}
++
++/* called for packets kfree'd in qdiscs at places other than enqueue */
++static void imq_skb_destructor(struct sk_buff *skb)
++{
++ struct nf_info *info = skb->nf_info;
++
++ if (info) {
++ if (info->indev)
++ dev_put(info->indev);
++ if (info->outdev)
++ dev_put(info->outdev);
++ kfree(info);
++ }
++}
++
++static int imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
++
++ stats->tx_bytes += skb->len;
++ stats->tx_packets++;
++
++ skb->imq_flags = 0;
++ skb->destructor = NULL;
++
++ dev->trans_start = jiffies;
++ nf_reinject(skb, skb->nf_info, NF_ACCEPT);
++ return 0;
++}
++
++static int imq_nf_queue(struct sk_buff *skb, struct nf_info *info,
++ void *data)
++{
++ struct net_device *dev;
++ struct net_device_stats *stats;
++ struct sk_buff *skb2 = NULL;
++ struct Qdisc *q;
++ unsigned int index = skb->imq_flags&IMQ_F_IFMASK;
++ int ret = -1;
++
++ if (index > numdevs)
++ return -1;
++
++ dev = imq_devs + index;
++ if (!(dev->flags & IFF_UP)) {
++ skb->imq_flags = 0;
++ nf_reinject(skb, info, NF_ACCEPT);
++ return 0;
++ }
++ dev->last_rx = jiffies;
++
++ if (skb->destructor) {
++ skb2 = skb;
++ skb = skb_clone(skb, GFP_ATOMIC);
++ if (!skb)
++ return -1;
++ }
++ skb->nf_info = info;
++
++ stats = (struct net_device_stats *)dev->priv;
++ stats->rx_bytes+= skb->len;
++ stats->rx_packets++;
++
++ spin_lock_bh(&dev->queue_lock);
++ q = dev->qdisc;
++ if (q->enqueue) {
++ q->enqueue(skb_get(skb), q);
++ if (skb_shared(skb)) {
++ skb->destructor = imq_skb_destructor;
++ kfree_skb(skb);
++ ret = 0;
++ }
++ }
++ if (spin_is_locked(&dev->xmit_lock))
++ netif_schedule(dev);
++ else
++ qdisc_run(dev);
++ spin_unlock_bh(&dev->queue_lock);
++
++ if (skb2)
++ kfree_skb(ret ? skb : skb2);
++
++ return ret;
++}
++
++static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff **pskb,
++ const struct net_device *indev,
++ const struct net_device *outdev,
++ int (*okfn)(struct sk_buff *))
++{
++ if ((*pskb)->imq_flags & IMQ_F_ENQUEUE)
++ return NF_QUEUE;
++
++ return NF_ACCEPT;
++}
++
++
++static int __init imq_init_hooks(void)
++{
++ int err;
++
++ if ((err = nf_register_queue_handler(PF_INET, imq_nf_queue, NULL)))
++ goto err1;
++ if ((err = nf_register_hook(&imq_ingress_ipv4)))
++ goto err2;
++ if ((err = nf_register_hook(&imq_egress_ipv4)))
++ goto err3;
++#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
++ if ((err = nf_register_queue_handler(PF_INET6, imq_nf_queue, NULL)))
++ goto err4;
++ if ((err = nf_register_hook(&imq_ingress_ipv6)))
++ goto err5;
++ if ((err = nf_register_hook(&imq_egress_ipv6)))
++ goto err6;
++#endif
++
++ return 0;
++
++#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
++err6:
++ nf_unregister_hook(&imq_ingress_ipv6);
++err5:
++ nf_unregister_queue_handler(PF_INET6);
++err4:
++ nf_unregister_hook(&imq_egress_ipv4);
++#endif
++err3:
++ nf_unregister_hook(&imq_ingress_ipv4);
++err2:
++ nf_unregister_queue_handler(PF_INET);
++err1:
++ return err;
++}
++
++static void __exit imq_unhook(void)
++{
++ nf_unregister_hook(&imq_ingress_ipv4);
++ nf_unregister_hook(&imq_egress_ipv4);
++ nf_unregister_queue_handler(PF_INET);
++#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
++ nf_unregister_hook(&imq_ingress_ipv6);
++ nf_unregister_hook(&imq_egress_ipv6);
++ nf_unregister_queue_handler(PF_INET6);
++#endif
++}
++
++static int __init imq_dev_init(struct net_device *dev)
++{
++ dev->hard_start_xmit = imq_dev_xmit;
++ dev->type = ARPHRD_VOID;
++ dev->mtu = 1500;
++ dev->tx_queue_len = 30;
++ dev->flags = IFF_NOARP;
++ dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
++ if (dev->priv == NULL)
++ return -ENOMEM;
++ memset(dev->priv, 0, sizeof(struct net_device_stats));
++ dev->get_stats = imq_get_stats;
++
++ return 0;
++}
++
++static void imq_dev_uninit(struct net_device *dev)
++{
++ kfree(dev->priv);
++}
++
++static int __init imq_init_devs(void)
++{
++ struct net_device *dev;
++ int i;
++
++ if (!numdevs || numdevs > IMQ_MAX_DEVS) {
++ printk(KERN_ERR "numdevs has to be betweed 1 and %u\n",
++ IMQ_MAX_DEVS);
++ return -EINVAL;
++ }
++
++ imq_devs = kmalloc(sizeof(struct net_device) * numdevs, GFP_KERNEL);
++ if (!imq_devs)
++ return -ENOMEM;
++ memset(imq_devs, 0, sizeof(struct net_device) * numdevs);
++
++ /* we start counting at zero */
++ numdevs--;
++
++ for (i = 0, dev = imq_devs; i <= numdevs; i++, dev++) {
++ SET_MODULE_OWNER(dev);
++ strcpy(dev->name, "imq%d");
++ dev->init = imq_dev_init;
++ dev->uninit = imq_dev_uninit;
++
++ if (register_netdev(dev) < 0)
++ goto err_register;
++ }
++ return 0;
++
++err_register:
++ for (; i; i--)
++ unregister_netdev(--dev);
++ kfree(imq_devs);
++ return -EIO;
++}
++
++static void imq_cleanup_devs(void)
++{
++ int i;
++ struct net_device *dev = imq_devs;
++
++ for (i = 0; i <= numdevs; i++)
++ unregister_netdev(dev++);
++
++ kfree(imq_devs);
++}
++
++static int __init imq_init_module(void)
++{
++ int err;
++
++ if ((err = imq_init_devs()))
++ return err;
++ if ((err = imq_init_hooks())) {
++ imq_cleanup_devs();
++ return err;
++ }
++
++ printk(KERN_INFO "imq driver loaded.\n");
++
++ return 0;
++}
++
++static void __exit imq_cleanup_module(void)
++{
++ imq_unhook();
++ imq_cleanup_devs();
++}
++
++module_init(imq_init_module);
++module_exit(imq_cleanup_module);
++MODULE_LICENSE("GPL");
+diff -aurN linux-2.4.28-orig/include/linux/imq.h linux-2.4.28/include/linux/imq.h
+--- linux-2.4.28-orig/include/linux/imq.h 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.4.28/include/linux/imq.h 2004-12-14 11:43:42.000000000 +0000
+@@ -0,0 +1,9 @@
++#ifndef _IMQ_H
++#define _IMQ_H
++
++#define IMQ_MAX_DEVS 16
++
++#define IMQ_F_IFMASK 0x7f
++#define IMQ_F_ENQUEUE 0x80
++
++#endif /* _IMQ_H */
+diff -aurN linux-2.4.28-orig/include/linux/netfilter_ipv4/ipt_IMQ.h linux-2.4.28/include/linux/netfilter_ipv4/ipt_IMQ.h
+--- linux-2.4.28-orig/include/linux/netfilter_ipv4/ipt_IMQ.h 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.4.28/include/linux/netfilter_ipv4/ipt_IMQ.h 2004-12-14 11:43:42.000000000 +0000
+@@ -0,0 +1,8 @@
++#ifndef _IPT_IMQ_H
++#define _IPT_IMQ_H
++
++struct ipt_imq_info {
++ unsigned int todev; /* target imq device */
++};
++
++#endif /* _IPT_IMQ_H */
+diff -aurN linux-2.4.28-orig/include/linux/netfilter_ipv6/ip6t_IMQ.h linux-2.4.28/include/linux/netfilter_ipv6/ip6t_IMQ.h
+--- linux-2.4.28-orig/include/linux/netfilter_ipv6/ip6t_IMQ.h 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.4.28/include/linux/netfilter_ipv6/ip6t_IMQ.h 2004-12-14 11:43:42.000000000 +0000
+@@ -0,0 +1,8 @@
++#ifndef _IP6T_IMQ_H
++#define _IP6T_IMQ_H
++
++struct ip6t_imq_info {
++ unsigned int todev; /* target imq device */
++};
++
++#endif /* _IP6T_IMQ_H */
+diff -aurN linux-2.4.28-orig/include/linux/skbuff.h linux-2.4.28/include/linux/skbuff.h
+--- linux-2.4.28-orig/include/linux/skbuff.h 2004-08-07 23:26:06.000000000 +0000
++++ linux-2.4.28/include/linux/skbuff.h 2004-12-14 11:43:42.000000000 +0000
+@@ -93,6 +93,9 @@
+ struct nf_conntrack *master;
+ };
+ #endif
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++struct nf_info;
++#endif
+
+ struct sk_buff_head {
+ /* These two members must be first. */
+@@ -182,7 +185,7 @@
+ unsigned int len; /* Length of actual data */
+ unsigned int data_len;
+ unsigned int csum; /* Checksum */
+- unsigned char __unused, /* Dead field, may be reused */
++ unsigned char imq_flags, /* intermediate queueing device */
+ cloned, /* head may be cloned (check refcnt to be sure). */
+ pkt_type, /* Packet class */
+ ip_summed; /* Driver fed us an IP checksum */
+@@ -219,6 +222,9 @@
+ #ifdef CONFIG_NET_SCHED
+ __u32 tc_index; /* traffic control index */
+ #endif
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++ struct nf_info *nf_info;
++#endif
+ };
+
+ #ifdef __KERNEL__
+diff -aurN linux-2.4.28-orig/net/core/skbuff.c linux-2.4.28/net/core/skbuff.c
+--- linux-2.4.28-orig/net/core/skbuff.c 2003-08-25 11:44:44.000000000 +0000
++++ linux-2.4.28/net/core/skbuff.c 2004-12-14 11:43:42.000000000 +0000
+@@ -202,6 +202,10 @@
+ /* Set up other state */
+ skb->len = 0;
+ skb->cloned = 0;
++#if defined(CONFIG_IMQ) || defined (CONFIG_IMQ_MODULE)
++ skb->imq_flags = 0;
++ skb->nf_info = NULL;
++#endif
+ skb->data_len = 0;
+
+ atomic_set(&skb->users, 1);
+@@ -250,6 +254,10 @@
+ #ifdef CONFIG_NET_SCHED
+ skb->tc_index = 0;
+ #endif
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++ skb->imq_flags = 0;
++ skb->nf_info = NULL;
++#endif
+ }
+
+ static void skb_drop_fraglist(struct sk_buff *skb)
+@@ -400,6 +408,10 @@
+ #ifdef CONFIG_NET_SCHED
+ C(tc_index);
+ #endif
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++ C(imq_flags);
++ C(nf_info);
++#endif
+
+ atomic_inc(&(skb_shinfo(skb)->dataref));
+ skb->cloned = 1;
+@@ -444,6 +456,10 @@
+ #ifdef CONFIG_NET_SCHED
+ new->tc_index = old->tc_index;
+ #endif
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++ new->imq_flags=old->imq_flags;
++ new->nf_info=old->nf_info;
++#endif
+ }
+
+ /**
+diff -aurN linux-2.4.28-orig/net/ipv4/netfilter/Config.in linux-2.4.28/net/ipv4/netfilter/Config.in
+--- linux-2.4.28-orig/net/ipv4/netfilter/Config.in 2003-08-25 11:44:44.000000000 +0000
++++ linux-2.4.28/net/ipv4/netfilter/Config.in 2004-12-14 11:43:43.000000000 +0000
+@@ -104,6 +104,7 @@
+ dep_tristate ' DSCP target support' CONFIG_IP_NF_TARGET_DSCP $CONFIG_IP_NF_MANGLE
+
+ dep_tristate ' MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
++ dep_tristate ' IMQ target support' CONFIG_IP_NF_TARGET_IMQ $CONFIG_IP_NF_MANGLE
+ fi
+ dep_tristate ' LOG target support' CONFIG_IP_NF_TARGET_LOG $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' ULOG target support' CONFIG_IP_NF_TARGET_ULOG $CONFIG_IP_NF_IPTABLES
+diff -aurN linux-2.4.28-orig/net/ipv4/netfilter/Makefile linux-2.4.28/net/ipv4/netfilter/Makefile
+--- linux-2.4.28-orig/net/ipv4/netfilter/Makefile 2003-08-25 11:44:44.000000000 +0000
++++ linux-2.4.28/net/ipv4/netfilter/Makefile 2004-12-14 11:43:43.000000000 +0000
+@@ -94,6 +94,7 @@
+ obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
+ obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
+ obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
++obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
+ obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
+ obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
+ obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
+diff -aurN linux-2.4.28-orig/net/ipv4/netfilter/ipt_IMQ.c linux-2.4.28/net/ipv4/netfilter/ipt_IMQ.c
+--- linux-2.4.28-orig/net/ipv4/netfilter/ipt_IMQ.c 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.4.28/net/ipv4/netfilter/ipt_IMQ.c 2004-12-14 11:43:43.000000000 +0000
+@@ -0,0 +1,78 @@
++/* This target marks packets to be enqueued to an imq device */
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_IMQ.h>
++#include <linux/imq.h>
++
++static unsigned int imq_target(struct sk_buff **pskb,
++ unsigned int hooknum,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *targinfo,
++ void *userinfo)
++{
++ struct ipt_imq_info *mr = (struct ipt_imq_info*)targinfo;
++
++ (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
++ (*pskb)->nfcache |= NFC_ALTERED;
++
++ return IPT_CONTINUE;
++}
++
++static int imq_checkentry(const char *tablename,
++ const struct ipt_entry *e,
++ void *targinfo,
++ unsigned int targinfosize,
++ unsigned int hook_mask)
++{
++ struct ipt_imq_info *mr;
++
++ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_imq_info))) {
++ printk(KERN_WARNING "IMQ: invalid targinfosize\n");
++ return 0;
++ }
++ mr = (struct ipt_imq_info*)targinfo;
++
++ if (strcmp(tablename, "mangle") != 0) {
++ printk(KERN_WARNING
++ "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
++ tablename);
++ return 0;
++ }
++
++ if (mr->todev > IMQ_MAX_DEVS) {
++ printk(KERN_WARNING
++ "IMQ: invalid device specified, highest is %u\n",
++ IMQ_MAX_DEVS);
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct ipt_target ipt_imq_reg = {
++ { NULL, NULL},
++ "IMQ",
++ imq_target,
++ imq_checkentry,
++ NULL,
++ THIS_MODULE
++};
++
++static int __init init(void)
++{
++ if (ipt_register_target(&ipt_imq_reg))
++ return -EINVAL;
++
++ return 0;
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_target(&ipt_imq_reg);
++}
++
++module_init(init);
++module_exit(fini);
++MODULE_LICENSE("GPL");
+diff -aurN linux-2.4.28-orig/net/ipv6/netfilter/Config.in linux-2.4.28/net/ipv6/netfilter/Config.in
+--- linux-2.4.28-orig/net/ipv6/netfilter/Config.in 2003-06-13 14:51:39.000000000 +0000
++++ linux-2.4.28/net/ipv6/netfilter/Config.in 2004-12-14 11:43:43.000000000 +0000
+@@ -71,6 +71,7 @@
+ if [ "$CONFIG_IP6_NF_MANGLE" != "n" ]; then
+ # dep_tristate ' TOS target support' CONFIG_IP6_NF_TARGET_TOS $CONFIG_IP_NF_MANGLE
+ dep_tristate ' MARK target support' CONFIG_IP6_NF_TARGET_MARK $CONFIG_IP6_NF_MANGLE
++ dep_tristate ' IMQ target support' CONFIG_IP6_NF_TARGET_IMQ $CONFIG_IP6_NF_MANGLE
+ fi
+ #dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
+ fi
+diff -aurN linux-2.4.28-orig/net/ipv6/netfilter/Makefile linux-2.4.28/net/ipv6/netfilter/Makefile
+--- linux-2.4.28-orig/net/ipv6/netfilter/Makefile 2003-06-13 14:51:39.000000000 +0000
++++ linux-2.4.28/net/ipv6/netfilter/Makefile 2004-12-14 11:43:43.000000000 +0000
+@@ -28,6 +28,7 @@
+ obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
+ obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
+ obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
++obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o
+ obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
+ obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
+ obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
+diff -aurN linux-2.4.28-orig/net/ipv6/netfilter/ip6t_IMQ.c linux-2.4.28/net/ipv6/netfilter/ip6t_IMQ.c
+--- linux-2.4.28-orig/net/ipv6/netfilter/ip6t_IMQ.c 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.4.28/net/ipv6/netfilter/ip6t_IMQ.c 2004-12-14 11:43:43.000000000 +0000
+@@ -0,0 +1,78 @@
++/* This target marks packets to be enqueued to an imq device */
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv6/ip6_tables.h>
++#include <linux/netfilter_ipv6/ip6t_IMQ.h>
++#include <linux/imq.h>
++
++static unsigned int imq_target(struct sk_buff **pskb,
++ unsigned int hooknum,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *targinfo,
++ void *userinfo)
++{
++ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)targinfo;
++
++ (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
++ (*pskb)->nfcache |= NFC_ALTERED;
++
++ return IP6T_CONTINUE;
++}
++
++static int imq_checkentry(const char *tablename,
++ const struct ip6t_entry *e,
++ void *targinfo,
++ unsigned int targinfosize,
++ unsigned int hook_mask)
++{
++ struct ip6t_imq_info *mr;
++
++ if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_imq_info))) {
++ printk(KERN_WARNING "IMQ: invalid targinfosize\n");
++ return 0;
++ }
++ mr = (struct ip6t_imq_info*)targinfo;
++
++ if (strcmp(tablename, "mangle") != 0) {
++ printk(KERN_WARNING
++ "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
++ tablename);
++ return 0;
++ }
++
++ if (mr->todev > IMQ_MAX_DEVS) {
++ printk(KERN_WARNING
++ "IMQ: invalid device specified, highest is %u\n",
++ IMQ_MAX_DEVS);
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct ip6t_target ip6t_imq_reg = {
++ { NULL, NULL},
++ "IMQ",
++ imq_target,
++ imq_checkentry,
++ NULL,
++ THIS_MODULE
++};
++
++static int __init init(void)
++{
++ if (ip6t_register_target(&ip6t_imq_reg))
++ return -EINVAL;
++
++ return 0;
++}
++
++static void __exit fini(void)
++{
++ ip6t_unregister_target(&ip6t_imq_reg);
++}
++
++module_init(init);
++module_exit(fini);
++MODULE_LICENSE("GPL");
+diff -aurN linux-2.4.28-orig/net/sched/sch_generic.c linux-2.4.28/net/sched/sch_generic.c
+--- linux-2.4.28-orig/net/sched/sch_generic.c 2004-11-17 11:54:22.000000000 +0000
++++ linux-2.4.28/net/sched/sch_generic.c 2004-12-14 11:44:27.000000000 +0000
+@@ -29,6 +29,9 @@
+ #include <linux/skbuff.h>
+ #include <linux/rtnetlink.h>
+ #include <linux/init.h>
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++#include <linux/imq.h>
++#endif
+ #include <linux/list.h>
+ #include <net/sock.h>
+ #include <net/pkt_sched.h>
+@@ -90,7 +93,11 @@
+ spin_unlock(&dev->queue_lock);
+
+ if (!netif_queue_stopped(dev)) {
+- if (netdev_nit)
++ if (netdev_nit
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++ && !(skb->imq_flags & IMQ_F_ENQUEUE)
++#endif
++ )
+ dev_queue_xmit_nit(skb, dev);
+
+ if (dev->hard_start_xmit(skb, dev) == 0) {
diff --git a/target/linux/generic-2.4/patches/617-netfilter_time.patch b/target/linux/generic-2.4/patches/617-netfilter_time.patch
new file mode 100644
index 0000000000..3593571b46
--- /dev/null
+++ b/target/linux/generic-2.4/patches/617-netfilter_time.patch
@@ -0,0 +1,238 @@
+diff -urN linux-2.4.32.orig/net/ipv4/netfilter/Config.in linux-2.4.32/net/ipv4/netfilter/Config.in
+--- linux-2.4.32.orig/net/ipv4/netfilter/Config.in 2006-01-07 12:11:37.000000000 +0100
++++ linux-2.4.32/net/ipv4/netfilter/Config.in 2006-01-07 12:15:45.000000000 +0100
+@@ -48,6 +48,7 @@
+ dep_tristate ' netfilter MARK match support' CONFIG_IP_NF_MATCH_MARK $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' Multiple port match support' CONFIG_IP_NF_MATCH_MULTIPORT $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' TOS match support' CONFIG_IP_NF_MATCH_TOS $CONFIG_IP_NF_IPTABLES
++ dep_tristate ' TIME match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_TIME $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' condition match support' CONFIG_IP_NF_MATCH_CONDITION $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' recent match support' CONFIG_IP_NF_MATCH_RECENT $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' ECN match support' CONFIG_IP_NF_MATCH_ECN $CONFIG_IP_NF_IPTABLES
+diff -urN linux-2.4.32.orig/net/ipv4/netfilter/ipt_time.c linux-2.4.32/net/ipv4/netfilter/ipt_time.c
+--- linux-2.4.32.orig/net/ipv4/netfilter/ipt_time.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32/net/ipv4/netfilter/ipt_time.c 2006-01-07 12:14:32.000000000 +0100
+@@ -0,0 +1,193 @@
++/*
++ This is a module which is used for time matching
++ It is using some modified code from dietlibc (localtime() function)
++ that you can find at http://www.fefe.de/dietlibc/
++ This file is distributed under the terms of the GNU General Public
++ License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
++ 2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
++ 2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
++ thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
++ 2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
++ 2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
++ added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
++ 2004-05-02 Fabrice : added support for date matching, from an idea of Fabien COELHO.
++*/
++
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_time.h>
++#include <linux/time.h>
++
++MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
++MODULE_DESCRIPTION("Match arrival timestamp/date");
++MODULE_LICENSE("GPL");
++
++struct tm
++{
++ int tm_sec; /* Seconds. [0-60] (1 leap second) */
++ int tm_min; /* Minutes. [0-59] */
++ int tm_hour; /* Hours. [0-23] */
++ int tm_mday; /* Day. [1-31] */
++ int tm_mon; /* Month. [0-11] */
++ int tm_year; /* Year - 1900. */
++ int tm_wday; /* Day of week. [0-6] */
++ int tm_yday; /* Days in year.[0-365] */
++ int tm_isdst; /* DST. [-1/0/1]*/
++
++ long int tm_gmtoff; /* we don't care, we count from GMT */
++ const char *tm_zone; /* we don't care, we count from GMT */
++};
++
++void
++localtime(const time_t *timepr, struct tm *r);
++
++static int
++match(const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *matchinfo,
++ int offset,
++ const void *hdr,
++ u_int16_t datalen,
++ int *hotdrop)
++{
++ const struct ipt_time_info *info = matchinfo; /* match info for rule */
++ struct tm currenttime; /* time human readable */
++ u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
++ u_int16_t packet_time;
++ struct timeval kerneltimeval;
++ time_t packet_local_time;
++
++ /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
++ if (info->kerneltime)
++ {
++ do_gettimeofday(&kerneltimeval);
++ packet_local_time = kerneltimeval.tv_sec;
++ }
++ else
++ packet_local_time = skb->stamp.tv_sec;
++
++ /* First we make sure we are in the date start-stop boundaries */
++ if ((packet_local_time < info->date_start) || (packet_local_time > info->date_stop))
++ return 0; /* We are outside the date boundaries */
++
++ /* Transform the timestamp of the packet, in a human readable form */
++ localtime(&packet_local_time, &currenttime);
++
++ /* check if we match this timestamp, we start by the days... */
++ if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
++ return 0; /* the day doesn't match */
++
++ /* ... check the time now */
++ packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
++ if ((packet_time < info->time_start) || (packet_time > info->time_stop))
++ return 0;
++
++ /* here we match ! */
++ return 1;
++}
++
++static int
++checkentry(const char *tablename,
++ const struct ipt_ip *ip,
++ void *matchinfo,
++ unsigned int matchsize,
++ unsigned int hook_mask)
++{
++ struct ipt_time_info *info = matchinfo; /* match info for rule */
++
++ /* First, check that we are in the correct hooks */
++ if (hook_mask
++ & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
++ {
++ printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
++ return 0;
++ }
++ /* we use the kerneltime if we are in forward or output */
++ info->kerneltime = 1;
++ if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
++ /* we use the skb time */
++ info->kerneltime = 0;
++
++ /* Check the size */
++ if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
++ return 0;
++ /* Now check the coherence of the data ... */
++ if ((info->time_start > 1439) || /* 23*60+59 = 1439*/
++ (info->time_stop > 1439))
++ {
++ printk(KERN_WARNING "ipt_time: invalid argument\n");
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct ipt_match time_match = {
++ .name = "time",
++ .match = match,
++ .checkentry = checkentry,
++ .me = THIS_MODULE,
++};
++
++static int __init init(void)
++{
++ printk("ipt_time loading\n");
++ return ipt_register_match(&time_match);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_match(&time_match);
++ printk("ipt_time unloaded\n");
++}
++
++module_init(init);
++module_exit(fini);
++
++
++/* The part below is borowed and modified from dietlibc */
++
++/* seconds per day */
++#define SPD 24*60*60
++
++void
++localtime(const time_t *timepr, struct tm *r) {
++ time_t i;
++ time_t timep;
++ extern struct timezone sys_tz;
++ const unsigned int __spm[12] =
++ { 0,
++ (31),
++ (31+28),
++ (31+28+31),
++ (31+28+31+30),
++ (31+28+31+30+31),
++ (31+28+31+30+31+30),
++ (31+28+31+30+31+30+31),
++ (31+28+31+30+31+30+31+31),
++ (31+28+31+30+31+30+31+31+30),
++ (31+28+31+30+31+30+31+31+30+31),
++ (31+28+31+30+31+30+31+31+30+31+30),
++ };
++ register time_t work;
++
++ timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
++ work=timep%(SPD);
++ r->tm_sec=work%60; work/=60;
++ r->tm_min=work%60; r->tm_hour=work/60;
++ work=timep/(SPD);
++ r->tm_wday=(4+work)%7;
++ for (i=1970; ; ++i) {
++ register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
++ if (work>k)
++ work-=k;
++ else
++ break;
++ }
++ r->tm_year=i-1900;
++ for (i=11; i && __spm[i]>work; --i) ;
++ r->tm_mon=i;
++ r->tm_mday=work-__spm[i]+1;
++}
+diff -urN linux-2.4.32.orig/net/ipv4/netfilter/Makefile linux-2.4.32/net/ipv4/netfilter/Makefile
+--- linux-2.4.32.orig/net/ipv4/netfilter/Makefile 2006-01-07 12:11:37.000000000 +0100
++++ linux-2.4.32/net/ipv4/netfilter/Makefile 2006-01-07 12:16:07.000000000 +0100
+@@ -118,6 +118,7 @@
+ obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
+ obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
+ obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
++obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
+ obj-$(CONFIG_IP_NF_MATCH_CONDITION) += ipt_condition.o
+
+ obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
+diff -urN linux-2.4.32.orig/include/linux/netfilter_ipv4/ipt_time.h linux-2.4.32/include/linux/netfilter_ipv4/ipt_time.h
+--- linux-2.4.32.orig/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32/include/linux/netfilter_ipv4/ipt_time.h 2006-01-07 12:16:42.000000000 +0100
+@@ -0,0 +1,15 @@
++#ifndef __ipt_time_h_included__
++#define __ipt_time_h_included__
++
++
++struct ipt_time_info {
++ u_int8_t days_match; /* 1 bit per day. -SMTWTFS */
++ u_int16_t time_start; /* 0 < time_start < 23*60+59 = 1439 */
++ u_int16_t time_stop; /* 0:0 < time_stat < 23:59 */
++ u_int8_t kerneltime; /* ignore skb time (and use kerneltime) or not. */
++ time_t date_start;
++ time_t date_stop;
++};
++
++
++#endif /* __ipt_time_h_included__ */
diff --git a/target/linux/generic-2.4/patches/618-netfilter_multiport_backport.patch b/target/linux/generic-2.4/patches/618-netfilter_multiport_backport.patch
new file mode 100644
index 0000000000..c34f9ecbb7
--- /dev/null
+++ b/target/linux/generic-2.4/patches/618-netfilter_multiport_backport.patch
@@ -0,0 +1,231 @@
+diff -urN linux.old/include/linux/netfilter_ipv4/ipt_multiport.h linux.dev/include/linux/netfilter_ipv4/ipt_multiport.h
+--- linux.old/include/linux/netfilter_ipv4/ipt_multiport.h 2000-12-11 22:31:30.000000000 +0100
++++ linux.dev/include/linux/netfilter_ipv4/ipt_multiport.h 2006-02-04 05:23:54.318518250 +0100
+@@ -11,11 +11,12 @@
+
+ #define IPT_MULTI_PORTS 15
+
+-/* Must fit inside union ipt_matchinfo: 16 bytes */
+-struct ipt_multiport
++struct ipt_multiport_v1
+ {
+ u_int8_t flags; /* Type of comparison */
+ u_int8_t count; /* Number of ports */
+ u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
++ u_int8_t pflags[IPT_MULTI_PORTS]; /* Port flags */
++ u_int8_t invert; /* Invert flag */
+ };
+ #endif /*_IPT_MULTIPORT_H*/
+diff -urN linux.old/net/ipv4/netfilter/ipt_multiport.c linux.dev/net/ipv4/netfilter/ipt_multiport.c
+--- linux.old/net/ipv4/netfilter/ipt_multiport.c 2003-06-13 16:51:39.000000000 +0200
++++ linux.dev/net/ipv4/netfilter/ipt_multiport.c 2006-02-04 05:34:27.362081000 +0100
+@@ -1,5 +1,14 @@
+ /* Kernel module to match one of a list of TCP/UDP ports: ports are in
+ the same place so we can treat them as equal. */
++
++/* (C) 1999-2001 Paul `Rusty' Russell
++ * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.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/types.h>
+ #include <linux/udp.h>
+@@ -8,97 +17,136 @@
+ #include <linux/netfilter_ipv4/ipt_multiport.h>
+ #include <linux/netfilter_ipv4/ip_tables.h>
+
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
++MODULE_DESCRIPTION("iptables multiple port match module");
++
+ #if 0
+ #define duprintf(format, args...) printk(format , ## args)
+ #else
+ #define duprintf(format, args...)
+ #endif
+
++/* from linux 2.6 skbuff.h */
++static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
++ int len, void *buffer)
++{
++ int hlen = skb_headlen(skb);
++
++ if (hlen - offset >= len)
++ return skb->data + offset;
++
++ if (skb_copy_bits(skb, offset, buffer, len) < 0)
++ return NULL;
++
++ return buffer;
++}
++
++
+ /* Returns 1 if the port is matched by the test, 0 otherwise. */
+ static inline int
+-ports_match(const u_int16_t *portlist, enum ipt_multiport_flags flags,
+- u_int8_t count, u_int16_t src, u_int16_t dst)
++ports_match_v1(const struct ipt_multiport_v1 *minfo,
++ u_int16_t src, u_int16_t dst)
+ {
+ unsigned int i;
+- for (i=0; i<count; i++) {
+- if (flags != IPT_MULTIPORT_DESTINATION
+- && portlist[i] == src)
+- return 1;
+-
+- if (flags != IPT_MULTIPORT_SOURCE
+- && portlist[i] == dst)
+- return 1;
+- }
++ u_int16_t s, e;
+
+- return 0;
++ for (i=0; i < minfo->count; i++) {
++ s = minfo->ports[i];
++
++ if (minfo->pflags[i]) {
++ /* range port matching */
++ e = minfo->ports[++i];
++ duprintf("src or dst matches with %d-%d?\n", s, e);
++
++ if (minfo->flags == IPT_MULTIPORT_SOURCE
++ && src >= s && src <= e)
++ return 1 ^ minfo->invert;
++ if (minfo->flags == IPT_MULTIPORT_DESTINATION
++ && dst >= s && dst <= e)
++ return 1 ^ minfo->invert;
++ if (minfo->flags == IPT_MULTIPORT_EITHER
++ && ((dst >= s && dst <= e)
++ || (src >= s && src <= e)))
++ return 1 ^ minfo->invert;
++ } else {
++ /* exact port matching */
++ duprintf("src or dst matches with %d?\n", s);
++
++ if (minfo->flags == IPT_MULTIPORT_SOURCE
++ && src == s)
++ return 1 ^ minfo->invert;
++ if (minfo->flags == IPT_MULTIPORT_DESTINATION
++ && dst == s)
++ return 1 ^ minfo->invert;
++ if (minfo->flags == IPT_MULTIPORT_EITHER
++ && (src == s || dst == s))
++ return 1 ^ minfo->invert;
++ }
++ }
++
++ return minfo->invert;
+ }
+
+ static int
+-match(const struct sk_buff *skb,
+- const struct net_device *in,
+- const struct net_device *out,
+- const void *matchinfo,
+- int offset,
+- const void *hdr,
+- u_int16_t datalen,
+- int *hotdrop)
++match_v1(const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *matchinfo,
++ int offset,
++ int *hotdrop)
+ {
+- const struct udphdr *udp = hdr;
+- const struct ipt_multiport *multiinfo = matchinfo;
++ u16 _ports[2], *pptr;
++ const struct ipt_multiport_v1 *multiinfo = matchinfo;
++
++ if (offset)
++ return 0;
+
+- /* Must be big enough to read ports. */
+- if (offset == 0 && datalen < sizeof(struct udphdr)) {
++ pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
++ sizeof(_ports), _ports);
++ if (pptr == NULL) {
+ /* We've been asked to examine this packet, and we
+- can't. Hence, no choice but to drop. */
+- duprintf("ipt_multiport:"
+- " Dropping evil offset=0 tinygram.\n");
+- *hotdrop = 1;
+- return 0;
++ * can't. Hence, no choice but to drop.
++ */
++ duprintf("ipt_multiport:"
++ " Dropping evil offset=0 tinygram.\n");
++ *hotdrop = 1;
++ return 0;
+ }
+
+- /* Must not be a fragment. */
+- return !offset
+- && ports_match(multiinfo->ports,
+- multiinfo->flags, multiinfo->count,
+- ntohs(udp->source), ntohs(udp->dest));
++ return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
+ }
+
+-/* Called when user tries to insert an entry of this type. */
+ static int
+-checkentry(const char *tablename,
+- const struct ipt_ip *ip,
+- void *matchinfo,
+- unsigned int matchsize,
+- unsigned int hook_mask)
++checkentry_v1(const char *tablename,
++ const struct ipt_ip *ip,
++ void *matchinfo,
++ unsigned int matchsize,
++ unsigned int hook_mask)
+ {
+- const struct ipt_multiport *multiinfo = matchinfo;
+-
+- if (matchsize != IPT_ALIGN(sizeof(struct ipt_multiport)))
+- return 0;
+-
+- /* Must specify proto == TCP/UDP, no unknown flags or bad count */
+- return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
+- && !(ip->invflags & IPT_INV_PROTO)
+- && matchsize == IPT_ALIGN(sizeof(struct ipt_multiport))
+- && (multiinfo->flags == IPT_MULTIPORT_SOURCE
+- || multiinfo->flags == IPT_MULTIPORT_DESTINATION
+- || multiinfo->flags == IPT_MULTIPORT_EITHER)
+- && multiinfo->count <= IPT_MULTI_PORTS;
++ return (matchsize == IPT_ALIGN(sizeof(struct ipt_multiport_v1)));
+ }
+
+-static struct ipt_match multiport_match
+-= { { NULL, NULL }, "multiport", &match, &checkentry, NULL, THIS_MODULE };
++static struct ipt_match multiport_match_v1 = {
++ .name = "multiport",
++ .match = &match_v1,
++ .checkentry = &checkentry_v1,
++ .me = THIS_MODULE,
++};
+
+ static int __init init(void)
+ {
+- return ipt_register_match(&multiport_match);
++ int err;
++
++ err = ipt_register_match(&multiport_match_v1);
++
++ return err;
+ }
+
+ static void __exit fini(void)
+ {
+- ipt_unregister_match(&multiport_match);
++ ipt_unregister_match(&multiport_match_v1);
+ }
+
+ module_init(init);
+ module_exit(fini);
+-MODULE_LICENSE("GPL");
diff --git a/target/linux/generic-2.4/patches/700-multiple_default_gateways.patch b/target/linux/generic-2.4/patches/700-multiple_default_gateways.patch
new file mode 100644
index 0000000000..46407c85f2
--- /dev/null
+++ b/target/linux/generic-2.4/patches/700-multiple_default_gateways.patch
@@ -0,0 +1,1299 @@
+diff -ur v2.4.29/linux/include/linux/netfilter_ipv4/ip_nat.h linux/include/linux/netfilter_ipv4/ip_nat.h
+--- v2.4.29/linux/include/linux/netfilter_ipv4/ip_nat.h 2005-01-20 09:25:34.000000000 +0200
++++ linux/include/linux/netfilter_ipv4/ip_nat.h 2005-01-20 09:55:46.998651976 +0200
+@@ -121,5 +121,13 @@
+ extern u_int16_t ip_nat_cheat_check(u_int32_t oldvalinv,
+ u_int32_t newval,
+ u_int16_t oldcheck);
++
++/* Call input routing for SNAT-ed traffic */
++extern unsigned int ip_nat_route_input(unsigned int hooknum,
++ struct sk_buff **pskb,
++ const struct net_device *in,
++ const struct net_device *out,
++ int (*okfn)(struct sk_buff *));
++
+ #endif /*__KERNEL__*/
+ #endif
+diff -ur v2.4.29/linux/include/linux/rtnetlink.h linux/include/linux/rtnetlink.h
+--- v2.4.29/linux/include/linux/rtnetlink.h 2004-08-08 10:56:48.000000000 +0300
++++ linux/include/linux/rtnetlink.h 2005-01-20 09:55:33.431714464 +0200
+@@ -234,6 +234,8 @@
+ #define RTNH_F_DEAD 1 /* Nexthop is dead (used by multipath) */
+ #define RTNH_F_PERVASIVE 2 /* Do recursive gateway lookup */
+ #define RTNH_F_ONLINK 4 /* Gateway is forced on link */
++#define RTNH_F_SUSPECT 8 /* We don't know the real state */
++#define RTNH_F_BADSTATE (RTNH_F_DEAD | RTNH_F_SUSPECT)
+
+ /* Macros to handle hexthops */
+
+diff -ur v2.4.29/linux/include/net/ip_fib.h linux/include/net/ip_fib.h
+--- v2.4.29/linux/include/net/ip_fib.h 2001-11-13 03:24:05.000000000 +0200
++++ linux/include/net/ip_fib.h 2005-01-20 09:55:33.432714312 +0200
+@@ -162,7 +162,8 @@
+
+ static inline void fib_select_default(const struct rt_key *key, struct fib_result *res)
+ {
+- if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
++ if ((FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) ||
++ FIB_RES_NH(*res).nh_scope == RT_SCOPE_HOST)
+ main_table->tb_select_default(main_table, key, res);
+ }
+
+@@ -174,6 +175,7 @@
+ extern int fib_lookup(const struct rt_key *key, struct fib_result *res);
+ extern struct fib_table *__fib_new_table(int id);
+ extern void fib_rule_put(struct fib_rule *r);
++extern int fib_result_table(struct fib_result *res);
+
+ static inline struct fib_table *fib_get_table(int id)
+ {
+@@ -275,5 +277,6 @@
+ #endif
+ }
+
++extern rwlock_t fib_nhflags_lock;
+
+ #endif /* _NET_FIB_H */
+diff -ur v2.4.29/linux/include/net/route.h linux/include/net/route.h
+--- v2.4.29/linux/include/net/route.h 2003-08-25 22:06:13.000000000 +0300
++++ linux/include/net/route.h 2005-01-20 09:55:46.999651824 +0200
+@@ -49,6 +49,8 @@
+ {
+ __u32 dst;
+ __u32 src;
++ __u32 lsrc;
++ __u32 gw;
+ int iif;
+ int oif;
+ #ifdef CONFIG_IP_ROUTE_FWMARK
+@@ -128,6 +130,7 @@
+ extern void rt_cache_flush(int how);
+ extern int ip_route_output_key(struct rtable **, const struct rt_key *key);
+ extern int ip_route_input(struct sk_buff*, u32 dst, u32 src, u8 tos, struct net_device *devin);
++extern int ip_route_input_lookup(struct sk_buff*, u32 dst, u32 src, u8 tos, struct net_device *devin, u32 lsrc);
+ extern unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu);
+ extern void ip_rt_update_pmtu(struct dst_entry *dst, unsigned mtu);
+ extern void ip_rt_send_redirect(struct sk_buff *skb);
+@@ -148,6 +151,15 @@
+ }
+
+
++static inline int
++ip_route_output_lookup(struct rtable **rp,
++ u32 daddr, u32 saddr, u32 tos, int oif, u32 gw)
++{
++ struct rt_key key = { dst:daddr, src:saddr, gw:gw, oif:oif, tos:tos };
++
++ return ip_route_output_key(rp, &key);
++}
++
+ static inline void ip_rt_put(struct rtable * rt)
+ {
+ if (rt)
+diff -ur v2.4.29/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
+--- v2.4.29/linux/net/ipv4/fib_frontend.c 2003-08-25 22:06:13.000000000 +0300
++++ linux/net/ipv4/fib_frontend.c 2005-01-20 09:55:46.999651824 +0200
+@@ -54,6 +54,8 @@
+ struct fib_table *local_table;
+ struct fib_table *main_table;
+
++#define FIB_RES_TABLE(r) (RT_TABLE_MAIN)
++
+ #else
+
+ #define RT_TABLE_MIN 1
+@@ -71,6 +73,7 @@
+ return tb;
+ }
+
++#define FIB_RES_TABLE(r) (fib_result_table(r))
+
+ #endif /* CONFIG_IP_MULTIPLE_TABLES */
+
+@@ -209,6 +212,9 @@
+ struct in_device *in_dev;
+ struct rt_key key;
+ struct fib_result res;
++ int table;
++ unsigned char prefixlen;
++ unsigned char scope;
+ int no_addr, rpf;
+ int ret;
+
+@@ -216,6 +222,7 @@
+ key.src = dst;
+ key.tos = tos;
+ key.oif = 0;
++ key.gw = 0;
+ key.iif = oif;
+ key.scope = RT_SCOPE_UNIVERSE;
+
+@@ -237,31 +244,35 @@
+ goto e_inval_res;
+ *spec_dst = FIB_RES_PREFSRC(res);
+ fib_combine_itag(itag, &res);
+-#ifdef CONFIG_IP_ROUTE_MULTIPATH
+- if (FIB_RES_DEV(res) == dev || res.fi->fib_nhs > 1)
+-#else
+ if (FIB_RES_DEV(res) == dev)
+-#endif
+ {
+ ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
+ fib_res_put(&res);
+ return ret;
+ }
++ table = FIB_RES_TABLE(&res);
++ prefixlen = res.prefixlen;
++ scope = res.scope;
+ fib_res_put(&res);
+ if (no_addr)
+ goto last_resort;
+- if (rpf)
+- goto e_inval;
+ key.oif = dev->ifindex;
+
+ ret = 0;
+ if (fib_lookup(&key, &res) == 0) {
+- if (res.type == RTN_UNICAST) {
++ if (res.type == RTN_UNICAST &&
++ ((table == FIB_RES_TABLE(&res) &&
++ res.prefixlen >= prefixlen && res.scope >= scope) ||
++ !rpf)) {
+ *spec_dst = FIB_RES_PREFSRC(res);
+ ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
++ fib_res_put(&res);
++ return ret;
+ }
+ fib_res_put(&res);
+ }
++ if (rpf)
++ goto e_inval;
+ return ret;
+
+ last_resort:
+@@ -579,9 +590,7 @@
+ switch (event) {
+ case NETDEV_UP:
+ fib_add_ifaddr(ifa);
+-#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ fib_sync_up(ifa->ifa_dev->dev);
+-#endif
+ rt_cache_flush(-1);
+ break;
+ case NETDEV_DOWN:
+@@ -617,9 +626,7 @@
+ for_ifa(in_dev) {
+ fib_add_ifaddr(ifa);
+ } endfor_ifa(in_dev);
+-#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ fib_sync_up(dev);
+-#endif
+ rt_cache_flush(-1);
+ break;
+ case NETDEV_DOWN:
+diff -ur v2.4.29/linux/net/ipv4/fib_hash.c linux/net/ipv4/fib_hash.c
+--- v2.4.29/linux/net/ipv4/fib_hash.c 2003-08-25 22:06:13.000000000 +0300
++++ linux/net/ipv4/fib_hash.c 2005-01-20 09:55:47.000651672 +0200
+@@ -71,6 +71,7 @@
+ struct fib_info *fn_info;
+ #define FIB_INFO(f) ((f)->fn_info)
+ fn_key_t fn_key;
++ int fn_last_dflt;
+ u8 fn_tos;
+ u8 fn_type;
+ u8 fn_scope;
+@@ -336,72 +337,123 @@
+ return err;
+ }
+
+-static int fn_hash_last_dflt=-1;
+-
+-static int fib_detect_death(struct fib_info *fi, int order,
+- struct fib_info **last_resort, int *last_idx)
++static int fib_detect_death(struct fib_info *fi, int order, int last_dflt,
++ struct fib_info **last_resort, int *last_idx,
++ int *last_nhsel, const struct rt_key *key)
+ {
+ struct neighbour *n;
+- int state = NUD_NONE;
++ int nhsel;
++ int state;
++ struct fib_nh * nh;
++ u32 dst;
++ int flag, dead = 1;
++
++ /* change_nexthops(fi) { */
++ for (nhsel = 0, nh = fi->fib_nh; nhsel < fi->fib_nhs; nh++, nhsel++) {
++ if (key->oif && key->oif != nh->nh_oif)
++ continue;
++ if (key->gw && key->gw != nh->nh_gw && nh->nh_gw &&
++ nh->nh_scope == RT_SCOPE_LINK)
++ continue;
++ if (nh->nh_flags & RTNH_F_DEAD)
++ continue;
+
+- n = neigh_lookup(&arp_tbl, &fi->fib_nh[0].nh_gw, fi->fib_dev);
+- if (n) {
+- state = n->nud_state;
+- neigh_release(n);
++ flag = 0;
++ if (nh->nh_dev->flags & IFF_NOARP) {
++ dead = 0;
++ goto setfl;
++ }
++
++ dst = nh->nh_gw;
++ if (!nh->nh_gw || nh->nh_scope != RT_SCOPE_LINK)
++ dst = key->dst;
++
++ state = NUD_NONE;
++ n = neigh_lookup(&arp_tbl, &dst, nh->nh_dev);
++ if (n) {
++ state = n->nud_state;
++ neigh_release(n);
++ }
++ if (state==NUD_REACHABLE ||
++ ((state&NUD_VALID) && order != last_dflt)) {
++ dead = 0;
++ goto setfl;
++ }
++ if (!(state&NUD_VALID))
++ flag = 1;
++ if (!dead)
++ goto setfl;
++ if ((state&NUD_VALID) ||
++ (*last_idx<0 && order >= last_dflt)) {
++ *last_resort = fi;
++ *last_idx = order;
++ *last_nhsel = nhsel;
++ }
++
++ setfl:
++
++ read_lock_bh(&fib_nhflags_lock);
++ if (flag)
++ nh->nh_flags |= RTNH_F_SUSPECT;
++ else
++ nh->nh_flags &= ~RTNH_F_SUSPECT;
++ read_unlock_bh(&fib_nhflags_lock);
+ }
+- if (state==NUD_REACHABLE)
+- return 0;
+- if ((state&NUD_VALID) && order != fn_hash_last_dflt)
+- return 0;
+- if ((state&NUD_VALID) ||
+- (*last_idx<0 && order > fn_hash_last_dflt)) {
+- *last_resort = fi;
+- *last_idx = order;
+- }
+- return 1;
++ /* } endfor_nexthops(fi) */
++
++ return dead;
+ }
+
+ static void
+ fn_hash_select_default(struct fib_table *tb, const struct rt_key *key, struct fib_result *res)
+ {
+- int order, last_idx;
+- struct fib_node *f;
++ int order, last_idx, last_dflt, last_nhsel;
++ struct fib_node *f, *first_node;
+ struct fib_info *fi = NULL;
+ struct fib_info *last_resort;
+ struct fn_hash *t = (struct fn_hash*)tb->tb_data;
+- struct fn_zone *fz = t->fn_zones[0];
++ struct fn_zone *fz = t->fn_zones[res->prefixlen];
++ fn_key_t k;
+
+ if (fz == NULL)
+ return;
+
++ k = fz_key(key->dst, fz);
++ last_dflt = -2;
++ first_node = NULL;
+ last_idx = -1;
+ last_resort = NULL;
++ last_nhsel = 0;
+ order = -1;
+
+ read_lock(&fib_hash_lock);
+- for (f = fz->fz_hash[0]; f; f = f->fn_next) {
++ for (f = fz_chain(k, fz); f; f = f->fn_next) {
+ struct fib_info *next_fi = FIB_INFO(f);
+
+- if ((f->fn_state&FN_S_ZOMBIE) ||
++ if (!fn_key_eq(k, f->fn_key) ||
++ (f->fn_state&FN_S_ZOMBIE) ||
+ f->fn_scope != res->scope ||
++#ifdef CONFIG_IP_ROUTE_TOS
++ (f->fn_tos && f->fn_tos != key->tos) ||
++#endif
+ f->fn_type != RTN_UNICAST)
+ continue;
+
+ if (next_fi->fib_priority > res->fi->fib_priority)
+ break;
+- if (!next_fi->fib_nh[0].nh_gw || next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
+- continue;
+ f->fn_state |= FN_S_ACCESSED;
+
+- if (fi == NULL) {
+- if (next_fi != res->fi)
+- break;
+- } else if (!fib_detect_death(fi, order, &last_resort, &last_idx)) {
++ if (!first_node) {
++ last_dflt = f->fn_last_dflt;
++ first_node = f;
++ }
++ if (fi && !fib_detect_death(fi, order, last_dflt,
++ &last_resort, &last_idx, &last_nhsel, key)) {
+ if (res->fi)
+ fib_info_put(res->fi);
+ res->fi = fi;
+ atomic_inc(&fi->fib_clntref);
+- fn_hash_last_dflt = order;
++ first_node->fn_last_dflt = order;
+ goto out;
+ }
+ fi = next_fi;
+@@ -409,16 +461,25 @@
+ }
+
+ if (order<=0 || fi==NULL) {
+- fn_hash_last_dflt = -1;
++ if (fi && fi->fib_nhs > 1 &&
++ fib_detect_death(fi, order, last_dflt,
++ &last_resort, &last_idx, &last_nhsel, key) &&
++ last_resort == fi) {
++ read_lock_bh(&fib_nhflags_lock);
++ fi->fib_nh[last_nhsel].nh_flags &= ~RTNH_F_SUSPECT;
++ read_unlock_bh(&fib_nhflags_lock);
++ }
++ if (first_node) first_node->fn_last_dflt = -1;
+ goto out;
+ }
+
+- if (!fib_detect_death(fi, order, &last_resort, &last_idx)) {
++ if (!fib_detect_death(fi, order, last_dflt, &last_resort, &last_idx,
++ &last_nhsel, key)) {
+ if (res->fi)
+ fib_info_put(res->fi);
+ res->fi = fi;
+ atomic_inc(&fi->fib_clntref);
+- fn_hash_last_dflt = order;
++ first_node->fn_last_dflt = order;
+ goto out;
+ }
+
+@@ -428,8 +489,11 @@
+ res->fi = last_resort;
+ if (last_resort)
+ atomic_inc(&last_resort->fib_clntref);
++ read_lock_bh(&fib_nhflags_lock);
++ last_resort->fib_nh[last_nhsel].nh_flags &= ~RTNH_F_SUSPECT;
++ read_unlock_bh(&fib_nhflags_lock);
++ first_node->fn_last_dflt = last_idx;
+ }
+- fn_hash_last_dflt = last_idx;
+ out:
+ read_unlock(&fib_hash_lock);
+ }
+@@ -589,6 +653,7 @@
+
+ memset(new_f, 0, sizeof(struct fib_node));
+
++ new_f->fn_last_dflt = -1;
+ new_f->fn_key = key;
+ #ifdef CONFIG_IP_ROUTE_TOS
+ new_f->fn_tos = tos;
+diff -ur v2.4.29/linux/net/ipv4/fib_rules.c linux/net/ipv4/fib_rules.c
+--- v2.4.29/linux/net/ipv4/fib_rules.c 2004-02-19 00:23:39.000000000 +0200
++++ linux/net/ipv4/fib_rules.c 2005-01-20 09:55:33.433714160 +0200
+@@ -307,6 +307,11 @@
+ }
+ }
+
++int fib_result_table(struct fib_result *res)
++{
++ return res->r->r_table;
++}
++
+ int fib_lookup(const struct rt_key *key, struct fib_result *res)
+ {
+ int err;
+@@ -371,8 +376,10 @@
+
+ void fib_select_default(const struct rt_key *key, struct fib_result *res)
+ {
+- if (res->r && res->r->r_action == RTN_UNICAST &&
+- FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) {
++ if (res->r &&
++ (res->r->r_action == RTN_UNICAST || res->r->r_action == RTN_NAT) &&
++ ((FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) ||
++ FIB_RES_NH(*res).nh_scope == RT_SCOPE_HOST)) {
+ struct fib_table *tb;
+ if ((tb = fib_get_table(res->r->r_table)) != NULL)
+ tb->tb_select_default(tb, key, res);
+diff -ur v2.4.29/linux/net/ipv4/fib_semantics.c linux/net/ipv4/fib_semantics.c
+--- v2.4.29/linux/net/ipv4/fib_semantics.c 2003-08-25 22:06:13.000000000 +0300
++++ linux/net/ipv4/fib_semantics.c 2005-01-20 09:55:47.000651672 +0200
+@@ -48,6 +48,7 @@
+ static struct fib_info *fib_info_list;
+ static rwlock_t fib_info_lock = RW_LOCK_UNLOCKED;
+ int fib_info_cnt;
++rwlock_t fib_nhflags_lock = RW_LOCK_UNLOCKED;
+
+ #define for_fib_info() { struct fib_info *fi; \
+ for (fi = fib_info_list; fi; fi = fi->fib_next)
+@@ -150,7 +151,7 @@
+ #ifdef CONFIG_NET_CLS_ROUTE
+ nh->nh_tclassid != onh->nh_tclassid ||
+ #endif
+- ((nh->nh_flags^onh->nh_flags)&~RTNH_F_DEAD))
++ ((nh->nh_flags^onh->nh_flags)&~RTNH_F_BADSTATE))
+ return -1;
+ onh++;
+ } endfor_nexthops(fi);
+@@ -166,7 +167,7 @@
+ nfi->fib_prefsrc == fi->fib_prefsrc &&
+ nfi->fib_priority == fi->fib_priority &&
+ memcmp(nfi->fib_metrics, fi->fib_metrics, sizeof(fi->fib_metrics)) == 0 &&
+- ((nfi->fib_flags^fi->fib_flags)&~RTNH_F_DEAD) == 0 &&
++ ((nfi->fib_flags^fi->fib_flags)&~RTNH_F_BADSTATE) == 0 &&
+ (nfi->fib_nhs == 0 || nh_comp(fi, nfi) == 0))
+ return fi;
+ } endfor_fib_info();
+@@ -365,8 +366,11 @@
+ return -EINVAL;
+ if ((dev = __dev_get_by_index(nh->nh_oif)) == NULL)
+ return -ENODEV;
+- if (!(dev->flags&IFF_UP))
+- return -ENETDOWN;
++ if (!(dev->flags&IFF_UP)) {
++ if (fi->fib_protocol != RTPROT_STATIC)
++ return -ENETDOWN;
++ nh->nh_flags |= RTNH_F_DEAD;
++ }
+ nh->nh_dev = dev;
+ dev_hold(dev);
+ nh->nh_scope = RT_SCOPE_LINK;
+@@ -380,23 +384,48 @@
+ /* It is not necessary, but requires a bit of thinking */
+ if (key.scope < RT_SCOPE_LINK)
+ key.scope = RT_SCOPE_LINK;
+- if ((err = fib_lookup(&key, &res)) != 0)
+- return err;
+- err = -EINVAL;
+- if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
+- goto out;
+- nh->nh_scope = res.scope;
+- nh->nh_oif = FIB_RES_OIF(res);
+- if ((nh->nh_dev = FIB_RES_DEV(res)) == NULL)
+- goto out;
+- dev_hold(nh->nh_dev);
+- err = -ENETDOWN;
+- if (!(nh->nh_dev->flags & IFF_UP))
+- goto out;
+- err = 0;
++
++ err = fib_lookup(&key, &res);
++ if (err) {
++ struct in_device *in_dev;
++
++ if (err != -ENETUNREACH ||
++ fi->fib_protocol != RTPROT_STATIC)
++ return err;
++
++ in_dev = inetdev_by_index(nh->nh_oif);
++ if (in_dev == NULL ||
++ in_dev->dev->flags & IFF_UP) {
++ if (in_dev)
++ in_dev_put(in_dev);
++ return err;
++ }
++ nh->nh_flags |= RTNH_F_DEAD;
++ nh->nh_scope = RT_SCOPE_LINK;
++ nh->nh_dev = in_dev->dev;
++ dev_hold(nh->nh_dev);
++ in_dev_put(in_dev);
++ } else {
++ err = -EINVAL;
++ if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
++ goto out;
++ nh->nh_scope = res.scope;
++ nh->nh_oif = FIB_RES_OIF(res);
++ if ((nh->nh_dev = FIB_RES_DEV(res)) == NULL)
++ goto out;
++ dev_hold(nh->nh_dev);
++ if (!(nh->nh_dev->flags & IFF_UP)) {
++ if (fi->fib_protocol != RTPROT_STATIC) {
++ err = -ENETDOWN;
++ goto out;
++ }
++ nh->nh_flags |= RTNH_F_DEAD;
++ }
++ err = 0;
+ out:
+- fib_res_put(&res);
+- return err;
++ fib_res_put(&res);
++ return err;
++ }
+ } else {
+ struct in_device *in_dev;
+
+@@ -407,8 +436,11 @@
+ if (in_dev == NULL)
+ return -ENODEV;
+ if (!(in_dev->dev->flags&IFF_UP)) {
+- in_dev_put(in_dev);
+- return -ENETDOWN;
++ if (fi->fib_protocol != RTPROT_STATIC) {
++ in_dev_put(in_dev);
++ return -ENETDOWN;
++ }
++ nh->nh_flags |= RTNH_F_DEAD;
+ }
+ nh->nh_dev = in_dev->dev;
+ dev_hold(nh->nh_dev);
+@@ -603,8 +635,12 @@
+ for_nexthops(fi) {
+ if (nh->nh_flags&RTNH_F_DEAD)
+ continue;
+- if (!key->oif || key->oif == nh->nh_oif)
+- break;
++ if (key->oif && key->oif != nh->nh_oif)
++ continue;
++ if (key->gw && key->gw != nh->nh_gw &&
++ nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK)
++ continue;
++ break;
+ }
+ #ifdef CONFIG_IP_ROUTE_MULTIPATH
+ if (nhsel < fi->fib_nhs) {
+@@ -870,22 +906,35 @@
+ if (local && fi->fib_prefsrc == local) {
+ fi->fib_flags |= RTNH_F_DEAD;
+ ret++;
+- } else if (dev && fi->fib_nhs) {
++ } else if (fi->fib_nhs) {
+ int dead = 0;
+
+ change_nexthops(fi) {
+- if (nh->nh_flags&RTNH_F_DEAD)
+- dead++;
+- else if (nh->nh_dev == dev &&
+- nh->nh_scope != scope) {
+- nh->nh_flags |= RTNH_F_DEAD;
++ if (nh->nh_flags&RTNH_F_DEAD) {
++ if (fi->fib_protocol!=RTPROT_STATIC ||
++ nh->nh_dev == NULL ||
++ !__in_dev_get(nh->nh_dev) ||
++ nh->nh_dev->flags&IFF_UP)
++ dead++;
++ } else if ((nh->nh_dev == dev && dev &&
++ nh->nh_scope != scope) ||
++ (local == nh->nh_gw && local &&
++ nh->nh_oif)) {
++ write_lock_bh(&fib_nhflags_lock);
+ #ifdef CONFIG_IP_ROUTE_MULTIPATH
+- spin_lock_bh(&fib_multipath_lock);
++ spin_lock(&fib_multipath_lock);
++ nh->nh_flags |= RTNH_F_DEAD;
+ fi->fib_power -= nh->nh_power;
+ nh->nh_power = 0;
+- spin_unlock_bh(&fib_multipath_lock);
++ spin_unlock(&fib_multipath_lock);
++#else
++ nh->nh_flags |= RTNH_F_DEAD;
+ #endif
+- dead++;
++ write_unlock_bh(&fib_nhflags_lock);
++ if (fi->fib_protocol!=RTPROT_STATIC ||
++ force ||
++ (dev && __in_dev_get(dev) == NULL))
++ dead++;
+ }
+ #ifdef CONFIG_IP_ROUTE_MULTIPATH
+ if (force > 1 && nh->nh_dev == dev) {
+@@ -903,37 +952,55 @@
+ return ret;
+ }
+
+-#ifdef CONFIG_IP_ROUTE_MULTIPATH
+-
+ /*
+- Dead device goes up. We wake up dead nexthops.
+- It takes sense only on multipath routes.
++ Dead device goes up or new address is added. We wake up dead nexthops.
+ */
+
+ int fib_sync_up(struct net_device *dev)
+ {
+- int ret = 0;
++ struct rt_key key;
++ struct fib_result res;
++ int ret, rep;
+
++repeat:
+ if (!(dev->flags&IFF_UP))
+ return 0;
+
++ ret = 0;
++ rep = 0;
+ for_fib_info() {
+ int alive = 0;
+
+ change_nexthops(fi) {
+- if (!(nh->nh_flags&RTNH_F_DEAD)) {
+- alive++;
++ if (!(nh->nh_flags&RTNH_F_DEAD))
+ continue;
+- }
+ if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP))
+ continue;
+ if (nh->nh_dev != dev || __in_dev_get(dev) == NULL)
+ continue;
++ if (nh->nh_gw && fi->fib_protocol == RTPROT_STATIC) {
++ memset(&key, 0, sizeof(key));
++ key.dst = nh->nh_gw;
++ key.oif = nh->nh_oif;
++ key.scope = nh->nh_scope;
++ if (fib_lookup(&key, &res) != 0)
++ continue;
++ if (res.type != RTN_UNICAST &&
++ res.type != RTN_LOCAL) {
++ fib_res_put(&res);
++ continue;
++ }
++ nh->nh_scope = res.scope;
++ fib_res_put(&res);
++ rep = 1;
++ }
+ alive++;
++#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ spin_lock_bh(&fib_multipath_lock);
+ nh->nh_power = 0;
+ nh->nh_flags &= ~RTNH_F_DEAD;
+ spin_unlock_bh(&fib_multipath_lock);
++#endif
+ } endfor_nexthops(fi)
+
+ if (alive > 0) {
+@@ -941,9 +1008,13 @@
+ ret++;
+ }
+ } endfor_fib_info();
++ if (rep)
++ goto repeat;
+ return ret;
+ }
+
++#ifdef CONFIG_IP_ROUTE_MULTIPATH
++
+ /*
+ The algorithm is suboptimal, but it provides really
+ fair weighted route distribution.
+@@ -952,24 +1023,45 @@
+ void fib_select_multipath(const struct rt_key *key, struct fib_result *res)
+ {
+ struct fib_info *fi = res->fi;
+- int w;
++ int w, alive;
+
+ spin_lock_bh(&fib_multipath_lock);
++ if (key->oif) {
++ int sel = -1;
++ w = -1;
++ change_nexthops(fi) {
++ if (key->oif != nh->nh_oif)
++ continue;
++ if (key->gw && key->gw != nh->nh_gw &&
++ nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK)
++ continue;
++ if (!(nh->nh_flags&RTNH_F_BADSTATE)) {
++ if (nh->nh_power > w) {
++ w = nh->nh_power;
++ sel = nhsel;
++ }
++ }
++ } endfor_nexthops(fi);
++ if (sel >= 0) {
++ spin_unlock_bh(&fib_multipath_lock);
++ res->nh_sel = sel;
++ return;
++ }
++ goto last_resort;
++ }
++
++repeat:
+ if (fi->fib_power <= 0) {
+ int power = 0;
+ change_nexthops(fi) {
+- if (!(nh->nh_flags&RTNH_F_DEAD)) {
++ if (!(nh->nh_flags&RTNH_F_BADSTATE)) {
+ power += nh->nh_weight;
+ nh->nh_power = nh->nh_weight;
+ }
+ } endfor_nexthops(fi);
+ fi->fib_power = power;
+- if (power <= 0) {
+- spin_unlock_bh(&fib_multipath_lock);
+- /* Race condition: route has just become dead. */
+- res->nh_sel = 0;
+- return;
+- }
++ if (power <= 0)
++ goto last_resort;
+ }
+
+
+@@ -979,20 +1071,40 @@
+
+ w = jiffies % fi->fib_power;
+
++ alive = 0;
+ change_nexthops(fi) {
+- if (!(nh->nh_flags&RTNH_F_DEAD) && nh->nh_power) {
++ if (!(nh->nh_flags&RTNH_F_BADSTATE) && nh->nh_power) {
+ if ((w -= nh->nh_power) <= 0) {
+ nh->nh_power--;
+ fi->fib_power--;
+- res->nh_sel = nhsel;
+ spin_unlock_bh(&fib_multipath_lock);
++ res->nh_sel = nhsel;
+ return;
+ }
++ alive = 1;
++ }
++ } endfor_nexthops(fi);
++ if (alive) {
++ fi->fib_power = 0;
++ goto repeat;
++ }
++
++last_resort:
++
++ for_nexthops(fi) {
++ if (!(nh->nh_flags&RTNH_F_DEAD)) {
++ if (key->oif && key->oif != nh->nh_oif)
++ continue;
++ if (key->gw && key->gw != nh->nh_gw &&
++ nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK)
++ continue;
++ spin_unlock_bh(&fib_multipath_lock);
++ res->nh_sel = nhsel;
++ return;
+ }
+ } endfor_nexthops(fi);
+
+ /* Race condition: route has just become dead. */
+- res->nh_sel = 0;
+ spin_unlock_bh(&fib_multipath_lock);
+ }
+ #endif
+diff -ur v2.4.29/linux/net/ipv4/ip_nat_dumb.c linux/net/ipv4/ip_nat_dumb.c
+--- v2.4.29/linux/net/ipv4/ip_nat_dumb.c 2001-11-13 03:25:26.000000000 +0200
++++ linux/net/ipv4/ip_nat_dumb.c 2005-01-20 09:55:47.001651520 +0200
+@@ -124,6 +124,7 @@
+ key.dst = ciph->saddr;
+ key.iif = skb->dev->ifindex;
+ key.oif = 0;
++ key.gw = 0;
+ #ifdef CONFIG_IP_ROUTE_TOS
+ key.tos = RT_TOS(ciph->tos);
+ #endif
+diff -ur v2.4.29/linux/net/ipv4/netfilter/ip_fw_compat_masq.c linux/net/ipv4/netfilter/ip_fw_compat_masq.c
+--- v2.4.29/linux/net/ipv4/netfilter/ip_fw_compat_masq.c 2005-01-20 09:25:34.000000000 +0200
++++ linux/net/ipv4/netfilter/ip_fw_compat_masq.c 2005-01-20 09:55:47.001651520 +0200
+@@ -41,6 +41,10 @@
+ enum ip_conntrack_info ctinfo;
+ struct ip_conntrack *ct;
+ unsigned int ret;
++ struct rtable *rt, *skb_rt;
++ struct net_device *skb_dev;
++ __u32 saddr;
++ int new;
+
+ /* Sorry, only ICMP, TCP and UDP. */
+ if (iph->protocol != IPPROTO_ICMP
+@@ -64,22 +68,28 @@
+ }
+
+ info = &ct->nat.info;
++ iph = (*pskb)->nh.iph;
++ saddr = iph->saddr;
++ new = 0;
+
+ WRITE_LOCK(&ip_nat_lock);
+ /* Setup the masquerade, if not already */
+ if (!info->initialized) {
+ u_int32_t newsrc;
+- struct rtable *rt;
+ struct ip_nat_multi_range range;
+
++ skb_rt = (struct rtable *) (*pskb)->dst;
++ skb_dev = skb_rt->u.dst.dev;
+ /* Pass 0 instead of saddr, since it's going to be changed
+ anyway. */
+- if (ip_route_output(&rt, iph->daddr, 0, 0, 0) != 0) {
++ if (ip_route_output_lookup(&rt, iph->daddr, 0, RT_TOS(iph->tos),
++ skb_dev? skb_dev->ifindex : 0,
++ skb_dev? skb_rt->rt_gateway : 0) != 0) {
++ WRITE_UNLOCK(&ip_nat_lock);
+ DEBUGP("ipnat_rule_masquerade: Can't reroute.\n");
+ return NF_DROP;
+ }
+- newsrc = inet_select_addr(rt->u.dst.dev, rt->rt_gateway,
+- RT_SCOPE_UNIVERSE);
++ newsrc = rt->rt_src;
+ ip_rt_put(rt);
+ range = ((struct ip_nat_multi_range)
+ { 1,
+@@ -92,11 +102,31 @@
+ WRITE_UNLOCK(&ip_nat_lock);
+ return ret;
+ }
++ new = 1;
+ } else
+ DEBUGP("Masquerading already done on this conn.\n");
+ WRITE_UNLOCK(&ip_nat_lock);
+
+- return do_bindings(ct, ctinfo, info, NF_IP_POST_ROUTING, pskb);
++ ret = do_bindings(ct, ctinfo, info, NF_IP_POST_ROUTING, pskb);
++ if (ret != NF_ACCEPT || saddr == (*pskb)->nh.iph->saddr || new)
++ return ret;
++
++ iph = (*pskb)->nh.iph;
++ if (ip_route_output(&rt, iph->daddr, iph->saddr, RT_TOS(iph->tos), 0) != 0)
++ return NF_DROP;
++
++ skb_rt = (struct rtable *) (*pskb)->dst;
++ skb_dev = skb_rt->u.dst.dev;
++ if (skb_dev != rt->u.dst.dev || rt->rt_gateway != skb_rt->rt_gateway) {
++ if (skb_dev != rt->u.dst.dev) {
++ /* TODO: check the new mtu and reply FRAG_NEEDED */
++ }
++ dst_release((*pskb)->dst);
++ (*pskb)->dst = &rt->u.dst;
++ } else {
++ ip_rt_put(rt);
++ }
++ return NF_ACCEPT;
+ }
+
+ void
+diff -ur v2.4.29/linux/net/ipv4/netfilter/ip_nat_core.c linux/net/ipv4/netfilter/ip_nat_core.c
+--- v2.4.29/linux/net/ipv4/netfilter/ip_nat_core.c 2005-01-20 09:25:34.000000000 +0200
++++ linux/net/ipv4/netfilter/ip_nat_core.c 2005-01-20 09:55:47.002651368 +0200
+@@ -994,6 +994,60 @@
+ return NF_ACCEPT;
+ }
+
++unsigned int
++ip_nat_route_input(unsigned int hooknum,
++ struct sk_buff **pskb,
++ const struct net_device *in,
++ const struct net_device *out,
++ int (*okfn)(struct sk_buff *))
++{
++ struct sk_buff *skb = *pskb;
++ struct iphdr *iph;
++ struct ip_conntrack *ct;
++ enum ip_conntrack_info ctinfo;
++ struct ip_nat_info *info;
++ enum ip_conntrack_dir dir;
++ __u32 saddr;
++ int i;
++
++ if (!(ct = ip_conntrack_get(skb, &ctinfo)))
++ return NF_ACCEPT;
++
++ info = &ct->nat.info;
++ if (!info->initialized)
++ return NF_ACCEPT;
++
++ if (skb->dst)
++ return NF_ACCEPT;
++
++ if (skb->len < sizeof(struct iphdr))
++ return NF_ACCEPT;
++
++ iph = skb->nh.iph;
++ saddr = iph->saddr;
++ hooknum = NF_IP_POST_ROUTING;
++ dir = CTINFO2DIR(ctinfo);
++
++ READ_LOCK(&ip_nat_lock);
++ for (i = 0; i < info->num_manips; i++) {
++ if (info->manips[i].direction == dir
++ && info->manips[i].hooknum == hooknum
++ && info->manips[i].maniptype == IP_NAT_MANIP_SRC) {
++ saddr = info->manips[i].manip.ip;
++ }
++ }
++ READ_UNLOCK(&ip_nat_lock);
++
++ if (saddr == iph->saddr)
++ return NF_ACCEPT;
++
++ if (ip_route_input_lookup(skb, iph->daddr, iph->saddr, iph->tos,
++ skb->dev, saddr))
++ return NF_DROP;
++
++ return NF_ACCEPT;
++}
++
+ int __init ip_nat_init(void)
+ {
+ size_t i;
+diff -ur v2.4.29/linux/net/ipv4/netfilter/ip_nat_standalone.c linux/net/ipv4/netfilter/ip_nat_standalone.c
+--- v2.4.29/linux/net/ipv4/netfilter/ip_nat_standalone.c 2005-01-20 09:25:34.000000000 +0200
++++ linux/net/ipv4/netfilter/ip_nat_standalone.c 2005-01-20 09:55:47.002651368 +0200
+@@ -241,6 +241,9 @@
+ /* Before packet filtering, change destination */
+ static struct nf_hook_ops ip_nat_in_ops
+ = { { NULL, NULL }, ip_nat_in, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_NAT_DST };
++/* Before routing, route before mangling */
++static struct nf_hook_ops ip_nat_inr_ops
++= { { NULL, NULL }, ip_nat_route_input, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_LAST-1 };
+ /* After packet filtering, change source */
+ static struct nf_hook_ops ip_nat_out_ops
+ = { { NULL, NULL }, ip_nat_out, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_NAT_SRC};
+@@ -309,10 +312,15 @@
+ printk("ip_nat_init: can't register in hook.\n");
+ goto cleanup_nat;
+ }
++ ret = nf_register_hook(&ip_nat_inr_ops);
++ if (ret < 0) {
++ printk("ip_nat_init: can't register inr hook.\n");
++ goto cleanup_inops;
++ }
+ ret = nf_register_hook(&ip_nat_out_ops);
+ if (ret < 0) {
+ printk("ip_nat_init: can't register out hook.\n");
+- goto cleanup_inops;
++ goto cleanup_inrops;
+ }
+ ret = nf_register_hook(&ip_nat_local_out_ops);
+ if (ret < 0) {
+@@ -332,6 +340,8 @@
+ nf_unregister_hook(&ip_nat_local_out_ops);
+ cleanup_outops:
+ nf_unregister_hook(&ip_nat_out_ops);
++ cleanup_inrops:
++ nf_unregister_hook(&ip_nat_inr_ops);
+ cleanup_inops:
+ nf_unregister_hook(&ip_nat_in_ops);
+ cleanup_nat:
+diff -ur v2.4.29/linux/net/ipv4/netfilter/ipt_MASQUERADE.c linux/net/ipv4/netfilter/ipt_MASQUERADE.c
+--- v2.4.29/linux/net/ipv4/netfilter/ipt_MASQUERADE.c 2005-01-20 09:25:34.000000000 +0200
++++ linux/net/ipv4/netfilter/ipt_MASQUERADE.c 2005-01-20 09:55:47.003651216 +0200
+@@ -87,7 +87,8 @@
+ key.dst = (*pskb)->nh.iph->daddr;
+ key.src = 0; /* Unknown: that's what we're trying to establish */
+ key.tos = RT_TOS((*pskb)->nh.iph->tos)|RTO_CONN;
+- key.oif = 0;
++ key.oif = out->ifindex;
++ key.gw = ((struct rtable *) (*pskb)->dst)->rt_gateway;
+ #ifdef CONFIG_IP_ROUTE_FWMARK
+ key.fwmark = (*pskb)->nfmark;
+ #endif
+@@ -98,13 +99,6 @@
+ " No route: Rusty's brain broke!\n");
+ return NF_DROP;
+ }
+- if (rt->u.dst.dev != out) {
+- if (net_ratelimit())
+- printk("MASQUERADE:"
+- " Route sent us somewhere else.\n");
+- ip_rt_put(rt);
+- return NF_DROP;
+- }
+
+ newsrc = rt->rt_src;
+ DEBUGP("newsrc = %u.%u.%u.%u\n", NIPQUAD(newsrc));
+diff -ur v2.4.29/linux/net/ipv4/route.c linux/net/ipv4/route.c
+--- v2.4.29/linux/net/ipv4/route.c 2004-11-18 08:30:33.000000000 +0200
++++ linux/net/ipv4/route.c 2005-01-20 09:55:47.004651064 +0200
+@@ -919,6 +919,7 @@
+
+ /* Gateway is different ... */
+ rt->rt_gateway = new_gw;
++ if (rt->key.gw) rt->key.gw = new_gw;
+
+ /* Redirect received -> path was valid */
+ dst_confirm(&rth->u.dst);
+@@ -1343,6 +1344,7 @@
+ rth->key.fwmark = skb->nfmark;
+ #endif
+ rth->key.src = saddr;
++ rth->key.lsrc = 0;
+ rth->rt_src = saddr;
+ #ifdef CONFIG_IP_ROUTE_NAT
+ rth->rt_dst_map = daddr;
+@@ -1356,6 +1358,7 @@
+ rth->u.dst.dev = &loopback_dev;
+ dev_hold(rth->u.dst.dev);
+ rth->key.oif = 0;
++ rth->key.gw = 0;
+ rth->rt_gateway = daddr;
+ rth->rt_spec_dst= spec_dst;
+ rth->rt_type = RTN_MULTICAST;
+@@ -1395,7 +1398,7 @@
+ */
+
+ int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
+- u8 tos, struct net_device *dev)
++ u8 tos, struct net_device *dev, u32 lsrc)
+ {
+ struct rt_key key;
+ struct fib_result res;
+@@ -1415,16 +1418,17 @@
+ goto out;
+
+ key.dst = daddr;
+- key.src = saddr;
++ key.src = lsrc? : saddr;
+ key.tos = tos;
+ #ifdef CONFIG_IP_ROUTE_FWMARK
+ key.fwmark = skb->nfmark;
+ #endif
+- key.iif = dev->ifindex;
++ key.iif = lsrc? loopback_dev.ifindex : dev->ifindex;
+ key.oif = 0;
++ key.gw = 0;
+ key.scope = RT_SCOPE_UNIVERSE;
+
+- hash = rt_hash_code(daddr, saddr ^ (key.iif << 5), tos);
++ hash = rt_hash_code(daddr, saddr ^ (dev->ifindex << 5), tos);
+
+ /* Check for the most weird martians, which can be not detected
+ by fib_lookup.
+@@ -1445,6 +1449,12 @@
+ if (BADCLASS(daddr) || ZERONET(daddr) || LOOPBACK(daddr))
+ goto martian_destination;
+
++ if (lsrc) {
++ if (MULTICAST(lsrc) || BADCLASS(lsrc) ||
++ ZERONET(lsrc) || LOOPBACK(lsrc))
++ goto e_inval;
++ }
++
+ /*
+ * Now we are ready to route packet.
+ */
+@@ -1454,6 +1464,10 @@
+ goto no_route;
+ }
+ free_res = 1;
++ if (lsrc && res.type != RTN_UNICAST && res.type != RTN_NAT)
++ goto e_inval;
++ key.iif = dev->ifindex;
++ key.src = saddr;
+
+ rt_cache_stat[smp_processor_id()].in_slow_tot++;
+
+@@ -1464,7 +1478,7 @@
+
+ if (1) {
+ u32 src_map = saddr;
+- if (res.r)
++ if (res.r && !lsrc)
+ src_map = fib_rules_policy(saddr, &res, &flags);
+
+ if (res.type == RTN_NAT) {
+@@ -1503,8 +1517,9 @@
+ if (res.type != RTN_UNICAST)
+ goto martian_destination;
+
++ fib_select_default(&key, &res);
+ #ifdef CONFIG_IP_ROUTE_MULTIPATH
+- if (res.fi->fib_nhs > 1 && key.oif == 0)
++ if (res.fi->fib_nhs > 1)
+ fib_select_multipath(&key, &res);
+ #endif
+ out_dev = in_dev_get(FIB_RES_DEV(res));
+@@ -1524,6 +1539,7 @@
+ flags |= RTCF_DIRECTSRC;
+
+ if (out_dev == in_dev && err && !(flags & (RTCF_NAT | RTCF_MASQ)) &&
++ !lsrc &&
+ (IN_DEV_SHARED_MEDIA(out_dev) ||
+ inet_addr_onlink(out_dev, saddr, FIB_RES_GW(res))))
+ flags |= RTCF_DOREDIRECT;
+@@ -1550,6 +1566,7 @@
+ #endif
+ rth->key.src = saddr;
+ rth->rt_src = saddr;
++ rth->key.lsrc = lsrc;
+ rth->rt_gateway = daddr;
+ #ifdef CONFIG_IP_ROUTE_NAT
+ rth->rt_src_map = key.src;
+@@ -1562,6 +1579,7 @@
+ rth->u.dst.dev = out_dev->dev;
+ dev_hold(rth->u.dst.dev);
+ rth->key.oif = 0;
++ rth->key.gw = 0;
+ rth->rt_spec_dst= spec_dst;
+
+ rth->u.dst.input = ip_forward;
+@@ -1572,7 +1590,8 @@
+ rth->rt_flags = flags;
+
+ #ifdef CONFIG_NET_FASTROUTE
+- if (netdev_fastroute && !(flags&(RTCF_NAT|RTCF_MASQ|RTCF_DOREDIRECT))) {
++ if (netdev_fastroute && !(flags&(RTCF_NAT|RTCF_MASQ|RTCF_DOREDIRECT)) &&
++ !lsrc) {
+ struct net_device *odev = rth->u.dst.dev;
+ if (odev != dev &&
+ dev->accept_fastpath &&
+@@ -1595,6 +1614,8 @@
+ brd_input:
+ if (skb->protocol != htons(ETH_P_IP))
+ goto e_inval;
++ if (lsrc)
++ goto e_inval;
+
+ if (ZERONET(saddr))
+ spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
+@@ -1627,6 +1648,7 @@
+ #endif
+ rth->key.src = saddr;
+ rth->rt_src = saddr;
++ rth->key.lsrc = 0;
+ #ifdef CONFIG_IP_ROUTE_NAT
+ rth->rt_dst_map = key.dst;
+ rth->rt_src_map = key.src;
+@@ -1639,6 +1661,7 @@
+ rth->u.dst.dev = &loopback_dev;
+ dev_hold(rth->u.dst.dev);
+ rth->key.oif = 0;
++ rth->key.gw = 0;
+ rth->rt_gateway = daddr;
+ rth->rt_spec_dst= spec_dst;
+ rth->u.dst.input= ip_local_deliver;
+@@ -1704,8 +1727,9 @@
+ goto e_inval;
+ }
+
+-int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
+- u8 tos, struct net_device *dev)
++static inline int
++ip_route_input_cached(struct sk_buff *skb, u32 daddr, u32 saddr,
++ u8 tos, struct net_device *dev, u32 lsrc)
+ {
+ struct rtable * rth;
+ unsigned hash;
+@@ -1719,6 +1743,7 @@
+ if (rth->key.dst == daddr &&
+ rth->key.src == saddr &&
+ rth->key.iif == iif &&
++ rth->key.lsrc == lsrc &&
+ rth->key.oif == 0 &&
+ #ifdef CONFIG_IP_ROUTE_FWMARK
+ rth->key.fwmark == skb->nfmark &&
+@@ -1766,9 +1791,21 @@
+ read_unlock(&inetdev_lock);
+ return -EINVAL;
+ }
+- return ip_route_input_slow(skb, daddr, saddr, tos, dev);
++ return ip_route_input_slow(skb, daddr, saddr, tos, dev, lsrc);
++}
++
++int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
++ u8 tos, struct net_device *dev)
++{
++ return ip_route_input_cached(skb, daddr, saddr, tos, dev, 0);
+ }
+
++int ip_route_input_lookup(struct sk_buff *skb, u32 daddr, u32 saddr,
++ u8 tos, struct net_device *dev, u32 lsrc)
++{
++ return ip_route_input_cached(skb, daddr, saddr, tos, dev, lsrc);
++}
++
+ /*
+ * Major route resolver routine.
+ */
+@@ -1791,6 +1828,7 @@
+ key.tos = tos & IPTOS_RT_MASK;
+ key.iif = loopback_dev.ifindex;
+ key.oif = oldkey->oif;
++ key.gw = oldkey->gw;
+ #ifdef CONFIG_IP_ROUTE_FWMARK
+ key.fwmark = oldkey->fwmark;
+ #endif
+@@ -1880,6 +1918,7 @@
+ dev_out = &loopback_dev;
+ dev_hold(dev_out);
+ key.oif = loopback_dev.ifindex;
++ key.gw = 0;
+ res.type = RTN_LOCAL;
+ flags |= RTCF_LOCAL;
+ goto make_route;
+@@ -1887,7 +1926,7 @@
+
+ if (fib_lookup(&key, &res)) {
+ res.fi = NULL;
+- if (oldkey->oif) {
++ if (oldkey->oif && dev_out->flags&IFF_UP) {
+ /* Apparently, routing tables are wrong. Assume,
+ that the destination is on link.
+
+@@ -1930,6 +1969,7 @@
+ dev_out = &loopback_dev;
+ dev_hold(dev_out);
+ key.oif = dev_out->ifindex;
++ key.gw = 0;
+ if (res.fi)
+ fib_info_put(res.fi);
+ res.fi = NULL;
+@@ -1937,13 +1977,12 @@
+ goto make_route;
+ }
+
++ if (res.type == RTN_UNICAST)
++ fib_select_default(&key, &res);
+ #ifdef CONFIG_IP_ROUTE_MULTIPATH
+- if (res.fi->fib_nhs > 1 && key.oif == 0)
++ if (res.fi->fib_nhs > 1)
+ fib_select_multipath(&key, &res);
+- else
+ #endif
+- if (!res.prefixlen && res.type == RTN_UNICAST && !key.oif)
+- fib_select_default(&key, &res);
+
+ if (!key.src)
+ key.src = FIB_RES_PREFSRC(res);
+@@ -2001,7 +2040,9 @@
+ rth->key.tos = tos;
+ rth->key.src = oldkey->src;
+ rth->key.iif = 0;
++ rth->key.lsrc = 0;
+ rth->key.oif = oldkey->oif;
++ rth->key.gw = oldkey->gw;
+ #ifdef CONFIG_IP_ROUTE_FWMARK
+ rth->key.fwmark = oldkey->fwmark;
+ #endif
+@@ -2080,6 +2121,7 @@
+ rth->key.src == key->src &&
+ rth->key.iif == 0 &&
+ rth->key.oif == key->oif &&
++ rth->key.gw == key->gw &&
+ #ifdef CONFIG_IP_ROUTE_FWMARK
+ rth->key.fwmark == key->fwmark &&
+ #endif
+diff -ur v2.4.29/linux/net/netsyms.c linux/net/netsyms.c
+--- v2.4.29/linux/net/netsyms.c 2005-01-20 09:25:34.000000000 +0200
++++ linux/net/netsyms.c 2005-01-20 09:55:47.005650912 +0200
+@@ -260,6 +260,7 @@
+ EXPORT_SYMBOL(inet_unregister_protosw);
+ EXPORT_SYMBOL(ip_route_output_key);
+ EXPORT_SYMBOL(ip_route_input);
++EXPORT_SYMBOL(ip_route_input_lookup);
+ EXPORT_SYMBOL(icmp_send);
+ EXPORT_SYMBOL(icmp_statistics);
+ EXPORT_SYMBOL(icmp_err_convert);
diff --git a/target/linux/generic-2.6/files/init b/target/linux/generic-2.6/files/init
new file mode 100755
index 0000000000..1fa6a7f1f6
--- /dev/null
+++ b/target/linux/generic-2.6/files/init
@@ -0,0 +1,82 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin
+mount none /proc -t proc
+mount none /dev -t devfs
+mount non /dev/pts -t devpts
+
+# the root mount point can come from the kernel command line
+# or it can be overridden in the preinit.arch file
+[ -f /etc/preinit.arch ] && . /etc/preinit.arch
+
+# if we have no root parameter, just go to running from ramfs
+[ -z $rootfs ] && {
+ export NOMOUNT="No Root"
+ exec /sbin/init
+}
+
+#if we have a failsafe boot selected, dont bother
+#trying to find or wait for a root mount point
+[ -z "$FAILSAFE" ] || {
+ exec /bin/busybox init
+}
+
+# Load the modules we have in initramfs, this should
+# make the media accessible, but, it may take some time
+. /etc/functions.sh
+load_modules /etc/modules /etc/modules.d/*
+
+#wait 10 seconds for the disc to show up
+#usb stick typically takes 4 to 6 seconds
+#till it's readable
+#it's quite possible the disc never shows up
+#if we netbooted this kernel
+COUNTER=0
+while [ $COUNTER -lt 10 ]; do
+ sleep 1
+ [ -e $rootfs ] && let COUNTER=10;
+ let COUNTER=COUNTER+1
+done
+[ -e $rootfs ] || {
+ export FAILSAFE="NoDisc"
+ exec /bin/busybox init
+}
+
+# now we'll try mount it, again with a timeout
+# This will fail if the inserted stick is formatted
+# in a manner we dont understand
+COUNTER=0
+while [ $COUNTER -lt 10 ]; do
+ sleep 1
+ mount $rootfs /mnt
+ [ $? -eq "0" ] && let COUNTER=100;
+ let COUNTER=COUNTER+1
+done
+[ $? -ne "0" ] && {
+ export FAILSAFE="MountFail"
+ exec /bin/busybox init
+}
+
+#It mounted, lets look for a postinit file, again, give it time
+#I've seen this take 6 seconds to actually complete
+COUNTER=0
+while [ $COUNTER -lt 10 ]; do
+ sleep 1
+ [ -e /mnt/etc/banner ] && let COUNTER=10;
+ let COUNTER=COUNTER+1
+done
+[ -e /mnt/etc/banner ] || {
+ export FAILSAFE="No Openwrt FS"
+ exec /bin/busybox init
+}
+
+unset rootfs
+
+mount -o move /proc /mnt/proc
+mount -o move /dev /mnt/dev
+mount -o move /dev/pts /mnt/dev/pts
+mount -o move /tmp /mnt/tmp
+mount -o move /sys /mnt/sys
+mount none /tmp -t tmpfs
+exec switch_root -c /dev/console /mnt /sbin/init
diff --git a/target/linux/generic-2.6/patches/000-reenable_devfs.patch b/target/linux/generic-2.6/patches/000-reenable_devfs.patch
new file mode 100644
index 0000000000..7871c4c378
--- /dev/null
+++ b/target/linux/generic-2.6/patches/000-reenable_devfs.patch
@@ -0,0 +1,718 @@
+diff -ur linux-2.6.15-rc5/drivers/mtd/mtd_blkdevs.c linux-2.6.15-rc5-openwrt/drivers/mtd/mtd_blkdevs.c
+--- linux-2.6.15-rc5/drivers/mtd/mtd_blkdevs.c 2005-12-04 06:10:42.000000000 +0100
++++ linux-2.6.15-rc5-openwrt/drivers/mtd/mtd_blkdevs.c 2005-12-15 07:53:20.000000000 +0100
+@@ -21,6 +21,9 @@
+ #include <linux/init.h>
+ #include <asm/semaphore.h>
+ #include <asm/uaccess.h>
++#ifdef CONFIG_DEVFS_FS
++#include <linux/devfs_fs_kernel.h>
++#endif
+
+ static LIST_HEAD(blktrans_majors);
+
+@@ -302,6 +305,11 @@
+ snprintf(gd->disk_name, sizeof(gd->disk_name),
+ "%s%d", tr->name, new->devnum);
+
++#ifdef CONFIG_DEVFS_FS
++ snprintf(gd->devfs_name, sizeof(gd->devfs_name),
++ "%s/%c", tr->name, (tr->part_bits?'a':'0') + new->devnum);
++#endif
++
+ /* 2.5 has capacity in units of 512 bytes while still
+ having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */
+ set_capacity(gd, (new->size * new->blksize) >> 9);
+@@ -418,6 +426,10 @@
+ return ret;
+ }
+
++#ifdef CONFIG_DEVFS_FS
++ devfs_mk_dir(tr->name);
++#endif
++
+ INIT_LIST_HEAD(&tr->devs);
+ list_add(&tr->list, &blktrans_majors);
+
+@@ -450,6 +462,10 @@
+ tr->remove_dev(dev);
+ }
+
++#ifdef CONFIG_DEVFS_FS
++ devfs_remove(tr->name);
++#endif
++
+ blk_cleanup_queue(tr->blkcore_priv->rq);
+ unregister_blkdev(tr->major, tr->name);
+
+diff -ur linux-2.6.15-rc5/drivers/mtd/mtdchar.c linux-2.6.15-rc5-openwrt/drivers/mtd/mtdchar.c
+--- linux-2.6.15-rc5/drivers/mtd/mtdchar.c 2005-12-04 06:10:42.000000000 +0100
++++ linux-2.6.15-rc5-openwrt/drivers/mtd/mtdchar.c 2005-12-15 07:49:15.000000000 +0100
+@@ -19,19 +18,33 @@
+
+ #include <asm/uaccess.h>
+
++#ifdef CONFIG_DEVFS_FS
++#include <linux/devfs_fs_kernel.h>
++#else
++#include <linux/device.h>
++
+ static struct class *mtd_class;
++#endif
+
+ static void mtd_notify_add(struct mtd_info* mtd)
+ {
+ if (!mtd)
+ return;
+
++#ifdef CONFIG_DEVFS_FS
++ devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
++ S_IFCHR | S_IRUGO | S_IWUGO, "mtd/%d", mtd->index);
++
++ devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
++ S_IFCHR | S_IRUGO, "mtd/%dro", mtd->index);
++#else
+ class_device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
+ NULL, "mtd%d", mtd->index);
+
+ class_device_create(mtd_class, NULL,
+ MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
+ NULL, "mtd%dro", mtd->index);
++#endif
+ }
+
+ static void mtd_notify_remove(struct mtd_info* mtd)
+@@ -39,8 +52,13 @@
+ if (!mtd)
+ return;
+
++#ifdef CONFIG_DEVFS_FS
++ devfs_remove("mtd/%d", mtd->index);
++ devfs_remove("mtd/%dro", mtd->index);
++#else
+ class_device_destroy(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2));
+ class_device_destroy(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1));
++#endif
+ }
+
+ static struct mtd_notifier notifier = {
+@@ -48,6 +66,22 @@
+ .remove = mtd_notify_remove,
+ };
+
++#ifdef CONFIG_DEVFS_FS
++ static inline void mtdchar_devfs_init(void)
++ {
++ devfs_mk_dir("mtd");
++ register_mtd_user(&notifier);
++ }
++ static inline void mtdchar_devfs_exit(void)
++ {
++ unregister_mtd_user(&notifier);
++ devfs_remove("mtd");
++ }
++ #else /* !DEVFS */
++ #define mtdchar_devfs_init() do { } while(0)
++ #define mtdchar_devfs_exit() do { } while(0)
++#endif
++
+ /*
+ * We use file->private_data to store a pointer to the MTDdevice.
+ * Since alighment is at least 32 bits, we have 2 bits free for OTP
+@@ -643,6 +677,9 @@
+ return -EAGAIN;
+ }
+
++#ifdef CONFIG_DEVFS_FS
++ mtdchar_devfs_init();
++#else
+ mtd_class = class_create(THIS_MODULE, "mtd");
+
+ if (IS_ERR(mtd_class)) {
+@@ -652,13 +689,19 @@
+ }
+
+ register_mtd_user(&notifier);
++#endif
+ return 0;
+ }
+
+ static void __exit cleanup_mtdchar(void)
+ {
++
++#ifdef CONFIG_DEVFS_FS
++ mtdchar_devfs_exit();
++#else
+ unregister_mtd_user(&notifier);
+ class_destroy(mtd_class);
++#endif
+ unregister_chrdev(MTD_CHAR_MAJOR, "mtd");
+ }
+
+diff -ur linux-2.6.15-rc5/fs/Kconfig linux-2.6.15-rc5-openwrt/fs/Kconfig
+--- linux-2.6.15-rc5/fs/Kconfig 2005-12-04 06:10:42.000000000 +0100
++++ linux-2.6.15-rc5-openwrt/fs/Kconfig 2005-12-15 07:44:01.000000000 +0100
+@@ -772,6 +772,56 @@
+ help
+ Exports the dump image of crashed kernel in ELF format.
+
++config DEVFS_FS
++ bool "/dev file system support (OBSOLETE)"
++ depends on EXPERIMENTAL
++ help
++ This is support for devfs, a virtual file system (like /proc) which
++ provides the file system interface to device drivers, normally found
++ in /dev. Devfs does not depend on major and minor number
++ allocations. Device drivers register entries in /dev which then
++ appear automatically, which means that the system administrator does
++ not have to create character and block special device files in the
++ /dev directory using the mknod command (or MAKEDEV script) anymore.
++
++ This is work in progress. If you want to use this, you *must* read
++ the material in <file:Documentation/filesystems/devfs/>, especially
++ the file README there.
++
++ Note that devfs no longer manages /dev/pts! If you are using UNIX98
++ ptys, you will also need to mount the /dev/pts filesystem (devpts).
++
++ Note that devfs has been obsoleted by udev,
++ <http://www.kernel.org/pub/linux/utils/kernel/hotplug/>.
++ It has been stripped down to a bare minimum and is only provided for
++ legacy installations that use its naming scheme which is
++ unfortunately different from the names normal Linux installations
++ use.
++
++ If unsure, say N.
++
++config DEVFS_MOUNT
++ bool "Automatically mount at boot"
++ depends on DEVFS_FS
++ help
++ This option appears if you have CONFIG_DEVFS_FS enabled. Setting
++ this to 'Y' will make the kernel automatically mount devfs onto /dev
++ when the system is booted, before the init thread is started.
++ You can override this with the "devfs=nomount" boot option.
++
++ If unsure, say N.
++
++config DEVFS_DEBUG
++ bool "Debug devfs"
++ depends on DEVFS_FS
++ help
++ If you say Y here, then the /dev file system code will generate
++ debugging messages. See the file
++ <file:Documentation/filesystems/devfs/boot-options> for more
++ details.
++
++ If unsure, say N.
++
+ config SYSFS
+ bool "sysfs file system support" if EMBEDDED
+ default y
+diff -ur linux-2.6.17/drivers/ieee1394/dv1394.c linux-2.6.17-devfs/drivers/ieee1394/dv1394.c
+--- linux-2.6.17/drivers/ieee1394/dv1394.c 2006-06-17 18:49:35.000000000 -0700
++++ linux-2.6.17-devfs/drivers/ieee1394/dv1394.c 2006-08-25 11:06:18.000000000 -0700
+@@ -73,7 +73,7 @@
+ - fix all XXX showstoppers
+ - disable IR/IT DMA interrupts on shutdown
+ - flush pci writes to the card by issuing a read
+- - character device dispatching
++ - devfs and character device dispatching (* needs testing with Linux 2.2.x)
+ - switch over to the new kernel DMA API (pci_map_*()) (* needs testing on platforms with IOMMU!)
+ - keep all video_cards in a list (for open() via chardev), set file->private_data = video
+ - dv1394_poll should indicate POLLIN when receiving buffers are available
+@@ -1096,6 +1096,7 @@
+
+ init.api_version = DV1394_API_VERSION;
+ init.n_frames = DV1394_MAX_FRAMES / 4;
++ /* the following are now set via devfs */
+ init.channel = video->channel;
+ init.format = video->pal_or_ntsc;
+ init.cip_n = video->cip_n;
+@@ -1790,6 +1791,8 @@
+ {
+ struct video_card *video = NULL;
+
++ /* if the device was opened through devfs, then file->private_data
++ has already been set to video by devfs */
+ if (file->private_data) {
+ video = (struct video_card*) file->private_data;
+
+@@ -2208,7 +2211,7 @@
+ video = kzalloc(sizeof(*video), GFP_KERNEL);
+ if (!video) {
+ printk(KERN_ERR "dv1394: cannot allocate video_card\n");
+- return -1;
++ goto err;
+ }
+
+ video->ohci = ohci;
+@@ -2263,14 +2266,37 @@
+ list_add_tail(&video->list, &dv1394_cards);
+ spin_unlock_irqrestore(&dv1394_cards_lock, flags);
+
++ if (devfs_mk_cdev(MKDEV(IEEE1394_MAJOR,
++ IEEE1394_MINOR_BLOCK_DV1394*16 + video->id),
++ S_IFCHR|S_IRUGO|S_IWUGO,
++ "ieee1394/dv/host%d/%s/%s",
++ (video->id>>2),
++ (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
++ (video->mode == MODE_RECEIVE ? "in" : "out")) < 0)
++ goto err_free;
++
+ debug_printk("dv1394: dv1394_init() OK on ID %d\n", video->id);
++
+ return 0;
++
++ err_free:
++ kfree(video);
++ err:
++ return -1;
+ }
+
+ static void dv1394_un_init(struct video_card *video)
+ {
++ char buf[32];
++
+ /* obviously nobody has the driver open at this point */
+ do_dv1394_shutdown(video, 1);
++ snprintf(buf, sizeof(buf), "dv/host%d/%s/%s", (video->id >> 2),
++ (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
++ (video->mode == MODE_RECEIVE ? "in" : "out")
++ );
++
++ devfs_remove("ieee1394/%s", buf);
+ kfree(video);
+ }
+
+@@ -2307,6 +2333,9 @@
+
+ class_device_destroy(hpsb_protocol_class,
+ MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)));
++ devfs_remove("ieee1394/dv/host%d/NTSC", id);
++ devfs_remove("ieee1394/dv/host%d/PAL", id);
++ devfs_remove("ieee1394/dv/host%d", id);
+ }
+
+ static void dv1394_add_host (struct hpsb_host *host)
+@@ -2323,6 +2352,9 @@
+ class_device_create(hpsb_protocol_class, NULL, MKDEV(
+ IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
+ NULL, "dv1394-%d", id);
++ devfs_mk_dir("ieee1394/dv/host%d", id);
++ devfs_mk_dir("ieee1394/dv/host%d/NTSC", id);
++ devfs_mk_dir("ieee1394/dv/host%d/PAL", id);
+
+ dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
+ dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
+@@ -2579,8 +2611,10 @@
+ static void __exit dv1394_exit_module(void)
+ {
+ hpsb_unregister_protocol(&dv1394_driver);
++
+ hpsb_unregister_highlevel(&dv1394_highlevel);
+ cdev_del(&dv1394_cdev);
++ devfs_remove("ieee1394/dv");
+ }
+
+ static int __init dv1394_init_module(void)
+@@ -2596,12 +2630,15 @@
+ return ret;
+ }
+
++ devfs_mk_dir("ieee1394/dv");
++
+ hpsb_register_highlevel(&dv1394_highlevel);
+
+ ret = hpsb_register_protocol(&dv1394_driver);
+ if (ret) {
+ printk(KERN_ERR "dv1394: failed to register protocol\n");
+ hpsb_unregister_highlevel(&dv1394_highlevel);
++ devfs_remove("ieee1394/dv");
+ cdev_del(&dv1394_cdev);
+ return ret;
+ }
+diff -ur linux-2.6.17/drivers/ieee1394/ieee1394_core.c linux-2.6.17-devfs/drivers/ieee1394/ieee1394_core.c
+--- linux-2.6.17/drivers/ieee1394/ieee1394_core.c 2006-06-17 18:49:35.000000000 -0700
++++ linux-2.6.17-devfs/drivers/ieee1394/ieee1394_core.c 2006-08-25 11:06:18.000000000 -0700
+@@ -1078,10 +1078,17 @@
+ goto exit_release_kernel_thread;
+ }
+
++ /* actually this is a non-fatal error */
++ ret = devfs_mk_dir("ieee1394");
++ if (ret < 0) {
++ HPSB_ERR("unable to make devfs dir for device major %d!\n", IEEE1394_MAJOR);
++ goto release_chrdev;
++ }
++
+ ret = bus_register(&ieee1394_bus_type);
+ if (ret < 0) {
+ HPSB_INFO("bus register failed");
+- goto release_chrdev;
++ goto release_devfs;
+ }
+
+ for (i = 0; fw_bus_attrs[i]; i++) {
+@@ -1092,7 +1099,7 @@
+ fw_bus_attrs[i--]);
+ }
+ bus_unregister(&ieee1394_bus_type);
+- goto release_chrdev;
++ goto release_devfs;
+ }
+ }
+
+@@ -1145,6 +1152,8 @@
+ for (i = 0; fw_bus_attrs[i]; i++)
+ bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
+ bus_unregister(&ieee1394_bus_type);
++release_devfs:
++ devfs_remove("ieee1394");
+ release_chrdev:
+ unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
+ exit_release_kernel_thread:
+@@ -1182,6 +1191,7 @@
+ hpsb_cleanup_config_roms();
+
+ unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
++ devfs_remove("ieee1394");
+ }
+
+ module_init(ieee1394_init);
+diff -ur linux-2.6.17/drivers/ieee1394/ieee1394_core.h linux-2.6.17-devfs/drivers/ieee1394/ieee1394_core.h
+--- linux-2.6.17/drivers/ieee1394/ieee1394_core.h 2006-06-17 18:49:35.000000000 -0700
++++ linux-2.6.17-devfs/drivers/ieee1394/ieee1394_core.h 2006-08-25 11:06:18.000000000 -0700
+@@ -3,6 +3,7 @@
+ #define _IEEE1394_CORE_H
+
+ #include <linux/slab.h>
++#include <linux/devfs_fs_kernel.h>
+ #include <asm/atomic.h>
+ #include <asm/semaphore.h>
+ #include "hosts.h"
+diff -ur linux-2.6.17/drivers/ieee1394/raw1394.c linux-2.6.17-devfs/drivers/ieee1394/raw1394.c
+--- linux-2.6.17/drivers/ieee1394/raw1394.c 2006-06-17 18:49:35.000000000 -0700
++++ linux-2.6.17-devfs/drivers/ieee1394/raw1394.c 2006-08-25 11:06:18.000000000 -0700
+@@ -41,6 +41,7 @@
+ #include <linux/cdev.h>
+ #include <asm/uaccess.h>
+ #include <asm/atomic.h>
++#include <linux/devfs_fs_kernel.h>
+ #include <linux/compat.h>
+
+ #include "csr1212.h"
+@@ -2998,6 +2999,9 @@
+ goto out_unreg;
+ }
+
++ devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
++ S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME);
++
+ cdev_init(&raw1394_cdev, &raw1394_fops);
+ raw1394_cdev.owner = THIS_MODULE;
+ kobject_set_name(&raw1394_cdev.kobj, RAW1394_DEVICE_NAME);
+@@ -3019,6 +3023,7 @@
+ goto out;
+
+ out_dev:
++ devfs_remove(RAW1394_DEVICE_NAME);
+ class_device_destroy(hpsb_protocol_class,
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+@@ -3034,6 +3039,7 @@
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+ cdev_del(&raw1394_cdev);
++ devfs_remove(RAW1394_DEVICE_NAME);
+ hpsb_unregister_highlevel(&raw1394_highlevel);
+ hpsb_unregister_protocol(&raw1394_driver);
+ }
+diff -ur linux-2.6.17/drivers/ieee1394/video1394.c linux-2.6.17-devfs/drivers/ieee1394/video1394.c
+--- linux-2.6.17/drivers/ieee1394/video1394.c 2006-06-17 18:49:35.000000000 -0700
++++ linux-2.6.17-devfs/drivers/ieee1394/video1394.c 2006-08-25 11:06:18.000000000 -0700
+@@ -42,6 +42,7 @@
+ #include <linux/poll.h>
+ #include <linux/smp_lock.h>
+ #include <linux/delay.h>
++#include <linux/devfs_fs_kernel.h>
+ #include <linux/bitops.h>
+ #include <linux/types.h>
+ #include <linux/vmalloc.h>
+@@ -1321,6 +1322,9 @@
+ class_device_create(hpsb_protocol_class, NULL, MKDEV(
+ IEEE1394_MAJOR, minor),
+ NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
++ devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
++ S_IFCHR | S_IRUSR | S_IWUSR,
++ "%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
+ }
+
+
+@@ -1328,9 +1332,12 @@
+ {
+ struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
+
+- if (ohci)
++ if (ohci) {
+ class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
++ devfs_remove("%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
++ }
++
+ return;
+ }
+
+@@ -1471,8 +1478,12 @@
+ static void __exit video1394_exit_module (void)
+ {
+ hpsb_unregister_protocol(&video1394_driver);
++
+ hpsb_unregister_highlevel(&video1394_highlevel);
++
++ devfs_remove(VIDEO1394_DRIVER_NAME);
+ cdev_del(&video1394_cdev);
++
+ PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module");
+ }
+
+@@ -1489,12 +1500,15 @@
+ return ret;
+ }
+
++ devfs_mk_dir(VIDEO1394_DRIVER_NAME);
++
+ hpsb_register_highlevel(&video1394_highlevel);
+
+ ret = hpsb_register_protocol(&video1394_driver);
+ if (ret) {
+ PRINT_G(KERN_ERR, "video1394: failed to register protocol");
+ hpsb_unregister_highlevel(&video1394_highlevel);
++ devfs_remove(VIDEO1394_DRIVER_NAME);
+ cdev_del(&video1394_cdev);
+ return ret;
+ }
+diff -ur linux-2.6.17/drivers/scsi/osst.c linux-2.6.17-devfs/drivers/scsi/osst.c
+--- linux-2.6.17/drivers/scsi/osst.c 2006-06-17 18:49:35.000000000 -0700
++++ linux-2.6.17-devfs/drivers/scsi/osst.c 2006-08-25 11:06:18.000000000 -0700
+@@ -48,6 +48,7 @@
+ #include <linux/vmalloc.h>
+ #include <linux/blkdev.h>
+ #include <linux/moduleparam.h>
++#include <linux/devfs_fs_kernel.h>
+ #include <linux/delay.h>
+ #include <linux/jiffies.h>
+ #include <asm/uaccess.h>
+@@ -5721,7 +5722,7 @@
+ struct st_partstat * STps;
+ struct osst_buffer * buffer;
+ struct gendisk * drive;
+- int i, dev_num;
++ int i, mode, dev_num;
+
+ if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
+ return -ENODEV;
+@@ -5857,6 +5858,18 @@
+ snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
+ osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
+ }
++ for (mode = 0; mode < ST_NBR_MODES; ++mode) {
++ /* Rewind entry */
++ devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5)),
++ S_IFCHR | S_IRUGO | S_IWUGO,
++ "%s/ot%s", SDp->devfs_name, osst_formats[mode]);
++
++ /* No-rewind entry */
++ devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5) + 128),
++ S_IFCHR | S_IRUGO | S_IWUGO,
++ "%s/ot%sn", SDp->devfs_name, osst_formats[mode]);
++ }
++ drive->number = devfs_register_tape(SDp->devfs_name);
+
+ sdev_printk(KERN_INFO, SDp,
+ "osst :I: Attached OnStream %.5s tape as %s\n",
+@@ -5873,7 +5886,7 @@
+ {
+ struct scsi_device * SDp = to_scsi_device(dev);
+ struct osst_tape * tpnt;
+- int i;
++ int i, mode;
+
+ if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
+ return 0;
+@@ -5884,6 +5897,11 @@
+ osst_sysfs_destroy(MKDEV(OSST_MAJOR, i));
+ osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128));
+ tpnt->device = NULL;
++ for (mode = 0; mode < ST_NBR_MODES; ++mode) {
++ devfs_remove("%s/ot%s", SDp->devfs_name, osst_formats[mode]);
++ devfs_remove("%s/ot%sn", SDp->devfs_name, osst_formats[mode]);
++ }
++ devfs_unregister_tape(tpnt->drive->number);
+ put_disk(tpnt->drive);
+ os_scsi_tapes[i] = NULL;
+ osst_nr_dev--;
+diff -ur linux-2.6.17/drivers/scsi/scsi.c linux-2.6.17-devfs/drivers/scsi/scsi.c
+--- linux-2.6.17/drivers/scsi/scsi.c 2006-06-17 18:49:35.000000000 -0700
++++ linux-2.6.17-devfs/drivers/scsi/scsi.c 2006-08-25 11:07:42.000000000 -0700
+@@ -48,6 +48,7 @@
+ #include <linux/delay.h>
+ #include <linux/init.h>
+ #include <linux/completion.h>
++#include <linux/devfs_fs_kernel.h>
+ #include <linux/unistd.h>
+ #include <linux/spinlock.h>
+ #include <linux/kmod.h>
+@@ -1247,6 +1248,7 @@
+ for_each_possible_cpu(i)
+ INIT_LIST_HEAD(&per_cpu(scsi_done_q, i));
+
++ devfs_mk_dir("scsi");
+ printk(KERN_NOTICE "SCSI subsystem initialized\n");
+ return 0;
+
+@@ -1271,6 +1273,7 @@
+ scsi_exit_sysctl();
+ scsi_exit_hosts();
+ scsi_exit_devinfo();
++ devfs_remove("scsi");
+ scsi_exit_procfs();
+ scsi_exit_queue();
+ }
+diff -ur linux-2.6.17/drivers/scsi/scsi_scan.c linux-2.6.17-devfs/drivers/scsi/scsi_scan.c
+--- linux-2.6.17/drivers/scsi/scsi_scan.c 2006-06-17 18:49:35.000000000 -0700
++++ linux-2.6.17-devfs/drivers/scsi/scsi_scan.c 2006-08-25 11:06:18.000000000 -0700
+@@ -716,8 +716,12 @@
+ if (inq_result[7] & 0x10)
+ sdev->sdtr = 1;
+
++ sprintf(sdev->devfs_name, "scsi/host%d/bus%d/target%d/lun%d",
++ sdev->host->host_no, sdev->channel,
++ sdev->id, sdev->lun);
++
+ /*
+- * End sysfs code.
++ * End driverfs/devfs code.
+ */
+
+ if ((sdev->scsi_level >= SCSI_2) && (inq_result[7] & 2) &&
+diff -ur linux-2.6.17/drivers/scsi/sd.c linux-2.6.17-devfs/drivers/scsi/sd.c
+--- linux-2.6.17/drivers/scsi/sd.c 2006-06-17 18:49:35.000000000 -0700
++++ linux-2.6.17-devfs/drivers/scsi/sd.c 2006-08-25 11:06:18.000000000 -0700
+@@ -1683,6 +1683,8 @@
+ 'a' + m1, 'a' + m2, 'a' + m3);
+ }
+
++ strcpy(gd->devfs_name, sdp->devfs_name);
++
+ gd->private_data = &sdkp->driver;
+ gd->queue = sdkp->device->request_queue;
+
+diff -ur linux-2.6.17/drivers/scsi/sg.c linux-2.6.17-devfs/drivers/scsi/sg.c
+--- linux-2.6.17/drivers/scsi/sg.c 2006-06-17 18:49:35.000000000 -0700
++++ linux-2.6.17-devfs/drivers/scsi/sg.c 2006-08-25 11:06:18.000000000 -0700
+@@ -44,6 +44,7 @@
+ #include <linux/poll.h>
+ #include <linux/smp_lock.h>
+ #include <linux/moduleparam.h>
++#include <linux/devfs_fs_kernel.h>
+ #include <linux/cdev.h>
+ #include <linux/seq_file.h>
+ #include <linux/blkdev.h>
+@@ -1427,10 +1428,14 @@
+ k = error;
+ sdp = sg_dev_arr[k];
+
++ devfs_mk_cdev(MKDEV(SCSI_GENERIC_MAJOR, k),
++ S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
++ "%s/generic", scsidp->devfs_name);
+ error = cdev_add(cdev, MKDEV(SCSI_GENERIC_MAJOR, k), 1);
+- if (error)
++ if (error) {
++ devfs_remove("%s/generic", scsidp->devfs_name);
+ goto out;
+-
++ }
+ sdp->cdev = cdev;
+ if (sg_sysfs_valid) {
+ struct class_device * sg_class_member;
+@@ -1520,6 +1525,7 @@
+ class_device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, k));
+ cdev_del(sdp->cdev);
+ sdp->cdev = NULL;
++ devfs_remove("%s/generic", scsidp->devfs_name);
+ put_disk(sdp->disk);
+ sdp->disk = NULL;
+ if (NULL == sdp->headfp)
+diff -ur linux-2.6.17/drivers/scsi/sr.c linux-2.6.17-devfs/drivers/scsi/sr.c
+--- linux-2.6.17/drivers/scsi/sr.c 2006-06-17 18:49:35.000000000 -0700
++++ linux-2.6.17-devfs/drivers/scsi/sr.c 2006-08-25 11:06:18.000000000 -0700
+@@ -592,6 +592,8 @@
+ get_capabilities(cd);
+ sr_vendor_init(cd);
+
++ snprintf(disk->devfs_name, sizeof(disk->devfs_name),
++ "%s/cd", sdev->devfs_name);
+ disk->driverfs_dev = &sdev->sdev_gendev;
+ set_capacity(disk, cd->capacity);
+ disk->private_data = &cd->driver;
+diff -ur linux-2.6.17/drivers/scsi/st.c linux-2.6.17-devfs/drivers/scsi/st.c
+--- linux-2.6.17/drivers/scsi/st.c 2006-06-17 18:49:35.000000000 -0700
++++ linux-2.6.17-devfs/drivers/scsi/st.c 2006-08-25 11:06:18.000000000 -0700
+@@ -35,6 +35,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/blkdev.h>
+ #include <linux/moduleparam.h>
++#include <linux/devfs_fs_kernel.h>
+ #include <linux/cdev.h>
+ #include <linux/delay.h>
+ #include <linux/mutex.h>
+@@ -4053,8 +4054,23 @@
+ do_create_class_files(tpnt, dev_num, mode);
+ }
+
++ for (mode = 0; mode < ST_NBR_MODES; ++mode) {
++ /* Make sure that the minor numbers corresponding to the four
++ first modes always get the same names */
++ i = mode << (4 - ST_NBR_MODE_BITS);
++ /* Rewind entry */
++ devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, 0)),
++ S_IFCHR | S_IRUGO | S_IWUGO,
++ "%s/mt%s", SDp->devfs_name, st_formats[i]);
++ /* No-rewind entry */
++ devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, 1)),
++ S_IFCHR | S_IRUGO | S_IWUGO,
++ "%s/mt%sn", SDp->devfs_name, st_formats[i]);
++ }
++ disk->number = devfs_register_tape(SDp->devfs_name);
++
+ sdev_printk(KERN_WARNING, SDp,
+ "Attached scsi tape %s\n", tape_name(tpnt));
+ printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B)\n",
+ tape_name(tpnt), tpnt->try_dio ? "yes" : "no",
+ queue_dma_alignment(SDp->request_queue) + 1);
+@@ -4106,9 +4122,13 @@
+ scsi_tapes[i] = NULL;
+ st_nr_dev--;
+ write_unlock(&st_dev_arr_lock);
++ devfs_unregister_tape(tpnt->disk->number);
+ sysfs_remove_link(&tpnt->device->sdev_gendev.kobj,
+ "tape");
+ for (mode = 0; mode < ST_NBR_MODES; ++mode) {
++ j = mode << (4 - ST_NBR_MODE_BITS);
++ devfs_remove("%s/mt%s", SDp->devfs_name, st_formats[j]);
++ devfs_remove("%s/mt%sn", SDp->devfs_name, st_formats[j]);
+ for (j=0; j < 2; j++) {
+ class_device_destroy(st_sysfs_class,
+ MKDEV(SCSI_TAPE_MAJOR,
+diff -ur linux-2.6.17/include/scsi/scsi_device.h linux-2.6.17-devfs/include/scsi/scsi_device.h
+--- linux-2.6.17/include/scsi/scsi_device.h 2006-06-17 18:49:35.000000000 -0700
++++ linux-2.6.17-devfs/include/scsi/scsi_device.h 2006-08-25 11:06:18.000000000 -0700
+@@ -74,6 +74,7 @@
+ unsigned sector_size; /* size in bytes */
+
+ void *hostdata; /* available to low-level driver */
++ char devfs_name[256]; /* devfs junk */
+ char type;
+ char scsi_level;
+ char inq_periph_qual; /* PQ from INQUIRY data */
diff --git a/target/linux/generic-2.6/patches/001-squashfs.patch b/target/linux/generic-2.6/patches/001-squashfs.patch
new file mode 100644
index 0000000000..f88dbbae8e
--- /dev/null
+++ b/target/linux/generic-2.6/patches/001-squashfs.patch
@@ -0,0 +1,4173 @@
+diff --new-file -urp linux-2.6.15/fs/Kconfig linux-2.6.15-squashfs3.0/fs/Kconfig
+--- linux-2.6.15/fs/Kconfig 2006-03-01 22:37:27.000000000 +0000
++++ linux-2.6.15-squashfs3.0/fs/Kconfig 2006-03-07 21:12:37.000000000 +0000
+@@ -1151,6 +1151,71 @@ config CRAMFS
+
+ If unsure, say N.
+
++config SQUASHFS
++ tristate "SquashFS 3.0 - Squashed file system support"
++ select ZLIB_INFLATE
++ help
++ Saying Y here includes support for SquashFS 3.0 (a Compressed Read-Only File
++ System). Squashfs is a highly compressed read-only filesystem for Linux.
++ It uses zlib compression to compress both files, inodes and directories.
++ Inodes in the system are very small and all blocks are packed to minimise
++ data overhead. Block sizes greater than 4K are supported up to a maximum of 64K.
++ SquashFS 3.0 supports 64 bit filesystems and files (larger than 4GB), full
++ uid/gid information, hard links and timestamps.
++
++ Squashfs is intended for general read-only filesystem use, for archival
++ use (i.e. in cases where a .tar.gz file may be used), and in embedded
++ systems where low overhead is needed. Further information and filesystem tools
++ are available from http://squashfs.sourceforge.net.
++
++ If you want to compile this as a module ( = code which can be
++ inserted in and removed from the running kernel whenever you want),
++ say M here and read <file:Documentation/modules.txt>. The module
++ will be called squashfs. Note that the root file system (the one
++ containing the directory /) cannot be compiled as a module.
++
++ If unsure, say N.
++
++config SQUASHFS_EMBEDDED
++
++ bool "Additional options for memory-constrained systems"
++ depends on SQUASHFS
++ default n
++ help
++ Saying Y here allows you to specify cache sizes and how Squashfs
++ allocates memory. This is only intended for memory constrained
++ systems.
++
++ If unsure, say N.
++
++config SQUASHFS_FRAGMENT_CACHE_SIZE
++ int "Number of fragments cached" if SQUASHFS_EMBEDDED
++ depends on SQUASHFS
++ default "3"
++ help
++ By default SquashFS caches the last 3 fragments read from
++ the filesystem. Increasing this amount may mean SquashFS
++ has to re-read fragments less often from disk, at the expense
++ of extra system memory. Decreasing this amount will mean
++ SquashFS uses less memory at the expense of extra reads from disk.
++
++ Note there must be at least one cached fragment. Anything
++ much more than three will probably not make much difference.
++
++config SQUASHFS_VMALLOC
++ bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED
++ depends on SQUASHFS
++ default n
++ help
++ By default SquashFS uses kmalloc to obtain fragment cache memory.
++ Kmalloc memory is the standard kernel allocator, but it can fail
++ on memory constrained systems. Because of the way Vmalloc works,
++ Vmalloc can succeed when kmalloc fails. Specifying this option
++ will make SquashFS always use Vmalloc to allocate the
++ fragment cache memory.
++
++ If unsure, say N.
++
+ config VXFS_FS
+ tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
+ help
+diff --new-file -urp linux-2.6.15/fs/Makefile linux-2.6.15-squashfs3.0/fs/Makefile
+--- linux-2.6.15/fs/Makefile 2006-03-01 22:37:27.000000000 +0000
++++ linux-2.6.15-squashfs3.0/fs/Makefile 2006-03-07 21:12:37.000000000 +0000
+@@ -55,6 +55,7 @@ obj-$(CONFIG_EXT3_FS) += ext3/ # Before
+ obj-$(CONFIG_JBD) += jbd/
+ obj-$(CONFIG_EXT2_FS) += ext2/
+ obj-$(CONFIG_CRAMFS) += cramfs/
++obj-$(CONFIG_SQUASHFS) += squashfs/
+ obj-$(CONFIG_RAMFS) += ramfs/
+ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
+ obj-$(CONFIG_CODA_FS) += coda/
+diff --new-file -urp linux-2.6.15/fs/squashfs/inode.c linux-2.6.15-squashfs3.0/fs/squashfs/inode.c
+--- linux-2.6.15/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-squashfs3.0/fs/squashfs/inode.c 2006-03-07 21:12:37.000000000 +0000
+@@ -0,0 +1,2127 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * inode.c
++ */
++
++#include <linux/types.h>
++#include <linux/squashfs_fs.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/fs.h>
++#include <linux/smp_lock.h>
++#include <linux/slab.h>
++#include <linux/squashfs_fs_sb.h>
++#include <linux/squashfs_fs_i.h>
++#include <linux/buffer_head.h>
++#include <linux/vfs.h>
++#include <linux/init.h>
++#include <linux/dcache.h>
++#include <linux/wait.h>
++#include <linux/zlib.h>
++#include <linux/blkdev.h>
++#include <linux/vmalloc.h>
++#include <asm/uaccess.h>
++#include <asm/semaphore.h>
++
++#include "squashfs.h"
++
++static void squashfs_put_super(struct super_block *);
++static int squashfs_statfs(struct super_block *, struct kstatfs *);
++static int squashfs_symlink_readpage(struct file *file, struct page *page);
++static int squashfs_readpage(struct file *file, struct page *page);
++static int squashfs_readpage4K(struct file *file, struct page *page);
++static int squashfs_readdir(struct file *, void *, filldir_t);
++static struct inode *squashfs_alloc_inode(struct super_block *sb);
++static void squashfs_destroy_inode(struct inode *inode);
++static int init_inodecache(void);
++static void destroy_inodecache(void);
++static struct dentry *squashfs_lookup(struct inode *, struct dentry *,
++ struct nameidata *);
++static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode);
++static long long read_blocklist(struct inode *inode, int index,
++ int readahead_blks, char *block_list,
++ unsigned short **block_p, unsigned int *bsize);
++static struct super_block *squashfs_get_sb(struct file_system_type *, int,
++ const char *, void *);
++
++
++static z_stream stream;
++
++static struct file_system_type squashfs_fs_type = {
++ .owner = THIS_MODULE,
++ .name = "squashfs",
++ .get_sb = squashfs_get_sb,
++ .kill_sb = kill_block_super,
++ .fs_flags = FS_REQUIRES_DEV
++};
++
++static unsigned char squashfs_filetype_table[] = {
++ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
++};
++
++static struct super_operations squashfs_ops = {
++ .alloc_inode = squashfs_alloc_inode,
++ .destroy_inode = squashfs_destroy_inode,
++ .statfs = squashfs_statfs,
++ .put_super = squashfs_put_super,
++};
++
++SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = {
++ .readpage = squashfs_symlink_readpage
++};
++
++SQSH_EXTERN struct address_space_operations squashfs_aops = {
++ .readpage = squashfs_readpage
++};
++
++SQSH_EXTERN struct address_space_operations squashfs_aops_4K = {
++ .readpage = squashfs_readpage4K
++};
++
++static struct file_operations squashfs_dir_ops = {
++ .read = generic_read_dir,
++ .readdir = squashfs_readdir
++};
++
++SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = {
++ .lookup = squashfs_lookup
++};
++
++
++static struct buffer_head *get_block_length(struct super_block *s,
++ int *cur_index, int *offset, int *c_byte)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ unsigned short temp;
++ struct buffer_head *bh;
++
++ if (!(bh = sb_bread(s, *cur_index)))
++ goto out;
++
++ if (msblk->devblksize - *offset == 1) {
++ if (msblk->swap)
++ ((unsigned char *) &temp)[1] = *((unsigned char *)
++ (bh->b_data + *offset));
++ else
++ ((unsigned char *) &temp)[0] = *((unsigned char *)
++ (bh->b_data + *offset));
++ brelse(bh);
++ if (!(bh = sb_bread(s, ++(*cur_index))))
++ goto out;
++ if (msblk->swap)
++ ((unsigned char *) &temp)[0] = *((unsigned char *)
++ bh->b_data);
++ else
++ ((unsigned char *) &temp)[1] = *((unsigned char *)
++ bh->b_data);
++ *c_byte = temp;
++ *offset = 1;
++ } else {
++ if (msblk->swap) {
++ ((unsigned char *) &temp)[1] = *((unsigned char *)
++ (bh->b_data + *offset));
++ ((unsigned char *) &temp)[0] = *((unsigned char *)
++ (bh->b_data + *offset + 1));
++ } else {
++ ((unsigned char *) &temp)[0] = *((unsigned char *)
++ (bh->b_data + *offset));
++ ((unsigned char *) &temp)[1] = *((unsigned char *)
++ (bh->b_data + *offset + 1));
++ }
++ *c_byte = temp;
++ *offset += 2;
++ }
++
++ if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {
++ if (*offset == msblk->devblksize) {
++ brelse(bh);
++ if (!(bh = sb_bread(s, ++(*cur_index))))
++ goto out;
++ *offset = 0;
++ }
++ if (*((unsigned char *) (bh->b_data + *offset)) !=
++ SQUASHFS_MARKER_BYTE) {
++ ERROR("Metadata block marker corrupt @ %x\n",
++ *cur_index);
++ brelse(bh);
++ goto out;
++ }
++ (*offset)++;
++ }
++ return bh;
++
++out:
++ return NULL;
++}
++
++
++SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,
++ long long index, unsigned int length,
++ long long *next_index)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>
++ msblk->devblksize_log2) + 2];
++ unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
++ unsigned int cur_index = index >> msblk->devblksize_log2;
++ int bytes, avail_bytes, b = 0, k;
++ char *c_buffer;
++ unsigned int compressed;
++ unsigned int c_byte = length;
++
++ if (c_byte) {
++ bytes = msblk->devblksize - offset;
++ compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);
++ c_buffer = compressed ? msblk->read_data : buffer;
++ c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
++
++ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
++ ? "" : "un", (unsigned int) c_byte);
++
++ if (!(bh[0] = sb_getblk(s, cur_index)))
++ goto block_release;
++
++ for (b = 1; bytes < c_byte; b++) {
++ if (!(bh[b] = sb_getblk(s, ++cur_index)))
++ goto block_release;
++ bytes += msblk->devblksize;
++ }
++ ll_rw_block(READ, b, bh);
++ } else {
++ if (!(bh[0] = get_block_length(s, &cur_index, &offset,
++ &c_byte)))
++ goto read_failure;
++
++ bytes = msblk->devblksize - offset;
++ compressed = SQUASHFS_COMPRESSED(c_byte);
++ c_buffer = compressed ? msblk->read_data : buffer;
++ c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
++
++ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
++ ? "" : "un", (unsigned int) c_byte);
++
++ for (b = 1; bytes < c_byte; b++) {
++ if (!(bh[b] = sb_getblk(s, ++cur_index)))
++ goto block_release;
++ bytes += msblk->devblksize;
++ }
++ ll_rw_block(READ, b - 1, bh + 1);
++ }
++
++ if (compressed)
++ down(&msblk->read_data_mutex);
++
++ for (bytes = 0, k = 0; k < b; k++) {
++ avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
++ msblk->devblksize - offset :
++ c_byte - bytes;
++ wait_on_buffer(bh[k]);
++ if (!buffer_uptodate(bh[k]))
++ goto block_release;
++ memcpy(c_buffer + bytes, bh[k]->b_data + offset, avail_bytes);
++ bytes += avail_bytes;
++ offset = 0;
++ brelse(bh[k]);
++ }
++
++ /*
++ * uncompress block
++ */
++ if (compressed) {
++ int zlib_err;
++
++ stream.next_in = c_buffer;
++ stream.avail_in = c_byte;
++ stream.next_out = buffer;
++ stream.avail_out = msblk->read_size;
++
++ if (((zlib_err = zlib_inflateInit(&stream)) != Z_OK) ||
++ ((zlib_err = zlib_inflate(&stream, Z_FINISH))
++ != Z_STREAM_END) || ((zlib_err =
++ zlib_inflateEnd(&stream)) != Z_OK)) {
++ ERROR("zlib_fs returned unexpected result 0x%x\n",
++ zlib_err);
++ bytes = 0;
++ } else
++ bytes = stream.total_out;
++
++ up(&msblk->read_data_mutex);
++ }
++
++ if (next_index)
++ *next_index = index + c_byte + (length ? 0 :
++ (SQUASHFS_CHECK_DATA(msblk->sblk.flags)
++ ? 3 : 2));
++ return bytes;
++
++block_release:
++ while (--b >= 0)
++ brelse(bh[b]);
++
++read_failure:
++ ERROR("sb_bread failed reading block 0x%x\n", cur_index);
++ return 0;
++}
++
++
++SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer,
++ long long block, unsigned int offset,
++ int length, long long *next_block,
++ unsigned int *next_offset)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ int n, i, bytes, return_length = length;
++ long long next_index;
++
++ TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);
++
++ while ( 1 ) {
++ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
++ if (msblk->block_cache[i].block == block)
++ break;
++
++ down(&msblk->block_cache_mutex);
++
++ if (i == SQUASHFS_CACHED_BLKS) {
++ /* read inode header block */
++ for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;
++ n ; n --, i = (i + 1) %
++ SQUASHFS_CACHED_BLKS)
++ if (msblk->block_cache[i].block !=
++ SQUASHFS_USED_BLK)
++ break;
++
++ if (n == 0) {
++ wait_queue_t wait;
++
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&msblk->waitq, &wait);
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ up(&msblk->block_cache_mutex);
++ schedule();
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&msblk->waitq, &wait);
++ continue;
++ }
++ msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
++
++ if (msblk->block_cache[i].block ==
++ SQUASHFS_INVALID_BLK) {
++ if (!(msblk->block_cache[i].data =
++ kmalloc(SQUASHFS_METADATA_SIZE,
++ GFP_KERNEL))) {
++ ERROR("Failed to allocate cache"
++ "block\n");
++ up(&msblk->block_cache_mutex);
++ goto out;
++ }
++ }
++
++ msblk->block_cache[i].block = SQUASHFS_USED_BLK;
++ up(&msblk->block_cache_mutex);
++
++ if (!(msblk->block_cache[i].length =
++ squashfs_read_data(s,
++ msblk->block_cache[i].data,
++ block, 0, &next_index))) {
++ ERROR("Unable to read cache block [%llx:%x]\n",
++ block, offset);
++ goto out;
++ }
++
++ down(&msblk->block_cache_mutex);
++ wake_up(&msblk->waitq);
++ msblk->block_cache[i].block = block;
++ msblk->block_cache[i].next_index = next_index;
++ TRACE("Read cache block [%llx:%x]\n", block, offset);
++ }
++
++ if (msblk->block_cache[i].block != block) {
++ up(&msblk->block_cache_mutex);
++ continue;
++ }
++
++ if ((bytes = msblk->block_cache[i].length - offset) >= length) {
++ if (buffer)
++ memcpy(buffer, msblk->block_cache[i].data +
++ offset, length);
++ if (msblk->block_cache[i].length - offset == length) {
++ *next_block = msblk->block_cache[i].next_index;
++ *next_offset = 0;
++ } else {
++ *next_block = block;
++ *next_offset = offset + length;
++ }
++ up(&msblk->block_cache_mutex);
++ goto finish;
++ } else {
++ if (buffer) {
++ memcpy(buffer, msblk->block_cache[i].data +
++ offset, bytes);
++ buffer += bytes;
++ }
++ block = msblk->block_cache[i].next_index;
++ up(&msblk->block_cache_mutex);
++ length -= bytes;
++ offset = 0;
++ }
++ }
++
++finish:
++ return return_length;
++out:
++ return 0;
++}
++
++
++static int get_fragment_location(struct super_block *s, unsigned int fragment,
++ long long *fragment_start_block,
++ unsigned int *fragment_size)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ long long start_block =
++ msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];
++ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
++ struct squashfs_fragment_entry fragment_entry;
++
++ if (msblk->swap) {
++ struct squashfs_fragment_entry sfragment_entry;
++
++ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
++ start_block, offset,
++ sizeof(sfragment_entry), &start_block,
++ &offset))
++ goto out;
++ SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);
++ } else
++ if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
++ start_block, offset,
++ sizeof(fragment_entry), &start_block,
++ &offset))
++ goto out;
++
++ *fragment_start_block = fragment_entry.start_block;
++ *fragment_size = fragment_entry.size;
++
++ return 1;
++
++out:
++ return 0;
++}
++
++
++SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct
++ squashfs_fragment_cache *fragment)
++{
++ down(&msblk->fragment_mutex);
++ fragment->locked --;
++ wake_up(&msblk->fragment_wait_queue);
++ up(&msblk->fragment_mutex);
++}
++
++
++SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block
++ *s, long long start_block,
++ int length)
++{
++ int i, n;
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++
++ while ( 1 ) {
++ down(&msblk->fragment_mutex);
++
++ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&
++ msblk->fragment[i].block != start_block; i++);
++
++ if (i == SQUASHFS_CACHED_FRAGMENTS) {
++ for (i = msblk->next_fragment, n =
++ SQUASHFS_CACHED_FRAGMENTS; n &&
++ msblk->fragment[i].locked; n--, i = (i + 1) %
++ SQUASHFS_CACHED_FRAGMENTS);
++
++ if (n == 0) {
++ wait_queue_t wait;
++
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&msblk->fragment_wait_queue,
++ &wait);
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ up(&msblk->fragment_mutex);
++ schedule();
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&msblk->fragment_wait_queue,
++ &wait);
++ continue;
++ }
++ msblk->next_fragment = (msblk->next_fragment + 1) %
++ SQUASHFS_CACHED_FRAGMENTS;
++
++ if (msblk->fragment[i].data == NULL)
++ if (!(msblk->fragment[i].data = SQUASHFS_ALLOC
++ (SQUASHFS_FILE_MAX_SIZE))) {
++ ERROR("Failed to allocate fragment "
++ "cache block\n");
++ up(&msblk->fragment_mutex);
++ goto out;
++ }
++
++ msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
++ msblk->fragment[i].locked = 1;
++ up(&msblk->fragment_mutex);
++
++ if (!(msblk->fragment[i].length = squashfs_read_data(s,
++ msblk->fragment[i].data,
++ start_block, length, NULL))) {
++ ERROR("Unable to read fragment cache block "
++ "[%llx]\n", start_block);
++ msblk->fragment[i].locked = 0;
++ goto out;
++ }
++
++ msblk->fragment[i].block = start_block;
++ TRACE("New fragment %d, start block %lld, locked %d\n",
++ i, msblk->fragment[i].block,
++ msblk->fragment[i].locked);
++ break;
++ }
++
++ msblk->fragment[i].locked++;
++ up(&msblk->fragment_mutex);
++ TRACE("Got fragment %d, start block %lld, locked %d\n", i,
++ msblk->fragment[i].block,
++ msblk->fragment[i].locked);
++ break;
++ }
++
++ return &msblk->fragment[i];
++
++out:
++ return NULL;
++}
++
++
++static struct inode *squashfs_new_inode(struct super_block *s,
++ struct squashfs_base_inode_header *inodeb)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct inode *i = new_inode(s);
++
++ if (i) {
++ i->i_ino = inodeb->inode_number;
++ i->i_mtime.tv_sec = inodeb->mtime;
++ i->i_atime.tv_sec = inodeb->mtime;
++ i->i_ctime.tv_sec = inodeb->mtime;
++ i->i_uid = msblk->uid[inodeb->uid];
++ i->i_mode = inodeb->mode;
++ i->i_size = 0;
++ if (inodeb->guid == SQUASHFS_GUIDS)
++ i->i_gid = i->i_uid;
++ else
++ i->i_gid = msblk->guid[inodeb->guid];
++ }
++
++ return i;
++}
++
++
++static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode)
++{
++ struct inode *i;
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long block = SQUASHFS_INODE_BLK(inode) +
++ sblk->inode_table_start;
++ unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
++ long long next_block;
++ unsigned int next_offset;
++ union squashfs_inode_header id, sid;
++ struct squashfs_base_inode_header *inodeb = &id.base,
++ *sinodeb = &sid.base;
++
++ TRACE("Entered squashfs_iget\n");
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
++ offset, sizeof(*sinodeb), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,
++ sizeof(*sinodeb));
++ } else
++ if (!squashfs_get_cached_block(s, (char *) inodeb, block,
++ offset, sizeof(*inodeb), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ switch(inodeb->inode_type) {
++ case SQUASHFS_FILE_TYPE: {
++ unsigned int frag_size;
++ long long frag_blk;
++ struct squashfs_reg_inode_header *inodep = &id.reg;
++ struct squashfs_reg_inode_header *sinodep = &sid.reg;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ frag_blk = SQUASHFS_INVALID_BLK;
++ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
++ !get_fragment_location(s,
++ inodep->fragment, &frag_blk, &frag_size))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb)) == NULL)
++ goto failed_read1;
++
++ i->i_nlink = 1;
++ i->i_size = inodep->file_size;
++ i->i_fop = &generic_ro_fops;
++ i->i_mode |= S_IFREG;
++ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
++ i->i_blksize = PAGE_CACHE_SIZE;
++ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
++ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
++ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++ if (sblk->block_size > 4096)
++ i->i_data.a_ops = &squashfs_aops;
++ else
++ i->i_data.a_ops = &squashfs_aops_4K;
++
++ TRACE("File inode %x:%x, start_block %llx, "
++ "block_list_start %llx, offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, next_block,
++ next_offset);
++ break;
++ }
++ case SQUASHFS_LREG_TYPE: {
++ unsigned int frag_size;
++ long long frag_blk;
++ struct squashfs_lreg_inode_header *inodep = &id.lreg;
++ struct squashfs_lreg_inode_header *sinodep = &sid.lreg;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ frag_blk = SQUASHFS_INVALID_BLK;
++ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
++ !get_fragment_location(s,
++ inodep->fragment, &frag_blk, &frag_size))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb)) == NULL)
++ goto failed_read1;
++
++ i->i_nlink = inodep->nlink;
++ i->i_size = inodep->file_size;
++ i->i_fop = &generic_ro_fops;
++ i->i_mode |= S_IFREG;
++ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
++ i->i_blksize = PAGE_CACHE_SIZE;
++ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
++ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
++ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++ if (sblk->block_size > 4096)
++ i->i_data.a_ops = &squashfs_aops;
++ else
++ i->i_data.a_ops = &squashfs_aops_4K;
++
++ TRACE("File inode %x:%x, start_block %llx, "
++ "block_list_start %llx, offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, next_block,
++ next_offset);
++ break;
++ }
++ case SQUASHFS_DIR_TYPE: {
++ struct squashfs_dir_inode_header *inodep = &id.dir;
++ struct squashfs_dir_inode_header *sinodep = &sid.dir;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb)) == NULL)
++ goto failed_read1;
++
++ i->i_nlink = inodep->nlink;
++ i->i_size = inodep->file_size;
++ i->i_op = &squashfs_dir_inode_ops;
++ i->i_fop = &squashfs_dir_ops;
++ i->i_mode |= S_IFDIR;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->offset = inodep->offset;
++ SQUASHFS_I(i)->u.s2.directory_index_count = 0;
++ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
++
++ TRACE("Directory inode %x:%x, start_block %x, offset "
++ "%x\n", SQUASHFS_INODE_BLK(inode),
++ offset, inodep->start_block,
++ inodep->offset);
++ break;
++ }
++ case SQUASHFS_LDIR_TYPE: {
++ struct squashfs_ldir_inode_header *inodep = &id.ldir;
++ struct squashfs_ldir_inode_header *sinodep = &sid.ldir;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,
++ sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb)) == NULL)
++ goto failed_read1;
++
++ i->i_nlink = inodep->nlink;
++ i->i_size = inodep->file_size;
++ i->i_op = &squashfs_dir_inode_ops;
++ i->i_fop = &squashfs_dir_ops;
++ i->i_mode |= S_IFDIR;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->offset = inodep->offset;
++ SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
++ SQUASHFS_I(i)->u.s2.directory_index_offset =
++ next_offset;
++ SQUASHFS_I(i)->u.s2.directory_index_count =
++ inodep->i_count;
++ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
++
++ TRACE("Long directory inode %x:%x, start_block %x, "
++ "offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, inodep->offset);
++ break;
++ }
++ case SQUASHFS_SYMLINK_TYPE: {
++ struct squashfs_symlink_inode_header *inodep =
++ &id.symlink;
++ struct squashfs_symlink_inode_header *sinodep =
++ &sid.symlink;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,
++ sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb)) == NULL)
++ goto failed_read1;
++
++ i->i_nlink = inodep->nlink;
++ i->i_size = inodep->symlink_size;
++ i->i_op = &page_symlink_inode_operations;
++ i->i_data.a_ops = &squashfs_symlink_aops;
++ i->i_mode |= S_IFLNK;
++ SQUASHFS_I(i)->start_block = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++
++ TRACE("Symbolic link inode %x:%x, start_block %llx, "
++ "offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ next_block, next_offset);
++ break;
++ }
++ case SQUASHFS_BLKDEV_TYPE:
++ case SQUASHFS_CHRDEV_TYPE: {
++ struct squashfs_dev_inode_header *inodep = &id.dev;
++ struct squashfs_dev_inode_header *sinodep = &sid.dev;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if ((i = squashfs_new_inode(s, inodeb)) == NULL)
++ goto failed_read1;
++
++ i->i_nlink = inodep->nlink;
++ i->i_mode |= (inodeb->inode_type ==
++ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
++ S_IFBLK;
++ init_special_inode(i, i->i_mode,
++ old_decode_dev(inodep->rdev));
++
++ TRACE("Device inode %x:%x, rdev %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->rdev);
++ break;
++ }
++ case SQUASHFS_FIFO_TYPE:
++ case SQUASHFS_SOCKET_TYPE: {
++ struct squashfs_ipc_inode_header *inodep = &id.ipc;
++ struct squashfs_ipc_inode_header *sinodep = &sid.ipc;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if ((i = squashfs_new_inode(s, inodeb)) == NULL)
++ goto failed_read1;
++
++ i->i_nlink = inodep->nlink;
++ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
++ ? S_IFIFO : S_IFSOCK;
++ init_special_inode(i, i->i_mode, 0);
++ break;
++ }
++ default:
++ ERROR("Unknown inode type %d in squashfs_iget!\n",
++ inodeb->inode_type);
++ goto failed_read1;
++ }
++
++ insert_inode_hash(i);
++ return i;
++
++failed_read:
++ ERROR("Unable to read inode [%llx:%x]\n", block, offset);
++
++failed_read1:
++ return NULL;
++}
++
++
++static int read_fragment_index_table(struct super_block *s)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ /* Allocate fragment index table */
++ if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES
++ (sblk->fragments), GFP_KERNEL))) {
++ ERROR("Failed to allocate uid/gid table\n");
++ return 0;
++ }
++
++ if (SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments) &&
++ !squashfs_read_data(s, (char *)
++ msblk->fragment_index,
++ sblk->fragment_table_start,
++ SQUASHFS_FRAGMENT_INDEX_BYTES
++ (sblk->fragments) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++ ERROR("unable to read fragment index table\n");
++ return 0;
++ }
++
++ if (msblk->swap) {
++ int i;
++ long long fragment;
++
++ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments);
++ i++) {
++ SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),
++ &msblk->fragment_index[i], 1);
++ msblk->fragment_index[i] = fragment;
++ }
++ }
++
++ return 1;
++}
++
++
++static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)
++{
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ msblk->iget = squashfs_iget;
++ msblk->read_blocklist = read_blocklist;
++ msblk->read_fragment_index_table = read_fragment_index_table;
++
++ if (sblk->s_major == 1) {
++ if (!squashfs_1_0_supported(msblk)) {
++ SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "
++ "are unsupported\n");
++ SERROR("Please recompile with "
++ "Squashfs 1.0 support enabled\n");
++ return 0;
++ }
++ } else if (sblk->s_major == 2) {
++ if (!squashfs_2_0_supported(msblk)) {
++ SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "
++ "are unsupported\n");
++ SERROR("Please recompile with "
++ "Squashfs 2.0 support enabled\n");
++ return 0;
++ }
++ } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >
++ SQUASHFS_MINOR) {
++ SERROR("Major/Minor mismatch, trying to mount newer %d.%d "
++ "filesystem\n", sblk->s_major, sblk->s_minor);
++ SERROR("Please update your kernel\n");
++ return 0;
++ }
++
++ return 1;
++}
++
++
++static int squashfs_fill_super(struct super_block *s, void *data, int silent)
++{
++ struct squashfs_sb_info *msblk;
++ struct squashfs_super_block *sblk;
++ int i;
++ char b[BDEVNAME_SIZE];
++ struct inode *root;
++
++ TRACE("Entered squashfs_read_superblock\n");
++
++ if (!(s->s_fs_info = kmalloc(sizeof(struct squashfs_sb_info),
++ GFP_KERNEL))) {
++ ERROR("Failed to allocate superblock\n");
++ goto failure;
++ }
++ memset(s->s_fs_info, 0, sizeof(struct squashfs_sb_info));
++ msblk = s->s_fs_info;
++ sblk = &msblk->sblk;
++
++ msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE);
++ msblk->devblksize_log2 = ffz(~msblk->devblksize);
++
++ init_MUTEX(&msblk->read_data_mutex);
++ init_MUTEX(&msblk->read_page_mutex);
++ init_MUTEX(&msblk->block_cache_mutex);
++ init_MUTEX(&msblk->fragment_mutex);
++ init_MUTEX(&msblk->meta_index_mutex);
++
++ init_waitqueue_head(&msblk->waitq);
++ init_waitqueue_head(&msblk->fragment_wait_queue);
++
++ if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
++ sizeof(struct squashfs_super_block) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++ SERROR("unable to read superblock\n");
++ goto failed_mount;
++ }
++
++ /* Check it is a SQUASHFS superblock */
++ msblk->swap = 0;
++ if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) {
++ if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) {
++ struct squashfs_super_block ssblk;
++
++ WARNING("Mounting a different endian SQUASHFS "
++ "filesystem on %s\n", bdevname(s->s_bdev, b));
++
++ SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);
++ memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));
++ msblk->swap = 1;
++ } else {
++ SERROR("Can't find a SQUASHFS superblock on %s\n",
++ bdevname(s->s_bdev, b));
++ goto failed_mount;
++ }
++ }
++
++ /* Check the MAJOR & MINOR versions */
++ if(!supported_squashfs_filesystem(msblk, silent))
++ goto failed_mount;
++
++ TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));
++ TRACE("Inodes are %scompressed\n",
++ SQUASHFS_UNCOMPRESSED_INODES
++ (sblk->flags) ? "un" : "");
++ TRACE("Data is %scompressed\n",
++ SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)
++ ? "un" : "");
++ TRACE("Check data is %s present in the filesystem\n",
++ SQUASHFS_CHECK_DATA(sblk->flags) ?
++ "" : "not");
++ TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);
++ TRACE("Block size %d\n", sblk->block_size);
++ TRACE("Number of inodes %d\n", sblk->inodes);
++ if (sblk->s_major > 1)
++ TRACE("Number of fragments %d\n", sblk->fragments);
++ TRACE("Number of uids %d\n", sblk->no_uids);
++ TRACE("Number of gids %d\n", sblk->no_guids);
++ TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);
++ TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);
++ if (sblk->s_major > 1)
++ TRACE("sblk->fragment_table_start %llx\n",
++ sblk->fragment_table_start);
++ TRACE("sblk->uid_start %llx\n", sblk->uid_start);
++
++ s->s_flags |= MS_RDONLY;
++ s->s_op = &squashfs_ops;
++
++ /* Init inode_table block pointer array */
++ if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *
++ SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
++ ERROR("Failed to allocate block cache\n");
++ goto failed_mount;
++ }
++
++ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
++ msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
++
++ msblk->next_cache = 0;
++
++ /* Allocate read_data block */
++ msblk->read_size = (sblk->block_size < SQUASHFS_METADATA_SIZE) ?
++ SQUASHFS_METADATA_SIZE :
++ sblk->block_size;
++
++ if (!(msblk->read_data = kmalloc(msblk->read_size, GFP_KERNEL))) {
++ ERROR("Failed to allocate read_data block\n");
++ goto failed_mount;
++ }
++
++ /* Allocate read_page block */
++ if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {
++ ERROR("Failed to allocate read_page block\n");
++ goto failed_mount;
++ }
++
++ /* Allocate uid and gid tables */
++ if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *
++ sizeof(unsigned int), GFP_KERNEL))) {
++ ERROR("Failed to allocate uid/gid table\n");
++ goto failed_mount;
++ }
++ msblk->guid = msblk->uid + sblk->no_uids;
++
++ if (msblk->swap) {
++ unsigned int suid[sblk->no_uids + sblk->no_guids];
++
++ if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,
++ ((sblk->no_uids + sblk->no_guids) *
++ sizeof(unsigned int)) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++ ERROR("unable to read uid/gid table\n");
++ goto failed_mount;
++ }
++
++ SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +
++ sblk->no_guids), (sizeof(unsigned int) * 8));
++ } else
++ if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,
++ ((sblk->no_uids + sblk->no_guids) *
++ sizeof(unsigned int)) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++ ERROR("unable to read uid/gid table\n");
++ goto failed_mount;
++ }
++
++
++ if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))
++ goto allocate_root;
++
++ if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *
++ SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {
++ ERROR("Failed to allocate fragment block cache\n");
++ goto failed_mount;
++ }
++
++ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {
++ msblk->fragment[i].locked = 0;
++ msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
++ msblk->fragment[i].data = NULL;
++ }
++
++ msblk->next_fragment = 0;
++
++ /* Allocate fragment index table */
++ if (msblk->read_fragment_index_table(s) == 0)
++ goto failed_mount;
++
++allocate_root:
++ if ((root = (msblk->iget)(s, sblk->root_inode)) == NULL)
++ goto failed_mount;
++
++ if ((s->s_root = d_alloc_root(root)) == NULL) {
++ ERROR("Root inode create failed\n");
++ iput(root);
++ goto failed_mount;
++ }
++
++ TRACE("Leaving squashfs_read_super\n");
++ return 0;
++
++failed_mount:
++ kfree(msblk->fragment_index);
++ kfree(msblk->fragment);
++ kfree(msblk->uid);
++ kfree(msblk->read_page);
++ kfree(msblk->read_data);
++ kfree(msblk->block_cache);
++ kfree(msblk->fragment_index_2);
++ kfree(s->s_fs_info);
++ s->s_fs_info = NULL;
++ return -EINVAL;
++
++failure:
++ return -ENOMEM;
++}
++
++
++static int squashfs_statfs(struct super_block *s, struct kstatfs *buf)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ TRACE("Entered squashfs_statfs\n");
++
++ buf->f_type = SQUASHFS_MAGIC;
++ buf->f_bsize = sblk->block_size;
++ buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;
++ buf->f_bfree = buf->f_bavail = 0;
++ buf->f_files = sblk->inodes;
++ buf->f_ffree = 0;
++ buf->f_namelen = SQUASHFS_NAME_LEN;
++
++ return 0;
++}
++
++
++static int squashfs_symlink_readpage(struct file *file, struct page *page)
++{
++ struct inode *inode = page->mapping->host;
++ int index = page->index << PAGE_CACHE_SHIFT, length, bytes;
++ long long block = SQUASHFS_I(inode)->start_block;
++ int offset = SQUASHFS_I(inode)->offset;
++ void *pageaddr = kmap(page);
++
++ TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
++ "%llx, offset %x\n", page->index,
++ SQUASHFS_I(inode)->start_block,
++ SQUASHFS_I(inode)->offset);
++
++ for (length = 0; length < index; length += bytes) {
++ if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,
++ block, offset, PAGE_CACHE_SIZE, &block,
++ &offset))) {
++ ERROR("Unable to read symbolic link [%llx:%x]\n", block,
++ offset);
++ goto skip_read;
++ }
++ }
++
++ if (length != index) {
++ ERROR("(squashfs_symlink_readpage) length != index\n");
++ bytes = 0;
++ goto skip_read;
++ }
++
++ bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :
++ i_size_read(inode) - length;
++
++ if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,
++ offset, bytes, &block, &offset)))
++ ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);
++
++skip_read:
++ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++ kunmap(page);
++ SetPageUptodate(page);
++ unlock_page(page);
++
++ return 0;
++}
++
++
++struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)
++{
++ struct meta_index *meta = NULL;
++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++ int i;
++
++ down(&msblk->meta_index_mutex);
++
++ TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
++
++ if(msblk->meta_index == NULL)
++ goto not_allocated;
++
++ for (i = 0; i < SQUASHFS_META_NUMBER; i ++)
++ if (msblk->meta_index[i].inode_number == inode->i_ino &&
++ msblk->meta_index[i].offset >= offset &&
++ msblk->meta_index[i].offset <= index &&
++ msblk->meta_index[i].locked == 0) {
++ TRACE("locate_meta_index: entry %d, offset %d\n", i,
++ msblk->meta_index[i].offset);
++ meta = &msblk->meta_index[i];
++ offset = meta->offset;
++ }
++
++ if (meta)
++ meta->locked = 1;
++
++not_allocated:
++ up(&msblk->meta_index_mutex);
++
++ return meta;
++}
++
++
++struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)
++{
++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++ struct meta_index *meta = NULL;
++ int i;
++
++ down(&msblk->meta_index_mutex);
++
++ TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
++
++ if(msblk->meta_index == NULL) {
++ if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *
++ SQUASHFS_META_NUMBER, GFP_KERNEL))) {
++ ERROR("Failed to allocate meta_index\n");
++ goto failed;
++ }
++ for(i = 0; i < SQUASHFS_META_NUMBER; i++) {
++ msblk->meta_index[i].inode_number = 0;
++ msblk->meta_index[i].locked = 0;
++ }
++ msblk->next_meta_index = 0;
++ }
++
++ for(i = SQUASHFS_META_NUMBER; i &&
++ msblk->meta_index[msblk->next_meta_index].locked; i --)
++ msblk->next_meta_index = (msblk->next_meta_index + 1) %
++ SQUASHFS_META_NUMBER;
++
++ if(i == 0) {
++ TRACE("empty_meta_index: failed!\n");
++ goto failed;
++ }
++
++ TRACE("empty_meta_index: returned meta entry %d, %p\n",
++ msblk->next_meta_index,
++ &msblk->meta_index[msblk->next_meta_index]);
++
++ meta = &msblk->meta_index[msblk->next_meta_index];
++ msblk->next_meta_index = (msblk->next_meta_index + 1) %
++ SQUASHFS_META_NUMBER;
++
++ meta->inode_number = inode->i_ino;
++ meta->offset = offset;
++ meta->skip = skip;
++ meta->entries = 0;
++ meta->locked = 1;
++
++failed:
++ up(&msblk->meta_index_mutex);
++ return meta;
++}
++
++
++void release_meta_index(struct inode *inode, struct meta_index *meta)
++{
++ meta->locked = 0;
++}
++
++
++static int read_block_index(struct super_block *s, int blocks, char *block_list,
++ long long *start_block, int *offset)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ unsigned int *block_listp;
++ int block = 0;
++
++ if (msblk->swap) {
++ char sblock_list[blocks << 2];
++
++ if (!squashfs_get_cached_block(s, sblock_list, *start_block,
++ *offset, blocks << 2, start_block, offset)) {
++ ERROR("Unable to read block list [%llx:%x]\n",
++ *start_block, *offset);
++ goto failure;
++ }
++ SQUASHFS_SWAP_INTS(((unsigned int *)block_list),
++ ((unsigned int *)sblock_list), blocks);
++ } else
++ if (!squashfs_get_cached_block(s, block_list, *start_block,
++ *offset, blocks << 2, start_block, offset)) {
++ ERROR("Unable to read block list [%llx:%x]\n",
++ *start_block, *offset);
++ goto failure;
++ }
++
++ for (block_listp = (unsigned int *) block_list; blocks;
++ block_listp++, blocks --)
++ block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
++
++ return block;
++
++failure:
++ return -1;
++}
++
++
++#define SIZE 256
++
++static inline int calculate_skip(int blocks) {
++ int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);
++ return skip >= 7 ? 7 : skip + 1;
++}
++
++
++static int get_meta_index(struct inode *inode, int index,
++ long long *index_block, int *index_offset,
++ long long *data_block, char *block_list)
++{
++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);
++ int offset = 0;
++ struct meta_index *meta;
++ struct meta_entry *meta_entry;
++ long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;
++ int cur_offset = SQUASHFS_I(inode)->offset;
++ long long cur_data_block = SQUASHFS_I(inode)->start_block;
++ int i;
++
++ index /= SQUASHFS_META_INDEXES * skip;
++
++ while ( offset < index ) {
++ meta = locate_meta_index(inode, index, offset + 1);
++
++ if (meta == NULL) {
++ if ((meta = empty_meta_index(inode, offset + 1,
++ skip)) == NULL)
++ goto all_done;
++ } else {
++ offset = index < meta->offset + meta->entries ? index :
++ meta->offset + meta->entries - 1;
++ meta_entry = &meta->meta_entry[offset - meta->offset];
++ cur_index_block = meta_entry->index_block + sblk->inode_table_start;
++ cur_offset = meta_entry->offset;
++ cur_data_block = meta_entry->data_block;
++ TRACE("get_meta_index: offset %d, meta->offset %d, "
++ "meta->entries %d\n", offset, meta->offset,
++ meta->entries);
++ TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
++ " data_block 0x%llx\n", cur_index_block,
++ cur_offset, cur_data_block);
++ }
++
++ for (i = meta->offset + meta->entries; i <= index &&
++ i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
++ int blocks = skip * SQUASHFS_META_INDEXES;
++
++ while (blocks) {
++ int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :
++ blocks;
++ int res = read_block_index(inode->i_sb, block,
++ block_list, &cur_index_block,
++ &cur_offset);
++
++ if (res == -1)
++ goto failed;
++
++ cur_data_block += res;
++ blocks -= block;
++ }
++
++ meta_entry = &meta->meta_entry[i - meta->offset];
++ meta_entry->index_block = cur_index_block - sblk->inode_table_start;
++ meta_entry->offset = cur_offset;
++ meta_entry->data_block = cur_data_block;
++ meta->entries ++;
++ offset ++;
++ }
++
++ TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
++ meta->offset, meta->entries);
++
++ release_meta_index(inode, meta);
++ }
++
++all_done:
++ *index_block = cur_index_block;
++ *index_offset = cur_offset;
++ *data_block = cur_data_block;
++
++ return offset * SQUASHFS_META_INDEXES * skip;
++
++failed:
++ release_meta_index(inode, meta);
++ return -1;
++}
++
++
++static long long read_blocklist(struct inode *inode, int index,
++ int readahead_blks, char *block_list,
++ unsigned short **block_p, unsigned int *bsize)
++{
++ long long block_ptr;
++ int offset;
++ long long block;
++ int res = get_meta_index(inode, index, &block_ptr, &offset, &block,
++ block_list);
++
++ TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"
++ " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,
++ block);
++
++ if(res == -1)
++ goto failure;
++
++ index -= res;
++
++ while ( index ) {
++ int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;
++ int res = read_block_index(inode->i_sb, blocks, block_list,
++ &block_ptr, &offset);
++ if (res == -1)
++ goto failure;
++ block += res;
++ index -= blocks;
++ }
++
++ if (read_block_index(inode->i_sb, 1, block_list,
++ &block_ptr, &offset) == -1)
++ goto failure;
++ *bsize = *((unsigned int *) block_list);
++
++ return block;
++
++failure:
++ return 0;
++}
++
++
++static int squashfs_readpage(struct file *file, struct page *page)
++{
++ struct inode *inode = page->mapping->host;
++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ unsigned char block_list[SIZE];
++ long long block;
++ unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;
++ int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);
++ void *pageaddr;
++ struct squashfs_fragment_cache *fragment = NULL;
++ char *data_ptr = msblk->read_page;
++
++ int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;
++ int start_index = page->index & ~mask;
++ int end_index = start_index | mask;
++
++ TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
++ page->index,
++ SQUASHFS_I(inode)->start_block);
++
++ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
++ PAGE_CACHE_SHIFT))
++ goto skip_read;
++
++ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++ || index < (i_size_read(inode) >>
++ sblk->block_log)) {
++ if ((block = (msblk->read_blocklist)(inode, index, 1,
++ block_list, NULL, &bsize)) == 0)
++ goto skip_read;
++
++ down(&msblk->read_page_mutex);
++
++ if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,
++ block, bsize, NULL))) {
++ ERROR("Unable to read page, block %llx, size %x\n", block,
++ bsize);
++ up(&msblk->read_page_mutex);
++ goto skip_read;
++ }
++ } else {
++ if ((fragment = get_cached_fragment(inode->i_sb,
++ SQUASHFS_I(inode)->
++ u.s1.fragment_start_block,
++ SQUASHFS_I(inode)->u.s1.fragment_size))
++ == NULL) {
++ ERROR("Unable to read page, block %llx, size %x\n",
++ SQUASHFS_I(inode)->
++ u.s1.fragment_start_block,
++ (int) SQUASHFS_I(inode)->
++ u.s1.fragment_size);
++ goto skip_read;
++ }
++ bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +
++ (i_size_read(inode) & (sblk->block_size
++ - 1));
++ byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;
++ data_ptr = fragment->data;
++ }
++
++ for (i = start_index; i <= end_index && byte_offset < bytes;
++ i++, byte_offset += PAGE_CACHE_SIZE) {
++ struct page *push_page;
++ int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ?
++ PAGE_CACHE_SIZE : bytes - byte_offset;
++
++ TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",
++ bytes, i, byte_offset, available_bytes);
++
++ if (i == page->index) {
++ pageaddr = kmap_atomic(page, KM_USER0);
++ memcpy(pageaddr, data_ptr + byte_offset,
++ available_bytes);
++ memset(pageaddr + available_bytes, 0,
++ PAGE_CACHE_SIZE - available_bytes);
++ kunmap_atomic(pageaddr, KM_USER0);
++ flush_dcache_page(page);
++ SetPageUptodate(page);
++ unlock_page(page);
++ } else if ((push_page =
++ grab_cache_page_nowait(page->mapping, i))) {
++ pageaddr = kmap_atomic(push_page, KM_USER0);
++
++ memcpy(pageaddr, data_ptr + byte_offset,
++ available_bytes);
++ memset(pageaddr + available_bytes, 0,
++ PAGE_CACHE_SIZE - available_bytes);
++ kunmap_atomic(pageaddr, KM_USER0);
++ flush_dcache_page(push_page);
++ SetPageUptodate(push_page);
++ unlock_page(push_page);
++ page_cache_release(push_page);
++ }
++ }
++
++ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++ || index < (i_size_read(inode) >>
++ sblk->block_log))
++ up(&msblk->read_page_mutex);
++ else
++ release_cached_fragment(msblk, fragment);
++
++ return 0;
++
++skip_read:
++ pageaddr = kmap_atomic(page, KM_USER0);
++ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++ kunmap_atomic(pageaddr, KM_USER0);
++ flush_dcache_page(page);
++ SetPageUptodate(page);
++ unlock_page(page);
++
++ return 0;
++}
++
++
++static int squashfs_readpage4K(struct file *file, struct page *page)
++{
++ struct inode *inode = page->mapping->host;
++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ unsigned char block_list[SIZE];
++ long long block;
++ unsigned int bsize, bytes = 0;
++ void *pageaddr;
++
++ TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",
++ page->index,
++ SQUASHFS_I(inode)->start_block);
++
++ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
++ PAGE_CACHE_SHIFT)) {
++ pageaddr = kmap_atomic(page, KM_USER0);
++ goto skip_read;
++ }
++
++ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++ || page->index < (i_size_read(inode) >>
++ sblk->block_log)) {
++ block = (msblk->read_blocklist)(inode, page->index, 1,
++ block_list, NULL, &bsize);
++
++ down(&msblk->read_page_mutex);
++ bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
++ bsize, NULL);
++ pageaddr = kmap_atomic(page, KM_USER0);
++ if (bytes)
++ memcpy(pageaddr, msblk->read_page, bytes);
++ else
++ ERROR("Unable to read page, block %llx, size %x\n",
++ block, bsize);
++ up(&msblk->read_page_mutex);
++ } else {
++ struct squashfs_fragment_cache *fragment =
++ get_cached_fragment(inode->i_sb,
++ SQUASHFS_I(inode)->
++ u.s1.fragment_start_block,
++ SQUASHFS_I(inode)-> u.s1.fragment_size);
++ pageaddr = kmap_atomic(page, KM_USER0);
++ if (fragment) {
++ bytes = i_size_read(inode) & (sblk->block_size - 1);
++ memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->
++ u.s1.fragment_offset, bytes);
++ release_cached_fragment(msblk, fragment);
++ } else
++ ERROR("Unable to read page, block %llx, size %x\n",
++ SQUASHFS_I(inode)->
++ u.s1.fragment_start_block, (int)
++ SQUASHFS_I(inode)-> u.s1.fragment_size);
++ }
++
++skip_read:
++ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++ kunmap_atomic(pageaddr, KM_USER0);
++ flush_dcache_page(page);
++ SetPageUptodate(page);
++ unlock_page(page);
++
++ return 0;
++}
++
++
++static int get_dir_index_using_offset(struct super_block *s, long long
++ *next_block, unsigned int *next_offset,
++ long long index_start,
++ unsigned int index_offset, int i_count,
++ long long f_pos)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int i, length = 0;
++ struct squashfs_dir_index index;
++
++ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
++ i_count, (unsigned int) f_pos);
++
++ f_pos =- 3;
++ if (f_pos == 0)
++ goto finish;
++
++ for (i = 0; i < i_count; i++) {
++ if (msblk->swap) {
++ struct squashfs_dir_index sindex;
++ squashfs_get_cached_block(s, (char *) &sindex,
++ index_start, index_offset,
++ sizeof(sindex), &index_start,
++ &index_offset);
++ SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);
++ } else
++ squashfs_get_cached_block(s, (char *) &index,
++ index_start, index_offset,
++ sizeof(index), &index_start,
++ &index_offset);
++
++ if (index.index > f_pos)
++ break;
++
++ squashfs_get_cached_block(s, NULL, index_start, index_offset,
++ index.size + 1, &index_start,
++ &index_offset);
++
++ length = index.index;
++ *next_block = index.start_block + sblk->directory_table_start;
++ }
++
++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++
++finish:
++ return length + 3;
++}
++
++
++static int get_dir_index_using_name(struct super_block *s, long long
++ *next_block, unsigned int *next_offset,
++ long long index_start,
++ unsigned int index_offset, int i_count,
++ const char *name, int size)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int i, length = 0;
++ char buffer[sizeof(struct squashfs_dir_index) + SQUASHFS_NAME_LEN + 1];
++ struct squashfs_dir_index *index = (struct squashfs_dir_index *) buffer;
++ char str[SQUASHFS_NAME_LEN + 1];
++
++ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
++
++ strncpy(str, name, size);
++ str[size] = '\0';
++
++ for (i = 0; i < i_count; i++) {
++ if (msblk->swap) {
++ struct squashfs_dir_index sindex;
++ squashfs_get_cached_block(s, (char *) &sindex,
++ index_start, index_offset,
++ sizeof(sindex), &index_start,
++ &index_offset);
++ SQUASHFS_SWAP_DIR_INDEX(index, &sindex);
++ } else
++ squashfs_get_cached_block(s, (char *) index,
++ index_start, index_offset,
++ sizeof(struct squashfs_dir_index),
++ &index_start, &index_offset);
++
++ squashfs_get_cached_block(s, index->name, index_start,
++ index_offset, index->size + 1,
++ &index_start, &index_offset);
++
++ index->name[index->size + 1] = '\0';
++
++ if (strcmp(index->name, str) > 0)
++ break;
++
++ length = index->index;
++ *next_block = index->start_block + sblk->directory_table_start;
++ }
++
++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++ return length + 3;
++}
++
++
++static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
++{
++ struct inode *i = file->f_dentry->d_inode;
++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long next_block = SQUASHFS_I(i)->start_block +
++ sblk->directory_table_start;
++ int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0,
++ dir_count;
++ struct squashfs_dir_header dirh;
++ char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1];
++ struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
++
++ TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);
++
++ while(file->f_pos < 3) {
++ char *name;
++ int size, i_ino;
++
++ if(file->f_pos == 0) {
++ name = ".";
++ size = 1;
++ i_ino = i->i_ino;
++ } else {
++ name = "..";
++ size = 2;
++ i_ino = SQUASHFS_I(i)->u.s2.parent_inode;
++ }
++ TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",
++ (unsigned int) dirent, name, size, (int)
++ file->f_pos, i_ino,
++ squashfs_filetype_table[1]);
++
++ if (filldir(dirent, name, size,
++ file->f_pos, i_ino,
++ squashfs_filetype_table[1]) < 0) {
++ TRACE("Filldir returned less than 0\n");
++ goto finish;
++ }
++ file->f_pos += size;
++ dirs_read++;
++ }
++
++ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_start,
++ SQUASHFS_I(i)->u.s2.directory_index_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_count,
++ file->f_pos);
++
++ while (length < i_size_read(i)) {
++ /* read directory header */
++ if (msblk->swap) {
++ struct squashfs_dir_header sdirh;
++
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++ next_block, next_offset, sizeof(sdirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdirh);
++ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++ next_block, next_offset, sizeof(dirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(dirh);
++ }
++
++ dir_count = dirh.count + 1;
++ while (dir_count--) {
++ if (msblk->swap) {
++ struct squashfs_dir_entry sdire;
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ &sdire, next_block, next_offset,
++ sizeof(sdire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdire);
++ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ dire, next_block, next_offset,
++ sizeof(*dire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(*dire);
++ }
++
++ if (!squashfs_get_cached_block(i->i_sb, dire->name,
++ next_block, next_offset,
++ dire->size + 1, &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += dire->size + 1;
++
++ if (file->f_pos >= length)
++ continue;
++
++ dire->name[dire->size + 1] = '\0';
++
++ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",
++ (unsigned int) dirent, dire->name,
++ dire->size + 1, (int) file->f_pos,
++ dirh.start_block, dire->offset,
++ dirh.inode_number + dire->inode_number,
++ squashfs_filetype_table[dire->type]);
++
++ if (filldir(dirent, dire->name, dire->size + 1,
++ file->f_pos,
++ dirh.inode_number + dire->inode_number,
++ squashfs_filetype_table[dire->type])
++ < 0) {
++ TRACE("Filldir returned less than 0\n");
++ goto finish;
++ }
++ file->f_pos = length;
++ dirs_read++;
++ }
++ }
++
++finish:
++ return dirs_read;
++
++failed_read:
++ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++ next_offset);
++ return 0;
++}
++
++
++static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry,
++ struct nameidata *nd)
++{
++ const unsigned char *name = dentry->d_name.name;
++ int len = dentry->d_name.len;
++ struct inode *inode = NULL;
++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long next_block = SQUASHFS_I(i)->start_block +
++ sblk->directory_table_start;
++ int next_offset = SQUASHFS_I(i)->offset, length = 0,
++ dir_count;
++ struct squashfs_dir_header dirh;
++ char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN];
++ struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
++
++ TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
++
++ if (len > SQUASHFS_NAME_LEN)
++ goto exit_loop;
++
++ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_start,
++ SQUASHFS_I(i)->u.s2.directory_index_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_count, name,
++ len);
++
++ while (length < i_size_read(i)) {
++ /* read directory header */
++ if (msblk->swap) {
++ struct squashfs_dir_header sdirh;
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++ next_block, next_offset, sizeof(sdirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdirh);
++ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++ next_block, next_offset, sizeof(dirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(dirh);
++ }
++
++ dir_count = dirh.count + 1;
++ while (dir_count--) {
++ if (msblk->swap) {
++ struct squashfs_dir_entry sdire;
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ &sdire, next_block,next_offset,
++ sizeof(sdire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdire);
++ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ dire, next_block,next_offset,
++ sizeof(*dire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(*dire);
++ }
++
++ if (!squashfs_get_cached_block(i->i_sb, dire->name,
++ next_block, next_offset, dire->size + 1,
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += dire->size + 1;
++
++ if (name[0] < dire->name[0])
++ goto exit_loop;
++
++ if ((len == dire->size + 1) && !strncmp(name,
++ dire->name, len)) {
++ squashfs_inode_t ino =
++ SQUASHFS_MKINODE(dirh.start_block,
++ dire->offset);
++
++ TRACE("calling squashfs_iget for directory "
++ "entry %s, inode %x:%x, %d\n", name,
++ dirh.start_block, dire->offset,
++ dirh.inode_number + dire->inode_number);
++
++ inode = (msblk->iget)(i->i_sb, ino);
++
++ goto exit_loop;
++ }
++ }
++ }
++
++exit_loop:
++ d_add(dentry, inode);
++ return ERR_PTR(0);
++
++failed_read:
++ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++ next_offset);
++ goto exit_loop;
++}
++
++
++static void squashfs_put_super(struct super_block *s)
++{
++ int i;
++
++ if (s->s_fs_info) {
++ struct squashfs_sb_info *sbi = s->s_fs_info;
++ if (sbi->block_cache)
++ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
++ if (sbi->block_cache[i].block !=
++ SQUASHFS_INVALID_BLK)
++ kfree(sbi->block_cache[i].data);
++ if (sbi->fragment)
++ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++)
++ SQUASHFS_FREE(sbi->fragment[i].data);
++ kfree(sbi->fragment);
++ kfree(sbi->block_cache);
++ kfree(sbi->read_data);
++ kfree(sbi->read_page);
++ kfree(sbi->uid);
++ kfree(sbi->fragment_index);
++ kfree(sbi->fragment_index_2);
++ kfree(sbi->meta_index);
++ kfree(s->s_fs_info);
++ s->s_fs_info = NULL;
++ }
++}
++
++
++static struct super_block *squashfs_get_sb(struct file_system_type *fs_type,
++ int flags, const char *dev_name, void *data)
++{
++ return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super);
++}
++
++
++static int __init init_squashfs_fs(void)
++{
++ int err = init_inodecache();
++ if (err)
++ goto out;
++
++ printk(KERN_INFO "squashfs: version 3.0 (2006/03/15) "
++ "Phillip Lougher\n");
++
++ if (!(stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
++ ERROR("Failed to allocate zlib workspace\n");
++ destroy_inodecache();
++ err = -ENOMEM;
++ goto out;
++ }
++
++ if ((err = register_filesystem(&squashfs_fs_type))) {
++ vfree(stream.workspace);
++ destroy_inodecache();
++ }
++
++out:
++ return err;
++}
++
++
++static void __exit exit_squashfs_fs(void)
++{
++ vfree(stream.workspace);
++ unregister_filesystem(&squashfs_fs_type);
++ destroy_inodecache();
++}
++
++
++static kmem_cache_t * squashfs_inode_cachep;
++
++
++static struct inode *squashfs_alloc_inode(struct super_block *sb)
++{
++ struct squashfs_inode_info *ei;
++ ei = kmem_cache_alloc(squashfs_inode_cachep, SLAB_KERNEL);
++ if (!ei)
++ return NULL;
++ return &ei->vfs_inode;
++}
++
++
++static void squashfs_destroy_inode(struct inode *inode)
++{
++ kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode));
++}
++
++
++static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
++{
++ struct squashfs_inode_info *ei = foo;
++
++ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
++ SLAB_CTOR_CONSTRUCTOR)
++ inode_init_once(&ei->vfs_inode);
++}
++
++
++static int __init init_inodecache(void)
++{
++ squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
++ sizeof(struct squashfs_inode_info),
++ 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
++ init_once, NULL);
++ if (squashfs_inode_cachep == NULL)
++ return -ENOMEM;
++ return 0;
++}
++
++
++static void destroy_inodecache(void)
++{
++ if (kmem_cache_destroy(squashfs_inode_cachep))
++ printk(KERN_INFO "squashfs_inode_cache: not all structures "
++ "were freed\n");
++}
++
++
++module_init(init_squashfs_fs);
++module_exit(exit_squashfs_fs);
++MODULE_DESCRIPTION("squashfs, a compressed read-only filesystem");
++MODULE_AUTHOR("Phillip Lougher <phillip@lougher.org.uk>");
++MODULE_LICENSE("GPL");
+diff --new-file -urp linux-2.6.15/fs/squashfs/Makefile linux-2.6.15-squashfs3.0/fs/squashfs/Makefile
+--- linux-2.6.15/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-squashfs3.0/fs/squashfs/Makefile 2006-03-07 21:12:37.000000000 +0000
+@@ -0,0 +1,7 @@
++#
++# Makefile for the linux squashfs routines.
++#
++
++obj-$(CONFIG_SQUASHFS) += squashfs.o
++squashfs-y += inode.o
++squashfs-y += squashfs2_0.o
+diff --new-file -urp linux-2.6.15/fs/squashfs/squashfs2_0.c linux-2.6.15-squashfs3.0/fs/squashfs/squashfs2_0.c
+--- linux-2.6.15/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-squashfs3.0/fs/squashfs/squashfs2_0.c 2006-03-07 21:12:37.000000000 +0000
+@@ -0,0 +1,758 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs2_0.c
++ */
++
++#include <linux/types.h>
++#include <linux/squashfs_fs.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/fs.h>
++#include <linux/smp_lock.h>
++#include <linux/slab.h>
++#include <linux/squashfs_fs_sb.h>
++#include <linux/squashfs_fs_i.h>
++#include <linux/buffer_head.h>
++#include <linux/vfs.h>
++#include <linux/init.h>
++#include <linux/dcache.h>
++#include <linux/wait.h>
++#include <linux/zlib.h>
++#include <linux/blkdev.h>
++#include <linux/vmalloc.h>
++#include <asm/uaccess.h>
++#include <asm/semaphore.h>
++
++#include "squashfs.h"
++static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);
++static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *,
++ struct nameidata *);
++
++static struct file_operations squashfs_dir_ops_2 = {
++ .read = generic_read_dir,
++ .readdir = squashfs_readdir_2
++};
++
++static struct inode_operations squashfs_dir_inode_ops_2 = {
++ .lookup = squashfs_lookup_2
++};
++
++static unsigned char squashfs_filetype_table[] = {
++ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
++};
++
++static int read_fragment_index_table_2(struct super_block *s)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2
++ (sblk->fragments), GFP_KERNEL))) {
++ ERROR("Failed to allocate uid/gid table\n");
++ return 0;
++ }
++
++ if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&
++ !squashfs_read_data(s, (char *)
++ msblk->fragment_index_2,
++ sblk->fragment_table_start,
++ SQUASHFS_FRAGMENT_INDEX_BYTES_2
++ (sblk->fragments) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++ ERROR("unable to read fragment index table\n");
++ return 0;
++ }
++
++ if (msblk->swap) {
++ int i;
++ unsigned int fragment;
++
++ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);
++ i++) {
++ SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),
++ &msblk->fragment_index_2[i], 1);
++ msblk->fragment_index_2[i] = fragment;
++ }
++ }
++
++ return 1;
++}
++
++
++static int get_fragment_location_2(struct super_block *s, unsigned int fragment,
++ long long *fragment_start_block,
++ unsigned int *fragment_size)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ long long start_block =
++ msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];
++ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);
++ struct squashfs_fragment_entry_2 fragment_entry;
++
++ if (msblk->swap) {
++ struct squashfs_fragment_entry_2 sfragment_entry;
++
++ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
++ start_block, offset,
++ sizeof(sfragment_entry), &start_block,
++ &offset))
++ goto out;
++ SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);
++ } else
++ if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
++ start_block, offset,
++ sizeof(fragment_entry), &start_block,
++ &offset))
++ goto out;
++
++ *fragment_start_block = fragment_entry.start_block;
++ *fragment_size = fragment_entry.size;
++
++ return 1;
++
++out:
++ return 0;
++}
++
++
++static struct inode *squashfs_new_inode(struct super_block *s,
++ struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ struct inode *i = new_inode(s);
++
++ if (i) {
++ i->i_ino = ino;
++ i->i_mtime.tv_sec = sblk->mkfs_time;
++ i->i_atime.tv_sec = sblk->mkfs_time;
++ i->i_ctime.tv_sec = sblk->mkfs_time;
++ i->i_uid = msblk->uid[inodeb->uid];
++ i->i_mode = inodeb->mode;
++ i->i_nlink = 1;
++ i->i_size = 0;
++ if (inodeb->guid == SQUASHFS_GUIDS)
++ i->i_gid = i->i_uid;
++ else
++ i->i_gid = msblk->guid[inodeb->guid];
++ }
++
++ return i;
++}
++
++
++static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t inode)
++{
++ struct inode *i;
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ unsigned int block = SQUASHFS_INODE_BLK(inode) +
++ sblk->inode_table_start;
++ unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
++ unsigned int ino = SQUASHFS_MK_VFS_INODE(block
++ - sblk->inode_table_start, offset);
++ long long next_block;
++ unsigned int next_offset;
++ union squashfs_inode_header_2 id, sid;
++ struct squashfs_base_inode_header_2 *inodeb = &id.base,
++ *sinodeb = &sid.base;
++
++ TRACE("Entered squashfs_iget\n");
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
++ offset, sizeof(*sinodeb), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,
++ sizeof(*sinodeb));
++ } else
++ if (!squashfs_get_cached_block(s, (char *) inodeb, block,
++ offset, sizeof(*inodeb), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ switch(inodeb->inode_type) {
++ case SQUASHFS_FILE_TYPE: {
++ struct squashfs_reg_inode_header_2 *inodep = &id.reg;
++ struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;
++ long long frag_blk;
++ unsigned int frag_size;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ frag_blk = SQUASHFS_INVALID_BLK;
++ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
++ !get_fragment_location_2(s,
++ inodep->fragment, &frag_blk, &frag_size))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++ goto failed_read1;
++
++ i->i_size = inodep->file_size;
++ i->i_fop = &generic_ro_fops;
++ i->i_mode |= S_IFREG;
++ i->i_mtime.tv_sec = inodep->mtime;
++ i->i_atime.tv_sec = inodep->mtime;
++ i->i_ctime.tv_sec = inodep->mtime;
++ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
++ i->i_blksize = PAGE_CACHE_SIZE;
++ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
++ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
++ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++ if (sblk->block_size > 4096)
++ i->i_data.a_ops = &squashfs_aops;
++ else
++ i->i_data.a_ops = &squashfs_aops_4K;
++
++ TRACE("File inode %x:%x, start_block %x, "
++ "block_list_start %llx, offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, next_block,
++ next_offset);
++ break;
++ }
++ case SQUASHFS_DIR_TYPE: {
++ struct squashfs_dir_inode_header_2 *inodep = &id.dir;
++ struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++ goto failed_read1;
++
++ i->i_size = inodep->file_size;
++ i->i_op = &squashfs_dir_inode_ops_2;
++ i->i_fop = &squashfs_dir_ops_2;
++ i->i_mode |= S_IFDIR;
++ i->i_mtime.tv_sec = inodep->mtime;
++ i->i_atime.tv_sec = inodep->mtime;
++ i->i_ctime.tv_sec = inodep->mtime;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->offset = inodep->offset;
++ SQUASHFS_I(i)->u.s2.directory_index_count = 0;
++ SQUASHFS_I(i)->u.s2.parent_inode = 0;
++
++ TRACE("Directory inode %x:%x, start_block %x, offset "
++ "%x\n", SQUASHFS_INODE_BLK(inode),
++ offset, inodep->start_block,
++ inodep->offset);
++ break;
++ }
++ case SQUASHFS_LDIR_TYPE: {
++ struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;
++ struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,
++ sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++ goto failed_read1;
++
++ i->i_size = inodep->file_size;
++ i->i_op = &squashfs_dir_inode_ops_2;
++ i->i_fop = &squashfs_dir_ops_2;
++ i->i_mode |= S_IFDIR;
++ i->i_mtime.tv_sec = inodep->mtime;
++ i->i_atime.tv_sec = inodep->mtime;
++ i->i_ctime.tv_sec = inodep->mtime;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->offset = inodep->offset;
++ SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
++ SQUASHFS_I(i)->u.s2.directory_index_offset =
++ next_offset;
++ SQUASHFS_I(i)->u.s2.directory_index_count =
++ inodep->i_count;
++ SQUASHFS_I(i)->u.s2.parent_inode = 0;
++
++ TRACE("Long directory inode %x:%x, start_block %x, "
++ "offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, inodep->offset);
++ break;
++ }
++ case SQUASHFS_SYMLINK_TYPE: {
++ struct squashfs_symlink_inode_header_2 *inodep =
++ &id.symlink;
++ struct squashfs_symlink_inode_header_2 *sinodep =
++ &sid.symlink;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,
++ sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++ goto failed_read1;
++
++ i->i_size = inodep->symlink_size;
++ i->i_op = &page_symlink_inode_operations;
++ i->i_data.a_ops = &squashfs_symlink_aops;
++ i->i_mode |= S_IFLNK;
++ SQUASHFS_I(i)->start_block = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++
++ TRACE("Symbolic link inode %x:%x, start_block %llx, "
++ "offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ next_block, next_offset);
++ break;
++ }
++ case SQUASHFS_BLKDEV_TYPE:
++ case SQUASHFS_CHRDEV_TYPE: {
++ struct squashfs_dev_inode_header_2 *inodep = &id.dev;
++ struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++ goto failed_read1;
++
++ i->i_mode |= (inodeb->inode_type ==
++ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
++ S_IFBLK;
++ init_special_inode(i, i->i_mode,
++ old_decode_dev(inodep->rdev));
++
++ TRACE("Device inode %x:%x, rdev %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->rdev);
++ break;
++ }
++ case SQUASHFS_FIFO_TYPE:
++ case SQUASHFS_SOCKET_TYPE: {
++ if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++ goto failed_read1;
++
++ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
++ ? S_IFIFO : S_IFSOCK;
++ init_special_inode(i, i->i_mode, 0);
++ break;
++ }
++ default:
++ ERROR("Unknown inode type %d in squashfs_iget!\n",
++ inodeb->inode_type);
++ goto failed_read1;
++ }
++
++ insert_inode_hash(i);
++ return i;
++
++failed_read:
++ ERROR("Unable to read inode [%x:%x]\n", block, offset);
++
++failed_read1:
++ return NULL;
++}
++
++
++static int get_dir_index_using_offset(struct super_block *s, long long
++ *next_block, unsigned int *next_offset,
++ long long index_start,
++ unsigned int index_offset, int i_count,
++ long long f_pos)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int i, length = 0;
++ struct squashfs_dir_index_2 index;
++
++ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
++ i_count, (unsigned int) f_pos);
++
++ if (f_pos == 0)
++ goto finish;
++
++ for (i = 0; i < i_count; i++) {
++ if (msblk->swap) {
++ struct squashfs_dir_index_2 sindex;
++ squashfs_get_cached_block(s, (char *) &sindex,
++ index_start, index_offset,
++ sizeof(sindex), &index_start,
++ &index_offset);
++ SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);
++ } else
++ squashfs_get_cached_block(s, (char *) &index,
++ index_start, index_offset,
++ sizeof(index), &index_start,
++ &index_offset);
++
++ if (index.index > f_pos)
++ break;
++
++ squashfs_get_cached_block(s, NULL, index_start, index_offset,
++ index.size + 1, &index_start,
++ &index_offset);
++
++ length = index.index;
++ *next_block = index.start_block + sblk->directory_table_start;
++ }
++
++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++
++finish:
++ return length;
++}
++
++
++static int get_dir_index_using_name(struct super_block *s, long long
++ *next_block, unsigned int *next_offset,
++ long long index_start,
++ unsigned int index_offset, int i_count,
++ const char *name, int size)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int i, length = 0;
++ char buffer[sizeof(struct squashfs_dir_index_2) + SQUASHFS_NAME_LEN + 1];
++ struct squashfs_dir_index_2 *index = (struct squashfs_dir_index_2 *) buffer;
++ char str[SQUASHFS_NAME_LEN + 1];
++
++ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
++
++ strncpy(str, name, size);
++ str[size] = '\0';
++
++ for (i = 0; i < i_count; i++) {
++ if (msblk->swap) {
++ struct squashfs_dir_index_2 sindex;
++ squashfs_get_cached_block(s, (char *) &sindex,
++ index_start, index_offset,
++ sizeof(sindex), &index_start,
++ &index_offset);
++ SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);
++ } else
++ squashfs_get_cached_block(s, (char *) index,
++ index_start, index_offset,
++ sizeof(struct squashfs_dir_index_2),
++ &index_start, &index_offset);
++
++ squashfs_get_cached_block(s, index->name, index_start,
++ index_offset, index->size + 1,
++ &index_start, &index_offset);
++
++ index->name[index->size + 1] = '\0';
++
++ if (strcmp(index->name, str) > 0)
++ break;
++
++ length = index->index;
++ *next_block = index->start_block + sblk->directory_table_start;
++ }
++
++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++ return length;
++}
++
++
++static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)
++{
++ struct inode *i = file->f_dentry->d_inode;
++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long next_block = SQUASHFS_I(i)->start_block +
++ sblk->directory_table_start;
++ int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0,
++ dir_count;
++ struct squashfs_dir_header_2 dirh;
++ char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1];
++ struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer;
++
++ TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);
++
++ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_start,
++ SQUASHFS_I(i)->u.s2.directory_index_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_count,
++ file->f_pos);
++
++ while (length < i_size_read(i)) {
++ /* read directory header */
++ if (msblk->swap) {
++ struct squashfs_dir_header_2 sdirh;
++
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++ next_block, next_offset, sizeof(sdirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdirh);
++ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++ next_block, next_offset, sizeof(dirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(dirh);
++ }
++
++ dir_count = dirh.count + 1;
++ while (dir_count--) {
++ if (msblk->swap) {
++ struct squashfs_dir_entry_2 sdire;
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ &sdire, next_block, next_offset,
++ sizeof(sdire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdire);
++ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ dire, next_block, next_offset,
++ sizeof(*dire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(*dire);
++ }
++
++ if (!squashfs_get_cached_block(i->i_sb, dire->name,
++ next_block, next_offset,
++ dire->size + 1, &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += dire->size + 1;
++
++ if (file->f_pos >= length)
++ continue;
++
++ dire->name[dire->size + 1] = '\0';
++
++ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",
++ (unsigned int) dirent, dire->name,
++ dire->size + 1, (int) file->f_pos,
++ dirh.start_block, dire->offset,
++ squashfs_filetype_table[dire->type]);
++
++ if (filldir(dirent, dire->name, dire->size + 1,
++ file->f_pos, SQUASHFS_MK_VFS_INODE(
++ dirh.start_block, dire->offset),
++ squashfs_filetype_table[dire->type])
++ < 0) {
++ TRACE("Filldir returned less than 0\n");
++ goto finish;
++ }
++ file->f_pos = length;
++ dirs_read++;
++ }
++ }
++
++finish:
++ return dirs_read;
++
++failed_read:
++ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++ next_offset);
++ return 0;
++}
++
++
++static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,
++ struct nameidata *nd)
++{
++ const unsigned char *name = dentry->d_name.name;
++ int len = dentry->d_name.len;
++ struct inode *inode = NULL;
++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long next_block = SQUASHFS_I(i)->start_block +
++ sblk->directory_table_start;
++ int next_offset = SQUASHFS_I(i)->offset, length = 0,
++ dir_count;
++ struct squashfs_dir_header_2 dirh;
++ char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN];
++ struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer;
++ int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;
++
++ TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
++
++ if (len > SQUASHFS_NAME_LEN)
++ goto exit_loop;
++
++ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_start,
++ SQUASHFS_I(i)->u.s2.directory_index_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_count, name,
++ len);
++
++ while (length < i_size_read(i)) {
++ /* read directory header */
++ if (msblk->swap) {
++ struct squashfs_dir_header_2 sdirh;
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++ next_block, next_offset, sizeof(sdirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdirh);
++ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++ next_block, next_offset, sizeof(dirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(dirh);
++ }
++
++ dir_count = dirh.count + 1;
++ while (dir_count--) {
++ if (msblk->swap) {
++ struct squashfs_dir_entry_2 sdire;
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ &sdire, next_block,next_offset,
++ sizeof(sdire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdire);
++ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ dire, next_block,next_offset,
++ sizeof(*dire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(*dire);
++ }
++
++ if (!squashfs_get_cached_block(i->i_sb, dire->name,
++ next_block, next_offset, dire->size + 1,
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += dire->size + 1;
++
++ if (sorted && name[0] < dire->name[0])
++ goto exit_loop;
++
++ if ((len == dire->size + 1) && !strncmp(name,
++ dire->name, len)) {
++ squashfs_inode_t ino =
++ SQUASHFS_MKINODE(dirh.start_block,
++ dire->offset);
++
++ TRACE("calling squashfs_iget for directory "
++ "entry %s, inode %x:%x, %lld\n", name,
++ dirh.start_block, dire->offset, ino);
++
++ inode = (msblk->iget)(i->i_sb, ino);
++
++ goto exit_loop;
++ }
++ }
++ }
++
++exit_loop:
++ d_add(dentry, inode);
++ return ERR_PTR(0);
++
++failed_read:
++ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++ next_offset);
++ goto exit_loop;
++}
++
++
++int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
++{
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ msblk->iget = squashfs_iget_2;
++ msblk->read_fragment_index_table = read_fragment_index_table_2;
++
++ sblk->bytes_used = sblk->bytes_used_2;
++ sblk->uid_start = sblk->uid_start_2;
++ sblk->guid_start = sblk->guid_start_2;
++ sblk->inode_table_start = sblk->inode_table_start_2;
++ sblk->directory_table_start = sblk->directory_table_start_2;
++ sblk->fragment_table_start = sblk->fragment_table_start_2;
++
++ return 1;
++}
+diff --new-file -urp linux-2.6.15/fs/squashfs/squashfs.h linux-2.6.15-squashfs3.0/fs/squashfs/squashfs.h
+--- linux-2.6.15/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-squashfs3.0/fs/squashfs/squashfs.h 2006-03-07 21:12:37.000000000 +0000
+@@ -0,0 +1,86 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs.h
++ */
++
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++#endif
++
++#ifdef SQUASHFS_TRACE
++#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)
++#else
++#define TRACE(s, args...) {}
++#endif
++
++#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args)
++
++#define SERROR(s, args...) do { \
++ if (!silent) \
++ printk(KERN_ERR "SQUASHFS error: "s, ## args);\
++ } while(0)
++
++#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args)
++
++static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode)
++{
++ return list_entry(inode, struct squashfs_inode_info, vfs_inode);
++}
++
++#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY)
++#define SQSH_EXTERN
++extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,
++ long long index, unsigned int length,
++ long long *next_index);
++extern int squashfs_get_cached_block(struct super_block *s, char *buffer,
++ long long block, unsigned int offset,
++ int length, long long *next_block,
++ unsigned int *next_offset);
++extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct
++ squashfs_fragment_cache *fragment);
++extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block
++ *s, long long start_block,
++ int length);
++extern struct address_space_operations squashfs_symlink_aops;
++extern struct address_space_operations squashfs_aops;
++extern struct address_space_operations squashfs_aops_4K;
++extern struct inode_operations squashfs_dir_inode_ops;
++#else
++#define SQSH_EXTERN static
++#endif
++
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk);
++#else
++static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk)
++{
++ return 0;
++}
++#endif
++
++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk);
++#else
++static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
++{
++ return 0;
++}
++#endif
+diff --new-file -urp linux-2.6.15/include/linux/squashfs_fs.h linux-2.6.15-squashfs3.0/include/linux/squashfs_fs.h
+--- linux-2.6.15/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-squashfs3.0/include/linux/squashfs_fs.h 2006-03-07 21:12:37.000000000 +0000
+@@ -0,0 +1,911 @@
++#ifndef SQUASHFS_FS
++#define SQUASHFS_FS
++
++/*
++ * Squashfs
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs_fs.h
++ */
++
++#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++#define CONFIG_SQUASHFS_2_0_COMPATIBILITY
++#endif
++
++#ifdef CONFIG_SQUASHFS_VMALLOC
++#define SQUASHFS_ALLOC(a) vmalloc(a)
++#define SQUASHFS_FREE(a) vfree(a)
++#else
++#define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL)
++#define SQUASHFS_FREE(a) kfree(a)
++#endif
++#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
++#define SQUASHFS_MAJOR 3
++#define SQUASHFS_MINOR 0
++#define SQUASHFS_MAGIC 0x73717368
++#define SQUASHFS_MAGIC_SWAP 0x68737173
++#define SQUASHFS_START 0
++
++/* size of metadata (inode and directory) blocks */
++#define SQUASHFS_METADATA_SIZE 8192
++#define SQUASHFS_METADATA_LOG 13
++
++/* default size of data blocks */
++#define SQUASHFS_FILE_SIZE 65536
++#define SQUASHFS_FILE_LOG 16
++
++#define SQUASHFS_FILE_MAX_SIZE 65536
++
++/* Max number of uids and gids */
++#define SQUASHFS_UIDS 256
++#define SQUASHFS_GUIDS 255
++
++/* Max length of filename (not 255) */
++#define SQUASHFS_NAME_LEN 256
++
++#define SQUASHFS_INVALID ((long long) 0xffffffffffff)
++#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff)
++#define SQUASHFS_INVALID_BLK ((long long) -1)
++#define SQUASHFS_USED_BLK ((long long) -2)
++
++/* Filesystem flags */
++#define SQUASHFS_NOI 0
++#define SQUASHFS_NOD 1
++#define SQUASHFS_CHECK 2
++#define SQUASHFS_NOF 3
++#define SQUASHFS_NO_FRAG 4
++#define SQUASHFS_ALWAYS_FRAG 5
++#define SQUASHFS_DUPLICATE 6
++
++#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1)
++
++#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_NOI)
++
++#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_NOD)
++
++#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_NOF)
++
++#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_NO_FRAG)
++
++#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_ALWAYS_FRAG)
++
++#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_DUPLICATE)
++
++#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_CHECK)
++
++#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
++ duplicate_checking) (noi | (nod << 1) | (check_data << 2) \
++ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
++ (duplicate_checking << 6))
++
++/* Max number of types and file types */
++#define SQUASHFS_DIR_TYPE 1
++#define SQUASHFS_FILE_TYPE 2
++#define SQUASHFS_SYMLINK_TYPE 3
++#define SQUASHFS_BLKDEV_TYPE 4
++#define SQUASHFS_CHRDEV_TYPE 5
++#define SQUASHFS_FIFO_TYPE 6
++#define SQUASHFS_SOCKET_TYPE 7
++#define SQUASHFS_LDIR_TYPE 8
++#define SQUASHFS_LREG_TYPE 9
++
++/* 1.0 filesystem type definitions */
++#define SQUASHFS_TYPES 5
++#define SQUASHFS_IPC_TYPE 0
++
++/* Flag whether block is compressed or uncompressed, bit is set if block is
++ * uncompressed */
++#define SQUASHFS_COMPRESSED_BIT (1 << 15)
++
++#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
++ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
++
++#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT))
++
++#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24)
++
++#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \
++ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \
++ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
++
++#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
++
++/*
++ * Inode number ops. Inodes consist of a compressed block number, and an
++ * uncompressed offset within that block
++ */
++#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16))
++
++#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff))
++
++#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\
++ << 16) + (B)))
++
++/* Compute 32 bit VFS inode number from squashfs inode number */
++#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \
++ ((b) >> 2) + 1))
++/* XXX */
++
++/* Translate between VFS mode and squashfs mode */
++#define SQUASHFS_MODE(a) ((a) & 0xfff)
++
++/* fragment and fragment table defines */
++#define SQUASHFS_FRAGMENT_BYTES(A) (A * sizeof(struct squashfs_fragment_entry))
++
++#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \
++ SQUASHFS_METADATA_SIZE - 1) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\
++ sizeof(long long))
++
++/* cached data constants for filesystem */
++#define SQUASHFS_CACHED_BLKS 8
++
++#define SQUASHFS_MAX_FILE_SIZE_LOG 64
++
++#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \
++ (SQUASHFS_MAX_FILE_SIZE_LOG - 2))
++
++#define SQUASHFS_MARKER_BYTE 0xff
++
++/* meta index cache */
++#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
++#define SQUASHFS_META_ENTRIES 31
++#define SQUASHFS_META_NUMBER 8
++#define SQUASHFS_SLOTS 4
++
++struct meta_entry {
++ long long data_block;
++ unsigned int index_block;
++ unsigned short offset;
++ unsigned short pad;
++};
++
++struct meta_index {
++ unsigned int inode_number;
++ unsigned int offset;
++ unsigned short entries;
++ unsigned short skip;
++ unsigned short locked;
++ unsigned short pad;
++ struct meta_entry meta_entry[SQUASHFS_META_ENTRIES];
++};
++
++
++/*
++ * definitions for structures on disk
++ */
++
++typedef long long squashfs_block_t;
++typedef long long squashfs_inode_t;
++
++struct squashfs_super_block {
++ unsigned int s_magic;
++ unsigned int inodes;
++ unsigned int bytes_used_2;
++ unsigned int uid_start_2;
++ unsigned int guid_start_2;
++ unsigned int inode_table_start_2;
++ unsigned int directory_table_start_2;
++ unsigned int s_major:16;
++ unsigned int s_minor:16;
++ unsigned int block_size_1:16;
++ unsigned int block_log:16;
++ unsigned int flags:8;
++ unsigned int no_uids:8;
++ unsigned int no_guids:8;
++ unsigned int mkfs_time /* time of filesystem creation */;
++ squashfs_inode_t root_inode;
++ unsigned int block_size;
++ unsigned int fragments;
++ unsigned int fragment_table_start_2;
++ long long bytes_used;
++ long long uid_start;
++ long long guid_start;
++ long long inode_table_start;
++ long long directory_table_start;
++ long long fragment_table_start;
++ long long unused;
++} __attribute__ ((packed));
++
++struct squashfs_dir_index {
++ unsigned int index;
++ unsigned int start_block;
++ unsigned char size;
++ unsigned char name[0];
++} __attribute__ ((packed));
++
++#define SQUASHFS_BASE_INODE_HEADER \
++ unsigned int inode_type:4; \
++ unsigned int mode:12; \
++ unsigned int uid:8; \
++ unsigned int guid:8; \
++ unsigned int mtime; \
++ unsigned int inode_number;
++
++struct squashfs_base_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ unsigned short rdev;
++} __attribute__ ((packed));
++
++struct squashfs_symlink_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ unsigned short symlink_size;
++ char symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ squashfs_block_t start_block;
++ unsigned int fragment;
++ unsigned int offset;
++ unsigned int file_size;
++ unsigned short block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_lreg_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ squashfs_block_t start_block;
++ unsigned int fragment;
++ unsigned int offset;
++ long long file_size;
++ unsigned short block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ unsigned int file_size:19;
++ unsigned int offset:13;
++ unsigned int start_block;
++ unsigned int parent_inode;
++} __attribute__ ((packed));
++
++struct squashfs_ldir_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ unsigned int file_size:27;
++ unsigned int offset:13;
++ unsigned int start_block;
++ unsigned int i_count:16;
++ unsigned int parent_inode;
++ struct squashfs_dir_index index[0];
++} __attribute__ ((packed));
++
++union squashfs_inode_header {
++ struct squashfs_base_inode_header base;
++ struct squashfs_dev_inode_header dev;
++ struct squashfs_symlink_inode_header symlink;
++ struct squashfs_reg_inode_header reg;
++ struct squashfs_lreg_inode_header lreg;
++ struct squashfs_dir_inode_header dir;
++ struct squashfs_ldir_inode_header ldir;
++ struct squashfs_ipc_inode_header ipc;
++};
++
++struct squashfs_dir_entry {
++ unsigned int offset:13;
++ unsigned int type:3;
++ unsigned int size:8;
++ int inode_number:16;
++ char name[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_header {
++ unsigned int count:8;
++ unsigned int start_block;
++ unsigned int inode_number;
++} __attribute__ ((packed));
++
++struct squashfs_fragment_entry {
++ long long start_block;
++ unsigned int size;
++ unsigned int unused;
++} __attribute__ ((packed));
++
++extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
++extern int squashfs_uncompress_init(void);
++extern int squashfs_uncompress_exit(void);
++
++/*
++ * macros to convert each packed bitfield structure from little endian to big
++ * endian and vice versa. These are needed when creating or using a filesystem
++ * on a machine with different byte ordering to the target architecture.
++ *
++ */
++
++#define SQUASHFS_SWAP_START \
++ int bits;\
++ int b_pos;\
++ unsigned long long val;\
++ unsigned char *s;\
++ unsigned char *d;
++
++#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\
++ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
++ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
++ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\
++ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\
++ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\
++ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\
++ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\
++ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
++ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
++ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
++ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
++ SQUASHFS_SWAP((s)->flags, d, 288, 8);\
++ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
++ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
++ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
++ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
++ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
++ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
++ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\
++ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\
++ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\
++ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\
++ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\
++ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\
++ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\
++ SQUASHFS_SWAP((s)->unused, d, 888, 64);\
++}
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
++ SQUASHFS_MEMSET(s, d, n);\
++ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++ SQUASHFS_SWAP((s)->uid, d, 16, 8);\
++ SQUASHFS_SWAP((s)->guid, d, 24, 8);\
++ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
++ SQUASHFS_SWAP((s)->inode_number, d, 64, 32);
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_ipc_inode_header))\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++}
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_dev_inode_header)); \
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_symlink_inode_header));\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_reg_inode_header));\
++ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\
++ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\
++ SQUASHFS_SWAP((s)->offset, d, 192, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\
++}
++
++#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_lreg_inode_header));\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\
++ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\
++ SQUASHFS_SWAP((s)->offset, d, 224, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_dir_inode_header));\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\
++ SQUASHFS_SWAP((s)->offset, d, 147, 13);\
++ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\
++ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\
++}
++
++#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_ldir_inode_header));\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\
++ SQUASHFS_SWAP((s)->offset, d, 155, 13);\
++ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\
++ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\
++ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\
++ SQUASHFS_SWAP((s)->index, d, 0, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\
++ SQUASHFS_SWAP((s)->size, d, 64, 8);\
++}
++
++#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\
++ SQUASHFS_SWAP((s)->count, d, 0, 8);\
++ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\
++ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\
++ SQUASHFS_SWAP((s)->offset, d, 0, 13);\
++ SQUASHFS_SWAP((s)->type, d, 13, 3);\
++ SQUASHFS_SWAP((s)->size, d, 16, 8);\
++ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\
++ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\
++ SQUASHFS_SWAP((s)->size, d, 64, 32);\
++}
++
++#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
++ int entry;\
++ int bit_position;\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, n * 2);\
++ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++ 16)\
++ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
++}
++
++#define SQUASHFS_SWAP_INTS(s, d, n) {\
++ int entry;\
++ int bit_position;\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, n * 4);\
++ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++ 32)\
++ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
++}
++
++#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\
++ int entry;\
++ int bit_position;\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, n * 8);\
++ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++ 64)\
++ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\
++}
++
++#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
++ int entry;\
++ int bit_position;\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, n * bits / 8);\
++ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++ bits)\
++ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
++
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++
++struct squashfs_base_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned int type:4;
++ unsigned int offset:4;
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned short rdev;
++} __attribute__ ((packed));
++
++struct squashfs_symlink_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned short symlink_size;
++ char symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned int mtime;
++ unsigned int start_block;
++ unsigned int file_size:32;
++ unsigned short block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned int file_size:19;
++ unsigned int offset:13;
++ unsigned int mtime;
++ unsigned int start_block:24;
++} __attribute__ ((packed));
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
++ SQUASHFS_MEMSET(s, d, n);\
++ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++ SQUASHFS_SWAP((s)->uid, d, 16, 4);\
++ SQUASHFS_SWAP((s)->guid, d, 20, 4);
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_ipc_inode_header_1));\
++ SQUASHFS_SWAP((s)->type, d, 24, 4);\
++ SQUASHFS_SWAP((s)->offset, d, 28, 4);\
++}
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_dev_inode_header_1));\
++ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_symlink_inode_header_1));\
++ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_reg_inode_header_1));\
++ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_dir_inode_header_1));\
++ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
++ SQUASHFS_SWAP((s)->offset, d, 43, 13);\
++ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
++}
++
++#endif
++
++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++
++struct squashfs_dir_index_2 {
++ unsigned int index:27;
++ unsigned int start_block:29;
++ unsigned char size;
++ unsigned char name[0];
++} __attribute__ ((packed));
++
++struct squashfs_base_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned short rdev;
++} __attribute__ ((packed));
++
++struct squashfs_symlink_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned short symlink_size;
++ char symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned int mtime;
++ unsigned int start_block;
++ unsigned int fragment;
++ unsigned int offset;
++ unsigned int file_size:32;
++ unsigned short block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned int file_size:19;
++ unsigned int offset:13;
++ unsigned int mtime;
++ unsigned int start_block:24;
++} __attribute__ ((packed));
++
++struct squashfs_ldir_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned int file_size:27;
++ unsigned int offset:13;
++ unsigned int mtime;
++ unsigned int start_block:24;
++ unsigned int i_count:16;
++ struct squashfs_dir_index_2 index[0];
++} __attribute__ ((packed));
++
++union squashfs_inode_header_2 {
++ struct squashfs_base_inode_header_2 base;
++ struct squashfs_dev_inode_header_2 dev;
++ struct squashfs_symlink_inode_header_2 symlink;
++ struct squashfs_reg_inode_header_2 reg;
++ struct squashfs_dir_inode_header_2 dir;
++ struct squashfs_ldir_inode_header_2 ldir;
++ struct squashfs_ipc_inode_header_2 ipc;
++};
++
++struct squashfs_dir_header_2 {
++ unsigned int count:8;
++ unsigned int start_block:24;
++} __attribute__ ((packed));
++
++struct squashfs_dir_entry_2 {
++ unsigned int offset:13;
++ unsigned int type:3;
++ unsigned int size:8;
++ char name[0];
++} __attribute__ ((packed));
++
++struct squashfs_fragment_entry_2 {
++ unsigned int start_block;
++ unsigned int size;
++} __attribute__ ((packed));
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
++ SQUASHFS_MEMSET(s, d, n);\
++ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++ SQUASHFS_SWAP((s)->uid, d, 16, 8);\
++ SQUASHFS_SWAP((s)->guid, d, 24, 8);\
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
++ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_dev_inode_header_2)); \
++ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_symlink_inode_header_2));\
++ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_reg_inode_header_2));\
++ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
++ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
++ SQUASHFS_SWAP((s)->offset, d, 128, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_dir_inode_header_2));\
++ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
++ SQUASHFS_SWAP((s)->offset, d, 51, 13);\
++ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
++}
++
++#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_ldir_inode_header_2));\
++ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
++ SQUASHFS_SWAP((s)->offset, d, 59, 13);\
++ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
++ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
++ SQUASHFS_SWAP((s)->index, d, 0, 27);\
++ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
++ SQUASHFS_SWAP((s)->size, d, 56, 8);\
++}
++#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
++ SQUASHFS_SWAP((s)->count, d, 0, 8);\
++ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
++}
++
++#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
++ SQUASHFS_SWAP((s)->offset, d, 0, 13);\
++ SQUASHFS_SWAP((s)->type, d, 13, 3);\
++ SQUASHFS_SWAP((s)->size, d, 16, 8);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
++ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
++ SQUASHFS_SWAP((s)->size, d, 32, 32);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
++
++/* fragment and fragment table defines */
++#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2))
++
++#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \
++ SQUASHFS_METADATA_SIZE - 1) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\
++ sizeof(int))
++
++#endif
++
++#ifdef __KERNEL__
++
++/*
++ * macros used to swap each structure entry, taking into account
++ * bitfields and different bitfield placing conventions on differing
++ * architectures
++ */
++
++#include <asm/byteorder.h>
++
++#ifdef __BIG_ENDIAN
++ /* convert from little endian to big endian */
++#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
++ tbits, b_pos)
++#else
++ /* convert from big endian to little endian */
++#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
++ tbits, 64 - tbits - b_pos)
++#endif
++
++#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
++ b_pos = pos % 8;\
++ val = 0;\
++ s = (unsigned char *)p + (pos / 8);\
++ d = ((unsigned char *) &val) + 7;\
++ for(bits = 0; bits < (tbits + b_pos); bits += 8) \
++ *d-- = *s++;\
++ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
++}
++
++#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n);
++
++#endif
++#endif
+diff --new-file -urp linux-2.6.15/include/linux/squashfs_fs_i.h linux-2.6.15-squashfs3.0/include/linux/squashfs_fs_i.h
+--- linux-2.6.15/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-squashfs3.0/include/linux/squashfs_fs_i.h 2006-03-07 21:12:37.000000000 +0000
+@@ -0,0 +1,45 @@
++#ifndef SQUASHFS_FS_I
++#define SQUASHFS_FS_I
++/*
++ * Squashfs
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs_fs_i.h
++ */
++
++struct squashfs_inode_info {
++ long long start_block;
++ unsigned int offset;
++ union {
++ struct {
++ long long fragment_start_block;
++ unsigned int fragment_size;
++ unsigned int fragment_offset;
++ long long block_list_start;
++ } s1;
++ struct {
++ long long directory_index_start;
++ unsigned int directory_index_offset;
++ unsigned int directory_index_count;
++ unsigned int parent_inode;
++ } s2;
++ } u;
++ struct inode vfs_inode;
++};
++#endif
+diff --new-file -urp linux-2.6.15/include/linux/squashfs_fs_sb.h linux-2.6.15-squashfs3.0/include/linux/squashfs_fs_sb.h
+--- linux-2.6.15/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-squashfs3.0/include/linux/squashfs_fs_sb.h 2006-03-07 21:12:37.000000000 +0000
+@@ -0,0 +1,74 @@
++#ifndef SQUASHFS_FS_SB
++#define SQUASHFS_FS_SB
++/*
++ * Squashfs
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs_fs_sb.h
++ */
++
++#include <linux/squashfs_fs.h>
++
++struct squashfs_cache {
++ long long block;
++ int length;
++ long long next_index;
++ char *data;
++};
++
++struct squashfs_fragment_cache {
++ long long block;
++ int length;
++ unsigned int locked;
++ char *data;
++};
++
++struct squashfs_sb_info {
++ struct squashfs_super_block sblk;
++ int devblksize;
++ int devblksize_log2;
++ int swap;
++ struct squashfs_cache *block_cache;
++ struct squashfs_fragment_cache *fragment;
++ int next_cache;
++ int next_fragment;
++ int next_meta_index;
++ unsigned int *uid;
++ unsigned int *guid;
++ long long *fragment_index;
++ unsigned int *fragment_index_2;
++ unsigned int read_size;
++ char *read_data;
++ char *read_page;
++ struct semaphore read_data_mutex;
++ struct semaphore read_page_mutex;
++ struct semaphore block_cache_mutex;
++ struct semaphore fragment_mutex;
++ struct semaphore meta_index_mutex;
++ wait_queue_head_t waitq;
++ wait_queue_head_t fragment_wait_queue;
++ struct meta_index *meta_index;
++ struct inode *(*iget)(struct super_block *s, squashfs_inode_t \
++ inode);
++ long long (*read_blocklist)(struct inode *inode, int \
++ index, int readahead_blks, char *block_list, \
++ unsigned short **block_p, unsigned int *bsize);
++ int (*read_fragment_index_table)(struct super_block *s);
++};
++#endif
+diff --new-file -urp linux-2.6.15/init/do_mounts_rd.c linux-2.6.15-squashfs3.0/init/do_mounts_rd.c
+--- linux-2.6.15/init/do_mounts_rd.c 2006-03-01 22:37:27.000000000 +0000
++++ linux-2.6.15-squashfs3.0/init/do_mounts_rd.c 2006-03-07 21:12:37.000000000 +0000
+@@ -5,6 +5,7 @@
+ #include <linux/ext2_fs.h>
+ #include <linux/romfs_fs.h>
+ #include <linux/cramfs_fs.h>
++#include <linux/squashfs_fs.h>
+ #include <linux/initrd.h>
+ #include <linux/string.h>
+
+@@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in
+ * numbers could not be found.
+ *
+ * We currently check for the following magic numbers:
++ * squashfs
+ * minix
+ * ext2
+ * romfs
+@@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start
+ struct ext2_super_block *ext2sb;
+ struct romfs_super_block *romfsb;
+ struct cramfs_super *cramfsb;
++ struct squashfs_super_block *squashfsb;
+ int nblocks = -1;
+ unsigned char *buf;
+
+@@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start
+ ext2sb = (struct ext2_super_block *) buf;
+ romfsb = (struct romfs_super_block *) buf;
+ cramfsb = (struct cramfs_super *) buf;
++ squashfsb = (struct squashfs_super_block *) buf;
+ memset(buf, 0xe5, size);
+
+ /*
+@@ -101,6 +105,15 @@ identify_ramdisk_image(int fd, int start
+ goto done;
+ }
+
++ /* squashfs is at block zero too */
++ if (squashfsb->s_magic == SQUASHFS_MAGIC) {
++ printk(KERN_NOTICE
++ "RAMDISK: squashfs filesystem found at block %d\n",
++ start_block);
++ nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
++ goto done;
++ }
++
+ /*
+ * Read block 1 to test for minix and ext2 superblock
+ */
diff --git a/target/linux/generic-2.6/patches/002-squashfs_lzma.patch b/target/linux/generic-2.6/patches/002-squashfs_lzma.patch
new file mode 100644
index 0000000000..a166e84971
--- /dev/null
+++ b/target/linux/generic-2.6/patches/002-squashfs_lzma.patch
@@ -0,0 +1,886 @@
+diff -Nur linux-2.6.16/fs/squashfs/inode.c linux-2.6.16-owrt/fs/squashfs/inode.c
+--- linux-2.6.16/fs/squashfs/inode.c 2006-03-21 10:55:59.000000000 +0100
++++ linux-2.6.16-owrt/fs/squashfs/inode.c 2006-03-21 12:24:37.000000000 +0100
+@@ -4,6 +4,9 @@
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
+ *
++ * LZMA decompressor support added by Oleg I. Vdovikin
++ * Copyright (c) 2005 Oleg I.Vdovikin <oleg@cs.msu.su>
++ *
+ * 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,
+@@ -21,6 +24,7 @@
+ * inode.c
+ */
+
++#define SQUASHFS_LZMA
+ #include <linux/types.h>
+ #include <linux/squashfs_fs.h>
+ #include <linux/module.h>
+@@ -44,6 +48,19 @@
+
+ #include "squashfs.h"
+
++#ifdef SQUASHFS_LZMA
++#include "LzmaDecode.h"
++
++/* default LZMA settings, should be in sync with mksquashfs */
++#define LZMA_LC 3
++#define LZMA_LP 0
++#define LZMA_PB 2
++
++#define LZMA_WORKSPACE_SIZE ((LZMA_BASE_SIZE + \
++ (LZMA_LIT_SIZE << (LZMA_LC + LZMA_LP))) * sizeof(CProb))
++
++#endif
++
+ static void squashfs_put_super(struct super_block *);
+ static int squashfs_statfs(struct super_block *, struct kstatfs *);
+ static int squashfs_symlink_readpage(struct file *file, struct page *page);
+@@ -64,7 +81,11 @@
+ const char *, void *);
+
+
++#ifdef SQUASHFS_LZMA
++static unsigned char lzma_workspace[LZMA_WORKSPACE_SIZE];
++#else
+ static z_stream stream;
++#endif
+
+ static struct file_system_type squashfs_fs_type = {
+ .owner = THIS_MODULE,
+@@ -249,6 +270,15 @@
+ if (compressed) {
+ int zlib_err;
+
++#ifdef SQUASHFS_LZMA
++ if ((zlib_err = LzmaDecode(lzma_workspace,
++ LZMA_WORKSPACE_SIZE, LZMA_LC, LZMA_LP, LZMA_PB,
++ c_buffer, c_byte, buffer, msblk->read_size, &bytes)) != LZMA_RESULT_OK)
++ {
++ ERROR("lzma returned unexpected result 0x%x\n", zlib_err);
++ bytes = 0;
++ }
++#else
+ stream.next_in = c_buffer;
+ stream.avail_in = c_byte;
+ stream.next_out = buffer;
+@@ -263,6 +293,7 @@
+ bytes = 0;
+ } else
+ bytes = stream.total_out;
++#endif
+
+ up(&msblk->read_data_mutex);
+ }
+@@ -2046,15 +2077,19 @@
+ printk(KERN_INFO "squashfs: version 3.0 (2006/03/15) "
+ "Phillip Lougher\n");
+
++#ifndef SQUASHFS_LZMA
+ if (!(stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
+ ERROR("Failed to allocate zlib workspace\n");
+ destroy_inodecache();
+ err = -ENOMEM;
+ goto out;
+ }
++#endif
+
+ if ((err = register_filesystem(&squashfs_fs_type))) {
++#ifndef SQUASHFS_LZMA
+ vfree(stream.workspace);
++#endif
+ destroy_inodecache();
+ }
+
+@@ -2065,7 +2100,9 @@
+
+ static void __exit exit_squashfs_fs(void)
+ {
++#ifndef SQUASHFS_LZMA
+ vfree(stream.workspace);
++#endif
+ unregister_filesystem(&squashfs_fs_type);
+ destroy_inodecache();
+ }
+diff -Nur linux-2.6.16/fs/squashfs/LzmaDecode.c linux-2.6.16-owrt/fs/squashfs/LzmaDecode.c
+--- linux-2.6.16/fs/squashfs/LzmaDecode.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/fs/squashfs/LzmaDecode.c 2006-03-21 10:56:57.000000000 +0100
+@@ -0,0 +1,663 @@
++/*
++ LzmaDecode.c
++ LZMA Decoder
++
++ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
++ http://www.7-zip.org/
++
++ LZMA SDK is licensed under two licenses:
++ 1) GNU Lesser General Public License (GNU LGPL)
++ 2) Common Public License (CPL)
++ It means that you can select one of these two licenses and
++ follow rules of that license.
++
++ SPECIAL EXCEPTION:
++ Igor Pavlov, as the author of this code, expressly permits you to
++ statically or dynamically link your code (or bind by name) to the
++ interfaces of this file without subjecting your linked code to the
++ terms of the CPL or GNU LGPL. Any modifications or additions
++ to this file, however, are subject to the LGPL or CPL terms.
++*/
++
++#include "LzmaDecode.h"
++
++#ifndef Byte
++#define Byte unsigned char
++#endif
++
++#define kNumTopBits 24
++#define kTopValue ((UInt32)1 << kNumTopBits)
++
++#define kNumBitModelTotalBits 11
++#define kBitModelTotal (1 << kNumBitModelTotalBits)
++#define kNumMoveBits 5
++
++typedef struct _CRangeDecoder
++{
++ Byte *Buffer;
++ Byte *BufferLim;
++ UInt32 Range;
++ UInt32 Code;
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *InCallback;
++ int Result;
++ #endif
++ int ExtraBytes;
++} CRangeDecoder;
++
++Byte RangeDecoderReadByte(CRangeDecoder *rd)
++{
++ if (rd->Buffer == rd->BufferLim)
++ {
++ #ifdef _LZMA_IN_CB
++ UInt32 size;
++ rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
++ rd->BufferLim = rd->Buffer + size;
++ if (size == 0)
++ #endif
++ {
++ rd->ExtraBytes = 1;
++ return 0xFF;
++ }
++ }
++ return (*rd->Buffer++);
++}
++
++/* #define ReadByte (*rd->Buffer++) */
++#define ReadByte (RangeDecoderReadByte(rd))
++
++void RangeDecoderInit(CRangeDecoder *rd,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *inCallback
++ #else
++ Byte *stream, UInt32 bufferSize
++ #endif
++ )
++{
++ int i;
++ #ifdef _LZMA_IN_CB
++ rd->InCallback = inCallback;
++ rd->Buffer = rd->BufferLim = 0;
++ #else
++ rd->Buffer = stream;
++ rd->BufferLim = stream + bufferSize;
++ #endif
++ rd->ExtraBytes = 0;
++ rd->Code = 0;
++ rd->Range = (0xFFFFFFFF);
++ for(i = 0; i < 5; i++)
++ rd->Code = (rd->Code << 8) | ReadByte;
++}
++
++#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;
++#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
++#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
++
++UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
++{
++ RC_INIT_VAR
++ UInt32 result = 0;
++ int i;
++ for (i = numTotalBits; i > 0; i--)
++ {
++ /* UInt32 t; */
++ range >>= 1;
++
++ result <<= 1;
++ if (code >= range)
++ {
++ code -= range;
++ result |= 1;
++ }
++ /*
++ t = (code - range) >> 31;
++ t &= 1;
++ code -= range & (t - 1);
++ result = (result + result) | (1 - t);
++ */
++ RC_NORMALIZE
++ }
++ RC_FLUSH_VAR
++ return result;
++}
++
++int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
++{
++ UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
++ if (rd->Code < bound)
++ {
++ rd->Range = bound;
++ *prob += (kBitModelTotal - *prob) >> kNumMoveBits;
++ if (rd->Range < kTopValue)
++ {
++ rd->Code = (rd->Code << 8) | ReadByte;
++ rd->Range <<= 8;
++ }
++ return 0;
++ }
++ else
++ {
++ rd->Range -= bound;
++ rd->Code -= bound;
++ *prob -= (*prob) >> kNumMoveBits;
++ if (rd->Range < kTopValue)
++ {
++ rd->Code = (rd->Code << 8) | ReadByte;
++ rd->Range <<= 8;
++ }
++ return 1;
++ }
++}
++
++#define RC_GET_BIT2(prob, mi, A0, A1) \
++ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
++ if (code < bound) \
++ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
++ else \
++ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
++ RC_NORMALIZE
++
++#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
++
++int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
++{
++ int mi = 1;
++ int i;
++ #ifdef _LZMA_LOC_OPT
++ RC_INIT_VAR
++ #endif
++ for(i = numLevels; i > 0; i--)
++ {
++ #ifdef _LZMA_LOC_OPT
++ CProb *prob = probs + mi;
++ RC_GET_BIT(prob, mi)
++ #else
++ mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
++ #endif
++ }
++ #ifdef _LZMA_LOC_OPT
++ RC_FLUSH_VAR
++ #endif
++ return mi - (1 << numLevels);
++}
++
++int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
++{
++ int mi = 1;
++ int i;
++ int symbol = 0;
++ #ifdef _LZMA_LOC_OPT
++ RC_INIT_VAR
++ #endif
++ for(i = 0; i < numLevels; i++)
++ {
++ #ifdef _LZMA_LOC_OPT
++ CProb *prob = probs + mi;
++ RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
++ #else
++ int bit = RangeDecoderBitDecode(probs + mi, rd);
++ mi = mi + mi + bit;
++ symbol |= (bit << i);
++ #endif
++ }
++ #ifdef _LZMA_LOC_OPT
++ RC_FLUSH_VAR
++ #endif
++ return symbol;
++}
++
++Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
++{
++ int symbol = 1;
++ #ifdef _LZMA_LOC_OPT
++ RC_INIT_VAR
++ #endif
++ do
++ {
++ #ifdef _LZMA_LOC_OPT
++ CProb *prob = probs + symbol;
++ RC_GET_BIT(prob, symbol)
++ #else
++ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
++ #endif
++ }
++ while (symbol < 0x100);
++ #ifdef _LZMA_LOC_OPT
++ RC_FLUSH_VAR
++ #endif
++ return symbol;
++}
++
++Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
++{
++ int symbol = 1;
++ #ifdef _LZMA_LOC_OPT
++ RC_INIT_VAR
++ #endif
++ do
++ {
++ int bit;
++ int matchBit = (matchByte >> 7) & 1;
++ matchByte <<= 1;
++ #ifdef _LZMA_LOC_OPT
++ {
++ CProb *prob = probs + ((1 + matchBit) << 8) + symbol;
++ RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
++ }
++ #else
++ bit = RangeDecoderBitDecode(probs + ((1 + matchBit) << 8) + symbol, rd);
++ symbol = (symbol << 1) | bit;
++ #endif
++ if (matchBit != bit)
++ {
++ while (symbol < 0x100)
++ {
++ #ifdef _LZMA_LOC_OPT
++ CProb *prob = probs + symbol;
++ RC_GET_BIT(prob, symbol)
++ #else
++ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
++ #endif
++ }
++ break;
++ }
++ }
++ while (symbol < 0x100);
++ #ifdef _LZMA_LOC_OPT
++ RC_FLUSH_VAR
++ #endif
++ return symbol;
++}
++
++#define kNumPosBitsMax 4
++#define kNumPosStatesMax (1 << kNumPosBitsMax)
++
++#define kLenNumLowBits 3
++#define kLenNumLowSymbols (1 << kLenNumLowBits)
++#define kLenNumMidBits 3
++#define kLenNumMidSymbols (1 << kLenNumMidBits)
++#define kLenNumHighBits 8
++#define kLenNumHighSymbols (1 << kLenNumHighBits)
++
++#define LenChoice 0
++#define LenChoice2 (LenChoice + 1)
++#define LenLow (LenChoice2 + 1)
++#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
++#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
++#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
++
++int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
++{
++ if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
++ return RangeDecoderBitTreeDecode(p + LenLow +
++ (posState << kLenNumLowBits), kLenNumLowBits, rd);
++ if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
++ return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
++ (posState << kLenNumMidBits), kLenNumMidBits, rd);
++ return kLenNumLowSymbols + kLenNumMidSymbols +
++ RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
++}
++
++#define kNumStates 12
++
++#define kStartPosModelIndex 4
++#define kEndPosModelIndex 14
++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
++
++#define kNumPosSlotBits 6
++#define kNumLenToPosStates 4
++
++#define kNumAlignBits 4
++#define kAlignTableSize (1 << kNumAlignBits)
++
++#define kMatchMinLen 2
++
++#define IsMatch 0
++#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
++#define IsRepG0 (IsRep + kNumStates)
++#define IsRepG1 (IsRepG0 + kNumStates)
++#define IsRepG2 (IsRepG1 + kNumStates)
++#define IsRep0Long (IsRepG2 + kNumStates)
++#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
++#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
++#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
++#define LenCoder (Align + kAlignTableSize)
++#define RepLenCoder (LenCoder + kNumLenProbs)
++#define Literal (RepLenCoder + kNumLenProbs)
++
++#if Literal != LZMA_BASE_SIZE
++StopCompilingDueBUG
++#endif
++
++#ifdef _LZMA_OUT_READ
++
++typedef struct _LzmaVarState
++{
++ CRangeDecoder RangeDecoder;
++ Byte *Dictionary;
++ UInt32 DictionarySize;
++ UInt32 DictionaryPos;
++ UInt32 GlobalPos;
++ UInt32 Reps[4];
++ int lc;
++ int lp;
++ int pb;
++ int State;
++ int PreviousIsMatch;
++ int RemainLen;
++} LzmaVarState;
++
++int LzmaDecoderInit(
++ unsigned char *buffer, UInt32 bufferSize,
++ int lc, int lp, int pb,
++ unsigned char *dictionary, UInt32 dictionarySize,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *inCallback
++ #else
++ unsigned char *inStream, UInt32 inSize
++ #endif
++ )
++{
++ LzmaVarState *vs = (LzmaVarState *)buffer;
++ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
++ UInt32 i;
++ if (bufferSize < numProbs * sizeof(CProb) + sizeof(LzmaVarState))
++ return LZMA_RESULT_NOT_ENOUGH_MEM;
++ vs->Dictionary = dictionary;
++ vs->DictionarySize = dictionarySize;
++ vs->DictionaryPos = 0;
++ vs->GlobalPos = 0;
++ vs->Reps[0] = vs->Reps[1] = vs->Reps[2] = vs->Reps[3] = 1;
++ vs->lc = lc;
++ vs->lp = lp;
++ vs->pb = pb;
++ vs->State = 0;
++ vs->PreviousIsMatch = 0;
++ vs->RemainLen = 0;
++ dictionary[dictionarySize - 1] = 0;
++ for (i = 0; i < numProbs; i++)
++ p[i] = kBitModelTotal >> 1;
++ RangeDecoderInit(&vs->RangeDecoder,
++ #ifdef _LZMA_IN_CB
++ inCallback
++ #else
++ inStream, inSize
++ #endif
++ );
++ return LZMA_RESULT_OK;
++}
++
++int LzmaDecode(unsigned char *buffer,
++ unsigned char *outStream, UInt32 outSize,
++ UInt32 *outSizeProcessed)
++{
++ LzmaVarState *vs = (LzmaVarState *)buffer;
++ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
++ CRangeDecoder rd = vs->RangeDecoder;
++ int state = vs->State;
++ int previousIsMatch = vs->PreviousIsMatch;
++ Byte previousByte;
++ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
++ UInt32 nowPos = 0;
++ UInt32 posStateMask = (1 << (vs->pb)) - 1;
++ UInt32 literalPosMask = (1 << (vs->lp)) - 1;
++ int lc = vs->lc;
++ int len = vs->RemainLen;
++ UInt32 globalPos = vs->GlobalPos;
++
++ Byte *dictionary = vs->Dictionary;
++ UInt32 dictionarySize = vs->DictionarySize;
++ UInt32 dictionaryPos = vs->DictionaryPos;
++
++ if (len == -1)
++ {
++ *outSizeProcessed = 0;
++ return LZMA_RESULT_OK;
++ }
++
++ while(len > 0 && nowPos < outSize)
++ {
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ len--;
++ }
++ if (dictionaryPos == 0)
++ previousByte = dictionary[dictionarySize - 1];
++ else
++ previousByte = dictionary[dictionaryPos - 1];
++#else
++
++int LzmaDecode(
++ Byte *buffer, UInt32 bufferSize,
++ int lc, int lp, int pb,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *inCallback,
++ #else
++ unsigned char *inStream, UInt32 inSize,
++ #endif
++ unsigned char *outStream, UInt32 outSize,
++ UInt32 *outSizeProcessed)
++{
++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
++ CProb *p = (CProb *)buffer;
++ CRangeDecoder rd;
++ UInt32 i;
++ int state = 0;
++ int previousIsMatch = 0;
++ Byte previousByte = 0;
++ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
++ UInt32 nowPos = 0;
++ UInt32 posStateMask = (1 << pb) - 1;
++ UInt32 literalPosMask = (1 << lp) - 1;
++ int len = 0;
++ if (bufferSize < numProbs * sizeof(CProb))
++ return LZMA_RESULT_NOT_ENOUGH_MEM;
++ for (i = 0; i < numProbs; i++)
++ p[i] = kBitModelTotal >> 1;
++ RangeDecoderInit(&rd,
++ #ifdef _LZMA_IN_CB
++ inCallback
++ #else
++ inStream, inSize
++ #endif
++ );
++#endif
++
++ *outSizeProcessed = 0;
++ while(nowPos < outSize)
++ {
++ int posState = (int)(
++ (nowPos
++ #ifdef _LZMA_OUT_READ
++ + globalPos
++ #endif
++ )
++ & posStateMask);
++ #ifdef _LZMA_IN_CB
++ if (rd.Result != LZMA_RESULT_OK)
++ return rd.Result;
++ #endif
++ if (rd.ExtraBytes != 0)
++ return LZMA_RESULT_DATA_ERROR;
++ if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
++ {
++ CProb *probs = p + Literal + (LZMA_LIT_SIZE *
++ (((
++ (nowPos
++ #ifdef _LZMA_OUT_READ
++ + globalPos
++ #endif
++ )
++ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
++
++ if (state < 4) state = 0;
++ else if (state < 10) state -= 3;
++ else state -= 6;
++ if (previousIsMatch)
++ {
++ Byte matchByte;
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ matchByte = dictionary[pos];
++ #else
++ matchByte = outStream[nowPos - rep0];
++ #endif
++ previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
++ previousIsMatch = 0;
++ }
++ else
++ previousByte = LzmaLiteralDecode(probs, &rd);
++ outStream[nowPos++] = previousByte;
++ #ifdef _LZMA_OUT_READ
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #endif
++ }
++ else
++ {
++ previousIsMatch = 1;
++ if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
++ {
++ if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
++ {
++ if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
++ {
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos;
++ #endif
++ if (
++ (nowPos
++ #ifdef _LZMA_OUT_READ
++ + globalPos
++ #endif
++ )
++ == 0)
++ return LZMA_RESULT_DATA_ERROR;
++ state = state < 7 ? 9 : 11;
++ #ifdef _LZMA_OUT_READ
++ pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ previousByte = dictionary[pos];
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #else
++ previousByte = outStream[nowPos - rep0];
++ #endif
++ outStream[nowPos++] = previousByte;
++ continue;
++ }
++ }
++ else
++ {
++ UInt32 distance;
++ if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
++ distance = rep1;
++ else
++ {
++ if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
++ distance = rep2;
++ else
++ {
++ distance = rep3;
++ rep3 = rep2;
++ }
++ rep2 = rep1;
++ }
++ rep1 = rep0;
++ rep0 = distance;
++ }
++ len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
++ state = state < 7 ? 8 : 11;
++ }
++ else
++ {
++ int posSlot;
++ rep3 = rep2;
++ rep2 = rep1;
++ rep1 = rep0;
++ state = state < 7 ? 7 : 10;
++ len = LzmaLenDecode(p + LenCoder, &rd, posState);
++ posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
++ kNumPosSlotBits), kNumPosSlotBits, &rd);
++ if (posSlot >= kStartPosModelIndex)
++ {
++ int numDirectBits = ((posSlot >> 1) - 1);
++ rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
++ if (posSlot < kEndPosModelIndex)
++ {
++ rep0 += RangeDecoderReverseBitTreeDecode(
++ p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
++ }
++ else
++ {
++ rep0 += RangeDecoderDecodeDirectBits(&rd,
++ numDirectBits - kNumAlignBits) << kNumAlignBits;
++ rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
++ }
++ }
++ else
++ rep0 = posSlot;
++ rep0++;
++ }
++ if (rep0 == (UInt32)(0))
++ {
++ /* it's for stream version */
++ len = -1;
++ break;
++ }
++ if (rep0 > nowPos
++ #ifdef _LZMA_OUT_READ
++ + globalPos
++ #endif
++ )
++ {
++ return LZMA_RESULT_DATA_ERROR;
++ }
++ len += kMatchMinLen;
++ do
++ {
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ previousByte = dictionary[pos];
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #else
++ previousByte = outStream[nowPos - rep0];
++ #endif
++ outStream[nowPos++] = previousByte;
++ len--;
++ }
++ while(len > 0 && nowPos < outSize);
++ }
++ }
++
++ #ifdef _LZMA_OUT_READ
++ vs->RangeDecoder = rd;
++ vs->DictionaryPos = dictionaryPos;
++ vs->GlobalPos = globalPos + nowPos;
++ vs->Reps[0] = rep0;
++ vs->Reps[1] = rep1;
++ vs->Reps[2] = rep2;
++ vs->Reps[3] = rep3;
++ vs->State = state;
++ vs->PreviousIsMatch = previousIsMatch;
++ vs->RemainLen = len;
++ #endif
++
++ *outSizeProcessed = nowPos;
++ return LZMA_RESULT_OK;
++}
+diff -Nur linux-2.6.16/fs/squashfs/LzmaDecode.h linux-2.6.16-owrt/fs/squashfs/LzmaDecode.h
+--- linux-2.6.16/fs/squashfs/LzmaDecode.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/fs/squashfs/LzmaDecode.h 2006-03-21 10:56:57.000000000 +0100
+@@ -0,0 +1,100 @@
++/*
++ LzmaDecode.h
++ LZMA Decoder interface
++
++ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
++ http://www.7-zip.org/
++
++ LZMA SDK is licensed under two licenses:
++ 1) GNU Lesser General Public License (GNU LGPL)
++ 2) Common Public License (CPL)
++ It means that you can select one of these two licenses and
++ follow rules of that license.
++
++ SPECIAL EXCEPTION:
++ Igor Pavlov, as the author of this code, expressly permits you to
++ statically or dynamically link your code (or bind by name) to the
++ interfaces of this file without subjecting your linked code to the
++ terms of the CPL or GNU LGPL. Any modifications or additions
++ to this file, however, are subject to the LGPL or CPL terms.
++*/
++
++#ifndef __LZMADECODE_H
++#define __LZMADECODE_H
++
++/* #define _LZMA_IN_CB */
++/* Use callback for input data */
++
++/* #define _LZMA_OUT_READ */
++/* Use read function for output data */
++
++/* #define _LZMA_PROB32 */
++/* It can increase speed on some 32-bit CPUs,
++ but memory usage will be doubled in that case */
++
++/* #define _LZMA_LOC_OPT */
++/* Enable local speed optimizations inside code */
++
++#ifndef UInt32
++#ifdef _LZMA_UINT32_IS_ULONG
++#define UInt32 unsigned long
++#else
++#define UInt32 unsigned int
++#endif
++#endif
++
++#ifdef _LZMA_PROB32
++#define CProb UInt32
++#else
++#define CProb unsigned short
++#endif
++
++#define LZMA_RESULT_OK 0
++#define LZMA_RESULT_DATA_ERROR 1
++#define LZMA_RESULT_NOT_ENOUGH_MEM 2
++
++#ifdef _LZMA_IN_CB
++typedef struct _ILzmaInCallback
++{
++ int (*Read)(void *object, unsigned char **buffer, UInt32 *bufferSize);
++} ILzmaInCallback;
++#endif
++
++#define LZMA_BASE_SIZE 1846
++#define LZMA_LIT_SIZE 768
++
++/*
++bufferSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)))* sizeof(CProb)
++bufferSize += 100 in case of _LZMA_OUT_READ
++by default CProb is unsigned short,
++but if specify _LZMA_PROB_32, CProb will be UInt32(unsigned int)
++*/
++
++#ifdef _LZMA_OUT_READ
++int LzmaDecoderInit(
++ unsigned char *buffer, UInt32 bufferSize,
++ int lc, int lp, int pb,
++ unsigned char *dictionary, UInt32 dictionarySize,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *inCallback
++ #else
++ unsigned char *inStream, UInt32 inSize
++ #endif
++);
++#endif
++
++int LzmaDecode(
++ unsigned char *buffer,
++ #ifndef _LZMA_OUT_READ
++ UInt32 bufferSize,
++ int lc, int lp, int pb,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *inCallback,
++ #else
++ unsigned char *inStream, UInt32 inSize,
++ #endif
++ #endif
++ unsigned char *outStream, UInt32 outSize,
++ UInt32 *outSizeProcessed);
++
++#endif
+diff -Nur linux-2.6.16/fs/squashfs/Makefile linux-2.6.16-owrt/fs/squashfs/Makefile
+--- linux-2.6.16/fs/squashfs/Makefile 2006-03-21 10:55:59.000000000 +0100
++++ linux-2.6.16-owrt/fs/squashfs/Makefile 2006-03-21 10:57:08.000000000 +0100
+@@ -5,3 +5,4 @@
+ obj-$(CONFIG_SQUASHFS) += squashfs.o
+ squashfs-y += inode.o
+ squashfs-y += squashfs2_0.o
++squashfs-y += LzmaDecode.o
diff --git a/target/linux/generic-2.6/patches/004-extra_optimization.patch b/target/linux/generic-2.6/patches/004-extra_optimization.patch
new file mode 100644
index 0000000000..805d2f0ea9
--- /dev/null
+++ b/target/linux/generic-2.6/patches/004-extra_optimization.patch
@@ -0,0 +1,12 @@
+--- linux-2.6.12.5/Makefile.old 2005-10-23 22:56:29.017270000 +0200
++++ linux-2.6.12.5/Makefile 2005-10-23 22:57:23.226138500 +0200
+@@ -533,6 +533,9 @@
+ NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
+ CHECKFLAGS += $(NOSTDINC_FLAGS)
+
++# improve gcc optimization
++CFLAGS += $(call cc-option,-funit-at-a-time,)
++
+ # warn about C99 declaration after statement
+ CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
+
diff --git a/target/linux/generic-2.6/patches/005-gcc4_fix.patch b/target/linux/generic-2.6/patches/005-gcc4_fix.patch
new file mode 100644
index 0000000000..99489b94b3
--- /dev/null
+++ b/target/linux/generic-2.6/patches/005-gcc4_fix.patch
@@ -0,0 +1,221 @@
+diff -ruN linux-2.6.15.1/include/asm-ppc/libgcc.h linux-2.6.15.1-openwrt/include/asm-ppc/libgcc.h
+--- linux-2.6.15.1/include/asm-ppc/libgcc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15.1-openwrt/include/asm-ppc/libgcc.h 2006-02-01 15:47:53.000000000 +0100
+@@ -0,0 +1,8 @@
++#ifndef __ASM_LIBGCC_H
++#define __ASM_LIBGCC_H
++
++#undef ARCH_NEEDS_ashldi3
++#undef ARCH_NEEDS_ashrdi3
++#undef ARCH_NEEDS_lshrdi3
++
++#endif /* __ASM_LIBGCC_H */
+diff -ruN linux-2.6.15.1/include/asm-i386/libgcc.h linux-2.6.15.1-openwrt/include/asm-i386/libgcc.h
+--- linux-2.6.15.1/include/asm-i386/libgcc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15.1-openwrt/include/asm-i386/libgcc.h 2006-02-01 15:47:53.000000000 +0100
+@@ -0,0 +1,8 @@
++#ifndef __ASM_LIBGCC_H
++#define __ASM_LIBGCC_H
++
++#undef ARCH_NEEDS_ashldi3
++#undef ARCH_NEEDS_ashrdi3
++#undef ARCH_NEEDS_lshrdi3
++
++#endif /* __ASM_LIBGCC_H */
+diff -ruN linux-2.6.15.1/include/asm-um/libgcc.h linux-2.6.15.1-openwrt/include/asm-i386/libgcc.h
+--- linux-2.6.15.1/include/asm-um/libgcc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15.1-openwrt/include/asm-um/libgcc.h 2006-02-01 15:47:53.000000000 +0100
+@@ -0,0 +1,8 @@
++#ifndef __ASM_LIBGCC_H
++#define __ASM_LIBGCC_H
++
++#undef ARCH_NEEDS_ashldi3
++#undef ARCH_NEEDS_ashrdi3
++#undef ARCH_NEEDS_lshrdi3
++
++#endif /* __ASM_LIBGCC_H */
+diff -Nur linux-2.6.15.1/include/asm-mips/libgcc.h linux-2.6.15.1-openwrt/include/asm-mips/libgcc.h
+--- linux-2.6.15.1/include/asm-mips/libgcc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15.1-openwrt/include/asm-mips/libgcc.h 2006-01-20 10:32:28.000000000 +0100
+@@ -0,0 +1,8 @@
++#ifndef __ASM_LIBGCC_H
++#define __ASM_LIBGCC_H
++
++#define ARCH_NEEDS_ashldi3
++#define ARCH_NEEDS_ashrdi3
++#define ARCH_NEEDS_lshrdi3
++
++#endif /* __ASM_LIBGCC_H */
+diff -Nur linux-2.6.15.1/include/linux/libgcc.h linux-2.6.15.1-openwrt/include/linux/libgcc.h
+--- linux-2.6.15.1/include/linux/libgcc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15.1-openwrt/include/linux/libgcc.h 2006-01-20 10:33:38.000000000 +0100
+@@ -0,0 +1,32 @@
++#ifndef __LINUX_LIBGCC_H
++#define __LINUX_LIBGCC_H
++
++#include <asm/byteorder.h>
++#include <asm/libgcc.h>
++
++typedef long long DWtype;
++typedef int Wtype;
++typedef unsigned int UWtype;
++typedef int word_type __attribute__ ((mode (__word__)));
++
++#define BITS_PER_UNIT 8
++
++#ifdef __BIG_ENDIAN
++struct DWstruct {
++ Wtype high, low;
++};
++#elif defined(__LITTLE_ENDIAN)
++struct DWstruct {
++ Wtype low, high;
++};
++#else
++#error I feel sick.
++#endif
++
++typedef union
++{
++ struct DWstruct s;
++ DWtype ll;
++} DWunion;
++
++#endif /* __LINUX_LIBGCC_H */
+diff -Nur linux-2.6.15.1/lib/ashldi3.c linux-2.6.15.1-openwrt/lib/ashldi3.c
+--- linux-2.6.15.1/lib/ashldi3.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15.1-openwrt/lib/ashldi3.c 2006-01-20 10:38:41.000000000 +0100
+@@ -0,0 +1,32 @@
++#include <linux/libgcc.h>
++#include <linux/module.h>
++
++#ifdef ARCH_NEEDS_ashldi3
++
++DWtype __ashldi3(DWtype u, word_type b)
++{
++ DWunion uu, w;
++ word_type bm;
++
++ if (b == 0)
++ return u;
++
++ uu.ll = u;
++ bm = (sizeof(Wtype) * BITS_PER_UNIT) - b;
++
++ if (bm <= 0) {
++ w.s.low = 0;
++ w.s.high = (UWtype) uu.s.low << -bm;
++ } else {
++ const UWtype carries = (UWtype) uu.s.low >> bm;
++
++ w.s.low = (UWtype) uu.s.low << b;
++ w.s.high = ((UWtype) uu.s.high << b) | carries;
++ }
++
++ return w.ll;
++}
++
++EXPORT_SYMBOL(__ashldi3);
++
++#endif /* ARCH_NEEDS_ashldi3 */
+diff -Nur linux-2.6.15.1/lib/ashrdi3.c linux-2.6.15.1-openwrt/lib/ashrdi3.c
+--- linux-2.6.15.1/lib/ashrdi3.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15.1-openwrt/lib/ashrdi3.c 2006-01-20 10:39:29.000000000 +0100
+@@ -0,0 +1,36 @@
++#include <linux/libgcc.h>
++#include <linux/module.h>
++
++/* Unless shift functions are defined with full ANSI prototypes,
++ parameter b will be promoted to int if word_type is smaller than an int. */
++#ifdef ARCH_NEEDS_ashrdi3
++
++DWtype __ashrdi3(DWtype u, word_type b)
++{
++ DWunion uu, w;
++ word_type bm;
++
++ if (b == 0)
++ return u;
++
++ uu.ll = u;
++ bm = (sizeof(Wtype) * BITS_PER_UNIT) - b;
++
++ if (bm <= 0) {
++ /* w.s.high = 1..1 or 0..0 */
++ w.s.high =
++ uu.s.high >> (sizeof(Wtype) * BITS_PER_UNIT - 1);
++ w.s.low = uu.s.high >> -bm;
++ } else {
++ const UWtype carries = (UWtype) uu.s.high << bm;
++
++ w.s.high = uu.s.high >> b;
++ w.s.low = ((UWtype) uu.s.low >> b) | carries;
++ }
++
++ return w.ll;
++}
++
++EXPORT_SYMBOL(__ashrdi3);
++
++#endif /* ARCH_NEEDS_ashrdi3 */
+diff -Nur linux-2.6.15.1/lib/lshrdi3.c linux-2.6.15.1-openwrt/lib/lshrdi3.c
+--- linux-2.6.15.1/lib/lshrdi3.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15.1-openwrt/lib/lshrdi3.c 2006-01-20 10:40:10.000000000 +0100
+@@ -0,0 +1,34 @@
++#include <linux/libgcc.h>
++#include <linux/module.h>
++
++/* Unless shift functions are defined with full ANSI prototypes,
++ parameter b will be promoted to int if word_type is smaller than an int. */
++#ifdef ARCH_NEEDS_lshrdi3
++
++DWtype __lshrdi3(DWtype u, word_type b)
++{
++ DWunion uu, w;
++ word_type bm;
++
++ if (b == 0)
++ return u;
++
++ uu.ll = u;
++ bm = (sizeof(Wtype) * BITS_PER_UNIT) - b;
++
++ if (bm <= 0) {
++ w.s.high = 0;
++ w.s.low = (UWtype) uu.s.high >> -bm;
++ } else {
++ const UWtype carries = (UWtype) uu.s.high << bm;
++
++ w.s.high = (UWtype) uu.s.high >> b;
++ w.s.low = ((UWtype) uu.s.low >> b) | carries;
++ }
++
++ return w.ll;
++}
++
++EXPORT_SYMBOL(__lshrdi3);
++
++#endif /* ARCH_NEEDS_lshrdi3 */
+diff -Nur linux-2.6.15.1/lib/Makefile linux-2.6.15.1-openwrt/lib/Makefile
+--- linux-2.6.15.1/lib/Makefile 2006-01-15 07:16:02.000000000 +0100
++++ linux-2.6.15.1-openwrt/lib/Makefile 2006-01-20 10:34:19.000000000 +0100
+@@ -8,6 +8,7 @@
+ sha1.o
+
+ lib-y += kobject.o kref.o kobject_uevent.o klist.o
++obj-y += ashldi3.o ashrdi3.o lshrdi3.o
+
+ obj-y += sort.o parser.o halfmd4.o
+
+diff -Nur linux-2.6.15.1/include/asm-arm/libgcc.h linux-2.6.15.1-openwrt/include/asm-arm/libgcc.h
+--- linux-2.6.15.1/include/asm-arm/libgcc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15.1-openwrt/include/asm-arm/libgcc.h 2006-04-12 23:01:18.000000000 +0200
+@@ -0,0 +1,8 @@
++#ifndef __ASM_LIBGCC_H
++#define __ASM_LIBGCC_H
++
++#undef ARCH_NEEDS_ashldi3
++#undef ARCH_NEEDS_ashrdi3
++#undef ARCH_NEEDS_lshrdi3
++
++#endif /* __ASM_LIBGCC_H */
diff --git a/target/linux/generic-2.6/patches/006-gcc4_inline_fix.patch b/target/linux/generic-2.6/patches/006-gcc4_inline_fix.patch
new file mode 100644
index 0000000000..e95663e382
--- /dev/null
+++ b/target/linux/generic-2.6/patches/006-gcc4_inline_fix.patch
@@ -0,0 +1,11 @@
+--- linux-2.6.15.1.old/include/asm-mips/system.h 2006-01-28 15:02:54.481032280 +0100
++++ linux-2.6.15.1.dev/include/asm-mips/system.h 2006-01-28 14:47:51.634285848 +0100
+@@ -273,7 +273,7 @@
+ if something tries to do an invalid xchg(). */
+ extern void __xchg_called_with_bad_pointer(void);
+
+-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
++static __always_inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+ {
+ switch (size) {
+ case 4:
diff --git a/target/linux/generic-2.6/patches/010-disable_old_squashfs_compatibility.patch b/target/linux/generic-2.6/patches/010-disable_old_squashfs_compatibility.patch
new file mode 100644
index 0000000000..1b8b61a8ea
--- /dev/null
+++ b/target/linux/generic-2.6/patches/010-disable_old_squashfs_compatibility.patch
@@ -0,0 +1,22 @@
+diff -Nur linux-2.6.16/fs/squashfs/Makefile linux-2.6.16-owrt/fs/squashfs/Makefile
+--- linux-2.6.16/fs/squashfs/Makefile 2006-03-21 13:50:31.000000000 +0100
++++ linux-2.6.16-owrt/fs/squashfs/Makefile 2006-03-21 13:51:09.000000000 +0100
+@@ -4,5 +4,4 @@
+
+ obj-$(CONFIG_SQUASHFS) += squashfs.o
+ squashfs-y += inode.o
+-squashfs-y += squashfs2_0.o
+ squashfs-y += LzmaDecode.o
+diff -Nur linux-2.6.16/fs/squashfs/squashfs.h linux-2.6.16-owrt/fs/squashfs/squashfs.h
+--- linux-2.6.16/fs/squashfs/squashfs.h 2006-03-21 10:55:59.000000000 +0100
++++ linux-2.6.16-owrt/fs/squashfs/squashfs.h 2006-03-21 13:50:58.000000000 +0100
+@@ -24,6 +24,9 @@
+ #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
+ #undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
+ #endif
++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++#undef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++#endif
+
+ #ifdef SQUASHFS_TRACE
+ #define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)
diff --git a/target/linux/generic-2.6/patches/011-mips_boot.patch b/target/linux/generic-2.6/patches/011-mips_boot.patch
new file mode 100644
index 0000000000..611c70d460
--- /dev/null
+++ b/target/linux/generic-2.6/patches/011-mips_boot.patch
@@ -0,0 +1,15 @@
+diff -Nur linux-cvs/arch/mips/kernel/head.S linux-aruba/arch/mips/kernel/head.S
+--- linux-cvs/arch/mips/kernel/head.S 2004-12-23 00:21:39.000000000 -0800
++++ linux-aruba/arch/mips/kernel/head.S 2005-10-20 09:16:08.000000000 -0700
+@@ -122,6 +122,10 @@
+ #endif
+ .endm
+
++
++ j kernel_entry
++ nop
++
+ /*
+ * Reserved space for exception handlers.
+ * Necessary for machines which link their kernels at KSEG0.
+
diff --git a/target/linux/generic-2.6/patches/100-netfilter_layer7_2.1nbd.patch b/target/linux/generic-2.6/patches/100-netfilter_layer7_2.1nbd.patch
new file mode 100644
index 0000000000..ec3929bf13
--- /dev/null
+++ b/target/linux/generic-2.6/patches/100-netfilter_layer7_2.1nbd.patch
@@ -0,0 +1,2071 @@
+diff -Nur linux-2.6.17/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.17-owrt/include/linux/netfilter_ipv4/ip_conntrack.h
+--- linux-2.6.17/include/linux/netfilter_ipv4/ip_conntrack.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/linux/netfilter_ipv4/ip_conntrack.h 2006-06-18 12:29:04.000000000 +0200
+@@ -124,6 +124,15 @@
+ /* Traversed often, so hopefully in different cacheline to top */
+ /* These are my tuples; original and reply */
+ struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
++
++#if defined(CONFIG_IP_NF_MATCH_LAYER7) || defined(CONFIG_IP_NF_MATCH_LAYER7_MODULE)
++ struct {
++ char * app_proto; /* e.g. "http". NULL before decision. "unknown" after decision if no match */
++ char * app_data; /* application layer data so far. NULL after match decision */
++ unsigned int app_data_len;
++ } layer7;
++#endif
++
+ };
+
+ struct ip_conntrack_expect
+diff -Nur linux-2.6.17/include/linux/netfilter_ipv4/ipt_layer7.h linux-2.6.17-owrt/include/linux/netfilter_ipv4/ipt_layer7.h
+--- linux-2.6.17/include/linux/netfilter_ipv4/ipt_layer7.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/linux/netfilter_ipv4/ipt_layer7.h 2006-06-18 12:29:04.000000000 +0200
+@@ -0,0 +1,27 @@
++/*
++ By Matthew Strait <quadong@users.sf.net>, Dec 2003.
++ 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
++*/
++
++#ifndef _IPT_LAYER7_H
++#define _IPT_LAYER7_H
++
++#define MAX_PATTERN_LEN 8192
++#define MAX_PROTOCOL_LEN 256
++
++typedef char *(*proc_ipt_search) (char *, char, char *);
++
++struct ipt_layer7_info {
++ char protocol[MAX_PROTOCOL_LEN];
++ char invert:1;
++ char pattern[MAX_PATTERN_LEN];
++ char pkt;
++};
++
++#endif /* _IPT_LAYER7_H */
+diff -Nur linux-2.6.17/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.17-owrt/net/ipv4/netfilter/ip_conntrack_core.c
+--- linux-2.6.17/net/ipv4/netfilter/ip_conntrack_core.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/net/ipv4/netfilter/ip_conntrack_core.c 2006-06-18 12:29:04.000000000 +0200
+@@ -339,6 +339,13 @@
+ * too. */
+ ip_ct_remove_expectations(ct);
+
++ #if defined(CONFIG_IP_NF_MATCH_LAYER7) || defined(CONFIG_IP_NF_MATCH_LAYER7_MODULE)
++ if(ct->layer7.app_proto)
++ kfree(ct->layer7.app_proto);
++ if(ct->layer7.app_data)
++ kfree(ct->layer7.app_data);
++ #endif
++
+ /* We overload first tuple to link into unconfirmed list. */
+ if (!is_confirmed(ct)) {
+ BUG_ON(list_empty(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list));
+diff -Nur linux-2.6.17/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.17-owrt/net/ipv4/netfilter/ip_conntrack_standalone.c
+--- linux-2.6.17/net/ipv4/netfilter/ip_conntrack_standalone.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/net/ipv4/netfilter/ip_conntrack_standalone.c 2006-06-18 12:29:04.000000000 +0200
+@@ -189,6 +189,12 @@
+ return -ENOSPC;
+ #endif
+
++#if defined(CONFIG_IP_NF_MATCH_LAYER7) || defined(CONFIG_IP_NF_MATCH_LAYER7_MODULE)
++ if(conntrack->layer7.app_proto)
++ if (seq_printf(s, "l7proto=%s ",conntrack->layer7.app_proto))
++ return 1;
++#endif
++
+ if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
+ return -ENOSPC;
+
+diff -Nur linux-2.6.17/net/ipv4/netfilter/ipt_layer7.c linux-2.6.17-owrt/net/ipv4/netfilter/ipt_layer7.c
+--- linux-2.6.17/net/ipv4/netfilter/ipt_layer7.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/net/ipv4/netfilter/ipt_layer7.c 2006-06-18 12:29:04.000000000 +0200
+@@ -0,0 +1,592 @@
++/*
++ Kernel module to match application layer (OSI layer 7)
++ data in connections.
++
++ http://l7-filter.sf.net
++
++ By Matthew Strait and Ethan Sommer, 2003-2005.
++
++ 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
++
++ Based on ipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>
++ and cls_layer7.c (C) 2003 Matthew Strait, Ethan Sommer, Justin Levandoski
++*/
++
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_conntrack.h>
++#include <linux/proc_fs.h>
++#include <linux/ctype.h>
++#include <net/ip.h>
++#include <net/tcp.h>
++#include <linux/spinlock.h>
++
++#include "regexp/regexp.c"
++
++#include <linux/netfilter_ipv4/ipt_layer7.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++
++MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("iptables application layer match module");
++MODULE_VERSION("2.0");
++
++static int maxdatalen = 2048; // this is the default
++module_param(maxdatalen, int, 0444);
++MODULE_PARM_DESC(maxdatalen, "maximum bytes of data looked at by l7-filter");
++
++#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
++ #define DPRINTK(format,args...) printk(format,##args)
++#else
++ #define DPRINTK(format,args...)
++#endif
++
++#define TOTAL_PACKETS master_conntrack->counters[IP_CT_DIR_ORIGINAL].packets + \
++ master_conntrack->counters[IP_CT_DIR_REPLY].packets
++
++/* Number of packets whose data we look at.
++This can be modified through /proc/net/layer7_numpackets */
++static int num_packets = 10;
++
++static struct pattern_cache {
++ char * regex_string;
++ regexp * pattern;
++ struct pattern_cache * next;
++} * first_pattern_cache = NULL;
++
++/* I'm new to locking. Here are my assumptions:
++
++- No one will write to /proc/net/layer7_numpackets over and over very fast;
++ if they did, nothing awful would happen.
++
++- This code will never be processing the same packet twice at the same time,
++ because iptables rules are traversed in order.
++
++- It doesn't matter if two packets from different connections are in here at
++ the same time, because they don't share any data.
++
++- It _does_ matter if two packets from the same connection are here at the same
++ time. In this case, we have to protect the conntracks and the list of
++ compiled patterns.
++*/
++DEFINE_RWLOCK(ct_lock);
++DEFINE_SPINLOCK(list_lock);
++
++#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
++/* Converts an unfriendly string into a friendly one by
++replacing unprintables with periods and all whitespace with " ". */
++static char * friendly_print(unsigned char * s)
++{
++ char * f = kmalloc(strlen(s) + 1, GFP_ATOMIC);
++ int i;
++
++ if(!f) {
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in friendly_print, bailing.\n");
++ return NULL;
++ }
++
++ for(i = 0; i < strlen(s); i++){
++ if(isprint(s[i]) && s[i] < 128) f[i] = s[i];
++ else if(isspace(s[i])) f[i] = ' ';
++ else f[i] = '.';
++ }
++ f[i] = '\0';
++ return f;
++}
++
++static char dec2hex(int i)
++{
++ switch (i) {
++ case 0 ... 9:
++ return (char)(i + '0');
++ break;
++ case 10 ... 15:
++ return (char)(i - 10 + 'a');
++ break;
++ default:
++ if (net_ratelimit())
++ printk("Problem in dec2hex\n");
++ return '\0';
++ }
++}
++
++static char * hex_print(unsigned char * s)
++{
++ char * g = kmalloc(strlen(s)*3 + 1, GFP_ATOMIC);
++ int i;
++
++ if(!g) {
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in hex_print, bailing.\n");
++ return NULL;
++ }
++
++ for(i = 0; i < strlen(s); i++) {
++ g[i*3 ] = dec2hex(s[i]/16);
++ g[i*3 + 1] = dec2hex(s[i]%16);
++ g[i*3 + 2] = ' ';
++ }
++ g[i*3] = '\0';
++
++ return g;
++}
++#endif // DEBUG
++
++/* Use instead of regcomp. As we expect to be seeing the same regexps over and
++over again, it make sense to cache the results. */
++static regexp * compile_and_cache(char * regex_string, char * protocol)
++{
++ struct pattern_cache * node = first_pattern_cache;
++ struct pattern_cache * last_pattern_cache = first_pattern_cache;
++ struct pattern_cache * tmp;
++ unsigned int len;
++
++ while (node != NULL) {
++ if (!strcmp(node->regex_string, regex_string))
++ return node->pattern;
++
++ last_pattern_cache = node;/* points at the last non-NULL node */
++ node = node->next;
++ }
++
++ /* If we reach the end of the list, then we have not yet cached
++ the pattern for this regex. Let's do that now.
++ Be paranoid about running out of memory to avoid list corruption. */
++ tmp = kmalloc(sizeof(struct pattern_cache), GFP_ATOMIC);
++
++ if(!tmp) {
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in compile_and_cache, bailing.\n");
++ return NULL;
++ }
++
++ tmp->regex_string = kmalloc(strlen(regex_string) + 1, GFP_ATOMIC);
++ tmp->pattern = kmalloc(sizeof(struct regexp), GFP_ATOMIC);
++ tmp->next = NULL;
++
++ if(!tmp->regex_string || !tmp->pattern) {
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in compile_and_cache, bailing.\n");
++ kfree(tmp->regex_string);
++ kfree(tmp->pattern);
++ kfree(tmp);
++ return NULL;
++ }
++
++ /* Ok. The new node is all ready now. */
++ node = tmp;
++
++ if(first_pattern_cache == NULL) /* list is empty */
++ first_pattern_cache = node; /* make node the beginning */
++ else
++ last_pattern_cache->next = node; /* attach node to the end */
++
++ /* copy the string and compile the regex */
++ len = strlen(regex_string);
++ DPRINTK("About to compile this: \"%s\"\n", regex_string);
++ node->pattern = regcomp(regex_string, &len);
++ if ( !node->pattern ) {
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: Error compiling regexp \"%s\" (%s)\n", regex_string, protocol);
++ /* pattern is now cached as NULL, so we won't try again. */
++ }
++
++ strcpy(node->regex_string, regex_string);
++ return node->pattern;
++}
++
++static int can_handle(const struct sk_buff *skb)
++{
++ if(!skb->nh.iph) /* not IP */
++ return 0;
++ if(skb->nh.iph->protocol != IPPROTO_TCP &&
++ skb->nh.iph->protocol != IPPROTO_UDP &&
++ skb->nh.iph->protocol != IPPROTO_ICMP)
++ return 0;
++ return 1;
++}
++
++/* Returns offset the into the skb->data that the application data starts */
++static int app_data_offset(const struct sk_buff *skb)
++{
++ /* In case we are ported somewhere (ebtables?) where skb->nh.iph
++ isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */
++ int ip_hl = 4*skb->nh.iph->ihl;
++
++ if( skb->nh.iph->protocol == IPPROTO_TCP ) {
++ /* 12 == offset into TCP header for the header length field.
++ Can't get this with skb->h.th->doff because the tcphdr
++ struct doesn't get set when routing (this is confirmed to be
++ true in Netfilter as well as QoS.) */
++ int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4);
++
++ return ip_hl + tcp_hl;
++ } else if( skb->nh.iph->protocol == IPPROTO_UDP ) {
++ return ip_hl + 8; /* UDP header is always 8 bytes */
++ } else if( skb->nh.iph->protocol == IPPROTO_ICMP ) {
++ return ip_hl + 8; /* ICMP header is 8 bytes */
++ } else {
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: tried to handle unknown protocol!\n");
++ return ip_hl + 8; /* something reasonable */
++ }
++}
++
++/* handles whether there's a match when we aren't appending data anymore */
++static int match_no_append(struct ip_conntrack * conntrack, struct ip_conntrack * master_conntrack,
++ enum ip_conntrack_info ctinfo, enum ip_conntrack_info master_ctinfo,
++ struct ipt_layer7_info * info)
++{
++ /* If we're in here, throw the app data away */
++ write_lock(&ct_lock);
++ if(master_conntrack->layer7.app_data != NULL) {
++
++ #ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
++ if(!master_conntrack->layer7.app_proto) {
++ char * f = friendly_print(master_conntrack->layer7.app_data);
++ char * g = hex_print(master_conntrack->layer7.app_data);
++ DPRINTK("\nl7-filter gave up after %d bytes (%llu packets):\n%s\n",
++ strlen(f),
++ TOTAL_PACKETS, f);
++ kfree(f);
++ DPRINTK("In hex: %s\n", g);
++ kfree(g);
++ }
++ #endif
++
++ kfree(master_conntrack->layer7.app_data);
++ master_conntrack->layer7.app_data = NULL; /* don't free again */
++ }
++ write_unlock(&ct_lock);
++
++ if(master_conntrack->layer7.app_proto){
++ /* Here child connections set their .app_proto (for /proc/net/ip_conntrack) */
++ write_lock(&ct_lock);
++ if(!conntrack->layer7.app_proto) {
++ conntrack->layer7.app_proto = kmalloc(strlen(master_conntrack->layer7.app_proto)+1, GFP_ATOMIC);
++ if(!conntrack->layer7.app_proto){
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in match_no_append, bailing.\n");
++ write_unlock(&ct_lock);
++ return 1;
++ }
++ strcpy(conntrack->layer7.app_proto, master_conntrack->layer7.app_proto);
++ }
++ write_unlock(&ct_lock);
++
++ return (!strcmp(master_conntrack->layer7.app_proto, info->protocol));
++ }
++ else {
++ /* If not classified, set to "unknown" to distinguish from
++ connections that are still being tested. */
++ write_lock(&ct_lock);
++ master_conntrack->layer7.app_proto = kmalloc(strlen("unknown")+1, GFP_ATOMIC);
++ if(!master_conntrack->layer7.app_proto){
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in match_no_append, bailing.\n");
++ write_unlock(&ct_lock);
++ return 1;
++ }
++ strcpy(master_conntrack->layer7.app_proto, "unknown");
++ write_unlock(&ct_lock);
++ return 0;
++ }
++}
++
++static int add_datastr(char *target, int offset, char *app_data, int len)
++{
++ int length = 0, i;
++
++ /* Strip nulls. Make everything lower case (our regex lib doesn't
++ do case insensitivity). Add it to the end of the current data. */
++ for(i = 0; i < maxdatalen-offset-1 && i < len; i++) {
++ if(app_data[i] != '\0') {
++ target[length+offset] =
++ /* the kernel version of tolower mungs 'upper ascii' */
++ isascii(app_data[i])? tolower(app_data[i]) : app_data[i];
++ length++;
++ }
++ }
++ target[length+offset] = '\0';
++
++ return length;
++}
++
++/* add the new app data to the conntrack. Return number of bytes added. */
++static int add_data(struct ip_conntrack * master_conntrack,
++ char * app_data, int appdatalen)
++{
++ int length;
++
++ length = add_datastr(master_conntrack->layer7.app_data, master_conntrack->layer7.app_data_len, app_data, appdatalen);
++ master_conntrack->layer7.app_data_len += length;
++
++ return length;
++}
++
++/* Returns true on match and false otherwise. */
++static int match(/* const */struct sk_buff *skb, const struct net_device *in,
++ const struct net_device *out, const void *matchinfo,
++ int offset, int *hotdrop)
++{
++ struct ipt_layer7_info * info = (struct ipt_layer7_info *)matchinfo;
++ enum ip_conntrack_info master_ctinfo, ctinfo;
++ struct ip_conntrack *master_conntrack, *conntrack;
++ unsigned char *app_data, *tmp_data;
++ unsigned int pattern_result, appdatalen;
++ regexp * comppattern;
++
++ if(!can_handle(skb)){
++ DPRINTK("layer7: This is some protocol I can't handle.\n");
++ return info->invert;
++ }
++
++ /* Treat parent & all its children together as one connection, except
++ for the purpose of setting conntrack->layer7.app_proto in the actual
++ connection. This makes /proc/net/ip_conntrack more satisfying. */
++ if(!(conntrack = ip_conntrack_get((struct sk_buff *)skb, &ctinfo)) ||
++ !(master_conntrack = ip_conntrack_get((struct sk_buff *)skb, &master_ctinfo))) {
++ //DPRINTK("layer7: packet is not from a known connection, giving up.\n");
++ return info->invert;
++ }
++
++ /* Try to get a master conntrack (and its master etc) for FTP, etc. */
++ while (master_ct(master_conntrack) != NULL)
++ master_conntrack = master_ct(master_conntrack);
++
++ /* if we've classified it or seen too many packets */
++ if(!info->pkt && (TOTAL_PACKETS > num_packets ||
++ master_conntrack->layer7.app_proto)) {
++
++ pattern_result = match_no_append(conntrack, master_conntrack, ctinfo, master_ctinfo, info);
++
++ /* skb->cb[0] == seen. Avoid doing things twice if there are two l7
++ rules. I'm not sure that using cb for this purpose is correct, although
++ it says "put your private variables there". But it doesn't look like it
++ is being used for anything else in the skbs that make it here. How can
++ I write to cb without making the compiler angry? */
++ skb->cb[0] = 1; /* marking it seen here is probably irrelevant, but consistant */
++
++ return (pattern_result ^ info->invert);
++ }
++
++ if(skb_is_nonlinear(skb)){
++ if(skb_linearize(skb, GFP_ATOMIC) != 0){
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: failed to linearize packet, bailing.\n");
++ return info->invert;
++ }
++ }
++
++ /* now that the skb is linearized, it's safe to set these. */
++ app_data = skb->data + app_data_offset(skb);
++ appdatalen = skb->tail - app_data;
++
++ spin_lock_bh(&list_lock);
++ /* the return value gets checked later, when we're ready to use it */
++ comppattern = compile_and_cache(info->pattern, info->protocol);
++ spin_unlock_bh(&list_lock);
++
++ if (info->pkt) {
++ tmp_data = kmalloc(maxdatalen, GFP_ATOMIC);
++ if(!tmp_data){
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
++ return info->invert;
++ }
++
++ tmp_data[0] = '\0';
++ add_datastr(tmp_data, 0, app_data, appdatalen);
++ pattern_result = ((comppattern && regexec(comppattern, tmp_data)) ? 1 : 0);
++ kfree(tmp_data);
++ tmp_data = NULL;
++
++ return (pattern_result ^ info->invert);
++ }
++
++ /* On the first packet of a connection, allocate space for app data */
++ write_lock(&ct_lock);
++ if(TOTAL_PACKETS == 1 && !skb->cb[0] && !master_conntrack->layer7.app_data) {
++ master_conntrack->layer7.app_data = kmalloc(maxdatalen, GFP_ATOMIC);
++ if(!master_conntrack->layer7.app_data){
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
++ write_unlock(&ct_lock);
++ return info->invert;
++ }
++
++ master_conntrack->layer7.app_data[0] = '\0';
++ }
++ write_unlock(&ct_lock);
++
++ /* Can be here, but unallocated, if numpackets is increased near
++ the beginning of a connection */
++ if(master_conntrack->layer7.app_data == NULL)
++ return (info->invert); /* unmatched */
++
++ if(!skb->cb[0]){
++ int newbytes;
++ write_lock(&ct_lock);
++ newbytes = add_data(master_conntrack, app_data, appdatalen);
++ write_unlock(&ct_lock);
++
++ if(newbytes == 0) { /* didn't add any data */
++ skb->cb[0] = 1;
++ /* Didn't match before, not going to match now */
++ return info->invert;
++ }
++ }
++
++ /* If looking for "unknown", then never match. "Unknown" means that
++ we've given up; we're still trying with these packets. */
++ if(!strcmp(info->protocol, "unknown")) {
++ pattern_result = 0;
++ /* If the regexp failed to compile, don't bother running it */
++ } else if(comppattern && regexec(comppattern, master_conntrack->layer7.app_data)) {
++ DPRINTK("layer7: matched %s\n", info->protocol);
++ pattern_result = 1;
++ } else pattern_result = 0;
++
++ if(pattern_result) {
++ write_lock(&ct_lock);
++ master_conntrack->layer7.app_proto = kmalloc(strlen(info->protocol)+1, GFP_ATOMIC);
++ if(!master_conntrack->layer7.app_proto){
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
++ write_unlock(&ct_lock);
++ return (pattern_result ^ info->invert);
++ }
++ strcpy(master_conntrack->layer7.app_proto, info->protocol);
++ write_unlock(&ct_lock);
++ }
++
++ /* mark the packet seen */
++ skb->cb[0] = 1;
++
++ return (pattern_result ^ info->invert);
++}
++
++static int checkentry(const char *tablename, const struct ipt_ip *ip,
++ void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
++{
++ if (matchsize != IPT_ALIGN(sizeof(struct ipt_layer7_info)))
++ return 0;
++ return 1;
++}
++
++static struct ipt_match layer7_match = {
++ .name = "layer7",
++ .match = &match,
++ .checkentry = &checkentry,
++ .me = THIS_MODULE
++};
++
++/* taken from drivers/video/modedb.c */
++static int my_atoi(const char *s)
++{
++ int val = 0;
++
++ for (;; s++) {
++ switch (*s) {
++ case '0'...'9':
++ val = 10*val+(*s-'0');
++ break;
++ default:
++ return val;
++ }
++ }
++}
++
++/* write out num_packets to userland. */
++static int layer7_read_proc(char* page, char ** start, off_t off, int count,
++ int* eof, void * data)
++{
++ if(num_packets > 99 && net_ratelimit())
++ printk(KERN_ERR "layer7: NOT REACHED. num_packets too big\n");
++
++ page[0] = num_packets/10 + '0';
++ page[1] = num_packets%10 + '0';
++ page[2] = '\n';
++ page[3] = '\0';
++
++ *eof=1;
++
++ return 3;
++}
++
++/* Read in num_packets from userland */
++static int layer7_write_proc(struct file* file, const char* buffer,
++ unsigned long count, void *data)
++{
++ char * foo = kmalloc(count, GFP_ATOMIC);
++
++ if(!foo){
++ if (net_ratelimit())
++ printk(KERN_ERR "layer7: out of memory, bailing. num_packets unchanged.\n");
++ return count;
++ }
++
++ if(copy_from_user(foo, buffer, count)) {
++ return -EFAULT;
++ }
++
++
++ num_packets = my_atoi(foo);
++ kfree (foo);
++
++ /* This has an arbitrary limit to make the math easier. I'm lazy.
++ But anyway, 99 is a LOT! If you want more, you're doing it wrong! */
++ if(num_packets > 99) {
++ printk(KERN_WARNING "layer7: num_packets can't be > 99.\n");
++ num_packets = 99;
++ } else if(num_packets < 1) {
++ printk(KERN_WARNING "layer7: num_packets can't be < 1.\n");
++ num_packets = 1;
++ }
++
++ return count;
++}
++
++/* register the proc file */
++static void layer7_init_proc(void)
++{
++ struct proc_dir_entry* entry;
++ entry = create_proc_entry("layer7_numpackets", 0644, proc_net);
++ entry->read_proc = layer7_read_proc;
++ entry->write_proc = layer7_write_proc;
++}
++
++static void layer7_cleanup_proc(void)
++{
++ remove_proc_entry("layer7_numpackets", proc_net);
++}
++
++static int __init init(void)
++{
++ layer7_init_proc();
++ if(maxdatalen < 1) {
++ printk(KERN_WARNING "layer7: maxdatalen can't be < 1, using 1\n");
++ maxdatalen = 1;
++ }
++ /* This is not a hard limit. It's just here to prevent people from
++ bringing their slow machines to a grinding halt. */
++ else if(maxdatalen > 65536) {
++ printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, using 65536\n");
++ maxdatalen = 65536;
++ }
++ return ipt_register_match(&layer7_match);
++}
++
++static void __exit fini(void)
++{
++ layer7_cleanup_proc();
++ ipt_unregister_match(&layer7_match);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Nur linux-2.6.17/net/ipv4/netfilter/Kconfig linux-2.6.17-owrt/net/ipv4/netfilter/Kconfig
+--- linux-2.6.17/net/ipv4/netfilter/Kconfig 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/net/ipv4/netfilter/Kconfig 2006-06-18 12:32:58.000000000 +0200
+@@ -314,6 +314,24 @@
+ destination IP' or `500pps from any given source IP' with a single
+ IPtables rule.
+
++config IP_NF_MATCH_LAYER7
++ tristate "Layer 7 match support (EXPERIMENTAL)"
++ depends on IP_NF_IPTABLES && IP_NF_CT_ACCT && IP_NF_CONNTRACK && EXPERIMENTAL
++ help
++ Say Y if you want to be able to classify connections (and their
++ packets) based on regular expression matching of their application
++ layer data. This is one way to classify applications such as
++ peer-to-peer filesharing systems that do not always use the same
++ port.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
++config IP_NF_MATCH_LAYER7_DEBUG
++ bool "Layer 7 debugging output"
++ depends on IP_NF_MATCH_LAYER7
++ help
++ Say Y to get lots of debugging output.
++
+ # `filter', generic and specific targets
+ config IP_NF_FILTER
+ tristate "Packet filtering"
+diff -Nur linux-2.6.17/net/ipv4/netfilter/Makefile linux-2.6.17-owrt/net/ipv4/netfilter/Makefile
+--- linux-2.6.17/net/ipv4/netfilter/Makefile 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/net/ipv4/netfilter/Makefile 2006-06-18 12:29:04.000000000 +0200
+@@ -62,6 +62,8 @@
+ obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
+ obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
+
++obj-$(CONFIG_IP_NF_MATCH_LAYER7) += ipt_layer7.o
++
+ # targets
+ obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
+ obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
+diff -Nur linux-2.6.17/net/ipv4/netfilter/regexp/regexp.c linux-2.6.17-owrt/net/ipv4/netfilter/regexp/regexp.c
+--- linux-2.6.17/net/ipv4/netfilter/regexp/regexp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/net/ipv4/netfilter/regexp/regexp.c 2006-06-18 12:29:04.000000000 +0200
+@@ -0,0 +1,1195 @@
++/*
++ * regcomp and regexec -- regsub and regerror are elsewhere
++ * @(#)regexp.c 1.3 of 18 April 87
++ *
++ * Copyright (c) 1986 by University of Toronto.
++ * Written by Henry Spencer. Not derived from licensed software.
++ *
++ * Permission is granted to anyone to use this software for any
++ * purpose on any computer system, and to redistribute it freely,
++ * subject to the following restrictions:
++ *
++ * 1. The author is not responsible for the consequences of use of
++ * this software, no matter how awful, even if they arise
++ * from defects in it.
++ *
++ * 2. The origin of this software must not be misrepresented, either
++ * by explicit claim or by omission.
++ *
++ * 3. Altered versions must be plainly marked as such, and must not
++ * be misrepresented as being the original software.
++ *
++ * Beware that some of this code is subtly aware of the way operator
++ * precedence is structured in regular expressions. Serious changes in
++ * regular-expression syntax might require a total rethink.
++ *
++ * This code was modified by Ethan Sommer to work within the kernel
++ * (it now uses kmalloc etc..)
++ *
++ * Modified slightly by Matthew Strait to use more modern C.
++ */
++
++#include "regexp.h"
++#include "regmagic.h"
++
++/* added by ethan and matt. Lets it work in both kernel and user space.
++(So iptables can use it, for instance.) Yea, it goes both ways... */
++#if __KERNEL__
++ #define malloc(foo) kmalloc(foo,GFP_ATOMIC)
++#else
++ #define printk(format,args...) printf(format,##args)
++#endif
++
++void regerror(char * s)
++{
++ printk("<3>Regexp: %s\n", s);
++ /* NOTREACHED */
++}
++
++/*
++ * The "internal use only" fields in regexp.h are present to pass info from
++ * compile to execute that permits the execute phase to run lots faster on
++ * simple cases. They are:
++ *
++ * regstart char that must begin a match; '\0' if none obvious
++ * reganch is the match anchored (at beginning-of-line only)?
++ * regmust string (pointer into program) that match must include, or NULL
++ * regmlen length of regmust string
++ *
++ * Regstart and reganch permit very fast decisions on suitable starting points
++ * for a match, cutting down the work a lot. Regmust permits fast rejection
++ * of lines that cannot possibly match. The regmust tests are costly enough
++ * that regcomp() supplies a regmust only if the r.e. contains something
++ * potentially expensive (at present, the only such thing detected is * or +
++ * at the start of the r.e., which can involve a lot of backup). Regmlen is
++ * supplied because the test in regexec() needs it and regcomp() is computing
++ * it anyway.
++ */
++
++/*
++ * Structure for regexp "program". This is essentially a linear encoding
++ * of a nondeterministic finite-state machine (aka syntax charts or
++ * "railroad normal form" in parsing technology). Each node is an opcode
++ * plus a "next" pointer, possibly plus an operand. "Next" pointers of
++ * all nodes except BRANCH implement concatenation; a "next" pointer with
++ * a BRANCH on both ends of it is connecting two alternatives. (Here we
++ * have one of the subtle syntax dependencies: an individual BRANCH (as
++ * opposed to a collection of them) is never concatenated with anything
++ * because of operator precedence.) The operand of some types of node is
++ * a literal string; for others, it is a node leading into a sub-FSM. In
++ * particular, the operand of a BRANCH node is the first node of the branch.
++ * (NB this is *not* a tree structure: the tail of the branch connects
++ * to the thing following the set of BRANCHes.) The opcodes are:
++ */
++
++/* definition number opnd? meaning */
++#define END 0 /* no End of program. */
++#define BOL 1 /* no Match "" at beginning of line. */
++#define EOL 2 /* no Match "" at end of line. */
++#define ANY 3 /* no Match any one character. */
++#define ANYOF 4 /* str Match any character in this string. */
++#define ANYBUT 5 /* str Match any character not in this string. */
++#define BRANCH 6 /* node Match this alternative, or the next... */
++#define BACK 7 /* no Match "", "next" ptr points backward. */
++#define EXACTLY 8 /* str Match this string. */
++#define NOTHING 9 /* no Match empty string. */
++#define STAR 10 /* node Match this (simple) thing 0 or more times. */
++#define PLUS 11 /* node Match this (simple) thing 1 or more times. */
++#define OPEN 20 /* no Mark this point in input as start of #n. */
++ /* OPEN+1 is number 1, etc. */
++#define CLOSE 30 /* no Analogous to OPEN. */
++
++/*
++ * Opcode notes:
++ *
++ * BRANCH The set of branches constituting a single choice are hooked
++ * together with their "next" pointers, since precedence prevents
++ * anything being concatenated to any individual branch. The
++ * "next" pointer of the last BRANCH in a choice points to the
++ * thing following the whole choice. This is also where the
++ * final "next" pointer of each individual branch points; each
++ * branch starts with the operand node of a BRANCH node.
++ *
++ * BACK Normal "next" pointers all implicitly point forward; BACK
++ * exists to make loop structures possible.
++ *
++ * STAR,PLUS '?', and complex '*' and '+', are implemented as circular
++ * BRANCH structures using BACK. Simple cases (one character
++ * per match) are implemented with STAR and PLUS for speed
++ * and to minimize recursive plunges.
++ *
++ * OPEN,CLOSE ...are numbered at compile time.
++ */
++
++/*
++ * A node is one char of opcode followed by two chars of "next" pointer.
++ * "Next" pointers are stored as two 8-bit pieces, high order first. The
++ * value is a positive offset from the opcode of the node containing it.
++ * An operand, if any, simply follows the node. (Note that much of the
++ * code generation knows about this implicit relationship.)
++ *
++ * Using two bytes for the "next" pointer is vast overkill for most things,
++ * but allows patterns to get big without disasters.
++ */
++#define OP(p) (*(p))
++#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
++#define OPERAND(p) ((p) + 3)
++
++/*
++ * See regmagic.h for one further detail of program structure.
++ */
++
++
++/*
++ * Utility definitions.
++ */
++#ifndef CHARBITS
++#define UCHARAT(p) ((int)*(unsigned char *)(p))
++#else
++#define UCHARAT(p) ((int)*(p)&CHARBITS)
++#endif
++
++#define FAIL(m) { regerror(m); return(NULL); }
++#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?')
++#define META "^$.[()|?+*\\"
++
++/*
++ * Flags to be passed up and down.
++ */
++#define HASWIDTH 01 /* Known never to match null string. */
++#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */
++#define SPSTART 04 /* Starts with * or +. */
++#define WORST 0 /* Worst case. */
++
++/*
++ * Global work variables for regcomp().
++ */
++static char *regparse; /* Input-scan pointer. */
++static int regnpar; /* () count. */
++static char regdummy;
++static char *regcode; /* Code-emit pointer; &regdummy = don't. */
++static long regsize; /* Code size. */
++
++/*
++ * Forward declarations for regcomp()'s friends.
++ */
++#ifndef STATIC
++#define STATIC static
++#endif
++STATIC char *reg(int paren,int *flagp);
++STATIC char *regbranch(int *flagp);
++STATIC char *regpiece(int *flagp);
++STATIC char *regatom(int *flagp);
++STATIC char *regnode(char op);
++STATIC char *regnext(char *p);
++STATIC void regc(char b);
++STATIC void reginsert(char op, char *opnd);
++STATIC void regtail(char *p, char *val);
++STATIC void regoptail(char *p, char *val);
++
++
++__kernel_size_t my_strcspn(const char *s1,const char *s2)
++{
++ char *scan1;
++ char *scan2;
++ int count;
++
++ count = 0;
++ for (scan1 = (char *)s1; *scan1 != '\0'; scan1++) {
++ for (scan2 = (char *)s2; *scan2 != '\0';) /* ++ moved down. */
++ if (*scan1 == *scan2++)
++ return(count);
++ count++;
++ }
++ return(count);
++}
++
++/*
++ - regcomp - compile a regular expression into internal code
++ *
++ * We can't allocate space until we know how big the compiled form will be,
++ * but we can't compile it (and thus know how big it is) until we've got a
++ * place to put the code. So we cheat: we compile it twice, once with code
++ * generation turned off and size counting turned on, and once "for real".
++ * This also means that we don't allocate space until we are sure that the
++ * thing really will compile successfully, and we never have to move the
++ * code and thus invalidate pointers into it. (Note that it has to be in
++ * one piece because free() must be able to free it all.)
++ *
++ * Beware that the optimization-preparation code in here knows about some
++ * of the structure of the compiled regexp.
++ */
++regexp *
++regcomp(char *exp,int *patternsize)
++{
++ register regexp *r;
++ register char *scan;
++ register char *longest;
++ register int len;
++ int flags;
++ /* commented out by ethan
++ extern char *malloc();
++ */
++
++ if (exp == NULL)
++ FAIL("NULL argument");
++
++ /* First pass: determine size, legality. */
++ regparse = exp;
++ regnpar = 1;
++ regsize = 0L;
++ regcode = &regdummy;
++ regc(MAGIC);
++ if (reg(0, &flags) == NULL)
++ return(NULL);
++
++ /* Small enough for pointer-storage convention? */
++ if (regsize >= 32767L) /* Probably could be 65535L. */
++ FAIL("regexp too big");
++
++ /* Allocate space. */
++ *patternsize=sizeof(regexp) + (unsigned)regsize;
++ r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize);
++ if (r == NULL)
++ FAIL("out of space");
++
++ /* Second pass: emit code. */
++ regparse = exp;
++ regnpar = 1;
++ regcode = r->program;
++ regc(MAGIC);
++ if (reg(0, &flags) == NULL)
++ return(NULL);
++
++ /* Dig out information for optimizations. */
++ r->regstart = '\0'; /* Worst-case defaults. */
++ r->reganch = 0;
++ r->regmust = NULL;
++ r->regmlen = 0;
++ scan = r->program+1; /* First BRANCH. */
++ if (OP(regnext(scan)) == END) { /* Only one top-level choice. */
++ scan = OPERAND(scan);
++
++ /* Starting-point info. */
++ if (OP(scan) == EXACTLY)
++ r->regstart = *OPERAND(scan);
++ else if (OP(scan) == BOL)
++ r->reganch++;
++
++ /*
++ * If there's something expensive in the r.e., find the
++ * longest literal string that must appear and make it the
++ * regmust. Resolve ties in favor of later strings, since
++ * the regstart check works with the beginning of the r.e.
++ * and avoiding duplication strengthens checking. Not a
++ * strong reason, but sufficient in the absence of others.
++ */
++ if (flags&SPSTART) {
++ longest = NULL;
++ len = 0;
++ for (; scan != NULL; scan = regnext(scan))
++ if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
++ longest = OPERAND(scan);
++ len = strlen(OPERAND(scan));
++ }
++ r->regmust = longest;
++ r->regmlen = len;
++ }
++ }
++
++ return(r);
++}
++
++/*
++ - reg - regular expression, i.e. main body or parenthesized thing
++ *
++ * Caller must absorb opening parenthesis.
++ *
++ * Combining parenthesis handling with the base level of regular expression
++ * is a trifle forced, but the need to tie the tails of the branches to what
++ * follows makes it hard to avoid.
++ */
++static char *
++reg(int paren, int *flagp /* Parenthesized? */ )
++{
++ register char *ret;
++ register char *br;
++ register char *ender;
++ register int parno = 0; /* 0 makes gcc happy */
++ int flags;
++
++ *flagp = HASWIDTH; /* Tentatively. */
++
++ /* Make an OPEN node, if parenthesized. */
++ if (paren) {
++ if (regnpar >= NSUBEXP)
++ FAIL("too many ()");
++ parno = regnpar;
++ regnpar++;
++ ret = regnode(OPEN+parno);
++ } else
++ ret = NULL;
++
++ /* Pick up the branches, linking them together. */
++ br = regbranch(&flags);
++ if (br == NULL)
++ return(NULL);
++ if (ret != NULL)
++ regtail(ret, br); /* OPEN -> first. */
++ else
++ ret = br;
++ if (!(flags&HASWIDTH))
++ *flagp &= ~HASWIDTH;
++ *flagp |= flags&SPSTART;
++ while (*regparse == '|') {
++ regparse++;
++ br = regbranch(&flags);
++ if (br == NULL)
++ return(NULL);
++ regtail(ret, br); /* BRANCH -> BRANCH. */
++ if (!(flags&HASWIDTH))
++ *flagp &= ~HASWIDTH;
++ *flagp |= flags&SPSTART;
++ }
++
++ /* Make a closing node, and hook it on the end. */
++ ender = regnode((paren) ? CLOSE+parno : END);
++ regtail(ret, ender);
++
++ /* Hook the tails of the branches to the closing node. */
++ for (br = ret; br != NULL; br = regnext(br))
++ regoptail(br, ender);
++
++ /* Check for proper termination. */
++ if (paren && *regparse++ != ')') {
++ FAIL("unmatched ()");
++ } else if (!paren && *regparse != '\0') {
++ if (*regparse == ')') {
++ FAIL("unmatched ()");
++ } else
++ FAIL("junk on end"); /* "Can't happen". */
++ /* NOTREACHED */
++ }
++
++ return(ret);
++}
++
++/*
++ - regbranch - one alternative of an | operator
++ *
++ * Implements the concatenation operator.
++ */
++static char *
++regbranch(int *flagp)
++{
++ register char *ret;
++ register char *chain;
++ register char *latest;
++ int flags;
++
++ *flagp = WORST; /* Tentatively. */
++
++ ret = regnode(BRANCH);
++ chain = NULL;
++ while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
++ latest = regpiece(&flags);
++ if (latest == NULL)
++ return(NULL);
++ *flagp |= flags&HASWIDTH;
++ if (chain == NULL) /* First piece. */
++ *flagp |= flags&SPSTART;
++ else
++ regtail(chain, latest);
++ chain = latest;
++ }
++ if (chain == NULL) /* Loop ran zero times. */
++ (void) regnode(NOTHING);
++
++ return(ret);
++}
++
++/*
++ - regpiece - something followed by possible [*+?]
++ *
++ * Note that the branching code sequences used for ? and the general cases
++ * of * and + are somewhat optimized: they use the same NOTHING node as
++ * both the endmarker for their branch list and the body of the last branch.
++ * It might seem that this node could be dispensed with entirely, but the
++ * endmarker role is not redundant.
++ */
++static char *
++regpiece(int *flagp)
++{
++ register char *ret;
++ register char op;
++ register char *next;
++ int flags;
++
++ ret = regatom(&flags);
++ if (ret == NULL)
++ return(NULL);
++
++ op = *regparse;
++ if (!ISMULT(op)) {
++ *flagp = flags;
++ return(ret);
++ }
++
++ if (!(flags&HASWIDTH) && op != '?')
++ FAIL("*+ operand could be empty");
++ *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
++
++ if (op == '*' && (flags&SIMPLE))
++ reginsert(STAR, ret);
++ else if (op == '*') {
++ /* Emit x* as (x&|), where & means "self". */
++ reginsert(BRANCH, ret); /* Either x */
++ regoptail(ret, regnode(BACK)); /* and loop */
++ regoptail(ret, ret); /* back */
++ regtail(ret, regnode(BRANCH)); /* or */
++ regtail(ret, regnode(NOTHING)); /* null. */
++ } else if (op == '+' && (flags&SIMPLE))
++ reginsert(PLUS, ret);
++ else if (op == '+') {
++ /* Emit x+ as x(&|), where & means "self". */
++ next = regnode(BRANCH); /* Either */
++ regtail(ret, next);
++ regtail(regnode(BACK), ret); /* loop back */
++ regtail(next, regnode(BRANCH)); /* or */
++ regtail(ret, regnode(NOTHING)); /* null. */
++ } else if (op == '?') {
++ /* Emit x? as (x|) */
++ reginsert(BRANCH, ret); /* Either x */
++ regtail(ret, regnode(BRANCH)); /* or */
++ next = regnode(NOTHING); /* null. */
++ regtail(ret, next);
++ regoptail(ret, next);
++ }
++ regparse++;
++ if (ISMULT(*regparse))
++ FAIL("nested *?+");
++
++ return(ret);
++}
++
++/*
++ - regatom - the lowest level
++ *
++ * Optimization: gobbles an entire sequence of ordinary characters so that
++ * it can turn them into a single node, which is smaller to store and
++ * faster to run. Backslashed characters are exceptions, each becoming a
++ * separate node; the code is simpler that way and it's not worth fixing.
++ */
++static char *
++regatom(int *flagp)
++{
++ register char *ret;
++ int flags;
++
++ *flagp = WORST; /* Tentatively. */
++
++ switch (*regparse++) {
++ case '^':
++ ret = regnode(BOL);
++ break;
++ case '$':
++ ret = regnode(EOL);
++ break;
++ case '.':
++ ret = regnode(ANY);
++ *flagp |= HASWIDTH|SIMPLE;
++ break;
++ case '[': {
++ register int class;
++ register int classend;
++
++ if (*regparse == '^') { /* Complement of range. */
++ ret = regnode(ANYBUT);
++ regparse++;
++ } else
++ ret = regnode(ANYOF);
++ if (*regparse == ']' || *regparse == '-')
++ regc(*regparse++);
++ while (*regparse != '\0' && *regparse != ']') {
++ if (*regparse == '-') {
++ regparse++;
++ if (*regparse == ']' || *regparse == '\0')
++ regc('-');
++ else {
++ class = UCHARAT(regparse-2)+1;
++ classend = UCHARAT(regparse);
++ if (class > classend+1)
++ FAIL("invalid [] range");
++ for (; class <= classend; class++)
++ regc(class);
++ regparse++;
++ }
++ } else
++ regc(*regparse++);
++ }
++ regc('\0');
++ if (*regparse != ']')
++ FAIL("unmatched []");
++ regparse++;
++ *flagp |= HASWIDTH|SIMPLE;
++ }
++ break;
++ case '(':
++ ret = reg(1, &flags);
++ if (ret == NULL)
++ return(NULL);
++ *flagp |= flags&(HASWIDTH|SPSTART);
++ break;
++ case '\0':
++ case '|':
++ case ')':
++ FAIL("internal urp"); /* Supposed to be caught earlier. */
++ break;
++ case '?':
++ case '+':
++ case '*':
++ FAIL("?+* follows nothing");
++ break;
++ case '\\':
++ if (*regparse == '\0')
++ FAIL("trailing \\");
++ ret = regnode(EXACTLY);
++ regc(*regparse++);
++ regc('\0');
++ *flagp |= HASWIDTH|SIMPLE;
++ break;
++ default: {
++ register int len;
++ register char ender;
++
++ regparse--;
++ len = my_strcspn((const char *)regparse, (const char *)META);
++ if (len <= 0)
++ FAIL("internal disaster");
++ ender = *(regparse+len);
++ if (len > 1 && ISMULT(ender))
++ len--; /* Back off clear of ?+* operand. */
++ *flagp |= HASWIDTH;
++ if (len == 1)
++ *flagp |= SIMPLE;
++ ret = regnode(EXACTLY);
++ while (len > 0) {
++ regc(*regparse++);
++ len--;
++ }
++ regc('\0');
++ }
++ break;
++ }
++
++ return(ret);
++}
++
++/*
++ - regnode - emit a node
++ */
++static char * /* Location. */
++regnode(char op)
++{
++ register char *ret;
++ register char *ptr;
++
++ ret = regcode;
++ if (ret == &regdummy) {
++ regsize += 3;
++ return(ret);
++ }
++
++ ptr = ret;
++ *ptr++ = op;
++ *ptr++ = '\0'; /* Null "next" pointer. */
++ *ptr++ = '\0';
++ regcode = ptr;
++
++ return(ret);
++}
++
++/*
++ - regc - emit (if appropriate) a byte of code
++ */
++static void
++regc(char b)
++{
++ if (regcode != &regdummy)
++ *regcode++ = b;
++ else
++ regsize++;
++}
++
++/*
++ - reginsert - insert an operator in front of already-emitted operand
++ *
++ * Means relocating the operand.
++ */
++static void
++reginsert(char op, char* opnd)
++{
++ register char *src;
++ register char *dst;
++ register char *place;
++
++ if (regcode == &regdummy) {
++ regsize += 3;
++ return;
++ }
++
++ src = regcode;
++ regcode += 3;
++ dst = regcode;
++ while (src > opnd)
++ *--dst = *--src;
++
++ place = opnd; /* Op node, where operand used to be. */
++ *place++ = op;
++ *place++ = '\0';
++ *place++ = '\0';
++}
++
++/*
++ - regtail - set the next-pointer at the end of a node chain
++ */
++static void
++regtail(char *p, char *val)
++{
++ register char *scan;
++ register char *temp;
++ register int offset;
++
++ if (p == &regdummy)
++ return;
++
++ /* Find last node. */
++ scan = p;
++ for (;;) {
++ temp = regnext(scan);
++ if (temp == NULL)
++ break;
++ scan = temp;
++ }
++
++ if (OP(scan) == BACK)
++ offset = scan - val;
++ else
++ offset = val - scan;
++ *(scan+1) = (offset>>8)&0377;
++ *(scan+2) = offset&0377;
++}
++
++/*
++ - regoptail - regtail on operand of first argument; nop if operandless
++ */
++static void
++regoptail(char *p, char *val)
++{
++ /* "Operandless" and "op != BRANCH" are synonymous in practice. */
++ if (p == NULL || p == &regdummy || OP(p) != BRANCH)
++ return;
++ regtail(OPERAND(p), val);
++}
++
++/*
++ * regexec and friends
++ */
++
++/*
++ * Global work variables for regexec().
++ */
++static char *reginput; /* String-input pointer. */
++static char *regbol; /* Beginning of input, for ^ check. */
++static char **regstartp; /* Pointer to startp array. */
++static char **regendp; /* Ditto for endp. */
++
++/*
++ * Forwards.
++ */
++STATIC int regtry(regexp *prog, char *string);
++STATIC int regmatch(char *prog);
++STATIC int regrepeat(char *p);
++
++#ifdef DEBUG
++int regnarrate = 0;
++void regdump();
++STATIC char *regprop(char *op);
++#endif
++
++/*
++ - regexec - match a regexp against a string
++ */
++int
++regexec(regexp *prog, char *string)
++{
++ register char *s;
++
++ /* Be paranoid... */
++ if (prog == NULL || string == NULL) {
++ printk("<3>Regexp: NULL parameter\n");
++ return(0);
++ }
++
++ /* Check validity of program. */
++ if (UCHARAT(prog->program) != MAGIC) {
++ printk("<3>Regexp: corrupted program\n");
++ return(0);
++ }
++
++ /* If there is a "must appear" string, look for it. */
++ if (prog->regmust != NULL) {
++ s = string;
++ while ((s = strchr(s, prog->regmust[0])) != NULL) {
++ if (strncmp(s, prog->regmust, prog->regmlen) == 0)
++ break; /* Found it. */
++ s++;
++ }
++ if (s == NULL) /* Not present. */
++ return(0);
++ }
++
++ /* Mark beginning of line for ^ . */
++ regbol = string;
++
++ /* Simplest case: anchored match need be tried only once. */
++ if (prog->reganch)
++ return(regtry(prog, string));
++
++ /* Messy cases: unanchored match. */
++ s = string;
++ if (prog->regstart != '\0')
++ /* We know what char it must start with. */
++ while ((s = strchr(s, prog->regstart)) != NULL) {
++ if (regtry(prog, s))
++ return(1);
++ s++;
++ }
++ else
++ /* We don't -- general case. */
++ do {
++ if (regtry(prog, s))
++ return(1);
++ } while (*s++ != '\0');
++
++ /* Failure. */
++ return(0);
++}
++
++/*
++ - regtry - try match at specific point
++ */
++static int /* 0 failure, 1 success */
++regtry(regexp *prog, char *string)
++{
++ register int i;
++ register char **sp;
++ register char **ep;
++
++ reginput = string;
++ regstartp = prog->startp;
++ regendp = prog->endp;
++
++ sp = prog->startp;
++ ep = prog->endp;
++ for (i = NSUBEXP; i > 0; i--) {
++ *sp++ = NULL;
++ *ep++ = NULL;
++ }
++ if (regmatch(prog->program + 1)) {
++ prog->startp[0] = string;
++ prog->endp[0] = reginput;
++ return(1);
++ } else
++ return(0);
++}
++
++/*
++ - regmatch - main matching routine
++ *
++ * Conceptually the strategy is simple: check to see whether the current
++ * node matches, call self recursively to see whether the rest matches,
++ * and then act accordingly. In practice we make some effort to avoid
++ * recursion, in particular by going through "ordinary" nodes (that don't
++ * need to know whether the rest of the match failed) by a loop instead of
++ * by recursion.
++ */
++static int /* 0 failure, 1 success */
++regmatch(char *prog)
++{
++ register char *scan = prog; /* Current node. */
++ char *next; /* Next node. */
++
++#ifdef DEBUG
++ if (scan != NULL && regnarrate)
++ fprintf(stderr, "%s(\n", regprop(scan));
++#endif
++ while (scan != NULL) {
++#ifdef DEBUG
++ if (regnarrate)
++ fprintf(stderr, "%s...\n", regprop(scan));
++#endif
++ next = regnext(scan);
++
++ switch (OP(scan)) {
++ case BOL:
++ if (reginput != regbol)
++ return(0);
++ break;
++ case EOL:
++ if (*reginput != '\0')
++ return(0);
++ break;
++ case ANY:
++ if (*reginput == '\0')
++ return(0);
++ reginput++;
++ break;
++ case EXACTLY: {
++ register int len;
++ register char *opnd;
++
++ opnd = OPERAND(scan);
++ /* Inline the first character, for speed. */
++ if (*opnd != *reginput)
++ return(0);
++ len = strlen(opnd);
++ if (len > 1 && strncmp(opnd, reginput, len) != 0)
++ return(0);
++ reginput += len;
++ }
++ break;
++ case ANYOF:
++ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
++ return(0);
++ reginput++;
++ break;
++ case ANYBUT:
++ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
++ return(0);
++ reginput++;
++ break;
++ case NOTHING:
++ case BACK:
++ break;
++ case OPEN+1:
++ case OPEN+2:
++ case OPEN+3:
++ case OPEN+4:
++ case OPEN+5:
++ case OPEN+6:
++ case OPEN+7:
++ case OPEN+8:
++ case OPEN+9: {
++ register int no;
++ register char *save;
++
++ no = OP(scan) - OPEN;
++ save = reginput;
++
++ if (regmatch(next)) {
++ /*
++ * Don't set startp if some later
++ * invocation of the same parentheses
++ * already has.
++ */
++ if (regstartp[no] == NULL)
++ regstartp[no] = save;
++ return(1);
++ } else
++ return(0);
++ }
++ break;
++ case CLOSE+1:
++ case CLOSE+2:
++ case CLOSE+3:
++ case CLOSE+4:
++ case CLOSE+5:
++ case CLOSE+6:
++ case CLOSE+7:
++ case CLOSE+8:
++ case CLOSE+9:
++ {
++ register int no;
++ register char *save;
++
++ no = OP(scan) - CLOSE;
++ save = reginput;
++
++ if (regmatch(next)) {
++ /*
++ * Don't set endp if some later
++ * invocation of the same parentheses
++ * already has.
++ */
++ if (regendp[no] == NULL)
++ regendp[no] = save;
++ return(1);
++ } else
++ return(0);
++ }
++ break;
++ case BRANCH: {
++ register char *save;
++
++ if (OP(next) != BRANCH) /* No choice. */
++ next = OPERAND(scan); /* Avoid recursion. */
++ else {
++ do {
++ save = reginput;
++ if (regmatch(OPERAND(scan)))
++ return(1);
++ reginput = save;
++ scan = regnext(scan);
++ } while (scan != NULL && OP(scan) == BRANCH);
++ return(0);
++ /* NOTREACHED */
++ }
++ }
++ break;
++ case STAR:
++ case PLUS: {
++ register char nextch;
++ register int no;
++ register char *save;
++ register int min;
++
++ /*
++ * Lookahead to avoid useless match attempts
++ * when we know what character comes next.
++ */
++ nextch = '\0';
++ if (OP(next) == EXACTLY)
++ nextch = *OPERAND(next);
++ min = (OP(scan) == STAR) ? 0 : 1;
++ save = reginput;
++ no = regrepeat(OPERAND(scan));
++ while (no >= min) {
++ /* If it could work, try it. */
++ if (nextch == '\0' || *reginput == nextch)
++ if (regmatch(next))
++ return(1);
++ /* Couldn't or didn't -- back up. */
++ no--;
++ reginput = save + no;
++ }
++ return(0);
++ }
++ break;
++ case END:
++ return(1); /* Success! */
++ break;
++ default:
++ printk("<3>Regexp: memory corruption\n");
++ return(0);
++ break;
++ }
++
++ scan = next;
++ }
++
++ /*
++ * We get here only if there's trouble -- normally "case END" is
++ * the terminating point.
++ */
++ printk("<3>Regexp: corrupted pointers\n");
++ return(0);
++}
++
++/*
++ - regrepeat - repeatedly match something simple, report how many
++ */
++static int
++regrepeat(char *p)
++{
++ register int count = 0;
++ register char *scan;
++ register char *opnd;
++
++ scan = reginput;
++ opnd = OPERAND(p);
++ switch (OP(p)) {
++ case ANY:
++ count = strlen(scan);
++ scan += count;
++ break;
++ case EXACTLY:
++ while (*opnd == *scan) {
++ count++;
++ scan++;
++ }
++ break;
++ case ANYOF:
++ while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
++ count++;
++ scan++;
++ }
++ break;
++ case ANYBUT:
++ while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
++ count++;
++ scan++;
++ }
++ break;
++ default: /* Oh dear. Called inappropriately. */
++ printk("<3>Regexp: internal foulup\n");
++ count = 0; /* Best compromise. */
++ break;
++ }
++ reginput = scan;
++
++ return(count);
++}
++
++/*
++ - regnext - dig the "next" pointer out of a node
++ */
++static char*
++regnext(char *p)
++{
++ register int offset;
++
++ if (p == &regdummy)
++ return(NULL);
++
++ offset = NEXT(p);
++ if (offset == 0)
++ return(NULL);
++
++ if (OP(p) == BACK)
++ return(p-offset);
++ else
++ return(p+offset);
++}
++
++#ifdef DEBUG
++
++STATIC char *regprop();
++
++/*
++ - regdump - dump a regexp onto stdout in vaguely comprehensible form
++ */
++void
++regdump(regexp *r)
++{
++ register char *s;
++ register char op = EXACTLY; /* Arbitrary non-END op. */
++ register char *next;
++ /* extern char *strchr(); */
++
++
++ s = r->program + 1;
++ while (op != END) { /* While that wasn't END last time... */
++ op = OP(s);
++ printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */
++ next = regnext(s);
++ if (next == NULL) /* Next ptr. */
++ printf("(0)");
++ else
++ printf("(%d)", (s-r->program)+(next-s));
++ s += 3;
++ if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
++ /* Literal string, where present. */
++ while (*s != '\0') {
++ putchar(*s);
++ s++;
++ }
++ s++;
++ }
++ putchar('\n');
++ }
++
++ /* Header fields of interest. */
++ if (r->regstart != '\0')
++ printf("start `%c' ", r->regstart);
++ if (r->reganch)
++ printf("anchored ");
++ if (r->regmust != NULL)
++ printf("must have \"%s\"", r->regmust);
++ printf("\n");
++}
++
++/*
++ - regprop - printable representation of opcode
++ */
++static char *
++regprop(char *op)
++{
++#define BUFLEN 50
++ register char *p;
++ static char buf[BUFLEN];
++
++ strcpy(buf, ":");
++
++ switch (OP(op)) {
++ case BOL:
++ p = "BOL";
++ break;
++ case EOL:
++ p = "EOL";
++ break;
++ case ANY:
++ p = "ANY";
++ break;
++ case ANYOF:
++ p = "ANYOF";
++ break;
++ case ANYBUT:
++ p = "ANYBUT";
++ break;
++ case BRANCH:
++ p = "BRANCH";
++ break;
++ case EXACTLY:
++ p = "EXACTLY";
++ break;
++ case NOTHING:
++ p = "NOTHING";
++ break;
++ case BACK:
++ p = "BACK";
++ break;
++ case END:
++ p = "END";
++ break;
++ case OPEN+1:
++ case OPEN+2:
++ case OPEN+3:
++ case OPEN+4:
++ case OPEN+5:
++ case OPEN+6:
++ case OPEN+7:
++ case OPEN+8:
++ case OPEN+9:
++ snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "OPEN%d", OP(op)-OPEN);
++ p = NULL;
++ break;
++ case CLOSE+1:
++ case CLOSE+2:
++ case CLOSE+3:
++ case CLOSE+4:
++ case CLOSE+5:
++ case CLOSE+6:
++ case CLOSE+7:
++ case CLOSE+8:
++ case CLOSE+9:
++ snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "CLOSE%d", OP(op)-CLOSE);
++ p = NULL;
++ break;
++ case STAR:
++ p = "STAR";
++ break;
++ case PLUS:
++ p = "PLUS";
++ break;
++ default:
++ printk("<3>Regexp: corrupted opcode\n");
++ break;
++ }
++ if (p != NULL)
++ strncat(buf, p, BUFLEN-strlen(buf));
++ return(buf);
++}
++#endif
++
++
+diff -Nur linux-2.6.17/net/ipv4/netfilter/regexp/regexp.h linux-2.6.17-owrt/net/ipv4/netfilter/regexp/regexp.h
+--- linux-2.6.17/net/ipv4/netfilter/regexp/regexp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/net/ipv4/netfilter/regexp/regexp.h 2006-06-18 12:29:04.000000000 +0200
+@@ -0,0 +1,41 @@
++/*
++ * Definitions etc. for regexp(3) routines.
++ *
++ * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
++ * not the System V one.
++ */
++
++#ifndef REGEXP_H
++#define REGEXP_H
++
++
++/*
++http://www.opensource.apple.com/darwinsource/10.3/expect-1/expect/expect.h ,
++which contains a version of this library, says:
++
++ *
++ * NSUBEXP must be at least 10, and no greater than 117 or the parser
++ * will not work properly.
++ *
++
++However, it looks rather like this library is limited to 10. If you think
++otherwise, let us know.
++*/
++
++#define NSUBEXP 10
++typedef struct regexp {
++ char *startp[NSUBEXP];
++ char *endp[NSUBEXP];
++ char regstart; /* Internal use only. */
++ char reganch; /* Internal use only. */
++ char *regmust; /* Internal use only. */
++ int regmlen; /* Internal use only. */
++ char program[1]; /* Unwarranted chumminess with compiler. */
++} regexp;
++
++regexp * regcomp(char *exp, int *patternsize);
++int regexec(regexp *prog, char *string);
++void regsub(regexp *prog, char *source, char *dest);
++void regerror(char *s);
++
++#endif
+diff -Nur linux-2.6.17/net/ipv4/netfilter/regexp/regmagic.h linux-2.6.17-owrt/net/ipv4/netfilter/regexp/regmagic.h
+--- linux-2.6.17/net/ipv4/netfilter/regexp/regmagic.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/net/ipv4/netfilter/regexp/regmagic.h 2006-06-18 12:29:04.000000000 +0200
+@@ -0,0 +1,5 @@
++/*
++ * The first byte of the regexp internal "program" is actually this magic
++ * number; the start node begins in the second byte.
++ */
++#define MAGIC 0234
+diff -Nur linux-2.6.17/net/ipv4/netfilter/regexp/regsub.c linux-2.6.17-owrt/net/ipv4/netfilter/regexp/regsub.c
+--- linux-2.6.17/net/ipv4/netfilter/regexp/regsub.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/net/ipv4/netfilter/regexp/regsub.c 2006-06-18 12:29:04.000000000 +0200
+@@ -0,0 +1,95 @@
++/*
++ * regsub
++ * @(#)regsub.c 1.3 of 2 April 86
++ *
++ * Copyright (c) 1986 by University of Toronto.
++ * Written by Henry Spencer. Not derived from licensed software.
++ *
++ * Permission is granted to anyone to use this software for any
++ * purpose on any computer system, and to redistribute it freely,
++ * subject to the following restrictions:
++ *
++ * 1. The author is not responsible for the consequences of use of
++ * this software, no matter how awful, even if they arise
++ * from defects in it.
++ *
++ * 2. The origin of this software must not be misrepresented, either
++ * by explicit claim or by omission.
++ *
++ * 3. Altered versions must be plainly marked as such, and must not
++ * be misrepresented as being the original software.
++ *
++ *
++ * This code was modified by Ethan Sommer to work within the kernel
++ * (it now uses kmalloc etc..)
++ *
++ */
++#include "regexp.h"
++#include "regmagic.h"
++#include <linux/string.h>
++
++
++#ifndef CHARBITS
++#define UCHARAT(p) ((int)*(unsigned char *)(p))
++#else
++#define UCHARAT(p) ((int)*(p)&CHARBITS)
++#endif
++
++#if 0
++//void regerror(char * s)
++//{
++// printk("regexp(3): %s", s);
++// /* NOTREACHED */
++//}
++#endif
++
++/*
++ - regsub - perform substitutions after a regexp match
++ */
++void
++regsub(regexp * prog, char * source, char * dest)
++{
++ register char *src;
++ register char *dst;
++ register char c;
++ register int no;
++ register int len;
++
++ /* Not necessary and gcc doesn't like it -MLS */
++ /*extern char *strncpy();*/
++
++ if (prog == NULL || source == NULL || dest == NULL) {
++ regerror("NULL parm to regsub");
++ return;
++ }
++ if (UCHARAT(prog->program) != MAGIC) {
++ regerror("damaged regexp fed to regsub");
++ return;
++ }
++
++ src = source;
++ dst = dest;
++ while ((c = *src++) != '\0') {
++ if (c == '&')
++ no = 0;
++ else if (c == '\\' && '0' <= *src && *src <= '9')
++ no = *src++ - '0';
++ else
++ no = -1;
++
++ if (no < 0) { /* Ordinary character. */
++ if (c == '\\' && (*src == '\\' || *src == '&'))
++ c = *src++;
++ *dst++ = c;
++ } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
++ len = prog->endp[no] - prog->startp[no];
++ (void) strncpy(dst, prog->startp[no], len);
++ dst += len;
++ if (len != 0 && *(dst-1) == '\0') { /* strncpy hit NUL. */
++ regerror("damaged match string");
++ return;
++ }
++ }
++ }
++ *dst++ = '\0';
++}
diff --git a/target/linux/generic-2.6/patches/101-ipp2p_0.8.1rc1.patch b/target/linux/generic-2.6/patches/101-ipp2p_0.8.1rc1.patch
new file mode 100644
index 0000000000..9841db99ed
--- /dev/null
+++ b/target/linux/generic-2.6/patches/101-ipp2p_0.8.1rc1.patch
@@ -0,0 +1,935 @@
+diff -Nur linux-2.6.17/include/linux/netfilter_ipv4/ipt_ipp2p.h linux-2.6.17-owrt/include/linux/netfilter_ipv4/ipt_ipp2p.h
+--- linux-2.6.17/include/linux/netfilter_ipv4/ipt_ipp2p.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/include/linux/netfilter_ipv4/ipt_ipp2p.h 2006-06-18 12:37:14.000000000 +0200
+@@ -0,0 +1,31 @@
++#ifndef __IPT_IPP2P_H
++#define __IPT_IPP2P_H
++#define IPP2P_VERSION "0.8.1_rc1"
++
++struct ipt_p2p_info {
++ int cmd;
++ int debug;
++};
++
++#endif //__IPT_IPP2P_H
++
++#define SHORT_HAND_IPP2P 1 /* --ipp2p switch*/
++//#define SHORT_HAND_DATA 4 /* --ipp2p-data switch*/
++#define SHORT_HAND_NONE 5 /* no short hand*/
++
++#define IPP2P_EDK (1 << 1)
++#define IPP2P_DATA_KAZAA (1 << 2)
++#define IPP2P_DATA_EDK (1 << 3)
++#define IPP2P_DATA_DC (1 << 4)
++#define IPP2P_DC (1 << 5)
++#define IPP2P_DATA_GNU (1 << 6)
++#define IPP2P_GNU (1 << 7)
++#define IPP2P_KAZAA (1 << 8)
++#define IPP2P_BIT (1 << 9)
++#define IPP2P_APPLE (1 << 10)
++#define IPP2P_SOUL (1 << 11)
++#define IPP2P_WINMX (1 << 12)
++#define IPP2P_ARES (1 << 13)
++#define IPP2P_MUTE (1 << 14)
++#define IPP2P_WASTE (1 << 15)
++#define IPP2P_XDCC (1 << 16)
+diff -Nur linux-2.6.17/net/ipv4/netfilter/ipt_ipp2p.c linux-2.6.17-owrt/net/ipv4/netfilter/ipt_ipp2p.c
+--- linux-2.6.17/net/ipv4/netfilter/ipt_ipp2p.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/net/ipv4/netfilter/ipt_ipp2p.c 2006-06-18 12:37:14.000000000 +0200
+@@ -0,0 +1,868 @@
++#if defined(MODVERSIONS)
++#include <linux/modversions.h>
++#endif
++#include <linux/module.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/version.h>
++#include <linux/netfilter_ipv4/ipt_ipp2p.h>
++#include <net/tcp.h>
++#include <net/udp.h>
++
++#define get_u8(X,O) (*(__u8 *)(X + O))
++#define get_u16(X,O) (*(__u16 *)(X + O))
++#define get_u32(X,O) (*(__u32 *)(X + O))
++
++MODULE_AUTHOR("Eicke Friedrich/Klaus Degner <ipp2p@ipp2p.org>");
++MODULE_DESCRIPTION("An extension to iptables to identify P2P traffic.");
++MODULE_LICENSE("GPL");
++
++
++/*Search for UDP eDonkey/eMule/Kad commands*/
++int
++udp_search_edk (unsigned char *haystack, int packet_len)
++{
++ unsigned char *t = haystack;
++ t += 8;
++
++ switch (t[0]) {
++ case 0xe3:
++ { /*edonkey*/
++ switch (t[1])
++ {
++ /* client -> server status request */
++ case 0x96:
++ if (packet_len == 14) return ((IPP2P_EDK * 100) + 50);
++ break;
++ /* server -> client status request */
++ case 0x97: if (packet_len == 42) return ((IPP2P_EDK * 100) + 51);
++ break;
++ /* server description request */
++ /* e3 2a ff f0 .. | size == 6 */
++ case 0xa2: if ( (packet_len == 14) && ( get_u16(t,2) == __constant_htons(0xfff0) ) ) return ((IPP2P_EDK * 100) + 52);
++ break;
++ /* server description response */
++ /* e3 a3 ff f0 .. | size > 40 && size < 200 */
++ //case 0xa3: return ((IPP2P_EDK * 100) + 53);
++ // break;
++ case 0x9a: if (packet_len==26) return ((IPP2P_EDK * 100) + 54);
++ break;
++
++ case 0x92: if (packet_len==18) return ((IPP2P_EDK * 100) + 55);
++ break;
++ }
++ break;
++ }
++ case 0xe4:
++ {
++ switch (t[1])
++ {
++ /* e4 20 .. | size == 43 */
++ case 0x20: if ((packet_len == 43) && (t[2] != 0x00) && (t[34] != 0x00)) return ((IPP2P_EDK * 100) + 60);
++ break;
++ /* e4 00 .. 00 | size == 35 ? */
++ case 0x00: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 61);
++ break;
++ /* e4 10 .. 00 | size == 35 ? */
++ case 0x10: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 62);
++ break;
++ /* e4 18 .. 00 | size == 35 ? */
++ case 0x18: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 63);
++ break;
++ /* e4 52 .. | size = 44 */
++ case 0x52: if (packet_len == 44 ) return ((IPP2P_EDK * 100) + 64);
++ break;
++ /* e4 58 .. | size == 6 */
++ case 0x58: if (packet_len == 14 ) return ((IPP2P_EDK * 100) + 65);
++ break;
++ /* e4 59 .. | size == 2 */
++ case 0x59: if (packet_len == 10 )return ((IPP2P_EDK * 100) + 66);
++ break;
++ /* e4 28 .. | packet_len == 52,77,102,127... */
++ case 0x28: if (((packet_len-52) % 25) == 0) return ((IPP2P_EDK * 100) + 67);
++ break;
++ /* e4 50 xx xx | size == 4 */
++ case 0x50: if (packet_len == 12) return ((IPP2P_EDK * 100) + 68);
++ break;
++ /* e4 40 xx xx | size == 48 */
++ case 0x40: if (packet_len == 56) return ((IPP2P_EDK * 100) + 69);
++ break;
++ }
++ break;
++ }
++ } /* end of switch (t[0]) */
++ return 0;
++}/*udp_search_edk*/
++
++
++/*Search for UDP Gnutella commands*/
++int
++udp_search_gnu (unsigned char *haystack, int packet_len)
++{
++ unsigned char *t = haystack;
++ t += 8;
++
++ if (memcmp(t, "GND", 3) == 0) return ((IPP2P_GNU * 100) + 51);
++ if (memcmp(t, "GNUTELLA ", 9) == 0) return ((IPP2P_GNU * 100) + 52);
++ return 0;
++}/*udp_search_gnu*/
++
++
++/*Search for UDP KaZaA commands*/
++int
++udp_search_kazaa (unsigned char *haystack, int packet_len)
++{
++ unsigned char *t = haystack;
++
++ if (t[packet_len-1] == 0x00){
++ t += (packet_len - 6);
++ if (memcmp(t, "KaZaA", 5) == 0) return (IPP2P_KAZAA * 100 +50);
++ }
++
++ return 0;
++}/*udp_search_kazaa*/
++
++/*Search for UDP DirectConnect commands*/
++int
++udp_search_directconnect (unsigned char *haystack, int packet_len)
++{
++ unsigned char *t = haystack;
++ if ((*(t + 8) == 0x24) && (*(t + packet_len - 1) == 0x7c)) {
++ t+=8;
++ if (memcmp(t, "SR ", 3) == 0) return ((IPP2P_DC * 100) + 60);
++ if (memcmp(t, "Ping ", 5) == 0) return ((IPP2P_DC * 100) + 61);
++ }
++ return 0;
++}/*udp_search_directconnect*/
++
++
++
++/*Search for UDP BitTorrent commands*/
++int
++udp_search_bit (unsigned char *haystack, int packet_len)
++{
++ switch(packet_len)
++ {
++ case 24:
++ /* ^ 00 00 04 17 27 10 19 80 */
++ if ((ntohl(get_u32(haystack, 8)) == 0x00000417) && (ntohl(get_u32(haystack, 12)) == 0x27101980))
++ return (IPP2P_BIT * 100 + 50);
++ break;
++ case 44:
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000400) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
++ return (IPP2P_BIT * 100 + 51);
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000400))
++ return (IPP2P_BIT * 100 + 61);
++ break;
++ case 65:
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000404) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
++ return (IPP2P_BIT * 100 + 52);
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000404))
++ return (IPP2P_BIT * 100 + 62);
++ break;
++ case 67:
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000406) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
++ return (IPP2P_BIT * 100 + 53);
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000406))
++ return (IPP2P_BIT * 100 + 63);
++ break;
++ case 211:
++ if (get_u32(haystack, 8) == __constant_htonl(0x00000405))
++ return (IPP2P_BIT * 100 + 54);
++ break;
++ case 29:
++ if ((get_u32(haystack, 8) == __constant_htonl(0x00000401)))
++ return (IPP2P_BIT * 100 + 55);
++ break;
++ case 52:
++ if (get_u32(haystack,8) == __constant_htonl(0x00000827) &&
++ get_u32(haystack,12) == __constant_htonl(0x37502950))
++ return (IPP2P_BIT * 100 + 80);
++ break;
++ default:
++ /* this packet does not have a constant size */
++ if (packet_len >= 40 && get_u32(haystack, 16) == __constant_htonl(0x00000402) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
++ return (IPP2P_BIT * 100 + 56);
++ break;
++ }
++
++ /* some extra-bitcomet rules:
++ * "d1:" [a|r] "d2:id20:"
++ */
++ if (packet_len > 30 && get_u8(haystack, 8) == 'd' && get_u8(haystack, 9) == '1' && get_u8(haystack, 10) == ':' )
++ {
++ if (get_u8(haystack, 11) == 'a' || get_u8(haystack, 11) == 'r')
++ {
++ if (memcmp(haystack+12,"d2:id20:",8)==0)
++ return (IPP2P_BIT * 100 + 57);
++ }
++ }
++
++#if 0
++ /* bitlord rules */
++ /* packetlen must be bigger than 40 */
++ /* first 4 bytes are zero */
++ if (packet_len > 40 && get_u32(haystack, 8) == 0x00000000)
++ {
++ /* first rule: 00 00 00 00 01 00 00 xx xx xx xx 00 00 00 00*/
++ if (get_u32(haystack, 12) == 0x00000000 &&
++ get_u32(haystack, 16) == 0x00010000 &&
++ get_u32(haystack, 24) == 0x00000000 )
++ return (IPP2P_BIT * 100 + 71);
++
++ /* 00 01 00 00 0d 00 00 xx xx xx xx 00 00 00 00*/
++ if (get_u32(haystack, 12) == 0x00000001 &&
++ get_u32(haystack, 16) == 0x000d0000 &&
++ get_u32(haystack, 24) == 0x00000000 )
++ return (IPP2P_BIT * 100 + 71);
++
++
++ }
++#endif
++
++ return 0;
++}/*udp_search_bit*/
++
++
++
++/*Search for Ares commands*/
++//#define IPP2P_DEBUG_ARES
++int
++search_ares (const unsigned char *payload, const u16 plen)
++//int search_ares (unsigned char *haystack, int packet_len, int head_len)
++{
++// const unsigned char *t = haystack + head_len;
++
++ /* all ares packets start with */
++ if (payload[1] == 0 && (plen - payload[0]) == 3)
++ {
++ switch (payload[2])
++ {
++ case 0x5a:
++ /* ares connect */
++ if ( plen == 6 && payload[5] == 0x05 ) return ((IPP2P_ARES * 100) + 1);
++ break;
++ case 0x09:
++ /* ares search, min 3 chars --> 14 bytes
++ * lets define a search can be up to 30 chars --> max 34 bytes
++ */
++ if ( plen >= 14 && plen <= 34 ) return ((IPP2P_ARES * 100) + 1);
++ break;
++#ifdef IPP2P_DEBUG_ARES
++ default:
++ printk(KERN_DEBUG "Unknown Ares command %x recognized, len: %u \n", (unsigned int) payload[2],plen);
++#endif /* IPP2P_DEBUG_ARES */
++ }
++ }
++
++#if 0
++ /* found connect packet: 03 00 5a 04 03 05 */
++ /* new version ares 1.8: 03 00 5a xx xx 05 */
++ if ((plen) == 6){ /* possible connect command*/
++ if ((payload[0] == 0x03) && (payload[1] == 0x00) && (payload[2] == 0x5a) && (payload[5] == 0x05))
++ return ((IPP2P_ARES * 100) + 1);
++ }
++ if ((plen) == 60){ /* possible download command*/
++ if ((payload[59] == 0x0a) && (payload[58] == 0x0a)){
++ if (memcmp(t, "PUSH SHA1:", 10) == 0) /* found download command */
++ return ((IPP2P_ARES * 100) + 2);
++ }
++ }
++#endif
++
++ return 0;
++} /*search_ares*/
++
++/*Search for SoulSeek commands*/
++int
++search_soul (const unsigned char *payload, const u16 plen)
++{
++//#define IPP2P_DEBUG_SOUL
++ /* match: xx xx xx xx | xx = sizeof(payload) - 4 */
++ if (get_u32(payload, 0) == (plen - 4)){
++ const __u32 m=get_u32(payload, 4);
++ /* match 00 yy yy 00, yy can be everything */
++ if ( get_u8(payload, 4) == 0x00 && get_u8(payload, 7) == 0x00 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "0: Soulseek command 0x%x recognized\n",get_u32(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 1);
++ }
++
++ /* next match: 01 yy 00 00 | yy can be everything */
++ if ( get_u8(payload, 4) == 0x01 && get_u16(payload, 6) == 0x0000 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "1: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 2);
++ }
++
++ /* other soulseek commandos are: 1-5,7,9,13-18,22,23,26,28,35-37,40-46,50,51,60,62-69,91,92,1001 */
++ /* try to do this in an intelligent way */
++ /* get all small commandos */
++ switch(m)
++ {
++ case 7:
++ case 9:
++ case 22:
++ case 23:
++ case 26:
++ case 28:
++ case 50:
++ case 51:
++ case 60:
++ case 91:
++ case 92:
++ case 1001:
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "2: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 3);
++ }
++
++ if (m > 0 && m < 6 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "3: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 4);
++ }
++ if (m > 12 && m < 19 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "4: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 5);
++ }
++
++ if (m > 34 && m < 38 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "5: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 6);
++ }
++
++ if (m > 39 && m < 47 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "6: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 7);
++ }
++
++ if (m > 61 && m < 70 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "7: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 8);
++ }
++
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "unknown SOULSEEK command: 0x%x, first 16 bit: 0x%x, first 8 bit: 0x%x ,soulseek ???\n",get_u32(payload, 4),get_u16(payload, 4) >> 16,get_u8(payload, 4) >> 24);
++#endif /* IPP2P_DEBUG_SOUL */
++ }
++
++ /* match 14 00 00 00 01 yy 00 00 00 STRING(YY) 01 00 00 00 00 46|50 00 00 00 00 */
++ /* without size at the beginning !!! */
++ if ( get_u32(payload, 0) == 0x14 && get_u8(payload, 4) == 0x01 )
++ {
++ __u32 y=get_u32(payload, 5);
++ /* we need 19 chars + string */
++ if ( (y + 19) <= (plen) )
++ {
++ const unsigned char *w=payload+9+y;
++ if (get_u32(w, 0) == 0x01 && ( get_u16(w, 4) == 0x4600 || get_u16(w, 4) == 0x5000) && get_u32(w, 6) == 0x00);
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "Soulssek special client command recognized\n");
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 9);
++ }
++ }
++ return 0;
++}
++
++
++/*Search for WinMX commands*/
++int
++search_winmx (const unsigned char *payload, const u16 plen)
++{
++//#define IPP2P_DEBUG_WINMX
++ if (((plen) == 4) && (memcmp(payload, "SEND", 4) == 0)) return ((IPP2P_WINMX * 100) + 1);
++ if (((plen) == 3) && (memcmp(payload, "GET", 3) == 0)) return ((IPP2P_WINMX * 100) + 2);
++ //if (packet_len < (head_len + 10)) return 0;
++ if (plen < 10) return 0;
++
++ if ((memcmp(payload, "SEND", 4) == 0) || (memcmp(payload, "GET", 3) == 0)){
++ u16 c=4;
++ const u16 end=plen-2;
++ u8 count=0;
++ while (c < end)
++ {
++ if (payload[c]== 0x20 && payload[c+1] == 0x22)
++ {
++ c++;
++ count++;
++ if (count>=2) return ((IPP2P_WINMX * 100) + 3);
++ }
++ c++;
++ }
++ }
++
++ if ( plen == 149 && payload[0] == '8' )
++ {
++#ifdef IPP2P_DEBUG_WINMX
++ printk(KERN_INFO "maybe WinMX\n");
++#endif
++ if (get_u32(payload,17) == 0 && get_u32(payload,21) == 0 && get_u32(payload,25) == 0 &&
++// get_u32(payload,33) == __constant_htonl(0x71182b1a) && get_u32(payload,37) == __constant_htonl(0x05050000) &&
++// get_u32(payload,133) == __constant_htonl(0x31097edf) && get_u32(payload,145) == __constant_htonl(0xdcb8f792))
++ get_u16(payload,39) == 0 && get_u16(payload,135) == __constant_htons(0x7edf) && get_u16(payload,147) == __constant_htons(0xf792))
++
++ {
++#ifdef IPP2P_DEBUG_WINMX
++ printk(KERN_INFO "got WinMX\n");
++#endif
++ return ((IPP2P_WINMX * 100) + 4);
++ }
++ }
++ return 0;
++} /*search_winmx*/
++
++
++/*Search for appleJuice commands*/
++int
++search_apple (const unsigned char *payload, const u16 plen)
++{
++ if ( (plen > 7) && (payload[6] == 0x0d) && (payload[7] == 0x0a) && (memcmp(payload, "ajprot", 6) == 0)) return (IPP2P_APPLE * 100);
++
++ return 0;
++}
++
++
++/*Search for BitTorrent commands*/
++int
++search_bittorrent (const unsigned char *payload, const u16 plen)
++{
++ if (plen > 20)
++ {
++ /* test for match 0x13+"BitTorrent protocol" */
++ if (payload[0] == 0x13)
++ {
++ if (memcmp(payload+1, "BitTorrent protocol", 19) == 0) return (IPP2P_BIT * 100);
++ }
++
++ /* get tracker commandos, all starts with GET /
++ * then it can follow: scrape| announce
++ * and then ?hash_info=
++ */
++ if (memcmp(payload,"GET /",5) == 0)
++ {
++ /* message scrape */
++ if ( memcmp(payload+5,"scrape?info_hash=",17)==0 ) return (IPP2P_BIT * 100 + 1);
++ /* message announce */
++ if ( memcmp(payload+5,"announce?info_hash=",19)==0 ) return (IPP2P_BIT * 100 + 2);
++ }
++ }
++ else
++ {
++ /* bitcomet encryptes the first packet, so we have to detect another
++ * one later in the flow */
++ /* first try failed, too many missdetections */
++ //if ( size == 5 && get_u32(t,0) == __constant_htonl(1) && t[4] < 3) return (IPP2P_BIT * 100 + 3);
++
++ /* second try: block request packets */
++ if ( plen == 17 && get_u32(payload,0) == __constant_htonl(0x0d) && payload[4] == 0x06 && get_u32(payload,13) == __constant_htonl(0x4000) ) return (IPP2P_BIT * 100 + 3);
++ }
++
++ return 0;
++}
++
++
++
++/*check for Kazaa get command*/
++int
++search_kazaa (const unsigned char *payload, const u16 plen)
++
++{
++ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a) && memcmp(payload, "GET /.hash=", 11) == 0)
++ return (IPP2P_DATA_KAZAA * 100);
++
++ return 0;
++}
++
++
++/*check for gnutella get command*/
++int
++search_gnu (const unsigned char *payload, const u16 plen)
++{
++ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
++ {
++ if (memcmp(payload, "GET /get/", 9) == 0) return ((IPP2P_DATA_GNU * 100) + 1);
++ if (memcmp(payload, "GET /uri-res/", 13) == 0) return ((IPP2P_DATA_GNU * 100) + 2);
++ }
++ return 0;
++}
++
++
++/*check for gnutella get commands and other typical data*/
++int
++search_all_gnu (const unsigned char *payload, const u16 plen)
++{
++
++ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
++ {
++
++ if (memcmp(payload, "GNUTELLA CONNECT/", 17) == 0) return ((IPP2P_GNU * 100) + 1);
++ if (memcmp(payload, "GNUTELLA/", 9) == 0) return ((IPP2P_GNU * 100) + 2);
++
++
++ if ((memcmp(payload, "GET /get/", 9) == 0) || (memcmp(payload, "GET /uri-res/", 13) == 0))
++ {
++ u16 c=8;
++ const u16 end=plen-22;
++ while (c < end) {
++ if ( payload[c] == 0x0a && payload[c+1] == 0x0d && ((memcmp(&payload[c+2], "X-Gnutella-", 11) == 0) || (memcmp(&payload[c+2], "X-Queue:", 8) == 0)))
++ return ((IPP2P_GNU * 100) + 3);
++ c++;
++ }
++ }
++ }
++ return 0;
++}
++
++
++/*check for KaZaA download commands and other typical data*/
++int
++search_all_kazaa (const unsigned char *payload, const u16 plen)
++{
++ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
++ {
++
++ if (memcmp(payload, "GIVE ", 5) == 0) return ((IPP2P_KAZAA * 100) + 1);
++
++ if (memcmp(payload, "GET /", 5) == 0) {
++ u16 c = 8;
++ const u16 end=plen-22;
++ while (c < end) {
++ if ( payload[c] == 0x0a && payload[c+1] == 0x0d && ((memcmp(&payload[c+2], "X-Kazaa-Username: ", 18) == 0) || (memcmp(&payload[c+2], "User-Agent: PeerEnabler/", 24) == 0)))
++ return ((IPP2P_KAZAA * 100) + 2);
++ c++;
++ }
++ }
++ }
++ return 0;
++}
++
++/*fast check for edonkey file segment transfer command*/
++int
++search_edk (const unsigned char *payload, const u16 plen)
++{
++ if (payload[0] != 0xe3)
++ return 0;
++ else {
++ if (payload[5] == 0x47)
++ return (IPP2P_DATA_EDK * 100);
++ else
++ return 0;
++ }
++}
++
++
++
++/*intensive but slower search for some edonkey packets including size-check*/
++int
++search_all_edk (const unsigned char *payload, const u16 plen)
++{
++ if (payload[0] != 0xe3)
++ return 0;
++ else {
++ //t += head_len;
++ const u16 cmd = get_u16(payload, 1);
++ if (cmd == (plen - 5)) {
++ switch (payload[5]) {
++ case 0x01: return ((IPP2P_EDK * 100) + 1); /*Client: hello or Server:hello*/
++ case 0x4c: return ((IPP2P_EDK * 100) + 9); /*Client: Hello-Answer*/
++ }
++ }
++ return 0;
++ }
++}
++
++
++/*fast check for Direct Connect send command*/
++int
++search_dc (const unsigned char *payload, const u16 plen)
++{
++
++ if (payload[0] != 0x24 )
++ return 0;
++ else {
++ if (memcmp(&payload[1], "Send|", 5) == 0)
++ return (IPP2P_DATA_DC * 100);
++ else
++ return 0;
++ }
++
++}
++
++
++/*intensive but slower check for all direct connect packets*/
++int
++search_all_dc (const unsigned char *payload, const u16 plen)
++{
++// unsigned char *t = haystack;
++
++ if (payload[0] == 0x24 && payload[plen-1] == 0x7c)
++ {
++ const unsigned char *t=&payload[1];
++ /* Client-Hub-Protocol */
++ if (memcmp(t, "Lock ", 5) == 0) return ((IPP2P_DC * 100) + 1);
++ /* Client-Client-Protocol, some are already recognized by client-hub (like lock) */
++ if (memcmp(t, "MyNick ", 7) == 0) return ((IPP2P_DC * 100) + 38);
++ }
++ return 0;
++}
++
++/*check for mute*/
++int
++search_mute (const unsigned char *payload, const u16 plen)
++{
++ if ( plen == 209 || plen == 345 || plen == 473 || plen == 609 || plen == 1121 )
++ {
++ //printk(KERN_DEBUG "size hit: %u",size);
++ if (memcmp(payload,"PublicKey: ",11) == 0 )
++ {
++ return ((IPP2P_MUTE * 100) + 0);
++
++/* if (memcmp(t+size-14,"\x0aEndPublicKey\x0a",14) == 0)
++ {
++ printk(KERN_DEBUG "end pubic key hit: %u",size);
++
++ }*/
++ }
++ }
++ return 0;
++}
++
++
++/* check for xdcc */
++int
++search_xdcc (const unsigned char *payload, const u16 plen)
++{
++ /* search in small packets only */
++ if (plen > 20 && plen < 200 && payload[plen-1] == 0x0a && payload[plen-2] == 0x0d && memcmp(payload,"PRIVMSG ",8) == 0)
++ {
++
++ u16 x=10;
++ const u16 end=plen - 13;
++
++ /* is seems to be a irc private massage, chedck for xdcc command */
++ while (x < end)
++ {
++ if (payload[x] == ':')
++ {
++ if ( memcmp(&payload[x+1],"xdcc send #",11) == 0 )
++ return ((IPP2P_XDCC * 100) + 0);
++ }
++ x++;
++ }
++ }
++ return 0;
++}
++
++/* search for waste */
++int search_waste(const unsigned char *payload, const u16 plen)
++{
++ if ( plen >= 8 && memcmp(payload,"GET.sha1:",9) == 0)
++ return ((IPP2P_WASTE * 100) + 0);
++
++ return 0;
++}
++
++
++static struct {
++ int command;
++ __u8 short_hand; /*for fucntions included in short hands*/
++ int packet_len;
++ int (*function_name) (const unsigned char *, const u16);
++} matchlist[] = {
++ {IPP2P_EDK,SHORT_HAND_IPP2P,20, &search_all_edk},
++// {IPP2P_DATA_KAZAA,SHORT_HAND_DATA,200, &search_kazaa},
++// {IPP2P_DATA_EDK,SHORT_HAND_DATA,60, &search_edk},
++// {IPP2P_DATA_DC,SHORT_HAND_DATA,26, &search_dc},
++ {IPP2P_DC,SHORT_HAND_IPP2P,5, search_all_dc},
++// {IPP2P_DATA_GNU,SHORT_HAND_DATA,40, &search_gnu},
++ {IPP2P_GNU,SHORT_HAND_IPP2P,5, &search_all_gnu},
++ {IPP2P_KAZAA,SHORT_HAND_IPP2P,5, &search_all_kazaa},
++ {IPP2P_BIT,SHORT_HAND_IPP2P,20, &search_bittorrent},
++ {IPP2P_APPLE,SHORT_HAND_IPP2P,5, &search_apple},
++ {IPP2P_SOUL,SHORT_HAND_IPP2P,5, &search_soul},
++ {IPP2P_WINMX,SHORT_HAND_IPP2P,2, &search_winmx},
++ {IPP2P_ARES,SHORT_HAND_IPP2P,5, &search_ares},
++ {IPP2P_MUTE,SHORT_HAND_NONE,200, &search_mute},
++ {IPP2P_WASTE,SHORT_HAND_NONE,5, &search_waste},
++ {IPP2P_XDCC,SHORT_HAND_NONE,5, &search_xdcc},
++ {0,0,0,NULL}
++};
++
++
++static struct {
++ int command;
++ __u8 short_hand; /*for fucntions included in short hands*/
++ int packet_len;
++ int (*function_name) (unsigned char *, int);
++} udp_list[] = {
++ {IPP2P_KAZAA,SHORT_HAND_IPP2P,14, &udp_search_kazaa},
++ {IPP2P_BIT,SHORT_HAND_IPP2P,23, &udp_search_bit},
++ {IPP2P_GNU,SHORT_HAND_IPP2P,11, &udp_search_gnu},
++ {IPP2P_EDK,SHORT_HAND_IPP2P,9, &udp_search_edk},
++ {IPP2P_DC,SHORT_HAND_IPP2P,12, &udp_search_directconnect},
++ {0,0,0,NULL}
++};
++
++
++static int
++match(const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *matchinfo,
++ int offset,
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++ const void *hdr,
++ u_int16_t datalen,
++#endif
++
++ int *hotdrop)
++{
++ const struct ipt_p2p_info *info = matchinfo;
++ unsigned char *haystack;
++ struct iphdr *ip = skb->nh.iph;
++ int p2p_result = 0, i = 0;
++// int head_len;
++ int hlen = ntohs(ip->tot_len)-(ip->ihl*4); /*hlen = packet-data length*/
++
++ /*must not be a fragment*/
++ if (offset) {
++ if (info->debug) printk("IPP2P.match: offset found %i \n",offset);
++ return 0;
++ }
++
++ /*make sure that skb is linear*/
++ if(skb_is_nonlinear(skb)){
++ if (info->debug) printk("IPP2P.match: nonlinear skb found\n");
++ return 0;
++ }
++
++
++ haystack=(char *)ip+(ip->ihl*4); /*haystack = packet data*/
++
++ switch (ip->protocol){
++ case IPPROTO_TCP: /*what to do with a TCP packet*/
++ {
++ struct tcphdr *tcph = (void *) ip + ip->ihl * 4;
++
++ if (tcph->fin) return 0; /*if FIN bit is set bail out*/
++ if (tcph->syn) return 0; /*if SYN bit is set bail out*/
++ if (tcph->rst) return 0; /*if RST bit is set bail out*/
++
++ haystack += tcph->doff * 4; /*get TCP-Header-Size*/
++ hlen -= tcph->doff * 4;
++ while (matchlist[i].command) {
++ if ((((info->cmd & matchlist[i].command) == matchlist[i].command) ||
++ ((info->cmd & matchlist[i].short_hand) == matchlist[i].short_hand)) &&
++ (hlen > matchlist[i].packet_len)) {
++ p2p_result = matchlist[i].function_name(haystack, hlen);
++ if (p2p_result)
++ {
++ if (info->debug) printk("IPP2P.debug:TCP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
++ p2p_result, NIPQUAD(ip->saddr),ntohs(tcph->source), NIPQUAD(ip->daddr),ntohs(tcph->dest),hlen);
++ return p2p_result;
++ }
++ }
++ i++;
++ }
++ return p2p_result;
++ }
++
++ case IPPROTO_UDP: /*what to do with an UDP packet*/
++ {
++ struct udphdr *udph = (void *) ip + ip->ihl * 4;
++
++ while (udp_list[i].command){
++ if ((((info->cmd & udp_list[i].command) == udp_list[i].command) ||
++ ((info->cmd & udp_list[i].short_hand) == udp_list[i].short_hand)) &&
++ (hlen > udp_list[i].packet_len)) {
++ p2p_result = udp_list[i].function_name(haystack, hlen);
++ if (p2p_result){
++ if (info->debug) printk("IPP2P.debug:UDP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
++ p2p_result, NIPQUAD(ip->saddr),ntohs(udph->source), NIPQUAD(ip->daddr),ntohs(udph->dest),hlen);
++ return p2p_result;
++ }
++ }
++ i++;
++ }
++ return p2p_result;
++ }
++
++ default: return 0;
++ }
++}
++
++
++
++static int
++checkentry(const char *tablename,
++ const struct ipt_ip *ip,
++ void *matchinfo,
++ unsigned int matchsize,
++ unsigned int hook_mask)
++{
++ /* Must specify -p tcp */
++/* if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) {
++ * printk("ipp2p: Only works on TCP packets, use -p tcp\n");
++ * return 0;
++ * }*/
++ return 1;
++}
++
++
++
++
++static struct ipt_match ipp2p_match = {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++ { NULL, NULL },
++ "ipp2p",
++ &match,
++ &checkentry,
++ NULL,
++ THIS_MODULE
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++ .name = "ipp2p",
++ .match = &match,
++ .checkentry = &checkentry,
++ .me = THIS_MODULE,
++#endif
++};
++
++
++static int __init init(void)
++{
++ printk(KERN_INFO "IPP2P v%s loading\n", IPP2P_VERSION);
++ return ipt_register_match(&ipp2p_match);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_match(&ipp2p_match);
++ printk(KERN_INFO "IPP2P v%s unloaded\n", IPP2P_VERSION);
++}
++
++module_init(init);
++module_exit(fini);
++
++
+diff -Nur linux-2.6.17/net/ipv4/netfilter/Kconfig linux-2.6.17-owrt/net/ipv4/netfilter/Kconfig
+--- linux-2.6.17/net/ipv4/netfilter/Kconfig 2006-06-18 12:36:55.000000000 +0200
++++ linux-2.6.17-owrt/net/ipv4/netfilter/Kconfig 2006-06-18 12:37:14.000000000 +0200
+@@ -222,6 +222,12 @@
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config IP_NF_MATCH_IPP2P
++ tristate "IPP2P"
++ depends on IP_NF_IPTABLES
++ help
++ Module for matching traffic of various Peer-to-Peer applications
++
+ config IP_NF_MATCH_TOS
+ tristate "TOS match support"
+ depends on IP_NF_IPTABLES
+diff -Nur linux-2.6.17/net/ipv4/netfilter/Makefile linux-2.6.17-owrt/net/ipv4/netfilter/Makefile
+--- linux-2.6.17/net/ipv4/netfilter/Makefile 2006-06-18 12:36:55.000000000 +0200
++++ linux-2.6.17-owrt/net/ipv4/netfilter/Makefile 2006-06-18 12:38:11.000000000 +0200
+@@ -61,7 +61,7 @@
+ obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
+ obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
+ obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
+-
++obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o
+ obj-$(CONFIG_IP_NF_MATCH_LAYER7) += ipt_layer7.o
+
+ # targets
diff --git a/target/linux/generic-2.6/patches/102-openswan-2.4.0.kernel-2.6-natt.patch b/target/linux/generic-2.6/patches/102-openswan-2.4.0.kernel-2.6-natt.patch
new file mode 100644
index 0000000000..6d6939beee
--- /dev/null
+++ b/target/linux/generic-2.6/patches/102-openswan-2.4.0.kernel-2.6-natt.patch
@@ -0,0 +1,171 @@
+diff -Nur linux-2.6.16/include/net/xfrmudp.h linux-2.6.16-owrt/include/net/xfrmudp.h
+--- linux-2.6.16/include/net/xfrmudp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/include/net/xfrmudp.h 2006-03-22 21:39:54.000000000 +0100
+@@ -0,0 +1,10 @@
++/*
++ * pointer to function for type that xfrm4_input wants, to permit
++ * decoupling of XFRM from udp.c
++ */
++#define HAVE_XFRM4_UDP_REGISTER
++
++typedef int (*xfrm4_rcv_encap_t)(struct sk_buff *skb, __u16 encap_type);
++extern int udp4_register_esp_rcvencap(xfrm4_rcv_encap_t func
++ , xfrm4_rcv_encap_t *oldfunc);
++extern int udp4_unregister_esp_rcvencap(xfrm4_rcv_encap_t func);
+diff -Nur linux-2.6.16/net/ipv4/Kconfig linux-2.6.16-owrt/net/ipv4/Kconfig
+--- linux-2.6.16/net/ipv4/Kconfig 2006-03-20 06:53:29.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv4/Kconfig 2006-03-22 21:49:04.000000000 +0100
+@@ -271,6 +271,12 @@
+ Network), but can be distributed all over the Internet. If you want
+ to do that, say Y here and to "IP multicast routing" below.
+
++config IPSEC_NAT_TRAVERSAL
++ bool "IPSEC NAT-Traversal (KLIPS compatible)"
++ depends on INET
++ ---help---
++ Includes support for RFC3947/RFC3948 NAT-Traversal of ESP over UDP.
++
+ config IP_MROUTE
+ bool "IP: multicast routing"
+ depends on IP_MULTICAST
+diff -Nur linux-2.6.16/net/ipv4/udp.c linux-2.6.16-owrt/net/ipv4/udp.c
+--- linux-2.6.16/net/ipv4/udp.c 2006-03-20 06:53:29.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv4/udp.c 2006-03-22 21:39:54.000000000 +0100
+@@ -109,11 +109,14 @@
+ #include <net/inet_common.h>
+ #include <net/checksum.h>
+ #include <net/xfrm.h>
++#include <net/xfrmudp.h>
+
+ /*
+ * Snmp MIB for the UDP layer
+ */
+
++static xfrm4_rcv_encap_t xfrm4_rcv_encap_func;
++
+ DEFINE_SNMP_STAT(struct udp_mib, udp_statistics) __read_mostly;
+
+ struct hlist_head udp_hash[UDP_HTABLE_SIZE];
+@@ -882,6 +885,42 @@
+ sk_common_release(sk);
+ }
+
++#if defined(CONFIG_XFRM) || defined(CONFIG_IPSEC_NAT_TRAVERSAL)
++
++/* if XFRM isn't a module, then register it directly. */
++#if 0 && !defined(CONFIG_XFRM_MODULE) && !defined(CONFIG_IPSEC_NAT_TRAVERSAL)
++static xfrm4_rcv_encap_t xfrm4_rcv_encap_func = xfrm4_rcv_encap;
++#else
++static xfrm4_rcv_encap_t xfrm4_rcv_encap_func = NULL;
++#endif
++
++int udp4_register_esp_rcvencap(xfrm4_rcv_encap_t func
++ , xfrm4_rcv_encap_t *oldfunc)
++{
++ if(oldfunc != NULL) {
++ *oldfunc = xfrm4_rcv_encap_func;
++ }
++
++#if 0
++ if(xfrm4_rcv_encap_func != NULL)
++ return -1;
++#endif
++
++ xfrm4_rcv_encap_func = func;
++ return 0;
++}
++
++int udp4_unregister_esp_rcvencap(xfrm4_rcv_encap_t func)
++{
++ if(xfrm4_rcv_encap_func != func)
++ return -1;
++
++ xfrm4_rcv_encap_func = NULL;
++ return 0;
++}
++#endif /* CONFIG_XFRM_MODULE || CONFIG_IPSEC_NAT_TRAVERSAL */
++
++
+ /* return:
+ * 1 if the the UDP system should process it
+ * 0 if we should drop this packet
+@@ -889,9 +928,9 @@
+ */
+ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
+ {
+-#ifndef CONFIG_XFRM
++#if !defined(CONFIG_XFRM) && !defined(CONFIG_IPSEC_NAT_TRAVERSAL)
+ return 1;
+-#else
++#else /* either CONFIG_XFRM or CONFIG_IPSEC_NAT_TRAVERSAL */
+ struct udp_sock *up = udp_sk(sk);
+ struct udphdr *uh = skb->h.uh;
+ struct iphdr *iph;
+@@ -903,11 +942,11 @@
+
+ /* if we're overly short, let UDP handle it */
+ if (udpdata > skb->tail)
+- return 1;
++ return 2;
+
+ /* if this is not encapsulated socket, then just return now */
+ if (!encap_type)
+- return 1;
++ return 3;
+
+ len = skb->tail - udpdata;
+
+@@ -922,7 +961,7 @@
+ len = sizeof(struct udphdr);
+ } else
+ /* Must be an IKE packet.. pass it through */
+- return 1;
++ return 4;
+ break;
+ case UDP_ENCAP_ESPINUDP_NON_IKE:
+ /* Check if this is a keepalive packet. If so, eat it. */
+@@ -935,7 +974,7 @@
+ len = sizeof(struct udphdr) + 2 * sizeof(u32);
+ } else
+ /* Must be an IKE packet.. pass it through */
+- return 1;
++ return 5;
+ break;
+ }
+
+@@ -946,6 +985,8 @@
+ */
+ if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+ return 0;
++ if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
++ return 0;
+
+ /* Now we can update and verify the packet length... */
+ iph = skb->nh.iph;
+@@ -1010,9 +1051,13 @@
+ return 0;
+ }
+ if (ret < 0) {
+- /* process the ESP packet */
+- ret = xfrm4_rcv_encap(skb, up->encap_type);
+- UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS);
++ if(xfrm4_rcv_encap_func != NULL) {
++ ret = (*xfrm4_rcv_encap_func)(skb, up->encap_type);
++ UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS);
++ } else {
++ UDP_INC_STATS_BH(UDP_MIB_INERRORS);
++ ret = 1;
++ }
+ return -ret;
+ }
+ /* FALLTHROUGH -- it's a UDP Packet */
+@@ -1559,3 +1604,9 @@
+ EXPORT_SYMBOL(udp_proc_register);
+ EXPORT_SYMBOL(udp_proc_unregister);
+ #endif
++
++#if defined(CONFIG_IPSEC_NAT_TRAVERSAL)
++EXPORT_SYMBOL(udp4_register_esp_rcvencap);
++EXPORT_SYMBOL(udp4_unregister_esp_rcvencap);
++#endif
++
diff --git a/target/linux/generic-2.6/patches/103-netfilter-ipset.patch b/target/linux/generic-2.6/patches/103-netfilter-ipset.patch
new file mode 100644
index 0000000000..fb75c8b7eb
--- /dev/null
+++ b/target/linux/generic-2.6/patches/103-netfilter-ipset.patch
@@ -0,0 +1,5739 @@
+diff -Nur linux-2.6.16/include/linux/netfilter_ipv4/ip_set.h linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set.h
+--- linux-2.6.16/include/linux/netfilter_ipv4/ip_set.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set.h 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,489 @@
++#ifndef _IP_SET_H
++#define _IP_SET_H
++
++/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
++ * Patrick Schaaf <bof@bof.de>
++ * Martin Josefsson <gandalf@wlug.westbo.se>
++ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/*
++ * A sockopt of such quality has hardly ever been seen before on the open
++ * market! This little beauty, hardly ever used: above 64, so it's
++ * traditionally used for firewalling, not touched (even once!) by the
++ * 2.0, 2.2 and 2.4 kernels!
++ *
++ * Comes with its own certificate of authenticity, valid anywhere in the
++ * Free world!
++ *
++ * Rusty, 19.4.2000
++ */
++#define SO_IP_SET 83
++
++/*
++ * Heavily modify by Joakim Axelsson 08.03.2002
++ * - Made it more modulebased
++ *
++ * Additional heavy modifications by Jozsef Kadlecsik 22.02.2004
++ * - bindings added
++ * - in order to "deal with" backward compatibility, renamed to ipset
++ */
++
++/*
++ * Used so that the kernel module and ipset-binary can match their versions
++ */
++#define IP_SET_PROTOCOL_VERSION 2
++
++#define IP_SET_MAXNAMELEN 32 /* set names and set typenames */
++
++/* Lets work with our own typedef for representing an IP address.
++ * We hope to make the code more portable, possibly to IPv6...
++ *
++ * The representation works in HOST byte order, because most set types
++ * will perform arithmetic operations and compare operations.
++ *
++ * For now the type is an uint32_t.
++ *
++ * Make sure to ONLY use the functions when translating and parsing
++ * in order to keep the host byte order and make it more portable:
++ * parse_ip()
++ * parse_mask()
++ * parse_ipandmask()
++ * ip_tostring()
++ * (Joakim: where are they???)
++ */
++
++typedef uint32_t ip_set_ip_t;
++
++/* Sets are identified by an id in kernel space. Tweak with ip_set_id_t
++ * and IP_SET_INVALID_ID if you want to increase the max number of sets.
++ */
++typedef uint16_t ip_set_id_t;
++
++#define IP_SET_INVALID_ID 65535
++
++/* How deep we follow bindings */
++#define IP_SET_MAX_BINDINGS 6
++
++/*
++ * Option flags for kernel operations (ipt_set_info)
++ */
++#define IPSET_SRC 0x01 /* Source match/add */
++#define IPSET_DST 0x02 /* Destination match/add */
++#define IPSET_MATCH_INV 0x04 /* Inverse matching */
++
++/*
++ * Set types (flavours)
++ */
++#define IPSET_TYPE_IP 0 /* IP address type of set */
++#define IPSET_TYPE_PORT 1 /* Port type of set */
++
++/* Reserved keywords */
++#define IPSET_TOKEN_DEFAULT ":default:"
++#define IPSET_TOKEN_ALL ":all:"
++
++/* SO_IP_SET operation constants, and their request struct types.
++ *
++ * Operation ids:
++ * 0-99: commands with version checking
++ * 100-199: add/del/test/bind/unbind
++ * 200-299: list, save, restore
++ */
++
++/* Single shot operations:
++ * version, create, destroy, flush, rename and swap
++ *
++ * Sets are identified by name.
++ */
++
++#define IP_SET_REQ_STD \
++ unsigned op; \
++ unsigned version; \
++ char name[IP_SET_MAXNAMELEN]
++
++#define IP_SET_OP_CREATE 0x00000001 /* Create a new (empty) set */
++struct ip_set_req_create {
++ IP_SET_REQ_STD;
++ char typename[IP_SET_MAXNAMELEN];
++};
++
++#define IP_SET_OP_DESTROY 0x00000002 /* Remove a (empty) set */
++struct ip_set_req_std {
++ IP_SET_REQ_STD;
++};
++
++#define IP_SET_OP_FLUSH 0x00000003 /* Remove all IPs in a set */
++/* Uses ip_set_req_std */
++
++#define IP_SET_OP_RENAME 0x00000004 /* Rename a set */
++/* Uses ip_set_req_create */
++
++#define IP_SET_OP_SWAP 0x00000005 /* Swap two sets */
++/* Uses ip_set_req_create */
++
++union ip_set_name_index {
++ char name[IP_SET_MAXNAMELEN];
++ ip_set_id_t index;
++};
++
++#define IP_SET_OP_GET_BYNAME 0x00000006 /* Get set index by name */
++struct ip_set_req_get_set {
++ unsigned op;
++ unsigned version;
++ union ip_set_name_index set;
++};
++
++#define IP_SET_OP_GET_BYINDEX 0x00000007 /* Get set name by index */
++/* Uses ip_set_req_get_set */
++
++#define IP_SET_OP_VERSION 0x00000100 /* Ask kernel version */
++struct ip_set_req_version {
++ unsigned op;
++ unsigned version;
++};
++
++/* Double shots operations:
++ * add, del, test, bind and unbind.
++ *
++ * First we query the kernel to get the index and type of the target set,
++ * then issue the command. Validity of IP is checked in kernel in order
++ * to minimalize sockopt operations.
++ */
++
++/* Get minimal set data for add/del/test/bind/unbind IP */
++#define IP_SET_OP_ADT_GET 0x00000010 /* Get set and type */
++struct ip_set_req_adt_get {
++ unsigned op;
++ unsigned version;
++ union ip_set_name_index set;
++ char typename[IP_SET_MAXNAMELEN];
++};
++
++#define IP_SET_REQ_BYINDEX \
++ unsigned op; \
++ ip_set_id_t index;
++
++struct ip_set_req_adt {
++ IP_SET_REQ_BYINDEX;
++};
++
++#define IP_SET_OP_ADD_IP 0x00000101 /* Add an IP to a set */
++/* Uses ip_set_req_adt, with type specific addage */
++
++#define IP_SET_OP_DEL_IP 0x00000102 /* Remove an IP from a set */
++/* Uses ip_set_req_adt, with type specific addage */
++
++#define IP_SET_OP_TEST_IP 0x00000103 /* Test an IP in a set */
++/* Uses ip_set_req_adt, with type specific addage */
++
++#define IP_SET_OP_BIND_SET 0x00000104 /* Bind an IP to a set */
++/* Uses ip_set_req_bind, with type specific addage */
++struct ip_set_req_bind {
++ IP_SET_REQ_BYINDEX;
++ char binding[IP_SET_MAXNAMELEN];
++};
++
++#define IP_SET_OP_UNBIND_SET 0x00000105 /* Unbind an IP from a set */
++/* Uses ip_set_req_bind, with type speficic addage
++ * index = 0 means unbinding for all sets */
++
++#define IP_SET_OP_TEST_BIND_SET 0x00000106 /* Test binding an IP to a set */
++/* Uses ip_set_req_bind, with type specific addage */
++
++/* Multiple shots operations: list, save, restore.
++ *
++ * - check kernel version and query the max number of sets
++ * - get the basic information on all sets
++ * and size required for the next step
++ * - get actual set data: header, data, bindings
++ */
++
++/* Get max_sets and the index of a queried set
++ */
++#define IP_SET_OP_MAX_SETS 0x00000020
++struct ip_set_req_max_sets {
++ unsigned op;
++ unsigned version;
++ ip_set_id_t max_sets; /* max_sets */
++ ip_set_id_t sets; /* real number of sets */
++ union ip_set_name_index set; /* index of set if name used */
++};
++
++/* Get the id and name of the sets plus size for next step */
++#define IP_SET_OP_LIST_SIZE 0x00000201
++#define IP_SET_OP_SAVE_SIZE 0x00000202
++struct ip_set_req_setnames {
++ unsigned op;
++ ip_set_id_t index; /* set to list/save */
++ size_t size; /* size to get setdata/bindings */
++ /* followed by sets number of struct ip_set_name_list */
++};
++
++struct ip_set_name_list {
++ char name[IP_SET_MAXNAMELEN];
++ char typename[IP_SET_MAXNAMELEN];
++ ip_set_id_t index;
++ ip_set_id_t id;
++};
++
++/* The actual list operation */
++#define IP_SET_OP_LIST 0x00000203
++struct ip_set_req_list {
++ IP_SET_REQ_BYINDEX;
++ /* sets number of struct ip_set_list in reply */
++};
++
++struct ip_set_list {
++ ip_set_id_t index;
++ ip_set_id_t binding;
++ u_int32_t ref;
++ size_t header_size; /* Set header data of header_size */
++ size_t members_size; /* Set members data of members_size */
++ size_t bindings_size; /* Set bindings data of bindings_size */
++};
++
++struct ip_set_hash_list {
++ ip_set_ip_t ip;
++ ip_set_id_t binding;
++};
++
++/* The save operation */
++#define IP_SET_OP_SAVE 0x00000204
++/* Uses ip_set_req_list, in the reply replaced by
++ * sets number of struct ip_set_save plus a marker
++ * ip_set_save followed by ip_set_hash_save structures.
++ */
++struct ip_set_save {
++ ip_set_id_t index;
++ ip_set_id_t binding;
++ size_t header_size; /* Set header data of header_size */
++ size_t members_size; /* Set members data of members_size */
++};
++
++/* At restoring, ip == 0 means default binding for the given set: */
++struct ip_set_hash_save {
++ ip_set_ip_t ip;
++ ip_set_id_t id;
++ ip_set_id_t binding;
++};
++
++/* The restore operation */
++#define IP_SET_OP_RESTORE 0x00000205
++/* Uses ip_set_req_setnames followed by ip_set_restore structures
++ * plus a marker ip_set_restore, followed by ip_set_hash_save
++ * structures.
++ */
++struct ip_set_restore {
++ char name[IP_SET_MAXNAMELEN];
++ char typename[IP_SET_MAXNAMELEN];
++ ip_set_id_t index;
++ size_t header_size; /* Create data of header_size */
++ size_t members_size; /* Set members data of members_size */
++};
++
++static inline int bitmap_bytes(ip_set_ip_t a, ip_set_ip_t b)
++{
++ return 4 * ((((b - a + 8) / 8) + 3) / 4);
++}
++
++#ifdef __KERNEL__
++
++#define ip_set_printk(format, args...) \
++ do { \
++ printk("%s: %s: ", __FILE__, __FUNCTION__); \
++ printk(format "\n" , ## args); \
++ } while (0)
++
++#if defined(IP_SET_DEBUG)
++#define DP(format, args...) \
++ do { \
++ printk("%s: %s (DBG): ", __FILE__, __FUNCTION__);\
++ printk(format "\n" , ## args); \
++ } while (0)
++#define IP_SET_ASSERT(x) \
++ do { \
++ if (!(x)) \
++ printk("IP_SET_ASSERT: %s:%i(%s)\n", \
++ __FILE__, __LINE__, __FUNCTION__); \
++ } while (0)
++#else
++#define DP(format, args...)
++#define IP_SET_ASSERT(x)
++#endif
++
++struct ip_set;
++
++/*
++ * The ip_set_type definition - one per set type, e.g. "ipmap".
++ *
++ * Each individual set has a pointer, set->type, going to one
++ * of these structures. Function pointers inside the structure implement
++ * the real behaviour of the sets.
++ *
++ * If not mentioned differently, the implementation behind the function
++ * pointers of a set_type, is expected to return 0 if ok, and a negative
++ * errno (e.g. -EINVAL) on error.
++ */
++struct ip_set_type {
++ struct list_head list; /* next in list of set types */
++
++ /* test for IP in set (kernel: iptables -m set src|dst)
++ * return 0 if not in set, 1 if in set.
++ */
++ int (*testip_kernel) (struct ip_set *set,
++ const struct sk_buff * skb,
++ u_int32_t flags,
++ ip_set_ip_t *ip);
++
++ /* test for IP in set (userspace: ipset -T set IP)
++ * return 0 if not in set, 1 if in set.
++ */
++ int (*testip) (struct ip_set *set,
++ const void *data, size_t size,
++ ip_set_ip_t *ip);
++
++ /*
++ * Size of the data structure passed by when
++ * adding/deletin/testing an entry.
++ */
++ size_t reqsize;
++
++ /* Add IP into set (userspace: ipset -A set IP)
++ * Return -EEXIST if the address is already in the set,
++ * and -ERANGE if the address lies outside the set bounds.
++ * If the address was not already in the set, 0 is returned.
++ */
++ int (*addip) (struct ip_set *set,
++ const void *data, size_t size,
++ ip_set_ip_t *ip);
++
++ /* Add IP into set (kernel: iptables ... -j SET set src|dst)
++ * Return -EEXIST if the address is already in the set,
++ * and -ERANGE if the address lies outside the set bounds.
++ * If the address was not already in the set, 0 is returned.
++ */
++ int (*addip_kernel) (struct ip_set *set,
++ const struct sk_buff * skb,
++ u_int32_t flags,
++ ip_set_ip_t *ip);
++
++ /* remove IP from set (userspace: ipset -D set --entry x)
++ * Return -EEXIST if the address is NOT in the set,
++ * and -ERANGE if the address lies outside the set bounds.
++ * If the address really was in the set, 0 is returned.
++ */
++ int (*delip) (struct ip_set *set,
++ const void *data, size_t size,
++ ip_set_ip_t *ip);
++
++ /* remove IP from set (kernel: iptables ... -j SET --entry x)
++ * Return -EEXIST if the address is NOT in the set,
++ * and -ERANGE if the address lies outside the set bounds.
++ * If the address really was in the set, 0 is returned.
++ */
++ int (*delip_kernel) (struct ip_set *set,
++ const struct sk_buff * skb,
++ u_int32_t flags,
++ ip_set_ip_t *ip);
++
++ /* new set creation - allocated type specific items
++ */
++ int (*create) (struct ip_set *set,
++ const void *data, size_t size);
++
++ /* retry the operation after successfully tweaking the set
++ */
++ int (*retry) (struct ip_set *set);
++
++ /* set destruction - free type specific items
++ * There is no return value.
++ * Can be called only when child sets are destroyed.
++ */
++ void (*destroy) (struct ip_set *set);
++
++ /* set flushing - reset all bits in the set, or something similar.
++ * There is no return value.
++ */
++ void (*flush) (struct ip_set *set);
++
++ /* Listing: size needed for header
++ */
++ size_t header_size;
++
++ /* Listing: Get the header
++ *
++ * Fill in the information in "data".
++ * This function is always run after list_header_size() under a
++ * writelock on the set. Therefor is the length of "data" always
++ * correct.
++ */
++ void (*list_header) (const struct ip_set *set,
++ void *data);
++
++ /* Listing: Get the size for the set members
++ */
++ int (*list_members_size) (const struct ip_set *set);
++
++ /* Listing: Get the set members
++ *
++ * Fill in the information in "data".
++ * This function is always run after list_member_size() under a
++ * writelock on the set. Therefor is the length of "data" always
++ * correct.
++ */
++ void (*list_members) (const struct ip_set *set,
++ void *data);
++
++ char typename[IP_SET_MAXNAMELEN];
++ char typecode;
++ int protocol_version;
++
++ /* Set this to THIS_MODULE if you are a module, otherwise NULL */
++ struct module *me;
++};
++
++extern int ip_set_register_set_type(struct ip_set_type *set_type);
++extern void ip_set_unregister_set_type(struct ip_set_type *set_type);
++
++/* A generic ipset */
++struct ip_set {
++ char name[IP_SET_MAXNAMELEN]; /* the name of the set */
++ rwlock_t lock; /* lock for concurrency control */
++ ip_set_id_t id; /* set id for swapping */
++ ip_set_id_t binding; /* default binding for the set */
++ atomic_t ref; /* in kernel and in hash references */
++ struct ip_set_type *type; /* the set types */
++ void *data; /* pooltype specific data */
++};
++
++/* Structure to bind set elements to sets */
++struct ip_set_hash {
++ struct list_head list; /* list of clashing entries in hash */
++ ip_set_ip_t ip; /* ip from set */
++ ip_set_id_t id; /* set id */
++ ip_set_id_t binding; /* set we bind the element to */
++};
++
++/* register and unregister set references */
++extern ip_set_id_t ip_set_get_byname(const char name[IP_SET_MAXNAMELEN]);
++extern ip_set_id_t ip_set_get_byindex(ip_set_id_t id);
++extern void ip_set_put(ip_set_id_t id);
++
++/* API for iptables set match, and SET target */
++extern void ip_set_addip_kernel(ip_set_id_t id,
++ const struct sk_buff *skb,
++ const u_int32_t *flags);
++extern void ip_set_delip_kernel(ip_set_id_t id,
++ const struct sk_buff *skb,
++ const u_int32_t *flags);
++extern int ip_set_testip_kernel(ip_set_id_t id,
++ const struct sk_buff *skb,
++ const u_int32_t *flags);
++
++#endif /* __KERNEL__ */
++
++#endif /*_IP_SET_H*/
+diff -Nur linux-2.6.16/include/linux/netfilter_ipv4/ip_set_iphash.h linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_iphash.h
+--- linux-2.6.16/include/linux/netfilter_ipv4/ip_set_iphash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_iphash.h 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,30 @@
++#ifndef __IP_SET_IPHASH_H
++#define __IP_SET_IPHASH_H
++
++#include <linux/netfilter_ipv4/ip_set.h>
++
++#define SETTYPE_NAME "iphash"
++#define MAX_RANGE 0x0000FFFF
++
++struct ip_set_iphash {
++ ip_set_ip_t *members; /* the iphash proper */
++ uint32_t initval; /* initval for jhash_1word */
++ uint32_t prime; /* prime for double hashing */
++ uint32_t hashsize; /* hash size */
++ uint16_t probes; /* max number of probes */
++ uint16_t resize; /* resize factor in percent */
++ ip_set_ip_t netmask; /* netmask */
++};
++
++struct ip_set_req_iphash_create {
++ uint32_t hashsize;
++ uint16_t probes;
++ uint16_t resize;
++ ip_set_ip_t netmask;
++};
++
++struct ip_set_req_iphash {
++ ip_set_ip_t ip;
++};
++
++#endif /* __IP_SET_IPHASH_H */
+diff -Nur linux-2.6.16/include/linux/netfilter_ipv4/ip_set_ipmap.h linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_ipmap.h
+--- linux-2.6.16/include/linux/netfilter_ipv4/ip_set_ipmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_ipmap.h 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,56 @@
++#ifndef __IP_SET_IPMAP_H
++#define __IP_SET_IPMAP_H
++
++#include <linux/netfilter_ipv4/ip_set.h>
++
++#define SETTYPE_NAME "ipmap"
++#define MAX_RANGE 0x0000FFFF
++
++struct ip_set_ipmap {
++ void *members; /* the ipmap proper */
++ ip_set_ip_t first_ip; /* host byte order, included in range */
++ ip_set_ip_t last_ip; /* host byte order, included in range */
++ ip_set_ip_t netmask; /* subnet netmask */
++ ip_set_ip_t sizeid; /* size of set in IPs */
++ u_int16_t hosts; /* number of hosts in a subnet */
++};
++
++struct ip_set_req_ipmap_create {
++ ip_set_ip_t from;
++ ip_set_ip_t to;
++ ip_set_ip_t netmask;
++};
++
++struct ip_set_req_ipmap {
++ ip_set_ip_t ip;
++};
++
++unsigned int
++mask_to_bits(ip_set_ip_t mask)
++{
++ unsigned int bits = 32;
++ ip_set_ip_t maskaddr;
++
++ if (mask == 0xFFFFFFFF)
++ return bits;
++
++ maskaddr = 0xFFFFFFFE;
++ while (--bits >= 0 && maskaddr != mask)
++ maskaddr <<= 1;
++
++ return bits;
++}
++
++ip_set_ip_t
++range_to_mask(ip_set_ip_t from, ip_set_ip_t to, unsigned int *bits)
++{
++ ip_set_ip_t mask = 0xFFFFFFFE;
++
++ *bits = 32;
++ while (--(*bits) >= 0 && mask && (to & mask) != from)
++ mask <<= 1;
++
++ return mask;
++}
++
++#endif /* __IP_SET_IPMAP_H */
+diff -Nur linux-2.6.16/include/linux/netfilter_ipv4/ip_set_iptree.h linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_iptree.h
+--- linux-2.6.16/include/linux/netfilter_ipv4/ip_set_iptree.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_iptree.h 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,39 @@
++#ifndef __IP_SET_IPTREE_H
++#define __IP_SET_IPTREE_H
++
++#include <linux/netfilter_ipv4/ip_set.h>
++
++#define SETTYPE_NAME "iptree"
++#define MAX_RANGE 0x0000FFFF
++
++struct ip_set_iptreed {
++ unsigned long expires[255]; /* x.x.x.ADDR */
++};
++
++struct ip_set_iptreec {
++ struct ip_set_iptreed *tree[255]; /* x.x.ADDR.* */
++};
++
++struct ip_set_iptreeb {
++ struct ip_set_iptreec *tree[255]; /* x.ADDR.*.* */
++};
++
++struct ip_set_iptree {
++ unsigned int timeout;
++ unsigned int gc_interval;
++#ifdef __KERNEL__
++ struct timer_list gc;
++ struct ip_set_iptreeb *tree[255]; /* ADDR.*.*.* */
++#endif
++};
++
++struct ip_set_req_iptree_create {
++ unsigned int timeout;
++};
++
++struct ip_set_req_iptree {
++ ip_set_ip_t ip;
++ unsigned int timeout;
++};
++
++#endif /* __IP_SET_IPTREE_H */
+diff -Nur linux-2.6.16/include/linux/netfilter_ipv4/ip_set_jhash.h linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_jhash.h
+--- linux-2.6.16/include/linux/netfilter_ipv4/ip_set_jhash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_jhash.h 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,148 @@
++#ifndef _LINUX_IPSET_JHASH_H
++#define _LINUX_IPSET_JHASH_H
++
++/* This is a copy of linux/jhash.h but the types u32/u8 are changed
++ * to __u32/__u8 so that the header file can be included into
++ * userspace code as well. Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
++ */
++
++/* jhash.h: Jenkins hash support.
++ *
++ * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
++ *
++ * http://burtleburtle.net/bob/hash/
++ *
++ * These are the credits from Bob's sources:
++ *
++ * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
++ * hash(), hash2(), hash3, and mix() are externally useful functions.
++ * Routines to test the hash are included if SELF_TEST is defined.
++ * You can use this free for any purpose. It has no warranty.
++ *
++ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
++ *
++ * I've modified Bob's hash to be useful in the Linux kernel, and
++ * any bugs present are surely my fault. -DaveM
++ */
++
++/* NOTE: Arguments are modified. */
++#define __jhash_mix(a, b, c) \
++{ \
++ a -= b; a -= c; a ^= (c>>13); \
++ b -= c; b -= a; b ^= (a<<8); \
++ c -= a; c -= b; c ^= (b>>13); \
++ a -= b; a -= c; a ^= (c>>12); \
++ b -= c; b -= a; b ^= (a<<16); \
++ c -= a; c -= b; c ^= (b>>5); \
++ a -= b; a -= c; a ^= (c>>3); \
++ b -= c; b -= a; b ^= (a<<10); \
++ c -= a; c -= b; c ^= (b>>15); \
++}
++
++/* The golden ration: an arbitrary value */
++#define JHASH_GOLDEN_RATIO 0x9e3779b9
++
++/* The most generic version, hashes an arbitrary sequence
++ * of bytes. No alignment or length assumptions are made about
++ * the input key.
++ */
++static inline __u32 jhash(void *key, __u32 length, __u32 initval)
++{
++ __u32 a, b, c, len;
++ __u8 *k = key;
++
++ len = length;
++ a = b = JHASH_GOLDEN_RATIO;
++ c = initval;
++
++ while (len >= 12) {
++ a += (k[0] +((__u32)k[1]<<8) +((__u32)k[2]<<16) +((__u32)k[3]<<24));
++ b += (k[4] +((__u32)k[5]<<8) +((__u32)k[6]<<16) +((__u32)k[7]<<24));
++ c += (k[8] +((__u32)k[9]<<8) +((__u32)k[10]<<16)+((__u32)k[11]<<24));
++
++ __jhash_mix(a,b,c);
++
++ k += 12;
++ len -= 12;
++ }
++
++ c += length;
++ switch (len) {
++ case 11: c += ((__u32)k[10]<<24);
++ case 10: c += ((__u32)k[9]<<16);
++ case 9 : c += ((__u32)k[8]<<8);
++ case 8 : b += ((__u32)k[7]<<24);
++ case 7 : b += ((__u32)k[6]<<16);
++ case 6 : b += ((__u32)k[5]<<8);
++ case 5 : b += k[4];
++ case 4 : a += ((__u32)k[3]<<24);
++ case 3 : a += ((__u32)k[2]<<16);
++ case 2 : a += ((__u32)k[1]<<8);
++ case 1 : a += k[0];
++ };
++
++ __jhash_mix(a,b,c);
++
++ return c;
++}
++
++/* A special optimized version that handles 1 or more of __u32s.
++ * The length parameter here is the number of __u32s in the key.
++ */
++static inline __u32 jhash2(__u32 *k, __u32 length, __u32 initval)
++{
++ __u32 a, b, c, len;
++
++ a = b = JHASH_GOLDEN_RATIO;
++ c = initval;
++ len = length;
++
++ while (len >= 3) {
++ a += k[0];
++ b += k[1];
++ c += k[2];
++ __jhash_mix(a, b, c);
++ k += 3; len -= 3;
++ }
++
++ c += length * 4;
++
++ switch (len) {
++ case 2 : b += k[1];
++ case 1 : a += k[0];
++ };
++
++ __jhash_mix(a,b,c);
++
++ return c;
++}
++
++
++/* A special ultra-optimized versions that knows they are hashing exactly
++ * 3, 2 or 1 word(s).
++ *
++ * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
++ * done at the end is not done here.
++ */
++static inline __u32 jhash_3words(__u32 a, __u32 b, __u32 c, __u32 initval)
++{
++ a += JHASH_GOLDEN_RATIO;
++ b += JHASH_GOLDEN_RATIO;
++ c += initval;
++
++ __jhash_mix(a, b, c);
++
++ return c;
++}
++
++static inline __u32 jhash_2words(__u32 a, __u32 b, __u32 initval)
++{
++ return jhash_3words(a, b, 0, initval);
++}
++
++static inline __u32 jhash_1word(__u32 a, __u32 initval)
++{
++ return jhash_3words(a, 0, 0, initval);
++}
++
++#endif /* _LINUX_IPSET_JHASH_H */
+diff -Nur linux-2.6.16/include/linux/netfilter_ipv4/ip_set_macipmap.h linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_macipmap.h
+--- linux-2.6.16/include/linux/netfilter_ipv4/ip_set_macipmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_macipmap.h 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,38 @@
++#ifndef __IP_SET_MACIPMAP_H
++#define __IP_SET_MACIPMAP_H
++
++#include <linux/netfilter_ipv4/ip_set.h>
++
++#define SETTYPE_NAME "macipmap"
++#define MAX_RANGE 0x0000FFFF
++
++/* general flags */
++#define IPSET_MACIP_MATCHUNSET 1
++
++/* per ip flags */
++#define IPSET_MACIP_ISSET 1
++
++struct ip_set_macipmap {
++ void *members; /* the macipmap proper */
++ ip_set_ip_t first_ip; /* host byte order, included in range */
++ ip_set_ip_t last_ip; /* host byte order, included in range */
++ u_int32_t flags;
++};
++
++struct ip_set_req_macipmap_create {
++ ip_set_ip_t from;
++ ip_set_ip_t to;
++ u_int32_t flags;
++};
++
++struct ip_set_req_macipmap {
++ ip_set_ip_t ip;
++ unsigned char ethernet[ETH_ALEN];
++};
++
++struct ip_set_macip {
++ unsigned short flags;
++ unsigned char ethernet[ETH_ALEN];
++};
++
++#endif /* __IP_SET_MACIPMAP_H */
+diff -Nur linux-2.6.16/include/linux/netfilter_ipv4/ip_set_malloc.h linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_malloc.h
+--- linux-2.6.16/include/linux/netfilter_ipv4/ip_set_malloc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_malloc.h 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,42 @@
++#ifndef _IP_SET_MALLOC_H
++#define _IP_SET_MALLOC_H
++
++#ifdef __KERNEL__
++
++/* Memory allocation and deallocation */
++static size_t max_malloc_size = 0;
++
++static inline void init_max_malloc_size(void)
++{
++#define CACHE(x) max_malloc_size = x;
++#include <linux/kmalloc_sizes.h>
++#undef CACHE
++}
++
++static inline void * ip_set_malloc_atomic(size_t bytes)
++{
++ if (bytes > max_malloc_size)
++ return __vmalloc(bytes, GFP_ATOMIC, PAGE_KERNEL);
++ else
++ return kmalloc(bytes, GFP_ATOMIC);
++}
++
++static inline void * ip_set_malloc(size_t bytes)
++{
++ if (bytes > max_malloc_size)
++ return vmalloc(bytes);
++ else
++ return kmalloc(bytes, GFP_KERNEL);
++}
++
++static inline void ip_set_free(void * data, size_t bytes)
++{
++ if (bytes > max_malloc_size)
++ vfree(data);
++ else
++ kfree(data);
++}
++
++#endif /* __KERNEL__ */
++
++#endif /*_IP_SET_MALLOC_H*/
+diff -Nur linux-2.6.16/include/linux/netfilter_ipv4/ip_set_nethash.h linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_nethash.h
+--- linux-2.6.16/include/linux/netfilter_ipv4/ip_set_nethash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_nethash.h 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,55 @@
++#ifndef __IP_SET_NETHASH_H
++#define __IP_SET_NETHASH_H
++
++#include <linux/netfilter_ipv4/ip_set.h>
++
++#define SETTYPE_NAME "nethash"
++#define MAX_RANGE 0x0000FFFF
++
++struct ip_set_nethash {
++ ip_set_ip_t *members; /* the nethash proper */
++ uint32_t initval; /* initval for jhash_1word */
++ uint32_t prime; /* prime for double hashing */
++ uint32_t hashsize; /* hash size */
++ uint16_t probes; /* max number of probes */
++ uint16_t resize; /* resize factor in percent */
++ unsigned char cidr[30]; /* CIDR sizes */
++};
++
++struct ip_set_req_nethash_create {
++ uint32_t hashsize;
++ uint16_t probes;
++ uint16_t resize;
++};
++
++struct ip_set_req_nethash {
++ ip_set_ip_t ip;
++ unsigned char cidr;
++};
++
++static unsigned char shifts[] = {255, 253, 249, 241, 225, 193, 129, 1};
++
++static inline ip_set_ip_t
++pack(ip_set_ip_t ip, unsigned char cidr)
++{
++ ip_set_ip_t addr, *paddr = &addr;
++ unsigned char n, t, *a;
++
++ addr = htonl(ip & (0xFFFFFFFF << (32 - (cidr))));
++#ifdef __KERNEL__
++ DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr);
++#endif
++ n = cidr / 8;
++ t = cidr % 8;
++ a = &((unsigned char *)paddr)[n];
++ *a = *a /(1 << (8 - t)) + shifts[t];
++#ifdef __KERNEL__
++ DP("n: %u, t: %u, a: %u", n, t, *a);
++ DP("ip:%u.%u.%u.%u/%u, %u.%u.%u.%u",
++ HIPQUAD(ip), cidr, NIPQUAD(addr));
++#endif
++
++ return ntohl(addr);
++}
++
++#endif /* __IP_SET_NETHASH_H */
+diff -Nur linux-2.6.16/include/linux/netfilter_ipv4/ip_set_portmap.h linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_portmap.h
+--- linux-2.6.16/include/linux/netfilter_ipv4/ip_set_portmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_portmap.h 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,25 @@
++#ifndef __IP_SET_PORTMAP_H
++#define __IP_SET_PORTMAP_H
++
++#include <linux/netfilter_ipv4/ip_set.h>
++
++#define SETTYPE_NAME "portmap"
++#define MAX_RANGE 0x0000FFFF
++#define INVALID_PORT (MAX_RANGE + 1)
++
++struct ip_set_portmap {
++ void *members; /* the portmap proper */
++ ip_set_ip_t first_port; /* host byte order, included in range */
++ ip_set_ip_t last_port; /* host byte order, included in range */
++};
++
++struct ip_set_req_portmap_create {
++ ip_set_ip_t from;
++ ip_set_ip_t to;
++};
++
++struct ip_set_req_portmap {
++ ip_set_ip_t port;
++};
++
++#endif /* __IP_SET_PORTMAP_H */
+diff -Nur linux-2.6.16/include/linux/netfilter_ipv4/ip_set_prime.h linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_prime.h
+--- linux-2.6.16/include/linux/netfilter_ipv4/ip_set_prime.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/include/linux/netfilter_ipv4/ip_set_prime.h 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,34 @@
++#ifndef __IP_SET_PRIME_H
++#define __IP_SET_PRIME_H
++
++static inline unsigned make_prime_bound(unsigned nr)
++{
++ unsigned long long nr64 = nr;
++ unsigned long long x = 1;
++ nr = 1;
++ while (x <= nr64) { x <<= 2; nr <<= 1; }
++ return nr;
++}
++
++static inline int make_prime_check(unsigned nr)
++{
++ unsigned x = 3;
++ unsigned b = make_prime_bound(nr);
++ while (x <= b) {
++ if (0 == (nr % x)) return 0;
++ x += 2;
++ }
++ return 1;
++}
++
++static unsigned make_prime(unsigned nr)
++{
++ if (0 == (nr & 1)) nr--;
++ while (nr > 1) {
++ if (make_prime_check(nr)) return nr;
++ nr -= 2;
++ }
++ return 2;
++}
++
++#endif /* __IP_SET_PRIME_H */
+diff -Nur linux-2.6.16/include/linux/netfilter_ipv4/ipt_set.h linux-2.6.16-owrt/include/linux/netfilter_ipv4/ipt_set.h
+--- linux-2.6.16/include/linux/netfilter_ipv4/ipt_set.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/include/linux/netfilter_ipv4/ipt_set.h 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,21 @@
++#ifndef _IPT_SET_H
++#define _IPT_SET_H
++
++#include <linux/netfilter_ipv4/ip_set.h>
++
++struct ipt_set_info {
++ ip_set_id_t index;
++ u_int32_t flags[IP_SET_MAX_BINDINGS + 1];
++};
++
++/* match info */
++struct ipt_set_info_match {
++ struct ipt_set_info match_set;
++};
++
++struct ipt_set_info_target {
++ struct ipt_set_info add_set;
++ struct ipt_set_info del_set;
++};
++
++#endif /*_IPT_SET_H*/
+diff -Nur linux-2.6.16/net/ipv4/netfilter/ip_set.c linux-2.6.16-owrt/net/ipv4/netfilter/ip_set.c
+--- linux-2.6.16/net/ipv4/netfilter/ip_set.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv4/netfilter/ip_set.c 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,1989 @@
++/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
++ * Patrick Schaaf <bof@bof.de>
++ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* Kernel module for IP set management */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/kmod.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++#include <linux/random.h>
++#include <linux/jhash.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <asm/semaphore.h>
++#include <linux/spinlock.h>
++#include <linux/vmalloc.h>
++
++#define ASSERT_READ_LOCK(x) /* dont use that */
++#define ASSERT_WRITE_LOCK(x)
++#include <linux/netfilter_ipv4/listhelp.h>
++#include <linux/netfilter_ipv4/ip_set.h>
++
++static struct list_head set_type_list; /* all registered sets */
++static struct ip_set **ip_set_list; /* all individual sets */
++static DEFINE_RWLOCK(ip_set_lock); /* protects the lists and the hash */
++static DECLARE_MUTEX(ip_set_app_mutex); /* serializes user access */
++static ip_set_id_t ip_set_max = CONFIG_IP_NF_SET_MAX;
++static ip_set_id_t ip_set_bindings_hash_size = CONFIG_IP_NF_SET_HASHSIZE;
++static struct list_head *ip_set_hash; /* hash of bindings */
++static unsigned int ip_set_hash_random; /* random seed */
++
++/*
++ * Sets are identified either by the index in ip_set_list or by id.
++ * The id never changes and is used to find a key in the hash.
++ * The index may change by swapping and used at all other places
++ * (set/SET netfilter modules, binding value, etc.)
++ *
++ * Userspace requests are serialized by ip_set_mutex and sets can
++ * be deleted only from userspace. Therefore ip_set_list locking
++ * must obey the following rules:
++ *
++ * - kernel requests: read and write locking mandatory
++ * - user requests: read locking optional, write locking mandatory
++ */
++
++static inline void
++__ip_set_get(ip_set_id_t index)
++{
++ atomic_inc(&ip_set_list[index]->ref);
++}
++
++static inline void
++__ip_set_put(ip_set_id_t index)
++{
++ atomic_dec(&ip_set_list[index]->ref);
++}
++
++/*
++ * Binding routines
++ */
++
++static inline int
++ip_hash_cmp(const struct ip_set_hash *set_hash,
++ ip_set_id_t id, ip_set_ip_t ip)
++{
++ return set_hash->id == id && set_hash->ip == ip;
++}
++
++static ip_set_id_t
++ip_set_find_in_hash(ip_set_id_t id, ip_set_ip_t ip)
++{
++ u_int32_t key = jhash_2words(id, ip, ip_set_hash_random)
++ % ip_set_bindings_hash_size;
++ struct ip_set_hash *set_hash;
++
++ ASSERT_READ_LOCK(&ip_set_lock);
++ IP_SET_ASSERT(ip_set_list[id]);
++ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));
++
++ set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
++ struct ip_set_hash *, id, ip);
++
++ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
++ HIPQUAD(ip),
++ set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");
++
++ return (set_hash != NULL ? set_hash->binding : IP_SET_INVALID_ID);
++}
++
++static inline void
++__set_hash_del(struct ip_set_hash *set_hash)
++{
++ ASSERT_WRITE_LOCK(&ip_set_lock);
++ IP_SET_ASSERT(ip_set_list[set_hash->binding]);
++
++ __ip_set_put(set_hash->binding);
++ list_del(&set_hash->list);
++ kfree(set_hash);
++}
++
++static int
++ip_set_hash_del(ip_set_id_t id, ip_set_ip_t ip)
++{
++ u_int32_t key = jhash_2words(id, ip, ip_set_hash_random)
++ % ip_set_bindings_hash_size;
++ struct ip_set_hash *set_hash;
++
++ IP_SET_ASSERT(ip_set_list[id]);
++ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));
++ write_lock_bh(&ip_set_lock);
++ set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
++ struct ip_set_hash *, id, ip);
++ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
++ HIPQUAD(ip),
++ set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");
++
++ if (set_hash != NULL)
++ __set_hash_del(set_hash);
++ write_unlock_bh(&ip_set_lock);
++ return 0;
++}
++
++static int
++ip_set_hash_add(ip_set_id_t id, ip_set_ip_t ip, ip_set_id_t binding)
++{
++ u_int32_t key = jhash_2words(id, ip, ip_set_hash_random)
++ % ip_set_bindings_hash_size;
++ struct ip_set_hash *set_hash;
++ int ret = 0;
++
++ IP_SET_ASSERT(ip_set_list[id]);
++ IP_SET_ASSERT(ip_set_list[binding]);
++ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
++ HIPQUAD(ip), ip_set_list[binding]->name);
++ write_lock_bh(&ip_set_lock);
++ set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
++ struct ip_set_hash *, id, ip);
++ if (!set_hash) {
++ set_hash = kmalloc(sizeof(struct ip_set_hash), GFP_KERNEL);
++ if (!set_hash) {
++ ret = -ENOMEM;
++ goto unlock;
++ }
++ INIT_LIST_HEAD(&set_hash->list);
++ set_hash->id = id;
++ set_hash->ip = ip;
++ list_add(&ip_set_hash[key], &set_hash->list);
++ } else {
++ IP_SET_ASSERT(ip_set_list[set_hash->binding]);
++ DP("overwrite binding: %s",
++ ip_set_list[set_hash->binding]->name);
++ __ip_set_put(set_hash->binding);
++ }
++ set_hash->binding = binding;
++ __ip_set_get(set_hash->binding);
++ unlock:
++ write_unlock_bh(&ip_set_lock);
++ return ret;
++}
++
++#define FOREACH_HASH_DO(fn, args...) \
++({ \
++ ip_set_id_t __key; \
++ struct ip_set_hash *__set_hash; \
++ \
++ for (__key = 0; __key < ip_set_bindings_hash_size; __key++) { \
++ list_for_each_entry(__set_hash, &ip_set_hash[__key], list) \
++ fn(__set_hash , ## args); \
++ } \
++})
++
++#define FOREACH_HASH_RW_DO(fn, args...) \
++({ \
++ ip_set_id_t __key; \
++ struct ip_set_hash *__set_hash, *__n; \
++ \
++ ASSERT_WRITE_LOCK(&ip_set_lock); \
++ for (__key = 0; __key < ip_set_bindings_hash_size; __key++) { \
++ list_for_each_entry_safe(__set_hash, __n, &ip_set_hash[__key], list)\
++ fn(__set_hash , ## args); \
++ } \
++})
++
++/* Add, del and test set entries from kernel */
++
++#define follow_bindings(index, set, ip) \
++((index = ip_set_find_in_hash((set)->id, ip)) != IP_SET_INVALID_ID \
++ || (index = (set)->binding) != IP_SET_INVALID_ID)
++
++int
++ip_set_testip_kernel(ip_set_id_t index,
++ const struct sk_buff *skb,
++ const u_int32_t *flags)
++{
++ struct ip_set *set;
++ ip_set_ip_t ip;
++ int res, i = 0;
++
++ IP_SET_ASSERT(flags[i]);
++ read_lock_bh(&ip_set_lock);
++ do {
++ set = ip_set_list[index];
++ IP_SET_ASSERT(set);
++ DP("set %s, index %u", set->name, index);
++ read_lock_bh(&set->lock);
++ res = set->type->testip_kernel(set, skb, flags[i], &ip);
++ read_unlock_bh(&set->lock);
++ } while (res > 0
++ && flags[++i]
++ && follow_bindings(index, set, ip));
++ read_unlock_bh(&ip_set_lock);
++
++ return res;
++}
++
++void
++ip_set_addip_kernel(ip_set_id_t index,
++ const struct sk_buff *skb,
++ const u_int32_t *flags)
++{
++ struct ip_set *set;
++ ip_set_ip_t ip;
++ int res, i= 0;
++
++ IP_SET_ASSERT(flags[i]);
++ retry:
++ read_lock_bh(&ip_set_lock);
++ do {
++ set = ip_set_list[index];
++ IP_SET_ASSERT(set);
++ DP("set %s, index %u", set->name, index);
++ write_lock_bh(&set->lock);
++ res = set->type->addip_kernel(set, skb, flags[i], &ip);
++ write_unlock_bh(&set->lock);
++ } while ((res == 0 || res == -EEXIST)
++ && flags[++i]
++ && follow_bindings(index, set, ip));
++ read_unlock_bh(&ip_set_lock);
++
++ if (res == -EAGAIN
++ && set->type->retry
++ && (res = set->type->retry(set)) == 0)
++ goto retry;
++}
++
++void
++ip_set_delip_kernel(ip_set_id_t index,
++ const struct sk_buff *skb,
++ const u_int32_t *flags)
++{
++ struct ip_set *set;
++ ip_set_ip_t ip;
++ int res, i = 0;
++
++ IP_SET_ASSERT(flags[i]);
++ read_lock_bh(&ip_set_lock);
++ do {
++ set = ip_set_list[index];
++ IP_SET_ASSERT(set);
++ DP("set %s, index %u", set->name, index);
++ write_lock_bh(&set->lock);
++ res = set->type->delip_kernel(set, skb, flags[i], &ip);
++ write_unlock_bh(&set->lock);
++ } while ((res == 0 || res == -EEXIST)
++ && flags[++i]
++ && follow_bindings(index, set, ip));
++ read_unlock_bh(&ip_set_lock);
++}
++
++/* Register and deregister settype */
++
++static inline int
++set_type_equal(const struct ip_set_type *set_type, const char *str2)
++{
++ return !strncmp(set_type->typename, str2, IP_SET_MAXNAMELEN - 1);
++}
++
++static inline struct ip_set_type *
++find_set_type(const char *name)
++{
++ return LIST_FIND(&set_type_list,
++ set_type_equal,
++ struct ip_set_type *,
++ name);
++}
++
++int
++ip_set_register_set_type(struct ip_set_type *set_type)
++{
++ int ret = 0;
++
++ if (set_type->protocol_version != IP_SET_PROTOCOL_VERSION) {
++ ip_set_printk("'%s' uses wrong protocol version %u (want %u)",
++ set_type->typename,
++ set_type->protocol_version,
++ IP_SET_PROTOCOL_VERSION);
++ return -EINVAL;
++ }
++
++ write_lock_bh(&ip_set_lock);
++ if (find_set_type(set_type->typename)) {
++ /* Duplicate! */
++ ip_set_printk("'%s' already registered!",
++ set_type->typename);
++ ret = -EINVAL;
++ goto unlock;
++ }
++ if (!try_module_get(THIS_MODULE)) {
++ ret = -EFAULT;
++ goto unlock;
++ }
++ list_append(&set_type_list, set_type);
++ DP("'%s' registered.", set_type->typename);
++ unlock:
++ write_unlock_bh(&ip_set_lock);
++ return ret;
++}
++
++void
++ip_set_unregister_set_type(struct ip_set_type *set_type)
++{
++ write_lock_bh(&ip_set_lock);
++ if (!find_set_type(set_type->typename)) {
++ ip_set_printk("'%s' not registered?",
++ set_type->typename);
++ goto unlock;
++ }
++ LIST_DELETE(&set_type_list, set_type);
++ module_put(THIS_MODULE);
++ DP("'%s' unregistered.", set_type->typename);
++ unlock:
++ write_unlock_bh(&ip_set_lock);
++
++}
++
++/*
++ * Userspace routines
++ */
++
++/*
++ * Find set by name, reference it once. The reference makes sure the
++ * thing pointed to, does not go away under our feet. Drop the reference
++ * later, using ip_set_put().
++ */
++ip_set_id_t
++ip_set_get_byname(const char *name)
++{
++ ip_set_id_t i, index = IP_SET_INVALID_ID;
++
++ down(&ip_set_app_mutex);
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] != NULL
++ && strcmp(ip_set_list[i]->name, name) == 0) {
++ __ip_set_get(i);
++ index = i;
++ break;
++ }
++ }
++ up(&ip_set_app_mutex);
++ return index;
++}
++
++/*
++ * Find set by index, reference it once. The reference makes sure the
++ * thing pointed to, does not go away under our feet. Drop the reference
++ * later, using ip_set_put().
++ */
++ip_set_id_t
++ip_set_get_byindex(ip_set_id_t index)
++{
++ down(&ip_set_app_mutex);
++
++ if (index >= ip_set_max)
++ return IP_SET_INVALID_ID;
++
++ if (ip_set_list[index])
++ __ip_set_get(index);
++ else
++ index = IP_SET_INVALID_ID;
++
++ up(&ip_set_app_mutex);
++ return index;
++}
++
++/*
++ * If the given set pointer points to a valid set, decrement
++ * reference count by 1. The caller shall not assume the index
++ * to be valid, after calling this function.
++ */
++void ip_set_put(ip_set_id_t index)
++{
++ down(&ip_set_app_mutex);
++ if (ip_set_list[index])
++ __ip_set_put(index);
++ up(&ip_set_app_mutex);
++}
++
++/* Find a set by name or index */
++static ip_set_id_t
++ip_set_find_byname(const char *name)
++{
++ ip_set_id_t i, index = IP_SET_INVALID_ID;
++
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] != NULL
++ && strcmp(ip_set_list[i]->name, name) == 0) {
++ index = i;
++ break;
++ }
++ }
++ return index;
++}
++
++static ip_set_id_t
++ip_set_find_byindex(ip_set_id_t index)
++{
++ if (index >= ip_set_max || ip_set_list[index] == NULL)
++ index = IP_SET_INVALID_ID;
++
++ return index;
++}
++
++/*
++ * Add, del, test, bind and unbind
++ */
++
++static inline int
++__ip_set_testip(struct ip_set *set,
++ const void *data,
++ size_t size,
++ ip_set_ip_t *ip)
++{
++ int res;
++
++ read_lock_bh(&set->lock);
++ res = set->type->testip(set, data, size, ip);
++ read_unlock_bh(&set->lock);
++
++ return res;
++}
++
++static int
++__ip_set_addip(ip_set_id_t index,
++ const void *data,
++ size_t size)
++{
++ struct ip_set *set = ip_set_list[index];
++ ip_set_ip_t ip;
++ int res;
++
++ IP_SET_ASSERT(set);
++ do {
++ write_lock_bh(&set->lock);
++ res = set->type->addip(set, data, size, &ip);
++ write_unlock_bh(&set->lock);
++ } while (res == -EAGAIN
++ && set->type->retry
++ && (res = set->type->retry(set)) == 0);
++
++ return res;
++}
++
++static int
++ip_set_addip(ip_set_id_t index,
++ const void *data,
++ size_t size)
++{
++
++ return __ip_set_addip(index,
++ data + sizeof(struct ip_set_req_adt),
++ size - sizeof(struct ip_set_req_adt));
++}
++
++static int
++ip_set_delip(ip_set_id_t index,
++ const void *data,
++ size_t size)
++{
++ struct ip_set *set = ip_set_list[index];
++ ip_set_ip_t ip;
++ int res;
++
++ IP_SET_ASSERT(set);
++ write_lock_bh(&set->lock);
++ res = set->type->delip(set,
++ data + sizeof(struct ip_set_req_adt),
++ size - sizeof(struct ip_set_req_adt),
++ &ip);
++ write_unlock_bh(&set->lock);
++
++ return res;
++}
++
++static int
++ip_set_testip(ip_set_id_t index,
++ const void *data,
++ size_t size)
++{
++ struct ip_set *set = ip_set_list[index];
++ ip_set_ip_t ip;
++ int res;
++
++ IP_SET_ASSERT(set);
++ res = __ip_set_testip(set,
++ data + sizeof(struct ip_set_req_adt),
++ size - sizeof(struct ip_set_req_adt),
++ &ip);
++
++ return (res > 0 ? -EEXIST : res);
++}
++
++static int
++ip_set_bindip(ip_set_id_t index,
++ const void *data,
++ size_t size)
++{
++ struct ip_set *set = ip_set_list[index];
++ struct ip_set_req_bind *req_bind;
++ ip_set_id_t binding;
++ ip_set_ip_t ip;
++ int res;
++
++ IP_SET_ASSERT(set);
++ if (size < sizeof(struct ip_set_req_bind))
++ return -EINVAL;
++
++ req_bind = (struct ip_set_req_bind *) data;
++ req_bind->binding[IP_SET_MAXNAMELEN - 1] = '\0';
++
++ if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {
++ /* Default binding of a set */
++ char *binding_name;
++
++ if (size != sizeof(struct ip_set_req_bind) + IP_SET_MAXNAMELEN)
++ return -EINVAL;
++
++ binding_name = (char *)(data + sizeof(struct ip_set_req_bind));
++ binding_name[IP_SET_MAXNAMELEN - 1] = '\0';
++
++ binding = ip_set_find_byname(binding_name);
++ if (binding == IP_SET_INVALID_ID)
++ return -ENOENT;
++
++ write_lock_bh(&ip_set_lock);
++ /* Sets as binding values are referenced */
++ if (set->binding != IP_SET_INVALID_ID)
++ __ip_set_put(set->binding);
++ set->binding = binding;
++ __ip_set_get(set->binding);
++ write_unlock_bh(&ip_set_lock);
++
++ return 0;
++ }
++ binding = ip_set_find_byname(req_bind->binding);
++ if (binding == IP_SET_INVALID_ID)
++ return -ENOENT;
++
++ res = __ip_set_testip(set,
++ data + sizeof(struct ip_set_req_bind),
++ size - sizeof(struct ip_set_req_bind),
++ &ip);
++ DP("set %s, ip: %u.%u.%u.%u, binding %s",
++ set->name, HIPQUAD(ip), ip_set_list[binding]->name);
++
++ if (res >= 0)
++ res = ip_set_hash_add(set->id, ip, binding);
++
++ return res;
++}
++
++#define FOREACH_SET_DO(fn, args...) \
++({ \
++ ip_set_id_t __i; \
++ struct ip_set *__set; \
++ \
++ for (__i = 0; __i < ip_set_max; __i++) { \
++ __set = ip_set_list[__i]; \
++ if (__set != NULL) \
++ fn(__set , ##args); \
++ } \
++})
++
++static inline void
++__set_hash_del_byid(struct ip_set_hash *set_hash, ip_set_id_t id)
++{
++ if (set_hash->id == id)
++ __set_hash_del(set_hash);
++}
++
++static inline void
++__unbind_default(struct ip_set *set)
++{
++ if (set->binding != IP_SET_INVALID_ID) {
++ /* Sets as binding values are referenced */
++ __ip_set_put(set->binding);
++ set->binding = IP_SET_INVALID_ID;
++ }
++}
++
++static int
++ip_set_unbindip(ip_set_id_t index,
++ const void *data,
++ size_t size)
++{
++ struct ip_set *set;
++ struct ip_set_req_bind *req_bind;
++ ip_set_ip_t ip;
++ int res;
++
++ DP("");
++ if (size < sizeof(struct ip_set_req_bind))
++ return -EINVAL;
++
++ req_bind = (struct ip_set_req_bind *) data;
++ req_bind->binding[IP_SET_MAXNAMELEN - 1] = '\0';
++
++ DP("%u %s", index, req_bind->binding);
++ if (index == IP_SET_INVALID_ID) {
++ /* unbind :all: */
++ if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {
++ /* Default binding of sets */
++ write_lock_bh(&ip_set_lock);
++ FOREACH_SET_DO(__unbind_default);
++ write_unlock_bh(&ip_set_lock);
++ return 0;
++ } else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {
++ /* Flush all bindings of all sets*/
++ write_lock_bh(&ip_set_lock);
++ FOREACH_HASH_RW_DO(__set_hash_del);
++ write_unlock_bh(&ip_set_lock);
++ return 0;
++ }
++ DP("unreachable reached!");
++ return -EINVAL;
++ }
++
++ set = ip_set_list[index];
++ IP_SET_ASSERT(set);
++ if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {
++ /* Default binding of set */
++ ip_set_id_t binding = ip_set_find_byindex(set->binding);
++
++ if (binding == IP_SET_INVALID_ID)
++ return -ENOENT;
++
++ write_lock_bh(&ip_set_lock);
++ /* Sets in hash values are referenced */
++ __ip_set_put(set->binding);
++ set->binding = IP_SET_INVALID_ID;
++ write_unlock_bh(&ip_set_lock);
++
++ return 0;
++ } else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {
++ /* Flush all bindings */
++
++ write_lock_bh(&ip_set_lock);
++ FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id);
++ write_unlock_bh(&ip_set_lock);
++ return 0;
++ }
++
++ res = __ip_set_testip(set,
++ data + sizeof(struct ip_set_req_bind),
++ size - sizeof(struct ip_set_req_bind),
++ &ip);
++
++ DP("set %s, ip: %u.%u.%u.%u", set->name, HIPQUAD(ip));
++ if (res >= 0)
++ res = ip_set_hash_del(set->id, ip);
++
++ return res;
++}
++
++static int
++ip_set_testbind(ip_set_id_t index,
++ const void *data,
++ size_t size)
++{
++ struct ip_set *set = ip_set_list[index];
++ struct ip_set_req_bind *req_bind;
++ ip_set_id_t binding;
++ ip_set_ip_t ip;
++ int res;
++
++ IP_SET_ASSERT(set);
++ if (size < sizeof(struct ip_set_req_bind))
++ return -EINVAL;
++
++ req_bind = (struct ip_set_req_bind *) data;
++ req_bind->binding[IP_SET_MAXNAMELEN - 1] = '\0';
++
++ if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {
++ /* Default binding of set */
++ char *binding_name;
++
++ if (size != sizeof(struct ip_set_req_bind) + IP_SET_MAXNAMELEN)
++ return -EINVAL;
++
++ binding_name = (char *)(data + sizeof(struct ip_set_req_bind));
++ binding_name[IP_SET_MAXNAMELEN - 1] = '\0';
++
++ binding = ip_set_find_byname(binding_name);
++ if (binding == IP_SET_INVALID_ID)
++ return -ENOENT;
++
++ res = (set->binding == binding) ? -EEXIST : 0;
++
++ return res;
++ }
++ binding = ip_set_find_byname(req_bind->binding);
++ if (binding == IP_SET_INVALID_ID)
++ return -ENOENT;
++
++
++ res = __ip_set_testip(set,
++ data + sizeof(struct ip_set_req_bind),
++ size - sizeof(struct ip_set_req_bind),
++ &ip);
++ DP("set %s, ip: %u.%u.%u.%u, binding %s",
++ set->name, HIPQUAD(ip), ip_set_list[binding]->name);
++
++ if (res >= 0)
++ res = (ip_set_find_in_hash(set->id, ip) == binding)
++ ? -EEXIST : 0;
++
++ return res;
++}
++
++static struct ip_set_type *
++find_set_type_rlock(const char *typename)
++{
++ struct ip_set_type *type;
++
++ read_lock_bh(&ip_set_lock);
++ type = find_set_type(typename);
++ if (type == NULL)
++ read_unlock_bh(&ip_set_lock);
++
++ return type;
++}
++
++static int
++find_free_id(const char *name,
++ ip_set_id_t *index,
++ ip_set_id_t *id)
++{
++ ip_set_id_t i;
++
++ *id = IP_SET_INVALID_ID;
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] == NULL) {
++ if (*id == IP_SET_INVALID_ID)
++ *id = *index = i;
++ } else if (strcmp(name, ip_set_list[i]->name) == 0)
++ /* Name clash */
++ return -EEXIST;
++ }
++ if (*id == IP_SET_INVALID_ID)
++ /* No free slot remained */
++ return -ERANGE;
++ /* Check that index is usable as id (swapping) */
++ check:
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] != NULL
++ && ip_set_list[i]->id == *id) {
++ *id = i;
++ goto check;
++ }
++ }
++ return 0;
++}
++
++/*
++ * Create a set
++ */
++static int
++ip_set_create(const char *name,
++ const char *typename,
++ ip_set_id_t restore,
++ const void *data,
++ size_t size)
++{
++ struct ip_set *set;
++ ip_set_id_t index, id;
++ int res = 0;
++
++ DP("setname: %s, typename: %s, id: %u", name, typename, restore);
++ /*
++ * First, and without any locks, allocate and initialize
++ * a normal base set structure.
++ */
++ set = kmalloc(sizeof(struct ip_set), GFP_KERNEL);
++ if (!set)
++ return -ENOMEM;
++ set->lock = RW_LOCK_UNLOCKED;
++ strncpy(set->name, name, IP_SET_MAXNAMELEN);
++ set->binding = IP_SET_INVALID_ID;
++ atomic_set(&set->ref, 0);
++
++ /*
++ * Next, take the &ip_set_lock, check that we know the type,
++ * and take a reference on the type, to make sure it
++ * stays available while constructing our new set.
++ *
++ * After referencing the type, we drop the &ip_set_lock,
++ * and let the new set construction run without locks.
++ */
++ set->type = find_set_type_rlock(typename);
++ if (set->type == NULL) {
++ /* Try loading the module */
++ char modulename[IP_SET_MAXNAMELEN + strlen("ip_set_") + 1];
++ strcpy(modulename, "ip_set_");
++ strcat(modulename, typename);
++ DP("try to load %s", modulename);
++ request_module(modulename);
++ set->type = find_set_type_rlock(typename);
++ }
++ if (set->type == NULL) {
++ ip_set_printk("no set type '%s', set '%s' not created",
++ typename, name);
++ res = -ENOENT;
++ goto out;
++ }
++ if (!try_module_get(set->type->me)) {
++ read_unlock_bh(&ip_set_lock);
++ res = -EFAULT;
++ goto out;
++ }
++ read_unlock_bh(&ip_set_lock);
++
++ /*
++ * Without holding any locks, create private part.
++ */
++ res = set->type->create(set, data, size);
++ if (res != 0)
++ goto put_out;
++
++ /* BTW, res==0 here. */
++
++ /*
++ * Here, we have a valid, constructed set. &ip_set_lock again,
++ * find free id/index and check that it is not already in
++ * ip_set_list.
++ */
++ write_lock_bh(&ip_set_lock);
++ if ((res = find_free_id(set->name, &index, &id)) != 0) {
++ DP("no free id!");
++ goto cleanup;
++ }
++
++ /* Make sure restore gets the same index */
++ if (restore != IP_SET_INVALID_ID && index != restore) {
++ DP("Can't restore, sets are screwed up");
++ res = -ERANGE;
++ goto cleanup;
++ }
++
++ /*
++ * Finally! Add our shiny new set to the list, and be done.
++ */
++ DP("create: '%s' created with index %u, id %u!", set->name, index, id);
++ set->id = id;
++ ip_set_list[index] = set;
++ write_unlock_bh(&ip_set_lock);
++ return res;
++
++ cleanup:
++ write_unlock_bh(&ip_set_lock);
++ set->type->destroy(set);
++ put_out:
++ module_put(set->type->me);
++ out:
++ kfree(set);
++ return res;
++}
++
++/*
++ * Destroy a given existing set
++ */
++static void
++ip_set_destroy_set(ip_set_id_t index)
++{
++ struct ip_set *set = ip_set_list[index];
++
++ IP_SET_ASSERT(set);
++ DP("set: %s", set->name);
++ write_lock_bh(&ip_set_lock);
++ FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id);
++ if (set->binding != IP_SET_INVALID_ID)
++ __ip_set_put(set->binding);
++ ip_set_list[index] = NULL;
++ write_unlock_bh(&ip_set_lock);
++
++ /* Must call it without holding any lock */
++ set->type->destroy(set);
++ module_put(set->type->me);
++ kfree(set);
++}
++
++/*
++ * Destroy a set - or all sets
++ * Sets must not be referenced/used.
++ */
++static int
++ip_set_destroy(ip_set_id_t index)
++{
++ ip_set_id_t i;
++
++ /* ref modification always protected by the mutex */
++ if (index != IP_SET_INVALID_ID) {
++ if (atomic_read(&ip_set_list[index]->ref))
++ return -EBUSY;
++ ip_set_destroy_set(index);
++ } else {
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] != NULL
++ && (atomic_read(&ip_set_list[i]->ref)))
++ return -EBUSY;
++ }
++
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] != NULL)
++ ip_set_destroy_set(i);
++ }
++ }
++ return 0;
++}
++
++static void
++ip_set_flush_set(struct ip_set *set)
++{
++ DP("set: %s %u", set->name, set->id);
++
++ write_lock_bh(&set->lock);
++ set->type->flush(set);
++ write_unlock_bh(&set->lock);
++}
++
++/*
++ * Flush data in a set - or in all sets
++ */
++static int
++ip_set_flush(ip_set_id_t index)
++{
++ if (index != IP_SET_INVALID_ID) {
++ IP_SET_ASSERT(ip_set_list[index]);
++ ip_set_flush_set(ip_set_list[index]);
++ } else
++ FOREACH_SET_DO(ip_set_flush_set);
++
++ return 0;
++}
++
++/* Rename a set */
++static int
++ip_set_rename(ip_set_id_t index, const char *name)
++{
++ struct ip_set *set = ip_set_list[index];
++ ip_set_id_t i;
++ int res = 0;
++
++ DP("set: %s to %s", set->name, name);
++ write_lock_bh(&ip_set_lock);
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] != NULL
++ && strncmp(ip_set_list[i]->name,
++ name,
++ IP_SET_MAXNAMELEN - 1) == 0) {
++ res = -EEXIST;
++ goto unlock;
++ }
++ }
++ strncpy(set->name, name, IP_SET_MAXNAMELEN);
++ unlock:
++ write_unlock_bh(&ip_set_lock);
++ return res;
++}
++
++/*
++ * Swap two sets so that name/index points to the other.
++ * References are also swapped.
++ */
++static int
++ip_set_swap(ip_set_id_t from_index, ip_set_id_t to_index)
++{
++ struct ip_set *from = ip_set_list[from_index];
++ struct ip_set *to = ip_set_list[to_index];
++ char from_name[IP_SET_MAXNAMELEN];
++ u_int32_t from_ref;
++
++ DP("set: %s to %s", from->name, to->name);
++ /* Type can't be changed. Artifical restriction. */
++ if (from->type->typecode != to->type->typecode)
++ return -ENOEXEC;
++
++ /* No magic here: ref munging protected by the mutex */
++ write_lock_bh(&ip_set_lock);
++ strncpy(from_name, from->name, IP_SET_MAXNAMELEN);
++ from_ref = atomic_read(&from->ref);
++
++ strncpy(from->name, to->name, IP_SET_MAXNAMELEN);
++ atomic_set(&from->ref, atomic_read(&to->ref));
++ strncpy(to->name, from_name, IP_SET_MAXNAMELEN);
++ atomic_set(&to->ref, from_ref);
++
++ ip_set_list[from_index] = to;
++ ip_set_list[to_index] = from;
++
++ write_unlock_bh(&ip_set_lock);
++ return 0;
++}
++
++/*
++ * List set data
++ */
++
++static inline void
++__set_hash_bindings_size_list(struct ip_set_hash *set_hash,
++ ip_set_id_t id, size_t *size)
++{
++ if (set_hash->id == id)
++ *size += sizeof(struct ip_set_hash_list);
++}
++
++static inline void
++__set_hash_bindings_size_save(struct ip_set_hash *set_hash,
++ ip_set_id_t id, size_t *size)
++{
++ if (set_hash->id == id)
++ *size += sizeof(struct ip_set_hash_save);
++}
++
++static inline void
++__set_hash_bindings(struct ip_set_hash *set_hash,
++ ip_set_id_t id, void *data, int *used)
++{
++ if (set_hash->id == id) {
++ struct ip_set_hash_list *hash_list =
++ (struct ip_set_hash_list *)(data + *used);
++
++ hash_list->ip = set_hash->ip;
++ hash_list->binding = set_hash->binding;
++ *used += sizeof(struct ip_set_hash_list);
++ }
++}
++
++static int ip_set_list_set(ip_set_id_t index,
++ void *data,
++ int *used,
++ int len)
++{
++ struct ip_set *set = ip_set_list[index];
++ struct ip_set_list *set_list;
++
++ /* Pointer to our header */
++ set_list = (struct ip_set_list *) (data + *used);
++
++ DP("set: %s, used: %d %p %p", set->name, *used, data, data + *used);
++
++ /* Get and ensure header size */
++ if (*used + sizeof(struct ip_set_list) > len)
++ goto not_enough_mem;
++ *used += sizeof(struct ip_set_list);
++
++ read_lock_bh(&set->lock);
++ /* Get and ensure set specific header size */
++ set_list->header_size = set->type->header_size;
++ if (*used + set_list->header_size > len)
++ goto unlock_set;
++
++ /* Fill in the header */
++ set_list->index = index;
++ set_list->binding = set->binding;
++ set_list->ref = atomic_read(&set->ref);
++
++ /* Fill in set spefific header data */
++ set->type->list_header(set, data + *used);
++ *used += set_list->header_size;
++
++ /* Get and ensure set specific members size */
++ set_list->members_size = set->type->list_members_size(set);
++ if (*used + set_list->members_size > len)
++ goto unlock_set;
++
++ /* Fill in set spefific members data */
++ set->type->list_members(set, data + *used);
++ *used += set_list->members_size;
++ read_unlock_bh(&set->lock);
++
++ /* Bindings */
++
++ /* Get and ensure set specific bindings size */
++ set_list->bindings_size = 0;
++ FOREACH_HASH_DO(__set_hash_bindings_size_list,
++ set->id, &set_list->bindings_size);
++ if (*used + set_list->bindings_size > len)
++ goto not_enough_mem;
++
++ /* Fill in set spefific bindings data */
++ FOREACH_HASH_DO(__set_hash_bindings, set->id, data, used);
++
++ return 0;
++
++ unlock_set:
++ read_unlock_bh(&set->lock);
++ not_enough_mem:
++ DP("not enough mem, try again");
++ return -EAGAIN;
++}
++
++/*
++ * Save sets
++ */
++static int ip_set_save_set(ip_set_id_t index,
++ void *data,
++ int *used,
++ int len)
++{
++ struct ip_set *set;
++ struct ip_set_save *set_save;
++
++ /* Pointer to our header */
++ set_save = (struct ip_set_save *) (data + *used);
++
++ /* Get and ensure header size */
++ if (*used + sizeof(struct ip_set_save) > len)
++ goto not_enough_mem;
++ *used += sizeof(struct ip_set_save);
++
++ set = ip_set_list[index];
++ DP("set: %s, used: %u(%u) %p %p", set->name, *used, len,
++ data, data + *used);
++
++ read_lock_bh(&set->lock);
++ /* Get and ensure set specific header size */
++ set_save->header_size = set->type->header_size;
++ if (*used + set_save->header_size > len)
++ goto unlock_set;
++
++ /* Fill in the header */
++ set_save->index = index;
++ set_save->binding = set->binding;
++
++ /* Fill in set spefific header data */
++ set->type->list_header(set, data + *used);
++ *used += set_save->header_size;
++
++ DP("set header filled: %s, used: %u %p %p", set->name, *used,
++ data, data + *used);
++ /* Get and ensure set specific members size */
++ set_save->members_size = set->type->list_members_size(set);
++ if (*used + set_save->members_size > len)
++ goto unlock_set;
++
++ /* Fill in set spefific members data */
++ set->type->list_members(set, data + *used);
++ *used += set_save->members_size;
++ read_unlock_bh(&set->lock);
++ DP("set members filled: %s, used: %u %p %p", set->name, *used,
++ data, data + *used);
++ return 0;
++
++ unlock_set:
++ read_unlock_bh(&set->lock);
++ not_enough_mem:
++ DP("not enough mem, try again");
++ return -EAGAIN;
++}
++
++static inline void
++__set_hash_save_bindings(struct ip_set_hash *set_hash,
++ ip_set_id_t id,
++ void *data,
++ int *used,
++ int len,
++ int *res)
++{
++ if (*res == 0
++ && (id == IP_SET_INVALID_ID || set_hash->id == id)) {
++ struct ip_set_hash_save *hash_save =
++ (struct ip_set_hash_save *)(data + *used);
++ /* Ensure bindings size */
++ if (*used + sizeof(struct ip_set_hash_save) > len) {
++ *res = -ENOMEM;
++ return;
++ }
++ hash_save->id = set_hash->id;
++ hash_save->ip = set_hash->ip;
++ hash_save->binding = set_hash->binding;
++ *used += sizeof(struct ip_set_hash_save);
++ }
++}
++
++static int ip_set_save_bindings(ip_set_id_t index,
++ void *data,
++ int *used,
++ int len)
++{
++ int res = 0;
++ struct ip_set_save *set_save;
++
++ DP("used %u, len %u", *used, len);
++ /* Get and ensure header size */
++ if (*used + sizeof(struct ip_set_save) > len)
++ return -ENOMEM;
++
++ /* Marker */
++ set_save = (struct ip_set_save *) (data + *used);
++ set_save->index = IP_SET_INVALID_ID;
++ *used += sizeof(struct ip_set_save);
++
++ DP("marker added used %u, len %u", *used, len);
++ /* Fill in bindings data */
++ if (index != IP_SET_INVALID_ID)
++ /* Sets are identified by id in hash */
++ index = ip_set_list[index]->id;
++ FOREACH_HASH_DO(__set_hash_save_bindings, index, data, used, len, &res);
++
++ return res;
++}
++
++/*
++ * Restore sets
++ */
++static int ip_set_restore(void *data,
++ int len)
++{
++ int res = 0;
++ int line = 0, used = 0, members_size;
++ struct ip_set *set;
++ struct ip_set_hash_save *hash_save;
++ struct ip_set_restore *set_restore;
++ ip_set_id_t index;
++
++ /* Loop to restore sets */
++ while (1) {
++ line++;
++
++ DP("%u %u %u", used, sizeof(struct ip_set_restore), len);
++ /* Get and ensure header size */
++ if (used + sizeof(struct ip_set_restore) > len)
++ return line;
++ set_restore = (struct ip_set_restore *) (data + used);
++ used += sizeof(struct ip_set_restore);
++
++ /* Ensure data size */
++ if (used
++ + set_restore->header_size
++ + set_restore->members_size > len)
++ return line;
++
++ /* Check marker */
++ if (set_restore->index == IP_SET_INVALID_ID) {
++ line--;
++ goto bindings;
++ }
++
++ /* Try to create the set */
++ DP("restore %s %s", set_restore->name, set_restore->typename);
++ res = ip_set_create(set_restore->name,
++ set_restore->typename,
++ set_restore->index,
++ data + used,
++ set_restore->header_size);
++
++ if (res != 0)
++ return line;
++ used += set_restore->header_size;
++
++ index = ip_set_find_byindex(set_restore->index);
++ DP("index %u, restore_index %u", index, set_restore->index);
++ if (index != set_restore->index)
++ return line;
++ /* Try to restore members data */
++ set = ip_set_list[index];
++ members_size = 0;
++ DP("members_size %u reqsize %u",
++ set_restore->members_size, set->type->reqsize);
++ while (members_size + set->type->reqsize <=
++ set_restore->members_size) {
++ line++;
++ DP("members: %u, line %u", members_size, line);
++ res = __ip_set_addip(index,
++ data + used + members_size,
++ set->type->reqsize);
++ if (!(res == 0 || res == -EEXIST))
++ return line;
++ members_size += set->type->reqsize;
++ }
++
++ DP("members_size %u %u",
++ set_restore->members_size, members_size);
++ if (members_size != set_restore->members_size)
++ return line++;
++ used += set_restore->members_size;
++ }
++
++ bindings:
++ /* Loop to restore bindings */
++ while (used < len) {
++ line++;
++
++ DP("restore binding, line %u", line);
++ /* Get and ensure size */
++ if (used + sizeof(struct ip_set_hash_save) > len)
++ return line;
++ hash_save = (struct ip_set_hash_save *) (data + used);
++ used += sizeof(struct ip_set_hash_save);
++
++ /* hash_save->id is used to store the index */
++ index = ip_set_find_byindex(hash_save->id);
++ DP("restore binding index %u, id %u, %u -> %u",
++ index, hash_save->id, hash_save->ip, hash_save->binding);
++ if (index != hash_save->id)
++ return line;
++
++ set = ip_set_list[hash_save->id];
++ /* Null valued IP means default binding */
++ if (hash_save->ip)
++ res = ip_set_hash_add(set->id,
++ hash_save->ip,
++ hash_save->binding);
++ else {
++ IP_SET_ASSERT(set->binding == IP_SET_INVALID_ID);
++ write_lock_bh(&ip_set_lock);
++ set->binding = hash_save->binding;
++ __ip_set_get(set->binding);
++ write_unlock_bh(&ip_set_lock);
++ DP("default binding: %u", set->binding);
++ }
++ if (res != 0)
++ return line;
++ }
++ if (used != len)
++ return line;
++
++ return 0;
++}
++
++static int
++ip_set_sockfn_set(struct sock *sk, int optval, void *user, unsigned int len)
++{
++ void *data;
++ int res = 0; /* Assume OK */
++ unsigned *op;
++ struct ip_set_req_adt *req_adt;
++ ip_set_id_t index = IP_SET_INVALID_ID;
++ int (*adtfn)(ip_set_id_t index,
++ const void *data, size_t size);
++ struct fn_table {
++ int (*fn)(ip_set_id_t index,
++ const void *data, size_t size);
++ } adtfn_table[] =
++ { { ip_set_addip }, { ip_set_delip }, { ip_set_testip},
++ { ip_set_bindip}, { ip_set_unbindip }, { ip_set_testbind },
++ };
++
++ DP("optval=%d, user=%p, len=%d", optval, user, len);
++ if (!capable(CAP_NET_ADMIN))
++ return -EPERM;
++ if (optval != SO_IP_SET)
++ return -EBADF;
++ if (len <= sizeof(unsigned)) {
++ ip_set_printk("short userdata (want >%zu, got %u)",
++ sizeof(unsigned), len);
++ return -EINVAL;
++ }
++ data = vmalloc(len);
++ if (!data) {
++ DP("out of mem for %u bytes", len);
++ return -ENOMEM;
++ }
++ if (copy_from_user(data, user, len) != 0) {
++ res = -EFAULT;
++ goto done;
++ }
++ if (down_interruptible(&ip_set_app_mutex)) {
++ res = -EINTR;
++ goto done;
++ }
++
++ op = (unsigned *)data;
++ DP("op=%x", *op);
++
++ if (*op < IP_SET_OP_VERSION) {
++ /* Check the version at the beginning of operations */
++ struct ip_set_req_version *req_version =
++ (struct ip_set_req_version *) data;
++ if (req_version->version != IP_SET_PROTOCOL_VERSION) {
++ res = -EPROTO;
++ goto done;
++ }
++ }
++
++ switch (*op) {
++ case IP_SET_OP_CREATE:{
++ struct ip_set_req_create *req_create
++ = (struct ip_set_req_create *) data;
++
++ if (len <= sizeof(struct ip_set_req_create)) {
++ ip_set_printk("short CREATE data (want >%zu, got %u)",
++ sizeof(struct ip_set_req_create), len);
++ res = -EINVAL;
++ goto done;
++ }
++ req_create->name[IP_SET_MAXNAMELEN - 1] = '\0';
++ req_create->typename[IP_SET_MAXNAMELEN - 1] = '\0';
++ res = ip_set_create(req_create->name,
++ req_create->typename,
++ IP_SET_INVALID_ID,
++ data + sizeof(struct ip_set_req_create),
++ len - sizeof(struct ip_set_req_create));
++ goto done;
++ }
++ case IP_SET_OP_DESTROY:{
++ struct ip_set_req_std *req_destroy
++ = (struct ip_set_req_std *) data;
++
++ if (len != sizeof(struct ip_set_req_std)) {
++ ip_set_printk("invalid DESTROY data (want %zu, got %u)",
++ sizeof(struct ip_set_req_std), len);
++ res = -EINVAL;
++ goto done;
++ }
++ if (strcmp(req_destroy->name, IPSET_TOKEN_ALL) == 0) {
++ /* Destroy all sets */
++ index = IP_SET_INVALID_ID;
++ } else {
++ req_destroy->name[IP_SET_MAXNAMELEN - 1] = '\0';
++ index = ip_set_find_byname(req_destroy->name);
++
++ if (index == IP_SET_INVALID_ID) {
++ res = -ENOENT;
++ goto done;
++ }
++ }
++
++ res = ip_set_destroy(index);
++ goto done;
++ }
++ case IP_SET_OP_FLUSH:{
++ struct ip_set_req_std *req_flush =
++ (struct ip_set_req_std *) data;
++
++ if (len != sizeof(struct ip_set_req_std)) {
++ ip_set_printk("invalid FLUSH data (want %zu, got %u)",
++ sizeof(struct ip_set_req_std), len);
++ res = -EINVAL;
++ goto done;
++ }
++ if (strcmp(req_flush->name, IPSET_TOKEN_ALL) == 0) {
++ /* Flush all sets */
++ index = IP_SET_INVALID_ID;
++ } else {
++ req_flush->name[IP_SET_MAXNAMELEN - 1] = '\0';
++ index = ip_set_find_byname(req_flush->name);
++
++ if (index == IP_SET_INVALID_ID) {
++ res = -ENOENT;
++ goto done;
++ }
++ }
++ res = ip_set_flush(index);
++ goto done;
++ }
++ case IP_SET_OP_RENAME:{
++ struct ip_set_req_create *req_rename
++ = (struct ip_set_req_create *) data;
++
++ if (len != sizeof(struct ip_set_req_create)) {
++ ip_set_printk("invalid RENAME data (want %zu, got %u)",
++ sizeof(struct ip_set_req_create), len);
++ res = -EINVAL;
++ goto done;
++ }
++
++ req_rename->name[IP_SET_MAXNAMELEN - 1] = '\0';
++ req_rename->typename[IP_SET_MAXNAMELEN - 1] = '\0';
++
++ index = ip_set_find_byname(req_rename->name);
++ if (index == IP_SET_INVALID_ID) {
++ res = -ENOENT;
++ goto done;
++ }
++ res = ip_set_rename(index, req_rename->typename);
++ goto done;
++ }
++ case IP_SET_OP_SWAP:{
++ struct ip_set_req_create *req_swap
++ = (struct ip_set_req_create *) data;
++ ip_set_id_t to_index;
++
++ if (len != sizeof(struct ip_set_req_create)) {
++ ip_set_printk("invalid SWAP data (want %zu, got %u)",
++ sizeof(struct ip_set_req_create), len);
++ res = -EINVAL;
++ goto done;
++ }
++
++ req_swap->name[IP_SET_MAXNAMELEN - 1] = '\0';
++ req_swap->typename[IP_SET_MAXNAMELEN - 1] = '\0';
++
++ index = ip_set_find_byname(req_swap->name);
++ if (index == IP_SET_INVALID_ID) {
++ res = -ENOENT;
++ goto done;
++ }
++ to_index = ip_set_find_byname(req_swap->typename);
++ if (to_index == IP_SET_INVALID_ID) {
++ res = -ENOENT;
++ goto done;
++ }
++ res = ip_set_swap(index, to_index);
++ goto done;
++ }
++ default:
++ break; /* Set identified by id */
++ }
++
++ /* There we may have add/del/test/bind/unbind/test_bind operations */
++ if (*op < IP_SET_OP_ADD_IP || *op > IP_SET_OP_TEST_BIND_SET) {
++ res = -EBADMSG;
++ goto done;
++ }
++ adtfn = adtfn_table[*op - IP_SET_OP_ADD_IP].fn;
++
++ if (len < sizeof(struct ip_set_req_adt)) {
++ ip_set_printk("short data in adt request (want >=%zu, got %u)",
++ sizeof(struct ip_set_req_adt), len);
++ res = -EINVAL;
++ goto done;
++ }
++ req_adt = (struct ip_set_req_adt *) data;
++
++ /* -U :all: :all:|:default: uses IP_SET_INVALID_ID */
++ if (!(*op == IP_SET_OP_UNBIND_SET
++ && req_adt->index == IP_SET_INVALID_ID)) {
++ index = ip_set_find_byindex(req_adt->index);
++ if (index == IP_SET_INVALID_ID) {
++ res = -ENOENT;
++ goto done;
++ }
++ }
++ res = adtfn(index, data, len);
++
++ done:
++ up(&ip_set_app_mutex);
++ vfree(data);
++ if (res > 0)
++ res = 0;
++ DP("final result %d", res);
++ return res;
++}
++
++static int
++ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len)
++{
++ int res = 0;
++ unsigned *op;
++ ip_set_id_t index = IP_SET_INVALID_ID;
++ void *data;
++ int copylen = *len;
++
++ DP("optval=%d, user=%p, len=%d", optval, user, *len);
++ if (!capable(CAP_NET_ADMIN))
++ return -EPERM;
++ if (optval != SO_IP_SET)
++ return -EBADF;
++ if (*len < sizeof(unsigned)) {
++ ip_set_printk("short userdata (want >=%zu, got %d)",
++ sizeof(unsigned), *len);
++ return -EINVAL;
++ }
++ data = vmalloc(*len);
++ if (!data) {
++ DP("out of mem for %d bytes", *len);
++ return -ENOMEM;
++ }
++ if (copy_from_user(data, user, *len) != 0) {
++ res = -EFAULT;
++ goto done;
++ }
++ if (down_interruptible(&ip_set_app_mutex)) {
++ res = -EINTR;
++ goto done;
++ }
++
++ op = (unsigned *) data;
++ DP("op=%x", *op);
++
++ if (*op < IP_SET_OP_VERSION) {
++ /* Check the version at the beginning of operations */
++ struct ip_set_req_version *req_version =
++ (struct ip_set_req_version *) data;
++ if (req_version->version != IP_SET_PROTOCOL_VERSION) {
++ res = -EPROTO;
++ goto done;
++ }
++ }
++
++ switch (*op) {
++ case IP_SET_OP_VERSION: {
++ struct ip_set_req_version *req_version =
++ (struct ip_set_req_version *) data;
++
++ if (*len != sizeof(struct ip_set_req_version)) {
++ ip_set_printk("invalid VERSION (want %zu, got %d)",
++ sizeof(struct ip_set_req_version),
++ *len);
++ res = -EINVAL;
++ goto done;
++ }
++
++ req_version->version = IP_SET_PROTOCOL_VERSION;
++ res = copy_to_user(user, req_version,
++ sizeof(struct ip_set_req_version));
++ goto done;
++ }
++ case IP_SET_OP_GET_BYNAME: {
++ struct ip_set_req_get_set *req_get
++ = (struct ip_set_req_get_set *) data;
++
++ if (*len != sizeof(struct ip_set_req_get_set)) {
++ ip_set_printk("invalid GET_BYNAME (want %zu, got %d)",
++ sizeof(struct ip_set_req_get_set), *len);
++ res = -EINVAL;
++ goto done;
++ }
++ req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
++ index = ip_set_find_byname(req_get->set.name);
++ req_get->set.index = index;
++ goto copy;
++ }
++ case IP_SET_OP_GET_BYINDEX: {
++ struct ip_set_req_get_set *req_get
++ = (struct ip_set_req_get_set *) data;
++
++ if (*len != sizeof(struct ip_set_req_get_set)) {
++ ip_set_printk("invalid GET_BYINDEX (want %zu, got %d)",
++ sizeof(struct ip_set_req_get_set), *len);
++ res = -EINVAL;
++ goto done;
++ }
++ req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
++ index = ip_set_find_byindex(req_get->set.index);
++ strncpy(req_get->set.name,
++ index == IP_SET_INVALID_ID ? ""
++ : ip_set_list[index]->name, IP_SET_MAXNAMELEN);
++ goto copy;
++ }
++ case IP_SET_OP_ADT_GET: {
++ struct ip_set_req_adt_get *req_get
++ = (struct ip_set_req_adt_get *) data;
++
++ if (*len != sizeof(struct ip_set_req_adt_get)) {
++ ip_set_printk("invalid ADT_GET (want %zu, got %d)",
++ sizeof(struct ip_set_req_adt_get), *len);
++ res = -EINVAL;
++ goto done;
++ }
++ req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
++ index = ip_set_find_byname(req_get->set.name);
++ if (index != IP_SET_INVALID_ID) {
++ req_get->set.index = index;
++ strncpy(req_get->typename,
++ ip_set_list[index]->type->typename,
++ IP_SET_MAXNAMELEN - 1);
++ } else {
++ res = -ENOENT;
++ goto done;
++ }
++ goto copy;
++ }
++ case IP_SET_OP_MAX_SETS: {
++ struct ip_set_req_max_sets *req_max_sets
++ = (struct ip_set_req_max_sets *) data;
++ ip_set_id_t i;
++
++ if (*len != sizeof(struct ip_set_req_max_sets)) {
++ ip_set_printk("invalid MAX_SETS (want %zu, got %d)",
++ sizeof(struct ip_set_req_max_sets), *len);
++ res = -EINVAL;
++ goto done;
++ }
++
++ if (strcmp(req_max_sets->set.name, IPSET_TOKEN_ALL) == 0) {
++ req_max_sets->set.index = IP_SET_INVALID_ID;
++ } else {
++ req_max_sets->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
++ req_max_sets->set.index =
++ ip_set_find_byname(req_max_sets->set.name);
++ if (req_max_sets->set.index == IP_SET_INVALID_ID) {
++ res = -ENOENT;
++ goto done;
++ }
++ }
++ req_max_sets->max_sets = ip_set_max;
++ req_max_sets->sets = 0;
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] != NULL)
++ req_max_sets->sets++;
++ }
++ goto copy;
++ }
++ case IP_SET_OP_LIST_SIZE:
++ case IP_SET_OP_SAVE_SIZE: {
++ struct ip_set_req_setnames *req_setnames
++ = (struct ip_set_req_setnames *) data;
++ struct ip_set_name_list *name_list;
++ struct ip_set *set;
++ ip_set_id_t i;
++ int used;
++
++ if (*len < sizeof(struct ip_set_req_setnames)) {
++ ip_set_printk("short LIST_SIZE (want >=%zu, got %d)",
++ sizeof(struct ip_set_req_setnames), *len);
++ res = -EINVAL;
++ goto done;
++ }
++
++ req_setnames->size = 0;
++ used = sizeof(struct ip_set_req_setnames);
++ for (i = 0; i < ip_set_max; i++) {
++ if (ip_set_list[i] == NULL)
++ continue;
++ name_list = (struct ip_set_name_list *)
++ (data + used);
++ used += sizeof(struct ip_set_name_list);
++ if (used > copylen) {
++ res = -EAGAIN;
++ goto done;
++ }
++ set = ip_set_list[i];
++ /* Fill in index, name, etc. */
++ name_list->index = i;
++ name_list->id = set->id;
++ strncpy(name_list->name,
++ set->name,
++ IP_SET_MAXNAMELEN - 1);
++ strncpy(name_list->typename,
++ set->type->typename,
++ IP_SET_MAXNAMELEN - 1);
++ DP("filled %s of type %s, index %u\n",
++ name_list->name, name_list->typename,
++ name_list->index);
++ if (!(req_setnames->index == IP_SET_INVALID_ID
++ || req_setnames->index == i))
++ continue;
++ /* Update size */
++ switch (*op) {
++ case IP_SET_OP_LIST_SIZE: {
++ req_setnames->size += sizeof(struct ip_set_list)
++ + set->type->header_size
++ + set->type->list_members_size(set);
++ FOREACH_HASH_DO(__set_hash_bindings_size_list,
++ i, &req_setnames->size);
++ break;
++ }
++ case IP_SET_OP_SAVE_SIZE: {
++ req_setnames->size += sizeof(struct ip_set_save)
++ + set->type->header_size
++ + set->type->list_members_size(set);
++ FOREACH_HASH_DO(__set_hash_bindings_size_save,
++ i, &req_setnames->size);
++ break;
++ }
++ default:
++ break;
++ }
++ }
++ if (copylen != used) {
++ res = -EAGAIN;
++ goto done;
++ }
++ goto copy;
++ }
++ case IP_SET_OP_LIST: {
++ struct ip_set_req_list *req_list
++ = (struct ip_set_req_list *) data;
++ ip_set_id_t i;
++ int used;
++
++ if (*len < sizeof(struct ip_set_req_list)) {
++ ip_set_printk("short LIST (want >=%zu, got %d)",
++ sizeof(struct ip_set_req_list), *len);
++ res = -EINVAL;
++ goto done;
++ }
++ index = req_list->index;
++ if (index != IP_SET_INVALID_ID
++ && ip_set_find_byindex(index) != index) {
++ res = -ENOENT;
++ goto done;
++ }
++ used = 0;
++ if (index == IP_SET_INVALID_ID) {
++ /* List all sets */
++ for (i = 0; i < ip_set_max && res == 0; i++) {
++ if (ip_set_list[i] != NULL)
++ res = ip_set_list_set(i, data, &used, *len);
++ }
++ } else {
++ /* List an individual set */
++ res = ip_set_list_set(index, data, &used, *len);
++ }
++ if (res != 0)
++ goto done;
++ else if (copylen != used) {
++ res = -EAGAIN;
++ goto done;
++ }
++ goto copy;
++ }
++ case IP_SET_OP_SAVE: {
++ struct ip_set_req_list *req_save
++ = (struct ip_set_req_list *) data;
++ ip_set_id_t i;
++ int used;
++
++ if (*len < sizeof(struct ip_set_req_list)) {
++ ip_set_printk("short SAVE (want >=%zu, got %d)",
++ sizeof(struct ip_set_req_list), *len);
++ res = -EINVAL;
++ goto done;
++ }
++ index = req_save->index;
++ if (index != IP_SET_INVALID_ID
++ && ip_set_find_byindex(index) != index) {
++ res = -ENOENT;
++ goto done;
++ }
++ used = 0;
++ if (index == IP_SET_INVALID_ID) {
++ /* Save all sets */
++ for (i = 0; i < ip_set_max && res == 0; i++) {
++ if (ip_set_list[i] != NULL)
++ res = ip_set_save_set(i, data, &used, *len);
++ }
++ } else {
++ /* Save an individual set */
++ res = ip_set_save_set(index, data, &used, *len);
++ }
++ if (res == 0)
++ res = ip_set_save_bindings(index, data, &used, *len);
++
++ if (res != 0)
++ goto done;
++ else if (copylen != used) {
++ res = -EAGAIN;
++ goto done;
++ }
++ goto copy;
++ }
++ case IP_SET_OP_RESTORE: {
++ struct ip_set_req_setnames *req_restore
++ = (struct ip_set_req_setnames *) data;
++ int line;
++
++ if (*len < sizeof(struct ip_set_req_setnames)
++ || *len != req_restore->size) {
++ ip_set_printk("invalid RESTORE (want =%zu, got %d)",
++ req_restore->size, *len);
++ res = -EINVAL;
++ goto done;
++ }
++ line = ip_set_restore(data + sizeof(struct ip_set_req_setnames),
++ req_restore->size - sizeof(struct ip_set_req_setnames));
++ DP("ip_set_restore: %u", line);
++ if (line != 0) {
++ res = -EAGAIN;
++ req_restore->size = line;
++ copylen = sizeof(struct ip_set_req_setnames);
++ goto copy;
++ }
++ goto done;
++ }
++ default:
++ res = -EBADMSG;
++ goto done;
++ } /* end of switch(op) */
++
++ copy:
++ DP("set %s, copylen %u", index != IP_SET_INVALID_ID
++ && ip_set_list[index]
++ ? ip_set_list[index]->name
++ : ":all:", copylen);
++ if (res == 0)
++ res = copy_to_user(user, data, copylen);
++ else
++ copy_to_user(user, data, copylen);
++
++ done:
++ up(&ip_set_app_mutex);
++ vfree(data);
++ if (res > 0)
++ res = 0;
++ DP("final result %d", res);
++ return res;
++}
++
++static struct nf_sockopt_ops so_set = {
++ .pf = PF_INET,
++ .set_optmin = SO_IP_SET,
++ .set_optmax = SO_IP_SET + 1,
++ .set = &ip_set_sockfn_set,
++ .get_optmin = SO_IP_SET,
++ .get_optmax = SO_IP_SET + 1,
++ .get = &ip_set_sockfn_get,
++ .use = 0
++};
++
++static int max_sets, hash_size;
++module_param(max_sets, int, 0600);
++MODULE_PARM_DESC(max_sets, "maximal number of sets");
++module_param(hash_size, int, 0600);
++MODULE_PARM_DESC(hash_size, "hash size for bindings");
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("module implementing core IP set support");
++
++static int __init init(void)
++{
++ int res;
++ ip_set_id_t i;
++
++ get_random_bytes(&ip_set_hash_random, 4);
++ if (max_sets)
++ ip_set_max = max_sets;
++ ip_set_list = vmalloc(sizeof(struct ip_set *) * ip_set_max);
++ if (!ip_set_list) {
++ printk(KERN_ERR "Unable to create ip_set_list\n");
++ return -ENOMEM;
++ }
++ memset(ip_set_list, 0, sizeof(struct ip_set *) * ip_set_max);
++ if (hash_size)
++ ip_set_bindings_hash_size = hash_size;
++ ip_set_hash = vmalloc(sizeof(struct list_head) * ip_set_bindings_hash_size);
++ if (!ip_set_hash) {
++ printk(KERN_ERR "Unable to create ip_set_hash\n");
++ vfree(ip_set_list);
++ return -ENOMEM;
++ }
++ for (i = 0; i < ip_set_bindings_hash_size; i++)
++ INIT_LIST_HEAD(&ip_set_hash[i]);
++
++ INIT_LIST_HEAD(&set_type_list);
++
++ res = nf_register_sockopt(&so_set);
++ if (res != 0) {
++ ip_set_printk("SO_SET registry failed: %d", res);
++ vfree(ip_set_list);
++ vfree(ip_set_hash);
++ return res;
++ }
++ return 0;
++}
++
++static void __exit fini(void)
++{
++ /* There can't be any existing set or binding */
++ nf_unregister_sockopt(&so_set);
++ vfree(ip_set_list);
++ vfree(ip_set_hash);
++ DP("these are the famous last words");
++}
++
++EXPORT_SYMBOL(ip_set_register_set_type);
++EXPORT_SYMBOL(ip_set_unregister_set_type);
++
++EXPORT_SYMBOL(ip_set_get_byname);
++EXPORT_SYMBOL(ip_set_get_byindex);
++EXPORT_SYMBOL(ip_set_put);
++
++EXPORT_SYMBOL(ip_set_addip_kernel);
++EXPORT_SYMBOL(ip_set_delip_kernel);
++EXPORT_SYMBOL(ip_set_testip_kernel);
++
++module_init(init);
++module_exit(fini);
+diff -Nur linux-2.6.16/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.16-owrt/net/ipv4/netfilter/ip_set_iphash.c
+--- linux-2.6.16/net/ipv4/netfilter/ip_set_iphash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv4/netfilter/ip_set_iphash.c 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,379 @@
++/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* Kernel module implementing an ip hash set */
++
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ip_set.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <linux/spinlock.h>
++#include <linux/vmalloc.h>
++#include <linux/random.h>
++
++#include <net/ip.h>
++
++#include <linux/netfilter_ipv4/ip_set_malloc.h>
++#include <linux/netfilter_ipv4/ip_set_iphash.h>
++#include <linux/netfilter_ipv4/ip_set_jhash.h>
++#include <linux/netfilter_ipv4/ip_set_prime.h>
++
++static inline __u32
++jhash_ip(const struct ip_set_iphash *map, ip_set_ip_t ip)
++{
++ return jhash_1word(ip, map->initval);
++}
++
++static inline __u32
++randhash_ip(const struct ip_set_iphash *map, ip_set_ip_t ip)
++{
++ return (1 + ip % map->prime);
++}
++
++static inline __u32
++hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
++ __u32 jhash, randhash, id;
++ u_int16_t i;
++
++ *hash_ip = ip & map->netmask;
++ jhash = jhash_ip(map, *hash_ip);
++ randhash = randhash_ip(map, *hash_ip);
++ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u, %u.%u.%u.%u",
++ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip), HIPQUAD(map->netmask));
++
++ for (i = 0; i < map->probes; i++) {
++ id = (jhash + i * randhash) % map->hashsize;
++ DP("hash key: %u", id);
++ if (map->members[id] == *hash_ip)
++ return id;
++ /* No shortcut at testing - there can be deleted
++ * entries. */
++ }
++ return UINT_MAX;
++}
++
++static inline int
++__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ return (hash_id(set, ip, hash_ip) != UINT_MAX);
++}
++
++static int
++testip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_iphash *req =
++ (struct ip_set_req_iphash *) data;
++
++ if (size != sizeof(struct ip_set_req_iphash)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_iphash),
++ size);
++ return -EINVAL;
++ }
++ return __testip(set, req->ip, hash_ip);
++}
++
++static int
++testip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ return __testip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++}
++
++static inline int
++__addip(struct ip_set_iphash *map, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ __u32 jhash, randhash, probe;
++ u_int16_t i;
++
++ *hash_ip = ip & map->netmask;
++ jhash = jhash_ip(map, *hash_ip);
++ randhash = randhash_ip(map, *hash_ip);
++
++ for (i = 0; i < map->probes; i++) {
++ probe = (jhash + i * randhash) % map->hashsize;
++ if (map->members[probe] == *hash_ip)
++ return -EEXIST;
++ if (!map->members[probe]) {
++ map->members[probe] = *hash_ip;
++ return 0;
++ }
++ }
++ /* Trigger rehashing */
++ return -EAGAIN;
++}
++
++static int
++addip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_iphash *req =
++ (struct ip_set_req_iphash *) data;
++
++ if (size != sizeof(struct ip_set_req_iphash)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_iphash),
++ size);
++ return -EINVAL;
++ }
++ return __addip((struct ip_set_iphash *) set->data, req->ip, hash_ip);
++}
++
++static int
++addip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ return __addip((struct ip_set_iphash *) set->data,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++}
++
++static int retry(struct ip_set *set)
++{
++ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
++ ip_set_ip_t hash_ip, *members;
++ u_int32_t i, hashsize;
++ unsigned newbytes;
++ int res;
++ struct ip_set_iphash tmp = {
++ .hashsize = map->hashsize,
++ .probes = map->probes,
++ .resize = map->resize,
++ .netmask = map->netmask,
++ };
++
++ if (map->resize == 0)
++ return -ERANGE;
++
++ again:
++ res = 0;
++
++ /* Calculate new parameters */
++ get_random_bytes(&tmp.initval, 4);
++ hashsize = tmp.hashsize + (tmp.hashsize * map->resize)/100;
++ if (hashsize == tmp.hashsize)
++ hashsize++;
++ tmp.prime = make_prime(hashsize);
++
++ ip_set_printk("rehashing of set %s triggered: "
++ "hashsize grows from %u to %u",
++ set->name, tmp.hashsize, hashsize);
++ tmp.hashsize = hashsize;
++
++ newbytes = hashsize * sizeof(ip_set_ip_t);
++ tmp.members = ip_set_malloc_atomic(newbytes);
++ if (!tmp.members) {
++ DP("out of memory for %d bytes", newbytes);
++ return -ENOMEM;
++ }
++ memset(tmp.members, 0, newbytes);
++
++ write_lock_bh(&set->lock);
++ map = (struct ip_set_iphash *) set->data; /* Play safe */
++ for (i = 0; i < map->hashsize && res == 0; i++) {
++ if (map->members[i])
++ res = __addip(&tmp, map->members[i], &hash_ip);
++ }
++ if (res) {
++ /* Failure, try again */
++ write_unlock_bh(&set->lock);
++ ip_set_free(tmp.members, newbytes);
++ goto again;
++ }
++
++ /* Success at resizing! */
++ members = map->members;
++ hashsize = map->hashsize;
++
++ map->initval = tmp.initval;
++ map->prime = tmp.prime;
++ map->hashsize = tmp.hashsize;
++ map->members = tmp.members;
++ write_unlock_bh(&set->lock);
++
++ ip_set_free(members, hashsize * sizeof(ip_set_ip_t));
++
++ return 0;
++}
++
++static inline int
++__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
++ ip_set_ip_t id = hash_id(set, ip, hash_ip);
++
++ if (id == UINT_MAX)
++ return -EEXIST;
++
++ map->members[id] = 0;
++ return 0;
++}
++
++static int
++delip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_iphash *req =
++ (struct ip_set_req_iphash *) data;
++
++ if (size != sizeof(struct ip_set_req_iphash)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_iphash),
++ size);
++ return -EINVAL;
++ }
++ return __delip(set, req->ip, hash_ip);
++}
++
++static int
++delip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ return __delip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++}
++
++static int create(struct ip_set *set, const void *data, size_t size)
++{
++ unsigned newbytes;
++ struct ip_set_req_iphash_create *req =
++ (struct ip_set_req_iphash_create *) data;
++ struct ip_set_iphash *map;
++
++ if (size != sizeof(struct ip_set_req_iphash_create)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_iphash_create),
++ size);
++ return -EINVAL;
++ }
++
++ if (req->hashsize < 1) {
++ ip_set_printk("hashsize too small");
++ return -ENOEXEC;
++ }
++
++ map = kmalloc(sizeof(struct ip_set_iphash), GFP_KERNEL);
++ if (!map) {
++ DP("out of memory for %d bytes",
++ sizeof(struct ip_set_iphash));
++ return -ENOMEM;
++ }
++ get_random_bytes(&map->initval, 4);
++ map->prime = make_prime(req->hashsize);
++ map->hashsize = req->hashsize;
++ map->probes = req->probes;
++ map->resize = req->resize;
++ map->netmask = req->netmask;
++ newbytes = map->hashsize * sizeof(ip_set_ip_t);
++ map->members = ip_set_malloc(newbytes);
++ if (!map->members) {
++ DP("out of memory for %d bytes", newbytes);
++ kfree(map);
++ return -ENOMEM;
++ }
++ memset(map->members, 0, newbytes);
++
++ set->data = map;
++ return 0;
++}
++
++static void destroy(struct ip_set *set)
++{
++ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
++
++ ip_set_free(map->members, map->hashsize * sizeof(ip_set_ip_t));
++ kfree(map);
++
++ set->data = NULL;
++}
++
++static void flush(struct ip_set *set)
++{
++ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
++ memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
++}
++
++static void list_header(const struct ip_set *set, void *data)
++{
++ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
++ struct ip_set_req_iphash_create *header =
++ (struct ip_set_req_iphash_create *) data;
++
++ header->hashsize = map->hashsize;
++ header->probes = map->probes;
++ header->resize = map->resize;
++ header->netmask = map->netmask;
++}
++
++static int list_members_size(const struct ip_set *set)
++{
++ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
++
++ return (map->hashsize * sizeof(ip_set_ip_t));
++}
++
++static void list_members(const struct ip_set *set, void *data)
++{
++ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
++ int bytes = map->hashsize * sizeof(ip_set_ip_t);
++
++ memcpy(data, map->members, bytes);
++}
++
++static struct ip_set_type ip_set_iphash = {
++ .typename = SETTYPE_NAME,
++ .typecode = IPSET_TYPE_IP,
++ .protocol_version = IP_SET_PROTOCOL_VERSION,
++ .create = &create,
++ .destroy = &destroy,
++ .flush = &flush,
++ .reqsize = sizeof(struct ip_set_req_iphash),
++ .addip = &addip,
++ .addip_kernel = &addip_kernel,
++ .retry = &retry,
++ .delip = &delip,
++ .delip_kernel = &delip_kernel,
++ .testip = &testip,
++ .testip_kernel = &testip_kernel,
++ .header_size = sizeof(struct ip_set_req_iphash_create),
++ .list_header = &list_header,
++ .list_members_size = &list_members_size,
++ .list_members = &list_members,
++ .me = THIS_MODULE,
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("iphash type of IP sets");
++
++static int __init init(void)
++{
++ init_max_malloc_size();
++ return ip_set_register_set_type(&ip_set_iphash);
++}
++
++static void __exit fini(void)
++{
++ /* FIXME: possible race with ip_set_create() */
++ ip_set_unregister_set_type(&ip_set_iphash);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Nur linux-2.6.16/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.16-owrt/net/ipv4/netfilter/ip_set_ipmap.c
+--- linux-2.6.16/net/ipv4/netfilter/ip_set_ipmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv4/netfilter/ip_set_ipmap.c 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,313 @@
++/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
++ * Patrick Schaaf <bof@bof.de>
++ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* Kernel module implementing an IP set type: the single bitmap type */
++
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ip_set.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <linux/spinlock.h>
++
++#include <linux/netfilter_ipv4/ip_set_ipmap.h>
++
++static inline ip_set_ip_t
++ip_to_id(const struct ip_set_ipmap *map, ip_set_ip_t ip)
++{
++ return (ip - map->first_ip)/map->hosts;
++}
++
++static inline int
++__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
++
++ if (ip < map->first_ip || ip > map->last_ip)
++ return -ERANGE;
++
++ *hash_ip = ip & map->netmask;
++ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
++ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip));
++ return !!test_bit(ip_to_id(map, *hash_ip), map->members);
++}
++
++static int
++testip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_ipmap *req =
++ (struct ip_set_req_ipmap *) data;
++
++ if (size != sizeof(struct ip_set_req_ipmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_ipmap),
++ size);
++ return -EINVAL;
++ }
++ return __testip(set, req->ip, hash_ip);
++}
++
++static int
++testip_kernel(struct ip_set *set,
++ const struct sk_buff *skb,
++ u_int32_t flags,
++ ip_set_ip_t *hash_ip)
++{
++ int res;
++
++ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
++ flags & IPSET_SRC ? "SRC" : "DST",
++ NIPQUAD(skb->nh.iph->saddr),
++ NIPQUAD(skb->nh.iph->daddr));
++
++ res = __testip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++ return (res < 0 ? 0 : res);
++}
++
++static inline int
++__addip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
++
++ if (ip < map->first_ip || ip > map->last_ip)
++ return -ERANGE;
++
++ *hash_ip = ip & map->netmask;
++ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
++ if (test_and_set_bit(ip_to_id(map, *hash_ip), map->members))
++ return -EEXIST;
++
++ return 0;
++}
++
++static int
++addip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_ipmap *req =
++ (struct ip_set_req_ipmap *) data;
++
++ if (size != sizeof(struct ip_set_req_ipmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_ipmap),
++ size);
++ return -EINVAL;
++ }
++ DP("%u.%u.%u.%u", HIPQUAD(req->ip));
++ return __addip(set, req->ip, hash_ip);
++}
++
++static int
++addip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ return __addip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++}
++
++static inline int
++__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
++
++ if (ip < map->first_ip || ip > map->last_ip)
++ return -ERANGE;
++
++ *hash_ip = ip & map->netmask;
++ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
++ if (!test_and_clear_bit(ip_to_id(map, *hash_ip), map->members))
++ return -EEXIST;
++
++ return 0;
++}
++
++static int
++delip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_ipmap *req =
++ (struct ip_set_req_ipmap *) data;
++
++ if (size != sizeof(struct ip_set_req_ipmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_ipmap),
++ size);
++ return -EINVAL;
++ }
++ return __delip(set, req->ip, hash_ip);
++}
++
++static int
++delip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ return __delip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++}
++
++static int create(struct ip_set *set, const void *data, size_t size)
++{
++ int newbytes;
++ struct ip_set_req_ipmap_create *req =
++ (struct ip_set_req_ipmap_create *) data;
++ struct ip_set_ipmap *map;
++
++ if (size != sizeof(struct ip_set_req_ipmap_create)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_ipmap_create),
++ size);
++ return -EINVAL;
++ }
++
++ DP("from %u.%u.%u.%u to %u.%u.%u.%u",
++ HIPQUAD(req->from), HIPQUAD(req->to));
++
++ if (req->from > req->to) {
++ DP("bad ip range");
++ return -ENOEXEC;
++ }
++
++ if (req->to - req->from > MAX_RANGE) {
++ ip_set_printk("range too big (max %d addresses)",
++ MAX_RANGE);
++ return -ENOEXEC;
++ }
++
++ map = kmalloc(sizeof(struct ip_set_ipmap), GFP_KERNEL);
++ if (!map) {
++ DP("out of memory for %d bytes",
++ sizeof(struct ip_set_ipmap));
++ return -ENOMEM;
++ }
++ map->first_ip = req->from;
++ map->last_ip = req->to;
++ map->netmask = req->netmask;
++
++ if (req->netmask == 0xFFFFFFFF) {
++ map->hosts = 1;
++ map->sizeid = map->last_ip - map->first_ip + 1;
++ } else {
++ unsigned int mask_bits, netmask_bits;
++ ip_set_ip_t mask;
++
++ map->first_ip &= map->netmask; /* Should we better bark? */
++
++ mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits);
++ netmask_bits = mask_to_bits(map->netmask);
++
++ if (!mask || netmask_bits <= mask_bits)
++ return -ENOEXEC;
++
++ map->hosts = 2 << (32 - netmask_bits - 1);
++ map->sizeid = 2 << (netmask_bits - mask_bits - 1);
++ }
++ newbytes = bitmap_bytes(0, map->sizeid - 1);
++ map->members = kmalloc(newbytes, GFP_KERNEL);
++ if (!map->members) {
++ DP("out of memory for %d bytes", newbytes);
++ kfree(map);
++ return -ENOMEM;
++ }
++ memset(map->members, 0, newbytes);
++
++ set->data = map;
++ return 0;
++}
++
++static void destroy(struct ip_set *set)
++{
++ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
++
++ kfree(map->members);
++ kfree(map);
++
++ set->data = NULL;
++}
++
++static void flush(struct ip_set *set)
++{
++ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
++ memset(map->members, 0, bitmap_bytes(0, map->sizeid - 1));
++}
++
++static void list_header(const struct ip_set *set, void *data)
++{
++ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
++ struct ip_set_req_ipmap_create *header =
++ (struct ip_set_req_ipmap_create *) data;
++
++ header->from = map->first_ip;
++ header->to = map->last_ip;
++ header->netmask = map->netmask;
++}
++
++static int list_members_size(const struct ip_set *set)
++{
++ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
++
++ return bitmap_bytes(0, map->sizeid - 1);
++}
++
++static void list_members(const struct ip_set *set, void *data)
++{
++ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
++ int bytes = bitmap_bytes(0, map->sizeid - 1);
++
++ memcpy(data, map->members, bytes);
++}
++
++static struct ip_set_type ip_set_ipmap = {
++ .typename = SETTYPE_NAME,
++ .typecode = IPSET_TYPE_IP,
++ .protocol_version = IP_SET_PROTOCOL_VERSION,
++ .create = &create,
++ .destroy = &destroy,
++ .flush = &flush,
++ .reqsize = sizeof(struct ip_set_req_ipmap),
++ .addip = &addip,
++ .addip_kernel = &addip_kernel,
++ .delip = &delip,
++ .delip_kernel = &delip_kernel,
++ .testip = &testip,
++ .testip_kernel = &testip_kernel,
++ .header_size = sizeof(struct ip_set_req_ipmap_create),
++ .list_header = &list_header,
++ .list_members_size = &list_members_size,
++ .list_members = &list_members,
++ .me = THIS_MODULE,
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("ipmap type of IP sets");
++
++static int __init init(void)
++{
++ return ip_set_register_set_type(&ip_set_ipmap);
++}
++
++static void __exit fini(void)
++{
++ /* FIXME: possible race with ip_set_create() */
++ ip_set_unregister_set_type(&ip_set_ipmap);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Nur linux-2.6.16/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.16-owrt/net/ipv4/netfilter/ip_set_iptree.c
+--- linux-2.6.16/net/ipv4/netfilter/ip_set_iptree.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv4/netfilter/ip_set_iptree.c 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,510 @@
++/* Copyright (C) 2005 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* Kernel module implementing an IP set type: the iptree type */
++
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ip_set.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <linux/spinlock.h>
++
++#include <linux/netfilter_ipv4/ip_set_iptree.h>
++
++/* Garbage collection interval in seconds: */
++#define IPTREE_GC_TIME 5*60
++/* Sleep so many milliseconds before trying again
++ * to delete the gc timer at destroying a set */
++#define IPTREE_DESTROY_SLEEP 100
++
++static kmem_cache_t *branch_cachep;
++static kmem_cache_t *leaf_cachep;
++
++#define ABCD(a,b,c,d,addrp) do { \
++ a = ((unsigned char *)addrp)[3]; \
++ b = ((unsigned char *)addrp)[2]; \
++ c = ((unsigned char *)addrp)[1]; \
++ d = ((unsigned char *)addrp)[0]; \
++} while (0)
++
++#define TESTIP_WALK(map, elem, branch) do { \
++ if ((map)->tree[elem]) { \
++ branch = (map)->tree[elem]; \
++ } else \
++ return 0; \
++} while (0)
++
++static inline int
++__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ struct ip_set_iptreeb *btree;
++ struct ip_set_iptreec *ctree;
++ struct ip_set_iptreed *dtree;
++ unsigned char a,b,c,d;
++
++ *hash_ip = ip;
++ ABCD(a, b, c, d, hash_ip);
++ DP("%u %u %u %u timeout %u", a, b, c, d, map->timeout);
++ TESTIP_WALK(map, a, btree);
++ TESTIP_WALK(btree, b, ctree);
++ TESTIP_WALK(ctree, c, dtree);
++ DP("%lu %lu", dtree->expires[d], jiffies);
++ return !!(map->timeout ? (time_after(dtree->expires[d], jiffies))
++ : dtree->expires[d]);
++}
++
++static int
++testip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_iptree *req =
++ (struct ip_set_req_iptree *) data;
++
++ if (size != sizeof(struct ip_set_req_iptree)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_iptree),
++ size);
++ return -EINVAL;
++ }
++ return __testip(set, req->ip, hash_ip);
++}
++
++static int
++testip_kernel(struct ip_set *set,
++ const struct sk_buff *skb,
++ u_int32_t flags,
++ ip_set_ip_t *hash_ip)
++{
++ int res;
++
++ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
++ flags & IPSET_SRC ? "SRC" : "DST",
++ NIPQUAD(skb->nh.iph->saddr),
++ NIPQUAD(skb->nh.iph->daddr));
++
++ res = __testip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++ return (res < 0 ? 0 : res);
++}
++
++#define ADDIP_WALK(map, elem, branch, type, cachep) do { \
++ if ((map)->tree[elem]) { \
++ DP("found %u", elem); \
++ branch = (map)->tree[elem]; \
++ } else { \
++ branch = (type *) \
++ kmem_cache_alloc(cachep, GFP_KERNEL); \
++ if (branch == NULL) \
++ return -ENOMEM; \
++ memset(branch, 0, sizeof(*branch)); \
++ (map)->tree[elem] = branch; \
++ DP("alloc %u", elem); \
++ } \
++} while (0)
++
++static inline int
++__addip(struct ip_set *set, ip_set_ip_t ip, unsigned int timeout,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ struct ip_set_iptreeb *btree;
++ struct ip_set_iptreec *ctree;
++ struct ip_set_iptreed *dtree;
++ unsigned char a,b,c,d;
++ int ret = 0;
++
++ *hash_ip = ip;
++ ABCD(a, b, c, d, hash_ip);
++ DP("%u %u %u %u timeout %u", a, b, c, d, timeout);
++ ADDIP_WALK(map, a, btree, struct ip_set_iptreeb, branch_cachep);
++ ADDIP_WALK(btree, b, ctree, struct ip_set_iptreec, branch_cachep);
++ ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreed, leaf_cachep);
++ if (dtree->expires[d]
++ && (!map->timeout || time_after(dtree->expires[d], jiffies)))
++ ret = -EEXIST;
++ dtree->expires[d] = map->timeout ? (timeout * HZ + jiffies) : 1;
++ DP("%u %lu", d, dtree->expires[d]);
++ return ret;
++}
++
++static int
++addip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ struct ip_set_req_iptree *req =
++ (struct ip_set_req_iptree *) data;
++
++ if (size != sizeof(struct ip_set_req_iptree)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_iptree),
++ size);
++ return -EINVAL;
++ }
++ DP("%u.%u.%u.%u %u", HIPQUAD(req->ip), req->timeout);
++ return __addip(set, req->ip,
++ req->timeout ? req->timeout : map->timeout,
++ hash_ip);
++}
++
++static int
++addip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++
++ return __addip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ map->timeout,
++ hash_ip);
++}
++
++#define DELIP_WALK(map, elem, branch) do { \
++ if ((map)->tree[elem]) { \
++ branch = (map)->tree[elem]; \
++ } else \
++ return -EEXIST; \
++} while (0)
++
++static inline int
++__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ struct ip_set_iptreeb *btree;
++ struct ip_set_iptreec *ctree;
++ struct ip_set_iptreed *dtree;
++ unsigned char a,b,c,d;
++
++ *hash_ip = ip;
++ ABCD(a, b, c, d, hash_ip);
++ DELIP_WALK(map, a, btree);
++ DELIP_WALK(btree, b, ctree);
++ DELIP_WALK(ctree, c, dtree);
++
++ if (dtree->expires[d]) {
++ dtree->expires[d] = 0;
++ return 0;
++ }
++ return -EEXIST;
++}
++
++static int
++delip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_iptree *req =
++ (struct ip_set_req_iptree *) data;
++
++ if (size != sizeof(struct ip_set_req_iptree)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_iptree),
++ size);
++ return -EINVAL;
++ }
++ return __delip(set, req->ip, hash_ip);
++}
++
++static int
++delip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ return __delip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++}
++
++#define LOOP_WALK_BEGIN(map, i, branch) \
++ for (i = 0; i < 255; i++) { \
++ if (!(map)->tree[i]) \
++ continue; \
++ branch = (map)->tree[i]
++
++#define LOOP_WALK_END }
++
++static void ip_tree_gc(unsigned long ul_set)
++{
++ struct ip_set *set = (void *) ul_set;
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ struct ip_set_iptreeb *btree;
++ struct ip_set_iptreec *ctree;
++ struct ip_set_iptreed *dtree;
++ unsigned char a,b,c,d;
++ unsigned char i,j,k;
++
++ i = j = k = 0;
++ DP("gc: %s", set->name);
++ write_lock_bh(&set->lock);
++ LOOP_WALK_BEGIN(map, a, btree);
++ LOOP_WALK_BEGIN(btree, b, ctree);
++ LOOP_WALK_BEGIN(ctree, c, dtree);
++ for (d = 0; d < 255; d++) {
++ if (dtree->expires[d]) {
++ DP("gc: %u %u %u %u: expires %lu jiffies %lu",
++ a, b, c, d,
++ dtree->expires[d], jiffies);
++ if (map->timeout
++ && time_before(dtree->expires[d], jiffies))
++ dtree->expires[d] = 0;
++ else
++ k = 1;
++ }
++ }
++ if (k == 0) {
++ DP("gc: %s: leaf %u %u %u empty",
++ set->name, a, b, c);
++ kmem_cache_free(leaf_cachep, dtree);
++ ctree->tree[c] = NULL;
++ } else {
++ DP("gc: %s: leaf %u %u %u not empty",
++ set->name, a, b, c);
++ j = 1;
++ k = 0;
++ }
++ LOOP_WALK_END;
++ if (j == 0) {
++ DP("gc: %s: branch %u %u empty",
++ set->name, a, b);
++ kmem_cache_free(branch_cachep, ctree);
++ btree->tree[b] = NULL;
++ } else {
++ DP("gc: %s: branch %u %u not empty",
++ set->name, a, b);
++ i = 1;
++ j = k = 0;
++ }
++ LOOP_WALK_END;
++ if (i == 0) {
++ DP("gc: %s: branch %u empty",
++ set->name, a);
++ kmem_cache_free(branch_cachep, btree);
++ map->tree[a] = NULL;
++ } else {
++ DP("gc: %s: branch %u not empty",
++ set->name, a);
++ i = j = k = 0;
++ }
++ LOOP_WALK_END;
++ write_unlock_bh(&set->lock);
++
++ map->gc.expires = jiffies + map->gc_interval * HZ;
++ add_timer(&map->gc);
++}
++
++static int create(struct ip_set *set, const void *data, size_t size)
++{
++ struct ip_set_req_iptree_create *req =
++ (struct ip_set_req_iptree_create *) data;
++ struct ip_set_iptree *map;
++
++ if (size != sizeof(struct ip_set_req_iptree_create)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_iptree_create),
++ size);
++ return -EINVAL;
++ }
++
++ map = kmalloc(sizeof(struct ip_set_iptree), GFP_KERNEL);
++ if (!map) {
++ DP("out of memory for %d bytes",
++ sizeof(struct ip_set_iptree));
++ return -ENOMEM;
++ }
++ memset(map, 0, sizeof(*map));
++ map->timeout = req->timeout;
++ set->data = map;
++
++ /* If there is no timeout for the entries,
++ * we still have to call gc because delete
++ * do not clean up empty branches */
++ map->gc_interval = IPTREE_GC_TIME;
++ init_timer(&map->gc);
++ map->gc.data = (unsigned long) set;
++ map->gc.function = ip_tree_gc;
++ map->gc.expires = jiffies + map->gc_interval * HZ;
++ add_timer(&map->gc);
++
++ return 0;
++}
++
++static void __flush(struct ip_set_iptree *map)
++{
++ struct ip_set_iptreeb *btree;
++ struct ip_set_iptreec *ctree;
++ struct ip_set_iptreed *dtree;
++ unsigned int a,b,c;
++
++ LOOP_WALK_BEGIN(map, a, btree);
++ LOOP_WALK_BEGIN(btree, b, ctree);
++ LOOP_WALK_BEGIN(ctree, c, dtree);
++ kmem_cache_free(leaf_cachep, dtree);
++ LOOP_WALK_END;
++ kmem_cache_free(branch_cachep, ctree);
++ LOOP_WALK_END;
++ kmem_cache_free(branch_cachep, btree);
++ LOOP_WALK_END;
++}
++
++static void destroy(struct ip_set *set)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++
++ while (!del_timer(&map->gc))
++ msleep(IPTREE_DESTROY_SLEEP);
++ __flush(map);
++ kfree(map);
++ set->data = NULL;
++}
++
++static void flush(struct ip_set *set)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ unsigned int timeout = map->timeout;
++
++ __flush(map);
++ memset(map, 0, sizeof(*map));
++ map->timeout = timeout;
++}
++
++static void list_header(const struct ip_set *set, void *data)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ struct ip_set_req_iptree_create *header =
++ (struct ip_set_req_iptree_create *) data;
++
++ header->timeout = map->timeout;
++}
++
++static int list_members_size(const struct ip_set *set)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ struct ip_set_iptreeb *btree;
++ struct ip_set_iptreec *ctree;
++ struct ip_set_iptreed *dtree;
++ unsigned char a,b,c,d;
++ unsigned int count = 0;
++
++ LOOP_WALK_BEGIN(map, a, btree);
++ LOOP_WALK_BEGIN(btree, b, ctree);
++ LOOP_WALK_BEGIN(ctree, c, dtree);
++ for (d = 0; d < 255; d++) {
++ if (dtree->expires[d]
++ && (!map->timeout || time_after(dtree->expires[d], jiffies)))
++ count++;
++ }
++ LOOP_WALK_END;
++ LOOP_WALK_END;
++ LOOP_WALK_END;
++
++ DP("members %u", count);
++ return (count * sizeof(struct ip_set_req_iptree));
++}
++
++static void list_members(const struct ip_set *set, void *data)
++{
++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
++ struct ip_set_iptreeb *btree;
++ struct ip_set_iptreec *ctree;
++ struct ip_set_iptreed *dtree;
++ unsigned char a,b,c,d;
++ size_t offset = 0;
++ struct ip_set_req_iptree *entry;
++
++ LOOP_WALK_BEGIN(map, a, btree);
++ LOOP_WALK_BEGIN(btree, b, ctree);
++ LOOP_WALK_BEGIN(ctree, c, dtree);
++ for (d = 0; d < 255; d++) {
++ if (dtree->expires[d]
++ && (!map->timeout || time_after(dtree->expires[d], jiffies))) {
++ entry = (struct ip_set_req_iptree *)(data + offset);
++ entry->ip = ((a << 24) | (b << 16) | (c << 8) | d);
++ entry->timeout = !map->timeout ? 0
++ : (dtree->expires[d] - jiffies)/HZ;
++ offset += sizeof(struct ip_set_req_iptree);
++ }
++ }
++ LOOP_WALK_END;
++ LOOP_WALK_END;
++ LOOP_WALK_END;
++}
++
++static struct ip_set_type ip_set_iptree = {
++ .typename = SETTYPE_NAME,
++ .typecode = IPSET_TYPE_IP,
++ .protocol_version = IP_SET_PROTOCOL_VERSION,
++ .create = &create,
++ .destroy = &destroy,
++ .flush = &flush,
++ .reqsize = sizeof(struct ip_set_req_iptree),
++ .addip = &addip,
++ .addip_kernel = &addip_kernel,
++ .delip = &delip,
++ .delip_kernel = &delip_kernel,
++ .testip = &testip,
++ .testip_kernel = &testip_kernel,
++ .header_size = sizeof(struct ip_set_req_iptree_create),
++ .list_header = &list_header,
++ .list_members_size = &list_members_size,
++ .list_members = &list_members,
++ .me = THIS_MODULE,
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("iptree type of IP sets");
++
++static int __init init(void)
++{
++ int ret;
++
++ branch_cachep = kmem_cache_create("ip_set_iptreeb",
++ sizeof(struct ip_set_iptreeb),
++ 0, 0, NULL, NULL);
++ if (!branch_cachep) {
++ printk(KERN_ERR "Unable to create ip_set_iptreeb slab cache\n");
++ ret = -ENOMEM;
++ goto out;
++ }
++ leaf_cachep = kmem_cache_create("ip_set_iptreed",
++ sizeof(struct ip_set_iptreed),
++ 0, 0, NULL, NULL);
++ if (!leaf_cachep) {
++ printk(KERN_ERR "Unable to create ip_set_iptreed slab cache\n");
++ ret = -ENOMEM;
++ goto free_branch;
++ }
++ ret = ip_set_register_set_type(&ip_set_iptree);
++ if (ret == 0)
++ goto out;
++
++ kmem_cache_destroy(leaf_cachep);
++ free_branch:
++ kmem_cache_destroy(branch_cachep);
++ out:
++ return ret;
++}
++
++static void __exit fini(void)
++{
++ /* FIXME: possible race with ip_set_create() */
++ ip_set_unregister_set_type(&ip_set_iptree);
++ kmem_cache_destroy(leaf_cachep);
++ kmem_cache_destroy(branch_cachep);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Nur linux-2.6.16/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.16-owrt/net/ipv4/netfilter/ip_set_macipmap.c
+--- linux-2.6.16/net/ipv4/netfilter/ip_set_macipmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv4/netfilter/ip_set_macipmap.c 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,338 @@
++/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
++ * Patrick Schaaf <bof@bof.de>
++ * Martin Josefsson <gandalf@wlug.westbo.se>
++ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* Kernel module implementing an IP set type: the macipmap type */
++
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ip_set.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <linux/spinlock.h>
++#include <linux/if_ether.h>
++#include <linux/vmalloc.h>
++
++#include <linux/netfilter_ipv4/ip_set_malloc.h>
++#include <linux/netfilter_ipv4/ip_set_macipmap.h>
++
++static int
++testip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_macipmap *map = (struct ip_set_macipmap *) set->data;
++ struct ip_set_macip *table = (struct ip_set_macip *) map->members;
++ struct ip_set_req_macipmap *req = (struct ip_set_req_macipmap *) data;
++
++ if (size != sizeof(struct ip_set_req_macipmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_macipmap),
++ size);
++ return -EINVAL;
++ }
++
++ if (req->ip < map->first_ip || req->ip > map->last_ip)
++ return -ERANGE;
++
++ *hash_ip = req->ip;
++ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
++ set->name, HIPQUAD(req->ip), HIPQUAD(*hash_ip));
++ if (test_bit(IPSET_MACIP_ISSET,
++ (void *) &table[req->ip - map->first_ip].flags)) {
++ return (memcmp(req->ethernet,
++ &table[req->ip - map->first_ip].ethernet,
++ ETH_ALEN) == 0);
++ } else {
++ return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
++ }
++}
++
++static int
++testip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_macipmap *map =
++ (struct ip_set_macipmap *) set->data;
++ struct ip_set_macip *table =
++ (struct ip_set_macip *) map->members;
++ ip_set_ip_t ip;
++
++ ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr);
++ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
++ flags & IPSET_SRC ? "SRC" : "DST",
++ NIPQUAD(skb->nh.iph->saddr),
++ NIPQUAD(skb->nh.iph->daddr));
++
++ if (ip < map->first_ip || ip > map->last_ip)
++ return 0;
++
++ *hash_ip = ip;
++ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
++ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip));
++ if (test_bit(IPSET_MACIP_ISSET,
++ (void *) &table[ip - map->first_ip].flags)) {
++ /* Is mac pointer valid?
++ * If so, compare... */
++ return (skb->mac.raw >= skb->head
++ && (skb->mac.raw + ETH_HLEN) <= skb->data
++ && (memcmp(eth_hdr(skb)->h_source,
++ &table[ip - map->first_ip].ethernet,
++ ETH_ALEN) == 0));
++ } else {
++ return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
++ }
++}
++
++/* returns 0 on success */
++static inline int
++__addip(struct ip_set *set,
++ ip_set_ip_t ip, unsigned char *ethernet, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_macipmap *map =
++ (struct ip_set_macipmap *) set->data;
++ struct ip_set_macip *table =
++ (struct ip_set_macip *) map->members;
++
++ if (ip < map->first_ip || ip > map->last_ip)
++ return -ERANGE;
++ if (test_and_set_bit(IPSET_MACIP_ISSET,
++ (void *) &table[ip - map->first_ip].flags))
++ return -EEXIST;
++
++ *hash_ip = ip;
++ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
++ memcpy(&table[ip - map->first_ip].ethernet, ethernet, ETH_ALEN);
++ return 0;
++}
++
++static int
++addip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_macipmap *req =
++ (struct ip_set_req_macipmap *) data;
++
++ if (size != sizeof(struct ip_set_req_macipmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_macipmap),
++ size);
++ return -EINVAL;
++ }
++ return __addip(set, req->ip, req->ethernet, hash_ip);
++}
++
++static int
++addip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ ip_set_ip_t ip;
++
++ ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr);
++
++ if (!(skb->mac.raw >= skb->head
++ && (skb->mac.raw + ETH_HLEN) <= skb->data))
++ return -EINVAL;
++
++ return __addip(set, ip, eth_hdr(skb)->h_source, hash_ip);
++}
++
++static inline int
++__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_macipmap *map =
++ (struct ip_set_macipmap *) set->data;
++ struct ip_set_macip *table =
++ (struct ip_set_macip *) map->members;
++
++ if (ip < map->first_ip || ip > map->last_ip)
++ return -ERANGE;
++ if (!test_and_clear_bit(IPSET_MACIP_ISSET,
++ (void *)&table[ip - map->first_ip].flags))
++ return -EEXIST;
++
++ *hash_ip = ip;
++ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
++ return 0;
++}
++
++static int
++delip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_macipmap *req =
++ (struct ip_set_req_macipmap *) data;
++
++ if (size != sizeof(struct ip_set_req_macipmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_macipmap),
++ size);
++ return -EINVAL;
++ }
++ return __delip(set, req->ip, hash_ip);
++}
++
++static int
++delip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ return __delip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++}
++
++static inline size_t members_size(ip_set_id_t from, ip_set_id_t to)
++{
++ return (size_t)((to - from + 1) * sizeof(struct ip_set_macip));
++}
++
++static int create(struct ip_set *set, const void *data, size_t size)
++{
++ int newbytes;
++ struct ip_set_req_macipmap_create *req =
++ (struct ip_set_req_macipmap_create *) data;
++ struct ip_set_macipmap *map;
++
++ if (size != sizeof(struct ip_set_req_macipmap_create)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_macipmap_create),
++ size);
++ return -EINVAL;
++ }
++
++ DP("from %u.%u.%u.%u to %u.%u.%u.%u",
++ HIPQUAD(req->from), HIPQUAD(req->to));
++
++ if (req->from > req->to) {
++ DP("bad ip range");
++ return -ENOEXEC;
++ }
++
++ if (req->to - req->from > MAX_RANGE) {
++ ip_set_printk("range too big (max %d addresses)",
++ MAX_RANGE);
++ return -ENOEXEC;
++ }
++
++ map = kmalloc(sizeof(struct ip_set_macipmap), GFP_KERNEL);
++ if (!map) {
++ DP("out of memory for %d bytes",
++ sizeof(struct ip_set_macipmap));
++ return -ENOMEM;
++ }
++ map->flags = req->flags;
++ map->first_ip = req->from;
++ map->last_ip = req->to;
++ newbytes = members_size(map->first_ip, map->last_ip);
++ map->members = ip_set_malloc(newbytes);
++ if (!map->members) {
++ DP("out of memory for %d bytes", newbytes);
++ kfree(map);
++ return -ENOMEM;
++ }
++ memset(map->members, 0, newbytes);
++
++ set->data = map;
++ return 0;
++}
++
++static void destroy(struct ip_set *set)
++{
++ struct ip_set_macipmap *map =
++ (struct ip_set_macipmap *) set->data;
++
++ ip_set_free(map->members, members_size(map->first_ip, map->last_ip));
++ kfree(map);
++
++ set->data = NULL;
++}
++
++static void flush(struct ip_set *set)
++{
++ struct ip_set_macipmap *map =
++ (struct ip_set_macipmap *) set->data;
++ memset(map->members, 0, members_size(map->first_ip, map->last_ip));
++}
++
++static void list_header(const struct ip_set *set, void *data)
++{
++ struct ip_set_macipmap *map =
++ (struct ip_set_macipmap *) set->data;
++ struct ip_set_req_macipmap_create *header =
++ (struct ip_set_req_macipmap_create *) data;
++
++ DP("list_header %x %x %u", map->first_ip, map->last_ip,
++ map->flags);
++
++ header->from = map->first_ip;
++ header->to = map->last_ip;
++ header->flags = map->flags;
++}
++
++static int list_members_size(const struct ip_set *set)
++{
++ struct ip_set_macipmap *map =
++ (struct ip_set_macipmap *) set->data;
++
++ return members_size(map->first_ip, map->last_ip);
++}
++
++static void list_members(const struct ip_set *set, void *data)
++{
++ struct ip_set_macipmap *map =
++ (struct ip_set_macipmap *) set->data;
++
++ int bytes = members_size(map->first_ip, map->last_ip);
++
++ memcpy(data, map->members, bytes);
++}
++
++static struct ip_set_type ip_set_macipmap = {
++ .typename = SETTYPE_NAME,
++ .typecode = IPSET_TYPE_IP,
++ .protocol_version = IP_SET_PROTOCOL_VERSION,
++ .create = &create,
++ .destroy = &destroy,
++ .flush = &flush,
++ .reqsize = sizeof(struct ip_set_req_macipmap),
++ .addip = &addip,
++ .addip_kernel = &addip_kernel,
++ .delip = &delip,
++ .delip_kernel = &delip_kernel,
++ .testip = &testip,
++ .testip_kernel = &testip_kernel,
++ .header_size = sizeof(struct ip_set_req_macipmap_create),
++ .list_header = &list_header,
++ .list_members_size = &list_members_size,
++ .list_members = &list_members,
++ .me = THIS_MODULE,
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("macipmap type of IP sets");
++
++static int __init init(void)
++{
++ init_max_malloc_size();
++ return ip_set_register_set_type(&ip_set_macipmap);
++}
++
++static void __exit fini(void)
++{
++ /* FIXME: possible race with ip_set_create() */
++ ip_set_unregister_set_type(&ip_set_macipmap);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Nur linux-2.6.16/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.16-owrt/net/ipv4/netfilter/ip_set_nethash.c
+--- linux-2.6.16/net/ipv4/netfilter/ip_set_nethash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv4/netfilter/ip_set_nethash.c 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,449 @@
++/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* Kernel module implementing a cidr nethash set */
++
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ip_set.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <linux/spinlock.h>
++#include <linux/vmalloc.h>
++#include <linux/random.h>
++
++#include <net/ip.h>
++
++#include <linux/netfilter_ipv4/ip_set_malloc.h>
++#include <linux/netfilter_ipv4/ip_set_nethash.h>
++#include <linux/netfilter_ipv4/ip_set_jhash.h>
++#include <linux/netfilter_ipv4/ip_set_prime.h>
++
++static inline __u32
++jhash_ip(const struct ip_set_nethash *map, ip_set_ip_t ip)
++{
++ return jhash_1word(ip, map->initval);
++}
++
++static inline __u32
++randhash_ip(const struct ip_set_nethash *map, ip_set_ip_t ip)
++{
++ return (1 + ip % map->prime);
++}
++
++static inline __u32
++hash_id_cidr(struct ip_set_nethash *map,
++ ip_set_ip_t ip,
++ unsigned char cidr,
++ ip_set_ip_t *hash_ip)
++{
++ __u32 jhash, randhash, id;
++ u_int16_t i;
++
++ *hash_ip = pack(ip, cidr);
++ jhash = jhash_ip(map, *hash_ip);
++ randhash = randhash_ip(map, *hash_ip);
++
++ for (i = 0; i < map->probes; i++) {
++ id = (jhash + i * randhash) % map->hashsize;
++ DP("hash key: %u", id);
++ if (map->members[id] == *hash_ip)
++ return id;
++ }
++ return UINT_MAX;
++}
++
++static inline __u32
++hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++ __u32 id = UINT_MAX;
++ int i;
++
++ for (i = 0; i < 30 && map->cidr[i]; i++) {
++ id = hash_id_cidr(map, ip, map->cidr[i], hash_ip);
++ if (id != UINT_MAX)
++ break;
++ }
++ return id;
++}
++
++static inline int
++__testip_cidr(struct ip_set *set, ip_set_ip_t ip, unsigned char cidr,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++
++ return (hash_id_cidr(map, ip, cidr, hash_ip) != UINT_MAX);
++}
++
++static inline int
++__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ return (hash_id(set, ip, hash_ip) != UINT_MAX);
++}
++
++static int
++testip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_nethash *req =
++ (struct ip_set_req_nethash *) data;
++
++ if (size != sizeof(struct ip_set_req_nethash)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_nethash),
++ size);
++ return -EINVAL;
++ }
++ return (req->cidr == 32 ? __testip(set, req->ip, hash_ip)
++ : __testip_cidr(set, req->ip, req->cidr, hash_ip));
++}
++
++static int
++testip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ return __testip(set,
++ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++ hash_ip);
++}
++
++static inline int
++__addip_base(struct ip_set_nethash *map, ip_set_ip_t ip)
++{
++ __u32 jhash, randhash, probe;
++ u_int16_t i;
++
++ jhash = jhash_ip(map, ip);
++ randhash = randhash_ip(map, ip);
++
++ for (i = 0; i < map->probes; i++) {
++ probe = (jhash + i * randhash) % map->hashsize;
++ if (map->members[probe] == ip)
++ return -EEXIST;
++ if (!map->members[probe]) {
++ map->members[probe] = ip;
++ return 0;
++ }
++ }
++ /* Trigger rehashing */
++ return -EAGAIN;
++}
++
++static inline int
++__addip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
++ ip_set_ip_t *hash_ip)
++{
++ *hash_ip = pack(ip, cidr);
++ DP("%u.%u.%u.%u/%u, %u.%u.%u.%u", HIPQUAD(ip), cidr, HIPQUAD(*hash_ip));
++
++ return __addip_base(map, *hash_ip);
++}
++
++static void
++update_cidr_sizes(struct ip_set_nethash *map, unsigned char cidr)
++{
++ unsigned char next;
++ int i;
++
++ for (i = 0; i < 30 && map->cidr[i]; i++) {
++ if (map->cidr[i] == cidr) {
++ return;
++ } else if (map->cidr[i] < cidr) {
++ next = map->cidr[i];
++ map->cidr[i] = cidr;
++ cidr = next;
++ }
++ }
++ if (i < 30)
++ map->cidr[i] = cidr;
++}
++
++static int
++addip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_nethash *req =
++ (struct ip_set_req_nethash *) data;
++ int ret;
++
++ if (size != sizeof(struct ip_set_req_nethash)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_nethash),
++ size);
++ return -EINVAL;
++ }
++ ret = __addip((struct ip_set_nethash *) set->data,
++ req->ip, req->cidr, hash_ip);
++
++ if (ret == 0)
++ update_cidr_sizes((struct ip_set_nethash *) set->data,
++ req->cidr);
++
++ return ret;
++}
++
++static int
++addip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++ int ret = -ERANGE;
++ ip_set_ip_t ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr);
++
++ if (map->cidr[0])
++ ret = __addip(map, ip, map->cidr[0], hash_ip);
++
++ return ret;
++}
++
++static int retry(struct ip_set *set)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++ ip_set_ip_t *members;
++ u_int32_t i, hashsize;
++ unsigned newbytes;
++ int res;
++ struct ip_set_nethash tmp = {
++ .hashsize = map->hashsize,
++ .probes = map->probes,
++ .resize = map->resize
++ };
++
++ if (map->resize == 0)
++ return -ERANGE;
++
++ memcpy(tmp.cidr, map->cidr, 30 * sizeof(unsigned char));
++ again:
++ res = 0;
++
++ /* Calculate new parameters */
++ get_random_bytes(&tmp.initval, 4);
++ hashsize = tmp.hashsize + (tmp.hashsize * map->resize)/100;
++ if (hashsize == tmp.hashsize)
++ hashsize++;
++ tmp.prime = make_prime(hashsize);
++
++ ip_set_printk("rehashing of set %s triggered: "
++ "hashsize grows from %u to %u",
++ set->name, tmp.hashsize, hashsize);
++ tmp.hashsize = hashsize;
++
++ newbytes = hashsize * sizeof(ip_set_ip_t);
++ tmp.members = ip_set_malloc_atomic(newbytes);
++ if (!tmp.members) {
++ DP("out of memory for %d bytes", newbytes);
++ return -ENOMEM;
++ }
++ memset(tmp.members, 0, newbytes);
++
++ write_lock_bh(&set->lock);
++ map = (struct ip_set_nethash *) set->data; /* Play safe */
++ for (i = 0; i < map->hashsize && res == 0; i++) {
++ if (map->members[i])
++ res = __addip_base(&tmp, map->members[i]);
++ }
++ if (res) {
++ /* Failure, try again */
++ write_unlock_bh(&set->lock);
++ ip_set_free(tmp.members, newbytes);
++ goto again;
++ }
++
++ /* Success at resizing! */
++ members = map->members;
++ hashsize = map->hashsize;
++
++ map->initval = tmp.initval;
++ map->prime = tmp.prime;
++ map->hashsize = tmp.hashsize;
++ map->members = tmp.members;
++ write_unlock_bh(&set->lock);
++
++ ip_set_free(members, hashsize * sizeof(ip_set_ip_t));
++
++ return 0;
++}
++
++static inline int
++__delip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
++ ip_set_ip_t *hash_ip)
++{
++ ip_set_ip_t id = hash_id_cidr(map, ip, cidr, hash_ip);
++
++ if (id == UINT_MAX)
++ return -EEXIST;
++
++ map->members[id] = 0;
++ return 0;
++}
++
++static int
++delip(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_nethash *req =
++ (struct ip_set_req_nethash *) data;
++
++ if (size != sizeof(struct ip_set_req_nethash)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_nethash),
++ size);
++ return -EINVAL;
++ }
++ /* TODO: no garbage collection in map->cidr */
++ return __delip((struct ip_set_nethash *) set->data,
++ req->ip, req->cidr, hash_ip);
++}
++
++static int
++delip_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++ int ret = -ERANGE;
++ ip_set_ip_t ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr);
++
++ if (map->cidr[0])
++ ret = __delip(map, ip, map->cidr[0], hash_ip);
++
++ return ret;
++}
++
++static int create(struct ip_set *set, const void *data, size_t size)
++{
++ unsigned newbytes;
++ struct ip_set_req_nethash_create *req =
++ (struct ip_set_req_nethash_create *) data;
++ struct ip_set_nethash *map;
++
++ if (size != sizeof(struct ip_set_req_nethash_create)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_nethash_create),
++ size);
++ return -EINVAL;
++ }
++
++ if (req->hashsize < 1) {
++ ip_set_printk("hashsize too small");
++ return -ENOEXEC;
++ }
++
++ map = kmalloc(sizeof(struct ip_set_nethash), GFP_KERNEL);
++ if (!map) {
++ DP("out of memory for %d bytes",
++ sizeof(struct ip_set_nethash));
++ return -ENOMEM;
++ }
++ get_random_bytes(&map->initval, 4);
++ map->prime = make_prime(req->hashsize);
++ map->hashsize = req->hashsize;
++ map->probes = req->probes;
++ map->resize = req->resize;
++ memset(map->cidr, 0, 30 * sizeof(unsigned char));
++ newbytes = map->hashsize * sizeof(ip_set_ip_t);
++ map->members = ip_set_malloc(newbytes);
++ if (!map->members) {
++ DP("out of memory for %d bytes", newbytes);
++ kfree(map);
++ return -ENOMEM;
++ }
++ memset(map->members, 0, newbytes);
++
++ set->data = map;
++ return 0;
++}
++
++static void destroy(struct ip_set *set)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++
++ ip_set_free(map->members, map->hashsize * sizeof(ip_set_ip_t));
++ kfree(map);
++
++ set->data = NULL;
++}
++
++static void flush(struct ip_set *set)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++ memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
++ memset(map->cidr, 0, 30 * sizeof(unsigned char));
++}
++
++static void list_header(const struct ip_set *set, void *data)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++ struct ip_set_req_nethash_create *header =
++ (struct ip_set_req_nethash_create *) data;
++
++ header->hashsize = map->hashsize;
++ header->probes = map->probes;
++ header->resize = map->resize;
++}
++
++static int list_members_size(const struct ip_set *set)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++
++ return (map->hashsize * sizeof(ip_set_ip_t));
++}
++
++static void list_members(const struct ip_set *set, void *data)
++{
++ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
++ int bytes = map->hashsize * sizeof(ip_set_ip_t);
++
++ memcpy(data, map->members, bytes);
++}
++
++static struct ip_set_type ip_set_nethash = {
++ .typename = SETTYPE_NAME,
++ .typecode = IPSET_TYPE_IP,
++ .protocol_version = IP_SET_PROTOCOL_VERSION,
++ .create = &create,
++ .destroy = &destroy,
++ .flush = &flush,
++ .reqsize = sizeof(struct ip_set_req_nethash),
++ .addip = &addip,
++ .addip_kernel = &addip_kernel,
++ .retry = &retry,
++ .delip = &delip,
++ .delip_kernel = &delip_kernel,
++ .testip = &testip,
++ .testip_kernel = &testip_kernel,
++ .header_size = sizeof(struct ip_set_req_nethash_create),
++ .list_header = &list_header,
++ .list_members_size = &list_members_size,
++ .list_members = &list_members,
++ .me = THIS_MODULE,
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("nethash type of IP sets");
++
++static int __init init(void)
++{
++ return ip_set_register_set_type(&ip_set_nethash);
++}
++
++static void __exit fini(void)
++{
++ /* FIXME: possible race with ip_set_create() */
++ ip_set_unregister_set_type(&ip_set_nethash);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Nur linux-2.6.16/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.16-owrt/net/ipv4/netfilter/ip_set_portmap.c
+--- linux-2.6.16/net/ipv4/netfilter/ip_set_portmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv4/netfilter/ip_set_portmap.c 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,325 @@
++/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* Kernel module implementing a port set type as a bitmap */
++
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/udp.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ip_set.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <linux/spinlock.h>
++
++#include <net/ip.h>
++
++#include <linux/netfilter_ipv4/ip_set_portmap.h>
++
++/* We must handle non-linear skbs */
++static inline ip_set_ip_t
++get_port(const struct sk_buff *skb, u_int32_t flags)
++{
++ struct iphdr *iph = skb->nh.iph;
++ u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
++
++ switch (iph->protocol) {
++ case IPPROTO_TCP: {
++ struct tcphdr tcph;
++
++ /* See comments at tcp_match in ip_tables.c */
++ if (offset)
++ return INVALID_PORT;
++
++ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
++ /* No choice either */
++ return INVALID_PORT;
++
++ return ntohs(flags & IPSET_SRC ?
++ tcph.source : tcph.dest);
++ }
++ case IPPROTO_UDP: {
++ struct udphdr udph;
++
++ if (offset)
++ return INVALID_PORT;
++
++ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0)
++ /* No choice either */
++ return INVALID_PORT;
++
++ return ntohs(flags & IPSET_SRC ?
++ udph.source : udph.dest);
++ }
++ default:
++ return INVALID_PORT;
++ }
++}
++
++static inline int
++__testport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
++{
++ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
++
++ if (port < map->first_port || port > map->last_port)
++ return -ERANGE;
++
++ *hash_port = port;
++ DP("set: %s, port:%u, %u", set->name, port, *hash_port);
++ return !!test_bit(port - map->first_port, map->members);
++}
++
++static int
++testport(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_port)
++{
++ struct ip_set_req_portmap *req =
++ (struct ip_set_req_portmap *) data;
++
++ if (size != sizeof(struct ip_set_req_portmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_portmap),
++ size);
++ return -EINVAL;
++ }
++ return __testport(set, req->port, hash_port);
++}
++
++static int
++testport_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_port)
++{
++ int res;
++ ip_set_ip_t port = get_port(skb, flags);
++
++ DP("flag %s port %u", flags & IPSET_SRC ? "SRC" : "DST", port);
++ if (port == INVALID_PORT)
++ return 0;
++
++ res = __testport(set, port, hash_port);
++
++ return (res < 0 ? 0 : res);
++}
++
++static inline int
++__addport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
++{
++ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
++
++ if (port < map->first_port || port > map->last_port)
++ return -ERANGE;
++ if (test_and_set_bit(port - map->first_port, map->members))
++ return -EEXIST;
++
++ *hash_port = port;
++ DP("port %u", port);
++ return 0;
++}
++
++static int
++addport(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_port)
++{
++ struct ip_set_req_portmap *req =
++ (struct ip_set_req_portmap *) data;
++
++ if (size != sizeof(struct ip_set_req_portmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_portmap),
++ size);
++ return -EINVAL;
++ }
++ return __addport(set, req->port, hash_port);
++}
++
++static int
++addport_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_port)
++{
++ ip_set_ip_t port = get_port(skb, flags);
++
++ if (port == INVALID_PORT)
++ return -EINVAL;
++
++ return __addport(set, port, hash_port);
++}
++
++static inline int
++__delport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
++{
++ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
++
++ if (port < map->first_port || port > map->last_port)
++ return -ERANGE;
++ if (!test_and_clear_bit(port - map->first_port, map->members))
++ return -EEXIST;
++
++ *hash_port = port;
++ DP("port %u", port);
++ return 0;
++}
++
++static int
++delport(struct ip_set *set, const void *data, size_t size,
++ ip_set_ip_t *hash_port)
++{
++ struct ip_set_req_portmap *req =
++ (struct ip_set_req_portmap *) data;
++
++ if (size != sizeof(struct ip_set_req_portmap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_portmap),
++ size);
++ return -EINVAL;
++ }
++ return __delport(set, req->port, hash_port);
++}
++
++static int
++delport_kernel(struct ip_set *set, const struct sk_buff *skb,
++ u_int32_t flags, ip_set_ip_t *hash_port)
++{
++ ip_set_ip_t port = get_port(skb, flags);
++
++ if (port == INVALID_PORT)
++ return -EINVAL;
++
++ return __delport(set, port, hash_port);
++}
++
++static int create(struct ip_set *set, const void *data, size_t size)
++{
++ int newbytes;
++ struct ip_set_req_portmap_create *req =
++ (struct ip_set_req_portmap_create *) data;
++ struct ip_set_portmap *map;
++
++ if (size != sizeof(struct ip_set_req_portmap_create)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)",
++ sizeof(struct ip_set_req_portmap_create),
++ size);
++ return -EINVAL;
++ }
++
++ DP("from %u to %u", req->from, req->to);
++
++ if (req->from > req->to) {
++ DP("bad port range");
++ return -ENOEXEC;
++ }
++
++ if (req->to - req->from > MAX_RANGE) {
++ ip_set_printk("range too big (max %d ports)",
++ MAX_RANGE);
++ return -ENOEXEC;
++ }
++
++ map = kmalloc(sizeof(struct ip_set_portmap), GFP_KERNEL);
++ if (!map) {
++ DP("out of memory for %d bytes",
++ sizeof(struct ip_set_portmap));
++ return -ENOMEM;
++ }
++ map->first_port = req->from;
++ map->last_port = req->to;
++ newbytes = bitmap_bytes(req->from, req->to);
++ map->members = kmalloc(newbytes, GFP_KERNEL);
++ if (!map->members) {
++ DP("out of memory for %d bytes", newbytes);
++ kfree(map);
++ return -ENOMEM;
++ }
++ memset(map->members, 0, newbytes);
++
++ set->data = map;
++ return 0;
++}
++
++static void destroy(struct ip_set *set)
++{
++ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
++
++ kfree(map->members);
++ kfree(map);
++
++ set->data = NULL;
++}
++
++static void flush(struct ip_set *set)
++{
++ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
++ memset(map->members, 0, bitmap_bytes(map->first_port, map->last_port));
++}
++
++static void list_header(const struct ip_set *set, void *data)
++{
++ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
++ struct ip_set_req_portmap_create *header =
++ (struct ip_set_req_portmap_create *) data;
++
++ DP("list_header %u %u", map->first_port, map->last_port);
++
++ header->from = map->first_port;
++ header->to = map->last_port;
++}
++
++static int list_members_size(const struct ip_set *set)
++{
++ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
++
++ return bitmap_bytes(map->first_port, map->last_port);
++}
++
++static void list_members(const struct ip_set *set, void *data)
++{
++ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
++ int bytes = bitmap_bytes(map->first_port, map->last_port);
++
++ memcpy(data, map->members, bytes);
++}
++
++static struct ip_set_type ip_set_portmap = {
++ .typename = SETTYPE_NAME,
++ .typecode = IPSET_TYPE_PORT,
++ .protocol_version = IP_SET_PROTOCOL_VERSION,
++ .create = &create,
++ .destroy = &destroy,
++ .flush = &flush,
++ .reqsize = sizeof(struct ip_set_req_portmap),
++ .addip = &addport,
++ .addip_kernel = &addport_kernel,
++ .delip = &delport,
++ .delip_kernel = &delport_kernel,
++ .testip = &testport,
++ .testip_kernel = &testport_kernel,
++ .header_size = sizeof(struct ip_set_req_portmap_create),
++ .list_header = &list_header,
++ .list_members_size = &list_members_size,
++ .list_members = &list_members,
++ .me = THIS_MODULE,
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("portmap type of IP sets");
++
++static int __init init(void)
++{
++ return ip_set_register_set_type(&ip_set_portmap);
++}
++
++static void __exit fini(void)
++{
++ /* FIXME: possible race with ip_set_create() */
++ ip_set_unregister_set_type(&ip_set_portmap);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Nur linux-2.6.16/net/ipv4/netfilter/ipt_set.c linux-2.6.16-owrt/net/ipv4/netfilter/ipt_set.c
+--- linux-2.6.16/net/ipv4/netfilter/ipt_set.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv4/netfilter/ipt_set.c 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,112 @@
++/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
++ * Patrick Schaaf <bof@bof.de>
++ * Martin Josefsson <gandalf@wlug.westbo.se>
++ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* Kernel module to match an IP set. */
++
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ip_set.h>
++#include <linux/netfilter_ipv4/ipt_set.h>
++
++static inline int
++match_set(const struct ipt_set_info *info,
++ const struct sk_buff *skb,
++ int inv)
++{
++ if (ip_set_testip_kernel(info->index, skb, info->flags))
++ inv = !inv;
++ return inv;
++}
++
++static int
++match(const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *matchinfo,
++ int offset,
++ int *hotdrop)
++{
++ const struct ipt_set_info_match *info = matchinfo;
++
++ return match_set(&info->match_set,
++ skb,
++ info->match_set.flags[0] & IPSET_MATCH_INV);
++}
++
++static int
++checkentry(const char *tablename,
++ const struct ipt_ip *ip,
++ void *matchinfo,
++ unsigned int matchsize,
++ unsigned int hook_mask)
++{
++ struct ipt_set_info_match *info =
++ (struct ipt_set_info_match *) matchinfo;
++ ip_set_id_t index;
++
++ if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) {
++ ip_set_printk("invalid matchsize %d", matchsize);
++ return 0;
++ }
++
++ index = ip_set_get_byindex(info->match_set.index);
++
++ if (index == IP_SET_INVALID_ID) {
++ ip_set_printk("Cannot find set indentified by id %u to match",
++ info->match_set.index);
++ return 0; /* error */
++ }
++ if (info->match_set.flags[IP_SET_MAX_BINDINGS] != 0) {
++ ip_set_printk("That's nasty!");
++ return 0; /* error */
++ }
++
++ return 1;
++}
++
++static void destroy(void *matchinfo, unsigned int matchsize)
++{
++ struct ipt_set_info_match *info = matchinfo;
++
++ if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) {
++ ip_set_printk("invalid matchsize %d", matchsize);
++ return;
++ }
++
++ ip_set_put(info->match_set.index);
++}
++
++static struct ipt_match set_match = {
++ .name = "set",
++ .match = &match,
++ .checkentry = &checkentry,
++ .destroy = &destroy,
++ .me = THIS_MODULE
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("iptables IP set match module");
++
++static int __init init(void)
++{
++ return ipt_register_match(&set_match);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_match(&set_match);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Nur linux-2.6.16/net/ipv4/netfilter/ipt_SET.c linux-2.6.16-owrt/net/ipv4/netfilter/ipt_SET.c
+--- linux-2.6.16/net/ipv4/netfilter/ipt_SET.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv4/netfilter/ipt_SET.c 2006-03-20 12:53:59.000000000 +0100
+@@ -0,0 +1,128 @@
++/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
++ * Patrick Schaaf <bof@bof.de>
++ * Martin Josefsson <gandalf@wlug.westbo.se>
++ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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.
++ */
++
++/* ipt_SET.c - netfilter target to manipulate IP sets */
++
++#include <linux/types.h>
++#include <linux/ip.h>
++#include <linux/timer.h>
++#include <linux/module.h>
++#include <linux/netfilter.h>
++#include <linux/netdevice.h>
++#include <linux/if.h>
++#include <linux/inetdevice.h>
++#include <net/protocol.h>
++#include <net/checksum.h>
++#include <linux/netfilter_ipv4.h>
++#include <linux/netfilter_ipv4/ip_nat_rule.h>
++#include <linux/netfilter_ipv4/ipt_set.h>
++
++static unsigned int
++target(struct sk_buff **pskb,
++ const struct net_device *in,
++ const struct net_device *out,
++ unsigned int hooknum,
++ const void *targinfo,
++ void *userinfo)
++{
++ const struct ipt_set_info_target *info = targinfo;
++
++ if (info->add_set.index != IP_SET_INVALID_ID)
++ ip_set_addip_kernel(info->add_set.index,
++ *pskb,
++ info->add_set.flags);
++ if (info->del_set.index != IP_SET_INVALID_ID)
++ ip_set_delip_kernel(info->del_set.index,
++ *pskb,
++ info->del_set.flags);
++
++ return IPT_CONTINUE;
++}
++
++static int
++checkentry(const char *tablename,
++ const struct ipt_entry *e,
++ void *targinfo,
++ unsigned int targinfosize, unsigned int hook_mask)
++{
++ struct ipt_set_info_target *info =
++ (struct ipt_set_info_target *) targinfo;
++ ip_set_id_t index;
++
++ if (targinfosize != IPT_ALIGN(sizeof(*info))) {
++ DP("bad target info size %u", targinfosize);
++ return 0;
++ }
++
++ if (info->add_set.index != IP_SET_INVALID_ID) {
++ index = ip_set_get_byindex(info->add_set.index);
++ if (index == IP_SET_INVALID_ID) {
++ ip_set_printk("cannot find add_set index %u as target",
++ info->add_set.index);
++ return 0; /* error */
++ }
++ }
++
++ if (info->del_set.index != IP_SET_INVALID_ID) {
++ index = ip_set_get_byindex(info->del_set.index);
++ if (index == IP_SET_INVALID_ID) {
++ ip_set_printk("cannot find del_set index %u as target",
++ info->del_set.index);
++ return 0; /* error */
++ }
++ }
++ if (info->add_set.flags[IP_SET_MAX_BINDINGS] != 0
++ || info->del_set.flags[IP_SET_MAX_BINDINGS] != 0) {
++ ip_set_printk("That's nasty!");
++ return 0; /* error */
++ }
++
++ return 1;
++}
++
++static void destroy(void *targetinfo, unsigned int targetsize)
++{
++ struct ipt_set_info_target *info = targetinfo;
++
++ if (targetsize != IPT_ALIGN(sizeof(struct ipt_set_info_target))) {
++ ip_set_printk("invalid targetsize %d", targetsize);
++ return;
++ }
++
++ if (info->add_set.index != IP_SET_INVALID_ID)
++ ip_set_put(info->add_set.index);
++ if (info->del_set.index != IP_SET_INVALID_ID)
++ ip_set_put(info->del_set.index);
++}
++
++static struct ipt_target SET_target = {
++ .name = "SET",
++ .target = target,
++ .checkentry = checkentry,
++ .destroy = destroy,
++ .me = THIS_MODULE
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
++MODULE_DESCRIPTION("iptables IP set target module");
++
++static int __init init(void)
++{
++ return ipt_register_target(&SET_target);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_target(&SET_target);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Nur linux-2.6.16/net/ipv4/netfilter/Kconfig linux-2.6.16-owrt/net/ipv4/netfilter/Kconfig
+--- linux-2.6.16/net/ipv4/netfilter/Kconfig 2006-03-20 12:52:42.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv4/netfilter/Kconfig 2006-03-20 12:53:59.000000000 +0100
+@@ -623,5 +623,106 @@
+ Allows altering the ARP packet payload: source and destination
+ hardware and network addresses.
+
++config IP_NF_SET
++ tristate "IP set support"
++ depends on INET && NETFILTER
++ help
++ This option adds IP set support to the kernel.
++ In order to define and use sets, you need the userspace utility
++ ipset(8).
++
++ To compile it as a module, choose M here. If unsure, say N.
++
++config IP_NF_SET_MAX
++ int "Maximum number of IP sets"
++ default 256
++ range 2 65534
++ depends on IP_NF_SET
++ help
++ You can define here default value of the maximum number
++ of IP sets for the kernel.
++
++ The value can be overriden by the 'max_sets' module
++ parameter of the 'ip_set' module.
++
++config IP_NF_SET_HASHSIZE
++ int "Hash size for bindings of IP sets"
++ default 1024
++ depends on IP_NF_SET
++ help
++ You can define here default value of the hash size for
++ bindings of IP sets.
++
++ The value can be overriden by the 'hash_size' module
++ parameter of the 'ip_set' module.
++
++config IP_NF_SET_IPMAP
++ tristate "ipmap set support"
++ depends on IP_NF_SET
++ help
++ This option adds the ipmap set type support.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
++config IP_NF_SET_MACIPMAP
++ tristate "macipmap set support"
++ depends on IP_NF_SET
++ help
++ This option adds the macipmap set type support.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
++config IP_NF_SET_PORTMAP
++ tristate "portmap set support"
++ depends on IP_NF_SET
++ help
++ This option adds the portmap set type support.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
++config IP_NF_SET_IPHASH
++ tristate "iphash set support"
++ depends on IP_NF_SET
++ help
++ This option adds the iphash set type support.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
++config IP_NF_SET_NETHASH
++ tristate "nethash set support"
++ depends on IP_NF_SET
++ help
++ This option adds the nethash set type support.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
++config IP_NF_SET_IPTREE
++ tristate "iptree set support"
++ depends on IP_NF_SET
++ help
++ This option adds the iptree set type support.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
++config IP_NF_MATCH_SET
++ tristate "set match support"
++ depends on IP_NF_SET
++ help
++ Set matching matches against given IP sets.
++ You need the ipset utility to create and set up the sets.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
++config IP_NF_TARGET_SET
++ tristate "SET target support"
++ depends on IP_NF_SET
++ help
++ The SET target makes possible to add/delete entries
++ in IP sets.
++ You need the ipset utility to create and set up the sets.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
++
+ endmenu
+
+diff -Nur linux-2.6.16/net/ipv4/netfilter/Makefile linux-2.6.16-owrt/net/ipv4/netfilter/Makefile
+--- linux-2.6.16/net/ipv4/netfilter/Makefile 2006-03-20 12:52:42.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv4/netfilter/Makefile 2006-03-20 12:56:30.000000000 +0100
+@@ -47,6 +47,7 @@
+
+ # matches
+ obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o
++obj-$(CONFIG_IP_NF_MATCH_SET) += ipt_set.o
+ obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
+ obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
+ obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
+@@ -74,6 +75,17 @@
+ obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
+ obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
+ obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
++obj-$(CONFIG_IP_NF_TARGET_SET) += ipt_SET.o
++
++# sets
++obj-$(CONFIG_IP_NF_SET) += ip_set.o
++obj-$(CONFIG_IP_NF_SET_IPMAP) += ip_set_ipmap.o
++obj-$(CONFIG_IP_NF_SET_PORTMAP) += ip_set_portmap.o
++obj-$(CONFIG_IP_NF_SET_MACIPMAP) += ip_set_macipmap.o
++obj-$(CONFIG_IP_NF_SET_IPHASH) += ip_set_iphash.o
++obj-$(CONFIG_IP_NF_SET_NETHASH) += ip_set_nethash.o
++obj-$(CONFIG_IP_NF_SET_IPTREE) += ip_set_iptree.o
++
+ obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
+ obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
+
diff --git a/target/linux/generic-2.6/patches/105-netfilter_time.patch b/target/linux/generic-2.6/patches/105-netfilter_time.patch
new file mode 100644
index 0000000000..34257ee93c
--- /dev/null
+++ b/target/linux/generic-2.6/patches/105-netfilter_time.patch
@@ -0,0 +1,241 @@
+diff -urN linux-2.6.15-rc6.orig/net/ipv4/netfilter/ipt_time.c linux-2.6.15-rc6/net/ipv4/netfilter/ipt_time.c
+--- linux-2.6.15-rc6.orig/net/ipv4/netfilter/ipt_time.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-rc6/net/ipv4/netfilter/ipt_time.c 2006-01-07 13:02:59.000000000 +0100
+@@ -0,0 +1,178 @@
++/*
++ This is a module which is used for time matching
++ It is using some modified code from dietlibc (localtime() function)
++ that you can find at http://www.fefe.de/dietlibc/
++ This file is distributed under the terms of the GNU General Public
++ License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
++ 2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
++ 2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
++ thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
++ 2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
++ 2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
++ added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
++ 2004-05-02 Fabrice : added support for date matching, from an idea of Fabien COELHO.
++*/
++
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_time.h>
++#include <linux/time.h>
++
++MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
++MODULE_DESCRIPTION("Match arrival timestamp/date");
++MODULE_LICENSE("GPL");
++
++struct tm
++{
++ int tm_sec; /* Seconds. [0-60] (1 leap second) */
++ int tm_min; /* Minutes. [0-59] */
++ int tm_hour; /* Hours. [0-23] */
++ int tm_mday; /* Day. [1-31] */
++ int tm_mon; /* Month. [0-11] */
++ int tm_year; /* Year - 1900. */
++ int tm_wday; /* Day of week. [0-6] */
++ int tm_yday; /* Days in year.[0-365] */
++ int tm_isdst; /* DST. [-1/0/1]*/
++
++ long int tm_gmtoff; /* we don't care, we count from GMT */
++ const char *tm_zone; /* we don't care, we count from GMT */
++};
++
++void
++localtime(const u32 time, struct tm *r);
++
++static int
++match(const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *matchinfo,
++ int offset,
++ int *hotdrop)
++{
++ const struct ipt_time_info *info = matchinfo; /* match info for rule */
++ struct tm currenttime; /* time human readable */
++ u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
++ u_int16_t packet_time;
++
++ /* We might not have a timestamp, get one */
++ if (skb->tstamp.off_sec == 0)
++ __net_timestamp((struct sk_buff *)skb);
++
++ /* First we make sure we are in the date start-stop boundaries */
++ if ((skb->tstamp.off_sec < info->date_start) || (skb->tstamp.off_sec > info->date_stop))
++ return 0; /* We are outside the date boundaries */
++
++ /* Transform the timestamp of the packet, in a human readable form */
++ localtime(skb->tstamp.off_sec, &currenttime);
++
++ /* check if we match this timestamp, we start by the days... */
++ if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
++ return 0; /* the day doesn't match */
++
++ /* ... check the time now */
++ packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
++ if ((packet_time < info->time_start) || (packet_time > info->time_stop))
++ return 0;
++
++ /* here we match ! */
++ return 1;
++}
++
++static int
++checkentry(const char *tablename,
++ const struct ipt_ip *ip,
++ void *matchinfo,
++ unsigned int matchsize,
++ unsigned int hook_mask)
++{
++ struct ipt_time_info *info = matchinfo; /* match info for rule */
++
++ /* First, check that we are in the correct hooks */
++ if (hook_mask
++ & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
++ {
++ printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
++ return 0;
++ }
++
++ /* Check the size */
++ if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
++ return 0;
++ /* Now check the coherence of the data ... */
++ if ((info->time_start > 1439) || /* 23*60+59 = 1439*/
++ (info->time_stop > 1439))
++ {
++ printk(KERN_WARNING "ipt_time: invalid argument\n");
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct ipt_match time_match = {
++ .name = "time",
++ .match = &match,
++ .checkentry = &checkentry,
++ .me = THIS_MODULE
++};
++
++static int __init init(void)
++{
++ printk("ipt_time loading\n");
++ return ipt_register_match(&time_match);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_match(&time_match);
++ printk("ipt_time unloaded\n");
++}
++
++module_init(init);
++module_exit(fini);
++
++
++/* The part below is borowed and modified from dietlibc */
++
++/* seconds per day */
++#define SPD 24*60*60
++
++void
++localtime(const u32 time, struct tm *r) {
++ u32 i, timep;
++ extern struct timezone sys_tz;
++ const unsigned int __spm[12] =
++ { 0,
++ (31),
++ (31+28),
++ (31+28+31),
++ (31+28+31+30),
++ (31+28+31+30+31),
++ (31+28+31+30+31+30),
++ (31+28+31+30+31+30+31),
++ (31+28+31+30+31+30+31+31),
++ (31+28+31+30+31+30+31+31+30),
++ (31+28+31+30+31+30+31+31+30+31),
++ (31+28+31+30+31+30+31+31+30+31+30),
++ };
++ register u32 work;
++
++ timep = time - (sys_tz.tz_minuteswest * 60);
++ work=timep%(SPD);
++ r->tm_sec=work%60; work/=60;
++ r->tm_min=work%60; r->tm_hour=work/60;
++ work=timep/(SPD);
++ r->tm_wday=(4+work)%7;
++ for (i=1970; ; ++i) {
++ register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
++ if (work>k)
++ work-=k;
++ else
++ break;
++ }
++ r->tm_year=i-1900;
++ for (i=11; i && __spm[i]>work; --i) ;
++ r->tm_mon=i;
++ r->tm_mday=work-__spm[i]+1;
++}
+diff -urN linux-2.6.15-rc6.orig/net/ipv4/netfilter/Kconfig linux-2.6.15-rc6/net/ipv4/netfilter/Kconfig
+--- linux-2.6.15-rc6.orig/net/ipv4/netfilter/Kconfig 2006-01-07 13:00:21.000000000 +0100
++++ linux-2.6.15-rc6/net/ipv4/netfilter/Kconfig 2006-01-07 13:05:07.000000000 +0100
+@@ -278,6 +278,22 @@
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++
++config IP_NF_MATCH_TIME
++ tristate 'TIME match support'
++ depends on IP_NF_IPTABLES
++ help
++ This option adds a `time' match, which allows you
++ to match based on the packet arrival time/date
++ (arrival time/date at the machine which netfilter is running on) or
++ departure time/date (for locally generated packets).
++
++ If you say Y here, try iptables -m time --help for more information.
++ If you want to compile it as a module, say M here and read
++
++ Documentation/modules.txt. If unsure, say `N'.
++
++
+ config IP_NF_MATCH_RECENT
+ tristate "recent match support"
+ depends on IP_NF_IPTABLES
+diff -urN linux-2.6.15-rc6.orig/net/ipv4/netfilter/Makefile linux-2.6.15-rc6/net/ipv4/netfilter/Makefile
+--- linux-2.6.15-rc6.orig/net/ipv4/netfilter/Makefile 2006-01-07 13:00:21.000000000 +0100
++++ linux-2.6.15-rc6/net/ipv4/netfilter/Makefile 2006-01-07 13:03:50.000000000 +0100
+@@ -58,6 +58,7 @@
+ obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
+ obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
+ obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
++obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
+ obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
+ obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
+ obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
+diff -urN linux-2.6.15-rc6.orig/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.15-rc6/include/linux/netfilter_ipv4/ipt_time.h
+--- linux-2.6.15-rc6.orig/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-rc6/include/linux/netfilter_ipv4/ipt_time.h 2006-01-07 13:02:14.000000000 +0100
+@@ -0,0 +1,18 @@
++#ifndef __ipt_time_h_included__
++#define __ipt_time_h_included__
++
++
++struct ipt_time_info {
++ u_int8_t days_match; /* 1 bit per day. -SMTWTFS */
++ u_int16_t time_start; /* 0 < time_start < 23*60+59 = 1439 */
++ u_int16_t time_stop; /* 0:0 < time_stat < 23:59 */
++
++ /* FIXME: Keep this one for userspace iptables binary compability: */
++ u_int8_t kerneltime; /* ignore skb time (and use kerneltime) or not. */
++
++ time_t date_start;
++ time_t date_stop;
++};
++
++
++#endif /* __ipt_time_h_included__ */
diff --git a/target/linux/generic-2.6/patches/106-netfilter_imq.patch b/target/linux/generic-2.6/patches/106-netfilter_imq.patch
new file mode 100644
index 0000000000..8114db621b
--- /dev/null
+++ b/target/linux/generic-2.6/patches/106-netfilter_imq.patch
@@ -0,0 +1,885 @@
+diff -Nur linux-2.6.16/drivers/net/imq.c linux-2.6.16-owrt/drivers/net/imq.c
+--- linux-2.6.16/drivers/net/imq.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/drivers/net/imq.c 2006-03-20 12:59:23.000000000 +0100
+@@ -0,0 +1,403 @@
++/*
++ * Pseudo-driver for the intermediate queue device.
++ *
++ * 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: Patrick McHardy, <kaber@trash.net>
++ *
++ * The first version was written by Martin Devera, <devik@cdi.cz>
++ *
++ * Credits: Jan Rafaj <imq2t@cedric.vabo.cz>
++ * - Update patch to 2.4.21
++ * Sebastian Strollo <sstrollo@nortelnetworks.com>
++ * - Fix "Dead-loop on netdevice imq"-issue
++ * Marcel Sebek <sebek64@post.cz>
++ * - Update to 2.6.2-rc1
++ *
++ * After some time of inactivity there is a group taking care
++ * of IMQ again: http://www.linuximq.net
++ *
++ *
++ * 2004/06/30 - New version of IMQ patch to kernels <=2.6.7 including
++ * the following changes:
++ *
++ * - Correction of ipv6 support "+"s issue (Hasso Tepper)
++ * - Correction of imq_init_devs() issue that resulted in
++ * kernel OOPS unloading IMQ as module (Norbert Buchmuller)
++ * - Addition of functionality to choose number of IMQ devices
++ * during kernel config (Andre Correa)
++ * - Addition of functionality to choose how IMQ hooks on
++ * PRE and POSTROUTING (after or before NAT) (Andre Correa)
++ * - Cosmetic corrections (Norbert Buchmuller) (Andre Correa)
++ *
++ *
++ * 2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were
++ * released with almost no problems. 2.6.14-x was released
++ * with some important changes: nfcache was removed; After
++ * some weeks of trouble we figured out that some IMQ fields
++ * in skb were missing in skbuff.c - skb_clone and copy_skb_header.
++ * These functions are correctly patched by this new patch version.
++ *
++ * Thanks for all who helped to figure out all the problems with
++ * 2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX,
++ * Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully
++ * I didn't forget anybody). I apologize again for my lack of time.
++ *
++ * More info at: http://www.linuximq.net/ (Andre Correa)
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/moduleparam.h>
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++#include <linux/rtnetlink.h>
++#include <linux/if_arp.h>
++#include <linux/netfilter.h>
++#include <linux/netfilter_ipv4.h>
++#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
++ #include <linux/netfilter_ipv6.h>
++#endif
++#include <linux/imq.h>
++#include <net/pkt_sched.h>
++
++static nf_hookfn imq_nf_hook;
++
++static struct nf_hook_ops imq_ingress_ipv4 = {
++ .hook = imq_nf_hook,
++ .owner = THIS_MODULE,
++ .pf = PF_INET,
++ .hooknum = NF_IP_PRE_ROUTING,
++#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
++ .priority = NF_IP_PRI_MANGLE + 1
++#else
++ .priority = NF_IP_PRI_NAT_DST + 1
++#endif
++};
++
++static struct nf_hook_ops imq_egress_ipv4 = {
++ .hook = imq_nf_hook,
++ .owner = THIS_MODULE,
++ .pf = PF_INET,
++ .hooknum = NF_IP_POST_ROUTING,
++#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
++ .priority = NF_IP_PRI_LAST
++#else
++ .priority = NF_IP_PRI_NAT_SRC - 1
++#endif
++};
++
++#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
++static struct nf_hook_ops imq_ingress_ipv6 = {
++ .hook = imq_nf_hook,
++ .owner = THIS_MODULE,
++ .pf = PF_INET6,
++ .hooknum = NF_IP6_PRE_ROUTING,
++#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
++ .priority = NF_IP6_PRI_MANGLE + 1
++#else
++ .priority = NF_IP6_PRI_NAT_DST + 1
++#endif
++};
++
++static struct nf_hook_ops imq_egress_ipv6 = {
++ .hook = imq_nf_hook,
++ .owner = THIS_MODULE,
++ .pf = PF_INET6,
++ .hooknum = NF_IP6_POST_ROUTING,
++#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
++ .priority = NF_IP6_PRI_LAST
++#else
++ .priority = NF_IP6_PRI_NAT_SRC - 1
++#endif
++};
++#endif
++
++#if defined(CONFIG_IMQ_NUM_DEVS)
++static unsigned int numdevs = CONFIG_IMQ_NUM_DEVS;
++#else
++static unsigned int numdevs = 2;
++#endif
++
++static struct net_device *imq_devs;
++
++static struct net_device_stats *imq_get_stats(struct net_device *dev)
++{
++ return (struct net_device_stats *)dev->priv;
++}
++
++/* called for packets kfree'd in qdiscs at places other than enqueue */
++static void imq_skb_destructor(struct sk_buff *skb)
++{
++ struct nf_info *info = skb->nf_info;
++
++ if (info) {
++ if (info->indev)
++ dev_put(info->indev);
++ if (info->outdev)
++ dev_put(info->outdev);
++ kfree(info);
++ }
++}
++
++static int imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
++
++ stats->tx_bytes += skb->len;
++ stats->tx_packets++;
++
++ skb->imq_flags = 0;
++ skb->destructor = NULL;
++
++ dev->trans_start = jiffies;
++ nf_reinject(skb, skb->nf_info, NF_ACCEPT);
++ return 0;
++}
++
++static int imq_nf_queue(struct sk_buff *skb, struct nf_info *info, unsigned queue_num, void *data)
++{
++ struct net_device *dev;
++ struct net_device_stats *stats;
++ struct sk_buff *skb2 = NULL;
++ struct Qdisc *q;
++ unsigned int index = skb->imq_flags&IMQ_F_IFMASK;
++ int ret = -1;
++
++ if (index > numdevs)
++ return -1;
++
++ dev = imq_devs + index;
++ if (!(dev->flags & IFF_UP)) {
++ skb->imq_flags = 0;
++ nf_reinject(skb, info, NF_ACCEPT);
++ return 0;
++ }
++ dev->last_rx = jiffies;
++
++ if (skb->destructor) {
++ skb2 = skb;
++ skb = skb_clone(skb, GFP_ATOMIC);
++ if (!skb)
++ return -1;
++ }
++ skb->nf_info = info;
++
++ stats = (struct net_device_stats *)dev->priv;
++ stats->rx_bytes+= skb->len;
++ stats->rx_packets++;
++
++ spin_lock_bh(&dev->queue_lock);
++ q = dev->qdisc;
++ if (q->enqueue) {
++ q->enqueue(skb_get(skb), q);
++ if (skb_shared(skb)) {
++ skb->destructor = imq_skb_destructor;
++ kfree_skb(skb);
++ ret = 0;
++ }
++ }
++ if (spin_is_locked(&dev->xmit_lock))
++ netif_schedule(dev);
++ else
++
++ while (!netif_queue_stopped(dev) &&
++ qdisc_restart(dev)<0)
++ /* NOTHING */;
++
++ spin_unlock_bh(&dev->queue_lock);
++
++ if (skb2)
++ kfree_skb(ret ? skb : skb2);
++
++ return ret;
++}
++
++static struct nf_queue_handler nfqh = {
++ .name = "imq",
++ .outfn = imq_nf_queue,
++};
++
++static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff **pskb,
++ const struct net_device *indev,
++ const struct net_device *outdev,
++ int (*okfn)(struct sk_buff *))
++{
++ if ((*pskb)->imq_flags & IMQ_F_ENQUEUE)
++ return NF_QUEUE;
++
++ return NF_ACCEPT;
++}
++
++
++static int __init imq_init_hooks(void)
++{
++ int err;
++
++ err = nf_register_queue_handler(PF_INET, &nfqh);
++ if (err > 0)
++ goto err1;
++ if ((err = nf_register_hook(&imq_ingress_ipv4)))
++ goto err2;
++ if ((err = nf_register_hook(&imq_egress_ipv4)))
++ goto err3;
++#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
++ if ((err = nf_register_queue_handler(PF_INET6, &nfqh)))
++ goto err4;
++ if ((err = nf_register_hook(&imq_ingress_ipv6)))
++ goto err5;
++ if ((err = nf_register_hook(&imq_egress_ipv6)))
++ goto err6;
++#endif
++
++ return 0;
++
++#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
++err6:
++ nf_unregister_hook(&imq_ingress_ipv6);
++err5:
++ nf_unregister_queue_handler(PF_INET6);
++err4:
++ nf_unregister_hook(&imq_egress_ipv6);
++#endif
++err3:
++ nf_unregister_hook(&imq_ingress_ipv4);
++err2:
++ nf_unregister_queue_handler(PF_INET);
++err1:
++ return err;
++}
++
++static void __exit imq_unhook(void)
++{
++ nf_unregister_hook(&imq_ingress_ipv4);
++ nf_unregister_hook(&imq_egress_ipv4);
++ nf_unregister_queue_handler(PF_INET);
++#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
++ nf_unregister_hook(&imq_ingress_ipv6);
++ nf_unregister_hook(&imq_egress_ipv6);
++ nf_unregister_queue_handler(PF_INET6);
++#endif
++}
++
++static int __init imq_dev_init(struct net_device *dev)
++{
++ dev->hard_start_xmit = imq_dev_xmit;
++ dev->type = ARPHRD_VOID;
++ dev->mtu = 1500;
++ dev->tx_queue_len = 30;
++ dev->flags = IFF_NOARP;
++ dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
++ if (dev->priv == NULL)
++ return -ENOMEM;
++ memset(dev->priv, 0, sizeof(struct net_device_stats));
++ dev->get_stats = imq_get_stats;
++
++ return 0;
++}
++
++static void imq_dev_uninit(struct net_device *dev)
++{
++ kfree(dev->priv);
++}
++
++static int __init imq_init_devs(void)
++{
++ struct net_device *dev;
++ int i,j;
++ j = numdevs;
++
++ if (!numdevs || numdevs > IMQ_MAX_DEVS) {
++ printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n",
++ IMQ_MAX_DEVS);
++ return -EINVAL;
++ }
++
++ imq_devs = kmalloc(sizeof(struct net_device) * numdevs, GFP_KERNEL);
++ if (!imq_devs)
++ return -ENOMEM;
++ memset(imq_devs, 0, sizeof(struct net_device) * numdevs);
++
++ /* we start counting at zero */
++ numdevs--;
++
++ for (i = 0, dev = imq_devs; i <= numdevs; i++, dev++) {
++ SET_MODULE_OWNER(dev);
++ strcpy(dev->name, "imq%d");
++ dev->init = imq_dev_init;
++ dev->uninit = imq_dev_uninit;
++
++ if (register_netdev(dev) < 0)
++ goto err_register;
++ }
++ printk(KERN_INFO "IMQ starting with %u devices...\n", j);
++ return 0;
++
++err_register:
++ for (; i; i--)
++ unregister_netdev(--dev);
++ kfree(imq_devs);
++ return -EIO;
++}
++
++static void imq_cleanup_devs(void)
++{
++ int i;
++ struct net_device *dev = imq_devs;
++
++ for (i = 0; i <= numdevs; i++)
++ unregister_netdev(dev++);
++
++ kfree(imq_devs);
++}
++
++static int __init imq_init_module(void)
++{
++ int err;
++
++ if ((err = imq_init_devs())) {
++ printk(KERN_ERR "IMQ: Error trying imq_init_devs()\n");
++ return err;
++ }
++ if ((err = imq_init_hooks())) {
++ printk(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
++ imq_cleanup_devs();
++ return err;
++ }
++
++ printk(KERN_INFO "IMQ driver loaded successfully.\n");
++
++#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
++ printk(KERN_INFO "\tHooking IMQ before NAT on PREROUTING.\n");
++#else
++ printk(KERN_INFO "\tHooking IMQ after NAT on PREROUTING.\n");
++#endif
++#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
++ printk(KERN_INFO "\tHooking IMQ before NAT on POSTROUTING.\n");
++#else
++ printk(KERN_INFO "\tHooking IMQ after NAT on POSTROUTING.\n");
++#endif
++
++ return 0;
++}
++
++static void __exit imq_cleanup_module(void)
++{
++ imq_unhook();
++ imq_cleanup_devs();
++ printk(KERN_INFO "IMQ driver unloaded successfully.\n");
++}
++
++
++module_init(imq_init_module);
++module_exit(imq_cleanup_module);
++
++module_param(numdevs, int, 0);
++MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will be created)");
++MODULE_AUTHOR("http://www.linuximq.net");
++MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
++MODULE_LICENSE("GPL");
+diff -Nur linux-2.6.16/drivers/net/Kconfig linux-2.6.16-owrt/drivers/net/Kconfig
+--- linux-2.6.16/drivers/net/Kconfig 2006-03-20 06:53:29.000000000 +0100
++++ linux-2.6.16-owrt/drivers/net/Kconfig 2006-03-20 12:59:23.000000000 +0100
+@@ -93,6 +93,129 @@
+ To compile this driver as a module, choose M here: the module
+ will be called eql. If unsure, say N.
+
++config IMQ
++ tristate "IMQ (intermediate queueing device) support"
++ depends on NETDEVICES && NETFILTER
++ ---help---
++ The IMQ device(s) is used as placeholder for QoS queueing disciplines.
++ Every packet entering/leaving the IP stack can be directed through
++ the IMQ device where it's enqueued/dequeued to the attached qdisc.
++ This allows you to treat network devices as classes and distribute
++ bandwidth among them. Iptables is used to specify through which IMQ
++ device, if any, packets travel.
++
++ More information at: http://www.linuximq.net/
++
++ To compile this driver as a module, choose M here: the module
++ will be called imq. If unsure, say N.
++
++choice
++ prompt "IMQ behavior (PRE/POSTROUTING)"
++ depends on IMQ
++ default IMQ_BEHAVIOR_BA
++ help
++
++ This settings defines how IMQ behaves in respect to its
++ hooking in PREROUTING and POSTROUTING.
++
++ IMQ can work in any of the following ways:
++
++ PREROUTING | POSTROUTING
++ -----------------|-------------------
++ #1 After NAT | After NAT
++ #2 After NAT | Before NAT
++ #3 Before NAT | After NAT
++ #4 Before NAT | Before NAT
++
++ The default behavior is to hook before NAT on PREROUTING
++ and after NAT on POSTROUTING (#3).
++
++ This settings are specially usefull when trying to use IMQ
++ to shape NATed clients.
++
++ More information can be found at: www.linuximq.net
++
++ If not sure leave the default settings alone.
++
++config IMQ_BEHAVIOR_AA
++ bool "IMQ AA"
++ help
++ This settings defines how IMQ behaves in respect to its
++ hooking in PREROUTING and POSTROUTING.
++
++ Choosing this option will make IMQ hook like this:
++
++ PREROUTING: After NAT
++ POSTROUTING: After NAT
++
++ More information can be found at: www.linuximq.net
++
++ If not sure leave the default settings alone.
++
++config IMQ_BEHAVIOR_AB
++ bool "IMQ AB"
++ help
++ This settings defines how IMQ behaves in respect to its
++ hooking in PREROUTING and POSTROUTING.
++
++ Choosing this option will make IMQ hook like this:
++
++ PREROUTING: After NAT
++ POSTROUTING: Before NAT
++
++ More information can be found at: www.linuximq.net
++
++ If not sure leave the default settings alone.
++
++config IMQ_BEHAVIOR_BA
++ bool "IMQ BA"
++ help
++ This settings defines how IMQ behaves in respect to its
++ hooking in PREROUTING and POSTROUTING.
++
++ Choosing this option will make IMQ hook like this:
++
++ PREROUTING: Before NAT
++ POSTROUTING: After NAT
++
++ More information can be found at: www.linuximq.net
++
++ If not sure leave the default settings alone.
++
++config IMQ_BEHAVIOR_BB
++ bool "IMQ BB"
++ help
++ This settings defines how IMQ behaves in respect to its
++ hooking in PREROUTING and POSTROUTING.
++
++ Choosing this option will make IMQ hook like this:
++
++ PREROUTING: Before NAT
++ POSTROUTING: Before NAT
++
++ More information can be found at: www.linuximq.net
++
++ If not sure leave the default settings alone.
++
++endchoice
++
++config IMQ_NUM_DEVS
++
++ int "Number of IMQ devices"
++ range 2 8
++ depends on IMQ
++ default "2"
++ help
++
++ This settings defines how many IMQ devices will be
++ created.
++
++ The default value is 2.
++
++ More information can be found at: www.linuximq.net
++
++ If not sure leave the default settings alone.
++
+ config TUN
+ tristate "Universal TUN/TAP device driver support"
+ select CRC32
+diff -Nur linux-2.6.16/drivers/net/Makefile linux-2.6.16-owrt/drivers/net/Makefile
+--- linux-2.6.16/drivers/net/Makefile 2006-03-20 06:53:29.000000000 +0100
++++ linux-2.6.16-owrt/drivers/net/Makefile 2006-03-20 13:00:13.000000000 +0100
+@@ -125,6 +125,7 @@
+ endif
+
+ obj-$(CONFIG_DUMMY) += dummy.o
++obj-$(CONFIG_IMQ) += imq.o
+ obj-$(CONFIG_IFB) += ifb.o
+ obj-$(CONFIG_DE600) += de600.o
+ obj-$(CONFIG_DE620) += de620.o
+diff -Nur linux-2.6.16/include/linux/imq.h linux-2.6.16-owrt/include/linux/imq.h
+--- linux-2.6.16/include/linux/imq.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/include/linux/imq.h 2006-03-20 12:59:23.000000000 +0100
+@@ -0,0 +1,9 @@
++#ifndef _IMQ_H
++#define _IMQ_H
++
++#define IMQ_MAX_DEVS 16
++
++#define IMQ_F_IFMASK 0x7f
++#define IMQ_F_ENQUEUE 0x80
++
++#endif /* _IMQ_H */
+diff -Nur linux-2.6.16/include/linux/netfilter_ipv4/ipt_IMQ.h linux-2.6.16-owrt/include/linux/netfilter_ipv4/ipt_IMQ.h
+--- linux-2.6.16/include/linux/netfilter_ipv4/ipt_IMQ.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/include/linux/netfilter_ipv4/ipt_IMQ.h 2006-03-20 12:59:23.000000000 +0100
+@@ -0,0 +1,8 @@
++#ifndef _IPT_IMQ_H
++#define _IPT_IMQ_H
++
++struct ipt_imq_info {
++ unsigned int todev; /* target imq device */
++};
++
++#endif /* _IPT_IMQ_H */
+diff -Nur linux-2.6.16/include/linux/netfilter_ipv6/ip6t_IMQ.h linux-2.6.16-owrt/include/linux/netfilter_ipv6/ip6t_IMQ.h
+--- linux-2.6.16/include/linux/netfilter_ipv6/ip6t_IMQ.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/include/linux/netfilter_ipv6/ip6t_IMQ.h 2006-03-20 12:59:23.000000000 +0100
+@@ -0,0 +1,8 @@
++#ifndef _IP6T_IMQ_H
++#define _IP6T_IMQ_H
++
++struct ip6t_imq_info {
++ unsigned int todev; /* target imq device */
++};
++
++#endif /* _IP6T_IMQ_H */
+diff -Nur linux-2.6.16/include/linux/skbuff.h linux-2.6.16-owrt/include/linux/skbuff.h
+--- linux-2.6.16/include/linux/skbuff.h 2006-03-20 06:53:29.000000000 +0100
++++ linux-2.6.16-owrt/include/linux/skbuff.h 2006-03-20 12:59:23.000000000 +0100
+@@ -275,6 +275,10 @@
+ #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+ struct sk_buff *nfct_reasm;
+ #endif
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++ unsigned char imq_flags;
++ struct nf_info *nf_info;
++#endif
+ #ifdef CONFIG_BRIDGE_NETFILTER
+ struct nf_bridge_info *nf_bridge;
+ #endif
+diff -Nur linux-2.6.16/net/core/skbuff.c linux-2.6.16-owrt/net/core/skbuff.c
+--- linux-2.6.16/net/core/skbuff.c 2006-03-20 06:53:29.000000000 +0100
++++ linux-2.6.16-owrt/net/core/skbuff.c 2006-03-20 12:59:23.000000000 +0100
+@@ -425,6 +425,10 @@
+ C(nfct_reasm);
+ nf_conntrack_get_reasm(skb->nfct_reasm);
+ #endif
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++ C(imq_flags);
++ C(nf_info);
++#endif /*CONFIG_IMQ*/
+ #ifdef CONFIG_BRIDGE_NETFILTER
+ C(nf_bridge);
+ nf_bridge_get(skb->nf_bridge);
+@@ -489,6 +493,10 @@
+ #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
+ new->ipvs_property = old->ipvs_property;
+ #endif
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++ new->imq_flags = old->imq_flags;
++ new->nf_info = old->nf_info;
++#endif /*CONFIG_IMQ*/
+ #ifdef CONFIG_BRIDGE_NETFILTER
+ new->nf_bridge = old->nf_bridge;
+ nf_bridge_get(old->nf_bridge);
+diff -Nur linux-2.6.16/net/ipv4/netfilter/ipt_IMQ.c linux-2.6.16-owrt/net/ipv4/netfilter/ipt_IMQ.c
+--- linux-2.6.16/net/ipv4/netfilter/ipt_IMQ.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv4/netfilter/ipt_IMQ.c 2006-03-20 12:59:23.000000000 +0100
+@@ -0,0 +1,80 @@
++/*
++ * This target marks packets to be enqueued to an imq device
++ */
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_IMQ.h>
++#include <linux/imq.h>
++
++static unsigned int imq_target(struct sk_buff **pskb,
++ const struct net_device *in,
++ const struct net_device *out,
++ unsigned int hooknum,
++ const void *targinfo,
++ void *userdata)
++{
++ struct ipt_imq_info *mr = (struct ipt_imq_info*)targinfo;
++
++ (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
++
++ return IPT_CONTINUE;
++}
++
++static int imq_checkentry(const char *tablename,
++ const struct ipt_entry *e,
++ void *targinfo,
++ unsigned int targinfosize,
++ unsigned int hook_mask)
++{
++ struct ipt_imq_info *mr;
++
++ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_imq_info))) {
++ printk(KERN_WARNING "IMQ: invalid targinfosize\n");
++ return 0;
++ }
++ mr = (struct ipt_imq_info*)targinfo;
++
++ if (strcmp(tablename, "mangle") != 0) {
++ printk(KERN_WARNING
++ "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
++ tablename);
++ return 0;
++ }
++
++ if (mr->todev > IMQ_MAX_DEVS) {
++ printk(KERN_WARNING
++ "IMQ: invalid device specified, highest is %u\n",
++ IMQ_MAX_DEVS);
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct ipt_target ipt_imq_reg = {
++ .name = "IMQ",
++ .target = imq_target,
++ .checkentry = imq_checkentry,
++ .me = THIS_MODULE
++};
++
++static int __init init(void)
++{
++ if (ipt_register_target(&ipt_imq_reg))
++ return -EINVAL;
++
++ return 0;
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_target(&ipt_imq_reg);
++}
++
++module_init(init);
++module_exit(fini);
++
++MODULE_AUTHOR("http://www.linuximq.net");
++MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
++MODULE_LICENSE("GPL");
+diff -Nur linux-2.6.16/net/ipv4/netfilter/Kconfig linux-2.6.16-owrt/net/ipv4/netfilter/Kconfig
+--- linux-2.6.16/net/ipv4/netfilter/Kconfig 2006-03-20 12:58:53.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv4/netfilter/Kconfig 2006-03-20 12:59:23.000000000 +0100
+@@ -351,6 +351,17 @@
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config IP_NF_TARGET_IMQ
++ tristate "IMQ target support"
++ depends on IP_NF_MANGLE
++ help
++ This option adds a `IMQ' target which is used to specify if and
++ to which IMQ device packets should get enqueued/dequeued.
++
++ For more information visit: http://www.linuximq.net/
++
++ To compile it as a module, choose M here. If unsure, say N.
++
+ config IP_NF_TARGET_LOG
+ tristate "LOG target support"
+ depends on IP_NF_IPTABLES
+diff -Nur linux-2.6.16/net/ipv4/netfilter/Makefile linux-2.6.16-owrt/net/ipv4/netfilter/Makefile
+--- linux-2.6.16/net/ipv4/netfilter/Makefile 2006-03-20 12:58:53.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv4/netfilter/Makefile 2006-03-20 13:01:12.000000000 +0100
+@@ -67,6 +67,7 @@
+ obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
+ obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
+ obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
++obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
+ obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
+ obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
+ obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
+diff -Nur linux-2.6.16/net/ipv6/netfilter/ip6t_IMQ.c linux-2.6.16-owrt/net/ipv6/netfilter/ip6t_IMQ.c
+--- linux-2.6.16/net/ipv6/netfilter/ip6t_IMQ.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv6/netfilter/ip6t_IMQ.c 2006-03-20 12:59:23.000000000 +0100
+@@ -0,0 +1,80 @@
++/*
++ * This target marks packets to be enqueued to an imq device
++ */
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv6/ip6_tables.h>
++#include <linux/netfilter_ipv6/ip6t_IMQ.h>
++#include <linux/imq.h>
++
++static unsigned int imq_target(struct sk_buff **pskb,
++ unsigned int hooknum,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *targinfo,
++ void *userdata)
++{
++ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)targinfo;
++
++ (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
++
++ return IP6T_CONTINUE;
++}
++
++static int imq_checkentry(const char *tablename,
++ const struct ip6t_entry *e,
++ void *targinfo,
++ unsigned int targinfosize,
++ unsigned int hook_mask)
++{
++ struct ip6t_imq_info *mr;
++
++ if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_imq_info))) {
++ printk(KERN_WARNING "IMQ: invalid targinfosize\n");
++ return 0;
++ }
++ mr = (struct ip6t_imq_info*)targinfo;
++
++ if (strcmp(tablename, "mangle") != 0) {
++ printk(KERN_WARNING
++ "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
++ tablename);
++ return 0;
++ }
++
++ if (mr->todev > IMQ_MAX_DEVS) {
++ printk(KERN_WARNING
++ "IMQ: invalid device specified, highest is %u\n",
++ IMQ_MAX_DEVS);
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct ip6t_target ip6t_imq_reg = {
++ .name = "IMQ",
++ .target = imq_target,
++ .checkentry = imq_checkentry,
++ .me = THIS_MODULE
++};
++
++static int __init init(void)
++{
++ if (ip6t_register_target(&ip6t_imq_reg))
++ return -EINVAL;
++
++ return 0;
++}
++
++static void __exit fini(void)
++{
++ ip6t_unregister_target(&ip6t_imq_reg);
++}
++
++module_init(init);
++module_exit(fini);
++
++MODULE_AUTHOR("http://www.linuximq.net");
++MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
++MODULE_LICENSE("GPL");
+diff -Nur linux-2.6.16/net/ipv6/netfilter/Kconfig linux-2.6.16-owrt/net/ipv6/netfilter/Kconfig
+--- linux-2.6.16/net/ipv6/netfilter/Kconfig 2006-03-20 06:53:29.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv6/netfilter/Kconfig 2006-03-20 12:59:23.000000000 +0100
+@@ -154,6 +154,15 @@
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config IP6_NF_TARGET_IMQ
++ tristate "IMQ target support"
++ depends on IP6_NF_MANGLE
++ help
++ This option adds a `IMQ' target which is used to specify if and
++ to which imq device packets should get enqueued/dequeued.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
+ config IP6_NF_TARGET_LOG
+ tristate "LOG target support"
+ depends on IP6_NF_FILTER
+diff -Nur linux-2.6.16/net/ipv6/netfilter/Makefile linux-2.6.16-owrt/net/ipv6/netfilter/Makefile
+--- linux-2.6.16/net/ipv6/netfilter/Makefile 2006-03-20 06:53:29.000000000 +0100
++++ linux-2.6.16-owrt/net/ipv6/netfilter/Makefile 2006-03-20 13:02:14.000000000 +0100
+@@ -4,6 +4,7 @@
+
+ # Link order matters here.
+ obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
++obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o
+ obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
+ obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
+ obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
+diff -Nur linux-2.6.16/net/sched/sch_generic.c linux-2.6.16-owrt/net/sched/sch_generic.c
+--- linux-2.6.16/net/sched/sch_generic.c 2006-03-20 06:53:29.000000000 +0100
++++ linux-2.6.16-owrt/net/sched/sch_generic.c 2006-03-20 12:59:23.000000000 +0100
+@@ -29,6 +29,9 @@
+ #include <linux/netdevice.h>
+ #include <linux/skbuff.h>
+ #include <linux/rtnetlink.h>
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++#include <linux/imq.h>
++#endif
+ #include <linux/init.h>
+ #include <linux/rcupdate.h>
+ #include <linux/list.h>
+@@ -136,7 +139,13 @@
+
+ if (!netif_queue_stopped(dev)) {
+ int ret;
+- if (netdev_nit)
++
++ if (netdev_nit
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++ && !(skb->imq_flags & IMQ_F_ENQUEUE)
++#endif
++ )
++
+ dev_queue_xmit_nit(skb, dev);
+
+ ret = dev->hard_start_xmit(skb, dev);
diff --git a/target/linux/generic-2.6/patches/107-netfilter_nat_sip.patch b/target/linux/generic-2.6/patches/107-netfilter_nat_sip.patch
new file mode 100644
index 0000000000..6640118f20
--- /dev/null
+++ b/target/linux/generic-2.6/patches/107-netfilter_nat_sip.patch
@@ -0,0 +1,830 @@
+diff -urN linux-2.6.16.4/net/ipv4/netfilter/ip_conntrack_sip.c linux-2.6.16.4.new/net/ipv4/netfilter/ip_conntrack_sip.c
+--- linux-2.6.16.4/net/ipv4/netfilter/ip_conntrack_sip.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.4.new/net/ipv4/netfilter/ip_conntrack_sip.c 2006-04-12 17:31:44.000000000 +0200
+@@ -0,0 +1,414 @@
++/* SIP extension for IP connection tracking.
++ *
++ * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
++ * based on RR's ip_conntrack_ftp.c and other modules.
++ *
++ * 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/config.h>
++#include <linux/module.h>
++#include <linux/netfilter.h>
++#include <linux/ip.h>
++#include <linux/ctype.h>
++#include <linux/in.h>
++#include <linux/udp.h>
++#include <net/checksum.h>
++#include <net/udp.h>
++
++#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
++#include <linux/netfilter_ipv4/ip_conntrack_sip.h>
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
++MODULE_DESCRIPTION("SIP connection tracking helper");
++
++static DEFINE_SPINLOCK(sipbf_lock);
++
++
++#define MAX_PORTS 8
++static int ports[MAX_PORTS];
++static int ports_c;
++module_param_array(ports, int, &ports_c, 0400);
++MODULE_PARM_DESC(ports, " port numbers of sip servers");
++
++static unsigned int sip_timeout = SIP_TIMEOUT;
++
++module_param(sip_timeout, int, 0600);
++MODULE_PARM_DESC(sip_timeout, "timeout for the master sip session");
++
++unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
++ enum ip_conntrack_info ctinfo,
++ struct ip_conntrack *ct,
++ const char **dptr);
++EXPORT_SYMBOL_GPL(ip_nat_sip_hook);
++
++unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb,
++ enum ip_conntrack_info ctinfo,
++ struct ip_conntrack_expect *exp,
++ const char *dptr);
++EXPORT_SYMBOL_GPL(ip_nat_sdp_hook);
++
++int ct_sip_get_info(const char *dptr, size_t dlen,
++ unsigned int *matchoff,
++ unsigned int *matchlen,
++ struct sip_header_nfo *hnfo);
++EXPORT_SYMBOL(ct_sip_get_info);
++
++#if 0
++#define DEBUGP printk
++#else
++#define DEBUGP(format, args...)
++#endif
++
++static int digits_len(const char *dptr, const char *limit, int *shift);
++static int epaddr_len(const char *dptr, const char *limit, int *shift);
++static int skp_digits_len(const char *dptr, const char *limit, int *shift);
++static int skp_epaddr_len(const char *dptr, const char *limit, int *shift);
++
++struct sip_header_nfo ct_sip_hdrs[] = {
++ { /* Via header */
++ "Via:", sizeof("Via:") - 1,
++ "\r\nv:", sizeof("\r\nv:") - 1, /* rfc3261 "\r\n" */
++ "UDP ", sizeof("UDP ") - 1,
++ epaddr_len
++ },
++ { /* Contact header */
++ "Contact:", sizeof("Contact:") - 1,
++ "\r\nm:", sizeof("\r\nm:") - 1,
++ "sip:", sizeof("sip:") - 1,
++ skp_epaddr_len
++ },
++ { /* Content length header */
++ "Content-Length:", sizeof("Content-Length:") - 1,
++ "\r\nl:", sizeof("\r\nl:") - 1,
++ ":", sizeof(":") - 1,
++ skp_digits_len
++ },
++ { /* SDP media info */
++ "\nm=", sizeof("\nm=") - 1,
++ "\rm=", sizeof("\rm=") - 1,
++ "audio ", sizeof("audio ") - 1,
++ digits_len
++ },
++ { /* SDP owner address*/
++ "\no=", sizeof("\no=") - 1,
++ "\ro=", sizeof("\ro=") - 1,
++ "IN IP4 ", sizeof("IN IP4 ") - 1,
++ epaddr_len
++ },
++ { /* SDP connection info */
++ "\nc=", sizeof("\nc=") - 1,
++ "\rc=", sizeof("\rc=") - 1,
++ "IN IP4 ", sizeof("IN IP4 ") - 1,
++ epaddr_len
++ },
++ { /* Requests headers */
++ "sip:", sizeof("sip:") - 1,
++ "sip:", sizeof("sip:") - 1, /* yes, i know.. ;) */
++ "@", sizeof("@") - 1,
++ epaddr_len
++ },
++ { /* SDP version header */
++ "\nv=", sizeof("\nv=") - 1,
++ "\rv=", sizeof("\rv=") - 1,
++ "=", sizeof("=") - 1,
++ digits_len
++ }
++};
++EXPORT_SYMBOL(ct_sip_hdrs);
++
++
++static int digits_len(const char *dptr, const char *limit, int *shift)
++{
++ int len = 0;
++ while (dptr <= limit && isdigit(*dptr)) {
++ dptr++;
++ len++;
++ }
++ return len;
++}
++
++/* get digits lenght, skiping blank spaces. */
++static int skp_digits_len(const char *dptr, const char *limit, int *shift)
++{
++ for (; dptr <= limit && *dptr == ' '; dptr++)
++ (*shift)++;
++
++ return digits_len(dptr, limit, shift);
++}
++
++/* Simple ipaddr parser.. */
++static int parse_ipaddr(const char *cp, const char **endp,
++ uint32_t *ipaddr, const char *limit)
++{
++ unsigned long int val;
++ int i, digit = 0;
++
++ for (i = 0, *ipaddr = 0; cp <= limit && i < 4; i++) {
++ digit = 0;
++ if (!isdigit(*cp))
++ break;
++
++ val = simple_strtoul(cp, (char **)&cp, 10);
++ if (val > 0xFF)
++ return -1;
++
++ ((uint8_t *)ipaddr)[i] = val;
++ digit = 1;
++
++ if (*cp != '.')
++ break;
++ cp++;
++ }
++ if (!digit)
++ return -1;
++
++ if (endp)
++ *endp = cp;
++
++ return 0;
++}
++
++/* skip ip address. returns it lenght. */
++static int epaddr_len(const char *dptr, const char *limit, int *shift)
++{
++ const char *aux = dptr;
++ uint32_t ip;
++
++ if (parse_ipaddr(dptr, &dptr, &ip, limit) < 0) {
++ DEBUGP("ip: %s parse failed.!\n", dptr);
++ return 0;
++ }
++
++ /* Port number */
++ if (*dptr == ':') {
++ dptr++;
++ dptr += digits_len(dptr, limit, shift);
++ }
++ return dptr - aux;
++}
++
++/* get address lenght, skiping user info. */
++static int skp_epaddr_len(const char *dptr, const char *limit, int *shift)
++{
++ for (; dptr <= limit && *dptr != '@'; dptr++)
++ (*shift)++;
++
++ if (*dptr == '@') {
++ dptr++;
++ (*shift)++;
++ return epaddr_len(dptr, limit, shift);
++ }
++ return 0;
++}
++
++/* Returns 0 if not found, -1 error parsing. */
++int ct_sip_get_info(const char *dptr, size_t dlen,
++ unsigned int *matchoff,
++ unsigned int *matchlen,
++ struct sip_header_nfo *hnfo)
++{
++ const char *limit, *aux, *k = dptr;
++ int shift = 0;
++
++ limit = dptr + (dlen - hnfo->lnlen);
++
++ while (dptr <= limit) {
++ if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) &&
++ (strncmp(dptr, hnfo->sname, hnfo->snlen) != 0))
++ {
++ dptr++;
++ continue;
++ }
++ aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen,
++ ct_sip_lnlen(dptr, limit));
++ if (!aux) {
++ DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str, hnfo->lname);
++ return -1;
++ }
++ aux += hnfo->ln_strlen;
++
++ *matchlen = hnfo->match_len(aux, limit, &shift);
++ if (!*matchlen)
++ return -1;
++
++ *matchoff = (aux - k) + shift;
++
++ DEBUGP("%s match succeeded! - len: %u\n", hnfo->lname, *matchlen);
++ return 1;
++ }
++ DEBUGP("%s header not found.\n", hnfo->lname);
++ return 0;
++}
++
++static int set_expected_rtp(struct sk_buff **pskb,
++ struct ip_conntrack *ct,
++ enum ip_conntrack_info ctinfo,
++ uint32_t ipaddr, uint16_t port,
++ const char *dptr)
++{
++ struct ip_conntrack_expect *exp;
++ int ret;
++
++ exp = ip_conntrack_expect_alloc(ct);
++ if (exp == NULL)
++ return NF_DROP;
++
++ exp->tuple = ((struct ip_conntrack_tuple)
++ { { ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip, { 0 } },
++ { ipaddr, { .udp = { htons(port) } }, IPPROTO_UDP }});
++
++ exp->mask = ((struct ip_conntrack_tuple)
++ { { 0xFFFFFFFF, { 0 } },
++ { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFF }});
++
++ exp->expectfn = NULL;
++
++ if (ip_nat_sdp_hook)
++ ret = ip_nat_sdp_hook(pskb, ctinfo, exp, dptr);
++ else {
++ if (ip_conntrack_expect_related(exp) != 0)
++ ret = NF_DROP;
++ else
++ ret = NF_ACCEPT;
++ }
++ ip_conntrack_expect_put(exp);
++
++ return ret;
++}
++
++static int sip_help(struct sk_buff **pskb,
++ struct ip_conntrack *ct,
++ enum ip_conntrack_info ctinfo)
++{
++ unsigned int dataoff, datalen;
++ const char *dptr;
++ int ret = NF_ACCEPT;
++ int matchoff, matchlen;
++ uint32_t ipaddr;
++ uint16_t port;
++
++ /* No Data ? */
++ dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
++ if (dataoff >= (*pskb)->len) {
++ DEBUGP("skb->len = %u\n", (*pskb)->len);
++ return NF_ACCEPT;
++ }
++
++ ip_ct_refresh(ct, *pskb, sip_timeout * HZ);
++
++ spin_lock_bh(&sipbf_lock);
++
++ if ((dataoff + (*pskb)->len - dataoff) <= skb_headlen(*pskb))
++ dptr = (*pskb)->data + dataoff;
++ else {
++ DEBUGP("Copy of skbuff not supported yet.\n");
++ goto out;
++ }
++
++ if (ip_nat_sip_hook) {
++ if (!ip_nat_sip_hook(pskb, ctinfo, ct, &dptr)) {
++ ret = NF_DROP;
++ goto out;
++ }
++ }
++
++ if ((ctinfo) >= IP_CT_IS_REPLY)
++ goto out;
++
++ /* After this point NAT, could have mangled skb, so
++ we need to recalculate payload lenght. */
++ datalen = (*pskb)->len - dataoff;
++
++ if (datalen < (sizeof("SIP/2.0 200") - 1))
++ goto out;
++
++ /* RTP info only in some SDP pkts */
++ if (memcmp(dptr, "INVITE", sizeof("INVITE") - 1) != 0 &&
++ memcmp(dptr, "SIP/2.0 200", sizeof("SIP/2.0 200") - 1) != 0) {
++ goto out;
++ }
++ /* Get ip and port address from SDP packet. */
++ if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
++ &ct_sip_hdrs[POS_CONECTION]) > 0) {
++
++ /* We'll drop only if there are parse problems. */
++ if (parse_ipaddr(dptr + matchoff, NULL, &ipaddr,
++ dptr + datalen) < 0) {
++ ret = NF_DROP;
++ goto out;
++ }
++ if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
++ &ct_sip_hdrs[POS_MEDIA]) > 0) {
++
++ port = simple_strtoul(dptr + matchoff, NULL, 10);
++ if (port < 1024) {
++ ret = NF_DROP;
++ goto out;
++ }
++ ret = set_expected_rtp(pskb, ct, ctinfo,
++ ipaddr, port, dptr);
++ }
++ }
++out: spin_unlock_bh(&sipbf_lock);
++ return ret;
++}
++
++static struct ip_conntrack_helper sip[MAX_PORTS];
++static char sip_names[MAX_PORTS][10];
++
++static void fini(void)
++{
++ int i = 0;
++ for (; i < ports_c; i++) {
++ DEBUGP("unregistering helper for port %d\n", ports[i]);
++ ip_conntrack_helper_unregister(&sip[i]);
++ }
++}
++
++static int __init init(void)
++{
++ int i, ret;
++ char *tmpname;
++
++ if (ports_c == 0)
++ ports[ports_c++] = SIP_PORT;
++
++ for (i = 0; i < ports_c; i++) {
++ /* Create helper structure */
++ memset(&sip[i], 0, sizeof(struct ip_conntrack_helper));
++
++ sip[i].tuple.dst.protonum = IPPROTO_UDP;
++ sip[i].tuple.src.u.udp.port = htons(ports[i]);
++ sip[i].mask.src.u.udp.port = 0xFFFF;
++ sip[i].mask.dst.protonum = 0xFF;
++ sip[i].max_expected = 1;
++ sip[i].timeout = 3 * 60; /* 3 minutes */
++ sip[i].me = THIS_MODULE;
++ sip[i].help = sip_help;
++
++ tmpname = &sip_names[i][0];
++ if (ports[i] == SIP_PORT)
++ sprintf(tmpname, "sip");
++ else
++ sprintf(tmpname, "sip-%d", i);
++ sip[i].name = tmpname;
++
++ DEBUGP("port #%d: %d\n", i, ports[i]);
++
++ ret=ip_conntrack_helper_register(&sip[i]);
++ if (ret) {
++ printk("ERROR registering helper for port %d\n",
++ ports[i]);
++ fini();
++ return(ret);
++ }
++ }
++ return(0);
++}
++
++module_init(init);
++module_exit(fini);
+diff -urN linux-2.6.16.4/net/ipv4/netfilter/ip_nat_sip.c linux-2.6.16.4.new/net/ipv4/netfilter/ip_nat_sip.c
+--- linux-2.6.16.4/net/ipv4/netfilter/ip_nat_sip.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.4.new/net/ipv4/netfilter/ip_nat_sip.c 2006-04-12 17:31:53.000000000 +0200
+@@ -0,0 +1,249 @@
++/* SIP extension for UDP NAT alteration.
++ *
++ * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
++ * based on RR's ip_nat_ftp.c and other modules.
++ *
++ * 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/netfilter_ipv4.h>
++#include <linux/ip.h>
++#include <linux/udp.h>
++#include <net/udp.h>
++
++#include <linux/netfilter_ipv4/ip_nat.h>
++#include <linux/netfilter_ipv4/ip_nat_helper.h>
++#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
++#include <linux/netfilter_ipv4/ip_conntrack_sip.h>
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
++MODULE_DESCRIPTION("SIP NAT helper");
++
++#if 0
++#define DEBUGP printk
++#else
++#define DEBUGP(format, args...)
++#endif
++
++extern struct sip_header_nfo ct_sip_hdrs[];
++
++static unsigned int mangle_sip_packet(struct sk_buff **pskb,
++ enum ip_conntrack_info ctinfo,
++ struct ip_conntrack *ct,
++ const char **dptr, size_t dlen,
++ char *buffer, int bufflen,
++ struct sip_header_nfo *hnfo)
++{
++ unsigned int matchlen, matchoff;
++
++ if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, hnfo) <= 0)
++ return 0;
++
++ if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
++ matchoff, matchlen, buffer, bufflen)) {
++ return 0;
++ }
++ /* We need to reload this. Thanks Patrick. */
++ *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
++ return 1;
++}
++
++static unsigned int ip_nat_sip(struct sk_buff **pskb,
++ enum ip_conntrack_info ctinfo,
++ struct ip_conntrack *ct,
++ const char **dptr)
++{
++ char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
++ unsigned int bufflen, dataoff;
++ uint32_t ip;
++ uint16_t port;
++
++ dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
++
++ if ((ctinfo) >= IP_CT_IS_REPLY) {
++ ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
++ port = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
++ } else {
++ ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
++ port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
++ }
++ bufflen = sprintf(buffer, "%u.%u.%u.%u:%u", NIPQUAD(ip), ntohs(port));
++
++ /* short packet ? */
++ if (((*pskb)->len - dataoff) < (sizeof("SIP/2.0") - 1))
++ return 0;
++
++ /* Basic rules: requests and responses. */
++ if (memcmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) == 0) {
++
++ if ((ctinfo) < IP_CT_IS_REPLY) {
++ mangle_sip_packet(pskb, ctinfo, ct, dptr,
++ (*pskb)->len - dataoff, buffer, bufflen,
++ &ct_sip_hdrs[POS_CONTACT]);
++ return 1;
++ }
++
++ if (!mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
++ buffer, bufflen, &ct_sip_hdrs[POS_VIA])) {
++ return 0;
++ }
++
++ /* This search should ignore case, but later.. */
++ const char *aux = ct_sip_search("CSeq:", *dptr, sizeof("CSeq:") - 1,
++ (*pskb)->len - dataoff);
++ if (!aux)
++ return 0;
++
++ if (!ct_sip_search("REGISTER", aux, sizeof("REGISTER"),
++ ct_sip_lnlen(aux, *dptr + (*pskb)->len - dataoff))) {
++ return 1;
++ }
++ return mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
++ buffer, bufflen, &ct_sip_hdrs[POS_CONTACT]);
++ }
++ if ((ctinfo) < IP_CT_IS_REPLY) {
++ if (!mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
++ buffer, bufflen, &ct_sip_hdrs[POS_VIA])) {
++ return 0;
++ }
++
++ /* Mangle Contact if exists only. - watch udp_nat_mangle()! */
++ mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
++ buffer, bufflen, &ct_sip_hdrs[POS_CONTACT]);
++ return 1;
++ }
++ /* This mangle requests headers. */
++ return mangle_sip_packet(pskb, ctinfo, ct, dptr,
++ ct_sip_lnlen(*dptr, *dptr + (*pskb)->len - dataoff),
++ buffer, bufflen, &ct_sip_hdrs[POS_REQ_HEADER]);
++}
++
++static int mangle_content_len(struct sk_buff **pskb,
++ enum ip_conntrack_info ctinfo,
++ struct ip_conntrack *ct,
++ const char *dptr)
++{
++ unsigned int dataoff, matchoff, matchlen;
++ char buffer[sizeof("65536")];
++ int bufflen;
++
++ dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
++
++ /* Get actual SDP lenght */
++ if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
++ &matchlen, &ct_sip_hdrs[POS_SDP_HEADER]) > 0) {
++
++ /* since ct_sip_get_info() give us a pointer passing 'v='
++ we need to add 2 bytes in this count. */
++ int c_len = (*pskb)->len - dataoff - matchoff + 2;
++
++ /* Now, update SDP lenght */
++ if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
++ &matchlen, &ct_sip_hdrs[POS_CONTENT]) > 0) {
++
++ bufflen = sprintf(buffer, "%u", c_len);
++
++ return ip_nat_mangle_udp_packet(pskb, ct, ctinfo, matchoff,
++ matchlen, buffer, bufflen);
++ }
++ }
++ return 0;
++}
++
++static unsigned int mangle_sdp(struct sk_buff **pskb,
++ enum ip_conntrack_info ctinfo,
++ struct ip_conntrack *ct,
++ uint32_t newip, uint16_t port,
++ const char *dptr)
++{
++ char buffer[sizeof("nnn.nnn.nnn.nnn")];
++ unsigned int dataoff, bufflen;
++
++ dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
++
++ /* Mangle owner and contact info. */
++ bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
++ if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
++ buffer, bufflen, &ct_sip_hdrs[POS_OWNER])) {
++ return 0;
++ }
++
++ if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
++ buffer, bufflen, &ct_sip_hdrs[POS_CONECTION])) {
++ return 0;
++ }
++
++ /* Mangle media port. */
++ bufflen = sprintf(buffer, "%u", port);
++ if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
++ buffer, bufflen, &ct_sip_hdrs[POS_MEDIA])) {
++ return 0;
++ }
++
++ return mangle_content_len(pskb, ctinfo, ct, dptr);
++}
++
++/* So, this packet has hit the connection tracking matching code.
++ Mangle it, and change the expectation to match the new version. */
++static unsigned int ip_nat_sdp(struct sk_buff **pskb,
++ enum ip_conntrack_info ctinfo,
++ struct ip_conntrack_expect *exp,
++ const char *dptr)
++{
++ struct ip_conntrack *ct = exp->master;
++ uint32_t newip;
++ uint16_t port;
++
++ DEBUGP("ip_nat_sdp():\n");
++
++ /* Connection will come from reply */
++ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
++
++ exp->tuple.dst.ip = newip;
++ exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
++ exp->dir = IP_CT_DIR_REPLY;
++
++ /* When you see the packet, we need to NAT it the same as the
++ this one. */
++ exp->expectfn = ip_nat_follow_master;
++
++ /* Try to get same port: if not, try to change it. */
++ for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) {
++ exp->tuple.dst.u.udp.port = htons(port);
++ if (ip_conntrack_expect_related(exp) == 0)
++ break;
++ }
++
++ if (port == 0)
++ return NF_DROP;
++
++ if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) {
++ ip_conntrack_unexpect_related(exp);
++ return NF_DROP;
++ }
++ return NF_ACCEPT;
++}
++
++static void __exit fini(void)
++{
++ ip_nat_sip_hook = NULL;
++ ip_nat_sdp_hook = NULL;
++ /* Make sure noone calls it, meanwhile. */
++ synchronize_net();
++}
++
++static int __init init(void)
++{
++ BUG_ON(ip_nat_sip_hook);
++ BUG_ON(ip_nat_sdp_hook);
++ ip_nat_sip_hook = ip_nat_sip;
++ ip_nat_sdp_hook = ip_nat_sdp;
++ return 0;
++}
++
++module_init(init);
++module_exit(fini);
+diff -urN linux-2.6.16.4/net/ipv4/netfilter/Kconfig linux-2.6.16.4.new/net/ipv4/netfilter/Kconfig
+--- linux-2.6.16.4/net/ipv4/netfilter/Kconfig 2006-04-12 17:29:19.000000000 +0200
++++ linux-2.6.16.4.new/net/ipv4/netfilter/Kconfig 2006-04-12 17:32:53.000000000 +0200
+@@ -168,6 +168,19 @@
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. If unsure, say `N'.
+
++config IP_NF_SIP
++ tristate 'SIP support'
++ depends on IP_NF_CONNTRACK
++ help
++ SIP is an application-layer control protocol that can establish,
++ modify, and terminate multimedia sessions (conferences) such as
++ Internet telephony calls. With the ip_conntrack_sip and
++ the ip_nat_sip modules you can support the protocol on a connection
++ tracking/NATing firewall.
++
++ If you want to compile it as a module, say 'M' here and read
++ Documentation/modules.txt. If unsure, say 'N'.
++
+ config IP_NF_QUEUE
+ tristate "IP Userspace queueing via NETLINK (OBSOLETE)"
+ help
+@@ -545,6 +558,12 @@
+ default IP_NF_NAT if IP_NF_PPTP=y
+ default m if IP_NF_PPTP=m
+
++config IP_NF_NAT_SIP
++ tristate
++ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
++ default IP_NF_NAT if IP_NF_SIP=y
++ default m if IP_NF_SIP=m
++
+ # mangle + specific targets
+ config IP_NF_MANGLE
+ tristate "Packet mangling"
+diff -urN linux-2.6.16.4/net/ipv4/netfilter/Makefile linux-2.6.16.4.new/net/ipv4/netfilter/Makefile
+--- linux-2.6.16.4/net/ipv4/netfilter/Makefile 2006-04-12 17:29:19.000000000 +0200
++++ linux-2.6.16.4.new/net/ipv4/netfilter/Makefile 2006-04-12 17:33:39.000000000 +0200
+@@ -28,6 +28,7 @@
+ obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
+ obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
+ obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
++obj-$(CONFIG_IP_NF_SIP) += ip_conntrack_sip.o
+
+ # NAT helpers
+ obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
+@@ -35,6 +36,7 @@
+ obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
+ obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
+ obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
++obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o
+
+ # generic IP tables
+ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
+diff -urN linux-2.6.16.4/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.16.4.new/include/linux/netfilter_ipv4/ip_conntrack.h
+--- linux-2.6.16.4/include/linux/netfilter_ipv4/ip_conntrack.h 2006-04-12 17:29:19.000000000 +0200
++++ linux-2.6.16.4.new/include/linux/netfilter_ipv4/ip_conntrack.h 2006-04-12 17:30:38.000000000 +0200
+@@ -33,6 +33,7 @@
+ #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
+ #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
+ #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
++#include <linux/netfilter_ipv4/ip_conntrack_sip.h>
+
+ /* per conntrack: application helper private data */
+ union ip_conntrack_help {
+@@ -40,6 +41,7 @@
+ struct ip_ct_pptp_master ct_pptp_info;
+ struct ip_ct_ftp_master ct_ftp_info;
+ struct ip_ct_irc_master ct_irc_info;
++ struct ip_ct_sip_master ct_sip_info;
+ };
+
+ #ifdef CONFIG_IP_NF_NAT_NEEDED
+diff -urN linux-2.6.16.4/include/linux/netfilter_ipv4/ip_conntrack_sip.h linux-2.6.16.4.new/include/linux/netfilter_ipv4/ip_conntrack_sip.h
+--- linux-2.6.16.4/include/linux/netfilter_ipv4/ip_conntrack_sip.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.4.new/include/linux/netfilter_ipv4/ip_conntrack_sip.h 2006-04-12 17:31:12.000000000 +0200
+@@ -0,0 +1,81 @@
++#ifndef __IP_CONNTRACK_SIP_H__
++#define __IP_CONNTRACK_SIP_H__
++/* SIP tracking. */
++
++#ifdef __KERNEL__
++
++#define SIP_PORT 5060
++#define SIP_TIMEOUT 3600
++
++#define POS_VIA 0
++#define POS_CONTACT 1
++#define POS_CONTENT 2
++#define POS_MEDIA 3
++#define POS_OWNER 4
++#define POS_CONECTION 5
++#define POS_REQ_HEADER 6
++#define POS_SDP_HEADER 7
++
++struct ip_ct_sip_master {
++};
++
++struct sip_header_nfo {
++ const char *lname;
++ size_t lnlen;
++ const char *sname;
++ size_t snlen;
++ const char *ln_str;
++ size_t ln_strlen;
++ int (*match_len)(const char *, const char *, int *);
++
++};
++
++extern unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
++ enum ip_conntrack_info ctinfo,
++ struct ip_conntrack *ct,
++ const char **dptr);
++
++/* For NAT to hook in when on expect. */
++extern unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb,
++ enum ip_conntrack_info ctinfo,
++ struct ip_conntrack_expect *exp,
++ const char *dptr);
++
++extern int ct_sip_get_info(const char *dptr, size_t dlen,
++ unsigned int *matchoff,
++ unsigned int *matchlen,
++ struct sip_header_nfo *hnfo);
++
++/* get line lenght until first CR or LF seen. */
++static __inline__ int ct_sip_lnlen(const char *line, const char *limit)
++{
++ const char *k = line;
++
++ while ((line <= limit) && (*line == '\r' || *line == '\n'))
++ line++;
++
++ while (line <= limit) {
++ if (*line == '\r' || *line == '\n')
++ break;
++ line++;
++ }
++ return line - k;
++}
++
++/* Linear string search, case sensitive. */
++static __inline__
++const char *ct_sip_search(const char *needle, const char *haystack,
++ size_t needle_len, size_t haystack_len)
++{
++ const char *limit = haystack + (haystack_len - needle_len);
++
++ while (haystack <= limit) {
++ if (memcmp(haystack, needle, needle_len) == 0)
++ return haystack;
++ haystack++;
++ }
++ return NULL;
++}
++#endif /* __KERNEL__ */
++
++#endif /* __IP_CONNTRACK_SIP_H__ */
diff --git a/target/linux/generic-2.6/patches/108-netfilter_route.patch b/target/linux/generic-2.6/patches/108-netfilter_route.patch
new file mode 100644
index 0000000000..571d6a381b
--- /dev/null
+++ b/target/linux/generic-2.6/patches/108-netfilter_route.patch
@@ -0,0 +1,914 @@
+diff -u'rNF^function' linux-2.6.16.7/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.16.7-ROUTE/include/linux/netfilter_ipv4/ipt_ROUTE.h
+--- linux-2.6.16.7/include/linux/netfilter_ipv4/ipt_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7-ROUTE/include/linux/netfilter_ipv4/ipt_ROUTE.h 2006-06-14 16:40:49.000000000 +0200
+@@ -0,0 +1,23 @@
++/* Header file for iptables ipt_ROUTE target
++ *
++ * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
++ *
++ * This software is distributed under GNU GPL v2, 1991
++ */
++#ifndef _IPT_ROUTE_H_target
++#define _IPT_ROUTE_H_target
++
++#define IPT_ROUTE_IFNAMSIZ 16
++
++struct ipt_route_target_info {
++ char oif[IPT_ROUTE_IFNAMSIZ]; /* Output Interface Name */
++ char iif[IPT_ROUTE_IFNAMSIZ]; /* Input Interface Name */
++ u_int32_t gw; /* IP address of gateway */
++ u_int8_t flags;
++};
++
++/* Values for "flags" field */
++#define IPT_ROUTE_CONTINUE 0x01
++#define IPT_ROUTE_TEE 0x02
++
++#endif /*_IPT_ROUTE_H_target*/
+diff -u'rNF^function' linux-2.6.16.7/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.16.7-ROUTE/include/linux/netfilter_ipv6/ip6t_ROUTE.h
+--- linux-2.6.16.7/include/linux/netfilter_ipv6/ip6t_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7-ROUTE/include/linux/netfilter_ipv6/ip6t_ROUTE.h 2006-06-14 16:41:08.000000000 +0200
+@@ -0,0 +1,23 @@
++/* Header file for iptables ip6t_ROUTE target
++ *
++ * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
++ *
++ * This software is distributed under GNU GPL v2, 1991
++ */
++#ifndef _IPT_ROUTE_H_target
++#define _IPT_ROUTE_H_target
++
++#define IP6T_ROUTE_IFNAMSIZ 16
++
++struct ip6t_route_target_info {
++ char oif[IP6T_ROUTE_IFNAMSIZ]; /* Output Interface Name */
++ char iif[IP6T_ROUTE_IFNAMSIZ]; /* Input Interface Name */
++ u_int32_t gw[4]; /* IPv6 address of gateway */
++ u_int8_t flags;
++};
++
++/* Values for "flags" field */
++#define IP6T_ROUTE_CONTINUE 0x01
++#define IP6T_ROUTE_TEE 0x02
++
++#endif /*_IP6T_ROUTE_H_target*/
+diff -u'rNF^function' linux-2.6.16.7/net/ipv4/netfilter/Kconfig linux-2.6.16.7-ROUTE/net/ipv4/netfilter/Kconfig
+--- linux-2.6.16.7/net/ipv4/netfilter/Kconfig 2006-06-14 16:05:44.000000000 +0200
++++ linux-2.6.16.7-ROUTE/net/ipv4/netfilter/Kconfig 2006-06-14 16:46:40.000000000 +0200
+@@ -491,6 +491,23 @@
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config IP_NF_TARGET_ROUTE
++ tristate 'ROUTE target support'
++ depends on IP_NF_MANGLE
++ help
++ This option adds a `ROUTE' target, which enables you to setup unusual
++ routes. For example, the ROUTE lets you route a received packet through
++ an interface or towards a host, even if the regular destination of the
++ packet is the router itself. The ROUTE target is also able to change the
++ incoming interface of a packet.
++
++ The target can be or not a final target. It has to be used inside the
++ mangle table.
++
++ If you want to compile it as a module, say M here and read
++ Documentation/modules.txt. The module will be called ipt_ROUTE.o.
++ If unsure, say `N'.
++
+ config IP_NF_TARGET_NETMAP
+ tristate "NETMAP target support"
+ depends on IP_NF_NAT
+diff -u'rNF^function' linux-2.6.16.7/net/ipv4/netfilter/Makefile linux-2.6.16.7-ROUTE/net/ipv4/netfilter/Makefile
+--- linux-2.6.16.7/net/ipv4/netfilter/Makefile 2006-06-14 16:05:44.000000000 +0200
++++ linux-2.6.16.7-ROUTE/net/ipv4/netfilter/Makefile 2006-06-14 16:44:02.000000000 +0200
+@@ -74,6 +74,7 @@
+ obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
+ obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
+ obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
++obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
+ obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
+ obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
+ obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
+diff -u'rNF^function' linux-2.6.16.7/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.16.7-ROUTE/net/ipv4/netfilter/ipt_ROUTE.c
+--- linux-2.6.16.7/net/ipv4/netfilter/ipt_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7-ROUTE/net/ipv4/netfilter/ipt_ROUTE.c 2006-06-14 16:42:23.000000000 +0200
+@@ -0,0 +1,461 @@
++/*
++ * This implements the ROUTE target, which enables you to setup unusual
++ * routes not supported by the standard kernel routing table.
++ *
++ * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
++ *
++ * v 1.11 2004/11/23
++ *
++ * This software is distributed under GNU GPL v2, 1991
++ */
++
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/ip.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ip_conntrack.h>
++#include <linux/netfilter_ipv4/ipt_ROUTE.h>
++#include <linux/netdevice.h>
++#include <linux/route.h>
++#include <linux/if_arp.h>
++#include <net/ip.h>
++#include <net/route.h>
++#include <net/icmp.h>
++#include <net/checksum.h>
++
++#if 0
++#define DEBUGP printk
++#else
++#define DEBUGP(format, args...)
++#endif
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Cedric de Launois <delaunois@info.ucl.ac.be>");
++MODULE_DESCRIPTION("iptables ROUTE target module");
++
++/* Try to route the packet according to the routing keys specified in
++ * route_info. Keys are :
++ * - ifindex :
++ * 0 if no oif preferred,
++ * otherwise set to the index of the desired oif
++ * - route_info->gw :
++ * 0 if no gateway specified,
++ * otherwise set to the next host to which the pkt must be routed
++ * If success, skb->dev is the output device to which the packet must
++ * be sent and skb->dst is not NULL
++ *
++ * RETURN: -1 if an error occured
++ * 1 if the packet was succesfully routed to the
++ * destination desired
++ * 0 if the kernel routing table could not route the packet
++ * according to the keys specified
++ */
++static int route(struct sk_buff *skb,
++ unsigned int ifindex,
++ const struct ipt_route_target_info *route_info)
++{
++ int err;
++ struct rtable *rt;
++ struct iphdr *iph = skb->nh.iph;
++ struct flowi fl = {
++ .oif = ifindex,
++ .nl_u = {
++ .ip4_u = {
++ .daddr = iph->daddr,
++ .saddr = 0,
++ .tos = RT_TOS(iph->tos),
++ .scope = RT_SCOPE_UNIVERSE,
++ }
++ }
++ };
++
++ /* The destination address may be overloaded by the target */
++ if (route_info->gw)
++ fl.fl4_dst = route_info->gw;
++
++ /* Trying to route the packet using the standard routing table. */
++ if ((err = ip_route_output_key(&rt, &fl))) {
++ if (net_ratelimit())
++ DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
++ return -1;
++ }
++
++ /* Drop old route. */
++ dst_release(skb->dst);
++ skb->dst = NULL;
++
++ /* Success if no oif specified or if the oif correspond to the
++ * one desired */
++ if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
++ skb->dst = &rt->u.dst;
++ skb->dev = skb->dst->dev;
++ skb->protocol = htons(ETH_P_IP);
++ return 1;
++ }
++
++ /* The interface selected by the routing table is not the one
++ * specified by the user. This may happen because the dst address
++ * is one of our own addresses.
++ */
++ if (net_ratelimit())
++ DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n",
++ NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
++
++ return 0;
++}
++
++
++/* Stolen from ip_finish_output2
++ * PRE : skb->dev is set to the device we are leaving by
++ * skb->dst is not NULL
++ * POST: the packet is sent with the link layer header pushed
++ * the packet is destroyed
++ */
++static void ip_direct_send(struct sk_buff *skb)
++{
++ struct dst_entry *dst = skb->dst;
++ struct hh_cache *hh = dst->hh;
++ struct net_device *dev = dst->dev;
++ int hh_len = LL_RESERVED_SPACE(dev);
++
++ /* Be paranoid, rather than too clever. */
++ if (unlikely(skb_headroom(skb) < hh_len && dev->hard_header)) {
++ struct sk_buff *skb2;
++
++ skb2 = skb_realloc_headroom(skb, LL_RESERVED_SPACE(dev));
++ if (skb2 == NULL) {
++ kfree_skb(skb);
++ return;
++ }
++ if (skb->sk)
++ skb_set_owner_w(skb2, skb->sk);
++ kfree_skb(skb);
++ skb = skb2;
++ }
++
++ if (hh) {
++ int hh_alen;
++
++ read_lock_bh(&hh->hh_lock);
++ hh_alen = HH_DATA_ALIGN(hh->hh_len);
++ memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
++ read_unlock_bh(&hh->hh_lock);
++ skb_push(skb, hh->hh_len);
++ hh->hh_output(skb);
++ } else if (dst->neighbour)
++ dst->neighbour->output(skb);
++ else {
++ if (net_ratelimit())
++ DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
++ kfree_skb(skb);
++ }
++}
++
++
++/* PRE : skb->dev is set to the device we are leaving by
++ * POST: - the packet is directly sent to the skb->dev device, without
++ * pushing the link layer header.
++ * - the packet is destroyed
++ */
++static inline int dev_direct_send(struct sk_buff *skb)
++{
++ return dev_queue_xmit(skb);
++}
++
++
++static unsigned int route_oif(const struct ipt_route_target_info *route_info,
++ struct sk_buff *skb)
++{
++ unsigned int ifindex = 0;
++ struct net_device *dev_out = NULL;
++
++ /* The user set the interface name to use.
++ * Getting the current interface index.
++ */
++ if ((dev_out = dev_get_by_name(route_info->oif))) {
++ ifindex = dev_out->ifindex;
++ } else {
++ /* Unknown interface name : packet dropped */
++ if (net_ratelimit())
++ DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
++ return NF_DROP;
++ }
++
++ /* Trying the standard way of routing packets */
++ switch (route(skb, ifindex, route_info)) {
++ case 1:
++ dev_put(dev_out);
++ if (route_info->flags & IPT_ROUTE_CONTINUE)
++ return IPT_CONTINUE;
++
++ ip_direct_send(skb);
++ return NF_STOLEN;
++
++ case 0:
++ /* Failed to send to oif. Trying the hard way */
++ if (route_info->flags & IPT_ROUTE_CONTINUE)
++ return NF_DROP;
++
++ if (net_ratelimit())
++ DEBUGP("ipt_ROUTE: forcing the use of %i\n",
++ ifindex);
++
++ /* We have to force the use of an interface.
++ * This interface must be a tunnel interface since
++ * otherwise we can't guess the hw address for
++ * the packet. For a tunnel interface, no hw address
++ * is needed.
++ */
++ if ((dev_out->type != ARPHRD_TUNNEL)
++ && (dev_out->type != ARPHRD_IPGRE)) {
++ if (net_ratelimit())
++ DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
++ dev_put(dev_out);
++ return NF_DROP;
++ }
++
++ /* Send the packet. This will also free skb
++ * Do not go through the POST_ROUTING hook because
++ * skb->dst is not set and because it will probably
++ * get confused by the destination IP address.
++ */
++ skb->dev = dev_out;
++ dev_direct_send(skb);
++ dev_put(dev_out);
++ return NF_STOLEN;
++
++ default:
++ /* Unexpected error */
++ dev_put(dev_out);
++ return NF_DROP;
++ }
++}
++
++
++static unsigned int route_iif(const struct ipt_route_target_info *route_info,
++ struct sk_buff *skb)
++{
++ struct net_device *dev_in = NULL;
++
++ /* Getting the current interface index. */
++ if (!(dev_in = dev_get_by_name(route_info->iif))) {
++ if (net_ratelimit())
++ DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->iif);
++ return NF_DROP;
++ }
++
++ skb->dev = dev_in;
++ dst_release(skb->dst);
++ skb->dst = NULL;
++
++ netif_rx(skb);
++ dev_put(dev_in);
++ return NF_STOLEN;
++}
++
++
++static unsigned int route_gw(const struct ipt_route_target_info *route_info,
++ struct sk_buff *skb)
++{
++ if (route(skb, 0, route_info)!=1)
++ return NF_DROP;
++
++ if (route_info->flags & IPT_ROUTE_CONTINUE)
++ return IPT_CONTINUE;
++
++ ip_direct_send(skb);
++ return NF_STOLEN;
++}
++
++
++/* To detect and deter routed packet loopback when using the --tee option,
++ * we take a page out of the raw.patch book: on the copied skb, we set up
++ * a fake ->nfct entry, pointing to the local &route_tee_track. We skip
++ * routing packets when we see they already have that ->nfct.
++ */
++
++static struct ip_conntrack route_tee_track;
++
++static unsigned int ipt_route_target(struct sk_buff **pskb,
++ const struct net_device *in,
++ const struct net_device *out,
++ unsigned int hooknum,
++ const void *targinfo,
++ void *userinfo)
++{
++ const struct ipt_route_target_info *route_info = targinfo;
++ struct sk_buff *skb = *pskb;
++ unsigned int res;
++
++ if (skb->nfct == &route_tee_track.ct_general) {
++ /* Loopback - a packet we already routed, is to be
++ * routed another time. Avoid that, now.
++ */
++ if (net_ratelimit())
++ DEBUGP(KERN_DEBUG "ipt_ROUTE: loopback - DROP!\n");
++ return NF_DROP;
++ }
++
++ /* If we are at PREROUTING or INPUT hook
++ * the TTL isn't decreased by the IP stack
++ */
++ if (hooknum == NF_IP_PRE_ROUTING ||
++ hooknum == NF_IP_LOCAL_IN) {
++
++ struct iphdr *iph = skb->nh.iph;
++
++ if (iph->ttl <= 1) {
++ struct rtable *rt;
++ struct flowi fl = {
++ .oif = 0,
++ .nl_u = {
++ .ip4_u = {
++ .daddr = iph->daddr,
++ .saddr = iph->saddr,
++ .tos = RT_TOS(iph->tos),
++ .scope = ((iph->tos & RTO_ONLINK) ?
++ RT_SCOPE_LINK :
++ RT_SCOPE_UNIVERSE)
++ }
++ }
++ };
++
++ if (ip_route_output_key(&rt, &fl)) {
++ return NF_DROP;
++ }
++
++ if (skb->dev == rt->u.dst.dev) {
++ /* Drop old route. */
++ dst_release(skb->dst);
++ skb->dst = &rt->u.dst;
++
++ /* this will traverse normal stack, and
++ * thus call conntrack on the icmp packet */
++ icmp_send(skb, ICMP_TIME_EXCEEDED,
++ ICMP_EXC_TTL, 0);
++ }
++
++ return NF_DROP;
++ }
++
++ /*
++ * If we are at INPUT the checksum must be recalculated since
++ * the length could change as the result of a defragmentation.
++ */
++ if(hooknum == NF_IP_LOCAL_IN) {
++ iph->ttl = iph->ttl - 1;
++ iph->check = 0;
++ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
++ } else {
++ ip_decrease_ttl(iph);
++ }
++ }
++
++ if ((route_info->flags & IPT_ROUTE_TEE)) {
++ /*
++ * Copy the *pskb, and route the copy. Will later return
++ * IPT_CONTINUE for the original skb, which should continue
++ * on its way as if nothing happened. The copy should be
++ * independantly delivered to the ROUTE --gw.
++ */
++ skb = skb_copy(*pskb, GFP_ATOMIC);
++ if (!skb) {
++ if (net_ratelimit())
++ DEBUGP(KERN_DEBUG "ipt_ROUTE: copy failed!\n");
++ return IPT_CONTINUE;
++ }
++ }
++
++ /* Tell conntrack to forget this packet since it may get confused
++ * when a packet is leaving with dst address == our address.
++ * Good idea ? Dunno. Need advice.
++ *
++ * NEW: mark the skb with our &route_tee_track, so we avoid looping
++ * on any already routed packet.
++ */
++ if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
++ nf_conntrack_put(skb->nfct);
++ skb->nfct = &route_tee_track.ct_general;
++ skb->nfctinfo = IP_CT_NEW;
++ nf_conntrack_get(skb->nfct);
++ }
++
++ if (route_info->oif[0] != '\0') {
++ res = route_oif(route_info, skb);
++ } else if (route_info->iif[0] != '\0') {
++ res = route_iif(route_info, skb);
++ } else if (route_info->gw) {
++ res = route_gw(route_info, skb);
++ } else {
++ if (net_ratelimit())
++ DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
++ res = IPT_CONTINUE;
++ }
++
++ if ((route_info->flags & IPT_ROUTE_TEE))
++ res = IPT_CONTINUE;
++
++ return res;
++}
++
++
++static int ipt_route_checkentry(const char *tablename,
++ const void *e,
++ void *targinfo,
++ unsigned int targinfosize,
++ unsigned int hook_mask)
++{
++ if (strcmp(tablename, "mangle") != 0) {
++ printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
++ tablename);
++ return 0;
++ }
++
++ if (hook_mask & ~( (1 << NF_IP_PRE_ROUTING)
++ | (1 << NF_IP_LOCAL_IN)
++ | (1 << NF_IP_FORWARD)
++ | (1 << NF_IP_LOCAL_OUT)
++ | (1 << NF_IP_POST_ROUTING))) {
++ printk("ipt_ROUTE: bad hook\n");
++ return 0;
++ }
++
++ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
++ printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
++ targinfosize,
++ IPT_ALIGN(sizeof(struct ipt_route_target_info)));
++ return 0;
++ }
++
++ return 1;
++}
++
++
++static struct ipt_target ipt_route_reg = {
++ .name = "ROUTE",
++ .target = ipt_route_target,
++ .checkentry = ipt_route_checkentry,
++ .me = THIS_MODULE,
++};
++
++static int __init init(void)
++{
++ /* Set up fake conntrack (stolen from raw.patch):
++ - to never be deleted, not in any hashes */
++ atomic_set(&route_tee_track.ct_general.use, 1);
++ /* - and look it like as a confirmed connection */
++ set_bit(IPS_CONFIRMED_BIT, &route_tee_track.status);
++ /* Initialize fake conntrack so that NAT will skip it */
++ route_tee_track.status |= IPS_NAT_DONE_MASK;
++
++ return ipt_register_target(&ipt_route_reg);
++}
++
++
++static void __exit fini(void)
++{
++ ipt_unregister_target(&ipt_route_reg);
++}
++
++module_init(init);
++module_exit(fini);
+diff -u'rNF^function' linux-2.6.16.7/net/ipv6/ipv6_syms.c linux-2.6.16.7-ROUTE/net/ipv6/ipv6_syms.c
+--- linux-2.6.16.7/net/ipv6/ipv6_syms.c 2006-04-17 23:53:25.000000000 +0200
++++ linux-2.6.16.7-ROUTE/net/ipv6/ipv6_syms.c 2006-06-14 17:02:32.000000000 +0200
+@@ -12,6 +12,7 @@
+ EXPORT_SYMBOL(icmpv6_statistics);
+ EXPORT_SYMBOL(icmpv6_err_convert);
+ EXPORT_SYMBOL(ndisc_mc_map);
++EXPORT_SYMBOL(nd_tbl);
+ EXPORT_SYMBOL(register_inet6addr_notifier);
+ EXPORT_SYMBOL(unregister_inet6addr_notifier);
+ EXPORT_SYMBOL(ip6_route_output);
+diff -u'rNF^function' linux-2.6.16.7/net/ipv6/netfilter/Kconfig linux-2.6.16.7-ROUTE/net/ipv6/netfilter/Kconfig
+--- linux-2.6.16.7/net/ipv6/netfilter/Kconfig 2006-06-14 16:05:44.000000000 +0200
++++ linux-2.6.16.7-ROUTE/net/ipv6/netfilter/Kconfig 2006-06-14 16:45:45.000000000 +0200
+@@ -182,6 +182,19 @@
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config IP6_NF_TARGET_ROUTE
++ tristate ' ROUTE target support'
++ depends on IP6_NF_MANGLE
++ help
++ This option adds a `ROUTE' target, which enables you to setup unusual
++ routes. The ROUTE target is also able to change the incoming interface
++ of a packet.
++
++ The target can be or not a final target. It has to be used inside the
++ mangle table.
++
++ Not working as a module.
++
+ config IP6_NF_MANGLE
+ tristate "Packet mangling"
+ depends on IP6_NF_IPTABLES
+diff -u'rNF^function' linux-2.6.16.7/net/ipv6/netfilter/Makefile linux-2.6.16.7-ROUTE/net/ipv6/netfilter/Makefile
+--- linux-2.6.16.7/net/ipv6/netfilter/Makefile 2006-06-14 16:05:44.000000000 +0200
++++ linux-2.6.16.7-ROUTE/net/ipv6/netfilter/Makefile 2006-06-14 16:45:00.000000000 +0200
+@@ -22,6 +22,7 @@
+ obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
+ obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
+ obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
++obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
+
+ # objects for l3 independent conntrack
+ nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o
+diff -u'rNF^function' linux-2.6.16.7/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.16.7-ROUTE/net/ipv6/netfilter/ip6t_ROUTE.c
+--- linux-2.6.16.7/net/ipv6/netfilter/ip6t_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16.7-ROUTE/net/ipv6/netfilter/ip6t_ROUTE.c 2006-06-14 16:42:44.000000000 +0200
+@@ -0,0 +1,308 @@
++/*
++ * This implements the ROUTE v6 target, which enables you to setup unusual
++ * routes not supported by the standard kernel routing table.
++ *
++ * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
++ *
++ * v 1.1 2004/11/23
++ *
++ * This software is distributed under GNU GPL v2, 1991
++ */
++
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/ipv6.h>
++#include <linux/netfilter_ipv6/ip6_tables.h>
++#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
++#include <linux/netdevice.h>
++#include <net/ipv6.h>
++#include <net/ndisc.h>
++#include <net/ip6_route.h>
++#include <linux/icmpv6.h>
++
++#if 1
++#define DEBUGP printk
++#else
++#define DEBUGP(format, args...)
++#endif
++
++#define NIP6(addr) \
++ ntohs((addr).s6_addr16[0]), \
++ ntohs((addr).s6_addr16[1]), \
++ ntohs((addr).s6_addr16[2]), \
++ ntohs((addr).s6_addr16[3]), \
++ ntohs((addr).s6_addr16[4]), \
++ ntohs((addr).s6_addr16[5]), \
++ ntohs((addr).s6_addr16[6]), \
++ ntohs((addr).s6_addr16[7])
++
++/* Route the packet according to the routing keys specified in
++ * route_info. Keys are :
++ * - ifindex :
++ * 0 if no oif preferred,
++ * otherwise set to the index of the desired oif
++ * - route_info->gw :
++ * 0 if no gateway specified,
++ * otherwise set to the next host to which the pkt must be routed
++ * If success, skb->dev is the output device to which the packet must
++ * be sent and skb->dst is not NULL
++ *
++ * RETURN: 1 if the packet was succesfully routed to the
++ * destination desired
++ * 0 if the kernel routing table could not route the packet
++ * according to the keys specified
++ */
++static int
++route6(struct sk_buff *skb,
++ unsigned int ifindex,
++ const struct ip6t_route_target_info *route_info)
++{
++ struct rt6_info *rt = NULL;
++ struct ipv6hdr *ipv6h = skb->nh.ipv6h;
++ struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
++
++ DEBUGP("ip6t_ROUTE: called with: ");
++ DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
++ DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
++ DEBUGP("OUT=%s\n", route_info->oif);
++
++ if (ipv6_addr_any(gw))
++ rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
++ else
++ rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
++
++ if (!rt)
++ goto no_route;
++
++ DEBUGP("ip6t_ROUTE: routing gives: ");
++ DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
++ DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
++ DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
++
++ if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
++ goto wrong_route;
++
++ if (!rt->rt6i_nexthop) {
++ DEBUGP("ip6t_ROUTE: discovering neighbour\n");
++ rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
++ }
++
++ /* Drop old route. */
++ dst_release(skb->dst);
++ skb->dst = &rt->u.dst;
++ skb->dev = rt->rt6i_dev;
++ return 1;
++
++ wrong_route:
++ dst_release(&rt->u.dst);
++ no_route:
++ if (!net_ratelimit())
++ return 0;
++
++ printk("ip6t_ROUTE: no explicit route found ");
++ if (ifindex)
++ printk("via interface %s ", route_info->oif);
++ if (!ipv6_addr_any(gw))
++ printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
++ printk("\n");
++ return 0;
++}
++
++
++/* Stolen from ip6_output_finish
++ * PRE : skb->dev is set to the device we are leaving by
++ * skb->dst is not NULL
++ * POST: the packet is sent with the link layer header pushed
++ * the packet is destroyed
++ */
++static void ip_direct_send(struct sk_buff *skb)
++{
++ struct dst_entry *dst = skb->dst;
++ struct hh_cache *hh = dst->hh;
++
++ if (hh) {
++ read_lock_bh(&hh->hh_lock);
++ memcpy(skb->data - 16, hh->hh_data, 16);
++ read_unlock_bh(&hh->hh_lock);
++ skb_push(skb, hh->hh_len);
++ hh->hh_output(skb);
++ } else if (dst->neighbour)
++ dst->neighbour->output(skb);
++ else {
++ if (net_ratelimit())
++ DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
++ kfree_skb(skb);
++ }
++}
++
++
++static unsigned int
++route6_oif(const struct ip6t_route_target_info *route_info,
++ struct sk_buff *skb)
++{
++ unsigned int ifindex = 0;
++ struct net_device *dev_out = NULL;
++
++ /* The user set the interface name to use.
++ * Getting the current interface index.
++ */
++ if ((dev_out = dev_get_by_name(route_info->oif))) {
++ ifindex = dev_out->ifindex;
++ } else {
++ /* Unknown interface name : packet dropped */
++ if (net_ratelimit())
++ DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
++
++ if (route_info->flags & IP6T_ROUTE_CONTINUE)
++ return IP6T_CONTINUE;
++ else
++ return NF_DROP;
++ }
++
++ /* Trying the standard way of routing packets */
++ if (route6(skb, ifindex, route_info)) {
++ dev_put(dev_out);
++ if (route_info->flags & IP6T_ROUTE_CONTINUE)
++ return IP6T_CONTINUE;
++
++ ip_direct_send(skb);
++ return NF_STOLEN;
++ } else
++ return NF_DROP;
++}
++
++
++static unsigned int
++route6_gw(const struct ip6t_route_target_info *route_info,
++ struct sk_buff *skb)
++{
++ if (route6(skb, 0, route_info)) {
++ if (route_info->flags & IP6T_ROUTE_CONTINUE)
++ return IP6T_CONTINUE;
++
++ ip_direct_send(skb);
++ return NF_STOLEN;
++ } else
++ return NF_DROP;
++}
++
++
++static unsigned int
++ip6t_route_target(struct sk_buff **pskb,
++ const struct net_device *in,
++ const struct net_device *out,
++ unsigned int hooknum,
++ const void *targinfo,
++ void *userinfo)
++{
++ const struct ip6t_route_target_info *route_info = targinfo;
++ struct sk_buff *skb = *pskb;
++ struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
++ unsigned int res;
++
++ if (route_info->flags & IP6T_ROUTE_CONTINUE)
++ goto do_it;
++
++ /* If we are at PREROUTING or INPUT hook
++ * the TTL isn't decreased by the IP stack
++ */
++ if (hooknum == NF_IP6_PRE_ROUTING ||
++ hooknum == NF_IP6_LOCAL_IN) {
++
++ struct ipv6hdr *ipv6h = skb->nh.ipv6h;
++
++ if (ipv6h->hop_limit <= 1) {
++ /* Force OUTPUT device used as source address */
++ skb->dev = skb->dst->dev;
++
++ icmpv6_send(skb, ICMPV6_TIME_EXCEED,
++ ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
++
++ return NF_DROP;
++ }
++
++ ipv6h->hop_limit--;
++ }
++
++ if ((route_info->flags & IP6T_ROUTE_TEE)) {
++ /*
++ * Copy the *pskb, and route the copy. Will later return
++ * IP6T_CONTINUE for the original skb, which should continue
++ * on its way as if nothing happened. The copy should be
++ * independantly delivered to the ROUTE --gw.
++ */
++ skb = skb_copy(*pskb, GFP_ATOMIC);
++ if (!skb) {
++ if (net_ratelimit())
++ DEBUGP(KERN_DEBUG "ip6t_ROUTE: copy failed!\n");
++ return IP6T_CONTINUE;
++ }
++ }
++
++do_it:
++ if (route_info->oif[0]) {
++ res = route6_oif(route_info, skb);
++ } else if (!ipv6_addr_any(gw)) {
++ res = route6_gw(route_info, skb);
++ } else {
++ if (net_ratelimit())
++ DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
++ res = IP6T_CONTINUE;
++ }
++
++ if ((route_info->flags & IP6T_ROUTE_TEE))
++ res = IP6T_CONTINUE;
++
++ return res;
++}
++
++
++static int
++ip6t_route_checkentry(const char *tablename,
++ const struct ip6t_entry *e,
++ void *targinfo,
++ unsigned int targinfosize,
++ unsigned int hook_mask)
++{
++ if (strcmp(tablename, "mangle") != 0) {
++ printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
++ return 0;
++ }
++
++ if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
++ printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
++ targinfosize,
++ IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
++ return 0;
++ }
++
++ return 1;
++}
++
++
++static struct ip6t_target ip6t_route_reg = {
++ .name = "ROUTE",
++ .target = ip6t_route_target,
++ .checkentry = ip6t_route_checkentry,
++ .me = THIS_MODULE
++};
++
++
++static int __init init(void)
++{
++ printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
++ if (ip6t_register_target(&ip6t_route_reg))
++ return -EINVAL;
++
++ return 0;
++}
++
++
++static void __exit fini(void)
++{
++ ip6t_unregister_target(&ip6t_route_reg);
++}
++
++module_init(init);
++module_exit(fini);
++MODULE_LICENSE("GPL");
diff --git a/target/linux/generic-2.6/patches/200-sched_esfq.patch b/target/linux/generic-2.6/patches/200-sched_esfq.patch
new file mode 100644
index 0000000000..8790bad2bf
--- /dev/null
+++ b/target/linux/generic-2.6/patches/200-sched_esfq.patch
@@ -0,0 +1,730 @@
+diff -Naur linux-2.6.15.1.orig/include/linux/pkt_sched.h linux-2.6.15.1/include/linux/pkt_sched.h
+--- linux-2.6.15.1.orig/include/linux/pkt_sched.h 2006-01-14 22:16:02.000000000 -0800
++++ linux-2.6.15.1/include/linux/pkt_sched.h 2006-01-30 16:02:32.000000000 -0800
+@@ -146,8 +146,35 @@
+ *
+ * The only reason for this is efficiency, it is possible
+ * to change these parameters in compile time.
++ *
++ * If you need to play with these values use esfq instead.
+ */
+
++/* ESFQ section */
++
++enum
++{
++ /* traditional */
++ TCA_SFQ_HASH_CLASSIC,
++ TCA_SFQ_HASH_DST,
++ TCA_SFQ_HASH_SRC,
++ TCA_SFQ_HASH_FWMARK,
++ /* direct */
++ TCA_SFQ_HASH_DSTDIR,
++ TCA_SFQ_HASH_SRCDIR,
++ TCA_SFQ_HASH_FWMARKDIR,
++};
++
++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
+diff -Naur linux-2.6.15.1.orig/net/sched/Kconfig linux-2.6.15.1/net/sched/Kconfig
+--- linux-2.6.15.1.orig/net/sched/Kconfig 2006-01-14 22:16:02.000000000 -0800
++++ linux-2.6.15.1/net/sched/Kconfig 2006-01-30 16:02:32.000000000 -0800
+@@ -185,6 +185,28 @@
+ To compile this code as a module, choose M here: the
+ module will be called sch_sfq.
+
++config NET_SCH_ESFQ
++ tristate "ESFQ queue"
++ depends on NET_SCHED
++ ---help---
++ Say Y here if you want to use the Enhanced Stochastic Fairness
++ Queueing (ESFQ) packet scheduling algorithm for some of your network
++ devices or as a leaf discipline for a classful qdisc such as HTB or
++ CBQ (see the top of <file:net/sched/sch_esfq.c> for details and
++ references to the SFQ algorithm).
++
++ This is an enchanced SFQ version which allows you to control some
++ hardcoded values in the SFQ scheduler: queue depth, hash table size,
++ and queues limit.
++
++ ESFQ also adds control to the hash function used to identify packet
++ flows. The original SFQ hashes by individual flow (TCP session or UDP
++ stream); ESFQ can hash by src or dst IP as well, which can be more
++ fair to users in some networking situations.
++
++ To compile this code as a module, choose M here: the
++ module will be called sch_esfq.
++
+ config NET_SCH_TEQL
+ tristate "True Link Equalizer (TEQL)"
+ ---help---
+diff -Naur linux-2.6.15.1.orig/net/sched/Makefile linux-2.6.15.1/net/sched/Makefile
+--- linux-2.6.15.1.orig/net/sched/Makefile 2006-01-14 22:16:02.000000000 -0800
++++ linux-2.6.15.1/net/sched/Makefile 2006-01-30 16:02:32.000000000 -0800
+@@ -23,6 +23,7 @@
+ obj-$(CONFIG_NET_SCH_INGRESS) += sch_ingress.o
+ obj-$(CONFIG_NET_SCH_DSMARK) += sch_dsmark.o
+ obj-$(CONFIG_NET_SCH_SFQ) += sch_sfq.o
++obj-$(CONFIG_NET_SCH_ESFQ) += sch_esfq.o
+ obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o
+ obj-$(CONFIG_NET_SCH_TEQL) += sch_teql.o
+ obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o
+diff -Naur linux-2.6.15.1.orig/net/sched/sch_esfq.c linux-2.6.15.1/net/sched/sch_esfq.c
+--- linux-2.6.15.1.orig/net/sched/sch_esfq.c 1969-12-31 16:00:00.000000000 -0800
++++ linux-2.6.15.1/net/sched/sch_esfq.c 2006-01-30 16:12:29.000000000 -0800
+@@ -0,0 +1,644 @@
++/*
++ * net/sched/sch_esfq.c Extended Stochastic Fairness Queueing discipline.
++ *
++ * 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>
++ * Added dynamic depth,limit,divisor,hash_kind options.
++ * Added dst and src hashes.
++ *
++ * Alexander Clouter, <alex@digriz.org.uk>
++ * Ported ESFQ to Linux 2.6.
++ *
++ * Corey Hickey, <bugfood-c@fatooh.org>
++ * Maintenance of the Linux 2.6 port.
++ * Added fwmark hash (thanks to Robert Kurjata)
++ * Added direct hashing for src, dst, and fwmark.
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <asm/uaccess.h>
++#include <asm/system.h>
++#include <linux/bitops.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/jiffies.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/socket.h>
++#include <linux/sockios.h>
++#include <linux/in.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/if_ether.h>
++#include <linux/inet.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/notifier.h>
++#include <linux/init.h>
++#include <net/ip.h>
++#include <linux/ipv6.h>
++#include <net/route.h>
++#include <linux/skbuff.h>
++#include <net/sock.h>
++#include <net/pkt_sched.h>
++
++
++/* Stochastic Fairness Queuing algorithm.
++ For more comments look at sch_sfq.c.
++ The difference is that you can change limit, depth,
++ hash table size and choose 7 hash types.
++
++ classic: same as in sch_sfq.c
++ dst: destination IP address
++ src: source IP address
++ fwmark: netfilter mark value
++ dst_direct:
++ src_direct:
++ fwmark_direct: direct hashing of the above sources
++
++ TODO:
++ make sfq_change work.
++*/
++
++
++/* This type should contain at least SFQ_DEPTH*2 values */
++typedef unsigned int esfq_index;
++
++struct esfq_head
++{
++ esfq_index next;
++ esfq_index prev;
++};
++
++struct esfq_sched_data
++{
++/* Parameters */
++ int perturb_period;
++ unsigned quantum; /* Allotment per round: MUST BE >= MTU */
++ int limit;
++ unsigned depth;
++ unsigned hash_divisor;
++ unsigned hash_kind;
++/* Variables */
++ struct timer_list perturb_timer;
++ int perturbation;
++ esfq_index tail; /* Index of current slot in round */
++ esfq_index max_depth; /* Maximal depth */
++
++ esfq_index *ht; /* Hash table */
++ esfq_index *next; /* Active slots link */
++ short *allot; /* Current allotment per slot */
++ unsigned short *hash; /* Hash value indexed by slots */
++ struct sk_buff_head *qs; /* Slot queue */
++ struct esfq_head *dep; /* Linked list of slots, indexed by depth */
++ unsigned dyn_min; /* For dynamic divisor adjustment; minimum value seen */
++ unsigned dyn_max; /* maximum value seen */
++ unsigned dyn_range; /* saved range */
++};
++
++static __inline__ unsigned esfq_hash_u32(struct esfq_sched_data *q,u32 h)
++{
++ int pert = q->perturbation;
++
++ if (pert)
++ h = (h<<pert) ^ (h>>(0x1F - pert));
++
++ h = ntohl(h) * 2654435761UL;
++ return h & (q->hash_divisor-1);
++}
++
++/* Hash input values directly into the "nearest" slot, taking into account the
++ * range of input values seen. This is most useful when the hash table is at
++ * least as large as the range of possible values. */
++static __inline__ unsigned esfq_hash_direct(struct esfq_sched_data *q, u32 h)
++{
++ /* adjust minimum and maximum */
++ if (h < q->dyn_min || h > q->dyn_max) {
++ q->dyn_min = h < q->dyn_min ? h : q->dyn_min;
++ q->dyn_max = h > q->dyn_max ? h : q->dyn_max;
++
++ /* find new range */
++ if ((q->dyn_range = q->dyn_max - q->dyn_min) >= q->hash_divisor)
++ printk(KERN_WARNING "ESFQ: (direct hash) Input range %u is larger than hash "
++ "table. See ESFQ README for details.\n", q->dyn_range);
++ }
++
++ /* hash input values into slot numbers */
++ if (q->dyn_min == q->dyn_max)
++ return 0; /* only one value seen; avoid division by 0 */
++ else
++ return (h - q->dyn_min) * (q->hash_divisor - 1) / q->dyn_range;
++}
++
++static __inline__ unsigned esfq_fold_hash_classic(struct esfq_sched_data *q, u32 h, u32 h1)
++{
++ int pert = q->perturbation;
++
++ /* Have we any rotation primitives? If not, WHY? */
++ h ^= (h1<<pert) ^ (h1>>(0x1F - pert));
++ h ^= h>>10;
++ return h & (q->hash_divisor-1);
++}
++
++static unsigned esfq_hash(struct esfq_sched_data *q, struct sk_buff *skb)
++{
++ u32 h, h2;
++ u32 hs;
++ u32 nfm;
++
++ switch (skb->protocol) {
++ case __constant_htons(ETH_P_IP):
++ {
++ struct iphdr *iph = skb->nh.iph;
++ h = iph->daddr;
++ hs = iph->saddr;
++ nfm = skb->nfmark;
++ h2 = hs^iph->protocol;
++ if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
++ (iph->protocol == IPPROTO_TCP ||
++ iph->protocol == IPPROTO_UDP ||
++ iph->protocol == IPPROTO_SCTP ||
++ iph->protocol == IPPROTO_DCCP ||
++ iph->protocol == IPPROTO_ESP))
++ h2 ^= *(((u32*)iph) + iph->ihl);
++ break;
++ }
++ case __constant_htons(ETH_P_IPV6):
++ {
++ struct ipv6hdr *iph = skb->nh.ipv6h;
++ h = iph->daddr.s6_addr32[3];
++ hs = iph->saddr.s6_addr32[3];
++ nfm = skb->nfmark;
++ h2 = hs^iph->nexthdr;
++ if (iph->nexthdr == IPPROTO_TCP ||
++ iph->nexthdr == IPPROTO_UDP ||
++ iph->nexthdr == IPPROTO_SCTP ||
++ iph->nexthdr == IPPROTO_DCCP ||
++ iph->nexthdr == IPPROTO_ESP)
++ h2 ^= *(u32*)&iph[1];
++ break;
++ }
++ default:
++ h = (u32)(unsigned long)skb->dst;
++ hs = (u32)(unsigned long)skb->sk;
++ nfm = skb->nfmark;
++ h2 = hs^skb->protocol;
++ }
++ switch(q->hash_kind)
++ {
++ case TCA_SFQ_HASH_CLASSIC:
++ return esfq_fold_hash_classic(q, h, h2);
++ case TCA_SFQ_HASH_DST:
++ return esfq_hash_u32(q,h);
++ case TCA_SFQ_HASH_DSTDIR:
++ return esfq_hash_direct(q, ntohl(h));
++ case TCA_SFQ_HASH_SRC:
++ return esfq_hash_u32(q,hs);
++ case TCA_SFQ_HASH_SRCDIR:
++ return esfq_hash_direct(q, ntohl(hs));
++#ifdef CONFIG_NETFILTER
++ case TCA_SFQ_HASH_FWMARK:
++ return esfq_hash_u32(q,nfm);
++ case TCA_SFQ_HASH_FWMARKDIR:
++ return esfq_hash_direct(q,nfm);
++#endif
++ default:
++ if (net_ratelimit())
++ printk(KERN_WARNING "ESFQ: Unknown hash method. Falling back to classic.\n");
++ }
++ return esfq_fold_hash_classic(q, h, h2);
++}
++
++static inline void esfq_link(struct esfq_sched_data *q, esfq_index x)
++{
++ esfq_index p, n;
++ int d = q->qs[x].qlen + q->depth;
++
++ p = d;
++ n = q->dep[d].next;
++ q->dep[x].next = n;
++ q->dep[x].prev = p;
++ q->dep[p].next = q->dep[n].prev = x;
++}
++
++static inline void esfq_dec(struct esfq_sched_data *q, esfq_index x)
++{
++ esfq_index p, n;
++
++ n = q->dep[x].next;
++ p = q->dep[x].prev;
++ q->dep[p].next = n;
++ q->dep[n].prev = p;
++
++ if (n == p && q->max_depth == q->qs[x].qlen + 1)
++ q->max_depth--;
++
++ esfq_link(q, x);
++}
++
++static inline void esfq_inc(struct esfq_sched_data *q, esfq_index x)
++{
++ esfq_index p, n;
++ int d;
++
++ n = q->dep[x].next;
++ p = q->dep[x].prev;
++ q->dep[p].next = n;
++ q->dep[n].prev = p;
++ d = q->qs[x].qlen;
++ if (q->max_depth < d)
++ q->max_depth = d;
++
++ esfq_link(q, x);
++}
++
++static unsigned int esfq_drop(struct Qdisc *sch)
++{
++ struct esfq_sched_data *q = qdisc_priv(sch);
++ esfq_index d = q->max_depth;
++ struct sk_buff *skb;
++ unsigned int len;
++
++ /* Queue is full! Find the longest slot and
++ drop a packet from it */
++
++ if (d > 1) {
++ esfq_index x = q->dep[d+q->depth].next;
++ skb = q->qs[x].prev;
++ len = skb->len;
++ __skb_unlink(skb, &q->qs[x]);
++ kfree_skb(skb);
++ esfq_dec(q, x);
++ sch->q.qlen--;
++ sch->qstats.drops++;
++ return len;
++ }
++
++ if (d == 1) {
++ /* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */
++ d = q->next[q->tail];
++ q->next[q->tail] = q->next[d];
++ q->allot[q->next[d]] += q->quantum;
++ skb = q->qs[d].prev;
++ len = skb->len;
++ __skb_unlink(skb, &q->qs[d]);
++ kfree_skb(skb);
++ esfq_dec(q, d);
++ sch->q.qlen--;
++ q->ht[q->hash[d]] = q->depth;
++ sch->qstats.drops++;
++ return len;
++ }
++
++ return 0;
++}
++
++static int
++esfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
++{
++ struct esfq_sched_data *q = qdisc_priv(sch);
++ unsigned hash = esfq_hash(q, skb);
++ unsigned depth = q->depth;
++ esfq_index x;
++
++ x = q->ht[hash];
++ if (x == depth) {
++ q->ht[hash] = x = q->dep[depth].next;
++ q->hash[x] = hash;
++ }
++ __skb_queue_tail(&q->qs[x], skb);
++ esfq_inc(q, x);
++ if (q->qs[x].qlen == 1) { /* The flow is new */
++ if (q->tail == depth) { /* It is the first flow */
++ q->tail = x;
++ q->next[x] = x;
++ q->allot[x] = q->quantum;
++ } else {
++ q->next[x] = q->next[q->tail];
++ q->next[q->tail] = x;
++ q->tail = x;
++ }
++ }
++ if (++sch->q.qlen < q->limit-1) {
++ sch->bstats.bytes += skb->len;
++ sch->bstats.packets++;
++ return 0;
++ }
++
++ esfq_drop(sch);
++ return NET_XMIT_CN;
++}
++
++static int
++esfq_requeue(struct sk_buff *skb, struct Qdisc* sch)
++{
++ struct esfq_sched_data *q = qdisc_priv(sch);
++ unsigned hash = esfq_hash(q, skb);
++ unsigned depth = q->depth;
++ esfq_index x;
++
++ x = q->ht[hash];
++ if (x == depth) {
++ q->ht[hash] = x = q->dep[depth].next;
++ q->hash[x] = hash;
++ }
++ __skb_queue_head(&q->qs[x], skb);
++ esfq_inc(q, x);
++ if (q->qs[x].qlen == 1) { /* The flow is new */
++ if (q->tail == depth) { /* It is the first flow */
++ q->tail = x;
++ q->next[x] = x;
++ q->allot[x] = q->quantum;
++ } else {
++ q->next[x] = q->next[q->tail];
++ q->next[q->tail] = x;
++ q->tail = x;
++ }
++ }
++ if (++sch->q.qlen < q->limit - 1) {
++ sch->qstats.requeues++;
++ return 0;
++ }
++
++ sch->qstats.drops++;
++ esfq_drop(sch);
++ return NET_XMIT_CN;
++}
++
++
++
++
++static struct sk_buff *
++esfq_dequeue(struct Qdisc* sch)
++{
++ struct esfq_sched_data *q = qdisc_priv(sch);
++ struct sk_buff *skb;
++ unsigned depth = q->depth;
++ esfq_index a, old_a;
++
++ /* No active slots */
++ if (q->tail == depth)
++ return NULL;
++
++ a = old_a = q->next[q->tail];
++
++ /* Grab packet */
++ skb = __skb_dequeue(&q->qs[a]);
++ esfq_dec(q, a);
++ sch->q.qlen--;
++
++ /* Is the slot empty? */
++ if (q->qs[a].qlen == 0) {
++ q->ht[q->hash[a]] = depth;
++ a = q->next[a];
++ if (a == old_a) {
++ q->tail = depth;
++ return skb;
++ }
++ q->next[q->tail] = a;
++ q->allot[a] += q->quantum;
++ } else if ((q->allot[a] -= skb->len) <= 0) {
++ q->tail = a;
++ a = q->next[a];
++ q->allot[a] += q->quantum;
++ }
++
++ return skb;
++}
++
++static void
++esfq_reset(struct Qdisc* sch)
++{
++ struct sk_buff *skb;
++
++ while ((skb = esfq_dequeue(sch)) != NULL)
++ kfree_skb(skb);
++}
++
++static void esfq_perturbation(unsigned long arg)
++{
++ struct Qdisc *sch = (struct Qdisc*)arg;
++ struct esfq_sched_data *q = qdisc_priv(sch);
++
++ q->perturbation = net_random()&0x1F;
++
++ if (q->perturb_period) {
++ q->perturb_timer.expires = jiffies + q->perturb_period;
++ add_timer(&q->perturb_timer);
++ }
++}
++
++static int esfq_change(struct Qdisc *sch, struct rtattr *opt)
++{
++ struct esfq_sched_data *q = qdisc_priv(sch);
++ struct tc_esfq_qopt *ctl = RTA_DATA(opt);
++ int old_perturb = q->perturb_period;
++
++ if (opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
++ return -EINVAL;
++
++ sch_tree_lock(sch);
++ q->quantum = ctl->quantum ? : psched_mtu(sch->dev);
++ q->perturb_period = ctl->perturb_period*HZ;
++// q->hash_divisor = ctl->divisor;
++// q->tail = q->limit = q->depth = ctl->flows;
++
++ if (ctl->limit)
++ q->limit = min_t(u32, ctl->limit, q->depth);
++
++ if (ctl->hash_kind) {
++ q->hash_kind = ctl->hash_kind;
++ if (q->hash_kind != TCA_SFQ_HASH_CLASSIC)
++ q->perturb_period = 0;
++ }
++
++ // is sch_tree_lock enough to do this ?
++ while (sch->q.qlen >= q->limit-1)
++ esfq_drop(sch);
++
++ if (old_perturb)
++ del_timer(&q->perturb_timer);
++ if (q->perturb_period) {
++ q->perturb_timer.expires = jiffies + q->perturb_period;
++ add_timer(&q->perturb_timer);
++ } else {
++ q->perturbation = 0;
++ }
++ sch_tree_unlock(sch);
++ return 0;
++}
++
++static int esfq_init(struct Qdisc *sch, struct rtattr *opt)
++{
++ struct esfq_sched_data *q = qdisc_priv(sch);
++ struct tc_esfq_qopt *ctl;
++ esfq_index p = ~0UL/2;
++ int i;
++
++ if (opt && opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
++ return -EINVAL;
++
++ init_timer(&q->perturb_timer);
++ q->perturb_timer.data = (unsigned long)sch;
++ q->perturb_timer.function = esfq_perturbation;
++ q->perturbation = 0;
++ q->hash_kind = TCA_SFQ_HASH_CLASSIC;
++ q->max_depth = 0;
++ q->dyn_min = ~0U; /* maximum value for this type */
++ q->dyn_max = 0; /* dyn_min/dyn_max will be set properly upon first packet */
++ if (opt == NULL) {
++ q->quantum = psched_mtu(sch->dev);
++ q->perturb_period = 0;
++ q->hash_divisor = 1024;
++ q->tail = q->limit = q->depth = 128;
++
++ } else {
++ ctl = RTA_DATA(opt);
++ q->quantum = ctl->quantum ? : psched_mtu(sch->dev);
++ q->perturb_period = ctl->perturb_period*HZ;
++ q->hash_divisor = ctl->divisor ? : 1024;
++ q->tail = q->limit = q->depth = ctl->flows ? : 128;
++
++ if ( q->depth > p - 1 )
++ return -EINVAL;
++
++ if (ctl->limit)
++ q->limit = min_t(u32, ctl->limit, q->depth);
++
++ if (ctl->hash_kind) {
++ q->hash_kind = ctl->hash_kind;
++ }
++
++ if (q->perturb_period) {
++ q->perturb_timer.expires = jiffies + q->perturb_period;
++ add_timer(&q->perturb_timer);
++ }
++ }
++
++ q->ht = kmalloc(q->hash_divisor*sizeof(esfq_index), GFP_KERNEL);
++ if (!q->ht)
++ goto err_case;
++
++ q->dep = kmalloc((1+q->depth*2)*sizeof(struct esfq_head), GFP_KERNEL);
++ if (!q->dep)
++ goto err_case;
++ q->next = kmalloc(q->depth*sizeof(esfq_index), GFP_KERNEL);
++ if (!q->next)
++ goto err_case;
++
++ q->allot = kmalloc(q->depth*sizeof(short), GFP_KERNEL);
++ if (!q->allot)
++ goto err_case;
++ q->hash = kmalloc(q->depth*sizeof(unsigned short), GFP_KERNEL);
++ if (!q->hash)
++ goto err_case;
++ q->qs = kmalloc(q->depth*sizeof(struct sk_buff_head), GFP_KERNEL);
++ if (!q->qs)
++ goto err_case;
++
++ for (i=0; i< q->hash_divisor; i++)
++ q->ht[i] = q->depth;
++ for (i=0; i<q->depth; i++) {
++ skb_queue_head_init(&q->qs[i]);
++ q->dep[i+q->depth].next = i+q->depth;
++ q->dep[i+q->depth].prev = i+q->depth;
++ }
++
++ for (i=0; i<q->depth; i++)
++ esfq_link(q, i);
++ return 0;
++err_case:
++ del_timer(&q->perturb_timer);
++ if (q->ht)
++ kfree(q->ht);
++ if (q->dep)
++ kfree(q->dep);
++ if (q->next)
++ kfree(q->next);
++ if (q->allot)
++ kfree(q->allot);
++ if (q->hash)
++ kfree(q->hash);
++ if (q->qs)
++ kfree(q->qs);
++ return -ENOBUFS;
++}
++
++static void esfq_destroy(struct Qdisc *sch)
++{
++ struct esfq_sched_data *q = qdisc_priv(sch);
++ del_timer(&q->perturb_timer);
++ if(q->ht)
++ kfree(q->ht);
++ if(q->dep)
++ kfree(q->dep);
++ if(q->next)
++ kfree(q->next);
++ if(q->allot)
++ kfree(q->allot);
++ if(q->hash)
++ kfree(q->hash);
++ if(q->qs)
++ kfree(q->qs);
++}
++
++static int esfq_dump(struct Qdisc *sch, struct sk_buff *skb)
++{
++ struct esfq_sched_data *q = qdisc_priv(sch);
++ unsigned char *b = skb->tail;
++ struct tc_esfq_qopt opt;
++
++ opt.quantum = q->quantum;
++ opt.perturb_period = q->perturb_period/HZ;
++
++ opt.limit = q->limit;
++ opt.divisor = q->hash_divisor;
++ opt.flows = q->depth;
++ opt.hash_kind = q->hash_kind;
++
++ RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
++
++ return skb->len;
++
++rtattr_failure:
++ skb_trim(skb, b - skb->data);
++ return -1;
++}
++
++static struct Qdisc_ops esfq_qdisc_ops =
++{
++ .next = NULL,
++ .cl_ops = NULL,
++ .id = "esfq",
++ .priv_size = sizeof(struct esfq_sched_data),
++ .enqueue = esfq_enqueue,
++ .dequeue = esfq_dequeue,
++ .requeue = esfq_requeue,
++ .drop = esfq_drop,
++ .init = esfq_init,
++ .reset = esfq_reset,
++ .destroy = esfq_destroy,
++ .change = NULL, /* esfq_change - needs more work */
++ .dump = esfq_dump,
++ .owner = THIS_MODULE,
++};
++
++static int __init esfq_module_init(void)
++{
++ return register_qdisc(&esfq_qdisc_ops);
++}
++static void __exit esfq_module_exit(void)
++{
++ unregister_qdisc(&esfq_qdisc_ops);
++}
++module_init(esfq_module_init)
++module_exit(esfq_module_exit)
++MODULE_LICENSE("GPL");
diff --git a/target/linux/generic-2.6/patches/201-multiple_default_gateways.patch b/target/linux/generic-2.6/patches/201-multiple_default_gateways.patch
new file mode 100644
index 0000000000..3be34d7c63
--- /dev/null
+++ b/target/linux/generic-2.6/patches/201-multiple_default_gateways.patch
@@ -0,0 +1,1238 @@
+diff -Nur linux-2.6.17/include/linux/netfilter_ipv4/ip_nat.h linux-2.6.17-owrt/include/linux/netfilter_ipv4/ip_nat.h
+--- linux-2.6.17/include/linux/netfilter_ipv4/ip_nat.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/linux/netfilter_ipv4/ip_nat.h 2006-06-18 16:53:21.000000000 +0200
+@@ -63,6 +63,13 @@
+
+ struct ip_conntrack;
+
++/* Call input routing for SNAT-ed traffic */
++extern unsigned int ip_nat_route_input(unsigned int hooknum,
++ struct sk_buff **pskb,
++ const struct net_device *in,
++ const struct net_device *out,
++ int (*okfn)(struct sk_buff *));
++
+ /* Set up the info structure to map into this range. */
+ extern unsigned int ip_nat_setup_info(struct ip_conntrack *conntrack,
+ const struct ip_nat_range *range,
+diff -Nur linux-2.6.17/include/linux/rtnetlink.h linux-2.6.17-owrt/include/linux/rtnetlink.h
+--- linux-2.6.17/include/linux/rtnetlink.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/linux/rtnetlink.h 2006-06-18 16:53:21.000000000 +0200
+@@ -293,6 +293,8 @@
+ #define RTNH_F_DEAD 1 /* Nexthop is dead (used by multipath) */
+ #define RTNH_F_PERVASIVE 2 /* Do recursive gateway lookup */
+ #define RTNH_F_ONLINK 4 /* Gateway is forced on link */
++#define RTNH_F_SUSPECT 8 /* We don't know the real state */
++#define RTNH_F_BADSTATE (RTNH_F_DEAD | RTNH_F_SUSPECT)
+
+ /* Macros to handle hexthops */
+
+diff -Nur linux-2.6.17/include/net/flow.h linux-2.6.17-owrt/include/net/flow.h
+--- linux-2.6.17/include/net/flow.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/net/flow.h 2006-06-18 16:53:21.000000000 +0200
+@@ -19,6 +19,8 @@
+ __u32 daddr;
+ __u32 saddr;
+ __u32 fwmark;
++ __u32 lsrc;
++ __u32 gw;
+ __u8 tos;
+ __u8 scope;
+ } ip4_u;
+@@ -46,6 +48,8 @@
+ #define fl4_dst nl_u.ip4_u.daddr
+ #define fl4_src nl_u.ip4_u.saddr
+ #define fl4_fwmark nl_u.ip4_u.fwmark
++#define fl4_lsrc nl_u.ip4_u.lsrc
++#define fl4_gw nl_u.ip4_u.gw
+ #define fl4_tos nl_u.ip4_u.tos
+ #define fl4_scope nl_u.ip4_u.scope
+
+diff -Nur linux-2.6.17/include/net/ip_fib.h linux-2.6.17-owrt/include/net/ip_fib.h
+--- linux-2.6.17/include/net/ip_fib.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/net/ip_fib.h 2006-06-18 16:53:21.000000000 +0200
+@@ -195,7 +195,8 @@
+
+ static inline void fib_select_default(const struct flowi *flp, struct fib_result *res)
+ {
+- if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
++ if ((FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) ||
++ FIB_RES_NH(*res).nh_scope == RT_SCOPE_HOST)
+ ip_fib_main_table->tb_select_default(ip_fib_main_table, flp, res);
+ }
+
+@@ -207,6 +208,7 @@
+ extern int fib_lookup(const struct flowi *flp, struct fib_result *res);
+ extern struct fib_table *__fib_new_table(int id);
+ extern void fib_rule_put(struct fib_rule *r);
++extern int fib_result_table(struct fib_result *res);
+
+ static inline struct fib_table *fib_get_table(int id)
+ {
+@@ -302,4 +304,6 @@
+ extern void fib_proc_exit(void);
+ #endif
+
++extern rwlock_t fib_nhflags_lock;
++
+ #endif /* _NET_FIB_H */
+diff -Nur linux-2.6.17/include/net/route.h linux-2.6.17-owrt/include/net/route.h
+--- linux-2.6.17/include/net/route.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/net/route.h 2006-06-18 16:53:21.000000000 +0200
+@@ -117,6 +117,7 @@
+ extern int ip_route_output_key(struct rtable **, struct flowi *flp);
+ extern int ip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk, int flags);
+ extern int ip_route_input(struct sk_buff*, u32 dst, u32 src, u8 tos, struct net_device *devin);
++extern int ip_route_input_lookup(struct sk_buff*, u32 dst, u32 src, u8 tos, struct net_device *devin, u32 lsrc);
+ extern unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu);
+ extern void ip_rt_send_redirect(struct sk_buff *skb);
+
+diff -Nur linux-2.6.17/net/ipv4/fib_frontend.c linux-2.6.17-owrt/net/ipv4/fib_frontend.c
+--- linux-2.6.17/net/ipv4/fib_frontend.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/net/ipv4/fib_frontend.c 2006-06-18 16:53:21.000000000 +0200
+@@ -56,6 +56,8 @@
+ struct fib_table *ip_fib_local_table;
+ struct fib_table *ip_fib_main_table;
+
++#define FIB_RES_TABLE(r) (RT_TABLE_MAIN)
++
+ #else
+
+ #define RT_TABLE_MIN 1
+@@ -73,6 +75,7 @@
+ return tb;
+ }
+
++#define FIB_RES_TABLE(r) (fib_result_table(r))
+
+ #endif /* CONFIG_IP_MULTIPLE_TABLES */
+
+@@ -170,6 +173,9 @@
+ .tos = tos } },
+ .iif = oif };
+ struct fib_result res;
++ int table;
++ unsigned char prefixlen;
++ unsigned char scope;
+ int no_addr, rpf;
+ int ret;
+
+@@ -191,31 +197,35 @@
+ goto e_inval_res;
+ *spec_dst = FIB_RES_PREFSRC(res);
+ fib_combine_itag(itag, &res);
+-#ifdef CONFIG_IP_ROUTE_MULTIPATH
+- if (FIB_RES_DEV(res) == dev || res.fi->fib_nhs > 1)
+-#else
+ if (FIB_RES_DEV(res) == dev)
+-#endif
+ {
+ ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
+ fib_res_put(&res);
+ return ret;
+ }
++ table = FIB_RES_TABLE(&res);
++ prefixlen = res.prefixlen;
++ scope = res.scope;
+ fib_res_put(&res);
+ if (no_addr)
+ goto last_resort;
+- if (rpf)
+- goto e_inval;
+ fl.oif = dev->ifindex;
+
+ ret = 0;
+ if (fib_lookup(&fl, &res) == 0) {
+- if (res.type == RTN_UNICAST) {
++ if (res.type == RTN_UNICAST &&
++ ((table == FIB_RES_TABLE(&res) &&
++ res.prefixlen >= prefixlen && res.scope >= scope) ||
++ !rpf)) {
+ *spec_dst = FIB_RES_PREFSRC(res);
+ ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
++ fib_res_put(&res);
++ return ret;
+ }
+ fib_res_put(&res);
+ }
++ if (rpf)
++ goto e_inval;
+ return ret;
+
+ last_resort:
+@@ -589,9 +599,7 @@
+ switch (event) {
+ case NETDEV_UP:
+ fib_add_ifaddr(ifa);
+-#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ fib_sync_up(ifa->ifa_dev->dev);
+-#endif
+ rt_cache_flush(-1);
+ break;
+ case NETDEV_DOWN:
+@@ -627,9 +635,7 @@
+ for_ifa(in_dev) {
+ fib_add_ifaddr(ifa);
+ } endfor_ifa(in_dev);
+-#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ fib_sync_up(dev);
+-#endif
+ rt_cache_flush(-1);
+ break;
+ case NETDEV_DOWN:
+diff -Nur linux-2.6.17/net/ipv4/fib_hash.c linux-2.6.17-owrt/net/ipv4/fib_hash.c
+--- linux-2.6.17/net/ipv4/fib_hash.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/net/ipv4/fib_hash.c 2006-06-18 16:53:21.000000000 +0200
+@@ -277,30 +277,38 @@
+ return err;
+ }
+
+-static int fn_hash_last_dflt=-1;
+-
+ static void
+ fn_hash_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
+ {
+- int order, last_idx;
++ int order, last_idx, last_dflt, last_nhsel;
++ struct fib_alias *first_fa = NULL;
++ struct hlist_head *head;
+ struct hlist_node *node;
+ struct fib_node *f;
+ struct fib_info *fi = NULL;
+ struct fib_info *last_resort;
+ struct fn_hash *t = (struct fn_hash*)tb->tb_data;
+- struct fn_zone *fz = t->fn_zones[0];
++ struct fn_zone *fz = t->fn_zones[res->prefixlen];
++ u32 k;
+
+ if (fz == NULL)
+ return;
+
++ k = fz_key(flp->fl4_dst, fz);
++ last_dflt = -2;
++ last_nhsel = 0;
+ last_idx = -1;
+ last_resort = NULL;
+ order = -1;
+
+ read_lock(&fib_hash_lock);
+- hlist_for_each_entry(f, node, &fz->fz_hash[0], fn_hash) {
++ head = &fz->fz_hash[fn_hash(k, fz)];
++ hlist_for_each_entry(f, node, head, fn_hash) {
+ struct fib_alias *fa;
+
++ if (f->fn_key != k)
++ continue;
++
+ list_for_each_entry(fa, &f->fn_alias, fa_list) {
+ struct fib_info *next_fi = fa->fa_info;
+
+@@ -308,41 +316,52 @@
+ fa->fa_type != RTN_UNICAST)
+ continue;
+
++ if (fa->fa_tos &&
++ fa->fa_tos != flp->fl4_tos)
++ continue;
+ if (next_fi->fib_priority > res->fi->fib_priority)
+ break;
+- if (!next_fi->fib_nh[0].nh_gw ||
+- next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
+- continue;
+ fa->fa_state |= FA_S_ACCESSED;
+
+- if (fi == NULL) {
+- if (next_fi != res->fi)
+- break;
+- } else if (!fib_detect_death(fi, order, &last_resort,
+- &last_idx, &fn_hash_last_dflt)) {
++ if (!first_fa) {
++ last_dflt = fa->fa_last_dflt;
++ first_fa = fa;
++ }
++ if (fi && !fib_detect_death(fi, order, &last_resort,
++ &last_idx, &last_dflt, &last_nhsel, flp)) {
+ if (res->fi)
+ fib_info_put(res->fi);
+ res->fi = fi;
+ atomic_inc(&fi->fib_clntref);
+- fn_hash_last_dflt = order;
++ first_fa->fa_last_dflt = order;
+ goto out;
+ }
+ fi = next_fi;
+ order++;
+ }
++ break;
+ }
+
+ if (order <= 0 || fi == NULL) {
+- fn_hash_last_dflt = -1;
++ if (fi && fi->fib_nhs > 1 &&
++ fib_detect_death(fi, order, &last_resort, &last_idx,
++ &last_dflt, &last_nhsel, flp) &&
++ last_resort == fi) {
++ read_lock_bh(&fib_nhflags_lock);
++ fi->fib_nh[last_nhsel].nh_flags &= ~RTNH_F_SUSPECT;
++ read_unlock_bh(&fib_nhflags_lock);
++ }
++ if (first_fa) first_fa->fa_last_dflt = -1;
+ goto out;
+ }
+
+- if (!fib_detect_death(fi, order, &last_resort, &last_idx, &fn_hash_last_dflt)) {
++ if (!fib_detect_death(fi, order, &last_resort, &last_idx,
++ &last_dflt, &last_nhsel, flp)) {
+ if (res->fi)
+ fib_info_put(res->fi);
+ res->fi = fi;
+ atomic_inc(&fi->fib_clntref);
+- fn_hash_last_dflt = order;
++ first_fa->fa_last_dflt = order;
+ goto out;
+ }
+
+@@ -352,8 +371,11 @@
+ res->fi = last_resort;
+ if (last_resort)
+ atomic_inc(&last_resort->fib_clntref);
++ read_lock_bh(&fib_nhflags_lock);
++ last_resort->fib_nh[last_nhsel].nh_flags &= ~RTNH_F_SUSPECT;
++ read_unlock_bh(&fib_nhflags_lock);
++ first_fa->fa_last_dflt = last_idx;
+ }
+- fn_hash_last_dflt = last_idx;
+ out:
+ read_unlock(&fib_hash_lock);
+ }
+@@ -452,6 +474,7 @@
+ write_lock_bh(&fib_hash_lock);
+ fi_drop = fa->fa_info;
+ fa->fa_info = fi;
++ fa->fa_last_dflt = -1;
+ fa->fa_type = type;
+ fa->fa_scope = r->rtm_scope;
+ state = fa->fa_state;
+@@ -511,6 +534,7 @@
+ new_fa->fa_type = type;
+ new_fa->fa_scope = r->rtm_scope;
+ new_fa->fa_state = 0;
++ new_fa->fa_last_dflt = -1;
+
+ /*
+ * Insert new entry to the list.
+diff -Nur linux-2.6.17/net/ipv4/fib_lookup.h linux-2.6.17-owrt/net/ipv4/fib_lookup.h
+--- linux-2.6.17/net/ipv4/fib_lookup.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/net/ipv4/fib_lookup.h 2006-06-18 16:53:21.000000000 +0200
+@@ -9,6 +9,7 @@
+ struct list_head fa_list;
+ struct rcu_head rcu;
+ struct fib_info *fa_info;
++ int fa_last_dflt;
+ u8 fa_tos;
+ u8 fa_type;
+ u8 fa_scope;
+@@ -40,6 +41,7 @@
+ u8 tos, u32 prio);
+ extern int fib_detect_death(struct fib_info *fi, int order,
+ struct fib_info **last_resort,
+- int *last_idx, int *dflt);
++ int *last_idx, int *dflt, int *last_nhsel,
++ const struct flowi *flp);
+
+ #endif /* _FIB_LOOKUP_H */
+diff -Nur linux-2.6.17/net/ipv4/fib_rules.c linux-2.6.17-owrt/net/ipv4/fib_rules.c
+--- linux-2.6.17/net/ipv4/fib_rules.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/net/ipv4/fib_rules.c 2006-06-18 16:53:21.000000000 +0200
+@@ -296,6 +296,11 @@
+ }
+ }
+
++int fib_result_table(struct fib_result *res)
++{
++ return res->r->r_table;
++}
++
+ int fib_lookup(const struct flowi *flp, struct fib_result *res)
+ {
+ int err;
+@@ -361,7 +366,8 @@
+ void fib_select_default(const struct flowi *flp, struct fib_result *res)
+ {
+ if (res->r && res->r->r_action == RTN_UNICAST &&
+- FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) {
++ ((FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) ||
++ FIB_RES_NH(*res).nh_scope == RT_SCOPE_HOST)) {
+ struct fib_table *tb;
+ if ((tb = fib_get_table(res->r->r_table)) != NULL)
+ tb->tb_select_default(tb, flp, res);
+diff -Nur linux-2.6.17/net/ipv4/fib_semantics.c linux-2.6.17-owrt/net/ipv4/fib_semantics.c
+--- linux-2.6.17/net/ipv4/fib_semantics.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/net/ipv4/fib_semantics.c 2006-06-18 16:53:21.000000000 +0200
+@@ -55,6 +55,7 @@
+ static struct hlist_head *fib_info_laddrhash;
+ static unsigned int fib_hash_size;
+ static unsigned int fib_info_cnt;
++rwlock_t fib_nhflags_lock = RW_LOCK_UNLOCKED;
+
+ #define DEVINDEX_HASHBITS 8
+ #define DEVINDEX_HASHSIZE (1U << DEVINDEX_HASHBITS)
+@@ -190,7 +191,7 @@
+ #ifdef CONFIG_NET_CLS_ROUTE
+ nh->nh_tclassid != onh->nh_tclassid ||
+ #endif
+- ((nh->nh_flags^onh->nh_flags)&~RTNH_F_DEAD))
++ ((nh->nh_flags^onh->nh_flags)&~RTNH_F_BADSTATE))
+ return -1;
+ onh++;
+ } endfor_nexthops(fi);
+@@ -227,7 +228,7 @@
+ nfi->fib_priority == fi->fib_priority &&
+ memcmp(nfi->fib_metrics, fi->fib_metrics,
+ sizeof(fi->fib_metrics)) == 0 &&
+- ((nfi->fib_flags^fi->fib_flags)&~RTNH_F_DEAD) == 0 &&
++ ((nfi->fib_flags^fi->fib_flags)&~RTNH_F_BADSTATE) == 0 &&
+ (nfi->fib_nhs == 0 || nh_comp(fi, nfi) == 0))
+ return fi;
+ }
+@@ -319,26 +320,70 @@
+ }
+
+ int fib_detect_death(struct fib_info *fi, int order,
+- struct fib_info **last_resort, int *last_idx, int *dflt)
++ struct fib_info **last_resort, int *last_idx, int *dflt,
++ int *last_nhsel, const struct flowi *flp)
+ {
+ struct neighbour *n;
+- int state = NUD_NONE;
++ int nhsel;
++ int state;
++ struct fib_nh * nh;
++ u32 dst;
++ int flag, dead = 1;
++
++ /* change_nexthops(fi) { */
++ for (nhsel = 0, nh = fi->fib_nh; nhsel < fi->fib_nhs; nh++, nhsel++) {
++ if (flp->oif && flp->oif != nh->nh_oif)
++ continue;
++ if (flp->fl4_gw && flp->fl4_gw != nh->nh_gw && nh->nh_gw &&
++ nh->nh_scope == RT_SCOPE_LINK)
++ continue;
++ if (nh->nh_flags & RTNH_F_DEAD)
++ continue;
+
+- n = neigh_lookup(&arp_tbl, &fi->fib_nh[0].nh_gw, fi->fib_dev);
+- if (n) {
+- state = n->nud_state;
+- neigh_release(n);
+- }
+- if (state==NUD_REACHABLE)
+- return 0;
+- if ((state&NUD_VALID) && order != *dflt)
+- return 0;
+- if ((state&NUD_VALID) ||
+- (*last_idx<0 && order > *dflt)) {
+- *last_resort = fi;
+- *last_idx = order;
++ flag = 0;
++ if (nh->nh_dev->flags & IFF_NOARP) {
++ dead = 0;
++ goto setfl;
++ }
++
++ dst = nh->nh_gw;
++ if (!nh->nh_gw || nh->nh_scope != RT_SCOPE_LINK)
++ dst = flp->fl4_dst;
++
++ state = NUD_NONE;
++ n = neigh_lookup(&arp_tbl, &dst, nh->nh_dev);
++ if (n) {
++ state = n->nud_state;
++ neigh_release(n);
++ }
++ if (state==NUD_REACHABLE ||
++ ((state&NUD_VALID) && order != *dflt)) {
++ dead = 0;
++ goto setfl;
++ }
++ if (!(state&NUD_VALID))
++ flag = 1;
++ if (!dead)
++ goto setfl;
++ if ((state&NUD_VALID) ||
++ (*last_idx<0 && order >= *dflt)) {
++ *last_resort = fi;
++ *last_idx = order;
++ *last_nhsel = nhsel;
++ }
++
++ setfl:
++
++ read_lock_bh(&fib_nhflags_lock);
++ if (flag)
++ nh->nh_flags |= RTNH_F_SUSPECT;
++ else
++ nh->nh_flags &= ~RTNH_F_SUSPECT;
++ read_unlock_bh(&fib_nhflags_lock);
+ }
+- return 1;
++ /* } endfor_nexthops(fi) */
++
++ return dead;
+ }
+
+ #ifdef CONFIG_IP_ROUTE_MULTIPATH
+@@ -509,8 +554,11 @@
+ return -EINVAL;
+ if ((dev = __dev_get_by_index(nh->nh_oif)) == NULL)
+ return -ENODEV;
+- if (!(dev->flags&IFF_UP))
+- return -ENETDOWN;
++ if (!(dev->flags&IFF_UP)) {
++ if (fi->fib_protocol != RTPROT_STATIC)
++ return -ENETDOWN;
++ nh->nh_flags |= RTNH_F_DEAD;
++ }
+ nh->nh_dev = dev;
+ dev_hold(dev);
+ nh->nh_scope = RT_SCOPE_LINK;
+@@ -525,24 +573,48 @@
+ /* It is not necessary, but requires a bit of thinking */
+ if (fl.fl4_scope < RT_SCOPE_LINK)
+ fl.fl4_scope = RT_SCOPE_LINK;
+- if ((err = fib_lookup(&fl, &res)) != 0)
+- return err;
++ err = fib_lookup(&fl, &res);
+ }
+- err = -EINVAL;
+- if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
+- goto out;
+- nh->nh_scope = res.scope;
+- nh->nh_oif = FIB_RES_OIF(res);
+- if ((nh->nh_dev = FIB_RES_DEV(res)) == NULL)
+- goto out;
+- dev_hold(nh->nh_dev);
+- err = -ENETDOWN;
+- if (!(nh->nh_dev->flags & IFF_UP))
+- goto out;
+- err = 0;
++ if (err) {
++ struct in_device *in_dev;
++
++ if (err != -ENETUNREACH ||
++ fi->fib_protocol != RTPROT_STATIC)
++ return err;
++
++ in_dev = inetdev_by_index(nh->nh_oif);
++ if (in_dev == NULL ||
++ in_dev->dev->flags & IFF_UP) {
++ if (in_dev)
++ in_dev_put(in_dev);
++ return err;
++ }
++ nh->nh_flags |= RTNH_F_DEAD;
++ nh->nh_scope = RT_SCOPE_LINK;
++ nh->nh_dev = in_dev->dev;
++ dev_hold(nh->nh_dev);
++ in_dev_put(in_dev);
++ } else {
++ err = -EINVAL;
++ if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
++ goto out;
++ nh->nh_scope = res.scope;
++ nh->nh_oif = FIB_RES_OIF(res);
++ if ((nh->nh_dev = FIB_RES_DEV(res)) == NULL)
++ goto out;
++ dev_hold(nh->nh_dev);
++ if (!(nh->nh_dev->flags & IFF_UP)) {
++ if (fi->fib_protocol != RTPROT_STATIC) {
++ err = -ENETDOWN;
++ goto out;
++ }
++ nh->nh_flags |= RTNH_F_DEAD;
++ }
++ err = 0;
+ out:
+- fib_res_put(&res);
+- return err;
++ fib_res_put(&res);
++ return err;
++ }
+ } else {
+ struct in_device *in_dev;
+
+@@ -553,8 +625,11 @@
+ if (in_dev == NULL)
+ return -ENODEV;
+ if (!(in_dev->dev->flags&IFF_UP)) {
+- in_dev_put(in_dev);
+- return -ENETDOWN;
++ if (fi->fib_protocol != RTPROT_STATIC) {
++ in_dev_put(in_dev);
++ return -ENETDOWN;
++ }
++ nh->nh_flags |= RTNH_F_DEAD;
+ }
+ nh->nh_dev = in_dev->dev;
+ dev_hold(nh->nh_dev);
+@@ -892,8 +967,12 @@
+ for_nexthops(fi) {
+ if (nh->nh_flags&RTNH_F_DEAD)
+ continue;
+- if (!flp->oif || flp->oif == nh->nh_oif)
+- break;
++ if (flp->oif && flp->oif != nh->nh_oif)
++ continue;
++ if (flp->fl4_gw && flp->fl4_gw != nh->nh_gw &&
++ nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK)
++ continue;
++ break;
+ }
+ #ifdef CONFIG_IP_ROUTE_MULTIPATH
+ if (nhsel < fi->fib_nhs) {
+@@ -1199,18 +1278,29 @@
+ prev_fi = fi;
+ dead = 0;
+ change_nexthops(fi) {
+- if (nh->nh_flags&RTNH_F_DEAD)
+- dead++;
+- else if (nh->nh_dev == dev &&
+- nh->nh_scope != scope) {
+- nh->nh_flags |= RTNH_F_DEAD;
++ if (nh->nh_flags&RTNH_F_DEAD) {
++ if (fi->fib_protocol!=RTPROT_STATIC ||
++ nh->nh_dev == NULL ||
++ __in_dev_get_rtnl(nh->nh_dev) == NULL ||
++ nh->nh_dev->flags&IFF_UP)
++ dead++;
++ } else if (nh->nh_dev == dev &&
++ nh->nh_scope != scope) {
++ write_lock_bh(&fib_nhflags_lock);
+ #ifdef CONFIG_IP_ROUTE_MULTIPATH
+- spin_lock_bh(&fib_multipath_lock);
++ spin_lock(&fib_multipath_lock);
++ nh->nh_flags |= RTNH_F_DEAD;
+ fi->fib_power -= nh->nh_power;
+ nh->nh_power = 0;
+- spin_unlock_bh(&fib_multipath_lock);
++ spin_unlock(&fib_multipath_lock);
++#else
++ nh->nh_flags |= RTNH_F_DEAD;
+ #endif
+- dead++;
++ write_unlock_bh(&fib_nhflags_lock);
++ if (fi->fib_protocol!=RTPROT_STATIC ||
++ force ||
++ __in_dev_get_rtnl(dev) == NULL)
++ dead++;
+ }
+ #ifdef CONFIG_IP_ROUTE_MULTIPATH
+ if (force > 1 && nh->nh_dev == dev) {
+@@ -1229,11 +1319,8 @@
+ return ret;
+ }
+
+-#ifdef CONFIG_IP_ROUTE_MULTIPATH
+-
+ /*
+- Dead device goes up. We wake up dead nexthops.
+- It takes sense only on multipath routes.
++ Dead device goes up or new address is added. We wake up dead nexthops.
+ */
+
+ int fib_sync_up(struct net_device *dev)
+@@ -1243,8 +1330,10 @@
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct fib_nh *nh;
+- int ret;
++ struct fib_result res;
++ int ret, rep;
+
++repeat:
+ if (!(dev->flags&IFF_UP))
+ return 0;
+
+@@ -1252,6 +1341,7 @@
+ hash = fib_devindex_hashfn(dev->ifindex);
+ head = &fib_info_devhash[hash];
+ ret = 0;
++ rep = 0;
+
+ hlist_for_each_entry(nh, node, head, nh_hash) {
+ struct fib_info *fi = nh->nh_parent;
+@@ -1264,19 +1354,37 @@
+ prev_fi = fi;
+ alive = 0;
+ change_nexthops(fi) {
+- if (!(nh->nh_flags&RTNH_F_DEAD)) {
+- alive++;
++ if (!(nh->nh_flags&RTNH_F_DEAD))
+ continue;
+- }
+ if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP))
+ continue;
+ if (nh->nh_dev != dev || !__in_dev_get_rtnl(dev))
+ continue;
++ if (nh->nh_gw && fi->fib_protocol == RTPROT_STATIC) {
++ struct flowi fl = {
++ .nl_u = { .ip4_u =
++ { .daddr = nh->nh_gw,
++ .scope = nh->nh_scope } },
++ .oif = nh->nh_oif,
++ };
++ if (fib_lookup(&fl, &res) != 0)
++ continue;
++ if (res.type != RTN_UNICAST &&
++ res.type != RTN_LOCAL) {
++ fib_res_put(&res);
++ continue;
++ }
++ nh->nh_scope = res.scope;
++ fib_res_put(&res);
++ rep = 1;
++ }
+ alive++;
++#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ spin_lock_bh(&fib_multipath_lock);
+ nh->nh_power = 0;
+ nh->nh_flags &= ~RTNH_F_DEAD;
+ spin_unlock_bh(&fib_multipath_lock);
++#endif
+ } endfor_nexthops(fi)
+
+ if (alive > 0) {
+@@ -1284,10 +1392,14 @@
+ ret++;
+ }
+ }
++ if (rep)
++ goto repeat;
+
+ return ret;
+ }
+
++#ifdef CONFIG_IP_ROUTE_MULTIPATH
++
+ /*
+ The algorithm is suboptimal, but it provides really
+ fair weighted route distribution.
+@@ -1296,24 +1408,45 @@
+ void fib_select_multipath(const struct flowi *flp, struct fib_result *res)
+ {
+ struct fib_info *fi = res->fi;
+- int w;
++ int w, alive;
+
+ spin_lock_bh(&fib_multipath_lock);
++ if (flp->oif) {
++ int sel = -1;
++ w = -1;
++ change_nexthops(fi) {
++ if (flp->oif != nh->nh_oif)
++ continue;
++ if (flp->fl4_gw && flp->fl4_gw != nh->nh_gw &&
++ nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK)
++ continue;
++ if (!(nh->nh_flags&RTNH_F_BADSTATE)) {
++ if (nh->nh_power > w) {
++ w = nh->nh_power;
++ sel = nhsel;
++ }
++ }
++ } endfor_nexthops(fi);
++ if (sel >= 0) {
++ spin_unlock_bh(&fib_multipath_lock);
++ res->nh_sel = sel;
++ return;
++ }
++ goto last_resort;
++ }
++
++repeat:
+ if (fi->fib_power <= 0) {
+ int power = 0;
+ change_nexthops(fi) {
+- if (!(nh->nh_flags&RTNH_F_DEAD)) {
++ if (!(nh->nh_flags&RTNH_F_BADSTATE)) {
+ power += nh->nh_weight;
+ nh->nh_power = nh->nh_weight;
+ }
+ } endfor_nexthops(fi);
+ fi->fib_power = power;
+- if (power <= 0) {
+- spin_unlock_bh(&fib_multipath_lock);
+- /* Race condition: route has just become dead. */
+- res->nh_sel = 0;
+- return;
+- }
++ if (power <= 0)
++ goto last_resort;
+ }
+
+
+@@ -1323,20 +1456,40 @@
+
+ w = jiffies % fi->fib_power;
+
++ alive = 0;
+ change_nexthops(fi) {
+- if (!(nh->nh_flags&RTNH_F_DEAD) && nh->nh_power) {
++ if (!(nh->nh_flags&RTNH_F_BADSTATE) && nh->nh_power) {
+ if ((w -= nh->nh_power) <= 0) {
+ nh->nh_power--;
+ fi->fib_power--;
+- res->nh_sel = nhsel;
+ spin_unlock_bh(&fib_multipath_lock);
++ res->nh_sel = nhsel;
+ return;
+ }
++ alive = 1;
++ }
++ } endfor_nexthops(fi);
++ if (alive) {
++ fi->fib_power = 0;
++ goto repeat;
++ }
++
++last_resort:
++
++ for_nexthops(fi) {
++ if (!(nh->nh_flags&RTNH_F_DEAD)) {
++ if (flp->oif && flp->oif != nh->nh_oif)
++ continue;
++ if (flp->fl4_gw && flp->fl4_gw != nh->nh_gw &&
++ nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK)
++ continue;
++ spin_unlock_bh(&fib_multipath_lock);
++ res->nh_sel = nhsel;
++ return;
+ }
+ } endfor_nexthops(fi);
+
+ /* Race condition: route has just become dead. */
+- res->nh_sel = 0;
+ spin_unlock_bh(&fib_multipath_lock);
+ }
+ #endif
+diff -Nur linux-2.6.17/net/ipv4/netfilter/ip_nat_core.c linux-2.6.17-owrt/net/ipv4/netfilter/ip_nat_core.c
+--- linux-2.6.17/net/ipv4/netfilter/ip_nat_core.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/net/ipv4/netfilter/ip_nat_core.c 2006-06-18 16:53:21.000000000 +0200
+@@ -589,6 +589,53 @@
+ EXPORT_SYMBOL_GPL(ip_nat_port_range_to_nfattr);
+ #endif
+
++unsigned int
++ip_nat_route_input(unsigned int hooknum,
++ struct sk_buff **pskb,
++ const struct net_device *in,
++ const struct net_device *out,
++ int (*okfn)(struct sk_buff *))
++{
++ struct sk_buff *skb = *pskb;
++ struct iphdr *iph;
++ struct ip_conntrack *conn;
++ enum ip_conntrack_info ctinfo;
++ enum ip_conntrack_dir dir;
++ unsigned long statusbit;
++ u32 saddr;
++
++ if (!(conn = ip_conntrack_get(skb, &ctinfo)))
++ return NF_ACCEPT;
++
++ if (!(conn->status & IPS_NAT_DONE_MASK))
++ return NF_ACCEPT;
++ dir = CTINFO2DIR(ctinfo);
++ statusbit = IPS_SRC_NAT;
++ if (dir == IP_CT_DIR_REPLY)
++ statusbit ^= IPS_NAT_MASK;
++ if (!(conn->status & statusbit))
++ return NF_ACCEPT;
++
++ if (skb->dst)
++ return NF_ACCEPT;
++
++ if (skb->len < sizeof(struct iphdr))
++ return NF_ACCEPT;
++
++ /* use daddr in other direction as masquerade address (lsrc) */
++ iph = skb->nh.iph;
++ saddr = conn->tuplehash[!dir].tuple.dst.ip;
++ if (saddr == iph->saddr)
++ return NF_ACCEPT;
++
++ if (ip_route_input_lookup(skb, iph->daddr, iph->saddr, iph->tos,
++ skb->dev, saddr))
++ return NF_DROP;
++
++ return NF_ACCEPT;
++}
++EXPORT_SYMBOL_GPL(ip_nat_route_input);
++
+ static int __init ip_nat_init(void)
+ {
+ size_t i;
+diff -Nur linux-2.6.17/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.17-owrt/net/ipv4/netfilter/ip_nat_standalone.c
+--- linux-2.6.17/net/ipv4/netfilter/ip_nat_standalone.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/net/ipv4/netfilter/ip_nat_standalone.c 2006-06-18 17:12:03.000000000 +0200
+@@ -334,6 +334,14 @@
+ .hooknum = NF_IP_LOCAL_OUT,
+ .priority = NF_IP_PRI_NAT_DST,
+ },
++ /* Before routing, route before mangling */
++ {
++ .hook = ip_nat_route_input,
++ .owner = THIS_MODULE,
++ .pf = PF_INET,
++ .hooknum = NF_IP_PRE_ROUTING,
++ .priority = NF_IP_PRI_LAST-1,
++ },
+ /* After packet filtering, change source */
+ {
+ .hook = ip_nat_fn,
+diff -Nur linux-2.6.17/net/ipv4/netfilter/ipt_MASQUERADE.c linux-2.6.17-owrt/net/ipv4/netfilter/ipt_MASQUERADE.c
+--- linux-2.6.17/net/ipv4/netfilter/ipt_MASQUERADE.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/net/ipv4/netfilter/ipt_MASQUERADE.c 2006-06-18 16:53:21.000000000 +0200
+@@ -88,13 +88,31 @@
+ return NF_ACCEPT;
+
+ mr = targinfo;
+- rt = (struct rtable *)(*pskb)->dst;
+- newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE);
+- if (!newsrc) {
+- printk("MASQUERADE: %s ate my IP address\n", out->name);
+- return NF_DROP;
++
++ {
++ struct flowi fl = { .nl_u = { .ip4_u =
++ { .daddr = (*pskb)->nh.iph->daddr,
++ .tos = (RT_TOS((*pskb)->nh.iph->tos) |
++ RTO_CONN),
++ .gw = ((struct rtable *) (*pskb)->dst)->rt_gateway,
++#ifdef CONFIG_IP_ROUTE_FWMARK
++ .fwmark = (*pskb)->nfmark
++#endif
++ } },
++ .oif = out->ifindex };
++ if (ip_route_output_key(&rt, &fl) != 0) {
++ /* Funky routing can do this. */
++ if (net_ratelimit())
++ printk("MASQUERADE:"
++ " No route: Rusty's brain broke!\n");
++ return NF_DROP;
++ }
+ }
+
++ newsrc = rt->rt_src;
++ DEBUGP("newsrc = %u.%u.%u.%u\n", NIPQUAD(newsrc));
++ ip_rt_put(rt);
++
+ write_lock_bh(&masq_lock);
+ ct->nat.masq_index = out->ifindex;
+ write_unlock_bh(&masq_lock);
+diff -Nur linux-2.6.17/net/ipv4/route.c linux-2.6.17-owrt/net/ipv4/route.c
+--- linux-2.6.17/net/ipv4/route.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/net/ipv4/route.c 2006-06-18 16:53:21.000000000 +0200
+@@ -1195,6 +1195,7 @@
+
+ /* Gateway is different ... */
+ rt->rt_gateway = new_gw;
++ if (rt->fl.fl4_gw) rt->fl.fl4_gw = new_gw;
+
+ /* Redirect received -> path was valid */
+ dst_confirm(&rth->u.dst);
+@@ -1626,6 +1627,7 @@
+ rth->fl.fl4_fwmark= skb->nfmark;
+ #endif
+ rth->fl.fl4_src = saddr;
++ rth->fl.fl4_lsrc = 0;
+ rth->rt_src = saddr;
+ #ifdef CONFIG_NET_CLS_ROUTE
+ rth->u.dst.tclassid = itag;
+@@ -1636,6 +1638,7 @@
+ dev_hold(rth->u.dst.dev);
+ rth->idev = in_dev_get(rth->u.dst.dev);
+ rth->fl.oif = 0;
++ rth->fl.fl4_gw = 0;
+ rth->rt_gateway = daddr;
+ rth->rt_spec_dst= spec_dst;
+ rth->rt_type = RTN_MULTICAST;
+@@ -1700,7 +1703,7 @@
+ struct fib_result* res,
+ struct in_device *in_dev,
+ u32 daddr, u32 saddr, u32 tos,
+- struct rtable **result)
++ u32 lsrc, struct rtable **result)
+ {
+
+ struct rtable *rth;
+@@ -1733,6 +1736,7 @@
+ flags |= RTCF_DIRECTSRC;
+
+ if (out_dev == in_dev && err && !(flags & (RTCF_NAT | RTCF_MASQ)) &&
++ !lsrc &&
+ (IN_DEV_SHARED_MEDIA(out_dev) ||
+ inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res))))
+ flags |= RTCF_DOREDIRECT;
+@@ -1772,6 +1776,7 @@
+ #endif
+ rth->fl.fl4_src = saddr;
+ rth->rt_src = saddr;
++ rth->fl.fl4_lsrc = lsrc;
+ rth->rt_gateway = daddr;
+ rth->rt_iif =
+ rth->fl.iif = in_dev->dev->ifindex;
+@@ -1779,6 +1784,7 @@
+ dev_hold(rth->u.dst.dev);
+ rth->idev = in_dev_get(rth->u.dst.dev);
+ rth->fl.oif = 0;
++ rth->fl.fl4_gw = 0;
+ rth->rt_spec_dst= spec_dst;
+
+ rth->u.dst.input = ip_forward;
+@@ -1800,19 +1806,20 @@
+ struct fib_result* res,
+ const struct flowi *fl,
+ struct in_device *in_dev,
+- u32 daddr, u32 saddr, u32 tos)
++ u32 daddr, u32 saddr, u32 tos, u32 lsrc)
+ {
+ struct rtable* rth = NULL;
+ int err;
+ unsigned hash;
+
++ fib_select_default(fl, res);
+ #ifdef CONFIG_IP_ROUTE_MULTIPATH
+- if (res->fi && res->fi->fib_nhs > 1 && fl->oif == 0)
++ if (res->fi && res->fi->fib_nhs > 1)
+ fib_select_multipath(fl, res);
+ #endif
+
+ /* create a routing cache entry */
+- err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, &rth);
++ err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, lsrc, &rth);
+ if (err)
+ return err;
+
+@@ -1825,7 +1832,7 @@
+ struct fib_result* res,
+ const struct flowi *fl,
+ struct in_device *in_dev,
+- u32 daddr, u32 saddr, u32 tos)
++ u32 daddr, u32 saddr, u32 tos, u32 lsrc)
+ {
+ #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ struct rtable* rth = NULL, *rtres;
+@@ -1841,7 +1848,7 @@
+ /* distinguish between multipath and singlepath */
+ if (hopcount < 2)
+ return ip_mkroute_input_def(skb, res, fl, in_dev, daddr,
+- saddr, tos);
++ saddr, tos, 0);
+
+ /* add all alternatives to the routing cache */
+ for (hop = 0; hop < hopcount; hop++) {
+@@ -1853,7 +1860,7 @@
+
+ /* create a routing cache entry */
+ err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos,
+- &rth);
++ 0, &rth);
+ if (err)
+ return err;
+
+@@ -1873,7 +1880,7 @@
+ skb->dst = &rtres->u.dst;
+ return err;
+ #else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
+- return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos);
++ return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos, lsrc);
+ #endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
+ }
+
+@@ -1889,20 +1896,20 @@
+ */
+
+ static int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
+- u8 tos, struct net_device *dev)
++ u8 tos, struct net_device *dev, u32 lsrc)
+ {
+ struct fib_result res;
+ struct in_device *in_dev = in_dev_get(dev);
+ struct flowi fl = { .nl_u = { .ip4_u =
+ { .daddr = daddr,
+- .saddr = saddr,
++ .saddr = lsrc? : saddr,
+ .tos = tos,
+ .scope = RT_SCOPE_UNIVERSE,
+ #ifdef CONFIG_IP_ROUTE_FWMARK
+ .fwmark = skb->nfmark
+ #endif
+ } },
+- .iif = dev->ifindex };
++ .iif = lsrc? loopback_dev.ifindex : dev->ifindex };
+ unsigned flags = 0;
+ u32 itag = 0;
+ struct rtable * rth;
+@@ -1935,6 +1942,12 @@
+ if (BADCLASS(daddr) || ZERONET(daddr) || LOOPBACK(daddr))
+ goto martian_destination;
+
++ if (lsrc) {
++ if (MULTICAST(lsrc) || BADCLASS(lsrc) ||
++ ZERONET(lsrc) || LOOPBACK(lsrc))
++ goto e_inval;
++ }
++
+ /*
+ * Now we are ready to route packet.
+ */
+@@ -1944,6 +1957,10 @@
+ goto no_route;
+ }
+ free_res = 1;
++ if (lsrc && res.type != RTN_UNICAST && res.type != RTN_NAT)
++ goto e_inval;
++ fl.iif = dev->ifindex;
++ fl.fl4_src = saddr;
+
+ RT_CACHE_STAT_INC(in_slow_tot);
+
+@@ -1968,7 +1985,7 @@
+ if (res.type != RTN_UNICAST)
+ goto martian_destination;
+
+- err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos);
++ err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos, lsrc);
+ if (err == -ENOBUFS)
+ goto e_nobufs;
+ if (err == -EINVAL)
+@@ -1983,6 +2000,8 @@
+ brd_input:
+ if (skb->protocol != htons(ETH_P_IP))
+ goto e_inval;
++ if (lsrc)
++ goto e_inval;
+
+ if (ZERONET(saddr))
+ spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
+@@ -2025,6 +2044,7 @@
+ rth->u.dst.dev = &loopback_dev;
+ dev_hold(rth->u.dst.dev);
+ rth->idev = in_dev_get(rth->u.dst.dev);
++ rth->fl.fl4_gw = 0;
+ rth->rt_gateway = daddr;
+ rth->rt_spec_dst= spec_dst;
+ rth->u.dst.input= ip_local_deliver;
+@@ -2074,8 +2094,9 @@
+ goto e_inval;
+ }
+
+-int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
+- u8 tos, struct net_device *dev)
++static inline int
++ip_route_input_cached(struct sk_buff *skb, u32 daddr, u32 saddr,
++ u8 tos, struct net_device *dev, u32 lsrc)
+ {
+ struct rtable * rth;
+ unsigned hash;
+@@ -2090,6 +2111,7 @@
+ if (rth->fl.fl4_dst == daddr &&
+ rth->fl.fl4_src == saddr &&
+ rth->fl.iif == iif &&
++ rth->fl.fl4_lsrc == lsrc &&
+ rth->fl.oif == 0 &&
+ #ifdef CONFIG_IP_ROUTE_FWMARK
+ rth->fl.fl4_fwmark == skb->nfmark &&
+@@ -2138,7 +2160,19 @@
+ rcu_read_unlock();
+ return -EINVAL;
+ }
+- return ip_route_input_slow(skb, daddr, saddr, tos, dev);
++ return ip_route_input_slow(skb, daddr, saddr, tos, dev, lsrc);
++}
++
++int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
++ u8 tos, struct net_device *dev)
++{
++ return ip_route_input_cached(skb, daddr, saddr, tos, dev, 0);
++}
++
++int ip_route_input_lookup(struct sk_buff *skb, u32 daddr, u32 saddr,
++ u8 tos, struct net_device *dev, u32 lsrc)
++{
++ return ip_route_input_cached(skb, daddr, saddr, tos, dev, lsrc);
+ }
+
+ static inline int __mkroute_output(struct rtable **result,
+@@ -2217,6 +2251,7 @@
+ rth->fl.fl4_tos = tos;
+ rth->fl.fl4_src = oldflp->fl4_src;
+ rth->fl.oif = oldflp->oif;
++ rth->fl.fl4_gw = oldflp->fl4_gw;
+ #ifdef CONFIG_IP_ROUTE_FWMARK
+ rth->fl.fl4_fwmark= oldflp->fl4_fwmark;
+ #endif
+@@ -2361,6 +2396,7 @@
+ struct flowi fl = { .nl_u = { .ip4_u =
+ { .daddr = oldflp->fl4_dst,
+ .saddr = oldflp->fl4_src,
++ .gw = oldflp->fl4_gw,
+ .tos = tos & IPTOS_RT_MASK,
+ .scope = ((tos & RTO_ONLINK) ?
+ RT_SCOPE_LINK :
+@@ -2466,6 +2502,7 @@
+ dev_out = &loopback_dev;
+ dev_hold(dev_out);
+ fl.oif = loopback_dev.ifindex;
++ fl.fl4_gw = 0;
+ res.type = RTN_LOCAL;
+ flags |= RTCF_LOCAL;
+ goto make_route;
+@@ -2473,7 +2510,7 @@
+
+ if (fib_lookup(&fl, &res)) {
+ res.fi = NULL;
+- if (oldflp->oif) {
++ if (oldflp->oif && dev_out->flags & IFF_UP) {
+ /* Apparently, routing tables are wrong. Assume,
+ that the destination is on link.
+
+@@ -2513,6 +2550,7 @@
+ dev_out = &loopback_dev;
+ dev_hold(dev_out);
+ fl.oif = dev_out->ifindex;
++ fl.fl4_gw = 0;
+ if (res.fi)
+ fib_info_put(res.fi);
+ res.fi = NULL;
+@@ -2520,13 +2558,12 @@
+ goto make_route;
+ }
+
++ if (res.type == RTN_UNICAST)
++ fib_select_default(&fl, &res);
+ #ifdef CONFIG_IP_ROUTE_MULTIPATH
+- if (res.fi->fib_nhs > 1 && fl.oif == 0)
++ if (res.fi->fib_nhs > 1)
+ fib_select_multipath(&fl, &res);
+- else
+ #endif
+- if (!res.prefixlen && res.type == RTN_UNICAST && !fl.oif)
+- fib_select_default(&fl, &res);
+
+ if (!fl.fl4_src)
+ fl.fl4_src = FIB_RES_PREFSRC(res);
+@@ -2563,6 +2600,7 @@
+ rth->fl.fl4_src == flp->fl4_src &&
+ rth->fl.iif == 0 &&
+ rth->fl.oif == flp->oif &&
++ rth->fl.fl4_gw == flp->fl4_gw &&
+ #ifdef CONFIG_IP_ROUTE_FWMARK
+ rth->fl.fl4_fwmark == flp->fl4_fwmark &&
+ #endif
+@@ -3199,3 +3237,4 @@
+ EXPORT_SYMBOL(__ip_select_ident);
+ EXPORT_SYMBOL(ip_route_input);
+ EXPORT_SYMBOL(ip_route_output_key);
++EXPORT_SYMBOL(ip_route_input_lookup);
diff --git a/target/linux/generic-2.6/patches/202-mips-freestanding.patch b/target/linux/generic-2.6/patches/202-mips-freestanding.patch
new file mode 100644
index 0000000000..04412619d7
--- /dev/null
+++ b/target/linux/generic-2.6/patches/202-mips-freestanding.patch
@@ -0,0 +1,12 @@
+--- linux-2.6.17/arch/mips/Makefile 2006-06-19 15:12:09.000000000 -0700
++++ linux-2.6.17/arch/mips/Makefile 2006-06-19 15:11:59.000000000 -0700
+@@ -602,6 +602,9 @@
+ core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/tx4938/common/
+ load-$(CONFIG_TOSHIBA_RBTX4938) += 0xffffffff80100000
+
++# temporary until string.h is fixed
++cflags-y += -ffreestanding
++
+ cflags-y += -Iinclude/asm-mips/mach-generic
+ drivers-$(CONFIG_PCI) += arch/mips/pci/
+
diff --git a/target/linux/generic-2.6/patches/203-fix_initrd_duplication.patch b/target/linux/generic-2.6/patches/203-fix_initrd_duplication.patch
new file mode 100644
index 0000000000..4cef893003
--- /dev/null
+++ b/target/linux/generic-2.6/patches/203-fix_initrd_duplication.patch
@@ -0,0 +1,13 @@
+diff -Nurb linux-2.6.17/usr/Makefile linux-2.6.17/usr/Makefile
+--- linux-2.6.17/usr/Makefile 2006-06-20 11:51:27.000000000 -0700
++++ linux-2.6.17/usr/Makefile 2006-06-20 11:51:34.000000000 -0700
+@@ -21,8 +21,7 @@
+ $(CONFIG_INITRAMFS_SOURCE),-d)
+ ramfs-args := \
+ $(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \
+- $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) \
+- $(ramfs-input)
++ $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID))
+
+ # .initramfs_data.cpio.gz.d is used to identify all files included
+ # in initramfs and to detect if any files are added/removed.
diff --git a/target/linux/generic-2.6/patches/204-jffs2_eofdetect.patch b/target/linux/generic-2.6/patches/204-jffs2_eofdetect.patch
new file mode 100644
index 0000000000..9f248c93dd
--- /dev/null
+++ b/target/linux/generic-2.6/patches/204-jffs2_eofdetect.patch
@@ -0,0 +1,58 @@
+diff -urN linux.old/fs/jffs2/build.c linux.dev/fs/jffs2/build.c
+--- linux.old/fs/jffs2/build.c 2006-06-18 03:49:35.000000000 +0200
++++ linux.dev/fs/jffs2/build.c 2006-06-23 21:46:48.000000000 +0200
+@@ -107,6 +107,17 @@
+ dbg_fsbuild("scanned flash completely\n");
+ jffs2_dbg_dump_block_lists_nolock(c);
+
++ if (c->flags & (1 << 7)) {
++ printk("%s(): unlocking the mtd device... ", __func__);
++ if (c->mtd->unlock)
++ c->mtd->unlock(c->mtd, 0, c->mtd->size);
++ printk("done.\n");
++
++ printk("%s(): erasing all blocks after the end marker... ", __func__);
++ jffs2_erase_pending_blocks(c, -1);
++ printk("done.\n");
++ }
++
+ dbg_fsbuild("pass 1 starting\n");
+ c->flags |= JFFS2_SB_FLAG_BUILDING;
+ /* Now scan the directory tree, increasing nlink according to every dirent found. */
+diff -urN linux.old/fs/jffs2/scan.c linux.dev/fs/jffs2/scan.c
+--- linux.old/fs/jffs2/scan.c 2006-06-23 21:39:38.000000000 +0200
++++ linux.dev/fs/jffs2/scan.c 2006-06-23 21:42:18.000000000 +0200
+@@ -119,9 +119,12 @@
+
+ /* reset summary info for next eraseblock scan */
+ jffs2_sum_reset_collected(s);
+-
+- ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
+- buf_size, s);
++
++ if (c->flags & (1 << 7))
++ ret = BLK_STATE_ALLFF;
++ else
++ ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
++ buf_size, s);
+
+ if (ret < 0)
+ goto out;
+@@ -389,6 +392,17 @@
+ return err;
+ }
+
++ if ((buf[0] == 0xde) &&
++ (buf[1] == 0xad) &&
++ (buf[2] == 0xc0) &&
++ (buf[3] == 0xde)) {
++ /* end of filesystem. erase everything after this point */
++ printk("%s(): End of filesystem marker found at 0x%x\n", __func__, jeb->offset);
++ c->flags |= (1 << 7);
++
++ return BLK_STATE_ALLFF;
++ }
++
+ /* We temporarily use 'ofs' as a pointer into the buffer/jeb */
+ ofs = 0;
+
diff --git a/target/linux/generic-2.6/patches/205-block2mtd_fix.patch b/target/linux/generic-2.6/patches/205-block2mtd_fix.patch
new file mode 100644
index 0000000000..9aaffc59ef
--- /dev/null
+++ b/target/linux/generic-2.6/patches/205-block2mtd_fix.patch
@@ -0,0 +1,235 @@
+diff -urN linux.old/drivers/mtd/devices/block2mtd.c linux.dev/drivers/mtd/devices/block2mtd.c
+--- linux.old/drivers/mtd/devices/block2mtd.c 2006-07-29 19:53:54.000000000 +0200
++++ linux.dev/drivers/mtd/devices/block2mtd.c 2006-07-29 19:47:03.000000000 +0200
+@@ -4,11 +4,10 @@
+ * block2mtd.c - create an mtd from a block device
+ *
+ * Copyright (C) 2001,2002 Simon Evans <spse@secret.org.uk>
+- * Copyright (C) 2004,2005 Jörn Engel <joern@wh.fh-wedel.de>
++ * Copyright (C) 2004-2006 Jörn Engel <joern@wh.fh-wedel.de>
+ *
+ * Licence: GPL
+ */
+-#include <linux/config.h>
+ #include <linux/module.h>
+ #include <linux/fs.h>
+ #include <linux/blkdev.h>
+@@ -19,6 +18,7 @@ #include <linux/init.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/buffer_head.h>
+ #include <linux/mutex.h>
++#include <linux/mount.h>
+
+ #define VERSION "$Revision: 1.30 $"
+
+@@ -62,10 +61,8 @@
+ read_lock_irq(&mapping->tree_lock);
+ for (i = 0; i < PAGE_READAHEAD; i++) {
+ pagei = index + i;
+- if (pagei > end_index) {
+- INFO("Overrun end of disk in cache readahead\n");
++ if (pagei > end_index)
+ break;
+- }
+ page = radix_tree_lookup(&mapping->page_tree, pagei);
+ if (page && (!i))
+ break;
+@@ -237,6 +237,8 @@ static int _block2mtd_write(struct block
+ }
+ return 0;
+ }
++
++
+ static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+ {
+@@ -300,6 +302,19 @@ static struct block2mtd_dev *add_device(
+
+ /* Get a handle on the device */
+ bdev = open_bdev_excl(devname, O_RDWR, NULL);
++#ifndef MODULE
++ if (IS_ERR(bdev)) {
++
++ /* We might not have rootfs mounted at this point. Try
++ to resolve the device name by other means. */
++
++ dev_t dev = name_to_dev_t(devname);
++ if (dev != 0) {
++ bdev = open_by_devnum(dev, FMODE_WRITE | FMODE_READ);
++ }
++ }
++#endif
++
+ if (IS_ERR(bdev)) {
+ ERROR("error: cannot open device %s", devname);
+ goto devinit_err;
+@@ -331,7 +347,6 @@ static struct block2mtd_dev *add_device(
+ dev->mtd.writev = default_mtd_writev;
+ dev->mtd.sync = block2mtd_sync;
+ dev->mtd.read = block2mtd_read;
+- dev->mtd.readv = default_mtd_readv;
+ dev->mtd.priv = dev;
+ dev->mtd.owner = THIS_MODULE;
+
+@@ -351,6 +366,12 @@ devinit_err:
+ }
+
+
++/* This function works similar to reguler strtoul. In addition, it
++ * allows some suffixes for a more human-readable number format:
++ * ki, Ki, kiB, KiB - multiply result with 1024
++ * Mi, MiB - multiply result with 1024^2
++ * Gi, GiB - multiply result with 1024^3
++ */
+ static int ustrtoul(const char *cp, char **endp, unsigned int base)
+ {
+ unsigned long result = simple_strtoul(cp, endp, base);
+@@ -359,11 +380,16 @@ static int ustrtoul(const char *cp, char
+ result *= 1024;
+ case 'M':
+ result *= 1024;
++ case 'K':
+ case 'k':
+ result *= 1024;
+ /* By dwmw2 editorial decree, "ki", "Mi" or "Gi" are to be used. */
+- if ((*endp)[1] == 'i')
+- (*endp) += 2;
++ if ((*endp)[1] == 'i') {
++ if ((*endp)[2] == 'B')
++ (*endp) += 3;
++ else
++ (*endp) += 2;
++ }
+ }
+ return result;
+ }
+@@ -383,26 +409,6 @@ static int parse_num(size_t *num, const
+ }
+
+
+-static int parse_name(char **pname, const char *token, size_t limit)
+-{
+- size_t len;
+- char *name;
+-
+- len = strlen(token) + 1;
+- if (len > limit)
+- return -ENOSPC;
+-
+- name = kmalloc(len, GFP_KERNEL);
+- if (!name)
+- return -ENOMEM;
+-
+- strcpy(name, token);
+-
+- *pname = name;
+- return 0;
+-}
+-
+-
+ static inline void kill_final_newline(char *str)
+ {
+ char *newline = strrchr(str, '\n');
+@@ -416,9 +422,16 @@ #define parse_err(fmt, args...) do { \
+ return 0; \
+ } while (0)
+
+-static int block2mtd_setup(const char *val, struct kernel_param *kp)
++#ifndef MODULE
++static int block2mtd_init_called = 0;
++static __initdata char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */
++#endif
++
++
++static int block2mtd_setup2(const char *val)
+ {
+- char buf[80+12], *str=buf; /* 80 for device, 12 for erase size */
++ char buf[80 + 12]; /* 80 for device, 12 for erase size */
++ char *str = buf;
+ char *token[2];
+ char *name;
+ size_t erase_size = PAGE_SIZE;
+@@ -430,7 +443,7 @@ static int block2mtd_setup(const char *v
+ strcpy(str, val);
+ kill_final_newline(str);
+
+- for (i=0; i<2; i++)
++ for (i = 0; i < 2; i++)
+ token[i] = strsep(&str, ",");
+
+ if (str)
+@@ -439,18 +452,16 @@ static int block2mtd_setup(const char *v
+ if (!token[0])
+ parse_err("no argument");
+
+- ret = parse_name(&name, token[0], 80);
+- if (ret == -ENOMEM)
+- parse_err("out of memory");
+- if (ret == -ENOSPC)
+- parse_err("name too long");
+- if (ret)
+- return 0;
++ name = token[0];
++ if (strlen(name) + 1 > 80)
++ parse_err("device name too long");
+
+ if (token[1]) {
+ ret = parse_num(&erase_size, token[1]);
+- if (ret)
++ if (ret) {
++ kfree(name);
+ parse_err("illegal erase size");
++ }
+ }
+
+ add_device(name, erase_size);
+@@ -459,13 +470,48 @@ static int block2mtd_setup(const char *v
+ }
+
+
++static int block2mtd_setup(const char *val, struct kernel_param *kp)
++{
++#ifdef MODULE
++ return block2mtd_setup2(val);
++#else
++ /* If more parameters are later passed in via
++ /sys/module/block2mtd/parameters/block2mtd
++ and block2mtd_init() has already been called,
++ we can parse the argument now. */
++
++ if (block2mtd_init_called)
++ return block2mtd_setup2(val);
++
++ /* During early boot stage, we only save the parameters
++ here. We must parse them later: if the param passed
++ from kernel boot command line, block2mtd_setup() is
++ called so early that it is not possible to resolve
++ the device (even kmalloc() fails). Deter that work to
++ block2mtd_setup2(). */
++
++ strlcpy(block2mtd_paramline, val, sizeof(block2mtd_paramline));
++
++ return 0;
++#endif
++}
++
++
+ module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
+ MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
+
+ static int __init block2mtd_init(void)
+ {
++ int ret = 0;
+ INFO("version " VERSION);
+- return 0;
++
++#ifndef MODULE
++ if (strlen(block2mtd_paramline))
++ ret = block2mtd_setup2(block2mtd_paramline);
++ block2mtd_init_called = 1;
++#endif
++
++ return ret;
+ }
+
+
diff --git a/target/linux/generic-2.6/patches/206-pppoe_mtu_fix.patch b/target/linux/generic-2.6/patches/206-pppoe_mtu_fix.patch
new file mode 100644
index 0000000000..1ad8220f8f
--- /dev/null
+++ b/target/linux/generic-2.6/patches/206-pppoe_mtu_fix.patch
@@ -0,0 +1,12 @@
+--- linux-2.6.17/drivers/net/pppoe.c.old 2006-10-10 13:47:56.000000000 +0200
++++ linux-2.6.17/drivers/net/pppoe.c 2006-10-10 13:52:02.000000000 +0200
+@@ -600,6 +600,9 @@
+ po->chan.hdrlen = (sizeof(struct pppoe_hdr) +
+ dev->hard_header_len);
+
++ if (po->chan.mtu > dev->mtu - sizeof(struct pppoe_hdr))
++ po->chan.mtu = dev->mtu - sizeof(struct pppoe_hdr);
++
+ po->chan.private = sk;
+ po->chan.ops = &pppoe_chan_ops;
+
diff --git a/target/linux/magicbox-2.6/Makefile b/target/linux/magicbox-2.6/Makefile
new file mode 100644
index 0000000000..7ffd11c668
--- /dev/null
+++ b/target/linux/magicbox-2.6/Makefile
@@ -0,0 +1,22 @@
+#
+# 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
+
+LINUX_VERSION:=2.6.17
+LINUX_RELEASE:=1
+LINUX_KERNEL_MD5SUM:=37ddefe96625502161f075b9d907f21e
+
+include ./config
+include $(INCLUDE_DIR)/kernel.mk
+include $(INCLUDE_DIR)/kernel-build.mk
+
+$(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked
+ [ -d ../generic-$(KERNEL)/patches ] && $(PATCH) $(LINUX_DIR) ../generic-$(KERNEL)/patches $(MAKE_TRACE)
+ [ -d ./patches ] && $(PATCH) $(LINUX_DIR) ./patches $(MAKE_TRACE)
+ @$(CP) config $(LINUX_DIR)/.config
+ touch $@
+
diff --git a/target/linux/magicbox-2.6/config b/target/linux/magicbox-2.6/config
new file mode 100644
index 0000000000..1f7f591bb3
--- /dev/null
+++ b/target/linux/magicbox-2.6/config
@@ -0,0 +1,1161 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Wed Aug 30 06:45:18 2006
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+# CONFIG_E500 is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_KEXEC is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_4xx=y
+CONFIG_WANT_EARLY_SERIAL=y
+
+#
+# IBM 4xx options
+#
+# CONFIG_BUBINGA is not set
+# CONFIG_CPCI405 is not set
+# CONFIG_EP405 is not set
+# CONFIG_REDWOOD_5 is not set
+# CONFIG_REDWOOD_6 is not set
+# CONFIG_SYCAMORE is not set
+# CONFIG_WALNUT is not set
+CONFIG_MAGICBOX=y
+# CONFIG_XILINX_ML300 is not set
+# CONFIG_XILINX_ML403 is not set
+CONFIG_IBM_OCP=y
+CONFIG_BIOS_FIXUP=y
+CONFIG_405EP=y
+CONFIG_PPC4xx_DMA=y
+CONFIG_PPC4xx_EDMA=y
+CONFIG_PPC_GEN550=y
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,115200"
+# CONFIG_PM is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+# CONFIG_PPC_I8259 is not set
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_START=0xff100000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IPSEC_NAT_TRAVERSAL is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_BRIDGE_NETFILTER is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NETFILTER_XTABLES=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+CONFIG_IP_NF_CT_ACCT=y
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=y
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_IPP2P=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TIME=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
+CONFIG_IP_NF_MATCH_LAYER7=m
+# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_IMQ=m
+# CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_TARGET_ROUTE=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_SAME is not set
+# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=y
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_IP_NF_SET=m
+CONFIG_IP_NF_SET_MAX=256
+CONFIG_IP_NF_SET_HASHSIZE=1024
+CONFIG_IP_NF_SET_IPMAP=m
+CONFIG_IP_NF_SET_MACIPMAP=m
+CONFIG_IP_NF_SET_PORTMAP=m
+CONFIG_IP_NF_SET_IPHASH=m
+CONFIG_IP_NF_SET_NETHASH=m
+CONFIG_IP_NF_SET_IPTREE=m
+CONFIG_IP_NF_MATCH_SET=m
+CONFIG_IP_NF_TARGET_SET=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_ESFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+# CONFIG_NET_SCH_NETEM is not set
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+# CONFIG_NET_ACT_SIMP is not set
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_MAGICMAP=y
+# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_IFB is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_IMQ=m
+# CONFIG_IMQ_BEHAVIOR_AA is not set
+# CONFIG_IMQ_BEHAVIOR_AB is not set
+CONFIG_IMQ_BEHAVIOR_BA=y
+# CONFIG_IMQ_BEHAVIOR_BB is not set
+CONFIG_IMQ_NUM_DEVS=2
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=64
+CONFIG_IBM_EMAC_TXB=8
+CONFIG_IBM_EMAC_POLL_WEIGHT=32
+CONFIG_IBM_EMAC_RX_COPY_THRESHOLD=256
+CONFIG_IBM_EMAC_RX_SKB_HEADROOM=0
+# CONFIG_IBM_EMAC_PHY_RX_CLK_FIX is not set
+# CONFIG_IBM_EMAC_DEBUG is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+# CONFIG_IPW_QOS is not set
+# CONFIG_IPW2200_DEBUG is not set
+# CONFIG_AIRO is not set
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+# CONFIG_HOSTAP_PLX is not set
+CONFIG_HOSTAP_PCI=m
+# CONFIG_BCM43XX is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_BOOKE_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=m
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# IBM 40x options
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_PPC_OCP=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/target/linux/magicbox-2.6/patches/001-magicbox_support.patch b/target/linux/magicbox-2.6/patches/001-magicbox_support.patch
new file mode 100644
index 0000000000..b7806da697
--- /dev/null
+++ b/target/linux/magicbox-2.6/patches/001-magicbox_support.patch
@@ -0,0 +1,372 @@
+diff -Nur linux-2.6.17/arch/ppc/platforms/4xx/Kconfig linux-2.6.17-owrt/arch/ppc/platforms/4xx/Kconfig
+--- linux-2.6.17/arch/ppc/platforms/4xx/Kconfig 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/arch/ppc/platforms/4xx/Kconfig 2006-08-25 23:33:05.000000000 +0200
+@@ -52,6 +52,12 @@
+ help
+ This option enables support for the IBM PPC405GP evaluation board.
+
++config MAGICBOX
++ bool "MagicBox"
++ select WANT_EARLY_SERIAL
++ help
++ This option enables support for the IBM PPC405EP evaluation board.
++
+ config XILINX_ML300
+ bool "Xilinx-ML300"
+ help
+@@ -173,7 +179,7 @@
+
+ config IBM_OCP
+ bool
+- depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || YUCCA || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
++ depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || YUCCA || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT || MAGICBOX
+ default y
+
+ config IBM_EMAC4
+@@ -183,7 +189,7 @@
+
+ config BIOS_FIXUP
+ bool
+- depends on BUBINGA || EP405 || SYCAMORE || WALNUT
++ depends on BUBINGA || EP405 || SYCAMORE || WALNUT || MAGICBOX
+ default y
+
+ # OAK doesn't exist but wanted to keep this around for any future 403GCX boards
+@@ -194,7 +200,7 @@
+
+ config 405EP
+ bool
+- depends on BUBINGA
++ depends on BUBINGA || MAGICBOX
+ default y
+
+ config 405GP
+diff -Nur linux-2.6.17/arch/ppc/platforms/4xx/magicbox.c linux-2.6.17-owrt/arch/ppc/platforms/4xx/magicbox.c
+--- linux-2.6.17/arch/ppc/platforms/4xx/magicbox.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/ppc/platforms/4xx/magicbox.c 2006-08-25 23:33:05.000000000 +0200
+@@ -0,0 +1,249 @@
++/*
++ * Support for IBM PPC 405EP-based MagicBox board
++ * Copyright (C) 2006 Karol Lewandowski
++ *
++ * Heavily based on bubinga.c
++ *
++ * Author: SAW (IBM), derived from walnut.c.
++ * Maintained by MontaVista Software <source@mvista.com>
++ *
++ * 2003 (c) MontaVista Softare Inc. 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/config.h>
++#include <linux/init.h>
++#include <linux/smp.h>
++#include <linux/threads.h>
++#include <linux/param.h>
++#include <linux/string.h>
++#include <linux/blkdev.h>
++#include <linux/pci.h>
++#include <linux/tty.h>
++#include <linux/serial.h>
++#include <linux/serial_core.h>
++
++#include <asm/system.h>
++#include <asm/pci-bridge.h>
++#include <asm/processor.h>
++#include <asm/machdep.h>
++#include <asm/page.h>
++#include <asm/time.h>
++#include <asm/io.h>
++#include <asm/kgdb.h>
++#include <asm/ocp.h>
++#include <asm/ibm_ocp_pci.h>
++
++#include <platforms/4xx/ibm405ep.h>
++
++#undef DEBUG
++
++#ifdef DEBUG
++#define DBG(x...) printk(x)
++#else
++#define DBG(x...)
++#endif
++
++extern bd_t __res;
++
++/* Some IRQs unique to board
++ * Used by the generic 405 PCI setup functions in ppc4xx_pci.c
++ */
++int __init
++ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
++{
++ static char pci_irq_table[][4] =
++ /*
++ * PCI IDSEL/INTPIN->INTLINE
++ * A B C D
++ */
++ {
++ {28, 28, 28, 28}, /* IDSEL 1 - PCI slot 1 */
++ {29, 29, 29, 29}, /* IDSEL 2 - PCI slot 2 */
++ {30, 30, 30, 30}, /* IDSEL 3 - PCI slot 3 */
++ {31, 31, 31, 31}, /* IDSEL 4 - PCI slot 4 */
++ };
++
++ const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
++ return PCI_IRQ_TABLE_LOOKUP;
++};
++
++
++/* The serial clock for the chip is an internal clock determined by
++ * different clock speeds/dividers.
++ * Calculate the proper input baud rate and setup the serial driver.
++ */
++static void __init
++magicbox_early_serial_map(void)
++{
++ u32 uart_div;
++ int uart_clock;
++ struct uart_port port;
++
++ /* Calculate the serial clock input frequency
++ *
++ * The base baud is the PLL OUTA (provided in the board info
++ * structure) divided by the external UART Divisor, divided
++ * by 16.
++ */
++ uart_div = (mfdcr(DCRN_CPC0_UCR_BASE) & DCRN_CPC0_UCR_U0DIV);
++ uart_clock = __res.bi_procfreq / uart_div;
++
++ /* Setup serial port access */
++ memset(&port, 0, sizeof(port));
++ port.membase = (void*)ACTING_UART0_IO_BASE;
++ port.irq = ACTING_UART0_INT;
++ port.uartclk = uart_clock;
++ port.regshift = 0;
++ port.iotype = SERIAL_IO_MEM;
++ port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
++ port.line = 0;
++
++ if (early_serial_setup(&port) != 0) {
++ printk("Early serial init of port 0 failed\n");
++ }
++
++ port.membase = (void*)ACTING_UART1_IO_BASE;
++ port.irq = ACTING_UART1_INT;
++ port.line = 1;
++
++ if (early_serial_setup(&port) != 0) {
++ printk("Early serial init of port 1 failed\n");
++ }
++}
++
++void __init
++bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip)
++{
++ unsigned int bar_response, bar;
++ /*
++ * Expected PCI mapping:
++ *
++ * PLB addr PCI memory addr
++ * --------------------- ---------------------
++ * 0000'0000 - 7fff'ffff <--- 0000'0000 - 7fff'ffff
++ * 8000'0000 - Bfff'ffff ---> 8000'0000 - Bfff'ffff
++ *
++ * PLB addr PCI io addr
++ * --------------------- ---------------------
++ * e800'0000 - e800'ffff ---> 0000'0000 - 0001'0000
++ *
++ * The following code is simplified by assuming that the bootrom
++ * has been well behaved in following this mapping.
++ */
++
++#ifdef DEBUG
++ int i;
++
++ printk("ioremap PCLIO_BASE = 0x%x\n", pcip);
++ printk("PCI bridge regs before fixup \n");
++ for (i = 0; i <= 3; i++) {
++ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
++ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
++ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila)));
++ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha)));
++ }
++ printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
++ printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
++ printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
++ printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
++
++#endif
++
++ /* added for IBM boot rom version 1.15 bios bar changes -AK */
++
++ /* Disable region first */
++ out_le32((void *) &(pcip->pmm[0].ma), 0x00000000);
++ /* PLB starting addr, PCI: 0x80000000 */
++ out_le32((void *) &(pcip->pmm[0].la), 0x80000000);
++ /* PCI start addr, 0x80000000 */
++ out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE);
++ /* 512MB range of PLB to PCI */
++ out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000);
++ /* Enable no pre-fetch, enable region */
++ out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff -
++ (PPC405_PCI_UPPER_MEM -
++ PPC405_PCI_MEM_BASE)) | 0x01));
++
++ /* Disable region one */
++ out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
++ out_le32((void *) &(pcip->pmm[1].la), 0x00000000);
++ out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000);
++ out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000);
++ out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
++ out_le32((void *) &(pcip->ptm1ms), 0x00000001);
++
++ /* Disable region two */
++ out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
++ out_le32((void *) &(pcip->pmm[2].la), 0x00000000);
++ out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000);
++ out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000);
++ out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
++ out_le32((void *) &(pcip->ptm2ms), 0x00000000);
++ out_le32((void *) &(pcip->ptm2la), 0x00000000);
++
++ /* Zero config bars */
++ for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
++ early_write_config_dword(hose, hose->first_busno,
++ PCI_FUNC(hose->first_busno), bar,
++ 0x00000000);
++ early_read_config_dword(hose, hose->first_busno,
++ PCI_FUNC(hose->first_busno), bar,
++ &bar_response);
++ DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n",
++ hose->first_busno, PCI_SLOT(hose->first_busno),
++ PCI_FUNC(hose->first_busno), bar, bar_response);
++ }
++ /* end work arround */
++
++#ifdef DEBUG
++ printk("PCI bridge regs after fixup \n");
++ for (i = 0; i <= 3; i++) {
++ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
++ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
++ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila)));
++ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha)));
++ }
++ printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
++ printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
++ printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
++ printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
++
++#endif /* DEBUG */
++}
++
++void __init
++magicbox_setup_arch(void)
++{
++ ppc4xx_setup_arch();
++
++ ibm_ocp_set_emac(0, 1);
++
++ magicbox_early_serial_map();
++
++ /* Identify the system */
++ printk("MagicBox port (C) 2005 Karol Lewandowski <kl@jasmine.eu.org>\n");
++}
++
++void __init
++magicbox_map_io(void)
++{
++ ppc4xx_map_io();
++}
++
++void __init
++platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
++ unsigned long r6, unsigned long r7)
++{
++ ppc4xx_init(r3, r4, r5, r6, r7);
++
++ ppc_md.setup_arch = magicbox_setup_arch;
++ ppc_md.setup_io_mappings = magicbox_map_io;
++
++#ifdef CONFIG_KGDB
++ ppc_md.early_serial_map = bubinga_early_serial_map;
++#endif
++
++}
+diff -Nur linux-2.6.17/arch/ppc/platforms/4xx/magicbox.h linux-2.6.17-owrt/arch/ppc/platforms/4xx/magicbox.h
+--- linux-2.6.17/arch/ppc/platforms/4xx/magicbox.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/ppc/platforms/4xx/magicbox.h 2006-08-25 23:33:05.000000000 +0200
+@@ -0,0 +1,47 @@
++/*
++ * Support for IBM PPC 405EP-based MagicBox board
++ *
++ * Heavily based on bubinga.h
++ *
++ *
++ * Author: SAW (IBM), derived from walnut.h.
++ * Maintained by MontaVista Software <source@mvista.com>
++ *
++ * 2003 (c) MontaVista Softare Inc. 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.
++ */
++
++#ifdef __KERNEL__
++#ifndef __MAGICBOX_H__
++#define __MAGICBOX_H__
++
++#include <linux/config.h>
++#include <platforms/4xx/ibm405ep.h>
++#include <asm/ppcboot.h>
++
++/* Memory map for the "MagicBox" 405EP evaluation board -- generic 4xx. */
++
++/* The UART clock is based off an internal clock -
++ * define BASE_BAUD based on the internal clock and divider(s).
++ * Since BASE_BAUD must be a constant, we will initialize it
++ * using clock/divider values which OpenBIOS initializes
++ * for typical configurations at various CPU speeds.
++ * The base baud is calculated as (FWDA / EXT UART DIV / 16)
++ */
++#define BASE_BAUD 0
++
++/* Flash */
++#define PPC40x_FPGA_BASE 0xF0300000
++#define PPC40x_FPGA_REG_OFFS 1 /* offset to flash map reg */
++#define PPC40x_FLASH_ONBD_N(x) (x & 0x02)
++#define PPC40x_FLASH_SRAM_SEL(x) (x & 0x01)
++#define PPC40x_FLASH_LOW 0xFFF00000
++#define PPC40x_FLASH_HIGH 0xFFF80000
++#define PPC40x_FLASH_SIZE 0x80000
++
++#define PPC4xx_MACHINE_NAME "MagicBox"
++
++#endif /* __MAGICBOX_H__ */
++#endif /* __KERNEL__ */
+diff -Nur linux-2.6.17/arch/ppc/platforms/4xx/Makefile linux-2.6.17-owrt/arch/ppc/platforms/4xx/Makefile
+--- linux-2.6.17/arch/ppc/platforms/4xx/Makefile 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/arch/ppc/platforms/4xx/Makefile 2006-08-25 23:33:05.000000000 +0200
+@@ -13,6 +13,7 @@
+ obj-$(CONFIG_REDWOOD_6) += redwood6.o
+ obj-$(CONFIG_SYCAMORE) += sycamore.o
+ obj-$(CONFIG_WALNUT) += walnut.o
++obj-$(CONFIG_MAGICBOX) += magicbox.o
+ obj-$(CONFIG_XILINX_ML300) += xilinx_ml300.o
+ obj-$(CONFIG_XILINX_ML403) += xilinx_ml403.o
+
+diff -Nur linux-2.6.17/include/asm-ppc/ibm4xx.h linux-2.6.17-owrt/include/asm-ppc/ibm4xx.h
+--- linux-2.6.17/include/asm-ppc/ibm4xx.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/asm-ppc/ibm4xx.h 2006-08-25 23:33:05.000000000 +0200
+@@ -19,6 +19,10 @@
+
+ #ifdef CONFIG_40x
+
++#if defined(CONFIG_MAGICBOX)
++#include <platforms/4xx/magicbox.h>
++#endif
++
+ #if defined(CONFIG_BUBINGA)
+ #include <platforms/4xx/bubinga.h>
+ #endif
diff --git a/target/linux/magicbox-2.6/patches/002-flash_map.patch b/target/linux/magicbox-2.6/patches/002-flash_map.patch
new file mode 100644
index 0000000000..e5f803a144
--- /dev/null
+++ b/target/linux/magicbox-2.6/patches/002-flash_map.patch
@@ -0,0 +1,147 @@
+diff -urN linux.old/drivers/mtd/maps/Kconfig linux.dev/drivers/mtd/maps/Kconfig
+--- linux.old/drivers/mtd/maps/Kconfig 2006-08-30 06:30:59.000000000 +0200
++++ linux.dev/drivers/mtd/maps/Kconfig 2006-08-30 06:11:51.000000000 +0200
+@@ -323,6 +323,15 @@
+ Walnut board. If you have one of these boards and would like to
+ use the flash chips on it, say 'Y'.
+
++config MTD_MAGICMAP
++ tristate "Flash device mapped on IBM 405EP MagicBox"
++ depends on MTD_CFI && MTD_PARTITIONS && 40x && MAGICBOX
++ help
++ This enables access routines for the flash chips on the IBM 405EP
++ MagicBox board. If you have one of these boards and would like to
++ use the flash chips on it, say 'Y'.
++
++
+ config MTD_EBONY
+ tristate "Flash devices mapped on IBM 440GP Ebony"
+ depends on MTD_JEDECPROBE && EBONY
+diff -urN linux.old/drivers/mtd/maps/magicmap.c linux.dev/drivers/mtd/maps/magicmap.c
+--- linux.old/drivers/mtd/maps/magicmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/mtd/maps/magicmap.c 2006-08-30 06:52:34.000000000 +0200
+@@ -0,0 +1,113 @@
++/*
++ * magicmap.c: Copyleft 2005 Karol Lewandowski
++ *
++ * Mapping for MagicBox flash.
++ * Based on walnut.c.
++ *
++ * Heikki Lindholm <holindho@infradead.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.
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++#include <linux/config.h>
++#include <asm/io.h>
++
++static struct mtd_info *flash;
++
++static struct map_info magic_map = {
++ .name = "Magically mapped flash",
++ .phys = 0xffc00000,
++ .size = 0x400000,
++ .bankwidth = 2,
++};
++
++static struct mtd_partition magic_partitions[] = {
++ {
++ .name = "linux",
++ .offset = 0x0,
++ .size = 0x3c0000,
++ },
++ {
++ .name = "rootfs",
++ .offset = 0x100000,
++ .size = 0x2c0000,
++ },
++ {
++ .name = "bootloader",
++ .offset = 0x3c0000,
++ .size = 0x040000,
++ .mask_flags = MTD_WRITEABLE,
++ },
++};
++
++int __init init_magic(void)
++{
++ u32 size, len;
++
++ magic_map.virt =
++ (void __iomem *)ioremap(magic_map.phys, magic_map.size);
++
++ if (!magic_map.virt) {
++ printk("Failed to ioremap flash.\n");
++ return -EIO;
++ }
++
++ simple_map_init(&magic_map);
++
++ flash = do_map_probe("cfi_probe", &magic_map);
++ if (flash) {
++ flash->owner = THIS_MODULE;
++ if (MTD_READ(flash, 12, sizeof(u32), &len, (char *) &size) ||
++ len != 4)
++ return -ENXIO;
++ size += 0x40; /* header size of the uImage */
++ if (size < 0x400000) {
++ /* skip to next erase block */
++ if (size & (flash->erasesize - 1)) {
++ size |= (flash->erasesize - 1);
++ size += 1;
++ }
++ magic_partitions[1].offset = size;
++ magic_partitions[1].size = magic_partitions[2].offset - size;
++ }
++
++ add_mtd_partitions(flash, magic_partitions,
++ ARRAY_SIZE(magic_partitions));
++ } else {
++ printk("map probe failed for flash\n");
++ return -ENXIO;
++ }
++
++ return 0;
++}
++
++static void __exit cleanup_magic(void)
++{
++ if (flash) {
++ del_mtd_partitions(flash);
++ map_destroy(flash);
++ }
++
++ if (magic_map.virt) {
++ iounmap((void *)magic_map.virt);
++ magic_map.virt = NULL;
++ }
++}
++
++module_init(init_magic);
++module_exit(cleanup_magic);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Karol Lewandowski");
++MODULE_DESCRIPTION("MTD map and partitions for IBM 405EP MagicBox boards");
+diff -urN linux.old/drivers/mtd/maps/Makefile linux.dev/drivers/mtd/maps/Makefile
+--- linux.old/drivers/mtd/maps/Makefile 2006-08-30 06:30:59.000000000 +0200
++++ linux.dev/drivers/mtd/maps/Makefile 2006-08-30 06:11:51.000000000 +0200
+@@ -58,6 +58,7 @@
+ obj-$(CONFIG_MTD_BEECH) += beech-mtd.o
+ obj-$(CONFIG_MTD_ARCTIC) += arctic-mtd.o
+ obj-$(CONFIG_MTD_WALNUT) += walnut.o
++obj-$(CONFIG_MTD_MAGICMAP) += magicmap.o
+ obj-$(CONFIG_MTD_H720X) += h720x-flash.o
+ obj-$(CONFIG_MTD_SBC8240) += sbc8240.o
+ obj-$(CONFIG_MTD_NOR_TOTO) += omap-toto-flash.o
diff --git a/target/linux/package/Config.in b/target/linux/package/Config.in
new file mode 100644
index 0000000000..4d97a57aaa
--- /dev/null
+++ b/target/linux/package/Config.in
@@ -0,0 +1 @@
+source "target/linux/package/*/Config.in"
diff --git a/target/linux/package/Makefile b/target/linux/package/Makefile
new file mode 100644
index 0000000000..d6ce8623ea
--- /dev/null
+++ b/target/linux/package/Makefile
@@ -0,0 +1,54 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# Main makefile for the packages
+include $(TOPDIR)/rules.mk
+include ../rules.mk
+
+package-$(CONFIG_PACKAGE_KMOD_ALSA) += alsa
+package-$(CONFIG_PACKAGE_KMOD_FUSE) += fuse
+package-$(CONFIG_PACKAGE_KMOD_HOSTAP) += hostap
+package-$(CONFIG_PACKAGE_KMOD_MADWIFI) += madwifi
+package-$(CONFIG_PACKAGE_KMOD_MINI_FO) += mini_fo
+package-$(CONFIG_PACKAGE_KMOD_OPENSWAN) += openswan
+package-$(CONFIG_PACKAGE_KMOD_SHFS) += shfs
+package-$(CONFIG_PACKAGE_KMOD_SPCA5XX) += spca5xx
+package-$(CONFIG_PACKAGE_KMOD_SWITCH) += switch
+package-$(CONFIG_PACKAGE_KMOD_UEAGLE_ATM) += ueagle-atm
+package-$(CONFIG_PACKAGE_KMOD_DIAG) += diag
+package-$(CONFIG_PACKAGE_KMOD_WLCOMPAT) += wlcompat
+package-$(CONFIG_PACKAGE_KMOD_ZD1211) += zd1211
+
+wlcompat-compile: base-files-compile
+
+all: compile install
+clean: $(patsubst %,%-clean,$(package-) $(package-y) $(package-m))
+prepare: $(patsubst %,%-prepare,$(package-y) $(package-m))
+compile: $(patsubst %,%-compile,$(package-y) $(package-m))
+install: $(patsubst %,%-install,$(package-y))
+
+KPKG_MAKEOPTS += BUILD_DIR="$(LINUX_BUILD_DIR)"
+
+%-prepare: FORCE
+ $(MAKE) -C $(patsubst %-prepare,%,$@) \
+ $(KPKG_MAKEOPTS) \
+ prepare
+
+%-compile: FORCE
+ $(MAKE) -C $(patsubst %-compile,%,$@) \
+ $(KPKG_MAKEOPTS) \
+ compile
+
+%-install: FORCE
+ $(MAKE) -C $(patsubst %-install,%,$@) \
+ $(KPKG_MAKEOPTS) \
+ install
+
+%-clean: FORCE
+ @$(MAKE) -C $(patsubst %-clean,%,$@) \
+ $(KPKG_MAKEOPTS) \
+ clean
+
diff --git a/target/linux/rb532-2.6/Makefile b/target/linux/rb532-2.6/Makefile
new file mode 100644
index 0000000000..30fa1a85a1
--- /dev/null
+++ b/target/linux/rb532-2.6/Makefile
@@ -0,0 +1,22 @@
+#
+# 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
+
+LINUX_VERSION:=2.6.17
+LINUX_RELEASE:=1
+LINUX_KERNEL_MD5SUM:=37ddefe96625502161f075b9d907f21e
+
+include ./config
+include $(INCLUDE_DIR)/kernel.mk
+include $(INCLUDE_DIR)/kernel-build.mk
+
+$(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked
+ [ -d ../generic-$(KERNEL)/patches ] && $(PATCH) $(LINUX_DIR) ../generic-$(KERNEL)/patches
+ [ -d ./patches ] && $(PATCH) $(LINUX_DIR) ./patches
+ @$(CP) config $(LINUX_DIR)/.config
+ touch $@
+
diff --git a/target/linux/rb532-2.6/config b/target/linux/rb532-2.6/config
new file mode 100644
index 0000000000..eaa3771d11
--- /dev/null
+++ b/target/linux/rb532-2.6/config
@@ -0,0 +1,1335 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Sun Jun 18 17:29:23 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+CONFIG_MIKROTIK_RB500=y
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_MIPS_L1_CACHE_SHIFT=4
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+# CONFIG_PCMCIA_LOAD_CIS is not set
+# CONFIG_PCMCIA_IOCTL is not set
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+# CONFIG_YENTA is not set
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+CONFIG_IPSEC_NAT_TRAVERSAL=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=y
+CONFIG_TCP_CONG_SCALABLE=m
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+CONFIG_IPV6_ROUTER_PREF=y
+# CONFIG_IPV6_ROUTE_INFO is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_BRIDGE_NETFILTER is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NETFILTER_XTABLES=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=y
+CONFIG_IP_NF_IRC=y
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_IPP2P=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TIME=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
+CONFIG_IP_NF_MATCH_LAYER7=m
+# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_IMQ=m
+# CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_TARGET_ROUTE=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_SAME is not set
+# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+CONFIG_IP_NF_NAT_IRC=y
+CONFIG_IP_NF_NAT_FTP=y
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+CONFIG_IP_NF_RAW=m
+# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_IP_NF_SET=m
+CONFIG_IP_NF_SET_MAX=256
+CONFIG_IP_NF_SET_HASHSIZE=1024
+CONFIG_IP_NF_SET_IPMAP=m
+CONFIG_IP_NF_SET_MACIPMAP=m
+CONFIG_IP_NF_SET_PORTMAP=m
+CONFIG_IP_NF_SET_IPHASH=m
+CONFIG_IP_NF_SET_NETHASH=m
+CONFIG_IP_NF_SET_IPTREE=m
+CONFIG_IP_NF_MATCH_SET=m
+CONFIG_IP_NF_TARGET_SET=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+# CONFIG_IP6_NF_MATCH_RT is not set
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+CONFIG_IP6_NF_MATCH_OWNER=m
+# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_IMQ=m
+# CONFIG_IP6_NF_TARGET_LOG is not set
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_ROUTE=m
+CONFIG_IP6_NF_MANGLE=m
+# CONFIG_IP6_NF_TARGET_HL is not set
+# CONFIG_IP6_NF_RAW is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_ESFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+# CONFIG_NET_SCH_NETEM is not set
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+CONFIG_AX25=m
+# CONFIG_AX25_DAMA_SLAVE is not set
+# CONFIG_NETROM is not set
+# CONFIG_ROSE is not set
+
+#
+# AX.25 network device drivers
+#
+CONFIG_MKISS=m
+# CONFIG_6PACK is not set
+# CONFIG_BPQETHER is not set
+# CONFIG_BAYCOM_SER_FDX is not set
+# CONFIG_BAYCOM_SER_HDX is not set
+# CONFIG_YAM is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+CONFIG_MTD_BLOCK2MTD=y
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_BLK_DEV_CF_MIPS=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_IMQ=m
+# CONFIG_IMQ_BEHAVIOR_AA is not set
+# CONFIG_IMQ_BEHAVIOR_AB is not set
+CONFIG_IMQ_BEHAVIOR_BA=y
+# CONFIG_IMQ_BEHAVIOR_BB is not set
+CONFIG_IMQ_NUM_DEVS=2
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_KORINA=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+CONFIG_VIA_RHINE=y
+# CONFIG_VIA_RHINE_MMIO is not set
+# CONFIG_LAN_SAA9730 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+# CONFIG_HOSTAP_PLX is not set
+# CONFIG_HOSTAP_PCI is not set
+CONFIG_HOSTAP_CS=m
+# CONFIG_BCM43XX is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+# CONFIG_SERIAL_8250_CS is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=m
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_OPENWRT_PARTITION=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=m
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="root=/dev/mtdblock1 rootfstype=squashfs,jffs2 noinitrd console=ttyS0,115200"
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
diff --git a/target/linux/rb532-2.6/patches/100-rb5xx_support.patch b/target/linux/rb532-2.6/patches/100-rb5xx_support.patch
new file mode 100644
index 0000000000..f846c78c2b
--- /dev/null
+++ b/target/linux/rb532-2.6/patches/100-rb5xx_support.patch
@@ -0,0 +1,5606 @@
+diff -urN linux.old/arch/mips/Kconfig linux.dev/arch/mips/Kconfig
+--- linux.old/arch/mips/Kconfig 2006-06-18 03:49:35.000000000 +0200
++++ linux.dev/arch/mips/Kconfig 2006-10-11 21:56:38.000000000 +0200
+@@ -742,6 +742,19 @@
+ select SYS_SUPPORTS_BIG_ENDIAN
+ select TOSHIBA_BOARDS
+
++config MIKROTIK_RB500
++ bool "Support for RB5xx boards"
++ select HW_HAS_PCI
++ select IRQ_CPU
++ select SYS_HAS_CPU_MIPS32_R1
++ select SYS_SUPPORTS_LITTLE_ENDIAN
++ select SYS_SUPPORTS_32BIT_KERNEL
++ select SWAP_IO_SPACE
++ select DMA_NONCOHERENT
++ help
++ Support the Mikrotik(tm) Routerboard 500 series,
++ such as the RB532.
++
+ config TOSHIBA_RBTX4927
+ bool "Toshiba TBTX49[23]7 board"
+ select DMA_NONCOHERENT
+@@ -1028,7 +1041,7 @@
+
+ config MIPS_L1_CACHE_SHIFT
+ int
+- default "4" if MACH_DECSTATION
++ default "4" if MACH_DECSTATION || MIKROTIK_RB500
+ default "7" if SGI_IP27
+ default "5"
+
+diff -urN linux.old/arch/mips/Makefile linux.dev/arch/mips/Makefile
+--- linux.old/arch/mips/Makefile 2006-10-11 21:55:59.000000000 +0200
++++ linux.dev/arch/mips/Makefile 2006-10-11 21:56:38.000000000 +0200
+@@ -580,6 +580,13 @@
+ load-$(CONFIG_TOSHIBA_JMR3927) += 0xffffffff80050000
+
+ #
++# Routerboard 532 board
++#
++core-$(CONFIG_MIKROTIK_RB500) += arch/mips/rb500/
++cflags-$(CONFIG_MIKROTIK_RB500) += -Iinclude/asm-mips/rc32434
++load-$(CONFIG_MIKROTIK_RB500) += 0xffffffff80101000
++
++#
+ # Toshiba RBTX4927 board or
+ # Toshiba RBTX4937 board
+ #
+diff -urN linux.old/arch/mips/mm/tlbex.c linux.dev/arch/mips/mm/tlbex.c
+--- linux.old/arch/mips/mm/tlbex.c 2006-06-18 03:49:35.000000000 +0200
++++ linux.dev/arch/mips/mm/tlbex.c 2006-10-11 21:56:38.000000000 +0200
+@@ -876,7 +876,6 @@
+ case CPU_R10000:
+ case CPU_R12000:
+ case CPU_R14000:
+- case CPU_4KC:
+ case CPU_SB1:
+ case CPU_SB1A:
+ case CPU_4KSC:
+@@ -904,6 +903,7 @@
+ tlbw(p);
+ break;
+
++ case CPU_4KC:
+ case CPU_4KEC:
+ case CPU_24K:
+ case CPU_34K:
+diff -urN linux.old/arch/mips/pci/fixup-rb500.c linux.dev/arch/mips/pci/fixup-rb500.c
+--- linux.old/arch/mips/pci/fixup-rb500.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/pci/fixup-rb500.c 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,49 @@
++/*
++ * Copyright 2001 MontaVista Software Inc.
++ * Author: MontaVista Software, Inc.
++ * stevel@mvista.com or source@mvista.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/config.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++
++#include <asm/rc32434/rc32434.h>
++
++static int __devinitdata irq_map[2][12] = {
++ { 0, 0, 2, 3, 2, 3, 0, 0, 0, 0, 0, 1 },
++ { 0, 0, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3 }
++};
++
++int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ int irq = 0;
++
++ if (dev->bus->number < 2 && PCI_SLOT(dev->devfn) < 12) {
++ irq = irq_map[dev->bus->number][PCI_SLOT(dev->devfn)];
++ }
++ return irq + GROUP4_IRQ_BASE + 4;
++}
++
+diff -urN linux.old/arch/mips/pci/Makefile linux.dev/arch/mips/pci/Makefile
+--- linux.old/arch/mips/pci/Makefile 2006-06-18 03:49:35.000000000 +0200
++++ linux.dev/arch/mips/pci/Makefile 2006-10-11 21:56:38.000000000 +0200
+@@ -57,3 +57,4 @@
+ obj-$(CONFIG_TOSHIBA_RBTX4938) += fixup-tx4938.o ops-tx4938.o
+ obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o
+ obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o
++obj-$(CONFIG_MIKROTIK_RB500) += pci-rc32434.o ops-rc32434.o fixup-rb500.o
+diff -urN linux.old/arch/mips/pci/ops-rc32434.c linux.dev/arch/mips/pci/ops-rc32434.c
+--- linux.old/arch/mips/pci/ops-rc32434.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/pci/ops-rc32434.c 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,195 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * pci_ops for IDT EB434 board
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++
++#include <asm/cpu.h>
++#include <asm/io.h>
++
++#include <asm/rc32434/rc32434.h>
++#include <asm/rc32434/pci.h>
++
++#define PCI_ACCESS_READ 0
++#define PCI_ACCESS_WRITE 1
++
++
++#define PCI_CFG_SET(bus,slot,func,off) \
++ (rc32434_pci->pcicfga = (0x80000000 | \
++ ((bus) << 16) | ((slot)<<11) | \
++ ((func)<<8) | (off)))
++
++static inline int config_access(unsigned char access_type, struct pci_bus *bus,
++ unsigned int devfn, unsigned char where,
++ u32 * data)
++{
++ unsigned int slot = PCI_SLOT(devfn);
++ u8 func = PCI_FUNC(devfn);
++
++ /* Setup address */
++ PCI_CFG_SET(bus->number, slot, func, where);
++ rc32434_sync();
++
++ if (access_type == PCI_ACCESS_WRITE)
++ rc32434_pci->pcicfgd = *data;
++ else
++ *data = rc32434_pci->pcicfgd;
++
++ rc32434_sync();
++
++ return 0;
++}
++
++
++/*
++ * We can't address 8 and 16 bit words directly. Instead we have to
++ * read/write a 32bit word and mask/modify the data we actually want.
++ */
++static int read_config_byte(struct pci_bus *bus, unsigned int devfn,
++ int where, u8 * val)
++{
++ u32 data;
++ int ret;
++
++ ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
++ *val = (data >> ((where & 3) << 3)) & 0xff;
++ return ret;
++}
++
++static int read_config_word(struct pci_bus *bus, unsigned int devfn,
++ int where, u16 * val)
++{
++ u32 data;
++ int ret;
++
++ ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
++ *val = (data >> ((where & 3) << 3)) & 0xffff;
++ return ret;
++}
++
++static int read_config_dword(struct pci_bus *bus, unsigned int devfn,
++ int where, u32 * val)
++{
++ int ret;
++
++ ret = config_access(PCI_ACCESS_READ, bus, devfn, where, val);
++ return ret;
++}
++
++static int
++write_config_byte(struct pci_bus *bus, unsigned int devfn, int where,
++ u8 val)
++{
++ u32 data = 0;
++
++ if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
++ return -1;
++
++ data = (data & ~(0xff << ((where & 3) << 3))) |
++ (val << ((where & 3) << 3));
++
++ if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
++ return -1;
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++
++static int
++write_config_word(struct pci_bus *bus, unsigned int devfn, int where,
++ u16 val)
++{
++ u32 data = 0;
++
++ if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
++ return -1;
++
++ data = (data & ~(0xffff << ((where & 3) << 3))) |
++ (val << ((where & 3) << 3));
++
++ if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
++ return -1;
++
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++
++static int
++write_config_dword(struct pci_bus *bus, unsigned int devfn, int where,
++ u32 val)
++{
++ if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val))
++ return -1;
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int pci_config_read(struct pci_bus *bus, unsigned int devfn,
++ int where, int size, u32 * val)
++{
++ switch (size) {
++ case 1:
++ return read_config_byte(bus, devfn, where, (u8 *) val);
++ case 2:
++ return read_config_word(bus, devfn, where, (u16 *) val);
++ default:
++ return read_config_dword(bus, devfn, where, val);
++ }
++}
++
++static int pci_config_write(struct pci_bus *bus, unsigned int devfn,
++ int where, int size, u32 val)
++{
++ switch (size) {
++ case 1:
++ return write_config_byte(bus, devfn, where, (u8) val);
++ case 2:
++ return write_config_word(bus, devfn, where, (u16) val);
++ default:
++ return write_config_dword(bus, devfn, where, val);
++ }
++}
++
++struct pci_ops rc32434_pci_ops = {
++ .read = pci_config_read,
++ .write = pci_config_write,
++};
+diff -urN linux.old/arch/mips/pci/pci-rc32434.c linux.dev/arch/mips/pci/pci-rc32434.c
+--- linux.old/arch/mips/pci/pci-rc32434.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/pci/pci-rc32434.c 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,234 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * PCI initialization for IDT EB434 board
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++
++#include <asm/rc32434/rc32434.h>
++#include <asm/rc32434/pci.h>
++
++#define PCI_ACCESS_READ 0
++#define PCI_ACCESS_WRITE 1
++
++/* define an unsigned array for the PCI registers */
++unsigned int korinaCnfgRegs[25] = {
++ KORINA_CNFG1, KORINA_CNFG2, KORINA_CNFG3, KORINA_CNFG4,
++ KORINA_CNFG5, KORINA_CNFG6, KORINA_CNFG7, KORINA_CNFG8,
++ KORINA_CNFG9, KORINA_CNFG10, KORINA_CNFG11, KORINA_CNFG12,
++ KORINA_CNFG13, KORINA_CNFG14, KORINA_CNFG15, KORINA_CNFG16,
++ KORINA_CNFG17, KORINA_CNFG18, KORINA_CNFG19, KORINA_CNFG20,
++ KORINA_CNFG21, KORINA_CNFG22, KORINA_CNFG23, KORINA_CNFG24
++};
++static struct resource rc32434_res_pci_mem1;
++static struct resource rc32434_res_pci_mem2;
++
++static struct resource rc32434_res_pci_mem1 = {
++ .name = "PCI MEM1",
++ .start = 0x50000000,
++ .end = 0x5FFFFFFF,
++ .flags = IORESOURCE_MEM,
++ .parent = &rc32434_res_pci_mem1,
++ .sibling = NULL,
++ .child = &rc32434_res_pci_mem2
++};
++
++static struct resource rc32434_res_pci_mem2 = {
++ .name = "PCI Mem2",
++ .start = 0x60000000,
++ .end = 0x6FFFFFFF,
++ .flags = IORESOURCE_MEM,
++ .parent = &rc32434_res_pci_mem1,
++ .sibling = NULL,
++ .child = NULL
++};
++
++static struct resource rc32434_res_pci_io1 = {
++ .name = "PCI I/O1",
++ .start = 0x18800000,
++ .end = 0x188FFFFF,
++ .flags = IORESOURCE_IO,
++};
++
++extern struct pci_ops rc32434_pci_ops;
++
++#define PCI_MEM1_START PCI_ADDR_START
++#define PCI_MEM1_END PCI_ADDR_START + CPUTOPCI_MEM_WIN - 1
++#define PCI_MEM2_START PCI_ADDR_START + CPUTOPCI_MEM_WIN
++#define PCI_MEM2_END PCI_ADDR_START + ( 2* CPUTOPCI_MEM_WIN) - 1
++#define PCI_IO1_START PCI_ADDR_START + (2 * CPUTOPCI_MEM_WIN)
++#define PCI_IO1_END PCI_ADDR_START + (2* CPUTOPCI_MEM_WIN) + CPUTOPCI_IO_WIN -1
++#define PCI_IO2_START PCI_ADDR_START + (2 * CPUTOPCI_MEM_WIN) + CPUTOPCI_IO_WIN
++#define PCI_IO2_END PCI_ADDR_START + (2* CPUTOPCI_MEM_WIN) + (2 * CPUTOPCI_IO_WIN) -1
++
++
++struct pci_controller rc32434_controller2;
++
++struct pci_controller rc32434_controller = {
++ .pci_ops = &rc32434_pci_ops,
++ .mem_resource = &rc32434_res_pci_mem1,
++ .io_resource = &rc32434_res_pci_io1,
++ .mem_offset = 0,
++ .io_offset = 0,
++
++};
++
++#ifdef __MIPSEB__
++#define PCI_ENDIAN_FLAG PCILBAC_sb_m
++#else
++#define PCI_ENDIAN_FLAG 0
++#endif
++
++static int __init rc32434_pcibridge_init(void)
++{
++ unsigned int pcicValue, pcicData = 0;
++ unsigned int dummyRead, pciCntlVal;
++ int loopCount;
++ unsigned int pciConfigAddr;
++
++ pcicValue = rc32434_pci->pcic;
++ pcicValue = (pcicValue >> PCIM_SHFT) & PCIM_BIT_LEN;
++ if (!((pcicValue == PCIM_H_EA) ||
++ (pcicValue == PCIM_H_IA_FIX) ||
++ (pcicValue == PCIM_H_IA_RR))) {
++ printk("PCI init error!!!\n");
++ /* Not in Host Mode, return ERROR */
++ return -1;
++ }
++ /* Enables the Idle Grant mode, Arbiter Parking */
++ pcicData |=(PCIC_igm_m|PCIC_eap_m|PCIC_en_m);
++ rc32434_pci->pcic = pcicData; /* Enable the PCI bus Interface */
++ /* Zero out the PCI status & PCI Status Mask */
++ for(;;)
++ {
++ pcicData = rc32434_pci->pcis;
++ if (!(pcicData & PCIS_rip_m))
++ break;
++ }
++
++ rc32434_pci->pcis = 0;
++ rc32434_pci->pcism = 0xFFFFFFFF;
++ /* Zero out the PCI decoupled registers */
++ rc32434_pci->pcidac=0; /* disable PCI decoupled accesses at initialization */
++ rc32434_pci->pcidas=0; /* clear the status */
++ rc32434_pci->pcidasm=0x0000007F; /* Mask all the interrupts */
++ /* Mask PCI Messaging Interrupts */
++ rc32434_pci_msg->pciiic = 0;
++ rc32434_pci_msg->pciiim = 0xFFFFFFFF;
++ rc32434_pci_msg->pciioic = 0;
++ rc32434_pci_msg->pciioim = 0;
++
++
++ /* Setup PCILB0 as Memory Window */
++ rc32434_pci->pcilba[0].a = (unsigned int) (PCI_ADDR_START);
++
++ /* setup the PCI map address as same as the local address */
++
++ rc32434_pci->pcilba[0].m = (unsigned int) (PCI_ADDR_START);
++
++
++ /* Setup PCILBA1 as MEM */
++ rc32434_pci->pcilba[0].c = ( ((SIZE_256MB & 0x1f) << PCILBAC_size_b) | PCI_ENDIAN_FLAG);
++ dummyRead = rc32434_pci->pcilba[0].c; /* flush the CPU write Buffers */
++ rc32434_pci->pcilba[1].a = 0x60000000;
++ rc32434_pci->pcilba[1].m = 0x60000000;
++
++ /* setup PCILBA2 as IO Window*/
++ rc32434_pci->pcilba[1].c = (((SIZE_256MB & 0x1f) << PCILBAC_size_b )| PCI_ENDIAN_FLAG);
++ dummyRead = rc32434_pci->pcilba[1].c; /* flush the CPU write Buffers */
++ rc32434_pci->pcilba[2].a = 0x18C00000;
++ rc32434_pci->pcilba[2].m = 0x18FFFFFF;
++
++ /* setup PCILBA2 as IO Window*/
++ rc32434_pci->pcilba[2].c = (((SIZE_4MB & 0x1f) << PCILBAC_size_b) | PCI_ENDIAN_FLAG );
++ dummyRead = rc32434_pci->pcilba[2].c; /* flush the CPU write Buffers */
++
++ /* Setup PCILBA3 as IO Window */
++ rc32434_pci->pcilba[3].a = 0x18800000;
++ rc32434_pci->pcilba[3].m = 0x18800000;
++ rc32434_pci->pcilba[3].c = ( (((SIZE_1MB & 0x1ff) << PCILBAC_size_b) | PCILBAC_msi_m) | PCI_ENDIAN_FLAG);
++ dummyRead = rc32434_pci->pcilba[3].c; /* flush the CPU write Buffers */
++
++ pciConfigAddr=(unsigned int)(0x80000004);
++ for(loopCount=0;loopCount<24;loopCount++){
++ rc32434_pci->pcicfga=pciConfigAddr;
++ dummyRead=rc32434_pci->pcicfga;
++ rc32434_pci->pcicfgd = korinaCnfgRegs[loopCount];
++ dummyRead=rc32434_pci->pcicfgd;
++ pciConfigAddr += 4;
++ }
++ rc32434_pci->pcitc = (unsigned int)((PCITC_RTIMER_VAL&0xff) << PCITC_rtimer_b)
++ | ((PCITC_DTIMER_VAL&0xff) << PCITC_dtimer_b);
++
++ pciCntlVal=rc32434_pci->pcic;
++ pciCntlVal &=~(PCIC_tnr_m);
++ rc32434_pci->pcic = pciCntlVal;
++ pciCntlVal=rc32434_pci->pcic;
++ return 0;
++}
++
++/* Do platform specific device initialization at pci_enable_device() time */
++int pcibios_plat_dev_init(struct pci_dev *dev)
++{
++ if (PCI_SLOT(dev->devfn) == 6 && dev->bus->number == 0) {
++ /* disable prefetched memory range */
++ pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT, 0);
++ pci_write_config_word(dev, PCI_PREF_MEMORY_BASE, 0x10);
++
++ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 4);
++ }
++ return 0;
++}
++
++static int __init rc32434_pci_init(void)
++{
++ printk("PCI: Initializing PCI\n");
++
++ ioport_resource.start = rc32434_res_pci_io1.start;
++ ioport_resource.end = rc32434_res_pci_io1.end;
++
++ rc32434_pcibridge_init();
++
++ register_pci_controller(&rc32434_controller);
++ rc32434_sync();
++}
++
++arch_initcall(rc32434_pci_init);
++
+diff -urN linux.old/arch/mips/rb500/devices.c linux.dev/arch/mips/rb500/devices.c
+--- linux.old/arch/mips/rb500/devices.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/rb500/devices.c 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,211 @@
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/ctype.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++#include <asm/unaligned.h>
++#include <asm/io.h>
++
++#include <asm/rc32434/rc32434.h>
++#include <asm/rc32434/dma.h>
++#include <asm/rc32434/dma_v.h>
++#include <asm/rc32434/eth.h>
++#include <asm/rc32434/rb.h>
++
++#define ETH0_DMA_RX_IRQ GROUP1_IRQ_BASE + 0
++#define ETH0_DMA_TX_IRQ GROUP1_IRQ_BASE + 1
++#define ETH0_RX_OVR_IRQ GROUP3_IRQ_BASE + 9
++#define ETH0_TX_UND_IRQ GROUP3_IRQ_BASE + 10
++
++#define ETH0_RX_DMA_ADDR (DMA0_PhysicalAddress + 0*DMA_CHAN_OFFSET)
++#define ETH0_TX_DMA_ADDR (DMA0_PhysicalAddress + 1*DMA_CHAN_OFFSET)
++
++static struct resource korina_dev0_res[] = {
++ {
++ .name = "korina_regs",
++ .start = ETH0_PhysicalAddress,
++ .end = ETH0_PhysicalAddress + sizeof(ETH_t),
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .name = "korina_rx",
++ .start = ETH0_DMA_RX_IRQ,
++ .end = ETH0_DMA_RX_IRQ,
++ .flags = IORESOURCE_IRQ
++ },
++ {
++ .name = "korina_tx",
++ .start = ETH0_DMA_TX_IRQ,
++ .end = ETH0_DMA_TX_IRQ,
++ .flags = IORESOURCE_IRQ
++ },
++ {
++ .name = "korina_ovr",
++ .start = ETH0_RX_OVR_IRQ,
++ .end = ETH0_RX_OVR_IRQ,
++ .flags = IORESOURCE_IRQ
++ },
++ {
++ .name = "korina_und",
++ .start = ETH0_TX_UND_IRQ,
++ .end = ETH0_TX_UND_IRQ,
++ .flags = IORESOURCE_IRQ
++ },
++ {
++ .name = "korina_dma_rx",
++ .start = ETH0_RX_DMA_ADDR,
++ .end = ETH0_RX_DMA_ADDR + DMA_CHAN_OFFSET - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .name = "korina_dma_tx",
++ .start = ETH0_TX_DMA_ADDR,
++ .end = ETH0_TX_DMA_ADDR + DMA_CHAN_OFFSET - 1,
++ .flags = IORESOURCE_MEM,
++ }
++};
++
++static struct korina_device korina_dev0_data = {
++ .name = "korina0",
++ .mac = { 0xde, 0xca, 0xff, 0xc0, 0xff, 0xee }
++};
++
++static struct platform_device korina_dev0 = {
++ .id = 0,
++ .name = "korina",
++ .dev.platform_data = &korina_dev0_data,
++ .resource = korina_dev0_res,
++ .num_resources = ARRAY_SIZE(korina_dev0_res),
++};
++
++
++#define CF_GPIO_NUM 13
++
++static struct resource cf_slot0_res[] = {
++ {
++ .name = "cf_membase",
++ .flags = IORESOURCE_MEM
++ },
++ {
++ .name = "cf_irq",
++ .start = (8 + 4 * 32 + CF_GPIO_NUM), /* 149 */
++ .end = (8 + 4 * 32 + CF_GPIO_NUM),
++ .flags = IORESOURCE_IRQ
++ }
++};
++
++static struct cf_device cf_slot0_data = {
++ .gpio_pin = 13
++};
++
++static struct platform_device cf_slot0 = {
++ .id = 0,
++ .name = "rb500-cf",
++ .dev.platform_data = &cf_slot0_data,
++ .resource = cf_slot0_res,
++ .num_resources = ARRAY_SIZE(cf_slot0_res),
++};
++
++
++
++static struct platform_device *rb500_devs[] = {
++ &korina_dev0,
++ &cf_slot0
++};
++
++static void __init parse_mac_addr(char* macstr)
++{
++ int i, j;
++ unsigned char result, value;
++
++ for (i=0; i<6; i++) {
++ result = 0;
++ if (i != 5 && *(macstr+2) != ':') {
++ return;
++ }
++ for (j=0; j<2; j++) {
++ if (isxdigit(*macstr) && (value = isdigit(*macstr) ? *macstr-'0' :
++ toupper(*macstr)-'A'+10) < 16) {
++ result = result*16 + value;
++ macstr++;
++ }
++ else return;
++ }
++
++ macstr++;
++ korina_dev0_data.mac[i] = result;
++ }
++}
++
++
++/* DEVICE CONTROLLER 1 */
++#define CFG_DC_DEV1 (void*)0xb8010010
++#define CFG_DC_DEVBASE 0x0
++#define CFG_DC_DEVMASK 0x4
++#define CFG_DC_DEVC 0x8
++#define CFG_DC_DEVTC 0xC
++
++
++static int __init plat_setup_devices(void)
++{
++ /* Look for the CF card reader */
++ if (!readl(CFG_DC_DEV1 + CFG_DC_DEVMASK))
++ rb500_devs[1] = NULL;
++ else {
++ cf_slot0_res[0].start = readl(CFG_DC_DEV1 + CFG_DC_DEVBASE);
++ cf_slot0_res[0].end = cf_slot0_res[0].start + 0x1000;
++ }
++
++ return platform_add_devices(rb500_devs, ARRAY_SIZE(rb500_devs));
++}
++
++static int __init setup_kmac(char *s)
++{
++ printk("korina mac = %s\n",s);
++ parse_mac_addr(s);
++ return 0;
++}
++
++__setup("kmac=", setup_kmac);
++arch_initcall(plat_setup_devices);
++
++
++#if defined(CONFIG_MTD_BLOCK2MTD) && defined(CONFIG_BLK_DEV_CF_MIPS)
++extern void block2mtd_setup(char *initstr);
++extern void mount_devfs_fs(void);
++
++static int __init setup_mtd(void)
++{
++ struct hd_struct **part;
++ int num = 0, i;
++ char initstr[64];
++
++ if (cf_slot0_data.gd == NULL)
++ return 0;
++
++ /* count partitions */
++ part = cf_slot0_data.gd->part;
++ while (part[num] != NULL) {
++ num++;
++ }
++
++ if (num < 2)
++ return 0;
++
++ mount_devfs_fs();
++ printk("Setting up block2mtd devices\n");
++
++ block2mtd_setup("/dev/cf/card0/part1,131072,kernel");
++ block2mtd_setup("/dev/cf/card0/part2,131072,rootfs");
++
++ for (i = 2; part[i]; i++) {
++ sprintf(initstr, "/dev/cf/card0/part%d,131072,part%d", i + 1, i + 1);
++ block2mtd_setup(initstr);
++ }
++
++ return 0;
++}
++
++late_initcall(setup_mtd);
++#endif
+diff -urN linux.old/arch/mips/rb500/early_serial.c linux.dev/arch/mips/rb500/early_serial.c
+--- linux.old/arch/mips/rb500/early_serial.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/rb500/early_serial.c 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,199 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * EB434 specific polling driver for 16550 UART.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * Copyright (C) 2000 by Lineo, Inc.
++ * Written by Quinn Jensen (jensenq@lineo.com)
++ **************************************************************************
++ * P. Sadik Oct 20, 2003
++ *
++ * DIVISOR is made a function of idt_cpu_freq
++ **************************************************************************
++ * P. Sadik Oct 30, 2003
++ *
++ * added reset_cons_port
++ **************************************************************************
++ */
++
++#include <linux/serial_reg.h>
++
++/* turn this on to watch the debug protocol echoed on the console port */
++#define DEBUG_REMOTE_DEBUG
++
++#define CONS_BAUD 115200
++
++extern unsigned int idt_cpu_freq;
++
++#define EXT_FREQ 24000000
++#define INT_FREQ idt_cpu_freq
++
++#define EXT_PORT 0xb9800000u
++#define EXT_SHIFT 0
++
++#ifdef __MIPSEB__
++#define INT_PORT 0xb8058003u
++#else
++#define INT_PORT 0xb8058000u
++#endif
++#define INT_SHIFT 2
++
++#define INT_FCR UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | UART_FCR_TRIGGER_14
++#define EXT_FCR UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT
++
++typedef struct
++{
++ volatile unsigned char *base;
++ unsigned int shift;
++ unsigned int freq;
++ unsigned int fcr;
++} ser_port;
++
++ser_port ports[2] =
++{
++ { (volatile unsigned char *)INT_PORT, INT_SHIFT, 0, INT_FCR},
++ { (volatile unsigned char *)EXT_PORT, EXT_SHIFT, EXT_FREQ, EXT_FCR}
++};
++
++#define CONS_PORT 0
++
++void cons_putc(char c);
++int port_getc(int port);
++void port_putc(int port, char c);
++
++int cons_getc(void)
++{
++ return port_getc(CONS_PORT);
++}
++
++void cons_putc(char c)
++{
++ port_putc(CONS_PORT, c);
++}
++
++void cons_puts(char *s)
++{
++ while(*s) {
++ if(*s == '\n') cons_putc('\r');
++ cons_putc(*s);
++ s++;
++ }
++}
++
++void cons_do_putn(int n)
++{
++ if(n) {
++ cons_do_putn(n / 10);
++ cons_putc(n % 10 + '0');
++ }
++}
++
++void cons_putn(int n)
++{
++ if(n < 0) {
++ cons_putc('-');
++ n = -n;
++ }
++
++ if (n == 0) {
++ cons_putc('0');
++ } else {
++ cons_do_putn(n);
++ }
++}
++
++int port_getc(int p)
++{
++ volatile unsigned char *port = ports[p].base;
++ int s = ports[p].shift;
++ int c;
++
++ while((*(port + (UART_LSR << s)) & UART_LSR_DR) == 0) {
++ continue;
++ }
++
++ c = *(port + (UART_RX << s));
++
++ return c;
++}
++
++int port_getc_ready(int p)
++{
++ volatile unsigned char *port = ports[p].base;
++ int s = ports[p].shift;
++
++ return *(port + (UART_LSR << s)) & UART_LSR_DR;
++}
++
++#define OK_TO_XMT (UART_LSR_TEMT | UART_LSR_THRE)
++
++void port_putc(int p, char c)
++{
++ volatile unsigned char *port = ports[p].base;
++ int s = ports[p].shift;
++ volatile unsigned char *lsr = port + (UART_LSR << s);
++
++ while((*lsr & OK_TO_XMT) != OK_TO_XMT) {
++ continue;
++ }
++
++ *(port + (UART_TX << s)) = c;
++}
++
++void reset_cons_port(void)
++{
++ volatile unsigned char *port = ports[CONS_PORT].base;
++ unsigned int s = ports[CONS_PORT].shift;
++ unsigned int DIVISOR;
++
++ if (ports[CONS_PORT].freq)
++ DIVISOR = (ports[CONS_PORT].freq / 16 / CONS_BAUD);
++ else
++ DIVISOR = (idt_cpu_freq / 16 / CONS_BAUD);
++
++ /* reset the port */
++ *(port + (UART_CSR << s)) = 0;
++
++ /* clear and enable the FIFOs */
++ *(port + (UART_FCR << s)) = ports[CONS_PORT].fcr;
++
++ /* set the baud rate */
++ *(port + (UART_LCR << s)) = UART_LCR_DLAB; /* enable DLL, DLM registers */
++
++ *(port + (UART_DLL << s)) = DIVISOR;
++ *(port + (UART_DLM << s)) = DIVISOR >> 8;
++ /* set the line control stuff and disable DLL, DLM regs */
++
++ *(port + (UART_LCR << s)) = UART_LCR_STOP | /* 2 stop bits */
++ UART_LCR_WLEN8; /* 8 bit word length */
++
++ /* leave interrupts off */
++ *(port + (UART_IER << s)) = 0;
++
++ /* the modem controls don't leave the chip on this port, so leave them alone */
++ *(port + (UART_MCR << s)) = 0;
++}
+diff -urN linux.old/arch/mips/rb500/irq.c linux.dev/arch/mips/rb500/irq.c
+--- linux.old/arch/mips/rb500/irq.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/rb500/irq.c 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,264 @@
++/*
++ * BRIEF MODULE DESCRIPTION
++ * RC32434 interrupt routines.
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ * Author: MontaVista Software, Inc.
++ * stevel@mvista.com or source@mvista.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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 <linux/errno.h>
++#include <linux/init.h>
++#include <linux/kernel_stat.h>
++#include <linux/module.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/timex.h>
++#include <linux/slab.h>
++#include <linux/random.h>
++#include <linux/delay.h>
++
++#include <asm/bitops.h>
++#include <asm/bootinfo.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/time.h>
++#include <asm/mipsregs.h>
++#include <asm/system.h>
++#include <asm/rc32434/rc32434.h>
++#include <asm/rc32434/gpio.h>
++
++extern void set_debug_traps(void);
++extern irq_cpustat_t irq_stat [NR_CPUS];
++unsigned int local_bh_count[NR_CPUS];
++unsigned int local_irq_count[NR_CPUS];
++
++static unsigned int startup_irq(unsigned int irq);
++static void rb500_end_irq(unsigned int irq_nr);
++static void mask_and_ack_irq(unsigned int irq_nr);
++static void rb500_enable_irq(unsigned int irq_nr);
++static void rb500_disable_irq(unsigned int irq_nr);
++
++extern void __init init_generic_irq(void);
++
++typedef struct {
++ u32 mask; /* mask of valid bits in pending/mask registers */
++ volatile u32 *base_addr;
++} intr_group_t;
++
++#define RC32434_NR_IRQS (GROUP4_IRQ_BASE + 32)
++
++#if (NR_IRQS < RC32434_NR_IRQS)
++#error Too little irqs defined. Did you override <asm/irq.h> ?
++#endif
++
++static const intr_group_t intr_group[NUM_INTR_GROUPS] = {
++ { 0x0000efff, (u32 *)KSEG1ADDR(IC_GROUP0_PEND + 0 * IC_GROUP_OFFSET) },
++ { 0x00001fff, (u32 *)KSEG1ADDR(IC_GROUP0_PEND + 1 * IC_GROUP_OFFSET) },
++ { 0x00000007, (u32 *)KSEG1ADDR(IC_GROUP0_PEND + 2 * IC_GROUP_OFFSET) },
++ { 0x0003ffff, (u32 *)KSEG1ADDR(IC_GROUP0_PEND + 3 * IC_GROUP_OFFSET) },
++ { 0xffffffff, (u32 *)KSEG1ADDR(IC_GROUP0_PEND + 4 * IC_GROUP_OFFSET) }
++};
++
++#define READ_PEND(base) (*(base))
++#define READ_MASK(base) (*(base + 2))
++#define WRITE_MASK(base, val) (*(base + 2) = (val))
++
++static inline int irq_to_group(unsigned int irq_nr)
++{
++ return ((irq_nr - GROUP0_IRQ_BASE) >> 5);
++}
++
++static inline int group_to_ip(unsigned int group)
++{
++ return group + 2;
++}
++
++static inline void enable_local_irq(unsigned int ip)
++{
++ int ipnum = 0x100 << ip;
++ clear_c0_cause(ipnum);
++ set_c0_status(ipnum);
++}
++
++static inline void disable_local_irq(unsigned int ip)
++{
++ int ipnum = 0x100 << ip;
++ clear_c0_status(ipnum);
++}
++
++static inline void ack_local_irq(unsigned int ip)
++{
++ int ipnum = 0x100 << ip;
++ clear_c0_cause(ipnum);
++}
++
++static void rb500_enable_irq(unsigned int irq_nr)
++{
++ int ip = irq_nr - GROUP0_IRQ_BASE;
++ unsigned int group, intr_bit;
++ volatile unsigned int *addr;
++
++
++ if (ip < 0)
++ enable_local_irq(irq_nr);
++ else {
++ group = ip >> 5;
++
++ ip &= (1<<5)-1;
++ intr_bit = 1 << ip;
++
++ enable_local_irq(group_to_ip(group));
++
++ addr = intr_group[group].base_addr;
++ WRITE_MASK(addr, READ_MASK(addr) & ~intr_bit);
++ }
++}
++
++static void rb500_disable_irq(unsigned int irq_nr)
++{
++ int ip = irq_nr - GROUP0_IRQ_BASE;
++ unsigned int group, intr_bit, mask;
++ volatile unsigned int *addr;
++
++ if (ip < 0) {
++ disable_local_irq(irq_nr);
++ }else{
++ group = ip >> 5;
++
++ ip &= (1<<5) -1;
++ intr_bit = 1 << ip;
++ addr = intr_group[group].base_addr;
++ mask = READ_MASK(addr);
++ mask |= intr_bit;
++ WRITE_MASK(addr,mask);
++
++ /*
++ * if there are no more interrupts enabled in this
++ * group, disable corresponding IP
++ */
++ if (mask == intr_group[group].mask)
++ disable_local_irq(group_to_ip(group));
++ }
++}
++
++static unsigned int startup_irq(unsigned int irq_nr)
++{
++ rb500_enable_irq(irq_nr);
++ return 0;
++}
++
++static void shutdown_irq(unsigned int irq_nr)
++{
++ rb500_disable_irq(irq_nr);
++ return;
++}
++
++static void mask_and_ack_irq(unsigned int irq_nr)
++{
++ rb500_disable_irq(irq_nr);
++ ack_local_irq(group_to_ip(irq_to_group(irq_nr)));
++}
++
++static void rb500_end_irq(unsigned int irq_nr)
++{
++
++ int ip = irq_nr - GROUP0_IRQ_BASE;
++ unsigned int intr_bit, group;
++ volatile unsigned int *addr;
++
++ if ((irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
++ printk("warning: end_irq %d did not enable (%x)\n",
++ irq_nr, irq_desc[irq_nr].status);
++ return;
++ }
++
++ if (ip < 0) {
++ enable_local_irq(irq_nr);
++ } else {
++ group = ip >> 5;
++
++ ip &= (1 << 5) - 1;
++ intr_bit = 1 << ip;
++
++ if (irq_nr >= GROUP4_IRQ_BASE && irq_nr <= (GROUP4_IRQ_BASE + 13)) {
++ gpio->gpioistat = gpio->gpioistat & ~intr_bit;
++ }
++
++ enable_local_irq(group_to_ip(group));
++
++ addr = intr_group[group].base_addr;
++ WRITE_MASK(addr, READ_MASK(addr) & ~intr_bit);
++ }
++}
++
++static struct hw_interrupt_type rc32434_irq_type = {
++ .typename = "RB500",
++ .startup = startup_irq,
++ .shutdown = shutdown_irq,
++ .enable = rb500_enable_irq,
++ .disable = rb500_disable_irq,
++ .ack = mask_and_ack_irq,
++ .end = rb500_end_irq,
++};
++
++
++void __init arch_init_irq(void)
++{
++ int i;
++
++ printk("Initializing IRQ's: %d out of %d\n", RC32434_NR_IRQS, NR_IRQS);
++ memset(irq_desc, 0, sizeof(irq_desc));
++
++ for (i = 0; i < RC32434_NR_IRQS; i++) {
++ irq_desc[i].status = IRQ_DISABLED;
++ irq_desc[i].action = NULL;
++ irq_desc[i].depth = 1;
++ irq_desc[i].handler = &rc32434_irq_type;
++ spin_lock_init(&irq_desc[i].lock);
++ }
++}
++
++/* Main Interrupt dispatcher */
++asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
++{
++ unsigned int ip, pend, group;
++ volatile unsigned int *addr;
++ unsigned int cp0_cause = read_c0_cause() & read_c0_status();
++
++ if (cp0_cause & CAUSEF_IP7) {
++ ll_timer_interrupt(7, regs);
++ } else if ((ip = (cp0_cause & 0x7c00))) {
++ group = 21 - rc32434_clz(ip);
++
++ addr = intr_group[group].base_addr;
++
++ pend = READ_PEND(addr);
++ pend &= ~READ_MASK(addr); // only unmasked interrupts
++ pend = 39 - rc32434_clz(pend);
++ do_IRQ((group << 5) + pend, regs);
++ }
++}
+diff -urN linux.old/arch/mips/rb500/Makefile linux.dev/arch/mips/rb500/Makefile
+--- linux.old/arch/mips/rb500/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/rb500/Makefile 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,5 @@
++#
++# Makefile for the RB500 board specific parts of the kernel
++#
++
++obj-y += irq.o time.o setup.o serial.o early_serial.o prom.o misc.o devices.o
+diff -urN linux.old/arch/mips/rb500/misc.c linux.dev/arch/mips/rb500/misc.c
+--- linux.old/arch/mips/rb500/misc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/rb500/misc.c 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,54 @@
++#include <linux/module.h>
++#include <linux/kernel.h> /* printk() */
++#include <linux/types.h> /* size_t */
++#include <linux/pci.h>
++#include <linux/spinlock.h>
++#include <asm/rc32434/rb.h>
++
++#define GPIO_BADDR 0xb8050000
++
++
++static unsigned char *devCtl3Base = (unsigned char *) KSEG1ADDR(0x18010030);
++static unsigned char latchU5State = 0;
++static spinlock_t clu5Lock = SPIN_LOCK_UNLOCKED;
++
++void set434Reg(unsigned regOffs, unsigned bit, unsigned len, unsigned val) {
++ unsigned flags, data;
++ unsigned i = 0;
++ spin_lock_irqsave(&clu5Lock, flags);
++ data = *(volatile unsigned *) (IDT434_REG_BASE + regOffs);
++ for (i = 0; i != len; ++i) {
++ if (val & (1 << i)) data |= (1 << (i + bit));
++ else data &= ~(1 << (i + bit));
++ }
++ *(volatile unsigned *) (IDT434_REG_BASE + regOffs) = data;
++ spin_unlock_irqrestore(&clu5Lock, flags);
++}
++
++void changeLatchU5(unsigned char orMask, unsigned char nandMask) {
++ unsigned flags;
++ spin_lock_irqsave(&clu5Lock, flags);
++ latchU5State = (latchU5State | orMask) & ~nandMask;
++ *devCtl3Base = latchU5State;
++ spin_unlock_irqrestore(&clu5Lock, flags);
++}
++
++u32 gpio_get(gpio_func func)
++{
++ return readl((void *) GPIO_BADDR + func);
++}
++
++void gpio_set(gpio_func func, u32 mask, u32 value)
++{
++ u32 val = readl((void *) GPIO_BADDR + func);
++
++ val &= ~mask;
++ val |= value & mask;
++
++ writel(val, (void *) GPIO_BADDR + func);
++}
++
++EXPORT_SYMBOL(gpio_set);
++EXPORT_SYMBOL(gpio_get);
++EXPORT_SYMBOL(set434Reg);
++EXPORT_SYMBOL(changeLatchU5);
+diff -urN linux.old/arch/mips/rb500/prom.c linux.dev/arch/mips/rb500/prom.c
+--- linux.old/arch/mips/rb500/prom.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/rb500/prom.c 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,181 @@
++/*
++* prom.c
++**********************************************************************
++* P . Sadik Oct 10, 2003
++*
++* Started change log
++* idt_cpu_freq is make a kernel configuration parameter
++* idt_cpu_freq is exported so that other modules can use it.
++* Code cleanup
++**********************************************************************
++* P. Sadik Oct 20, 2003
++*
++* Removed NVRAM code from here, since they are already available under
++* nvram directory.
++* Added serial port initialisation.
++**********************************************************************
++**********************************************************************
++* P. Sadik Oct 30, 2003
++*
++* Added reset_cons_port
++**********************************************************************
++
++ P.Christeas, 2005-2006
++ Port to 2.6, add 2.6 cmdline parsing
++
++*/
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/console.h>
++#include <asm/bootinfo.h>
++#include <linux/bootmem.h>
++#include <linux/ioport.h>
++#include <linux/blkdev.h>
++#include <asm/rc32434/ddr.h>
++
++#define PROM_ENTRY(x) (0xbfc00000+((x)*8))
++extern void __init setup_serial_port(void);
++extern void cons_putc(char c);
++extern void cons_puts(char *s);
++
++unsigned int idt_cpu_freq = 132000000;
++EXPORT_SYMBOL(idt_cpu_freq);
++unsigned int board_type = 500;
++EXPORT_SYMBOL(board_type);
++unsigned int gpio_bootup_state = 0;
++EXPORT_SYMBOL(gpio_bootup_state);
++
++
++char mips_mac_address[18] = "08:00:06:05:40:01";
++EXPORT_SYMBOL(mips_mac_address);
++
++/* what to append to cmdline when button is [not] pressed */
++#define GPIO_INIT_NOBUTTON ""
++#define GPIO_INIT_BUTTON " 2"
++
++#ifdef CONFIG_MIKROTIK_RB500
++unsigned soft_reboot = 0;
++EXPORT_SYMBOL(soft_reboot);
++#endif
++
++#define SR_NMI 0x00180000 /* NMI */
++#define SERIAL_SPEED_ENTRY 0x00000001
++
++#ifdef CONFIG_REMOTE_DEBUG
++extern int remote_debug;
++#endif
++
++extern unsigned long mips_machgroup;
++extern unsigned long mips_machtype;
++
++#define FREQ_TAG "HZ="
++#define GPIO_TAG "gpio="
++#define KMAC_TAG "kmac="
++#define MEM_TAG "mem="
++#define BOARD_TAG "board="
++#define IGNORE_CMDLINE_MEM 1
++#define DEBUG_DDR
++
++void parse_soft_settings(unsigned *ptr, unsigned size);
++void parse_hard_settings(unsigned *ptr, unsigned size);
++
++void __init prom_setup_cmdline(void);
++
++#ifdef DEBUG_DDR
++void cons_puthex4(u32 h){
++ h&=0x0f;
++ if (h>=10)
++ cons_putc((h-10)+'a');
++ else
++ cons_putc(h+'0');
++}
++
++void cons_putreg32(u32 reg){
++ char c;
++ cons_putc('0');
++ cons_putc('x');
++ for (c=28;c>=0;c-=4)
++ cons_puthex4(reg>>c);
++}
++#endif
++
++void __init prom_init(void)
++{
++ DDR_t ddr = (DDR_t) DDR_VirtualAddress; /* define the pointer to the DDR registers */
++ phys_t memsize = 0-ddr->ddrmask;
++
++ /* this should be the very first message, even before serial is properly initialized */
++ prom_setup_cmdline();
++ setup_serial_port();
++
++ mips_machgroup = MACH_GROUP_MIKROTIK;
++ soft_reboot = read_c0_status() & SR_NMI;
++ pm_power_off = NULL;
++
++ /*
++ * give all RAM to boot allocator,
++ * except for the first 0x400 and the last 0x200 bytes
++ */
++ add_memory_region(ddr->ddrbase + 0x400, memsize - 0x600, BOOT_MEM_RAM);
++}
++
++void prom_free_prom_memory(void)
++{
++ /* FIXME: STUB */
++}
++
++void __init prom_setup_cmdline(void){
++ char cmd_line[CL_SIZE];
++ char *cp;
++ int prom_argc;
++ char **prom_argv, **prom_envp;
++ int i;
++
++ prom_argc = fw_arg0;
++ prom_argv = (char **) fw_arg1;
++ prom_envp = (char **) fw_arg2;
++
++ cp=cmd_line;
++ /* Note: it is common that parameters start at argv[1] and not argv[0],
++ however, our elf loader starts at [0] */
++ for(i=0;i<prom_argc;i++){
++ if (strncmp(prom_argv[i], FREQ_TAG, sizeof(FREQ_TAG) - 1) == 0) {
++ idt_cpu_freq = simple_strtoul(prom_argv[i] + sizeof(FREQ_TAG) - 1, 0, 10);
++ continue;
++ }
++#ifdef IGNORE_CMDLINE_MEM
++ /* parses out the "mem=xx" arg */
++ if (strncmp(prom_argv[i], MEM_TAG, sizeof(MEM_TAG) - 1) == 0) {
++ continue;
++ }
++#endif
++ if (i>0) *(cp++) = ' ';
++ if (strncmp(prom_argv[i], BOARD_TAG, sizeof(BOARD_TAG) - 1) == 0) {
++ board_type = simple_strtoul(prom_argv[i] + sizeof(BOARD_TAG) - 1, 0, 10);
++ }
++ if (strncmp(prom_argv[i], GPIO_TAG, sizeof(GPIO_TAG) - 1) == 0) {
++ gpio_bootup_state = simple_strtoul(prom_argv[i] + sizeof(GPIO_TAG) - 1, 0, 10);
++ }
++ strcpy(cp,prom_argv[i]);
++ cp+=strlen(prom_argv[i]);
++ }
++
++ i=strlen(arcs_cmdline);
++ if (i>0){
++ *(cp++) = ' ';
++ strcpy(cp,arcs_cmdline);
++ cp+=strlen(arcs_cmdline);
++ }
++ if (gpio_bootup_state&0x02)
++ strcpy(cp,GPIO_INIT_NOBUTTON);
++ else
++ strcpy(cp,GPIO_INIT_BUTTON);
++ cmd_line[CL_SIZE-1] = '\0';
++
++ strcpy(arcs_cmdline,cmd_line);
++}
++
+diff -urN linux.old/arch/mips/rb500/serial.c linux.dev/arch/mips/rb500/serial.c
+--- linux.old/arch/mips/rb500/serial.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/rb500/serial.c 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,79 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Serial port initialisation.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/pci.h>
++#include <linux/interrupt.h>
++#include <linux/tty.h>
++#include <linux/serial.h>
++#include <linux/serial_core.h>
++
++#include <asm/time.h>
++#include <asm/cpu.h>
++#include <asm/bootinfo.h>
++#include <asm/irq.h>
++#include <asm/serial.h>
++#include <asm/rc32434/rc32434.h>
++
++extern unsigned int idt_cpu_freq;
++
++static struct uart_port serial_req = {
++ .type = PORT_16550A,
++ .line = 0,
++ .irq = RC32434_UART0_IRQ,
++ .flags = STD_COM_FLAGS,
++ .iotype = UPIO_MEM,
++ .membase = (char *) KSEG1ADDR(RC32434_UART0_BASE),
++// .fifosize = 14
++ .regshift = 2
++};
++
++int __init setup_serial_port(void)
++{
++ serial_req.uartclk = idt_cpu_freq;
++
++ if (early_serial_setup(&serial_req)){
++ cons_puts("Serial setup failed!\n");
++ return -ENODEV;
++ }
++
++ return(0);
++}
+diff -urN linux.old/arch/mips/rb500/setup.c linux.dev/arch/mips/rb500/setup.c
+--- linux.old/arch/mips/rb500/setup.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/rb500/setup.c 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,84 @@
++/*
++ * setup.c - boot time setup code
++ */
++
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/irq.h>
++#include <asm/bootinfo.h>
++#include <asm/io.h>
++#include <linux/ioport.h>
++#include <asm/mipsregs.h>
++#include <asm/pgtable.h>
++#include <asm/reboot.h>
++#include <asm/addrspace.h> /* for KSEG1ADDR() */
++#include <asm/rc32434/rc32434.h>
++#include <linux/pm.h>
++#include <asm/rc32434/pci.h>
++
++extern void (*board_time_init)(void);
++extern void (*board_timer_setup)(struct irqaction *irq);
++extern void rc32434_time_init(void);
++extern void rc32434_timer_setup(struct irqaction *irq);
++#ifdef CONFIG_PCI
++extern int __init rc32434_pcibridge_init(void);
++#endif
++
++#define epldMask ((volatile unsigned char *)0xB900000d)
++
++static void rb_machine_restart(char *command)
++{
++ /* just jump to the reset vector */
++ * (volatile unsigned *) KSEG1ADDR(0x18008000) = 0x80000001;
++ ((void (*)(void))KSEG1ADDR(0x1FC00000u))();
++}
++
++static void rb_machine_halt(void)
++{
++ for(;;) continue;
++}
++
++#ifdef CONFIG_CPU_HAS_WB
++void (*__wbflush) (void);
++
++static void rb_write_buffer_flush(void)
++{
++ __asm__ __volatile__
++ ("sync\n\t" "nop\n\t" "loop: bc0f loop\n\t" "nop\n\t");
++}
++#endif
++
++void __init plat_setup(void)
++{
++ unsigned int pciCntlVal;
++
++ board_time_init = rc32434_time_init;
++ board_timer_setup = rc32434_timer_setup;
++
++#ifdef CONFIG_CPU_HAS_WB
++ __wbflush = rb_write_buffer_flush;
++#endif
++ _machine_restart = rb_machine_restart;
++ _machine_halt = rb_machine_halt;
++ /*_machine_power_off = rb_machine_power_halt;*/
++ pm_power_off = rb_machine_halt;
++
++ set_io_port_base(KSEG1);
++
++ pciCntlVal=rc32434_pci->pcic;
++ pciCntlVal &= 0xFFFFFF7;
++ rc32434_pci->pcic = pciCntlVal;
++
++#ifdef CONFIG_PCI
++ /* Enable PCI interrupts in EPLD Mask register */
++ *epldMask = 0x0;
++ *(epldMask + 1) = 0x0;
++#endif
++ write_c0_wired(0);
++}
++
++const char *get_system_type(void)
++{
++ return "MIPS RB500";
++}
+diff -urN linux.old/arch/mips/rb500/time.c linux.dev/arch/mips/rb500/time.c
+--- linux.old/arch/mips/rb500/time.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/rb500/time.c 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,94 @@
++/*
++****************************************************************************
++* Carsten Langgaard, carstenl@mips.com
++* Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
++*
++***************************************************************************
++*
++* This program is free software; you can distribute 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 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.
++*
++****************************************************************************
++*
++* Setting up the clock on the MIPS boards.
++*
++****************************************************************************
++* P. Sadik Oct 10, 2003
++*
++* Started change log.
++* mips_counter_frequency is now calculated at run time, based on idt_cpu_freq.
++* Code cleanup
++****************************************************************************
++*/
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/kernel_stat.h>
++#include <linux/sched.h>
++#include <linux/spinlock.h>
++#include <linux/mc146818rtc.h>
++#include <linux/irq.h>
++#include <linux/timex.h>
++
++#include <asm/mipsregs.h>
++#include <asm/ptrace.h>
++#include <asm/debug.h>
++#include <asm/rc32434/rc32434.h>
++
++static unsigned long r4k_offset; /* Amount to incr compare reg each time */
++static unsigned long r4k_cur; /* What counter should be at next timer irq */
++extern void ll_timer_interrupt(int irq, struct pt_regs *regs);
++extern unsigned int mips_hpt_frequency;
++extern unsigned int idt_cpu_freq;
++
++/*
++ * Figure out the r4k offset, the amount to increment the compare
++ * register for each time tick. There is no RTC available.
++ *
++ * The RC32434 counts at half the CPU *core* speed.
++ */
++static unsigned long __init cal_r4koff(void)
++{
++ mips_hpt_frequency = idt_cpu_freq * IDT_CLOCK_MULT / 2;
++ return (mips_hpt_frequency / HZ);
++}
++
++
++void __init rc32434_time_init(void)
++{
++ unsigned int est_freq, flags;
++
++ local_irq_save(flags);
++
++ printk("calculating r4koff... ");
++ r4k_offset = cal_r4koff();
++ printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);
++
++ est_freq = 2*r4k_offset*HZ;
++ est_freq += 5000; /* round */
++ est_freq -= est_freq%10000;
++ printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
++ (est_freq%1000000)*100/1000000);
++ local_irq_restore(flags);
++}
++
++void __init rc32434_timer_setup(struct irqaction *irq)
++{
++ /* we are using the cpu counter for timer interrupts */
++ setup_irq(MIPS_CPU_TIMER_IRQ, irq);
++
++ /* to generate the first timer interrupt */
++ r4k_cur = (read_c0_count() + r4k_offset);
++ write_c0_compare(r4k_cur);
++}
++
+diff -urN linux.old/drivers/mtd/devices/block2mtd.c linux.dev/drivers/mtd/devices/block2mtd.c
+--- linux.old/drivers/mtd/devices/block2mtd.c 2006-10-11 21:55:59.000000000 +0200
++++ linux.dev/drivers/mtd/devices/block2mtd.c 2006-10-11 22:24:51.000000000 +0200
+@@ -26,7 +26,6 @@
+ #define ERROR(fmt, args...) printk(KERN_ERR "block2mtd: " fmt "\n" , ## args)
+ #define INFO(fmt, args...) printk(KERN_INFO "block2mtd: " fmt "\n" , ## args)
+
+-
+ /* Info for the block device */
+ struct block2mtd_dev {
+ struct list_head list;
+@@ -104,7 +103,7 @@
+
+ while (pages) {
+ page = page_readahead(mapping, index);
+- if (!page)
++ if (!page || !page_address(page))
+ return -ENOMEM;
+ if (IS_ERR(page))
+ return PTR_ERR(page);
+@@ -285,7 +284,7 @@
+
+
+ /* FIXME: ensure that mtd->size % erase_size == 0 */
+-static struct block2mtd_dev *add_device(char *devname, int erase_size)
++static struct block2mtd_dev *add_device(char *devname, int erase_size, char *alias)
+ {
+ struct block_device *bdev;
+ struct block2mtd_dev *dev;
+@@ -328,14 +327,15 @@
+
+ /* Setup the MTD structure */
+ /* make the name contain the block device in */
+- dev->mtd.name = kmalloc(sizeof("block2mtd: ") + strlen(devname),
++ dev->mtd.name = kmalloc(strlen((alias ?: devname)),
+ GFP_KERNEL);
+ if (!dev->mtd.name)
+ goto devinit_err;
+
+- sprintf(dev->mtd.name, "block2mtd: %s", devname);
++ strcpy(dev->mtd.name, (alias ?: devname));
+
+ dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
++ dev->mtd.size -= dev->mtd.size % erase_size;
+ dev->mtd.erasesize = erase_size;
+ dev->mtd.type = MTD_RAM;
+ dev->mtd.flags = MTD_CAP_RAM;
+@@ -353,7 +353,7 @@
+ }
+ list_add(&dev->list, &blkmtd_device_list);
+ INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index,
+- dev->mtd.name + strlen("blkmtd: "),
++ dev->mtd.name,
+ dev->mtd.erasesize >> 10, dev->mtd.erasesize);
+ return dev;
+
+@@ -429,7 +429,7 @@
+ {
+ char buf[80 + 12]; /* 80 for device, 12 for erase size */
+ char *str = buf;
+- char *token[2];
++ char *token[3];
+ char *name;
+ size_t erase_size = PAGE_SIZE;
+ int i, ret;
+@@ -440,7 +440,7 @@
+ strcpy(str, val);
+ kill_final_newline(str);
+
+- for (i = 0; i < 2; i++)
++ for (i = 0; i < 3; i++)
+ token[i] = strsep(&str, ",");
+
+ if (str)
+@@ -461,13 +461,13 @@
+ }
+ }
+
+- add_device(name, erase_size);
++ add_device(name, erase_size, token[2]);
+
+ return 0;
+ }
+
+
+-static int block2mtd_setup(const char *val, struct kernel_param *kp)
++int block2mtd_setup(const char *val, struct kernel_param *kp)
+ {
+ #ifdef MODULE
+ return block2mtd_setup2(val);
+@@ -496,6 +496,7 @@
+
+ module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
+ MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
++EXPORT_SYMBOL(block2mtd_setup);
+
+ static int __init block2mtd_init(void)
+ {
+diff -urN linux.old/drivers/pci/Makefile linux.dev/drivers/pci/Makefile
+--- linux.old/drivers/pci/Makefile 2006-06-18 03:49:35.000000000 +0200
++++ linux.dev/drivers/pci/Makefile 2006-10-11 21:56:38.000000000 +0200
+@@ -27,6 +27,7 @@
+ obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
+ obj-$(CONFIG_X86_VISWS) += setup-irq.o
+ obj-$(CONFIG_PCI_MSI) += msi.o
++obj-$(CONFIG_MIKROTIK_RB500) += setup-irq.o
+
+ #
+ # ACPI Related PCI FW Functions
+diff -urN linux.old/include/asm-mips/bootinfo.h linux.dev/include/asm-mips/bootinfo.h
+--- linux.old/include/asm-mips/bootinfo.h 2006-06-18 03:49:35.000000000 +0200
++++ linux.dev/include/asm-mips/bootinfo.h 2006-10-11 21:56:38.000000000 +0200
+@@ -218,6 +218,8 @@
+ #define MACH_GROUP_TITAN 22 /* PMC-Sierra Titan */
+ #define MACH_TITAN_YOSEMITE 1 /* PMC-Sierra Yosemite */
+
++#define MACH_GROUP_MIKROTIK 24 /* Mikrotik Boards */
++
+ #define CL_SIZE COMMAND_LINE_SIZE
+
+ const char *get_system_type(void);
+diff -urN linux.old/include/asm-mips/cpu.h linux.dev/include/asm-mips/cpu.h
+--- linux.old/include/asm-mips/cpu.h 2006-06-18 03:49:35.000000000 +0200
++++ linux.dev/include/asm-mips/cpu.h 2006-10-11 21:56:38.000000000 +0200
+@@ -200,7 +200,8 @@
+ #define CPU_SB1A 62
+ #define CPU_74K 63
+ #define CPU_R14000 64
+-#define CPU_LAST 64
++#define CPU_RC32300 65
++#define CPU_LAST 65
+
+ /*
+ * ISA Level encodings
+diff -urN linux.old/include/asm-mips/rc32434/crom.h linux.dev/include/asm-mips/rc32434/crom.h
+--- linux.old/include/asm-mips/rc32434/crom.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/crom.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,98 @@
++#ifndef __IDT_CROM_H__
++#define __IDT_CROM_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * Configuration ROM register definitions.
++ *
++ * File : $Id: crom.h,v 1.2 2002/06/06 18:34:03 astichte Exp $
++ *
++ * Author : Allen.Stichter@idt.com
++ * Date : 20020118
++ * Update :
++ * $Log: crom.h,v $
++ * Revision 1.2 2002/06/06 18:34:03 astichte
++ * Added XXX_PhysicalAddress and XXX_VirtualAddress
++ *
++ * Revision 1.1 2002/05/29 17:33:21 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ *
++ ******************************************************************************/
++
++#include <asm/rc32434/types.h>
++
++enum
++{
++ CROM0_PhysicalAddress = 0x100b8000,
++ CROM_PhysicalAddress = CROM0_PhysicalAddress,
++
++ CROM0_VirtualAddress = 0xb00b8000,
++ CROM_VirtualAddress = CROM0_VirtualAddress,
++} ;
++
++typedef struct CROM_s
++{
++ U32 cromw0 ; // use CROMW0_
++ U32 cromw1 ; // use CROMW1_
++ U32 cromw2 ; // use CROMW2_
++} volatile * CROM_t ;
++
++enum
++{
++ CROMW0_xloc_b = 0,
++ CROMW0_xloc_m = 0x0000003f,
++ CROMW0_yloc_b = 8,
++ CROMW0_yloc_m = 0x00003f00,
++ CROMW0_speed_b = 16,
++ CROMW0_speed_m = 0x01ff0000,
++ CROMW1_wafer_b = 0,
++ CROMW1_wafer_m = 0x0000001f,
++ CROMW1_lot_b = 8,
++ CROMW1_lot_m = 0x0fffff00,
++ CROMW1_fab_b = 28,
++ CROMW1_fab_m = 0xf0000000,
++ CROMW2_pci_b = 0,
++ CROMW2_pci_m = 0x00000001,
++ CROMW2_eth0_b = 1,
++ CROMW2_eth0_m = 0x00000002,
++ CROMW2_eth1_b = 2,
++ CROMW2_eth1_m = 0x00000004
++ CROMW2_i2c_b = 3,
++ CROMW2_i2c_m = 0x00000008,
++ CROMW2_rng_b = 4,
++ CROMW2_rng_m = 0x00000010,
++ CROMW2_se_b = 5,
++ CROMW2_se_m = 0x00000020,
++ CROMW2_des_b = 6,
++ CROMW2_des_m = 0x00000040,
++ CROMW2_tdes_b = 7,
++ CROMW2_tdes_m = 0x00000080,
++ CROMW2_a128_b = 8,
++ CROMW2_a128_m = 0x00000100,
++ CROMW2_a192_b = 9,
++ CROMW2_a192_m = 0x00000200,
++ CROMW2_a256_b = 10,
++ CROMW2_a256_m = 0x00000400,
++ CROMW2_md5_b = 11,
++ CROMW2_md5_m = 0x00000800,
++ CROMW2_s1_b = 12,
++ CROMW2_s1_m = 0x00001000,
++ CROMW2_s256_b = 13,
++ CROMW2_s256_m = 0x00002000,
++ CROMW2_pka_b = 14,
++ CROMW2_pka_m = 0x00004000,
++ CROMW2_exp_b = 15,
++ CROMW2_exp_m = 0x00018000,
++ CROMW2_exp_8192_v = 0,
++ CROMW2_exp_1536_v = 1,
++ CROMW2_exp_1024_v = 2,
++ CROMW2_exp_512_v = 3,
++ CROMW2_rocfg_b = 17,
++ CROMW2_rocfg_m = 0x000e0000,
++} ;
++
++#endif // __IDT_CROM_H__
+diff -urN linux.old/include/asm-mips/rc32434/ddr.h linux.dev/include/asm-mips/rc32434/ddr.h
+--- linux.old/include/asm-mips/rc32434/ddr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/ddr.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,175 @@
++#ifndef __IDT_DDR_H__
++#define __IDT_DDR_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * DDR register definition.
++ *
++ * File : $Id: ddr.h,v 1.2 2002/06/06 18:34:03 astichte Exp $
++ *
++ * Author : ryan.holmQVist@idt.com
++ * Date : 20011005
++ * Update :
++ * $Log: ddr.h,v $
++ * Revision 1.2 2002/06/06 18:34:03 astichte
++ * Added XXX_PhysicalAddress and XXX_VirtualAddress
++ *
++ * Revision 1.1 2002/05/29 17:33:21 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ *
++ ******************************************************************************/
++
++#include <asm/rc32434/types.h>
++
++enum
++{
++ DDR0_PhysicalAddress = 0x18018000,
++ DDR_PhysicalAddress = DDR0_PhysicalAddress, // Default
++
++ DDR0_VirtualAddress = 0xb8018000,
++ DDR_VirtualAddress = DDR0_VirtualAddress, // Default
++} ;
++
++typedef struct DDR_s
++{
++ U32 ddrbase ;
++ U32 ddrmask ;
++ U32 res1;
++ U32 res2;
++ U32 ddrc ;
++ U32 ddrabase ;
++ U32 ddramask ;
++ U32 ddramap ;
++ U32 ddrcust;
++ U32 ddrrdc;
++ U32 ddrspare;
++} volatile *DDR_t ;
++
++enum
++{
++ DDR0BASE_baseaddr_b = 16,
++ DDR0BASE_baseaddr_m = 0xffff0000,
++
++ DDR0MASK_mask_b = 16,
++ DDR0MASK_mask_m = 0xffff0000,
++
++ DDR1BASE_baseaddr_b = 16,
++ DDR1BASE_baseaddr_m = 0xffff0000,
++
++ DDR1MASK_mask_b = 16,
++ DDR1MASK_mask_m = 0xffff0000,
++
++ DDRC_ata_b = 5,
++ DDRC_ata_m = 0x000000E0,
++ DDRC_dbw_b = 8,
++ DDRC_dbw_m = 0x00000100,
++ DDRC_wr_b = 9,
++ DDRC_wr_m = 0x00000600,
++ DDRC_ps_b = 11,
++ DDRC_ps_m = 0x00001800,
++ DDRC_dtype_b = 13,
++ DDRC_dtype_m = 0x0000e000,
++ DDRC_rfc_b = 16,
++ DDRC_rfc_m = 0x000f0000,
++ DDRC_rp_b = 20,
++ DDRC_rp_m = 0x00300000,
++ DDRC_ap_b = 22,
++ DDRC_ap_m = 0x00400000,
++ DDRC_rcd_b = 23,
++ DDRC_rcd_m = 0x01800000,
++ DDRC_cl_b = 25,
++ DDRC_cl_m = 0x06000000,
++ DDRC_dbm_b = 27,
++ DDRC_dbm_m = 0x08000000,
++ DDRC_sds_b = 28,
++ DDRC_sds_m = 0x10000000,
++ DDRC_atp_b = 29,
++ DDRC_atp_m = 0x60000000,
++ DDRC_re_b = 31,
++ DDRC_re_m = 0x80000000,
++
++ DDRRDC_ces_b = 0,
++ DDRRDC_ces_m = 0x00000001,
++ DDRRDC_ace_b = 1,
++ DDRRDC_ace_m = 0x00000002,
++
++ DDRABASE_baseaddr_b = 16,
++ DDRABASE_baseaddr_m = 0xffff0000,
++
++ DDRAMASK_mask_b = 16,
++ DDRAMASK_mask_m = 0xffff0000,
++
++ DDRAMAP_map_b = 16,
++ DDRAMAP_map_m = 0xffff0000,
++
++ DDRCUST_cs_b = 0,
++ DDRCUST_cs_m = 0x00000003,
++ DDRCUST_we_b = 2,
++ DDRCUST_we_m = 0x00000004,
++ DDRCUST_ras_b = 3,
++ DDRCUST_ras_m = 0x00000008,
++ DDRCUST_cas_b = 4,
++ DDRCUST_cas_m = 0x00000010,
++ DDRCUST_cke_b = 5,
++ DDRCUST_cke_m = 0x00000020,
++ DDRCUST_ba_b = 6,
++ DDRCUST_ba_m = 0x000000c0,
++
++ RCOUNT_rcount_b = 0,
++ RCOUNT_rcount_m = 0x0000ffff,
++
++ RCOMPARE_rcompare_b = 0,
++ RCOMPARE_rcompare_m = 0x0000ffff,
++
++ RTC_ce_b = 0,
++ RTC_ce_m = 0x00000001,
++ RTC_to_b = 1,
++ RTC_to_m = 0x00000002,
++ RTC_rqe_b = 2,
++ RTC_rqe_m = 0x00000004,
++
++ DDRDQSC_dm_b = 0,
++ DDRDQSC_dm_m = 0x00000003,
++ DDRDQSC_dqsbs_b = 2,
++ DDRDQSC_dqsbs_m = 0x000000fc,
++ DDRDQSC_db_b = 8,
++ DDRDQSC_db_m = 0x00000100,
++ DDRDQSC_dbsp_b = 9,
++ DDRDQSC_dbsp_m = 0x01fffe00,
++ DDRDQSC_bdp_b = 25,
++ DDRDQSC_bdp_m = 0x7e000000,
++
++ DDRDLLC_eao_b = 0,
++ DDRDLLC_eao_m = 0x00000001,
++ DDRDLLC_eo_b = 1,
++ DDRDLLC_eo_m = 0x0000003e,
++ DDRDLLC_fs_b = 6,
++ DDRDLLC_fs_m = 0x000000c0,
++ DDRDLLC_as_b = 8,
++ DDRDLLC_as_m = 0x00000700,
++ DDRDLLC_sp_b = 11,
++ DDRDLLC_sp_m = 0x001ff800,
++
++ DDRDLLFC_men_b = 0,
++ DDRDLLFC_men_m = 0x00000001,
++ DDRDLLFC_aen_b = 1,
++ DDRDLLFC_aen_m = 0x00000002,
++ DDRDLLFC_ff_b = 2,
++ DDRDLLFC_ff_m = 0x00000004,
++
++ DDRDLLTA_addr_b = 2,
++ DDRDLLTA_addr_m = 0xfffffffc,
++
++ DDRDLLED_dbe_b = 0,
++ DDRDLLED_dbe_m = 0x00000001,
++ DDRDLLED_dte_b = 1,
++ DDRDLLED_dte_m = 0x00000002,
++
++
++} ;
++
++#endif // __IDT_DDR_H__
+diff -urN linux.old/include/asm-mips/rc32434/dev.h linux.dev/include/asm-mips/rc32434/dev.h
+--- linux.old/include/asm-mips/rc32434/dev.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/dev.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,134 @@
++#ifndef __IDT_DEV_H__
++#define __IDT_DEV_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * Device Controller register definition.
++ *
++ * File : $Id: dev.h,v 1.2 2002/06/06 18:34:03 astichte Exp $
++ *
++ * Author : John.Ahrens@idt.com
++ * Date : 200112013
++ * Update :
++ * $Log: dev.h,v $
++ * Revision 1.2 2002/06/06 18:34:03 astichte
++ * Added XXX_PhysicalAddress and XXX_VirtualAddress
++ *
++ * Revision 1.1 2002/05/29 17:33:21 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ *
++ ******************************************************************************/
++
++#include <asm/rc32434/types.h>
++
++enum
++{
++ DEV0_PhysicalAddress = 0x18010000,
++ DEV_PhysicalAddress = DEV0_PhysicalAddress, // Default
++
++ DEV0_VirtualAddress = 0xb8010000,
++ DEV_VirtualAddress = DEV0_VirtualAddress, // Default
++} ;
++
++typedef struct DEVICE_s
++{
++ U32 devbase ; // Device Base
++ U32 devmask ; // Device Mask
++ U32 devc ; // Device Control
++ U32 devtc ; // Device Timing Control
++} volatile *DEVICE_t ;
++
++enum
++{
++ DEV_Count = 3,
++} ;
++
++typedef struct DEV_s
++{
++ struct DEVICE_s dev [DEV_Count] ;
++ U32 btcs ; // Bus timeout control / status
++ U32 btcompare ; // Compare
++ U32 btaddr ; // Timeout address.
++ U32 devdacs ; // Decoupled access control.
++ U32 devdaa ; // Decoupled access address.
++ U32 devdad ; // Decoupled access address.
++ U32 devspare ; // spare.
++} volatile *DEV_t ;
++
++enum
++{
++ DEVBASE_baseaddr_b = 16,
++ DEVBASE_baseaddr_m = 0xffff0000,
++ DEVMASK_mask_b = 16,
++ DEVMASK_mask_m = 0xffff0000,
++
++ DEVC_ds_b = 0,
++ DEVC_ds_m = 0x00000003,
++ DEVC_ds_8_v = 0, // 8-bit device.
++ DEVC_ds_16_v = 1, // reserved
++ DEVC_ds_res_v = 2, // reserved.
++ DEVC_ds_res2_v = 3, // reserved.
++ DEVC_be_b = 2,
++ DEVC_be_m = 0x00000004,
++ DEVC_wp_b = 3,
++ DEVC_wp_m = 0x00000008,
++ DEVC_csd_b = 4,
++ DEVC_csd_m = 0x000000f0,
++ DEVC_oed_b = 8,
++ DEVC_oed_m = 0x00000f00,
++ DEVC_bwd_b = 12,
++ DEVC_bwd_m = 0x0000f000,
++ DEVC_rws_b = 16,
++ DEVC_rws_m = 0x003f0000,
++ DEVC_wws_b = 22,
++ DEVC_wws_m = 0x0fc00000,
++ DEVC_bre_b = 28,
++ DEVC_bre_m = 0x10000000,
++ DEVC_bwe_b = 29,
++ DEVC_bwe_m = 0x20000000,
++ DEVC_wam_b = 30,
++ DEVC_wam_m = 0x40000000,
++
++ DEVTC_prd_b = 0,
++ DEVTC_prd_m = 0x0000000f,
++ DEVTC_pwd_b = 4,
++ DEVTC_pwd_m = 0x000000f0,
++ DEVTC_wdh_b = 8,
++ DEVTC_wdh_m = 0x00000700,
++ DEVTC_csh_b = 11,
++ DEVTC_csh_m = 0x00001800,
++
++ BTCS_tt_b = 0,
++ BTCS_tt_m = 0x00000001,
++ BTCS_tt_write = 0,
++ BTCS_tt_read = 1,
++ BTCS_bto_b = 1, // In btcs
++ BTCS_bto_m = 0x00000002, // In btcs
++ BTCS_bte_b = 2, // In btcs
++ BTCS_bte_m = 0x00000004, // In btcs
++
++ BTCOMPARE_compare_b = 0, // In btcompare
++ BTCOMPARE_compare_m = 0x0000ffff, // In btcompare
++
++ DEVDACS_op_b = 0, // In devdacs
++ DEVDACS_op_m = 0x00000001, // In devdacs
++ DEVDACS_op_write_v = 0,
++ DEVDACS_op_read_v = 1,
++ DEVDACS_size_b = 1, // In devdacs
++ DEVDACS_size_m = 0x00000006, // In devdacs
++ DEVDACS_size_byte_v = 0,
++ DEVDACS_size_halfword = 1,
++ DEVDACS_size_triplebyte = 2,
++ DEVDACS_size_word = 3,
++ DEVDACS_err_b = 3, // In devdacs
++ DEVDACS_err_m = 0x00000008, // In devdacs
++ DEVDACS_f_b = 4, // In devdacs
++ DEVDACS_f_m = 0x00000010, // In devdacs
++} ;
++
++#endif //__IDT_DEV_H__
++
+diff -urN linux.old/include/asm-mips/rc32434/dma.h linux.dev/include/asm-mips/rc32434/dma.h
+--- linux.old/include/asm-mips/rc32434/dma.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/dma.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,202 @@
++#ifndef __IDT_DMA_H__
++#define __IDT_DMA_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * DMA register definition.
++ *
++ * File : $Id: dma.h,v 1.3 2002/06/06 18:34:03 astichte Exp $
++ *
++ * Author : ryan.holmQVist@idt.com
++ * Date : 20011005
++ * Update :
++ * $Log: dma.h,v $
++ * Revision 1.3 2002/06/06 18:34:03 astichte
++ * Added XXX_PhysicalAddress and XXX_VirtualAddress
++ *
++ * Revision 1.2 2002/06/05 18:30:46 astichte
++ * Removed IDTField
++ *
++ * Revision 1.1 2002/05/29 17:33:21 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ *
++ ******************************************************************************/
++
++#include <asm/rc32434/types.h>
++enum
++{
++ DMA0_PhysicalAddress = 0x18040000,
++ DMA_PhysicalAddress = DMA0_PhysicalAddress, // Default
++
++ DMA0_VirtualAddress = 0xb8040000,
++ DMA_VirtualAddress = DMA0_VirtualAddress, // Default
++} ;
++
++/*
++ * DMA descriptor (in physical memory).
++ */
++
++typedef struct DMAD_s
++{
++ U32 control ; // Control. use DMAD_*
++ U32 ca ; // Current Address.
++ U32 devcs ; // Device control and status.
++ U32 link ; // Next descriptor in chain.
++} volatile *DMAD_t ;
++
++enum
++{
++ DMAD_size = sizeof (struct DMAD_s),
++ DMAD_count_b = 0, // in DMAD_t -> control
++ DMAD_count_m = 0x0003ffff, // in DMAD_t -> control
++ DMAD_ds_b = 20, // in DMAD_t -> control
++ DMAD_ds_m = 0x00300000, // in DMAD_t -> control
++ DMAD_ds_ethRcv_v = 0,
++ DMAD_ds_ethXmt_v = 0,
++ DMAD_ds_memToFifo_v = 0,
++ DMAD_ds_fifoToMem_v = 0,
++ DMAD_ds_pciToMem_v = 0,
++ DMAD_ds_memToPci_v = 0,
++
++ DMAD_devcmd_b = 22, // in DMAD_t -> control
++ DMAD_devcmd_m = 0x01c00000, // in DMAD_t -> control
++ DMAD_devcmd_byte_v = 0, //memory-to-memory
++ DMAD_devcmd_halfword_v = 1, //memory-to-memory
++ DMAD_devcmd_word_v = 2, //memory-to-memory
++ DMAD_devcmd_2words_v = 3, //memory-to-memory
++ DMAD_devcmd_4words_v = 4, //memory-to-memory
++ DMAD_devcmd_6words_v = 5, //memory-to-memory
++ DMAD_devcmd_8words_v = 6, //memory-to-memory
++ DMAD_devcmd_16words_v = 7, //memory-to-memory
++ DMAD_cof_b = 25, // chain on finished
++ DMAD_cof_m = 0x02000000, //
++ DMAD_cod_b = 26, // chain on done
++ DMAD_cod_m = 0x04000000, //
++ DMAD_iof_b = 27, // interrupt on finished
++ DMAD_iof_m = 0x08000000, //
++ DMAD_iod_b = 28, // interrupt on done
++ DMAD_iod_m = 0x10000000, //
++ DMAD_t_b = 29, // terminated
++ DMAD_t_m = 0x20000000, //
++ DMAD_d_b = 30, // done
++ DMAD_d_m = 0x40000000, //
++ DMAD_f_b = 31, // finished
++ DMAD_f_m = 0x80000000, //
++} ;
++
++/*
++ * DMA register (within Internal Register Map).
++ */
++
++struct DMA_Chan_s
++{
++ U32 dmac ; // Control.
++ U32 dmas ; // Status.
++ U32 dmasm ; // Mask.
++ U32 dmadptr ; // Descriptor pointer.
++ U32 dmandptr ; // Next descriptor pointer.
++};
++
++typedef struct DMA_Chan_s volatile *DMA_Chan_t ;
++
++//DMA_Channels use DMACH_count instead
++
++enum
++{
++ DMAC_run_b = 0, //
++ DMAC_run_m = 0x00000001, //
++ DMAC_dm_b = 1, // done mask
++ DMAC_dm_m = 0x00000002, //
++ DMAC_mode_b = 2, //
++ DMAC_mode_m = 0x0000000c, //
++ DMAC_mode_auto_v = 0,
++ DMAC_mode_burst_v = 1,
++ DMAC_mode_transfer_v = 2, //usually used
++ DMAC_mode_reserved_v = 3,
++ DMAC_a_b = 4, //
++ DMAC_a_m = 0x00000010, //
++
++ DMAS_f_b = 0, // finished (sticky)
++ DMAS_f_m = 0x00000001, //
++ DMAS_d_b = 1, // done (sticky)
++ DMAS_d_m = 0x00000002, //
++ DMAS_c_b = 2, // chain (sticky)
++ DMAS_c_m = 0x00000004, //
++ DMAS_e_b = 3, // error (sticky)
++ DMAS_e_m = 0x00000008, //
++ DMAS_h_b = 4, // halt (sticky)
++ DMAS_h_m = 0x00000010, //
++
++ DMASM_f_b = 0, // finished (1=mask)
++ DMASM_f_m = 0x00000001, //
++ DMASM_d_b = 1, // done (1=mask)
++ DMASM_d_m = 0x00000002, //
++ DMASM_c_b = 2, // chain (1=mask)
++ DMASM_c_m = 0x00000004, //
++ DMASM_e_b = 3, // error (1=mask)
++ DMASM_e_m = 0x00000008, //
++ DMASM_h_b = 4, // halt (1=mask)
++ DMASM_h_m = 0x00000010, //
++} ;
++
++/*
++ * DMA channel definitions
++ */
++
++enum
++{
++ DMACH_ethRcv = 0,
++ DMACH_ethXmt = 1,
++ DMACH_memToFifo = 2,
++ DMACH_fifoToMem = 3,
++ DMACH_pciToMem = 4,
++ DMACH_memToPci = 5,
++
++ DMACH_count //must be last
++};
++
++
++typedef struct DMAC_s
++{
++ struct DMA_Chan_s ch [DMACH_count] ; //use ch[DMACH_]
++} volatile *DMA_t ;
++
++
++/*
++ * External DMA parameters
++*/
++#if 0
++enum
++{
++ DMADEVCMD_ts_b = 0, // ts field in devcmd
++ DMADEVCMD_ts_m = 0x00000007, // ts field in devcmd
++ DMADEVCMD_ts_byte_v = 0,
++ DMADEVCMD_ts_halfword_v = 1,
++ DMADEVCMD_ts_word_v = 2,
++ DMADEVCMD_ts_2word_v = 3,
++ DMADEVCMD_ts_4word_v = 4,
++ DMADEVCMD_ts_6word_v = 5,
++ DMADEVCMD_ts_8word_v = 6,
++ DMADEVCMD_ts_16word_v = 7
++};
++#endif
++
++#if 1 // aws - Compatibility.
++# define EXTDMA_ts_b DMADEVCMD_ts_b
++# define EXTDMA_ts_m DMADEVCMD_ts_m
++# define EXTDMA_ts_byte_v DMADEVCMD_ts_byte_v
++# define EXTDMA_ts_halfword_v DMADEVCMD_ts_halfword_v
++# define EXTDMA_ts_word_v DMADEVCMD_ts_word_v
++# define EXTDMA_ts_2word_v DMADEVCMD_ts_2word_v
++# define EXTDMA_ts_4word_v DMADEVCMD_ts_4word_v
++# define EXTDMA_ts_6word_v DMADEVCMD_ts_6word_v
++# define EXTDMA_ts_8word_v DMADEVCMD_ts_8word_v
++# define EXTDMA_ts_16word_v DMADEVCMD_ts_16word_v
++#endif // aws - Compatibility.
++
++#endif // __IDT_DMA_H__
++
+diff -urN linux.old/include/asm-mips/rc32434/dma_v.h linux.dev/include/asm-mips/rc32434/dma_v.h
+--- linux.old/include/asm-mips/rc32434/dma_v.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/dma_v.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,73 @@
++#ifndef __IDT_DMA_V_H__
++#define __IDT_DMA_V_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * DMA register definition.
++ *
++ * File : $Id: dma.h,v 1.3 2002/06/06 18:34:03 astichte Exp $
++ *
++ * Author : ryan.holmQVist@idt.com
++ * Date : 20011005
++ * Update :
++ * $Log: dma.h,v $
++ * Revision 1.3 2002/06/06 18:34:03 astichte
++ * Added XXX_PhysicalAddress and XXX_VirtualAddress
++ *
++ * Revision 1.2 2002/06/05 18:30:46 astichte
++ * Removed IDTField
++ *
++ * Revision 1.1 2002/05/29 17:33:21 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ *
++ ******************************************************************************/
++#include <asm/rc32434/types.h>
++#include <asm/rc32434/dma.h>
++#include <asm/rc32434/rc32434.h>
++#define DMA_CHAN_OFFSET 0x14
++#define IS_DMA_USED(X) (((X) & (DMAD_f_m | DMAD_d_m | DMAD_t_m)) != 0)
++#define DMA_COUNT(count) \
++ ((count) & DMAD_count_m)
++
++#define DMA_HALT_TIMEOUT 500
++
++
++static inline int rc32434_halt_dma(DMA_Chan_t ch)
++{
++ int timeout=1;
++ if (local_readl(&ch->dmac) & DMAC_run_m) {
++ local_writel(0, &ch->dmac);
++ for (timeout = DMA_HALT_TIMEOUT; timeout > 0; timeout--) {
++ if (local_readl(&ch->dmas) & DMAS_h_m) {
++ local_writel(0, &ch->dmas);
++ break;
++ }
++ }
++ }
++
++ return timeout ? 0 : 1;
++}
++
++static inline void rc32434_start_dma(DMA_Chan_t ch, u32 dma_addr)
++{
++ local_writel(0, &ch->dmandptr);
++ local_writel(dma_addr, &ch->dmadptr);
++}
++
++static inline void rc32434_chain_dma(DMA_Chan_t ch, u32 dma_addr)
++{
++ local_writel(dma_addr, &ch->dmandptr);
++}
++
++#endif // __IDT_DMA_V_H__
++
++
++
++
++
++
++
+diff -urN linux.old/include/asm-mips/rc32434/eth.h linux.dev/include/asm-mips/rc32434/eth.h
+--- linux.old/include/asm-mips/rc32434/eth.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/eth.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,322 @@
++#ifndef __IDT_ETH_H__
++#define __IDT_ETH_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * Ethernet register definition.
++ *
++ * File : $Id: eth.h,v 1.3 2002/06/06 18:34:04 astichte Exp $
++ *
++ * Author : Allen.Stichter@idt.com
++ * Date : 20020605
++ * Update :
++ * $Log: eth.h,v $
++ * Revision 1.3 2002/06/06 18:34:04 astichte
++ * Added XXX_PhysicalAddress and XXX_VirtualAddress
++ *
++ * Revision 1.2 2002/06/05 18:19:46 astichte
++ * Added
++ *
++ * Revision 1.1 2002/05/29 17:33:22 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ ******************************************************************************/
++
++#include <asm/rc32434/types.h>
++
++enum
++{
++ ETH0_PhysicalAddress = 0x18060000,
++ ETH_PhysicalAddress = ETH0_PhysicalAddress, // Default
++
++ ETH0_VirtualAddress = 0xb8060000,
++ ETH_VirtualAddress = ETH0_VirtualAddress, // Default
++} ;
++
++typedef struct
++{
++ U32 ethintfc ;
++ U32 ethfifott ;
++ U32 etharc ;
++ U32 ethhash0 ;
++ U32 ethhash1 ;
++ U32 ethu0 [4] ; // Reserved.
++ U32 ethpfs ;
++ U32 ethmcp ;
++ U32 eth_u1 [10] ; // Reserved.
++ U32 ethspare ;
++ U32 eth_u2 [42] ; // Reserved.
++ U32 ethsal0 ;
++ U32 ethsah0 ;
++ U32 ethsal1 ;
++ U32 ethsah1 ;
++ U32 ethsal2 ;
++ U32 ethsah2 ;
++ U32 ethsal3 ;
++ U32 ethsah3 ;
++ U32 ethrbc ;
++ U32 ethrpc ;
++ U32 ethrupc ;
++ U32 ethrfc ;
++ U32 ethtbc ;
++ U32 ethgpf ;
++ U32 eth_u9 [50] ; // Reserved.
++ U32 ethmac1 ;
++ U32 ethmac2 ;
++ U32 ethipgt ;
++ U32 ethipgr ;
++ U32 ethclrt ;
++ U32 ethmaxf ;
++ U32 eth_u10 ; // Reserved.
++ U32 ethmtest ;
++ U32 miimcfg ;
++ U32 miimcmd ;
++ U32 miimaddr ;
++ U32 miimwtd ;
++ U32 miimrdd ;
++ U32 miimind ;
++ U32 eth_u11 ; // Reserved.
++ U32 eth_u12 ; // Reserved.
++ U32 ethcfsa0 ;
++ U32 ethcfsa1 ;
++ U32 ethcfsa2 ;
++} volatile *ETH_t;
++
++enum
++{
++ ETHINTFC_en_b = 0,
++ ETHINTFC_en_m = 0x00000001,
++ ETHINTFC_its_b = 1,
++ ETHINTFC_its_m = 0x00000002,
++ ETHINTFC_rip_b = 2,
++ ETHINTFC_rip_m = 0x00000004,
++ ETHINTFC_jam_b = 3,
++ ETHINTFC_jam_m = 0x00000008,
++ ETHINTFC_ovr_b = 4,
++ ETHINTFC_ovr_m = 0x00000010,
++ ETHINTFC_und_b = 5,
++ ETHINTFC_und_m = 0x00000020,
++ ETHINTFC_iom_b = 6,
++ ETHINTFC_iom_m = 0x000000c0,
++
++ ETHFIFOTT_tth_b = 0,
++ ETHFIFOTT_tth_m = 0x0000007f,
++
++ ETHARC_pro_b = 0,
++ ETHARC_pro_m = 0x00000001,
++ ETHARC_am_b = 1,
++ ETHARC_am_m = 0x00000002,
++ ETHARC_afm_b = 2,
++ ETHARC_afm_m = 0x00000004,
++ ETHARC_ab_b = 3,
++ ETHARC_ab_m = 0x00000008,
++
++ ETHSAL_byte5_b = 0,
++ ETHSAL_byte5_m = 0x000000ff,
++ ETHSAL_byte4_b = 8,
++ ETHSAL_byte4_m = 0x0000ff00,
++ ETHSAL_byte3_b = 16,
++ ETHSAL_byte3_m = 0x00ff0000,
++ ETHSAL_byte2_b = 24,
++ ETHSAL_byte2_m = 0xff000000,
++
++ ETHSAH_byte1_b = 0,
++ ETHSAH_byte1_m = 0x000000ff,
++ ETHSAH_byte0_b = 8,
++ ETHSAH_byte0_m = 0x0000ff00,
++
++ ETHGPF_ptv_b = 0,
++ ETHGPF_ptv_m = 0x0000ffff,
++
++ ETHPFS_pfd_b = 0,
++ ETHPFS_pfd_m = 0x00000001,
++
++ ETHCFSA0_cfsa4_b = 0,
++ ETHCFSA0_cfsa4_m = 0x000000ff,
++ ETHCFSA0_cfsa5_b = 8,
++ ETHCFSA0_cfsa5_m = 0x0000ff00,
++
++ ETHCFSA1_cfsa2_b = 0,
++ ETHCFSA1_cfsa2_m = 0x000000ff,
++ ETHCFSA1_cfsa3_b = 8,
++ ETHCFSA1_cfsa3_m = 0x0000ff00,
++
++ ETHCFSA2_cfsa0_b = 0,
++ ETHCFSA2_cfsa0_m = 0x000000ff,
++ ETHCFSA2_cfsa1_b = 8,
++ ETHCFSA2_cfsa1_m = 0x0000ff00,
++
++ ETHMAC1_re_b = 0,
++ ETHMAC1_re_m = 0x00000001,
++ ETHMAC1_paf_b = 1,
++ ETHMAC1_paf_m = 0x00000002,
++ ETHMAC1_rfc_b = 2,
++ ETHMAC1_rfc_m = 0x00000004,
++ ETHMAC1_tfc_b = 3,
++ ETHMAC1_tfc_m = 0x00000008,
++ ETHMAC1_lb_b = 4,
++ ETHMAC1_lb_m = 0x00000010,
++ ETHMAC1_mr_b = 31,
++ ETHMAC1_mr_m = 0x80000000,
++
++ ETHMAC2_fd_b = 0,
++ ETHMAC2_fd_m = 0x00000001,
++ ETHMAC2_flc_b = 1,
++ ETHMAC2_flc_m = 0x00000002,
++ ETHMAC2_hfe_b = 2,
++ ETHMAC2_hfe_m = 0x00000004,
++ ETHMAC2_dc_b = 3,
++ ETHMAC2_dc_m = 0x00000008,
++ ETHMAC2_cen_b = 4,
++ ETHMAC2_cen_m = 0x00000010,
++ ETHMAC2_pe_b = 5,
++ ETHMAC2_pe_m = 0x00000020,
++ ETHMAC2_vpe_b = 6,
++ ETHMAC2_vpe_m = 0x00000040,
++ ETHMAC2_ape_b = 7,
++ ETHMAC2_ape_m = 0x00000080,
++ ETHMAC2_ppe_b = 8,
++ ETHMAC2_ppe_m = 0x00000100,
++ ETHMAC2_lpe_b = 9,
++ ETHMAC2_lpe_m = 0x00000200,
++ ETHMAC2_nb_b = 12,
++ ETHMAC2_nb_m = 0x00001000,
++ ETHMAC2_bp_b = 13,
++ ETHMAC2_bp_m = 0x00002000,
++ ETHMAC2_ed_b = 14,
++ ETHMAC2_ed_m = 0x00004000,
++
++ ETHIPGT_ipgt_b = 0,
++ ETHIPGT_ipgt_m = 0x0000007f,
++
++ ETHIPGR_ipgr2_b = 0,
++ ETHIPGR_ipgr2_m = 0x0000007f,
++ ETHIPGR_ipgr1_b = 8,
++ ETHIPGR_ipgr1_m = 0x00007f00,
++
++ ETHCLRT_maxret_b = 0,
++ ETHCLRT_maxret_m = 0x0000000f,
++ ETHCLRT_colwin_b = 8,
++ ETHCLRT_colwin_m = 0x00003f00,
++
++ ETHMAXF_maxf_b = 0,
++ ETHMAXF_maxf_m = 0x0000ffff,
++
++ ETHMTEST_tb_b = 2,
++ ETHMTEST_tb_m = 0x00000004,
++
++ ETHMCP_div_b = 0,
++ ETHMCP_div_m = 0x000000ff,
++
++ MIIMCFG_rsv_b = 0,
++ MIIMCFG_rsv_m = 0x0000000c,
++
++ MIIMCMD_rd_b = 0,
++ MIIMCMD_rd_m = 0x00000001,
++ MIIMCMD_scn_b = 1,
++ MIIMCMD_scn_m = 0x00000002,
++
++ MIIMADDR_regaddr_b = 0,
++ MIIMADDR_regaddr_m = 0x0000001f,
++ MIIMADDR_phyaddr_b = 8,
++ MIIMADDR_phyaddr_m = 0x00001f00,
++
++ MIIMWTD_wdata_b = 0,
++ MIIMWTD_wdata_m = 0x0000ffff,
++
++ MIIMRDD_rdata_b = 0,
++ MIIMRDD_rdata_m = 0x0000ffff,
++
++ MIIMIND_bsy_b = 0,
++ MIIMIND_bsy_m = 0x00000001,
++ MIIMIND_scn_b = 1,
++ MIIMIND_scn_m = 0x00000002,
++ MIIMIND_nv_b = 2,
++ MIIMIND_nv_m = 0x00000004,
++
++} ;
++
++/*
++ * Values for the DEVCS field of the Ethernet DMA Rx and Tx descriptors.
++ */
++enum
++{
++ ETHRX_fd_b = 0,
++ ETHRX_fd_m = 0x00000001,
++ ETHRX_ld_b = 1,
++ ETHRX_ld_m = 0x00000002,
++ ETHRX_rok_b = 2,
++ ETHRX_rok_m = 0x00000004,
++ ETHRX_fm_b = 3,
++ ETHRX_fm_m = 0x00000008,
++ ETHRX_mp_b = 4,
++ ETHRX_mp_m = 0x00000010,
++ ETHRX_bp_b = 5,
++ ETHRX_bp_m = 0x00000020,
++ ETHRX_vlt_b = 6,
++ ETHRX_vlt_m = 0x00000040,
++ ETHRX_cf_b = 7,
++ ETHRX_cf_m = 0x00000080,
++ ETHRX_ovr_b = 8,
++ ETHRX_ovr_m = 0x00000100,
++ ETHRX_crc_b = 9,
++ ETHRX_crc_m = 0x00000200,
++ ETHRX_cv_b = 10,
++ ETHRX_cv_m = 0x00000400,
++ ETHRX_db_b = 11,
++ ETHRX_db_m = 0x00000800,
++ ETHRX_le_b = 12,
++ ETHRX_le_m = 0x00001000,
++ ETHRX_lor_b = 13,
++ ETHRX_lor_m = 0x00002000,
++ ETHRX_ces_b = 14,
++ ETHRX_ces_m = 0x00004000,
++ ETHRX_length_b = 16,
++ ETHRX_length_m = 0xffff0000,
++
++ ETHTX_fd_b = 0,
++ ETHTX_fd_m = 0x00000001,
++ ETHTX_ld_b = 1,
++ ETHTX_ld_m = 0x00000002,
++ ETHTX_oen_b = 2,
++ ETHTX_oen_m = 0x00000004,
++ ETHTX_pen_b = 3,
++ ETHTX_pen_m = 0x00000008,
++ ETHTX_cen_b = 4,
++ ETHTX_cen_m = 0x00000010,
++ ETHTX_hen_b = 5,
++ ETHTX_hen_m = 0x00000020,
++ ETHTX_tok_b = 6,
++ ETHTX_tok_m = 0x00000040,
++ ETHTX_mp_b = 7,
++ ETHTX_mp_m = 0x00000080,
++ ETHTX_bp_b = 8,
++ ETHTX_bp_m = 0x00000100,
++ ETHTX_und_b = 9,
++ ETHTX_und_m = 0x00000200,
++ ETHTX_of_b = 10,
++ ETHTX_of_m = 0x00000400,
++ ETHTX_ed_b = 11,
++ ETHTX_ed_m = 0x00000800,
++ ETHTX_ec_b = 12,
++ ETHTX_ec_m = 0x00001000,
++ ETHTX_lc_b = 13,
++ ETHTX_lc_m = 0x00002000,
++ ETHTX_td_b = 14,
++ ETHTX_td_m = 0x00004000,
++ ETHTX_crc_b = 15,
++ ETHTX_crc_m = 0x00008000,
++ ETHTX_le_b = 16,
++ ETHTX_le_m = 0x00010000,
++ ETHTX_cc_b = 17,
++ ETHTX_cc_m = 0x001E0000,
++} ;
++
++#endif // __IDT_ETH_H__
++
++
++
++
+diff -urN linux.old/include/asm-mips/rc32434/eth_v.h linux.dev/include/asm-mips/rc32434/eth_v.h
+--- linux.old/include/asm-mips/rc32434/eth_v.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/eth_v.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,64 @@
++#ifndef __IDT_ETH_V_H__
++#define __IDT_ETH_V_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * Ethernet register definition.
++ *
++ * File : $Id: eth.h,v 1.3 2002/06/06 18:34:04 astichte Exp $
++ *
++ * Author : Allen.Stichter@idt.com
++ * Date : 20020605
++ * Update :
++ * $Log: eth.h,v $
++ * Revision 1.3 2002/06/06 18:34:04 astichte
++ * Added XXX_PhysicalAddress and XXX_VirtualAddress
++ *
++ * Revision 1.2 2002/06/05 18:19:46 astichte
++ * Added
++ *
++ * Revision 1.1 2002/05/29 17:33:22 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ ******************************************************************************/
++
++#include <asm/rc32434/types.h>
++#include <asm/rc32434/eth.h>
++
++#define IS_TX_TOK(X) (((X) & (1<<ETHTX_tok_b)) >> ETHTX_tok_b ) /* Transmit Okay */
++#define IS_TX_MP(X) (((X) & (1<<ETHTX_mp_b)) >> ETHTX_mp_b ) /* Multicast */
++#define IS_TX_BP(X) (((X) & (1<<ETHTX_bp_b)) >> ETHTX_bp_b ) /* Broadcast */
++#define IS_TX_UND_ERR(X) (((X) & (1<<ETHTX_und_b)) >> ETHTX_und_b ) /* Transmit FIFO Underflow */
++#define IS_TX_OF_ERR(X) (((X) & (1<<ETHTX_of_b)) >> ETHTX_of_b ) /* Oversized frame */
++#define IS_TX_ED_ERR(X) (((X) & (1<<ETHTX_ed_b)) >> ETHTX_ed_b ) /* Excessive deferral */
++#define IS_TX_EC_ERR(X) (((X) & (1<<ETHTX_ec_b)) >> ETHTX_ec_b) /* Excessive collisions */
++#define IS_TX_LC_ERR(X) (((X) & (1<<ETHTX_lc_b)) >> ETHTX_lc_b ) /* Late Collision */
++#define IS_TX_TD_ERR(X) (((X) & (1<<ETHTX_td_b)) >> ETHTX_td_b ) /* Transmit deferred*/
++#define IS_TX_CRC_ERR(X) (((X) & (1<<ETHTX_crc_b)) >> ETHTX_crc_b ) /* CRC Error */
++#define IS_TX_LE_ERR(X) (((X) & (1<<ETHTX_le_b)) >> ETHTX_le_b ) /* Length Error */
++
++#define TX_COLLISION_COUNT(X) (((X) & ETHTX_cc_m)>>ETHTX_cc_b) /* Collision Count */
++
++#define IS_RCV_ROK(X) (((X) & (1<<ETHRX_rok_b)) >> ETHRX_rok_b) /* Receive Okay */
++#define IS_RCV_FM(X) (((X) & (1<<ETHRX_fm_b)) >> ETHRX_fm_b) /* Is Filter Match */
++#define IS_RCV_MP(X) (((X) & (1<<ETHRX_mp_b)) >> ETHRX_mp_b) /* Is it MP */
++#define IS_RCV_BP(X) (((X) & (1<<ETHRX_bp_b)) >> ETHRX_bp_b) /* Is it BP */
++#define IS_RCV_VLT(X) (((X) & (1<<ETHRX_vlt_b)) >> ETHRX_vlt_b) /* VLAN Tag Detect */
++#define IS_RCV_CF(X) (((X) & (1<<ETHRX_cf_b)) >> ETHRX_cf_b) /* Control Frame */
++#define IS_RCV_OVR_ERR(X) (((X) & (1<<ETHRX_ovr_b)) >> ETHRX_ovr_b) /* Receive Overflow */
++#define IS_RCV_CRC_ERR(X) (((X) & (1<<ETHRX_crc_b)) >> ETHRX_crc_b) /* CRC Error */
++#define IS_RCV_CV_ERR(X) (((X) & (1<<ETHRX_cv_b)) >> ETHRX_cv_b) /* Code Violation */
++#define IS_RCV_DB_ERR(X) (((X) & (1<<ETHRX_db_b)) >> ETHRX_db_b) /* Dribble Bits */
++#define IS_RCV_LE_ERR(X) (((X) & (1<<ETHRX_le_b)) >> ETHRX_le_b) /* Length error */
++#define IS_RCV_LOR_ERR(X) (((X) & (1<<ETHRX_lor_b)) >> ETHRX_lor_b) /* Length Out of Range */
++#define IS_RCV_CES_ERR(X) (((X) & (1<<ETHRX_ces_b)) >> ETHRX_ces_b) /* Preamble error */
++#define RCVPKT_LENGTH(X) (((X) & ETHRX_length_m) >> ETHRX_length_b) /* Length of the received packet */
++#endif // __IDT_ETH_V_H__
++
++
++
++
++
+diff -urN linux.old/include/asm-mips/rc32434/gpio.h linux.dev/include/asm-mips/rc32434/gpio.h
+--- linux.old/include/asm-mips/rc32434/gpio.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/gpio.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,182 @@
++#ifndef __IDT_GPIO_H__
++#define __IDT_GPIO_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * GPIO register definition.
++ *
++ * File : $Id: gpio.h,v 1.2 2002/06/06 18:34:04 astichte Exp $
++ *
++ * Author : ryan.holmQVist@idt.com
++ * Date : 20011005
++ * Update :
++ * $Log: gpio.h,v $
++ * Revision 1.2 2002/06/06 18:34:04 astichte
++ * Added XXX_PhysicalAddress and XXX_VirtualAddress
++ *
++ * Revision 1.1 2002/05/29 17:33:22 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ *
++ ******************************************************************************/
++
++#include <asm/rc32434/types.h>
++enum
++{
++ GPIO0_PhysicalAddress = 0x18050000,
++ GPIO_PhysicalAddress = GPIO0_PhysicalAddress, // Default
++
++ GPIO0_VirtualAddress = 0xb8050000,
++ GPIO_VirtualAddress = GPIO0_VirtualAddress, // Default
++} ;
++
++typedef struct
++{
++ U32 gpiofunc; /* GPIO Function Register
++ * gpiofunc[x]==0 bit = gpio
++ * func[x]==1 bit = altfunc
++ */
++ U32 gpiocfg; /* GPIO Configuration Register
++ * gpiocfg[x]==0 bit = input
++ * gpiocfg[x]==1 bit = output
++ */
++ U32 gpiod; /* GPIO Data Register
++ * gpiod[x] read/write gpio pinX status
++ */
++ U32 gpioilevel; /* GPIO Interrupt Status Register
++ * interrupt level (see gpioistat)
++ */
++ U32 gpioistat; /* Gpio Interrupt Status Register
++ * istat[x] = (gpiod[x] == level[x])
++ * cleared in ISR (STICKY bits)
++ */
++ U32 gpionmien; /* GPIO Non-maskable Interrupt Enable Register */
++} volatile * GPIO_t ;
++
++typedef enum
++{
++ GPIO_gpio_v = 0, // gpiofunc use pin as GPIO.
++ GPIO_alt_v = 1, // gpiofunc use pin as alt.
++ GPIO_input_v = 0, // gpiocfg use pin as input.
++ GPIO_output_v = 1, // gpiocfg use pin as output.
++ GPIO_pin0_b = 0,
++ GPIO_pin0_m = 0x00000001,
++ GPIO_pin1_b = 1,
++ GPIO_pin1_m = 0x00000002,
++ GPIO_pin2_b = 2,
++ GPIO_pin2_m = 0x00000004,
++ GPIO_pin3_b = 3,
++ GPIO_pin3_m = 0x00000008,
++ GPIO_pin4_b = 4,
++ GPIO_pin4_m = 0x00000010,
++ GPIO_pin5_b = 5,
++ GPIO_pin5_m = 0x00000020,
++ GPIO_pin6_b = 6,
++ GPIO_pin6_m = 0x00000040,
++ GPIO_pin7_b = 7,
++ GPIO_pin7_m = 0x00000080,
++ GPIO_pin8_b = 8,
++ GPIO_pin8_m = 0x00000100,
++ GPIO_pin9_b = 9,
++ GPIO_pin9_m = 0x00000200,
++ GPIO_pin10_b = 10,
++ GPIO_pin10_m = 0x00000400,
++ GPIO_pin11_b = 11,
++ GPIO_pin11_m = 0x00000800,
++ GPIO_pin12_b = 12,
++ GPIO_pin12_m = 0x00001000,
++ GPIO_pin13_b = 13,
++ GPIO_pin13_m = 0x00002000,
++ GPIO_pin14_b = 14,
++ GPIO_pin14_m = 0x00004000,
++ GPIO_pin15_b = 15,
++ GPIO_pin15_m = 0x00008000,
++ GPIO_pin16_b = 16,
++ GPIO_pin16_m = 0x00010000,
++ GPIO_pin17_b = 17,
++ GPIO_pin17_m = 0x00020000,
++ GPIO_pin18_b = 18,
++ GPIO_pin18_m = 0x00040000,
++ GPIO_pin19_b = 19,
++ GPIO_pin19_m = 0x00080000,
++ GPIO_pin20_b = 20,
++ GPIO_pin20_m = 0x00100000,
++ GPIO_pin21_b = 21,
++ GPIO_pin21_m = 0x00200000,
++ GPIO_pin22_b = 22,
++ GPIO_pin22_m = 0x00400000,
++ GPIO_pin23_b = 23,
++ GPIO_pin23_m = 0x00800000,
++ GPIO_pin24_b = 24,
++ GPIO_pin24_m = 0x01000000,
++ GPIO_pin25_b = 25,
++ GPIO_pin25_m = 0x02000000,
++ GPIO_pin26_b = 26,
++ GPIO_pin26_m = 0x04000000,
++ GPIO_pin27_b = 27,
++ GPIO_pin27_m = 0x08000000,
++ GPIO_pin28_b = 28,
++ GPIO_pin28_m = 0x10000000,
++ GPIO_pin29_b = 29,
++ GPIO_pin29_m = 0x20000000,
++ GPIO_pin30_b = 30,
++ GPIO_pin30_m = 0x40000000,
++ GPIO_pin31_b = 31,
++ GPIO_pin31_m = 0x80000000,
++
++// Alternate function pins. Corrsponding gpiofunc bit set to GPIO_alt_v.
++
++ GPIO_u0sout_b = GPIO_pin0_b, // UART 0 serial out.
++ GPIO_u0sout_m = GPIO_pin0_m,
++ GPIO_u0sout_cfg_v = GPIO_output_v,
++ GPIO_u0sinp_b = GPIO_pin1_b, // UART 0 serial in.
++ GPIO_u0sinp_m = GPIO_pin1_m,
++ GPIO_u0sinp_cfg_v = GPIO_input_v,
++ GPIO_u0rtsn_b = GPIO_pin2_b, // UART 0 req. to send.
++ GPIO_u0rtsn_m = GPIO_pin2_m,
++ GPIO_u0rtsn_cfg_v = GPIO_output_v,
++ GPIO_u0ctsn_b = GPIO_pin3_b, // UART 0 clear to send.
++ GPIO_u0ctsn_m = GPIO_pin3_m,
++ GPIO_u0ctsn_cfg_v = GPIO_input_v,
++ GPIO_maddr22_b = GPIO_pin4_b, // M&P bus bit 22.
++ GPIO_maddr22_m = GPIO_pin4_m,
++ GPIO_maddr22_cfg_v = GPIO_output_v,
++
++ GPIO_maddr23_b = GPIO_pin5_b, // M&P bus bit 23.
++ GPIO_maddr23_m = GPIO_pin5_m,
++ GPIO_maddr23_cfg_v = GPIO_output_v,
++
++ GPIO_maddr24_b = GPIO_pin6_b, // M&P bus bit 24.
++ GPIO_maddr24_m = GPIO_pin6_m,
++ GPIO_maddr24_cfg_v = GPIO_output_v,
++
++ GPIO_maddr25_b = GPIO_pin7_b, // M&P bus bit 25.
++ GPIO_maddr25_m = GPIO_pin7_m,
++ GPIO_maddr25_cfg_v = GPIO_output_v,
++
++ GPIO_cpu_b = GPIO_pin8_b, // M&P bus bit 25.
++ GPIO_cpu_m = GPIO_pin8_m,
++ GPIO_cpu_cfg_v = GPIO_output_v,
++ GPIO_afspare6_b = GPIO_pin9_b, // reserved.
++ GPIO_afspare6_m = GPIO_pin9_m,
++ GPIO_afspare6_cfg_v = GPIO_input_v,
++ GPIO_afspare4_b = GPIO_pin10_b, // reserved.
++ GPIO_afspare4_m = GPIO_pin10_m,
++ GPIO_afspare4_cfg_v = GPIO_input_v,
++ GPIO_afspare3_b = GPIO_pin11_b, // reserved.
++ GPIO_afspare3_m = GPIO_pin11_m,
++ GPIO_afspare3_cfg_v = GPIO_input_v,
++ GPIO_afspare2_b = GPIO_pin12_b, // reserved.
++ GPIO_afspare2_m = GPIO_pin12_m,
++ GPIO_afspare2_cfg_v = GPIO_input_v,
++ GPIO_pcimuintn_b = GPIO_pin13_b, // PCI messaging int.
++ GPIO_pcimuintn_m = GPIO_pin13_m,
++ GPIO_pcimuintn_cfg_v = GPIO_output_v,
++
++} GPIO_DEFS_t;
++
++#endif // __IDT_GPIO_H__
++
+diff -urN linux.old/include/asm-mips/rc32434/i2c.h linux.dev/include/asm-mips/rc32434/i2c.h
+--- linux.old/include/asm-mips/rc32434/i2c.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/i2c.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,147 @@
++#ifndef __IDT_I2C_H__
++#define __IDT_I2C_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * I2C register definitions.
++ *
++ * File : $Id: i2c.h,v 1.2 2002/06/06 18:34:04 astichte Exp $
++ *
++ * Author : Allen.Stichter@idt.com
++ * Date : 20020120
++ * Update :
++ * $Log: i2c.h,v $
++ * Revision 1.2 2002/06/06 18:34:04 astichte
++ * Added XXX_PhysicalAddress and XXX_VirtualAddress
++ *
++ * Revision 1.1 2002/05/29 17:33:22 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ *
++ ******************************************************************************/
++
++#include <asm/rc32434/types.h>
++
++enum
++{
++ I2C0_PhysicalAddress = 0x18068000,
++ I2C_PhysicalAddress = I2C0_PhysicalAddress,
++
++ I2C0_VirtualAddress = 0xb8068000,
++ I2C_VirtualAddress = I2C0_VirtualAddress,
++} ;
++
++typedef struct
++{
++ U32 i2cc ;
++ U32 i2cdi ;
++ U32 i2cdo ;
++ U32 i2ccp ; // I2C clk = ICLK / div / 8
++ U32 i2cmcmd ;
++ U32 i2cms ;
++ U32 i2cmsm ;
++ U32 i2css ;
++ U32 i2cssm ;
++ U32 i2csaddr ;
++ U32 i2csack ;
++} volatile * I2C_t ;
++enum
++{
++ I2CC_men_b = 0, // In I2C-> i2cc
++ I2CC_men_m = 0x00000001,
++ I2CC_sen_b = 1, // In I2C-> i2cc
++ I2CC_sen_m = 0x00000002,
++ I2CC_iom_b = 2, // In I2C-> i2cc
++ I2CC_iom_m = 0x00000004,
++
++ I2CDI_data_b = 0, // In I2C-> i2cdi
++ I2CDI_data_m = 0x000000ff,
++
++ I2CDO_data_b = 0, // In I2C-> i2cdo
++ I2CDO_data_m = 0x000000ff,
++
++ I2CCP_div_b = 0, // In I2C-> i2ccp
++ I2CCP_div_m = 0x0000ffff,
++
++ I2CMCMD_cmd_b = 0, // In I2C-> i2cmcmd
++ I2CMCMD_cmd_m = 0x0000000f,
++ I2CMCMD_cmd_nop_v = 0,
++ I2CMCMD_cmd_start_v = 1,
++ I2CMCMD_cmd_stop_v = 2,
++ I2CMCMD_cmd_res3_v = 3,
++ I2CMCMD_cmd_rd_v = 4,
++ I2CMCMD_cmd_rdack_v = 5,
++ I2CMCMD_cmd_wd_v = 6,
++ I2CMCMD_cmd_wdack_v = 7,
++ I2CMCMD_cmd_res8_v = 8,
++ I2CMCMD_cmd_res9_v = 9,
++ I2CMCMD_cmd_res10_v = 10,
++ I2CMCMD_cmd_res11_v = 11,
++ I2CMCMD_cmd_res12_v = 12,
++ I2CMCMD_cmd_res13_v = 13,
++ I2CMCMD_cmd_res14_v = 14,
++ I2CMCMD_cmd_res15_v = 15,
++
++ I2CMS_d_b = 0, // In I2C-> i2cms
++ I2CMS_d_m = 0x00000001,
++ I2CMS_na_b = 1, // In I2C-> i2cms
++ I2CMS_na_m = 0x00000002,
++ I2CMS_la_b = 2, // In I2C-> i2cms
++ I2CMS_la_m = 0x00000004,
++ I2CMS_err_b = 3, // In I2C-> i2cms
++ I2CMS_err_m = 0x00000008,
++
++ I2CMSM_d_b = 0, // In I2C-> i2cmsm
++ I2CMSM_d_m = 0x00000001,
++ I2CMSM_na_b = 1, // In I2C-> i2cmsm
++ I2CMSM_na_m = 0x00000002,
++ I2CMSM_la_b = 2, // In I2C-> i2cmsm
++ I2CMSM_la_m = 0x00000004,
++ I2CMSM_err_b = 3, // In I2C-> i2cmsm
++ I2CMSM_err_m = 0x00000008,
++
++ I2CSS_rr_b = 0, // In I2C-> i2css
++ I2CSS_rr_m = 0x00000001,
++ I2CSS_wr_b = 1, // In I2C-> i2css
++ I2CSS_wr_m = 0x00000002,
++ I2CSS_sa_b = 2, // In I2C-> i2css
++ I2CSS_sa_m = 0x00000004,
++ I2CSS_tf_b = 3, // In I2C-> i2css
++ I2CSS_tf_m = 0x00000008,
++ I2CSS_gc_b = 4, // In I2C-> i2css
++ I2CSS_gc_m = 0x00000010,
++ I2CSS_na_b = 5, // In I2C-> i2css
++ I2CSS_na_m = 0x00000020,
++ I2CSS_err_b = 6, // In I2C-> i2css
++ I2CSS_err_m = 0x00000040,
++
++ I2CSSM_rr_b = 0, // In I2C-> i2cssm
++ I2CSSM_rr_m = 0x00000001,
++ I2CSSM_wr_b = 1, // In I2C-> i2cssm
++ I2CSSM_wr_m = 0x00000002,
++ I2CSSM_sa_b = 2, // In I2C-> i2cssm
++ I2CSSM_sa_m = 0x00000004,
++ I2CSSM_tf_b = 3, // In I2C-> i2cssm
++ I2CSSM_tf_m = 0x00000008,
++ I2CSSM_gc_b = 4, // In I2C-> i2cssm
++ I2CSSM_gc_m = 0x00000010,
++ I2CSSM_na_b = 5, // In I2C-> i2cssm
++ I2CSSM_na_m = 0x00000020,
++ I2CSSM_err_b = 6, // In I2C-> i2cssm
++ I2CSSM_err_m = 0x00000040,
++
++ I2CSADDR_addr_b = 0, // In I2C-> i2csaddr
++ I2CSADDR_addr_m = 0x000003ff,
++ I2CSADDR_a_gc_b = 10, // In I2C-> i2csaddr
++ I2CSADDR_a_gc_m = 0x00000400,
++ I2CSADDR_a10_b = 11, // In I2C-> i2csaddr
++ I2CSADDR_a10_m = 0x00000800,
++
++ I2CSACK_ack_b = 0, // In I2C-> i2csack
++ I2CSACK_ack_m = 0x00000001,
++
++} ;
++#endif // __IDT_I2C_H__
+diff -urN linux.old/include/asm-mips/rc32434/integ.h linux.dev/include/asm-mips/rc32434/integ.h
+--- linux.old/include/asm-mips/rc32434/integ.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/integ.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,78 @@
++#ifndef __IDT_INTEG_H__
++#define __IDT_INTEG_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * System Integrity register definition.
++ *
++ * File : $Id: integ.h,v 1.3 2002/06/06 18:34:04 astichte Exp $
++ *
++ * Author : ryan.holmQVist@idt.com
++ * Date : 20011005
++ * Update :
++ * $Log: integ.h,v $
++ * Revision 1.3 2002/06/06 18:34:04 astichte
++ * Added XXX_PhysicalAddress and XXX_VirtualAddress
++ *
++ * Revision 1.2 2002/06/05 18:32:33 astichte
++ * Removed IDTField
++ *
++ * Revision 1.1 2002/05/29 17:33:22 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ ******************************************************************************/
++
++#include <asm/rc32434/types.h>
++
++enum
++{
++ INTEG0_PhysicalAddress = 0x18030000,
++ INTEG_PhysicalAddress = INTEG0_PhysicalAddress, // Default
++
++ INTEG0_VirtualAddress = 0xb8030000,
++ INTEG_VirtualAddress = INTEG0_VirtualAddress, // Default
++} ;
++
++// if you are looing for CEA, try rst.h
++typedef struct
++{
++ U32 filler [0xc] ; // 0x30 bytes unused.
++ U32 errcs ; // sticky use ERRCS_
++ U32 wtcount ; // Watchdog timer count reg.
++ U32 wtcompare ; // Watchdog timer timeout value.
++ U32 wtc ; // Watchdog timer control. use WTC_
++} volatile *INTEG_t ;
++
++enum
++{
++ ERRCS_wto_b = 0, // In INTEG_t -> errcs
++ ERRCS_wto_m = 0x00000001,
++ ERRCS_wne_b = 1, // In INTEG_t -> errcs
++ ERRCS_wne_m = 0x00000002,
++ ERRCS_ucw_b = 2, // In INTEG_t -> errcs
++ ERRCS_ucw_m = 0x00000004,
++ ERRCS_ucr_b = 3, // In INTEG_t -> errcs
++ ERRCS_ucr_m = 0x00000008,
++ ERRCS_upw_b = 4, // In INTEG_t -> errcs
++ ERRCS_upw_m = 0x00000010,
++ ERRCS_upr_b = 5, // In INTEG_t -> errcs
++ ERRCS_upr_m = 0x00000020,
++ ERRCS_udw_b = 6, // In INTEG_t -> errcs
++ ERRCS_udw_m = 0x00000040,
++ ERRCS_udr_b = 7, // In INTEG_t -> errcs
++ ERRCS_udr_m = 0x00000080,
++ ERRCS_sae_b = 8, // In INTEG_t -> errcs
++ ERRCS_sae_m = 0x00000100,
++ ERRCS_wre_b = 9, // In INTEG_t -> errcs
++ ERRCS_wre_m = 0x00000200,
++
++ WTC_en_b = 0, // In INTEG_t -> wtc
++ WTC_en_m = 0x00000001,
++ WTC_to_b = 1, // In INTEG_t -> wtc
++ WTC_to_m = 0x00000002,
++} ;
++
++#endif // __IDT_INTEG_H__
+diff -urN linux.old/include/asm-mips/rc32434/int.h linux.dev/include/asm-mips/rc32434/int.h
+--- linux.old/include/asm-mips/rc32434/int.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/int.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,167 @@
++#ifndef __IDT_INT_H__
++#define __IDT_INT_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * Interrupt Controller register definition.
++ *
++ * File : $Id: int.h,v 1.3 2002/06/06 18:34:04 astichte Exp $
++ *
++ * Author : ryan.holmqvist@idt.com
++ * Date : 20011005
++ * Update :
++ * $Log: int.h,v $
++ * Revision 1.3 2002/06/06 18:34:04 astichte
++ * Added XXX_PhysicalAddress and XXX_VirtualAddress
++ *
++ * Revision 1.2 2002/06/05 18:47:33 astichte
++ * Removed IDTField
++ *
++ * Revision 1.1 2002/05/29 17:33:22 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ *
++ ******************************************************************************/
++
++#include <asm/rc32434/types.h>
++
++enum
++{
++ INT0_PhysicalAddress = 0x18038000,
++ INT_PhysicalAddress = INT0_PhysicalAddress, // Default
++
++ INT0_VirtualAddress = 0xb8038000,
++ INT_VirtualAddress = INT0_VirtualAddress, // Default
++} ;
++
++struct INT_s
++{
++ U32 ipend ; //Pending interrupts. use INT?_
++ U32 itest ; //Test bits. use INT?_
++ U32 imask ; //Interrupt disabled when set. use INT?_
++} ;
++
++enum
++{
++ IPEND2 = 0, // HW 2 interrupt to core. use INT2_
++ IPEND3 = 1, // HW 3 interrupt to core. use INT3_
++ IPEND4 = 2, // HW 4 interrupt to core. use INT4_
++ IPEND5 = 3, // HW 5 interrupt to core. use INT5_
++ IPEND6 = 4, // HW 6 interrupt to core. use INT6_
++
++ IPEND_count, // must be last (used in loops)
++ IPEND_min = IPEND2 // min IPEND (used in loops)
++};
++
++typedef struct INTC_s
++{
++ struct INT_s i [IPEND_count] ;// use i[IPEND?] = INT?_
++ U32 nmips ; // use NMIPS_
++} volatile *INT_t ;
++
++enum
++{
++ INT2_timer0_b = 0,
++ INT2_timer0_m = 0x00000001,
++ INT2_timer1_b = 1,
++ INT2_timer1_m = 0x00000002,
++ INT2_timer2_b = 2,
++ INT2_timer2_m = 0x00000004,
++ INT2_refresh_b = 3,
++ INT2_refresh_m = 0x00000008,
++ INT2_watchdogTimeout_b = 4,
++ INT2_watchdogTimeout_m = 0x00000010,
++ INT2_undecodedCpuWrite_b = 5,
++ INT2_undecodedCpuWrite_m = 0x00000020,
++ INT2_undecodedCpuRead_b = 6,
++ INT2_undecodedCpuRead_m = 0x00000040,
++ INT2_undecodedPciWrite_b = 7,
++ INT2_undecodedPciWrite_m = 0x00000080,
++ INT2_undecodedPciRead_b = 8,
++ INT2_undecodedPciRead_m = 0x00000100,
++ INT2_undecodedDmaWrite_b = 9,
++ INT2_undecodedDmaWrite_m = 0x00000200,
++ INT2_undecodedDmaRead_b = 10,
++ INT2_undecodedDmaRead_m = 0x00000400,
++ INT2_ipBusSlaveAckError_b = 11,
++ INT2_ipBusSlaveAckError_m = 0x00000800,
++
++ INT3_dmaChannel0_b = 0,
++ INT3_dmaChannel0_m = 0x00000001,
++ INT3_dmaChannel1_b = 1,
++ INT3_dmaChannel1_m = 0x00000002,
++ INT3_dmaChannel2_b = 2,
++ INT3_dmaChannel2_m = 0x00000004,
++ INT3_dmaChannel3_b = 3,
++ INT3_dmaChannel3_m = 0x00000008,
++ INT3_dmaChannel4_b = 4,
++ INT3_dmaChannel4_m = 0x00000010,
++ INT3_dmaChannel5_b = 5,
++ INT3_dmaChannel5_m = 0x00000020,
++
++ INT5_uartGeneral0_b = 0,
++ INT5_uartGeneral0_m = 0x00000001,
++ INT5_uartTxrdy0_b = 1,
++ INT5_uartTxrdy0_m = 0x00000002,
++ INT5_uartRxrdy0_b = 2,
++ INT5_uartRxrdy0_m = 0x00000004,
++ INT5_pci_b = 3,
++ INT5_pci_m = 0x00000008,
++ INT5_pciDecoupled_b = 4,
++ INT5_pciDecoupled_m = 0x00000010,
++ INT5_spi_b = 5,
++ INT5_spi_m = 0x00000020,
++ INT5_deviceDecoupled_b = 6,
++ INT5_deviceDecoupled_m = 0x00000040,
++ INT5_i2cMaster_b = 7,
++ INT5_i2cMaster_m = 0x00000080,
++ INT5_i2cSlave_b = 8,
++ INT5_i2cSlave_m = 0x00000100,
++ INT5_ethOvr_b = 9,
++ INT5_ethOvr_m = 0x00000200,
++ INT5_ethUnd_b = 10,
++ INT5_ethUnd_m = 0x00000400,
++ INT5_ethPfd_b = 11,
++ INT5_ethPfd_m = 0x00000800,
++ INT5_nvram_b = 12,
++ INT5_nvram_m = 0x00001000,
++
++ INT6_gpio0_b = 0,
++ INT6_gpio0_m = 0x00000001,
++ INT6_gpio1_b = 1,
++ INT6_gpio1_m = 0x00000002,
++ INT6_gpio2_b = 2,
++ INT6_gpio2_m = 0x00000004,
++ INT6_gpio3_b = 3,
++ INT6_gpio3_m = 0x00000008,
++ INT6_gpio4_b = 4,
++ INT6_gpio4_m = 0x00000010,
++ INT6_gpio5_b = 5,
++ INT6_gpio5_m = 0x00000020,
++ INT6_gpio6_b = 6,
++ INT6_gpio6_m = 0x00000040,
++ INT6_gpio7_b = 7,
++ INT6_gpio7_m = 0x00000080,
++ INT6_gpio8_b = 8,
++ INT6_gpio8_m = 0x00000100,
++ INT6_gpio9_b = 9,
++ INT6_gpio9_m = 0x00000200,
++ INT6_gpio10_b = 10,
++ INT6_gpio10_m = 0x00000400,
++ INT6_gpio11_b = 11,
++ INT6_gpio11_m = 0x00000800,
++ INT6_gpio12_b = 12,
++ INT6_gpio12_m = 0x00001000,
++ INT6_gpio13_b = 13,
++ INT6_gpio13_m = 0x00002000,
++
++ NMIPS_gpio_b = 0,
++ NMIPS_gpio_m = 0x00000001,
++} ;
++
++#endif // __IDT_INT_H__
++
++
+diff -urN linux.old/include/asm-mips/rc32434/iparb.h linux.dev/include/asm-mips/rc32434/iparb.h
+--- linux.old/include/asm-mips/rc32434/iparb.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/iparb.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,95 @@
++#ifndef __IDT_IPARB_H__
++#define __IDT_IPARB_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * IP Arbiter register definitions.
++ *
++ * File : $Id: iparb.h,v 1.3 2002/06/06 18:34:04 astichte Exp $
++ *
++ * Author : Allen.Stichter@idt.com
++ * Date : 20020120
++ * Update :
++ * $Log: iparb.h,v $
++ * Revision 1.3 2002/06/06 18:34:04 astichte
++ * Added XXX_PhysicalAddress and XXX_VirtualAddress
++ *
++ * Revision 1.2 2002/06/05 19:01:42 astichte
++ * Removed IDTField
++ *
++ * Revision 1.1 2002/05/29 17:33:23 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ ******************************************************************************/
++
++#include <asm/rc32434/types.h>
++
++enum
++{
++ IPARB0_PhysicalAddress = 0x18048000,
++ IPARB_PhysicalAddress = IPARB0_PhysicalAddress, // Default
++
++ IPARB0_VirtualAddress = 0xb8048000,
++ IPARB_VirtualAddress = IPARB0_VirtualAddress, // Default
++} ;
++
++enum
++{
++ IPABMXC_ethernetReceive = 0,
++ IPABMXC_ethernetTransmit = 1,
++ IPABMXC_memoryToHoldFifo = 2,
++ IPABMXC_holdFifoToMemory = 3,
++ IPABMXC_pciToMemory = 4,
++ IPABMXC_memoryToPci = 5,
++ IPABMXC_pciTarget = 6,
++ IPABMXC_pciTargetStart = 7,
++ IPABMXC_cpuToIpBus = 8,
++
++ IPABMXC_Count, // Must be last in list !
++ IPABMXC_Min = IPABMXC_ethernetReceive,
++
++ IPAPXC_PriorityCount = 4, // 3-highest, 0-lowest.
++} ;
++
++typedef struct
++{
++ U32 ipapc [IPAPXC_PriorityCount] ; // ipapc[IPAPXC_] = IPAPC_
++ U32 ipabmc [IPABMXC_Count] ; // ipabmc[IPABMXC_] = IPABMC_
++ U32 ipac ; // use IPAC_
++ U32 ipaitcc; // use IPAITCC_
++ U32 ipaspare ;
++} volatile * IPARB_t ;
++
++enum
++{
++ IPAC_dwm_b = 2,
++ IPAC_dwm_m = 0x00000004,
++ IPAC_drm_b = 3,
++ IPAC_drm_m = 0x00000008,
++ IPAC_msk_b = 4,
++ IPAC_msk_m = 0x00000010,
++
++ IPAPC_ptc_b = 0,
++ IPAPC_ptc_m = 0x00003fff,
++ IPAPC_mf_b = 14,
++ IPAPC_mf_m = 0x00004000,
++ IPAPC_cptc_b = 16,
++ IPAPC_cptc_m = 0x3fff0000,
++
++ IPAITCC_itcc = 0,
++ IPAITCC_itcc, = 0x000001ff,
++
++ IPABMC_mtc_b = 0,
++ IPABMC_mtc_m = 0x00000fff,
++ IPABMC_p_b = 12,
++ IPABMC_p_m = 0x00003000,
++ IPABMC_msk_b = 14,
++ IPABMC_msk_m = 0x00004000,
++ IPABMC_cmtc_b = 16,
++ IPABMC_cmtc_m = 0x0fff0000,
++};
++
++#endif // __IDT_IPARB_H__
+diff -urN linux.old/include/asm-mips/rc32434/irm.h linux.dev/include/asm-mips/rc32434/irm.h
+--- linux.old/include/asm-mips/rc32434/irm.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/irm.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,55 @@
++#ifndef __IDT_IRM_H__
++#define __IDT_IRM_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * Internal Register Map
++ *
++ * File : $Id: irm.h,v 1.2 2002/06/05 14:51:06 astichte Exp $
++ *
++ * Author : Allen.Stichter@idt.com
++ * Date : 20020605
++ * Update :
++ * $Log: irm.h,v $
++ * Revision 1.2 2002/06/05 14:51:06 astichte
++ * *** empty log message ***
++ *
++ * Revision 1.1 2002/05/29 17:33:23 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ ******************************************************************************/
++
++/*
++ * NOTE --
++ * This file is here for backwards compatibility.
++ * DO NOT USE !!!!
++ */
++
++typedef enum
++{
++ IRM_Physical = 0x18000000, // Internal Reg. map physical.
++ RST_Offset = 0x00000000, // Includes sysid and RST.
++ DEV_Offset = 0x00010000, // Device Controller 0.
++ DDR_Offset = 0x00018000, // Double-Data-Rate mem. controller.
++ PMARB_Offset = 0x00020000, // PM bus arbiter.
++ TIM_Offset = 0x00028000, // Counter / timer.
++ INTEG_Offset = 0x00030000, // System Integrity.
++ INT_Offset = 0x00038000, // Interrupt controller.
++ DMA_Offset = 0x00040000, // DMA.
++ IPARB_Offset = 0x00044000, // IP bus arbiter.
++ GPIO_Offset = 0x00050000, // GPIO.
++ UART_Offset = 0x00058000, // UART
++ ETH_Offset = 0x00060000, // Ethernet 1.
++ I2C_Offset = 0x00068000, // I2C interface.
++ SPI_Offset = 0x00070000, // Serial Peripheral Interface.
++ NVRAM_Offset = 0x00078000, // NVRAM interface
++ AUTH_Offset = 0x0007c000, // Authorization unit
++ PCI_Offset = 0x00080000,
++ CROM_Offset = 0x000b8000, // Configuration ROM.
++ IRM_Size = 0x00200000, // Internal Reg. map size.
++} IRM_Offset_t ;
++
++#endif // __IDT_IRM_H__
+diff -urN linux.old/include/asm-mips/rc32434/irq.h linux.dev/include/asm-mips/rc32434/irq.h
+--- linux.old/include/asm-mips/rc32434/irq.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/irq.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,8 @@
++#ifndef __ASM_MACH_MIPS_IRQ_H
++#define __ASM_MACH_MIPS_IRQ_H
++
++#include <linux/config.h>
++
++#define NR_IRQS 256
++
++#endif /* __ASM_MACH_MIPS_IRQ_H */
+diff -urN linux.old/include/asm-mips/rc32434/nvram.h linux.dev/include/asm-mips/rc32434/nvram.h
+--- linux.old/include/asm-mips/rc32434/nvram.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/nvram.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,97 @@
++#ifndef __IDT_NVRAM_H
++#define __IDT_NVRAM_H
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * IP Arbiter register definitions.
++ *
++ * File : $Id: nvram.h,v 1.3 2003/07/24 18:34:04 astichte Exp $
++ *
++ * Author : kiran.rao@idt.com
++ * Date : 20030724
++ * Update :
++ * $Log: nvram.h,v $
++ *
++ *
++ ******************************************************************************/
++#include <asm/rc32434/tpes.h>
++
++
++enum
++{
++ NVRAM0_PhysicalAddress = 0xba000000,
++ NVRAM_PhysicalAddress = NVRAM0_PhysicalAddress, // Default
++
++ NVRAM0_VirtualAddress = 0xba000000,
++ NVRAM_VirtualAddress = NVRAM0_VirtualAddress, // Default
++} ;
++
++enum
++{
++ NVRCMD_cmd_b = 0,
++ NVRCMD_cmd_m = 0x0000007f,
++
++ NVRS_r_b = 0,
++ NVRS_r_m = 0x00000001,
++ NVRS_e_b = 1,
++ NVRS_e_m = 0x00000002,
++ NVRS_k_b = 2,
++ NVRS_k_m = 0x00000004,
++
++ NVRSM_r_b = 0,
++ NVRSM_r_m = 0x00000001,
++ NVRSM_e_b = 1,
++ NVRSM_e_m = 0x00000002,
++ NVRSM_k_b = 2,
++ NVRSM_k_m = 0x00000004,
++
++ NVRCFG0_pwidth_b = 0,
++ NVRCFG0_pwidth_m = 0x00000003,
++ NVRCFG0_nmax_b = 2,
++ NVRCFG0_nmax_m = 0x0000000C,
++ NVRCFG0_vppl_b = 4,
++ NVRCFG0_vppl_m = 0x000000f0,
++ NVRCFG0_vppm_b = 8,
++ NVRCFG0_vppm_m = 0x00000300,
++ NVRCFG0_dvpp_b = 10,
++ NVRCFG0_dvpp_m = 0x00000c00,
++ NVRCFG0_x_b = 12,
++ NVRCFG0_x_m = 0x00007000,
++
++ NVRCFG1_t1tecc_b = 0,
++ NVRCFG1_t1tecc_m = 0x00000003,
++ NVRCFG1_t1mrcl_b = 2,
++ NVRCFG1_t1mrcl_m = 0x0000000c,
++ NVRCFG1_t1bias_b = 4,
++ NVRCFG1_t1bias_m = 0x00000030,
++ NVRCFG1_t2tecc_b = 6,
++ NVRCFG1_t2tecc_m = 0x000000c0,
++ NVRCFG1_t2mrcl_b = 8,
++ NVRCFG1_t2mrcl_m = 0x00000300,
++ NVRCFG1_t2bias_b = 10,
++ NVRCFG1_t2bias_m = 0x00000c00,
++ NVRCFG1_t3tecc_b = 12,
++ NVRCFG1_t3tecc_m = 0x00003000,
++ NVRCFG1_t3mrcl_b = 14,
++ NVRCFG1_t3mrcl_m = 0x0000c000,
++ NVRCFG1_t3bias_b = 16,
++ NVRCFG1_t3bias_m = 0x00030000,
++ NVRCFG1_t4tecc_b = 18,
++ NVRCFG1_t4tecc_m = 0x000c0000,
++ NVRCFG1_t4mrcl_b = 20,
++ NVRCFG1_t4mrcl_m = 0x00300000,
++ NVRCFG1_t4bias_b = 22,
++ NVRCFG1_t4bias_m = 0x00c00000,
++ NVRCFG1_t5tecc_b = 24,
++ NVRCFG1_t5tecc_m = 0x03000000,
++ NVRCFG1_t5mrcl_b = 26,
++ NVRCFG1_t5mrcl_m = 0x0c000000,
++ NVRCFG1_t5bias_b = 28,
++ NVRCFG1_t5bias_m = 0x30000000,
++}
++
++#endif // __IDT_NVRAM_H__
++
+diff -urN linux.old/include/asm-mips/rc32434/pci.h linux.dev/include/asm-mips/rc32434/pci.h
+--- linux.old/include/asm-mips/rc32434/pci.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/pci.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,695 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * PCI register definitio
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_PCI_H__
++#define __IDT_PCI_H__
++
++enum
++{
++ PCI0_PhysicalAddress = 0x18080000,
++ PCI_PhysicalAddress = PCI0_PhysicalAddress,
++
++ PCI0_VirtualAddress = 0xB8080000,
++ PCI_VirtualAddress = PCI0_VirtualAddress,
++} ;
++
++enum
++{
++ PCI_LbaCount = 4, // Local base addresses.
++} ;
++
++typedef struct
++{
++ u32 a ; // Address.
++ u32 c ; // Control.
++ u32 m ; // mapping.
++} PCI_Map_s ;
++
++typedef struct
++{
++ u32 pcic ;
++ u32 pcis ;
++ u32 pcism ;
++ u32 pcicfga ;
++ u32 pcicfgd ;
++ PCI_Map_s pcilba [PCI_LbaCount] ;
++ u32 pcidac ;
++ u32 pcidas ;
++ u32 pcidasm ;
++ u32 pcidad ;
++ u32 pcidma8c ;
++ u32 pcidma9c ;
++ u32 pcitc ;
++} volatile *PCI_t ;
++
++// PCI messaging unit.
++enum
++{
++ PCIM_Count = 2,
++} ;
++typedef struct
++{
++ u32 pciim [PCIM_Count] ;
++ u32 pciom [PCIM_Count] ;
++ u32 pciid ;
++ u32 pciiic ;
++ u32 pciiim ;
++ u32 pciiod ;
++ u32 pciioic ;
++ u32 pciioim ;
++} volatile *PCIM_t ;
++
++/*******************************************************************************
++ *
++ * PCI Control Register
++ *
++ ******************************************************************************/
++enum
++{
++ PCIC_en_b = 0,
++ PCIC_en_m = 0x00000001,
++ PCIC_tnr_b = 1,
++ PCIC_tnr_m = 0x00000002,
++ PCIC_sce_b = 2,
++ PCIC_sce_m = 0x00000004,
++ PCIC_ien_b = 3,
++ PCIC_ien_m = 0x00000008,
++ PCIC_aaa_b = 4,
++ PCIC_aaa_m = 0x00000010,
++ PCIC_eap_b = 5,
++ PCIC_eap_m = 0x00000020,
++ PCIC_pcim_b = 6,
++ PCIC_pcim_m = 0x000001c0,
++ PCIC_pcim_disabled_v = 0,
++ PCIC_pcim_tnr_v = 1, // Satellite - target not ready
++ PCIC_pcim_suspend_v = 2, // Satellite - suspended CPU.
++ PCIC_pcim_extern_v = 3, // Host - external arbiter.
++ PCIC_pcim_fixed_v = 4, // Host - fixed priority arb.
++ PCIC_pcim_roundrobin_v = 5, // Host - round robin priority.
++ PCIC_pcim_reserved6_v = 6,
++ PCIC_pcim_reserved7_v = 7,
++ PCIC_igm_b = 9,
++ PCIC_igm_m = 0x00000200,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Status Register
++ *
++ ******************************************************************************/
++enum {
++ PCIS_eed_b = 0,
++ PCIS_eed_m = 0x00000001,
++ PCIS_wr_b = 1,
++ PCIS_wr_m = 0x00000002,
++ PCIS_nmi_b = 2,
++ PCIS_nmi_m = 0x00000004,
++ PCIS_ii_b = 3,
++ PCIS_ii_m = 0x00000008,
++ PCIS_cwe_b = 4,
++ PCIS_cwe_m = 0x00000010,
++ PCIS_cre_b = 5,
++ PCIS_cre_m = 0x00000020,
++ PCIS_mdpe_b = 6,
++ PCIS_mdpe_m = 0x00000040,
++ PCIS_sta_b = 7,
++ PCIS_sta_m = 0x00000080,
++ PCIS_rta_b = 8,
++ PCIS_rta_m = 0x00000100,
++ PCIS_rma_b = 9,
++ PCIS_rma_m = 0x00000200,
++ PCIS_sse_b = 10,
++ PCIS_sse_m = 0x00000400,
++ PCIS_ose_b = 11,
++ PCIS_ose_m = 0x00000800,
++ PCIS_pe_b = 12,
++ PCIS_pe_m = 0x00001000,
++ PCIS_tae_b = 13,
++ PCIS_tae_m = 0x00002000,
++ PCIS_rle_b = 14,
++ PCIS_rle_m = 0x00004000,
++ PCIS_bme_b = 15,
++ PCIS_bme_m = 0x00008000,
++ PCIS_prd_b = 16,
++ PCIS_prd_m = 0x00010000,
++ PCIS_rip_b = 17,
++ PCIS_rip_m = 0x00020000,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Status Mask Register
++ *
++ ******************************************************************************/
++enum {
++ PCISM_eed_b = 0,
++ PCISM_eed_m = 0x00000001,
++ PCISM_wr_b = 1,
++ PCISM_wr_m = 0x00000002,
++ PCISM_nmi_b = 2,
++ PCISM_nmi_m = 0x00000004,
++ PCISM_ii_b = 3,
++ PCISM_ii_m = 0x00000008,
++ PCISM_cwe_b = 4,
++ PCISM_cwe_m = 0x00000010,
++ PCISM_cre_b = 5,
++ PCISM_cre_m = 0x00000020,
++ PCISM_mdpe_b = 6,
++ PCISM_mdpe_m = 0x00000040,
++ PCISM_sta_b = 7,
++ PCISM_sta_m = 0x00000080,
++ PCISM_rta_b = 8,
++ PCISM_rta_m = 0x00000100,
++ PCISM_rma_b = 9,
++ PCISM_rma_m = 0x00000200,
++ PCISM_sse_b = 10,
++ PCISM_sse_m = 0x00000400,
++ PCISM_ose_b = 11,
++ PCISM_ose_m = 0x00000800,
++ PCISM_pe_b = 12,
++ PCISM_pe_m = 0x00001000,
++ PCISM_tae_b = 13,
++ PCISM_tae_m = 0x00002000,
++ PCISM_rle_b = 14,
++ PCISM_rle_m = 0x00004000,
++ PCISM_bme_b = 15,
++ PCISM_bme_m = 0x00008000,
++ PCISM_prd_b = 16,
++ PCISM_prd_m = 0x00010000,
++ PCISM_rip_b = 17,
++ PCISM_rip_m = 0x00020000,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Configuration Address Register
++ *
++ ******************************************************************************/
++enum {
++ PCICFGA_reg_b = 2,
++ PCICFGA_reg_m = 0x000000fc,
++ PCICFGA_reg_id_v = 0x00>>2, //use PCFGID_
++ PCICFGA_reg_04_v = 0x04>>2, //use PCFG04_
++ PCICFGA_reg_08_v = 0x08>>2, //use PCFG08_
++ PCICFGA_reg_0C_v = 0x0C>>2, //use PCFG0C_
++ PCICFGA_reg_pba0_v = 0x10>>2, //use PCIPBA_
++ PCICFGA_reg_pba1_v = 0x14>>2, //use PCIPBA_
++ PCICFGA_reg_pba2_v = 0x18>>2, //use PCIPBA_
++ PCICFGA_reg_pba3_v = 0x1c>>2, //use PCIPBA_
++ PCICFGA_reg_subsystem_v = 0x2c>>2, //use PCFGSS_
++ PCICFGA_reg_3C_v = 0x3C>>2, //use PCFG3C_
++ PCICFGA_reg_pba0c_v = 0x44>>2, //use PCIPBAC_
++ PCICFGA_reg_pba0m_v = 0x48>>2,
++ PCICFGA_reg_pba1c_v = 0x4c>>2, //use PCIPBAC_
++ PCICFGA_reg_pba1m_v = 0x50>>2,
++ PCICFGA_reg_pba2c_v = 0x54>>2, //use PCIPBAC_
++ PCICFGA_reg_pba2m_v = 0x58>>2,
++ PCICFGA_reg_pba3c_v = 0x5c>>2, //use PCIPBAC_
++ PCICFGA_reg_pba3m_v = 0x60>>2,
++ PCICFGA_reg_pmgt_v = 0x64>>2,
++ PCICFGA_func_b = 8,
++ PCICFGA_func_m = 0x00000700,
++ PCICFGA_dev_b = 11,
++ PCICFGA_dev_m = 0x0000f800,
++ PCICFGA_dev_internal_v = 0,
++ PCICFGA_bus_b = 16,
++ PCICFGA_bus_m = 0x00ff0000,
++ PCICFGA_bus_type0_v = 0, //local bus
++ PCICFGA_en_b = 31, // read only
++ PCICFGA_en_m = 0x80000000,
++} ;
++
++enum {
++ PCFGID_vendor_b = 0,
++ PCFGID_vendor_m = 0x0000ffff,
++ PCFGID_vendor_IDT_v = 0x111d,
++ PCFGID_device_b = 16,
++ PCFGID_device_m = 0xffff0000,
++ PCFGID_device_Korinade_v = 0x0214,
++
++ PCFG04_command_ioena_b = 1,
++ PCFG04_command_ioena_m = 0x00000001,
++ PCFG04_command_memena_b = 2,
++ PCFG04_command_memena_m = 0x00000002,
++ PCFG04_command_bmena_b = 3,
++ PCFG04_command_bmena_m = 0x00000004,
++ PCFG04_command_mwinv_b = 5,
++ PCFG04_command_mwinv_m = 0x00000010,
++ PCFG04_command_parena_b = 7,
++ PCFG04_command_parena_m = 0x00000040,
++ PCFG04_command_serrena_b = 9,
++ PCFG04_command_serrena_m = 0x00000100,
++ PCFG04_command_fastbbena_b = 10,
++ PCFG04_command_fastbbena_m = 0x00000200,
++ PCFG04_status_b = 16,
++ PCFG04_status_m = 0xffff0000,
++ PCFG04_status_66MHz_b = 21, // 66 MHz enable
++ PCFG04_status_66MHz_m = 0x00200000,
++ PCFG04_status_fbb_b = 23,
++ PCFG04_status_fbb_m = 0x00800000,
++ PCFG04_status_mdpe_b = 24,
++ PCFG04_status_mdpe_m = 0x01000000,
++ PCFG04_status_dst_b = 25,
++ PCFG04_status_dst_m = 0x06000000,
++ PCFG04_status_sta_b = 27,
++ PCFG04_status_sta_m = 0x08000000,
++ PCFG04_status_rta_b = 28,
++ PCFG04_status_rta_m = 0x10000000,
++ PCFG04_status_rma_b = 29,
++ PCFG04_status_rma_m = 0x20000000,
++ PCFG04_status_sse_b = 30,
++ PCFG04_status_sse_m = 0x40000000,
++ PCFG04_status_pe_b = 31,
++ PCFG04_status_pe_m = 0x40000000,
++
++ PCFG08_revId_b = 0,
++ PCFG08_revId_m = 0x000000ff,
++ PCFG08_classCode_b = 0,
++ PCFG08_classCode_m = 0xffffff00,
++ PCFG08_classCode_bridge_v = 06,
++ PCFG08_classCode_proc_v = 0x0b3000, // processor-MIPS
++ PCFG0C_cacheline_b = 0,
++ PCFG0C_cacheline_m = 0x000000ff,
++ PCFG0C_masterLatency_b = 8,
++ PCFG0C_masterLatency_m = 0x0000ff00,
++ PCFG0C_headerType_b = 16,
++ PCFG0C_headerType_m = 0x00ff0000,
++ PCFG0C_bist_b = 24,
++ PCFG0C_bist_m = 0xff000000,
++
++ PCIPBA_msi_b = 0,
++ PCIPBA_msi_m = 0x00000001,
++ PCIPBA_p_b = 3,
++ PCIPBA_p_m = 0x00000004,
++ PCIPBA_baddr_b = 8,
++ PCIPBA_baddr_m = 0xffffff00,
++
++ PCFGSS_vendorId_b = 0,
++ PCFGSS_vendorId_m = 0x0000ffff,
++ PCFGSS_id_b = 16,
++ PCFGSS_id_m = 0xffff0000,
++
++ PCFG3C_interruptLine_b = 0,
++ PCFG3C_interruptLine_m = 0x000000ff,
++ PCFG3C_interruptPin_b = 8,
++ PCFG3C_interruptPin_m = 0x0000ff00,
++ PCFG3C_minGrant_b = 16,
++ PCFG3C_minGrant_m = 0x00ff0000,
++ PCFG3C_maxLat_b = 24,
++ PCFG3C_maxLat_m = 0xff000000,
++
++ PCIPBAC_msi_b = 0,
++ PCIPBAC_msi_m = 0x00000001,
++ PCIPBAC_p_b = 1,
++ PCIPBAC_p_m = 0x00000002,
++ PCIPBAC_size_b = 2,
++ PCIPBAC_size_m = 0x0000007c,
++ PCIPBAC_sb_b = 7,
++ PCIPBAC_sb_m = 0x00000080,
++ PCIPBAC_pp_b = 8,
++ PCIPBAC_pp_m = 0x00000100,
++ PCIPBAC_mr_b = 9,
++ PCIPBAC_mr_m = 0x00000600,
++ PCIPBAC_mr_read_v =0, //no prefetching
++ PCIPBAC_mr_readLine_v =1,
++ PCIPBAC_mr_readMult_v =2,
++ PCIPBAC_mrl_b = 11,
++ PCIPBAC_mrl_m = 0x00000800,
++ PCIPBAC_mrm_b = 12,
++ PCIPBAC_mrm_m = 0x00001000,
++ PCIPBAC_trp_b = 13,
++ PCIPBAC_trp_m = 0x00002000,
++
++ PCFG40_trdyTimeout_b = 0,
++ PCFG40_trdyTimeout_m = 0x000000ff,
++ PCFG40_retryLim_b = 8,
++ PCFG40_retryLim_m = 0x0000ff00,
++};
++
++/*******************************************************************************
++ *
++ * PCI Local Base Address [0|1|2|3] Register
++ *
++ ******************************************************************************/
++enum {
++ PCILBA_baddr_b = 0, // In PCI_t -> pcilba [] .a
++ PCILBA_baddr_m = 0xffffff00,
++} ;
++/*******************************************************************************
++ *
++ * PCI Local Base Address Control Register
++ *
++ ******************************************************************************/
++enum {
++ PCILBAC_msi_b = 0, // In pPci->pcilba[i].c
++ PCILBAC_msi_m = 0x00000001,
++ PCILBAC_msi_mem_v = 0,
++ PCILBAC_msi_io_v = 1,
++ PCILBAC_size_b = 2, // In pPci->pcilba[i].c
++ PCILBAC_size_m = 0x0000007c,
++ PCILBAC_sb_b = 7, // In pPci->pcilba[i].c
++ PCILBAC_sb_m = 0x00000080,
++ PCILBAC_rt_b = 8, // In pPci->pcilba[i].c
++ PCILBAC_rt_m = 0x00000100,
++ PCILBAC_rt_noprefetch_v = 0, // mem read
++ PCILBAC_rt_prefetch_v = 1, // mem readline
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Local Base Address [0|1|2|3] Mapping Register
++ *
++ ******************************************************************************/
++enum {
++ PCILBAM_maddr_b = 8,
++ PCILBAM_maddr_m = 0xffffff00,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Decoupled Access Control Register
++ *
++ ******************************************************************************/
++enum {
++ PCIDAC_den_b = 0,
++ PCIDAC_den_m = 0x00000001,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI Decoupled Access Status Register
++ *
++ ******************************************************************************/
++enum {
++ PCIDAS_d_b = 0,
++ PCIDAS_d_m = 0x00000001,
++ PCIDAS_b_b = 1,
++ PCIDAS_b_m = 0x00000002,
++ PCIDAS_e_b = 2,
++ PCIDAS_e_m = 0x00000004,
++ PCIDAS_ofe_b = 3,
++ PCIDAS_ofe_m = 0x00000008,
++ PCIDAS_off_b = 4,
++ PCIDAS_off_m = 0x00000010,
++ PCIDAS_ife_b = 5,
++ PCIDAS_ife_m = 0x00000020,
++ PCIDAS_iff_b = 6,
++ PCIDAS_iff_m = 0x00000040,
++} ;
++
++/*******************************************************************************
++ *
++ * PCI DMA Channel 8 Configuration Register
++ *
++ ******************************************************************************/
++enum
++{
++ PCIDMA8C_mbs_b = 0, // Maximum Burst Size.
++ PCIDMA8C_mbs_m = 0x00000fff, // { pcidma8c }
++ PCIDMA8C_our_b = 12, // Optimize Unaligned Burst Reads.
++ PCIDMA8C_our_m = 0x00001000, // { pcidma8c }
++} ;
++
++/*******************************************************************************
++ *
++ * PCI DMA Channel 9 Configuration Register
++ *
++ ******************************************************************************/
++enum
++{
++ PCIDMA9C_mbs_b = 0, // Maximum Burst Size.
++ PCIDMA9C_mbs_m = 0x00000fff, // { pcidma9c }
++} ;
++
++/*******************************************************************************
++ *
++ * PCI to Memory(DMA Channel 8) AND Memory to PCI DMA(DMA Channel 9)Descriptors
++ *
++ ******************************************************************************/
++enum {
++ PCIDMAD_pt_b = 22, // in DEVCMD field (descriptor)
++ PCIDMAD_pt_m = 0x00c00000, // preferred transaction field
++ // These are for reads (DMA channel 8)
++ PCIDMAD_devcmd_mr_v = 0, //memory read
++ PCIDMAD_devcmd_mrl_v = 1, //memory read line
++ PCIDMAD_devcmd_mrm_v = 2, //memory read multiple
++ PCIDMAD_devcmd_ior_v = 3, //I/O read
++ // These are for writes (DMA channel 9)
++ PCIDMAD_devcmd_mw_v = 0, //memory write
++ PCIDMAD_devcmd_mwi_v = 1, //memory write invalidate
++ PCIDMAD_devcmd_iow_v = 3, //I/O write
++
++ // Swap byte field applies to both DMA channel 8 and 9
++ PCIDMAD_sb_b = 24, // in DEVCMD field (descriptor)
++ PCIDMAD_sb_m = 0x01000000, // swap byte field
++} ;
++
++
++/*******************************************************************************
++ *
++ * PCI Target Control Register
++ *
++ ******************************************************************************/
++enum
++{
++ PCITC_rtimer_b = 0, // In PCITC_t -> pcitc
++ PCITC_rtimer_m = 0x000000ff,
++ PCITC_dtimer_b = 8, // In PCITC_t -> pcitc
++ PCITC_dtimer_m = 0x0000ff00,
++ PCITC_rdr_b = 18, // In PCITC_t -> pcitc
++ PCITC_rdr_m = 0x00040000,
++ PCITC_ddt_b = 19, // In PCITC_t -> pcitc
++ PCITC_ddt_m = 0x00080000,
++} ;
++/*******************************************************************************
++ *
++ * PCI messaging unit [applies to both inbound and outbound registers ]
++ *
++ ******************************************************************************/
++enum
++{
++ PCIM_m0_b = 0, // In PCIM_t -> {pci{iic,iim,ioic,ioim}}
++ PCIM_m0_m = 0x00000001, // inbound or outbound message 0
++ PCIM_m1_b = 1, // In PCIM_t -> {pci{iic,iim,ioic,ioim}}
++ PCIM_m1_m = 0x00000002, // inbound or outbound message 1
++ PCIM_db_b = 2, // In PCIM_t -> {pci{iic,iim,ioic,ioim}}
++ PCIM_db_m = 0x00000004, // inbound or outbound doorbell
++};
++
++
++
++
++
++
++#define PCI_MSG_VirtualAddress 0xB8088010
++#define rc32434_pci ((volatile PCI_t) PCI0_VirtualAddress)
++#define rc32434_pci_msg ((volatile PCIM_t) PCI_MSG_VirtualAddress)
++
++#define PCIM_SHFT 0x6
++#define PCIM_BIT_LEN 0x7
++#define PCIM_H_EA 0x3
++#define PCIM_H_IA_FIX 0x4
++#define PCIM_H_IA_RR 0x5
++#if 0
++#define PCI_ADDR_START 0x13000000
++#endif
++
++#define PCI_ADDR_START 0x50000000
++
++#define CPUTOPCI_MEM_WIN 0x02000000
++#define CPUTOPCI_IO_WIN 0x00100000
++#define PCILBA_SIZE_SHFT 2
++#define PCILBA_SIZE_MASK 0x1F
++#define SIZE_256MB 0x1C
++#define SIZE_128MB 0x1B
++#define SIZE_64MB 0x1A
++#define SIZE_32MB 0x19
++#define SIZE_16MB 0x18
++#define SIZE_4MB 0x16
++#define SIZE_2MB 0x15
++#define SIZE_1MB 0x14
++#define KORINA_CONFIG0_ADDR 0x80000000
++#define KORINA_CONFIG1_ADDR 0x80000004
++#define KORINA_CONFIG2_ADDR 0x80000008
++#define KORINA_CONFIG3_ADDR 0x8000000C
++#define KORINA_CONFIG4_ADDR 0x80000010
++#define KORINA_CONFIG5_ADDR 0x80000014
++#define KORINA_CONFIG6_ADDR 0x80000018
++#define KORINA_CONFIG7_ADDR 0x8000001C
++#define KORINA_CONFIG8_ADDR 0x80000020
++#define KORINA_CONFIG9_ADDR 0x80000024
++#define KORINA_CONFIG10_ADDR 0x80000028
++#define KORINA_CONFIG11_ADDR 0x8000002C
++#define KORINA_CONFIG12_ADDR 0x80000030
++#define KORINA_CONFIG13_ADDR 0x80000034
++#define KORINA_CONFIG14_ADDR 0x80000038
++#define KORINA_CONFIG15_ADDR 0x8000003C
++#define KORINA_CONFIG16_ADDR 0x80000040
++#define KORINA_CONFIG17_ADDR 0x80000044
++#define KORINA_CONFIG18_ADDR 0x80000048
++#define KORINA_CONFIG19_ADDR 0x8000004C
++#define KORINA_CONFIG20_ADDR 0x80000050
++#define KORINA_CONFIG21_ADDR 0x80000054
++#define KORINA_CONFIG22_ADDR 0x80000058
++#define KORINA_CONFIG23_ADDR 0x8000005C
++#define KORINA_CONFIG24_ADDR 0x80000060
++#define KORINA_CONFIG25_ADDR 0x80000064
++#define KORINA_CMD (PCFG04_command_ioena_m | \
++ PCFG04_command_memena_m | \
++ PCFG04_command_bmena_m | \
++ PCFG04_command_mwinv_m | \
++ PCFG04_command_parena_m | \
++ PCFG04_command_serrena_m )
++
++#define KORINA_STAT (PCFG04_status_mdpe_m | \
++ PCFG04_status_sta_m | \
++ PCFG04_status_rta_m | \
++ PCFG04_status_rma_m | \
++ PCFG04_status_sse_m | \
++ PCFG04_status_pe_m)
++
++#define KORINA_CNFG1 ((KORINA_STAT<<16)|KORINA_CMD)
++
++#define KORINA_REVID 0
++#define KORINA_CLASS_CODE 0
++#define KORINA_CNFG2 ((KORINA_CLASS_CODE<<8) | \
++ KORINA_REVID)
++
++#define KORINA_CACHE_LINE_SIZE 4
++#define KORINA_MASTER_LAT 0x3c
++#define KORINA_HEADER_TYPE 0
++#define KORINA_BIST 0
++
++#define KORINA_CNFG3 ((KORINA_BIST << 24) | \
++ (KORINA_HEADER_TYPE<<16) | \
++ (KORINA_MASTER_LAT<<8) | \
++ KORINA_CACHE_LINE_SIZE )
++
++#define KORINA_BAR0 0x00000008 /* 128 MB Memory */
++#define KORINA_BAR1 0x18800001 /* 1 MB IO */
++#define KORINA_BAR2 0x18000001 /* 2 MB IO window for Korina
++ internal Registers */
++#define KORINA_BAR3 0x48000008 /* Spare 128 MB Memory */
++
++#define KORINA_CNFG4 KORINA_BAR0
++#define KORINA_CNFG5 KORINA_BAR1
++#define KORINA_CNFG6 KORINA_BAR2
++#define KORINA_CNFG7 KORINA_BAR3
++
++#define KORINA_SUBSYS_VENDOR_ID 0x011d
++#define KORINA_SUBSYSTEM_ID 0x0214
++#define KORINA_CNFG8 0
++#define KORINA_CNFG9 0
++#define KORINA_CNFG10 0
++#define KORINA_CNFG11 ((KORINA_SUBSYS_VENDOR_ID<<16) | \
++ KORINA_SUBSYSTEM_ID)
++#define KORINA_INT_LINE 1
++#define KORINA_INT_PIN 1
++#define KORINA_MIN_GNT 8
++#define KORINA_MAX_LAT 0x38
++#define KORINA_CNFG12 0
++#define KORINA_CNFG13 0
++#define KORINA_CNFG14 0
++#define KORINA_CNFG15 ((KORINA_MAX_LAT<<24) | \
++ (KORINA_MIN_GNT<<16) | \
++ (KORINA_INT_PIN<<8) | \
++ KORINA_INT_LINE)
++#define KORINA_RETRY_LIMIT 0x80
++#define KORINA_TRDY_LIMIT 0x80
++#define KORINA_CNFG16 ((KORINA_RETRY_LIMIT<<8) | \
++ KORINA_TRDY_LIMIT)
++#define PCI_PBAxC_R 0x0
++#define PCI_PBAxC_RL 0x1
++#define PCI_PBAxC_RM 0x2
++#define SIZE_SHFT 2
++
++#if defined(__MIPSEB__)
++#define KORINA_PBA0C ( PCIPBAC_mrl_m | PCIPBAC_sb_m | \
++ ((PCI_PBAxC_RM &0x3) << PCIPBAC_mr_b) | \
++ PCIPBAC_pp_m | \
++ (SIZE_128MB<<SIZE_SHFT) | \
++ PCIPBAC_p_m)
++#else
++#define KORINA_PBA0C ( PCIPBAC_mrl_m | \
++ ((PCI_PBAxC_RM &0x3) << PCIPBAC_mr_b) | \
++ PCIPBAC_pp_m | \
++ (SIZE_128MB<<SIZE_SHFT) | \
++ PCIPBAC_p_m)
++#endif
++#define KORINA_CNFG17 KORINA_PBA0C
++#define KORINA_PBA0M 0x0
++#define KORINA_CNFG18 KORINA_PBA0M
++
++#if defined(__MIPSEB__)
++#define KORINA_PBA1C ((SIZE_1MB<<SIZE_SHFT) | PCIPBAC_sb_m | \
++ PCIPBAC_msi_m)
++#else
++#define KORINA_PBA1C ((SIZE_1MB<<SIZE_SHFT) | \
++ PCIPBAC_msi_m)
++#endif
++#define KORINA_CNFG19 KORINA_PBA1C
++#define KORINA_PBA1M 0x0
++#define KORINA_CNFG20 KORINA_PBA1M
++
++#if defined(__MIPSEB__)
++#define KORINA_PBA2C ((SIZE_2MB<<SIZE_SHFT) | PCIPBAC_sb_m | \
++ PCIPBAC_msi_m)
++#else
++#define KORINA_PBA2C ((SIZE_2MB<<SIZE_SHFT) | \
++ PCIPBAC_msi_m)
++#endif
++#define KORINA_CNFG21 KORINA_PBA2C
++#define KORINA_PBA2M 0x18000000
++#define KORINA_CNFG22 KORINA_PBA2M
++#define KORINA_PBA3C 0
++#define KORINA_CNFG23 KORINA_PBA3C
++#define KORINA_PBA3M 0
++#define KORINA_CNFG24 KORINA_PBA3M
++
++
++
++#define PCITC_DTIMER_VAL 8
++#define PCITC_RTIMER_VAL 0x10
++
++
++
++
++#endif // __IDT_PCI_H__
++
++
++
+diff -urN linux.old/include/asm-mips/rc32434/pcikorina.h linux.dev/include/asm-mips/rc32434/pcikorina.h
+--- linux.old/include/asm-mips/rc32434/pcikorina.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/pcikorina.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,209 @@
++/* $Id: pciacacia.h,v 1.5 2001/05/01 10:09:17 carstenl Exp $
++ *
++ * 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.
++ */
++#ifndef _PCIKORINA_H
++#define _PCIKORINA_H
++
++
++#define PCI_MSG_VirtualAddress 0xB8088010
++#define rc32434_pci ((volatile PCI_t) PCI0_VirtualAddress)
++#define rc32434_pci_msg ((volatile PCIM_t) PCI_MSG_VirtualAddress)
++
++#define PCIM_SHFT 0x6
++#define PCIM_BIT_LEN 0x7
++#define PCIM_H_EA 0x3
++#define PCIM_H_IA_FIX 0x4
++#define PCIM_H_IA_RR 0x5
++#if 0
++#define PCI_ADDR_START 0x13000000
++#endif
++
++#define PCI_ADDR_START 0x50000000
++
++#define CPUTOPCI_MEM_WIN 0x02000000
++#define CPUTOPCI_IO_WIN 0x00100000
++#define PCILBA_SIZE_SHFT 2
++#define PCILBA_SIZE_MASK 0x1F
++#define SIZE_256MB 0x1C
++#define SIZE_128MB 0x1B
++#define SIZE_64MB 0x1A
++#define SIZE_32MB 0x19
++#define SIZE_16MB 0x18
++#define SIZE_4MB 0x16
++#define SIZE_2MB 0x15
++#define SIZE_1MB 0x14
++#define KORINA_CONFIG0_ADDR 0x80000000
++#define KORINA_CONFIG1_ADDR 0x80000004
++#define KORINA_CONFIG2_ADDR 0x80000008
++#define KORINA_CONFIG3_ADDR 0x8000000C
++#define KORINA_CONFIG4_ADDR 0x80000010
++#define KORINA_CONFIG5_ADDR 0x80000014
++#define KORINA_CONFIG6_ADDR 0x80000018
++#define KORINA_CONFIG7_ADDR 0x8000001C
++#define KORINA_CONFIG8_ADDR 0x80000020
++#define KORINA_CONFIG9_ADDR 0x80000024
++#define KORINA_CONFIG10_ADDR 0x80000028
++#define KORINA_CONFIG11_ADDR 0x8000002C
++#define KORINA_CONFIG12_ADDR 0x80000030
++#define KORINA_CONFIG13_ADDR 0x80000034
++#define KORINA_CONFIG14_ADDR 0x80000038
++#define KORINA_CONFIG15_ADDR 0x8000003C
++#define KORINA_CONFIG16_ADDR 0x80000040
++#define KORINA_CONFIG17_ADDR 0x80000044
++#define KORINA_CONFIG18_ADDR 0x80000048
++#define KORINA_CONFIG19_ADDR 0x8000004C
++#define KORINA_CONFIG20_ADDR 0x80000050
++#define KORINA_CONFIG21_ADDR 0x80000054
++#define KORINA_CONFIG22_ADDR 0x80000058
++#define KORINA_CONFIG23_ADDR 0x8000005C
++#define KORINA_CONFIG24_ADDR 0x80000060
++#define KORINA_CONFIG25_ADDR 0x80000064
++#define KORINA_CMD (PCFG04_command_ioena_m | \
++ PCFG04_command_memena_m | \
++ PCFG04_command_bmena_m | \
++ PCFG04_command_mwinv_m | \
++ PCFG04_command_parena_m | \
++ PCFG04_command_serrena_m )
++
++#define KORINA_STAT (PCFG04_status_mdpe_m | \
++ PCFG04_status_sta_m | \
++ PCFG04_status_rta_m | \
++ PCFG04_status_rma_m | \
++ PCFG04_status_sse_m | \
++ PCFG04_status_pe_m)
++
++#define KORINA_CNFG1 ((KORINA_STAT<<16)|KORINA_CMD)
++
++#define KORINA_REVID 0
++#define KORINA_CLASS_CODE 0
++#define KORINA_CNFG2 ((KORINA_CLASS_CODE<<8) | \
++ KORINA_REVID)
++
++#define KORINA_CACHE_LINE_SIZE 4
++#define KORINA_MASTER_LAT 0x3c
++#define KORINA_HEADER_TYPE 0
++#define KORINA_BIST 0
++
++#define KORINA_CNFG3 ((KORINA_BIST << 24) | \
++ (KORINA_HEADER_TYPE<<16) | \
++ (KORINA_MASTER_LAT<<8) | \
++ KORINA_CACHE_LINE_SIZE )
++
++#define KORINA_BAR0 0x00000008 /* 128 MB Memory */
++#define KORINA_BAR1 0x18800001 /* 1 MB IO */
++#define KORINA_BAR2 0x18000001 /* 2 MB IO window for Acacia
++ internal Registers */
++#define KORINA_BAR3 0x48000008 /* Spare 128 MB Memory */
++
++#define KORINA_CNFG4 KORINA_BAR0
++#define KORINA_CNFG5 KORINA_BAR1
++#define KORINA_CNFG6 KORINA_BAR2
++#define KORINA_CNFG7 KORINA_BAR3
++
++#define KORINA_SUBSYS_VENDOR_ID 0
++#define KORINA_SUBSYSTEM_ID 0
++#define KORINA_CNFG8 0
++#define KORINA_CNFG9 0
++#define KORINA_CNFG10 0
++#define KORINA_CNFG11 ((KORINA_SUBSYS_VENDOR_ID<<16) | \
++ KORINA_SUBSYSTEM_ID)
++#define KORINA_INT_LINE 1
++#define KORINA_INT_PIN 1
++#define KORINA_MIN_GNT 8
++#define KORINA_MAX_LAT 0x38
++#define KORINA_CNFG12 0
++#define KORINA_CNFG13 0
++#define KORINA_CNFG14 0
++#define KORINA_CNFG15 ((KORINA_MAX_LAT<<24) | \
++ (KORINA_MIN_GNT<<16) | \
++ (KORINA_INT_PIN<<8) | \
++ KORINA_INT_LINE)
++#define KORINA_RETRY_LIMIT 0x80
++#define KORINA_TRDY_LIMIT 0x80
++#define KORINA_CNFG16 ((KORINA_RETRY_LIMIT<<8) | \
++ KORINA_TRDY_LIMIT)
++#define PCI_PBAxC_R 0x0
++#define PCI_PBAxC_RL 0x1
++#define PCI_PBAxC_RM 0x2
++#define SIZE_SHFT 2
++
++#ifdef __MIPSEB__
++#define KORINA_PBA0C ( PCIPBAC_mrl_m | PCIPBAC_sb_m | \
++ ((PCI_PBAxC_RM &0x3) << PCIPBAC_mr_b) | \
++ PCIPBAC_pp_m | \
++ (SIZE_32MB<<SIZE_SHFT) | \
++ PCIPBAC_p_m)
++#else
++#define KORINA_PBA0C ( PCIPBAC_mrl_m | \
++ ((PCI_PBAxC_RM &0x3) << PCIPBAC_mr_b) | \
++ PCIPBAC_pp_m | \
++ (SIZE_32MB<<SIZE_SHFT) | \
++ PCIPBAC_p_m)
++#endif
++
++#if 0
++
++#define KORINA_PBA0C ( PCIPBAC_sb_m | PCIPBAC_pp_m | \
++ ((PCI_PBAxC_R &0x3) << PCIPBAC_mr_b) | \
++ (SIZE_128MB<<SIZE_SHFT))
++#endif
++#define KORINA_CNFG17 KORINA_PBA0C
++#define KORINA_PBA0M 0x0
++#define KORINA_CNFG18 KORINA_PBA0M
++
++#ifdef __MIPSEB__
++#define KORINA_PBA1C ((SIZE_1MB<<SIZE_SHFT) | PCIPBAC_sb_m | \
++ PCIPBAC_msi_m)
++#else
++#define KORINA_PBA1C ((SIZE_1MB<<SIZE_SHFT) | \
++ PCIPBAC_msi_m)
++
++#endif
++
++#define KORINA_CNFG19 KORINA_PBA1C
++#define KORINA_PBA1M 0x0
++#define KORINA_CNFG20 KORINA_PBA1M
++
++#ifdef __MIPSEB__
++#define KORINA_PBA2C ((SIZE_2MB<<SIZE_SHFT) | PCIPBAC_sb_m | \
++ PCIPBAC_msi_m)
++#else
++#define KORINA_PBA2C ((SIZE_2MB<<SIZE_SHFT) | \
++ PCIPBAC_msi_m)
++
++#endif
++#define KORINA_CNFG21 KORINA_PBA2C
++#define KORINA_PBA2M 0x18000000
++#define KORINA_CNFG22 KORINA_PBA2M
++#define KORINA_PBA3C 0
++#define KORINA_CNFG23 KORINA_PBA3C
++#define KORINA_PBA3M 0
++#define KORINA_CNFG24 KORINA_PBA3M
++
++
++
++#define PCITC_DTIMER_VAL 8
++#define PCITC_RTIMER_VAL 0x10
++
++
++#endif /* _PCIKORINA_H */
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
+diff -urN linux.old/include/asm-mips/rc32434/pci_regs.h linux.dev/include/asm-mips/rc32434/pci_regs.h
+--- linux.old/include/asm-mips/rc32434/pci_regs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/pci_regs.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,8 @@
++/* Override the default address space for this arch
++*/
++
++#include <linux/pci_regs.h>
++
++//#undef PCI_BASE_ADDRESS_SPACE
++//#define PCI_BASE_ADDRESS_SPACE PCI_BASE_ADDRESS_SPACE_MEMORY
++
+diff -urN linux.old/include/asm-mips/rc32434/rb.h linux.dev/include/asm-mips/rc32434/rb.h
+--- linux.old/include/asm-mips/rc32434/rb.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/rb.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,69 @@
++#ifndef __MIPS_RB_H__
++#define __MIPS_RB_H__
++#include <linux/genhd.h>
++
++#define IDT434_REG_BASE ((volatile void *) KSEG1ADDR(0x18000000))
++#define DEV0BASE 0x010000
++#define DEV0MASK 0x010004
++#define DEV0C 0x010008
++#define DEV0TC 0x01000C
++#define DEV1BASE 0x010010
++#define DEV1MASK 0x010014
++#define DEV1C 0x010018
++#define DEV1TC 0x01001C
++#define DEV2BASE 0x010020
++#define DEV2MASK 0x010024
++#define DEV2C 0x010028
++#define DEV2TC 0x01002C
++#define DEV3BASE 0x010030
++#define DEV3MASK 0x010034
++#define DEV3C 0x010038
++#define DEV3TC 0x01003C
++#define BTCS 0x010040
++#define BTCOMPARE 0x010044
++#define GPIOFUNC 0x050000
++#define GPIOCFG 0x050004
++#define GPIOD 0x050008
++#define GPIOILEVEL 0x05000C
++#define GPIOISTAT 0x050010
++#define GPIONMIEN 0x050014
++#define IMASK6 0x038038
++
++#define LO_WPX (1 << 0)
++#define LO_ALE (1 << 1)
++#define LO_CLE (1 << 2)
++#define LO_CEX (1 << 3)
++#define LO_FOFF (1 << 5)
++#define LO_SPICS (1 << 6)
++#define LO_ULED (1 << 7)
++
++typedef enum {
++ FUNC = 0x00,
++ CFG = 0x04,
++ DATA = 0x08,
++ ILEVEL = 0x0c,
++ ISTAT = 0x10,
++ NMIEN = 0x14
++} gpio_func;
++
++extern void changeLatchU5(unsigned char orMask, unsigned char nandMask);
++extern unsigned get434Reg(unsigned regOffs);
++extern void set434Reg(unsigned regOffs, unsigned bit, unsigned len, unsigned val);
++extern void gpio_set(gpio_func func, u32 mask, u32 value);
++extern u32 gpio_get(gpio_func func);
++
++#define get434Reg(x) (*(volatile unsigned *) (IDT434_REG_BASE + (x)))
++
++struct korina_device {
++ char *name;
++ unsigned char mac[6];
++ struct net_device *dev;
++};
++
++struct cf_device {
++ int gpio_pin;
++ void *dev;
++ struct gendisk *gd;
++};
++
++#endif
+diff -urN linux.old/include/asm-mips/rc32434/rc32434.h linux.dev/include/asm-mips/rc32434/rc32434.h
+--- linux.old/include/asm-mips/rc32434/rc32434.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/rc32434.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,126 @@
++/*
++ ***************************************************************************
++ * Definitions for IDT RC323434 CPU.
++ *
++ ****************************************************************************
++ * Kiran Rao
++ *
++ * Original form
++ ****************************************************************************
++ * P. Sadik Oct 08, 2003
++ *
++ * Started revision history
++ * Made IDT_BUS_FREQ a kernel configuration parameter
++ ****************************************************************************
++ * P. Sadik Oct 10, 2003
++ *
++ * Removed IDT_BUS_FREQ, since this parameter is no longer required. Instead
++ * idt_cpu_freq is used everywhere
++ ****************************************************************************
++ * P. Sadik Oct 20, 2003
++ *
++ * Removed RC32434_BASE_BAUD
++ ****************************************************************************
++*/
++#ifndef _RC32434_H_
++#define _RC32434_H_
++
++#include <linux/config.h>
++#include <linux/delay.h>
++#include <asm/io.h>
++#include <asm/rc32434/timer.h>
++
++#define RC32434_REG_BASE 0x18000000
++
++#define interrupt ((volatile INT_t ) INT0_VirtualAddress)
++#define timer ((volatile TIM_t) TIM0_VirtualAddress)
++#define gpio ((volatile GPIO_t) GPIO0_VirtualAddress)
++
++#define IDT_CLOCK_MULT 2
++#define MIPS_CPU_TIMER_IRQ 7
++/* Interrupt Controller */
++#define IC_GROUP0_PEND (RC32434_REG_BASE + 0x38000)
++#define IC_GROUP0_MASK (RC32434_REG_BASE + 0x38008)
++#define IC_GROUP_OFFSET 0x0C
++
++#define NUM_INTR_GROUPS 5
++/* 16550 UARTs */
++
++#define GROUP0_IRQ_BASE 8 /* GRP2 IRQ numbers start here */
++#define GROUP1_IRQ_BASE (GROUP0_IRQ_BASE + 32) /* GRP3 IRQ numbers start here */
++#define GROUP2_IRQ_BASE (GROUP1_IRQ_BASE + 32) /* GRP4 IRQ numbers start here */
++#define GROUP3_IRQ_BASE (GROUP2_IRQ_BASE + 32) /* GRP5 IRQ numbers start here */
++#define GROUP4_IRQ_BASE (GROUP3_IRQ_BASE + 32)
++
++
++#ifdef __MIPSEB__
++#define RC32434_UART0_BASE (RC32434_REG_BASE + 0x58003)
++#else
++#define RC32434_UART0_BASE (RC32434_REG_BASE + 0x58000)
++#endif
++
++#define RC32434_UART0_IRQ GROUP3_IRQ_BASE + 0
++// #define EB434_UART1_IRQ GROUP4_IRQ_BASE + 11
++
++#define local_readl(addr) __raw_readl(addr)
++#define local_writel(l,addr) __raw_writel(l,addr)
++
++/* cpu pipeline flush */
++static inline void rc32434_sync(void)
++{
++ __asm__ volatile ("sync");
++}
++
++static inline void rc32434_sync_udelay(int us)
++{
++ __asm__ volatile ("sync");
++ udelay(us);
++}
++
++static inline void rc32434_sync_delay(int ms)
++{
++ __asm__ volatile ("sync");
++ mdelay(ms);
++}
++
++/*
++ * C access to CLZ and CLO instructions
++ * (count leading zeroes/ones).
++ */
++static inline int rc32434_clz(unsigned long val)
++{
++ int ret;
++ __asm__ volatile (
++ ".set\tnoreorder\n\t"
++ ".set\tnoat\n\t"
++ ".set\tmips32\n\t"
++ "clz\t%0,%1\n\t"
++ ".set\tmips0\n\t"
++ ".set\tat\n\t"
++ ".set\treorder"
++ : "=r" (ret)
++ : "r" (val));
++
++ return ret;
++}
++static inline int rc32434_clo(unsigned long val)
++{
++ int ret;
++ __asm__ volatile (
++ ".set\tnoreorder\n\t"
++ ".set\tnoat\n\t"
++ ".set\tmips32\n\t"
++ "clo\t%0,%1\n\t"
++ ".set\tmips0\n\t"
++ ".set\tat\n\t"
++ ".set\treorder"
++ : "=r" (ret)
++ : "r" (val));
++
++ return ret;
++}
++
++extern void cons_putc(char c);
++extern void cons_puts(char *s);
++
++#endif /* _RC32434_H_ */
+diff -urN linux.old/include/asm-mips/rc32434/rst.h linux.dev/include/asm-mips/rc32434/rst.h
+--- linux.old/include/asm-mips/rc32434/rst.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/rst.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,105 @@
++#ifndef __IDT_RST_H__
++#define __IDT_RST_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * Reset register definitions.
++ *
++ * File : $Id: rst.h,v 1.2 2002/06/06 18:34:05 astichte Exp $
++ *
++ * Author : Allen.Stichter@idt.com
++ * Date : 20020118
++ * Update :
++ * $Log: rst.h,v $
++ * Revision 1.2 2002/06/06 18:34:05 astichte
++ * Added XXX_PhysicalAddress and XXX_VirtualAddress
++ *
++ * Revision 1.1 2002/05/29 17:33:24 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ *
++ ******************************************************************************/
++
++#include <asm/rc32434/types.h>
++
++enum
++{
++ RST0_PhysicalAddress = 0x18000000,
++ RST_PhysicalAddress = RST0_PhysicalAddress, // Default
++
++ RST0_VirtualAddress = 0xb8000000,
++ RST_VirtualAddress = RST0_VirtualAddress, // Default
++} ;
++
++typedef struct RST_s
++{
++ U32 filler [0x0006] ;
++ U32 sysid ;
++ U32 filler2 [0x2000-8] ; // Pad out to offset 0x8000
++ U32 reset ;
++ U32 bcv ;
++ U32 cea ;
++} volatile * RST_t ;
++
++enum
++{
++ SYSID_rev_b = 0,
++ SYSID_rev_m = 0x000000ff,
++ SYSID_imp_b = 8,
++ SYSID_imp_m = 0x000fff00,
++ SYSID_vendor_b = 20,
++ SYSID_vendor_m = 0xfff00000,
++
++ BCV_pll_b = 0,
++ BCV_pll_m = 0x0000000f,
++ BCV_pll_PLLBypass_v = 0x0, // PCLK=1*CLK.
++ BCV_pll_Mul3_v = 0x1, // PCLK=3*CLK.
++ BCV_pll_Mul4_v = 0x2, // PCLK=4*CLK.
++ BCV_pll_SlowMul5_v = 0x3, // PCLK=4*CLK.
++ BCV_pll_Mul5_v = 0x4, // PCLK=6*CLK.
++ BCV_pll_SlowMul6_v = 0x5, // PCLK=8*CLK.
++ BCV_pll_Mul6_v = 0x6, // PCLK=8*CLK.
++ BCV_pll_Mul8_v = 0x7, // PCLK=8*CLK.
++ BCV_pll_Mul10_v = 0x8, // PCLK=8*CLK.
++ BCV_pll_Res5_v = 0x9,
++ BCV_pll_Res6_v = 0xa,
++ BCV_pll_Res7_v = 0xb,
++ BCV_pll_Res8_v = 0xc,
++ BCV_pll_Res13_v = 0xd,
++ BCV_pll_Res14_v = 0xe,
++ BCV_pll_Res15_v = 0xf,
++ BCV_clkDiv_b = 4,
++ BCV_clkDiv_m = 0x00000030,
++ BCV_clkDiv_Div1_v = 0x0,
++ BCV_clkDiv_Div2_v = 0x1,
++ BCV_clkDiv_Div4_v = 0x2,
++ BCV_clkDiv_Res3_v = 0x3,
++ BCV_bigEndian_b = 6,
++ BCV_bigEndian_m = 0x00000040,
++ BCV_resetFast_b = 7,
++ BCV_resetFast_m = 0x00000080,
++ BCV_pciMode_b = 8,
++ BCV_pciMode_m = 0x00000100,
++ BCV_pciMode_disabled_v = 0, // PCI is disabled.
++ BCV_pciMode_tnr_v = 1, // satellite Target Not Ready.
++ BCV_pciMode_suspended_v = 2, // satellite with suspended CPU.
++ BCV_pciMode_external_v = 3, // host, external arbiter.
++ BCV_pciMode_fixed_v = 4, // host, fixed priority arbiter.
++ BCV_pciMode_roundRobin_v= 5, // host, round robin arbiter.
++ BCV_pciMode_res6_v = 6,
++ BCV_pciMode_res7_v = 7,
++ BCV_watchDisable_b = 11,
++ BCV_watchDisable_m = 0x00000800,
++ BCV_pllTest_b = 12,
++ BCV_pllTest_m = 0x00001000,
++ BCV_nvramInit_b = 13,
++ BCV_nvramInit_m = 0x00002000,
++ BCV_clksyncTstMd_b = 14,
++ BCV_clksyncTstMd_m = 0x00004000,
++ BCV_delayBypass_b = 15,
++ BCV_delayByPass_m = 0x00008000,
++} ;
++#endif // __IDT_RST_H__
+diff -urN linux.old/include/asm-mips/rc32434/spi.h linux.dev/include/asm-mips/rc32434/spi.h
+--- linux.old/include/asm-mips/rc32434/spi.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/spi.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,100 @@
++#ifndef __IDT_SPI_H__
++#define __IDT_SPI_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * Serial Peripheral Interface register definitions.
++ *
++ * File : $Id: spi.h,v 1.2 2002/06/06 18:34:05 astichte Exp $
++ *
++ * Author : ryan.holmQVist@idt.com
++ * Date : 20011005
++ * Update :
++ * $Log: spi.h,v $
++ * Revision 1.2 2002/06/06 18:34:05 astichte
++ * Added XXX_PhysicalAddress and XXX_VirtualAddress
++ *
++ * Revision 1.1 2002/05/29 17:33:25 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ *
++ ******************************************************************************/
++
++#include <asm/rc32434/types.h>
++
++enum
++{
++ SPI0_PhysicalAddress = 0x18070000,
++ SPI_PhysicalAddress = SPI0_PhysicalAddress,
++
++ SPI0_VirtualAddress = 0xb8070000,
++ SPI_VirtualAddress = SPI0_VirtualAddress,
++} ;
++
++typedef struct
++{
++ U32 spcp ; // prescalar. 0=off, * spiClk = sysClk/(2*(spcp+1)*SPR)
++ U32 spc ; // spi control reg use SPC_
++ U32 sps ; // spi status reg use SPS_
++ U32 spd ; // spi data reg use SPD_
++ U32 siofunc ; // serial IO function use SIOFUNC_
++ U32 siocfg ; // serial IO config use SIOCFG_
++ U32 siod; // serial IO data use SIOD_
++} volatile *SPI_t ;
++
++enum
++{
++ SPCP_div_b = 0,
++ SPCP_div_m = 0x000000ff,
++ SPC_spr_b = 0,
++ SPC_spr_m = 0x00000003,
++ SPC_spr_div2_v = 0,
++ SPC_spr_div4_v = 1,
++ SPC_spr_div16_v = 2,
++ SPC_spr_div32_v = 3,
++ SPC_cpha_b = 2,
++ SPC_cpha_m = 0x00000004,
++ SPC_cpol_b = 3,
++ SPC_cpol_m = 0x00000008,
++ SPC_mstr_b = 4,
++ SPC_mstr_m = 0x00000010,
++ SPC_spe_b = 6,
++ SPC_spe_m = 0x00000040,
++ SPC_spie_b = 7,
++ SPC_spie_m = 0x00000080,
++
++ SPS_modf_b = 4,
++ SPS_modf_m = 0x00000010,
++ SPS_wcol_b = 6,
++ SPS_wcol_m = 0x00000040,
++ SPS_spif_b = 7,
++ SPS_spif_m = 0x00000070,
++
++ SPD_data_b = 0,
++ SPD_data_m = 0x000000ff,
++
++ SIOFUNC_sdo_b = 0,
++ SIOFUNC_sdo_m = 0x00000001,
++ SIOFUNC_sdi_b = 1,
++ SIOFUNC_sdi_m = 0x00000002,
++ SIOFUNC_sck_b = 2,
++ SIOFUNC_sck_m = 0x00000004,
++
++ SIOCFG_sdo_b = 0,
++ SIOCFG_sdo_m = 0x00000001,
++ SIOCFG_sdi_b = 1,
++ SIOCFG_sdi_m = 0x00000002,
++ SIOCFG_sck_b = 2,
++ SIOCFG_sck_m = 0x00000004,
++
++ SIOD_sdo_b = 0,
++ SIOD_sdo_m = 0x00000001,
++ SIOD_sdi_b = 1,
++ SIOD_sdi_m = 0x00000002,
++ SIOD_sck_b = 2,
++ SIOD_sck_m = 0x00000004,
++} ;
++#endif // __IDT_SPI_H__
+diff -urN linux.old/include/asm-mips/rc32434/timer.h linux.dev/include/asm-mips/rc32434/timer.h
+--- linux.old/include/asm-mips/rc32434/timer.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/timer.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,91 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Definitions for timer registers
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt,neb.
++ *
++ * Initial Release
++ *
++ *
++ *
++ **************************************************************************
++ */
++
++#ifndef __IDT_TIM_H__
++#define __IDT_TIM_H__
++
++enum
++{
++ TIM0_PhysicalAddress = 0x18028000,
++ TIM_PhysicalAddress = TIM0_PhysicalAddress, // Default
++
++ TIM0_VirtualAddress = 0xb8028000,
++ TIM_VirtualAddress = TIM0_VirtualAddress, // Default
++} ;
++
++enum
++{
++ TIM_Count = 3,
++} ;
++
++struct TIM_CNTR_s
++{
++ u32 count ;
++ u32 compare ;
++ u32 ctc ; //use CTC_
++} ;
++
++typedef struct TIM_s
++{
++ struct TIM_CNTR_s tim [TIM_Count] ;
++ u32 rcount ; //use RCOUNT_
++ u32 rcompare ; //use RCOMPARE_
++ u32 rtc ; //use RTC_
++} volatile * TIM_t ;
++
++enum
++{
++ CTC_en_b = 0,
++ CTC_en_m = 0x00000001,
++ CTC_to_b = 1,
++ CTC_to_m = 0x00000002,
++
++ RCOUNT_count_b = 0,
++ RCOUNT_count_m = 0x0000ffff,
++ RCOMPARE_compare_b = 0,
++ RCOMPARE_compare_m = 0x0000ffff,
++ RTC_ce_b = 0,
++ RTC_ce_m = 0x00000001,
++ RTC_to_b = 1,
++ RTC_to_m = 0x00000002,
++ RTC_rqe_b = 2,
++ RTC_rqe_m = 0x00000004,
++
++} ;
++#endif // __IDT_TIM_H__
++
+diff -urN linux.old/include/asm-mips/rc32434/tim.h linux.dev/include/asm-mips/rc32434/tim.h
+--- linux.old/include/asm-mips/rc32434/tim.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/tim.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,78 @@
++#ifndef __IDT_TIM_H__
++#define __IDT_TIM_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * Timer register definition.
++ *
++ * File : $Id: tim.h,v 1.2 2002/06/06 18:34:05 astichte Exp $
++ *
++ * Author : ryan.holmQVist@idt.com
++ * Date : 20011005
++ * Update :
++ * $Log: tim.h,v $
++ * Revision 1.2 2002/06/06 18:34:05 astichte
++ * Added XXX_PhysicalAddress and XXX_VirtualAddress
++ *
++ * Revision 1.1 2002/05/29 17:33:25 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ *
++ ******************************************************************************/
++
++
++#include <asm/rc32434/types.h>
++
++enum
++{
++ TIM0_PhysicalAddress = 0x18028000,
++ TIM_PhysicalAddress = TIM0_PhysicalAddress, // Default
++
++ TIM0_VirtualAddress = 0xb8028000,
++ TIM_VirtualAddress = TIM0_VirtualAddress, // Default
++} ;
++
++enum
++{
++ TIM_Count = 3,
++} ;
++
++struct TIM_CNTR_s
++{
++ U32 count ;
++ U32 compare ;
++ U32 ctc ; //use CTC_
++} ;
++
++typedef struct TIM_s
++{
++ struct TIM_CNTR_s tim [TIM_Count] ;
++ U32 rcount ; //use RCOUNT_
++ U32 rcompare ; //use RCOMPARE_
++ U32 rtc ; //use RTC_
++} volatile * TIM_t ;
++
++enum
++{
++ CTC_en_b = 0,
++ CTC_en_m = 0x00000001,
++ CTC_to_b = 1,
++ CTC_to_m = 0x00000002,
++
++ RCOUNT_count_b = 0,
++ RCOUNT_count_m = 0x0000ffff,
++ RCOMPARE_compare_b = 0,
++ RCOMPARE_compare_m = 0x0000ffff,
++ RTC_ce_b = 0,
++ RTC_ce_m = 0x00000001,
++ RTC_to_b = 1,
++ RTC_to_m = 0x00000002,
++ RTC_rqe_b = 2,
++ RTC_rqe_m = 0x00000004,
++
++} ;
++#endif // __IDT_TIM_H__
++
+diff -urN linux.old/include/asm-mips/rc32434/types.h linux.dev/include/asm-mips/rc32434/types.h
+--- linux.old/include/asm-mips/rc32434/types.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/types.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,39 @@
++#ifndef __IDT_TYPES_H__
++#define __IDT_TYPES_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * Common typedefs used in IDT-generated code.
++ *
++ * File : $Id: types.h,v 1.1 2002/06/06 16:16:56 astichte Exp $
++ *
++ * Author : Allen.Stichter@idt.com
++ * Date : 20020606
++ * Update :
++ * $Log: types.h,v $
++ * Revision 1.1 2002/06/06 16:16:56 astichte
++ * Added
++ *
++ *
++ ******************************************************************************/
++
++typedef unsigned char U8 ;
++typedef signed char S8 ;
++
++typedef unsigned short U16 ;
++typedef signed short S16 ;
++
++typedef unsigned int U32 ;
++typedef signed int S32 ;
++
++typedef unsigned long long U64 ;
++typedef signed long long S64 ;
++
++#ifndef __cplusplus
++ typedef U32 bool ; // (false == 0), (true is != false)
++#endif // __cplusplus
++
++#endif // __IDT_TYPES_H__
+diff -urN linux.old/include/asm-mips/rc32434/uart.h linux.dev/include/asm-mips/rc32434/uart.h
+--- linux.old/include/asm-mips/rc32434/uart.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/rc32434/uart.h 2006-10-11 21:56:38.000000000 +0200
+@@ -0,0 +1,178 @@
++#ifndef __IDT_UART_H__
++#define __IDT_UART_H__
++
++/*******************************************************************************
++ *
++ * Copyright 2002 Integrated Device Technology, Inc.
++ * All rights reserved.
++ *
++ * UART register definitions.
++ *
++ * File : $Id: uart.h,v 1.3 2002/06/06 18:34:05 astichte Exp $
++ *
++ * Author : Allen.Stichter@idt.com
++ * Date : 20020118
++ * Update :
++ * $Log: uart.h,v $
++ * Revision 1.3 2002/06/06 18:34:05 astichte
++ * Added XXX_PhysicalAddress and XXX_VirtualAddress
++ *
++ * Revision 1.2 2002/06/04 17:37:52 astichte
++ * Updated register definitions.
++ *
++ * Revision 1.1 2002/05/29 17:33:25 sysarch
++ * jba File moved from vcode/include/idt/acacia
++ *
++ *
++ ******************************************************************************/
++
++#include <asm/rc32434/types.h>
++
++enum
++{
++ UART_PhysicalAddress = 0x18058000,
++ UART_PhysicalAddress = UART_PhysicalAddress, // Default
++
++ UART_VirtualAddress = 0xb8058000,
++ UART_VirtualAddress = UART_VirtualAddress, // Default
++} ;
++
++/*
++ * Register definitions are in bytes so we can handle endian problems.
++ */
++
++typedef struct UART_s
++{
++ union
++ {
++ U32 const uartrb ; // 0x00 - DLAB=0, read.
++ U32 uartth ; // 0x00 - DLAB=0, write.
++ U32 uartdll ; // 0x00 - DLAB=1, read/write.
++ } ;
++
++ union
++ {
++ U32 uartie ; // 0x04 - DLAB=0, read/write.
++ U32 uartdlh ; // 0x04 - DLAB=1, read/write.
++ } ;
++ union
++ {
++ U32 const uartii ; // 0x08 - DLAB=0, read.
++ U32 uartfc ; // 0x08 - DLAB=0, write.
++ } ;
++
++ U32 uartlc ; // 0x0c
++ U32 uartmc ; // 0x10
++ U32 uartls ; // 0x14
++ U32 uartms ; // 0x18
++ U32 uarts ; // 0x1c
++} volatile *UART_t ;
++
++// Reset registers.
++typedef U32 volatile *UARTRR_t ;
++
++enum
++{
++ UARTIE_rda_b = 0,
++ UARTIE_rda_m = 0x00000001,
++ UARTIE_the_b = 1,
++ UARTIE_the_m = 0x00000002,
++ UARTIE_rls_b = 2,
++ UARTIE_rls_m = 0x00000004,
++ UARTIE_ems_b = 3,
++ UARTIE_ems_m = 0x00000008,
++
++ UARTII_pi_b = 0,
++ UARTII_pi_m = 0x00000001,
++ UARTII_iid_b = 1,
++ UARTII_iid_m = 0x0000000e,
++ UARTII_iid_ms_v = 0, // Modem stat-CTS,DSR,RI or DCD.
++ UARTII_iid_thre_v = 1, // Trans. Holding Reg. empty.
++ UARTII_iid_rda_v = 2, // Receive data available
++ UARTII_iid_rls_v = 3, // Overrun, parity, etc, error.
++ UARTII_iid_res4_v = 4, // reserved.
++ UARTII_iid_res5_v = 5, // reserved.
++ UARTII_iid_cto_v = 6, // Character timeout.
++ UARTII_iid_res7_v = 7, // reserved.
++
++ UARTFC_en_b = 0,
++ UARTFC_en_m = 0x00000001,
++ UARTFC_rr_b = 1,
++ UARTFC_rr_m = 0x00000002,
++ UARTFC_tr_b = 2,
++ UARTFC_tr_m = 0x00000004,
++ UARTFC_dms_b = 3,
++ UARTFC_dms_m = 0x00000008,
++ UARTFC_rt_b = 6,
++ UARTFC_rt_m = 0x000000c0,
++ UARTFC_rt_1Byte_v = 0,
++ UARTFC_rt_4Byte_v = 1,
++ UARTFC_rt_8Byte_v = 2,
++ UARTFC_rt_14Byte_v = 3,
++
++ UARTLC_wls_b = 0,
++ UARTLC_wls_m = 0x00000003,
++ UARTLC_wls_5Bits_v = 0,
++ UARTLC_wls_6Bits_v = 1,
++ UARTLC_wls_7Bits_v = 2,
++ UARTLC_wls_8Bits_v = 3,
++ UARTLC_stb_b = 2,
++ UARTLC_stb_m = 0x00000004,
++ UARTLC_pen_b = 3,
++ UARTLC_pen_m = 0x00000008,
++ UARTLC_eps_b = 4,
++ UARTLC_eps_m = 0x00000010,
++ UARTLC_sp_b = 5,
++ UARTLC_sp_m = 0x00000020,
++ UARTLC_sb_b = 6,
++ UARTLC_sb_m = 0x00000040,
++ UARTLC_dlab_b = 7,
++ UARTLC_dlab_m = 0x00000080,
++
++ UARTMC_dtr_b = 0,
++ UARTMC_dtr_m = 0x00000001,
++ UARTMC_rts_b = 1,
++ UARTMC_rts_m = 0x00000002,
++ UARTMC_o1_b = 2,
++ UARTMC_o1_m = 0x00000004,
++ UARTMC_o2_b = 3,
++ UARTMC_o2_m = 0x00000008,
++ UARTMC_lp_b = 4,
++ UARTMC_lp_m = 0x00000010,
++
++ UARTLS_dr_b = 0,
++ UARTLS_dr_m = 0x00000001,
++ UARTLS_oe_b = 1,
++ UARTLS_oe_m = 0x00000002,
++ UARTLS_pe_b = 2,
++ UARTLS_pe_m = 0x00000004,
++ UARTLS_fe_b = 3,
++ UARTLS_fe_m = 0x00000008,
++ UARTLS_bi_b = 4,
++ UARTLS_bi_m = 0x00000010,
++ UARTLS_thr_b = 5,
++ UARTLS_thr_m = 0x00000020,
++ UARTLS_te_b = 6,
++ UARTLS_te_m = 0x00000040,
++ UARTLS_rfe_b = 7,
++ UARTLS_rfe_m = 0x00000080,
++
++ UARTMS_dcts_b = 0,
++ UARTMS_dcts_m = 0x00000001,
++ UARTMS_ddsr_b = 1,
++ UARTMS_ddsr_m = 0x00000002,
++ UARTMS_teri_b = 2,
++ UARTMS_teri_m = 0x00000004,
++ UARTMS_ddcd_b = 3,
++ UARTMS_ddcd_m = 0x00000008,
++ UARTMS_cts_b = 4,
++ UARTMS_cts_m = 0x00000010,
++ UARTMS_dsr_b = 5,
++ UARTMS_dsr_m = 0x00000020,
++ UARTMS_ri_b = 6,
++ UARTMS_ri_m = 0x00000040,
++ UARTMS_dcd_b = 7,
++ UARTMS_dcd_m = 0x00000080,
++} ;
++
++#endif // __IDT_UART_H__
diff --git a/target/linux/rb532-2.6/patches/110-korina_ethernet.patch b/target/linux/rb532-2.6/patches/110-korina_ethernet.patch
new file mode 100644
index 0000000000..723bc4ff10
--- /dev/null
+++ b/target/linux/rb532-2.6/patches/110-korina_ethernet.patch
@@ -0,0 +1,1375 @@
+diff -urN linux.old/drivers/net/Kconfig linux.dev/drivers/net/Kconfig
+--- linux.old/drivers/net/Kconfig 2006-06-08 20:21:20.000000000 +0200
++++ linux.dev/drivers/net/Kconfig 2006-06-08 20:19:40.000000000 +0200
+@@ -310,6 +310,13 @@
+
+ source "drivers/net/arm/Kconfig"
+
++config KORINA
++ tristate "Korina Local Ethernet support"
++ depends on NET_ETHERNET && ( IDT_EB434 || MIKROTIK_RB500)
++ help
++ IDT RC32434 has one local ethernet port. Say Y here to enable it.
++ To compile this driver as a module, choose M here.
++
+ config MACE
+ tristate "MACE (Power Mac ethernet) support"
+ depends on NET_ETHERNET && PPC_PMAC && PPC32
+diff -urN linux.old/drivers/net/korina.c linux.dev/drivers/net/korina.c
+--- linux.old/drivers/net/korina.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/korina.c 2006-06-09 00:48:40.000000000 +0200
+@@ -0,0 +1,1159 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Driver for the IDT RC32434 on-chip ethernet controller.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Based on the driver developed by B. Maruthanayakam, H. Kou and others.
++ *
++ * Aug 2004 Sadik
++ *
++ * Added NAPI
++ *
++ **************************************************************************
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/moduleparam.h>
++#include <linux/sched.h>
++#include <linux/ctype.h>
++#include <linux/types.h>
++#include <linux/fcntl.h>
++#include <linux/interrupt.h>
++#include <linux/ptrace.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/proc_fs.h>
++#include <linux/in.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++#include <linux/errno.h>
++#include <linux/platform_device.h>
++#include <asm/bootinfo.h>
++#include <asm/system.h>
++#include <asm/bitops.h>
++#include <asm/pgtable.h>
++#include <asm/segment.h>
++#include <asm/io.h>
++#include <asm/dma.h>
++
++#include <asm/rc32434/rb.h>
++#include "rc32434_eth.h"
++
++#define DRIVER_VERSION "(mar2904)"
++
++#define DRIVER_NAME "rc32434 Ethernet driver. " DRIVER_VERSION
++
++#define STATION_ADDRESS_HIGH(dev) (((dev)->dev_addr[0] << 8) | \
++ ((dev)->dev_addr[1]))
++#define STATION_ADDRESS_LOW(dev) (((dev)->dev_addr[2] << 24) | \
++ ((dev)->dev_addr[3] << 16) | \
++ ((dev)->dev_addr[4] << 8) | \
++ ((dev)->dev_addr[5]))
++
++#define MII_CLOCK 1250000 /* no more than 2.5MHz */
++#define CONFIG_IDT_USE_NAPI 1
++
++
++static inline void rc32434_abort_tx(struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ rc32434_abort_dma(dev, lp->tx_dma_regs);
++
++}
++
++static inline void rc32434_abort_rx(struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ rc32434_abort_dma(dev, lp->rx_dma_regs);
++
++}
++
++static inline void rc32434_start_tx(struct rc32434_local *lp, volatile DMAD_t td)
++{
++ rc32434_start_dma(lp->tx_dma_regs, CPHYSADDR(td));
++}
++
++static inline void rc32434_start_rx(struct rc32434_local *lp, volatile DMAD_t rd)
++{
++ rc32434_start_dma(lp->rx_dma_regs, CPHYSADDR(rd));
++}
++
++static inline void rc32434_chain_tx(struct rc32434_local *lp, volatile DMAD_t td)
++{
++ rc32434_chain_dma(lp->tx_dma_regs, CPHYSADDR(td));
++}
++
++static inline void rc32434_chain_rx(struct rc32434_local *lp, volatile DMAD_t rd)
++{
++ rc32434_chain_dma(lp->rx_dma_regs, CPHYSADDR(rd));
++}
++
++#ifdef RC32434_PROC_DEBUG
++static int rc32434_read_proc(char *buf, char **start, off_t fpos,
++ int length, int *eof, void *data)
++{
++ struct net_device *dev = (struct net_device *)data;
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ int len = 0;
++
++ /* print out header */
++ len += sprintf(buf + len, "\n\tKorina Ethernet Debug\n\n");
++ len += sprintf (buf + len,
++ "DMA halt count = %10d, DMA run count = %10d\n",
++ lp->dma_halt_cnt, lp->dma_run_cnt);
++
++ if (fpos >= len) {
++ *start = buf;
++ *eof = 1;
++ return 0;
++ }
++ *start = buf + fpos;
++
++ if ((len -= fpos) > length)
++ return length;
++ *eof = 1;
++
++ return len;
++
++}
++#endif
++
++
++/*
++ * Restart the RC32434 ethernet controller.
++ */
++static int rc32434_restart(struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++
++ /*
++ * Disable interrupts
++ */
++ disable_irq(lp->rx_irq);
++ disable_irq(lp->tx_irq);
++#ifdef RC32434_REVISION
++ disable_irq(lp->ovr_irq);
++#endif
++ disable_irq(lp->und_irq);
++
++ /* Mask F E bit in Tx DMA */
++ __raw_writel(__raw_readl(&lp->tx_dma_regs->dmasm) | DMASM_f_m | DMASM_e_m, &lp->tx_dma_regs->dmasm);
++ /* Mask D H E bit in Rx DMA */
++ __raw_writel(__raw_readl(&lp->rx_dma_regs->dmasm) | DMASM_d_m | DMASM_h_m | DMASM_e_m, &lp->rx_dma_regs->dmasm);
++
++ rc32434_init(dev);
++ rc32434_multicast_list(dev);
++
++ enable_irq(lp->und_irq);
++#ifdef RC32434_REVISION
++ enable_irq(lp->ovr_irq);
++#endif
++ enable_irq(lp->tx_irq);
++ enable_irq(lp->rx_irq);
++
++ return 0;
++}
++
++static int rc32434_probe(struct platform_device *pdev)
++{
++ struct korina_device *bif = (struct korina_device *) pdev->dev.platform_data;
++ struct rc32434_local *lp = NULL;
++ struct net_device *dev = NULL;
++ struct resource *r;
++ int i, retval,err;
++
++ dev = alloc_etherdev(sizeof(struct rc32434_local));
++ if(!dev) {
++ ERR("Korina_eth: alloc_etherdev failed\n");
++ return -1;
++ }
++
++ platform_set_drvdata(pdev, dev);
++ SET_MODULE_OWNER(dev);
++ bif->dev = dev;
++
++ memcpy(dev->dev_addr, bif->mac, 6);
++
++ /* Initialize the device structure. */
++ if (dev->priv == NULL) {
++ lp = (struct rc32434_local *)kmalloc(sizeof(*lp), GFP_KERNEL);
++ memset(lp, 0, sizeof(struct rc32434_local));
++ }
++ else {
++ lp = (struct rc32434_local *)dev->priv;
++ }
++
++ lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx");
++ lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx");
++ lp->ovr_irq = platform_get_irq_byname(pdev, "korina_ovr");
++ lp->und_irq = platform_get_irq_byname(pdev, "korina_und");
++
++ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_regs");
++ dev->base_addr = r->start;
++ lp->eth_regs = ioremap_nocache(r->start, r->end - r->start);
++ if (!lp->eth_regs) {
++ ERR("Can't remap eth registers\n");
++ retval = -ENXIO;
++ goto probe_err_out;
++ }
++
++ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_rx");
++ lp->rx_dma_regs = ioremap_nocache(r->start, r->end - r->start);
++ if (!lp->rx_dma_regs) {
++ ERR("Can't remap Rx DMA registers\n");
++ retval = -ENXIO;
++ goto probe_err_out;
++ }
++
++ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_tx");
++ lp->tx_dma_regs = ioremap_nocache(r->start, r->end - r->start);
++ if (!lp->tx_dma_regs) {
++ ERR("Can't remap Tx DMA registers\n");
++ retval = -ENXIO;
++ goto probe_err_out;
++ }
++
++#ifdef RC32434_PROC_DEBUG
++ lp->ps = create_proc_read_entry (bif->name, 0, proc_net,
++ rc32434_read_proc, dev);
++#endif
++
++ lp->td_ring = (DMAD_t)kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL);
++ if (!lp->td_ring) {
++ ERR("Can't allocate descriptors\n");
++ retval = -ENOMEM;
++ goto probe_err_out;
++ }
++
++ dma_cache_inv((unsigned long)(lp->td_ring), TD_RING_SIZE + RD_RING_SIZE);
++
++ /* now convert TD_RING pointer to KSEG1 */
++ lp->td_ring = (DMAD_t )KSEG1ADDR(lp->td_ring);
++ lp->rd_ring = &lp->td_ring[RC32434_NUM_TDS];
++
++
++ spin_lock_init(&lp->lock);
++
++ /* just use the rx dma irq */
++ dev->irq = lp->rx_irq;
++
++ dev->priv = lp;
++
++ dev->open = rc32434_open;
++ dev->stop = rc32434_close;
++ dev->hard_start_xmit = rc32434_send_packet;
++ dev->get_stats = rc32434_get_stats;
++ dev->set_multicast_list = &rc32434_multicast_list;
++ dev->tx_timeout = rc32434_tx_timeout;
++ dev->watchdog_timeo = RC32434_TX_TIMEOUT;
++
++#ifdef CONFIG_IDT_USE_NAPI
++ dev->poll = rc32434_poll;
++ dev->weight = 64;
++ printk("Using NAPI with weight %d\n",dev->weight);
++#else
++ lp->rx_tasklet = kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
++ tasklet_init(lp->rx_tasklet, rc32434_rx_tasklet, (unsigned long)dev);
++#endif
++ lp->tx_tasklet = kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
++ tasklet_init(lp->tx_tasklet, rc32434_tx_tasklet, (unsigned long)dev);
++
++ if ((err = register_netdev(dev))) {
++ printk(KERN_ERR "rc32434 ethernet. Cannot register net device %d\n", err);
++ free_netdev(dev);
++ retval = -EINVAL;
++ goto probe_err_out;
++ }
++
++ INFO("Rx IRQ %d, Tx IRQ %d, ", lp->rx_irq, lp->tx_irq);
++ for (i = 0; i < 6; i++) {
++ printk("%2.2x", dev->dev_addr[i]);
++ if (i<5)
++ printk(":");
++ }
++ printk("\n");
++
++ return 0;
++
++ probe_err_out:
++ rc32434_cleanup_module();
++ ERR(" failed. Returns %d\n", retval);
++ return retval;
++
++}
++
++static int rc32434_remove(struct platform_device *pdev)
++{
++ struct korina_device *bif = (struct korina_device *) pdev->dev.platform_data;
++
++ if (bif->dev != NULL) {
++ struct rc32434_local *lp = (struct rc32434_local *)bif->dev->priv;
++ if (lp != NULL) {
++ if (lp->eth_regs)
++ iounmap((void*)lp->eth_regs);
++ if (lp->rx_dma_regs)
++ iounmap((void*)lp->rx_dma_regs);
++ if (lp->tx_dma_regs)
++ iounmap((void*)lp->tx_dma_regs);
++ if (lp->td_ring)
++ kfree((void*)KSEG0ADDR(lp->td_ring));
++
++#ifdef RC32434_PROC_DEBUG
++ if (lp->ps) {
++ remove_proc_entry(bif->name, proc_net);
++ }
++#endif
++ kfree(lp);
++ }
++
++ platform_set_drvdata(pdev, NULL);
++ unregister_netdev(bif->dev);
++ free_netdev(bif->dev);
++ kfree(bif->dev);
++ }
++ return 0;
++}
++
++
++static int rc32434_open(struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++
++ /* Initialize */
++ if (rc32434_init(dev)) {
++ ERR("Error: cannot open the Ethernet device\n");
++ return -EAGAIN;
++ }
++
++ /* Install the interrupt handler that handles the Done Finished Ovr and Und Events */
++ if (request_irq(lp->rx_irq, &rc32434_rx_dma_interrupt,
++ SA_SHIRQ | SA_INTERRUPT,
++ "Korina ethernet Rx", dev)) {
++ ERR(": unable to get Rx DMA IRQ %d\n",
++ lp->rx_irq);
++ return -EAGAIN;
++ }
++ if (request_irq(lp->tx_irq, &rc32434_tx_dma_interrupt,
++ SA_SHIRQ | SA_INTERRUPT,
++ "Korina ethernet Tx", dev)) {
++ ERR(": unable to get Tx DMA IRQ %d\n",
++ lp->tx_irq);
++ free_irq(lp->rx_irq, dev);
++ return -EAGAIN;
++ }
++
++#ifdef RC32434_REVISION
++ /* Install handler for overrun error. */
++ if (request_irq(lp->ovr_irq, &rc32434_ovr_interrupt,
++ SA_SHIRQ | SA_INTERRUPT,
++ "Ethernet Overflow", dev)) {
++ ERR(": unable to get OVR IRQ %d\n",
++ lp->ovr_irq);
++ free_irq(lp->rx_irq, dev);
++ free_irq(lp->tx_irq, dev);
++ return -EAGAIN;
++ }
++#endif
++
++ /* Install handler for underflow error. */
++ if (request_irq(lp->und_irq, &rc32434_und_interrupt,
++ SA_SHIRQ | SA_INTERRUPT,
++ "Ethernet Underflow", dev)) {
++ ERR(": unable to get UND IRQ %d\n",
++ lp->und_irq);
++ free_irq(lp->rx_irq, dev);
++ free_irq(lp->tx_irq, dev);
++#ifdef RC32434_REVISION
++ free_irq(lp->ovr_irq, dev);
++#endif
++ return -EAGAIN;
++ }
++
++
++ return 0;
++}
++
++
++
++
++static int rc32434_close(struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ u32 tmp;
++
++ /* Disable interrupts */
++ disable_irq(lp->rx_irq);
++ disable_irq(lp->tx_irq);
++#ifdef RC32434_REVISION
++ disable_irq(lp->ovr_irq);
++#endif
++ disable_irq(lp->und_irq);
++
++ tmp = __raw_readl(&lp->tx_dma_regs->dmasm);
++ tmp = tmp | DMASM_f_m | DMASM_e_m;
++ __raw_writel(tmp, &lp->tx_dma_regs->dmasm);
++
++ tmp = __raw_readl(&lp->rx_dma_regs->dmasm);
++ tmp = tmp | DMASM_d_m | DMASM_h_m | DMASM_e_m;
++ __raw_writel(tmp, &lp->rx_dma_regs->dmasm);
++
++ free_irq(lp->rx_irq, dev);
++ free_irq(lp->tx_irq, dev);
++#ifdef RC32434_REVISION
++ free_irq(lp->ovr_irq, dev);
++#endif
++ free_irq(lp->und_irq, dev);
++ return 0;
++}
++
++
++/* transmit packet */
++static int rc32434_send_packet(struct sk_buff *skb, struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ unsigned long flags;
++ u32 length;
++ DMAD_t td;
++
++
++ spin_lock_irqsave(&lp->lock, flags);
++
++ td = &lp->td_ring[lp->tx_chain_tail];
++
++ /* stop queue when full, drop pkts if queue already full */
++ if(lp->tx_count >= (RC32434_NUM_TDS - 2)) {
++ lp->tx_full = 1;
++
++ if(lp->tx_count == (RC32434_NUM_TDS - 2)) {
++ netif_stop_queue(dev);
++ }
++ else {
++ lp->stats.tx_dropped++;
++ dev_kfree_skb_any(skb);
++ spin_unlock_irqrestore(&lp->lock, flags);
++ return 1;
++ }
++ }
++
++ lp->tx_count ++;
++
++ lp->tx_skb[lp->tx_chain_tail] = skb;
++
++ length = skb->len;
++
++ /* Setup the transmit descriptor. */
++ td->ca = CPHYSADDR(skb->data);
++
++ if(__raw_readl(&(lp->tx_dma_regs->dmandptr)) == 0) {
++ if( lp->tx_chain_status == empty ) {
++ td->control = DMA_COUNT(length) |DMAD_cof_m |DMAD_iof_m; /* Update tail */
++ lp->tx_chain_tail = (lp->tx_chain_tail + 1) & RC32434_TDS_MASK; /* Move tail */
++ __raw_writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]), &(lp->tx_dma_regs->dmandptr)); /* Write to NDPTR */
++ lp->tx_chain_head = lp->tx_chain_tail; /* Move head to tail */
++ }
++ else {
++ td->control = DMA_COUNT(length) |DMAD_cof_m|DMAD_iof_m; /* Update tail */
++ lp->td_ring[(lp->tx_chain_tail-1)& RC32434_TDS_MASK].control &= ~(DMAD_cof_m); /* Link to prev */
++ lp->td_ring[(lp->tx_chain_tail-1)& RC32434_TDS_MASK].link = CPHYSADDR(td); /* Link to prev */
++ lp->tx_chain_tail = (lp->tx_chain_tail + 1) & RC32434_TDS_MASK; /* Move tail */
++ __raw_writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]), &(lp->tx_dma_regs->dmandptr)); /* Write to NDPTR */
++ lp->tx_chain_head = lp->tx_chain_tail; /* Move head to tail */
++ lp->tx_chain_status = empty;
++ }
++ }
++ else {
++ if( lp->tx_chain_status == empty ) {
++ td->control = DMA_COUNT(length) |DMAD_cof_m |DMAD_iof_m; /* Update tail */
++ lp->tx_chain_tail = (lp->tx_chain_tail + 1) & RC32434_TDS_MASK; /* Move tail */
++ lp->tx_chain_status = filled;
++ }
++ else {
++ td->control = DMA_COUNT(length) |DMAD_cof_m |DMAD_iof_m; /* Update tail */
++ lp->td_ring[(lp->tx_chain_tail-1)& RC32434_TDS_MASK].control &= ~(DMAD_cof_m); /* Link to prev */
++ lp->td_ring[(lp->tx_chain_tail-1)& RC32434_TDS_MASK].link = CPHYSADDR(td); /* Link to prev */
++ lp->tx_chain_tail = (lp->tx_chain_tail + 1) & RC32434_TDS_MASK; /* Move tail */
++ }
++ }
++
++ dev->trans_start = jiffies;
++
++ spin_unlock_irqrestore(&lp->lock, flags);
++
++ return 0;
++}
++
++
++/* Ethernet MII-PHY Handler */
++static void rc32434_mii_handler(unsigned long data)
++{
++ struct net_device *dev = (struct net_device *)data;
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ unsigned long flags;
++ unsigned long duplex_status;
++ int port_addr = (lp->rx_irq == 0x2c? 1:0) << 8;
++
++ spin_lock_irqsave(&lp->lock, flags);
++
++ /* Two ports are using the same MII, the difference is the PHY address */
++ __raw_writel(0, &rc32434_eth0_regs->miimcfg);
++ __raw_writel(0, &rc32434_eth0_regs->miimcmd);
++ __raw_writel(port_addr |0x05, &rc32434_eth0_regs->miimaddr);
++ __raw_writel(MIIMCMD_scn_m, &rc32434_eth0_regs->miimcmd);
++ while(__raw_readl(&rc32434_eth0_regs->miimind) & MIIMIND_nv_m);
++
++ ERR("irq:%x port_addr:%x RDD:%x\n",
++ lp->rx_irq, port_addr, __raw_readl(&rc32434_eth0_regs->miimrdd));
++ duplex_status = (__raw_readl(&rc32434_eth0_regs->miimrdd) & 0x140)? ETHMAC2_fd_m: 0;
++ if(duplex_status != lp->duplex_mode) {
++ ERR("The MII-PHY is Auto-negotiated to %s-Duplex mode for Eth-%x\n", duplex_status? "Full":"Half", lp->rx_irq == 0x2c? 1:0);
++ lp->duplex_mode = duplex_status;
++ rc32434_restart(dev);
++ }
++
++ lp->mii_phy_timer.expires = jiffies + 10 * HZ;
++ add_timer(&lp->mii_phy_timer);
++
++ spin_unlock_irqrestore(&lp->lock, flags);
++
++}
++
++#ifdef RC32434_REVISION
++/* Ethernet Rx Overflow interrupt */
++static irqreturn_t
++rc32434_ovr_interrupt(int irq, void *dev_id, struct pt_regs * regs)
++{
++ struct net_device *dev = (struct net_device *)dev_id;
++ struct rc32434_local *lp;
++ unsigned int ovr;
++ irqreturn_t retval = IRQ_NONE;
++
++ ASSERT(dev != NULL);
++
++ lp = (struct rc32434_local *)dev->priv;
++ spin_lock(&lp->lock);
++ ovr = __raw_readl(&lp->eth_regs->ethintfc);
++
++ if(ovr & ETHINTFC_ovr_m) {
++ netif_stop_queue(dev);
++
++ /* clear OVR bit */
++ __raw_writel((ovr & ~ETHINTFC_ovr_m), &lp->eth_regs->ethintfc);
++
++ /* Restart interface */
++ rc32434_restart(dev);
++ retval = IRQ_HANDLED;
++ }
++ spin_unlock(&lp->lock);
++
++ return retval;
++}
++
++#endif
++
++
++/* Ethernet Tx Underflow interrupt */
++static irqreturn_t
++rc32434_und_interrupt(int irq, void *dev_id, struct pt_regs * regs)
++{
++ struct net_device *dev = (struct net_device *)dev_id;
++ struct rc32434_local *lp;
++ unsigned int und;
++ irqreturn_t retval = IRQ_NONE;
++
++ ASSERT(dev != NULL);
++
++ lp = (struct rc32434_local *)dev->priv;
++
++ spin_lock(&lp->lock);
++
++ und = __raw_readl(&lp->eth_regs->ethintfc);
++
++ if(und & ETHINTFC_und_m) {
++ netif_stop_queue(dev);
++
++ __raw_writel((und & ~ETHINTFC_und_m), &lp->eth_regs->ethintfc);
++
++ /* Restart interface */
++ rc32434_restart(dev);
++ retval = IRQ_HANDLED;
++ }
++
++ spin_unlock(&lp->lock);
++
++ return retval;
++}
++
++
++/* Ethernet Rx DMA interrupt */
++static irqreturn_t
++rc32434_rx_dma_interrupt(int irq, void *dev_id, struct pt_regs * regs)
++{
++ struct net_device *dev = (struct net_device *)dev_id;
++ struct rc32434_local* lp;
++ volatile u32 dmas,dmasm;
++ irqreturn_t retval;
++
++ ASSERT(dev != NULL);
++
++ lp = (struct rc32434_local *)dev->priv;
++
++ spin_lock(&lp->lock);
++ dmas = __raw_readl(&lp->rx_dma_regs->dmas);
++ if(dmas & (DMAS_d_m|DMAS_h_m|DMAS_e_m)) {
++ /* Mask D H E bit in Rx DMA */
++ dmasm = __raw_readl(&lp->rx_dma_regs->dmasm);
++ __raw_writel(dmasm | (DMASM_d_m | DMASM_h_m | DMASM_e_m), &lp->rx_dma_regs->dmasm);
++#ifdef CONFIG_IDT_USE_NAPI
++ if(netif_rx_schedule_prep(dev))
++ __netif_rx_schedule(dev);
++#else
++ tasklet_hi_schedule(lp->rx_tasklet);
++#endif
++
++ if (dmas & DMAS_e_m)
++ ERR(": DMA error\n");
++
++ retval = IRQ_HANDLED;
++ }
++ else
++ retval = IRQ_NONE;
++
++ spin_unlock(&lp->lock);
++ return retval;
++}
++
++#ifdef CONFIG_IDT_USE_NAPI
++static int rc32434_poll(struct net_device *rx_data_dev, int *budget)
++#else
++static void rc32434_rx_tasklet(unsigned long rx_data_dev)
++#endif
++{
++ struct net_device *dev = (struct net_device *)rx_data_dev;
++ struct rc32434_local* lp = netdev_priv(dev);
++ volatile DMAD_t rd = &lp->rd_ring[lp->rx_next_done];
++ struct sk_buff *skb, *skb_new;
++ u8* pkt_buf;
++ u32 devcs, count, pkt_len, pktuncrc_len;
++ volatile u32 dmas;
++#ifdef CONFIG_IDT_USE_NAPI
++ u32 received = 0;
++ int rx_work_limit = min(*budget,dev->quota);
++#else
++ unsigned long flags;
++ spin_lock_irqsave(&lp->lock, flags);
++#endif
++
++ while ( (count = RC32434_RBSIZE - (u32)DMA_COUNT(rd->control)) != 0) {
++#ifdef CONFIG_IDT_USE_NAPI
++ if(--rx_work_limit <0)
++ {
++ break;
++ }
++#endif
++ /* init the var. used for the later operations within the while loop */
++ skb_new = NULL;
++ devcs = rd->devcs;
++ pkt_len = RCVPKT_LENGTH(devcs);
++ skb = lp->rx_skb[lp->rx_next_done];
++
++ if (count < 64) {
++ lp->stats.rx_errors++;
++ lp->stats.rx_dropped++;
++ }
++ else if ((devcs & ( ETHRX_ld_m)) != ETHRX_ld_m) {
++ /* check that this is a whole packet */
++ /* WARNING: DMA_FD bit incorrectly set in Rc32434 (errata ref #077) */
++ lp->stats.rx_errors++;
++ lp->stats.rx_dropped++;
++ }
++ else if ( (devcs & ETHRX_rok_m) ) {
++
++ {
++ /* must be the (first and) last descriptor then */
++ pkt_buf = (u8*)lp->rx_skb[lp->rx_next_done]->data;
++
++ pktuncrc_len = pkt_len - 4;
++ /* invalidate the cache */
++ dma_cache_inv((unsigned long)pkt_buf, pktuncrc_len);
++
++ /* Malloc up new buffer. */
++ skb_new = dev_alloc_skb(RC32434_RBSIZE + 2);
++
++ if (skb_new != NULL){
++ /* Make room */
++ skb_put(skb, pktuncrc_len);
++
++ skb->protocol = eth_type_trans(skb, dev);
++
++ /* pass the packet to upper layers */
++#ifdef CONFIG_IDT_USE_NAPI
++ netif_receive_skb(skb);
++#else
++ netif_rx(skb);
++#endif
++
++ dev->last_rx = jiffies;
++ lp->stats.rx_packets++;
++ lp->stats.rx_bytes += pktuncrc_len;
++
++ if (IS_RCV_MP(devcs))
++ lp->stats.multicast++;
++
++ /* 16 bit align */
++ skb_reserve(skb_new, 2);
++
++ skb_new->dev = dev;
++ lp->rx_skb[lp->rx_next_done] = skb_new;
++ }
++ else {
++ ERR("no memory, dropping rx packet.\n");
++ lp->stats.rx_errors++;
++ lp->stats.rx_dropped++;
++ }
++ }
++
++ }
++ else {
++ /* This should only happen if we enable accepting broken packets */
++ lp->stats.rx_errors++;
++ lp->stats.rx_dropped++;
++
++ /* add statistics counters */
++ if (IS_RCV_CRC_ERR(devcs)) {
++ DBG(2, "RX CRC error\n");
++ lp->stats.rx_crc_errors++;
++ }
++ else if (IS_RCV_LOR_ERR(devcs)) {
++ DBG(2, "RX LOR error\n");
++ lp->stats.rx_length_errors++;
++ }
++ else if (IS_RCV_LE_ERR(devcs)) {
++ DBG(2, "RX LE error\n");
++ lp->stats.rx_length_errors++;
++ }
++ else if (IS_RCV_OVR_ERR(devcs)) {
++ lp->stats.rx_over_errors++;
++ }
++ else if (IS_RCV_CV_ERR(devcs)) {
++ /* code violation */
++ DBG(2, "RX CV error\n");
++ lp->stats.rx_frame_errors++;
++ }
++ else if (IS_RCV_CES_ERR(devcs)) {
++ DBG(2, "RX Preamble error\n");
++ }
++ }
++
++ rd->devcs = 0;
++
++ /* restore descriptor's curr_addr */
++ if(skb_new)
++ rd->ca = CPHYSADDR(skb_new->data);
++ else
++ rd->ca = CPHYSADDR(skb->data);
++
++ rd->control = DMA_COUNT(RC32434_RBSIZE) |DMAD_cod_m |DMAD_iod_m;
++ lp->rd_ring[(lp->rx_next_done-1)& RC32434_RDS_MASK].control &= ~(DMAD_cod_m);
++
++ lp->rx_next_done = (lp->rx_next_done + 1) & RC32434_RDS_MASK;
++ rd = &lp->rd_ring[lp->rx_next_done];
++ __raw_writel( ~DMAS_d_m, &lp->rx_dma_regs->dmas);
++ }
++#ifdef CONFIG_IDT_USE_NAPI
++ dev->quota -= received;
++ *budget =- received;
++ if(rx_work_limit < 0)
++ goto not_done;
++#endif
++
++ dmas = __raw_readl(&lp->rx_dma_regs->dmas);
++
++ if(dmas & DMAS_h_m) {
++ __raw_writel( ~(DMAS_h_m | DMAS_e_m), &lp->rx_dma_regs->dmas);
++#ifdef RC32434_PROC_DEBUG
++ lp->dma_halt_cnt++;
++#endif
++ rd->devcs = 0;
++ skb = lp->rx_skb[lp->rx_next_done];
++ rd->ca = CPHYSADDR(skb->data);
++ rc32434_chain_rx(lp,rd);
++ }
++
++#ifdef CONFIG_IDT_USE_NAPI
++ netif_rx_complete(dev);
++#endif
++ /* Enable D H E bit in Rx DMA */
++ __raw_writel(__raw_readl(&lp->rx_dma_regs->dmasm) & ~(DMASM_d_m | DMASM_h_m |DMASM_e_m), &lp->rx_dma_regs->dmasm);
++#ifdef CONFIG_IDT_USE_NAPI
++ return 0;
++ not_done:
++ return 1;
++#else
++ spin_unlock_irqrestore(&lp->lock, flags);
++ return;
++#endif
++
++
++}
++
++
++
++/* Ethernet Tx DMA interrupt */
++static irqreturn_t
++rc32434_tx_dma_interrupt(int irq, void *dev_id, struct pt_regs * regs)
++{
++ struct net_device *dev = (struct net_device *)dev_id;
++ struct rc32434_local *lp;
++ volatile u32 dmas,dmasm;
++ irqreturn_t retval;
++
++ ASSERT(dev != NULL);
++
++ lp = (struct rc32434_local *)dev->priv;
++
++ spin_lock(&lp->lock);
++
++ dmas = __raw_readl(&lp->tx_dma_regs->dmas);
++
++ if (dmas & (DMAS_f_m | DMAS_e_m)) {
++ dmasm = __raw_readl(&lp->tx_dma_regs->dmasm);
++ /* Mask F E bit in Tx DMA */
++ __raw_writel(dmasm | (DMASM_f_m | DMASM_e_m), &lp->tx_dma_regs->dmasm);
++
++ tasklet_hi_schedule(lp->tx_tasklet);
++
++ if(lp->tx_chain_status == filled && (__raw_readl(&(lp->tx_dma_regs->dmandptr)) == 0)) {
++ __raw_writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]), &(lp->tx_dma_regs->dmandptr));
++ lp->tx_chain_status = empty;
++ lp->tx_chain_head = lp->tx_chain_tail;
++ dev->trans_start = jiffies;
++ }
++
++ if (dmas & DMAS_e_m)
++ ERR(": DMA error\n");
++
++ retval = IRQ_HANDLED;
++ }
++ else
++ retval = IRQ_NONE;
++
++ spin_unlock(&lp->lock);
++
++ return retval;
++}
++
++
++static void rc32434_tx_tasklet(unsigned long tx_data_dev)
++{
++ struct net_device *dev = (struct net_device *)tx_data_dev;
++ struct rc32434_local* lp = (struct rc32434_local *)dev->priv;
++ volatile DMAD_t td = &lp->td_ring[lp->tx_next_done];
++ u32 devcs;
++ unsigned long flags;
++ volatile u32 dmas;
++
++ spin_lock_irqsave(&lp->lock, flags);
++
++ /* process all desc that are done */
++ while(IS_DMA_FINISHED(td->control)) {
++ if(lp->tx_full == 1) {
++ netif_wake_queue(dev);
++ lp->tx_full = 0;
++ }
++
++ devcs = lp->td_ring[lp->tx_next_done].devcs;
++ if ((devcs & (ETHTX_fd_m | ETHTX_ld_m)) != (ETHTX_fd_m | ETHTX_ld_m)) {
++ lp->stats.tx_errors++;
++ lp->stats.tx_dropped++;
++
++ /* should never happen */
++ DBG(1, __FUNCTION__ ": split tx ignored\n");
++ }
++ else if (IS_TX_TOK(devcs)) {
++ lp->stats.tx_packets++;
++ }
++ else {
++ lp->stats.tx_errors++;
++ lp->stats.tx_dropped++;
++
++ /* underflow */
++ if (IS_TX_UND_ERR(devcs))
++ lp->stats.tx_fifo_errors++;
++
++ /* oversized frame */
++ if (IS_TX_OF_ERR(devcs))
++ lp->stats.tx_aborted_errors++;
++
++ /* excessive deferrals */
++ if (IS_TX_ED_ERR(devcs))
++ lp->stats.tx_carrier_errors++;
++
++ /* collisions: medium busy */
++ if (IS_TX_EC_ERR(devcs))
++ lp->stats.collisions++;
++
++ /* late collision */
++ if (IS_TX_LC_ERR(devcs))
++ lp->stats.tx_window_errors++;
++
++ }
++
++ /* We must always free the original skb */
++ if (lp->tx_skb[lp->tx_next_done] != NULL) {
++ dev_kfree_skb_any(lp->tx_skb[lp->tx_next_done]);
++ lp->tx_skb[lp->tx_next_done] = NULL;
++ }
++
++ lp->td_ring[lp->tx_next_done].control = DMAD_iof_m;
++ lp->td_ring[lp->tx_next_done].devcs = ETHTX_fd_m | ETHTX_ld_m;
++ lp->td_ring[lp->tx_next_done].link = 0;
++ lp->td_ring[lp->tx_next_done].ca = 0;
++ lp->tx_count --;
++
++ /* go on to next transmission */
++ lp->tx_next_done = (lp->tx_next_done + 1) & RC32434_TDS_MASK;
++ td = &lp->td_ring[lp->tx_next_done];
++
++ }
++
++ dmas = __raw_readl(&lp->tx_dma_regs->dmas);
++ __raw_writel( ~dmas, &lp->tx_dma_regs->dmas);
++
++ /* Enable F E bit in Tx DMA */
++ __raw_writel(__raw_readl(&lp->tx_dma_regs->dmasm) & ~(DMASM_f_m | DMASM_e_m), &lp->tx_dma_regs->dmasm);
++ spin_unlock_irqrestore(&lp->lock, flags);
++
++}
++
++
++static struct net_device_stats * rc32434_get_stats(struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ return &lp->stats;
++}
++
++
++/*
++ * Set or clear the multicast filter for this adaptor.
++ */
++static void rc32434_multicast_list(struct net_device *dev)
++{
++ /* listen to broadcasts always and to treat */
++ /* IFF bits independantly */
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ unsigned long flags;
++ u32 recognise = ETHARC_ab_m; /* always accept broadcasts */
++
++ if (dev->flags & IFF_PROMISC) /* set promiscuous mode */
++ recognise |= ETHARC_pro_m;
++
++ if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 15))
++ recognise |= ETHARC_am_m; /* all multicast & bcast */
++ else if (dev->mc_count > 0) {
++ DBG(2, __FUNCTION__ ": mc_count %d\n", dev->mc_count);
++ recognise |= ETHARC_am_m; /* for the time being */
++ }
++
++ spin_lock_irqsave(&lp->lock, flags);
++ __raw_writel(recognise, &lp->eth_regs->etharc);
++ spin_unlock_irqrestore(&lp->lock, flags);
++}
++
++
++static void rc32434_tx_timeout(struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ unsigned long flags;
++
++ spin_lock_irqsave(&lp->lock, flags);
++ rc32434_restart(dev);
++ spin_unlock_irqrestore(&lp->lock, flags);
++
++}
++
++
++/*
++ * Initialize the RC32434 ethernet controller.
++ */
++static int rc32434_init(struct net_device *dev)
++{
++ struct rc32434_local *lp = (struct rc32434_local *)dev->priv;
++ int i, j;
++
++ /* Disable DMA */
++ rc32434_abort_tx(dev);
++ rc32434_abort_rx(dev);
++
++ /* reset ethernet logic */
++ __raw_writel(0, &lp->eth_regs->ethintfc);
++ while((__raw_readl(&lp->eth_regs->ethintfc) & ETHINTFC_rip_m))
++ dev->trans_start = jiffies;
++
++ /* Enable Ethernet Interface */
++ __raw_writel(ETHINTFC_en_m, &lp->eth_regs->ethintfc);
++
++#ifndef CONFIG_IDT_USE_NAPI
++ tasklet_disable(lp->rx_tasklet);
++#endif
++ tasklet_disable(lp->tx_tasklet);
++
++ /* Initialize the transmit Descriptors */
++ for (i = 0; i < RC32434_NUM_TDS; i++) {
++ lp->td_ring[i].control = DMAD_iof_m;
++ lp->td_ring[i].devcs = ETHTX_fd_m | ETHTX_ld_m;
++ lp->td_ring[i].ca = 0;
++ lp->td_ring[i].link = 0;
++ if (lp->tx_skb[i] != NULL) {
++ dev_kfree_skb_any(lp->tx_skb[i]);
++ lp->tx_skb[i] = NULL;
++ }
++ }
++ lp->tx_next_done = lp->tx_chain_head = lp->tx_chain_tail = lp->tx_full = lp->tx_count = 0;
++ lp-> tx_chain_status = empty;
++
++ /*
++ * Initialize the receive descriptors so that they
++ * become a circular linked list, ie. let the last
++ * descriptor point to the first again.
++ */
++ for (i=0; i<RC32434_NUM_RDS; i++) {
++ struct sk_buff *skb = lp->rx_skb[i];
++
++ if (lp->rx_skb[i] == NULL) {
++ skb = dev_alloc_skb(RC32434_RBSIZE + 2);
++ if (skb == NULL) {
++ ERR("No memory in the system\n");
++ for (j = 0; j < RC32434_NUM_RDS; j ++)
++ if (lp->rx_skb[j] != NULL)
++ dev_kfree_skb_any(lp->rx_skb[j]);
++
++ return 1;
++ }
++ else {
++ skb->dev = dev;
++ skb_reserve(skb, 2);
++ lp->rx_skb[i] = skb;
++ lp->rd_ring[i].ca = CPHYSADDR(skb->data);
++
++ }
++ }
++ lp->rd_ring[i].control = DMAD_iod_m | DMA_COUNT(RC32434_RBSIZE);
++ lp->rd_ring[i].devcs = 0;
++ lp->rd_ring[i].ca = CPHYSADDR(skb->data);
++ lp->rd_ring[i].link = CPHYSADDR(&lp->rd_ring[i+1]);
++
++ }
++ /* loop back */
++ lp->rd_ring[RC32434_NUM_RDS-1].link = CPHYSADDR(&lp->rd_ring[0]);
++ lp->rx_next_done = 0;
++
++ lp->rd_ring[RC32434_NUM_RDS-1].control |= DMAD_cod_m;
++ lp->rx_chain_head = 0;
++ lp->rx_chain_tail = 0;
++ lp->rx_chain_status = empty;
++
++ __raw_writel(0, &lp->rx_dma_regs->dmas);
++ /* Start Rx DMA */
++ rc32434_start_rx(lp, &lp->rd_ring[0]);
++
++ /* Enable F E bit in Tx DMA */
++ __raw_writel(__raw_readl(&lp->tx_dma_regs->dmasm) & ~(DMASM_f_m | DMASM_e_m), &lp->tx_dma_regs->dmasm);
++ /* Enable D H E bit in Rx DMA */
++ __raw_writel(__raw_readl(&lp->rx_dma_regs->dmasm) & ~(DMASM_d_m | DMASM_h_m | DMASM_e_m), &lp->rx_dma_regs->dmasm);
++
++ /* Accept only packets destined for this Ethernet device address */
++ __raw_writel(ETHARC_ab_m, &lp->eth_regs->etharc);
++
++ /* Set all Ether station address registers to their initial values */
++ __raw_writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal0);
++ __raw_writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah0);
++
++ __raw_writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal1);
++ __raw_writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah1);
++
++ __raw_writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal2);
++ __raw_writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah2);
++
++ __raw_writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal3);
++ __raw_writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah3);
++
++
++ /* Frame Length Checking, Pad Enable, CRC Enable, Full Duplex set */
++ __raw_writel(ETHMAC2_pe_m | ETHMAC2_cen_m | ETHMAC2_fd_m, &lp->eth_regs->ethmac2);
++ //ETHMAC2_flc_m ETHMAC2_fd_m lp->duplex_mode
++
++ /* Back to back inter-packet-gap */
++ __raw_writel(0x15, &lp->eth_regs->ethipgt);
++ /* Non - Back to back inter-packet-gap */
++ __raw_writel(0x12, &lp->eth_regs->ethipgr);
++
++ /* Management Clock Prescaler Divisor */
++ /* Clock independent setting */
++ __raw_writel(((idt_cpu_freq)/MII_CLOCK+1) & ~1,
++ &lp->eth_regs->ethmcp);
++
++ /* don't transmit until fifo contains 48b */
++ __raw_writel(48, &lp->eth_regs->ethfifott);
++
++ __raw_writel(ETHMAC1_re_m, &lp->eth_regs->ethmac1);
++
++#ifndef CONFIG_IDT_USE_NAPI
++ tasklet_enable(lp->rx_tasklet);
++#endif
++ tasklet_enable(lp->tx_tasklet);
++
++ netif_start_queue(dev);
++
++ return 0;
++}
++
++static struct platform_driver korina_driver = {
++ .driver.name = "korina",
++ .probe = rc32434_probe,
++ .remove = rc32434_remove,
++};
++
++static int __init rc32434_init_module(void)
++{
++ return platform_driver_register(&korina_driver);
++}
++
++static void rc32434_cleanup_module(void)
++{
++ return platform_driver_unregister(&korina_driver);
++}
++
++module_init(rc32434_init_module);
++module_exit(rc32434_cleanup_module);
+diff -urN linux.old/drivers/net/Makefile linux.dev/drivers/net/Makefile
+--- linux.old/drivers/net/Makefile 2006-06-08 20:21:20.000000000 +0200
++++ linux.dev/drivers/net/Makefile 2006-06-08 20:19:40.000000000 +0200
+@@ -23,6 +23,8 @@
+ #
+ obj-$(CONFIG_PLIP) += plip.o
+
++obj-$(CONFIG_KORINA) += korina.o
++
+ obj-$(CONFIG_ROADRUNNER) += rrunner.o
+
+ obj-$(CONFIG_HAPPYMEAL) += sunhme.o
+diff -urN linux.old/drivers/net/rc32434_eth.h linux.dev/drivers/net/rc32434_eth.h
+--- linux.old/drivers/net/rc32434_eth.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/rc32434_eth.h 2006-06-08 21:57:12.000000000 +0200
+@@ -0,0 +1,178 @@
++/**************************************************************************
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Definitions for IDT RC32434 on-chip ethernet controller.
++ *
++ * Copyright 2004 IDT Inc. (rischelp@idt.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 SOFTWARE IS PROVIDED ``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.
++ *
++ * 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.
++ *
++ *
++ **************************************************************************
++ * May 2004 rkt, neb
++ *
++ * Initial Release
++ *
++ * Aug 2004
++ *
++ * Added NAPI
++ *
++ **************************************************************************
++ */
++
++
++#include <asm/rc32434/rc32434.h>
++#include <asm/rc32434/dma_v.h>
++#include <asm/rc32434/eth_v.h>
++
++#define CONFIG_IDT_USE_NAPI 1
++#define RC32434_DEBUG 2
++//#define RC32434_PROC_DEBUG
++#undef RC32434_DEBUG
++
++#ifdef RC32434_DEBUG
++
++/* use 0 for production, 1 for verification, >2 for debug */
++static int rc32434_debug = RC32434_DEBUG;
++#define ASSERT(expr) \
++ if(!(expr)) { \
++ printk( "Assertion failed! %s,%s,%s,line=%d\n", \
++ #expr,__FILE__,__FUNCTION__,__LINE__); }
++#define DBG(lvl, format, arg...) if (rc32434_debug > lvl) printk(KERN_INFO "%s: " format, dev->name , ## arg)
++#else
++#define ASSERT(expr) do {} while (0)
++#define DBG(lvl, format, arg...) do {} while (0)
++#endif
++
++#define INFO(format, arg...) printk(KERN_INFO "%s: " format, dev->name , ## arg)
++#define ERR(format, arg...) printk(KERN_ERR "%s: " format, dev->name , ## arg)
++#define WARN(format, arg...) printk(KERN_WARNING "%s: " format, dev->name , ## arg)
++
++/* the following must be powers of two */
++#ifdef CONFIG_IDT_USE_NAPI
++#define RC32434_NUM_RDS 64 /* number of receive descriptors */
++#define RC32434_NUM_TDS 64 /* number of transmit descriptors */
++#else
++#define RC32434_NUM_RDS 128 /* number of receive descriptors */
++#define RC32434_NUM_TDS 128 /* number of transmit descriptors */
++#endif
++
++#define RC32434_RBSIZE 1536 /* size of one resource buffer = Ether MTU */
++#define RC32434_RDS_MASK (RC32434_NUM_RDS-1)
++#define RC32434_TDS_MASK (RC32434_NUM_TDS-1)
++#define RD_RING_SIZE (RC32434_NUM_RDS * sizeof(struct DMAD_s))
++#define TD_RING_SIZE (RC32434_NUM_TDS * sizeof(struct DMAD_s))
++
++#define RC32434_TX_TIMEOUT HZ * 100
++
++#define rc32434_eth0_regs ((ETH_t)(ETH0_VirtualAddress))
++#define rc32434_eth1_regs ((ETH_t)(ETH1_VirtualAddress))
++
++enum status { filled, empty};
++#define IS_DMA_FINISHED(X) (((X) & (DMAD_f_m)) != 0)
++#define IS_DMA_DONE(X) (((X) & (DMAD_d_m)) != 0)
++
++
++/* Information that need to be kept for each board. */
++struct rc32434_local {
++ ETH_t eth_regs;
++ DMA_Chan_t rx_dma_regs;
++ DMA_Chan_t tx_dma_regs;
++ volatile DMAD_t td_ring; /* transmit descriptor ring */
++ volatile DMAD_t rd_ring; /* receive descriptor ring */
++
++ struct sk_buff* tx_skb[RC32434_NUM_TDS]; /* skbuffs for pkt to trans */
++ struct sk_buff* rx_skb[RC32434_NUM_RDS]; /* skbuffs for pkt to trans */
++
++#ifndef CONFIG_IDT_USE_NAPI
++ struct tasklet_struct * rx_tasklet;
++#endif
++ struct tasklet_struct * tx_tasklet;
++
++ int rx_next_done;
++ int rx_chain_head;
++ int rx_chain_tail;
++ enum status rx_chain_status;
++
++ int tx_next_done;
++ int tx_chain_head;
++ int tx_chain_tail;
++ enum status tx_chain_status;
++ int tx_count;
++ int tx_full;
++
++ struct timer_list mii_phy_timer;
++ unsigned long duplex_mode;
++
++ int rx_irq;
++ int tx_irq;
++ int ovr_irq;
++ int und_irq;
++
++ struct net_device_stats stats;
++ spinlock_t lock;
++
++ /* debug /proc entry */
++ struct proc_dir_entry *ps;
++ int dma_halt_cnt; int dma_run_cnt;
++};
++
++extern unsigned int idt_cpu_freq;
++
++/* Index to functions, as function prototypes. */
++static int rc32434_open(struct net_device *dev);
++static int rc32434_send_packet(struct sk_buff *skb, struct net_device *dev);
++static void rc32434_mii_handler(unsigned long data);
++static irqreturn_t rc32434_und_interrupt(int irq, void *dev_id, struct pt_regs * regs);
++static irqreturn_t rc32434_rx_dma_interrupt(int irq, void *dev_id, struct pt_regs * regs);
++static irqreturn_t rc32434_tx_dma_interrupt(int irq, void *dev_id, struct pt_regs * regs);
++#ifdef RC32434_REVISION
++static irqreturn_t rc32434_ovr_interrupt(int irq, void *dev_id, struct pt_regs * regs);
++#endif
++static int rc32434_close(struct net_device *dev);
++static struct net_device_stats *rc32434_get_stats(struct net_device *dev);
++static void rc32434_multicast_list(struct net_device *dev);
++static int rc32434_init(struct net_device *dev);
++static void rc32434_tx_timeout(struct net_device *dev);
++
++static void rc32434_tx_tasklet(unsigned long tx_data_dev);
++#ifdef CONFIG_IDT_USE_NAPI
++static int rc32434_poll(struct net_device *rx_data_dev, int *budget);
++#else
++static void rc32434_rx_tasklet(unsigned long rx_data_dev);
++#endif
++static void rc32434_cleanup_module(void);
++
++
++static inline void rc32434_abort_dma(struct net_device *dev, DMA_Chan_t ch)
++{
++ if (__raw_readl(&ch->dmac) & DMAC_run_m) {
++ __raw_writel(0x10, &ch->dmac);
++
++ while (!(__raw_readl(&ch->dmas) & DMAS_h_m))
++ dev->trans_start = jiffies;
++
++ __raw_writel(0, &ch->dmas);
++ }
++
++ __raw_writel(0, &ch->dmadptr);
++ __raw_writel(0, &ch->dmandptr);
++}
+
diff --git a/target/linux/rb532-2.6/patches/120-cf.patch b/target/linux/rb532-2.6/patches/120-cf.patch
new file mode 100644
index 0000000000..657d8157d0
--- /dev/null
+++ b/target/linux/rb532-2.6/patches/120-cf.patch
@@ -0,0 +1,990 @@
+diff -urN linux.old/drivers/block/Kconfig linux.dev/drivers/block/Kconfig
+--- linux.old/drivers/block/Kconfig 2006-06-08 20:20:52.000000000 +0200
++++ linux.dev/drivers/block/Kconfig 2006-06-08 22:14:58.000000000 +0200
+@@ -453,4 +453,12 @@
+ This driver provides Support for ATA over Ethernet block
+ devices like the Coraid EtherDrive (R) Storage Blade.
+
++config BLK_DEV_CF_MIPS
++ bool "CF slot of RB532 board"
++ depends on MIKROTIK_RB500
++ default y
++ help
++ The Routerboard 532 has a CF slot on it. Enable the special block
++ device driver for it.
++
+ endmenu
+diff -urN linux.old/drivers/block/rb500/ata.c linux.dev/drivers/block/rb500/ata.c
+--- linux.old/drivers/block/rb500/ata.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/block/rb500/ata.c 2006-06-09 01:58:40.000000000 +0200
+@@ -0,0 +1,474 @@
++#include <linux/kernel.h> /* printk() */
++#include <linux/module.h> /* module to be loadable */
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <linux/pci.h>
++#include <linux/ioport.h> /* request_mem_region() */
++#include <asm/unaligned.h> /* ioremap() */
++#include <asm/io.h> /* ioremap() */
++#include <asm/rc32434/rb.h>
++
++#include "ata.h"
++
++#define REQUEST_MEM_REGION 0
++#define DEBUG 1
++
++#if DEBUG
++#define DEBUGP printk
++#else
++#define DEBUGP(format, args...)
++#endif
++
++#define SECS 1000000 /* unit for wait_not_busy() is 1us */
++
++unsigned cf_head = 0;
++unsigned cf_cyl = 0;
++unsigned cf_spt = 0;
++unsigned cf_sectors = 0;
++static unsigned cf_block_size = 1;
++static void *baddr = 0;
++
++#define DBUF32 ((volatile u32 *)((unsigned long)dev->baddr | ATA_DBUF_OFFSET))
++
++
++static void cf_do_tasklet(unsigned long dev_l);
++
++
++static inline void wareg(u8 val, unsigned reg, struct cf_mips_dev* dev)
++{
++ writeb(val, dev->baddr + ATA_REG_OFFSET + reg);
++}
++
++static inline u8 rareg(unsigned reg, struct cf_mips_dev* dev)
++{
++ return readb(dev->baddr + ATA_REG_OFFSET + reg);
++}
++
++static inline int get_gpio_bit(gpio_func ofs, struct cf_mips_dev *dev)
++{
++ return (gpio_get(ofs) >> dev->pin) & 1;
++}
++
++static inline void set_gpio_bit(int bit, gpio_func ofs, struct cf_mips_dev *dev)
++{
++ gpio_set(ofs, (1 << dev->pin), ((bit & 1) << dev->pin));
++}
++
++static inline int cfrdy(struct cf_mips_dev *dev)
++{
++ return get_gpio_bit(DATA, dev);
++}
++
++static inline void prepare_cf_irq(struct cf_mips_dev *dev)
++{
++ set_gpio_bit(1, ILEVEL, dev); /* interrupt on cf ready (not busy) */
++ set_gpio_bit(0, ISTAT, dev); /* clear interrupt status */
++}
++
++static inline int cf_present(struct cf_mips_dev* dev)
++{
++ /* TODO: read and configure CIS into memory mapped mode
++ * TODO: parse CISTPL_CONFIG on CF+ cards to get base address (0x200)
++ * TODO: maybe adjust power saving setting for Hitachi Microdrive
++ */
++ int i;
++
++ /* setup CFRDY GPIO as input */
++ set_gpio_bit(0, FUNC, dev);
++ set_gpio_bit(0, CFG, dev);
++
++ for (i = 0; i < 0x10; ++i) {
++ if (rareg(i,dev) != 0xff)
++ return 1;
++ }
++ return 0;
++}
++
++static inline int is_busy(struct cf_mips_dev *dev)
++{
++ return !cfrdy(dev);
++}
++
++static int wait_not_busy(int to_us, int wait_for_busy,struct cf_mips_dev *dev)
++{
++ int us_passed = 0;
++ if (wait_for_busy && !is_busy(dev)) {
++ /* busy must appear within 400ns,
++ * but it may dissapear before we see it
++ * => must not wait for busy in a loop
++ */
++ ndelay(400);
++ }
++
++ do {
++ if (us_passed)
++ udelay(1); /* never reached in async mode */
++ if (!is_busy(dev)) {
++ if (us_passed > 1 * SECS) {
++ printk(KERN_WARNING "cf-mips: not busy ok (after %dus)"
++ ", status 0x%02x\n", us_passed, (unsigned) rareg(ATA_REG_ST,dev));
++ }
++ return CF_TRANS_OK;
++ }
++ if (us_passed == 1 * SECS) {
++ printk(KERN_WARNING "cf-mips: wait not busy %dus..\n", to_us);
++ }
++ if (dev->async_mode) {
++ dev->to_timer.expires = jiffies + (to_us * HZ / SECS);
++ dev->irq_enable_time = jiffies;
++ prepare_cf_irq(dev);
++ if (is_busy(dev)) {
++ add_timer(&dev->to_timer);
++ enable_irq(dev->irq);
++ return CF_TRANS_IN_PROGRESS;
++ }
++ continue;
++ }
++ ++us_passed;
++ } while (us_passed < to_us);
++
++ printk(KERN_ERR "cf-mips: wait not busy timeout (%dus)"
++ ", status 0x%02x, state %d\n",
++ to_us, (unsigned) rareg(ATA_REG_ST,dev), dev->tstate);
++ return CF_TRANS_FAILED;
++}
++
++static irqreturn_t cf_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
++{
++ /* While tasklet has not disabled irq, irq will be retried all the time
++ * because of ILEVEL matching GPIO pin status => deadlock.
++ * To avoid this, we change ILEVEL to 0.
++ */
++ struct cf_mips_dev *dev=dev_id;
++
++ set_gpio_bit(0, ILEVEL, dev);
++ set_gpio_bit(0, ISTAT, dev);
++
++ del_timer(&dev->to_timer);
++ tasklet_schedule(&dev->tasklet);
++ return IRQ_HANDLED;
++}
++
++static int do_reset(struct cf_mips_dev *dev)
++{
++ printk(KERN_INFO "cf-mips: resetting..\n");
++
++ wareg(ATA_REG_DC_SRST, ATA_REG_DC,dev);
++ udelay(1); /* FIXME: how long should we wait here? */
++ wareg(0, ATA_REG_DC,dev);
++
++ return wait_not_busy(30 * SECS, 1,dev);
++}
++
++static int set_multiple(struct cf_mips_dev *dev)
++{
++ if (dev->block_size <= 1)
++ return CF_TRANS_OK;
++
++ wareg(dev->block_size, ATA_REG_SC,dev);
++ wareg(ATA_REG_DH_BASE | ATA_REG_DH_LBA, ATA_REG_DH,dev);
++ wareg(ATA_CMD_SET_MULTIPLE, ATA_REG_CMD,dev);
++
++ return wait_not_busy(10 * SECS, 1,dev);
++}
++
++static int set_cmd(struct cf_mips_dev *dev)
++{
++ //DEBUGP(KERN_INFO "cf-mips: ata cmd 0x%02x\n", dev->tcmd);
++ // sector_count should be <=24 bits..
++ BUG_ON(dev->tsect_start>=0x10000000);
++ // This way, it addresses 2^24 * 512 = 128G
++
++ if (dev->tsector_count) {
++ wareg(dev->tsector_count & 0xff, ATA_REG_SC,dev);
++ wareg(dev->tsect_start & 0xff, ATA_REG_SN,dev);
++ wareg((dev->tsect_start >> 8) & 0xff, ATA_REG_CL,dev);
++ wareg((dev->tsect_start >> 16) & 0xff, ATA_REG_CH,dev);
++ }
++ wareg(((dev->tsect_start >> 24) & 0x0f) | ATA_REG_DH_BASE | ATA_REG_DH_LBA,
++ ATA_REG_DH,dev); /* select drive on all commands */
++ wareg(dev->tcmd, ATA_REG_CMD,dev);
++ return wait_not_busy(10 * SECS, 1,dev);
++}
++
++static int do_trans(struct cf_mips_dev *dev)
++{
++ int res;
++ unsigned st;
++ int transfered;
++
++ //printk("do_trans: %d sectors left\n",dev->tsectors_left);
++ while (dev->tsectors_left) {
++ transfered = 0;
++
++ st = rareg(ATA_REG_ST,dev);
++ if (!(st & ATA_REG_ST_DRQ)) {
++ printk(KERN_ERR "cf-mips: do_trans without DRQ (status 0x%x)!\n", st);
++ if (st & ATA_REG_ST_ERR) {
++ int errId = rareg(ATA_REG_ERR,dev);
++ printk(KERN_ERR "cf-mips: %s error, status 0x%x, errid 0x%x\n",
++ (dev->tread ? "read" : "write"), st, errId);
++ }
++ return CF_TRANS_FAILED;
++ }
++ do { /* Fill/read the buffer one block */
++ u32 *qbuf, *qend;
++ qbuf = (u32 *)dev->tbuf;
++ qend = qbuf + CF_SECT_SIZE / sizeof(u32);
++ if (dev->tread) {
++ while (qbuf!=qend)
++ put_unaligned(*DBUF32,qbuf++);
++ //*(qbuf++) = *DBUF32;
++ }
++ else {
++ while(qbuf!=qend)
++ *DBUF32 = get_unaligned(qbuf++);
++ }
++
++ dev->tsectors_left--;
++ dev->tbuf += CF_SECT_SIZE;
++ dev->tbuf_size -= CF_SECT_SIZE;
++ transfered++;
++ } while (transfered != dev->block_size && dev->tsectors_left > 0);
++
++ res = wait_not_busy(10 * SECS, 1,dev);
++ if (res != CF_TRANS_OK)
++ return res;
++ };
++
++ st = rareg(ATA_REG_ST,dev);
++ if (st & (ATA_REG_ST_DRQ | ATA_REG_ST_DWF | ATA_REG_ST_ERR)) {
++ if (st & ATA_REG_ST_DRQ) {
++ printk(KERN_ERR "cf-mips: DRQ after all %d sectors are %s"
++ ", status 0x%x\n", dev->tsector_count, (dev->tread ? "read" : "written"), st);
++ } else if (st & ATA_REG_ST_DWF) {
++ printk(KERN_ERR "cf-mips: write fault, status 0x%x\n", st);
++ } else {
++ int errId = rareg(ATA_REG_ERR,dev);
++ printk(KERN_ERR "cf-mips: %s error, status 0x%x, errid 0x%x\n",
++ (dev->tread ? "read" : "write"), st, errId);
++ }
++ return CF_TRANS_FAILED;
++ }
++ return CF_TRANS_OK;
++}
++
++static int cf_do_state(struct cf_mips_dev *dev)
++{
++ int res;
++ switch (dev->tstate) { /* fall through everywhere */
++ case TS_IDLE:
++ dev->tstate = TS_READY;
++ if (is_busy(dev)) {
++ dev->tstate = TS_AFTER_RESET;
++ res = do_reset(dev);
++ if (res != CF_TRANS_OK)
++ break;
++ }
++ case TS_AFTER_RESET:
++ if (dev->tstate == TS_AFTER_RESET) {
++ dev->tstate = TS_READY;
++ res = set_multiple(dev);
++ if (res != CF_TRANS_OK)
++ break;
++ }
++ case TS_READY:
++ dev->tstate = TS_CMD;
++ res = set_cmd(dev);
++ if (res != CF_TRANS_OK)
++ break;;
++ case TS_CMD:
++ dev->tstate = TS_TRANS;
++ case TS_TRANS:
++ res = do_trans(dev);
++ break;
++ default:
++ printk(KERN_ERR "cf-mips: BUG: unknown tstate %d\n", dev->tstate);
++ return CF_TRANS_FAILED;
++ }
++ if (res != CF_TRANS_IN_PROGRESS)
++ dev->tstate = TS_IDLE;
++ return res;
++}
++
++static void cf_do_tasklet(unsigned long dev_l)
++{
++ struct cf_mips_dev* dev=(struct cf_mips_dev*) dev_l;
++ int res;
++
++ disable_irq(dev->irq);
++
++ if (dev->tstate == TS_IDLE)
++ return; /* can happen when irq is first registered */
++
++#if 0
++ DEBUGP(KERN_WARNING "cf-mips: not busy ok (tasklet) status 0x%02x\n",
++ (unsigned) rareg(ATA_REG_ST,dev));
++#endif
++
++ res = cf_do_state(dev);
++ if (res == CF_TRANS_IN_PROGRESS)
++ return;
++ cf_async_trans_done(dev,res);
++}
++
++static void cf_async_timeout(unsigned long dev_l)
++{
++ struct cf_mips_dev* dev=(struct cf_mips_dev*) dev_l;
++ disable_irq(dev->irq);
++ /* Perhaps send abort to the device? */
++ printk(KERN_ERR "cf-mips: wait not busy timeout (%lus)"
++ ", status 0x%02x, state %d\n",
++ jiffies - dev->irq_enable_time, (unsigned) rareg(ATA_REG_ST,dev), dev->tstate);
++ dev->tstate = TS_IDLE;
++ cf_async_trans_done(dev,CF_TRANS_FAILED);
++}
++
++int cf_do_transfer(struct cf_mips_dev* dev,sector_t sector, unsigned long nsect,
++ char* buffer, int is_write)
++{
++ BUG_ON(dev->tstate!=TS_IDLE);
++ if (nsect > ATA_MAX_SECT_PER_CMD) {
++ printk(KERN_WARNING "cf-mips: sector count %lu out of range\n",nsect);
++ return CF_TRANS_FAILED;
++ }
++ if (sector + nsect > dev->sectors) {
++ printk(KERN_WARNING "cf-mips: sector %lu out of range\n",sector);
++ return CF_TRANS_FAILED;
++ }
++ dev->tbuf = buffer;
++ dev->tbuf_size = nsect*512;
++ dev->tsect_start = sector;
++ dev->tsector_count = nsect;
++ dev->tsectors_left = dev->tsector_count;
++ dev->tread = (is_write)?0:1;
++
++ dev->tcmd = (dev->block_size == 1 ?
++ (is_write ? ATA_CMD_WRITE_SECTORS : ATA_CMD_READ_SECTORS) :
++ (is_write ? ATA_CMD_WRITE_MULTIPLE : ATA_CMD_READ_MULTIPLE));
++
++ return cf_do_state(dev);
++}
++
++static int do_identify(struct cf_mips_dev *dev)
++{
++ u16 sbuf[CF_SECT_SIZE >> 1];
++ int res;
++ char tstr[17]; //serial
++ BUG_ON(dev->tstate!=TS_IDLE);
++ dev->tbuf = (char *) sbuf;
++ dev->tbuf_size = CF_SECT_SIZE;
++ dev->tsect_start = 0;
++ dev->tsector_count = 0;
++ dev->tsectors_left = 1;
++ dev->tread = 1;
++ dev->tcmd = ATA_CMD_IDENTIFY_DRIVE;
++
++ DEBUGP(KERN_INFO "cf-mips: identify drive..\n");
++ res = cf_do_state(dev);
++ if (res == CF_TRANS_IN_PROGRESS) {
++ printk(KERN_ERR "cf-mips: BUG: async identify cmd\n");
++ return CF_TRANS_FAILED;
++ }
++ if (res != CF_TRANS_OK)
++ return 0;
++
++ dev->head = sbuf[3];
++ dev->cyl = sbuf[1];
++ dev->spt = sbuf[6];
++ dev->sectors = ((unsigned long) sbuf[7] << 16) | sbuf[8];
++ dev->dtype=sbuf[0];
++ memcpy(tstr,&sbuf[12],16);
++ tstr[16]=0;
++ printk(KERN_INFO "cf-mips: %s detected, C/H/S=%d/%d/%d sectors=%u (%uMB) Serial=%s\n",
++ (sbuf[0] == 0x848A ? "CF card" : "ATA drive"), dev->cyl, dev->head,
++ dev->spt, dev->sectors, dev->sectors >> 11,tstr);
++ return 1;
++}
++
++static void init_multiple(struct cf_mips_dev * dev)
++{
++ int res;
++ DEBUGP(KERN_INFO "cf-mips: detecting block size\n");
++
++ dev->block_size = 128; /* max block size = 128 sectors (64KB) */
++ do {
++ wareg(dev->block_size, ATA_REG_SC,dev);
++ wareg(ATA_REG_DH_BASE | ATA_REG_DH_LBA, ATA_REG_DH,dev);
++ wareg(ATA_CMD_SET_MULTIPLE, ATA_REG_CMD,dev);
++
++ res = wait_not_busy(10 * SECS, 1,dev);
++ if (res != CF_TRANS_OK) {
++ printk(KERN_ERR "cf-mips: failed to detect block size: busy!\n");
++ dev->block_size = 1;
++ return;
++ }
++ if ((rareg(ATA_REG_ST,dev) & ATA_REG_ST_ERR) == 0)
++ break;
++ dev->block_size /= 2;
++ } while (dev->block_size > 1);
++
++ printk(KERN_INFO "cf-mips: multiple sectors = %d\n", dev->block_size);
++}
++
++int cf_init(struct cf_mips_dev *dev)
++{
++ tasklet_init(&dev->tasklet,cf_do_tasklet,(unsigned long)dev);
++ dev->baddr = ioremap_nocache((unsigned long)dev->base, CFDEV_BUF_SIZE);
++ if (!dev->baddr) {
++ printk(KERN_ERR "cf-mips: cf_init: ioremap for (%lx,%x) failed\n",
++ (unsigned long) dev->base, CFDEV_BUF_SIZE);
++ return -EBUSY;
++ }
++
++ if (!cf_present(dev)) {
++ printk(KERN_WARNING "cf-mips: cf card not present\n");
++ iounmap(dev->baddr);
++ return -ENODEV;
++ }
++
++ if (do_reset(dev) != CF_TRANS_OK) {
++ printk(KERN_ERR "cf-mips: cf reset failed\n");
++ iounmap(dev->baddr);
++ return -EBUSY;
++ }
++
++ if (!do_identify(dev)) {
++ printk(KERN_ERR "cf-mips: cf identify failed\n");
++ iounmap(dev->baddr);
++ return -EBUSY;
++ }
++
++/* set_apm_level(ATA_APM_WITH_STANDBY); */
++ init_multiple(dev);
++
++ init_timer(&dev->to_timer);
++ dev->to_timer.function = cf_async_timeout;
++ dev->to_timer.data = (unsigned long)dev;
++
++ prepare_cf_irq(dev);
++ if (request_irq(dev->irq, cf_irq_handler, 0, "CF Mips", dev)) {
++ printk(KERN_ERR "cf-mips: failed to get irq\n");
++ iounmap(dev->baddr);
++ return -EBUSY;
++ }
++ /* Disable below would be odd, because request will enable, and the tasklet
++ will disable it itself */
++ //disable_irq(dev->irq);
++
++ dev->async_mode = 1;
++
++ return 0;
++}
++
++void cf_cleanup(struct cf_mips_dev *dev)
++{
++ iounmap(dev->baddr);
++ free_irq(dev->irq, NULL);
++#if REQUEST_MEM_REGION
++ release_mem_region((unsigned long)dev->base, CFDEV_BUF_SIZE);
++#endif
++}
++
++
++/*eof*/
+diff -urN linux.old/drivers/block/rb500/ata.h linux.dev/drivers/block/rb500/ata.h
+--- linux.old/drivers/block/rb500/ata.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/block/rb500/ata.h 2006-06-09 00:15:23.000000000 +0200
+@@ -0,0 +1,132 @@
++#ifndef __CFMIPS_ATA_H__
++#define __CFMIPS_ATA_H__
++
++#include <linux/interrupt.h>
++
++#define CFG_DC_DEV1 (void*)0xb8010010
++#define CFG_DC_DEVBASE 0x0
++#define CFG_DC_DEVMASK 0x4
++#define CFG_DC_DEVC 0x8
++#define CFG_DC_DEVTC 0xC
++
++#define CFDEV_BUF_SIZE 0x1000
++#define ATA_CIS_OFFSET 0x200
++#define ATA_REG_OFFSET 0x800
++#define ATA_DBUF_OFFSET 0xC00
++
++#define ATA_REG_FEAT 0x1
++#define ATA_REG_SC 0x2
++#define ATA_REG_SN 0x3
++#define ATA_REG_CL 0x4
++#define ATA_REG_CH 0x5
++#define ATA_REG_DH 0x6
++#define ATA_REG_DH_BASE 0xa0
++#define ATA_REG_DH_LBA 0x40
++#define ATA_REG_DH_DRV 0x10
++#define ATA_REG_CMD 0x7
++#define ATA_REG_ST 0x7
++#define ATA_REG_ST_BUSY 0x80
++#define ATA_REG_ST_RDY 0x40
++#define ATA_REG_ST_DWF 0x20
++#define ATA_REG_ST_DSC 0x10
++#define ATA_REG_ST_DRQ 0x08
++#define ATA_REG_ST_CORR 0x04
++#define ATA_REG_ST_ERR 0x01
++#define ATA_REG_ERR 0xd
++#define ATA_REG_DC 0xe
++#define ATA_REG_DC_IEN 0x02
++#define ATA_REG_DC_SRST 0x04
++
++#define ATA_CMD_READ_SECTORS 0x20
++#define ATA_CMD_WRITE_SECTORS 0x30
++#define ATA_CMD_EXEC_DRIVE_DIAG 0x90
++#define ATA_CMD_READ_MULTIPLE 0xC4
++#define ATA_CMD_WRITE_MULTIPLE 0xC5
++#define ATA_CMD_SET_MULTIPLE 0xC6
++#define ATA_CMD_IDENTIFY_DRIVE 0xEC
++#define ATA_CMD_SET_FEATURES 0xEF
++
++#define ATA_FEATURE_ENABLE_APM 0x05
++#define ATA_FEATURE_DISABLE_APM 0x85
++#define ATA_APM_DISABLED 0x00
++#define ATA_APM_MIN_POWER 0x01
++#define ATA_APM_WITH_STANDBY 0x7f
++#define ATA_APM_WITHOUT_STANDBY 0x80
++#define ATA_APM_MAX_PERFORMANCE 0xfe
++
++#define CF_SECT_SIZE 0x200
++/* That is the ratio CF_SECT_SIZE/512 (the kernel sector size) */
++#define CF_KERNEL_MUL 1
++#define ATA_MAX_SECT_PER_CMD 0x100
++
++#define CF_TRANS_FAILED 0
++#define CF_TRANS_OK 1
++#define CF_TRANS_IN_PROGRESS 2
++
++
++enum trans_state {
++ TS_IDLE = 0,
++ TS_AFTER_RESET,
++ TS_READY,
++ TS_CMD,
++ TS_TRANS
++};
++
++//
++// #if DEBUG
++// static unsigned long busy_time;
++// #endif
++
++/** Struct to hold the cfdev
++Actually, all the data here only has one instance. However, for
++reasons of programming conformity, it is passed around as a pointer
++*/
++struct cf_mips_dev {
++ void *base; /* base address for I/O */
++ void *baddr; /* remapped address */
++
++ int pin; /* gpio pin */
++ int irq; /* gpio irq */
++
++ unsigned head;
++ unsigned cyl;
++ unsigned spt;
++ unsigned sectors;
++
++ unsigned short block_size;
++ unsigned dtype ; // ATA or CF
++ struct request_queue *queue;
++ struct gendisk *gd;
++
++ /* Transaction state */
++ enum trans_state tstate;
++ char *tbuf;
++ unsigned long tbuf_size;
++ sector_t tsect_start;
++ unsigned tsector_count;
++ unsigned tsectors_left;
++ int tread;
++ unsigned tcmd;
++ int async_mode;
++ unsigned long irq_enable_time;
++
++ struct request *active_req; /* A request is being carried out. Is that different from tstate? */
++ int users;
++ struct timer_list to_timer;
++ struct tasklet_struct tasklet;
++
++ /** This lock ensures that the requests to this device are all done
++ atomically. Transfers can run in parallel, requests are all queued
++ one-by-one */
++ spinlock_t lock;
++};
++
++int cf_do_transfer(struct cf_mips_dev* dev,sector_t sector, unsigned long nsect,
++ char* buffer, int is_write);
++int cf_init(struct cf_mips_dev* dev);
++void cf_cleanup(struct cf_mips_dev* dev);
++
++void cf_async_trans_done(struct cf_mips_dev* dev, int result);
++// void *cf_get_next_buf(unsigned long *buf_size);
++
++#endif
+diff -urN linux.old/drivers/block/rb500/bdev.c linux.dev/drivers/block/rb500/bdev.c
+--- linux.old/drivers/block/rb500/bdev.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/block/rb500/bdev.c 2006-06-15 16:29:04.000000000 +0200
+@@ -0,0 +1,340 @@
++/* CF-mips driver
++ This is a block driver for the direct (mmaped) interface to the CF-slot,
++ found in Routerboard.com's RB532 board
++ See SDK provided from routerboard.com.
++
++ Module adapted By P.Christeas <p_christeas@yahoo.com>, 2005-6.
++ Cleaned up and adapted to platform_device by Felix Fietkau <nbd@openwrt.org>
++
++ This work is redistributed under the terms of the GNU General Public License.
++*/
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/time.h>
++#include <linux/wait.h>
++#include <linux/fs.h>
++#include <linux/genhd.h>
++#include <linux/blkdev.h>
++#include <linux/blkpg.h>
++#include <linux/hdreg.h>
++#include <linux/platform_device.h>
++
++#include <asm/uaccess.h>
++#include <asm/io.h>
++
++#include <asm/rc32434/rb.h>
++
++#ifdef DEBUG
++#define DEBUGP printk
++#define DLEVEL 1
++#else
++#define DEBUGP(format, args...)
++#define DLEVEL 0
++#endif
++
++#define CF_MIPS_MAJOR 13
++#define MAJOR_NR CF_MIPS_MAJOR
++#define CF_MAX_PART 16 /* max 15 partitions */
++
++#include "ata.h"
++
++//extern struct block_device_operations cf_bdops;
++
++// static struct hd_struct cf_parts[CF_MAX_PART];
++// static int cf_part_sizes[CF_MAX_PART];
++// static int cf_hsect_sizes[CF_MAX_PART];
++// static int cf_max_sectors[CF_MAX_PART];
++// static int cf_blksize_sizes[CF_MAX_PART];
++
++// static spinlock_t lock = SPIN_LOCK_UNLOCKED;
++
++// volatile int cf_busy = 0;
++
++static struct request *active_req = NULL;
++
++static int cf_open (struct inode *, struct file *);
++static int cf_release (struct inode *, struct file *);
++static int cf_ioctl (struct inode *, struct file *, unsigned, unsigned long);
++
++static void cf_request(request_queue_t * q);
++static int cf_transfer(const struct request *req);
++
++/*long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
++long (*compat_ioctl) (struct file *, unsigned, unsigned long);*/
++// int (*direct_access) (struct block_device *, sector_t, unsigned long *);
++// int (*media_changed) (struct gendisk *);
++// int (*revalidate_disk) (struct gendisk *);
++
++static struct block_device_operations cf_bdops = {
++ .owner = THIS_MODULE,
++ .open = cf_open,
++ .release = cf_release,
++ .ioctl = cf_ioctl,
++ .media_changed = NULL,
++ .unlocked_ioctl = NULL,
++ .revalidate_disk = NULL,
++ .compat_ioctl = NULL,
++ .direct_access = NULL
++};
++
++
++int cf_mips_probe(struct platform_device *pdev)
++{
++ struct gendisk* cf_gendisk=NULL;
++ struct cf_device *cdev = (struct cf_device *) pdev->dev.platform_data;
++ struct cf_mips_dev *dev;
++ struct resource *r;
++ int reg_result;
++
++ reg_result = register_blkdev(MAJOR_NR, "cf-mips");
++ if (reg_result < 0) {
++ printk(KERN_WARNING "cf-mips: can't get major %d\n", MAJOR_NR);
++ return reg_result;
++ }
++
++ dev = (struct cf_mips_dev *)kmalloc(sizeof(struct cf_mips_dev),GFP_KERNEL);
++ if (!dev)
++ goto out_err;
++ memset(dev, 0, sizeof(struct cf_mips_dev));
++ cdev->dev = dev;
++
++ dev->pin = cdev->gpio_pin;
++ dev->irq = platform_get_irq_byname(pdev, "cf_irq");
++ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cf_membase");
++ dev->base = (void *) r->start;
++
++ if (cf_init(dev)) goto out_err;
++ printk("init done");
++
++ spin_lock_init(&dev->lock);
++ dev->queue = blk_init_queue(cf_request,&dev->lock);
++ if (!dev->queue){
++ printk(KERN_ERR "cf-mips: no mem for queue\n");
++ goto out_err;
++ }
++ blk_queue_max_sectors(dev->queue,ATA_MAX_SECT_PER_CMD);
++
++ /* For memory devices, it is always better to avoid crossing segments
++ inside the same request. */
++/* if (dev->dtype==0x848A){
++ printk(KERN_INFO "Setting boundary for cf to 0x%x",(dev->block_size*512)-1);
++ blk_queue_segment_boundary(dev->queue, (dev->block_size*512)-1);
++ }*/
++
++ dev->gd = alloc_disk(CF_MAX_PART);
++ cf_gendisk = dev->gd;
++ cdev->gd = dev->gd;
++ if (!cf_gendisk) goto out_err; /* Last of these goto's */
++
++ cf_gendisk->major = MAJOR_NR;
++ cf_gendisk->first_minor = 0;
++ cf_gendisk->queue=dev->queue;
++ BUG_ON(cf_gendisk->minors != CF_MAX_PART);
++ strcpy(cf_gendisk->disk_name,"cfa");
++ strcpy(cf_gendisk->devfs_name,"cf/card0");
++ cf_gendisk->fops = &cf_bdops;
++ cf_gendisk->flags = 0 ; /* is not yet GENHD_FL_REMOVABLE */
++ cf_gendisk->private_data=dev;
++
++ set_capacity(cf_gendisk,dev->sectors * CF_KERNEL_MUL);
++
++ /* Let the disk go live */
++ add_disk(cf_gendisk);
++#if 0
++ result = cf_init();
++
++ /* default cfg for all partitions */
++ memset(cf_parts, 0, sizeof (cf_parts[0]) * CF_MAX_PART);
++ memset(cf_part_sizes, 0, sizeof (cf_part_sizes[0]) * CF_MAX_PART);
++ for (i = 0; i < CF_MAX_PART; ++i) {
++ cf_hsect_sizes[i] = CF_SECT_SIZE;
++ cf_max_sectors[i] = ATA_MAX_SECT_PER_CMD;
++ cf_blksize_sizes[i] = BLOCK_SIZE;
++ }
++
++ /* setup info for whole disk (partition 0) */
++ cf_part_sizes[0] = cf_sectors / 2;
++ cf_parts[0].nr_sects = cf_sectors;
++
++ blk_size[MAJOR_NR] = cf_part_sizes;
++ blksize_size[MAJOR_NR] = cf_blksize_sizes;
++ max_sectors[MAJOR_NR] = cf_max_sectors;
++ hardsect_size[MAJOR_NR] = cf_hsect_sizes;
++ read_ahead[MAJOR_NR] = 8; /* (4kB) */
++
++ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
++
++ add_gendisk(&cf_gendisk);
++#endif
++// printk(KERN_INFO "cf-mips partition check: \n");
++// register_disk(cf_gendisk, MKDEV(MAJOR_NR, 0), CF_MAX_PART,
++// &cf_bdops, dev->sectors);
++ return 0;
++
++out_err:
++ if (dev->queue){
++ blk_cleanup_queue(dev->queue);
++ }
++ if (reg_result) {
++ unregister_blkdev(MAJOR_NR, "cf-mips");
++ return reg_result;
++ }
++ if (dev){
++ cf_cleanup(dev);
++ kfree(dev);
++ }
++ return 1;
++}
++
++static int
++cf_mips_remove(struct platform_device *pdev)
++{
++ struct cf_device *cdev = (struct cf_device *) pdev->dev.platform_data;
++ struct cf_mips_dev *dev = (struct cf_mips_dev *) cdev->dev;
++
++ unregister_blkdev(MAJOR_NR, "cf-mips");
++ blk_cleanup_queue(dev->queue);
++
++ del_gendisk(dev->gd);
++ cf_cleanup(dev);
++ return 0;
++}
++
++
++static struct platform_driver cf_driver = {
++ .driver.name = "rb500-cf",
++ .probe = cf_mips_probe,
++ .remove = cf_mips_remove,
++};
++
++static int __init cf_mips_init(void)
++{
++ printk(KERN_INFO "cf-mips module loaded\n");
++ return platform_driver_register(&cf_driver);
++}
++
++static void cf_mips_cleanup(void)
++{
++ platform_driver_unregister(&cf_driver);
++ printk(KERN_INFO "cf-mips module removed\n");
++}
++
++module_init(cf_mips_init);
++module_exit(cf_mips_cleanup);
++
++MODULE_LICENSE("GPL");
++MODULE_ALIAS_BLOCKDEV_MAJOR(CF_MIPS_MAJOR);
++
++
++static int cf_open(struct inode *inode, struct file *filp)
++{
++ struct cf_mips_dev *dev=inode->i_bdev->bd_disk->private_data;
++ int minor = MINOR(inode->i_rdev);
++
++ if (minor >= CF_MAX_PART)
++ return -ENODEV;
++ //DEBUGP(KERN_INFO "cf-mips module opened, minor %d\n", minor);
++ spin_lock(&dev->lock);
++ dev->users++;
++ spin_unlock(&dev->lock);
++ filp->private_data=dev;
++
++ /* dirty workaround to set CFRDY GPIO as an input when some other
++ program sets it as an output */
++ gpio_set(CFG, (1 << dev->pin), 0);
++ return 0; /* success */
++}
++
++static int cf_release(struct inode *inode, struct file *filp)
++{
++ int minor = MINOR(inode->i_rdev);
++ struct cf_mips_dev *dev=inode->i_bdev->bd_disk->private_data;
++ spin_lock(&dev->lock);
++ dev->users--;
++ spin_unlock(&dev->lock);
++ return 0;
++}
++
++static int cf_ioctl(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
++{
++ unsigned minor = MINOR(inode->i_rdev);
++ struct cf_mips_dev *dev=inode->i_bdev->bd_disk->private_data;
++
++ DEBUGP(KERN_INFO "cf_ioctl cmd %u\n", cmd);
++ switch (cmd) {
++ case BLKRRPART: /* re-read partition table */
++ if (!capable(CAP_SYS_ADMIN))
++ return -EACCES;
++ printk(KERN_INFO "cf-mips partition check: \n");
++ register_disk(dev->gd);
++ return 0;
++
++ case HDIO_GETGEO:
++ {
++ struct hd_geometry geo;
++ geo.cylinders = dev->cyl;
++ geo.heads = dev->head;
++ geo.sectors = dev->spt;
++ geo.start = (*dev->gd->part)[minor].start_sect;
++ if (copy_to_user((void *) arg, &geo, sizeof (geo)))
++ return -EFAULT;
++ }
++ return 0;
++ }
++
++ return -EINVAL; /* unknown command */
++}
++
++static void cf_request(request_queue_t * q)
++{
++ struct cf_mips_dev* dev;
++
++ struct request * req;
++ int status;
++
++ /* We could have q->queuedata = dev , but haven't yet. */
++ if (active_req)
++ return;
++
++ while ((req=elv_next_request(q))!=NULL){
++ dev=req->rq_disk->private_data;
++ status=cf_transfer(req);
++ if (status==CF_TRANS_IN_PROGRESS){
++ active_req=req;
++ return;
++ }
++ end_request(req,status);
++ }
++}
++
++static int cf_transfer(const struct request *req)
++{
++ struct cf_mips_dev* dev=req->rq_disk->private_data;
++
++ if (!blk_fs_request(req)){
++ if (printk_ratelimit())
++ printk(KERN_WARNING "cf-mips: skipping non-fs request 0x%x\n",req->cmd[0]);
++ return CF_TRANS_FAILED;
++ }
++
++ return cf_do_transfer(dev,req->sector,req->current_nr_sectors,req->buffer,rq_data_dir(req));
++}
++
++void cf_async_trans_done(struct cf_mips_dev * dev,int result)
++{
++ struct request *req;
++
++ spin_lock(&dev->lock);
++ req=active_req;
++ active_req=NULL;
++ end_request(req,result);
++ spin_unlock(&dev->lock);
++
++ spin_lock(&dev->lock);
++ cf_request(dev->queue);
++ spin_unlock(&dev->lock);
++}
++
+diff -urN linux.old/drivers/block/rb500/Makefile linux.dev/drivers/block/rb500/Makefile
+--- linux.old/drivers/block/rb500/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/block/rb500/Makefile 2006-06-08 22:14:58.000000000 +0200
+@@ -0,0 +1,3 @@
++## Makefile for the RB532 CF port
++
++obj-y += bdev.o ata.o
+diff -urN linux.old/drivers/Makefile linux.dev/drivers/Makefile
+--- linux.old/drivers/Makefile 2006-06-08 20:20:52.000000000 +0200
++++ linux.dev/drivers/Makefile 2006-06-08 22:14:58.000000000 +0200
+@@ -73,3 +73,4 @@
+ obj-y += firmware/
+ obj-$(CONFIG_CRYPTO) += crypto/
+ obj-$(CONFIG_SUPERH) += sh/
++obj-$(CONFIG_BLK_DEV_CF_MIPS) += block/rb500/
+\ No newline at end of file
diff --git a/target/linux/rb532-2.6/patches/130-custom_partitions.patch b/target/linux/rb532-2.6/patches/130-custom_partitions.patch
new file mode 100644
index 0000000000..e4b332703a
--- /dev/null
+++ b/target/linux/rb532-2.6/patches/130-custom_partitions.patch
@@ -0,0 +1,311 @@
+diff -urN linux.old/fs/partitions/check.c linux.dev/fs/partitions/check.c
+--- linux.old/fs/partitions/check.c 2006-05-31 02:31:44.000000000 +0200
++++ linux.dev/fs/partitions/check.c 2006-06-15 01:27:17.000000000 +0200
+@@ -29,6 +29,7 @@
+ #include "ldm.h"
+ #include "mac.h"
+ #include "msdos.h"
++#include "openwrt.h"
+ #include "osf.h"
+ #include "sgi.h"
+ #include "sun.h"
+@@ -48,6 +49,9 @@
+ * Probe partition formats with tables at disk address 0
+ * that also have an ADFS boot block at 0xdc0.
+ */
++#ifdef CONFIG_OPENWRT_PARTITION
++ openwrt_partition,
++#endif
+ #ifdef CONFIG_ACORN_PARTITION_ICS
+ adfspart_check_ICS,
+ #endif
+diff -urN linux.old/fs/partitions/Kconfig linux.dev/fs/partitions/Kconfig
+--- linux.old/fs/partitions/Kconfig 2006-05-31 02:31:44.000000000 +0200
++++ linux.dev/fs/partitions/Kconfig 2006-06-15 01:27:17.000000000 +0200
+@@ -14,6 +14,12 @@
+
+ If unsure, say N.
+
++config OPENWRT_PARTITION
++ bool "OpenWrt partition support" if PARTITION_ADVANCED
++ default y
++ help
++ Support the custom OpenWrt partition map
++
+ config ACORN_PARTITION
+ bool "Acorn partition support" if PARTITION_ADVANCED
+ default y if ARCH_ACORN
+diff -urN linux.old/fs/partitions/Makefile linux.dev/fs/partitions/Makefile
+--- linux.old/fs/partitions/Makefile 2006-05-31 02:31:44.000000000 +0200
++++ linux.dev/fs/partitions/Makefile 2006-06-15 01:27:17.000000000 +0200
+@@ -11,6 +11,7 @@
+ obj-$(CONFIG_MAC_PARTITION) += mac.o
+ obj-$(CONFIG_LDM_PARTITION) += ldm.o
+ obj-$(CONFIG_MSDOS_PARTITION) += msdos.o
++obj-$(CONFIG_OPENWRT_PARTITION) += openwrt.o
+ obj-$(CONFIG_OSF_PARTITION) += osf.o
+ obj-$(CONFIG_SGI_PARTITION) += sgi.o
+ obj-$(CONFIG_SUN_PARTITION) += sun.o
+diff -urN linux.old/fs/partitions/openwrt.c linux.dev/fs/partitions/openwrt.c
+--- linux.old/fs/partitions/openwrt.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/fs/partitions/openwrt.c 2006-06-15 01:27:17.000000000 +0200
+@@ -0,0 +1,249 @@
++/*
++ * fs/partitions/openwrt.c
++ *
++ * Code extracted from drivers/block/genhd.c
++ * and fs/partitions/msdos.c
++ *
++ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
++ * Copyright (C) 1991-1998 Linus Torvalds
++ *
++ * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
++ * in the early extended-partition checks and added DM partitions
++ *
++ * Support for DiskManager v6.0x added by Mark Lord,
++ * with information provided by OnTrack. This now works for linux fdisk
++ * and LILO, as well as loadlin and bootln. Note that disks other than
++ * /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
++ *
++ * More flexible handling of extended partitions - aeb, 950831
++ *
++ * Check partition table on IDE disks for common CHS translations
++ *
++ * Re-organised Feb 1998 Russell King
++ */
++
++#include <linux/config.h>
++
++#include "check.h"
++#include "openwrt.h"
++
++/*
++ * Many architectures don't like unaligned accesses, while
++ * the nr_sects and start_sect partition table entries are
++ * at a 2 (mod 4) address.
++ */
++#include <asm/unaligned.h>
++
++#define SYS_IND(p) (get_unaligned(&p->sys_ind))
++#define NR_SECTS(p) ({ __typeof__(p->nr_sects) __a = \
++ get_unaligned(&p->nr_sects); \
++ le32_to_cpu(__a); \
++ })
++
++#define START_SECT(p) ({ __typeof__(p->start_sect) __a = \
++ get_unaligned(&p->start_sect); \
++ le32_to_cpu(__a); \
++ })
++
++static inline int is_extended_partition(struct partition *p)
++{
++ return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
++ SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
++ SYS_IND(p) == LINUX_EXTENDED_PARTITION);
++}
++
++#define MSDOS_LABEL_MAGIC1 0x55
++#define MSDOS_LABEL_MAGIC2 0xAA
++
++static inline int
++msdos_magic_present(unsigned char *p)
++{
++ return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);
++}
++
++static inline int
++openwrt_magic_present(unsigned char *p)
++{
++ return (p[0] == 'O' &&
++ p[1] == 'W' &&
++ p[2] == 'R' &&
++ p[3] == 'T');
++}
++
++/*
++ * Create devices for each logical partition in an extended partition.
++ * The logical partitions form a linked list, with each entry being
++ * a partition table with two entries. The first entry
++ * is the real data partition (with a start relative to the partition
++ * table start). The second is a pointer to the next logical partition
++ * (with a start relative to the entire extended partition).
++ * We do not create a Linux partition for the partition tables, but
++ * only for the actual data partitions.
++ */
++
++static void
++parse_extended(struct parsed_partitions *state, struct block_device *bdev,
++ u32 first_sector, u32 first_size)
++{
++ struct partition *p;
++ Sector sect;
++ unsigned char *data;
++ u32 this_sector, this_size;
++ int sector_size = bdev_hardsect_size(bdev) / 512;
++ int loopct = 0; /* number of links followed
++ without finding a data partition */
++ int i;
++
++ this_sector = first_sector;
++ this_size = first_size;
++
++ while (1) {
++ if (++loopct > 100)
++ return;
++ if (state->next == state->limit)
++ return;
++ data = read_dev_sector(bdev, this_sector, &sect);
++ if (!data)
++ return;
++
++ if (!msdos_magic_present(data + 510))
++ goto done;
++
++ p = (struct partition *) (data + 0x1be);
++
++ /*
++ * Usually, the first entry is the real data partition,
++ * the 2nd entry is the next extended partition, or empty,
++ * and the 3rd and 4th entries are unused.
++ * However, DRDOS sometimes has the extended partition as
++ * the first entry (when the data partition is empty),
++ * and OS/2 seems to use all four entries.
++ */
++
++ /*
++ * First process the data partition(s)
++ */
++ for (i=0; i<4; i++, p++) {
++ u32 offs, size, next;
++ if (!NR_SECTS(p) || is_extended_partition(p))
++ continue;
++
++ /* Check the 3rd and 4th entries -
++ these sometimes contain random garbage */
++ offs = START_SECT(p)*sector_size;
++ size = NR_SECTS(p)*sector_size;
++ next = this_sector + offs;
++ if (i >= 2) {
++ if (offs + size > this_size)
++ continue;
++ if (next < first_sector)
++ continue;
++ if (next + size > first_sector + first_size)
++ continue;
++ }
++
++ put_partition(state, state->next, next, size);
++ if (SYS_IND(p) == LINUX_RAID_PARTITION)
++ state->parts[state->next].flags = 1;
++ loopct = 0;
++ if (++state->next == state->limit)
++ goto done;
++ }
++ /*
++ * Next, process the (first) extended partition, if present.
++ * (So far, there seems to be no reason to make
++ * parse_extended() recursive and allow a tree
++ * of extended partitions.)
++ * It should be a link to the next logical partition.
++ */
++ p -= 4;
++ for (i=0; i<4; i++, p++)
++ if (NR_SECTS(p) && is_extended_partition(p))
++ break;
++ if (i == 4)
++ goto done; /* nothing left to do */
++
++ this_sector = first_sector + START_SECT(p) * sector_size;
++ this_size = NR_SECTS(p) * sector_size;
++ put_dev_sector(sect);
++ }
++done:
++ put_dev_sector(sect);
++}
++
++
++int openwrt_partition(struct parsed_partitions *state, struct block_device *bdev)
++{
++ int sector_size = bdev_hardsect_size(bdev) / 512;
++ Sector sect;
++ unsigned char *data;
++ struct partition *p;
++ int slot;
++ u32 last_block = 0;
++ u32 size = 0;
++ int firstfree = 5;
++
++ data = read_dev_sector(bdev, 0, &sect);
++ if (!data)
++ return -1;
++ if (!openwrt_magic_present(data)) {
++ printk("No OpenWrt partition table detected\n");
++ put_dev_sector(sect);
++ return 0;
++ }
++
++ /*
++ * Now that the 55aa signature is present, this is probably
++ * either the boot sector of a FAT filesystem or a DOS-type
++ * partition table. Reject this in case the boot indicator
++ * is not 0 or 0x80.
++ */
++ p = (struct partition *) (data + 0x1be);
++ for (slot = 1; slot <= 4; slot++, p++) {
++ if (p->boot_ind != 0 && p->boot_ind != 0x80) {
++ put_dev_sector(sect);
++ return 0;
++ }
++ }
++
++ p = (struct partition *) (data + 0x1be);
++
++ /*
++ * Look for partitions in two passes:
++ * First find the primary and DOS-type extended partitions.
++ */
++
++ state->next = 6;
++ for (slot = 1 ; slot <= 4 ; slot++, p++) {
++ u32 start = START_SECT(p)*sector_size;
++ size = NR_SECTS(p)*sector_size;
++ if (!size) {
++ if (firstfree > slot)
++ firstfree = slot;
++
++ continue;
++ }
++ if (is_extended_partition(p)) {
++ /* prevent someone doing mkfs or mkswap on an
++ extended partition, but leave room for LILO */
++ last_block = start + size;
++ put_partition(state, slot, start, size == 1 ? 1 : 2);
++ printk(" <");
++ parse_extended(state, bdev, start, size);
++ printk(" >");
++ continue;
++ }
++ if ((start + size) > get_capacity(bdev->bd_disk))
++ size = get_capacity(bdev->bd_disk) - start;
++ last_block = start + size;
++ put_partition(state, slot, start, size);
++ }
++ if (last_block + 1024 < (size = get_capacity(bdev->bd_disk)))
++ put_partition(state, firstfree, last_block, size - last_block);
++
++ printk("\n");
++
++ put_dev_sector(sect);
++ return 1;
++}
++
+diff -urN linux.old/fs/partitions/openwrt.h linux.dev/fs/partitions/openwrt.h
+--- linux.old/fs/partitions/openwrt.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/fs/partitions/openwrt.h 2006-06-15 01:27:17.000000000 +0200
+@@ -0,0 +1,6 @@
++/*
++ * fs/partitions/openwrt.h
++ */
++
++int openwrt_partition(struct parsed_partitions *state, struct block_device *bdev);
++
diff --git a/target/linux/rb532-2.6/patches/200-bridge_resource_hack.patch b/target/linux/rb532-2.6/patches/200-bridge_resource_hack.patch
new file mode 100644
index 0000000000..3017f5dfcd
--- /dev/null
+++ b/target/linux/rb532-2.6/patches/200-bridge_resource_hack.patch
@@ -0,0 +1,13 @@
+--- linux.old/arch/mips/pci/pci.c 2006-04-19 08:10:14.000000000 +0200
++++ linux.dev/arch/mips/pci/pci.c 2006-06-14 20:23:18.000000000 +0200
+@@ -65,8 +65,10 @@
+ /*
+ * Put everything into 0x00-0xff region modulo 0x400
+ */
++#ifndef CONFIG_MIKROTIK_RB500
+ if (start & 0x300)
+ start = (start + 0x3ff) & ~0x3ff;
++#endif
+ } else if (res->flags & IORESOURCE_MEM) {
+ /* Make sure we start at our min on all hoses */
+ if (start < PCIBIOS_MIN_MEM + hose->mem_resource->start)
diff --git a/target/linux/rb532-2.6/patches/210-pci_fixes.patch b/target/linux/rb532-2.6/patches/210-pci_fixes.patch
new file mode 100644
index 0000000000..02cd2f063c
--- /dev/null
+++ b/target/linux/rb532-2.6/patches/210-pci_fixes.patch
@@ -0,0 +1,46 @@
+diff -urN linux.old/drivers/pci/probe.c linux.dev/drivers/pci/probe.c
+--- linux.old/drivers/pci/probe.c 2006-06-08 20:21:20.000000000 +0200
++++ linux.dev/drivers/pci/probe.c 2006-06-08 20:19:40.000000000 +0200
+@@ -760,15 +760,22 @@
+ u32 l;
+ u8 hdr_type;
+ int delay = 1;
+-
+- if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
+- return NULL;
+-
+- /* some broken boards return 0 or ~0 if a slot is empty: */
+- if (l == 0xffffffff || l == 0x00000000 ||
+- l == 0x0000ffff || l == 0xffff0000)
+- return NULL;
+-
++ do {
++ if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
++ return NULL;
++ /* some broken boards return 0 or ~0 if a slot is empty: */
++ if (l == 0xffffffff || l == 0x00000000 ||
++ l == 0x0000ffff || l == 0xffff0000){
++ if (delay > 4)
++ return NULL;
++ /* But that could also be the previous dev not settled */
++ pr_debug("PCI: retrying scan at 0x%x, because config is 0x%x\n",devfn,l);
++ msleep(delay);
++ delay *=2;
++ l=0;
++ }
++ }while (l==0);
++
+ /* Configuration request Retry Status */
+ while (l == 0xffff0001) {
+ msleep(delay);
+@@ -903,7 +910,10 @@
+
+ /* Go find them, Rover! */
+ for (devfn = 0; devfn < 0x100; devfn += 8)
++ {
++ if (bus->number == 0 && (devfn >> 3) > 21) break;
+ pci_scan_slot(bus, devfn);
++ }
+
+ /*
+ * After performing arch-dependent fixup of the bus, look behind
diff --git a/target/linux/rb532-2.6/patches/220-serial_fix.patch b/target/linux/rb532-2.6/patches/220-serial_fix.patch
new file mode 100644
index 0000000000..d36f263a33
--- /dev/null
+++ b/target/linux/rb532-2.6/patches/220-serial_fix.patch
@@ -0,0 +1,18 @@
+diff -urN linux.old/drivers/serial/8250.c linux.dev/drivers/serial/8250.c
+--- linux.old/drivers/serial/8250.c 2006-06-08 20:21:20.000000000 +0200
++++ linux.dev/drivers/serial/8250.c 2006-06-08 20:19:40.000000000 +0200
+@@ -351,6 +351,13 @@
+ default:
+ outb(value, up->port.iobase + offset);
+ }
++
++#if defined(CONFIG_IDT_EB434) || defined(CONFIG_MIKROTIK_RB500)
++ __SLOW_DOWN_IO;
++ __SLOW_DOWN_IO;
++ __SLOW_DOWN_IO;
++ __SLOW_DOWN_IO;
++#endif
+ }
+
+ /*
+
diff --git a/target/linux/rb532-2.6/patches/230-dma_limit.patch b/target/linux/rb532-2.6/patches/230-dma_limit.patch
new file mode 100644
index 0000000000..ca87115704
--- /dev/null
+++ b/target/linux/rb532-2.6/patches/230-dma_limit.patch
@@ -0,0 +1,13 @@
+diff -urN linux.old/arch/mips/mm/init.c linux.dev/arch/mips/mm/init.c
+--- linux.old/arch/mips/mm/init.c 2006-06-08 20:21:20.000000000 +0200
++++ linux.dev/arch/mips/mm/init.c 2006-06-08 20:19:40.000000000 +0200
+@@ -149,7 +149,7 @@
+ kmap_init();
+ #endif
+
+- max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
++ max_dma = virt_to_phys((char *) (256 * 1024 * 1024)) >> PAGE_SHIFT;
+ low = max_low_pfn;
+ high = highend_pfn;
+
+
diff --git a/target/linux/rb532-2.6/patches/240-via_rhine_performance.patch b/target/linux/rb532-2.6/patches/240-via_rhine_performance.patch
new file mode 100644
index 0000000000..56c1fb559c
--- /dev/null
+++ b/target/linux/rb532-2.6/patches/240-via_rhine_performance.patch
@@ -0,0 +1,461 @@
+diff -urN linux.old/drivers/net/via-rhine.c linux.dev/drivers/net/via-rhine.c
+--- linux.old/drivers/net/via-rhine.c 2006-06-08 20:21:20.000000000 +0200
++++ linux.dev/drivers/net/via-rhine.c 2006-06-08 20:19:40.000000000 +0200
+@@ -131,6 +131,10 @@
+ - Fix Tx engine race for good
+ - Craig Brind: Zero padded aligned buffers for short packets.
+
++ OpenWrt Version (Felix Fietkau <nbd@openwrt.org>)
++ - Performance improvements
++ - NAPI polling
++
+ */
+
+ #define DRV_NAME "via-rhine"
+@@ -142,7 +146,6 @@
+ These may be modified when a driver module is loaded. */
+
+ static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */
+-static int max_interrupt_work = 20;
+
+ /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
+ Setting to > 1518 effectively disables this feature. */
+@@ -165,9 +168,9 @@
+ Making the Tx ring too large decreases the effectiveness of channel
+ bonding and packet priority.
+ There are no ill effects from too-large receive rings. */
+-#define TX_RING_SIZE 16
+-#define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */
+-#define RX_RING_SIZE 16
++#define TX_RING_SIZE 128
++#define TX_QUEUE_LEN 120 /* Limit ring entries actually used. */
++#define RX_RING_SIZE 128
+
+
+ /* Operational parameters that usually are not changed. */
+@@ -201,6 +204,7 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/uaccess.h>
++#include <asm/unaligned.h>
+
+ /* These identify the driver base version and may not be removed. */
+ static char version[] __devinitdata =
+@@ -217,10 +221,8 @@
+ MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver");
+ MODULE_LICENSE("GPL");
+
+-module_param(max_interrupt_work, int, 0);
+ module_param(debug, int, 0);
+ module_param(rx_copybreak, int, 0);
+-MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt");
+ MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)");
+ MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames");
+
+@@ -461,6 +463,8 @@
+ struct tx_desc *tx_ring;
+ dma_addr_t rx_ring_dma;
+ dma_addr_t tx_ring_dma;
++ u32 istat;
++ u32 imask;
+
+ /* The addresses of receive-in-place skbuffs. */
+ struct sk_buff *rx_skbuff[RX_RING_SIZE];
+@@ -504,9 +508,10 @@
+ static void rhine_check_media_task(struct net_device *dev);
+ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev);
+ static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+-static void rhine_tx(struct net_device *dev);
+-static void rhine_rx(struct net_device *dev);
+-static void rhine_error(struct net_device *dev, int intr_status);
++static int rhine_poll(struct net_device *dev, int *budget);
++static int rhine_tx(struct net_device *dev);
++static int rhine_rx(struct net_device *dev);
++static void rhine_error(struct net_device *dev);
+ static void rhine_set_rx_mode(struct net_device *dev);
+ static struct net_device_stats *rhine_get_stats(struct net_device *dev);
+ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+@@ -601,6 +606,8 @@
+ struct rhine_private *rp = netdev_priv(dev);
+ void __iomem *ioaddr = rp->base;
+
++ pci_enable_device(rp->pdev);
++
+ iowrite8(Cmd1Reset, ioaddr + ChipCmd1);
+ IOSYNC;
+
+@@ -622,6 +629,28 @@
+ "failed" : "succeeded");
+ }
+
++static inline void rhine_intr_enable(struct net_device *dev)
++{
++ struct rhine_private *rp = netdev_priv(dev);
++ void __iomem *ioaddr = rp->base;
++
++ iowrite16(rp->imask = (IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
++ IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
++ IntrTxDone | IntrTxError | IntrTxUnderrun |
++ IntrPCIErr | IntrStatsMax | IntrLinkChange),
++ ioaddr + IntrEnable);
++}
++
++static inline void rhine_intr_disable(struct net_device *dev)
++{
++ struct rhine_private *rp = netdev_priv(dev);
++ void __iomem *ioaddr = rp->base;
++
++ iowrite16(rp->imask = (IntrRxOverflow | IntrRxNoBuf | IntrTxAborted |
++ IntrTxError | IntrTxUnderrun | IntrPCIErr | IntrStatsMax | IntrLinkChange),
++ ioaddr + IntrEnable);
++}
++
+ #ifdef USE_MMIO
+ static void enable_mmio(long pioaddr, u32 quirks)
+ {
+@@ -664,14 +693,26 @@
+
+ }
+
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+-static void rhine_poll(struct net_device *dev)
++static int rhine_poll(struct net_device *dev, int *budget)
+ {
+- disable_irq(dev->irq);
+- rhine_interrupt(dev->irq, (void *)dev, NULL);
+- enable_irq(dev->irq);
++ unsigned int work_done, work_to_do = min(*budget, dev->quota);
++ struct rhine_private *rp = netdev_priv(dev);
++
++ work_done = rhine_rx(dev);
++
++ if (rp->istat & (IntrTxErrSummary | IntrTxDone))
++ rhine_tx(dev);
++
++ *budget -= work_done;
++ dev->quota -= work_done;
++
++ if (work_done < work_to_do) {
++ netif_rx_complete(dev);
++ rhine_intr_enable(dev);
++ }
++
++ return (work_done >= work_to_do);
+ }
+-#endif
+
+ static void rhine_hw_init(struct net_device *dev, long pioaddr)
+ {
+@@ -850,11 +891,10 @@
+ dev->ethtool_ops = &netdev_ethtool_ops;
+ dev->tx_timeout = rhine_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+- dev->poll_controller = rhine_poll;
+-#endif
+- if (rp->quirks & rqRhineI)
+- dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
++ dev->poll = rhine_poll;
++ dev->weight = 64;
++
++ dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
+
+ INIT_WORK(&rp->tx_timeout_task,
+ (void (*)(void *))rhine_tx_timeout_task, dev);
+@@ -904,6 +944,10 @@
+ }
+ }
+ rp->mii_if.phy_id = phy_id;
++
++ // shut down until somebody really needs it
++ iowrite8(0x80, ioaddr + 0xa1);
++ pci_set_power_state(rp->pdev, 3);
+
+ return 0;
+
+@@ -995,7 +1039,7 @@
+
+ /* Fill in the Rx buffers. Handle allocation failure gracefully. */
+ for (i = 0; i < RX_RING_SIZE; i++) {
+- struct sk_buff *skb = dev_alloc_skb(rp->rx_buf_sz);
++ struct sk_buff *skb = dev_alloc_skb(rp->rx_buf_sz + 4);
+ rp->rx_skbuff[i] = skb;
+ if (skb == NULL)
+ break;
+@@ -1115,11 +1159,7 @@
+ rhine_set_rx_mode(dev);
+
+ /* Enable interrupts by setting the interrupt mask. */
+- iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
+- IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
+- IntrTxDone | IntrTxError | IntrTxUnderrun |
+- IntrPCIErr | IntrStatsMax | IntrLinkChange,
+- ioaddr + IntrEnable);
++ rhine_intr_enable(dev);
+
+ iowrite16(CmdStart | CmdTxOn | CmdRxOn | (Cmd1NoTxPoll << 8),
+ ioaddr + ChipCmd);
+@@ -1230,6 +1270,7 @@
+ mdio_read(dev, rp->mii_if.phy_id, MII_BMSR));
+
+ netif_start_queue(dev);
++ netif_poll_enable(dev);
+
+ return 0;
+ }
+@@ -1268,8 +1309,8 @@
+ /* Reinitialize the hardware. */
+ rhine_chip_reset(dev);
+ init_registers(dev);
+-
+ spin_unlock(&rp->lock);
++
+ enable_irq(rp->pdev->irq);
+
+ dev->trans_start = jiffies;
+@@ -1363,69 +1404,56 @@
+ struct net_device *dev = dev_instance;
+ struct rhine_private *rp = netdev_priv(dev);
+ void __iomem *ioaddr = rp->base;
+- u32 intr_status;
+- int boguscnt = max_interrupt_work;
+ int handled = 0;
+
+- while ((intr_status = get_intr_status(dev))) {
++ if ((rp->istat = (get_intr_status(dev) & rp->imask))) {
+ handled = 1;
+
+ /* Acknowledge all of the current interrupt sources ASAP. */
+- if (intr_status & IntrTxDescRace)
++ if (rp->istat & IntrTxDescRace)
+ iowrite8(0x08, ioaddr + IntrStatus2);
+- iowrite16(intr_status & 0xffff, ioaddr + IntrStatus);
++ iowrite16(rp->istat & 0xffff, ioaddr + IntrStatus);
+ IOSYNC;
+
+- if (debug > 4)
+- printk(KERN_DEBUG "%s: Interrupt, status %8.8x.\n",
+- dev->name, intr_status);
++ if (likely(rp->istat & ((IntrRxDone | IntrRxErr | IntrRxDropped |
++ IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf |
++ IntrTxErrSummary | IntrTxDone)))) {
++
++ rhine_intr_disable(dev);
+
+- if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped |
+- IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf))
+- rhine_rx(dev);
+-
+- if (intr_status & (IntrTxErrSummary | IntrTxDone)) {
+- if (intr_status & IntrTxErrSummary) {
+- /* Avoid scavenging before Tx engine turned off */
+- RHINE_WAIT_FOR(!(ioread8(ioaddr+ChipCmd) & CmdTxOn));
+- if (debug > 2 &&
+- ioread8(ioaddr+ChipCmd) & CmdTxOn)
+- printk(KERN_WARNING "%s: "
+- "rhine_interrupt() Tx engine"
+- "still on.\n", dev->name);
+- }
+- rhine_tx(dev);
++ if (likely(netif_rx_schedule_prep(dev)))
++ __netif_rx_schedule(dev);
+ }
+
+ /* Abnormal error summary/uncommon events handlers. */
+- if (intr_status & (IntrPCIErr | IntrLinkChange |
++ if (unlikely(rp->istat & (IntrPCIErr | IntrLinkChange |
+ IntrStatsMax | IntrTxError | IntrTxAborted |
+- IntrTxUnderrun | IntrTxDescRace))
+- rhine_error(dev, intr_status);
+-
+- if (--boguscnt < 0) {
+- printk(KERN_WARNING "%s: Too much work at interrupt, "
+- "status=%#8.8x.\n",
+- dev->name, intr_status);
+- break;
+- }
++ IntrTxUnderrun | IntrTxDescRace)))
++ rhine_error(dev);
+ }
+
+- if (debug > 3)
+- printk(KERN_DEBUG "%s: exiting interrupt, status=%8.8x.\n",
+- dev->name, ioread16(ioaddr + IntrStatus));
+ return IRQ_RETVAL(handled);
+ }
+
+ /* This routine is logically part of the interrupt handler, but isolated
+ for clarity. */
+-static void rhine_tx(struct net_device *dev)
++static int rhine_tx(struct net_device *dev)
+ {
+ struct rhine_private *rp = netdev_priv(dev);
+ int txstatus = 0, entry = rp->dirty_tx % TX_RING_SIZE;
++ void __iomem *ioaddr = rp->base;
++ int done = 0;
+
+- spin_lock(&rp->lock);
++ /* Avoid scavenging before Tx engine turned off */
++ RHINE_WAIT_FOR(!(ioread8(ioaddr+ChipCmd) & CmdTxOn));
++ if (debug > 2 &&
++ ioread8(ioaddr+ChipCmd) & CmdTxOn)
++ printk(KERN_WARNING "%s: "
++ "rhine_interrupt() Tx engine"
++ "still on.\n", dev->name);
+
++
++ spin_lock_irq(&rp->lock);
+ /* find and cleanup dirty tx descriptors */
+ while (rp->dirty_tx != rp->cur_tx) {
+ txstatus = le32_to_cpu(rp->tx_ring[entry].tx_status);
+@@ -1462,6 +1490,7 @@
+ txstatus & 0xF);
+ rp->stats.tx_bytes += rp->tx_skbuff[entry]->len;
+ rp->stats.tx_packets++;
++ done++;
+ }
+ /* Free the original skb. */
+ if (rp->tx_skbuff_dma[entry]) {
+@@ -1470,23 +1499,25 @@
+ rp->tx_skbuff[entry]->len,
+ PCI_DMA_TODEVICE);
+ }
+- dev_kfree_skb_irq(rp->tx_skbuff[entry]);
++ dev_kfree_skb_any(rp->tx_skbuff[entry]);
+ rp->tx_skbuff[entry] = NULL;
+ entry = (++rp->dirty_tx) % TX_RING_SIZE;
+ }
++ spin_unlock_irq(&rp->lock);
++
+ if ((rp->cur_tx - rp->dirty_tx) < TX_QUEUE_LEN - 4)
+ netif_wake_queue(dev);
+
+- spin_unlock(&rp->lock);
++ return done;
+ }
+
+ /* This routine is logically part of the interrupt handler, but isolated
+ for clarity and better register allocation. */
+-static void rhine_rx(struct net_device *dev)
++static int rhine_rx(struct net_device *dev)
+ {
+ struct rhine_private *rp = netdev_priv(dev);
+ int entry = rp->cur_rx % RX_RING_SIZE;
+- int boguscnt = rp->dirty_rx + RX_RING_SIZE - rp->cur_rx;
++ int done = 0;
+
+ if (debug > 4) {
+ printk(KERN_DEBUG "%s: rhine_rx(), entry %d status %8.8x.\n",
+@@ -1503,8 +1534,6 @@
+ if (debug > 4)
+ printk(KERN_DEBUG "rhine_rx() status is %8.8x.\n",
+ desc_status);
+- if (--boguscnt < 0)
+- break;
+ if ((desc_status & (RxWholePkt | RxErr)) != RxWholePkt) {
+ if ((desc_status & RxWholePkt) != RxWholePkt) {
+ printk(KERN_WARNING "%s: Oversized Ethernet "
+@@ -1528,9 +1557,7 @@
+ if (desc_status & 0x0004) rp->stats.rx_frame_errors++;
+ if (desc_status & 0x0002) {
+ /* this can also be updated outside the interrupt handler */
+- spin_lock(&rp->lock);
+ rp->stats.rx_crc_errors++;
+- spin_unlock(&rp->lock);
+ }
+ }
+ } else {
+@@ -1558,6 +1585,7 @@
+ rp->rx_buf_sz,
+ PCI_DMA_FROMDEVICE);
+ } else {
++ int i;
+ skb = rp->rx_skbuff[entry];
+ if (skb == NULL) {
+ printk(KERN_ERR "%s: Inconsistent Rx "
+@@ -1566,6 +1594,14 @@
+ break;
+ }
+ rp->rx_skbuff[entry] = NULL;
++
++ /* align the data to the ip header - should be faster than using rx_copybreak */
++ for (i = pkt_len - (pkt_len % 4); i >= 0; i -= 4) {
++ put_unaligned(*((u32 *) (skb->data + i)), (u32 *) (skb->data + i + 2));
++ }
++ skb->data += 2;
++ skb->tail += 2;
++
+ skb_put(skb, pkt_len);
+ pci_unmap_single(rp->pdev,
+ rp->rx_skbuff_dma[entry],
+@@ -1573,10 +1609,11 @@
+ PCI_DMA_FROMDEVICE);
+ }
+ skb->protocol = eth_type_trans(skb, dev);
+- netif_rx(skb);
++ netif_receive_skb(skb);
+ dev->last_rx = jiffies;
+ rp->stats.rx_bytes += pkt_len;
+ rp->stats.rx_packets++;
++ done++;
+ }
+ entry = (++rp->cur_rx) % RX_RING_SIZE;
+ rp->rx_head_desc = &rp->rx_ring[entry];
+@@ -1587,7 +1624,7 @@
+ struct sk_buff *skb;
+ entry = rp->dirty_rx % RX_RING_SIZE;
+ if (rp->rx_skbuff[entry] == NULL) {
+- skb = dev_alloc_skb(rp->rx_buf_sz);
++ skb = dev_alloc_skb(rp->rx_buf_sz + 4);
+ rp->rx_skbuff[entry] = skb;
+ if (skb == NULL)
+ break; /* Better luck next round. */
+@@ -1600,6 +1637,8 @@
+ }
+ rp->rx_ring[entry].rx_status = cpu_to_le32(DescOwn);
+ }
++
++ return done;
+ }
+
+ /*
+@@ -1649,11 +1688,11 @@
+
+ }
+
+-static void rhine_error(struct net_device *dev, int intr_status)
++static void rhine_error(struct net_device *dev)
+ {
+ struct rhine_private *rp = netdev_priv(dev);
+ void __iomem *ioaddr = rp->base;
+-
++ u32 intr_status = rp->istat;
+ spin_lock(&rp->lock);
+
+ if (intr_status & IntrLinkChange)
+@@ -1898,6 +1937,7 @@
+
+ /* Disable interrupts by clearing the interrupt mask. */
+ iowrite16(0x0000, ioaddr + IntrEnable);
++ rp->imask = 0;
+
+ /* Stop the chip's Tx and Rx processes. */
+ iowrite16(CmdStop, ioaddr + ChipCmd);
+@@ -1912,6 +1952,9 @@
+ free_tbufs(dev);
+ free_ring(dev);
+
++ writeb(0x80, ioaddr + 0xa1);
++ pci_set_power_state(rp->pdev, 3);
++
+ return 0;
+ }
+
+@@ -1941,6 +1984,7 @@
+ return; /* Nothing to do for non-WOL adapters */
+
+ rhine_power_init(dev);
++ netif_poll_disable(dev);
+
+ /* Make sure we use pattern 0, 1 and not 4, 5 */
+ if (rp->quirks & rq6patterns)
diff --git a/target/linux/sibyte-2.6/Makefile b/target/linux/sibyte-2.6/Makefile
new file mode 100644
index 0000000000..30fa1a85a1
--- /dev/null
+++ b/target/linux/sibyte-2.6/Makefile
@@ -0,0 +1,22 @@
+#
+# 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
+
+LINUX_VERSION:=2.6.17
+LINUX_RELEASE:=1
+LINUX_KERNEL_MD5SUM:=37ddefe96625502161f075b9d907f21e
+
+include ./config
+include $(INCLUDE_DIR)/kernel.mk
+include $(INCLUDE_DIR)/kernel-build.mk
+
+$(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked
+ [ -d ../generic-$(KERNEL)/patches ] && $(PATCH) $(LINUX_DIR) ../generic-$(KERNEL)/patches
+ [ -d ./patches ] && $(PATCH) $(LINUX_DIR) ./patches
+ @$(CP) config $(LINUX_DIR)/.config
+ touch $@
+
diff --git a/target/linux/sibyte-2.6/config b/target/linux/sibyte-2.6/config
new file mode 100644
index 0000000000..79c4c72f06
--- /dev/null
+++ b/target/linux/sibyte-2.6/config
@@ -0,0 +1,1313 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16.4
+# Fri Apr 21 16:08:33 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+CONFIG_SIBYTE_SWARM=y
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_SIBYTE_SB1250=y
+CONFIG_SIBYTE_SB1xxx_SOC=y
+# CONFIG_CPU_SB1_PASS_1 is not set
+# CONFIG_CPU_SB1_PASS_2_1250 is not set
+# CONFIG_CPU_SB1_PASS_2_2 is not set
+CONFIG_CPU_SB1_PASS_4=y
+# CONFIG_CPU_SB1_PASS_2_112x is not set
+# CONFIG_CPU_SB1_PASS_3 is not set
+CONFIG_SIBYTE_HAS_LDT=y
+# CONFIG_SIMULATION is not set
+# CONFIG_SB1_CEX_ALWAYS_FATAL is not set
+# CONFIG_SB1_CERR_STALL is not set
+CONFIG_SIBYTE_CFE=y
+CONFIG_SIBYTE_CFE_CONSOLE=y
+# CONFIG_SIBYTE_BUS_WATCHER is not set
+# CONFIG_SIBYTE_SB1250_PROF is not set
+# CONFIG_SIBYTE_TBPROF is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DMA_COHERENT=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+CONFIG_CPU_SB1=y
+CONFIG_SYS_HAS_CPU_SB1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+# CONFIG_32BIT is not set
+CONFIG_64BIT=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_SIBYTE_DMA_PAGEOPS is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_PREEMPT_BKL is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_INITRAMFS_SOURCE="../root"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+CONFIG_STOP_MACHINE=y
+
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+# CONFIG_IOSCHED_NOOP is not set
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is noet set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_BUILD_ELF64=y
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_MIPS32_O32=y
+# CONFIG_MIPS32_N32 is not set
+CONFIG_BINFMT_ELF32=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+CONFIG_IPSEC_NAT_TRAVERSAL=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=y
+CONFIG_TCP_CONG_SCALABLE=m
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_BRIDGE_NETFILTER is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NETFILTER_XTABLES=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=y
+CONFIG_IP_NF_IRC=y
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_LAYER7=m
+# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_IPP2P=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TIME=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
+# CONFIG_IP_NF_MATCH_POLICY is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_IMQ=m
+# CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_TARGET_ROUTE=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_SAME is not set
+# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+CONFIG_IP_NF_NAT_IRC=y
+CONFIG_IP_NF_NAT_FTP=y
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_IP_NF_SET=m
+CONFIG_IP_NF_SET_MAX=256
+CONFIG_IP_NF_SET_HASHSIZE=1024
+CONFIG_IP_NF_SET_IPMAP=m
+CONFIG_IP_NF_SET_MACIPMAP=m
+CONFIG_IP_NF_SET_PORTMAP=m
+CONFIG_IP_NF_SET_IPHASH=m
+CONFIG_IP_NF_SET_NETHASH=m
+CONFIG_IP_NF_SET_IPTREE=m
+CONFIG_IP_NF_MATCH_SET=m
+CONFIG_IP_NF_TARGET_SET=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+# CONFIG_IP6_NF_MATCH_RT is not set
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
+# CONFIG_IP6_NF_MATCH_AHESP is not set
+CONFIG_IP6_NF_MATCH_EUI64=m
+# CONFIG_IP6_NF_MATCH_POLICY is not set
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_IMQ=m
+# CONFIG_IP6_NF_TARGET_LOG is not set
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_ROUTE=m
+CONFIG_IP6_NF_MANGLE=m
+# CONFIG_IP6_NF_TARGET_HL is not set
+# CONFIG_IP6_NF_RAW is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+CONFIG_ATM_CLIP_NO_ICMP=y
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+CONFIG_ATM_BR2684_IPFILTER=y
+CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=y
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_ESFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+# CONFIG_NET_SCH_NETEM is not set
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+CONFIG_AX25=m
+# CONFIG_AX25_DAMA_SLAVE is not set
+# CONFIG_NETROM is not set
+# CONFIG_ROSE is not set
+
+#
+# AX.25 network device drivers
+#
+CONFIG_MKISS=m
+# CONFIG_6PACK is not set
+# CONFIG_BPQETHER is not set
+# CONFIG_BAYCOM_SER_FDX is not set
+# CONFIG_BAYCOM_SER_HDX is not set
+# CONFIG_YAM is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_IMQ=m
+# CONFIG_IMQ_BEHAVIOR_AA is not set
+# CONFIG_IMQ_BEHAVIOR_AB is not set
+CONFIG_IMQ_BEHAVIOR_BA=y
+# CONFIG_IMQ_BEHAVIOR_BB is not set
+CONFIG_IMQ_NUM_DEVS=2
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_NET_SB1250_MAC=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+# CONFIG_HOSTAP_PLX is not set
+# CONFIG_HOSTAP_PCI is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+CONFIG_ATM_DUMMY=m
+CONFIG_ATM_TCP=m
+# CONFIG_ATM_LANAI is not set
+# CONFIG_ATM_ENI is not set
+# CONFIG_ATM_FIRESTREAM is not set
+# CONFIG_ATM_ZATM is not set
+# CONFIG_ATM_IDT77252 is not set
+# CONFIG_ATM_AMBASSADOR is not set
+# CONFIG_ATM_HORIZON is not set
+# CONFIG_ATM_FORE200E_MAYBE is not set
+# CONFIG_ATM_HE is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=m
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_SYNCLINK_GT is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_STALDRV is not set
+CONFIG_SIBYTE_SB1250_DUART=y
+CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y
+# CONFIG_AU1000_UART is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=m
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=m
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=15
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_SB1XXX_CORELIS is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/target/linux/sibyte-2.6/patches/000-DUART.patch b/target/linux/sibyte-2.6/patches/000-DUART.patch
new file mode 100644
index 0000000000..fe899f1453
--- /dev/null
+++ b/target/linux/sibyte-2.6/patches/000-DUART.patch
@@ -0,0 +1,957 @@
+diff -Nur linux-2.6.17/drivers/char/Kconfig linux-2.6.17-owrt/drivers/char/Kconfig
+--- linux-2.6.17/drivers/char/Kconfig 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/drivers/char/Kconfig 2006-06-18 12:41:36.000000000 +0200
+@@ -340,6 +340,14 @@
+ To compile this driver as a module, choose M here: the
+ module will be called istallion.
+
++config SIBYTE_SB1250_DUART
++ bool "Support for BCM1xxx onchip DUART"
++ depends on MIPS && SIBYTE_SB1xxx_SOC=y
++
++config SIBYTE_SB1250_DUART_CONSOLE
++ bool "Console on BCM1xxx DUART"
++ depends on SIBYTE_SB1250_DUART
++
+ config AU1000_UART
+ bool "Enable Au1000 UART Support"
+ depends on SERIAL_NONSTANDARD && MIPS
+diff -Nur linux-2.6.17/drivers/char/Makefile linux-2.6.17-owrt/drivers/char/Makefile
+--- linux-2.6.17/drivers/char/Makefile 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/drivers/char/Makefile 2006-06-18 12:42:57.000000000 +0200
+@@ -31,6 +31,7 @@
+ obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o
+ obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
+ obj-$(CONFIG_MOXA_SMARTIO) += mxser.o
++obj-$(CONFIG_SIBYTE_SB1250_DUART) += sb1250_duart.o
+ obj-$(CONFIG_COMPUTONE) += ip2/
+ obj-$(CONFIG_RISCOM8) += riscom8.o
+ obj-$(CONFIG_ISI) += isicom.o
+diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/char/sb1250_duart.c
+--- linux-2.6.17/drivers/char/sb1250_duart.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/drivers/char/sb1250_duart.c 2006-06-18 12:41:36.000000000 +0200
+@@ -0,0 +1,911 @@
++/*
++ * Copyright (C) 2000,2001,2002,2003,2004 Broadcom Corporation
++ *
++ * 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.
++ */
++
++/*
++ * Driver support for the on-chip sb1250 dual-channel serial port,
++ * running in asynchronous mode. Also, support for doing a serial console
++ * on one of those ports
++ */
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/serial.h>
++#include <linux/interrupt.h>
++#include <linux/module.h>
++#include <linux/console.h>
++#include <linux/kdev_t.h>
++#include <linux/major.h>
++#include <linux/termios.h>
++#include <linux/spinlock.h>
++#include <linux/irq.h>
++#include <linux/errno.h>
++#include <linux/tty.h>
++#include <linux/sched.h>
++#include <linux/tty_flip.h>
++#include <linux/timer.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <asm/delay.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/sibyte/swarm.h>
++#include <asm/sibyte/sb1250.h>
++#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
++#include <asm/sibyte/bcm1480_regs.h>
++#include <asm/sibyte/bcm1480_int.h>
++#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
++#include <asm/sibyte/sb1250_regs.h>
++#include <asm/sibyte/sb1250_int.h>
++#else
++#error invalid SiByte UART configuation
++#endif
++#include <asm/sibyte/sb1250_uart.h>
++#include <asm/war.h>
++
++#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
++#define UNIT_CHANREG(n,reg) A_BCM1480_DUART_CHANREG((n),(reg))
++#define UNIT_IMRREG(n) A_BCM1480_DUART_IMRREG(n)
++#define UNIT_INT(n) (K_BCM1480_INT_UART_0 + (n))
++#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
++#define UNIT_CHANREG(n,reg) A_DUART_CHANREG((n),(reg))
++#define UNIT_IMRREG(n) A_DUART_IMRREG(n)
++#define UNIT_INT(n) (K_INT_UART_0 + (n))
++#else
++#error invalid SiByte UART configuation
++#endif
++
++/* Toggle spewing of debugging output */
++#undef DEBUG
++
++#define DEFAULT_CFLAGS (CS8 | B115200)
++
++#define TX_INTEN 1
++#define DUART_INITIALIZED 2
++
++#define DUART_MAX_LINE 4
++char sb1250_duart_present[DUART_MAX_LINE];
++EXPORT_SYMBOL(sb1250_duart_present);
++
++/*
++ * Still not sure what the termios structures set up here are for,
++ * but we have to supply pointers to them to register the tty driver
++ */
++static struct tty_driver *sb1250_duart_driver; //, sb1250_duart_callout_driver;
++
++/*
++ * This lock protects both the open flags for all the uart states as
++ * well as the reference count for the module
++ */
++static DEFINE_SPINLOCK(open_lock);
++
++typedef struct {
++ unsigned char outp_buf[SERIAL_XMIT_SIZE];
++ unsigned int outp_head;
++ unsigned int outp_tail;
++ unsigned int outp_count;
++ spinlock_t outp_lock;
++ unsigned int open;
++ unsigned int line;
++ unsigned int last_cflags;
++ unsigned long flags;
++ struct tty_struct *tty;
++ /* CSR addresses */
++ volatile u32 *status;
++ volatile u32 *imr;
++ volatile u32 *tx_hold;
++ volatile u32 *rx_hold;
++ volatile u32 *mode_1;
++ volatile u32 *mode_2;
++ volatile u32 *clk_sel;
++ volatile u32 *cmd;
++} uart_state_t;
++
++static uart_state_t uart_states[DUART_MAX_LINE];
++
++/*
++ * Inline functions local to this module
++ */
++
++/*
++ * In bug 1956, we get glitches that can mess up uart registers. This
++ * "write-mode-1 after any register access" is the accepted
++ * workaround.
++ */
++#if SIBYTE_1956_WAR
++static unsigned int last_mode1[DUART_MAX_LINE];
++#endif
++
++static inline u32 READ_SERCSR(volatile u32 *addr, int line)
++{
++ u32 val = csr_in32(addr);
++#if SIBYTE_1956_WAR
++ csr_out32(last_mode1[line], uart_states[line].mode_1);
++#endif
++ return val;
++}
++
++static inline void WRITE_SERCSR(u32 val, volatile u32 *addr, int line)
++{
++ csr_out32(val, addr);
++#if SIBYTE_1956_WAR
++ csr_out32(last_mode1[line], uart_states[line].mode_1);
++#endif
++}
++
++static void init_duart_port(uart_state_t *port, int line)
++{
++ if (!(port->flags & DUART_INITIALIZED)) {
++ port->line = line;
++ port->status = IOADDR(UNIT_CHANREG(line, R_DUART_STATUS));
++ port->imr = IOADDR(UNIT_IMRREG(line));
++ port->tx_hold = IOADDR(UNIT_CHANREG(line, R_DUART_TX_HOLD));
++ port->rx_hold = IOADDR(UNIT_CHANREG(line, R_DUART_RX_HOLD));
++ port->mode_1 = IOADDR(UNIT_CHANREG(line, R_DUART_MODE_REG_1));
++ port->mode_2 = IOADDR(UNIT_CHANREG(line, R_DUART_MODE_REG_2));
++ port->clk_sel = IOADDR(UNIT_CHANREG(line, R_DUART_CLK_SEL));
++ port->cmd = IOADDR(UNIT_CHANREG(line, R_DUART_CMD));
++ port->flags |= DUART_INITIALIZED;
++ }
++}
++
++/*
++ * Mask out the passed interrupt lines at the duart level. This should be
++ * called while holding the associated outp_lock.
++ */
++static inline void duart_mask_ints(unsigned int line, unsigned int mask)
++{
++ uart_state_t *port = uart_states + line;
++ u64 tmp = READ_SERCSR(port->imr, line);
++ WRITE_SERCSR(tmp & ~mask, port->imr, line);
++}
++
++
++/* Unmask the passed interrupt lines at the duart level */
++static inline void duart_unmask_ints(unsigned int line, unsigned int mask)
++{
++ uart_state_t *port = uart_states + line;
++ u64 tmp = READ_SERCSR(port->imr, line);
++ WRITE_SERCSR(tmp | mask, port->imr, line);
++}
++
++static inline void transmit_char_pio(uart_state_t *us)
++{
++ struct tty_struct *tty = us->tty;
++ int blocked = 0;
++
++ if (spin_trylock(&us->outp_lock)) {
++ for (;;) {
++ if (!(READ_SERCSR(us->status, us->line) & M_DUART_TX_RDY))
++ break;
++ if (us->outp_count <= 0 || tty->stopped || tty->hw_stopped) {
++ break;
++ } else {
++ WRITE_SERCSR(us->outp_buf[us->outp_head],
++ us->tx_hold, us->line);
++ us->outp_head = (us->outp_head + 1) & (SERIAL_XMIT_SIZE-1);
++ if (--us->outp_count <= 0)
++ break;
++ }
++ udelay(10);
++ }
++ spin_unlock(&us->outp_lock);
++ } else {
++ blocked = 1;
++ }
++
++ if (!us->outp_count || tty->stopped ||
++ tty->hw_stopped || blocked) {
++ us->flags &= ~TX_INTEN;
++ duart_mask_ints(us->line, M_DUART_IMR_TX);
++ }
++
++ if (us->open &&
++ (us->outp_count < (SERIAL_XMIT_SIZE/2))) {
++ /*
++ * We told the discipline at one point that we had no
++ * space, so it went to sleep. Wake it up when we hit
++ * half empty
++ */
++ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
++ tty->ldisc.write_wakeup)
++ tty->ldisc.write_wakeup(tty);
++ wake_up_interruptible(&tty->write_wait);
++ }
++}
++
++/*
++ * Generic interrupt handler for both channels. dev_id is a pointer
++ * to the proper uart_states structure, so from that we can derive
++ * which port interrupted
++ */
++
++static irqreturn_t duart_int(int irq, void *dev_id, struct pt_regs *regs)
++{
++ uart_state_t *us = (uart_state_t *)dev_id;
++ struct tty_struct *tty = us->tty;
++ unsigned int status = READ_SERCSR(us->status, us->line);
++
++ pr_debug("DUART INT\n");
++
++ if (status & M_DUART_RX_RDY) {
++ int counter = 2048;
++ unsigned int ch;
++
++ if (status & M_DUART_OVRUN_ERR)
++ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
++ if (status & M_DUART_PARITY_ERR) {
++ printk("Parity error!\n");
++ } else if (status & M_DUART_FRM_ERR) {
++ printk("Frame error!\n");
++ }
++
++ while (counter > 0) {
++ if (!(READ_SERCSR(us->status, us->line) & M_DUART_RX_RDY))
++ break;
++ ch = READ_SERCSR(us->rx_hold, us->line);
++ tty_insert_flip_char(tty, ch, 0);
++ udelay(1);
++ counter--;
++ }
++ tty_flip_buffer_push(tty);
++ }
++
++ if (status & M_DUART_TX_RDY) {
++ transmit_char_pio(us);
++ }
++
++ return IRQ_HANDLED;
++}
++
++/*
++ * Actual driver functions
++ */
++
++/* Return the number of characters we can accomodate in a write at this instant */
++static int duart_write_room(struct tty_struct *tty)
++{
++ uart_state_t *us = (uart_state_t *) tty->driver_data;
++ int retval;
++
++ retval = SERIAL_XMIT_SIZE - us->outp_count;
++
++ pr_debug("duart_write_room called, returning %i\n", retval);
++
++ return retval;
++}
++
++/* memcpy the data from src to destination, but take extra care if the
++ data is coming from user space */
++static inline int copy_buf(char *dest, const char *src, int size, int from_user)
++{
++ if (from_user) {
++ (void) copy_from_user(dest, src, size);
++ } else {
++ memcpy(dest, src, size);
++ }
++ return size;
++}
++
++/*
++ * Buffer up to count characters from buf to be written. If we don't have
++ * other characters buffered, enable the tx interrupt to start sending
++ */
++static int duart_write(struct tty_struct *tty, const unsigned char *buf,
++ int count)
++{
++ uart_state_t *us;
++ int c, t, total = 0;
++ unsigned long flags;
++
++ if (!tty) return 0;
++
++ us = tty->driver_data;
++ if (!us) return 0;
++
++ pr_debug("duart_write called for %i chars by %i (%s)\n", count, current->pid, current->comm);
++
++ spin_lock_irqsave(&us->outp_lock, flags);
++
++ for (;;) {
++ c = count;
++
++ t = SERIAL_XMIT_SIZE - us->outp_tail;
++ if (t < c) c = t;
++
++ t = SERIAL_XMIT_SIZE - 1 - us->outp_count;
++ if (t < c) c = t;
++
++ if (c <= 0) break;
++
++ memcpy(us->outp_buf + us->outp_tail, buf, c);
++
++ us->outp_count += c;
++ us->outp_tail = (us->outp_tail + c) & (SERIAL_XMIT_SIZE - 1);
++ buf += c;
++ count -= c;
++ total += c;
++ }
++
++ spin_unlock_irqrestore(&us->outp_lock, flags);
++
++ if (us->outp_count && !tty->stopped &&
++ !tty->hw_stopped && !(us->flags & TX_INTEN)) {
++ us->flags |= TX_INTEN;
++ duart_unmask_ints(us->line, M_DUART_IMR_TX);
++ }
++
++ return total;
++}
++
++
++/* Buffer one character to be written. If there's not room for it, just drop
++ it on the floor. This is used for echo, among other things */
++static void duart_put_char(struct tty_struct *tty, u_char ch)
++{
++ uart_state_t *us = (uart_state_t *) tty->driver_data;
++ unsigned long flags;
++
++ pr_debug("duart_put_char called. Char is %x (%c)\n", (int)ch, ch);
++
++ spin_lock_irqsave(&us->outp_lock, flags);
++
++ if (us->outp_count == SERIAL_XMIT_SIZE) {
++ spin_unlock_irqrestore(&us->outp_lock, flags);
++ return;
++ }
++
++ us->outp_buf[us->outp_tail] = ch;
++ us->outp_tail = (us->outp_tail + 1) &(SERIAL_XMIT_SIZE-1);
++ us->outp_count++;
++
++ spin_unlock_irqrestore(&us->outp_lock, flags);
++}
++
++static void duart_flush_chars(struct tty_struct * tty)
++{
++ uart_state_t *port;
++
++ if (!tty) return;
++
++ port = tty->driver_data;
++
++ if (!port) return;
++
++ if (port->outp_count <= 0 || tty->stopped || tty->hw_stopped) {
++ return;
++ }
++
++ port->flags |= TX_INTEN;
++ duart_unmask_ints(port->line, M_DUART_IMR_TX);
++}
++
++/* Return the number of characters in the output buffer that have yet to be
++ written */
++static int duart_chars_in_buffer(struct tty_struct *tty)
++{
++ uart_state_t *us = (uart_state_t *) tty->driver_data;
++ int retval;
++
++ retval = us->outp_count;
++
++ pr_debug("duart_chars_in_buffer returning %i\n", retval);
++
++ return retval;
++}
++
++/* Kill everything we haven't yet shoved into the FIFO. Turn off the
++ transmit interrupt since we've nothing more to transmit */
++static void duart_flush_buffer(struct tty_struct *tty)
++{
++ uart_state_t *us = (uart_state_t *) tty->driver_data;
++ unsigned long flags;
++
++ pr_debug("duart_flush_buffer called\n");
++ spin_lock_irqsave(&us->outp_lock, flags);
++ us->outp_head = us->outp_tail = us->outp_count = 0;
++ spin_unlock_irqrestore(&us->outp_lock, flags);
++
++ wake_up_interruptible(&us->tty->write_wait);
++ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
++ tty->ldisc.write_wakeup)
++ tty->ldisc.write_wakeup(tty);
++}
++
++
++/* See sb1250 user manual for details on these registers */
++static inline void duart_set_cflag(unsigned int line, unsigned int cflag)
++{
++ unsigned int mode_reg1 = 0, mode_reg2 = 0;
++ unsigned int clk_divisor;
++ uart_state_t *port = uart_states + line;
++
++ switch (cflag & CSIZE) {
++ case CS7:
++ mode_reg1 |= V_DUART_BITS_PER_CHAR_7;
++
++ default:
++ /* We don't handle CS5 or CS6...is there a way we're supposed to flag this?
++ right now we just force them to CS8 */
++ mode_reg1 |= 0x0;
++ break;
++ }
++ if (cflag & CSTOPB) {
++ mode_reg2 |= M_DUART_STOP_BIT_LEN_2;
++ }
++ if (!(cflag & PARENB)) {
++ mode_reg1 |= V_DUART_PARITY_MODE_NONE;
++ }
++ if (cflag & PARODD) {
++ mode_reg1 |= M_DUART_PARITY_TYPE_ODD;
++ }
++
++ /* Formula for this is (5000000/baud)-1, but we saturate
++ at 12 bits, which means we can't actually do anything less
++ that 1200 baud */
++ switch (cflag & CBAUD) {
++ case B200:
++ case B300:
++ case B1200: clk_divisor = 4095; break;
++ case B1800: clk_divisor = 2776; break;
++ case B2400: clk_divisor = 2082; break;
++ case B4800: clk_divisor = 1040; break;
++ default:
++ case B9600: clk_divisor = 519; break;
++ case B19200: clk_divisor = 259; break;
++ case B38400: clk_divisor = 129; break;
++ case B57600: clk_divisor = 85; break;
++ case B115200: clk_divisor = 42; break;
++ }
++ WRITE_SERCSR(mode_reg1, port->mode_1, port->line);
++ WRITE_SERCSR(mode_reg2, port->mode_2, port->line);
++ WRITE_SERCSR(clk_divisor, port->clk_sel, port->line);
++ port->last_cflags = cflag;
++}
++
++
++/* Handle notification of a termios change. */
++static void duart_set_termios(struct tty_struct *tty, struct termios *old)
++{
++ uart_state_t *us = (uart_state_t *) tty->driver_data;
++
++ pr_debug("duart_set_termios called by %i (%s)\n", current->pid, current->comm);
++ if (old && tty->termios->c_cflag == old->c_cflag)
++ return;
++ duart_set_cflag(us->line, tty->termios->c_cflag);
++}
++
++static int get_serial_info(uart_state_t *us, struct serial_struct * retinfo) {
++
++ struct serial_struct tmp;
++
++ memset(&tmp, 0, sizeof(tmp));
++
++ tmp.type=PORT_SB1250;
++ tmp.line=us->line;
++ tmp.port=UNIT_CHANREG(tmp.line,0);
++ tmp.irq=UNIT_INT(tmp.line);
++ tmp.xmit_fifo_size=16; /* fixed by hw */
++ tmp.baud_base=5000000;
++ tmp.io_type=SERIAL_IO_MEM;
++
++ if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
++ return -EFAULT;
++
++ return 0;
++}
++
++static int duart_ioctl(struct tty_struct *tty, struct file * file,
++ unsigned int cmd, unsigned long arg)
++{
++ uart_state_t *us = (uart_state_t *) tty->driver_data;
++
++/* if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
++ return -ENODEV;*/
++ switch (cmd) {
++ case TIOCMGET:
++ printk("Ignoring TIOCMGET\n");
++ break;
++ case TIOCMBIS:
++ printk("Ignoring TIOCMBIS\n");
++ break;
++ case TIOCMBIC:
++ printk("Ignoring TIOCMBIC\n");
++ break;
++ case TIOCMSET:
++ printk("Ignoring TIOCMSET\n");
++ break;
++ case TIOCGSERIAL:
++ return get_serial_info(us,(struct serial_struct *) arg);
++ case TIOCSSERIAL:
++ printk("Ignoring TIOCSSERIAL\n");
++ break;
++ case TIOCSERCONFIG:
++ printk("Ignoring TIOCSERCONFIG\n");
++ break;
++ case TIOCSERGETLSR: /* Get line status register */
++ printk("Ignoring TIOCSERGETLSR\n");
++ break;
++ case TIOCSERGSTRUCT:
++ printk("Ignoring TIOCSERGSTRUCT\n");
++ break;
++ case TIOCMIWAIT:
++ printk("Ignoring TIOCMIWAIT\n");
++ break;
++ case TIOCGICOUNT:
++ printk("Ignoring TIOCGICOUNT\n");
++ break;
++ case TIOCSERGWILD:
++ printk("Ignoring TIOCSERGWILD\n");
++ break;
++ case TIOCSERSWILD:
++ printk("Ignoring TIOCSERSWILD\n");
++ break;
++ default:
++ break;
++ }
++// printk("Ignoring IOCTL %x from pid %i (%s)\n", cmd, current->pid, current->comm);
++ return -ENOIOCTLCMD;
++}
++
++/* XXXKW locking? */
++static void duart_start(struct tty_struct *tty)
++{
++ uart_state_t *us = (uart_state_t *) tty->driver_data;
++
++ pr_debug("duart_start called\n");
++
++ if (us->outp_count && !(us->flags & TX_INTEN)) {
++ us->flags |= TX_INTEN;
++ duart_unmask_ints(us->line, M_DUART_IMR_TX);
++ }
++}
++
++/* XXXKW locking? */
++static void duart_stop(struct tty_struct *tty)
++{
++ uart_state_t *us = (uart_state_t *) tty->driver_data;
++
++ pr_debug("duart_stop called\n");
++
++ if (us->outp_count && (us->flags & TX_INTEN)) {
++ us->flags &= ~TX_INTEN;
++ duart_mask_ints(us->line, M_DUART_IMR_TX);
++ }
++}
++
++/* Not sure on the semantics of this; are we supposed to wait until the stuff
++ already in the hardware FIFO drains, or are we supposed to wait until
++ we've drained the output buffer, too? I'm assuming the former, 'cause thats
++ what the other drivers seem to assume
++*/
++
++static void duart_wait_until_sent(struct tty_struct *tty, int timeout)
++{
++ uart_state_t *us = (uart_state_t *) tty->driver_data;
++ unsigned long orig_jiffies;
++
++ orig_jiffies = jiffies;
++ pr_debug("duart_wait_until_sent(%d)+\n", timeout);
++ while (!(READ_SERCSR(us->status, us->line) & M_DUART_TX_EMT)) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(1);
++ if (signal_pending(current))
++ break;
++ if (timeout && time_after(jiffies, orig_jiffies + timeout))
++ break;
++ }
++ pr_debug("duart_wait_until_sent()-\n");
++}
++
++/*
++ * duart_hangup() --- called by tty_hangup() when a hangup is signaled.
++ */
++static void duart_hangup(struct tty_struct *tty)
++{
++ uart_state_t *us = (uart_state_t *) tty->driver_data;
++
++ duart_flush_buffer(tty);
++ us->open = 0;
++ us->tty = 0;
++}
++
++/*
++ * Open a tty line. Note that this can be called multiple times, so ->open can
++ * be >1. Only set up the tty struct if this is a "new" open, e.g. ->open was
++ * zero
++ */
++static int duart_open(struct tty_struct *tty, struct file *filp)
++{
++ uart_state_t *us;
++ unsigned int line = tty->index;
++ unsigned long flags;
++
++ if ((line >= tty->driver->num) || !sb1250_duart_present[line])
++ return -ENODEV;
++
++ pr_debug("duart_open called by %i (%s), tty is %p, rw is %p, ww is %p\n",
++ current->pid, current->comm, tty, tty->read_wait,
++ tty->write_wait);
++
++ us = uart_states + line;
++ tty->driver_data = us;
++
++ spin_lock_irqsave(&open_lock, flags);
++ if (!us->open) {
++ us->tty = tty;
++ us->tty->termios->c_cflag = us->last_cflags;
++ }
++ us->open++;
++ us->flags &= ~TX_INTEN;
++ duart_unmask_ints(line, M_DUART_IMR_RX);
++ spin_unlock_irqrestore(&open_lock, flags);
++
++ return 0;
++}
++
++
++/*
++ * Close a reference count out. If reference count hits zero, null the
++ * tty, kill the interrupts. The tty_io driver is responsible for making
++ * sure we've cleared out our internal buffers before calling close()
++ */
++static void duart_close(struct tty_struct *tty, struct file *filp)
++{
++ uart_state_t *us = (uart_state_t *) tty->driver_data;
++ unsigned long flags;
++
++ pr_debug("duart_close called by %i (%s)\n", current->pid, current->comm);
++
++ if (!us || !us->open)
++ return;
++
++ spin_lock_irqsave(&open_lock, flags);
++ if (tty_hung_up_p(filp)) {
++ spin_unlock_irqrestore(&open_lock, flags);
++ return;
++ }
++
++ if (--us->open < 0) {
++ us->open = 0;
++ printk(KERN_ERR "duart: bad open count: %d\n", us->open);
++ }
++ if (us->open) {
++ spin_unlock_irqrestore(&open_lock, flags);
++ return;
++ }
++
++ spin_unlock_irqrestore(&open_lock, flags);
++
++ tty->closing = 1;
++
++ /* Stop accepting input */
++ duart_mask_ints(us->line, M_DUART_IMR_RX);
++ /* Wait for FIFO to drain */
++ while (!(READ_SERCSR(us->status, us->line) & M_DUART_TX_EMT))
++ ;
++
++ if (tty->driver->flush_buffer)
++ tty->driver->flush_buffer(tty);
++ if (tty->ldisc.flush_buffer)
++ tty->ldisc.flush_buffer(tty);
++ tty->closing = 0;
++}
++
++
++static struct tty_operations duart_ops = {
++ .open = duart_open,
++ .close = duart_close,
++ .write = duart_write,
++ .put_char = duart_put_char,
++ .flush_chars = duart_flush_chars,
++ .write_room = duart_write_room,
++ .chars_in_buffer = duart_chars_in_buffer,
++ .flush_buffer = duart_flush_buffer,
++ .ioctl = duart_ioctl,
++// .throttle = duart_throttle,
++// .unthrottle = duart_unthrottle,
++ .set_termios = duart_set_termios,
++ .stop = duart_stop,
++ .start = duart_start,
++ .hangup = duart_hangup,
++ .wait_until_sent = duart_wait_until_sent,
++};
++
++/* Initialize the sb1250_duart_present array based on SOC type. */
++static void __init sb1250_duart_init_present_lines(void)
++{
++ int i, max_lines;
++
++ /* Set the number of available units based on the SOC type. */
++ switch (soc_type) {
++ case K_SYS_SOC_TYPE_BCM1x55:
++ case K_SYS_SOC_TYPE_BCM1x80:
++ max_lines = 4;
++ break;
++ default:
++ /* Assume at least two serial ports at the normal address. */
++ max_lines = 2;
++ break;
++ }
++ if (max_lines > DUART_MAX_LINE)
++ max_lines = DUART_MAX_LINE;
++
++ for (i = 0; i < max_lines; i++)
++ sb1250_duart_present[i] = 1;
++}
++
++/* Set up the driver and register it, register the UART interrupts. This
++ is called from tty_init, or as a part of the module init */
++static int __init sb1250_duart_init(void)
++{
++ int i;
++
++ sb1250_duart_init_present_lines();
++
++ sb1250_duart_driver = alloc_tty_driver(DUART_MAX_LINE);
++ if (!sb1250_duart_driver)
++ return -ENOMEM;
++
++ sb1250_duart_driver->owner = THIS_MODULE;
++ sb1250_duart_driver->name = "duart";
++ sb1250_duart_driver->devfs_name = "duart/";
++ sb1250_duart_driver->major = TTY_MAJOR;
++ sb1250_duart_driver->minor_start = SB1250_DUART_MINOR_BASE;
++ sb1250_duart_driver->type = TTY_DRIVER_TYPE_SERIAL;
++ sb1250_duart_driver->subtype = SERIAL_TYPE_NORMAL;
++ sb1250_duart_driver->init_termios = tty_std_termios;
++ sb1250_duart_driver->flags = TTY_DRIVER_REAL_RAW;
++ tty_set_operations(sb1250_duart_driver, &duart_ops);
++
++ for (i=0; i<DUART_MAX_LINE; i++) {
++ uart_state_t *port = uart_states + i;
++
++ if (!sb1250_duart_present[i])
++ continue;
++
++ init_duart_port(port, i);
++ spin_lock_init(&port->outp_lock);
++ duart_mask_ints(i, M_DUART_IMR_ALL);
++ if (request_irq(UNIT_INT(i), duart_int, 0, "uart", port)) {
++ panic("Couldn't get uart0 interrupt line");
++ }
++ __raw_writeq(M_DUART_RX_EN|M_DUART_TX_EN,
++ IOADDR(UNIT_CHANREG(i, R_DUART_CMD)));
++ duart_set_cflag(i, DEFAULT_CFLAGS);
++ }
++
++ /* Interrupts are now active, our ISR can be called. */
++
++ if (tty_register_driver(sb1250_duart_driver)) {
++ printk(KERN_ERR "Couldn't register sb1250 duart serial driver\n");
++ put_tty_driver(sb1250_duart_driver);
++ return 1;
++ }
++ return 0;
++}
++
++/* Unload the driver. Unregister stuff, get ready to go away */
++static void __exit sb1250_duart_fini(void)
++{
++ unsigned long flags;
++ int i;
++
++ local_irq_save(flags);
++ tty_unregister_driver(sb1250_duart_driver);
++ put_tty_driver(sb1250_duart_driver);
++
++ for (i=0; i<DUART_MAX_LINE; i++) {
++ if (!sb1250_duart_present[i])
++ continue;
++ free_irq(UNIT_INT(i), &uart_states[i]);
++ disable_irq(UNIT_INT(i));
++ }
++ local_irq_restore(flags);
++}
++
++module_init(sb1250_duart_init);
++module_exit(sb1250_duart_fini);
++MODULE_DESCRIPTION("SB1250 Duart serial driver");
++MODULE_AUTHOR("Broadcom Corp.");
++
++#ifdef CONFIG_SIBYTE_SB1250_DUART_CONSOLE
++
++/*
++ * Serial console stuff. Very basic, polling driver for doing serial
++ * console output. The console_sem is held by the caller, so we
++ * shouldn't be interrupted for more console activity.
++ * XXXKW What about getting interrupted by uart driver activity?
++ */
++
++void serial_outc(unsigned char c, int line)
++{
++ uart_state_t *port = uart_states + line;
++ while (!(READ_SERCSR(port->status, line) & M_DUART_TX_RDY)) ;
++ WRITE_SERCSR(c, port->tx_hold, line);
++ while (!(READ_SERCSR(port->status, port->line) & M_DUART_TX_EMT)) ;
++}
++
++static void ser_console_write(struct console *cons, const char *s,
++ unsigned int count)
++{
++ int line = cons->index;
++ uart_state_t *port = uart_states + line;
++ u32 imr;
++
++ imr = READ_SERCSR(port->imr, line);
++ WRITE_SERCSR(0, port->imr, line);
++ while (count--) {
++ if (*s == '\n')
++ serial_outc('\r', line);
++ serial_outc(*s++, line);
++ }
++ WRITE_SERCSR(imr, port->imr, line);
++}
++
++static struct tty_driver *ser_console_device(struct console *c, int *index)
++{
++ *index = c->index;
++ return sb1250_duart_driver;
++}
++
++static int ser_console_setup(struct console *cons, char *str)
++{
++ int i;
++
++ sb1250_duart_init_present_lines();
++
++ for (i=0; i<DUART_MAX_LINE; i++) {
++ uart_state_t *port = uart_states + i;
++
++ if (!sb1250_duart_present[i])
++ continue;
++
++ init_duart_port(port, i);
++#if SIBYTE_1956_WAR
++ last_mode1[i] = V_DUART_PARITY_MODE_NONE|V_DUART_BITS_PER_CHAR_8;
++#endif
++ WRITE_SERCSR(V_DUART_PARITY_MODE_NONE|V_DUART_BITS_PER_CHAR_8,
++ port->mode_1, i);
++ WRITE_SERCSR(M_DUART_STOP_BIT_LEN_1,
++ port->mode_2, i);
++ WRITE_SERCSR(V_DUART_BAUD_RATE(115200),
++ port->clk_sel, i);
++ WRITE_SERCSR(M_DUART_RX_EN|M_DUART_TX_EN,
++ port->cmd, i);
++ }
++ return 0;
++}
++
++static struct console sb1250_ser_cons = {
++ .name = "duart",
++ .write = ser_console_write,
++ .device = ser_console_device,
++ .setup = ser_console_setup,
++ .flags = CON_PRINTBUFFER,
++ .index = -1,
++};
++
++static int __init sb1250_serial_console_init(void)
++{
++ register_console(&sb1250_ser_cons);
++ return 0;
++}
++
++console_initcall(sb1250_serial_console_init);
++
++#endif /* CONFIG_SIBYTE_SB1250_DUART_CONSOLE */
+diff -Nur linux-2.6.17/include/linux/serial.h linux-2.6.17-owrt/include/linux/serial.h
+--- linux-2.6.17/include/linux/serial.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/linux/serial.h 2006-06-18 12:41:36.000000000 +0200
+@@ -76,7 +76,8 @@
+ #define PORT_16654 11
+ #define PORT_16850 12
+ #define PORT_RSA 13 /* RSA-DV II/S card */
+-#define PORT_MAX 13
++#define PORT_SB1250 14
++#define PORT_MAX 14
+
+ #define SERIAL_IO_PORT 0
+ #define SERIAL_IO_HUB6 1
diff --git a/target/linux/sibyte-2.6/patches/001-bcm112x_ax.patch b/target/linux/sibyte-2.6/patches/001-bcm112x_ax.patch
new file mode 100644
index 0000000000..c80d4aea54
--- /dev/null
+++ b/target/linux/sibyte-2.6/patches/001-bcm112x_ax.patch
@@ -0,0 +1,17 @@
+--- linux-2.6.16.4/arch/mips/sibyte/sb1250/setup.c 2006-04-21 16:16:18.000000000 -0700
++++ linux-2.6.16.4/arch/mips/sibyte/sb1250/setup.c 2006-04-21 16:15:22.000000000 -0700
+@@ -140,6 +140,14 @@
+ periph_rev = 3;
+ pass_str = "A2";
+ break;
++ case K_SYS_REVISION_BCM112x_A3:
++ periph_rev = 3;
++ pass_str = "A3";
++ break;
++ case K_SYS_REVISION_BCM112x_A4:
++ periph_rev = 3;
++ pass_str = "A4";
++ break;
+ default:
+ prom_printf("Unknown %s rev %x\n", soc_str, soc_pass);
+ ret = 1;
diff --git a/target/linux/uml-2.6/Makefile b/target/linux/uml-2.6/Makefile
new file mode 100644
index 0000000000..59f02b3340
--- /dev/null
+++ b/target/linux/uml-2.6/Makefile
@@ -0,0 +1,21 @@
+#
+# 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
+
+LINUX_VERSION:=2.6.17
+LINUX_RELEASE:=1
+LINUX_KERNEL_MD5SUM:=37ddefe96625502161f075b9d907f21e
+
+include ./config
+include $(INCLUDE_DIR)/kernel.mk
+include $(INCLUDE_DIR)/kernel-build.mk
+
+$(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked
+ [ -d ../generic-$(KERNEL)/patches ] && $(PATCH) $(LINUX_DIR) ../generic-$(KERNEL)/patches
+ [ -d ./patches ] && $(PATCH) $(LINUX_DIR) ./patches
+ @$(CP) config $(LINUX_DIR)/.config
+ touch $@
diff --git a/target/linux/uml-2.6/README b/target/linux/uml-2.6/README
new file mode 100644
index 0000000000..84bf114867
--- /dev/null
+++ b/target/linux/uml-2.6/README
@@ -0,0 +1,45 @@
+Openwrt inside a user mode linux. Why would we even want this many ask?
+
+There are potentially a lot of reasons, one obvious one to me, it allows
+folks to 'kick the tires' without actually flashing up any hardware. It's
+also a great environment for porting over packages, you can get a package
+fully functional in the uclibc root environment inside a uml without actually
+disturbing your 'real router', and then rebuild for a specific target once
+it's fully tested.
+
+This is a first stab at a build that 'just works' and there will be more
+cleanup to come. The simple directions are:-
+
+Configure for uml target
+Configure with an ext2 root file system
+build it all
+
+In your bin directory you will find a kernel and an ext2 root file system
+when it's finished. Just run it like this:-
+
+bin/openwrt-uml-2.6-vmlinux ubd0=bin/openwrt-uml-2.6-ext2.img con=null ssl=null ssl0=fd:0,fd:1 con0=null,fd:1
+
+The uml will start, and eventually the serial console of the uml will be at your
+console prompt. If you would like it in xterms, substitute con=xterm and con0=xterm.
+No networking is configured, but, it's a starting point. The resulting file system
+has just enough free space to start kicking the tires and playing in the world of
+'embedded routers' along with all the resource restrictions that come with that
+world.
+
+To configure networking and more, refer to the user mode linux documentation online.
+A quick start goes along this line. install the uml-utilities packages so you have
+the uml switch in and running, then add a command param to your uml start like this
+
+eth0=daemon,00:01:01:01:01:01,unix,/<your uml switch control socket here>
+
+With that in, and uml networking actually functional (can be a challenge at times),
+you should be able to ifconfig the interface and talk to the host side, or, if you
+bridged the uml switch to your host network, you should be able to run udhcp and be
+away with networking off to the world. Again, if you are unfamiliar with uml and
+uml networking, please read the docs and how-to stuff available on the net. It does
+take some fiddling to get it started and working right the first time, but after that,
+it opens up a whole new world of virtual machines.
+
+
+
+http://user-mode-linux.sourceforge.net/
diff --git a/target/linux/uml-2.6/config b/target/linux/uml-2.6/config
new file mode 100644
index 0000000000..08665583c5
--- /dev/null
+++ b/target/linux/uml-2.6/config
@@ -0,0 +1,904 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Tue Aug 22 17:19:49 2006
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_UML=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_IRQ_RELEASE_METHOD=y
+
+#
+# UML-specific options
+#
+# CONFIG_MODE_TT is not set
+# CONFIG_STATIC_LINK is not set
+CONFIG_MODE_SKAS=y
+
+#
+# Host processor type and features
+#
+# CONFIG_M386 is not set
+CONFIG_M486=y
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+# CONFIG_M686 is not set
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP2 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_F00F_BUG=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_ALIGNMENT_16=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_UML_X86=y
+# CONFIG_64BIT is not set
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_HOST_2G_2G=y
+CONFIG_TOP_ADDR=0x80000000
+# CONFIG_3_LEVEL_PGTABLES is not set
+CONFIG_STUB_CODE=0x7fffe000
+CONFIG_STUB_DATA=0x7ffff000
+CONFIG_STUB_START=0x7fffe000
+CONFIG_ARCH_HAS_SC_SIGNALS=y
+CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_LD_SCRIPT_DYN=y
+CONFIG_NET=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+CONFIG_HOSTFS=y
+# CONFIG_HPPFS is not set
+CONFIG_MCONSOLE=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_NEST_LEVEL=0
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_STACK_ORDER=2
+CONFIG_UML_REAL_TIME_CLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_UBD=y
+CONFIG_BLK_DEV_UBD_SYNC=y
+CONFIG_BLK_DEV_COW_COMMON=y
+# CONFIG_MMAPPER is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Character Devices
+#
+CONFIG_STDERR_CONSOLE=y
+CONFIG_STDIO_CONSOLE=y
+CONFIG_SSL=y
+CONFIG_NULL_CHAN=y
+CONFIG_PORT_CHAN=y
+CONFIG_PTY_CHAN=y
+CONFIG_TTY_CHAN=y
+CONFIG_XTERM_CHAN=y
+# CONFIG_NOCONFIG_CHAN is not set
+CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
+CONFIG_CON_CHAN="xterm"
+CONFIG_SSL_CHAN="pty"
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_UML_WATCHDOG=m
+CONFIG_UML_SOUND=m
+CONFIG_SOUND=m
+CONFIG_HOSTAUDIO=m
+CONFIG_UML_RANDOM=y
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Networking
+#
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+# CONFIG_IP_ROUTE_FWMARK is not set
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_MULTIPATH_CACHED=y
+CONFIG_IP_ROUTE_MULTIPATH_RR=y
+CONFIG_IP_ROUTE_MULTIPATH_RANDOM=y
+CONFIG_IP_ROUTE_MULTIPATH_WRANDOM=y
+CONFIG_IP_ROUTE_MULTIPATH_DRR=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IPSEC_NAT_TRAVERSAL=y
+# CONFIG_IP_MROUTE is not set
+CONFIG_ARPD=y
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+CONFIG_IPV6_ROUTER_PREF=y
+# CONFIG_IPV6_ROUTE_INFO is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NETFILTER_XTABLES=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_IPP2P=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TIME=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_MATCH_LAYER7=m
+# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_IMQ=y
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_ROUTE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_IP_NF_SET=m
+CONFIG_IP_NF_SET_MAX=256
+CONFIG_IP_NF_SET_HASHSIZE=1024
+CONFIG_IP_NF_SET_IPMAP=m
+CONFIG_IP_NF_SET_MACIPMAP=m
+CONFIG_IP_NF_SET_PORTMAP=m
+CONFIG_IP_NF_SET_IPHASH=m
+CONFIG_IP_NF_SET_NETHASH=m
+CONFIG_IP_NF_SET_IPTREE=m
+CONFIG_IP_NF_MATCH_SET=m
+CONFIG_IP_NF_TARGET_SET=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_IMQ=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_ROUTE=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_ESFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_IEEE80211=m
+CONFIG_IEEE80211_DEBUG=y
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# UML Network Devices
+#
+CONFIG_UML_NET=y
+CONFIG_UML_NET_ETHERTAP=y
+CONFIG_UML_NET_TUNTAP=y
+CONFIG_UML_NET_SLIP=y
+CONFIG_UML_NET_DAEMON=y
+CONFIG_UML_NET_MCAST=y
+# CONFIG_UML_NET_PCAP is not set
+CONFIG_UML_NET_SLIRP=y
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_IFB is not set
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_IMQ=m
+# CONFIG_IMQ_BEHAVIOR_AA is not set
+# CONFIG_IMQ_BEHAVIOR_AB is not set
+CONFIG_IMQ_BEHAVIOR_BA=y
+# CONFIG_IMQ_BEHAVIOR_BB is not set
+CONFIG_IMQ_NUM_DEVS=2
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+CONFIG_WAN=y
+# CONFIG_SYNCLINK_SYNCPPP is not set
+# CONFIG_HDLC is not set
+# CONFIG_DLCI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_SLIP=m
+# CONFIG_SLIP_COMPRESSED is not set
+# CONFIG_SLIP_SMART is not set
+# CONFIG_SLIP_MODE_SLIP6 is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+# CONFIG_REISERFS_FS_XATTR is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+# CONFIG_QFMT_V2 is not set
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_EMBEDDED=y
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+# CONFIG_CIFS_STATS2 is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_AES_586 is not set
+# CONFIG_CRYPTO_AES_X86_64 is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=m
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID5=m
+# CONFIG_MD_RAID5_RESHAPE is not set
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+# CONFIG_INPUT is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_UNWIND_INFO=y
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_GPROF is not set
+# CONFIG_GCOV is not set
+# CONFIG_SYSCALL_DEBUG is not set
diff --git a/target/linux/x86-2.6/Makefile b/target/linux/x86-2.6/Makefile
new file mode 100644
index 0000000000..59f02b3340
--- /dev/null
+++ b/target/linux/x86-2.6/Makefile
@@ -0,0 +1,21 @@
+#
+# 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
+
+LINUX_VERSION:=2.6.17
+LINUX_RELEASE:=1
+LINUX_KERNEL_MD5SUM:=37ddefe96625502161f075b9d907f21e
+
+include ./config
+include $(INCLUDE_DIR)/kernel.mk
+include $(INCLUDE_DIR)/kernel-build.mk
+
+$(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked
+ [ -d ../generic-$(KERNEL)/patches ] && $(PATCH) $(LINUX_DIR) ../generic-$(KERNEL)/patches
+ [ -d ./patches ] && $(PATCH) $(LINUX_DIR) ./patches
+ @$(CP) config $(LINUX_DIR)/.config
+ touch $@
diff --git a/target/linux/x86-2.6/config b/target/linux/x86-2.6/config
new file mode 100644
index 0000000000..d43bd801d9
--- /dev/null
+++ b/target/linux/x86-2.6/config
@@ -0,0 +1,2077 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Mon Oct 9 15:42:06 2006
+#
+CONFIG_X86_32=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86=y
+CONFIG_MMU=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE="../../root"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+CONFIG_UID16=y
+# CONFIG_VM86 is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# Processor type and features
+#
+CONFIG_SCx200HR_TIMER=y
+# CONFIG_SMP is not set
+CONFIG_X86_PC=y
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_NUMAQ is not set
+# CONFIG_X86_SUMMIT is not set
+# CONFIG_X86_BIGSMP is not set
+# CONFIG_X86_VISWS is not set
+# CONFIG_X86_GENERICARCH is not set
+# CONFIG_X86_ES7000 is not set
+# CONFIG_M386 is not set
+CONFIG_M486=y
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+# CONFIG_M686 is not set
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP2 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+# CONFIG_X86_GENERIC is not set
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=4
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_F00F_BUG=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_ALIGNMENT_16=y
+# CONFIG_HPET_TIMER is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_X86_UP_APIC is not set
+# CONFIG_X86_MCE is not set
+# CONFIG_TOSHIBA is not set
+# CONFIG_I8K is not set
+# CONFIG_X86_REBOOTFIXUPS is not set
+# CONFIG_MICROCODE is not set
+# CONFIG_X86_MSR is not set
+# CONFIG_X86_CPUID is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+# CONFIG_DELL_RBU is not set
+# CONFIG_DCDBAS is not set
+CONFIG_NOHIGHMEM=y
+# CONFIG_HIGHMEM4G is not set
+# CONFIG_HIGHMEM64G is not set
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_MTRR is not set
+# CONFIG_REGPARM is not set
+# CONFIG_SECCOMP is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_KEXEC is not set
+CONFIG_PHYSICAL_START=0x100000
+
+#
+# Power management options (ACPI, APM)
+#
+# CONFIG_PM is not set
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+# CONFIG_ACPI is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+
+#
+# CPUFreq processor drivers
+#
+# CONFIG_X86_POWERNOW_K6 is not set
+# CONFIG_X86_POWERNOW_K7 is not set
+# CONFIG_X86_POWERNOW_K8 is not set
+CONFIG_X86_GX_SUSPMOD=m
+# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
+# CONFIG_X86_SPEEDSTEP_ICH is not set
+# CONFIG_X86_SPEEDSTEP_SMI is not set
+# CONFIG_X86_P4_CLOCKMOD is not set
+# CONFIG_X86_CPUFREQ_NFORCE2 is not set
+# CONFIG_X86_LONGRUN is not set
+
+#
+# shared options
+#
+# CONFIG_X86_SPEEDSTEP_LIB is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_ISA_DMA_API=y
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+CONFIG_SCx200=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+# CONFIG_PCMCIA_LOAD_CIS is not set
+# CONFIG_PCMCIA_IOCTL is not set
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=m
+# CONFIG_YENTA_O2 is not set
+# CONFIG_YENTA_RICOH is not set
+# CONFIG_YENTA_TI is not set
+# CONFIG_YENTA_TOSHIBA is not set
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_PROBE=y
+CONFIG_PCCARD_NONSTATIC=m
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+CONFIG_IPSEC_NAT_TRAVERSAL=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=y
+CONFIG_TCP_CONG_SCALABLE=m
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+CONFIG_IPV6_ROUTER_PREF=y
+# CONFIG_IPV6_ROUTE_INFO is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_BRIDGE_NETFILTER is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NETFILTER_XTABLES=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=y
+CONFIG_IP_NF_IRC=y
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_IPP2P=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TIME=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_MATCH_LAYER7=m
+# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_IMQ=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_TARGET_ROUTE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+CONFIG_IP_NF_NAT_IRC=y
+CONFIG_IP_NF_NAT_FTP=y
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_IP_NF_SET=m
+CONFIG_IP_NF_SET_MAX=256
+CONFIG_IP_NF_SET_HASHSIZE=1024
+CONFIG_IP_NF_SET_IPMAP=m
+CONFIG_IP_NF_SET_MACIPMAP=m
+CONFIG_IP_NF_SET_PORTMAP=m
+CONFIG_IP_NF_SET_IPHASH=m
+CONFIG_IP_NF_SET_NETHASH=m
+CONFIG_IP_NF_SET_IPTREE=m
+CONFIG_IP_NF_MATCH_SET=m
+CONFIG_IP_NF_TARGET_SET=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_IMQ=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_ROUTE=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+CONFIG_ATM_CLIP_NO_ICMP=y
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+CONFIG_ATM_BR2684_IPFILTER=y
+CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_ESFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+# CONFIG_NET_SCH_NETEM is not set
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+CONFIG_AX25=m
+# CONFIG_AX25_DAMA_SLAVE is not set
+# CONFIG_NETROM is not set
+# CONFIG_ROSE is not set
+
+#
+# AX.25 network device drivers
+#
+CONFIG_MKISS=m
+# CONFIG_6PACK is not set
+# CONFIG_BPQETHER is not set
+# CONFIG_DMASCC is not set
+# CONFIG_SCC is not set
+# CONFIG_BAYCOM_SER_FDX is not set
+# CONFIG_BAYCOM_SER_HDX is not set
+# CONFIG_YAM is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIDTL1 is not set
+# CONFIG_BT_HCIBT3C is not set
+# CONFIG_BT_HCIBLUECARD is not set
+# CONFIG_BT_HCIBTUART is not set
+# CONFIG_BT_HCIVHCI is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_IEEE80211_SOFTMAC is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_TS5500 is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+CONFIG_MTD_BLOCK2MTD=y
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_ISAPNP=y
+# CONFIG_PNPBIOS is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_IDEPNP is not set
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_ATIIXP is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_CS5535 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+CONFIG_BLK_DEV_SC1200=y
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SIS5513 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_IMQ=m
+# CONFIG_IMQ_BEHAVIOR_AA is not set
+# CONFIG_IMQ_BEHAVIOR_AB is not set
+CONFIG_IMQ_BEHAVIOR_BA=y
+# CONFIG_IMQ_BEHAVIOR_BB is not set
+CONFIG_IMQ_NUM_DEVS=2
+CONFIG_TUN=m
+# CONFIG_NET_SB1000 is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+# CONFIG_EL3 is not set
+# CONFIG_3C515 is not set
+CONFIG_VORTEX=m
+# CONFIG_TYPHOON is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+CONFIG_FORCEDETH=m
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+# CONFIG_FEALNX is not set
+CONFIG_NATSEMI=m
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+CONFIG_VIA_RHINE=m
+# CONFIG_VIA_RHINE_MMIO is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+CONFIG_SIS190=m
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+# CONFIG_NORTEL_HERMES is not set
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+# CONFIG_PCMCIA_HERMES is not set
+# CONFIG_PCMCIA_SPECTRUM is not set
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+# CONFIG_PCMCIA_WL3501 is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+CONFIG_ATM_DUMMY=m
+CONFIG_ATM_TCP=m
+# CONFIG_ATM_LANAI is not set
+# CONFIG_ATM_ENI is not set
+# CONFIG_ATM_FIRESTREAM is not set
+# CONFIG_ATM_ZATM is not set
+# CONFIG_ATM_NICSTAR is not set
+# CONFIG_ATM_IDT77252 is not set
+# CONFIG_ATM_AMBASSADOR is not set
+# CONFIG_ATM_HORIZON is not set
+# CONFIG_ATM_IA is not set
+# CONFIG_ATM_FORE200E_MAYBE is not set
+# CONFIG_ATM_HE is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=m
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+# CONFIG_SERIAL_8250_PNP is not set
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+# CONFIG_ALIM1535_WDT is not set
+# CONFIG_ALIM7101_WDT is not set
+# CONFIG_SC520_WDT is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+# CONFIG_IBMASR is not set
+# CONFIG_WAFER_WDT is not set
+# CONFIG_I6300ESB_WDT is not set
+# CONFIG_I8XX_TCO is not set
+CONFIG_SC1200_WDT=m
+CONFIG_SCx200_WDT=m
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+# CONFIG_CPU5_WDT is not set
+# CONFIG_W83627HF_WDT is not set
+# CONFIG_W83877F_WDT is not set
+# CONFIG_W83977F_WDT is not set
+# CONFIG_MACHZ_WDT is not set
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# ISA-based Watchdog Cards
+#
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_NVRAM=y
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_SONYPI is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_MWAVE is not set
+CONFIG_SCx200_GPIO=m
+# CONFIG_CS5535_GPIO is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_ELEKTOR is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+CONFIG_SCx200_I2C=m
+CONFIG_SCx200_I2C_SCL=12
+CONFIG_SCx200_I2C_SDA=13
+CONFIG_SCx200_ACB=m
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+# CONFIG_IBM_ASM is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+# CONFIG_VIDEO_V4L1 is not set
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_CX88 is not set
+
+#
+# Encoders and Decoders
+#
+# CONFIG_VIDEO_MSP3400 is not set
+# CONFIG_VIDEO_CS53L32A is not set
+# CONFIG_VIDEO_WM8775 is not set
+# CONFIG_VIDEO_WM8739 is not set
+# CONFIG_VIDEO_CX25840 is not set
+# CONFIG_VIDEO_SAA7127 is not set
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+
+#
+# V4L USB devices
+#
+
+#
+# Radio Adapters
+#
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_RTCTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ISA devices
+#
+# CONFIG_SND_ADLIB is not set
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+# CONFIG_SND_CS4236 is not set
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+# CONFIG_SND_ES18XX is not set
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+# CONFIG_SND_OPL3SA2 is not set
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+# CONFIG_SND_MIRO is not set
+# CONFIG_SND_SB8 is not set
+# CONFIG_SND_SB16 is not set
+# CONFIG_SND_SBAWE is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+# CONFIG_SND_WAVEFRONT is not set
+
+#
+# PCI devices
+#
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS5535AUDIO is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+# CONFIG_SND_USB_USX2Y is not set
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+CONFIG_USB_SERIAL_BELKIN=m
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+CONFIG_USB_SERIAL_VISOR=m
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+# CONFIG_USB_CXACRU is not set
+CONFIG_USB_UEAGLEATM=m
+# CONFIG_USB_XUSBATM is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+# CONFIG_LEDS_TRIGGER_IDE_DISK is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+# CONFIG_EDAC is not set
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=m
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=m
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+# CONFIG_KPROBES is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_STACK_BACKTRACE_COLS=2
+CONFIG_DOUBLEFAULT=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_586=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+# CONFIG_CRYPTO_DEV_PADLOCK is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_KTIME_SCALAR=y
diff --git a/target/linux/x86-2.6/patches/100-scx200_hr_timer.patch b/target/linux/x86-2.6/patches/100-scx200_hr_timer.patch
new file mode 100644
index 0000000000..38fc16a74c
--- /dev/null
+++ b/target/linux/x86-2.6/patches/100-scx200_hr_timer.patch
@@ -0,0 +1,320 @@
+SCx200 High Resolution Timer Patch for Linux 2.6
+http://www.gnusto.com/scx200-hr-timer.html
+
+diff -Naurp linux-2.6.12-rc6.orig/arch/i386/Kconfig linux-2.6.12-rc6/arch/i386/Kconfig
+--- linux-2.6.12-rc6.orig/arch/i386/Kconfig 2005-06-07 14:56:02.000000000 +0100
++++ linux-2.6.12-rc6/arch/i386/Kconfig 2005-06-07 16:43:19.000000000 +0100
+@@ -458,6 +458,17 @@ config HPET_EMULATE_RTC
+ bool "Provide RTC interrupt"
+ depends on HPET_TIMER && RTC=y
+
++config SCx200HR_TIMER
++ bool "NatSemi SCx200 27MHz High-Resolution Timer Support"
++ help
++ Some of the AMD (formerly National Semiconductor) Geode
++ processors, notably the SC1100, suffer from a buggy time
++ stamp counter which causes them to lose time when the
++ processor is sleeping. Enable this option to use the
++ on-board 27Mz high-resolution timer to keep time instead.
++ depends on (SCx200)
++ default n
++
+ config SMP
+ bool "Symmetric multi-processing support"
+ ---help---
+diff -Naurp linux-2.6.12-rc6.orig/arch/i386/kernel/scx200.c linux-2.6.12-rc6/arch/i386/kernel/scx200.c
+--- linux-2.6.12-rc6.orig/arch/i386/kernel/scx200.c 2005-06-07 14:56:02.000000000 +0100
++++ linux-2.6.12-rc6/arch/i386/kernel/scx200.c 2005-06-07 16:43:19.000000000 +0100
+@@ -27,6 +27,10 @@ long scx200_gpio_shadow[2];
+
+ unsigned scx200_cb_base = 0;
+
++#ifdef CONFIG_SCx200HR_TIMER
++extern void __devinit scx200hr_timer_enable(void);
++#endif
++
+ static struct pci_device_id scx200_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) },
+@@ -83,6 +87,9 @@ static int __devinit scx200_probe(struct
+ printk(KERN_INFO NAME ": Configuration Block base 0x%x\n", scx200_cb_base);
+ }
+
++#ifdef CONFIG_SCx200HR_TIMER
++ scx200hr_timer_enable();
++#endif
+ return 0;
+ }
+
+diff -Naurp linux-2.6.12-rc6.orig/arch/i386/kernel/timers/Makefile linux-2.6.12-rc6/arch/i386/kernel/timers/Makefile
+--- linux-2.6.12-rc6.orig/arch/i386/kernel/timers/Makefile 2004-03-11 18:21:13.000000000 +0000
++++ linux-2.6.12-rc6/arch/i386/kernel/timers/Makefile 2005-06-07 16:43:19.000000000 +0100
+@@ -5,5 +5,6 @@
+ obj-y := timer.o timer_none.o timer_tsc.o timer_pit.o common.o
+
+ obj-$(CONFIG_X86_CYCLONE_TIMER) += timer_cyclone.o
++obj-$(CONFIG_SCx200HR_TIMER) += timer_scx200hr.o
+ obj-$(CONFIG_HPET_TIMER) += timer_hpet.o
+ obj-$(CONFIG_X86_PM_TIMER) += timer_pm.o
+diff -Naurp linux-2.6.12-rc6.orig/arch/i386/kernel/timers/timer.c linux-2.6.12-rc6/arch/i386/kernel/timers/timer.c
+--- linux-2.6.12-rc6.orig/arch/i386/kernel/timers/timer.c 2004-12-26 14:07:37.000000000 +0000
++++ linux-2.6.12-rc6/arch/i386/kernel/timers/timer.c 2005-06-07 16:43:19.000000000 +0100
+@@ -13,6 +13,9 @@
+ #endif
+ /* list of timers, ordered by preference, NULL terminated */
+ static struct init_timer_opts* __initdata timers[] = {
++#ifdef CONFIG_SCx200HR_TIMER
++ &timer_scx200hr_init,
++#endif
+ #ifdef CONFIG_X86_CYCLONE_TIMER
+ &timer_cyclone_init,
+ #endif
+diff -Naurp linux-2.6.12-rc6.orig/arch/i386/kernel/timers/timer_scx200hr.c linux-2.6.12-rc6/arch/i386/kernel/timers/timer_scx200hr.c
+--- linux-2.6.12-rc6.orig/arch/i386/kernel/timers/timer_scx200hr.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.12-rc6/arch/i386/kernel/timers/timer_scx200hr.c 2005-06-07 16:43:19.000000000 +0100
+@@ -0,0 +1,220 @@
++/*
++ * Copyright (C) 2005 Ted Phelps
++ *
++ * This is a clock driver for the Geode SCx200's 27MHz high-resolution
++ * timer as the system clock replacing its buggy time stamp counter.
++ *
++ * Based on parts of timer_hpet.c, timer_tsc.c and timer_pit.c.
++ *
++ * 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 <asm/timer.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/seq_file.h>
++#include <linux/scx200.h>
++
++#define NAME "scx200hr"
++
++/* Read the clock */
++#define SCx200HR_CLOCK() inl(scx200_cb_base + SCx200_TIMER_OFFSET)
++
++/* High-resolution timer configuration address */
++#define SCx200_TMCNFG_OFFSET (SCx200_TIMER_OFFSET + 5)
++
++/* Set this bit to disable the 27 MHz input clock */
++#define HR_TM27MPD (1 << 2)
++
++/* Set this bit to update the count-up timer once per cycle of the
++ * 27MHz timer, clear it to update the timer once every 27 cycles
++ * (effectively producing a 1MHz counter) */
++#define HR_TMCLKSEL (1 << 1)
++
++/* Set this bit to enable the high-resolution timer interrupt */
++#define HR_TMEN (1 << 0)
++
++/* The frequency of the timer. Change this to 27000000 and set
++ * HR_TMCLKSEL in scx200hr_enable to run at the faster clock rate. At
++ * this point in time there is no point in doing so since times are
++ * recorded in usec except for the monotonic clock, which is only used
++ * by the hangcheck-timer. */
++#define HR_FREQ 1000000
++
++/* The number of cycles of the high-resolution timer we expect to see
++ * in a single tick. Note that the result is <<8 for greater precision*/
++#define HR_CYCLES_PER_TICK \
++ (SH_DIV(HR_FREQ / 1000000 * TICK_NSEC, 1000, 8))
++
++/* The number of cycles of the high-resolution timer we expect to see
++ * in one microsecond, <<8 */
++#define HR_CYCLES_PER_US ((HR_FREQ / 1000000) << 8)
++
++
++/* The value of the timer at the last interrupt */
++static u32 clock_at_last_interrupt;
++
++/* The number of high-resolution clock cycles beyond what we would
++ have expected that the last tick occurred, <<8 for greater precision */
++static long clock_delay;
++
++/* The total number of timer nanoseconds between the time the timer
++ * went live and the most recent tick. */
++static unsigned long long total_ns;
++
++/* A lock to guard access to the monotonic clock-related variables
++ * (total_ns and clocal_at_last_interrupt). Note that these are also
++ * protected by the xtime lock. */
++static seqlock_t hr_lock = SEQLOCK_UNLOCKED;
++
++/* Nonzero if the timer has been selected */
++static int enable_scx200hr;
++
++static int __init scx200hr_init(char *override)
++{
++ /* Watch for a command-line clock= override */
++ if (override[0] && strncmp(override, NAME, sizeof(NAME) - 1) != 0) {
++ return -ENODEV;
++ }
++
++ /* Note that we should try to enable this timer once the
++ * configuration block address is known */
++ printk(KERN_WARNING NAME ": timer not yet accessible; will probe later.\n");
++ enable_scx200hr = 1;
++ return -EAGAIN;
++}
++
++/* Called by the timer interrupt. The xtime_lock will be held. */
++static void mark_offset_scx200hr(void)
++{
++ u32 now, delta;
++
++ /* Avoid races between the interrupt handler and monotonic_clock */
++ write_seqlock(&hr_lock);
++
++ /* Determine how many cycles have elapsed since the last interrupt */
++ now = SCx200HR_CLOCK();
++ delta = (now - clock_at_last_interrupt) << 8;
++ clock_at_last_interrupt = now;
++
++ /* Update the total us count and remainder */
++ total_ns += (delta * 1000) / HR_CYCLES_PER_US;
++
++ /* The monotonic clock is safe now */
++ write_sequnlock(&hr_lock);
++
++ /* Adjust for interrupt handling delay */
++ delta += clock_delay;
++
++ /* The high-resolution timer is driven by a different crystal
++ * to the main CPU, so there's no guarantee that the 1KHz
++ * interrupt rate will coincide with the timer. This keeps
++ * the jiffies count in line with the high-resolution timer,
++ * which makes it possible for NTP to do its magic */
++ if (delta < HR_CYCLES_PER_TICK) {
++#if 1
++ /* Didn't go over 1000us: decrement jiffies to balance
++ * out increment in do_timer. This will cause some
++ * jitter if the frequency offset is large, as that
++ * adjustment will be applied about 1ms late. */
++ jiffies_64--;
++ clock_delay = delta;
++#else /* !1 */
++ clock_delay = 0;
++#endif /* 1 */
++ } else if (delta < (HR_CYCLES_PER_TICK << 1) + (HR_CYCLES_PER_TICK >> 1)) {
++ clock_delay = delta - HR_CYCLES_PER_TICK;
++ } else {
++ jiffies_64 += delta / HR_CYCLES_PER_TICK - 2;
++ clock_delay = HR_CYCLES_PER_TICK + delta % HR_CYCLES_PER_TICK;
++ }
++}
++
++/* Called by gettimeofday(). Returns the number of microseconds since
++ * the last interrupt. This is called with the xtime_lock held.*/
++static unsigned long get_offset_scx200hr(void)
++{
++ u32 delta;
++
++ /* Get the time now and determine how many cycles have
++ * transpired since the interrupt, adjusting for timer
++ * interrupt jitter. */
++ delta = ((SCx200HR_CLOCK() - clock_at_last_interrupt) << 8) + clock_delay;
++
++ /* Convert from cycles<<8 to microseconds */
++ return delta / HR_CYCLES_PER_US;
++}
++
++/* Returns the number of nanoseconds since the init of the timer. */
++static unsigned long long monotonic_clock_scx200hr(void)
++{
++ u32 delta, seq;
++ unsigned long long ns;
++
++ /* This function is *not* called with xtime_lock held, so we
++ * need to get the hr_lock to ensure we're not competing with
++ * mark_offset_scx200hr. */
++ do {
++ seq = read_seqbegin(&hr_lock);
++ ns = total_ns;
++ delta = SCx200HR_CLOCK() - clock_at_last_interrupt;
++ } while (read_seqretry(&hr_lock, seq));
++
++ /* Convert cycles to microseconds and add. */
++ return ns + delta * 1000 / HR_CYCLES_PER_US;
++}
++
++/* scx200hr timer_opts struct */
++struct timer_opts timer_scx200hr = {
++ .name = NAME,
++ .mark_offset = mark_offset_scx200hr,
++ .get_offset = get_offset_scx200hr,
++ .monotonic_clock = monotonic_clock_scx200hr,
++ .delay = NULL
++};
++
++/* And the init_timer struct */
++struct init_timer_opts __devinitdata timer_scx200hr_init = {
++ .init = scx200hr_init,
++ .opts = &timer_scx200hr
++};
++
++
++/* Switch from the original timer to the high-resolution timer */
++void __devinit scx200hr_timer_enable(void)
++{
++ /* Make sure the timer was requested and that the
++ * configuration block is present */
++ if (!enable_scx200hr || !scx200_cb_present()) {
++ return;
++ }
++
++ /* Reserve the timer region for ourselves */
++ if (!request_region(scx200_cb_base + SCx200_TIMER_OFFSET,
++ SCx200_TIMER_SIZE,
++ "NatSemi SCx200 High-Resolution Timer")) {
++ printk(KERN_WARNING NAME ": unable to lock timer region\n");
++ return;
++ }
++
++ /* Configure the timer */
++ outb(0, scx200_cb_base + SCx200_TMCNFG_OFFSET);
++
++ /* Record the current value of the timer. */
++ clock_at_last_interrupt = SCx200HR_CLOCK();
++
++ /* Get the current value of the monotonic clock */
++ total_ns = cur_timer->monotonic_clock();
++
++ /* Switch from the original timer functions to ours, but keep
++ * the current delay function since loops_per_jiffy will have
++ * been computed using that */
++ timer_scx200hr.delay = cur_timer->delay;
++ cur_timer = &timer_scx200hr;
++
++ printk(KERN_INFO "switching to scx200 high-resolution timer (%lu cpt)\n",
++ HR_CYCLES_PER_TICK);
++}
+diff -Naurp linux-2.6.12-rc6.orig/include/asm-i386/timer.h linux-2.6.12-rc6/include/asm-i386/timer.h
+--- linux-2.6.12-rc6.orig/include/asm-i386/timer.h 2005-06-07 14:56:11.000000000 +0100
++++ linux-2.6.12-rc6/include/asm-i386/timer.h 2005-06-07 16:43:19.000000000 +0100
+@@ -50,6 +50,9 @@ extern struct init_timer_opts timer_tsc_
+ #ifdef CONFIG_X86_CYCLONE_TIMER
+ extern struct init_timer_opts timer_cyclone_init;
+ #endif
++#ifdef CONFIG_SCx200HR_TIMER
++extern struct init_timer_opts timer_scx200hr_init;
++#endif
+
+ extern unsigned long calibrate_tsc(void);
+ extern void init_cpu_khz(void);
+diff -Naurp linux-2.6.12-rc6.orig/include/linux/scx200.h linux-2.6.12-rc6/include/linux/scx200.h
+--- linux-2.6.12-rc6.orig/include/linux/scx200.h 2005-06-07 14:56:11.000000000 +0100
++++ linux-2.6.12-rc6/include/linux/scx200.h 2005-06-07 16:43:19.000000000 +0100
+@@ -32,7 +32,7 @@ extern unsigned scx200_cb_base;
+
+ /* High Resolution Timer */
+ #define SCx200_TIMER_OFFSET 0x08
+-#define SCx200_TIMER_SIZE 0x05
++#define SCx200_TIMER_SIZE 0x06
+
+ /* Clock Generators */
+ #define SCx200_CLOCKGEN_OFFSET 0x10
diff --git a/target/linux/xscale-2.6/Makefile b/target/linux/xscale-2.6/Makefile
new file mode 100644
index 0000000000..59f02b3340
--- /dev/null
+++ b/target/linux/xscale-2.6/Makefile
@@ -0,0 +1,21 @@
+#
+# 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
+
+LINUX_VERSION:=2.6.17
+LINUX_RELEASE:=1
+LINUX_KERNEL_MD5SUM:=37ddefe96625502161f075b9d907f21e
+
+include ./config
+include $(INCLUDE_DIR)/kernel.mk
+include $(INCLUDE_DIR)/kernel-build.mk
+
+$(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked
+ [ -d ../generic-$(KERNEL)/patches ] && $(PATCH) $(LINUX_DIR) ../generic-$(KERNEL)/patches
+ [ -d ./patches ] && $(PATCH) $(LINUX_DIR) ./patches
+ @$(CP) config $(LINUX_DIR)/.config
+ touch $@
diff --git a/target/linux/xscale-2.6/config b/target/linux/xscale-2.6/config
new file mode 100644
index 0000000000..4df1a4ca3c
--- /dev/null
+++ b/target/linux/xscale-2.6/config
@@ -0,0 +1,1384 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Sun Aug 6 11:18:40 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_SHMEM is not set
+CONFIG_SLAB=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+CONFIG_ARCH_IXP4XX=y
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+
+#
+# Intel IXP4xx Implementation Options
+#
+
+#
+# IXP4xx Platforms
+#
+# CONFIG_MACH_NSLU2 is not set
+# CONFIG_ARCH_AVILA is not set
+# CONFIG_ARCH_ADI_COYOTE is not set
+CONFIG_MACH_GATEWAY7001=y
+# CONFIG_ARCH_IXDP425 is not set
+# CONFIG_MACH_IXDPG425 is not set
+# CONFIG_MACH_IXDP465 is not set
+# CONFIG_ARCH_PRPMC1100 is not set
+# CONFIG_MACH_NAS100D is not set
+# CONFIG_MACH_GTWX5715 is not set
+
+#
+# IXP4xx Options
+#
+CONFIG_DMABOUNCE=y
+# CONFIG_IXP4XX_INDIRECT_PCI is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_XSCALE_PMU=y
+
+#
+# Bus support
+#
+CONFIG_PCI=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=jffs2 noinitrd console=ttyS0,115200"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IPSEC_NAT_TRAVERSAL=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=y
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+CONFIG_TCP_CONG_VEGAS=m
+# CONFIG_TCP_CONG_SCALABLE is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+CONFIG_NETFILTER_XTABLES=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=y
+CONFIG_IP_NF_IRC=y
+# CONFIG_IP_NF_NETBIOS_NS is not set
+# CONFIG_IP_NF_TFTP is not set
+# CONFIG_IP_NF_AMANDA is not set
+# CONFIG_IP_NF_PPTP is not set
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_IPP2P=m
+CONFIG_IP_NF_MATCH_TOS=m
+# CONFIG_IP_NF_MATCH_TIME is not set
+# CONFIG_IP_NF_MATCH_RECENT is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_DSCP is not set
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
+CONFIG_IP_NF_MATCH_LAYER7=m
+# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_IMQ=m
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_IP_NF_TARGET_TCPMSS=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_ROUTE=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_SAME is not set
+# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+CONFIG_IP_NF_NAT_IRC=y
+CONFIG_IP_NF_NAT_FTP=y
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_TOS=m
+# CONFIG_IP_NF_TARGET_ECN is not set
+# CONFIG_IP_NF_TARGET_DSCP is not set
+# CONFIG_IP_NF_TARGET_TTL is not set
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_SET is not set
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+# CONFIG_IP6_NF_MATCH_RT is not set
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+# CONFIG_IP6_NF_MATCH_OWNER is not set
+# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
+CONFIG_IP6_NF_MATCH_AH=m
+# CONFIG_IP6_NF_MATCH_EUI64 is not set
+CONFIG_IP6_NF_FILTER=m
+# CONFIG_IP6_NF_TARGET_LOG is not set
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_ROUTE=m
+# CONFIG_IP6_NF_MANGLE is not set
+# CONFIG_IP6_NF_RAW is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_ESFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+# CONFIG_NET_SCH_NETEM is not set
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_IEEE80211_SOFTMAC is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_IXP4XX=y
+# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_IMQ=m
+# CONFIG_IMQ_BEHAVIOR_AA is not set
+# CONFIG_IMQ_BEHAVIOR_AB is not set
+CONFIG_IMQ_BEHAVIOR_BA=y
+# CONFIG_IMQ_BEHAVIOR_BB is not set
+CONFIG_IMQ_NUM_DEVS=2
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+# CONFIG_IPW_QOS is not set
+# CONFIG_IPW2200_DEBUG is not set
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+CONFIG_WAN=y
+# CONFIG_DSCC4 is not set
+# CONFIG_LANMEDIA is not set
+# CONFIG_SYNCLINK_SYNCPPP is not set
+CONFIG_HDLC=m
+CONFIG_HDLC_RAW=y
+# CONFIG_HDLC_RAW_ETH is not set
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+
+#
+# X.25/LAPB support is disabled
+#
+# CONFIG_PCI200SYN is not set
+# CONFIG_WANXL is not set
+# CONFIG_PC300 is not set
+# CONFIG_FARSYNC is not set
+CONFIG_DLCI=m
+CONFIG_DLCI_COUNT=24
+CONFIG_DLCI_MAX=8
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_IXP4XX_WATCHDOG=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_BANDWIDTH=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/target/linux/xscale-2.6/patches/001-gateway_7001.patch b/target/linux/xscale-2.6/patches/001-gateway_7001.patch
new file mode 100644
index 0000000000..d144758b24
--- /dev/null
+++ b/target/linux/xscale-2.6/patches/001-gateway_7001.patch
@@ -0,0 +1,163 @@
+diff -Nur linux-2.6.17/arch/arm/boot/compressed/head-xscale.S linux-2.6.17-owrt/arch/arm/boot/compressed/head-xscale.S
+--- linux-2.6.17/arch/arm/boot/compressed/head-xscale.S 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/arch/arm/boot/compressed/head-xscale.S 2006-08-05 17:02:21.000000000 +0200
+@@ -47,6 +47,11 @@
+ orr r7, r7, #(MACH_TYPE_GTWX5715 & 0xff00)
+ #endif
+
++#ifdef CONFIG_MACH_GATEWAY7001
++ mov r7, #(MACH_TYPE_GATEWAY7001 & 0xff)
++ orr r7, r7, #(MACH_TYPE_GATEWAY7001 & 0xff00)
++#endif
++
+ #ifdef CONFIG_ARCH_IXP2000
+ mov r1, #-1
+ mov r0, #0xd6000000
+diff -Nur linux-2.6.17/arch/arm/mach-ixp4xx/coyote-setup.c linux-2.6.17-owrt/arch/arm/mach-ixp4xx/coyote-setup.c
+--- linux-2.6.17/arch/arm/mach-ixp4xx/coyote-setup.c 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/arch/arm/mach-ixp4xx/coyote-setup.c 2006-08-05 17:02:21.000000000 +0200
+@@ -1,9 +1,10 @@
+ /*
+ * arch/arm/mach-ixp4xx/coyote-setup.c
+ *
+- * Board setup for ADI Engineering and IXDGP425 boards
++ * Board setup for ADI Engineering, IXDGP425 and Gateway 7001 boards
+ *
+ * Copyright (C) 2003-2005 MontaVista Software, Inc.
++ * Copyright (C) 2006 Imre Kaloz <Kaloz@openwrt.org>
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ */
+@@ -111,6 +112,19 @@
+ MACHINE_END
+ #endif
+
++#ifdef CONFIG_MACH_GATEWAY7001
++MACHINE_START(GATEWAY7001, "Gateway 7001")
++ /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
++ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
++ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
++ .map_io = ixp4xx_map_io,
++ .init_irq = ixp4xx_init_irq,
++ .timer = &ixp4xx_timer,
++ .boot_params = 0x0100,
++ .init_machine = coyote_init,
++MACHINE_END
++#endif
++
+ /*
+ * IXDPG425 is identical to Coyote except for which serial port
+ * is connected.
+diff -Nur linux-2.6.17/arch/arm/mach-ixp4xx/gateway7001-pci.c linux-2.6.17-owrt/arch/arm/mach-ixp4xx/gateway7001-pci.c
+--- linux-2.6.17/arch/arm/mach-ixp4xx/gateway7001-pci.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.17-owrt/arch/arm/mach-ixp4xx/gateway7001-pci.c 2006-08-06 10:37:35.000000000 +0200
+@@ -0,0 +1,67 @@
++/*
++ * arch/arch/mach-ixp4xx/gateway7001-pci.c
++ *
++ * PCI setup routines for Gateway 7001
++ *
++ * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
++ *
++ * based on coyote-pci.c:
++ * Copyright (C) 2002 Jungo Software Technologies.
++ * Copyright (C) 2003 MontaVista Softwrae, Inc.
++ *
++ * Maintainer: Imre Kaloz <kaloz@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/kernel.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++
++#include <asm/mach-types.h>
++#include <asm/hardware.h>
++#include <asm/irq.h>
++
++#include <asm/mach/pci.h>
++
++extern void ixp4xx_pci_preinit(void);
++extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
++extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
++
++void __init gateway7001_pci_preinit(void)
++{
++ set_irq_type(IRQ_IXP4XX_GPIO10, IRQT_LOW);
++ set_irq_type(IRQ_IXP4XX_GPIO11, IRQT_LOW);
++
++ ixp4xx_pci_preinit();
++}
++
++static int __init gateway7001_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ if (slot == 0)
++ return IRQ_IXP4XX_GPIO10;
++ else if (slot == 1)
++ return IRQ_IXP4XX_GPIO11;
++ else return -1;
++}
++
++struct hw_pci gateway7001_pci __initdata = {
++ .nr_controllers = 1,
++ .preinit = gateway7001_pci_preinit,
++ .swizzle = pci_std_swizzle,
++ .setup = ixp4xx_setup,
++ .scan = ixp4xx_scan_bus,
++ .map_irq = gateway7001_map_irq,
++};
++
++int __init gateway7001_pci_init(void)
++{
++ if (machine_is_gateway7001())
++ pci_common_init(&gateway7001_pci);
++ return 0;
++}
++
++subsys_initcall(gateway7001_pci_init);
+diff -Nur linux-2.6.17/arch/arm/mach-ixp4xx/Kconfig linux-2.6.17-owrt/arch/arm/mach-ixp4xx/Kconfig
+--- linux-2.6.17/arch/arm/mach-ixp4xx/Kconfig 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/arch/arm/mach-ixp4xx/Kconfig 2006-08-05 17:04:13.000000000 +0200
+@@ -33,6 +33,14 @@
+ Engineering Coyote Gateway Reference Platform. For more
+ information on this platform, see <file:Documentation/arm/IXP4xx>.
+
++config MACH_GATEWAY7001
++ bool "Gateway 7001"
++ select PCI
++ help
++ Say 'Y' here if you want your kernel to support Gateway's
++ 7001 Access Point. For more information on this platform,
++ see http://openwrt.org
++
+ config ARCH_IXDP425
+ bool "IXDP425"
+ select PCI
+diff -Nur linux-2.6.17/arch/arm/mach-ixp4xx/Makefile linux-2.6.17-owrt/arch/arm/mach-ixp4xx/Makefile
+--- linux-2.6.17/arch/arm/mach-ixp4xx/Makefile 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/arch/arm/mach-ixp4xx/Makefile 2006-08-05 17:02:21.000000000 +0200
+@@ -11,4 +11,5 @@
+ obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o gtwx5715-setup.o
+ obj-$(CONFIG_MACH_NSLU2) += nslu2-pci.o nslu2-setup.o nslu2-power.o
+ obj-$(CONFIG_MACH_NAS100D) += nas100d-pci.o nas100d-setup.o nas100d-power.o
++obj-$(CONFIG_MACH_GATEWAY7001) += gateway7001-pci.o coyote-setup.o
+
+diff -Nur linux-2.6.17/include/asm-arm/arch-ixp4xx/uncompress.h linux-2.6.17-owrt/include/asm-arm/arch-ixp4xx/uncompress.h
+--- linux-2.6.17/include/asm-arm/arch-ixp4xx/uncompress.h 2006-06-18 03:49:35.000000000 +0200
++++ linux-2.6.17-owrt/include/asm-arm/arch-ixp4xx/uncompress.h 2006-08-05 17:03:32.000000000 +0200
+@@ -38,9 +38,9 @@
+ static __inline__ void __arch_decomp_setup(unsigned long arch_id)
+ {
+ /*
+- * Coyote and gtwx5715 only have UART2 connected
++ * Some targets only have UART2 connected
+ */
+- if (machine_is_adi_coyote() || machine_is_gtwx5715())
++ if (machine_is_adi_coyote() || machine_is_gtwx5715() || machine_is_gateway7001())
+ uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS;
+ else
+ uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS;
diff --git a/target/sdk/Config.in b/target/sdk/Config.in
new file mode 100644
index 0000000000..3ead29600c
--- /dev/null
+++ b/target/sdk/Config.in
@@ -0,0 +1,9 @@
+config SDK
+ bool "Build the OpenWrt SDK"
+ default y if ALL
+ help
+ This is essentially a stripped-down version of the buildroot
+ with a precompiled toolchain. It can be used to develop and
+ test packages for OpenWrt before including them in the buildroot
+
+
diff --git a/target/sdk/Makefile b/target/sdk/Makefile
new file mode 100644
index 0000000000..a8413562b2
--- /dev/null
+++ b/target/sdk/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.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_OS:=$(shell uname -s)
+PKG_CPU:=$(shell uname -m)
+
+SDK_NAME:=OpenWrt-SDK-$(BOARD)-$(KERNEL)-for-$(PKG_OS)-$(PKG_CPU)
+SDK_BUILD_DIR:=$(BUILD_DIR)/$(SDK_NAME)
+
+all: compile
+
+$(BIN_DIR)/$(SDK_NAME).tar.bz2:
+ (cd $(STAGING_DIR); \
+ rm -rf info man share stampfiles; \
+ cd usr; \
+ rm -rf doc info man share; \
+ )
+ rm -rf $(SDK_BUILD_DIR)
+ mkdir -p $(SDK_BUILD_DIR)/dl $(SDK_BUILD_DIR)/package
+ $(CP) $(STAGING_DIR) $(INCLUDE_DIR) $(SCRIPT_DIR) $(TOPDIR)/docs $(SDK_BUILD_DIR)/
+ $(CP) $(TOPDIR)/rules.mk $(TOPDIR)/.config $(SDK_BUILD_DIR)/
+ $(CP) $(TOPDIR)/package/Makefile $(SDK_BUILD_DIR)/package/
+ $(CP) ./files/Makefile $(SDK_BUILD_DIR)/
+ $(CP) ./files/README.SDK $(SDK_BUILD_DIR)/
+ $(CP) ./files/package/rules.mk $(SDK_BUILD_DIR)/package/
+ echo OPENWRTVERSION:=$(OPENWRTVERSION) > $(SDK_BUILD_DIR)/.version.mk
+ find $(SDK_BUILD_DIR) -name .svn | xargs rm -rf
+ find $(SDK_BUILD_DIR) -name CVS | xargs rm -rf
+ (cd $(BUILD_DIR); \
+ tar cfj $@ $(SDK_NAME); \
+ )
+
+download:
+prepare:
+compile: $(BIN_DIR)/$(SDK_NAME).tar.bz2
+install:
+
+clean:
+ rm -rf $(SDK_BUILD_DIR) $(BIN_DIR)/$(SDK_NAME).tar.bz2
diff --git a/target/sdk/files/Makefile b/target/sdk/files/Makefile
new file mode 100644
index 0000000000..ba488e380c
--- /dev/null
+++ b/target/sdk/files/Makefile
@@ -0,0 +1,69 @@
+# Makefile for OpenWrt
+#
+# Copyright (C) 2006 by 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
+#
+
+RELEASE:=Kamikaze
+#VERSION:=2.0 # uncomment for final release
+
+#--------------------------------------------------------------
+# Just run 'make menuconfig', configure stuff, then run 'make'.
+# You shouldn't need to mess with anything beyond this point...
+#--------------------------------------------------------------
+TOPDIR=${shell pwd}
+export TOPDIR
+
+DEVELOPER=1
+export DEVELOPER
+
+all: world
+
+.pkginfo: FORCE
+ifneq ($(shell ./scripts/timestamp.pl -p .pkginfo package Makefile),.pkginfo)
+ @echo Collecting package info...
+ @-for dir in package/*/; do \
+ echo Source-Makefile: $${dir}Makefile; \
+ $(MAKE) --no-print-dir DUMP=1 -C $$dir 2>&- || true; \
+ done > $@
+endif
+
+pkginfo-clean: FORCE
+ -rm -f .pkginfo .config.in
+
+package/%: .pkginfo FORCE
+ $(MAKE) -C package $(patsubst package/%,%,$@) SDK=1
+
+download: FORCE
+ $(MAKE) package/download
+
+world: FORCE
+ $(MAKE) package/compile
+ -( \
+ cd package; \
+ find . -maxdepth 2 -name Config.in | \
+ sed -e 's,/Config.in,,g' | \
+ xargs -r -n1 make compile -C; \
+ )
+
+clean: FORCE
+ rm -rf build_* bin
+
+distclean: clean
+ rm -rf dl .pkg*
+
+.PHONY: FORCE
+FORCE:
diff --git a/target/sdk/files/README.SDK b/target/sdk/files/README.SDK
new file mode 100644
index 0000000000..454e32b2fc
--- /dev/null
+++ b/target/sdk/files/README.SDK
@@ -0,0 +1,7 @@
+This is the OpenWrt SDK. It contains a stripped-down version of
+the buildroot. You can use it to test/develop packages without
+having to compile your own toolchain or any of the libraries
+included with OpenWrt.
+
+To use it, just put your buildroot-compatible package directory
+in the subdir 'package/' and run 'make' from this directory.
diff --git a/target/sdk/files/package/depend.mk b/target/sdk/files/package/depend.mk
new file mode 100644
index 0000000000..d7b844db55
--- /dev/null
+++ b/target/sdk/files/package/depend.mk
@@ -0,0 +1,6 @@
+# You can put your package dependencies in here
+# Example (make openvpn depend on openssl):
+# openvpn-compile: openssl-compile
+#
+# Note: This file is not present in the full buildroot. There you
+# have to put your package dependencies in buildroot/package/Makefile
diff --git a/target/sdk/files/package/rules.mk b/target/sdk/files/package/rules.mk
new file mode 100644
index 0000000000..b3f4cdbea9
--- /dev/null
+++ b/target/sdk/files/package/rules.mk
@@ -0,0 +1,89 @@
+# invoke ipkg with configuration in $(STAGING_DIR)/etc/ipkg.conf
+IPKG := IPKG_INSTROOT=$(TARGET_DIR) IPKG_CONF_DIR=$(IPKG_CONF) $(SCRIPT_DIR)/ipkg -force-defaults -force-depends
+IPKG_STATE_DIR := $(TARGET_DIR)/usr/lib/ipkg
+
+ifneq ($(DUMP),)
+dump:
+.PHONY: dump
+endif
+
+define PKG_template
+IPKG_$(1):=$(PACKAGE_DIR)/$(2)_$(3)_$(4).ipk
+IDIR_$(1):=$(PKG_BUILD_DIR)/ipkg/$(2)
+INFO_$(1):=$(IPKG_STATE_DIR)/info/$(2).list
+
+ifneq ($(BR2_PACKAGE_$(1)),)
+compile-targets: $$(IPKG_$(1))
+endif
+ifneq ($(DEVELOPER),)
+compile-targets: $$(IPKG_$(1))
+endif
+ifeq ($(BR2_PACKAGE_$(1)),y)
+install-targets: $$(INFO_$(1))
+endif
+
+IDEPEND_$(1):=$$(strip $(5))
+
+$$(IDIR_$(1))/CONTROL/control: $(PKG_BUILD_DIR)/.prepared
+ $(SCRIPT_DIR)/make-ipkg-dir.sh $$(IDIR_$(1)) ./ipkg/$(2).control $(3) $(4)
+ if [ "$$(IDEPEND_$(1))" != "" ]; then echo "Depends: $$(IDEPEND_$(1))" >> $$(IDIR_$(1))/CONTROL/control; fi
+ for file in conffiles preinst postinst prerm postrm; do \
+ [ -f ./ipkg/$(2).$$$$file ] && cp ./ipkg/$(2).$$$$file $$(IDIR_$(1))/CONTROL/$$$$file || true; \
+ done
+
+$$(IPKG_$(1)): $$(IDIR_$(1))/CONTROL/control $(PKG_BUILD_DIR)/.built $(PACKAGE_DIR)
+
+$$(INFO_$(1)): $$(IPKG_$(1))
+ $(IPKG) install $$(IPKG_$(1))
+
+$(2)-clean:
+ rm -f $$(IPKG_$(1))
+clean-targets: $(2)-clean
+endef
+
+ifeq ($(DUMP),)
+ifneq ($(strip $(PKG_SOURCE)),)
+$(DL_DIR)/$(PKG_SOURCE):
+ $(SCRIPT_DIR)/download.pl "$(DL_DIR)" "$(PKG_SOURCE)" "$(PKG_MD5SUM)" $(PKG_SOURCE_URL)
+endif
+
+ifneq ($(strip $(PKG_CAT)),)
+$(PKG_BUILD_DIR)/.prepared: $(DL_DIR)/$(PKG_SOURCE)
+ rm -rf $(PKG_BUILD_DIR)
+ mkdir -p $(PKG_BUILD_DIR)
+ $(PKG_CAT) $(DL_DIR)/$(PKG_SOURCE) | tar -C $(PKG_BUILD_DIR)/.. $(TAR_OPTIONS) -
+ if [ -d ./patches ]; then \
+ $(PATCH) $(PKG_BUILD_DIR) ./patches ; \
+ fi
+ touch $(PKG_BUILD_DIR)/.prepared
+endif
+
+all: compile
+
+compile-targets:
+install-targets:
+clean-targets:
+
+source: $(DL_DIR)/$(PKG_SOURCE)
+prepare: $(PKG_BUILD_DIR)/.prepared
+compile: compile-targets
+install: install-targets
+mostlyclean:
+rebuild:
+ -$(MAKE) mostlyclean
+ if [ -f $(PKG_BUILD_DIR)/.built ]; then \
+ $(MAKE) clean; \
+ fi
+ $(MAKE) compile
+
+$(PKG_BUILD_DIR)/.configured: $(PKG_BUILD_DIR)/.prepared
+$(PKG_BUILD_DIR)/.built: $(PKG_BUILD_DIR)/.configured
+
+$(PACKAGE_DIR):
+ mkdir -p $@
+
+clean: clean-targets
+ rm -rf $(PKG_BUILD_DIR)
+
+.PHONY: all source prepare compile install clean
+endif
diff --git a/target/utils/Makefile b/target/utils/Makefile
new file mode 100644
index 0000000000..f2a92fec3d
--- /dev/null
+++ b/target/utils/Makefile
@@ -0,0 +1,32 @@
+#
+# 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
+
+TARGETS := addpattern trx motorola-bin dgfirmware
+
+UTILS_BUILD_DIR:=$(BUILD_DIR)/target-utils
+
+download:
+prepare: $(UTILS_BUILD_DIR)
+compile: prepare $(patsubst %,$(UTILS_BUILD_DIR)/%,$(TARGETS)) FORCE
+ mkdir -p $(STAGING_DIR)/bin
+ $(CP) $(UTILS_BUILD_DIR)/* $(STAGING_DIR)/bin/
+install: compile
+package:
+clean: FORCE
+ rm -rf $(UTILS_BUILD_DIR)
+ for f in $(TARGETS); do \
+ rm -f $(STAGING_DIR)/bin/$$f ; \
+ done
+
+$(UTILS_BUILD_DIR):
+ mkdir -p $(UTILS_BUILD_DIR)
+
+$(UTILS_BUILD_DIR)/%: src/%.c
+ $(CC) -O2 -I $(STAGING_DIR)/include-host -o $@ $(patsubst $(UTILS_BUILD_DIR)/%,src/%.c,$@)
+ chmod 755 $@
+
diff --git a/target/utils/src/addpattern.c b/target/utils/src/addpattern.c
new file mode 100644
index 0000000000..5f49b921f6
--- /dev/null
+++ b/target/utils/src/addpattern.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.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
+ */
+
+/* July 29, 2004
+ *
+ * This is a hacked replacement for the 'addpattern' utility used to
+ * create wrt54g .bin firmware files. It isn't pretty, but it does
+ * the job for me.
+ *
+ * Extensions:
+ * -v allows setting the version string on the command line.
+ * -{0|1} sets the (currently ignored) hw_ver flag in the header
+ * to 0 or 1 respectively.
+ */
+
+/* January 12, 2005
+ *
+ * Modified by rodent at rodent dot za dot net
+ * Support added for the new WRT54G v2.2 and WRT54GS v1.1 "flags"
+ * Without the flags set to 0x7, the above units will refuse to flash.
+ *
+ * Extensions:
+ * -{0|1|2} sets {0|1} sets hw_ver flag to 0/1. {2} sets hw_ver to 1
+ * and adds the new hardware "flags" for the v2.2/v1.1 units
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+/**********************************************************************/
+
+#define CODE_ID "U2ND" /* from code_pattern.h */
+#define CODE_PATTERN "W54S" /* from code_pattern.h */
+#define PBOT_PATTERN "PBOT"
+
+#define CYBERTAN_VERSION "v3.37.2" /* from cyutils.h */
+
+/* WRT54G v2.2 and WRT54GS v1.1 "flags" (from 3.37.32 firmware cyutils.h) */
+#define SUPPORT_4712_CHIP 0x0001
+#define SUPPORT_INTEL_FLASH 0x0002
+#define SUPPORT_5325E_SWITCH 0x0004
+
+struct code_header { /* from cyutils.h */
+ char magic[4];
+ char res1[4]; /* for extra magic */
+ char fwdate[3];
+ char fwvern[3];
+ char id[4]; /* U2ND */
+ char hw_ver; /* 0: for 4702, 1: for 4712 -- new in 2.04.3 */
+ char unused;
+ unsigned char flags[2]; /* SUPPORT_ flags new for 3.37.2 (WRT54G v2.2 and WRT54GS v1.1) */
+ unsigned char res2[10];
+} ;
+
+/**********************************************************************/
+
+void usage(void) __attribute__ (( __noreturn__ ));
+
+void usage(void)
+{
+ fprintf(stderr, "Usage: addpattern [-i trxfile] [-o binfile] [-p pattern] [-g] [-b] [-v v#.#.#] [-{0|1|2|4}]\n");
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv)
+{
+ char buf[1024]; /* keep this at 1k or adjust garbage calc below */
+ struct code_header *hdr;
+ FILE *in = stdin;
+ FILE *out = stdout;
+ char *ifn = NULL;
+ char *ofn = NULL;
+ char *pattern = CODE_PATTERN;
+ char *pbotpat = PBOT_PATTERN;
+ char *version = CYBERTAN_VERSION;
+ int gflag = 0;
+ int pbotflag = 0;
+ int c;
+ int v0, v1, v2;
+ size_t off, n;
+ time_t t;
+ struct tm *ptm;
+
+ fprintf(stderr, "mjn3's addpattern replacement - v0.81\n");
+
+ hdr = (struct code_header *) buf;
+ memset(hdr, 0, sizeof(struct code_header));
+
+ while ((c = getopt(argc, argv, "i:o:p:gbv:0124")) != -1) {
+ switch (c) {
+ case 'i':
+ ifn = optarg;
+ break;
+ case 'o':
+ ofn = optarg;
+ break;
+ case 'p':
+ pattern = optarg;
+ break;
+ case 'g':
+ gflag = 1;
+ break;
+ case 'b':
+ pbotflag = 1;
+ break;
+ case 'v': /* extension to allow setting version */
+ version = optarg;
+ break;
+ case '0':
+ hdr->hw_ver = 0;
+ break;
+ case '1':
+ hdr->hw_ver = 1;
+ break;
+ case '2': /* new 54G v2.2 and 54GS v1.1 flags */
+ hdr->hw_ver = 1;
+ hdr->flags[0] |= SUPPORT_4712_CHIP;
+ hdr->flags[0] |= SUPPORT_INTEL_FLASH;
+ hdr->flags[0] |= SUPPORT_5325E_SWITCH;
+ break;
+ case '4':
+ /* V4 firmware sets the flags to 0x1f */
+ hdr->hw_ver = 0;
+ hdr->flags[0] = 0x1f;
+ break;
+
+ default:
+ usage();
+ }
+ }
+
+ if (optind != argc) {
+ fprintf(stderr, "illegal arg \"%s\"\n", argv[optind]);
+ usage();
+ }
+
+ if (strlen(pattern) != 4) {
+ fprintf(stderr, "illegal pattern \"%s\": length != 4\n", pattern);
+ usage();
+ }
+
+ if (ifn && !(in = fopen(ifn, "r"))) {
+ fprintf(stderr, "can not open \"%s\" for reading\n", ifn);
+ usage();
+ }
+
+ if (ofn && !(out = fopen(ofn, "w"))) {
+ fprintf(stderr, "can not open \"%s\" for writing\n", ofn);
+ usage();
+ }
+
+ if (time(&t) == (time_t)(-1)) {
+ fprintf(stderr, "time call failed\n");
+ return EXIT_FAILURE;
+ }
+
+ ptm = localtime(&t);
+
+ if (3 != sscanf(version, "v%d.%d.%d", &v0, &v1, &v2)) {
+ fprintf(stderr, "bad version string \"%s\"\n", version);
+ return EXIT_FAILURE;
+ }
+
+ memcpy(&hdr->magic, pattern, 4);
+ if (pbotflag)
+ memcpy(&hdr->res1, pbotpat, 4);
+ hdr->fwdate[0] = ptm->tm_year % 100;
+ hdr->fwdate[1] = ptm->tm_mon + 1;
+ hdr->fwdate[2] = ptm->tm_mday;
+ hdr->fwvern[0] = v0;
+ hdr->fwvern[1] = v1;
+ hdr->fwvern[2] = v2;
+ memcpy(&hdr->id, CODE_ID, strlen(CODE_ID));
+
+ off = sizeof(struct code_header);
+
+ fprintf(stderr, "writing firmware v%d.%d.%d on %d/%d/%d (y/m/d)\n",
+ v0, v1, v2,
+ hdr->fwdate[0], hdr->fwdate[1], hdr->fwdate[2]);
+
+
+ while ((n = fread(buf + off, 1, sizeof(buf)-off, in) + off) > 0) {
+ off = 0;
+ if (n < sizeof(buf)) {
+ if (ferror(in)) {
+ FREAD_ERROR:
+ fprintf(stderr, "fread error\n");
+ return EXIT_FAILURE;
+ }
+ if (gflag) {
+ gflag = sizeof(buf) - n;
+ memset(buf + n, 0xff, gflag);
+ fprintf(stderr, "adding %d bytes of garbage\n", gflag);
+ n = sizeof(buf);
+ }
+ }
+ if (!fwrite(buf, n, 1, out)) {
+ FWRITE_ERROR:
+ fprintf(stderr, "fwrite error\n");
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (ferror(in)) {
+ goto FREAD_ERROR;
+ }
+
+ if (fflush(out)) {
+ goto FWRITE_ERROR;
+ }
+
+ fclose(in);
+ fclose(out);
+
+ return EXIT_SUCCESS;
+}
diff --git a/target/utils/src/dgfirmware.c b/target/utils/src/dgfirmware.c
new file mode 100644
index 0000000000..5ff3b69646
--- /dev/null
+++ b/target/utils/src/dgfirmware.c
@@ -0,0 +1,376 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+
+#define IMG_SIZE 0x3e0000
+
+#define KERNEL_START 0x020000
+#define KERNEL_SIZE 0x0b0000
+
+#define ROOTFS_START 0x0d0000
+#define ROOTFS_SIZE 0x30ffb2
+
+char* app_name;
+
+
+
+
+void print_usage(void)
+{
+ fprintf(stderr, "usage: dgfirmware [<opts>] <img>\n");
+ fprintf(stderr, " <img> firmware image filename\n");
+ fprintf(stderr, " <opts> -h print this message\n");
+ fprintf(stderr, " -f fix the checksum\n");
+ fprintf(stderr, " -x <file> extract the rootfs file to <file>\n");
+ fprintf(stderr, " -xk <file> extract the kernel to <file>\n");
+ fprintf(stderr, " -m <file> merge in rootfs fil\e from <file>\n");
+ fprintf(stderr, " -k <file> merge in kernel from <file>\n");
+ fprintf(stderr, " -w <file> write back the modified firmware\n");
+}
+
+
+unsigned char* read_img(const char *fname)
+{
+ FILE *fp;
+ int size;
+ unsigned char *img;
+
+ fp = fopen(fname, "rb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+
+ if (size != IMG_SIZE) {
+ fprintf(stderr, "%s: image file has wrong size\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ rewind(fp);
+
+ img = malloc(IMG_SIZE);
+ if (img == NULL) {
+ perror(app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ if (fread(img, 1, IMG_SIZE, fp) != IMG_SIZE) {
+ fprintf(stderr, "%s: can't read image file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ fclose(fp);
+ return img;
+}
+
+
+void write_img(unsigned char* img, const char *fname)
+{
+ FILE *fp;
+
+ fp = fopen(fname, "wb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ if (fwrite(img, 1, IMG_SIZE, fp) != IMG_SIZE) {
+ fprintf(stderr, "%s: can't write image file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+}
+
+
+void write_rootfs(unsigned char* img, const char *fname)
+{
+ FILE *fp;
+
+ fp = fopen(fname, "wb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ if (fwrite(img+ROOTFS_START, 1, ROOTFS_SIZE, fp) != ROOTFS_SIZE) {
+ fprintf(stderr, "%s: can't write image file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+}
+
+
+void write_kernel(unsigned char* img, const char *fname)
+{
+ FILE *fp;
+
+ fp = fopen(fname, "wb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ if (fwrite(img+KERNEL_START, 1, KERNEL_SIZE, fp) != KERNEL_SIZE) {
+ fprintf(stderr, "%s: can't write kernel file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+}
+
+
+unsigned char* read_rootfs(unsigned char* img, const char *fname)
+{
+ FILE *fp;
+ int size;
+ int i;
+
+ for (i=ROOTFS_START; i<ROOTFS_START+ROOTFS_SIZE; i++)
+ img[i] = 0xff;
+
+ fp = fopen(fname, "rb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+
+ if (size > ROOTFS_SIZE) {
+ fprintf(stderr, "%s: rootfs image file is too big\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ rewind(fp);
+
+ if (fread(img+ROOTFS_START, 1, size, fp) != size) {
+ fprintf(stderr, "%s: can't read rootfs image file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ fclose(fp);
+ return img;
+}
+
+
+unsigned char* read_kernel(unsigned char* img, const char *fname)
+{
+ FILE *fp;
+ int size;
+ int i;
+
+ for (i=KERNEL_START; i<KERNEL_START+KERNEL_SIZE; i++)
+ img[i] = 0xff;
+
+ fp = fopen(fname, "rb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+
+ if (size > KERNEL_SIZE) {
+ fprintf(stderr, "%s: kernel binary file is too big\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ rewind(fp);
+
+ if (fread(img+KERNEL_START, 1, size, fp) != size) {
+ fprintf(stderr, "%s: can't read kernel file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ fclose(fp);
+ return img;
+}
+
+
+int get_checksum(unsigned char* img)
+{
+ short unsigned s;
+
+ s = img[0x3dfffc] + (img[0x3dfffd]<<8);
+
+ return s;
+}
+
+
+void set_checksum(unsigned char*img, unsigned short sum)
+{
+ img[0x3dfffc] = sum & 0xff;
+ img[0x3dfffd] = (sum>>8) & 0xff;
+}
+
+
+int compute_checksum(unsigned char* img)
+{
+ int i;
+ short s=0;
+
+ for (i=0; i<0x3dfffc; i++)
+ s += img[i];
+
+ return s;
+}
+
+
+int main(int argc, char* argv[])
+{
+ char *img_fname = NULL;
+ char *rootfs_fname = NULL;
+ char *kernel_fname = NULL;
+ char *new_img_fname = NULL;
+
+ int do_fix_checksum = 0;
+ int do_write = 0;
+ int do_write_rootfs = 0;
+ int do_read_rootfs = 0;
+ int do_write_kernel = 0;
+ int do_read_kernel = 0;
+
+ int i;
+ unsigned char *img;
+ unsigned short img_checksum;
+ unsigned short real_checksum;
+
+ app_name = argv[0];
+
+ for (i=1; i<argc; i++) {
+ if (!strcmp(argv[i], "-h")) {
+ print_usage();
+ return 0;
+ }
+ else if (!strcmp(argv[i], "-f")) {
+ do_fix_checksum = 1;
+ }
+ else if (!strcmp(argv[i], "-x")) {
+ if (i+1 >= argc) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+ do_write_rootfs = 1;
+ rootfs_fname = argv[i+1];
+ i++;
+ }
+ else if (!strcmp(argv[i], "-xk")) {
+ if (i+1 >= argc) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+ do_write_kernel = 1;
+ kernel_fname = argv[i+1];
+ i++;
+ }
+ else if (!strcmp(argv[i], "-m")) {
+ if (i+1 >= argc) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+ do_read_rootfs = 1;
+ rootfs_fname = argv[i+1];
+ i++;
+ }
+ else if (!strcmp(argv[i], "-k")) {
+ if (i+1 >= argc) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+ do_read_kernel = 1;
+ kernel_fname = argv[i+1];
+ i++;
+ }
+ else if (!strcmp(argv[i], "-w")) {
+ if (i+1 >= argc) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+ do_write = 1;
+ new_img_fname = argv[i+1];
+ i++;
+ }
+ else if (img_fname != 0) {
+ fprintf(stderr, "%s: too many arguments\n", app_name);
+ return -1;
+ }
+ else {
+ img_fname = argv[i];
+ }
+ }
+
+ if (img_fname == NULL) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+
+ if ((do_read_rootfs && do_write_rootfs) ||
+ (do_read_kernel && do_write_kernel)) {
+ fprintf(stderr, "%s: conflictuous options\n", app_name);
+ return -1;
+ }
+
+ printf ("** Read firmware file\n");
+ img = read_img(img_fname);
+
+ printf ("Firmware product: %s\n", img+0x3dffbd);
+ printf ("Firmware version: 1.%02d.%02d\n", (img[0x3dffeb] & 0x7f), img[0x3dffec]);
+
+ if (do_write_rootfs) {
+ printf ("** Write rootfs file\n");
+ write_rootfs(img, rootfs_fname);
+ }
+
+ if (do_write_kernel) {
+ printf ("** Write kernel file\n");
+ write_kernel(img, kernel_fname);
+ }
+
+ if (do_read_rootfs) {
+ printf ("** Read rootfs file\n");
+ read_rootfs(img, rootfs_fname);
+ do_fix_checksum = 1;
+ }
+
+ if (do_read_kernel) {
+ printf ("** Read kernel file\n");
+ read_kernel(img, kernel_fname);
+ do_fix_checksum = 1;
+ }
+
+ img_checksum = get_checksum(img);
+ real_checksum = compute_checksum(img);
+
+ printf ("image checksum = %04x\n", img_checksum);
+ printf ("real checksum = %04x\n", real_checksum);
+
+ if (do_fix_checksum) {
+ if (img_checksum != real_checksum) {
+ printf ("** Bad Checksum, fix it\n");
+ set_checksum(img, real_checksum);
+ }
+ else {
+ printf ("** Checksum is correct, good\n");
+ }
+ }
+
+ if (do_write) {
+ printf ("** Write image file\n");
+ write_img(img, new_img_fname);
+ }
+
+ free(img);
+ return 0;
+}
+
diff --git a/target/utils/src/motorola-bin.c b/target/utils/src/motorola-bin.c
new file mode 100644
index 0000000000..acf856dde6
--- /dev/null
+++ b/target/utils/src/motorola-bin.c
@@ -0,0 +1,146 @@
+/*
+ * motorola-bin.c
+ *
+ * Copyright (C) 2005-2006 Mike Baker,
+ * Imre Kaloz <kaloz@openwrt.org>
+ * OpenWrt.org
+ *
+ * $Id$
+ *
+ * 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.
+ *
+ */
+
+/*
+ * February 1, 2006
+ *
+ * Add support for for creating WA840G and WE800G images
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <netinet/in.h>
+
+unsigned long *crc32;
+
+void init_crc32()
+{
+ unsigned long crc;
+ unsigned long poly = ntohl(0x2083b8ed);
+ int n, bit;
+ if ((crc32 = (unsigned long *) malloc(256 * sizeof(unsigned long))) == (void *)-1) {
+ perror("malloc");
+ exit(1);
+ }
+ for (n = 0; n < 256; n++) {
+ crc = (unsigned long) n;
+ for (bit = 0; bit < 8; bit++)
+ crc = (crc & 1) ? (poly ^ (crc >> 1)) : (crc >> 1);
+ crc32[n] = crc;
+ }
+}
+
+unsigned int crc32buf(char *buf, size_t len)
+{
+ unsigned int crc = 0xFFFFFFFF;
+ for (; len; len--, buf++)
+ crc = crc32[(crc ^ *buf) & 0xff] ^ (crc >> 8);
+ return crc;
+}
+
+struct motorola {
+ unsigned int crc; // crc32 of the remainder
+ unsigned int flags; // unknown, 105770*
+ char *trx; // standard trx
+};
+
+void usage(void) __attribute__ (( __noreturn__ ));
+
+void usage(void)
+{
+ printf("Usage: motorola-bin [-device] [trxfile] [binfile]\n\n");
+ printf("Known devices: 1 - WR850G | 2 - WA840G | 3 - WE800G\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ unsigned int len;
+ int fd;
+ int c;
+ void *trx;
+ struct motorola *firmware;
+
+ // verify parameters
+
+ if (argc!=4)
+ {
+ usage();
+ }
+
+ // mmap trx file
+ if (((fd = open(argv[2], O_RDONLY)) < 0)
+ || ((len = lseek(fd, 0, SEEK_END)) < 0)
+ || ((trx = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0)) == (void *) (-1))
+ || (close(fd) < 0)) {
+ perror("open/malloc");
+ exit(1);
+ }
+
+ // create a firmware image in memory
+ // and copy the trx to it
+ firmware = malloc(len+8);
+ memcpy(&firmware->trx,trx,len);
+ munmap(trx,len);
+
+ // setup the motorola headers
+ init_crc32();
+
+ // setup the firmware magic
+
+ while ((c = getopt(argc, argv, "123")) !=-1) {
+ switch (c) {
+ case '1':
+ firmware->flags = ntohl(0x10577050); // Motorola WR850G
+ break;
+ case '2':
+ firmware->flags = ntohl(0x10577040); // Motorola WA840G
+ break;
+ case '3':
+ firmware->flags = ntohl(0x10577000); // Motorola WE800G
+ break;
+ default:
+ usage();
+ }
+ }
+
+ firmware->crc = htonl(crc32buf((char *)&firmware->flags,len+4));
+
+ // write the firmware
+ if (((fd = open(argv[3], O_CREAT|O_WRONLY,0644)) < 0)
+ || (write(fd,firmware,len+8) != len+8)
+ || (close(fd) < 0)) {
+ perror("write");
+ exit(-1);
+ }
+
+ free(firmware);
+
+ return 0;
+}
diff --git a/target/utils/src/trx.c b/target/utils/src/trx.c
new file mode 100644
index 0000000000..abc9bc93c4
--- /dev/null
+++ b/target/utils/src/trx.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.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
+ */
+
+/* July 29, 2004
+ *
+ * This is a hacked replacement for the 'trx' utility used to create
+ * wrt54g .trx firmware files. It isn't pretty, but it does the job
+ * for me.
+ *
+ * As an extension, you can specify a larger maximum length for the
+ * .trx file using '-m'. It will be rounded up to be a multiple of 4K.
+ * NOTE: This space will be malloc()'d.
+ *
+ * August 16, 2004
+ *
+ * Sigh... Make it endian-neutral.
+ *
+ * TODO: Support '-b' option to specify offsets for each file.
+ *
+ * February 19, 2005 - mbm
+ *
+ * Add -a (align offset) and -b (absolute offset)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#if defined(__APPLE__)
+#include <machine/endian.h>
+#include <machine/byte_order.h>
+#define __BYTE_ORDER BYTE_ORDER
+#define __BIG_ENDIAN BIG_ENDIAN
+#define bswap_16(x) NXSwapShort(x)
+#define bswap_32(x) NXSwapInt(x)
+#define bswap_64(x) NXSwapLongLong(x)
+#else
+#include <endian.h>
+#include <byteswap.h>
+#endif
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define STORE32_LE(X) bswap_32(X)
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define STORE32_LE(X) (X)
+#else
+#error unkown endianness!
+#endif
+
+uint32_t crc32buf(char *buf, size_t len);
+
+/**********************************************************************/
+/* from trxhdr.h */
+
+#define TRX_MAGIC 0x30524448 /* "HDR0" */
+#define TRX_VERSION 1
+#define TRX_MAX_LEN 0x5A0000
+#define TRX_NO_HEADER 1 /* Do not write TRX header */
+
+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 */
+};
+
+/**********************************************************************/
+
+void usage(void) __attribute__ (( __noreturn__ ));
+
+void usage(void)
+{
+ fprintf(stderr, "Usage: trx [-o outfile] [-m maxlen] [-a align] [-b offset] [-f file] [-f file [-f file]]\n");
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv)
+{
+ FILE *out = stdout;
+ FILE *in;
+ char *ofn = NULL;
+ char *buf;
+ char *e;
+ int c, i;
+ size_t n;
+ uint32_t cur_len;
+ unsigned long maxlen = TRX_MAX_LEN;
+ struct trx_header *p;
+
+ fprintf(stderr, "mjn3's trx replacement - v0.81.1\n");
+
+ if (!(buf = malloc(maxlen))) {
+ fprintf(stderr, "malloc failed\n");
+ return EXIT_FAILURE;
+ }
+
+ p = (struct trx_header *) buf;
+
+ p->magic = STORE32_LE(TRX_MAGIC);
+ cur_len = sizeof(struct trx_header);
+ p->flag_version = STORE32_LE((TRX_VERSION << 16));
+
+ in = NULL;
+ i = 0;
+
+ while ((c = getopt(argc, argv, "-:o:m:a:b:f:")) != -1) {
+ switch (c) {
+ case 'f':
+ case 1:
+ p->offsets[i++] = STORE32_LE(cur_len);
+
+ if (!(in = fopen(optarg, "r"))) {
+ fprintf(stderr, "can not open \"%s\" for reading\n", optarg);
+ usage();
+ }
+ n = fread(buf + cur_len, 1, maxlen - cur_len, in);
+ if (!feof(in)) {
+ fprintf(stderr, "fread failure or file \"%s\" too large\n",optarg);
+ fclose(in);
+ return EXIT_FAILURE;
+ }
+ fclose(in);
+#undef ROUND
+#define ROUND 4
+ if (n & (ROUND-1)) {
+ memset(buf + cur_len + n, 0, ROUND - (n & (ROUND-1)));
+ n += ROUND - (n & (ROUND-1));
+ }
+ cur_len += n;
+
+ break;
+ case 'o':
+ ofn = optarg;
+ if (ofn && !(out = fopen(ofn, "w"))) {
+ fprintf(stderr, "can not open \"%s\" for writing\n", ofn);
+ usage();
+ }
+
+ break;
+ case 'm':
+ errno = 0;
+ maxlen = strtoul(optarg, &e, 0);
+ if (errno || (e == optarg) || *e) {
+ fprintf(stderr, "illegal numeric string\n");
+ usage();
+ }
+#undef ROUND
+#define ROUND 0x1000
+ if (maxlen & (ROUND-1)) {
+ maxlen += (ROUND - (maxlen & (ROUND-1)));
+ }
+ if (maxlen < ROUND) {
+ fprintf(stderr, "maxlen too small (or wrapped)\n");
+ usage();
+ }
+ if (maxlen > TRX_MAX_LEN) {
+ fprintf(stderr, "WARNING: maxlen exceeds default maximum! Beware of overwriting nvram!\n");
+ }
+ if (!(buf = realloc(buf,maxlen))) {
+ fprintf(stderr, "realloc failed");
+ return EXIT_FAILURE;
+ }
+ break;
+ case 'a':
+ errno = 0;
+ n = strtoul(optarg, &e, 0);
+ if (errno || (e == optarg) || *e) {
+ fprintf(stderr, "illegal numeric string\n");
+ usage();
+ }
+ if (cur_len & (n-1)) {
+ n = n - (cur_len & (n-1));
+ memset(buf + cur_len, 0, n);
+ cur_len += n;
+ }
+ break;
+ case 'b':
+ errno = 0;
+ n = strtoul(optarg, &e, 0);
+ if (errno || (e == optarg) || *e) {
+ fprintf(stderr, "illegal numeric string\n");
+ usage();
+ }
+ if (n < cur_len) {
+ fprintf(stderr, "WARNING: current length exceeds -b %d offset\n",n);
+ } else {
+ memset(buf + cur_len, 0, n - cur_len);
+ cur_len = n;
+ }
+ break;
+ default:
+ usage();
+ }
+ }
+
+ if (!in) {
+ fprintf(stderr, "we require atleast one filename\n");
+ usage();
+ }
+
+#undef ROUND
+#define ROUND 0x1000
+ n = cur_len & (ROUND-1);
+ if (n) {
+ memset(buf + cur_len, 0, ROUND - n);
+ cur_len += ROUND - n;
+ }
+
+ p->crc32 = crc32buf((char *) &p->flag_version,
+ cur_len - offsetof(struct trx_header, flag_version));
+ p->crc32 = STORE32_LE(p->crc32);
+
+ p->len = STORE32_LE(cur_len);
+
+ if (!fwrite(buf, cur_len, 1, out) || fflush(out)) {
+ fprintf(stderr, "fwrite failed\n");
+ return EXIT_FAILURE;
+ }
+
+ fclose(out);
+
+ return EXIT_SUCCESS;
+}
+
+/**********************************************************************/
+/* The following was grabbed and tweaked from the old snippets collection
+ * of public domain C code. */
+
+/**********************************************************************\
+|* Demonstration program to compute the 32-bit CRC used as the frame *|
+|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *|
+|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *|
+|* protocol). The 32-bit FCS was added via the Federal Register, *|
+|* 1 June 1982, p.23798. I presume but don't know for certain that *|
+|* this polynomial is or will be included in CCITT V.41, which *|
+|* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *|
+|* PUB 78 says that the 32-bit FCS reduces otherwise undetected *|
+|* errors by a factor of 10^-5 over 16-bit FCS. *|
+\**********************************************************************/
+
+/* 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: */
+/* */
+/* 1. 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. */
+/* */
+/* 2. The CRC accumulation logic is the same for all CRC polynomials, */
+/* be they sixteen or thirty-two bits wide. You simply choose the */
+/* appropriate table. Alternatively, because the table can be */
+/* generated at runtime, you can start by generating the table for */
+/* the polynomial in question and use exactly the same "updcrc", */
+/* if your application needn't simultaneously handle two CRC */
+/* polynomials. (Note, however, that XMODEM is strange.) */
+/* */
+/* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */
+/* of course, 32-bit entries work OK if the high 16 bits are zero. */
+/* */
+/* 4. 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. */
+
+static const uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
+0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+#define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
+
+uint32_t crc32buf(char *buf, size_t len)
+{
+ uint32_t crc;
+
+ crc = 0xFFFFFFFF;
+
+ for ( ; len; --len, ++buf)
+ {
+ crc = UPDC32(*buf, crc);
+ }
+
+ return crc;
+}
diff --git a/toolchain/Config.in b/toolchain/Config.in
new file mode 100644
index 0000000000..7b0a0aaeee
--- /dev/null
+++ b/toolchain/Config.in
@@ -0,0 +1,54 @@
+#
+config NATIVE_TOOLCHAIN
+ bool
+ prompt "Use host's toolchain" if DEVEL && BROKEN
+ default n
+ help
+ If enabled, OpenWrt will compile using your existing toolchain instead of compiling one
+
+menuconfig TOOLCHAINOPTS
+ bool "Toolchain Options" if DEVEL
+ depends !NATIVE_TOOLCHAIN
+
+source "toolchain/binutils/Config.in"
+source "toolchain/gcc/Config.in"
+
+config GDB
+ bool
+ prompt "Build gdb" if TOOLCHAINOPTS
+ default n
+ help
+ Enable if you want to build the gdb
+
+config LARGEFILE
+ bool
+ prompt "Enable large file (files > 2 GB) support?" if TOOLCHAINOPTS
+ depends on !cris
+ default y
+ help
+ Enable large file (files > 2 GB) support
+
+config SOFT_FLOAT
+ bool
+ prompt "Use software floating point by default" if TOOLCHAINOPTS
+ default n
+ depends on arm || mips || powerpc
+ help
+ If your target CPU does not have a Floating Point Unit (FPU) or a
+ kernel FPU emulator, but you still wish to support floating point
+ functions, then everything will need to be compiled with soft floating
+ point support (-msoft-float).
+
+ Most people will answer N.
+
+config TARGET_OPTIMIZATION
+ string
+ prompt "Target Optimizations" if TOOLCHAINOPTS
+ default "-Os -pipe -march=i486 -funit-at-a-time" if i386
+ default "-Os -pipe -mips32 -mtune=mips32 -funit-at-a-time" if mipsel || mips
+ default "-Os -pipe -mcpu=xscale -funit-at-a-time" if armeb
+ default "-Os -pipe -funit-at-a-time"
+ help
+ Optimizations to use when building for the target host.
+
+source "toolchain/gcc/Config.version"
diff --git a/toolchain/Makefile b/toolchain/Makefile
new file mode 100644
index 0000000000..2d8d88219d
--- /dev/null
+++ b/toolchain/Makefile
@@ -0,0 +1,72 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# Main makefile for the toolchain
+#
+include $(TOPDIR)/rules.mk
+
+TARGETS-y:=kernel-headers libnotimpl
+TARGETS-$(CONFIG_GDB) += gdb
+ifeq ($(CONFIG_NATIVE_TOOLCHAIN),)
+ TARGETS-y+=binutils gcc uClibc
+endif
+
+TARGETS_DOWNLOAD:=$(patsubst %,%-download,$(TARGETS-y))
+TARGETS_INSTALL:=$(patsubst %,%-install,$(TARGETS-y))
+TARGETS_CLEAN:=$(patsubst %,%-clean,$(TARGETS-y))
+
+all: install
+download: $(TARGETS_DOWNLOAD)
+install: $(TARGETS_INSTALL)
+clean: $(TARGETS_CLEAN)
+$(TARGETS_INSTALL): $(STAGING_DIR)/$(REAL_GNU_TARGET_NAME)
+
+uClibc-prepare: kernel-headers-prepare
+ifeq ($(CONFIG_NATIVE_TOOLCHAIN),)
+ binutils-prepare: uClibc-prepare
+ gcc-prepare: binutils-install
+ uClibc-compile: gcc-compile
+ libnotimpl-compile: gcc-install
+endif
+gcc-install: uClibc-install
+
+TOOLCHAIN_STAMP_DIR:=$(STAGING_DIR)/stampfiles
+
+$(STAGING_DIR)/$(REAL_GNU_TARGET_NAME):
+ @mkdir -p $@
+ @ln -sf ../lib $@/lib
+
+$(TOOLCHAIN_STAMP_DIR):
+ mkdir -p $@
+
+$(TOOLCHAIN_BUILD_DIR):
+ @mkdir -p $@
+
+%-download: FORCE
+ $(MAKE) -C $(patsubst %-download,%,$@) download
+
+%-prepare: $(TOOLCHAIN_STAMP_DIR) $(STAGING_DIR)/$(REAL_GNU_TARGET_NAME) $(TOOLCHAIN_BUILD_DIR) FORCE
+ @[ -f $(TOOLCHAIN_STAMP_DIR)/.toolchain_$@ ] || { \
+ $(MAKE) -C $(patsubst %-prepare,%,$@) prepare; \
+ }
+ @touch $(TOOLCHAIN_STAMP_DIR)/.toolchain_$@
+
+%-compile: %-prepare
+ @[ -f $(TOOLCHAIN_STAMP_DIR)/.toolchain_$@ ] || { \
+ $(MAKE) -C $(patsubst %-compile,%,$@) compile; \
+ }
+ @touch $(TOOLCHAIN_STAMP_DIR)/.toolchain_$@
+
+%-install: %-compile
+ @[ -f $(TOOLCHAIN_STAMP_DIR)/.toolchain_$@ ] || { \
+ $(MAKE) -C $(patsubst %-install,%,$@) install; \
+ }
+ @touch $(TOOLCHAIN_STAMP_DIR)/.toolchain_$@
+
+%-clean: FORCE
+ @$(MAKE) -C $(patsubst %-clean,%,$@) clean
+ @rm -f $(TOOLCHAIN_STAMP_DIR)/.toolchain_$(patsubst %-clean,%,$@)-*
+
diff --git a/toolchain/binutils/Config.in b/toolchain/binutils/Config.in
new file mode 100644
index 0000000000..9b4fe07b7d
--- /dev/null
+++ b/toolchain/binutils/Config.in
@@ -0,0 +1,24 @@
+# Choose binutils version.
+
+choice
+ prompt "Binutils Version" if TOOLCHAINOPTS
+ default BINUTILS_VERSION_2_16_1
+ help
+ Select the version of binutils you wish to use.
+
+ config BINUTILS_VERSION_2_16_1
+ bool "binutils 2.16.1"
+
+ config BINUTILS_VERSION_2_17
+ bool "binutils 2.17"
+
+endchoice
+
+config BINUTILS_VERSION
+ string
+ prompt "Binutils Version" if (TOOLCHAINOPTS && NULL)
+ default "2.16.1" if BINUTILS_VERSION_2_16_1
+ default "2.17" if BINUTILS_VERSION_2_17
+ default "2.16.1"
+
+
diff --git a/toolchain/binutils/Makefile b/toolchain/binutils/Makefile
new file mode 100644
index 0000000000..e36758fe4c
--- /dev/null
+++ b/toolchain/binutils/Makefile
@@ -0,0 +1,54 @@
+#
+# 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:=binutils
+PKG_VERSION:=$(strip $(subst ",, $(CONFIG_BINUTILS_VERSION)))#"))
+
+PKG_SOURCE_URL:=http://ftp.gnu.org/gnu/binutils/ \
+ ftp://gatekeeper.dec.com/pub/GNU/ \
+ ftp://ftp.uu.net/archive/systems/gnu/ \
+ ftp://ftp.eu.uu.net/pub/gnu/ \
+ ftp://ftp.funet.fi/pub/gnu/prep/ \
+ ftp://ftp.leo.org/pub/comp/os/unix/gnu/
+
+PKG_SOURCE:=binutils-$(PKG_VERSION).tar.bz2
+PKG_MD5SUM:=unknown
+PKG_BUILD_DIR:=$(TOOLCHAIN_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_CAT:=bzcat
+
+include $(INCLUDE_DIR)/host-build.mk
+
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ if [ -d ./patches/$(PKG_VERSION) ]; then \
+ $(SCRIPT_DIR)/patch-kernel.sh $(PKG_BUILD_DIR) ./patches/$(PKG_VERSION); \
+ fi
+endef
+
+define Build/Configure
+ (cd $(PKG_BUILD_DIR); \
+ ./configure \
+ --prefix=$(STAGING_DIR) \
+ --build=$(GNU_HOST_NAME) \
+ --host=$(GNU_HOST_NAME) \
+ --target=$(REAL_GNU_TARGET_NAME) \
+ --disable-werror \
+ --disable-nls \
+ );
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) -j $(CONFIG_JLEVEL) all
+endef
+
+define Build/Install
+ $(MAKE) -C $(PKG_BUILD_DIR) -j $(CONFIG_JLEVEL) install
+endef
+
+$(eval $(call HostBuild))
diff --git a/toolchain/binutils/patches/2.16.1/100-uclibc-conf.patch b/toolchain/binutils/patches/2.16.1/100-uclibc-conf.patch
new file mode 100644
index 0000000000..7c0a72693f
--- /dev/null
+++ b/toolchain/binutils/patches/2.16.1/100-uclibc-conf.patch
@@ -0,0 +1,586 @@
+diff -ur binutils-2.15.97.orig/bfd/config.bfd binutils-2.15.97/bfd/config.bfd
+--- binutils-2.15.97.orig/bfd/config.bfd 2005-04-29 20:48:14.000000000 -0400
++++ binutils-2.15.97/bfd/config.bfd 2005-04-29 20:53:50.000000000 -0400
+@@ -140,7 +140,7 @@
+ targ_defvec=ecoffalpha_little_vec
+ targ_selvecs=bfd_elf64_alpha_vec
+ ;;
+- alpha*-*-linux-gnu* | alpha*-*-elf*)
++ alpha*-*-linux-* | alpha*-*-elf*)
+ targ_defvec=bfd_elf64_alpha_vec
+ targ_selvecs=ecoffalpha_little_vec
+ ;;
+@@ -150,7 +150,7 @@
+ alpha*-*-*)
+ targ_defvec=ecoffalpha_little_vec
+ ;;
+- ia64*-*-freebsd* | ia64*-*-netbsd* | ia64*-*-linux-gnu* | ia64*-*-elf* | ia64*-*-kfreebsd*-gnu)
++ ia64*-*-freebsd* | ia64*-*-netbsd* | ia64*-*-linux-* | ia64*-*-elf* | ia64*-*-kfreebsd*-gnu)
+ targ_defvec=bfd_elf64_ia64_little_vec
+ targ_selvecs="bfd_elf64_ia64_big_vec bfd_efi_app_ia64_vec"
+ ;;
+@@ -227,7 +227,7 @@
+ targ_defvec=bfd_elf32_littlearm_vec
+ targ_selvecs=bfd_elf32_bigarm_vec
+ ;;
+- armeb-*-elf | arm*b-*-linux-gnu*)
++ armeb-*-elf | arm*b-*-linux-*)
+ targ_defvec=bfd_elf32_bigarm_vec
+ targ_selvecs=bfd_elf32_littlearm_vec
+ ;;
+@@ -235,7 +235,7 @@
+ targ_defvec=bfd_elf32_littlearm_vec
+ targ_selvecs=bfd_elf32_bigarm_vec
+ ;;
+- arm-*-elf | arm-*-freebsd* | arm*-*-linux-gnu* | arm*-*-conix* | \
++ arm-*-elf | arm-*-freebsd* | arm*-*-linux-* | arm*-*-conix* | \
+ arm*-*-uclinux* | arm-*-kfreebsd*-gnu | \
+ arm*-*-eabi* )
+ targ_defvec=bfd_elf32_littlearm_vec
+@@ -385,7 +385,7 @@
+ ;;
+
+ #ifdef BFD64
+- hppa*64*-*-linux-gnu*)
++ hppa*64*-*-linux-*)
+ targ_defvec=bfd_elf64_hppa_linux_vec
+ targ_selvecs=bfd_elf64_hppa_vec
+ ;;
+@@ -396,7 +396,7 @@
+ ;;
+ #endif
+
+- hppa*-*-linux-gnu*)
++ hppa*-*-linux-*)
+ targ_defvec=bfd_elf32_hppa_linux_vec
+ targ_selvecs=bfd_elf32_hppa_vec
+ ;;
+@@ -529,7 +529,7 @@
+ targ_selvecs=bfd_elf32_i386_vec
+ targ_underscore=yes
+ ;;
+- i[3-7]86-*-linux-gnu*)
++ i[3-7]86-*-linux-*)
+ targ_defvec=bfd_elf32_i386_vec
+ targ_selvecs="i386linux_vec bfd_efi_app_ia32_vec"
+ targ64_selvecs=bfd_elf64_x86_64_vec
+@@ -543,7 +543,7 @@
+ targ_defvec=bfd_elf64_x86_64_vec
+ targ_selvecs="bfd_elf32_i386_vec i386netbsd_vec i386coff_vec bfd_efi_app_ia32_vec"
+ ;;
+- x86_64-*-linux-gnu*)
++ x86_64-*-linux-*)
+ targ_defvec=bfd_elf64_x86_64_vec
+ targ_selvecs="bfd_elf32_i386_vec i386linux_vec bfd_efi_app_ia32_vec"
+ ;;
+@@ -719,7 +719,7 @@
+ targ_selvecs=bfd_elf32_m68k_vec
+ targ_underscore=yes
+ ;;
+- m68*-*-linux-gnu*)
++ m68*-*-linux-*)
+ targ_defvec=bfd_elf32_m68k_vec
+ targ_selvecs=m68klinux_vec
+ ;;
+@@ -1005,7 +1005,7 @@
+ ;;
+ #endif
+ powerpc-*-*bsd* | powerpc-*-elf* | powerpc-*-sysv4* | powerpc-*-eabi* | \
+- powerpc-*-solaris2* | powerpc-*-linux-gnu* | powerpc-*-rtems* | \
++ powerpc-*-solaris2* | powerpc-*-linux-* | powerpc-*-rtems* | \
+ powerpc-*-chorus* | powerpc-*-vxworks* | powerpc-*-windiss*)
+ targ_defvec=bfd_elf32_powerpc_vec
+ targ_selvecs="rs6000coff_vec bfd_elf32_powerpcle_vec ppcboot_vec"
+@@ -1042,7 +1042,7 @@
+ targ_selvecs="rs6000coff_vec bfd_elf32_powerpc_vec ppcboot_vec"
+ ;;
+ powerpcle-*-elf* | powerpcle-*-sysv4* | powerpcle-*-eabi* | \
+- powerpcle-*-solaris2* | powerpcle-*-linux-gnu* | powerpcle-*-vxworks* |\
++ powerpcle-*-solaris2* | powerpcle-*-linux-* | powerpcle-*-vxworks* |\
+ powerpcle-*-rtems*)
+ targ_defvec=bfd_elf32_powerpcle_vec
+ targ_selvecs="rs6000coff_vec bfd_elf32_powerpc_vec ppcboot_vec"
+@@ -1213,7 +1213,7 @@
+ targ_selvecs="bfd_elf32_sparc_vec sunos_big_vec"
+ targ_underscore=yes
+ ;;
+- sparc-*-linux-gnu*)
++ sparc-*-linux-*)
+ targ_defvec=bfd_elf32_sparc_vec
+ targ_selvecs="sparclinux_vec bfd_elf64_sparc_vec sunos_big_vec"
+ ;;
+@@ -1260,7 +1260,7 @@
+ targ_defvec=sunos_big_vec
+ targ_underscore=yes
+ ;;
+- sparc64-*-linux-gnu*)
++ sparc64-*-linux-*)
+ targ_defvec=bfd_elf64_sparc_vec
+ targ_selvecs="bfd_elf32_sparc_vec sparclinux_vec sunos_big_vec"
+ ;;
+@@ -1329,7 +1329,7 @@
+ targ_underscore=yes
+ ;;
+
+- vax-*-linux-gnu*)
++ vax-*-linux-*)
+ targ_defvec=bfd_elf32_vax_vec
+ ;;
+
+diff -ur binutils-2.15.97.orig/bfd/configure binutils-2.15.97/bfd/configure
+--- binutils-2.15.97.orig/bfd/configure 2005-04-29 20:48:14.000000000 -0400
++++ binutils-2.15.97/bfd/configure 2005-04-29 20:53:50.000000000 -0400
+@@ -9918,7 +9918,7 @@
+ alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu)
+ COREFILE=''
+ ;;
+- alpha*-*-linux-gnu*)
++ alpha*-*-linux-*)
+ COREFILE=trad-core.lo
+ TRAD_HEADER='"hosts/alphalinux.h"'
+ ;;
+@@ -9982,7 +9982,7 @@
+ COREFILE=trad-core.lo
+ TRAD_HEADER='"hosts/i386mach3.h"'
+ ;;
+- i[3-7]86-*-linux-gnu*)
++ i[3-7]86-*-linux-*)
+ COREFILE=trad-core.lo
+ TRAD_HEADER='"hosts/i386linux.h"'
+ ;;
+@@ -10020,7 +10020,7 @@
+ COREFILE=trad-core.lo
+ TRAD_HEADER='"hosts/hp300bsd.h"'
+ ;;
+- m68*-*-linux-gnu*)
++ m68*-*-linux-*)
+ COREFILE=trad-core.lo
+ TRAD_HEADER='"hosts/m68klinux.h"'
+ ;;
+@@ -10154,7 +10154,7 @@
+ COREFILE=trad-core.lo
+ TRAD_HEADER='"hosts/vaxult2.h"'
+ ;;
+- vax-*-linux-gnu*)
++ vax-*-linux-*)
+ COREFILE=trad-core.lo
+ TRAD_HEADER='"hosts/vaxlinux.h"'
+ ;;
+diff -ur binutils-2.15.97.orig/bfd/configure.in binutils-2.15.97/bfd/configure.in
+--- binutils-2.15.97.orig/bfd/configure.in 2005-04-29 20:48:14.000000000 -0400
++++ binutils-2.15.97/bfd/configure.in 2005-04-29 20:53:50.000000000 -0400
+@@ -163,7 +163,7 @@
+ alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu)
+ COREFILE=''
+ ;;
+- alpha*-*-linux-gnu*)
++ alpha*-*-linux-*)
+ COREFILE=trad-core.lo
+ TRAD_HEADER='"hosts/alphalinux.h"'
+ ;;
+@@ -248,7 +248,7 @@
+ TRAD_HEADER='"hosts/i386mach3.h"'
+ ;;
+ changequote(,)dnl
+- i[3-7]86-*-linux-gnu*)
++ i[3-7]86-*-linux-*)
+ changequote([,])dnl
+ COREFILE=trad-core.lo
+ TRAD_HEADER='"hosts/i386linux.h"'
+@@ -289,7 +289,7 @@
+ COREFILE=trad-core.lo
+ TRAD_HEADER='"hosts/hp300bsd.h"'
+ ;;
+- m68*-*-linux-gnu*)
++ m68*-*-linux-*)
+ COREFILE=trad-core.lo
+ TRAD_HEADER='"hosts/m68klinux.h"'
+ ;;
+@@ -375,7 +375,7 @@
+ COREFILE=trad-core.lo
+ TRAD_HEADER='"hosts/vaxult2.h"'
+ ;;
+- vax-*-linux-gnu*)
++ vax-*-linux-*)
+ COREFILE=trad-core.lo
+ TRAD_HEADER='"hosts/vaxlinux.h"'
+ ;;
+diff -ur binutils-2.15.97.orig/gas/configure binutils-2.15.97/gas/configure
+--- binutils-2.15.97.orig/gas/configure 2005-04-29 20:48:14.000000000 -0400
++++ binutils-2.15.97/gas/configure 2005-04-29 20:53:50.000000000 -0400
+@@ -4462,7 +4462,7 @@
+ _ACEOF
+
+ ;;
+- ppc-*-linux-gnu*)
++ ppc-*-linux-*)
+ case "$endian" in
+ big) ;;
+ *) { { echo "$as_me:$LINENO: error: GNU/Linux must be configured big endian" >&5
+diff -ur binutils-2.15.97.orig/gas/configure.in binutils-2.15.97/gas/configure.in
+--- binutils-2.15.97.orig/gas/configure.in 2005-04-29 20:48:14.000000000 -0400
++++ binutils-2.15.97/gas/configure.in 2005-04-29 20:53:50.000000000 -0400
+@@ -161,7 +161,7 @@
+ AC_DEFINE(AIX_WEAK_SUPPORT, 1,
+ [Define if using AIX 5.2 value for C_WEAKEXT.])
+ ;;
+- ppc-*-linux-gnu*)
++ ppc-*-linux-*)
+ case "$endian" in
+ big) ;;
+ *) AC_MSG_ERROR(GNU/Linux must be configured big endian) ;;
+diff -ur binutils-2.15.97.orig/gas/configure.tgt binutils-2.15.97/gas/configure.tgt
+--- binutils-2.15.97.orig/gas/configure.tgt 2005-04-29 20:48:14.000000000 -0400
++++ binutils-2.15.97/gas/configure.tgt 2005-04-29 20:53:50.000000000 -0400
+@@ -100,7 +100,7 @@
+ alpha-*-*vms*) fmt=evax ;;
+ alpha-*-osf*) fmt=ecoff ;;
+ alpha-*-linuxecoff*) fmt=ecoff ;;
+- alpha-*-linux-gnu*) fmt=elf em=linux ;;
++ alpha-*-linux-*) fmt=elf em=linux ;;
+ alpha-*-netbsd*) fmt=elf em=nbsd ;;
+ alpha-*-openbsd*) fmt=elf em=obsd ;;
+
+@@ -116,7 +116,7 @@
+ arm-*-conix*) fmt=elf ;;
+ arm-*-linux*aout*) fmt=aout em=linux ;;
+ arm-*-linux-gnueabi*) fmt=elf em=armlinuxeabi ;;
+- arm-*-linux-gnu*) fmt=elf em=linux ;;
++ arm-*-linux-*) fmt=elf em=linux ;;
+ arm-*-uclinux*) fmt=elf em=linux ;;
+ arm-*-netbsdelf*) fmt=elf em=nbsd ;;
+ arm-*-*n*bsd*) fmt=aout em=nbsd ;;
+@@ -128,7 +128,7 @@
+
+ avr-*-*) fmt=elf ;;
+
+- cris-*-linux-gnu* | crisv32-*-linux-gnu*)
++ cris-*-linux-* | crisv32-*-linux-*)
+ fmt=multi bfd_gas=yes em=linux ;;
+ cris-*-* | crisv32-*-*) fmt=multi bfd_gas=yes ;;
+
+@@ -192,7 +192,7 @@
+ i386-*-linux*aout*) fmt=aout em=linux ;;
+ i386-*-linux*oldld) fmt=aout em=linux ;;
+ i386-*-linux*coff*) fmt=coff em=linux ;;
+- i386-*-linux-gnu*) fmt=elf em=linux ;;
++ i386-*-linux-*) fmt=elf em=linux ;;
+ i386-*-lynxos*) fmt=elf em=lynx bfd_gas=yes ;;
+ i386-*-sysv[45]*) fmt=elf ;;
+ i386-*-solaris*) fmt=elf ;;
+@@ -238,7 +238,7 @@
+
+ ia64-*-elf*) fmt=elf ;;
+ ia64-*-aix*) fmt=elf em=ia64aix ;;
+- ia64-*-linux-gnu*) fmt=elf em=linux ;;
++ ia64-*-linux-*) fmt=elf em=linux ;;
+ ia64-*-hpux*) fmt=elf em=hpux ;;
+ ia64-*-netbsd*) fmt=elf em=nbsd ;;
+
+@@ -265,7 +265,7 @@
+ m68k-*-rtems*) fmt=elf ;;
+ m68k-*-hpux*) fmt=hp300 em=hp300 ;;
+ m68k-*-linux*aout*) fmt=aout em=linux ;;
+- m68k-*-linux-gnu*) fmt=elf em=linux ;;
++ m68k-*-linux-*) fmt=elf em=linux ;;
+ m68k-*-uclinux*) fmt=elf ;;
+ m68k-*-gnu*) fmt=elf ;;
+ m68k-*-netbsdelf*) fmt=elf em=nbsd ;;
+@@ -332,7 +332,7 @@
+ ppc-*-beos*) fmt=coff ;;
+ ppc-*-*n*bsd* | ppc-*-elf*) fmt=elf ;;
+ ppc-*-eabi* | ppc-*-sysv4*) fmt=elf ;;
+- ppc-*-linux-gnu*) fmt=elf em=linux ;;
++ ppc-*-linux-*) fmt=elf em=linux ;;
+ ppc-*-solaris*) fmt=elf ;;
+ ppc-*-rtems*) fmt=elf ;;
+ ppc-*-macos*) fmt=coff em=macos ;;
+@@ -340,7 +340,7 @@
+ ppc-*-kaos*) fmt=elf ;;
+ ppc-*-lynxos*) fmt=elf em=lynx bfd_gas=yes ;;
+
+- s390-*-linux-gnu*) fmt=elf em=linux ;;
++ s390-*-linux-*) fmt=elf em=linux ;;
+ s390-*-tpf*) fmt=elf ;;
+
+ sh*-*-linux*) fmt=elf em=linux
+@@ -369,7 +369,7 @@
+ sparc-*-aout | sparc*-*-vxworks*) fmt=aout em=sparcaout ;;
+ sparc-*-coff) fmt=coff ;;
+ sparc-*-linux*aout*) fmt=aout em=linux ;;
+- sparc-*-linux-gnu*) fmt=elf em=linux ;;
++ sparc-*-linux-*) fmt=elf em=linux ;;
+ sparc-fujitsu-none) fmt=aout ;;
+ sparc-*-elf) fmt=elf ;;
+ sparc-*-sysv4*) fmt=elf ;;
+@@ -398,7 +398,7 @@
+ vax-*-netbsdelf*) fmt=elf em=nbsd ;;
+ vax-*-netbsd*) fmt=aout em=nbsd ;;
+ vax-*-bsd* | vax-*-ultrix*) fmt=aout ;;
+- vax-*-linux-gnu*) fmt=elf em=linux bfd_gas=yes ;;
++ vax-*-linux-*) fmt=elf em=linux bfd_gas=yes ;;
+
+ w65-*-*) fmt=coff ;;
+
+diff -ur binutils-2.15.97.orig/ld/configure.host binutils-2.15.97/ld/configure.host
+--- binutils-2.15.97.orig/ld/configure.host 2005-04-29 20:48:15.000000000 -0400
++++ binutils-2.15.97/ld/configure.host 2005-04-29 20:53:50.000000000 -0400
+@@ -83,7 +83,7 @@
+ HOSTING_CRT0=`echo "$HOSTING_CRT0" | sed -e "s,ld\[^ \]\*,ld-linux,g"`
+ ;;
+
+-arm*-*-linux-gnu*)
++arm*-*-linux-*)
+ HOSTING_CRT0='-p '`echo "$HOSTING_CRT0" | sed -e "s,ld\[^ \]\*,ld-linux,g"`
+ ;;
+
+@@ -141,7 +141,7 @@
+ HOSTING_LIBS="$HOSTING_LIBS"' -lcygwin -L/usr/lib/w32api -luser32 -lkernel32 -ladvapi32 -lshell32 `if [ -f ../gcc/libgcc.a ] ; then echo ../gcc/libgcc.a ; else ${CC} -print-libgcc-file-name; fi`'
+ ;;
+
+-ia64-*-linux-gnu*)
++ia64-*-linux-*)
+ HOSTING_CRT0=`echo "$HOSTING_CRT0" | sed -e "s,ld\[^ \]*\*,ld-linux-ia64,g"`
+ ;;
+
+@@ -155,11 +155,11 @@
+ HOSTING_LIBS='-L/usr/lib32 '"$HOSTING_LIBS"' `if [ -f ../gcc/crtend.o ]; then echo ../gcc/crtend.o ; else ${CC} -print-file-name=crtend.o; fi` /usr/lib32/crtn.o -init __do_global_ctors -fini __do_global_dtors'
+ ;;
+
+-mips*-*-linux-gnu*)
++mips*-*-linux-*)
+ HOSTING_CRT0=`echo "$HOSTING_CRT0" | sed -e "s,\\\`specs.*\"\\\`,/lib/ld.so.1,"`
+ ;;
+
+-m68*-*-linux-gnu*)
++m68*-*-linux-*)
+ HOSTING_CRT0=`echo "$HOSTING_CRT0" | sed -e "s,\\\`specs.*\"\\\`,/lib/ld.so.1,"`
+ ;;
+
+@@ -183,19 +183,19 @@
+ HOSTING_LIBS="$HOSTING_LIBS"' `if [ -f ../gcc/crtend.o ]; then echo ../gcc/crtend.o; else ${CC} -print-file-name=crtend.o; fi`'
+ ;;
+
+-powerpc64*-*-linux-gnu*)
++powerpc64*-*-linux-*)
+ HOSTING_CRT0=`echo "$HOSTING_CRT0" | sed -e "s,\\\`specs.*\"\\\`,/lib64/ld64.so.1,"`
+ ;;
+
+-powerpc*-*-linux-gnu*)
++powerpc*-*-linux-*)
+ HOSTING_CRT0=`echo "$HOSTING_CRT0" | sed -e "s,\\\`specs.*\"\\\`,/lib/ld.so.1,"`
+ ;;
+
+-s390x-*-linux-gnu*)
++s390x-*-linux-*)
+ HOSTING_CRT0=`echo "$HOSTING_CRT0" | sed -e "s,\\\`specs.*\"\\\`,/lib/ld64.so.1,"`
+ ;;
+
+-s390-*-linux-gnu*)
++s390-*-linux-*)
+ HOSTING_CRT0=`echo "$HOSTING_CRT0" | sed -e "s,\\\`specs.*\"\\\`,/lib/ld.so.1,"`
+ ;;
+
+@@ -209,15 +209,15 @@
+ HOSTING_LIBS="$HOSTING_LIBS"' `if [ -f ../gcc/crtend.o ]; then echo ../gcc/crtend.o; else ${CC} -print-file-name=crtend.o; fi` `if [ -f ../gcc/crtn.o ]; then echo ../gcc/crtn.o; else ${CC} -print-file-name=crtn.o; fi`'
+ ;;
+
+-sparc-*-linux-gnu*)
++sparc-*-linux-*)
+ HOSTING_CRT0=`echo "$HOSTING_CRT0" | sed -e "s,\\\`specs.*\"\\\`,/lib/ld-linux.so.2,"`
+ ;;
+
+-sparc64-*-linux-gnu*)
++sparc64-*-linux-*)
+ HOSTING_CRT0=`echo "$HOSTING_CRT0" | sed -e "s,\\\`specs.*\"\\\`,/lib64/ld-linux.so.2,"`
+ ;;
+
+-x86_64-*-linux-gnu*)
++x86_64-*-linux-*)
+ HOSTING_CRT0=`echo "$HOSTING_CRT0" | sed -e "s,\\\`specs.*\"\\\`,/lib64/ld-linux-x86-64.so.2,"`
+ ;;
+
+diff -ur binutils-2.15.97.orig/ld/configure.tgt binutils-2.15.97/ld/configure.tgt
+--- binutils-2.15.97.orig/ld/configure.tgt 2005-04-29 20:48:15.000000000 -0400
++++ binutils-2.15.97/ld/configure.tgt 2005-04-29 20:53:50.000000000 -0400
+@@ -30,7 +30,7 @@
+ cris-*-*aout*) targ_emul=crisaout
+ targ_extra_emuls="criself crislinux"
+ targ_extra_libpath=$targ_extra_emuls ;;
+-cris-*-linux-gnu* | cris-*-linux-gnu*)
++cris-*-linux-* | crisv32-*-linux-*)
+ targ_emul=crislinux ;;
+ cris-*-* | crisv32-*-*) targ_emul=criself
+ targ_extra_emuls="crisaout crislinux"
+@@ -62,14 +62,14 @@
+ tdir_elf32_sparc=`echo ${targ_alias} | sed -e 's/aout//'`
+ tdir_sun4=sparc-sun-sunos4
+ ;;
+-sparc64-*-linux-gnu*) targ_emul=elf64_sparc
++sparc64-*-linux-*) targ_emul=elf64_sparc
+ targ_extra_emuls="elf32_sparc sparclinux sun4"
+ targ_extra_libpath=elf32_sparc
+ tdir_elf32_sparc=`echo ${targ_alias} | sed -e 's/64//'`
+ tdir_sparclinux=${tdir_elf32_sparc}aout
+ tdir_sun4=sparc-sun-sunos4
+ ;;
+-sparc*-*-linux-gnu*) targ_emul=elf32_sparc
++sparc*-*-linux-*) targ_emul=elf32_sparc
+ targ_extra_emuls="sparclinux elf64_sparc sun4"
+ targ_extra_libpath=elf64_sparc
+ tdir_sparclinux=${targ_alias}aout
+@@ -119,8 +119,8 @@
+ ia64-*-aix*) targ_emul=elf64_aix ;;
+ m32r*le-*-elf*) targ_emul=m32rlelf ;;
+ m32r*-*-elf*) targ_emul=m32relf ;;
+-m32r*le-*-linux-gnu*) targ_emul=m32rlelf_linux ;;
+-m32r*-*-linux-gnu*) targ_emul=m32relf_linux ;;
++m32r*le-*-linux-*) targ_emul=m32rlelf_linux ;;
++m32r*-*-linux-*) targ_emul=m32relf_linux ;;
+ m68hc11-*-*|m6811-*-*) targ_emul=m68hc11elf
+ targ_extra_emuls="m68hc11elfb m68hc12elf m68hc12elfb" ;;
+ m68hc12-*-*|m6812-*-*) targ_emul=m68hc12elf
+@@ -131,7 +131,7 @@
+ m68*-apple-aux*) targ_emul=m68kaux ;;
+ maxq-*-coff) targ_emul=maxqcoff;;
+ *-tandem-none) targ_emul=st2000 ;;
+-i370-*-elf* | i370-*-linux-gnu*) targ_emul=elf32i370 ;;
++i370-*-elf* | i370-*-linux-*) targ_emul=elf32i370 ;;
+ i[3-7]86-*-nto-qnx*) targ_emul=i386nto ;;
+ i[3-7]86-*-vsta) targ_emul=vsta ;;
+ i[3-7]86-go32-rtems*) targ_emul=i386go32 ;;
+@@ -155,14 +155,14 @@
+ tdir_elf_i386=`echo ${targ_alias} | sed -e 's/aout//'`
+ ;;
+ i[3-7]86-*-linux*oldld) targ_emul=i386linux; targ_extra_emuls=elf_i386 ;;
+-i[3-7]86-*-linux-gnu*) targ_emul=elf_i386
++i[3-7]86-*-linux-*) targ_emul=elf_i386
+ targ_extra_emuls=i386linux
+ if test x${want64} = xtrue; then
+ targ_extra_emuls="$targ_extra_emuls elf_x86_64"
+ fi
+ tdir_i386linux=${targ_alias}aout
+ ;;
+-x86_64-*-linux-gnu*) targ_emul=elf_x86_64
++x86_64-*-linux-*) targ_emul=elf_x86_64
+ targ_extra_emuls="elf_i386 i386linux"
+ targ_extra_libpath=elf_i386
+ tdir_i386linux=`echo ${targ_alias}aout | sed -e 's/x86_64/i386/'`
+@@ -262,13 +262,13 @@
+ arm-*-kaos*) targ_emul=armelf ;;
+ arm9e-*-elf) targ_emul=armelf ;;
+ arm*b-*-linux-gnueabi) targ_emul=armelfb_linux_eabi ;;
+-arm*b-*-linux-gnu*) targ_emul=armelfb_linux; targ_extra_emuls=armelfb ;;
++arm*b-*-linux-*) targ_emul=armelfb_linux; targ_extra_emuls=armelfb ;;
+ arm*-*-linux-gnueabi) targ_emul=armelf_linux_eabi ;;
+-arm*-*-linux-gnu*) targ_emul=armelf_linux; targ_extra_emuls=armelf ;;
++arm*-*-linux-*) targ_emul=armelf_linux; targ_extra_emuls=armelf ;;
+ arm*-*-uclinux*) targ_emul=armelf_linux; targ_extra_emuls=armelf ;;
+ arm-*-vxworks) targ_emul=armelf_vxworks ;;
+ arm*-*-conix*) targ_emul=armelf ;;
+-thumb-*-linux-gnu* | thumb-*-uclinux*) targ_emul=armelf_linux; targ_extra_emuls=armelf ;;
++thumb-*-linux-* | thumb-*-uclinux*) targ_emul=armelf_linux; targ_extra_emuls=armelf ;;
+ strongarm-*-coff) targ_emul=armcoff ;;
+ strongarm-*-elf) targ_emul=armelf ;;
+ strongarm-*-kaos*) targ_emul=armelf ;;
+@@ -372,7 +372,7 @@
+ targ_extra_emuls=m68kelf
+ tdir_m68kelf=`echo ${targ_alias} | sed -e 's/aout//'`
+ ;;
+-m68k-*-linux-gnu*) targ_emul=m68kelf
++m68k-*-linux-*) targ_emul=m68kelf
+ targ_extra_emuls=m68klinux
+ tdir_m68klinux=`echo ${targ_alias} | sed -e 's/linux/linuxaout/'`
+ ;;
+@@ -388,9 +388,9 @@
+ m68*-*-psos*) targ_emul=m68kpsos ;;
+ m68*-*-rtemscoff*) targ_emul=m68kcoff ;;
+ m68*-*-rtems*) targ_emul=m68kelf ;;
+-hppa*64*-*-linux-gnu*) targ_emul=hppa64linux ;;
++hppa*64*-*-linux-*) targ_emul=hppa64linux ;;
+ hppa*64*-*) targ_emul=elf64hppa ;;
+-hppa*-*-linux-gnu*) targ_emul=hppalinux ;;
++hppa*-*-linux-*) targ_emul=hppalinux ;;
+ hppa*-*-*elf*) targ_emul=hppaelf ;;
+ hppa*-*-lites*) targ_emul=hppaelf ;;
+ hppa*-*-netbsd*) targ_emul=hppanbsd ;;
+@@ -402,7 +402,7 @@
+ vax-*-netbsdaout* | vax-*-netbsd*)
+ targ_emul=vaxnbsd
+ targ_extra_emuls=elf32vax ;;
+-vax-*-linux-gnu*) targ_emul=elf32vax ;;
++vax-*-linux-*) targ_emul=elf32vax ;;
+ mips*-*-pe) targ_emul=mipspe ;
+ targ_extra_ofiles="deffilep.o pe-dll.o" ;;
+ mips*-dec-ultrix*) targ_emul=mipslit ;;
+@@ -436,18 +436,18 @@
+ mips*-*-vxworks*) targ_emul=elf32ebmip
+ targ_extra_emuls="elf32elmip" ;;
+ mips*-*-windiss) targ_emul=elf32mipswindiss ;;
+-mips64*el-*-linux-gnu*) targ_emul=elf32ltsmipn32
++mips64*el-*-linux-*) targ_emul=elf32ltsmipn32
+ targ_extra_emuls="elf32btsmipn32 elf32ltsmip elf32btsmip elf64ltsmip elf64btsmip"
+ targ_extra_libpath="elf32ltsmip elf64ltsmip"
+ ;;
+-mips64*-*-linux-gnu*) targ_emul=elf32btsmipn32
++mips64*-*-linux-*) targ_emul=elf32btsmipn32
+ targ_extra_emuls="elf32ltsmipn32 elf32btsmip elf32ltsmip elf64btsmip elf64ltsmip"
+ targ_extra_libpath="elf32btsmip elf64btsmip"
+ ;;
+-mips*el-*-linux-gnu*) targ_emul=elf32ltsmip
++mips*el-*-linux-*) targ_emul=elf32ltsmip
+ targ_extra_emuls="elf32btsmip elf32ltsmipn32 elf64ltsmip elf32btsmipn32 elf64btsmip"
+ ;;
+-mips*-*-linux-gnu*) targ_emul=elf32btsmip
++mips*-*-linux-*) targ_emul=elf32btsmip
+ targ_extra_emuls="elf32ltsmip elf32btsmipn32 elf64btsmip elf32ltsmipn32 elf64ltsmip"
+ ;;
+ mips*-*-lnews*) targ_emul=mipslnews ;;
+@@ -467,7 +467,7 @@
+ alpha*-*-linuxecoff*) targ_emul=alpha targ_extra_emuls=elf64alpha
+ tdir_elf64alpha=`echo ${targ_alias} | sed -e 's/ecoff//'`
+ ;;
+-alpha*-*-linux-gnu*) targ_emul=elf64alpha targ_extra_emuls=alpha
++alpha*-*-linux-*) targ_emul=elf64alpha targ_extra_emuls=alpha
+ tdir_alpha=`echo ${targ_alias} | sed -e 's/linux/linuxecoff/'`
+ ;;
+ alpha*-*-osf*) targ_emul=alpha ;;
+diff -ur binutils-2.15.97.orig/ld/emultempl/elf32.em binutils-2.15.97/ld/emultempl/elf32.em
+--- binutils-2.15.97.orig/ld/emultempl/elf32.em 2005-04-29 20:48:15.000000000 -0400
++++ binutils-2.15.97/ld/emultempl/elf32.em 2005-04-29 20:53:50.000000000 -0400
+@@ -65,7 +65,7 @@
+
+ if [ "x${USE_LIBPATH}" = xyes ] ; then
+ case ${target} in
+- *-*-linux-gnu*)
++ *-*-linux-*)
+ cat >>e${EMULATION_NAME}.c <<EOF
+ #ifdef HAVE_GLOB
+ #include <glob.h>
+@@ -350,7 +350,7 @@
+
+ EOF
+ case ${target} in
+- *-*-linux-gnu*)
++ *-*-linux-*)
+ cat >>e${EMULATION_NAME}.c <<EOF
+ {
+ struct bfd_link_needed_list *l;
+@@ -522,7 +522,7 @@
+
+ EOF
+ case ${target} in
+- *-*-linux-gnu*)
++ *-*-linux-*)
+ cat >>e${EMULATION_NAME}.c <<EOF
+ /* For a native linker, check the file /etc/ld.so.conf for directories
+ in which we may find shared libraries. /etc/ld.so.conf is really
+@@ -932,7 +932,7 @@
+ EOF
+ if [ "x${USE_LIBPATH}" = xyes ] ; then
+ case ${target} in
+- *-*-linux-gnu*)
++ *-*-linux-*)
+ cat >>e${EMULATION_NAME}.c <<EOF
+ if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
+ break;
diff --git a/toolchain/binutils/patches/2.16.1/110-uclibc-libtool-conf.patch b/toolchain/binutils/patches/2.16.1/110-uclibc-libtool-conf.patch
new file mode 100644
index 0000000000..ec38caa125
--- /dev/null
+++ b/toolchain/binutils/patches/2.16.1/110-uclibc-libtool-conf.patch
@@ -0,0 +1,218 @@
+diff -urN binutils-2.16.90.0.2-dist/bfd/configure binutils-2.16.90.0.2/bfd/configure
+--- binutils-2.16.90.0.2-dist/bfd/configure 2005-04-29 12:50:24.000000000 -0500
++++ binutils-2.16.90.0.2/bfd/configure 2005-04-30 11:34:59.246377032 -0500
+@@ -3584,6 +3584,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd* | knetbsd*-gnu)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+diff -urN binutils-2.16.90.0.2-dist/binutils/configure binutils-2.16.90.0.2/binutils/configure
+--- binutils-2.16.90.0.2-dist/binutils/configure 2005-04-29 12:50:26.000000000 -0500
++++ binutils-2.16.90.0.2/binutils/configure 2005-04-30 11:35:28.900868864 -0500
+@@ -1577,6 +1577,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd* | knetbsd*-gnu)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+diff -urN binutils-2.16.90.0.2-dist/configure binutils-2.16.90.0.2/configure
+--- binutils-2.16.90.0.2-dist/configure 2005-04-29 12:50:23.000000000 -0500
++++ binutils-2.16.90.0.2/configure 2005-04-30 11:31:12.525843792 -0500
+@@ -1111,7 +1111,7 @@
+ ;;
+ "")
+ case "${target}" in
+- *-*-linux*-gnu | *-*-gnu* | *-*-k*bsd*-gnu)
++ *-*-linux*-gnu | *-*-gnu* | *-*-k*bsd*-gnu | *-*-linux-uclibc*)
+ # Enable libmudflap by default in GNU and friends.
+ ;;
+ *-*-freebsd*)
+diff -urN binutils-2.16.90.0.2-dist/configure.in binutils-2.16.90.0.2/configure.in
+--- binutils-2.16.90.0.2-dist/configure.in 2005-04-29 12:50:23.000000000 -0500
++++ binutils-2.16.90.0.2/configure.in 2005-04-30 11:29:51.643139832 -0500
+@@ -328,7 +328,7 @@
+ ;;
+ "")
+ case "${target}" in
+- *-*-linux*-gnu | *-*-gnu* | *-*-k*bsd*-gnu)
++ *-*-linux*-gnu | *-*-gnu* | *-*-k*bsd*-gnu | *-*-linux-uclibc*)
+ # Enable libmudflap by default in GNU and friends.
+ ;;
+ *-*-freebsd*)
+diff -urN binutils-2.16.90.0.2-dist/gas/configure binutils-2.16.90.0.2/gas/configure
+--- binutils-2.16.90.0.2-dist/gas/configure 2005-04-29 12:50:27.000000000 -0500
++++ binutils-2.16.90.0.2/gas/configure 2005-04-30 11:35:21.097055224 -0500
+@@ -3421,6 +3421,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd* | knetbsd*-gnu)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+diff -urN binutils-2.16.90.0.2-dist/gas/testsuite/gas/sh/basic.exp binutils-2.16.90.0.2/gas/testsuite/gas/sh/basic.exp
+--- binutils-2.16.90.0.2-dist/gas/testsuite/gas/sh/basic.exp 2005-04-09 14:03:14.000000000 -0500
++++ binutils-2.16.90.0.2/gas/testsuite/gas/sh/basic.exp 2005-04-30 11:41:57.301822944 -0500
+@@ -20,7 +20,7 @@
+
+ # Written by Cygnus Support.
+
+-if [istarget "sh*-*-linux-gnu"] {
++if {[istarget "sh*-*-linux-gnu"] || [istarget "sh*-*-linux-uclibc"]} {
+ global ASFLAGS
+ set ASFLAGS "$ASFLAGS -big"
+ }
+diff -urN binutils-2.16.90.0.2-dist/gprof/configure binutils-2.16.90.0.2/gprof/configure
+--- binutils-2.16.90.0.2-dist/gprof/configure 2005-04-29 12:50:29.000000000 -0500
++++ binutils-2.16.90.0.2/gprof/configure 2005-04-30 11:35:36.880655752 -0500
+@@ -3419,6 +3419,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd* | knetbsd*-gnu)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+diff -urN binutils-2.16.90.0.2-dist/ld/configure binutils-2.16.90.0.2/ld/configure
+--- binutils-2.16.90.0.2-dist/ld/configure 2005-04-29 12:50:30.000000000 -0500
++++ binutils-2.16.90.0.2/ld/configure 2005-04-30 11:46:15.974498720 -0500
+@@ -1581,6 +1581,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd* | knetbsd*-gnu)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+diff -urN binutils-2.16.90.0.2-dist/ld/testsuite/ld-sh/sh.exp binutils-2.16.90.0.2/ld/testsuite/ld-sh/sh.exp
+--- binutils-2.16.90.0.2-dist/ld/testsuite/ld-sh/sh.exp 2005-04-09 14:03:29.000000000 -0500
++++ binutils-2.16.90.0.2/ld/testsuite/ld-sh/sh.exp 2005-04-30 11:45:07.890849008 -0500
+@@ -62,7 +62,7 @@
+
+ set testsrec "SH relaxing to S-records"
+
+-if [istarget sh*-linux-gnu] {
++if {[istarget sh*-linux-gnu] || [istarget sh*-*-linux-uclibc]} {
+ # This target needs the explicit entry address.
+ catch "exec $objdump -x tmpdir/sh1 | grep start\\ address | sed s/start\\ address//" entry_addr
+ set srec_relax_arg "-Ttext $entry_addr -relax --oformat srec tmpdir/sh1.o"
+@@ -117,7 +117,7 @@
+ return
+ }
+
+-if [istarget sh*-linux-gnu] {
++if {[istarget sh*-linux-gnu] || [istarget sh*-*-linux-uclibc]} {
+ exec sed -e s/_main/main/ -e s/_trap/trap/ -e s/_stack/stack/ \
+ < $srcdir/$subdir/start.s >tmpdir/start.s
+ } else {
+diff -urN binutils-2.16.90.0.2-dist/ld/testsuite/ld-srec/srec.exp binutils-2.16.90.0.2/ld/testsuite/ld-srec/srec.exp
+--- binutils-2.16.90.0.2-dist/ld/testsuite/ld-srec/srec.exp 2005-04-29 12:50:30.000000000 -0500
++++ binutils-2.16.90.0.2/ld/testsuite/ld-srec/srec.exp 2005-04-30 11:44:26.358162936 -0500
+@@ -385,7 +385,7 @@
+ setup_xfail "v850*-*-elf"
+
+ # The S-record linker doesn't handle Alpha Elf relaxation.
+-setup_xfail "alpha*-*-elf*" "alpha*-*-linux-gnu*" "alpha*-*-gnu*"
++setup_xfail "alpha*-*-elf*" "alpha*-*-linux-gnu*" "alpha*-*-gnu*" "alpha*-*-linux-uclibc*"
+ setup_xfail "alpha*-*-netbsd*"
+
+ # The S-record linker hasn't any hope of coping with HPPA relocs.
+@@ -424,7 +424,7 @@
+ setup_xfail "thumb-*-*"
+ setup_xfail "powerpc*-*-eabi*"
+ setup_xfail "v850*-*-elf"
+-setup_xfail "alpha*-*-elf*" "alpha*-*-linux-gnu*" "alpha*-*-gnu*"
++setup_xfail "alpha*-*-elf*" "alpha*-*-linux-gnu*" "alpha*-*-gnu*" "alpha*-*-linux-uclibc*"
+ setup_xfail "alpha*-*-netbsd*"
+ setup_xfail "hppa*-*-*"
+ setup_xfail "ia64-*-*"
+diff -urN binutils-2.16.90.0.2-dist/libtool.m4 binutils-2.16.90.0.2/libtool.m4
+--- binutils-2.16.90.0.2-dist/libtool.m4 2004-07-27 23:36:06.000000000 -0500
++++ binutils-2.16.90.0.2/libtool.m4 2005-04-30 11:35:54.062043784 -0500
+@@ -645,6 +645,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd* | knetbsd*-gnu)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ [lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$']
+diff -urN binutils-2.16.90.0.2-dist/ltconfig binutils-2.16.90.0.2/ltconfig
+--- binutils-2.16.90.0.2-dist/ltconfig 2004-11-22 14:33:30.000000000 -0600
++++ binutils-2.16.90.0.2/ltconfig 2005-04-30 11:22:10.594229920 -0500
+@@ -602,6 +602,7 @@
+
+ # Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+ case $host_os in
++linux-uclibc*) ;;
+ linux-gnu*) ;;
+ linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+ esac
+@@ -1270,6 +1271,23 @@
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
++linux-uclibc*)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
++ soname_spec='${libname}${release}.so$major'
++ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ # This implies no fast_install, which is unacceptable.
++ # Some rework will be needed to allow for fast_install
++ # before this can be enabled.
++ hardcode_into_libs=yes
++ # Assume using the uClibc dynamic linker.
++ dynamic_linker="uClibc ld.so"
++ ;;
++
+ netbsd*)
+ need_lib_prefix=no
+ need_version=no
+diff -urN binutils-2.16.90.0.2-dist/opcodes/configure binutils-2.16.90.0.2/opcodes/configure
+--- binutils-2.16.90.0.2-dist/opcodes/configure 2005-04-29 12:50:31.000000000 -0500
++++ binutils-2.16.90.0.2/opcodes/configure 2005-04-30 11:17:07.168357664 -0500
+@@ -3588,6 +3588,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd* | knetbsd*-gnu)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
diff --git a/toolchain/binutils/patches/2.16.1/300-001_ld_makefile_patch.patch b/toolchain/binutils/patches/2.16.1/300-001_ld_makefile_patch.patch
new file mode 100644
index 0000000000..b25d5b7e21
--- /dev/null
+++ b/toolchain/binutils/patches/2.16.1/300-001_ld_makefile_patch.patch
@@ -0,0 +1,52 @@
+#!/bin/sh -e
+## 001_ld_makefile_patch.dpatch
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: correct where ld scripts are installed
+## DP: Author: Chris Chimelis <chris@debian.org>
+## DP: Upstream status: N/A
+## DP: Date: ??
+
+if [ $# -ne 1 ]; then
+ echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+ exit 1
+fi
+
+[ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts
+patch_opts="${patch_opts:--f --no-backup-if-mismatch}"
+
+case "$1" in
+ -patch) patch $patch_opts -p1 < $0;;
+ -unpatch) patch $patch_opts -p1 -R < $0;;
+ *)
+ echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+ exit 1;;
+esac
+
+exit 0
+
+@DPATCH@
+diff -urNad /home/james/debian/packages/binutils/binutils-2.14.90.0.6/ld/Makefile.am binutils-2.14.90.0.6/ld/Makefile.am
+--- /home/james/debian/packages/binutils/binutils-2.14.90.0.6/ld/Makefile.am 2003-08-21 16:28:48.000000000 +0100
++++ binutils-2.14.90.0.6/ld/Makefile.am 2003-09-10 23:12:09.000000000 +0100
+@@ -19,7 +19,7 @@
+ # We put the scripts in the directory $(scriptdir)/ldscripts.
+ # We can't put the scripts in $(datadir) because the SEARCH_DIR
+ # directives need to be different for native and cross linkers.
+-scriptdir = $(tooldir)/lib
++scriptdir = $(libdir)
+
+ EMUL = @EMUL@
+ EMULATION_OFILES = @EMULATION_OFILES@
+diff -urNad /home/james/debian/packages/binutils/binutils-2.14.90.0.6/ld/Makefile.in binutils-2.14.90.0.6/ld/Makefile.in
+--- /home/james/debian/packages/binutils/binutils-2.14.90.0.6/ld/Makefile.in 2003-08-21 16:28:48.000000000 +0100
++++ binutils-2.14.90.0.6/ld/Makefile.in 2003-09-10 23:12:09.000000000 +0100
+@@ -128,7 +128,7 @@
+ # We put the scripts in the directory $(scriptdir)/ldscripts.
+ # We can't put the scripts in $(datadir) because the SEARCH_DIR
+ # directives need to be different for native and cross linkers.
+-scriptdir = $(tooldir)/lib
++scriptdir = $(libdir)
+
+ EMUL = @EMUL@
+ EMULATION_OFILES = @EMULATION_OFILES@
diff --git a/toolchain/binutils/patches/2.16.1/300-006_better_file_error.patch b/toolchain/binutils/patches/2.16.1/300-006_better_file_error.patch
new file mode 100644
index 0000000000..f337611edf
--- /dev/null
+++ b/toolchain/binutils/patches/2.16.1/300-006_better_file_error.patch
@@ -0,0 +1,43 @@
+#!/bin/sh -e
+## 006_better_file_error.dpatch by David Kimdon <dwhedon@gordian.com>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Specify which filename is causing an error if the filename is a
+## DP: directory. (#45832)
+
+if [ $# -ne 1 ]; then
+ echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+ exit 1
+fi
+
+[ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts
+patch_opts="${patch_opts:--f --no-backup-if-mismatch}"
+
+case "$1" in
+ -patch) patch $patch_opts -p1 < $0;;
+ -unpatch) patch $patch_opts -p1 -R < $0;;
+ *)
+ echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+ exit 1;;
+esac
+
+exit 0
+
+@DPATCH@
+diff -urNad /home/james/debian/packages/binutils/binutils-2.14.90.0.6/bfd/opncls.c binutils-2.14.90.0.6/bfd/opncls.c
+--- /home/james/debian/packages/binutils/binutils-2.14.90.0.6/bfd/opncls.c 2003-07-23 16:08:09.000000000 +0100
++++ binutils-2.14.90.0.6/bfd/opncls.c 2003-09-10 22:35:00.000000000 +0100
+@@ -150,6 +150,13 @@
+ {
+ bfd *nbfd;
+ const bfd_target *target_vec;
++ struct stat s;
++
++ if (stat (filename, &s) == 0)
++ if (S_ISDIR(s.st_mode)) {
++ bfd_set_error (bfd_error_file_not_recognized);
++ return NULL;
++ }
+
+ nbfd = _bfd_new_bfd ();
+ if (nbfd == NULL)
diff --git a/toolchain/binutils/patches/2.16.1/300-012_check_ldrunpath_length.patch b/toolchain/binutils/patches/2.16.1/300-012_check_ldrunpath_length.patch
new file mode 100644
index 0000000000..498651a90c
--- /dev/null
+++ b/toolchain/binutils/patches/2.16.1/300-012_check_ldrunpath_length.patch
@@ -0,0 +1,47 @@
+#!/bin/sh -e
+## 012_check_ldrunpath_length.dpatch by Chris Chimelis <chris@debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Only generate an RPATH entry if LD_RUN_PATH is not empty, for
+## DP: cases where -rpath isn't specified. (#151024)
+
+if [ $# -ne 1 ]; then
+ echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+ exit 1
+fi
+
+[ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts
+patch_opts="${patch_opts:--f --no-backup-if-mismatch}"
+
+case "$1" in
+ -patch) patch $patch_opts -p1 < $0;;
+ -unpatch) patch $patch_opts -p1 -R < $0;;
+ *)
+ echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+ exit 1;;
+esac
+
+exit 0
+
+@DPATCH@
+diff -urNad /home/james/debian/packages/binutils/new/binutils-2.15/ld/emultempl/elf32.em binutils-2.15/ld/emultempl/elf32.em
+--- /home/james/debian/packages/binutils/new/binutils-2.15/ld/emultempl/elf32.em 2004-05-21 23:12:58.000000000 +0100
++++ binutils-2.15/ld/emultempl/elf32.em 2004-05-21 23:12:59.000000000 +0100
+@@ -692,6 +692,8 @@
+ && command_line.rpath == NULL)
+ {
+ lib_path = (const char *) getenv ("LD_RUN_PATH");
++ if ((lib_path) && (strlen (lib_path) == 0))
++ lib_path = NULL;
+ if (gld${EMULATION_NAME}_search_needed (lib_path, &n,
+ force))
+ break;
+@@ -871,6 +873,8 @@
+ rpath = command_line.rpath;
+ if (rpath == NULL)
+ rpath = (const char *) getenv ("LD_RUN_PATH");
++ if ((rpath) && (strlen (rpath) == 0))
++ rpath = NULL;
+ if (! (bfd_elf_size_dynamic_sections
+ (output_bfd, command_line.soname, rpath,
+ command_line.filter_shlib,
diff --git a/toolchain/binutils/patches/2.16.1/702-binutils-skip-comments.patch b/toolchain/binutils/patches/2.16.1/702-binutils-skip-comments.patch
new file mode 100644
index 0000000000..9ef7a7c9ec
--- /dev/null
+++ b/toolchain/binutils/patches/2.16.1/702-binutils-skip-comments.patch
@@ -0,0 +1,93 @@
+Retrieved from http://sources.redhat.com/ml/binutils/2004-04/msg00646.html
+Fixes
+localealias.s:544: Error: junk at end of line, first unrecognized character is `,'
+when building glibc-2.3.2 with gcc-3.4.0 and binutils-2.15.90.0.3
+
+Paths adjusted to match crosstool's patcher.
+
+Message-Id: m3n052qw2g.fsf@whitebox.m5r.de
+From: Andreas Schwab <schwab at suse dot de>
+To: Nathan Sidwell <nathan at codesourcery dot com>
+Cc: Ian Lance Taylor <ian at wasabisystems dot com>, binutils at sources dot redhat dot com
+Date: Fri, 23 Apr 2004 22:27:19 +0200
+Subject: Re: demand_empty_rest_of_line and ignore_rest_of_line
+
+Nathan Sidwell <nathan@codesourcery.com> writes:
+
+> Index: read.c
+> ===================================================================
+> RCS file: /cvs/src/src/gas/read.c,v
+> retrieving revision 1.76
+> diff -c -3 -p -r1.76 read.c
+> *** read.c 12 Mar 2004 17:48:12 -0000 1.76
+> --- read.c 18 Mar 2004 09:56:05 -0000
+> *************** read_a_source_file (char *name)
+> *** 1053,1059 ****
+> #endif
+> input_line_pointer--;
+> /* Report unknown char as ignored. */
+> ! ignore_rest_of_line ();
+> }
+>
+> #ifdef md_after_pass_hook
+> --- 1053,1059 ----
+> #endif
+> input_line_pointer--;
+> /* Report unknown char as ignored. */
+> ! demand_empty_rest_of_line ();
+> }
+>
+> #ifdef md_after_pass_hook
+
+This means that the unknown character is no longer ignored, despite the
+comment. As a side effect a line starting with a line comment character
+not followed by APP in NO_APP mode now triggers an error instead of just a
+warning, breaking builds of glibc on m68k-linux. Earlier in
+read_a_source_file where #APP is handled there is another comment that
+claims that unknown comments are ignored, when in fact they aren't (only
+the initial line comment character is skipped).
+
+Note that the presence of #APP will mess up the line counters, but
+that appears to be difficult to fix.
+
+Andreas.
+
+2004-04-23 Andreas Schwab <schwab@suse.de>
+
+ * read.c (read_a_source_file): Ignore unknown text after line
+ comment character. Fix misleading comment.
+
+--- binutils/gas/read.c.~1.78.~ 2004-04-23 08:58:23.000000000 +0200
++++ binutils/gas/read.c 2004-04-23 21:49:01.000000000 +0200
+@@ -950,10 +950,14 @@ read_a_source_file (char *name)
+ unsigned int new_length;
+ char *tmp_buf = 0;
+
+- bump_line_counters ();
+ s = input_line_pointer;
+ if (strncmp (s, "APP\n", 4))
+- continue; /* We ignore it */
++ {
++ /* We ignore it */
++ ignore_rest_of_line ();
++ continue;
++ }
++ bump_line_counters ();
+ s += 4;
+
+ sb_new (&sbuf);
+@@ -1052,7 +1056,7 @@ read_a_source_file (char *name)
+ continue;
+ #endif
+ input_line_pointer--;
+- /* Report unknown char as ignored. */
++ /* Report unknown char as error. */
+ demand_empty_rest_of_line ();
+ }
+
+
+--
+Andreas Schwab, SuSE Labs, schwab@suse.de
+SuSE Linux AG, Maxfeldstra&#xC3;e 5, 90409 N&#xC3;rnberg, Germany
+Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
+"And now for something completely different."
diff --git a/toolchain/binutils/patches/2.17/100-uclibc-conf.patch b/toolchain/binutils/patches/2.17/100-uclibc-conf.patch
new file mode 100644
index 0000000000..25222e5df2
--- /dev/null
+++ b/toolchain/binutils/patches/2.17/100-uclibc-conf.patch
@@ -0,0 +1,139 @@
+--- binutils-2.16.91.0.7/bfd/configure
++++ binutils-2.16.91.0.7/bfd/configure
+@@ -3576,7 +3576,7 @@
+ ;;
+
+ # This must be Linux ELF.
+-linux-gnu*)
++linux-gnu*|linux-uclibc*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+--- binutils-2.16.91.0.7/binutils/configure
++++ binutils-2.16.91.0.7/binutils/configure
+@@ -3411,7 +3411,7 @@
+ ;;
+
+ # This must be Linux ELF.
+-linux-gnu*)
++linux-gnu*|linux-uclibc*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+--- binutils-2.16.91.0.7/configure
++++ binutils-2.16.91.0.7/configure
+@@ -1270,7 +1270,7 @@
+ am33_2.0-*-linux*)
+ noconfigdirs="$noconfigdirs ${libgcj} target-newlib target-libgloss"
+ ;;
+- sh-*-linux*)
++ sh*-*-linux*)
+ noconfigdirs="$noconfigdirs ${libgcj} target-newlib target-libgloss"
+ ;;
+ sh*-*-pe|mips*-*-pe|*arm-wince-pe)
+@@ -1578,7 +1578,7 @@
+ romp-*-*)
+ noconfigdirs="$noconfigdirs bfd binutils ld gas opcodes target-libgloss ${libgcj}"
+ ;;
+- sh-*-* | sh64-*-*)
++ sh*-*-* | sh64-*-*)
+ case "${host}" in
+ i[3456789]86-*-vsta) ;; # don't add gprof back in
+ i[3456789]86-*-go32*) ;; # don't add gprof back in
+--- binutils-2.16.91.0.7/configure.in
++++ binutils-2.16.91.0.7/configure.in
+@@ -468,7 +468,7 @@
+ am33_2.0-*-linux*)
+ noconfigdirs="$noconfigdirs ${libgcj} target-newlib target-libgloss"
+ ;;
+- sh-*-linux*)
++ sh*-*-linux*)
+ noconfigdirs="$noconfigdirs ${libgcj} target-newlib target-libgloss"
+ ;;
+ sh*-*-pe|mips*-*-pe|*arm-wince-pe)
+@@ -776,7 +776,7 @@
+ romp-*-*)
+ noconfigdirs="$noconfigdirs bfd binutils ld gas opcodes target-libgloss ${libgcj}"
+ ;;
+- sh-*-* | sh64-*-*)
++ sh*-*-* | sh64-*-*)
+ case "${host}" in
+ i[[3456789]]86-*-vsta) ;; # don't add gprof back in
+ i[[3456789]]86-*-go32*) ;; # don't add gprof back in
+--- binutils-2.16.91.0.7/gas/configure
++++ binutils-2.16.91.0.7/gas/configure
+@@ -3411,7 +3411,7 @@
+ ;;
+
+ # This must be Linux ELF.
+-linux-gnu*)
++linux-gnu*|linux-uclibc*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+--- binutils-2.16.91.0.7/gprof/configure
++++ binutils-2.16.91.0.7/gprof/configure
+@@ -3419,6 +3419,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd* | knetbsd*-gnu)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+--- binutils-2.16.91.0.7/ld/configure
++++ binutils-2.16.91.0.7/ld/configure
+@@ -3413,7 +3413,7 @@
+ ;;
+
+ # This must be Linux ELF.
+-linux-gnu*)
++linux-gnu*|linux-uclibc*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+--- binutils-2.16.91.0.7/libtool.m4
++++ binutils-2.16.91.0.7/libtool.m4
+@@ -739,7 +739,7 @@
+ ;;
+
+ # This must be Linux ELF.
+-linux-gnu*)
++linux-gnu*|linux-uclibc*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+--- binutils-2.16.91.0.7/ltconfig
++++ binutils-2.16.91.0.7/ltconfig
+@@ -602,6 +602,7 @@
+
+ # Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+ case $host_os in
++linux-uclibc*) ;;
+ linux-gnu*) ;;
+ linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+ esac
+@@ -1247,7 +1248,7 @@
+ ;;
+
+ # This must be Linux ELF.
+-linux-gnu*)
++linux-gnu*|linux-uclibc*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+--- binutils-2.16.91.0.7/opcodes/configure
++++ binutils-2.16.91.0.7/opcodes/configure
+@@ -3579,7 +3579,7 @@
+ ;;
+
+ # This must be Linux ELF.
+-linux-gnu*)
++linux-gnu*|linux-uclibc*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
diff --git a/toolchain/binutils/patches/2.17/110-arm-eabi-conf.patch b/toolchain/binutils/patches/2.17/110-arm-eabi-conf.patch
new file mode 100644
index 0000000000..be85ceb109
--- /dev/null
+++ b/toolchain/binutils/patches/2.17/110-arm-eabi-conf.patch
@@ -0,0 +1,24 @@
+diff -urN binutils-2.16.91.0.7.orig/configure binutils-2.16.91.0.7/configure
+--- binutils-2.16.91.0.7.orig/configure 2006-05-31 14:54:24.000000000 +0300
++++ binutils-2.16.91.0.7/configure 2006-05-31 14:55:53.000000000 +0300
+@@ -1299,7 +1299,7 @@
+ arm-*-elf* | strongarm-*-elf* | xscale-*-elf* | arm*-*-eabi* )
+ noconfigdirs="$noconfigdirs target-libffi target-qthreads"
+ ;;
+- arm*-*-linux-gnueabi)
++ arm*-*-linux-gnueabi | arm*-*-linux-uclibcgnueabi)
+ noconfigdirs="$noconfigdirs target-libffi target-qthreads"
+ noconfigdirs="$noconfigdirs target-libjava target-libobjc"
+ ;;
+diff -urN binutils-2.16.91.0.7.orig/configure.in binutils-2.16.91.0.7/configure.in
+--- binutils-2.16.91.0.7.orig/configure.in 2006-05-31 14:54:24.000000000 +0300
++++ binutils-2.16.91.0.7/configure.in 2006-05-31 14:55:53.000000000 +0300
+@@ -497,7 +497,7 @@
+ arm-*-elf* | strongarm-*-elf* | xscale-*-elf* | arm*-*-eabi* )
+ noconfigdirs="$noconfigdirs target-libffi target-qthreads"
+ ;;
+- arm*-*-linux-gnueabi)
++ arm*-*-linux-gnueabi | arm*-*-linux-uclibcgnueabi)
+ noconfigdirs="$noconfigdirs target-libffi target-qthreads"
+ noconfigdirs="$noconfigdirs target-libjava target-libobjc"
+ ;;
diff --git a/toolchain/binutils/patches/2.17/300-001_ld_makefile_patch.patch b/toolchain/binutils/patches/2.17/300-001_ld_makefile_patch.patch
new file mode 100644
index 0000000000..04a7e61e25
--- /dev/null
+++ b/toolchain/binutils/patches/2.17/300-001_ld_makefile_patch.patch
@@ -0,0 +1,50 @@
+#!/bin/sh -e
+## 001_ld_makefile_patch.dpatch
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: correct where ld scripts are installed
+## DP: Author: Chris Chimelis <chris@debian.org>
+## DP: Upstream status: N/A
+## DP: Date: ??
+
+if [ $# -ne 1 ]; then
+ echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+ exit 1
+fi
+
+[ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts
+patch_opts="${patch_opts:--f --no-backup-if-mismatch}"
+
+case "$1" in
+ -patch) patch $patch_opts -p1 < $0;;
+ -unpatch) patch $patch_opts -p1 -R < $0;;
+ *)
+ echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+ exit 1;;
+esac
+
+exit 0
+
+@DPATCH@
+--- binutils-2.16.91.0.1/ld/Makefile.am
++++ binutils-2.16.91.0.1/ld/Makefile.am
+@@ -20,7 +20,7 @@
+ # We put the scripts in the directory $(scriptdir)/ldscripts.
+ # We can't put the scripts in $(datadir) because the SEARCH_DIR
+ # directives need to be different for native and cross linkers.
+-scriptdir = $(tooldir)/lib
++scriptdir = $(libdir)
+
+ EMUL = @EMUL@
+ EMULATION_OFILES = @EMULATION_OFILES@
+--- binutils-2.16.91.0.1/ld/Makefile.in
++++ binutils-2.16.91.0.1/ld/Makefile.in
+@@ -268,7 +268,7 @@
+ # We put the scripts in the directory $(scriptdir)/ldscripts.
+ # We can't put the scripts in $(datadir) because the SEARCH_DIR
+ # directives need to be different for native and cross linkers.
+-scriptdir = $(tooldir)/lib
++scriptdir = $(libdir)
+ BASEDIR = $(srcdir)/..
+ BFDDIR = $(BASEDIR)/bfd
+ INCDIR = $(BASEDIR)/include
diff --git a/toolchain/binutils/patches/2.17/300-006_better_file_error.patch b/toolchain/binutils/patches/2.17/300-006_better_file_error.patch
new file mode 100644
index 0000000000..f337611edf
--- /dev/null
+++ b/toolchain/binutils/patches/2.17/300-006_better_file_error.patch
@@ -0,0 +1,43 @@
+#!/bin/sh -e
+## 006_better_file_error.dpatch by David Kimdon <dwhedon@gordian.com>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Specify which filename is causing an error if the filename is a
+## DP: directory. (#45832)
+
+if [ $# -ne 1 ]; then
+ echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+ exit 1
+fi
+
+[ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts
+patch_opts="${patch_opts:--f --no-backup-if-mismatch}"
+
+case "$1" in
+ -patch) patch $patch_opts -p1 < $0;;
+ -unpatch) patch $patch_opts -p1 -R < $0;;
+ *)
+ echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+ exit 1;;
+esac
+
+exit 0
+
+@DPATCH@
+diff -urNad /home/james/debian/packages/binutils/binutils-2.14.90.0.6/bfd/opncls.c binutils-2.14.90.0.6/bfd/opncls.c
+--- /home/james/debian/packages/binutils/binutils-2.14.90.0.6/bfd/opncls.c 2003-07-23 16:08:09.000000000 +0100
++++ binutils-2.14.90.0.6/bfd/opncls.c 2003-09-10 22:35:00.000000000 +0100
+@@ -150,6 +150,13 @@
+ {
+ bfd *nbfd;
+ const bfd_target *target_vec;
++ struct stat s;
++
++ if (stat (filename, &s) == 0)
++ if (S_ISDIR(s.st_mode)) {
++ bfd_set_error (bfd_error_file_not_recognized);
++ return NULL;
++ }
+
+ nbfd = _bfd_new_bfd ();
+ if (nbfd == NULL)
diff --git a/toolchain/binutils/patches/2.17/300-012_check_ldrunpath_length.patch b/toolchain/binutils/patches/2.17/300-012_check_ldrunpath_length.patch
new file mode 100644
index 0000000000..498651a90c
--- /dev/null
+++ b/toolchain/binutils/patches/2.17/300-012_check_ldrunpath_length.patch
@@ -0,0 +1,47 @@
+#!/bin/sh -e
+## 012_check_ldrunpath_length.dpatch by Chris Chimelis <chris@debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Only generate an RPATH entry if LD_RUN_PATH is not empty, for
+## DP: cases where -rpath isn't specified. (#151024)
+
+if [ $# -ne 1 ]; then
+ echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+ exit 1
+fi
+
+[ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts
+patch_opts="${patch_opts:--f --no-backup-if-mismatch}"
+
+case "$1" in
+ -patch) patch $patch_opts -p1 < $0;;
+ -unpatch) patch $patch_opts -p1 -R < $0;;
+ *)
+ echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+ exit 1;;
+esac
+
+exit 0
+
+@DPATCH@
+diff -urNad /home/james/debian/packages/binutils/new/binutils-2.15/ld/emultempl/elf32.em binutils-2.15/ld/emultempl/elf32.em
+--- /home/james/debian/packages/binutils/new/binutils-2.15/ld/emultempl/elf32.em 2004-05-21 23:12:58.000000000 +0100
++++ binutils-2.15/ld/emultempl/elf32.em 2004-05-21 23:12:59.000000000 +0100
+@@ -692,6 +692,8 @@
+ && command_line.rpath == NULL)
+ {
+ lib_path = (const char *) getenv ("LD_RUN_PATH");
++ if ((lib_path) && (strlen (lib_path) == 0))
++ lib_path = NULL;
+ if (gld${EMULATION_NAME}_search_needed (lib_path, &n,
+ force))
+ break;
+@@ -871,6 +873,8 @@
+ rpath = command_line.rpath;
+ if (rpath == NULL)
+ rpath = (const char *) getenv ("LD_RUN_PATH");
++ if ((rpath) && (strlen (rpath) == 0))
++ rpath = NULL;
+ if (! (bfd_elf_size_dynamic_sections
+ (output_bfd, command_line.soname, rpath,
+ command_line.filter_shlib,
diff --git a/toolchain/binutils/patches/2.17/702-binutils-skip-comments.patch b/toolchain/binutils/patches/2.17/702-binutils-skip-comments.patch
new file mode 100644
index 0000000000..9ef7a7c9ec
--- /dev/null
+++ b/toolchain/binutils/patches/2.17/702-binutils-skip-comments.patch
@@ -0,0 +1,93 @@
+Retrieved from http://sources.redhat.com/ml/binutils/2004-04/msg00646.html
+Fixes
+localealias.s:544: Error: junk at end of line, first unrecognized character is `,'
+when building glibc-2.3.2 with gcc-3.4.0 and binutils-2.15.90.0.3
+
+Paths adjusted to match crosstool's patcher.
+
+Message-Id: m3n052qw2g.fsf@whitebox.m5r.de
+From: Andreas Schwab <schwab at suse dot de>
+To: Nathan Sidwell <nathan at codesourcery dot com>
+Cc: Ian Lance Taylor <ian at wasabisystems dot com>, binutils at sources dot redhat dot com
+Date: Fri, 23 Apr 2004 22:27:19 +0200
+Subject: Re: demand_empty_rest_of_line and ignore_rest_of_line
+
+Nathan Sidwell <nathan@codesourcery.com> writes:
+
+> Index: read.c
+> ===================================================================
+> RCS file: /cvs/src/src/gas/read.c,v
+> retrieving revision 1.76
+> diff -c -3 -p -r1.76 read.c
+> *** read.c 12 Mar 2004 17:48:12 -0000 1.76
+> --- read.c 18 Mar 2004 09:56:05 -0000
+> *************** read_a_source_file (char *name)
+> *** 1053,1059 ****
+> #endif
+> input_line_pointer--;
+> /* Report unknown char as ignored. */
+> ! ignore_rest_of_line ();
+> }
+>
+> #ifdef md_after_pass_hook
+> --- 1053,1059 ----
+> #endif
+> input_line_pointer--;
+> /* Report unknown char as ignored. */
+> ! demand_empty_rest_of_line ();
+> }
+>
+> #ifdef md_after_pass_hook
+
+This means that the unknown character is no longer ignored, despite the
+comment. As a side effect a line starting with a line comment character
+not followed by APP in NO_APP mode now triggers an error instead of just a
+warning, breaking builds of glibc on m68k-linux. Earlier in
+read_a_source_file where #APP is handled there is another comment that
+claims that unknown comments are ignored, when in fact they aren't (only
+the initial line comment character is skipped).
+
+Note that the presence of #APP will mess up the line counters, but
+that appears to be difficult to fix.
+
+Andreas.
+
+2004-04-23 Andreas Schwab <schwab@suse.de>
+
+ * read.c (read_a_source_file): Ignore unknown text after line
+ comment character. Fix misleading comment.
+
+--- binutils/gas/read.c.~1.78.~ 2004-04-23 08:58:23.000000000 +0200
++++ binutils/gas/read.c 2004-04-23 21:49:01.000000000 +0200
+@@ -950,10 +950,14 @@ read_a_source_file (char *name)
+ unsigned int new_length;
+ char *tmp_buf = 0;
+
+- bump_line_counters ();
+ s = input_line_pointer;
+ if (strncmp (s, "APP\n", 4))
+- continue; /* We ignore it */
++ {
++ /* We ignore it */
++ ignore_rest_of_line ();
++ continue;
++ }
++ bump_line_counters ();
+ s += 4;
+
+ sb_new (&sbuf);
+@@ -1052,7 +1056,7 @@ read_a_source_file (char *name)
+ continue;
+ #endif
+ input_line_pointer--;
+- /* Report unknown char as ignored. */
++ /* Report unknown char as error. */
+ demand_empty_rest_of_line ();
+ }
+
+
+--
+Andreas Schwab, SuSE Labs, schwab@suse.de
+SuSE Linux AG, Maxfeldstra&#xC3;e 5, 90409 N&#xC3;rnberg, Germany
+Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
+"And now for something completely different."
diff --git a/toolchain/binutils/patches/400-mips-ELF_MAXPAGESIZE-4k.patch b/toolchain/binutils/patches/400-mips-ELF_MAXPAGESIZE-4k.patch
new file mode 100644
index 0000000000..a8ae110e86
--- /dev/null
+++ b/toolchain/binutils/patches/400-mips-ELF_MAXPAGESIZE-4k.patch
@@ -0,0 +1,12 @@
+diff -urN binutils-2.14.90.0.8.test/bfd/elf32-mips.c binutils-2.14.90.0.8/bfd/elf32-mips.c
+--- binutils-2.14.90.0.8.test/bfd/elf32-mips.c 2004-01-14 22:07:43.000000000 +0100
++++ binutils-2.14.90.0.8/bfd/elf32-mips.c 2005-03-03 23:44:00.000000000 +0100
+@@ -1611,7 +1611,7 @@
+
+ /* The SVR4 MIPS ABI says that this should be 0x10000, and Linux uses
+ page sizes of up to that limit, so we need to respect it. */
+-#define ELF_MAXPAGESIZE 0x10000
++#define ELF_MAXPAGESIZE 0x1000
+ #define elf32_bed elf32_tradbed
+
+ /* Include the target file again for this target. */
diff --git a/toolchain/gcc/Config.in b/toolchain/gcc/Config.in
new file mode 100644
index 0000000000..f5f27c6907
--- /dev/null
+++ b/toolchain/gcc/Config.in
@@ -0,0 +1,51 @@
+# Choose gcc version.
+
+choice
+ prompt "GCC compiler Version" if TOOLCHAINOPTS
+ default GCC_VERSION_4_1_1 if LINUX_2_6_ARUBA
+ default GCC_VERSION_3_4_6
+ help
+ Select the version of gcc you wish to use.
+
+
+ config GCC_VERSION_3_4_4
+ bool "gcc 3.4.4"
+
+ config GCC_VERSION_3_4_5
+ bool "gcc 3.4.5"
+
+ config GCC_VERSION_3_4_6
+ bool "gcc 3.4.6"
+
+ config GCC_VERSION_3_4_6_nonmips
+ bool "gcc 3.4.6-nonmips"
+
+ config GCC_VERSION_4_0_2
+ bool "gcc 4.0.2"
+
+ config GCC_VERSION_4_0_3
+ bool "gcc 4.0.3"
+
+ config GCC_VERSION_4_1_0
+ bool "gcc 4.1.0"
+
+ config GCC_VERSION_4_1_1
+ bool "gcc 4.1.1"
+
+endchoice
+
+config EXTRA_GCC_CONFIG_OPTIONS
+ string
+ prompt "Additional gcc options" if TOOLCHAINOPTS
+ default ""
+ help
+ Any additional gcc options you may want to include....
+
+config INSTALL_LIBSTDCPP
+ bool
+ prompt "Build/install c++ compiler and libstdc++?" if TOOLCHAINOPTS
+ default y
+ help
+ Build/install c++ compiler and libstdc++?
+
+
diff --git a/toolchain/gcc/Config.version b/toolchain/gcc/Config.version
new file mode 100644
index 0000000000..e728bc4087
--- /dev/null
+++ b/toolchain/gcc/Config.version
@@ -0,0 +1,20 @@
+config GCC_VERSION
+ string
+ default "3.4.4" if GCC_VERSION_3_4_4
+ default "3.4.5" if GCC_VERSION_3_4_5
+ default "3.4.6" if GCC_VERSION_3_4_6
+ default "4.0.2" if GCC_VERSION_4_0_2
+ default "4.0.3" if GCC_VERSION_4_0_3
+ default "4.1.0" if GCC_VERSION_4_1_0
+ default "4.1.1" if GCC_VERSION_4_1_1
+ default "3.4.6-nonmips" if GCC_VERSION_3_4_6_nonmips
+ default "3.4.6"
+
+if !TOOLCHAINOPTS
+ config GCC_VERSION_4_1_1
+ default y if LINUX_2_6_ARUBA || LINUX_2_6_X86
+ config GCC_VERSION_4_0_3
+ default y if LINUX_2_6_XSCALE
+endif
+
+
diff --git a/toolchain/gcc/Makefile b/toolchain/gcc/Makefile
new file mode 100644
index 0000000000..7ef6005d06
--- /dev/null
+++ b/toolchain/gcc/Makefile
@@ -0,0 +1,143 @@
+# Makefile for to build a gcc/uClibc toolchain
+#
+# Copyright (C) 2002-2003 Erik Andersen <andersen@uclibc.org>
+# Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org>
+# Copyright (C) 2005-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.
+#
+# 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)/rules.mk
+
+PKG_NAME:=gcc
+PKG_VERSION:=$(strip $(subst ",, $(CONFIG_GCC_VERSION)))#"))
+
+PKG_SOURCE:=gcc-$(PKG_VERSION).tar.bz2
+PKG_MD5SUM:=unknown
+PKG_SOURCE_URL:=ftp://ftp.fu-berlin.de/unix/languages/gcc/releases/gcc-$(PKG_VERSION) \
+ http://mirrors.rcn.net/pub/sourceware/gcc/releases/gcc-$(PKG_VERSION) \
+ ftp://ftp.gnu.org/gnu/gcc/releases/gcc-$(PKG_VERSION)
+PKG_CAT:=bzcat
+
+PKG_BUILD_DIR:=$(TOOLCHAIN_BUILD_DIR)/gcc-$(PKG_VERSION)
+
+TARGET_LANGUAGES:=c
+ifeq ($(CONFIG_INSTALL_LIBSTDCPP),y)
+TARGET_LANGUAGES:=$(TARGET_LANGUAGES),c++
+endif
+ifeq ($(CONFIG_INSTALL_LIBGCJ),y)
+TARGET_LANGUAGES:=$(TARGET_LANGUAGES),java
+endif
+
+include $(INCLUDE_DIR)/host-build.mk
+
+BUILD_DIR1:=$(TOOLCHAIN_BUILD_DIR)/gcc-$(PKG_VERSION)-initial
+BUILD_DIR2:=$(TOOLCHAIN_BUILD_DIR)/gcc-$(PKG_VERSION)-final
+
+override SHELL:=$(BASH)
+
+define Stage1/Configure
+ mkdir -p $(BUILD_DIR1)
+ (cd $(BUILD_DIR1); rm -f config.cache; \
+ $(PKG_BUILD_DIR)/configure \
+ --prefix=$(STAGING_DIR) \
+ --build=$(GNU_HOST_NAME) \
+ --host=$(GNU_HOST_NAME) \
+ --target=$(REAL_GNU_TARGET_NAME) \
+ --enable-languages=c \
+ --disable-shared \
+ --with-sysroot=$(TOOLCHAIN_BUILD_DIR)/uClibc_dev/ \
+ --disable-__cxa_atexit \
+ --enable-target-optspace \
+ --with-gnu-ld \
+ --disable-nls \
+ );
+endef
+define Stage1/Compile
+ $(MAKE) -C $(BUILD_DIR1) all-gcc
+endef
+define Stage1/Install
+ $(MAKE) -C $(BUILD_DIR1) install-gcc
+endef
+
+define Stage2/Configure
+ mkdir -p $(BUILD_DIR2)
+ # Important! Required for limits.h to be fixed.
+ rm -rf $(STAGING_DIR)/$(REAL_GNU_TARGET_NAME)/sys-include
+ ln -sf ../include $(STAGING_DIR)/$(REAL_GNU_TARGET_NAME)/sys-include
+ rm -rf $(STAGING_DIR)/$(REAL_GNU_TARGET_NAME)/lib
+ ln -sf ../lib $(STAGING_DIR)/$(REAL_GNU_TARGET_NAME)/lib
+ (cd $(BUILD_DIR2); rm -f config.cache; \
+ $(PKG_BUILD_DIR)/configure \
+ --prefix=$(STAGING_DIR) \
+ --build=$(GNU_HOST_NAME) \
+ --host=$(GNU_HOST_NAME) \
+ --target=$(REAL_GNU_TARGET_NAME) \
+ --enable-languages=$(TARGET_LANGUAGES) \
+ --enable-shared \
+ --disable-__cxa_atexit \
+ --enable-target-optspace \
+ --with-gnu-ld \
+ --disable-nls \
+ );
+endef
+define Stage2/Compile
+ $(MAKE) -C $(BUILD_DIR2) all
+endef
+define Stage2/Install
+ $(MAKE) -C $(BUILD_DIR2) install
+ echo $(PKG_VERSION) > $(STAGING_DIR)/gcc_version
+ # Set up the symlinks to enable lying about target name.
+ set -e; \
+ (cd $(STAGING_DIR); \
+ ln -sf $(REAL_GNU_TARGET_NAME) $(GNU_TARGET_NAME); \
+ cd bin; \
+ for app in $(REAL_GNU_TARGET_NAME)-* ; do \
+ ln -sf $$$${app} \
+ $(GNU_TARGET_NAME)$$$${app##$(REAL_GNU_TARGET_NAME)}; \
+ done; \
+ );
+endef
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ $(SCRIPT_DIR)/patch-kernel.sh $(PKG_BUILD_DIR) ./patches/$(PKG_VERSION) \*.patch
+ $(SED) 's,\(version_string.. = "[0-9\.]*\).*\(";\),\1 (OpenWrt-2.0)\2,' $(PKG_BUILD_DIR)/gcc/version.c
+ $(SED) 's,\(bug_report_url.. = "\).*\(";\),\1<URL:https://dev.openwrt.org/>\2,' $(PKG_BUILD_DIR)/gcc/version.c
+endef
+
+define Build/Configure
+ $(call Stage1/Configure)
+endef
+
+define Build/Compile
+ $(call Stage1/Compile)
+ $(call Stage1/Install)
+endef
+
+define Build/Install
+ $(call Stage2/Configure)
+ $(call Stage2/Compile)
+ $(call Stage2/Install)
+endef
+
+define Build/Clean
+ rm -rf $(PKG_BUILD_DIR)
+ rm -rf $(BUILD_DIR1)
+ rm -rf $(BUILD_DIR2)
+ rm -f $(STAGING_DIR)/bin/$(REAL_GNU_TARGET_NAME)-gc*
+ rm -f $(STAGING_DIR)/bin/$(REAL_GNU_TARGET_NAME)-c*
+endef
+
+$(eval $(call HostBuild))
diff --git a/toolchain/gcc/patches/3.4.4/100-uclibc-conf.patch b/toolchain/gcc/patches/3.4.4/100-uclibc-conf.patch
new file mode 100644
index 0000000000..29e4c802e2
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.4/100-uclibc-conf.patch
@@ -0,0 +1,442 @@
+diff -urN gcc-3.4.1-dist/boehm-gc/configure gcc-3.4.1/boehm-gc/configure
+--- gcc-3.4.1-dist/boehm-gc/configure 2004-07-01 14:14:03.000000000 -0500
++++ gcc-3.4.1/boehm-gc/configure 2004-08-12 16:22:57.000000000 -0500
+@@ -1947,6 +1947,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+diff -urN gcc-3.4.1-dist/boehm-gc/ltconfig gcc-3.4.1/boehm-gc/ltconfig
+--- gcc-3.4.1-dist/boehm-gc/ltconfig 2002-11-20 09:59:06.000000000 -0600
++++ gcc-3.4.1/boehm-gc/ltconfig 2004-08-12 15:54:42.000000000 -0500
+@@ -1981,6 +1981,23 @@
+ fi
+ ;;
+
++linux-uclibc*)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
++ soname_spec='${libname}${release}.so$major'
++ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
++ file_magic_cmd=/usr/bin/file
++ file_magic_test_file=`echo /lib/libuClibc-*.so`
++
++ # Assume using the uClibc dynamic linker.
++ dynamic_linker="uClibc ld.so"
++ ;;
++
+ netbsd*)
+ version_type=sunos
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+diff -urN gcc-3.4.1-dist/gcc/config/arm/linux-elf.h gcc-3.4.1/gcc/config/arm/linux-elf.h
+--- gcc-3.4.1-dist/gcc/config/arm/linux-elf.h 2004-01-31 00:18:11.000000000 -0600
++++ gcc-3.4.1/gcc/config/arm/linux-elf.h 2004-08-12 15:54:42.000000000 -0500
+@@ -81,6 +81,18 @@
+ "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
+
+ #undef LINK_SPEC
++#ifdef USE_UCLIBC
++#define LINK_SPEC "%{h*} %{version:-v} \
++ %{b} %{Wl,*:%*} \
++ %{static:-Bstatic} \
++ %{shared:-shared} \
++ %{symbolic:-Bsymbolic} \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0} \
++ -X \
++ %{mbig-endian:-EB}" \
++ SUBTARGET_EXTRA_LINK_SPEC
++#else
+ #define LINK_SPEC "%{h*} %{version:-v} \
+ %{b} %{Wl,*:%*} \
+ %{static:-Bstatic} \
+@@ -91,6 +103,7 @@
+ -X \
+ %{mbig-endian:-EB}" \
+ SUBTARGET_EXTRA_LINK_SPEC
++#endif
+
+ #define TARGET_OS_CPP_BUILTINS() LINUX_TARGET_OS_CPP_BUILTINS()
+
+diff -urN gcc-3.4.1-dist/gcc/config/cris/linux.h gcc-3.4.1/gcc/config/cris/linux.h
+--- gcc-3.4.1-dist/gcc/config/cris/linux.h 2003-11-28 21:08:09.000000000 -0600
++++ gcc-3.4.1/gcc/config/cris/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -79,6 +79,25 @@
+ #undef CRIS_DEFAULT_CPU_VERSION
+ #define CRIS_DEFAULT_CPU_VERSION CRIS_CPU_NG
+
++#ifdef USE_UCLIBC
++
++#undef CRIS_SUBTARGET_VERSION
++#define CRIS_SUBTARGET_VERSION " - cris-axis-linux-uclibc"
++
++#undef CRIS_LINK_SUBTARGET_SPEC
++#define CRIS_LINK_SUBTARGET_SPEC \
++ "-mcrislinux\
++ -rpath-link include/asm/../..%s\
++ %{shared} %{static}\
++ %{symbolic:-Bdynamic} %{shlib:-Bdynamic} %{static:-Bstatic}\
++ %{!shared: \
++ %{!static: \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}}} \
++ %{!r:%{O2|O3: --gc-sections}}"
++
++#else /* USE_UCLIBC */
++
+ #undef CRIS_SUBTARGET_VERSION
+ #define CRIS_SUBTARGET_VERSION " - cris-axis-linux-gnu"
+
+@@ -93,6 +112,8 @@
+ %{!shared:%{!static:%{rdynamic:-export-dynamic}}}\
+ %{!r:%{O2|O3: --gc-sections}}"
+
++#endif /* USE_UCLIBC */
++
+
+ /* Node: Run-time Target */
+
+diff -urN gcc-3.4.1-dist/gcc/config/cris/t-linux-uclibc gcc-3.4.1/gcc/config/cris/t-linux-uclibc
+--- gcc-3.4.1-dist/gcc/config/cris/t-linux-uclibc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.1/gcc/config/cris/t-linux-uclibc 2004-08-12 15:54:43.000000000 -0500
+@@ -0,0 +1,3 @@
++T_CFLAGS = -DUSE_UCLIBC
++TARGET_LIBGCC2_CFLAGS += -fPIC
++CRTSTUFF_T_CFLAGS_S = $(TARGET_LIBGCC2_CFLAGS)
+diff -urN gcc-3.4.1-dist/gcc/config/i386/linux.h gcc-3.4.1/gcc/config/i386/linux.h
+--- gcc-3.4.1-dist/gcc/config/i386/linux.h 2003-11-28 21:08:10.000000000 -0600
++++ gcc-3.4.1/gcc/config/i386/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -118,6 +118,15 @@
+ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \
+ %{static:-static}}}"
+ #else
++#if defined USE_UCLIBC
++#define LINK_SPEC "-m elf_i386 %{shared:-shared} \
++ %{!shared: \
++ %{!ibcs: \
++ %{!static: \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}} \
++ %{static:-static}}}"
++#else
+ #define LINK_SPEC "-m elf_i386 %{shared:-shared} \
+ %{!shared: \
+ %{!ibcs: \
+@@ -126,6 +135,7 @@
+ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
+ %{static:-static}}}"
+ #endif
++#endif
+
+ /* A C statement (sans semicolon) to output to the stdio stream
+ FILE the assembler definition of uninitialized global DECL named
+diff -urN gcc-3.4.1-dist/gcc/config/mips/linux.h gcc-3.4.1/gcc/config/mips/linux.h
+--- gcc-3.4.1-dist/gcc/config/mips/linux.h 2004-06-15 20:42:24.000000000 -0500
++++ gcc-3.4.1/gcc/config/mips/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -109,6 +109,17 @@
+
+ /* Borrowed from sparc/linux.h */
+ #undef LINK_SPEC
++#ifdef USE_UCLIBC
++#define LINK_SPEC \
++ "%(endian_spec) \
++ %{shared:-shared} \
++ %{!shared: \
++ %{!ibcs: \
++ %{!static: \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}} \
++ %{static:-static}}}"
++#else
+ #define LINK_SPEC \
+ "%(endian_spec) \
+ %{shared:-shared} \
+@@ -118,6 +129,7 @@
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}} \
+ %{static:-static}}}"
++#endif
+
+ #undef SUBTARGET_ASM_SPEC
+ #define SUBTARGET_ASM_SPEC "\
+diff -urN gcc-3.4.1-dist/gcc/config/rs6000/linux.h gcc-3.4.1/gcc/config/rs6000/linux.h
+--- gcc-3.4.1-dist/gcc/config/rs6000/linux.h 2004-02-25 09:11:19.000000000 -0600
++++ gcc-3.4.1/gcc/config/rs6000/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -61,7 +61,11 @@
+ #define LINK_START_DEFAULT_SPEC "%(link_start_linux)"
+
+ #undef LINK_OS_DEFAULT_SPEC
++#ifdef USE_UCLIBC
++#define LINK_OS_DEFAULT_SPEC "%(link_os_linux_uclibc)"
++#else
+ #define LINK_OS_DEFAULT_SPEC "%(link_os_linux)"
++#endif
+
+ #define LINK_GCC_C_SEQUENCE_SPEC \
+ "%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}"
+diff -urN gcc-3.4.1-dist/gcc/config/rs6000/sysv4.h gcc-3.4.1/gcc/config/rs6000/sysv4.h
+--- gcc-3.4.1-dist/gcc/config/rs6000/sysv4.h 2004-06-10 01:39:50.000000000 -0500
++++ gcc-3.4.1/gcc/config/rs6000/sysv4.h 2004-08-12 15:54:43.000000000 -0500
+@@ -947,6 +947,7 @@
+ mcall-linux : %(link_os_linux) ; \
+ mcall-gnu : %(link_os_gnu) ; \
+ mcall-netbsd : %(link_os_netbsd) ; \
++ mcall-linux-uclibc : %(link_os_linux_uclibc); \
+ mcall-openbsd: %(link_os_openbsd) ; \
+ : %(link_os_default) }"
+
+@@ -1124,6 +1125,10 @@
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}}}"
+
++#define LINK_OS_LINUX_UCLIBC_SPEC "-m elf32ppclinux %{!shared: %{!static: \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}}}"
++
+ #if defined(HAVE_LD_EH_FRAME_HDR)
+ # define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
+ #endif
+@@ -1290,6 +1295,7 @@
+ { "link_os_sim", LINK_OS_SIM_SPEC }, \
+ { "link_os_freebsd", LINK_OS_FREEBSD_SPEC }, \
+ { "link_os_linux", LINK_OS_LINUX_SPEC }, \
++ { "link_os_linux_uclibc", LINK_OS_LINUX_UCLIBC_SPEC }, \
+ { "link_os_gnu", LINK_OS_GNU_SPEC }, \
+ { "link_os_netbsd", LINK_OS_NETBSD_SPEC }, \
+ { "link_os_openbsd", LINK_OS_OPENBSD_SPEC }, \
+diff -urN gcc-3.4.1-dist/gcc/config/sh/linux.h gcc-3.4.1/gcc/config/sh/linux.h
+--- gcc-3.4.1-dist/gcc/config/sh/linux.h 2004-01-11 20:29:13.000000000 -0600
++++ gcc-3.4.1/gcc/config/sh/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -73,12 +73,21 @@
+ #undef SUBTARGET_LINK_EMUL_SUFFIX
+ #define SUBTARGET_LINK_EMUL_SUFFIX "_linux"
+ #undef SUBTARGET_LINK_SPEC
++#ifdef USE_UCLIBC
++#define SUBTARGET_LINK_SPEC \
++ "%{shared:-shared} \
++ %{!static: \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}} \
++ %{static:-static}"
++#else
+ #define SUBTARGET_LINK_SPEC \
+ "%{shared:-shared} \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
+ %{static:-static}"
++#endif
+
+ #undef LIB_SPEC
+ #define LIB_SPEC \
+diff -urN gcc-3.4.1-dist/gcc/config/sh/t-linux-uclibc gcc-3.4.1/gcc/config/sh/t-linux-uclibc
+--- gcc-3.4.1-dist/gcc/config/sh/t-linux-uclibc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.1/gcc/config/sh/t-linux-uclibc 2004-08-12 15:54:43.000000000 -0500
+@@ -0,0 +1,13 @@
++T_CFLAGS = -DUSE_UCLIBC
++
++TARGET_LIBGCC2_CFLAGS = -fpic -DNO_FPSCR_VALUES
++LIB1ASMFUNCS_CACHE = _ic_invalidate
++
++LIB2FUNCS_EXTRA=
++
++MULTILIB_OPTIONS= $(MULTILIB_ENDIAN) m3e/m4
++MULTILIB_DIRNAMES=
++MULTILIB_MATCHES =
++MULTILIB_EXCEPTIONS=
++
++EXTRA_MULTILIB_PARTS= crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
+diff -urN gcc-3.4.1-dist/gcc/config/sh/t-sh64-uclibc gcc-3.4.1/gcc/config/sh/t-sh64-uclibc
+--- gcc-3.4.1-dist/gcc/config/sh/t-sh64-uclibc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.1/gcc/config/sh/t-sh64-uclibc 2004-08-12 15:54:43.000000000 -0500
+@@ -0,0 +1,13 @@
++EXTRA_MULTILIB_PARTS= crt1.o crti.o crtn.o crtbegin.o crtend.o
++
++LIB1ASMFUNCS = \
++ _sdivsi3 _sdivsi3_i4 _udivsi3 _udivsi3_i4 _set_fpscr \
++ _shcompact_call_trampoline _shcompact_return_trampoline \
++ _shcompact_incoming_args _ic_invalidate _nested_trampoline \
++ _push_pop_shmedia_regs \
++ _udivdi3 _divdi3 _umoddi3 _moddi3
++
++MULTILIB_OPTIONS = $(MULTILIB_ENDIAN) m5-32media-nofpu/m5-compact/m5-compact-nofpu/m5-64media/m5-64media-nofpu
++MULTILIB_DIRNAMES= $(MULTILIB_ENDIAN) nofpu compact nofpu/compact media64 nofpu/media64
++MULTILIB_MATCHES=
++MULTILIB_EXCEPTIONS=
+diff -urN gcc-3.4.1-dist/gcc/config/t-linux-uclibc gcc-3.4.1/gcc/config/t-linux-uclibc
+--- gcc-3.4.1-dist/gcc/config/t-linux-uclibc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.1/gcc/config/t-linux-uclibc 2004-08-12 15:54:43.000000000 -0500
+@@ -0,0 +1,15 @@
++T_CFLAGS = -DUSE_UCLIBC
++
++# Compile crtbeginS.o and crtendS.o with pic.
++CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
++# Compile libgcc2.a with pic.
++TARGET_LIBGCC2_CFLAGS = -fPIC
++
++# Override t-slibgcc-elf-ver to export some libgcc symbols with
++# the symbol versions that glibc used.
++#SHLIB_MAPFILES += $(srcdir)/config/libgcc-glibc.ver
++
++# Use unwind-dw2-fde
++LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
++ $(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c $(srcdir)/unwind-c.c
++LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h
+diff -urN gcc-3.4.1-dist/gcc/config.gcc gcc-3.4.1/gcc/config.gcc
+--- gcc-3.4.1-dist/gcc/config.gcc 2004-04-21 10:12:35.000000000 -0500
++++ gcc-3.4.1/gcc/config.gcc 2004-08-12 15:59:46.000000000 -0500
+@@ -664,6 +664,12 @@
+ extra_parts=""
+ use_collect2=yes
+ ;;
++arm*-*-linux-uclibc*) # ARM GNU/Linux with ELF - uClibc
++ tm_file="dbxelf.h elfos.h linux.h arm/elf.h arm/linux-gas.h arm/linux-elf.h arm/aout.h arm/arm.h"
++ tmake_file="t-slibgcc-elf-ver t-linux-uclibc arm/t-linux"
++ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
++ gnu_ld=yes
++ ;;
+ arm*-*-linux*) # ARM GNU/Linux with ELF
+ tm_file="dbxelf.h elfos.h linux.h arm/elf.h arm/linux-gas.h arm/linux-elf.h arm/aout.h arm/arm.h"
+ tmake_file="t-slibgcc-elf-ver t-linux arm/t-linux"
+@@ -725,6 +731,10 @@
+ tmake_file="cris/t-cris cris/t-elfmulti"
+ gas=yes
+ ;;
++cris-*-linux-uclibc*)
++ tm_file="dbxelf.h elfos.h svr4.h ${tm_file} linux.h cris/linux.h"
++ tmake_file="cris/t-cris t-slibgcc-elf-ver cris/t-linux-uclibc"
++ ;;
+ cris-*-linux*)
+ tm_file="dbxelf.h elfos.h svr4.h ${tm_file} linux.h cris/linux.h"
+ tmake_file="cris/t-cris t-slibgcc-elf-ver cris/t-linux"
+@@ -988,6 +998,11 @@
+ thread_file='single'
+ fi
+ ;;
++i[34567]86-*-linux*uclibc*) # Intel 80386's running GNU/Linux
++ # with ELF format using uClibc
++ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h linux.h i386/linux.h"
++ tmake_file="t-slibgcc-elf-ver t-linux-uclibc i386/t-crtstuff"
++ ;;
+ i[34567]86-*-linux*) # Intel 80386's running GNU/Linux
+ # with ELF format using glibc 2
+ # aka GNU/Linux C library 6
+@@ -1547,6 +1562,16 @@
+ gnu_ld=yes
+ gas=yes
+ ;;
++mips*-*-linux-uclibc*) # Linux MIPS, either endian. uClibc
++ tm_file="dbxelf.h elfos.h svr4.h linux.h ${tm_file} mips/linux.h"
++ case ${target} in
++ mipsisa32*-*)
++ target_cpu_default="MASK_SOFT_FLOAT"
++ tm_defines="MIPS_ISA_DEFAULT=32"
++ ;;
++ esac
++ tmake_file="t-slibgcc-elf-ver t-linux-uclibc"
++ ;;
+ mips*-*-linux*) # Linux MIPS, either endian.
+ tm_file="dbxelf.h elfos.h svr4.h linux.h ${tm_file} mips/linux.h"
+ case ${target} in
+@@ -1764,6 +1789,10 @@
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/linux.h rs6000/linuxspe.h"
+ tmake_file="rs6000/t-fprules rs6000/t-ppcos t-slibgcc-elf-ver t-linux rs6000/t-ppccomm"
+ ;;
++powerpc-*-linux-uclibc*)
++ tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/linux.h"
++ tmake_file="rs6000/t-fprules rs6000/t-ppcos t-slibgcc-elf-ver t-linux-uclibc rs6000/t-ppccomm"
++ ;;
+ powerpc-*-linux*)
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/linux.h"
+ tmake_file="rs6000/t-fprules rs6000/t-ppcos t-slibgcc-elf-ver t-linux rs6000/t-ppccomm"
+@@ -1916,7 +1945,7 @@
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sh/elf.h sh/embed-elf.h sh/rtemself.h rtems.h"
+ ;;
+ sh-*-linux* | sh[2346lbe]*-*-linux*)
+- tmake_file="sh/t-sh sh/t-elf t-slibgcc-elf-ver t-linux"
++ tmake_file="sh/t-sh sh/t-elf t-slibgcc-elf-ver"
+ case ${target} in
+ sh*be-*-* | sh*eb-*-*) ;;
+ *)
+@@ -1924,9 +1953,17 @@
+ tmake_file="${tmake_file} sh/t-le"
+ ;;
+ esac
+- tmake_file="${tmake_file} sh/t-linux"
++ case ${target} in
++ *-*-linux-uclibc*) tmake_file="${tmake_file} t-linux-uclibc sh/t-linux-uclibc" ;;
++ *) tmake_file="${tmake_file} t-linux sh/t-linux" ;;
++ esac
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sh/elf.h sh/linux.h"
+ case ${target} in
++ sh64*-*-linux-uclibc*)
++ tmake_file="${tmake_file} sh/t-sh64-uclibc"
++ tm_file="${tm_file} sh/sh64.h"
++ extra_headers="shmedia.h ushmedia.h sshmedia.h"
++ ;;
+ sh64*)
+ tmake_file="${tmake_file} sh/t-sh64"
+ tm_file="${tm_file} sh/sh64.h"
+diff -urN gcc-3.4.1-dist/libtool.m4 gcc-3.4.1/libtool.m4
+--- gcc-3.4.1-dist/libtool.m4 2004-05-18 04:08:37.000000000 -0500
++++ gcc-3.4.1/libtool.m4 2004-08-12 15:54:43.000000000 -0500
+@@ -689,6 +689,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ [lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$']
+diff -urN gcc-3.4.1-dist/ltconfig gcc-3.4.1/ltconfig
+--- gcc-3.4.1-dist/ltconfig 2004-03-05 15:05:41.000000000 -0600
++++ gcc-3.4.1/ltconfig 2004-08-12 15:55:48.000000000 -0500
+@@ -602,6 +602,7 @@
+
+ # Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+ case $host_os in
++linux-uclibc*) ;;
+ linux-gnu*) ;;
+ linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+ esac
+@@ -1262,6 +1263,24 @@
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
++linux-uclibc*)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
++ soname_spec='${libname}${release}.so$major'
++ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ # This implies no fast_install, which is unacceptable.
++ # Some rework will be needed to allow for fast_install
++ # before this can be enabled.
++ # Note: copied from linux-gnu, and may not be appropriate.
++ hardcode_into_libs=yes
++ # Assume using the uClibc dynamic linker.
++ dynamic_linker="uClibc ld.so"
++ ;;
++
+ netbsd*)
+ need_lib_prefix=no
+ need_version=no
diff --git a/toolchain/gcc/patches/3.4.4/200-uclibc-locale.patch b/toolchain/gcc/patches/3.4.4/200-uclibc-locale.patch
new file mode 100644
index 0000000000..3fc4900b06
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.4/200-uclibc-locale.patch
@@ -0,0 +1,3246 @@
+diff -urN gcc-3.4.2-dist/libstdc++-v3/acinclude.m4 gcc-3.4.2/libstdc++-v3/acinclude.m4
+--- gcc-3.4.2-dist/libstdc++-v3/acinclude.m4 2004-07-15 12:42:45.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/acinclude.m4 2004-09-10 10:47:40.000000000 -0500
+@@ -996,7 +996,7 @@
+ AC_MSG_CHECKING([for C locale to use])
+ GLIBCXX_ENABLE(clocale,auto,[@<:@=MODEL@:>@],
+ [use MODEL for target locale package],
+- [permit generic|gnu|ieee_1003.1-2001|yes|no|auto])
++ [permit generic|gnu|ieee_1003.1-2001|uclibc|yes|no|auto])
+
+ # If they didn't use this option switch, or if they specified --enable
+ # with no specific model, we'll have to look for one. If they
+@@ -1012,6 +1012,9 @@
+ # Default to "generic".
+ if test $enable_clocale_flag = auto; then
+ case x${target_os} in
++ x*-uclibc*)
++ enable_clocale_flag=uclibc
++ ;;
+ xlinux* | xgnu* | xkfreebsd*-gnu | xknetbsd*-gnu)
+ AC_EGREP_CPP([_GLIBCXX_ok], [
+ #include <features.h>
+@@ -1138,6 +1141,41 @@
+ CTIME_CC=config/locale/generic/time_members.cc
+ CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+ ;;
++ uclibc)
++ AC_MSG_RESULT(uclibc)
++
++ # Declare intention to use gettext, and add support for specific
++ # languages.
++ # For some reason, ALL_LINGUAS has to be before AM-GNU-GETTEXT
++ ALL_LINGUAS="de fr"
++
++ # Don't call AM-GNU-GETTEXT here. Instead, assume glibc.
++ AC_CHECK_PROG(check_msgfmt, msgfmt, yes, no)
++ if test x"$check_msgfmt" = x"yes" && test x"$enable_nls" = x"yes"; then
++ USE_NLS=yes
++ fi
++ # Export the build objects.
++ for ling in $ALL_LINGUAS; do \
++ glibcxx_MOFILES="$glibcxx_MOFILES $ling.mo"; \
++ glibcxx_POFILES="$glibcxx_POFILES $ling.po"; \
++ done
++ AC_SUBST(glibcxx_MOFILES)
++ AC_SUBST(glibcxx_POFILES)
++
++ CLOCALE_H=config/locale/uclibc/c_locale.h
++ CLOCALE_CC=config/locale/uclibc/c_locale.cc
++ CCODECVT_H=config/locale/ieee_1003.1-2001/codecvt_specializations.h
++ CCODECVT_CC=config/locale/uclibc/codecvt_members.cc
++ CCOLLATE_CC=config/locale/uclibc/collate_members.cc
++ CCTYPE_CC=config/locale/uclibc/ctype_members.cc
++ CMESSAGES_H=config/locale/uclibc/messages_members.h
++ CMESSAGES_CC=config/locale/uclibc/messages_members.cc
++ CMONEY_CC=config/locale/uclibc/monetary_members.cc
++ CNUMERIC_CC=config/locale/uclibc/numeric_members.cc
++ CTIME_H=config/locale/uclibc/time_members.h
++ CTIME_CC=config/locale/uclibc/time_members.cc
++ CLOCALE_INTERNAL_H=config/locale/uclibc/c++locale_internal.h
++ ;;
+ esac
+
+ # This is where the testsuite looks for locale catalogs, using the
+diff -urN gcc-3.4.2-dist/libstdc++-v3/aclocal.m4 gcc-3.4.2/libstdc++-v3/aclocal.m4
+--- gcc-3.4.2-dist/libstdc++-v3/aclocal.m4 2004-08-13 15:44:03.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/aclocal.m4 2004-09-10 10:47:40.000000000 -0500
+@@ -1025,6 +1025,9 @@
+ # Default to "generic".
+ if test $enable_clocale_flag = auto; then
+ case x${target_os} in
++ x*-uclibc*)
++ enable_clocale_flag=uclibc
++ ;;
+ xlinux* | xgnu* | xkfreebsd*-gnu | xknetbsd*-gnu)
+ AC_EGREP_CPP([_GLIBCXX_ok], [
+ #include <features.h>
+@@ -1151,6 +1154,41 @@
+ CTIME_CC=config/locale/generic/time_members.cc
+ CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+ ;;
++ uclibc)
++ AC_MSG_RESULT(uclibc)
++
++ # Declare intention to use gettext, and add support for specific
++ # languages.
++ # For some reason, ALL_LINGUAS has to be before AM-GNU-GETTEXT
++ ALL_LINGUAS="de fr"
++
++ # Don't call AM-GNU-GETTEXT here. Instead, assume glibc.
++ AC_CHECK_PROG(check_msgfmt, msgfmt, yes, no)
++ if test x"$check_msgfmt" = x"yes" && test x"$enable_nls" = x"yes"; then
++ USE_NLS=yes
++ fi
++ # Export the build objects.
++ for ling in $ALL_LINGUAS; do \
++ glibcxx_MOFILES="$glibcxx_MOFILES $ling.mo"; \
++ glibcxx_POFILES="$glibcxx_POFILES $ling.po"; \
++ done
++ AC_SUBST(glibcxx_MOFILES)
++ AC_SUBST(glibcxx_POFILES)
++
++ CLOCALE_H=config/locale/uclibc/c_locale.h
++ CLOCALE_CC=config/locale/uclibc/c_locale.cc
++ CCODECVT_H=config/locale/ieee_1003.1-2001/codecvt_specializations.h
++ CCODECVT_CC=config/locale/uclibc/codecvt_members.cc
++ CCOLLATE_CC=config/locale/uclibc/collate_members.cc
++ CCTYPE_CC=config/locale/uclibc/ctype_members.cc
++ CMESSAGES_H=config/locale/uclibc/messages_members.h
++ CMESSAGES_CC=config/locale/uclibc/messages_members.cc
++ CMONEY_CC=config/locale/uclibc/monetary_members.cc
++ CNUMERIC_CC=config/locale/uclibc/numeric_members.cc
++ CTIME_H=config/locale/uclibc/time_members.h
++ CTIME_CC=config/locale/uclibc/time_members.cc
++ CLOCALE_INTERNAL_H=config/locale/uclibc/c++locale_internal.h
++ ;;
+ esac
+
+ # This is where the testsuite looks for locale catalogs, using the
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c++locale_internal.h gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c++locale_internal.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c++locale_internal.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c++locale_internal.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,59 @@
++// Prototypes for GLIBC thread locale __-prefixed functions -*- C++ -*-
++
++// Copyright (C) 2002, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++// Written by Jakub Jelinek <jakub@redhat.com>
++
++#include <clocale>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning clean this up
++#endif
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++
++extern "C" __typeof(iswctype_l) __iswctype_l;
++extern "C" __typeof(nl_langinfo_l) __nl_langinfo_l;
++extern "C" __typeof(strcoll_l) __strcoll_l;
++extern "C" __typeof(strftime_l) __strftime_l;
++extern "C" __typeof(strtod_l) __strtod_l;
++extern "C" __typeof(strtof_l) __strtof_l;
++extern "C" __typeof(strtold_l) __strtold_l;
++extern "C" __typeof(strxfrm_l) __strxfrm_l;
++extern "C" __typeof(towlower_l) __towlower_l;
++extern "C" __typeof(towupper_l) __towupper_l;
++extern "C" __typeof(wcscoll_l) __wcscoll_l;
++extern "C" __typeof(wcsftime_l) __wcsftime_l;
++extern "C" __typeof(wcsxfrm_l) __wcsxfrm_l;
++extern "C" __typeof(wctype_l) __wctype_l;
++extern "C" __typeof(newlocale) __newlocale;
++extern "C" __typeof(freelocale) __freelocale;
++extern "C" __typeof(duplocale) __duplocale;
++extern "C" __typeof(uselocale) __uselocale;
++
++#endif // GLIBC 2.3 and later
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,160 @@
++// Wrapper for underlying C-language localization -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.8 Standard locale categories.
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <cerrno> // For errno
++#include <locale>
++#include <stdexcept>
++#include <langinfo.h>
++#include <bits/c++locale_internal.h>
++
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __strtol_l(S, E, B, L) strtol((S), (E), (B))
++#define __strtoul_l(S, E, B, L) strtoul((S), (E), (B))
++#define __strtoll_l(S, E, B, L) strtoll((S), (E), (B))
++#define __strtoull_l(S, E, B, L) strtoull((S), (E), (B))
++#define __strtof_l(S, E, L) strtof((S), (E))
++#define __strtod_l(S, E, L) strtod((S), (E))
++#define __strtold_l(S, E, L) strtold((S), (E))
++#warning should dummy __newlocale check for C|POSIX ?
++#define __newlocale(a, b, c) NULL
++#define __freelocale(a) ((void)0)
++#define __duplocale(a) __c_locale()
++#endif
++
++namespace std
++{
++ template<>
++ void
++ __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err,
++ const __c_locale& __cloc)
++ {
++ if (!(__err & ios_base::failbit))
++ {
++ char* __sanity;
++ errno = 0;
++ float __f = __strtof_l(__s, &__sanity, __cloc);
++ if (__sanity != __s && errno != ERANGE)
++ __v = __f;
++ else
++ __err |= ios_base::failbit;
++ }
++ }
++
++ template<>
++ void
++ __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err,
++ const __c_locale& __cloc)
++ {
++ if (!(__err & ios_base::failbit))
++ {
++ char* __sanity;
++ errno = 0;
++ double __d = __strtod_l(__s, &__sanity, __cloc);
++ if (__sanity != __s && errno != ERANGE)
++ __v = __d;
++ else
++ __err |= ios_base::failbit;
++ }
++ }
++
++ template<>
++ void
++ __convert_to_v(const char* __s, long double& __v, ios_base::iostate& __err,
++ const __c_locale& __cloc)
++ {
++ if (!(__err & ios_base::failbit))
++ {
++ char* __sanity;
++ errno = 0;
++ long double __ld = __strtold_l(__s, &__sanity, __cloc);
++ if (__sanity != __s && errno != ERANGE)
++ __v = __ld;
++ else
++ __err |= ios_base::failbit;
++ }
++ }
++
++ void
++ locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
++ __c_locale __old)
++ {
++ __cloc = __newlocale(1 << LC_ALL, __s, __old);
++#ifdef __UCLIBC_HAS_XLOCALE__
++ if (!__cloc)
++ {
++ // This named locale is not supported by the underlying OS.
++ __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
++ "name not valid"));
++ }
++#endif
++ }
++
++ void
++ locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
++ {
++ if (_S_get_c_locale() != __cloc)
++ __freelocale(__cloc);
++ }
++
++ __c_locale
++ locale::facet::_S_clone_c_locale(__c_locale& __cloc)
++ { return __duplocale(__cloc); }
++} // namespace std
++
++namespace __gnu_cxx
++{
++ const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
++ {
++ "LC_CTYPE",
++ "LC_NUMERIC",
++ "LC_TIME",
++ "LC_COLLATE",
++ "LC_MONETARY",
++ "LC_MESSAGES",
++#if _GLIBCXX_NUM_CATEGORIES != 0
++ "LC_PAPER",
++ "LC_NAME",
++ "LC_ADDRESS",
++ "LC_TELEPHONE",
++ "LC_MEASUREMENT",
++ "LC_IDENTIFICATION"
++#endif
++ };
++}
++
++namespace std
++{
++ const char* const* const locale::_S_categories = __gnu_cxx::category_names;
++} // namespace std
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.h gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.h 2004-09-10 10:48:08.000000000 -0500
+@@ -0,0 +1,115 @@
++// Wrapper for underlying C-language localization -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.8 Standard locale categories.
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#ifndef _C_LOCALE_H
++#define _C_LOCALE_H 1
++
++#pragma GCC system_header
++
++#include <cstring> // get std::strlen
++#include <cstdio> // get std::snprintf or std::sprintf
++#include <clocale>
++#include <langinfo.h> // For codecvt
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix this
++#endif
++#ifdef __UCLIBC_HAS_LOCALE__
++#include <iconv.h> // For codecvt using iconv, iconv_t
++#endif
++#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
++#include <libintl.h> // For messages
++#endif
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning what is _GLIBCXX_C_LOCALE_GNU for
++#endif
++#define _GLIBCXX_C_LOCALE_GNU 1
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix categories
++#endif
++// #define _GLIBCXX_NUM_CATEGORIES 6
++#define _GLIBCXX_NUM_CATEGORIES 0
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++namespace __gnu_cxx
++{
++ extern "C" __typeof(uselocale) __uselocale;
++}
++#endif
++
++namespace std
++{
++#ifdef __UCLIBC_HAS_XLOCALE__
++ typedef __locale_t __c_locale;
++#else
++ typedef int* __c_locale;
++#endif
++
++ // Convert numeric value of type _Tv to string and return length of
++ // string. If snprintf is available use it, otherwise fall back to
++ // the unsafe sprintf which, in general, can be dangerous and should
++ // be avoided.
++ template<typename _Tv>
++ int
++ __convert_from_v(char* __out, const int __size, const char* __fmt,
++#ifdef __UCLIBC_HAS_XLOCALE__
++ _Tv __v, const __c_locale& __cloc, int __prec)
++ {
++ __c_locale __old = __gnu_cxx::__uselocale(__cloc);
++#else
++ _Tv __v, const __c_locale&, int __prec)
++ {
++# ifdef __UCLIBC_HAS_LOCALE__
++ char* __old = std::setlocale(LC_ALL, NULL);
++ char* __sav = new char[std::strlen(__old) + 1];
++ std::strcpy(__sav, __old);
++ std::setlocale(LC_ALL, "C");
++# endif
++#endif
++
++ const int __ret = std::snprintf(__out, __size, __fmt, __prec, __v);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __gnu_cxx::__uselocale(__old);
++#elif defined __UCLIBC_HAS_LOCALE__
++ std::setlocale(LC_ALL, __sav);
++ delete [] __sav;
++#endif
++ return __ret;
++ }
++}
++
++#endif
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/codecvt_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/codecvt_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/codecvt_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/codecvt_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,306 @@
++// std::codecvt implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2002, 2003 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.1.5 - Template class codecvt
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <locale>
++#include <bits/c++locale_internal.h>
++
++namespace std
++{
++ // Specializations.
++#ifdef _GLIBCXX_USE_WCHAR_T
++ codecvt_base::result
++ codecvt<wchar_t, char, mbstate_t>::
++ do_out(state_type& __state, const intern_type* __from,
++ const intern_type* __from_end, const intern_type*& __from_next,
++ extern_type* __to, extern_type* __to_end,
++ extern_type*& __to_next) const
++ {
++ result __ret = ok;
++ state_type __tmp_state(__state);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++
++ // wcsnrtombs is *very* fast but stops if encounters NUL characters:
++ // in case we fall back to wcrtomb and then continue, in a loop.
++ // NB: wcsnrtombs is a GNU extension
++ for (__from_next = __from, __to_next = __to;
++ __from_next < __from_end && __to_next < __to_end
++ && __ret == ok;)
++ {
++ const intern_type* __from_chunk_end = wmemchr(__from_next, L'\0',
++ __from_end - __from_next);
++ if (!__from_chunk_end)
++ __from_chunk_end = __from_end;
++
++ __from = __from_next;
++ const size_t __conv = wcsnrtombs(__to_next, &__from_next,
++ __from_chunk_end - __from_next,
++ __to_end - __to_next, &__state);
++ if (__conv == static_cast<size_t>(-1))
++ {
++ // In case of error, in order to stop at the exact place we
++ // have to start again from the beginning with a series of
++ // wcrtomb.
++ for (; __from < __from_next; ++__from)
++ __to_next += wcrtomb(__to_next, *__from, &__tmp_state);
++ __state = __tmp_state;
++ __ret = error;
++ }
++ else if (__from_next && __from_next < __from_chunk_end)
++ {
++ __to_next += __conv;
++ __ret = partial;
++ }
++ else
++ {
++ __from_next = __from_chunk_end;
++ __to_next += __conv;
++ }
++
++ if (__from_next < __from_end && __ret == ok)
++ {
++ extern_type __buf[MB_LEN_MAX];
++ __tmp_state = __state;
++ const size_t __conv = wcrtomb(__buf, *__from_next, &__tmp_state);
++ if (__conv > static_cast<size_t>(__to_end - __to_next))
++ __ret = partial;
++ else
++ {
++ memcpy(__to_next, __buf, __conv);
++ __state = __tmp_state;
++ __to_next += __conv;
++ ++__from_next;
++ }
++ }
++ }
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++
++ return __ret;
++ }
++
++ codecvt_base::result
++ codecvt<wchar_t, char, mbstate_t>::
++ do_in(state_type& __state, const extern_type* __from,
++ const extern_type* __from_end, const extern_type*& __from_next,
++ intern_type* __to, intern_type* __to_end,
++ intern_type*& __to_next) const
++ {
++ result __ret = ok;
++ state_type __tmp_state(__state);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++
++ // mbsnrtowcs is *very* fast but stops if encounters NUL characters:
++ // in case we store a L'\0' and then continue, in a loop.
++ // NB: mbsnrtowcs is a GNU extension
++ for (__from_next = __from, __to_next = __to;
++ __from_next < __from_end && __to_next < __to_end
++ && __ret == ok;)
++ {
++ const extern_type* __from_chunk_end;
++ __from_chunk_end = static_cast<const extern_type*>(memchr(__from_next, '\0',
++ __from_end
++ - __from_next));
++ if (!__from_chunk_end)
++ __from_chunk_end = __from_end;
++
++ __from = __from_next;
++ size_t __conv = mbsnrtowcs(__to_next, &__from_next,
++ __from_chunk_end - __from_next,
++ __to_end - __to_next, &__state);
++ if (__conv == static_cast<size_t>(-1))
++ {
++ // In case of error, in order to stop at the exact place we
++ // have to start again from the beginning with a series of
++ // mbrtowc.
++ for (;; ++__to_next, __from += __conv)
++ {
++ __conv = mbrtowc(__to_next, __from, __from_end - __from,
++ &__tmp_state);
++ if (__conv == static_cast<size_t>(-1)
++ || __conv == static_cast<size_t>(-2))
++ break;
++ }
++ __from_next = __from;
++ __state = __tmp_state;
++ __ret = error;
++ }
++ else if (__from_next && __from_next < __from_chunk_end)
++ {
++ // It is unclear what to return in this case (see DR 382).
++ __to_next += __conv;
++ __ret = partial;
++ }
++ else
++ {
++ __from_next = __from_chunk_end;
++ __to_next += __conv;
++ }
++
++ if (__from_next < __from_end && __ret == ok)
++ {
++ if (__to_next < __to_end)
++ {
++ // XXX Probably wrong for stateful encodings
++ __tmp_state = __state;
++ ++__from_next;
++ *__to_next++ = L'\0';
++ }
++ else
++ __ret = partial;
++ }
++ }
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++
++ return __ret;
++ }
++
++ int
++ codecvt<wchar_t, char, mbstate_t>::
++ do_encoding() const throw()
++ {
++ // XXX This implementation assumes that the encoding is
++ // stateless and is either single-byte or variable-width.
++ int __ret = 0;
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++ if (MB_CUR_MAX == 1)
++ __ret = 1;
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ return __ret;
++ }
++
++ int
++ codecvt<wchar_t, char, mbstate_t>::
++ do_max_length() const throw()
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++ // XXX Probably wrong for stateful encodings.
++ int __ret = MB_CUR_MAX;
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ return __ret;
++ }
++
++ int
++ codecvt<wchar_t, char, mbstate_t>::
++ do_length(state_type& __state, const extern_type* __from,
++ const extern_type* __end, size_t __max) const
++ {
++ int __ret = 0;
++ state_type __tmp_state(__state);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++
++ // mbsnrtowcs is *very* fast but stops if encounters NUL characters:
++ // in case we advance past it and then continue, in a loop.
++ // NB: mbsnrtowcs is a GNU extension
++
++ // A dummy internal buffer is needed in order for mbsnrtocws to consider
++ // its fourth parameter (it wouldn't with NULL as first parameter).
++ wchar_t* __to = static_cast<wchar_t*>(__builtin_alloca(sizeof(wchar_t)
++ * __max));
++ while (__from < __end && __max)
++ {
++ const extern_type* __from_chunk_end;
++ __from_chunk_end = static_cast<const extern_type*>(memchr(__from, '\0',
++ __end
++ - __from));
++ if (!__from_chunk_end)
++ __from_chunk_end = __end;
++
++ const extern_type* __tmp_from = __from;
++ size_t __conv = mbsnrtowcs(__to, &__from,
++ __from_chunk_end - __from,
++ __max, &__state);
++ if (__conv == static_cast<size_t>(-1))
++ {
++ // In case of error, in order to stop at the exact place we
++ // have to start again from the beginning with a series of
++ // mbrtowc.
++ for (__from = __tmp_from;; __from += __conv)
++ {
++ __conv = mbrtowc(NULL, __from, __end - __from,
++ &__tmp_state);
++ if (__conv == static_cast<size_t>(-1)
++ || __conv == static_cast<size_t>(-2))
++ break;
++ }
++ __state = __tmp_state;
++ __ret += __from - __tmp_from;
++ break;
++ }
++ if (!__from)
++ __from = __from_chunk_end;
++
++ __ret += __from - __tmp_from;
++ __max -= __conv;
++
++ if (__from < __end && __max)
++ {
++ // XXX Probably wrong for stateful encodings
++ __tmp_state = __state;
++ ++__from;
++ ++__ret;
++ --__max;
++ }
++ }
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++
++ return __ret;
++ }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/collate_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/collate_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/collate_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/collate_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,80 @@
++// std::collate implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.4.1.2 collate virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <locale>
++#include <bits/c++locale_internal.h>
++
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __strcoll_l(S1, S2, L) strcoll((S1), (S2))
++#define __strxfrm_l(S1, S2, N, L) strxfrm((S1), (S2), (N))
++#define __wcscoll_l(S1, S2, L) wcscoll((S1), (S2))
++#define __wcsxfrm_l(S1, S2, N, L) wcsxfrm((S1), (S2), (N))
++#endif
++
++namespace std
++{
++ // These are basically extensions to char_traits, and perhaps should
++ // be put there instead of here.
++ template<>
++ int
++ collate<char>::_M_compare(const char* __one, const char* __two) const
++ {
++ int __cmp = __strcoll_l(__one, __two, _M_c_locale_collate);
++ return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0);
++ }
++
++ template<>
++ size_t
++ collate<char>::_M_transform(char* __to, const char* __from,
++ size_t __n) const
++ { return __strxfrm_l(__to, __from, __n, _M_c_locale_collate); }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ template<>
++ int
++ collate<wchar_t>::_M_compare(const wchar_t* __one,
++ const wchar_t* __two) const
++ {
++ int __cmp = __wcscoll_l(__one, __two, _M_c_locale_collate);
++ return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0);
++ }
++
++ template<>
++ size_t
++ collate<wchar_t>::_M_transform(wchar_t* __to, const wchar_t* __from,
++ size_t __n) const
++ { return __wcsxfrm_l(__to, __from, __n, _M_c_locale_collate); }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/ctype_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/ctype_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/ctype_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/ctype_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,300 @@
++// std::ctype implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.1.1.2 ctype virtual functions.
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#define _LIBC
++#include <locale>
++#undef _LIBC
++#include <bits/c++locale_internal.h>
++
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __wctype_l(S, L) wctype((S))
++#define __towupper_l(C, L) towupper((C))
++#define __towlower_l(C, L) towlower((C))
++#define __iswctype_l(C, M, L) iswctype((C), (M))
++#endif
++
++namespace std
++{
++ // NB: The other ctype<char> specializations are in src/locale.cc and
++ // various /config/os/* files.
++ template<>
++ ctype_byname<char>::ctype_byname(const char* __s, size_t __refs)
++ : ctype<char>(0, false, __refs)
++ {
++ if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
++ {
++ this->_S_destroy_c_locale(this->_M_c_locale_ctype);
++ this->_S_create_c_locale(this->_M_c_locale_ctype, __s);
++#ifdef __UCLIBC_HAS_XLOCALE__
++ this->_M_toupper = this->_M_c_locale_ctype->__ctype_toupper;
++ this->_M_tolower = this->_M_c_locale_ctype->__ctype_tolower;
++ this->_M_table = this->_M_c_locale_ctype->__ctype_b;
++#endif
++ }
++ }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ ctype<wchar_t>::__wmask_type
++ ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const
++ {
++ __wmask_type __ret;
++ switch (__m)
++ {
++ case space:
++ __ret = __wctype_l("space", _M_c_locale_ctype);
++ break;
++ case print:
++ __ret = __wctype_l("print", _M_c_locale_ctype);
++ break;
++ case cntrl:
++ __ret = __wctype_l("cntrl", _M_c_locale_ctype);
++ break;
++ case upper:
++ __ret = __wctype_l("upper", _M_c_locale_ctype);
++ break;
++ case lower:
++ __ret = __wctype_l("lower", _M_c_locale_ctype);
++ break;
++ case alpha:
++ __ret = __wctype_l("alpha", _M_c_locale_ctype);
++ break;
++ case digit:
++ __ret = __wctype_l("digit", _M_c_locale_ctype);
++ break;
++ case punct:
++ __ret = __wctype_l("punct", _M_c_locale_ctype);
++ break;
++ case xdigit:
++ __ret = __wctype_l("xdigit", _M_c_locale_ctype);
++ break;
++ case alnum:
++ __ret = __wctype_l("alnum", _M_c_locale_ctype);
++ break;
++ case graph:
++ __ret = __wctype_l("graph", _M_c_locale_ctype);
++ break;
++ default:
++ __ret = 0;
++ }
++ return __ret;
++ }
++
++ wchar_t
++ ctype<wchar_t>::do_toupper(wchar_t __c) const
++ { return __towupper_l(__c, _M_c_locale_ctype); }
++
++ const wchar_t*
++ ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const
++ {
++ while (__lo < __hi)
++ {
++ *__lo = __towupper_l(*__lo, _M_c_locale_ctype);
++ ++__lo;
++ }
++ return __hi;
++ }
++
++ wchar_t
++ ctype<wchar_t>::do_tolower(wchar_t __c) const
++ { return __towlower_l(__c, _M_c_locale_ctype); }
++
++ const wchar_t*
++ ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const
++ {
++ while (__lo < __hi)
++ {
++ *__lo = __towlower_l(*__lo, _M_c_locale_ctype);
++ ++__lo;
++ }
++ return __hi;
++ }
++
++ bool
++ ctype<wchar_t>::
++ do_is(mask __m, wchar_t __c) const
++ {
++ // Highest bitmask in ctype_base == 10, but extra in "C"
++ // library for blank.
++ bool __ret = false;
++ const size_t __bitmasksize = 11;
++ for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
++ if (__m & _M_bit[__bitcur]
++ && __iswctype_l(__c, _M_wmask[__bitcur], _M_c_locale_ctype))
++ {
++ __ret = true;
++ break;
++ }
++ return __ret;
++ }
++
++ const wchar_t*
++ ctype<wchar_t>::
++ do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __vec) const
++ {
++ for (; __lo < __hi; ++__vec, ++__lo)
++ {
++ // Highest bitmask in ctype_base == 10, but extra in "C"
++ // library for blank.
++ const size_t __bitmasksize = 11;
++ mask __m = 0;
++ for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
++ if (__iswctype_l(*__lo, _M_wmask[__bitcur], _M_c_locale_ctype))
++ __m |= _M_bit[__bitcur];
++ *__vec = __m;
++ }
++ return __hi;
++ }
++
++ const wchar_t*
++ ctype<wchar_t>::
++ do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const
++ {
++ while (__lo < __hi && !this->do_is(__m, *__lo))
++ ++__lo;
++ return __lo;
++ }
++
++ const wchar_t*
++ ctype<wchar_t>::
++ do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const
++ {
++ while (__lo < __hi && this->do_is(__m, *__lo) != 0)
++ ++__lo;
++ return __lo;
++ }
++
++ wchar_t
++ ctype<wchar_t>::
++ do_widen(char __c) const
++ { return _M_widen[static_cast<unsigned char>(__c)]; }
++
++ const char*
++ ctype<wchar_t>::
++ do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const
++ {
++ while (__lo < __hi)
++ {
++ *__dest = _M_widen[static_cast<unsigned char>(*__lo)];
++ ++__lo;
++ ++__dest;
++ }
++ return __hi;
++ }
++
++ char
++ ctype<wchar_t>::
++ do_narrow(wchar_t __wc, char __dfault) const
++ {
++ if (__wc >= 0 && __wc < 128 && _M_narrow_ok)
++ return _M_narrow[__wc];
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_ctype);
++#endif
++ const int __c = wctob(__wc);
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ return (__c == EOF ? __dfault : static_cast<char>(__c));
++ }
++
++ const wchar_t*
++ ctype<wchar_t>::
++ do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault,
++ char* __dest) const
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_ctype);
++#endif
++ if (_M_narrow_ok)
++ while (__lo < __hi)
++ {
++ if (*__lo >= 0 && *__lo < 128)
++ *__dest = _M_narrow[*__lo];
++ else
++ {
++ const int __c = wctob(*__lo);
++ *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
++ }
++ ++__lo;
++ ++__dest;
++ }
++ else
++ while (__lo < __hi)
++ {
++ const int __c = wctob(*__lo);
++ *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
++ ++__lo;
++ ++__dest;
++ }
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ return __hi;
++ }
++
++ void
++ ctype<wchar_t>::_M_initialize_ctype()
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_ctype);
++#endif
++ wint_t __i;
++ for (__i = 0; __i < 128; ++__i)
++ {
++ const int __c = wctob(__i);
++ if (__c == EOF)
++ break;
++ else
++ _M_narrow[__i] = static_cast<char>(__c);
++ }
++ if (__i == 128)
++ _M_narrow_ok = true;
++ else
++ _M_narrow_ok = false;
++ for (size_t __j = 0;
++ __j < sizeof(_M_widen) / sizeof(wint_t); ++__j)
++ _M_widen[__j] = btowc(__j);
++
++ for (size_t __k = 0; __k <= 11; ++__k)
++ {
++ _M_bit[__k] = static_cast<mask>(_ISbit(__k));
++ _M_wmask[__k] = _M_convert_to_wmask(_M_bit[__k]);
++ }
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ }
++#endif // _GLIBCXX_USE_WCHAR_T
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/messages_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/messages_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/messages_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/messages_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,100 @@
++// std::messages implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.7.1.2 messages virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <locale>
++#include <bits/c++locale_internal.h>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix gettext stuff
++#endif
++#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
++extern "C" char *__dcgettext(const char *domainname,
++ const char *msgid, int category);
++#undef gettext
++#define gettext(msgid) __dcgettext(NULL, msgid, LC_MESSAGES)
++#else
++#undef gettext
++#define gettext(msgid) (msgid)
++#endif
++
++namespace std
++{
++ // Specializations.
++ template<>
++ string
++ messages<char>::do_get(catalog, int, int, const string& __dfault) const
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_messages);
++ const char* __msg = const_cast<const char*>(gettext(__dfault.c_str()));
++ __uselocale(__old);
++ return string(__msg);
++#elif defined __UCLIBC_HAS_LOCALE__
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, _M_name_messages);
++ const char* __msg = gettext(__dfault.c_str());
++ setlocale(LC_ALL, __old);
++ free(__old);
++ return string(__msg);
++#else
++ const char* __msg = gettext(__dfault.c_str());
++ return string(__msg);
++#endif
++ }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ template<>
++ wstring
++ messages<wchar_t>::do_get(catalog, int, int, const wstring& __dfault) const
++ {
++# ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_messages);
++ char* __msg = gettext(_M_convert_to_char(__dfault));
++ __uselocale(__old);
++ return _M_convert_from_char(__msg);
++# elif defined __UCLIBC_HAS_LOCALE__
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, _M_name_messages);
++ char* __msg = gettext(_M_convert_to_char(__dfault));
++ setlocale(LC_ALL, __old);
++ free(__old);
++ return _M_convert_from_char(__msg);
++# else
++ char* __msg = gettext(_M_convert_to_char(__dfault));
++ return _M_convert_from_char(__msg);
++# endif
++ }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/messages_members.h gcc-3.4.2/libstdc++-v3/config/locale/uclibc/messages_members.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/messages_members.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/messages_members.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,118 @@
++// std::messages implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.7.1.2 messages functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix prototypes for *textdomain funcs
++#endif
++#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
++extern "C" char *__textdomain(const char *domainname);
++extern "C" char *__bindtextdomain(const char *domainname,
++ const char *dirname);
++#else
++#undef __textdomain
++#undef __bindtextdomain
++#define __textdomain(D) ((void)0)
++#define __bindtextdomain(D,P) ((void)0)
++#endif
++
++ // Non-virtual member functions.
++ template<typename _CharT>
++ messages<_CharT>::messages(size_t __refs)
++ : facet(__refs), _M_c_locale_messages(_S_get_c_locale()),
++ _M_name_messages(_S_get_c_name())
++ { }
++
++ template<typename _CharT>
++ messages<_CharT>::messages(__c_locale __cloc, const char* __s,
++ size_t __refs)
++ : facet(__refs), _M_c_locale_messages(_S_clone_c_locale(__cloc)),
++ _M_name_messages(__s)
++ {
++ char* __tmp = new char[std::strlen(__s) + 1];
++ std::strcpy(__tmp, __s);
++ _M_name_messages = __tmp;
++ }
++
++ template<typename _CharT>
++ typename messages<_CharT>::catalog
++ messages<_CharT>::open(const basic_string<char>& __s, const locale& __loc,
++ const char* __dir) const
++ {
++ __bindtextdomain(__s.c_str(), __dir);
++ return this->do_open(__s, __loc);
++ }
++
++ // Virtual member functions.
++ template<typename _CharT>
++ messages<_CharT>::~messages()
++ {
++ if (_M_name_messages != _S_get_c_name())
++ delete [] _M_name_messages;
++ _S_destroy_c_locale(_M_c_locale_messages);
++ }
++
++ template<typename _CharT>
++ typename messages<_CharT>::catalog
++ messages<_CharT>::do_open(const basic_string<char>& __s,
++ const locale&) const
++ {
++ // No error checking is done, assume the catalog exists and can
++ // be used.
++ __textdomain(__s.c_str());
++ return 0;
++ }
++
++ template<typename _CharT>
++ void
++ messages<_CharT>::do_close(catalog) const
++ { }
++
++ // messages_byname
++ template<typename _CharT>
++ messages_byname<_CharT>::messages_byname(const char* __s, size_t __refs)
++ : messages<_CharT>(__refs)
++ {
++ if (this->_M_name_messages != locale::facet::_S_get_c_name())
++ delete [] this->_M_name_messages;
++ char* __tmp = new char[std::strlen(__s) + 1];
++ std::strcpy(__tmp, __s);
++ this->_M_name_messages = __tmp;
++
++ if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
++ {
++ this->_S_destroy_c_locale(this->_M_c_locale_messages);
++ this->_S_create_c_locale(this->_M_c_locale_messages, __s);
++ }
++ }
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/monetary_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/monetary_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/monetary_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/monetary_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,698 @@
++// std::moneypunct implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.6.3.2 moneypunct virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#define _LIBC
++#include <locale>
++#undef _LIBC
++#include <bits/c++locale_internal.h>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning optimize this for uclibc
++#warning tailor for stub locale support
++#endif
++
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __nl_langinfo_l(N, L) nl_langinfo((N))
++#endif
++
++namespace std
++{
++ // Construct and return valid pattern consisting of some combination of:
++ // space none symbol sign value
++ money_base::pattern
++ money_base::_S_construct_pattern(char __precedes, char __space, char __posn)
++ {
++ pattern __ret;
++
++ // This insanely complicated routine attempts to construct a valid
++ // pattern for use with monyepunct. A couple of invariants:
++
++ // if (__precedes) symbol -> value
++ // else value -> symbol
++
++ // if (__space) space
++ // else none
++
++ // none == never first
++ // space never first or last
++
++ // Any elegant implementations of this are welcome.
++ switch (__posn)
++ {
++ case 0:
++ case 1:
++ // 1 The sign precedes the value and symbol.
++ __ret.field[0] = sign;
++ if (__space)
++ {
++ // Pattern starts with sign.
++ if (__precedes)
++ {
++ __ret.field[1] = symbol;
++ __ret.field[3] = value;
++ }
++ else
++ {
++ __ret.field[1] = value;
++ __ret.field[3] = symbol;
++ }
++ __ret.field[2] = space;
++ }
++ else
++ {
++ // Pattern starts with sign and ends with none.
++ if (__precedes)
++ {
++ __ret.field[1] = symbol;
++ __ret.field[2] = value;
++ }
++ else
++ {
++ __ret.field[1] = value;
++ __ret.field[2] = symbol;
++ }
++ __ret.field[3] = none;
++ }
++ break;
++ case 2:
++ // 2 The sign follows the value and symbol.
++ if (__space)
++ {
++ // Pattern either ends with sign.
++ if (__precedes)
++ {
++ __ret.field[0] = symbol;
++ __ret.field[2] = value;
++ }
++ else
++ {
++ __ret.field[0] = value;
++ __ret.field[2] = symbol;
++ }
++ __ret.field[1] = space;
++ __ret.field[3] = sign;
++ }
++ else
++ {
++ // Pattern ends with sign then none.
++ if (__precedes)
++ {
++ __ret.field[0] = symbol;
++ __ret.field[1] = value;
++ }
++ else
++ {
++ __ret.field[0] = value;
++ __ret.field[1] = symbol;
++ }
++ __ret.field[2] = sign;
++ __ret.field[3] = none;
++ }
++ break;
++ case 3:
++ // 3 The sign immediately precedes the symbol.
++ if (__precedes)
++ {
++ __ret.field[0] = sign;
++ __ret.field[1] = symbol;
++ if (__space)
++ {
++ __ret.field[2] = space;
++ __ret.field[3] = value;
++ }
++ else
++ {
++ __ret.field[2] = value;
++ __ret.field[3] = none;
++ }
++ }
++ else
++ {
++ __ret.field[0] = value;
++ if (__space)
++ {
++ __ret.field[1] = space;
++ __ret.field[2] = sign;
++ __ret.field[3] = symbol;
++ }
++ else
++ {
++ __ret.field[1] = sign;
++ __ret.field[2] = symbol;
++ __ret.field[3] = none;
++ }
++ }
++ break;
++ case 4:
++ // 4 The sign immediately follows the symbol.
++ if (__precedes)
++ {
++ __ret.field[0] = symbol;
++ __ret.field[1] = sign;
++ if (__space)
++ {
++ __ret.field[2] = space;
++ __ret.field[3] = value;
++ }
++ else
++ {
++ __ret.field[2] = value;
++ __ret.field[3] = none;
++ }
++ }
++ else
++ {
++ __ret.field[0] = value;
++ if (__space)
++ {
++ __ret.field[1] = space;
++ __ret.field[2] = symbol;
++ __ret.field[3] = sign;
++ }
++ else
++ {
++ __ret.field[1] = symbol;
++ __ret.field[2] = sign;
++ __ret.field[3] = none;
++ }
++ }
++ break;
++ default:
++ ;
++ }
++ return __ret;
++ }
++
++ template<>
++ void
++ moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc,
++ const char*)
++ {
++ if (!_M_data)
++ _M_data = new __moneypunct_cache<char, true>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_decimal_point = '.';
++ _M_data->_M_thousands_sep = ',';
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_curr_symbol = "";
++ _M_data->_M_curr_symbol_size = 0;
++ _M_data->_M_positive_sign = "";
++ _M_data->_M_positive_sign_size = 0;
++ _M_data->_M_negative_sign = "";
++ _M_data->_M_negative_sign_size = 0;
++ _M_data->_M_frac_digits = 0;
++ _M_data->_M_pos_format = money_base::_S_default_pattern;
++ _M_data->_M_neg_format = money_base::_S_default_pattern;
++
++ for (size_t __i = 0; __i < money_base::_S_end; ++__i)
++ _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
++ }
++ else
++ {
++ // Named locale.
++ _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT,
++ __cloc));
++ _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP,
++ __cloc));
++ _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++ _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
++ _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign);
++
++ char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
++ if (!__nposn)
++ _M_data->_M_negative_sign = "()";
++ else
++ _M_data->_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN,
++ __cloc);
++ _M_data->_M_negative_sign_size = strlen(_M_data->_M_negative_sign);
++
++ // _Intl == true
++ _M_data->_M_curr_symbol = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
++ _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol);
++ _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
++ __cloc));
++ char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
++ char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
++ char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
++ _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
++ __pposn);
++ char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
++ char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
++ _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
++ __nposn);
++ }
++ }
++
++ template<>
++ void
++ moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc,
++ const char*)
++ {
++ if (!_M_data)
++ _M_data = new __moneypunct_cache<char, false>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_decimal_point = '.';
++ _M_data->_M_thousands_sep = ',';
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_curr_symbol = "";
++ _M_data->_M_curr_symbol_size = 0;
++ _M_data->_M_positive_sign = "";
++ _M_data->_M_positive_sign_size = 0;
++ _M_data->_M_negative_sign = "";
++ _M_data->_M_negative_sign_size = 0;
++ _M_data->_M_frac_digits = 0;
++ _M_data->_M_pos_format = money_base::_S_default_pattern;
++ _M_data->_M_neg_format = money_base::_S_default_pattern;
++
++ for (size_t __i = 0; __i < money_base::_S_end; ++__i)
++ _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
++ }
++ else
++ {
++ // Named locale.
++ _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT,
++ __cloc));
++ _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP,
++ __cloc));
++ _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++ _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
++ _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign);
++
++ char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
++ if (!__nposn)
++ _M_data->_M_negative_sign = "()";
++ else
++ _M_data->_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN,
++ __cloc);
++ _M_data->_M_negative_sign_size = strlen(_M_data->_M_negative_sign);
++
++ // _Intl == false
++ _M_data->_M_curr_symbol = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
++ _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol);
++ _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
++ char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
++ char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
++ char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
++ _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
++ __pposn);
++ char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
++ char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
++ _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
++ __nposn);
++ }
++ }
++
++ template<>
++ moneypunct<char, true>::~moneypunct()
++ { delete _M_data; }
++
++ template<>
++ moneypunct<char, false>::~moneypunct()
++ { delete _M_data; }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ template<>
++ void
++ moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc,
++#ifdef __UCLIBC_HAS_XLOCALE__
++ const char*)
++#else
++ const char* __name)
++#endif
++ {
++ if (!_M_data)
++ _M_data = new __moneypunct_cache<wchar_t, true>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_decimal_point = L'.';
++ _M_data->_M_thousands_sep = L',';
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_curr_symbol = L"";
++ _M_data->_M_curr_symbol_size = 0;
++ _M_data->_M_positive_sign = L"";
++ _M_data->_M_positive_sign_size = 0;
++ _M_data->_M_negative_sign = L"";
++ _M_data->_M_negative_sign_size = 0;
++ _M_data->_M_frac_digits = 0;
++ _M_data->_M_pos_format = money_base::_S_default_pattern;
++ _M_data->_M_neg_format = money_base::_S_default_pattern;
++
++ // Use ctype::widen code without the facet...
++ unsigned char uc;
++ for (size_t __i = 0; __i < money_base::_S_end; ++__i)
++ {
++ uc = static_cast<unsigned char>(money_base::_S_atoms[__i]);
++ _M_data->_M_atoms[__i] = btowc(uc);
++ }
++ }
++ else
++ {
++ // Named locale.
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(__cloc);
++#else
++ // Switch to named locale so that mbsrtowcs will work.
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, __name);
++#endif
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix this... should be monetary
++#endif
++#ifdef __UCLIBC__
++# ifdef __UCLIBC_HAS_XLOCALE__
++ _M_data->_M_decimal_point = __cloc->decimal_point_wc;
++ _M_data->_M_thousands_sep = __cloc->thousands_sep_wc;
++# else
++ _M_data->_M_decimal_point = __global_locale->decimal_point_wc;
++ _M_data->_M_thousands_sep = __global_locale->thousands_sep_wc;
++# endif
++#else
++ union __s_and_w { const char *__s; unsigned int __w; } __u;
++ __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
++ _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
++
++ __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
++ _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
++#endif
++ _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++
++ const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
++ const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
++ const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
++
++ wchar_t* __wcs_ps = 0;
++ wchar_t* __wcs_ns = 0;
++ const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
++ try
++ {
++ mbstate_t __state;
++ size_t __len = strlen(__cpossign);
++ if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ __wcs_ps = new wchar_t[__len];
++ mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
++ _M_data->_M_positive_sign = __wcs_ps;
++ }
++ else
++ _M_data->_M_positive_sign = L"";
++ _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
++
++ __len = strlen(__cnegsign);
++ if (!__nposn)
++ _M_data->_M_negative_sign = L"()";
++ else if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ __wcs_ns = new wchar_t[__len];
++ mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
++ _M_data->_M_negative_sign = __wcs_ns;
++ }
++ else
++ _M_data->_M_negative_sign = L"";
++ _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
++
++ // _Intl == true.
++ __len = strlen(__ccurr);
++ if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ wchar_t* __wcs = new wchar_t[__len];
++ mbsrtowcs(__wcs, &__ccurr, __len, &__state);
++ _M_data->_M_curr_symbol = __wcs;
++ }
++ else
++ _M_data->_M_curr_symbol = L"";
++ _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
++ }
++ catch (...)
++ {
++ delete _M_data;
++ _M_data = 0;
++ delete __wcs_ps;
++ delete __wcs_ns;
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#else
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ __throw_exception_again;
++ }
++
++ _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
++ __cloc));
++ char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
++ char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
++ char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
++ _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
++ __pposn);
++ char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
++ char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
++ _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
++ __nposn);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#else
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ }
++ }
++
++ template<>
++ void
++ moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
++#ifdef __UCLIBC_HAS_XLOCALE__
++ const char*)
++#else
++ const char* __name)
++#endif
++ {
++ if (!_M_data)
++ _M_data = new __moneypunct_cache<wchar_t, false>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_decimal_point = L'.';
++ _M_data->_M_thousands_sep = L',';
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_curr_symbol = L"";
++ _M_data->_M_curr_symbol_size = 0;
++ _M_data->_M_positive_sign = L"";
++ _M_data->_M_positive_sign_size = 0;
++ _M_data->_M_negative_sign = L"";
++ _M_data->_M_negative_sign_size = 0;
++ _M_data->_M_frac_digits = 0;
++ _M_data->_M_pos_format = money_base::_S_default_pattern;
++ _M_data->_M_neg_format = money_base::_S_default_pattern;
++
++ // Use ctype::widen code without the facet...
++ unsigned char uc;
++ for (size_t __i = 0; __i < money_base::_S_end; ++__i)
++ {
++ uc = static_cast<unsigned char>(money_base::_S_atoms[__i]);
++ _M_data->_M_atoms[__i] = btowc(uc);
++ }
++ }
++ else
++ {
++ // Named locale.
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(__cloc);
++#else
++ // Switch to named locale so that mbsrtowcs will work.
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, __name);
++#endif
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix this... should be monetary
++#endif
++#ifdef __UCLIBC__
++# ifdef __UCLIBC_HAS_XLOCALE__
++ _M_data->_M_decimal_point = __cloc->decimal_point_wc;
++ _M_data->_M_thousands_sep = __cloc->thousands_sep_wc;
++# else
++ _M_data->_M_decimal_point = __global_locale->decimal_point_wc;
++ _M_data->_M_thousands_sep = __global_locale->thousands_sep_wc;
++# endif
++#else
++ union __s_and_w { const char *__s; unsigned int __w; } __u;
++ __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
++ _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
++
++ __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
++ _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
++#endif
++ _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++
++ const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
++ const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
++ const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
++
++ wchar_t* __wcs_ps = 0;
++ wchar_t* __wcs_ns = 0;
++ const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
++ try
++ {
++ mbstate_t __state;
++ size_t __len;
++ __len = strlen(__cpossign);
++ if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ __wcs_ps = new wchar_t[__len];
++ mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
++ _M_data->_M_positive_sign = __wcs_ps;
++ }
++ else
++ _M_data->_M_positive_sign = L"";
++ _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
++
++ __len = strlen(__cnegsign);
++ if (!__nposn)
++ _M_data->_M_negative_sign = L"()";
++ else if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ __wcs_ns = new wchar_t[__len];
++ mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
++ _M_data->_M_negative_sign = __wcs_ns;
++ }
++ else
++ _M_data->_M_negative_sign = L"";
++ _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
++
++ // _Intl == true.
++ __len = strlen(__ccurr);
++ if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ wchar_t* __wcs = new wchar_t[__len];
++ mbsrtowcs(__wcs, &__ccurr, __len, &__state);
++ _M_data->_M_curr_symbol = __wcs;
++ }
++ else
++ _M_data->_M_curr_symbol = L"";
++ _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
++ }
++ catch (...)
++ {
++ delete _M_data;
++ _M_data = 0;
++ delete __wcs_ps;
++ delete __wcs_ns;
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#else
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ __throw_exception_again;
++ }
++
++ _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
++ char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
++ char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
++ char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
++ _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
++ __pposn);
++ char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
++ char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
++ _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
++ __nposn);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#else
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ }
++ }
++
++ template<>
++ moneypunct<wchar_t, true>::~moneypunct()
++ {
++ if (_M_data->_M_positive_sign_size)
++ delete [] _M_data->_M_positive_sign;
++ if (_M_data->_M_negative_sign_size
++ && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
++ delete [] _M_data->_M_negative_sign;
++ if (_M_data->_M_curr_symbol_size)
++ delete [] _M_data->_M_curr_symbol;
++ delete _M_data;
++ }
++
++ template<>
++ moneypunct<wchar_t, false>::~moneypunct()
++ {
++ if (_M_data->_M_positive_sign_size)
++ delete [] _M_data->_M_positive_sign;
++ if (_M_data->_M_negative_sign_size
++ && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
++ delete [] _M_data->_M_negative_sign;
++ if (_M_data->_M_curr_symbol_size)
++ delete [] _M_data->_M_curr_symbol;
++ delete _M_data;
++ }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/numeric_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/numeric_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/numeric_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/numeric_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,183 @@
++// std::numpunct implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.3.1.2 numpunct virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#define _LIBC
++#include <locale>
++#undef _LIBC
++#include <bits/c++locale_internal.h>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning tailor for stub locale support
++#endif
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __nl_langinfo_l(N, L) nl_langinfo((N))
++#endif
++
++namespace std
++{
++ template<>
++ void
++ numpunct<char>::_M_initialize_numpunct(__c_locale __cloc)
++ {
++ if (!_M_data)
++ _M_data = new __numpunct_cache<char>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_use_grouping = false;
++
++ _M_data->_M_decimal_point = '.';
++ _M_data->_M_thousands_sep = ',';
++
++ for (size_t __i = 0; __i < __num_base::_S_oend; ++__i)
++ _M_data->_M_atoms_out[__i] = __num_base::_S_atoms_out[__i];
++
++ for (size_t __j = 0; __j < __num_base::_S_iend; ++__j)
++ _M_data->_M_atoms_in[__j] = __num_base::_S_atoms_in[__j];
++ }
++ else
++ {
++ // Named locale.
++ _M_data->_M_decimal_point = *(__nl_langinfo_l(DECIMAL_POINT,
++ __cloc));
++ _M_data->_M_thousands_sep = *(__nl_langinfo_l(THOUSANDS_SEP,
++ __cloc));
++
++ // Check for NULL, which implies no grouping.
++ if (_M_data->_M_thousands_sep == '\0')
++ _M_data->_M_grouping = "";
++ else
++ _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++ }
++
++ // NB: There is no way to extact this info from posix locales.
++ // _M_truename = __nl_langinfo_l(YESSTR, __cloc);
++ _M_data->_M_truename = "true";
++ _M_data->_M_truename_size = strlen(_M_data->_M_truename);
++ // _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
++ _M_data->_M_falsename = "false";
++ _M_data->_M_falsename_size = strlen(_M_data->_M_falsename);
++ }
++
++ template<>
++ numpunct<char>::~numpunct()
++ { delete _M_data; }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ template<>
++ void
++ numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc)
++ {
++ if (!_M_data)
++ _M_data = new __numpunct_cache<wchar_t>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_use_grouping = false;
++
++ _M_data->_M_decimal_point = L'.';
++ _M_data->_M_thousands_sep = L',';
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_S_get_c_locale());
++#endif
++ // Use ctype::widen code without the facet...
++ unsigned char uc;
++ for (size_t __i = 0; __i < __num_base::_S_oend; ++__i)
++ {
++ uc = static_cast<unsigned char>(__num_base::_S_atoms_out[__i]);
++ _M_data->_M_atoms_out[__i] = btowc(uc);
++ }
++
++ for (size_t __j = 0; __j < __num_base::_S_iend; ++__j)
++ {
++ uc = static_cast<unsigned char>(__num_base::_S_atoms_in[__j]);
++ _M_data->_M_atoms_in[__j] = btowc(uc);
++ }
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ }
++ else
++ {
++ // Named locale.
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix this
++#endif
++#ifdef __UCLIBC__
++# ifdef __UCLIBC_HAS_XLOCALE__
++ _M_data->_M_decimal_point = __cloc->decimal_point_wc;
++ _M_data->_M_thousands_sep = __cloc->thousands_sep_wc;
++# else
++ _M_data->_M_decimal_point = __global_locale->decimal_point_wc;
++ _M_data->_M_thousands_sep = __global_locale->thousands_sep_wc;
++# endif
++#else
++ union __s_and_w { const char *__s; unsigned int __w; } __u;
++ __u.__s = __nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc);
++ _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
++
++ __u.__s = __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc);
++ _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
++#endif
++
++ if (_M_data->_M_thousands_sep == L'\0')
++ _M_data->_M_grouping = "";
++ else
++ _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++ }
++
++ // NB: There is no way to extact this info from posix locales.
++ // _M_truename = __nl_langinfo_l(YESSTR, __cloc);
++ _M_data->_M_truename = L"true";
++ _M_data->_M_truename_size = wcslen(_M_data->_M_truename);
++ // _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
++ _M_data->_M_falsename = L"false";
++ _M_data->_M_falsename_size = wcslen(_M_data->_M_falsename);
++ }
++
++ template<>
++ numpunct<wchar_t>::~numpunct()
++ { delete _M_data; }
++ #endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/time_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/time_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/time_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/time_members.cc 2004-09-10 10:48:00.000000000 -0500
+@@ -0,0 +1,356 @@
++// std::time_get, std::time_put implementation, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.5.1.2 - time_get virtual functions
++// ISO C++ 14882: 22.2.5.3.2 - time_put virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <locale>
++#include <bits/c++locale_internal.h>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning tailor for stub locale support
++#endif
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __nl_langinfo_l(N, L) nl_langinfo((N))
++#endif
++
++namespace std
++{
++ template<>
++ void
++ __timepunct<char>::
++ _M_put(char* __s, size_t __maxlen, const char* __format,
++ const tm* __tm) const
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ const size_t __len = __strftime_l(__s, __maxlen, __format, __tm,
++ _M_c_locale_timepunct);
++#else
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, _M_name_timepunct);
++ const size_t __len = strftime(__s, __maxlen, __format, __tm);
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ // Make sure __s is null terminated.
++ if (__len == 0)
++ __s[0] = '\0';
++ }
++
++ template<>
++ void
++ __timepunct<char>::_M_initialize_timepunct(__c_locale __cloc)
++ {
++ if (!_M_data)
++ _M_data = new __timepunct_cache<char>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_c_locale_timepunct = _S_get_c_locale();
++
++ _M_data->_M_date_format = "%m/%d/%y";
++ _M_data->_M_date_era_format = "%m/%d/%y";
++ _M_data->_M_time_format = "%H:%M:%S";
++ _M_data->_M_time_era_format = "%H:%M:%S";
++ _M_data->_M_date_time_format = "";
++ _M_data->_M_date_time_era_format = "";
++ _M_data->_M_am = "AM";
++ _M_data->_M_pm = "PM";
++ _M_data->_M_am_pm_format = "";
++
++ // Day names, starting with "C"'s Sunday.
++ _M_data->_M_day1 = "Sunday";
++ _M_data->_M_day2 = "Monday";
++ _M_data->_M_day3 = "Tuesday";
++ _M_data->_M_day4 = "Wednesday";
++ _M_data->_M_day5 = "Thursday";
++ _M_data->_M_day6 = "Friday";
++ _M_data->_M_day7 = "Saturday";
++
++ // Abbreviated day names, starting with "C"'s Sun.
++ _M_data->_M_aday1 = "Sun";
++ _M_data->_M_aday2 = "Mon";
++ _M_data->_M_aday3 = "Tue";
++ _M_data->_M_aday4 = "Wed";
++ _M_data->_M_aday5 = "Thu";
++ _M_data->_M_aday6 = "Fri";
++ _M_data->_M_aday7 = "Sat";
++
++ // Month names, starting with "C"'s January.
++ _M_data->_M_month01 = "January";
++ _M_data->_M_month02 = "February";
++ _M_data->_M_month03 = "March";
++ _M_data->_M_month04 = "April";
++ _M_data->_M_month05 = "May";
++ _M_data->_M_month06 = "June";
++ _M_data->_M_month07 = "July";
++ _M_data->_M_month08 = "August";
++ _M_data->_M_month09 = "September";
++ _M_data->_M_month10 = "October";
++ _M_data->_M_month11 = "November";
++ _M_data->_M_month12 = "December";
++
++ // Abbreviated month names, starting with "C"'s Jan.
++ _M_data->_M_amonth01 = "Jan";
++ _M_data->_M_amonth02 = "Feb";
++ _M_data->_M_amonth03 = "Mar";
++ _M_data->_M_amonth04 = "Apr";
++ _M_data->_M_amonth05 = "May";
++ _M_data->_M_amonth06 = "Jun";
++ _M_data->_M_amonth07 = "Jul";
++ _M_data->_M_amonth08 = "Aug";
++ _M_data->_M_amonth09 = "Sep";
++ _M_data->_M_amonth10 = "Oct";
++ _M_data->_M_amonth11 = "Nov";
++ _M_data->_M_amonth12 = "Dec";
++ }
++ else
++ {
++ _M_c_locale_timepunct = _S_clone_c_locale(__cloc);
++
++ _M_data->_M_date_format = __nl_langinfo_l(D_FMT, __cloc);
++ _M_data->_M_date_era_format = __nl_langinfo_l(ERA_D_FMT, __cloc);
++ _M_data->_M_time_format = __nl_langinfo_l(T_FMT, __cloc);
++ _M_data->_M_time_era_format = __nl_langinfo_l(ERA_T_FMT, __cloc);
++ _M_data->_M_date_time_format = __nl_langinfo_l(D_T_FMT, __cloc);
++ _M_data->_M_date_time_era_format = __nl_langinfo_l(ERA_D_T_FMT, __cloc);
++ _M_data->_M_am = __nl_langinfo_l(AM_STR, __cloc);
++ _M_data->_M_pm = __nl_langinfo_l(PM_STR, __cloc);
++ _M_data->_M_am_pm_format = __nl_langinfo_l(T_FMT_AMPM, __cloc);
++
++ // Day names, starting with "C"'s Sunday.
++ _M_data->_M_day1 = __nl_langinfo_l(DAY_1, __cloc);
++ _M_data->_M_day2 = __nl_langinfo_l(DAY_2, __cloc);
++ _M_data->_M_day3 = __nl_langinfo_l(DAY_3, __cloc);
++ _M_data->_M_day4 = __nl_langinfo_l(DAY_4, __cloc);
++ _M_data->_M_day5 = __nl_langinfo_l(DAY_5, __cloc);
++ _M_data->_M_day6 = __nl_langinfo_l(DAY_6, __cloc);
++ _M_data->_M_day7 = __nl_langinfo_l(DAY_7, __cloc);
++
++ // Abbreviated day names, starting with "C"'s Sun.
++ _M_data->_M_aday1 = __nl_langinfo_l(ABDAY_1, __cloc);
++ _M_data->_M_aday2 = __nl_langinfo_l(ABDAY_2, __cloc);
++ _M_data->_M_aday3 = __nl_langinfo_l(ABDAY_3, __cloc);
++ _M_data->_M_aday4 = __nl_langinfo_l(ABDAY_4, __cloc);
++ _M_data->_M_aday5 = __nl_langinfo_l(ABDAY_5, __cloc);
++ _M_data->_M_aday6 = __nl_langinfo_l(ABDAY_6, __cloc);
++ _M_data->_M_aday7 = __nl_langinfo_l(ABDAY_7, __cloc);
++
++ // Month names, starting with "C"'s January.
++ _M_data->_M_month01 = __nl_langinfo_l(MON_1, __cloc);
++ _M_data->_M_month02 = __nl_langinfo_l(MON_2, __cloc);
++ _M_data->_M_month03 = __nl_langinfo_l(MON_3, __cloc);
++ _M_data->_M_month04 = __nl_langinfo_l(MON_4, __cloc);
++ _M_data->_M_month05 = __nl_langinfo_l(MON_5, __cloc);
++ _M_data->_M_month06 = __nl_langinfo_l(MON_6, __cloc);
++ _M_data->_M_month07 = __nl_langinfo_l(MON_7, __cloc);
++ _M_data->_M_month08 = __nl_langinfo_l(MON_8, __cloc);
++ _M_data->_M_month09 = __nl_langinfo_l(MON_9, __cloc);
++ _M_data->_M_month10 = __nl_langinfo_l(MON_10, __cloc);
++ _M_data->_M_month11 = __nl_langinfo_l(MON_11, __cloc);
++ _M_data->_M_month12 = __nl_langinfo_l(MON_12, __cloc);
++
++ // Abbreviated month names, starting with "C"'s Jan.
++ _M_data->_M_amonth01 = __nl_langinfo_l(ABMON_1, __cloc);
++ _M_data->_M_amonth02 = __nl_langinfo_l(ABMON_2, __cloc);
++ _M_data->_M_amonth03 = __nl_langinfo_l(ABMON_3, __cloc);
++ _M_data->_M_amonth04 = __nl_langinfo_l(ABMON_4, __cloc);
++ _M_data->_M_amonth05 = __nl_langinfo_l(ABMON_5, __cloc);
++ _M_data->_M_amonth06 = __nl_langinfo_l(ABMON_6, __cloc);
++ _M_data->_M_amonth07 = __nl_langinfo_l(ABMON_7, __cloc);
++ _M_data->_M_amonth08 = __nl_langinfo_l(ABMON_8, __cloc);
++ _M_data->_M_amonth09 = __nl_langinfo_l(ABMON_9, __cloc);
++ _M_data->_M_amonth10 = __nl_langinfo_l(ABMON_10, __cloc);
++ _M_data->_M_amonth11 = __nl_langinfo_l(ABMON_11, __cloc);
++ _M_data->_M_amonth12 = __nl_langinfo_l(ABMON_12, __cloc);
++ }
++ }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ template<>
++ void
++ __timepunct<wchar_t>::
++ _M_put(wchar_t* __s, size_t __maxlen, const wchar_t* __format,
++ const tm* __tm) const
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __wcsftime_l(__s, __maxlen, __format, __tm, _M_c_locale_timepunct);
++ const size_t __len = __wcsftime_l(__s, __maxlen, __format, __tm,
++ _M_c_locale_timepunct);
++#else
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, _M_name_timepunct);
++ const size_t __len = wcsftime(__s, __maxlen, __format, __tm);
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ // Make sure __s is null terminated.
++ if (__len == 0)
++ __s[0] = L'\0';
++ }
++
++ template<>
++ void
++ __timepunct<wchar_t>::_M_initialize_timepunct(__c_locale __cloc)
++ {
++ if (!_M_data)
++ _M_data = new __timepunct_cache<wchar_t>;
++
++#warning wide time stuff
++// if (!__cloc)
++ {
++ // "C" locale
++ _M_c_locale_timepunct = _S_get_c_locale();
++
++ _M_data->_M_date_format = L"%m/%d/%y";
++ _M_data->_M_date_era_format = L"%m/%d/%y";
++ _M_data->_M_time_format = L"%H:%M:%S";
++ _M_data->_M_time_era_format = L"%H:%M:%S";
++ _M_data->_M_date_time_format = L"";
++ _M_data->_M_date_time_era_format = L"";
++ _M_data->_M_am = L"AM";
++ _M_data->_M_pm = L"PM";
++ _M_data->_M_am_pm_format = L"";
++
++ // Day names, starting with "C"'s Sunday.
++ _M_data->_M_day1 = L"Sunday";
++ _M_data->_M_day2 = L"Monday";
++ _M_data->_M_day3 = L"Tuesday";
++ _M_data->_M_day4 = L"Wednesday";
++ _M_data->_M_day5 = L"Thursday";
++ _M_data->_M_day6 = L"Friday";
++ _M_data->_M_day7 = L"Saturday";
++
++ // Abbreviated day names, starting with "C"'s Sun.
++ _M_data->_M_aday1 = L"Sun";
++ _M_data->_M_aday2 = L"Mon";
++ _M_data->_M_aday3 = L"Tue";
++ _M_data->_M_aday4 = L"Wed";
++ _M_data->_M_aday5 = L"Thu";
++ _M_data->_M_aday6 = L"Fri";
++ _M_data->_M_aday7 = L"Sat";
++
++ // Month names, starting with "C"'s January.
++ _M_data->_M_month01 = L"January";
++ _M_data->_M_month02 = L"February";
++ _M_data->_M_month03 = L"March";
++ _M_data->_M_month04 = L"April";
++ _M_data->_M_month05 = L"May";
++ _M_data->_M_month06 = L"June";
++ _M_data->_M_month07 = L"July";
++ _M_data->_M_month08 = L"August";
++ _M_data->_M_month09 = L"September";
++ _M_data->_M_month10 = L"October";
++ _M_data->_M_month11 = L"November";
++ _M_data->_M_month12 = L"December";
++
++ // Abbreviated month names, starting with "C"'s Jan.
++ _M_data->_M_amonth01 = L"Jan";
++ _M_data->_M_amonth02 = L"Feb";
++ _M_data->_M_amonth03 = L"Mar";
++ _M_data->_M_amonth04 = L"Apr";
++ _M_data->_M_amonth05 = L"May";
++ _M_data->_M_amonth06 = L"Jun";
++ _M_data->_M_amonth07 = L"Jul";
++ _M_data->_M_amonth08 = L"Aug";
++ _M_data->_M_amonth09 = L"Sep";
++ _M_data->_M_amonth10 = L"Oct";
++ _M_data->_M_amonth11 = L"Nov";
++ _M_data->_M_amonth12 = L"Dec";
++ }
++#if 0
++ else
++ {
++ _M_c_locale_timepunct = _S_clone_c_locale(__cloc);
++
++ _M_data->_M_date_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WD_FMT, __cloc));
++ _M_data->_M_date_era_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WERA_D_FMT, __cloc));
++ _M_data->_M_time_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WT_FMT, __cloc));
++ _M_data->_M_time_era_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WERA_T_FMT, __cloc));
++ _M_data->_M_date_time_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WD_T_FMT, __cloc));
++ _M_data->_M_date_time_era_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WERA_D_T_FMT, __cloc));
++ _M_data->_M_am = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WAM_STR, __cloc));
++ _M_data->_M_pm = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WPM_STR, __cloc));
++ _M_data->_M_am_pm_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WT_FMT_AMPM, __cloc));
++
++ // Day names, starting with "C"'s Sunday.
++ _M_data->_M_day1 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_1, __cloc));
++ _M_data->_M_day2 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_2, __cloc));
++ _M_data->_M_day3 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_3, __cloc));
++ _M_data->_M_day4 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_4, __cloc));
++ _M_data->_M_day5 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_5, __cloc));
++ _M_data->_M_day6 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_6, __cloc));
++ _M_data->_M_day7 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_7, __cloc));
++
++ // Abbreviated day names, starting with "C"'s Sun.
++ _M_data->_M_aday1 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_1, __cloc));
++ _M_data->_M_aday2 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_2, __cloc));
++ _M_data->_M_aday3 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_3, __cloc));
++ _M_data->_M_aday4 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_4, __cloc));
++ _M_data->_M_aday5 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_5, __cloc));
++ _M_data->_M_aday6 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_6, __cloc));
++ _M_data->_M_aday7 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_7, __cloc));
++
++ // Month names, starting with "C"'s January.
++ _M_data->_M_month01 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_1, __cloc));
++ _M_data->_M_month02 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_2, __cloc));
++ _M_data->_M_month03 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_3, __cloc));
++ _M_data->_M_month04 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_4, __cloc));
++ _M_data->_M_month05 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_5, __cloc));
++ _M_data->_M_month06 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_6, __cloc));
++ _M_data->_M_month07 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_7, __cloc));
++ _M_data->_M_month08 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_8, __cloc));
++ _M_data->_M_month09 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_9, __cloc));
++ _M_data->_M_month10 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_10, __cloc));
++ _M_data->_M_month11 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_11, __cloc));
++ _M_data->_M_month12 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_12, __cloc));
++
++ // Abbreviated month names, starting with "C"'s Jan.
++ _M_data->_M_amonth01 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_1, __cloc));
++ _M_data->_M_amonth02 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_2, __cloc));
++ _M_data->_M_amonth03 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_3, __cloc));
++ _M_data->_M_amonth04 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_4, __cloc));
++ _M_data->_M_amonth05 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_5, __cloc));
++ _M_data->_M_amonth06 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_6, __cloc));
++ _M_data->_M_amonth07 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_7, __cloc));
++ _M_data->_M_amonth08 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_8, __cloc));
++ _M_data->_M_amonth09 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_9, __cloc));
++ _M_data->_M_amonth10 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_10, __cloc));
++ _M_data->_M_amonth11 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_11, __cloc));
++ _M_data->_M_amonth12 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_12, __cloc));
++ }
++#endif // 0
++ }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/time_members.h gcc-3.4.2/libstdc++-v3/config/locale/uclibc/time_members.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/time_members.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/time_members.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,68 @@
++// std::time_get, std::time_put implementation, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.5.1.2 - time_get functions
++// ISO C++ 14882: 22.2.5.3.2 - time_put functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++ template<typename _CharT>
++ __timepunct<_CharT>::__timepunct(size_t __refs)
++ : facet(__refs), _M_data(NULL), _M_c_locale_timepunct(NULL),
++ _M_name_timepunct(_S_get_c_name())
++ { _M_initialize_timepunct(); }
++
++ template<typename _CharT>
++ __timepunct<_CharT>::__timepunct(__cache_type* __cache, size_t __refs)
++ : facet(__refs), _M_data(__cache), _M_c_locale_timepunct(NULL),
++ _M_name_timepunct(_S_get_c_name())
++ { _M_initialize_timepunct(); }
++
++ template<typename _CharT>
++ __timepunct<_CharT>::__timepunct(__c_locale __cloc, const char* __s,
++ size_t __refs)
++ : facet(__refs), _M_data(NULL), _M_c_locale_timepunct(NULL),
++ _M_name_timepunct(__s)
++ {
++ char* __tmp = new char[std::strlen(__s) + 1];
++ std::strcpy(__tmp, __s);
++ _M_name_timepunct = __tmp;
++ _M_initialize_timepunct(__cloc);
++ }
++
++ template<typename _CharT>
++ __timepunct<_CharT>::~__timepunct()
++ {
++ if (_M_name_timepunct != _S_get_c_name())
++ delete [] _M_name_timepunct;
++ delete _M_data;
++ _S_destroy_c_locale(_M_c_locale_timepunct);
++ }
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_base.h gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_base.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_base.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_base.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,58 @@
++// Locale support -*- C++ -*-
++
++// Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003
++// Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.1 Locales
++//
++
++// Information as gleaned from /usr/include/ctype.h
++
++ struct ctype_base
++ {
++ // Note: In uClibc, the following two types depend on configuration.
++
++ // Non-standard typedefs.
++ typedef const __ctype_touplow_t* __to_type;
++
++ // NB: Offsets into ctype<char>::_M_table force a particular size
++ // on the mask type. Because of this, we don't use an enum.
++ typedef __ctype_mask_t mask;
++ static const mask upper = _ISupper;
++ static const mask lower = _ISlower;
++ static const mask alpha = _ISalpha;
++ static const mask digit = _ISdigit;
++ static const mask xdigit = _ISxdigit;
++ static const mask space = _ISspace;
++ static const mask print = _ISprint;
++ static const mask graph = _ISalpha | _ISdigit | _ISpunct;
++ static const mask cntrl = _IScntrl;
++ static const mask punct = _ISpunct;
++ static const mask alnum = _ISalpha | _ISdigit;
++ };
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_inline.h gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_inline.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_inline.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_inline.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,69 @@
++// Locale support -*- C++ -*-
++
++// Copyright (C) 2000, 2002 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.1 Locales
++//
++
++// ctype bits to be inlined go here. Non-inlinable (ie virtual do_*)
++// functions go in ctype.cc
++
++ bool
++ ctype<char>::
++ is(mask __m, char __c) const
++ { return _M_table[static_cast<unsigned char>(__c)] & __m; }
++
++ const char*
++ ctype<char>::
++ is(const char* __low, const char* __high, mask* __vec) const
++ {
++ while (__low < __high)
++ *__vec++ = _M_table[static_cast<unsigned char>(*__low++)];
++ return __high;
++ }
++
++ const char*
++ ctype<char>::
++ scan_is(mask __m, const char* __low, const char* __high) const
++ {
++ while (__low < __high
++ && !(_M_table[static_cast<unsigned char>(*__low)] & __m))
++ ++__low;
++ return __low;
++ }
++
++ const char*
++ ctype<char>::
++ scan_not(mask __m, const char* __low, const char* __high) const
++ {
++ while (__low < __high
++ && (_M_table[static_cast<unsigned char>(*__low)] & __m) != 0)
++ ++__low;
++ return __low;
++ }
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_noninline.h gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_noninline.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_noninline.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_noninline.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,92 @@
++// Locale support -*- C++ -*-
++
++// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2004
++// Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.1 Locales
++//
++
++// Information as gleaned from /usr/include/ctype.h
++
++ const ctype_base::mask*
++ ctype<char>::classic_table() throw()
++ { return __C_ctype_b; }
++
++ ctype<char>::ctype(__c_locale, const mask* __table, bool __del,
++ size_t __refs)
++ : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()),
++ _M_del(__table != 0 && __del), _M_widen_ok(0), _M_narrow_ok(0)
++ {
++ _M_toupper = __C_ctype_toupper;
++ _M_tolower = __C_ctype_tolower;
++ _M_table = __table ? __table : __C_ctype_b;
++ memset(_M_widen, 0, sizeof(_M_widen));
++ memset(_M_narrow, 0, sizeof(_M_narrow));
++ }
++
++ ctype<char>::ctype(const mask* __table, bool __del, size_t __refs)
++ : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()),
++ _M_del(__table != 0 && __del), _M_widen_ok(0), _M_narrow_ok(0)
++ {
++ _M_toupper = __C_ctype_toupper;
++ _M_tolower = __C_ctype_tolower;
++ _M_table = __table ? __table : __C_ctype_b;
++ memset(_M_widen, 0, sizeof(_M_widen));
++ memset(_M_narrow, 0, sizeof(_M_narrow));
++ }
++
++ char
++ ctype<char>::do_toupper(char __c) const
++ { return _M_toupper[static_cast<unsigned char>(__c)]; }
++
++ const char*
++ ctype<char>::do_toupper(char* __low, const char* __high) const
++ {
++ while (__low < __high)
++ {
++ *__low = _M_toupper[static_cast<unsigned char>(*__low)];
++ ++__low;
++ }
++ return __high;
++ }
++
++ char
++ ctype<char>::do_tolower(char __c) const
++ { return _M_tolower[static_cast<unsigned char>(__c)]; }
++
++ const char*
++ ctype<char>::do_tolower(char* __low, const char* __high) const
++ {
++ while (__low < __high)
++ {
++ *__low = _M_tolower[static_cast<unsigned char>(*__low)];
++ ++__low;
++ }
++ return __high;
++ }
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/os_defines.h gcc-3.4.2/libstdc++-v3/config/os/uclibc/os_defines.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/os_defines.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/os/uclibc/os_defines.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,44 @@
++// Specific definitions for GNU/Linux -*- C++ -*-
++
++// Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++#ifndef _GLIBCXX_OS_DEFINES
++#define _GLIBCXX_OS_DEFINES 1
++
++// System-specific #define, typedefs, corrections, etc, go here. This
++// file will come before all others.
++
++// This keeps isanum, et al from being propagated as macros.
++#define __NO_CTYPE 1
++
++#include <features.h>
++
++// We must not see the optimized string functions GNU libc defines.
++#define __NO_STRING_INLINES
++
++#endif
+diff -urN gcc-3.4.2-dist/libstdc++-v3/configure gcc-3.4.2/libstdc++-v3/configure
+--- gcc-3.4.2-dist/libstdc++-v3/configure 2004-08-13 15:44:04.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/configure 2004-09-10 10:47:40.000000000 -0500
+@@ -3878,6 +3878,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+@@ -5545,6 +5550,9 @@
+ # Default to "generic".
+ if test $enable_clocale_flag = auto; then
+ case x${target_os} in
++ xlinux-uclibc*)
++ enable_clocale_flag=uclibc
++ ;;
+ xlinux* | xgnu* | xkfreebsd*-gnu | xknetbsd*-gnu)
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -5759,6 +5767,77 @@
+ CTIME_CC=config/locale/generic/time_members.cc
+ CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+ ;;
++ uclibc)
++ echo "$as_me:$LINENO: result: uclibc" >&5
++echo "${ECHO_T}uclibc" >&6
++
++ # Declare intention to use gettext, and add support for specific
++ # languages.
++ # For some reason, ALL_LINGUAS has to be before AM-GNU-GETTEXT
++ ALL_LINGUAS="de fr"
++
++ # Don't call AM-GNU-GETTEXT here. Instead, assume glibc.
++ # Extract the first word of "msgfmt", so it can be a program name with args.
++set dummy msgfmt; 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_check_msgfmt+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ if test -n "$check_msgfmt"; then
++ ac_cv_prog_check_msgfmt="$check_msgfmt" # 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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ ac_cv_prog_check_msgfmt="yes"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
++ fi
++done
++done
++
++ test -z "$ac_cv_prog_check_msgfmt" && ac_cv_prog_check_msgfmt="no"
++fi
++fi
++check_msgfmt=$ac_cv_prog_check_msgfmt
++if test -n "$check_msgfmt"; then
++ echo "$as_me:$LINENO: result: $check_msgfmt" >&5
++echo "${ECHO_T}$check_msgfmt" >&6
++else
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
++fi
++
++ if test x"$check_msgfmt" = x"yes" && test x"$enable_nls" = x"yes"; then
++ USE_NLS=yes
++ fi
++ # Export the build objects.
++ for ling in $ALL_LINGUAS; do \
++ glibcxx_MOFILES="$glibcxx_MOFILES $ling.mo"; \
++ glibcxx_POFILES="$glibcxx_POFILES $ling.po"; \
++ done
++
++
++
++ CLOCALE_H=config/locale/uclibc/c_locale.h
++ CLOCALE_CC=config/locale/uclibc/c_locale.cc
++ CCODECVT_H=config/locale/ieee_1003.1-2001/codecvt_specializations.h
++ CCODECVT_CC=config/locale/uclibc/codecvt_members.cc
++ CCOLLATE_CC=config/locale/uclibc/collate_members.cc
++ CCTYPE_CC=config/locale/uclibc/ctype_members.cc
++ CMESSAGES_H=config/locale/uclibc/messages_members.h
++ CMESSAGES_CC=config/locale/uclibc/messages_members.cc
++ CMONEY_CC=config/locale/uclibc/monetary_members.cc
++ CNUMERIC_CC=config/locale/uclibc/numeric_members.cc
++ CTIME_H=config/locale/uclibc/time_members.h
++ CTIME_CC=config/locale/uclibc/time_members.cc
++ CLOCALE_INTERNAL_H=config/locale/uclibc/c++locale_internal.h
++ ;;
+ esac
+
+ # This is where the testsuite looks for locale catalogs, using the
+diff -urN gcc-3.4.2-dist/libstdc++-v3/configure.host gcc-3.4.2/libstdc++-v3/configure.host
+--- gcc-3.4.2-dist/libstdc++-v3/configure.host 2004-08-27 14:52:30.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/configure.host 2004-09-10 10:47:40.000000000 -0500
+@@ -217,6 +217,12 @@
+ ;;
+ esac
+
++# Override for uClibc since linux-uclibc gets mishandled above.
++case "${host_os}" in
++ *-uclibc*)
++ os_include_dir="os/uclibc"
++ ;;
++esac
+
+ # Set any OS-dependent and CPU-dependent bits.
+ # THIS TABLE IS SORTED. KEEP IT THAT WAY.
+diff -urN gcc-3.4.2-dist/libstdc++-v3/crossconfig.m4 gcc-3.4.2/libstdc++-v3/crossconfig.m4
+--- gcc-3.4.2-dist/libstdc++-v3/crossconfig.m4 2004-07-06 20:23:49.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/crossconfig.m4 2004-09-10 10:47:40.000000000 -0500
+@@ -138,6 +138,99 @@
+ ;;
+ esac
+ ;;
++ *-uclibc*)
++# Temporary hack until we implement the float versions of the libm funcs
++ AC_CHECK_HEADERS([nan.h ieeefp.h endian.h sys/isa_defs.h \
++ machine/endian.h machine/param.h sys/machine.h sys/types.h \
++ fp.h float.h endian.h inttypes.h locale.h float.h stdint.h])
++ SECTION_FLAGS='-ffunction-sections -fdata-sections'
++ AC_SUBST(SECTION_FLAGS)
++ GLIBCXX_CHECK_LINKER_FEATURES
++ GLIBCXX_CHECK_COMPLEX_MATH_SUPPORT
++ GLIBCXX_CHECK_WCHAR_T_SUPPORT
++
++ # For LFS.
++ AC_DEFINE(HAVE_INT64_T)
++ case "$target" in
++ *-uclinux*)
++ # Don't enable LFS with uClinux
++ ;;
++ *)
++ AC_DEFINE(_GLIBCXX_USE_LFS)
++ esac
++
++ # For showmanyc_helper().
++ AC_CHECK_HEADERS(sys/ioctl.h sys/filio.h)
++ GLIBCXX_CHECK_POLL
++ GLIBCXX_CHECK_S_ISREG_OR_S_IFREG
++
++ # For xsputn_2().
++ AC_CHECK_HEADERS(sys/uio.h)
++ GLIBCXX_CHECK_WRITEV
++
++# AC_DEFINE(HAVE_ACOSF)
++# AC_DEFINE(HAVE_ASINF)
++# AC_DEFINE(HAVE_ATANF)
++# AC_DEFINE(HAVE_ATAN2F)
++ AC_DEFINE(HAVE_CEILF)
++ AC_DEFINE(HAVE_COPYSIGN)
++# AC_DEFINE(HAVE_COPYSIGNF)
++# AC_DEFINE(HAVE_COSF)
++# AC_DEFINE(HAVE_COSHF)
++# AC_DEFINE(HAVE_EXPF)
++# AC_DEFINE(HAVE_FABSF)
++ AC_DEFINE(HAVE_FINITE)
++ AC_DEFINE(HAVE_FINITEF)
++ AC_DEFINE(HAVE_FLOORF)
++# AC_DEFINE(HAVE_FMODF)
++# AC_DEFINE(HAVE_FREXPF)
++ AC_DEFINE(HAVE_HYPOT)
++# AC_DEFINE(HAVE_HYPOTF)
++ AC_DEFINE(HAVE_ISINF)
++ AC_DEFINE(HAVE_ISINFF)
++ AC_DEFINE(HAVE_ISNAN)
++ AC_DEFINE(HAVE_ISNANF)
++# AC_DEFINE(HAVE_LOGF)
++# AC_DEFINE(HAVE_LOG10F)
++# AC_DEFINE(HAVE_MODFF)
++# AC_DEFINE(HAVE_SINF)
++# AC_DEFINE(HAVE_SINHF)
++# AC_DEFINE(HAVE_SINCOS)
++# AC_DEFINE(HAVE_SINCOSF)
++ AC_DEFINE(HAVE_SQRTF)
++# AC_DEFINE(HAVE_TANF)
++# AC_DEFINE(HAVE_TANHF)
++ if test x"long_double_math_on_this_cpu" = x"yes"; then
++ AC_MSG_ERROR([long_double_math_on_this_cpu is yes!])
++# AC_DEFINE(HAVE_ACOSL)
++# AC_DEFINE(HAVE_ASINL)
++# AC_DEFINE(HAVE_ATANL)
++# AC_DEFINE(HAVE_ATAN2L)
++# AC_DEFINE(HAVE_CEILL)
++# AC_DEFINE(HAVE_COPYSIGNL)
++# AC_DEFINE(HAVE_COSL)
++# AC_DEFINE(HAVE_COSHL)
++# AC_DEFINE(HAVE_EXPL)
++# AC_DEFINE(HAVE_FABSL)
++# AC_DEFINE(HAVE_FINITEL)
++# AC_DEFINE(HAVE_FLOORL)
++# AC_DEFINE(HAVE_FMODL)
++# AC_DEFINE(HAVE_FREXPL)
++# AC_DEFINE(HAVE_HYPOTL)
++# AC_DEFINE(HAVE_ISINFL)
++# AC_DEFINE(HAVE_ISNANL)
++# AC_DEFINE(HAVE_LOGL)
++# AC_DEFINE(HAVE_LOG10L)
++# AC_DEFINE(HAVE_MODFL)
++# AC_DEFINE(HAVE_POWL)
++# AC_DEFINE(HAVE_SINL)
++# AC_DEFINE(HAVE_SINHL)
++# AC_DEFINE(HAVE_SINCOSL)
++# AC_DEFINE(HAVE_SQRTL)
++# AC_DEFINE(HAVE_TANL)
++# AC_DEFINE(HAVE_TANHL)
++ fi
++ ;;
+ *-linux* | *-uclinux* | *-gnu* | *-kfreebsd*-gnu | *-knetbsd*-gnu)
+ AC_CHECK_HEADERS([nan.h ieeefp.h endian.h sys/isa_defs.h \
+ machine/endian.h machine/param.h sys/machine.h sys/types.h \
+@@ -152,7 +245,7 @@
+ AC_DEFINE(HAVE_INT64_T)
+ case "$target" in
+ *-uclinux*)
+- # Don't enable LFS with uClibc
++ # Don't enable LFS with uClinux
+ ;;
+ *)
+ AC_DEFINE(_GLIBCXX_USE_LFS)
+diff -urN gcc-3.4.2-dist/libstdc++-v3/include/c_compatibility/wchar.h gcc-3.4.2/libstdc++-v3/include/c_compatibility/wchar.h
+--- gcc-3.4.2-dist/libstdc++-v3/include/c_compatibility/wchar.h 2003-12-08 21:51:45.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/include/c_compatibility/wchar.h 2004-09-10 10:47:40.000000000 -0500
+@@ -101,7 +101,9 @@
+ using std::wmemcpy;
+ using std::wmemmove;
+ using std::wmemset;
++#if _GLIBCXX_HAVE_WCSFTIME
+ using std::wcsftime;
++#endif
+
+ #if _GLIBCXX_USE_C99
+ using std::wcstold;
+diff -urN gcc-3.4.2-dist/libstdc++-v3/include/c_std/std_cwchar.h gcc-3.4.2/libstdc++-v3/include/c_std/std_cwchar.h
+--- gcc-3.4.2-dist/libstdc++-v3/include/c_std/std_cwchar.h 2004-07-20 03:52:12.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/include/c_std/std_cwchar.h 2004-09-10 10:47:40.000000000 -0500
+@@ -179,7 +179,9 @@
+ using ::wcscoll;
+ using ::wcscpy;
+ using ::wcscspn;
++#if _GLIBCXX_HAVE_WCSFTIME
+ using ::wcsftime;
++#endif
+ using ::wcslen;
+ using ::wcsncat;
+ using ::wcsncmp;
diff --git a/toolchain/gcc/patches/3.4.4/300-libstdc++-pic.patch b/toolchain/gcc/patches/3.4.4/300-libstdc++-pic.patch
new file mode 100644
index 0000000000..c030ba6205
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.4/300-libstdc++-pic.patch
@@ -0,0 +1,47 @@
+# DP: Build and install libstdc++_pic.a library.
+
+--- gcc/libstdc++-v3/src/Makefile.am~ 2003-02-28 09:21:05.000000000 +0100
++++ gcc/libstdc++-v3/src/Makefile.am 2003-02-28 09:28:50.000000000 +0100
+@@ -224,6 +224,10 @@
+ @OPT_LDFLAGS@ @SECTION_LDFLAGS@ $(AM_CXXFLAGS) $(LDFLAGS) -o $@
+
+
++install-exec-local:
++ $(AR) cru libstdc++_pic.a .libs/*.o $(top_builddir)/libsupc++/*.o
++ $(INSTALL_DATA) libstdc++_pic.a $(DESTDIR)$(toolexeclibdir)
++
+ # Added bits to build debug library.
+ if GLIBCPP_BUILD_DEBUG
+ all-local: build_debug
+
+--- gcc/libstdc++-v3/src/Makefile.in~ 2004-02-21 09:55:48.000000000 +0100
++++ gcc/libstdc++-v3/src/Makefile.in 2004-02-21 09:59:34.000000000 +0100
+@@ -585,7 +585,7 @@
+
+ install-data-am: install-data-local
+
+-install-exec-am: install-toolexeclibLTLIBRARIES
++install-exec-am: install-toolexeclibLTLIBRARIES install-exec-local
+
+ install-info: install-info-am
+
+@@ -618,6 +618,7 @@
+ distclean-tags distdir dvi dvi-am info info-am install \
+ install-am install-data install-data-am install-data-local \
+ install-exec install-exec-am install-info install-info-am \
++ install-exec-local \
+ install-man install-strip install-toolexeclibLTLIBRARIES \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+@@ -707,6 +708,11 @@
+ install_debug:
+ (cd ${debugdir} && $(MAKE) \
+ toolexeclibdir=$(glibcxx_toolexeclibdir)/debug install)
++
++install-exec-local:
++ $(AR) cru libstdc++_pic.a .libs/*.o $(top_builddir)/libsupc++/*.o
++ $(INSTALL_DATA) libstdc++_pic.a $(DESTDIR)$(toolexeclibdir)
++
+ # 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/toolchain/gcc/patches/3.4.4/601-gcc34-arm-ldm.patch b/toolchain/gcc/patches/3.4.4/601-gcc34-arm-ldm.patch
new file mode 100644
index 0000000000..142052fdf0
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.4/601-gcc34-arm-ldm.patch
@@ -0,0 +1,119 @@
+--- gcc-3.4.0/gcc/config/arm/arm.c.arm-ldm 2004-02-27 09:51:05.000000000 -0500
++++ gcc-3.4.0/gcc/config/arm/arm.c 2004-04-24 18:16:25.000000000 -0400
+@@ -8520,6 +8520,26 @@
+ return_used_this_function = 0;
+ }
+
++/* Return the number (counting from 0) of
++ the least significant set bit in MASK. */
++
++#ifdef __GNUC__
++inline
++#endif
++static int
++number_of_first_bit_set (mask)
++ int mask;
++{
++ int bit;
++
++ for (bit = 0;
++ (mask & (1 << bit)) == 0;
++ ++bit)
++ continue;
++
++ return bit;
++}
++
+ const char *
+ arm_output_epilogue (rtx sibling)
+ {
+@@ -8753,27 +8773,47 @@
+ saved_regs_mask |= (1 << PC_REGNUM);
+ }
+
+- /* Load the registers off the stack. If we only have one register
+- to load use the LDR instruction - it is faster. */
+- if (saved_regs_mask == (1 << LR_REGNUM))
+- {
+- /* The exception handler ignores the LR, so we do
+- not really need to load it off the stack. */
+- if (eh_ofs)
+- asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
+- else
+- asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM);
+- }
+- else if (saved_regs_mask)
++ if (saved_regs_mask)
+ {
+- if (saved_regs_mask & (1 << SP_REGNUM))
+- /* Note - write back to the stack register is not enabled
+- (ie "ldmfd sp!..."). We know that the stack pointer is
+- in the list of registers and if we add writeback the
+- instruction becomes UNPREDICTABLE. */
+- print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
++ /* Load the registers off the stack. If we only have one register
++ to load use the LDR instruction - it is faster. */
++ if (bit_count (saved_regs_mask) == 1)
++ {
++ int reg = number_of_first_bit_set (saved_regs_mask);
++
++ switch (reg)
++ {
++ case SP_REGNUM:
++ /* Mustn't use base writeback when loading SP. */
++ asm_fprintf (f, "\tldr\t%r, [%r]\n", SP_REGNUM, SP_REGNUM);
++ break;
++
++ case LR_REGNUM:
++ if (eh_ofs)
++ {
++ /* The exception handler ignores the LR, so we do
++ not really need to load it off the stack. */
++ asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
++ break;
++ }
++ /* else fall through */
++
++ default:
++ asm_fprintf (f, "\tldr\t%r, [%r], #4\n", reg, SP_REGNUM);
++ break;
++ }
++ }
+ else
+- print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
++ {
++ if (saved_regs_mask & (1 << SP_REGNUM))
++ /* Note - write back to the stack register is not enabled
++ (ie "ldmfd sp!..."). We know that the stack pointer is
++ in the list of registers and if we add writeback the
++ instruction becomes UNPREDICTABLE. */
++ print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
++ else
++ print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
++ }
+ }
+
+ if (current_function_pretend_args_size)
+@@ -11401,22 +11441,6 @@
+ }
+ }
+
+-/* Return the number (counting from 0) of
+- the least significant set bit in MASK. */
+-
+-inline static int
+-number_of_first_bit_set (int mask)
+-{
+- int bit;
+-
+- for (bit = 0;
+- (mask & (1 << bit)) == 0;
+- ++bit)
+- continue;
+-
+- return bit;
+-}
+-
+ /* Generate code to return from a thumb function.
+ If 'reg_containing_return_addr' is -1, then the return address is
+ actually on the stack, at the stack pointer. */
diff --git a/toolchain/gcc/patches/3.4.4/602-sdk-libstdc++-includes.patch b/toolchain/gcc/patches/3.4.4/602-sdk-libstdc++-includes.patch
new file mode 100644
index 0000000000..4377c2143b
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.4/602-sdk-libstdc++-includes.patch
@@ -0,0 +1,22 @@
+--- gcc-3.4.1/libstdc++-v3/libmath/Makefile.am~ 2003-08-27 22:29:42.000000000 +0100
++++ gcc-3.4.1/libstdc++-v3/libmath/Makefile.am 2004-07-22 16:41:45.152130128 +0100
+@@ -32,7 +32,7 @@
+
+ libmath_la_SOURCES = stubs.c
+
+-AM_CPPFLAGS = $(CANADIAN_INCLUDES)
++AM_CPPFLAGS = $(CANADIAN_INCLUDES) -I$(toplevel_srcdir)/include
+
+ # Only compiling "C" sources in this directory.
+ LIBTOOL = @LIBTOOL@ --tag CC
+--- gcc-3.4.1/libstdc++-v3/fragment.am.old 2004-07-22 18:24:58.024083656 +0100
++++ gcc-3.4.1/libstdc++-v3/fragment.am 2004-07-22 18:24:59.019932264 +0100
+@@ -18,7 +18,7 @@
+ $(WARN_FLAGS) $(WERROR) -fdiagnostics-show-location=once
+
+ # -I/-D flags to pass when compiling.
+-AM_CPPFLAGS = $(GLIBCXX_INCLUDES)
++AM_CPPFLAGS = $(GLIBCXX_INCLUDES) -I$(toplevel_srcdir)/include
+
+
+
diff --git a/toolchain/gcc/patches/3.4.4/700-pr15068-fix.patch b/toolchain/gcc/patches/3.4.4/700-pr15068-fix.patch
new file mode 100644
index 0000000000..2977765c5f
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.4/700-pr15068-fix.patch
@@ -0,0 +1,44 @@
+See http://gcc.gnu.org/PR15068
+
+Fixes error
+
+../sysdeps/generic/s_fmax.c: In function `__fmax':
+../sysdeps/generic/s_fmax.c:28: internal compiler error: in elim_reg_cond, at flow.c:3257
+Please submit a full bug report,
+with preprocessed source if appropriate.
+See <URL:http://gcc.gnu.org/bugs.html> for instructions.
+make[2]: *** [/home/dank/wk/crosstool-0.28-rc35/build/arm-unknown-linux-gnu/gcc-3.4.1-glibc-20040822/build-glibc/math/s_fmax.o] Error 1
+make[2]: Leaving directory `/home/dank/wk/crosstool-0.28-rc35/build/arm-unknown-linux-gnu/gcc-3.4.1-glibc-20040822/glibc-20040822/math'
+make[1]: *** [math/others] Error 2
+make[1]: Leaving directory `/home/dank/wk/crosstool-0.28-rc35/build/arm-unknown-linux-gnu/gcc-3.4.1-glibc-20040822/glibc-20040822'
+make: *** [all] Error 2
+
+[ rediffed against gcc-3.4.1, with elbow grease, ending up with same thing as
+http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/flow.c.diff?cvsroot=gcc&only_with_tag=csl-arm-branch&r1=1.563.4.2&r2=1.563.4.3 ]
+
+--- gcc-3.4.1/gcc/flow.c.old 2004-02-27 19:39:19.000000000 -0800
++++ gcc-3.4.1/gcc/flow.c 2004-08-26 07:29:46.000000000 -0700
+@@ -1878,6 +1878,7 @@
+ rtx set_src = SET_SRC (pc_set (BB_END (bb)));
+ rtx cond_true = XEXP (set_src, 0);
+ rtx reg = XEXP (cond_true, 0);
++ enum rtx_code inv_cond;
+
+ if (GET_CODE (reg) == SUBREG)
+ reg = SUBREG_REG (reg);
+@@ -1886,11 +1887,13 @@
+ in the form of a comparison of a register against zero.
+ If the condition is more complex than that, then it is safe
+ not to record any information. */
+- if (GET_CODE (reg) == REG
++ inv_cond = reversed_comparison_code (cond_true, BB_END (bb));
++ if (inv_cond != UNKNOWN
++ && GET_CODE (reg) == REG
+ && XEXP (cond_true, 1) == const0_rtx)
+ {
+ rtx cond_false
+- = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond_true)),
++ = gen_rtx_fmt_ee (inv_cond,
+ GET_MODE (cond_true), XEXP (cond_true, 0),
+ XEXP (cond_true, 1));
+ if (GET_CODE (XEXP (set_src, 1)) == PC)
diff --git a/toolchain/gcc/patches/3.4.4/800-arm-bigendian.patch b/toolchain/gcc/patches/3.4.4/800-arm-bigendian.patch
new file mode 100644
index 0000000000..0bae8f474c
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.4/800-arm-bigendian.patch
@@ -0,0 +1,70 @@
+By Lennert Buytenhek <buytenh@wantstofly.org>
+Adds support for arm*b-linux* big-endian ARM targets
+
+See http://gcc.gnu.org/PR16350
+
+diff -urN gcc-3.4.1-dist/gcc/config/arm/linux-elf.h gcc-3.4.1/gcc/config/arm/linux-elf.h
+--- gcc-3.4.1-dist/gcc/config/arm/linux-elf.h 2004-08-16 16:01:50.000000000 -0500
++++ gcc-3.4.1/gcc/config/arm/linux-elf.h 2004-08-16 15:43:40.000000000 -0500
+@@ -30,17 +30,34 @@
+ /* Do not assume anything about header files. */
+ #define NO_IMPLICIT_EXTERN_C
+
++/*
++ * 'config.gcc' defines TARGET_BIG_ENDIAN_DEFAULT as 1 for arm*b-*
++ * (big endian) configurations.
++ */
++#if TARGET_BIG_ENDIAN_DEFAULT
++#define TARGET_ENDIAN_DEFAULT ARM_FLAG_BIG_END
++#define TARGET_ENDIAN_OPTION "mbig-endian"
++#define TARGET_LINKER_EMULATION "armelfb_linux"
++#else
++#define TARGET_ENDIAN_DEFAULT 0
++#define TARGET_ENDIAN_OPTION "mlittle-endian"
++#define TARGET_LINKER_EMULATION "armelf_linux"
++#endif
++
+ /* Default is to use APCS-32 mode. */
+ #undef TARGET_DEFAULT
+-#define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_MMU_TRAPS)
++#define TARGET_DEFAULT \
++ ( ARM_FLAG_APCS_32 | \
++ ARM_FLAG_MMU_TRAPS | \
++ TARGET_ENDIAN_DEFAULT )
+
+ #define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6
+
+-#define SUBTARGET_EXTRA_LINK_SPEC " -m armelf_linux -p"
++#define SUBTARGET_EXTRA_LINK_SPEC " -m " TARGET_LINKER_EMULATION " -p"
+
+ #undef MULTILIB_DEFAULTS
+ #define MULTILIB_DEFAULTS \
+- { "marm", "mlittle-endian", "mhard-float", "mapcs-32", "mno-thumb-interwork" }
++ { "marm", TARGET_ENDIAN_OPTION, "mhard-float", "mapcs-32", "mno-thumb-interwork" }
+
+ #define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
+
+@@ -101,7 +118,7 @@
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2} \
+ -X \
+- %{mbig-endian:-EB}" \
++ %{mbig-endian:-EB} %{mlittle-endian:-EL}" \
+ SUBTARGET_EXTRA_LINK_SPEC
+ #endif
+
+diff -urN gcc-3.4.1-dist/gcc/config.gcc gcc-3.4.1/gcc/config.gcc
+--- gcc-3.4.1-dist/gcc/config.gcc 2004-08-16 16:01:50.000000000 -0500
++++ gcc-3.4.1/gcc/config.gcc 2004-08-16 16:01:25.000000000 -0500
+@@ -672,6 +672,11 @@
+ ;;
+ arm*-*-linux*) # ARM GNU/Linux with ELF
+ tm_file="dbxelf.h elfos.h linux.h arm/elf.h arm/linux-gas.h arm/linux-elf.h arm/aout.h arm/arm.h"
++ case $target in
++ arm*b-*)
++ tm_defines="TARGET_BIG_ENDIAN_DEFAULT=1 $tm_defines"
++ ;;
++ esac
+ tmake_file="t-slibgcc-elf-ver t-linux arm/t-linux"
+ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
+ gnu_ld=yes
diff --git a/toolchain/gcc/patches/3.4.4/810-arm-bigendian-uclibc.patch b/toolchain/gcc/patches/3.4.4/810-arm-bigendian-uclibc.patch
new file mode 100644
index 0000000000..a4d87e2317
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.4/810-arm-bigendian-uclibc.patch
@@ -0,0 +1,27 @@
+diff -urN gcc-3.4.1-dist/gcc/config/arm/linux-elf.h gcc-3.4.1/gcc/config/arm/linux-elf.h
+--- gcc-3.4.1-dist/gcc/config/arm/linux-elf.h 2004-08-16 16:08:18.000000000 -0500
++++ gcc-3.4.1/gcc/config/arm/linux-elf.h 2004-08-16 16:06:24.000000000 -0500
+@@ -107,7 +107,7 @@
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0} \
+ -X \
+- %{mbig-endian:-EB}" \
++ %{mbig-endian:-EB} %{mlittle-endian:-EL}" \
+ SUBTARGET_EXTRA_LINK_SPEC
+ #else
+ #define LINK_SPEC "%{h*} %{version:-v} \
+diff -urN gcc-3.4.1-dist/gcc/config.gcc gcc-3.4.1/gcc/config.gcc
+--- gcc-3.4.1-dist/gcc/config.gcc 2004-08-16 16:08:18.000000000 -0500
++++ gcc-3.4.1/gcc/config.gcc 2004-08-16 16:03:25.000000000 -0500
+@@ -666,6 +666,11 @@
+ ;;
+ arm*-*-linux-uclibc*) # ARM GNU/Linux with ELF - uClibc
+ tm_file="dbxelf.h elfos.h linux.h arm/elf.h arm/linux-gas.h arm/linux-elf.h arm/aout.h arm/arm.h"
++ case $target in
++ arm*b-*)
++ tm_defines="TARGET_BIG_ENDIAN_DEFAULT=1 $tm_defines"
++ ;;
++ esac
+ tmake_file="t-slibgcc-elf-ver t-linux-uclibc arm/t-linux"
+ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
+ gnu_ld=yes
diff --git a/toolchain/gcc/patches/3.4.4/830-gcc-bug-num-22167.patch b/toolchain/gcc/patches/3.4.4/830-gcc-bug-num-22167.patch
new file mode 100644
index 0000000000..c7419af90a
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.4/830-gcc-bug-num-22167.patch
@@ -0,0 +1,16 @@
+Index: gcc/gcse.c
+===================================================================
+RCS file: /cvs/gcc/gcc/gcc/gcse.c,v
+retrieving revision 1.288.2.9
+diff -u -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.288.2.9 gcse.c
+--- gcc/gcc/gcse.c 30 Oct 2004 18:02:53 -0000 1.288.2.9
++++ gcc/gcc/gcse.c 14 Jul 2005 13:19:57 -0000
+@@ -6445,7 +6445,7 @@ hoist_code (void)
+ insn_inserted_p = 0;
+
+ /* These tests should be the same as the tests above. */
+- if (TEST_BIT (hoist_vbeout[bb->index], i))
++ if (TEST_BIT (hoist_exprs[bb->index], i))
+ {
+ /* We've found a potentially hoistable expression, now
+ we look at every block BB dominates to see if it
diff --git a/toolchain/gcc/patches/3.4.4/arm-softfloat.patch.conditional b/toolchain/gcc/patches/3.4.4/arm-softfloat.patch.conditional
new file mode 100644
index 0000000000..19d1b90dac
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.4/arm-softfloat.patch.conditional
@@ -0,0 +1,270 @@
+Note... modified my mjn3 to not conflict with the big endian arm patch.
+Warning!!! Only the linux target is aware of TARGET_ENDIAN_DEFAULT.
+Also changed
+ #define SUBTARGET_EXTRA_ASM_SPEC "\
+ %{!mcpu=*:-mcpu=xscale} \
+ %{mhard-float:-mfpu=fpa} \
+ %{!mhard-float: %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}}"
+to
+ #define SUBTARGET_EXTRA_ASM_SPEC "\
+ %{mhard-float:-mfpu=fpa} \
+ %{!mhard-float: %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}}"
+in gcc/config/arm/linux-elf.h.
+#
+# Submitted:
+#
+# Dimitry Andric <dimitry@andric.com>, 2004-05-01
+#
+# Description:
+#
+# Nicholas Pitre released this patch for gcc soft-float support here:
+# http://lists.arm.linux.org.uk/pipermail/linux-arm/2003-October/006436.html
+#
+# This version has been adapted to work with gcc 3.4.0.
+#
+# The original patch doesn't distinguish between softfpa and softvfp modes
+# in the way Nicholas Pitre probably meant. His description is:
+#
+# "Default is to use APCS-32 mode with soft-vfp. The old Linux default for
+# floats can be achieved with -mhard-float or with the configure
+# --with-float=hard option. If -msoft-float or --with-float=soft is used then
+# software float support will be used just like the default but with the legacy
+# big endian word ordering for double float representation instead."
+#
+# Which means the following:
+#
+# * If you compile without -mhard-float or -msoft-float, you should get
+# software floating point, using the VFP format. The produced object file
+# should have these flags in its header:
+#
+# private flags = 600: [APCS-32] [VFP float format] [software FP]
+#
+# * If you compile with -mhard-float, you should get hardware floating point,
+# which always uses the FPA format. Object file header flags should be:
+#
+# private flags = 0: [APCS-32] [FPA float format]
+#
+# * If you compile with -msoft-float, you should get software floating point,
+# using the FPA format. This is done for compatibility reasons with many
+# existing distributions. Object file header flags should be:
+#
+# private flags = 200: [APCS-32] [FPA float format] [software FP]
+#
+# The original patch from Nicholas Pitre contained the following constructs:
+#
+# #define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mcpu=xscale} \
+# %{mhard-float:-mfpu=fpa} \
+# %{!mhard-float: %{msoft-float:-mfpu=softfpa;:-mfpu=softvfp}}"
+#
+# However, gcc doesn't accept this ";:" notation, used in the 3rd line. This
+# is probably the reason Robert Schwebel modified it to:
+#
+# #define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mcpu=xscale} \
+# %{mhard-float:-mfpu=fpa} \
+# %{!mhard-float: %{msoft-float:-mfpu=softfpa -mfpu=softvfp}}"
+#
+# But this causes the following behaviour:
+#
+# * If you compile without -mhard-float or -msoft-float, the compiler generates
+# software floating point instructions, but *nothing* is passed to the
+# assembler, which results in an object file which has flags:
+#
+# private flags = 0: [APCS-32] [FPA float format]
+#
+# This is not correct!
+#
+# * If you compile with -mhard-float, the compiler generates hardware floating
+# point instructions, and passes "-mfpu=fpa" to the assembler, which results
+# in an object file which has the same flags as in the previous item, but now
+# those *are* correct.
+#
+# * If you compile with -msoft-float, the compiler generates software floating
+# point instructions, and passes "-mfpu=softfpa -mfpu=softvfp" (in that
+# order) to the assembler, which results in an object file with flags:
+#
+# private flags = 600: [APCS-32] [VFP float format] [software FP]
+#
+# This is not correct, because the last "-mfpu=" option on the assembler
+# command line determines the actual FPU convention used (which should be FPA
+# in this case).
+#
+# Therefore, I modified this patch to get the desired behaviour. Every
+# instance of the notation:
+#
+# %{msoft-float:-mfpu=softfpa -mfpu=softvfp}
+#
+# was changed to:
+#
+# %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}
+#
+# I also did the following:
+#
+# * Modified all TARGET_DEFAULT macros I could find to include ARM_FLAG_VFP, to
+# be consistent with Nicholas' original patch.
+# * Removed any "msoft-float" or "mhard-float" from all MULTILIB_DEFAULTS
+# macros I could find. I think that if you compile without any options, you
+# would like to get the defaults. :)
+# * Removed the extra -lfloat option from LIBGCC_SPEC, since it isn't needed
+# anymore. (The required functions are now in libgcc.)
+
+diff -urN gcc-3.4.1-old/gcc/config/arm/coff.h gcc-3.4.1/gcc/config/arm/coff.h
+--- gcc-3.4.1-old/gcc/config/arm/coff.h 2004-02-24 08:25:22.000000000 -0600
++++ gcc-3.4.1/gcc/config/arm/coff.h 2004-09-02 21:51:15.000000000 -0500
+@@ -31,11 +31,16 @@
+ #define TARGET_VERSION fputs (" (ARM/coff)", stderr)
+
+ #undef TARGET_DEFAULT
+-#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_32 | ARM_FLAG_APCS_FRAME | ARM_FLAG_MMU_TRAPS)
++#define TARGET_DEFAULT \
++ ( ARM_FLAG_SOFT_FLOAT \
++ | ARM_FLAG_VFP \
++ | ARM_FLAG_APCS_32 \
++ | ARM_FLAG_APCS_FRAME \
++ | ARM_FLAG_MMU_TRAPS )
+
+ #ifndef MULTILIB_DEFAULTS
+ #define MULTILIB_DEFAULTS \
+- { "marm", "mlittle-endian", "msoft-float", "mapcs-32", "mno-thumb-interwork" }
++ { "marm", "mlittle-endian", "mapcs-32", "mno-thumb-interwork" }
+ #endif
+
+ /* This is COFF, but prefer stabs. */
+diff -urN gcc-3.4.1-old/gcc/config/arm/elf.h gcc-3.4.1/gcc/config/arm/elf.h
+--- gcc-3.4.1-old/gcc/config/arm/elf.h 2004-02-24 08:25:22.000000000 -0600
++++ gcc-3.4.1/gcc/config/arm/elf.h 2004-09-02 21:51:15.000000000 -0500
+@@ -46,7 +46,9 @@
+
+ #ifndef SUBTARGET_ASM_FLOAT_SPEC
+ #define SUBTARGET_ASM_FLOAT_SPEC "\
+-%{mapcs-float:-mfloat} %{msoft-float:-mfpu=softfpa}"
++%{mapcs-float:-mfloat} \
++%{mhard-float:-mfpu=fpa} \
++%{!mhard-float: %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}}"
+ #endif
+
+ #ifndef ASM_SPEC
+@@ -106,12 +108,17 @@
+ #endif
+
+ #ifndef TARGET_DEFAULT
+-#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_32 | ARM_FLAG_APCS_FRAME | ARM_FLAG_MMU_TRAPS)
++#define TARGET_DEFAULT \
++ ( ARM_FLAG_SOFT_FLOAT \
++ | ARM_FLAG_VFP \
++ | ARM_FLAG_APCS_32 \
++ | ARM_FLAG_APCS_FRAME \
++ | ARM_FLAG_MMU_TRAPS )
+ #endif
+
+ #ifndef MULTILIB_DEFAULTS
+ #define MULTILIB_DEFAULTS \
+- { "marm", "mlittle-endian", "msoft-float", "mapcs-32", "mno-thumb-interwork", "fno-leading-underscore" }
++ { "marm", "mlittle-endian", "mapcs-32", "mno-thumb-interwork", "fno-leading-underscore" }
+ #endif
+
+ #define TARGET_ASM_FILE_START_APP_OFF true
+diff -urN gcc-3.4.1-old/gcc/config/arm/linux-elf.h gcc-3.4.1/gcc/config/arm/linux-elf.h
+--- gcc-3.4.1-old/gcc/config/arm/linux-elf.h 2004-09-02 21:50:52.000000000 -0500
++++ gcc-3.4.1/gcc/config/arm/linux-elf.h 2004-09-02 22:00:49.000000000 -0500
+@@ -44,12 +44,26 @@
+ #define TARGET_LINKER_EMULATION "armelf_linux"
+ #endif
+
+-/* Default is to use APCS-32 mode. */
++/*
++ * Default is to use APCS-32 mode with soft-vfp.
++ * The old Linux default for floats can be achieved with -mhard-float
++ * or with the configure --with-float=hard option.
++ * If -msoft-float or --with-float=soft is used then software float
++ * support will be used just like the default but with the legacy
++ * big endian word ordering for double float representation instead.
++ */
+ #undef TARGET_DEFAULT
+-#define TARGET_DEFAULT \
+- ( ARM_FLAG_APCS_32 | \
+- ARM_FLAG_MMU_TRAPS | \
+- TARGET_ENDIAN_DEFAULT )
++#define TARGET_DEFAULT \
++ ( ARM_FLAG_APCS_32 \
++ | ARM_FLAG_SOFT_FLOAT \
++ | TARGET_ENDIAN_DEFAULT \
++ | ARM_FLAG_VFP \
++ | ARM_FLAG_MMU_TRAPS )
++
++#undef SUBTARGET_EXTRA_ASM_SPEC
++#define SUBTARGET_EXTRA_ASM_SPEC "\
++%{mhard-float:-mfpu=fpa} \
++%{!mhard-float: %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}}"
+
+ #define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6
+
+@@ -57,7 +71,7 @@
+
+ #undef MULTILIB_DEFAULTS
+ #define MULTILIB_DEFAULTS \
+- { "marm", TARGET_ENDIAN_OPTION, "mhard-float", "mapcs-32", "mno-thumb-interwork" }
++ { "marm", TARGET_ENDIAN_OPTION, "mapcs-32", "mno-thumb-interwork" }
+
+ #define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
+
+@@ -72,7 +86,7 @@
+ %{shared:-lc} \
+ %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
+
+-#define LIBGCC_SPEC "%{msoft-float:-lfloat} -lgcc"
++#define LIBGCC_SPEC "-lgcc"
+
+ /* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add
+ the GNU/Linux magical crtbegin.o file (see crtstuff.c) which
+diff -urN gcc-3.4.1-old/gcc/config/arm/t-linux gcc-3.4.1/gcc/config/arm/t-linux
+--- gcc-3.4.1-old/gcc/config/arm/t-linux 2003-09-20 16:09:07.000000000 -0500
++++ gcc-3.4.1/gcc/config/arm/t-linux 2004-09-02 21:51:15.000000000 -0500
+@@ -4,7 +4,10 @@
+ LIBGCC2_DEBUG_CFLAGS = -g0
+
+ LIB1ASMSRC = arm/lib1funcs.asm
+-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx
++LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx \
++ _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \
++ _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
++ _fixsfsi _fixunssfsi
+
+ # MULTILIB_OPTIONS = mhard-float/msoft-float
+ # MULTILIB_DIRNAMES = hard-float soft-float
+diff -urN gcc-3.4.1-old/gcc/config/arm/unknown-elf.h gcc-3.4.1/gcc/config/arm/unknown-elf.h
+--- gcc-3.4.1-old/gcc/config/arm/unknown-elf.h 2004-02-24 08:25:22.000000000 -0600
++++ gcc-3.4.1/gcc/config/arm/unknown-elf.h 2004-09-02 21:51:15.000000000 -0500
+@@ -30,7 +30,12 @@
+
+ /* Default to using APCS-32 and software floating point. */
+ #ifndef TARGET_DEFAULT
+-#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_32 | ARM_FLAG_APCS_FRAME | ARM_FLAG_MMU_TRAPS)
++#define TARGET_DEFAULT \
++ ( ARM_FLAG_SOFT_FLOAT \
++ | ARM_FLAG_VFP \
++ | ARM_FLAG_APCS_32 \
++ | ARM_FLAG_APCS_FRAME \
++ | ARM_FLAG_MMU_TRAPS )
+ #endif
+
+ /* Now we define the strings used to build the spec file. */
+diff -urN gcc-3.4.1-old/gcc/config/arm/xscale-elf.h gcc-3.4.1/gcc/config/arm/xscale-elf.h
+--- gcc-3.4.1-old/gcc/config/arm/xscale-elf.h 2003-07-01 18:26:43.000000000 -0500
++++ gcc-3.4.1/gcc/config/arm/xscale-elf.h 2004-09-02 21:51:15.000000000 -0500
+@@ -49,11 +49,12 @@
+ endian, regardless of the endian-ness of the memory
+ system. */
+
+-#define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mcpu=xscale} \
+- %{mhard-float:-mfpu=fpa} \
+- %{!mhard-float: %{msoft-float:-mfpu=softfpa;:-mfpu=softvfp}}"
++#define SUBTARGET_EXTRA_ASM_SPEC "\
++%{!mcpu=*:-mcpu=xscale} \
++%{mhard-float:-mfpu=fpa} \
++%{!mhard-float: %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}}"
+
+ #ifndef MULTILIB_DEFAULTS
+ #define MULTILIB_DEFAULTS \
+- { "mlittle-endian", "mno-thumb-interwork", "marm", "msoft-float" }
++ { "mlittle-endian", "mno-thumb-interwork", "marm" }
+ #endif
diff --git a/toolchain/gcc/patches/3.4.5/100-uclibc-conf.patch b/toolchain/gcc/patches/3.4.5/100-uclibc-conf.patch
new file mode 100644
index 0000000000..6bc73a427a
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.5/100-uclibc-conf.patch
@@ -0,0 +1,462 @@
+--- gcc-3.4.1/gcc/config.gcc
++++ gcc-3.4.1/gcc/config.gcc
+@@ -2310,10 +2310,16 @@
+ *)
+ echo "*** Configuration ${target} not supported" 1>&2
+ exit 1
+ ;;
+ esac
++
++# Rather than hook into each target, just do it after all the linux
++# targets have been processed
++case ${target} in
++*-linux-uclibc*) tm_defines="${tm_defines} USE_UCLIBC"
++esac
+
+ # Support for --with-cpu and related options (and a few unrelated options,
+ # too).
+ case ${with_cpu} in
+ yes | no)
+--- gcc-3.4.4/gcc/config/alpha/linux-elf.h
++++ gcc-3.4.4/gcc/config/alpha/linux-elf.h
+@@ -27,7 +27,11 @@
+ #define SUBTARGET_EXTRA_SPECS \
+ { "elf_dynamic_linker", ELF_DYNAMIC_LINKER },
+
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#else
+ #define ELF_DYNAMIC_LINKER "/lib/ld-linux.so.2"
++#endif
+
+ #define LINK_SPEC "-m elf64alpha %{G*} %{relax:-relax} \
+ %{O*:-O3} %{!O*:-O1} \
+--- gcc-3.4.1-dist/gcc/config/arm/linux-elf.h 2004-01-31 00:18:11.000000000 -0600
++++ gcc-3.4.1/gcc/config/arm/linux-elf.h 2004-08-12 15:54:42.000000000 -0500
+@@ -80,14 +80,19 @@
+ #define ENDFILE_SPEC \
+ "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
+
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#else
++#define ELF_DYNAMIC_LINKER "/lib/ld-linux.so.2"
++#endif
+ #undef LINK_SPEC
+ #define LINK_SPEC "%{h*} %{version:-v} \
+ %{b} %{Wl,*:%*} \
+ %{static:-Bstatic} \
+ %{shared:-shared} \
+ %{symbolic:-Bsymbolic} \
+ %{rdynamic:-export-dynamic} \
+- %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2} \
++ %{!dynamic-linker:-dynamic-linker " ELF_DYNAMIC_LINKER "} \
+ -X \
+ %{mbig-endian:-EB}" \
+ SUBTARGET_EXTRA_LINK_SPEC
+--- gcc-3.4.1-dist/gcc/config/cris/linux.h 2003-11-28 21:08:09.000000000 -0600
++++ gcc-3.4.1/gcc/config/cris/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -79,6 +79,25 @@
+ #undef CRIS_DEFAULT_CPU_VERSION
+ #define CRIS_DEFAULT_CPU_VERSION CRIS_CPU_NG
+
++#ifdef USE_UCLIBC
++
++#undef CRIS_SUBTARGET_VERSION
++#define CRIS_SUBTARGET_VERSION " - cris-axis-linux-uclibc"
++
++#undef CRIS_LINK_SUBTARGET_SPEC
++#define CRIS_LINK_SUBTARGET_SPEC \
++ "-mcrislinux\
++ -rpath-link include/asm/../..%s\
++ %{shared} %{static}\
++ %{symbolic:-Bdynamic} %{shlib:-Bdynamic} %{static:-Bstatic}\
++ %{!shared: \
++ %{!static: \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}}} \
++ %{!r:%{O2|O3: --gc-sections}}"
++
++#else /* USE_UCLIBC */
++
+ #undef CRIS_SUBTARGET_VERSION
+ #define CRIS_SUBTARGET_VERSION " - cris-axis-linux-gnu"
+
+@@ -93,6 +112,8 @@
+ %{!shared:%{!static:%{rdynamic:-export-dynamic}}}\
+ %{!r:%{O2|O3: --gc-sections}}"
+
++#endif /* USE_UCLIBC */
++
+
+ /* Node: Run-time Target */
+
+--- gcc-3.4.1-dist/gcc/config/i386/linux.h 2003-11-28 21:08:10.000000000 -0600
++++ gcc-3.4.1/gcc/config/i386/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -110,22 +110,21 @@
+
+ #undef LINK_SPEC
+ #ifdef USE_GNULIBC_1
+-#define LINK_SPEC "-m elf_i386 %{shared:-shared} \
+- %{!shared: \
+- %{!ibcs: \
+- %{!static: \
+- %{rdynamic:-export-dynamic} \
+- %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \
+- %{static:-static}}}"
++#define ELF_DYNAMIC_LINKER "/lib/ld-linux.so.1"
++#else
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
+ #else
++#define ELF_DYNAMIC_LINKER "/lib/ld-linux.so.2"
++#endif
++#endif
+ #define LINK_SPEC "-m elf_i386 %{shared:-shared} \
+ %{!shared: \
+ %{!ibcs: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+- %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
++ %{!dynamic-linker:-dynamic-linker " ELF_DYNAMIC_LINKER "}} \
+ %{static:-static}}}"
+-#endif
+
+ /* A C statement (sans semicolon) to output to the stdio stream
+ FILE the assembler definition of uninitialized global DECL named
+--- gcc-3.4.4/gcc/config/i386/linux64.h
++++ gcc-3.4.4/gcc/config/i386/linux64.h
+@@ -54,14 +54,21 @@
+ When the -shared link option is used a final link is not being
+ done. */
+
++#ifdef USE_UCLIBC
++#define ELF32_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#define ELF64_DYNAMIC_LINKER "/lib/ld64-uClibc.so.0"
++#else
++#define ELF32_DYNAMIC_LINKER "/lib/ld-linux.so.2"
++#define ELF64_DYNAMIC_LINKER "/lib64/ld-linux-x86-64.so.2"
++#endif
+ #undef LINK_SPEC
+ #define LINK_SPEC "%{!m32:-m elf_x86_64} %{m32:-m elf_i386} \
+ %{shared:-shared} \
+ %{!shared: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+- %{m32:%{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
+- %{!m32:%{!dynamic-linker:-dynamic-linker /lib64/ld-linux-x86-64.so.2}}} \
++ %{m32:%{!dynamic-linker:-dynamic-linker " ELF32_DYNAMIC_LINKER "}} \
++ %{!m32:%{!dynamic-linker:-dynamic-linker " ELF64_DYNAMIC_LINKER "}}} \
+ %{static:-static}}"
+
+ #define MULTILIB_DEFAULTS { "m64" }
+--- gcc-3.4.4/gcc/config/ia64/linux.h
++++ gcc-3.4.4/gcc/config/ia64/linux.h
+@@ -37,13 +37,18 @@
+ /* Define this for shared library support because it isn't in the main
+ linux.h file. */
+
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#else
++#define ELF_DYNAMIC_LINKER "/lib/ld-linux-ia64.so.2"
++#endif
+ #undef LINK_SPEC
+ #define LINK_SPEC "\
+ %{shared:-shared} \
+ %{!shared: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+- %{!dynamic-linker:-dynamic-linker /lib/ld-linux-ia64.so.2}} \
++ %{!dynamic-linker:-dynamic-linker " ELF_DYNAMIC_LINKER "}} \
+ %{static:-static}}"
+
+
+--- gcc-3.4.4/gcc/config/m68k/linux.h
++++ gcc-3.4.4/gcc/config/m68k/linux.h
+@@ -131,12 +131,17 @@
+
+ /* If ELF is the default format, we should not use /lib/elf. */
+
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#else
++#define ELF_DYNAMIC_LINKER "/lib/ld.so.1"
++#endif
+ #undef LINK_SPEC
+ #define LINK_SPEC "-m m68kelf %{shared} \
+ %{!shared: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+- %{!dynamic-linker*:-dynamic-linker /lib/ld.so.1}} \
++ %{!dynamic-linker*:-dynamic-linker " ELF_DYNAMIC_LINKER "}} \
+ %{static}}"
+
+ /* For compatibility with linux/a.out */
+--- gcc-3.4.1-dist/gcc/config/mips/linux.h 2004-06-15 20:42:24.000000000 -0500
++++ gcc-3.4.1/gcc/config/mips/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -109,14 +109,19 @@
+
+ /* Borrowed from sparc/linux.h */
+ #undef LINK_SPEC
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#else
++#define ELF_DYNAMIC_LINKER "/lib/ld.so.1"
++#endif
+ #define LINK_SPEC \
+ "%(endian_spec) \
+ %{shared:-shared} \
+ %{!shared: \
+ %{!ibcs: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+- %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}} \
++ %{!dynamic-linker:-dynamic-linker " ELF_DYNAMIC_LINKER "}} \
+ %{static:-static}}}"
+
+ #undef SUBTARGET_ASM_SPEC
+--- gcc-3.4.4/gcc/config/pa/pa-linux.h
++++ gcc-3.4.4/gcc/config/pa/pa-linux.h
+@@ -77,13 +77,18 @@
+ /* Define this for shared library support because it isn't in the main
+ linux.h file. */
+
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#else
++#define ELF_DYNAMIC_LINKER "/lib/ld.so.1"
++#endif
+ #undef LINK_SPEC
+ #define LINK_SPEC "\
+ %{shared:-shared} \
+ %{!shared: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+- %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}} \
++ %{!dynamic-linker:-dynamic-linker " ELF_DYNAMIC_LINKER "}} \
+ %{static:-static}}"
+
+ /* glibc's profiling functions don't need gcc to allocate counters. */
+--- gcc-3.4.1-dist/gcc/config/rs6000/linux.h 2004-02-25 09:11:19.000000000 -0600
++++ gcc-3.4.1/gcc/config/rs6000/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -69,7 +69,11 @@
+ #define LINK_START_DEFAULT_SPEC "%(link_start_linux)"
+
+ #undef LINK_OS_DEFAULT_SPEC
++#ifdef USE_UCLIBC
++#define LINK_OS_DEFAULT_SPEC "%(link_os_linux_uclibc)"
++#else
+ #define LINK_OS_DEFAULT_SPEC "%(link_os_linux)"
++#endif
+
+ #define LINK_GCC_C_SEQUENCE_SPEC \
+ "%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}"
+--- gcc-3.4.1-dist/gcc/config/rs6000/sysv4.h 2004-06-10 01:39:50.000000000 -0500
++++ gcc-3.4.1/gcc/config/rs6000/sysv4.h 2004-08-12 15:54:43.000000000 -0500
+@@ -947,6 +947,7 @@
+ mcall-linux : %(link_os_linux) ; \
+ mcall-gnu : %(link_os_gnu) ; \
+ mcall-netbsd : %(link_os_netbsd) ; \
++ mcall-linux-uclibc : %(link_os_linux_uclibc); \
+ mcall-openbsd: %(link_os_openbsd) ; \
+ : %(link_os_default) }"
+
+@@ -1125,6 +1126,10 @@
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}}}"
+
++#define LINK_OS_LINUX_UCLIBC_SPEC "-m elf32ppclinux %{!shared: %{!static: \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}}}"
++
+ #if defined(HAVE_LD_EH_FRAME_HDR)
+ # define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
+ #endif
+@@ -1291,6 +1296,7 @@
+ { "link_os_sim", LINK_OS_SIM_SPEC }, \
+ { "link_os_freebsd", LINK_OS_FREEBSD_SPEC }, \
+ { "link_os_linux", LINK_OS_LINUX_SPEC }, \
++ { "link_os_linux_uclibc", LINK_OS_LINUX_UCLIBC_SPEC }, \
+ { "link_os_gnu", LINK_OS_GNU_SPEC }, \
+ { "link_os_netbsd", LINK_OS_NETBSD_SPEC }, \
+ { "link_os_openbsd", LINK_OS_OPENBSD_SPEC }, \
+--- gcc-3.4.4/gcc/config/s390/linux.h
++++ gcc-3.4.4/gcc/config/s390/linux.h
+@@ -77,6 +77,13 @@
+ #define MULTILIB_DEFAULTS { "m31" }
+ #endif
+
++#ifdef USE_UCLIBC
++#define ELF31_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#define ELF64_DYNAMIC_LINKER "/lib/ld64-uClibc.so.0"
++#else
++#define ELF31_DYNAMIC_LINKER "/lib/ld.so.1"
++#define ELF64_DYNAMIC_LINKER "/lib/ld64.so.1"
++#endif
+ #undef LINK_SPEC
+ #define LINK_SPEC \
+ "%{m31:-m elf_s390}%{m64:-m elf64_s390} \
+@@ -86,8 +93,8 @@
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker: \
+- %{m31:-dynamic-linker /lib/ld.so.1} \
+- %{m64:-dynamic-linker /lib/ld64.so.1}}}}"
++ %{m31:-dynamic-linker " ELF31_DYNAMIC_LINKER "} \
++ %{m64:-dynamic-linker " ELF64_DYNAMIC_LINKER "}}}}"
+
+
+ #define TARGET_ASM_FILE_END file_end_indicate_exec_stack
+--- gcc-3.4.1-dist/gcc/config/sh/linux.h 2004-01-11 20:29:13.000000000 -0600
++++ gcc-3.4.1/gcc/config/sh/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -73,11 +73,16 @@
+ #undef SUBTARGET_LINK_EMUL_SUFFIX
+ #define SUBTARGET_LINK_EMUL_SUFFIX "_linux"
+ #undef SUBTARGET_LINK_SPEC
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#else
++#define ELF_DYNAMIC_LINKER "/lib/ld-linux.so.2"
++#endif
+ #define SUBTARGET_LINK_SPEC \
+ "%{shared:-shared} \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+- %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
++ %{!dynamic-linker:-dynamic-linker " ELF_DYNAMIC_LINKER "}} \
+ %{static:-static}"
+
+ #undef LIB_SPEC
+--- gcc-3.4.4/gcc/config/sparc/linux.h
++++ gcc-3.4.4/gcc/config/sparc/linux.h
+@@ -162,13 +162,18 @@
+ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \
+ %{static:-static}}}"
+ #else
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#else
++#define ELF_DYNAMIC_LINKER "/lib/ld-linux.so.2"
++#endif
+ #define LINK_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \
+ %{!mno-relax:%{!r:-relax}} \
+ %{!shared: \
+ %{!ibcs: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+- %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
++ %{!dynamic-linker:-dynamic-linker " ELF_DYNAMIC_LINKER "}} \
+ %{static:-static}}}"
+ #endif
+
+--- gcc-3.4.4/gcc/config/sparc/linux64.h
++++ gcc-3.4.4/gcc/config/sparc/linux64.h
+@@ -167,12 +166,17 @@
+ { "link_arch_default", LINK_ARCH_DEFAULT_SPEC }, \
+ { "link_arch", LINK_ARCH_SPEC },
+
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#else
++#define ELF_DYNAMIC_LINKER "/lib/ld-linux.so.2"
++#endif
+ #define LINK_ARCH32_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \
+ %{!shared: \
+ %{!ibcs: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+- %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
++ %{!dynamic-linker:-dynamic-linker " ELF_DYNAMIC_LINKER "}} \
+ %{static:-static}}} \
+ "
+
+--- gcc-3.4.1-dist/libtool.m4 2004-05-18 04:08:37.000000000 -0500
++++ gcc-3.4.1/libtool.m4 2004-08-12 15:54:43.000000000 -0500
+@@ -689,6 +689,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ [lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$']
+--- gcc-3.4.1-dist/ltconfig 2004-03-05 15:05:41.000000000 -0600
++++ gcc-3.4.1/ltconfig 2004-08-12 15:55:48.000000000 -0500
+@@ -602,6 +602,7 @@
+
+ # Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+ case $host_os in
++linux-uclibc*) ;;
+ linux-gnu*) ;;
+ linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+ esac
+@@ -1262,6 +1263,24 @@
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
++linux-uclibc*)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
++ soname_spec='${libname}${release}.so$major'
++ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ # This implies no fast_install, which is unacceptable.
++ # Some rework will be needed to allow for fast_install
++ # before this can be enabled.
++ # Note: copied from linux-gnu, and may not be appropriate.
++ hardcode_into_libs=yes
++ # Assume using the uClibc dynamic linker.
++ dynamic_linker="uClibc ld.so"
++ ;;
++
+ netbsd*)
+ need_lib_prefix=no
+ need_version=no
+--- gcc-3.4.1-dist/boehm-gc/configure 2004-07-01 14:14:03.000000000 -0500
++++ gcc-3.4.1/boehm-gc/configure 2004-08-12 16:22:57.000000000 -0500
+@@ -1947,6 +1947,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+--- gcc-3.4.1-dist/boehm-gc/ltconfig 2002-11-20 09:59:06.000000000 -0600
++++ gcc-3.4.1/boehm-gc/ltconfig 2004-08-12 15:54:42.000000000 -0500
+@@ -1981,6 +1981,23 @@
+ fi
+ ;;
+
++linux-uclibc*)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
++ soname_spec='${libname}${release}.so$major'
++ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
++ file_magic_cmd=/usr/bin/file
++ file_magic_test_file=`echo /lib/libuClibc-*.so`
++
++ # Assume using the uClibc dynamic linker.
++ dynamic_linker="uClibc ld.so"
++ ;;
++
+ netbsd*)
+ version_type=sunos
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
diff --git a/toolchain/gcc/patches/3.4.5/200-uclibc-locale.patch b/toolchain/gcc/patches/3.4.5/200-uclibc-locale.patch
new file mode 100644
index 0000000000..a97f22b49a
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.5/200-uclibc-locale.patch
@@ -0,0 +1,3255 @@
+diff -urN gcc-3.4.2-dist/libstdc++-v3/acinclude.m4 gcc-3.4.2/libstdc++-v3/acinclude.m4
+--- gcc-3.4.2-dist/libstdc++-v3/acinclude.m4 2004-07-15 12:42:45.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/acinclude.m4 2004-09-10 10:47:40.000000000 -0500
+@@ -996,7 +996,7 @@
+ AC_MSG_CHECKING([for C locale to use])
+ GLIBCXX_ENABLE(clocale,auto,[@<:@=MODEL@:>@],
+ [use MODEL for target locale package],
+- [permit generic|gnu|ieee_1003.1-2001|yes|no|auto])
++ [permit generic|gnu|ieee_1003.1-2001|uclibc|yes|no|auto])
+
+ # If they didn't use this option switch, or if they specified --enable
+ # with no specific model, we'll have to look for one. If they
+@@ -1012,6 +1012,9 @@
+ # Default to "generic".
+ if test $enable_clocale_flag = auto; then
+ case x${target_os} in
++ x*-uclibc*)
++ enable_clocale_flag=uclibc
++ ;;
+ xlinux* | xgnu* | xkfreebsd*-gnu | xknetbsd*-gnu)
+ AC_EGREP_CPP([_GLIBCXX_ok], [
+ #include <features.h>
+@@ -1138,6 +1141,41 @@
+ CTIME_CC=config/locale/generic/time_members.cc
+ CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+ ;;
++ uclibc)
++ AC_MSG_RESULT(uclibc)
++
++ # Declare intention to use gettext, and add support for specific
++ # languages.
++ # For some reason, ALL_LINGUAS has to be before AM-GNU-GETTEXT
++ ALL_LINGUAS="de fr"
++
++ # Don't call AM-GNU-GETTEXT here. Instead, assume glibc.
++ AC_CHECK_PROG(check_msgfmt, msgfmt, yes, no)
++ if test x"$check_msgfmt" = x"yes" && test x"$enable_nls" = x"yes"; then
++ USE_NLS=yes
++ fi
++ # Export the build objects.
++ for ling in $ALL_LINGUAS; do \
++ glibcxx_MOFILES="$glibcxx_MOFILES $ling.mo"; \
++ glibcxx_POFILES="$glibcxx_POFILES $ling.po"; \
++ done
++ AC_SUBST(glibcxx_MOFILES)
++ AC_SUBST(glibcxx_POFILES)
++
++ CLOCALE_H=config/locale/uclibc/c_locale.h
++ CLOCALE_CC=config/locale/uclibc/c_locale.cc
++ CCODECVT_H=config/locale/ieee_1003.1-2001/codecvt_specializations.h
++ CCODECVT_CC=config/locale/uclibc/codecvt_members.cc
++ CCOLLATE_CC=config/locale/uclibc/collate_members.cc
++ CCTYPE_CC=config/locale/uclibc/ctype_members.cc
++ CMESSAGES_H=config/locale/uclibc/messages_members.h
++ CMESSAGES_CC=config/locale/uclibc/messages_members.cc
++ CMONEY_CC=config/locale/uclibc/monetary_members.cc
++ CNUMERIC_CC=config/locale/uclibc/numeric_members.cc
++ CTIME_H=config/locale/uclibc/time_members.h
++ CTIME_CC=config/locale/uclibc/time_members.cc
++ CLOCALE_INTERNAL_H=config/locale/uclibc/c++locale_internal.h
++ ;;
+ esac
+
+ # This is where the testsuite looks for locale catalogs, using the
+diff -urN gcc-3.4.2-dist/libstdc++-v3/aclocal.m4 gcc-3.4.2/libstdc++-v3/aclocal.m4
+--- gcc-3.4.2-dist/libstdc++-v3/aclocal.m4 2004-08-13 15:44:03.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/aclocal.m4 2004-09-10 10:47:40.000000000 -0500
+@@ -1025,6 +1025,9 @@
+ # Default to "generic".
+ if test $enable_clocale_flag = auto; then
+ case x${target_os} in
++ x*-uclibc*)
++ enable_clocale_flag=uclibc
++ ;;
+ xlinux* | xgnu* | xkfreebsd*-gnu | xknetbsd*-gnu)
+ AC_EGREP_CPP([_GLIBCXX_ok], [
+ #include <features.h>
+@@ -1151,6 +1154,41 @@
+ CTIME_CC=config/locale/generic/time_members.cc
+ CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+ ;;
++ uclibc)
++ AC_MSG_RESULT(uclibc)
++
++ # Declare intention to use gettext, and add support for specific
++ # languages.
++ # For some reason, ALL_LINGUAS has to be before AM-GNU-GETTEXT
++ ALL_LINGUAS="de fr"
++
++ # Don't call AM-GNU-GETTEXT here. Instead, assume glibc.
++ AC_CHECK_PROG(check_msgfmt, msgfmt, yes, no)
++ if test x"$check_msgfmt" = x"yes" && test x"$enable_nls" = x"yes"; then
++ USE_NLS=yes
++ fi
++ # Export the build objects.
++ for ling in $ALL_LINGUAS; do \
++ glibcxx_MOFILES="$glibcxx_MOFILES $ling.mo"; \
++ glibcxx_POFILES="$glibcxx_POFILES $ling.po"; \
++ done
++ AC_SUBST(glibcxx_MOFILES)
++ AC_SUBST(glibcxx_POFILES)
++
++ CLOCALE_H=config/locale/uclibc/c_locale.h
++ CLOCALE_CC=config/locale/uclibc/c_locale.cc
++ CCODECVT_H=config/locale/ieee_1003.1-2001/codecvt_specializations.h
++ CCODECVT_CC=config/locale/uclibc/codecvt_members.cc
++ CCOLLATE_CC=config/locale/uclibc/collate_members.cc
++ CCTYPE_CC=config/locale/uclibc/ctype_members.cc
++ CMESSAGES_H=config/locale/uclibc/messages_members.h
++ CMESSAGES_CC=config/locale/uclibc/messages_members.cc
++ CMONEY_CC=config/locale/uclibc/monetary_members.cc
++ CNUMERIC_CC=config/locale/uclibc/numeric_members.cc
++ CTIME_H=config/locale/uclibc/time_members.h
++ CTIME_CC=config/locale/uclibc/time_members.cc
++ CLOCALE_INTERNAL_H=config/locale/uclibc/c++locale_internal.h
++ ;;
+ esac
+
+ # This is where the testsuite looks for locale catalogs, using the
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c++locale_internal.h gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c++locale_internal.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c++locale_internal.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c++locale_internal.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,59 @@
++// Prototypes for GLIBC thread locale __-prefixed functions -*- C++ -*-
++
++// Copyright (C) 2002, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++// Written by Jakub Jelinek <jakub@redhat.com>
++
++#include <clocale>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning clean this up
++#endif
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++
++extern "C" __typeof(iswctype_l) __iswctype_l;
++extern "C" __typeof(nl_langinfo_l) __nl_langinfo_l;
++extern "C" __typeof(strcoll_l) __strcoll_l;
++extern "C" __typeof(strftime_l) __strftime_l;
++extern "C" __typeof(strtod_l) __strtod_l;
++extern "C" __typeof(strtof_l) __strtof_l;
++extern "C" __typeof(strtold_l) __strtold_l;
++extern "C" __typeof(strxfrm_l) __strxfrm_l;
++extern "C" __typeof(towlower_l) __towlower_l;
++extern "C" __typeof(towupper_l) __towupper_l;
++extern "C" __typeof(wcscoll_l) __wcscoll_l;
++extern "C" __typeof(wcsftime_l) __wcsftime_l;
++extern "C" __typeof(wcsxfrm_l) __wcsxfrm_l;
++extern "C" __typeof(wctype_l) __wctype_l;
++extern "C" __typeof(newlocale) __newlocale;
++extern "C" __typeof(freelocale) __freelocale;
++extern "C" __typeof(duplocale) __duplocale;
++extern "C" __typeof(uselocale) __uselocale;
++
++#endif // GLIBC 2.3 and later
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,160 @@
++// Wrapper for underlying C-language localization -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.8 Standard locale categories.
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <cerrno> // For errno
++#include <locale>
++#include <stdexcept>
++#include <langinfo.h>
++#include <bits/c++locale_internal.h>
++
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __strtol_l(S, E, B, L) strtol((S), (E), (B))
++#define __strtoul_l(S, E, B, L) strtoul((S), (E), (B))
++#define __strtoll_l(S, E, B, L) strtoll((S), (E), (B))
++#define __strtoull_l(S, E, B, L) strtoull((S), (E), (B))
++#define __strtof_l(S, E, L) strtof((S), (E))
++#define __strtod_l(S, E, L) strtod((S), (E))
++#define __strtold_l(S, E, L) strtold((S), (E))
++#warning should dummy __newlocale check for C|POSIX ?
++#define __newlocale(a, b, c) NULL
++#define __freelocale(a) ((void)0)
++#define __duplocale(a) __c_locale()
++#endif
++
++namespace std
++{
++ template<>
++ void
++ __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err,
++ const __c_locale& __cloc)
++ {
++ if (!(__err & ios_base::failbit))
++ {
++ char* __sanity;
++ errno = 0;
++ float __f = __strtof_l(__s, &__sanity, __cloc);
++ if (__sanity != __s && errno != ERANGE)
++ __v = __f;
++ else
++ __err |= ios_base::failbit;
++ }
++ }
++
++ template<>
++ void
++ __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err,
++ const __c_locale& __cloc)
++ {
++ if (!(__err & ios_base::failbit))
++ {
++ char* __sanity;
++ errno = 0;
++ double __d = __strtod_l(__s, &__sanity, __cloc);
++ if (__sanity != __s && errno != ERANGE)
++ __v = __d;
++ else
++ __err |= ios_base::failbit;
++ }
++ }
++
++ template<>
++ void
++ __convert_to_v(const char* __s, long double& __v, ios_base::iostate& __err,
++ const __c_locale& __cloc)
++ {
++ if (!(__err & ios_base::failbit))
++ {
++ char* __sanity;
++ errno = 0;
++ long double __ld = __strtold_l(__s, &__sanity, __cloc);
++ if (__sanity != __s && errno != ERANGE)
++ __v = __ld;
++ else
++ __err |= ios_base::failbit;
++ }
++ }
++
++ void
++ locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
++ __c_locale __old)
++ {
++ __cloc = __newlocale(1 << LC_ALL, __s, __old);
++#ifdef __UCLIBC_HAS_XLOCALE__
++ if (!__cloc)
++ {
++ // This named locale is not supported by the underlying OS.
++ __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
++ "name not valid"));
++ }
++#endif
++ }
++
++ void
++ locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
++ {
++ if (_S_get_c_locale() != __cloc)
++ __freelocale(__cloc);
++ }
++
++ __c_locale
++ locale::facet::_S_clone_c_locale(__c_locale& __cloc)
++ { return __duplocale(__cloc); }
++} // namespace std
++
++namespace __gnu_cxx
++{
++ const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
++ {
++ "LC_CTYPE",
++ "LC_NUMERIC",
++ "LC_TIME",
++ "LC_COLLATE",
++ "LC_MONETARY",
++ "LC_MESSAGES",
++#if _GLIBCXX_NUM_CATEGORIES != 0
++ "LC_PAPER",
++ "LC_NAME",
++ "LC_ADDRESS",
++ "LC_TELEPHONE",
++ "LC_MEASUREMENT",
++ "LC_IDENTIFICATION"
++#endif
++ };
++}
++
++namespace std
++{
++ const char* const* const locale::_S_categories = __gnu_cxx::category_names;
++} // namespace std
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.h gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.h 2004-09-10 10:48:08.000000000 -0500
+@@ -0,0 +1,115 @@
++// Wrapper for underlying C-language localization -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.8 Standard locale categories.
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#ifndef _C_LOCALE_H
++#define _C_LOCALE_H 1
++
++#pragma GCC system_header
++
++#include <cstring> // get std::strlen
++#include <cstdio> // get std::snprintf or std::sprintf
++#include <clocale>
++#include <langinfo.h> // For codecvt
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix this
++#endif
++#ifdef __UCLIBC_HAS_LOCALE__
++#include <iconv.h> // For codecvt using iconv, iconv_t
++#endif
++#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
++#include <libintl.h> // For messages
++#endif
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning what is _GLIBCXX_C_LOCALE_GNU for
++#endif
++#define _GLIBCXX_C_LOCALE_GNU 1
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix categories
++#endif
++// #define _GLIBCXX_NUM_CATEGORIES 6
++#define _GLIBCXX_NUM_CATEGORIES 0
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++namespace __gnu_cxx
++{
++ extern "C" __typeof(uselocale) __uselocale;
++}
++#endif
++
++namespace std
++{
++#ifdef __UCLIBC_HAS_XLOCALE__
++ typedef __locale_t __c_locale;
++#else
++ typedef int* __c_locale;
++#endif
++
++ // Convert numeric value of type _Tv to string and return length of
++ // string. If snprintf is available use it, otherwise fall back to
++ // the unsafe sprintf which, in general, can be dangerous and should
++ // be avoided.
++ template<typename _Tv>
++ int
++ __convert_from_v(char* __out, const int __size, const char* __fmt,
++#ifdef __UCLIBC_HAS_XLOCALE__
++ _Tv __v, const __c_locale& __cloc, int __prec)
++ {
++ __c_locale __old = __gnu_cxx::__uselocale(__cloc);
++#else
++ _Tv __v, const __c_locale&, int __prec)
++ {
++# ifdef __UCLIBC_HAS_LOCALE__
++ char* __old = std::setlocale(LC_ALL, NULL);
++ char* __sav = new char[std::strlen(__old) + 1];
++ std::strcpy(__sav, __old);
++ std::setlocale(LC_ALL, "C");
++# endif
++#endif
++
++ const int __ret = std::snprintf(__out, __size, __fmt, __prec, __v);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __gnu_cxx::__uselocale(__old);
++#elif defined __UCLIBC_HAS_LOCALE__
++ std::setlocale(LC_ALL, __sav);
++ delete [] __sav;
++#endif
++ return __ret;
++ }
++}
++
++#endif
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/codecvt_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/codecvt_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/codecvt_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/codecvt_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,306 @@
++// std::codecvt implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2002, 2003 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.1.5 - Template class codecvt
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <locale>
++#include <bits/c++locale_internal.h>
++
++namespace std
++{
++ // Specializations.
++#ifdef _GLIBCXX_USE_WCHAR_T
++ codecvt_base::result
++ codecvt<wchar_t, char, mbstate_t>::
++ do_out(state_type& __state, const intern_type* __from,
++ const intern_type* __from_end, const intern_type*& __from_next,
++ extern_type* __to, extern_type* __to_end,
++ extern_type*& __to_next) const
++ {
++ result __ret = ok;
++ state_type __tmp_state(__state);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++
++ // wcsnrtombs is *very* fast but stops if encounters NUL characters:
++ // in case we fall back to wcrtomb and then continue, in a loop.
++ // NB: wcsnrtombs is a GNU extension
++ for (__from_next = __from, __to_next = __to;
++ __from_next < __from_end && __to_next < __to_end
++ && __ret == ok;)
++ {
++ const intern_type* __from_chunk_end = wmemchr(__from_next, L'\0',
++ __from_end - __from_next);
++ if (!__from_chunk_end)
++ __from_chunk_end = __from_end;
++
++ __from = __from_next;
++ const size_t __conv = wcsnrtombs(__to_next, &__from_next,
++ __from_chunk_end - __from_next,
++ __to_end - __to_next, &__state);
++ if (__conv == static_cast<size_t>(-1))
++ {
++ // In case of error, in order to stop at the exact place we
++ // have to start again from the beginning with a series of
++ // wcrtomb.
++ for (; __from < __from_next; ++__from)
++ __to_next += wcrtomb(__to_next, *__from, &__tmp_state);
++ __state = __tmp_state;
++ __ret = error;
++ }
++ else if (__from_next && __from_next < __from_chunk_end)
++ {
++ __to_next += __conv;
++ __ret = partial;
++ }
++ else
++ {
++ __from_next = __from_chunk_end;
++ __to_next += __conv;
++ }
++
++ if (__from_next < __from_end && __ret == ok)
++ {
++ extern_type __buf[MB_LEN_MAX];
++ __tmp_state = __state;
++ const size_t __conv = wcrtomb(__buf, *__from_next, &__tmp_state);
++ if (__conv > static_cast<size_t>(__to_end - __to_next))
++ __ret = partial;
++ else
++ {
++ memcpy(__to_next, __buf, __conv);
++ __state = __tmp_state;
++ __to_next += __conv;
++ ++__from_next;
++ }
++ }
++ }
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++
++ return __ret;
++ }
++
++ codecvt_base::result
++ codecvt<wchar_t, char, mbstate_t>::
++ do_in(state_type& __state, const extern_type* __from,
++ const extern_type* __from_end, const extern_type*& __from_next,
++ intern_type* __to, intern_type* __to_end,
++ intern_type*& __to_next) const
++ {
++ result __ret = ok;
++ state_type __tmp_state(__state);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++
++ // mbsnrtowcs is *very* fast but stops if encounters NUL characters:
++ // in case we store a L'\0' and then continue, in a loop.
++ // NB: mbsnrtowcs is a GNU extension
++ for (__from_next = __from, __to_next = __to;
++ __from_next < __from_end && __to_next < __to_end
++ && __ret == ok;)
++ {
++ const extern_type* __from_chunk_end;
++ __from_chunk_end = static_cast<const extern_type*>(memchr(__from_next, '\0',
++ __from_end
++ - __from_next));
++ if (!__from_chunk_end)
++ __from_chunk_end = __from_end;
++
++ __from = __from_next;
++ size_t __conv = mbsnrtowcs(__to_next, &__from_next,
++ __from_chunk_end - __from_next,
++ __to_end - __to_next, &__state);
++ if (__conv == static_cast<size_t>(-1))
++ {
++ // In case of error, in order to stop at the exact place we
++ // have to start again from the beginning with a series of
++ // mbrtowc.
++ for (;; ++__to_next, __from += __conv)
++ {
++ __conv = mbrtowc(__to_next, __from, __from_end - __from,
++ &__tmp_state);
++ if (__conv == static_cast<size_t>(-1)
++ || __conv == static_cast<size_t>(-2))
++ break;
++ }
++ __from_next = __from;
++ __state = __tmp_state;
++ __ret = error;
++ }
++ else if (__from_next && __from_next < __from_chunk_end)
++ {
++ // It is unclear what to return in this case (see DR 382).
++ __to_next += __conv;
++ __ret = partial;
++ }
++ else
++ {
++ __from_next = __from_chunk_end;
++ __to_next += __conv;
++ }
++
++ if (__from_next < __from_end && __ret == ok)
++ {
++ if (__to_next < __to_end)
++ {
++ // XXX Probably wrong for stateful encodings
++ __tmp_state = __state;
++ ++__from_next;
++ *__to_next++ = L'\0';
++ }
++ else
++ __ret = partial;
++ }
++ }
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++
++ return __ret;
++ }
++
++ int
++ codecvt<wchar_t, char, mbstate_t>::
++ do_encoding() const throw()
++ {
++ // XXX This implementation assumes that the encoding is
++ // stateless and is either single-byte or variable-width.
++ int __ret = 0;
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++ if (MB_CUR_MAX == 1)
++ __ret = 1;
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ return __ret;
++ }
++
++ int
++ codecvt<wchar_t, char, mbstate_t>::
++ do_max_length() const throw()
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++ // XXX Probably wrong for stateful encodings.
++ int __ret = MB_CUR_MAX;
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ return __ret;
++ }
++
++ int
++ codecvt<wchar_t, char, mbstate_t>::
++ do_length(state_type& __state, const extern_type* __from,
++ const extern_type* __end, size_t __max) const
++ {
++ int __ret = 0;
++ state_type __tmp_state(__state);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++
++ // mbsnrtowcs is *very* fast but stops if encounters NUL characters:
++ // in case we advance past it and then continue, in a loop.
++ // NB: mbsnrtowcs is a GNU extension
++
++ // A dummy internal buffer is needed in order for mbsnrtocws to consider
++ // its fourth parameter (it wouldn't with NULL as first parameter).
++ wchar_t* __to = static_cast<wchar_t*>(__builtin_alloca(sizeof(wchar_t)
++ * __max));
++ while (__from < __end && __max)
++ {
++ const extern_type* __from_chunk_end;
++ __from_chunk_end = static_cast<const extern_type*>(memchr(__from, '\0',
++ __end
++ - __from));
++ if (!__from_chunk_end)
++ __from_chunk_end = __end;
++
++ const extern_type* __tmp_from = __from;
++ size_t __conv = mbsnrtowcs(__to, &__from,
++ __from_chunk_end - __from,
++ __max, &__state);
++ if (__conv == static_cast<size_t>(-1))
++ {
++ // In case of error, in order to stop at the exact place we
++ // have to start again from the beginning with a series of
++ // mbrtowc.
++ for (__from = __tmp_from;; __from += __conv)
++ {
++ __conv = mbrtowc(NULL, __from, __end - __from,
++ &__tmp_state);
++ if (__conv == static_cast<size_t>(-1)
++ || __conv == static_cast<size_t>(-2))
++ break;
++ }
++ __state = __tmp_state;
++ __ret += __from - __tmp_from;
++ break;
++ }
++ if (!__from)
++ __from = __from_chunk_end;
++
++ __ret += __from - __tmp_from;
++ __max -= __conv;
++
++ if (__from < __end && __max)
++ {
++ // XXX Probably wrong for stateful encodings
++ __tmp_state = __state;
++ ++__from;
++ ++__ret;
++ --__max;
++ }
++ }
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++
++ return __ret;
++ }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/collate_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/collate_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/collate_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/collate_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,80 @@
++// std::collate implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.4.1.2 collate virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <locale>
++#include <bits/c++locale_internal.h>
++
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __strcoll_l(S1, S2, L) strcoll((S1), (S2))
++#define __strxfrm_l(S1, S2, N, L) strxfrm((S1), (S2), (N))
++#define __wcscoll_l(S1, S2, L) wcscoll((S1), (S2))
++#define __wcsxfrm_l(S1, S2, N, L) wcsxfrm((S1), (S2), (N))
++#endif
++
++namespace std
++{
++ // These are basically extensions to char_traits, and perhaps should
++ // be put there instead of here.
++ template<>
++ int
++ collate<char>::_M_compare(const char* __one, const char* __two) const
++ {
++ int __cmp = __strcoll_l(__one, __two, _M_c_locale_collate);
++ return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0);
++ }
++
++ template<>
++ size_t
++ collate<char>::_M_transform(char* __to, const char* __from,
++ size_t __n) const
++ { return __strxfrm_l(__to, __from, __n, _M_c_locale_collate); }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ template<>
++ int
++ collate<wchar_t>::_M_compare(const wchar_t* __one,
++ const wchar_t* __two) const
++ {
++ int __cmp = __wcscoll_l(__one, __two, _M_c_locale_collate);
++ return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0);
++ }
++
++ template<>
++ size_t
++ collate<wchar_t>::_M_transform(wchar_t* __to, const wchar_t* __from,
++ size_t __n) const
++ { return __wcsxfrm_l(__to, __from, __n, _M_c_locale_collate); }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/ctype_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/ctype_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/ctype_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/ctype_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,300 @@
++// std::ctype implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.1.1.2 ctype virtual functions.
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#define _LIBC
++#include <locale>
++#undef _LIBC
++#include <bits/c++locale_internal.h>
++
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __wctype_l(S, L) wctype((S))
++#define __towupper_l(C, L) towupper((C))
++#define __towlower_l(C, L) towlower((C))
++#define __iswctype_l(C, M, L) iswctype((C), (M))
++#endif
++
++namespace std
++{
++ // NB: The other ctype<char> specializations are in src/locale.cc and
++ // various /config/os/* files.
++ template<>
++ ctype_byname<char>::ctype_byname(const char* __s, size_t __refs)
++ : ctype<char>(0, false, __refs)
++ {
++ if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
++ {
++ this->_S_destroy_c_locale(this->_M_c_locale_ctype);
++ this->_S_create_c_locale(this->_M_c_locale_ctype, __s);
++#ifdef __UCLIBC_HAS_XLOCALE__
++ this->_M_toupper = this->_M_c_locale_ctype->__ctype_toupper;
++ this->_M_tolower = this->_M_c_locale_ctype->__ctype_tolower;
++ this->_M_table = this->_M_c_locale_ctype->__ctype_b;
++#endif
++ }
++ }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ ctype<wchar_t>::__wmask_type
++ ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const
++ {
++ __wmask_type __ret;
++ switch (__m)
++ {
++ case space:
++ __ret = __wctype_l("space", _M_c_locale_ctype);
++ break;
++ case print:
++ __ret = __wctype_l("print", _M_c_locale_ctype);
++ break;
++ case cntrl:
++ __ret = __wctype_l("cntrl", _M_c_locale_ctype);
++ break;
++ case upper:
++ __ret = __wctype_l("upper", _M_c_locale_ctype);
++ break;
++ case lower:
++ __ret = __wctype_l("lower", _M_c_locale_ctype);
++ break;
++ case alpha:
++ __ret = __wctype_l("alpha", _M_c_locale_ctype);
++ break;
++ case digit:
++ __ret = __wctype_l("digit", _M_c_locale_ctype);
++ break;
++ case punct:
++ __ret = __wctype_l("punct", _M_c_locale_ctype);
++ break;
++ case xdigit:
++ __ret = __wctype_l("xdigit", _M_c_locale_ctype);
++ break;
++ case alnum:
++ __ret = __wctype_l("alnum", _M_c_locale_ctype);
++ break;
++ case graph:
++ __ret = __wctype_l("graph", _M_c_locale_ctype);
++ break;
++ default:
++ __ret = 0;
++ }
++ return __ret;
++ }
++
++ wchar_t
++ ctype<wchar_t>::do_toupper(wchar_t __c) const
++ { return __towupper_l(__c, _M_c_locale_ctype); }
++
++ const wchar_t*
++ ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const
++ {
++ while (__lo < __hi)
++ {
++ *__lo = __towupper_l(*__lo, _M_c_locale_ctype);
++ ++__lo;
++ }
++ return __hi;
++ }
++
++ wchar_t
++ ctype<wchar_t>::do_tolower(wchar_t __c) const
++ { return __towlower_l(__c, _M_c_locale_ctype); }
++
++ const wchar_t*
++ ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const
++ {
++ while (__lo < __hi)
++ {
++ *__lo = __towlower_l(*__lo, _M_c_locale_ctype);
++ ++__lo;
++ }
++ return __hi;
++ }
++
++ bool
++ ctype<wchar_t>::
++ do_is(mask __m, wchar_t __c) const
++ {
++ // Highest bitmask in ctype_base == 10, but extra in "C"
++ // library for blank.
++ bool __ret = false;
++ const size_t __bitmasksize = 11;
++ for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
++ if (__m & _M_bit[__bitcur]
++ && __iswctype_l(__c, _M_wmask[__bitcur], _M_c_locale_ctype))
++ {
++ __ret = true;
++ break;
++ }
++ return __ret;
++ }
++
++ const wchar_t*
++ ctype<wchar_t>::
++ do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __vec) const
++ {
++ for (; __lo < __hi; ++__vec, ++__lo)
++ {
++ // Highest bitmask in ctype_base == 10, but extra in "C"
++ // library for blank.
++ const size_t __bitmasksize = 11;
++ mask __m = 0;
++ for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
++ if (__iswctype_l(*__lo, _M_wmask[__bitcur], _M_c_locale_ctype))
++ __m |= _M_bit[__bitcur];
++ *__vec = __m;
++ }
++ return __hi;
++ }
++
++ const wchar_t*
++ ctype<wchar_t>::
++ do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const
++ {
++ while (__lo < __hi && !this->do_is(__m, *__lo))
++ ++__lo;
++ return __lo;
++ }
++
++ const wchar_t*
++ ctype<wchar_t>::
++ do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const
++ {
++ while (__lo < __hi && this->do_is(__m, *__lo) != 0)
++ ++__lo;
++ return __lo;
++ }
++
++ wchar_t
++ ctype<wchar_t>::
++ do_widen(char __c) const
++ { return _M_widen[static_cast<unsigned char>(__c)]; }
++
++ const char*
++ ctype<wchar_t>::
++ do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const
++ {
++ while (__lo < __hi)
++ {
++ *__dest = _M_widen[static_cast<unsigned char>(*__lo)];
++ ++__lo;
++ ++__dest;
++ }
++ return __hi;
++ }
++
++ char
++ ctype<wchar_t>::
++ do_narrow(wchar_t __wc, char __dfault) const
++ {
++ if (__wc >= 0 && __wc < 128 && _M_narrow_ok)
++ return _M_narrow[__wc];
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_ctype);
++#endif
++ const int __c = wctob(__wc);
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ return (__c == EOF ? __dfault : static_cast<char>(__c));
++ }
++
++ const wchar_t*
++ ctype<wchar_t>::
++ do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault,
++ char* __dest) const
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_ctype);
++#endif
++ if (_M_narrow_ok)
++ while (__lo < __hi)
++ {
++ if (*__lo >= 0 && *__lo < 128)
++ *__dest = _M_narrow[*__lo];
++ else
++ {
++ const int __c = wctob(*__lo);
++ *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
++ }
++ ++__lo;
++ ++__dest;
++ }
++ else
++ while (__lo < __hi)
++ {
++ const int __c = wctob(*__lo);
++ *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
++ ++__lo;
++ ++__dest;
++ }
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ return __hi;
++ }
++
++ void
++ ctype<wchar_t>::_M_initialize_ctype()
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_ctype);
++#endif
++ wint_t __i;
++ for (__i = 0; __i < 128; ++__i)
++ {
++ const int __c = wctob(__i);
++ if (__c == EOF)
++ break;
++ else
++ _M_narrow[__i] = static_cast<char>(__c);
++ }
++ if (__i == 128)
++ _M_narrow_ok = true;
++ else
++ _M_narrow_ok = false;
++ for (size_t __j = 0;
++ __j < sizeof(_M_widen) / sizeof(wint_t); ++__j)
++ _M_widen[__j] = btowc(__j);
++
++ for (size_t __k = 0; __k <= 11; ++__k)
++ {
++ _M_bit[__k] = static_cast<mask>(_ISbit(__k));
++ _M_wmask[__k] = _M_convert_to_wmask(_M_bit[__k]);
++ }
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ }
++#endif // _GLIBCXX_USE_WCHAR_T
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/messages_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/messages_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/messages_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/messages_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,100 @@
++// std::messages implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.7.1.2 messages virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <locale>
++#include <bits/c++locale_internal.h>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix gettext stuff
++#endif
++#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
++extern "C" char *__dcgettext(const char *domainname,
++ const char *msgid, int category);
++#undef gettext
++#define gettext(msgid) __dcgettext(NULL, msgid, LC_MESSAGES)
++#else
++#undef gettext
++#define gettext(msgid) (msgid)
++#endif
++
++namespace std
++{
++ // Specializations.
++ template<>
++ string
++ messages<char>::do_get(catalog, int, int, const string& __dfault) const
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_messages);
++ const char* __msg = const_cast<const char*>(gettext(__dfault.c_str()));
++ __uselocale(__old);
++ return string(__msg);
++#elif defined __UCLIBC_HAS_LOCALE__
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, _M_name_messages);
++ const char* __msg = gettext(__dfault.c_str());
++ setlocale(LC_ALL, __old);
++ free(__old);
++ return string(__msg);
++#else
++ const char* __msg = gettext(__dfault.c_str());
++ return string(__msg);
++#endif
++ }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ template<>
++ wstring
++ messages<wchar_t>::do_get(catalog, int, int, const wstring& __dfault) const
++ {
++# ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_messages);
++ char* __msg = gettext(_M_convert_to_char(__dfault));
++ __uselocale(__old);
++ return _M_convert_from_char(__msg);
++# elif defined __UCLIBC_HAS_LOCALE__
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, _M_name_messages);
++ char* __msg = gettext(_M_convert_to_char(__dfault));
++ setlocale(LC_ALL, __old);
++ free(__old);
++ return _M_convert_from_char(__msg);
++# else
++ char* __msg = gettext(_M_convert_to_char(__dfault));
++ return _M_convert_from_char(__msg);
++# endif
++ }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/messages_members.h gcc-3.4.2/libstdc++-v3/config/locale/uclibc/messages_members.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/messages_members.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/messages_members.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,118 @@
++// std::messages implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.7.1.2 messages functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix prototypes for *textdomain funcs
++#endif
++#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
++extern "C" char *__textdomain(const char *domainname);
++extern "C" char *__bindtextdomain(const char *domainname,
++ const char *dirname);
++#else
++#undef __textdomain
++#undef __bindtextdomain
++#define __textdomain(D) ((void)0)
++#define __bindtextdomain(D,P) ((void)0)
++#endif
++
++ // Non-virtual member functions.
++ template<typename _CharT>
++ messages<_CharT>::messages(size_t __refs)
++ : facet(__refs), _M_c_locale_messages(_S_get_c_locale()),
++ _M_name_messages(_S_get_c_name())
++ { }
++
++ template<typename _CharT>
++ messages<_CharT>::messages(__c_locale __cloc, const char* __s,
++ size_t __refs)
++ : facet(__refs), _M_c_locale_messages(_S_clone_c_locale(__cloc)),
++ _M_name_messages(__s)
++ {
++ char* __tmp = new char[std::strlen(__s) + 1];
++ std::strcpy(__tmp, __s);
++ _M_name_messages = __tmp;
++ }
++
++ template<typename _CharT>
++ typename messages<_CharT>::catalog
++ messages<_CharT>::open(const basic_string<char>& __s, const locale& __loc,
++ const char* __dir) const
++ {
++ __bindtextdomain(__s.c_str(), __dir);
++ return this->do_open(__s, __loc);
++ }
++
++ // Virtual member functions.
++ template<typename _CharT>
++ messages<_CharT>::~messages()
++ {
++ if (_M_name_messages != _S_get_c_name())
++ delete [] _M_name_messages;
++ _S_destroy_c_locale(_M_c_locale_messages);
++ }
++
++ template<typename _CharT>
++ typename messages<_CharT>::catalog
++ messages<_CharT>::do_open(const basic_string<char>& __s,
++ const locale&) const
++ {
++ // No error checking is done, assume the catalog exists and can
++ // be used.
++ __textdomain(__s.c_str());
++ return 0;
++ }
++
++ template<typename _CharT>
++ void
++ messages<_CharT>::do_close(catalog) const
++ { }
++
++ // messages_byname
++ template<typename _CharT>
++ messages_byname<_CharT>::messages_byname(const char* __s, size_t __refs)
++ : messages<_CharT>(__refs)
++ {
++ if (this->_M_name_messages != locale::facet::_S_get_c_name())
++ delete [] this->_M_name_messages;
++ char* __tmp = new char[std::strlen(__s) + 1];
++ std::strcpy(__tmp, __s);
++ this->_M_name_messages = __tmp;
++
++ if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
++ {
++ this->_S_destroy_c_locale(this->_M_c_locale_messages);
++ this->_S_create_c_locale(this->_M_c_locale_messages, __s);
++ }
++ }
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/monetary_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/monetary_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/monetary_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/monetary_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,698 @@
++// std::moneypunct implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.6.3.2 moneypunct virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#define _LIBC
++#include <locale>
++#undef _LIBC
++#include <bits/c++locale_internal.h>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning optimize this for uclibc
++#warning tailor for stub locale support
++#endif
++
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __nl_langinfo_l(N, L) nl_langinfo((N))
++#endif
++
++namespace std
++{
++ // Construct and return valid pattern consisting of some combination of:
++ // space none symbol sign value
++ money_base::pattern
++ money_base::_S_construct_pattern(char __precedes, char __space, char __posn)
++ {
++ pattern __ret;
++
++ // This insanely complicated routine attempts to construct a valid
++ // pattern for use with monyepunct. A couple of invariants:
++
++ // if (__precedes) symbol -> value
++ // else value -> symbol
++
++ // if (__space) space
++ // else none
++
++ // none == never first
++ // space never first or last
++
++ // Any elegant implementations of this are welcome.
++ switch (__posn)
++ {
++ case 0:
++ case 1:
++ // 1 The sign precedes the value and symbol.
++ __ret.field[0] = sign;
++ if (__space)
++ {
++ // Pattern starts with sign.
++ if (__precedes)
++ {
++ __ret.field[1] = symbol;
++ __ret.field[3] = value;
++ }
++ else
++ {
++ __ret.field[1] = value;
++ __ret.field[3] = symbol;
++ }
++ __ret.field[2] = space;
++ }
++ else
++ {
++ // Pattern starts with sign and ends with none.
++ if (__precedes)
++ {
++ __ret.field[1] = symbol;
++ __ret.field[2] = value;
++ }
++ else
++ {
++ __ret.field[1] = value;
++ __ret.field[2] = symbol;
++ }
++ __ret.field[3] = none;
++ }
++ break;
++ case 2:
++ // 2 The sign follows the value and symbol.
++ if (__space)
++ {
++ // Pattern either ends with sign.
++ if (__precedes)
++ {
++ __ret.field[0] = symbol;
++ __ret.field[2] = value;
++ }
++ else
++ {
++ __ret.field[0] = value;
++ __ret.field[2] = symbol;
++ }
++ __ret.field[1] = space;
++ __ret.field[3] = sign;
++ }
++ else
++ {
++ // Pattern ends with sign then none.
++ if (__precedes)
++ {
++ __ret.field[0] = symbol;
++ __ret.field[1] = value;
++ }
++ else
++ {
++ __ret.field[0] = value;
++ __ret.field[1] = symbol;
++ }
++ __ret.field[2] = sign;
++ __ret.field[3] = none;
++ }
++ break;
++ case 3:
++ // 3 The sign immediately precedes the symbol.
++ if (__precedes)
++ {
++ __ret.field[0] = sign;
++ __ret.field[1] = symbol;
++ if (__space)
++ {
++ __ret.field[2] = space;
++ __ret.field[3] = value;
++ }
++ else
++ {
++ __ret.field[2] = value;
++ __ret.field[3] = none;
++ }
++ }
++ else
++ {
++ __ret.field[0] = value;
++ if (__space)
++ {
++ __ret.field[1] = space;
++ __ret.field[2] = sign;
++ __ret.field[3] = symbol;
++ }
++ else
++ {
++ __ret.field[1] = sign;
++ __ret.field[2] = symbol;
++ __ret.field[3] = none;
++ }
++ }
++ break;
++ case 4:
++ // 4 The sign immediately follows the symbol.
++ if (__precedes)
++ {
++ __ret.field[0] = symbol;
++ __ret.field[1] = sign;
++ if (__space)
++ {
++ __ret.field[2] = space;
++ __ret.field[3] = value;
++ }
++ else
++ {
++ __ret.field[2] = value;
++ __ret.field[3] = none;
++ }
++ }
++ else
++ {
++ __ret.field[0] = value;
++ if (__space)
++ {
++ __ret.field[1] = space;
++ __ret.field[2] = symbol;
++ __ret.field[3] = sign;
++ }
++ else
++ {
++ __ret.field[1] = symbol;
++ __ret.field[2] = sign;
++ __ret.field[3] = none;
++ }
++ }
++ break;
++ default:
++ ;
++ }
++ return __ret;
++ }
++
++ template<>
++ void
++ moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc,
++ const char*)
++ {
++ if (!_M_data)
++ _M_data = new __moneypunct_cache<char, true>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_decimal_point = '.';
++ _M_data->_M_thousands_sep = ',';
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_curr_symbol = "";
++ _M_data->_M_curr_symbol_size = 0;
++ _M_data->_M_positive_sign = "";
++ _M_data->_M_positive_sign_size = 0;
++ _M_data->_M_negative_sign = "";
++ _M_data->_M_negative_sign_size = 0;
++ _M_data->_M_frac_digits = 0;
++ _M_data->_M_pos_format = money_base::_S_default_pattern;
++ _M_data->_M_neg_format = money_base::_S_default_pattern;
++
++ for (size_t __i = 0; __i < money_base::_S_end; ++__i)
++ _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
++ }
++ else
++ {
++ // Named locale.
++ _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT,
++ __cloc));
++ _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP,
++ __cloc));
++ _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++ _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
++ _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign);
++
++ char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
++ if (!__nposn)
++ _M_data->_M_negative_sign = "()";
++ else
++ _M_data->_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN,
++ __cloc);
++ _M_data->_M_negative_sign_size = strlen(_M_data->_M_negative_sign);
++
++ // _Intl == true
++ _M_data->_M_curr_symbol = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
++ _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol);
++ _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
++ __cloc));
++ char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
++ char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
++ char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
++ _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
++ __pposn);
++ char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
++ char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
++ _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
++ __nposn);
++ }
++ }
++
++ template<>
++ void
++ moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc,
++ const char*)
++ {
++ if (!_M_data)
++ _M_data = new __moneypunct_cache<char, false>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_decimal_point = '.';
++ _M_data->_M_thousands_sep = ',';
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_curr_symbol = "";
++ _M_data->_M_curr_symbol_size = 0;
++ _M_data->_M_positive_sign = "";
++ _M_data->_M_positive_sign_size = 0;
++ _M_data->_M_negative_sign = "";
++ _M_data->_M_negative_sign_size = 0;
++ _M_data->_M_frac_digits = 0;
++ _M_data->_M_pos_format = money_base::_S_default_pattern;
++ _M_data->_M_neg_format = money_base::_S_default_pattern;
++
++ for (size_t __i = 0; __i < money_base::_S_end; ++__i)
++ _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
++ }
++ else
++ {
++ // Named locale.
++ _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT,
++ __cloc));
++ _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP,
++ __cloc));
++ _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++ _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
++ _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign);
++
++ char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
++ if (!__nposn)
++ _M_data->_M_negative_sign = "()";
++ else
++ _M_data->_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN,
++ __cloc);
++ _M_data->_M_negative_sign_size = strlen(_M_data->_M_negative_sign);
++
++ // _Intl == false
++ _M_data->_M_curr_symbol = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
++ _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol);
++ _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
++ char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
++ char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
++ char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
++ _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
++ __pposn);
++ char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
++ char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
++ _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
++ __nposn);
++ }
++ }
++
++ template<>
++ moneypunct<char, true>::~moneypunct()
++ { delete _M_data; }
++
++ template<>
++ moneypunct<char, false>::~moneypunct()
++ { delete _M_data; }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ template<>
++ void
++ moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc,
++#ifdef __UCLIBC_HAS_XLOCALE__
++ const char*)
++#else
++ const char* __name)
++#endif
++ {
++ if (!_M_data)
++ _M_data = new __moneypunct_cache<wchar_t, true>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_decimal_point = L'.';
++ _M_data->_M_thousands_sep = L',';
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_curr_symbol = L"";
++ _M_data->_M_curr_symbol_size = 0;
++ _M_data->_M_positive_sign = L"";
++ _M_data->_M_positive_sign_size = 0;
++ _M_data->_M_negative_sign = L"";
++ _M_data->_M_negative_sign_size = 0;
++ _M_data->_M_frac_digits = 0;
++ _M_data->_M_pos_format = money_base::_S_default_pattern;
++ _M_data->_M_neg_format = money_base::_S_default_pattern;
++
++ // Use ctype::widen code without the facet...
++ unsigned char uc;
++ for (size_t __i = 0; __i < money_base::_S_end; ++__i)
++ {
++ uc = static_cast<unsigned char>(money_base::_S_atoms[__i]);
++ _M_data->_M_atoms[__i] = btowc(uc);
++ }
++ }
++ else
++ {
++ // Named locale.
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(__cloc);
++#else
++ // Switch to named locale so that mbsrtowcs will work.
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, __name);
++#endif
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix this... should be monetary
++#endif
++#ifdef __UCLIBC__
++# ifdef __UCLIBC_HAS_XLOCALE__
++ _M_data->_M_decimal_point = __cloc->decimal_point_wc;
++ _M_data->_M_thousands_sep = __cloc->thousands_sep_wc;
++# else
++ _M_data->_M_decimal_point = __global_locale->decimal_point_wc;
++ _M_data->_M_thousands_sep = __global_locale->thousands_sep_wc;
++# endif
++#else
++ union __s_and_w { const char *__s; unsigned int __w; } __u;
++ __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
++ _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
++
++ __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
++ _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
++#endif
++ _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++
++ const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
++ const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
++ const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
++
++ wchar_t* __wcs_ps = 0;
++ wchar_t* __wcs_ns = 0;
++ const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
++ try
++ {
++ mbstate_t __state;
++ size_t __len = strlen(__cpossign);
++ if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ __wcs_ps = new wchar_t[__len];
++ mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
++ _M_data->_M_positive_sign = __wcs_ps;
++ }
++ else
++ _M_data->_M_positive_sign = L"";
++ _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
++
++ __len = strlen(__cnegsign);
++ if (!__nposn)
++ _M_data->_M_negative_sign = L"()";
++ else if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ __wcs_ns = new wchar_t[__len];
++ mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
++ _M_data->_M_negative_sign = __wcs_ns;
++ }
++ else
++ _M_data->_M_negative_sign = L"";
++ _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
++
++ // _Intl == true.
++ __len = strlen(__ccurr);
++ if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ wchar_t* __wcs = new wchar_t[__len];
++ mbsrtowcs(__wcs, &__ccurr, __len, &__state);
++ _M_data->_M_curr_symbol = __wcs;
++ }
++ else
++ _M_data->_M_curr_symbol = L"";
++ _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
++ }
++ catch (...)
++ {
++ delete _M_data;
++ _M_data = 0;
++ delete __wcs_ps;
++ delete __wcs_ns;
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#else
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ __throw_exception_again;
++ }
++
++ _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
++ __cloc));
++ char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
++ char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
++ char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
++ _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
++ __pposn);
++ char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
++ char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
++ _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
++ __nposn);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#else
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ }
++ }
++
++ template<>
++ void
++ moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
++#ifdef __UCLIBC_HAS_XLOCALE__
++ const char*)
++#else
++ const char* __name)
++#endif
++ {
++ if (!_M_data)
++ _M_data = new __moneypunct_cache<wchar_t, false>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_decimal_point = L'.';
++ _M_data->_M_thousands_sep = L',';
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_curr_symbol = L"";
++ _M_data->_M_curr_symbol_size = 0;
++ _M_data->_M_positive_sign = L"";
++ _M_data->_M_positive_sign_size = 0;
++ _M_data->_M_negative_sign = L"";
++ _M_data->_M_negative_sign_size = 0;
++ _M_data->_M_frac_digits = 0;
++ _M_data->_M_pos_format = money_base::_S_default_pattern;
++ _M_data->_M_neg_format = money_base::_S_default_pattern;
++
++ // Use ctype::widen code without the facet...
++ unsigned char uc;
++ for (size_t __i = 0; __i < money_base::_S_end; ++__i)
++ {
++ uc = static_cast<unsigned char>(money_base::_S_atoms[__i]);
++ _M_data->_M_atoms[__i] = btowc(uc);
++ }
++ }
++ else
++ {
++ // Named locale.
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(__cloc);
++#else
++ // Switch to named locale so that mbsrtowcs will work.
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, __name);
++#endif
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix this... should be monetary
++#endif
++#ifdef __UCLIBC__
++# ifdef __UCLIBC_HAS_XLOCALE__
++ _M_data->_M_decimal_point = __cloc->decimal_point_wc;
++ _M_data->_M_thousands_sep = __cloc->thousands_sep_wc;
++# else
++ _M_data->_M_decimal_point = __global_locale->decimal_point_wc;
++ _M_data->_M_thousands_sep = __global_locale->thousands_sep_wc;
++# endif
++#else
++ union __s_and_w { const char *__s; unsigned int __w; } __u;
++ __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
++ _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
++
++ __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
++ _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
++#endif
++ _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++
++ const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
++ const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
++ const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
++
++ wchar_t* __wcs_ps = 0;
++ wchar_t* __wcs_ns = 0;
++ const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
++ try
++ {
++ mbstate_t __state;
++ size_t __len;
++ __len = strlen(__cpossign);
++ if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ __wcs_ps = new wchar_t[__len];
++ mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
++ _M_data->_M_positive_sign = __wcs_ps;
++ }
++ else
++ _M_data->_M_positive_sign = L"";
++ _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
++
++ __len = strlen(__cnegsign);
++ if (!__nposn)
++ _M_data->_M_negative_sign = L"()";
++ else if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ __wcs_ns = new wchar_t[__len];
++ mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
++ _M_data->_M_negative_sign = __wcs_ns;
++ }
++ else
++ _M_data->_M_negative_sign = L"";
++ _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
++
++ // _Intl == true.
++ __len = strlen(__ccurr);
++ if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ wchar_t* __wcs = new wchar_t[__len];
++ mbsrtowcs(__wcs, &__ccurr, __len, &__state);
++ _M_data->_M_curr_symbol = __wcs;
++ }
++ else
++ _M_data->_M_curr_symbol = L"";
++ _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
++ }
++ catch (...)
++ {
++ delete _M_data;
++ _M_data = 0;
++ delete __wcs_ps;
++ delete __wcs_ns;
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#else
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ __throw_exception_again;
++ }
++
++ _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
++ char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
++ char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
++ char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
++ _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
++ __pposn);
++ char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
++ char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
++ _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
++ __nposn);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#else
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ }
++ }
++
++ template<>
++ moneypunct<wchar_t, true>::~moneypunct()
++ {
++ if (_M_data->_M_positive_sign_size)
++ delete [] _M_data->_M_positive_sign;
++ if (_M_data->_M_negative_sign_size
++ && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
++ delete [] _M_data->_M_negative_sign;
++ if (_M_data->_M_curr_symbol_size)
++ delete [] _M_data->_M_curr_symbol;
++ delete _M_data;
++ }
++
++ template<>
++ moneypunct<wchar_t, false>::~moneypunct()
++ {
++ if (_M_data->_M_positive_sign_size)
++ delete [] _M_data->_M_positive_sign;
++ if (_M_data->_M_negative_sign_size
++ && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
++ delete [] _M_data->_M_negative_sign;
++ if (_M_data->_M_curr_symbol_size)
++ delete [] _M_data->_M_curr_symbol;
++ delete _M_data;
++ }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/numeric_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/numeric_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/numeric_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/numeric_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,183 @@
++// std::numpunct implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.3.1.2 numpunct virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#define _LIBC
++#include <locale>
++#undef _LIBC
++#include <bits/c++locale_internal.h>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning tailor for stub locale support
++#endif
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __nl_langinfo_l(N, L) nl_langinfo((N))
++#endif
++
++namespace std
++{
++ template<>
++ void
++ numpunct<char>::_M_initialize_numpunct(__c_locale __cloc)
++ {
++ if (!_M_data)
++ _M_data = new __numpunct_cache<char>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_use_grouping = false;
++
++ _M_data->_M_decimal_point = '.';
++ _M_data->_M_thousands_sep = ',';
++
++ for (size_t __i = 0; __i < __num_base::_S_oend; ++__i)
++ _M_data->_M_atoms_out[__i] = __num_base::_S_atoms_out[__i];
++
++ for (size_t __j = 0; __j < __num_base::_S_iend; ++__j)
++ _M_data->_M_atoms_in[__j] = __num_base::_S_atoms_in[__j];
++ }
++ else
++ {
++ // Named locale.
++ _M_data->_M_decimal_point = *(__nl_langinfo_l(DECIMAL_POINT,
++ __cloc));
++ _M_data->_M_thousands_sep = *(__nl_langinfo_l(THOUSANDS_SEP,
++ __cloc));
++
++ // Check for NULL, which implies no grouping.
++ if (_M_data->_M_thousands_sep == '\0')
++ _M_data->_M_grouping = "";
++ else
++ _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++ }
++
++ // NB: There is no way to extact this info from posix locales.
++ // _M_truename = __nl_langinfo_l(YESSTR, __cloc);
++ _M_data->_M_truename = "true";
++ _M_data->_M_truename_size = strlen(_M_data->_M_truename);
++ // _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
++ _M_data->_M_falsename = "false";
++ _M_data->_M_falsename_size = strlen(_M_data->_M_falsename);
++ }
++
++ template<>
++ numpunct<char>::~numpunct()
++ { delete _M_data; }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ template<>
++ void
++ numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc)
++ {
++ if (!_M_data)
++ _M_data = new __numpunct_cache<wchar_t>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_use_grouping = false;
++
++ _M_data->_M_decimal_point = L'.';
++ _M_data->_M_thousands_sep = L',';
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_S_get_c_locale());
++#endif
++ // Use ctype::widen code without the facet...
++ unsigned char uc;
++ for (size_t __i = 0; __i < __num_base::_S_oend; ++__i)
++ {
++ uc = static_cast<unsigned char>(__num_base::_S_atoms_out[__i]);
++ _M_data->_M_atoms_out[__i] = btowc(uc);
++ }
++
++ for (size_t __j = 0; __j < __num_base::_S_iend; ++__j)
++ {
++ uc = static_cast<unsigned char>(__num_base::_S_atoms_in[__j]);
++ _M_data->_M_atoms_in[__j] = btowc(uc);
++ }
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ }
++ else
++ {
++ // Named locale.
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix this
++#endif
++#ifdef __UCLIBC__
++# ifdef __UCLIBC_HAS_XLOCALE__
++ _M_data->_M_decimal_point = __cloc->decimal_point_wc;
++ _M_data->_M_thousands_sep = __cloc->thousands_sep_wc;
++# else
++ _M_data->_M_decimal_point = __global_locale->decimal_point_wc;
++ _M_data->_M_thousands_sep = __global_locale->thousands_sep_wc;
++# endif
++#else
++ union __s_and_w { const char *__s; unsigned int __w; } __u;
++ __u.__s = __nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc);
++ _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
++
++ __u.__s = __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc);
++ _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
++#endif
++
++ if (_M_data->_M_thousands_sep == L'\0')
++ _M_data->_M_grouping = "";
++ else
++ _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++ }
++
++ // NB: There is no way to extact this info from posix locales.
++ // _M_truename = __nl_langinfo_l(YESSTR, __cloc);
++ _M_data->_M_truename = L"true";
++ _M_data->_M_truename_size = wcslen(_M_data->_M_truename);
++ // _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
++ _M_data->_M_falsename = L"false";
++ _M_data->_M_falsename_size = wcslen(_M_data->_M_falsename);
++ }
++
++ template<>
++ numpunct<wchar_t>::~numpunct()
++ { delete _M_data; }
++ #endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/time_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/time_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/time_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/time_members.cc 2004-09-10 10:48:00.000000000 -0500
+@@ -0,0 +1,356 @@
++// std::time_get, std::time_put implementation, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.5.1.2 - time_get virtual functions
++// ISO C++ 14882: 22.2.5.3.2 - time_put virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <locale>
++#include <bits/c++locale_internal.h>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning tailor for stub locale support
++#endif
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __nl_langinfo_l(N, L) nl_langinfo((N))
++#endif
++
++namespace std
++{
++ template<>
++ void
++ __timepunct<char>::
++ _M_put(char* __s, size_t __maxlen, const char* __format,
++ const tm* __tm) const
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ const size_t __len = __strftime_l(__s, __maxlen, __format, __tm,
++ _M_c_locale_timepunct);
++#else
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, _M_name_timepunct);
++ const size_t __len = strftime(__s, __maxlen, __format, __tm);
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ // Make sure __s is null terminated.
++ if (__len == 0)
++ __s[0] = '\0';
++ }
++
++ template<>
++ void
++ __timepunct<char>::_M_initialize_timepunct(__c_locale __cloc)
++ {
++ if (!_M_data)
++ _M_data = new __timepunct_cache<char>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_c_locale_timepunct = _S_get_c_locale();
++
++ _M_data->_M_date_format = "%m/%d/%y";
++ _M_data->_M_date_era_format = "%m/%d/%y";
++ _M_data->_M_time_format = "%H:%M:%S";
++ _M_data->_M_time_era_format = "%H:%M:%S";
++ _M_data->_M_date_time_format = "";
++ _M_data->_M_date_time_era_format = "";
++ _M_data->_M_am = "AM";
++ _M_data->_M_pm = "PM";
++ _M_data->_M_am_pm_format = "";
++
++ // Day names, starting with "C"'s Sunday.
++ _M_data->_M_day1 = "Sunday";
++ _M_data->_M_day2 = "Monday";
++ _M_data->_M_day3 = "Tuesday";
++ _M_data->_M_day4 = "Wednesday";
++ _M_data->_M_day5 = "Thursday";
++ _M_data->_M_day6 = "Friday";
++ _M_data->_M_day7 = "Saturday";
++
++ // Abbreviated day names, starting with "C"'s Sun.
++ _M_data->_M_aday1 = "Sun";
++ _M_data->_M_aday2 = "Mon";
++ _M_data->_M_aday3 = "Tue";
++ _M_data->_M_aday4 = "Wed";
++ _M_data->_M_aday5 = "Thu";
++ _M_data->_M_aday6 = "Fri";
++ _M_data->_M_aday7 = "Sat";
++
++ // Month names, starting with "C"'s January.
++ _M_data->_M_month01 = "January";
++ _M_data->_M_month02 = "February";
++ _M_data->_M_month03 = "March";
++ _M_data->_M_month04 = "April";
++ _M_data->_M_month05 = "May";
++ _M_data->_M_month06 = "June";
++ _M_data->_M_month07 = "July";
++ _M_data->_M_month08 = "August";
++ _M_data->_M_month09 = "September";
++ _M_data->_M_month10 = "October";
++ _M_data->_M_month11 = "November";
++ _M_data->_M_month12 = "December";
++
++ // Abbreviated month names, starting with "C"'s Jan.
++ _M_data->_M_amonth01 = "Jan";
++ _M_data->_M_amonth02 = "Feb";
++ _M_data->_M_amonth03 = "Mar";
++ _M_data->_M_amonth04 = "Apr";
++ _M_data->_M_amonth05 = "May";
++ _M_data->_M_amonth06 = "Jun";
++ _M_data->_M_amonth07 = "Jul";
++ _M_data->_M_amonth08 = "Aug";
++ _M_data->_M_amonth09 = "Sep";
++ _M_data->_M_amonth10 = "Oct";
++ _M_data->_M_amonth11 = "Nov";
++ _M_data->_M_amonth12 = "Dec";
++ }
++ else
++ {
++ _M_c_locale_timepunct = _S_clone_c_locale(__cloc);
++
++ _M_data->_M_date_format = __nl_langinfo_l(D_FMT, __cloc);
++ _M_data->_M_date_era_format = __nl_langinfo_l(ERA_D_FMT, __cloc);
++ _M_data->_M_time_format = __nl_langinfo_l(T_FMT, __cloc);
++ _M_data->_M_time_era_format = __nl_langinfo_l(ERA_T_FMT, __cloc);
++ _M_data->_M_date_time_format = __nl_langinfo_l(D_T_FMT, __cloc);
++ _M_data->_M_date_time_era_format = __nl_langinfo_l(ERA_D_T_FMT, __cloc);
++ _M_data->_M_am = __nl_langinfo_l(AM_STR, __cloc);
++ _M_data->_M_pm = __nl_langinfo_l(PM_STR, __cloc);
++ _M_data->_M_am_pm_format = __nl_langinfo_l(T_FMT_AMPM, __cloc);
++
++ // Day names, starting with "C"'s Sunday.
++ _M_data->_M_day1 = __nl_langinfo_l(DAY_1, __cloc);
++ _M_data->_M_day2 = __nl_langinfo_l(DAY_2, __cloc);
++ _M_data->_M_day3 = __nl_langinfo_l(DAY_3, __cloc);
++ _M_data->_M_day4 = __nl_langinfo_l(DAY_4, __cloc);
++ _M_data->_M_day5 = __nl_langinfo_l(DAY_5, __cloc);
++ _M_data->_M_day6 = __nl_langinfo_l(DAY_6, __cloc);
++ _M_data->_M_day7 = __nl_langinfo_l(DAY_7, __cloc);
++
++ // Abbreviated day names, starting with "C"'s Sun.
++ _M_data->_M_aday1 = __nl_langinfo_l(ABDAY_1, __cloc);
++ _M_data->_M_aday2 = __nl_langinfo_l(ABDAY_2, __cloc);
++ _M_data->_M_aday3 = __nl_langinfo_l(ABDAY_3, __cloc);
++ _M_data->_M_aday4 = __nl_langinfo_l(ABDAY_4, __cloc);
++ _M_data->_M_aday5 = __nl_langinfo_l(ABDAY_5, __cloc);
++ _M_data->_M_aday6 = __nl_langinfo_l(ABDAY_6, __cloc);
++ _M_data->_M_aday7 = __nl_langinfo_l(ABDAY_7, __cloc);
++
++ // Month names, starting with "C"'s January.
++ _M_data->_M_month01 = __nl_langinfo_l(MON_1, __cloc);
++ _M_data->_M_month02 = __nl_langinfo_l(MON_2, __cloc);
++ _M_data->_M_month03 = __nl_langinfo_l(MON_3, __cloc);
++ _M_data->_M_month04 = __nl_langinfo_l(MON_4, __cloc);
++ _M_data->_M_month05 = __nl_langinfo_l(MON_5, __cloc);
++ _M_data->_M_month06 = __nl_langinfo_l(MON_6, __cloc);
++ _M_data->_M_month07 = __nl_langinfo_l(MON_7, __cloc);
++ _M_data->_M_month08 = __nl_langinfo_l(MON_8, __cloc);
++ _M_data->_M_month09 = __nl_langinfo_l(MON_9, __cloc);
++ _M_data->_M_month10 = __nl_langinfo_l(MON_10, __cloc);
++ _M_data->_M_month11 = __nl_langinfo_l(MON_11, __cloc);
++ _M_data->_M_month12 = __nl_langinfo_l(MON_12, __cloc);
++
++ // Abbreviated month names, starting with "C"'s Jan.
++ _M_data->_M_amonth01 = __nl_langinfo_l(ABMON_1, __cloc);
++ _M_data->_M_amonth02 = __nl_langinfo_l(ABMON_2, __cloc);
++ _M_data->_M_amonth03 = __nl_langinfo_l(ABMON_3, __cloc);
++ _M_data->_M_amonth04 = __nl_langinfo_l(ABMON_4, __cloc);
++ _M_data->_M_amonth05 = __nl_langinfo_l(ABMON_5, __cloc);
++ _M_data->_M_amonth06 = __nl_langinfo_l(ABMON_6, __cloc);
++ _M_data->_M_amonth07 = __nl_langinfo_l(ABMON_7, __cloc);
++ _M_data->_M_amonth08 = __nl_langinfo_l(ABMON_8, __cloc);
++ _M_data->_M_amonth09 = __nl_langinfo_l(ABMON_9, __cloc);
++ _M_data->_M_amonth10 = __nl_langinfo_l(ABMON_10, __cloc);
++ _M_data->_M_amonth11 = __nl_langinfo_l(ABMON_11, __cloc);
++ _M_data->_M_amonth12 = __nl_langinfo_l(ABMON_12, __cloc);
++ }
++ }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ template<>
++ void
++ __timepunct<wchar_t>::
++ _M_put(wchar_t* __s, size_t __maxlen, const wchar_t* __format,
++ const tm* __tm) const
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __wcsftime_l(__s, __maxlen, __format, __tm, _M_c_locale_timepunct);
++ const size_t __len = __wcsftime_l(__s, __maxlen, __format, __tm,
++ _M_c_locale_timepunct);
++#else
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, _M_name_timepunct);
++ const size_t __len = wcsftime(__s, __maxlen, __format, __tm);
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ // Make sure __s is null terminated.
++ if (__len == 0)
++ __s[0] = L'\0';
++ }
++
++ template<>
++ void
++ __timepunct<wchar_t>::_M_initialize_timepunct(__c_locale __cloc)
++ {
++ if (!_M_data)
++ _M_data = new __timepunct_cache<wchar_t>;
++
++#warning wide time stuff
++// if (!__cloc)
++ {
++ // "C" locale
++ _M_c_locale_timepunct = _S_get_c_locale();
++
++ _M_data->_M_date_format = L"%m/%d/%y";
++ _M_data->_M_date_era_format = L"%m/%d/%y";
++ _M_data->_M_time_format = L"%H:%M:%S";
++ _M_data->_M_time_era_format = L"%H:%M:%S";
++ _M_data->_M_date_time_format = L"";
++ _M_data->_M_date_time_era_format = L"";
++ _M_data->_M_am = L"AM";
++ _M_data->_M_pm = L"PM";
++ _M_data->_M_am_pm_format = L"";
++
++ // Day names, starting with "C"'s Sunday.
++ _M_data->_M_day1 = L"Sunday";
++ _M_data->_M_day2 = L"Monday";
++ _M_data->_M_day3 = L"Tuesday";
++ _M_data->_M_day4 = L"Wednesday";
++ _M_data->_M_day5 = L"Thursday";
++ _M_data->_M_day6 = L"Friday";
++ _M_data->_M_day7 = L"Saturday";
++
++ // Abbreviated day names, starting with "C"'s Sun.
++ _M_data->_M_aday1 = L"Sun";
++ _M_data->_M_aday2 = L"Mon";
++ _M_data->_M_aday3 = L"Tue";
++ _M_data->_M_aday4 = L"Wed";
++ _M_data->_M_aday5 = L"Thu";
++ _M_data->_M_aday6 = L"Fri";
++ _M_data->_M_aday7 = L"Sat";
++
++ // Month names, starting with "C"'s January.
++ _M_data->_M_month01 = L"January";
++ _M_data->_M_month02 = L"February";
++ _M_data->_M_month03 = L"March";
++ _M_data->_M_month04 = L"April";
++ _M_data->_M_month05 = L"May";
++ _M_data->_M_month06 = L"June";
++ _M_data->_M_month07 = L"July";
++ _M_data->_M_month08 = L"August";
++ _M_data->_M_month09 = L"September";
++ _M_data->_M_month10 = L"October";
++ _M_data->_M_month11 = L"November";
++ _M_data->_M_month12 = L"December";
++
++ // Abbreviated month names, starting with "C"'s Jan.
++ _M_data->_M_amonth01 = L"Jan";
++ _M_data->_M_amonth02 = L"Feb";
++ _M_data->_M_amonth03 = L"Mar";
++ _M_data->_M_amonth04 = L"Apr";
++ _M_data->_M_amonth05 = L"May";
++ _M_data->_M_amonth06 = L"Jun";
++ _M_data->_M_amonth07 = L"Jul";
++ _M_data->_M_amonth08 = L"Aug";
++ _M_data->_M_amonth09 = L"Sep";
++ _M_data->_M_amonth10 = L"Oct";
++ _M_data->_M_amonth11 = L"Nov";
++ _M_data->_M_amonth12 = L"Dec";
++ }
++#if 0
++ else
++ {
++ _M_c_locale_timepunct = _S_clone_c_locale(__cloc);
++
++ _M_data->_M_date_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WD_FMT, __cloc));
++ _M_data->_M_date_era_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WERA_D_FMT, __cloc));
++ _M_data->_M_time_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WT_FMT, __cloc));
++ _M_data->_M_time_era_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WERA_T_FMT, __cloc));
++ _M_data->_M_date_time_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WD_T_FMT, __cloc));
++ _M_data->_M_date_time_era_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WERA_D_T_FMT, __cloc));
++ _M_data->_M_am = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WAM_STR, __cloc));
++ _M_data->_M_pm = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WPM_STR, __cloc));
++ _M_data->_M_am_pm_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WT_FMT_AMPM, __cloc));
++
++ // Day names, starting with "C"'s Sunday.
++ _M_data->_M_day1 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_1, __cloc));
++ _M_data->_M_day2 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_2, __cloc));
++ _M_data->_M_day3 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_3, __cloc));
++ _M_data->_M_day4 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_4, __cloc));
++ _M_data->_M_day5 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_5, __cloc));
++ _M_data->_M_day6 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_6, __cloc));
++ _M_data->_M_day7 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_7, __cloc));
++
++ // Abbreviated day names, starting with "C"'s Sun.
++ _M_data->_M_aday1 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_1, __cloc));
++ _M_data->_M_aday2 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_2, __cloc));
++ _M_data->_M_aday3 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_3, __cloc));
++ _M_data->_M_aday4 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_4, __cloc));
++ _M_data->_M_aday5 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_5, __cloc));
++ _M_data->_M_aday6 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_6, __cloc));
++ _M_data->_M_aday7 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_7, __cloc));
++
++ // Month names, starting with "C"'s January.
++ _M_data->_M_month01 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_1, __cloc));
++ _M_data->_M_month02 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_2, __cloc));
++ _M_data->_M_month03 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_3, __cloc));
++ _M_data->_M_month04 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_4, __cloc));
++ _M_data->_M_month05 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_5, __cloc));
++ _M_data->_M_month06 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_6, __cloc));
++ _M_data->_M_month07 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_7, __cloc));
++ _M_data->_M_month08 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_8, __cloc));
++ _M_data->_M_month09 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_9, __cloc));
++ _M_data->_M_month10 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_10, __cloc));
++ _M_data->_M_month11 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_11, __cloc));
++ _M_data->_M_month12 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_12, __cloc));
++
++ // Abbreviated month names, starting with "C"'s Jan.
++ _M_data->_M_amonth01 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_1, __cloc));
++ _M_data->_M_amonth02 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_2, __cloc));
++ _M_data->_M_amonth03 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_3, __cloc));
++ _M_data->_M_amonth04 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_4, __cloc));
++ _M_data->_M_amonth05 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_5, __cloc));
++ _M_data->_M_amonth06 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_6, __cloc));
++ _M_data->_M_amonth07 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_7, __cloc));
++ _M_data->_M_amonth08 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_8, __cloc));
++ _M_data->_M_amonth09 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_9, __cloc));
++ _M_data->_M_amonth10 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_10, __cloc));
++ _M_data->_M_amonth11 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_11, __cloc));
++ _M_data->_M_amonth12 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_12, __cloc));
++ }
++#endif // 0
++ }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/time_members.h gcc-3.4.2/libstdc++-v3/config/locale/uclibc/time_members.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/time_members.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/time_members.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,68 @@
++// std::time_get, std::time_put implementation, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.5.1.2 - time_get functions
++// ISO C++ 14882: 22.2.5.3.2 - time_put functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++ template<typename _CharT>
++ __timepunct<_CharT>::__timepunct(size_t __refs)
++ : facet(__refs), _M_data(NULL), _M_c_locale_timepunct(NULL),
++ _M_name_timepunct(_S_get_c_name())
++ { _M_initialize_timepunct(); }
++
++ template<typename _CharT>
++ __timepunct<_CharT>::__timepunct(__cache_type* __cache, size_t __refs)
++ : facet(__refs), _M_data(__cache), _M_c_locale_timepunct(NULL),
++ _M_name_timepunct(_S_get_c_name())
++ { _M_initialize_timepunct(); }
++
++ template<typename _CharT>
++ __timepunct<_CharT>::__timepunct(__c_locale __cloc, const char* __s,
++ size_t __refs)
++ : facet(__refs), _M_data(NULL), _M_c_locale_timepunct(NULL),
++ _M_name_timepunct(__s)
++ {
++ char* __tmp = new char[std::strlen(__s) + 1];
++ std::strcpy(__tmp, __s);
++ _M_name_timepunct = __tmp;
++ _M_initialize_timepunct(__cloc);
++ }
++
++ template<typename _CharT>
++ __timepunct<_CharT>::~__timepunct()
++ {
++ if (_M_name_timepunct != _S_get_c_name())
++ delete [] _M_name_timepunct;
++ delete _M_data;
++ _S_destroy_c_locale(_M_c_locale_timepunct);
++ }
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_base.h gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_base.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_base.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_base.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,58 @@
++// Locale support -*- C++ -*-
++
++// Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003
++// Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.1 Locales
++//
++
++// Information as gleaned from /usr/include/ctype.h
++
++ struct ctype_base
++ {
++ // Note: In uClibc, the following two types depend on configuration.
++
++ // Non-standard typedefs.
++ typedef const __ctype_touplow_t* __to_type;
++
++ // NB: Offsets into ctype<char>::_M_table force a particular size
++ // on the mask type. Because of this, we don't use an enum.
++ typedef __ctype_mask_t mask;
++ static const mask upper = _ISupper;
++ static const mask lower = _ISlower;
++ static const mask alpha = _ISalpha;
++ static const mask digit = _ISdigit;
++ static const mask xdigit = _ISxdigit;
++ static const mask space = _ISspace;
++ static const mask print = _ISprint;
++ static const mask graph = _ISalpha | _ISdigit | _ISpunct;
++ static const mask cntrl = _IScntrl;
++ static const mask punct = _ISpunct;
++ static const mask alnum = _ISalpha | _ISdigit;
++ };
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_inline.h gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_inline.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_inline.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_inline.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,69 @@
++// Locale support -*- C++ -*-
++
++// Copyright (C) 2000, 2002 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.1 Locales
++//
++
++// ctype bits to be inlined go here. Non-inlinable (ie virtual do_*)
++// functions go in ctype.cc
++
++ bool
++ ctype<char>::
++ is(mask __m, char __c) const
++ { return _M_table[static_cast<unsigned char>(__c)] & __m; }
++
++ const char*
++ ctype<char>::
++ is(const char* __low, const char* __high, mask* __vec) const
++ {
++ while (__low < __high)
++ *__vec++ = _M_table[static_cast<unsigned char>(*__low++)];
++ return __high;
++ }
++
++ const char*
++ ctype<char>::
++ scan_is(mask __m, const char* __low, const char* __high) const
++ {
++ while (__low < __high
++ && !(_M_table[static_cast<unsigned char>(*__low)] & __m))
++ ++__low;
++ return __low;
++ }
++
++ const char*
++ ctype<char>::
++ scan_not(mask __m, const char* __low, const char* __high) const
++ {
++ while (__low < __high
++ && (_M_table[static_cast<unsigned char>(*__low)] & __m) != 0)
++ ++__low;
++ return __low;
++ }
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_noninline.h gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_noninline.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_noninline.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_noninline.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,92 @@
++// Locale support -*- C++ -*-
++
++// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2004
++// Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.1 Locales
++//
++
++// Information as gleaned from /usr/include/ctype.h
++
++ const ctype_base::mask*
++ ctype<char>::classic_table() throw()
++ { return __C_ctype_b; }
++
++ ctype<char>::ctype(__c_locale, const mask* __table, bool __del,
++ size_t __refs)
++ : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()),
++ _M_del(__table != 0 && __del), _M_widen_ok(0), _M_narrow_ok(0)
++ {
++ _M_toupper = __C_ctype_toupper;
++ _M_tolower = __C_ctype_tolower;
++ _M_table = __table ? __table : __C_ctype_b;
++ memset(_M_widen, 0, sizeof(_M_widen));
++ memset(_M_narrow, 0, sizeof(_M_narrow));
++ }
++
++ ctype<char>::ctype(const mask* __table, bool __del, size_t __refs)
++ : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()),
++ _M_del(__table != 0 && __del), _M_widen_ok(0), _M_narrow_ok(0)
++ {
++ _M_toupper = __C_ctype_toupper;
++ _M_tolower = __C_ctype_tolower;
++ _M_table = __table ? __table : __C_ctype_b;
++ memset(_M_widen, 0, sizeof(_M_widen));
++ memset(_M_narrow, 0, sizeof(_M_narrow));
++ }
++
++ char
++ ctype<char>::do_toupper(char __c) const
++ { return _M_toupper[static_cast<unsigned char>(__c)]; }
++
++ const char*
++ ctype<char>::do_toupper(char* __low, const char* __high) const
++ {
++ while (__low < __high)
++ {
++ *__low = _M_toupper[static_cast<unsigned char>(*__low)];
++ ++__low;
++ }
++ return __high;
++ }
++
++ char
++ ctype<char>::do_tolower(char __c) const
++ { return _M_tolower[static_cast<unsigned char>(__c)]; }
++
++ const char*
++ ctype<char>::do_tolower(char* __low, const char* __high) const
++ {
++ while (__low < __high)
++ {
++ *__low = _M_tolower[static_cast<unsigned char>(*__low)];
++ ++__low;
++ }
++ return __high;
++ }
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/os_defines.h gcc-3.4.2/libstdc++-v3/config/os/uclibc/os_defines.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/os_defines.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/os/uclibc/os_defines.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,44 @@
++// Specific definitions for GNU/Linux -*- C++ -*-
++
++// Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++#ifndef _GLIBCXX_OS_DEFINES
++#define _GLIBCXX_OS_DEFINES 1
++
++// System-specific #define, typedefs, corrections, etc, go here. This
++// file will come before all others.
++
++// This keeps isanum, et al from being propagated as macros.
++#define __NO_CTYPE 1
++
++#include <features.h>
++
++// We must not see the optimized string functions GNU libc defines.
++#define __NO_STRING_INLINES
++
++#endif
+diff -urN gcc-3.4.2-dist/libstdc++-v3/configure gcc-3.4.2/libstdc++-v3/configure
+--- gcc-3.4.2-dist/libstdc++-v3/configure 2004-08-13 15:44:04.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/configure 2004-09-10 10:47:40.000000000 -0500
+@@ -3878,6 +3878,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+@@ -5479,7 +5479,7 @@
+ enableval="$enable_clocale"
+
+ case "$enableval" in
+- generic|gnu|ieee_1003.1-2001|yes|no|auto) ;;
++ generic|gnu|ieee_1003.1-2001|uclibc|yes|no|auto) ;;
+ *) { { echo "$as_me:$LINENO: error: Unknown argument to enable/disable clocale" >&5
+ echo "$as_me: error: Unknown argument to enable/disable clocale" >&2;}
+ { (exit 1); exit 1; }; } ;;
+@@ -5545,6 +5550,9 @@
+ # Default to "generic".
+ if test $enable_clocale_flag = auto; then
+ case x${target_os} in
++ xlinux-uclibc*)
++ enable_clocale_flag=uclibc
++ ;;
+ xlinux* | xgnu* | xkfreebsd*-gnu | xknetbsd*-gnu)
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -5759,6 +5767,77 @@
+ CTIME_CC=config/locale/generic/time_members.cc
+ CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+ ;;
++ uclibc)
++ echo "$as_me:$LINENO: result: uclibc" >&5
++echo "${ECHO_T}uclibc" >&6
++
++ # Declare intention to use gettext, and add support for specific
++ # languages.
++ # For some reason, ALL_LINGUAS has to be before AM-GNU-GETTEXT
++ ALL_LINGUAS="de fr"
++
++ # Don't call AM-GNU-GETTEXT here. Instead, assume glibc.
++ # Extract the first word of "msgfmt", so it can be a program name with args.
++set dummy msgfmt; 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_check_msgfmt+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ if test -n "$check_msgfmt"; then
++ ac_cv_prog_check_msgfmt="$check_msgfmt" # 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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ ac_cv_prog_check_msgfmt="yes"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
++ fi
++done
++done
++
++ test -z "$ac_cv_prog_check_msgfmt" && ac_cv_prog_check_msgfmt="no"
++fi
++fi
++check_msgfmt=$ac_cv_prog_check_msgfmt
++if test -n "$check_msgfmt"; then
++ echo "$as_me:$LINENO: result: $check_msgfmt" >&5
++echo "${ECHO_T}$check_msgfmt" >&6
++else
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
++fi
++
++ if test x"$check_msgfmt" = x"yes" && test x"$enable_nls" = x"yes"; then
++ USE_NLS=yes
++ fi
++ # Export the build objects.
++ for ling in $ALL_LINGUAS; do \
++ glibcxx_MOFILES="$glibcxx_MOFILES $ling.mo"; \
++ glibcxx_POFILES="$glibcxx_POFILES $ling.po"; \
++ done
++
++
++
++ CLOCALE_H=config/locale/uclibc/c_locale.h
++ CLOCALE_CC=config/locale/uclibc/c_locale.cc
++ CCODECVT_H=config/locale/ieee_1003.1-2001/codecvt_specializations.h
++ CCODECVT_CC=config/locale/uclibc/codecvt_members.cc
++ CCOLLATE_CC=config/locale/uclibc/collate_members.cc
++ CCTYPE_CC=config/locale/uclibc/ctype_members.cc
++ CMESSAGES_H=config/locale/uclibc/messages_members.h
++ CMESSAGES_CC=config/locale/uclibc/messages_members.cc
++ CMONEY_CC=config/locale/uclibc/monetary_members.cc
++ CNUMERIC_CC=config/locale/uclibc/numeric_members.cc
++ CTIME_H=config/locale/uclibc/time_members.h
++ CTIME_CC=config/locale/uclibc/time_members.cc
++ CLOCALE_INTERNAL_H=config/locale/uclibc/c++locale_internal.h
++ ;;
+ esac
+
+ # This is where the testsuite looks for locale catalogs, using the
+diff -urN gcc-3.4.2-dist/libstdc++-v3/configure.host gcc-3.4.2/libstdc++-v3/configure.host
+--- gcc-3.4.2-dist/libstdc++-v3/configure.host 2004-08-27 14:52:30.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/configure.host 2004-09-10 10:47:40.000000000 -0500
+@@ -217,6 +217,12 @@
+ ;;
+ esac
+
++# Override for uClibc since linux-uclibc gets mishandled above.
++case "${host_os}" in
++ *-uclibc*)
++ os_include_dir="os/uclibc"
++ ;;
++esac
+
+ # Set any OS-dependent and CPU-dependent bits.
+ # THIS TABLE IS SORTED. KEEP IT THAT WAY.
+diff -urN gcc-3.4.2-dist/libstdc++-v3/crossconfig.m4 gcc-3.4.2/libstdc++-v3/crossconfig.m4
+--- gcc-3.4.2-dist/libstdc++-v3/crossconfig.m4 2004-07-06 20:23:49.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/crossconfig.m4 2004-09-10 10:47:40.000000000 -0500
+@@ -138,6 +138,99 @@
+ ;;
+ esac
+ ;;
++ *-uclibc*)
++# Temporary hack until we implement the float versions of the libm funcs
++ AC_CHECK_HEADERS([nan.h ieeefp.h endian.h sys/isa_defs.h \
++ machine/endian.h machine/param.h sys/machine.h sys/types.h \
++ fp.h float.h endian.h inttypes.h locale.h float.h stdint.h])
++ SECTION_FLAGS='-ffunction-sections -fdata-sections'
++ AC_SUBST(SECTION_FLAGS)
++ GLIBCXX_CHECK_LINKER_FEATURES
++ GLIBCXX_CHECK_COMPLEX_MATH_SUPPORT
++ GLIBCXX_CHECK_WCHAR_T_SUPPORT
++
++ # For LFS.
++ AC_DEFINE(HAVE_INT64_T)
++ case "$target" in
++ *-uclinux*)
++ # Don't enable LFS with uClinux
++ ;;
++ *)
++ AC_DEFINE(_GLIBCXX_USE_LFS)
++ esac
++
++ # For showmanyc_helper().
++ AC_CHECK_HEADERS(sys/ioctl.h sys/filio.h)
++ GLIBCXX_CHECK_POLL
++ GLIBCXX_CHECK_S_ISREG_OR_S_IFREG
++
++ # For xsputn_2().
++ AC_CHECK_HEADERS(sys/uio.h)
++ GLIBCXX_CHECK_WRITEV
++
++# AC_DEFINE(HAVE_ACOSF)
++# AC_DEFINE(HAVE_ASINF)
++# AC_DEFINE(HAVE_ATANF)
++# AC_DEFINE(HAVE_ATAN2F)
++ AC_DEFINE(HAVE_CEILF)
++ AC_DEFINE(HAVE_COPYSIGN)
++# AC_DEFINE(HAVE_COPYSIGNF)
++# AC_DEFINE(HAVE_COSF)
++# AC_DEFINE(HAVE_COSHF)
++# AC_DEFINE(HAVE_EXPF)
++# AC_DEFINE(HAVE_FABSF)
++ AC_DEFINE(HAVE_FINITE)
++ AC_DEFINE(HAVE_FINITEF)
++ AC_DEFINE(HAVE_FLOORF)
++# AC_DEFINE(HAVE_FMODF)
++# AC_DEFINE(HAVE_FREXPF)
++ AC_DEFINE(HAVE_HYPOT)
++# AC_DEFINE(HAVE_HYPOTF)
++ AC_DEFINE(HAVE_ISINF)
++ AC_DEFINE(HAVE_ISINFF)
++ AC_DEFINE(HAVE_ISNAN)
++ AC_DEFINE(HAVE_ISNANF)
++# AC_DEFINE(HAVE_LOGF)
++# AC_DEFINE(HAVE_LOG10F)
++# AC_DEFINE(HAVE_MODFF)
++# AC_DEFINE(HAVE_SINF)
++# AC_DEFINE(HAVE_SINHF)
++# AC_DEFINE(HAVE_SINCOS)
++# AC_DEFINE(HAVE_SINCOSF)
++ AC_DEFINE(HAVE_SQRTF)
++# AC_DEFINE(HAVE_TANF)
++# AC_DEFINE(HAVE_TANHF)
++ if test x"long_double_math_on_this_cpu" = x"yes"; then
++ AC_MSG_ERROR([long_double_math_on_this_cpu is yes!])
++# AC_DEFINE(HAVE_ACOSL)
++# AC_DEFINE(HAVE_ASINL)
++# AC_DEFINE(HAVE_ATANL)
++# AC_DEFINE(HAVE_ATAN2L)
++# AC_DEFINE(HAVE_CEILL)
++# AC_DEFINE(HAVE_COPYSIGNL)
++# AC_DEFINE(HAVE_COSL)
++# AC_DEFINE(HAVE_COSHL)
++# AC_DEFINE(HAVE_EXPL)
++# AC_DEFINE(HAVE_FABSL)
++# AC_DEFINE(HAVE_FINITEL)
++# AC_DEFINE(HAVE_FLOORL)
++# AC_DEFINE(HAVE_FMODL)
++# AC_DEFINE(HAVE_FREXPL)
++# AC_DEFINE(HAVE_HYPOTL)
++# AC_DEFINE(HAVE_ISINFL)
++# AC_DEFINE(HAVE_ISNANL)
++# AC_DEFINE(HAVE_LOGL)
++# AC_DEFINE(HAVE_LOG10L)
++# AC_DEFINE(HAVE_MODFL)
++# AC_DEFINE(HAVE_POWL)
++# AC_DEFINE(HAVE_SINL)
++# AC_DEFINE(HAVE_SINHL)
++# AC_DEFINE(HAVE_SINCOSL)
++# AC_DEFINE(HAVE_SQRTL)
++# AC_DEFINE(HAVE_TANL)
++# AC_DEFINE(HAVE_TANHL)
++ fi
++ ;;
+ *-linux* | *-uclinux* | *-gnu* | *-kfreebsd*-gnu | *-knetbsd*-gnu)
+ AC_CHECK_HEADERS([nan.h ieeefp.h endian.h sys/isa_defs.h \
+ machine/endian.h machine/param.h sys/machine.h sys/types.h \
+@@ -152,7 +245,7 @@
+ AC_DEFINE(HAVE_INT64_T)
+ case "$target" in
+ *-uclinux*)
+- # Don't enable LFS with uClibc
++ # Don't enable LFS with uClinux
+ ;;
+ *)
+ AC_DEFINE(_GLIBCXX_USE_LFS)
+diff -urN gcc-3.4.2-dist/libstdc++-v3/include/c_compatibility/wchar.h gcc-3.4.2/libstdc++-v3/include/c_compatibility/wchar.h
+--- gcc-3.4.2-dist/libstdc++-v3/include/c_compatibility/wchar.h 2003-12-08 21:51:45.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/include/c_compatibility/wchar.h 2004-09-10 10:47:40.000000000 -0500
+@@ -101,7 +101,9 @@
+ using std::wmemcpy;
+ using std::wmemmove;
+ using std::wmemset;
++#if _GLIBCXX_HAVE_WCSFTIME
+ using std::wcsftime;
++#endif
+
+ #if _GLIBCXX_USE_C99
+ using std::wcstold;
+diff -urN gcc-3.4.2-dist/libstdc++-v3/include/c_std/std_cwchar.h gcc-3.4.2/libstdc++-v3/include/c_std/std_cwchar.h
+--- gcc-3.4.2-dist/libstdc++-v3/include/c_std/std_cwchar.h 2004-07-20 03:52:12.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/include/c_std/std_cwchar.h 2004-09-10 10:47:40.000000000 -0500
+@@ -179,7 +179,9 @@
+ using ::wcscoll;
+ using ::wcscpy;
+ using ::wcscspn;
++#if _GLIBCXX_HAVE_WCSFTIME
+ using ::wcsftime;
++#endif
+ using ::wcslen;
+ using ::wcsncat;
+ using ::wcsncmp;
diff --git a/toolchain/gcc/patches/3.4.5/300-libstdc++-pic.patch b/toolchain/gcc/patches/3.4.5/300-libstdc++-pic.patch
new file mode 100644
index 0000000000..c030ba6205
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.5/300-libstdc++-pic.patch
@@ -0,0 +1,47 @@
+# DP: Build and install libstdc++_pic.a library.
+
+--- gcc/libstdc++-v3/src/Makefile.am~ 2003-02-28 09:21:05.000000000 +0100
++++ gcc/libstdc++-v3/src/Makefile.am 2003-02-28 09:28:50.000000000 +0100
+@@ -224,6 +224,10 @@
+ @OPT_LDFLAGS@ @SECTION_LDFLAGS@ $(AM_CXXFLAGS) $(LDFLAGS) -o $@
+
+
++install-exec-local:
++ $(AR) cru libstdc++_pic.a .libs/*.o $(top_builddir)/libsupc++/*.o
++ $(INSTALL_DATA) libstdc++_pic.a $(DESTDIR)$(toolexeclibdir)
++
+ # Added bits to build debug library.
+ if GLIBCPP_BUILD_DEBUG
+ all-local: build_debug
+
+--- gcc/libstdc++-v3/src/Makefile.in~ 2004-02-21 09:55:48.000000000 +0100
++++ gcc/libstdc++-v3/src/Makefile.in 2004-02-21 09:59:34.000000000 +0100
+@@ -585,7 +585,7 @@
+
+ install-data-am: install-data-local
+
+-install-exec-am: install-toolexeclibLTLIBRARIES
++install-exec-am: install-toolexeclibLTLIBRARIES install-exec-local
+
+ install-info: install-info-am
+
+@@ -618,6 +618,7 @@
+ distclean-tags distdir dvi dvi-am info info-am install \
+ install-am install-data install-data-am install-data-local \
+ install-exec install-exec-am install-info install-info-am \
++ install-exec-local \
+ install-man install-strip install-toolexeclibLTLIBRARIES \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+@@ -707,6 +708,11 @@
+ install_debug:
+ (cd ${debugdir} && $(MAKE) \
+ toolexeclibdir=$(glibcxx_toolexeclibdir)/debug install)
++
++install-exec-local:
++ $(AR) cru libstdc++_pic.a .libs/*.o $(top_builddir)/libsupc++/*.o
++ $(INSTALL_DATA) libstdc++_pic.a $(DESTDIR)$(toolexeclibdir)
++
+ # 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/toolchain/gcc/patches/3.4.5/600-gcc34-arm-ldm-peephole.patch b/toolchain/gcc/patches/3.4.5/600-gcc34-arm-ldm-peephole.patch
new file mode 100644
index 0000000000..0c370502c8
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.5/600-gcc34-arm-ldm-peephole.patch
@@ -0,0 +1,65 @@
+--- gcc-3.4.0/gcc/config/arm/arm.md.arm-ldm-peephole 2004-01-13 08:24:37.000000000 -0500
++++ gcc-3.4.0/gcc/config/arm/arm.md 2004-04-24 18:18:04.000000000 -0400
+@@ -8810,13 +8810,16 @@
+ (set_attr "length" "4,8,8")]
+ )
+
++; Try to convert LDR+LDR+arith into [add+]LDM+arith
++; On XScale, LDM is always slower than two LDRs, so only do this if
++; optimising for size.
+ (define_insn "*arith_adjacentmem"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (match_operator:SI 1 "shiftable_operator"
+ [(match_operand:SI 2 "memory_operand" "m")
+ (match_operand:SI 3 "memory_operand" "m")]))
+ (clobber (match_scratch:SI 4 "=r"))]
+- "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
++ "TARGET_ARM && (!arm_tune_xscale || optimize_size) && adjacent_mem_locations (operands[2], operands[3])"
+ "*
+ {
+ rtx ldm[3];
+@@ -8851,6 +8854,8 @@
+ }
+ if (val1 && val2)
+ {
++ /* This would be a loss on a Harvard core, but adjacent_mem_locations()
++ will prevent it from happening. */
+ rtx ops[3];
+ ldm[0] = ops[0] = operands[4];
+ ops[1] = XEXP (XEXP (operands[2], 0), 0);
+--- gcc-3.4.0/gcc/config/arm/arm.c.arm-ldm-peephole 2004-04-24 18:16:25.000000000 -0400
++++ gcc-3.4.0/gcc/config/arm/arm.c 2004-04-24 18:18:04.000000000 -0400
+@@ -4838,6 +4841,11 @@
+ *load_offset = unsorted_offsets[order[0]];
+ }
+
++ /* For XScale a two-word LDM is a performance loss, so only do this if
++ size is more important. See comments in arm_gen_load_multiple. */
++ if (nops == 2 && arm_tune_xscale && !optimize_size)
++ return 0;
++
+ if (unsorted_offsets[order[0]] == 0)
+ return 1; /* ldmia */
+
+@@ -5064,6 +5072,11 @@
+ *load_offset = unsorted_offsets[order[0]];
+ }
+
++ /* For XScale a two-word LDM is a performance loss, so only do this if
++ size is more important. See comments in arm_gen_load_multiple. */
++ if (nops == 2 && arm_tune_xscale && !optimize_size)
++ return 0;
++
+ if (unsorted_offsets[order[0]] == 0)
+ return 1; /* stmia */
+
+--- gcc-3.4.0/gcc/genpeep.c.arm-ldm-peephole 2003-07-05 01:27:22.000000000 -0400
++++ gcc-3.4.0/gcc/genpeep.c 2004-04-24 18:18:04.000000000 -0400
+@@ -381,6 +381,7 @@
+ printf ("#include \"recog.h\"\n");
+ printf ("#include \"except.h\"\n\n");
+ printf ("#include \"function.h\"\n\n");
++ printf ("#include \"flags.h\"\n\n");
+
+ printf ("#ifdef HAVE_peephole\n");
+ printf ("extern rtx peep_operand[];\n\n");
diff --git a/toolchain/gcc/patches/3.4.5/601-gcc34-arm-ldm-peephole2.patch b/toolchain/gcc/patches/3.4.5/601-gcc34-arm-ldm-peephole2.patch
new file mode 100644
index 0000000000..27f7c07db9
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.5/601-gcc34-arm-ldm-peephole2.patch
@@ -0,0 +1,42 @@
+The 30_all_gcc34-arm-ldm-peephole.patch from Debian was conflicting
+with the newer 36_all_pr16201-fix.patch, so i cut out the hunk from
+it that was causing problems and grabbed an updated version from
+upstream cvs.
+
+Index: gcc/config/arm/arm.c
+===================================================================
+RCS file: /cvsroot/gcc/gcc/gcc/config/arm/arm.c,v
+retrieving revision 1.432
+retrieving revision 1.433
+diff -u -r1.432 -r1.433
+--- gcc-3.4.4/gcc/config/arm/arm.c 29 Mar 2005 03:00:23 -0000 1.432
++++ gcc-3.4.4/gcc/config/arm/arm.c 1 Apr 2005 11:02:22 -0000 1.433
+@@ -5139,6 +5139,10 @@
+ int
+ adjacent_mem_locations (rtx a, rtx b)
+ {
++ /* We don't guarantee to preserve the order of these memory refs. */
++ if (volatile_refs_p (a) || volatile_refs_p (b))
++ return 0;
++
+ if ((GET_CODE (XEXP (a, 0)) == REG
+ || (GET_CODE (XEXP (a, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (a, 0), 1)) == CONST_INT))
+@@ -5178,6 +5182,17 @@
+ return 0;
+
+ val_diff = val1 - val0;
++
++ if (arm_ld_sched)
++ {
++ /* If the target has load delay slots, then there's no benefit
++ to using an ldm instruction unless the offset is zero and
++ we are optimizing for size. */
++ return (optimize_size && (REGNO (reg0) == REGNO (reg1))
++ && (val0 == 0 || val1 == 0 || val0 == 4 || val1 == 4)
++ && (val_diff == 4 || val_diff == -4));
++ }
++
+ return ((REGNO (reg0) == REGNO (reg1))
+ && (val_diff == 4 || val_diff == -4));
+ }
diff --git a/toolchain/gcc/patches/3.4.5/601-gcc34-arm-ldm.patch b/toolchain/gcc/patches/3.4.5/601-gcc34-arm-ldm.patch
new file mode 100644
index 0000000000..142052fdf0
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.5/601-gcc34-arm-ldm.patch
@@ -0,0 +1,119 @@
+--- gcc-3.4.0/gcc/config/arm/arm.c.arm-ldm 2004-02-27 09:51:05.000000000 -0500
++++ gcc-3.4.0/gcc/config/arm/arm.c 2004-04-24 18:16:25.000000000 -0400
+@@ -8520,6 +8520,26 @@
+ return_used_this_function = 0;
+ }
+
++/* Return the number (counting from 0) of
++ the least significant set bit in MASK. */
++
++#ifdef __GNUC__
++inline
++#endif
++static int
++number_of_first_bit_set (mask)
++ int mask;
++{
++ int bit;
++
++ for (bit = 0;
++ (mask & (1 << bit)) == 0;
++ ++bit)
++ continue;
++
++ return bit;
++}
++
+ const char *
+ arm_output_epilogue (rtx sibling)
+ {
+@@ -8753,27 +8773,47 @@
+ saved_regs_mask |= (1 << PC_REGNUM);
+ }
+
+- /* Load the registers off the stack. If we only have one register
+- to load use the LDR instruction - it is faster. */
+- if (saved_regs_mask == (1 << LR_REGNUM))
+- {
+- /* The exception handler ignores the LR, so we do
+- not really need to load it off the stack. */
+- if (eh_ofs)
+- asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
+- else
+- asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM);
+- }
+- else if (saved_regs_mask)
++ if (saved_regs_mask)
+ {
+- if (saved_regs_mask & (1 << SP_REGNUM))
+- /* Note - write back to the stack register is not enabled
+- (ie "ldmfd sp!..."). We know that the stack pointer is
+- in the list of registers and if we add writeback the
+- instruction becomes UNPREDICTABLE. */
+- print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
++ /* Load the registers off the stack. If we only have one register
++ to load use the LDR instruction - it is faster. */
++ if (bit_count (saved_regs_mask) == 1)
++ {
++ int reg = number_of_first_bit_set (saved_regs_mask);
++
++ switch (reg)
++ {
++ case SP_REGNUM:
++ /* Mustn't use base writeback when loading SP. */
++ asm_fprintf (f, "\tldr\t%r, [%r]\n", SP_REGNUM, SP_REGNUM);
++ break;
++
++ case LR_REGNUM:
++ if (eh_ofs)
++ {
++ /* The exception handler ignores the LR, so we do
++ not really need to load it off the stack. */
++ asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
++ break;
++ }
++ /* else fall through */
++
++ default:
++ asm_fprintf (f, "\tldr\t%r, [%r], #4\n", reg, SP_REGNUM);
++ break;
++ }
++ }
+ else
+- print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
++ {
++ if (saved_regs_mask & (1 << SP_REGNUM))
++ /* Note - write back to the stack register is not enabled
++ (ie "ldmfd sp!..."). We know that the stack pointer is
++ in the list of registers and if we add writeback the
++ instruction becomes UNPREDICTABLE. */
++ print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
++ else
++ print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
++ }
+ }
+
+ if (current_function_pretend_args_size)
+@@ -11401,22 +11441,6 @@
+ }
+ }
+
+-/* Return the number (counting from 0) of
+- the least significant set bit in MASK. */
+-
+-inline static int
+-number_of_first_bit_set (int mask)
+-{
+- int bit;
+-
+- for (bit = 0;
+- (mask & (1 << bit)) == 0;
+- ++bit)
+- continue;
+-
+- return bit;
+-}
+-
+ /* Generate code to return from a thumb function.
+ If 'reg_containing_return_addr' is -1, then the return address is
+ actually on the stack, at the stack pointer. */
diff --git a/toolchain/gcc/patches/3.4.5/602-sdk-libstdc++-includes.patch b/toolchain/gcc/patches/3.4.5/602-sdk-libstdc++-includes.patch
new file mode 100644
index 0000000000..4377c2143b
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.5/602-sdk-libstdc++-includes.patch
@@ -0,0 +1,22 @@
+--- gcc-3.4.1/libstdc++-v3/libmath/Makefile.am~ 2003-08-27 22:29:42.000000000 +0100
++++ gcc-3.4.1/libstdc++-v3/libmath/Makefile.am 2004-07-22 16:41:45.152130128 +0100
+@@ -32,7 +32,7 @@
+
+ libmath_la_SOURCES = stubs.c
+
+-AM_CPPFLAGS = $(CANADIAN_INCLUDES)
++AM_CPPFLAGS = $(CANADIAN_INCLUDES) -I$(toplevel_srcdir)/include
+
+ # Only compiling "C" sources in this directory.
+ LIBTOOL = @LIBTOOL@ --tag CC
+--- gcc-3.4.1/libstdc++-v3/fragment.am.old 2004-07-22 18:24:58.024083656 +0100
++++ gcc-3.4.1/libstdc++-v3/fragment.am 2004-07-22 18:24:59.019932264 +0100
+@@ -18,7 +18,7 @@
+ $(WARN_FLAGS) $(WERROR) -fdiagnostics-show-location=once
+
+ # -I/-D flags to pass when compiling.
+-AM_CPPFLAGS = $(GLIBCXX_INCLUDES)
++AM_CPPFLAGS = $(GLIBCXX_INCLUDES) -I$(toplevel_srcdir)/include
+
+
+
diff --git a/toolchain/gcc/patches/3.4.5/700-pr15068-fix.patch b/toolchain/gcc/patches/3.4.5/700-pr15068-fix.patch
new file mode 100644
index 0000000000..2977765c5f
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.5/700-pr15068-fix.patch
@@ -0,0 +1,44 @@
+See http://gcc.gnu.org/PR15068
+
+Fixes error
+
+../sysdeps/generic/s_fmax.c: In function `__fmax':
+../sysdeps/generic/s_fmax.c:28: internal compiler error: in elim_reg_cond, at flow.c:3257
+Please submit a full bug report,
+with preprocessed source if appropriate.
+See <URL:http://gcc.gnu.org/bugs.html> for instructions.
+make[2]: *** [/home/dank/wk/crosstool-0.28-rc35/build/arm-unknown-linux-gnu/gcc-3.4.1-glibc-20040822/build-glibc/math/s_fmax.o] Error 1
+make[2]: Leaving directory `/home/dank/wk/crosstool-0.28-rc35/build/arm-unknown-linux-gnu/gcc-3.4.1-glibc-20040822/glibc-20040822/math'
+make[1]: *** [math/others] Error 2
+make[1]: Leaving directory `/home/dank/wk/crosstool-0.28-rc35/build/arm-unknown-linux-gnu/gcc-3.4.1-glibc-20040822/glibc-20040822'
+make: *** [all] Error 2
+
+[ rediffed against gcc-3.4.1, with elbow grease, ending up with same thing as
+http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/flow.c.diff?cvsroot=gcc&only_with_tag=csl-arm-branch&r1=1.563.4.2&r2=1.563.4.3 ]
+
+--- gcc-3.4.1/gcc/flow.c.old 2004-02-27 19:39:19.000000000 -0800
++++ gcc-3.4.1/gcc/flow.c 2004-08-26 07:29:46.000000000 -0700
+@@ -1878,6 +1878,7 @@
+ rtx set_src = SET_SRC (pc_set (BB_END (bb)));
+ rtx cond_true = XEXP (set_src, 0);
+ rtx reg = XEXP (cond_true, 0);
++ enum rtx_code inv_cond;
+
+ if (GET_CODE (reg) == SUBREG)
+ reg = SUBREG_REG (reg);
+@@ -1886,11 +1887,13 @@
+ in the form of a comparison of a register against zero.
+ If the condition is more complex than that, then it is safe
+ not to record any information. */
+- if (GET_CODE (reg) == REG
++ inv_cond = reversed_comparison_code (cond_true, BB_END (bb));
++ if (inv_cond != UNKNOWN
++ && GET_CODE (reg) == REG
+ && XEXP (cond_true, 1) == const0_rtx)
+ {
+ rtx cond_false
+- = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond_true)),
++ = gen_rtx_fmt_ee (inv_cond,
+ GET_MODE (cond_true), XEXP (cond_true, 0),
+ XEXP (cond_true, 1));
+ if (GET_CODE (XEXP (set_src, 1)) == PC)
diff --git a/toolchain/gcc/patches/3.4.5/71_all_sh-pr16665-fix.patch b/toolchain/gcc/patches/3.4.5/71_all_sh-pr16665-fix.patch
new file mode 100644
index 0000000000..680bb3978d
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.5/71_all_sh-pr16665-fix.patch
@@ -0,0 +1,43 @@
+--- gcc/gcc/config/sh/sh.c
++++ gcc/gcc/config/sh/sh.c
+@@ -9106,6 +9106,15 @@ sh_output_mi_thunk (FILE *file, tree thu
+ }
+ this = FUNCTION_ARG (cum, Pmode, ptr_type_node, 1);
+
++ /* In PIC case, we set PIC register to compute the target address. We
++ can use a scratch register to save and restore the original value
++ except for SHcompact. For SHcompact, use stack. */
++ if (flag_pic && TARGET_SHCOMPACT)
++ {
++ push (PIC_OFFSET_TABLE_REGNUM);
++ emit_insn (gen_GOTaddr2picreg ());
++ }
++
+ /* For SHcompact, we only have r0 for a scratch register: r1 is the
+ static chain pointer (even if you can't have nested virtual functions
+ right now, someone might implement them sometime), and the rest of the
+@@ -9188,8 +9197,24 @@ sh_output_mi_thunk (FILE *file, tree thu
+ assemble_external (function);
+ TREE_USED (function) = 1;
+ }
++ /* We can use scratch1 to save and restore the original value of
++ PIC register except for SHcompact. */
++ if (flag_pic && ! TARGET_SHCOMPACT)
++ {
++ emit_move_insn (scratch1,
++ gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM));
++ emit_insn (gen_GOTaddr2picreg ());
++ }
+ funexp = XEXP (DECL_RTL (function), 0);
+ emit_move_insn (scratch2, funexp);
++ if (flag_pic)
++ {
++ if (! TARGET_SHCOMPACT)
++ emit_move_insn (gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM),
++ scratch1);
++ else
++ pop (PIC_OFFSET_TABLE_REGNUM);
++ }
+ funexp = gen_rtx_MEM (FUNCTION_MODE, scratch2);
+ sibcall = emit_call_insn (gen_sibcall (funexp, const0_rtx, NULL_RTX));
+ SIBLING_CALL_P (sibcall) = 1;
diff --git a/toolchain/gcc/patches/3.4.5/72_all_sh-no-reorder-blocks.patch b/toolchain/gcc/patches/3.4.5/72_all_sh-no-reorder-blocks.patch
new file mode 100644
index 0000000000..8b9826831b
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.5/72_all_sh-no-reorder-blocks.patch
@@ -0,0 +1,13 @@
+--- g/gcc/config/sh/sh.h
++++ g/gcc/config/sh/sh.h
+@@ -422,6 +422,10 @@
+ do { \
+ if (LEVEL) \
+ flag_omit_frame_pointer = -1; \
++ if (LEVEL <= 2) \
++ { \
++ flag_reorder_blocks = 0; \
++ } \
+ if (SIZE) \
+ target_flags |= SPACE_BIT; \
+ if (TARGET_SHMEDIA && LEVEL > 1) \
diff --git a/toolchain/gcc/patches/3.4.5/73_all_sh-pr20617.patch b/toolchain/gcc/patches/3.4.5/73_all_sh-pr20617.patch
new file mode 100644
index 0000000000..6d8021cc70
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.5/73_all_sh-pr20617.patch
@@ -0,0 +1,28 @@
+2005-03-24 J"orn Rennecke <joern.rennecke@st.com>
+
+ Band aid for PR target/20617:
+ * config/sh/lib1funcs.asm (FUNC, ALIAS): Add .hidden directive.
+
+--- g/gcc/config/sh/lib1funcs.asm
++++ g/gcc/config/sh/lib1funcs.asm
+@@ -37,9 +37,19 @@ Boston, MA 02111-1307, USA. */
+ ELF local label prefixes by J"orn Rennecke
+ amylaar@cygnus.com */
+
++#define ALIAS(X,Y) .global GLOBAL(X); .set GLOBAL(X),GLOBAL(Y)
++
+ #ifdef __ELF__
+ #define LOCAL(X) .L_##X
+-#define FUNC(X) .type X,@function
++
++#if 1 /* ??? The export list mechanism is broken, everything that is not
++ hidden is exported. */
++#undef FUNC
++#define FUNC(X) .type X,@function; .hidden X
++#undef ALIAS
++#define ALIAS(X,Y) .global GLOBAL(X); .set GLOBAL(X),GLOBAL(Y); .hidden GLOBAL(X)
++#endif
++
+ #define ENDFUNC0(X) .Lfe_##X: .size X,.Lfe_##X-X
+ #define ENDFUNC(X) ENDFUNC0(X)
+ #else
diff --git a/toolchain/gcc/patches/3.4.5/800-arm-bigendian.patch b/toolchain/gcc/patches/3.4.5/800-arm-bigendian.patch
new file mode 100644
index 0000000000..0bae8f474c
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.5/800-arm-bigendian.patch
@@ -0,0 +1,70 @@
+By Lennert Buytenhek <buytenh@wantstofly.org>
+Adds support for arm*b-linux* big-endian ARM targets
+
+See http://gcc.gnu.org/PR16350
+
+diff -urN gcc-3.4.1-dist/gcc/config/arm/linux-elf.h gcc-3.4.1/gcc/config/arm/linux-elf.h
+--- gcc-3.4.1-dist/gcc/config/arm/linux-elf.h 2004-08-16 16:01:50.000000000 -0500
++++ gcc-3.4.1/gcc/config/arm/linux-elf.h 2004-08-16 15:43:40.000000000 -0500
+@@ -30,17 +30,34 @@
+ /* Do not assume anything about header files. */
+ #define NO_IMPLICIT_EXTERN_C
+
++/*
++ * 'config.gcc' defines TARGET_BIG_ENDIAN_DEFAULT as 1 for arm*b-*
++ * (big endian) configurations.
++ */
++#if TARGET_BIG_ENDIAN_DEFAULT
++#define TARGET_ENDIAN_DEFAULT ARM_FLAG_BIG_END
++#define TARGET_ENDIAN_OPTION "mbig-endian"
++#define TARGET_LINKER_EMULATION "armelfb_linux"
++#else
++#define TARGET_ENDIAN_DEFAULT 0
++#define TARGET_ENDIAN_OPTION "mlittle-endian"
++#define TARGET_LINKER_EMULATION "armelf_linux"
++#endif
++
+ /* Default is to use APCS-32 mode. */
+ #undef TARGET_DEFAULT
+-#define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_MMU_TRAPS)
++#define TARGET_DEFAULT \
++ ( ARM_FLAG_APCS_32 | \
++ ARM_FLAG_MMU_TRAPS | \
++ TARGET_ENDIAN_DEFAULT )
+
+ #define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6
+
+-#define SUBTARGET_EXTRA_LINK_SPEC " -m armelf_linux -p"
++#define SUBTARGET_EXTRA_LINK_SPEC " -m " TARGET_LINKER_EMULATION " -p"
+
+ #undef MULTILIB_DEFAULTS
+ #define MULTILIB_DEFAULTS \
+- { "marm", "mlittle-endian", "mhard-float", "mapcs-32", "mno-thumb-interwork" }
++ { "marm", TARGET_ENDIAN_OPTION, "mhard-float", "mapcs-32", "mno-thumb-interwork" }
+
+ #define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
+
+@@ -101,7 +118,7 @@
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2} \
+ -X \
+- %{mbig-endian:-EB}" \
++ %{mbig-endian:-EB} %{mlittle-endian:-EL}" \
+ SUBTARGET_EXTRA_LINK_SPEC
+ #endif
+
+diff -urN gcc-3.4.1-dist/gcc/config.gcc gcc-3.4.1/gcc/config.gcc
+--- gcc-3.4.1-dist/gcc/config.gcc 2004-08-16 16:01:50.000000000 -0500
++++ gcc-3.4.1/gcc/config.gcc 2004-08-16 16:01:25.000000000 -0500
+@@ -672,6 +672,11 @@
+ ;;
+ arm*-*-linux*) # ARM GNU/Linux with ELF
+ tm_file="dbxelf.h elfos.h linux.h arm/elf.h arm/linux-gas.h arm/linux-elf.h arm/aout.h arm/arm.h"
++ case $target in
++ arm*b-*)
++ tm_defines="TARGET_BIG_ENDIAN_DEFAULT=1 $tm_defines"
++ ;;
++ esac
+ tmake_file="t-slibgcc-elf-ver t-linux arm/t-linux"
+ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
+ gnu_ld=yes
diff --git a/toolchain/gcc/patches/3.4.5/800-powerpc-libc_stack_end-uclibc.patch b/toolchain/gcc/patches/3.4.5/800-powerpc-libc_stack_end-uclibc.patch
new file mode 100644
index 0000000000..a209470f7a
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.5/800-powerpc-libc_stack_end-uclibc.patch
@@ -0,0 +1,15 @@
+--- gcc-3.4.4/gcc/config/rs6000/linux-unwind.h.org 2005-06-23 17:50:34.000000000 -0600
++++ gcc-3.4.4/gcc/config/rs6000/linux-unwind.h 2005-06-23 17:52:02.000000000 -0600
+@@ -32,6 +32,7 @@
+ these structs elsewhere; Many fields are missing, particularly
+ from the end of the structures. */
+
++#ifndef inhibit_libc
+ struct gcc_vregs
+ {
+ __attribute__ ((vector_size (16))) int vr[32];
+@@ -320,3 +321,4 @@
+ \
+ goto SUCCESS; \
+ } while (0)
++#endif
diff --git a/toolchain/gcc/patches/3.4.6-nonmips/001-non_mips.patch b/toolchain/gcc/patches/3.4.6-nonmips/001-non_mips.patch
new file mode 100644
index 0000000000..5de77a4419
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.6-nonmips/001-non_mips.patch
@@ -0,0 +1,85 @@
+diff -urN gcc-3.4.6/gcc/config/mips/mips.c gcc-3.4.6-nonmips/gcc/config/mips/mips.c
+--- gcc-3.4.6/gcc/config/mips/mips.c 2005-07-31 10:35:15.000000000 +0200
++++ gcc-3.4.6-nonmips/gcc/config/mips/mips.c 2006-07-19 20:25:03.000000000 +0200
+@@ -3466,26 +3466,26 @@
+ for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
+ {
+ regs[i] = gen_reg_rtx (mode);
+- if (MEM_ALIGN (src) >= bits)
++ //if (MEM_ALIGN (src) >= bits)
+ emit_move_insn (regs[i], adjust_address (src, mode, offset));
+- else
+- {
+- rtx part = adjust_address (src, BLKmode, offset);
+- if (!mips_expand_unaligned_load (regs[i], part, bits, 0))
+- abort ();
+- }
++ //else
++ //{
++ //rtx part = adjust_address (src, BLKmode, offset);
++ //if (!mips_expand_unaligned_load (regs[i], part, bits, 0))
++ //abort ();
++ //}
+ }
+
+ /* Copy the chunks to the destination. */
+ for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
+- if (MEM_ALIGN (dest) >= bits)
++ //if (MEM_ALIGN (dest) >= bits)
+ emit_move_insn (adjust_address (dest, mode, offset), regs[i]);
+- else
+- {
+- rtx part = adjust_address (dest, BLKmode, offset);
+- if (!mips_expand_unaligned_store (part, regs[i], bits, 0))
+- abort ();
+- }
++ //else
++ //{
++ //rtx part = adjust_address (dest, BLKmode, offset);
++ //if (!mips_expand_unaligned_store (part, regs[i], bits, 0))
++ //abort ();
++ //}
+
+ /* Mop up any left-over bytes. */
+ if (offset < length)
+@@ -4488,6 +4488,7 @@
+ mips_expand_unaligned_load (rtx dest, rtx src, unsigned int width, int bitpos)
+ {
+ rtx left, right, temp;
++ return false;
+
+ /* If TARGET_64BIT, the destination of a 32-bit load will be a
+ paradoxical word_mode subreg. This is the only case in which
+@@ -4514,8 +4515,9 @@
+ }
+ else
+ {
+- emit_insn (gen_mov_lwl (temp, src, left));
+- emit_insn (gen_mov_lwr (dest, copy_rtx (src), right, temp));
++ return false;
++ //emit_insn (gen_mov_lwl (temp, src, left));
++ //emit_insn (gen_mov_lwr (dest, copy_rtx (src), right, temp));
+ }
+ return true;
+ }
+@@ -4528,6 +4530,7 @@
+ mips_expand_unaligned_store (rtx dest, rtx src, unsigned int width, int bitpos)
+ {
+ rtx left, right;
++ return false;
+
+ if (!mips_get_unaligned_mem (&dest, width, bitpos, &left, &right))
+ return false;
+@@ -4541,8 +4544,10 @@
+ }
+ else
+ {
+- emit_insn (gen_mov_swl (dest, src, left));
+- emit_insn (gen_mov_swr (copy_rtx (dest), copy_rtx (src), right));
++ /* Patented instructions */
++ //emit_insn (gen_mov_swl (dest, src, left));
++ //emit_insn (gen_mov_swr (copy_rtx (dest), copy_rtx (src), right));
++ return false;
+ }
+ return true;
+ }
diff --git a/toolchain/gcc/patches/3.4.6-nonmips/100-uclibc-conf.patch b/toolchain/gcc/patches/3.4.6-nonmips/100-uclibc-conf.patch
new file mode 100644
index 0000000000..29e4c802e2
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.6-nonmips/100-uclibc-conf.patch
@@ -0,0 +1,442 @@
+diff -urN gcc-3.4.1-dist/boehm-gc/configure gcc-3.4.1/boehm-gc/configure
+--- gcc-3.4.1-dist/boehm-gc/configure 2004-07-01 14:14:03.000000000 -0500
++++ gcc-3.4.1/boehm-gc/configure 2004-08-12 16:22:57.000000000 -0500
+@@ -1947,6 +1947,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+diff -urN gcc-3.4.1-dist/boehm-gc/ltconfig gcc-3.4.1/boehm-gc/ltconfig
+--- gcc-3.4.1-dist/boehm-gc/ltconfig 2002-11-20 09:59:06.000000000 -0600
++++ gcc-3.4.1/boehm-gc/ltconfig 2004-08-12 15:54:42.000000000 -0500
+@@ -1981,6 +1981,23 @@
+ fi
+ ;;
+
++linux-uclibc*)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
++ soname_spec='${libname}${release}.so$major'
++ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
++ file_magic_cmd=/usr/bin/file
++ file_magic_test_file=`echo /lib/libuClibc-*.so`
++
++ # Assume using the uClibc dynamic linker.
++ dynamic_linker="uClibc ld.so"
++ ;;
++
+ netbsd*)
+ version_type=sunos
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+diff -urN gcc-3.4.1-dist/gcc/config/arm/linux-elf.h gcc-3.4.1/gcc/config/arm/linux-elf.h
+--- gcc-3.4.1-dist/gcc/config/arm/linux-elf.h 2004-01-31 00:18:11.000000000 -0600
++++ gcc-3.4.1/gcc/config/arm/linux-elf.h 2004-08-12 15:54:42.000000000 -0500
+@@ -81,6 +81,18 @@
+ "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
+
+ #undef LINK_SPEC
++#ifdef USE_UCLIBC
++#define LINK_SPEC "%{h*} %{version:-v} \
++ %{b} %{Wl,*:%*} \
++ %{static:-Bstatic} \
++ %{shared:-shared} \
++ %{symbolic:-Bsymbolic} \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0} \
++ -X \
++ %{mbig-endian:-EB}" \
++ SUBTARGET_EXTRA_LINK_SPEC
++#else
+ #define LINK_SPEC "%{h*} %{version:-v} \
+ %{b} %{Wl,*:%*} \
+ %{static:-Bstatic} \
+@@ -91,6 +103,7 @@
+ -X \
+ %{mbig-endian:-EB}" \
+ SUBTARGET_EXTRA_LINK_SPEC
++#endif
+
+ #define TARGET_OS_CPP_BUILTINS() LINUX_TARGET_OS_CPP_BUILTINS()
+
+diff -urN gcc-3.4.1-dist/gcc/config/cris/linux.h gcc-3.4.1/gcc/config/cris/linux.h
+--- gcc-3.4.1-dist/gcc/config/cris/linux.h 2003-11-28 21:08:09.000000000 -0600
++++ gcc-3.4.1/gcc/config/cris/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -79,6 +79,25 @@
+ #undef CRIS_DEFAULT_CPU_VERSION
+ #define CRIS_DEFAULT_CPU_VERSION CRIS_CPU_NG
+
++#ifdef USE_UCLIBC
++
++#undef CRIS_SUBTARGET_VERSION
++#define CRIS_SUBTARGET_VERSION " - cris-axis-linux-uclibc"
++
++#undef CRIS_LINK_SUBTARGET_SPEC
++#define CRIS_LINK_SUBTARGET_SPEC \
++ "-mcrislinux\
++ -rpath-link include/asm/../..%s\
++ %{shared} %{static}\
++ %{symbolic:-Bdynamic} %{shlib:-Bdynamic} %{static:-Bstatic}\
++ %{!shared: \
++ %{!static: \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}}} \
++ %{!r:%{O2|O3: --gc-sections}}"
++
++#else /* USE_UCLIBC */
++
+ #undef CRIS_SUBTARGET_VERSION
+ #define CRIS_SUBTARGET_VERSION " - cris-axis-linux-gnu"
+
+@@ -93,6 +112,8 @@
+ %{!shared:%{!static:%{rdynamic:-export-dynamic}}}\
+ %{!r:%{O2|O3: --gc-sections}}"
+
++#endif /* USE_UCLIBC */
++
+
+ /* Node: Run-time Target */
+
+diff -urN gcc-3.4.1-dist/gcc/config/cris/t-linux-uclibc gcc-3.4.1/gcc/config/cris/t-linux-uclibc
+--- gcc-3.4.1-dist/gcc/config/cris/t-linux-uclibc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.1/gcc/config/cris/t-linux-uclibc 2004-08-12 15:54:43.000000000 -0500
+@@ -0,0 +1,3 @@
++T_CFLAGS = -DUSE_UCLIBC
++TARGET_LIBGCC2_CFLAGS += -fPIC
++CRTSTUFF_T_CFLAGS_S = $(TARGET_LIBGCC2_CFLAGS)
+diff -urN gcc-3.4.1-dist/gcc/config/i386/linux.h gcc-3.4.1/gcc/config/i386/linux.h
+--- gcc-3.4.1-dist/gcc/config/i386/linux.h 2003-11-28 21:08:10.000000000 -0600
++++ gcc-3.4.1/gcc/config/i386/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -118,6 +118,15 @@
+ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \
+ %{static:-static}}}"
+ #else
++#if defined USE_UCLIBC
++#define LINK_SPEC "-m elf_i386 %{shared:-shared} \
++ %{!shared: \
++ %{!ibcs: \
++ %{!static: \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}} \
++ %{static:-static}}}"
++#else
+ #define LINK_SPEC "-m elf_i386 %{shared:-shared} \
+ %{!shared: \
+ %{!ibcs: \
+@@ -126,6 +135,7 @@
+ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
+ %{static:-static}}}"
+ #endif
++#endif
+
+ /* A C statement (sans semicolon) to output to the stdio stream
+ FILE the assembler definition of uninitialized global DECL named
+diff -urN gcc-3.4.1-dist/gcc/config/mips/linux.h gcc-3.4.1/gcc/config/mips/linux.h
+--- gcc-3.4.1-dist/gcc/config/mips/linux.h 2004-06-15 20:42:24.000000000 -0500
++++ gcc-3.4.1/gcc/config/mips/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -109,6 +109,17 @@
+
+ /* Borrowed from sparc/linux.h */
+ #undef LINK_SPEC
++#ifdef USE_UCLIBC
++#define LINK_SPEC \
++ "%(endian_spec) \
++ %{shared:-shared} \
++ %{!shared: \
++ %{!ibcs: \
++ %{!static: \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}} \
++ %{static:-static}}}"
++#else
+ #define LINK_SPEC \
+ "%(endian_spec) \
+ %{shared:-shared} \
+@@ -118,6 +129,7 @@
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}} \
+ %{static:-static}}}"
++#endif
+
+ #undef SUBTARGET_ASM_SPEC
+ #define SUBTARGET_ASM_SPEC "\
+diff -urN gcc-3.4.1-dist/gcc/config/rs6000/linux.h gcc-3.4.1/gcc/config/rs6000/linux.h
+--- gcc-3.4.1-dist/gcc/config/rs6000/linux.h 2004-02-25 09:11:19.000000000 -0600
++++ gcc-3.4.1/gcc/config/rs6000/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -61,7 +61,11 @@
+ #define LINK_START_DEFAULT_SPEC "%(link_start_linux)"
+
+ #undef LINK_OS_DEFAULT_SPEC
++#ifdef USE_UCLIBC
++#define LINK_OS_DEFAULT_SPEC "%(link_os_linux_uclibc)"
++#else
+ #define LINK_OS_DEFAULT_SPEC "%(link_os_linux)"
++#endif
+
+ #define LINK_GCC_C_SEQUENCE_SPEC \
+ "%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}"
+diff -urN gcc-3.4.1-dist/gcc/config/rs6000/sysv4.h gcc-3.4.1/gcc/config/rs6000/sysv4.h
+--- gcc-3.4.1-dist/gcc/config/rs6000/sysv4.h 2004-06-10 01:39:50.000000000 -0500
++++ gcc-3.4.1/gcc/config/rs6000/sysv4.h 2004-08-12 15:54:43.000000000 -0500
+@@ -947,6 +947,7 @@
+ mcall-linux : %(link_os_linux) ; \
+ mcall-gnu : %(link_os_gnu) ; \
+ mcall-netbsd : %(link_os_netbsd) ; \
++ mcall-linux-uclibc : %(link_os_linux_uclibc); \
+ mcall-openbsd: %(link_os_openbsd) ; \
+ : %(link_os_default) }"
+
+@@ -1124,6 +1125,10 @@
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}}}"
+
++#define LINK_OS_LINUX_UCLIBC_SPEC "-m elf32ppclinux %{!shared: %{!static: \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}}}"
++
+ #if defined(HAVE_LD_EH_FRAME_HDR)
+ # define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
+ #endif
+@@ -1290,6 +1295,7 @@
+ { "link_os_sim", LINK_OS_SIM_SPEC }, \
+ { "link_os_freebsd", LINK_OS_FREEBSD_SPEC }, \
+ { "link_os_linux", LINK_OS_LINUX_SPEC }, \
++ { "link_os_linux_uclibc", LINK_OS_LINUX_UCLIBC_SPEC }, \
+ { "link_os_gnu", LINK_OS_GNU_SPEC }, \
+ { "link_os_netbsd", LINK_OS_NETBSD_SPEC }, \
+ { "link_os_openbsd", LINK_OS_OPENBSD_SPEC }, \
+diff -urN gcc-3.4.1-dist/gcc/config/sh/linux.h gcc-3.4.1/gcc/config/sh/linux.h
+--- gcc-3.4.1-dist/gcc/config/sh/linux.h 2004-01-11 20:29:13.000000000 -0600
++++ gcc-3.4.1/gcc/config/sh/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -73,12 +73,21 @@
+ #undef SUBTARGET_LINK_EMUL_SUFFIX
+ #define SUBTARGET_LINK_EMUL_SUFFIX "_linux"
+ #undef SUBTARGET_LINK_SPEC
++#ifdef USE_UCLIBC
++#define SUBTARGET_LINK_SPEC \
++ "%{shared:-shared} \
++ %{!static: \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}} \
++ %{static:-static}"
++#else
+ #define SUBTARGET_LINK_SPEC \
+ "%{shared:-shared} \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
+ %{static:-static}"
++#endif
+
+ #undef LIB_SPEC
+ #define LIB_SPEC \
+diff -urN gcc-3.4.1-dist/gcc/config/sh/t-linux-uclibc gcc-3.4.1/gcc/config/sh/t-linux-uclibc
+--- gcc-3.4.1-dist/gcc/config/sh/t-linux-uclibc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.1/gcc/config/sh/t-linux-uclibc 2004-08-12 15:54:43.000000000 -0500
+@@ -0,0 +1,13 @@
++T_CFLAGS = -DUSE_UCLIBC
++
++TARGET_LIBGCC2_CFLAGS = -fpic -DNO_FPSCR_VALUES
++LIB1ASMFUNCS_CACHE = _ic_invalidate
++
++LIB2FUNCS_EXTRA=
++
++MULTILIB_OPTIONS= $(MULTILIB_ENDIAN) m3e/m4
++MULTILIB_DIRNAMES=
++MULTILIB_MATCHES =
++MULTILIB_EXCEPTIONS=
++
++EXTRA_MULTILIB_PARTS= crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
+diff -urN gcc-3.4.1-dist/gcc/config/sh/t-sh64-uclibc gcc-3.4.1/gcc/config/sh/t-sh64-uclibc
+--- gcc-3.4.1-dist/gcc/config/sh/t-sh64-uclibc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.1/gcc/config/sh/t-sh64-uclibc 2004-08-12 15:54:43.000000000 -0500
+@@ -0,0 +1,13 @@
++EXTRA_MULTILIB_PARTS= crt1.o crti.o crtn.o crtbegin.o crtend.o
++
++LIB1ASMFUNCS = \
++ _sdivsi3 _sdivsi3_i4 _udivsi3 _udivsi3_i4 _set_fpscr \
++ _shcompact_call_trampoline _shcompact_return_trampoline \
++ _shcompact_incoming_args _ic_invalidate _nested_trampoline \
++ _push_pop_shmedia_regs \
++ _udivdi3 _divdi3 _umoddi3 _moddi3
++
++MULTILIB_OPTIONS = $(MULTILIB_ENDIAN) m5-32media-nofpu/m5-compact/m5-compact-nofpu/m5-64media/m5-64media-nofpu
++MULTILIB_DIRNAMES= $(MULTILIB_ENDIAN) nofpu compact nofpu/compact media64 nofpu/media64
++MULTILIB_MATCHES=
++MULTILIB_EXCEPTIONS=
+diff -urN gcc-3.4.1-dist/gcc/config/t-linux-uclibc gcc-3.4.1/gcc/config/t-linux-uclibc
+--- gcc-3.4.1-dist/gcc/config/t-linux-uclibc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.1/gcc/config/t-linux-uclibc 2004-08-12 15:54:43.000000000 -0500
+@@ -0,0 +1,15 @@
++T_CFLAGS = -DUSE_UCLIBC
++
++# Compile crtbeginS.o and crtendS.o with pic.
++CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
++# Compile libgcc2.a with pic.
++TARGET_LIBGCC2_CFLAGS = -fPIC
++
++# Override t-slibgcc-elf-ver to export some libgcc symbols with
++# the symbol versions that glibc used.
++#SHLIB_MAPFILES += $(srcdir)/config/libgcc-glibc.ver
++
++# Use unwind-dw2-fde
++LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
++ $(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c $(srcdir)/unwind-c.c
++LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h
+diff -urN gcc-3.4.1-dist/gcc/config.gcc gcc-3.4.1/gcc/config.gcc
+--- gcc-3.4.1-dist/gcc/config.gcc 2004-04-21 10:12:35.000000000 -0500
++++ gcc-3.4.1/gcc/config.gcc 2004-08-12 15:59:46.000000000 -0500
+@@ -664,6 +664,12 @@
+ extra_parts=""
+ use_collect2=yes
+ ;;
++arm*-*-linux-uclibc*) # ARM GNU/Linux with ELF - uClibc
++ tm_file="dbxelf.h elfos.h linux.h arm/elf.h arm/linux-gas.h arm/linux-elf.h arm/aout.h arm/arm.h"
++ tmake_file="t-slibgcc-elf-ver t-linux-uclibc arm/t-linux"
++ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
++ gnu_ld=yes
++ ;;
+ arm*-*-linux*) # ARM GNU/Linux with ELF
+ tm_file="dbxelf.h elfos.h linux.h arm/elf.h arm/linux-gas.h arm/linux-elf.h arm/aout.h arm/arm.h"
+ tmake_file="t-slibgcc-elf-ver t-linux arm/t-linux"
+@@ -725,6 +731,10 @@
+ tmake_file="cris/t-cris cris/t-elfmulti"
+ gas=yes
+ ;;
++cris-*-linux-uclibc*)
++ tm_file="dbxelf.h elfos.h svr4.h ${tm_file} linux.h cris/linux.h"
++ tmake_file="cris/t-cris t-slibgcc-elf-ver cris/t-linux-uclibc"
++ ;;
+ cris-*-linux*)
+ tm_file="dbxelf.h elfos.h svr4.h ${tm_file} linux.h cris/linux.h"
+ tmake_file="cris/t-cris t-slibgcc-elf-ver cris/t-linux"
+@@ -988,6 +998,11 @@
+ thread_file='single'
+ fi
+ ;;
++i[34567]86-*-linux*uclibc*) # Intel 80386's running GNU/Linux
++ # with ELF format using uClibc
++ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h linux.h i386/linux.h"
++ tmake_file="t-slibgcc-elf-ver t-linux-uclibc i386/t-crtstuff"
++ ;;
+ i[34567]86-*-linux*) # Intel 80386's running GNU/Linux
+ # with ELF format using glibc 2
+ # aka GNU/Linux C library 6
+@@ -1547,6 +1562,16 @@
+ gnu_ld=yes
+ gas=yes
+ ;;
++mips*-*-linux-uclibc*) # Linux MIPS, either endian. uClibc
++ tm_file="dbxelf.h elfos.h svr4.h linux.h ${tm_file} mips/linux.h"
++ case ${target} in
++ mipsisa32*-*)
++ target_cpu_default="MASK_SOFT_FLOAT"
++ tm_defines="MIPS_ISA_DEFAULT=32"
++ ;;
++ esac
++ tmake_file="t-slibgcc-elf-ver t-linux-uclibc"
++ ;;
+ mips*-*-linux*) # Linux MIPS, either endian.
+ tm_file="dbxelf.h elfos.h svr4.h linux.h ${tm_file} mips/linux.h"
+ case ${target} in
+@@ -1764,6 +1789,10 @@
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/linux.h rs6000/linuxspe.h"
+ tmake_file="rs6000/t-fprules rs6000/t-ppcos t-slibgcc-elf-ver t-linux rs6000/t-ppccomm"
+ ;;
++powerpc-*-linux-uclibc*)
++ tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/linux.h"
++ tmake_file="rs6000/t-fprules rs6000/t-ppcos t-slibgcc-elf-ver t-linux-uclibc rs6000/t-ppccomm"
++ ;;
+ powerpc-*-linux*)
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/linux.h"
+ tmake_file="rs6000/t-fprules rs6000/t-ppcos t-slibgcc-elf-ver t-linux rs6000/t-ppccomm"
+@@ -1916,7 +1945,7 @@
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sh/elf.h sh/embed-elf.h sh/rtemself.h rtems.h"
+ ;;
+ sh-*-linux* | sh[2346lbe]*-*-linux*)
+- tmake_file="sh/t-sh sh/t-elf t-slibgcc-elf-ver t-linux"
++ tmake_file="sh/t-sh sh/t-elf t-slibgcc-elf-ver"
+ case ${target} in
+ sh*be-*-* | sh*eb-*-*) ;;
+ *)
+@@ -1924,9 +1953,17 @@
+ tmake_file="${tmake_file} sh/t-le"
+ ;;
+ esac
+- tmake_file="${tmake_file} sh/t-linux"
++ case ${target} in
++ *-*-linux-uclibc*) tmake_file="${tmake_file} t-linux-uclibc sh/t-linux-uclibc" ;;
++ *) tmake_file="${tmake_file} t-linux sh/t-linux" ;;
++ esac
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sh/elf.h sh/linux.h"
+ case ${target} in
++ sh64*-*-linux-uclibc*)
++ tmake_file="${tmake_file} sh/t-sh64-uclibc"
++ tm_file="${tm_file} sh/sh64.h"
++ extra_headers="shmedia.h ushmedia.h sshmedia.h"
++ ;;
+ sh64*)
+ tmake_file="${tmake_file} sh/t-sh64"
+ tm_file="${tm_file} sh/sh64.h"
+diff -urN gcc-3.4.1-dist/libtool.m4 gcc-3.4.1/libtool.m4
+--- gcc-3.4.1-dist/libtool.m4 2004-05-18 04:08:37.000000000 -0500
++++ gcc-3.4.1/libtool.m4 2004-08-12 15:54:43.000000000 -0500
+@@ -689,6 +689,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ [lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$']
+diff -urN gcc-3.4.1-dist/ltconfig gcc-3.4.1/ltconfig
+--- gcc-3.4.1-dist/ltconfig 2004-03-05 15:05:41.000000000 -0600
++++ gcc-3.4.1/ltconfig 2004-08-12 15:55:48.000000000 -0500
+@@ -602,6 +602,7 @@
+
+ # Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+ case $host_os in
++linux-uclibc*) ;;
+ linux-gnu*) ;;
+ linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+ esac
+@@ -1262,6 +1263,24 @@
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
++linux-uclibc*)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
++ soname_spec='${libname}${release}.so$major'
++ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ # This implies no fast_install, which is unacceptable.
++ # Some rework will be needed to allow for fast_install
++ # before this can be enabled.
++ # Note: copied from linux-gnu, and may not be appropriate.
++ hardcode_into_libs=yes
++ # Assume using the uClibc dynamic linker.
++ dynamic_linker="uClibc ld.so"
++ ;;
++
+ netbsd*)
+ need_lib_prefix=no
+ need_version=no
diff --git a/toolchain/gcc/patches/3.4.6-nonmips/200-uclibc-locale.patch b/toolchain/gcc/patches/3.4.6-nonmips/200-uclibc-locale.patch
new file mode 100644
index 0000000000..3fc4900b06
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.6-nonmips/200-uclibc-locale.patch
@@ -0,0 +1,3246 @@
+diff -urN gcc-3.4.2-dist/libstdc++-v3/acinclude.m4 gcc-3.4.2/libstdc++-v3/acinclude.m4
+--- gcc-3.4.2-dist/libstdc++-v3/acinclude.m4 2004-07-15 12:42:45.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/acinclude.m4 2004-09-10 10:47:40.000000000 -0500
+@@ -996,7 +996,7 @@
+ AC_MSG_CHECKING([for C locale to use])
+ GLIBCXX_ENABLE(clocale,auto,[@<:@=MODEL@:>@],
+ [use MODEL for target locale package],
+- [permit generic|gnu|ieee_1003.1-2001|yes|no|auto])
++ [permit generic|gnu|ieee_1003.1-2001|uclibc|yes|no|auto])
+
+ # If they didn't use this option switch, or if they specified --enable
+ # with no specific model, we'll have to look for one. If they
+@@ -1012,6 +1012,9 @@
+ # Default to "generic".
+ if test $enable_clocale_flag = auto; then
+ case x${target_os} in
++ x*-uclibc*)
++ enable_clocale_flag=uclibc
++ ;;
+ xlinux* | xgnu* | xkfreebsd*-gnu | xknetbsd*-gnu)
+ AC_EGREP_CPP([_GLIBCXX_ok], [
+ #include <features.h>
+@@ -1138,6 +1141,41 @@
+ CTIME_CC=config/locale/generic/time_members.cc
+ CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+ ;;
++ uclibc)
++ AC_MSG_RESULT(uclibc)
++
++ # Declare intention to use gettext, and add support for specific
++ # languages.
++ # For some reason, ALL_LINGUAS has to be before AM-GNU-GETTEXT
++ ALL_LINGUAS="de fr"
++
++ # Don't call AM-GNU-GETTEXT here. Instead, assume glibc.
++ AC_CHECK_PROG(check_msgfmt, msgfmt, yes, no)
++ if test x"$check_msgfmt" = x"yes" && test x"$enable_nls" = x"yes"; then
++ USE_NLS=yes
++ fi
++ # Export the build objects.
++ for ling in $ALL_LINGUAS; do \
++ glibcxx_MOFILES="$glibcxx_MOFILES $ling.mo"; \
++ glibcxx_POFILES="$glibcxx_POFILES $ling.po"; \
++ done
++ AC_SUBST(glibcxx_MOFILES)
++ AC_SUBST(glibcxx_POFILES)
++
++ CLOCALE_H=config/locale/uclibc/c_locale.h
++ CLOCALE_CC=config/locale/uclibc/c_locale.cc
++ CCODECVT_H=config/locale/ieee_1003.1-2001/codecvt_specializations.h
++ CCODECVT_CC=config/locale/uclibc/codecvt_members.cc
++ CCOLLATE_CC=config/locale/uclibc/collate_members.cc
++ CCTYPE_CC=config/locale/uclibc/ctype_members.cc
++ CMESSAGES_H=config/locale/uclibc/messages_members.h
++ CMESSAGES_CC=config/locale/uclibc/messages_members.cc
++ CMONEY_CC=config/locale/uclibc/monetary_members.cc
++ CNUMERIC_CC=config/locale/uclibc/numeric_members.cc
++ CTIME_H=config/locale/uclibc/time_members.h
++ CTIME_CC=config/locale/uclibc/time_members.cc
++ CLOCALE_INTERNAL_H=config/locale/uclibc/c++locale_internal.h
++ ;;
+ esac
+
+ # This is where the testsuite looks for locale catalogs, using the
+diff -urN gcc-3.4.2-dist/libstdc++-v3/aclocal.m4 gcc-3.4.2/libstdc++-v3/aclocal.m4
+--- gcc-3.4.2-dist/libstdc++-v3/aclocal.m4 2004-08-13 15:44:03.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/aclocal.m4 2004-09-10 10:47:40.000000000 -0500
+@@ -1025,6 +1025,9 @@
+ # Default to "generic".
+ if test $enable_clocale_flag = auto; then
+ case x${target_os} in
++ x*-uclibc*)
++ enable_clocale_flag=uclibc
++ ;;
+ xlinux* | xgnu* | xkfreebsd*-gnu | xknetbsd*-gnu)
+ AC_EGREP_CPP([_GLIBCXX_ok], [
+ #include <features.h>
+@@ -1151,6 +1154,41 @@
+ CTIME_CC=config/locale/generic/time_members.cc
+ CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+ ;;
++ uclibc)
++ AC_MSG_RESULT(uclibc)
++
++ # Declare intention to use gettext, and add support for specific
++ # languages.
++ # For some reason, ALL_LINGUAS has to be before AM-GNU-GETTEXT
++ ALL_LINGUAS="de fr"
++
++ # Don't call AM-GNU-GETTEXT here. Instead, assume glibc.
++ AC_CHECK_PROG(check_msgfmt, msgfmt, yes, no)
++ if test x"$check_msgfmt" = x"yes" && test x"$enable_nls" = x"yes"; then
++ USE_NLS=yes
++ fi
++ # Export the build objects.
++ for ling in $ALL_LINGUAS; do \
++ glibcxx_MOFILES="$glibcxx_MOFILES $ling.mo"; \
++ glibcxx_POFILES="$glibcxx_POFILES $ling.po"; \
++ done
++ AC_SUBST(glibcxx_MOFILES)
++ AC_SUBST(glibcxx_POFILES)
++
++ CLOCALE_H=config/locale/uclibc/c_locale.h
++ CLOCALE_CC=config/locale/uclibc/c_locale.cc
++ CCODECVT_H=config/locale/ieee_1003.1-2001/codecvt_specializations.h
++ CCODECVT_CC=config/locale/uclibc/codecvt_members.cc
++ CCOLLATE_CC=config/locale/uclibc/collate_members.cc
++ CCTYPE_CC=config/locale/uclibc/ctype_members.cc
++ CMESSAGES_H=config/locale/uclibc/messages_members.h
++ CMESSAGES_CC=config/locale/uclibc/messages_members.cc
++ CMONEY_CC=config/locale/uclibc/monetary_members.cc
++ CNUMERIC_CC=config/locale/uclibc/numeric_members.cc
++ CTIME_H=config/locale/uclibc/time_members.h
++ CTIME_CC=config/locale/uclibc/time_members.cc
++ CLOCALE_INTERNAL_H=config/locale/uclibc/c++locale_internal.h
++ ;;
+ esac
+
+ # This is where the testsuite looks for locale catalogs, using the
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c++locale_internal.h gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c++locale_internal.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c++locale_internal.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c++locale_internal.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,59 @@
++// Prototypes for GLIBC thread locale __-prefixed functions -*- C++ -*-
++
++// Copyright (C) 2002, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++// Written by Jakub Jelinek <jakub@redhat.com>
++
++#include <clocale>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning clean this up
++#endif
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++
++extern "C" __typeof(iswctype_l) __iswctype_l;
++extern "C" __typeof(nl_langinfo_l) __nl_langinfo_l;
++extern "C" __typeof(strcoll_l) __strcoll_l;
++extern "C" __typeof(strftime_l) __strftime_l;
++extern "C" __typeof(strtod_l) __strtod_l;
++extern "C" __typeof(strtof_l) __strtof_l;
++extern "C" __typeof(strtold_l) __strtold_l;
++extern "C" __typeof(strxfrm_l) __strxfrm_l;
++extern "C" __typeof(towlower_l) __towlower_l;
++extern "C" __typeof(towupper_l) __towupper_l;
++extern "C" __typeof(wcscoll_l) __wcscoll_l;
++extern "C" __typeof(wcsftime_l) __wcsftime_l;
++extern "C" __typeof(wcsxfrm_l) __wcsxfrm_l;
++extern "C" __typeof(wctype_l) __wctype_l;
++extern "C" __typeof(newlocale) __newlocale;
++extern "C" __typeof(freelocale) __freelocale;
++extern "C" __typeof(duplocale) __duplocale;
++extern "C" __typeof(uselocale) __uselocale;
++
++#endif // GLIBC 2.3 and later
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,160 @@
++// Wrapper for underlying C-language localization -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.8 Standard locale categories.
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <cerrno> // For errno
++#include <locale>
++#include <stdexcept>
++#include <langinfo.h>
++#include <bits/c++locale_internal.h>
++
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __strtol_l(S, E, B, L) strtol((S), (E), (B))
++#define __strtoul_l(S, E, B, L) strtoul((S), (E), (B))
++#define __strtoll_l(S, E, B, L) strtoll((S), (E), (B))
++#define __strtoull_l(S, E, B, L) strtoull((S), (E), (B))
++#define __strtof_l(S, E, L) strtof((S), (E))
++#define __strtod_l(S, E, L) strtod((S), (E))
++#define __strtold_l(S, E, L) strtold((S), (E))
++#warning should dummy __newlocale check for C|POSIX ?
++#define __newlocale(a, b, c) NULL
++#define __freelocale(a) ((void)0)
++#define __duplocale(a) __c_locale()
++#endif
++
++namespace std
++{
++ template<>
++ void
++ __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err,
++ const __c_locale& __cloc)
++ {
++ if (!(__err & ios_base::failbit))
++ {
++ char* __sanity;
++ errno = 0;
++ float __f = __strtof_l(__s, &__sanity, __cloc);
++ if (__sanity != __s && errno != ERANGE)
++ __v = __f;
++ else
++ __err |= ios_base::failbit;
++ }
++ }
++
++ template<>
++ void
++ __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err,
++ const __c_locale& __cloc)
++ {
++ if (!(__err & ios_base::failbit))
++ {
++ char* __sanity;
++ errno = 0;
++ double __d = __strtod_l(__s, &__sanity, __cloc);
++ if (__sanity != __s && errno != ERANGE)
++ __v = __d;
++ else
++ __err |= ios_base::failbit;
++ }
++ }
++
++ template<>
++ void
++ __convert_to_v(const char* __s, long double& __v, ios_base::iostate& __err,
++ const __c_locale& __cloc)
++ {
++ if (!(__err & ios_base::failbit))
++ {
++ char* __sanity;
++ errno = 0;
++ long double __ld = __strtold_l(__s, &__sanity, __cloc);
++ if (__sanity != __s && errno != ERANGE)
++ __v = __ld;
++ else
++ __err |= ios_base::failbit;
++ }
++ }
++
++ void
++ locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
++ __c_locale __old)
++ {
++ __cloc = __newlocale(1 << LC_ALL, __s, __old);
++#ifdef __UCLIBC_HAS_XLOCALE__
++ if (!__cloc)
++ {
++ // This named locale is not supported by the underlying OS.
++ __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
++ "name not valid"));
++ }
++#endif
++ }
++
++ void
++ locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
++ {
++ if (_S_get_c_locale() != __cloc)
++ __freelocale(__cloc);
++ }
++
++ __c_locale
++ locale::facet::_S_clone_c_locale(__c_locale& __cloc)
++ { return __duplocale(__cloc); }
++} // namespace std
++
++namespace __gnu_cxx
++{
++ const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
++ {
++ "LC_CTYPE",
++ "LC_NUMERIC",
++ "LC_TIME",
++ "LC_COLLATE",
++ "LC_MONETARY",
++ "LC_MESSAGES",
++#if _GLIBCXX_NUM_CATEGORIES != 0
++ "LC_PAPER",
++ "LC_NAME",
++ "LC_ADDRESS",
++ "LC_TELEPHONE",
++ "LC_MEASUREMENT",
++ "LC_IDENTIFICATION"
++#endif
++ };
++}
++
++namespace std
++{
++ const char* const* const locale::_S_categories = __gnu_cxx::category_names;
++} // namespace std
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.h gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.h 2004-09-10 10:48:08.000000000 -0500
+@@ -0,0 +1,115 @@
++// Wrapper for underlying C-language localization -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.8 Standard locale categories.
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#ifndef _C_LOCALE_H
++#define _C_LOCALE_H 1
++
++#pragma GCC system_header
++
++#include <cstring> // get std::strlen
++#include <cstdio> // get std::snprintf or std::sprintf
++#include <clocale>
++#include <langinfo.h> // For codecvt
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix this
++#endif
++#ifdef __UCLIBC_HAS_LOCALE__
++#include <iconv.h> // For codecvt using iconv, iconv_t
++#endif
++#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
++#include <libintl.h> // For messages
++#endif
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning what is _GLIBCXX_C_LOCALE_GNU for
++#endif
++#define _GLIBCXX_C_LOCALE_GNU 1
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix categories
++#endif
++// #define _GLIBCXX_NUM_CATEGORIES 6
++#define _GLIBCXX_NUM_CATEGORIES 0
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++namespace __gnu_cxx
++{
++ extern "C" __typeof(uselocale) __uselocale;
++}
++#endif
++
++namespace std
++{
++#ifdef __UCLIBC_HAS_XLOCALE__
++ typedef __locale_t __c_locale;
++#else
++ typedef int* __c_locale;
++#endif
++
++ // Convert numeric value of type _Tv to string and return length of
++ // string. If snprintf is available use it, otherwise fall back to
++ // the unsafe sprintf which, in general, can be dangerous and should
++ // be avoided.
++ template<typename _Tv>
++ int
++ __convert_from_v(char* __out, const int __size, const char* __fmt,
++#ifdef __UCLIBC_HAS_XLOCALE__
++ _Tv __v, const __c_locale& __cloc, int __prec)
++ {
++ __c_locale __old = __gnu_cxx::__uselocale(__cloc);
++#else
++ _Tv __v, const __c_locale&, int __prec)
++ {
++# ifdef __UCLIBC_HAS_LOCALE__
++ char* __old = std::setlocale(LC_ALL, NULL);
++ char* __sav = new char[std::strlen(__old) + 1];
++ std::strcpy(__sav, __old);
++ std::setlocale(LC_ALL, "C");
++# endif
++#endif
++
++ const int __ret = std::snprintf(__out, __size, __fmt, __prec, __v);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __gnu_cxx::__uselocale(__old);
++#elif defined __UCLIBC_HAS_LOCALE__
++ std::setlocale(LC_ALL, __sav);
++ delete [] __sav;
++#endif
++ return __ret;
++ }
++}
++
++#endif
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/codecvt_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/codecvt_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/codecvt_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/codecvt_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,306 @@
++// std::codecvt implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2002, 2003 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.1.5 - Template class codecvt
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <locale>
++#include <bits/c++locale_internal.h>
++
++namespace std
++{
++ // Specializations.
++#ifdef _GLIBCXX_USE_WCHAR_T
++ codecvt_base::result
++ codecvt<wchar_t, char, mbstate_t>::
++ do_out(state_type& __state, const intern_type* __from,
++ const intern_type* __from_end, const intern_type*& __from_next,
++ extern_type* __to, extern_type* __to_end,
++ extern_type*& __to_next) const
++ {
++ result __ret = ok;
++ state_type __tmp_state(__state);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++
++ // wcsnrtombs is *very* fast but stops if encounters NUL characters:
++ // in case we fall back to wcrtomb and then continue, in a loop.
++ // NB: wcsnrtombs is a GNU extension
++ for (__from_next = __from, __to_next = __to;
++ __from_next < __from_end && __to_next < __to_end
++ && __ret == ok;)
++ {
++ const intern_type* __from_chunk_end = wmemchr(__from_next, L'\0',
++ __from_end - __from_next);
++ if (!__from_chunk_end)
++ __from_chunk_end = __from_end;
++
++ __from = __from_next;
++ const size_t __conv = wcsnrtombs(__to_next, &__from_next,
++ __from_chunk_end - __from_next,
++ __to_end - __to_next, &__state);
++ if (__conv == static_cast<size_t>(-1))
++ {
++ // In case of error, in order to stop at the exact place we
++ // have to start again from the beginning with a series of
++ // wcrtomb.
++ for (; __from < __from_next; ++__from)
++ __to_next += wcrtomb(__to_next, *__from, &__tmp_state);
++ __state = __tmp_state;
++ __ret = error;
++ }
++ else if (__from_next && __from_next < __from_chunk_end)
++ {
++ __to_next += __conv;
++ __ret = partial;
++ }
++ else
++ {
++ __from_next = __from_chunk_end;
++ __to_next += __conv;
++ }
++
++ if (__from_next < __from_end && __ret == ok)
++ {
++ extern_type __buf[MB_LEN_MAX];
++ __tmp_state = __state;
++ const size_t __conv = wcrtomb(__buf, *__from_next, &__tmp_state);
++ if (__conv > static_cast<size_t>(__to_end - __to_next))
++ __ret = partial;
++ else
++ {
++ memcpy(__to_next, __buf, __conv);
++ __state = __tmp_state;
++ __to_next += __conv;
++ ++__from_next;
++ }
++ }
++ }
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++
++ return __ret;
++ }
++
++ codecvt_base::result
++ codecvt<wchar_t, char, mbstate_t>::
++ do_in(state_type& __state, const extern_type* __from,
++ const extern_type* __from_end, const extern_type*& __from_next,
++ intern_type* __to, intern_type* __to_end,
++ intern_type*& __to_next) const
++ {
++ result __ret = ok;
++ state_type __tmp_state(__state);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++
++ // mbsnrtowcs is *very* fast but stops if encounters NUL characters:
++ // in case we store a L'\0' and then continue, in a loop.
++ // NB: mbsnrtowcs is a GNU extension
++ for (__from_next = __from, __to_next = __to;
++ __from_next < __from_end && __to_next < __to_end
++ && __ret == ok;)
++ {
++ const extern_type* __from_chunk_end;
++ __from_chunk_end = static_cast<const extern_type*>(memchr(__from_next, '\0',
++ __from_end
++ - __from_next));
++ if (!__from_chunk_end)
++ __from_chunk_end = __from_end;
++
++ __from = __from_next;
++ size_t __conv = mbsnrtowcs(__to_next, &__from_next,
++ __from_chunk_end - __from_next,
++ __to_end - __to_next, &__state);
++ if (__conv == static_cast<size_t>(-1))
++ {
++ // In case of error, in order to stop at the exact place we
++ // have to start again from the beginning with a series of
++ // mbrtowc.
++ for (;; ++__to_next, __from += __conv)
++ {
++ __conv = mbrtowc(__to_next, __from, __from_end - __from,
++ &__tmp_state);
++ if (__conv == static_cast<size_t>(-1)
++ || __conv == static_cast<size_t>(-2))
++ break;
++ }
++ __from_next = __from;
++ __state = __tmp_state;
++ __ret = error;
++ }
++ else if (__from_next && __from_next < __from_chunk_end)
++ {
++ // It is unclear what to return in this case (see DR 382).
++ __to_next += __conv;
++ __ret = partial;
++ }
++ else
++ {
++ __from_next = __from_chunk_end;
++ __to_next += __conv;
++ }
++
++ if (__from_next < __from_end && __ret == ok)
++ {
++ if (__to_next < __to_end)
++ {
++ // XXX Probably wrong for stateful encodings
++ __tmp_state = __state;
++ ++__from_next;
++ *__to_next++ = L'\0';
++ }
++ else
++ __ret = partial;
++ }
++ }
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++
++ return __ret;
++ }
++
++ int
++ codecvt<wchar_t, char, mbstate_t>::
++ do_encoding() const throw()
++ {
++ // XXX This implementation assumes that the encoding is
++ // stateless and is either single-byte or variable-width.
++ int __ret = 0;
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++ if (MB_CUR_MAX == 1)
++ __ret = 1;
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ return __ret;
++ }
++
++ int
++ codecvt<wchar_t, char, mbstate_t>::
++ do_max_length() const throw()
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++ // XXX Probably wrong for stateful encodings.
++ int __ret = MB_CUR_MAX;
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ return __ret;
++ }
++
++ int
++ codecvt<wchar_t, char, mbstate_t>::
++ do_length(state_type& __state, const extern_type* __from,
++ const extern_type* __end, size_t __max) const
++ {
++ int __ret = 0;
++ state_type __tmp_state(__state);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++
++ // mbsnrtowcs is *very* fast but stops if encounters NUL characters:
++ // in case we advance past it and then continue, in a loop.
++ // NB: mbsnrtowcs is a GNU extension
++
++ // A dummy internal buffer is needed in order for mbsnrtocws to consider
++ // its fourth parameter (it wouldn't with NULL as first parameter).
++ wchar_t* __to = static_cast<wchar_t*>(__builtin_alloca(sizeof(wchar_t)
++ * __max));
++ while (__from < __end && __max)
++ {
++ const extern_type* __from_chunk_end;
++ __from_chunk_end = static_cast<const extern_type*>(memchr(__from, '\0',
++ __end
++ - __from));
++ if (!__from_chunk_end)
++ __from_chunk_end = __end;
++
++ const extern_type* __tmp_from = __from;
++ size_t __conv = mbsnrtowcs(__to, &__from,
++ __from_chunk_end - __from,
++ __max, &__state);
++ if (__conv == static_cast<size_t>(-1))
++ {
++ // In case of error, in order to stop at the exact place we
++ // have to start again from the beginning with a series of
++ // mbrtowc.
++ for (__from = __tmp_from;; __from += __conv)
++ {
++ __conv = mbrtowc(NULL, __from, __end - __from,
++ &__tmp_state);
++ if (__conv == static_cast<size_t>(-1)
++ || __conv == static_cast<size_t>(-2))
++ break;
++ }
++ __state = __tmp_state;
++ __ret += __from - __tmp_from;
++ break;
++ }
++ if (!__from)
++ __from = __from_chunk_end;
++
++ __ret += __from - __tmp_from;
++ __max -= __conv;
++
++ if (__from < __end && __max)
++ {
++ // XXX Probably wrong for stateful encodings
++ __tmp_state = __state;
++ ++__from;
++ ++__ret;
++ --__max;
++ }
++ }
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++
++ return __ret;
++ }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/collate_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/collate_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/collate_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/collate_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,80 @@
++// std::collate implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.4.1.2 collate virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <locale>
++#include <bits/c++locale_internal.h>
++
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __strcoll_l(S1, S2, L) strcoll((S1), (S2))
++#define __strxfrm_l(S1, S2, N, L) strxfrm((S1), (S2), (N))
++#define __wcscoll_l(S1, S2, L) wcscoll((S1), (S2))
++#define __wcsxfrm_l(S1, S2, N, L) wcsxfrm((S1), (S2), (N))
++#endif
++
++namespace std
++{
++ // These are basically extensions to char_traits, and perhaps should
++ // be put there instead of here.
++ template<>
++ int
++ collate<char>::_M_compare(const char* __one, const char* __two) const
++ {
++ int __cmp = __strcoll_l(__one, __two, _M_c_locale_collate);
++ return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0);
++ }
++
++ template<>
++ size_t
++ collate<char>::_M_transform(char* __to, const char* __from,
++ size_t __n) const
++ { return __strxfrm_l(__to, __from, __n, _M_c_locale_collate); }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ template<>
++ int
++ collate<wchar_t>::_M_compare(const wchar_t* __one,
++ const wchar_t* __two) const
++ {
++ int __cmp = __wcscoll_l(__one, __two, _M_c_locale_collate);
++ return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0);
++ }
++
++ template<>
++ size_t
++ collate<wchar_t>::_M_transform(wchar_t* __to, const wchar_t* __from,
++ size_t __n) const
++ { return __wcsxfrm_l(__to, __from, __n, _M_c_locale_collate); }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/ctype_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/ctype_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/ctype_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/ctype_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,300 @@
++// std::ctype implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.1.1.2 ctype virtual functions.
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#define _LIBC
++#include <locale>
++#undef _LIBC
++#include <bits/c++locale_internal.h>
++
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __wctype_l(S, L) wctype((S))
++#define __towupper_l(C, L) towupper((C))
++#define __towlower_l(C, L) towlower((C))
++#define __iswctype_l(C, M, L) iswctype((C), (M))
++#endif
++
++namespace std
++{
++ // NB: The other ctype<char> specializations are in src/locale.cc and
++ // various /config/os/* files.
++ template<>
++ ctype_byname<char>::ctype_byname(const char* __s, size_t __refs)
++ : ctype<char>(0, false, __refs)
++ {
++ if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
++ {
++ this->_S_destroy_c_locale(this->_M_c_locale_ctype);
++ this->_S_create_c_locale(this->_M_c_locale_ctype, __s);
++#ifdef __UCLIBC_HAS_XLOCALE__
++ this->_M_toupper = this->_M_c_locale_ctype->__ctype_toupper;
++ this->_M_tolower = this->_M_c_locale_ctype->__ctype_tolower;
++ this->_M_table = this->_M_c_locale_ctype->__ctype_b;
++#endif
++ }
++ }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ ctype<wchar_t>::__wmask_type
++ ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const
++ {
++ __wmask_type __ret;
++ switch (__m)
++ {
++ case space:
++ __ret = __wctype_l("space", _M_c_locale_ctype);
++ break;
++ case print:
++ __ret = __wctype_l("print", _M_c_locale_ctype);
++ break;
++ case cntrl:
++ __ret = __wctype_l("cntrl", _M_c_locale_ctype);
++ break;
++ case upper:
++ __ret = __wctype_l("upper", _M_c_locale_ctype);
++ break;
++ case lower:
++ __ret = __wctype_l("lower", _M_c_locale_ctype);
++ break;
++ case alpha:
++ __ret = __wctype_l("alpha", _M_c_locale_ctype);
++ break;
++ case digit:
++ __ret = __wctype_l("digit", _M_c_locale_ctype);
++ break;
++ case punct:
++ __ret = __wctype_l("punct", _M_c_locale_ctype);
++ break;
++ case xdigit:
++ __ret = __wctype_l("xdigit", _M_c_locale_ctype);
++ break;
++ case alnum:
++ __ret = __wctype_l("alnum", _M_c_locale_ctype);
++ break;
++ case graph:
++ __ret = __wctype_l("graph", _M_c_locale_ctype);
++ break;
++ default:
++ __ret = 0;
++ }
++ return __ret;
++ }
++
++ wchar_t
++ ctype<wchar_t>::do_toupper(wchar_t __c) const
++ { return __towupper_l(__c, _M_c_locale_ctype); }
++
++ const wchar_t*
++ ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const
++ {
++ while (__lo < __hi)
++ {
++ *__lo = __towupper_l(*__lo, _M_c_locale_ctype);
++ ++__lo;
++ }
++ return __hi;
++ }
++
++ wchar_t
++ ctype<wchar_t>::do_tolower(wchar_t __c) const
++ { return __towlower_l(__c, _M_c_locale_ctype); }
++
++ const wchar_t*
++ ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const
++ {
++ while (__lo < __hi)
++ {
++ *__lo = __towlower_l(*__lo, _M_c_locale_ctype);
++ ++__lo;
++ }
++ return __hi;
++ }
++
++ bool
++ ctype<wchar_t>::
++ do_is(mask __m, wchar_t __c) const
++ {
++ // Highest bitmask in ctype_base == 10, but extra in "C"
++ // library for blank.
++ bool __ret = false;
++ const size_t __bitmasksize = 11;
++ for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
++ if (__m & _M_bit[__bitcur]
++ && __iswctype_l(__c, _M_wmask[__bitcur], _M_c_locale_ctype))
++ {
++ __ret = true;
++ break;
++ }
++ return __ret;
++ }
++
++ const wchar_t*
++ ctype<wchar_t>::
++ do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __vec) const
++ {
++ for (; __lo < __hi; ++__vec, ++__lo)
++ {
++ // Highest bitmask in ctype_base == 10, but extra in "C"
++ // library for blank.
++ const size_t __bitmasksize = 11;
++ mask __m = 0;
++ for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
++ if (__iswctype_l(*__lo, _M_wmask[__bitcur], _M_c_locale_ctype))
++ __m |= _M_bit[__bitcur];
++ *__vec = __m;
++ }
++ return __hi;
++ }
++
++ const wchar_t*
++ ctype<wchar_t>::
++ do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const
++ {
++ while (__lo < __hi && !this->do_is(__m, *__lo))
++ ++__lo;
++ return __lo;
++ }
++
++ const wchar_t*
++ ctype<wchar_t>::
++ do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const
++ {
++ while (__lo < __hi && this->do_is(__m, *__lo) != 0)
++ ++__lo;
++ return __lo;
++ }
++
++ wchar_t
++ ctype<wchar_t>::
++ do_widen(char __c) const
++ { return _M_widen[static_cast<unsigned char>(__c)]; }
++
++ const char*
++ ctype<wchar_t>::
++ do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const
++ {
++ while (__lo < __hi)
++ {
++ *__dest = _M_widen[static_cast<unsigned char>(*__lo)];
++ ++__lo;
++ ++__dest;
++ }
++ return __hi;
++ }
++
++ char
++ ctype<wchar_t>::
++ do_narrow(wchar_t __wc, char __dfault) const
++ {
++ if (__wc >= 0 && __wc < 128 && _M_narrow_ok)
++ return _M_narrow[__wc];
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_ctype);
++#endif
++ const int __c = wctob(__wc);
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ return (__c == EOF ? __dfault : static_cast<char>(__c));
++ }
++
++ const wchar_t*
++ ctype<wchar_t>::
++ do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault,
++ char* __dest) const
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_ctype);
++#endif
++ if (_M_narrow_ok)
++ while (__lo < __hi)
++ {
++ if (*__lo >= 0 && *__lo < 128)
++ *__dest = _M_narrow[*__lo];
++ else
++ {
++ const int __c = wctob(*__lo);
++ *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
++ }
++ ++__lo;
++ ++__dest;
++ }
++ else
++ while (__lo < __hi)
++ {
++ const int __c = wctob(*__lo);
++ *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
++ ++__lo;
++ ++__dest;
++ }
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ return __hi;
++ }
++
++ void
++ ctype<wchar_t>::_M_initialize_ctype()
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_ctype);
++#endif
++ wint_t __i;
++ for (__i = 0; __i < 128; ++__i)
++ {
++ const int __c = wctob(__i);
++ if (__c == EOF)
++ break;
++ else
++ _M_narrow[__i] = static_cast<char>(__c);
++ }
++ if (__i == 128)
++ _M_narrow_ok = true;
++ else
++ _M_narrow_ok = false;
++ for (size_t __j = 0;
++ __j < sizeof(_M_widen) / sizeof(wint_t); ++__j)
++ _M_widen[__j] = btowc(__j);
++
++ for (size_t __k = 0; __k <= 11; ++__k)
++ {
++ _M_bit[__k] = static_cast<mask>(_ISbit(__k));
++ _M_wmask[__k] = _M_convert_to_wmask(_M_bit[__k]);
++ }
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ }
++#endif // _GLIBCXX_USE_WCHAR_T
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/messages_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/messages_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/messages_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/messages_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,100 @@
++// std::messages implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.7.1.2 messages virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <locale>
++#include <bits/c++locale_internal.h>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix gettext stuff
++#endif
++#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
++extern "C" char *__dcgettext(const char *domainname,
++ const char *msgid, int category);
++#undef gettext
++#define gettext(msgid) __dcgettext(NULL, msgid, LC_MESSAGES)
++#else
++#undef gettext
++#define gettext(msgid) (msgid)
++#endif
++
++namespace std
++{
++ // Specializations.
++ template<>
++ string
++ messages<char>::do_get(catalog, int, int, const string& __dfault) const
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_messages);
++ const char* __msg = const_cast<const char*>(gettext(__dfault.c_str()));
++ __uselocale(__old);
++ return string(__msg);
++#elif defined __UCLIBC_HAS_LOCALE__
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, _M_name_messages);
++ const char* __msg = gettext(__dfault.c_str());
++ setlocale(LC_ALL, __old);
++ free(__old);
++ return string(__msg);
++#else
++ const char* __msg = gettext(__dfault.c_str());
++ return string(__msg);
++#endif
++ }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ template<>
++ wstring
++ messages<wchar_t>::do_get(catalog, int, int, const wstring& __dfault) const
++ {
++# ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_M_c_locale_messages);
++ char* __msg = gettext(_M_convert_to_char(__dfault));
++ __uselocale(__old);
++ return _M_convert_from_char(__msg);
++# elif defined __UCLIBC_HAS_LOCALE__
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, _M_name_messages);
++ char* __msg = gettext(_M_convert_to_char(__dfault));
++ setlocale(LC_ALL, __old);
++ free(__old);
++ return _M_convert_from_char(__msg);
++# else
++ char* __msg = gettext(_M_convert_to_char(__dfault));
++ return _M_convert_from_char(__msg);
++# endif
++ }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/messages_members.h gcc-3.4.2/libstdc++-v3/config/locale/uclibc/messages_members.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/messages_members.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/messages_members.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,118 @@
++// std::messages implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.7.1.2 messages functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix prototypes for *textdomain funcs
++#endif
++#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
++extern "C" char *__textdomain(const char *domainname);
++extern "C" char *__bindtextdomain(const char *domainname,
++ const char *dirname);
++#else
++#undef __textdomain
++#undef __bindtextdomain
++#define __textdomain(D) ((void)0)
++#define __bindtextdomain(D,P) ((void)0)
++#endif
++
++ // Non-virtual member functions.
++ template<typename _CharT>
++ messages<_CharT>::messages(size_t __refs)
++ : facet(__refs), _M_c_locale_messages(_S_get_c_locale()),
++ _M_name_messages(_S_get_c_name())
++ { }
++
++ template<typename _CharT>
++ messages<_CharT>::messages(__c_locale __cloc, const char* __s,
++ size_t __refs)
++ : facet(__refs), _M_c_locale_messages(_S_clone_c_locale(__cloc)),
++ _M_name_messages(__s)
++ {
++ char* __tmp = new char[std::strlen(__s) + 1];
++ std::strcpy(__tmp, __s);
++ _M_name_messages = __tmp;
++ }
++
++ template<typename _CharT>
++ typename messages<_CharT>::catalog
++ messages<_CharT>::open(const basic_string<char>& __s, const locale& __loc,
++ const char* __dir) const
++ {
++ __bindtextdomain(__s.c_str(), __dir);
++ return this->do_open(__s, __loc);
++ }
++
++ // Virtual member functions.
++ template<typename _CharT>
++ messages<_CharT>::~messages()
++ {
++ if (_M_name_messages != _S_get_c_name())
++ delete [] _M_name_messages;
++ _S_destroy_c_locale(_M_c_locale_messages);
++ }
++
++ template<typename _CharT>
++ typename messages<_CharT>::catalog
++ messages<_CharT>::do_open(const basic_string<char>& __s,
++ const locale&) const
++ {
++ // No error checking is done, assume the catalog exists and can
++ // be used.
++ __textdomain(__s.c_str());
++ return 0;
++ }
++
++ template<typename _CharT>
++ void
++ messages<_CharT>::do_close(catalog) const
++ { }
++
++ // messages_byname
++ template<typename _CharT>
++ messages_byname<_CharT>::messages_byname(const char* __s, size_t __refs)
++ : messages<_CharT>(__refs)
++ {
++ if (this->_M_name_messages != locale::facet::_S_get_c_name())
++ delete [] this->_M_name_messages;
++ char* __tmp = new char[std::strlen(__s) + 1];
++ std::strcpy(__tmp, __s);
++ this->_M_name_messages = __tmp;
++
++ if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
++ {
++ this->_S_destroy_c_locale(this->_M_c_locale_messages);
++ this->_S_create_c_locale(this->_M_c_locale_messages, __s);
++ }
++ }
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/monetary_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/monetary_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/monetary_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/monetary_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,698 @@
++// std::moneypunct implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.6.3.2 moneypunct virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#define _LIBC
++#include <locale>
++#undef _LIBC
++#include <bits/c++locale_internal.h>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning optimize this for uclibc
++#warning tailor for stub locale support
++#endif
++
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __nl_langinfo_l(N, L) nl_langinfo((N))
++#endif
++
++namespace std
++{
++ // Construct and return valid pattern consisting of some combination of:
++ // space none symbol sign value
++ money_base::pattern
++ money_base::_S_construct_pattern(char __precedes, char __space, char __posn)
++ {
++ pattern __ret;
++
++ // This insanely complicated routine attempts to construct a valid
++ // pattern for use with monyepunct. A couple of invariants:
++
++ // if (__precedes) symbol -> value
++ // else value -> symbol
++
++ // if (__space) space
++ // else none
++
++ // none == never first
++ // space never first or last
++
++ // Any elegant implementations of this are welcome.
++ switch (__posn)
++ {
++ case 0:
++ case 1:
++ // 1 The sign precedes the value and symbol.
++ __ret.field[0] = sign;
++ if (__space)
++ {
++ // Pattern starts with sign.
++ if (__precedes)
++ {
++ __ret.field[1] = symbol;
++ __ret.field[3] = value;
++ }
++ else
++ {
++ __ret.field[1] = value;
++ __ret.field[3] = symbol;
++ }
++ __ret.field[2] = space;
++ }
++ else
++ {
++ // Pattern starts with sign and ends with none.
++ if (__precedes)
++ {
++ __ret.field[1] = symbol;
++ __ret.field[2] = value;
++ }
++ else
++ {
++ __ret.field[1] = value;
++ __ret.field[2] = symbol;
++ }
++ __ret.field[3] = none;
++ }
++ break;
++ case 2:
++ // 2 The sign follows the value and symbol.
++ if (__space)
++ {
++ // Pattern either ends with sign.
++ if (__precedes)
++ {
++ __ret.field[0] = symbol;
++ __ret.field[2] = value;
++ }
++ else
++ {
++ __ret.field[0] = value;
++ __ret.field[2] = symbol;
++ }
++ __ret.field[1] = space;
++ __ret.field[3] = sign;
++ }
++ else
++ {
++ // Pattern ends with sign then none.
++ if (__precedes)
++ {
++ __ret.field[0] = symbol;
++ __ret.field[1] = value;
++ }
++ else
++ {
++ __ret.field[0] = value;
++ __ret.field[1] = symbol;
++ }
++ __ret.field[2] = sign;
++ __ret.field[3] = none;
++ }
++ break;
++ case 3:
++ // 3 The sign immediately precedes the symbol.
++ if (__precedes)
++ {
++ __ret.field[0] = sign;
++ __ret.field[1] = symbol;
++ if (__space)
++ {
++ __ret.field[2] = space;
++ __ret.field[3] = value;
++ }
++ else
++ {
++ __ret.field[2] = value;
++ __ret.field[3] = none;
++ }
++ }
++ else
++ {
++ __ret.field[0] = value;
++ if (__space)
++ {
++ __ret.field[1] = space;
++ __ret.field[2] = sign;
++ __ret.field[3] = symbol;
++ }
++ else
++ {
++ __ret.field[1] = sign;
++ __ret.field[2] = symbol;
++ __ret.field[3] = none;
++ }
++ }
++ break;
++ case 4:
++ // 4 The sign immediately follows the symbol.
++ if (__precedes)
++ {
++ __ret.field[0] = symbol;
++ __ret.field[1] = sign;
++ if (__space)
++ {
++ __ret.field[2] = space;
++ __ret.field[3] = value;
++ }
++ else
++ {
++ __ret.field[2] = value;
++ __ret.field[3] = none;
++ }
++ }
++ else
++ {
++ __ret.field[0] = value;
++ if (__space)
++ {
++ __ret.field[1] = space;
++ __ret.field[2] = symbol;
++ __ret.field[3] = sign;
++ }
++ else
++ {
++ __ret.field[1] = symbol;
++ __ret.field[2] = sign;
++ __ret.field[3] = none;
++ }
++ }
++ break;
++ default:
++ ;
++ }
++ return __ret;
++ }
++
++ template<>
++ void
++ moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc,
++ const char*)
++ {
++ if (!_M_data)
++ _M_data = new __moneypunct_cache<char, true>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_decimal_point = '.';
++ _M_data->_M_thousands_sep = ',';
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_curr_symbol = "";
++ _M_data->_M_curr_symbol_size = 0;
++ _M_data->_M_positive_sign = "";
++ _M_data->_M_positive_sign_size = 0;
++ _M_data->_M_negative_sign = "";
++ _M_data->_M_negative_sign_size = 0;
++ _M_data->_M_frac_digits = 0;
++ _M_data->_M_pos_format = money_base::_S_default_pattern;
++ _M_data->_M_neg_format = money_base::_S_default_pattern;
++
++ for (size_t __i = 0; __i < money_base::_S_end; ++__i)
++ _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
++ }
++ else
++ {
++ // Named locale.
++ _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT,
++ __cloc));
++ _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP,
++ __cloc));
++ _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++ _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
++ _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign);
++
++ char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
++ if (!__nposn)
++ _M_data->_M_negative_sign = "()";
++ else
++ _M_data->_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN,
++ __cloc);
++ _M_data->_M_negative_sign_size = strlen(_M_data->_M_negative_sign);
++
++ // _Intl == true
++ _M_data->_M_curr_symbol = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
++ _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol);
++ _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
++ __cloc));
++ char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
++ char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
++ char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
++ _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
++ __pposn);
++ char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
++ char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
++ _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
++ __nposn);
++ }
++ }
++
++ template<>
++ void
++ moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc,
++ const char*)
++ {
++ if (!_M_data)
++ _M_data = new __moneypunct_cache<char, false>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_decimal_point = '.';
++ _M_data->_M_thousands_sep = ',';
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_curr_symbol = "";
++ _M_data->_M_curr_symbol_size = 0;
++ _M_data->_M_positive_sign = "";
++ _M_data->_M_positive_sign_size = 0;
++ _M_data->_M_negative_sign = "";
++ _M_data->_M_negative_sign_size = 0;
++ _M_data->_M_frac_digits = 0;
++ _M_data->_M_pos_format = money_base::_S_default_pattern;
++ _M_data->_M_neg_format = money_base::_S_default_pattern;
++
++ for (size_t __i = 0; __i < money_base::_S_end; ++__i)
++ _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
++ }
++ else
++ {
++ // Named locale.
++ _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT,
++ __cloc));
++ _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP,
++ __cloc));
++ _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++ _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
++ _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign);
++
++ char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
++ if (!__nposn)
++ _M_data->_M_negative_sign = "()";
++ else
++ _M_data->_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN,
++ __cloc);
++ _M_data->_M_negative_sign_size = strlen(_M_data->_M_negative_sign);
++
++ // _Intl == false
++ _M_data->_M_curr_symbol = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
++ _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol);
++ _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
++ char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
++ char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
++ char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
++ _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
++ __pposn);
++ char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
++ char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
++ _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
++ __nposn);
++ }
++ }
++
++ template<>
++ moneypunct<char, true>::~moneypunct()
++ { delete _M_data; }
++
++ template<>
++ moneypunct<char, false>::~moneypunct()
++ { delete _M_data; }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ template<>
++ void
++ moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc,
++#ifdef __UCLIBC_HAS_XLOCALE__
++ const char*)
++#else
++ const char* __name)
++#endif
++ {
++ if (!_M_data)
++ _M_data = new __moneypunct_cache<wchar_t, true>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_decimal_point = L'.';
++ _M_data->_M_thousands_sep = L',';
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_curr_symbol = L"";
++ _M_data->_M_curr_symbol_size = 0;
++ _M_data->_M_positive_sign = L"";
++ _M_data->_M_positive_sign_size = 0;
++ _M_data->_M_negative_sign = L"";
++ _M_data->_M_negative_sign_size = 0;
++ _M_data->_M_frac_digits = 0;
++ _M_data->_M_pos_format = money_base::_S_default_pattern;
++ _M_data->_M_neg_format = money_base::_S_default_pattern;
++
++ // Use ctype::widen code without the facet...
++ unsigned char uc;
++ for (size_t __i = 0; __i < money_base::_S_end; ++__i)
++ {
++ uc = static_cast<unsigned char>(money_base::_S_atoms[__i]);
++ _M_data->_M_atoms[__i] = btowc(uc);
++ }
++ }
++ else
++ {
++ // Named locale.
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(__cloc);
++#else
++ // Switch to named locale so that mbsrtowcs will work.
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, __name);
++#endif
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix this... should be monetary
++#endif
++#ifdef __UCLIBC__
++# ifdef __UCLIBC_HAS_XLOCALE__
++ _M_data->_M_decimal_point = __cloc->decimal_point_wc;
++ _M_data->_M_thousands_sep = __cloc->thousands_sep_wc;
++# else
++ _M_data->_M_decimal_point = __global_locale->decimal_point_wc;
++ _M_data->_M_thousands_sep = __global_locale->thousands_sep_wc;
++# endif
++#else
++ union __s_and_w { const char *__s; unsigned int __w; } __u;
++ __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
++ _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
++
++ __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
++ _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
++#endif
++ _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++
++ const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
++ const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
++ const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
++
++ wchar_t* __wcs_ps = 0;
++ wchar_t* __wcs_ns = 0;
++ const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
++ try
++ {
++ mbstate_t __state;
++ size_t __len = strlen(__cpossign);
++ if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ __wcs_ps = new wchar_t[__len];
++ mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
++ _M_data->_M_positive_sign = __wcs_ps;
++ }
++ else
++ _M_data->_M_positive_sign = L"";
++ _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
++
++ __len = strlen(__cnegsign);
++ if (!__nposn)
++ _M_data->_M_negative_sign = L"()";
++ else if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ __wcs_ns = new wchar_t[__len];
++ mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
++ _M_data->_M_negative_sign = __wcs_ns;
++ }
++ else
++ _M_data->_M_negative_sign = L"";
++ _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
++
++ // _Intl == true.
++ __len = strlen(__ccurr);
++ if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ wchar_t* __wcs = new wchar_t[__len];
++ mbsrtowcs(__wcs, &__ccurr, __len, &__state);
++ _M_data->_M_curr_symbol = __wcs;
++ }
++ else
++ _M_data->_M_curr_symbol = L"";
++ _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
++ }
++ catch (...)
++ {
++ delete _M_data;
++ _M_data = 0;
++ delete __wcs_ps;
++ delete __wcs_ns;
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#else
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ __throw_exception_again;
++ }
++
++ _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
++ __cloc));
++ char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
++ char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
++ char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
++ _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
++ __pposn);
++ char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
++ char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
++ _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
++ __nposn);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#else
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ }
++ }
++
++ template<>
++ void
++ moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
++#ifdef __UCLIBC_HAS_XLOCALE__
++ const char*)
++#else
++ const char* __name)
++#endif
++ {
++ if (!_M_data)
++ _M_data = new __moneypunct_cache<wchar_t, false>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_decimal_point = L'.';
++ _M_data->_M_thousands_sep = L',';
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_curr_symbol = L"";
++ _M_data->_M_curr_symbol_size = 0;
++ _M_data->_M_positive_sign = L"";
++ _M_data->_M_positive_sign_size = 0;
++ _M_data->_M_negative_sign = L"";
++ _M_data->_M_negative_sign_size = 0;
++ _M_data->_M_frac_digits = 0;
++ _M_data->_M_pos_format = money_base::_S_default_pattern;
++ _M_data->_M_neg_format = money_base::_S_default_pattern;
++
++ // Use ctype::widen code without the facet...
++ unsigned char uc;
++ for (size_t __i = 0; __i < money_base::_S_end; ++__i)
++ {
++ uc = static_cast<unsigned char>(money_base::_S_atoms[__i]);
++ _M_data->_M_atoms[__i] = btowc(uc);
++ }
++ }
++ else
++ {
++ // Named locale.
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(__cloc);
++#else
++ // Switch to named locale so that mbsrtowcs will work.
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, __name);
++#endif
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix this... should be monetary
++#endif
++#ifdef __UCLIBC__
++# ifdef __UCLIBC_HAS_XLOCALE__
++ _M_data->_M_decimal_point = __cloc->decimal_point_wc;
++ _M_data->_M_thousands_sep = __cloc->thousands_sep_wc;
++# else
++ _M_data->_M_decimal_point = __global_locale->decimal_point_wc;
++ _M_data->_M_thousands_sep = __global_locale->thousands_sep_wc;
++# endif
++#else
++ union __s_and_w { const char *__s; unsigned int __w; } __u;
++ __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
++ _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
++
++ __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
++ _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
++#endif
++ _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++
++ const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
++ const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
++ const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
++
++ wchar_t* __wcs_ps = 0;
++ wchar_t* __wcs_ns = 0;
++ const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
++ try
++ {
++ mbstate_t __state;
++ size_t __len;
++ __len = strlen(__cpossign);
++ if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ __wcs_ps = new wchar_t[__len];
++ mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
++ _M_data->_M_positive_sign = __wcs_ps;
++ }
++ else
++ _M_data->_M_positive_sign = L"";
++ _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
++
++ __len = strlen(__cnegsign);
++ if (!__nposn)
++ _M_data->_M_negative_sign = L"()";
++ else if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ __wcs_ns = new wchar_t[__len];
++ mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
++ _M_data->_M_negative_sign = __wcs_ns;
++ }
++ else
++ _M_data->_M_negative_sign = L"";
++ _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
++
++ // _Intl == true.
++ __len = strlen(__ccurr);
++ if (__len)
++ {
++ ++__len;
++ memset(&__state, 0, sizeof(mbstate_t));
++ wchar_t* __wcs = new wchar_t[__len];
++ mbsrtowcs(__wcs, &__ccurr, __len, &__state);
++ _M_data->_M_curr_symbol = __wcs;
++ }
++ else
++ _M_data->_M_curr_symbol = L"";
++ _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
++ }
++ catch (...)
++ {
++ delete _M_data;
++ _M_data = 0;
++ delete __wcs_ps;
++ delete __wcs_ns;
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#else
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ __throw_exception_again;
++ }
++
++ _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
++ char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
++ char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
++ char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
++ _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
++ __pposn);
++ char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
++ char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
++ _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
++ __nposn);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#else
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ }
++ }
++
++ template<>
++ moneypunct<wchar_t, true>::~moneypunct()
++ {
++ if (_M_data->_M_positive_sign_size)
++ delete [] _M_data->_M_positive_sign;
++ if (_M_data->_M_negative_sign_size
++ && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
++ delete [] _M_data->_M_negative_sign;
++ if (_M_data->_M_curr_symbol_size)
++ delete [] _M_data->_M_curr_symbol;
++ delete _M_data;
++ }
++
++ template<>
++ moneypunct<wchar_t, false>::~moneypunct()
++ {
++ if (_M_data->_M_positive_sign_size)
++ delete [] _M_data->_M_positive_sign;
++ if (_M_data->_M_negative_sign_size
++ && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
++ delete [] _M_data->_M_negative_sign;
++ if (_M_data->_M_curr_symbol_size)
++ delete [] _M_data->_M_curr_symbol;
++ delete _M_data;
++ }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/numeric_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/numeric_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/numeric_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/numeric_members.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,183 @@
++// std::numpunct implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.3.1.2 numpunct virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#define _LIBC
++#include <locale>
++#undef _LIBC
++#include <bits/c++locale_internal.h>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning tailor for stub locale support
++#endif
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __nl_langinfo_l(N, L) nl_langinfo((N))
++#endif
++
++namespace std
++{
++ template<>
++ void
++ numpunct<char>::_M_initialize_numpunct(__c_locale __cloc)
++ {
++ if (!_M_data)
++ _M_data = new __numpunct_cache<char>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_use_grouping = false;
++
++ _M_data->_M_decimal_point = '.';
++ _M_data->_M_thousands_sep = ',';
++
++ for (size_t __i = 0; __i < __num_base::_S_oend; ++__i)
++ _M_data->_M_atoms_out[__i] = __num_base::_S_atoms_out[__i];
++
++ for (size_t __j = 0; __j < __num_base::_S_iend; ++__j)
++ _M_data->_M_atoms_in[__j] = __num_base::_S_atoms_in[__j];
++ }
++ else
++ {
++ // Named locale.
++ _M_data->_M_decimal_point = *(__nl_langinfo_l(DECIMAL_POINT,
++ __cloc));
++ _M_data->_M_thousands_sep = *(__nl_langinfo_l(THOUSANDS_SEP,
++ __cloc));
++
++ // Check for NULL, which implies no grouping.
++ if (_M_data->_M_thousands_sep == '\0')
++ _M_data->_M_grouping = "";
++ else
++ _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++ }
++
++ // NB: There is no way to extact this info from posix locales.
++ // _M_truename = __nl_langinfo_l(YESSTR, __cloc);
++ _M_data->_M_truename = "true";
++ _M_data->_M_truename_size = strlen(_M_data->_M_truename);
++ // _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
++ _M_data->_M_falsename = "false";
++ _M_data->_M_falsename_size = strlen(_M_data->_M_falsename);
++ }
++
++ template<>
++ numpunct<char>::~numpunct()
++ { delete _M_data; }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ template<>
++ void
++ numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc)
++ {
++ if (!_M_data)
++ _M_data = new __numpunct_cache<wchar_t>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_data->_M_grouping = "";
++ _M_data->_M_grouping_size = 0;
++ _M_data->_M_use_grouping = false;
++
++ _M_data->_M_decimal_point = L'.';
++ _M_data->_M_thousands_sep = L',';
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __c_locale __old = __uselocale(_S_get_c_locale());
++#endif
++ // Use ctype::widen code without the facet...
++ unsigned char uc;
++ for (size_t __i = 0; __i < __num_base::_S_oend; ++__i)
++ {
++ uc = static_cast<unsigned char>(__num_base::_S_atoms_out[__i]);
++ _M_data->_M_atoms_out[__i] = btowc(uc);
++ }
++
++ for (size_t __j = 0; __j < __num_base::_S_iend; ++__j)
++ {
++ uc = static_cast<unsigned char>(__num_base::_S_atoms_in[__j]);
++ _M_data->_M_atoms_in[__j] = btowc(uc);
++ }
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __uselocale(__old);
++#endif
++ }
++ else
++ {
++ // Named locale.
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix this
++#endif
++#ifdef __UCLIBC__
++# ifdef __UCLIBC_HAS_XLOCALE__
++ _M_data->_M_decimal_point = __cloc->decimal_point_wc;
++ _M_data->_M_thousands_sep = __cloc->thousands_sep_wc;
++# else
++ _M_data->_M_decimal_point = __global_locale->decimal_point_wc;
++ _M_data->_M_thousands_sep = __global_locale->thousands_sep_wc;
++# endif
++#else
++ union __s_and_w { const char *__s; unsigned int __w; } __u;
++ __u.__s = __nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc);
++ _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
++
++ __u.__s = __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc);
++ _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
++#endif
++
++ if (_M_data->_M_thousands_sep == L'\0')
++ _M_data->_M_grouping = "";
++ else
++ _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
++ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++ }
++
++ // NB: There is no way to extact this info from posix locales.
++ // _M_truename = __nl_langinfo_l(YESSTR, __cloc);
++ _M_data->_M_truename = L"true";
++ _M_data->_M_truename_size = wcslen(_M_data->_M_truename);
++ // _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
++ _M_data->_M_falsename = L"false";
++ _M_data->_M_falsename_size = wcslen(_M_data->_M_falsename);
++ }
++
++ template<>
++ numpunct<wchar_t>::~numpunct()
++ { delete _M_data; }
++ #endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/time_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/time_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/time_members.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/time_members.cc 2004-09-10 10:48:00.000000000 -0500
+@@ -0,0 +1,356 @@
++// std::time_get, std::time_put implementation, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.5.1.2 - time_get virtual functions
++// ISO C++ 14882: 22.2.5.3.2 - time_put virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <locale>
++#include <bits/c++locale_internal.h>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning tailor for stub locale support
++#endif
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __nl_langinfo_l(N, L) nl_langinfo((N))
++#endif
++
++namespace std
++{
++ template<>
++ void
++ __timepunct<char>::
++ _M_put(char* __s, size_t __maxlen, const char* __format,
++ const tm* __tm) const
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ const size_t __len = __strftime_l(__s, __maxlen, __format, __tm,
++ _M_c_locale_timepunct);
++#else
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, _M_name_timepunct);
++ const size_t __len = strftime(__s, __maxlen, __format, __tm);
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ // Make sure __s is null terminated.
++ if (__len == 0)
++ __s[0] = '\0';
++ }
++
++ template<>
++ void
++ __timepunct<char>::_M_initialize_timepunct(__c_locale __cloc)
++ {
++ if (!_M_data)
++ _M_data = new __timepunct_cache<char>;
++
++ if (!__cloc)
++ {
++ // "C" locale
++ _M_c_locale_timepunct = _S_get_c_locale();
++
++ _M_data->_M_date_format = "%m/%d/%y";
++ _M_data->_M_date_era_format = "%m/%d/%y";
++ _M_data->_M_time_format = "%H:%M:%S";
++ _M_data->_M_time_era_format = "%H:%M:%S";
++ _M_data->_M_date_time_format = "";
++ _M_data->_M_date_time_era_format = "";
++ _M_data->_M_am = "AM";
++ _M_data->_M_pm = "PM";
++ _M_data->_M_am_pm_format = "";
++
++ // Day names, starting with "C"'s Sunday.
++ _M_data->_M_day1 = "Sunday";
++ _M_data->_M_day2 = "Monday";
++ _M_data->_M_day3 = "Tuesday";
++ _M_data->_M_day4 = "Wednesday";
++ _M_data->_M_day5 = "Thursday";
++ _M_data->_M_day6 = "Friday";
++ _M_data->_M_day7 = "Saturday";
++
++ // Abbreviated day names, starting with "C"'s Sun.
++ _M_data->_M_aday1 = "Sun";
++ _M_data->_M_aday2 = "Mon";
++ _M_data->_M_aday3 = "Tue";
++ _M_data->_M_aday4 = "Wed";
++ _M_data->_M_aday5 = "Thu";
++ _M_data->_M_aday6 = "Fri";
++ _M_data->_M_aday7 = "Sat";
++
++ // Month names, starting with "C"'s January.
++ _M_data->_M_month01 = "January";
++ _M_data->_M_month02 = "February";
++ _M_data->_M_month03 = "March";
++ _M_data->_M_month04 = "April";
++ _M_data->_M_month05 = "May";
++ _M_data->_M_month06 = "June";
++ _M_data->_M_month07 = "July";
++ _M_data->_M_month08 = "August";
++ _M_data->_M_month09 = "September";
++ _M_data->_M_month10 = "October";
++ _M_data->_M_month11 = "November";
++ _M_data->_M_month12 = "December";
++
++ // Abbreviated month names, starting with "C"'s Jan.
++ _M_data->_M_amonth01 = "Jan";
++ _M_data->_M_amonth02 = "Feb";
++ _M_data->_M_amonth03 = "Mar";
++ _M_data->_M_amonth04 = "Apr";
++ _M_data->_M_amonth05 = "May";
++ _M_data->_M_amonth06 = "Jun";
++ _M_data->_M_amonth07 = "Jul";
++ _M_data->_M_amonth08 = "Aug";
++ _M_data->_M_amonth09 = "Sep";
++ _M_data->_M_amonth10 = "Oct";
++ _M_data->_M_amonth11 = "Nov";
++ _M_data->_M_amonth12 = "Dec";
++ }
++ else
++ {
++ _M_c_locale_timepunct = _S_clone_c_locale(__cloc);
++
++ _M_data->_M_date_format = __nl_langinfo_l(D_FMT, __cloc);
++ _M_data->_M_date_era_format = __nl_langinfo_l(ERA_D_FMT, __cloc);
++ _M_data->_M_time_format = __nl_langinfo_l(T_FMT, __cloc);
++ _M_data->_M_time_era_format = __nl_langinfo_l(ERA_T_FMT, __cloc);
++ _M_data->_M_date_time_format = __nl_langinfo_l(D_T_FMT, __cloc);
++ _M_data->_M_date_time_era_format = __nl_langinfo_l(ERA_D_T_FMT, __cloc);
++ _M_data->_M_am = __nl_langinfo_l(AM_STR, __cloc);
++ _M_data->_M_pm = __nl_langinfo_l(PM_STR, __cloc);
++ _M_data->_M_am_pm_format = __nl_langinfo_l(T_FMT_AMPM, __cloc);
++
++ // Day names, starting with "C"'s Sunday.
++ _M_data->_M_day1 = __nl_langinfo_l(DAY_1, __cloc);
++ _M_data->_M_day2 = __nl_langinfo_l(DAY_2, __cloc);
++ _M_data->_M_day3 = __nl_langinfo_l(DAY_3, __cloc);
++ _M_data->_M_day4 = __nl_langinfo_l(DAY_4, __cloc);
++ _M_data->_M_day5 = __nl_langinfo_l(DAY_5, __cloc);
++ _M_data->_M_day6 = __nl_langinfo_l(DAY_6, __cloc);
++ _M_data->_M_day7 = __nl_langinfo_l(DAY_7, __cloc);
++
++ // Abbreviated day names, starting with "C"'s Sun.
++ _M_data->_M_aday1 = __nl_langinfo_l(ABDAY_1, __cloc);
++ _M_data->_M_aday2 = __nl_langinfo_l(ABDAY_2, __cloc);
++ _M_data->_M_aday3 = __nl_langinfo_l(ABDAY_3, __cloc);
++ _M_data->_M_aday4 = __nl_langinfo_l(ABDAY_4, __cloc);
++ _M_data->_M_aday5 = __nl_langinfo_l(ABDAY_5, __cloc);
++ _M_data->_M_aday6 = __nl_langinfo_l(ABDAY_6, __cloc);
++ _M_data->_M_aday7 = __nl_langinfo_l(ABDAY_7, __cloc);
++
++ // Month names, starting with "C"'s January.
++ _M_data->_M_month01 = __nl_langinfo_l(MON_1, __cloc);
++ _M_data->_M_month02 = __nl_langinfo_l(MON_2, __cloc);
++ _M_data->_M_month03 = __nl_langinfo_l(MON_3, __cloc);
++ _M_data->_M_month04 = __nl_langinfo_l(MON_4, __cloc);
++ _M_data->_M_month05 = __nl_langinfo_l(MON_5, __cloc);
++ _M_data->_M_month06 = __nl_langinfo_l(MON_6, __cloc);
++ _M_data->_M_month07 = __nl_langinfo_l(MON_7, __cloc);
++ _M_data->_M_month08 = __nl_langinfo_l(MON_8, __cloc);
++ _M_data->_M_month09 = __nl_langinfo_l(MON_9, __cloc);
++ _M_data->_M_month10 = __nl_langinfo_l(MON_10, __cloc);
++ _M_data->_M_month11 = __nl_langinfo_l(MON_11, __cloc);
++ _M_data->_M_month12 = __nl_langinfo_l(MON_12, __cloc);
++
++ // Abbreviated month names, starting with "C"'s Jan.
++ _M_data->_M_amonth01 = __nl_langinfo_l(ABMON_1, __cloc);
++ _M_data->_M_amonth02 = __nl_langinfo_l(ABMON_2, __cloc);
++ _M_data->_M_amonth03 = __nl_langinfo_l(ABMON_3, __cloc);
++ _M_data->_M_amonth04 = __nl_langinfo_l(ABMON_4, __cloc);
++ _M_data->_M_amonth05 = __nl_langinfo_l(ABMON_5, __cloc);
++ _M_data->_M_amonth06 = __nl_langinfo_l(ABMON_6, __cloc);
++ _M_data->_M_amonth07 = __nl_langinfo_l(ABMON_7, __cloc);
++ _M_data->_M_amonth08 = __nl_langinfo_l(ABMON_8, __cloc);
++ _M_data->_M_amonth09 = __nl_langinfo_l(ABMON_9, __cloc);
++ _M_data->_M_amonth10 = __nl_langinfo_l(ABMON_10, __cloc);
++ _M_data->_M_amonth11 = __nl_langinfo_l(ABMON_11, __cloc);
++ _M_data->_M_amonth12 = __nl_langinfo_l(ABMON_12, __cloc);
++ }
++ }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++ template<>
++ void
++ __timepunct<wchar_t>::
++ _M_put(wchar_t* __s, size_t __maxlen, const wchar_t* __format,
++ const tm* __tm) const
++ {
++#ifdef __UCLIBC_HAS_XLOCALE__
++ __wcsftime_l(__s, __maxlen, __format, __tm, _M_c_locale_timepunct);
++ const size_t __len = __wcsftime_l(__s, __maxlen, __format, __tm,
++ _M_c_locale_timepunct);
++#else
++ char* __old = strdup(setlocale(LC_ALL, NULL));
++ setlocale(LC_ALL, _M_name_timepunct);
++ const size_t __len = wcsftime(__s, __maxlen, __format, __tm);
++ setlocale(LC_ALL, __old);
++ free(__old);
++#endif
++ // Make sure __s is null terminated.
++ if (__len == 0)
++ __s[0] = L'\0';
++ }
++
++ template<>
++ void
++ __timepunct<wchar_t>::_M_initialize_timepunct(__c_locale __cloc)
++ {
++ if (!_M_data)
++ _M_data = new __timepunct_cache<wchar_t>;
++
++#warning wide time stuff
++// if (!__cloc)
++ {
++ // "C" locale
++ _M_c_locale_timepunct = _S_get_c_locale();
++
++ _M_data->_M_date_format = L"%m/%d/%y";
++ _M_data->_M_date_era_format = L"%m/%d/%y";
++ _M_data->_M_time_format = L"%H:%M:%S";
++ _M_data->_M_time_era_format = L"%H:%M:%S";
++ _M_data->_M_date_time_format = L"";
++ _M_data->_M_date_time_era_format = L"";
++ _M_data->_M_am = L"AM";
++ _M_data->_M_pm = L"PM";
++ _M_data->_M_am_pm_format = L"";
++
++ // Day names, starting with "C"'s Sunday.
++ _M_data->_M_day1 = L"Sunday";
++ _M_data->_M_day2 = L"Monday";
++ _M_data->_M_day3 = L"Tuesday";
++ _M_data->_M_day4 = L"Wednesday";
++ _M_data->_M_day5 = L"Thursday";
++ _M_data->_M_day6 = L"Friday";
++ _M_data->_M_day7 = L"Saturday";
++
++ // Abbreviated day names, starting with "C"'s Sun.
++ _M_data->_M_aday1 = L"Sun";
++ _M_data->_M_aday2 = L"Mon";
++ _M_data->_M_aday3 = L"Tue";
++ _M_data->_M_aday4 = L"Wed";
++ _M_data->_M_aday5 = L"Thu";
++ _M_data->_M_aday6 = L"Fri";
++ _M_data->_M_aday7 = L"Sat";
++
++ // Month names, starting with "C"'s January.
++ _M_data->_M_month01 = L"January";
++ _M_data->_M_month02 = L"February";
++ _M_data->_M_month03 = L"March";
++ _M_data->_M_month04 = L"April";
++ _M_data->_M_month05 = L"May";
++ _M_data->_M_month06 = L"June";
++ _M_data->_M_month07 = L"July";
++ _M_data->_M_month08 = L"August";
++ _M_data->_M_month09 = L"September";
++ _M_data->_M_month10 = L"October";
++ _M_data->_M_month11 = L"November";
++ _M_data->_M_month12 = L"December";
++
++ // Abbreviated month names, starting with "C"'s Jan.
++ _M_data->_M_amonth01 = L"Jan";
++ _M_data->_M_amonth02 = L"Feb";
++ _M_data->_M_amonth03 = L"Mar";
++ _M_data->_M_amonth04 = L"Apr";
++ _M_data->_M_amonth05 = L"May";
++ _M_data->_M_amonth06 = L"Jun";
++ _M_data->_M_amonth07 = L"Jul";
++ _M_data->_M_amonth08 = L"Aug";
++ _M_data->_M_amonth09 = L"Sep";
++ _M_data->_M_amonth10 = L"Oct";
++ _M_data->_M_amonth11 = L"Nov";
++ _M_data->_M_amonth12 = L"Dec";
++ }
++#if 0
++ else
++ {
++ _M_c_locale_timepunct = _S_clone_c_locale(__cloc);
++
++ _M_data->_M_date_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WD_FMT, __cloc));
++ _M_data->_M_date_era_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WERA_D_FMT, __cloc));
++ _M_data->_M_time_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WT_FMT, __cloc));
++ _M_data->_M_time_era_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WERA_T_FMT, __cloc));
++ _M_data->_M_date_time_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WD_T_FMT, __cloc));
++ _M_data->_M_date_time_era_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WERA_D_T_FMT, __cloc));
++ _M_data->_M_am = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WAM_STR, __cloc));
++ _M_data->_M_pm = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WPM_STR, __cloc));
++ _M_data->_M_am_pm_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WT_FMT_AMPM, __cloc));
++
++ // Day names, starting with "C"'s Sunday.
++ _M_data->_M_day1 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_1, __cloc));
++ _M_data->_M_day2 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_2, __cloc));
++ _M_data->_M_day3 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_3, __cloc));
++ _M_data->_M_day4 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_4, __cloc));
++ _M_data->_M_day5 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_5, __cloc));
++ _M_data->_M_day6 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_6, __cloc));
++ _M_data->_M_day7 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_7, __cloc));
++
++ // Abbreviated day names, starting with "C"'s Sun.
++ _M_data->_M_aday1 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_1, __cloc));
++ _M_data->_M_aday2 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_2, __cloc));
++ _M_data->_M_aday3 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_3, __cloc));
++ _M_data->_M_aday4 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_4, __cloc));
++ _M_data->_M_aday5 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_5, __cloc));
++ _M_data->_M_aday6 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_6, __cloc));
++ _M_data->_M_aday7 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_7, __cloc));
++
++ // Month names, starting with "C"'s January.
++ _M_data->_M_month01 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_1, __cloc));
++ _M_data->_M_month02 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_2, __cloc));
++ _M_data->_M_month03 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_3, __cloc));
++ _M_data->_M_month04 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_4, __cloc));
++ _M_data->_M_month05 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_5, __cloc));
++ _M_data->_M_month06 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_6, __cloc));
++ _M_data->_M_month07 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_7, __cloc));
++ _M_data->_M_month08 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_8, __cloc));
++ _M_data->_M_month09 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_9, __cloc));
++ _M_data->_M_month10 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_10, __cloc));
++ _M_data->_M_month11 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_11, __cloc));
++ _M_data->_M_month12 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_12, __cloc));
++
++ // Abbreviated month names, starting with "C"'s Jan.
++ _M_data->_M_amonth01 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_1, __cloc));
++ _M_data->_M_amonth02 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_2, __cloc));
++ _M_data->_M_amonth03 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_3, __cloc));
++ _M_data->_M_amonth04 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_4, __cloc));
++ _M_data->_M_amonth05 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_5, __cloc));
++ _M_data->_M_amonth06 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_6, __cloc));
++ _M_data->_M_amonth07 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_7, __cloc));
++ _M_data->_M_amonth08 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_8, __cloc));
++ _M_data->_M_amonth09 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_9, __cloc));
++ _M_data->_M_amonth10 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_10, __cloc));
++ _M_data->_M_amonth11 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_11, __cloc));
++ _M_data->_M_amonth12 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_12, __cloc));
++ }
++#endif // 0
++ }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/time_members.h gcc-3.4.2/libstdc++-v3/config/locale/uclibc/time_members.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/time_members.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/time_members.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,68 @@
++// std::time_get, std::time_put implementation, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.5.1.2 - time_get functions
++// ISO C++ 14882: 22.2.5.3.2 - time_put functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++ template<typename _CharT>
++ __timepunct<_CharT>::__timepunct(size_t __refs)
++ : facet(__refs), _M_data(NULL), _M_c_locale_timepunct(NULL),
++ _M_name_timepunct(_S_get_c_name())
++ { _M_initialize_timepunct(); }
++
++ template<typename _CharT>
++ __timepunct<_CharT>::__timepunct(__cache_type* __cache, size_t __refs)
++ : facet(__refs), _M_data(__cache), _M_c_locale_timepunct(NULL),
++ _M_name_timepunct(_S_get_c_name())
++ { _M_initialize_timepunct(); }
++
++ template<typename _CharT>
++ __timepunct<_CharT>::__timepunct(__c_locale __cloc, const char* __s,
++ size_t __refs)
++ : facet(__refs), _M_data(NULL), _M_c_locale_timepunct(NULL),
++ _M_name_timepunct(__s)
++ {
++ char* __tmp = new char[std::strlen(__s) + 1];
++ std::strcpy(__tmp, __s);
++ _M_name_timepunct = __tmp;
++ _M_initialize_timepunct(__cloc);
++ }
++
++ template<typename _CharT>
++ __timepunct<_CharT>::~__timepunct()
++ {
++ if (_M_name_timepunct != _S_get_c_name())
++ delete [] _M_name_timepunct;
++ delete _M_data;
++ _S_destroy_c_locale(_M_c_locale_timepunct);
++ }
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_base.h gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_base.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_base.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_base.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,58 @@
++// Locale support -*- C++ -*-
++
++// Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003
++// Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.1 Locales
++//
++
++// Information as gleaned from /usr/include/ctype.h
++
++ struct ctype_base
++ {
++ // Note: In uClibc, the following two types depend on configuration.
++
++ // Non-standard typedefs.
++ typedef const __ctype_touplow_t* __to_type;
++
++ // NB: Offsets into ctype<char>::_M_table force a particular size
++ // on the mask type. Because of this, we don't use an enum.
++ typedef __ctype_mask_t mask;
++ static const mask upper = _ISupper;
++ static const mask lower = _ISlower;
++ static const mask alpha = _ISalpha;
++ static const mask digit = _ISdigit;
++ static const mask xdigit = _ISxdigit;
++ static const mask space = _ISspace;
++ static const mask print = _ISprint;
++ static const mask graph = _ISalpha | _ISdigit | _ISpunct;
++ static const mask cntrl = _IScntrl;
++ static const mask punct = _ISpunct;
++ static const mask alnum = _ISalpha | _ISdigit;
++ };
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_inline.h gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_inline.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_inline.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_inline.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,69 @@
++// Locale support -*- C++ -*-
++
++// Copyright (C) 2000, 2002 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.1 Locales
++//
++
++// ctype bits to be inlined go here. Non-inlinable (ie virtual do_*)
++// functions go in ctype.cc
++
++ bool
++ ctype<char>::
++ is(mask __m, char __c) const
++ { return _M_table[static_cast<unsigned char>(__c)] & __m; }
++
++ const char*
++ ctype<char>::
++ is(const char* __low, const char* __high, mask* __vec) const
++ {
++ while (__low < __high)
++ *__vec++ = _M_table[static_cast<unsigned char>(*__low++)];
++ return __high;
++ }
++
++ const char*
++ ctype<char>::
++ scan_is(mask __m, const char* __low, const char* __high) const
++ {
++ while (__low < __high
++ && !(_M_table[static_cast<unsigned char>(*__low)] & __m))
++ ++__low;
++ return __low;
++ }
++
++ const char*
++ ctype<char>::
++ scan_not(mask __m, const char* __low, const char* __high) const
++ {
++ while (__low < __high
++ && (_M_table[static_cast<unsigned char>(*__low)] & __m) != 0)
++ ++__low;
++ return __low;
++ }
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_noninline.h gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_noninline.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_noninline.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_noninline.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,92 @@
++// Locale support -*- C++ -*-
++
++// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2004
++// Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.1 Locales
++//
++
++// Information as gleaned from /usr/include/ctype.h
++
++ const ctype_base::mask*
++ ctype<char>::classic_table() throw()
++ { return __C_ctype_b; }
++
++ ctype<char>::ctype(__c_locale, const mask* __table, bool __del,
++ size_t __refs)
++ : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()),
++ _M_del(__table != 0 && __del), _M_widen_ok(0), _M_narrow_ok(0)
++ {
++ _M_toupper = __C_ctype_toupper;
++ _M_tolower = __C_ctype_tolower;
++ _M_table = __table ? __table : __C_ctype_b;
++ memset(_M_widen, 0, sizeof(_M_widen));
++ memset(_M_narrow, 0, sizeof(_M_narrow));
++ }
++
++ ctype<char>::ctype(const mask* __table, bool __del, size_t __refs)
++ : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()),
++ _M_del(__table != 0 && __del), _M_widen_ok(0), _M_narrow_ok(0)
++ {
++ _M_toupper = __C_ctype_toupper;
++ _M_tolower = __C_ctype_tolower;
++ _M_table = __table ? __table : __C_ctype_b;
++ memset(_M_widen, 0, sizeof(_M_widen));
++ memset(_M_narrow, 0, sizeof(_M_narrow));
++ }
++
++ char
++ ctype<char>::do_toupper(char __c) const
++ { return _M_toupper[static_cast<unsigned char>(__c)]; }
++
++ const char*
++ ctype<char>::do_toupper(char* __low, const char* __high) const
++ {
++ while (__low < __high)
++ {
++ *__low = _M_toupper[static_cast<unsigned char>(*__low)];
++ ++__low;
++ }
++ return __high;
++ }
++
++ char
++ ctype<char>::do_tolower(char __c) const
++ { return _M_tolower[static_cast<unsigned char>(__c)]; }
++
++ const char*
++ ctype<char>::do_tolower(char* __low, const char* __high) const
++ {
++ while (__low < __high)
++ {
++ *__low = _M_tolower[static_cast<unsigned char>(*__low)];
++ ++__low;
++ }
++ return __high;
++ }
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/os_defines.h gcc-3.4.2/libstdc++-v3/config/os/uclibc/os_defines.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/os_defines.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/os/uclibc/os_defines.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,44 @@
++// Specific definitions for GNU/Linux -*- C++ -*-
++
++// Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++#ifndef _GLIBCXX_OS_DEFINES
++#define _GLIBCXX_OS_DEFINES 1
++
++// System-specific #define, typedefs, corrections, etc, go here. This
++// file will come before all others.
++
++// This keeps isanum, et al from being propagated as macros.
++#define __NO_CTYPE 1
++
++#include <features.h>
++
++// We must not see the optimized string functions GNU libc defines.
++#define __NO_STRING_INLINES
++
++#endif
+diff -urN gcc-3.4.2-dist/libstdc++-v3/configure gcc-3.4.2/libstdc++-v3/configure
+--- gcc-3.4.2-dist/libstdc++-v3/configure 2004-08-13 15:44:04.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/configure 2004-09-10 10:47:40.000000000 -0500
+@@ -3878,6 +3878,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+@@ -5545,6 +5550,9 @@
+ # Default to "generic".
+ if test $enable_clocale_flag = auto; then
+ case x${target_os} in
++ xlinux-uclibc*)
++ enable_clocale_flag=uclibc
++ ;;
+ xlinux* | xgnu* | xkfreebsd*-gnu | xknetbsd*-gnu)
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -5759,6 +5767,77 @@
+ CTIME_CC=config/locale/generic/time_members.cc
+ CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+ ;;
++ uclibc)
++ echo "$as_me:$LINENO: result: uclibc" >&5
++echo "${ECHO_T}uclibc" >&6
++
++ # Declare intention to use gettext, and add support for specific
++ # languages.
++ # For some reason, ALL_LINGUAS has to be before AM-GNU-GETTEXT
++ ALL_LINGUAS="de fr"
++
++ # Don't call AM-GNU-GETTEXT here. Instead, assume glibc.
++ # Extract the first word of "msgfmt", so it can be a program name with args.
++set dummy msgfmt; 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_check_msgfmt+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ if test -n "$check_msgfmt"; then
++ ac_cv_prog_check_msgfmt="$check_msgfmt" # 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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++ ac_cv_prog_check_msgfmt="yes"
++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++ break 2
++ fi
++done
++done
++
++ test -z "$ac_cv_prog_check_msgfmt" && ac_cv_prog_check_msgfmt="no"
++fi
++fi
++check_msgfmt=$ac_cv_prog_check_msgfmt
++if test -n "$check_msgfmt"; then
++ echo "$as_me:$LINENO: result: $check_msgfmt" >&5
++echo "${ECHO_T}$check_msgfmt" >&6
++else
++ echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
++fi
++
++ if test x"$check_msgfmt" = x"yes" && test x"$enable_nls" = x"yes"; then
++ USE_NLS=yes
++ fi
++ # Export the build objects.
++ for ling in $ALL_LINGUAS; do \
++ glibcxx_MOFILES="$glibcxx_MOFILES $ling.mo"; \
++ glibcxx_POFILES="$glibcxx_POFILES $ling.po"; \
++ done
++
++
++
++ CLOCALE_H=config/locale/uclibc/c_locale.h
++ CLOCALE_CC=config/locale/uclibc/c_locale.cc
++ CCODECVT_H=config/locale/ieee_1003.1-2001/codecvt_specializations.h
++ CCODECVT_CC=config/locale/uclibc/codecvt_members.cc
++ CCOLLATE_CC=config/locale/uclibc/collate_members.cc
++ CCTYPE_CC=config/locale/uclibc/ctype_members.cc
++ CMESSAGES_H=config/locale/uclibc/messages_members.h
++ CMESSAGES_CC=config/locale/uclibc/messages_members.cc
++ CMONEY_CC=config/locale/uclibc/monetary_members.cc
++ CNUMERIC_CC=config/locale/uclibc/numeric_members.cc
++ CTIME_H=config/locale/uclibc/time_members.h
++ CTIME_CC=config/locale/uclibc/time_members.cc
++ CLOCALE_INTERNAL_H=config/locale/uclibc/c++locale_internal.h
++ ;;
+ esac
+
+ # This is where the testsuite looks for locale catalogs, using the
+diff -urN gcc-3.4.2-dist/libstdc++-v3/configure.host gcc-3.4.2/libstdc++-v3/configure.host
+--- gcc-3.4.2-dist/libstdc++-v3/configure.host 2004-08-27 14:52:30.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/configure.host 2004-09-10 10:47:40.000000000 -0500
+@@ -217,6 +217,12 @@
+ ;;
+ esac
+
++# Override for uClibc since linux-uclibc gets mishandled above.
++case "${host_os}" in
++ *-uclibc*)
++ os_include_dir="os/uclibc"
++ ;;
++esac
+
+ # Set any OS-dependent and CPU-dependent bits.
+ # THIS TABLE IS SORTED. KEEP IT THAT WAY.
+diff -urN gcc-3.4.2-dist/libstdc++-v3/crossconfig.m4 gcc-3.4.2/libstdc++-v3/crossconfig.m4
+--- gcc-3.4.2-dist/libstdc++-v3/crossconfig.m4 2004-07-06 20:23:49.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/crossconfig.m4 2004-09-10 10:47:40.000000000 -0500
+@@ -138,6 +138,99 @@
+ ;;
+ esac
+ ;;
++ *-uclibc*)
++# Temporary hack until we implement the float versions of the libm funcs
++ AC_CHECK_HEADERS([nan.h ieeefp.h endian.h sys/isa_defs.h \
++ machine/endian.h machine/param.h sys/machine.h sys/types.h \
++ fp.h float.h endian.h inttypes.h locale.h float.h stdint.h])
++ SECTION_FLAGS='-ffunction-sections -fdata-sections'
++ AC_SUBST(SECTION_FLAGS)
++ GLIBCXX_CHECK_LINKER_FEATURES
++ GLIBCXX_CHECK_COMPLEX_MATH_SUPPORT
++ GLIBCXX_CHECK_WCHAR_T_SUPPORT
++
++ # For LFS.
++ AC_DEFINE(HAVE_INT64_T)
++ case "$target" in
++ *-uclinux*)
++ # Don't enable LFS with uClinux
++ ;;
++ *)
++ AC_DEFINE(_GLIBCXX_USE_LFS)
++ esac
++
++ # For showmanyc_helper().
++ AC_CHECK_HEADERS(sys/ioctl.h sys/filio.h)
++ GLIBCXX_CHECK_POLL
++ GLIBCXX_CHECK_S_ISREG_OR_S_IFREG
++
++ # For xsputn_2().
++ AC_CHECK_HEADERS(sys/uio.h)
++ GLIBCXX_CHECK_WRITEV
++
++# AC_DEFINE(HAVE_ACOSF)
++# AC_DEFINE(HAVE_ASINF)
++# AC_DEFINE(HAVE_ATANF)
++# AC_DEFINE(HAVE_ATAN2F)
++ AC_DEFINE(HAVE_CEILF)
++ AC_DEFINE(HAVE_COPYSIGN)
++# AC_DEFINE(HAVE_COPYSIGNF)
++# AC_DEFINE(HAVE_COSF)
++# AC_DEFINE(HAVE_COSHF)
++# AC_DEFINE(HAVE_EXPF)
++# AC_DEFINE(HAVE_FABSF)
++ AC_DEFINE(HAVE_FINITE)
++ AC_DEFINE(HAVE_FINITEF)
++ AC_DEFINE(HAVE_FLOORF)
++# AC_DEFINE(HAVE_FMODF)
++# AC_DEFINE(HAVE_FREXPF)
++ AC_DEFINE(HAVE_HYPOT)
++# AC_DEFINE(HAVE_HYPOTF)
++ AC_DEFINE(HAVE_ISINF)
++ AC_DEFINE(HAVE_ISINFF)
++ AC_DEFINE(HAVE_ISNAN)
++ AC_DEFINE(HAVE_ISNANF)
++# AC_DEFINE(HAVE_LOGF)
++# AC_DEFINE(HAVE_LOG10F)
++# AC_DEFINE(HAVE_MODFF)
++# AC_DEFINE(HAVE_SINF)
++# AC_DEFINE(HAVE_SINHF)
++# AC_DEFINE(HAVE_SINCOS)
++# AC_DEFINE(HAVE_SINCOSF)
++ AC_DEFINE(HAVE_SQRTF)
++# AC_DEFINE(HAVE_TANF)
++# AC_DEFINE(HAVE_TANHF)
++ if test x"long_double_math_on_this_cpu" = x"yes"; then
++ AC_MSG_ERROR([long_double_math_on_this_cpu is yes!])
++# AC_DEFINE(HAVE_ACOSL)
++# AC_DEFINE(HAVE_ASINL)
++# AC_DEFINE(HAVE_ATANL)
++# AC_DEFINE(HAVE_ATAN2L)
++# AC_DEFINE(HAVE_CEILL)
++# AC_DEFINE(HAVE_COPYSIGNL)
++# AC_DEFINE(HAVE_COSL)
++# AC_DEFINE(HAVE_COSHL)
++# AC_DEFINE(HAVE_EXPL)
++# AC_DEFINE(HAVE_FABSL)
++# AC_DEFINE(HAVE_FINITEL)
++# AC_DEFINE(HAVE_FLOORL)
++# AC_DEFINE(HAVE_FMODL)
++# AC_DEFINE(HAVE_FREXPL)
++# AC_DEFINE(HAVE_HYPOTL)
++# AC_DEFINE(HAVE_ISINFL)
++# AC_DEFINE(HAVE_ISNANL)
++# AC_DEFINE(HAVE_LOGL)
++# AC_DEFINE(HAVE_LOG10L)
++# AC_DEFINE(HAVE_MODFL)
++# AC_DEFINE(HAVE_POWL)
++# AC_DEFINE(HAVE_SINL)
++# AC_DEFINE(HAVE_SINHL)
++# AC_DEFINE(HAVE_SINCOSL)
++# AC_DEFINE(HAVE_SQRTL)
++# AC_DEFINE(HAVE_TANL)
++# AC_DEFINE(HAVE_TANHL)
++ fi
++ ;;
+ *-linux* | *-uclinux* | *-gnu* | *-kfreebsd*-gnu | *-knetbsd*-gnu)
+ AC_CHECK_HEADERS([nan.h ieeefp.h endian.h sys/isa_defs.h \
+ machine/endian.h machine/param.h sys/machine.h sys/types.h \
+@@ -152,7 +245,7 @@
+ AC_DEFINE(HAVE_INT64_T)
+ case "$target" in
+ *-uclinux*)
+- # Don't enable LFS with uClibc
++ # Don't enable LFS with uClinux
+ ;;
+ *)
+ AC_DEFINE(_GLIBCXX_USE_LFS)
+diff -urN gcc-3.4.2-dist/libstdc++-v3/include/c_compatibility/wchar.h gcc-3.4.2/libstdc++-v3/include/c_compatibility/wchar.h
+--- gcc-3.4.2-dist/libstdc++-v3/include/c_compatibility/wchar.h 2003-12-08 21:51:45.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/include/c_compatibility/wchar.h 2004-09-10 10:47:40.000000000 -0500
+@@ -101,7 +101,9 @@
+ using std::wmemcpy;
+ using std::wmemmove;
+ using std::wmemset;
++#if _GLIBCXX_HAVE_WCSFTIME
+ using std::wcsftime;
++#endif
+
+ #if _GLIBCXX_USE_C99
+ using std::wcstold;
+diff -urN gcc-3.4.2-dist/libstdc++-v3/include/c_std/std_cwchar.h gcc-3.4.2/libstdc++-v3/include/c_std/std_cwchar.h
+--- gcc-3.4.2-dist/libstdc++-v3/include/c_std/std_cwchar.h 2004-07-20 03:52:12.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/include/c_std/std_cwchar.h 2004-09-10 10:47:40.000000000 -0500
+@@ -179,7 +179,9 @@
+ using ::wcscoll;
+ using ::wcscpy;
+ using ::wcscspn;
++#if _GLIBCXX_HAVE_WCSFTIME
+ using ::wcsftime;
++#endif
+ using ::wcslen;
+ using ::wcsncat;
+ using ::wcsncmp;
diff --git a/toolchain/gcc/patches/3.4.6-nonmips/300-libstdc++-pic.patch b/toolchain/gcc/patches/3.4.6-nonmips/300-libstdc++-pic.patch
new file mode 100644
index 0000000000..c030ba6205
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.6-nonmips/300-libstdc++-pic.patch
@@ -0,0 +1,47 @@
+# DP: Build and install libstdc++_pic.a library.
+
+--- gcc/libstdc++-v3/src/Makefile.am~ 2003-02-28 09:21:05.000000000 +0100
++++ gcc/libstdc++-v3/src/Makefile.am 2003-02-28 09:28:50.000000000 +0100
+@@ -224,6 +224,10 @@
+ @OPT_LDFLAGS@ @SECTION_LDFLAGS@ $(AM_CXXFLAGS) $(LDFLAGS) -o $@
+
+
++install-exec-local:
++ $(AR) cru libstdc++_pic.a .libs/*.o $(top_builddir)/libsupc++/*.o
++ $(INSTALL_DATA) libstdc++_pic.a $(DESTDIR)$(toolexeclibdir)
++
+ # Added bits to build debug library.
+ if GLIBCPP_BUILD_DEBUG
+ all-local: build_debug
+
+--- gcc/libstdc++-v3/src/Makefile.in~ 2004-02-21 09:55:48.000000000 +0100
++++ gcc/libstdc++-v3/src/Makefile.in 2004-02-21 09:59:34.000000000 +0100
+@@ -585,7 +585,7 @@
+
+ install-data-am: install-data-local
+
+-install-exec-am: install-toolexeclibLTLIBRARIES
++install-exec-am: install-toolexeclibLTLIBRARIES install-exec-local
+
+ install-info: install-info-am
+
+@@ -618,6 +618,7 @@
+ distclean-tags distdir dvi dvi-am info info-am install \
+ install-am install-data install-data-am install-data-local \
+ install-exec install-exec-am install-info install-info-am \
++ install-exec-local \
+ install-man install-strip install-toolexeclibLTLIBRARIES \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+@@ -707,6 +708,11 @@
+ install_debug:
+ (cd ${debugdir} && $(MAKE) \
+ toolexeclibdir=$(glibcxx_toolexeclibdir)/debug install)
++
++install-exec-local:
++ $(AR) cru libstdc++_pic.a .libs/*.o $(top_builddir)/libsupc++/*.o
++ $(INSTALL_DATA) libstdc++_pic.a $(DESTDIR)$(toolexeclibdir)
++
+ # 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/toolchain/gcc/patches/3.4.6-nonmips/601-gcc34-arm-ldm.patch b/toolchain/gcc/patches/3.4.6-nonmips/601-gcc34-arm-ldm.patch
new file mode 100644
index 0000000000..142052fdf0
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.6-nonmips/601-gcc34-arm-ldm.patch
@@ -0,0 +1,119 @@
+--- gcc-3.4.0/gcc/config/arm/arm.c.arm-ldm 2004-02-27 09:51:05.000000000 -0500
++++ gcc-3.4.0/gcc/config/arm/arm.c 2004-04-24 18:16:25.000000000 -0400
+@@ -8520,6 +8520,26 @@
+ return_used_this_function = 0;
+ }
+
++/* Return the number (counting from 0) of
++ the least significant set bit in MASK. */
++
++#ifdef __GNUC__
++inline
++#endif
++static int
++number_of_first_bit_set (mask)
++ int mask;
++{
++ int bit;
++
++ for (bit = 0;
++ (mask & (1 << bit)) == 0;
++ ++bit)
++ continue;
++
++ return bit;
++}
++
+ const char *
+ arm_output_epilogue (rtx sibling)
+ {
+@@ -8753,27 +8773,47 @@
+ saved_regs_mask |= (1 << PC_REGNUM);
+ }
+
+- /* Load the registers off the stack. If we only have one register
+- to load use the LDR instruction - it is faster. */
+- if (saved_regs_mask == (1 << LR_REGNUM))
+- {
+- /* The exception handler ignores the LR, so we do
+- not really need to load it off the stack. */
+- if (eh_ofs)
+- asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
+- else
+- asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM);
+- }
+- else if (saved_regs_mask)
++ if (saved_regs_mask)
+ {
+- if (saved_regs_mask & (1 << SP_REGNUM))
+- /* Note - write back to the stack register is not enabled
+- (ie "ldmfd sp!..."). We know that the stack pointer is
+- in the list of registers and if we add writeback the
+- instruction becomes UNPREDICTABLE. */
+- print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
++ /* Load the registers off the stack. If we only have one register
++ to load use the LDR instruction - it is faster. */
++ if (bit_count (saved_regs_mask) == 1)
++ {
++ int reg = number_of_first_bit_set (saved_regs_mask);
++
++ switch (reg)
++ {
++ case SP_REGNUM:
++ /* Mustn't use base writeback when loading SP. */
++ asm_fprintf (f, "\tldr\t%r, [%r]\n", SP_REGNUM, SP_REGNUM);
++ break;
++
++ case LR_REGNUM:
++ if (eh_ofs)
++ {
++ /* The exception handler ignores the LR, so we do
++ not really need to load it off the stack. */
++ asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
++ break;
++ }
++ /* else fall through */
++
++ default:
++ asm_fprintf (f, "\tldr\t%r, [%r], #4\n", reg, SP_REGNUM);
++ break;
++ }
++ }
+ else
+- print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
++ {
++ if (saved_regs_mask & (1 << SP_REGNUM))
++ /* Note - write back to the stack register is not enabled
++ (ie "ldmfd sp!..."). We know that the stack pointer is
++ in the list of registers and if we add writeback the
++ instruction becomes UNPREDICTABLE. */
++ print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
++ else
++ print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
++ }
+ }
+
+ if (current_function_pretend_args_size)
+@@ -11401,22 +11441,6 @@
+ }
+ }
+
+-/* Return the number (counting from 0) of
+- the least significant set bit in MASK. */
+-
+-inline static int
+-number_of_first_bit_set (int mask)
+-{
+- int bit;
+-
+- for (bit = 0;
+- (mask & (1 << bit)) == 0;
+- ++bit)
+- continue;
+-
+- return bit;
+-}
+-
+ /* Generate code to return from a thumb function.
+ If 'reg_containing_return_addr' is -1, then the return address is
+ actually on the stack, at the stack pointer. */
diff --git a/toolchain/gcc/patches/3.4.6-nonmips/602-sdk-libstdc++-includes.patch b/toolchain/gcc/patches/3.4.6-nonmips/602-sdk-libstdc++-includes.patch
new file mode 100644
index 0000000000..4377c2143b
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.6-nonmips/602-sdk-libstdc++-includes.patch
@@ -0,0 +1,22 @@
+--- gcc-3.4.1/libstdc++-v3/libmath/Makefile.am~ 2003-08-27 22:29:42.000000000 +0100
++++ gcc-3.4.1/libstdc++-v3/libmath/Makefile.am 2004-07-22 16:41:45.152130128 +0100
+@@ -32,7 +32,7 @@
+
+ libmath_la_SOURCES = stubs.c
+
+-AM_CPPFLAGS = $(CANADIAN_INCLUDES)
++AM_CPPFLAGS = $(CANADIAN_INCLUDES) -I$(toplevel_srcdir)/include
+
+ # Only compiling "C" sources in this directory.
+ LIBTOOL = @LIBTOOL@ --tag CC
+--- gcc-3.4.1/libstdc++-v3/fragment.am.old 2004-07-22 18:24:58.024083656 +0100
++++ gcc-3.4.1/libstdc++-v3/fragment.am 2004-07-22 18:24:59.019932264 +0100
+@@ -18,7 +18,7 @@
+ $(WARN_FLAGS) $(WERROR) -fdiagnostics-show-location=once
+
+ # -I/-D flags to pass when compiling.
+-AM_CPPFLAGS = $(GLIBCXX_INCLUDES)
++AM_CPPFLAGS = $(GLIBCXX_INCLUDES) -I$(toplevel_srcdir)/include
+
+
+
diff --git a/toolchain/gcc/patches/3.4.6-nonmips/700-pr15068-fix.patch b/toolchain/gcc/patches/3.4.6-nonmips/700-pr15068-fix.patch
new file mode 100644
index 0000000000..2977765c5f
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.6-nonmips/700-pr15068-fix.patch
@@ -0,0 +1,44 @@
+See http://gcc.gnu.org/PR15068
+
+Fixes error
+
+../sysdeps/generic/s_fmax.c: In function `__fmax':
+../sysdeps/generic/s_fmax.c:28: internal compiler error: in elim_reg_cond, at flow.c:3257
+Please submit a full bug report,
+with preprocessed source if appropriate.
+See <URL:http://gcc.gnu.org/bugs.html> for instructions.
+make[2]: *** [/home/dank/wk/crosstool-0.28-rc35/build/arm-unknown-linux-gnu/gcc-3.4.1-glibc-20040822/build-glibc/math/s_fmax.o] Error 1
+make[2]: Leaving directory `/home/dank/wk/crosstool-0.28-rc35/build/arm-unknown-linux-gnu/gcc-3.4.1-glibc-20040822/glibc-20040822/math'
+make[1]: *** [math/others] Error 2
+make[1]: Leaving directory `/home/dank/wk/crosstool-0.28-rc35/build/arm-unknown-linux-gnu/gcc-3.4.1-glibc-20040822/glibc-20040822'
+make: *** [all] Error 2
+
+[ rediffed against gcc-3.4.1, with elbow grease, ending up with same thing as
+http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/flow.c.diff?cvsroot=gcc&only_with_tag=csl-arm-branch&r1=1.563.4.2&r2=1.563.4.3 ]
+
+--- gcc-3.4.1/gcc/flow.c.old 2004-02-27 19:39:19.000000000 -0800
++++ gcc-3.4.1/gcc/flow.c 2004-08-26 07:29:46.000000000 -0700
+@@ -1878,6 +1878,7 @@
+ rtx set_src = SET_SRC (pc_set (BB_END (bb)));
+ rtx cond_true = XEXP (set_src, 0);
+ rtx reg = XEXP (cond_true, 0);
++ enum rtx_code inv_cond;
+
+ if (GET_CODE (reg) == SUBREG)
+ reg = SUBREG_REG (reg);
+@@ -1886,11 +1887,13 @@
+ in the form of a comparison of a register against zero.
+ If the condition is more complex than that, then it is safe
+ not to record any information. */
+- if (GET_CODE (reg) == REG
++ inv_cond = reversed_comparison_code (cond_true, BB_END (bb));
++ if (inv_cond != UNKNOWN
++ && GET_CODE (reg) == REG
+ && XEXP (cond_true, 1) == const0_rtx)
+ {
+ rtx cond_false
+- = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond_true)),
++ = gen_rtx_fmt_ee (inv_cond,
+ GET_MODE (cond_true), XEXP (cond_true, 0),
+ XEXP (cond_true, 1));
+ if (GET_CODE (XEXP (set_src, 1)) == PC)
diff --git a/toolchain/gcc/patches/3.4.6-nonmips/800-arm-bigendian.patch b/toolchain/gcc/patches/3.4.6-nonmips/800-arm-bigendian.patch
new file mode 100644
index 0000000000..0bae8f474c
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.6-nonmips/800-arm-bigendian.patch
@@ -0,0 +1,70 @@
+By Lennert Buytenhek <buytenh@wantstofly.org>
+Adds support for arm*b-linux* big-endian ARM targets
+
+See http://gcc.gnu.org/PR16350
+
+diff -urN gcc-3.4.1-dist/gcc/config/arm/linux-elf.h gcc-3.4.1/gcc/config/arm/linux-elf.h
+--- gcc-3.4.1-dist/gcc/config/arm/linux-elf.h 2004-08-16 16:01:50.000000000 -0500
++++ gcc-3.4.1/gcc/config/arm/linux-elf.h 2004-08-16 15:43:40.000000000 -0500
+@@ -30,17 +30,34 @@
+ /* Do not assume anything about header files. */
+ #define NO_IMPLICIT_EXTERN_C
+
++/*
++ * 'config.gcc' defines TARGET_BIG_ENDIAN_DEFAULT as 1 for arm*b-*
++ * (big endian) configurations.
++ */
++#if TARGET_BIG_ENDIAN_DEFAULT
++#define TARGET_ENDIAN_DEFAULT ARM_FLAG_BIG_END
++#define TARGET_ENDIAN_OPTION "mbig-endian"
++#define TARGET_LINKER_EMULATION "armelfb_linux"
++#else
++#define TARGET_ENDIAN_DEFAULT 0
++#define TARGET_ENDIAN_OPTION "mlittle-endian"
++#define TARGET_LINKER_EMULATION "armelf_linux"
++#endif
++
+ /* Default is to use APCS-32 mode. */
+ #undef TARGET_DEFAULT
+-#define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_MMU_TRAPS)
++#define TARGET_DEFAULT \
++ ( ARM_FLAG_APCS_32 | \
++ ARM_FLAG_MMU_TRAPS | \
++ TARGET_ENDIAN_DEFAULT )
+
+ #define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6
+
+-#define SUBTARGET_EXTRA_LINK_SPEC " -m armelf_linux -p"
++#define SUBTARGET_EXTRA_LINK_SPEC " -m " TARGET_LINKER_EMULATION " -p"
+
+ #undef MULTILIB_DEFAULTS
+ #define MULTILIB_DEFAULTS \
+- { "marm", "mlittle-endian", "mhard-float", "mapcs-32", "mno-thumb-interwork" }
++ { "marm", TARGET_ENDIAN_OPTION, "mhard-float", "mapcs-32", "mno-thumb-interwork" }
+
+ #define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
+
+@@ -101,7 +118,7 @@
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2} \
+ -X \
+- %{mbig-endian:-EB}" \
++ %{mbig-endian:-EB} %{mlittle-endian:-EL}" \
+ SUBTARGET_EXTRA_LINK_SPEC
+ #endif
+
+diff -urN gcc-3.4.1-dist/gcc/config.gcc gcc-3.4.1/gcc/config.gcc
+--- gcc-3.4.1-dist/gcc/config.gcc 2004-08-16 16:01:50.000000000 -0500
++++ gcc-3.4.1/gcc/config.gcc 2004-08-16 16:01:25.000000000 -0500
+@@ -672,6 +672,11 @@
+ ;;
+ arm*-*-linux*) # ARM GNU/Linux with ELF
+ tm_file="dbxelf.h elfos.h linux.h arm/elf.h arm/linux-gas.h arm/linux-elf.h arm/aout.h arm/arm.h"
++ case $target in
++ arm*b-*)
++ tm_defines="TARGET_BIG_ENDIAN_DEFAULT=1 $tm_defines"
++ ;;
++ esac
+ tmake_file="t-slibgcc-elf-ver t-linux arm/t-linux"
+ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
+ gnu_ld=yes
diff --git a/toolchain/gcc/patches/3.4.6-nonmips/810-arm-bigendian-uclibc.patch b/toolchain/gcc/patches/3.4.6-nonmips/810-arm-bigendian-uclibc.patch
new file mode 100644
index 0000000000..a4d87e2317
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.6-nonmips/810-arm-bigendian-uclibc.patch
@@ -0,0 +1,27 @@
+diff -urN gcc-3.4.1-dist/gcc/config/arm/linux-elf.h gcc-3.4.1/gcc/config/arm/linux-elf.h
+--- gcc-3.4.1-dist/gcc/config/arm/linux-elf.h 2004-08-16 16:08:18.000000000 -0500
++++ gcc-3.4.1/gcc/config/arm/linux-elf.h 2004-08-16 16:06:24.000000000 -0500
+@@ -107,7 +107,7 @@
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0} \
+ -X \
+- %{mbig-endian:-EB}" \
++ %{mbig-endian:-EB} %{mlittle-endian:-EL}" \
+ SUBTARGET_EXTRA_LINK_SPEC
+ #else
+ #define LINK_SPEC "%{h*} %{version:-v} \
+diff -urN gcc-3.4.1-dist/gcc/config.gcc gcc-3.4.1/gcc/config.gcc
+--- gcc-3.4.1-dist/gcc/config.gcc 2004-08-16 16:08:18.000000000 -0500
++++ gcc-3.4.1/gcc/config.gcc 2004-08-16 16:03:25.000000000 -0500
+@@ -666,6 +666,11 @@
+ ;;
+ arm*-*-linux-uclibc*) # ARM GNU/Linux with ELF - uClibc
+ tm_file="dbxelf.h elfos.h linux.h arm/elf.h arm/linux-gas.h arm/linux-elf.h arm/aout.h arm/arm.h"
++ case $target in
++ arm*b-*)
++ tm_defines="TARGET_BIG_ENDIAN_DEFAULT=1 $tm_defines"
++ ;;
++ esac
+ tmake_file="t-slibgcc-elf-ver t-linux-uclibc arm/t-linux"
+ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
+ gnu_ld=yes
diff --git a/toolchain/gcc/patches/3.4.6-nonmips/arm-softfloat.patch.conditional b/toolchain/gcc/patches/3.4.6-nonmips/arm-softfloat.patch.conditional
new file mode 100644
index 0000000000..19d1b90dac
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.6-nonmips/arm-softfloat.patch.conditional
@@ -0,0 +1,270 @@
+Note... modified my mjn3 to not conflict with the big endian arm patch.
+Warning!!! Only the linux target is aware of TARGET_ENDIAN_DEFAULT.
+Also changed
+ #define SUBTARGET_EXTRA_ASM_SPEC "\
+ %{!mcpu=*:-mcpu=xscale} \
+ %{mhard-float:-mfpu=fpa} \
+ %{!mhard-float: %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}}"
+to
+ #define SUBTARGET_EXTRA_ASM_SPEC "\
+ %{mhard-float:-mfpu=fpa} \
+ %{!mhard-float: %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}}"
+in gcc/config/arm/linux-elf.h.
+#
+# Submitted:
+#
+# Dimitry Andric <dimitry@andric.com>, 2004-05-01
+#
+# Description:
+#
+# Nicholas Pitre released this patch for gcc soft-float support here:
+# http://lists.arm.linux.org.uk/pipermail/linux-arm/2003-October/006436.html
+#
+# This version has been adapted to work with gcc 3.4.0.
+#
+# The original patch doesn't distinguish between softfpa and softvfp modes
+# in the way Nicholas Pitre probably meant. His description is:
+#
+# "Default is to use APCS-32 mode with soft-vfp. The old Linux default for
+# floats can be achieved with -mhard-float or with the configure
+# --with-float=hard option. If -msoft-float or --with-float=soft is used then
+# software float support will be used just like the default but with the legacy
+# big endian word ordering for double float representation instead."
+#
+# Which means the following:
+#
+# * If you compile without -mhard-float or -msoft-float, you should get
+# software floating point, using the VFP format. The produced object file
+# should have these flags in its header:
+#
+# private flags = 600: [APCS-32] [VFP float format] [software FP]
+#
+# * If you compile with -mhard-float, you should get hardware floating point,
+# which always uses the FPA format. Object file header flags should be:
+#
+# private flags = 0: [APCS-32] [FPA float format]
+#
+# * If you compile with -msoft-float, you should get software floating point,
+# using the FPA format. This is done for compatibility reasons with many
+# existing distributions. Object file header flags should be:
+#
+# private flags = 200: [APCS-32] [FPA float format] [software FP]
+#
+# The original patch from Nicholas Pitre contained the following constructs:
+#
+# #define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mcpu=xscale} \
+# %{mhard-float:-mfpu=fpa} \
+# %{!mhard-float: %{msoft-float:-mfpu=softfpa;:-mfpu=softvfp}}"
+#
+# However, gcc doesn't accept this ";:" notation, used in the 3rd line. This
+# is probably the reason Robert Schwebel modified it to:
+#
+# #define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mcpu=xscale} \
+# %{mhard-float:-mfpu=fpa} \
+# %{!mhard-float: %{msoft-float:-mfpu=softfpa -mfpu=softvfp}}"
+#
+# But this causes the following behaviour:
+#
+# * If you compile without -mhard-float or -msoft-float, the compiler generates
+# software floating point instructions, but *nothing* is passed to the
+# assembler, which results in an object file which has flags:
+#
+# private flags = 0: [APCS-32] [FPA float format]
+#
+# This is not correct!
+#
+# * If you compile with -mhard-float, the compiler generates hardware floating
+# point instructions, and passes "-mfpu=fpa" to the assembler, which results
+# in an object file which has the same flags as in the previous item, but now
+# those *are* correct.
+#
+# * If you compile with -msoft-float, the compiler generates software floating
+# point instructions, and passes "-mfpu=softfpa -mfpu=softvfp" (in that
+# order) to the assembler, which results in an object file with flags:
+#
+# private flags = 600: [APCS-32] [VFP float format] [software FP]
+#
+# This is not correct, because the last "-mfpu=" option on the assembler
+# command line determines the actual FPU convention used (which should be FPA
+# in this case).
+#
+# Therefore, I modified this patch to get the desired behaviour. Every
+# instance of the notation:
+#
+# %{msoft-float:-mfpu=softfpa -mfpu=softvfp}
+#
+# was changed to:
+#
+# %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}
+#
+# I also did the following:
+#
+# * Modified all TARGET_DEFAULT macros I could find to include ARM_FLAG_VFP, to
+# be consistent with Nicholas' original patch.
+# * Removed any "msoft-float" or "mhard-float" from all MULTILIB_DEFAULTS
+# macros I could find. I think that if you compile without any options, you
+# would like to get the defaults. :)
+# * Removed the extra -lfloat option from LIBGCC_SPEC, since it isn't needed
+# anymore. (The required functions are now in libgcc.)
+
+diff -urN gcc-3.4.1-old/gcc/config/arm/coff.h gcc-3.4.1/gcc/config/arm/coff.h
+--- gcc-3.4.1-old/gcc/config/arm/coff.h 2004-02-24 08:25:22.000000000 -0600
++++ gcc-3.4.1/gcc/config/arm/coff.h 2004-09-02 21:51:15.000000000 -0500
+@@ -31,11 +31,16 @@
+ #define TARGET_VERSION fputs (" (ARM/coff)", stderr)
+
+ #undef TARGET_DEFAULT
+-#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_32 | ARM_FLAG_APCS_FRAME | ARM_FLAG_MMU_TRAPS)
++#define TARGET_DEFAULT \
++ ( ARM_FLAG_SOFT_FLOAT \
++ | ARM_FLAG_VFP \
++ | ARM_FLAG_APCS_32 \
++ | ARM_FLAG_APCS_FRAME \
++ | ARM_FLAG_MMU_TRAPS )
+
+ #ifndef MULTILIB_DEFAULTS
+ #define MULTILIB_DEFAULTS \
+- { "marm", "mlittle-endian", "msoft-float", "mapcs-32", "mno-thumb-interwork" }
++ { "marm", "mlittle-endian", "mapcs-32", "mno-thumb-interwork" }
+ #endif
+
+ /* This is COFF, but prefer stabs. */
+diff -urN gcc-3.4.1-old/gcc/config/arm/elf.h gcc-3.4.1/gcc/config/arm/elf.h
+--- gcc-3.4.1-old/gcc/config/arm/elf.h 2004-02-24 08:25:22.000000000 -0600
++++ gcc-3.4.1/gcc/config/arm/elf.h 2004-09-02 21:51:15.000000000 -0500
+@@ -46,7 +46,9 @@
+
+ #ifndef SUBTARGET_ASM_FLOAT_SPEC
+ #define SUBTARGET_ASM_FLOAT_SPEC "\
+-%{mapcs-float:-mfloat} %{msoft-float:-mfpu=softfpa}"
++%{mapcs-float:-mfloat} \
++%{mhard-float:-mfpu=fpa} \
++%{!mhard-float: %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}}"
+ #endif
+
+ #ifndef ASM_SPEC
+@@ -106,12 +108,17 @@
+ #endif
+
+ #ifndef TARGET_DEFAULT
+-#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_32 | ARM_FLAG_APCS_FRAME | ARM_FLAG_MMU_TRAPS)
++#define TARGET_DEFAULT \
++ ( ARM_FLAG_SOFT_FLOAT \
++ | ARM_FLAG_VFP \
++ | ARM_FLAG_APCS_32 \
++ | ARM_FLAG_APCS_FRAME \
++ | ARM_FLAG_MMU_TRAPS )
+ #endif
+
+ #ifndef MULTILIB_DEFAULTS
+ #define MULTILIB_DEFAULTS \
+- { "marm", "mlittle-endian", "msoft-float", "mapcs-32", "mno-thumb-interwork", "fno-leading-underscore" }
++ { "marm", "mlittle-endian", "mapcs-32", "mno-thumb-interwork", "fno-leading-underscore" }
+ #endif
+
+ #define TARGET_ASM_FILE_START_APP_OFF true
+diff -urN gcc-3.4.1-old/gcc/config/arm/linux-elf.h gcc-3.4.1/gcc/config/arm/linux-elf.h
+--- gcc-3.4.1-old/gcc/config/arm/linux-elf.h 2004-09-02 21:50:52.000000000 -0500
++++ gcc-3.4.1/gcc/config/arm/linux-elf.h 2004-09-02 22:00:49.000000000 -0500
+@@ -44,12 +44,26 @@
+ #define TARGET_LINKER_EMULATION "armelf_linux"
+ #endif
+
+-/* Default is to use APCS-32 mode. */
++/*
++ * Default is to use APCS-32 mode with soft-vfp.
++ * The old Linux default for floats can be achieved with -mhard-float
++ * or with the configure --with-float=hard option.
++ * If -msoft-float or --with-float=soft is used then software float
++ * support will be used just like the default but with the legacy
++ * big endian word ordering for double float representation instead.
++ */
+ #undef TARGET_DEFAULT
+-#define TARGET_DEFAULT \
+- ( ARM_FLAG_APCS_32 | \
+- ARM_FLAG_MMU_TRAPS | \
+- TARGET_ENDIAN_DEFAULT )
++#define TARGET_DEFAULT \
++ ( ARM_FLAG_APCS_32 \
++ | ARM_FLAG_SOFT_FLOAT \
++ | TARGET_ENDIAN_DEFAULT \
++ | ARM_FLAG_VFP \
++ | ARM_FLAG_MMU_TRAPS )
++
++#undef SUBTARGET_EXTRA_ASM_SPEC
++#define SUBTARGET_EXTRA_ASM_SPEC "\
++%{mhard-float:-mfpu=fpa} \
++%{!mhard-float: %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}}"
+
+ #define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6
+
+@@ -57,7 +71,7 @@
+
+ #undef MULTILIB_DEFAULTS
+ #define MULTILIB_DEFAULTS \
+- { "marm", TARGET_ENDIAN_OPTION, "mhard-float", "mapcs-32", "mno-thumb-interwork" }
++ { "marm", TARGET_ENDIAN_OPTION, "mapcs-32", "mno-thumb-interwork" }
+
+ #define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
+
+@@ -72,7 +86,7 @@
+ %{shared:-lc} \
+ %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
+
+-#define LIBGCC_SPEC "%{msoft-float:-lfloat} -lgcc"
++#define LIBGCC_SPEC "-lgcc"
+
+ /* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add
+ the GNU/Linux magical crtbegin.o file (see crtstuff.c) which
+diff -urN gcc-3.4.1-old/gcc/config/arm/t-linux gcc-3.4.1/gcc/config/arm/t-linux
+--- gcc-3.4.1-old/gcc/config/arm/t-linux 2003-09-20 16:09:07.000000000 -0500
++++ gcc-3.4.1/gcc/config/arm/t-linux 2004-09-02 21:51:15.000000000 -0500
+@@ -4,7 +4,10 @@
+ LIBGCC2_DEBUG_CFLAGS = -g0
+
+ LIB1ASMSRC = arm/lib1funcs.asm
+-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx
++LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx \
++ _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \
++ _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
++ _fixsfsi _fixunssfsi
+
+ # MULTILIB_OPTIONS = mhard-float/msoft-float
+ # MULTILIB_DIRNAMES = hard-float soft-float
+diff -urN gcc-3.4.1-old/gcc/config/arm/unknown-elf.h gcc-3.4.1/gcc/config/arm/unknown-elf.h
+--- gcc-3.4.1-old/gcc/config/arm/unknown-elf.h 2004-02-24 08:25:22.000000000 -0600
++++ gcc-3.4.1/gcc/config/arm/unknown-elf.h 2004-09-02 21:51:15.000000000 -0500
+@@ -30,7 +30,12 @@
+
+ /* Default to using APCS-32 and software floating point. */
+ #ifndef TARGET_DEFAULT
+-#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_32 | ARM_FLAG_APCS_FRAME | ARM_FLAG_MMU_TRAPS)
++#define TARGET_DEFAULT \
++ ( ARM_FLAG_SOFT_FLOAT \
++ | ARM_FLAG_VFP \
++ | ARM_FLAG_APCS_32 \
++ | ARM_FLAG_APCS_FRAME \
++ | ARM_FLAG_MMU_TRAPS )
+ #endif
+
+ /* Now we define the strings used to build the spec file. */
+diff -urN gcc-3.4.1-old/gcc/config/arm/xscale-elf.h gcc-3.4.1/gcc/config/arm/xscale-elf.h
+--- gcc-3.4.1-old/gcc/config/arm/xscale-elf.h 2003-07-01 18:26:43.000000000 -0500
++++ gcc-3.4.1/gcc/config/arm/xscale-elf.h 2004-09-02 21:51:15.000000000 -0500
+@@ -49,11 +49,12 @@
+ endian, regardless of the endian-ness of the memory
+ system. */
+
+-#define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mcpu=xscale} \
+- %{mhard-float:-mfpu=fpa} \
+- %{!mhard-float: %{msoft-float:-mfpu=softfpa;:-mfpu=softvfp}}"
++#define SUBTARGET_EXTRA_ASM_SPEC "\
++%{!mcpu=*:-mcpu=xscale} \
++%{mhard-float:-mfpu=fpa} \
++%{!mhard-float: %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}}"
+
+ #ifndef MULTILIB_DEFAULTS
+ #define MULTILIB_DEFAULTS \
+- { "mlittle-endian", "mno-thumb-interwork", "marm", "msoft-float" }
++ { "mlittle-endian", "mno-thumb-interwork", "marm" }
+ #endif
diff --git a/toolchain/gcc/patches/3.4.6/100-uclibc-conf.patch b/toolchain/gcc/patches/3.4.6/100-uclibc-conf.patch
new file mode 100644
index 0000000000..29e4c802e2
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.6/100-uclibc-conf.patch
@@ -0,0 +1,442 @@
+diff -urN gcc-3.4.1-dist/boehm-gc/configure gcc-3.4.1/boehm-gc/configure
+--- gcc-3.4.1-dist/boehm-gc/configure 2004-07-01 14:14:03.000000000 -0500
++++ gcc-3.4.1/boehm-gc/configure 2004-08-12 16:22:57.000000000 -0500
+@@ -1947,6 +1947,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+diff -urN gcc-3.4.1-dist/boehm-gc/ltconfig gcc-3.4.1/boehm-gc/ltconfig
+--- gcc-3.4.1-dist/boehm-gc/ltconfig 2002-11-20 09:59:06.000000000 -0600
++++ gcc-3.4.1/boehm-gc/ltconfig 2004-08-12 15:54:42.000000000 -0500
+@@ -1981,6 +1981,23 @@
+ fi
+ ;;
+
++linux-uclibc*)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
++ soname_spec='${libname}${release}.so$major'
++ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
++ file_magic_cmd=/usr/bin/file
++ file_magic_test_file=`echo /lib/libuClibc-*.so`
++
++ # Assume using the uClibc dynamic linker.
++ dynamic_linker="uClibc ld.so"
++ ;;
++
+ netbsd*)
+ version_type=sunos
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+diff -urN gcc-3.4.1-dist/gcc/config/arm/linux-elf.h gcc-3.4.1/gcc/config/arm/linux-elf.h
+--- gcc-3.4.1-dist/gcc/config/arm/linux-elf.h 2004-01-31 00:18:11.000000000 -0600
++++ gcc-3.4.1/gcc/config/arm/linux-elf.h 2004-08-12 15:54:42.000000000 -0500
+@@ -81,6 +81,18 @@
+ "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
+
+ #undef LINK_SPEC
++#ifdef USE_UCLIBC
++#define LINK_SPEC "%{h*} %{version:-v} \
++ %{b} %{Wl,*:%*} \
++ %{static:-Bstatic} \
++ %{shared:-shared} \
++ %{symbolic:-Bsymbolic} \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0} \
++ -X \
++ %{mbig-endian:-EB}" \
++ SUBTARGET_EXTRA_LINK_SPEC
++#else
+ #define LINK_SPEC "%{h*} %{version:-v} \
+ %{b} %{Wl,*:%*} \
+ %{static:-Bstatic} \
+@@ -91,6 +103,7 @@
+ -X \
+ %{mbig-endian:-EB}" \
+ SUBTARGET_EXTRA_LINK_SPEC
++#endif
+
+ #define TARGET_OS_CPP_BUILTINS() LINUX_TARGET_OS_CPP_BUILTINS()
+
+diff -urN gcc-3.4.1-dist/gcc/config/cris/linux.h gcc-3.4.1/gcc/config/cris/linux.h
+--- gcc-3.4.1-dist/gcc/config/cris/linux.h 2003-11-28 21:08:09.000000000 -0600
++++ gcc-3.4.1/gcc/config/cris/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -79,6 +79,25 @@
+ #undef CRIS_DEFAULT_CPU_VERSION
+ #define CRIS_DEFAULT_CPU_VERSION CRIS_CPU_NG
+
++#ifdef USE_UCLIBC
++
++#undef CRIS_SUBTARGET_VERSION
++#define CRIS_SUBTARGET_VERSION " - cris-axis-linux-uclibc"
++
++#undef CRIS_LINK_SUBTARGET_SPEC
++#define CRIS_LINK_SUBTARGET_SPEC \
++ "-mcrislinux\
++ -rpath-link include/asm/../..%s\
++ %{shared} %{static}\
++ %{symbolic:-Bdynamic} %{shlib:-Bdynamic} %{static:-Bstatic}\
++ %{!shared: \
++ %{!static: \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}}} \
++ %{!r:%{O2|O3: --gc-sections}}"
++
++#else /* USE_UCLIBC */
++
+ #undef CRIS_SUBTARGET_VERSION
+ #define CRIS_SUBTARGET_VERSION " - cris-axis-linux-gnu"
+
+@@ -93,6 +112,8 @@
+ %{!shared:%{!static:%{rdynamic:-export-dynamic}}}\
+ %{!r:%{O2|O3: --gc-sections}}"
+
++#endif /* USE_UCLIBC */
++
+
+ /* Node: Run-time Target */
+
+diff -urN gcc-3.4.1-dist/gcc/config/cris/t-linux-uclibc gcc-3.4.1/gcc/config/cris/t-linux-uclibc
+--- gcc-3.4.1-dist/gcc/config/cris/t-linux-uclibc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.1/gcc/config/cris/t-linux-uclibc 2004-08-12 15:54:43.000000000 -0500
+@@ -0,0 +1,3 @@
++T_CFLAGS = -DUSE_UCLIBC
++TARGET_LIBGCC2_CFLAGS += -fPIC
++CRTSTUFF_T_CFLAGS_S = $(TARGET_LIBGCC2_CFLAGS)
+diff -urN gcc-3.4.1-dist/gcc/config/i386/linux.h gcc-3.4.1/gcc/config/i386/linux.h
+--- gcc-3.4.1-dist/gcc/config/i386/linux.h 2003-11-28 21:08:10.000000000 -0600
++++ gcc-3.4.1/gcc/config/i386/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -118,6 +118,15 @@
+ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \
+ %{static:-static}}}"
+ #else
++#if defined USE_UCLIBC
++#define LINK_SPEC "-m elf_i386 %{shared:-shared} \
++ %{!shared: \
++ %{!ibcs: \
++ %{!static: \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}} \
++ %{static:-static}}}"
++#else
+ #define LINK_SPEC "-m elf_i386 %{shared:-shared} \
+ %{!shared: \
+ %{!ibcs: \
+@@ -126,6 +135,7 @@
+ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
+ %{static:-static}}}"
+ #endif
++#endif
+
+ /* A C statement (sans semicolon) to output to the stdio stream
+ FILE the assembler definition of uninitialized global DECL named
+diff -urN gcc-3.4.1-dist/gcc/config/mips/linux.h gcc-3.4.1/gcc/config/mips/linux.h
+--- gcc-3.4.1-dist/gcc/config/mips/linux.h 2004-06-15 20:42:24.000000000 -0500
++++ gcc-3.4.1/gcc/config/mips/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -109,6 +109,17 @@
+
+ /* Borrowed from sparc/linux.h */
+ #undef LINK_SPEC
++#ifdef USE_UCLIBC
++#define LINK_SPEC \
++ "%(endian_spec) \
++ %{shared:-shared} \
++ %{!shared: \
++ %{!ibcs: \
++ %{!static: \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}} \
++ %{static:-static}}}"
++#else
+ #define LINK_SPEC \
+ "%(endian_spec) \
+ %{shared:-shared} \
+@@ -118,6 +129,7 @@
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}} \
+ %{static:-static}}}"
++#endif
+
+ #undef SUBTARGET_ASM_SPEC
+ #define SUBTARGET_ASM_SPEC "\
+diff -urN gcc-3.4.1-dist/gcc/config/rs6000/linux.h gcc-3.4.1/gcc/config/rs6000/linux.h
+--- gcc-3.4.1-dist/gcc/config/rs6000/linux.h 2004-02-25 09:11:19.000000000 -0600
++++ gcc-3.4.1/gcc/config/rs6000/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -61,7 +61,11 @@
+ #define LINK_START_DEFAULT_SPEC "%(link_start_linux)"
+
+ #undef LINK_OS_DEFAULT_SPEC
++#ifdef USE_UCLIBC
++#define LINK_OS_DEFAULT_SPEC "%(link_os_linux_uclibc)"
++#else
+ #define LINK_OS_DEFAULT_SPEC "%(link_os_linux)"
++#endif
+
+ #define LINK_GCC_C_SEQUENCE_SPEC \
+ "%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}"
+diff -urN gcc-3.4.1-dist/gcc/config/rs6000/sysv4.h gcc-3.4.1/gcc/config/rs6000/sysv4.h
+--- gcc-3.4.1-dist/gcc/config/rs6000/sysv4.h 2004-06-10 01:39:50.000000000 -0500
++++ gcc-3.4.1/gcc/config/rs6000/sysv4.h 2004-08-12 15:54:43.000000000 -0500
+@@ -947,6 +947,7 @@
+ mcall-linux : %(link_os_linux) ; \
+ mcall-gnu : %(link_os_gnu) ; \
+ mcall-netbsd : %(link_os_netbsd) ; \
++ mcall-linux-uclibc : %(link_os_linux_uclibc); \
+ mcall-openbsd: %(link_os_openbsd) ; \
+ : %(link_os_default) }"
+
+@@ -1124,6 +1125,10 @@
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}}}"
+
++#define LINK_OS_LINUX_UCLIBC_SPEC "-m elf32ppclinux %{!shared: %{!static: \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}}}"
++
+ #if defined(HAVE_LD_EH_FRAME_HDR)
+ # define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
+ #endif
+@@ -1290,6 +1295,7 @@
+ { "link_os_sim", LINK_OS_SIM_SPEC }, \
+ { "link_os_freebsd", LINK_OS_FREEBSD_SPEC }, \
+ { "link_os_linux", LINK_OS_LINUX_SPEC }, \
++ { "link_os_linux_uclibc", LINK_OS_LINUX_UCLIBC_SPEC }, \
+ { "link_os_gnu", LINK_OS_GNU_SPEC }, \
+ { "link_os_netbsd", LINK_OS_NETBSD_SPEC }, \
+ { "link_os_openbsd", LINK_OS_OPENBSD_SPEC }, \
+diff -urN gcc-3.4.1-dist/gcc/config/sh/linux.h gcc-3.4.1/gcc/config/sh/linux.h
+--- gcc-3.4.1-dist/gcc/config/sh/linux.h 2004-01-11 20:29:13.000000000 -0600
++++ gcc-3.4.1/gcc/config/sh/linux.h 2004-08-12 15:54:43.000000000 -0500
+@@ -73,12 +73,21 @@
+ #undef SUBTARGET_LINK_EMUL_SUFFIX
+ #define SUBTARGET_LINK_EMUL_SUFFIX "_linux"
+ #undef SUBTARGET_LINK_SPEC
++#ifdef USE_UCLIBC
++#define SUBTARGET_LINK_SPEC \
++ "%{shared:-shared} \
++ %{!static: \
++ %{rdynamic:-export-dynamic} \
++ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}} \
++ %{static:-static}"
++#else
+ #define SUBTARGET_LINK_SPEC \
+ "%{shared:-shared} \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
+ %{static:-static}"
++#endif
+
+ #undef LIB_SPEC
+ #define LIB_SPEC \
+diff -urN gcc-3.4.1-dist/gcc/config/sh/t-linux-uclibc gcc-3.4.1/gcc/config/sh/t-linux-uclibc
+--- gcc-3.4.1-dist/gcc/config/sh/t-linux-uclibc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.1/gcc/config/sh/t-linux-uclibc 2004-08-12 15:54:43.000000000 -0500
+@@ -0,0 +1,13 @@
++T_CFLAGS = -DUSE_UCLIBC
++
++TARGET_LIBGCC2_CFLAGS = -fpic -DNO_FPSCR_VALUES
++LIB1ASMFUNCS_CACHE = _ic_invalidate
++
++LIB2FUNCS_EXTRA=
++
++MULTILIB_OPTIONS= $(MULTILIB_ENDIAN) m3e/m4
++MULTILIB_DIRNAMES=
++MULTILIB_MATCHES =
++MULTILIB_EXCEPTIONS=
++
++EXTRA_MULTILIB_PARTS= crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
+diff -urN gcc-3.4.1-dist/gcc/config/sh/t-sh64-uclibc gcc-3.4.1/gcc/config/sh/t-sh64-uclibc
+--- gcc-3.4.1-dist/gcc/config/sh/t-sh64-uclibc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.1/gcc/config/sh/t-sh64-uclibc 2004-08-12 15:54:43.000000000 -0500
+@@ -0,0 +1,13 @@
++EXTRA_MULTILIB_PARTS= crt1.o crti.o crtn.o crtbegin.o crtend.o
++
++LIB1ASMFUNCS = \
++ _sdivsi3 _sdivsi3_i4 _udivsi3 _udivsi3_i4 _set_fpscr \
++ _shcompact_call_trampoline _shcompact_return_trampoline \
++ _shcompact_incoming_args _ic_invalidate _nested_trampoline \
++ _push_pop_shmedia_regs \
++ _udivdi3 _divdi3 _umoddi3 _moddi3
++
++MULTILIB_OPTIONS = $(MULTILIB_ENDIAN) m5-32media-nofpu/m5-compact/m5-compact-nofpu/m5-64media/m5-64media-nofpu
++MULTILIB_DIRNAMES= $(MULTILIB_ENDIAN) nofpu compact nofpu/compact media64 nofpu/media64
++MULTILIB_MATCHES=
++MULTILIB_EXCEPTIONS=
+diff -urN gcc-3.4.1-dist/gcc/config/t-linux-uclibc gcc-3.4.1/gcc/config/t-linux-uclibc
+--- gcc-3.4.1-dist/gcc/config/t-linux-uclibc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.1/gcc/config/t-linux-uclibc 2004-08-12 15:54:43.000000000 -0500
+@@ -0,0 +1,15 @@
++T_CFLAGS = -DUSE_UCLIBC
++
++# Compile crtbeginS.o and crtendS.o with pic.
++CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
++# Compile libgcc2.a with pic.
++TARGET_LIBGCC2_CFLAGS = -fPIC
++
++# Override t-slibgcc-elf-ver to export some libgcc symbols with
++# the symbol versions that glibc used.
++#SHLIB_MAPFILES += $(srcdir)/config/libgcc-glibc.ver
++
++# Use unwind-dw2-fde
++LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
++ $(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c $(srcdir)/unwind-c.c
++LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h
+diff -urN gcc-3.4.1-dist/gcc/config.gcc gcc-3.4.1/gcc/config.gcc
+--- gcc-3.4.1-dist/gcc/config.gcc 2004-04-21 10:12:35.000000000 -0500
++++ gcc-3.4.1/gcc/config.gcc 2004-08-12 15:59:46.000000000 -0500
+@@ -664,6 +664,12 @@
+ extra_parts=""
+ use_collect2=yes
+ ;;
++arm*-*-linux-uclibc*) # ARM GNU/Linux with ELF - uClibc
++ tm_file="dbxelf.h elfos.h linux.h arm/elf.h arm/linux-gas.h arm/linux-elf.h arm/aout.h arm/arm.h"
++ tmake_file="t-slibgcc-elf-ver t-linux-uclibc arm/t-linux"
++ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
++ gnu_ld=yes
++ ;;
+ arm*-*-linux*) # ARM GNU/Linux with ELF
+ tm_file="dbxelf.h elfos.h linux.h arm/elf.h arm/linux-gas.h arm/linux-elf.h arm/aout.h arm/arm.h"
+ tmake_file="t-slibgcc-elf-ver t-linux arm/t-linux"
+@@ -725,6 +731,10 @@
+ tmake_file="cris/t-cris cris/t-elfmulti"
+ gas=yes
+ ;;
++cris-*-linux-uclibc*)
++ tm_file="dbxelf.h elfos.h svr4.h ${tm_file} linux.h cris/linux.h"
++ tmake_file="cris/t-cris t-slibgcc-elf-ver cris/t-linux-uclibc"
++ ;;
+ cris-*-linux*)
+ tm_file="dbxelf.h elfos.h svr4.h ${tm_file} linux.h cris/linux.h"
+ tmake_file="cris/t-cris t-slibgcc-elf-ver cris/t-linux"
+@@ -988,6 +998,11 @@
+ thread_file='single'
+ fi
+ ;;
++i[34567]86-*-linux*uclibc*) # Intel 80386's running GNU/Linux
++ # with ELF format using uClibc
++ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h linux.h i386/linux.h"
++ tmake_file="t-slibgcc-elf-ver t-linux-uclibc i386/t-crtstuff"
++ ;;
+ i[34567]86-*-linux*) # Intel 80386's running GNU/Linux
+ # with ELF format using glibc 2
+ # aka GNU/Linux C library 6
+@@ -1547,6 +1562,16 @@
+ gnu_ld=yes
+ gas=yes
+ ;;
++mips*-*-linux-uclibc*) # Linux MIPS, either endian. uClibc
++ tm_file="dbxelf.h elfos.h svr4.h linux.h ${tm_file} mips/linux.h"
++ case ${target} in
++ mipsisa32*-*)
++ target_cpu_default="MASK_SOFT_FLOAT"
++ tm_defines="MIPS_ISA_DEFAULT=32"
++ ;;
++ esac
++ tmake_file="t-slibgcc-elf-ver t-linux-uclibc"
++ ;;
+ mips*-*-linux*) # Linux MIPS, either endian.
+ tm_file="dbxelf.h elfos.h svr4.h linux.h ${tm_file} mips/linux.h"
+ case ${target} in
+@@ -1764,6 +1789,10 @@
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/linux.h rs6000/linuxspe.h"
+ tmake_file="rs6000/t-fprules rs6000/t-ppcos t-slibgcc-elf-ver t-linux rs6000/t-ppccomm"
+ ;;
++powerpc-*-linux-uclibc*)
++ tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/linux.h"
++ tmake_file="rs6000/t-fprules rs6000/t-ppcos t-slibgcc-elf-ver t-linux-uclibc rs6000/t-ppccomm"
++ ;;
+ powerpc-*-linux*)
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/linux.h"
+ tmake_file="rs6000/t-fprules rs6000/t-ppcos t-slibgcc-elf-ver t-linux rs6000/t-ppccomm"
+@@ -1916,7 +1945,7 @@
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sh/elf.h sh/embed-elf.h sh/rtemself.h rtems.h"
+ ;;
+ sh-*-linux* | sh[2346lbe]*-*-linux*)
+- tmake_file="sh/t-sh sh/t-elf t-slibgcc-elf-ver t-linux"
++ tmake_file="sh/t-sh sh/t-elf t-slibgcc-elf-ver"
+ case ${target} in
+ sh*be-*-* | sh*eb-*-*) ;;
+ *)
+@@ -1924,9 +1953,17 @@
+ tmake_file="${tmake_file} sh/t-le"
+ ;;
+ esac
+- tmake_file="${tmake_file} sh/t-linux"
++ case ${target} in
++ *-*-linux-uclibc*) tmake_file="${tmake_file} t-linux-uclibc sh/t-linux-uclibc" ;;
++ *) tmake_file="${tmake_file} t-linux sh/t-linux" ;;
++ esac
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sh/elf.h sh/linux.h"
+ case ${target} in
++ sh64*-*-linux-uclibc*)
++ tmake_file="${tmake_file} sh/t-sh64-uclibc"
++ tm_file="${tm_file} sh/sh64.h"
++ extra_headers="shmedia.h ushmedia.h sshmedia.h"
++ ;;
+ sh64*)
+ tmake_file="${tmake_file} sh/t-sh64"
+ tm_file="${tm_file} sh/sh64.h"
+diff -urN gcc-3.4.1-dist/libtool.m4 gcc-3.4.1/libtool.m4
+--- gcc-3.4.1-dist/libtool.m4 2004-05-18 04:08:37.000000000 -0500
++++ gcc-3.4.1/libtool.m4 2004-08-12 15:54:43.000000000 -0500
+@@ -689,6 +689,11 @@
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
++linux-uclibc*)
++ lt_cv_deplibs_check_method=pass_all
++ lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++ ;;
++
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ [lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$']
+diff -urN gcc-3.4.1-dist/ltconfig gcc-3.4.1/ltconfig
+--- gcc-3.4.1-dist/ltconfig 2004-03-05 15:05:41.000000000 -0600
++++ gcc-3.4.1/ltconfig 2004-08-12 15:55:48.000000000 -0500
+@@ -602,6 +602,7 @@
+
+ # Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+ case $host_os in
++linux-uclibc*) ;;
+ linux-gnu*) ;;
+ linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+ esac
+@@ -1262,6 +1263,24 @@
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
++linux-uclibc*)
++ version_type=linux
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
++ soname_spec='${libname}${release}.so$major'
++ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ # This implies no fast_install, which is unacceptable.
++ # Some rework will be needed to allow for fast_install
++ # before this can be enabled.
++ # Note: copied from linux-gnu, and may not be appropriate.
++ hardcode_into_libs=yes
++ # Assume using the uClibc dynamic linker.
++ dynamic_linker="uClibc ld.so"
++ ;;
++
+ netbsd*)
+ need_lib_prefix=no
+ need_version=no
diff --git a/toolchain/gcc/patches/3.4.6/200-uclibc-locale.patch b/toolchain/gcc/patches/3.4.6/200-uclibc-locale.patch
new file mode 100644
index 0000000000..3fc4900b06
--- /dev/null
+++ b/toolchain/gcc/patches/3.4.6/200-uclibc-locale.patch
@@ -0,0 +1,3246 @@
+diff -urN gcc-3.4.2-dist/libstdc++-v3/acinclude.m4 gcc-3.4.2/libstdc++-v3/acinclude.m4
+--- gcc-3.4.2-dist/libstdc++-v3/acinclude.m4 2004-07-15 12:42:45.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/acinclude.m4 2004-09-10 10:47:40.000000000 -0500
+@@ -996,7 +996,7 @@
+ AC_MSG_CHECKING([for C locale to use])
+ GLIBCXX_ENABLE(clocale,auto,[@<:@=MODEL@:>@],
+ [use MODEL for target locale package],
+- [permit generic|gnu|ieee_1003.1-2001|yes|no|auto])
++ [permit generic|gnu|ieee_1003.1-2001|uclibc|yes|no|auto])
+
+ # If they didn't use this option switch, or if they specified --enable
+ # with no specific model, we'll have to look for one. If they
+@@ -1012,6 +1012,9 @@
+ # Default to "generic".
+ if test $enable_clocale_flag = auto; then
+ case x${target_os} in
++ x*-uclibc*)
++ enable_clocale_flag=uclibc
++ ;;
+ xlinux* | xgnu* | xkfreebsd*-gnu | xknetbsd*-gnu)
+ AC_EGREP_CPP([_GLIBCXX_ok], [
+ #include <features.h>
+@@ -1138,6 +1141,41 @@
+ CTIME_CC=config/locale/generic/time_members.cc
+ CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+ ;;
++ uclibc)
++ AC_MSG_RESULT(uclibc)
++
++ # Declare intention to use gettext, and add support for specific
++ # languages.
++ # For some reason, ALL_LINGUAS has to be before AM-GNU-GETTEXT
++ ALL_LINGUAS="de fr"
++
++ # Don't call AM-GNU-GETTEXT here. Instead, assume glibc.
++ AC_CHECK_PROG(check_msgfmt, msgfmt, yes, no)
++ if test x"$check_msgfmt" = x"yes" && test x"$enable_nls" = x"yes"; then
++ USE_NLS=yes
++ fi
++ # Export the build objects.
++ for ling in $ALL_LINGUAS; do \
++ glibcxx_MOFILES="$glibcxx_MOFILES $ling.mo"; \
++ glibcxx_POFILES="$glibcxx_POFILES $ling.po"; \
++ done
++ AC_SUBST(glibcxx_MOFILES)
++ AC_SUBST(glibcxx_POFILES)
++
++ CLOCALE_H=config/locale/uclibc/c_locale.h
++ CLOCALE_CC=config/locale/uclibc/c_locale.cc
++ CCODECVT_H=config/locale/ieee_1003.1-2001/codecvt_specializations.h
++ CCODECVT_CC=config/locale/uclibc/codecvt_members.cc
++ CCOLLATE_CC=config/locale/uclibc/collate_members.cc
++ CCTYPE_CC=config/locale/uclibc/ctype_members.cc
++ CMESSAGES_H=config/locale/uclibc/messages_members.h
++ CMESSAGES_CC=config/locale/uclibc/messages_members.cc
++ CMONEY_CC=config/locale/uclibc/monetary_members.cc
++ CNUMERIC_CC=config/locale/uclibc/numeric_members.cc
++ CTIME_H=config/locale/uclibc/time_members.h
++ CTIME_CC=config/locale/uclibc/time_members.cc
++ CLOCALE_INTERNAL_H=config/locale/uclibc/c++locale_internal.h
++ ;;
+ esac
+
+ # This is where the testsuite looks for locale catalogs, using the
+diff -urN gcc-3.4.2-dist/libstdc++-v3/aclocal.m4 gcc-3.4.2/libstdc++-v3/aclocal.m4
+--- gcc-3.4.2-dist/libstdc++-v3/aclocal.m4 2004-08-13 15:44:03.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/aclocal.m4 2004-09-10 10:47:40.000000000 -0500
+@@ -1025,6 +1025,9 @@
+ # Default to "generic".
+ if test $enable_clocale_flag = auto; then
+ case x${target_os} in
++ x*-uclibc*)
++ enable_clocale_flag=uclibc
++ ;;
+ xlinux* | xgnu* | xkfreebsd*-gnu | xknetbsd*-gnu)
+ AC_EGREP_CPP([_GLIBCXX_ok], [
+ #include <features.h>
+@@ -1151,6 +1154,41 @@
+ CTIME_CC=config/locale/generic/time_members.cc
+ CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+ ;;
++ uclibc)
++ AC_MSG_RESULT(uclibc)
++
++ # Declare intention to use gettext, and add support for specific
++ # languages.
++ # For some reason, ALL_LINGUAS has to be before AM-GNU-GETTEXT
++ ALL_LINGUAS="de fr"
++
++ # Don't call AM-GNU-GETTEXT here. Instead, assume glibc.
++ AC_CHECK_PROG(check_msgfmt, msgfmt, yes, no)
++ if test x"$check_msgfmt" = x"yes" && test x"$enable_nls" = x"yes"; then
++ USE_NLS=yes
++ fi
++ # Export the build objects.
++ for ling in $ALL_LINGUAS; do \
++ glibcxx_MOFILES="$glibcxx_MOFILES $ling.mo"; \
++ glibcxx_POFILES="$glibcxx_POFILES $ling.po"; \
++ done
++ AC_SUBST(glibcxx_MOFILES)
++ AC_SUBST(glibcxx_POFILES)
++
++ CLOCALE_H=config/locale/uclibc/c_locale.h
++ CLOCALE_CC=config/locale/uclibc/c_locale.cc
++ CCODECVT_H=config/locale/ieee_1003.1-2001/codecvt_specializations.h
++ CCODECVT_CC=config/locale/uclibc/codecvt_members.cc
++ CCOLLATE_CC=config/locale/uclibc/collate_members.cc
++ CCTYPE_CC=config/locale/uclibc/ctype_members.cc
++ CMESSAGES_H=config/locale/uclibc/messages_members.h
++ CMESSAGES_CC=config/locale/uclibc/messages_members.cc
++ CMONEY_CC=config/locale/uclibc/monetary_members.cc
++ CNUMERIC_CC=config/locale/uclibc/numeric_members.cc
++ CTIME_H=config/locale/uclibc/time_members.h
++ CTIME_CC=config/locale/uclibc/time_members.cc
++ CLOCALE_INTERNAL_H=config/locale/uclibc/c++locale_internal.h
++ ;;
+ esac
+
+ # This is where the testsuite looks for locale catalogs, using the
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c++locale_internal.h gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c++locale_internal.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c++locale_internal.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c++locale_internal.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,59 @@
++// Prototypes for GLIBC thread locale __-prefixed functions -*- C++ -*-
++
++// Copyright (C) 2002, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++// Written by Jakub Jelinek <jakub@redhat.com>
++
++#include <clocale>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning clean this up
++#endif
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++
++extern "C" __typeof(iswctype_l) __iswctype_l;
++extern "C" __typeof(nl_langinfo_l) __nl_langinfo_l;
++extern "C" __typeof(strcoll_l) __strcoll_l;
++extern "C" __typeof(strftime_l) __strftime_l;
++extern "C" __typeof(strtod_l) __strtod_l;
++extern "C" __typeof(strtof_l) __strtof_l;
++extern "C" __typeof(strtold_l) __strtold_l;
++extern "C" __typeof(strxfrm_l) __strxfrm_l;
++extern "C" __typeof(towlower_l) __towlower_l;
++extern "C" __typeof(towupper_l) __towupper_l;
++extern "C" __typeof(wcscoll_l) __wcscoll_l;
++extern "C" __typeof(wcsftime_l) __wcsftime_l;
++extern "C" __typeof(wcsxfrm_l) __wcsxfrm_l;
++extern "C" __typeof(wctype_l) __wctype_l;
++extern "C" __typeof(newlocale) __newlocale;
++extern "C" __typeof(freelocale) __freelocale;
++extern "C" __typeof(duplocale) __duplocale;
++extern "C" __typeof(uselocale) __uselocale;
++
++#endif // GLIBC 2.3 and later
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.cc 1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.cc 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,160 @@
++// Wrapper for underlying C-language localization -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library. This library 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 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 this library; see the file COPYING. If not, write to the Free
++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++// USA.
++
++// As a special exception, you may use this file as part of a free software
++// library without restriction. Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License. This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//